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
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
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)
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
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
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
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
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
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")
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)
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)
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
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
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
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
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)
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
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)
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()
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()
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)