diff options
author | elie <elie> | 2015-05-17 21:01:43 +0000 |
---|---|---|
committer | elie <elie> | 2015-05-17 21:01:43 +0000 |
commit | a4fb54639e97cb572689e24a5c5e42b4f66a62e0 (patch) | |
tree | 96ae7dcd54ba6cbc090d33018993f4f993bab72e /pysnmp | |
parent | 1118e0d43b694f8a1b68e4d0b9d72b2e7e6c8277 (diff) | |
download | pysnmp-a4fb54639e97cb572689e24a5c5e42b4f66a62e0.tar.gz |
- Initial PySMI integration. Original ASN.1 MIBs could now be parsed, stored
at a local pysnmp MIBs repository and loaded into SNMP Engine.
- smi.MibBuilder will now raise more specific exceptions (MibLoadError,
MibNotFoundError) on MIB loading problems rather than more generic
SmiError.
- MibBuilder.addMibSources() convenience method added.
Diffstat (limited to 'pysnmp')
-rw-r--r-- | pysnmp/entity/rfc3413/oneliner/mibvar.py | 13 | ||||
-rw-r--r-- | pysnmp/smi/builder.py | 126 | ||||
-rw-r--r-- | pysnmp/smi/compiler.py | 62 | ||||
-rw-r--r-- | pysnmp/smi/error.py | 3 |
4 files changed, 150 insertions, 54 deletions
diff --git a/pysnmp/entity/rfc3413/oneliner/mibvar.py b/pysnmp/entity/rfc3413/oneliner/mibvar.py index 6846334..cb7b163 100644 --- a/pysnmp/entity/rfc3413/oneliner/mibvar.py +++ b/pysnmp/entity/rfc3413/oneliner/mibvar.py @@ -1,5 +1,6 @@ from pysnmp.proto import rfc1902 from pysnmp.smi.builder import ZipMibSource +from pysnmp.smi.compiler import addMibCompiler from pysnmp.error import PySnmpError from pyasn1.error import PyAsn1Error @@ -20,6 +21,7 @@ class MibVariable: def __init__(self, *args): self.__args = args self.__mibSourcesToAdd = self.__modNamesToLoad = None + self.__asn1SourcesToAdd = None self.__state = self.stDirty # @@ -56,6 +58,10 @@ class MibVariable: # A gateway to MIBs manipulation routines # + def addAsn1Sources(self, *asn1Sources): + self.__asn1SourcesToAdd = asn1Sources + return self + def addMibSource(self, *mibSources): self.__mibSourcesToAdd = mibSources return self @@ -75,6 +81,13 @@ class MibVariable: mibViewController.mibBuilder.setMibSources(*mibSources) self.__mibSourcesToAdd = None + if self.__asn1SourcesToAdd is not None: + addMibCompiler( + mibViewController.mibBuilder, + sources=self.__asn1SourcesToAdd + ) + self.__asn1SourcesToAdd = None + if self.__modNamesToLoad is not None: mibViewController.mibBuilder.loadModules(*self.__modNamesToLoad) self.__modNamesToLoad = None diff --git a/pysnmp/smi/builder.py b/pysnmp/smi/builder.py index 610e89d..795da83 100644 --- a/pysnmp/smi/builder.py +++ b/pysnmp/smi/builder.py @@ -200,17 +200,7 @@ class MibBuilder: defaultCoreMibs = os.pathsep.join( ('pysnmp.smi.mibs.instances', 'pysnmp.smi.mibs') ) - if sys.platform[:3] == 'win': - defaultMiscMibs = os.pathsep.join( - ( os.path.join(os.path.expanduser("~"), - 'PySNMP Configuration', 'mibs'), - 'pysnmp_mibs' ) - ) - else: - defaultMiscMibs = os.pathsep.join( - ( os.path.join(os.path.expanduser("~"), '.pysnmp', 'mibs'), - 'pysnmp_mibs' ) - ) + defaultMiscMibs = 'pysnmp_mibs' moduleID = 'PYSNMP_MODULE_ID' def __init__(self): self.lastBuildId = self._autoName = 0 @@ -229,13 +219,29 @@ class MibBuilder: self.mibSymbols = {} self.__modSeen = {} self.__modPathsSeen = {} + self.__mibCompiler = None self.setMibSources(*sources) - + + # MIB compiler management + + def getMibCompiler(self): + return self.__mibCompiler + + def setMibCompiler(self, mibCompiler, destDir): + self.addMibSources(DirMibSource(destDir)) + self.__mibCompiler = mibCompiler + return self + # MIB modules management + def addMibSources(self, *mibSources): + self.__mibSources.extend([ s.init() for s in mibSources ]) + debug.logger & debug.flagBld and debug.logger('addMibSources: new MIB sources %s' % (self.__mibSources,)) + + def setMibSources(self, *mibSources): self.__mibSources = [ s.init() for s in mibSources ] - debug.logger & debug.flagBld and debug.logger('setMibPath: new MIB sources %s' % (self.__mibSources,)) + debug.logger & debug.flagBld and debug.logger('setMibSources: new MIB sources %s' % (self.__mibSources,)) def getMibSources(self): return tuple(self.__mibSources) @@ -254,6 +260,49 @@ class MibBuilder: ) return paths + def loadModule(self, modName, **userCtx): + for mibSource in self.__mibSources: + debug.logger & debug.flagBld and debug.logger('loadModule: trying %s at %s' % (modName, mibSource)) + try: + modData, sfx = mibSource.read(modName) + except IOError: + debug.logger & debug.flagBld and debug.logger('loadModule: read %s from %s failed: %s' % (modName, mibSource, sys.exc_info()[1])) + continue + + modPath = mibSource.fullPath(modName, sfx) + + if modPath in self.__modPathsSeen: + debug.logger & debug.flagBld and debug.logger('loadModule: seen %s' % modPath) + break + else: + self.__modPathsSeen[modPath] = 1 + + debug.logger & debug.flagBld and debug.logger('loadModule: evaluating %s' % modPath) + + g = { 'mibBuilder': self, + 'userCtx': userCtx } + + try: + exec(modData, g) + except Exception: + del self.__modPathsSeen[modPath] + raise error.MibLoadError( + 'MIB module \"%s\" load error: %s' % (modPath, traceback.format_exception(*sys.exc_info())) + ) + + self.__modSeen[modName] = modPath + + debug.logger & debug.flagBld and debug.logger('loadModule: loaded %s' % modPath) + + break + + if modName not in self.__modSeen: + raise error.MibNotFoundError( + 'MIB file \"%s\" not found in search path (%s)' % (modName and modName + ".py[co]", ', '.join([str(x) for x in self.__mibSources])) + ) + + return self + def loadModules(self, *modNames, **userCtx): # Build a list of available modules if not modNames: @@ -263,50 +312,19 @@ class MibBuilder: modNames[modName] = None modNames = list(modNames.keys()) if not modNames: - raise error.SmiError( + raise error.MibNotFoundError( 'No MIB module to load at %s' % (self,) - ) + ) for modName in modNames: - for mibSource in self.__mibSources: - debug.logger & debug.flagBld and debug.logger('loadModules: trying %s at %s' % (modName, mibSource)) - try: - modData, sfx = mibSource.read(modName) - except IOError: - debug.logger & debug.flagBld and debug.logger('loadModules: read %s from %s failed: %s' % (modName, mibSource, sys.exc_info()[1])) - continue - - modPath = mibSource.fullPath(modName, sfx) - - if modPath in self.__modPathsSeen: - debug.logger & debug.flagBld and debug.logger('loadModules: seen %s' % modPath) - break - else: - self.__modPathsSeen[modPath] = 1 - - debug.logger & debug.flagBld and debug.logger('loadModules: evaluating %s' % modPath) - - g = { 'mibBuilder': self, - 'userCtx': userCtx } - - try: - exec(modData, g) - except Exception: - del self.__modPathsSeen[modPath] - raise error.SmiError( - 'MIB module \"%s\" load error: %s' % (modPath, traceback.format_exception(*sys.exc_info())) - ) - - self.__modSeen[modName] = modPath - - debug.logger & debug.flagBld and debug.logger('loadModules: loaded %s' % modPath) - - break - - if modName not in self.__modSeen: - raise error.SmiError( - 'MIB file \"%s\" not found in search path (%s)' % (modName and modName + ".py[co]", ', '.join([str(x) for x in self.__mibSources])) - ) + try: + self.loadModule(modName, **userCtx) + except error.MibNotFoundError: + if self.__mibCompiler: + debug.logger & debug.flagBld and debug.logger('loadModules: calling MIB compiler for %s' % modName) + self.__mibCompiler.compile(modName) + # in case this missing MIB becomes available + self.loadModule(modName, **userCtx) return self diff --git a/pysnmp/smi/compiler.py b/pysnmp/smi/compiler.py new file mode 100644 index 0000000..80e041c --- /dev/null +++ b/pysnmp/smi/compiler.py @@ -0,0 +1,62 @@ +# +# Attach PySMI MIB compiler to PySNMP MIB builder and configure +# both accordingly. +# +import os +import sys +try: + from pysmi.reader.url import getReadersFromUrls + from pysmi.searcher.pypackage import PyPackageSearcher + from pysmi.searcher.stub import StubSearcher + from pysmi.borrower.pyfile import PyFileBorrower + from pysmi.writer.pyfile import PyFileWriter + from pysmi.parser.smi import parserFactory + from pysmi.parser.dialect import smiV1Relaxed + from pysmi.codegen.pysnmp import PySnmpCodeGen, baseMibs + from pysmi.compiler import MibCompiler + +except ImportError: + from pysnmp.smi import error + + def addMibCompiler(mibBuilder, + sources=defaultSources, + destination=defaultDest, + borrowers=defaultBorrowers): + raise error.SmiError('MIB compiler not available (pysmi not installed)') + +else: + defaultSources = [ 'file:///usr/share/snmp/mibs' ] + + if sys.platform[:3] == 'win': + defaultDest = os.path.join(os.path.expanduser("~"), + 'PySNMP Configuration', 'mibs') + else: + defaultDest = os.path.join(os.path.expanduser("~"), '.pysnmp', 'mibs') + + defaultBorrowers = [] + + def addMibCompiler(mibBuilder, + sources=defaultSources, + destination=defaultDest, + borrowers=defaultBorrowers): + + compiler = MibCompiler( + parserFactory(**smiV1Relaxed)(), + PySnmpCodeGen(), + PyFileWriter(destination) + ) + + compiler.addSources(*getReadersFromUrls(*sources)) + + compiler.addSearchers( + StubSearcher(*baseMibs) # XXX + ) + compiler.addSearchers( + *[ PyPackageSearcher(x.fullPath()) for x in mibBuilder.getMibSources() ] + ) + + compiler.addBorrowers( + *[ PyFileBorrower(x) for x in getReadersFromUrls(*borrowers, originalMatching=False, lowcaseMatching=False) ] + ) + + mibBuilder.setMibCompiler(compiler, destination) diff --git a/pysnmp/smi/error.py b/pysnmp/smi/error.py index cb0de11..1895a97 100644 --- a/pysnmp/smi/error.py +++ b/pysnmp/smi/error.py @@ -2,6 +2,9 @@ from pyasn1.error import PyAsn1Error from pysnmp.error import PySnmpError class SmiError(PySnmpError, PyAsn1Error): pass +class MibLoadError(SmiError): pass +class MibNotFoundError(MibLoadError): pass + class MibOperationError(SmiError): def __init__(self, **kwargs): self.__outArgs = kwargs def __str__(self): return '%s(%s)' % ( |