Пример #1
0
    def finalise_protocol(self, device=None):
        """Called by Finalize action to power down and clean up the assigned
        device.
        """
        # Reboot devices that have adb serial number.
        if 'adb_serial_number' in device:
            reboot_cmd = "lxc-attach -n {0} -- adb reboot bootloader".format(
                self.lxc_name)
            self.logger.debug("%s protocol: executing '%s'", self.name,
                              reboot_cmd)
            shell = ShellCommand("%s\n" % reboot_cmd,
                                 self.system_timeout,
                                 logger=self.logger)
            # execute the command.
            shell.expect(pexpect.EOF)
            if shell.exitstatus:
                self.logger.debug("%s command exited %d: %s", reboot_cmd,
                                  shell.exitstatus, shell.readlines())

        # ShellCommand executes the destroy command
        cmd = "lxc-destroy -n {0} -f".format(self.lxc_name)
        self.logger.debug("%s protocol: executing '%s'", self.name, cmd)
        shell = ShellCommand("%s\n" % cmd,
                             self.system_timeout,
                             logger=self.logger)
        # execute the command.
        shell.expect(pexpect.EOF)
        if shell.exitstatus:
            raise JobError("%s command exited %d: %s" %
                           (cmd, shell.exitstatus, shell.readlines()))
        self.logger.debug("%s protocol finalised.", self.name)
Пример #2
0
    def run(self, connection, args=None):
        # substitutions
        substitutions = {'{emptyimage}': self.get_common_data('prepare-empty-image', 'output')}
        sub_command = self.get_common_data('prepare-qemu-commands', 'sub_command')
        sub_command = substitute(sub_command, substitutions)
        command_line = ' '.join(sub_command)

        commands = []
        # get the download args in run()
        image_arg = self.data['download_action']['iso'].get('image_arg', None)
        action_arg = self.data['download_action']['iso'].get('file', None)
        substitutions["{%s}" % 'iso'] = action_arg
        commands.append(image_arg)
        command_line += ' '.join(substitute(commands, substitutions))

        preseed_file = self.get_common_data('file', 'preseed')
        if not preseed_file:
            raise JobError("Unable to identify downloaded preseed filename.")
        substitutions = {'{preseed}': preseed_file}
        append_args = self.get_common_data('prepare-qemu-commands', 'append')
        append_args = substitute([append_args], substitutions)
        command_line += ' '.join(append_args)

        self.logger.info(command_line)
        shell = ShellCommand(command_line, self.timeout, logger=self.logger)
        if shell.exitstatus:
            raise JobError("%s command exited %d: %s" % (sub_command[0], shell.exitstatus, shell.readlines()))
        self.logger.debug("started a shell command")

        shell_connection = ShellSession(self.job, shell)
        shell_connection.prompt_str = self.get_common_data('prepare-qemu-commands', 'prompts')
        shell_connection = super(IsoCommandLine, self).run(shell_connection, args)
        return shell_connection
Пример #3
0
    def run(self, connection, args=None):
        """
        qemu needs help to reboot after running the debian installer
        and typically the boot is quiet, so there is almost nothing to log.
        """
        base_image = self.get_common_data('prepare-empty-image', 'output')
        self.sub_command.append('-drive format=raw,file=%s' % base_image)
        guest = self.get_common_data('guest', 'filename')
        if guest:
            self.logger.info("Extending command line for qcow2 test overlay")
            self.sub_command.append('-drive format=qcow2,file=%s,media=disk' % (os.path.realpath(guest)))
            # push the mount operation to the test shell pre-command to be run
            # before the test shell tries to execute.
            shell_precommand_list = []
            mountpoint = self.data['lava_test_results_dir']
            shell_precommand_list.append('mkdir %s' % mountpoint)
            shell_precommand_list.append('mount -L LAVA %s' % mountpoint)
            self.set_common_data('lava-test-shell', 'pre-command-list', shell_precommand_list)

        self.logger.info("Boot command: %s", ' '.join(self.sub_command))
        shell = ShellCommand(' '.join(self.sub_command), self.timeout, logger=self.logger)
        if shell.exitstatus:
            raise JobError("%s command exited %d: %s" % (self.sub_command, shell.exitstatus, shell.readlines()))
        self.logger.debug("started a shell command")

        shell_connection = ShellSession(self.job, shell)
        shell_connection = super(IsoRebootAction, self).run(shell_connection, args)
        shell_connection.prompt_str = [INSTALLER_QUIET_MSG]
        self.wait(shell_connection)
        self.data['boot-result'] = 'failed' if self.errors else 'success'
        self.logger.debug("boot-result: %s", self.data['boot-result'])
        return shell_connection
