前言:
老板现在给你任务,公司有haproxy配置文件,希望通过python程序可以对ha配置文件进行增删改。
思路:
1、要求用户输入相应的数字,判断用户需要进行的操作,然后再让用户输入需要操作的backend数据。
2、当用户输入数字“1”时,提示用户输入需要查询的数据,并将查询的数据信息打印到屏幕。
3、当用户输入数字“2”时,提示用户输入需要新增的数据,并将用户输入的字符串转换成字典类型,然后调用add_data()方法执行新增操作。add_data()方法会先去调用fetch()方法,将原文件中匹配到的数据保存到fetch_list列表中,如果fetch_list列表有数据,则通过for循环将原文件haproxy.txt的内容一行一行读取出来,同时将读取到的内容一行一行的写入到新文件haproxy.new中,当匹配到需要新增的backend行时,先将原有的数据写入到新文件,再将用户输入新增的数据插入对应的位置;如果fetch_list列表没有数据,则一边读取原文件haproxy.txt的内容,一边将内容写入到新文件haproxy.new中,原文件内容循环完毕后再将用户输入的新增backend数据写入到新文件haproxy.new中,最后通过os.rename()修改两个文件的名称。
4、当用户输入数字“3”时,提示用户输入需要删除的数据,并将用户输入的字符串转换成字典类型,然后调用delete_data()方法执行删除操作。delete_data()方法会先去调用fetch()方法,将原文件中匹配到的数据保存到fetch_list列表中,如果fetch_list列表没有数据,则提示用户“没有找到需要删除的数据”,如果fetch_list列表仅有一条数据且与用户输入需要删除的数据匹配时,需要将匹配到的backend和backend数据行一并删除,否则只删除backend数据行,最后通过os.rename()修改两个文件的名称。
代码实现:
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3
4 import json, os
5
6 # 定义fetch()方法,逐行匹配用户输入的backend
7 def fetch(backend):
8 flag = False # 定义flag,用于判断后面是否有可取的backend
9 fetch_list = [] # 用于存放匹配到的backend的值
10 with open('haproxy.txt', 'r') as f: # 以读取的方式打开haproxy.txt文件
11 for line in f: # 逐行循环文件内容
12 if line.strip() == "backend %s" % backend: # 判断用户输入的backend是否与haproxy.txt文件中backend匹配
13 flag = True # 将flag设置为True,为获取backend后面的值
14 continue # 退出本次循环
15 if not line.strip().startswith("server"): # 当flag=True时,判断每行如果不以“server”开头,则重新将flag改为False
16 flag = False
17 if flag and line.strip():
18 fetch_list.append(line.strip()) # 将匹配到的backend值添加到fetch_list列表
19 return fetch_list # 返回fetch_list
20
21 # 定义add_data()方法,将用户输入的数据添加至haproxy.txt文件
22 def add_data(data_dict):
23 backend_title = data_dict["backend"] # 获取要添加的backend的值
24 backend_context = "backend %s" % backend_title # 需要添加的backend整个字段
25 record_title = data_dict["record"] # 获取record的值
26 # 获取需要添加的信息
27 record_context = "server %s %s weight %s maxconn %s" % (record_title["server"], record_title["server"], record_title["weight"], record_title["maxconn"])
28 # 调用fetch()方法,将haproxy.txt文件中匹配到的backend值保存到fetch_list列表中
29 fetch_list = fetch(backend_title)
30
31 if fetch_list: # 如果用户输入的backend存在haproxy.txt文件中
32 flag = False # 定义一个flag,用于找到需要添加的backend内容
33 with open('haproxy.txt', 'r') as read_file, open('haproxy.new', 'w') as write_file: # 定义一个只读和一个只写的文件对象
34 for line in read_file: # 循环原文件对象的每一行
35 if line.strip() == backend_context: # 判断用户输入的backend是否与原文件中的backend匹配
36 write_file.write(line) # 将匹配的backend写入到新文件中
37 flag = True # 修改flag值
38 continue # 退出此次循环
39 if not line.strip().startswith("server"):
40 flag = False
41 if flag and line.strip(): # 当flag标签为True时执行
42 if line.strip() == record_context: # 如果用户输入的bakend的值存在原文件中,就只讲原文件的数据到新文件中
43 print("您输入的backend值%s已经存在。" % record_context)
44 write_file.write(line)
45 else:
46 write_file.write(line) # 将匹配的backend原有的数据写入到新文件中
47 fetch_list.remove(line.strip()) # 在fetch_list列表中移除已写入新文件中的数据
48 if len(fetch_list) == 0: # 当fetch_list列表等长度为0时候,插入用户新增的数据
49 new_line = "%s%s" % (" "*8, record_context)
50 write_file.write(new_line + "\n") # 将用户新增的数据插入到新文件中
51 else:
52 write_file.write(line) # 当上述的条件都不满足的情况下,将原文件的数据写入到新文件中
53 else: # 如果用户输入的backend不存在haproxy.txt文件中
54 with open('haproxy.txt', 'r') as read_file, open('haproxy.new', 'w') as write_file: # 定义一个只读和一个只写的文件对象
55 for line in read_file: # 循环原文件对象的每一行
56 write_file.write(line) # 将原文件的每一行数据写入到新文件中
57 write_file.write("\n\n" + backend_context + "\n") # 在新文件的末尾追加用户输入的backend
58 new_line = "%s%s" % (" "*8, record_context)
59 write_file.write(new_line + "\n") # 在新文件的末尾追加用户输入的backend值
60
61 os.rename("haproxy.txt", "haproxy.bak") # 备份原文件
62 os.rename("haproxy.new", "haproxy.txt") # 将新文件重命名成haproxy.txt
63
64 # 定义delete_data()方法,删除haproxy.txt文件中匹配的数据
65 def delete_data(data_dict):
66 backend_title = data_dict["backend"] # 获取要删除的backend的值
67 backend_context = "backend %s" % backend_title # 需要删除的backend整个字段
68 record_title = data_dict["record"] # 获取需要删除的record值
69 # 获取需要删除的信息
70 record_context = "server %s %s weight %s maxconn %s" % (record_title["server"], record_title["server"], record_title["weight"], record_title["maxconn"])
71 # 调用fetch()方法,将haproxy.txt文件中匹配到的backend值保存到fetch_list列表中
72 fetch_list = fetch(backend_title)
73 if not fetch_list or record_context not in fetch_list: # 如果在文件中没有找到需要删除的数据,则提示用户没有可以删除的数据
74 print("Sorry, 没有找到需要删除的数据。")
75 return
76 else:
77 with open('haproxy.txt', 'r') as read_file, open('haproxy.new', 'w') as write_file:
78 flag = False # 定义一个flag,用于找到需要删除的backend行
79 if len(fetch_list) == 1 and record_context in fetch_list: # 如果原文件backend只有一行数据,且需要删除,则连带backend一起删除
80 for line in read_file:
81 if line.strip() == backend_context: # 找到需要删除的backend行
82 flag = True
83 continue
84 if not line.strip().startswith("server"):
85 flag = False
86 if flag and line.strip(): # 匹配到backend的数据时,只打印输出信息,不做写入动作
87 print('%s数据已被删除。' % (data_dict))
88 else:
89 write_file.write(line)
90 else: # 如果原文件backend数据有多条时,将需要删除的数据删除,其他输入正常写入新文件中
91 for line in read_file:
92 if line.strip() == backend_context: # 找到需要删除的backend行
93 write_file.write(line) # 将backend信息写入到新文件
94 flag = True
95 continue
96 if not line.strip().startswith("server"):
97 flag = False
98 if flag and line.strip():
99 if line.strip() == record_context: # 当匹配到需要删除的数据时,打印删除信息,不做写入动作
100 print('[%s]数据已被删除。' % record_context)
101 else:
102 write_file.write(line) # 其他backend数据则继续写入新文件中
103 else:
104 write_file.write(line)
105
106 os.rename("haproxy.txt", "haproxy.bak") # 备份原文件
107 os.rename("haproxy.new", "haproxy.txt") # 将新文件重命名成haproxy.txt
108
109 # 主函数
110 def main():
111 print("1、查询\n2、添加\n3、删除\n")
112 # 根据用户输入的数字进行选择对文件进行相关的操作
113 select_num = input("请输入上面对应的数字: ")
114 if select_num == "1":
115 print()
116 backend = input("请输入需要查询的backend: ")
117 fetch_list = fetch(backend)
118 for i in fetch_list:
119 print(i)
120 else:
121 print()
122 print("输入参考样例:", '{"backend":"ttt.oldboy.org","record":{"server":"100.1.7.9","weight":"20","maxconn":"3000"}}')
123 data_str = input("请按样例输入: ")
124 data_dict = json.loads(data_str) # 因为input()方法接收用户输入的类型为字符串,所以需要通过json函数将类似字典的字符串转换成字典类型
125 if select_num == "2":
126 add_data(data_dict)
127 elif select_num == "3":
128 delete_data(data_dict)
129 else:
130 print("输入错误")
131
132 if __name__ == "__main__":
133 main()
index.py
1 global
2 log 127.0.0.1 local2
3 daemon
4 maxconn 256
5 log 127.0.0.1 local2 info
6 defaults
7 log global
8 mode http
9 timeout connect 5000ms
10 timeout client 50000ms
11 timeout server 50000ms
12 option dontlognull
13
14 listen stats :8888
15 stats enable
16 stats uri /admin
17 stats auth admin:1234
18
19 frontend oldboy.org
20 bind 0.0.0.0:80
21 option httplog
22 option httpclose
23 option forwardfor
24 log global
25 acl www hdr_reg(host) -i www.oldboy.org
26 use_backend www.oldboy.org if www
27
28 backend www.oldboy.org
29 server 100.1.7.9 100.1.7.9 weight 20 maxconn 3000
30 server 100.1.7.19 100.1.7.19 weight 20 maxconn 3000
31
32 listen stats :9999
33 stats enable
34 stats uri /admin
35 stats auth admin:1234
36
37 backend buy.oldboy.org
38 server 100.1.7.90 100.1.7.90 weight 20 maxconn 3000
haproxy.txt
实现效果: