pysnmp:值与SNMPWalk不同 - 为什么?

时间:2015-05-27 17:35:11

标签: python snmp pysnmp

简而言之,

我正在利用pysnmp获取多个值来创建包含路由表信息的.CSV。

当我在OID上执行SNMPWALK I时:.1.3.6.1.2.1.4.20.1.3我得到:

IP-MIB::ipAdEntNetMask.10.30.0.0 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.2 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.14 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.18 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.22 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.26 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.30 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.32 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.65 = IpAddress: 255.255.255.248
IP-MIB::ipAdEntNetMask.10.30.0.97 = IpAddress: 255.255.255.248
IP-MIB::ipAdEntNetMask.10.30.0.128 = IpAddress: 255.255.255.255
IP-MIB::ipAdEntNetMask.127.0.0.50 = IpAddress: 255.0.0.0

在我的pysnmp脚本中使用相同的方法时,我得到以下输出:

-> snmpNetMAsk = (snmpDictClean(snmpNetMAsk, 10))
(Pdb) pprint.pprint(snmpNetMAsk)
[[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.0)),
   IpAddress(hexValue='fffffffe'))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.2)),
   IpAddress(hexValue='fffffffe'))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.14)),
   IpAddress(hexValue='fffffffe'))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.18)),
   IpAddress(hexValue='fffffffe'))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.22)),
   IpAddress(hexValue='fffffffe'))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.26)),
   IpAddress(hexValue='fffffffe'))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.30)),
   IpAddress(hexValue='fffffffe'))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.32)),
   IpAddress(hexValue='fffffffe'))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.65)),
   IpAddress(hexValue='fffffff8'))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.97)),
   IpAddress(hexValue='fffffff8'))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.128)),
   IpAddress(hexValue='ffffffff'))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.127.0.0.50)),
   IpAddress(hexValue='ff000000'))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.0)), Integer(1))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.2)), Integer(1))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.14)), Integer(1))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.18)), Integer(1))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.22)), Integer(1))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.26)), Integer(1))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.30)), Integer(1))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.32)), Integer(1))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.65)), Integer(1))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.97)), Integer(1))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.128)), Integer(1))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.127.0.0.50)), Integer(1))],
 [(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.5.10.30.0.0)), Integer(18024))]]

您可以清楚地看到,我的所有值都是HEX,然后复制到某个Interger。我不完全明白这里发生了什么。在终端中运行snmpwalk并将其捕获到文件似乎更容易,然后使用python脚本编辑该文件。如果有一种方法可以使用pysnnmp维护字典中的值,我宁愿这样做。经过几天的自我搜索后,我才问这个问题。谢谢你的帮助!

编辑:显示我正在使用的完整版脚本。

#!/usr/bin/python

import pprint
import pysnmp
from snmp_helper import *


def snmpDictClean(input_list, input_num):
    output_dict = dict()
    for varBindTableRow in input_list:
        for name, val in varBindTableRow:
            name = str(name)
            val = str(val)
            splitKey = name.split('.')
            del splitKey[0:input_num]
            splitKey = '.'.join(splitKey)
            output_dict[splitKey] = val
    return output_dict


def main():

    ipCidrRouteIfIndex = '.1.3.6.1.2.1.4.24.4.1.5'
    ifDescr = '.1.3.6.1.2.1.2.2.1.2'
    ipAdEntIfIndex = '.1.3.6.1.2.1.4.20.1.2'
    ipAdEntNetMask = '.1.3.6.1.2.1.4.20.1.3'

    # SNMPv3 Connection Parameters
    a_user = 'USER'
    auth_key = 'AUTH_KEY'
    encrypt_key = 'ENCRYPT_KEY'

    snmp_user = (a_user, auth_key, encrypt_key)

    ipAddr = [
        'host1',
        'host2',
        ]

    for hlist in ipAddr:
        snmpDevice = (hlist, 161)

        snmpRoute = snmp_bulk_oid_v3(snmpDevice, snmp_user, oid=ipCidrRouteIfIndex)
        snmpRoute = (snmpDictClean(snmpRoute, 11))

        snmpIfDescr = snmp_bulk_oid_v3(snmpDevice, snmp_user, oid=ifDescr)
        snmpIfDescr = (snmpDictClean(snmpIfDescr, 10))

        snmpIpIndex = snmp_bulk_oid_v3(snmpDevice, snmp_user, oid=ipAdEntIfIndex)
        snmpIpIndex = (snmpDictClean(snmpIpIndex, 10))

        snmpNetMAsk = snmp_bulk_oid_v3(snmpDevice, snmp_user, oid=ipAdEntNetMask)
        snmpNetMAsk = (snmpDictClean(snmpNetMAsk, 10))

        import pdb; pdb.set_trace()

if __name__ == '__main__':

    main()

我正在使用@ktbyers中的snmp_helper:https://github.com/ktbyers/pynet/tree/master/snmp。我将其修改为使用snmpbulk而不是get。