Пример #4
0
    def run(self, connection, args=None):
        if connection:
            self.logger.debug("Already connected")
            return connection
        signal.alarm(0)  # clear the timeouts used without connections.
        # ShellCommand executes the connection command

        params = self._check_params()
        if self.valid:
            self.command = ['ssh']
            self.command.extend(params['options'])
        command = self.command[:]  # local copy for idempotency
        command.extend(['-i', self.identity_file])

        if self.host:
            command.append("%s@%s" % (self.ssh_user, self.host))
        else:
            # get from the protocol
            pass
        command_str = " ".join(str(item) for item in command)
        # use device data for destination
        self.logger.info("%s Connecting to device %s using '%s'", self.name,
                         self.host, command_str)
        shell = ShellCommand("%s\n" % command_str, self.timeout)
        if shell.exitstatus:
            raise JobError("%s command exited %d: %s" %
                           (self.command, shell.exitstatus, shell.readlines()))
        # SshSession monitors the pexpect
        connection = SShSession(self.job, shell)
        connection = super(ConnectSsh, self).run(connection, args)
        connection.prompt_str = self.job.device['test_image_prompts']
        connection.connected = True
        self.wait(connection)
        self.data["boot-result"] = 'success'
        return connection
Пример #5
0
    def run(self, connection, args=None):
        """
        CommandRunner expects a pexpect.spawn connection which is the return value
        of target.device.power_on executed by boot in the old dispatcher.

        In the new pipeline, the pexpect.spawn is a ShellCommand and the
        connection is a ShellSession. CommandRunner inside the ShellSession
        turns the ShellCommand into a runner which the ShellSession uses via ShellSession.run()
        to run commands issued *after* the device has booted.
        pexpect.spawn is one of the raw_connection objects for a Connection class.
        """
        # initialise the first Connection object, a command line shell into the running QEMU.
        self.logger.info("Boot command: %s", ' '.join(self.sub_command))
        shell = ShellCommand(' '.join(self.sub_command),
                             self.timeout,
                             logger=self.logger)
        if shell.exitstatus:
            raise JobError(
                "%s command exited %d: %s" %
                (self.sub_command, shell.exitstatus, shell.readlines()))
        self.logger.debug("started a shell command")

        shell_connection = ShellSession(self.job, shell)
        shell_connection = super(MonitorQemuAction,
                                 self).run(shell_connection, args)

        # FIXME: the shell needs to wait for something

        # FIXME: tests with multiple boots need to be handled too.
        self.data['boot-result'] = 'failed' if self.errors else 'success'
        # FIXME: from here, go into the new test action.
        return shell_connection
Пример #6
0
 def test_check_char(self):
     shell = ShellCommand("%s\n" % 'ls', Timeout('fake', 30), logger=logging.getLogger())
     if shell.exitstatus:
         raise JobError("%s command exited %d: %s" % ('ls', shell.exitstatus, shell.readlines()))
     connection = ShellSession(self.job, shell)
     self.assertFalse(hasattr(shell, 'check_char'))
     self.assertTrue(hasattr(connection, 'check_char'))
     self.assertIsNotNone(connection.check_char)
