Skip to content

Commit

Permalink
Handle low-level SnmpTimeoutErrors for SNMPv3
Browse files Browse the repository at this point in the history
An SNMPv3 conversation may start with a discovery phase, to learn the
remote SNMP entity's authoritative EngineID.  This initial pair of
"discovery" and "report" packages are handled implicitly by NET-SNMP.

However, this can result in a timeout error from the async call to get
a value, rather than a timeout error that we generate "ourselves" when
we have waited too long.  This type of error is raised by pynetsnmp
as "yet another timeout exception class", rather than one of the
existing timeout exceptions.

This adds `SnmpTimeoutError` to the list of handled timeout exceptions
where timeouts are handled explicitly, while in the mibretriever
retrieval methods it is translated to a regular TimeoutError exception.
  • Loading branch information
lunkwill42 committed Nov 17, 2023
1 parent 45b43ef commit 03cdad2
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 2 deletions.
4 changes: 2 additions & 2 deletions python/nav/ipdevpoll/plugins/snmpcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# License along with NAV. If not, see <http://www.gnu.org/licenses/>.
#
"""snmp check plugin"""

from pynetsnmp.netsnmp import SnmpTimeoutError
from twisted.internet import error, defer
from twisted.internet.defer import returnValue

Expand Down Expand Up @@ -69,7 +69,7 @@ def _do_check(self):
self._logger.debug("checking SNMP v%s availability", self.agent.snmpVersion)
try:
result = yield self.agent.walk(SYSTEM_OID)
except (defer.TimeoutError, error.TimeoutError):
except (defer.TimeoutError, error.TimeoutError, SnmpTimeoutError):
self._logger.debug("SNMP v%s timed out", self.agent.snmpVersion)
returnValue(False)

Expand Down
7 changes: 7 additions & 0 deletions python/nav/mibs/mibretriever.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

import logging

from pynetsnmp.netsnmp import SnmpTimeoutError
from twisted.internet import defer, reactor
from twisted.internet.defer import returnValue
from twisted.internet.error import TimeoutError
Expand Down Expand Up @@ -427,6 +428,11 @@ def _result_formatter(result):

return formatted_result

def _snmp_timeout_handler(failure: defer.failure.Failure):
"""Transforms SnmpTimeoutErrors into "regular" TimeoutErrors"""
failure.trap(SnmpTimeoutError)
raise TimeoutError(failure.value)

def _valueerror_handler(failure):
failure.trap(ValueError)
self._logger.warning(
Expand All @@ -439,6 +445,7 @@ def _valueerror_handler(failure):
return {} # alternative is to retry or raise a Timeout exception

deferred = self.agent_proxy.getTable([str(node.oid)])
deferred.addErrback(_snmp_timeout_handler)
deferred.addCallbacks(_result_formatter, _valueerror_handler)
return deferred

Expand Down

0 comments on commit 03cdad2

Please sign in to comment.