Beispiel #1
0
    def validate(self):
        super(DockerAction, self).validate()
        which("docker")

        # Print docker version
        try:
            out = subprocess.check_output(
                ["docker", "version", "-f", "{{.Server.Version}}"])
            out = out.decode("utf-8", errors="replace").strip("\n")
            self.logger.debug("docker server, installed at version: %s", out)
            out = subprocess.check_output(
                ["docker", "version", "-f", "{{.Client.Version}}"])
            out = out.decode("utf-8", errors="replace").strip("\n")
            self.logger.debug("docker client, installed at version: %s", out)
        except subprocess.CalledProcessError as exc:
            raise InfrastructureError("Unable to call '%s': %s" %
                                      (exc.cmd, exc.output))
        except OSError:
            raise InfrastructureError("Command 'docker' does not exist")

        # check docker image name
        # The string should be safe for command line inclusion
        image_name = self.parameters["image"]
        if re.compile("^[a-z0-9._:/-]+$").match(image_name) is None:
            self.errors = "image_name '%s' is invalid" % image_name
        self.set_namespace_data(action=self.name,
                                label='image',
                                key='name',
                                value=image_name)
Beispiel #2
0
    def validate(self):
        super().validate()
        persist = self.parameters.get("persistent_nfs")
        if not persist:
            return
        if "address" not in persist:
            self.errors = "Missing address for persistent NFS"
            return
        if ":" not in persist["address"]:
            self.errors = ("Unrecognised NFS URL: '%s'" %
                           self.parameters["persistent_nfs"]["address"])
            return
        nfs_server, dirname = persist["address"].split(":")
        which("rpcinfo")
        self.errors = rpcinfo_nfs(nfs_server)
        self.set_namespace_data(action=self.name,
                                label="nfs_address",
                                key="nfsroot",
                                value=dirname)
        self.set_namespace_data(action=self.name,
                                label="nfs_address",
                                key="serverip",
                                value=nfs_server)

        self.job.device["dynamic_data"]["NFS_ROOTFS"] = dirname
        self.job.device["dynamic_data"]["NFS_SERVER_IP"] = nfs_server
Beispiel #3
0
 def validate(self):
     super().validate()
     if not self.parameters.get("ramdisk"):  # idempotency
         return
     if not self.parameters["ramdisk"].get(
         "install_modules", True
     ) and not self.parameters["ramdisk"].get("install_overlay", True):
         self.skip = True
         return
     if "parameters" in self.job.device["actions"]["deploy"]:
         self.add_header = self.job.device["actions"]["deploy"]["parameters"].get(
             "add_header"
         )
         if self.add_header is not None:
             if self.add_header == "u-boot":
                 which("mkimage")
                 if (
                     "mkimage_arch"
                     not in self.job.device["actions"]["deploy"]["parameters"]
                 ):
                     self.errors = "Missing architecture for uboot mkimage support (mkimage_arch in deploy parameters)"
                     return
                 self.mkimage_arch = self.job.device["actions"]["deploy"][
                     "parameters"
                 ]["mkimage_arch"]
             else:
                 self.errors = "ramdisk: add_header: unknown header type"
Beispiel #4
0
 def validate(self):
     super(UBootPrepareKernelAction, self).validate()
     if 'parameters' not in self.job.device['actions']['deploy']:
         return
     self.params = self.job.device['actions']['deploy']['parameters']
     self.kernel_type = self.get_namespace_data(
         action='download-action',
         label='type',
         key='kernel'
     )
     self.bootcommand = None
     if 'parameters' not in self.job.device:
         if self.kernel_type:
             self.errors = "Kernel boot type is not supported by this device."
     if self.kernel_type:
         self.set_namespace_data(action=self.name, label='prepared-kernel', key='exists', value=True)
         self.bootcommand = map_kernel_uboot(self.kernel_type, self.job.device.get('parameters', None))
         self.kernel_type = str(self.kernel_type).lower()
         if self.bootcommand not in self.job.device['parameters']:
             self.errors = "Requested kernel boot type '%s' is not supported by this device." % self.bootcommand
         if self.kernel_type == "bootm" or self.kernel_type == "bootz" or self.kernel_type == "booti":
             self.errors = "booti, bootm and bootz are deprecated, please use 'image', 'uimage' or 'zimage'"
         which('mkimage')
         if 'mkimage_arch' not in self.params:
             self.errors = "Missing architecture for uboot mkimage support (mkimage_arch in u-boot parameters)"
         if self.bootcommand == 'bootm' and self.kernel_type != 'uimage':
             self.mkimage_conversion = True
     self.set_namespace_data(
         action='uboot-prepare-kernel', label='bootcommand',
         key='bootcommand', value=self.bootcommand)
Beispiel #5
0
 def validate(self):
     super().validate()
     boot = self.job.device['actions']['boot']['methods']['pyocd']
     pyocd_binary = boot['parameters']['command']
     which(pyocd_binary)
     self.base_command = [pyocd_binary]
     self.base_command.extend(boot['parameters'].get('options', []))
     if self.job.device['board_id'] == '0000000000':
         self.errors = "[PYOCD] board_id unset"
     substitutions = {}
     self.base_command.extend(['--board', self.job.device['board_id']])
     for action in self.get_namespace_keys('download-action'):
         pyocd_full_command = []
         image_arg = self.get_namespace_data(action='download-action',
                                             label=action,
                                             key='image_arg')
         action_arg = self.get_namespace_data(action='download-action',
                                              label=action,
                                              key='file')
         if image_arg:
             if not isinstance(image_arg, str):
                 self.errors = "image_arg is not a string (try quoting it)"
                 continue
             substitutions["{%s}" % action] = action_arg
             pyocd_full_command.extend(self.base_command)
             pyocd_full_command.extend(
                 substitute([image_arg], substitutions))
             self.exec_list.append(pyocd_full_command)
         else:
             pyocd_full_command.extend(self.base_command)
             pyocd_full_command.extend([action_arg])
             self.exec_list.append(pyocd_full_command)
     if len(self.exec_list) < 1:
         self.errors = "No PyOCD command to execute"
