Ejemplo n.º 1
0
    def run(self, connection, 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, args)
        try:
            ip_addr = dispatcher_ip()
        except InfrastructureError as exc:
            raise RuntimeError("Unable to get dispatcher IP address: %s" % exc)
        substitutions = {
            '{SERVER_IP}': ip_addr
        }
        substitutions['{PRESEED_CONFIG}'] = self.get_common_data('file', 'preseed')
        substitutions['{DTB}'] = self.get_common_data('file', 'dtb')
        substitutions['{RAMDISK}'] = self.get_common_data('file', 'ramdisk')
        substitutions['{KERNEL}'] = self.get_common_data('file', 'kernel')
        nfs_url = self.get_common_data('nfs_url', 'nfsroot')
        if 'download_action' in self.data and 'nfsrootfs' in self.data['download_action']:
            substitutions['{NFSROOTFS}'] = self.get_common_data('file', 'nfsroot')
            substitutions['{NFS_SERVER_IP}'] = ip_addr
        elif nfs_url:
            substitutions['{NFSROOTFS}'] = nfs_url
            substitutions['{NFS_SERVER_IP}'] = self.get_common_data('nfs_url', 'serverip')

        substitutions['{ROOT}'] = self.get_common_data('uuid', 'root')  # UUID label, not a file
        substitutions['{ROOT_PART}'] = self.get_common_data('uuid', 'boot_part')

        self.data[self.type]['commands'] = substitute(self.commands, substitutions)
        self.logger.debug("Parsed boot commands: %s" % '; '.join(self.data[self.type]['commands']))
        return connection
Ejemplo n.º 2
0
    def validate(self):
        super(QemuCommandLine, self).validate()
        boot = self.job.device['actions']['boot']['methods']['qemu']
        qemu_binary = which(boot['parameters']['command'])
        self.sub_command = [qemu_binary]
        self.sub_command.extend(boot['parameters'].get('options', []))
        boot_opts = boot['parameters'].get('boot_options', None)
        if boot_opts:
            self.console = "console=%s" % boot_opts['console']
            self.boot_order = "-boot %s" % boot_opts['boot_order']
        if not qemu_binary or not self.console or not self.boot_order:
            self.errors = "Invalid parameters for %s" % self.name
        # create the preseed.cfg url
        # needs to be an IP address for DI, DNS is not available.
        # PRESEED_URL='http://10.15.0.32/tmp/d-i/jessie/preseed.cfg'
        self.preseed_url = 'tftp://%s/' % dispatcher_ip()

        self.sub_command.append(' -drive format=raw,file={emptyimage} ')
        self.sub_command.append(self.boot_order)
        self.command_line = " -append '%s console=tty0 console=tty1 %s %s %s %s preseed/url=%s{preseed} --- %s '  " % (
            self.parameters['deployment_data']['base'],
            self.parameters['deployment_data']['locale'], self.console,
            self.parameters['deployment_data']['keymaps'],
            self.parameters['deployment_data']['netcfg'], self.preseed_url,
            self.console)
        self.set_common_data(self.name, 'prompts',
                             self.parameters['deployment_data']['prompts'])
        self.set_common_data(self.name, 'append', self.command_line)
Ejemplo n.º 3
0
    def validate(self):
        super(QemuCommandLine, self).validate()
        boot = self.job.device['actions']['boot']['methods']['qemu']
        qemu_binary = which(boot['parameters']['command'])
        self.sub_command = [qemu_binary]
        self.sub_command.extend(boot['parameters'].get('options', []))
        boot_opts = boot['parameters'].get('boot_options', None)
        if boot_opts:
            self.console = "console=%s" % boot_opts['console']
            self.boot_order = "-boot %s" % boot_opts['boot_order']
        if not qemu_binary or not self.console or not self.boot_order:
            self.errors = "Invalid parameters for %s" % self.name
        # create the preseed.cfg url
        # needs to be an IP address for DI, DNS is not available.
        # PRESEED_URL='http://10.15.0.32/tmp/d-i/jessie/preseed.cfg'
        self.preseed_url = 'tftp://%s/' % dispatcher_ip()

        self.sub_command.append(' -drive format=raw,file={emptyimage} ')
        self.sub_command.append(self.boot_order)
        self.command_line = " -append '%s console=tty0 console=tty1 %s %s %s %s preseed/url=%s{preseed} --- %s '  " % (
            self.parameters['deployment_data']['base'],
            self.parameters['deployment_data']['locale'],
            self.console,
            self.parameters['deployment_data']['keymaps'],
            self.parameters['deployment_data']['netcfg'],
            self.preseed_url,
            self.console)
        self.set_common_data(self.name, 'prompts', self.parameters['deployment_data']['prompts'])
        self.set_common_data(self.name, 'append', self.command_line)
