class TestLxcDeploy(StdoutTestCase):  # pylint: disable=too-many-public-methods
    def setUp(self):
        super(TestLxcDeploy, self).setUp()
        factory = LxcFactory()
        self.job = factory.create_lxc_job('sample_jobs/lxc.yaml', mkdtemp())

    def test_deploy_job(self):
        self.assertEqual(self.job.pipeline.job, self.job)
        for action in self.job.pipeline.actions:
            if isinstance(action, DeployAction):
                self.assertEqual(action.job, self.job)

    def test_pipeline(self):
        description_ref = self.pipeline_reference('lxc.yaml')
        self.assertEqual(description_ref, self.job.pipeline.describe(False))

    @unittest.skipIf(infrastructure_error('lxc-create'),
                     'lxc-create not installed')
    def test_validate(self):
        try:
            self.job.pipeline.validate_actions()
        except JobError as exc:
            self.fail(exc)
        for action in self.job.pipeline.actions:
            self.assertEqual([], action.errors)

    @unittest.skipIf(infrastructure_error('lxc-create'),
                     'lxc-create not installed')
    def test_create(self):
        for action in self.job.pipeline.actions:
            if isinstance(action, LxcCreateAction):
                self.assertEqual(action.lxc_data['lxc_name'],
                                 'pipeline-lxc-test-4577')
                self.assertEqual(action.lxc_data['lxc_distribution'], 'debian')
                self.assertEqual(action.lxc_data['lxc_release'], 'sid')
                self.assertEqual(action.lxc_data['lxc_arch'], 'amd64')
                self.assertEqual(action.lxc_data['lxc_template'], 'debian')
                self.assertEqual(action.lxc_data['lxc_mirror'],
                                 'http://ftp.us.debian.org/debian/')
                self.assertEqual(
                    action.lxc_data['lxc_security_mirror'],
                    'http://mirror.csclub.uwaterloo.ca/debian-security/')

    @unittest.skipIf(infrastructure_error('lxc-start'),
                     'lxc-start not installed')
    def test_boot(self):
        for action in self.job.pipeline.actions:
            if isinstance(action, BootAction):
                # get the action & populate it
                self.assertEqual(action.parameters['method'], 'lxc')
                self.assertEqual(action.parameters['prompts'],
                                 ['root@(.*):/#'])

    def test_testdefinitions(self):
        for action in self.job.pipeline.actions:
            if action.name == 'test':
                # get the action & populate it
                self.assertEqual(len(action.parameters['definitions']), 2)
Example #2
0
 def validate(self):
     super(FastbootAction, self).validate()
     self.errors = infrastructure_error('fastboot')
     if infrastructure_error('fastboot'):
         self.errors = "Unable to find 'fastboot' command"
     if 'fastboot_serial_number' not in self.job.device:
         self.errors = "device fastboot serial number missing"
         if self.job.device['fastboot_serial_number'] == '0000000000':
             self.errors = "device fastboot serial number unset"
Example #3
0
    def validate(self):
        super(TftpAction, self).validate()
        if 'kernel' not in self.parameters:
            self.errors = "%s needs a kernel to deploy" % self.name
        if not self.valid:
            return
        if 'nfs_url' in self.parameters:
            self.errors = "Use a persistent_nfs dictionary instead of nfs_url"
        if 'nfsrootfs' in self.parameters and 'persistent_nfs' in self.parameters:
            self.errors = "Only one of nfsrootfs or persistent_nfs can be specified"
        if self.test_needs_deployment(self.parameters):
            lava_test_results_base = self.parameters['deployment_data']['lava_test_results_dir']
            lava_test_results_dir = lava_test_results_base % self.job.job_id
            self.set_namespace_data(action='test', label='results', key='lava_test_results_dir', value=lava_test_results_dir)
        # Extract the 3 last path elements. See action.mkdtemp()
        suffix = os.path.join(*self.tftp_dir.split('/')[-2:])
        self.set_namespace_data(action=self.name, label='tftp', key='suffix', value=suffix)
        self.errors = infrastructure_error('in.tftpd')

        # Check that the tmp directory is in the tftpd_dir or in /tmp for the
        # unit tests
        tftpd_directory = os.path.realpath(tftpd_dir())
        tftp_dir = os.path.realpath(self.tftp_dir)
        tmp_dir = tempfile.gettempdir()
        if not tftp_dir.startswith(tftpd_directory) and \
           not tftp_dir.startswith(tmp_dir):
            self.errors = "tftpd directory is not configured correctly, see /etc/default/tftpd-hpa"
Example #4
0
 def validate(self):
     super(LxcAction, self).validate()
     if LxcProtocol.name not in [protocol.name for protocol in self.job.protocols]:
         self.errors = "Invalid job - missing protocol"
     self.errors = infrastructure_error('lxc-create')
     lava_test_results_dir = self.parameters['deployment_data']['lava_test_results_dir']
     self.data['lava_test_results_dir'] = lava_test_results_dir % self.job.job_id
Example #5
0
    def run(self, connection, max_end_time, args=None):
        connection = super(XnbdAction, self).run(connection, max_end_time,
                                                 args)
        self.logger.debug("%s: starting xnbd-server", self.name)
        # pull from parameters - as previously set
        self.nbd_server_port = self.parameters['lava-xnbd']['port']
        self.nbd_server_ip = self.parameters['lava-xnbd']['ip']
        self.nbd_root = self.parameters['lava-xnbd']['nbdroot']
        self.logger.debug(
            "NBD-IP: %s, NBD-PORT: %s, NBD-ROOT: %s" %
            (self.nbd_server_ip, self.nbd_server_port, self.nbd_root))
        nbd_cmd = [
            'xnbd-server', '--logpath',
            '/tmp/xnbd.log.%s' % self.nbd_server_port, '--daemon', '--target',
            '--lport',
            '%s' % self.nbd_server_port,
            '%s/%s' % (os.path.realpath(tftpd_dir()), self.nbd_root)
        ]
        command_output = self.run_command(nbd_cmd, allow_fail=False)

        if command_output and 'error' in command_output:
            self.errors = infrastructure_error('xnbd-server: %s' %
                                               command_output)
        self.logger.debug("%s: starting xnbd-server done", self.name)
        return connection
Example #6
0
 def validate(self):
     if 'lxc' not in self.job.device['actions']['boot']['methods']:
         return
     super(ConnectLxc, self).validate()
     self.errors = infrastructure_error('lxc-attach')
     if 'prompts' not in self.parameters:
         self.errors = "Unable to identify test image prompts from parameters."
Example #7
0
 def validate(self):
     if 'lxc' not in self.job.device['actions']['boot']['methods']:
         return
     super(ConnectLxc, self).validate()
     self.errors = infrastructure_error('lxc-attach')
     if 'prompts' not in self.parameters:
         self.errors = "Unable to identify test image prompts from parameters."
Example #8
0
 def validate(self):
     super(ConnectSsh, self).validate()
     params = self._check_params()
     self.errors = infrastructure_error('ssh')
     if self.valid:
         self.command = ['ssh']
         self.command.extend(params['options'])
