Example #1
0
class Bokor():

    Action = Action

    def __init__(self,
                 Configuration,
                 Interface,
                 Transmission,
                 Features,
                 Act=Action,
                 handle_signal=True):
        """Build Bokor object

        @type  Configuration: a subclass of the Configuration class 
        @param Configuration: Class that load, check and store the Configuration

        @type  Interface: a subclass of the Interface class 
        @param Interface: Class that manage the reception of order, its run function is the listening loop

        @type  Features: a list of subclass of the Feature class 
        @param Features: list of Class that process the order

        @type  Transmission: a subclass of the Transmission class 
        @param Transmission: Class that manage the connexion of other agent and transmit the orders to them

        @return: C_SUCCESS(=0)
        """
        change_action(Act)
        #init logging
        self._init_logging()
        self.bocore = None

        # deal with signals
        self.force_quit = False
        if handle_signal:
            signal.signal(signal.SIGTERM, self.quiting)
            signal.signal(signal.SIGINT, self.quiting)

        #try to create configuration
        configuration = self._init_configuration(Configuration)

        #configuration could be None, if the Configuration class
        #is not suitable.
        # in that case the _validate_classes will exist with a more global check.

        self._validate_classes(Configuration, Interface, Transmission,
                               Features)

        # at this point all classes have the good type

        logging.info("All classes are of valid type")
        self._validate_dependance(Configuration, Interface, Transmission,
                                  Features)
        logging.info("All dependances are met")

        #after all validation configuration should not be empty
        # checking just in case

        if not configuration:
            logging.critical(
                "configuration was not created, should not happen (sorry)")
            sys.exit(FATAL_ERROR)

        # ready to lauch
        self._launch(configuration, Configuration, Interface, Transmission,
                     Features)

        sys.exit(SUCCESS)

    def _init_logging(self):
        #logging.basicConfig(format='%(levelname)s:%(asctime)s:%(message)s',  level=logging.DEBUG)
        #logging instance
        self.logging = logging.getLogger()
        self.logging.setLevel(logging.DEBUG)
        #clean handlers :
        self.logging.handlers = []
        # create console handler and set level to debug
        ch = logging.StreamHandler()
        ch.setLevel(logging.DEBUG)
        # create formatter
        formatter = logging.Formatter(
            '%(levelname)s:%(asctime)s:%(filename)s:%(lineno)d:%(message)s')

        # add formatter to ch
        ch.setFormatter(formatter)
        # add ch to logger
        self.logging.addHandler(ch)

        #default logging handler, not known for the momment
        self.lh_stdout = ch

    def _launch(self, configuration, Configuration, Interface, Transmission,
                Features):
        """ _launch create the bocore object and wait for it's return.
        At return Bocore objet will answer a set of classes, and a
        status tellling this function if this agent must be rebooter, reconfigured or stopped

        @type  configuration: class instance that load, check and store the Configuration
        @param configuration: the configuration object

        @type  Configuration: a subclass of the Configuration class 
        @param Configuration: Class that load, check and store the Configuration

        @type  Interface: a subclass of the Interface class 
        @param Interface: Class that manage the reception of order, its run function is the listening loop

        @type  Features: a list of subclass of the Feature class 
        @param Features: list of Class that process the order

        @type  Transmission: a subclass of the Transmission class 
        @param Transmission: Class that manage the connexion of other agent and transmit the orders to them

        @return nothing
        
        """

        #known object in a structure, that structure will be uses as return type par Bocore.run()
        original_bokor_struct = {
            'configuration_object': configuration,
            'Configuration': Configuration,
            'Interface': Interface,
            'interface_object': None,
            'Transmission': Transmission,
            'transmission_object': None,
            'Features': Features,
            'feature_object_list': [],
            'status': 'init',  #no bject instantiated exept configuration
        }
        # we keep original and use bokor_struct
        logging.info("original structure for agent : %s" %
                     (str(original_bokor_struct)))
        bokor_struct = original_bokor_struct.copy()
        self.bocore = None

        # main loop
        while True:
            # creating only if needed
            if not self.bocore:
                logging.info("building bocore object")
                self.bocore = Bocore(configuration, Configuration, Interface,
                                     Transmission, Features)
            #running agent
            bokor_struct = self.bocore.run()
            #shall we quit ?
            if bokor_struct['status'] in ['quit'] or self.force_quit:
                self.bocore.destroy()
                break
            #shall we destroy Bocore ?
            # clodrebbot : destroy all then recreate
            if bokor_struct['status'] in ['coldreboot']:
                self.bocore.destroy()
                self.bocore = None

            sleep(15)
        return

    def _init_configuration(self, Configuration):
        """ try to get logging from Configuration, if Configuration does not provide a logging
        _try_and_get_logging will configure stderr as logging
        
        @type  Configuration: a subclass of the Configuration class 
        @param Configuration: Class that load, check and store the Configuration

        return a Configuration instance, or None if not possible to instanciate Configuration, 
        """
        configuration = None
        valid_class = issubclass(Configuration, BaseConfiguration)
        if valid_class:
            configuration = Configuration()
            #if configuration is not ready (missing conf file)
        self._try_and_get_logging(configuration)
        return configuration

    def _try_and_get_logging(self, configuration):
        """ try to get logging from Configuration, if Configuration does not provide a logging
        _try_and_get_logging will configure stderr as logging
        
        @type  configuration: a subclass of the Configuration class 
        @param configuration: a Configuration object

        @return Nothing, 
        """
        new_handler = None

        if configuration:
            #we try to get the newhandler
            #
            new_handler = configuration.get_logging_handler()
        if new_handler:
            self.logging.debug("new handler %s for logging given by %s" %
                               (new_handler, configuration))
            #rest handlers
            self.logging.handlers = []
            # installing the new handler
            self.logging.addHandler(new_handler)
            #setting new logging level
            self.logging.setLevel(new_handler.level)

        logging.info("logging ready")

    def _validate_dependance(self, Configuration, Interface, Transmission,
                             Features):
        """validate that all classes are meeting their dependances
        (class must be vlid before)
        
        @type  Configuration: a subclass of the Configuration class 
        @param Configuration: Class that load, check and store the Configuration

        @type  Interface: a subclass of the Interface class 
        @param Interface: Class that manage the reception of order, its run function is the listening loop

        @type  Features: a list of subclass of the Feature class 
        @param Features: list of Class that process the order

        @type  Transmission: a subclass of the Transmission class 
        @param Transmission: Class that manage the connexion of other agent and transmit the orders to them

        return : True if everything is valid
        """

        valid = True
        all_valid = True
        for bokorclass in [Configuration, Interface, Transmission] + Features:
            #maybe it can be None
            if bokorclass is None: continue
            for categorie, knowns in [("configuration", [Configuration]),
                                      ("interface", [Interface]),
                                      ("transmission", [Transmission]),
                                      ("feature", Features)]:
                for dclass in bokorclass.dependances[categorie]:
                    valid = False
                    for known in knowns:
                        if self._is_sub_class(known, dclass, log=False):
                            valid = True
                    if not valid:
                        logging.critical(
                            "%s need of a %s for %s, but %s will be loaded" %
                            (bokorclass, dclass, categorie, str(knowns)))
                        all_valid = False

        if not all_valid:
            sys.exit(FATAL_ERROR)

    def _validate_classes(self, Configuration, Interface, Transmission,
                          Features):
        """validate all clsses given as subclasses of the wanted class

        @type  Configuration: a subclass of the Configuration class 
        @param Configuration: Class that load, check and store the Configuration

        @type  Interface: a subclass of the Interface class 
        @param Interface: Class that manage the reception of order, its run function is the listening loop

        @type  Features: a list of subclass of the Feature class 
        @param Features: list of Class that process the order

        @type  Transmission: a subclass of the Transmission class 
        @param Transmission: Class that manage the connexion of other agent and transmit the orders to them

        return : Nothing, quit if not validate
        """

        valid = self._is_sub_class(Configuration, BaseConfiguration)
        valid = self._is_sub_class(Interface, BaseInterface) and valid
        valid = self._is_sub_class(
            Transmission, BaseTransmission, allow_none=True) and valid
        valid = reduce(
            lambda x, y: x and y,
            [self._is_sub_class(Feature, Executor)
             for Feature in Features], True) and valid
        if not valid:
            logging.error("Classes misfit, aborting")
            sys.exit(FATAL_ERROR)

    def _is_sub_class(self, wanted, mandatory, allow_none=False, log=True):
        """validate that wanted is a sub class of mandatory

        @type  wanted: a class wanted
        @param wanted: the class to test

        @type  mandatory: a class
        @param mandatory: the class that wanted should heritated from

        return True if wanted is a sub class of mandatory, False in any other case
        """
        try:
            #are we allowing None and is it None as wanted
            if allow_none and not wanted:
                return True
            if not issubclass(wanted, mandatory):
                if log:
                    logging.error("%s is not a sub Class of %s" %
                                  (wanted.__name__, mandatory.__name__))
                return False
            return True
        except TypeError:
            if log:
                logging.error(
                    "%s is not a Class but a %s (awaiting a sub class of %s)" %
                    (str(wanted), type(wanted), mandatory.__name__))
        return False

    def quiting(self, signal, frame):
        logging.critical('Caught signal %s, exiting.' % (str(signal)))
        self.force_quit = True
        self.bocore.interface.stop('quit')
        sys.exit()
