예제 #1
0
        def method(cmd_result):
            """
            Parse method for `systemctl list $name.service`.

            Return a dict from service name to status.

            e.g:
                {"sshd": "enabled",
                 "vsftpd": "disabled",
                 "systemd-sysctl": "static",
                 ...
                 }
            """
            if cmd_result.exit_status:
                raise process.CmdError(cmd_result.command, cmd_result)
            # Dict to store service name to status.
            _service2status_dict = {}
            lines = cmd_result.stdout_text.strip().splitlines()
            for line in lines:
                sublines = line.strip().split()
                if ((not len(sublines) == 2) or
                        (not sublines[0].endswith("service"))):
                    # Some lines useless.
                    continue
                service_name = sublines[0].rstrip(".service")
                status = sublines[-1]
                _service2status_dict[service_name] = status
            return _service2status_dict
예제 #2
0
def systemd_list_parser(cmdResult=None):
    """
    Parse method for service sub-command list.

    :return in form of dict-like, including service name, status and so on

    For example::

        {"sshd": "enabled",
         "vsftpd": "disabled",
         "systemd-sysctl": "static",
         ...
        }
    """
    if cmdResult.exit_status:
        raise process.CmdError(cmdResult.command, cmdResult)
    # store service name and status.
    _service2status_dict = {}
    lines = cmdResult.stdout_text.strip().splitlines()
    for line in lines:
        sublines = line.strip().split()
        if (not len(sublines) == 2) or (not sublines[0].endswith("service")):
            # Some lines useless.
            continue
        service_name = sublines[0].rstrip(".service")
        status = sublines[-1]
        _service2status_dict[service_name] = status
    return _service2status_dict
예제 #3
0
    def _dumpxml(name, to_file="", **dargs):
        """
        Get a xml from name.
        """
        if not name:
            cmd = "virsh dumpxml %s" % name
            stdout = "error: command 'dumpxml' requires <domain> option"
            stderr = stdout
            exit_status = 1
            result = process.CmdResult(cmd, stdout, stderr, exit_status)
            raise process.CmdError(cmd, result,
                                   "Virsh Command returned non-zero exit status")

        file_path = os.path.join(LibvirtXMLTestBase.__doms_dir__,
                                 '%s.xml' % name)
        if os.path.exists(file_path):
            xml_file = open(file_path, 'r')
            domain_xml = xml_file.read()
        else:
            xml_file = open(file_path, 'w')
            domain_xml = LibvirtXMLTestBase.__domain_xml__ % (name,
                                                              LibvirtXMLTestBase._domuuid(None))
            xml_file.write(domain_xml)
        xml_file.close()

        cmd = "virsh dumpxml %s" % name
        stdout = domain_xml
        stderr = ""
        exit_status = 0
        return process.CmdResult(cmd, stdout, stderr, exit_status)
예제 #4
0
    def _run(self, cmd, timeout, verbose, ignore_status, connect_timeout,
             env, options, args, log_file, watch_stdout_pattern):
        ssh_cmd = self.ssh_command(connect_timeout, options)
        if not env.strip():
            env = ""
        else:
            env = "export %s;" % env
        for arg in args:
            cmd += ' "%s"' % astring.shell_escape(arg)
        if env:
            full_cmd = '%s "%s %s"' % (ssh_cmd, env, astring.shell_escape(cmd))
        else:
            full_cmd = '%s "%s"' % (ssh_cmd, astring.shell_escape(cmd))
        result = ssh_run(full_cmd, verbose=verbose,
                         ignore_status=ignore_status, timeout=timeout,
                         extra_text=self.hostname, shell=True,
                         log_file=log_file,
                         watch_stdout_pattern=watch_stdout_pattern)

        # The error messages will show up in band (indistinguishable
        # from stuff sent through the SSH connection), so we have the
        # remote computer echo the message "Connected." before running
        # any cmd.  Since the following 2 errors have to do with
        # connecting, it's safe to do these checks.
        if result.exit_status == 255:
            if re.search(r'^ssh: connect to host .* port .*: '
                         r'Connection timed out\r$', result.stderr):
                raise SSHTimeout("SSH timed out:\n%s" % result)
            if "Permission denied." in result.stderr:
                raise SSHPermissionDeniedError("SSH permission denied:\n%s" %
                                               result)
        if not ignore_status and result.exit_status > 0:
            raise process.CmdError(command=full_cmd, result=result)
        return result