Example #9
0
 def validate(self):
     super(Scp, self).validate()
     params = self._check_params()
     self.errors = infrastructure_error('scp')
     if self.valid:
         self.scp.append('scp')
         self.scp.extend(params['options'])
 def validate(self):
     super(Scp, self).validate()
     params = self._check_params()
     self.errors = infrastructure_error('scp')
     if 'ssh' not in self.job.device['actions']['deploy']['methods']:
         self.errors = "Unable to use %s without ssh deployment" % self.name
     if 'ssh' not in self.job.device['actions']['boot']['methods']:
         self.errors = "Unable to use %s without ssh boot" % self.name
     if self.get_namespace_data(action='prepare-scp-overlay',
                                label="prepare-scp-overlay",
                                key=self.key):
         self.primary = False
     elif 'host' not in self.job.device['actions']['deploy']['methods'][
             'ssh']:
         self.errors = "Invalid device or job configuration, missing host."
     if not self.primary and len(
             self.get_namespace_data(action='prepare-scp-overlay',
                                     label="prepare-scp-overlay",
                                     key=self.key)) != 1:
         self.errors = "Invalid number of host_keys"
     if self.primary:
         host_address = self.job.device['actions']['deploy']['methods'][
             'ssh']['host']
         if not host_address:
             self.errors = "Unable to retrieve ssh_host address for primary connection."
     if 'port' in self.job.device['actions']['deploy']['methods']['ssh']:
         port = str(
             self.job.device['actions']['deploy']['methods']['ssh']['port'])
         if not port.isdigit():
             self.errors = "Port was set but was not a digit"
     if self.valid:
         self.scp.append('scp')
         if 'options' in params:
             self.scp.extend(params['options'])
Example #11
0
 def validate(self):
     super(FastbootAction, self).validate()
     self.errors = infrastructure_error('fastboot')
     if 'serial_number' not in self.job.device:
         self.errors = "device serial number missing"
         if self.job.device['serial_number'] == '0000000000':
             self.errors = "device serial number unset"
Example #12
0
    def validate(self):
        super(TftpAction, self).validate()
        if 'kernel' not in self.parameters:
            self.errors = "%s needs a kernel to deploy" % self.name
        if not self.valid:
            return
        if 'nfsrootfs' in self.parameters and 'nfs_url' in self.parameters:
            self.errors = "Only one of nfsrootfs or nfs_url can be specified"
        lava_test_results_dir = self.parameters['deployment_data'][
            'lava_test_results_dir']
        self.data[
            'lava_test_results_dir'] = lava_test_results_dir % self.job.job_id
        # Extract the 3 last path elements. See action.mkdtemp()
        suffix = os.path.join(*self.tftp_dir.split('/')[-2:])
        self.data[self.name].setdefault('suffix', suffix)
        self.errors = infrastructure_error('in.tftpd')

        # Check that the tmp directory is in the tftpd_dir or in /tmp for the
        # unit tests
        tftpd_directory = os.path.realpath(tftpd_dir())
        tftp_dir = os.path.realpath(self.tftp_dir)
        tmp_dir = tempfile.gettempdir()
        if not tftp_dir.startswith(tftpd_directory) and \
           not tftp_dir.startswith(tmp_dir):
            self.errors = "tftpd directory is not configured correctly, see /etc/default/tftpd-hpa"
Example #13
0
 def validate(self):
     super(Scp, self).validate()
     params = self._check_params()
     self.errors = infrastructure_error('scp')
     if self.valid:
         self.scp.append('scp')
         self.scp.extend(params['options'])
Example #14
0
 def validate(self):
     super(ConnectSsh, self).validate()
     params = self._check_params()
     self.errors = infrastructure_error('ssh')
     if self.valid:
         self.command = ['ssh']
         self.command.extend(params['options'])
