From 627d9ff4a3715477e56fe397f099ad0db0d5c1b9 Mon Sep 17 00:00:00 2001 From: elie Date: Sun, 27 Sep 2015 10:26:25 +0000 Subject: * Asyncore and asyncio-based APIs reworked to become functions. * Asyncio and Twisted API moved entirely into high-level domain to be aligned with other high-level APIs. This WILL BREAK backward compatibility for those apps that use Twisted API. --- CHANGES.txt | 18 +- README.txt | 167 ++++ docs/source/conf.py | 5 +- docs/source/docs/contents.rst | 371 +++++++- .../hlapi/asyncio/agent/ntforg/notification.rst | 8 + docs/source/docs/hlapi/asyncio/contents.rst | 60 ++ .../docs/hlapi/asyncio/manager/cmdgen/bulkcmd.rst | 8 + .../docs/hlapi/asyncio/manager/cmdgen/getcmd.rst | 8 + .../docs/hlapi/asyncio/manager/cmdgen/nextcmd.rst | 8 + .../docs/hlapi/asyncio/manager/cmdgen/setcmd.rst | 8 + docs/source/docs/hlapi/asyncore/contents.rst | 69 ++ .../manager/cmdgen/async-command-generator.rst | 3 +- .../hlapi/twisted/agent/ntforg/notification.rst | 8 + docs/source/docs/hlapi/twisted/contents.rst | 58 ++ .../docs/hlapi/twisted/manager/cmdgen/bulkcmd.rst | 8 + .../docs/hlapi/twisted/manager/cmdgen/getcmd.rst | 8 + .../docs/hlapi/twisted/manager/cmdgen/nextcmd.rst | 8 + .../docs/hlapi/twisted/manager/cmdgen/setcmd.rst | 8 + .../hlapi/asyncio/agent/ntforg/default-v1-trap.py | 54 ++ .../agent/ntforg/multiple-notifications-at-once.py | 55 ++ .../hlapi/asyncio/manager/cmdgen/getbulk-to-eom.py | 59 ++ .../cmdgen/multiple-concurrent-async-queries.py | 52 ++ .../cmdgen/multiple-sequential-async-queries.py | 55 ++ examples/hlapi/asyncio/manager/cmdgen/v1-get.py | 46 + .../agent/ntforg/async-multiple-informs-at-once.py | 6 +- .../agent/ntforg/async-multiple-traps-at-once.py | 6 +- .../async-running-multiple-snmp-engines-at-once.py | 6 +- .../agent/ntforg/custom-contextengineid.py | 6 +- .../asyncore/agent/ntforg/custom-contextname.py | 2 +- .../hlapi/asyncore/agent/ntforg/custom-v1-trap.py | 4 +- .../hlapi/asyncore/agent/ntforg/default-v1-trap.py | 4 +- .../send-notification-with-additional-varbinds.py | 2 +- .../agent/ntforg/v2c-trap-via-notification-type.py | 4 +- examples/hlapi/asyncore/agent/ntforg/v3-inform.py | 2 +- examples/hlapi/asyncore/agent/ntforg/v3-trap.py | 2 +- ...async-pull-mibs-from-multiple-agents-at-once.py | 21 +- .../cmdgen/async-query-multiple-snmp-engines.py | 8 +- .../manager/cmdgen/coerce-set-value-to-mib-spec.py | 2 +- .../manager/cmdgen/custom-asn1-mib-search-path.py | 2 +- .../custom-contextengineid-and-contextname.py | 2 +- .../manager/cmdgen/custom-contextengineid.py | 2 +- .../cmdgen/custom-pysnmp-mibs-search-path.py | 2 +- .../manager/cmdgen/custom-timeout-and-retries.py | 6 +- .../manager/cmdgen/custom-v3-security-name.py | 2 +- .../manager/cmdgen/fetch-variables-over-ipv6.py | 2 +- .../manager/cmdgen/get-table-object-by-index.py | 2 +- .../cmdgen/get-table-object-by-multiple-indices.py | 2 +- .../getbulk-fetch-scalar-and-table-variables.py | 2 +- .../cmdgen/getbulk-limit-number-of-packets.py | 2 +- .../cmdgen/getbulk-limit-number-of-variables.py | 2 +- .../cmdgen/getnext-limit-number-of-variables.py | 2 +- .../manager/cmdgen/getnext-multiple-oids-to-eom.py | 2 +- .../cmdgen/multiple-concurrent-async-queries.py | 9 +- .../asyncore/manager/cmdgen/multiple-get-calls.py | 2 +- .../asyncore/manager/cmdgen/preload-pysnmp-mibs.py | 2 +- .../asyncore/manager/cmdgen/pull-whole-mib.py | 6 +- .../manager/cmdgen/pull-whole-snmp-table.py | 2 +- .../cmdgen/query-agents-from-multuple-threads.py | 2 +- .../manager/cmdgen/set-multiple-scalar-values.py | 2 +- .../manager/cmdgen/specific-v3-engine-id.py | 2 +- .../hlapi/asyncore/manager/cmdgen/usm-md5-des.py | 2 +- .../hlapi/asyncore/manager/cmdgen/usm-md5-none.py | 2 +- .../hlapi/asyncore/manager/cmdgen/usm-none-none.py | 2 +- .../asyncore/manager/cmdgen/usm-sha-aes128.py | 2 +- examples/hlapi/asyncore/manager/cmdgen/v1-get.py | 2 +- examples/hlapi/asyncore/manager/cmdgen/v2c-get.py | 2 +- .../hlapi/asyncore/manager/cmdgen/v2c-getbulk.py | 2 +- .../asyncore/manager/cmdgen/waive-mib-lookup.py | 2 +- .../hlapi/trollius/agent/ntforg/default-v1-trap.py | 58 ++ .../trollius/manager/cmdgen/getbulk-to-eom.py | 60 ++ examples/hlapi/trollius/manager/cmdgen/v1-get.py | 47 + .../hlapi/twisted/agent/ntforg/default-v1-trap.py | 64 ++ .../agent/ntforg/multiple-notifications-at-once.py | 73 ++ .../manager/cmdgen/custom-timeout-and-retries.py | 49 + .../hlapi/twisted/manager/cmdgen/getbulk-to-eom.py | 52 ++ .../cmdgen/multiple-concurrent-async-queries.py | 56 ++ .../pull-mibs-from-multiple-agents-at-once.py | 61 ++ .../hlapi/twisted/manager/cmdgen/pull-whole-mib.py | 50 ++ examples/hlapi/twisted/manager/cmdgen/v1-get.py | 47 + pysnmp/carrier/twisted/dgram/udp.py | 6 +- pysnmp/entity/config.py | 1 + pysnmp/entity/rfc3413/asyncio/__init__.py | 1 - pysnmp/entity/rfc3413/asyncio/cmdgen.py | 91 -- pysnmp/entity/rfc3413/asyncio/ntforg.py | 68 -- pysnmp/entity/rfc3413/twisted/__init__.py | 1 - pysnmp/entity/rfc3413/twisted/cmdgen.py | 136 --- pysnmp/entity/rfc3413/twisted/ntforg.py | 75 -- pysnmp/hlapi/__init__.py | 3 + pysnmp/hlapi/asyncio/__init__.py | 8 + pysnmp/hlapi/asyncio/cmdgen.py | 479 ++++++++++ pysnmp/hlapi/asyncio/ntforg.py | 172 ++++ pysnmp/hlapi/asyncio/transport.py | 109 +++ pysnmp/hlapi/asyncore/__init__.py | 7 - pysnmp/hlapi/asyncore/_sync/__init__.py | 13 + pysnmp/hlapi/asyncore/_sync/cmdgen.py | 28 +- pysnmp/hlapi/asyncore/_sync/compat/cmdgen.py | 28 +- pysnmp/hlapi/asyncore/_sync/compat/ntforg.py | 8 +- pysnmp/hlapi/asyncore/_sync/ntforg.py | 8 +- pysnmp/hlapi/asyncore/cmdgen.py | 981 ++++++++++----------- pysnmp/hlapi/asyncore/ntforg.py | 288 +++--- pysnmp/hlapi/asyncore/transport.py | 52 +- pysnmp/hlapi/lcd.py | 9 + pysnmp/hlapi/transport.py | 37 + pysnmp/hlapi/twisted/__init__.py | 8 + pysnmp/hlapi/twisted/cmdgen.py | 502 +++++++++++ pysnmp/hlapi/twisted/ntforg.py | 147 +++ pysnmp/hlapi/twisted/transport.py | 51 ++ setup.py | 6 +- 108 files changed, 3963 insertions(+), 1279 deletions(-) create mode 100644 README.txt create mode 100644 docs/source/docs/hlapi/asyncio/agent/ntforg/notification.rst create mode 100644 docs/source/docs/hlapi/asyncio/contents.rst create mode 100644 docs/source/docs/hlapi/asyncio/manager/cmdgen/bulkcmd.rst create mode 100644 docs/source/docs/hlapi/asyncio/manager/cmdgen/getcmd.rst create mode 100644 docs/source/docs/hlapi/asyncio/manager/cmdgen/nextcmd.rst create mode 100644 docs/source/docs/hlapi/asyncio/manager/cmdgen/setcmd.rst create mode 100644 docs/source/docs/hlapi/asyncore/contents.rst create mode 100644 docs/source/docs/hlapi/twisted/agent/ntforg/notification.rst create mode 100644 docs/source/docs/hlapi/twisted/contents.rst create mode 100644 docs/source/docs/hlapi/twisted/manager/cmdgen/bulkcmd.rst create mode 100644 docs/source/docs/hlapi/twisted/manager/cmdgen/getcmd.rst create mode 100644 docs/source/docs/hlapi/twisted/manager/cmdgen/nextcmd.rst create mode 100644 docs/source/docs/hlapi/twisted/manager/cmdgen/setcmd.rst create mode 100644 examples/hlapi/asyncio/agent/ntforg/default-v1-trap.py create mode 100644 examples/hlapi/asyncio/agent/ntforg/multiple-notifications-at-once.py create mode 100644 examples/hlapi/asyncio/manager/cmdgen/getbulk-to-eom.py create mode 100644 examples/hlapi/asyncio/manager/cmdgen/multiple-concurrent-async-queries.py create mode 100644 examples/hlapi/asyncio/manager/cmdgen/multiple-sequential-async-queries.py create mode 100644 examples/hlapi/asyncio/manager/cmdgen/v1-get.py create mode 100644 examples/hlapi/trollius/agent/ntforg/default-v1-trap.py create mode 100644 examples/hlapi/trollius/manager/cmdgen/getbulk-to-eom.py create mode 100644 examples/hlapi/trollius/manager/cmdgen/v1-get.py create mode 100644 examples/hlapi/twisted/agent/ntforg/default-v1-trap.py create mode 100644 examples/hlapi/twisted/agent/ntforg/multiple-notifications-at-once.py create mode 100644 examples/hlapi/twisted/manager/cmdgen/custom-timeout-and-retries.py create mode 100644 examples/hlapi/twisted/manager/cmdgen/getbulk-to-eom.py create mode 100644 examples/hlapi/twisted/manager/cmdgen/multiple-concurrent-async-queries.py create mode 100644 examples/hlapi/twisted/manager/cmdgen/pull-mibs-from-multiple-agents-at-once.py create mode 100644 examples/hlapi/twisted/manager/cmdgen/pull-whole-mib.py create mode 100644 examples/hlapi/twisted/manager/cmdgen/v1-get.py delete mode 100644 pysnmp/entity/rfc3413/asyncio/__init__.py delete mode 100644 pysnmp/entity/rfc3413/asyncio/cmdgen.py delete mode 100644 pysnmp/entity/rfc3413/asyncio/ntforg.py delete mode 100644 pysnmp/entity/rfc3413/twisted/__init__.py delete mode 100644 pysnmp/entity/rfc3413/twisted/cmdgen.py delete mode 100644 pysnmp/entity/rfc3413/twisted/ntforg.py create mode 100644 pysnmp/hlapi/asyncio/__init__.py create mode 100644 pysnmp/hlapi/asyncio/cmdgen.py create mode 100644 pysnmp/hlapi/asyncio/ntforg.py create mode 100644 pysnmp/hlapi/asyncio/transport.py create mode 100644 pysnmp/hlapi/asyncore/_sync/__init__.py create mode 100644 pysnmp/hlapi/transport.py create mode 100644 pysnmp/hlapi/twisted/__init__.py create mode 100644 pysnmp/hlapi/twisted/cmdgen.py create mode 100644 pysnmp/hlapi/twisted/ntforg.py create mode 100644 pysnmp/hlapi/twisted/transport.py diff --git a/CHANGES.txt b/CHANGES.txt index 0c990ca..392c44e 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -29,7 +29,11 @@ Revision 4.3.0, work in progress at its original location. * Synchronous oneliner apps redesigned to offer Python generator-based API along with a more comprehensive set of accepted parameters. - * keep backward compatibility for all existing major/documented interfaces + * Asyncore-based asynchronous apps reworked to become functions. + * Twisted API moved entirely into high-level domain to be aligned with + other high-level APIs. This WILL BREAK backward compatibility for + those apps that use Twisted API. + * Keep backward compatibility for all existing major/documented interfaces - Sphinx documentation added to source code and example scripts. Library documentation converted from .html into RsT markup. @@ -62,23 +66,15 @@ Revision 4.3.0, work in progress apps objects to [a singular] snmpEngine "user context" object. That would allow for better cache reuse and allow for a single app working with many snmpEngine instances. -- Legacy interfaces and APIs dropped in new oneliner AsyncCommandGenerator - and AsyncNotificationOriginator classes (notice 'c' in Async). Original - AsynCommandGenerator and AsynNotificationOriginator implementations - rebuilt on top of these new optimized versions keeping all the legacy - for compatibility reasons. These classes no more keep references to - SnmpEngine what makes them reusable with many SnmpEngine class instances. - Oneliner GETBULK Command Generator now strips possible excessive OIDs off the bottom of returned var-binds table. - Constraints assignment shortcut added to some base rfc1902 types (Integer, Integer32, OctetString, Bits). That formally constitutes ASN.1 sub-typing. - Built-in debugging is now based on Python logging module. -- Example on a single Transport Dispatcher use with multiple SnmpEngine's - in oneliner AsyncCommandGenerator & AsyncNotificationOriginator based - applicatons added. +- Examples on a single Transport Dispatcher use with multiple SnmpEngine + instances applicatons added. - Example script on transport timeout & retries manipulation added. - Example script explaining incoming message's communityName re-mapping added. -- Some more examples on MIB lookup and use at oneliner CommandGenerator added. - Broadcast socket option can now be enabled with the .enableBroadcast() call for any datagram-based transport (namely, UDP and UDP6). - AbstractTransportDispatcher's jobStarted() and jobFinished() methods diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..323d177 --- /dev/null +++ b/README.txt @@ -0,0 +1,167 @@ + +PYTHON SNMP FRAMEWORK +--------------------- + +This is a pure-Python, open source and free implementation of v1/v2c/v3 +SNMP engine. + +The PySNMP project has been sponsored by a PSF grant [11]. Thanks! + +FEATURES +-------- + +* Complete SNMPv1/v2c and SNMPv3 support +* SMI framework for resolving MIB information and implementing SMI + Managed Objects +* Complete SNMP entity implementation +* USM Extended Security Options support (3DES, 192/256-bit AES encryption) +* Extensible network transports framework (UDP/IPv4, UDP/IPv6 and UNIX domain + sockets already implemented) +* Asynchronous socket-based IO API support +* Twisted, Asyncio and Trollius integration +* PySMI integration for dynamic MIB compilation +* Python eggs and py2exe friendly +* 100% Python, works with Python 2.4 though 3.4 +* MT-safe (only if run locally to a thread) + +Features, specific to SNMPv3 model include: + +* USM authentication (MD5/SHA) and privacy (DES/AES) protocols (RFC3414) +* View-based access control to use with any SNMP model (RFC3415) +* Built-in SNMP proxy PDU converter for building multi-lingual + SNMP entities (RFC2576) +* Remote SNMP engine configuration +* Optional SNMP engine discovery +* Shipped with standard SNMP applications (RC3413) + +MISFEATURES +----------- + +* Much slower than C implementations. Some optimization still possible. + +INSTALLATION +------------ + +The PySNMP package uses setuptools for package management. The PyASN1 [8] +package is required. For secure SNMPv3 communication, PyCrypto [9] +should also be installed. For MIB-related operations PySMI [10] package is +needed. + +OPERATION +--------- + +As of this writing, PySNMP implements two SNMP architectures -- the first +is a legacy one specified by SNMPv1 & v2c standards [5]. It is quite +low-level and protocol-oriented by design. In particular, it requires +application to manage authentication and access issues, deal with transport +failures and similar housekeeping stuff. + +The second model supported by PySNMP is aligned to SNMPv3 architecture, +as specified in [4]. Here is an example on querying SNMP agent +for arbitrary value (sysDescr) over SNMP v3 with authentication and +privacy enabled: + +8X---------------- cut here -------------------- + +from pysnmp.hlapi import * + +iterator = getCmd( + SnmpEngine(), + CommunityData('public'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)) +) +errorIndication, errorStatus, errorIndex, varBinds = next(iterator) + +if errorIndication: # SNMP engine errors + print errorIndication +else: + if errorStatus: # SNMP agent errors + print(%s at %s' % (errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1] or '?')) + else: + for varBind in varBinds: + print('='.join([x.prettyPrint() for x in varBind])) + +8X---------------- cut here -------------------- + +For more examples, please see the examples directory in the PySNMP distribution. + +MIB SUPPORT +----------- + +The pysnmp.smi package component defines and implements data model for SNMP SMI +objects. With that model, various objects defined in MIB file could be +implemented in Python, loaded into SNMP entity and used for verification and +visualisation purposes (SNMP manager side) and/or become management targets +(SNMP agent side). + +The PySMI package [10] could be used for automatic, one-time convertion of +ASN.1 MIB text files into Python code snippets designed to be dynamically +loaded and used by PySNMP engine. + +A large set of pre-compiled MIB files is shipped along the pysnmp-mibs +package.[2] + +AVAILABILITY +------------ + +The PySNMP software is freely available for download from PyPI and +project homepage [1] + +GETTING HELP +------------ + +If something does not work as expected, please, try browsing PySNMP +mailing list archives or post your question there. [7] + +FEEDBACK +-------- + +I'm interested in bug reports and fixes, suggestions and improvements. +I'd be happy knowning whenever you used the PySNMP software for whatever +purpose. Please, send me a note then. Thanks! + +REFERENCES +---------- + +[1] PySNMP project homepage: + http://pysnmp.sf.net + +[2] Pre-compiled PySNMP MIB modules: + http://sourceforge.net/project/showfiles.php?group_id=14735 + +[3] PySNMP applications: + http://sourceforge.net/project/showfiles.php?group_id=14735 + +[4] SNMP Version 3 specification and related + http://www.ibr.cs.tu-bs.de/projects/snmpv3/ + +[5] SNMP Version 1/2 specifications: + http://www.ietf.org/rfc/rfc1155.txt - http://www.ietf.org/rfc/rfc1158.txt + http://www.ietf.org/rfc/rfc1901.txt - http://www.ietf.org/rfc/rfc1909.txt + +[6] libsmi homepage + http://www.ibr.cs.tu-bs.de/projects/libsmi/ + Use libsmi version > 0.4.5, possibly from libsmi SVN: + svn checkout http://www.ibr.cs.tu-bs.de/svn/libsmi + +[7] PySNMP mailing list archives: + http://sourceforge.net/mail/?group_id=14735 + +[8] PyASN1 project homepage: + http://pyasn1.sf.net + +[9] PyCrypto package: + http://pycrypto.org + +[10] PySMI package: + http://sf.net/projects/pysmi + + +[11] Python Software Foundation + http://www.python.org/psf/ + +=-=-= +mailto: ilya@glas.net diff --git a/docs/source/conf.py b/docs/source/conf.py index 165cdfa..46f13f4 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -295,8 +295,9 @@ texinfo_documents = [ # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = { 'python': ('https://docs.python.org/', None), - 'pysmi': ('http://pysmi.sf.net/', None) } +intersphinx_mapping = { 'python': ('https://docs.python.org/3.4/', None), + 'pysmi': ('http://pysmi.sf.net/', None), + 'twisted': ('https://twistedmatrix.com/documents/15.4.0/api/', None) } # this merges constructor docstring with class docstring autoclass_content = 'both' diff --git a/docs/source/docs/contents.rst b/docs/source/docs/contents.rst index 1e6dc2f..d2447f1 100644 --- a/docs/source/docs/contents.rst +++ b/docs/source/docs/contents.rst @@ -5,57 +5,352 @@ Library reference .. toctree:: :maxdepth: 2 -As dealing with many features may overwhelm developers who aim at a +Dealing with many SNMP features may quickly overwhelm developers who aim at a quick and trivial task, PySNMP employs a layered architecture approach where the topmost programming API tries to be as simple as possible -to allow immediate solutions for most common use cases. For instance -it will let you perform SNMP GET/SET/WALK operations by pasting code -snippets from this web-site right into your Python interactive session. +to allow immediate solutions for most common use cases. +It will let you perform SNMP GET/SET/WALK and TRAP/INFORM operations by +pasting code snippets from PySNMP documentation and example scripts +right into your Python interactive session. + +Synchronous SNMP +---------------- + +Most simple and strightforward way to use PySNMP is by employing its +Synchronous, blocking API. It's also the default API offered by +users on *pysnmp.hlapi* sub-package import. + +Command Generator + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/asyncore/manager/cmdgen/getcmd + /docs/hlapi/asyncore/manager/cmdgen/setcmd + /docs/hlapi/asyncore/manager/cmdgen/nextcmd + /docs/hlapi/asyncore/manager/cmdgen/bulkcmd + +Notification Originator + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/asyncore/agent/ntforg/notification + +Transport configuration + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/asyncore/transport-configuration + +Most of SNMP operations involve packet exchange over network. PySNMP +is shipped with a set of bindings to popular asynchronous Python I/O +frameworks that let you run PySNMP in parallel with other tasks your +application may perform. + +Asynchronous: asyncore +---------------------- + +The :mod:`asyncore` module is in Python standard library since ancient +times. Main loop is built around :mod:`select` dispatcher, user +code is invoked through callback callables. + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/asyncore/manager/cmdgen/async-command-generator + /docs/hlapi/asyncore/agent/ntforg/async-notification-originator + +.. _asyncio: + +Asynchronous: asyncio +--------------------- + +The :mod:`asyncio` module first appeared in standard library since +Python 3.3 (in provisional basis). Its main design feature is that +it makes asynchronous code looking like synchronous one. That greately +simplifies development and maintanence. + +Command Generator + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/asyncio/manager/cmdgen/getcmd + /docs/hlapi/asyncio/manager/cmdgen/setcmd + /docs/hlapi/asyncio/manager/cmdgen/nextcmd + /docs/hlapi/asyncio/manager/cmdgen/bulkcmd + +Notification Originator + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/asyncio/agent/ntforg/notification + +Transport configuration + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/asyncio/transport-configuration + +.. _trollius: + +Asynchronous: trollius +---------------------- + +An almost compatible alternative to :ref:`asyncio` for pre-3.3 Python +is `Trollius `_ module. PySNMP's +`asyncio` bindings automatically work with Trolleus. + +Please refer to :doc:`Trollius examples ` for +more information. + +.. _twisted: + +Asynchronous: Twisted +--------------------- + +`Twisted `_ is one of the earliest and hugely +popular asynchronous I/O framework. It introduced a concept of +:class:`~twisted.internet.defer.Deferred` for representing work-in-progress +that is not blocking the rest of I/O operations. PySNMP provides Twisted +bindings. + +Command Generator + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/twisted/manager/cmdgen/getcmd + /docs/hlapi/twisted/manager/cmdgen/setcmd + /docs/hlapi/twisted/manager/cmdgen/nextcmd + /docs/hlapi/twisted/manager/cmdgen/bulkcmd + +Notification Originator + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/twisted/agent/ntforg/notification + +Transport configuration + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/twisted/transport-configuration + + +SNMP Engine +----------- + +SNMP Engine is a central, stateful object used by all SNMP v3 +substsems. Calls to high-level Applications API also consume SNMP +Engine object on input. + +.. toctree:: + :maxdepth: 2 + +.. autoclass:: pysnmp.hlapi.SnmpEngine(snmpEngineID=None) + +Security Parameters +------------------- + +Calls to high-level Applications API consume Security Parameters +configuration object on input. The shortcut classes described in +this section convey configuration information to SNMP engine's +Local Configuration Datastore (:RFC:`2271#section-3.4.2`). +Once committed to LCD, SNMP engine saves its configuration for +the lifetime of SNMP engine object. + +Community-based ++++++++++++++++ + +Security Parameters object is Security Model specific. The +:py:class:`~pysnmp.hlapi.CommunityData` +class is used for configuring Community-Based Security Model of SNMPv1/SNMPv2c. + +.. toctree:: + :maxdepth: 2 + +.. autoclass:: pysnmp.hlapi.CommunityData(communityIndex, communityName=None, mpModel=1, contextEngineId=None, contextName='', tag='') + +User-based +++++++++++ + +The :py:class:`~pysnmp.hlapi.UsmUserData` class provides SNMPv3 User-Based +Security Model configuration for SNMP v3 systems. + +.. autoclass:: pysnmp.hlapi.UsmUserData(userName, authKey=None, privKey=None, authProtocol=usmNoAuthProtocol, privProtocol=usmNoPrivProtocol, securityEngineId=None) + +Identification of Authentication and Privacy Protocols is done +via constant OIDs: + +.. autodata:: pysnmp.hlapi.usmNoAuthProtocol +.. autodata:: pysnmp.hlapi.usmHMACMD5AuthProtocol +.. autodata:: pysnmp.hlapi.usmHMACSHAAuthProtocol + +.. autodata:: pysnmp.hlapi.usmNoPrivProtocol +.. autodata:: pysnmp.hlapi.usmDESPrivProtocol +.. autodata:: pysnmp.hlapi.usm3DESEDEPrivProtocol +.. autodata:: pysnmp.hlapi.usmAesCfb128Protocol +.. autodata:: pysnmp.hlapi.usmAesCfb192Protocol +.. autodata:: pysnmp.hlapi.usmAesCfb256Protocol + +Transport configuration is I/O framework specific and is described in +respective sections. + +SNMP Context +------------ + +SNMP engine may serve several instances of the same MIB within +possibly multiple SNMP entities. SNMP context is a method to +unambiguously identify a collection of MIB variables behind +SNMP engine. See :RFC:`3411#section-3.3.1` for details. + +.. note:: + + SNMP context is only defined within SNMPv3 framework. For SNMPv1/v2c + architecture integration :RFC:`2576#section-5.1` introduces + interoperability aid which is available through + :py:class:`~pysnmp.hlapi.CommunityData`. + +.. toctree:: + :maxdepth: 2 + +.. autoclass:: pysnmp.hlapi.ContextData + +.. _mib-services: + +MIB services +------------ + +.. _mib-variables: + +MIB Variables ++++++++++++++ + +SNMP MIB variable is identified by an OBJECT IDENTIFIER (OID) and is +accompanied by a value belonging to one of SNMP types (:RFC:`1902#section-2`). +This pair is collectively called a variable-binding in SNMP parlance. + +The :py:mod:`~pysnmp.smi.rfc1902` module implements :RFC:`1902#section-2` +MACRO definiitons. .. toctree:: - /docs/hlapi/contents + :maxdepth: 2 + +.. autoclass:: pysnmp.smi.rfc1902.ObjectIdentity + :members: + +.. autoclass:: pysnmp.smi.rfc1902.ObjectType + :members: + +.. _notification-types: -At the basic level, PySNMP offers a complete set of Standard SNMP -Applications to give you maximum flexibility with integration of SNMP -facilities into other applications, building special purpose SNMP Agents, -TRAP collectors, Proxy entities and all kinds of SNMP-related things. +MIB notification types +++++++++++++++++++++++ -Many user applications are built within some input/output framework. -PySNMP offers native bindings to some of these framework. +SNMP Notifications are enumerated and imply including certain +set of MIB variables. +Notification Originator applications refer to MIBs for MIB notifications +through *NOTIFICATION-TYPE* ASN.1 macro. It conveys a set of MIB variables to +be gathered and reported in SNMP Notification. The +:py:mod:`~pysnmp.smi.rfc1902` module implements :RFC:`1902#section-2` +macro definiitons. .. toctree:: -.. /docs/v3arch/asyncore/contents -.. /docs/v3arch/asyncio/contents -.. /docs/v3arch/trollius/contents -.. /docs/v3arch/twisted/contents + :maxdepth: 2 + +.. autoclass:: pysnmp.smi.rfc1902.NotificationType + :members: + +.. _snmp-types: + +SNMP base types +--------------- -At the other end of the complexity spectrum, PySNMP offers packet-level -ASN.1 data structures that let you build, parse and analyze SNMP messages -travelling over network. This extremely low-level programming interface is -explained by the SNMPv1/v2c example scripts. If your goal is to conduct -experiments on the protocol level or optimize for highest possible -performance - this is a way to go. +SNMP represents real-world objects it serves along with their +states in form of values. Those values each belong to one +of SNMP types (:RFC:`1902#section-2`) which, in turn, are based +on `ASN.1 `_ +data description language. PySNMP types are derived from +`Python ASN.1 types `_ implementation. .. toctree:: -.. /docs/v1arch/asyncore/contents + :maxdepth: 2 + +.. _integer32: + +Integer32 type +++++++++++++++ + +.. autoclass:: pysnmp.proto.rfc1902.Integer32(initializer) + :members: + +.. _integer: + +Integer type +++++++++++++ + +.. autoclass:: pysnmp.proto.rfc1902.Integer(initializer) + :members: + +.. _octetstring: + +OctetString type +++++++++++++++++ + +.. autoclass:: pysnmp.proto.rfc1902.OctetString(strValue=None, hexValue=None) + :members: + +.. _ipaddress: + +IpAddress type +++++++++++++++ + +.. autoclass:: pysnmp.proto.rfc1902.IpAddress(strValue=None, hexValue=None) + +ObjectIdentifier type ++++++++++++++++++++++ + +.. autoclass:: pysnmp.proto.rfc1902.ObjectIdentifier(initializer) + +Counter32 type +++++++++++++++ + +.. autoclass:: pysnmp.proto.rfc1902.Counter32(initializer) + +Gauge32 type +++++++++++++ + +.. autoclass:: pysnmp.proto.rfc1902.Gauge32(initializer) + +Unsigned32 type ++++++++++++++++ + +.. autoclass:: pysnmp.proto.rfc1902.Unsigned32(initializer) + +TimeTicks type +++++++++++++++ + +.. autoclass:: pysnmp.proto.rfc1902.TimeTicks(initializer) + +Opaque type ++++++++++++ -.. comment:: - MIB support - ----------- +.. autoclass:: pysnmp.proto.rfc1902.Opaque(initializer) - SNMP suite of standards defines a data model for objects being managed - (known as `SMI `_), - it takes shape of `MIB `_ - files semi-formally listing and describing capabilities of a SNMP-managed - system. In PySNMP, MIB files are converted into Python code objects which - could be loaded and executed at run-time by both SNMP Manager (for purposes - of data presentation to human beings) and SNMP Agents (as a gateway to - backend systems like DBMS). +Counter64 type +++++++++++++++ - MIB conversion is handled automatically by `PySMI `_ - library. Large collection of original MIB files is maintained at - `our MIB repository `_ . +.. autoclass:: pysnmp.proto.rfc1902.Counter64(initializer) - .. toctree:: - .. /docs/smi/contents +Bits type ++++++++++ +.. autoclass:: pysnmp.proto.rfc1902.Bits(initializer) + :members: diff --git a/docs/source/docs/hlapi/asyncio/agent/ntforg/notification.rst b/docs/source/docs/hlapi/asyncio/agent/ntforg/notification.rst new file mode 100644 index 0000000..954c923 --- /dev/null +++ b/docs/source/docs/hlapi/asyncio/agent/ntforg/notification.rst @@ -0,0 +1,8 @@ + +TRAP/INFORM notification +======================== + +.. toctree:: + :maxdepth: 2 + +.. autofunction:: pysnmp.hlapi.asyncio.sendNotification diff --git a/docs/source/docs/hlapi/asyncio/contents.rst b/docs/source/docs/hlapi/asyncio/contents.rst new file mode 100644 index 0000000..ab7d8e0 --- /dev/null +++ b/docs/source/docs/hlapi/asyncio/contents.rst @@ -0,0 +1,60 @@ + +SNMP with asyncio +================= + +There are a handful of most basic SNMP Applications defined by RFC3413 and +called Standard Applications. Those implementing Manager side of the system +(:RFC:`3411#section-3.1.3.1`) are Command Generator (initiating GET, SET, +GETNEXT, GETBULK operations) and Notification Receiver (handling arrived +notifications). On Agent side (:RFC:`3411#section-3.1.3.2`) there are +Command Responder (handling GET, SET, GETNEXT, GETBULK operations) and +Notification Originator (issuing TRAP and INFORM notifications). In +PySNMP Standard Applications are implemented on top of SNMPv3 framework. + +There're two kinds of high-level programming interfaces to Standard SNMP +Applications: synchronous and asynchronous. They are similar in terms of +call signatures but differ in behaviour. Synchronous calls block the whole +application till requested operation is finished. Asynchronous interface +breaks its synchronous version apart - at first required data are prepared +and put on the outgoing queue. The the application is free to deal with +other tasks till pending message is sent out (by I/O dispacher) and +response is arrived. At that point a previously supplied callback function +will be invoked and response data will be passed along. + +Command Generator + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/asyncio/manager/cmdgen/getcmd + /docs/hlapi/asyncio/manager/cmdgen/setcmd + /docs/hlapi/asyncio/manager/cmdgen/nextcmd + /docs/hlapi/asyncio/manager/cmdgen/bulkcmd + +Notification Originator + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/asyncio/agent/ntforg/notification + +The asynchronous version is best suited for massively parallel SNMP +messaging possibly handling other I/O activities in the same time. The +synchronous version is advised to employ for singular and blocking +operations as well as for rapid prototyping. + +Transport configuration +----------------------- + +Type of network transport SNMP engine uses along with transport +options is summarized by +:py:class:`~pysnmp.hlapi.asyncio.UdpTransportTarget` +and +:py:class:`~pysnmp.hlapi.asyncio.Udp6TransportTarget` +container classes: + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/asyncio/transport-configuration + diff --git a/docs/source/docs/hlapi/asyncio/manager/cmdgen/bulkcmd.rst b/docs/source/docs/hlapi/asyncio/manager/cmdgen/bulkcmd.rst new file mode 100644 index 0000000..970cfb1 --- /dev/null +++ b/docs/source/docs/hlapi/asyncio/manager/cmdgen/bulkcmd.rst @@ -0,0 +1,8 @@ + +GETBULK command +=============== + +.. toctree:: + :maxdepth: 2 + +.. autofunction:: pysnmp.hlapi.asyncio.bulkCmd diff --git a/docs/source/docs/hlapi/asyncio/manager/cmdgen/getcmd.rst b/docs/source/docs/hlapi/asyncio/manager/cmdgen/getcmd.rst new file mode 100644 index 0000000..4ac0a52 --- /dev/null +++ b/docs/source/docs/hlapi/asyncio/manager/cmdgen/getcmd.rst @@ -0,0 +1,8 @@ + +GET command +=========== + +.. toctree:: + :maxdepth: 2 + +.. autofunction:: pysnmp.hlapi.asyncio.getCmd diff --git a/docs/source/docs/hlapi/asyncio/manager/cmdgen/nextcmd.rst b/docs/source/docs/hlapi/asyncio/manager/cmdgen/nextcmd.rst new file mode 100644 index 0000000..b88291c --- /dev/null +++ b/docs/source/docs/hlapi/asyncio/manager/cmdgen/nextcmd.rst @@ -0,0 +1,8 @@ + +GETNEXT command +=============== + +.. toctree:: + :maxdepth: 2 + +.. autofunction:: pysnmp.hlapi.asyncio.nextCmd diff --git a/docs/source/docs/hlapi/asyncio/manager/cmdgen/setcmd.rst b/docs/source/docs/hlapi/asyncio/manager/cmdgen/setcmd.rst new file mode 100644 index 0000000..c34fc44 --- /dev/null +++ b/docs/source/docs/hlapi/asyncio/manager/cmdgen/setcmd.rst @@ -0,0 +1,8 @@ + +SET command +=========== + +.. toctree:: + :maxdepth: 2 + +.. autofunction:: pysnmp.hlapi.asyncio.setCmd diff --git a/docs/source/docs/hlapi/asyncore/contents.rst b/docs/source/docs/hlapi/asyncore/contents.rst new file mode 100644 index 0000000..847c21d --- /dev/null +++ b/docs/source/docs/hlapi/asyncore/contents.rst @@ -0,0 +1,69 @@ + +High-level SNMP +=============== + +There are a handful of most basic SNMP Applications defined by RFC3413 and +called Standard Applications. Those implementing Manager side of the system +(:RFC:`3411#section-3.1.3.1`) are Command Generator (initiating GET, SET, +GETNEXT, GETBULK operations) and Notification Receiver (handling arrived +notifications). On Agent side (:RFC:`3411#section-3.1.3.2`) there are +Command Responder (handling GET, SET, GETNEXT, GETBULK operations) and +Notification Originator (issuing TRAP and INFORM notifications). In +PySNMP Standard Applications are implemented on top of SNMPv3 framework. + +There're two kinds of high-level programming interfaces to Standard SNMP +Applications: synchronous and asynchronous. They are similar in terms of +call signatures but differ in behaviour. Synchronous calls block the whole +application till requested operation is finished. Asynchronous interface +breaks its synchronous version apart - at first required data are prepared +and put on the outgoing queue. The the application is free to deal with +other tasks till pending message is sent out (by I/O dispacher) and +response is arrived. At that point a previously supplied callback function +will be invoked and response data will be passed along. + +Synchronous Command Generator + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/asyncore/manager/cmdgen/getcmd + /docs/hlapi/asyncore/manager/cmdgen/setcmd + /docs/hlapi/asyncore/manager/cmdgen/nextcmd + /docs/hlapi/asyncore/manager/cmdgen/bulkcmd + +Synchronous Notification Originator + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/asyncore/agent/ntforg/notification + +The asynchronous version is best suited for massively parallel SNMP +messaging possibly handling other I/O activities in the same time. The +synchronous version is advised to employ for singular and blocking +operations as well as for rapid prototyping. + +Asynchronous operations +----------------------- + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/asyncore/manager/cmdgen/async-command-generator + /docs/hlapi/asyncore/agent/ntforg/async-notification-originator + +Transport configuration +----------------------- + +Type of network transport SNMP engine uses along with transport +options is summarized by +:py:class:`~pysnmp.hlapi.asyncore.UdpTransportTarget` +and +:py:class:`~pysnmp.hlapi.asyncore.Udp6TransportTarget` +container classes: + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/asyncore/transport-configuration + diff --git a/docs/source/docs/hlapi/asyncore/manager/cmdgen/async-command-generator.rst b/docs/source/docs/hlapi/asyncore/manager/cmdgen/async-command-generator.rst index f8584a7..cd45072 100644 --- a/docs/source/docs/hlapi/asyncore/manager/cmdgen/async-command-generator.rst +++ b/docs/source/docs/hlapi/asyncore/manager/cmdgen/async-command-generator.rst @@ -5,5 +5,4 @@ Asynchronous Command Generator .. toctree:: :maxdepth: 2 -.. autoclass:: pysnmp.hlapi.asyncore.AsyncCommandGenerator - :members: +.. autofunction:: pysnmp.hlapi.asyncore.getCmd diff --git a/docs/source/docs/hlapi/twisted/agent/ntforg/notification.rst b/docs/source/docs/hlapi/twisted/agent/ntforg/notification.rst new file mode 100644 index 0000000..7928912 --- /dev/null +++ b/docs/source/docs/hlapi/twisted/agent/ntforg/notification.rst @@ -0,0 +1,8 @@ + +TRAP/INFORM notification +======================== + +.. toctree:: + :maxdepth: 2 + +.. autofunction:: pysnmp.hlapi.twisted.sendNotification diff --git a/docs/source/docs/hlapi/twisted/contents.rst b/docs/source/docs/hlapi/twisted/contents.rst new file mode 100644 index 0000000..d0decf2 --- /dev/null +++ b/docs/source/docs/hlapi/twisted/contents.rst @@ -0,0 +1,58 @@ + +SNMP with Twisted +================= + +There are a handful of most basic SNMP Applications defined by RFC3413 and +called Standard Applications. Those implementing Manager side of the system +(:RFC:`3411#section-3.1.3.1`) are Command Generator (initiating GET, SET, +GETNEXT, GETBULK operations) and Notification Receiver (handling arrived +notifications). On Agent side (:RFC:`3411#section-3.1.3.2`) there are +Command Responder (handling GET, SET, GETNEXT, GETBULK operations) and +Notification Originator (issuing TRAP and INFORM notifications). In +PySNMP Standard Applications are implemented on top of SNMPv3 framework. + +There're two kinds of high-level programming interfaces to Standard SNMP +Applications: synchronous and asynchronous. They are similar in terms of +call signatures but differ in behaviour. Synchronous calls block the whole +application till requested operation is finished. Asynchronous interface +breaks its synchronous version apart - at first required data are prepared +and put on the outgoing queue. The the application is free to deal with +other tasks till pending message is sent out (by I/O dispacher) and +response is arrived. At that point a previously supplied callback function +will be invoked and response data will be passed along. + +Command Generator + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/twisted/manager/cmdgen/getcmd + /docs/hlapi/twisted/manager/cmdgen/setcmd + /docs/hlapi/twisted/manager/cmdgen/nextcmd + /docs/hlapi/twisted/manager/cmdgen/bulkcmd + +Notification Originator + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/twisted/agent/ntforg/notification + +The asynchronous version is best suited for massively parallel SNMP +messaging possibly handling other I/O activities in the same time. The +synchronous version is advised to employ for singular and blocking +operations as well as for rapid prototyping. + +Transport configuration +----------------------- + +Type of network transport SNMP engine uses along with transport +options is summarized by +:py:class:`~pysnmp.hlapi.twisted.UdpTransportTarget` +container class: + +.. toctree:: + :maxdepth: 2 + + /docs/hlapi/twisted/transport-configuration + diff --git a/docs/source/docs/hlapi/twisted/manager/cmdgen/bulkcmd.rst b/docs/source/docs/hlapi/twisted/manager/cmdgen/bulkcmd.rst new file mode 100644 index 0000000..24fff6e --- /dev/null +++ b/docs/source/docs/hlapi/twisted/manager/cmdgen/bulkcmd.rst @@ -0,0 +1,8 @@ + +GETBULK command +=============== + +.. toctree:: + :maxdepth: 2 + +.. autofunction:: pysnmp.hlapi.twisted.bulkCmd diff --git a/docs/source/docs/hlapi/twisted/manager/cmdgen/getcmd.rst b/docs/source/docs/hlapi/twisted/manager/cmdgen/getcmd.rst new file mode 100644 index 0000000..53d3a14 --- /dev/null +++ b/docs/source/docs/hlapi/twisted/manager/cmdgen/getcmd.rst @@ -0,0 +1,8 @@ + +GET command +=========== + +.. toctree:: + :maxdepth: 2 + +.. autofunction:: pysnmp.hlapi.twisted.getCmd diff --git a/docs/source/docs/hlapi/twisted/manager/cmdgen/nextcmd.rst b/docs/source/docs/hlapi/twisted/manager/cmdgen/nextcmd.rst new file mode 100644 index 0000000..54aa540 --- /dev/null +++ b/docs/source/docs/hlapi/twisted/manager/cmdgen/nextcmd.rst @@ -0,0 +1,8 @@ + +GETNEXT command +=============== + +.. toctree:: + :maxdepth: 2 + +.. autofunction:: pysnmp.hlapi.twisted.nextCmd diff --git a/docs/source/docs/hlapi/twisted/manager/cmdgen/setcmd.rst b/docs/source/docs/hlapi/twisted/manager/cmdgen/setcmd.rst new file mode 100644 index 0000000..8a7890a --- /dev/null +++ b/docs/source/docs/hlapi/twisted/manager/cmdgen/setcmd.rst @@ -0,0 +1,8 @@ + +SET command +=========== + +.. toctree:: + :maxdepth: 2 + +.. autofunction:: pysnmp.hlapi.twisted.setCmd diff --git a/examples/hlapi/asyncio/agent/ntforg/default-v1-trap.py b/examples/hlapi/asyncio/agent/ntforg/default-v1-trap.py new file mode 100644 index 0000000..20cee83 --- /dev/null +++ b/examples/hlapi/asyncio/agent/ntforg/default-v1-trap.py @@ -0,0 +1,54 @@ +""" +SNMPv1 TRAP with defaults ++++++++++++++++++++++++++ + +Send SNMPv1 TRAP through unified SNMPv3 message processing framework +using the following options: + +* SNMPv1 +* with community name 'public' +* over IPv4/UDP +* send TRAP notification +* with Generic Trap #1 (warmStart) and Specific Trap 0 +* with default Uptime +* with default Agent Address +* with Enterprise OID 1.3.6.1.4.1.20408.4.1.1.2 +* include managed object information '1.3.6.1.2.1.1.1.0' = 'my system' + +Functionally similar to: + +| $ snmptrap -v1 -c public demo.snmplabs.com \ +| 1.3.6.1.4.1.20408.4.1.1.2 \ +| 0.0.0.0 \ +| 1 \ +| 0 \ +| 0 +| '1.3.6.1.2.1.1.1.0' s 'my system' + +"""# +import asyncio +from pysnmp.hlapi.asyncio import * + +@asyncio.coroutine +def run(): + snmpEngine = SnmpEngine() + errorIndication, errorStatus, errorIndex, varBinds = yield from sendNotification( + snmpEngine, + CommunityData('public'), # mpModel=0), + UdpTransportTarget(('localhost', 162)), + ContextData(), + 'inform', + NotificationType( + ObjectIdentity('1.3.6.1.6.3.1.1.5.2') + ).addVarBinds( + ('1.3.6.1.6.3.1.1.4.3.0', '1.3.6.1.4.1.20408.4.1.1.2'), + ('1.3.6.1.2.1.1.1.0', OctetString('my system')) + ) + ) + + if errorIndication: + print(errorIndication) + + snmpEngine.transportDispatcher.closeDispatcher() + +asyncio.get_event_loop().run_until_complete(run()) diff --git a/examples/hlapi/asyncio/agent/ntforg/multiple-notifications-at-once.py b/examples/hlapi/asyncio/agent/ntforg/multiple-notifications-at-once.py new file mode 100644 index 0000000..a67e374 --- /dev/null +++ b/examples/hlapi/asyncio/agent/ntforg/multiple-notifications-at-once.py @@ -0,0 +1,55 @@ +""" +Multiple concurrent notifications ++++++++++++++++++++++++++++++++++ + +Send multiple SNMP notifications at once using the following options: + +* SNMPv2c and SNMPv3 +* with community name 'public' +* over IPv4/UDP +* send INFORM notification +* to multiple Managers +* with TRAP ID 'coldStart' specified as a MIB symbol +* include managed object information specified as var-bind objects pair + +Here we tag each SNMP-COMMUNITY-MIB::snmpCommunityTable row +with the same tag as SNMP-TARGET-MIB::snmpTargetAddrTable row +what leads to excessive tables information. + +Functionally similar to: + +| $ snmptrap -v2c -c public demo.snmplabs.com 12345 1.3.6.1.6.3.1.1.5.2 +| $ snmpinform -v2c -c public localhost 12345 1.3.6.1.6.3.1.1.5.2 +| $ snmptrap -v2c -c public demo.snmplabs.com 12345 1.3.6.1.6.3.1.1.5.2 + +"""# +import asyncio +from pysnmp.hlapi.asyncio import * + +@asyncio.coroutine +def sendone(snmpEngine, hostname, notifyType): + errorIndication, errorStatus, \ + errorIndex, varBinds = yield from sendNotification( + snmpEngine, + CommunityData('public', tag=hostname), + UdpTransportTarget((hostname, 162), tagList=hostname), + ContextData(), + notifyType, + NotificationType( + ObjectIdentity('1.3.6.1.6.3.1.1.5.2') + ).addVarBinds( + ('1.3.6.1.6.3.1.1.4.3.0', '1.3.6.1.4.1.20408.4.1.1.2'), + ('1.3.6.1.2.1.1.1.0', OctetString('my system')) + ) + ) + + if errorIndication: + print(errorIndication) + +snmpEngine = SnmpEngine() + +loop = asyncio.get_event_loop() +loop.run_until_complete( + asyncio.wait([sendone(snmpEngine, 'demo.snmplabs.com', 'trap'), + sendone(snmpEngine, 'localhost', 'inform')]) +) diff --git a/examples/hlapi/asyncio/manager/cmdgen/getbulk-to-eom.py b/examples/hlapi/asyncio/manager/cmdgen/getbulk-to-eom.py new file mode 100644 index 0000000..c555683 --- /dev/null +++ b/examples/hlapi/asyncio/manager/cmdgen/getbulk-to-eom.py @@ -0,0 +1,59 @@ +""" +Bulk walk MIB ++++++++++++++ + +Send a series of SNMP GETBULK requests using the following options: + +* with SNMPv3, user 'usr-none-none', no authentication, no privacy +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for all OIDs past SNMPv2-MIB::system +* run till end-of-mib condition is reported by Agent +* based on asyncio I/O framework + +Functionally similar to: + +| $ snmpbulkwalk -v3 -lnoAuthNoPriv -u usr-none-none -Cn0 -Cr50 \ +| demo.snmplabs.com SNMPv2-MIB::system + +"""# +import asyncio +from pysnmp.hlapi.asyncio import * + +@asyncio.coroutine +def run(varBinds): + snmpEngine = SnmpEngine() + while True: + errorIndication, errorStatus, errorIndex, \ + varBindTable = yield from bulkCmd( + snmpEngine, + UsmUserData('usr-none-none'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + 0, 50, + *varBinds) + + if errorIndication: + print(errorIndication) + break + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for varBindRow in varBindTable: + for varBind in varBindRow: + print(' = '.join([ x.prettyPrint() for x in varBind ])) + + varBinds = varBindTable[-1] + if isEndOfMib(varBinds): + break + + snmpEngine.transportDispatcher.closeDispatcher() + +loop = asyncio.get_event_loop() +loop.run_until_complete( + run([ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr'))]) +) diff --git a/examples/hlapi/asyncio/manager/cmdgen/multiple-concurrent-async-queries.py b/examples/hlapi/asyncio/manager/cmdgen/multiple-concurrent-async-queries.py new file mode 100644 index 0000000..81de80a --- /dev/null +++ b/examples/hlapi/asyncio/manager/cmdgen/multiple-concurrent-async-queries.py @@ -0,0 +1,52 @@ +""" +Concurrent queries +++++++++++++++++++ + +Send multiple SNMP GET requests at once using the following options: + +* with SNMPv2c, community 'public' +* over IPv4/UDP +* to multiple Agents at demo.snmplabs.com +* for instance of SNMPv2-MIB::sysDescr.0 MIB object +* based on asyncio I/O framework + +Functionally similar to: + +| $ snmpget -v2c -c public demo.snmplabs.com:1161 SNMPv2-MIB::sysDescr.0 +| $ snmpget -v2c -c public demo.snmplabs.com:2161 SNMPv2-MIB::sysDescr.0 +| $ snmpget -v2c -c public demo.snmplabs.com:3161 SNMPv2-MIB::sysDescr.0 + +"""# +import asyncio +from pysnmp.hlapi.asyncio import * + +@asyncio.coroutine +def getone(snmpEngine, hostname): + errorIndication, errorStatus, errorIndex, varBinds = yield from getCmd( + snmpEngine, + CommunityData('public'), + UdpTransportTarget(hostname), + ContextData(), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)) + ) + + if errorIndication: + print(errorIndication) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) + +snmpEngine = SnmpEngine() + +loop = asyncio.get_event_loop() +loop.run_until_complete( + asyncio.wait([getone(snmpEngine, ('demo.snmplabs.com', 1161)), + getone(snmpEngine, ('demo.snmplabs.com', 2161)), + getone(snmpEngine, ('demo.snmplabs.com', 3161))]) +) diff --git a/examples/hlapi/asyncio/manager/cmdgen/multiple-sequential-async-queries.py b/examples/hlapi/asyncio/manager/cmdgen/multiple-sequential-async-queries.py new file mode 100644 index 0000000..1867d5b --- /dev/null +++ b/examples/hlapi/asyncio/manager/cmdgen/multiple-sequential-async-queries.py @@ -0,0 +1,55 @@ +""" +Concurrent queries +++++++++++++++++++ + +Send multiple SNMP GET requests one by one using the following options: + +* with SNMPv2c, community 'public' +* over IPv4/UDP +* to multiple Agents at demo.snmplabs.com +* for instance of SNMPv2-MIB::sysDescr.0 MIB object +* based on asyncio I/O framework + +Functionally similar to: + +| $ snmpget -v2c -c public demo.snmplabs.com:1161 SNMPv2-MIB::sysDescr.0 +| $ snmpget -v2c -c public demo.snmplabs.com:2161 SNMPv2-MIB::sysDescr.0 +| $ snmpget -v2c -c public demo.snmplabs.com:3161 SNMPv2-MIB::sysDescr.0 + +"""# +import asyncio +from pysnmp.hlapi.asyncio import * + +@asyncio.coroutine +def getone(snmpEngine, hostname): + errorIndication, errorStatus, errorIndex, varBinds = yield from getCmd( + snmpEngine, + CommunityData('public'), + UdpTransportTarget(hostname), + ContextData(), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)) + ) + + if errorIndication: + print(errorIndication) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) + +@asyncio.coroutine +def getall(snmpEngine, hostnames): + for hostname in hostnames: + yield from getone(snmpEngine, hostname) + +snmpEngine = SnmpEngine() + +loop = asyncio.get_event_loop() +loop.run_until_complete(getall(snmpEngine, [('demo.snmplabs.com', 1161), + ('demo.snmplabs.com', 2161), + ('demo.snmplabs.com', 3161)])) diff --git a/examples/hlapi/asyncio/manager/cmdgen/v1-get.py b/examples/hlapi/asyncio/manager/cmdgen/v1-get.py new file mode 100644 index 0000000..7757dec --- /dev/null +++ b/examples/hlapi/asyncio/manager/cmdgen/v1-get.py @@ -0,0 +1,46 @@ +""" +SNMPv1 +++++++ + +Send SNMP GET request using the following options: + + * with SNMPv1, community 'public' + * over IPv4/UDP + * to an Agent at demo.snmplabs.com:161 + * for an instance of SNMPv2-MIB::sysDescr.0 MIB object + * Based on asyncio I/O framework + +Functionally similar to: + +| $ snmpget -v1 -c public demo.snmplabs.com SNMPv2-MIB::sysDescr.0 + +"""# +import asyncio +from pysnmp.hlapi.asyncio import * + +@asyncio.coroutine +def run(): + snmpEngine = SnmpEngine() + errorIndication, errorStatus, errorIndex, varBinds = yield from getCmd( + snmpEngine, + CommunityData('public', mpModel=0), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)) + ) + + if errorIndication: + print(errorIndication) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) + + snmpEngine.transportDispatcher.closeDispatcher() + +asyncio.get_event_loop().run_until_complete(run()) diff --git a/examples/hlapi/asyncore/agent/ntforg/async-multiple-informs-at-once.py b/examples/hlapi/asyncore/agent/ntforg/async-multiple-informs-at-once.py index e2cacbe..c0ae96b 100644 --- a/examples/hlapi/asyncore/agent/ntforg/async-multiple-informs-at-once.py +++ b/examples/hlapi/asyncore/agent/ntforg/async-multiple-informs-at-once.py @@ -42,10 +42,8 @@ def cbFun(snmpEngine, sendRequestHandle, errorIndication, snmpEngine = SnmpEngine() -ntfOrg = AsyncNotificationOriginator() - for authData, transportTarget, contextData in targets: - sendPduHandle = ntfOrg.sendNotification( + sendPduHandle = sendNotification( snmpEngine, authData, transportTarget, @@ -54,7 +52,7 @@ for authData, transportTarget, contextData in targets: NotificationType( ObjectIdentity('SNMPv2-MIB', 'coldStart') ).addVarBinds( ( '1.3.6.1.2.1.1.1.0', 'my name' ) ), - cbInfo=(cbFun, None) + cbFun=cbFun ) snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/hlapi/asyncore/agent/ntforg/async-multiple-traps-at-once.py b/examples/hlapi/asyncore/agent/ntforg/async-multiple-traps-at-once.py index 3d4d4b6..729f2e5 100644 --- a/examples/hlapi/asyncore/agent/ntforg/async-multiple-traps-at-once.py +++ b/examples/hlapi/asyncore/agent/ntforg/async-multiple-traps-at-once.py @@ -31,10 +31,8 @@ targets = ( snmpEngine = SnmpEngine() -ntfOrg = AsyncNotificationOriginator() - for authData, transportTarget, contextData in targets: - ntfOrg.sendNotification( + sendNotification( snmpEngine, authData, transportTarget, @@ -43,7 +41,7 @@ for authData, transportTarget, contextData in targets: NotificationType( ObjectIdentity('SNMPv2-MIB', 'coldStart') ).addVarBinds( - ( ObjectName('1.3.6.1.2.1.1.1.0'), + ( ObjectIdentifier('1.3.6.1.2.1.1.1.0'), OctetString('my name') ) ) ) diff --git a/examples/hlapi/asyncore/agent/ntforg/async-running-multiple-snmp-engines-at-once.py b/examples/hlapi/asyncore/agent/ntforg/async-running-multiple-snmp-engines-at-once.py index 9df9daf..ce9db15 100644 --- a/examples/hlapi/asyncore/agent/ntforg/async-running-multiple-snmp-engines-at-once.py +++ b/examples/hlapi/asyncore/agent/ntforg/async-running-multiple-snmp-engines-at-once.py @@ -68,12 +68,10 @@ snmpEngineA.registerTransportDispatcher(transportDispatcher, 'A') snmpEngineB = SnmpEngine() snmpEngineB.registerTransportDispatcher(transportDispatcher, 'B') -ntfOrg = AsyncNotificationOriginator() - for authData, transportTarget, contextData in targets: snmpEngine = transportTarget.getTransportInfo()[1][1] % 3 and \ snmpEngineA or snmpEngineB - sendPduHandle = ntfOrg.sendNotification( + sendPduHandle = sendNotification( snmpEngine, authData, transportTarget, @@ -82,7 +80,7 @@ for authData, transportTarget, contextData in targets: NotificationType( ObjectIdentity('SNMPv2-MIB', 'coldStart') ).addVarBinds( ( '1.3.6.1.2.1.1.1.0', 'my name' ) ), - cbInfo=(cbFun, snmpEngine) + cbFun=cbFun, cbCtx=snmpEngine ) transportDispatcher.runDispatcher() diff --git a/examples/hlapi/asyncore/agent/ntforg/custom-contextengineid.py b/examples/hlapi/asyncore/agent/ntforg/custom-contextengineid.py index 1a65a61..2ccdafe 100644 --- a/examples/hlapi/asyncore/agent/ntforg/custom-contextengineid.py +++ b/examples/hlapi/asyncore/agent/ntforg/custom-contextengineid.py @@ -24,15 +24,13 @@ Functionally similar to: | 1.3.6.1.6.3.1.1.5.2 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( sendNotification(SnmpEngine(), UsmUserData('usr-md5-none', 'authkey1'), UdpTransportTarget(('localhost', 162)), - ContextData( - rfc1902.OctetString(hexValue='8000000004030201') - ), + ContextData(OctetString(hexValue='8000000004030201')), 'inform', NotificationType(ObjectIdentity('1.3.6.1.6.3.1.1.5.2'))) ) diff --git a/examples/hlapi/asyncore/agent/ntforg/custom-contextname.py b/examples/hlapi/asyncore/agent/ntforg/custom-contextname.py index c322d55..a087c7e 100644 --- a/examples/hlapi/asyncore/agent/ntforg/custom-contextname.py +++ b/examples/hlapi/asyncore/agent/ntforg/custom-contextname.py @@ -24,7 +24,7 @@ Functionally similar to: | 1.3.6.1.6.3.1.1.5.2 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( sendNotification(SnmpEngine(), diff --git a/examples/hlapi/asyncore/agent/ntforg/custom-v1-trap.py b/examples/hlapi/asyncore/agent/ntforg/custom-v1-trap.py index 51bf05a..768ad26 100644 --- a/examples/hlapi/asyncore/agent/ntforg/custom-v1-trap.py +++ b/examples/hlapi/asyncore/agent/ntforg/custom-v1-trap.py @@ -28,7 +28,7 @@ Functionally similar to: | '1.3.6.1.2.1.1.1.0' s 'my system' """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( sendNotification(SnmpEngine(), @@ -42,7 +42,7 @@ errorIndication, errorStatus, errorIndex, varBinds = next( ('1.3.6.1.2.1.1.3.0', 12345), ('1.3.6.1.6.3.18.1.3.0', '127.0.0.1'), ('1.3.6.1.6.3.1.1.4.3.0', '1.3.6.1.4.1.20408.4.1.1.2'), - ('1.3.6.1.2.1.1.1.0', rfc1902.OctetString('my system')) + ('1.3.6.1.2.1.1.1.0', OctetString('my system')) ) ) ) diff --git a/examples/hlapi/asyncore/agent/ntforg/default-v1-trap.py b/examples/hlapi/asyncore/agent/ntforg/default-v1-trap.py index 75542ba..7d4a9d0 100644 --- a/examples/hlapi/asyncore/agent/ntforg/default-v1-trap.py +++ b/examples/hlapi/asyncore/agent/ntforg/default-v1-trap.py @@ -26,7 +26,7 @@ Functionally similar to: | '1.3.6.1.2.1.1.1.0' s 'my system' """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( sendNotification(SnmpEngine(), @@ -38,7 +38,7 @@ errorIndication, errorStatus, errorIndex, varBinds = next( ObjectIdentity('1.3.6.1.6.3.1.1.5.2') ).addVarBinds( ('1.3.6.1.6.3.1.1.4.3.0', '1.3.6.1.4.1.20408.4.1.1.2'), - ('1.3.6.1.2.1.1.1.0', rfc1902.OctetString('my system')) + ('1.3.6.1.2.1.1.1.0', OctetString('my system')) ) ) ) diff --git a/examples/hlapi/asyncore/agent/ntforg/send-notification-with-additional-varbinds.py b/examples/hlapi/asyncore/agent/ntforg/send-notification-with-additional-varbinds.py index 096eb34..17cf899 100644 --- a/examples/hlapi/asyncore/agent/ntforg/send-notification-with-additional-varbinds.py +++ b/examples/hlapi/asyncore/agent/ntforg/send-notification-with-additional-varbinds.py @@ -20,7 +20,7 @@ Functionally similar to: | 1.3.6.1.2.1.1.1.0 s 'my system' """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( sendNotification(SnmpEngine(), diff --git a/examples/hlapi/asyncore/agent/ntforg/v2c-trap-via-notification-type.py b/examples/hlapi/asyncore/agent/ntforg/v2c-trap-via-notification-type.py index 296aebc..e5121b2 100644 --- a/examples/hlapi/asyncore/agent/ntforg/v2c-trap-via-notification-type.py +++ b/examples/hlapi/asyncore/agent/ntforg/v2c-trap-via-notification-type.py @@ -16,10 +16,10 @@ Functionally similar to: | $ snmptrap -v2c -c public demo.snmplabs.com \ | 12345 -| 1.3.6.1.4.1.20408.4.1.1.2 \ +| 1.3.6.1.4.1.20408.4.1.1.2 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( sendNotification(SnmpEngine(), diff --git a/examples/hlapi/asyncore/agent/ntforg/v3-inform.py b/examples/hlapi/asyncore/agent/ntforg/v3-inform.py index ebf2fdf..39f5127 100644 --- a/examples/hlapi/asyncore/agent/ntforg/v3-inform.py +++ b/examples/hlapi/asyncore/agent/ntforg/v3-inform.py @@ -20,7 +20,7 @@ Functionally similar to: | '1.3.6.1.2.1.1.1.0' s 'my system' """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( sendNotification(SnmpEngine(), diff --git a/examples/hlapi/asyncore/agent/ntforg/v3-trap.py b/examples/hlapi/asyncore/agent/ntforg/v3-trap.py index 27d081d..ba62b39 100644 --- a/examples/hlapi/asyncore/agent/ntforg/v3-trap.py +++ b/examples/hlapi/asyncore/agent/ntforg/v3-trap.py @@ -26,7 +26,7 @@ Functionally similar to: | '1.3.6.1.2.1.1.1.0' s 'my system' """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( sendNotification(SnmpEngine(OctetString(hexValue='8000000001020304')), diff --git a/examples/hlapi/asyncore/manager/cmdgen/async-pull-mibs-from-multiple-agents-at-once.py b/examples/hlapi/asyncore/manager/cmdgen/async-pull-mibs-from-multiple-agents-at-once.py index ecb35ee..b671f19 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/async-pull-mibs-from-multiple-agents-at-once.py +++ b/examples/hlapi/asyncore/manager/cmdgen/async-pull-mibs-from-multiple-agents-at-once.py @@ -12,7 +12,7 @@ following options: over IPv6/UDP * to an Agent at demo.snmplabs.com:161 and to an Agent at [::1]:161 -* for multiple MIB subtrees and tables +* pull variables till EOM """# from pysnmp.hlapi.asyncore import * @@ -44,7 +44,7 @@ targets = ( # Wait for responses or errors, submit GETNEXT requests for further OIDs def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBindTable, cbCtx): - (varBindHead, authData, transportTarget) = cbCtx + (authData, transportTarget) = cbCtx print('%s via %s' % (authData, transportTarget)) if errorIndication: print(errorIndication) @@ -57,13 +57,6 @@ def cbFun(snmpEngine, sendRequestHandle, errorIndication, ) return else: - for idx, varBind in enumerate(varBindTable[-1]): - if varBind[1] is not None and varBindHead[idx] <= varBind[0]: - break # still in table - else: - print('went out of table at %s' % (name, )) - return - for varBindRow in varBindTable: for varBind in varBindRow: print(' = '.join([ x.prettyPrint() for x in varBind ])) @@ -72,15 +65,9 @@ def cbFun(snmpEngine, sendRequestHandle, errorIndication, snmpEngine = SnmpEngine() -cmdGen = AsyncCommandGenerator() - # Submit initial GETNEXT requests and wait for responses for authData, transportTarget, varBinds in targets: - varBindHead = [ x[0] for x in cmdGen.makeVarBinds(snmpEngine, varBinds ) ] - cmdGen.nextCmd( - snmpEngine, authData, transportTarget, ContextData(), varBinds, - # User-space callback function and its context - (cbFun, (varBindHead, authData, transportTarget)) - ) + nextCmd(snmpEngine, authData, transportTarget, ContextData(), varBinds, + cbFun=cbFun, cbCtx=(authData, transportTarget)) snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/hlapi/asyncore/manager/cmdgen/async-query-multiple-snmp-engines.py b/examples/hlapi/asyncore/manager/cmdgen/async-query-multiple-snmp-engines.py index 1ce32ae..d0a5c62 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/async-query-multiple-snmp-engines.py +++ b/examples/hlapi/asyncore/manager/cmdgen/async-query-multiple-snmp-engines.py @@ -88,14 +88,10 @@ snmpEngineA.registerTransportDispatcher(transportDispatcher, 'A') snmpEngineB = SnmpEngine() snmpEngineB.registerTransportDispatcher(transportDispatcher, 'B') -cmdGen = AsyncCommandGenerator() - for authData, transportTarget, varBinds in targets: snmpEngine = transportTarget.getTransportInfo()[1][1] % 3 and \ snmpEngineA or snmpEngineB - cmdGen.getCmd( - snmpEngine, authData, transportTarget, ContextData(), varBinds, - (cbFun, (snmpEngine, authData, transportTarget)) - ) + getCmd(snmpEngine, authData, transportTarget, ContextData(), varBinds, + cbFun=cbFun, cbCtx=(snmpEngine, authData, transportTarget)) transportDispatcher.runDispatcher() diff --git a/examples/hlapi/asyncore/manager/cmdgen/coerce-set-value-to-mib-spec.py b/examples/hlapi/asyncore/manager/cmdgen/coerce-set-value-to-mib-spec.py index bbcac86..ab2df92 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/coerce-set-value-to-mib-spec.py +++ b/examples/hlapi/asyncore/manager/cmdgen/coerce-set-value-to-mib-spec.py @@ -15,7 +15,7 @@ Functionally similar to: | = "new system name" """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( setCmd(SnmpEngine(), diff --git a/examples/hlapi/asyncore/manager/cmdgen/custom-asn1-mib-search-path.py b/examples/hlapi/asyncore/manager/cmdgen/custom-asn1-mib-search-path.py index 445d665..22fbe6d 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/custom-asn1-mib-search-path.py +++ b/examples/hlapi/asyncore/manager/cmdgen/custom-asn1-mib-search-path.py @@ -16,7 +16,7 @@ Functionally similar to: | IF-MIB::ifInOctets.1 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( getCmd(SnmpEngine(), diff --git a/examples/hlapi/asyncore/manager/cmdgen/custom-contextengineid-and-contextname.py b/examples/hlapi/asyncore/manager/cmdgen/custom-contextengineid-and-contextname.py index 2e84bba..1244583 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/custom-contextengineid-and-contextname.py +++ b/examples/hlapi/asyncore/manager/cmdgen/custom-contextengineid-and-contextname.py @@ -20,7 +20,7 @@ Functionally similar to: | SNMPv2-MIB::sysORDescr.1 = "new system name" """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( setCmd(SnmpEngine(), diff --git a/examples/hlapi/asyncore/manager/cmdgen/custom-contextengineid.py b/examples/hlapi/asyncore/manager/cmdgen/custom-contextengineid.py index d8e19ab..ea97c59 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/custom-contextengineid.py +++ b/examples/hlapi/asyncore/manager/cmdgen/custom-contextengineid.py @@ -18,7 +18,7 @@ Functionally similar to: | SNMPv2-MIB::sysORDescr.1 = "new system name" """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( setCmd(SnmpEngine(), diff --git a/examples/hlapi/asyncore/manager/cmdgen/custom-pysnmp-mibs-search-path.py b/examples/hlapi/asyncore/manager/cmdgen/custom-pysnmp-mibs-search-path.py index e49ef4b..42b1df6 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/custom-pysnmp-mibs-search-path.py +++ b/examples/hlapi/asyncore/manager/cmdgen/custom-pysnmp-mibs-search-path.py @@ -18,7 +18,7 @@ Functionally similar to: | demo.snmplabs.com TCP-MIB::tcpConnTable """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * for errorIndication, \ errorStatus, errorIndex, \ diff --git a/examples/hlapi/asyncore/manager/cmdgen/custom-timeout-and-retries.py b/examples/hlapi/asyncore/manager/cmdgen/custom-timeout-and-retries.py index a6965fe..cfa274f 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/custom-timeout-and-retries.py +++ b/examples/hlapi/asyncore/manager/cmdgen/custom-timeout-and-retries.py @@ -25,16 +25,16 @@ means one initial request plus one retry. Functionally similar to: -| $ snmpget -v1 -c public demo.snmplabs.com 1.3.6.1.2.1.1.1.0 +| $ snmpget -v1 -c public -t 2 -r 0 demo.snmplabs.com 1.3.6.1.2.1.1.1.0 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( getCmd(SnmpEngine(), CommunityData('public'), UdpTransportTarget( - ('demo.snmplabs.com', 161), timeout=1.5, retries=0 + ('demo.snmplabs.com', 161), timeout=2.0, retries=0 ), ContextData(), ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0'))) diff --git a/examples/hlapi/asyncore/manager/cmdgen/custom-v3-security-name.py b/examples/hlapi/asyncore/manager/cmdgen/custom-v3-security-name.py index 77c4cf6..4346b26 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/custom-v3-security-name.py +++ b/examples/hlapi/asyncore/manager/cmdgen/custom-v3-security-name.py @@ -15,7 +15,7 @@ allows you to address a USM Table row just as userName does. However securityName can be made human-readable, also it is not an index in usmUserTable, thus duplicate securityName parameters are possible. """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( getCmd(SnmpEngine(), diff --git a/examples/hlapi/asyncore/manager/cmdgen/fetch-variables-over-ipv6.py b/examples/hlapi/asyncore/manager/cmdgen/fetch-variables-over-ipv6.py index 3967ab6..d431659 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/fetch-variables-over-ipv6.py +++ b/examples/hlapi/asyncore/manager/cmdgen/fetch-variables-over-ipv6.py @@ -17,7 +17,7 @@ Functionally similar to: | 1.3.6.1.2.1.1.2.0 \ | 1.3.6.1.2.1.1.3.0 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( getCmd(SnmpEngine(), diff --git a/examples/hlapi/asyncore/manager/cmdgen/get-table-object-by-index.py b/examples/hlapi/asyncore/manager/cmdgen/get-table-object-by-index.py index 6b382ea..fc8a882 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/get-table-object-by-index.py +++ b/examples/hlapi/asyncore/manager/cmdgen/get-table-object-by-index.py @@ -17,7 +17,7 @@ Functionally similar to: | IF-MIB::ifInOctets.1 IF-MIB::ifOutOctets.1 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( getCmd(SnmpEngine(), diff --git a/examples/hlapi/asyncore/manager/cmdgen/get-table-object-by-multiple-indices.py b/examples/hlapi/asyncore/manager/cmdgen/get-table-object-by-multiple-indices.py index e344dc0..5d0621d 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/get-table-object-by-multiple-indices.py +++ b/examples/hlapi/asyncore/manager/cmdgen/get-table-object-by-multiple-indices.py @@ -17,7 +17,7 @@ Functionally similar to: | TCP-MIB::tcpConnLocalAddress."0.0.0.0".22."0.0.0.0".0 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( getCmd(SnmpEngine(), diff --git a/examples/hlapi/asyncore/manager/cmdgen/getbulk-fetch-scalar-and-table-variables.py b/examples/hlapi/asyncore/manager/cmdgen/getbulk-fetch-scalar-and-table-variables.py index f30ae1e..6b18d42 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/getbulk-fetch-scalar-and-table-variables.py +++ b/examples/hlapi/asyncore/manager/cmdgen/getbulk-fetch-scalar-and-table-variables.py @@ -20,7 +20,7 @@ Functionally similar to: | IP-MIB::ipAddrEntry """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * for errorIndication, \ errorStatus, errorIndex, \ diff --git a/examples/hlapi/asyncore/manager/cmdgen/getbulk-limit-number-of-packets.py b/examples/hlapi/asyncore/manager/cmdgen/getbulk-limit-number-of-packets.py index 0cf9e0f..5146808 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/getbulk-limit-number-of-packets.py +++ b/examples/hlapi/asyncore/manager/cmdgen/getbulk-limit-number-of-packets.py @@ -17,7 +17,7 @@ Functionally similar to: | demo.snmplabs.com SNMPv2-MIB::system """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * for errorIndication, \ errorStatus, errorIndex, \ diff --git a/examples/hlapi/asyncore/manager/cmdgen/getbulk-limit-number-of-variables.py b/examples/hlapi/asyncore/manager/cmdgen/getbulk-limit-number-of-variables.py index ec2abdd..ef95f5a 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/getbulk-limit-number-of-variables.py +++ b/examples/hlapi/asyncore/manager/cmdgen/getbulk-limit-number-of-variables.py @@ -19,7 +19,7 @@ Functionally similar to: | 1.3.6.1.2.1.2.2 1.3.6.1.2.1.2.3 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * for errorIndication, \ errorStatus, errorIndex, \ diff --git a/examples/hlapi/asyncore/manager/cmdgen/getnext-limit-number-of-variables.py b/examples/hlapi/asyncore/manager/cmdgen/getnext-limit-number-of-variables.py index 2844bfa..9536ebb 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/getnext-limit-number-of-variables.py +++ b/examples/hlapi/asyncore/manager/cmdgen/getnext-limit-number-of-variables.py @@ -18,7 +18,7 @@ Functionally similar to: | SNMPv2-MIB::system """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * for errorIndication, \ errorStatus, errorIndex, \ diff --git a/examples/hlapi/asyncore/manager/cmdgen/getnext-multiple-oids-to-eom.py b/examples/hlapi/asyncore/manager/cmdgen/getnext-multiple-oids-to-eom.py index ac66388..c2858a7 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/getnext-multiple-oids-to-eom.py +++ b/examples/hlapi/asyncore/manager/cmdgen/getnext-multiple-oids-to-eom.py @@ -16,7 +16,7 @@ Functionally similar to: | 1.3.6.1.2.1.2.2.1.2 1.3.6.1.2.1.2.2.1.3 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * for errorIndication, \ errorStatus, errorIndex, \ diff --git a/examples/hlapi/asyncore/manager/cmdgen/multiple-concurrent-async-queries.py b/examples/hlapi/asyncore/manager/cmdgen/multiple-concurrent-async-queries.py index 0c6e9bf..6222c3e 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/multiple-concurrent-async-queries.py +++ b/examples/hlapi/asyncore/manager/cmdgen/multiple-concurrent-async-queries.py @@ -72,14 +72,9 @@ def cbFun(snmpEngine, sendRequestHandle, errorIndication, snmpEngine = SnmpEngine() -cmdGen = AsyncCommandGenerator() - # Submit GET requests for authData, transportTarget, varNames in targets: - cmdGen.getCmd( - snmpEngine, authData, transportTarget, ContextData(), varNames, - # User-space callback function and its context - (cbFun, (authData, transportTarget)) - ) + getCmd(snmpEngine, authData, transportTarget, ContextData(), varNames, + cbFun=cbFun, cbCtx=(authData, transportTarget)) snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/hlapi/asyncore/manager/cmdgen/multiple-get-calls.py b/examples/hlapi/asyncore/manager/cmdgen/multiple-get-calls.py index b17da65..d8c63ef 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/multiple-get-calls.py +++ b/examples/hlapi/asyncore/manager/cmdgen/multiple-get-calls.py @@ -20,7 +20,7 @@ Functionally similar to: | IF-MIB::ifInOctets.1 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * queue = [ [ ObjectType(ObjectIdentity('IF-MIB', 'ifInOctets', 1)) ], [ ObjectType(ObjectIdentity('IF-MIB', 'ifOutOctets', 1)) ] ] diff --git a/examples/hlapi/asyncore/manager/cmdgen/preload-pysnmp-mibs.py b/examples/hlapi/asyncore/manager/cmdgen/preload-pysnmp-mibs.py index 080b5d1..885dbdf 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/preload-pysnmp-mibs.py +++ b/examples/hlapi/asyncore/manager/cmdgen/preload-pysnmp-mibs.py @@ -18,7 +18,7 @@ Functionally similar to: | 1.3.6 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * for errorIndication, \ errorStatus, errorIndex, \ diff --git a/examples/hlapi/asyncore/manager/cmdgen/pull-whole-mib.py b/examples/hlapi/asyncore/manager/cmdgen/pull-whole-mib.py index 479c504..10538f2 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/pull-whole-mib.py +++ b/examples/hlapi/asyncore/manager/cmdgen/pull-whole-mib.py @@ -8,7 +8,6 @@ Send a series of SNMP GETNEXT requests using the following options: * over IPv4/UDP * to an Agent at demo.snmplabs.com:161 * for all OIDs in IF-MIB -* stop when response OIDs leave the scopes of the table Functionally similar to: @@ -16,7 +15,7 @@ Functionally similar to: | demo.snmplabs.com IF-MIB:: """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * for errorIndication, \ errorStatus, errorIndex, \ @@ -24,8 +23,7 @@ for errorIndication, \ UsmUserData('usr-md5-none', 'authkey1'), UdpTransportTarget(('demo.snmplabs.com', 161)), ContextData(), - ObjectType(ObjectIdentity('IF-MIB')), - lexicographicMode=False): + ObjectType(ObjectIdentity('IF-MIB'))): if errorIndication: print(errorIndication) diff --git a/examples/hlapi/asyncore/manager/cmdgen/pull-whole-snmp-table.py b/examples/hlapi/asyncore/manager/cmdgen/pull-whole-snmp-table.py index 3c3f40b..5b8d221 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/pull-whole-snmp-table.py +++ b/examples/hlapi/asyncore/manager/cmdgen/pull-whole-snmp-table.py @@ -21,7 +21,7 @@ Functionally similar to: | IF-MIB::ifType \ """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * for errorIndication, \ errorStatus, \ diff --git a/examples/hlapi/asyncore/manager/cmdgen/query-agents-from-multuple-threads.py b/examples/hlapi/asyncore/manager/cmdgen/query-agents-from-multuple-threads.py index 442855a..34ead8b 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/query-agents-from-multuple-threads.py +++ b/examples/hlapi/asyncore/manager/cmdgen/query-agents-from-multuple-threads.py @@ -22,7 +22,7 @@ if version_info[0] == 2: else: from queue import Queue from threading import Thread -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * # List of targets in the followin format: # ( ( authData, transportTarget, varNames ), ... ) diff --git a/examples/hlapi/asyncore/manager/cmdgen/set-multiple-scalar-values.py b/examples/hlapi/asyncore/manager/cmdgen/set-multiple-scalar-values.py index b2b67eb..c3d3c5c 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/set-multiple-scalar-values.py +++ b/examples/hlapi/asyncore/manager/cmdgen/set-multiple-scalar-values.py @@ -21,7 +21,7 @@ Functionally similar to: | 1.3.6.1.2.1.1.9.1.3.1 s "new system name" """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( setCmd(SnmpEngine(), diff --git a/examples/hlapi/asyncore/manager/cmdgen/specific-v3-engine-id.py b/examples/hlapi/asyncore/manager/cmdgen/specific-v3-engine-id.py index f7db38f..72263be 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/specific-v3-engine-id.py +++ b/examples/hlapi/asyncore/manager/cmdgen/specific-v3-engine-id.py @@ -18,7 +18,7 @@ Send SNMP GET request using the following scenario and options: * for an OID in text form """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * snmpEngine = SnmpEngine() diff --git a/examples/hlapi/asyncore/manager/cmdgen/usm-md5-des.py b/examples/hlapi/asyncore/manager/cmdgen/usm-md5-des.py index cdd6ce3..1d8030d 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/usm-md5-des.py +++ b/examples/hlapi/asyncore/manager/cmdgen/usm-md5-des.py @@ -16,7 +16,7 @@ Functionally similar to: | IF-MIB::ifInOctets.1 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( getCmd(SnmpEngine(), diff --git a/examples/hlapi/asyncore/manager/cmdgen/usm-md5-none.py b/examples/hlapi/asyncore/manager/cmdgen/usm-md5-none.py index 363bddb..c38d2f3 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/usm-md5-none.py +++ b/examples/hlapi/asyncore/manager/cmdgen/usm-md5-none.py @@ -15,7 +15,7 @@ Functionally similar to: | IF-MIB::ifInOctets.1 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( getCmd(SnmpEngine(), diff --git a/examples/hlapi/asyncore/manager/cmdgen/usm-none-none.py b/examples/hlapi/asyncore/manager/cmdgen/usm-none-none.py index 5049a7c..15f570a 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/usm-none-none.py +++ b/examples/hlapi/asyncore/manager/cmdgen/usm-none-none.py @@ -16,7 +16,7 @@ Functionally similar to: | IF-MIB::ifInOctets.1 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( getCmd(SnmpEngine(), diff --git a/examples/hlapi/asyncore/manager/cmdgen/usm-sha-aes128.py b/examples/hlapi/asyncore/manager/cmdgen/usm-sha-aes128.py index 1a1c0cb..1e985f5 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/usm-sha-aes128.py +++ b/examples/hlapi/asyncore/manager/cmdgen/usm-sha-aes128.py @@ -32,7 +32,7 @@ Functionally similar to: | SNMPv2-MIB::sysDescr.0 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( getCmd(SnmpEngine(), diff --git a/examples/hlapi/asyncore/manager/cmdgen/v1-get.py b/examples/hlapi/asyncore/manager/cmdgen/v1-get.py index 7d417ef..3f03c7c 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/v1-get.py +++ b/examples/hlapi/asyncore/manager/cmdgen/v1-get.py @@ -14,7 +14,7 @@ Functionally similar to: | $ snmpget -v1 -c public demo.snmplabs.com SNMPv2-MIB::sysDescr.0 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( getCmd(SnmpEngine(), diff --git a/examples/hlapi/asyncore/manager/cmdgen/v2c-get.py b/examples/hlapi/asyncore/manager/cmdgen/v2c-get.py index a11c48c..169b6a6 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/v2c-get.py +++ b/examples/hlapi/asyncore/manager/cmdgen/v2c-get.py @@ -15,7 +15,7 @@ Functionally similar to: | 1.3.6.1.2.1.1.6.0 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * errorIndication, errorStatus, errorIndex, varBinds = next( getCmd(SnmpEngine(), diff --git a/examples/hlapi/asyncore/manager/cmdgen/v2c-getbulk.py b/examples/hlapi/asyncore/manager/cmdgen/v2c-getbulk.py index ff82017..a65bb35 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/v2c-getbulk.py +++ b/examples/hlapi/asyncore/manager/cmdgen/v2c-getbulk.py @@ -18,7 +18,7 @@ Functionally similar to: | 1.3.6.1.2.1.2.2 1.3.6.1.2.1.2.3 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * for errorIndication, \ errorStatus, errorIndex, \ diff --git a/examples/hlapi/asyncore/manager/cmdgen/waive-mib-lookup.py b/examples/hlapi/asyncore/manager/cmdgen/waive-mib-lookup.py index 595d7ad..7038d96 100644 --- a/examples/hlapi/asyncore/manager/cmdgen/waive-mib-lookup.py +++ b/examples/hlapi/asyncore/manager/cmdgen/waive-mib-lookup.py @@ -19,7 +19,7 @@ Functionally similar to: | $ snmpwalk -v2c -c public -ObentU demo.snmplabs.com 1.3.6.1.2.1 """# -from pysnmp.hlapi.asyncore import * +from pysnmp.hlapi import * for errorIndication, \ errorStatus, errorIndex, \ diff --git a/examples/hlapi/trollius/agent/ntforg/default-v1-trap.py b/examples/hlapi/trollius/agent/ntforg/default-v1-trap.py new file mode 100644 index 0000000..dbfb63e --- /dev/null +++ b/examples/hlapi/trollius/agent/ntforg/default-v1-trap.py @@ -0,0 +1,58 @@ +""" +SNMPv1 TRAP with defaults ++++++++++++++++++++++++++ + +Send SNMPv1 TRAP through unified SNMPv3 message processing framework +using the following options: + +* SNMPv1 +* with community name 'public' +* over IPv4/UDP +* send TRAP notification +* with Generic Trap #1 (warmStart) and Specific Trap 0 +* with default Uptime +* with default Agent Address +* with Enterprise OID 1.3.6.1.4.1.20408.4.1.1.2 +* include managed object information '1.3.6.1.2.1.1.1.0' = 'my system' +* use trollius I/O framework + +Functionally similar to: + +| $ snmptrap -v1 -c public demo.snmplabs.com \ +| 1.3.6.1.4.1.20408.4.1.1.2 \ +| 0.0.0.0 \ +| 1 \ +| 0 \ +| 0 +| '1.3.6.1.2.1.1.1.0' s 'my system' + +"""# +import trollius +from pysnmp.hlapi.asyncio import * + +@trollius.coroutine +def run(): + snmpEngine = SnmpEngine() + errorIndication, errorStatus, \ + errorIndex, varBinds = yield trollius.From( + sendNotification( + snmpEngine, + CommunityData('public'), # mpModel=0), + UdpTransportTarget(('localhost', 162)), + ContextData(), + 'inform', + NotificationType( + ObjectIdentity('1.3.6.1.6.3.1.1.5.2') + ).addVarBinds( + ('1.3.6.1.6.3.1.1.4.3.0', '1.3.6.1.4.1.20408.4.1.1.2'), + ('1.3.6.1.2.1.1.1.0', OctetString('my system')) + ) + ) + ) + + if errorIndication: + print(errorIndication) + + snmpEngine.transportDispatcher.closeDispatcher() + +trollius.get_event_loop().run_until_complete(run()) diff --git a/examples/hlapi/trollius/manager/cmdgen/getbulk-to-eom.py b/examples/hlapi/trollius/manager/cmdgen/getbulk-to-eom.py new file mode 100644 index 0000000..6d4cf71 --- /dev/null +++ b/examples/hlapi/trollius/manager/cmdgen/getbulk-to-eom.py @@ -0,0 +1,60 @@ +""" +Bulk walk MIB ++++++++++++++ + +Send a series of SNMP GETBULK requests using the following options: + +* with SNMPv3, user 'usr-none-none', no authentication, no privacy +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for all OIDs past SNMPv2-MIB::system +* run till end-of-mib condition is reported by Agent +* based on trollius I/O framework + +Functionally similar to: + +| $ snmpbulkwalk -v3 -lnoAuthNoPriv -u usr-none-none -Cn0 -Cr50 \ +| demo.snmplabs.com SNMPv2-MIB::system + +"""# +import trollius +from pysnmp.hlapi.asyncio import * + +@trollius.coroutine +def run(varBinds): + snmpEngine = SnmpEngine() + while True: + errorIndication, errorStatus, errorIndex, \ + varBindTable = yield trollius.From( + bulkCmd(snmpEngine, + UsmUserData('usr-none-none'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + 0, 50, + *varBinds) + ) + + if errorIndication: + print(errorIndication) + break + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for varBindRow in varBindTable: + for varBind in varBindRow: + print(' = '.join([ x.prettyPrint() for x in varBind ])) + + varBinds = varBindTable[-1] + if isEndOfMib(varBinds): + break + + snmpEngine.transportDispatcher.closeDispatcher() + +loop = trollius.get_event_loop() +loop.run_until_complete( + run([ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr'))]) +) diff --git a/examples/hlapi/trollius/manager/cmdgen/v1-get.py b/examples/hlapi/trollius/manager/cmdgen/v1-get.py new file mode 100644 index 0000000..c75be31 --- /dev/null +++ b/examples/hlapi/trollius/manager/cmdgen/v1-get.py @@ -0,0 +1,47 @@ +""" +SNMPv1 +++++++ + +Send SNMP GET request using the following options: + + * with SNMPv1, community 'public' + * over IPv4/UDP + * to an Agent at demo.snmplabs.com:161 + * for an instance of SNMPv2-MIB::sysDescr.0 MIB object + * Based on trollius I/O framework + +Functionally similar to: + +| $ snmpget -v1 -c public demo.snmplabs.com SNMPv2-MIB::sysDescr.0 + +"""# +import trollius +from pysnmp.hlapi.asyncio import * + +@trollius.coroutine +def run(): + snmpEngine = SnmpEngine() + errorIndication, errorStatus, \ + errorIndex, varBinds = yield trollius.From( + getCmd(snmpEngine, + CommunityData('public', mpModel=0), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0))) + ) + + if errorIndication: + print(errorIndication) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) + + snmpEngine.transportDispatcher.closeDispatcher() + +trollius.get_event_loop().run_until_complete(run()) diff --git a/examples/hlapi/twisted/agent/ntforg/default-v1-trap.py b/examples/hlapi/twisted/agent/ntforg/default-v1-trap.py new file mode 100644 index 0000000..c17e3cf --- /dev/null +++ b/examples/hlapi/twisted/agent/ntforg/default-v1-trap.py @@ -0,0 +1,64 @@ +""" +SNMPv1 TRAP with defaults ++++++++++++++++++++++++++ + +Send SNMPv1 TRAP through unified SNMPv3 message processing framework +using the following options: + +* SNMPv1 +* with community name 'public' +* over IPv4/UDP +* send TRAP notification +* with Generic Trap #1 (warmStart) and Specific Trap 0 +* with default Uptime +* with default Agent Address +* with Enterprise OID 1.3.6.1.4.1.20408.4.1.1.2 +* include managed object information '1.3.6.1.2.1.1.1.0' = 'my system' + +Functionally similar to: + +| $ snmptrap -v1 -c public demo.snmplabs.com \ +| 1.3.6.1.4.1.20408.4.1.1.2 \ +| 0.0.0.0 \ +| 1 \ +| 0 \ +| 0 +| '1.3.6.1.2.1.1.1.0' s 'my system' + +"""# +from twisted.internet.task import react +from pysnmp.hlapi.twisted import * + +def success((errorStatus, errorIndex, varBinds), hostname): + if errorStatus: + print('%s: %s at %s' % ( + hostname, + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) + +def failure(errorIndication, hostname): + print('%s failure: %s' % (hostname, errorIndication)) + +def run(reactor, hostname): + d = sendNotification( + SnmpEngine(), + CommunityData('public', mpModel=0), + UdpTransportTarget((hostname, 162)), + ContextData(), + 'trap', + NotificationType( + ObjectIdentity('1.3.6.1.6.3.1.1.5.2') + ).addVarBinds( + ('1.3.6.1.6.3.1.1.4.3.0', '1.3.6.1.4.1.20408.4.1.1.2'), + ('1.3.6.1.2.1.1.1.0', OctetString('my system')) + ) + ) + d.addCallback(success, hostname).addErrback(failure, hostname) + return d + +react(run, ['demo.snmplabs.com']) diff --git a/examples/hlapi/twisted/agent/ntforg/multiple-notifications-at-once.py b/examples/hlapi/twisted/agent/ntforg/multiple-notifications-at-once.py new file mode 100644 index 0000000..e0839c3 --- /dev/null +++ b/examples/hlapi/twisted/agent/ntforg/multiple-notifications-at-once.py @@ -0,0 +1,73 @@ +""" +Multiple concurrent notifications ++++++++++++++++++++++++++++++++++ + +Send multiple SNMP notifications at once using the following options: + +* SNMPv2c and SNMPv3 +* with community name 'public' or USM username usr-md5-des +* over IPv4/UDP +* send INFORM notification +* to multiple Managers +* with TRAP ID 'coldStart' specified as a MIB symbol +* include managed object information specified as var-bind objects pair + +Here we tag each SNMP-COMMUNITY-MIB::snmpCommunityTable row +with the same tag as SNMP-TARGET-MIB::snmpTargetAddrTable row +what leads to excessive tables information. + +Functionally similar to: + +| $ snmpinform -v2c -c public demo.snmplabs.com 12345 1.3.6.1.6.3.1.1.5.2 +| +| $ snmpinform -v3 -l authNoPriv -u usr-md5-none -A authkey1 \ +| demo.snmplabs.com \ +| 12345 \ +| 1.3.6.1.6.3.1.1.5.2 + +"""# +from twisted.internet.defer import DeferredList +from twisted.internet.task import react +from pysnmp.hlapi.twisted import * + +def success((errorStatus, errorIndex, varBinds), hostname): + if errorStatus: + print('%s: %s at %s' % ( + hostname, + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) + +def failure(errorIndication, hostname): + print('%s failure: %s' % (hostname, errorIndication)) + +def sendone(reactor, snmpEngine, hostname, notifyType): + d = sendNotification( + snmpEngine, + CommunityData('public', tag=hostname), + UdpTransportTarget((hostname, 162), tagList=hostname), + ContextData(), + notifyType, + NotificationType( + ObjectIdentity('1.3.6.1.6.3.1.1.5.2') + ).addVarBinds( + ('1.3.6.1.6.3.1.1.4.3.0', '1.3.6.1.4.1.20408.4.1.1.2'), + ('1.3.6.1.2.1.1.1.0', OctetString('my system')) + ) + ) + d.addCallback(success, hostname).addErrback(failure, hostname) + return d + +def sendall(reactor, destinations): + snmpEngine = SnmpEngine() + + return DeferredList( + [ sendone(reactor, snmpEngine, hostname, notifyType) + for hostname, notifyType in destinations ] + ) + +react(sendall, [[('localhost', 'trap'), ('localhost', 'inform')]]) diff --git a/examples/hlapi/twisted/manager/cmdgen/custom-timeout-and-retries.py b/examples/hlapi/twisted/manager/cmdgen/custom-timeout-and-retries.py new file mode 100644 index 0000000..fefcd68 --- /dev/null +++ b/examples/hlapi/twisted/manager/cmdgen/custom-timeout-and-retries.py @@ -0,0 +1,49 @@ +""" +SNMPv2c ++++++++ + +Send SNMP GET request using the following options: + + * with SNMPv2c, community 'public' + * over IPv4/UDP with non-default timeout and no retries + * to an Agent at demo.snmplabs.com:161 + * for two instances of SNMPv2-MIB::sysDescr.0 MIB object, + * based on Twisted I/O framework + +Functionally similar to: + +| $ snmpget -v2c -c public -r 0 -t 2 demo.snmplabs.com SNMPv2-MIB::sysDescr.0 + +"""# +from twisted.internet.task import react +from pysnmp.hlapi.twisted import * + +def success((errorStatus, errorIndex, varBinds), hostname): + if errorStatus: + print('%s: %s at %s' % ( + hostname, + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) + +def failure(errorIndication, hostname): + print('%s failure: %s' % (hostname, errorIndication)) + +def getSysDescr(reactor, hostname): + snmpEngine = SnmpEngine() + + d = getCmd(snmpEngine, + CommunityData('public'), + UdpTransportTarget((hostname, 161), timeout=2.0, retries=0), + ContextData(), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0))) + + d.addCallback(success, hostname).addErrback(failure, hostname) + + return d + +react(getSysDescr, ['demo.snmplabs.com']) diff --git a/examples/hlapi/twisted/manager/cmdgen/getbulk-to-eom.py b/examples/hlapi/twisted/manager/cmdgen/getbulk-to-eom.py new file mode 100644 index 0000000..47ede70 --- /dev/null +++ b/examples/hlapi/twisted/manager/cmdgen/getbulk-to-eom.py @@ -0,0 +1,52 @@ +""" +Bulk walk MIB ++++++++++++++ + +Send a series of SNMP GETBULK requests using the following options: + +* with SNMPv3, user 'usr-none-none', no authentication, no privacy +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for all OIDs past SNMPv2-MIB::system +* run till end-of-mib condition is reported by Agent +* based on Twisted I/O framework + +Functionally similar to: + +| $ snmpbulkwalk -v3 -lnoAuthNoPriv -u usr-none-none -Cn0 -Cr50 \ +| demo.snmplabs.com SNMPv2-MIB::system + +"""# +from twisted.internet.task import react +from pysnmp.hlapi.twisted import * + +def success((errorStatus, errorIndex, varBindTable), reactor, snmpEngine): + if errorStatus: + print('%s: %s at %s' % ( + hostname, + errorStatus.prettyPrint(), + errorIndex and varBindTable[0][int(errorIndex)-1][0] or '?' + ) + ) + else: + for varBindRow in varBindTable: + for varBind in varBindRow: + print(' = '.join([ x.prettyPrint() for x in varBind ])) + + if not isEndOfMib(varBindTable[-1]): + return getbulk(reactor, snmpEngine, *varBindTable[-1]) + +def failure(errorIndication): + print(errorIndication) + +def getbulk(reactor, snmpEngine, varBinds): + d = bulkCmd(snmpEngine, + UsmUserData('usr-none-none'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + 0, 50, + varBinds) + d.addCallback(success, reactor, snmpEngine).addErrback(failure) + return d + +react(getbulk, [SnmpEngine(), ObjectType(ObjectIdentity('SNMPv2-MIB', 'system'))]) diff --git a/examples/hlapi/twisted/manager/cmdgen/multiple-concurrent-async-queries.py b/examples/hlapi/twisted/manager/cmdgen/multiple-concurrent-async-queries.py new file mode 100644 index 0000000..5349e97 --- /dev/null +++ b/examples/hlapi/twisted/manager/cmdgen/multiple-concurrent-async-queries.py @@ -0,0 +1,56 @@ +""" +Concurrent queries +++++++++++++++++++ + +Send multiple SNMP GET requests at once using the following options: + +* with SNMPv2c, community 'public' +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for two instances of SNMPv2-MIB::sysDescr.0 and SNMPv2-MIB::sysLocation.0 + MIB object, +* based on Twisted I/O framework + +Functionally similar to: + +| $ snmpget -v2c -c public demo.snmplabs.com SNMPv2-MIB::sysDescr.0 +| $ snmpget -v2c -c public demo.snmplabs.com SNMPv2-MIB::sysLocation.0 + +"""# +from twisted.internet.defer import DeferredList +from twisted.internet.task import react +from pysnmp.hlapi.twisted import * + +def success((errorStatus, errorIndex, varBinds), hostname): + if errorStatus: + print('%s: %s at %s' % ( + hostname, + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) + +def failure(errorIndication, hostname): + print('%s failure: %s' % (hostname, errorIndication)) + +def getSystem(reactor, hostname): + snmpEngine = SnmpEngine() + + def getScalar(objectType): + d = getCmd(snmpEngine, + CommunityData('public', mpModel=0), + UdpTransportTarget((hostname, 161)), + ContextData(), + objectType) + d.addCallback(success, hostname).addErrback(failure, hostname) + return d + + return DeferredList( + [getScalar(ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0))), + getScalar(ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0)))] + ) + +react(getSystem, ['demo.snmplabs.com']) diff --git a/examples/hlapi/twisted/manager/cmdgen/pull-mibs-from-multiple-agents-at-once.py b/examples/hlapi/twisted/manager/cmdgen/pull-mibs-from-multiple-agents-at-once.py new file mode 100644 index 0000000..30d710b --- /dev/null +++ b/examples/hlapi/twisted/manager/cmdgen/pull-mibs-from-multiple-agents-at-once.py @@ -0,0 +1,61 @@ +""" +Walk multiple Agents at once +++++++++++++++++++++++++++++ + +* with SNMPv3 with user 'usr-md5-none', MD5 auth and no privacy protocols +* over IPv4/UDP +* to Agents at demo.snmplabs.com:161 and demo.snmplabs.com:1161 +* for multiple MIB subtrees and tables +* for whole MIB +* based on Twisted I/O framework + +Functionally similar to: + +| $ snmpget -v2c -c public demo.snmplabs.com:161 SNMPv2-MIB::system +| $ snmpget -v2c -c public demo.snmplabs.comL1161 SNMPv2-MIB::system + +"""# +from twisted.internet.defer import DeferredList +from twisted.internet.task import react +from pysnmp.hlapi.twisted import * + +def success((errorStatus, errorIndex, varBindTable), reactor, snmpEngine, hostname): + if errorStatus: + print('%s: %s at %s' % ( + hostname, + errorStatus.prettyPrint(), + errorIndex and varBindTable[0][int(errorIndex)-1][0] or '?' + ) + ) + else: + for varBindRow in varBindTable: + for varBind in varBindRow: + print(' = '.join([ x.prettyPrint() for x in varBind ])) + + if not isEndOfMib(varBindTable[-1]): + return getbulk(reactor, snmpEngine, hostname, *varBindTable[-1]) + +def failure(errorIndication): + print(errorIndication) + +def getbulk(reactor, snmpEngine, hostname, varBinds): + d = bulkCmd(snmpEngine, + UsmUserData('usr-md5-none', 'authkey1'), + UdpTransportTarget(hostname), + ContextData(), + 0, 25, + varBinds) + d.addCallback(success, reactor, snmpEngine, hostname).addErrback(failure) + return d + +def getall(reactor, hostnames): + snmpEngine = SnmpEngine() + + return DeferredList( + [ getbulk(reactor, snmpEngine, hostname, + ObjectType(ObjectIdentity('SNMPv2-MIB', 'system'))) + for hostname in hostnames ] + ) + +react(getall, [(('demo.snmplabs.com', 161), ('demo.snmplabs.com', 1161))]) + diff --git a/examples/hlapi/twisted/manager/cmdgen/pull-whole-mib.py b/examples/hlapi/twisted/manager/cmdgen/pull-whole-mib.py new file mode 100644 index 0000000..6df1668 --- /dev/null +++ b/examples/hlapi/twisted/manager/cmdgen/pull-whole-mib.py @@ -0,0 +1,50 @@ +""" +Walk whole MIB +++++++++++++++ + +Send a series of SNMP GETNEXT requests using the following options: + +* with SNMPv3, user 'usr-md5-none', MD5 authentication, no privacy +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for all OIDs in IF-MIB +* based on Twisted I/O framework + +Functionally similar to: + +| $ snmpwalk -v3 -lauthPriv -u usr-md5-none -A authkey1 -X privkey1 \ +| demo.snmplabs.com IF-MIB:: + +"""# +from twisted.internet.task import react +from pysnmp.hlapi.twisted import * + +def success((errorStatus, errorIndex, varBindTable), reactor, snmpEngine): + if errorStatus: + print('%s: %s at %s' % ( + hostname, + errorStatus.prettyPrint(), + errorIndex and varBindTable[0][int(errorIndex)-1][0] or '?' + ) + ) + else: + for varBindRow in varBindTable: + for varBind in varBindRow: + print(' = '.join([ x.prettyPrint() for x in varBind ])) + + if not isEndOfMib(varBindTable[-1]): + return getnext(reactor, snmpEngine, *varBindTable[-1]) + +def failure(errorIndication): + print(errorIndication) + +def getnext(reactor, snmpEngine, varBinds): + d = nextCmd(snmpEngine, + UsmUserData('usr-md5-none', 'authkey1'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + varBinds) + d.addCallback(success, reactor, snmpEngine).addErrback(failure) + return d + +react(getnext, [SnmpEngine(), ObjectType(ObjectIdentity('SNMPv2-MIB', 'system'))]) diff --git a/examples/hlapi/twisted/manager/cmdgen/v1-get.py b/examples/hlapi/twisted/manager/cmdgen/v1-get.py new file mode 100644 index 0000000..02b3690 --- /dev/null +++ b/examples/hlapi/twisted/manager/cmdgen/v1-get.py @@ -0,0 +1,47 @@ +""" +SNMPv1 +++++++ + +Send SNMP GET request using the following options: + +* with SNMPv1, community 'public' +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for two instances of SNMPv2-MIB::sysDescr.0 MIB object, +* based on Twisted I/O framework + +Functionally similar to: + +| $ snmpget -v1 -c public demo.snmplabs.com SNMPv2-MIB::sysDescr.0 + +"""# +from twisted.internet.task import react +from pysnmp.hlapi.twisted import * + +def success((errorStatus, errorIndex, varBinds), hostname): + if errorStatus: + print('%s: %s at %s' % ( + hostname, + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) + +def failure(errorIndication, hostname): + print('%s failure: %s' % (hostname, errorIndication)) + +def getSysDescr(reactor, hostname): + d = getCmd(SnmpEngine(), + CommunityData('public', mpModel=0), + UdpTransportTarget((hostname, 161)), + ContextData(), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0))) + + d.addCallback(success, hostname).addErrback(failure, hostname) + + return d + +react(getSysDescr, ['demo.snmplabs.com']) diff --git a/pysnmp/carrier/twisted/dgram/udp.py b/pysnmp/carrier/twisted/dgram/udp.py index d90d93b..82e2d2b 100644 --- a/pysnmp/carrier/twisted/dgram/udp.py +++ b/pysnmp/carrier/twisted/dgram/udp.py @@ -14,14 +14,16 @@ class UdpTwistedTransport(DgramTwistedTransport): # AbstractTwistedTransport API - def openClientMode(self, iface=('', 0)): + def openClientMode(self, iface=None): + if iface is None: + iface = ('', 0) try: self._lport = reactor.listenUDP(iface[1], self, iface[0]) except Exception: raise error.CarrierError(sys.exc_info()[1]) return self - def openServerMode(self, iface=('', 161)): + def openServerMode(self, iface): try: self._lport = reactor.listenUDP(iface[1], self, iface[0]) except Exception: diff --git a/pysnmp/entity/config.py b/pysnmp/entity/config.py index 5c1bd83..05941b8 100644 --- a/pysnmp/entity/config.py +++ b/pysnmp/entity/config.py @@ -326,6 +326,7 @@ def addTransport(snmpEngine, transportDomain, transport): ) # here we note that we have created transportDispatcher automatically snmpEngine.setUserContext(automaticTransportDispatcher=0) + snmpEngine.transportDispatcher.registerTransport( transportDomain, transport ) diff --git a/pysnmp/entity/rfc3413/asyncio/__init__.py b/pysnmp/entity/rfc3413/asyncio/__init__.py deleted file mode 100644 index ac0b2c0..0000000 --- a/pysnmp/entity/rfc3413/asyncio/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# This file is necessary to make this directory a package. diff --git a/pysnmp/entity/rfc3413/asyncio/cmdgen.py b/pysnmp/entity/rfc3413/asyncio/cmdgen.py deleted file mode 100644 index 9e8d603..0000000 --- a/pysnmp/entity/rfc3413/asyncio/cmdgen.py +++ /dev/null @@ -1,91 +0,0 @@ -# -# Copyright (C) 2014, Zebra Technologies -# Authors: Matt Hooks -# Zachary Lorusso -# Modified by Ilya Etingof -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -# THE POSSIBILITY OF SUCH DAMAGE. -# -from pysnmp.entity.rfc3413 import cmdgen -from pyasn1.compat.octets import null -from pysnmp.proto.api import v2c -try: - import asyncio -except ImportError: - import trollius as asyncio - -getNextVarBinds = cmdgen.getNextVarBinds - -class AbstractCommandGenerator: - commandGenerator = None - - def _cbFunWithFuture(self, snmpEngine, sendRequestHandle, errorIndication, - errorStatus, errorIndex, varBinds, future): - if future.cancelled(): - return - future.set_result( - (snmpEngine, errorIndication, errorStatus, errorIndex, varBinds) - ) - - def sendVarBinds(self, snmpEngine, targetName, - contextEngineId, contextName, varBinds): - future = asyncio.Future() - self.commandGenerator.sendVarBinds( - snmpEngine, - targetName, - contextEngineId, - contextName, - varBinds, - self._cbFunWithFuture, - future - ) - return future - -class GetCommandGenerator(AbstractCommandGenerator): - commandGenerator = cmdgen.GetCommandGenerator() - -class SetCommandGenerator(AbstractCommandGenerator): - commandGenerator = cmdgen.SetCommandGenerator() - -class NextCommandGenerator(AbstractCommandGenerator): - commandGenerator = cmdgen.NextCommandGenerator() - -class BulkCommandGenerator(AbstractCommandGenerator): - commandGenerator = cmdgen.BulkCommandGenerator() - - def sendVarBinds(self, snmpEngine, targetName, - contextEngineId, contextName, - nonRepeaters, maxRepetitions, varBinds): - future = asyncio.Future() - self.commandGenerator.sendVarBinds( - snmpEngine, - targetName, - contextEngineId, - contextName, - nonRepeaters, - maxRepetitions, - varBinds, - self._cbFunWithFuture, - future - ) - return future diff --git a/pysnmp/entity/rfc3413/asyncio/ntforg.py b/pysnmp/entity/rfc3413/asyncio/ntforg.py deleted file mode 100644 index 03e927d..0000000 --- a/pysnmp/entity/rfc3413/asyncio/ntforg.py +++ /dev/null @@ -1,68 +0,0 @@ -# -# Copyright (C) 2014, Zebra Technologies -# Authors: Matt Hooks -# Zachary Lorusso -# Modified by Ilya Etingof -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -# THE POSSIBILITY OF SUCH DAMAGE. -# -from pysnmp.entity.rfc3413 import ntforg -from pyasn1.compat.octets import null -try: - import asyncio -except ImportError: - import trollius as asyncio - -def _cbFunWithFuture(snmpEngine, sendRequestHandle, errorIndication, - errorStatus, errorIndex, varBinds, future): - if future.cancelled(): - return - future.set_result( - (snmpEngine, errorIndication, errorStatus, errorIndex, varBinds) - ) - -class NotificationOriginator: - def __init__(self): - self.notificationOriginator = ntforg.NotificationOriginator() - - def sendVarBinds(self, - snmpEngine, - notificationTarget, - snmpContext, - contextName, - notificationName, - instanceIndex, - additionalVarBinds=()): - future = asyncio.Future() - self.notificationOriginator.sendVarBinds( - snmpEngine, - notificationTarget, - snmpContext, - contextName, - notificationName, - instanceIndex, - additionalVarBinds, - _cbFunWithFuture, - future - ) - return future diff --git a/pysnmp/entity/rfc3413/twisted/__init__.py b/pysnmp/entity/rfc3413/twisted/__init__.py deleted file mode 100644 index 8c3066b..0000000 --- a/pysnmp/entity/rfc3413/twisted/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# This file is necessary to make this directory a package. diff --git a/pysnmp/entity/rfc3413/twisted/cmdgen.py b/pysnmp/entity/rfc3413/twisted/cmdgen.py deleted file mode 100644 index 40f5464..0000000 --- a/pysnmp/entity/rfc3413/twisted/cmdgen.py +++ /dev/null @@ -1,136 +0,0 @@ -from twisted.internet import defer -from pysnmp.entity.rfc3413 import cmdgen - -def _cbFun(snmpEngine, sendRequestHandle, errorIndication, - errorStatus, errorIndex, varBinds, cbCtx): - df = cbCtx['df'] - df.callback( - (snmpEngine, errorIndication, errorStatus, errorIndex, varBinds) - ) - # Callback function may return another deferred to indicate - # it wishes to continue MIB walk. - if isinstance(df.result, defer.Deferred): - cbCtx['df'] = df.result - return 1 # continue walking - -class AbstractCommandGenerator: - commandGenerator = None - - def sendVarBinds(self, snmpEngine, targetName, - contextEngineId, contextName, varBinds): - df = defer.Deferred() - self.commandGenerator.sendVarBinds( - snmpEngine, - targetName, - contextEngineId, - contextName, - varBinds, - _cbFun, - { 'df': df } # anonymous dictionary used for cbCtx - ) - return df - -class GetCommandGenerator(AbstractCommandGenerator): - commandGenerator = cmdgen.GetCommandGenerator() - -class SetCommandGenerator(AbstractCommandGenerator): - commandGenerator = cmdgen.SetCommandGenerator() - -class NextCommandGeneratorSingleRun(AbstractCommandGenerator): - commandGenerator = cmdgen.NextCommandGeneratorSingleRun() - -class NextCommandGenerator(AbstractCommandGenerator): - commandGenerator = cmdgen.NextCommandGenerator() - -class AbstractBulkCommandGenerator: - commandGenerator = None - - def sendVarBinds( - self, - snmpEngine, - targetName, - contextEngineId, - contextName, - nonRepeaters, - maxRepetitions, - varBinds - ): - df = defer.Deferred() - self.commandGenerator.sendVarBinds( - snmpEngine, - targetName, - contextEngineId, - contextName, - nonRepeaters, - maxRepetitions, - varBinds, - _cbFun, - { 'df': df } # anonymous dictionary used for cbCtx - ) - return df - -class BulkCommandGeneratorSingleRun(AbstractBulkCommandGenerator): - commandGenerator = cmdgen.BulkCommandGeneratorSingleRun() - -class BulkCommandGenerator(AbstractBulkCommandGenerator): - commandGenerator = cmdgen.BulkCommandGenerator() - -# -# Obsolete, compatibility interfaces. -# - -def __sendReqCbFun(response, outerDf): - ( snmpEngine, - errorIndication, - errorStatus, - errorIndex, - varBinds) = response - outerDf.callback((errorIndication, errorStatus, errorIndex, varBinds)) - # Callback function may return another deferred to indicate - # it wishes to continue MIB walk. - if isinstance(outerDf.result, defer.Deferred): - innerDf = defer.Deferred() - innerDf.addCallback(__sendReqCbFun, outerDf.result) - return innerDf - -def _sendReq(self, - snmpEngine, - targetName, - varBinds, - contextEngineId=None, - contextName=''): - innerDf = self.sendVarBinds(snmpEngine, - targetName, - contextEngineId, - contextName, - varBinds) - outerDf = defer.Deferred() - innerDf.addCallback(__sendReqCbFun, outerDf) - return outerDf - -def _sendBulkReq(self, - snmpEngine, - targetName, - nonRepeaters, - maxRepetitions, - varBinds, - contextEngineId=None, - contextName=''): - innerDf = self.sendVarBinds(snmpEngine, - targetName, - contextEngineId, - contextName, - nonRepeaters, - maxRepetitions, - varBinds) - outerDf = defer.Deferred() - innerDf.addCallback(__sendReqCbFun, outerDf) - return outerDf - -# install compatibility wrappers -GetCommandGenerator.sendReq = _sendReq -SetCommandGenerator.sendReq = _sendReq -NextCommandGenerator.sendReq = _sendReq -NextCommandGeneratorSingleRun.sendReq = _sendReq -BulkCommandGenerator.sendReq = _sendBulkReq -BulkCommandGeneratorSingleRun.sendReq = _sendBulkReq diff --git a/pysnmp/entity/rfc3413/twisted/ntforg.py b/pysnmp/entity/rfc3413/twisted/ntforg.py deleted file mode 100644 index cc796b6..0000000 --- a/pysnmp/entity/rfc3413/twisted/ntforg.py +++ /dev/null @@ -1,75 +0,0 @@ -from twisted.internet import defer -from pysnmp.entity.rfc3413 import ntforg -from pyasn1.compat.octets import null - -def __cbFun(snmpEngine, sendRequestHandle, errorIndication, - errorStatus, errorIndex, varBinds, cbCtx): - cbCtx.callback( - (snmpEngine, errorIndication, errorStatus, errorIndex, varBinds) - ) - -class NotificationOriginator: - def __init__(self, snmpContext=None): - self.snmpContext = snmpContext # this is deprecated - self.notificationOriginator = ntforg.NotificationOriginator() - - def sendVarBinds(self, - snmpEngine, - notificationTarget, - snmpContext, - contextName, - notificationName, - instanceIndex, - additionalVarBinds=()): - df = defer.Deferred() - self.notificationOriginator.sendVarBinds( - snmpEngine, - notificationTarget, - snmpContext, - contextName, - notificationName, - instanceIndex, - additionalVarBinds, - __cbFun, - df - ) - return df - -# -# Obsolete, compatibility interfaces. -# - -def __sendReqCbFun(response, outerDf): - ( snmpEngine, - errorIndication, - errorStatus, - errorIndex, - varBinds) = response - outerDf.callback((errorIndication, errorStatus, errorIndex, varBinds)) - # Callback function may return another deferred to indicate - # it wishes to continue MIB walk. - if isinstance(outerDf.result, defer.Deferred): - innerDf = defer.Deferred() - innerDf.addCallback(__sendReqCbFun, outerDf.result) - return innerDf - -def _sendNotification(self, - snmpEngine, - notificationTarget, - notificationName, - additionalVarBinds=None, - contextName=null): - - innerDf = self.sendVarBinds(snmpEngine, - notificationTarget, - self.snmpContext, - contextName, - notificationName, - None, - additionalVarBinds) - outerDf = defer.Deferred() - innerDf.addCallback(__sendReqCbFun, outerDf) - return outerDf - -# install compatibility wrappers -NotificationOriginator.sendNotification = _sendNotification diff --git a/pysnmp/hlapi/__init__.py b/pysnmp/hlapi/__init__.py index 7289fb6..3f8bee9 100644 --- a/pysnmp/hlapi/__init__.py +++ b/pysnmp/hlapi/__init__.py @@ -3,3 +3,6 @@ from pysnmp.smi.rfc1902 import * from pysnmp.hlapi.auth import * from pysnmp.hlapi.context import * from pysnmp.entity.engine import * + +# default is synchronous asyncore-based API +from pysnmp.hlapi.asyncore._sync import * diff --git a/pysnmp/hlapi/asyncio/__init__.py b/pysnmp/hlapi/asyncio/__init__.py new file mode 100644 index 0000000..9ec0fdf --- /dev/null +++ b/pysnmp/hlapi/asyncio/__init__.py @@ -0,0 +1,8 @@ +from pysnmp.proto.rfc1902 import * +from pysnmp.smi.rfc1902 import * +from pysnmp.entity.engine import * +from pysnmp.hlapi.auth import * +from pysnmp.hlapi.context import * +from pysnmp.hlapi.asyncio.transport import * +from pysnmp.hlapi.asyncio.cmdgen import * +from pysnmp.hlapi.asyncio.ntforg import * diff --git a/pysnmp/hlapi/asyncio/cmdgen.py b/pysnmp/hlapi/asyncio/cmdgen.py new file mode 100644 index 0000000..a1610bc --- /dev/null +++ b/pysnmp/hlapi/asyncio/cmdgen.py @@ -0,0 +1,479 @@ +# +# Copyright (C) 2014, Zebra Technologies +# Authors: Matt Hooks +# Zachary Lorusso +# Modified by Ilya Etingof +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. +# +from pysnmp.smi.rfc1902 import * +from pysnmp.hlapi.auth import * +from pysnmp.hlapi.context import * +from pysnmp.hlapi.lcd import * +from pysnmp.hlapi.varbinds import * +from pysnmp.hlapi.asyncio.transport import * +from pysnmp.entity.rfc3413 import cmdgen +try: + import asyncio +except ImportError: + import trollius as asyncio + +__all__ = ['getCmd', 'nextCmd', 'setCmd', 'bulkCmd', 'isEndOfMib'] + +vbProcessor = CommandGeneratorVarBinds() +lcd = CommandGeneratorLcdConfigurator() + +isEndOfMib = lambda x: not cmdgen.getNextVarBinds(x)[1] + +@asyncio.coroutine +def getCmd(snmpEngine, authData, transportTarget, contextData, + *varBinds, **options): + """Creates a generator to perform SNMP GET query. + + When itereator gets advanced by :py:mod:`asyncio` main loop, + SNMP GET request is send (:RFC:`1905#section-4.2.1`). + The iterator yields :py:class:`asyncio.Future` which gets done whenever + response arrives or error occurs. + + Parameters + ---------- + snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine` + Class instance representing SNMP engine. + + authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :py:class:`~pysnmp.hlapi.asyncio.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncio.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer address. + + contextData : :py:class:`~pysnmp.hlapi.ContextData` + Class instance representing SNMP ContextEngineId and ContextName values. + + \*varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType` + One or more class instances representing MIB variables to place + into SNMP request. + + Other Parameters + ---------------- + \*\*options : + Request options: + + * `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. Default is `True`. + + Yields + ------ + errorIndication : str + True value indicates SNMP engine error. + errorStatus : str + True value indicates SNMP PDU error. + errorIndex : int + Non-zero value refers to `varBinds[errorIndex-1]` + varBinds : tuple + A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class + instances representing MIB variables returned in SNMP response. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Examples + -------- + >>> import asyncio + >>> from pysnmp.hlapi.asyncio import * + >>> + >>> @asyncio.coroutine + ... def run(): + ... errorIndication, errorStatus, errorIndex, varBinds = yield from getCmd( + ... SnmpEngine(), + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 161)), + ... ContextData(), + ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)) + ... ) + ... print(errorIndication, errorStatus, errorIndex, varBinds) + >>> + >>> asyncio.get_event_loop().run_until_complete(run()) + (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))]) + >>> + + """ + def __cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBinds, cbCtx): + lookupMib, future = cbCtx + if future.cancelled(): + return + future.set_result( + (errorIndication, errorStatus, errorIndex, + vbProcessor.unmakeVarBinds(snmpEngine, varBinds, lookupMib)) + ) + + addrName, paramsName = lcd.configure( + snmpEngine, authData, transportTarget + ) + + future = asyncio.Future() + + cmdgen.GetCommandGenerator().sendVarBinds( + snmpEngine, + addrName, + contextData.contextEngineId, + contextData.contextName, + vbProcessor.makeVarBinds(snmpEngine, varBinds), + __cbFun, + (options.get('lookupMib', True), future) + ) + return future + +@asyncio.coroutine +def setCmd(snmpEngine, authData, transportTarget, contextData, + *varBinds, **options): + """Creates a generator to perform SNMP SET query. + + When itereator gets advanced by :py:mod:`asyncio` main loop, + SNMP SET request is send (:RFC:`1905#section-4.2.5`). + The iterator yields :py:class:`asyncio.Future` which gets done whenever + response arrives or error occurs. + + Parameters + ---------- + snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine` + Class instance representing SNMP engine. + + authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :py:class:`~pysnmp.hlapi.asyncio.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncio.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer address. + + contextData : :py:class:`~pysnmp.hlapi.ContextData` + Class instance representing SNMP ContextEngineId and ContextName values. + + \*varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType` + One or more class instances representing MIB variables to place + into SNMP request. + + Other Parameters + ---------------- + \*\*options : + Request options: + + * `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. Default is `True`. + + Yields + ------ + errorIndication : str + True value indicates SNMP engine error. + errorStatus : str + True value indicates SNMP PDU error. + errorIndex : int + Non-zero value refers to `varBinds[errorIndex-1]` + varBinds : tuple + A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class + instances representing MIB variables returned in SNMP response. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Examples + -------- + >>> import asyncio + >>> from pysnmp.hlapi.asyncio import * + >>> + >>> @asyncio.coroutine + ... def run(): + ... errorIndication, errorStatus, errorIndex, varBinds = yield from setCmd( + ... SnmpEngine(), + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 161)), + ... ContextData(), + ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0), 'Linux i386') + ... ) + ... print(errorIndication, errorStatus, errorIndex, varBinds) + >>> + >>> asyncio.get_event_loop().run_until_complete(run()) + (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('Linux i386'))]) + >>> + + """ + def __cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBinds, cbCtx): + lookupMib, future = cbCtx + if future.cancelled(): + return + future.set_result( + (errorIndication, errorStatus, errorIndex, + vbProcessor.unmakeVarBinds(snmpEngine, varBinds, lookupMib)) + ) + + addrName, paramsName = lcd.configure( + snmpEngine, authData, transportTarget + ) + + future = asyncio.Future() + + cmdgen.SetCommandGenerator().sendVarBinds( + snmpEngine, + addrName, + contextData.contextEngineId, + contextData.contextName, + vbProcessor.makeVarBinds(snmpEngine, varBinds), + __cbFun, + (options.get('lookupMib', True), future) + ) + return future + +@asyncio.coroutine +def nextCmd(snmpEngine, authData, transportTarget, contextData, + *varBinds, **options): + """Creates a generator to perform SNMP GETNEXT query. + + When itereator gets advanced by :py:mod:`asyncio` main loop, + SNMP GETNEXT request is send (:RFC:`1905#section-4.2.2`). + The iterator yields :py:class:`asyncio.Future` which gets done whenever + response arrives or error occurs. + + Parameters + ---------- + snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine` + Class instance representing SNMP engine. + + authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :py:class:`~pysnmp.hlapi.asyncio.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncio.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer address. + + contextData : :py:class:`~pysnmp.hlapi.ContextData` + Class instance representing SNMP ContextEngineId and ContextName values. + + \*varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType` + One or more class instances representing MIB variables to place + into SNMP request. + + Other Parameters + ---------------- + \*\*options : + Request options: + + * `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. Default is `True`. + + Yields + ------ + errorIndication : str + True value indicates SNMP engine error. + errorStatus : str + True value indicates SNMP PDU error. + errorIndex : int + Non-zero value refers to `varBinds[errorIndex-1]` + varBinds : tuple + A sequence of sequences (e.g. 2-D array) of + :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances + representing a table of MIB variables returned in SNMP response. + Inner sequences represent table rows and ordered exactly the same + as `varBinds` in request. Response to GETNEXT always contain + a single row. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Examples + -------- + >>> import asyncio + >>> from pysnmp.hlapi.asyncio import * + >>> + >>> @asyncio.coroutine + ... def run(): + ... errorIndication, errorStatus, errorIndex, varBinds = yield from nextCmd( + ... SnmpEngine(), + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 161)), + ... ContextData(), + ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')) + ... ) + ... print(errorIndication, errorStatus, errorIndex, varBinds) + >>> + >>> asyncio.get_event_loop().run_until_complete(run()) + (None, 0, 0, [[ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0'), DisplayString('Linux i386'))]]) + >>> + + """ + def __cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBindTable, cbCtx): + lookupMib, future = cbCtx + if future.cancelled(): + return + future.set_result( + (errorIndication, errorStatus, errorIndex, + [ vbProcessor.unmakeVarBinds(snmpEngine, varBindTableRow, lookupMib) for varBindTableRow in varBindTable ]) + ) + + addrName, paramsName = lcd.configure( + snmpEngine, authData, transportTarget + ) + + future = asyncio.Future() + + cmdgen.NextCommandGenerator().sendVarBinds( + snmpEngine, + addrName, + contextData.contextEngineId, + contextData.contextName, + vbProcessor.makeVarBinds(snmpEngine, varBinds), + __cbFun, + (options.get('lookupMib', True), future) + ) + return future + +@asyncio.coroutine +def bulkCmd(snmpEngine, authData, transportTarget, contextData, + nonRepeaters, maxRepetitions, *varBinds, **options): + """Creates a generator to perform SNMP GETBULK query. + + When itereator gets advanced by :py:mod:`asyncio` main loop, + SNMP GETBULK request is send (:RFC:`1905#section-4.2.3`). + The iterator yields :py:class:`asyncio.Future` which gets done whenever + response arrives or error occurs. + + Parameters + ---------- + snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine` + Class instance representing SNMP engine. + + authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :py:class:`~pysnmp.hlapi.asyncio.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncio.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer address. + + contextData : :py:class:`~pysnmp.hlapi.ContextData` + Class instance representing SNMP ContextEngineId and ContextName values. + + nonRepeaters : int + One MIB variable is requested in response for the first + `nonRepeaters` MIB variables in request. + + maxRepetitions : int + `maxRepetitions` MIB variables are requested in response for each + of the remaining MIB variables in the request (e.g. excluding + `nonRepeaters`). Remote SNMP engine may choose lesser value than + requested. + + \*varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType` + One or more class instances representing MIB variables to place + into SNMP request. + + Other Parameters + ---------------- + \*\*options : + Request options: + + * `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. Default is `True`. + + Yields + ------ + errorIndication : str + True value indicates SNMP engine error. + errorStatus : str + True value indicates SNMP PDU error. + errorIndex : int + Non-zero value refers to `varBinds[errorIndex-1]` + varBinds : tuple + A sequence of sequences (e.g. 2-D array) of + :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances + representing a table of MIB variables returned in SNMP response. + Inner sequences represent table rows and ordered exactly the same + as `varBinds` in request. Response to GETNEXT always contain + a single row. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Examples + -------- + >>> import asyncio + >>> from pysnmp.hlapi.asyncio import * + >>> + >>> @asyncio.coroutine + ... def run(): + ... errorIndication, errorStatus, errorIndex, varBinds = yield from nextCmd( + ... SnmpEngine(), + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 161)), + ... ContextData(), + ... 0, 2, + ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')) + ... ) + ... print(errorIndication, errorStatus, errorIndex, varBinds) + >>> + >>> asyncio.get_event_loop().run_until_complete(run()) + (None, 0, 0, [[ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m')), ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.2.0')), ObjectIdentifier('1.3.6.1.4.1.424242.1.1')]]) + >>> + + """ + def __cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBindTable, cbCtx): + lookupMib, future = cbCtx + if future.cancelled(): + return + future.set_result( + (errorIndication, errorStatus, errorIndex, + [ vbProcessor.unmakeVarBinds(snmpEngine, varBindTableRow, lookupMib) for varBindTableRow in varBindTable ]) + ) + + addrName, paramsName = lcd.configure( + snmpEngine, authData, transportTarget + ) + + future = asyncio.Future() + + cmdgen.BulkCommandGenerator().sendVarBinds( + snmpEngine, + addrName, + contextData.contextEngineId, + contextData.contextName, + nonRepeaters, + maxRepetitions, + vbProcessor.makeVarBinds(snmpEngine, varBinds), + __cbFun, + (options.get('lookupMib', True), future) + ) + return future diff --git a/pysnmp/hlapi/asyncio/ntforg.py b/pysnmp/hlapi/asyncio/ntforg.py new file mode 100644 index 0000000..5f2d10b --- /dev/null +++ b/pysnmp/hlapi/asyncio/ntforg.py @@ -0,0 +1,172 @@ +# +# Copyright (C) 2014, Zebra Technologies +# Authors: Matt Hooks +# Zachary Lorusso +# Modified by Ilya Etingof +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. +# +from pysnmp.smi.rfc1902 import * +from pysnmp.hlapi.auth import * +from pysnmp.hlapi.context import * +from pysnmp.hlapi.lcd import * +from pysnmp.hlapi.varbinds import * +from pysnmp.hlapi.asyncio.transport import * +from pysnmp.entity.rfc3413 import ntforg, context +try: + import asyncio +except ImportError: + import trollius as asyncio + +__all__ = ['sendNotification'] + +vbProcessor = NotificationOriginatorVarBinds() +lcd = NotificationOriginatorLcdConfigurator() + +@asyncio.coroutine +def sendNotification(snmpEngine, authData, transportTarget, contextData, + notifyType, varBinds, **options): + """Creates a generator to send SNMP notification. + + When itereator gets advanced by :py:mod:`asyncio` main loop, + SNMP TRAP or INFORM notification is send (:RFC:`1905#section-4.2.6`). + The iterator yields :py:class:`asyncio.Future` which gets done whenever + response arrives or error occurs. + + Parameters + ---------- + snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine` + Class instance representing SNMP engine. + + authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :py:class:`~pysnmp.hlapi.asyncio.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncio.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer address. + + contextData : :py:class:`~pysnmp.hlapi.ContextData` + Class instance representing SNMP ContextEngineId and ContextName values. + + notifyType : str + Indicates type of notification to be sent. Recognized literal + values are *trap* or *inform*. + + varBinds: tuple + Single :py:class:`~pysnmp.smi.rfc1902.NotificationType` class instance + representing a minimum sequence of MIB variables required for + particular notification type. + Alternatively, a sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` + objects could be passed instead. In the latter case it is up to + the user to ensure proper Notification PDU contents. + + Other Parameters + ---------------- + \*\*options : + Request options: + + * `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. Default is `True`. + + Yields + ------ + errorIndication : str + True value indicates SNMP engine error. + errorStatus : str + True value indicates SNMP PDU error. + errorIndex : int + Non-zero value refers to `varBinds[errorIndex-1]` + varBinds : tuple + A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class + instances representing MIB variables returned in SNMP response. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Notes + ----- + The `sendNotification` generator will be exhausted immidiately unless + an instance of :py:class:`~pysnmp.smi.rfc1902.NotificationType` class + or a sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` `varBinds` + are send back into running generator (supported since Python 2.6). + + Examples + -------- + >>> import asyncio + >>> from pysnmp.hlapi.asyncio import * + >>> + >>> @asyncio.coroutine + ... def run(): + ... errorIndication, errorStatus, errorIndex, varBinds = yield from sendNotification( + ... SnmpEngine(), + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 162)), + ... ContextData(), + ... 'trap', + ... NotificationType(ObjectIdentity('IF-MIB', 'linkDown'))) + ... print(errorIndication, errorStatus, errorIndex, varBinds) + ... + >>> asyncio.get_event_loop().run_until_complete(run()) + (None, 0, 0, []) + >>> + + """ + def __cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBinds, cbCtx): + lookupMib, future = cbCtx + if future.cancelled(): + return + future.set_result( + (errorIndication, errorStatus, errorIndex, + vbProcessor.unmakeVarBinds(snmpEngine, varBinds, lookupMib)) + ) + + notifyName = lcd.configure( + snmpEngine, authData, transportTarget, notifyType + ) + + future = asyncio.Future() + + ntforg.NotificationOriginator().sendVarBinds( + snmpEngine, + notifyName, + contextData.contextEngineId, + contextData.contextName, + vbProcessor.makeVarBinds(snmpEngine, varBinds), + __cbFun, + (options.get('lookupMib', True), future) + ) + + if notifyType == 'trap': + def __trapFun(future): + if future.cancelled(): + return + future.set_result((None, 0, 0, [])) + + loop = asyncio.get_event_loop() + loop.call_soon(__trapFun, future) + + return future diff --git a/pysnmp/hlapi/asyncio/transport.py b/pysnmp/hlapi/asyncio/transport.py new file mode 100644 index 0000000..6376039 --- /dev/null +++ b/pysnmp/hlapi/asyncio/transport.py @@ -0,0 +1,109 @@ +import socket, sys +from pysnmp.carrier.asyncio.dgram import udp, udp6 +from pysnmp.hlapi.transport import AbstractTransportTarget + +__all__ = ['Udp6TransportTarget', 'UdpTransportTarget'] + +class UdpTransportTarget(AbstractTransportTarget): + """Creates UDP/IPv4 configuration entry and initialize socket API if needed. + + This object can be used for adding new entries to Local Configuration + Datastore (LCD) managed by :py:class:`~pysnmp.hlapi.SnmpEngine` + class instance. + + See :RFC:`1906#section-3` for more information on the UDP transport mapping. + + Parameters + ---------- + transportAddr : tuple + Indicates remote address in Python :py:mod:`socket` module format + which is a tuple of FQDN, port where FQDN is a string representing + either hostname or IPv4 address in quad-dotted form, port is an + integer. + timeout : int + Response timeout in seconds. + retries : int + Maximum number of request retries, 0 retries means just a single + request. + tagList : str + Arbitrary string that contains a list of tag values which are used + to select target addresses for a particular operation + (:RFC:`3413#section-4.1.4`). + + Examples + -------- + >>> from pysnmp.hlapi.asyncio import UdpTransportTarget + >>> UdpTransportTarget(('demo.snmplabs.com', 161)) + UdpTransportTarget(('195.218.195.228', 161), timeout=1, retries=5, tagList='') + >>> + + """ + transportDomain = udp.domainName + protoTransport = udp.UdpAsyncioTransport + def _resolveAddr(self, transportAddr): + try: + return socket.getaddrinfo(transportAddr[0], + transportAddr[1], + socket.AF_INET, + socket.SOCK_DGRAM, + socket.IPPROTO_UDP)[0][4][:2] + except socket.gaierror: + raise error.PySnmpError('Bad IPv4/UDP transport address %s: %s' % ('@'.join([ str(x) for x in transportAddr ]), sys.exc_info()[1])) + +class Udp6TransportTarget(AbstractTransportTarget): + """Creates UDP/IPv6 configuration entry and initialize socket API if needed. + + This object can be used by + :py:class:`~pysnmp.hlapi.asyncio.AsyncCommandGenerator` or + :py:class:`~pysnmp.hlapi.asyncio.AsyncNotificationOriginator` + and their derevatives for adding new entries to Local Configuration + Datastore (LCD) managed by :py:class:`~pysnmp.hlapi.SnmpEngine` + class instance. + + See :RFC:`1906#section-3`, :RFC:`2851#section-4` for more information + on the UDP and IPv6 transport mapping. + + Parameters + ---------- + transportAddr : tuple + Indicates remote address in Python :py:mod:`socket` module format + which is a tuple of FQDN, port where FQDN is a string representing + either hostname or IPv6 address in one of three conventional forms + (:RFC:`1924#section-3`), port is an integer. + timeout : int + Response timeout in seconds. + retries : int + Maximum number of request retries, 0 retries means just a single + request. + tagList : str + Arbitrary string that contains a list of tag values which are used + to select target addresses for a particular operation + (:RFC:`3413#section-4.1.4`). + + Examples + -------- + >>> from pysnmp.hlapi.asyncio import Udp6TransportTarget + >>> Udp6TransportTarget(('google.com', 161)) + Udp6TransportTarget(('2a00:1450:4014:80a::100e', 161), timeout=1, retries=5, tagList='') + >>> Udp6TransportTarget(('FEDC:BA98:7654:3210:FEDC:BA98:7654:3210', 161)) + Udp6TransportTarget(('fedc:ba98:7654:3210:fedc:ba98:7654:3210', 161), timeout=1, retries=5, tagList='') + >>> Udp6TransportTarget(('1080:0:0:0:8:800:200C:417A', 161)) + Udp6TransportTarget(('1080::8:800:200c:417a', 161), timeout=1, retries=5, tagList='') + >>> Udp6TransportTarget(('::0', 161)) + Udp6TransportTarget(('::', 161), timeout=1, retries=5, tagList='') + >>> Udp6TransportTarget(('::', 161)) + Udp6TransportTarget(('::', 161), timeout=1, retries=5, tagList='') + >>> + + """ + transportDomain = udp6.domainName + protoTransport = udp6.Udp6AsyncioTransport + def _resolveAddr(self, transportAddr): + try: + return socket.getaddrinfo(transportAddr[0], + transportAddr[1], + socket.AF_INET6, + socket.SOCK_DGRAM, + socket.IPPROTO_UDP)[0][4][:2] + except socket.gaierror: + raise error.PySnmpError('Bad IPv6/UDP transport address %s: %s' % ('@'.join([ str(x) for x in transportAddr ]), sys.exc_info()[1])) diff --git a/pysnmp/hlapi/asyncore/__init__.py b/pysnmp/hlapi/asyncore/__init__.py index 9831a39..a6d2ece 100644 --- a/pysnmp/hlapi/asyncore/__init__.py +++ b/pysnmp/hlapi/asyncore/__init__.py @@ -6,10 +6,3 @@ from pysnmp.hlapi.asyncore.transport import * from pysnmp.hlapi.asyncore.cmdgen import * from pysnmp.hlapi.asyncore.ntforg import * from pysnmp.entity.engine import * - -try: - from pysnmp.hlapi.asyncore._sync.cmdgen import * - from pysnmp.hlapi.asyncore._sync.ntforg import * -except SyntaxError: - from pysnmp.hlapi.asyncore._sync.compat.cmdgen import * - from pysnmp.hlapi.asyncore._sync.compat.ntforg import * diff --git a/pysnmp/hlapi/asyncore/_sync/__init__.py b/pysnmp/hlapi/asyncore/_sync/__init__.py new file mode 100644 index 0000000..2a14fd2 --- /dev/null +++ b/pysnmp/hlapi/asyncore/_sync/__init__.py @@ -0,0 +1,13 @@ +from pysnmp.proto.rfc1902 import * +from pysnmp.smi.rfc1902 import * +from pysnmp.hlapi.auth import * +from pysnmp.hlapi.context import * +from pysnmp.hlapi.asyncore.transport import * +from pysnmp.entity.engine import * + +try: + from pysnmp.hlapi.asyncore._sync.cmdgen import * + from pysnmp.hlapi.asyncore._sync.ntforg import * +except SyntaxError: + from pysnmp.hlapi.asyncore._sync.compat.cmdgen import * + from pysnmp.hlapi.asyncore._sync.compat.ntforg import * diff --git a/pysnmp/hlapi/asyncore/_sync/cmdgen.py b/pysnmp/hlapi/asyncore/_sync/cmdgen.py index 36da95c..5cb8ab4 100644 --- a/pysnmp/hlapi/asyncore/_sync/cmdgen.py +++ b/pysnmp/hlapi/asyncore/_sync/cmdgen.py @@ -1,7 +1,7 @@ -from pysnmp.hlapi.asyncore.cmdgen import * +from pysnmp.hlapi.asyncore import cmdgen from pysnmp.hlapi.varbinds import * from pysnmp.proto.rfc1905 import endOfMibView -from pysnmp.proto.errind import * +from pysnmp.proto import errind from pyasn1.type.univ import Null __all__ = ['getCmd', 'nextCmd', 'setCmd', 'bulkCmd'] @@ -86,17 +86,15 @@ def getCmd(snmpEngine, authData, transportTarget, contextData, cbCtx = {} - cmdGen = AsyncCommandGenerator() - while True: if varBinds: - cmdGen.getCmd( + cmdgen.getCmd( snmpEngine, authData, transportTarget, contextData, varBinds, - (cbFun, cbCtx), + cbFun, cbCtx, options.get('lookupMib', True) ) @@ -196,17 +194,15 @@ def setCmd(snmpEngine, authData, transportTarget, contextData, cbCtx = {} - cmdGen = AsyncCommandGenerator() - while True: if varBinds: - cmdGen.setCmd( + cmdgen.setCmd( snmpEngine, authData, transportTarget, contextData, varBinds, - (cbFun, cbCtx), + cbFun, cbCtx, options.get('lookupMib', True) ) @@ -335,20 +331,18 @@ def nextCmd(snmpEngine, authData, transportTarget, contextData, vbProcessor = CommandGeneratorVarBinds() - cmdGen = AsyncCommandGenerator() - initialVars = [ x[0] for x in vbProcessor.makeVarBinds(snmpEngine, varBinds) ] totalRows = totalCalls = 0 while True: if varBinds: - cmdGen.nextCmd(snmpEngine, + cmdgen.nextCmd(snmpEngine, authData, transportTarget, contextData, [ (x[0], Null()) for x in varBinds ], - (cbFun, cbCtx), + cbFun, cbCtx, lookupMib) snmpEngine.transportDispatcher.runDispatcher() @@ -525,8 +519,6 @@ def bulkCmd(snmpEngine, authData, transportTarget, contextData, vbProcessor = CommandGeneratorVarBinds() - cmdGen = AsyncCommandGenerator() - initialVars = [ x[0] for x in vbProcessor.makeVarBinds(snmpEngine, varBinds) ] nullVarBinds = [ False ] * len(initialVars) @@ -537,13 +529,13 @@ def bulkCmd(snmpEngine, authData, transportTarget, contextData, if maxRows and totalRows < maxRows: maxRepetitions = min(maxRepetitions, maxRows-totalRows) - cmdGen.bulkCmd(snmpEngine, + cmdgen.bulkCmd(snmpEngine, authData, transportTarget, contextData, nonRepeaters, maxRepetitions, [ (x[0], Null()) for x in varBinds ], - (cbFun, cbCtx), + cbFun, cbCtx, lookupMib) snmpEngine.transportDispatcher.runDispatcher() diff --git a/pysnmp/hlapi/asyncore/_sync/compat/cmdgen.py b/pysnmp/hlapi/asyncore/_sync/compat/cmdgen.py index 530c376..701cb5f 100644 --- a/pysnmp/hlapi/asyncore/_sync/compat/cmdgen.py +++ b/pysnmp/hlapi/asyncore/_sync/compat/cmdgen.py @@ -1,10 +1,10 @@ # # This is a Python 2.6- version of the same file at level up # -from pysnmp.hlapi.asyncore.cmdgen import * +from pysnmp.hlapi.asyncore import cmdgen from pysnmp.hlapi.varbinds import * from pysnmp.proto.rfc1905 import endOfMibView -from pysnmp.proto.errind import * +from pysnmp.proto import errind from pyasn1.type.univ import Null __all__ = ['getCmd', 'nextCmd', 'setCmd', 'bulkCmd', 'next'] @@ -25,16 +25,14 @@ def getCmd(snmpEngine, authData, transportTarget, contextData, cbCtx = {} - cmdGen = AsyncCommandGenerator() - if varBinds: - cmdGen.getCmd( + cmdgen.getCmd( snmpEngine, authData, transportTarget, contextData, varBinds, - (cbFun, cbCtx), + cbFun, cbCtx, options.get('lookupMib', True) ) @@ -63,16 +61,14 @@ def setCmd(snmpEngine, authData, transportTarget, contextData, cbCtx = {} - cmdGen = AsyncCommandGenerator() - while True: - cmdGen.setCmd( + cmdgen.setCmd( snmpEngine, authData, transportTarget, contextData, varBinds, - (cbFun, cbCtx), + cbFun, cbCtx, options.get('lookupMib', True) ) @@ -106,19 +102,17 @@ def nextCmd(snmpEngine, authData, transportTarget, contextData, vbProcessor = CommandGeneratorVarBinds() - cmdGen = AsyncCommandGenerator() - initialVars = [ x[0] for x in vbProcessor.makeVarBinds(snmpEngine, varBinds) ] totalRows = totalCalls = 0 while True: - cmdGen.nextCmd(snmpEngine, + cmdgen.nextCmd(snmpEngine, authData, transportTarget, contextData, [ (x[0], Null()) for x in varBinds ], - (cbFun, cbCtx), + cbFun, cbCtx, lookupMib) snmpEngine.transportDispatcher.runDispatcher() @@ -183,8 +177,6 @@ def bulkCmd(snmpEngine, authData, transportTarget, contextData, vbProcessor = CommandGeneratorVarBinds() - cmdGen = AsyncCommandGenerator() - initialVars = [ x[0] for x in vbProcessor.makeVarBinds(snmpEngine, varBinds) ] nullVarBinds = [ False ] * len(initialVars) @@ -195,13 +187,13 @@ def bulkCmd(snmpEngine, authData, transportTarget, contextData, if maxRows and totalRows < maxRows: maxRepetitions = min(maxRepetitions, maxRows-totalRows) - cmdGen.bulkCmd(snmpEngine, + cmdgen.bulkCmd(snmpEngine, authData, transportTarget, contextData, nonRepeaters, maxRepetitions, [ (x[0], Null()) for x in varBinds ], - (cbFun, cbCtx), + cbFun, cbCtx, lookupMib) snmpEngine.transportDispatcher.runDispatcher() diff --git a/pysnmp/hlapi/asyncore/_sync/compat/ntforg.py b/pysnmp/hlapi/asyncore/_sync/compat/ntforg.py index 420b3b6..92b32b3 100644 --- a/pysnmp/hlapi/asyncore/_sync/compat/ntforg.py +++ b/pysnmp/hlapi/asyncore/_sync/compat/ntforg.py @@ -1,7 +1,7 @@ # # This is a Python 2.6- version of the same file at level up # -from pysnmp.hlapi.asyncore.ntforg import * +from pysnmp.hlapi.asyncore import ntforg __all__ = ['sendNotification', 'next'] @@ -25,17 +25,15 @@ def sendNotification(snmpEngine, authData, transportTarget, contextData, cbCtx = {} - ntfOrg = AsyncNotificationOriginator() - if varBinds: - ntfOrg.sendNotification( + ntforg.sendNotification( snmpEngine, authData, transportTarget, contextData, notifyType, varBinds, - (cbFun, cbCtx), + cbFun, cbCtx, options.get('lookupMib', True) ) diff --git a/pysnmp/hlapi/asyncore/_sync/ntforg.py b/pysnmp/hlapi/asyncore/_sync/ntforg.py index ac778c1..e43a974 100644 --- a/pysnmp/hlapi/asyncore/_sync/ntforg.py +++ b/pysnmp/hlapi/asyncore/_sync/ntforg.py @@ -1,4 +1,4 @@ -from pysnmp.hlapi.asyncore.ntforg import * +from pysnmp.hlapi.asyncore import ntforg __all__ = ['sendNotification'] @@ -93,18 +93,16 @@ def sendNotification(snmpEngine, authData, transportTarget, contextData, cbCtx = {} - ntfOrg = AsyncNotificationOriginator() - while True: if varBinds: - ntfOrg.sendNotification( + ntforg.sendNotification( snmpEngine, authData, transportTarget, contextData, notifyType, varBinds, - cbInfo=(cbFun, cbCtx), + cbFun, cbCtx, lookupMib=options.get('lookupMib', True) ) diff --git a/pysnmp/hlapi/asyncore/cmdgen.py b/pysnmp/hlapi/asyncore/cmdgen.py index 28c5954..b9be41b 100644 --- a/pysnmp/hlapi/asyncore/cmdgen.py +++ b/pysnmp/hlapi/asyncore/cmdgen.py @@ -10,520 +10,491 @@ from pysnmp.hlapi.asyncore.transport import * from pysnmp.proto import rfc1905, errind from pyasn1.type import univ, base -__all__ = ['AsyncCommandGenerator'] - -class AsyncCommandGenerator: - """Creates asyncore-based SNMP Command Generator object. - - This is a high-level wrapper around pure Command Generator - impementation that aims at simplyfing - :py:class:`pysnmp.hlapi.SnmpEngine`'s Local Configuration - Datastore (:RFC:`2271#section-3.4.2`) management. Typically, - users instantiate `AsyncCommandGenerator` and call its - commmand-specific methods passing them canned Security, - Transport and SNMP Context parameters along with - :py:class:`~pysnmp.smi.rfc1902.ObjectType` object carrying - MIB variables to include with SNMP request. `AsyncCommandGenerator` - will manage LCD by applying user-supplied configuratoin parameters - and running requested operation. - - See :RFC:`3413#section-3.1` for more information on SNMP - Command Generator purpose, design and supported operations. +__all__ = ['getCmd', 'nextCmd', 'setCmd', 'bulkCmd', 'isEndOfMib'] + +vbProcessor = CommandGeneratorVarBinds() +lcd = CommandGeneratorLcdConfigurator() + +isEndOfMib = lambda x: not cmdgen.getNextVarBinds(x)[1] + +def getCmd(snmpEngine, authData, transportTarget, contextData, + varBinds, cbFun=None, cbCtx=None, lookupMib=True): + """Performs SNMP GET query. + + Based on passed parameters, prepares SNMP GET packet + (:RFC:`1905#section-4.2.1`) and schedules its transmission by + I/O framework at a later point of time. + + Parameters + ---------- + snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine` + Class instance representing SNMP engine. + + authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :py:class:`~pysnmp.hlapi.asyncore.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncore.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer + address. + + contextData : :py:class:`~pysnmp.hlapi.ContextData` + Class instance representing SNMP ContextEngineId and ContextName + values. + + varBinds : tuple + A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class + instances representing MIB variables to place into SNMP request. + + Other Parameters + ---------------- + cbFun : callable + user-supplied callable that is invoked to pass SNMP response + data or error to user at a later point of time. + cbCtx : object + user-supplied object passing additional parameters to/from + `cbFun`. + lookupMib : bool + `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. + + Notes + ----- + User-supplied `cbFun` callable must have the following call + signature: + + * snmpEngine (:py:class:`~pysnmp.hlapi.SnmpEngine`): + Class instance representing SNMP engine. + * sendRequestHandle (int): Unique request identifier. Can be used + for matching multiple ongoing requests with received responses. + * errorIndication (str): True value indicates SNMP engine error. + * errorStatus (str): True value indicates SNMP PDU error. + * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]` + * varBinds (tuple): A sequence of + :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances + representing MIB variables returned in SNMP response in exactly + the same order as `varBinds` in request. + * `cbCtx` : Original user-supplied object. + + Returns + ------- + sendRequestHandle : int + Unique request identifier. Can be used for matching received + responses with ongoing requests. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Examples + -------- + >>> from pysnmp.hlapi.asyncore import * + >>> def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx): + ... print(errorIndication, errorStatus, errorIndex, varBinds) + >>> + >>> snmpEngine = SnmpEngine() + >>> getCmd(snmpEngine, + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 161)), + ... ContextData(), + ... [ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0))], + ... cbFun=cbFun) + >>> snmpEngine.transportDispatcher.runDispatcher() + (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))]) + >>> """ - vbProcessor = CommandGeneratorVarBinds() - lcd = CommandGeneratorLcdConfigurator() - - def getCmd(self, snmpEngine, authData, transportTarget, contextData, - varBinds, cbInfo, lookupMib=True): - """Performs SNMP GET query. - - Based on passed parameters, prepares SNMP GET packet - (:RFC:`1905#section-4.2.1`) and schedules its transmission by - I/O framework at a later point of time. - - Parameters - ---------- - snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine` - Class instance representing SNMP engine. - - authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData` - Class instance representing SNMP credentials. - - transportTarget : :py:class:`~pysnmp.hlapi.asyncore.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncore.Udp6TransportTarget` - Class instance representing transport type along with SNMP peer - address. - - contextData : :py:class:`~pysnmp.hlapi.ContextData` - Class instance representing SNMP ContextEngineId and ContextName - values. - - varBinds : tuple - A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class - instances representing MIB variables to place into SNMP request. - - cbInfo : tuple - - * `cbFun` - user-supplied callable that is invoked to pass - SNMP response data or error to user at a later point of time. - * `cbCtx` - user-supplied object passing additional parameters - to/from `cbFun`. Default is `None`. - - Other Parameters - ---------------- - lookupMib : bool - `lookupMib` - load MIB and resolve response MIB variables at - the cost of slightly reduced performance. Default is `True`. - - Notes - ----- - User-supplied `cbFun` callable must have the following call - signature: - - * snmpEngine (:py:class:`~pysnmp.hlapi.SnmpEngine`): - Class instance representing SNMP engine. - * sendRequestHandle (int): Unique request identifier. Can be used - for matching multiple ongoing requests with received responses. - * errorIndication (str): True value indicates SNMP engine error. - * errorStatus (str): True value indicates SNMP PDU error. - * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]` - * varBinds (tuple): A sequence of - :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances - representing MIB variables returned in SNMP response in exactly - the same order as `varBinds` in request. - * `cbCtx` : Original user-supplied object. - - Returns - ------- - sendRequestHandle : int - Unique request identifier. Can be used for matching received - responses with ongoing requests. - - Raises - ------ - PySnmpError - Or its derivative indicating that an error occurred while - performing SNMP operation. - - Examples - -------- - >>> from pysnmp.hlapi.asyncore import * - >>> def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx): - ... print(errorIndication, errorStatus, errorIndex, varBinds) - >>> - >>> snmpEngine = SnmpEngine() - >>> g = AsyncCommandGenerator() - >>> g.getCmd(snmpEngine, - ... CommunityData('public'), - ... UdpTransportTarget(('demo.snmplabs.com', 161)), - ... ContextData(), - ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), - ... (cbFun, None)) - >>> snmpEngine.transportDispatcher.runDispatcher() - (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))]) - >>> - - """ - def __cbFun(snmpEngine, sendRequestHandle, - errorIndication, errorStatus, errorIndex, - varBinds, cbCtx): - lookupMib, cbFun, cbCtx = cbCtx - return cbFun( - snmpEngine, - sendRequestHandle, - errorIndication, - errorStatus, - errorIndex, - self.vbProcessor.unmakeVarBinds( - snmpEngine, varBinds, lookupMib - ), - cbCtx - ) - - (cbFun, cbCtx) = cbInfo - addrName, paramsName = self.lcd.configure( - snmpEngine, authData, transportTarget - ) - - return cmdgen.GetCommandGenerator().sendVarBinds( + def __cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBinds, cbCtx): + lookupMib, cbFun, cbCtx = cbCtx + return cbFun( snmpEngine, - addrName, - contextData.contextEngineId, - contextData.contextName, - self.vbProcessor.makeVarBinds(snmpEngine, varBinds), - __cbFun, - (lookupMib, cbFun, cbCtx) - ) - - def setCmd(self, snmpEngine, authData, transportTarget, contextData, - varBinds, cbInfo, lookupMib=True): - """Performs SNMP SET query. - - Based on passed parameters, prepares SNMP SET packet - (:RFC:`1905#section-4.2.5`) and schedules its transmission by - I/O framework at a later point of time. - - Parameters - ---------- - snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine` - Class instance representing SNMP engine. - - authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData` - Class instance representing SNMP credentials. - - transportTarget : :py:class:`~pysnmp.hlapi.asyncore.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncore.Udp6TransportTarget` - Class instance representing transport type along with SNMP peer - address. - - contextData : :py:class:`~pysnmp.hlapi.ContextData` - Class instance representing SNMP ContextEngineId and ContextName - values. - - varBinds : tuple - A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class - instances representing MIB variables to place into SNMP request. - - cbInfo : tuple - - * `cbFun` - user-supplied callable that is invoked to pass - SNMP response data or error to user at a later point of time. - * `cbCtx` - user-supplied object passing additional parameters - to/from `cbFun`. Default is `None`. - - Other Parameters - ---------------- - lookupMib : bool - `lookupMib` - load MIB and resolve response MIB variables at - the cost of slightly reduced performance. Default is `True`. - - Notes - ----- - User-supplied `cbFun` callable must have the following call - signature: - - * snmpEngine (:py:class:`~pysnmp.hlapi.SnmpEngine`): - Class instance representing SNMP engine. - * sendRequestHandle (int): Unique request identifier. Can be used - for matching multiple ongoing requests with received responses. - * errorIndication (str): True value indicates SNMP engine error. - * errorStatus (str): True value indicates SNMP PDU error. - * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]` - * varBinds (tuple): A sequence of - :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances - representing MIB variables returned in SNMP response in exactly - the same order as `varBinds` in request. - * `cbCtx` : Original user-supplied object. - - Returns - ------- - sendRequestHandle : int - Unique request identifier. Can be used for matching received - responses with ongoing requests. - - Raises - ------ - PySnmpError - Or its derivative indicating that an error occurred while - performing SNMP operation. - - Examples - -------- - >>> from pysnmp.hlapi.asyncore import * - >>> def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx): - ... print(errorIndication, errorStatus, errorIndex, varBinds) - >>> - >>> snmpEngine = SnmpEngine() - >>> g = AsyncCommandGenerator() - >>> g.setCmd(snmpEngine, - ... CommunityData('public'), - ... UdpTransportTarget(('demo.snmplabs.com', 161)), - ... ContextData(), - ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysContact', 0), 'info@snmplabs.com'), - ... (cbFun, None)) - >>> snmpEngine.transportDispatcher.runDispatcher() - (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.4.0')), DisplayString('info@snmplabs.com'))]) - >>> - - """ - def __cbFun(snmpEngine, sendRequestHandle, - errorIndication, errorStatus, errorIndex, - varBinds, cbCtx): - lookupMib, cbFun, cbCtx = cbCtx - return cbFun( - snmpEngine, - sendRequestHandle, - errorIndication, - errorStatus, - errorIndex, - self.vbProcessor.unmakeVarBinds( - snmpEngine, varBinds, lookupMib - ), - cbCtx - ) - - (cbFun, cbCtx) = cbInfo - addrName, paramsName = self.lcd.configure( - snmpEngine, authData, transportTarget + sendRequestHandle, + errorIndication, + errorStatus, + errorIndex, + vbProcessor.unmakeVarBinds( + snmpEngine, varBinds, lookupMib + ), + cbCtx ) - return cmdgen.SetCommandGenerator().sendVarBinds( + addrName, paramsName = lcd.configure( + snmpEngine, authData, transportTarget + ) + + return cmdgen.GetCommandGenerator().sendVarBinds( + snmpEngine, + addrName, + contextData.contextEngineId, + contextData.contextName, + vbProcessor.makeVarBinds(snmpEngine, varBinds), + __cbFun, + (lookupMib, cbFun, cbCtx) + ) + +def setCmd(snmpEngine, authData, transportTarget, contextData, + varBinds, cbFun=None, cbCtx=None, lookupMib=True): + """Performs SNMP SET query. + + Based on passed parameters, prepares SNMP SET packet + (:RFC:`1905#section-4.2.5`) and schedules its transmission by + I/O framework at a later point of time. + + Parameters + ---------- + snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine` + Class instance representing SNMP engine. + + authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :py:class:`~pysnmp.hlapi.asyncore.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncore.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer + address. + + contextData : :py:class:`~pysnmp.hlapi.ContextData` + Class instance representing SNMP ContextEngineId and ContextName + values. + + varBinds : tuple + A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class + instances representing MIB variables to place into SNMP request. + + Other Parameters + ---------------- + cbFun : callable + user-supplied callable that is invoked to pass SNMP response + data or error to user at a later point of time. + cbCtx : object + user-supplied object passing additional parameters to/from + `cbFun`. + lookupMib : bool + `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. + + Notes + ----- + User-supplied `cbFun` callable must have the following call + signature: + + * snmpEngine (:py:class:`~pysnmp.hlapi.SnmpEngine`): + Class instance representing SNMP engine. + * sendRequestHandle (int): Unique request identifier. Can be used + for matching multiple ongoing requests with received responses. + * errorIndication (str): True value indicates SNMP engine error. + * errorStatus (str): True value indicates SNMP PDU error. + * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]` + * varBinds (tuple): A sequence of + :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances + representing MIB variables returned in SNMP response in exactly + the same order as `varBinds` in request. + * `cbCtx` : Original user-supplied object. + + Returns + ------- + sendRequestHandle : int + Unique request identifier. Can be used for matching received + responses with ongoing requests. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Examples + -------- + >>> from pysnmp.hlapi.asyncore import * + >>> def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx): + ... print(errorIndication, errorStatus, errorIndex, varBinds) + >>> + >>> snmpEngine = SnmpEngine() + >>> setCmd(snmpEngine, + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 161)), + ... ContextData(), + ... [ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysContact', 0), 'info@snmplabs.com')], + ... cbFun=cbFun) + >>> snmpEngine.transportDispatcher.runDispatcher() + (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.4.0')), DisplayString('info@snmplabs.com'))]) + >>> + + """ + def __cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBinds, cbCtx): + lookupMib, cbFun, cbCtx = cbCtx + return cbFun( snmpEngine, - addrName, - contextData.contextEngineId, - contextData.contextName, - self.vbProcessor.makeVarBinds(snmpEngine, varBinds), - __cbFun, - (lookupMib, cbFun, cbCtx) - ) - - def nextCmd(self, snmpEngine, authData, transportTarget, contextData, - varBinds, cbInfo, lookupMib=True): - """Performs SNMP GETNEXT query. - - Based on passed parameters, prepares SNMP GETNEXT packet - (:RFC:`1905#section-4.2.2`) and schedules its transmission by - I/O framework at a later point of time. - - Parameters - ---------- - snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine` - Class instance representing SNMP engine. - - authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData` - Class instance representing SNMP credentials. - - transportTarget : :py:class:`~pysnmp.hlapi.asyncore.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncore.Udp6TransportTarget` - Class instance representing transport type along with SNMP peer - address. - - contextData : :py:class:`~pysnmp.hlapi.ContextData` - Class instance representing SNMP ContextEngineId and ContextName - values. - - varBinds : tuple - A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class - instances representing MIB variables to place into SNMP request. - - cbInfo : tuple - - * `cbFun` - user-supplied callable that is invoked to pass - SNMP response data or error to user at a later point of time. - * `cbCtx` - user-supplied object passing additional parameters - to/from `cbFun`. Default is `None`. - - Other Parameters - ---------------- - lookupMib : bool - `lookupMib` - load MIB and resolve response MIB variables at - the cost of slightly reduced performance. Default is `True`. - - Notes - ----- - User-supplied `cbFun` callable must have the following call - signature: - - * snmpEngine (:py:class:`~pysnmp.hlapi.SnmpEngine`): - Class instance representing SNMP engine. - * sendRequestHandle (int): Unique request identifier. Can be used - for matching multiple ongoing requests with received responses. - * errorIndication (str): True value indicates SNMP engine error. - * errorStatus (str): True value indicates SNMP PDU error. - * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]` - * varBinds (tuple): A sequence of sequences (e.g. 2-D array) of - :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances - representing a table of MIB variables returned in SNMP response. - Inner sequences represent table rows and ordered exactly the same - as `varBinds` in request. Response to GETNEXT always contain a - single row. - * `cbCtx` : Original user-supplied object. - - Returns - ------- - sendRequestHandle : int - Unique request identifier. Can be used for matching received - responses with ongoing requests. - - Raises - ------ - PySnmpError - Or its derivative indicating that an error occurred while - performing SNMP operation. - - Examples - -------- - >>> from pysnmp.hlapi.asyncore import * - >>> def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx): - ... print(errorIndication, errorStatus, errorIndex, varBinds) - >>> - >>> snmpEngine = SnmpEngine() - >>> g = AsyncCommandGenerator() - >>> g.nextCmd(snmpEngine, - ... CommunityData('public'), - ... UdpTransportTarget(('demo.snmplabs.com', 161)), - ... ContextData(), - ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')), - ... (cbFun, None)) - >>> snmpEngine.transportDispatcher.runDispatcher() - (None, 0, 0, [ [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))] ]) - >>> - - """ - def __cbFun(snmpEngine, sendRequestHandle, - errorIndication, errorStatus, errorIndex, - varBindTable, cbCtx): - lookupMib, cbFun, cbCtx = cbCtx - return cbFun( - snmpEngine, - sendRequestHandle, - errorIndication, - errorStatus, - errorIndex, - [ self.vbProcessor.unmakeVarBinds(snmpEngine, varBindTableRow, lookupMib) for varBindTableRow in varBindTable ], - cbCtx - ) - - (cbFun, cbCtx) = cbInfo - addrName, paramsName = self.lcd.configure( - snmpEngine, authData, transportTarget + sendRequestHandle, + errorIndication, + errorStatus, + errorIndex, + vbProcessor.unmakeVarBinds( + snmpEngine, varBinds, lookupMib + ), + cbCtx ) - return cmdgen.NextCommandGenerator().sendVarBinds( + + addrName, paramsName = lcd.configure( + snmpEngine, authData, transportTarget + ) + + return cmdgen.SetCommandGenerator().sendVarBinds( + snmpEngine, + addrName, + contextData.contextEngineId, + contextData.contextName, + vbProcessor.makeVarBinds(snmpEngine, varBinds), + __cbFun, + (lookupMib, cbFun, cbCtx) + ) + +def nextCmd(snmpEngine, authData, transportTarget, contextData, + varBinds, cbFun=None, cbCtx=None, lookupMib=True): + """Performs SNMP GETNEXT query. + + Based on passed parameters, prepares SNMP GETNEXT packet + (:RFC:`1905#section-4.2.2`) and schedules its transmission by + I/O framework at a later point of time. + + Parameters + ---------- + snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine` + Class instance representing SNMP engine. + + authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :py:class:`~pysnmp.hlapi.asyncore.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncore.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer + address. + + contextData : :py:class:`~pysnmp.hlapi.ContextData` + Class instance representing SNMP ContextEngineId and ContextName + values. + + varBinds : tuple + A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class + instances representing MIB variables to place into SNMP request. + + Other Parameters + ---------------- + cbFun : callable + user-supplied callable that is invoked to pass SNMP response + data or error to user at a later point of time. + cbCtx : object + user-supplied object passing additional parameters to/from + `cbFun`. + lookupMib : bool + `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. + + Notes + ----- + User-supplied `cbFun` callable must have the following call + signature: + + * snmpEngine (:py:class:`~pysnmp.hlapi.SnmpEngine`): + Class instance representing SNMP engine. + * sendRequestHandle (int): Unique request identifier. Can be used + for matching multiple ongoing requests with received responses. + * errorIndication (str): True value indicates SNMP engine error. + * errorStatus (str): True value indicates SNMP PDU error. + * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]` + * varBinds (tuple): A sequence of sequences (e.g. 2-D array) of + :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances + representing a table of MIB variables returned in SNMP response. + Inner sequences represent table rows and ordered exactly the same + as `varBinds` in request. Response to GETNEXT always contain a + single row. + * `cbCtx` : Original user-supplied object. + + Returns + ------- + sendRequestHandle : int + Unique request identifier. Can be used for matching received + responses with ongoing requests. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Examples + -------- + >>> from pysnmp.hlapi.asyncore import * + >>> def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx): + ... print(errorIndication, errorStatus, errorIndex, varBinds) + >>> + >>> snmpEngine = SnmpEngine() + >>> nextCmd(snmpEngine, + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 161)), + ... ContextData(), + ... [ObjectType(ObjectIdentity('SNMPv2-MIB', 'system'))], + ... cbFun=cbFun) + >>> snmpEngine.transportDispatcher.runDispatcher() + (None, 0, 0, [ [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))] ]) + >>> + + """ + def __cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBindTable, cbCtx): + lookupMib, cbFun, cbCtx = cbCtx + return cbFun( snmpEngine, - addrName, - contextData.contextEngineId, contextData.contextName, - self.vbProcessor.makeVarBinds(snmpEngine, varBinds), - __cbFun, - (lookupMib, cbFun, cbCtx) + sendRequestHandle, + errorIndication, + errorStatus, + errorIndex, + [ vbProcessor.unmakeVarBinds(snmpEngine, varBindTableRow, lookupMib) for varBindTableRow in varBindTable ], + cbCtx ) - def bulkCmd(self, snmpEngine, authData, transportTarget, contextData, - nonRepeaters, maxRepetitions, varBinds, cbInfo, - lookupMib=True): - """Performs SNMP GETBULK query. - - Based on passed parameters, prepares SNMP GETBULK packet - (:RFC:`1905#section-4.2.3`) and schedules its transmission by - I/O framework at a later point of time. - - Parameters - ---------- - snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine` - Class instance representing SNMP engine. - - authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData` - Class instance representing SNMP credentials. - - transportTarget : :py:class:`~pysnmp.hlapi.asyncore.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncore.Udp6TransportTarget` - Class instance representing transport type along with SNMP peer - address. - - contextData : :py:class:`~pysnmp.hlapi.ContextData` - Class instance representing SNMP ContextEngineId and ContextName - values. - - nonRepeaters : int - One MIB variable is requested in response for the first - `nonRepeaters` MIB variables in request. - - maxRepetitions : int - `maxRepetitions` MIB variables are requested in response for each - of the remaining MIB variables in the request (e.g. excluding - `nonRepeaters`). Remote SNMP engine may choose lesser value than - requested. - - varBinds : tuple - A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class - instances representing MIB variables to place into SNMP request. - - cbInfo : tuple - - * `cbFun` - user-supplied callable that is invoked to pass - SNMP response data or error to user at a later point of time. - * `cbCtx` - user-supplied object passing additional parameters - to/from `cbFun`. Default is `None`. - - Other Parameters - ---------------- - lookupMib : bool - `lookupMib` - load MIB and resolve response MIB variables at - the cost of slightly reduced performance. Default is `True`. - - Notes - ----- - User-supplied `cbFun` callable must have the following call - signature: - - * snmpEngine (:py:class:`~pysnmp.hlapi.SnmpEngine`): - Class instance representing SNMP engine. - * sendRequestHandle (int): Unique request identifier. Can be used - for matching multiple ongoing requests with received responses. - * errorIndication (str): True value indicates SNMP engine error. - * errorStatus (str): True value indicates SNMP PDU error. - * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]` - * varBinds (tuple): A sequence of sequences (e.g. 2-D array) of - :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances - representing a table of MIB variables returned in SNMP response. - Inner sequences represent table rows and ordered exactly the same - as `varBinds` in request. Number of rows might be less or equal - to `maxRepetitions` value in request. - * `cbCtx` : Original user-supplied object. - - Returns - ------- - sendRequestHandle : int - Unique request identifier. Can be used for matching received - responses with ongoing requests. - - Raises - ------ - PySnmpError - Or its derivative indicating that an error occurred while - performing SNMP operation. - - Examples - -------- - >>> from pysnmp.hlapi.asyncore import * - >>> def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx): - ... print(errorIndication, errorStatus, errorIndex, varBinds) - >>> - >>> snmpEngine = SnmpEngine() - >>> g = AsyncCommandGenerator() - >>> g.bulkCmd(snmpEngine, - ... CommunityData('public'), - ... UdpTransportTarget(('demo.snmplabs.com', 161)), - ... ContextData(), - ... 0, 2, - ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')), - ... (cbFun, None)) - >>> snmpEngine.transportDispatcher.runDispatcher() - (None, 0, 0, [ [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m')), ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.2.0')), ObjectIdentifier('1.3.6.1.4.1.424242.1.1')] ]) - >>> - - """ - def __cbFun(snmpEngine, sendRequestHandle, - errorIndication, errorStatus, errorIndex, - varBindTable, cbCtx): - lookupMib, cbFun, cbCtx = cbCtx - return cbFun( - snmpEngine, - sendRequestHandle, - errorIndication, - errorStatus, - errorIndex, - [ self.vbProcessor.unmakeVarBinds(snmpEngine, varBindTableRow, lookupMib) for varBindTableRow in varBindTable ], - cbCtx - ) - - (cbFun, cbCtx) = cbInfo - addrName, paramsName = self.lcd.configure( - snmpEngine, authData, transportTarget - ) - return cmdgen.BulkCommandGenerator().sendVarBinds( + addrName, paramsName = lcd.configure( + snmpEngine, authData, transportTarget + ) + return cmdgen.NextCommandGenerator().sendVarBinds( + snmpEngine, + addrName, + contextData.contextEngineId, contextData.contextName, + vbProcessor.makeVarBinds(snmpEngine, varBinds), + __cbFun, + (lookupMib, cbFun, cbCtx) + ) + +def bulkCmd(snmpEngine, authData, transportTarget, contextData, + nonRepeaters, maxRepetitions, varBinds, + cbFun=None, cbCtx=None, lookupMib=True): + """Performs SNMP GETBULK query. + + Based on passed parameters, prepares SNMP GETBULK packet + (:RFC:`1905#section-4.2.3`) and schedules its transmission by + I/O framework at a later point of time. + + Parameters + ---------- + snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine` + Class instance representing SNMP engine. + + authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :py:class:`~pysnmp.hlapi.asyncore.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncore.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer + address. + + contextData : :py:class:`~pysnmp.hlapi.ContextData` + Class instance representing SNMP ContextEngineId and ContextName + values. + + nonRepeaters : int + One MIB variable is requested in response for the first + `nonRepeaters` MIB variables in request. + + maxRepetitions : int + `maxRepetitions` MIB variables are requested in response for each + of the remaining MIB variables in the request (e.g. excluding + `nonRepeaters`). Remote SNMP engine may choose lesser value than + requested. + + varBinds : tuple + A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class + instances representing MIB variables to place into SNMP request. + + Other Parameters + ---------------- + cbFun : callable + user-supplied callable that is invoked to pass SNMP response + data or error to user at a later point of time. + cbCtx : object + user-supplied object passing additional parameters to/from + `cbFun`. + lookupMib : bool + `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. + + Notes + ----- + User-supplied `cbFun` callable must have the following call + signature: + + * snmpEngine (:py:class:`~pysnmp.hlapi.SnmpEngine`): + Class instance representing SNMP engine. + * sendRequestHandle (int): Unique request identifier. Can be used + for matching multiple ongoing requests with received responses. + * errorIndication (str): True value indicates SNMP engine error. + * errorStatus (str): True value indicates SNMP PDU error. + * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]` + * varBinds (tuple): A sequence of sequences (e.g. 2-D array) of + :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances + representing a table of MIB variables returned in SNMP response. + Inner sequences represent table rows and ordered exactly the same + as `varBinds` in request. Number of rows might be less or equal + to `maxRepetitions` value in request. + * `cbCtx` : Original user-supplied object. + + Returns + ------- + sendRequestHandle : int + Unique request identifier. Can be used for matching received + responses with ongoing requests. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Examples + -------- + >>> from pysnmp.hlapi.asyncore import * + >>> def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx): + ... print(errorIndication, errorStatus, errorIndex, varBinds) + >>> + >>> snmpEngine = SnmpEngine() + >>> bulkCmd(snmpEngine, + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 161)), + ... ContextData(), + ... 0, 2, + ... [ObjectType(ObjectIdentity('SNMPv2-MIB', 'system'))], + ... cbFun=cbFun) + >>> snmpEngine.transportDispatcher.runDispatcher() + (None, 0, 0, [ [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m')), ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.2.0')), ObjectIdentifier('1.3.6.1.4.1.424242.1.1')] ]) + >>> + + """ + def __cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBindTable, cbCtx): + lookupMib, cbFun, cbCtx = cbCtx + return cbFun( snmpEngine, - addrName, - contextData.contextEngineId, - contextData.contextName, - nonRepeaters, maxRepetitions, - self.vbProcessor.makeVarBinds(snmpEngine, varBinds), - __cbFun, - (lookupMib, cbFun, cbCtx) + sendRequestHandle, + errorIndication, + errorStatus, + errorIndex, + [ vbProcessor.unmakeVarBinds(snmpEngine, varBindTableRow, lookupMib) for varBindTableRow in varBindTable ], + cbCtx ) + + addrName, paramsName = lcd.configure( + snmpEngine, authData, transportTarget + ) + return cmdgen.BulkCommandGenerator().sendVarBinds( + snmpEngine, + addrName, + contextData.contextEngineId, + contextData.contextName, + nonRepeaters, maxRepetitions, + vbProcessor.makeVarBinds(snmpEngine, varBinds), + __cbFun, + (lookupMib, cbFun, cbCtx) + ) diff --git a/pysnmp/hlapi/asyncore/ntforg.py b/pysnmp/hlapi/asyncore/ntforg.py index 3565a2f..e250650 100644 --- a/pysnmp/hlapi/asyncore/ntforg.py +++ b/pysnmp/hlapi/asyncore/ntforg.py @@ -6,164 +6,142 @@ from pysnmp.hlapi.context import * from pysnmp.hlapi.lcd import * from pysnmp.hlapi.varbinds import * from pysnmp.hlapi.asyncore.transport import * -from pysnmp.hlapi.asyncore import cmdgen from pysnmp import error -__all__ = ['AsyncNotificationOriginator'] - -class AsyncNotificationOriginator: - """Creates asyncore-based SNMP Notification Originator object. - - This is a high-level wrapper around pure Notification Originator - impementation that aims at simplyfing - :py:class:`pysnmp.hlapi.SnmpEngine`'s Local Configuration - Datastore (:RFC:`2271#section-3.4.2`) management. Typically, - users instantiate `AsyncNotificationOriginator` and call its - commmand-specific methods passing them canned Security, - Transport and SNMP Context parameters along with - :py:class:`~pysnmp.smi.rfc1902.NotificationType` object carrying - MIB variables to include with Notification. `AsyncNotificationOriginator` - will manage LCD by applying user-supplied configuratoin parameters - and running requested operation. - - See :RFC:`3413#section-3.2` for more information on SNMP - Notification Originator purpose, design and supported operations. +__all__ = ['sendNotification'] + +vbProcessor = NotificationOriginatorVarBinds() +lcd = NotificationOriginatorLcdConfigurator() + +def sendNotification(snmpEngine, authData, transportTarget, contextData, + notifyType, varBinds, cbFun=None, cbCtx=None, + lookupMib=False): + """Send SNMP notification. + + Based on passed parameters, prepares SNMP TRAP or INFORM + notification (:RFC:`1905#section-4.2.6`) and schedules its + transmission by I/O framework at a later point of time. + + Parameters + ---------- + snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine` + Class instance representing SNMP engine. + + authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :py:class:`~pysnmp.hlapi.asyncore.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncore.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer + address. + + contextData : :py:class:`~pysnmp.hlapi.ContextData` + Class instance representing SNMP ContextEngineId and ContextName + values. + + notifyType : str + Indicates type of notification to be sent. Recognized literal + values are *trap* or *inform*. + + varBinds: tuple + Single :py:class:`~pysnmp.smi.rfc1902.NotificationType` class + instance representing a minimum sequence of MIB variables + required for particular notification type. Alternatively, + a sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` + objects could be passed instead. In the latter case it is up to + the user to ensure proper Notification PDU contents. + + cbInfo : tuple + + * `cbFun` - user-supplied callable that is invoked to pass + SNMP response to *INFORM* notification or error to user at + a later point of time. The `cbFun` callable is never invoked + for *TRAP* notifications. + * `cbCtx` - user-supplied object passing additional parameters + to/from `cbFun`. Default is `None`. + + Other Parameters + ---------------- + cbFun : callable + user-supplied callable that is invoked to pass SNMP response + to *INFORM* notification or error to user at a later point of + time. The `cbFun` callable is never invoked for *TRAP* notifications. + cbCtx : object + user-supplied object passing additional parameters to/from + `cbFun`. + lookupMib : bool + `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. Default is `True`. + + Notes + ----- + User-supplied `cbFun` callable must have the following call + signature: + + * snmpEngine (:py:class:`~pysnmp.hlapi.SnmpEngine`): + Class instance representing SNMP engine. + * sendRequestHandle (int): Unique request identifier. Can be used + for matching multiple ongoing *INFORM* notifications with received + responses. + * errorIndication (str): True value indicates SNMP engine error. + * errorStatus (str): True value indicates SNMP PDU error. + * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]` + * varBinds (tuple): A sequence of + :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances + representing MIB variables returned in SNMP response in exactly + the same order as `varBinds` in request. + * `cbCtx` : Original user-supplied object. + + Returns + ------- + sendRequestHandle : int + Unique request identifier. Can be used for matching received + responses with ongoing *INFORM* requests. Returns `None` for + *TRAP* notifications. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Examples + -------- + >>> from pysnmp.hlapi.asyncore import * + >>> + >>> snmpEngine = SnmpEngine() + >>> sendNotification( + ... snmpEngine, + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 162)), + ... ContextData(), + ... 'trap', + ... NotificationType(ObjectIdentity('SNMPv2-MIB', 'coldStart')), + ... ) + >>> snmpEngine.transportDispatcher.runDispatcher() + >>> """ - vbProcessor = NotificationOriginatorVarBinds() - lcd = NotificationOriginatorLcdConfigurator() - - def sendNotification(self, snmpEngine, - authData, transportTarget, contextData, - notifyType, - varBinds, - cbInfo=(None, None), - lookupMib=False): - """Send SNMP notification. - - Based on passed parameters, prepares SNMP TRAP or INFORM - notification (:RFC:`1905#section-4.2.6`) and schedules its - transmission by I/O framework at a later point of time. - - Parameters - ---------- - snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine` - Class instance representing SNMP engine. - - authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData` - Class instance representing SNMP credentials. - - transportTarget : :py:class:`~pysnmp.hlapi.asyncore.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncore.Udp6TransportTarget` - Class instance representing transport type along with SNMP peer - address. - - contextData : :py:class:`~pysnmp.hlapi.ContextData` - Class instance representing SNMP ContextEngineId and ContextName - values. - - notifyType : str - Indicates type of notification to be sent. Recognized literal - values are *trap* or *inform*. - - varBinds: tuple - Single :py:class:`~pysnmp.smi.rfc1902.NotificationType` class - instance representing a minimum sequence of MIB variables - required for particular notification type. Alternatively, - a sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` - objects could be passed instead. In the latter case it is up to - the user to ensure proper Notification PDU contents. - - cbInfo : tuple - - * `cbFun` - user-supplied callable that is invoked to pass - SNMP response to *INFORM* notification or error to user at - a later point of time. The `cbFun` callable is never invoked - for *TRAP* notifications. - * `cbCtx` - user-supplied object passing additional parameters - to/from `cbFun`. Default is `None`. - - Other Parameters - ---------------- - lookupMib : bool - `lookupMib` - load MIB and resolve response MIB variables at - the cost of slightly reduced performance. Default is `True`. - - Notes - ----- - User-supplied `cbFun` callable must have the following call - signature: - - * snmpEngine (:py:class:`~pysnmp.hlapi.SnmpEngine`): - Class instance representing SNMP engine. - * sendRequestHandle (int): Unique request identifier. Can be used - for matching multiple ongoing *INFORM* notifications with received - responses. - * errorIndication (str): True value indicates SNMP engine error. - * errorStatus (str): True value indicates SNMP PDU error. - * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]` - * varBinds (tuple): A sequence of - :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances - representing MIB variables returned in SNMP response in exactly - the same order as `varBinds` in request. - * `cbCtx` : Original user-supplied object. - - Returns - ------- - sendRequestHandle : int - Unique request identifier. Can be used for matching received - responses with ongoing *INFORM* requests. Returns `None` for - *TRAP* notifications. - - Raises - ------ - PySnmpError - Or its derivative indicating that an error occurred while - performing SNMP operation. - - Examples - -------- - >>> from pysnmp.hlapi.asyncore import * - >>> - >>> snmpEngine = SnmpEngine() - >>> n = AsyncNotificationOriginator() - >>> n.sendNotification( - ... snmpEngine, - ... CommunityData('public'), - ... UdpTransportTarget(('demo.snmplabs.com', 162)), - ... ContextData(), - ... 'trap', - ... NotificationType(ObjectIdentity('SNMPv2-MIB', 'coldStart')), - ... ) - >>> snmpEngine.transportDispatcher.runDispatcher() - >>> - - """ - def __cbFun(snmpEngine, sendRequestHandle, errorIndication, - errorStatus, errorIndex, varBinds, cbCtx): - lookupMib, cbFun, cbCtx = cbCtx - return cbFun and cbFun( - snmpEngine, - sendRequestHandle, - errorIndication, - errorStatus, errorIndex, - self.vbProcessor.unmakeVarBinds( - snmpEngine, varBinds, lookupMib - ), - cbCtx - ) - - cbFun, cbCtx = cbInfo - - # Create matching transport tags if not given by user - if not transportTarget.tagList: - transportTarget.tagList = str( - hash((authData.securityName, transportTarget.transportAddr)) - ) - if isinstance(authData, CommunityData) and not authData.tag: - authData.tag = transportTarget.tagList.split()[0] - - notifyName = self.lcd.configure( - snmpEngine, authData, transportTarget, notifyType + def __cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBinds, cbCtx): + lookupMib, cbFun, cbCtx = cbCtx + return cbFun and cbFun( + snmpEngine, + sendRequestHandle, + errorIndication, + errorStatus, errorIndex, + vbProcessor.unmakeVarBinds( + snmpEngine, varBinds, lookupMib + ), + cbCtx ) - return ntforg.NotificationOriginator().sendVarBinds(snmpEngine, notifyName, contextData.contextEngineId, contextData.contextName, self.vbProcessor.makeVarBinds(snmpEngine, varBinds), __cbFun, (lookupMib, cbFun, cbCtx)) + notifyName = lcd.configure( + snmpEngine, authData, transportTarget, notifyType + ) + + return ntforg.NotificationOriginator().sendVarBinds( + snmpEngine, notifyName, + contextData.contextEngineId, contextData.contextName, + vbProcessor.makeVarBinds(snmpEngine, varBinds), + __cbFun, (lookupMib, cbFun, cbCtx) + ) diff --git a/pysnmp/hlapi/asyncore/transport.py b/pysnmp/hlapi/asyncore/transport.py index c585e0c..cadcbb5 100644 --- a/pysnmp/hlapi/asyncore/transport.py +++ b/pysnmp/hlapi/asyncore/transport.py @@ -1,50 +1,13 @@ import socket, sys from pysnmp.carrier.asyncore.dgram import udp, udp6, unix -from pysnmp import error -from pyasn1.compat.octets import null +from pysnmp.hlapi.transport import AbstractTransportTarget __all__ = ['UnixTransportTarget', 'Udp6TransportTarget', 'UdpTransportTarget'] -class _AbstractTransportTarget: - transportDomain = None - protoTransport = NotImplementedError - def __init__(self, transportAddr, timeout=1, retries=5, tagList=null): - self.transportAddr = self._resolveAddr(transportAddr) - self.timeout = timeout - self.retries = retries - self.tagList = tagList - self.iface = None - - def __repr__(self): - return '%s(%r, timeout=%r, retries=%r, tagList=%r)' % ( - self.__class__.__name__, self.transportAddr, - self.timeout, self.retries, self.tagList - ) - - def getTransportInfo(self): - return self.transportDomain, self.transportAddr - - def setLocalAddress(self, iface): - self.iface = iface - return self - - def openClientMode(self): - self.transport = self.protoTransport().openClientMode(self.iface) - return self.transport - - def verifyDispatcherCompatibility(self, snmpEngine): - if not self.protoTransport.isCompatibleWithDispatcher(snmpEngine.transportDispatcher): - raise error.PySnmpError('Transport %r is not compatible with dispatcher %r' % (self.protoTransport, snmpEngine.transportDispatcher)) - - def _resolveAddr(self, transportAddr): raise NotImplementedError() - -class UdpTransportTarget(_AbstractTransportTarget): +class UdpTransportTarget(AbstractTransportTarget): """Creates UDP/IPv4 configuration entry and initialize socket API if needed. - This object can be used by - :py:class:`~pysnmp.hlapi.asyncore.AsyncCommandGenerator` or - :py:class:`~pysnmp.hlapi.asyncore.AsyncNotificationOriginator` - and their derevatives for adding new entries to Local Configuration + This object can be used for adding new entries to Local Configuration Datastore (LCD) managed by :py:class:`~pysnmp.hlapi.SnmpEngine` class instance. @@ -87,13 +50,10 @@ class UdpTransportTarget(_AbstractTransportTarget): except socket.gaierror: raise error.PySnmpError('Bad IPv4/UDP transport address %s: %s' % ('@'.join([ str(x) for x in transportAddr ]), sys.exc_info()[1])) -class Udp6TransportTarget(_AbstractTransportTarget): +class Udp6TransportTarget(AbstractTransportTarget): """Creates UDP/IPv6 configuration entry and initialize socket API if needed. - This object can be used by - :py:class:`~pysnmp.hlapi.asyncore.AsyncCommandGenerator` or - :py:class:`~pysnmp.hlapi.asyncore.AsyncNotificationOriginator` - and their derevatives for adding new entries to Local Configuration + This object can be used for adding new entries to Local Configuration Datastore (LCD) managed by :py:class:`~pysnmp.hlapi.SnmpEngine` class instance. @@ -145,6 +105,6 @@ class Udp6TransportTarget(_AbstractTransportTarget): except socket.gaierror: raise error.PySnmpError('Bad IPv6/UDP transport address %s: %s' % ('@'.join([ str(x) for x in transportAddr ]), sys.exc_info()[1])) -class UnixTransportTarget(_AbstractTransportTarget): +class UnixTransportTarget(AbstractTransportTarget): transportDomain = unix.domainName protoTransport = unix.UnixSocketTransport diff --git a/pysnmp/hlapi/lcd.py b/pysnmp/hlapi/lcd.py index 2709ed3..2b62a11 100644 --- a/pysnmp/hlapi/lcd.py +++ b/pysnmp/hlapi/lcd.py @@ -183,6 +183,15 @@ class NotificationOriginatorLcdConfigurator(AbstractLcdConfigurator): _cmdGenLcdCfg = CommandGeneratorLcdConfigurator() def configure(self, snmpEngine, authData, transportTarget, notifyType): cache = self._getCache(snmpEngine) + + # Create matching transport tags if not given by user. Not good! + if not transportTarget.tagList: + transportTarget.tagList = str( + hash((authData.securityName, transportTarget.transportAddr)) + ) + if isinstance(authData, CommunityData) and not authData.tag: + authData.tag = transportTarget.tagList.split()[0] + addrName, paramsName = self._cmdGenLcdCfg.configure(snmpEngine, authData, transportTarget) tagList = transportTarget.tagList.split() if not tagList: diff --git a/pysnmp/hlapi/transport.py b/pysnmp/hlapi/transport.py new file mode 100644 index 0000000..c836a03 --- /dev/null +++ b/pysnmp/hlapi/transport.py @@ -0,0 +1,37 @@ +from pyasn1.compat.octets import null +from pysnmp import error + +__all__ = [] + +class AbstractTransportTarget: + transportDomain = None + protoTransport = NotImplementedError + def __init__(self, transportAddr, timeout=1, retries=5, tagList=null): + self.transportAddr = self._resolveAddr(transportAddr) + self.timeout = timeout + self.retries = retries + self.tagList = tagList + self.iface = None + + def __repr__(self): + return '%s(%r, timeout=%r, retries=%r, tagList=%r)' % ( + self.__class__.__name__, self.transportAddr, + self.timeout, self.retries, self.tagList + ) + + def getTransportInfo(self): + return self.transportDomain, self.transportAddr + + def setLocalAddress(self, iface): + self.iface = iface + return self + + def openClientMode(self): + self.transport = self.protoTransport().openClientMode(self.iface) + return self.transport + + def verifyDispatcherCompatibility(self, snmpEngine): + if not self.protoTransport.isCompatibleWithDispatcher(snmpEngine.transportDispatcher): + raise error.PySnmpError('Transport %r is not compatible with dispatcher %r' % (self.protoTransport, snmpEngine.transportDispatcher)) + + def _resolveAddr(self, transportAddr): raise NotImplementedError() diff --git a/pysnmp/hlapi/twisted/__init__.py b/pysnmp/hlapi/twisted/__init__.py new file mode 100644 index 0000000..4e3e129 --- /dev/null +++ b/pysnmp/hlapi/twisted/__init__.py @@ -0,0 +1,8 @@ +from pysnmp.proto.rfc1902 import * +from pysnmp.smi.rfc1902 import * +from pysnmp.entity.engine import * +from pysnmp.hlapi.auth import * +from pysnmp.hlapi.context import * +from pysnmp.hlapi.twisted.transport import * +from pysnmp.hlapi.twisted.cmdgen import * +from pysnmp.hlapi.twisted.ntforg import * diff --git a/pysnmp/hlapi/twisted/cmdgen.py b/pysnmp/hlapi/twisted/cmdgen.py new file mode 100644 index 0000000..7f58175 --- /dev/null +++ b/pysnmp/hlapi/twisted/cmdgen.py @@ -0,0 +1,502 @@ +from pysnmp.smi.rfc1902 import * +from pysnmp.hlapi.auth import * +from pysnmp.hlapi.context import * +from pysnmp.hlapi.lcd import * +from pysnmp.hlapi.varbinds import * +from pysnmp.hlapi.twisted.transport import * +from pysnmp.entity.rfc3413 import cmdgen +from pysnmp.error import PySnmpError +from twisted.internet.defer import Deferred +from twisted.python.failure import Failure + +__all__ = ['getCmd', 'nextCmd', 'setCmd', 'bulkCmd', 'isEndOfMib'] + +vbProcessor = CommandGeneratorVarBinds() +lcd = CommandGeneratorLcdConfigurator() + +isEndOfMib = lambda x: not cmdgen.getNextVarBinds(x)[1] + +def getCmd(snmpEngine, authData, transportTarget, contextData, + *varBinds, **options): + """Performs SNMP GET query. + + Based on passed parameters, prepares SNMP GET packet + (:RFC:`1905#section-4.2.1`) and schedules its transmission by + :mod:`twisted` I/O framework at a later point of time. + + Parameters + ---------- + snmpEngine : :class:`~pysnmp.hlapi.SnmpEngine` + Class instance representing SNMP engine. + + authData : :class:`~pysnmp.hlapi.CommunityData` or :class:`~pysnmp.hlapi.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :class:`~pysnmp.hlapi.twisted.UdpTransportTarget` or :class:`~pysnmp.hlapi.twisted.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer address. + + contextData : :class:`~pysnmp.hlapi.ContextData` + Class instance representing SNMP ContextEngineId and ContextName values. + + \*varBinds : :class:`~pysnmp.smi.rfc1902.ObjectType` + One or more class instances representing MIB variables to place + into SNMP request. + + Other Parameters + ---------------- + \*\*options : + Request options: + + * `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. Default is `True`. + + Returns + ------- + deferred : :class:`~twisted.internet.defer.Deferred` + Twisted Deferred object representing work-in-progress. User + is expected to attach his own `success` and `error` callback + functions to the Deferred object though + :meth:`~twisted.internet.defer.Deferred.addCallbacks` method. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Notes + ----- + User `success` callback is called with the following tuple as + its first argument: + + * errorStatus (str) : True value indicates SNMP PDU error. + * errorIndex (int) : Non-zero value refers to `varBinds[errorIndex-1]` + * varBinds (tuple) : A sequence of + :class:`~pysnmp.smi.rfc1902.ObjectType` class instances representing + MIB variables returned in SNMP response. + + User `error` callback is called with `errorIndication` object wrapped + in :class:`~twisted.python.failure.Failure` object. + + Examples + -------- + >>> from twisted.internet.task import react + >>> from pysnmp.hlapi.twisted import * + >>> + >>> def success((errorStatus, errorIndex, varBinds)): + ... print(errorStatus, errorIndex, varBind) + ... + >>> def failure(errorIndication): + ... print(errorIndication) + ... + >>> def run(reactor): + ... d = getCmd(SnmpEngine(), + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 161)), + ... ContextData(), + ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0))) + ... d.addCallback(success).addErrback(failure) + ... return d + ... + >>> react(run) + (0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))]) + >>> + + """ + def __cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBinds, cbCtx): + lookupMib, deferred = cbCtx + if errorIndication: + deferred.errback(Failure(errorIndication)) + else: + deferred.callback( + (errorStatus, errorIndex, + vbProcessor.unmakeVarBinds(snmpEngine, varBinds, lookupMib)) + ) + + addrName, paramsName = lcd.configure( + snmpEngine, authData, transportTarget + ) + + deferred = Deferred() + + cmdgen.GetCommandGenerator().sendVarBinds( + snmpEngine, + addrName, + contextData.contextEngineId, + contextData.contextName, + vbProcessor.makeVarBinds(snmpEngine, varBinds), + __cbFun, + (options.get('lookupMib', True), deferred) + ) + return deferred + +def setCmd(snmpEngine, authData, transportTarget, contextData, + *varBinds, **options): + """Performs SNMP SET query. + + Based on passed parameters, prepares SNMP SET packet + (:RFC:`1905#section-4.2.5`) and schedules its transmission by + :mod:`twisted` I/O framework at a later point of time. + + Parameters + ---------- + snmpEngine : :class:`~pysnmp.hlapi.SnmpEngine` + Class instance representing SNMP engine. + + authData : :class:`~pysnmp.hlapi.CommunityData` or :class:`~pysnmp.hlapi.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :class:`~pysnmp.hlapi.twisted.UdpTransportTarget` or :class:`~pysnmp.hlapi.twisted.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer address. + + contextData : :class:`~pysnmp.hlapi.ContextData` + Class instance representing SNMP ContextEngineId and ContextName values. + + \*varBinds : :class:`~pysnmp.smi.rfc1902.ObjectType` + One or more class instances representing MIB variables to place + into SNMP request. + + Other Parameters + ---------------- + \*\*options : + Request options: + + * `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. Default is `True`. + + Returns + ------- + deferred : :class:`~twisted.internet.defer.Deferred` + Twisted Deferred object representing work-in-progress. User + is expected to attach his own `success` and `error` callback + functions to the Deferred object though + :meth:`~twisted.internet.defer.Deferred.addCallbacks` method. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Notes + ----- + User `success` callback is called with the following tuple as + its first argument: + + * errorStatus (str) : True value indicates SNMP PDU error. + * errorIndex (int) : Non-zero value refers to `varBinds[errorIndex-1]` + * varBinds (tuple) : A sequence of + :class:`~pysnmp.smi.rfc1902.ObjectType` class instances representing + MIB variables returned in SNMP response. + + User `error` callback is called with `errorIndication` object wrapped + in :class:`~twisted.python.failure.Failure` object. + + Examples + -------- + >>> from twisted.internet.task import react + >>> from pysnmp.hlapi.twisted import * + >>> + >>> def success((errorStatus, errorIndex, varBinds)): + ... print(errorStatus, errorIndex, varBind) + ... + >>> def failure(errorIndication): + ... print(errorIndication) + ... + >>> def run(reactor): + ... d = setCmd(SnmpEngine(), + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 161)), + ... ContextData(), + ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0), 'Linux i386') + ... d.addCallback(success).addErrback(failure) + ... return d + ... + >>> react(run) + (0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('Linux i386'))]) + >>> + + """ + def __cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBinds, cbCtx): + lookupMib, deferred = cbCtx + if errorIndication: + deferred.errback(Failure(errorIndication)) + else: + deferred.callback( + (errorStatus, errorIndex, + vbProcessor.unmakeVarBinds(snmpEngine, varBinds, lookupMib)) + ) + + addrName, paramsName = lcd.configure( + snmpEngine, authData, transportTarget + ) + + deferred = Deferred() + + cmdgen.SetCommandGenerator().sendVarBinds( + snmpEngine, + addrName, + contextData.contextEngineId, + contextData.contextName, + vbProcessor.makeVarBinds(snmpEngine, varBinds), + __cbFun, + (options.get('lookupMib', True), deferred) + ) + return deferred + +def nextCmd(snmpEngine, authData, transportTarget, contextData, + *varBinds, **options): + """Performs SNMP GETNEXT query. + + Based on passed parameters, prepares SNMP GETNEXT packet + (:RFC:`1905#section-4.2.2`) and schedules its transmission by + :mod:`twisted` I/O framework at a later point of time. + + Parameters + ---------- + snmpEngine : :class:`~pysnmp.hlapi.SnmpEngine` + Class instance representing SNMP engine. + + authData : :class:`~pysnmp.hlapi.CommunityData` or :class:`~pysnmp.hlapi.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :class:`~pysnmp.hlapi.twisted.UdpTransportTarget` or :class:`~pysnmp.hlapi.twisted.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer address. + + contextData : :class:`~pysnmp.hlapi.ContextData` + Class instance representing SNMP ContextEngineId and ContextName values. + + \*varBinds : :class:`~pysnmp.smi.rfc1902.ObjectType` + One or more class instances representing MIB variables to place + into SNMP request. + + Other Parameters + ---------------- + \*\*options : + Request options: + + * `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. Default is `True`. + + Returns + ------- + deferred : :class:`~twisted.internet.defer.Deferred` + Twisted Deferred object representing work-in-progress. User + is expected to attach his own `success` and `error` callback + functions to the Deferred object though + :meth:`~twisted.internet.defer.Deferred.addCallbacks` method. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Notes + ----- + User `success` callback is called with the following tuple as + its first argument: + + * errorStatus (str) : True value indicates SNMP PDU error. + * errorIndex (int) : Non-zero value refers to `varBinds[errorIndex-1]` + * varBinds (tuple) : + A sequence of sequences (e.g. 2-D array) of + :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances + representing a table of MIB variables returned in SNMP response. + Inner sequences represent table rows and ordered exactly the same + as `varBinds` in request. Response to GETNEXT always contain + a single row. + + User `error` callback is called with `errorIndication` object wrapped + in :class:`~twisted.python.failure.Failure` object. + + Examples + -------- + >>> from twisted.internet.task import react + >>> from pysnmp.hlapi.twisted import * + >>> + >>> def success((errorStatus, errorIndex, varBindTable)): + ... print(errorStatus, errorIndex, varBindTable) + ... + >>> def failure(errorIndication): + ... print(errorIndication) + ... + >>> def run(reactor): + ... d = nextCmd(SnmpEngine(), + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 161)), + ... ContextData(), + ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')) + ... d.addCallback(success).addErrback(failure) + ... return d + ... + >>> react(run) + (0, 0, [[ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))]]) + >>> + + """ + def __cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBindTable, cbCtx): + lookupMib, deferred = cbCtx + if errorIndication: + deferred.errback(Failure(errorIndication)) + else: + deferred.callback( + (errorStatus, errorIndex, + [ vbProcessor.unmakeVarBinds(snmpEngine, varBindTableRow, lookupMib) for varBindTableRow in varBindTable ]) + ) + + addrName, paramsName = lcd.configure( + snmpEngine, authData, transportTarget + ) + + deferred = Deferred() + + cmdgen.NextCommandGenerator().sendVarBinds( + snmpEngine, + addrName, + contextData.contextEngineId, + contextData.contextName, + vbProcessor.makeVarBinds(snmpEngine, varBinds), + __cbFun, + (options.get('lookupMib', True), deferred) + ) + return deferred + +def bulkCmd(snmpEngine, authData, transportTarget, contextData, + nonRepeaters, maxRepetitions, *varBinds, **options): + """Performs SNMP GETBULK query. + + Based on passed parameters, prepares SNMP GETNEXT packet + (:RFC:`1905#section-4.2.3`) and schedules its transmission by + :mod:`twisted` I/O framework at a later point of time. + + Parameters + ---------- + snmpEngine : :class:`~pysnmp.hlapi.SnmpEngine` + Class instance representing SNMP engine. + + authData : :class:`~pysnmp.hlapi.CommunityData` or :class:`~pysnmp.hlapi.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :class:`~pysnmp.hlapi.twisted.UdpTransportTarget` or :class:`~pysnmp.hlapi.twisted.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer address. + + contextData : :class:`~pysnmp.hlapi.ContextData` + Class instance representing SNMP ContextEngineId and ContextName values. + + nonRepeaters : int + One MIB variable is requested in response for the first + `nonRepeaters` MIB variables in request. + + maxRepetitions : int + `maxRepetitions` MIB variables are requested in response for each + of the remaining MIB variables in the request (e.g. excluding + `nonRepeaters`). Remote SNMP engine may choose lesser value than + requested. + + \*varBinds : :class:`~pysnmp.smi.rfc1902.ObjectType` + One or more class instances representing MIB variables to place + into SNMP request. + + Other Parameters + ---------------- + \*\*options : + Request options: + + * `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. Default is `True`. + + Returns + ------- + deferred : :class:`~twisted.internet.defer.Deferred` + Twisted Deferred object representing work-in-progress. User + is expected to attach his own `success` and `error` callback + functions to the Deferred object though + :meth:`~twisted.internet.defer.Deferred.addCallbacks` method. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Notes + ----- + User `success` callback is called with the following tuple as + its first argument: + + * errorStatus (str) : True value indicates SNMP PDU error. + * errorIndex (int) : Non-zero value refers to `varBinds[errorIndex-1]` + * varBinds (tuple) : + A sequence of sequences (e.g. 2-D array) of + :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances + representing a table of MIB variables returned in SNMP response. + Inner sequences represent table rows and ordered exactly the same + as `varBinds` in request. Number of rows might be less or equal + to `maxRepetitions` value in request. + + User `error` callback is called with `errorIndication` object wrapped + in :class:`~twisted.python.failure.Failure` object. + + Examples + -------- + >>> from twisted.internet.task import react + >>> from pysnmp.hlapi.twisted import * + >>> + >>> def success((errorStatus, errorIndex, varBindTable)): + ... print(errorStatus, errorIndex, varBindTable) + ... + >>> def failure(errorIndication): + ... print(errorIndication) + ... + >>> def run(reactor): + ... d = bulkCmd(SnmpEngine(), + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 161)), + ... ContextData(), + ... 0, 2, + ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')) + ... d.addCallback(success).addErrback(failure) + ... return d + ... + >>> react(run) + (0, 0, [[ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m')), ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.2.0')), ObjectIdentifier('1.3.6.1.4.1.424242.1.1')]]) + >>> + + """ + def __cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBindTable, cbCtx): + lookupMib, deferred = cbCtx + if errorIndication: + deferred.errback(Failure(errorIndication)) + else: + deferred.callback( + (errorStatus, errorIndex, + [ vbProcessor.unmakeVarBinds(snmpEngine, varBindTableRow, lookupMib) for varBindTableRow in varBindTable ]) + ) + + addrName, paramsName = lcd.configure( + snmpEngine, authData, transportTarget + ) + + deferred = Deferred() + + cmdgen.BulkCommandGenerator().sendVarBinds( + snmpEngine, + addrName, + contextData.contextEngineId, + contextData.contextName, + nonRepeaters, + maxRepetitions, + vbProcessor.makeVarBinds(snmpEngine, varBinds), + __cbFun, + (options.get('lookupMib', True), deferred) + ) + return deferred diff --git a/pysnmp/hlapi/twisted/ntforg.py b/pysnmp/hlapi/twisted/ntforg.py new file mode 100644 index 0000000..ac92845 --- /dev/null +++ b/pysnmp/hlapi/twisted/ntforg.py @@ -0,0 +1,147 @@ +from pysnmp.smi.rfc1902 import * +from pysnmp.hlapi.auth import * +from pysnmp.hlapi.context import * +from pysnmp.hlapi.lcd import * +from pysnmp.hlapi.varbinds import * +from pysnmp.hlapi.twisted.transport import * +from pysnmp.entity.rfc3413 import ntforg, context +from twisted.internet import reactor +from twisted.internet.defer import Deferred +from twisted.python.failure import Failure + +__all__ = ['sendNotification'] + +vbProcessor = NotificationOriginatorVarBinds() +lcd = NotificationOriginatorLcdConfigurator() + +def sendNotification(snmpEngine, authData, transportTarget, contextData, + notifyType, varBinds, **options): + """Sends SNMP notification. + + Based on passed parameters, prepares SNMP TRAP or INFORM message + (:RFC:`1905#section-4.2.6`) and schedules its transmission by + :mod:`twisted` I/O framework at a later point of time. + + Parameters + ---------- + snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine` + Class instance representing SNMP engine. + + authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :py:class:`~pysnmp.hlapi.twisted.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.twisted.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer address. + + contextData : :py:class:`~pysnmp.hlapi.ContextData` + Class instance representing SNMP ContextEngineId and ContextName values. + + notifyType : str + Indicates type of notification to be sent. Recognized literal + values are *trap* or *inform*. + + varBinds: tuple + Single :py:class:`~pysnmp.smi.rfc1902.NotificationType` class instance + representing a minimum sequence of MIB variables required for + particular notification type. + Alternatively, a sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` + objects could be passed instead. In the latter case it is up to + the user to ensure proper Notification PDU contents. + + Other Parameters + ---------------- + \*\*options : + Request options: + + * `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. Default is `True`. + + Returns + ------- + deferred : :class:`~twisted.internet.defer.Deferred` + Twisted Deferred object representing work-in-progress. User + is expected to attach his own `success` and `error` callback + functions to the Deferred object though + :meth:`~twisted.internet.defer.Deferred.addCallbacks` method. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Notes + ----- + User `success` callback is called with the following tuple as + its first argument: + + * errorStatus (str) : True value indicates SNMP PDU error. + * errorIndex (int) : Non-zero value refers to `varBinds[errorIndex-1]` + * varBinds (tuple) : A sequence of + :class:`~pysnmp.smi.rfc1902.ObjectType` class instances representing + MIB variables returned in SNMP response. + + User `error` callback is called with `errorIndication` object wrapped + in :class:`~twisted.python.failure.Failure` object. + + Examples + -------- + >>> from twisted.internet.task import react + >>> from pysnmp.hlapi.twisted import * + >>> + >>> def success((errorStatus, errorIndex, varBinds)): + ... print(errorStatus, errorIndex, varBind) + ... + >>> def failure(errorIndication): + ... print(errorIndication) + ... + >>> def run(reactor): + ... d = sendNotification(SnmpEngine(), + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 162)), + ... ContextData(), + ... 'trap', + ... NotificationType(ObjectIdentity('IF-MIB', 'linkDown'))) + ... d.addCallback(success).addErrback(failure) + ... return d + ... + >>> react(run) + (0, 0, []) + >>> + + """ + def __cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBinds, cbCtx): + lookupMib, future = cbCtx + if errorIndication: + deferred.errback(Failure(errorIndication)) + else: + deferred.callback( + (errorStatus, errorIndex, + vbProcessor.unmakeVarBinds(snmpEngine, varBinds, lookupMib)) + ) + + notifyName = lcd.configure( + snmpEngine, authData, transportTarget, notifyType + ) + + def __trapFun(deferred): + deferred.callback((0, 0, [])) + + deferred = Deferred() + + ntforg.NotificationOriginator().sendVarBinds( + snmpEngine, + notifyName, + contextData.contextEngineId, + contextData.contextName, + vbProcessor.makeVarBinds(snmpEngine, varBinds), + __cbFun, + (options.get('lookupMib', True), deferred) + ) + + if notifyType == 'trap': + reactor.callLater(0, __trapFun, deferred) + + return deferred diff --git a/pysnmp/hlapi/twisted/transport.py b/pysnmp/hlapi/twisted/transport.py new file mode 100644 index 0000000..3fcff42 --- /dev/null +++ b/pysnmp/hlapi/twisted/transport.py @@ -0,0 +1,51 @@ +import socket, sys +from pysnmp.carrier.twisted.dgram import udp +from pysnmp.hlapi.transport import AbstractTransportTarget + +__all__ = ['UdpTransportTarget'] + +class UdpTransportTarget(AbstractTransportTarget): + """Creates UDP/IPv4 configuration entry and initialize socket API if needed. + + This object can be used for adding new entries to Local Configuration + Datastore (LCD) managed by :py:class:`~pysnmp.hlapi.SnmpEngine` + class instance. + + See :RFC:`1906#section-3` for more information on the UDP transport mapping. + + Parameters + ---------- + transportAddr : tuple + Indicates remote address in Python :py:mod:`socket` module format + which is a tuple of FQDN, port where FQDN is a string representing + either hostname or IPv4 address in quad-dotted form, port is an + integer. + timeout : int + Response timeout in seconds. + retries : int + Maximum number of request retries, 0 retries means just a single + request. + tagList : str + Arbitrary string that contains a list of tag values which are used + to select target addresses for a particular operation + (:RFC:`3413#section-4.1.4`). + + Examples + -------- + >>> from pysnmp.hlapi.twisted import UdpTransportTarget + >>> UdpTransportTarget(('demo.snmplabs.com', 161)) + UdpTransportTarget(('195.218.195.228', 161), timeout=1, retries=5, tagList='') + >>> + + """ + transportDomain = udp.domainName + protoTransport = udp.UdpTwistedTransport + def _resolveAddr(self, transportAddr): + try: + return socket.getaddrinfo(transportAddr[0], + transportAddr[1], + socket.AF_INET, + socket.SOCK_DGRAM, + socket.IPPROTO_UDP)[0][4][:2] + except socket.gaierror: + raise error.PySnmpError('Bad IPv4/UDP transport address %s: %s' % ('@'.join([ str(x) for x in transportAddr ]), sys.exc_info()[1])) diff --git a/setup.py b/setup.py index 7f189ad..4cf6cbe 100644 --- a/setup.py +++ b/setup.py @@ -104,12 +104,14 @@ params.update( { 'pysnmp.carrier.asyncio.dgram', 'pysnmp.entity', 'pysnmp.entity.rfc3413', - 'pysnmp.entity.rfc3413.twisted', - 'pysnmp.entity.rfc3413.asyncio', + 'pysnmp.entity.rfc3413.oneliner', 'pysnmp.hlapi', + 'pysnmp.hlapi.asyncio', 'pysnmp.hlapi.asyncore', 'pysnmp.hlapi.asyncore._sync', 'pysnmp.hlapi.asyncore._sync.compat', + 'pysnmp.hlapi.trollius', + 'pysnmp.hlapi.twisted', 'pysnmp.proto', 'pysnmp.proto.mpmod', 'pysnmp.proto.secmod', -- cgit v1.2.1