summaryrefslogtreecommitdiff
path: root/pysnmp
diff options
context:
space:
mode:
Diffstat (limited to 'pysnmp')
-rw-r--r--pysnmp/entity/config.py3
-rw-r--r--pysnmp/entity/rfc3413/cmdrsp.py139
-rw-r--r--pysnmp/smi/instrum.py30
3 files changed, 101 insertions, 71 deletions
diff --git a/pysnmp/entity/config.py b/pysnmp/entity/config.py
index 63bed7c6..ca1d82ed 100644
--- a/pysnmp/entity/config.py
+++ b/pysnmp/entity/config.py
@@ -422,7 +422,8 @@ def delContext(snmpEngine, contextName):
vacmContextEntry, tblIdx = __cookVacmContextInfo(snmpEngine, contextName)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- (vacmContextEntry.name + (2,) + tblIdx, 'destroy')
+ (vacmContextEntry.name + (2,) + tblIdx, 'destroy'),
+ ** dict(snmpEngine=snmpEngine)
)
diff --git a/pysnmp/entity/rfc3413/cmdrsp.py b/pysnmp/entity/rfc3413/cmdrsp.py
index 3d2cb5ab..8f6bbab5 100644
--- a/pysnmp/entity/rfc3413/cmdrsp.py
+++ b/pysnmp/entity/rfc3413/cmdrsp.py
@@ -25,8 +25,7 @@ class CommandResponderBase(object):
self.cbCtx = cbCtx
self.__pendingReqs = {}
- def handleMgmtOperation(self, snmpEngine, stateReference,
- contextName, PDU, acCtx):
+ def initiateMgmtOperation(self, snmpEngine, stateReference, contextName, PDU):
pass
def close(self, snmpEngine):
@@ -147,7 +146,7 @@ class CommandResponderBase(object):
'processPdu: stateReference %s, varBinds %s' % (stateReference, varBinds))
try:
- self.handleMgmtOperation(snmpEngine, stateReference, contextName, PDU)
+ self.initiateMgmtOperation(snmpEngine, stateReference, contextName, PDU)
# SNMPv2 SMI exceptions
except pysnmp.smi.error.GenError:
@@ -263,53 +262,79 @@ class CommandResponderBase(object):
class GetCommandResponder(CommandResponderBase):
pduTypes = (rfc1905.GetRequestPDU.tagSet,)
+ def completeMgmtOperation(self, varBinds, **context):
+ self.sendVarBinds(context['snmpEngine'], context['stateReference'],
+ 0, 0, varBinds)
+ self.releaseStateInformation(context['stateReference'])
+
# rfc1905: 4.2.1
- def handleMgmtOperation(self, snmpEngine, stateReference, contextName, PDU):
+ def initiateMgmtOperation(self, snmpEngine, stateReference, contextName, PDU):
# rfc1905: 4.2.1.1
mgmtFun = self.snmpContext.getMibInstrum(contextName).readVars
varBinds = v2c.apiPDU.getVarBinds(PDU)
- context = dict(snmpEngine=snmpEngine, acFun=self.verifyAccess, cbCtx=self.cbCtx)
-
- rspVarBinds = mgmtFun(*varBinds, **context)
+ context = dict(snmpEngine=snmpEngine,
+ stateReference=stateReference,
+ acFun=self.verifyAccess,
+ cbFun=self.completeMgmtOperation,
+ cbCtx=self.cbCtx)
- self.sendVarBinds(snmpEngine, stateReference, 0, 0, rspVarBinds)
- self.releaseStateInformation(stateReference)
+ mgmtFun(*varBinds, **context)
class NextCommandResponder(CommandResponderBase):
pduTypes = (rfc1905.GetNextRequestPDU.tagSet,)
+ def completeMgmtOperation(self, varBinds, **context):
+ self.sendVarBinds(context['snmpEngine'], context['stateReference'],
+ 0, 0, varBinds)
+ self.releaseStateInformation(context['stateReference'])
+
# rfc1905: 4.2.2
- def handleMgmtOperation(self, snmpEngine, stateReference, contextName, PDU):
+ def initiateMgmtOperation(self, snmpEngine, stateReference, contextName, PDU):
# rfc1905: 4.2.2.1
mgmtFun = self.snmpContext.getMibInstrum(contextName).readNextVars
varBinds = v2c.apiPDU.getVarBinds(PDU)
- context = dict(snmpEngine=snmpEngine, acFun=self.verifyAccess, cbCtx=self.cbCtx)
-
- while True:
- rspVarBinds = mgmtFun(*varBinds, **context)
+ context = dict(snmpEngine=snmpEngine,
+ stateReference=stateReference,
+ acFun=self.verifyAccess,
+ cbFun=self.completeMgmtOperation,
+ cbCtx=self.cbCtx)
- try:
- self.sendVarBinds(snmpEngine, stateReference, 0, 0, rspVarBinds)
-
- except error.StatusInformation:
- idx = sys.exc_info()[1]['idx']
- varBinds[idx] = (rspVarBinds[idx][0], varBinds[idx][1])
- else:
- break
-
- self.releaseStateInformation(stateReference)
+ mgmtFun(*varBinds, **context)
class BulkCommandResponder(CommandResponderBase):
pduTypes = (rfc1905.GetBulkRequestPDU.tagSet,)
maxVarBinds = 64
+ def _completeNonRepeaters(self, varBinds, **context):
+ context['rspVarBinds'][:] = varBinds
+ context['cbFun'] = self.completeMgmtOperation
+
+ mgmtFun = self.snmpContext.getMibInstrum(context['contextName']).readNextVars
+
+ mgmtFun(*context['varBinds'], **context)
+
+ def completeMgmtOperation(self, varBinds, **context):
+ context['rspVarBinds'].extend(varBinds)
+ context['counters']['M'] -= 1
+
+ if context['counters']['M'] and context['counters']['R']:
+ mgmtFun = self.snmpContext.getMibInstrum(context['contextName']).readNextVars
+
+ context['cbFun'] = self.completeMgmtOperation
+ mgmtFun(*varBinds[-context['counters']['R']:], **context)
+
+ else:
+ self.sendVarBinds(context['snmpEngine'], context['stateReference'],
+ 0, 0, varBinds)
+ self.releaseStateInformation(context['stateReference'])
+
# rfc1905: 4.2.3
- def handleMgmtOperation(self, snmpEngine, stateReference, contextName, PDU):
+ def initiateMgmtOperation(self, snmpEngine, stateReference, contextName, PDU):
nonRepeaters = v2c.apiBulkPDU.getNonRepeaters(PDU)
if nonRepeaters < 0:
nonRepeaters = 0
@@ -318,68 +343,60 @@ class BulkCommandResponder(CommandResponderBase):
if maxRepetitions < 0:
maxRepetitions = 0
- reqVarBinds = v2c.apiPDU.getVarBinds(PDU)
+ varBinds = v2c.apiPDU.getVarBinds(PDU)
- N = min(int(nonRepeaters), len(reqVarBinds))
+ N = min(int(nonRepeaters), len(varBinds))
M = int(maxRepetitions)
- R = max(len(reqVarBinds) - N, 0)
+ R = max(len(varBinds) - N, 0)
if R:
M = min(M, self.maxVarBinds // R)
- debug.logger & debug.flagApp and debug.logger('handleMgmtOperation: N %d, M %d, R %d' % (N, M, R))
+ debug.logger & debug.flagApp and debug.logger(
+ 'initiateMgmtOperation: N %d, M %d, R %d' % (N, M, R))
mgmtFun = self.snmpContext.getMibInstrum(contextName).readNextVars
- context = dict(snmpEngine=snmpEngine, acFun=self.verifyAccess, cbCtx=self.cbCtx)
-
- if N:
- # TODO(etingof): manage all PDU var-binds in a single call
- rspVarBinds = mgmtFun(*reqVarBinds[:N], **context)
-
- else:
- rspVarBinds = []
+ context = dict(snmpEngine=snmpEngine,
+ stateReference=stateReference,
+ contextName=contextName,
+ acFun=self.verifyAccess,
+ cbFun=self._completeNonRepeaters,
+ cbCtx=self.cbCtx,
+ varBinds=varBinds[-R:],
+ counters={'M': M, 'R': R},
+ rspVarBinds=[])
- varBinds = reqVarBinds[-R:]
-
- while M and R:
- rspVarBinds.extend(mgmtFun(*varBinds, **context))
- varBinds = rspVarBinds[-R:]
- M -= 1
-
- if len(rspVarBinds):
- self.sendVarBinds(snmpEngine, stateReference, 0, 0, rspVarBinds)
- self.releaseStateInformation(stateReference)
- else:
- raise pysnmp.smi.error.SmiError()
+ mgmtFun(*varBinds[:N], **context)
class SetCommandResponder(CommandResponderBase):
pduTypes = (rfc1905.SetRequestPDU.tagSet,)
+ def completeMgmtOperation(self, varBinds, **context):
+ self.sendVarBinds(context['snmpEngine'], context['stateReference'],
+ 0, 0, varBinds)
+ self.releaseStateInformation(context['stateReference'])
+
# rfc1905: 4.2.5
- def handleMgmtOperation(self, snmpEngine, stateReference, contextName, PDU):
+ def initiateMgmtOperation(self, snmpEngine, stateReference, contextName, PDU):
mgmtFun = self.snmpContext.getMibInstrum(contextName).writeVars
varBinds = v2c.apiPDU.getVarBinds(PDU)
- instrumError = None
-
- context = dict(snmpEngine=snmpEngine, acFun=self.verifyAccess, cbCtx=self.cbCtx)
+ context = dict(snmpEngine=snmpEngine,
+ stateReference=stateReference,
+ acFun=self.verifyAccess,
+ cbFun=self.completeMgmtOperation,
+ cbCtx=self.cbCtx)
# rfc1905: 4.2.5.1-13
try:
- rspVarBinds = mgmtFun(*varBinds, **context)
+ mgmtFun(*varBinds, **context)
except (pysnmp.smi.error.NoSuchObjectError,
pysnmp.smi.error.NoSuchInstanceError):
instrumError = pysnmp.smi.error.NotWritableError()
instrumError.update(sys.exc_info()[1])
-
- else:
- self.sendVarBinds(snmpEngine, stateReference, 0, 0, rspVarBinds)
-
- self.releaseStateInformation(stateReference)
-
- if instrumError:
+ self.releaseStateInformation(stateReference)
raise instrumError
diff --git a/pysnmp/smi/instrum.py b/pysnmp/smi/instrum.py
index 84902025..d84493ac 100644
--- a/pysnmp/smi/instrum.py
+++ b/pysnmp/smi/instrum.py
@@ -184,15 +184,25 @@ class MibInstrumController(AbstractMibInstrumController):
# MIB instrumentation
def flipFlopFsm(self, fsmTable, *varBinds, **context):
- self.__indexMib()
- debug.logger & debug.flagIns and debug.logger('flipFlopFsm: input var-binds %r' % (varBinds,))
+ try:
+ fsmContext = context['fsmState']
+
+ except KeyError:
+ self.__indexMib()
+
+ fsmContext = context['fsmState'] = dict(varBinds=[], state='start', status='ok')
+
+ debug.logger & debug.flagIns and debug.logger('flipFlopFsm: input var-binds %r' % (varBinds,))
mibTree, = self.mibBuilder.importSymbols('SNMPv2-SMI', 'iso')
- outputVarBinds = []
- state, status = 'start', 'ok'
+ outputVarBinds = fsmContext['varBinds']
+ state = fsmContext['state']
+ status = fsmContext['status']
+
origExc = origTraceback = None
+
while True:
k = state, status
if k in fsmTable:
@@ -237,7 +247,7 @@ class MibInstrumController(AbstractMibInstrumController):
break
else:
debug.logger & debug.flagIns and debug.logger(
- 'flipFlopFsm: fun %s suceeded for %s=%r' % (mgmtFun, name, val))
+ 'flipFlopFsm: fun %s succeeded for %s=%r' % (mgmtFun, name, val))
if rval is not None:
outputVarBinds.append((rval[0], rval[1]))
@@ -252,13 +262,15 @@ class MibInstrumController(AbstractMibInstrumController):
# (seems to be irrelevant on Py3 but just in case)
del origTraceback
- return outputVarBinds
+ cbFun = context.get('cbFun')
+ if cbFun:
+ cbFun(outputVarBinds, **context)
def readVars(self, *varBinds, **context):
- return self.flipFlopFsm(self.fsmReadVar, *varBinds, **context)
+ self.flipFlopFsm(self.fsmReadVar, *varBinds, **context)
def readNextVars(self, *varBinds, **context):
- return self.flipFlopFsm(self.fsmReadNextVar, *varBinds, **context)
+ self.flipFlopFsm(self.fsmReadNextVar, *varBinds, **context)
def writeVars(self, *varBinds, **context):
- return self.flipFlopFsm(self.fsmWriteVar, *varBinds, **context)
+ self.flipFlopFsm(self.fsmWriteVar, *varBinds, **context)