Beispiel #6
0
 def validate(self):
     super().validate()
     if 'parameters' not in self.job.device['actions']['deploy']:
         return
     self.params = self.job.device['actions']['deploy']['parameters']
     self.kernel_type = self.get_namespace_data(action='download-action',
                                                label='type',
                                                key='kernel')
     self.bootcommand = None
     if 'parameters' not in self.job.device:
         if self.kernel_type:
             self.errors = "Kernel boot type is not supported by this device."
     if self.kernel_type:
         self.set_namespace_data(action=self.name,
                                 label='prepared-kernel',
                                 key='exists',
                                 value=True)
         self.bootcommand = map_kernel_uboot(
             self.kernel_type, self.job.device.get('parameters'))
         self.kernel_type = str(self.kernel_type).lower()
         if self.bootcommand not in self.job.device['parameters']:
             self.errors = "Requested kernel boot type '%s' is not supported by this device." % self.bootcommand
         if self.kernel_type == "bootm" or self.kernel_type == "bootz" or self.kernel_type == "booti":
             self.errors = "booti, bootm and bootz are deprecated, please use 'image', 'uimage' or 'zimage'"
         which('mkimage')
         if 'mkimage_arch' not in self.params:
             self.errors = "Missing architecture for uboot mkimage support (mkimage_arch in u-boot parameters)"
         if self.bootcommand == 'bootm' and self.kernel_type != 'uimage':
             self.mkimage_conversion = True
     self.set_namespace_data(action='uboot-prepare-kernel',
                             label='bootcommand',
                             key='bootcommand',
                             value=self.bootcommand)
Beispiel #7
0
    def validate(self):
        super(TftpAction, self).validate()
        if 'kernel' not in self.parameters:
            self.errors = "%s needs a kernel to deploy" % self.name
        if not self.valid:
            return
        if 'nfs_url' in self.parameters:
            self.errors = "Use a persistent_nfs dictionary instead of nfs_url"
        if 'nfsrootfs' in self.parameters and 'persistent_nfs' in self.parameters:
            self.errors = "Only one of nfsrootfs or persistent_nfs can be specified"
        # Extract the 3 last path elements. See action.mkdtemp()
        suffix = os.path.join(*self.tftp_dir.split('/')[-2:])
        self.set_namespace_data(action=self.name,
                                label='tftp',
                                key='suffix',
                                value=suffix)
        which('in.tftpd')

        # Check that the tmp directory is in the tftpd_dir or in /tmp for the
        # unit tests
        tftpd_directory = os.path.realpath(tftpd_dir())
        tftp_dir = os.path.realpath(self.tftp_dir)
        tmp_dir = tempfile.gettempdir()
        if not tftp_dir.startswith(tftpd_directory) and \
           not tftp_dir.startswith(tmp_dir):
            self.errors = "tftpd directory is not configured correctly, see /etc/default/tftpd-hpa"
Beispiel #8
0
 def validate(self):
     super(FlashPyOCDAction, self).validate()
     boot = self.job.device['actions']['boot']['methods']['pyocd']
     pyocd_binary = boot['parameters']['command']
     which(pyocd_binary)
     self.base_command = [pyocd_binary]
     self.base_command.extend(boot['parameters'].get('options', []))
     if self.job.device['board_id'] == '0000000000':
         self.errors = "board_id unset"
     substitutions = {}
     self.base_command.extend(['--board', self.job.device['board_id']])
     namespace = self.parameters['namespace']
     for action in self.data[namespace]['download-action'].keys():
         pyocd_full_command = []
         image_arg = self.get_namespace_data(action='download-action', label=action, key='image_arg')
         action_arg = self.get_namespace_data(action='download-action', label=action, key='file')
         if image_arg:
             if not isinstance(image_arg, str):
                 self.errors = "image_arg is not a string (try quoting it)"
                 continue
             substitutions["{%s}" % action] = action_arg
             pyocd_full_command.extend(self.base_command)
             pyocd_full_command.extend(substitute([image_arg], substitutions))
             self.exec_list.append(pyocd_full_command)
         else:
             pyocd_full_command.extend(self.base_command)
             pyocd_full_command.extend([action_arg])
             self.exec_list.append(pyocd_full_command)
     if len(self.exec_list) < 1:
         self.errors = "No PyOCD command to execute"
