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"
  ]
}

Leave a Reply

Your email address will not be published. Required fields are marked *

X