Example #2
0
class Bokor:

    Action = Action

    def __init__(self, Configuration, Interface, Transmission, Features, Act=Action, handle_signal=True):
        """Build Bokor object

        @type  Configuration: a subclass of the Configuration class 
        @param Configuration: Class that load, check and store the Configuration

        @type  Interface: a subclass of the Interface class 
        @param Interface: Class that manage the reception of order, its run function is the listening loop

        @type  Features: a list of subclass of the Feature class 
        @param Features: list of Class that process the order

        @type  Transmission: a subclass of the Transmission class 
        @param Transmission: Class that manage the connexion of other agent and transmit the orders to them

        @return: C_SUCCESS(=0)
        """
        change_action(Act)
        # init logging
        self._init_logging()
        self.bocore = None

        # deal with signals
        self.force_quit = False
        if handle_signal:
            signal.signal(signal.SIGTERM, self.quiting)
            signal.signal(signal.SIGINT, self.quiting)

        # try to create configuration
        configuration = self._init_configuration(Configuration)

        # configuration could be None, if the Configuration class
        # is not suitable.
        # in that case the _validate_classes will exist with a more global check.

        self._validate_classes(Configuration, Interface, Transmission, Features)

        # at this point all classes have the good type

        logging.info("All classes are of valid type")
        self._validate_dependance(Configuration, Interface, Transmission, Features)
        logging.info("All dependances are met")

        # after all validation configuration should not be empty
        # checking just in case

        if not configuration:
            logging.critical("configuration was not created, should not happen (sorry)")
            sys.exit(FATAL_ERROR)

        # ready to lauch
        self._launch(configuration, Configuration, Interface, Transmission, Features)

        sys.exit(SUCCESS)

    def _init_logging(self):
        # logging.basicConfig(format='%(levelname)s:%(asctime)s:%(message)s',  level=logging.DEBUG)
        # logging instance
        self.logging = logging.getLogger()
        self.logging.setLevel(logging.DEBUG)
        # clean handlers :
        self.logging.handlers = []
        # create console handler and set level to debug
        ch = logging.StreamHandler()
        ch.setLevel(logging.DEBUG)
        # create formatter
        formatter = logging.Formatter("%(levelname)s:%(asctime)s:%(filename)s:%(lineno)d:%(message)s")

        # add formatter to ch
        ch.setFormatter(formatter)
        # add ch to logger
        self.logging.addHandler(ch)

        # default logging handler, not known for the momment
        self.lh_stdout = ch

    def _launch(self, configuration, Configuration, Interface, Transmission, Features):
        """ _launch create the bocore object and wait for it's return.
        At return Bocore objet will answer a set of classes, and a
        status tellling this function if this agent must be rebooter, reconfigured or stopped

        @type  configuration: class instance that load, check and store the Configuration
        @param configuration: the configuration object

        @type  Configuration: a subclass of the Configuration class 
        @param Configuration: Class that load, check and store the Configuration

        @type  Interface: a subclass of the Interface class 
        @param Interface: Class that manage the reception of order, its run function is the listening loop

        @type  Features: a list of subclass of the Feature class 
        @param Features: list of Class that process the order

        @type  Transmission: a subclass of the Transmission class 
        @param Transmission: Class that manage the connexion of other agent and transmit the orders to them

        @return nothing
        
        """

        # known object in a structure, that structure will be uses as return type par Bocore.run()
        original_bokor_struct = {
            "configuration_object": configuration,
            "Configuration": Configuration,
            "Interface": Interface,
            "interface_object": None,
            "Transmission": Transmission,
            "transmission_object": None,
            "Features": Features,
            "feature_object_list": [],
            "status": "init",  # no bject instantiated exept configuration
        }
        # we keep original and use bokor_struct
        logging.info("original structure for agent : %s" % (str(original_bokor_struct)))
        bokor_struct = original_bokor_struct.copy()
        self.bocore = None

        # main loop
        while True:
            # creating only if needed
            if not self.bocore:
                logging.info("building bocore object")
                self.bocore = Bocore(configuration, Configuration, Interface, Transmission, Features)
            # running agent
            bokor_struct = self.bocore.run()
            # shall we quit ?
            if bokor_struct["status"] in ["quit"] or self.force_quit:
                self.bocore.destroy()
                break
            # shall we destroy Bocore ?
            # clodrebbot : destroy all then recreate
            if bokor_struct["status"] in ["coldreboot"]:
                self.bocore.destroy()
                self.bocore = None

            sleep(15)
        return

    def _init_configuration(self, Configuration):
        """ try to get logging from Configuration, if Configuration does not provide a logging
        _try_and_get_logging will configure stderr as logging
        
        @type  Configuration: a subclass of the Configuration class 
        @param Configuration: Class that load, check and store the Configuration

        return a Configuration instance, or None if not possible to instanciate Configuration, 
        """
        configuration = None
        valid_class = issubclass(Configuration, BaseConfiguration)
        if valid_class:
            configuration = Configuration()
            # if configuration is not ready (missing conf file)
        self._try_and_get_logging(configuration)
        return configuration

    def _try_and_get_logging(self, configuration):
        """ try to get logging from Configuration, if Configuration does not provide a logging
        _try_and_get_logging will configure stderr as logging
        
        @type  configuration: a subclass of the Configuration class 
        @param configuration: a Configuration object

        @return Nothing, 
        """
        new_handler = None

        if configuration:
            # we try to get the newhandler
            #
            new_handler = configuration.get_logging_handler()
        if new_handler:
            self.logging.debug("new handler %s for logging given by %s" % (new_handler, configuration))
            # rest handlers
            self.logging.handlers = []
            # installing the new handler
            self.logging.addHandler(new_handler)
            # setting new logging level
            self.logging.setLevel(new_handler.level)

        logging.info("logging ready")

    def _validate_dependance(self, Configuration, Interface, Transmission, Features):
        """validate that all classes are meeting their dependances
        (class must be vlid before)
        
        @type  Configuration: a subclass of the Configuration class 
        @param Configuration: Class that load, check and store the Configuration

        @type  Interface: a subclass of the Interface class 
        @param Interface: Class that manage the reception of order, its run function is the listening loop

        @type  Features: a list of subclass of the Feature class 
        @param Features: list of Class that process the order

        @type  Transmission: a subclass of the Transmission class 
        @param Transmission: Class that manage the connexion of other agent and transmit the orders to them

        return : True if everything is valid
        """

        valid = True
        all_valid = True
        for bokorclass in [Configuration, Interface, Transmission] + Features:
            # maybe it can be None
            if bokorclass is None:
                continue
            for categorie, knowns in [
                ("configuration", [Configuration]),
                ("interface", [Interface]),
                ("transmission", [Transmission]),
                ("feature", Features),
            ]:
                for dclass in bokorclass.dependances[categorie]:
                    valid = False
                    for known in knowns:
                        if self._is_sub_class(known, dclass, log=False):
                            valid = True
                    if not valid:
                        logging.critical(
                            "%s need of a %s for %s, but %s will be loaded"
                            % (bokorclass, dclass, categorie, str(knowns))
                        )
                        all_valid = False

        if not all_valid:
            sys.exit(FATAL_ERROR)

    def _validate_classes(self, Configuration, Interface, Transmission, Features):
        """validate all clsses given as subclasses of the wanted class

        @type  Configuration: a subclass of the Configuration class 
        @param Configuration: Class that load, check and store the Configuration

        @type  Interface: a subclass of the Interface class 
        @param Interface: Class that manage the reception of order, its run function is the listening loop

        @type  Features: a list of subclass of the Feature class 
        @param Features: list of Class that process the order

        @type  Transmission: a subclass of the Transmission class 
        @param Transmission: Class that manage the connexion of other agent and transmit the orders to them

        return : Nothing, quit if not validate
        """

        valid = self._is_sub_class(Configuration, BaseConfiguration)
        valid = self._is_sub_class(Interface, BaseInterface) and valid
        valid = self._is_sub_class(Transmission, BaseTransmission, allow_none=True) and valid
        valid = (
            reduce(lambda x, y: x and y, [self._is_sub_class(Feature, Executor) for Feature in Features], True)
            and valid
        )
        if not valid:
            logging.error("Classes misfit, aborting")
            sys.exit(FATAL_ERROR)

    def _is_sub_class(self, wanted, mandatory, allow_none=False, log=True):
        """validate that wanted is a sub class of mandatory

        @type  wanted: a class wanted
        @param wanted: the class to test

        @type  mandatory: a class
        @param mandatory: the class that wanted should heritated from

        return True if wanted is a sub class of mandatory, False in any other case
        """
        try:
            # are we allowing None and is it None as wanted
            if allow_none and not wanted:
                return True
            if not issubclass(wanted, mandatory):
                if log:
                    logging.error("%s is not a sub Class of %s" % (wanted.__name__, mandatory.__name__))
                return False
            return True
        except TypeError:
            if log:
                logging.error(
                    "%s is not a Class but a %s (awaiting a sub class of %s)"
                    % (str(wanted), type(wanted), mandatory.__name__)
                )
        return False

    def quiting(self, signal, frame):
        logging.critical("Caught signal %s, exiting." % (str(signal)))
        self.force_quit = True
        self.bocore.interface.stop("quit")
        sys.exit()
