Esempio n. 1
0
    def __init__(self, confFile, tokens_start, parent_pid, monitoring_period):
        Process.__init__(self)
        self.monitoring_period = monitoring_period
        self.parent_pid = parent_pid
        self.tokens_start = tokens_start
        self.socketHelper = SocketHelper()

        # The following parameters are intended to be set after JSON conf file has been read in method parse

        # Name of this virtual agent
        self.name = ""
        self.engineID = None
        # Listen parameters
        self.listen = None
        # Parameters for variations used by this agent
        self.variation = None
        # Parameters for each snmp version
        self.snmpv1 = None
        self.snmpv2c = None
        self.snmpv3 = None

        # Set configuration from file
        self.parse(confFile)
Esempio n. 2
0
class Agent(Process):
    """
        Agent entry point.

        We use Process instead of threads because Python threading model does not give enough control:
        acquire() methods are not interruptible and cannot be "timeouted". Therefore there is no possibility
        to stop a thread waiting for I/O. We cannot even combine waiting on multiple synchronization object
        in a single wait which could give a solution to this lack.
    """

    def __init__(self, confFile, tokens_start, parent_pid, monitoring_period):
        Process.__init__(self)
        self.monitoring_period = monitoring_period
        self.parent_pid = parent_pid
        self.tokens_start = tokens_start
        self.socketHelper = SocketHelper()

        # The following parameters are intended to be set after JSON conf file has been read in method parse

        # Name of this virtual agent
        self.name = ""
        self.engineID = None
        # Listen parameters
        self.listen = None
        # Parameters for variations used by this agent
        self.variation = None
        # Parameters for each snmp version
        self.snmpv1 = None
        self.snmpv2c = None
        self.snmpv3 = None

        # Set configuration from file
        self.parse(confFile)

    def run(self):

        transportDispatcher = None
        try:
            # Initialize the engine
            self.tokens_start.get()
            if self.active is not None and self.active.lower() == "false":

                # Changes the process name shown by ps for instance
                setProcTitle("agentcluster agent  [active: False]  [name: %s]" % self.name)

                logger.info('Agent "%s": inactive', self.name)
                # Generates a deadlock to enter in sleep mode
                # Only an external signal can break this deadlock
                self.tokens_start.task_done()
                queue = JoinableQueue()
                queue.put(object())
                queue.join()

            # Changes the process name shown by ps for instance
            setProcTitle("agentcluster agent  [active: True ]  [name: %s]" % self.name)

            logger.info('Agent "%s": run', self.name)
            logger.debug('EngineID="%s"', self.engineID)

            engineID_bin = None
            if self.engineID != None:
                try:
                    engineID_bin = self.engineID.decode("hex")
                except Exception:
                    logger.warn(
                        "Cannot convert configured engine ID to byte array, engine ID ignored: %s", self.engineID
                    )
                    logger.debug("", exc_info=True)
            else:
                logger.debug("No context engineID specified, let pysnmp generate one")

            snmpEngine = engine.SnmpEngine(snmpEngineID=engineID_bin)

            logger.debug('Agent "%s": Configure transport layer', self.name)
            for protocol, params in self.listen.__dict__.items():
                if type(params) is list:
                    for param in params:
                        (domain, socket) = self.socketHelper.openSocket(protocol, param.encode("ascii"))
                        config.addSocketTransport(snmpEngine, domain, socket)
                else:
                    (domain, socket) = self.socketHelper.openSocket(protocol, params.encode("ascii"))
                    config.addSocketTransport(snmpEngine, domain, socket)

            logger.debug('Agent "%s": Configure application layer', self.name)
            snmpContext = context.SnmpContext(snmpEngine)
            if self.snmpv1 is not None:
                SnmpConfHelperV1().configure(snmpEngine, snmpContext, self.snmpv1)
            if self.snmpv2c is not None:
                SnmpConfHelperV2().configure(snmpEngine, snmpContext, self.snmpv2c)
            if self.snmpv3 is not None:
                SnmpConfHelperV3().configure(snmpEngine, snmpContext, self.snmpv3)

            cmdrsp.GetCommandResponder(snmpEngine, snmpContext)
            cmdrsp.SetCommandResponder(snmpEngine, snmpContext)
            cmdrsp.NextCommandResponder(snmpEngine, snmpContext)
            cmdrsp.BulkCommandResponder(snmpEngine, snmpContext)

            logger.debug('Agent "%s": Configured', self.name)
            self.tokens_start.task_done()

            logger.debug("Starting parent and database watchdog")
            self.monitor = Watchdog(self.parent_pid, self.monitoring_period)
            self.monitor.start()

            # Job will never end unless killed
            logger.debug('Agent "%s": Running dispatcher', self.name)
            transportDispatcher = snmpEngine.transportDispatcher
            transportDispatcher.jobStarted(1)
            transportDispatcher.runDispatcher()

        except KeyboardInterrupt:
            logger.debug('Agent "%s": interrupted', self.name)
        except Exception:
            logger.error("Unexpected exception catched in agent: %s", sys.exc_info()[1])
            logger.error("", exc_info=True)
        finally:
            if transportDispatcher != None:
                transportDispatcher.closeDispatcher()
            logger.info('Agent "%s": end', self.name)
            logging.shutdown()
            try:
                # Issue #3: Python 2.7.6 releases the parent process if children is killed
                # not Python 2.6.6 so we must still release the token.
                self.tokens_start.task_done()
            except:
                pass
            # Issue #3: This agent is no longer usable so commit suicide to be sure
            # This process won't become a zombie and that parent will start a new agent
            os.kill(os.getpid(), signal.SIGKILL)

    def parse(self, confFile):
        parsed = AnyJsonDecoder().decode(open(confFile).read())
        self.__dict__.update(parsed.__dict__)
        if parsed.name is None:
            msg = "Agent name is mandatory in conf file %s" % (confFile)
            logger.error(msg)
            raise ClusterException(msg)

        self.name = makeAppName(parsed.name)

        if self.snmpv1 is None and self.snmpv2c is None and self.snmpv3 is None:
            msg = 'Agent "%s": no protocol specified in conf file %s' % (self.name, confFile)
            logger.error(msg)
            raise ClusterException(msg)
        confPath = os.path.abspath(os.path.dirname(confFile))
        if self.snmpv1 is not None:
            self.snmpv1.confPath = confPath
        if self.snmpv2c is not None:
            self.snmpv2c.confPath = confPath
        if self.snmpv3 is not None:
            self.snmpv3.confPath = confPath