示例#1
0
 def run(self, connection, max_end_time, args=None):
     connection = super(UefiSubstituteCommands, self).run(connection, max_end_time, args)
     ip_addr = dispatcher_ip(self.job.parameters['dispatcher'])
     substitution_dictionary = {
         '{SERVER_IP}': ip_addr,
         '{RAMDISK}': self.get_namespace_data(action='compress-ramdisk', label='file', key='ramdisk'),
         '{KERNEL}': self.get_namespace_data(action='download-action', label='file', key='kernel'),
         '{DTB}': self.get_namespace_data(action='download-action', label='file', key='dtb'),
         'TEST_MENU_NAME': "LAVA %s test image" % self.parameters['commands']
     }
     nfs_address = self.get_namespace_data(action='persistent-nfs-overlay', label='nfs_address', key='nfsroot')
     nfs_root = self.get_namespace_data(action='download-action', label='file', key='nfsrootfs')
     if nfs_root:
         substitution_dictionary['{NFSROOTFS}'] = self.get_namespace_data(action='extract-rootfs', label='file', key='nfsroot')
         substitution_dictionary['{NFS_SERVER_IP}'] = ip_addr
     elif nfs_address:
         substitution_dictionary['{NFSROOTFS}'] = nfs_address
         substitution_dictionary['{NFS_SERVER_IP}'] = self.get_namespace_data(
             action='persistent-nfs-overlay', label='nfs_address', key='serverip')
     for item in self.items:
         if 'enter' in item['select']:
             item['select']['enter'] = substitute([item['select']['enter']], substitution_dictionary)[0]
         if 'items' in item['select']:
             # items is already a list, so pass without wrapping in []
             item['select']['items'] = substitute(item['select']['items'], substitution_dictionary)
     return connection
示例#2
0
    def run(self, connection, max_end_time, args=None):
        # substitutions
        substitutions = {'{emptyimage}': self.get_namespace_data(action='prepare-empty-image', label='prepare-empty-image', key='output')}
        sub_command = self.get_namespace_data(action='prepare-qemu-commands', label='prepare-qemu-commands', key='sub_command')
        sub_command = substitute(sub_command, substitutions)
        command_line = ' '.join(sub_command)

        commands = []
        # get the download args in run()
        image_arg = self.get_namespace_data(action='download-action', label='iso', key='image_arg')
        action_arg = self.get_namespace_data(action='download-action', label='iso', key='file')
        substitutions["{%s}" % 'iso'] = action_arg
        commands.append(image_arg)
        command_line += ' '.join(substitute(commands, substitutions))

        preseed_file = self.get_namespace_data(action='download-action', label='file', key='preseed')
        if not preseed_file:
            raise JobError("Unable to identify downloaded preseed filename.")
        substitutions = {'{preseed}': preseed_file}
        append_args = self.get_namespace_data(action='prepare-qemu-commands', label='prepare-qemu-commands', key='append')
        append_args = substitute([append_args], substitutions)
        command_line += ' '.join(append_args)

        self.logger.info(command_line)
        shell = ShellCommand(command_line, self.timeout, logger=self.logger)
        if shell.exitstatus:
            raise JobError("%s command exited %d: %s" % (sub_command[0], shell.exitstatus, shell.readlines()))
        self.logger.debug("started a shell command")

        shell_connection = ShellSession(self.job, shell)
        shell_connection.prompt_str = self.get_namespace_data(
            action='prepare-qemu-commands', label='prepare-qemu-commands', key='prompts')
        shell_connection = super(IsoCommandLine, self).run(shell_connection, max_end_time, args)
        return shell_connection
示例#3
0
    def run(self, connection, max_end_time):
        connection = super().run(connection, max_end_time)

        # Create the cmdline file, this is not set by any bootloader command
        ip_addr = dispatcher_ip(self.job.parameters["dispatcher"])
        kernel_path = self.get_namespace_data(
            action="download-action", label="kernel", key="file"
        )
        cmdline_path = os.path.join(os.path.dirname(kernel_path), "cmdline")
        nfs_address = self.get_namespace_data(
            action="persistent-nfs-overlay", label="nfs_address", key="nfsroot"
        )
        nfs_root = self.get_namespace_data(
            action="download-action", label="file", key="nfsrootfs"
        )

        if nfs_root:
            substitutions = {
                "{NFSROOTFS}": self.get_namespace_data(
                    action="extract-rootfs", label="file", key="nfsroot"
                ),
                "{NFS_SERVER_IP}": ip_addr,
            }
        elif nfs_address:
            substitutions = {
                "{NFSROOTFS}": nfs_address,
                "{NFS_SERVER_IP}": self.get_namespace_data(
                    action="persistent-nfs-overlay", label="nfs_address", key="serverip"
                ),
            }
        else:
            substitutions = {}
        cmdline = substitute([self.cmdline], substitutions)[0]

        with open(cmdline_path, "w") as cmdline_file:
            cmdline_file.write(cmdline)

        # Substitute {CMDLINE} with the cmdline file TFTP path
        kernel_tftp = self.get_namespace_data(
            action="download-action", label="file", key="kernel"
        )
        cmdline_tftp = os.path.join(os.path.dirname(kernel_tftp), "cmdline")
        fit_tftp = self.get_namespace_data(
            action="prepare-fit", label="file", key="fit"
        )
        substitutions = {"{CMDLINE}": cmdline_tftp, "{FIT}": fit_tftp}
        commands = self.get_namespace_data(
            action="bootloader-overlay", label=self.method, key="commands"
        )
        commands = substitute(commands, substitutions)
        self.set_namespace_data(
            action="bootloader-overlay",
            label=self.method,
            key="commands",
            value=commands,
        )
        self.logger.info("Parsed boot commands: %s", "; ".join(commands))

        return connection
示例#4
0
文件: gdb.py 项目: doytsujin/lava
    def run(self, connection, max_end_time):
        connection = super().run(connection, max_end_time)

        # Build the substitutions dictionary
        substitutions = {}
        paths = set()
        for action in self.get_namespace_keys("download-action"):
            filename = self.get_namespace_data(action="download-action",
                                               label=action,
                                               key="file")
            if filename is None:
                self.logger.warning(
                    "Empty value for action='download-action' label='%s' key='file'",
                    action,
                )
                continue
            substitutions["{%s}" % action.upper()] = filename
            paths.add(os.path.dirname(filename))

        # If needed, prepend with docker
        if self.container is None:
            cmd = self.gdb
        else:
            cmd = "docker run --rm -it --name lava-%s-%s" % (
                self.job.job_id,
                self.level,
            )
            for path in paths:
                cmd += " --volume %s:%s" % (path, path)
            for device in self.devices:
                cmd += " --device %s:%s:rw" % (device, device)
            cmd += " %s %s" % (self.container, self.gdb)

        for arg in substitute(self.arguments, substitutions):
            cmd += " " + arg

        # Start gdb
        self.logger.info("Starting gdb: %s", cmd)
        shell = ShellCommand(cmd, self.timeout, logger=self.logger)
        gdb = ShellSession(self.job, shell)
        gdb.prompt_str = "\\(gdb\\) "
        self.gdb_connection = gdb
        self.gdb_connection.wait()

        # Send all gdb commands
        for cmd in substitute(self.commands, substitutions):
            self.gdb_connection.sendline(cmd)
            self.gdb_connection.wait()

        # "continue" is send last
        if self.wait_before_continue:
            self.logger.debug("Sleeping %ss before sending 'continue'",
                              self.wait_before_continue)
            time.sleep(self.wait_before_continue)
        self.gdb_connection.sendline("continue")

        return connection
示例#5
0
    def run(self, connection, max_end_time):
        # substitutions
        substitutions = {
            "{emptyimage}":
            self.get_namespace_data(action="prepare-empty-image",
                                    label="prepare-empty-image",
                                    key="output")
        }
        sub_command = self.get_namespace_data(
            action="prepare-qemu-commands",
            label="prepare-qemu-commands",
            key="sub_command",
        )
        sub_command = substitute(sub_command, substitutions)
        command_line = " ".join(sub_command)

        commands = []
        # get the download args in run()
        image_arg = self.get_namespace_data(action="download-action",
                                            label="iso",
                                            key="image_arg")
        action_arg = self.get_namespace_data(action="download-action",
                                             label="iso",
                                             key="file")
        substitutions["{%s}" % "iso"] = action_arg
        commands.append(image_arg)
        command_line += " ".join(substitute(commands, substitutions))

        preseed_file = self.get_namespace_data(action="download-action",
                                               label="file",
                                               key="preseed")
        if not preseed_file:
            raise JobError("Unable to identify downloaded preseed filename.")
        substitutions = {"{preseed}": preseed_file}
        append_args = self.get_namespace_data(action="prepare-qemu-commands",
                                              label="prepare-qemu-commands",
                                              key="append")
        append_args = substitute([append_args], substitutions)
        command_line += " ".join(append_args)

        self.logger.info(command_line)
        shell = ShellCommand(command_line, self.timeout, logger=self.logger)
        if shell.exitstatus:
            raise JobError(
                "%s command exited %d: %s" %
                (sub_command[0], shell.exitstatus, shell.readlines()))
        self.logger.debug("started a shell command")

        shell_connection = ShellSession(self.job, shell)
        shell_connection.prompt_str = self.get_namespace_data(
            action="prepare-qemu-commands",
            label="prepare-qemu-commands",
            key="prompts")
        shell_connection = super().run(shell_connection, max_end_time)
        return shell_connection
示例#6
0
    def run(self, connection, max_end_time, args=None):
        # substitutions
        substitutions = {
            '{emptyimage}':
            self.get_namespace_data(action='prepare-empty-image',
                                    label='prepare-empty-image',
                                    key='output')
        }
        sub_command = self.get_namespace_data(action='prepare-qemu-commands',
                                              label='prepare-qemu-commands',
                                              key='sub_command')
        sub_command = substitute(sub_command, substitutions)
        command_line = ' '.join(sub_command)

        commands = []
        # get the download args in run()
        image_arg = self.get_namespace_data(action='download-action',
                                            label='iso',
                                            key='image_arg')
        action_arg = self.get_namespace_data(action='download-action',
                                             label='iso',
                                             key='file')
        substitutions["{%s}" % 'iso'] = action_arg
        commands.append(image_arg)
        command_line += ' '.join(substitute(commands, substitutions))

        preseed_file = self.get_namespace_data(action='download-action',
                                               label='file',
                                               key='preseed')
        if not preseed_file:
            raise JobError("Unable to identify downloaded preseed filename.")
        substitutions = {'{preseed}': preseed_file}
        append_args = self.get_namespace_data(action='prepare-qemu-commands',
                                              label='prepare-qemu-commands',
                                              key='append')
        append_args = substitute([append_args], substitutions)
        command_line += ' '.join(append_args)

        self.logger.info(command_line)
        shell = ShellCommand(command_line, self.timeout, logger=self.logger)
        if shell.exitstatus:
            raise JobError(
                "%s command exited %d: %s" %
                (sub_command[0], shell.exitstatus, shell.readlines()))
        self.logger.debug("started a shell command")

        shell_connection = ShellSession(self.job, shell)
        shell_connection.prompt_str = self.get_namespace_data(
            action='prepare-qemu-commands',
            label='prepare-qemu-commands',
            key='prompts')
        shell_connection = super(IsoCommandLine,
                                 self).run(shell_connection, max_end_time,
                                           args)
        return shell_connection
