背景:通过Python获取F5 vs,pool,snat,irule等信息输出到csv表格。


一. 结果展示

f5config.png

二. 脚本展示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320

# 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

1
C:\Users\whb>pip install f5-sdk

3.2 执行

1
2
3
4
5
6
7
# 语法:
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