def guest_netwok_connecting_check(guest_ip, link_up, change_queues=False): """ Check whether guest network is connective by ping """ if change_queues: env["run_change_queues"] = False bg_thread = utils.InterruptedThread(change_queues_number_repeatly, (guest_ifname, )) bg_thread.start() utils_misc.wait_for(lambda: env["run_change_queues"], 30, 0, 2, "wait queues change start") time.sleep(0.5) output = utils_test.ping(guest_ip, 10, interface=host_interface, timeout=20, session=None)[1] if not link_up and utils_test.get_loss_ratio(output) < 80: err_msg = "guest network still connecting after down the link" raise error.TestFail(err_msg) elif link_up and utils_test.get_loss_ratio(output) > 20: err_msg = "All packets lost during ping guest ip after link up" raise error.TestFail(err_msg) if change_queues: env["run_change_queues"] = False bg_thread.join()
def run_nic_promisc(test, params, env): """ Test nic driver in promisc mode: 1) Boot up a VM. 2) Repeatedly enable/disable promiscuous mode in guest. 3) Transfer file from host to guest, and from guest to host in the same time @param test: QEMU test object. @param params: Dictionary with the test parameters. @param env: Dictionary with test environment. """ vm = env.get_vm(params["main_vm"]) vm.verify_alive() timeout = int(params.get("login_timeout", 360)) session_serial = vm.wait_for_serial_login(timeout=timeout) ethname = utils_net.get_linux_ifname(session_serial, vm.get_mac_address(0)) try: transfer_thread = utils.InterruptedThread(utils_test.run_file_transfer, (test, params, env)) transfer_thread.start() while transfer_thread.isAlive(): session_serial.cmd("ip link set %s promisc on" % ethname) session_serial.cmd("ip link set %s promisc off" % ethname) except Exception: transfer_thread.join(suppress_exception=True) raise else: transfer_thread.join()
def start_stress(session): """ Load stress in guest. """ error.context("Load stress in guest", logging.info) stress_type = params.get("stress_type", "none") if stress_type == "none": return if stress_type == "netperf": bg = "" bg_stress_test = params.get("run_bgstress") bg = utils.InterruptedThread(utils_test.run_virt_sub_test, (test, params, env), {"sub_type": bg_stress_test}) bg.start() if stress_type == "io": install_stress_app(session) cmd = params.get("start_cmd") logging.info("Launch stress app in guest with command: '%s'" % cmd) session.sendline(cmd) running = utils_misc.wait_for(lambda: stress_running(session), timeout=150, step=5) if not running: raise error.TestError("Stress isn't running") logging.info("Stress running now")
def guest_netwok_connecting_check(guest_ip, link_up, change_queues=False): """ Check whether guest network is connective by ping """ if link_up: vm.wait_for_login() guest_ip = vm.get_address() if change_queues: env["run_change_queues"] = False bg_thread = utils.InterruptedThread(change_queues_number_repeatly, (guest_ifname, )) bg_thread.start() utils_misc.wait_for(lambda: env["run_change_queues"], 30, 0, 2, "wait queues change start") _, output = utils_test.ping(guest_ip, count=10, timeout=20) if not link_up and utils_test.get_loss_ratio(output) != 100: err_msg = "guest network still connecting after down the link" raise error.TestFail(err_msg) elif link_up and utils_test.get_loss_ratio(output) == 100: err_msg = "All packets lost during ping guest ip after link up" raise error.TestFail(err_msg) else: logging.info("Guest network connecting is exactly as expected") if change_queues: env["run_change_queues"] = False bg_thread.join()
def bootstrap_tests(options): """ Bootstrap process (download the appropriate JeOS file to data dir). This function will check whether the JeOS is in the right location of the data dir, if not, it will download it non interactively. @param options: OptParse object with program command line options. """ test_dir = os.path.dirname(sys.modules[__name__].__file__) if options.type: test_dir = os.path.abspath( os.path.join(os.path.dirname(test_dir), options.type)) elif options.config: test_dir = os.path.dirname(os.path.dirname(options.config)) test_dir = os.path.abspath(test_dir) check_modules = [ "kvm", "kvm-%s" % utils_misc.get_cpu_vendor(verbose=False) ] online_docs_url = "https://github.com/autotest/virt-test/wiki" kwargs = { 'test_name': options.type, 'test_dir': test_dir, 'base_dir': data_dir.get_data_dir(), 'default_userspace_paths': None, 'check_modules': check_modules, 'online_docs_url': online_docs_url, 'restore_image': options.restore, 'interactive': False } # Tolerance we have without printing a message for the user to wait (3 s) tolerance = 3 failed = False wait_message_printed = False bg = utils.InterruptedThread(bootstrap.bootstrap, kwargs=kwargs) t_begin = time.time() bg.start() while bg.isAlive(): t_elapsed = time.time() - t_begin if t_elapsed > tolerance and not wait_message_printed: print_stdout("Running setup. Please wait...") wait_message_printed = True sys.stdout.switch() time.sleep(0.1) if wait_message_printed: sys.stdout.switch() reason = None try: bg.join() except Exception, e: failed = True reason = e
def wrapper(*args, **kargs): threads = [] for o in self: threads.append(utils.InterruptedThread(o.__getattribute__(name), args=args, kwargs=kargs)) for t in threads: t.start() return map(lambda t: t.join(), threads)
def run_nicdriver_unload(test, params, env): """ Test nic driver. 1) Boot a VM. 2) Get the NIC driver name. 3) Repeatedly unload/load NIC driver. 4) Multi-session TCP transfer on test interface. 5) Check whether the test interface should still work. @param test: KVM test object. @param params: Dictionary with the test parameters. @param env: Dictionary with test environment. """ timeout = int(params.get("login_timeout", 360)) vm = env.get_vm(params["main_vm"]) vm.verify_alive() session_serial = vm.wait_for_serial_login(timeout=timeout) ethname = utils_test.get_linux_ifname(session_serial, vm.get_mac_address(0)) # get ethernet driver from '/sys' directory. # ethtool can do the same thing and doesn't care about os type. # if we make sure all guests have ethtool, we can make a change here. sys_path = params.get("sys_path") % (ethname) # readlink in RHEL4.8 doesn't have '-e' param, should use '-f' in RHEL4.8. readlink_cmd = params.get("readlink_command", "readlink -e") driver = os.path.basename( session_serial.cmd("%s %s" % (readlink_cmd, sys_path)).strip()) logging.info("driver is %s", driver) try: threads = [] for _ in range(int(params.get("sessions_num", "10"))): thread = utils.InterruptedThread(utils_test.run_file_transfer, (test, params, env)) thread.start() threads.append(thread) time.sleep(10) while threads[0].isAlive(): session_serial.cmd("sleep 10") session_serial.cmd("ifconfig %s down" % ethname) session_serial.cmd("modprobe -r %s" % driver) session_serial.cmd("modprobe %s" % driver) session_serial.cmd("ifconfig %s up" % ethname) except Exception: for thread in threads: thread.join(suppress_exception=True) raise else: for thread in threads: thread.join()
def parallel(targets): """ Run multiple functions in parallel. @param targets: A sequence of tuples or functions. If it's a sequence of tuples, each tuple will be interpreted as (target, args, kwargs) or (target, args) or (target,) depending on its length. If it's a sequence of functions, the functions will be called without arguments. @return: A list of the values returned by the functions called. """ threads = [] for target in targets: if isinstance(target, tuple) or isinstance(target, list): t = utils.InterruptedThread(*target) else: t = utils.InterruptedThread(target) threads.append(t) t.start() return [t.join() for t in threads]
def run(test, params, env): """ Run guest suspend under guest nic stress 1) Boot up VM, and login guest 2) Run bg_stress_test(pktgen, netperf or file copy) if needed 3) Do guest suspend and resume test :param test: QEMU test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ 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) bg_stress_test = params.get("run_bgstress") try: 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() if not utils_misc.wait_for(lambda: env.get(bg_stress_run_flag), wait_time, 0, 5, "Wait %s test start" % bg_stress_test): raise error.TestError("Run stress test error") suspend_type = params.get("guest_suspend_type") error.context("Run suspend '%s' test under stress" % suspend_type, logging.info) bg_cmd = guest_suspend.run_guest_suspend args = (test, params, env) bg = utils_test.BackgroundTest(bg_cmd, args) bg.start() if bg.is_alive(): try: env[bg_stress_run_flag] = False bg.join() except Exception, e: err_msg = "Run guest suspend: '%s' error!\n" % suspend_type err_msg += "Error info: '%s'" % e raise error.TestFail(err_msg) finally: env[bg_stress_run_flag] = False
def run(test, params, env): """ Test nic driver in promisc mode: 1) Boot up a VM. 2) Repeatedly enable/disable promiscuous mode in guest. 3) Transfer file between host and guest during nic promisc on/off :param test: QEMU test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ def set_nic_promisc_onoff(session): if os_type == "linux": session.cmd_output_safe("ip link set %s promisc on" % ethname) session.cmd_output_safe("ip link set %s promisc off" % ethname) else: cmd = "c:\\set_win_promisc.py" session.cmd(cmd) error.context("Boot vm and prepare test environment", logging.info) vm = env.get_vm(params["main_vm"]) vm.verify_alive() timeout = int(params.get("login_timeout", 360)) session_serial = vm.wait_for_serial_login(timeout=timeout) session = vm.wait_for_login(timeout=timeout) os_type = params.get("os_type") if os_type == "linux": ethname = utils_net.get_linux_ifname(session, vm.get_mac_address(0)) else: script_path = os.path.join(test.virtdir, "scripts/set_win_promisc.py") vm.copy_files_to(script_path, "C:\\") try: transfer_thread = utils.InterruptedThread(utils_test.run_file_transfer, (test, params, env)) error.context("Run utils_test.file_transfer ...", logging.info) transfer_thread.start() error.context("Perform file transfer while turning nic promisc on/off", logging.info) while transfer_thread.isAlive(): set_nic_promisc_onoff(session_serial) except Exception: transfer_thread.join(suppress_exception=True) raise else: transfer_thread.join() if session: session.close()
def transfer_data(session, receive_cmd, send_cmd, data_file, n_time): txt = "Transfer data betwwen guest and host for %s times" % n_time error.context(txt, logging.info) for num in xrange(n_time): logging.info("Data transfer repeat %s/%s." % (num + 1, n_time)) try: args = (session, receive_cmd, data_file) guest_receive = utils.InterruptedThread(receive_data, args) guest_receive.start() utils.system(send_cmd, timeout=30) finally: if guest_receive: guest_receive.join(10)
def netload_kill_problem(session_serial): setup_cmd = params.get("setup_cmd") clean_cmd = params.get("clean_cmd") firewall_flush = params.get("firewall_flush", "service iptables stop") error.context("Stop firewall in guest and host.", logging.info) try: utils.run(firewall_flush) except Exception: logging.warning("Could not stop firewall in host") try: session_serial.cmd(firewall_flush) except Exception: logging.warning("Could not stop firewall in guest") try: bg_stress_test = params.get("background_stress_test", 'netperf_stress') error.context( "Run subtest %s between host and guest." % bg_stress_test, logging.info) stress_thread = None wait_time = int(params.get("wait_bg_time", 60)) bg_stress_run_flag = params.get("bg_stress_run_flag") vm_wait_time = int(params.get("wait_before_kill_vm")) 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 not utils_misc.wait_for(lambda: env.get(bg_stress_run_flag), wait_time, 0, 1, "Wait %s test start" % bg_stress_test): err = "Fail to start netperf test between guest and host" raise error.TestError(err) logging.info("Sleep %ss before killing the VM", vm_wait_time) time.sleep(vm_wait_time) msg = "During netperf running, Check that we can kill VM with signal 0" error.context(msg, logging.info) kill_and_check(vm) finally: try: stress_thread.join(60) except Exception: pass
def _action_before_fsfreeze(self, *args): copy_timeout = int(self.params.get("copy_timeoout", 600)) file_size = int(self.params.get("file_size", "500")) tmp_name = utils_misc.generate_random_string(5) self.host_path = self.guest_path = "/tmp/%s" % tmp_name if self.params.get("os_type") != "linux": self.guest_path = r"c:\%s" % tmp_name error.context("Create a file in host.") utils.run("dd if=/dev/urandom of=%s bs=1M count=%s" % (self.host_path, file_size)) self.orig_hash = utils.hash_file(self.host_path) error.context("Transfer file from %s to %s" % (self.host_path, self.guest_path), logging.info) self.bg = utils.InterruptedThread(self.vm.copy_files_to, (self.host_path, self.guest_path), dict(verbose=True, timeout=copy_timeout)) self.bg.start()
def bootstrap_tests(options): """ Bootstrap process (download the appropriate JeOS file to data dir). This function will check whether the JeOS is in the right location of the data dir, if not, it will download it non interactively. :param options: OptParse object with program command line options. """ if options.vt_config: parent_config_dir = os.path.dirname(os.path.dirname(options.vt_config)) parent_config_dir = os.path.dirname(parent_config_dir) options.vt_type = parent_config_dir kwargs = {'options': options} # Tolerance we have without printing a message for the user to wait (3 s) tolerance = 3 failed = False wait_message_printed = False bg = utils.InterruptedThread(bootstrap.setup, kwargs=kwargs) t_begin = time.time() bg.start() while bg.isAlive(): t_elapsed = time.time() - t_begin if t_elapsed > tolerance and not wait_message_printed: print_stdout("Running setup. Please wait...") wait_message_printed = True # if bootstrap takes too long, we temporarily make stdout verbose # again, so the user can see what's taking so long sys.stdout.restore() time.sleep(0.1) # in case stdout was restored above, redirect it again sys.stdout.redirect() reason = None try: bg.join() except Exception, e: failed = True reason = e
def wrapper(*args, **kargs): threads = [] for o in self: threads.append(utils.InterruptedThread(o.__getattribute__(name), args=args, kwargs=kargs)) for t in threads: t.start() result = [] for t in threads: ret = {} try: ret["return"] = t.join() except Exception: ret["exception"] = sys.exc_info() ret["args"] = args ret["kargs"] = kargs result.append(ret) return result
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_nicdriver_unload(test, params, env): """ Test nic driver load/unload. 1) Boot a VM. 2) Get the NIC driver name. 3) Multi-session TCP transfer on test interface. 4) Repeatedly unload/load NIC driver during file transfer. 5) Check whether the test interface should still work. :param test: QEMU test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ def all_threads_done(threads): for thread in threads: if thread.isAlive(): return False else: continue return True def all_threads_alive(threads): for thread in threads: if not thread.isAlive(): return False else: continue return True timeout = int(params.get("login_timeout", 360)) transfer_timeout = int(params.get("transfer_timeout", 1000)) filesize = int(params.get("filesize", 512)) vm = env.get_vm(params["main_vm"]) vm.verify_alive() session = vm.wait_for_login(timeout=timeout) error.base_context("Test env prepare") error.context("Get NIC interface name in guest.", logging.info) ethname = utils_net.get_linux_ifname(session, vm.get_mac_address(0)) # get ethernet driver from '/sys' directory. # ethtool can do the same thing and doesn't care about os type. # if we make sure all guests have ethtool, we can make a change here. sys_path = params.get("sys_path") % (ethname) # readlink in RHEL4.8 doesn't have '-e' param, should use '-f' in RHEL4.8. readlink_cmd = params.get("readlink_command", "readlink -e") driver = os.path.basename( session.cmd("%s %s" % (readlink_cmd, sys_path)).strip()) logging.info("The guest interface %s using driver %s" % (ethname, driver)) error.context( "Host test file prepare, create %dMB file on host" % filesize, logging.info) tmp_dir = data_dir.get_tmp_dir() host_path = os.path.join( tmp_dir, "host_file_%s" % utils_misc.generate_random_string(8)) guest_path = os.path.join( "/home", "guest_file_%s" % utils_misc.generate_random_string(8)) cmd = "dd if=/dev/zero of=%s bs=1M count=%d" % (host_path, filesize) utils.run(cmd) file_checksum = utils.hash_file(host_path, "md5") error.context( "Guest test file prepare, Copy file %s from host to guest" % host_path, logging.info) vm.copy_files_to(host_path, guest_path, timeout=transfer_timeout) if session.cmd_status("md5sum %s | grep %s" % (guest_path, file_checksum)): raise error.TestNAError("File MD5SUMs changed after copy to guest") logging.info("Test env prepare successfully") error.base_context("Nic driver load/unload testing", logging.info) session_serial = vm.wait_for_serial_login(timeout=timeout) try: error.context("Transfer file between host and guest", logging.info) threads = [] file_paths = [] host_file_paths = [] for sess_index in range(int(params.get("sessions_num", "10"))): sess_path = os.path.join("/home", "dst-%s" % sess_index) host_sess_path = os.path.join(tmp_dir, "dst-%s" % sess_index) thread1 = utils.InterruptedThread(vm.copy_files_to, (host_path, sess_path), {"timeout": transfer_timeout}) thread2 = utils.InterruptedThread(vm.copy_files_from, (guest_path, host_sess_path), {"timeout": transfer_timeout}) thread1.start() threads.append(thread1) thread2.start() threads.append(thread2) file_paths.append(sess_path) host_file_paths.append(host_sess_path) utils_misc.wait_for(lambda: all_threads_alive(threads), 60, 10, 1) time.sleep(5) error.context("Repeatedly unload/load NIC driver during file transfer", logging.info) while not all_threads_done(threads): error.context("Shutdown the driver for NIC interface.", logging.info) session_serial.cmd_output_safe("ifconfig %s down" % ethname) error.context("Unload NIC driver.", logging.info) session_serial.cmd_output_safe("modprobe -r %s" % driver) error.context("Load NIC driver.", logging.info) session_serial.cmd_output_safe("modprobe %s" % driver) error.context("Activate NIC driver.", logging.info) session_serial.cmd_output_safe("ifconfig %s up" % ethname) session_serial.cmd_output_safe("sleep %s" % random.randint(10, 60)) # files md5sums check error.context("File transfer finished, checking files md5sums", logging.info) err_info = [] for copied_file in file_paths: if session_serial.cmd_status("md5sum %s | grep %s" % (copied_file, file_checksum)): err_msg = "Guest file %s md5sum changed" err_info.append(err_msg % copied_file) for copied_file in host_file_paths: if utils.system("md5sum %s | grep %s" % (copied_file, file_checksum)): err_msg = "Host file %s md5sum changed" err_info.append(err_msg % copied_file) if err_info: raise error.TestError("files MD5SUMs changed after copying %s" % err_info) except Exception: for thread in threads: thread.join(suppress_exception=True) raise else: for thread in threads: thread.join() for copied_file in file_paths: session_serial.cmd("rm -rf %s" % copied_file) for copied_file in host_file_paths: utils.system("rm -rf %s" % copied_file) session_serial.cmd("%s %s" % ("rm -rf", guest_path)) os.remove(host_path) session.close() session_serial.close()
def run(test, params, env): """ Enable MULTI_QUEUE feature in guest 1) Boot up VM(s) 2) Login guests one by one 3) Enable MQ for all virtio nics by ethtool -L 4) Run netperf on guest 5) check vhost threads on host, if vhost is enable 6) check cpu affinity if smp == queues :param test: QEMU test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ def get_virtio_queues_irq(session): """ Return multi queues input irq list """ guest_irq_info = session.cmd_output("cat /proc/interrupts") return re.findall(r"(\d+):.*virtio\d+-input.\d", guest_irq_info) def get_cpu_affinity_hint(session, irq_number): """ Return the cpu affinity_hint of irq_number """ cmd_get_cpu_affinity = r"cat /proc/irq/%s/affinity_hint" % irq_number return session.cmd_output(cmd_get_cpu_affinity).strip() def get_cpu_index(cpu_id): """ Transfer cpu_id to cpu index """ cpu_used_index = [] for cpu_index in range(int(vm.cpuinfo.smp)): if int(cpu_id) & (1 << cpu_index) != 0: cpu_used_index.append(cpu_index) return cpu_used_index def set_cpu_affinity(session): """ Set cpu affinity """ cmd_set_cpu_affinity = r"echo $(cat /proc/irq/%s/affinity_hint)" cmd_set_cpu_affinity += " > /proc/irq/%s/smp_affinity" irq_list = get_virtio_queues_irq(session) for irq in irq_list: session.cmd(cmd_set_cpu_affinity % (irq, irq)) def get_cpu_irq_statistics(session, irq_number, cpu_id=None): """ Get guest interrupts statistics """ cmd = r"cat /proc/interrupts | sed -n '/^\s\+%s:/p'" % irq_number irq_statics = session.cmd_output(cmd) irq_statics_list = map(int, irq_statics.split()[1:-2]) if irq_statics_list: if cpu_id and cpu_id < len(irq_statics_list): return irq_statics_list[cpu_id] if not cpu_id: return irq_statics_list return [] login_timeout = int(params.get("login_timeout", 360)) queues = int(params.get("queues", 1)) vms = params.get("vms").split() if queues == 1: logging.info("No need to enable MQ feature for single queue") return for vm in vms: vm = env.get_vm(vm) vm.verify_alive() session = vm.wait_for_login(timeout=login_timeout) for i, nic in enumerate(vm.virtnet): if "virtio" in nic['nic_model']: ifname = utils_net.get_linux_ifname(session, vm.get_mac_address(i)) session.cmd_output("ethtool -L %s combined %d" % (ifname, queues)) o = session.cmd_output("ethtool -l %s" % ifname) if len(re.findall(r"Combined:\s+%d\s" % queues, o)) != 2: raise error.TestError("Fail to enable MQ feature of (%s)" % nic.nic_name) logging.info("MQ feature of (%s) is enabled" % nic.nic_name) taskset_cpu = params.get("netperf_taskset_cpu") if taskset_cpu: taskset_cmd = "taskset -c %s " % " ".join(taskset_cpu) params["netperf_cmd_prefix"] = taskset_cmd check_cpu_affinity = params.get("check_cpu_affinity", 'no') check_vhost = params.get("check_vhost_threads", 'yes') if check_cpu_affinity == 'yes' and (vm.cpuinfo.smp == queues): utils.system("systemctl stop irqbalance.service") set_cpu_affinity(session) bg_sub_test = params.get("bg_sub_test") n_instance = int(params.get("netperf_para_sessions", queues)) try: if bg_sub_test: error.context("Run test %s background" % bg_sub_test, logging.info) # Set flag, when the sub test really running, will change this # flag to True bg_stress_run_flag = params.get("bg_stress_run_flag") env[bg_stress_run_flag] = False stress_thread = "" wait_time = float(params.get("wait_bg_time", 60)) stress_thread = utils.InterruptedThread( utils_test.run_virt_sub_test, (test, params, env), {"sub_type": bg_sub_test}) stress_thread.start() # here wait sub test chang the test flag utils_misc.wait_for(lambda: env.get(bg_stress_run_flag), wait_time, 0, 5, "Wait %s start background" % bg_sub_test) if params.get("vhost") == 'vhost=on' and check_vhost == 'yes': error.context("Check vhost threads on host", logging.info) vhost_thread_pattern = params.get( "vhost_thread_pattern", r"\w+\s+(\d+)\s.*\[vhost-%s\]") vhost_threads = vm.get_vhost_threads(vhost_thread_pattern) time.sleep(10) top_cmd = r"top -n 1 -p %s -b" % ",".join( map(str, vhost_threads)) top_info = utils.system_output(top_cmd) logging.info("%s", top_info) vhost_re = re.compile(r"S(\s+0.0+){2}.*vhost-\d+[\d|+]") sleep_vhost_thread = len(vhost_re.findall(top_info, re.I)) running_threads = len(vhost_threads) - int(sleep_vhost_thread) n_instance = min(n_instance, int(queues), int(vm.cpuinfo.smp)) if (running_threads != n_instance): err_msg = "Run %s netperf session, but %s queues works" raise error.TestFail(err_msg % (n_instance, running_threads)) # check cpu affinity if check_cpu_affinity == 'yes' and (vm.cpuinfo.smp == queues): error.context("Check cpu affinity", logging.info) vectors = params.get("vectors", None) enable_msix_vectors = params.get("enable_msix_vectors") expect_vectors = 2 * int(queues) + 1 if (not vectors) and (enable_msix_vectors == "yes"): vectors = expect_vectors if vectors and (vectors >= expect_vectors) and taskset_cpu: cpu_irq_affinity = {} for irq in get_virtio_queues_irq(session): cpu_id = get_cpu_affinity_hint(session, irq) cpu_index = get_cpu_index(cpu_id) if cpu_index: for cpu in cpu_index: cpu_irq_affinity["%s" % cpu] = irq else: raise error.TestError("Can not get the cpu") irq_number = cpu_irq_affinity[taskset_cpu] irq_ori = get_cpu_irq_statistics(session, irq_number) logging.info("Cpu irq info: %s" % irq_ori) time.sleep(10) irq_cur = get_cpu_irq_statistics(session, irq_number) logging.info("After 10s, cpu irq info: %s" % irq_cur) irq_change_list = map(lambda x: x[0] - x[1], zip(irq_cur, irq_ori)) cpu_affinity = irq_change_list.index(max(irq_change_list)) if cpu_affinity != int(taskset_cpu): err_msg = "Error, taskset on cpu %s, " err_msg += "but queues use cpu %s" raise error.TestFail(err_msg % (taskset_cpu, cpu_affinity)) if bg_sub_test and stress_thread: env[bg_stress_run_flag] = False 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_sub_test, e)) finally: env[bg_stress_run_flag] = False if session: session.close()
def migrate(self, vms_name, srchost, dsthost, start_work=None, check_work=None, mig_mode="tcp", params_append=None): """ Migrate machine from srchost to dsthost. It executes start_work on source machine before migration and executes check_work on dsthost after migration. Migration execution progress: :: source host | dest host -------------------------------------------------------- prepare guest on both sides of migration - start machine and check if machine works - synchronize transfer data needed for migration -------------------------------------------------------- start work on source guests | wait for migration -------------------------------------------------------- migrate guest to dest host. wait on finish migration synchronization -------------------------------------------------------- | check work on vms -------------------------------------------------------- wait for sync on finish migration :param vms_name: List of vms. :param srchost: src host id. :param dsthost: dst host id. :param start_work: Function started before migration. :param check_work: Function started after migration. :param mig_mode: Migration mode. :param params_append: Append params to self.params only for migration. """ def migrate_wrap(vms_name, srchost, dsthost, start_work=None, check_work=None, params_append=None): logging.info("Starting migrate vms %s from host %s to %s" % (vms_name, srchost, dsthost)) pause = self.params.get("paused_after_start_vm") mig_error = None mig_data = MigrationData(self.params, srchost, dsthost, vms_name, params_append) cancel_delay = self.params.get("cancel_delay", None) host_offline_migration = self.params.get("host_mig_offline") try: try: if mig_data.is_src(): self.prepare_for_migration(mig_data, None) elif self.hostid == dsthost: if host_offline_migration != "yes": self.prepare_for_migration(mig_data, mig_mode) else: return if mig_data.is_src(): if start_work: if pause != "yes": start_work(mig_data) else: raise error.TestNAError("Can't start work if " "vm is paused.") # Starts VM and waits timeout before migration. if pause == "yes" and mig_data.is_src(): for vm in mig_data.vms: vm.resume() wait = self.params.get("start_migration_timeout", 0) logging.debug("Wait for migration %s seconds." % (wait)) time.sleep(int(wait)) self.before_migration(mig_data) self.migrate_vms(mig_data) timeout = 60 if cancel_delay is None: if host_offline_migration == "yes": self._hosts_barrier(self.hosts, mig_data.mig_id, 'wait_for_offline_mig', self.finish_timeout) if mig_data.is_dst(): self.prepare_for_migration(mig_data, mig_mode) self._hosts_barrier(self.hosts, mig_data.mig_id, 'wait2_for_offline_mig', self.finish_timeout) if (not mig_data.is_src()): timeout = self.mig_timeout self._hosts_barrier(mig_data.hosts, mig_data.mig_id, 'mig_finished', timeout) if mig_data.is_dst(): self.check_vms_dst(mig_data) if check_work: check_work(mig_data) else: self.check_vms_src(mig_data) if check_work: check_work(mig_data) except: mig_error = True raise finally: if mig_error and cancel_delay is not None: self._hosts_barrier(self.hosts, mig_data.mig_id, 'test_finihed', self.finish_timeout) elif mig_error: raise def wait_wrap(vms_name, srchost, dsthost): mig_data = MigrationData(self.params, srchost, dsthost, vms_name, None) timeout = (self.login_timeout + self.mig_timeout + self.finish_timeout) self._hosts_barrier(self.hosts, mig_data.mig_id, 'test_finihed', timeout) if (self.hostid in [srchost, dsthost]): mig_thread = utils.InterruptedThread(migrate_wrap, (vms_name, srchost, dsthost, start_work, check_work, params_append)) else: mig_thread = utils.InterruptedThread(wait_wrap, (vms_name, srchost, dsthost)) mig_thread.start() return mig_thread
def bootstrap_tests(options): """ Bootstrap process (download the appropriate JeOS file to data dir). This function will check whether the JeOS is in the right location of the data dir, if not, it will download it non interactively. :param options: OptParse object with program command line options. """ if options.type: test_dir = data_dir.get_backend_dir(options.type) elif options.config: parent_config_dir = os.path.dirname(os.path.dirname(options.config)) parent_config_dir = os.path.dirname(parent_config_dir) options.type = parent_config_dir test_dir = os.path.abspath(parent_config_dir) if options.type == 'qemu': check_modules = arch.get_kvm_module_list() else: check_modules = None online_docs_url = "https://github.com/autotest/virt-test/wiki" if not options.config: restore_image = not options.keep_image else: restore_image = False kwargs = {'test_name': options.type, 'test_dir': test_dir, 'base_dir': data_dir.get_data_dir(), 'default_userspace_paths': None, 'check_modules': check_modules, 'online_docs_url': online_docs_url, 'download_image': not options.no_downloads, 'selinux': options.selinux_setup, 'restore_image': restore_image, 'interactive': False, 'update_providers': options.update_providers} # Tolerance we have without printing a message for the user to wait (3 s) tolerance = 3 failed = False wait_message_printed = False bg = utils.InterruptedThread(bootstrap.bootstrap, kwargs=kwargs) t_begin = time.time() bg.start() while bg.isAlive(): t_elapsed = time.time() - t_begin if t_elapsed > tolerance and not wait_message_printed: print_stdout("Running setup. Please wait...") wait_message_printed = True # if bootstrap takes too long, we temporarily make stdout verbose # again, so the user can see what's taking so long sys.stdout.restore() time.sleep(0.1) # in case stdout was restored above, redirect it again sys.stdout.redirect() reason = None try: bg.join() except Exception, e: failed = True reason = e
def run(test, params, env): """ Test Steps: 1. boot up guest with sndbuf=1048576 or other value. 2. Transfer file between host and guest. 3. Run netperf between host and guest. 4. During netperf testing, from an external host ping the host whitch booting the guest. Params: :param test: QEMU test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ dst_ses = None try: error.context("Transfer file between host and guest", logging.info) utils_test.run_file_transfer(test, params, env) dsthost = params.get("dsthost") login_timeout = int(params.get("login_timeout", 360)) if dsthost: params_host = params.object_params("dsthost") dst_ses = remote.wait_for_login(params_host.get("shell_client"), dsthost, params_host.get("shell_port"), params_host.get("username"), params_host.get("password"), params_host.get("shell_prompt"), timeout=login_timeout) else: vm = env.get_vm(params["main_vm"]) vm.verify_alive() dst_ses = vm.wait_for_login(timeout=login_timeout) dsthost = vm.get_address() bg_stress_test = params.get("background_stress_test", 'netperf_stress') error.context("Run subtest %s between host and guest." % bg_stress_test, logging.info) s_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() if not utils_misc.wait_for(lambda: env.get(bg_stress_run_flag), wait_time, 0, 1, "Wait %s test start" % bg_stress_test): err = "Fail to start netperf test between guest and host" raise error.TestError(err) ping_timeout = int(params.get("ping_timeout", 60)) host_ip = utils_net.get_host_ip_address(params) txt = "Ping %s from %s during netperf testing" % (host_ip, dsthost) error.context(txt, logging.info) status, output = utils_test.ping(host_ip, session=dst_ses, timeout=ping_timeout) if status != 0: raise error.TestFail("Ping returns non-zero value %s" % output) package_lost = utils_test.get_loss_ratio(output) package_lost_ratio = float(params.get("package_lost_ratio", 5)) txt = "%s%% packeage lost when ping %s from %s." % (package_lost, host_ip, dsthost) if package_lost > package_lost_ratio: raise error.TestFail(txt) logging.info(txt) finally: try: stress_thread.join(60) except Exception: pass if dst_ses: dst_ses.close()
(destination_autotest_path, destination_autotest_path)) # Run the test logging.info("Running autotest control file %s on guest, timeout %ss", os.path.basename(control_path), timeout) try: bg = None try: logging.info("---------------- Test output ----------------") if migrate_background: mig_timeout = float(params.get("mig_timeout", "3600")) mig_protocol = params.get("migration_protocol", "tcp") bg = utils.InterruptedThread(session.cmd_output, kwargs={ 'cmd': "./autotest control", 'timeout': timeout, 'print_func': logging.info }) bg.start() while bg.isAlive(): logging.info("Autotest job did not end, start a round of " "migration") vm.migrate(timeout=mig_timeout, protocol=mig_protocol) else: session.cmd_output("./autotest-local --verbose control", timeout=timeout, print_func=logging.info) finally: logging.info("------------- End of test output ------------")
addresses.append(vm.get_address()) mon_session = vms[2].wait_for_login(timeout=timeout) src_file = (tmp_dir + "src-%s" % utils_misc.generate_random_string(8)) dst_file = (tmp_dir + "dst-%s" % utils_misc.generate_random_string(8)) try: # Before transfer, run tcpdump to try to catche data error_msg = "In guest3, try to capture the packets(guest1 <-> guest2)" error.context(error_msg, logging.info) interface_name = utils_net.get_linux_ifname(sessions[2], vm.get_mac_address()) tcpdump_cmd = tcpdump_cmd % (addresses[1], addresses[0], interface_name) t = utils.InterruptedThread( data_mon, (sessions[2], tcpdump_cmd, mon_process_timeout)) logging.info("Tcpdump mon start ...") logging.info("Creating %dMB file on guest1", filesize) sessions[0].cmd(dd_cmd % (src_file, filesize), timeout=timeout) t.start() error.context("Transferring file guest1 -> guest2", logging.info) remote.scp_between_remotes(addresses[0], addresses[1], shell_port, password, password, username, username, src_file, dst_file) error.context("Check the src and dst file is same", logging.info) src_md5 = sessions[0].cmd_output(md5_check % src_file).split()[0] dst_md5 = sessions[1].cmd_output(md5_check % dst_file).split()[0]
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)
if os_type == "linux": session.cmd(install_cmd % (guest_path, iperf_version)) muliticast_addr = params.get("muliticast_addr", "225.0.0.3") multicast_port = params.get("multicast_port", "5001") step_msg = "Start iperf server, bind host to multicast address %s " error.context(step_msg % muliticast_addr, logging.info) server_start_cmd = ("iperf -s -u -B %s -p %s " % (muliticast_addr, multicast_port)) default_flag = "%s port %s connected with %s" connected_flag = params.get("connected_flag", default_flag) catch_data = connected_flag % (muliticast_addr, multicast_port, client_ip) t = utils.InterruptedThread(server_start, (server_start_cmd, catch_data)) t.start() if not utils.process_is_alive("iperf"): raise error.TestError("Start iperf server failed cmd: %s" % server_start_cmd) logging.info("Server start successfully") step_msg = "In client try to connect server and transfer file " step_msg += " through multicast address %s" error.context(step_msg % muliticast_addr, logging.info) if os_type == "linux": client_cmd = "iperf" else: client_cmd = guest_path start_cmd = params.get("start_client_cmd", "%s -c %s -u -p %s") start_client_cmd = start_cmd % (client_cmd, muliticast_addr,
def run_vmstop(test, params, env): """ KVM guest stop test: 1) Log into a guest 2) Copy a file into guest 3) Stop guest 4) Check the status through monitor 5) Check the session 6) Migrat the vm to a file twice and compare them. :param test: kvm test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ vm = env.get_vm(params["main_vm"]) vm.verify_alive() timeout = float(params.get("login_timeout", 240)) session = vm.wait_for_login(timeout=timeout) save_path = params.get("save_path", "/tmp") clean_save = params.get("clean_save") == "yes" save1 = os.path.join(save_path, "save1") save2 = os.path.join(save_path, "save2") guest_path = params.get("guest_path", "/tmp") file_size = params.get("file_size", "1000") try: utils.run("dd if=/dev/zero of=/tmp/file bs=1M count=%s" % file_size) # Transfer file from host to guest, we didn't expect the finish of # transfer, we just let it to be a kind of stress in guest. bg = utils.InterruptedThread(vm.copy_files_to, ("/tmp/file", guest_path), dict(verbose=True, timeout=60)) logging.info("Start the background transfer") bg.start() try: # wait for the transfer start time.sleep(5) logging.info("Stop the VM") vm.pause() # check with monitor logging.info("Check the status through monitor") if not vm.monitor.verify_status("paused"): status = str(vm.monitor.info("status")) raise error.TestFail("Guest did not pause after sending stop," " guest status is %s" % status) # check through session logging.info("Check the session") if session.is_responsive(): raise error.TestFail("Session still alive after sending stop") # Check with the migration file logging.info("Save and check the state files") for p in [save1, save2]: vm.save_to_file(p) time.sleep(1) if not os.path.isfile(p): raise error.TestFail("VM failed to save state file %s" % p) # Fail if we see deltas md5_save1 = utils.hash_file(save1) md5_save2 = utils.hash_file(save2) if md5_save1 != md5_save2: raise error.TestFail("The produced state files differ") finally: bg.join(suppress_exception=True) finally: session.close() if clean_save: logging.debug("Clean the state files") if os.path.isfile(save1): os.remove(save1) if os.path.isfile(save2): os.remove(save2) vm.resume()