示例#7
0
 def test_uefi_job(self):
     self.assertIsNotNone(self.job)
     self.job.validate()
     uefi_menu = [action for action in self.job.pipeline.actions if action.name == 'uefi-menu-action'][0]
     selector = [action for action in uefi_menu.internal_pipeline.actions if action.name == 'uefi-menu-selector'][0]
     self.assertEqual(
         selector.selector.prompt,
         "Start:"
     )
     self.assertIsInstance(selector.items, list)
     description_ref = self.pipeline_reference('mustang-uefi.yaml')
     self.assertEqual(description_ref, self.job.pipeline.describe(False))
     # just dummy strings
     substitution_dictionary = {
         '{SERVER_IP}': '10.4.0.1',
         '{RAMDISK}': None,
         '{KERNEL}': 'uImage',
         '{DTB}': 'mustang.dtb',
         '{NFSROOTFS}': 'tmp/tmp21dfed/',
         '{TEST_MENU_NAME}': 'LAVA NFS Test Image'
     }
     for block in selector.items:
         if 'select' in block:
             if 'enter' in block['select']:
                 block['select']['enter'] = substitute([block['select']['enter']], substitution_dictionary)
             if 'items' in block['select']:
                 block['select']['items'] = substitute(block['select']['items'], substitution_dictionary)
     count = 0
     check_block = [
         {'items': ['Boot Manager'], 'wait': 'Choice:'},
         {'items': ['Remove Boot Device Entry'], 'fallback': 'Return to Main Menu', 'wait': 'Delete entry'},
         {'items': ['LAVA NFS Test Image'], 'wait': 'Choice:'},
         {'items': ['Add Boot Device Entry'], 'wait': 'Select the Boot Device:'},
         {'items': ['TFTP on MAC Address: 00:01:73:69:5A:EF'], 'wait': 'Get the IP address from DHCP:'},
         {'enter': ['y'], 'wait': 'Get the TFTP server IP address:'},
         {'enter': ['10.4.0.1'], 'wait': 'File path of the EFI Application or the kernel :'},
         {'enter': ['uImage'], 'wait': 'Is an EFI Application?'},
         {'enter': ['n'], 'wait': 'Boot Type:'},
         {'enter': ['f'], 'wait': 'Add an initrd:'},
         {'enter': ['n'], 'wait': 'Get the IP address from DHCP:'},
         {'enter': ['y'], 'wait': 'Get the TFTP server IP address:'},
         {'enter': ['10.4.0.1'], 'wait': 'File path of the FDT :'},
         {'enter': ['mustang.dtb'], 'wait': 'Arguments to pass to the binary:'},
         {'enter': ['console=ttyS0,115200 earlyprintk=uart8250-32bit,0x1c020000 debug root=/dev/nfs rw '
                    'nfsroot=10.4.0.1:tmp/tmp21dfed/,tcp,hard,intr ip=dhcp'], 'wait': 'Description for this new Entry:'},
         {'enter': ['LAVA NFS Test Image'], 'wait': 'Choice:'},
         {'items': ['Return to main menu'], 'wait': 'Start:'},
         {'items': ['LAVA NFS Test Image']},
     ]
     for item in selector.items:
         self.assertEqual(
             item['select'],
             check_block[count])
         count += 1
示例#8
0
    def run(self, connection, max_end_time, args=None):
        connection = super(DepthchargeCommandOverlay, self).run(
            connection, max_end_time, args)

        # Create the cmdline file, this is not set by any bootloader command
        ip_addr = dispatcher_ip(self.job.parameters['dispatcher'])
        kernel_path = self.get_namespace_data(
            action='download-action', label='kernel', key='file')
        cmdline_path = os.path.join(os.path.dirname(kernel_path), 'cmdline')
        nfs_address = self.get_namespace_data(
            action='persistent-nfs-overlay', label='nfs_address', key='nfsroot')
        nfs_root = self.get_namespace_data(
            action='download-action', label='file', key='nfsrootfs')

        if nfs_root:
            substitutions = {
                '{NFSROOTFS}': self.get_namespace_data(
                    action='extract-rootfs', label='file', key='nfsroot'),
                '{NFS_SERVER_IP}': ip_addr,
            }
        elif nfs_address:
            substitutions = {
                '{NFSROOTFS}': nfs_address,
                '{NFS_SERVER_IP}': self.get_namespace_data(
                    action='persistent-nfs-overlay', label='nfs_address',
                    key='serverip'),
            }
        else:
            substitutions = {}
        cmdline = substitute([self.cmdline], substitutions)[0]

        with open(cmdline_path, "w") as cmdline_file:
            cmdline_file.write(cmdline)

        # Substitute {CMDLINE} with the cmdline file TFTP path
        kernel_tftp = self.get_namespace_data(
            action='download-action', label='file', key='kernel')
        cmdline_tftp = os.path.join(os.path.dirname(kernel_tftp), 'cmdline')
        fit_tftp = self.get_namespace_data(
            action='prepare-fit', label='file', key='fit')
        substitutions = {
            '{CMDLINE}': cmdline_tftp,
            '{FIT}': fit_tftp,
        }
        commands = self.get_namespace_data(
            action='bootloader-overlay', label=self.method, key='commands')
        commands = substitute(commands, substitutions)
        self.set_namespace_data(
            action='bootloader-overlay', label=self.method, key='commands',
            value=commands)
        self.logger.info("Parsed boot commands: %s", '; '.join(commands))

        return connection
示例#9
0
    def run(self, connection, max_end_time):
        connection = super().run(connection, max_end_time)

        # Create the cmdline file, this is not set by any bootloader command
        ip_addr = dispatcher_ip(self.job.parameters['dispatcher'])
        kernel_path = self.get_namespace_data(
            action='download-action', label='kernel', key='file')
        cmdline_path = os.path.join(os.path.dirname(kernel_path), 'cmdline')
        nfs_address = self.get_namespace_data(
            action='persistent-nfs-overlay', label='nfs_address', key='nfsroot')
        nfs_root = self.get_namespace_data(
            action='download-action', label='file', key='nfsrootfs')

        if nfs_root:
            substitutions = {
                '{NFSROOTFS}': self.get_namespace_data(
                    action='extract-rootfs', label='file', key='nfsroot'),
                '{NFS_SERVER_IP}': ip_addr,
            }
        elif nfs_address:
            substitutions = {
                '{NFSROOTFS}': nfs_address,
                '{NFS_SERVER_IP}': self.get_namespace_data(
                    action='persistent-nfs-overlay', label='nfs_address',
                    key='serverip'),
            }
        else:
            substitutions = {}
        cmdline = substitute([self.cmdline], substitutions)[0]

        with open(cmdline_path, "w") as cmdline_file:
            cmdline_file.write(cmdline)

        # Substitute {CMDLINE} with the cmdline file TFTP path
        kernel_tftp = self.get_namespace_data(
            action='download-action', label='file', key='kernel')
        cmdline_tftp = os.path.join(os.path.dirname(kernel_tftp), 'cmdline')
        fit_tftp = self.get_namespace_data(
            action='prepare-fit', label='file', key='fit')
        substitutions = {
            '{CMDLINE}': cmdline_tftp,
            '{FIT}': fit_tftp,
        }
        commands = self.get_namespace_data(
            action='bootloader-overlay', label=self.method, key='commands')
        commands = substitute(commands, substitutions)
        self.set_namespace_data(
            action='bootloader-overlay', label=self.method, key='commands',
            value=commands)
        self.logger.info("Parsed boot commands: %s", '; '.join(commands))

        return connection
示例#10
0
 def run(self, connection, max_end_time):
     connection = super().run(connection, max_end_time)
     ip_addr = dispatcher_ip(self.job.parameters["dispatcher"])
     substitution_dictionary = {
         "{SERVER_IP}":
         ip_addr,
         "{RAMDISK}":
         self.get_namespace_data(action="compress-ramdisk",
                                 label="file",
                                 key="ramdisk"),
         "{KERNEL}":
         self.get_namespace_data(action="download-action",
                                 label="file",
                                 key="kernel"),
         "{DTB}":
         self.get_namespace_data(action="download-action",
                                 label="file",
                                 key="dtb"),
         "TEST_MENU_NAME":
         "LAVA %s test image" % self.parameters["commands"],
     }
     nfs_address = self.get_namespace_data(action="persistent-nfs-overlay",
                                           label="nfs_address",
                                           key="nfsroot")
     nfs_root = self.get_namespace_data(action="download-action",
                                        label="file",
                                        key="nfsrootfs")
     if nfs_root:
         substitution_dictionary["{NFSROOTFS}"] = self.get_namespace_data(
             action="extract-rootfs", label="file", key="nfsroot")
         substitution_dictionary["{NFS_SERVER_IP}"] = dispatcher_ip(
             self.job.parameters["dispatcher"], "nfs")
     elif nfs_address:
         substitution_dictionary["{NFSROOTFS}"] = nfs_address
         substitution_dictionary[
             "{NFS_SERVER_IP}"] = self.get_namespace_data(
                 action="persistent-nfs-overlay",
                 label="nfs_address",
                 key="serverip")
     for item in self.items:
         if "enter" in item["select"]:
             item["select"]["enter"] = substitute(
                 [item["select"]["enter"]], substitution_dictionary)[0]
         if "items" in item["select"]:
             # items is already a list, so pass without wrapping in []
             item["select"]["items"] = substitute(item["select"]["items"],
                                                  substitution_dictionary)
     return connection
示例#11
0
 def run(self, connection, max_end_time, args=None):
     connection = super(UefiSubstituteCommands,
                        self).run(connection, max_end_time, args)
     ip_addr = dispatcher_ip(self.job.parameters['dispatcher'])
     substitution_dictionary = {
         '{SERVER_IP}':
         ip_addr,
         '{RAMDISK}':
         self.get_namespace_data(action='compress-ramdisk',
                                 label='file',
                                 key='ramdisk'),
         '{KERNEL}':
         self.get_namespace_data(action='download-action',
                                 label='file',
                                 key='kernel'),
         '{DTB}':
         self.get_namespace_data(action='download-action',
                                 label='file',
                                 key='dtb'),
         'TEST_MENU_NAME':
         "LAVA %s test image" % self.parameters['commands']
     }
     nfs_address = self.get_namespace_data(action='persistent-nfs-overlay',
                                           label='nfs_address',
                                           key='nfsroot')
     nfs_root = self.get_namespace_data(action='download-action',
                                        label='file',
                                        key='nfsrootfs')
     if nfs_root:
         substitution_dictionary['{NFSROOTFS}'] = self.get_namespace_data(
             action='extract-rootfs', label='file', key='nfsroot')
         substitution_dictionary['{NFS_SERVER_IP}'] = ip_addr
     elif nfs_address:
         substitution_dictionary['{NFSROOTFS}'] = nfs_address
         substitution_dictionary[
             '{NFS_SERVER_IP}'] = self.get_namespace_data(
                 action='persistent-nfs-overlay',
                 label='nfs_address',
                 key='serverip')
     for item in self.items:
         if 'enter' in item['select']:
             item['select']['enter'] = substitute(
                 [item['select']['enter']], substitution_dictionary)[0]
         if 'items' in item['select']:
             # items is already a list, so pass without wrapping in []
             item['select']['items'] = substitute(item['select']['items'],
                                                  substitution_dictionary)
     return connection
示例#12
0
    def test_overlay_noramdisk(self, which_mock):
        parameters = {
            "dispatcher": {},  # fake dispatcher parameter. Normally added by parser
            "device_type": "beaglebone-black",
            "job_name": "uboot-pipeline",
            "job_timeout": "15m",
            "action_timeout": "5m",
            "priority": "medium",
            "actions": {
                "boot": {
                    "namespace": "common",
                    "method": "u-boot",
                    "commands": "ramdisk",
                    "prompts": ["linaro-test", "root@debian:~#"],
                },
                "deploy": {
                    "namespace": "common",
                    "ramdisk": {"url": ""},
                    "kernel": {"url": "zImage", "type": "zimage"},
                    "dtb": {"url": "broken.dtb"},
                },
            },
        }
        data = yaml_safe_load(Factory().create_device("bbb-01.jinja2")[0])
        device = NewDevice(data)
        ip_addr = dispatcher_ip(None)
        parsed = []
        kernel_addr = "0x83000000"
        ramdisk_addr = "0x83000000"
        dtb_addr = "0x88000000"
        kernel = parameters["actions"]["deploy"]["kernel"]["url"]
        ramdisk = parameters["actions"]["deploy"]["ramdisk"]["url"]
        dtb = parameters["actions"]["deploy"]["dtb"]["url"]

        substitution_dictionary = {
            "{SERVER_IP}": ip_addr,
            # the addresses need to be hexadecimal
            "{KERNEL_ADDR}": kernel_addr,
            "{DTB_ADDR}": dtb_addr,
            "{RAMDISK_ADDR}": ramdisk_addr,
            "{BOOTX}": "%s %s %s %s" % ("bootz", kernel_addr, ramdisk_addr, dtb_addr),
            "{RAMDISK}": ramdisk,
            "{KERNEL}": kernel,
            "{DTB}": dtb,
        }
        params = device["actions"]["boot"]["methods"]
        params["u-boot"]["ramdisk"]["commands"] = substitute(
            params["u-boot"]["ramdisk"]["commands"], substitution_dictionary, drop=True
        )

        commands = params["u-boot"]["ramdisk"]["commands"]
        self.assertIs(type(commands), list)
        self.assertIn("tftp 0x83000000 zImage", commands)
        self.assertNotIn("tftp 0x83000000 {RAMDISK}", commands)
        self.assertNotIn("tftp 0x83000000 ", commands)
        self.assertIn("setenv initrd_size ${filesize}", commands)
        self.assertIn("tftp 0x88000000 broken.dtb", commands)
        self.assertNotIn("setenv kernel_addr_r '{KERNEL_ADDR}'", commands)
        self.assertNotIn("setenv initrd_addr_r '{RAMDISK_ADDR}'", commands)
        self.assertNotIn("setenv fdt_addr_r '{DTB_ADDR}'", commands)
