Re: [pysnmp-dev] Asyncio support in Python 3
Brought to you by:
elie
From: R. D. M. <rdm...@bi...> - 2014-11-04 22:01:16
|
On Tue, 04 Nov 2014 23:30:29 +0300, Ilya Etingof <il...@gl...> wrote: > Hi Matt, > > Iâve applied your patch to pysnmp and slightly reworked it afterwards. Please, try to use pysnmp development code and let me know in case of any issues: > > download latest CVS snapshot <http://pysnmp.cvs.sourceforge.net/viewvc/pysnmp/pysnmp/?view=tar> > > Please be aware that Iâve slightly changed the API you introduced in your patch to make it more uniform with the rest of pysnmp. See examples for details. > > Iâm also interested in real-world use cases of the asyncio transport to better adapt pysnmp API. On a somewhat different note... This is not a real world example, but it does show how the asyncio API (can) differ from that of pysnmp. This is an example I got working of a simple snmpv1 'get', based on the 'low level' get example. (Instead of printing errors, it should probably use set_exception.) I'm working on incorporating a more advanced version of this technique (that will handle multiple gets) into the application I'm writing. I also created a pynsmp asyncio transport patch, but frankly I couldn't figure out how to use the sort of intermediate-level API that is shown in the examples for the Twisted transport in my own application, so I gave up on that approach. Fortunately I only need v1. ---------------------------------------------------------------------- from pyasn1.codec.ber import encoder, decoder from pysnmp.proto import api import asyncio # Protocol version to use pMod = api.protoModules[api.protoVersion1] # Build PDU reqPDU = pMod.GetRequestPDU() pMod.apiPDU.setDefaults(reqPDU) pMod.apiPDU.setVarBinds( reqPDU, ( ('1.3.6.1.2.1.1.1.0', pMod.Null('')), ('1.3.6.1.2.1.1.3.0', pMod.Null('')) ) ) # Build message reqMsg = pMod.Message() pMod.apiMessage.setDefaults(reqMsg) pMod.apiMessage.setCommunity(reqMsg, 'public') pMod.apiMessage.setPDU(reqMsg, reqPDU) # Future for the result. reqFut = asyncio.Future() class SNMPProtocol(asyncio.DatagramProtocol): def datagram_received(self, data, transport_address): res = [] while data: rspMsg, data = decoder.decode(data, asn1Spec=pMod.Message()) rspPDU = pMod.apiMessage.getPDU(rspMsg) # Match response to request if pMod.apiPDU.getRequestID(reqPDU)==pMod.apiPDU.getRequestID(rspPDU): # Check for SNMP errors reported errorStatus = pMod.apiPDU.getErrorStatus(rspPDU) if errorStatus: print(errorStatus.prettyPrint()) else: for oid, val in pMod.apiPDU.getVarBinds(rspPDU): res.append((oid, val)) reqFut.set_result(res) @asyncio.coroutine def get(reqMsg): snmp.sendto(encoder.encode(reqMsg)) return reqFut @asyncio.coroutine def main(): for oid, val in (yield from asyncio.wait_for(get(reqMsg), timeout=3)): print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) loop = asyncio.get_event_loop() snmp, snmp_proto = loop.run_until_complete( loop.create_datagram_endpoint(SNMPProtocol, remote_addr=('demo.snmplabs.com', 161))) loop.run_until_complete(main()) |