python操作文件练习,配置haproxy

时间:2022-08-02 18:27:08

  在使用python操作文件的时候,特别是对于网络设备,通常操作配置文件,会简化配置量,配置文件加载到内存中,运行时使用的是内存中的配置,内存中配置修改后立即生效,如果不将配置内容保存到硬盘中,则下次重新启动会导致配置丢失。下面模拟一下haproxy的backend的添加删除修改。

  示例的配置文件如下:

  

global
log 127.0.0.1 local2
daemon
maxconn
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 :
stats enable
stats uri /admin
stats auth admin: frontend cccc.org
bind 0.0.0.0:
option httplog
option httpclose
option forwardfor
log global
acl www hdr_reg(host) -i www. cccc.org
use_backend www. cccc.org if www backend www. cccc.org
server 100.1.7.9 100.1.7.9 weight maxconn
server 100.1.7.8 100.1.7.8 weight maxconn
server 100.1.7.7 100.1.7.7 weight maxconn
backend www.cccc.com
server server110 192.168.1.110 weight maxconn

  需求如下:

  1、当输入backend的名字时,要求能打印出属于该backend的所有server信息,格式化输出

  2、可以添加backend的server,输入相关属性字段后,完成添加

  3、可以删除backend的server信息。

  4、以上要求,要基于python 的文件操作来实现。

  

  想了好久之后,有以下几个点是需要注意的地方:

  1、配置文件是存放在硬盘中的,硬盘上的数据不能直接在中间插入修改,只能先将内容读取到内存中,在内存中进行修改

  2、主要修改的地方backend字段,backend字段在整个配置文件中的是有顺序的,修改了前后的内容,都需要在对应的位置上

  3、backend下可能存在多个server,每个server都有固定的属性配置,可能存在多个backend

  下面简单写了一个操作的方法。

  

