Exemplo n.º 1
0
    def verify_controller_module(module):
        """Verifies a module object follows the required interface for
        controllers.

        Args:
            module: An object that is a controller module. This is usually
                    imported with import statements or loaded by importlib.

        Raises:
            ControllerError is raised if the module does not match the ACTS
            controller interface, or one of the required members is null.
        """
        required_attributes = ("create", "destroy",
                               "ACTS_CONTROLLER_CONFIG_NAME")
        for attr in required_attributes:
            if not hasattr(module, attr):
                raise signals.ControllerError(
                    ("Module %s missing required "
                     "controller module attribute %s.") %
                    (module.__name__, attr))
            if not getattr(module, attr):
                raise signals.ControllerError(
                    "Controller interface %s in %s cannot be null." %
                    (attr, module.__name__))
Exemplo n.º 2
0
    def register_controller(self,
                            controller_module,
                            required=True,
                            builtin=False):
        """Registers an ACTS controller module for a test run.

        An ACTS controller module is a Python lib that can be used to control
        a device, service, or equipment. To be ACTS compatible, a controller
        module needs to have the following members:

            def create(configs):
                [Required] Creates controller objects from configurations.
                Args:
                    configs: A list of serialized data like string/dict. Each
                             element of the list is a configuration for a
                             controller object.
                Returns:
                    A list of objects.

            def destroy(objects):
                [Required] Destroys controller objects created by the create
                function. Each controller object shall be properly cleaned up
                and all the resources held should be released, e.g. memory
                allocation, sockets, file handlers etc.
                Args:
                    A list of controller objects created by the create function.

            def get_info(objects):
                [Optional] Gets info from the controller objects used in a test
                run. The info will be included in test_result_summary.json under
                the key "ControllerInfo". Such information could include unique
                ID, version, or anything that could be useful for describing the
                test bed and debugging.
                Args:
                    objects: A list of controller objects created by the create
                             function.
                Returns:
                    A list of json serializable objects, each represents the
                    info of a controller object. The order of the info object
                    should follow that of the input objects.
            def get_post_job_info(controller_list):
                [Optional] Returns information about the controller after the
                test has run. This info is sent to test_run_summary.json's
                "Extras" key.
                Args:
                    The list of controller objects created by the module
                Returns:
                    A (name, data) tuple.
        Registering a controller module declares a test class's dependency the
        controller. If the module config exists and the module matches the
        controller interface, controller objects will be instantiated with
        corresponding configs. The module should be imported first.

        Args:
            controller_module: A module that follows the controller module
                interface.
            required: A bool. If True, failing to register the specified
                controller module raises exceptions. If False, returns None upon
                failures.
            builtin: Specifies that the module is a builtin controller module in
                ACTS. If true, adds itself to test_run_info.
        Returns:
            A list of controller objects instantiated from controller_module, or
            None.

        Raises:
            When required is True, ControllerError is raised if no corresponding
            config can be found.
            Regardless of the value of "required", ControllerError is raised if
            the controller module has already been registered or any other error
            occurred in the registration process.
        """
        TestRunner.verify_controller_module(controller_module)
        module_ref_name = self.get_module_reference_name(controller_module)

        if controller_module in self.controller_registry:
            raise signals.ControllerError(
                "Controller module %s has already been registered. It can not "
                "be registered again." % module_ref_name)
        # Create controller objects.
        module_config_name = controller_module.ACTS_CONTROLLER_CONFIG_NAME
        if module_config_name not in self.testbed_configs:
            if required:
                raise signals.ControllerError(
                    "No corresponding config found for %s" %
                    module_config_name)
            else:
                self.log.warning(
                    "No corresponding config found for optional controller %s",
                    module_config_name)
            return None
        try:
            # Make a deep copy of the config to pass to the controller module,
            # in case the controller module modifies the config internally.
            original_config = self.testbed_configs[module_config_name]
            controller_config = copy.deepcopy(original_config)
            controllers = controller_module.create(controller_config)
        except:
            self.log.exception(
                "Failed to initialize objects for controller %s, abort!",
                module_config_name)
            raise
        if not isinstance(controllers, list):
            raise signals.ControllerError(
                "Controller module %s did not return a list of objects, abort."
                % module_ref_name)
        self.controller_registry[controller_module] = controllers
        # Collect controller information and write to test result.
        # Implementation of "get_info" is optional for a controller module.
        if hasattr(controller_module, "get_info"):
            controller_info = controller_module.get_info(controllers)
            self.log.info("Controller %s: %s", module_config_name,
                          controller_info)
            self.results.add_controller_info(module_config_name,
                                             controller_info)
        else:
            self.log.warning("No controller info obtained for %s",
                             module_config_name)

        # TODO(angli): After all tests move to register_controller, stop
        # tracking controller objs in test_run_info.
        if builtin:
            self.test_run_info[module_ref_name] = controllers
        self.log.debug("Found %d objects for controller %s", len(controllers),
                       module_config_name)
        return controllers
    def register_controller(self, module, required=True):
        """Registers a controller module for a test run.

        This declares a controller dependency of this test class. If the target
        module exists and matches the controller interface, the controller
        module will be instantiated with corresponding configs in the test
        config file. The module should be imported first.

        Args:
            module: A module that follows the controller module interface.
            required: A bool. If True, failing to register the specified
                      controller module raises exceptions. If False, returns
                      None upon failures.

        Returns:
            A list of controller objects instantiated from controller_module, or
            None.

        Raises:
            When required is True, ControllerError is raised if no corresponding
            config can be found.
            Regardless of the value of "required", ControllerError is raised if
            the controller module has already been registered or any other error
            occurred in the registration process.
        """
        TestRunner.verify_controller_module(module)
        try:
            # If this is a builtin controller module, use the default ref name.
            module_ref_name = module.ACTS_CONTROLLER_REFERENCE_NAME
            builtin = True
        except AttributeError:
            # Or use the module's name
            builtin = False
            module_ref_name = module.__name__.split('.')[-1]
        if module_ref_name in self.controller_registry:
            raise signals.ControllerError(
                ("Controller module %s has already been registered. It can not"
                 " be registered again.") % module_ref_name)
        # Create controller objects.
        create = module.create
        module_config_name = module.ACTS_CONTROLLER_CONFIG_NAME
        if module_config_name not in self.testbed_configs:
            if required:
                raise signals.ControllerError(
                    "No corresponding config found for %s" %
                    module_config_name)
            self.log.warning(
                "No corresponding config found for optional controller %s",
                module_config_name)
            return None
        try:
            # Make a deep copy of the config to pass to the controller module,
            # in case the controller module modifies the config internally.
            original_config = self.testbed_configs[module_config_name]
            controller_config = copy.deepcopy(original_config)
            objects = create(controller_config)
        except:
            self.log.exception(
                "Failed to initialize objects for controller %s, abort!",
                module_config_name)
            raise
        if not isinstance(objects, list):
            raise ControllerError(
                "Controller module %s did not return a list of objects, abort."
                % module_ref_name)
        self.controller_registry[module_ref_name] = objects
        # TODO(angli): After all tests move to register_controller, stop
        # tracking controller objs in test_run_info.
        if builtin:
            self.test_run_info[module_ref_name] = objects
        self.log.debug("Found %d objects for controller %s", len(objects),
                       module_config_name)
        destroy_func = module.destroy
        self.controller_destructors[module_ref_name] = destroy_func
        return objects