# Python

from __future__ import print_function
from pysnmp.entity.rfc3413.oneliner import cmdgen
import pprint

def snmp_bulk_oid_v3(snmp_device, snmp_user, oid='', auth_proto='sha',
                    encrypt_proto='des', display_errors=True):
    # unpack snmp_user
    a_user, auth_key, encrypt_key = snmp_user

    auth_proto_map = {
        'sha':  cmdgen.usmHMACSHAAuthProtocol,
        'md5':  cmdgen.usmHMACMD5AuthProtocol,
        'none': cmdgen.usmNoAuthProtocol
    }

    if auth_proto in auth_proto_map.keys():
        auth_protocol = auth_proto_map[auth_proto]
    else:
        raise ValueError("Invalid authentication protocol specified: %s" % auth_proto)

    encrypt_proto_map = {
        'des':      cmdgen.usmDESPrivProtocol,
        '3des':     cmdgen.usm3DESEDEPrivProtocol,
        'aes128':   cmdgen.usmAesCfb128Protocol,
        'aes192':   cmdgen.usmAesCfb192Protocol,
        'aes256':   cmdgen.usmAesCfb256Protocol,
        'none':     cmdgen.usmNoPrivProtocol,
    }

    if encrypt_proto in encrypt_proto_map.keys():
        encrypt_protocol = encrypt_proto_map[encrypt_proto]
    else:
        raise ValueError("Invalid encryption protocol specified: %s" % encrypt_proto)

    # Create a PYSNMP cmdgen object
    cmdGen = cmdgen.CommandGenerator()

    (errorIndication, errorStatus, errorIndex, varBindTable) = cmdGen.bulkCmd(

        cmdgen.UsmUserData(a_user, auth_key, encrypt_key,
            authProtocol=auth_protocol,
            privProtocol=encrypt_protocol, ),
        cmdgen.UdpTransportTarget(snmp_device),
        0,
        25,
        oid,
        lookupNames=True, lookupValues=True 
    )

    if errorIndication:
        print(errorIndication)
    else:
        if errorStatus:
            print('%s at %s' % (
                errorStatus.prettyPrint(),
                errorIndex and varBindTable[-1][int(errorIndex)-1] or '?'
                )
            )

        '''
        else:
            for varBindTableRow in varBindTable:
                for name, val in varBindTableRow:
                    snmp_data = print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))
        '''

    return varBindTable

2 个答案:

答案 0 :(得分:0)

如果您希望输出看起来相同,则需要使用pprint以外的其他内容对其进行格式化。试试这个:

    for row in snmpNetMAsk:
        for name, val in row:
            print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))

参考:http://pysnmp.sourceforge.net/examples/current/v3arch/oneliner/manager/cmdgen/getnext-v2c.html

答案 1 :(得分:0)

您看到的是从SNMP Agent收到的vanilla OID值对。要使用pysnmp获得更漂亮的输出,您需要通过MIB解析器传递接收到的OID值对。使用this示例作为原型,但另外加载IP-MIB如下:

...
errorIndication, errorStatus, errorIndex, varBindTable = cmdGen.nextCmd(
    cmdgen.CommunityData('public'),
    cmdgen.UdpTransportTarget(('demo.snmplabs.com', 161)),
    MibVariable('1.3.6.1.2.1.4.20.1.3').loadMibs('IP-MIB'),
    lookupNames=True, lookupValues=True
)
...

确保使用.prettyPrint()打印出OID /值。

请记住,您需要将传统的ASN.1 IP-MIB转换为pysnmp格式,以便pysnmp使用它。您可以使用(实验性的)pysmi MIB compiler或使用pysnmp附带的build-pysnmp-mib脚本执行此操作,或者只需从PyPI安装预构建的MIB集合(pip pysnmp-mibs)。

如果您获得自己的IP-MIB.py,而不是使用pysnmp-mibs包,则可以将IP -MIB.py放入目录,并通过MibVariable.addMibSource()方法将pysnmp指向该自定义位置。有关详细信息,请参阅this example。所有MibVariable方法都可以这样链接:

MibVariable('1.3.6.1.2.1.4.20.1.3').addMibSource('/etc/pymibs').loadMibs('IP-MIB')

或者您可以通过指定要在初始化程序中加载的MIB名称来跳过.loadMibs():

MibVariable('IP-MIB', 'ipRoute').addMibSource('/etc/pymibs')

MibVariable类与ObjectIdentifier具有多态性,因此这两者可以互换使用。但是MibVariable可以从MIB文件中收集与初始化的OID相关的更多信息。例如,MibVariable可能包含与所讨论的OID相关联的MIB模块名称和MIB符号名称。它还可以保存与该OID关联的值的SNMP数据类型。

您可以将MibVariable视为SNMPv2-SMI的OBJECT-TYPE宏的实现。