pysnmp-sky/pysnmp/hlapi/lcd.py

280 lines
11 KiB
Python

#
# This file is part of pysnmp software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pysnmp.sf.net/license.html
#
from pysnmp.entity import config
from pysnmp import nextid, error
from pysnmp.hlapi.auth import *
__all__ = ['CommandGeneratorLcdConfigurator',
'NotificationOriginatorLcdConfigurator']
class AbstractLcdConfigurator(object):
nextID = nextid.Integer(0xffffffff)
cacheKeys = []
def _getCache(self, snmpEngine):
cacheId = self.__class__.__name__
cache = snmpEngine.getUserContext(cacheId)
if cache is None:
cache = dict([(x, {}) for x in self.cacheKeys])
snmpEngine.setUserContext(**{cacheId: cache})
return cache
def configure(self, snmpEngine, authData, transportTarget, *options):
pass
def unconfigure(self, snmpEngine, authData=None):
pass
class CommandGeneratorLcdConfigurator(AbstractLcdConfigurator):
cacheKeys = ['auth', 'parm', 'tran', 'addr']
def configure(self, snmpEngine, authData, transportTarget, *options):
cache = self._getCache(snmpEngine)
if isinstance(authData, CommunityData):
if authData.communityIndex not in cache['auth']:
config.addV1System(
snmpEngine,
authData.communityIndex,
authData.communityName,
authData.contextEngineId,
authData.contextName,
authData.tag,
authData.securityName
)
cache['auth'][authData.communityIndex] = authData
elif isinstance(authData, UsmUserData):
authDataKey = authData.userName, authData.securityEngineId
if authDataKey not in cache['auth']:
config.addV3User(
snmpEngine,
authData.userName,
authData.authProtocol, authData.authKey,
authData.privProtocol, authData.privKey,
authData.securityEngineId,
securityName=authData.securityName
)
cache['auth'][authDataKey] = authData
else:
raise error.PySnmpError('Unsupported authentication object')
paramsKey = (authData.securityName,
authData.securityLevel,
authData.mpModel)
if paramsKey in cache['parm']:
paramsName, useCount = cache['parm'][paramsKey]
cache['parm'][paramsKey] = paramsName, useCount + 1
else:
paramsName = 'p%s' % self.nextID()
config.addTargetParams(
snmpEngine, paramsName,
authData.securityName, authData.securityLevel, authData.mpModel
)
cache['parm'][paramsKey] = paramsName, 1
if transportTarget.transportDomain in cache['tran']:
transport, useCount = cache['tran'][transportTarget.transportDomain]
transportTarget.verifyDispatcherCompatibility(snmpEngine)
cache['tran'][transportTarget.transportDomain] = transport, useCount + 1
elif config.getTransport(snmpEngine, transportTarget.transportDomain):
transportTarget.verifyDispatcherCompatibility(snmpEngine)
else:
transport = transportTarget.openClientMode()
config.addTransport(
snmpEngine,
transportTarget.transportDomain,
transport
)
cache['tran'][transportTarget.transportDomain] = transport, 1
transportKey = (paramsName, transportTarget.transportDomain,
transportTarget.transportAddr,
transportTarget.tagList)
if transportKey in cache['addr']:
addrName, useCount = cache['addr'][transportKey]
cache['addr'][transportKey] = addrName, useCount + 1
else:
addrName = 'a%s' % self.nextID()
config.addTargetAddr(
snmpEngine, addrName,
transportTarget.transportDomain,
transportTarget.transportAddr,
paramsName,
transportTarget.timeout * 100,
transportTarget.retries,
transportTarget.tagList
)
cache['addr'][transportKey] = addrName, 1
return addrName, paramsName
def unconfigure(self, snmpEngine, authData=None):
cache = self._getCache(snmpEngine)
if authData:
if isinstance(authData, CommunityData):
authDataKey = authData.communityIndex
elif isinstance(authData, UsmUserData):
authDataKey = authData.userName, authData.securityEngineId
else:
raise error.PySnmpError('Unsupported authentication object')
if authDataKey in cache['auth']:
authDataKeys = (authDataKey,)
else:
raise error.PySnmpError('Unknown authData %s' % (authData,))
else:
authDataKeys = list(cache['auth'].keys())
addrNames, paramsNames = set(), set()
for authDataKey in authDataKeys:
authDataX = cache['auth'][authDataKey]
del cache['auth'][authDataKey]
if isinstance(authDataX, CommunityData):
config.delV1System(
snmpEngine,
authDataX.communityIndex
)
elif isinstance(authDataX, UsmUserData):
config.delV3User(
snmpEngine,
authDataX.userName,
authDataX.securityEngineId
)
else:
raise error.PySnmpError('Unsupported authentication object')
paramsKey = (authDataX.securityName,
authDataX.securityLevel,
authDataX.mpModel)
if paramsKey in cache['parm']:
paramsName, useCount = cache['parm'][paramsKey]
useCount -= 1
if useCount:
cache['parm'][paramsKey] = paramsName, useCount
else:
del cache['parm'][paramsKey]
config.delTargetParams(
snmpEngine, paramsName
)
paramsNames.add(paramsName)
else:
raise error.PySnmpError('Unknown target %s' % (paramsKey,))
addrKeys = [x for x in cache['addr'] if x[0] == paramsName]
for addrKey in addrKeys:
addrName, useCount = cache['addr'][addrKey]
useCount -= 1
if useCount:
cache['addr'][addrKey] = addrName, useCount
else:
config.delTargetAddr(snmpEngine, addrName)
addrNames.add(addrKey)
if addrKey[1] in cache['tran']:
transport, useCount = cache['tran'][addrKey[1]]
if useCount > 1:
useCount -= 1
cache['tran'][addrKey[1]] = transport, useCount
else:
config.delTransport(snmpEngine, addrKey[1])
transport.closeTransport()
del cache['tran'][addrKey[1]]
return addrNames, paramsNames
class NotificationOriginatorLcdConfigurator(AbstractLcdConfigurator):
cacheKeys = ['auth', 'name']
_cmdGenLcdCfg = CommandGeneratorLcdConfigurator()
def configure(self, snmpEngine, authData, transportTarget, *options):
cache = self._getCache(snmpEngine)
notifyType = options and options[0] or 'trap'
notifyName = None
# Create matching transport tags if not given by user. Not good!
if not transportTarget.tagList:
transportTarget.tagList = str(
hash((authData.securityName, transportTarget.transportAddr))
)
if isinstance(authData, CommunityData) and not authData.tag:
authData.tag = transportTarget.tagList.split()[0]
addrName, paramsName = self._cmdGenLcdCfg.configure(snmpEngine, authData, transportTarget)
tagList = transportTarget.tagList.split()
if not tagList:
tagList = ['']
for tag in tagList:
notifyNameKey = paramsName, tag, notifyType
if notifyNameKey in cache['name']:
notifyName, paramsName, useCount = cache['name'][notifyNameKey]
cache['name'][notifyNameKey] = notifyName, paramsName, useCount + 1
else:
notifyName = 'n%s' % self.nextID()
config.addNotificationTarget(
snmpEngine,
notifyName,
paramsName,
tag,
notifyType
)
cache['name'][notifyNameKey] = notifyName, paramsName, 1
authDataKey = authData.securityName, authData.securityModel
if authDataKey in cache['auth']:
authDataX, subTree, useCount = cache['auth'][authDataKey]
cache['auth'][authDataKey] = authDataX, subTree, useCount + 1
else:
subTree = (1, 3, 6)
config.addTrapUser(snmpEngine, authData.securityModel,
authData.securityName, authData.securityLevel,
subTree)
cache['auth'][authDataKey] = authData, subTree, 1
return notifyName
def unconfigure(self, snmpEngine, authData=None):
cache = self._getCache(snmpEngine)
if authData:
authDataKey = authData.securityName, authData.securityModel
if authDataKey in cache['auth']:
authDataKeys = (authDataKey,)
else:
raise error.PySnmpError('Unknown authData %s' % (authData,))
else:
authDataKeys = tuple(cache['auth'].keys())
addrNames, paramsNames = self._cmdGenLcdCfg.unconfigure(snmpEngine, authData)
notifyAndParamsNames = [(cache['name'][x], x) for x in cache['name'].keys() if x[0] in paramsNames]
for (notifyName, paramsName, useCount), notifyNameKey in notifyAndParamsNames:
useCount -= 1
if useCount:
cache['name'][notifyNameKey] = notifyName, paramsName, useCount
else:
config.delNotificationTarget(
snmpEngine, notifyName, paramsName
)
del cache['name'][notifyNameKey]
for authDataKey in authDataKeys:
authDataX, subTree, useCount = cache['auth'][authDataKey]
useCount -= 1
if useCount:
cache['auth'][authDataKey] = authDataX, subTree, useCount
else:
config.delTrapUser(
snmpEngine, authDataX.securityModel,
authDataX.securityName, authDataX.securityLevel,
subTree
)
del cache['auth'][authDataKey]