Beispiel #1
0
 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)
Beispiel #2
0
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))
Beispiel #3
0
    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)
Beispiel #4
0
 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)
Beispiel #5
0
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))
Beispiel #6
0
            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)