def validate(self): super(NbdAction, self).validate() if 'kernel' not in self.parameters: self.errors = "%s needs a kernel to deploy" % self.name if not self.valid: return if 'nbdroot' not in self.parameters: self.errors = "NBD deployment needs a 'nbdroot' parameter" if 'initrd' not in self.parameters: self.errors = "NBD deployment needs an 'initrd' parameter" # we cannot work with these when using nbd if 'nfsrootfs' in self.parameters or 'nfs_url' in self.parameters: self.errors = "nfsrootfs or nfs_url cannot be used with NBD deployment, use a e.g. ext3/4 filesystem as 'nbdroot=' parameter" if 'ramdisk' in self.parameters: self.errors = "ramdisk cannot be used with NBD deployment, use a e.g. ext3/4 filesystem as 'initrd' parameter" # Extract the 3 last path elements. See action.mkdtemp() suffix = os.path.join(*self.tftp_dir.split('/')[-2:]) self.set_namespace_data(action="tftp-deploy", label='tftp', key='suffix', value=suffix) # we need tftp _and_ xnbd-server 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"
class Pyocd_Factory(Factory): # pylint: disable=too-few-public-methods """ Not Model based, this is not a Django factory. Factory objects are dispatcher based classes, independent of any database objects. """ @unittest.skipIf(infrastructure_error('pyocd-flashtool'), 'pyocd-flashtool not installed') def create_k64f_job(self, filename): # pylint: disable=no-self-use device = NewDevice(os.path.join(os.path.dirname(__file__), '../devices/frdm-k64f-01.yaml')) y_file = os.path.join(os.path.dirname(__file__), filename) with open(y_file) as sample_job_data: parser = JobParser() job = parser.parse(sample_job_data, device, 4999, None, "") job.logger = DummyLogger() return job @unittest.skipIf(infrastructure_error('pyocd-flashtool'), 'pyocd-flashtool not installed') def create_k64f_job_with_power(self, filename): # pylint: disable=no-self-use device = NewDevice(os.path.join(os.path.dirname(__file__), '../devices/frdm-k64f-01-with-power.yaml')) y_file = os.path.join(os.path.dirname(__file__), filename) with open(y_file) as sample_job_data: parser = JobParser() job = parser.parse(sample_job_data, device, 5999, None, "") job.logger = DummyLogger() return job
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') 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)
class TestUbootUMSAction(StdoutTestCase): # pylint: disable=too-many-public-methods def setUp(self): super(TestUbootUMSAction, self).setUp() self.factory = UBootUMSFactory() @unittest.skipIf(infrastructure_error('dd'), "dd not installed") def test_ums_action(self): job = self.factory.create_warp7_job('sample_jobs/warp7-ums.yaml') self.assertIsNotNone(job) description_ref = self.pipeline_reference('uboot-ums.yaml', job=job) self.assertEqual(description_ref, job.pipeline.describe(False)) self.assertIsNone(job.validate()) self.assertEqual(job.device['device_type'], 'imx7s-warp') 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] flash = [ action for action in retry.internal_pipeline.actions if action.name == 'flash-uboot-ums' ][0] self.assertEqual("ums", flash.parameters['commands']) self.assertEqual("/dev/vde", flash.usb_mass_device)
def validate(self): super(UBootPrepareKernelAction, self).validate() if 'parameters' not in self.job.device['actions']['deploy']: return self.params = self.job.device['actions']['deploy']['parameters'] self.kernel_type = self.get_namespace_data(action='download-action', label='type', key='kernel') self.bootcommand = None if 'parameters' not in self.job.device: if self.kernel_type: self.errors = "Kernel boot type is not supported by this device." if self.kernel_type: self.set_namespace_data(action=self.name, label='prepared-kernel', key='exists', value=True) self.bootcommand = map_kernel_uboot( self.kernel_type, self.job.device.get('parameters', None)) self.kernel_type = str(self.kernel_type).lower() if self.bootcommand not in self.job.device['parameters']: self.errors = "Requested kernel boot type '%s' is not supported by this device." % self.bootcommand if self.kernel_type == "bootm" or self.kernel_type == "bootz" or self.kernel_type == "booti": self.errors = "booti, bootm and bootz are deprecated, please use 'image', 'uimage' or 'zimage'" self.errors = infrastructure_error('mkimage') if 'mkimage_arch' not in self.params: self.errors = "Missing architecture for uboot mkimage support (mkimage_arch in u-boot parameters)" if self.bootcommand == 'bootm' and self.kernel_type != 'uimage': self.mkimage_conversion = True self.set_namespace_data(action='uboot-prepare-kernel', label='bootcommand', key='bootcommand', value=self.bootcommand)
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): super(DockerAction, self).validate() err = infrastructure_error("docker") if err is not None: self.errors = err return # Print docker version try: out = subprocess.check_output( ["docker", "version", "-f", "{{.Server.Version}}"]) out = out.decode("utf-8").strip("\n") self.logger.debug("docker server, installed at version: %s", out) out = subprocess.check_output( ["docker", "version", "-f", "{{.Client.Version}}"]) out = out.decode("utf-8").strip("\n") self.logger.debug("docker client, installed at version: %s", out) except subprocess.CalledProcessError as exc: raise InfrastructureError("Unable to call '%s': %s" % (exc.cmd, exc.output)) except OSError: raise InfrastructureError("Command 'docker' does not exist") # check docker image name # The string should be safe for command line inclusion image_name = self.parameters["image"] if re.compile("^[a-z0-9._:/-]+$").match(image_name) is None: self.errors = "image_name '%s' is invalid" % image_name self.set_namespace_data(action=self.name, label='image', key='name', value=image_name)
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 _check_command(self): exe = '' try: exe = self.command.split(' ')[0] except AttributeError: self.errors = "Unable to parse the connection command %s" % self.command self.errors = infrastructure_error(exe)
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(LxcAction, self).validate() self.logger.info("lxc, installed at version: %s", debian_package_version(pkg='lxc', split=False)) protocols = [protocol.name for protocol in self.job.protocols] if LxcProtocol.name not in protocols: self.logger.debug("Missing protocol '%s' in %s", LxcProtocol.name, protocols) self.errors = "Missing protocol '%s'" % LxcProtocol.name self.errors = infrastructure_error('lxc-create')
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') @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(PrepareFITAction, self).validate() self.errors = infrastructure_error('mkimage') deploy_params = self.job.device['actions']['deploy'].get('parameters') if deploy_params is None: self.errors = "Missing parameters in deploy action" elif 'mkimage_arch' not in deploy_params: self.errors = "Missing mkimage_arch parameter for FIT support" else: self.deploy_params = deploy_params device_params = self.job.device.get('parameters') if device_params is None: self.errors = "Missing device parameters" elif 'load_address' not in device_params: self.errors = "Missing load_address from device parameters" else: self.device_params = device_params
def 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(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" # If we are allowed to use a filesystem label, we don't require a board_id # By default, we do require a board_id (serial) requires_board_id = not allow_fs_label(self.job.device) try: if 'device_info' in self.job.device: for usb_device in self.job.device['device_info']: if usb_device.get('board_id', '') in ['', '0000000000'] \ and requires_board_id: self.errors = "board_id unset" if usb_device.get('usb_vendor_id', '') == '0000': self.errors = 'usb_vendor_id unset' if usb_device.get('usb_product_id', '') == '0000': self.errors = 'usb_product_id unset' except TypeError: self.errors = "Invalid parameters for %s" % self.name
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(CompressRamdisk, self).validate() if not self.parameters.get('ramdisk', None): # idempotency return if not self.parameters['ramdisk'].get('install_modules', True) and \ not self.parameters['ramdisk'].get('install_overlay', True): self.skip = True return if 'parameters' in self.job.device['actions']['deploy']: self.add_header = self.job.device['actions']['deploy'][ 'parameters'].get('add_header', None) if self.add_header is not None: if self.add_header == 'u-boot': 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(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(TftpAction, self).validate() if 'kernel' not in self.parameters: self.errors = "%s needs a kernel to deploy" % self.name if not self.valid: return if 'nfs_url' in self.parameters: self.errors = "Use a persistent_nfs dictionary instead of nfs_url" if 'nfsrootfs' in self.parameters and 'persistent_nfs' in self.parameters: self.errors = "Only one of nfsrootfs or persistent_nfs can be specified" # Extract the 3 last path elements. See action.mkdtemp() suffix = os.path.join(*self.tftp_dir.split('/')[-2:]) self.set_namespace_data(action=self.name, label='tftp', key='suffix', value=suffix) 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(ApplyOverlaySparseImage, self).validate() self.errors = infrastructure_error('/usr/bin/simg2img') self.errors = infrastructure_error('/bin/mount') self.errors = infrastructure_error('/bin/umount') self.errors = infrastructure_error('/usr/bin/img2simg')
class TestRemovable(StdoutTestCase): # pylint: disable=too-many-public-methods def test_device_parameters(self): """ Test that the correct parameters have been set for the device """ cubie = NewDevice( os.path.join(os.path.dirname(__file__), '../devices/cubie1.yaml')) self.assertIsNotNone(cubie['parameters']['media'].get('usb', None)) self.assertIsNotNone(cubie.get('commands', None)) self.assertIsNotNone(cubie.get('actions', None)) self.assertIsNotNone(cubie['actions'].get('deploy', None)) self.assertIsNotNone(cubie['actions']['deploy'].get('methods', None)) self.assertIn('usb', cubie['actions']['deploy']['methods']) self.assertIsNotNone(cubie['actions'].get('boot', None)) self.assertIsNotNone(cubie['actions']['boot'].get('methods', None)) self.assertIn('u-boot', cubie['actions']['boot']['methods']) u_boot_params = cubie['actions']['boot']['methods']['u-boot'] self.assertIn('usb', u_boot_params) self.assertIn('commands', u_boot_params['usb']) self.assertIn('parameters', u_boot_params) self.assertIn('boot_message', u_boot_params['parameters']) self.assertIn('bootloader_prompt', u_boot_params['parameters']) def _check_valid_job(self, device, test_file): self.maxDiff = None # pylint: disable=invalid-name job_parser = JobParser() sample_job_file = os.path.join(os.path.dirname(__file__), 'sample_jobs/{}'.format(test_file)) with open(sample_job_file) as sample_job_data: job = job_parser.parse(sample_job_data, device, 4212, None, "") job.logger = DummyLogger() try: job.validate() except JobError: self.fail(job.pipeline.errors) description_ref = self.pipeline_reference(test_file, job=job) self.assertEqual(description_ref, job.pipeline.describe(False)) return job def _check_job_parameters(self, device, job, agent_key): mass_storage = None # deploy for action in job.pipeline.actions: if isinstance(action, DeployAction): if isinstance(action, MassStorage): self.assertTrue(action.valid) agent = action.parameters[agent_key]['tool'] self.assertTrue( agent.startswith('/') ) # needs to be a full path but on the device, so avoid os.path self.assertIn(action.parameters['device'], job.device['parameters']['media']['usb']) mass_storage = action self.assertIsNotNone(mass_storage) self.assertIn('device', mass_storage.parameters) self.assertIn(mass_storage.parameters['device'], device['parameters']['media']['usb']) self.assertIsNotNone( mass_storage.get_namespace_data(action='storage-deploy', label='u-boot', key='device')) u_boot_params = device['actions']['boot']['methods']['u-boot'] self.assertEqual( mass_storage.get_namespace_data(action='uboot-retry', label='bootloader_prompt', key='prompt'), u_boot_params['parameters']['bootloader_prompt']) def test_job_parameters(self): """ Test that the job parameters match expected structure """ cubie = NewDevice( os.path.join(os.path.dirname(__file__), '../devices/cubie1.yaml')) job = self._check_valid_job(cubie, 'cubietruck-removable.yaml') self._check_job_parameters(cubie, job, 'download') def test_writer_job_parameters(self): """ Test that the job parameters with a writer tool match expected structure """ cubie = NewDevice( os.path.join(os.path.dirname(__file__), '../devices/cubie1.yaml')) job = self._check_valid_job(cubie, 'cubietruck-removable-with-writer.yaml') self._check_job_parameters(cubie, job, 'writer') def _check_deployment(self, device, test_file): job_parser = JobParser() job = self._check_valid_job(device, test_file) self.assertIn('usb', device['parameters']['media'].keys()) deploy_params = [ methods for methods in job.parameters['actions'] if 'deploy' in methods.keys() ][1]['deploy'] self.assertIn('device', deploy_params) self.assertIn(deploy_params['device'], device['parameters']['media']['usb']) self.assertIn( 'uuid', device['parameters']['media']['usb'][deploy_params['device']]) self.assertIn( 'device_id', device['parameters']['media']['usb'][deploy_params['device']]) self.assertNotIn( 'boot_part', device['parameters']['media']['usb'][deploy_params['device']]) deploy_action = [ action for action in job.pipeline.actions if action.name == 'storage-deploy' ][0] tftp_deploy_action = [ action for action in job.pipeline.actions if action.name == 'tftp-deploy' ][0] self.assertIsNotNone(deploy_action) test_dir = deploy_action.get_namespace_data( action='test', label='results', key='lava_test_results_dir', parameters=tftp_deploy_action.parameters) self.assertIsNotNone(test_dir) self.assertIn('/lava-', test_dir) self.assertIsInstance(deploy_action, MassStorage) img_params = deploy_action.parameters.get('images', deploy_action.parameters) self.assertIn('image', img_params) dd_action = [ action for action in deploy_action.internal_pipeline.actions if action.name == 'dd-image' ][0] self.assertEqual( dd_action.boot_params[dd_action.parameters['device']]['uuid'], 'usb-SanDisk_Ultra_20060775320F43006019-0:0') self.assertIsNotNone( dd_action.get_namespace_data(action=dd_action.name, label='u-boot', key='boot_part')) self.assertIsNotNone( dd_action.get_namespace_data(action='uboot-from-media', label='uuid', key='boot_part')) self.assertEqual( '0', '%s' % dd_action.get_namespace_data( action=dd_action.name, label='u-boot', key='boot_part')) self.assertIsInstance( dd_action.get_namespace_data(action='uboot-from-media', label='uuid', key='boot_part'), str) self.assertEqual( '0:1', dd_action.get_namespace_data(action='uboot-from-media', label='uuid', key='boot_part')) self.assertIsNotNone( dd_action.get_namespace_data(action='uboot-prepare-kernel', label='bootcommand', key='bootcommand')) def test_deployment(self): cubie = NewDevice( os.path.join(os.path.dirname(__file__), '../devices/cubie1.yaml')) self._check_deployment(cubie, 'cubietruck-removable.yaml') def test_writer_deployment(self): cubie = NewDevice( os.path.join(os.path.dirname(__file__), '../devices/cubie1.yaml')) self._check_deployment(cubie, 'cubietruck-removable-with-writer.yaml') def test_juno_deployment(self): factory = RemovableFactory() job = factory.create_job('sample_jobs/juno-uboot-removable.yaml', '../devices/juno-uboot.yaml') job.logger = DummyLogger() job.validate() self.assertEqual(job.pipeline.errors, []) self.assertIn('usb', job.device['parameters']['media'].keys()) deploy_params = [ methods for methods in job.parameters['actions'] if 'deploy' in methods.keys() ][1]['deploy'] self.assertIn('device', deploy_params) self.assertIn(deploy_params['device'], job.device['parameters']['media']['usb']) self.assertIn( 'uuid', job.device['parameters']['media']['usb'][deploy_params['device']]) self.assertIn( 'device_id', job.device['parameters']['media']['usb'][deploy_params['device']]) self.assertNotIn( 'boot_part', job.device['parameters']['media']['usb'][deploy_params['device']]) tftp_deploys = [ action for action in job.pipeline.actions if action.name == 'tftp-deploy' ] self.assertEqual(len(tftp_deploys), 2) first_deploy = tftp_deploys[0] second_deploy = tftp_deploys[1] self.assertIsNotNone(first_deploy) self.assertIsNotNone(second_deploy) self.assertEqual('openembedded', first_deploy.parameters['namespace']) self.assertEqual('android', second_deploy.parameters['namespace']) self.assertNotIn('deployment_data', first_deploy.parameters) self.assertNotIn('deployment_data', second_deploy.parameters) storage_deploy_action = [ action for action in job.pipeline.actions if action.name == 'storage-deploy' ][0] download_action = [ action for action in storage_deploy_action.internal_pipeline.actions if action.name == 'download-retry' ][0] self.assertIsNotNone(download_action) self.assertEqual('android', storage_deploy_action.parameters['namespace']) def test_mustang_deployment(self): factory = RemovableFactory() job = factory.create_job('sample_jobs/mustang-secondary-media.yaml', '../devices/mustang-media.yaml') job.validate() description_ref = self.pipeline_reference('mustang-media.yaml', job=job) self.assertEqual(description_ref, job.pipeline.describe(False)) self.assertIn('sata', job.device['parameters']['media'].keys()) deploy_params = [ methods for methods in job.parameters['actions'] if 'deploy' in methods.keys() ][1]['deploy'] self.assertIn('device', deploy_params) self.assertIn(deploy_params['device'], job.device['parameters']['media']['sata']) self.assertIn( 'uuid', job.device['parameters']['media']['sata'][deploy_params['device']]) self.assertIn( 'device_id', job.device['parameters']['media']['sata'][deploy_params['device']]) self.assertEqual( 'hd0', job.device['parameters']['media']['sata'][ deploy_params['device']]['grub_interface']) grub_deploys = [ action for action in job.pipeline.actions if action.name == 'grub-main-action' ] self.assertEqual(len(grub_deploys), 2) first_deploy = grub_deploys[0] second_deploy = grub_deploys[1] self.assertEqual('nfsdeploy', first_deploy.parameters['namespace']) self.assertEqual('satadeploy', second_deploy.parameters['namespace']) def test_secondary_media(self): factory = RemovableFactory() job = factory.create_job('sample_jobs/mustang-secondary-media.yaml', '../devices/mustang-media.yaml') job.validate() grub_nfs = [ action for action in job.pipeline.actions if action.name == 'grub-main-action' and action.parameters['namespace'] == 'nfsdeploy' ][0] media_action = [ action for action in grub_nfs.internal_pipeline.actions if action.name == 'bootloader-from-media' ][0] self.assertEqual( None, media_action.get_namespace_data(action='download-action', label='file', key='kernel')) self.assertEqual( None, media_action.get_namespace_data(action='compress-ramdisk', label='file', key='ramdisk')) self.assertEqual( None, media_action.get_namespace_data(action='download-action', label='file', key='dtb')) self.assertEqual( None, media_action.get_namespace_data(action=media_action.name, label='file', key='root')) grub_main = [ action for action in job.pipeline.actions if action.name == 'grub-main-action' and action.parameters['namespace'] == 'satadeploy' ][0] media_action = [ action for action in grub_main.internal_pipeline.actions if action.name == 'bootloader-from-media' ][0] self.assertIsInstance(media_action, BootloaderSecondaryMedia) self.assertIsNotNone( media_action.get_namespace_data(action='download-action', label='file', key='kernel')) self.assertIsNotNone( media_action.get_namespace_data(action='compress-ramdisk', label='file', key='ramdisk')) self.assertIsNotNone( media_action.get_namespace_data(action='download-action', label='file', key='ramdisk')) self.assertEqual( '', media_action.get_namespace_data(action='download-action', label='file', key='dtb')) self.assertIsNotNone( media_action.get_namespace_data(action=media_action.name, label='uuid', key='root')) self.assertIsNotNone( media_action.get_namespace_data(action=media_action.name, label='uuid', key='boot_part')) @unittest.skipIf(infrastructure_error('mkimage'), "u-boot-tools not installed") def test_primary_media(self): """ Test that definitions of secondary media do not block submissions using primary media """ job_parser = JobParser() bbb = 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, bbb, 4212, None, "") job.logger = DummyLogger() job.validate() self.assertEqual(job.pipeline.errors, []) self.assertIn('usb', bbb['parameters']['media'].keys()) def test_substitutions(self): """ Test substitution of secondary media values into u-boot commands Unlike most u-boot calls, removable knows in advance all the values it needs to substitute into the boot commands for the secondary deployment as these are fixed by the device config and the image details from the job submission. """ job_parser = JobParser() cubie = NewDevice( os.path.join(os.path.dirname(__file__), '../devices/cubie1.yaml')) sample_job_file = os.path.join( os.path.dirname(__file__), 'sample_jobs/cubietruck-removable.yaml') with open(sample_job_file) as sample_job_data: job = job_parser.parse(sample_job_data, cubie, 4212, None, "") job.logger = DummyLogger() job.validate() boot_params = [ methods for methods in job.parameters['actions'] if 'boot' in methods.keys() ][1]['boot'] self.assertIn('ramdisk', boot_params) self.assertIn('kernel', boot_params) self.assertIn('dtb', boot_params) self.assertIn('root_uuid', boot_params) self.assertIn('boot_part', boot_params) self.assertNotIn('type', boot_params) self.assertGreater(len(job.pipeline.actions), 1) self.assertIsNotNone(job.pipeline.actions[1].internal_pipeline) u_boot_action = [ action for action in job.pipeline.actions if action.name == 'uboot-action' ][1] overlay = [ action for action in u_boot_action.internal_pipeline.actions if action.name == 'bootloader-overlay' ][0] self.assertIsNotNone( overlay.get_namespace_data(action='storage-deploy', label='u-boot', key='device')) methods = cubie['actions']['boot']['methods'] self.assertIn('u-boot', methods) self.assertIn('usb', methods['u-boot']) self.assertIn('commands', methods['u-boot']['usb']) commands_list = methods['u-boot']['usb']['commands'] device_id = u_boot_action.get_namespace_data(action='storage-deploy', label='u-boot', key='device') self.assertIsNotNone(device_id) kernel_type = u_boot_action.parameters['kernel_type'] bootcommand = map_kernel_uboot(kernel_type, device_params=cubie.get( 'parameters', None)) substitutions = { '{BOOTX}': "%s %s %s %s" % ( bootcommand, cubie['parameters'][bootcommand]['kernel'], cubie['parameters'][bootcommand]['ramdisk'], cubie['parameters'][bootcommand]['dtb'], ), '{RAMDISK}': boot_params['ramdisk'], '{KERNEL}': boot_params['kernel'], '{DTB}': boot_params['dtb'], '{ROOT}': boot_params['root_uuid'], '{ROOT_PART}': "%s:%s" % (cubie['parameters']['media']['usb'][device_id]['device_id'], u_boot_action.parameters['boot_part']) } self.assertEqual('bootz 0x42000000 0x43300000 0x43000000', substitutions['{BOOTX}']) self.assertEqual('/boot/initrd.img-3.16.0-4-armmp-lpae.u-boot', substitutions['{RAMDISK}']) commands = substitute(commands_list, substitutions) self.assertEqual(commands, [ 'usb start', 'usb info', 'setenv autoload no', "setenv initrd_high '0xffffffff'", "setenv fdt_high '0xffffffff'", 'setenv initrd_addr_r ${ramdisk_addr_r}', "setenv loadkernel 'load usb 0:1 ${kernel_addr_r} /boot/vmlinuz-3.16.0-4-armmp-lpae'", "setenv loadinitrd 'load usb 0:1 ${initrd_addr_r} /boot/initrd.img-3.16.0-4-armmp-lpae.u-boot; setenv initrd_size ${filesize}'", "setenv loadfdt 'load usb 0:1 ${fdt_addr_r} /boot/dtb-3.16.0-4-armmp-lpae'", "setenv bootargs 'console=ttyS0,115200n8 root=UUID=159d17cc-697c-4125-95a0-a3775e1deabe ip=dhcp'", "setenv bootcmd 'run loadkernel; run loadinitrd; run loadfdt; bootz 0x42000000 0x43300000 0x43000000'", 'boot' ])
class TestFastbootDeploy(StdoutTestCase): # pylint: disable=too-many-public-methods def setUp(self): super(TestFastbootDeploy, self).setUp() self.factory = FastBootFactory() self.job = self.factory.create_fastboot_job( 'sample_jobs/fastboot.yaml') def test_deploy_job(self): self.assertEqual(self.job.pipeline.job, self.job) self.assertIsInstance(self.job.device['device_info'], list) 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('fastboot.yaml') self.assertEqual(description_ref, self.job.pipeline.describe(False)) @unittest.skipIf( infrastructure_error_multi_paths(['lxc-info', 'img2simg', 'simg2img']), "lxc or img2simg or simg2img not installed") def test_lxc_api(self): job = self.factory.create_hikey_job('sample_jobs/hikey-oe.yaml') description_ref = self.pipeline_reference('hikey-oe.yaml', job=job) job.validate() self.assertEqual(description_ref, job.pipeline.describe(False)) self.assertIn(LxcProtocol.name, [protocol.name for protocol in job.protocols]) self.assertEqual(len(job.protocols), 1) self.assertIsNone( job.device.pre_os_command ) # FIXME: a real device config would typically need this. uefi_menu = [ action for action in job.pipeline.actions if action.name == 'uefi-menu-action' ][0] select = [ action for action in uefi_menu.internal_pipeline.actions if action.name == 'uefi-menu-selector' ][0] self.assertIn(LxcProtocol.name, select.parameters.keys()) self.assertIn('protocols', select.parameters.keys()) self.assertIn(LxcProtocol.name, select.parameters['protocols'].keys()) self.assertEqual(len(select.parameters['protocols'][LxcProtocol.name]), 1) lxc_active = any([ protocol for protocol in job.protocols if protocol.name == LxcProtocol.name ]) self.assertTrue(lxc_active) for calling in select.parameters['protocols'][LxcProtocol.name]: self.assertEqual(calling['action'], select.name) self.assertEqual(calling['request'], 'pre-os-command') deploy = [ action for action in job.pipeline.actions if action.name == 'fastboot-deploy' ][0] self.assertIn(LxcProtocol.name, deploy.parameters.keys()) self.assertIn('protocols', deploy.parameters.keys()) self.assertIn(LxcProtocol.name, deploy.parameters['protocols'].keys()) self.assertEqual(len(deploy.parameters['protocols'][LxcProtocol.name]), 1) for calling in deploy.parameters['protocols'][LxcProtocol.name]: self.assertEqual(calling['action'], deploy.name) self.assertEqual(calling['request'], 'pre-power-command') pair = ['pre-os-command', 'pre-power-command'] action_list = { list(jaction.keys())[0] for jaction in job.parameters['actions'] } block = job.parameters['actions'] for action in action_list: for item in block: if action in item: if 'protocols' in item[action]: caller = (item[action]['protocols'][LxcProtocol.name]) for call in caller: self.assertIn(call['request'], pair) @unittest.skipIf(infrastructure_error('lxc-info'), "lxc-info not installed") def test_fastboot_lxc(self): job = self.factory.create_hikey_job('sample_jobs/hi6220-hikey.yaml') description_ref = self.pipeline_reference('hi6220-hikey.yaml', job=job) self.assertEqual(description_ref, job.pipeline.describe(False)) uefi_menu = [ action for action in job.pipeline.actions if action.name == 'uefi-menu-action' ][0] self.assertIn('commands', uefi_menu.parameters) self.assertIn('fastboot', uefi_menu.parameters['commands']) self.assertEqual( job.device.pre_power_command, '/usr/local/lab-scripts/usb_hub_control -p 8000 -m sync -u 06') lxc_deploy = [ action for action in job.pipeline.actions if action.name == 'lxc-deploy' ][0] overlay = [ action for action in lxc_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] job.validate() self.assertEqual( { '1.8.3.20': '4_android-optee', '1.8.3.4': '0_get-adb-serial', '1.8.3.12': '2_android-busybox', '1.8.3.8': '1_android-meminfo', '1.8.3.16': '3_android-ping-dns' }, testdef.get_namespace_data(action='test-runscript-overlay', label='test-runscript-overlay', key='testdef_levels')) for testdef in testdef.test_list[0]: self.assertEqual('git', testdef['from']) @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) def test_overlay(self): overlay = None for action in self.job.pipeline.actions: self.assertIsNotNone(action.name) if isinstance(action, DeployAction): if action.parameters['namespace'] == 'tlxc': overlay = [ action for action in action.pipeline.actions if action.name == 'lava-overlay' ][0] self.assertIsNotNone(overlay) # these tests require that lava-dispatcher itself is installed, not just running tests from a git clone self.assertTrue(os.path.exists(overlay.lava_test_dir)) self.assertIsNot(overlay.lava_test_dir, '/') self.assertNotIn('lava_multi_node_test_dir', dir(overlay)) self.assertNotIn('lava_multi_node_cache_file', dir(overlay)) self.assertNotIn('lava_lmp_test_dir', dir(overlay)) self.assertNotIn('lava_lmp_cache_file', dir(overlay)) self.assertIsNotNone( overlay.parameters['deployment_data']['lava_test_results_dir']) self.assertIsNotNone( overlay.parameters['deployment_data']['lava_test_sh_cmd']) self.assertEqual(overlay.parameters['deployment_data']['distro'], 'debian') self.assertIsNotNone(overlay.parameters['deployment_data'] ['lava_test_results_part_attr']) self.assertIsNotNone( glob.glob(os.path.join(overlay.lava_test_dir, 'lava-*'))) @unittest.skipIf(infrastructure_error('lxc-attach'), 'lxc-attach not installed') def test_boot(self): for action in self.job.pipeline.actions: if isinstance(action, BootAction): # get the action & populate it self.assertIn(action.parameters['method'], ['lxc', 'fastboot']) 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 test_udev_actions(self): self.factory = FastBootFactory() job = self.factory.create_db410c_job('sample_jobs/db410c.yaml') self.assertTrue(job.device.get('fastboot_via_uboot', True)) self.assertEqual('', self.job.device.power_command) description_ref = self.pipeline_reference('db410c.yaml', job=job) self.assertEqual(description_ref, job.pipeline.describe(False)) boot = [ action for action in job.pipeline.actions if action.name == 'fastboot-boot' ][0] def test_x15_job(self): self.factory = FastBootFactory() job = self.factory.create_x15_job('sample_jobs/x15.yaml') job.validate() description_ref = self.pipeline_reference('x15.yaml', job=job) self.assertEqual(description_ref, job.pipeline.describe(False)) deploy = [ action for action in job.pipeline.actions if action.name == 'fastboot-deploy' ][0] enter = [ action for action in deploy.internal_pipeline.actions if action.name == 'uboot-enter-fastboot' ][0] interrupt = [ action for action in enter.internal_pipeline.actions if action.name == 'bootloader-interrupt' ][0] self.assertTrue(interrupt.needs_interrupt) self.assertIsInstance(interrupt.params, dict) self.assertNotEqual(interrupt.params, {}) self.assertIn('mkimage_arch', interrupt.params) self.assertIn('interrupt_prompt', interrupt.params) boot = [ action for action in job.pipeline.actions if action.name == 'fastboot-boot' ][0] enter = [ action for action in boot.internal_pipeline.actions if action.name == 'uboot-enter-fastboot' ][0] interrupt = [ action for action in enter.internal_pipeline.actions if action.name == 'bootloader-interrupt' ][0] self.assertIsInstance(interrupt.params, dict) self.assertNotEqual(interrupt.params, {}) self.assertIn('mkimage_arch', interrupt.params) self.assertIn('interrupt_prompt', interrupt.params) self.assertTrue(interrupt.needs_interrupt) autologin = [ action for action in boot.internal_pipeline.actions if action.name == 'auto-login-action' ][0] print(autologin.booting) print(autologin.parameters.get('prompts', None)) self.assertIsNone(autologin.parameters.get('boot_message', None)) def test_nexus5x_job(self): self.factory = FastBootFactory() job = self.factory.create_nexus5x_job('sample_jobs/nexus5x.yaml') # do not run job.validate() - urls no longer exist. description_ref = self.pipeline_reference('nexus5x.yaml', job=job) self.assertEqual(description_ref, job.pipeline.describe(False)) def test_pixel_job(self): self.factory = FastBootFactory() job = self.factory.create_pixel_job('sample_jobs/pixel.yaml') # do not run job.validate() - urls no longer exist. description_ref = self.pipeline_reference('pixel.yaml', job=job) self.assertEqual(description_ref, job.pipeline.describe(False)) def test_flash_cmds_order(self): self.factory = FastBootFactory() job = self.factory.create_db410c_job('sample_jobs/db410c.yaml') # The expected_flash_cmds list ensures the following: # 1. Order of flash commands. # 2. Number / Count of flash commands. # 3. 'cdt' flash command is not part of draganboard-410c's device # dictionary, but ensure that it gets added in the final flash # commands list. expected_flash_cmds = [ 'partition', 'hyp', 'rpm', 'sbl1', 'tz', 'aboot', 'cdt', 'boot', 'rootfs' ] flash_order = None for action in job.pipeline.actions: self.assertIsNotNone(action.name) if isinstance(action, DeployAction): if action.name == 'fastboot-deploy': flash_order = [ action for action in action.pipeline.actions if action.name == 'fastboot-flash-order-action' ][0] flash_cmds = [ action.command for action in flash_order.pipeline.actions if action.name == 'fastboot-flash-action' ] self.assertIsNotNone(flash_order) self.assertIsInstance(flash_order, FastbootFlashOrderAction) self.assertEqual(expected_flash_cmds, flash_cmds) def test_hikey960_fastboot(self): job = self.factory.create_hikey960_job( 'sample_jobs/hikey960-aosp.yaml') self.assertIsNotNone(job) job.validate() description_ref = self.pipeline_reference('hi960-aosp-efi.yaml', job=job) self.assertEqual(description_ref, job.pipeline.describe(False)) flash_order = None expected_flash_cmds = ['boot', 'system', 'userdata', 'cache'] for action in job.pipeline.actions: self.assertIsNotNone(action.name) if isinstance(action, DeployAction): if action.name == 'fastboot-deploy': flash_order = [ action for action in action.pipeline.actions if action.name == 'fastboot-flash-order-action' ][0] flash_cmds = [ action.command for action in flash_order.pipeline.actions if action.name == 'fastboot-flash-action' ] self.assertIsNotNone(flash_order) self.assertIsInstance(flash_order, FastbootFlashOrderAction) self.assertEqual(expected_flash_cmds, flash_cmds)
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 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 validate(self): super(ApplyLxcOverlay, self).validate() self.errors = infrastructure_error('tar') if not os.path.exists(self.lava_test_dir): self.errors = "Missing lava-test-runner: %s" % self.lava_test_dir
class TestDepthchargeAction(StdoutTestCase): def setUp(self): super(TestDepthchargeAction, self).setUp() self.factory = DepthchargeFactory() @unittest.skipIf(infrastructure_error('mkimage'), "mkimage not installed") def test_depthcharge(self): job = self.factory.create_jaq_job('sample_jobs/depthcharge.yaml') self.assertIsNotNone(job) description_ref = self.pipeline_reference('depthcharge.yaml', job=job) self.assertEqual(description_ref, job.pipeline.describe(False)) self.assertIsNone(job.validate()) self.assertEqual(job.device['device_type'], 'rk3288-veyron-jaq') self.assertEqual([action.name for action in job.pipeline.actions], ['tftp-deploy', 'depthcharge-action', 'finalize']) tftp = [ action for action in job.pipeline.actions if action.name == 'tftp-deploy' ][0] prep_overlay = [ action for action in tftp.pipeline.actions if action.name == 'prepare-tftp-overlay' ][0] prep_kernel = [ action for action in prep_overlay.pipeline.actions if action.name == 'prepare-kernel' ][0] self.assertEqual( [action.name for action in prep_kernel.internal_pipeline.actions], ['prepare-fit']) prep_fit = [ action for action in prep_kernel.pipeline.actions if action.name == 'prepare-fit' ][0] params = { 'arch': 'neo-gothic', 'load_addr': '0x1234', 'kernel': '/some/zImage', 'dtb': '/some/file.dtb', 'ramdisk': '/some/ramdisk.cpio', 'fit_path': '/does/not/exist', } cmd_ref = 'mkimage \ -D "-I dts -O dtb -p 2048" \ -f auto \ -A {arch} \ -O linux \ -T kernel \ -C None \ -d {kernel} \ -a {load_addr} \ -b {dtb} \ -i {ramdisk} \ {fit_path}'.format(**params) cmd = prep_fit._make_mkimage_command(params) self.assertEqual(cmd_ref, ' '.join(cmd)) depthcharge = [ action for action in job.pipeline.actions if action.name == 'depthcharge-action' ][0] self.assertEqual( [action.name for action in depthcharge.internal_pipeline.actions], ['depthcharge-overlay', 'connect-device', 'depthcharge-retry']) retry = [ action for action in depthcharge.internal_pipeline.actions if action.name == 'depthcharge-retry' ][0] self.assertEqual( [action.name for action in retry.internal_pipeline.actions], ['reset-device', 'depthcharge-start', 'bootloader-commands'])
def validate(self): if 'lxc' not in self.job.device['actions']['boot']['methods']: return super(ConnectLxc, self).validate() self.errors = infrastructure_error('lxc-attach')
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-create-udev-rule-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']['connections']['uart0']['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('kernel-start-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_fastboot_uboot(self): # pylint: disable=too-many-locals job = self.factory.create_x15_job('sample_jobs/x15-uboot.yaml') job.validate() description_ref = self.pipeline_reference('x15-uboot.yaml', job=job) self.assertEqual(description_ref, job.pipeline.describe(False)) deploy = [ action for action in job.pipeline.actions if action.name == 'fastboot-deploy' ][0] enter = [ action for action in deploy.internal_pipeline.actions if action.name == 'uboot-enter-fastboot' ][0] interrupt = [ action for action in enter.internal_pipeline.actions if action.name == 'bootloader-interrupt' ][0] self.assertIsNotNone(interrupt.params) self.assertNotEqual(interrupt.params, {}) self.assertEqual('u-boot', interrupt.method) def test_x15_uboot_nfs(self): # pylint: disable=too-many-locals job = self.factory.create_x15_job('sample_jobs/x15-nfs.yaml') job.validate() description_ref = self.pipeline_reference('x15-nfs.yaml', job=job) self.assertEqual(description_ref, job.pipeline.describe(False)) 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'], 'gz') def test_juno_uboot_nfs(self): job = self.factory.create_juno_job('sample_jobs/juno-uboot-nfs.yaml') job.validate() description_ref = self.pipeline_reference('juno-uboot-nfs.yaml', job=job) self.assertEqual(description_ref, job.pipeline.describe(False)) def test_overlay_action(self): # pylint: disable=too-many-locals parameters = { 'device_type': 'beaglebone-black', 'job_name': 'uboot-pipeline', 'job_timeout': '15m', 'action_timeout': '5m', 'priority': 'medium', 'actions': { 'boot': { 'method': 'u-boot', 'commands': 'ramdisk', 'type': 'bootz', 'prompts': ['linaro-test', 'root@debian:~#'] }, 'deploy': { 'ramdisk': 'initrd.gz', 'kernel': 'zImage', 'dtb': 'broken.dtb' } } } device = NewDevice( os.path.join(os.path.dirname(__file__), '../devices/bbb-01.yaml')) job = Job(4212, parameters, None) job.device = device pipeline = Pipeline(job=job, parameters=parameters['actions']['boot']) job.pipeline = pipeline overlay = BootloaderCommandOverlay() pipeline.add_action(overlay) ip_addr = dispatcher_ip(None) parsed = [] kernel_addr = job.device['parameters'][ overlay.parameters['type']]['ramdisk'] ramdisk_addr = job.device['parameters'][ overlay.parameters['type']]['ramdisk'] dtb_addr = job.device['parameters'][overlay.parameters['type']]['dtb'] kernel = parameters['actions']['deploy']['kernel'] ramdisk = parameters['actions']['deploy']['ramdisk'] dtb = parameters['actions']['deploy']['dtb'] substitution_dictionary = { '{SERVER_IP}': ip_addr, # the addresses need to be hexadecimal '{KERNEL_ADDR}': kernel_addr, '{DTB_ADDR}': dtb_addr, '{RAMDISK_ADDR}': ramdisk_addr, '{BOOTX}': "%s %s %s %s" % (overlay.parameters['type'], kernel_addr, ramdisk_addr, dtb_addr), '{RAMDISK}': ramdisk, '{KERNEL}': kernel, '{DTB}': dtb } params = device['actions']['boot']['methods'] params['u-boot']['ramdisk']['commands'] = substitute( params['u-boot']['ramdisk']['commands'], substitution_dictionary) commands = params['u-boot']['ramdisk']['commands'] self.assertIs(type(commands), list) self.assertIn("setenv loadkernel 'tftp ${kernel_addr_r} zImage'", commands) self.assertIn( "setenv loadinitrd 'tftp ${initrd_addr_r} initrd.gz; setenv initrd_size ${filesize}'", commands) self.assertIn("setenv loadfdt 'tftp ${fdt_addr_r} broken.dtb'", commands) self.assertNotIn("setenv kernel_addr_r '{KERNEL_ADDR}'", commands) self.assertNotIn("setenv initrd_addr_r '{RAMDISK_ADDR}'", commands) self.assertNotIn("setenv fdt_addr_r '{DTB_ADDR}'", commands) for line in params['u-boot']['ramdisk']['commands']: line = line.replace('{SERVER_IP}', ip_addr) # the addresses need to be hexadecimal line = line.replace('{KERNEL_ADDR}', kernel_addr) line = line.replace('{DTB_ADDR}', dtb_addr) line = line.replace('{RAMDISK_ADDR}', ramdisk_addr) line = line.replace( '{BOOTX}', "%s %s %s %s" % (overlay.parameters['type'], kernel_addr, ramdisk_addr, dtb_addr)) line = line.replace('{RAMDISK}', ramdisk) line = line.replace('{KERNEL}', kernel) line = line.replace('{DTB}', dtb) parsed.append(line) self.assertIn("setenv loadkernel 'tftp ${kernel_addr_r} zImage'", parsed) self.assertIn( "setenv loadinitrd 'tftp ${initrd_addr_r} initrd.gz; setenv initrd_size ${filesize}'", parsed) self.assertIn("setenv loadfdt 'tftp ${fdt_addr_r} broken.dtb'", parsed) self.assertNotIn("setenv kernel_addr_r '{KERNEL_ADDR}'", parsed) self.assertNotIn("setenv initrd_addr_r '{RAMDISK_ADDR}'", parsed) self.assertNotIn("setenv fdt_addr_r '{DTB_ADDR}'", parsed) 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']) @unittest.skipIf(infrastructure_error('xnbd-server'), "xnbd-server not installed") def test_nbd_boot(self): job = self.factory.create_bbb_job('sample_jobs/bbb-initrd-nbd.yaml') job.validate() self.assertEqual(job.pipeline.errors, []) description_ref = self.pipeline_reference('bbb-initrd-nbd.yaml', job=job) self.assertEqual(description_ref, job.pipeline.describe(False)) # Fixme: more asserts self.assertIn('u-boot', job.device['actions']['boot']['methods']) params = job.device['actions']['deploy']['parameters'] for action in job.pipeline.actions: action.validate() if isinstance(action, UBootAction): self.assertIn('method', action.parameters) self.assertEqual('u-boot', action.parameters['method']) elif isinstance(action, TftpAction): self.assertIn('initrd', action.parameters) self.assertIn('kernel', action.parameters) self.assertIn('nbdroot', action.parameters) self.assertIn('to', action.parameters) self.assertEqual('nbd', action.parameters['to']) self.assertTrue(action.valid) 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] for setenv in overlay.commands: if 'setenv nbdbasekargs' in setenv: self.assertIn('rw', setenv.split("'")[1]) self.assertIn('${extraargs}', setenv.split("'")[1]) self.assertEqual(3, len(setenv.split("'"))) 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('bootloader-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, "") job.logger = DummyLogger() job.validate() sample_job_data.close() uboot_action = [ action for action in job.pipeline.actions if action.name == 'uboot-action' and action.parameters['namespace'] == 'boot2' ][0] u_boot_media = [ action for action in uboot_action.internal_pipeline.actions if action.name == 'uboot-from-media' and action.parameters['namespace'] == 'boot2' ][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='download-action', label='file', key='kernel')) self.assertEqual( u_boot_media.parameters['ramdisk'], u_boot_media.get_namespace_data(action='compress-ramdisk', label='file', key='ramdisk')) self.assertEqual( u_boot_media.parameters['dtb'], u_boot_media.get_namespace_data(action='download-action', label='file', key='dtb')) # use the base class name so that uboot-from-media can pick up the value reliably. self.assertEqual( u_boot_media.parameters['root_uuid'], u_boot_media.get_namespace_data(action='bootloader-from-media', 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') def test_zcu102(self): job = self.factory.create_zcu102_job('sample_jobs/zcu102-ramdisk.yaml') job.validate() self.assertEqual(job.pipeline.errors, []) description_ref = self.pipeline_reference('zcu102-ramdisk.yaml', job=job) self.assertEqual(description_ref, job.pipeline.describe(False))
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, "") 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)