Example #3
0
    def _launch(self, configuration, Configuration, Interface, Transmission,
                Features):
        """ _launch create the bocore object and wait for it's return.
        At return Bocore objet will answer a set of classes, and a
        status tellling this function if this agent must be rebooter, reconfigured or stopped

        @type  configuration: class instance that load, check and store the Configuration
        @param configuration: the configuration object

        @type  Configuration: a subclass of the Configuration class 
        @param Configuration: Class that load, check and store the Configuration

        @type  Interface: a subclass of the Interface class 
        @param Interface: Class that manage the reception of order, its run function is the listening loop

        @type  Features: a list of subclass of the Feature class 
        @param Features: list of Class that process the order

        @type  Transmission: a subclass of the Transmission class 
        @param Transmission: Class that manage the connexion of other agent and transmit the orders to them

        @return nothing
        
        """

        #known object in a structure, that structure will be uses as return type par Bocore.run()
        original_bokor_struct = {
            'configuration_object': configuration,
            'Configuration': Configuration,
            'Interface': Interface,
            'interface_object': None,
            'Transmission': Transmission,
            'transmission_object': None,
            'Features': Features,
            'feature_object_list': [],
            'status': 'init',  #no bject instantiated exept configuration
        }
        # we keep original and use bokor_struct
        logging.info("original structure for agent : %s" %
                     (str(original_bokor_struct)))
        bokor_struct = original_bokor_struct.copy()
        self.bocore = None

        # main loop
        while True:
            # creating only if needed
            if not self.bocore:
                logging.info("building bocore object")
                self.bocore = Bocore(configuration, Configuration, Interface,
                                     Transmission, Features)
            #running agent
            bokor_struct = self.bocore.run()
            #shall we quit ?
            if bokor_struct['status'] in ['quit'] or self.force_quit:
                self.bocore.destroy()
                break
            #shall we destroy Bocore ?
            # clodrebbot : destroy all then recreate
            if bokor_struct['status'] in ['coldreboot']:
                self.bocore.destroy()
                self.bocore = None

            sleep(15)
        return