Ejemplo n.º 4
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
Ejemplo n.º 5
0
    def run(self, connection, args=None):
        """
        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, args)
        if 'file' not in self.data['download_action']['image']:
            self.logger.debug("Skipping %s - nothing downloaded")
            return connection
        decompressed_image = os.path.basename(
            self.data['download_action']['image']['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'])

        suffix = "tmp"
        wget_options = ''
        if self.parameters.get('download', '/usr/bin/wget') == '/usr/bin/wget':
            wget_options = "--no-check-certificate --no-proxy --connect-timeout=30 -S --progress=dot:giga -O -"
        wget_cmd = "%s %s http://%s/%s/%s" % (self.parameters['download'],
                                              wget_options, dispatcher_ip(),
                                              suffix, decompressed_image)
        dd_cmd = "dd of='%s' bs=4M" % device_path  # busybox dd does not support other flags
        connection.sendline("%s | %s" % (wget_cmd, dd_cmd))
        # connection.wait()  # long command lines can echo back
        # connection.wait()
        if not self.valid:
            self.logger.error(self.errors)

        return connection
Ejemplo n.º 6
0
    def run(self, connection, args=None):
        """
        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, args)
        if 'file' not in self.data['download_action']['image']:
            self.logger.debug("Skipping %s - nothing downloaded")
            return connection
        decompressed_image = os.path.basename(self.data['download_action']['image']['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'])

        suffix = "tmp"
        wget_options = ''
        if self.parameters.get('download', '/usr/bin/wget') == '/usr/bin/wget':
            wget_options = "--no-check-certificate --no-proxy --connect-timeout=30 -S --progress=dot:giga -O -"
        wget_cmd = "%s %s http://%s/%s/%s" % (
            self.parameters['download'], wget_options, dispatcher_ip(), suffix, decompressed_image
        )
        dd_cmd = "dd of='%s' bs=4M" % device_path  # busybox dd does not support other flags
        connection.sendline("%s | %s" % (wget_cmd, dd_cmd))
        # connection.wait()  # long command lines can echo back
        # connection.wait()
        if not self.valid:
            self.logger.error(self.errors)

        return connection
Ejemplo n.º 7
0
 def run(self, connection, args=None):
     connection = super(UefiSubstituteCommands, self).run(connection, args)
     try:
         ip_addr = dispatcher_ip()
     except InfrastructureError as exc:
         raise RuntimeError("Unable to get dispatcher IP address: %s" % exc)
     substitution_dictionary = {
         '{SERVER_IP}': ip_addr,
         '{RAMDISK}': self.get_common_data('file', 'ramdisk'),
         '{KERNEL}': self.get_common_data('file', 'kernel'),
         '{DTB}': self.get_common_data('file', 'dtb'),
         'TEST_MENU_NAME':
         "LAVA %s test image" % self.parameters['commands']
     }
     if 'download_action' in self.data and 'nfsrootfs' in self.data[
             'download_action']:
         substitution_dictionary['{NFSROOTFS}'] = self.get_common_data(
             'file', 'nfsroot')
     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
Ejemplo n.º 8
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',
            'output_dir': mkdtemp(),
            '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, None, None, None, parameters)
        job.device = device
        pipeline = Pipeline(job=job, parameters=parameters['actions']['boot'])
        job.set_pipeline(pipeline)
        overlay = BootloaderCommandOverlay()
        pipeline.add_action(overlay)
        try:
            ip_addr = dispatcher_ip()
        except InfrastructureError as exc:
            raise RuntimeError("Unable to get dispatcher IP address: %s" % exc)
        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)
Ejemplo n.º 9
0
 def run(self, connection, args=None):
     if self.parameters["deployment_data"].get('installer_extra_cmd', None):
         if self.parameters.get('os', None) == "debian_installer":
             add_late_command(self.data['download_action']['preseed']['file'], self.parameters["deployment_data"]["installer_extra_cmd"])
         if self.parameters.get('os', None) == "centos_installer":
             substitutions = {}
             substitutions['{OVERLAY_URL}'] = 'tftp://' + dispatcher_ip() + '/' + self.get_common_data('file', 'overlay')
             post_command = substitute([self.parameters["deployment_data"]["installer_extra_cmd"]], substitutions)
             add_to_kickstart(self.data['download_action']['preseed']['file'], post_command[0])