예제 #5
0
    def run(self, command, timeout=60, ignore_status=False):
        """
        Method to provide a utils.run-like interface to execute command on
        remote host or guest.

        :param timeout: Total time duration to wait for command return.
        :param ignore_status: If ignore_status=True, do not raise an exception,
                              no matter what the exit code of the command is.
                              Else, raise CmdError if exit code of command is not
                              zero.
        """
        # Redirect the stdout and stderr to file, Deviding error message
        # from output, and taking off the color of output. To return the same
        # result with utils.run() function.
        command = "%s 1>%s 2>%s" % (command, self.stdout_pipe,
                                    self.stderr_pipe)
        status, _ = self.session.cmd_status_output(command, timeout=timeout)
        output = self.session.cmd_output("cat %s;rm -f %s" %
                                         (self.stdout_pipe, self.stdout_pipe))
        errput = self.session.cmd_output("cat %s;rm -f %s" %
                                         (self.stderr_pipe, self.stderr_pipe))
        cmd_result = process.CmdResult(command=command,
                                       exit_status=status,
                                       stdout=output,
                                       stderr=errput)
        if status and (not ignore_status):
            raise process.CmdError(command, cmd_result)
        return cmd_result
예제 #6
0
    def ssh_run(self,
                cmd,
                timeout=None,
                verbose=True,
                ignore_status=False,
                allow_output_check='all',
                shell=False,
                env=None,
                extra_text=None,
                log_file=None,
                watch_stdout_pattern=None):
        sp = SSHSubProcess(cmd=cmd,
                           verbose=verbose,
                           allow_output_check=allow_output_check,
                           shell=shell,
                           env=env,
                           extra_text=extra_text,
                           log_file=log_file,
                           watch_stdout_pattern=watch_stdout_pattern)

        self.splist.append(sp)
        cmd_result = sp.run(timeout=timeout)
        sp.close_file_handler()
        self.splist.remove(sp)

        fail_condition = cmd_result.exit_status != 0 or cmd_result.interrupted
        if fail_condition and not ignore_status:
            raise process.CmdError(cmd, sp.result)
        return cmd_result
예제 #7
0
def run(command, ignore_status=False, quiet=True, timeout=60):
    """
    Executes a command on the defined fabric hosts.

    This is basically a wrapper to fabric.operations.run, encapsulating
    the result on an avocado process.CmdResult object. This also assumes
    the fabric environment was previously (and properly) initialized.

    :param command: the command string to execute.
    :param ignore_status: Whether to not raise exceptions in case the
        command's return code is different than zero.
    :param timeout: Maximum time allowed for the command to return.
    :param quiet: Whether to not log command stdout/err. Default: True.

    :return: the result of the remote program's execution.
    :rtype: :class:`avocado.utils.process.CmdResult`.
    :raise fabric.exceptions.CommandTimeout: When timeout exhausted.
    """

    result = process.CmdResult()
    start_time = time.time()
    end_time = time.time() + (timeout or 0)  # Support timeout=None
    # Fabric sometimes returns NetworkError even when timeout not reached
    fabric_result = None
    fabric_exception = None
    while True:
        try:
            fabric_result = fabric.operations.run(command=command,
                                                  quiet=quiet,
                                                  warn_only=True,
                                                  timeout=timeout,
                                                  pty=False,
                                                  combine_stderr=False)
            break
        except fabric.network.NetworkError as details:
            fabric_exception = details
            timeout = end_time - time.time()
        if time.time() > end_time:
            break
    if fabric_result is None:
        if fabric_exception is not None:
            raise fabric_exception  # it's not None pylint: disable=E0702
        else:
            raise fabric.network.NetworkError("Remote execution of '%s'"
                                              "failed without any "
                                              "exception. This should not "
                                              "happen." % command)
    end_time = time.time()
    duration = end_time - start_time
    result.command = command
    result.stdout = str(fabric_result.stdout)
    result.stderr = str(fabric_result.stderr)
    result.duration = duration
    result.exit_status = fabric_result.return_code
    result.failed = fabric_result.failed
    result.succeeded = fabric_result.succeeded
    if not ignore_status:
        if result.failed:
            raise process.CmdError(command=command, result=result)
    return result
