Exemple #1
0
 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)
Exemple #2
0
 def populate(self, parameters):
     self.internal_pipeline = Pipeline(parent=self,
                                       job=self.job,
                                       parameters=parameters)
     self.internal_pipeline.add_action(BootDockerRetry())
     if self.has_prompts(parameters):
         if self.test_has_shell(parameters):
             self.internal_pipeline.add_action(ExpectShellSession())
             self.internal_pipeline.add_action(ExportDeviceEnvironment())
Exemple #3
0
 def populate(self, parameters):
     self.pipeline = Pipeline(parent=self,
                              job=self.job,
                              parameters=parameters)
     # customize the device configuration for this job
     self.pipeline.add_action(UBootSecondaryMedia())
     self.pipeline.add_action(BootloaderCommandOverlay())
     self.pipeline.add_action(ConnectDevice())
     self.pipeline.add_action(UBootRetry())
Exemple #4
0
 def populate(self, parameters):
     self.pipeline = Pipeline(parent=self,
                              job=self.job,
                              parameters=parameters)
     # establish a new connection before trying the reset
     self.pipeline.add_action(ResetDevice())
     # need to look for Hit any key to stop autoboot
     self.pipeline.add_action(BootloaderInterruptAction())
     self.pipeline.add_action(ConnectLxc())
Exemple #5
0
 def populate(self, parameters):
     self.pipeline = Pipeline(parent=self,
                              job=self.job,
                              parameters=parameters)
     self.pipeline.add_action(CheckFVPVersionAction())
     self.pipeline.add_action(StartFVPAction())
     if parameters.get("use_telnet", True):
         self.pipeline.add_action(GetFVPSerialAction())
         self.pipeline.add_action(ReadFeedback())
Exemple #6
0
    def test_overlay_action(self):  # pylint: disable=too-many-locals
        parameters = {
            'device_type': 'd02',
            'job_name': 'grub-standard-ramdisk',
            'job_timeout': '15m',
            'action_timeout': '5m',
            'priority': 'medium',
            'actions': {
                'boot': {
                    'method': 'grub',
                    'commands': 'ramdisk',
                    'prompts': ['linaro-test', 'root@debian:~#']
                },
                'deploy': {
                    'ramdisk': 'initrd.gz',
                    'kernel': 'zImage',
                    'dtb': 'broken.dtb'
                }
            }
        }
        (rendered, _) = self.factory.create_device('d02-01.jinja2')
        device = NewDevice(yaml.load(rendered))
        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)
Exemple #7
0
    def populate(self, parameters):
        self.tftp_dir = self.mkdtemp(override=filesystem.tftpd_dir())
        self.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,
                                            params=parameters[key])
                download.max_retries = (
                    3  # overridden by failure_retry in the parameters, if set.
                )
                self.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.pipeline.add_action(OverlayAction())
        if "kernel" in parameters and "type" in parameters["kernel"]:
            self.pipeline.add_action(PrepareKernelAction())
        # 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"] = {}
        # handle XnbdAction next - bring-up xnbd-server
        self.pipeline.add_action(XnbdAction())
Exemple #8
0
def test_repeat_action(monkeypatch):
    monkeypatch.setattr(time, "time", lambda: 0)
    ra = RetryAction()
    ra.parameters = {"repeat": 5}
    ra.level = "1"
    ra.internal_pipeline = Pipeline(parent=ra)
    ra.internal_pipeline.add_action(DummyAction())
    ra.run(None, 1)
    assert ra.internal_pipeline.actions[
        0].ran == 5  # nosec - unit test support.
Exemple #9
0
 def populate(self, parameters):
     self.internal_pipeline = Pipeline(parent=self,
                                       job=self.job,
                                       parameters=parameters)
     self.internal_pipeline.add_action(ResetDevice())
     self.internal_pipeline.add_action(
         BootloaderInterruptAction(method=parameters["bootloader"]))
     self.internal_pipeline.add_action(
         BootloaderCommandsAction(expect_final=False,
                                  method=parameters["bootloader"]))
Exemple #10
0
 def populate(self, parameters):
     self.pipeline = Pipeline(parent=self,
                              job=self.job,
                              parameters=parameters)
     # the logic here can be upgraded in future if needed with more parameters to the deploy.
     methods = self.job.device["actions"]["boot"]["methods"]
     if "u-boot" in methods:
         self.pipeline.add_action(UBootPrepareKernelAction())
     elif "depthcharge" in methods:
         self.pipeline.add_action(PrepareFITAction())
Exemple #11
0
 def populate(self, parameters):
     self.internal_pipeline = Pipeline(parent=self,
                                       job=self.job,
                                       parameters=parameters)
     if self.job.device.hard_reset_command:
         self.internal_pipeline.add_action(ResetDevice())
         self.internal_pipeline.add_action(
             WaitDeviceBoardID(self.job.device.get("board_id")))
     self.internal_pipeline.add_action(FlashOpenOCDAction())
     self.internal_pipeline.add_action(ConnectDevice())
Exemple #12
0
 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())
