Skip to content

Python 获取 F5 LTM 配置文件

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

一. 结果展示

f5config.png

二. 脚本展示

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