예제 #8
0
    def run_systemdrun(self, command, internal_background=False, **kwargs):
        """
        execute command via systemd-run inside container

        :param command:
        :param internal_background:
        :param kwargs:
        :return:
        """
        if not kwargs:
            kwargs = {}
        self.__machined_restart()
        add_sleep_infinite = ""
        unit_name = common.generate_unique_name()
        lpath = "/var/tmp/{}".format(unit_name)
        if self.__systemd_wait_support:
            add_wait_var = "--wait"
        else:
            # keep service exist after it finish, to be able to read exit code
            add_wait_var = "-r"
        if internal_background:
            add_wait_var = ""
            add_sleep_infinite = "&& sleep infinity"
        opts = " --unit {unitname} {wait} -M {machine}".format(
            wait=add_wait_var, machine=self.name, unitname=unit_name)
        try:
            comout = process.run(
                """systemd-run {opts} /bin/bash -c "({comm})>{pin}.stdout 2>{pin}.stderr {sleep}" """
                .format(opts=opts,
                        comm=common.sanitize_cmd(command),
                        pin=lpath,
                        sleep=add_sleep_infinite), **kwargs)
            if not internal_background:
                if not self.__systemd_wait_support:
                    comout.exit_status = self.__systemctl_wait_until_finish(
                        self.name, unit_name)
                with open(
                        "{chroot}{pin}.stdout".format(chroot=self.location,
                                                      pin=lpath),
                        'r') as content_file:
                    comout.stdout = content_file.read()
                with open(
                        "{chroot}{pin}.stderr".format(chroot=self.location,
                                                      pin=lpath),
                        'r') as content_file:
                    comout.stderr = content_file.read()
                comout.command = command
                os.remove("{chroot}{pin}.stdout".format(chroot=self.location,
                                                        pin=lpath))
                os.remove("{chroot}{pin}.stderr".format(chroot=self.location,
                                                        pin=lpath))
                self.logger.debug(comout)
                if not self.__systemd_wait_support and not kwargs.get(
                        "ignore_status") and comout.exit_status != 0:
                    raise process.CmdError(comout.command, comout)
            return comout
        except process.CmdError as e:
            raise e
예제 #9
0
 def test_nasty_str(self):
     result = process.CmdResult("ls", b"unicode_follows: \xc5\xa1",
                                b"cp1250 follows: \xfd", 1, 2, 3,
                                "wrong_encoding")
     err = process.CmdError("ls", result, "please don't crash")
     self.assertEqual(str(err), "Command 'ls' failed.\nstdout: "
                      "b'unicode_follows: \\xc5\\xa1'\nstderr: "
                      "b'cp1250 follows: \\xfd'\nadditional_info: "
                      "please don't crash")
예제 #10
0
    def run_output_check(self, cmd, timeout=None, ignore_status=False,
                         stdout_ok_regexp=None, stdout_err_regexp=None,
                         stderr_ok_regexp=None, stderr_err_regexp=None,
                         connect_timeout=300):
        """
        Run a cmd on the remote host, check output to determine success.

        :param cmd: The cmd line string.
        :param timeout: Time limit in seconds before attempting to kill the
            running process. The run() function will take a few seconds
            longer than 'timeout' to complete if it has to kill the process.
        :param ignore_status: Do not raise an exception, no matter
            what the exit code of the cmd is.
        :param stdout_ok_regexp: Regular expression that should be in stdout
            if the cmd was successul.
        :param stdout_err_regexp: Regular expression that should be in stdout
            if the cmd failed.
        :param stderr_ok_regexp: regexp that should be in stderr if the
            cmd was successul.
        :param stderr_err_regexp: Regexp that should be in stderr if the
            cmd failed.
        :param connect_timeout: Connection timeout that will be passed to run.

        :raises: OutputCheckError under the following conditions:
            - The exit code of the cmd execution was not 0.
            - If stderr_err_regexp is found in stderr,
            - If stdout_err_regexp is found in stdout,
            - If stderr_ok_regexp is not found in stderr.
            - If stdout_ok_regexp is not found in stdout,
        """

        # We ignore the status, because we will handle it at the end.
        result = self.run(cmd=cmd, timeout=timeout, ignore_status=True,
                          connect_timeout=connect_timeout)

        # Look for the patterns, in order
        for (regexp, stream) in ((stderr_err_regexp, result.stderr),
                                 (stdout_err_regexp, result.stdout)):
            if regexp and stream:
                err_re = re.compile(regexp)
                if err_re.search(stream):
                    e_msg = ('%s failed, found error pattern: "%s"' %
                             (cmd, regexp))
                    raise OutputCheckError(e_msg, result)

        for (regexp, stream) in ((stderr_ok_regexp, result.stderr),
                                 (stdout_ok_regexp, result.stdout)):
            if regexp and stream:
                ok_re = re.compile(regexp)
                if ok_re.search(stream):
                    if ok_re.search(stream):
                        return

        if not ignore_status and result.exit_status > 0:
            raise process.CmdError(command=result.command, result=result)
예제 #11
0
    def test_safe_kill_sudo_enabled_with_exception(self, owner_mocked, run_mocked):
        owner_id = 0
        process_id = 123
        signal = 1
        owner_mocked.return_value = owner_id
        expected_cmd = 'kill -%d %d' % (signal, process_id)
        run_mocked.side_effect = process.CmdError()

        killed = process.safe_kill(process_id, signal)
        self.assertFalse(killed)
        run_mocked.assert_called_with(expected_cmd, sudo=True)
예제 #12
0
def run(cmd, timeout=60, env=None, log_error=True):
    if isinstance(cmd, list):
        cmd = ' '.join(['"%s"' % arg for arg in cmd])

    result = process.run(cmd, verbose=False, ignore_status=True, env=env)
    if result.exit_status != 0:
        if log_error:
            logging.error(result)
        raise process.CmdError(cmd, result)

    return result.stdout