Ejemplo n.º 10
0
    def populate(self, parameters):
        self.tftp_dir = self.mkdtemp(override=tftpd_dir())
        self.internal_pipeline = Pipeline(parent=self,
                                          job=self.job,
                                          parameters=parameters)
        self.set_namespace_data(action=self.name,
                                label='tftp',
                                key='tftp_dir',
                                value=self.tftp_dir,
                                parameters=parameters)

        for key in ['initrd', 'kernel', 'dtb', 'nbdroot']:
            if key in parameters:
                download = DownloaderAction(key, path=self.tftp_dir)
                download.max_retries = 3  # overridden by failure_retry in the parameters, if set.
                self.internal_pipeline.add_action(download)
                if key == 'initrd':
                    self.set_namespace_data(action="tftp-deploy",
                                            label='tftp',
                                            key='ramdisk',
                                            value=True,
                                            parameters=parameters)
                    self.set_namespace_data(action=self.name,
                                            label='nbd',
                                            key='initrd',
                                            value=True,
                                            parameters=parameters)

        # prepare overlay
        self.internal_pipeline.add_action(OverlayAction())
        # setup values for protocol and later steps
        self.set_namespace_data(action=self.name,
                                label='nbd',
                                key='initrd',
                                value=True,
                                parameters=parameters)
        # store in parameters for protocol 'xnbd' to tear-down xnbd-server
        # and store in namespace for boot action
        # ip
        parameters['lava-xnbd'] = {}
        self.nbd_ip = dispatcher_ip(self.job.parameters['dispatcher'])
        parameters['lava-xnbd']['ip'] = self.nbd_ip
        self.set_namespace_data(action=self.name,
                                label='nbd',
                                key='nbd_server_ip',
                                value=self.nbd_ip,
                                parameters=parameters)
        # port
        self.nbd_port = get_free_port(self.job.parameters['dispatcher'])
        parameters['lava-xnbd']['port'] = self.nbd_port
        self.set_namespace_data(action=self.name,
                                label='nbd',
                                key='nbd_server_port',
                                value=self.nbd_port,
                                parameters=parameters)
        # handle XnbdAction next - bring-up xnbd-server
        self.internal_pipeline.add_action(XnbdAction())
