背景介绍

由于历史原因公司遗留了很多老旧设备,这些设备有很多的是 H3C 的 58 系列,这些老设备有的不支持 Netconf,所以在做 SDN 的时候只能判断多种情况来适配这些老旧设备。

华为新设备和 H3C 的 68 系列都用 Netconf 下发配置,如果是 H3C 的 58 系列或者其他老旧设备则用分为两种情况:设备配置用 SNMP设备配置用 SSH

# 匹配设备和型号对应的适配器
if agent_name == 'h3c':
    if model_name in ['S5800-60C-PWR', 'S5820X-26S', 'S5820-32F']:  # V5
        if model == 'read':
            device_params['ssh_password'] = device_snmp
            return SNMPDevice(**device_params)
        elif model == 'write':
            return SSHDevice(**device_params)
        else:
            raise ValueError('不支持该操作!')
    elif model_name in ['S6800-2C', 'S6800-4C', 'S10506X', 'S10506', 'S6800-54QF']:  # V7
        device_params['ssh_port'] = 830
        return NetconfDevice(**device_params)
    else:
        raise ValueError('不支持该设备!')
else:
    raise ValueError('不支持该厂商!')

出现问题

但是最近 58 系列设备的读功能(SNMP)出现了问题。

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

from easysnmp import snmp_walk


def main(oid):
    cursor = snmp_walk(
        oids=oid,
        hostname='xxx.xxx.xxx.xxx',
        community='xxx',
        version=2,
        use_sprint_value=True
    )
    print(cursor)


if __name__ == '__main__':
    snmp_oid = 'IF-MIB::ifDescr'
    main(snmp_oid)

zabbix python 自动发现 python snmp 自动发现设备_H3C

解决思路和解决方案

第一回合

报错的意思是找不到对应对象的 oid,但是本地 MIB库 是没问题的。

MacBook:~ zhangyi$ snmpwalk -v 2c -c xxx xxx.xxx.xxx.xxx IF-MIB::ifDescr
IF-MIB::ifDescr.1 = STRING: GigabitEthernet1/0/1
IF-MIB::ifDescr.2 = STRING: GigabitEthernet1/0/2
IF-MIB::ifDescr.3 = STRING: GigabitEthernet1/0/3
IF-MIB::ifDescr.4 = STRING: GigabitEthernet1/0/4
IF-MIB::ifDescr.5 = STRING: GigabitEthernet1/0/5
IF-MIB::ifDescr.6 = STRING: GigabitEthernet1/0/6
IF-MIB::ifDescr.7 = STRING: GigabitEthernet1/0/7
IF-MIB::ifDescr.8 = STRING: GigabitEthernet1/0/8
IF-MIB::ifDescr.9 = STRING: GigabitEthernet1/0/9
IF-MIB::ifDescr.10 = STRING: GigabitEthernet1/0/10
......

所以大概是因为 IF-MIB::ifDescr 这个字符串用不了了,当我把它换成具体的 oid 号时是不报错了,但是返回的 oid_index 也没有了值。

if __name__ == '__main__':
    snmp_oid = '1.3.6.1.2.1.2.2.1.2'
    main(snmp_oid)

zabbix python 自动发现 python snmp 自动发现设备_zabbix python 自动发现_02


所以这个问题不是 IF-MIB::ifDescr 导致的。

第二回合

接下来就是从 easysnmp 这个 Python 包中找问题了,easysnmp 底层是调用的是 net-snmp 这个系统级包,所以先查询下 net-snmp 在本机上的版本。

snmpget --version
NET-SNMP version: 5.6.2.1

当我打开官网看到 net-snmp 最新版本是 5.9.1 的时候就怀疑是不是旧版本导致的问题,所以决定先升级试试。

zabbix python 自动发现 python snmp 自动发现设备_Python_03

我本机系统是 Mac OS X,所以使用 brew 安装很方便。

brew install net-snmp

但是当我装好最新本版以后发现系统版本还是原来的 5.6.2.1

原因是我本机有多个版本,解决方法有两种:一种是删除旧版本,另一种是将新版本加到环境变量中。旧版本建议别删除万一系统中哪个应用用到呢,所以我们选择添加环境变量。

打开 ~/.bashrc 文件:

vi ~/.bashrc

添加到环境变量:

export PATH=/usr/local/Cellar/net-snmp/5.9.3/bin/:$PATH

重新打开终端这时就改成新版本了:

snmpget -V
NET-SNMP version: 5.9.3

但是结果很失望,还是不行!

第三回合

既然不是底层 net-snmp 的问题难道是 easysnmp 这个包的问题吗?

重新版本后发现确实比之前的版本高一点。

pip list | grep easysnmp
easysnmp  0.2.6

之前用的版本是 0.2.5,现在最新的是 0.2.6

但按道理说应该新版本会向下兼容的,为了打消疑虑决定将版本回退到 0.2.5

zabbix python 自动发现 python snmp 自动发现设备_SD-WAN_04


当我把版本降到 0.2.5 之后一切都正常了!

我:@#$^&%!$# ……*&%¥&@34%#!!!

总结

最后总结下经验教训吧,虽然最后查到的问题只是个版本的问题,但是为了解决这个问题前前后后浪费了大半天的时间也是郁闷。

这也说明在软件开发过程中,任何细节都不能放过,那些我们认为理所当然的事(版本应该向下兼容)也有可能出“黑天鹅”事件。所以在以后的开发中第三方包也应该在考虑范围之内,当时开发的包是什么版本就强制指定,即使在后续需要升级也要在版本改动后进行大量测试!