作業(yè):HAproxy配置文件操作
一、作業(yè)要求
- 根據(jù)用戶輸入輸出對(duì)應(yīng)的backend下的server信息
- 可添加backend 和sever信息
- 可修改backend 和sever信息
- 可刪除backend 和sever信息
- 操作配置文件前進(jìn)行備份
- 添加server信息時(shí),如果ip已經(jīng)存在則修改;如果backend不存在則創(chuàng)建;若信息與已有信息重復(fù)則不操作
二、簡(jiǎn)單思路
- 用函數(shù)功能實(shí)現(xiàn)查詢、添加、修改、刪除和備份功能。
- 每次增刪改前都先進(jìn)行備份。
- 文件在已有內(nèi)容的修改方面有困難點(diǎn),需要查詢有什么方法實(shí)現(xiàn)。
三、流程圖

Day03 - HAproxy配置文件操作
四、參考站點(diǎn)
五、代碼
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time, json, os
def write_file(backend_title, exist_res): # 向文件寫入 backend 和 server 信息
with open('haproxy', 'r', encoding='utf-8') as f, open('haproxy_new', 'w', encoding='utf-8') as f2:
write_flag = False
for line in f:
if line.strip() == 'backend %s' % backend_title: # 如果該行的內(nèi)容為匹配,說(shuō)明從此往后的內(nèi)容為新內(nèi)容
write_flag = True
f2.write(line)
for i in exist_res:
f2.write(' '*8 + i + '\n')
continue
elif line.strip().startswith('backend') and write_flag: # 如果以backend開(kāi)頭且write_flag為真,說(shuō)明新加信息已寫完
write_flag = False
f2.write(line)
continue
elif write_flag and line.strip(): # 如果write_flag為真且該行有內(nèi)容,說(shuō)明是不需寫入的舊信息。
continue
else: # 正常寫入
f2.write(line)
def search(search_input): # 按 backend 查詢
search_res = []
with open('haproxy', 'r', encoding='utf-8') as f:
check_flag = False
for line in f:
if line.strip() == 'backend %s' % search_input: # 如果該行與'backend %s' % search_input相同
check_flag = True
continue
elif line.strip().startswith('backend') and check_flag: # 該行僅以'backend'開(kāi)頭,并且check_flag為真
check_flag = False
break
elif check_flag and line.strip(): # 如果check_flag為真且該行有內(nèi)容,說(shuō)明是需查詢到的server信息。
search_res.append(line.strip())
if not search_res:
print("文件中沒(méi)有 %s 的信息!" % search_input)
return search_res
else:
return search_res
def add(backend_title, backend_info):
exist_res = search(backend_title) # 先查詢輸入記錄是否已經(jīng)存在
if not exist_res: # 輸入的backend和server信息均不存在
backup()
with open('haproxy', 'r', encoding='utf-8') as f, open('haproxy_new', 'w', encoding='utf-8') as f2:
for line in f:
f2.write(line)
f2.write('\n\nbackend %s\n' % backend_title) # 開(kāi)始添加新的backend和server信息
f2.write(' '*8 + backend_info) # 字符也可以用乘法,刷新認(rèn)知了。
print("新的 backend 和 server 信息已添加進(jìn)入文件!")
os.rename('haproxy_new', 'haproxy') # 重命名文件
else: # 輸入的backend信息已存在
if backend_info in exist_res: # 輸入的server記錄也已存在,即重復(fù)了
print("您要添加的 backend 和 server 信息已經(jīng)存在!")
else: # 輸入的server記錄為新記錄
backup()
exist_res.append(backend_info)
write_file(backend_title, exist_res) # 調(diào)用write_file函數(shù)
print("新的 server 信息已添加進(jìn)入文件!")
os.rename('haproxy_new', 'haproxy') # 重命名文件
def delete(backend_title, backend_info):
exist_res = search(backend_title) # 先查詢輸入記錄是否已經(jīng)存在
if not exist_res: # 輸入的backend和server信息均不存在
return
else: # 輸入的backend信息已存在
if backend_info not in exist_res: # 輸入的server記錄不存在
print("%s 中沒(méi)有您要?jiǎng)h除的 server 信息!" % backend_title)
else: # 輸入的server記錄存在
backup()
exist_res.remove(backend_info)
with open('haproxy', 'r', encoding='utf-8') as f, open('haproxy_new', 'w', encoding='utf-8') as f2:
write_flag = False
for line in f:
if line.strip() == 'backend %s' % backend_title: # 如果該行與'backend %s' % backend_title相同
write_flag = True
if not exist_res: # 如果exist_res列表為False,則跳過(guò)不寫入
continue
else: # 如果exist_res列表不為空,則寫入已有內(nèi)容
f2.write(line)
for i in exist_res:
f2.write(' '*8 + i + '\n')
continue
elif line.strip().startswith('backend') and write_flag: # 該行僅以'backend'開(kāi)頭,并且write_flag為真
write_flag = False
f2.write(line)
continue
elif write_flag and line.strip(): # write_flag為真且不為空行
continue
else:
f2.write(line)
print("backend 和 server 信息已刪除!")
os.rename('haproxy_new', 'haproxy') # 重命名文件
def replace(backend_title, backend_info):
exist_res = search(backend_title)
if not exist_res: # 根據(jù)server信息列表真假值,來(lái)判斷要修改的backend是否存在于文件中。
return
elif backend_info in exist_res: # 要修改的backend和server信息,文件中均已存在。
print("文件中已經(jīng)含有該條 backend 和 server 信息!")
return
else:
backup()
for server_info in enumerate(exist_res):
print(server_info[0], server_info[1])
server_num = input("請(qǐng)選擇在 %s 中您要修改的記錄:" % backend_title)
while True: # 判斷選擇是否正確,不然總是報(bào)錯(cuò)
if server_num.isdigit():
server_num = int(server_num)
if server_num > len(exist_res):
print("請(qǐng)輸入正確的數(shù)字!")
else:
exist_res[server_num] = backend_info
break
else:
print("請(qǐng)輸入正確的格式!")
write_file(backend_title, exist_res)
print("已將 %s 中的信息修改為 %s" % (backend_title, exist_res[server_num]))
os.rename('haproxy_new', 'haproxy')
def backup(): # 文件操作前先備份已有文件
backup_time = time.strftime('%Y%m%d_%H%M%S')
with open('haproxy', 'r', encoding='utf-8') as f,\
open('haproxy_%s.bak' % backup_time, 'w', encoding='utf-8') as f2:
for line in f:
f2.write(line)
return "原配置已備份為 haproxy_%s.bak" % backup_time
while True:
print("1. 查詢 backend 信息\n2. 添加 backend 和 server 信息\n3. 修改 backend 和 server 信息\n"
"4. 刪除 backend 和 server 信息\nq. 退出")
choice_input = input("\n請(qǐng)輸入您想進(jìn)行的操作:").strip()
if choice_input.isdigit():
choice_input = int(choice_input)
if choice_input == 1:
user_input = input("請(qǐng)輸入您想查詢的 backend 信息:").strip()
for info in search(user_input):
print(info)
elif choice_input in [2, 3, 4]:
print('\n請(qǐng)以字典形式輸入 backend 和 server 信息。\n例如:{"backend": "test.oldboy.org","record":'
'{"server": "100.1.7.9","weight": 20,"maxconn": 30}}\n')
user_input = input("請(qǐng)輸入您想進(jìn)行操作的 backend 和 server 信息:").strip()
backend_dict = json.loads(user_input)
backend_title = backend_dict['backend']
backend_info = 'server %s %s weight %d maxconn %d' % (backend_dict['record']['server'],
backend_dict['record']['server'],
backend_dict['record']['weight'],
backend_dict['record']['maxconn'])
if choice_input == 2:
add(backend_title, backend_info)
elif choice_input == 3:
replace(backend_title, backend_info)
elif choice_input == 4:
delete(backend_title, backend_info)
else:
print("請(qǐng)輸入正確的數(shù)字!")
elif choice_input == 'q':
exit("Bye!")
else:
print("請(qǐng)輸入正確的格式!")