作业要求:
HAproxy配置文件操作:
1. 根据用户输入输出对应的backend下的server信息
2. 可添加backend 和sever信息
3. 可修改backend 和sever信息
4. 可删除backend 和sever信息
5. 操作配置文件前进行备份
6 添加server信息时,如果ip已经存在则修改;如果backend不存在则创建;若信息与已有信息重复则不操作
Readme:
1). need enviroment[重要的环境]
Win7 + Python3.6环境内完成
2). move[移植问题]
使用了Python的OS模块
3). feature[作业的特征]
用特定的格式,把字符串转成字典格式
用字符串.split("|")的方法把字符串转成列表
用了def定义一系列的函数,减少代码输入
用了def定义一个文件处理的函数,减少重复代码输入
4). important py file[重要的Python文件]
os.py
5). how to [怎么执行]
用eval将字符串转换成字典
while, if, def, os.rename,os.remove等等
6). 这里是程序 需要输入的格式,【】内的内容。
【{'backend':'www.oldboy1.org','record':{'server':'2.2.2.3','weight':'20','maxconn':30000}}】
****************************以下是HAProxy.conf的内容****************************
global
log 127.0.0.1 local2
daemon
maxconn 256
log 127.0.0.1 local2 info
defaults
log global
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
option dontlognull
listen stats :8888
stats enable
stats uri /admin
stats auth admin:1234
frontend oldboy.org
bind 0.0.0.0:80
option httplog
option httpclose
option forwardfor
log global
acl www hdr_reg(host) -i www.oldboy.org
use_backend www.oldboy.org if www
backend www.oldboy.org
server 100.1.7.9 100.1.7.9 weight 20 maxconn 3000
server 100.1.7.10 100.1.7.10 weight 20 maxconn 3000
backend buy.oldboy.org
server 100.1.7.90 100.1.7.90 weight 20 maxconn 3000
****************************The End****************************
1 #_*_coding:utf-8_*_ 2 import os 3 # 定义多个文件操作的类型, type = fetch,append,change 4 def file_handle(file_name,backend_data,record_list=None,type = 'fetch'): 5 new_file = file_name+'_new' 6 bak_file = file_name+'_bak' 7 if type == 'fetch': # 首先先做查找的功能 8 r_list = [] 9 with open(file_name, 'r') as f: 10 tag = False 11 for line in f: 12 if line.strip() == backend_data: # 这里需要strip() 13 tag = True 14 continue 15 if tag and line.startswith("backend"): 16 break 17 if tag and line: 18 r_list.append(line.strip()) 19 for line in r_list: 20 print(line) 21 return r_list 22 elif type == 'append': 23 with open(file_name,'r') as read_file,\ 24 open(new_file,'w') as write_file: # 打开老的haproxy文件,再创建一个新的haproxy文件 25 for r_line in read_file: # 原文件一行一行读,在新文件一行一行写 26 write_file.write(r_line) 27 28 for new_line in record_list: # 把record_list的内容逐行写入新haproxy文件里 29 # write_file.write(new_line) 这样写没有任何格式,不是需要的效果,所以代码需要改动 30 if new_line.startswith('backend'): # 如果new_line以“backend”开头,写到新haproxy时候,需要加回车 31 write_file.write(new_line + '\n') 32 else: 33 write_file.write('{0}{1}\n'.format(' '*8,new_line)) 34 os.rename(file_name, bak_file) # 用os模块的rename函数将原haproxy文件备份 35 os.rename(new_file, file_name) 36 os.remove(bak_file) 37 elif type == 'change': 38 with open(file_name, 'r') as read_file, \ 39 open(new_file, 'w') as write_file: # 打开老的haproxy文件,再创建一个新的haproxy文件 40 tag = False 41 has_writed = False 42 for r_line in read_file: 43 if r_line.split() == backend_data: 44 tag = True 45 continue # 这里continue是跳出本次循环,进入下一次循环,也就是下面的代码不跑了 46 if tag and r_line.startswith('backend'): 47 tag = False 48 if not tag: # 如果警报没有响起,就一直写 49 write_file.write(r_line) 50 else: # 警报响起,就要把record_list的内容写到新的haproxy里面 51 if not has_writed: # 这句的意思就是if not False,就是if True 52 for new_line in record_list: 53 if new_line.startwith('backend'): 54 write_file.write(new_line+'\n') 55 else: 56 write_file.write('{0}{1}\n'.format(' '*8,new_line)) 57 has_writed = True 58 os.rename(file_name,bak_file ) # 用os模块的rename函数将原haproxy文件备份 59 os.rename(new_file, file_name) 60 os.remove(bak_file) 61 62 63 def fetch(data): 64 backend_data = "backend {0}".format(data) 65 return file_handle('haproxy.conf',backend_data,type='fetch') 66 67 68 def add(data): 69 backend = data['backend'] # 通过字典的key值获取对应的value值 70 record_list = fetch(backend) 71 current_record = 'server {0} {0} weight {1} maxconn {2}'.format( 72 data['record']['server'], 73 data['record']['weight'], 74 data['record']['maxconn'] 75 ) 76 backend_data = 'backend {0}'.format(backend) 77 if not record_list: # 如果record_list为空,那么record_list的值就是False,not False就是True 78 record_list.append(backend_data) 79 record_list.append(current_record) 80 file_handle('haproxy.conf',backend_data,record_list,type='append') 81 82 else: 83 record_list.insert(0,backend_data) 84 if current_record not in record_list: 85 record_list.append(current_record) 86 file_handle('haproxy.conf',backend_data,record_list,type='change') 87 88 89 def remove(data): 90 backend = data['backend'] 91 record_list = fetch(backend) 92 current_record = 'server {0} {0} weight {1} maxconn {2}'.format( 93 data['record']['server'], 94 data['record']['weight'], 95 data['record']['maxconn'] 96 ) 97 backend_data = 'backend {0}'.format(backend) 98 if not record_list or current_record not in record_list: # 如果record_list范围为空或record_list不存在, 99 # 就告知没有记录 100 print('\033[33:1m无此条记录\033[0m') #不知道有没有效果 todo 101 return 102 103 else: # 处理record_list 104 record_list.insert(0,backend_data) 105 record_list.remove(current_record) # 删除用户输入的记录 106 file_handle('haproxy.conf',backend_data,record_list,type='change') 107 108 109 def change(data): 110 backend = data[0]['backend'] 111 record_list = fetch(backend) 112 113 old_record = 'server {0} {0} weight {1} maxconn {2}'.format( 114 data[0]['record']['server'], 115 data[0]['record']['weight'], 116 data[0]['record']['maxconn'] 117 ) 118 new_record = 'server {0} {0} weight {1} maxconn {2}'.format( 119 data[1]['record']['server'], 120 data[1]['record']['weight'], 121 data[1]['record']['maxconn'] 122 ) 123 backend_data = 'backend {0}'.format(backend) 124 125 if not record_list or old_record not in record_list: # 如果record_list为空 126 print('\033[33:1m无此条记录\033[0m') # 好像无效这段高亮显示 todo 127 return 128 else: 129 record_list.insert(0,backend_data) 130 index = record_list.index(old_record) 131 record_list[index] = new_record 132 file_handle('haproxy.conf',backend_data,record_list,type='change') 133 134 135 136 if __name__ == '__main__': # 让你写的脚本模块既可以导入到别的模块中用,另外该模块自己也可执行 137 # Make a script both importable and executable 138 msg = ''' 139 1:查询 140 2:添加 141 3:删除 142 4:修改 143 5:退出 144 ''' 145 menu_dic = { 146 '1':fetch, # 这里不加小括号,在调用menu——dic['1'](),就等同于调用fetch() 147 '2':add, 148 '3':remove, 149 '4':change, 150 '5':exit 151 } 152 while True: 153 print(msg) 154 choice=input('操作>>:').strip() 155 if len(choice) == 0 or choice not in menu_dic: 156 continue # continue是碰到后,调到loop的开始点 157 if choice == '5': 158 break 159 160 data = input('数据>>:').strip() 161 162 if choice != '1': 163 data = eval(data) # 通过eval就把用户输入的字典格式的字符串,转换成一个字典格式 164 menu_dic[choice](data) 165 166 ''' 167 {'backend':'www.oldboy1.org','record':{'server':'2.2.2.3','weight':'20','maxconn':30000}} 168 '''