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)
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"
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"
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
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
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."
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."
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'])
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'])
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"
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"
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(ConnectSsh, self).validate() params = self._check_params() self.errors = infrastructure_error('ssh') if self.valid: self.command = ['ssh'] self.command.extend(params['options'])
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"
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
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"
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')
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']
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"
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'])
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')
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)
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)
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)
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)
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)
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)
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)
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
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)
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"
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)
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)
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)
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)
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)
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"
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'])
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)
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']
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']
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"
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"
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"
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)
def check_missing_path(testcase, exception, path): if isinstance(exception, InfrastructureError): if not infrastructure_error(path): testcase.fail(exception)
def allow_missing_path(function, testcase, path): try: function() except InfrastructureError as exc: if not infrastructure_error(path): testcase.fail(exc)
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)
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
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)
def validate(self): super(ApplyLxcOverlay, self).validate() self.errors = infrastructure_error('tar')
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)
def validate(self): super(LxcStop, self).validate() self.errors = infrastructure_error('lxc-stop')
def validate(self): super(LxcDestroy, self).validate() self.errors = infrastructure_error('lxc-destroy')
def check_missing_path(testcase, exception, path): if isinstance(exception, InfrastructureError): if not infrastructure_error(path): testcase.fail(exception)
def allow_missing_path(function, testcase, path): try: function() except InfrastructureError as exc: if not infrastructure_error(path): testcase.fail(exc)
def validate(self): super(LxcStartAction, self).validate() self.errors = infrastructure_error('lxc-start')
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."
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')