class MibTree(ObjectType): branchVersionId = 0 # cnanges on tree structure change maxAccess = 'not-accessible' def __init__(self, name, syntax=None): ObjectType.__init__(self, name, syntax) self._vars = OidOrderedDict() # Subtrees registration def registerSubtrees(self, *subTrees): self.branchVersionId += 1 for subTree in subTrees: if subTree.name in self._vars: raise error.SmiError( 'MIB subtree %s already registered at %s' % (subTree.name, self)) self._vars[subTree.name] = subTree def unregisterSubtrees(self, *names): self.branchVersionId += 1 for name in names: # This may fail if you fill a table by exporting MibScalarInstances # but later drop them through SNMP. if name not in self._vars: raise error.SmiError('MIB subtree %s not registered at %s' % (name, self)) del self._vars[name] # # Tree traversal # # Missing branches are indicated by the NoSuchObjectError exception. # Although subtrees may indicate their missing branches by the # NoSuchInstanceError exception. # def getBranch(self, name, idx): """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) def getNextBranch(self, name, idx=None): # Start from the beginning if self._vars: first = list(self._vars.keys())[0] if self._vars and name < first: return self._vars[first] else: try: return self._vars[self._vars.nextKey(name)] except KeyError: raise error.NoSuchObjectError(idx=idx, name=name) def getNode(self, name, idx=None): """Return tree node found by name""" if name == self.name: return self else: return self.getBranch(name, idx).getNode(name, idx) def getNextNode(self, name, idx=None): """Return tree node next to name""" try: nextNode = self.getBranch(name, idx) except (error.NoSuchInstanceError, error.NoSuchObjectError): return self.getNextBranch(name, idx) else: try: return nextNode.getNextNode(name, idx) except (error.NoSuchInstanceError, error.NoSuchObjectError): try: return self._vars[self._vars.nextKey(nextNode.name)] except KeyError: raise error.NoSuchObjectError(idx=idx, name=name) # MIB instrumentation # Read operation def readTest(self, name, val, idx, acInfo): (acFun, acCtx) = acInfo if name == self.name: 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) else: try: node = self.getBranch(name, idx) except (error.NoSuchInstanceError, error.NoSuchObjectError): return # missing object is not an error here else: node.readTest(name, val, idx, acInfo) def readGet(self, name, val, idx, acInfo): try: node = self.getBranch(name, idx) except (error.NoSuchInstanceError, error.NoSuchObjectError): return name, exval.noSuchObject else: return node.readGet(name, val, idx, acInfo) # 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 nextName = name direction = self.depthFirst while 1: # XXX linear search here if direction == self.depthFirst: direction = self.breadthFirst try: node = self.getBranch(nextName, idx) except (error.NoSuchInstanceError, error.NoSuchObjectError): continue else: try: node = self.getNextBranch(nextName, idx) except (error.NoSuchInstanceError, error.NoSuchObjectError): if topOfTheMib: return raise direction = self.depthFirst nextName = node.name try: return node.readTestNext(nextName, val, idx, acInfo, oName) 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 nextName = name direction = self.depthFirst while 1: # XXX linear search here if direction == self.depthFirst: direction = self.breadthFirst try: node = self.getBranch(nextName, idx) except (error.NoSuchInstanceError, error.NoSuchObjectError): continue else: try: node = self.getNextBranch(nextName, idx) 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) except (error.NoAccessError, error.NoSuchInstanceError, error.NoSuchObjectError): pass # Write operation def writeTest(self, name, val, idx, acInfo): (acFun, acCtx) = acInfo if name == self.name: # Make sure variable is writable if acFun: if self.maxAccess not in ('readwrite', 'readcreate') or \ acFun(name, self.syntax, idx, 'write', acCtx): raise error.NotWritableError(idx=idx, name=name) else: node = self.getBranch(name, idx) node.writeTest(name, val, idx, acInfo) def writeCommit(self, name, val, idx, acInfo): self.getBranch(name, idx).writeCommit(name, val, idx, acInfo) 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)
def __init__(self, name, syntax=None): ObjectType.__init__(self, name, syntax) self._vars = OidOrderedDict()
class MibTree(ObjectType): branchVersionId = 0 # increments on tree structure change XXX maxAccess = 'not-accessible' def __init__(self, name, syntax=None): ObjectType.__init__(self, name, syntax) self._vars = OidOrderedDict() # Subtrees registration def registerSubtrees(self, *subTrees): """Register subtrees at this tree. Subtrees are always attached at the level of this tree, not subtrees.""" for subTree in subTrees: if subTree.name in self._vars: raise error.SmiError( 'MIB subtree %s already registered at %s' % (subTree.name, self) ) self._vars[subTree.name] = subTree MibTree.branchVersionId = MibTree.branchVersionId + 1 def unregisterSubtrees(self, *names): """Detach subtrees from this tree""" for name in names: # This may fail if you fill a table by exporting MibScalarInstances # but later drop them through SNMP. if name not in self._vars: raise error.SmiError( 'MIB subtree %s not registered at %s' % (name, self) ) del self._vars[name] MibTree.branchVersionId = MibTree.branchVersionId + 1 # Tree traversal def getBranch(self, name, idx): """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) def getNode(self, name, idx=None): """Return tree node found by name""" if name == self.name: return self else: return self.getBranch(name, idx).getNode(name, idx) def getNextNode(self, name, idx=None): """Return tree node next to name""" try: nextNode = self.getBranch(name, idx) except error.NoSuchObjectError: # Start from the beginning if self._vars: first = list(self._vars.keys())[0] if self._vars and name <= first: return self._vars[first] else: # Try following the white rabbit at our level try: return self._vars[self._vars.nextKey(name)] except KeyError: raise error.NoSuchObjectError(idx=idx, name=name) else: try: return nextNode.getNextNode(name, idx) except error.NoSuchObjectError: try: return self._vars[self._vars.nextKey(nextNode.name)] except KeyError: raise error.NoSuchObjectError(idx=idx, name=name) # MIB instrumentation # Read operation def readTest(self, name, val, idx, acInfo): (acFun, acCtx) = acInfo if name == self.name: 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) else: try: node = self.getBranch(name, idx) except error.NoSuchObjectError: return # missing object is not an error here node.readTest(name, val, idx, (acFun, acCtx)) def readGet(self, name, val, idx, acInfo): (acFun, acCtx) = acInfo try: node = self.getBranch(name, idx) except error.NoSuchObjectError: return name, exval.noSuchInstance else: return node.readGet(name, val, idx, (acFun, acCtx)) # Read next operation is subtree-specific def readTestNext(self, name, val, idx, acInfo): (acFun, acCtx) = acInfo nextName = name while 1: # XXX linear search here try: nextName = self.getNextNode(nextName, idx).name except error.NoSuchObjectError: return # missing object is not an error here try: return self.readTest(nextName, val, idx, (acFun, acCtx)) except error.NoAccessError: continue def readGetNext(self, name, val, idx, acInfo): (acFun, acCtx) = acInfo nextName = name while 1: try: nextName = self.getNextNode(nextName, idx).name except error.NoSuchObjectError: return name, exval.endOfMib try: self.readTest(nextName, val, idx, (acFun, acCtx)) # XXX except error.NoAccessError: continue else: return self.readGet(nextName, val, idx, (acFun, acCtx)) # Write operation def writeTest(self, name, val, idx, acInfo): (acFun, acCtx) = acInfo if name == self.name: # Make sure variable is writable if acFun: if self.maxAccess not in ('readwrite', 'readcreate') or \ acFun(name, self.syntax, idx, 'write', acCtx): raise error.NotWritableError(idx=idx, name=name) else: node = self.getBranch(name, idx) node.writeTest(name, val, idx, (acFun, acCtx)) def writeCommit(self, name, val, idx, acInfo): (acFun, acCtx) = acInfo self.getBranch(name, idx).writeCommit(name, val, idx, (acFun, acCtx)) def writeCleanup(self, name, val, idx, acInfo): (acFun, acCtx) = acInfo self.getBranch(name, idx).writeCleanup(name, val, idx, (acFun, acCtx)) def writeUndo(self, name, val, idx, acInfo): (acFun, acCtx) = acInfo self.getBranch(name, idx).writeUndo(name, val, idx, (acFun, acCtx))
class MibTree(ObjectType): branchVersionId = 0 # cnanges on tree structure change maxAccess = 'not-accessible' def __init__(self, name, syntax=None): ObjectType.__init__(self, name, syntax) self._vars = OidOrderedDict() # Subtrees registration def registerSubtrees(self, *subTrees): self.branchVersionId += 1 for subTree in subTrees: if subTree.name in self._vars: raise error.SmiError( 'MIB subtree %s already registered at %s' % (subTree.name, self) ) self._vars[subTree.name] = subTree def unregisterSubtrees(self, *names): self.branchVersionId += 1 for name in names: # This may fail if you fill a table by exporting MibScalarInstances # but later drop them through SNMP. if name not in self._vars: raise error.SmiError( 'MIB subtree %s not registered at %s' % (name, self) ) del self._vars[name] # # Tree traversal # # Missing branches are indicated by the NoSuchObjectError exception. # Although subtrees may indicate their missing branches by the # NoSuchInstanceError exception. # def getBranch(self, name, idx): """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) def getNextBranch(self, name, idx=None): # Start from the beginning if self._vars: first = list(self._vars.keys())[0] if self._vars and name < first: return self._vars[first] else: try: return self._vars[self._vars.nextKey(name)] except KeyError: raise error.NoSuchObjectError(idx=idx, name=name) def getNode(self, name, idx=None): """Return tree node found by name""" if name == self.name: return self else: return self.getBranch(name, idx).getNode(name, idx) def getNextNode(self, name, idx=None): """Return tree node next to name""" try: nextNode = self.getBranch(name, idx) except (error.NoSuchInstanceError, error.NoSuchObjectError): return self.getNextBranch(name, idx) else: try: return nextNode.getNextNode(name, idx) except (error.NoSuchInstanceError, error.NoSuchObjectError): try: return self._vars[self._vars.nextKey(nextNode.name)] except KeyError: raise error.NoSuchObjectError(idx=idx, name=name) # MIB instrumentation # Read operation def readTest(self, name, val, idx, acInfo): (acFun, acCtx) = acInfo if name == self.name: 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) else: try: node = self.getBranch(name, idx) except (error.NoSuchInstanceError, error.NoSuchObjectError): return # missing object is not an error here else: node.readTest(name, val, idx, acInfo) def readGet(self, name, val, idx, acInfo): try: node = self.getBranch(name, idx) except (error.NoSuchInstanceError, error.NoSuchObjectError): return name, exval.noSuchObject else: return node.readGet(name, val, idx, acInfo) # 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 nextName = name direction = self.depthFirst while 1: # XXX linear search here if direction == self.depthFirst: direction = self.breadthFirst try: node = self.getBranch(nextName, idx) except (error.NoSuchInstanceError, error.NoSuchObjectError): continue else: try: node = self.getNextBranch(nextName, idx) except (error.NoSuchInstanceError, error.NoSuchObjectError): if topOfTheMib: return raise direction = self.depthFirst nextName = node.name try: return node.readTestNext(nextName, val, idx, acInfo, oName) 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 nextName = name direction = self.depthFirst while 1: # XXX linear search here if direction == self.depthFirst: direction = self.breadthFirst try: node = self.getBranch(nextName, idx) except (error.NoSuchInstanceError, error.NoSuchObjectError): continue else: try: node = self.getNextBranch(nextName, idx) 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) except (error.NoAccessError, error.NoSuchInstanceError, error.NoSuchObjectError): pass # Write operation def writeTest(self, name, val, idx, acInfo): (acFun, acCtx) = acInfo if name == self.name: # Make sure variable is writable if acFun: if self.maxAccess not in ('readwrite', 'readcreate') or \ acFun(name, self.syntax, idx, 'write', acCtx): raise error.NotWritableError(idx=idx, name=name) else: node = self.getBranch(name, idx) node.writeTest(name, val, idx, acInfo) def writeCommit(self, name, val, idx, acInfo): self.getBranch(name, idx).writeCommit(name, val, idx, acInfo) 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)
def indexMib(self): if self.lastBuildId == self.mibBuilder.lastBuildId: return debug.logger & debug.flagMIB and debug.logger( 'indexMib: re-indexing MIB view') MibScalarInstance, = self.mibBuilder.importSymbols( 'SNMPv2-SMI', 'MibScalarInstance') # # Create indices # # Module name -> module-scope indices self.__mibSymbolsIdx = OrderedDict() # Oid <-> label indices # This is potentionally ambiguous mapping. Sort modules in # ascending age for resolution def __sortFun(x, b=self.mibBuilder): if b.moduleID in b.mibSymbols[x]: m = b.mibSymbols[x][b.moduleID] r = m.getRevisions() if r: return r[0] else: return "1970-01-01 00:00" modNames = list(self.mibBuilder.mibSymbols.keys()) modNames.sort(key=__sortFun) # Index modules names for modName in [''] + modNames: # Modules index self.__mibSymbolsIdx[modName] = mibMod = { 'oidToLabelIdx': OidOrderedDict(), 'labelToOidIdx': {}, 'varToNameIdx': {}, 'typeToModIdx': OrderedDict(), 'oidToModIdx': {} } if not modName: globMibMod = mibMod continue # Types & MIB vars indices for n, v in self.mibBuilder.mibSymbols[modName].items(): if n == self.mibBuilder.moduleID: # do not index this continue # special symbol if isinstance(v, classTypes): if n in mibMod['typeToModIdx']: raise error.SmiError( 'Duplicate SMI type %s::%s, has %s' % \ (modName, n, mibMod['typeToModIdx'][n]) ) globMibMod['typeToModIdx'][n] = modName mibMod['typeToModIdx'][n] = modName elif isinstance(v, instanceTypes): if isinstance(v, MibScalarInstance): continue if n in mibMod['varToNameIdx']: raise error.SmiError( 'Duplicate MIB variable %s::%s has %s' % \ (modName, n, mibMod['varToNameIdx'][n]) ) globMibMod['varToNameIdx'][n] = v.name mibMod['varToNameIdx'][n] = v.name # Potentionally ambiguous mapping ahead globMibMod['oidToModIdx'][v.name] = modName mibMod['oidToModIdx'][v.name] = modName globMibMod['oidToLabelIdx'][v.name] = (n, ) mibMod['oidToLabelIdx'][v.name] = (n, ) else: raise error.SmiError('Unexpected object %s::%s' % (modName, n)) # Build oid->long-label index oidToLabelIdx = self.__mibSymbolsIdx['']['oidToLabelIdx'] labelToOidIdx = self.__mibSymbolsIdx['']['labelToOidIdx'] if oidToLabelIdx: prevOid = oidToLabelIdx.keys()[0] else: prevOid = () baseLabel = () for key in oidToLabelIdx.keys(): keydiff = len(key) - len(prevOid) if keydiff > 0: baseLabel = oidToLabelIdx[prevOid] if keydiff > 1: baseLabel = baseLabel + key[-keydiff:-1] if keydiff < 0: keyLen = len(key) i = keyLen - 1 while i: k = key[:i] if k in oidToLabelIdx: baseLabel = oidToLabelIdx[k] if i != keyLen - 1: baseLabel = baseLabel + key[i:-1] break i = i - 1 # Build oid->long-label index oidToLabelIdx[key] = baseLabel + oidToLabelIdx[key] # Build label->oid index labelToOidIdx[oidToLabelIdx[key]] = key prevOid = key # Build module-scope oid->long-label index for mibMod in self.__mibSymbolsIdx.values(): for oid in mibMod['oidToLabelIdx'].keys(): mibMod['oidToLabelIdx'][oid] = oidToLabelIdx[oid] mibMod['labelToOidIdx'][oidToLabelIdx[oid]] = oid self.lastBuildId = self.mibBuilder.lastBuildId
class MibTree(ObjectType): branchVersionId = 0L # increments on tree structure change XXX maxAccess = "not-accessible" def __init__(self, name, syntax=None): ObjectType.__init__(self, name, syntax) self._vars = OidOrderedDict() # Subtrees registration def registerSubtrees(self, *subTrees): """Register subtrees at this tree. Subtrees are always attached at the level of this tree, not subtrees.""" for subTree in subTrees: if self._vars.has_key(subTree.name): raise error.SmiError("MIB subtree %s already registered at %s" % (subTree.name, self)) self._vars[subTree.name] = subTree MibTree.branchVersionId = MibTree.branchVersionId + 1 def unregisterSubtrees(self, *names): """Detach subtrees from this tree""" for name in names: # This may fail if you fill a table by exporting MibScalarInstances # but later drop them through SNMP. if not self._vars.has_key(name): raise error.SmiError("MIB subtree %s not registered at %s" % (name, self)) del self._vars[name] MibTree.branchVersionId = MibTree.branchVersionId + 1 # Tree traversal def getBranch(self, name, idx): """Return a branch of this tree where the 'name' OID may reside""" name = tuple(name) # XXX if len(self.name) < len(name): for keyLen in self._vars.getKeysLens(): subName = name[:keyLen] if self._vars.has_key(subName): return self._vars[subName] raise error.NoSuchObjectError(name=name, idx=idx) def getNode(self, name, idx=None): """Return tree node found by name""" if name == self.name: return self else: return self.getBranch(name, idx).getNode(name, idx) def getNextNode(self, name, idx=None): """Return tree node next to name""" try: nextNode = self.getBranch(name, idx) except error.NoSuchObjectError: # Start from the beginning if self._vars and name <= self._vars.keys()[0]: return self._vars[self._vars.keys()[0]] else: # Try following the white rabbit at our level try: return self._vars[self._vars.nextKey(name)] except KeyError: raise error.NoSuchObjectError(idx=idx, name=name) else: try: return nextNode.getNextNode(name, idx) except error.NoSuchObjectError: try: return self._vars[self._vars.nextKey(nextNode.name)] except KeyError: raise error.NoSuchObjectError(idx=idx, name=name) # MIB instrumentation # Read operation def readTest(self, name, val, idx, (acFun, acCtx)): if name == self.name: if ( acFun and self.maxAccess != "readonly" and self.maxAccess != "readwrite" and self.maxAccess != "readcreate" or acFun and acFun(name, idx, "read", acCtx) ): raise error.NoAccessError(idx=idx, name=name) else: try: node = self.getBranch(name, idx) except error.NoSuchObjectError: return # missing object is not an error here node.readTest(name, val, idx, (acFun, acCtx))
def indexMib(self): if self.lastBuildId == self.mibBuilder.lastBuildId: return debug.logger & debug.FLAG_MIB and debug.logger( 'indexMib: re-indexing MIB view') MibScalarInstance, = self.mibBuilder.importSymbols( 'SNMPv2-SMI', 'MibScalarInstance') # # Create indices # # Module name -> module-scope indices self._mibSymbolsIdx.clear() globMibMod = { 'oidToLabelIdx': OidOrderedDict(), 'labelToOidIdx': {}, 'varToNameIdx': {}, 'typeToModIdx': OrderedDict(), 'oidToModIdx': {} } self._mibSymbolsIdx[''] = globMibMod # Oid <-> label indices modNames = sorted(self.mibBuilder.mibSymbols, key=self._sortFun) # Index modules names for modName in modNames: mibMod = { 'oidToLabelIdx': OidOrderedDict(), 'labelToOidIdx': {}, 'varToNameIdx': {}, 'typeToModIdx': OrderedDict(), 'oidToModIdx': {} } self._mibSymbolsIdx[modName] = mibMod # Types & MIB vars indices for n, v in self.mibBuilder.mibSymbols[modName].items(): if n == self.mibBuilder.moduleID: # do not index this continue # special symbol if isinstance(v, classTypes): if n in mibMod['typeToModIdx']: raise error.SmiError( 'Duplicate SMI type %s::%s, has ' '%s' % (modName, n, mibMod['typeToModIdx'][n])) globMibMod['typeToModIdx'][n] = modName mibMod['typeToModIdx'][n] = modName elif isinstance(v, instanceTypes): if isinstance(v, MibScalarInstance): continue if n in mibMod['varToNameIdx']: raise error.SmiError( 'Duplicate MIB variable %s::%s has ' '%s' % (modName, n, mibMod['varToNameIdx'][n])) globMibMod['varToNameIdx'][n] = v.name mibMod['varToNameIdx'][n] = v.name # Potentially ambiguous mapping ahead globMibMod['oidToModIdx'][v.name] = modName mibMod['oidToModIdx'][v.name] = modName globMibMod['oidToLabelIdx'][v.name] = (n, ) mibMod['oidToLabelIdx'][v.name] = (n, ) else: raise error.SmiError('Unexpected object %s::%s' % (modName, n)) # Build oid->long-label index oidToLabelIdx = self._mibSymbolsIdx['']['oidToLabelIdx'] labelToOidIdx = self._mibSymbolsIdx['']['labelToOidIdx'] prevOid = () baseLabel = () for key in oidToLabelIdx: keydiff = len(key) - len(prevOid) if keydiff > 0: if prevOid: if keydiff == 1: baseLabel = oidToLabelIdx[prevOid] else: baseLabel += key[-keydiff:-1] else: baseLabel = () elif keydiff < 0: baseLabel = () keyLen = len(key) i = keyLen - 1 while i: k = key[:i] if k in oidToLabelIdx: baseLabel = oidToLabelIdx[k] if i != keyLen - 1: baseLabel += key[i:-1] break i -= 1 # Build oid->long-label index oidToLabelIdx[key] = baseLabel + oidToLabelIdx[key] # Build label->oid index labelToOidIdx[oidToLabelIdx[key]] = key prevOid = key # Build module-scope oid->long-label index for mibMod in self._mibSymbolsIdx.values(): for oid in mibMod['oidToLabelIdx']: mibMod['oidToLabelIdx'][oid] = oidToLabelIdx[oid] mibMod['labelToOidIdx'][oidToLabelIdx[oid]] = oid self.lastBuildId = self.mibBuilder.lastBuildId
class MibTree(ObjectType): branchVersionId = 0 # increments on tree structure change XXX maxAccess = 'not-accessible' def __init__(self, name, syntax=None): ObjectType.__init__(self, name, syntax) self._vars = OidOrderedDict() # Subtrees registration def registerSubtrees(self, *subTrees): """Register subtrees at this tree. Subtrees are always attached at the level of this tree, not subtrees.""" for subTree in subTrees: if self._vars.has_key(subTree.name): raise error.SmiError( 'MIB subtree %s already registered at %s' % (subTree.name, self)) self._vars[subTree.name] = subTree MibTree.branchVersionId = MibTree.branchVersionId + 1 def unregisterSubtrees(self, *names): """Detach subtrees from this tree""" for name in names: # This may fail if you fill a table by exporting MibScalarInstances # but later drop them through SNMP. if not self._vars.has_key(name): raise error.SmiError('MIB subtree %s not registered at %s' % (name, self)) del self._vars[name] MibTree.branchVersionId = MibTree.branchVersionId + 1 # Tree traversal def getBranch(self, name, idx): """Return a branch of this tree where the 'name' OID may reside""" name = tuple(name) # XXX if len(self.name) < len(name): for keyLen in self._vars.getKeysLens(): subName = name[:keyLen] if self._vars.has_key(subName): return self._vars[subName] raise error.NoSuchObjectError(name=name, idx=idx) def getNode(self, name, idx=None): """Return tree node found by name""" if name == self.name: return self else: return self.getBranch(name, idx).getNode(name, idx) def getNextNode(self, name, idx=None): """Return tree node next to name""" try: nextNode = self.getBranch(name, idx) except error.NoSuchObjectError: # Start from the beginning if self._vars and name <= self._vars.keys()[0]: return self._vars[self._vars.keys()[0]] else: # Try following the white rabbit at our level try: return self._vars[self._vars.nextKey(name)] except KeyError: raise error.NoSuchObjectError(idx=idx, name=name) else: try: return nextNode.getNextNode(name, idx) except error.NoSuchObjectError: try: return self._vars[self._vars.nextKey(nextNode.name)] except KeyError: raise error.NoSuchObjectError(idx=idx, name=name) # MIB instrumentation # Read operation def readTest(self, name, val, idx, (acFun, acCtx)): if name == self.name: if acFun and \ self.maxAccess != 'readonly' and \ self.maxAccess != 'readwrite' and \ self.maxAccess != 'readcreate' or \ acFun and acFun(name, idx, 'read', acCtx): raise error.NoAccessError(idx=idx, name=name) else: try: node = self.getBranch(name, idx) except error.NoSuchObjectError: return # missing object is not an error here node.readTest(name, val, idx, (acFun, acCtx))