예제 #13
0
        def method(cmd_result):
            """
            Parse method for `service $name list`.

            Return dict from service name to status.

            >>> {"sshd": {0: 'off', 1: 'off', 2: 'off', 3: 'off', 4: 'off',
            >>>           5: 'off', 6: 'off'},
            >>>  "vsftpd": {0: 'off', 1: 'off', 2: 'off', 3: 'off', 4: 'off',
            >>>             5: 'off', 6: 'off'},
            >>>  "xinetd": {'discard-dgram:': 'off',
            >>>             'rsync:': 'off'...'chargen-stream:': 'off'},
            >>>  ...
            >>>  }
            """
            if cmd_result.exit_status:
                raise process.CmdError(cmd_result.command, cmd_result)
            # The final dict to return.
            services_statuses_dict = {}
            # Dict to store status on every target for each service.
            status_per_target_dict = {}
            # Dict to store the status for service based on xinetd.
            xinet_services_dict = {}
            lines = cmd_result.stdout_text.strip().splitlines()
            for line in lines:
                sublines = line.strip().split()
                if len(sublines) == 8:
                    # Service and status on each target.
                    service_name = sublines[0]
                    # Store the status of each target in status_per_target_dict
                    for target in range(7):
                        status = sublines[target + 1].split(":")[-1]
                        status_per_target_dict[target] = status
                    services_statuses_dict[service_name] = (
                        status_per_target_dict.copy())

                elif len(sublines) == 2:
                    # Service based on xinetd.
                    service_name = sublines[0].strip(":")
                    status = sublines[-1]
                    xinet_services_dict[service_name] = status

                else:
                    # Header or some lines useless.
                    continue
            # Add xinetd based service in the main dict.
            services_statuses_dict["xinetd"] = xinet_services_dict
            return services_statuses_dict
예제 #14
0
 def cmd_result(self, cmd, ignore_status=False, debug=False, timeout=60):
     """
     Mimic process.run()
     :param cmd: virtadmin command to send.
     :param timeout: Time we'll wait until the process is finished.
     :returns: The command result object.
     """
     exit_status, stdout = self.cmd_status_output(cmd, timeout=timeout)
     stderr = ''  # no way to retrieve this separately
     result = process.CmdResult(cmd, stdout, stderr, exit_status)
     if not ignore_status and exit_status:
         raise process.CmdError(
             cmd, result, "Virtadmin Command returned non-zero exit status")
     if debug:
         logging.debug(result)
     return result
예제 #15
0
def sysvinit_list_parser(cmdResult=None):
    """
    Parse method for service sub-command list.

    :return in form of dict-like, including service name, status and so on

    For example::

        {"sshd":   {0: 'off', 1: 'off', 2: 'off', ..., 6: 'off'},
         "vsftpd": {0: 'off', 1: 'off', 2: 'off', ..., 6: 'off'},
         "xinetd": {'discard-dgram:': 'off', 'rsync:': 'on',...},
         ...
        }
    """
    if cmdResult.exit_status:
        raise process.CmdError(cmdResult.command, cmdResult)
    # The final dict to return.
    _service2statusOnTarget_dict = {}
    # Dict to store status on every target for each service.
    _status_on_target = {}
    # Dict to store the status for service based on xinetd.
    _service2statusOnXinet_dict = {}
    lines = cmdResult.stdout_text.strip().splitlines()
    for line in lines:
        sublines = line.strip().split()
        if len(sublines) == 8:
            # Service and status on each target.
            service_name = sublines[0]
            # Store the status of each target in _status_on_target.
            for target in range(7):
                status = sublines[target + 1].split(":")[-1]
                _status_on_target[target] = status
            _service2statusOnTarget_dict[
                service_name] = _status_on_target.copy()

        elif len(sublines) == 2:
            # Service based on xinetd.
            service_name = sublines[0].strip(":")
            status = sublines[-1]
            _service2statusOnXinet_dict[service_name] = status

        else:
            # Header or some lines useless.
            continue
    # Add xinetd based service in the main dict.
    _service2statusOnTarget_dict["xinetd"] = _service2statusOnXinet_dict
    return _service2statusOnTarget_dict
예제 #16
0
def check_qemu_image_lock_support():
    """
    QEMU commit 244a566(qemu-2.10) introduced the image locking feature which brought
    a new option '-U' to the qemu-img command:info, compare, check, bench, convert,
    dd, map, snapshot, rebase. This method provides one way to determine whether
    current qemu-img support or not.

    :return: True if current qemu-img command support
    """
    cmd = "qemu-img"
    try:
        binary_path = decode_to_text(process.system_output("which %s" % cmd))
    except process.CmdError:
        raise process.CmdError(cmd, binary_path,
                               "qemu-img command is not found")
    cmd_result = process.run(binary_path + ' -h', ignore_status=True,
                             shell=True, verbose=False)
    return '-U' in results_stdout_52lts(cmd_result)