Example #4
0
    def _launch(self, configuration, Configuration, Interface, Transmission, Features):
        """ _launch create the bocore object and wait for it's return.
        At return Bocore objet will answer a set of classes, and a
        status tellling this function if this agent must be rebooter, reconfigured or stopped

        @type  configuration: class instance that load, check and store the Configuration
        @param configuration: the configuration object

        @type  Configuration: a subclass of the Configuration class 
        @param Configuration: Class that load, check and store the Configuration

        @type  Interface: a subclass of the Interface class 
        @param Interface: Class that manage the reception of order, its run function is the listening loop

        @type  Features: a list of subclass of the Feature class 
        @param Features: list of Class that process the order

        @type  Transmission: a subclass of the Transmission class 
        @param Transmission: Class that manage the connexion of other agent and transmit the orders to them

        @return nothing
        
        """

        # known object in a structure, that structure will be uses as return type par Bocore.run()
        original_bokor_struct = {
            "configuration_object": configuration,
            "Configuration": Configuration,
            "Interface": Interface,
            "interface_object": None,
            "Transmission": Transmission,
            "transmission_object": None,
            "Features": Features,
            "feature_object_list": [],
            "status": "init",  # no bject instantiated exept configuration
        }
        # we keep original and use bokor_struct
        logging.info("original structure for agent : %s" % (str(original_bokor_struct)))
        bokor_struct = original_bokor_struct.copy()
        self.bocore = None

        # main loop
        while True:
            # creating only if needed
            if not self.bocore:
                logging.info("building bocore object")
                self.bocore = Bocore(configuration, Configuration, Interface, Transmission, Features)
            # running agent
            bokor_struct = self.bocore.run()
            # shall we quit ?
            if bokor_struct["status"] in ["quit"] or self.force_quit:
                self.bocore.destroy()
                break
            # shall we destroy Bocore ?
            # clodrebbot : destroy all then recreate
            if bokor_struct["status"] in ["coldreboot"]:
                self.bocore.destroy()
                self.bocore = None

            sleep(15)
        return