Пример #7
0
    def run(self, connection, args=None):
        if connection:
            self.logger.debug("Already connected")
            return connection
        signal.alarm(0)  # clear the timeouts used without connections.
        # ShellCommand executes the connection command

        params = self._check_params()
        command = self.command[:]  # local copy for idempotency
        overrides = self.get_common_data("prepare-scp-overlay", self.key)
        host_address = None
        if overrides:
            host_address = str(
                self.get_common_data("prepare-scp-overlay", overrides[0]))
        if host_address:
            self.logger.info(
                "Using common data to retrieve host_address for secondary connection."
            )
            command_str = " ".join(str(item) for item in command)
            self.logger.info("%s Connecting to device %s using '%s'",
                             self.name, host_address, command_str)
            command.append("%s@%s" % (self.ssh_user, host_address))
        elif self.host and self.primary:
            self.logger.info(
                "Using device data host_address for primary connection.")
            command_str = " ".join(str(item) for item in command)
            self.logger.info("%s Connecting to device %s using '%s'",
                             self.name, self.host, command_str)
            command.append("%s@%s" % (self.ssh_user, self.host))
        else:
            raise JobError("Unable to identify host address. Primary? %s",
                           self.primary)
        command_str = " ".join(str(item) for item in command)
        shell = ShellCommand("%s\n" % command_str,
                             self.timeout,
                             logger=self.logger)
        if shell.exitstatus:
            raise JobError("%s command exited %d: %s" %
                           (self.command, shell.exitstatus, shell.readlines()))
        # SshSession monitors the pexpect
        connection = SShSession(self.job, shell)
        connection = super(ConnectSsh, self).run(connection, args)
        connection.sendline('export PS1="%s"' % DEFAULT_SHELL_PROMPT)
        connection.prompt_str = [DEFAULT_SHELL_PROMPT]
        connection.connected = True
        self.wait(connection)
        self.data["boot-result"] = 'failed' if self.errors else 'success'
        return connection
Пример #8
0
    def run(self, connection, args=None):
        """
        CommandRunner expects a pexpect.spawn connection which is the return value
        of target.device.power_on executed by boot in the old dispatcher.

        In the new pipeline, the pexpect.spawn is a ShellCommand and the
        connection is a ShellSession. CommandRunner inside the ShellSession
        turns the ShellCommand into a runner which the ShellSession uses via ShellSession.run()
        to run commands issued *after* the device has booted.
        pexpect.spawn is one of the raw_connection objects for a Connection class.
        """
        # initialise the first Connection object, a command line shell into the running QEMU.
        guest = self.get_common_data('guest', 'filename')
        if guest:
            self.logger.info("Extending command line for qcow2 test overlay")
            self.sub_command.append('-drive format=qcow2,file=%s,media=disk' %
                                    (os.path.realpath(guest)))
            # push the mount operation to the test shell pre-command to be run
            # before the test shell tries to execute.
            shell_precommand_list = []
            mountpoint = self.data['lava_test_results_dir']
            shell_precommand_list.append('mkdir %s' % mountpoint)
            shell_precommand_list.append('mount -L LAVA %s' % mountpoint)
            self.set_common_data('lava-test-shell', 'pre-command-list',
                                 shell_precommand_list)

        self.logger.info("Boot command: %s", ' '.join(self.sub_command))
        shell = ShellCommand(' '.join(self.sub_command),
                             self.timeout,
                             logger=self.logger)
        if shell.exitstatus:
            raise JobError(
                "%s command exited %d: %s" %
                (self.sub_command, shell.exitstatus, shell.readlines()))
        self.logger.debug("started a shell command")

        shell_connection = ShellSession(self.job, shell)
        if not shell_connection.prompt_str and self.parameters[
                'method'] == 'qemu':
            shell_connection.prompt_str = self.parameters['prompts']
        shell_connection = super(CallQemuAction,
                                 self).run(shell_connection, args)

        # FIXME: tests with multiple boots need to be handled too.
        self.data['boot-result'] = 'failed' if self.errors else 'success'
        return shell_connection
Пример #9
0
 def finalise_protocol(self, device=None):
     """Called by Finalize action to power down and clean up the assigned
     device.
     """
     # shutdown xnbd for the given device/job based in the port-number used
     try:
         self.logger.debug("%s cleanup", self.name)
         self.port = self.parameters['protocols']['lava-xnbd']['port']
         nbd_cmd = "pkill -f xnbd-server.*%s" % (self.port)
         shell = ShellCommand("%s\n" % nbd_cmd,
                              self.system_timeout,
                              logger=self.logger)
         shell.expect(pexpect.EOF)
     except Exception as e:
         self.logger.debug(str(e))
         self.logger.debug(
             "xnbd-finalize-protocol failed, but continuing anyway.")
