netmiko+textfsm自动统计交换机端口模块型号数量与闲置模块
个人博客地址
统计和查找交换机模块是件很费时费力的事情,特别是需要掌握库存数量时,成百上千块模块一块一块统计没有两天的时间是不行的,且统计出的数据需要一定的格式化才能便捷的录入数据库
为此可以用netmiko模块自动执行命令,返回结果用textfsm来解析格式话,基于这两个模块以盛科交换机为对象做出了以下脚本
脚本运行环境
python 3.7 以上
netmiko 4.1.2
盛科交换机
安装netmiko,4.1.2版本会自动安装textfsm,ntc_templates
tree
.
├── centec.py
└── textfsm
├── centec_os_show_interface_status.textfsm
├── centec_os_show_transceiver_detail.textfsm
└── index
centec.py
#!/usr/bin/env python #-*-coding:utf-8-*- from collections import Counter from netmiko import ConnectHandler import getpass,json,sys,os def 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,ModuleStatus if __name__ == '__main__': BaseDir = os.path.dirname(os.path.realpath(sys.argv[0])) os.environ['NET_TEXTFSM'] = BaseDir+'/textfsm' 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(' <host> <username> <port> <verbose>') print('options:') print(' host: <device_ip>') print(' username: <ssh user>') print(' port: <default 22>') print(' verbose: <default False>') 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
#index Template, Hostname, Platform, Command centec_os_show_interface_status.textfsm, .*, centec_os, sh[[ow]] interface status centec_os_show_transceiver_detail.textfsm, .*, centec_os, sh[[ow]] tran[[sceiver]] d[[etail]] #centec_os_show_interface_status.textfsm Value port (eth\S+) Value status (\S+) Start ^${port}\s+${status} -> Record #centec_os_show_transceiver_detail.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
脚本用法
# ./cent.py 10.0.0.1 admin verbose or # ./cent.py 10.0.0.1 admin
执行效果,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" ] }
以驱魔为理想,为生计而奔波