request.POST重构
最近在写MHA部署的平台化操作页面,先简单说下MHA平台化的主要步骤,大概如下(以一主一从为例进行分析):
1.部署两台MySQL环境,搭建主从关系
2.开通主从两台环境和MHA manager节点之间的防火墙
3.创建主从节点和MHA manager节点的SSH信任关系
4.跑脚本生成线上环境规定的目录形式
5.启动MHA
6.检测MHA的运行状态
我遇到的问题,发生在第二步,主从两台环境和MHA manager之间开通防火墙的问题,之前处理的情景都是一对多的防火墙开通情况,也花时间写了相应的API,但是处理的情况仅限一对多的防火墙开通方式,而今天这个需求是要开通多对多的防火墙关系,为了提高效率,我不想重新写相关的API,还想调用之前的API,所以需要在之前的基础上做一些改进。
防火墙开通的界面如下,系统权限也就是防火墙权限,其中需要填写的信息是ansible用户名,需要开通的防火墙实例IP信息,实例端口信息,目标客户端的实例IP以及相应的说明信息和用户信息。其中,每个信息在request.POST中的key值如右侧的标签所示:
而高可用部署模块的前端页面如下,图中所示每个节点都需要对其他三个节点开通对应的防火墙关系。
可以看到,此时的需求是多对多开通防火墙,需要借助已有的防火墙开通方法,拆解为四个一对多的防火墙开通步骤。
整体的设计思路如下:
所以这个问题的重点就集中在了,怎么把前端发过来的request.POST请求进行拼接重构,然后再用拼接好的request.POST值作为api的参数,去调用防火墙开通的api,开通防火墙的api的参数格式和调用方法如下:
调用方法:
目前,前端传回来的request.POST请求的内容如下:
<QueryDict:
{u'slave_ip1': [u''],
u'slave_ip0': [u'10.XX.XXX.128'],
u'app_code': [u'app35'],
u'mha_manager0': [u'10.XX.XXX.251'],
u'mha_manager1': [u'10.XX.XXX.252'],
u'master_ip': [u'10.XX.XXX.68'],
u'slave_port0': [u'4306'],
u'slave_port1': [u''],
u'master_port': [u'4306'],
u'csrfmiddlewaretoken': [u'09XXXXXXXXXXXXXXX57aR5hjb']
}
>
细心的朋友可能已经注意到了,返回的值是一个QueryDict对象,所以这就要求我们进行重构的时候,也要将request.POST重构成一个QueryDict对象,这样才能实现替代和拼接,这里我们先给出QueryDict的实例化方法:
#在HttpRequest对象中,属性 GET 和 POST 得到的都是 django.http.QueryDict 所创建的实例。
#这是一个 django 自定义的类似字典的类,用来处理同一个键带多个值的情况。
>>> QueryDict('a=1&a=2&c=3')
<QueryDict: {'a': ['1', '2'], 'c': ['3']}>
具体的重构代码如下:
from django.http import QueryDict
#前端的request.POST解析
master_ip = request.POST.get('master_ip')
master_port=request.POST.get('master_port')
slave_ip0 = request.POST.get('slave_ip0')
slave_port0 = request.POST.get('slave_port0')
mha_manager0 = request.POST.get('mha_manager0')
mha_manager1 = request.POST.get('mha_manager1')
#第一次拼接---主节点对其他的节点
dest_ip_list = slave_ip0+','+mha_manager0+','+mha_manager1
tmpstr='ansible_user=dba_mysql&src_ip='+master_ip+
'&dest_ip_list='+dest_ip_list+
'&open_port_list='+master_port+
'&description=MHA_iptables&controler=yeyz&dest_user=MHA'
tmp = QueryDict(tmpstr)
#拼接好的request.POST内容
request.POST=tmp
url = LOCAL_SERVER_URL + '/api/iptables_add/'
result = api_access(url, 'POST', request.user.id, request.POST)
#第二次拼接---从节点对其他的节点
dest_ip_list1 = master_ip + ',' + mha_manager0 + ',' + mha_manager1
tmpstr1 = 'ansible_user=dba_mysql&src_ip=' + slave_ip0 +
'&dest_ip_list='+dest_ip_list1+
'&open_port_list='+slave_port0+
'&description=MHA_iptables&controler=yeyz&dest_user=MHA'
tmp1 = QueryDict(tmpstr1)
#拼接好的request.POST内容
request.POST=tmp1
url = LOCAL_SERVER_URL + '/api/iptables_add/'
result = api_access(url, 'POST', request.user.id, request.POST)
可以看到,在进行重构之前,必须导入QueryDict相应的包,也就是django.http包,我们首先把request.POST中的内容拿到,存到一个个变量里面,然后把这些变量拼接在字符串中,最后通过接口的方法去调用这些参数,实现request,POST请求重构,从而循环调用一对多的防火墙开通api,实现防火墙的多对多功能。