Beispiel #9
0
    def validate(self):
        super(NbdAction, self).validate()
        if 'kernel' not in self.parameters:
            self.errors = "%s needs a kernel to deploy" % self.name
        if not self.valid:
            return
        if 'nbdroot' not in self.parameters:
            self.errors = "NBD deployment needs a 'nbdroot' parameter"
        if 'initrd' not in self.parameters:
            self.errors = "NBD deployment needs an 'initrd' parameter"
        # we cannot work with these when using nbd
        if 'nfsrootfs' in self.parameters or 'nfs_url' in self.parameters:
            self.errors = "nfsrootfs or nfs_url cannot be used with NBD deployment, use a e.g. ext3/4 filesystem as 'nbdroot=' parameter"
        if 'ramdisk' in self.parameters:
            self.errors = "ramdisk cannot be used with NBD deployment, use a e.g. ext3/4 filesystem as 'initrd' parameter"

        # Extract the 3 last path elements. See action.mkdtemp()
        suffix = os.path.join(*self.tftp_dir.split('/')[-2:])
        self.set_namespace_data(action="tftp-deploy", label='tftp', key='suffix', value=suffix)
        # we need tftp _and_ xnbd-server
        which('in.tftpd')
        which('xnbd-server')

        # Check that the tmp directory is in the nbdd_dir or in /tmp for the
        # unit tests
        tftpd_directory = os.path.realpath(tftpd_dir())
        tftp_dir = os.path.realpath(self.tftp_dir)
        tmp_dir = tempfile.gettempdir()
        if not tftp_dir.startswith(tftpd_directory) and \
           not tftp_dir.startswith(tmp_dir):
            self.errors = "tftpd directory is not configured correctly, see /etc/default/tftpd-hpa"
Beispiel #10
0
 def validate(self):
     super(Scp, self).validate()
     params = self._check_params()
     which('scp')
     if 'ssh' not in self.job.device['actions']['deploy']['methods']:
         self.errors = "Unable to use %s without ssh deployment" % self.name
     if 'ssh' not in self.job.device['actions']['boot']['methods']:
         self.errors = "Unable to use %s without ssh boot" % self.name
     if self.get_namespace_data(action='prepare-scp-overlay',
                                label="prepare-scp-overlay",
                                key=self.key):
         self.primary = False
     elif 'host' not in self.job.device['actions']['deploy']['methods'][
             'ssh']:
         self.errors = "Invalid device or job configuration, missing host."
     if not self.primary and len(
             self.get_namespace_data(action='prepare-scp-overlay',
                                     label="prepare-scp-overlay",
                                     key=self.key)) != 1:
         self.errors = "Invalid number of host_keys"
     if self.primary:
         host_address = self.job.device['actions']['deploy']['methods'][
             'ssh']['host']
         if not host_address:
             self.errors = "Unable to retrieve ssh_host address for primary connection."
     if 'port' in self.job.device['actions']['deploy']['methods']['ssh']:
         port = str(
             self.job.device['actions']['deploy']['methods']['ssh']['port'])
         if not port.isdigit():
             self.errors = "Port was set but was not a digit"
     if self.valid:
         self.scp.append('scp')
         if 'options' in params:
             self.scp.extend(params['options'])
Beispiel #11
0
 def _check_command(self):
     exe = ''
     try:
         exe = self.command.split(' ')[0]
     except AttributeError:
         self.errors = "Unable to parse the connection command %s" % self.command
     which(exe)
Beispiel #12
0
 def validate(self):
     super().validate()
     suffix = os.path.join(*self.preseed_path.split("/")[-2:])
     self.set_namespace_data(
         action=self.name, label="iso", key="suffix", value=suffix
     )
     which("in.tftpd")
Beispiel #13
0
    def validate(self):
        super().validate()
        if 'kernel' not in self.parameters:
            self.errors = "%s needs a kernel to deploy" % self.name
        if not self.valid:
            return
        if 'nbdroot' not in self.parameters:
            self.errors = "NBD deployment needs a 'nbdroot' parameter"
        if 'initrd' not in self.parameters:
            self.errors = "NBD deployment needs an 'initrd' parameter"
        # we cannot work with these when using nbd
        if 'nfsrootfs' in self.parameters or 'nfs_url' in self.parameters:
            self.errors = "nfsrootfs or nfs_url cannot be used with NBD deployment, use a e.g. ext3/4 filesystem as 'nbdroot=' parameter"
        if 'ramdisk' in self.parameters:
            self.errors = "ramdisk cannot be used with NBD deployment, use a e.g. ext3/4 filesystem as 'initrd' parameter"

        # Extract the 3 last path elements. See action.mkdtemp()
        suffix = os.path.join(*self.tftp_dir.split('/')[-2:])
        self.set_namespace_data(action="tftp-deploy",
                                label='tftp',
                                key='suffix',
                                value=suffix)
        # we need tftp _and_ xnbd-server
        which('in.tftpd')
        which('xnbd-server')

        # Check that the tmp directory is in the nbdd_dir or in /tmp for the
        # unit tests
        tftpd_directory = os.path.realpath(tftpd_dir())
        tftp_dir = os.path.realpath(self.tftp_dir)
        tmp_dir = tempfile.gettempdir()
        if not tftp_dir.startswith(tftpd_directory) and \
           not tftp_dir.startswith(tmp_dir):
            self.errors = "tftpd directory is not configured correctly, see /etc/default/tftpd-hpa"
Beispiel #14
0
 def _check_command(self):
     exe = ''
     try:
         exe = self.command.split(' ')[0]
     except AttributeError:
         self.errors = "Unable to parse the connection command %s" % self.command
     which(exe)
Beispiel #15
0
 def validate(self):
     if "lxc" not in self.job.device["actions"]["boot"]["methods"]:
         return
     super().validate()
     which("lxc-attach")
     if "lxc" not in self.job.device["actions"]["boot"]["connections"]:
         self.errors = "Device not configured to support LXC connection."
Beispiel #16
0
 def validate(self):
     super().validate()
     suffix = os.path.join(*self.preseed_path.split('/')[-2:])
     self.set_namespace_data(action=self.name,
                             label='iso',
                             key='suffix',
                             value=suffix)
     which('in.tftpd')