예제 #17
0
    def run(self, command, ignore_status=False, quiet=None, timeout=60):
        """
        Run command inside the container
        """
        def print_func(*args, **kwargs):    # pylint: disable=W0613
            """ Accept anything and does nothing """

        if timeout is None:
            timeout = 31536000  # aexpect does not support None, use one year
        start = time.time()
        if quiet is not False:
            print_func = logging.getLogger('avocado.remote').debug
        status, output = self._docker.cmd_status_output(command,
                                                        timeout=timeout,
                                                        print_func=print_func)
        result = process.CmdResult(command, output, '', status,
                                   time.time() - start)
        if status and not ignore_status:
            raise process.CmdError(command, result, "in container %s"
                                   % self._docker_id)
        return result
예제 #18
0
    def run_machinectl(self, command, **kwargs):
        """
        execute command via machinectl shell inside container

        :param command:
        :param kwargs:
        :return:
        """
        self.__machined_restart()
        lpath = "/var/tmp"
        if not kwargs:
            kwargs = {}
        should_ignore = kwargs.get("ignore_status")
        kwargs["ignore_status"] = True
        comout = process.run(
            """machinectl shell root@{machine} /bin/bash -c "({comm})>{pin}/stdout 2>{pin}/stderr; echo $?>{pin}/retcode; sleep {defaultsleep}" """
            .format(machine=self.name,
                    comm=common.sanitize_cmd(command),
                    pin=lpath,
                    defaultsleep=self.__default_command_sleep), **kwargs)
        if comout.exit_status != 0:
            raise mtfexceptions.NspawnExc(
                "This command should not fail anyhow inside NSPAWN:", command)
        try:
            kwargs["verbose"] = False
            b = process.run(
                'bash -c "cat {chroot}{pin}/stdout; cat {chroot}{pin}/stderr > /dev/stderr; exit `cat {chroot}{pin}/retcode`"'
                .format(chroot=self.location, pin=lpath), **kwargs)
        finally:
            comout.stdout = b.stdout
            comout.stderr = b.stderr
            comout.exit_status = b.exit_status
            removesworkaround = re.search('[^(]*\((.*)\)[^)]*', comout.command)
            if removesworkaround:
                comout.command = removesworkaround.group(1)
            if comout.exit_status == 0 or should_ignore:
                return comout
            else:
                raise process.CmdError(comout.command, comout)
예제 #19
0
            raise fabric.network.NetworkError("Remote execution of '%s'"
                                              "failed without any "
                                              "exception. This should not "
                                              "happen." % command)
    end_time = time.time()
    duration = end_time - start_time
    result.command = command
    result.stdout = str(fabric_result.stdout)
    result.stderr = str(fabric_result.stderr)
    result.duration = duration
    result.exit_status = fabric_result.return_code
    result.failed = fabric_result.failed
    result.succeeded = fabric_result.succeeded
    if not ignore_status:
        if result.failed:
            raise process.CmdError(command=command, result=result)
    return result


def send_files(local_path, remote_path):
    """
    Send files to the defined fabric host.

    This assumes the fabric environment was previously (and properly)
    initialized.

    :param local_path: the local path.
    :param remote_path: the remote path.
    """
    try:
        fabric.operations.put(local_path, remote_path, mirror_local_mode=True)
