Question

I would like to do a snmpget in python without blocking. I don't want to use threads, I really like gevent library but I haven't used it before so not sure where to start. I looked at their examples and understood how I can monkey patch sockets. If I monkey patch sockets and use a module like pysnmp would it be sufficient to perform non-blocking queries?

Also, since I'll be on a linux box I have access to snmpget command line utility, so I can invoke them using gevent.subprocess which is available in version 1.0 which can make these queries non-blocking too.

I'd prefer using a python module to do a snmp get than using command line utility, however if the second option is easier to get to work then I won't mind taking that approach.

Any hints/directions would be much appreciated. Thanks!

UPDATE:

I've taken the pysnmp_eventlet module and tried to adopt the Twisted example with eventlet. I'm not sure why my callback function is not getting invoked. I can see the SNMP request and response coming back in tcpdump. However my callback function (cbFun) is not getting invoked. Am I missing something?

from pysnmp_eventlet.carrier.eventlet.dispatch import EventletDispatcher
from pysnmp_eventlet.carrier.eventlet.dgram import udp

from pysnmp.entity.rfc3413 import cmdgen
from pysnmp.entity import engine, config


# Create SNMP engine instance

snmpEngine = engine.SnmpEngine()
dispatcher = EventletDispatcher()
snmpEngine.registerTransportDispatcher(dispatcher)



# SecurityName <-> CommunityName mapping
config.addV1System(snmpEngine, 'my-area', 'public')

# Specify security settings per SecurityName (SNMPv1 - 0, SNMPv2c - 1)
config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 1)


# UDP/IPv4
config.addSocketTransport(
    snmpEngine,
    udp.domainName,
    udp.UdpEventletTransport().openClientMode()
)
config.addTargetAddr(
    snmpEngine,
    'my-router',
    udp.domainName,
    ('127.0.0.1', 161),
    'my-creds',
    timeout=300,  # in 1/100 sec
    retryCount=1
)

def cbFun(cbCtx):
    (errorIndication, errorStatus, errorIndex, varBinds) = cbCtx

    if errorIndication:
        print(errorIndication)
    elif errorStatus:
        print('%s at %s' % (
                errorStatus.prettyPrint(),
                errorIndex and varBinds[int(errorIndex)-1][0] or '?'
            )
        )
    else:
        for oid, val in varBinds:
            print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))




cmdGen = cmdgen.GetCommandGenerator()
cmdGen.sendReq(
    snmpEngine,
    'my-router',
    ( ('1.3.6.1.2.1.1.1.0', None), ),
    cbFun
)
Was it helpful?

Solution

In the code above you still need to run the dispatcher for eventlet to process the incoming packets:

while True:
    eventlet.sleep(dispatcher.getTimerResolution())
    try:
        dispatcher.handleTimerTick(time.time())
    except Exception:
        print 'Error while handling dispatcher tick!'
        raise

You'd normally spawn this in a greenlet and forget about it (or likely implement some orderly shutdown for it).

(I'll be adding proper examples to the pysnmp_eventlet sometime in the future.)

OTHER TIPS

There's a patch to pysnmp that makes it running with eventlet:

https://bitbucket.org/flub/pysnmp_eventlet

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top