Example #15
0
 def validate(self):
     super(FlashPyOCDAction, self).validate()
     boot = self.job.device['actions']['boot']['methods']['pyocd']
     pyocd_binary = boot['parameters']['command']
     self.errors = infrastructure_error(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"
Example #16
0
 def validate(self):
     super(ConnectAdb, self).validate()
     if 'connect' not in self.job.device['commands']:
         self.errors = "Unable to connect to device %s - missing connect command." % self.job.device.hostname
         return
     if 'prompts' not in self.parameters:
         self.errors = "Unable to identify test image prompts from parameters."
     command = self.job.device['commands']['connect']
     exe = ''
     try:
         exe = command.split(' ')[0]
     except AttributeError:
         self.errors = "Unable to parse the connection command %s" % command
     self.errors = infrastructure_error(exe)
     if infrastructure_error(exe):
         self.errors = "Unable to find '%s' command" % exe
Example #17
0
 def validate(self):
     super(AdbOverlayUnpack, self).validate()
     if 'adb_serial_number' not in self.job.device:
         self.errors = "device adb serial number missing"
         if self.job.device['adb_serial_number'] == '0000000000':
             self.errors = "device adb serial number unset"
     if infrastructure_error('adb'):
         self.errors = "Unable to find 'adb' command"
Example #18
0
 def validate(self):
     super(FlashRomDeploy, self).validate()
     if 'coreboot' not in self.parameters:
         self.errors = "%s needs a coreboot to deploy" % self.name
     if not self.valid:
         return
     lava_test_results_dir = self.parameters['deployment_data']['lava_test_results_dir']
     self.data['lava_test_results_dir'] = lava_test_results_dir % self.job.job_id
     self.errors = infrastructure_error('flashrom')
Example #19
0
 def validate(self):
     super(CompressRamdisk, self).validate()
     if not self.parameters.get('ramdisk', None):  # idempotency
         return
     self.errors = infrastructure_error('mkimage')
     if 'mkimage_arch' not in self.job.device['actions']['boot']['methods']['u-boot']['parameters']:
         self.errors = "Missing architecture string for uboot mkimage support"
         return
     self.mkimage_arch = self.job.device['actions']['boot']['methods']['u-boot']['parameters']['mkimage_arch']
Example #20
0
    def validate(self):
        super(NbdAction, self).validate()
        if 'kernel' not in self.parameters:
            self.errors = "%s needs a kernel to deploy" % self.name
        if not self.valid:
            return
        if 'nbdroot' not in self.parameters:
            self.errors = "NBD deployment needs a 'nbdroot' parameter"
        if 'initrd' not in self.parameters:
            self.errors = "NBD deployment needs an 'initrd' parameter"
        # we cannot work with these when using nbd
        if 'nfsrootfs' in self.parameters or 'nfs_url' in self.parameters:
            self.errors = "nfsrootfs or nfs_url cannot be used with NBD deployment, use a e.g. ext3/4 filesystem as 'nbdroot=' parameter"
        if 'ramdisk' in self.parameters:
            self.errors = "ramdisk cannot be used with NBD deployment, use a e.g. ext3/4 filesystem as 'initrd' parameter"

        if self.test_needs_deployment(self.parameters):
            lava_test_results_base = self.parameters['deployment_data'][
                'lava_test_results_dir']
            lava_test_results_dir = lava_test_results_base % self.job.job_id
            self.set_namespace_data(action='test',
                                    label='results',
                                    key='lava_test_results_dir',
                                    value=lava_test_results_dir)

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

        # Check that the tmp directory is in the nbdd_dir or in /tmp for the
        # unit tests
        tftpd_directory = os.path.realpath(tftpd_dir())
        tftp_dir = os.path.realpath(self.tftp_dir)
        tmp_dir = tempfile.gettempdir()
        if not tftp_dir.startswith(tftpd_directory) and \
           not tftp_dir.startswith(tmp_dir):
            self.errors = "tftpd directory is not configured correctly, see /etc/default/tftpd-hpa"
Example #21
0
 def validate(self):
     super(ConnectSsh, self).validate()
     params = self._check_params()
     self.errors = infrastructure_error('ssh')
     if 'host' in self.job.device['actions']['deploy']['methods']['ssh']:
         self.primary = True
         self.host = self.job.device['actions']['deploy']['methods']['ssh']['host']
     if self.valid:
         self.command = ['ssh']
         self.command.extend(params['options'])
Example #22
0
 def validate(self):
     super(TftpAction, self).validate()
     if 'kernel' not in self.parameters:
         self.errors = "%s needs a kernel to deploy" % self.name
     if not self.valid:
         return
     lava_test_results_dir = self.parameters['deployment_data']['lava_test_results_dir']
     self.data['lava_test_results_dir'] = lava_test_results_dir % self.job.job_id
     if self.suffix:
         self.data[self.name].setdefault('suffix', self.suffix)
     self.data[self.name].setdefault('suffix', os.path.basename(self.tftp_dir))
     self.errors = infrastructure_error('in.tftpd')
Example #23
0
 def validate(self):
     super(PersistentNFSOverlay, self).validate()
     if 'nfs_url' not in self.parameters:
         return None
     if ':' not in self.parameters['nfs_url']:
         self.errors = "Unrecognised NFS URL: '%s'" % self.parameters['nfs_url']
         return
     nfs_server, dirname = self.parameters['nfs_url'].split(':')
     self.errors = infrastructure_error('rpcinfo')
     self.errors = rpcinfo_nfs(nfs_server)
     self.set_common_data('nfs_url', 'nfsroot', dirname)
     self.set_common_data('nfs_url', 'serverip', nfs_server)
Example #24
0
 def validate(self):
     super(ConnectDevice, self).validate()
     if 'connect' not in self.job.device['commands']:
         self.errors = "Unable to connect to device %s - missing connect command." % self.job.device.hostname
         return
     command = self.job.device['commands']['connect']
     exe = ''
     try:
         exe = command.split(' ')[0]
     except AttributeError:
         self.errors = "Unable to parse the connection command %s" % command
     self.errors = infrastructure_error(exe)
Example #25
0
 def validate(self):
     super(ConnectDevice, self).validate()
     if 'connect' not in self.job.device['commands']:
         self.errors = "Unable to connect to device %s - missing connect command." % self.job.device.hostname
         return
     command = self.job.device['commands']['connect']
     exe = ''
     try:
         exe = command.split(' ')[0]
     except AttributeError:
         self.errors = "Unable to parse the connection command %s" % command
     self.errors = infrastructure_error(exe)
Example #26
0
 def validate(self):
     super(LxcAction, self).validate()
     self.logger.info("lxc, installed at version: %s" %
                      debian_package_version(pkg='lxc', split=False))
     if LxcProtocol.name not in [protocol.name for protocol in self.job.protocols]:
         self.errors = "Invalid job - missing protocol"
     self.errors = infrastructure_error('lxc-create')
     lava_test_results_dir = self.parameters['deployment_data']['lava_test_results_dir']
     lava_test_results_dir = lava_test_results_dir % self.job.job_id
     self.set_namespace_data(action='test', label='results', key='lava_test_results_dir', value=lava_test_results_dir)
     lava_test_sh_cmd = self.parameters['deployment_data']['lava_test_sh_cmd']
     self.set_namespace_data(action=self.name, label='shared', key='lava_test_sh_cmd', value=lava_test_sh_cmd)
Example #27
0
 def validate(self):
     super(PersistentNFSOverlay, self).validate()
     if 'nfs_url' not in self.parameters:
         return None
     if ':' not in self.parameters['nfs_url']:
         self.errors = "Unrecognised NFS URL: '%s'" % self.parameters[
             'nfs_url']
         return
     nfs_server, dirname = self.parameters['nfs_url'].split(':')
     self.errors = infrastructure_error('rpcinfo')
     self.errors = rpcinfo_nfs(nfs_server)
     self.set_common_data('nfs_url', 'nfsroot', dirname)
     self.set_common_data('nfs_url', 'serverip', nfs_server)
Example #28
0
 def validate(self):
     super(ConnectDevice, self).validate()
     if 'connect' not in self.job.device['commands']:
         self.errors = "Unable to connect to device %s - missing connect command." % self.job.device.hostname
         return
     if 'test_image_prompts' not in self.job.device:
         self.errors = "Unable to identify test image prompts from device configuration."
     command = self.job.device['commands']['connect']
     exe = ''
     try:
         exe = command.split(' ')[0]
     except AttributeError:
         self.errors = "Unable to parse the connection command %s" % command
     self.errors = infrastructure_error(exe)
Example #29
0
 def validate(self):
     super(ConnectAdb, self).validate()
     if "connect" not in self.job.device["commands"]:
         self.errors = "Unable to connect to device %s - missing connect command." % self.job.device.hostname
         return
     if "prompts" not in self.parameters:
         self.errors = "Unable to identify test image prompts from parameters."
     command = self.job.device["commands"]["connect"]
     exe = ""
     try:
         exe = command.split(" ")[0]
     except AttributeError:
         self.errors = "Unable to parse the connection command %s" % command
     self.errors = infrastructure_error(exe)
Example #30
0
 def validate(self):
     super(LxcCreateUdevRuleAction, self).validate()
     self.errors = infrastructure_error('udevadm')
     if 'device_info' in self.job.device \
        and not isinstance(self.job.device.get('device_info'), list):
         self.errors = "device_info unset"
     try:
         if 'device_info' in self.job.device:
             for usb_device in self.job.device['device_info']:
                 board_id = usb_device.get('board_id', '')
                 if board_id == '0000000000':
                     self.errors = "board_id unset"
     except TypeError:
         self.errors = "Invalid parameters for %s" % self.name
Example #31
0
 def validate(self):
     super(ConnectDevice, self).validate()
     if 'connect' not in self.job.device['commands']:
         self.errors = "Unable to connect to device %s - missing connect command." % self.job.device.hostname
         return
     if 'test_image_prompts' not in self.job.device:
         self.errors = "Unable to identify test image prompts from device configuration."
     command = self.job.device['commands']['connect']
     exe = ''
     try:
         exe = command.split(' ')[0]
     except AttributeError:
         self.errors = "Unable to parse the connection command %s" % command
     self.errors = infrastructure_error(exe)
Example #32
0
 def validate(self):
     super(CompressRamdisk, self).validate()
     if not self.parameters.get('ramdisk', None):  # idempotency
         return
     if 'parameters' in self.job.device['actions']['deploy']:
         self.add_header = self.job.device['actions']['deploy']['parameters'].get('add_header', None)
         if self.add_header is not None:
             if self.add_header == 'u-boot':
                 self.errors = infrastructure_error('mkimage')
                 if 'mkimage_arch' not in self.job.device['actions']['deploy']['parameters']:
                     self.errors = "Missing architecture for uboot mkimage support (mkimage_arch in deploy parameters)"
                     return
                 self.mkimage_arch = self.job.device['actions']['deploy']['parameters']['mkimage_arch']
             else:
                 self.errors = "ramdisk: add_header: unknown header type"
Example #33
0
 def validate(self):
     super(LxcAction, self).validate()
     if LxcProtocol.name not in [protocol.name for protocol in self.job.protocols]:
         self.errors = "Invalid job - missing protocol"
     self.errors = infrastructure_error('lxc-create')
     lava_test_results_dir = self.parameters['deployment_data']['lava_test_results_dir']
     lava_test_results_dir = lava_test_results_dir % self.job.job_id
     self.data['lava_test_results_dir'] = lava_test_results_dir
     namespace = self.parameters.get('namespace', None)
     if namespace:
         self.action_namespaces.append(namespace)
         self.set_common_data(namespace, 'lava_test_results_dir',
                              lava_test_results_dir)
         lava_test_sh_cmd = self.parameters['deployment_data']['lava_test_sh_cmd']
         self.set_common_data(namespace, 'lava_test_sh_cmd',
                              lava_test_sh_cmd)
Example #34
0
 def validate(self):
     super(PersistentNFSOverlay, self).validate()
     persist = self.parameters.get('persistent_nfs', None)
     if not persist:
         return
     if 'address' not in persist:
         self.errors = "Missing address for persistent NFS"
         return
     if ':' not in persist['address']:
         self.errors = "Unrecognised NFS URL: '%s'" % self.parameters['persistent_nfs']['address']
         return
     nfs_server, dirname = persist['address'].split(':')
     self.errors = infrastructure_error('rpcinfo')
     self.errors = rpcinfo_nfs(nfs_server)
     self.set_namespace_data(action=self.name, label='nfs_address', key='nfsroot', value=dirname)
     self.set_namespace_data(action=self.name, label='nfs_address', key='serverip', value=nfs_server)
Example #35
0
 def validate(self):
     super(ConnectSsh, self).validate()
     params = self._check_params()
     self.errors = infrastructure_error('ssh')
     if 'host' in self.job.device['actions']['deploy']['methods']['ssh']:
         self.primary = True
         self.host = self.job.device['actions']['deploy']['methods']['ssh']['host']
     if self.valid:
         self.command = ['ssh']
         if 'options' in params:
             self.command.extend(params['options'])
         # add arguments to ignore host key checking of the host device
         self.command.extend(['-o', 'UserKnownHostsFile=/dev/null', '-o', 'StrictHostKeyChecking=no'])
         if self.identity_file:
             # add optional identity file
             self.command.extend(['-i', self.identity_file])
         self.command.extend(self.ssh_port)
Example #36
0
 def validate(self):
     super(ConnectSsh, self).validate()
     params = self._check_params()
     self.errors = infrastructure_error('ssh')
     if 'host' in self.job.device['actions']['deploy']['methods']['ssh']:
         self.primary = True
         self.host = self.job.device['actions']['deploy']['methods']['ssh']['host']
     if self.valid:
         self.command = ['ssh']
         if 'options' in params:
             self.command.extend(params['options'])
         # add arguments to ignore host key checking of the host device
         self.command.extend(['-o', 'UserKnownHostsFile=/dev/null', '-o', 'StrictHostKeyChecking=no'])
         if self.identity_file:
             # add optional identity file
             self.command.extend(['-i', self.identity_file])
         self.command.extend(self.ssh_port)
Example #37
0
class TestKvmUefi(StdoutTestCase):  # pylint: disable=too-many-public-methods
    def setUp(self):
        super(TestKvmUefi, self).setUp()
        factory = Factory()
        self.job = factory.create_kvm_job('sample_jobs/kvm-uefi.yaml',
                                          mkdtemp())

    @unittest.skipIf(infrastructure_error('qemu-system-x86_64'),
                     'qemu-system-x86_64 not installed')
    def test_uefi_path(self):
        deploy = [
            action for action in self.job.pipeline.actions
            if action.name == 'deployimages'
        ][0]
        downloaders = [
            action for action in deploy.internal_pipeline.actions
            if action.name == 'download-retry'
        ]
        self.assertEqual(len(downloaders), 2)
        uefi_download = downloaders[0]
        image_download = downloaders[1]
        self.assertEqual(image_download.key, 'disk1')
        uefi_dir = uefi_download.get_namespace_data(action='deployimages',
                                                    label='image',
                                                    key='uefi_dir')
        self.assertIsNotNone(uefi_dir)
        self.assertTrue(
            os.path.exists(uefi_dir)
        )  # no download has taken place, but the directory needs to exist
        self.assertFalse(uefi_dir.endswith('bios-256k.bin'))
        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.assertIn('-L', execute.sub_command)
        self.assertIn(uefi_dir, execute.sub_command)
Example #38
0
 def validate(self):
     super(CompressRamdisk, self).validate()
     if not self.parameters.get('ramdisk', None):  # idempotency
         return
     if 'parameters' in self.job.device['actions']['deploy']:
         self.add_header = self.job.device['actions']['deploy'][
             'parameters'].get('add_header', None)
         if self.add_header is not None:
             if self.add_header == 'u-boot':
                 self.errors = infrastructure_error('mkimage')
                 if 'mkimage_arch' not in self.job.device['actions'][
                         'deploy']['parameters']:
                     self.errors = "Missing architecture for uboot mkimage support (mkimage_arch in deploy parameters)"
                     return
                 self.mkimage_arch = self.job.device['actions']['deploy'][
                     'parameters']['mkimage_arch']
             else:
                 self.errors = "ramdisk: add_header: unknown header type"
Example #39
0
 def validate(self):
     super(Scp, self).validate()
     params = self._check_params()
     self.errors = infrastructure_error('scp')
     if 'ssh' not in self.job.device['actions']['deploy']['methods']:
         self.errors = "Unable to use %s without ssh deployment" % self.name
     if 'ssh' not in self.job.device['actions']['boot']['methods']:
         self.errors = "Unable to use %s without ssh boot" % self.name
     if self.get_common_data("prepare-scp-overlay", self.key):
         self.primary = False
     elif 'host' not in self.job.device['actions']['deploy']['methods']['ssh']:
         self.errors = "Invalid device or job configuration, missing host."
     if not self.primary and len(
             self.get_common_data("prepare-scp-overlay", self.key)) != 1:
         self.errors = "Invalid number of host_keys"
     if self.valid:
         self.scp.append('scp')
         self.scp.extend(params['options'])
Example #40
0
 def validate(self):
     super(LxcAction, self).validate()
     if LxcProtocol.name not in [
             protocol.name for protocol in self.job.protocols
     ]:
         self.errors = "Invalid job - missing protocol"
     self.errors = infrastructure_error('lxc-create')
     lava_test_results_dir = self.parameters['deployment_data'][
         'lava_test_results_dir']
     lava_test_results_dir = lava_test_results_dir % self.job.job_id
     self.data['lava_test_results_dir'] = lava_test_results_dir
     namespace = self.parameters.get('namespace', None)
     if namespace:
         self.action_namespaces.append(namespace)
         self.set_common_data(namespace, 'lava_test_results_dir',
                              lava_test_results_dir)
         lava_test_sh_cmd = self.parameters['deployment_data'][
             'lava_test_sh_cmd']
         self.set_common_data(namespace, 'lava_test_sh_cmd',
                              lava_test_sh_cmd)
Example #41
0
 def validate(self):
     """
     The unit test skips if schroot is not installed, the action marks the
     pipeline as invalid if schroot is not installed.
     """
     if 'schroot' not in self.parameters:
         return
     if 'schroot' not in self.job.device['actions']['boot']['methods']:
         self.errors = "No schroot support in device boot methods"
         return
     self.errors = infrastructure_error('schroot')
     # device parameters are for ssh
     params = self.job.device['actions']['boot']['methods']
     if 'command' not in params['schroot']:
         self.errors = "Missing schroot command in device configuration"
         return
     if 'name' not in params['schroot']:
         self.errors = "Missing schroot name in device configuration"
         return
     self.schroot = params['schroot']['name']
     self.command = params['schroot']['command']
Example #42
0
 def validate(self):
     """
     The unit test skips if schroot is not installed, the action marks the
     pipeline as invalid if schroot is not installed.
     """
     if 'schroot' not in self.parameters:
         return
     if 'schroot' not in self.job.device['actions']['boot']['methods']:
         self.errors = "No schroot support in device boot methods"
         return
     self.errors = infrastructure_error('schroot')
     # device parameters are for ssh
     params = self.job.device['actions']['boot']['methods']
     if 'command' not in params['schroot']:
         self.errors = "Missing schroot command in device configuration"
         return
     if 'name' not in params['schroot']:
         self.errors = "Missing schroot name in device configuration"
         return
     self.schroot = params['schroot']['name']
     self.command = params['schroot']['command']
Example #43
0
 def validate(self):
     super(MonitorPyOCDAction, self).validate()
     boot = self.job.device['actions']['boot']['methods']['pyocd']
     pyocd_binary = boot['parameters']['command']
     self.errors = infrastructure_error(pyocd_binary)
     self.sub_command = ['flock -o /var/lock/lava-pyocd.lck', pyocd_binary]
     self.sub_command.extend(boot['parameters'].get('options', []))
     if self.job.device['board_id'] == '0000000000':
         self.errors = "board_id unset"
     substitutions = {}
     commands = ['-b ' + self.job.device['board_id']]
     for action in self.data['download_action'].keys():
         image_arg = self.data['download_action'][action].get('image_arg', None)
         action_arg = self.data['download_action'][action].get('file', None)
         if not image_arg or not action_arg:
             self.errors = "Missing image_arg for %s. " % action
             continue
         substitutions["{%s}" % action] = action_arg
         commands.append(image_arg)
     self.sub_command.extend(substitute(commands, substitutions))
     if not self.sub_command:
         self.errors = "No PyOCD command to execute"
Example #44
0
    def validate(self):
        super(TftpAction, self).validate()
        if "kernel" not in self.parameters:
            self.errors = "%s needs a kernel to deploy" % self.name
        if not self.valid:
            return
        if "nfsrootfs" in self.parameters and "nfs_url" in self.parameters:
            self.errors = "Only one of nfsrootfs or nfs_url can be specified"
        lava_test_results_dir = self.parameters["deployment_data"]["lava_test_results_dir"]
        self.data["lava_test_results_dir"] = lava_test_results_dir % self.job.job_id
        # Extract the 3 last path elements. See action.mkdtemp()
        suffix = os.path.join(*self.tftp_dir.split("/")[-2:])
        self.data[self.name].setdefault("suffix", suffix)
        self.errors = infrastructure_error("in.tftpd")

        # Check that the tmp directory is in the tftpd_dir or in /tmp for the
        # unit tests
        tftpd_directory = os.path.realpath(tftpd_dir())
        tftp_dir = os.path.realpath(self.tftp_dir)
        tmp_dir = tempfile.gettempdir()
        if not tftp_dir.startswith(tftpd_directory) and not tftp_dir.startswith(tmp_dir):
            self.errors = "tftpd directory is not configured correctly, see /etc/default/tftpd-hpa"
Example #45
0
 def validate(self):
     super(MonitorPyOCDAction, self).validate()
     boot = self.job.device['actions']['boot']['methods']['pyocd']
     pyocd_binary = boot['parameters']['command']
     self.errors = infrastructure_error(pyocd_binary)
     self.sub_command = ['flock -o /var/lock/lava-pyocd.lck', pyocd_binary]
     self.sub_command.extend(boot['parameters'].get('options', []))
     if self.job.device['board_id'] == '0000000000':
         self.errors = "board_id unset"
     substitutions = {}
     commands = ['-b ' + self.job.device['board_id']]
     for action in self.data['download_action'].keys():
         image_arg = self.data['download_action'][action].get(
             'image_arg', None)
         action_arg = self.data['download_action'][action].get('file', None)
         if not image_arg or not action_arg:
             self.errors = "Missing image_arg for %s. " % action
             continue
         substitutions["{%s}" % action] = action_arg
         commands.append(image_arg)
     self.sub_command.extend(substitute(commands, substitutions))
     if not self.sub_command:
         self.errors = "No PyOCD command to execute"
Example #46
0
class TestDefinitionParams(StdoutTestCase):  # pylint: disable=too-many-public-methods

    def setUp(self):
        super(TestDefinitionParams, self).setUp()
        self.factory = Factory()
        self.job = self.factory.create_kvm_job('sample_jobs/kvm-params.yaml')

    def test_job_without_tests(self):
        boot = finalize = None
        allow_missing_path(self.job.pipeline.validate_actions, self, 'qemu-system-x86_64')
        deploy = [action for action in self.job.pipeline.actions if action.name == 'deployimages'][0]
        overlay = [action for action in deploy.internal_pipeline.actions if action.name == 'lava-overlay'][0]
        testdef = [action for action in overlay.internal_pipeline.actions if action.name == 'test-definition'][0]
        for action in self.job.pipeline.actions:
            self.assertNotIsInstance(action, TestDefinitionAction)
            self.assertNotIsInstance(action, OverlayAction)
            boot = self.job.pipeline.actions[1]
            finalize = self.job.pipeline.actions[3]
        self.assertIsInstance(overlay, OverlayAction)
        self.assertIsInstance(testdef, TestDefinitionAction)
        test = testdef.internal_pipeline.actions[1]
        install = testdef.internal_pipeline.actions[2]
        runsh = testdef.internal_pipeline.actions[3]
        self.assertIsInstance(deploy, DeployImagesAction)
        self.assertIsInstance(boot, BootAction)
        self.assertIsInstance(finalize, FinalizeAction)
        self.assertEqual(len(self.job.pipeline.actions), 4)  # deploy, boot, test, finalize
        self.assertNotIn('test_params', testdef.parameters)
        self.assertIsInstance(install, TestInstallAction)
        self.assertIsInstance(runsh, TestRunnerAction)
        self.assertIsNot(list(install.parameters.items()), [])
        testdef = {'params': {'VARIABLE_NAME_1': 'value_1',
                              'VARIABLE_NAME_2': 'value_2'}}
        content = test.handle_parameters(testdef)
        self.assertEqual(
            set(content),
            {
                '###default parameters from test definition###\n',
                "VARIABLE_NAME_1='value_1'\n", "VARIABLE_NAME_2='value_2'\n",
                '######\n', '###test parameters from job submission###\n',
                "VARIABLE_NAME_1='eth2'\n", "VARIABLE_NAME_2='wlan0'\n",
                '######\n'
            }
        )
        testdef = {'parameters': {'VARIABLE_NAME_1': 'value_1',
                                  'VARIABLE_NAME_2': 'value_2'}}
        content = test.handle_parameters(testdef)
        self.assertEqual(
            set(content),
            {
                '###default parameters from test definition###\n',
                "VARIABLE_NAME_1='value_1'\n", "VARIABLE_NAME_2='value_2'\n",
                '######\n', '###test parameters from job submission###\n',
                "VARIABLE_NAME_1='eth2'\n", "VARIABLE_NAME_2='wlan0'\n",
                '######\n'
            }
        )

    @unittest.skipIf(infrastructure_error('git'), 'git not installed')
    def test_install_repos(self):
        job = self.factory.create_kvm_job('sample_jobs/kvm-install.yaml')
        allow_missing_path(self.job.pipeline.validate_actions, self, 'qemu-system-x86_64')
        deploy = [action for action in job.pipeline.actions if action.name == 'deployimages'][0]
        overlay = [action for action in deploy.internal_pipeline.actions if action.name == 'lava-overlay'][0]
        testdef = [action for action in overlay.internal_pipeline.actions if action.name == 'test-definition'][0]
        test_install = [
            action for action in testdef.internal_pipeline.actions
            if action.name == 'test-install-overlay'][0]
        self.assertIsNotNone(test_install)
        yaml_file = os.path.join(os.path.dirname(__file__), './testdefs/install.yaml')
        self.assertTrue(os.path.exists(yaml_file))
        with open(yaml_file, 'r') as test_file:
            testdef = yaml.safe_load(test_file)
        repos = testdef['install'].get('git-repos', [])
        self.assertIsNotNone(repos)
        self.assertIsInstance(repos, list)
        for repo in repos:
            self.assertIsNotNone(repo)
        runner_path = tempfile.mkdtemp()
        test_install.install_git_repos(testdef, runner_path)
        shutil.rmtree(runner_path)
Example #47
0
def check_missing_path(testcase, exception, path):
    if isinstance(exception, InfrastructureError):
        if not infrastructure_error(path):
            testcase.fail(exception)
Example #48
0
def allow_missing_path(function, testcase, path):
    try:
        function()
    except InfrastructureError as exc:
        if not infrastructure_error(path):
            testcase.fail(exc)
Example #49
0
class TestQemuNFS(StdoutTestCase):
    def setUp(self):
        super(TestQemuNFS, self).setUp()
        device = NewDevice(
            os.path.join(os.path.dirname(__file__), '../devices/kvm03.yaml'))
        kvm_yaml = os.path.join(os.path.dirname(__file__),
                                'sample_jobs/qemu-nfs.yaml')
        parser = JobParser()
        try:
            with open(kvm_yaml) as sample_job_data:
                job = parser.parse(sample_job_data,
                                   device,
                                   4212,
                                   None,
                                   "",
                                   output_dir=mkdtemp())
        except NotImplementedError as exc:
            print(exc)
            # some deployments listed in basics.yaml are not implemented yet
            return None
        self.job = job
        self.job.logger = DummyLogger()

    @unittest.skipIf(infrastructure_error('qemu-system-aarch64'),
                     'qemu-system-arm not installed')
    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)
