Esempio n. 1
0
File: docker.py Progetto: slawr/lava
    def run(self, connection, max_end_time):
        # obtain lava overlay
        # start container
        # create USB device mapping to container
        # connect to container, and run lava-test-shell over it
        location = self.get_namespace_data(action="test",
                                           label="shared",
                                           key="location")
        overlay = self.get_namespace_data(
            action="test", label="results",
            key="lava_test_results_dir").strip("/")

        image = self.parameters["docker"]["image"]
        container = "lava-docker-test-shell-%s-%s" % (self.job.job_id,
                                                      self.level)

        board_id = self.get_board_id()
        device_info = {"board_id": board_id}
        add_device_container_mapping(
            job_id=self.job.job_id,
            device_info=device_info,
            container=container,
            container_type="docker",
            logging_info=self.get_logging_info(),
        )

        docker = DockerRun(image)
        docker.bind_mount(os.path.join(location, overlay), "/" + overlay)
        docker.interactive()
        docker.hostname("lava")
        docker.name(container)
        docker.environment("PS1", "docker-test-shell:$ ")
        if self.wait_for_device:
            devices = get_udev_devices(device_info=[device_info])
            for dev in devices:
                docker.add_device(dev)

        docker_cmd = docker.cmdline("bash", "--norc", "-i")

        cmd = " ".join([shlex.quote(s) for s in docker_cmd])
        self.logger.debug("Starting docker test shell container: %s" % cmd)
        shell = ShellCommand(cmd, self.timeout, logger=self.logger)

        shell_connection = ShellSession(self.job, shell)
        shell_connection.prompt_str = "docker-test-shell:"

        self.__set_connection__(shell_connection)
        super().run(shell_connection, max_end_time)

        # finish the container
        shell_connection.finalise()

        # return the original connection untouched
        self.__set_connection__(connection)
        return connection
Esempio n. 2
0
 def run(self, connection, max_end_time, args=None):
     connection = super(LxcAddStaticDevices, self).run(connection, max_end_time, args)
     lxc_name = self.get_namespace_data(action='lxc-create-action', label='lxc', key='name')
     # If there are no USB devices under static_info then this action should be idempotent.
     if not self.get_usb_devices():
         return connection
     device_list = get_udev_devices(
         job=self.job, logger=self.logger,
         device_info=self.get_usb_devices())
     for link in device_list:
         lxc_cmd = ['lxc-device', '-n', lxc_name, 'add', link]
         cmd_out = self.run_command(lxc_cmd, allow_silent=True)
         if not isinstance(cmd_out, bool) and cmd_out:
             self.logger.debug(cmd_out)
     return connection
Esempio n. 3
0
 def run(self, connection, max_end_time):
     connection = super().run(connection, max_end_time)
     lxc_name = self.get_namespace_data(action='lxc-create-action',
                                        label='lxc',
                                        key='name')
     # If there are no USB devices under static_info then this action should be idempotent.
     if not self.get_usb_devices():
         return connection
     device_list = get_udev_devices(job=self.job,
                                    logger=self.logger,
                                    device_info=self.get_usb_devices())
     for link in device_list:
         lxc_cmd = ['lxc-device', '-n', lxc_name, 'add', link]
         cmd_out = self.run_command(lxc_cmd, allow_silent=True)
         if not isinstance(cmd_out, bool) and cmd_out:
             self.logger.debug(cmd_out)
     return connection
Esempio n. 4
0
 def __get_device_nodes__(self):
     device_info = self.action.job.device.get("device_info", {})
     if device_info:
         return get_udev_devices(device_info=device_info)
     else:
         return []