#!/usr/bin/env python
#-*- coding:utf-8 -*- def get_configuration(configuration_name):
configuration = open(configuration_name,"r",encoding="utf-8")
configuration_dict = {}
configuration_full = []#定义一个列表,用来存放所有的配置信息
line_number = 0#定义一个计数器,用来记录关键位置的信息,比如backend开始时候的数字信息,在列表中的位置
configuration_position = []#定义一个列表,用来存放出现的backend的位置
for line in configuration:
# line = line.strip()#清除前后的空格
backend_server_configuration_all =[]
if line.strip().startswith("backend"):#如果开头是backend,证明后面是一个节点域名信息。记录第一个出现的行数信息
backend_position = line_number
line_list = line.strip().split(" ")
backend_name = line_list[1]
configuration_dict[backend_name] = []
configuration_position.append(line_number)#如果出现backend,记录出现的位置,到时候好用来恢复文件的位置。
elif line.strip().startswith("server"):
line_list = line.strip().split(" ")
server_name = line_list[1]
server_address = line_list[2]
server_weight = line_list[4]
server_maxconn = line_list[6]
backend_server_configuration = {"server_name":server_name,
"server_address":server_address,
"server_weight":server_weight,
"server_maxconn":server_maxconn}
configuration_dict[backend_name].append(backend_server_configuration)#列表增加一个配置项
else:
configuration_full.append(line)
line_number += 1
# print(line_number)
# print(configuration_position)
#将配置字典,完整的配置信息,和配置点的信息返回,完整配置信息中不包含配置字典信息
return configuration_dict,configuration_full,configuration_position #查询是否存在对应的backend,如果有,将server信息打印
def select_backend(configuration_dict):
backend_name = input("请输入要查询的backend名称:")
if backend_name in configuration_dict.keys():
backend_server_list = configuration_dict[backend_name]
print("backend :%s"%backend_name)
for backend_server_item in backend_server_list:
print_backend(backend_server_item)
else:
print("输入的backend不存在") #打印,格式化打印
def print_backend(backend_server_item):
print(
'''--------------------------
server_name:%s
server_address:%s
server_weight:%s
server_maxconn:%s'''%(backend_server_item["server_name"],backend_server_item["server_address"],backend_server_item["server_weight"],backend_server_item["server_maxconn"])) def configuration_input():#获取需要操作的对象信息
backend_name = input("backend name:")
server_name = input("server name:")
server_address = input("server address:")
server_weight = input("server weight:")
server_maxconn = input("server weight:")
return backend_name,server_name,server_address,server_weight,server_maxconn #增加节点
def add_backend(configuration_dict):
#获取当前配置文件的完整配置信息
#将添加节点的关键信息,整理成字典,如果该节点所属的名字在配置中存在,则追加新的配置项,如果不存在,则直接添加
configuration_new = configuration_input()
backend_name = configuration_new[0]
server_name = configuration_new[1]
server_address = configuration_new[2]
server_weight = configuration_new[3]
server_maxconn = configuration_new[4]
backend_server_configuration = {"server_name": server_name,
"server_address": server_address,
"server_weight": server_weight,
"server_maxconn": server_maxconn}
if backend_name in configuration_dict.keys():
configuration_dict[backend_name].append(backend_server_configuration)
else:
configuration_dict[backend_name] = [backend_server_configuration]
print("添加成功!")
return configuration_dict
#删除后台节点,返回字典文件
def delete_backend(configuration_dict):
configuration_new = configuration_input()
backend_name = configuration_new[0]
server_name = configuration_new[1]
server_address = configuration_new[2]
server_weight = configuration_new[2]
server_maxconn = configuration_new[4]
if backend_name in configuration_dict:
backend_server_configuration = {"server_name": server_name,
"server_address": server_address,
"server_weight": server_weight,
"server_maxconn": server_maxconn}
# for backend_server in configuration_dict[backend_name]:
if backend_server_configuration in configuration_dict[backend_name]:
configuration_dict[backend_name].remove(backend_server_configuration)
if configuration_dict[backend_name] == []:#如果配置中该节点下没有了后台站点,就把该配置项删除。
configuration_dict.pop(backend_name)
print("删除成功!")
else:
print("删除的backend不存在,请检查输入")
return configuration_dict def show_backend(configuration_dict):
for backend_name in configuration_dict.keys():
backend_server_list = configuration_dict[backend_name]
print("********************************")
print("backend :%s"%backend_name)
for backend_server_item in backend_server_list:
print_backend(backend_server_item)
print("********************************") #定义写文件的函数,将配置脚本传递进去,然后写入到某个文件中,如果配置中有其他配置,需要将配置内容插入到原配置内容的位置
def new_configuration(configuration_dict,configuration_full,configuration_position):
# configuration_new = open(configuration_name,'w',encoding='utf-8')
# configuration_full = get_configuration(configuration_name)[1]
# configuration_position = get_configuration(configuration_name)[2][0]#只取出第一个位置点,然后以该位置为基础,往后排
configuration = configuration_dict
# print(configuration)
# for item in configuration:
backend_servers = []
backend_server = []
for key in configuration:#取出backend的名字,以该名字为键,值是后端服务器列表
backend_name = key
backend_string = "backend %s\n"%backend_name
backend_server.append(backend_string)
for server_item in configuration[key]:
server_string = '''\t\tserver %s %s weight %s maxconn %s\n'''%(server_item["server_name"],server_item["server_address"],server_item["server_weight"],server_item["server_maxconn"])#格式化写入文件的内容,前后是可以用tab,中间必须是空格,因为在拆分的时候使用的空格,split
backend_server.append(server_string)#将同一个backend的后端多台服务器,放在同一个列表中
# print(backend_server)
position_tmp = 0
#将拿到的配置列表,写入到之前拿到的配置信息列表中,定向插入到之前的位置
while position_tmp < len(backend_server):
new_position = configuration_position + position_tmp
configuration_full.insert(new_position,backend_server[position_tmp])
position_tmp += 1
# print(configuration_full)
return configuration_full #返回整体的配置信息 #定义写文件的方法,将配置文件整体写入到文件中
def write_configuration(configuration_name,configuration_full):
configuration_new = open(configuration_name, 'w', encoding='utf-8')
for line in configuration_full:
configuration_new.write(line)
configuration_new.close() # string_format = '''--------------------------
# server_name:%s
# server_address:%s
# server_weight:%s
# server_maxconn:%s'''%(1,2,3,4)
# # print(string_format)
#查询
# select_backend("haproxy_configuration",'www.oldboy.org')
# configuration_dict = add_backend("111","www.cmcc.com",'server108','192.168.200.108',30,5000)
# configuration_dict = add_backend("haproxy_configuration","www.cmcc.com",'server108','192.168.200.108',30,5000)
# configuration_dict = delete_backend("haproxy_configuration","www.cmcc.com",'server108','192.168.200.108','30','5000')
# show_backend(configuration_dict)p # select_backend(configuration_dict,'www.cmcc.com')
# configuration_dict = get_configuration("haproxy_configuration")
# configuration_full = new_configuration(configuration_dict,'haproxy_configuration')
# write_configuration('haproxy_configuration',configuration_full)
if __name__ == '__main__':
configuration_name = "haproxy_configuration"
configuration_tuple = get_configuration(configuration_name)
configuration_dict = configuration_tuple[0]
configuration_full = configuration_tuple[1]
configuration_position = configuration_tuple[2][0]
option_list = ['查询','显示所有','增加backend','删除','保存退出']
exit_flag = True
while exit_flag: for No,option in enumerate(option_list,1):
print("%d:%s"%(No,option))
user_select = input("请输入操作的编号:")
# user_select = int(user_select)
if user_select == "":
select_backend(configuration_dict)
elif user_select == "":
show_backend(configuration_dict)
elif user_select == "":
configuration_dict = add_backend(configuration_dict)
elif user_select == "":
configuration_dict = delete_backend(configuration_dict)
elif user_select == "":
configuration_full = new_configuration(configuration_dict,configuration_full,configuration_position)
write_configuration(configuration_name,configuration_full)
exit_flag = False
else:
print("输入错误,请重新输入。")

  用到的主要方法还是文件的操作、字符串的操作、字典和列表的嵌套、循环。所有的方法之间,调用的输入参数和输出参数,都设置固定的格式字典,基于字典进行相关操作。最后能够实现全部查询、指定查询、删除、添加、保存退出。最后体现在文件上。