Example #50
0
 def validate(self):
     super(FastbootAction, self).validate()
     self.errors = infrastructure_error('adb')
     self.errors = infrastructure_error('fastboot')
     lava_test_results_dir = self.parameters['deployment_data']['lava_test_results_dir']
     self.data['lava_test_results_dir'] = lava_test_results_dir % self.job.job_id
Example #51
0
class TestDeviceEnvironment(StdoutTestCase):  # pylint: disable=too-many-public-methods
    """
    Test parsing of device environment support
    """
    def test_empty_device_environment(self):
        data = None
        job_parser = JobParser()
        device = NewDevice(
            os.path.join(os.path.dirname(__file__), '../devices/bbb-01.yaml'))
        sample_job_file = os.path.join(os.path.dirname(__file__),
                                       'sample_jobs/uboot-ramdisk.yaml')
        with open(sample_job_file) as sample_job_data:
            job = job_parser.parse(sample_job_data,
                                   device,
                                   4212,
                                   None,
                                   "",
                                   output_dir='/tmp',
                                   env_dut=data)
        self.assertEqual(job.parameters['env_dut'], None)

    @unittest.skipIf(infrastructure_error('mkimage'),
                     "u-boot-tools not installed")
    def test_device_environment_validity(self):  # pylint: disable=invalid-name
        """
        Use non-YAML syntax a bit like existing device config syntax.
        Ensure this syntax is picked up as invalid.
        """
        data = """
# YAML syntax.
overrides:
 DEBEMAIL = "*****@*****.**"
 DEBFULLNAME: "Neil Williams"
        """
        job_parser = JobParser()
        device = NewDevice(
            os.path.join(os.path.dirname(__file__), '../devices/bbb-01.yaml'))
        sample_job_file = os.path.join(os.path.dirname(__file__),
                                       'sample_jobs/uboot-ramdisk.yaml')
        with open(sample_job_file) as sample_job_data:
            job = job_parser.parse(sample_job_data,
                                   device,
                                   4212,
                                   None,
                                   "",
                                   output_dir='/tmp',
                                   env_dut=data)
        job.logger = DummyLogger()
        self.assertEqual(job.parameters['env_dut'], data)
        with self.assertRaises(JobError):
            job.validate()

    @unittest.skipIf(infrastructure_error('mkimage'),
                     "u-boot-tools not installed")
    def test_device_environment(self):
        data = """
# YAML syntax.
overrides:
 DEBEMAIL: "*****@*****.**"
 DEBFULLNAME: "Neil Williams"
        """
        job_parser = JobParser()
        device = NewDevice(
            os.path.join(os.path.dirname(__file__), '../devices/bbb-01.yaml'))
        sample_job_file = os.path.join(os.path.dirname(__file__),
                                       'sample_jobs/uboot-ramdisk.yaml')
        with open(sample_job_file) as sample_job_data:
            job = job_parser.parse(sample_job_data,
                                   device,
                                   4212,
                                   None,
                                   "",
                                   output_dir='/tmp',
                                   env_dut=data)
        job.logger = DummyLogger()
        self.assertEqual(job.parameters['env_dut'], data)
        job.validate()
        boot_actions = [
            action.internal_pipeline.actions for action in job.pipeline.actions
            if action.name == 'uboot-action'
        ][0]
        retry = [
            action for action in boot_actions if action.name == 'uboot-retry'
        ][0]
        boot_env = [
            action for action in retry.internal_pipeline.actions
            if action.name == 'export-device-env'
        ][0]
        found = False
        for line in boot_env.env:
            if 'DEBFULLNAME' in line:
                found = True
                # assert that the string containing a space still contains that space and is quoted
                self.assertIn('\\\'Neil Williams\\\'', line)
        self.assertTrue(found)
