1

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

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

由于在查询设备的 sysObjectId.0 oid 之前我不能说要加载哪个 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!!!
4

0 回答 0