def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) self.internal_pipeline.add_action( RebootDevice()) # skipped if power is off self.internal_pipeline.add_action( PDUReboot()) # adjuvant, only if RebootDevice acts and fails self.internal_pipeline.add_action(PowerOn())
def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) # customize the device configuration for this job self.internal_pipeline.add_action(UBootSecondaryMedia()) self.internal_pipeline.add_action(BootloaderCommandOverlay()) self.internal_pipeline.add_action(ConnectDevice()) self.internal_pipeline.add_action(UBootRetry())
def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) # establish a new connection before trying the reset self.internal_pipeline.add_action(ResetDevice()) # need to look for Hit any key to stop autoboot self.internal_pipeline.add_action(UBootInterrupt()) self.internal_pipeline.add_action(ConnectLxc())
def test_runs_subaction(self): pipe = Pipeline() pipe.add_action(self.sub0) pipe.add_action(self.sub1) pipe.run_actions(None, None) self.assertTrue(self.sub0.ran) self.assertTrue(self.sub1.ran) self.assertNotEqual(self.sub0.timeout.elapsed_time, 0) self.assertNotEqual(self.sub1.timeout.elapsed_time, 0)
def populate(self, parameters): self.tftp_dir = self.mkdtemp(override=tftpd_dir()) self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) self.set_namespace_data(action=self.name, label='tftp', key='tftp_dir', value=self.tftp_dir, parameters=parameters) for key in ['initrd', 'kernel', 'dtb', 'nbdroot']: if key in parameters: download = DownloaderAction(key, path=self.tftp_dir) download.max_retries = 3 # overridden by failure_retry in the parameters, if set. self.internal_pipeline.add_action(download) if key == 'initrd': self.set_namespace_data(action="tftp-deploy", label='tftp', key='ramdisk', value=True, parameters=parameters) self.set_namespace_data(action=self.name, label='nbd', key='initrd', value=True, parameters=parameters) # prepare overlay self.internal_pipeline.add_action(OverlayAction()) # setup values for protocol and later steps self.set_namespace_data(action=self.name, label='nbd', key='initrd', value=True, parameters=parameters) # store in parameters for protocol 'xnbd' to tear-down xnbd-server # and store in namespace for boot action # ip parameters['lava-xnbd'] = {} self.nbd_ip = dispatcher_ip(self.job.parameters['dispatcher']) parameters['lava-xnbd']['ip'] = self.nbd_ip self.set_namespace_data(action=self.name, label='nbd', key='nbd_server_ip', value=self.nbd_ip, parameters=parameters) # port self.nbd_port = get_free_port(self.job.parameters['dispatcher']) parameters['lava-xnbd']['port'] = self.nbd_port self.set_namespace_data(action=self.name, label='nbd', key='nbd_server_port', value=self.nbd_port, parameters=parameters) # handle XnbdAction next - bring-up xnbd-server self.internal_pipeline.add_action(XnbdAction())
def test_overlay_action(self): # pylint: disable=too-many-locals parameters = { 'device_type': 'd02', 'job_name': 'grub-standard-ramdisk', 'job_timeout': '15m', 'action_timeout': '5m', 'priority': 'medium', 'output_dir': mkdtemp(), 'actions': { 'boot': { 'method': 'grub', 'commands': 'ramdisk', 'prompts': ['linaro-test', 'root@debian:~#'] }, 'deploy': { 'ramdisk': 'initrd.gz', 'kernel': 'zImage', 'dtb': 'broken.dtb' } } } device = NewDevice(os.path.join(os.path.dirname(__file__), '../devices/d02-01.yaml')) job = Job(4212, parameters, None) job.device = device pipeline = Pipeline(job=job, parameters=parameters['actions']['boot']) job.pipeline = pipeline overlay = BootloaderCommandOverlay() pipeline.add_action(overlay) ip_addr = dispatcher_ip(None) parsed = [] kernel = parameters['actions']['deploy']['kernel'] ramdisk = parameters['actions']['deploy']['ramdisk'] dtb = parameters['actions']['deploy']['dtb'] substitution_dictionary = { '{SERVER_IP}': ip_addr, # the addresses need to be hexadecimal '{RAMDISK}': ramdisk, '{KERNEL}': kernel, '{DTB}': dtb } params = device['actions']['boot']['methods'] commands = params['grub']['ramdisk']['commands'] self.assertIn('net_bootp', commands) self.assertIn("linux (tftp,{SERVER_IP})/{KERNEL} console=ttyS0,115200 earlycon=uart8250,mmio32,0x80300000 root=/dev/ram0 ip=dhcp", commands) self.assertIn('initrd (tftp,{SERVER_IP})/{RAMDISK}', commands) self.assertIn('devicetree (tftp,{SERVER_IP})/{DTB}', commands) params['grub']['ramdisk']['commands'] = substitute(params['grub']['ramdisk']['commands'], substitution_dictionary) substituted_commands = params['grub']['ramdisk']['commands'] self.assertIs(type(substituted_commands), list) self.assertIn('net_bootp', substituted_commands) self.assertNotIn("linux (tftp,{SERVER_IP})/{KERNEL} console=ttyS0,115200 earlycon=uart8250,mmio32,0x80300000 root=/dev/ram0 ip=dhcp", substituted_commands) self.assertIn("linux (tftp,%s)/%s console=ttyS0,115200 earlycon=uart8250,mmio32,0x80300000 root=/dev/ram0 ip=dhcp" % (ip_addr, kernel), substituted_commands) self.assertNotIn('initrd (tftp,{SERVER_IP})/{RAMDISK}', parsed) self.assertNotIn('devicetree (tftp,{SERVER_IP})/{DTB}', parsed)
def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) self.internal_pipeline.add_action(BootQemuRetry()) if self.has_prompts(parameters): self.internal_pipeline.add_action(AutoLoginAction()) if self.test_has_shell(parameters): self.internal_pipeline.add_action(ExpectShellSession()) if 'transfer_overlay' in parameters: self.internal_pipeline.add_action(OverlayUnpack()) self.internal_pipeline.add_action(ExportDeviceEnvironment())
def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) self.internal_pipeline.add_action(KexecAction()) # Add AutoLoginAction unconditionally as this action does nothing if # the configuration does not contain 'auto_login' self.internal_pipeline.add_action(AutoLoginAction()) self.internal_pipeline.add_action(ExpectShellSession()) self.internal_pipeline.add_action(ExportDeviceEnvironment())
def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) self.internal_pipeline.add_action(LxcStartAction()) self.internal_pipeline.add_action(ConnectLxc()) # Skip AutoLoginAction unconditionally as this action tries to parse kernel message # self.internal_pipeline.add_action(AutoLoginAction()) self.internal_pipeline.add_action(ExpectShellSession()) self.internal_pipeline.add_action(ExportDeviceEnvironment())
def __init__(self, parent): super(BootKVM, self).__init__(parent) self.action = BootQEMUImageAction() self.action.job = self.job parent.add_action(self.action) internal_pipeline = Pipeline(parent=self.action, job=self.job) if 'auto_login' in self.action.parameters: internal_pipeline.add_action(AutoLoginAction()) internal_pipeline.add_action(ExpectShellSession())
def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) path = self.mkdtemp() for image in parameters['images'].keys(): if image != 'yaml_line': download = DownloaderAction(image, path) download.max_retries = 3 # overridden by failure_retry in the parameters, if set. self.internal_pipeline.add_action(download)
def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) method_params = self.job.device['actions']['boot']['methods'][ 'cmsis-dap']['parameters'] self.internal_pipeline.add_action(FlashCMSISAction()) if method_params.get('resets_after_flash', True): self.internal_pipeline.add_action(WaitUSBSerialDeviceAction()) self.internal_pipeline.add_action(ConnectDevice())
def test_overlay_action(self): # pylint: disable=too-many-locals parameters = { 'device_type': 'x86', 'job_name': 'ipxe-pipeline', 'job_timeout': '15m', 'action_timeout': '5m', 'priority': 'medium', 'output_dir': mkdtemp(), 'actions': { 'boot': { 'method': 'ipxe', 'commands': 'ramdisk', 'prompts': ['linaro-test', 'root@debian:~#'] }, 'deploy': { 'ramdisk': 'initrd.gz', 'kernel': 'zImage', } } } device = NewDevice( os.path.join(os.path.dirname(__file__), '../devices/x86-01.yaml')) job = Job(4212, parameters, None) job.device = device pipeline = Pipeline(job=job, parameters=parameters['actions']['boot']) job.pipeline = pipeline overlay = BootloaderCommandOverlay() pipeline.add_action(overlay) ip_addr = dispatcher_ip(None) kernel = parameters['actions']['deploy']['kernel'] ramdisk = parameters['actions']['deploy']['ramdisk'] substitution_dictionary = { '{SERVER_IP}': ip_addr, '{RAMDISK}': ramdisk, '{KERNEL}': kernel, '{LAVA_MAC}': "00:00:00:00:00:00" } params = device['actions']['boot']['methods'] params['ipxe']['ramdisk']['commands'] = substitute( params['ipxe']['ramdisk']['commands'], substitution_dictionary) commands = params['ipxe']['ramdisk']['commands'] self.assertIs(type(commands), list) self.assertIn("dhcp net0", commands) self.assertIn( "set console console=ttyS0,115200n8 lava_mac=00:00:00:00:00:00", commands) self.assertIn("set extraargs init=/sbin/init ip=dhcp", commands) self.assertNotIn( "kernel tftp://{SERVER_IP}/{KERNEL} ${extraargs} ${console}", commands) self.assertNotIn("initrd tftp://{SERVER_IP}/{RAMDISK}", commands) self.assertIn("boot", commands)
def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) if self.test_needs_overlay(parameters): if any('ssh' in data for data in self.job.device['actions']['deploy']['methods']): # only devices supporting ssh deployments add this action. self.internal_pipeline.add_action(SshAuthorize()) self.internal_pipeline.add_action(VlandOverlayAction()) self.internal_pipeline.add_action(MultinodeOverlayAction()) self.internal_pipeline.add_action(TestDefinitionAction()) self.internal_pipeline.add_action(CompressOverlay()) self.internal_pipeline.add_action(PersistentNFSOverlay()) # idempotent
def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) sequences = self.job.device['actions']['boot']['methods'].get( 'fastboot', []) for sequence in sequences: mapped = _fastboot_sequence_map(sequence) if mapped[1]: self.internal_pipeline.add_action( mapped[0](device_actions=mapped[1])) elif mapped[0]: self.internal_pipeline.add_action(mapped[0]())
def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) if parameters['nexell_ext']: self.internal_pipeline.add_action(NexellCreateAction()) self.internal_pipeline.add_action(OverlayAction()) self.internal_pipeline.add_action(ApplyNexellOverlay()) else: self.internal_pipeline.add_action(LxcCreateAction()) self.internal_pipeline.add_action(OverlayAction()) self.internal_pipeline.add_action(ApplyLxcOverlay())
def populate(self, parameters): """ Each time a test definition is processed by a handler, a new set of overlay files are needed, based on that test definition. Basic overlay files are created by TestOverlayAction. More complex scripts like the install:deps script and the main run script have custom Actions. """ index = {} self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) self.test_list = identify_test_definitions(self.job.parameters) if not self.test_list: return for testdefs in self.test_list: for testdef in testdefs: # FIXME: only run the tests defined for this test action, not all the jobs for this deployment/job # This includes only running the install steps for the relevant deployment as the next deployment # could be a different OS. handler = RepoAction.select(testdef['from'])() # set the full set of job YAML parameters for this handler as handler parameters. handler.job = self.job handler.parameters = testdef # store the correct test_name before incrementing the local index dict handler.parameters['test_name'] = "%s_%s" % (len(list(index.keys())), handler.parameters['name']) # copy details into the overlay, one per handler but the same class each time. overlay = TestOverlayAction() overlay.job = self.job overlay.parameters = testdef overlay.parameters['test_name'] = handler.parameters['test_name'] overlay.test_uuid = handler.uuid # add install handler - uses job parameters installer = TestInstallAction() installer.job = self.job installer.parameters = testdef installer.parameters['test_name'] = handler.parameters['test_name'] installer.test_uuid = handler.uuid # add runsh handler - uses job parameters runsh = TestRunnerAction() runsh.job = self.job runsh.parameters = testdef runsh.parameters['test_name'] = handler.parameters['test_name'] runsh.test_uuid = handler.uuid index[len(list(index.keys()))] = handler.parameters['name'] self.internal_pipeline.add_action(handler) # add overlay handlers to the pipeline self.internal_pipeline.add_action(overlay) self.internal_pipeline.add_action(installer) self.internal_pipeline.add_action(runsh)
def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) scp = Scp('overlay') self.internal_pipeline.add_action(scp) self.internal_pipeline.add_action(PrepareSsh()) self.internal_pipeline.add_action(ConnectSsh()) self.internal_pipeline.add_action(AutoLoginAction()) self.internal_pipeline.add_action(ExpectShellSession()) self.internal_pipeline.add_action(ExportDeviceEnvironment()) self.internal_pipeline.add_action(ScpOverlayUnpack())
def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) # establish a new connection before trying the reset self.internal_pipeline.add_action(ResetDevice()) self.internal_pipeline.add_action(MonitorBootloaderAutoBoot()) # wait # and set prompt to the uboot prompt # Add AutoLoginAction unconditionally as this action does nothing if # the configuration does not contain 'auto_login' self.internal_pipeline.add_action(AutoLoginAction()) self.internal_pipeline.add_action(ExpectShellSession()) # wait self.internal_pipeline.add_action(ExportDeviceEnvironment())
def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) self.internal_pipeline.add_action(LxcCreateAction()) if 'packages' in parameters: self.internal_pipeline.add_action(LxcStartAction()) self.internal_pipeline.add_action(LxcAptUpdateAction()) self.internal_pipeline.add_action(LxcAptInstallAction()) self.internal_pipeline.add_action(LxcStopAction()) # needed if export device environment is also to be used self.internal_pipeline.add_action(DeployDeviceEnvironment()) self.internal_pipeline.add_action(OverlayAction()) self.internal_pipeline.add_action(ApplyLxcOverlay())
def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) # establish a new connection before trying the reset self.internal_pipeline.add_action(ResetDevice()) self.internal_pipeline.add_action(UBootInterrupt()) self.internal_pipeline.add_action(BootloaderCommandsAction()) if self.has_prompts(parameters): self.internal_pipeline.add_action(AutoLoginAction()) if self.test_has_shell(parameters): self.internal_pipeline.add_action(ExpectShellSession()) if 'transfer_overlay' in parameters: self.internal_pipeline.add_action(OverlayUnpack()) self.internal_pipeline.add_action(ExportDeviceEnvironment())
def test_composite_action_aggregates_errors_from_sub_actions(self): # pylint: disable=invalid-name # Unable to call Action.validate() as there is no job in this unit test sub1 = Action() sub1.__errors__ = [1] sub2 = Action() sub2.name = "sub2" sub2.__errors__ = [2] pipe = Pipeline() sub1.name = "sub1" pipe.add_action(sub1) pipe.add_action(sub2) self.assertEqual([1, 2], pipe.errors)
def test_multi_deploy(self): self.assertIsNotNone(self.parsed_data) job = Job(4212, None, None, None, self.parsed_data) pipeline = Pipeline(job=job) device = TestMultiDeploy.FakeDevice() self.assertIsNotNone(device) job.device = device job.parameters['output_dir'] = mkdtemp() job.set_pipeline(pipeline) counts = {} for action_data in self.parsed_data['actions']: for name in action_data: counts.setdefault(name, 1) parameters = action_data[name] test_deploy = TestMultiDeploy.TestDeploy( pipeline, parameters, job) self.assertEqual({'common': {}}, test_deploy.action.data) counts[name] += 1 # check that only one action has the example set self.assertEqual(['nowhere'], [ detail['deploy']['example'] for detail in self.parsed_data['actions'] if 'example' in detail['deploy'] ]) self.assertEqual(['faked', 'valid'], [ detail['deploy']['parameters'] for detail in self.parsed_data['actions'] if 'parameters' in detail['deploy'] ]) self.assertIsInstance(pipeline.actions[0], TestMultiDeploy.TestDeployAction) self.assertIsInstance(pipeline.actions[1], TestMultiDeploy.TestDeployAction) self.assertIsInstance(pipeline.actions[2], TestMultiDeploy.TestDeployAction) job.validate() self.assertEqual([], job.pipeline.errors) job.run() self.assertNotEqual(pipeline.actions[0].data, { 'common': {}, 'fake_deploy': pipeline.actions[0].parameters }) self.assertEqual(pipeline.actions[1].data, { 'common': {}, 'fake_deploy': pipeline.actions[2].parameters }) # check that values from previous DeployAction run actions have been cleared self.assertEqual(pipeline.actions[2].data, { 'common': {}, 'fake_deploy': pipeline.actions[2].parameters })
def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) # Nexell Extension if len(parameters['nexell_ext']) > 0: self.internal_pipeline.add_action(NexellFastbootBootAction(parameters)) #self.internal_pipeline.add_action(ConnectTelnet(parameters)) #self.internal_pipeline.add_action(WaitForAdbDeviceForNexell()) self.internal_pipeline.add_action(ConnectTelnet(parameters)) self.internal_pipeline.add_action(WaitForPromptForNexell(parameters)) else: self.internal_pipeline.add_action(FastbootBootAction()) self.internal_pipeline.add_action(ConnectLxc()) self.internal_pipeline.add_action(WaitForAdbDevice())
def populate(self): """ Needs to take account of the deployment type / image type etc. to determine which actions need to be added to the internal pipeline as part of the deployment selection step. """ if not self.job: raise RuntimeError("No job object supplied to action") # FIXME: not all mount operations will need these actions self.internal_pipeline = Pipeline(parent=self, job=self.job) self.internal_pipeline.add_action(OffsetAction()) # FIXME: LoopCheckAction and LoopMountAction should be in only one Action self.internal_pipeline.add_action(LoopCheckAction()) self.internal_pipeline.add_action(LoopMountAction())
def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) # Find the right action according to the url url = urlparse.urlparse(parameters[self.key]) if url.scheme == 'scp': action = ScpDownloadAction(self.key, self.path, url) elif url.scheme == 'http' or url.scheme == 'https': action = HttpDownloadAction(self.key, self.path, url) elif url.scheme == 'file': action = FileDownloadAction(self.key, self.path, url) else: raise JobError("Unsupported url protocol scheme: %s" % url.scheme) self.internal_pipeline.add_action(action)
def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) self.internal_pipeline.add_action(LxcCreateAction()) if 'packages' in parameters: self.internal_pipeline.add_action(LxcStartAction()) self.internal_pipeline.add_action(LxcAptUpdateAction()) self.internal_pipeline.add_action(LxcAptInstallAction()) self.internal_pipeline.add_action(LxcStopAction()) if self.test_needs_deployment(parameters): self.internal_pipeline.add_action(DeployDeviceEnvironment()) if self.test_needs_overlay(parameters): self.internal_pipeline.add_action(OverlayAction()) self.internal_pipeline.add_action(ApplyLxcOverlay())
def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) # establish a new connection before trying the reset self.internal_pipeline.add_action(ResetDevice()) self.internal_pipeline.add_action(BootloaderInterrupt()) # need to look for Hit any key to stop autoboot self.internal_pipeline.add_action(BootloaderCommandsAction()) # Add AutoLoginAction unconditionally as this action does nothing if # the configuration does not contain 'auto_login' self.internal_pipeline.add_action(AutoLoginAction()) self.internal_pipeline.add_action(ExpectShellSession()) # wait self.internal_pipeline.add_action(ExportDeviceEnvironment())
def test_add_action_to_pipeline(self): action = Action() action.name = "test-action" action.description = "test action only" action.summary = "starter" self.assertEqual(action.description, "test action only") self.assertEqual(action.summary, "starter") # action needs to be added to a top level pipe first with self.assertRaises(RuntimeError): Pipeline(action) pipe = Pipeline() with self.assertRaises(RuntimeError): pipe.add_action(None) with self.assertRaises(RuntimeError): pipe.add_action(pipe) pipe.add_action(action) self.assertNotEqual(pipe.children, {pipe: []}) self.assertEqual(pipe.children, {pipe: [action]}) self.assertEqual(action.level, "1") try: simplejson.loads(pipe.describe()) except: # pylint: disable=bare-except self.assertFalse(0)
def populate(self, parameters): download_dir = self.mkdtemp() self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) if 'nfsrootfs' in parameters: self.internal_pipeline.add_action(DownloaderAction('nfsrootfs', path=download_dir)) if 'modules' in parameters: self.internal_pipeline.add_action(DownloaderAction('modules', path=download_dir)) # NfsAction is a deployment, so once the nfsrootfs has been deployed, just do the overlay self.internal_pipeline.add_action(ExtractNfsRootfs()) self.internal_pipeline.add_action(OverlayAction()) self.internal_pipeline.add_action(ExtractModules()) self.internal_pipeline.add_action(ApplyOverlayTftp()) if self.test_needs_deployment(parameters): self.internal_pipeline.add_action(DeployDeviceEnvironment())