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)
class MibTableColumn(MibScalar): """MIB table column. Manages a set of column instance variables""" protoInstance = MibScalarInstance def __init__(self, name, syntax): MibScalar.__init__(self, name, syntax) self.__createdInstances = {} self.__destroyedInstances = {} self.__rowOpWanted = {} def getNode(self, name, idx=None): try: return MibScalar.getNode(self, name, idx=None) except error.NoSuchObjectError: raise error.NoSuchInstanceError(idx=idx, name=name) def getNextNode(self, name, idx=None): try: return MibScalar.getNextNode(self, name, idx=None) except error.NoSuchObjectError: raise error.NoSuchInstanceError(idx=idx, name=name) def setProtoInstance(self, protoInstance): self.protoInstance = protoInstance # Column creation (this should probably be converted into some state # 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, (acFun, acCtx)): # 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) if acFun and \ val is not None and \ self.maxAccess != 'readcreate' or \ acFun and acFun(name, idx, 'write', acCtx): raise error.NoCreationError(idx=idx, name=name) # 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 self.__createdInstances.has_key(name): return self.__createdInstances[name] = self.protoInstance( self.name, name[len(self.name):], self.syntax.clone()) self.__createdInstances[name].createTest(name, val, idx, (acFun, acCtx))
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('read', (name, self.syntax), **context)): raise error.NoAccessError(name=name, idx=context.get('idx')) else: try: node = self.getBranch(name, **context) except (error.NoSuchInstanceError, error.NoSuchObjectError): return # missing object is not an error here else: node.readTest(varBind, **context)
def createTest(self, name, val, idx, acInfo): (acFun, acCtx) = acInfo # 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) if acFun: if val is not None and self.maxAccess != 'readcreate' or \ acFun(name, self.syntax, idx, 'write', acCtx): 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) # 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)
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))
raise error.NoAccessError(idx=idx, name=name) else: MibTree.readTest(self, name, val, idx, (acFun, acCtx)) # If instance exists, check permissions 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) # Two-phase commit implementation def writeTest(self, name, val, idx, (acFun, acCtx)): if name == self.name: raise error.NoAccessError(idx=idx, name=name) else: MibTree.writeTest(self, name, val, idx, (acFun, acCtx)) # If instance exists, check permissions if acFun and \ self.maxAccess != 'readwrite' and \ self.maxAccess != 'readcreate' or \ acFun and acFun(name, idx, 'write', acCtx): raise error.NotWritableError(idx=idx, name=name) class MibScalarInstance(MibTree): """Scalar MIB variable instance. Implements read/write operations.""" def __init__(self, typeName, instId, syntax): MibTree.__init__(self, typeName + instId, syntax) self.typeName = typeName
def __init__(self, udpIp, udpPort): # Create SNMP engine with autogenernated engineID and pre-bound # to socket transport dispatcher self.snmpEngine = engine.SnmpEngine() self.mibBuilder = self.snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder mibPath = self.mibBuilder.getMibPath() + ('.', ) self.mibBuilder.setMibPath(*mibPath) # Setup UDP over IPv4 transport endpoint config.addSocketTransport( self.snmpEngine, udp.domainName, udp.UdpSocketTransport().openServerMode((udpIp, udpPort))) print 'Publishing readings via SNMP' print 'Agent address {}:{}'.format(udpIp, udpPort) print 'Community name public' # v1/2 setup config.addV1System(self.snmpEngine, 'test-agent', 'public') # v3 setup config.addV3User(self.snmpEngine, 'test-user') # VACM setup config.addContext(self.snmpEngine, '') config.addRwUser(self.snmpEngine, 1, 'test-agent', 'noAuthNoPriv', (1, 3, 6)) # v1 config.addRwUser(self.snmpEngine, 2, 'test-agent', 'noAuthNoPriv', (1, 3, 6)) # v2c config.addRwUser(self.snmpEngine, 3, 'test-user', 'noAuthNoPriv', (1, 3, 6)) # v3 # SNMP context snmpContext = context.SnmpContext(self.snmpEngine) # Apps registration cmdrsp.GetCommandResponder(self.snmpEngine, snmpContext) cmdrsp.SetCommandResponder(self.snmpEngine, snmpContext) cmdrsp.NextCommandResponder(self.snmpEngine, snmpContext) cmdrsp.BulkCommandResponder(self.snmpEngine, snmpContext) MibScalarInstance, = self.mibBuilder.importSymbols( 'SNMPv2-SMI', 'MibScalarInstance') class ScalarFromCallback(MibScalarInstance): def __init__(self, sensorId, valueGetter, typeName, instId, syntax): MibScalarInstance.__init__(self, typeName, instId, syntax) self.valueGetter = valueGetter def readTest(self, name, val, idx, (acFun, acCtx)): if not self.valueGetter(): raise error.NoAccessError(idx=idx, name=name) def readGet(self, name, val, idx, (acFun, acCtx)): value = self.valueGetter() if not value: raise error.NoAccessError(idx=idx, name=name) else: return name, self.syntax.clone(value)