Beispiel #17
0
 def validate(self):
     if "adb" not in self.job.device["actions"]["boot"]["methods"]:
         return
     if "adb_serial_number" not in self.job.device:
         self.errors = "device adb serial number missing"
     if "adb" not in self.job.device["actions"]["boot"]["connections"]:
         self.errors = "Device not configured to support adb connection."
     super().validate()
     which("adb")
Beispiel #18
0
 def validate(self):
     super().validate()
     which("bmaptool")
     self.params = self.job.device["actions"]["boot"]["methods"][
         self.parameters["method"]
     ]["parameters"]
     if self.params.get("uboot_mass_storage_device", False):
         self.ums_device = self.params["uboot_mass_storage_device"]
     else:
         raise JobError("uboot_mass_storage_device is not set")
Beispiel #19
0
 def validate(self):
     super(LxcAction, self).validate()
     self.logger.info("lxc, installed at version: %s",
                      debian_package_version(pkg='lxc', split=False))
     protocols = [protocol.name for protocol in self.job.protocols]
     if LxcProtocol.name not in protocols:
         self.logger.debug("Missing protocol '%s' in %s",
                           LxcProtocol.name, protocols)
         self.errors = "Missing protocol '%s'" % LxcProtocol.name
     which('lxc-create')
Beispiel #20
0
    def validate(self):
        super().validate()
        which("mkimage")

        self.deploy_params = self.job.device["actions"]["deploy"].get(
            "parameters", dict())

        device_params = self.job.device.get("parameters")
        if device_params is None:
            self.errors = "Missing device parameters"
        elif "load_address" not in device_params:
            self.errors = "Missing load_address from device parameters"
        else:
            self.device_params = device_params
Beispiel #21
0
 def validate(self):
     super().validate()
     lxc_version = debian_package_version(pkg='lxc', split=False)
     if lxc_version is not '':
         self.logger.info("lxc, installed at version: %s", lxc_version)
     else:
         self.logger.info(
             "lava-lxc-mocker, installed at version: %s",
             debian_package_version(pkg='lava-lxc-mocker', split=False))
     protocols = [protocol.name for protocol in self.job.protocols]
     if LxcProtocol.name not in protocols:
         self.logger.debug("Missing protocol '%s' in %s", LxcProtocol.name,
                           protocols)
         self.errors = "Missing protocol '%s'" % LxcProtocol.name
     which('lxc-create')
Beispiel #22
0
def cpio(directory, filename):
    which("cpio")
    which("find")
    with chdir(directory):
        try:
            find = subprocess.check_output(["find", "."],
                                           stderr=subprocess.STDOUT)  # nosec
            return subprocess.check_output(  # nosec
                ["cpio", "--create", "--format", "newc", "--file", filename],
                input=find,
                stderr=subprocess.STDOUT,
            ).decode("utf-8", errors="replace")
        except Exception as exc:
            raise InfrastructureError("Unable to create cpio archive %r: %s" %
                                      (filename, exc))
Beispiel #23
0
    def validate(self):
        super(QemuCommandLine, self).validate()
        boot = self.job.device['actions']['boot']['methods']['qemu']
        qemu_binary = which(boot['parameters']['command'])
        self.sub_command = [qemu_binary]
        self.sub_command.extend(boot['parameters'].get('options', []))
        boot_opts = boot['parameters'].get('boot_options', None)
        if boot_opts:
            self.console = "console=%s" % boot_opts['console']
            self.boot_order = "-boot %s" % boot_opts['boot_order']
        if not qemu_binary or not self.console or not self.boot_order:
            self.errors = "Invalid parameters for %s" % self.name
        # create the preseed.cfg url
        # needs to be an IP address for DI, DNS is not available.
        # PRESEED_URL='http://10.15.0.32/tmp/d-i/jessie/preseed.cfg'
        ip_addr = dispatcher_ip(self.job.parameters['dispatcher'])
        self.preseed_url = 'tftp://%s/' % ip_addr

        self.sub_command.append(' -drive format=raw,file={emptyimage} ')
        self.sub_command.append(self.boot_order)
        self.command_line = " -append '%s console=tty0 console=tty1 %s %s %s %s preseed/url=%s{preseed} --- %s '  " % (
            self.parameters['deployment_data']['base'],
            self.parameters['deployment_data']['locale'],
            self.console,
            self.parameters['deployment_data']['keymaps'],
            self.parameters['deployment_data']['netcfg'],
            self.preseed_url,
            self.console)
        self.set_namespace_data(action=self.name, label=self.name, key='prompts', value=self.parameters['deployment_data']['prompts'])
        self.set_namespace_data(action=self.name, label=self.name, key='append', value=self.command_line)
Beispiel #24
0
 def validate(self):
     super(PersistentNFSOverlay, self).validate()
     persist = self.parameters.get('persistent_nfs', None)
     if not persist:
         return
     if 'address' not in persist:
         self.errors = "Missing address for persistent NFS"
         return
     if ':' not in persist['address']:
         self.errors = "Unrecognised NFS URL: '%s'" % self.parameters['persistent_nfs']['address']
         return
     nfs_server, dirname = persist['address'].split(':')
     which('rpcinfo')
     self.errors = rpcinfo_nfs(nfs_server)
     self.set_namespace_data(action=self.name, label='nfs_address', key='nfsroot', value=dirname)
     self.set_namespace_data(action=self.name, label='nfs_address', key='serverip', value=nfs_server)
