def test_args_zipl(self, *mocks): update_boot_option(self.vm, args_added="3", need_reboot=False, guest_arch_name="s390x") utils_test.check_kernel_cmdline.assert_called_once() self.assertEqual(2, self.session.cmd_status_output.call_count)
def run(test, params, env): """ support Virtual SPEC_CTRL inside guest 1. check the 'v_spec_ctrl' on supported host 2. add guest kernel command line 'spec_store_bypass_disable=on' 3. verify the guest sets the spec ctrl properly on all the cpus. :param test: QEMU test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ flags = params["flags"] check_host_flags = params.get_boolean("check_host_flags") if check_host_flags: check_cpu_flags(params, flags, test) supported_models = params.get("supported_models", "") cpu_model = params.get("cpu_model") if not cpu_model: cpu_model = cpu.get_qemu_best_cpu_model(params) if cpu_model not in supported_models.split(): test.cancel("'%s' doesn't support this test case" % cpu_model) params["start_vm"] = "yes" vm_name = params['main_vm'] env_process.preprocess_vm(test, params, env, vm_name) proc_cmdline = params["proc_cmdline"] vm = env.get_vm(vm_name) session = vm.wait_for_login() boot_option = params["boot_option"] check_output = str(session.cmd(proc_cmdline, timeout=60)).split() if boot_option and boot_option not in check_output: error_context.context("Add '%s' to guest" % boot_option, test.log.info) update_boot_option(vm, args_added=boot_option) session = vm.wait_for_login() test_dir = params["test_dir"] source_file = params["source_file"] src_msr = os.path.join(data_dir.get_deps_dir(), source_file) vm.copy_files_to(src_msr, test_dir) guest_dir = params["guest_dir"] compile_cmd = params["compile_cmd"] try: session.cmd(compile_cmd % guest_dir) check_msr = 'cd %s && ' % guest_dir + params["check_msr"] result = session.cmd_output(check_msr) nums_vcpus = session.cmd_output("grep processor /proc/cpuinfo -c") if result != nums_vcpus: test.fail("verify the guest sets the spec ctrl failed.") finally: session.cmd("rm -rf %s/msr* %s/master*" % (test_dir, test_dir)) session.close() vm.verify_kernel_crash() if boot_option and boot_option not in check_output: update_boot_option(vm, args_removed=boot_option)
def test_cmd_fail(self, *mocks): self.session.cmd_status_output.return_value = [ 1, self.some_error_message ] with self.assertRaises(exceptions.TestError) as e: update_boot_option(self.vm, args_added="3", need_reboot=False) self.assertIsNotNone(e.exception.args[0]) LOG.error.assert_called_with(self.some_error_message)
def run(test, params, env): """ Test to disabling radix MMU mode on guest. Steps: 1) There are two options, boot up a native(radix)guest or HPT guest. 2) Check the MMU mode in the guest. 3) Adding disable radix to guest's kernel line directly then reboot guest. 4) Check again the MMU mode in the guest. 5) Check guest call trace in dmesg log. :params test: QEMU test object. :params params: Dictionary with the test parameters. :params env: Dictionary with test environment. """ def cpu_info_match(pattern): match = re.search(pattern, session.cmd_output("cat /proc/cpuinfo")) return True if match else False vm = env.get_vm(params["main_vm"]) vm.verify_alive() session = vm.wait_for_login() error_context.context("Check the MMU mode.", logging.info) if cpu_info_match('MMU'): if cpu_info_match('POWER9'): if cpu_info_match('Radix') is False: test.fail("mmu mode is not Radix, doesn't meet expectations.") else: if cpu_info_match('Hash') is False: test.fail("mmu mode is not Hash, doesn't meet expectations.") else: if params["mmu_option"] == 'yes': test.fail("There should be MMU mode.") utils_test.update_boot_option(vm, args_added="disable_radix") session = vm.wait_for_login() error_context.context("Check the MMU mode.", logging.info) if cpu_info_match('MMU'): if cpu_info_match('Hash') is False: test.fail("mmu mode is not Hash, mmu mode disabled failure.") else: if params["mmu_option"] == 'yes': test.fail("There should be MMU mode.") vm.verify_dmesg()
def update_clksrc(vm, clksrc=None): """ Update linux guest's clocksource and re-boot guest :params vm: Virtual machine for vm :params clksrc: Expected clocksource """ params = vm.get_params() if 'fedora' in params["os_variant"] and clksrc and clksrc != 'kvm-clock': cpu_model_flags = params.get["cpu_model_flags"] params["cpu_model_flags"] = cpu_model_flags + ",-kvmclock" error_context.context("Update guest kernel cli to '%s'" % (clksrc or "kvm-clock"), logging.info) if clksrc: boot_option_added = "clocksource=%s" % clksrc utils_test.update_boot_option(vm, args_added=boot_option_added)
def update_clksrc(vm, clksrc=None): """ Update linux guest's clocksource and re-boot guest :params vm: Virtual machine for vm :params clksrc: Expected clocksource, 'kvm-clock' by default """ params = vm.get_params() if 'fedora' in params["os_variant"] and clksrc and clksrc != 'kvm-clock': cpu_model_flags = params.get["cpu_model_flags"] params["cpu_model_flags"] = cpu_model_flags + ",-kvmclock" error_context.context("Update guest kernel cli to '%s'" % (clksrc or "kvm-clock"), logging.info) utils_test.update_boot_option(vm, args_removed="clocksource=*") if clksrc and clksrc != 'kvm-clock': boot_option_added = "clocksource=%s" % clksrc utils_test.update_boot_option(vm, args_added=boot_option_added)
def start_test(self): operation = self.params["operation"] target_mems = self.params["target_mems"] stage = self.params.get("stage", "before") login_timeout = int(self.params.get("login_timeout", 360)) sub_test_runner = ( stage == 'during' and [ self.run_background_test] or [ self.run_sub_test])[0] func = getattr(self, "%s_memory" % operation) if not callable(func): self.test.error("Unsupported memory operation '%s'" % operation) vm = self.env.get_vm(self.params["main_vm"]) vm.wait_for_login(timeout=login_timeout) bootup_time = time.time() - vm.start_time utils_test.update_boot_option(vm, args_added="movable_node") try: if stage != "after": sub_test = sub_test_runner() if self.params.get("sub_type") == "boot": time.sleep(bootup_time/2) for target_mem in target_mems.split(): func(vm, target_mem) self.check_memory(vm) else: for target_mem in target_mems.split(): func(vm, target_mem) self.check_memory(vm) sub_test = sub_test_runner() if stage == "during": sub_test.join(timeout=3600) vm = self.env.get_vm(self.params["main_vm"]) vm.reboot() finally: try: self.restore_memory( vm, self.env.get_vm( self.params['main_vm'])) except Exception as details: logging.warn("Error happen when restore vm: %s" % details) self.close_sessions()
def start_test(self): """ Prepare required test params, then for scalability test, hotplug memory 256 times, then unplug 256 times. Otherwise, repeat hotplug and unplug in turn for 256 times. This is test entry. """ times = int(self.params["repeat_times"]) target_mems = [] for i in range(times): target_mems.append("mem%s" % i) vm = self.env.get_vm(self.params["main_vm"]) session = vm.wait_for_login() if self.params.get('os_type') == 'linux': arg = "movable_node" utils_test.update_boot_option(vm, args_added=arg) original_mem = self.get_guest_total_mem(vm) if self.params["test_type"] == "scalability_test": error_context.context("Repeat hotplug memory for %s times" % times, logging.info) self.repeat_hotplug(vm, target_mems) if self.params.get('os_type') == 'linux': error_context.context( "Repeat unplug memory for %s times" % times, logging.info) self.repeat_unplug(vm, target_mems) else: for target_mem in target_mems: error_context.context( "Hotplug and unplug memory %s" % target_mem, logging.info) self.hotplug_memory(vm, target_mem) self.unplug_memory(vm, target_mem) if self.params.get('os_type') == 'linux': current_mem = self.get_guest_total_mem(vm) if current_mem != original_mem: self.test.fail("Guest memory changed about repeat" " hotpug/unplug memory %d times" % times) vm.verify_kernel_crash() session.close()
def start_test(self): operation = self.params["operation"] target_mems = self.params["target_mems"] stage = self.params.get("stage", "before") login_timeout = int(self.params.get("login_timeout", 360)) sub_test_runner = (stage == 'during' and [self.run_background_test] or [self.run_sub_test])[0] func = getattr(self, "%s_memory" % operation) if not callable(func): self.test.error("Unsupported memory operation '%s'" % operation) vm = self.env.get_vm(self.params["main_vm"]) vm.wait_for_login(timeout=login_timeout) bootup_time = time.time() - vm.start_time utils_test.update_boot_option(vm, args_added="movable_node") try: if stage != "after": sub_test = sub_test_runner() if self.params.get("sub_type") == "boot": time.sleep(bootup_time / 2) for target_mem in target_mems.split(): func(vm, target_mem) self.check_memory(vm) else: for target_mem in target_mems.split(): func(vm, target_mem) self.check_memory(vm) sub_test = sub_test_runner() if stage == "during": sub_test.join(timeout=3600) vm = self.env.get_vm(self.params["main_vm"]) vm.reboot() finally: try: self.restore_memory(vm, self.env.get_vm(self.params['main_vm'])) except Exception as details: logging.warn("Error happen when restore vm: %s" % details) self.close_sessions()
def start_test(self): """ Prepare required test params, then for scalability test, hotplug memory 256 times, then unplug 256 times. Otherwise, repeat hotplug and unplug in turn for 256 times. This is test entry. """ times = int(self.params["repeat_times"]) target_mems = [] for i in range(times): target_mems.append("mem%s" % i) vm = self.env.get_vm(self.params["main_vm"]) session = vm.wait_for_login() if self.params.get('os_type') == 'linux': arg = "movable_node" utils_test.update_boot_option(vm, args_added=arg) original_mem = self.get_guest_total_mem(vm) if self.params["test_type"] == "scalability_test": error_context.context("Repeat hotplug memory for %s times" % times, logging.info) self.repeat_hotplug(vm, target_mems) if self.params.get('os_type') == 'linux': error_context.context("Repeat unplug memory for %s times" % times, logging.info) self.repeat_unplug(vm, target_mems) else: for target_mem in target_mems: error_context.context("Hotplug and unplug memory %s" % target_mem, logging.info) self.hotplug_memory(vm, target_mem) self.unplug_memory(vm, target_mem) if self.params.get('os_type') == 'linux': current_mem = self.get_guest_total_mem(vm) if current_mem != original_mem: self.test.fail("Guest memory changed about repeat" " hotpug/unplug memory %d times" % times) vm.verify_kernel_crash() session.close()
def run(test, params, env): """ Time drift test with reboot: 1) Log into a guest. 2) Take a time reading from the guest and host. 3) Reboot the guest. 4) Take a second time reading. 5) If the drift (in seconds) is higher than a user specified value, fail. :param test: QEMU test object. :param params: Dictionary with test parameters. :param env: Dictionary with the test environment. """ vm = env.get_vm(params["main_vm"]) vm.verify_alive() boot_option_added = params.get("boot_option_added") boot_option_removed = params.get("boot_option_removed") if boot_option_added or boot_option_removed: utils_test.update_boot_option(vm, args_removed=boot_option_removed, args_added=boot_option_added) timeout = int(params.get("login_timeout", 360)) session = vm.wait_for_login(timeout=timeout) # Collect test parameters: # Command to run to get the current time time_command = params["time_command"] # Filter which should match a string to be passed to time.strptime() time_filter_re = params["time_filter_re"] # Time format for time.strptime() time_format = params["time_format"] drift_threshold = float(params.get("drift_threshold", "10")) drift_threshold_single = float(params.get("drift_threshold_single", "3")) reboot_iterations = int(params.get("reboot_iterations", 1)) try: # Get initial time # (ht stands for host time, gt stands for guest time) (ht0, gt0) = utils_test.get_time(session, time_command, time_filter_re, time_format) # Reboot for i in range(reboot_iterations): # Get time before current iteration (ht0_, gt0_) = utils_test.get_time(session, time_command, time_filter_re, time_format) # Run current iteration logging.info("Rebooting: iteration %d of %d...", (i + 1), reboot_iterations) session = vm.reboot(session, timeout=timeout) # Get time after current iteration (ht1_, gt1_) = utils_test.get_time(session, time_command, time_filter_re, time_format) # Report iteration results host_delta = ht1_ - ht0_ guest_delta = gt1_ - gt0_ drift = abs(host_delta - guest_delta) logging.info("Host duration (iteration %d): %.2f", (i + 1), host_delta) logging.info("Guest duration (iteration %d): %.2f", (i + 1), guest_delta) logging.info("Drift at iteration %d: %.2f seconds", (i + 1), drift) # Fail if necessary if drift > drift_threshold_single: raise error.TestFail("Time drift too large at iteration %d: " "%.2f seconds" % (i + 1, drift)) # Get final time (ht1, gt1) = utils_test.get_time(session, time_command, time_filter_re, time_format) finally: if session: session.close() # remove flags add for this test. if boot_option_added or boot_option_removed: utils_test.update_boot_option(vm, args_removed=boot_option_added, args_added=boot_option_removed) # Report results host_delta = ht1 - ht0 guest_delta = gt1 - gt0 drift = abs(host_delta - guest_delta) logging.info("Host duration (%d reboots): %.2f", reboot_iterations, host_delta) logging.info("Guest duration (%d reboots): %.2f", reboot_iterations, guest_delta) logging.info("Drift after %d reboots: %.2f seconds", reboot_iterations, drift) # Fail if necessary if drift > drift_threshold: raise error.TestFail("Time drift too large after %d reboots: " "%.2f seconds" % (reboot_iterations, drift))
def run(test, params, env): """ Test send-key command, include all types of codeset and sysrq For normal sendkey test, we create a file to check the command execute by send-key. For sysrq test, check the /var/log/messages in RHEL or /var/log/syslog in Ubuntu and guest status """ if not virsh.has_help_command('send-key'): test.cancel("This version of libvirt does not support the send-key " "test") vm_name = params.get("main_vm", "avocado-vt-vm1") status_error = ("yes" == params.get("status_error", "no")) keystrokes = params.get("sendkey", "") codeset = params.get("codeset", "") holdtime = params.get("holdtime", "") sysrq_test = ("yes" == params.get("sendkey_sysrq", "no")) sleep_time = int(params.get("sendkey_sleeptime", 5)) readonly = params.get("readonly", False) username = params.get("username") password = params.get("password") create_file = params.get("create_file_name") uri = params.get("virsh_uri") simultaneous = params.get("sendkey_simultaneous", "yes") == "yes" unprivileged_user = params.get('unprivileged_user') if unprivileged_user: if unprivileged_user.count('EXAMPLE'): unprivileged_user = '******' if not libvirt_version.version_compare(1, 1, 1): if params.get('setup_libvirt_polkit') == 'yes': test.cancel("API acl test not supported in current libvirt " "version.") def send_line(send_str): """ send string to guest with send-key and end with Enter """ for send_ch in list(send_str): virsh.sendkey(vm_name, "KEY_%s" % send_ch.upper(), ignore_status=False) virsh.sendkey(vm_name, "KEY_ENTER", ignore_status=False) vm = env.get_vm(vm_name) vm.wait_for_login().close() # Boot the guest in text only mode so that send-key commands would succeed # in creating a file try: utils_test.update_boot_option(vm, args_added="3") except Exception as info: test.error(info) session = vm.wait_for_login() if sysrq_test: # In postprocess of previous testcase would pause and resume the VM # that would change the domstate to running (unpaused) and cause # sysrq reboot testcase to fail as the domstate persist across reboot # so it is better to destroy and start VM before the test starts if "KEY_B" in keystrokes: cmd_result = virsh.domstate(vm_name, '--reason', ignore_status=True) if "unpaused" in cmd_result.stdout.strip(): vm.destroy() vm.start() session = vm.wait_for_login() LOG_FILE = "/var/log/messages" if "ubuntu" in vm.get_distro().lower(): LOG_FILE = "/var/log/syslog" # Is 'rsyslog' installed on guest? It'll be what writes out # to LOG_FILE if not utils_package.package_install("rsyslog", session): test.fail("Fail to install rsyslog, make sure that you have " "usable repo in guest") # clear messages, restart rsyslog, and make sure it's running session.cmd("echo '' > %s" % LOG_FILE) session.cmd("service rsyslog restart") ps_stat = session.cmd_status("ps aux |grep rsyslog") if ps_stat != 0: test.fail("rsyslog is not running in guest") # enable sysrq session.cmd("echo 1 > /proc/sys/kernel/sysrq") # make sure the environment is clear if create_file is not None: session.cmd("rm -rf %s" % create_file) try: # wait for tty started tty_stat = "ps aux|grep tty" timeout = 60 while timeout >= 0 and \ session.get_command_status(tty_stat) != 0: time.sleep(1) timeout = timeout - 1 if timeout < 0: test.fail("Can not wait for tty started in 60s") # send user and passwd to guest to login send_line(username) time.sleep(2) send_line(password) time.sleep(2) if sysrq_test or simultaneous: output = virsh.sendkey(vm_name, keystrokes, codeset=codeset, holdtime=holdtime, readonly=readonly, unprivileged_user=unprivileged_user, uri=uri) else: # If multiple keycodes are specified, they are all sent # simultaneously to the guest, and they may be received # in random order. If you need distinct keypresses, you # must use multiple send-key invocations. for keystroke in keystrokes.split(): output = virsh.sendkey(vm_name, keystroke, codeset=codeset, holdtime=holdtime, readonly=readonly, unprivileged_user=unprivileged_user, uri=uri) if output.exit_status: test.fail("Failed to send key %s to guest: %s" % (keystroke, output.stderr)) time.sleep(sleep_time) if output.exit_status != 0: if status_error: logging.info("Failed to sendkey to guest as expected, Error:" "%s.", output.stderr) return else: test.fail("Failed to send key to guest, Error:%s." % output.stderr) elif status_error: test.fail("Expect fail, but succeed indeed.") if create_file is not None: # check if created file exist cmd_ls = "ls %s" % create_file sec_status, sec_output = session.get_command_status_output(cmd_ls) if sec_status == 0: logging.info("Succeed to create file with send key") else: test.fail("Fail to create file with send key, Error:%s" % sec_output) elif sysrq_test: # check LOG_FILE info according to different key # Since there's no guarantee when messages will be written # we'll do a check and wait loop for up to 60 seconds timeout = 60 while timeout >= 0: if "KEY_H" in keystrokes: cmd = "cat %s | grep 'SysRq.*HELP'" % LOG_FILE get_status = session.cmd_status(cmd) elif "KEY_M" in keystrokes: cmd = "cat %s | grep 'SysRq.*Show Memory'" % LOG_FILE get_status = session.cmd_status(cmd) elif "KEY_T" in keystrokes: cmd = "cat %s | grep 'SysRq.*Show State'" % LOG_FILE get_status = session.cmd_status(cmd) # Sometimes SysRq.*Show State string missed in LOG_FILE # as a fall back check for runnable tasks logged if get_status != 0: cmd = "cat %s | grep 'runnable tasks:'" % LOG_FILE get_status = session.cmd_status(cmd) elif "KEY_B" in keystrokes: session = vm.wait_for_login() result = virsh.domstate(vm_name, '--reason', ignore_status=True) output = result.stdout.strip() logging.debug("The guest state: %s", output) if not output.count("booted"): get_status = 1 else: get_status = 0 session.close() if get_status == 0: timeout = -1 else: session.cmd("echo \"virsh sendkey waiting\" >> %s" % LOG_FILE) time.sleep(1) timeout = timeout - 1 if get_status != 0: test.fail("SysRq does not take effect in guest, keystrokes is " "%s" % keystrokes) else: logging.info("Succeed to send SysRq command") else: test.fail("Test cfg file invalid: either sysrq_params or " "create_file_name must be defined") finally: if create_file is not None: session = vm.wait_for_login() session.cmd("rm -rf %s" % create_file) session.close()
def run(test, params, env): """ Test send-key command, include all types of codeset and sysrq For normal sendkey test, we create a file to check the command execute by send-key. For sysrq test, check the /var/log/messages in RHEL or /var/log/syslog in Ubuntu and guest status """ if not virsh.has_help_command('send-key'): test.cancel("This version of libvirt does not support the send-key " "test") vm_name = params.get("main_vm", "avocado-vt-vm1") status_error = ("yes" == params.get("status_error", "no")) keystrokes = params.get("sendkey", "") codeset = params.get("codeset", "") holdtime = params.get("holdtime", "") hold_timeout = eval(params.get("hold_timeout", "1")) sysrq_test = ("yes" == params.get("sendkey_sysrq", "no")) sleep_time = int(params.get("sendkey_sleeptime", 5)) readonly = params.get("readonly", False) username = params.get("username") password = params.get("password") create_file = params.get("create_file_name") uri = params.get("virsh_uri") simultaneous = params.get("sendkey_simultaneous", "yes") == "yes" unprivileged_user = params.get('unprivileged_user') is_crash = ("yes" == params.get("is_crash", "no")) add_panic_device = ("yes" == params.get("add_panic_device", "yes")) need_keyboard_device = ("yes" == params.get("need_keyboard_device", "yes")) panic_model = params.get('panic_model', 'isa') force_vm_boot_text_mode = ("yes" == params.get("force_vm_boot_text_mode", "yes")) crash_dir = "/var/crash" if unprivileged_user: if unprivileged_user.count('EXAMPLE'): unprivileged_user = '******' if not libvirt_version.version_compare(1, 1, 1): if params.get('setup_libvirt_polkit') == 'yes': test.cancel("API acl test not supported in current libvirt " "version.") def send_line(send_str): """ send string to guest with send-key and end with Enter """ for send_ch in list(send_str): virsh.sendkey(vm_name, "KEY_%s" % send_ch.upper(), ignore_status=False) virsh.sendkey(vm_name, "KEY_ENTER", ignore_status=False) def add_keyboard_device(vm_name): """ Add keyboard to guest if guest doesn't have :params: vm_name: the guest name """ inputs = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)\ .get_devices(device_type="input") for input_device in inputs: if input_device.type_name == "keyboard": logging.debug("Guest already has a keyboard device") return kbd = Input("keyboard") kbd.input_bus = "virtio" logging.debug("Add keyboard device %s" % kbd) result = virsh.attach_device(vm_name, kbd.xml) if result.exit_status: test.error("Failed to add keyboard device") vm = env.get_vm(vm_name) # Part of sysrq tests need keyboard device otherwise the sysrq cmd doesn't # work. Refer to BZ#1526862 if need_keyboard_device: add_keyboard_device(vm_name) vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) vm.wait_for_login().close() if force_vm_boot_text_mode: # Boot the guest in text only mode so that send-key commands would succeed # in creating a file try: utils_test.update_boot_option( vm, args_added="3", guest_arch_name=params.get('vm_arch_name')) except Exception as info: test.error(info) session = vm.wait_for_login() if sysrq_test: # In postprocess of previous testcase would pause and resume the VM # that would change the domstate to running (unpaused) and cause # sysrq reboot testcase to fail as the domstate persist across reboot # so it is better to destroy and start VM before the test starts if "KEY_B" in keystrokes: cmd_result = virsh.domstate(vm_name, '--reason', ignore_status=True) if "unpaused" in cmd_result.stdout.strip(): vm.destroy() vm.start() session = vm.wait_for_login() if is_crash: session.cmd("rm -rf {0}; mkdir {0}".format(crash_dir)) libvirt.update_on_crash(vm_name, "destroy") if add_panic_device: libvirt.add_panic_device(vm_name, model=panic_model) if not vm.is_alive(): vm.start() session = vm.wait_for_login() LOG_FILE = "/var/log/messages" if "ubuntu" in vm.get_distro().lower(): LOG_FILE = "/var/log/syslog" # Is 'rsyslog' installed on guest? It'll be what writes out # to LOG_FILE if not utils_package.package_install("rsyslog", session): test.fail("Fail to install rsyslog, make sure that you have " "usable repo in guest") # clear messages, restart rsyslog, and make sure it's running session.cmd("echo '' > %s" % LOG_FILE) # check the result of restart rsyslog status, output = session.cmd_status_output("service rsyslog restart") if status: # To avoid 'Exec format error' utils_package.package_remove("rsyslog", session) utils_package.package_install("rsyslog", session) # if rsyslog.service is masked, need to unmask rsyslog if "Unit rsyslog.service is masked" in output: session.cmd("systemctl unmask rsyslog") session.cmd("echo '' > %s" % LOG_FILE) session.cmd("service rsyslog restart") ps_stat = session.cmd_status("ps aux |grep rsyslog") if ps_stat != 0: test.fail("rsyslog is not running in guest") # enable sysrq session.cmd("echo 1 > /proc/sys/kernel/sysrq") # make sure the environment is clear if create_file is not None: session.cmd("rm -rf %s" % create_file) try: # wait for tty started tty_stat = "ps aux|grep tty" timeout = 60 while timeout >= 0 and \ session.get_command_status(tty_stat) != 0: time.sleep(1) timeout = timeout - 1 if timeout < 0: test.fail("Can not wait for tty started in 60s") # send user and passwd to guest to login send_line(username) time.sleep(2) send_line(password) time.sleep(2) if sysrq_test or simultaneous: output = virsh.sendkey(vm_name, keystrokes, codeset=codeset, holdtime=holdtime, readonly=readonly, unprivileged_user=unprivileged_user, uri=uri) else: # If multiple keycodes are specified, they are all sent # simultaneously to the guest, and they may be received # in random order. If you need distinct keypresses, you # must use multiple send-key invocations. for keystroke in keystrokes.split(): output = virsh.sendkey(vm_name, keystroke, codeset=codeset, holdtime=holdtime, readonly=readonly, unprivileged_user=unprivileged_user, uri=uri) if output.exit_status: test.fail("Failed to send key %s to guest: %s" % (keystroke, output.stderr)) time.sleep(sleep_time) if output.exit_status != 0: if status_error: logging.info( "Failed to sendkey to guest as expected, Error:" "%s.", output.stderr) return else: test.fail("Failed to send key to guest, Error:%s." % output.stderr) elif status_error: test.fail("Expect fail, but succeed indeed.") if create_file is not None: # check if created file exist cmd_ls = "ls %s" % create_file if not wait.wait_for( lambda: session.get_command_status_output(cmd_ls), hold_timeout, step=5): test.fail("Fail to create file with send key") logging.info("Succeed to create file with send key") elif sysrq_test: # check LOG_FILE info according to different key # Since there's no guarantee when messages will be written # we'll do a check and wait loop for up to 60 seconds timeout = 60 while timeout >= 0: if "KEY_H" in keystrokes: cmd = "cat %s | grep -i 'SysRq.*HELP'" % LOG_FILE get_status = session.cmd_status(cmd) elif "KEY_M" in keystrokes: cmd = "cat %s | grep -i 'SysRq.*Show Memory'" % LOG_FILE get_status = session.cmd_status(cmd) elif "KEY_T" in keystrokes: cmd = "cat %s | grep -i 'SysRq.*Show State'" % LOG_FILE get_status = session.cmd_status(cmd) # Sometimes SysRq.*Show State string missed in LOG_FILE # as a fall back check for runnable tasks logged if get_status != 0: cmd = "cat %s | grep 'runnable tasks:'" % LOG_FILE get_status = session.cmd_status(cmd) elif "KEY_B" in keystrokes: session = vm.wait_for_login() result = virsh.domstate(vm_name, '--reason', ignore_status=True) output = result.stdout.strip() logging.debug("The guest state: %s", output) if not output.count("booted"): get_status = 1 else: get_status = 0 session.close() # crash elif is_crash: dom_state = virsh.domstate(vm_name, "--reason").stdout.strip() logging.debug("domain state is %s" % dom_state) if "crashed" in dom_state: get_status = 0 else: get_status = 1 if get_status == 0: timeout = -1 else: if not is_crash: session.cmd("echo \"virsh sendkey waiting\" >> %s" % LOG_FILE) time.sleep(1) timeout = timeout - 1 if get_status != 0: test.fail("SysRq does not take effect in guest, keystrokes is " "%s" % keystrokes) else: logging.info("Succeed to send SysRq command") else: test.fail("Test cfg file invalid: either sysrq_params or " "create_file_name must be defined") finally: if create_file is not None: session = vm.wait_for_login() session.cmd("rm -rf %s" % create_file) session.close() vmxml_backup.sync()
def run_timedrift_with_cpu_offline(test, params, env): """ Time drift test with vm's cpu offline/online: 1) Log into a guest (the vcpu num >= 2). 2) Take a time reading from the guest and host. 3) Set cpu offline in vm. 4) Take the time from the guest and host as given frequency. 5) Set cpu online, which was set offline before 5) Take the time from the guest and host as given frequency. 6) If the drift (in seconds) is higher than a user specified value, fail. :param test: QEMU test object. :param params: Dictionary with test parameters. :param env: Dictionary with the test environment. """ login_timeout = int(params.get("login_timeout", 360)) vm = env.get_vm(params["main_vm"]) vm.verify_alive() boot_option_added = params.get("boot_option_added") boot_option_removed = params.get("boot_option_removed") if boot_option_added or boot_option_removed: utils_test.update_boot_option(vm, args_removed=boot_option_removed, args_added=boot_option_added) session = vm.wait_for_login(timeout=login_timeout) # Command to run to get the current time time_command = params.get("time_command") # Filter which should match a string to be passed to time.strptime() time_filter_re = params.get("time_filter_re") # Time format for time.strptime() time_format = params.get("time_format") # Use this value to measure the drift. drift_threshold = params.get("drift_threshold") # The time interval to check vm's time interval_gettime = int(params.get("interval_gettime", 600)) test_duration = float(params.get("test_duration", "60")) try: # Get time before set cpu offine # (ht stands for host time, gt stands for guest time) error.context("get time before set cpu offline") (ht0, gt0) = utils_test.get_time(session, time_command, time_filter_re, time_format) # Check cpu number error.context("check guest cpu number") smp = int(params.get("smp")) if smp < 2: raise error.TestError("The guest only has %d vcpu," "unsupport cpu offline" % smp) # Set cpu offline error.context("set cpu offline ") offline_cpu_cmd = params.get("offline_cpu_cmd") s, o = session.cmd_status_output(offline_cpu_cmd) if s != 0: logging.error(o) raise error.TestError("Failed set guest cpu offline") # Get time after set cpu offline error.context("get time after set cpu offline") (ht1, gt1) = utils_test.get_time(session, time_command, time_filter_re, time_format) # Report results host_delta = ht1 - ht0 guest_delta = gt1 - gt0 drift = 100.0 * (host_delta - guest_delta) / host_delta logging.info("Host duration: %.2f", host_delta) logging.info("Guest duration: %.2f", guest_delta) logging.info("Drift: %.2f%%", drift) if abs(drift) > drift_threshold: raise error.TestFail("Time drift too large: %.2f%%" % drift) # Set cpu online again error.context("set cpu online") online_cpu_cmd = params.get("online_cpu_cmd") s, o = session.cmd_status_output(online_cpu_cmd) if s != 0: logging.error(o) raise error.TestError("Failed set guest cpu online") error.context("get time after set cpu online") start_time = time.time() while (time.time() - start_time) < test_duration: # Get time delta after set cpu online (ht1, gt1) = utils_test.get_time(session, time_command, time_filter_re, time_format) # Report results host_delta = ht1 - ht0 guest_delta = gt1 - gt0 drift = 100.0 * (host_delta - guest_delta) / host_delta logging.info("Host duration: %.2f", host_delta) logging.info("Guest duration: %.2f", guest_delta) logging.info("Drift: %.2f%%", drift) time.sleep(interval_gettime) if abs(drift) > drift_threshold: raise error.TestFail("Time drift too large: %.2f%%" % drift) finally: session.close() # remove flags add for this test. if boot_option_added or boot_option_removed: utils_test.update_boot_option(vm, args_removed=boot_option_added, args_added=boot_option_removed)
def run_timedrift(test, params, env): """ Time drift test (mainly for Windows guests): 1) Log into a guest. 2) Take a time reading from the guest and host. 3) Run load on the guest and host. 4) Take a second time reading. 5) Stop the load and rest for a while. 6) Take a third time reading. 7) If the drift immediately after load is higher than a user- specified value (in %), fail. If the drift after the rest period is higher than a user-specified value, fail. @param test: QEMU test object. @param params: Dictionary with test parameters. @param env: Dictionary with the test environment. """ # Helper functions def set_cpu_affinity(pid, mask): """ Set the CPU affinity of all threads of the process with PID pid. Do this recursively for all child processes as well. @param pid: The process ID. @param mask: The CPU affinity mask. @return: A dict containing the previous mask for each thread. """ tids = commands.getoutput("ps -L --pid=%s -o lwp=" % pid).split() prev_masks = {} for tid in tids: prev_mask = commands.getoutput("taskset -p %s" % tid).split()[-1] prev_masks[tid] = prev_mask commands.getoutput("taskset -p %s %s" % (mask, tid)) children = commands.getoutput("ps --ppid=%s -o pid=" % pid).split() for child in children: prev_masks.update(set_cpu_affinity(child, mask)) return prev_masks def restore_cpu_affinity(prev_masks): """ Restore the CPU affinity of several threads. @param prev_masks: A dict containing TIDs as keys and masks as values. """ for tid, mask in prev_masks.items(): commands.getoutput("taskset -p %s %s" % (mask, tid)) vm = env.get_vm(params["main_vm"]) vm.verify_alive() boot_option_added = params.get("boot_option_added") boot_option_removed = params.get("boot_option_removed") if boot_option_added or boot_option_removed: utils_test.update_boot_option(vm, args_removed=boot_option_removed, args_added=boot_option_added) timeout = int(params.get("login_timeout", 360)) session = vm.wait_for_login(timeout=timeout) # Collect test parameters: # Command to run to get the current time time_command = params["time_command"] # Filter which should match a string to be passed to time.strptime() time_filter_re = params["time_filter_re"] # Time format for time.strptime() time_format = params["time_format"] guest_load_command = params["guest_load_command"] guest_load_stop_command = params["guest_load_stop_command"] host_load_command = params["host_load_command"] guest_load_instances = int(params.get("guest_load_instances", "1")) host_load_instances = int(params.get("host_load_instances", "0")) # CPU affinity mask for taskset cpu_mask = params.get("cpu_mask", "0xFF") load_duration = float(params.get("load_duration", "30")) rest_duration = float(params.get("rest_duration", "10")) drift_threshold = float(params.get("drift_threshold", "200")) drift_threshold_after_rest = float(params.get("drift_threshold_after_rest", "200")) test_duration = float(params.get("test_duration", "60")) interval_gettime = float(params.get("interval_gettime", "20")) guest_load_sessions = [] host_load_sessions = [] try: # Set the VM's CPU affinity prev_affinity = set_cpu_affinity(vm.get_shell_pid(), cpu_mask) try: # Open shell sessions with the guest logging.info("Starting load on guest...") for i in range(guest_load_instances): load_session = vm.login() # Set output func to None to stop it from being called so we # can change the callback function and the parameters it takes # with no problems load_session.set_output_func(None) load_session.set_output_params(()) load_session.set_output_prefix("(guest load %d) " % i) load_session.set_output_func(logging.debug) guest_load_sessions.append(load_session) # Get time before load # (ht stands for host time, gt stands for guest time) (ht0, gt0) = utils_test.get_time(session, time_command, time_filter_re, time_format) # Run some load on the guest for load_session in guest_load_sessions: load_session.sendline(guest_load_command) # Run some load on the host logging.info("Starting load on host...") for i in range(host_load_instances): load_cmd = aexpect.run_bg( host_load_command, output_func=logging.debug, output_prefix="(host load %d) " % i, timeout=0.5 ) host_load_sessions.append(load_cmd) # Set the CPU affinity of the load process pid = load_cmd.get_pid() set_cpu_affinity(pid, cpu_mask) # Sleep for a while (during load) logging.info("Sleeping for %s seconds...", load_duration) time.sleep(load_duration) start_time = time.time() while (time.time() - start_time) < test_duration: # Get time delta after load (ht1, gt1) = utils_test.get_time(session, time_command, time_filter_re, time_format) # Report results host_delta = ht1 - ht0 guest_delta = gt1 - gt0 drift = 100.0 * (host_delta - guest_delta) / host_delta logging.info("Host duration: %.2f", host_delta) logging.info("Guest duration: %.2f", guest_delta) logging.info("Drift: %.2f%%", drift) time.sleep(interval_gettime) finally: logging.info("Cleaning up...") # Restore the VM's CPU affinity restore_cpu_affinity(prev_affinity) # Stop the guest load if guest_load_stop_command: session.cmd_output(guest_load_stop_command) # Close all load shell sessions for load_session in guest_load_sessions: load_session.close() for load_session in host_load_sessions: load_session.close() # Sleep again (rest) logging.info("Sleeping for %s seconds...", rest_duration) time.sleep(rest_duration) # Get time after rest (ht2, gt2) = utils_test.get_time(session, time_command, time_filter_re, time_format) finally: session.close() # remove flags add for this test. if boot_option_added or boot_option_removed: utils_test.update_boot_option(vm, args_removed=boot_option_added, args_added=boot_option_removed) # Report results host_delta_total = ht2 - ht0 guest_delta_total = gt2 - gt0 drift_total = 100.0 * (host_delta_total - guest_delta_total) / host_delta logging.info("Total host duration including rest: %.2f", host_delta_total) logging.info("Total guest duration including rest: %.2f", guest_delta_total) logging.info("Total drift after rest: %.2f%%", drift_total) # Fail the test if necessary if abs(drift) > drift_threshold: raise error.TestFail("Time drift too large: %.2f%%" % drift) if abs(drift_total) > drift_threshold_after_rest: raise error.TestFail("Time drift too large after rest period: %.2f%%" % drift_total)
def run(test, params, env): """ Time drift test (mainly for Windows guests): 1) Log into a guest. 2) Take a time reading from the guest and host. 3) Run load on the guest and host. 4) Take a second time reading. 5) Stop the load and rest for a while. 6) Take a third time reading. 7) If the drift immediately after load is higher than a user- specified value (in %), fail. If the drift after the rest period is higher than a user-specified value, fail. :param test: QEMU test object. :param params: Dictionary with test parameters. :param env: Dictionary with the test environment. """ # Helper functions def set_cpu_affinity(pid, mask): """ Set the CPU affinity of all threads of the process with PID pid. Do this recursively for all child processes as well. :param pid: The process ID. :param mask: The CPU affinity mask. :return: A dict containing the previous mask for each thread. """ tids = decode_to_text( process.system_output("ps -L --pid=%s -o lwp=" % pid, verbose=False, ignore_status=True)).split() prev_masks = {} for tid in tids: prev_mask = decode_to_text( process.system_output("taskset -p %s" % tid, verbose=False)).split()[-1] prev_masks[tid] = prev_mask process.system("taskset -p %s %s" % (mask, tid), verbose=False) children = decode_to_text( process.system_output("ps --ppid=%s -o pid=" % pid, verbose=False, ignore_status=True)).split() for child in children: prev_masks.update(set_cpu_affinity(child, mask)) return prev_masks def restore_cpu_affinity(prev_masks): """ Restore the CPU affinity of several threads. :param prev_masks: A dict containing TIDs as keys and masks as values. """ for tid, mask in prev_masks.items(): process.system("taskset -p %s %s" % (mask, tid), verbose=False, ignore_status=True) vm = env.get_vm(params["main_vm"]) vm.verify_alive() boot_option_added = params.get("boot_option_added") boot_option_removed = params.get("boot_option_removed") if boot_option_added or boot_option_removed: utils_test.update_boot_option(vm, args_removed=boot_option_removed, args_added=boot_option_added) if params["os_type"] == "windows": utils_time.sync_timezone_win(vm) timeout = int(params.get("login_timeout", 360)) session = vm.wait_for_serial_login(timeout=timeout) # Collect test parameters: # Command to run to get the current time time_command = params["time_command"] # Filter which should match a string to be passed to time.strptime() time_filter_re = params["time_filter_re"] # Time format for time.strptime() time_format = params["time_format"] guest_load_command = params["guest_load_command"] guest_load_stop_command = params["guest_load_stop_command"] host_load_command = params["host_load_command"] guest_load_instances = params["guest_load_instances"] host_load_instances = params["host_load_instances"] if not guest_load_instances and not host_load_instances: host_load_instances = cpu.total_cpus_count() guest_load_instances = vm.get_cpu_count() else: host_load_instances = int(host_load_instances) guest_load_instances = int(guest_load_instances) # CPU affinity mask for taskset cpu_mask = int(params.get("cpu_mask", "0xFF"), 16) load_duration = float(params.get("load_duration", "30")) rest_duration = float(params.get("rest_duration", "10")) drift_threshold = float(params.get("drift_threshold", "200")) drift_threshold_after_rest = float( params.get("drift_threshold_after_rest", "200")) test_duration = float(params.get("test_duration", "60")) interval_gettime = float(params.get("interval_gettime", "20")) guest_load_sessions = [] host_load_sessions = [] try: # Set the VM's CPU affinity prev_affinity = set_cpu_affinity(vm.get_shell_pid(), cpu_mask) try: # Open shell sessions with the guest logging.info("Starting load on guest...") for i in range(guest_load_instances): load_session = vm.wait_for_login(timeout=timeout) # Set output func to None to stop it from being called so we # can change the callback function and the parameters it takes # with no problems load_session.set_output_func(None) load_session.set_output_params(()) load_session.set_output_prefix("(guest load %d) " % i) load_session.set_output_func(logging.debug) guest_load_sessions.append(load_session) # Get time before load # (ht stands for host time, gt stands for guest time) (ht0, gt0) = utils_test.get_time(session, time_command, time_filter_re, time_format) # Run some load on the guest if params["os_type"] == "linux": for i, load_session in enumerate(guest_load_sessions): load_session.sendline(guest_load_command % i) else: for load_session in guest_load_sessions: load_session.sendline(guest_load_command) # Run some load on the host logging.info("Starting load on host...") for i in range(host_load_instances): load_cmd = aexpect.run_bg(host_load_command, output_func=logging.debug, output_prefix="(host load %d) " % i, timeout=0.5) host_load_sessions.append(load_cmd) # Set the CPU affinity of the load process pid = load_cmd.get_pid() set_cpu_affinity(pid, cpu_mask << i) # Sleep for a while (during load) logging.info("Sleeping for %s seconds...", load_duration) time.sleep(load_duration) start_time = time.time() while (time.time() - start_time) < test_duration: # Get time delta after load (ht1, gt1) = utils_test.get_time(session, time_command, time_filter_re, time_format) # Report results host_delta = ht1 - ht0 guest_delta = gt1 - gt0 drift = 100.0 * (host_delta - guest_delta) / host_delta logging.info("Host duration: %.2f", host_delta) logging.info("Guest duration: %.2f", guest_delta) logging.info("Drift: %.2f%%", drift) time.sleep(interval_gettime) finally: logging.info("Cleaning up...") # Restore the VM's CPU affinity restore_cpu_affinity(prev_affinity) # Stop the guest load if guest_load_stop_command: session.cmd_output(guest_load_stop_command) # Close all load shell sessions for load_session in guest_load_sessions: load_session.close() for load_session in host_load_sessions: load_session.close() # Sleep again (rest) logging.info("Sleeping for %s seconds...", rest_duration) time.sleep(rest_duration) # Get time after rest (ht2, gt2) = utils_test.get_time(session, time_command, time_filter_re, time_format) finally: session.close() # remove flags add for this test. if boot_option_added or boot_option_removed: utils_test.update_boot_option(vm, args_removed=boot_option_added, args_added=boot_option_removed) # Report results host_delta_total = ht2 - ht0 guest_delta_total = gt2 - gt0 drift_total = 100.0 * (host_delta_total - guest_delta_total) / host_delta logging.info("Total host duration including rest: %.2f", host_delta_total) logging.info("Total guest duration including rest: %.2f", guest_delta_total) logging.info("Total drift after rest: %.2f%%", drift_total) # Fail the test if necessary if abs(drift) > drift_threshold: test.fail("Time drift too large: %.2f%%" % drift) if abs(drift_total) > drift_threshold_after_rest: test.fail("Time drift too large after rest period: %.2f%%" % drift_total)
def run(test, params, env): """ Timer device check guest after update kernel line without kvmclock: 1) Boot a guest with kvm-clock 2) Check the current clocksource in guest 3) Check the available clocksource in guest 4) Update "clocksource=" parameter in guest kernel cli 5) Boot guest system 6) Check the current clocksource in guest :param test: QEMU test object. :param params: Dictionary with test parameters. :param env: Dictionary with the test environment. """ def verify_guest_clock_source(session, expected): if expected not in session.cmd(cur_clk): test.fail("Guest didn't use '%s' clocksource" % expected) error_context.context("Boot a guest with kvm-clock", test.log.info) vm = env.get_vm(params["main_vm"]) vm.verify_alive() timeout = int(params.get("login_timeout", 360)) session = vm.wait_for_login(timeout=timeout) error_context.context("Check the current clocksource in guest", test.log.info) cur_clk = params["cur_clk"] if "kvm-clock" not in session.cmd(cur_clk): error_context.context("Update guest kernel cli to kvm-clock", test.log.info) utils_time.update_clksrc(vm, clksrc="kvm-clock") session = vm.wait_for_login(timeout=timeout) verify_guest_clock_source(session, "kvm-clock") error_context.context("Check the available clocksource in guest", test.log.info) avl_clk = params["avl_clk"] try: available_clksrc_list = session.cmd(avl_clk).split() except Exception as detail: test.fail("Couldn't get guest available clock source." " Detail: '%s'" % detail) try: for avl_clksrc in available_clksrc_list: if avl_clksrc == "kvm-clock": continue error_context.context( "Update guest kernel cli to '%s'" % avl_clksrc, test.log.info) utils_time.update_clksrc(vm, clksrc=avl_clksrc) session = vm.wait_for_login(timeout=timeout) error_context.context("Check the current clocksource in guest", test.log.info) verify_guest_clock_source(session, avl_clksrc) finally: error_context.context("Restore guest kernel cli", test.log.info) proc_cmdline = "cat /proc/cmdline" check_output = str(session.cmd(proc_cmdline, timeout=60)) clk_removed = re.search("clocksource.*", check_output).group() utils_test.update_boot_option(vm, args_removed=clk_removed) session = vm.wait_for_login(timeout=timeout) verify_guest_clock_source(session, "kvm-clock")
def run(test, params, env): """ MULTI_QUEUE chang queues number test 1) Boot up VM, and login guest 2) Check guest pci msi support and reset it as expection 3) Run bg_stress_test(pktgen, netperf or file copy) if needed 4) Change queues number repeatly during stress test running :param test: QEMU test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ def change_queues_number(session, ifname, q_number, queues_status=None): """ Change queues number """ mq_set_cmd = "ethtool -L %s combined %d" % (ifname, q_number) if not queues_status: queues_status = get_queues_status(session, ifname) if q_number != queues_status[1] and q_number <= queues_status[0]: expect_status = 0 else: expect_status = 1 status, output = session.cmd_status_output(mq_set_cmd) cur_queues_status = get_queues_status(session, ifname) if status != expect_status: err_msg = "Change queues number failed, " err_msg += "current queues set is %s, " % queues_status[1] err_msg += "max allow queues set is %s, " % queues_status[0] err_msg += "when run cmd: '%s', " % mq_set_cmd err_msg += "expect exit status is: %s, " % expect_status err_msg += "output: '%s'" % output raise error.TestFail(err_msg) if not status and cur_queues_status == queues_status: raise error.TestFail("params is right, but change queues failed") elif status and cur_queues_status != queues_status: raise error.TestFail("No need change queues number") return [int(_) for _ in cur_queues_status] def get_queues_status(session, ifname, timeout=240): """ Get queues status """ mq_get_cmd = "ethtool -l %s" % ifname nic_mq_info = session.cmd_output(mq_get_cmd, timeout=timeout) queues_reg = re.compile(r"Combined:\s+(\d)", re.I) queues_info = queues_reg.findall(" ".join(nic_mq_info.splitlines())) if len(queues_info) != 2: err_msg = "Oops, get guest queues info failed, " err_msg += "make sure your guest support MQ.\n" err_msg += "Check cmd is: '%s', " % mq_get_cmd err_msg += "Command output is: '%s'." % nic_mq_info raise error.TestNAError(err_msg) return [int(x) for x in queues_info] error.context("Init guest and try to login", logging.info) login_timeout = int(params.get("login_timeout", 360)) vm = env.get_vm(params["main_vm"]) vm.verify_alive() vm.wait_for_login(timeout=login_timeout) if params.get("pci_nomsi", "no") == "yes": error.context("Disable pci msi in guest", logging.info) utils_test.update_boot_option(vm, args_added="pci=nomsi") vm.wait_for_login(timeout=login_timeout) session_serial = vm.wait_for_serial_login(timeout=login_timeout) bg_stress_test = params.get("run_bgstress") try: ifnames = [] for nic_index, nic in enumerate(vm.virtnet): ifname = utils_net.get_linux_ifname(session_serial, vm.virtnet[nic_index].mac) ifnames.append(ifname) if bg_stress_test: error.context("Run test %s background" % bg_stress_test, logging.info) stress_thread = "" wait_time = float(params.get("wait_bg_time", 60)) bg_stress_run_flag = params.get("bg_stress_run_flag") env[bg_stress_run_flag] = False stress_thread = utils.InterruptedThread( utils_test.run_virt_sub_test, (test, params, env), {"sub_type": bg_stress_test}) stress_thread.start() utils_misc.wait_for(lambda: env.get(bg_stress_run_flag), wait_time, 0, 5, "Wait %s start background" % bg_stress_test) error.context("Change queues number repeatly", logging.info) repeat_counts = int(params.get("repeat_counts", 10)) for nic_index, nic in enumerate(vm.virtnet): if "virtio" not in nic['nic_model']: continue queues = int(vm.virtnet[nic_index].queues) if queues == 1: logging.info("Nic with single queue, skip and continue") continue ifname = ifnames[nic_index] default_change_list = xrange(1, int(queues)) change_list = params.get("change_list") if change_list: change_list = change_list.split(",") else: change_list = default_change_list for repeat_num in xrange(1, repeat_counts + 1): error.context("Change queues number -- %sth" % repeat_num, logging.info) try: queues_status = get_queues_status(session_serial, ifname) for q_number in change_list: queues_status = change_queues_number(session_serial, ifname, int(q_number), queues_status) except aexpect.ShellProcessTerminatedError: vm = env.get_vm(params["main_vm"]) session = vm.wait_for_serial_login(timeout=login_timeout) session_serial = session queues_status = get_queues_status(session_serial, ifname) for q_number in change_list: queues_status = change_queues_number(session_serial, ifname, int(q_number), queues_status) if bg_stress_test: env[bg_stress_run_flag] = False if stress_thread: try: stress_thread.join() except Exception, e: err_msg = "Run %s test background error!\n " err_msg += "Error Info: '%s'" raise error.TestError(err_msg % (bg_stress_test, e)) finally: env[bg_stress_run_flag] = False if session_serial: session_serial.close()
def run(test, params, env): """ vhost is no longer disabled when guest does not use MSI-X. The vhostforce flag is no longer required. 1) Start guest with different NIC option 2) Check virtio device's irq number,irq number should be greater than one. 3) Disable msi of guest 4) Reboot guest,check if msi is disabled and irq number should be equal to 1. 5) Check network and vhost process (transfer data). 6) Check md5 value of both sides. :param test: QEMU test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ def irq_check(session, device_name, devcon_folder): hwid = win_dev.get_hwids(session, device_name, devcon_folder, login_timeout)[0] get_irq_cmd = params["get_irq_cmd"] % (devcon_folder, hwid) irq_list = re.findall(r':\s+(\d+)', session.cmd_output(get_irq_cmd), re.M) if not irq_list: test.error("device %s's irq checked fail" % device_name) return irq_list def get_file_md5sum(file_name, session, timeout): """ return: Return the md5sum value of the guest. """ logging.info("Get md5sum of the file:'%s'", file_name) s, o = session.cmd_status_output("md5sum %s" % file_name, timeout=timeout) if s != 0: test.error("Get file md5sum failed as %s" % o) return re.findall(r"\w{32}", o)[0] tmp_dir = params["tmp_dir"] filesize = int(params.get("filesize")) dd_cmd = params["dd_cmd"] delete_cmd = params["delete_cmd"] file_md5_check_timeout = int(params.get("file_md5_check_timeout")) login_timeout = int(params.get("login_timeout", 360)) vm = env.get_vm(params["main_vm"]) vm.verify_alive() session = vm.wait_for_serial_login() if params.get("os_type") == "linux": error_context.context("Check the pci msi in guest", logging.info) pci_id = session.cmd("lspci |grep Eth |awk {'print $1'}").strip() status = session.cmd("lspci -vvv -s %s|grep MSI-X" % pci_id).strip() enable_status = re.search(r'Enable\+', status, re.M | re.I) if enable_status.group() == "Enable+": error_context.context("Disable pci msi in guest", logging.info) utils_test.update_boot_option(vm, args_added="pci=nomsi") session_msi = vm.wait_for_serial_login(timeout=login_timeout) pci_id = session_msi.cmd( "lspci |grep Eth |awk {'print $1'}").strip() status = session_msi.cmd("lspci -vvv -s %s|grep MSI-X" % pci_id).strip() session_msi.close() change_status = re.search(r'Enable\-', status, re.M | re.I) if change_status.group() != "Enable-": test.fail("virtio device's statuts is not correct") elif enable_status.group() != "Enable+": test.fail("virtio device's statuts is not correct") else: driver = params.get("driver_name") driver_verifier = params.get("driver_verifier", driver) device_name = params["device_name"] devcon_folder = utils_misc.set_winutils_letter(session, params["devcon_folder"]) error_context.context("Boot guest with %s device" % driver, logging.info) session = utils_test.qemu.windrv_check_running_verifier( session, vm, test, driver_verifier, login_timeout) error_context.context("Check %s's irq number" % device_name, logging.info) irq_list = irq_check(session, device_name, devcon_folder) irq_nums = len(irq_list) if not irq_nums > 1 and\ max(ctypes.c_int32(int(irq)).value for irq in irq_list) < 0: test.fail("%s's irq is not correct." % device_name) if params.get("msi_cmd"): error_context.context("Disable MSI in guest", logging.info) hwid_msi = win_dev.get_hwids(session, device_name, devcon_folder, login_timeout)[0] session.cmd(params["msi_cmd"] % (hwid_msi, 0)) session = vm.reboot(session=session) error_context.context("Check %s's irq number" % device_name, logging.info) irq_list = irq_check(session, device_name, devcon_folder) irq_nums = len(irq_list) if not irq_nums == 1 and \ min(ctypes.c_int32(int(irq)).value for irq in irq_list) > 0: test.fail("%s's irq is not correct." % device_name) # prepare test data guest_path = (tmp_dir + "src-%s" % utils_misc.generate_random_string(8)) host_path = os.path.join(test.tmpdir, "tmp-%s" % utils_misc.generate_random_string(8)) logging.info("Test setup: Creating %dMB file on host", filesize) process.run(dd_cmd % host_path, shell=True) try: src_md5 = crypto.hash_file(host_path, algorithm="md5") logging.info("md5 value of data from src: %s", src_md5) # transfer data error_context.context("Transfer data from host to %s" % vm.name, logging.info) vm.copy_files_to(host_path, guest_path) dst_md5 = get_file_md5sum(guest_path, session, timeout=file_md5_check_timeout) logging.info("md5 value of data in %s: %s", vm.name, dst_md5) if dst_md5 != src_md5: test.fail("File changed after transfer host -> %s" % vm.name) finally: os.remove(host_path) session.cmd(delete_cmd % guest_path, timeout=login_timeout, ignore_all_errors=True) session.close()
def test_args_no_zipl(self, *mocks): update_boot_option(self.vm, args_added="3", need_reboot=False) utils_test.check_kernel_cmdline.assert_called_once() self.session.cmd_status_output.assert_called_once()
def run(test, params, env): """ MULTI_QUEUE chang queues number test 1) Boot up VM, and login guest 2) Check guest pci msi support and reset it as expection 3) Enable the queues in guest 4) Run bg_stress_test(pktgen, netperf or file copy) if needed 5) Change queues number repeatly during stress test running 6) Ping external host (local host, if external host not available) :param test: QEMU test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ def change_queues_number(session, ifname, q_number, queues_status=None): """ Change queues number """ mq_set_cmd = "ethtool -L %s combined %d" % (ifname, q_number) if not queues_status: queues_status = get_queues_status(session, ifname) if (q_number != queues_status[1] and q_number <= queues_status[0] and q_number > 0): expect_status = 0 else: expect_status = 1 status, output = session.cmd_status_output(mq_set_cmd, safe=True) cur_queues_status = get_queues_status(session, ifname) if status != expect_status: err_msg = "Change queues number failed, " err_msg += "current queues set is %s, " % queues_status[1] err_msg += "max allow queues set is %s, " % queues_status[0] err_msg += "when run cmd: '%s', " % mq_set_cmd err_msg += "expect exit status is: %s, " % expect_status err_msg += "output: '%s'" % output raise error.TestFail(err_msg) if not status and cur_queues_status == queues_status: raise error.TestFail("params is right, but change queues failed") elif status and cur_queues_status != queues_status: raise error.TestFail("No need change queues number") return [int(_) for _ in cur_queues_status] def get_queues_status(session, ifname, timeout=240): """ Get queues status """ mq_get_cmd = "ethtool -l %s" % ifname nic_mq_info = session.cmd_output(mq_get_cmd, timeout=timeout, safe=True) queues_reg = re.compile(r"Combined:\s+(\d)", re.I) queues_info = queues_reg.findall(" ".join(nic_mq_info.splitlines())) if len(queues_info) != 2: err_msg = "Oops, get guest queues info failed, " err_msg += "make sure your guest support MQ.\n" err_msg += "Check cmd is: '%s', " % mq_get_cmd err_msg += "Command output is: '%s'." % nic_mq_info raise error.TestNAError(err_msg) return [int(x) for x in queues_info] def enable_multi_queues(vm): sess = vm.wait_for_serial_login(timeout=login_timeout) error.context("Enable multi queues in guest.", logging.info) for nic_index, nic in enumerate(vm.virtnet): ifname = utils_net.get_linux_ifname(sess, nic.mac) queues = int(nic.queues) change_queues_number(sess, ifname, queues) def ping_test(dest_ip, ping_time, lost_raito, session=None): status, output = utils_test.ping(dest=dest_ip, timeout=ping_time, session=session) packets_lost = utils_test.get_loss_ratio(output) if packets_lost > lost_raito: err = " %s%% packages lost during ping. " % packets_lost err += "Ping command log:\n %s" % "\n".join(output.splitlines()[-3:]) raise error.TestFail(err) error.context("Init guest and try to login", logging.info) login_timeout = int(params.get("login_timeout", 360)) bg_stress_test = params.get("run_bgstress") bg_stress_run_flag = params.get("bg_stress_run_flag") vm = env.get_vm(params["main_vm"]) vm.verify_alive() vm.wait_for_login(timeout=login_timeout) if params.get("pci_nomsi", "no") == "yes": error.context("Disable pci msi in guest", logging.info) utils_test.update_boot_option(vm, args_added="pci=nomsi") vm.wait_for_login(timeout=login_timeout) enable_multi_queues(vm) session_serial = vm.wait_for_serial_login(timeout=login_timeout) s_session = None bg_ping = params.get("bg_ping") b_ping_lost_ratio = int(params.get("background_ping_package_lost_ratio", 5)) f_ping_lost_ratio = int(params.get("final_ping_package_lost_ratio", 5)) guest_ip = vm.get_address() b_ping_time = int(params.get("background_ping_time", 60)) f_ping_time = int(params.get("final_ping_time", 60)) bg_test = None try: ifnames = [] for nic_index, nic in enumerate(vm.virtnet): ifname = utils_net.get_linux_ifname(session_serial, vm.virtnet[nic_index].mac) ifnames.append(ifname) if bg_stress_test: error.context("Run test %s background" % bg_stress_test, logging.info) stress_thread = "" wait_time = float(params.get("wait_bg_time", 60)) env[bg_stress_run_flag] = False stress_thread = utils.InterruptedThread( utils_test.run_virt_sub_test, (test, params, env), {"sub_type": bg_stress_test}) stress_thread.start() if bg_stress_run_flag: utils_misc.wait_for(lambda: env.get(bg_stress_run_flag), wait_time, 0, 5, "Wait %s start background" % bg_stress_test) if bg_ping == "yes": error.context("Ping guest from host", logging.info) args = (guest_ip, b_ping_time, b_ping_lost_ratio) bg_test = utils.InterruptedThread(ping_test, args) bg_test.start() error.context("Change queues number repeatly", logging.info) repeat_counts = int(params.get("repeat_counts", 10)) for nic_index, nic in enumerate(vm.virtnet): if "virtio" not in nic['nic_model']: continue queues = int(vm.virtnet[nic_index].queues) if queues == 1: logging.info("Nic with single queue, skip and continue") continue ifname = ifnames[nic_index] default_change_list = xrange(1, int(queues + 1)) change_list = params.get("change_list") if change_list: change_list = change_list.split(",") else: change_list = default_change_list for repeat_num in xrange(1, repeat_counts + 1): error.context("Change queues number -- %sth" % repeat_num, logging.info) try: queues_status = get_queues_status(session_serial, ifname) for q_number in change_list: queues_status = change_queues_number(session_serial, ifname, int(q_number), queues_status) except aexpect.ShellProcessTerminatedError: vm = env.get_vm(params["main_vm"]) session = vm.wait_for_serial_login(timeout=login_timeout) session_serial = session queues_status = get_queues_status(session_serial, ifname) for q_number in change_list: queues_status = change_queues_number(session_serial, ifname, int(q_number), queues_status) if params.get("ping_after_changing_queues", "yes") == "yes": default_host = "www.redhat.com" try: ext_host = utils_net.get_host_default_gateway() except error.CmdError: logging.warn("Can't get specified host," " Fallback to default host '%s'", default_host) ext_host = default_host if not ext_host: # Fallback to a hardcode host, eg: ext_host = default_host s_session = vm.wait_for_login(timeout=login_timeout) txt = "ping %s after changing queues in guest." error.context(txt, logging.info) ping_test(ext_host, f_ping_time, f_ping_lost_ratio, s_session) if bg_stress_test: env[bg_stress_run_flag] = False if stress_thread: error.context("wait for background test finish", logging.info) try: stress_thread.join() except Exception, err: err_msg = "Run %s test background error!\n " err_msg += "Error Info: '%s'" raise error.TestError(err_msg % (bg_stress_test, err)) finally: if bg_stress_test: env[bg_stress_run_flag] = False if session_serial: session_serial.close() if s_session: s_session.close() if bg_test: error.context("Wait for background ping test finish.", logging.info) try: bg_test.join() except Exception, err: txt = "Fail to wait background ping test finish. " txt += "Got error message %s" % err raise error.TestFail(txt)
def run(test, params, env): """ Test to change the kernel param based on user input. 1. Prepare test environment, boot the guest 2. Change the kernel parameter as per user input 3. Reboot the guest and check whether /proc/cmdline reflects 4. Check the boot log in guest dmesg and validate 5. Perform any test operation if any, based on kernel param change 6. Recover test environment """ vms = params.get("vms").split() kernel_param = params.get("kernel_param", "quiet") kernel_param_remove = params.get("kernel_param_remove", "") if not kernel_param: kernel_param = None if not kernel_param_remove: kernel_param_remove = None cpu_check = params.get("hardware", "").upper() boot_log = params.get("boot_log", None) status_error = params.get("status_error", "no") == "yes" vm_dict = {} vm_list = env.get_all_vms() # To ensure host that doesn't support Radix MMU gets skipped if cpu_check: cpu_model = utils_misc.get_cpu_info()['Model name'].upper() if cpu_check not in cpu_model: logging.info("This test will work for %s", cpu_check) test.skip("Test is not applicable for %s" % cpu_model) # back up vmxml for vm_name in vms: vm_dict[vm_name] = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) try: for vm in vm_list: session = vm.wait_for_login() utils_test.update_boot_option(vm, args_added=kernel_param, args_removed=kernel_param_remove, need_reboot=True) if boot_log: session = vm.wait_for_login() # To ensure guest that doesn't support Radix MMU gets skipped if cpu_check: cmd = "grep cpu /proc/cpuinfo | awk '{print $3}' | " cmd += "head -n 1" status, output = session.cmd_status_output(cmd) if status: test.error("couldn't get cpu information from guest " "%s" % vm.name) if cpu_check not in output.upper() and "radix" in boot_log: test.skip("radix MMU not supported in %s" % output) status, output = session.cmd_status_output("dmesg") if status: logging.error(output) test.error("unable to get dmesg from guest: %s" % vm.name) if status_error: if boot_log in output: test.fail("Able to find %s in dmesg of guest: " "%s" % (boot_log, vm.name)) logging.info("unable to find %s in dmesg of guest: %s", boot_log, vm.name) else: if boot_log not in output: test.fail("unable to find %s in dmesg of guest: " "%s" % (boot_log, vm.name)) logging.info("Able to find %s in dmesg of guest: %s", boot_log, vm.name) if session: session.close() finally: # close the session and recover the vms if session: session.close() for vm in vm_list: vm.destroy() vm_dict[vm.name].sync()
def run(test, params, env): """ Time drift test with vm's cpu offline/online: 1) Log into a guest (the vcpu num >= 2). 2) Take a time reading from the guest and host. 3) Set cpu offline in vm. 4) Take the time from the guest and host as given frequency. 5) Set cpu online, which was set offline before 5) Take the time from the guest and host as given frequency. 6) If the drift (in seconds) is higher than a user specified value, fail. :param test: QEMU test object. :param params: Dictionary with test parameters. :param env: Dictionary with the test environment. """ login_timeout = int(params.get("login_timeout", 360)) vm = env.get_vm(params["main_vm"]) vm.verify_alive() boot_option_added = params.get("boot_option_added") boot_option_removed = params.get("boot_option_removed") if boot_option_added or boot_option_removed: utils_test.update_boot_option(vm, args_removed=boot_option_removed, args_added=boot_option_added) session = vm.wait_for_login(timeout=login_timeout) # Command to run to get the current time time_command = params.get("time_command") # Filter which should match a string to be passed to time.strptime() time_filter_re = params.get("time_filter_re") # Time format for time.strptime() time_format = params.get("time_format") # Use this value to measure the drift. drift_threshold = int(params.get("drift_threshold", 10)) # The time interval to check vm's time interval_gettime = int(params.get("interval_gettime", 600)) test_duration = float(params.get("test_duration", "120")) stop_time = int(params.get("stop_time", 60)) try: # Get time before set cpu offline # (ht stands for host time, gt stands for guest time) error_context.context("get time before set cpu offline") (ht0, gt0) = utils_test.get_time(session, time_command, time_filter_re, time_format) # Check cpu number error_context.context("check guest cpu number") smp = int(params.get("smp")) if smp < 2: test.error("The guest only has %d vcpu," "unsupport cpu offline" % smp) # Set cpu offline error_context.context("set cpu offline ") offline_cpu_cmd = params.get("offline_cpu_cmd") s, o = session.cmd_status_output(offline_cpu_cmd) if s != 0: logging.error(o) test.error("Failed set guest cpu offline") # Sleep for a while after set cpu offline time.sleep(stop_time) # Get time after set cpu offline error_context.context("get time after set cpu offline") (ht1, gt1) = utils_test.get_time(session, time_command, time_filter_re, time_format) # Report results host_delta = ht1 - ht0 guest_delta = gt1 - gt0 drift = 100.0 * (host_delta - guest_delta) / host_delta logging.info("Host duration: %.2f", host_delta) logging.info("Guest duration: %.2f", guest_delta) logging.info("Drift: %.2f%%", drift) if abs(drift) > drift_threshold: test.fail("Time drift too large: %.2f%%" % drift) # Set cpu online again error_context.context("set cpu online") online_cpu_cmd = params.get("online_cpu_cmd") s, o = session.cmd_status_output(online_cpu_cmd) if s != 0: logging.error(o) test.error("Failed set guest cpu online") error_context.context("get time after set cpu online") start_time = time.time() while (time.time() - start_time) < test_duration: # Get time delta after set cpu online (ht1, gt1) = utils_test.get_time(session, time_command, time_filter_re, time_format) # Report results host_delta = ht1 - ht0 guest_delta = gt1 - gt0 drift = 100.0 * (host_delta - guest_delta) / host_delta logging.info("Host duration: %.2f", host_delta) logging.info("Guest duration: %.2f", guest_delta) logging.info("Drift: %.2f%%", drift) time.sleep(interval_gettime) if abs(drift) > drift_threshold: test.fail("Time drift too large: %.2f%%" % drift) finally: session.close() # remove flags add for this test. if boot_option_added or boot_option_removed: utils_test.update_boot_option(vm, args_removed=boot_option_added, args_added=boot_option_removed)
def run(test, params, env): """ Verify the login guest with multi backends spapr-vty: 1) Boot guest with multi spapr-vty with backend 2) Modify the kernel cfg file to specify the backend 3) For pty and file backend: 3.1) Open and close chardev 4) For unix_socket and tcp_socket: 4.1) Login guest 4.2) Create and delete files inside guest :param test: QEMU test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ prompt = params.get("shell_prompt") create_delete_file = params["create_delete_file"] vm = env.get_vm(params["main_vm"]) vm.wait_for_login() for serial_id in params.objects("serials"): if serial_id != "vs1": hvc_id = int(serial_id.replace('vs', '')) - 1 kernel_params = "console=hvc%s,115200" % hvc_id utils_test.update_boot_option(vm, args_added=kernel_params) backend = params.object_params(serial_id)["chardev_backend"] serial_device = vm.devices.get(serial_id) chardev_qid = serial_device.get_param("chardev") chardev_device = vm.devices.get_by_qid(chardev_qid)[0] logging.info("The currently tested backend is %s.", backend) if backend == 'unix_socket': session = vm.wait_for_serial_login(timeout=60) session.cmd(create_delete_file) session.close() elif backend == 'tcp_socket': session = remote.remote_login(client='nc', host=chardev_device.params['host'], port=chardev_device.params['port'], username=params['username'], password=params['password'], prompt=prompt, timeout=240) session.cmd(create_delete_file) session.close() elif backend == 'pty': chardev_info = vm.monitor.human_monitor_cmd('info chardev') hostfile = re.findall( '%s: filename=pty:(/dev/pts/\\d)?' % serial_id, chardev_info) if not hostfile: test.fail("Can't find the corresponding pty backend: %s" % chardev_info) fd_pty = os.open(hostfile[0], os.O_RDWR | os.O_NONBLOCK) os.close(fd_pty) elif backend == 'file': filename = chardev_device.params['path'] with open(filename) as f: if 'Linux' not in f.read(): test.fail("Guest boot fail with file backend.") elif backend == 'null': session = vm.wait_for_login() session.cmd(create_delete_file) vm.verify_dmesg() vm.destroy()
def run_timedrift_with_stop(test, params, env): """ Time drift test with stop/continue the guest: 1) Log into a guest. 2) Take a time reading from the guest and host. 3) Stop the running of the guest 4) Sleep for a while 5) Continue the guest running 6) Take a second time reading. 7) If the drift (in seconds) is higher than a user specified value, fail. :param test: QEMU test object. :param params: Dictionary with test parameters. :param env: Dictionary with the test environment. """ login_timeout = int(params.get("login_timeout", 360)) sleep_time = int(params.get("sleep_time", 30)) vm = env.get_vm(params["main_vm"]) vm.verify_alive() boot_option_added = params.get("boot_option_added") boot_option_removed = params.get("boot_option_removed") if boot_option_added or boot_option_removed: utils_test.update_boot_option(vm, args_removed=boot_option_removed, args_added=boot_option_added) session = vm.wait_for_login(timeout=login_timeout) # Collect test parameters: # Command to run to get the current time time_command = params["time_command"] # Filter which should match a string to be passed to time.strptime() time_filter_re = params["time_filter_re"] # Time format for time.strptime() time_format = params["time_format"] drift_threshold = float(params.get("drift_threshold", "10")) drift_threshold_single = float(params.get("drift_threshold_single", "3")) stop_iterations = int(params.get("stop_iterations", 1)) stop_time = int(params.get("stop_time", 60)) stop_with_signal = params.get("stop_with_signal") == "yes" # Get guest's pid. pid = vm.get_pid() try: # Get initial time # (ht stands for host time, gt stands for guest time) (ht0, gt0) = utils_test.get_time(session, time_command, time_filter_re, time_format) # Stop the guest for i in range(stop_iterations): # Get time before current iteration (ht0_, gt0_) = utils_test.get_time(session, time_command, time_filter_re, time_format) # Run current iteration logging.info("Stop %s second: iteration %d of %d...", stop_time, (i + 1), stop_iterations) if stop_with_signal: logging.debug("Stop guest") os.kill(pid, signal.SIGSTOP) time.sleep(stop_time) logging.debug("Continue guest") os.kill(pid, signal.SIGCONT) else: vm.pause() time.sleep(stop_time) vm.resume() # Sleep for a while to wait the interrupt to be reinjected logging.info("Waiting for the interrupt to be reinjected ...") time.sleep(sleep_time) # Get time after current iteration (ht1_, gt1_) = utils_test.get_time(session, time_command, time_filter_re, time_format) # Report iteration results host_delta = ht1_ - ht0_ guest_delta = gt1_ - gt0_ drift = abs(host_delta - guest_delta) logging.info("Host duration (iteration %d): %.2f", (i + 1), host_delta) logging.info("Guest duration (iteration %d): %.2f", (i + 1), guest_delta) logging.info("Drift at iteration %d: %.2f seconds", (i + 1), drift) # Fail if necessary if drift > drift_threshold_single: raise error.TestFail("Time drift too large at iteration %d: " "%.2f seconds" % (i + 1, drift)) # Get final time (ht1, gt1) = utils_test.get_time(session, time_command, time_filter_re, time_format) finally: if session: session.close() # remove flags add for this test. if boot_option_added or boot_option_removed: utils_test.update_boot_option(vm, args_removed=boot_option_added, args_added=boot_option_removed) # Report results host_delta = ht1 - ht0 guest_delta = gt1 - gt0 drift = abs(host_delta - guest_delta) logging.info("Host duration (%d stops): %.2f", stop_iterations, host_delta) logging.info("Guest duration (%d stops): %.2f", stop_iterations, guest_delta) logging.info("Drift after %d stops: %.2f seconds", stop_iterations, drift) # Fail if necessary if drift > drift_threshold: raise error.TestFail("Time drift too large after %d stops: " "%.2f seconds" % (stop_iterations, drift))
def run(test, params, env): """ MULTI_QUEUE chang queues number test 1) Boot up VM, and login guest 2) Check guest pci msi support and reset it as expection 3) Enable the queues in guest 4) Run bg_stress_test(pktgen, netperf or file copy) if needed 5) Change queues number repeatly during stress test running 6) Ping external host (local host, if external host not available) :param test: QEMU test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ def change_queues_number(session, ifname, q_number, queues_status=None): """ Change queues number """ mq_set_cmd = "ethtool -L %s combined %d" % (ifname, q_number) if not queues_status: queues_status = get_queues_status(session, ifname) if (q_number != queues_status[1] and q_number <= queues_status[0] and q_number > 0): expect_status = 0 else: expect_status = 1 status, output = session.cmd_status_output(mq_set_cmd) cur_queues_status = get_queues_status(session, ifname) if status != expect_status: err_msg = "Change queues number failed, " err_msg += "current queues set is %s, " % queues_status[1] err_msg += "max allow queues set is %s, " % queues_status[0] err_msg += "when run cmd: '%s', " % mq_set_cmd err_msg += "expect exit status is: %s, " % expect_status err_msg += "output: '%s'" % output raise error.TestFail(err_msg) if not status and cur_queues_status == queues_status: raise error.TestFail("params is right, but change queues failed") elif status and cur_queues_status != queues_status: raise error.TestFail("No need change queues number") return [int(_) for _ in cur_queues_status] def get_queues_status(session, ifname, timeout=240): """ Get queues status """ mq_get_cmd = "ethtool -l %s" % ifname nic_mq_info = session.cmd_output(mq_get_cmd, timeout=timeout) queues_reg = re.compile(r"Combined:\s+(\d)", re.I) queues_info = queues_reg.findall(" ".join(nic_mq_info.splitlines())) if len(queues_info) != 2: err_msg = "Oops, get guest queues info failed, " err_msg += "make sure your guest support MQ.\n" err_msg += "Check cmd is: '%s', " % mq_get_cmd err_msg += "Command output is: '%s'." % nic_mq_info raise error.TestNAError(err_msg) return [int(x) for x in queues_info] def enable_multi_queues(vm): sess = vm.wait_for_serial_login(timeout=login_timeout) error.context("Enable multi queues in guest.", logging.info) for nic_index, nic in enumerate(vm.virtnet): ifname = utils_net.get_linux_ifname(sess, nic.mac) queues = int(nic.queues) change_queues_number(sess, ifname, queues) def ping_test(dest_ip, ping_time, lost_raito, session=None): status, output = utils_test.ping(dest=dest_ip, timeout=ping_time, session=session) packets_lost = utils_test.get_loss_ratio(output) if packets_lost > lost_raito: err = " %s%% packages lost during ping. " % packets_lost err += "Ping command log:\n %s" % "\n".join( output.splitlines()[-3:]) raise error.TestFail(err) error.context("Init guest and try to login", logging.info) login_timeout = int(params.get("login_timeout", 360)) bg_stress_test = params.get("run_bgstress") bg_stress_run_flag = params.get("bg_stress_run_flag") vm = env.get_vm(params["main_vm"]) vm.verify_alive() vm.wait_for_login(timeout=login_timeout) if params.get("pci_nomsi", "no") == "yes": error.context("Disable pci msi in guest", logging.info) utils_test.update_boot_option(vm, args_added="pci=nomsi") vm.wait_for_login(timeout=login_timeout) enable_multi_queues(vm) session_serial = vm.wait_for_serial_login(timeout=login_timeout) s_session = None bg_ping = params.get("bg_ping") b_ping_lost_ratio = int(params.get("background_ping_package_lost_ratio", 5)) f_ping_lost_ratio = int(params.get("final_ping_package_lost_ratio", 5)) guest_ip = vm.get_address() b_ping_time = int(params.get("background_ping_time", 60)) f_ping_time = int(params.get("final_ping_time", 60)) bg_test = None try: ifnames = [] for nic_index, nic in enumerate(vm.virtnet): ifname = utils_net.get_linux_ifname(session_serial, vm.virtnet[nic_index].mac) ifnames.append(ifname) if bg_stress_test: error.context("Run test %s background" % bg_stress_test, logging.info) stress_thread = "" wait_time = float(params.get("wait_bg_time", 60)) env[bg_stress_run_flag] = False stress_thread = utils.InterruptedThread( utils_test.run_virt_sub_test, (test, params, env), {"sub_type": bg_stress_test}) stress_thread.start() if bg_stress_run_flag: utils_misc.wait_for( lambda: env.get(bg_stress_run_flag), wait_time, 0, 5, "Wait %s start background" % bg_stress_test) if bg_ping == "yes": error.context("Ping guest from host", logging.info) args = (guest_ip, b_ping_time, b_ping_lost_ratio) bg_test = utils.InterruptedThread(ping_test, args) bg_test.start() error.context("Change queues number repeatly", logging.info) repeat_counts = int(params.get("repeat_counts", 10)) for nic_index, nic in enumerate(vm.virtnet): if "virtio" not in nic['nic_model']: continue queues = int(vm.virtnet[nic_index].queues) if queues == 1: logging.info("Nic with single queue, skip and continue") continue ifname = ifnames[nic_index] default_change_list = xrange(1, int(queues + 1)) change_list = params.get("change_list") if change_list: change_list = change_list.split(",") else: change_list = default_change_list for repeat_num in xrange(1, repeat_counts + 1): error.context("Change queues number -- %sth" % repeat_num, logging.info) try: queues_status = get_queues_status(session_serial, ifname) for q_number in change_list: queues_status = change_queues_number( session_serial, ifname, int(q_number), queues_status) except aexpect.ShellProcessTerminatedError: vm = env.get_vm(params["main_vm"]) session = vm.wait_for_serial_login(timeout=login_timeout) session_serial = session queues_status = get_queues_status(session_serial, ifname) for q_number in change_list: queues_status = change_queues_number( session_serial, ifname, int(q_number), queues_status) if params.get("ping_after_changing_queues", "yes") == "yes": default_host = "www.redhat.com" ext_host_get_cmd = params.get("ext_host_get_cmd", "") try: ext_host = utils.system_output(ext_host_get_cmd) except error.CmdError: logging.warn( "Can't get specified host with cmd '%s'," " Fallback to default host '%s'", ext_host_get_cmd, default_host) ext_host = default_host if not ext_host: # Fallback to a hardcode host, eg: ext_host = default_host s_session = vm.wait_for_login(timeout=login_timeout) txt = "ping %s after changing queues in guest." error.context(txt, logging.info) ping_test(ext_host, f_ping_time, f_ping_lost_ratio, s_session) if bg_stress_test: env[bg_stress_run_flag] = False if stress_thread: error.context("wait for background test finish", logging.info) try: stress_thread.join() except Exception, err: err_msg = "Run %s test background error!\n " err_msg += "Error Info: '%s'" raise error.TestError(err_msg % (bg_stress_test, err)) finally: if bg_stress_test: env[bg_stress_run_flag] = False if session_serial: session_serial.close() if s_session: s_session.close() if bg_test: error.context("Wait for background ping test finish.", logging.info) try: bg_test.join() except Exception, err: txt = "Fail to wait background ping test finish. " txt += "Got error message %s" % err raise error.TestFail(txt)
def run(test, params, env): """ Test to change the kernel param based on user input. 1. Prepare test environment, boot the guest 2. Change the kernel parameter as per user input 3. Reboot the guest and check whether /proc/cmdline reflects 4. Check the boot log in guest dmesg and validate 5. Perform any test operation if any, based on kernel param change 6. Recover test environment """ vms = params.get("vms").split() kernel_param = params.get("kernel_param", "quiet") kernel_param_remove = params.get("kernel_param_remove", "") if not kernel_param: kernel_param = None if not kernel_param_remove: kernel_param_remove = None cpu_check = params.get("hardware", "").upper() boot_log = params.get("boot_log", None) check_cmdline_only = "yes" == params.get("check_cmdline_only", "no") status_error = params.get("status_error", "no") == "yes" vm_dict = {} vm_list = env.get_all_vms() # To ensure host that doesn't support Radix MMU gets skipped if cpu_check: cpu_model = cpu.get_cpu_info()['Model name'].upper() if cpu_check not in cpu_model: logging.info("This test will work for %s", cpu_check) test.skip("Test is not applicable for %s" % cpu_model) # back up vmxml for vm_name in vms: vm_dict[vm_name] = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) try: for vm in vm_list: session = vm.wait_for_login() if check_cmdline_only: check_cmdline( session, params.get( "expect_in_cmdline", "expect_in_cmdline not defined in test configuration")) else: utils_test.update_boot_option(vm, args_added=kernel_param, args_removed=kernel_param_remove, need_reboot=True) if boot_log: session = vm.wait_for_login() # To ensure guest that doesn't support Radix MMU gets skipped if cpu_check: cmd = "grep cpu /proc/cpuinfo | awk '{print $3}' | " cmd += "head -n 1" status, output = session.cmd_status_output(cmd) if status: test.error("couldn't get cpu information from guest " "%s" % vm.name) if cpu_check not in output.upper() and "radix" in boot_log: test.skip("radix MMU not supported in %s" % output) status, output = session.cmd_status_output("dmesg") if status: logging.error(output) test.error("unable to get dmesg from guest: %s" % vm.name) if status_error: if boot_log in output: test.fail("Able to find %s in dmesg of guest: " "%s" % (boot_log, vm.name)) logging.info("unable to find %s in dmesg of guest: %s", boot_log, vm.name) else: if boot_log not in output: test.fail("unable to find %s in dmesg of guest: " "%s" % (boot_log, vm.name)) logging.info("Able to find %s in dmesg of guest: %s", boot_log, vm.name) if session: session.close() finally: # close the session and recover the vms if session: session.close() for vm in vm_list: vm.destroy() vm_dict[vm.name].sync()
def run_timedrift_monotonicity(test, params, env): """ Check guest time monotonicity during migration: 1) Log into a guest. 2) Take time from guest. 3) Migrate the guest. 4) Keep guest running for a period after migration, and record the time log. 5) Analyse log if it is exist. @param test: QEMU test object. @param params: Dictionary with test parameters. @param env: Dictionary with the test environment. """ def get_time(cmd, test_time, session): if os.path.isfile(host_path): os.remove(host_path) lasttv = "0" cmd_timeout=int(params.get("cmd_timeout")) start_time = time.time() while (time.time() - start_time) < test_time : tv = session.cmd_output(cmd, timeout=cmd_timeout) if params.get("os_type") == 'windows': list = re.split('[:]',tv) tv = str(int(list[0])*3600 + int(list[1])*60 + float(list[2])) if float(tv) < float(lasttv): p_tv = "time value = " + tv + "\n" p_lasttv = "last time value = " + lasttv + "\n" time_log = file(host_path, 'a') time_log.write("time went backwards:\n" + p_tv + p_lasttv) time_log.close() lasttv = tv time.sleep(0.1) vm = env.get_vm(params["main_vm"]) vm.verify_alive() boot_option_added = params.get("boot_option_added") boot_option_removed = params.get("boot_option_removed") if boot_option_added or boot_option_removed: utils_test.update_boot_option(vm, args_removed=boot_option_removed, args_added=boot_option_added) timeout = int(params.get("login_timeout", 360)) session1 = vm.wait_for_login(timeout=timeout) host_path = params.get("host_path") cmd = params.get("cmd_get_time") test_time = int(params.get("time_linger","60")) try: # take time logging.info("Start take guest time") bg = utils.InterruptedThread(get_time,(cmd,test_time,session1)) bg.start() # migration logging.info("Start migration") vm.migrate() # log in logging.info("Logging in after migration...") session2 = vm.wait_for_login(timeout=timeout) if not session2: raise error.TestFail("Could not log in after migration") logging.info("Logged in after migration") # linger a while time.sleep(test_time) # analyse the result if os.path.isfile(host_path): log_dir = os.path.join(test.outputdir, "timedrift-monotonicity-result.txt") shutil.copyfile(host_path, log_dir) myfile = file(host_path, 'r') for line in myfile: if "time went backwards" in line: myfile.close() raise error.TestFail("Failed Time Monotonicity testing, " "Please check log %s" % host_path) finally: session1.close() # remove flags add for this test. if boot_option_added or boot_option_removed: utils_test.update_boot_option(vm, args_removed=boot_option_added, args_added=boot_option_removed)