最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

netmiko+textfsm自动统计交换机端口模块型号数量与闲置模块

来源:博客园

统计和查找交换机模块是件很费时费力的事情,特别是需要掌握库存数量时,成百上千块模块一块一块统计没有两天的时间是不行的,且统计出的数据需要一定的格式化才能便捷的录入数据库


(资料图片)

为此可以用netmiko模块自动执行命令,返回结果用textfsm来解析格式话,基于这两个模块以盛科交换机为对象做出了以下脚本

脚本运行环境

python 3.7 以上

netmiko 4.1.2

盛科交换机

第一步安装netmiko,4.1.2版本会自动安装textfsm,ntc_templates

ntc_templates路径 /usr/local/lib/python3.8/dist-packages/ntc_templates 后面会用到

脚本如下

#!/usr/bin/env python#-*-coding:utf-8-*-from collections import Counterfrom netmiko import ConnectHandlerimport getpass,json,sysdef Module(host,username,port=22,verbose=False):    passwd = getpass.getpass()    ModuleCount = []    ModuleStatus = {"free":[],"line":[]}    portstatus = {}    dev = {"device_type": "centec_os",        "host": host,        "username": username,        "password": passwd,        "port": 22}    with ConnectHandler(**dev) as conn:        PortTran = conn.send_command("show transceiver detail",use_textfsm=True)        ret = json.dumps(PortTran,indent=2)        PortStatus = conn.send_command("show interface status",use_textfsm=True)        for x in PortStatus:            portstatus[x["port"]]=x["status"]    if  verbose : print(ret)     for port in PortTran:        flag = True if portstatus[port["port"]] == "up" else False        info = " ".join([port["moduletype"],port["wavelength"],port["linklength"]])        ModuleCount.append(info)        db = port["db"]        if flag or(db and db!="-40.00"):            ModuleStatus["line"].append(port["port"]+" "+port["moduletype"])        else:            ModuleStatus["free"].append(port["port"]+" "+port["moduletype"])    ModuleCount = json.dumps(Counter(ModuleCount),indent=2)    ModuleStatus = json.dumps(ModuleStatus,indent=2)    return ModuleCount,ModuleStatusif __name__ == "__main__":    try:        host,username = sys.argv[1],sys.argv[2]        try:            verbose = sys.argv[3]            verbose = True if verbose =="verbose" else False        except:            verbose = False    except:        print("usage:")        print("       ")        print("options:")        print("    host: ")        print("    username: ")        print("    port: ")        print("    verbose: ")        print("examples:")        print("    ./centec 10.0.0.1 dark verbose")    try:        ModuleCount,ModuleStatus=Module(host,username,verbose=verbose)        print("------------------模块数量统计-----------------")        print(ModuleCount)        print("------------------模块状态统计-----------------")        print(ModuleStatus)    except Exception as e:        print(e)

其中两个自定义textfsm文件如下,需要放进ntc_templates目录

Value port (eth\S+)Value status (\S+)Start  ^${port}\s+${status} -> Record
interfaces.textfsm
Value port (\S+)Value moduletype (\S+\s?\S+)Value sn (\S+)Value wavelength (\S+\s?\S+)Value linklength (\S+\s?\S+)Value db (\S+)Start  ^Port ${port} transceiver info:  ^Transceiver Type: ${moduletype}  ^\s+Transceiver S/N         :\s${sn}  ^Transceiver Output Wavelength: ${wavelength}  ^      Link Length.*:\s+${linklength}  ^eth\S+\s+${db}  ^$$ -> Record
ModuleInfo.textfsm

脚本使用方法

# ./cent.py 10.0.0.1 admin verboseor# ./cent.py 10.0.0.1 admin

以上脚本打包后运行也需要运行机器上安装ntc_templates适配性不是很好,我们可以改动下,手动加载textfsm文件,如下