Ejemplo n.º 11
0
    def run(self, connection, 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(UBootCommandOverlay, self).run(connection, args)
        try:
            ip_addr = dispatcher_ip()
        except InfrastructureError as exc:
            raise RuntimeError("Unable to get dispatcher IP address: %s" % exc)
        substitutions = {
            '{SERVER_IP}': ip_addr
        }

        kernel_addr = self.job.device['parameters'][self.parameters['type']]['kernel']
        dtb_addr = self.job.device['parameters'][self.parameters['type']]['dtb']
        ramdisk_addr = self.job.device['parameters'][self.parameters['type']]['ramdisk']

        substitutions['{KERNEL_ADDR}'] = kernel_addr
        substitutions['{DTB_ADDR}'] = dtb_addr
        substitutions['{RAMDISK_ADDR}'] = ramdisk_addr
        if not self.get_common_data('tftp', 'ramdisk') and not self.get_common_data('file', 'ramdisk'):
            ramdisk_addr = '-'
        bootcommand = self.parameters['type']
        if self.parameters['type'] == 'uimage':
            bootcommand = 'bootm'
        elif self.parameters['type'] == 'zimage':
            bootcommand = 'bootz'
        elif self.parameters['type'] == 'image':
            bootcommand = 'booti'
        substitutions['{BOOTX}'] = "%s %s %s %s" % (
            bootcommand, kernel_addr, ramdisk_addr, dtb_addr)

        substitutions['{RAMDISK}'] = self.get_common_data('file', 'ramdisk')
        substitutions['{KERNEL}'] = self.get_common_data('file', 'kernel')
        substitutions['{DTB}'] = self.get_common_data('file', 'dtb')

        nfs_url = self.get_common_data('nfs_url', 'nfsroot')
        if 'download_action' in self.data and 'nfsrootfs' in self.data['download_action']:
            substitutions['{NFSROOTFS}'] = self.get_common_data('file', 'nfsroot')
            substitutions['{NFS_SERVER_IP}'] = ip_addr
        elif nfs_url:

            substitutions['{NFSROOTFS}'] = nfs_url
            substitutions['{NFS_SERVER_IP}'] = self.get_common_data('nfs_url', 'serverip')

        substitutions['{ROOT}'] = self.get_common_data('uuid', 'root')  # UUID label, not a file
        substitutions['{ROOT_PART}'] = self.get_common_data('uuid', 'boot_part')

        self.data.setdefault('u-boot', {})
        self.data['u-boot']['commands'] = substitute(self.commands, substitutions)
        self.logger.debug("Parsed boot commands: %s", '; '.join(self.data['u-boot']['commands']))
        return connection
Ejemplo n.º 12
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',
            'output_dir': mkdtemp(),
            '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)
Ejemplo n.º 13
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',
            'output_dir': mkdtemp(),
            '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)
Ejemplo n.º 14
0
    def run(self, connection, args=None):
        """
        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, args)
        if 'file' not in self.data['download_action']['image']:
            self.logger.debug("Skipping %s - nothing downloaded")
            return connection
        decompressed_image = os.path.basename(
            self.data['download_action']['image']['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'])

        suffix = "%s/%s" % ("tmp", self.data['storage-deploy'].get(
            '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
        download_url = "http://%s/%s/%s" % (dispatcher_ip(), suffix,
                                            decompressed_image)
        substitutions = {'{DOWNLOAD_URL}': download_url}
        download_options = substitute([self.parameters['download']['options']],
                                      substitutions)[0]
        download_cmd = "%s %s" % (self.parameters['download']['tool'],
                                  download_options)

        dd_cmd = "dd of='%s' bs=4M" % device_path  # busybox dd does not support other flags

        # We must ensure that the secondary media deployment has completed before handing over
        # the connection.  Echoing the SECONDARY_DEPLOYMENT_MSG after the deployment means we
        # always have a constant string to match against
        prompt_string = connection.prompt_str
        connection.prompt_str = SECONDARY_DEPLOYMENT_MSG
        self.logger.debug("Changing prompt to %s" % connection.prompt_str)
        connection.sendline("%s | %s ; echo %s" %
                            (download_cmd, dd_cmd, SECONDARY_DEPLOYMENT_MSG))
        self.wait(connection)
        if not self.valid:
            self.logger.error(self.errors)

        # set prompt back
        connection.prompt_str = prompt_string
        self.logger.debug("Changing prompt to %s" % connection.prompt_str)
        return connection
Ejemplo n.º 15
0
    def run(self, connection, 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(UBootCommandOverlay, self).run(connection, args)
        try:
            ip_addr = dispatcher_ip()
        except InfrastructureError as exc:
            raise RuntimeError("Unable to get dispatcher IP address: %s" % exc)
        substitutions = {'{SERVER_IP}': ip_addr}

        kernel_addr = self.job.device['parameters'][
            self.parameters['type']]['kernel']
        dtb_addr = self.job.device['parameters'][
            self.parameters['type']]['dtb']
        ramdisk_addr = self.job.device['parameters'][
            self.parameters['type']]['ramdisk']

        substitutions['{KERNEL_ADDR}'] = kernel_addr
        substitutions['{DTB_ADDR}'] = dtb_addr
        substitutions['{RAMDISK_ADDR}'] = ramdisk_addr
        if not self.get_common_data('tftp',
                                    'ramdisk') and not self.get_common_data(
                                        'file', 'ramdisk'):
            ramdisk_addr = '-'

        substitutions['{BOOTX}'] = "%s %s %s %s" % (
            self.parameters['type'], kernel_addr, ramdisk_addr, dtb_addr)

        substitutions['{RAMDISK}'] = self.get_common_data('file', 'ramdisk')
        substitutions['{KERNEL}'] = self.get_common_data('file', 'kernel')
        substitutions['{DTB}'] = self.get_common_data('file', 'dtb')

        if 'download_action' in self.data and 'nfsrootfs' in self.data[
                'download_action']:
            substitutions['{NFSROOTFS}'] = self.get_common_data(
                'file', 'nfsroot')

        substitutions['{ROOT}'] = self.get_common_data(
            'uuid', 'root')  # UUID label, not a file
        substitutions['{ROOT_PART}'] = self.get_common_data(
            'uuid', 'boot_part')

        self.data['u-boot']['commands'] = substitute(self.commands,
                                                     substitutions)
        self.logger.debug("Parsed boot commands: %s" %
                          '; '.join(self.data['u-boot']['commands']))
        return connection
Ejemplo n.º 16
0
    def run(self, connection, args=None):
        """
        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, args)
        if 'file' not in self.data['download_action']['image']:
            self.logger.debug("Skipping %s - nothing downloaded")
            return connection
        decompressed_image = os.path.basename(self.data['download_action']['image']['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'])

        suffix = "%s/%s" % ("tmp", self.data['storage-deploy'].get('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
        download_url = "http://%s/%s/%s" % (
            dispatcher_ip(), suffix, decompressed_image
        )
        substitutions = {
            '{DOWNLOAD_URL}': download_url
        }
        download_options = substitute([self.parameters['download']['options']], substitutions)[0]
        download_cmd = "%s %s" % (
            self.parameters['download']['tool'], download_options
        )

        dd_cmd = "dd of='%s' bs=4M" % device_path  # busybox dd does not support other flags

        # We must ensure that the secondary media deployment has completed before handing over
        # the connection.  Echoing the SECONDARY_DEPLOYMENT_MSG after the deployment means we
        # always have a constant string to match against
        prompt_string = connection.prompt_str
        connection.prompt_str = SECONDARY_DEPLOYMENT_MSG
        self.logger.debug("Changing prompt to %s", connection.prompt_str)
        connection.sendline("%s | %s ; echo %s" % (download_cmd, dd_cmd, SECONDARY_DEPLOYMENT_MSG))
        self.wait(connection)
        if not self.valid:
            self.logger.error(self.errors)

        # set prompt back
        connection.prompt_str = prompt_string
        self.logger.debug("Changing prompt to %s", connection.prompt_str)
        return connection
Ejemplo n.º 17
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',
            'output_dir': mkdtemp(),
            '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, None, parameters)
        job.device = device
        pipeline = Pipeline(job=job, parameters=parameters['actions']['boot'])
        job.set_pipeline(pipeline)
        overlay = BootloaderCommandOverlay()
        pipeline.add_action(overlay)
        try:
            ip_addr = dispatcher_ip()
        except InfrastructureError as exc:
            raise RuntimeError("Unable to get dispatcher IP address: %s" % exc)
        parsed = []
        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)
Ejemplo n.º 18
0
    def run(self, connection, 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, args)
        try:
            ip_addr = dispatcher_ip()
        except InfrastructureError as exc:
            raise RuntimeError("Unable to get dispatcher IP address: %s" % exc)
        substitutions = {'{SERVER_IP}': ip_addr}
        substitutions['{RAMDISK}'] = self.get_common_data('file', 'ramdisk')
        substitutions['{KERNEL}'] = self.get_common_data('file', 'kernel')
        substitutions['{LAVA_MAC}'] = self.lava_mac
        nfs_url = self.get_common_data('nfs_url', 'nfsroot')
        if 'download_action' in self.data and 'nfsrootfs' in self.data[
                'download_action']:
            substitutions['{NFSROOTFS}'] = self.get_common_data(
                'file', 'nfsroot')
            substitutions['{NFS_SERVER_IP}'] = ip_addr
        elif nfs_url:
            substitutions['{NFSROOTFS}'] = nfs_url
            substitutions['{NFS_SERVER_IP}'] = self.get_common_data(
                'nfs_url', 'serverip')

        substitutions['{ROOT}'] = self.get_common_data(
            'uuid', 'root')  # UUID label, not a file
        substitutions['{ROOT_PART}'] = self.get_common_data(
            'uuid', 'boot_part')
        if self.use_bootscript:
            script = "/script.ipxe"
            bootscript = self.get_common_data('tftp', '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.data[self.type]['commands'] = bootscript_commands
        else:
            self.data[self.type]['commands'] = substitute(
                self.commands, substitutions)
        self.logger.debug("Parsed boot commands: %s" %
                          '; '.join(self.data[self.type]['commands']))
        return connection
Ejemplo n.º 19
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
Ejemplo n.º 20
0
 def run(self, connection, args=None):
     if self.parameters["deployment_data"].get('installer_extra_cmd', None):
         if self.parameters.get('os', None) == "debian_installer":
             add_late_command(
                 self.data['download_action']['preseed']['file'],
                 self.parameters["deployment_data"]["installer_extra_cmd"])
         if self.parameters.get('os', None) == "centos_installer":
             substitutions = {}
             substitutions['{OVERLAY_URL}'] = 'tftp://' + dispatcher_ip(
             ) + '/' + self.get_common_data('file', 'overlay')
             post_command = substitute([
                 self.parameters["deployment_data"]["installer_extra_cmd"]
             ], substitutions)
             add_to_kickstart(
                 self.data['download_action']['preseed']['file'],
                 post_command[0])
Ejemplo n.º 21
0
    def run(self, connection, 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, args)
        try:
            ip_addr = dispatcher_ip()
        except InfrastructureError as exc:
            raise RuntimeError("Unable to get dispatcher IP address: %s" % exc)
        substitutions = {'{SERVER_IP}': ip_addr}
        substitutions['{PRESEED_CONFIG}'] = self.get_common_data(
            'file', 'preseed')
        substitutions['{PRESEED_LOCAL}'] = self.get_common_data(
            'file', 'preseed_local')
        substitutions['{DTB}'] = self.get_common_data('file', 'dtb')
        substitutions['{RAMDISK}'] = self.get_common_data('file', 'ramdisk')
        substitutions['{KERNEL}'] = self.get_common_data('file', 'kernel')
        nfs_url = self.get_common_data('nfs_url', 'nfsroot')
        if 'download_action' in self.data and 'nfsrootfs' in self.data[
                'download_action']:
            substitutions['{NFSROOTFS}'] = self.get_common_data(
                'file', 'nfsroot')
            substitutions['{NFS_SERVER_IP}'] = ip_addr
        elif nfs_url:
            substitutions['{NFSROOTFS}'] = nfs_url
            substitutions['{NFS_SERVER_IP}'] = self.get_common_data(
                'nfs_url', 'serverip')

        substitutions['{ROOT}'] = self.get_common_data(
            'uuid', 'root')  # UUID label, not a file
        substitutions['{ROOT_PART}'] = self.get_common_data(
            'uuid', 'boot_part')

        self.data[self.type]['commands'] = substitute(self.commands,
                                                      substitutions)
        self.logger.debug("Parsed boot commands: %s" %
                          '; '.join(self.data[self.type]['commands']))
        return connection
Ejemplo n.º 22
0
    def run(self, connection, 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, args)
        try:
            ip_addr = dispatcher_ip()
        except InfrastructureError as exc:
            raise RuntimeError("Unable to get dispatcher IP address: %s" % exc)
        substitutions = {
            '{SERVER_IP}': ip_addr
        }
        substitutions['{RAMDISK}'] = self.get_common_data('file', 'ramdisk')
        substitutions['{KERNEL}'] = self.get_common_data('file', 'kernel')
        substitutions['{LAVA_MAC}'] = self.lava_mac
        nfs_url = self.get_common_data('nfs_url', 'nfsroot')
        if 'download_action' in self.data and 'nfsrootfs' in self.data['download_action']:
            substitutions['{NFSROOTFS}'] = self.get_common_data('file', 'nfsroot')
            substitutions['{NFS_SERVER_IP}'] = ip_addr
        elif nfs_url:
            substitutions['{NFSROOTFS}'] = nfs_url
            substitutions['{NFS_SERVER_IP}'] = self.get_common_data('nfs_url', 'serverip')

        substitutions['{ROOT}'] = self.get_common_data('uuid', 'root')  # UUID label, not a file
        substitutions['{ROOT_PART}'] = self.get_common_data('uuid', 'boot_part')
        if self.use_bootscript:
            script = "/script.ipxe"
            bootscript = self.get_common_data('tftp', '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.data[self.type]['commands'] = bootscript_commands
        else:
            self.data[self.type]['commands'] = substitute(self.commands, substitutions)
        self.logger.debug("Parsed boot commands: %s",
                          '; '.join(self.data[self.type]['commands']))
        return connection
Ejemplo n.º 23
0
 def run(self, connection, max_end_time, args=None):
     connection = super(OverlayUnpack, self).run(connection, max_end_time,
                                                 args)
     if not connection:
         raise LAVABug("Cannot transfer overlay, no connection available.")
     ip_addr = dispatcher_ip(self.job.parameters['dispatcher'])
     overlay_file = self.get_namespace_data(action='compress-overlay',
                                            label='output',
                                            key='file')
     if not overlay_file:
         raise JobError("No overlay file identified for the transfer.")
     overlay = os.path.basename(overlay_file).strip()
     self.url = os.path.join(DISPATCHER_DOWNLOAD_DIR, overlay)
     shutil.move(overlay_file, self.url)
     self.logger.debug("Moved %s to %s", overlay_file, self.url)
     dwnld = self.parameters['transfer_overlay']['download_command']
     dwnld += " http://%s/tmp/%s" % (ip_addr, overlay)
     unpack = self.parameters['transfer_overlay']['unpack_command']
     unpack += ' ' + overlay
     connection.sendline("rm %s; %s && %s" % (overlay, dwnld, unpack))
     return connection
Ejemplo n.º 24
0
 def run(self, connection, args=None):
     connection = super(UefiSubstituteCommands, self).run(connection, args)
     try:
         ip_addr = dispatcher_ip()
     except InfrastructureError as exc:
         raise RuntimeError("Unable to get dispatcher IP address: %s" % exc)
     substitution_dictionary = {
         '{SERVER_IP}': ip_addr,
         '{RAMDISK}': self.get_common_data('file', 'ramdisk'),
         '{KERNEL}': self.get_common_data('file', 'kernel'),
         '{DTB}': self.get_common_data('file', 'dtb'),
         'TEST_MENU_NAME': "LAVA %s test image" % self.parameters['commands']
     }
     if 'download_action' in self.data and 'nfsrootfs' in self.data['download_action']:
         substitution_dictionary['{NFSROOTFS}'] = self.get_common_data('file', 'nfsroot')
     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
Ejemplo n.º 25
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."
Ejemplo n.º 26
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',
            'output_dir': mkdtemp(),
            '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, None, parameters)
        job.device = device
        pipeline = Pipeline(job=job, parameters=parameters['actions']['boot'])
        job.set_pipeline(pipeline)
        overlay = UBootCommandOverlay()
        pipeline.add_action(overlay)
        try:
            ip_addr = dispatcher_ip()
        except InfrastructureError as exc:
            raise RuntimeError("Unable to get dispatcher IP address: %s" % exc)
        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)
Ejemplo n.º 27
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'])

        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.get_namespace_data(action='compress-ramdisk',
                                    label='file',
                                    key='ramdisk'),
            '{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:
            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'):
                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 = '-'

            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')

        substitutions['{ROOT}'] = self.get_namespace_data(
            action='uboot-from-media', label='uuid',
            key='root')  # UUID label, not a file
        substitutions['{ROOT_PART}'] = self.get_namespace_data(
            action='uboot-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
Ejemplo n.º 28
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
        }
        download_options = substitute([self.parameters['download']['options']], substitutions)[0]
        download_cmd = "%s %s" % (
            self.parameters['download']['tool'], download_options
        )
        dd_cmd = "dd of='%s' bs=4M" % device_path  # busybox dd does not support other flags

        # set prompt to download prompt to ensure that the secondary deployment has started
        prompt_string = connection.prompt_str
        connection.prompt_str = self.parameters['download']['prompt']
        self.logger.debug("Changing prompt to %s", connection.prompt_str)
        connection.sendline("%s | %s ; echo %s" % (download_cmd, dd_cmd, SECONDARY_DEPLOYMENT_MSG))
        self.wait(connection)
        if not self.valid:
            self.logger.error(self.errors)

        # We must ensure that the secondary media deployment has completed before handing over
        # the connection.  Echoing the SECONDARY_DEPLOYMENT_MSG after the deployment means we
        # always have a constant string to match against
        connection.prompt_str = SECONDARY_DEPLOYMENT_MSG
        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
Ejemplo n.º 29
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",
            "output_dir": mkdtemp(),
            "actions": {
                "boot": {"method": "u-boot", "commands": "ramdisk", "type": "bootz"},
                "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, None, parameters)
        job.device = device
        pipeline = Pipeline(job=job, parameters=parameters["actions"]["boot"])
        job.set_pipeline(pipeline)
        overlay = UBootCommandOverlay()
        pipeline.add_action(overlay)
        try:
            ip_addr = dispatcher_ip()
        except InfrastructureError as exc:
            raise RuntimeError("Unable to get dispatcher IP address: %s" % exc)
        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)
Ejemplo n.º 30
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',
            'output_dir': mkdtemp(),
            '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)