diff options
author | elie <elie> | 2014-04-04 15:03:22 +0000 |
---|---|---|
committer | elie <elie> | 2014-04-04 15:03:22 +0000 |
commit | 292dfeff126ff9c5b15a06be6cf8d3b44517248b (patch) | |
tree | cf1efe193479357476e8b2d7b255f1aaaf082be9 /pysnmp | |
parent | c6a76ec5ad93e1194641dbf4042dcc2d8345dd9e (diff) | |
download | pysnmp-292dfeff126ff9c5b15a06be6cf8d3b44517248b.tar.gz |
Major rewrite of native SNMPv3 CommandGenerator and NotificationOriginator
applications towards the following goals:
* avoid bonding with particular SNMP engine instance to promote single
app instance using many SNMP engine instances
* support two APIs for working with request data: one operates on the
whole PDU object while the other on PDU contents
* keep callback context data in stack rather than in stateful application
cache
* newly introduced sendVarBinds() method offers a more functional and
logical signatures.
* keep backward compatibility for all existing major/documented interfaces
Diffstat (limited to 'pysnmp')
-rw-r--r-- | pysnmp/entity/rfc3413/cmdgen.py | 809 | ||||
-rw-r--r-- | pysnmp/entity/rfc3413/ntforg.py | 413 | ||||
-rw-r--r-- | pysnmp/entity/rfc3413/oneliner/ntforg.py | 12 |
3 files changed, 649 insertions, 585 deletions
diff --git a/pysnmp/entity/rfc3413/cmdgen.py b/pysnmp/entity/rfc3413/cmdgen.py index 1cda2f2..0ea6467 100644 --- a/pysnmp/entity/rfc3413/cmdgen.py +++ b/pysnmp/entity/rfc3413/cmdgen.py @@ -31,27 +31,26 @@ def getNextVarBinds(origVarBinds, varBinds): return errorIndication, rspVarBinds -class CommandGeneratorBase: +class CommandGenerator: _null = univ.Null('') def __init__(self): self.__pendingReqs = {} - def processResponsePdu( - self, - snmpEngine, - messageProcessingModel, - securityModel, - securityName, - securityLevel, - contextEngineId, - contextName, - pduVersion, - PDU, - statusInformation, - sendPduHandle, - cbInfo - ): - (cbFun, cbCtx) = cbInfo + def processResponsePdu(self, + snmpEngine, + messageProcessingModel, + securityModel, + securityName, + securityLevel, + contextEngineId, + contextName, + pduVersion, + PDU, + statusInformation, + sendPduHandle, + cbCtx): + origSendRequestHandle, cbFun, cbCtx = cbCtx + # 3.1.1 if sendPduHandle not in self.__pendingReqs: raise error.PySnmpError('Missing sendPduHandle %s' % sendPduHandle) @@ -68,11 +67,8 @@ class CommandGeneratorBase: origPdu, origTimeout, origRetryCount, - origRetries, - origSendRequestHandle ) = self.__pendingReqs[sendPduHandle] + origRetries ) = self.__pendingReqs.pop(sendPduHandle) - del self.__pendingReqs[sendPduHandle] - snmpEngine.transportDispatcher.jobFinished(id(self)) # 3.1.3 @@ -87,12 +83,17 @@ class CommandGeneratorBase: errind.unknownEngineID) and \ origRetries == origRetryCount: debug.logger & debug.flagApp and debug.logger('processResponsePdu: sendPduHandle %s, retry count %d exceeded' % (sendPduHandle, origRetries)) - cbFun(origSendRequestHandle, - statusInformation['errorIndication'], 0, 0, (), + cbFun(snmpEngine, + origSendRequestHandle, + statusInformation['errorIndication'], + None, cbCtx) return try: - self._sendPdu( + cbCtx = origSendRequestHandle, cbFun, cbCtx + cbFun = self.processResponsePdu + + sendPduHandle = snmpEngine.msgAndPduDsp.sendPdu( snmpEngine, origTransportDomain, origTransportAddress, @@ -102,20 +103,42 @@ class CommandGeneratorBase: origSecurityLevel, origContextEngineId, origContextName, + origPduVersion, + origPdu, + True, # expectResponse + origTimeout, # already in ticks + cbFun, + cbCtx + ) + + snmpEngine.transportDispatcher.jobStarted(id(self)) + + self.__pendingReqs[sendPduHandle] = ( + origTransportDomain, + origTransportAddress, + origMessageProcessingModel, + origSecurityModel, + origSecurityName, + origSecurityLevel, + origContextEngineId, + origContextName, + origPduVersion, origPdu, origTimeout, origRetryCount, - origRetries + 1, - origSendRequestHandle, - (self.processResponsePdu, (cbFun, cbCtx)) + origRetries + 1 ) + return + except StatusInformation: statusInformation = sys.exc_info()[1] debug.logger & debug.flagApp and debug.logger('processResponsePdu: origSendRequestHandle %s, _sendPdu() failed with %r' % (sendPduHandle, statusInformation)) - cbFun(origSendRequestHandle, - statusInformation['errorIndication'], 0, 0, (), + cbFun(snmpEngine, + origSendRequestHandle, + statusInformation['errorIndication'], + None, cbCtx) - return + return if origMessageProcessingModel != messageProcessingModel or \ origSecurityModel != securityModel or \ @@ -124,7 +147,12 @@ class CommandGeneratorBase: origContextName and origContextName != contextName or \ origPduVersion != pduVersion: debug.logger & debug.flagApp and debug.logger('processResponsePdu: sendPduHandle %s, request/response data mismatch' % sendPduHandle) - cbFun(origSendRequestHandle, 'badResponse', 0, 0, (), cbCtx) + + cbFun(snmpEngine, + origSendRequestHandle, + 'badResponse', # errorIndication + None, + cbCtx) return # User-side API assumes SMIv2 @@ -134,58 +162,35 @@ class CommandGeneratorBase: # 3.1.2 if v2c.apiPDU.getRequestID(PDU) != v2c.apiPDU.getRequestID(origPdu): debug.logger & debug.flagApp and debug.logger('processResponsePdu: sendPduHandle %s, request-id/response-id mismatch' % sendPduHandle) - cbFun(origSendRequestHandle, 'badResponse', 0, 0, (), cbCtx) + cbFun(snmpEngine, + origSendRequestHandle, + 'badResponse', # errorIndication + None, + cbCtx) return - self._handleResponse( - snmpEngine, - origTransportDomain, - origTransportAddress, - origMessageProcessingModel, - origSecurityModel, - origSecurityName, - origSecurityLevel, - origContextEngineId, - origContextName, - origPdu, - origTimeout, - origRetryCount, - PDU, - origSendRequestHandle, - (cbFun, cbCtx), - ) + cbFun(snmpEngine, + origSendRequestHandle, + None, # errorIndication + PDU, + cbCtx) - def sendReq( - self, - snmpEngine, - addrName, - varBinds, - cbFun, - cbCtx=None, - contextEngineId=None, - contextName='' - ): - raise error.PySnmpError('Method not implemented') - - def _sendPdu( - self, - snmpEngine, - transportDomain, - transportAddress, - messageProcessingModel, - securityModel, - securityName, - securityLevel, - contextEngineId, - contextName, - reqPDU, - timeout, - retryCount, - retries, - sendRequestHandle, - cbInfo - ): - (processResponsePdu, cbCtx) = cbInfo + def sendPdu(self, + snmpEngine, + targetName, + contextEngineId, + contextName, + PDU, + cbFun, + cbCtx): + ( transportDomain, + transportAddress, + timeout, + retryCount, + messageProcessingModel, + securityModel, + securityName, + securityLevel ) = config.getTargetInfo(snmpEngine, targetName) # Convert timeout in seconds into timeout in timer ticks timeoutInTicks = float(timeout)/100/snmpEngine.transportDispatcher.getTimerResolution() @@ -197,15 +202,20 @@ class CommandGeneratorBase: contextEngineId = SnmpEngineID(contextEngineId) contextName = SnmpAdminString(contextName) - origPDU = reqPDU + origPDU = PDU # User-side API assumes SMIv2 if messageProcessingModel == 0: - reqPDU = rfc2576.v2ToV1(reqPDU) + PDU = rfc2576.v2ToV1(PDU) pduVersion = 0 else: pduVersion = 1 + + sendRequestHandle = getNextHandle() + cbCtx = sendRequestHandle, cbFun, cbCtx + cbFun = self.processResponsePdu + # 3.1 sendPduHandle = snmpEngine.msgAndPduDsp.sendPdu( snmpEngine, @@ -218,10 +228,10 @@ class CommandGeneratorBase: contextEngineId, contextName, pduVersion, - reqPDU, + PDU, 1, # expectResponse timeoutInTicks, - processResponsePdu, + cbFun, cbCtx ) @@ -238,290 +248,229 @@ class CommandGeneratorBase: contextName, pduVersion, origPDU, - timeout, + timeoutInTicks, retryCount, - retries, - sendRequestHandle + 0 ) - debug.logger & debug.flagApp and debug.logger('_sendPdu: sendPduHandle %s, timeout %d*10 ms/%d ticks, retry %d of %d' % (sendPduHandle, timeout, timeoutInTicks, retries, retryCount)) - - def _handleResponse( - self, - snmpEngine, - transportDomain, - transportAddress, - messageProcessingModel, - securityModel, - securityName, - securityLevel, - contextEngineId, - contextName, - PDU, - timeout, - retryCount, - rspPDU, - sendRequestHandle, - cbInfo - ): - (cbFun, cbCtx) = cbInfo - cbFun(sendRequestHandle, - None, - v2c.apiPDU.getErrorStatus(rspPDU), - v2c.apiPDU.getErrorIndex(rspPDU, muteErrors=True), - v2c.apiPDU.getVarBinds(rspPDU), - cbCtx) + debug.logger & debug.flagApp and debug.logger('sendPdu: sendPduHandle %s, timeout %d*10 ms/%d ticks, retry %d of %d' % (sendPduHandle, timeout, timeoutInTicks, retries, retryCount)) -class GetCommandGenerator(CommandGeneratorBase): - def sendReq( - self, - snmpEngine, - addrName, - varBinds, - cbFun, - cbCtx=None, - contextEngineId=None, - contextName='' - ): - ( transportDomain, - transportAddress, - timeout, - retryCount, - messageProcessingModel, - securityModel, - securityName, - securityLevel ) = config.getTargetInfo(snmpEngine, addrName) + return sendRequestHandle + +class GetCommandGenerator(CommandGenerator): + def processResponseVarBinds(self, + snmpEngine, + sendRequestHandle, + errorIndication, + PDU, + cbCtx): + cbFun, cbCtx = cbCtx + + cbFun(snmpEngine, + sendRequestHandle, + errorIndication, + PDU and v2c.apiPDU.getErrorStatus(PDU) or 0, + PDU and v2c.apiPDU.getErrorIndex(PDU, muteErrors=True) or 0, + PDU and v2c.apiPDU.getVarBinds(PDU) or (), + cbCtx) + def sendVarBinds(self, + snmpEngine, + targetName, + contextEngineId, + contextName, + varBinds, + cbFun, + cbCtx=None): reqPDU = v2c.GetRequestPDU() v2c.apiPDU.setDefaults(reqPDU) v2c.apiPDU.setVarBinds(reqPDU, varBinds) - sendRequestHandle = getNextHandle() - - try: - self._sendPdu( - snmpEngine, - transportDomain, - transportAddress, - messageProcessingModel, - securityModel, - securityName, - securityLevel, - contextEngineId, - contextName, - reqPDU, - timeout, - retryCount, - 0, # retries - sendRequestHandle, - (self.processResponsePdu, (cbFun, cbCtx)) - ) - except StatusInformation: - statusInformation = sys.exc_info()[1] - debug.logger & debug.flagApp and debug.logger('sendReq: sendPduHandle %s: _sendPdu() failed with %r' % (sendRequestHandle, statusInformation)) - cbFun(sendRequestHandle, statusInformation['errorIndication'], - 0, 0, (), cbCtx) - - return sendRequestHandle - -class SetCommandGenerator(CommandGeneratorBase): - def sendReq( - self, - snmpEngine, - addrName, - varBinds, - cbFun, - cbCtx=None, - contextEngineId=None, - contextName='' - ): - ( transportDomain, - transportAddress, - timeout, - retryCount, - messageProcessingModel, - securityModel, - securityName, - securityLevel ) = config.getTargetInfo(snmpEngine, addrName) + cbCtx = cbFun, cbCtx + cbFun = self.processResponseVarBinds + + return self.sendPdu(snmpEngine, + targetName, + contextEngineId, + contextName, + reqPDU, + cbFun, + cbCtx) + +class SetCommandGenerator(CommandGenerator): + def processResponseVarBinds(self, + snmpEngine, + sendRequestHandle, + errorIndication, + PDU, + cbCtx): + cbFun, cbCtx = cbCtx + + cbFun(snmpEngine, + sendRequestHandle, + errorIndication, + PDU and v2c.apiPDU.getErrorStatus(PDU) or 0, + PDU and v2c.apiPDU.getErrorIndex(PDU, muteErrors=True) or 0, + PDU and v2c.apiPDU.getVarBinds(PDU) or (), + cbCtx) + def sendVarBinds(self, + snmpEngine, + targetName, + contextEngineId, + contextName, + varBinds, + cbFun, + cbCtx=None): reqPDU = v2c.SetRequestPDU() v2c.apiPDU.setDefaults(reqPDU) - + v2c.apiPDU.setVarBinds(reqPDU, varBinds) - sendRequestHandle = getNextHandle() - - try: - self._sendPdu( - snmpEngine, - transportDomain, - transportAddress, - messageProcessingModel, - securityModel, - securityName, - securityLevel, - contextEngineId, - contextName, - reqPDU, - timeout, - retryCount, - 0, # retries - sendRequestHandle, - (self.processResponsePdu, (cbFun, cbCtx)) - ) - except StatusInformation: - statusInformation = sys.exc_info()[1] - debug.logger & debug.flagApp and debug.logger('sendReq: sendPduHandle %s: _sendPdu() failed with %r' % (sendRequestHandle, statusInformation)) - cbFun(sendRequestHandle, statusInformation['errorIndication'], - 0, 0, (), cbCtx) - - return sendRequestHandle - -class NextCommandGeneratorSingleRun(CommandGeneratorBase): - def sendReq( - self, - snmpEngine, - addrName, - varBinds, - cbFun, - cbCtx=None, - contextEngineId=None, - contextName='' - ): - ( transportDomain, - transportAddress, - timeout, - retryCount, - messageProcessingModel, - securityModel, - securityName, - securityLevel ) = config.getTargetInfo(snmpEngine, addrName) - + cbCtx = cbFun, cbCtx + cbFun = self.processResponseVarBinds + + return self.sendPdu(snmpEngine, + targetName, + contextEngineId, + contextName, + reqPDU, + cbFun, + cbCtx) + +class NextCommandGeneratorSingleRun(CommandGenerator): + def processResponseVarBinds(self, + snmpEngine, + sendRequestHandle, + errorIndication, + PDU, + cbCtx): + targetName, contextEngineId, contextName, reqPDU, cbFun, cbCtx = cbCtx + cbFun(snmpEngine, + sendRequestHandle, + errorIndication, + PDU and v2c.apiPDU.getErrorStatus(PDU) or 0, + PDU and v2c.apiPDU.getErrorIndex(PDU, muteErrors=True) or 0, + PDU and v2c.apiPDU.getVarBinds(PDU) or (), + cbCtx) + + def sendVarBinds(self, + snmpEngine, + targetName, + contextEngineId, + contextName, + varBinds, + cbFun, + cbCtx=None): reqPDU = v2c.GetNextRequestPDU() v2c.apiPDU.setDefaults(reqPDU) v2c.apiPDU.setVarBinds(reqPDU, varBinds) - sendRequestHandle = getNextHandle() + cbCtx = targetName, contextEngineId, contextName, reqPDU, cbFun, cbCtx + cbFun = self.processResponseVarBinds - try: - self._sendPdu( - snmpEngine, - transportDomain, - transportAddress, - messageProcessingModel, - securityModel, - securityName, - securityLevel, - contextEngineId, - contextName, - reqPDU, - timeout, - retryCount, - 0, # retries - sendRequestHandle, - (self.processResponsePdu, (cbFun, cbCtx)) - ) - except StatusInformation: - statusInformation = sys.exc_info()[1] - debug.logger & debug.flagApp and debug.logger('sendReq: sendPduHandle %s: _sendPdu() failed with %r' % (sendRequestHandle, statusInformation)) - cbFun(sendRequestHandle, statusInformation['errorIndication'], - 0, 0, (), cbCtx) + return self.sendPdu(snmpEngine, + targetName, + contextEngineId, + contextName, + reqPDU, + cbFun, + cbCtx) - return sendRequestHandle - class NextCommandGenerator(NextCommandGeneratorSingleRun): - def _handleResponse( - self, - snmpEngine, - transportDomain, - transportAddress, - messageProcessingModel, - securityModel, - securityName, - securityLevel, - contextEngineId, - contextName, - PDU, - timeout, - retryCount, - rspPDU, - sendRequestHandle, - cbInfo - ): - (cbFun, cbCtx) = cbInfo - - varBindTable = v2c.apiPDU.getVarBindTable(PDU, rspPDU) - - if v2c.apiPDU.getErrorStatus(rspPDU): + def processResponseVarBinds(self, + snmpEngine, + sendRequestHandle, + errorIndication, + PDU, + cbCtx): + targetName, contextEngineId, contextName, reqPDU, cbFun, cbCtx = cbCtx + + if errorIndication: + cbFun(snmpEngine, + sendRequestHandle, + errorIndication, + 0, 0, (), + cbCtx) + return + + varBindTable = v2c.apiPDU.getVarBindTable(reqPDU, PDU) + + if v2c.apiPDU.getErrorStatus(PDU): errorIndication, varBinds = None, () elif not varBindTable: errorIndication, varBinds = errind.emptyResponse, () else: errorIndication, varBinds = getNextVarBinds( - v2c.apiPDU.getVarBinds(PDU), varBindTable[-1] + v2c.apiPDU.getVarBinds(reqPDU), varBindTable[-1] ) - if not cbFun(sendRequestHandle, errorIndication, - v2c.apiPDU.getErrorStatus(rspPDU), - v2c.apiPDU.getErrorIndex(rspPDU, muteErrors=True), - varBindTable, cbCtx): - debug.logger & debug.flagApp and debug.logger('_handleResponse: sendRequestHandle %s, app says to stop walking' % sendRequestHandle) + if not cbFun(snmpEngine, + sendRequestHandle, + errorIndication, + v2c.apiPDU.getErrorStatus(PDU), + v2c.apiPDU.getErrorIndex(PDU, muteErrors=True), + varBindTable, + cbCtx): + debug.logger & debug.flagApp and debug.logger('processResponseVarBinds: sendRequestHandle %s, app says to stop walking' % sendRequestHandle) return # app says enough if not varBinds: return # no more objects available - - v2c.apiPDU.setRequestID(PDU, v2c.getNextRequestID()) - v2c.apiPDU.setVarBinds(PDU, varBinds) + v2c.apiPDU.setRequestID(reqPDU, v2c.getNextRequestID()) + v2c.apiPDU.setVarBinds(reqPDU, varBinds) + + cbCtx = targetName, contextEngineId, contextName, reqPDU, cbFun, cbCtx + cbFun = self.processResponseVarBinds + try: - self._sendPdu( - snmpEngine, - transportDomain, - transportAddress, - messageProcessingModel, - securityModel, - securityName, - securityLevel, - contextEngineId, - contextName, - PDU, - timeout, - retryCount, - 0, # retries - sendRequestHandle, - (self.processResponsePdu, (cbFun, cbCtx)) - ) + self.sendPdu(snmpEngine, + targetName, + contextEngineId, + contextName, + reqPDU, + cbFun, + cbCtx) + except StatusInformation: statusInformation = sys.exc_info()[1] - debug.logger & debug.flagApp and debug.logger('sendReq: sendPduHandle %s: _sendPdu() failed with %r' % (sendRequestHandle, statusInformation)) - cbFun(sendRequestHandle, statusInformation['errorIndication'], + debug.logger & debug.flagApp and debug.logger('sendVarBinds: sendPduHandle %s: sendPdu() failed with %r' % (sendRequestHandle, statusInformation)) + cbFun(snmpEngine, + sendRequestHandle, + statusInformation['errorIndication'], 0, 0, (), cbCtx) - -class BulkCommandGeneratorSingleRun(CommandGeneratorBase): - def sendReq( - self, - snmpEngine, - addrName, - nonRepeaters, - maxRepetitions, - varBinds, - cbFun, - cbCtx=None, - contextEngineId=None, - contextName='' - ): - ( transportDomain, - transportAddress, - timeout, - retryCount, - messageProcessingModel, - securityModel, - securityName, - securityLevel ) = config.getTargetInfo(snmpEngine, addrName) +class BulkCommandGeneratorSingleRun(CommandGenerator): + def processResponseVarBinds(self, + snmpEngine, + sendRequestHandle, + errorIndication, + PDU, + cbCtx): + ( targetName, nonRepeaters, maxRepetitions, + contextEngineId, contextName, reqPDU, cbFun, cbCtx ) = cbCtx + + cbFun(snmpEngine, + sendRequestHandle, + errorIndication, + PDU and v2c.apiPDU.getErrorStatus(PDU) or 0, + PDU and v2c.apiPDU.getErrorIndex(PDU, muteErrors=True) or 0, + PDU and v2c.apiPDU.getVarBinds(PDU) or (), + cbCtx) + + def sendVarBinds(self, + snmpEngine, + targetName, + nonRepeaters, + maxRepetitions, + contextEngineId, + contextName, + varBinds, + cbFun, + cbCtx=None): reqPDU = v2c.GetBulkRequestPDU() v2c.apiBulkPDU.setDefaults(reqPDU) @@ -530,102 +479,150 @@ class BulkCommandGeneratorSingleRun(CommandGeneratorBase): v2c.apiBulkPDU.setVarBinds(reqPDU, varBinds) - sendRequestHandle = getNextHandle() + cbCtx = ( targetName, nonRepeaters, maxRepetitions, + contextEngineId, contextName, reqPDU, cbFun, cbCtx ) + cbFun = self.processResponseVarBinds + + return self.sendPdu(snmpEngine, + targetName, + contextEngineId, + contextName, + reqPDU, + cbFun, + cbCtx) + +def _sendBulkReq(self, + snmpEngine, + targetName, + nonRepeaters, + maxRepetitions, + varBinds, + cbFun, + cbCtx=None, + contextEngineId=None, + contextName=''): + cbCtx = cbFun, cbCtx + cbFun = __sendReqCbFun + return self.sendVarBinds(snmpEngine, + targetName, + nonRepeaters, + maxRepetitions, + contextEngineId, + contextName, + varBinds, + cbFun, + cbCtx) - try: - self._sendPdu( - snmpEngine, - transportDomain, - transportAddress, - messageProcessingModel, - securityModel, - securityName, - securityLevel, - contextEngineId, - contextName, - reqPDU, - timeout, - retryCount, - 0, # retries - sendRequestHandle, - (self.processResponsePdu, (cbFun, cbCtx)) - ) - except StatusInformation: - statusInformation = sys.exc_info()[1] - debug.logger & debug.flagApp and debug.logger('sendReq: sendPduHandle %s: _sendPdu() failed with %r' % (sendRequestHandle, statusInformation)) - cbFun(sendRequestHandle, statusInformation['errorIndication'], - 0, 0, (), cbCtx) - - return sendRequestHandle - class BulkCommandGenerator(BulkCommandGeneratorSingleRun): - def _handleResponse( - self, - snmpEngine, - transportDomain, - transportAddress, - messageProcessingModel, - securityModel, - securityName, - securityLevel, - contextEngineId, - contextName, - PDU, - timeout, - retryCount, - rspPDU, - sendRequestHandle, - cbInfo - ): - (cbFun, cbCtx) = cbInfo - varBindTable = v2c.apiBulkPDU.getVarBindTable(PDU, rspPDU) - - if v2c.apiBulkPDU.getErrorStatus(rspPDU): + def processResponseVarBinds(self, + snmpEngine, + sendRequestHandle, + errorIndication, + PDU, + cbCtx): + ( targetName, nonRepeaters, maxRepetitions, + contextEngineId, contextName, reqPDU, cbFun, cbCtx ) = cbCtx + + if errorIndication: + cbFun(snmpEngine, + sendRequestHandle, + errorIndication, + 0, 0, (), + cbCtx) + return + + varBindTable = v2c.apiBulkPDU.getVarBindTable(reqPDU, PDU) + + if v2c.apiBulkPDU.getErrorStatus(PDU): errorIndication, varBinds = None, () elif not varBindTable: errorIndication, varBinds = errind.emptyResponse, () else: errorIndication, varBinds = getNextVarBinds( - v2c.apiBulkPDU.getVarBinds(PDU), varBindTable[-1] + v2c.apiBulkPDU.getVarBinds(reqPDU), varBindTable[-1] ) - nonRepeaters = v2c.apiBulkPDU.getNonRepeaters(PDU) + nonRepeaters = v2c.apiBulkPDU.getNonRepeaters(reqPDU) if nonRepeaters: - varBinds = v2c.apiBulkPDU.getVarBinds(PDU)[:nonRepeaters] + \ + varBinds = v2c.apiBulkPDU.getVarBinds(reqPDU)[:nonRepeaters]+\ varBinds[nonRepeaters:] - if not cbFun(sendRequestHandle, errorIndication, - v2c.apiBulkPDU.getErrorStatus(rspPDU), - v2c.apiBulkPDU.getErrorIndex(rspPDU, muteErrors=True), + if not cbFun(snmpEngine, + sendRequestHandle, + errorIndication, + v2c.apiBulkPDU.getErrorStatus(PDU), + v2c.apiBulkPDU.getErrorIndex(PDU, muteErrors=True), varBindTable, cbCtx): - debug.logger & debug.flagApp and debug.logger('_handleResponse: sendRequestHandle %s, app says to stop walking' % sendRequestHandle) + debug.logger & debug.flagApp and debug.logger('processResponseVarBinds: sendRequestHandle %s, app says to stop walking' % sendRequestHandle) return # app says enough if not varBinds: return # no more objects available - v2c.apiBulkPDU.setRequestID(PDU, v2c.getNextRequestID()) - v2c.apiBulkPDU.setVarBinds(PDU, varBinds) + v2c.apiBulkPDU.setRequestID(reqPDU, v2c.getNextRequestID()) + v2c.apiBulkPDU.setVarBinds(reqPDU, varBinds) + + cbCtx = ( targetName, nonRepeaters, maxRepetitions, + contextEngineId, contextName, reqPDU, cbFun, cbCtx ) + cbFun = self.processResponseVarBinds + + try: + self.sendPdu(snmpEngine, + targetName, + contextEngineId, + contextName, + reqPDU, + cbFun, + cbCtx) - try: - self._sendPdu( - snmpEngine, - transportDomain, - transportAddress, - messageProcessingModel, - securityModel, - securityName, - securityLevel, - contextEngineId, - contextName, - PDU, - timeout, - retryCount, - 0, # retries - sendRequestHandle, - (self.processResponsePdu, (cbFun, cbCtx)) - ) except StatusInformation: statusInformation = sys.exc_info()[1] - debug.logger & debug.flagApp and debug.logger('sendReq: sendPduHandle %s: _sendPdu() failed with %r' % (sendRequestHandle, statusInformation)) - cbFun(sendRequestHandle, statusInformation['errorIndication'], + debug.logger & debug.flagApp and debug.logger('processResponseVarBinds: sendPduHandle %s: _sendPdu() failed with %r' % (sendRequestHandle, statusInformation)) + cbFun(snmpEngine, + sendRequestHandle, + statusInformation['errorIndication'], 0, 0, (), cbCtx) + +# +# Obsolete, compatibility interfaces. +# + +def __sendReqCbFun(snmpEngine, + sendRequestHandle, + errorIndication, + errorStatus, + errorIndex, + PDU, + cbCtx): + cbFun, cbCtx = cbCtx + return cbFun(sendRequestHandle, + errorIndication, + errorStatus, + errorIndex, + PDU, + cbCtx) + +def _sendReq(self, + snmpEngine, + targetName, + varBinds, + cbFun, + cbCtx=None, + contextEngineId=None, + contextName=''): + cbCtx = cbFun, cbCtx + cbFun = __sendReqCbFun + return self.sendVarBinds(snmpEngine, + targetName, + contextEngineId, + contextName, + varBinds, + cbFun, + cbCtx) + +# 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/ntforg.py b/pysnmp/entity/rfc3413/ntforg.py index 1e278cf..422c2cf 100644 --- a/pysnmp/entity/rfc3413/ntforg.py +++ b/pysnmp/entity/rfc3413/ntforg.py @@ -2,6 +2,7 @@ import sys from pyasn1.compat.octets import null from pysnmp.entity.rfc3413 import config from pysnmp.proto.proxy import rfc2576 +from pysnmp.proto import rfc3411 from pysnmp.proto.api import v2c from pysnmp.proto import error from pysnmp import nextid @@ -11,26 +12,25 @@ getNextHandle = nextid.Integer(0x7fffffff) class NotificationOriginator: acmID = 3 # default MIB access control method to use - def __init__(self, snmpContext): + def __init__(self, snmpContext=None): self.__pendingReqs = {} + self.__metaSendPduHandles = {} self.__pendingNotifications = {} - self.snmpContext = snmpContext - - def processResponsePdu( - self, - snmpEngine, - messageProcessingModel, - securityModel, - securityName, - securityLevel, - contextEngineId, - contextName, - pduVersion, - PDU, - statusInformation, - sendPduHandle, - cbInfo - ): + self.snmpContext = snmpContext # this is deprecated + + def processResponsePdu(self, + snmpEngine, + messageProcessingModel, + securityModel, + securityName, + securityLevel, + contextEngineId, + contextName, + pduVersion, + PDU, + statusInformation, + sendPduHandle, + cbInfo): (cbFun, cbCtx) = cbInfo # 3.3.6d if sendPduHandle not in self.__pendingReqs: @@ -47,11 +47,9 @@ class NotificationOriginator: origPdu, origTimeout, origRetryCount, - origRetries, - metaSendPduHandle - ) = self.__pendingReqs[sendPduHandle] + origRetries ) = self.__pendingReqs.pop(sendPduHandle) - del self.__pendingReqs[sendPduHandle] + metaSendPduHandle = self.__metaSendPduHandles.pop(sendPduHandle) self.__pendingNotifications[metaSendPduHandle] -= 1 @@ -63,13 +61,11 @@ class NotificationOriginator: debug.logger & debug.flagApp and debug.logger('processResponsePdu: metaSendPduHandle %s, sendPduHandle %s retry count %d exceeded' % (metaSendPduHandle, sendPduHandle, origRetries)) if not self.__pendingNotifications[metaSendPduHandle]: del self.__pendingNotifications[metaSendPduHandle] - self._handleResponse( - metaSendPduHandle, - statusInformation['errorIndication'], - 0, 0, (), - cbFun, - cbCtx - ) + cbFun(snmpEngine, + metaSendPduHandle, + statusInformation['errorIndication'], + None, + cbCtx) return # Convert timeout in seconds into timeout in timer ticks @@ -107,13 +103,11 @@ class NotificationOriginator: debug.logger & debug.flagApp and debug.logger('processResponsePdu: metaSendPduHandle %s: sendPdu() failed with %r ' % (metaSendPduHandle, statusInformation)) if not self.__pendingNotifications[metaSendPduHandle]: del self.__pendingNotifications[metaSendPduHandle] - self._handleResponse( - metaSendPduHandle, - statusInformation['errorIndication'], - 0, 0, (), - cbFun, - cbCtx - ) + cbFun(snmpEngine, + metaSendPduHandle, + statusInformation['errorIndication'], + None, + cbCtx) return self.__pendingNotifications[metaSendPduHandle] += 1 @@ -135,9 +129,10 @@ class NotificationOriginator: origPdu, origTimeout, origRetryCount, - origRetries + 1, - metaSendPduHandle + origRetries + 1 ) + self.__metaSendPduHandles[sendPduHandle] = metaSendPduHandle + return # 3.3.6c @@ -148,38 +143,125 @@ class NotificationOriginator: if messageProcessingModel == 0: PDU = rfc2576.v1ToV2(PDU, origPdu) - self._handleResponse(metaSendPduHandle, None, - v2c.apiPDU.getErrorStatus(PDU), - v2c.apiPDU.getErrorIndex(PDU,muteErrors=True), - v2c.apiPDU.getVarBinds(PDU), - cbFun, cbCtx) - - def _handleResponse(self, - sendRequestHandle, - errorIndication, - errorStatus, errorIndex, - varBinds, - cbFun, cbCtx): - try: - # we need to pass response PDU information to user for INFORMs - cbFun(sendRequestHandle, errorIndication, - errorStatus, errorIndex, varBinds, cbCtx) - except TypeError: - # a backward compatible way of calling user function - cbFun(sendRequestHandle, errorIndication, cbCtx) + cbFun(snmpEngine, metaSendPduHandle, None, PDU, cbCtx) + + def sendPdu(self, + snmpEngine, + targetName, + contextEngineId, + contextName, + pdu, + cbFun=None, + cbCtx=None): + ( transportDomain, + transportAddress, + timeout, + retryCount, + params ) = config.getTargetAddr(snmpEngine, targetName) + + ( messageProcessingModel, + securityModel, + securityName, + securityLevel ) = config.getTargetParams(snmpEngine, params) + + # User-side API assumes SMIv2 + if messageProcessingModel == 0: + reqPDU = rfc2576.v2ToV1(pdu) + pduVersion = 0 + else: + reqPDU = pdu + pduVersion = 1 + + # 3.3.5 + if reqPDU.tagSet in rfc3411.confirmedClassPDUs: + # Convert timeout in seconds into timeout in timer ticks + timeoutInTicks = float(timeout)/100/snmpEngine.transportDispatcher.getTimerResolution() + + cbCtx = cbFun, cbCtx + cbFun = self.processResponsePdu + + # 3.3.6a + sendPduHandle = snmpEngine.msgAndPduDsp.sendPdu(snmpEngine, + transportDomain, + transportAddress, + messageProcessingModel, + securityModel, + securityName, + securityLevel, + contextEngineId, + contextName, + pduVersion, + reqPDU, + # expectResponse + 1, + timeoutInTicks, + cbFun, + cbCtx) + + debug.logger & debug.flagApp and debug.logger('sendVarBinds: sendPduHandle %s, timeout %d' % (sendPduHandle, timeout)) + + # 3.3.6b + self.__pendingReqs[sendPduHandle] = ( + transportDomain, + transportAddress, + messageProcessingModel, + securityModel, + securityName, + securityLevel, + contextEngineId, + contextName, + pdu, + timeout, + retryCount, + 1 + ) + snmpEngine.transportDispatcher.jobStarted(id(self)) + else: + snmpEngine.msgAndPduDsp.sendPdu(snmpEngine, + transportDomain, + transportAddress, + messageProcessingModel, + securityModel, + securityName, + securityLevel, + contextEngineId, + contextName, + pduVersion, + reqPDU, + None) # do not expectResponse + + sendPduHandle = None + + debug.logger & debug.flagApp and debug.logger('sendVarBinds: message sent') + + return sendPduHandle + + def processResponseVarBinds(self, + snmpEngine, + metaSendPduHandle, + errorIndication, + pdu, + cbCtx): + cbFun, cbCtx = cbCtx + cbFun(snmpEngine, + metaSendPduHandle, + errorIndication, + pdu and v2c.apiPDU.getErrorStatus(pdu) or 0, + pdu and v2c.apiPDU.getErrorIndex(pdu, muteErrors=True) or 0, + pdu and v2c.apiPDU.getVarBinds(pdu) or (), + cbCtx) - def sendNotification( - self, - snmpEngine, - notificationTarget, - notificationName, - additionalVarBinds=(), - cbFun=None, - cbCtx=None, - contextName=null, - instanceIndex=None - ): - debug.logger & debug.flagApp and debug.logger('sendNotification: notificationTarget %s, notificationName %s, additionalVarBinds %s, contextName "%s", instanceIndex %s' % (notificationTarget, notificationName, additionalVarBinds, contextName, instanceIndex)) + def sendVarBinds(self, + snmpEngine, + snmpContext, + contextName, + notificationTarget, + notificationName, + instanceIndex, + additionalVarBinds=(), + cbFun=None, + cbCtx=None): + debug.logger & debug.flagApp and debug.logger('sendVarBinds: notificationTarget %s, notificationName %s, additionalVarBinds %s, contextName "%s", instanceIndex %s' % (notificationTarget, notificationName, additionalVarBinds, contextName, instanceIndex)) if contextName: __SnmpAdminString, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('SNMP-FRAMEWORK-MIB', 'SnmpAdminString') @@ -188,14 +270,14 @@ class NotificationOriginator: # 3.3 ( notifyTag, notifyType ) = config.getNotificationInfo( - snmpEngine, notificationTarget + snmpEngine, notificationTarget ) metaSendPduHandle = getNextHandle() - debug.logger & debug.flagApp and debug.logger('sendNotification: metaSendPduHandle %s, notifyTag %s, notifyType %s' % (metaSendPduHandle, notifyTag, notifyType)) + debug.logger & debug.flagApp and debug.logger('sendVarBinds: metaSendPduHandle %s, notifyTag %s, notifyType %s' % (metaSendPduHandle, notifyTag, notifyType)) - contextMibInstrumCtl = self.snmpContext.getMibInstrum(contextName) + contextMibInstrumCtl = snmpContext.getMibInstrum(contextName) additionalVarBinds = [ (v2c.ObjectIdentifier(x),y) for x,y in additionalVarBinds ] @@ -210,7 +292,7 @@ class NotificationOriginator: securityName, securityLevel ) = config.getTargetParams(snmpEngine, params) - debug.logger & debug.flagApp and debug.logger('sendNotification: metaSendPduHandle %s, notifyTag %s yields: transportDomain %s, transportAddress %r, securityModel %s, securityName %s, securityLevel %s' % (metaSendPduHandle, notifyTag, transportDomain, transportAddress, securityModel, securityName, securityLevel)) + debug.logger & debug.flagApp and debug.logger('sendVarBinds: metaSendPduHandle %s, notifyTag %s yields: transportDomain %s, transportAddress %r, securityModel %s, securityName %s, securityLevel %s' % (metaSendPduHandle, notifyTag, transportDomain, transportAddress, securityModel, securityName, securityLevel)) # 3.3.1 XXX # XXX filtering's yet to be implemented @@ -237,7 +319,7 @@ class NotificationOriginator: if len(notificationName) == 2: # ('MIB', 'symbol') notificationTypeObject, = contextMibInstrumCtl.mibBuilder.importSymbols(*notificationName) varBinds.append((snmpTrapOid.name, v2c.ObjectIdentifier(notificationTypeObject.name))) - debug.logger & debug.flagApp and debug.logger('sendNotification: notification type object is %s' % notificationTypeObject) + debug.logger & debug.flagApp and debug.logger('sendVarBinds: notification type object is %s' % notificationTypeObject) for notificationObject in notificationTypeObject.getObjects(): mibNode, = contextMibInstrumCtl.mibBuilder.importSymbols(*notificationObject) if instanceIndex: @@ -245,7 +327,7 @@ class NotificationOriginator: else: mibNode = mibNode.getNextNode(mibNode.name) varBinds.append((mibNode.name, mibNode.syntax)) - debug.logger & debug.flagApp and debug.logger('sendNotification: processed notification object %s, instance index %s, var-bind %s' % (notificationObject, instanceIndex is None and "<first>" or instanceIndex, mibNode)) + debug.logger & debug.flagApp and debug.logger('sendVarBinds: processed notification object %s, instance index %s, var-bind %s' % (notificationObject, instanceIndex is None and "<first>" or instanceIndex, mibNode)) elif notificationName: # numeric OID varBinds.append( (snmpTrapOid.name, @@ -263,7 +345,7 @@ class NotificationOriginator: securityLevel, 'notify', contextName, varName ) except error.StatusInformation: - debug.logger & debug.flagApp and debug.logger('sendNotification: OID %s not allowed for %s, droppping notification' % (varName, securityName)) + debug.logger & debug.flagApp and debug.logger('sendVarBinds: OID %s not allowed for %s, droppping notification' % (varName, securityName)) return else: varBinds.append((varName, varVal)) @@ -274,118 +356,101 @@ class NotificationOriginator: elif notifyType == 2: pdu = v2c.InformRequestPDU() else: - raise RuntimeError() + raise error.ProtocolError('Unknown notify-type %r', notifyType) + v2c.apiPDU.setDefaults(pdu) v2c.apiPDU.setVarBinds(pdu, varBinds) - # User-side API assumes SMIv2 - if messageProcessingModel == 0: - reqPDU = rfc2576.v2ToV1(pdu) - pduVersion = 0 - else: - reqPDU = pdu - pduVersion = 1 + cbCtx = cbFun, cbCtx + cbFun = self.processResponseVarBinds # 3.3.5 - if notifyType == 1: - try: - snmpEngine.msgAndPduDsp.sendPdu( - snmpEngine, - transportDomain, - transportAddress, - messageProcessingModel, - securityModel, - securityName, - securityLevel, - self.snmpContext.contextEngineId, - contextName, - pduVersion, - reqPDU, - None + try: + sendPduHandle = self.sendPdu(snmpEngine, + targetAddrName, + snmpContext.contextEngineId, + contextName, + pdu, + cbFun, + cbCtx) + + except error.StatusInformation: + statusInformation = sys.exc_info()[1] + debug.logger & debug.flagApp and debug.logger('sendVarBinds: metaSendPduHandle %s: sendVarBindsPdu() failed with %r' % (metaSendPduHandle, statusInformation)) + if metaSendPduHandle not in self.__pendingNotifications or \ + not self.__pendingNotifications[metaSendPduHandle]: + if metaSendPduHandle in self.__pendingNotifications: + del self.__pendingNotifications[metaSendPduHandle] + self._handleResponse( + metaSendPduHandle, + statusInformation['errorIndication'], + 0, 0, (), + cbFun, + cbCtx ) - except error.StatusInformation: - statusInformation = sys.exc_info()[1] - debug.logger & debug.flagApp and debug.logger('sendReq: metaSendPduHandle %s: sendPdu() failed with %r' % (metaSendPduHandle, statusInformation)) - if metaSendPduHandle not in self.__pendingNotifications or \ - not self.__pendingNotifications[metaSendPduHandle]: - if metaSendPduHandle in self.__pendingNotifications: - del self.__pendingNotifications[metaSendPduHandle] - self._handleResponse( - metaSendPduHandle, - statusInformation['errorIndication'], - 0, 0, (), - cbFun, - cbCtx - ) - return metaSendPduHandle - else: - # Convert timeout in seconds into timeout in timer ticks - timeoutInTicks = float(timeout)/100/snmpEngine.transportDispatcher.getTimerResolution() + return metaSendPduHandle - # 3.3.6a - try: - sendPduHandle = snmpEngine.msgAndPduDsp.sendPdu( - snmpEngine, - transportDomain, - transportAddress, - messageProcessingModel, - securityModel, - securityName, - securityLevel, - self.snmpContext.contextEngineId, - contextName, - pduVersion, - reqPDU, - 1, # expectResponse - timeoutInTicks, - self.processResponsePdu, - (cbFun, cbCtx) - ) - except error.StatusInformation: - statusInformation = sys.exc_info()[1] - debug.logger & debug.flagApp and debug.logger('sendReq: metaSendPduHandle %s: sendPdu() failed with %r' % (metaSendPduHandle, statusInformation)) - if metaSendPduHandle not in self.__pendingNotifications or \ - not self.__pendingNotifications[metaSendPduHandle]: - if metaSendPduHandle in self.__pendingNotifications: - del self.__pendingNotifications[metaSendPduHandle] - self._handleResponse( - metaSendPduHandle, - statusInformation['errorIndication'], - 0, 0, (), - cbFun, - cbCtx - ) - return metaSendPduHandle + debug.logger & debug.flagApp and debug.logger('sendVarBinds: metaSendPduHandle %s, timeout %d' % (metaSendPduHandle, timeout)) - debug.logger & debug.flagApp and debug.logger('sendNotification: metaSendPduHandle %s, sendPduHandle %s, timeout %d' % (metaSendPduHandle, sendPduHandle, timeout)) - - # 3.3.6b - self.__pendingReqs[sendPduHandle] = ( - transportDomain, - transportAddress, - messageProcessingModel, - securityModel, - securityName, - securityLevel, - self.snmpContext.contextEngineId, - contextName, - pdu, - timeout, - retryCount, - 1, - metaSendPduHandle - ) - + if notifyType == 2: if metaSendPduHandle not in self.__pendingNotifications: self.__pendingNotifications[metaSendPduHandle] = 0 self.__pendingNotifications[metaSendPduHandle] += 1 - - snmpEngine.transportDispatcher.jobStarted(id(self)) - - debug.logger & debug.flagApp and debug.logger('sendNotification: metaSendPduHandle %s, notification(s) sent' % metaSendPduHandle) + self.__metaSendPduHandles[sendPduHandle] = metaSendPduHandle + + debug.logger & debug.flagApp and debug.logger('sendVarBinds: metaSendPduHandle %s, notification(s) sent' % metaSendPduHandle) return metaSendPduHandle +# +# Obsolete, compatibility interfaces. +# + +def _sendNotificationCbFun(snmpEngine, + sendRequestHandle, + errorIndication, + errorStatus, + errorIndex, + varBinds, + cbCtx): + cbFun, cbCtx = cbCtx + + try: + # we need to pass response PDU information to user for INFORMs + cbFun(sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBinds, cbCtx) + except TypeError: + # a backward compatible way of calling user function + cbFun(sendRequestHandle, errorIndication, cbCtx) + +def _sendNotification(self, + snmpEngine, + notificationTarget, + notificationName, + additionalVarBinds=(), + cbFun=None, + cbCtx=None, + contextName=null, + instanceIndex=None): + if self.snmpContext is None: + raise error.ProtocolError('SNMP context not specified') + + cbCtx = cbFun, cbCtx + cbFun = _sendNotificationCbFun + + return self.sendVarBinds(snmpEngine, + self.snmpContext, + contextName, + notificationTarget, + notificationName, + instanceIndex, + additionalVarBinds, + cbFun, + cbCtx) + +# install compatibility wrapper +NotificationOriginator.sendNotification = _sendNotification + # XXX # move/group/implement config setting/retrieval at a stand-alone module diff --git a/pysnmp/entity/rfc3413/oneliner/ntforg.py b/pysnmp/entity/rfc3413/oneliner/ntforg.py index 5075001..6e933c5 100644 --- a/pysnmp/entity/rfc3413/oneliner/ntforg.py +++ b/pysnmp/entity/rfc3413/oneliner/ntforg.py @@ -114,16 +114,18 @@ class AsyncNotificationOriginator(cmdgen.AsyncCommandGenerator): def sendNotification(self, snmpEngine, snmpContext, authData, transportTarget, - notifyType, notificationType, + notifyType, + notificationType, instanceIndex, varBinds=(), cbInfo=(None, None), lookupNames=False, lookupValues=False, contextName=null): - def __cbFun(sendRequestHandle, errorIndication, + def __cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx): lookupNames, lookupValues, cbFun, cbCtx = cbCtx return cbFun and cbFun( + snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, @@ -153,7 +155,7 @@ class AsyncNotificationOriginator(cmdgen.AsyncCommandGenerator): cache['mibViewController'], oidOnly=True ) - return ntforg.NotificationOriginator(snmpContext).sendNotification(snmpEngine, notifyName, notificationType, self.makeVarBinds(snmpEngine, varBinds), __cbFun, (lookupNames, lookupValues, cbFun, cbCtx), contextName) + return ntforg.NotificationOriginator().sendVarBinds(snmpEngine, snmpContext, contextName, notifyName, notificationType, instanceIndex, self.makeVarBinds(snmpEngine, varBinds), __cbFun, (lookupNames, lookupValues, cbFun, cbCtx)) # substitute sendNotification return object for backward compatibility class ErrorIndicationReturn: @@ -198,7 +200,7 @@ class AsynNotificationOriginator(cmdgen.AsynCommandGenerator): lookupNames=False, lookupValues=False, contextName=null): - def __cbFun(sendRequestHandle, errorIndication, + def __cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx): cbFun, cbCtx = cbCtx try: @@ -230,7 +232,7 @@ class AsynNotificationOriginator(cmdgen.AsynCommandGenerator): return self.__asyncNtfOrg.sendNotification( self.snmpEngine, self.snmpContext, authData, transportTarget, - notifyType, notificationType, varBinds, + notifyType, notificationType, None, varBinds, (__cbFun, cbInfo), lookupNames, lookupValues, contextName ) |