Пример #10
0
    def run(self, connection, max_end_time, args=None):
        if connection:
            self.logger.debug("Already connected")
            return connection
        # ShellCommand executes the connection command

        params = self._check_params()
        command = self.command[:]  # local copy for idempotency
        overrides = None
        if self.key:
            overrides = self.get_namespace_data(action='prepare-scp-overlay', label="prepare-scp-overlay", key=self.key)
        host_address = None
        if overrides:
            host_address = str(self.get_namespace_data(
                action='prepare-scp-overlay', label="prepare-scp-overlay", key=overrides[0]))
        if host_address:
            self.logger.info("Using common data to retrieve host_address for secondary connection.")
            command_str = " ".join(str(item) for item in command)
            self.logger.info("%s Connecting to device %s using '%s'", self.name, host_address, command_str)
            command.append("%s@%s" % (self.ssh_user, host_address))
        elif self.host and self.primary:
            self.logger.info("Using device data host_address for primary connection.")
            command_str = " ".join(str(item) for item in command)
            self.logger.info("%s Connecting to device %s using '%s'", self.name, self.host, command_str)
            command.append("%s@%s" % (self.ssh_user, self.host))
        else:
            raise JobError("Unable to identify host address. Primary? %s", self.primary)
        command_str = " ".join(str(item) for item in command)
        shell = ShellCommand("%s\n" % command_str, self.timeout, logger=self.logger)
        if shell.exitstatus:
            raise JobError("%s command exited %d: %s" % (
                self.command, shell.exitstatus, shell.readlines()))
        # SshSession monitors the pexpect
        connection = SShSession(self.job, shell)
        connection = super(ConnectSsh, self).run(connection, max_end_time, args)
        connection.sendline('export PS1="%s"' % self.job.device.get_constant(
            'default-shell-prompt'))
        connection.prompt_str = [self.job.device.get_constant(
            'default-shell-prompt')]
        connection.connected = True
        self.wait(connection)
        res = 'failed' if self.errors else 'success'
        self.set_namespace_data(action='boot', label='shared', key='boot-result', value=res)
        self.set_namespace_data(action='shared', label='shared', key='connection', value=connection)
        return connection
Пример #11
0
 def run(self, connection, args=None):
     self._log("Boot command: %s" % ' '.join(self.command))
     # initialise the first Connection object, a command line shell into the running QEMU.
     # ShellCommand wraps pexpect.spawn.
     shell = ShellCommand(' '.join(self.command), self.timeout)
     if shell.exitstatus:
         raise JobError("%s command exited %d: %s" % (self.command, shell.exitstatus, shell.readlines()))
     self._log("started a shell command")
     # CommandRunner expects a pexpect.spawn connection which is the return value
     # of target.device.power_on executed by boot in the old dispatcher.
     #
     # In the new pipeline, the pexpect.spawn is a ShellCommand and the
     # connection is a ShellSession. CommandRunner inside the ShellSession
     # turns the ShellCommand into a runner which the ShellSession uses via ShellSession.run()
     # to run commands issued *after* the device has booted.
     # pexpect.spawn is one of the raw_connection objects for a Connection class.
     shell_connection = ShellSession(self.job.device, shell)
     self.pipeline.run_actions(shell_connection)
     return shell_connection
Пример #12
0
 def run(self, connection, args=None):
     if connection:
         self.logger.debug("Already connected")
         connection.prompt_str = self.job.device['test_image_prompts']
         return connection
     command = self.job.device['commands'][
         'connect'][:]  # local copy to retain idempotency.
     self.logger.info("%s Connecting to device using '%s'", self.name,
                      command)
     signal.alarm(0)  # clear the timeouts used without connections.
     # ShellCommand executes the connection command
     shell = ShellCommand("%s\n" % command, self.timeout)
     if shell.exitstatus:
         raise JobError("%s command exited %d: %s" %
                        (command, shell.exitstatus, shell.readlines()))
     # ShellSession monitors the pexpect
     connection = ShellSession(self.job, shell)
     connection.connected = True
     connection = super(ConnectDevice, self).run(connection, args)
     # append ser2net port to the prompt_str
     # FIXME: this improves speed but relies on using ser2net
     connection.prompt_str = self.job.device['test_image_prompts'].append(
         'ser2net port')
     return connection
