Python - динамические MIB с помощью netsnmp / easysnmp

Итак, я пытаюсь создать службу опроса SNMP, чтобы получить данные инвентаризации от моих сетевых устройств. Я могу подключиться к устройствам с помощью модулей netsnmp или easysnmp.

Проблема возникает, когда я пытаюсь изменить MIB, которые нужно использовать для запроса некоторых более специфичных для предприятия вещей, таких как chStackUnitTable сетевого устройства Force10.

Поскольку я не могу сказать, какой mib загружать до запроса oid устройства sysObjectId.0, я сначала должен запросить устройство, а затем указать привязкам 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

Работает но плохо

Однако, если я добавлю переменную среды MIBDIRS до вызова привязок netsnmp, это сработает:

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 ответов

Другие вопросы по тегам