def run(test, params, env):
    """
    Stress test for the hotplug feature of usb device.
    """
    # get the params from params
    vm_name = params.get("main_vm", "avocado-vt-vm1")
    vm = env.get_vm(vm_name)

    keyboard = "yes" == params.get("usb_hotplug_keyboard", "no")
    mouse = "yes" == params.get("usb_hotplug_mouse", "no")
    tablet = "yes" == params.get("usb_hotplug_tablet", "no")
    disk = "yes" == params.get("usb_hotplug_disk", "no")

    attach_count = int(params.get("attach_count", "1"))
    attach_type = params.get("attach_type", "attach_device")
    bench_type = params.get("guest_bench", None)
    control_file = params.get("control_file", None)

    status_error = ("yes" == params.get("status_error", "no"))

    vm_xml = VMXML.new_from_inactive_dumpxml(vm_name)
    vm_xml_backup = vm_xml.copy()

    tmp_dir = os.path.join(data_dir.get_tmp_dir(), "usb_hotplug_files")

    if control_file is not None:
        params["test_control_file"] = control_file
        params["main_vm"] = vm_name
        control_path = os.path.join(test.virtdir, "control", control_file)

        session = vm.wait_for_login()
        command = utils_test.run_autotest(vm,
                                          session,
                                          control_path,
                                          None,
                                          None,
                                          params,
                                          copy_only=True)
        session.cmd("%s &" % command)

        def _is_iozone_running():
            session_tmp = vm.wait_for_login()
            return (
                not session_tmp.cmd_status("ps -ef|grep iozone|grep -v grep"))

        def _is_stress_running():
            session_tmp = vm.wait_for_login()
            return (
                not session_tmp.cmd_status("ps -ef|grep stress|grep -v grep"))

        if bench_type == "stress":
            if not utils_misc.wait_for(_is_stress_running, timeout=160):
                test.cancel("Failed to run stress in guest.\n"
                            "Since we need to run a autotest of iozone "
                            "in guest, so please make sure there are "
                            "some necessary packages in guest,"
                            "such as gcc, tar, bzip2")
        elif bench_type == "iozone":
            if not utils_misc.wait_for(_is_iozone_running, timeout=160):
                test.cancel("Failed to run iozone in guest.\n"
                            "Since we need to run a autotest of iozone "
                            "in guest, so please make sure there are "
                            "some necessary packages in guest,"
                            "such as gcc, tar, bzip2")
        logging.debug("bench is already running in guest.")
    try:
        try:
            result = None
            disk_xml = None
            tablet_xml = None
            mouse_xml = None
            if not os.path.isdir(tmp_dir):
                os.mkdir(tmp_dir)
            for i in range(attach_count):
                path = os.path.join(tmp_dir, "%s.img" % i)
                if attach_type == "qemu_monitor":
                    options = "--hmp"
                    if disk:
                        utils_test.libvirt.create_local_disk("file",
                                                             path,
                                                             size="1M")
                        attach_cmd = "drive_add"
                        attach_cmd += (
                            " 0 id=drive-usb-disk%s,if=none,file=%s" %
                            (i, path))

                        result = virsh.qemu_monitor_command(vm_name,
                                                            attach_cmd,
                                                            options=options)
                        if result.exit_status:
                            raise process.CmdError(result.command, result)
                    if keyboard:
                        attach_cmd = "device_add"
                        attach_cmd += " usb-kdb,bus=usb1.0,id=kdb"

                        result = virsh.qemu_monitor_command(vm_name,
                                                            attach_cmd,
                                                            options=options)
                        if result.exit_status:
                            raise process.CmdError(result.command, result)
                    if mouse:
                        attach_cmd = "device_add"
                        attach_cmd += " usb-mouse,bus=usb1.0,id=mouse"

                        result = virsh.qemu_monitor_command(vm_name,
                                                            attach_cmd,
                                                            options=options)
                        if result.exit_status:
                            raise process.CmdError(result.command, result)
                    if tablet:
                        attach_cmd = "device_add"
                        attach_cmd += " usb-tablet,bus=usb1.0,id=tablet"

                        result = virsh.qemu_monitor_command(vm_name,
                                                            attach_cmd,
                                                            options=options)
                        if result.exit_status:
                            raise process.CmdError(result.command, result)
                else:
                    if disk:
                        utils_test.libvirt.create_local_disk("file",
                                                             path,
                                                             size="1M")
                        os.chmod(path, 0o666)
                        disk_xml = Disk(type_name="file")
                        disk_xml.device = "disk"
                        disk_xml.source = disk_xml.new_disk_source(
                            **{"attrs": {
                                'file': path
                            }})
                        disk_xml.driver = {
                            "name": "qemu",
                            "type": 'raw',
                            "cache": "none"
                        }
                        disk_xml.target = {"dev": 'sdb', "bus": "usb"}

                        attributes = {
                            'type_name': "usb",
                            'bus': "1",
                            'port': "0"
                        }
                        disk_xml.address = disk_xml.new_disk_address(
                            **{"attrs": attributes})

                        result = virsh.attach_device(vm_name, disk_xml.xml)
                        if result.exit_status:
                            raise process.CmdError(result.command, result)
                    if mouse:
                        mouse_xml = Input("mouse")
                        mouse_xml.input_bus = "usb"
                        attributes = {
                            'type_name': "usb",
                            'bus': "1",
                            'port': "0"
                        }
                        mouse_xml.address = mouse_xml.new_input_address(
                            **{"attrs": attributes})

                        result = virsh.attach_device(vm_name, mouse_xml.xml)
                        if result.exit_status:
                            raise process.CmdError(result.command, result)
                    if tablet:
                        tablet_xml = Input("tablet")
                        tablet_xml.input_bus = "usb"
                        attributes = {
                            'type_name': "usb",
                            'bus': "1",
                            'port': "0"
                        }
                        tablet_xml.address = tablet_xml.new_input_address(
                            **{"attrs": attributes})

                        result = virsh.attach_device(vm_name, tablet_xml.xml)
                        if result.exit_status:
                            raise process.CmdError(result.command, result)
                    if keyboard:
                        kbd_xml = Input("keyboard")
                        kbd_xml.input_bus = "usb"
                        attributes = {
                            'type_name': "usb",
                            'bus': "1",
                            'port': "0"
                        }
                        kbd_xml.address = kbd_xml.new_input_address(
                            **{"attrs": attributes})

                        result = virsh.attach_device(vm_name, kbd_xml.xml)
                        if result.exit_status:
                            raise process.CmdError(result.command, result)

                if attach_type == "qemu_monitor":
                    options = "--hmp"
                    if disk:
                        attach_cmd = "drive_del"
                        attach_cmd += (" drive-usb-disk")

                        result = virsh.qemu_monitor_command(vm_name,
                                                            attach_cmd,
                                                            options=options)
                        if result.exit_status:
                            raise process.CmdError(result.command, result)
                    if mouse:
                        attach_cmd = "device_del"
                        attach_cmd += (" mouse")

                        result = virsh.qemu_monitor_command(vm_name,
                                                            attach_cmd,
                                                            options=options)
                        if result.exit_status:
                            raise process.CmdError(result.command, result)
                    if keyboard:
                        attach_cmd = "device_del"
                        attach_cmd += (" keyboard")

                        result = virsh.qemu_monitor_command(vm_name,
                                                            attach_cmd,
                                                            options=options)
                        if result.exit_status:
                            raise process.CmdError(result.command, result)
                    if tablet:
                        attach_cmd = "device_del"
                        attach_cmd += (" tablet")

                        result = virsh.qemu_monitor_command(vm_name,
                                                            attach_cmd,
                                                            options=options)
                        if result.exit_status:
                            raise process.CmdError(result.command, result)
                else:
                    if disk:
                        result = virsh.detach_device(vm_name, disk_xml.xml)
                        if result.exit_status:
                            raise process.CmdError(result.command, result)
                    if mouse:
                        result = virsh.detach_device(vm_name, mouse_xml.xml)
                        if result.exit_status:
                            raise process.CmdError(result.command, result)
                    if keyboard:
                        result = virsh.detach_device(vm_name, kbd_xml.xml)
                        if result.exit_status:
                            raise process.CmdError(result.command, result)
                    if tablet:
                        result = virsh.detach_device(vm_name, tablet_xml.xml)
                        if result.exit_status:
                            raise process.CmdError(result.command, result)
        except process.CmdError as e:
            if not status_error:
                test.fail("failed to attach device.\n" "Detail: %s." % result)
    finally:
        if os.path.isdir(tmp_dir):
            shutil.rmtree(tmp_dir)
        vm_xml_backup.sync()