Exemple #13
0
 def populate(self, parameters):
     self.pipeline = Pipeline(parent=self, job=self.job, parameters=parameters)
     self.pipeline.add_action(IsoCommandLine())
     self.pipeline.add_action(MonitorInstallerSession())
     self.pipeline.add_action(IsoRebootAction())
     # Add AutoLoginAction unconditionally as this action does nothing if
     # the configuration does not contain 'auto_login'
     self.pipeline.add_action(AutoLoginAction())
     self.pipeline.add_action(ExpectShellSession())
     self.pipeline.add_action(ExportDeviceEnvironment())
Exemple #14
0
 def populate(self, parameters):
     self.internal_pipeline = Pipeline(parent=self,
                                       job=self.job,
                                       parameters=parameters)
     # the logic here can be upgraded in future if needed with more parameters to the deploy.
     methods = self.job.device['actions']['boot']['methods']
     if 'u-boot' in methods:
         self.internal_pipeline.add_action(UBootPrepareKernelAction())
     elif 'depthcharge' in methods:
         self.internal_pipeline.add_action(PrepareFITAction())
Exemple #15
0
 def populate(self, parameters):
     self.pipeline = Pipeline(parent=self, job=self.job, parameters=parameters)
     self.pipeline.add_action(BootQemuRetry())
     if self.has_prompts(parameters):
         self.pipeline.add_action(AutoLoginAction())
         if self.test_has_shell(parameters):
             self.pipeline.add_action(ExpectShellSession())
             if "transfer_overlay" in parameters:
                 self.pipeline.add_action(OverlayUnpack())
             self.pipeline.add_action(ExportDeviceEnvironment())
Exemple #16
0
 def populate(self, parameters):
     self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters)
     name = parameters['connection']
     self.internal_pipeline.add_action(ConnectShell(name=name))
     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())
Exemple #17
0
 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(LxcAddStaticDevices())
     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())
Exemple #18
0
 def populate(self, parameters):
     self.pipeline = Pipeline(parent=self,
                              job=self.job,
                              parameters=parameters)
     self.pipeline.add_action(ResetDevice())
     self.pipeline.add_action(
         CheckSerialDownloadMode(parent_pipeline=self.pipeline))
     self.pipeline.add_action(BootBootloaderCorruptBootMediaAction())
     self.pipeline.add_action(ResetDevice())
     self.pipeline.add_action(UUUBootRetry(), parameters=parameters)
     self.pipeline.add_action(ConnectDevice())
 def populate(self, parameters):
     self.internal_pipeline = Pipeline(parent=self,
                                       job=self.job,
                                       parameters=parameters)
     path = self.mkdtemp()
     self.internal_pipeline.add_action(DownloaderAction('image', path=path))
     if self.test_needs_overlay(parameters):
         self.internal_pipeline.add_action(OverlayAction())
         self.internal_pipeline.add_action(ApplyOverlayImage())
         if self.test_needs_deployment(parameters):
             self.internal_pipeline.add_action(DeployDeviceEnvironment())
 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
Exemple #21
0
 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']
     usb_mass_device = method_params.get('usb_mass_device')
     resets_after_flash = method_params.get('resets_after_flash', True)
     if self.job.device.hard_reset_command:
         self.internal_pipeline.add_action(ResetDevice())
         self.internal_pipeline.add_action(WaitDevicePathAction(usb_mass_device))
     self.internal_pipeline.add_action(FlashCMSISAction())
     if resets_after_flash:
         self.internal_pipeline.add_action(WaitUSBSerialDeviceAction())
     self.internal_pipeline.add_action(ConnectDevice())
Exemple #22
0
 def populate(self, parameters):
     self.pipeline = Pipeline(parent=self, job=self.job, parameters=parameters)
     self.pipeline.add_action(ConnectDevice())
     if parameters.get("reset", True):
         self.pipeline.add_action(ResetDevice())
     if self.has_prompts(parameters):
         self.pipeline.add_action(AutoLoginAction())
         if self.test_has_shell(parameters):
             self.pipeline.add_action(ExpectShellSession())
             if "transfer_overlay" in parameters:
                 self.pipeline.add_action(OverlayUnpack())
             self.pipeline.add_action(ExportDeviceEnvironment())
Exemple #23
0
 def populate(self, parameters):
     self.pipeline = Pipeline(parent=self, job=self.job, parameters=parameters)
     self.pipeline.add_action(ResetDevice())
     self.pipeline.add_action(DepthchargeStart())
     self.pipeline.add_action(BootloaderCommandsAction())
     if self.has_prompts(parameters):
         self.pipeline.add_action(AutoLoginAction())
         if self.test_has_shell(parameters):
             self.pipeline.add_action(ExpectShellSession())
             if "transfer_overlay" in parameters:
                 self.pipeline.add_action(OverlayUnpack())
             self.pipeline.add_action(ExportDeviceEnvironment())
Exemple #24
0
 def populate(self, parameters):
     self.pipeline = Pipeline(parent=self,
                              job=self.job,
                              parameters=parameters)
     self.pipeline.add_action(BootFVPMain())
     if self.has_prompts(parameters):
         self.pipeline.add_action(ReadFeedback())
         self.pipeline.add_action(AutoLoginAction())
         if self.test_has_shell(parameters):
             self.pipeline.add_action(ExpectShellSession())
             if "transfer_overlay" in parameters:
                 self.pipeline.add_action(OverlayUnpack())
