1 #!/usr/bin/env python 2 import os,sys,time,re,prettytable,json 3 from collections import defaultdict,OrderedDict 4 conf='haproxy.cfg' ###指定haproxy配置文件### 5 jgf='' 6 ######################1.input输入字符类型转化函数####################### 7 def input_handle(s): 8 if str.isdigit(s): ###对输入是否是数字进行判断### 9 s = int(s) ###如果输出的是个数字,则转化为整数类型### 10 return s ###返回输入字符### 11 12 ###########################2.backend列表展示函数############################ 13 def backend_read(conf): 14 backend_list = [] ###初始化backend的列表### 15 show_dict = {} ###初始化要返回的显示字典### 16 backend_name_dict = defaultdict(list) ###定义一个value为列表的字典,用来存放server### 17 server_flag = False ###初始化server判断标志位### 18 with open(conf,'r') as ha: ###打开haproxy配置文件### 19 for line in ha: 20 server_dict = OrderedDict() ###定义一个有序字典### 21 line = line.strip('\n') 22 #情况1 23 if re.match('backend',line): ###匹配配置文件以backend开头的行### 24 backend_name = re.split('\s+',line)[1] 25 backend_list.append(backend_name) ###将配置到的backend的名称插入到列表### 26 server_flag = True ###赋值标志位为真,用来与server关联### 27 #情况2 28 elif server_flag and re.match('\s+server',line): ###匹配配置文件以server开头的行### 29 server_info = re.split('\s+',line) ###对server进行分隔### 30 server_dict['name'] = server_info[2] ###对server的具体信息进行字典赋值### 31 server_dict['address'] = server_info[3] 32 server_dict['weight'] = server_info[5] 33 server_dict['maxconn'] = server_info[7] 34 backend_name_dict[backend_name].append(server_dict) ###将server字典与backend的名称进行关联### 35 else: 36 server_flag = False ###当server没匹配到,赋值标志位为假,结束关联### 37 for k,v in enumerate(backend_list,1): 38 show_dict[k] = v ###对backend名称进行新字典赋值,方便查询和展示### 39 print('%d . %s' % (k,v)) ###输出backend列表### 40 return(show_dict,backend_name_dict) ###返回显示的字典和backend-server字典### 41 42 ########################3.显示server服务器函数############################# 43 def backend_server_show(backend_show_value,server_show_dict): 44 ############对backend名称进行遍历并加上数字编号########################### 45 print(jgf.center(70,'=')) 46 print('\033[1m后端服务器(%s)信息如下:\033[0m'%backend_show_value) 47 print('%-20s %-20s %-20s %-20s'%('name','address','weight','maxconn')) 48 server_list = server_show_dict[backend_show_value] 49 for v in server_list: ###用enumerate进行server展示### 50 n=list(v.values()) 51 print('\033[32;40m%-5s%20s%15s%25s\033[1m'%(n[0],n[1],n[2],n[3])) 52 print(jgf.center(60, '=')) 53 54 #####################4.名称输入判断函数############################# 55 def name_decide(): 56 (name,name_flag) = ('',True) ###初始化返回的名称和判断标志位### 57 while name_flag: 58 name_input = input('\033[32m请输入新服务名(退出输入q):\033[0m') 59 if len(name_input) == 0: ###如果输入为空则直接下一次循环### 60 continue 61 elif name_input == 'q': ###输入q,退出本次输入### 62 name_flag = False 63 sys.exit('\033[32;1m脚本已退出!\033[1m') 64 elif re.match('[0-9a-zA-Z\_]+',name_input): ###匹配输入是否以字符、数字或下划线开头### 65 name = name_input 66 name_flag = False ###输入成功后退出循环### 67 else: 68 print('\033[31m名称输入错误,请重新输入!!!\033[0m') 69 break 70 return(name) ###返回输入的结果### 71 #####################5.IP地址及端口输入判断函数############################# 72 def ipaddress_decide(): 73 (address,address_flag) = ('',True) ###初始化返回的IP地址和判断标志位### 74 while address_flag: 75 address_input = input('\033[32m请输入新地址(IP哦)(退出输入q):\033[0m') 76 if len(address_input) == 0: ###如果输入为空则直接下一次循环### 77 continue 78 elif address_input == 'q': ###输入q,退出本次输入### 79 address_flag = False 80 sys.exit('\033[32;1m脚本已退出!\033[1m') 81 ##################匹配输入是否是ip:port的格式###################### 82 elif re.match('(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}(\:\d{1,5})?$',address_input): 83 address = address_input 84 address_flag = False ###输入成功后退出循环### 85 else: 86 print('\033[31m地址输入错误,请重新输入!!!\033[0m') 87 return(address) ###返回输入的结果### 88 89 ####################6.数字输入判断函数###################################### 90 def number_decide(name): 91 (number,number_flag) = ('',True) ###初始化返回的数字和判断标志位### 92 while number_flag: 93 number_input =input('\033[32m请输入%s(数字哦)(退出输入q):\033[0m' % name) 94 if len(number_input) == 0: ###如果输入为空则直接下一次循环### 95 continue 96 elif number_input == 'q': ###输入q,退出本次输入### 97 number_flag = False 98 sys.exit('\033[32;1m脚本已退出!\033[32;1m') 99 else: 100 try: 101 int(number_input) ###匹配输入是否是数字### 102 except: 103 print('\033[31;1m%s输入类型错误,请重新输入!!!\033[0m'%name) 104 else: 105 number = number_input 106 number_flag = False ###输入成功后退出循环### 107 return(number) ###返回输入的结果### 108 109 #############################7.节点输入判断函数########################## 110 def backend_input_if(input_index,input_dict): 111 (input_name,input_flag) = ('',True) ###初始化返回的名称和判断标志位### 112 ###############如果输入非空,对输入进行判断并转化类型################# 113 if len(input_index) != 0: 114 input_index = input_handle(input_index) 115 if input_index == 'b': ###如果输入为b,则退出程序### 116 input_flag = False 117 elif input_index in input_dict.keys(): ###如果输入为数字编号,则从字典中获取具体backend名称### 118 input_name = input_dict[input_index] 119 elif input_index in input_dict.values(): ###如果输入为backend名称,则直接获取### 120 input_name = input_index 121 else: 122 input_name = '' ###输入其他字符,赋值变量为空### 123 return(input_name,input_flag) ###返回输入的结果和循环标志位### 124 125 ########################8.配置文件操作函数################# 126 def backend_server_handle(conf,handle_dict): 127 newfile = '%s.new'%conf ###定义回写的新文件### 128 server_flag = False 129 with open(conf,'r') as read_file,open(newfile,'w') as write_file: ###同时打开二文件,一个读,一个写### 130 for line in read_file: 131 if re.match('backend',line): ###匹配到backend行时进行server信息插入### 132 write_file.write(line) 133 backend_name = re.split('\s+',line)[1] 134 for server_dict in handle_dict[backend_name]: ###对backend-server字典进行遍历### 135 server_line = '\tserver {name} {address} weight {weight} maxconn {maxconn}\n' 136 write_file.write(server_line.format(**server_dict)) ###将指定的backend下的server条目插入文件### 137 138 server_flag = True ###指定标志位为真,方便server判断### 139 elif server_flag and re.match('\s+server',line): ###匹配server开头的行,跳过不做任何操作### 140 pass 141 else: 142 write_file.write(line) ###其他的行,直接插入新文件### 143 server_flag = False 144 print('\033[33;1m server更新成功\033[0m') 145 os.system('mv %s %s.bak'%(conf,conf)) ###对源配置文件进行备份### 146 os.system('mv %s %s'%(newfile,conf)) ###对新生成的配置文件进行改名### 147 148 ##################################主程序开始################################## 149 if __name__ == '__main__': 150 flag = True 151 backend_name = '' 152 haproxy_name_show_dict = {} ###初始化backend显示字典### 153 haproxy_server_show_dict = {} ###初始化server显示字典### 154 while flag: 155 print(jgf.center(60,'=')) 156 hy='\033[36m欢迎访问haproxy配置文件管理脚本\033[0m' 157 print(hy.center(60,'*')) 158 print('\033[1mbackend列表信息如下:') 159 (haproxy_name_show_dict,haproxy_server_show_dict) = backend_read(conf) 160 print(jgf.center(50,'=')) 161 time.sleep(1) 162 print(''' 163 \033[35;1m1.查询后端服务\033[0m 164 \033[35;1m 2.添加后端服务\033[0m 165 \033[35;1m 3.修改后端服务\033[0m 166 \033[31;1m 4.删除后端服务\033[0m 167 \033[32;1m 5.退出\033[0m ''') 168 print(jgf.center(60,'=')) 169 select_num = input('\033[35;1m请选择操作条目:\033[0m') 170 171 #######################1. 查询后端服务################################ 172 if select_num == '1': 173 query_flag = True ###初始化查询循环标志### 174 while query_flag: 175 backend_index =input('\033[31;1m请输入需要查询的backend编号或名称(返回上级菜单输入b,退出输入q):\033[0m') 176 177 ##############################对输入值进行判断################ 178 (backend_name,query_flag) = backend_input_if(backend_index,haproxy_name_show_dict) 179 if backend_name: ###显示对应backend下的server列表### 180 backend_server_show(backend_name,haproxy_server_show_dict) 181 elif backend_index=='b': 182 break 183 elif backend_index=='q': 184 sys.exit('\033[35;1m脚本退出!\033[0m') 185 else: 186 query_flag=False 187 print('\033[31;1m您输入的节点不存在!请重新输入!') 188 time.sleep(1) 189 190 #######################2. 添加后端服务################################ 191 if select_num == '2': 192 add_flag = True ###初始化添加循环标志### 193 while add_flag: 194 backend_index =input('\033[32;1m请输入添加的backend的编号或名称(返回上级菜单,请输入b):\033[0m') 195 ##############################对输入值进行判断################ 196 (backend_name,add_flag) = backend_input_if(backend_index,haproxy_name_show_dict) 197 if backend_name: ###显示对应backend下的server列表### 198 backend_server_show(backend_name,haproxy_server_show_dict) 199 add_server_dict = OrderedDict() ###设置实例默认为有序字典 200 print('\033[34;1m请依次输入后端服务信息(name,address,weight,maxconn):\033[0m') 201 add_server_dict['name'] = name_decide() ###对输入的name有效性进行判断### 202 add_server_dict['address'] = ipaddress_decide() ###对输入的IP有效性进行判断### 203 add_server_dict['weight'] = number_decide('权重值') ###对输入的权重有效性进行判断### 204 add_server_dict['maxconn'] = number_decide('最大连接数') ###对输入的连接数有效性进行判断### 205 206 print(add_server_dict['name'],add_server_dict['address'],add_server_dict['weight'],add_server_dict['maxconn']) 207 208 #############对输入的四个服务信息是否成功判断############# 209 if add_server_dict['name'] and add_server_dict['address'] and add_server_dict['weight'] and add_server_dict['maxconn']: 210 add_commit = input('\033[31;1m请确认是否添加此条目(y | n):\033[0m') 211 if add_commit == 'y': ###确认添加服务条目,并回写配置文件### 212 haproxy_server_show_dict[backend_name].append(add_server_dict) 213 backend_server_handle(conf,haproxy_server_show_dict) 214 else: 215 add_flag = False ###否则退出本次循环### 216 else: 217 print('\033[1;31m server信息输入有误,请重新输入!!!\033[0m') 218 time.sleep(2) 219 220 #######################3. 修改后端服务################################# 221 if select_num == '3': 222 backend_modify_flag = True ###初始化修改循环标志### 223 while backend_modify_flag: 224 backend_index =input('\033[32;1m请输入修改的backend的编号或名称(返回上级菜单,请输入b):\033[0m') 225 ##############################对输入值进行判断################ 226 (backend_name,backend_modify_flag) = backend_input_if(backend_index,haproxy_name_show_dict) 227 228 if backend_name: ###显示对应backend下的server列表### 229 backend_server_show(backend_name,haproxy_server_show_dict) 230 231 server_modify_flag = True ###初始化server条目修改标志位### 232 while server_modify_flag: 233 234 server_index =input('\033[32;1m请输入修改的server的编号(返回上级菜单,请输入b):\033[0m') 235 if len(server_index) != 0: 236 server_index = input_handle(server_index) 237 if server_index == 'b': ###输入b,返还上一层### 238 server_modify_flag = False 239 #####################指定具体的server编号进行判断##### 240 elif server_index >= 1 and server_index <= len(haproxy_server_show_dict[backend_name]): 241 modify_server_dict = OrderedDict() 242 print('\033[34;1m请依次输入后端服务信息(name,address,weight,maxconn):\033[0m') 243 modify_server_dict['name'] = name_decide() ###对输入的四个信息有效性进行判断### 244 modify_server_dict['address'] = ipaddress_decide() 245 modify_server_dict['weight'] = number_decide('权重值') 246 modify_server_dict['maxconn'] = number_decide('最大连接数') 247 248 print(modify_server_dict['name'],modify_server_dict['address'],modify_server_dict['weight'],modify_server_dict['maxconn']) 249 250 ######对输入的四个服务信息是否成功判断############# 251 if modify_server_dict['name'] and modify_server_dict['address'] and modify_server_dict['weight'] and modify_server_dict['maxconn']: 252 modify_commit =input('\033[32;1m请确认是否修改此条目(y|n):\033[1m') 253 if modify_commit == 'y': ###确认修改服务条目,并回写配置文件### 254 haproxy_server_show_dict[backend_name][server_index - 1] = modify_server_dict 255 backend_server_handle(conf,haproxy_server_show_dict) 256 modify_server_flag = False 257 258 else: ###否则退出本次循环### 259 modify_server_flag = False 260 else: 261 print('\033[31m server输入信息有误,请重新输入!!!\033[0m') 262 else: 263 print('\033[31m server编号输入错误,请重新输入!!!\033[0m') 264 265 #######################4. 删除后端服务################################ 266 if select_num == '4': 267 backend_delete_flag = True ###初始化删除循环标志### 268 while backend_delete_flag: 269 backend_index =input('\033[32;1m请输入删除的backend下条目编号或名称(返回上层菜单,请输入b):\033[0m') 270 ##############################对输入值进行判断################ 271 (backend_name,backend_delete_flag) = backend_input_if(backend_index,haproxy_name_show_dict) 272 273 if backend_name: ###显示对应backend下的server列表### 274 backend_server_show(backend_name,haproxy_server_show_dict) 275 276 server_delete_flag = True ###初始化server条目删除标志位### 277 while server_delete_flag: 278 279 server_index =input('\033[32;1m请输入要删除的server编号(返回上层菜单,请输入b):\033[0m') 280 if len(server_index) != 0: 281 server_index = input_handle(server_index) 282 if server_index == 'b': ###输入b,返还上一层### 283 server_delete_flag = False 284 #####################指定具体的server编号进行判断##### 285 elif server_index >= 1 and server_index <= len(haproxy_server_show_dict[backend_name]): 286 287 print(haproxy_server_show_dict[backend_name][server_index - 1]) 288 delete_commit =input('请确认是否删除此条目(y|n):') 289 if delete_commit == 'y': ###确认删除服务条目,并回写配置文件### 290 del haproxy_server_show_dict[backend_name][server_index - 1] 291 backend_server_handle(conf,haproxy_server_show_dict) 292 delete_server_flag = False 293 294 else: ###否则退出本次循环### 295 delete_server_flag = False 296 else: 297 print('\033[31m server编号输入错误,请重新输入!!!\033[0m') 298 299 #######################5. 退出程序###################### 300 if select_num == '5': 301 print('\033[31;1m程序将在两秒后退出,欢迎再次使用,谢谢!\033[0m') 302 time.sleep(1) 303 print('\033[32;1m1s\033[0m') 304 time.sleep(1) 305 print('\033[32;1m2s\033[0m') 306 print('\033[31;1m程序退出') 307 sys.exit()
相信梦想是价值的源泉,相信眼光决定未来的一切,相信成功的信念比成功本身更重要,相信人生有挫折没有失败,相信生命的质量来自决不妥协的信念!——I`m geek!