pysnmp是用python语言开发的snmp开源项目,感觉没有net-snmp强大。但如果你只开发snmp 客户端的 trap,那么用pysnmp还是很简单的。

 

1、安装

下载pysnmp和pyasn1源码python setup.py安装,比较简单。

2、pysnmp扩展trap

直接帖代码了:

简单标准MIB

# Notification Originator Application (TRAP)
from pysnmp.carrier.asynsock.dispatch import AsynsockDispatcher
from pysnmp.carrier.asynsock.dgram import udp
from pyasn1.codec.ber import encoder
from pysnmp.proto import api

# Protocol version to use
verID = api.protoVersion1
pMod = api.protoModules[verID]

# Build PDU
trapPDU =  pMod.TrapPDU()
pMod.apiTrapPDU.setDefaults(trapPDU)

# Traps have quite different semantics among proto versions
if verID == api.protoVersion1:
    pMod.apiTrapPDU.setEnterprise(trapPDU, (1,3,6,1,6,3,1,1,5,1))
    pMod.apiTrapPDU.setGenericTrap(trapPDU, 'coldStart')

# Build message
trapMsg = pMod.Message()
pMod.apiMessage.setDefaults(trapMsg)
pMod.apiMessage.setCommunity(trapMsg, 'public')
pMod.apiMessage.setPDU(trapMsg, trapPDU)

transportDispatcher = AsynsockDispatcher()
transportDispatcher.registerTransport(
    udp.domainName, udp.UdpSocketTransport().openClientMode()
    )
transportDispatcher.sendMessage(
    encoder.encode(trapMsg), udp.domainName, ('10.8.80.108', 162)
    )
transportDispatcher.runDispatcher()
transportDispatcher.closeDispatcher()

带参数的标准MIB
 
 
使用的是setVarBinds函数,注意函数的第二个参数,是一个list,每个list元素是一个字典变量。下边是一个很好的例子,开发时照猫画虎就OK了。
# Notification Originator Application (TRAP)
from pysnmp.carrier.asynsock.dispatch import AsynsockDispatcher
from pysnmp.carrier.asynsock.dgram import udp
from pyasn1.codec.ber import encoder
from pysnmp.proto import api

# Protocol version to use
verID = api.protoVersion1
pMod = api.protoModules[verID]

# Build PDU
trapPDU =  pMod.TrapPDU()
pMod.apiTrapPDU.setDefaults(trapPDU)

# Traps have quite different semantics among proto versions
if verID == api.protoVersion1:
    pMod.apiTrapPDU.setEnterprise(trapPDU, (1,3,6,1,6,3,1,1,5,4))
    pMod.apiTrapPDU.setGenericTrap(trapPDU, 'linkUp')
    var = []
    oid = (1,3,6,1,6,3,1,1,5,3,1)
    val = pMod.Integer(1)
    var.append((oid,val))
    oid = (1,3,6,1,6,3,1,1,5,3,2)
    val = pMod.Integer(2)
    var.append((oid,val))
    oid = (1,3,6,1,6,3,1,1,5,3,3)
    val = pMod.Integer(3)
    var.append((oid,val))
    pMod.apiTrapPDU.setVarBinds(trapPDU, var)
# Build message
trapMsg = pMod.Message()
pMod.apiMessage.setDefaults(trapMsg)
pMod.apiMessage.setCommunity(trapMsg, 'public')
pMod.apiMessage.setPDU(trapMsg, trapPDU)

transportDispatcher = AsynsockDispatcher()

私有MIB

上面举的例子都是标准MIB中定义的。要扩展私有MIB会遇到什么问题呢?

问题在这句:pMod.apiTrapPDU.setGenericTrap(trapPDU, 'linkUp')

当setGenericTrap的第二个参数是一个标准MIB时,pysnmp是可以识别的,但是如果换成了私有MIB比如RamUsageThresExceed啥的,就会报错:

pyasn1.error.PyAsn1Error: Can't coerce RamUsageThresExceed into integer。

这需要修改pysnmp/proto下面的rfc1157.py,在里面定义class TrapPDU的地方

namedtype.NamedType('generic-trap', univ.Integer().clone(XXXXX)的那一行把你要定义的私有MIB加进来。

但是如果你发现pysnmp的版本不一样,找不到那一行,那你就把pysnmp和pyasn1目录建一个工程,在工程里面搜linkUp(注意大小写),看他们对linkUp做了什么,你就照猫画虎好了~~~

3、注意事项

 

几乎没有什么注意事项,勉强找一个的话那就是对标准的MIB属性,如ifIndex之类的,

在设置它的oid 的时候需要在后面加一个.0。比如:ifIndex的OID值是(1,3,6,1,2,1,2,2,1,1),但是在给他赋值的时候,要写成(1,3,6,1,2,1,2,2,1,1,0)