Compare commits

...

5 Commits

Author SHA1 Message Date
Ilya Etingof 96fac697b4 Merge branch 'mib-instrumentation-api-overhaul' of github.com:etingof/pysnmp into mib-instrumentation-api-overhaul 2018-06-29 09:41:47 +02:00
Ilya Etingof 6b25affd2f 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.
2018-06-29 09:41:13 +02:00
Ilya Etingof a537119944 Merge branch 'mib-instrumentation-api-overhaul' of github.com:etingof/pysnmp into mib-instrumentation-api-overhaul 2018-06-28 08:31:27 +02:00
Ilya Etingof 6236611469 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.
2018-06-28 08:27:20 +02:00
Ilya Etingof 27c7bd0116 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.
2018-06-27 10:18:30 +02:00
10 changed files with 678 additions and 425 deletions

View File

@ -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
-----------------------------------

View File

@ -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())

View File

@ -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()))

View File

@ -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]

View File

@ -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 ---

View File

@ -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)
)

View File

@ -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

View File

@ -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)
)

View File

@ -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)

File diff suppressed because it is too large Load Diff