Python 获取 F5 LTM 配置文件
背景:通过Python获取F5 vs,pool,snat,irule等信息输出到csv表格。
一. 结果展示
二. 脚本展示
python
# coding:utf-8
import csv
from optparse import OptionParser
from f5.bigip import ManagementRoot
import os
import platform
parser = OptionParser()
parser.add_option("-a", "--address", dest="address", help=" IP address of F5 bigip")
parser.add_option("-u", "--username", dest="username", help="admin user name")
parser.add_option("-p", "--password", dest="password", help="admin password")
options, args = parser.parse_args()
ip = options.address
username = options.username
password = options.password
try:
if not ip:
print('ip地址未输入,请按照如下的格式输入')
raise Exception
if not username:
print('username用户名未输入,请按照如下的格式输入')
raise Exception
if not password:
print('password用户密码未输入,请按照如下的格式输入')
raise Exception
except Exception as e:
print("请再次输入正确命令: python 文件名 -a ip地址 -u 用户名(GUI) -p 密码(GUI)")
exit()
try:
mgmt = ManagementRoot(ip, username, password)
# print(" ip + username + pwd ---> ok!")
vs_list = mgmt.tm.ltm.virtuals.get_collection()
except Exception as e:
print('输入错误,请按照以下格式,正确输入')
print("请再次输入正确命令: python 文件名 -a ip地址 -u 用户名 -p 密码")
exit()
def writecsv3(csvfilepath):
#定义表头
headers = ['分区名称','vs名称','vs对外服务地址与端口','描述','允许源地址', 'IP协议', 'Pool名称', '服务器实际地址与端口','irule','snat类型','snatpool','snat地址']
#初始化行,表示按行输入数据到表格中
rows = []
#初始化列表,用于存储每个vs字典信息
dic_list = []
#遍历每个VS
for vs in vs_list:
# 初始化字典,把vs遍历参数存入字典
dic = {}
#判断partition,不同partition获取pool和snat信息要指定分区
if vs.partition == 'Common':
# 1. 获取vs分区信息
partition_name = vs.partition
dic['分区名称'] = partition_name
# 2. 获取vs名称信息
vs_name = vs.name
dic['vs名称'] = vs_name # 1. vs名称
# 3. 获取vs对外服务地址与端口
destination = vs.destination
ip_port = destination.split('/')[-1] #vs目的地址格式为:/Common/192.168.5.123:8080,我们取最后一部分,用split分割
dic['vs对外服务地址与端口'] = ip_port
# 4. 获取vs描述信息
description = getattr(vs, 'description', None)
dic['描述'] = description
# 5. 获取vs允许源地址信息
source = getattr(vs, 'source', None)
dic['允许源地址'] = source
# 6. 获取vs所使用IP协议
ip_protocol = vs.ipProtocol
dic['IP协议'] = ip_protocol
# 7. 获取vs所使用pool信息
pool= getattr(vs, 'pool', None)
# 判断vs是否存在pool,如果不存在,则vs对应的pool字段是为空
if pool is None:
dic['Pool名称'] = '/'
dic['服务器实际地址与端口'] = '/'
# 判断vs是否存在pool,如果存在,则进一步获取vs信息
else:
#获取pool名称
pool_name = pool.split('/')[-1]
dic['Pool名称'] = pool_name
#加载pool信息
pool_ = mgmt.tm.ltm.pools.pool.load(name=pool_name)
#初始化pool列表,用于存储pool成员
member_address_list = []
# 遍历每个pool成员,加工处理为IP+Port形式,存储到member_address_list列表。
for mem in pool_.members_s.get_collection():
if mem:
member_address = mem.address
member_all_name = mem.name
member_port = member_all_name.rsplit(':')[-1]
member_address_port = member_address + ":" + str(member_port)
member_address_list.append(member_address_port)
dic['服务器实际地址与端口'] = member_address_list
# 8. 获取vs所使用irule信息
rule = getattr(vs, 'rules', None)
#初始化irule列表
rule_list=[]
#判断是否使用irule,未使用则输出‘/’
if rule is None:
dic['irule'] = '/'
#判断是否使用irule,如果使用则把每个使用的irule存入rule_list列表
else :
for rule_ in rule :
rules_ = rule_.split('/')[-1]
rule_list.append(rules_)
dic['irule'] = rule_list
# 9. 获取vs所使用snat信息
snat = vs.sourceAddressTranslation
#提取snatpool信息
snat_pool = snat.get('pool')
#提取snat类型
snat_type = snat['type']
dic['snat类型'] = snat_type
#判断是否使用snatpool,未使用则输出‘/’
if snat_pool is None:
dic['snatpool'] = '/'
dic['snat地址'] = '/'
#判断使用snatpool的情况,进一步输出snatpool成员
else:
#切割处理snatpool名称
snatpool_name = snat_pool.split('/')[-1]
dic['snatpool'] = snatpool_name
#加载snatpool信息
snat_ = mgmt.tm.ltm.snatpools.snatpool.load(name=snatpool_name)
#初始化snatpool成员列表
snat_address_list = []
#获取成员信息并添加到成岩列表
snat_bl = getattr(snat_, 'members', None)
for snat_mem in snat_bl:
snat_mem_all = snat_mem.split("/")[-1]
snat_address_list.append(snat_mem_all)
dic['snat地址'] = snat_address_list
#其他分区信息提取,原理和common分区差不多,在提取pool成员信息和snat成员信息时,要指定分区名称
else:
partition_name = vs.partition
dic['分区名称'] = partition_name
vs_name = vs.name
dic['vs名称'] = vs_name
destination = vs.destination
ip_port = destination.split('/')[-1]
dic['vs对外服务地址与端口'] = ip_port
description = getattr(vs, 'description', None)
dic['描述'] = description
source = getattr(vs, 'source', None)
dic['允许源地址'] = source
ip_protocol = vs.ipProtocol
dic['IP协议'] = ip_protocol
pool = getattr(vs, 'pool', None)
if pool is None:
dic['Pool名称'] = '/'
dic['服务器实际地址与端口'] = '/'
else:
pool_name = pool.split('/')[-1]
dic['Pool名称'] = pool_name
subpath = getattr(vs, 'subPath', '')
member_address_list1 = []
if subpath:
pool_ = mgmt.tm.ltm.pools.pool.load(name=pool_name, partition=partition_name,subPath=subpath)
for mem in pool_.members_s.get_collection():
if mem:
member_address = mem.address
member_all_name = mem.name
member_port = member_all_name.rsplit(':')[-1]
member_address_port = member_address + ":" + str(member_port)
member_address_list1.append(member_address_port)
else:
pool_ = mgmt.tm.ltm.pools.pool.load(name=pool_name, partition=partition_name)
for mem in pool_.members_s.get_collection():
if mem:
member_address = mem.address
member_all_name = mem.name
member_name = member_all_name.rsplit(':')[0]
member_port = member_all_name.rsplit(':')[-1]
member_address_port = member_address + ":" + str(member_port)
member_address_list1.append(member_address_port)
dic['服务器实际地址与端口'] = member_address_list1
rule = getattr(vs, 'rules', None)
rule_list = []
if rule is None:
dic['irule'] = '/'
else:
for rule_ in rule:
# print(type(rule_))
rules_ = rule_.split('/')[-1]
rule_list.append(rules_)
dic['irule'] = rule_list
snat = vs.sourceAddressTranslation
snat_pool = snat.get('pool')
snat_type = snat['type']
dic['snat类型'] = snat_type
if snat_pool is None:
dic['snatpool'] = '/'
dic['snat地址'] = '/'
else:
snatpool_name = snat_pool.split('/')[-1]
dic['snatpool'] = snatpool_name
snat_address_list = []
snat_ = mgmt.tm.ltm.snatpools.snatpool.load(name=snatpool_name,
partition=partition_name)
snat_bl = getattr(snat_, 'members', None)
for snat_mem in snat_bl:
snat_mem_all = snat_mem.split("/")[-1]
snat_address_list.append(snat_mem_all)
dic['snat地址'] = snat_address_list
# 把每个vs字典添加到一个完整的列表
if dic:
dic_list.append(dic)
#服务器输出如下 ['172.17.6.80:80', '192.168.6.64:443'],我们把他们分开,表格每行输出一个pool成员。
for dic in dic_list:
server_ip = dic.get('服务器实际地址与端口')
if server_ip:
count = len(server_ip)
for i in range(count):
space_dic = {'分区名称': '','vs名称': '', 'vs对外服务地址与端口': '', '描述': '', '允许源地址': '', 'IP协议': '', 'Pool名称': '','服务器实际地址与端口': '', 'irule': '', 'snat类型': '', 'snatpool': '', 'snat地址': ''}
if i == 0:
dic['服务器实际地址与端口'] = server_ip[i] # 80
rows.append(dic)
else:
space_dic['服务器实际地址与端口'] = server_ip[i]
rows.append(space_dic)
else:
dic['服务器实际地址与端口'] = ''
rows.append(dic)
#打开表格,输入数据。
with open(csvfilepath, 'w+',newline='') as f:
f_csv = csv.DictWriter(f, fieldnames=headers)
f_csv.writeheader()
# f_csv1 = csv.DictWriter(f, headers)
f_csv.writerows(rows)
# 在linux下,再运行这条指令,因为linux默认zh_CN.utf-8编码,而windows是gbk编码,所以传输之后会乱码
sys_new = platform.system()
if sys_new == "Linux":
os.system('iconv -f UTF-8 -t GBK f5_write.csv -o f5_config.csv')
os.remove('f5_write.csv')
#执行主函数
if __name__ == '__main__':
try:
import platform
sys = platform.system()
if sys == "Windows":
file_name = r'f5_config.csv'
elif sys == "Linux":
file_name = r'f5_write.csv'
else:
file_name = r'f5_write.csv'
writecsv3(file_name)
except Exception as e:
print(e)
三. 执行方法
3.1 安装 F5-sdk
python
C:\Users\whb>pip install f5-sdk
3.2 执行
python
# 语法:
python 文件名 -a ip地址 -u 用户名(GUI) -p 密码(GUI)
#示例:
C:\Users\whb>python f5csv1.0.py -a 192.168.10.122 -u admin -p admin
#注:执行后输出表格,位置在C:\Users\whb\f5_config.csv