Пример #13
0
    def run(self, connection, args=None):
        """
        CommandRunner expects a pexpect.spawn connection which is the return value
        of target.device.power_on executed by boot in the old dispatcher.

        In the new pipeline, the pexpect.spawn is a ShellCommand and the
        connection is a ShellSession. CommandRunner inside the ShellSession
        turns the ShellCommand into a runner which the ShellSession uses via ShellSession.run()
        to run commands issued *after* the device has booted.
        pexpect.spawn is one of the raw_connection objects for a Connection class.
        """
        if 'download_action' not in self.data:
            raise RuntimeError("Value for download_action is missing from %s" %
                               self.name)
        if 'image' not in self.data['download_action']:
            raise RuntimeError(
                "No image file setting from the download_action")
        command = self.get_common_data('qemu-command', 'command')
        command.extend(["-hda", self.data['download_action']['image']['file']])
        self.logger.info("Boot command: %s" % ' '.join(command))

        # initialise the first Connection object, a command line shell into the running QEMU.
        shell = ShellCommand(' '.join(command), self.timeout)
        if shell.exitstatus:
            raise JobError("%s command exited %d: %s" %
                           (command, shell.exitstatus, shell.readlines()))
        self.logger.debug("started a shell command")

        shell_connection = ShellSession(self.job, shell)
        shell_connection.prompt_str = self.job.device['test_image_prompts']
        shell_connection = super(CallQemuAction,
                                 self).run(shell_connection, args)

        # FIXME: tests with multiple boots need to be handled too.
        self.data['boot-result'] = 'failed' if self.errors else 'success'
        return shell_connection
Пример #14
0
    def finalise_protocol(self, device=None):
        """Called by Finalize action to power down and clean up the assigned
        device.
        """
        # Reboot devices to bootloader if required, based on the availability
        # of power cycle option and adb_serial_number.
        # Do not reboot to bootloader if 'reboot_to_fastboot' is set to
        # 'false' in job definition.
        if self.fastboot_reboot:
            if 'adb_serial_number' in device and hasattr(device, 'power_state'):
                if device.power_state not in ['on', 'off']:
                    reboot_cmd = "lxc-attach -n {0} -- adb reboot bootloader".format(self.lxc_name)
                    self.logger.debug("%s protocol: executing '%s'", self.name,
                                      reboot_cmd)
                    shell = ShellCommand("%s\n" % reboot_cmd,
                                         self.system_timeout,
                                         logger=self.logger)
                    # execute the command.
                    shell.expect(pexpect.EOF)
                    if shell.exitstatus:
                        self.logger.debug("%s command exited %d: %s",
                                          reboot_cmd,
                                          shell.exitstatus, shell.readlines())
        else:
            self.logger.info("%s protocol: device not rebooting to fastboot",
                             self.name)

        # Stop the container.
        self.logger.debug("%s protocol: issue stop", self.name)
        cmd = "lxc-stop -n {0} -k".format(self.lxc_name)
        shell = ShellCommand("%s\n" % cmd, self.system_timeout,
                             logger=self.logger)
        # execute the command.
        shell.expect(pexpect.EOF)
        if shell.exitstatus:
            self.logger.debug(
                "%s command exited %d: %s" % (cmd, shell.exitstatus,
                                              shell.readlines()))
        # Check if the container should persist and skip destroying it.
        if self.persistence:
            self.logger.debug("%s protocol: persistence requested",
                              self.name)
        else:
            self.logger.debug("%s protocol: destroy", self.name)
            if self.custom_lxc_path:
                abs_path = os.path.realpath(os.path.join(LXC_PATH,
                                                         self.lxc_name))
                cmd = "lxc-destroy -n {0} -f -P {1}".format(
                    self.lxc_name, os.path.dirname(abs_path))
            else:
                cmd = "lxc-destroy -n {0} -f".format(self.lxc_name)
                self.logger.debug("%s protocol: executing '%s'",
                                  self.name, cmd)
            shell = ShellCommand("%s\n" % cmd, self.system_timeout,
                                 logger=self.logger)
            # execute the command.
            shell.expect(pexpect.EOF)
            if shell.exitstatus:
                self.logger.debug(
                    "%s command exited %d: %s" % (cmd, shell.exitstatus,
                                                  shell.readlines()))
            if self.custom_lxc_path and not self.persistence:
                os.remove(os.path.join(LXC_PATH, self.lxc_name))
        self.logger.debug("%s protocol finalised.", self.name)