Example #52
0
 def validate(self):
     super(ApplyLxcOverlay, self).validate()
     self.errors = infrastructure_error('tar')
Example #53
0
class MasterTest(TestCaseWithFactory):  # pylint: disable=too-many-ancestors

    def setUp(self):
        super(MasterTest, self).setUp()
        self.factory = YamlFactory()
        jinja_template_path(system=False)
        self.device_type = self.factory.make_device_type()
        self.conf = {
            'arch': 'amd64',
            'extends': 'qemu.jinja2',
            'mac_addr': '52:54:00:12:34:59',
            'memory': '256',
        }
        self.worker, _ = Worker.objects.get_or_create(hostname='localhost')
        self.remote, _ = Worker.objects.get_or_create(hostname='remote')
        # exclude remote from the list
        self.dispatchers = [self.worker.hostname]
        logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
        logger = logging.getLogger('unittests')
        logger.disabled = True
        logger.propagate = False
        logger = logging.getLogger('dispatcher')
        logging.disable(logging.DEBUG)
        logger.disabled = True
        logger.propagate = False

    def restart(self):  # pylint: disable=no-self-use
        # make sure the DB is in a clean state wrt devices and jobs
        Device.objects.all().delete()  # pylint: disable=no-member
        TestJob.objects.all().delete()  # pylint: disable=no-member
        Tag.objects.all().delete()

    @unittest.skipIf(infrastructure_error('qemu-system-x86_64'),
                     'qemu-system-x86_64 not installed')
    def test_select_device(self):
        self.restart()
        hostname = 'fakeqemu3'
        device_dict = DeviceDictionary(hostname=hostname)
        device_dict.parameters = self.conf
        device_dict.save()
        device = self.factory.make_device(self.device_type, hostname)
        job = TestJob.from_yaml_and_user(
            self.factory.make_job_yaml(),
            self.factory.make_user())
        # this uses the system jinja2 path - local changes to the qemu.jinja2
        # will not be available.
        selected = select_device(job, self.dispatchers)
        self.assertIsNone(selected)
        job.actual_device = device
        selected = select_device(job, self.dispatchers)
        self.assertIsNone(selected)
        device.worker_host = self.worker
        selected = select_device(job, self.dispatchers)
        self.assertIsNone(selected)
        # device needs to be in reserved state
        # fake up the assignment which needs a separate test
        job.actual_device = device
        job.save()
        device.current_job = job
        device.status = Device.RESERVED
        device.save()
        selected = select_device(job, self.dispatchers)
        self.assertEqual(selected, device)
        # print(selected)  # pylint: disable=superfluous-parens

    def test_job_handlers(self):
        self.restart()
        hostname = 'fakeqemu3'
        device_dict = DeviceDictionary(hostname=hostname)
        device_dict.parameters = self.conf
        device_dict.save()
        device = self.factory.make_device(self.device_type, hostname)
        job = TestJob.from_yaml_and_user(
            self.factory.make_job_yaml(),
            self.factory.make_user())
        selected = select_device(job, self.dispatchers)
        self.assertIsNone(selected)
        job.actual_device = device
        selected = select_device(job, self.dispatchers)
        self.assertIsNone(selected)
        device.worker_host = self.worker
        selected = select_device(job, self.dispatchers)
        self.assertIsNone(selected)
        create_job(job, device)
        self.assertEqual(job.actual_device, device)
        self.assertEqual(device.status, Device.RESERVED)

    def test_dispatcher_restart(self):
        self.restart()
        hostname = 'fakeqemu4'
        device_dict = DeviceDictionary(hostname=hostname)
        device_dict.parameters = self.conf
        device_dict.save()
        device = self.factory.make_device(self.device_type, hostname)
        job = TestJob.from_yaml_and_user(
            self.factory.make_job_yaml(),
            self.factory.make_user())
        job.actual_device = device
        self.assertEqual(job.status, TestJob.SUBMITTED)
        device.worker_host = self.remote
        selected = select_device(job, self.dispatchers)
        self.assertIsNone(selected)
        self.assertEqual(job.status, TestJob.SUBMITTED)
        create_job(job, device)
        self.assertEqual(job.actual_device, device)
        self.assertEqual(device.status, Device.RESERVED)
        selected = select_device(job, self.dispatchers)
        self.assertIsNone(selected)
        self.assertEqual(job.status, TestJob.SUBMITTED)
