summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlya Etingof <etingof@gmail.com>2018-06-30 20:14:57 +0200
committerGitHub <noreply@github.com>2018-06-30 20:14:57 +0200
commitda4539e34cacdc0bd6ecfba98dc48caecc12b104 (patch)
tree22fdd82dae7dc971a8998d7679d9d6698105116c
parentdf6d6a6efd7ec6810feb9edddf369264512612b2 (diff)
downloadpysnmp-git-da4539e34cacdc0bd6ecfba98dc48caecc12b104.tar.gz
Overhaul SMI/MIB instrumentation API (#161)
Overhaul SMI/MIB instrumentation API SMI/MIB managed objects API overhauled for simplicity and flexibility breaking backward compatibility. This change would allow way more control over custom MIB managed objects and also is the prerequisite for asynchronous MIB instrumentation.
-rw-r--r--CHANGES.txt12
-rw-r--r--examples/smi/agent/custom-managed-object.py13
-rw-r--r--examples/smi/agent/operations-on-managed-objects.py11
-rw-r--r--examples/v3arch/asyncore/agent/cmdrsp/custom-mib-controller.py2
-rw-r--r--examples/v3arch/asyncore/agent/cmdrsp/implementing-snmp-table.py6
-rw-r--r--pysnmp/entity/config.py209
-rw-r--r--pysnmp/entity/rfc3413/cmdrsp.py151
-rw-r--r--pysnmp/proto/secmod/rfc3414/service.py9
-rw-r--r--pysnmp/smi/instrum.py52
-rw-r--r--pysnmp/smi/mibs/SNMPv2-SMI.py604
10 files changed, 661 insertions, 408 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 6d51f9c6..ca6eb6d7 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,5 @@
-Revision 5.0.0, released 2018-03-??
+Revision 5.0.0, released 2018-07-??
-----------------------------------
- SNMPv3 crypto operations that require external dependencies
@@ -12,6 +12,16 @@ Revision 5.0.0, released 2018-03-??
Most importantly, the `pysnmp.entity.rfc3413.oneliner` and
everything related to (non-standard) UNIX domain socket transport
are gone.
+- The MIB instrumentation API overhauled in backward incompatible
+ way:
+
+ - MIB instrumentation methods signatures simplified to accept
+ just var-binds (as var-arg), the rest of the parameters packed
+ into opaque kwargs
+ - CommandResponder application passes `snmpEngine` and optionally
+ user-supplied `cbCtx` object throughout the MIB instrumentation
+ methods. The goal is to let MIB objects access/modify whatever
+ custom Python objects they need while being called back.
Revision 4.4.5, released 2018-04-XX
-----------------------------------
diff --git a/examples/smi/agent/custom-managed-object.py b/examples/smi/agent/custom-managed-object.py
index 0b175193..73bfa836 100644
--- a/examples/smi/agent/custom-managed-object.py
+++ b/examples/smi/agent/custom-managed-object.py
@@ -28,9 +28,9 @@ sysLocation, = mibBuilder.importSymbols('SNMPv2-MIB', 'sysLocation')
# Custom Managed Object
class MySysLocationInstance(MibScalarInstance):
# noinspection PyUnusedLocal
- def readGet(self, name, *args):
+ def readGet(self, varBind, **context):
# Just return a custom value
- return name, self.syntax.clone('The Leaky Cauldron')
+ return varBind[0], self.syntax.clone('The Leaky Cauldron')
sysLocationInstance = MySysLocationInstance(
@@ -52,9 +52,12 @@ if __name__ == '__main__':
mibInstrum = instrum.MibInstrumController(mibBuilder)
print('Remote manager read access to MIB instrumentation (table walk)')
- oid, val = (), None
- while 1:
- oid, val = mibInstrum.readNextVars(((oid, val),))[0]
+
+ varBinds = [((), None)]
+
+ while True:
+ varBinds = mibInstrum.readNextVars(*varBinds)
+ oid, val = varBinds[0]
if exval.endOfMib.isSameTypeWith(val):
break
print(oid, val.prettyPrint())
diff --git a/examples/smi/agent/operations-on-managed-objects.py b/examples/smi/agent/operations-on-managed-objects.py
index 7d1f300c..e1eb52d6 100644
--- a/examples/smi/agent/operations-on-managed-objects.py
+++ b/examples/smi/agent/operations-on-managed-objects.py
@@ -28,18 +28,19 @@ print('done')
print('Create/update SNMP-COMMUNITY-MIB::snmpCommunityEntry table row: ')
varBinds = mibInstrum.writeVars(
- ((snmpCommunityEntry.name + (2,) + instanceId, 'mycomm'),
- (snmpCommunityEntry.name + (3,) + instanceId, 'mynmsname'),
- (snmpCommunityEntry.name + (7,) + instanceId, 'volatile'))
+ (snmpCommunityEntry.name + (2,) + instanceId, 'mycomm'),
+ (snmpCommunityEntry.name + (3,) + instanceId, 'mynmsname'),
+ (snmpCommunityEntry.name + (7,) + instanceId, 'volatile')
)
for oid, val in varBinds:
print('%s = %s' % ('.'.join([str(x) for x in oid]), not val.isValue and 'N/A' or val.prettyPrint()))
print('done')
print('Read whole MIB (table walk)')
-oid, val = (), None
+varBinds = [((), None)]
while True:
- oid, val = mibInstrum.readNextVars(((oid, val),))[0]
+ varBinds = mibInstrum.readNextVars(*varBinds)
+ oid, val = varBinds[0]
if exval.endOfMib.isSameTypeWith(val):
break
print('%s = %s' % ('.'.join([str(x) for x in oid]), not val.isValue and 'N/A' or val.prettyPrint()))
diff --git a/examples/v3arch/asyncore/agent/cmdrsp/custom-mib-controller.py b/examples/v3arch/asyncore/agent/cmdrsp/custom-mib-controller.py
index 1a03e725..94bdb7de 100644
--- a/examples/v3arch/asyncore/agent/cmdrsp/custom-mib-controller.py
+++ b/examples/v3arch/asyncore/agent/cmdrsp/custom-mib-controller.py
@@ -53,7 +53,7 @@ snmpContext = context.SnmpContext(snmpEngine)
# any Managed Objects attached. It supports only GET's and
# always echos request var-binds in response.
class EchoMibInstrumController(instrum.AbstractMibInstrumController):
- def readVars(self, varBinds, acInfo=(None, None)):
+ def readVars(self, *varBinds, **context):
return [(ov[0], v2c.OctetString('You queried OID %s' % ov[0])) for ov in varBinds]
diff --git a/examples/v3arch/asyncore/agent/cmdrsp/implementing-snmp-table.py b/examples/v3arch/asyncore/agent/cmdrsp/implementing-snmp-table.py
index 0e15599a..ea924fc2 100644
--- a/examples/v3arch/asyncore/agent/cmdrsp/implementing-snmp-table.py
+++ b/examples/v3arch/asyncore/agent/cmdrsp/implementing-snmp-table.py
@@ -102,9 +102,9 @@ mibBuilder.exportSymbols(
rowInstanceId = exampleTableEntry.getInstIdFromIndices('example record one')
mibInstrumentation = snmpContext.getMibInstrum()
mibInstrumentation.writeVars(
- ((exampleTableColumn2.name + rowInstanceId, 'my string value'),
- (exampleTableColumn3.name + rowInstanceId, 123456),
- (exampleTableStatus.name + rowInstanceId, 'createAndGo'))
+ (exampleTableColumn2.name + rowInstanceId, 'my string value'),
+ (exampleTableColumn3.name + rowInstanceId, 123456),
+ (exampleTableStatus.name + rowInstanceId, 'createAndGo')
)
# --- end of SNMP table population ---
diff --git a/pysnmp/entity/config.py b/pysnmp/entity/config.py
index d34c3773..ce6e9b07 100644
--- a/pysnmp/entity/config.py
+++ b/pysnmp/entity/config.py
@@ -83,17 +83,19 @@ def addV1System(snmpEngine, communityIndex, communityName,
contextName = null
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((snmpCommunityEntry.name + (8,) + tblIdx, 'destroy'),)
+ (snmpCommunityEntry.name + (8,) + tblIdx, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((snmpCommunityEntry.name + (1,) + tblIdx, communityIndex),
- (snmpCommunityEntry.name + (2,) + tblIdx, communityName),
- (snmpCommunityEntry.name + (3,) + tblIdx, securityName is not None and securityName or communityIndex),
- (snmpCommunityEntry.name + (4,) + tblIdx, contextEngineId),
- (snmpCommunityEntry.name + (5,) + tblIdx, contextName),
- (snmpCommunityEntry.name + (6,) + tblIdx, transportTag),
- (snmpCommunityEntry.name + (7,) + tblIdx, 'nonVolatile'),
- (snmpCommunityEntry.name + (8,) + tblIdx, 'createAndGo'))
+ (snmpCommunityEntry.name + (1,) + tblIdx, communityIndex),
+ (snmpCommunityEntry.name + (2,) + tblIdx, communityName),
+ (snmpCommunityEntry.name + (3,) + tblIdx, securityName is not None and securityName or communityIndex),
+ (snmpCommunityEntry.name + (4,) + tblIdx, contextEngineId),
+ (snmpCommunityEntry.name + (5,) + tblIdx, contextName),
+ (snmpCommunityEntry.name + (6,) + tblIdx, transportTag),
+ (snmpCommunityEntry.name + (7,) + tblIdx, 'nonVolatile'),
+ (snmpCommunityEntry.name + (8,) + tblIdx, 'createAndGo'),
+ **dict(snmpEngine=snmpEngine)
)
@@ -101,7 +103,8 @@ def delV1System(snmpEngine, communityIndex):
(snmpCommunityEntry, tblIdx,
snmpEngineID) = __cookV1SystemInfo(snmpEngine, communityIndex)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((snmpCommunityEntry.name + (8,) + tblIdx, 'destroy'),)
+ (snmpCommunityEntry.name + (8,) + tblIdx, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
@@ -143,15 +146,17 @@ def addV3User(snmpEngine, userName,
zeroDotZero, = mibBuilder.importSymbols('SNMPv2-SMI', 'zeroDotZero')
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((usmUserEntry.name + (13,) + tblIdx1, 'destroy'),)
+ (usmUserEntry.name + (13,) + tblIdx1, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((usmUserEntry.name + (2,) + tblIdx1, userName),
- (usmUserEntry.name + (3,) + tblIdx1, securityName),
- (usmUserEntry.name + (4,) + tblIdx1, zeroDotZero.name),
- (usmUserEntry.name + (5,) + tblIdx1, authProtocol),
- (usmUserEntry.name + (8,) + tblIdx1, privProtocol),
- (usmUserEntry.name + (13,) + tblIdx1, 'createAndGo'))
+ (usmUserEntry.name + (2,) + tblIdx1, userName),
+ (usmUserEntry.name + (3,) + tblIdx1, securityName),
+ (usmUserEntry.name + (4,) + tblIdx1, zeroDotZero.name),
+ (usmUserEntry.name + (5,) + tblIdx1, authProtocol),
+ (usmUserEntry.name + (8,) + tblIdx1, privProtocol),
+ (usmUserEntry.name + (13,) + tblIdx1, 'createAndGo'),
+ **dict(snmpEngine=snmpEngine)
)
# Localize keys
@@ -177,22 +182,25 @@ def addV3User(snmpEngine, userName,
# Commit localized keys
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((pysnmpUsmKeyEntry.name + (1,) + tblIdx1, localAuthKey),
- (pysnmpUsmKeyEntry.name + (2,) + tblIdx1, localPrivKey),
- (pysnmpUsmKeyEntry.name + (3,) + tblIdx1, hashedAuthPassphrase),
- (pysnmpUsmKeyEntry.name + (4,) + tblIdx1, hashedPrivPassphrase))
+ (pysnmpUsmKeyEntry.name + (1,) + tblIdx1, localAuthKey),
+ (pysnmpUsmKeyEntry.name + (2,) + tblIdx1, localPrivKey),
+ (pysnmpUsmKeyEntry.name + (3,) + tblIdx1, hashedAuthPassphrase),
+ (pysnmpUsmKeyEntry.name + (4,) + tblIdx1, hashedPrivPassphrase),
+ **dict(snmpEngine=snmpEngine)
)
# Commit passphrases
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((pysnmpUsmSecretEntry.name + (4,) + tblIdx2, 'destroy'),)
+ (pysnmpUsmSecretEntry.name + (4,) + tblIdx2, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((pysnmpUsmSecretEntry.name + (1,) + tblIdx2, userName),
- (pysnmpUsmSecretEntry.name + (2,) + tblIdx2, authKey),
- (pysnmpUsmSecretEntry.name + (3,) + tblIdx2, privKey),
- (pysnmpUsmSecretEntry.name + (4,) + tblIdx2, 'createAndGo'))
+ (pysnmpUsmSecretEntry.name + (1,) + tblIdx2, userName),
+ (pysnmpUsmSecretEntry.name + (2,) + tblIdx2, authKey),
+ (pysnmpUsmSecretEntry.name + (3,) + tblIdx2, privKey),
+ (pysnmpUsmSecretEntry.name + (4,) + tblIdx2, 'createAndGo'),
+ **dict(snmpEngine=snmpEngine)
)
@@ -202,10 +210,12 @@ def delV3User(snmpEngine,
(snmpEngineID, usmUserEntry, tblIdx1, pysnmpUsmSecretEntry,
tblIdx2) = __cookV3UserInfo(snmpEngine, userName, securityEngineId)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((usmUserEntry.name + (13,) + tblIdx1, 'destroy'),)
+ (usmUserEntry.name + (13,) + tblIdx1, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((pysnmpUsmSecretEntry.name + (4,) + tblIdx2, 'destroy'),)
+ (pysnmpUsmSecretEntry.name + (4,) + tblIdx2, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
# Drop all derived rows
@@ -216,7 +226,7 @@ def delV3User(snmpEngine,
)
while varBinds:
varBinds = snmpEngine.msgAndPduDsp.mibInstrumController.readNextVars(
- varBinds
+ *varBinds, **dict(snmpEngine=snmpEngine)
)
if varBinds[0][1].isSameTypeWith(rfc1905.endOfMibView):
break
@@ -249,22 +259,25 @@ def addTargetParams(snmpEngine, name, securityName, securityLevel, mpModel=3):
snmpTargetParamsEntry, tblIdx = __cookTargetParamsInfo(snmpEngine, name)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((snmpTargetParamsEntry.name + (7,) + tblIdx, 'destroy'),)
+ (snmpTargetParamsEntry.name + (7,) + tblIdx, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((snmpTargetParamsEntry.name + (1,) + tblIdx, name),
- (snmpTargetParamsEntry.name + (2,) + tblIdx, mpModel),
- (snmpTargetParamsEntry.name + (3,) + tblIdx, securityModel),
- (snmpTargetParamsEntry.name + (4,) + tblIdx, securityName),
- (snmpTargetParamsEntry.name + (5,) + tblIdx, securityLevel),
- (snmpTargetParamsEntry.name + (7,) + tblIdx, 'createAndGo'))
+ (snmpTargetParamsEntry.name + (1,) + tblIdx, name),
+ (snmpTargetParamsEntry.name + (2,) + tblIdx, mpModel),
+ (snmpTargetParamsEntry.name + (3,) + tblIdx, securityModel),
+ (snmpTargetParamsEntry.name + (4,) + tblIdx, securityName),
+ (snmpTargetParamsEntry.name + (5,) + tblIdx, securityLevel),
+ (snmpTargetParamsEntry.name + (7,) + tblIdx, 'createAndGo'),
+ **dict(snmpEngine=snmpEngine)
)
def delTargetParams(snmpEngine, name):
snmpTargetParamsEntry, tblIdx = __cookTargetParamsInfo(snmpEngine, name)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((snmpTargetParamsEntry.name + (7,) + tblIdx, 'destroy'),)
+ (snmpTargetParamsEntry.name + (7,) + tblIdx, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
@@ -299,18 +312,20 @@ def addTargetAddr(snmpEngine, addrName, transportDomain, transportAddress,
sourceAddress = TransportAddressIPv6(sourceAddress)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((snmpTargetAddrEntry.name + (9,) + tblIdx, 'destroy'),)
+ (snmpTargetAddrEntry.name + (9,) + tblIdx, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((snmpTargetAddrEntry.name + (1,) + tblIdx, addrName),
- (snmpTargetAddrEntry.name + (2,) + tblIdx, transportDomain),
- (snmpTargetAddrEntry.name + (3,) + tblIdx, transportAddress),
- (snmpTargetAddrEntry.name + (4,) + tblIdx, timeout),
- (snmpTargetAddrEntry.name + (5,) + tblIdx, retryCount),
- (snmpTargetAddrEntry.name + (6,) + tblIdx, tagList),
- (snmpTargetAddrEntry.name + (7,) + tblIdx, params),
- (snmpSourceAddrEntry.name + (1,) + tblIdx, sourceAddress),
- (snmpTargetAddrEntry.name + (9,) + tblIdx, 'createAndGo'))
+ (snmpTargetAddrEntry.name + (1,) + tblIdx, addrName),
+ (snmpTargetAddrEntry.name + (2,) + tblIdx, transportDomain),
+ (snmpTargetAddrEntry.name + (3,) + tblIdx, transportAddress),
+ (snmpTargetAddrEntry.name + (4,) + tblIdx, timeout),
+ (snmpTargetAddrEntry.name + (5,) + tblIdx, retryCount),
+ (snmpTargetAddrEntry.name + (6,) + tblIdx, tagList),
+ (snmpTargetAddrEntry.name + (7,) + tblIdx, params),
+ (snmpSourceAddrEntry.name + (1,) + tblIdx, sourceAddress),
+ (snmpTargetAddrEntry.name + (9,) + tblIdx, 'createAndGo'),
+ **dict(snmpEngine=snmpEngine)
)
@@ -318,7 +333,8 @@ def delTargetAddr(snmpEngine, addrName):
(snmpTargetAddrEntry, snmpSourceAddrEntry,
tblIdx) = __cookTargetAddrInfo(snmpEngine, addrName)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((snmpTargetAddrEntry.name + (9,) + tblIdx, 'destroy'),)
+ (snmpTargetAddrEntry.name + (9,) + tblIdx, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
@@ -386,7 +402,8 @@ def addContext(snmpEngine, contextName):
vacmContextEntry, = mibBuilder.importSymbols('SNMP-VIEW-BASED-ACM-MIB', 'vacmContextEntry')
tblIdx = vacmContextEntry.getInstIdFromIndices(contextName)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((vacmContextEntry.name + (1,) + tblIdx, contextName),)
+ (vacmContextEntry.name + (1,) + tblIdx, contextName),
+ ** dict(snmpEngine=snmpEngine)
)
@@ -404,13 +421,15 @@ def addVacmGroup(snmpEngine, groupName, securityModel, securityName):
(vacmSecurityToGroupEntry,
tblIdx) = __cookVacmGroupInfo(snmpEngine, securityModel, securityName)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((vacmSecurityToGroupEntry.name + (5,) + tblIdx, 'destroy'),)
+ (vacmSecurityToGroupEntry.name + (5,) + tblIdx, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((vacmSecurityToGroupEntry.name + (1,) + tblIdx, securityModel),
- (vacmSecurityToGroupEntry.name + (2,) + tblIdx, securityName),
- (vacmSecurityToGroupEntry.name + (3,) + tblIdx, groupName),
- (vacmSecurityToGroupEntry.name + (5,) + tblIdx, 'createAndGo'))
+ (vacmSecurityToGroupEntry.name + (1,) + tblIdx, securityModel),
+ (vacmSecurityToGroupEntry.name + (2,) + tblIdx, securityName),
+ (vacmSecurityToGroupEntry.name + (3,) + tblIdx, groupName),
+ (vacmSecurityToGroupEntry.name + (5,) + tblIdx, 'createAndGo'),
+ **dict(snmpEngine=snmpEngine)
)
@@ -419,7 +438,8 @@ def delVacmGroup(snmpEngine, securityModel, securityName):
snmpEngine, securityModel, securityName
)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((vacmSecurityToGroupEntry.name + (5,) + tblIdx, 'destroy'),)
+ (vacmSecurityToGroupEntry.name + (5,) + tblIdx, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
@@ -442,17 +462,19 @@ def addVacmAccess(snmpEngine, groupName, contextName, securityModel,
addContext(snmpEngine, contextName) # this is leaky
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((vacmAccessEntry.name + (9,) + tblIdx, 'destroy'),)
+ (vacmAccessEntry.name + (9,) + tblIdx, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((vacmAccessEntry.name + (1,) + tblIdx, contextName),
- (vacmAccessEntry.name + (2,) + tblIdx, securityModel),
- (vacmAccessEntry.name + (3,) + tblIdx, securityLevel),
- (vacmAccessEntry.name + (4,) + tblIdx, prefix),
- (vacmAccessEntry.name + (5,) + tblIdx, readView),
- (vacmAccessEntry.name + (6,) + tblIdx, writeView),
- (vacmAccessEntry.name + (7,) + tblIdx, notifyView),
- (vacmAccessEntry.name + (9,) + tblIdx, 'createAndGo'))
+ (vacmAccessEntry.name + (1,) + tblIdx, contextName),
+ (vacmAccessEntry.name + (2,) + tblIdx, securityModel),
+ (vacmAccessEntry.name + (3,) + tblIdx, securityLevel),
+ (vacmAccessEntry.name + (4,) + tblIdx, prefix),
+ (vacmAccessEntry.name + (5,) + tblIdx, readView),
+ (vacmAccessEntry.name + (6,) + tblIdx, writeView),
+ (vacmAccessEntry.name + (7,) + tblIdx, notifyView),
+ (vacmAccessEntry.name + (9,) + tblIdx, 'createAndGo'),
+ **dict(snmpEngine=snmpEngine)
)
@@ -462,7 +484,8 @@ def delVacmAccess(snmpEngine, groupName, contextName, securityModel,
contextName, securityModel,
securityLevel)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((vacmAccessEntry.name + (9,) + tblIdx, 'destroy'),)
+ (vacmAccessEntry.name + (9,) + tblIdx, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
@@ -480,14 +503,16 @@ def addVacmView(snmpEngine, viewName, viewType, subTree, mask):
vacmViewTreeFamilyEntry, tblIdx = __cookVacmViewInfo(snmpEngine, viewName,
subTree)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((vacmViewTreeFamilyEntry.name + (6,) + tblIdx, 'destroy'),)
+ (vacmViewTreeFamilyEntry.name + (6,) + tblIdx, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((vacmViewTreeFamilyEntry.name + (1,) + tblIdx, viewName),
- (vacmViewTreeFamilyEntry.name + (2,) + tblIdx, subTree),
- (vacmViewTreeFamilyEntry.name + (3,) + tblIdx, mask),
- (vacmViewTreeFamilyEntry.name + (4,) + tblIdx, viewType),
- (vacmViewTreeFamilyEntry.name + (6,) + tblIdx, 'createAndGo'))
+ (vacmViewTreeFamilyEntry.name + (1,) + tblIdx, viewName),
+ (vacmViewTreeFamilyEntry.name + (2,) + tblIdx, subTree),
+ (vacmViewTreeFamilyEntry.name + (3,) + tblIdx, mask),
+ (vacmViewTreeFamilyEntry.name + (4,) + tblIdx, viewType),
+ (vacmViewTreeFamilyEntry.name + (6,) + tblIdx, 'createAndGo'),
+ **dict(snmpEngine=snmpEngine)
)
@@ -495,7 +520,8 @@ def delVacmView(snmpEngine, viewName, subTree):
vacmViewTreeFamilyEntry, tblIdx = __cookVacmViewInfo(snmpEngine, viewName,
subTree)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((vacmViewTreeFamilyEntry.name + (6,) + tblIdx, 'destroy'),)
+ (vacmViewTreeFamilyEntry.name + (6,) + tblIdx, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
@@ -586,33 +612,39 @@ def addNotificationTarget(snmpEngine, notificationName, paramsName,
paramsName, filterSubtree)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((snmpNotifyEntry.name + (5,) + tblIdx1, 'destroy'),)
+ (snmpNotifyEntry.name + (5,) + tblIdx1, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((snmpNotifyEntry.name + (2,) + tblIdx1, transportTag),
- (snmpNotifyEntry.name + (3,) + tblIdx1, notifyType),
- (snmpNotifyEntry.name + (5,) + tblIdx1, 'createAndGo'))
+ (snmpNotifyEntry.name + (2,) + tblIdx1, transportTag),
+ (snmpNotifyEntry.name + (3,) + tblIdx1, notifyType),
+ (snmpNotifyEntry.name + (5,) + tblIdx1, 'createAndGo'),
+ **dict(snmpEngine=snmpEngine)
)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((snmpNotifyFilterProfileEntry.name + (3,) + tblIdx2, 'destroy'),)
+ (snmpNotifyFilterProfileEntry.name + (3,) + tblIdx2, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((snmpNotifyFilterProfileEntry.name + (1,) + tblIdx2, profileName),
- (snmpNotifyFilterProfileEntry.name + (3,) + tblIdx2, 'createAndGo'))
+ (snmpNotifyFilterProfileEntry.name + (1,) + tblIdx2, profileName),
+ (snmpNotifyFilterProfileEntry.name + (3,) + tblIdx2, 'createAndGo'),
+ **dict(snmpEngine=snmpEngine)
)
if not snmpNotifyFilterEntry:
return
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((snmpNotifyFilterEntry.name + (5,) + tblIdx3, 'destroy'),)
+ (snmpNotifyFilterEntry.name + (5,) + tblIdx3, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((snmpNotifyFilterEntry.name + (1,) + tblIdx3, filterSubtree),
- (snmpNotifyFilterEntry.name + (2,) + tblIdx3, filterMask),
- (snmpNotifyFilterEntry.name + (3,) + tblIdx3, filterType),
- (snmpNotifyFilterEntry.name + (5,) + tblIdx3, 'createAndGo'))
+ (snmpNotifyFilterEntry.name + (1,) + tblIdx3, filterSubtree),
+ (snmpNotifyFilterEntry.name + (2,) + tblIdx3, filterMask),
+ (snmpNotifyFilterEntry.name + (3,) + tblIdx3, filterType),
+ (snmpNotifyFilterEntry.name + (5,) + tblIdx3, 'createAndGo'),
+ **dict(snmpEngine=snmpEngine)
)
@@ -624,18 +656,21 @@ def delNotificationTarget(snmpEngine, notificationName, paramsName,
paramsName, filterSubtree)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((snmpNotifyEntry.name + (5,) + tblIdx1, 'destroy'),)
+ (snmpNotifyEntry.name + (5,) + tblIdx1, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((snmpNotifyFilterProfileEntry.name + (3,) + tblIdx2, 'destroy'),)
+ (snmpNotifyFilterProfileEntry.name + (3,) + tblIdx2, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
if not snmpNotifyFilterEntry:
return
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((snmpNotifyFilterEntry.name + (5,) + tblIdx3, 'destroy'),)
+ (snmpNotifyFilterEntry.name + (5,) + tblIdx3, 'destroy'),
+ **dict(snmpEngine=snmpEngine)
)
diff --git a/pysnmp/entity/rfc3413/cmdrsp.py b/pysnmp/entity/rfc3413/cmdrsp.py
index 94b4d45b..3d2cb5ab 100644
--- a/pysnmp/entity/rfc3413/cmdrsp.py
+++ b/pysnmp/entity/rfc3413/cmdrsp.py
@@ -17,15 +17,16 @@ class CommandResponderBase(object):
acmID = 3 # default MIB access control method to use
pduTypes = ()
- def __init__(self, snmpEngine, snmpContext):
+ def __init__(self, snmpEngine, snmpContext, cbCtx=None):
snmpEngine.msgAndPduDsp.registerContextEngineId(
snmpContext.contextEngineId, self.pduTypes, self.processPdu
)
self.snmpContext = snmpContext
+ self.cbCtx = cbCtx
self.__pendingReqs = {}
- def handleMgmtOperation(self, snmpEngine, stateReference, contextName,
- PDU, acInfo):
+ def handleMgmtOperation(self, snmpEngine, stateReference,
+ contextName, PDU, acCtx):
pass
def close(self, snmpEngine):
@@ -36,9 +37,16 @@ class CommandResponderBase(object):
def sendVarBinds(self, snmpEngine, stateReference,
errorStatus, errorIndex, varBinds):
- (messageProcessingModel, securityModel, securityName,
- securityLevel, contextEngineId, contextName,
- pduVersion, PDU, origPdu, maxSizeResponseScopedPDU,
+ (messageProcessingModel,
+ securityModel,
+ securityName,
+ securityLevel,
+ contextEngineId,
+ contextName,
+ pduVersion,
+ PDU,
+ origPdu,
+ maxSizeResponseScopedPDU,
statusInformation) = self.__pendingReqs[stateReference]
v2c.apiPDU.setErrorStatus(PDU, errorStatus)
@@ -53,9 +61,16 @@ class CommandResponderBase(object):
self.sendPdu(snmpEngine, stateReference, PDU)
def sendPdu(self, snmpEngine, stateReference, PDU):
- (messageProcessingModel, securityModel, securityName,
- securityLevel, contextEngineId, contextName,
- pduVersion, _, origPdu, maxSizeResponseScopedPDU,
+ (messageProcessingModel,
+ securityModel,
+ securityName,
+ securityLevel,
+ contextEngineId,
+ contextName,
+ pduVersion,
+ _,
+ origPdu,
+ maxSizeResponseScopedPDU,
statusInformation) = self.__pendingReqs[stateReference]
# Agent-side API complies with SMIv2
@@ -132,9 +147,8 @@ class CommandResponderBase(object):
'processPdu: stateReference %s, varBinds %s' % (stateReference, varBinds))
try:
- self.handleMgmtOperation(snmpEngine, stateReference,
- contextName, PDU,
- (self.__verifyAccess, snmpEngine))
+ self.handleMgmtOperation(snmpEngine, stateReference, contextName, PDU)
+
# SNMPv2 SMI exceptions
except pysnmp.smi.error.GenError:
errorIndication = sys.exc_info()[1]
@@ -185,18 +199,29 @@ class CommandResponderBase(object):
self.releaseStateInformation(stateReference)
- def __verifyAccess(self, name, syntax, idx, viewType, acCtx):
- snmpEngine = acCtx
+ @classmethod
+ def verifyAccess(cls, viewType, varBind, **context):
+ name, val = varBind
+
+ snmpEngine = context['snmpEngine']
+
execCtx = snmpEngine.observer.getExecutionContext('rfc3412.receiveMessage:request')
- (securityModel, securityName, securityLevel, contextName,
- pduType) = (execCtx['securityModel'], execCtx['securityName'],
- execCtx['securityLevel'], execCtx['contextName'],
+ (securityModel,
+ securityName,
+ securityLevel,
+ contextName,
+ pduType) = (execCtx['securityModel'],
+ execCtx['securityName'],
+ execCtx['securityLevel'],
+ execCtx['contextName'],
execCtx['pdu'].getTagSet())
+
try:
- snmpEngine.accessControlModel[self.acmID].isAccessAllowed(
+ snmpEngine.accessControlModel[cls.acmID].isAccessAllowed(
snmpEngine, securityModel, securityName,
securityLevel, viewType, contextName, name
)
+
# Map ACM errors onto SMI ones
except error.StatusInformation:
statusInformation = sys.exc_info()[1]
@@ -207,41 +232,48 @@ class CommandResponderBase(object):
if (errorIndication == errind.noSuchView or
errorIndication == errind.noAccessEntry or
errorIndication == errind.noGroupName):
- raise pysnmp.smi.error.AuthorizationError(name=name, idx=idx)
+ raise pysnmp.smi.error.AuthorizationError(name=name, idx=context.get('idx'))
+
elif errorIndication == errind.otherError:
- raise pysnmp.smi.error.GenError(name=name, idx=idx)
+ raise pysnmp.smi.error.GenError(name=name, idx=context.get('idx'))
+
elif errorIndication == errind.noSuchContext:
snmpUnknownContexts, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
'__SNMP-TARGET-MIB', 'snmpUnknownContexts')
snmpUnknownContexts.syntax += 1
# Request REPORT generation
- raise pysnmp.smi.error.GenError(name=name, idx=idx,
+ raise pysnmp.smi.error.GenError(name=name, idx=context.get('idx'),
oid=snmpUnknownContexts.name,
val=snmpUnknownContexts.syntax)
+
elif errorIndication == errind.notInView:
- return 1
+ return True
+
else:
raise error.ProtocolError('Unknown ACM error %s' % errorIndication)
else:
# rfc2576: 4.1.2.1
- if (securityModel == 1 and syntax is not None and
- self._counter64Type == syntax.getTagSet() and
- self._getNextRequestType == pduType):
+ if (securityModel == 1 and val is not None and
+ cls._counter64Type == val.getTagSet() and
+ cls._getNextRequestType == pduType):
# This will cause MibTree to skip this OID-value
- raise pysnmp.smi.error.NoAccessError(name=name, idx=idx)
+ raise pysnmp.smi.error.NoAccessError(name=name, idx=context.get('idx'))
class GetCommandResponder(CommandResponderBase):
pduTypes = (rfc1905.GetRequestPDU.tagSet,)
# rfc1905: 4.2.1
- def handleMgmtOperation(self, snmpEngine, stateReference,
- contextName, PDU, acInfo):
- (acFun, acCtx) = acInfo
+ def handleMgmtOperation(self, snmpEngine, stateReference, contextName, PDU):
# rfc1905: 4.2.1.1
mgmtFun = self.snmpContext.getMibInstrum(contextName).readVars
- self.sendVarBinds(snmpEngine, stateReference, 0, 0,
- mgmtFun(v2c.apiPDU.getVarBinds(PDU), (acFun, acCtx)))
+ varBinds = v2c.apiPDU.getVarBinds(PDU)
+
+ context = dict(snmpEngine=snmpEngine, acFun=self.verifyAccess, cbCtx=self.cbCtx)
+
+ rspVarBinds = mgmtFun(*varBinds, **context)
+
+ self.sendVarBinds(snmpEngine, stateReference, 0, 0, rspVarBinds)
self.releaseStateInformation(stateReference)
@@ -249,21 +281,26 @@ class NextCommandResponder(CommandResponderBase):
pduTypes = (rfc1905.GetNextRequestPDU.tagSet,)
# rfc1905: 4.2.2
- def handleMgmtOperation(self, snmpEngine, stateReference,
- contextName, PDU, acInfo):
- (acFun, acCtx) = acInfo
+ def handleMgmtOperation(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, (acFun, acCtx))
+ rspVarBinds = mgmtFun(*varBinds, **context)
+
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)
@@ -272,12 +309,11 @@ class BulkCommandResponder(CommandResponderBase):
maxVarBinds = 64
# rfc1905: 4.2.3
- def handleMgmtOperation(self, snmpEngine, stateReference,
- contextName, PDU, acInfo):
- (acFun, acCtx) = acInfo
+ def handleMgmtOperation(self, snmpEngine, stateReference, contextName, PDU):
nonRepeaters = v2c.apiBulkPDU.getNonRepeaters(PDU)
if nonRepeaters < 0:
nonRepeaters = 0
+
maxRepetitions = v2c.apiBulkPDU.getMaxRepetitions(PDU)
if maxRepetitions < 0:
maxRepetitions = 0
@@ -295,14 +331,19 @@ class BulkCommandResponder(CommandResponderBase):
mgmtFun = self.snmpContext.getMibInstrum(contextName).readNextVars
+ context = dict(snmpEngine=snmpEngine, acFun=self.verifyAccess, cbCtx=self.cbCtx)
+
if N:
- rspVarBinds = mgmtFun(reqVarBinds[:N], (acFun, acCtx))
+ # TODO(etingof): manage all PDU var-binds in a single call
+ rspVarBinds = mgmtFun(*reqVarBinds[:N], **context)
+
else:
rspVarBinds = []
varBinds = reqVarBinds[-R:]
+
while M and R:
- rspVarBinds.extend(mgmtFun(varBinds, (acFun, acCtx)))
+ rspVarBinds.extend(mgmtFun(*varBinds, **context))
varBinds = rspVarBinds[-R:]
M -= 1
@@ -317,18 +358,28 @@ class SetCommandResponder(CommandResponderBase):
pduTypes = (rfc1905.SetRequestPDU.tagSet,)
# rfc1905: 4.2.5
- def handleMgmtOperation(self, snmpEngine, stateReference,
- contextName, PDU, acInfo):
- (acFun, acCtx) = acInfo
+ def handleMgmtOperation(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)
+
# rfc1905: 4.2.5.1-13
try:
- self.sendVarBinds(snmpEngine, stateReference, 0, 0,
- mgmtFun(v2c.apiPDU.getVarBinds(PDU),
- (acFun, acCtx)))
- self.releaseStateInformation(stateReference)
+ rspVarBinds = mgmtFun(*varBinds, **context)
+
except (pysnmp.smi.error.NoSuchObjectError,
pysnmp.smi.error.NoSuchInstanceError):
- e = pysnmp.smi.error.NotWritableError()
- e.update(sys.exc_info()[1])
- raise e
+ instrumError = pysnmp.smi.error.NotWritableError()
+ instrumError.update(sys.exc_info()[1])
+
+ else:
+ self.sendVarBinds(snmpEngine, stateReference, 0, 0, rspVarBinds)
+
+ self.releaseStateInformation(stateReference)
+
+ if instrumError:
+ raise instrumError
diff --git a/pysnmp/proto/secmod/rfc3414/service.py b/pysnmp/proto/secmod/rfc3414/service.py
index b7760e4b..f3324961 100644
--- a/pysnmp/proto/secmod/rfc3414/service.py
+++ b/pysnmp/proto/secmod/rfc3414/service.py
@@ -138,8 +138,9 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
pysnmpUsmKeyAuthLocalized, usmUserPrivProtocol,
pysnmpUsmKeyPrivLocalized)
- def __cloneUserInfo(self, mibInstrumController, securityEngineID,
- userName):
+ def __cloneUserInfo(self, snmpEngine, securityEngineID, userName):
+ mibInstrumController = snmpEngine.msgAndPduDsp.mibInstrumController
+
snmpEngineID, = mibInstrumController.mibBuilder.importSymbols(
'__SNMP-FRAMEWORK-MIB', 'snmpEngineID'
)
@@ -169,7 +170,7 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
# New row
mibInstrumController.writeVars(
- ((usmUserEntry.name + (13,) + tblIdx2, 4),)
+ (usmUserEntry.name + (13,) + tblIdx2, 4), **dict(snmpEngine=snmpEngine)
)
# Set user&securityNames
@@ -273,7 +274,7 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
usmUserAuthProtocol, usmUserAuthKeyLocalized,
usmUserPrivProtocol,
usmUserPrivKeyLocalized) = self.__cloneUserInfo(
- snmpEngine.msgAndPduDsp.mibInstrumController,
+ snmpEngine,
securityEngineID,
self.__sec2usr(snmpEngine, securityName)
)
diff --git a/pysnmp/smi/instrum.py b/pysnmp/smi/instrum.py
index bd1444a9..84902025 100644
--- a/pysnmp/smi/instrum.py
+++ b/pysnmp/smi/instrum.py
@@ -13,13 +13,13 @@ __all__ = ['AbstractMibInstrumController', 'MibInstrumController']
class AbstractMibInstrumController(object):
- def readVars(self, varBinds, acInfo=(None, None)):
+ def readVars(self, *varBinds, **context):
raise error.NoSuchInstanceError(idx=0)
- def readNextVars(self, varBinds, acInfo=(None, None)):
+ def readNextVars(self, *varBinds, **context):
raise error.EndOfMibViewError(idx=0)
- def writeVars(self, varBinds, acInfo=(None, None)):
+ def writeVars(self, *varBinds, **context):
raise error.NoSuchObjectError(idx=0)
@@ -183,19 +183,22 @@ class MibInstrumController(AbstractMibInstrumController):
# MIB instrumentation
- def flipFlopFsm(self, fsmTable, inputVarBinds, acInfo):
+ def flipFlopFsm(self, fsmTable, *varBinds, **context):
self.__indexMib()
- debug.logger & debug.flagIns and debug.logger('flipFlopFsm: input var-binds %r' % (inputVarBinds,))
+
+ 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'
- origExc = None
+ origExc = origTraceback = None
while True:
- k = (state, status)
+ k = state, status
if k in fsmTable:
fsmState = fsmTable[k]
else:
- k = ('*', status)
+ k = '*', status
if k in fsmTable:
fsmState = fsmTable[k]
else:
@@ -208,32 +211,36 @@ class MibInstrumController(AbstractMibInstrumController):
status = 'ok'
if state == 'stop':
break
- idx = 0
- for name, val in inputVarBinds:
- f = getattr(mibTree, state, None)
- if f is None:
+
+ for idx, (name, val) in enumerate(varBinds):
+ mgmtFun = getattr(mibTree, state, None)
+ if not mgmtFun:
raise error.SmiError(
'Unsupported state handler %s at %s' % (state, self)
)
+
+ context['idx'] = idx
+
try:
# Convert to tuple to avoid ObjectName instantiation
# on subscription
- rval = f(tuple(name), val, idx, acInfo)
+ rval = mgmtFun((tuple(name), val), **context)
+
except error.SmiError:
exc_t, exc_v, exc_tb = sys.exc_info()
debug.logger & debug.flagIns and debug.logger(
'flipFlopFsm: fun %s exception %s for %s=%r with traceback: %s' % (
- f, exc_t, name, val, traceback.format_exception(exc_t, exc_v, exc_tb)))
+ mgmtFun, exc_t, name, val, traceback.format_exception(exc_t, exc_v, exc_tb)))
if origExc is None: # Take the first exception
origExc, origTraceback = exc_v, exc_tb
status = 'err'
break
else:
debug.logger & debug.flagIns and debug.logger(
- 'flipFlopFsm: fun %s suceeded for %s=%r' % (f, name, val))
+ 'flipFlopFsm: fun %s suceeded for %s=%r' % (mgmtFun, name, val))
if rval is not None:
outputVarBinds.append((rval[0], rval[1]))
- idx += 1
+
if origExc:
if sys.version_info[0] <= 2:
raise origExc
@@ -244,13 +251,14 @@ class MibInstrumController(AbstractMibInstrumController):
# Break cycle between locals and traceback object
# (seems to be irrelevant on Py3 but just in case)
del origTraceback
+
return outputVarBinds
- def readVars(self, varBinds, acInfo=(None, None)):
- return self.flipFlopFsm(self.fsmReadVar, varBinds, acInfo)
+ def readVars(self, *varBinds, **context):
+ return self.flipFlopFsm(self.fsmReadVar, *varBinds, **context)
- def readNextVars(self, varBinds, acInfo=(None, None)):
- return self.flipFlopFsm(self.fsmReadNextVar, varBinds, acInfo)
+ def readNextVars(self, *varBinds, **context):
+ return self.flipFlopFsm(self.fsmReadNextVar, *varBinds, **context)
- def writeVars(self, varBinds, acInfo=(None, None)):
- return self.flipFlopFsm(self.fsmWriteVar, varBinds, acInfo)
+ def writeVars(self, *varBinds, **context):
+ return self.flipFlopFsm(self.fsmWriteVar, *varBinds, **context)
diff --git a/pysnmp/smi/mibs/SNMPv2-SMI.py b/pysnmp/smi/mibs/SNMPv2-SMI.py
index abd64ddc..b5d69cf0 100644
--- a/pysnmp/smi/mibs/SNMPv2-SMI.py
+++ b/pysnmp/smi/mibs/SNMPv2-SMI.py
@@ -371,16 +371,16 @@ class MibTree(ObjectType):
# NoSuchInstanceError exception.
#
- def getBranch(self, name, idx):
+ def getBranch(self, name, **context):
"""Return a branch of this tree where the 'name' OID may reside"""
for keyLen in self._vars.getKeysLens():
subName = name[:keyLen]
if subName in self._vars:
return self._vars[subName]
- raise error.NoSuchObjectError(name=name, idx=idx)
+ raise error.NoSuchObjectError(name=name, idx=context.get('idx'))
- def getNextBranch(self, name, idx=None):
+ def getNextBranch(self, name, **context):
# Start from the beginning
if self._vars:
first = list(self._vars.keys())[0]
@@ -392,143 +392,178 @@ class MibTree(ObjectType):
try:
return self._vars[self._vars.nextKey(name)]
except KeyError:
- raise error.NoSuchObjectError(idx=idx, name=name)
+ raise error.NoSuchObjectError(name=name, idx=context.get('idx'))
- def getNode(self, name, idx=None):
+ def getNode(self, name, **context):
"""Return tree node found by name"""
if name == self.name:
return self
else:
- return self.getBranch(name, idx).getNode(name, idx)
+ return self.getBranch(name, **context).getNode(name, **context)
- def getNextNode(self, name, idx=None):
+ def getNextNode(self, name, **context):
"""Return tree node next to name"""
try:
- nextNode = self.getBranch(name, idx)
+ nextNode = self.getBranch(name, **context)
except (error.NoSuchInstanceError, error.NoSuchObjectError):
- return self.getNextBranch(name, idx)
+ return self.getNextBranch(name, **context)
else:
try:
- return nextNode.getNextNode(name, idx)
+ return nextNode.getNextNode(name, **context)
except (error.NoSuchInstanceError, error.NoSuchObjectError):
try:
return self._vars[self._vars.nextKey(nextNode.name)]
except KeyError:
- raise error.NoSuchObjectError(idx=idx, name=name)
+ raise error.NoSuchObjectError(name=name, idx=context.get('idx'))
# MIB instrumentation
# Read operation
- def readTest(self, name, val, idx, acInfo):
- (acFun, acCtx) = acInfo
+ def readTest(self, varBind, **context):
+ name, val = varBind
+
if name == self.name:
+ acFun = context.get('acFun')
if acFun:
- if self.maxAccess not in ('readonly',
- 'readwrite', 'readcreate') or \
- acFun(name, self.syntax, idx, 'read', acCtx):
- raise error.NoAccessError(idx=idx, name=name)
+ if (self.maxAccess not in ('readonly', 'readwrite', 'readcreate') or
+ acFun('read', (name, self.syntax), **context)):
+ raise error.NoAccessError(name=name, idx=context.get('idx'))
else:
try:
- node = self.getBranch(name, idx)
+ node = self.getBranch(name, **context)
+
except (error.NoSuchInstanceError, error.NoSuchObjectError):
return # missing object is not an error here
+
else:
- node.readTest(name, val, idx, acInfo)
+ node.readTest(varBind, **context)
+
+ def readGet(self, varBind, **context):
+ name, val = varBind
- def readGet(self, name, val, idx, acInfo):
try:
- node = self.getBranch(name, idx)
+ node = self.getBranch(name, **context)
+
except (error.NoSuchInstanceError, error.NoSuchObjectError):
return name, exval.noSuchObject
+
else:
- return node.readGet(name, val, idx, acInfo)
+ return node.readGet(varBind, **context)
# Read next operation is subtree-specific
depthFirst, breadthFirst = 0, 1
- def readTestNext(self, name, val, idx, acInfo, oName=None):
- if oName is None:
- oName = name
- topOfTheMib = True
- else:
- topOfTheMib = False
+ def readTestNext(self, varBind, **context):
+ name, val = varBind
+
+ topOfTheMib = context.get('oName') is None
+ if topOfTheMib:
+ context['oName'] = name
+
nextName = name
direction = self.depthFirst
- while 1: # XXX linear search here
+
+ while True: # NOTE(etingof): linear search here
if direction == self.depthFirst:
direction = self.breadthFirst
try:
- node = self.getBranch(nextName, idx)
+ node = self.getBranch(nextName, **context)
+
except (error.NoSuchInstanceError, error.NoSuchObjectError):
continue
+
else:
try:
- node = self.getNextBranch(nextName, idx)
+ node = self.getNextBranch(nextName, **context)
+
except (error.NoSuchInstanceError, error.NoSuchObjectError):
if topOfTheMib:
return
raise
+
direction = self.depthFirst
nextName = node.name
+
try:
- return node.readTestNext(nextName, val, idx, acInfo, oName)
+ return node.readTestNext(varBind, **context)
+
except (error.NoAccessError, error.NoSuchInstanceError, error.NoSuchObjectError):
pass
- def readGetNext(self, name, val, idx, acInfo, oName=None):
- if oName is None:
- oName = name
- topOfTheMib = True
- else:
- topOfTheMib = False
+ def readGetNext(self, varBind, **context):
+ name, val = varBind
+
+ topOfTheMib = context.get('oName') is None
+ if topOfTheMib:
+ context['oName'] = name
+
nextName = name
direction = self.depthFirst
- while True: # XXX linear search ahead!
+
+ while True: # NOTE(etingof): linear search ahead!
if direction == self.depthFirst:
direction = self.breadthFirst
try:
- node = self.getBranch(nextName, idx)
+ node = self.getBranch(nextName, **context)
+
except (error.NoSuchInstanceError, error.NoSuchObjectError):
continue
+
else:
try:
- node = self.getNextBranch(nextName, idx)
+ node = self.getNextBranch(nextName, **context)
+
except (error.NoSuchInstanceError, error.NoSuchObjectError):
if topOfTheMib:
return name, exval.endOfMib
raise
+
direction = self.depthFirst
nextName = node.name
+
try:
- return node.readGetNext(nextName, val, idx, acInfo, oName)
+ return node.readGetNext((nextName, val), **context)
+
except (error.NoAccessError, error.NoSuchInstanceError, error.NoSuchObjectError):
pass
# Write operation
- def writeTest(self, name, val, idx, acInfo):
- acFun, acCtx = acInfo
+ def writeTest(self, varBind, **context):
+ name, val = varBind
+
if name == self.name:
# Make sure variable is writable
+ acFun = context.get('acFun')
if acFun:
- if self.maxAccess not in ('readwrite', 'readcreate') or \
- acFun(name, self.syntax, idx, 'write', acCtx):
- raise error.NotWritableError(idx=idx, name=name)
+ if (self.maxAccess not in ('readwrite', 'readcreate') or
+ acFun('write', (name, self.syntax), **context)):
+ raise error.NotWritableError(name=name, idx=context.get('idx'))
else:
- node = self.getBranch(name, idx)
- node.writeTest(name, val, idx, acInfo)
+ node = self.getBranch(name, **context)
+ node.writeTest(varBind, **context)
- def writeCommit(self, name, val, idx, acInfo):
- self.getBranch(name, idx).writeCommit(name, val, idx, acInfo)
+ def writeCommit(self, varBind, **context):
+ name, val = varBind
+
+ node = self.getBranch(name, **context)
+ node.writeCommit(varBind, **context)
+
+ def writeCleanup(self, varBind, **context):
+ name, val = varBind
- def writeCleanup(self, name, val, idx, acInfo):
self.branchVersionId += 1
- self.getBranch(name, idx).writeCleanup(name, val, idx, acInfo)
- def writeUndo(self, name, val, idx, acInfo):
- self.getBranch(name, idx).writeUndo(name, val, idx, acInfo)
+ node = self.getBranch(name, **context)
+ node.writeCleanup(varBind, **context)
+
+ def writeUndo(self, varBind, **context):
+ name, val = varBind
+
+ node = self.getBranch(name, **context)
+ node.writeUndo(varBind, **context)
class MibScalar(MibTree):
@@ -541,85 +576,104 @@ class MibScalar(MibTree):
# Missing branches are indicated by the NoSuchInstanceError exception.
#
- def getBranch(self, name, idx):
+ def getBranch(self, name, **context):
try:
- return MibTree.getBranch(self, name, idx)
+ return MibTree.getBranch(self, name, **context)
+
except (error.NoSuchInstanceError, error.NoSuchObjectError):
- raise error.NoSuchInstanceError(idx=idx, name=name)
+ raise error.NoSuchInstanceError(name=name, idx=context.get('idx'))
- def getNextBranch(self, name, idx=None):
+ def getNextBranch(self, name, **context):
try:
- return MibTree.getNextBranch(self, name, idx)
+ return MibTree.getNextBranch(self, name, **context)
+
except (error.NoSuchInstanceError, error.NoSuchObjectError):
- raise error.NoSuchInstanceError(idx=idx, name=name)
+ raise error.NoSuchInstanceError(name=name, idx=context.get('idx'))
- def getNode(self, name, idx=None):
+ def getNode(self, name, **context):
try:
- return MibTree.getNode(self, name, idx)
+ return MibTree.getNode(self, name, **context)
+
except (error.NoSuchInstanceError, error.NoSuchObjectError):
- raise error.NoSuchInstanceError(idx=idx, name=name)
+ raise error.NoSuchInstanceError(name=name, idx=context.get('idx'))
- def getNextNode(self, name, idx=None):
+ def getNextNode(self, name, **context):
try:
- return MibTree.getNextNode(self, name, idx)
+ return MibTree.getNextNode(self, name, **context)
+
except (error.NoSuchInstanceError, error.NoSuchObjectError):
- raise error.NoSuchInstanceError(idx=idx, name=name)
+ raise error.NoSuchInstanceError(name=name, idx=context.get('idx'))
# MIB instrumentation methods
# Read operation
- def readTest(self, name, val, idx, acInfo):
- (acFun, acCtx) = acInfo
+ def readTest(self, varBind, **context):
+ name, val = varBind
+
if name == self.name:
- raise error.NoAccessError(idx=idx, name=name)
+ raise error.NoAccessError(name=name, idx=context.get('idx'))
+
+ acFun = context.get('acFun')
if acFun:
- if self.maxAccess not in ('readonly', 'readwrite',
- 'readcreate') or \
- acFun(name, self.syntax, idx, 'read', acCtx):
- raise error.NoAccessError(idx=idx, name=name)
- MibTree.readTest(self, name, val, idx, acInfo)
+ if (self.maxAccess not in ('readonly', 'readwrite', 'readcreate') or
+ acFun('read', (name, self.syntax), **context)):
+ raise error.NoAccessError(name=name, idx=context.get('idx'))
+
+ MibTree.readTest(self, varBind, **context)
+
+ def readGet(self, varBind, **context):
+ name, val = varBind
- def readGet(self, name, val, idx, acInfo):
try:
- node = self.getBranch(name, idx)
+ node = self.getBranch(name, **context)
+
except error.NoSuchInstanceError:
return name, exval.noSuchInstance
+
else:
- return node.readGet(name, val, idx, acInfo)
+ return node.readGet(varBind, **context)
+
+ def readTestNext(self, varBind, **context):
+ name, val = varBind
- def readTestNext(self, name, val, idx, acInfo, oName=None):
- (acFun, acCtx) = acInfo
+ acFun = context.get('acFun')
if acFun:
- if self.maxAccess not in ('readonly', 'readwrite',
- 'readcreate') or \
- acFun(name, self.syntax, idx, 'read', acCtx):
- raise error.NoAccessError(idx=idx, name=name)
- MibTree.readTestNext(self, name, val, idx, acInfo, oName)
-
- def readGetNext(self, name, val, idx, acInfo, oName=None):
- (acFun, acCtx) = acInfo
+ if (self.maxAccess not in ('readonly', 'readwrite', 'readcreate') or
+ acFun('read', (name, self.syntax), **context)):
+ raise error.NoAccessError(name=name, idx=context.get('idx'))
+
+ MibTree.readTestNext(self, varBind, **context)
+
+ def readGetNext(self, varBind, **context):
+ name, val = varBind
+
# have to duplicate AC here as *Next code above treats
# noAccess as a noSuchObject at the Test stage, goes on
# to Reading
+ acFun = context.get('acFun')
if acFun:
- if self.maxAccess not in ('readonly', 'readwrite',
- 'readcreate') or \
- acFun(name, self.syntax, idx, 'read', acCtx):
- raise error.NoAccessError(idx=idx, name=name)
- return MibTree.readGetNext(self, name, val, idx, acInfo, oName)
+ if (self.maxAccess not in ('readonly', 'readwrite', 'readcreate') or
+ acFun('read', (name, self.syntax), **context)):
+ raise error.NoAccessError(name=name, idx=context.get('idx'))
+
+ return MibTree.readGetNext(self, varBind, **context)
# Two-phase commit implementation
- def writeTest(self, name, val, idx, acInfo):
- acFun, acCtx = acInfo
+ def writeTest(self, varBind, **context):
+ name, val = varBind
+
if name == self.name:
- raise error.NoAccessError(idx=idx, name=name)
+ raise error.NoAccessError(name=name, idx=context.get('idx'))
+
+ acFun = context.get('acFun')
if acFun:
- if self.maxAccess not in ('readwrite', 'readcreate') or \
- acFun(name, self.syntax, idx, 'write', acCtx):
- raise error.NotWritableError(idx=idx, name=name)
- MibTree.writeTest(self, name, val, idx, acInfo)
+ if (self.maxAccess not in ('readwrite', 'readcreate') or
+ acFun('write', (name, self.syntax), **context)):
+ raise error.NotWritableError(name=name, idx=context.get('idx'))
+
+ MibTree.writeTest(self, varBind, **context)
class MibScalarInstance(MibTree):
@@ -636,18 +690,20 @@ class MibScalarInstance(MibTree):
#
# noinspection PyUnusedLocal
- def getValue(self, name, idx):
+ def getValue(self, name, **context):
debug.logger & debug.flagIns and debug.logger('getValue: returning %r for %s' % (self.syntax, self.name))
return self.syntax.clone()
- def setValue(self, value, name, idx):
+ def setValue(self, value, name, **context):
if value is None:
value = univ.noValue
+
try:
if hasattr(self.syntax, 'setValue'):
return self.syntax.setValue(value)
else:
return self.syntax.clone(value)
+
except PyAsn1Error:
exc_t, exc_v, exc_tb = sys.exc_info()
debug.logger & debug.flagIns and debug.logger('setValue: %s=%r failed with traceback %s' % (
@@ -655,7 +711,7 @@ class MibScalarInstance(MibTree):
if isinstance(exc_v, error.TableRowManagement):
raise exc_v
else:
- raise error.WrongValueError(idx=idx, name=name, msg=exc_v)
+ raise error.WrongValueError(name=name, idx=context.get('idx'), msg=exc_v)
#
# Subtree traversal
@@ -663,62 +719,80 @@ class MibScalarInstance(MibTree):
# Missing branches are indicated by the NoSuchInstanceError exception.
#
- def getBranch(self, name, idx):
+ def getBranch(self, name, **context):
try:
- return MibTree.getBranch(self, name, idx)
+ return MibTree.getBranch(self, name, **context)
+
except (error.NoSuchInstanceError, error.NoSuchObjectError):
- raise error.NoSuchInstanceError(idx=idx, name=name)
+ raise error.NoSuchInstanceError(name=name, idx=context.get('idx'))
- def getNextBranch(self, name, idx=None):
+ def getNextBranch(self, name, **context):
try:
- return MibTree.getNextBranch(self, name, idx)
+ return MibTree.getNextBranch(self, name, **context)
+
except (error.NoSuchInstanceError, error.NoSuchObjectError):
- raise error.NoSuchInstanceError(idx=idx, name=name)
+ raise error.NoSuchInstanceError(name=name, idx=context.get('idx'))
- def getNode(self, name, idx=None):
+ def getNode(self, name, **context):
# Recursion terminator
if name == self.name:
return self
- raise error.NoSuchInstanceError(idx=idx, name=name)
+ raise error.NoSuchInstanceError(name=name, idx=context.get('idx'))
- def getNextNode(self, name, idx=None):
- raise error.NoSuchInstanceError(idx=idx, name=name)
+ def getNextNode(self, name, **context):
+ raise error.NoSuchInstanceError(name=name, idx=context.get('idx'))
# MIB instrumentation methods
# Read operation
- def readTest(self, name, val, idx, acInfo):
+ def readTest(self, varBind, **context):
+ name, val = varBind
+
if name != self.name:
- raise error.NoSuchInstanceError(idx=idx, name=name)
+ raise error.NoSuchInstanceError(name=name, idx=context.get('idx'))
+
+ def readGet(self, varBind, **context):
+ name, val = varBind
- def readGet(self, name, val, idx, acInfo):
# Return current variable (name, value)
if name == self.name:
debug.logger & debug.flagIns and debug.logger('readGet: %s=%r' % (self.name, self.syntax))
- return self.name, self.getValue(name, idx)
+ return self.name, self.getValue(name, **context)
else:
- raise error.NoSuchInstanceError(idx=idx, name=name)
+ raise error.NoSuchInstanceError(name=name, idx=context.get('idx'))
+
+ def readTestNext(self, varBind, **context):
+ name, val = varBind
+
+ oName = context.get('oName')
- def readTestNext(self, name, val, idx, acInfo, oName=None):
if name != self.name or name <= oName:
- raise error.NoSuchInstanceError(idx=idx, name=name)
+ raise error.NoSuchInstanceError(name=name, idx=context.get('idx'))
+
+ def readGetNext(self, varBind, **context):
+ name, val = varBind
+
+ oName = context.get('oName')
- def readGetNext(self, name, val, idx, acInfo, oName=None):
if name == self.name and name > oName:
debug.logger & debug.flagIns and debug.logger('readGetNext: %s=%r' % (self.name, self.syntax))
- return self.readGet(name, val, idx, acInfo)
+ return self.readGet(varBind, **context)
+
else:
- raise error.NoSuchInstanceError(idx=idx, name=name)
+ raise error.NoSuchInstanceError(name=name, idx=context.get('idx'))
# Write operation: two-phase commit
# noinspection PyAttributeOutsideInit
- def writeTest(self, name, val, idx, acInfo):
+ def writeTest(self, varBind, **context):
+ name, val = varBind
+
# Make sure write's allowed
if name == self.name:
try:
- self.__newSyntax = self.setValue(val, name, idx)
+ self.__newSyntax = self.setValue(val, name, **context)
+
except error.MibOperationError:
# SMI exceptions may carry additional content
why = sys.exc_info()[1]
@@ -726,11 +800,11 @@ class MibScalarInstance(MibTree):
self.__newSyntax = why['syntax']
raise why
else:
- raise error.WrongValueError(idx=idx, name=name, msg=sys.exc_info()[1])
+ raise error.WrongValueError(name=name, idx=context.get('idx'), msg=sys.exc_info()[1])
else:
- raise error.NoSuchInstanceError(idx=idx, name=name)
+ raise error.NoSuchInstanceError(name=name, idx=context.get('idx'))
- def writeCommit(self, name, val, idx, acInfo):
+ def writeCommit(self, varBind, **context):
# Backup original value
if self.__oldSyntax is None:
self.__oldSyntax = self.syntax
@@ -738,14 +812,14 @@ class MibScalarInstance(MibTree):
self.syntax = self.__newSyntax
# noinspection PyAttributeOutsideInit
- def writeCleanup(self, name, val, idx, acInfo):
+ def writeCleanup(self, varBind, **context):
self.branchVersionId += 1
debug.logger & debug.flagIns and debug.logger('writeCleanup: %s=%r' % (name, val))
# Drop previous value
self.__newSyntax = self.__oldSyntax = None
# noinspection PyAttributeOutsideInit
- def writeUndo(self, name, val, idx, acInfo):
+ def writeUndo(self, varBind, **context):
# Revive previous value
self.syntax = self.__oldSyntax
self.__newSyntax = self.__oldSyntax = None
@@ -755,57 +829,70 @@ class MibScalarInstance(MibTree):
# Create operation
# noinspection PyUnusedLocal,PyAttributeOutsideInit
- def createTest(self, name, val, idx, acInfo):
+ def createTest(self, varBind, **context):
+ name, val = varBind
+
if name == self.name:
try:
- self.__newSyntax = self.setValue(val, name, idx)
+ self.__newSyntax = self.setValue(val, name, **context)
+
except error.MibOperationError:
# SMI exceptions may carry additional content
why = sys.exc_info()[1]
if 'syntax' in why:
self.__newSyntax = why['syntax']
else:
- raise error.WrongValueError(idx=idx, name=name, msg=sys.exc_info()[1])
+ raise error.WrongValueError(name=name, idx=context.get('idx'), msg=sys.exc_info()[1])
else:
- raise error.NoSuchInstanceError(idx=idx, name=name)
+ raise error.NoSuchInstanceError(name=name, idx=context.get('idx'))
+
+ def createCommit(self, varBind, **context):
+ name, val = varBind
- def createCommit(self, name, val, idx, acInfo):
if val is not None:
- self.writeCommit(name, val, idx, acInfo)
+ self.writeCommit(varBind, **context)
- def createCleanup(self, name, val, idx, acInfo):
+ def createCleanup(self, varBind, **context):
self.branchVersionId += 1
+ name, val = varBind
+
debug.logger & debug.flagIns and debug.logger('createCleanup: %s=%r' % (name, val))
+
if val is not None:
- self.writeCleanup(name, val, idx, acInfo)
+ self.writeCleanup(varBind, **context)
+
+ def createUndo(self, varBind, **context):
+ name, val = varBind
- def createUndo(self, name, val, idx, acInfo):
if val is not None:
- self.writeUndo(name, val, idx, acInfo)
+ self.writeUndo(varBind, **context)
# Destroy operation
# noinspection PyUnusedLocal,PyAttributeOutsideInit
- def destroyTest(self, name, val, idx, acInfo):
+ def destroyTest(self, varBind, **context):
+ name, val = varBind
+
if name == self.name:
try:
- self.__newSyntax = self.setValue(val, name, idx)
+ self.__newSyntax = self.setValue(val, name, **context)
+
except error.MibOperationError:
# SMI exceptions may carry additional content
why = sys.exc_info()[1]
if 'syntax' in why:
self.__newSyntax = why['syntax']
else:
- raise error.NoSuchInstanceError(idx=idx, name=name)
+ raise error.NoSuchInstanceError(name=name, idx=context.get('idx'))
- def destroyCommit(self, name, val, idx, acInfo):
+ def destroyCommit(self, varBind, **context):
pass
# noinspection PyUnusedLocal
- def destroyCleanup(self, name, val, idx, acInfo):
+ def destroyCleanup(self, varBind, **context):
self.branchVersionId += 1
- def destroyUndo(self, name, val, idx, acInfo):
+ def destroyUndo(self, varBind, **context):
pass
@@ -827,10 +914,10 @@ class MibTableColumn(MibScalar):
# Missing leaves are indicated by the NoSuchInstanceError exception.
#
- def getBranch(self, name, idx):
+ def getBranch(self, name, **context):
if name in self._vars:
return self._vars[name]
- raise error.NoSuchInstanceError(name=name, idx=idx)
+ raise error.NoSuchInstanceError(name=name, idx=context.get('idx'))
def setProtoInstance(self, protoInstance):
self.protoInstance = protoInstance
@@ -839,50 +926,63 @@ class MibTableColumn(MibScalar):
# machine for clarity). Also, it might be a good idea to inidicate
# defaulted cols creation in a clearer way than just a val == None.
- def createTest(self, name, val, idx, acInfo):
- (acFun, acCtx) = acInfo
+ def createTest(self, varBind, **context):
+ name, val = varBind
+
# Make sure creation allowed, create a new column instance but
# do not replace the old one
if name == self.name:
- raise error.NoAccessError(idx=idx, name=name)
+ raise error.NoAccessError(name=name, idx=context.get('idx'))
+
+ acFun = context.get('acFun')
if acFun:
- if val is not None and self.maxAccess != 'readcreate' or \
- acFun(name, self.syntax, idx, 'write', acCtx):
+ if (val is not None and self.maxAccess != 'readcreate' or
+ acFun('write', (name, self.syntax), **context)):
debug.logger & debug.flagACL and debug.logger(
'createTest: %s=%r %s at %s' % (name, val, self.maxAccess, self.name))
- raise error.NoCreationError(idx=idx, name=name)
+ raise error.NoCreationError(name=name, idx=context.get('idx'))
+
# Create instances if either it does not yet exist (row creation)
# or a value is passed (multiple OIDs in SET PDU)
if val is None and name in self.__createdInstances:
return
+
self.__createdInstances[name] = self.protoInstance(
self.name, name[len(self.name):], self.syntax.clone()
)
- self.__createdInstances[name].createTest(name, val, idx, acInfo)
- def createCommit(self, name, val, idx, acInfo):
+ self.__createdInstances[name].createTest(varBind, **context)
+
+ def createCommit(self, varBind, **context):
+ name, val = varBind
+
# Commit new instance value
if name in self._vars: # XXX
if name in self.__createdInstances:
- self._vars[name].createCommit(name, val, idx, acInfo)
+ self._vars[name].createCommit(varBind, **context)
return
- self.__createdInstances[name].createCommit(name, val, idx, acInfo)
+
+ self.__createdInstances[name].createCommit(varBind, **context)
+
# ...commit new column instance
- self._vars[name], self.__createdInstances[name] = \
- self.__createdInstances[name], self._vars.get(name)
+ self._vars[name], self.__createdInstances[name] = self.__createdInstances[name], self._vars.get(name)
+
+ def createCleanup(self, varBind, **context):
+ name, val = varBind
- def createCleanup(self, name, val, idx, acInfo):
# Drop previous column instance
self.branchVersionId += 1
if name in self.__createdInstances:
if self.__createdInstances[name] is not None:
- self.__createdInstances[name].createCleanup(name, val, idx,
- acInfo)
+ self.__createdInstances[name].createCleanup(varBind, **context)
del self.__createdInstances[name]
+
elif name in self._vars:
- self._vars[name].createCleanup(name, val, idx, acInfo)
+ self._vars[name].createCleanup(varBind, **context)
+
+ def createUndo(self, varBind, **context):
+ name, val = varBind
- def createUndo(self, name, val, idx, acInfo):
# Set back previous column instance, drop the new one
if name in self.__createdInstances:
self._vars[name] = self.__createdInstances[name]
@@ -890,60 +990,77 @@ class MibTableColumn(MibScalar):
# Remove new instance on rollback
if self._vars[name] is None:
del self._vars[name]
+
else:
# Catch half-created instances (hackerish)
try:
self._vars[name] == 0
+
except PyAsn1Error:
del self._vars[name]
+
else:
- self._vars[name].createUndo(name, val, idx, acInfo)
+ self._vars[name].createUndo(varBind, **context)
# Column destruction
- def destroyTest(self, name, val, idx, acInfo):
- (acFun, acCtx) = acInfo
+ def destroyTest(self, varBind, **context):
+ name, val = varBind
+
# Make sure destruction is allowed
if name == self.name:
- raise error.NoAccessError(idx=idx, name=name)
+ raise error.NoAccessError(name=name, idx=context.get('idx'))
+
if name not in self._vars:
return
+
+ acFun = context.get('acFun')
if acFun:
- if val is not None and self.maxAccess != 'readcreate' or \
- acFun(name, self.syntax, idx, 'write', acCtx):
- raise error.NoAccessError(idx=idx, name=name)
- self._vars[name].destroyTest(name, val, idx, acInfo)
+ if (val is not None and self.maxAccess != 'readcreate' or
+ acFun('write', (name, self.syntax), **context)):
+ raise error.NoAccessError(name=name, idx=context.get('idx'))
+
+ self._vars[name].destroyTest(varBind, **context)
+
+ def destroyCommit(self, varBind, **context):
+ name, val = varBind
- def destroyCommit(self, name, val, idx, acInfo):
# Make a copy of column instance and take it off the tree
if name in self._vars:
- self._vars[name].destroyCommit(name, val, idx, acInfo)
+ self._vars[name].destroyCommit(varBind, **context)
self.__destroyedInstances[name] = self._vars[name]
del self._vars[name]
- def destroyCleanup(self, name, val, idx, acInfo):
+ def destroyCleanup(self, varBind, **context):
+ name, val = varBind
+
# Drop instance copy
self.branchVersionId += 1
+
if name in self.__destroyedInstances:
- self.__destroyedInstances[name].destroyCleanup(name, val,
- idx, acInfo)
+ self.__destroyedInstances[name].destroyCleanup(varBind, **context)
debug.logger & debug.flagIns and debug.logger('destroyCleanup: %s=%r' % (name, val))
del self.__destroyedInstances[name]
- def destroyUndo(self, name, val, idx, acInfo):
+ def destroyUndo(self, varBind, **context):
+ name, val = varBind
+
# Set back column instance
if name in self.__destroyedInstances:
self._vars[name] = self.__destroyedInstances[name]
- self._vars[name].destroyUndo(name, val, idx, acInfo)
+ self._vars[name].destroyUndo(varBind, **context)
del self.__destroyedInstances[name]
# Set/modify column
- def writeTest(self, name, val, idx, acInfo):
+ def writeTest(self, varBind, **context):
+ name, val = varBind
+
# Besides common checks, request row creation on no-instance
try:
# First try the instance
- MibScalar.writeTest(self, name, val, idx, acInfo)
+ MibScalar.writeTest(self, varBind, **context)
+
# ...otherwise proceed with creating new column
except (error.NoSuchInstanceError, error.RowCreationWanted):
excValue = sys.exc_info()[1]
@@ -951,42 +1068,60 @@ class MibTableColumn(MibScalar):
self.__rowOpWanted[name] = excValue
else:
self.__rowOpWanted[name] = error.RowCreationWanted()
- self.createTest(name, val, idx, acInfo)
+ self.createTest(varBind, **context)
+
except error.RowDestructionWanted:
self.__rowOpWanted[name] = error.RowDestructionWanted()
- self.destroyTest(name, val, idx, acInfo)
+ self.destroyTest(varBind, **context)
+
if name in self.__rowOpWanted:
debug.logger & debug.flagIns and debug.logger(
'%s flagged by %s=%r, exception %s' % (self.__rowOpWanted[name], name, val, sys.exc_info()[1]))
raise self.__rowOpWanted[name]
- def __delegateWrite(self, subAction, name, val, idx, acInfo):
+ def __delegateWrite(self, subAction, varBind, **context):
+ name, val = varBind
+
if name not in self.__rowOpWanted:
- getattr(MibScalar, 'write' + subAction)(self, name, val, idx, acInfo)
- return
+ actionFun = getattr(MibScalar, 'write' + subAction)
+ return actionFun(self, varBind, **context)
+
if isinstance(self.__rowOpWanted[name], error.RowCreationWanted):
- getattr(self, 'create' + subAction)(name, val, idx, acInfo)
+ actionFun = getattr(self, 'create' + subAction)
+ return actionFun(varBind, **context)
+
if isinstance(self.__rowOpWanted[name], error.RowDestructionWanted):
- getattr(self, 'destroy' + subAction)(name, val, idx, acInfo)
+ actionFun = getattr(self, 'destroy' + subAction)
+ return actionFun(varBind, **context)
- def writeCommit(self, name, val, idx, acInfo):
- self.__delegateWrite('Commit', name, val, idx, acInfo)
+ def writeCommit(self, varBind, **context):
+ name, val = varBind
+
+ self.__delegateWrite('Commit', varBind, **context)
if name in self.__rowOpWanted:
raise self.__rowOpWanted[name]
- def writeCleanup(self, name, val, idx, acInfo):
+ def writeCleanup(self, varBind, **context):
+ name, val = varBind
+
self.branchVersionId += 1
- self.__delegateWrite('Cleanup', name, val, idx, acInfo)
+
+ self.__delegateWrite('Cleanup', varBind, **context)
+
if name in self.__rowOpWanted:
e = self.__rowOpWanted[name]
del self.__rowOpWanted[name]
debug.logger & debug.flagIns and debug.logger('%s dropped by %s=%r' % (e, name, val))
raise e
- def writeUndo(self, name, val, idx, acInfo):
+ def writeUndo(self, varBind, **context):
+ name, val = varBind
+
if name in self.__rowOpWanted:
self.__rowOpWanted[name] = error.RowDestructionWanted()
- self.__delegateWrite('Undo', name, val, idx, acInfo)
+
+ self.__delegateWrite('Undo', varBind, **context)
+
if name in self.__rowOpWanted:
e = self.__rowOpWanted[name]
del self.__rowOpWanted[name]
@@ -1075,7 +1210,9 @@ class MibTableRow(MibTree):
# Fate sharing mechanics
- def announceManagementEvent(self, action, name, val, idx, acInfo):
+ def announceManagementEvent(self, action, varBind, **context):
+ name, val = varBind
+
# Convert OID suffix into index vals
instId = name[len(self.name) + 1:]
baseIndices = []
@@ -1096,14 +1233,14 @@ class MibTableRow(MibTree):
if not baseIndices:
return
- for modName, mibSym in self.augmentingRows.keys():
+ for modName, mibSym in self.augmentingRows:
mibObj, = mibBuilder.importSymbols(modName, mibSym)
debug.logger & debug.flagIns and debug.logger('announceManagementEvent %s to %s' % (action, mibObj))
- mibObj.receiveManagementEvent(
- action, baseIndices, val, idx, acInfo
- )
+ mibObj.receiveManagementEvent(action, (baseIndices, val), **context)
+
+ def receiveManagementEvent(self, action, varBind, **context):
+ baseIndices, val = varBind
- def receiveManagementEvent(self, action, baseIndices, val, idx, acInfo):
# The default implementation supports one-to-one rows dependency
newSuffix = ()
# Resolve indices intersection
@@ -1118,7 +1255,7 @@ class MibTableRow(MibTree):
if newSuffix:
debug.logger & debug.flagIns and debug.logger(
'receiveManagementEvent %s for suffix %s' % (action, newSuffix))
- self.__manageColumns(action, (), newSuffix, val, idx, acInfo)
+ self.__manageColumns(action, (), (newSuffix, val), **context)
def registerAugmentions(self, *names):
for modName, symName in names:
@@ -1137,8 +1274,9 @@ class MibTableRow(MibTree):
def getIndexNames(self):
return self.indexNames
- def __manageColumns(self, action, excludeName, nameSuffix,
- val, idx, acInfo):
+ def __manageColumns(self, action, excludeName, varBind, **context):
+ nameSuffix, val = varBind
+
# Build a map of index names and values for automatic initialization
indexVals = {}
instId = nameSuffix
@@ -1154,65 +1292,71 @@ class MibTableRow(MibTree):
if name == excludeName:
continue
+ actionFun = getattr(var, action)
+
if name in indexVals:
- getattr(var, action)(name + nameSuffix, indexVals[name], idx,
- (None, None))
+ # NOTE(etingof): disable VACM call
+ _context = context.copy()
+ _context.pop('acFun', None)
+
+ actionFun((name + nameSuffix, indexVals[name]), **_context)
else:
- getattr(var, action)(name + nameSuffix, val, idx, acInfo)
+ actionFun((name + nameSuffix, val), **context)
debug.logger & debug.flagIns and debug.logger('__manageColumns: action %s name %s suffix %s %svalue %r' % (
action, name, nameSuffix, name in indexVals and "index " or "", indexVals.get(name, val)))
- def __delegate(self, subAction, name, val, idx, acInfo):
+ def __delegate(self, subAction, varBind, **context):
+ name, val = varBind
+
# Relay operation request to column, expect row operation request.
rowIsActive = False
+
try:
- getattr(self.getBranch(name, idx), 'write' + subAction)(
- name, val, idx, acInfo
- )
+ writeFun = getattr(self.getBranch(name, **context), 'write' + subAction)
+ writeFun(varBind, **context)
except error.RowCreationWanted:
+ createAction = 'create' + subAction
+
self.__manageColumns(
- 'create' + subAction, name[:len(self.name) + 1],
- name[len(self.name) + 1:], None, idx, acInfo
+ createAction, name[:len(self.name) + 1], (name[len(self.name) + 1:], None), **context
)
- self.announceManagementEvent(
- 'create' + subAction, name, None, idx, acInfo
- )
+ self.announceManagementEvent(createAction, (name, None), **context)
# watch for RowStatus == 'stActive'
rowIsActive = sys.exc_info()[1].get('syntax', 0) == 1
except error.RowDestructionWanted:
+ destroyAction = 'destroy' + subAction
+
self.__manageColumns(
- 'destroy' + subAction, name[:len(self.name) + 1],
- name[len(self.name) + 1:], None, idx, acInfo
+ destroyAction, name[:len(self.name) + 1], (name[len(self.name) + 1:], None), **context
)
- self.announceManagementEvent(
- 'destroy' + subAction, name, None, idx, acInfo
- )
+ self.announceManagementEvent(destroyAction, (name, None), **context)
return rowIsActive
- def writeTest(self, name, val, idx, acInfo):
- self.__delegate('Test', name, val, idx, acInfo)
+ def writeTest(self, varBind, **context):
+ self.__delegate('Test', varBind, **context)
- def writeCommit(self, name, val, idx, acInfo):
- rowIsActive = self.__delegate('Commit', name, val, idx, acInfo)
+ def writeCommit(self, varBind, **context):
+ name, val = varBind
+ rowIsActive = self.__delegate('Commit', varBind, **context)
if rowIsActive:
for mibNode in self._vars.values():
- colNode = mibNode.getNode(mibNode.name + name[len(self.name) + 1:])
+ colNode = mibNode.getNode(mibNode.name + name[len(self.name) + 1:], **context)
if not colNode.syntax.hasValue():
raise error.InconsistentValueError(msg='Row consistency check failed for %r' % colNode)
- def writeCleanup(self, name, val, idx, acInfo):
+ def writeCleanup(self, varBind, **context):
self.branchVersionId += 1
- self.__delegate('Cleanup', name, val, idx, acInfo)
+ self.__delegate('Cleanup', varBind, **context)
- def writeUndo(self, name, val, idx, acInfo):
- self.__delegate('Undo', name, val, idx, acInfo)
+ def writeUndo(self, varBind, **context):
+ self.__delegate('Undo', varBind, **context)
# Table row management