From 41b494dacf074ddb60de372863d5d31d9c998be5 Mon Sep 17 00:00:00 2001 From: Lex Li Date: Mon, 25 Dec 2023 15:30:28 -0500 Subject: [PATCH] Improved Slim class to fix #38. --- pysnmp/hlapi/v3arch/asyncio/slim.py | 113 +++++++++++++++++++--------- 1 file changed, 76 insertions(+), 37 deletions(-) diff --git a/pysnmp/hlapi/v3arch/asyncio/slim.py b/pysnmp/hlapi/v3arch/asyncio/slim.py index 92d3c2096..1ffa9bd52 100644 --- a/pysnmp/hlapi/v3arch/asyncio/slim.py +++ b/pysnmp/hlapi/v3arch/asyncio/slim.py @@ -7,7 +7,8 @@ from pysnmp.error import PySnmpError from pysnmp.hlapi.v3arch.asyncio import * -__all__ = ['Slim'] +__all__ = ["Slim"] + class Slim: """Creates slim SNMP wrapper object. @@ -36,16 +37,16 @@ class Slim: def __init__(self, version=2): self.snmpEngine = SnmpEngine() if version not in (1, 2): - raise PySnmpError('Not supported version {}'.format(version)) + raise PySnmpError("Not supported version {}".format(version)) self.version = version def close(self): - """Closes the wrapper to release its resources. - """ + """Closes the wrapper to release its resources.""" self.snmpEngine.transportDispatcher.closeDispatcher() - async def get(self, communityName, address, port, *varBinds): - r"""Creates a generator to perform SNMP GET query. + async def get(self, communityName, address, port, *varBinds, timeout=1, retries=5): + """ + Creates a generator to perform SNMP GET query. When iterator gets advanced by :py:mod:`asyncio` main loop, SNMP GET request is send (:RFC:`1905#section-4.2.1`). @@ -63,19 +64,28 @@ async def get(self, communityName, address, port, *varBinds): port : :py:obj:`int` Remote SNMP engine port number. - \*varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType` + *varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType` One or more class instances representing MIB variables to place into SNMP request. + timeout : :py:obj:`int`, optional + Timeout value in seconds (default is 1). + + retries : :py:obj:`int`, optional + Number of retries (default is 5). + Yields ------ errorIndication : :py:class:`~pysnmp.proto.errind.ErrorIndication` True value indicates SNMP engine error. - errorStatus : str + + errorStatus : :py:obj:`str` True value indicates SNMP PDU error. - errorIndex : int - Non-zero value refers to `varBinds[errorIndex-1]` - varBinds : tuple + + errorIndex : :py:obj:`int` + Non-zero value refers to `varBinds[errorIndex-1]`. + + varBinds : :py:obj:`tuple` A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances representing MIB variables returned in SNMP response. @@ -102,23 +112,23 @@ async def get(self, communityName, address, port, *varBinds): >>> asyncio.run(run()) (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.pysnmp.com 4.1.3_U1 1 sun4m'))]) >>> - """ return await getCmd( self.snmpEngine, CommunityData(communityName, mpModel=self.version - 1), - UdpTransportTarget((address, port)), + UdpTransportTarget((address, port), timeout, retries), ContextData(), *varBinds, ) - async def next(self, communityName, address, port, *varBinds): - r"""Creates a generator to perform SNMP GETNEXT query. + async def next(self, communityName, address, port, *varBinds, timeout=1, retries=5): + """ + 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.get_running_loop().create_future()` which gets done whenever + The iterator yields :py:class:`~asyncio.get_running_loop().create_future()` which gets done whenever response arrives or error occurs. Parameters @@ -132,19 +142,28 @@ async def next(self, communityName, address, port, *varBinds): port : :py:obj:`int` Remote SNMP engine port number. - \*varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType` + *varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType` One or more class instances representing MIB variables to place into SNMP request. + timeout : :py:obj:`int`, optional + Timeout value in seconds. Default is 1. + + retries : :py:obj:`int`, optional + Number of retries. Default is 5. + Yields ------ errorIndication : :py:class:`~pysnmp.proto.errind.ErrorIndication` True value indicates SNMP engine error. - errorStatus : str + + errorStatus : :py:obj:`str` True value indicates SNMP PDU error. - errorIndex : int + + errorIndex : :py:obj:`int` Non-zero value refers to `varBinds[errorIndex-1]` - varBinds : tuple + + varBinds : :py:obj:`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. @@ -167,7 +186,7 @@ async def next(self, communityName, address, port, *varBinds): ... errorIndication, errorStatus, errorIndex, varBinds = await Slim().next( ... 'public', ... 'demo.pysnmp.com', - ..... 161, + ... 161, ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')) ... ) ... print(errorIndication, errorStatus, errorIndex, varBinds) @@ -175,18 +194,26 @@ async def next(self, communityName, address, port, *varBinds): >>> asyncio.run(run()) (None, 0, 0, [[ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0'), DisplayString('Linux i386'))]]) >>> - """ - return await nextCmd( self.snmpEngine, CommunityData(communityName, mpModel=self.version - 1), - UdpTransportTarget((address, port)), + UdpTransportTarget((address, port), timeout, retries), ContextData(), *varBinds, ) - async def bulk(self, communityName, address, port, nonRepeaters, maxRepetitions, *varBinds): + async def bulk( + self, + communityName, + address, + port, + nonRepeaters, + maxRepetitions, + *varBinds, + timeout=1, + retries=5 + ): r"""Creates a generator to perform SNMP GETBULK query. When iterator gets advanced by :py:mod:`asyncio` main loop, @@ -205,11 +232,11 @@ async def bulk(self, communityName, address, port, nonRepeaters, maxRepetitions, port : :py:obj:`int` Remote SNMP engine port number. - nonRepeaters : int + nonRepeaters : :py:obj:`int` One MIB variable is requested in response for the first `nonRepeaters` MIB variables in request. - maxRepetitions : int + maxRepetitions : :py:obj:`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 @@ -219,6 +246,12 @@ async def bulk(self, communityName, address, port, nonRepeaters, maxRepetitions, One or more class instances representing MIB variables to place into SNMP request. + timeout : :py:obj:`int`, optional + Timeout value in seconds. Default is 1. + + retries : :py:obj:`int`, optional + Number of retries. Default is 5. + Yields ------ errorIndication : :py:class:`~pysnmp.proto.errind.ErrorIndication` @@ -283,19 +316,20 @@ async def bulk(self, communityName, address, port, nonRepeaters, maxRepetitions, version = self.version - 1 if version == 0: - raise PySnmpError('Cannot send V2 PDU on V1 session') + raise PySnmpError("Cannot send V2 PDU on V1 session") return await bulkCmd( self.snmpEngine, CommunityData(communityName, mpModel=version), - UdpTransportTarget((address, port)), + UdpTransportTarget((address, port), timeout, retries), ContextData(), nonRepeaters, maxRepetitions, *varBinds, ) - async def set(self, communityName, address, port, *varBinds): - r"""Creates a generator to perform SNMP SET query. + async def set(self, communityName, address, port, *varBinds, timeout=1, retries=5): + """ + Creates a generator to perform SNMP SET query. When iterator gets advanced by :py:mod:`asyncio` main loop, SNMP SET request is send (:RFC:`1905#section-4.2.5`). @@ -313,19 +347,25 @@ async def set(self, communityName, address, port, *varBinds): port : :py:obj:`int` Remote SNMP engine port number. - \*varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType` + *varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType` One or more class instances representing MIB variables to place into SNMP request. + timeout : :py:obj:`int`, optional + Timeout value in seconds. Default is 1. + + retries : :py:obj:`int`, optional + Number of retries. Default is 5. + Yields ------ errorIndication : :py:class:`~pysnmp.proto.errind.ErrorIndication` True value indicates SNMP engine error. - errorStatus : str + errorStatus : :py:obj:`str` True value indicates SNMP PDU error. - errorIndex : int + errorIndex : :py:obj:`int` Non-zero value refers to `varBinds[errorIndex-1]` - varBinds : tuple + varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType` A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances representing MIB variables returned in SNMP response. @@ -352,13 +392,12 @@ async def set(self, communityName, address, port, *varBinds): >>> asyncio.run(run()) (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('Linux i386'))]) >>> - """ return await setCmd( self.snmpEngine, CommunityData(communityName, mpModel=self.version - 1), - UdpTransportTarget((address, port)), + UdpTransportTarget((address, port), timeout, retries), ContextData(), *varBinds, )