#!/usr/bin/env python#-*-coding:utf-8-*-from collections import Counterfrom netmiko import ConnectHandlerimport getpass,json,sys,textfsm,osdef Module(host,username,verbose=False,port=22):    BasePath = os.path.dirname(sys.argv[0])    InterFaceFsm=BasePath+"/interfaces.textfsm"    TranFsm=BasePath+"/ModuleInfo.textfsm"    passwd = getpass.getpass()    ModuleCount = []    ModuleStatus = {"free":[],"line":[]}    portstatus = {}    dev = {"device_type": "centec_os",        "host": host,        "username": username,        "password": passwd,        "port": 22}    with ConnectHandler(**dev) as conn:        PortTran = conn.send_command("show transceiver detail")                PortStatus = conn.send_command("show interface status")        with open(InterFaceFsm) as tem:            fsm = textfsm.TextFSM(template=tem)            PortStatus = fsm.ParseTextToDicts(PortStatus)        with open(TranFsm) as tem:            fsm = textfsm.TextFSM(template=tem)            PortTran = fsm.ParseTextToDicts(PortTran)    for x in PortStatus:        portstatus[x["port"]]=x["status"]    if verbose : print(json.dumps(PortTran,indent=2))    for port in PortTran:        flag = True if portstatus[port["port"]] == "up" else False        info = " ".join([port["moduletype"],port["wavelength"],port["linklength"]])        ModuleCount.append(info)        db = port["db"]        if flag or(db and db!="-40.00"):            ModuleStatus["line"].append(port["port"]+" "+port["moduletype"])        else:            ModuleStatus["free"].append(port["port"]+" "+port["moduletype"])    ModuleCount = json.dumps(Counter(ModuleCount),indent=2)    ModuleStatus = json.dumps(ModuleStatus,indent=2)    return ModuleCount,ModuleStatusif __name__ == "__main__":    try:        host,username = sys.argv[1],sys.argv[2]        try:            verbose = sys.argv[3]            verbose = True if verbose =="verbose" else False            print(verbose)        except:            verbose = False        try:            ModuleCount,ModuleStatus=Module(host,username,verbose=verbose)            print("------------------模块数量统计-----------------")            print(ModuleCount)            print("------------------模块状态统计-----------------")            print(ModuleStatus)        except Exception as e:            print(e)    except:        print("usage:")        print("      ")        print("options:")        print("    host: ")        print("    username: ")        print("    verbose: ")        print("examples:")        print("    ./centec 10.0.0.1 dark verbose")

执行效果,sn信息已遮挡

[  {    "port": "eth-0-1",    "moduletype": "1000BASE-LX",    "sn": "XXXXXX",    "wavelength": "1310 nm",    "linklength": "10 km",    "db": "-10.57"  },  {    "port": "eth-0-2",    "moduletype": "1000BASE-T_SFP",    "sn": "XXXXXX",    "wavelength": "N/A",    "linklength": "100 m",    "db": ""  },  {    "port": "eth-0-3",    "moduletype": "1000BASE-T_SFP",    "sn": "XXXXXX",    "wavelength": "N/A",    "linklength": "100 m",    "db": ""  },  {    "port": "eth-0-7",    "moduletype": "1000BASE-T_SFP",    "sn": "XXXXXX",    "wavelength": "N/A",    "linklength": "100 m",    "db": ""  },  {    "port": "eth-0-8",    "moduletype": "1000BASE-T_SFP",    "sn": "XXXXXX",    "wavelength": "N/A",    "linklength": "100 m",    "db": ""  },  {    "port": "eth-0-9",    "moduletype": "1000BASE-LX",    "sn": "XXXXXX",    "wavelength": "1310 nm",    "linklength": "10 km",    "db": "-40.00"  },  {    "port": "eth-0-10",    "moduletype": "1000BASE-T_SFP",    "sn": "XXXXXX",    "wavelength": "N/A",    "linklength": "100 m",    "db": ""  },  {    "port": "eth-0-18",    "moduletype": "1000BASE-T_SFP",    "sn": "XXXXXX",    "wavelength": "N/A",    "linklength": "100 m",    "db": ""  },  {    "port": "eth-0-31",    "moduletype": "1000BASE-LX",    "sn": "XXXXXX",    "wavelength": "1310 nm",    "linklength": "20 km",    "db": "-5.13"  },  {    "port": "eth-0-35",    "moduletype": "1000BASE-T_SFP",    "sn": "XXXXXX",    "wavelength": "N/A",    "linklength": "100 m",    "db": ""  },  {    "port": "eth-0-47",    "moduletype": "1000BASE-T_SFP",    "sn": "XXXXXX",    "wavelength": "N/A",    "linklength": "100 m",    "db": ""  }]------------------模块数量统计-----------------{  "1000BASE-LX 1310 nm 10 km": 2,  "1000BASE-T_SFP N/A 100 m": 8,  "1000BASE-LX 1310 nm 20 km": 1}------------------模块状态统计-----------------{  "free": [    "eth-0-9 1000BASE-LX",    "eth-0-18 1000BASE-T_SFP",    "eth-0-47 1000BASE-T_SFP"  ],  "line": [    "eth-0-1 1000BASE-LX",    "eth-0-2 1000BASE-T_SFP",    "eth-0-3 1000BASE-T_SFP",    "eth-0-7 1000BASE-T_SFP",    "eth-0-8 1000BASE-T_SFP",    "eth-0-10 1000BASE-T_SFP",    "eth-0-31 1000BASE-LX",    "eth-0-35 1000BASE-T_SFP"  ]}

关键词: 执行命令 不是很好 运行环境