예제 #21
0
def run(test, params, env):
    """
    Test for hotplug usb device.
    """
    # get the params from params
    vm_name = params.get("main_vm", "avocado-vt-vm1")
    vm = env.get_vm(vm_name)

    usb_type = params.get("usb_type", "kbd")
    attach_type = params.get("attach_type", "attach_device")
    attach_count = int(params.get("attach_count", "1"))
    if usb_type == "storage":
        model = params.get("model", "nec-xhci")
        index = params.get("index", "1")
    status_error = ("yes" == params.get("status_error", "no"))

    vm_xml = VMXML.new_from_inactive_dumpxml(vm_name)
    vm_xml_backup = vm_xml.copy()

    # Set selinux of host.
    backup_sestatus = utils_selinux.get_status()
    utils_selinux.set_status("permissive")

    if usb_type == "storage":
        controllers = vm_xml.get_devices(device_type="controller")
        devices = vm_xml.get_devices()
        for dev in controllers:
            if dev.type == "usb" and dev.index == "1":
                devices.remove(dev)
        controller = Controller("controller")
        controller.type = "usb"
        controller.index = index
        controller.model = model
        devices.append(controller)
        vm_xml.set_devices(devices)

    try:
        session = vm.wait_for_login()
    except (LoginError, VMError, ShellError) as e:
        test.fail("Test failed: %s" % str(e))

    def is_hotplug_ok():
        try:
            output = session.cmd_output(
                "fdisk -l | grep -c '^Disk /dev/.* 1 M'")
            if int(output.strip()) != attach_count:
                return False
            else:
                return True
        except ShellTimeoutError as detail:
            test.fail("unhotplug failed: %s, " % detail)

    tmp_dir = os.path.join(data_dir.get_tmp_dir(), "usb_hotplug_files")
    if not os.path.isdir(tmp_dir):
        os.mkdir(tmp_dir)

    try:
        result = None
        dev_xml = None
        opt = "--hmp"
        for i in range(attach_count):
            if usb_type == "storage":
                path = os.path.join(tmp_dir, "%s.img" % i)
                libvirt.create_local_disk("file",
                                          path,
                                          size="1M",
                                          disk_format="qcow2")
                os.chmod(path, 0o666)

            if attach_type == "qemu_monitor":
                if usb_type == "storage":
                    attach_cmd = "drive_add"
                    attach_cmd += (" 0 id=drive-usb-%s,if=none,file=%s" %
                                   (i, path))

                    result = virsh.qemu_monitor_command(vm_name,
                                                        attach_cmd,
                                                        options=opt)
                    if result.exit_status or (result.stdout.strip().find("OK")
                                              == -1):
                        raise process.CmdError(result.command, result)

                    attach_cmd = "device_add usb-storage,"
                    attach_cmd += (
                        "id=drive-usb-%s,bus=usb1.0,drive=drive-usb-%s" %
                        (i, i))
                else:
                    attach_cmd = "device_add"
                    attach_cmd += " usb-%s,bus=usb1.0,id=%s%s" % (usb_type,
                                                                  usb_type, i)

                result = virsh.qemu_monitor_command(vm_name,
                                                    attach_cmd,
                                                    options=opt)
                if result.exit_status:
                    raise process.CmdError(result.command, result)
            else:
                attributes = {'type_name': "usb", 'bus': "1", 'port': "0"}
                if usb_type == "storage":
                    dev_xml = Disk(type_name="file")
                    dev_xml.device = "disk"
                    dev_xml.source = dev_xml.new_disk_source(
                        **{"attrs": {
                            'file': path
                        }})
                    dev_xml.driver = {
                        "name": "qemu",
                        "type": 'qcow2',
                        "cache": "none"
                    }
                    dev_xml.target = {"dev": 'sdb', "bus": "usb"}
                    dev_xml.address = dev_xml.new_disk_address(
                        **{"attrs": attributes})
                else:
                    if usb_type == "mouse":
                        dev_xml = Input("mouse")
                    elif usb_type == "tablet":
                        dev_xml = Input("tablet")
                    else:
                        dev_xml = Input("keyboard")

                    dev_xml.input_bus = "usb"
                    dev_xml.address = dev_xml.new_input_address(
                        **{"attrs": attributes})

                result = virsh.attach_device(vm_name, dev_xml.xml)
                if result.exit_status:
                    raise process.CmdError(result.command, result)

        if status_error and usb_type == "storage":
            if utils_misc.wait_for(is_hotplug_ok, timeout=30):
                # Sometimes we meet an error but the ret in $? is 0.
                test.fail("\nAttach device successfully in negative case."
                          "\nExcept it fail when attach count exceed maximum."
                          "\nDetail: %s" % result)

        for i in range(attach_count):
            attach_cmd = "device_del"
            if attach_type == "qemu_monitor":
                if usb_type == "storage":
                    attach_cmd += (" drive-usb-%s" % i)
                else:
                    if usb_type == "mouse":
                        attach_cmd += " mouse"
                    elif usb_type == "tablet":
                        attach_cmd += " tablet"
                    else:
                        attach_cmd += " keyboard"

                result = virsh.qemu_monitor_command(vm_name,
                                                    attach_cmd,
                                                    options=opt)
                if result.exit_status:
                    raise process.CmdError(result.command, result)
            else:
                result = virsh.detach_device(vm_name, dev_xml.xml)
                if result.exit_status:
                    raise process.CmdError(result.command, result)
    except process.CmdError as e:
        if not status_error:
            # live attach of device 'input' is not supported
            ret = result.stderr.find("Operation not supported")
            if usb_type != "storage" and ret > -1:
                pass
            else:
                test.fail("failed to attach device.\nDetail: %s." % result)
    finally:
        session.close()
        if os.path.isdir(tmp_dir):
            shutil.rmtree(tmp_dir)
        utils_selinux.set_status(backup_sestatus)
        vm_xml_backup.sync()
예제 #22
0
                                          path,
                                          size="1M",
                                          disk_format="qcow2")
                os.chmod(path, 0666)

            if attach_type == "qemu_monitor":
                if usb_type == "storage":
                    attach_cmd = "drive_add"
                    attach_cmd += (" 0 id=drive-usb-%s,if=none,file=%s" %
                                   (i, path))

                    result = virsh.qemu_monitor_command(vm_name,
                                                        attach_cmd,
                                                        options=opt)
                    if result.exit_status or (result.stdout.find("OK") == -1):
                        raise process.CmdError(result.command, result)

                    attach_cmd = "device_add usb-storage,"
                    attach_cmd += (
                        "id=drive-usb-%s,bus=usb1.0,drive=drive-usb-%s" %
                        (i, i))
                else:
                    attach_cmd = "device_add"
                    attach_cmd += " usb-%s,bus=usb1.0,id=%s%s" % (usb_type,
                                                                  usb_type, i)

                result = virsh.qemu_monitor_command(vm_name,
                                                    attach_cmd,
                                                    options=opt)
                if result.exit_status:
                    raise process.CmdError(result.command, result)