Exemple #25
0
    def test_overlay_action(self):  # pylint: disable=too-many-locals
        parameters = {
            "device_type": "x86",
            "job_name": "ipxe-pipeline",
            "job_timeout": "15m",
            "action_timeout": "5m",
            "priority": "medium",
            "actions": {
                "boot": {
                    "method": "ipxe",
                    "commands": "ramdisk",
                    "prompts": ["linaro-test", "root@debian:~#"],
                },
                "deploy": {
                    "ramdisk": "initrd.gz",
                    "kernel": "zImage"
                },
            },
        }
        (rendered, _) = self.factory.create_device("x86-01.jinja2")
        device = NewDevice(yaml.safe_load(rendered))
        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  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)
Exemple #26
0
 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(booting=False))
     self.internal_pipeline.add_action(ExpectShellSession())
     self.internal_pipeline.add_action(ExportDeviceEnvironment())
     self.internal_pipeline.add_action(ScpOverlayUnpack())
Exemple #27
0
    def test_overlay_action(self):  # pylint: disable=too-many-locals
        parameters = {
            'device_type': 'x86',
            'job_name': 'ipxe-pipeline',
            'job_timeout': '15m',
            'action_timeout': '5m',
            'priority': 'medium',
            'actions': {
                'boot': {
                    'method': 'ipxe',
                    'commands': 'ramdisk',
                    'prompts': ['linaro-test', 'root@debian:~#']
                },
                'deploy': {
                    'ramdisk': 'initrd.gz',
                    'kernel': 'zImage',
                }
            }
        }
        (rendered, _) = self.factory.create_device('x86-01.jinja2')
        device = NewDevice(yaml.safe_load(rendered))
        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  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)
Exemple #28
0
 def test_multi_deploy(self):
     self.assertIsNotNone(self.parsed_data)
     job = Job(4212, self.parsed_data, None)
     job.timeout = Timeout("Job", Timeout.parse({"minutes": 2}))
     pipeline = Pipeline(job=job)
     device = TestMultiDeploy.FakeDevice()
     self.assertIsNotNone(device)
     job.device = device
     job.logger = DummyLogger()
     job.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({}, 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,
                         {"fake-deploy": pipeline.actions[0].parameters})
     self.assertEqual(pipeline.actions[1].data,
                      {"fake-deploy": pipeline.actions[2].parameters})
     # check that values from previous DeployAction run actions have been cleared
     self.assertEqual(pipeline.actions[2].data,
                      {"fake-deploy": pipeline.actions[2].parameters})
Exemple #29
0
    def populate(self, parameters):
        self.pipeline = Pipeline(parent=self,
                                 job=self.job,
                                 parameters=parameters)

        # Find the right action according to the url
        url = self.params.get("url")
        if url is None:
            raise JobError("Invalid deploy action: 'url' is missing for '%s'" %
                           self.key)

        url = urlparse(url)
        if url.scheme == "scp":
            action = ScpDownloadAction(self.key,
                                       self.path,
                                       url,
                                       self.uniquify,
                                       params=self.params)
        elif url.scheme == "http" or url.scheme == "https":
            action = HttpDownloadAction(self.key,
                                        self.path,
                                        url,
                                        self.uniquify,
                                        params=self.params)
        elif url.scheme == "file":
            action = FileDownloadAction(self.key,
                                        self.path,
                                        url,
                                        self.uniquify,
                                        params=self.params)
        elif url.scheme == "lxc":
            action = LxcDownloadAction(self.key, self.path, url)
        elif url.scheme == "downloads":
            action = PreDownloadedAction(self.key,
                                         url,
                                         self.path,
                                         params=self.params)
        else:
            raise JobError("Unsupported url protocol scheme: %s" % url.scheme)
        self.pipeline.add_action(action)
        overlays = self.params.get("overlays", [])
        for overlay in overlays:
            if overlay == "lava":
                # Special case, don't download an overlay, just defined where to find overlays
                continue
            self.pipeline.add_action(
                DownloaderAction("%s.%s" % (self.key, overlay),
                                 self.path,
                                 params=overlays[overlay]))
        if overlays:
            self.pipeline.add_action(
                AppendOverlays(self.key, params=self.params))
Exemple #30
0
 def populate(self, parameters):
     self.pipeline = Pipeline(parent=self, job=self.job, parameters=parameters)
     # establish a new connection before trying the reset
     self.pipeline.add_action(ResetDevice())
     self.pipeline.add_action(BootloaderInterruptAction())
     self.pipeline.add_action(BootloaderCommandsAction())
     if self.has_prompts(parameters):
         self.pipeline.add_action(AutoLoginAction())
         if self.test_has_shell(parameters):
             self.pipeline.add_action(ExpectShellSession())
             if "transfer_overlay" in parameters:
                 self.pipeline.add_action(OverlayUnpack())
             self.pipeline.add_action(ExportDeviceEnvironment())