示例#13
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"
示例#14
0
文件: pyocd.py 项目: doytsujin/lava
 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"
示例#15
0
 def run(self, connection, max_end_time, args=None):
     if 'deployment_data' not in self.parameters:
         return connection
     if self.parameters["deployment_data"].get('installer_extra_cmd', None):
         if self.parameters.get('os', None) == "debian_installer":
             add_late_command(
                 self.get_namespace_data(action='download-action',
                                         label='preseed',
                                         key='file'),
                 self.parameters["deployment_data"]["installer_extra_cmd"])
         if self.parameters.get('os', None) == "centos_installer":
             ip_addr = dispatcher_ip(self.job.parameters['dispatcher'])
             overlay = self.get_namespace_data(action='download-action',
                                               label='file',
                                               key='overlay')
             substitutions = {
                 '{OVERLAY_URL}': 'tftp://' + ip_addr + '/' + overlay
             }
             post_command = substitute([
                 self.parameters["deployment_data"]["installer_extra_cmd"]
             ], substitutions)
             add_to_kickstart(
                 self.get_namespace_data(action='download-action',
                                         label='preseed',
                                         key='file'), post_command[0])
     return connection
示例#16
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"
示例#17
0
    def run(self, connection, max_end_time, args=None):
        connection = super(FlasherAction, self).run(connection, max_end_time, args)
        # Substitute in the device commands
        substitutions = {}
        for key in [key for key in self.parameters['images'].keys() if key != "yaml_line"]:
            filename = self.get_namespace_data(action='download-action', label=key, key='file')
            filename = filename[len(self.path) + 1:]
            substitutions["{%s}" % key.upper()] = filename

        # Add power commands
        substitutions["{HARD_RESET_COMMAND}"] = self.job.device.hard_reset_command
        substitutions["{SOFT_RESET_COMMAND}"] = self.job.device.soft_reset_command
        substitutions["{PRE_OS_COMMAND}"] = self.job.device.pre_os_command
        if substitutions["{PRE_OS_COMMAND}"] is None:
            substitutions["{PRE_OS_COMMAND}"] = ''
        substitutions["{PRE_POWER_COMMAND}"] = self.job.device.pre_power_command
        if substitutions["{PRE_POWER_COMMAND}"] is None:
            substitutions["{PRE_POWER_COMMAND}"] = ''
        substitutions["{POWER_ON_COMMAND}"] = self.job.device.power_command
        substitutions["{POWER_OFF_COMMAND}"] = self.job.device.get('commands', {}).get('power_off', '')

        # Add some device configuration
        substitutions["{DEVICE_INFO}"] = yaml.dump(self.job.device.get("device_info", []))
        substitutions["{STATIC_INFO}"] = yaml.dump(self.job.device.get("static_info", []))

        # Run the commands
        for cmd in self.commands:
            cmds = substitute(cmd.split(" "), substitutions)
            if not self.run_command(cmds, allow_fail=False, allow_silent=True, cwd=self.path):
                raise JobError("Unable to flash the device")

        return connection
示例#18
0
 def run(self, connection, max_end_time):
     if "deployment_data" not in self.parameters:
         return connection
     if self.parameters["deployment_data"].get("installer_extra_cmd"):
         if self.parameters.get("os") == "debian_installer":
             add_late_command(
                 self.get_namespace_data(action="download-action",
                                         label="preseed",
                                         key="file"),
                 self.parameters["deployment_data"]["installer_extra_cmd"],
             )
         if self.parameters.get("os") == "centos_installer":
             ip_addr = dispatcher_ip(self.job.parameters["dispatcher"])
             overlay = self.get_namespace_data(action="download-action",
                                               label="file",
                                               key="overlay")
             substitutions = {
                 "{OVERLAY_URL}": "tftp://" + ip_addr + "/" + overlay
             }
             post_command = substitute(
                 [
                     self.parameters["deployment_data"]
                     ["installer_extra_cmd"]
                 ],
                 substitutions,
             )
             add_to_kickstart(
                 self.get_namespace_data(action="download-action",
                                         label="preseed",
                                         key="file"),
                 post_command[0],
             )
     return connection
示例#19
0
    def run(self, connection, max_end_time, args=None):
        """
        CommandRunner expects a pexpect.spawn connection which is the return value
        of target.device.power_on executed by boot in the old dispatcher.

        In the new pipeline, the pexpect.spawn is a ShellCommand and the
        connection is a ShellSession. CommandRunner inside the ShellSession
        turns the ShellCommand into a runner which the ShellSession uses via ShellSession.run()
        to run commands issued *after* the device has booted.
        pexpect.spawn is one of the raw_connection objects for a Connection class.
        """
        # initialise the first Connection object, a command line shell into the running QEMU.
        guest = self.get_namespace_data(action='apply-overlay-guest', label='guest', key='filename')
        # check for NFS
        if 'qemu-nfs' in self.methods and self.parameters.get('media', None) == 'nfs':
            self.logger.debug("Adding NFS arguments to kernel command line.")
            root_dir = self.get_namespace_data(action='extract-rootfs', label='file', key='nfsroot')
            self.substitutions["{NFSROOTFS}"] = root_dir
            params = self.methods['qemu-nfs']['parameters']['append']
            # console=ttyAMA0 root=/dev/nfs nfsroot=10.3.2.1:/var/lib/lava/dispatcher/tmp/dirname,tcp,hard,intr ip=dhcp
            append = [
                'console=%s' % params['console'],
                'root=/dev/nfs',
                '%s rw' % substitute([params['nfsrootargs']], self.substitutions)[0],
                "%s" % params['ipargs']
            ]
            self.sub_command.append('--append')
            self.sub_command.append('"%s"' % ' '.join(append))
        elif guest:
            self.logger.info("Extending command line for qcow2 test overlay")
            # interface is ide by default in qemu
            interface = self.job.device['actions']['deploy']['methods']['image']['parameters']['guest'].get('interface', 'ide')
            self.sub_command.append('-drive format=qcow2,file=%s,media=disk,if=%s' %
                                    (os.path.realpath(guest), interface))
            # push the mount operation to the test shell pre-command to be run
            # before the test shell tries to execute.
            shell_precommand_list = []
            mountpoint = self.get_namespace_data(action='test', label='results', key='lava_test_results_dir')
            uuid = '/dev/disk/by-uuid/%s' % self.get_namespace_data(action='apply-overlay-guest', label='guest', key='UUID')
            shell_precommand_list.append('mkdir %s' % mountpoint)
            # prepare_guestfs always uses ext2
            shell_precommand_list.append('mount %s -t ext2 %s' % (uuid, mountpoint))
            # debug line to show the effect of the mount operation
            # also allows time for kernel messages from the mount operation to be processed.
            shell_precommand_list.append('ls -la %s/bin/lava-test-runner' % mountpoint)
            self.set_namespace_data(action='test', label='lava-test-shell', key='pre-command-list', value=shell_precommand_list)

        self.logger.info("Boot command: %s", ' '.join(self.sub_command))
        shell = ShellCommand(' '.join(self.sub_command), self.timeout, logger=self.logger)
        if shell.exitstatus:
            raise JobError("%s command exited %d: %s" % (self.sub_command, shell.exitstatus, shell.readlines()))
        self.logger.debug("started a shell command")

        shell_connection = ShellSession(self.job, shell)
        shell_connection = super(CallQemuAction, self).run(shell_connection, max_end_time, args)

        self.set_namespace_data(action='shared', label='shared', key='connection', value=shell_connection)
        return shell_connection
示例#20
0
    def test_overlay_action(self):  # pylint: disable=too-many-locals
        parameters = {
            'device_type': 'd02',
            'job_name': 'grub-standard-ramdisk',
            'job_timeout': '15m',
            'action_timeout': '5m',
            'priority': 'medium',
            'actions': {
                'boot': {
                    'method': 'grub',
                    'commands': 'ramdisk',
                    'prompts': ['linaro-test', 'root@debian:~#']
                },
                'deploy': {
                    'ramdisk': 'initrd.gz',
                    'kernel': 'zImage',
                    'dtb': 'broken.dtb'
                }
            }
        }
        (rendered, _) = self.factory.create_device('d02-01.jinja2')
        device = NewDevice(yaml.load(rendered))
        job = Job(4212, parameters, None)
        job.device = device
        pipeline = Pipeline(job=job, parameters=parameters['actions']['boot'])
        job.pipeline = pipeline
        overlay = BootloaderCommandOverlay()
        pipeline.add_action(overlay)
        ip_addr = dispatcher_ip(None)
        parsed = []
        kernel = parameters['actions']['deploy']['kernel']
        ramdisk = parameters['actions']['deploy']['ramdisk']
        dtb = parameters['actions']['deploy']['dtb']

        substitution_dictionary = {
            '{SERVER_IP}': ip_addr,
            # the addresses need to be hexadecimal
            '{RAMDISK}': ramdisk,
            '{KERNEL}': kernel,
            '{DTB}': dtb
        }
        params = device['actions']['boot']['methods']
        commands = params['grub']['ramdisk']['commands']
        self.assertIn('net_bootp', commands)
        self.assertIn("linux (tftp,{SERVER_IP})/{KERNEL} console=ttyS0,115200 earlycon=uart8250,mmio32,0x80300000 root=/dev/ram0 ip=dhcp", commands)
        self.assertIn('initrd (tftp,{SERVER_IP})/{RAMDISK}', commands)
        self.assertIn('devicetree (tftp,{SERVER_IP})/{DTB}', commands)

        params['grub']['ramdisk']['commands'] = substitute(params['grub']['ramdisk']['commands'], substitution_dictionary)
        substituted_commands = params['grub']['ramdisk']['commands']
        self.assertIs(type(substituted_commands), list)
        self.assertIn('net_bootp', substituted_commands)
        self.assertNotIn("linux (tftp,{SERVER_IP})/{KERNEL} console=ttyS0,115200 earlycon=uart8250,mmio32,0x80300000 root=/dev/ram0 ip=dhcp", substituted_commands)
        self.assertIn("linux (tftp,%s)/%s console=ttyS0,115200 earlycon=uart8250,mmio32,0x80300000 root=/dev/ram0 ip=dhcp" % (ip_addr, kernel), substituted_commands)
        self.assertNotIn('initrd (tftp,{SERVER_IP})/{RAMDISK}', parsed)
        self.assertNotIn('devicetree (tftp,{SERVER_IP})/{DTB}', parsed)
示例#21
0
 def test_substitutions(self):
     sub_command = [
         '/usr/bin/qemu-system-x86_64', '-nographic', '-enable-kvm',
         '-cpu host', '-net nic,model=virtio,macaddr=52:54:00:12:34:58 -net user',
         '-m 2048', ' -drive format=raw,file={emptyimage} ', '-boot c']
     substitutions = {'{emptyimage}': '/tmp/tmp.00000/hd.img'}  # nosec unit test support.
     sub_command = substitute(sub_command, substitutions)
     self.assertNotIn('{emptyimage}', sub_command)
     self.assertNotIn('/tmp/tmp.00000/hd.img', sub_command)  # nosec unit test support.
     self.assertIn('/tmp/tmp.00000/hd.img', ' '.join(sub_command))  # nosec unit test support.