Beispiel #25
0
 def validate(self):
     super().validate()
     boot = self.job.device["actions"]["boot"]["methods"]["pyocd"]
     pyocd_binary = boot["parameters"]["command"]
     binary = which(pyocd_binary)
     self.logger.info(binary_version(binary, "--version"))
     self.base_command = [pyocd_binary]
     self.base_command.extend(boot["parameters"].get("options", []))
     if self.job.device["board_id"] == "0000000000":
         self.errors = "[PYOCD] board_id unset"
     substitutions = {}
     self.base_command.extend(["--board", self.job.device["board_id"]])
     for action in self.get_namespace_keys("download-action"):
         pyocd_full_command = []
         image_arg = self.get_namespace_data(action="download-action",
                                             label=action,
                                             key="image_arg")
         action_arg = self.get_namespace_data(action="download-action",
                                              label=action,
                                              key="file")
         if image_arg:
             if not isinstance(image_arg, str):
                 self.errors = "image_arg is not a string (try quoting it)"
                 continue
             substitutions["{%s}" % action] = action_arg
             pyocd_full_command.extend(self.base_command)
             pyocd_full_command.extend(
                 substitute([image_arg], substitutions))
             self.exec_list.append(pyocd_full_command)
         else:
             pyocd_full_command.extend(self.base_command)
             pyocd_full_command.extend([action_arg])
             self.exec_list.append(pyocd_full_command)
     if not self.exec_list:
         self.errors = "No PyOCD command to execute"
Beispiel #26
0
 def validate(self):
     super(ConnectSsh, self).validate()
     params = self._check_params()
     which('ssh')
     if 'host' in self.job.device['actions']['deploy']['methods']['ssh']:
         self.primary = True
         self.host = self.job.device['actions']['deploy']['methods']['ssh']['host']
     if self.valid:
         self.command = ['ssh']
         if 'options' in params:
             self.command.extend(params['options'])
         # add arguments to ignore host key checking of the host device
         self.command.extend(['-o', 'UserKnownHostsFile=/dev/null', '-o', 'StrictHostKeyChecking=no'])
         if self.identity_file:
             # add optional identity file
             self.command.extend(['-i', self.identity_file])
         self.command.extend(self.ssh_port)
Beispiel #27
0
    def validate(self):
        super().validate()
        which("docker")

        options = self.job.device["actions"]["deploy"]["methods"]["docker"]["options"]
        if options["remote"]:
            self.remote = ["--host"] + [options["remote"]]

        # Print docker version
        try:
            out = subprocess.check_output(  # nosec - internal
                ["docker"] + self.remote + ["version", "-f", "{{.Server.Version}}"]
            )
            out = out.decode("utf-8", errors="replace").strip("\n")
            self.logger.debug("docker server, installed at version: %s", out)
            out = subprocess.check_output(  # nosec - internal
                ["docker", "version", "-f", "{{.Client.Version}}"]
            )
            out = out.decode("utf-8", errors="replace").strip("\n")
            self.logger.debug("docker client, installed at version: %s", out)
        except subprocess.CalledProcessError as exc:
            raise InfrastructureError("Unable to call '%s': %s" % (exc.cmd, exc.output))
        except OSError:
            raise InfrastructureError("Command 'docker' does not exist")

        # "image" can be a dict or a string
        image = self.parameters["image"]
        if isinstance(image, str):
            self.image_name = image
            self.local = False
        else:
            self.image_name = image["name"]
            self.local = image.get("local", False)

        # check docker image name
        # The string should be safe for command line inclusion
        if (
            re.compile(
                "^[a-z0-9]+[a-z0-9._/-]*[a-z0-9]+(:[a-zA-Z0-9_]+[a-zA-Z0-9._-]*)?$"
            ).match(self.image_name)
            is None
        ):
            self.errors = "image name '%s' is invalid" % self.image_name
        self.set_namespace_data(
            action=self.name, label="image", key="name", value=self.image_name
        )
Beispiel #28
0
def uncpio(filename, directory):
    which("cpio")
    with chdir(directory):
        try:
            subprocess.check_output(  # nosec
                [
                    "cpio",
                    "--extract",
                    "--make-directories",
                    "--unconditional",
                    "--file",
                    filename,
                ],
                stderr=subprocess.STDOUT,
            )
        except subprocess.SubprocessError as exc:
            raise InfrastructureError("Unable to extract cpio archive %r: %s" %
                                      (filename, exc))
Beispiel #29
0
def compress_file(infile, compression):
    if not compression:
        return infile
    if compression not in compress_command_map.keys():
        raise JobError("Cannot find shell command to compress: %s" % compression)

    # Check that the command does exists
    which(compress_command_map[compression][0])

    with chdir(os.path.dirname(infile)):
        # local copy for idempotency
        cmd = compress_command_map[compression][:]
        cmd.append(infile)
        try:
            subprocess.check_output(cmd)  # nosec - internal use.
            return "%s.%s" % (infile, compression)
        except (OSError, subprocess.CalledProcessError) as exc:
            raise InfrastructureError("unable to compress file %s: %s" % (infile, exc))
Beispiel #30
0
    def validate(self):
        super().validate()
        if "kernel" not in self.parameters:
            self.errors = "%s needs a kernel to deploy" % self.name
        if not self.valid:
            return
        if "nfsrootfs" in self.parameters and "persistent_nfs" in self.parameters:
            self.errors = "Only one of nfsrootfs or persistent_nfs can be specified"
        which("in.tftpd")

        # Check that the tmp directory is in the tftpd_dir or in /tmp for the
        # unit tests
        tftpd_directory = os.path.realpath(filesystem.tftpd_dir())
        tftp_dir = os.path.realpath(self.tftp_dir)
        tmp_dir = tempfile.gettempdir()
        if not tftp_dir.startswith(
                tftpd_directory) and not tftp_dir.startswith(tmp_dir):
            self.errors = "tftpd directory is not configured correctly, see /etc/default/tftpd-hpa"