Пример #15
0
    def run(self, connection, max_end_time, args=None):
        """
        CommandRunner expects a pexpect.spawn connection which is the return value
        of target.device.power_on executed by boot in the old dispatcher.

        In the new pipeline, the pexpect.spawn is a ShellCommand and the
        connection is a ShellSession. CommandRunner inside the ShellSession
        turns the ShellCommand into a runner which the ShellSession uses via ShellSession.run()
        to run commands issued *after* the device has booted.
        pexpect.spawn is one of the raw_connection objects for a Connection class.
        """
        # initialise the first Connection object, a command line shell into the running QEMU.
        guest = self.get_namespace_data(action='apply-overlay-guest',
                                        label='guest',
                                        key='filename')
        # check for NFS
        if 'qemu-nfs' in self.methods and self.parameters.get('media',
                                                              None) == 'nfs':
            self.logger.debug("Adding NFS arguments to kernel command line.")
            root_dir = self.get_namespace_data(action='extract-rootfs',
                                               label='file',
                                               key='nfsroot')
            self.substitutions["{NFSROOTFS}"] = root_dir
            params = self.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 rw' %
                substitute([params['nfsrootargs']], self.substitutions)[0],
                "%s" % params['ipargs']
            ]
            self.sub_command.append('--append')
            self.sub_command.append('"%s"' % ' '.join(append))
        elif guest:
            self.logger.info("Extending command line for qcow2 test overlay")
            # interface is ide by default in qemu
            interface = self.job.device['actions']['deploy']['methods'][
                'image']['parameters']['guest'].get('interface', 'ide')
            self.sub_command.append(
                '-drive format=qcow2,file=%s,media=disk,if=%s' %
                (os.path.realpath(guest), interface))
            # push the mount operation to the test shell pre-command to be run
            # before the test shell tries to execute.
            shell_precommand_list = []
            mountpoint = self.get_namespace_data(action='test',
                                                 label='results',
                                                 key='lava_test_results_dir')
            uuid = '/dev/disk/by-uuid/%s' % self.get_namespace_data(
                action='apply-overlay-guest', label='guest', key='UUID')
            shell_precommand_list.append('mkdir %s' % mountpoint)
            # prepare_guestfs always uses ext2
            shell_precommand_list.append('mount %s -t ext2 %s' %
                                         (uuid, mountpoint))
            # debug line to show the effect of the mount operation
            # also allows time for kernel messages from the mount operation to be processed.
            shell_precommand_list.append('ls -la %s/bin/lava-test-runner' %
                                         mountpoint)
            self.set_namespace_data(action='test',
                                    label='lava-test-shell',
                                    key='pre-command-list',
                                    value=shell_precommand_list)

        self.logger.info("Boot command: %s", ' '.join(self.sub_command))
        shell = ShellCommand(' '.join(self.sub_command),
                             self.timeout,
                             logger=self.logger)
        if shell.exitstatus:
            raise JobError(
                "%s command exited %d: %s" %
                (self.sub_command, shell.exitstatus, shell.readlines()))
        self.logger.debug("started a shell command")

        shell_connection = ShellSession(self.job, shell)
        shell_connection = super(CallQemuAction,
                                 self).run(shell_connection, max_end_time,
                                           args)

        self.set_namespace_data(action='shared',
                                label='shared',
                                key='connection',
                                value=shell_connection)
        return shell_connection
Пример #16
0
 def run(self, connection, args=None):
     telnet = ShellCommand(self.job.device.parameters['connection_command'],
                           self.timeout)
     return Connection(self.job.device, telnet)