示例#22
0
    def test_overlay_action(self):  # pylint: disable=too-many-locals
        parameters = {
            'device_type': 'd02',
            'job_name': 'grub-standard-ramdisk',
            'job_timeout': '15m',
            'action_timeout': '5m',
            'priority': 'medium',
            'actions': {
                'boot': {
                    'method': 'grub',
                    'commands': 'ramdisk',
                    'prompts': ['linaro-test', 'root@debian:~#']
                },
                'deploy': {
                    'ramdisk': 'initrd.gz',
                    'kernel': 'zImage',
                    'dtb': 'broken.dtb'
                }
            }
        }
        device = NewDevice(os.path.join(os.path.dirname(__file__), '../devices/d02-01.yaml'))
        job = Job(4212, parameters, None)
        job.device = device
        pipeline = Pipeline(job=job, parameters=parameters['actions']['boot'])
        job.pipeline = pipeline
        overlay = BootloaderCommandOverlay()
        pipeline.add_action(overlay)
        ip_addr = dispatcher_ip(None)
        parsed = []
        kernel = parameters['actions']['deploy']['kernel']
        ramdisk = parameters['actions']['deploy']['ramdisk']
        dtb = parameters['actions']['deploy']['dtb']

        substitution_dictionary = {
            '{SERVER_IP}': ip_addr,
            # the addresses need to be hexadecimal
            '{RAMDISK}': ramdisk,
            '{KERNEL}': kernel,
            '{DTB}': dtb
        }
        params = device['actions']['boot']['methods']
        commands = params['grub']['ramdisk']['commands']
        self.assertIn('net_bootp', commands)
        self.assertIn("linux (tftp,{SERVER_IP})/{KERNEL} console=ttyS0,115200 earlycon=uart8250,mmio32,0x80300000 root=/dev/ram0 ip=dhcp", commands)
        self.assertIn('initrd (tftp,{SERVER_IP})/{RAMDISK}', commands)
        self.assertIn('devicetree (tftp,{SERVER_IP})/{DTB}', commands)

        params['grub']['ramdisk']['commands'] = substitute(params['grub']['ramdisk']['commands'], substitution_dictionary)
        substituted_commands = params['grub']['ramdisk']['commands']
        self.assertIs(type(substituted_commands), list)
        self.assertIn('net_bootp', substituted_commands)
        self.assertNotIn("linux (tftp,{SERVER_IP})/{KERNEL} console=ttyS0,115200 earlycon=uart8250,mmio32,0x80300000 root=/dev/ram0 ip=dhcp", substituted_commands)
        self.assertIn("linux (tftp,%s)/%s console=ttyS0,115200 earlycon=uart8250,mmio32,0x80300000 root=/dev/ram0 ip=dhcp" % (ip_addr, kernel), substituted_commands)
        self.assertNotIn('initrd (tftp,{SERVER_IP})/{RAMDISK}', parsed)
        self.assertNotIn('devicetree (tftp,{SERVER_IP})/{DTB}', parsed)
示例#23
0
    def test_overlay_action(self):  # pylint: disable=too-many-locals
        parameters = {
            "device_type": "x86",
            "job_name": "ipxe-pipeline",
            "job_timeout": "15m",
            "action_timeout": "5m",
            "priority": "medium",
            "actions": {
                "boot": {
                    "method": "ipxe",
                    "commands": "ramdisk",
                    "prompts": ["linaro-test", "root@debian:~#"],
                },
                "deploy": {
                    "ramdisk": "initrd.gz",
                    "kernel": "zImage"
                },
            },
        }
        (rendered, _) = self.factory.create_device("x86-01.jinja2")
        device = NewDevice(yaml.safe_load(rendered))
        job = Job(4212, parameters, None)
        job.device = device
        pipeline = Pipeline(job=job, parameters=parameters["actions"]["boot"])
        job.pipeline = pipeline
        overlay = BootloaderCommandOverlay()
        pipeline.add_action(overlay)
        ip_addr = dispatcher_ip(None)
        kernel = parameters["actions"]["deploy"]["kernel"]
        ramdisk = parameters["actions"]["deploy"]["ramdisk"]

        substitution_dictionary = {
            "{SERVER_IP}": ip_addr,
            "{RAMDISK}": ramdisk,
            "{KERNEL}": kernel,
            "{LAVA_MAC}": "00:00:00:00:00:00",
        }
        params = device["actions"]["boot"]["methods"]
        params["ipxe"]["ramdisk"]["commands"] = substitute(
            params["ipxe"]["ramdisk"]["commands"], substitution_dictionary)

        commands = params["ipxe"]["ramdisk"]["commands"]
        self.assertIs(type(commands), list)
        self.assertIn("dhcp net0", commands)
        self.assertIn(
            "set console console=ttyS0,115200n8 lava_mac=00:00:00:00:00:00",
            commands)
        self.assertIn("set extraargs  ip=dhcp", commands)
        self.assertNotIn(
            "kernel tftp://{SERVER_IP}/{KERNEL} ${extraargs} ${console}",
            commands)
        self.assertNotIn("initrd tftp://{SERVER_IP}/{RAMDISK}", commands)
        self.assertIn("boot", commands)
示例#24
0
    def test_overlay_action(self):  # pylint: disable=too-many-locals
        parameters = {
            'device_type': 'x86',
            'job_name': 'ipxe-pipeline',
            'job_timeout': '15m',
            'action_timeout': '5m',
            'priority': 'medium',
            'actions': {
                'boot': {
                    'method': 'ipxe',
                    'commands': 'ramdisk',
                    'prompts': ['linaro-test', 'root@debian:~#']
                },
                'deploy': {
                    'ramdisk': 'initrd.gz',
                    'kernel': 'zImage',
                }
            }
        }
        (rendered, _) = self.factory.create_device('x86-01.jinja2')
        device = NewDevice(yaml.safe_load(rendered))
        job = Job(4212, parameters, None)
        job.device = device
        pipeline = Pipeline(job=job, parameters=parameters['actions']['boot'])
        job.pipeline = pipeline
        overlay = BootloaderCommandOverlay()
        pipeline.add_action(overlay)
        ip_addr = dispatcher_ip(None)
        kernel = parameters['actions']['deploy']['kernel']
        ramdisk = parameters['actions']['deploy']['ramdisk']

        substitution_dictionary = {
            '{SERVER_IP}': ip_addr,
            '{RAMDISK}': ramdisk,
            '{KERNEL}': kernel,
            '{LAVA_MAC}': "00:00:00:00:00:00"
        }
        params = device['actions']['boot']['methods']
        params['ipxe']['ramdisk']['commands'] = substitute(
            params['ipxe']['ramdisk']['commands'], substitution_dictionary)

        commands = params['ipxe']['ramdisk']['commands']
        self.assertIs(type(commands), list)
        self.assertIn("dhcp net0", commands)
        self.assertIn(
            "set console console=ttyS0,115200n8 lava_mac=00:00:00:00:00:00",
            commands)
        self.assertIn("set extraargs  ip=dhcp", commands)
        self.assertNotIn(
            "kernel tftp://{SERVER_IP}/{KERNEL} ${extraargs} ${console}",
            commands)
        self.assertNotIn("initrd tftp://{SERVER_IP}/{RAMDISK}", commands)
        self.assertIn("boot", commands)