Esempio n. 5
0
    def run(self, connection, max_end_time):
        # obtain lava overlay
        # start container
        # create USB device mapping to container
        # connect to container, and run lava-test-shell over it
        location = self.get_namespace_data(action="test",
                                           label="shared",
                                           key="location")
        overlay = self.get_namespace_data(
            action="test", label="results",
            key="lava_test_results_dir").strip("/")

        container = "lava-docker-test-shell-%s-%s" % (self.job.job_id,
                                                      self.level)

        docker = DockerRun.from_parameters(self.parameters["docker"])
        docker.prepare()
        docker.bind_mount(os.path.join(location, overlay), "/" + overlay)

        namespace = self.parameters.get("downloads-namespace",
                                        self.parameters.get("namespace"))
        if namespace:
            downloads_dir = pathlib.Path(
                self.job.tmp_dir) / "downloads" / namespace
            if downloads_dir.exists():
                docker.bind_mount(downloads_dir, LAVA_DOWNLOADS)

        for bind_mount in self.test_docker_bind_mounts:
            read_only = True if len(bind_mount) == 2 else False
            docker.bind_mount(bind_mount[0], bind_mount[1], read_only)

        docker.interactive()
        docker.tty()
        docker.hostname("lava")
        docker.name(container)
        docker.environment("PS1", "docker-test-shell:$ ")

        docker_cmd = docker.cmdline("bash", "--norc", "-i")

        cmd = " ".join([shlex.quote(s) for s in docker_cmd])
        self.logger.debug("Starting docker test shell container: %s" % cmd)
        shell = ShellCommand(cmd, self.timeout, logger=self.logger)

        shell_connection = ShellSession(self.job, shell)
        shell_connection.prompt_str = "docker-test-shell:"
        self.__set_connection__(shell_connection)

        self.add_device_container_mappings(container, "docker")

        devices = get_udev_devices(device_info=self.device_info,
                                   logger=self.logger,
                                   required=False)

        docker.wait()

        # share all the devices as there isn't a 1:1 relationship between
        # the trigger and actual sharing of the devices
        for dev in devices:
            if not os.path.islink(dev):
                self.trigger_share_device_with_container(dev)

        for dev in devices:
            docker.wait_file(dev)

        try:
            super().run(shell_connection, max_end_time)
        finally:
            # finish the container
            shell_connection.finalise()
            docker.destroy()

        # return the original connection untouched
        self.__set_connection__(connection)
        return connection
Esempio n. 6
0
    def run(self, connection, max_end_time):
        # obtain lava overlay
        # start container
        # create USB device mapping to container
        # connect to container, and run lava-test-shell over it
        location = self.get_namespace_data(action="test",
                                           label="shared",
                                           key="location")
        overlay = self.get_namespace_data(
            action="test", label="results",
            key="lava_test_results_dir").strip("/")

        container = "lava-docker-test-shell-%s-%s" % (self.job.job_id,
                                                      self.level)

        docker = DockerRun.from_parameters(self.parameters["docker"], self.job)
        docker.prepare()
        docker.bind_mount(os.path.join(location, overlay), "/" + overlay)

        docker_method_conf = (self.job.device["actions"].get("test", {}).get(
            "methods", {}).get("docker", {}))

        # Preprocess docker option list, to better support partial
        # overriding of them via device dict:
        # 1. Filter out None, to make it easier to template
        # YAML syntactic lists with Jinja2:
        # '- {{ some_opt_from_device_dict }}'
        # (if not default, will be set to None).
        # 2. Flatten sublists, `- ['--opt1', '--opt2']`.
        def preproc_opts(opts):
            res = []
            for o in opts:
                if o is None:
                    continue
                elif isinstance(o, list):
                    res += o
                else:
                    res.append(o)
            return res

        if "global_options" in docker_method_conf:
            docker.add_docker_options(
                *preproc_opts(docker_method_conf["global_options"]))
        if "options" in docker_method_conf:
            docker.add_docker_run_options(
                *preproc_opts(docker_method_conf["options"]))

        namespace = self.parameters.get("downloads-namespace",
                                        self.parameters.get("namespace"))
        if namespace:
            downloads_dir = pathlib.Path(
                self.job.tmp_dir) / "downloads" / namespace
            if downloads_dir.exists():
                docker.bind_mount(downloads_dir, LAVA_DOWNLOADS)

        for bind_mount in self.test_docker_bind_mounts:
            read_only = True if len(bind_mount) == 2 else False
            docker.bind_mount(bind_mount[0], bind_mount[1], read_only)

        docker.interactive()
        docker.tty()
        docker.name(container)
        docker.environment("PS1", "docker-test-shell:$ ")

        docker_cmd = docker.cmdline("bash", "--norc", "-i")

        cmd = " ".join([shlex.quote(s) for s in docker_cmd])
        self.logger.debug("Starting docker test shell container: %s" % cmd)
        shell = ShellCommand(cmd, self.timeout, logger=self.logger)

        shell_connection = ShellSession(self.job, shell)
        shell_connection.prompt_str = "docker-test-shell:"
        self.__set_connection__(shell_connection)

        self.add_device_container_mappings(container, "docker")

        devices = get_udev_devices(device_info=self.device_info,
                                   logger=self.logger,
                                   required=False)

        docker.wait(shell)

        # share all the devices as there isn't a 1:1 relationship between
        # the trigger and actual sharing of the devices
        for dev in devices:
            if not os.path.islink(dev):
                self.trigger_share_device_with_container(dev)

        for dev in devices:
            docker.wait_file(dev)

        try:
            super().run(shell_connection, max_end_time)
        finally:
            # finish the container
            shell_connection.finalise()
            docker.destroy()

        # return the original connection untouched
        self.__set_connection__(connection)
        return connection