Beispiel #31
0
    def validate(self):
        super().validate()
        which("mkimage")

        deploy_params = self.job.device["actions"]["deploy"].get("parameters")
        if deploy_params is None:
            self.errors = "Missing parameters in deploy action"
        elif "mkimage_arch" not in deploy_params:
            self.errors = "Missing mkimage_arch parameter for FIT support"
        else:
            self.deploy_params = deploy_params

        device_params = self.job.device.get("parameters")
        if device_params is None:
            self.errors = "Missing device parameters"
        elif "load_address" not in device_params:
            self.errors = "Missing load_address from device parameters"
        else:
            self.device_params = device_params
def compress_file(infile, compression):
    if not compression:
        return infile
    if compression not in compress_command_map.keys():
        raise JobError("Cannot find shell command to compress: %s" %
                       compression)

    # Check that the command does exists
    which(compress_command_map[compression].split(" ")[0])

    with chdir(os.path.dirname(infile)):
        cmd = "%s %s" % (compress_command_map[compression], infile)
        try:
            # safe to use shell=True here, no external arguments
            subprocess.check_output(cmd, shell=True)
            return "%s.%s" % (infile, compression)
        except (OSError, subprocess.CalledProcessError) as exc:
            raise InfrastructureError('unable to compress file %s: %s' %
                                      (infile, exc))
Beispiel #33
0
    def validate(self):
        super(PrepareFITAction, self).validate()
        which('mkimage')

        deploy_params = self.job.device['actions']['deploy'].get('parameters')
        if deploy_params is None:
            self.errors = "Missing parameters in deploy action"
        elif 'mkimage_arch' not in deploy_params:
            self.errors = "Missing mkimage_arch parameter for FIT support"
        else:
            self.deploy_params = deploy_params

        device_params = self.job.device.get('parameters')
        if device_params is None:
            self.errors = "Missing device parameters"
        elif 'load_address' not in device_params:
            self.errors = "Missing load_address from device parameters"
        else:
            self.device_params = device_params
Beispiel #34
0
 def validate(self):
     super(CompressRamdisk, self).validate()
     if not self.parameters.get('ramdisk', None):  # idempotency
         return
     if not self.parameters['ramdisk'].get('install_modules', True) and \
             not self.parameters['ramdisk'].get('install_overlay', True):
         self.skip = True
         return
     if 'parameters' in self.job.device['actions']['deploy']:
         self.add_header = self.job.device['actions']['deploy']['parameters'].get('add_header', None)
         if self.add_header is not None:
             if self.add_header == 'u-boot':
                 which('mkimage')
                 if 'mkimage_arch' not in self.job.device['actions']['deploy']['parameters']:
                     self.errors = "Missing architecture for uboot mkimage support (mkimage_arch in deploy parameters)"
                     return
                 self.mkimage_arch = self.job.device['actions']['deploy']['parameters']['mkimage_arch']
             else:
                 self.errors = "ramdisk: add_header: unknown header type"
Beispiel #35
0
    def validate(self):
        super().validate()
        which('mkimage')

        deploy_params = self.job.device['actions']['deploy'].get('parameters')
        if deploy_params is None:
            self.errors = "Missing parameters in deploy action"
        elif 'mkimage_arch' not in deploy_params:
            self.errors = "Missing mkimage_arch parameter for FIT support"
        else:
            self.deploy_params = deploy_params

        device_params = self.job.device.get('parameters')
        if device_params is None:
            self.errors = "Missing device parameters"
        elif 'load_address' not in device_params:
            self.errors = "Missing load_address from device parameters"
        else:
            self.device_params = device_params
Beispiel #36
0
Datei: ssh.py Projekt: czfgd/lava
 def validate(self):
     super().validate()
     params = self._check_params()
     which("scp")
     if "ssh" not in self.job.device["actions"]["deploy"]["methods"]:
         self.errors = "Unable to use %s without ssh deployment" % self.name
     if "ssh" not in self.job.device["actions"]["boot"]["methods"]:
         self.errors = "Unable to use %s without ssh boot" % self.name
     if self.get_namespace_data(
         action="prepare-scp-overlay", label="prepare-scp-overlay", key=self.key
     ):
         self.primary = False
     elif "host" not in self.job.device["actions"]["deploy"]["methods"]["ssh"]:
         self.errors = "Invalid device or job configuration, missing host."
     if (
         not self.primary
         and len(
             self.get_namespace_data(
                 action="prepare-scp-overlay",
                 label="prepare-scp-overlay",
                 key=self.key,
             )
         )
         != 1
     ):
         self.errors = "Invalid number of host_keys"
     if self.primary:
         host_address = self.job.device["actions"]["deploy"]["methods"]["ssh"][
             "host"
         ]
         if not host_address:
             self.errors = (
                 "Unable to retrieve ssh_host address for primary connection."
             )
     if "port" in self.job.device["actions"]["deploy"]["methods"]["ssh"]:
         port = str(self.job.device["actions"]["deploy"]["methods"]["ssh"]["port"])
         if not port.isdigit():
             self.errors = "Port was set but was not a digit"
     if self.valid:
         self.scp.append("scp")
         if "options" in params:
             self.scp.extend(params["options"])