示例#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 = {}
        # '--uid' should be used with 'pyocd flash' for connecting to
        # a specific board. 'pyocd flash --board' doesn't work for
        # selecting board, and the option has been removed since
        # version v0.32.0.
        # '--board' should be used for 'pyocd-flashtool' as '--uid'
        # isn't available for 'pyocd-flashtool'.
        # Different boards require (or work better) with a particular
        # version of pyocd. Due to this, we need to maintain support
        # for both 'pyocd flash' and 'pyocd-flashtool' for the foreseeable
        # future.
        connecting_option = "--uid"
        if pyocd_binary.startswith("pyocd-flashtool"):
            connecting_option = "--board"
        self.base_command.extend([connecting_option, 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"

        pre_os_command = self.job.device.pre_os_command
        if pre_os_command:
            self.exec_list.append(pre_os_command.split(" "))
示例#26
0
    def test_overlay_action(self):  # pylint: disable=too-many-locals
        parameters = {
            'device_type': 'x86',
            'job_name': 'ipxe-pipeline',
            'job_timeout': '15m',
            'action_timeout': '5m',
            'priority': 'medium',
            'actions': {
                'boot': {
                    'method': 'ipxe',
                    'commands': 'ramdisk',
                    'prompts': ['linaro-test', 'root@debian:~#']
                },
                'deploy': {
                    'ramdisk': 'initrd.gz',
                    'kernel': 'zImage',
                }
            }
        }
        device = NewDevice(os.path.join(os.path.dirname(__file__), '../devices/x86-01.yaml'))
        job = Job(4212, parameters, None)
        job.device = device
        pipeline = Pipeline(job=job, parameters=parameters['actions']['boot'])
        job.pipeline = pipeline
        overlay = BootloaderCommandOverlay()
        pipeline.add_action(overlay)
        ip_addr = dispatcher_ip(None)
        kernel = parameters['actions']['deploy']['kernel']
        ramdisk = parameters['actions']['deploy']['ramdisk']

        substitution_dictionary = {
            '{SERVER_IP}': ip_addr,
            '{RAMDISK}': ramdisk,
            '{KERNEL}': kernel,
            '{LAVA_MAC}': "00:00:00:00:00:00"
        }
        params = device['actions']['boot']['methods']
        params['ipxe']['ramdisk']['commands'] = substitute(params['ipxe']['ramdisk']['commands'], substitution_dictionary)

        commands = params['ipxe']['ramdisk']['commands']
        self.assertIs(type(commands), list)
        self.assertIn("dhcp net0", commands)
        self.assertIn("set console console=ttyS0,115200n8 lava_mac=00:00:00:00:00:00", commands)
        self.assertIn("set extraargs init=/sbin/init ip=dhcp", commands)
        self.assertNotIn("kernel tftp://{SERVER_IP}/{KERNEL} ${extraargs} ${console}", commands)
        self.assertNotIn("initrd tftp://{SERVER_IP}/{RAMDISK}", commands)
        self.assertIn("boot", commands)
示例#27
0
 def run(self, connection, max_end_time, args=None):
     if 'deployment_data' not in self.parameters:
         return connection
     if self.parameters["deployment_data"].get('installer_extra_cmd', None):
         if self.parameters.get('os', None) == "debian_installer":
             add_late_command(self.get_namespace_data(action='download-action', label='preseed', key='file'),
                              self.parameters["deployment_data"]["installer_extra_cmd"])
         if self.parameters.get('os', None) == "centos_installer":
             ip_addr = dispatcher_ip(self.job.parameters['dispatcher'])
             overlay = self.get_namespace_data(
                 action='download-action', label='file', key='overlay')
             substitutions = {
                 '{OVERLAY_URL}': 'tftp://' + ip_addr + '/' + overlay
             }
             post_command = substitute([self.parameters["deployment_data"]["installer_extra_cmd"]], substitutions)
             add_to_kickstart(self.get_namespace_data(action='download-action', label='preseed', key='file'), post_command[0])
     return connection
示例#28
0
 def validate(self):
     super().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 = "[FLASH_DFU] board_id unset"
         if self.job.device['usb_vendor_id'] == '0000':
             self.errors = '[FLASH_DFU] usb_vendor_id unset'
         if self.job.device['usb_product_id'] == '0000':
             self.errors = '[FLASH_DFU] 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 = {}
     for action in self.get_namespace_keys('download-action'):
         dfu_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 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"
示例#29
0
 def validate(self):
     super().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 = "[FLASH_DFU] board_id unset"
         if self.job.device["usb_vendor_id"] == "0000":
             self.errors = "[FLASH_DFU] usb_vendor_id unset"
         if self.job.device["usb_product_id"] == "0000":
             self.errors = "[FLASH_DFU] 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 = {}
     for action in self.get_namespace_keys("download-action"):
         dfu_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 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 not self.exec_list:
         self.errors = "No DFU command to execute"
示例#30
0
    def run(self, connection, max_end_time, args=None):
        connection = super(FlasherAction, self).run(connection, max_end_time,
                                                    args)
        # Substitute in the device commands
        substitutions = {}
        for key in [
                key for key in self.parameters['images'].keys()
                if key != "yaml_line"
        ]:
            filename = self.get_namespace_data(action='download-action',
                                               label=key,
                                               key='file')
            filename = filename[len(self.path) + 1:]
            substitutions["{%s}" % key.upper()] = filename

        # Add power commands
        substitutions[
            "{HARD_RESET_COMMAND}"] = self.job.device.hard_reset_command
        substitutions[
            "{SOFT_RESET_COMMAND}"] = self.job.device.soft_reset_command
        substitutions["{PRE_OS_COMMAND}"] = self.job.device.pre_os_command
        if substitutions["{PRE_OS_COMMAND}"] is None:
            substitutions["{PRE_OS_COMMAND}"] = ''
        substitutions[
            "{PRE_POWER_COMMAND}"] = self.job.device.pre_power_command
        if substitutions["{PRE_POWER_COMMAND}"] is None:
            substitutions["{PRE_POWER_COMMAND}"] = ''
        substitutions["{POWER_ON_COMMAND}"] = self.job.device.power_command
        substitutions["{POWER_OFF_COMMAND}"] = self.job.device.get(
            'commands', {}).get('power_off', '')

        # Add some device configuration
        substitutions["{DEVICE_INFO}"] = yaml.dump(
            self.job.device.get("device_info", []))
        substitutions["{STATIC_INFO}"] = yaml.dump(
            self.job.device.get("static_info", []))

        # Run the commands
        for cmd in self.commands:
            cmds = substitute(cmd.split(" "), substitutions)
            if not self.run_command(
                    cmds, allow_fail=False, allow_silent=True, cwd=self.path):
                raise JobError("Unable to flash the device")

        return connection
示例#31
0
def test_substitute():
    assert substitute(["hello", "world"], {}) == ["hello", "world"]
    assert substitute(["hello", "world"],
                      {"hello": "strange"}) == ["strange", "world"]
    assert substitute(["hello", "world"],
                      {"nice": "strange"}) == ["hello", "world"]
    assert substitute(["hello", "world"], {"nice": "strange"}, drop=True) == [
        "hello",
        "world",
    ]
    assert substitute(["hello", "world"],
                      {"hello": None}) == ["hello", "world"]
    assert substitute(["hello", "world"], {"hello": None},
                      drop=True) == ["world"]
    assert substitute(["hello", "world"], {"hello": None},
                      drop=True,
                      drop_line=False) == ["world"]
示例#32
0
文件: flasher.py 项目: mytxyang/lava
    def run(self, connection, max_end_time):
        connection = super().run(connection, max_end_time)
        # Substitute in the device commands
        substitutions = {}
        for key in self.parameters["images"].keys():
            filename = self.get_namespace_data(action="download-action",
                                               label=key,
                                               key="file")
            filename = filename[len(self.path) + 1:]
            substitutions["{%s}" % key.upper()] = filename

        # Add power commands
        substitutions["{HARD_RESET_COMMAND}"] = str(
            self.job.device.hard_reset_command)
        substitutions["{SOFT_RESET_COMMAND}"] = str(
            self.job.device.soft_reset_command)
        substitutions["{PRE_OS_COMMAND}"] = str(self.job.device.pre_os_command)
        if self.job.device.pre_os_command is None:
            substitutions["{PRE_OS_COMMAND}"] = ""
        substitutions["{PRE_POWER_COMMAND}"] = str(
            self.job.device.pre_power_command)
        if self.job.device.pre_power_command is None:
            substitutions["{PRE_POWER_COMMAND}"] = ""
        substitutions["{POWER_ON_COMMAND}"] = str(
            self.job.device.power_command)
        substitutions["{POWER_OFF_COMMAND}"] = str(
            self.job.device.get("commands", {}).get("power_off", ""))

        # Add some device configuration
        substitutions["{DEVICE_INFO}"] = yaml_safe_dump(
            self.job.device.get("device_info", []))
        substitutions["{STATIC_INFO}"] = yaml_safe_dump(
            self.job.device.get("static_info", []))

        # Run the commands
        for cmd in self.commands:
            cmds = substitute([cmd], substitutions)
            self.run_cmd(cmds[0],
                         error_msg="Unable to flash the device",
                         cwd=self.path)

        return connection
示例#33
0
    def test_qemu_nfs(self):
        self.assertIsNotNone(self.job)
        description_ref = self.pipeline_reference('qemu-nfs.yaml')
        self.assertEqual(description_ref, self.job.pipeline.describe(False))

        boot = [action for action in self.job.pipeline.actions if action.name == 'boot-image-retry'][0]
        qemu = [action for action in boot.internal_pipeline.actions if action.name == 'boot-qemu-image'][0]
        execute = [action for action in qemu.internal_pipeline.actions if action.name == 'execute-qemu'][0]
        self.job.validate()
        self.assertNotEqual([], [line for line in execute.sub_command if line.startswith('-kernel')])
        self.assertEqual(1, len([line for line in execute.sub_command if line.startswith('-kernel')]))
        self.assertIn('vmlinuz', [line for line in execute.sub_command if line.startswith('-kernel')][0])

        self.assertNotEqual([], [line for line in execute.sub_command if line.startswith('-initrd')])
        self.assertEqual(1, len([line for line in execute.sub_command if line.startswith('-initrd')]))
        self.assertIn('initrd.img', [line for line in execute.sub_command if line.startswith('-initrd')][0])

        self.assertEqual([], [line for line in execute.sub_command if '/dev/nfs' in line])
        self.assertEqual([], [line for line in execute.sub_command if 'nfsroot' in line])

        args = execute.methods['qemu-nfs']['parameters']['append']['nfsrootargs']
        self.assertIn('{NFS_SERVER_IP}', args)
        self.assertIn('{NFSROOTFS}', args)

        substitutions = execute.substitutions
        substitutions["{NFSROOTFS}"] = 'root_dir'
        params = execute.methods['qemu-nfs']['parameters']['append']
        # console=ttyAMA0 root=/dev/nfs nfsroot=10.3.2.1:/var/lib/lava/dispatcher/tmp/dirname,tcp,hard,intr ip=dhcp
        append = [
            'console=%s' % params['console'],
            'root=/dev/nfs',
            '%s' % substitute([params['nfsrootargs']], substitutions)[0],
            "%s" % params['ipargs']
        ]
        execute.sub_command.append('--append')
        execute.sub_command.append('"%s"' % ' '.join(append))
        kernel_cmdline = ' '.join(execute.sub_command)
        self.assertIn('console=ttyAMA0', kernel_cmdline)
        self.assertIn('/dev/nfs', kernel_cmdline)
        self.assertIn('root_dir,tcp,hard,intr', kernel_cmdline)
        self.assertIn('smp', kernel_cmdline)
        self.assertIn('cpu host', kernel_cmdline)
示例#34
0
    def test_qemu_nfs(self):
        self.assertIsNotNone(self.job)
        description_ref = self.pipeline_reference('qemu-nfs.yaml')
        self.assertEqual(description_ref, self.job.pipeline.describe(False))

        boot = [action for action in self.job.pipeline.actions if action.name == 'boot-image-retry'][0]
        qemu = [action for action in boot.internal_pipeline.actions if action.name == 'boot-qemu-image'][0]
        execute = [action for action in qemu.internal_pipeline.actions if action.name == 'execute-qemu'][0]
        self.job.validate()
        self.assertNotEqual([], [line for line in execute.sub_command if line.startswith('-kernel')])
        self.assertEqual(1, len([line for line in execute.sub_command if line.startswith('-kernel')]))
        self.assertIn('vmlinuz', [line for line in execute.sub_command if line.startswith('-kernel')][0])

        self.assertNotEqual([], [line for line in execute.sub_command if line.startswith('-initrd')])
        self.assertEqual(1, len([line for line in execute.sub_command if line.startswith('-initrd')]))
        self.assertIn('initrd.img', [line for line in execute.sub_command if line.startswith('-initrd')][0])

        self.assertEqual([], [line for line in execute.sub_command if '/dev/nfs' in line])
        self.assertEqual([], [line for line in execute.sub_command if 'nfsroot' in line])

        args = execute.methods['qemu-nfs']['parameters']['append']['nfsrootargs']
        self.assertIn('{NFS_SERVER_IP}', args)
        self.assertIn('{NFSROOTFS}', args)

        substitutions = execute.substitutions
        substitutions["{NFSROOTFS}"] = 'root_dir'
        params = execute.methods['qemu-nfs']['parameters']['append']
        # console=ttyAMA0 root=/dev/nfs nfsroot=10.3.2.1:/var/lib/lava/dispatcher/tmp/dirname,tcp,hard,intr ip=dhcp
        append = [
            'console=%s' % params['console'],
            'root=/dev/nfs',
            '%s' % substitute([params['nfsrootargs']], substitutions)[0],
            "%s" % params['ipargs']
        ]
        execute.sub_command.append('--append')
        execute.sub_command.append('"%s"' % ' '.join(append))
        kernel_cmdline = ' '.join(execute.sub_command)
        self.assertIn('console=ttyAMA0', kernel_cmdline)
        self.assertIn('/dev/nfs', kernel_cmdline)
        self.assertIn('root_dir,tcp,hard,intr', kernel_cmdline)
        self.assertIn('smp', kernel_cmdline)
        self.assertIn('cortex-a57', kernel_cmdline)
示例#35
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"
示例#36
0
 def test_substitutions(self):
     sub_command = [
         "/usr/bin/qemu-system-x86_64",
         "-nographic",
         "-enable-kvm",
         "-cpu host",
         "-net nic,model=virtio,macaddr=52:54:00:12:34:58 -net user",
         "-m 2048",
         " -drive format=raw,file={emptyimage} ",
         "-boot c",
     ]
     substitutions = {
         "{emptyimage}": "/tmp/tmp.00000/hd.img"  # nosec unit test support.
     }
     sub_command = substitute(sub_command, substitutions)
     self.assertNotIn("{emptyimage}", sub_command)
     self.assertNotIn(
         "/tmp/tmp.00000/hd.img", sub_command  # nosec unit test support.
     )
     self.assertIn(
         "/tmp/tmp.00000/hd.img", " ".join(sub_command)  # nosec unit test support.
     )
示例#37
0
    def test_overlay_action(self):  # pylint: disable=too-many-locals
        parameters = {
            "device_type": "beaglebone-black",
            "job_name": "uboot-pipeline",
            "job_timeout": "15m",
            "action_timeout": "5m",
            "priority": "medium",
            "actions": {
                "boot": {
                    "method": "u-boot",
                    "commands": "ramdisk",
                    "type": "bootz",
                    "prompts": ["linaro-test", "root@debian:~#"],
                },
                "deploy": {
                    "ramdisk": "initrd.gz",
                    "kernel": "zImage",
                    "dtb": "broken.dtb",
                },
            },
        }
        device = NewDevice(
            os.path.join(os.path.dirname(__file__), "devices/bbb-01.yaml"))
        job = Job(4212, parameters, None)
        job.device = device
        pipeline = Pipeline(job=job, parameters=parameters["actions"]["boot"])
        job.pipeline = pipeline
        overlay = BootloaderCommandOverlay()
        pipeline.add_action(overlay)
        ip_addr = dispatcher_ip(None)
        parsed = []
        kernel_addr = job.device["parameters"][
            overlay.parameters["type"]]["ramdisk"]
        ramdisk_addr = job.device["parameters"][
            overlay.parameters["type"]]["ramdisk"]
        dtb_addr = job.device["parameters"][overlay.parameters["type"]]["dtb"]
        kernel = parameters["actions"]["deploy"]["kernel"]
        ramdisk = parameters["actions"]["deploy"]["ramdisk"]
        dtb = parameters["actions"]["deploy"]["dtb"]

        substitution_dictionary = {
            "{SERVER_IP}":
            ip_addr,
            # the addresses need to be hexadecimal
            "{KERNEL_ADDR}":
            kernel_addr,
            "{DTB_ADDR}":
            dtb_addr,
            "{RAMDISK_ADDR}":
            ramdisk_addr,
            "{BOOTX}":
            "%s %s %s %s" %
            (overlay.parameters["type"], kernel_addr, ramdisk_addr, dtb_addr),
            "{RAMDISK}":
            ramdisk,
            "{KERNEL}":
            kernel,
            "{DTB}":
            dtb,
        }
        params = device["actions"]["boot"]["methods"]
        params["u-boot"]["ramdisk"]["commands"] = substitute(
            params["u-boot"]["ramdisk"]["commands"], substitution_dictionary)

        commands = params["u-boot"]["ramdisk"]["commands"]
        self.assertIs(type(commands), list)
        self.assertIn("setenv loadkernel 'tftp ${kernel_addr_r} zImage'",
                      commands)
        self.assertIn(
            "setenv loadinitrd 'tftp ${initrd_addr_r} initrd.gz; setenv initrd_size ${filesize}'",
            commands,
        )
        self.assertIn("setenv loadfdt 'tftp ${fdt_addr_r} broken.dtb'",
                      commands)
        self.assertNotIn("setenv kernel_addr_r '{KERNEL_ADDR}'", commands)
        self.assertNotIn("setenv initrd_addr_r '{RAMDISK_ADDR}'", commands)
        self.assertNotIn("setenv fdt_addr_r '{DTB_ADDR}'", commands)

        for line in params["u-boot"]["ramdisk"]["commands"]:
            line = line.replace("{SERVER_IP}", ip_addr)
            # the addresses need to be hexadecimal
            line = line.replace("{KERNEL_ADDR}", kernel_addr)
            line = line.replace("{DTB_ADDR}", dtb_addr)
            line = line.replace("{RAMDISK_ADDR}", ramdisk_addr)
            line = line.replace(
                "{BOOTX}",
                "%s %s %s %s" % (overlay.parameters["type"], kernel_addr,
                                 ramdisk_addr, dtb_addr),
            )
            line = line.replace("{RAMDISK}", ramdisk)
            line = line.replace("{KERNEL}", kernel)
            line = line.replace("{DTB}", dtb)
            parsed.append(line)
        self.assertIn("setenv loadkernel 'tftp ${kernel_addr_r} zImage'",
                      parsed)
        self.assertIn(
            "setenv loadinitrd 'tftp ${initrd_addr_r} initrd.gz; setenv initrd_size ${filesize}'",
            parsed,
        )
        self.assertIn("setenv loadfdt 'tftp ${fdt_addr_r} broken.dtb'", parsed)
        self.assertNotIn("setenv kernel_addr_r '{KERNEL_ADDR}'", parsed)
        self.assertNotIn("setenv initrd_addr_r '{RAMDISK_ADDR}'", parsed)
        self.assertNotIn("setenv fdt_addr_r '{DTB_ADDR}'", parsed)
示例#38
0
    def test_substitutions(self):
        """
        Test substitution of secondary media values into u-boot commands

        Unlike most u-boot calls, removable knows in advance all the values it needs to substitute
        into the boot commands for the secondary deployment as these are fixed by the device config
        and the image details from the job submission.
        """
        job_parser = JobParser()
        cubie = NewDevice(os.path.join(os.path.dirname(__file__), '../devices/cubie1.yaml'))
        sample_job_file = os.path.join(os.path.dirname(__file__), 'sample_jobs/cubietruck-removable.yaml')
        with open(sample_job_file) as sample_job_data:
            job = job_parser.parse(sample_job_data, cubie, 4212, None, "")
        job.logger = DummyLogger()
        job.validate()
        boot_params = [
            methods for methods in job.parameters['actions'] if 'boot' in methods.keys()][1]['boot']
        self.assertIn('ramdisk', boot_params)
        self.assertIn('kernel', boot_params)
        self.assertIn('dtb', boot_params)
        self.assertIn('root_uuid', boot_params)
        self.assertIn('boot_part', boot_params)
        self.assertNotIn('type', boot_params)
        self.assertGreater(len(job.pipeline.actions), 1)
        self.assertIsNotNone(job.pipeline.actions[1].internal_pipeline)
        u_boot_action = [action for action in job.pipeline.actions if action.name == 'uboot-action'][1]
        overlay = [action for action in u_boot_action.internal_pipeline.actions if action.name == 'bootloader-overlay'][0]
        self.assertIsNotNone(overlay.get_namespace_data(action='storage-deploy', label='u-boot', key='device'))

        methods = cubie['actions']['boot']['methods']
        self.assertIn('u-boot', methods)
        self.assertIn('usb', methods['u-boot'])
        self.assertIn('commands', methods['u-boot']['usb'])
        commands_list = methods['u-boot']['usb']['commands']
        device_id = u_boot_action.get_namespace_data(action='storage-deploy', label='u-boot', key='device')
        self.assertIsNotNone(device_id)
        kernel_type = u_boot_action.parameters['kernel_type']
        bootcommand = map_kernel_uboot(kernel_type, device_params=cubie.get('parameters', None))
        substitutions = {
            '{BOOTX}': "%s %s %s %s" % (
                bootcommand,
                cubie['parameters'][bootcommand]['kernel'],
                cubie['parameters'][bootcommand]['ramdisk'],
                cubie['parameters'][bootcommand]['dtb'],),
            '{RAMDISK}': boot_params['ramdisk'],
            '{KERNEL}': boot_params['kernel'],
            '{DTB}': boot_params['dtb'],
            '{ROOT}': boot_params['root_uuid'],
            '{ROOT_PART}': "%s:%s" % (
                cubie['parameters']['media']['usb'][device_id]['device_id'],
                u_boot_action.parameters['boot_part']
            )
        }
        self.assertEqual('bootz 0x42000000 0x43300000 0x43000000', substitutions['{BOOTX}'])
        self.assertEqual('/boot/initrd.img-3.16.0-4-armmp-lpae.u-boot', substitutions['{RAMDISK}'])
        commands = substitute(commands_list, substitutions)
        self.assertEqual(
            commands,
            [
                'usb start',
                'usb info',
                'setenv autoload no',
                "setenv initrd_high '0xffffffff'",
                "setenv fdt_high '0xffffffff'",
                'setenv initrd_addr_r ${ramdisk_addr_r}',
                "setenv loadkernel 'load usb 0:1 ${kernel_addr_r} /boot/vmlinuz-3.16.0-4-armmp-lpae'",
                "setenv loadinitrd 'load usb 0:1 ${initrd_addr_r} /boot/initrd.img-3.16.0-4-armmp-lpae.u-boot; setenv initrd_size ${filesize}'",
                "setenv loadfdt 'load usb 0:1 ${fdt_addr_r} /boot/dtb-3.16.0-4-armmp-lpae'",
                "setenv bootargs 'console=ttyS0,115200n8 root=UUID=159d17cc-697c-4125-95a0-a3775e1deabe ip=dhcp'",
                "setenv bootcmd 'run loadkernel; run loadinitrd; run loadfdt; bootz 0x42000000 0x43300000 0x43000000'", 'boot'
            ]
        )
示例#39
0
 def test_uefi_job(self, which_mock):
     self.assertIsNotNone(self.job)
     self.job.validate()
     uefi_menu = [
         action for action in self.job.pipeline.actions
         if action.name == "uefi-menu-action"
     ][0]
     selector = [
         action for action in uefi_menu.internal_pipeline.actions
         if action.name == "uefi-menu-selector"
     ][0]
     self.assertEqual(selector.selector.prompt, "Start:")
     self.assertIsInstance(selector.items, list)
     description_ref = self.pipeline_reference("mustang-uefi.yaml",
                                               job=self.job)
     self.assertEqual(description_ref, self.job.pipeline.describe(False))
     # just dummy strings
     substitution_dictionary = {
         "{SERVER_IP}": "10.4.0.1",
         "{RAMDISK}": None,
         "{KERNEL}": "uImage",
         "{DTB}": "mustang.dtb",
         "{NFSROOTFS}": "tmp/tmp21dfed/",
         "{TEST_MENU_NAME}": "LAVA NFS Test Image",
     }
     for block in selector.items:
         if "select" in block:
             if "enter" in block["select"]:
                 block["select"]["enter"] = substitute(
                     [block["select"]["enter"]], substitution_dictionary)
             if "items" in block["select"]:
                 block["select"]["items"] = substitute(
                     block["select"]["items"], substitution_dictionary)
     count = 0
     check_block = [
         {
             "items": ["Boot Manager"],
             "wait": "Choice:"
         },
         {
             "items": ["Remove Boot Device Entry"],
             "fallback": "Return to Main Menu",
             "wait": "Delete entry",
         },
         {
             "items": ["LAVA NFS Test Image"],
             "wait": "Choice:"
         },
         {
             "items": ["Add Boot Device Entry"],
             "wait": "Select the Boot Device:"
         },
         {
             "items": ["TFTP on MAC Address: 00:01:73:69:5A:EF"],
             "wait": "Get the IP address from DHCP:",
         },
         {
             "enter": ["y"],
             "wait": "Get the TFTP server IP address:"
         },
         {
             "enter": ["10.4.0.1"],
             "wait": "File path of the EFI Application or the kernel :",
         },
         {
             "enter": ["uImage"],
             "wait": "Is an EFI Application?"
         },
         {
             "enter": ["n"],
             "wait": "Boot Type:"
         },
         {
             "enter": ["f"],
             "wait": "Add an initrd:"
         },
         {
             "enter": ["n"],
             "wait": "Get the IP address from DHCP:"
         },
         {
             "enter": ["y"],
             "wait": "Get the TFTP server IP address:"
         },
         {
             "enter": ["10.4.0.1"],
             "wait": "File path of the FDT :"
         },
         {
             "enter": ["mustang.dtb"],
             "wait": "Arguments to pass to the binary:"
         },
         {
             "enter": [
                 "console=ttyS0,115200 earlyprintk=uart8250-32bit,0x1c020000 debug root=/dev/nfs rw "
                 "nfsroot=10.4.0.1:tmp/tmp21dfed/,tcp,hard,intr ip=dhcp"
             ],
             "wait":
             "Description for this new Entry:",
         },
         {
             "enter": ["LAVA NFS Test Image"],
             "wait": "Choice:"
         },
         {
             "items": ["Return to main menu"],
             "wait": "Start:"
         },
         {
             "items": ["LAVA NFS Test Image"]
         },
     ]
     for item in selector.items:
         self.assertEqual(item["select"], check_block[count])
         count += 1
示例#40
0
    def test_overlay_action(self):  # pylint: disable=too-many-locals
        parameters = {
            'device_type': 'beaglebone-black',
            'job_name': 'uboot-pipeline',
            'job_timeout': '15m',
            'action_timeout': '5m',
            'priority': 'medium',
            'actions': {
                'boot': {
                    'method': 'u-boot',
                    'commands': 'ramdisk',
                    'type': 'bootz',
                    'prompts': ['linaro-test', 'root@debian:~#']
                },
                'deploy': {
                    'ramdisk': 'initrd.gz',
                    'kernel': 'zImage',
                    'dtb': 'broken.dtb'
                }
            }
        }
        device = NewDevice(
            os.path.join(os.path.dirname(__file__), '../devices/bbb-01.yaml'))
        job = Job(4212, parameters, None)
        job.device = device
        pipeline = Pipeline(job=job, parameters=parameters['actions']['boot'])
        job.pipeline = pipeline
        overlay = BootloaderCommandOverlay()
        pipeline.add_action(overlay)
        ip_addr = dispatcher_ip(None)
        parsed = []
        kernel_addr = job.device['parameters'][
            overlay.parameters['type']]['ramdisk']
        ramdisk_addr = job.device['parameters'][
            overlay.parameters['type']]['ramdisk']
        dtb_addr = job.device['parameters'][overlay.parameters['type']]['dtb']
        kernel = parameters['actions']['deploy']['kernel']
        ramdisk = parameters['actions']['deploy']['ramdisk']
        dtb = parameters['actions']['deploy']['dtb']

        substitution_dictionary = {
            '{SERVER_IP}':
            ip_addr,
            # the addresses need to be hexadecimal
            '{KERNEL_ADDR}':
            kernel_addr,
            '{DTB_ADDR}':
            dtb_addr,
            '{RAMDISK_ADDR}':
            ramdisk_addr,
            '{BOOTX}':
            "%s %s %s %s" %
            (overlay.parameters['type'], kernel_addr, ramdisk_addr, dtb_addr),
            '{RAMDISK}':
            ramdisk,
            '{KERNEL}':
            kernel,
            '{DTB}':
            dtb
        }
        params = device['actions']['boot']['methods']
        params['u-boot']['ramdisk']['commands'] = substitute(
            params['u-boot']['ramdisk']['commands'], substitution_dictionary)

        commands = params['u-boot']['ramdisk']['commands']
        self.assertIs(type(commands), list)
        self.assertIn("setenv loadkernel 'tftp ${kernel_addr_r} zImage'",
                      commands)
        self.assertIn(
            "setenv loadinitrd 'tftp ${initrd_addr_r} initrd.gz; setenv initrd_size ${filesize}'",
            commands)
        self.assertIn("setenv loadfdt 'tftp ${fdt_addr_r} broken.dtb'",
                      commands)
        self.assertNotIn("setenv kernel_addr_r '{KERNEL_ADDR}'", commands)
        self.assertNotIn("setenv initrd_addr_r '{RAMDISK_ADDR}'", commands)
        self.assertNotIn("setenv fdt_addr_r '{DTB_ADDR}'", commands)

        for line in params['u-boot']['ramdisk']['commands']:
            line = line.replace('{SERVER_IP}', ip_addr)
            # the addresses need to be hexadecimal
            line = line.replace('{KERNEL_ADDR}', kernel_addr)
            line = line.replace('{DTB_ADDR}', dtb_addr)
            line = line.replace('{RAMDISK_ADDR}', ramdisk_addr)
            line = line.replace(
                '{BOOTX}',
                "%s %s %s %s" % (overlay.parameters['type'], kernel_addr,
                                 ramdisk_addr, dtb_addr))
            line = line.replace('{RAMDISK}', ramdisk)
            line = line.replace('{KERNEL}', kernel)
            line = line.replace('{DTB}', dtb)
            parsed.append(line)
        self.assertIn("setenv loadkernel 'tftp ${kernel_addr_r} zImage'",
                      parsed)
        self.assertIn(
            "setenv loadinitrd 'tftp ${initrd_addr_r} initrd.gz; setenv initrd_size ${filesize}'",
            parsed)
        self.assertIn("setenv loadfdt 'tftp ${fdt_addr_r} broken.dtb'", parsed)
        self.assertNotIn("setenv kernel_addr_r '{KERNEL_ADDR}'", parsed)
        self.assertNotIn("setenv initrd_addr_r '{RAMDISK_ADDR}'", parsed)
        self.assertNotIn("setenv fdt_addr_r '{DTB_ADDR}'", parsed)
示例#41
0
    def run(self, connection, max_end_time, args=None):  # pylint: disable=too-many-locals
        """
        Retrieve the decompressed image from the dispatcher by calling the tool specified
        by the test writer, from within the test image of the first deployment, using the
        device to write directly to the secondary media, without needing to cache on the device.
        """
        connection = super(DDAction, self).run(connection, max_end_time, args)
        d_file = self.get_namespace_data(action='download-action', label='image', key='file')
        if not d_file:
            self.logger.debug("Skipping %s - nothing downloaded")
            return connection
        decompressed_image = os.path.basename(d_file)
        try:
            device_path = os.path.realpath(
                "/dev/disk/by-id/%s" %
                self.boot_params[self.parameters['device']]['uuid'])
        except OSError:
            raise JobError("Unable to find disk by id %s" %
                           self.boot_params[self.parameters['device']]['uuid'])
        storage_suffix = self.get_namespace_data(action='storage-deploy', label='storage', key='suffix')
        if not storage_suffix:
            storage_suffix = ''
        suffix = "%s/%s" % ("tmp", storage_suffix)

        # As the test writer can use any tool we cannot predict where the
        # download URL will be positioned in the download command.
        # Providing the download URL as a substitution option gets round this
        ip_addr = dispatcher_ip(self.job.parameters['dispatcher'])
        download_url = "http://%s/%s/%s" % (
            ip_addr, suffix, decompressed_image
        )
        substitutions = {
            '{DOWNLOAD_URL}': download_url,
            '{DEVICE}': device_path
        }

        download_cmd = None
        download_params = self.parameters.get('download')
        if download_params:
            download_options = substitute([download_params['options']], substitutions)[0]
            download_cmd = ' '.join([download_params['tool'], download_options])

        writer_params = self.parameters.get('writer')
        if writer_params:
            tool_options = substitute([writer_params['options']], substitutions)[0]
            tool_cmd = [writer_params['tool'], tool_options]
        else:
            tool_cmd = ["dd of='{}' bs=4M".format(device_path)]  # busybox dd does not support other flags
        if self.tool_flags:
            tool_cmd.append(self.tool_flags)
        cmd = ' '.join(tool_cmd)

        cmd_line = ' '.join([download_cmd, '|', cmd]) if download_cmd else cmd

        # set prompt to either `download' or `writer' prompt to ensure that the
        # secondary deployment has started
        prompt_string = connection.prompt_str
        prompt_param = download_params or writer_params
        connection.prompt_str = prompt_param['prompt']
        self.logger.debug("Changing prompt to %s", connection.prompt_str)

        connection.sendline(cmd_line)
        self.wait(connection)
        if not self.valid:
            self.logger.error(self.errors)

        # change prompt string to list of dd outputs
        connection.prompt_str = self.tool_prompts
        self.logger.debug("Changing prompt to %s", connection.prompt_str)
        self.wait(connection)

        # set prompt back once secondary deployment is complete
        connection.prompt_str = prompt_string
        self.logger.debug("Changing prompt to %s", connection.prompt_str)
        self.set_namespace_data(action='shared', label='shared', key='connection', value=connection)
        return connection
示例#42
0
    def test_qemu_nfs(self):
        self.assertIsNotNone(self.job)
        description_ref = self.pipeline_reference("qemu-nfs.yaml")
        self.assertEqual(description_ref, self.job.pipeline.describe(False))

        boot = [
            action for action in self.job.pipeline.actions
            if action.name == "boot-image-retry"
        ][0]
        qemu = [
            action for action in boot.internal_pipeline.actions
            if action.name == "boot-qemu-image"
        ][0]
        execute = [
            action for action in qemu.internal_pipeline.actions
            if action.name == "execute-qemu"
        ][0]
        self.job.validate()
        self.assertNotEqual([], [
            line for line in execute.sub_command if line.startswith("-kernel")
        ])
        self.assertEqual(
            1,
            len([
                line for line in execute.sub_command
                if line.startswith("-kernel")
            ]))
        self.assertIn(
            "vmlinuz",
            [
                line for line in execute.sub_command
                if line.startswith("-kernel")
            ][0],
        )

        self.assertNotEqual([], [
            line for line in execute.sub_command if line.startswith("-initrd")
        ])
        self.assertEqual(
            1,
            len([
                line for line in execute.sub_command
                if line.startswith("-initrd")
            ]))
        self.assertIn(
            "initrd.img",
            [
                line for line in execute.sub_command
                if line.startswith("-initrd")
            ][0],
        )

        self.assertEqual(
            [], [line for line in execute.sub_command if "/dev/nfs" in line])
        self.assertEqual(
            [], [line for line in execute.sub_command if "nfsroot" in line])

        args = execute.methods["qemu-nfs"]["parameters"]["append"][
            "nfsrootargs"]
        self.assertIn("{NFS_SERVER_IP}", args)
        self.assertIn("{NFSROOTFS}", args)

        substitutions = execute.substitutions
        substitutions["{NFSROOTFS}"] = "root_dir"
        params = execute.methods["qemu-nfs"]["parameters"]["append"]
        # console=ttyAMA0 root=/dev/nfs nfsroot=10.3.2.1:/var/lib/lava/dispatcher/tmp/dirname,tcp,hard,intr ip=dhcp
        append = [
            "console=%s" % params["console"],
            "root=/dev/nfs",
            "%s" % substitute([params["nfsrootargs"]], substitutions)[0],
            "%s" % params["ipargs"],
        ]
        execute.sub_command.append("--append")
        execute.sub_command.append('"%s"' % " ".join(append))
        kernel_cmdline = " ".join(execute.sub_command)
        self.assertIn("console=ttyAMA0", kernel_cmdline)
        self.assertIn("/dev/nfs", kernel_cmdline)
        self.assertIn("root_dir,tcp,hard,intr", kernel_cmdline)
        self.assertIn("smp", kernel_cmdline)
        self.assertIn("cpu host", kernel_cmdline)
示例#43
0
    def test_substitutions(self, which_mock):
        """
        Test substitution of secondary media values into u-boot commands

        Unlike most u-boot calls, removable knows in advance all the values it needs to substitute
        into the boot commands for the secondary deployment as these are fixed by the device config
        and the image details from the job submission.
        """
        job_parser = JobParser()
        (rendered, _) = self.factory.create_device("cubie1.jinja2")
        cubie = NewDevice(yaml_safe_load(rendered))
        sample_job_file = os.path.join(
            os.path.dirname(__file__), "sample_jobs/cubietruck-removable.yaml")
        with open(sample_job_file) as sample_job_data:
            job = job_parser.parse(sample_job_data, cubie, 4212, None, "")
        job.logger = DummyLogger()
        job.validate()
        boot_params = [
            methods for methods in job.parameters["actions"]
            if "boot" in methods.keys()
        ][1]["boot"]
        self.assertIn("ramdisk", boot_params)
        self.assertIn("kernel", boot_params)
        self.assertIn("dtb", boot_params)
        self.assertIn("root_uuid", boot_params)
        self.assertIn("boot_part", boot_params)
        self.assertNotIn("type", boot_params)
        self.assertGreater(len(job.pipeline.actions), 1)
        self.assertIsNotNone(job.pipeline.actions[1].pipeline)
        u_boot_action = [
            action for action in job.pipeline.actions
            if action.name == "uboot-action"
        ][1]
        overlay = [
            action for action in u_boot_action.pipeline.actions
            if action.name == "bootloader-overlay"
        ][0]
        self.assertIsNotNone(
            overlay.get_namespace_data(action="storage-deploy",
                                       label="u-boot",
                                       key="device"))

        methods = cubie["actions"]["boot"]["methods"]
        self.assertIn("u-boot", methods)
        self.assertIn("usb", methods["u-boot"])
        self.assertIn("commands", methods["u-boot"]["usb"])
        commands_list = methods["u-boot"]["usb"]["commands"]
        device_id = u_boot_action.get_namespace_data(action="storage-deploy",
                                                     label="u-boot",
                                                     key="device")
        self.assertIsNotNone(device_id)
        kernel_type = u_boot_action.parameters["kernel_type"]
        bootcommand = map_kernel_uboot(kernel_type,
                                       device_params=cubie.get("parameters"))
        substitutions = {
            "{BOOTX}":
            "%s %s %s %s" % (
                bootcommand,
                cubie["parameters"][bootcommand]["kernel"],
                cubie["parameters"][bootcommand]["ramdisk"],
                cubie["parameters"][bootcommand]["dtb"],
            ),
            "{RAMDISK}":
            boot_params["ramdisk"],
            "{KERNEL}":
            boot_params["kernel"],
            "{DTB}":
            boot_params["dtb"],
            "{ROOT}":
            boot_params["root_uuid"],
            "{ROOT_PART}":
            "%s:%s" % (
                cubie["parameters"]["media"]["usb"][device_id]["device_id"],
                u_boot_action.parameters["boot_part"],
            ),
        }
        self.assertEqual("bootz 0x42000000 0x43300000 0x43000000",
                         substitutions["{BOOTX}"])
        self.assertEqual("/boot/initrd.img-3.16.0-4-armmp-lpae.u-boot",
                         substitutions["{RAMDISK}"])
        commands = substitute(commands_list, substitutions)
        print(commands)
        self.assertEqual(
            commands,
            [
                "usb start",
                "setenv autoload no",
                "load usb 0:0:1 {KERNEL_ADDR} /boot/vmlinuz-3.16.0-4-armmp-lpae",
                "load usb 0:0:1 {RAMDISK_ADDR} /boot/initrd.img-3.16.0-4-armmp-lpae.u-boot",
                "setenv initrd_size ${filesize}",
                "load usb 0:0:1 {DTB_ADDR} /boot/dtb-3.16.0-4-armmp-lpae",
                "console=ttyS0,115200n8 root=UUID=159d17cc-697c-4125-95a0-a3775e1deabe  ip=dhcp",
                "bootz 0x42000000 0x43300000 0x43000000",
            ],
        )
示例#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."
示例#45
0
    def test_overlay_action(self):  # pylint: disable=too-many-locals
        parameters = {
            'device_type': 'beaglebone-black',
            'job_name': 'uboot-pipeline',
            'job_timeout': '15m',
            'action_timeout': '5m',
            'priority': 'medium',
            'actions': {
                'boot': {
                    'method': 'u-boot',
                    'commands': 'ramdisk',
                    'type': 'bootz',
                    'prompts': ['linaro-test', 'root@debian:~#']
                },
                'deploy': {
                    'ramdisk': 'initrd.gz',
                    'kernel': 'zImage',
                    'dtb': 'broken.dtb'
                }
            }
        }
        device = NewDevice(os.path.join(os.path.dirname(__file__), '../devices/bbb-01.yaml'))
        job = Job(4212, parameters, None)
        job.device = device
        pipeline = Pipeline(job=job, parameters=parameters['actions']['boot'])
        job.pipeline = pipeline
        overlay = BootloaderCommandOverlay()
        pipeline.add_action(overlay)
        ip_addr = dispatcher_ip(None)
        parsed = []
        kernel_addr = job.device['parameters'][overlay.parameters['type']]['ramdisk']
        ramdisk_addr = job.device['parameters'][overlay.parameters['type']]['ramdisk']
        dtb_addr = job.device['parameters'][overlay.parameters['type']]['dtb']
        kernel = parameters['actions']['deploy']['kernel']
        ramdisk = parameters['actions']['deploy']['ramdisk']
        dtb = parameters['actions']['deploy']['dtb']

        substitution_dictionary = {
            '{SERVER_IP}': ip_addr,
            # the addresses need to be hexadecimal
            '{KERNEL_ADDR}': kernel_addr,
            '{DTB_ADDR}': dtb_addr,
            '{RAMDISK_ADDR}': ramdisk_addr,
            '{BOOTX}': "%s %s %s %s" % (
                overlay.parameters['type'], kernel_addr, ramdisk_addr, dtb_addr),
            '{RAMDISK}': ramdisk,
            '{KERNEL}': kernel,
            '{DTB}': dtb
        }
        params = device['actions']['boot']['methods']
        params['u-boot']['ramdisk']['commands'] = substitute(params['u-boot']['ramdisk']['commands'], substitution_dictionary)

        commands = params['u-boot']['ramdisk']['commands']
        self.assertIs(type(commands), list)
        self.assertIn("setenv loadkernel 'tftp ${kernel_addr_r} zImage'", commands)
        self.assertIn("setenv loadinitrd 'tftp ${initrd_addr_r} initrd.gz; setenv initrd_size ${filesize}'", commands)
        self.assertIn("setenv loadfdt 'tftp ${fdt_addr_r} broken.dtb'", commands)
        self.assertNotIn("setenv kernel_addr_r '{KERNEL_ADDR}'", commands)
        self.assertNotIn("setenv initrd_addr_r '{RAMDISK_ADDR}'", commands)
        self.assertNotIn("setenv fdt_addr_r '{DTB_ADDR}'", commands)

        for line in params['u-boot']['ramdisk']['commands']:
            line = line.replace('{SERVER_IP}', ip_addr)
            # the addresses need to be hexadecimal
            line = line.replace('{KERNEL_ADDR}', kernel_addr)
            line = line.replace('{DTB_ADDR}', dtb_addr)
            line = line.replace('{RAMDISK_ADDR}', ramdisk_addr)
            line = line.replace('{BOOTX}', "%s %s %s %s" % (
                overlay.parameters['type'], kernel_addr, ramdisk_addr, dtb_addr))
            line = line.replace('{RAMDISK}', ramdisk)
            line = line.replace('{KERNEL}', kernel)
            line = line.replace('{DTB}', dtb)
            parsed.append(line)
        self.assertIn("setenv loadkernel 'tftp ${kernel_addr_r} zImage'", parsed)
        self.assertIn("setenv loadinitrd 'tftp ${initrd_addr_r} initrd.gz; setenv initrd_size ${filesize}'", parsed)
        self.assertIn("setenv loadfdt 'tftp ${fdt_addr_r} broken.dtb'", parsed)
        self.assertNotIn("setenv kernel_addr_r '{KERNEL_ADDR}'", parsed)
        self.assertNotIn("setenv initrd_addr_r '{RAMDISK_ADDR}'", parsed)
        self.assertNotIn("setenv fdt_addr_r '{DTB_ADDR}'", parsed)
示例#46
0
文件: test_uboot.py 项目: atline/lava
    def test_overlay_action(self, which_mock):
        parameters = {
            "dispatcher":
            {},  # fake dispatcher parameter. Normally added by parser
            "device_type": "beaglebone-black",
            "job_name": "uboot-pipeline",
            "job_timeout": "15m",
            "action_timeout": "5m",
            "priority": "medium",
            "actions": {
                "boot": {
                    "namespace": "common",
                    "method": "u-boot",
                    "commands": "ramdisk",
                    "prompts": ["linaro-test", "root@debian:~#"],
                },
                "deploy": {
                    "namespace": "common",
                    "ramdisk": {
                        "url": "initrd.gz",
                        "compression": "gz"
                    },
                    "kernel": {
                        "url": "zImage",
                        "type": "zimage"
                    },
                    "dtb": {
                        "url": "broken.dtb"
                    },
                },
            },
        }
        data = yaml_safe_load(Factory().create_device("bbb-01.jinja2")[0])
        device = NewDevice(data)
        job = Job(4212, parameters, None)
        job.device = device
        pipeline = Pipeline(job=job, parameters=parameters["actions"]["boot"])
        job.pipeline = pipeline
        overlay = BootloaderCommandOverlay()
        connection = MagicMock()
        connection.timeout = MagicMock()
        pipeline.add_action(overlay)
        overlay.set_namespace_data(
            action="uboot-prepare-kernel",
            label="bootcommand",
            key="bootcommand",
            value="bootz",
        )
        overlay.validate()
        overlay.run(connection, 100)
        ip_addr = dispatcher_ip(None)
        parsed = []
        kernel_addr = job.device["parameters"][overlay.bootcommand]["ramdisk"]
        ramdisk_addr = job.device["parameters"][overlay.bootcommand]["ramdisk"]
        dtb_addr = job.device["parameters"][overlay.bootcommand]["dtb"]
        kernel = parameters["actions"]["deploy"]["kernel"]["url"]
        ramdisk = parameters["actions"]["deploy"]["ramdisk"]["url"]
        dtb = parameters["actions"]["deploy"]["dtb"]["url"]

        substitution_dictionary = {
            "{SERVER_IP}":
            ip_addr,
            # the addresses need to be hexadecimal
            "{KERNEL_ADDR}":
            kernel_addr,
            "{DTB_ADDR}":
            dtb_addr,
            "{RAMDISK_ADDR}":
            ramdisk_addr,
            "{BOOTX}":
            "%s %s %s %s" %
            (overlay.bootcommand, kernel_addr, ramdisk_addr, dtb_addr),
            "{RAMDISK}":
            ramdisk,
            "{KERNEL}":
            kernel,
            "{DTB}":
            dtb,
        }
        params = device["actions"]["boot"]["methods"]
        params["u-boot"]["ramdisk"]["commands"] = substitute(
            params["u-boot"]["ramdisk"]["commands"], substitution_dictionary)

        commands = params["u-boot"]["ramdisk"]["commands"]
        self.assertIs(type(commands), list)
        self.assertIn("tftp 0x83000000 zImage", commands)
        self.assertIn("tftp 0x83000000 initrd.gz", commands)
        self.assertIn("setenv initrd_size ${filesize}", commands)
        self.assertIn("tftp 0x88000000 broken.dtb", commands)
        self.assertNotIn("setenv kernel_addr_r '{KERNEL_ADDR}'", commands)
        self.assertNotIn("setenv initrd_addr_r '{RAMDISK_ADDR}'", commands)
        self.assertNotIn("setenv fdt_addr_r '{DTB_ADDR}'", commands)

        for line in params["u-boot"]["ramdisk"]["commands"]:
            line = line.replace("{SERVER_IP}", ip_addr)
            # the addresses need to be hexadecimal
            line = line.replace("{KERNEL_ADDR}", kernel_addr)
            line = line.replace("{DTB_ADDR}", dtb_addr)
            line = line.replace("{RAMDISK_ADDR}", ramdisk_addr)
            line = line.replace(
                "{BOOTX}",
                "%s %s %s %s" %
                (overlay.bootcommand, kernel_addr, ramdisk_addr, dtb_addr),
            )
            line = line.replace("{RAMDISK}", ramdisk)
            line = line.replace("{KERNEL}", kernel)
            line = line.replace("{DTB}", dtb)
            parsed.append(line)
        self.assertNotIn("setenv kernel_addr_r '{KERNEL_ADDR}'", parsed)
        self.assertNotIn("setenv initrd_addr_r '{RAMDISK_ADDR}'", parsed)
        self.assertNotIn("setenv fdt_addr_r '{DTB_ADDR}'", parsed)
示例#47
0
    def run(self, connection, max_end_time, args=None):
        """
        Read data from the download action and replace in context
        Use common data for all values passed into the substitutions so that
        multiple actions can use the same code.
        """
        # Multiple deployments would overwrite the value if parsed in the validate step.
        # FIXME: implement isolation for repeated steps.
        connection = super(BootloaderCommandOverlay, self).run(connection, max_end_time, args)
        ip_addr = dispatcher_ip(self.job.parameters['dispatcher'])

        self.ram_disk = self.get_namespace_data(action='compress-ramdisk', label='file', key='ramdisk')
        # most jobs substitute RAMDISK, so also use this for the initrd
        if self.get_namespace_data(action='nbd-deploy', label='nbd', key='initrd'):
            self.ram_disk = self.get_namespace_data(action='download-action', label='file', key='initrd')

        substitutions = {
            '{SERVER_IP}': ip_addr,
            '{PRESEED_CONFIG}': self.get_namespace_data(action='download-action', label='file', key='preseed'),
            '{PRESEED_LOCAL}': self.get_namespace_data(action='compress-ramdisk', label='file', key='preseed_local'),
            '{DTB}': self.get_namespace_data(action='download-action', label='file', key='dtb'),
            '{RAMDISK}': self.ram_disk,
            '{INITRD}': self.ram_disk,
            '{KERNEL}': self.get_namespace_data(action='download-action', label='file', key='kernel'),
            '{LAVA_MAC}': self.lava_mac
        }
        self.bootcommand = self.get_namespace_data(action='uboot-prepare-kernel', label='bootcommand', key='bootcommand')
        if not self.bootcommand:
            if 'type' in self.parameters:
                self.logger.warning("Using type from the boot action as the boot-command. "
                                    "Declaring a kernel type in the deploy is preferred.")
                self.bootcommand = self.parameters['type']
        prepared_kernel = self.get_namespace_data(action='prepare-kernel', label='file', key='kernel')
        if prepared_kernel:
            self.logger.info("Using kernel file from prepare-kernel: %s", prepared_kernel)
            substitutions['{KERNEL}'] = prepared_kernel
        if self.bootcommand:
            self.logger.debug("%s", self.job.device['parameters'])
            kernel_addr = self.job.device['parameters'][self.bootcommand]['kernel']
            dtb_addr = self.job.device['parameters'][self.bootcommand]['dtb']
            ramdisk_addr = self.job.device['parameters'][self.bootcommand]['ramdisk']

            if not self.get_namespace_data(action='tftp-deploy', label='tftp', key='ramdisk') \
                    and not self.get_namespace_data(action='download-action', label='file', key='ramdisk') \
                    and not self.get_namespace_data(action='download-action', label='file', key='initrd'):
                ramdisk_addr = '-'
            add_header = self.job.device['actions']['deploy']['parameters'].get('add_header', None)
            if self.method == 'u-boot' and not add_header == "u-boot":
                self.logger.debug("No u-boot header, not passing ramdisk to bootX cmd")
                ramdisk_addr = '-'

            if self.get_namespace_data(action='download-action', label='file', key='initrd'):
                # no u-boot header, thus no embedded size, so we have to add it to the
                # boot cmd with colon after the ramdisk
                substitutions['{BOOTX}'] = "%s %s %s:%s %s" % (
                    self.bootcommand, kernel_addr, ramdisk_addr, '${initrd_size}', dtb_addr)
            else:
                substitutions['{BOOTX}'] = "%s %s %s %s" % (
                    self.bootcommand, kernel_addr, ramdisk_addr, dtb_addr)

            substitutions['{KERNEL_ADDR}'] = kernel_addr
            substitutions['{DTB_ADDR}'] = dtb_addr
            substitutions['{RAMDISK_ADDR}'] = ramdisk_addr
            self.results = {
                'kernel_addr': kernel_addr,
                'dtb_addr': dtb_addr,
                'ramdisk_addr': ramdisk_addr
            }

        nfs_address = self.get_namespace_data(action='persistent-nfs-overlay', label='nfs_address', key='nfsroot')
        nfs_root = self.get_namespace_data(action='download-action', label='file', key='nfsrootfs')
        if nfs_root:
            substitutions['{NFSROOTFS}'] = self.get_namespace_data(action='extract-rootfs', label='file', key='nfsroot')
            substitutions['{NFS_SERVER_IP}'] = ip_addr
        elif nfs_address:
            substitutions['{NFSROOTFS}'] = nfs_address
            substitutions['{NFS_SERVER_IP}'] = self.get_namespace_data(
                action='persistent-nfs-overlay', label='nfs_address', key='serverip')

        nbd_root = self.get_namespace_data(action='download-action', label='file', key='nbdroot')
        if nbd_root:
            substitutions['{NBDSERVERIP}'] = str(self.get_namespace_data(action='nbd-deploy', label='nbd', key='nbd_server_ip'))
            substitutions['{NBDSERVERPORT}'] = str(self.get_namespace_data(action='nbd-deploy', label='nbd', key='nbd_server_port'))

        substitutions['{ROOT}'] = self.get_namespace_data(action='bootloader-from-media', label='uuid', key='root')  # UUID label, not a file
        substitutions['{ROOT_PART}'] = self.get_namespace_data(action='bootloader-from-media', label='uuid', key='boot_part')
        if self.use_bootscript:
            script = "/script.ipxe"
            bootscript = self.get_namespace_data(action='tftp-deploy', label='tftp', key='tftp_dir') + script
            bootscripturi = "tftp://%s/%s" % (ip_addr, os.path.dirname(substitutions['{KERNEL}']) + script)
            write_bootscript(substitute(self.commands, substitutions), bootscript)
            bootscript_commands = ['dhcp net0', "chain %s" % bootscripturi]
            self.set_namespace_data(action=self.name, label=self.method, key='commands', value=bootscript_commands)
            self.logger.info("Parsed boot commands: %s", '; '.join(bootscript_commands))
            return connection
        subs = substitute(self.commands, substitutions)
        self.set_namespace_data(action='bootloader-overlay', label=self.method, key='commands', value=subs)
        self.logger.info("Parsed boot commands: %s", '; '.join(subs))
        return connection