Python - 使用netsnmp / easysnmp的动态mib

时间:2017-07-05 15:33:07

标签: python python-2.7 net-snmp mib easysnmp

所以,我正在尝试构建一个SNMP轮询服务,以便从我的网络设备中获取一些库存数据。我可以使用netsnmp或easysnmp模块连接到设备。

当我尝试更改哪些MIB用于查询某些更具企业特性的内容(例如Force10网络设备的“chStackUnitTable”)时,问题就出现了。

由于我无法在查询设备的sysObjectId.0之前说明要加载哪个mib,我必须首先查询设备,然后告诉net-snmp绑定(netsnmp和easysnmp都依赖它)查看通过设置os.environ['MIBDIRS']变量来确定特定目录。

问题似乎是在使用这些绑定的第一个方法调用之后,net-snmp绑定忽略了对MIBDIRS环境变量的更改。

实施例

不工作但我想要的订单

使用Force10 S3048-ON开关的示例:

import os
import netsnmp

mib_dir_root = "/opt/project/var/lib/snmp/mibs"

session_options = {'DestHost': "10.0.0.254", 'Version': 2, 'Community': "public"}
s = netsnmp.Session(**session_options)

vl = netsnmp.VarList(netsnmp.Varbind('sysObjectID', 0))
_r = s.get(vl)
obj_id = vl[0].val

print('{:s}.{:s}: {:s}'.format(vl.tag, vl.iid, vl.val))
# output: "sysObjectID.0: .1.3.6.1.4.1.6027.1.3.23"

# We can now determine which MIB to use to get the interesting stuff (serial number, 
# service tag, etc) by inspecting the obj_id.  In this case we know we want to query 
# the chStackUnitTable of the F10-S-SERIES-CHASSIS-MIB mib.

# Let's add the MIB directory to our MIBDIRS environment variable
mib_dir = os.path.join(mib_dir_root, 'Force10')
os.environ['MIBDIRS'] = "+{:s}".format(mib_dir))

# We also have the annoyance here of having another mib (F10-M-SERIES-CHASSIS-MIB) 
# that has the same OID name of 'chStackUnitTable' at a different numeric OID.  So we 
# need to specify the MIB explicitly

mib = 'F10-S-SERIES-CHASSIS-MIB'
oid = 'chStackUnitTable'
vl = netsnmp.VarList(netsnmp.Varbind('{:s}:{:s}'.format(mib, oid)))

s.walk(vl)
# output:
#  MIB search path: /home/username/.snmp/mibs;/usr/share/snmp/mibs
#  Cannot find module (F10-S-SERIES-CHASSIS-MIB): At line 1 in (none)
#  snmp_build: unknown failure

工作但不好

但是,如果我在调用netsnmp绑定之前添加MIBDIRS环境变量,它可以工作:

import os
import netsnmp

mib_dir_root = "/opt/project/var/lib/snmp/mibs"
mib_dirs = ['Force10', 'Cisco', 'Dell']
mib_dirs = [os.path.join(mib_dir_root, d) for d in mib_dirs if os.path.isdir(os.path.join(mib_dir_root, d))]
os.environ['MIBDIRS'] = "+{:s}".format(";".join(mib_dirs))
print(os.environ['MIBDIRS'])
# output:
#  +/opt/project/var/lib/snmp/mibs/Force10;/opt/project/var/lib/snmp/mibs/Cisco;/opt/project/var/lib/snmp/mibs/Dell;

session_options = {'DestHost': "10.0.0.254", 'Version': 2, 'Community': "public"}
s = netsnmp.Session(**session_options)

vl = netsnmp.VarList(netsnmp.Varbind('sysObjectID', 0))
_r = s.get(vl)
obj_id = vl[0].val

print('{:s}.{:s}: {:s}'.format(vl.tag, vl.iid, vl.val))
# output: "sysObjectID.0: .1.3.6.1.4.1.6027.1.3.23"

mib = 'F10-S-SERIES-CHASSIS-MIB'
oid = 'chStackUnitTable'
vl = netsnmp.VarList(netsnmp.Varbind('{:s}:{:s}'.format(mib, oid)))

_r = s.walk(vl)
cols = ['chStackUnitSerialNumber', 'chStackUnitModelID', 'chStackUnitCodeVersion', 'chStackUnitServiceTag']
for v in vl:
    if v.tag in cols:
        print('{:s}.{:s}: {:s}'.format(v.tag, v.iid, v.val))
# output:
#  chStackUnitModelID.1: S3048-ON-01-FE-52T
#  chStackUnitCodeVersion.1: 9.8(0.0P2)
#  chStackUnitSerialNumber.1: NA
#  chStackUnitServiceTag.1: <REDACTED>

我对此解决方案的问题是可扩展性。我计划支持许多不同的设备,并且每个制造商都需要一个MIB目录。这意味着MIBDIRS和MIB搜索路径将变得非常糟糕。更不用说net-snmp绑定可能会在某个阶段剥落,因为它必须搜索可能数千个MIB文件。

有没有办法在第一次snmp查询完成后清除绑定,设置MIBDIRS变量,然后重新导入netsnmp模块?我尝试使用reload(netsnmp),但这似乎不起作用。

所需的代码文本

理想情况下,这样的事情:

...
sess.get(object_id)
# determine which mib dir to point to
os.environ['MIBDIRS'] = "+" + "path_to_mib_dir"

# magic reloading of netsnmp

sess = netsnmp.Session(**session_options)
varlist = netsnmp.VarList(netsnmp.Varbind(mib + ":" + table_oid))
sess.walk(varlist)

...
# Profit!!!

0 个答案:

没有答案