Beispiel #37
0
 def validate(self):
     super(LxcCreateUdevRuleAction, self).validate()
     which('udevadm')
     if 'device_info' in self.job.device \
        and not isinstance(self.job.device.get('device_info'), list):
         self.errors = "device_info unset"
     # If we are allowed to use a filesystem label, we don't require a board_id
     # By default, we do require a board_id (serial)
     requires_board_id = not allow_fs_label(self.job.device)
     try:
         if 'device_info' in self.job.device:
             for usb_device in self.job.device['device_info']:
                 if usb_device.get('board_id', '') in ['', '0000000000'] \
                         and requires_board_id:
                     self.errors = "board_id unset"
                 if usb_device.get('usb_vendor_id', '') == '0000':
                     self.errors = 'usb_vendor_id unset'
                 if usb_device.get('usb_product_id', '') == '0000':
                     self.errors = 'usb_product_id unset'
     except TypeError:
         self.errors = "Invalid parameters for %s" % self.name
Beispiel #38
0
 def validate(self):
     """
     The unit test skips if schroot is not installed, the action marks the
     pipeline as invalid if schroot is not installed.
     """
     if "schroot" not in self.parameters:
         return
     if "schroot" not in self.job.device["actions"]["boot"]["methods"]:
         self.errors = "No schroot support in device boot methods"
         return
     which("schroot")
     # device parameters are for ssh
     params = self.job.device["actions"]["boot"]["methods"]
     if "command" not in params["schroot"]:
         self.errors = "Missing schroot command in device configuration"
         return
     if "name" not in params["schroot"]:
         self.errors = "Missing schroot name in device configuration"
         return
     self.schroot = params["schroot"]["name"]
     self.command = params["schroot"]["command"]
Beispiel #39
0
 def validate(self):
     super(IsoRebootAction, self).validate()
     if 'prompts' not in self.parameters:
         self.errors = "Unable to identify boot prompts from job definition."
     try:
         boot = self.job.device['actions']['boot']['methods']['qemu']
         qemu_binary = which(boot['parameters']['command'])
         self.sub_command = [qemu_binary]
         self.sub_command.extend(boot['parameters'].get('options', []))
     except AttributeError as exc:
         raise ConfigurationError(exc)
     except (KeyError, TypeError):
         self.errors = "Invalid parameters for %s" % self.name
Beispiel #40
0
    def validate(self):
        super(TftpAction, self).validate()
        if 'kernel' not in self.parameters:
            self.errors = "%s needs a kernel to deploy" % self.name
        if not self.valid:
            return
        if 'nfs_url' in self.parameters:
            self.errors = "Use a persistent_nfs dictionary instead of nfs_url"
        if 'nfsrootfs' in self.parameters and 'persistent_nfs' in self.parameters:
            self.errors = "Only one of nfsrootfs or persistent_nfs can be specified"
        # Extract the 3 last path elements. See action.mkdtemp()
        suffix = os.path.join(*self.tftp_dir.split('/')[-2:])
        self.set_namespace_data(action=self.name, label='tftp', key='suffix', value=suffix)
        which('in.tftpd')

        # Check that the tmp directory is in the tftpd_dir or in /tmp for the
        # unit tests
        tftpd_directory = os.path.realpath(tftpd_dir())
        tftp_dir = os.path.realpath(self.tftp_dir)
        tmp_dir = tempfile.gettempdir()
        if not tftp_dir.startswith(tftpd_directory) and \
           not tftp_dir.startswith(tmp_dir):
            self.errors = "tftpd directory is not configured correctly, see /etc/default/tftpd-hpa"
Beispiel #41
0
    def validate(self):
        super(DockerAction, self).validate()
        which("docker")

        # Print docker version
        try:
            out = subprocess.check_output(["docker", "version", "-f", "{{.Server.Version}}"])
            out = out.decode("utf-8", errors="replace").strip("\n")
            self.logger.debug("docker server, installed at version: %s", out)
            out = subprocess.check_output(["docker", "version", "-f", "{{.Client.Version}}"])
            out = out.decode("utf-8", errors="replace").strip("\n")
            self.logger.debug("docker client, installed at version: %s", out)
        except subprocess.CalledProcessError as exc:
            raise InfrastructureError("Unable to call '%s': %s" % (exc.cmd, exc.output))
        except OSError:
            raise InfrastructureError("Command 'docker' does not exist")

        # check docker image name
        # The string should be safe for command line inclusion
        image_name = self.parameters["image"]
        if re.compile("^[a-z0-9._:/-]+$").match(image_name) is None:
            self.errors = "image_name '%s' is invalid" % image_name
        self.set_namespace_data(action=self.name, label='image',
                                key='name', value=image_name)
Beispiel #42
0
 def validate(self):
     super(FlashDFUAction, self).validate()
     try:
         boot = self.job.device['actions']['boot']['methods']['dfu']
         dfu_binary = which(boot['parameters']['command'])
         self.base_command = [dfu_binary]
         self.base_command.extend(boot['parameters'].get('options', []))
         if self.job.device['board_id'] == '0000000000':
             self.errors = "board_id unset"
         if self.job.device['usb_vendor_id'] == '0000':
             self.errors = 'usb_vendor_id unset'
         if self.job.device['usb_product_id'] == '0000':
             self.errors = 'usb_product_id unset'
         self.usb_vendor_id = self.job.device['usb_vendor_id']
         self.usb_product_id = self.job.device['usb_product_id']
         self.board_id = self.job.device['board_id']
         self.base_command.extend(['--serial', self.board_id])
         self.base_command.extend(['--device', '%s:%s' % (self.usb_vendor_id, self.usb_product_id)])
     except AttributeError as exc:
         raise ConfigurationError(exc)
     except (KeyError, TypeError):
         self.errors = "Invalid parameters for %s" % self.name
     substitutions = {}
     namespace = self.parameters['namespace']
     for action in self.data[namespace]['download-action'].keys():
         dfu_full_command = []
         image_arg = self.data[namespace]['download-action'][action].get('image_arg', None)
         action_arg = self.data[namespace]['download-action'][action].get('file', None)
         if not image_arg or not action_arg:
             self.errors = "Missing image_arg for %s. " % action
             continue
         if not isinstance(image_arg, str):
             self.errors = "image_arg is not a string (try quoting it)"
             continue
         substitutions["{%s}" % action] = action_arg
         dfu_full_command.extend(self.base_command)
         dfu_full_command.extend(substitute([image_arg], substitutions))
         self.exec_list.append(dfu_full_command)
     if len(self.exec_list) < 1:
         self.errors = "No DFU command to execute"
