summaryrefslogtreecommitdiff
path: root/pysnmp
diff options
context:
space:
mode:
Diffstat (limited to 'pysnmp')
-rw-r--r--pysnmp/hlapi/v1arch/asyncio/__init__.py13
-rw-r--r--pysnmp/hlapi/v1arch/asyncio/cmdgen.py567
-rw-r--r--pysnmp/hlapi/v1arch/asyncio/dispatch.py29
-rw-r--r--pysnmp/hlapi/v1arch/asyncio/ntforg.py199
-rw-r--r--pysnmp/hlapi/v1arch/asyncio/transport.py126
-rw-r--r--pysnmp/hlapi/v1arch/asyncore/transport.py1
-rw-r--r--pysnmp/hlapi/v3arch/asyncio/transport.py33
7 files changed, 951 insertions, 17 deletions
diff --git a/pysnmp/hlapi/v1arch/asyncio/__init__.py b/pysnmp/hlapi/v1arch/asyncio/__init__.py
new file mode 100644
index 00000000..efebeeb4
--- /dev/null
+++ b/pysnmp/hlapi/v1arch/asyncio/__init__.py
@@ -0,0 +1,13 @@
+#
+# This file is part of pysnmp software.
+#
+# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
+# License: http://snmplabs.com/pysnmp/license.html
+#
+from pysnmp.hlapi.v1arch.auth import *
+from pysnmp.hlapi.v1arch.asyncio.transport import *
+from pysnmp.hlapi.v1arch.asyncio.cmdgen import *
+from pysnmp.hlapi.v1arch.asyncio.ntforg import *
+from pysnmp.hlapi.v1arch.asyncio.dispatch import *
+from pysnmp.proto.rfc1902 import *
+from pysnmp.smi.rfc1902 import *
diff --git a/pysnmp/hlapi/v1arch/asyncio/cmdgen.py b/pysnmp/hlapi/v1arch/asyncio/cmdgen.py
new file mode 100644
index 00000000..346b7c76
--- /dev/null
+++ b/pysnmp/hlapi/v1arch/asyncio/cmdgen.py
@@ -0,0 +1,567 @@
+#
+# This file is part of pysnmp software.
+#
+# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
+# License: http://snmplabs.com/pysnmp/license.html
+#
+from pysnmp.hlapi.v1arch.auth import *
+from pysnmp.hlapi.varbinds import *
+from pysnmp.hlapi.v1arch.asyncio.transport import *
+from pysnmp.smi.rfc1902 import *
+from pysnmp.proto import api
+
+try:
+ import asyncio
+
+except ImportError:
+ import trollius as asyncio
+
+__all__ = ['getCmd', 'nextCmd', 'setCmd', 'bulkCmd', 'isEndOfMib']
+
+VB_PROCESSOR = CommandGeneratorVarBinds()
+
+isEndOfMib = lambda varBinds: not api.v2c.apiPDU.getNextVarBinds(varBinds)[1]
+
+
+@asyncio.coroutine
+def getCmd(snmpDispatcher, authData, transportTarget,
+ *varBinds, **options):
+ """Creates a generator to perform SNMP GET query.
+
+ When iterator gets advanced by :py:mod:`asyncio` main loop,
+ SNMP GET request is sent (:RFC:`1905#section-4.2.1`).
+ The iterator yields :py:class:`asyncio.Future` which gets done whenever
+ response arrives or error occurs.
+
+ Parameters
+ ----------
+ snmpDispatcher: :py:class:`~pysnmp.hlapi.v1arch.asyncore.SnmpDispatcher`
+ Class instance representing asynio-based asynchronous event loop and
+ associated state information.
+
+ authData: :py:class:`~pysnmp.hlapi.v1arch.CommunityData`
+ Class instance representing SNMPv1/v2c credentials.
+
+ transportTarget: :py:class:`~pysnmp.hlapi.v1arch.asyncio.UdpTransportTarget` or
+ :py:class:`~pysnmp.hlapi.v1arch.asyncio.Udp6TransportTarget` Class instance representing
+ transport type along with SNMP peer address.
+
+ \*varBinds: :class:`tuple` of OID-value pairs or :py:class:`~pysnmp.smi.rfc1902.ObjectType`
+ One or more class instances representing MIB variables to place
+ into SNMP request.
+
+ Note
+ ----
+ The `SnmpDispatcher` object may be expensive to create, therefore it is
+ advised to maintain it for the lifecycle of the application/thread for
+ as long as possible.
+
+ Other Parameters
+ ----------------
+ \*\*options :
+ Request options:
+
+ * `lookupMib` - load MIB and resolve response MIB variables at
+ the cost of slightly reduced performance. Default is `False`,
+ unless :py:class:`~pysnmp.smi.rfc1902.ObjectType` is present
+ among `varBinds` in which case `lookupMib` gets automatically
+ enabled.
+
+ 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 OID-value pairs in form of base SNMP types (if
+ `lookupMib` is `False`) or :py:class:`~pysnmp.smi.rfc1902.ObjectType`
+ class instances (if `lookupMib` is `True`) 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.v1arch.asyncio import *
+ >>>
+ >>> @asyncio.coroutine
+ ... def run():
+ ... errorIndication, errorStatus, errorIndex, varBinds = yield from getCmd(
+ ... SnmpDispatcher(),
+ ... CommunityData('public'),
+ ... UdpTransportTarget(('demo.snmplabs.com', 161)),
+ ... 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(snmpDispatcher, stateHandle, errorIndication, rspPdu, _cbCtx):
+ if future.cancelled():
+ return
+
+ errorStatus = pMod.apiPDU.getErrorStatus(rspPdu)
+ errorIndex = pMod.apiPDU.getErrorIndex(rspPdu)
+
+ varBinds = pMod.apiPDU.getVarBinds(rspPdu)
+
+ if lookupMib:
+ try:
+ varBinds = VB_PROCESSOR.unmakeVarBinds(
+ snmpDispatcher.cache, varBinds, lookupMib)
+
+ except Exception as e:
+ future.set_exception(e)
+ return
+
+ future.set_result(
+ (errorIndication, errorStatus, errorIndex, varBinds)
+ )
+
+ lookupMib = options.get('lookupMib')
+
+ if not lookupMib and any(isinstance(x, ObjectType) for x in varBinds):
+ lookupMib = True
+
+ if lookupMib:
+ varBinds = VB_PROCESSOR.makeVarBinds(snmpDispatcher.cache, varBinds)
+
+ pMod = api.PROTOCOL_MODULES[authData.mpModel]
+
+ reqPdu = pMod.GetRequestPDU()
+ pMod.apiPDU.setDefaults(reqPdu)
+ pMod.apiPDU.setVarBinds(reqPdu, varBinds)
+
+ future = asyncio.Future()
+
+ snmpDispatcher.sendPdu(authData, transportTarget, reqPdu, cbFun=_cbFun)
+
+ return future
+
+
+@asyncio.coroutine
+def setCmd(snmpDispatcher, authData, transportTarget,
+ *varBinds, **options):
+ """Creates a generator to perform SNMP SET query.
+
+ When iterator gets advanced by :py:mod:`asyncio` main loop,
+ SNMP SET request is sent (:RFC:`1905#section-4.2.5`).
+ The iterator yields :py:class:`asyncio.Future` which gets done whenever
+ response arrives or error occurs.
+
+ Parameters
+ ----------
+ snmpDispatcher: :py:class:`~pysnmp.hlapi.v1arch.asyncore.SnmpDispatcher`
+ Class instance representing asynio-based asynchronous event loop and
+ associated state information.
+
+ authData: :py:class:`~pysnmp.hlapi.v1arch.CommunityData`
+ Class instance representing SNMPv1/v2c credentials.
+
+ transportTarget: :py:class:`~pysnmp.hlapi.v1arch.asyncio.UdpTransportTarget` or
+ :py:class:`~pysnmp.hlapi.v1arch.asyncio.Udp6TransportTarget` Class instance representing
+ transport type along with SNMP peer address.
+
+ \*varBinds: :class:`tuple` of OID-value pairs or :py:class:`~pysnmp.smi.rfc1902.ObjectType`
+ One or more class instances representing MIB variables to place
+ into SNMP request.
+
+ Note
+ ----
+ The `SnmpDispatcher` object may be expensive to create, therefore it is
+ advised to maintain it for the lifecycle of the application/thread for
+ as long as possible.
+
+ Other Parameters
+ ----------------
+ \*\*options :
+ Request options:
+
+ * `lookupMib` - load MIB and resolve response MIB variables at
+ the cost of slightly reduced performance. Default is `False`,
+ unless :py:class:`~pysnmp.smi.rfc1902.ObjectType` is present
+ among `varBinds` in which case `lookupMib` gets automatically
+ enabled.
+
+ 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 OID-value pairs in form of base SNMP types (if
+ `lookupMib` is `False`) or :py:class:`~pysnmp.smi.rfc1902.ObjectType`
+ class instances (if `lookupMib` is `True`) 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.v1arch.asyncio import *
+ >>>
+ >>> @asyncio.coroutine
+ ... def run():
+ ... errorIndication, errorStatus, errorIndex, varBinds = yield from setCmd(
+ ... SnmpDispatcher(),
+ ... CommunityData('public'),
+ ... UdpTransportTarget(('demo.snmplabs.com', 161)),
+ ... 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(snmpDispatcher, stateHandle, errorIndication, rspPdu, _cbCtx):
+ if future.cancelled():
+ return
+
+ errorStatus = pMod.apiPDU.getErrorStatus(rspPdu)
+ errorIndex = pMod.apiPDU.getErrorIndex(rspPdu)
+
+ varBinds = pMod.apiPDU.getVarBinds(rspPdu)
+
+ if lookupMib:
+ try:
+ varBinds = VB_PROCESSOR.unmakeVarBinds(
+ snmpDispatcher.cache, varBinds, lookupMib)
+
+ except Exception as e:
+ future.set_exception(e)
+ return
+
+ future.set_result(
+ (errorIndication, errorStatus, errorIndex, varBinds)
+ )
+
+ lookupMib = options.get('lookupMib')
+
+ if not lookupMib and any(isinstance(x, ObjectType) for x in varBinds):
+ lookupMib = True
+
+ if lookupMib:
+ varBinds = VB_PROCESSOR.makeVarBinds(snmpDispatcher.cache, varBinds)
+
+ pMod = api.PROTOCOL_MODULES[authData.mpModel]
+
+ reqPdu = pMod.SetRequestPDU()
+ pMod.apiPDU.setDefaults(reqPdu)
+ pMod.apiPDU.setVarBinds(reqPdu, varBinds)
+
+ future = asyncio.Future()
+
+ snmpDispatcher.sendPdu(authData, transportTarget, reqPdu, cbFun=_cbFun)
+
+ return future
+
+
+@asyncio.coroutine
+def nextCmd(snmpDispatcher, authData, transportTarget,
+ *varBinds, **options):
+ """Creates a generator to perform SNMP GETNEXT query.
+
+ When iterator 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
+ ----------
+ snmpDispatcher: :py:class:`~pysnmp.hlapi.v1arch.asyncore.SnmpDispatcher`
+ Class instance representing asynio-based asynchronous event loop and
+ associated state information.
+
+ authData: :py:class:`~pysnmp.hlapi.v1arch.CommunityData`
+ Class instance representing SNMPv1/v2c credentials.
+
+ transportTarget: :py:class:`~pysnmp.hlapi.v1arch.asyncio.UdpTransportTarget` or
+ :py:class:`~pysnmp.hlapi.v1arch.asyncio.Udp6TransportTarget` Class instance representing
+ transport type along with SNMP peer address.
+
+ \*varBinds: :class:`tuple` of OID-value pairs or :py:class:`~pysnmp.smi.rfc1902.ObjectType`
+ One or more class instances representing MIB variables to place
+ into SNMP request.
+
+ Note
+ ----
+ The `SnmpDispatcher` object may be expensive to create, therefore it is
+ advised to maintain it for the lifecycle of the application/thread for
+ as long as possible.
+
+ Other Parameters
+ ----------------
+ \*\*options:
+ Request options:
+
+ * `lookupMib` - load MIB and resolve response MIB variables at
+ the cost of slightly reduced performance. Default is `False`,
+ unless :py:class:`~pysnmp.smi.rfc1902.ObjectType` is present
+ among `varBinds` in which case `lookupMib` gets automatically
+ enabled.
+
+ 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 OID-value pairs in form
+ of base SNMP types (if `lookupMib` is `False`) or
+ :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances (if
+ `lookupMib` is `True`) 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(
+ ... SnmpDispatcher(),
+ ... 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(snmpDispatcher, stateHandle, errorIndication, rspPdu, _cbCtx):
+ if future.cancelled():
+ return
+
+ errorStatus = pMod.apiPDU.getErrorStatus(rspPdu)
+ errorIndex = pMod.apiPDU.getErrorIndex(rspPdu)
+
+ varBindTable = pMod.apiPDU.getVarBindTable(reqPdu, rspPdu)
+
+ if lookupMib:
+ try:
+ varBindTable = [
+ VB_PROCESSOR.unmakeVarBinds(snmpDispatcher.cache,
+ varBindTableRow, lookupMib)
+ for varBindTableRow in varBindTable
+ ]
+
+ except Exception as e:
+ future.set_exception(e)
+ return
+
+ future.set_result(
+ (errorIndication, errorStatus, errorIndex, varBindTable)
+ )
+
+ lookupMib = options.get('lookupMib')
+
+ if not lookupMib and any(isinstance(x, ObjectType) for x in varBinds):
+ lookupMib = True
+
+ if lookupMib:
+ varBinds = VB_PROCESSOR.makeVarBinds(snmpDispatcher.cache, varBinds)
+
+ pMod = api.PROTOCOL_MODULES[authData.mpModel]
+
+ reqPdu = pMod.GetNextRequestPDU()
+ pMod.apiPDU.setDefaults(reqPdu)
+ pMod.apiPDU.setVarBinds(reqPdu, varBinds)
+
+ future = asyncio.Future()
+
+ snmpDispatcher.sendPdu(authData, transportTarget, reqPdu, cbFun=_cbFun)
+
+ return future
+
+
+@asyncio.coroutine
+def bulkCmd(snmpDispatcher, authData, transportTarget,
+ nonRepeaters, maxRepetitions, *varBinds, **options):
+ """Creates a generator to perform SNMP GETBULK query.
+
+ When iterator 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
+ ----------
+ snmpDispatcher: :py:class:`~pysnmp.hlapi.v1arch.asyncore.SnmpDispatcher`
+ Class instance representing asynio-based asynchronous event loop and
+ associated state information.
+
+ authData: :py:class:`~pysnmp.hlapi.v1arch.CommunityData`
+ Class instance representing SNMPv1/v2c credentials.
+
+ transportTarget: :py:class:`~pysnmp.hlapi.v1arch.asyncio.UdpTransportTarget` or
+ :py:class:`~pysnmp.hlapi.v1arch.asyncio.Udp6TransportTarget` Class instance representing
+ transport type along with SNMP peer address.
+
+ 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:`tuple` of OID-value pairs or :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 `False`,
+ unless :py:class:`~pysnmp.smi.rfc1902.ObjectType` is present
+ among `varBinds` in which case `lookupMib` gets automatically
+ enabled.
+
+ 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]`
+ varBindTable: tuple
+ A sequence of sequences (e.g. 2-D array) of OID-value pairs in form
+ of base SNMP types (if `lookupMib` is `False`) or
+ :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances (if
+ `lookupMib` is `True`) a table of MIB variables returned in SNMP
+ response, with up to `maxRepetitions` rows, i.e.
+ `len(varBindTable) <= maxRepetitions`.
+
+ For `0 <= i < len(varBindTable)` and `0 <= j < len(varBinds)`,
+ `varBindTable[i][j]` represents:
+
+ - For non-repeaters (`j < nonRepeaters`), the first lexicographic
+ successor of `varBinds[j]`, regardless the value of `i`, or an
+ :py:class:`~pysnmp.smi.rfc1902.ObjectType` instance with the
+ :py:obj:`~pysnmp.proto.rfc1905.endOfMibView` value if no such
+ successor exists;
+ - For repeaters (`j >= nonRepeaters`), the `i`-th lexicographic
+ successor of `varBinds[j]`, or an
+ :py:class:`~pysnmp.smi.rfc1902.ObjectType` instance with the
+ :py:obj:`~pysnmp.proto.rfc1905.endOfMibView` value if no such
+ successor exists.
+
+ See :rfc:`3416#section-4.2.3` for details on the underlying
+ `GetBulkRequest-PDU` and the associated `GetResponse-PDU`, such as
+ specific conditions under which the server may truncate the response,
+ causing `varBindTable` to have less than `maxRepetitions` rows.
+
+ Raises
+ ------
+ PySnmpError
+ Or its derivative indicating that an error occurred while
+ performing SNMP operation.
+
+ Examples
+ --------
+ >>> import asyncio
+ >>> from pysnmp.hlapi.v1arch.asyncio import *
+ >>>
+ >>> @asyncio.coroutine
+ ... def run():
+ ... errorIndication, errorStatus, errorIndex, varBinds = yield from bulkCmd(
+ ... SnmpDispatcher(),
+ ... CommunityData('public'),
+ ... UdpTransportTarget(('demo.snmplabs.com', 161)),
+ ... 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(snmpDispatcher, stateHandle, errorIndication, rspPdu, _cbCtx):
+ if future.cancelled():
+ return
+
+ errorStatus = pMod.apiPDU.getErrorStatus(rspPdu)
+ errorIndex = pMod.apiPDU.getErrorIndex(rspPdu)
+
+ varBindTable = pMod.apiBulkPDU.getVarBindTable(reqPdu, rspPdu)
+
+ if lookupMib:
+ try:
+ varBindTable = [
+ VB_PROCESSOR.unmakeVarBinds(snmpDispatcher.cache,
+ varBindTableRow, lookupMib)
+ for varBindTableRow in varBindTable
+ ]
+
+ except Exception as e:
+ future.set_exception(e)
+ return
+
+ future.set_result(
+ (errorIndication, errorStatus, errorIndex, varBindTable)
+ )
+
+ lookupMib = options.get('lookupMib')
+
+ if not lookupMib and any(isinstance(x, ObjectType) for x in varBinds):
+ lookupMib = True
+
+ if lookupMib:
+ varBinds = VB_PROCESSOR.makeVarBinds(snmpDispatcher.cache, varBinds)
+
+ pMod = api.PROTOCOL_MODULES[authData.mpModel]
+
+ reqPdu = pMod.GetBulkRequestPDU()
+ pMod.apiPDU.setDefaults(reqPdu)
+ pMod.apiBulkPDU.setNonRepeaters(reqPdu, nonRepeaters)
+ pMod.apiBulkPDU.setMaxRepetitions(reqPdu, maxRepetitions)
+ pMod.apiPDU.setVarBinds(reqPdu, varBinds)
+
+ future = asyncio.Future()
+
+ snmpDispatcher.sendPdu(authData, transportTarget, reqPdu, cbFun=_cbFun)
+
+ return future
diff --git a/pysnmp/hlapi/v1arch/asyncio/dispatch.py b/pysnmp/hlapi/v1arch/asyncio/dispatch.py
new file mode 100644
index 00000000..d908beb9
--- /dev/null
+++ b/pysnmp/hlapi/v1arch/asyncio/dispatch.py
@@ -0,0 +1,29 @@
+#
+# This file is part of pysnmp software.
+#
+# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
+# License: http://snmplabs.com/pysnmp/license.html
+#
+from pysnmp.carrier.asyncio.dispatch import AsyncioDispatcher
+from pysnmp.hlapi.v1arch.dispatch import AbstractSnmpDispatcher
+
+__all__ = ['SnmpDispatcher']
+
+
+class SnmpDispatcher(AbstractSnmpDispatcher):
+ """Creates SNMP message dispatcher object.
+
+ `SnmpDispatcher` object manages send and receives SNMP PDU
+ messages through underlying transport dispatcher and dispatches
+ them to the callers.
+
+ `SnmpDispatcher` is the only stateful object, all `hlapi.v1arch` SNMP
+ operations require an instance of `SnmpDispatcher`. Users do not normally
+ request services directly from `SnmpDispather`, but pass it around to
+ other `hlapi.v1arch` interfaces.
+
+ It is possible to run multiple instances of `SnmpDispatcher` in the
+ application. In a multithreaded environment, each thread that
+ works with SNMP must have its own `SnmpDispatcher` instance.
+ """
+ PROTO_DISPATCHER = AsyncioDispatcher
diff --git a/pysnmp/hlapi/v1arch/asyncio/ntforg.py b/pysnmp/hlapi/v1arch/asyncio/ntforg.py
new file mode 100644
index 00000000..25d831e9
--- /dev/null
+++ b/pysnmp/hlapi/v1arch/asyncio/ntforg.py
@@ -0,0 +1,199 @@
+#
+# This file is part of pysnmp software.
+#
+# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
+# License: http://snmplabs.com/pysnmp/license.html
+#
+from pysnmp.hlapi.v1arch.auth import *
+from pysnmp.hlapi.varbinds import *
+from pysnmp.hlapi.v1arch.asyncio.transport import *
+from pysnmp.smi.rfc1902 import *
+from pysnmp.proto import api
+
+try:
+ import asyncio
+
+except ImportError:
+ import trollius as asyncio
+
+__all__ = ['sendNotification']
+
+VB_PROCESSOR = NotificationOriginatorVarBinds()
+
+
+@asyncio.coroutine
+def sendNotification(snmpDispatcher, authData, transportTarget,
+ notifyType, *varBinds, **options):
+ """Creates a generator to send SNMP notification.
+
+ When iterator 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
+ ----------
+ snmpDispatcher: :py:class:`~pysnmp.hlapi.v1arch.asyncore.SnmpDispatcher`
+ Class instance representing asynio-based asynchronous event loop and
+ associated state information.
+
+ authData: :py:class:`~pysnmp.hlapi.v1arch.CommunityData`
+ Class instance representing SNMPv1/v2c credentials.
+
+ transportTarget: :py:class:`~pysnmp.hlapi.v1arch.asyncio.UdpTransportTarget` or
+ :py:class:`~pysnmp.hlapi.v1arch.asyncio.Udp6TransportTarget` Class instance representing
+ transport type along with SNMP peer address.
+
+ notifyType : str
+ Indicates type of notification to be sent. Recognized literal
+ values are *trap* or *inform*.
+
+ \*varBinds: :class:`tuple` of OID-value pairs or :py:class:`~pysnmp.smi.rfc1902.ObjectType` or :py:class:`~pysnmp.smi.rfc1902.NotificationType`
+ One or more objects representing MIB variables to place
+ into SNMP notification. It could be tuples of OID-values
+ or :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances
+ of :py:class:`~pysnmp.smi.rfc1902.NotificationType` objects.
+
+ SNMP Notification PDU places rigid requirement on the ordering of
+ the variable-bindings.
+
+ Mandatory variable-bindings:
+
+ 0. SNMPv2-MIB::sysUpTime.0 = <agent uptime>
+ 1. SNMPv2-SMI::snmpTrapOID.0 = {SNMPv2-MIB::coldStart, ...}
+
+ Optional variable-bindings (applicable to SNMP v1 TRAP):
+
+ 2. SNMP-COMMUNITY-MIB::snmpTrapAddress.0 = <agent-IP>
+ 3. SNMP-COMMUNITY-MIB::snmpTrapCommunity.0 = <snmp-community-name>
+ 4. SNMP-COMMUNITY-MIB::snmpTrapEnterprise.0 = <enterprise-OID>
+
+ Informational variable-bindings:
+
+ * SNMPv2-SMI::NOTIFICATION-TYPE
+ * SNMPv2-SMI::OBJECT-TYPE
+
+ Other Parameters
+ ----------------
+ \*\*options :
+ Request options:
+
+ * `lookupMib` - load MIB and resolve response MIB variables at
+ the cost of slightly reduced performance. Default is `False`,
+ unless :py:class:`~pysnmp.smi.rfc1902.ObjectType` or
+ :py:class:`~pysnmp.smi.rfc1902.NotificationType` is present
+ among `varBinds` in which case `lookupMib` gets automatically
+ enabled.
+
+ 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 OID-value pairs in form of base SNMP types (if
+ `lookupMib` is `False`) or :py:class:`~pysnmp.smi.rfc1902.ObjectType`
+ class instances (if `lookupMib` is `True`) 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 sendNotification(
+ ... SnmpDispatcher(),
+ ... CommunityData('public'),
+ ... UdpTransportTarget(('demo.snmplabs.com', 162)),
+ ... 'trap',
+ ... NotificationType(ObjectIdentity('IF-MIB', 'linkDown')))
+ ... print(errorIndication, errorStatus, errorIndex, varBinds)
+ ...
+ >>> asyncio.get_event_loop().run_until_complete(run())
+ (None, 0, 0, [])
+ >>>
+ """
+
+ def _cbFun(snmpDispatcher, stateHandle, errorIndication, rspPdu, _cbCtx):
+ if future.cancelled():
+ return
+
+ errorStatus = pMod.apiTrapPDU.getErrorStatus(rspPdu)
+ errorIndex = pMod.apiTrapPDU.getErrorIndex(rspPdu)
+
+ varBinds = pMod.apiTrapPDU.getVarBinds(rspPdu)
+
+ try:
+ varBindsUnmade = VB_PROCESSOR.unmakeVarBinds(snmpDispatcher.cache, varBinds,
+ lookupMib)
+ except Exception as e:
+ future.set_exception(e)
+
+ else:
+ future.set_result(
+ (errorIndication, errorStatus, errorIndex, varBindsUnmade)
+ )
+
+ lookupMib = options.get('lookupMib')
+
+ if not lookupMib and any(isinstance(x, (NotificationType, ObjectType))
+ for x in varBinds):
+ lookupMib = True
+
+ if lookupMib:
+ varBinds = VB_PROCESSOR.makeVarBinds(snmpDispatcher.cache, varBinds)
+
+ # # make sure required PDU payload is in place
+ # completeVarBinds = []
+ #
+ # # ensure sysUpTime
+ # if len(varBinds) < 1 or varBinds[0][0] != pMod.apiTrapPDU.sysUpTime:
+ # varBinds.insert(0, (ObjectIdentifier(pMod.apiTrapPDU.sysUpTime), pMod.Integer(0)))
+ #
+ # # ensure sysUpTime
+ # if len(varBinds) < 1 or varBinds[0][0] != pMod.apiTrapPDU.sysUpTime:
+ # varBinds.insert(0, (ObjectIdentifier(pMod.apiTrapPDU.sysUpTime), pMod.Integer(0)))
+ #
+ # # ensure snmpTrapOID
+ # if len(varBinds) < 2 or varBinds[1][0] != pMod.apiTrapPDU.snmpTrapOID:
+ # varBinds.insert(0, (ObjectIdentifier(pMod.apiTrapPDU.sysUpTime), pMod.Integer(0)))
+
+ # input PDU is always v2c
+ pMod = api.PROTOCOL_MODULES[api.SNMP_VERSION_2C]
+
+ if notifyType == 'trap':
+ reqPdu = pMod.TrapPDU()
+ else:
+ reqPdu = pMod.InformRequestPDU()
+
+ pMod.apiTrapPDU.setDefaults(reqPdu)
+ pMod.apiTrapPDU.setVarBinds(reqPdu, varBinds)
+
+ if authData.mpModel == 0:
+ reqPdu = rfc2576.v2ToV1(reqPdu)
+
+ future = asyncio.Future()
+
+ snmpDispatcher.sendPdu(authData, transportTarget, reqPdu, cbFun=_cbFun)
+
+ 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/v1arch/asyncio/transport.py b/pysnmp/hlapi/v1arch/asyncio/transport.py
new file mode 100644
index 00000000..5d4895e5
--- /dev/null
+++ b/pysnmp/hlapi/v1arch/asyncio/transport.py
@@ -0,0 +1,126 @@
+#
+# This file is part of pysnmp software.
+#
+# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
+# License: http://snmplabs.com/pysnmp/license.html
+#
+import socket
+import sys
+
+from pysnmp.carrier.asyncio.dgram import udp
+from pysnmp.carrier.asyncio.dgram import udp6
+from pysnmp.error import PySnmpError
+from pysnmp.hlapi.transport import AbstractTransportTarget
+
+__all__ = ['Udp6TransportTarget', 'UdpTransportTarget']
+
+
+class UdpTransportTarget(AbstractTransportTarget):
+ """Represent UDP/IPv4 transport endpoint.
+
+ This object can be used for passing UDP/IPv4 configuration
+ information to the
+ :py:class:`~pysnmp.hlapi.v1arch.asyncio.AsyncCommandGenerator` and
+ :py:class:`~pysnmp.hlapi.v1arch.asyncio.AsyncNotificationOriginator`
+ objects scheduled on I/O by :py:class:`~pysnmp.hlapi.SnmpDispatcher`
+ 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: :py:class:`int`
+ Response timeout in seconds.
+ retries: :py:class:`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.v1arch.asyncore import UdpTransportTarget
+ >>> UdpTransportTarget(('demo.snmplabs.com', 161))
+ UdpTransportTarget(('195.218.195.228', 161), timeout=1, retries=5)
+ >>>
+ """
+ TRANSPORT_DOMAIN = udp.domainName
+ PROTO_TRANSPORT = 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 as exc:
+ raise PySnmpError('Bad IPv4/UDP transport address %s: %s' % (
+ '@'.join([str(x) for x in transportAddr]), exc))
+
+
+class Udp6TransportTarget(AbstractTransportTarget):
+ """Represent UDP/IPv6 transport endpoint.
+
+ This object can be used for passing UDP/IPv6 configuration
+ information to the
+ :py:class:`~pysnmp.hlapi.v1arch.asyncio.AsyncCommandGenerator` and
+ :py:class:`~pysnmp.hlapi.v1arch.asyncio.AsyncNotificationOriginator`
+ objects scheduled on I/O by :py:class:`~pysnmp.hlapi.SnmpDispatcher`
+ 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='')
+ >>>
+ """
+ TRANSPORT_DOMAIN = udp6.domainName
+ PROTO_TRANSPORT = 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 as exc:
+ raise PySnmpError('Bad IPv6/UDP transport address %s: %s' % (
+ '@'.join([str(x) for x in transportAddr]), exc))
diff --git a/pysnmp/hlapi/v1arch/asyncore/transport.py b/pysnmp/hlapi/v1arch/asyncore/transport.py
index 507424fe..ad180337 100644
--- a/pysnmp/hlapi/v1arch/asyncore/transport.py
+++ b/pysnmp/hlapi/v1arch/asyncore/transport.py
@@ -42,7 +42,6 @@ class UdpTransportTarget(AbstractTransportTarget):
>>> UdpTransportTarget(('demo.snmplabs.com', 161))
UdpTransportTarget(('195.218.195.228', 161), timeout=1, retries=5)
>>>
-
"""
TRANSPORT_DOMAIN = udp.DOMAIN_NAME
PROTO_TRANSPORT = udp.UdpSocketTransport
diff --git a/pysnmp/hlapi/v3arch/asyncio/transport.py b/pysnmp/hlapi/v3arch/asyncio/transport.py
index 9079c1c8..0b795163 100644
--- a/pysnmp/hlapi/v3arch/asyncio/transport.py
+++ b/pysnmp/hlapi/v3arch/asyncio/transport.py
@@ -16,27 +16,30 @@ __all__ = ['Udp6TransportTarget', 'UdpTransportTarget']
class UdpTransportTarget(AbstractTransportTarget):
- """Creates UDP/IPv4 configuration entry and initialize socket API if needed.
+ """Represent UDP/IPv6 transport endpoint.
- This object can be used for adding new entries to Local Configuration
- Datastore (LCD) managed by :py:class:`~pysnmp.hlapi.SnmpEngine`
+ This object can be used for passing UDP/IPv6 configuration
+ information to the
+ :py:class:`~pysnmp.hlapi.v3arch.asyncio.AsyncCommandGenerator` and
+ :py:class:`~pysnmp.hlapi.v3arch.asyncio.AsyncNotificationOriginator`
+ Datastore (LCD) managed by :py:class:`~pysnmp.hlapi.v3arch.SnmpEngine`
class instance.
See :RFC:`1906#section-3` for more information on the UDP transport mapping.
Parameters
----------
- transportAddr : tuple
+ 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
+ timeout: int
Response timeout in seconds.
- retries : int
+ retries: int
Maximum number of request retries, 0 retries means just a single
request.
- tagList : str
+ 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`).
@@ -47,7 +50,6 @@ class UdpTransportTarget(AbstractTransportTarget):
>>> UdpTransportTarget(('demo.snmplabs.com', 161))
UdpTransportTarget(('195.218.195.228', 161), timeout=1, retries=5, tagList='')
>>>
-
"""
TRANSPORT_DOMAIN = udp.domainName
PROTO_TRANSPORT = udp.UdpAsyncioTransport
@@ -68,10 +70,10 @@ 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`
+ :py:class:`~pysnmp.hlapi.v3arch.asyncio.AsyncCommandGenerator` or
+ :py:class:`~pysnmp.hlapi.v3arch.asyncio.AsyncNotificationOriginator`
+ and their derivatives for adding new entries to Local Configuration
+ Datastore (LCD) managed by :py:class:`~pysnmp.hlapi.v3arch.SnmpEngine`
class instance.
See :RFC:`1906#section-3`, :RFC:`2851#section-4` for more information
@@ -84,12 +86,12 @@ class Udp6TransportTarget(AbstractTransportTarget):
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
+ timeout: int
Response timeout in seconds.
- retries : int
+ retries: int
Maximum number of request retries, 0 retries means just a single
request.
- tagList : str
+ 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`).
@@ -108,7 +110,6 @@ class Udp6TransportTarget(AbstractTransportTarget):
>>> Udp6TransportTarget(('::', 161))
Udp6TransportTarget(('::', 161), timeout=1, retries=5, tagList='')
>>>
-
"""
TRANSPORT_DOMAIN = udp6.domainName
PROTO_TRANSPORT = udp6.Udp6AsyncioTransport