Example #54
0
 def validate(self):
     super(LxcStop, self).validate()
     self.errors = infrastructure_error('lxc-stop')
Example #55
0
 def validate(self):
     super(LxcDestroy, self).validate()
     self.errors = infrastructure_error('lxc-destroy')
Example #56
0
def check_missing_path(testcase, exception, path):
    if isinstance(exception, InfrastructureError):
        if not infrastructure_error(path):
            testcase.fail(exception)
Example #57
0
def allow_missing_path(function, testcase, path):
    try:
        function()
    except InfrastructureError as exc:
        if not infrastructure_error(path):
            testcase.fail(exc)
Example #58
0
 def validate(self):
     super(LxcStartAction, self).validate()
     self.errors = infrastructure_error('lxc-start')
Example #59
0
 def validate(self):
     super(ConnectLxc, self).validate()
     self.errors = infrastructure_error('lxc-attach')
     if 'prompts' not in self.parameters:
         self.errors = "Unable to identify test image prompts from parameters."
Example #60
0
class TestUbootAction(StdoutTestCase):  # pylint: disable=too-many-public-methods
    def setUp(self):
        super(TestUbootAction, self).setUp()
        self.factory = UBootFactory()

    @unittest.skipIf(infrastructure_error('mkimage'),
                     "u-boot-tools not installed")
    def test_simulated_action(self):
        job = self.factory.create_bbb_job('sample_jobs/uboot-ramdisk.yaml')
        self.assertIsNotNone(job)

        # uboot and uboot-ramdisk have the same pipeline structure
        description_ref = self.pipeline_reference('uboot.yaml', job=job)
        self.assertEqual(description_ref, job.pipeline.describe(False))

        self.assertIsNone(job.validate())
        self.assertEqual(job.device['device_type'], 'beaglebone-black')

    def test_tftp_pipeline(self):
        job = self.factory.create_bbb_job('sample_jobs/uboot-ramdisk.yaml')
        self.assertEqual(
            [action.name for action in job.pipeline.actions],
            ['tftp-deploy', 'uboot-action', 'lava-test-retry', 'finalize'])
        tftp = [
            action for action in job.pipeline.actions
            if action.name == 'tftp-deploy'
        ][0]
        self.assertTrue(
            tftp.get_namespace_data(action=tftp.name,
                                    label='tftp',
                                    key='ramdisk'))
        self.assertIsNotNone(tftp.internal_pipeline)
        self.assertEqual(
            [action.name for action in tftp.internal_pipeline.actions], [
                'download-retry', 'download-retry', 'download-retry',
                'prepare-tftp-overlay', 'lxc-add-device-action',
                'deploy-device-env'
            ])
        self.assertIn('ramdisk', [
            action.key for action in tftp.internal_pipeline.actions
            if hasattr(action, 'key')
        ])
        self.assertIn('kernel', [
            action.key for action in tftp.internal_pipeline.actions
            if hasattr(action, 'key')
        ])
        self.assertIn('dtb', [
            action.key for action in tftp.internal_pipeline.actions
            if hasattr(action, 'key')
        ])
        self.assertNotIn('=', tftpd_dir())
        job.validate()
        tftp.validate()
        self.assertEqual([], tftp.errors)

    def test_device_bbb(self):
        job = self.factory.create_bbb_job('sample_jobs/uboot.yaml')
        self.assertEqual(job.device['commands']['connect'],
                         'telnet localhost 6000')
        self.assertEqual(job.device['commands'].get('interrupt', ' '), ' ')
        methods = job.device['actions']['boot']['methods']
        self.assertIn('u-boot', methods)
        self.assertEqual(
            methods['u-boot']['parameters'].get('bootloader_prompt', None),
            'U-Boot')

    @unittest.skipIf(infrastructure_error('mkimage'),
                     "u-boot-tools not installed")
    def test_uboot_action(self):
        job = self.factory.create_bbb_job('sample_jobs/uboot-ramdisk.yaml')
        job.validate()
        self.assertEqual(job.pipeline.errors, [])
        self.assertIn('u-boot', job.device['actions']['boot']['methods'])
        params = job.device['actions']['deploy']['parameters']
        self.assertIn('mkimage_arch', params)
        boot_message = params.get('boot_message',
                                  job.device.get_constant('boot-message'))
        self.assertIsNotNone(boot_message)
        for action in job.pipeline.actions:
            action.validate()
            if isinstance(action, UBootAction):
                self.assertIn('method', action.parameters)
                self.assertEqual('u-boot', action.parameters['method'])
                self.assertEqual(
                    'reboot: Restarting system',
                    action.parameters.get('parameters', {}).get(
                        'shutdown-message',
                        job.device.get_constant('shutdown-message')))
            if isinstance(action, TftpAction):
                self.assertIn('ramdisk', action.parameters)
                self.assertIn('kernel', action.parameters)
                self.assertIn('to', action.parameters)
                self.assertEqual('tftp', action.parameters['to'])
            if isinstance(action, CompressRamdisk):
                self.assertEqual(action.mkimage_arch, 'arm')
            self.assertTrue(action.valid)

    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)

    def test_boot_commands(self):
        job = self.factory.create_bbb_job(
            'sample_jobs/uboot-ramdisk-inline-commands.yaml')
        job.validate()
        uboot = [
            action for action in job.pipeline.actions
            if action.name == 'uboot-action'
        ][0]
        overlay = [
            action for action in uboot.internal_pipeline.actions
            if action.name == 'bootloader-overlay'
        ][0]
        self.assertEqual(
            overlay.commands,
            ['a list', 'of commands', 'with a {KERNEL_ADDR} substitution'])

    def test_transfer_media(self):
        """
        Test adding the overlay to existing rootfs
        """
        job = self.factory.create_bbb_job(
            'sample_jobs/uboot-ramdisk-inline-commands.yaml')
        job.validate()
        description_ref = self.pipeline_reference(
            'uboot-ramdisk-inline-commands.yaml', job=job)
        self.assertEqual(description_ref, job.pipeline.describe(False))
        uboot = [
            action for action in job.pipeline.actions
            if action.name == 'uboot-action'
        ][0]
        retry = [
            action for action in uboot.internal_pipeline.actions
            if action.name == 'uboot-retry'
        ][0]
        transfer = [
            action for action in retry.internal_pipeline.actions
            if action.name == 'overlay-unpack'
        ][0]
        self.assertIn('transfer_overlay', transfer.parameters)
        self.assertIn('download_command',
                      transfer.parameters['transfer_overlay'])
        self.assertIn('unpack_command',
                      transfer.parameters['transfer_overlay'])

    def test_download_action(self):
        job = self.factory.create_bbb_job('sample_jobs/uboot.yaml')
        for action in job.pipeline.actions:
            action.validate()
            self.assertTrue(action.valid)
        job.validate()
        self.assertEqual(job.pipeline.errors, [])
        deploy = None
        overlay = None
        extract = None
        for action in job.pipeline.actions:
            if action.name == 'tftp-deploy':
                deploy = action
        if deploy:
            for action in deploy.internal_pipeline.actions:
                if action.name == 'prepare-tftp-overlay':
                    overlay = action
        if overlay:
            for action in overlay.internal_pipeline.actions:
                if action.name == 'extract-nfsrootfs':
                    extract = action
        test_dir = overlay.get_namespace_data(action='test',
                                              label='results',
                                              key='lava_test_results_dir')
        self.assertIsNotNone(test_dir)
        self.assertIn('/lava-', test_dir)
        self.assertIsNotNone(extract)
        self.assertEqual(extract.timeout.duration, 240)

    def test_reset_actions(self):
        job = self.factory.create_bbb_job('sample_jobs/uboot.yaml')
        uboot_action = None
        uboot_retry = None
        reset_action = None
        for action in job.pipeline.actions:
            action.validate()
            self.assertTrue(action.valid)
            if action.name == 'uboot-action':
                uboot_action = action
        names = [
            r_action.name
            for r_action in uboot_action.internal_pipeline.actions
        ]
        self.assertIn('connect-device', names)
        self.assertIn('uboot-retry', names)
        for action in uboot_action.internal_pipeline.actions:
            if action.name == 'uboot-retry':
                uboot_retry = action
        names = [
            r_action.name for r_action in uboot_retry.internal_pipeline.actions
        ]
        self.assertIn('reset-device', names)
        self.assertIn('u-boot-interrupt', names)
        self.assertIn('expect-shell-connection', names)
        self.assertIn('bootloader-commands', names)
        for action in uboot_retry.internal_pipeline.actions:
            if action.name == 'reset-device':
                reset_action = action
        names = [
            r_action.name
            for r_action in reset_action.internal_pipeline.actions
        ]
        self.assertIn('pdu-reboot', names)

    def test_secondary_media(self):
        """
        Test UBootSecondaryMedia validation
        """
        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')
        sample_job_data = open(sample_job_file)
        job = job_parser.parse(sample_job_data,
                               cubie,
                               4212,
                               None,
                               "",
                               output_dir='/tmp/')
        job.logger = DummyLogger()
        job.validate()
        sample_job_data.close()
        u_boot_media = [
            action for action in job.pipeline.actions
            if action.name == 'uboot-action'
        ][1].internal_pipeline.actions[0]
        self.assertIsInstance(u_boot_media, UBootSecondaryMedia)
        self.assertEqual([], u_boot_media.errors)
        self.assertEqual(u_boot_media.parameters['kernel'],
                         '/boot/vmlinuz-3.16.0-4-armmp-lpae')
        self.assertEqual(
            u_boot_media.parameters['kernel'],
            u_boot_media.get_namespace_data(action=u_boot_media.name,
                                            label='file',
                                            key='kernel'))
        self.assertEqual(
            u_boot_media.parameters['ramdisk'],
            u_boot_media.get_namespace_data(action=u_boot_media.name,
                                            label='file',
                                            key='ramdisk'))
        self.assertEqual(
            u_boot_media.parameters['dtb'],
            u_boot_media.get_namespace_data(action=u_boot_media.name,
                                            label='file',
                                            key='dtb'))
        self.assertEqual(
            u_boot_media.parameters['root_uuid'],
            u_boot_media.get_namespace_data(action=u_boot_media.name,
                                            label='uuid',
                                            key='root'))
        device = u_boot_media.get_namespace_data(action='storage-deploy',
                                                 label='u-boot',
                                                 key='device')
        self.assertIsNotNone(device)
        part_reference = '%s:%s' % (
            job.device['parameters']['media']['usb'][device]['device_id'],
            u_boot_media.parameters['boot_part'])
        self.assertEqual(
            part_reference,
            u_boot_media.get_namespace_data(action=u_boot_media.name,
                                            label='uuid',
                                            key='boot_part'))
        self.assertEqual(part_reference, "0:1")

    def test_xz_nfs(self):
        job = self.factory.create_bbb_job('sample_jobs/uboot-nfs.yaml')
        # this job won't validate as the .xz nfsrootfs URL is a fiction
        self.assertRaises(JobError, job.validate)
        tftp_deploy = [
            action for action in job.pipeline.actions
            if action.name == 'tftp-deploy'
        ][0]
        prepare = [
            action for action in tftp_deploy.internal_pipeline.actions
            if action.name == 'prepare-tftp-overlay'
        ][0]
        nfs = [
            action for action in prepare.internal_pipeline.actions
            if action.name == 'extract-nfsrootfs'
        ][0]
        self.assertIn('compression', nfs.parameters['nfsrootfs'])
        self.assertEqual(nfs.parameters['nfsrootfs']['compression'], 'xz')

    def test_prefix(self):
        job = self.factory.create_bbb_job('sample_jobs/bbb-skip-install.yaml')
        job.validate()
        tftp_deploy = [
            action for action in job.pipeline.actions
            if action.name == 'tftp-deploy'
        ][0]
        prepare = [
            action for action in tftp_deploy.internal_pipeline.actions
            if action.name == 'prepare-tftp-overlay'
        ][0]
        nfs = [
            action for action in prepare.internal_pipeline.actions
            if action.name == 'extract-nfsrootfs'
        ][0]
        self.assertIn('prefix', nfs.parameters['nfsrootfs'])
        self.assertEqual(nfs.parameters['nfsrootfs']['prefix'], 'jessie/')
        self.assertEqual(nfs.param_key, 'nfsrootfs')