Beispiel #43
0
 def validate(self):
     if 'lxc' not in self.job.device['actions']['boot']['methods']:
         return
     super(ConnectLxc, self).validate()
     which('lxc-attach')
Beispiel #44
0
    def validate(self):
        super(CallQemuAction, self).validate()

        # 'arch' must be defined in job definition context.
        try:
            if self.job.parameters['context']['arch'] not in \
               self.job.device['available_architectures']:
                self.errors = "Non existing architecture specified in context arch parameter. Please check the device configuration for available options."
                return
        except KeyError:
            self.errors = "Arch parameter must be set in the context section. Please check the device configuration for available architectures."
            return
        if self.job.parameters['context']['arch'] in ['amd64', 'x86_64']:
            self.logger.info("qemu-system-x86, installed at version: %s",
                             debian_package_version(pkg='qemu-system-x86', split=False))
        if self.job.parameters['context']['arch'] in ['arm64', 'arm', 'armhf', 'aarch64']:
            self.logger.info("qemu-system-arm, installed at version: %s",
                             debian_package_version(pkg='qemu-system-arm', split=False))

        if self.parameters['method'] in ['qemu', 'qemu-nfs']:
            if 'prompts' not in self.parameters:
                if self.test_has_shell(self.parameters):
                    self.errors = "Unable to identify boot prompts from job definition."
        self.methods = self.job.device['actions']['boot']['methods']
        method = self.parameters['method']
        boot = self.methods['qemu'] if 'qemu' in self.methods else self.methods['qemu-nfs']
        try:
            if 'parameters' not in boot or 'command' not in boot['parameters']:
                self.errors = "Invalid device configuration - missing parameters"
            elif not boot['parameters']['command']:
                self.errors = "No QEMU binary command found - missing context."
            qemu_binary = which(boot['parameters']['command'])
            self.sub_command = [qemu_binary]
            self.sub_command.extend(boot['parameters'].get('options', []))
            self.sub_command.extend(
                ['%s' % item for item in boot['parameters'].get('extra', [])])
        except AttributeError as exc:
            self.errors = "Unable to parse device options: %s %s" % (
                exc, self.job.device['actions']['boot']['methods'][method])
        except (KeyError, TypeError):
            self.errors = "Invalid parameters for %s" % self.name
        namespace = self.parameters['namespace']
        for label in self.data[namespace]['download-action'].keys():
            if label in ['offset', 'available_loops', 'uefi', 'nfsrootfs']:
                continue
            image_arg = self.get_namespace_data(action='download-action', label=label, key='image_arg')
            action_arg = self.get_namespace_data(action='download-action', label=label, key='file')
            if not image_arg or not action_arg:
                self.errors = "Missing image_arg for %s. " % label
                continue
            self.substitutions["{%s}" % label] = action_arg
            self.commands.append(image_arg)
        self.substitutions["{NFS_SERVER_IP}"] = dispatcher_ip(self.job.parameters['dispatcher'])
        self.sub_command.extend(substitute(self.commands, self.substitutions))
        if not self.sub_command:
            self.errors = "No QEMU command to execute"
        uefi_dir = self.get_namespace_data(action='deployimages', label='image', key='uefi_dir')
        if uefi_dir:
            self.sub_command.extend(['-L', uefi_dir, '-monitor', 'none'])

        # Check for enable-kvm command line option in device configuration.
        if method not in self.job.device['actions']['boot']['methods']:
            self.errors = "Unknown boot method '%s'" % method
            return

        options = self.job.device['actions']['boot']['methods'][method]['parameters']['options']
        if "-enable-kvm" in options:
            # Check if the worker has kvm enabled.
            if not os.path.exists(SYS_CLASS_KVM):
                self.errors = "Device configuration contains -enable-kvm option but kvm module is not enabled."
Beispiel #45
0
 def validate(self):
     super(DeployIsoAction, self).validate()
     suffix = os.path.join(*self.preseed_path.split('/')[-2:])
     self.set_namespace_data(action=self.name, label='iso', key='suffix', value=suffix)
     which('in.tftpd')
Beispiel #46
0
 def validate(self):
     super(ApplyOverlaySparseImage, self).validate()
     which('simg2img')
     which('mount')
     which('umount')
     which('img2simg')
Beispiel #47
0
 def validate(self):
     super(ApplyLxcOverlay, self).validate()
     which('tar')
     if not os.path.exists(self.lava_test_dir):
         self.errors = "Missing lava-test-runner: %s" % self.lava_test_dir
Beispiel #48
0
 def validate(self):
     super(LxcStartAction, self).validate()
     which('lxc-start')
Beispiel #49
0
 def validate(self):
     super(LxcStopAction, self).validate()
     which('lxc-stop')