如何从pysnmp中的陷阱var-binds中正确获取表行索引和命名值

时间:2017-11-15 20:44:56

标签: python python-3.x pysnmp

我尽量保持我的代码尽可能干净,但我对目前所取得的成就并不完全满意。

我构建了一个SNMP管理器,它使用自定义MIB从另一个设备接收陷阱,我将其称为MY-MIB。

我不确定这是最干净的方式,但基本上我有:

from pysnmp.entity import engine, config
from pysnmp.carrier.asynsock.dgram import udp
from pysnmp.entity.rfc3413 import ntfrcv, context
from pysnmp.smi import builder, rfc1902
from pysnmp.smi.view import MibViewController
from pysnmp.entity.rfc3413 import mibvar

_snmp_engine = engine.SnmpEngine()
_snmpContext = context.SnmpContext(_snmpEngine)
_mibBuilder = _snmpContext.getMibInstrum().getMibBuilder()
#Add local path where MY-MIB is located
_mibSources = _mibBuilder.getMibSources() + (builder.DirMibSource('.'),)
_mibBuilder.setMibSources(*mibSources)
_mibBuilder.loadModules('MY-MIB')
_view_controller = MibViewController(_mibBuilder)    


def my_callback_trap_processor(snmp_engine, state_reference,
                                   context_id, context_name, var_binds, ctx):

    #...CALLBACK CODE...


config.addV1System(snmp_engine, 'my-area', 'MYCOMMUNITY')
config.addTargetParams(snmp_engine, 'my-creds', 'my-area',
                       'noAuthNoPriv', 1)

config.addSocketTransport(snmp_engine,
                          udp.domainName + (1,),
                          udp.UdpTransport().openServerMode((IP_ADDRESS,
                                                             PORT)))

ntfrcv.NotificationReceiver(snmp_engine, my_callback_trap_processor)

snmp_engine.transportDispatcher.jobStarted(1)

try:
    snmp_engine.transportDispatcher.runDispatcher()
except:
    snmp_engine.transportDispatcher.closeDispatcher()
    raise

在上面的回调函数中,只需使用以下代码即可获得非常易懂的打印:

    varBinds = [rfc1902.ObjectType(rfc1902.ObjectIdentity(x[0]), x[1]).resolveWithMib(_view_controller) for x in var_binds]
    for varBind in varBinds:
        print(varBind.prettyPrint())

,从我收到的特定陷阱中,它给了我:

SNMPv2-MIB::sysUpTime.0 = 0
SNMPv2-MIB::snmpTrapOID.0 = MY-MIB::myNotificationType
MY-MIB::myReplyKey.47746."ABC" = 0x00000000000000000000000000000000000
MY-MIB::myTime.0 = 20171115131544Z
MY-MIB::myOperationMode.0 = 'standalone'

尼斯。但我想从给定的变量中操纵/剖析每一点信息,特别是以更高层次的方式。

看着图书馆的内部,我能够收集这些代码:

for varBind in var_binds:   
    objct = rfc1902.ObjectIdentity(varBind[0]).resolveWithMib(self._view_controller)
    (symName, modName), indices = mibvar.oidToMibName(
                self._view_controller, objct.getOid()
                )
    print(symName, modName, indices, varBind[1])

给了我:

sysUpTime SNMPv2-MIB (Integer(0),) 0
snmpTrapOID SNMPv2-MIB (Integer(0),) 1.3.6.1.X.Y.Z.A.B.C.D
myReplyKey MY-MIB (myTimeStamp(47746), myName(b'X00080')) 0x00000000000000000000000000000000000
myTime MY-MIB (Integer(0),) 20171115131544Z
myOperationMode MY-MIB (Integer(0),) 1

在myReplyKey索引的情况下,我可以做一个:

    for idx in indices:
        try:
            print(idx.getValue())
        except AttributeError:
            print(int(idx))

但是在myOperationMode var-bind的情况下,如何获取命名值'standalone'而不是1?以及如何获取索引的名称(myTimeStampmyName)?

更新

在Ilya的建议之后,我为了获得namedValues而更多地研究了库,而且,我还使用了一些Python黑客来获取我在索引上寻找的东西。

varBinds = [rfc1902.ObjectType(rfc1902.ObjectIdentity(x[0]), x[1]).resolveWithMib(_view_controller) for x in var_binds]
processed_var_binds = []
for var_bind in resolved_var_binds:   

    object_identity, object_value = var_bind
    mod_name, var_name, indices = object_identity.getMibSymbol()

    var_bind_dict = {'mib': mod_name, 'name': var_name, 'indices': {}}

    for idx in indices:
        try:
            value = idx.getValue()
        except AttributeError:
            var_bind_dict['indices'] = int(idx.prettyPrint())
        else:
            var_bind_dict['indices'][type(value).__name__] = str(value)

    try:
        var_bind_dict['value'] = object_value.namedValues[object_value]
    except (AttributeError, KeyError):
        try:
            var_bind_dict['value'] = int(object_value.prettyPrint())
        except ValueError:
            var_bind_dict['value'] = object_value.prettyPrint()

    processed_var_binds.append(var_bind_dict)

1 个答案:

答案 0 :(得分:1)

要解决针对MIB的SNMP PDU var-bindings,您可以使用我认为您已经完成的this snippet

from pysnmp.smi.rfc1902 import *

var_binds = [ObjectType(ObjectIdentity(x[0]), x[1]).resolveWithMib(mibViewController)
            for x in var_binds]

到目前为止,您有一个rfc1902.ObjectType个对象的列表。 ObjectType实例模仿了一个双元素元组:ObjectIdentitySNMP value object

var_bind = var_binds[0]
object_identity, object_value = var_bind

现在,getMibSymbol()将为您提供MIB名称,MIB对象名称以及由OID的尾随部分组成的索引元组。索引元素为SNMP value objects,就像object_value

一样
>>> object_identity.getMibSymbol()
('SNMPv2-MIB', 'sysDescr', (0,))

枚举(如果存在)由.prettyPrint()报告:

>>> from pysnmp.proto.rfc1902 import *
>>> Error = Integer.withNamedValues(**{'disk-full': 1, 'no-disk': -1})
>>> error = Error(1)
>>> error.prettyPrint()
'disk-full'
>>> int(error)
1