def run(test, params, env): """ Test blkdevio tuning Positive test has covered the following combination. ------------------------- | total | read | write | ------------------------- | 0 | 0 | 0 | | non-0 | 0 | 0 | | 0 | non-0 | non-0 | | 0 | non-0 | 0 | | 0 | 0 | non-0 | ------------------------- Negative test has covered unsupported combination and invalid command arguments. NB: only qemu-kvm-rhev supports block I/O throttling on >= RHEL6.5, the qemu-kvm is okay for block I/O throttling on >= RHEL7.0. """ # Run test case vm_name = params.get("main_vm") vm = env.get_vm(vm_name) start_vm = params.get("start_vm", "yes") change_parameters = params.get("change_parameters", "no") original_vm_xml = libvirt_xml.VMXML.new_from_inactive_dumpxml(vm_name) # Used for default device of blkdeviotune device = params.get("blkdevio_device", "vmblk") sys_image_target = vm.get_first_disk_devices()["target"] # Make sure vm is down if start not requested if start_vm == "no" and vm and vm.is_alive(): vm.destroy() # Recover previous running guest if vm and not vm.is_alive() and start_vm == "yes": vm.start() test_dict = dict(params) test_dict['vm'] = vm if device == "vmblk": test_dict['blkdevio_device'] = sys_image_target # Make sure libvirtd service is running if not utils_libvirtd.libvirtd_is_running(): raise error.TestNAError("libvirt service is not running!") ########## positive and negative testing ######### try: if change_parameters == "no": get_blkdevio_parameter(test_dict) else: set_blkdevio_parameter(test_dict) finally: # Restore guest original_vm_xml.sync()
def run(test, params, env): """ Test blkdevio tuning Positive test has covered the following combination. ------------------------- | total | read | write | ------------------------- | 0 | 0 | 0 | | non-0 | 0 | 0 | | 0 | non-0 | non-0 | | 0 | non-0 | 0 | | 0 | 0 | non-0 | ------------------------- Negative test has covered unsupported combination and invalid command arguments. NB: only qemu-kvm-rhev supports block I/O throttling on >= RHEL6.5, the qemu-kvm is okay for block I/O throttling on >= RHEL7.0. """ # Run test case vm_name = params.get("main_vm") vm = env.get_vm(vm_name) start_vm = params.get("start_vm", "yes") change_parameters = params.get("change_parameters", "no") original_vm_xml = libvirt_xml.VMXML.new_from_inactive_dumpxml(vm_name) # Used for default device of blkdeviotune device = params.get("blkdevio_device", "vmblk") sys_image_target = vm.get_first_disk_devices()["target"] # Make sure vm is down if start not requested if start_vm == "no" and vm and vm.is_alive(): vm.destroy() # Recover previous running guest if vm and not vm.is_alive() and start_vm == "yes": vm.start() test_dict = dict(params) test_dict['vm'] = vm if device == "vmblk": test_dict['blkdevio_device'] = sys_image_target # Make sure libvirtd service is running if not utils_libvirtd.libvirtd_is_running(): raise error.TestNAError("libvirt service is not running!") # Positive and negative testing try: if change_parameters == "no": get_blkdevio_parameter(test_dict) else: set_blkdevio_parameter(test_dict) finally: # Restore guest original_vm_xml.sync()
def check_libvirtd_process_id(ori_pid_libvirtd, test): """ Check libvirtd process id not change :param params: original libvirtd process id :param test: test assert object """ if not utils_split_daemons.is_modular_daemon(): aft_pid_libvirtd = process.getoutput("pidof libvirtd") if not utils_libvirtd.libvirtd_is_running() or ori_pid_libvirtd != aft_pid_libvirtd: test.fail("Libvirtd crash after attaching ccw addr devices")
options1 = "--wait --raw --finish --verbose" cmd_result = virsh.blockcopy(vm_name, target, dest_path, options1, ignore_status=True, debug=True) status = cmd_result.exit_status if status != 0: raise error.TestFail("Run blockcopy command fail.") elif not os.path.exists(dest_path): raise error.TestFail("Cannot find the created copy.") cmd_result = virsh.blockcopy(vm_name, target, dest_path, options, ignore_status=True, debug=True) status = cmd_result.exit_status except Exception, detail: logging.error(detail) if not utils_libvirtd.libvirtd_is_running(): raise error.TestFail("Libvirtd service is dead.") # Check_result try: try: if not status_error: if status == 0: check_xml(vm_name, target, dest_path, options) if options.count("--bandwidth"): utl.check_blockjob(vm_name, target, "bandwidth", bandwidth) if options.count("--pivot") + options.count("--finish") == 0: finish_job(vm_name, target, default_timeout) if options.count("--raw"): check_format(dest_path, "raw") else: raise error.TestFail(cmd_result.stderr)
def run(test, params, env): """ Test command: virsh dump. This command can dump the core of a domain to a file for analysis. 1. Positive testing 1.1 Dump domain with valid options. 1.2 Avoid file system cache when dumping. 1.3 Compress the dump images to valid/invalid formats. 2. Negative testing 2.1 Dump domain to a non-exist directory. 2.2 Dump domain with invalid option. 2.3 Dump a shut-off domain. """ vm_name = params.get("main_vm", "vm1") vm = env.get_vm(vm_name) options = params.get("dump_options") dump_file = params.get("dump_file", "vm.core") if os.path.dirname(dump_file) is "": dump_file = os.path.join(test.tmpdir, dump_file) dump_image_format = params.get("dump_image_format") start_vm = params.get("start_vm") == "yes" paused_after_start_vm = params.get("paused_after_start_vm") == "yes" status_error = params.get("status_error", "no") == "yes" timeout = int(params.get("timeout", "5")) qemu_conf = "/etc/libvirt/qemu.conf" def check_domstate(actual, options): """ Check the domain status according to dump options. """ if options.find('live') >= 0: domstate = "running" if options.find('crash') >= 0 or options.find('reset') > 0: domstate = "running" if paused_after_start_vm: domstate = "paused" elif options.find('crash') >= 0: domstate = "shut off" if options.find('reset') >= 0: domstate = "running" elif options.find('reset') >= 0: domstate = "running" if paused_after_start_vm: domstate = "paused" else: domstate = "running" if paused_after_start_vm: domstate = "paused" if not start_vm: domstate = "shut off" logging.debug("Domain should %s after run dump %s", domstate, options) return (domstate == actual) def check_dump_format(dump_image_format, dump_file): """ Check the format of dumped file. If 'dump_image_format' is not specified or invalid in qemu.conf, then the file shoule be normal raw file, otherwise it shoud be compress to specified format, the supported compress format including: lzop, gzip, bzip2, and xz. """ valid_format = ["lzop", "gzip", "bzip2", "xz"] if len(dump_image_format) == 0 or dump_image_format not in valid_format: logging.debug("No need check the dumped file format") return True else: file_cmd = "file %s" % dump_file (status, output) = commands.getstatusoutput(file_cmd) if status: logging.error("Fail to check dumped file %s", dump_file) return False logging.debug("Run file %s output: %s", dump_file, output) actual_format = output.split(" ")[1] if actual_format.lower() != dump_image_format.lower(): logging.error("Compress dumped file to %s fail: %s" % (dump_image_format, actual_format)) return False else: return True # Configure dump_image_format in /etc/libvirt/qemu.conf. if len(dump_image_format): conf_cmd = ("echo dump_image_format = \\\"%s\\\" >> %s" % (dump_image_format, qemu_conf)) if os.system(conf_cmd): logging.error("Config dump_image_format to %s fail", dump_image_format) utils_libvirtd.libvirtd_restart() if not utils_libvirtd.libvirtd_is_running(): raise error.TestNAError("libvirt service is not running!") # Deal with bypass-cache option child_pid = 0 if options.find('bypass-cache') >= 0: pid = os.fork() if pid: # Guarantee check_bypass function has run before dump child_pid = pid try: wait_pid_active(pid, timeout) finally: os.kill(child_pid, signal.SIGUSR1) else: check_bypass(dump_file) # Wait for parent process over while True: time.sleep(1) # Run virsh command cmd_result = virsh.dump(vm_name, dump_file, options, ignore_status=True, debug=True) status = cmd_result.exit_status try: logging.info("Start check result") if not check_domstate(vm.state(), options): raise error.TestFail("Domain status check fail.") if status_error: if not status: raise error.TestFail("Expect fail, but run successfully") else: if status: raise error.TestFail("Expect succeed, but run fail") if not os.path.exists(dump_file): raise error.TestFail("Fail to find domain dumped file.") if check_dump_format(dump_image_format, dump_file): logging.info("Successfully dump domain to %s", dump_file) else: raise error.TestFail("The format of dumped file is wrong.") finally: if child_pid: os.kill(child_pid, signal.SIGUSR1) if os.path.isfile(dump_file): os.remove(dump_file) if len(dump_image_format): clean_qemu_conf = "sed -i '$d' %s " % qemu_conf if os.system(clean_qemu_conf): raise error.TestFail("Fail to recover %s", qemu_conf)
if status != 0: raise error.TestFail("Run blockcopy command fail.") elif not os.path.exists(dest_path): raise error.TestFail("Cannot find the created copy.") cmd_result = virsh.blockcopy(vm_name, target, dest_path, options, ignore_status=True, debug=True) status = cmd_result.exit_status except Exception, detail: logging.error(detail) if not utils_libvirtd.libvirtd_is_running(): raise error.TestFail("Libvirtd service is dead.") # Check_result try: try: if not status_error: if status == 0: check_xml(vm_name, target, dest_path, options) if options.count("--bandwidth"): utl.check_blockjob(vm_name, target, "bandwidth", bandwidth) if options.count("--pivot") + options.count( "--finish") == 0: finish_job(vm_name, target, default_timeout) if options.count("--raw"): check_format(dest_path, dest_extension, dest_format)
def run(test, params, env): """ Test command: virsh blockjob. This command can manage active block operations. 1. Positive testing 1.1 Query active block job for the specified disk. 1.2 Manager the active block job(cancle/pivot). 1.3 Adjust speed for the active block job. 2. Negative testing 2.1 Query active block job for a invalid disk. 2.2 Invalid bandwith test. 2.3 No active block job management. """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) options = params.get("blockjob_options", "") bandwidth = params.get("blockjob_bandwidth", "") no_blockjob = "yes" == params.get("no_blockjob", "no") invalid_disk = params.get("invalid_disk") persistent_vm = "yes" == params.get("persistent_vm", "no") status_error = "yes" == params.get("status_error", "no") target = get_disk(vm_name) if not target: raise error.TestFail("Require target disk to copy.") # Prepare transient/persistent vm original_xml = vm.backup_xml() if not persistent_vm and vm.is_persistent(): vm.undefine() elif persistent_vm and not vm.is_persistent(): vm.define(original_xml) #Create a block job, e.g.: blockcopy tmp_file = time.strftime("%Y-%m-%d-%H.%M.%S.img") dest_path = os.path.join(data_dir.get_tmp_dir(), tmp_file) if not no_blockjob: cmd_result = virsh.blockcopy(vm_name, target, dest_path, "", ignore_status=True, debug=True) status = cmd_result.exit_status if status != 0: raise error.TestError("Fail to create blockcopy job.") # This option need blockjcopy job finish first if options.count("--pivot"): #Set default blockcopy timeout to 300 sec timeout = 300 finish_job(vm_name, target, timeout) if len(bandwidth): options += "--bandwidth %s" % bandwidth if invalid_disk: target = invalid_disk # Run virsh blockjob command cmd_result = virsh.blockjob(vm_name, target, options, ignore_status=True, debug=True) err = cmd_result.stderr.strip() status = cmd_result.exit_status # Check result if not utils_libvirtd.libvirtd_is_running(): raise error.TestFail("Libvirtd service is dead.") try: if not status_error: if status == 0: #'abort' option check if options.count("--abort"): utl.check_blockjob(vm_name, target, "no_job", 0) #'pivot' option check if options.count("--pivot"): if utl.check_blockjob(vm_name, target, "no_job", 0): check_disk(vm_name, dest_path) #'bandwidth' option check if options.count("--bandwidth"): utl.check_blockjob(vm_name, target, "bandwidth", bandwidth) else: raise error.TestFail(err) else: if status: logging.debug("Expect error: %s", err) else: raise error.TestFail("Expect fail, but run successfully.") #cleanup finally: try: if vm.exists(): vm.destroy() else: raise error.TestFail("Domain is disappeared.") finally: vm.define(original_xml) if os.path.exists(dest_path): os.remove(dest_path)
def run(test, params, env): """ Test numa tuning 1) Positive testing 1.1) get the current numa parameters for a running/shutoff guest 1.2) set the current numa parameters for a running/shutoff guest 1.2.1) set valid 'mode' parameters 1.2.2) set valid 'nodeset' parameters 2) Negative testing 2.1) get numa parameters 2.1.1) invalid options 2.1.2) stop cgroup service 2.2) set numa parameters 2.2.1) invalid 'mode' parameters 2.2.2) invalid 'nodeset' parameters 2.2.3) change 'mode' for a running guest and 'mode' is not 'strict' 2.2.4) change 'nodeset' for running guest with mode of 'interleave' 'interleave' or 'preferred' numa mode 2.2.5) stop cgroup service """ try: utils_misc.find_command("numactl") except ValueError: raise error.TestNAError("Command 'numactl' is missing. You must " "install it.") # Run test case #vm_name = params.get("vms") vm_name = params.get("main_vm") vm = env.get_vm(vm_name) original_vm_xml = libvirt_xml.VMXML.new_from_inactive_dumpxml(vm_name) cg = utils_cgroup.CgconfigService() status_error = params.get("status_error", "no") libvirtd = params.get("libvirtd", "on") cgconfig = params.get("cgconfig", "on") start_vm = params.get("start_vm", "no") change_parameters = params.get("change_parameters", "no") # Make sure vm is down if start not requested if start_vm == "no" and vm.is_alive(): vm.destroy() # positive and negative testing ######### cgstop = False try: if status_error == "no": if change_parameters == "no": get_numa_parameter(params, cgstop) else: set_numa_parameter(params, cgstop) if cgconfig == "off": # If running, then need to shutdown a running guest before # stopping cgconfig service and will start the guest after # restarting libvirtd service if cg.cgconfig_is_running(): if vm.is_alive(): vm.destroy() cg.cgconfig_stop() cgstop = True # If we stopped cg, then refresh libvirtd service # to get latest cgconfig service change; otherwise, # if no cg change restart of libvirtd is pointless if cgstop and libvirtd == "restart": try: utils_libvirtd.libvirtd_restart() finally: # Not running is not a good thing, but it does happen # and it will affect other tests if not utils_libvirtd.libvirtd_is_running(): raise error.TestNAError("libvirt service is not running!") # Recover previous running guest if (cgconfig == "off" and libvirtd == "restart" and not vm.is_alive() and start_vm == "yes"): vm.start() if status_error == "yes": if change_parameters == "no": get_numa_parameter(params, cgstop) else: set_numa_parameter(params, cgstop) finally: # Restore guest original_vm_xml.sync() # If we stopped cg, then recover and refresh libvirtd to recognize if cgstop: cg.cgconfig_start() utils_libvirtd.libvirtd_restart()
def run_virsh_setmem(test, params, env): """ Test command: virsh setmem. 1) Prepare vm environment. 2) Handle params 3) Prepare libvirtd status. 4) Run test command and wait for current memory's stable. 5) Recover environment. 4) Check result. TODO: support new libvirt with more options. """ def vm_proc_meminfo(session): proc_meminfo = session.cmd_output("cat /proc/meminfo") # verify format and units are expected return int(re.search(r'MemTotal:\s+(\d+)\s+kB', proc_meminfo).group(1)) def make_domref(domarg, vm_ref, domid, vm_name, domuuid): # Specify domain as argument or parameter if domarg == "yes": dom_darg_key = "domainarg" else: dom_darg_key = "domain" # How to reference domain if vm_ref == "domid": dom_darg_value = domid elif vm_ref == "domname": dom_darg_value = vm_name elif vm_ref == "domuuid": dom_darg_value = domuuid elif vm_ref == "none": dom_darg_value = None elif vm_ref == "emptystring": dom_darg_value = '""' else: # stick in value directly dom_darg_value = vm_ref return {dom_darg_key: dom_darg_value} def make_sizeref(sizearg, mem_ref, original_mem): if sizearg == "yes": size_darg_key = "sizearg" else: size_darg_key = "size" if mem_ref == "halfless": size_darg_value = "%d" % (original_mem / 2) elif mem_ref == "halfmore": size_darg_value = "%d" % int(original_mem * 1.5) # no fraction elif mem_ref == "same": size_darg_value = "%d" % original_mem elif mem_ref == "emptystring": size_darg_value = '""' elif mem_ref == "zero": size_darg_value = "0" elif mem_ref == "toosmall": size_darg_value = "1024" elif mem_ref == "toobig": size_darg_value = "1099511627776" # (KiB) One Petabyte elif mem_ref == "none": size_darg_value = None else: # stick in value directly size_darg_value = mem_ref return {size_darg_key: size_darg_value} def is_in_range(actual, expected, error_percent): deviation = 100 - (100 * (float(actual) / float(expected))) logging.debug("Deviation: %0.2f%%" % float(deviation)) return float(deviation) <= float(error_percent) def is_old_libvirt(): regex = r'\s+\[--size\]\s+' return bool(not virsh.has_command_help_match('setmem', regex)) def print_debug_stats(original_inside_mem, original_outside_mem, test_inside_mem, test_outside_mem, expected_mem, delta_percentage): dbgmsg = ("Original inside mem : %d KiB\n" "Expected inside mem : %d KiB\n" "Actual inside mem : %d KiB\n" "Inside mem deviation : %0.2f%%\n" "Original outside mem : %d KiB\n" "Expected outside mem : %d KiB\n" "Actual outside mem : %d KiB\n" "Outside mem deviation: %0.2f%%\n" "Acceptable deviation %0.2f%%" % ( original_inside_mem, expected_mem, test_inside_mem, 100 - (100 * (float(test_inside_mem) / float(expected_mem))), original_outside_mem, expected_mem, test_outside_mem, 100 - (100 * (float(test_outside_mem) / float(expected_mem))), float(delta_percentage))) for dbgline in dbgmsg.splitlines(): logging.debug(dbgline) # MAIN TEST CODE ### # Process cartesian parameters vm_ref = params.get("setmem_vm_ref", "") mem_ref = params.get("setmem_mem_ref", "") flags = params.get("setmem_flags", "") status_error = params.get("status_error", "no") old_libvirt_fail = params.get("setmem_old_libvirt_fail", "no") quiesce_delay = int(params.get("setmem_quiesce_delay", "1")) domarg = params.get("setmem_domarg", "no") sizearg = params.get("setmem_sizearg", "no") libvirt = params.get("libvirt", "on") delta_percentage = float(params.get("setmem_delta_per", "10")) start_vm = params.get("start_vm", "yes") vm_name = params.get("main_vm") paused_after_start_vm = "yes" == params.get("paused_after_start_vm", "no") # Gather environment parameters vm = env.get_vm(params["main_vm"]) if start_vm == "yes": if paused_after_start_vm: vm.resume() session = vm.wait_for_login() original_inside_mem = vm_proc_meminfo(session) session.close() if paused_after_start_vm: vm.pause() else: session = None # Retrieve known mem value, convert into kilobytes original_inside_mem = int(params.get("mem", "1024")) * 1024 original_outside_mem = vm.get_used_mem() domid = vm.get_id() domuuid = vm.get_uuid() uri = vm.connect_uri old_libvirt = is_old_libvirt() if old_libvirt: logging.info("Running test on older libvirt") use_kilobytes = True else: logging.info("Running test on newer libvirt") use_kilobytes = False # Argument pattern is complex, build with dargs dargs = {'flagstr': flags, 'use_kilobytes': use_kilobytes, 'uri': uri, 'ignore_status': True, "debug": True} dargs.update(make_domref(domarg, vm_ref, domid, vm_name, domuuid)) dargs.update(make_sizeref(sizearg, mem_ref, original_outside_mem)) # Prepare libvirtd status if libvirt == "off": utils_libvirtd.libvirtd_stop() else: if not utils_libvirtd.libvirtd_is_running() and \ not utils_libvirtd.libvirtd_start(): raise error.TestFail("Cannot start libvirtd") if status_error == "yes" or old_libvirt_fail == "yes": logging.info("Error Test: Expecting an error to occur!") result = virsh.setmem(**dargs) status = result.exit_status # Recover libvirtd status if libvirt == "off": utils_libvirtd.libvirtd_start() if status is 0: logging.info( "Waiting %d seconds for VM memory to settle", quiesce_delay) # It takes time for kernel to settle on new memory # and current clean pages is not predictable. Therefor, # extremely difficult to determine quiescence, so # sleep one second per error percent is reasonable option. time.sleep(quiesce_delay) # Gather stats if not running error test if status_error == "no" and old_libvirt_fail == "no": if vm.state() == "shut off": vm.start() # Make sure it's never paused vm.resume() session = vm.wait_for_login() # Actual results test_inside_mem = vm_proc_meminfo(session) session.close() test_outside_mem = vm.get_used_mem() # Expected results for both inside and outside if sizearg == "yes": expected_mem = int(dargs["sizearg"]) else: expected_mem = int(dargs["size"]) print_debug_stats(original_inside_mem, original_outside_mem, test_inside_mem, test_outside_mem, expected_mem, delta_percentage) if status is 0: # Restore original memory restore_status = virsh.setmem(domainarg=vm_name, sizearg=original_outside_mem, ignore_status=True).exit_status if restore_status is not 0: logging.warning("Failed to restore VM's original memory to %s KiB" % original_outside_mem) else: # virsh setmem failed, no need to restore pass # Don't care about memory comparison on error test if status_error == "no" and old_libvirt_fail == "no": outside_in_range = is_in_range(test_outside_mem, expected_mem, delta_percentage) inside_in_range = is_in_range(test_inside_mem, expected_mem, delta_percentage) if status is not 0 or not outside_in_range or not inside_in_range: msg = "test conditions not met: " if status is not 0: msg += "Non-zero virsh setmem exit code. " # maybe multiple if not outside_in_range: # errors msg += "Outside memory deviated. " if not inside_in_range: msg += "Inside memory deviated. " raise error.TestFail(msg) return # Normal test passed elif status_error == "no" and old_libvirt_fail == "yes": if status is 0: if old_libvirt: raise error.TestFail("Error test did not result in an error") else: if not old_libvirt: raise error.TestFail("Newer libvirt failed when it should not") else: # Verify an error test resulted in error if status is 0: raise error.TestFail("Error test did not result in an error")
def run_virsh_dump(test, params, env): """ Test command: virsh dump. This command can dump the core of a domain to a file for analysis. 1. Positive testing 1.1 Dump domain with valid options. 1.2 Avoid file system cache when dumping. 1.3 Compress the dump images to valid/invalid formats. 2. Negative testing 2.1 Dump domain to a non-exist directory. 2.2 Dump domain with invalid option. 2.3 Dump a shut-off domain. """ vm_name = params.get("main_vm", "vm1") vm = env.get_vm(params["main_vm"]) options = params.get("dump_options") dump_file = params.get("dump_file", "vm.core") if os.path.dirname(dump_file) is "": dump_file = os.path.join(test.tmpdir, dump_file) dump_image_format = params.get("dump_image_format") start_vm = params.get("start_vm") status_error = params.get("status_error", "no") qemu_conf = "/etc/libvirt/qemu.conf" # prepare the vm state if vm.is_alive() and start_vm == "no": vm.destroy() if vm.is_dead() and start_vm == "yes": vm.start() def check_domstate(actual, options): """ Check the domain status according to dump options. """ if options.find('live') >= 0: domstate = "running" if options.find('crash') >= 0 or options.find('reset') > 0: domstate = "running" elif options.find('crash') >= 0: domstate = "shut off" if options.find('reset') >= 0: domstate = "running" elif options.find('reset') >= 0: domstate = "running" else: domstate = "running" if start_vm == "no": domstate = "shut off" logging.debug("Domain should %s after run dump %s", domstate, options) if domstate == actual: return True else: return False def check_dump_format(dump_image_format, dump_file): """ Check the format of dumped file. If 'dump_image_format' is not specified or invalid in qemu.conf, then the file shoule be normal raw file, otherwise it shoud be compress to specified format, the supported compress format including: lzop, gzip, bzip2, and xz. """ valid_format = ["lzop", "gzip", "bzip2", "xz"] if len(dump_image_format ) == 0 or dump_image_format not in valid_format: logging.debug("No need check the dumped file format") return True else: file_cmd = "file %s" % dump_file (status, output) = commands.getstatusoutput(file_cmd) if status == 0: logging.debug("Run file %s output: %s", dump_file, output) actual_format = output.split(" ")[1] if actual_format == dump_image_format: if dump_image_format in valid_format: logging.info("Compress dumped file to %s successfully", dump_image_format) return True else: logging.error("Compress dumped file to %s fail", dump_image_format) return False else: logging.error("Fail to check dumped file %s", dump_file) return False # Configure dump_image_format in /etc/libvirt/qemu.conf. if len(dump_image_format) != 0: conf_cmd = ("echo dump_image_format = \\\"%s\\\" >> %s" % (dump_image_format, qemu_conf)) if os.system(conf_cmd): logging.error("Config dump_image_format to %s fail", dump_image_format) utils_libvirtd.libvirtd_restart() # Deal with bypass-cache option if options.find('bypass-cache') >= 0: thread.start_new_thread(check_bypass, (dump_file, )) # Guarantee check_bypass function has run before dump time.sleep(5) # Run virsh command cmd_result = virsh.dump(vm_name, dump_file, options, ignore_status=True, debug=True) status = cmd_result.exit_status # Check libvirtd status if utils_libvirtd.libvirtd_is_running(): if check_domstate(vm.state(), options): if status_error == "yes": if status == 0: raise error.TestFail("Expect fail, but run successfully") if status_error == "no": if status != 0: raise error.TestFail("Expect succeed, but run fail") else: if os.path.exists(dump_file): if check_dump_format(dump_image_format, dump_file): logging.info("Successfully dump domain to %s", dump_file) else: raise error.TestFail("The format of dumped file " "is wrong.") else: raise error.TestFail( "Fail to find domain dumped file.") else: raise error.TestFail("Domain status check fail.") else: raise error.TestFail("Libvirtd service is dead.") if os.path.isfile(dump_file): os.remove(dump_file) if len(dump_image_format) != 0: clean_qemu_conf = "sed -i '$d' %s " % qemu_conf if os.system(clean_qemu_conf): raise error.TestFail("Fail to recover %s", qemu_conf)
def run(test, params, env): """ Test command: virsh nodedev-reset <device> When `device_option` is: 1) resettable : Reset specified device if it is resettable. 2) non-exist : Try to reset specified device which doesn't exist. 3) non-pci : Try to reset all local non-PCI devices. 4) active : Try to reset specified device which is attached to VM. 5) unresettable : Try to reset all unresettable PCI devices. """ # Retrive parameters expect_succeed = params.get('expect_succeed', 'yes') device_option = params.get('device_option', 'valid') unspecified = 'REPLACE_WITH_TEST_DEVICE' specified_device = params.get('specified_device', unspecified) # Backup original libvirtd status and prepare libvirtd status logging.debug('Preparing libvirtd') libvirtd = params.get("libvirtd", "on") libvirtd_status = utils_libvirtd.libvirtd_is_running() if libvirtd == "off" and libvirtd_status: utils_libvirtd.libvirtd_stop() elif libvirtd == "on" and not libvirtd_status: utils_libvirtd.libvirtd_start() # Get whether PCI devices are resettable from sysfs. devices = get_pci_info() # Devide PCI devices into to catagories. resettable_nodes = [] unresettable_nodes = [] for device in devices: info = devices[device] if info['reset'] and info['driver']: resettable_nodes.append(device) else: unresettable_nodes.append(device) # Find out all non-PCI devices. all_devices = virsh.nodedev_list().stdout.strip().splitlines() non_pci_nodes = [] for device in all_devices: if device not in devices: non_pci_nodes.append(device) try: if device_option == 'resettable': # Test specified resettable device. if specified_device != unspecified: if specified_device in resettable_nodes: test_nodedev_reset([specified_device], expect_succeed) else: raise error.TestNAError( 'Param specified_device is not set!') else: raise error.TestNAError('Param specified_device is not set!') elif device_option == 'non-exist': # Test specified non-exist device. if specified_device != unspecified: if specified_device not in all_devices: test_nodedev_reset([specified_device], expect_succeed) else: raise error.TestError('Specified device exists!') else: raise error.TestNAError('Param specified_device is not set!') elif device_option == 'non-pci': # Test all non-PCI device. if non_pci_nodes: test_nodedev_reset(non_pci_nodes, expect_succeed) else: raise error.TestNAError('No non-PCI device found!') elif device_option == 'active': # Test specified device if attached to VM. if specified_device != unspecified: vm_name = params.get('main_vm', 'virt-tests-vm1') vm = env.get_vm(vm_name) test_active_nodedev_reset(specified_device, vm, expect_succeed) else: raise error.TestNAError('Param specified_device is not set!') elif device_option == 'unresettable': # Test all unresettable device. if unresettable_nodes: test_nodedev_reset(unresettable_nodes, expect_succeed) else: raise error.TestNAError('No unresettable device found!') else: raise error.TestError('Unrecognisable device option %s!' % device_option) finally: # Restore libvirtd status logging.debug('Restoring libvirtd') current_libvirtd_status = utils_libvirtd.libvirtd_is_running() if current_libvirtd_status and not libvirtd_status: utils_libvirtd.libvirtd_stop() elif not current_libvirtd_status and libvirtd_status: utils_libvirtd.libvirtd_start()
def run(test, params, env): """ Test blkio tuning 1) Positive testing 1.1) get the current blkio parameters for a running/shutoff guest 1.2) set the current blkio parameters for a running/shutoff guest 2) Negative testing 2.1) get blkio parameters for a running/shutoff guest 2.2) set blkio parameters running/shutoff guest """ # Run test case vm_name = params.get("main_vm") vm = env.get_vm(vm_name) cg = utils_cgroup.CgconfigService() cgconfig = params.get("cgconfig", "on") libvirtd = params.get("libvirtd", "on") start_vm = params.get("start_vm", "yes") status_error = params.get("status_error", "no") change_parameters = params.get("change_parameters", "no") original_vm_xml = libvirt_xml.VMXML.new_from_inactive_dumpxml(vm_name) # Make sure vm is down if start not requested if start_vm == "no" and vm and vm.is_alive(): vm.destroy() test_dict = prepare_scheduler(params, test, vm) # positive and negative testing cgstop = False try: if start_vm == "yes" and not vm.is_alive(): vm.start() vm.wait_for_login() if status_error == "no": if change_parameters == "no": get_blkio_parameter(test, test_dict, cgstop) else: set_blkio_parameter(test, test_dict, cgstop) if cgconfig == "off": # If running, then need to shutdown a running guest before # stopping cgconfig service and will start the guest after # restarting libvirtd service if cg.cgconfig_is_running(): if vm.is_alive(): vm.destroy() cg.cgconfig_stop() cgstop = True # If we stopped cg, then refresh libvirtd service # to get latest cgconfig service change; otherwise, # if no cg change restart of libvirtd is pointless if cgstop and libvirtd == "restart": try: utils_libvirtd.libvirtd_restart() finally: # Not running is not a good thing, but it does happen # and it will affect other tests if not utils_libvirtd.libvirtd_is_running(): test.fail("libvirt service is not running!") # Recover previous running guest if (cgconfig == "off" and libvirtd == "restart" and not vm.is_alive() and start_vm == "yes"): vm.start() if status_error == "yes": if change_parameters == "no": get_blkio_parameter(test, test_dict, cgstop) else: set_blkio_parameter(test, test_dict, cgstop) finally: # Restore guest original_vm_xml.sync() with open(schedulerfd, 'w') as scf: scf.write(test_dict['oldmode']) # If we stopped cg, then recover and refresh libvirtd to recognize if cgstop: cg.cgconfig_start() utils_libvirtd.libvirtd_restart()
def run(test, params, env): """ Test blkio tuning 1) Positive testing 1.1) get the current blkio parameters for a running/shutoff guest 1.2) set the current blkio parameters for a running/shutoff guest 2) Negative testing 2.1) get blkio parameters for a running/shutoff guest 2.2) set blkio parameters running/shutoff guest """ # Run test case vm_name = params.get("main_vm") vm = env.get_vm(vm_name) cg = utils_cgroup.CgconfigService() cgconfig = params.get("cgconfig", "on") libvirtd = params.get("libvirtd", "on") start_vm = params.get("start_vm", "yes") status_error = params.get("status_error", "no") change_parameters = params.get("change_parameters", "no") original_vm_xml = libvirt_xml.VMXML.new_from_inactive_dumpxml(vm_name) # Make sure vm is down if start not requested if start_vm == "no" and vm and vm.is_alive(): vm.destroy() cmd = "cat /sys/block/sda/queue/scheduler" iosche = results_stdout_52lts(process.run(cmd, shell=True)) logging.debug("iosche value is:%s", iosche) oldmode = re.findall("\[(.*?)\]", iosche)[0] with open('/sys/block/sda/queue/scheduler', 'w') as scf: if 'cfq' in iosche: scf.write('cfq') elif 'bfq' in iosche: scf.write('bfq') else: test.fail('Unknown scheduler in "/sys/block/sda/queue/scheduler"') test_dict = dict(params) test_dict['vm'] = vm # positive and negative testing cgstop = False try: if start_vm == "yes" and not vm.is_alive(): vm.start() vm.wait_for_login() if status_error == "no": if change_parameters == "no": get_blkio_parameter(test, test_dict, cgstop) else: set_blkio_parameter(test, test_dict, cgstop) if cgconfig == "off": # If running, then need to shutdown a running guest before # stopping cgconfig service and will start the guest after # restarting libvirtd service if cg.cgconfig_is_running(): if vm.is_alive(): vm.destroy() cg.cgconfig_stop() cgstop = True # If we stopped cg, then refresh libvirtd service # to get latest cgconfig service change; otherwise, # if no cg change restart of libvirtd is pointless if cgstop and libvirtd == "restart": try: utils_libvirtd.libvirtd_restart() finally: # Not running is not a good thing, but it does happen # and it will affect other tests if not utils_libvirtd.libvirtd_is_running(): test.fail("libvirt service is not running!") # Recover previous running guest if (cgconfig == "off" and libvirtd == "restart" and not vm.is_alive() and start_vm == "yes"): vm.start() if status_error == "yes": if change_parameters == "no": get_blkio_parameter(test, test_dict, cgstop) else: set_blkio_parameter(test, test_dict, cgstop) finally: # Restore guest original_vm_xml.sync() with open('/sys/block/sda/queue/scheduler', 'w') as scf: scf.write(oldmode) # If we stopped cg, then recover and refresh libvirtd to recognize if cgstop: cg.cgconfig_start() utils_libvirtd.libvirtd_restart()
def run(test, params, env): """ Test command: virsh blockjob. This command can manage active block operations. 1. Positive testing 1.1 Query active block job for the specified disk. 1.2 Manager the active block job(cancle/pivot). 1.3 Adjust speed for the active block job. 2. Negative testing 2.1 Query active block job for a invalid disk. 2.2 Invalid bandwith test. 2.3 No active block job management. """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) options = params.get("blockjob_options", "") bandwidth = params.get("blockjob_bandwidth", "") no_blockjob = "yes" == params.get("no_blockjob", "no") invalid_disk = params.get("invalid_disk") persistent_vm = "yes" == params.get("persistent_vm", "no") status_error = "yes" == params.get("status_error", "no") target = get_disk(vm_name, test) if not target: test.fail("Require target disk to copy.") # Prepare transient/persistent vm original_xml = vm.backup_xml() if not persistent_vm and vm.is_persistent(): vm.undefine("--nvram") elif persistent_vm and not vm.is_persistent(): vm.define(original_xml) #Create a block job, e.g.: blockcopy tmp_file = time.strftime("%Y-%m-%d-%H.%M.%S.img") dest_path = os.path.join(data_dir.get_tmp_dir(), tmp_file) if not no_blockjob: cmd_result = virsh.blockcopy(vm_name, target, dest_path, "", ignore_status=True, debug=True) status = cmd_result.exit_status if status != 0: test.error("Fail to create blockcopy job.") # This option need blockjcopy job finish first if options.count("--pivot"): #Set default blockcopy timeout to 300 sec timeout = 300 finish_job(vm_name, target, timeout, test) if len(bandwidth): options += "--bandwidth %s" % bandwidth if invalid_disk: target = invalid_disk # Wait for few seconds to be more like human activity, # otherwise, unexpected failure may happen. time.sleep(3) # Run virsh blockjob command cmd_result = virsh.blockjob(vm_name, target, options, ignore_status=True, debug=True) err = cmd_result.stderr.strip() status = cmd_result.exit_status # Check result if not utils_libvirtd.libvirtd_is_running(): test.fail("Libvirtd service is dead.") try: if not status_error: if status == 0: #'abort' option check if options.count("--abort"): utl.check_blockjob(vm_name, target, "no_job", 0) #'pivot' option check if options.count("--pivot"): if utl.check_blockjob(vm_name, target, "no_job", 0): check_disk(vm_name, dest_path, test) #'bandwidth' option check if options.count("--bandwidth"): utl.check_blockjob(vm_name, target, "bandwidth", bandwidth) else: test.fail(err) else: if status: logging.debug("Expect error: %s", err) else: test.fail("Expect fail, but run successfully.") #cleanup finally: try: if vm.exists(): vm.destroy() else: test.fail("Domain is disappeared.") finally: vm.define(original_xml) if os.path.exists(dest_path): os.remove(dest_path)
def run(test, params, env): """ Test command: virsh setmem. 1) Prepare vm environment. 2) Handle params 3) Prepare libvirtd status. 4) Run test command and wait for current memory's stable. 5) Recover environment. 4) Check result. """ def vm_proc_meminfo(session): """ Get guest total memory """ proc_meminfo = session.cmd_output("cat /proc/meminfo") # verify format and units are expected return int(re.search(r'MemTotal:\s+(\d+)\s+kB', proc_meminfo).group(1)) def make_domref(domarg, vm_ref, domid, vm_name, domuuid): """ Create domain options of command """ # Specify domain as argument or parameter if domarg == "yes": dom_darg_key = "domainarg" else: dom_darg_key = "domain" # How to reference domain if vm_ref == "domid": dom_darg_value = domid elif vm_ref == "domname": dom_darg_value = vm_name elif vm_ref == "domuuid": dom_darg_value = domuuid elif vm_ref == "none": dom_darg_value = None elif vm_ref == "emptystring": dom_darg_value = '""' else: # stick in value directly dom_darg_value = vm_ref return {dom_darg_key: dom_darg_value} def make_sizeref(sizearg, mem_ref, original_mem): """ Create size options of command """ if sizearg == "yes": size_darg_key = "sizearg" else: size_darg_key = "size" if mem_ref == "halfless": size_darg_value = "%d" % (original_mem / 2) elif mem_ref == "halfmore": size_darg_value = "%d" % int(original_mem * 1.5) # no fraction elif mem_ref == "same": size_darg_value = "%d" % original_mem elif mem_ref == "emptystring": size_darg_value = '""' elif mem_ref == "zero": size_darg_value = "0" elif mem_ref == "toosmall": size_darg_value = "1024" elif mem_ref == "toobig": size_darg_value = "1099511627776" # (KiB) One Petabyte elif mem_ref == "none": size_darg_value = None else: # stick in value directly size_darg_value = mem_ref return {size_darg_key: size_darg_value} def is_in_range(actual, expected, error_percent): """ Check if value in reasonable range """ deviation = 100 - (100 * (float(actual) / float(expected))) logging.debug("Deviation: %0.2f%%" % float(deviation)) return float(deviation) <= float(error_percent) def is_old_libvirt(): """ Check if libvirt is old version """ regex = r'\s+\[--size\]\s+' return bool(not virsh.has_command_help_match('setmem', regex)) def print_debug_stats(original_inside_mem, original_outside_mem, test_inside_mem, test_outside_mem, expected_mem, delta_percentage): """ Print debug message for test """ dbgmsg = ("Original inside mem : %d KiB\n" "Expected inside mem : %d KiB\n" "Actual inside mem : %d KiB\n" "Inside mem deviation : %0.2f%%\n" "Original outside mem : %d KiB\n" "Expected outside mem : %d KiB\n" "Actual outside mem : %d KiB\n" "Outside mem deviation: %0.2f%%\n" "Acceptable deviation %0.2f%%" % (original_inside_mem, expected_mem, test_inside_mem, 100 - (100 * (float(test_inside_mem) / float(expected_mem))), original_outside_mem, expected_mem, test_outside_mem, 100 - (100 * (float(test_outside_mem) / float(expected_mem))), float(delta_percentage))) for dbgline in dbgmsg.splitlines(): logging.debug(dbgline) # MAIN TEST CODE ### # Process cartesian parameters vm_ref = params.get("setmem_vm_ref", "") mem_ref = params.get("setmem_mem_ref", "") flags = params.get("setmem_flags", "") status_error = params.get("status_error", "no") old_libvirt_fail = params.get("setmem_old_libvirt_fail", "no") quiesce_delay = int(params.get("setmem_quiesce_delay", "1")) domarg = params.get("setmem_domarg", "no") sizearg = params.get("setmem_sizearg", "no") libvirt = params.get("libvirt", "on") delta_percentage = float(params.get("setmem_delta_per", "10")) start_vm = params.get("start_vm", "yes") vm_name = params.get("main_vm", "virt-tests-vm1") paused_after_start_vm = "yes" == params.get("paused_after_start_vm", "no") # Gather environment parameters vm = env.get_vm(vm_name) if start_vm == "yes": if paused_after_start_vm: vm.resume() session = vm.wait_for_login() original_inside_mem = vm_proc_meminfo(session) session.close() if paused_after_start_vm: vm.pause() else: # Retrieve known mem value, convert into kilobytes original_inside_mem = int(params.get("mem", "1024")) * 1024 original_outside_mem = vm.get_used_mem() domid = vm.get_id() domuuid = vm.get_uuid() uri = vm.connect_uri old_libvirt = is_old_libvirt() if old_libvirt: logging.info("Running test on older libvirt") use_kilobytes = True else: logging.info("Running test on newer libvirt") use_kilobytes = False # Argument pattern is complex, build with dargs dargs = { 'flagstr': flags, 'use_kilobytes': use_kilobytes, 'uri': uri, 'ignore_status': True, "debug": True } dargs.update(make_domref(domarg, vm_ref, domid, vm_name, domuuid)) dargs.update(make_sizeref(sizearg, mem_ref, original_outside_mem)) # Prepare libvirtd status if libvirt == "off": utils_libvirtd.libvirtd_stop() else: if not utils_libvirtd.libvirtd_is_running() and \ not utils_libvirtd.libvirtd_start(): raise error.TestFail("Cannot start libvirtd") if status_error == "yes" or old_libvirt_fail == "yes": logging.info("Error Test: Expecting an error to occur!") result = virsh.setmem(**dargs) status = result.exit_status # Recover libvirtd status if libvirt == "off": utils_libvirtd.libvirtd_start() if status is 0: logging.info("Waiting %d seconds for VM memory to settle", quiesce_delay) # It takes time for kernel to settle on new memory # and current clean pages is not predictable. Therefor, # extremely difficult to determine quiescence, so # sleep one second per error percent is reasonable option. time.sleep(quiesce_delay) # Gather stats if not running error test if status_error == "no" and old_libvirt_fail == "no": if start_vm == "yes": if vm.state() == "shut off": vm.start() # Make sure it's never paused vm.resume() session = vm.wait_for_login() # Actual results test_inside_mem = vm_proc_meminfo(session) session.close() else: test_inside_mem = original_inside_mem test_outside_mem = vm.get_used_mem() # Expected results for both inside and outside if sizearg == "yes": expected_mem = int(dargs["sizearg"]) else: expected_mem = int(dargs["size"]) print_debug_stats(original_inside_mem, original_outside_mem, test_inside_mem, test_outside_mem, expected_mem, delta_percentage) if status is 0: # Restore original memory restore_status = virsh.setmem(domainarg=vm_name, sizearg=original_outside_mem, ignore_status=True, flagstr=flags).exit_status if restore_status != 0: logging.warning( "Failed to restore VM's original memory to %s KiB" % original_outside_mem) else: # virsh setmem failed, no need to restore pass # Don't care about memory comparison on error test if status_error == "no" and old_libvirt_fail == "no": outside_in_range = is_in_range(test_outside_mem, expected_mem, delta_percentage) inside_in_range = is_in_range(test_inside_mem, expected_mem, delta_percentage) if status is not 0 or not outside_in_range or not inside_in_range: msg = "test conditions not met: " if status is not 0: msg += "Non-zero virsh setmem exit code. " # maybe multiple if not outside_in_range: # errors msg += "Outside memory deviated. " if not inside_in_range: msg += "Inside memory deviated. " raise error.TestFail(msg) return # Normal test passed elif status_error == "no" and old_libvirt_fail == "yes": if status is 0: if old_libvirt: raise error.TestFail("Error test did not result in an error") else: if not old_libvirt: raise error.TestFail("Newer libvirt failed when it should not") else: # Verify an error test resulted in error if status is 0: raise error.TestFail("Error test did not result in an error")
def run(test, params, env): """ Test command: virsh nodedev-reset <device> When `device_option` is: 1) resettable : Reset specified device if it is resettable. 2) non-exist : Try to reset specified device which doesn't exist. 3) non-pci : Try to reset all local non-PCI devices. 4) active : Try to reset specified device which is attached to VM. 5) unresettable : Try to reset all unresettable PCI devices. """ # Retrive parameters expect_succeed = params.get('expect_succeed', 'yes') device_option = params.get('device_option', 'valid') unspecified = 'REPLACE_WITH_TEST_DEVICE' specified_device = params.get('specified_device', unspecified) # Backup original libvirtd status and prepare libvirtd status logging.debug('Preparing libvirtd') libvirtd = params.get("libvirtd", "on") libvirtd_status = utils_libvirtd.libvirtd_is_running() if libvirtd == "off" and libvirtd_status: utils_libvirtd.libvirtd_stop() elif libvirtd == "on" and not libvirtd_status: utils_libvirtd.libvirtd_start() # Get whether PCI devices are resettable from sysfs. devices = get_pci_info() # Devide PCI devices into to catagories. resettable_nodes = [] unresettable_nodes = [] for device in devices: info = devices[device] if info['reset'] and info['driver']: resettable_nodes.append(device) else: unresettable_nodes.append(device) # Find out all non-PCI devices. all_devices = virsh.nodedev_list().stdout.strip().splitlines() non_pci_nodes = [] for device in all_devices: if device not in devices: non_pci_nodes.append(device) try: if device_option == 'resettable': # Test specified resettable device. if specified_device != unspecified: if specified_device in resettable_nodes: test_nodedev_reset([specified_device], expect_succeed) else: raise error.TestNAError( 'Param specified_device is not set!') else: raise error.TestNAError('Param specified_device is not set!') elif device_option == 'non-exist': # Test specified non-exist device. if specified_device != unspecified: if specified_device not in all_devices: test_nodedev_reset([specified_device], expect_succeed) else: raise error.TestError('Specified device exists!') else: raise error.TestNAError('Param specified_device is not set!') elif device_option == 'non-pci': # Test all non-PCI device. if non_pci_nodes: test_nodedev_reset(non_pci_nodes, expect_succeed) else: raise error.TestNAError('No non-PCI device found!') elif device_option == 'active': # Test specified device if attached to VM. if specified_device != unspecified: vm_name = params.get('main_vm', 'virt-tests-vm1') vm = env.get_vm(vm_name) test_active_nodedev_reset( specified_device, vm, expect_succeed) else: raise error.TestNAError('Param specified_device is not set!') elif device_option == 'unresettable': # Test all unresettable device. if unresettable_nodes: test_nodedev_reset(unresettable_nodes, expect_succeed) else: raise error.TestNAError('No unresettable device found!') else: raise error.TestError( 'Unrecognisable device option %s!' % device_option) finally: # Restore libvirtd status logging.debug('Restoring libvirtd') current_libvirtd_status = utils_libvirtd.libvirtd_is_running() if current_libvirtd_status and not libvirtd_status: utils_libvirtd.libvirtd_stop() elif not current_libvirtd_status and libvirtd_status: utils_libvirtd.libvirtd_start()
def run(test, params, env): """ Test blkdevio tuning Positive test has covered the following combination. ------------------------- | total | read | write | ------------------------- | 0 | 0 | 0 | | non-0 | 0 | 0 | | 0 | non-0 | non-0 | | 0 | non-0 | 0 | | 0 | 0 | non-0 | ------------------------- Negative test has covered unsupported combination and invalid command arguments. NB: only qemu-kvm-rhev supports block I/O throttling on >= RHEL6.5, the qemu-kvm is okay for block I/O throttling on >= RHEL7.0. """ # Run test case vm_name = params.get("main_vm") vm = env.get_vm(vm_name) start_vm = params.get("start_vm", "yes") change_parameters = params.get("change_parameters", "no") attach_disk = "yes" == params.get("attach_disk", "no") attach_before_start = "yes" == params.get("attach_before_start", "yes") disk_type = params.get("disk_type", 'file') disk_format = params.get("disk_format", 'qcow2') disk_bus = params.get("disk_bus", 'virtio') disk_alias = params.get("disk_alias") attach_options = params.get("attach_options") original_vm_xml = libvirt_xml.VMXML.new_from_inactive_dumpxml(vm_name) # Used for default device of blkdeviotune device = params.get("device_name", "vmblk") sys_image_target = vm.get_first_disk_devices()["target"] # Make sure vm is down if start not requested if (start_vm == "no" or attach_before_start) and vm and vm.is_alive(): vm.destroy() if attach_disk: disk_source = tempfile.mktemp(dir=data_dir.get_tmp_dir()) libvirt.create_local_disk(disk_type, path=disk_source, size='1', disk_format=disk_format) attach_extra = "" if disk_alias: attach_extra += " --alias %s" % disk_alias if disk_bus: attach_extra += " --targetbus %s" % disk_bus if disk_format: attach_extra += " --subdriver %s" % disk_format if attach_options: attach_extra += " %s" % attach_options # Coldplug disk if attach_disk and attach_before_start: ret = virsh.attach_disk(vm_name, disk_source, device, extra=attach_extra, debug=True) libvirt.check_exit_status(ret) # Recover previous running guest if vm and not vm.is_alive() and start_vm == "yes": try: vm.start() vm.wait_for_login().close() except (virt_vm.VMError, remote.LoginError) as detail: vm.destroy() test.fail(str(detail)) # Hotplug disk if attach_disk and not attach_before_start: ret = virsh.attach_disk(vm_name, disk_source, device, extra=attach_extra, debug=True) libvirt.check_exit_status(ret) test_dict = dict(params) test_dict['vm'] = vm if device == "vmblk": test_dict['device_name'] = sys_image_target # Make sure libvirtd service is running if not utils_libvirtd.libvirtd_is_running(): test.cancel("libvirt service is not running!") # Positive and negative testing try: if change_parameters == "no": get_blkdevio_parameter(test_dict, test) else: set_blkdevio_parameter(test_dict, test) finally: # Restore guest original_vm_xml.sync()
def run(test, params, env): global flag_list, flag_list_abs, update_sec, without_sec global check_sec, check_without_sec, newxml # Basic network params net_name = params.get("net_update_net_name", "updatenet") net_section = params.get("network_section") update_command = params.get("update_command", "add-last") options = params.get("cmd_options", "") net_state = params.get("net_state") use_in_guest = params.get("use_in_guest") iface_type = params.get("iface_type", "network") ip_version = params.get("ip_version", "ipv4") new_start_ip = params.get("start_ip") new_end_ip = params.get("end_ip") parent_index = params.get("parent_index") status_error = params.get("status_error", "no") # dhcp host test new_dhcp_host_ip = params.get("new_dhcp_host_ip") new_dhcp_host_id = params.get("new_dhcp_host_id") new_dhcp_host_name = params.get("new_dhcp_host_name") new_dhcp_host_mac = params.get("new_dhcp_host_mac") # ipv4 range/host test ipv4_range_start = params.get("ori_ipv4_range_start") ipv4_range_end = params.get("ori_ipv4_range_end") ipv4_host_mac = params.get("ori_ipv4_host_mac") ipv4_host_ip = params.get("ori_ipv4_host_ip") ipv4_host_name = params.get("ori_ipv4_host_name") # ipv6 range/host test ipv6_range_start = params.get("ori_ipv6_range_start") ipv6_range_end = params.get("ori_ipv6_range_end") ipv6_host_id = params.get("ori_ipv6_host_id") ipv6_host_name = params.get("ori_ipv6_host_name") ipv6_host_ip = params.get("ori_ipv6_host_ip") # dns test dns_name = params.get("ori_dns_name") dns_value = params.get("ori_dns_value") new_dns_name = params.get("new_dns_name") new_dns_value = params.get("new_dns_value") # srv test srv_service = params.get("ori_srv_service") srv_protocol = params.get("ori_srv_protocol") srv_domain = params.get("ori_srv_domain") srv_target = params.get("ori_srv_target") srv_port = params.get("ori_srv_port") srv_priority = params.get("ori_srv_priority") srv_weight = params.get("ori_srv_weight") new_srv_service = params.get("new_srv_service") new_srv_protocol = params.get("new_srv_protocol") new_srv_domain = params.get("new_srv_domain") new_srv_target = params.get("new_srv_target") new_srv_port = params.get("new_srv_port") new_srv_priority = params.get("new_srv_priority") new_srv_weight = params.get("new_srv_weight") # dns host test dns_hostip = params.get("ori_dns_hostip") dns_hostname = params.get("ori_dns_hostname") dns_hostname2 = params.get("ori_dns_hostname2") # setting for without part without_ip_dhcp = params.get("without_ip_dhcp", "no") without_dns = params.get("without_dns", "no") without_dns_host = params.get("without_dns_host", "no") without_dns_txt = params.get("without_dns_txt", "no") without_dns_srv = params.get("without_dns_srv", "no") without_dns_forwarder = params.get("without_dns_forwarder", "no") # setting for update/check/without section update_sec = params.get("update_sec") check_sec = params.get("check_sec") without_sec = params.get("without_sec") check_without_sec = params.get("check_without_sec") # forward test forward_mode = params.get("forward_mode") forward_iface = params.get("forward_iface", "eth2") # other params error_type = params.get("error_type", "") vm_name = params.get("main_vm") loop_time = int(params.get("loop_time", 1)) check_config_round = params.get("check_config_round", -1) ipv4_host_id = ipv6_host_mac = "" dns_enable = params.get("dns_enable", "yes") guest_iface_num = int(params.get("guest_iface_num", 1)) newxml = "" def get_hostfile(): """ Get the content of hostfile """ logging.info("Checking network hostfile...") hostfile = "/var/lib/libvirt/dnsmasq/%s.hostsfile" % net_name with open(hostfile) as hostfile_d: hostfile = hostfile_d.readlines() return hostfile def find_config(check_file, need_find): """ Find configure in check_file :param check_file: The file that will check :param need_find: If need to find the item in check_file, Boolean """ def _find_config(check_func): def __find_config(*args, **kwargs): logging.info("Checking content of %s", check_file) ret = False item = None with open(check_file) as checkfile_d: while True: check_line = checkfile_d.readline() if not check_line: break (ret, item) = check_func(check_line, *args, **kwargs) if ret: break if not ret: if need_find: test.fail("Fail to find %s in %s" % (item, check_file)) else: logging.info("Can not find %s in %s as expected" % (item, check_file)) return __find_config return _find_config conf_file = "/var/lib/libvirt/dnsmasq/%s.conf" % net_name @find_config(conf_file, True) def check_item(check_line, item): """ Check if the item in config file """ if item in check_line: logging.info("Find %s in %s", item, conf_file) return (True, item) else: return (False, item) host_file = "/var/lib/libvirt/dnsmasq/%s.addnhosts" % net_name @find_config(host_file, True) def check_host(check_line, item): """ Check if the item in host_file """ if re.search(item, check_line): logging.info("Find %s in %s", item, host_file) return (True, item) else: return (False, item) @find_config(conf_file, False) def check_item_absent(check_line, item): """ Check if the item not in config file """ if item in check_line: test.fail("Find %s in %s" % (item, conf_file)) else: return (False, item) @find_config(host_file, False) def check_host_absent(check_line, item): """ Check if the item not in host_file """ if re.search(item, check_line): test.fail("Find %s in %s" % (item, host_file)) else: return (False, item) def section_update(ori_pre, new_pre): """ Deal with update section and without section in func :param ori_pre: prefix of original section parameter name :param new_pre: prefix of new section parameter name """ global flag_list, flag_list_abs, update_sec, without_sec global check_sec, check_without_sec, newxml if update_sec: for sec in update_sec.split(","): newxml = newxml.replace(names[ori_pre+sec], names[new_pre+sec]) if update_command != "delete": check_sec = update_sec if without_sec: for sec_no in without_sec.split(","): newxml = re.sub(sec_no+"=\".*?\"", "", newxml) if update_command == "modify": check_without_sec = without_sec if check_sec: for c_sec in check_sec.split(","): flag_list.append(names[new_pre+c_sec]) if check_without_sec: for c_sec_no in check_without_sec.split(","): flag_list_abs.append(names[ori_pre+c_sec_no]) dns_host_xml = """ <host ip='%s'> <hostname>%s</hostname> <hostname>%s</hostname> </host> """ % (dns_hostip, dns_hostname, dns_hostname2) virtual_net = """ <network> <name>%s</name> <forward mode='nat'/> <bridge name='%s' stp='on' delay='0' /> <mac address='52:54:00:03:78:6c'/> <domain name="example.com" localOnly="no"/> <mtu size="9000"/> <dns enable='%s'> <forwarder domain='example.com' addr="8.8.4.4"/> <txt name='%s' value='%s'/> <srv service='%s' protocol='%s' domain='%s' target='%s' port='%s' priority='%s' weight='%s'/> %s </dns> <ip address='192.168.100.1' netmask='255.255.255.0'> <dhcp> <range start='%s' end='%s' /> <host mac='%s' ip='%s' name='%s' /> </dhcp> </ip> <ip family='ipv6' address='2001:db8:ca2:2::1' prefix='64'> <dhcp> <range start='%s' end='%s'/> <host id='%s' name='%s' ip='%s'/> </dhcp> </ip> <route family='ipv6' address='2001:db8:ca2:2::' prefix='64' gateway='2001:db8:ca2:2::4'/> <ip address='192.168.101.1' netmask='255.255.255.0'/> <ip family='ipv6' address='2001:db8:ca2:3::1' prefix='64' /> </network> """ % (net_name, net_name, dns_enable, dns_name, dns_value, srv_service, srv_protocol, srv_domain, srv_target, srv_port, srv_priority, srv_weight, dns_host_xml, ipv4_range_start, ipv4_range_end, ipv4_host_mac, ipv4_host_ip, ipv4_host_name, ipv6_range_start, ipv6_range_end, ipv6_host_id, ipv6_host_name, ipv6_host_ip) port_group = """ <portgroup name='engineering' default='no'> <virtualport type='802.1Qbh'> <parameters profileid='test'/> </virtualport> <bandwidth> <inbound average='1000' peak='5000' burst='5120'/> <outbound average='1000' peak='5000' burst='5120'/> </bandwidth> </portgroup> """ if use_in_guest == "yes": vm = env.get_vm(vm_name) vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) vmxml_backup = vmxml.copy() backup_files = [] try: for loop in range(loop_time): if loop_time > 1: logging.info("Round %s:", loop+1) update_command = params.get("update_command").split(",")[loop] if net_section == "ip-dhcp-host": new_dhcp_host_ip = params.get("new_dhcp_host_ip").split(",")[loop] new_dhcp_host_name = params.get("new_dhcp_host_name").split(",")[loop] new_dhcp_host_mac = params.get("new_dhcp_host_mac").split(",")[loop] status_error = params.get("status_error").split(",")[loop] elif net_section == "dns-txt": net_state = params.get("net_state").split(",")[loop] # Get a tmp_dir. tmp_dir = data_dir.get_tmp_dir() # Write new xml into a tempfile tmp_file = tempfile.NamedTemporaryFile(prefix=("new_xml_"), dir=tmp_dir) xmlfile = tmp_file.name tmp_file.close() # Generate testxml test_xml = network_xml.NetworkXML(network_name=net_name) test_xml.xml = virtual_net names = locals() if net_section == "portgroup": portgroup_xml = network_xml.PortgroupXML() portgroup_xml.xml = port_group test_xml.portgroup = portgroup_xml elif net_section == "forward-interface": if forward_mode == "bridge": forward_iface = utils_net.get_net_if(state="UP")[0] test_xml.forward = {'mode': forward_mode} test_xml.forward_interface = [{'dev': forward_iface}] del test_xml.bridge del test_xml.mac for ip_num in range(4): del test_xml.ip del test_xml.routes del test_xml.dns del test_xml.mtu del test_xml.domain_name section_index = 0 if ip_version == "ipv6": section_index = 1 element = "/%s" % net_section.replace('-', '/') try: section_xml = test_xml.get_section_string(xpath=element, index=section_index) except xcepts.LibvirtXMLNotFoundError: newxml = section_xml = test_xml.get_section_string(xpath="/ip/dhcp/range") newxml = section_xml logging.debug("section xml is %s", newxml) flag_list = [] flag_list_abs = [] if (update_command == "delete" and error_type not in ["host-mismatch", "range-mismatch"] and not without_sec and not update_sec): logging.info("The delete xml is %s", newxml) else: if net_section == "bridge": new_bridge_name = net_name + "_new" flag_list.append(new_bridge_name) newxml = section_xml.replace(net_name, new_bridge_name) logging.info("The new bridge xml is %s", newxml) elif net_section == "forward": new_mode = "route" flag_list.append(new_mode) newxml = section_xml.replace("nat", new_mode) logging.info("The new forward xml is %s", newxml) elif net_section == "ip": new_netmask = "255.255.0.0" flag_list.append(new_netmask) newxml = section_xml.replace("255.255.255.0", new_netmask) elif net_section == "ip-dhcp-range": newxml = section_xml.replace(names[ip_version+"_range_start"], new_start_ip) newxml = newxml.replace(names[ip_version+"_range_end"], new_end_ip) for location in ["end", "start"]: if names["new_"+location+"_ip"] == "": newxml = newxml.replace(location+"=\"\"", "") else: flag_list.append(names["new_"+location+"_ip"]) elif net_section == "portgroup": new_inbound_average = "2000" flag_list.append(new_inbound_average) newxml = section_xml.replace("1000", new_inbound_average) newxml = newxml.replace("default=\"no\"", "default=\"yes\"") flag_list.append("default=('|\")yes") if update_command in ['add-first', 'add-last', 'add']: newxml = newxml.replace("engineering", "sales") flag_list.append("sales") if update_command == "modify" and status_error == "yes": newxml = newxml.replace("engineering", "") elif net_section == "forward-interface": new_forward_iface = params.get("new_forward_iface") if error_type != "interface-duplicate": find_iface = 0 if not new_forward_iface and forward_mode == "bridge": new_iface_list = utils_net.get_net_if(qdisc="(mq|pfifo_fast)", state="(UP|DOWN)", optional="MULTICAST,UP") logging.info("new_iface_list is %s", new_iface_list) for iface in new_iface_list: if iface[0] != forward_iface: new_forward_iface = iface[0] find_iface = 1 break if not find_iface: test.cancel("Can not find another physical interface to attach") else: new_forward_iface = forward_iface flag_list.append(new_forward_iface) newxml = section_xml.replace(forward_iface, new_forward_iface) elif net_section == "ip-dhcp-host": if (update_sec is None and update_command not in ['modify', 'delete']): if ip_version == "ipv4": update_sec = "ip,mac,name" elif ip_version == "ipv6": update_sec = "ip,id,name" section_update(ip_version+"_host_", "new_dhcp_host_") elif net_section == "dns-txt": section_update("dns_", "new_dns_") elif net_section == "dns-srv": section_update("srv_", "new_srv_") elif net_section == "dns-host": if without_sec == "hostname": newxml = re.sub("<hostname>.*</hostname>\n", "", newxml) if status_error == 'no': flag_list.append("ip=.*?"+dns_hostip) flag_list.append(dns_hostname) flag_list.append(dns_hostname2) # for negative test may have net_section do not match issues elif status_error == "no": test.fail("Unknown network section") logging.info("The new xml of %s is %s", net_section, newxml) with open(xmlfile, 'w') as xmlfile_d: xmlfile_d.write(newxml) if without_ip_dhcp == "yes": test_xml.del_element(element="/ip/dhcp") test_xml.del_element(element="/ip/dhcp") if without_dns == "yes": test_xml.del_element(element='/dns') if without_dns_host == "yes": test_xml.del_element(element='/dns/host') if without_dns_txt == "yes": test_xml.del_element(element='/dns/txt') if without_dns_srv == "yes": test_xml.del_element(element='/dns/srv') if without_dns_forwarder == "yes": test_xml.del_element(element='/dns/forwarder') # Only do net define/start in first loop if (net_section == "ip-dhcp-range" and use_in_guest == "yes" and without_ip_dhcp == "no"): test_xml.del_element(element="/ip/dhcp", index=section_index) if loop == 0: try: # Define and start network test_xml.debug_xml() test_xml.define() ori_net_xml = virsh.net_dumpxml(net_name).stdout.strip() if "ipv6" in ori_net_xml: host_ifaces = utils_net.get_net_if(state="UP") backup_files.append( remote.RemoteFile(address='127.0.0.1', client='scp', username=params.get('username'), password=params.get('password'), port='22', remote_path='/proc/sys/net/ipv6/' 'conf/all/accept_ra')) process.run("echo 2 > /proc/sys/net/ipv6/conf/all/accept_ra", shell=True) for host_iface in host_ifaces: backup_files.append( remote.RemoteFile(address='127.0.0.1', client='scp', username=params.get('username'), password=params.get('password'), port='22', remote_path='/proc/sys/net/ipv6/' 'conf/%s/accept_ra' % host_iface)) process.run("echo 2 > /proc/sys/net/ipv6/conf/%s/accept_ra" % host_iface, shell=True) process.run("cat /proc/sys/net/ipv6/conf/%s/accept_ra" % host_iface) if net_state == "active" or net_state == "transient": test_xml.start() if net_state == "transient": test_xml.del_defined() list_result = virsh.net_list("--all --name").stdout.strip() if net_name not in list_result: test.fail("Can not find %s in net-list" % net_name) except xcepts.LibvirtXMLError as detail: test.error("Failed to define a test network.\n" "Detail: %s." % detail) else: # setting net status for following loops if net_state == "active": test_xml.set_active(True) elif net_state == "inactive": test_xml.set_active(False) # get hostfile before update if without_ip_dhcp == "yes" and net_state == "active": hostfile_before = get_hostfile() if hostfile_before != []: test.fail("hostfile is not empty before update: %s" % hostfile_before) logging.info("hostfile is empty before update") # Get dnsmasq pid before update check_dnsmasq = ((update_command == "add" or update_command == "delete") and net_section == "ip-dhcp-range" and status_error == "no" and net_state == "active" and options != "--config") if check_dnsmasq: cmd = "ps aux|grep dnsmasq|grep -v grep|grep %s|awk '{print $2}'" % net_name pid_list_bef = process.run(cmd, shell=True).stdout_text.strip().split('\n') if parent_index: options += " --parent-index %s" % parent_index # Check config before update if net_state == "active": dns_txt = dns_srv = dns_host_str = None try: dns_txt = test_xml.get_section_string(xpath="/dns/txt") dns_srv = test_xml.get_section_string(xpath="/dns/srv") dns_host_str = test_xml.get_section_string(xpath="/dns/host") except xcepts.LibvirtXMLNotFoundError: pass txt_record = "txt-record=%s,%s" % (dns_name, dns_value) srv_host = "srv-host=_%s._%s.%s,%s,%s,%s,%s" % (srv_service, srv_protocol, srv_domain, srv_target, srv_port, srv_priority, srv_weight) hostline = "%s.*%s.*%s" % (dns_hostip, dns_hostname, dns_hostname2) if dns_txt: check_item(txt_record) if dns_srv: check_item(srv_host) if dns_host_str: check_host(hostline) # check libvirtd should not crash during the net-update ori_pid_libvirtd = process.getoutput("pidof libvirtd") # Do net-update operation cmd_result = virsh.net_update(net_name, update_command, net_section, xmlfile, options, debug=True) aft_pid_libvirtd = process.getoutput("pidof libvirtd") if not utils_libvirtd.libvirtd_is_running() or ori_pid_libvirtd != aft_pid_libvirtd: test.fail("Libvirtd crash after net-update operation") if cmd_result.exit_status: err = cmd_result.stderr.strip() if status_error == "yes": # index-mismatch error info and judgement index_err1 = "the address family of a host entry IP must match the" + \ " address family of the dhcp element's parent" index_err2 = "XML error: Invalid to specify MAC address.* in network" + \ ".* IPv6 static host definition" index_err3 = "mismatch of address family in range.* for network" mismatch_expect = (error_type == "index-mismatch" and (re.search(index_err1, err) or re.search(index_err2, err) or re.search(index_err3, err))) err_dic = {} # multi-host error info err_dic["multi-hosts"] = "dhcp is supported only for a single.*" + \ " address on each network" # range-mismatch error info err_dic["range-mismatch"] = "couldn't locate a matching dhcp " + \ "range entry in network " # host-mismatch error info err_dic["host-mismatch"] = "couldn't locate a matching dhcp " + \ "host entry in network " # dns-mismatch error info err_dic["dns-mismatch"] = "couldn't locate a matching DNS TXT " + \ "record in network " # range-duplicate error info err_dic["range-duplicate"] = "there is an existing dhcp range" + \ " entry in network.* that matches" # host-duplicate error info err_dic["host-duplicate"] = "there is an existing dhcp host" + \ " entry in network.* that matches" # out_of_range error info err_dic["out-of-range"] = "range.* is not entirely within network" # no end for range error err_dic["range-no-end"] = "Missing 'end' attribute in dhcp " + \ "range for network" # no match item for host modify err err_dic["no-match-item"] = "couldn't locate an existing dhcp" + \ " host entry with.* in network" # no host name and mac for modify err err_dic["host-no-name-mac"] = "Static host definition in IPv4 network" + \ ".* must have mac or name attribute" # no host ip for modify err err_dic["host-no-ip"] = "Missing IP address in static host " + \ "definition for network" # wrong command name err_dic["wrong-command-name"] = "unrecognized command name" # wrong section name err_dic["wrong-section-name"] = "unrecognized section name" # delete with only id err_dic["only-id"] = "At least one of name, mac, or ip attribute must be" + \ " specified for static host definition in network" # options exclusive err_dic["opt-exclusive"] = "Options --current and.* are mutually exclusive" # range_reverse error info if ip_version == "ipv4": err_dic["range-reverse"] = "range.* is reversed" elif ip_version == "ipv6": err_dic["range-reverse"] = "range.*start larger than end" # --live with inactive net err_dic["invalid-state"] = "network is not running" err_dic["transient"] = "cannot change persistent config of a transient network" err_dic["dns-disable"] = "Extra data in disabled network" err_dic["modify"] = "cannot be modified, only added or deleted" err_dic["not-support"] = "can't update.*section of network" err_dic["unrecognized"] = "unrecognized section name" err_dic["interface-duplicate"] = "there is an existing interface entry " + \ "in network.* that matches" err_dic["XML error"] = "XML error: Missing required name attribute in portgroup" if (error_type in list(err_dic.keys()) and re.search(err_dic[error_type], err) or mismatch_expect): logging.debug("Get expect error: %s", err) else: test.fail("Do not get expect err msg: %s, %s" % (error_type, err_dic)) else: test.fail("Failed to execute net-update command") elif status_error == "yes": test.fail("Expect fail, but succeed") # Get dnsmasq pid after update if check_dnsmasq: pid_list_aft = process.run(cmd, shell=True).stdout_text.strip().split('\n') for pid in pid_list_aft: if pid in pid_list_bef: test.fail("dnsmasq do not updated") # Check the actual xml cmd_result = virsh.net_dumpxml(net_name) actual_net_xml = cmd_result.stdout.strip() new_xml_obj = network_xml.NetworkXML.new_from_net_dumpxml(net_name) logging.info("After net-update, the actual net xml is %s", actual_net_xml) if "ip-dhcp" in net_section: if ip_version == "ipv6": new_xml_obj.del_element(element="/ip", index=0) if ip_version == "ipv4": new_xml_obj.del_element(element="/ip", index=1) config_not_work = ("--config" in options and net_state == "active" and "--live" not in options) if config_not_work: if update_command != "delete": flag_list_abs = flag_list flag_list = [] else: flag_list = flag_list_abs flag_list_abs = [] logging.info("The check list is %s, absent list is %s", flag_list, flag_list_abs) if (update_command == "delete" and status_error == "no" and not config_not_work and loop_time == 1): try: section_str = new_xml_obj.get_section_string(xpath=element) except xcepts.LibvirtXMLNotFoundError: section_str = None logging.info("Can not find section %s in xml after delete", element) if section_str is not None: test.fail("The actual net xml is not expected," "element still exists") elif ("duplicate" not in error_type and error_type != "range-mismatch" and error_type != "host-mismatch" and error_type != "not-support"): # check xml should exists for flag_string in flag_list: logging.info("checking %s should in xml in positive test," "and absent in negative test", flag_string) if not re.search(flag_string, actual_net_xml): if ((status_error == "no" and update_command != "delete") or (update_command == "delete" and status_error == "yes")): test.fail("The actual net xml failed to update," "or expect delete fail but xml missing" ":%s" % flag_string) else: if ((status_error == "yes" and update_command != "delete") or (status_error == "no" and update_command == "delete" and not config_not_work)): test.fail("Expect test fail, but find xml %s" " actual, or expect delete succeed," "but fail in fact" % flag_string) # check xml should not exists for flag_string_abs in flag_list_abs: logging.info("checking %s should NOT in xml in positive test," "and exist in negative test", flag_string_abs) if re.search(flag_string_abs, actual_net_xml): if status_error == "no": test.fail("Expect absent in net xml, but exists" "in fact: %s" % flag_string_abs) else: if status_error == "yes": test.fail("Should exists in net xml, but it " "disappeared: %s" % flag_string_abs) # Check if add-last, add-fist works well if (status_error == "no" and not config_not_work and update_command in ["add-last", "add", "add-first"]): if update_command == "add-first": find_index = 0 else: find_index = -1 section_str_aft = new_xml_obj.get_section_string(xpath=element, index=find_index) logging.info("xpath is %s, find_index is %s, section_str_aft is %s", element, find_index, section_str_aft) for flag_string in flag_list: logging.info("flag_string is %s", flag_string) if not re.search(flag_string, section_str_aft): test.fail("Can not find %s in %s" % (flag_string, section_str_aft)) logging.info("%s %s in right place", update_command, section_str_aft) # Check the positive test result if status_error == "no": # Check the network conf file # live update if ("--live" in options or "--config" not in options) and net_state == "active": if net_section == "ip-dhcp-range" and update_command == "add-first": ip_range = "%s,%s" % (new_start_ip, new_end_ip) if ip_version == "ipv6": ip_range = ip_range + ",64" check_item(ip_range) if "dns" in net_section: if update_command == "delete" and loop == 0: if net_section == "dns-srv": check_item_absent(srv_host) if net_section == "dns-txt": check_item_absent(txt_record) if net_section == "dns-host": check_host_absent(dns_host_str) elif "add" in update_command: if net_section == "dns-srv": for sec in update_sec.split(","): srv_host = srv_host.replace(names["srv_"+sec], names["new_srv_"+sec]) check_item(srv_host) if net_section == "dns-txt": for sec in update_sec.split(","): txt_record = txt_record.replace(names["dns_"+sec], names["new_dns_"+sec]) check_item(txt_record) if net_section == "dns-host": check_host(hostline) # Check the hostfile if (net_section == "ip-dhcp-host" and update_command != "modify" and update_command != "delete"): dic_hostfile = {} for sec in ["ip", "mac", "name", "id"]: if update_sec is not None and sec in update_sec.split(","): dic_hostfile[sec] = names["new_dhcp_host_"+sec]+"," else: dic_hostfile[sec] = names[ip_version+"_host_"+sec]+"," if sec == "ip" and ip_version == "ipv6": dic_hostfile[sec] = "[" + dic_hostfile[sec].strip(",") + "]" if without_sec is not None and sec in without_sec.split(","): dic_hostfile[sec] = "" if ip_version == "ipv4": host_info = (dic_hostfile["mac"] + dic_hostfile["ip"] + dic_hostfile["name"]) if dic_hostfile["mac"] == "": host_info = dic_hostfile["name"] + dic_hostfile["ip"] if ip_version == "ipv6": host_info = ("id:" + dic_hostfile["id"] + dic_hostfile["name"] + dic_hostfile["ip"]) hostfile = get_hostfile() host_info_patten = host_info.strip(",") + "\n" if host_info_patten in hostfile: logging.info("host info %s is in hostfile %s", host_info, hostfile) else: test.fail("Can not find %s in host file: %s" % (host_info, hostfile)) # Check the net in guest if use_in_guest == "yes" and loop == 0: # Detach all interfaces of vm first iface_index = 0 mac_list = vm_xml.VMXML.get_iface_dev(vm_name) for mac in mac_list: iface_dict = vm_xml.VMXML.get_iface_by_mac(vm_name, mac) virsh.detach_interface(vm_name, "--type %s --mac %s --config" % (iface_dict.get('type'), mac)) vm.free_mac_address(iface_index) iface_index += 1 # attach new interface to guest for j in range(guest_iface_num): if net_section == "ip-dhcp-host" and new_dhcp_host_mac: mac = new_dhcp_host_mac else: mac = utils_net.generate_mac_address_simple() ret = virsh.attach_interface(vm_name, "--type %s --source %s --mac %s --config" % (iface_type, net_name, mac)) if ret.exit_status: test.fail("Fail to attach new interface to guest: %s" % ret.stderr.strip()) # The sleep here is to make sure the update make effect time.sleep(2) # Start guest and check ip/mac/hostname... vm.start() logging.debug("vm xml is %s", vm.get_xml()) session = vm.wait_for_serial_login(internal_timeout=60) if "ip-dhcp" in net_section: dhclient_cmd = "(if pgrep dhclient;" \ "then pkill dhclient; sleep 3; fi) " \ "&& dhclient -%s -lf /dev/stdout" % ip_version[-1] leases = session.cmd_output(dhclient_cmd) iface_ip = utils_net.get_guest_ip_addr(session, mac, ip_version=ip_version, timeout=10) if net_section == "ip-dhcp-range": if new_start_ip <= iface_ip <= new_end_ip: logging.info("getting ip %s is in range [%s ~ %s]", iface_ip, new_start_ip, new_end_ip) else: test.fail("getting ip %s not in range [%s ~ %s]" % (iface_ip, new_start_ip, new_end_ip)) if net_section == "ip-dhcp-host": if iface_ip == new_dhcp_host_ip: logging.info("getting ip is same with set: %s", iface_ip) else: test.fail("getting ip %s is not same with setting %s" % (iface_ip, new_dhcp_host_ip)) hostname = session.cmd_output("hostname -s").strip('\n') # option host-name "redhatipv4-2" dhcp_hostname = "option host-name \"%s\"" % new_dhcp_host_name.split('.')[0] if hostname == new_dhcp_host_name.split('.')[0] or dhcp_hostname in leases: logging.info("getting hostname same with setting: %s", new_dhcp_host_name.split('.')[0]) else: test.fail("getting hostname %s is not same with " "setting: %s" % (hostname, new_dhcp_host_name)) session.close() # Check network connection for macvtap if (use_in_guest == "yes" and net_section == "forward-interface" and forward_mode == "bridge"): xml_obj_use = network_xml.NetworkXML.new_from_net_dumpxml(net_name) net_conn = int(xml_obj_use.connection) iface_conn = xml_obj_use.get_interface_connection() conn_count = 0 for k in iface_conn: conn_count = conn_count + int(k) logging.info("net_conn=%s, conn_count=%s, guest_iface_num=%s" % (net_conn, conn_count, guest_iface_num)) if (net_conn != conn_count or (loop == 1 and guest_iface_num != net_conn)): test.fail("Can not get expected connection num: " "net_conn = %s, iface_conn = %s" % (net_conn, conn_count)) #Check --config option after net destroyed if (int(check_config_round) == loop or (loop_time == 1 and "--current" in options and net_state == "active")): test_xml.set_active(False) logging.info("Checking xml after net destroyed") cmd_result = virsh.net_dumpxml(net_name) inactive_xml = cmd_result.stdout.strip() logging.info("inactive_xml is %s", inactive_xml) #Check the inactive xml for check_str in flag_list: if update_command != "delete": if "--config" in options: if not re.search(check_str, inactive_xml): test.fail("Can not find xml after net destroyed") if "--current" in options: if re.search(check_str, inactive_xml): test.fail("XML still exists after net destroyed") else: if "--config" in options: if re.search(check_str, inactive_xml): test.fail("XML still exists after net destroyed") if "--current" in options: if not re.search(check_str, inactive_xml): test.fail("Can not find xml after net destroyed") logging.info("Check for net inactive PASS") finally: if test_xml.get_active(): test_xml.del_active() if test_xml.get_defined(): test_xml.del_defined() if os.path.exists(xmlfile): os.remove(xmlfile) if use_in_guest == "yes": vm = env.get_vm(vm_name) if vm.is_alive(): vm.destroy(gracefully=False) vmxml_backup.sync() for config_file in backup_files: config_file._reset_file()
def run(test, params, env): """ Test numa tuning 1) Positive testing 1.1) get the current numa parameters for a running/shutoff guest 1.2) set the current numa parameters for a running/shutoff guest 1.2.1) set valid 'mode' parameters 1.2.2) set valid 'nodeset' parameters 2) Negative testing 2.1) get numa parameters 2.1.1) invalid options 2.1.2) stop cgroup service 2.2) set numa parameters 2.2.1) invalid 'mode' parameters 2.2.2) invalid 'nodeset' parameters 2.2.3) change 'mode' for a running guest and 'mode' is not 'strict' 2.2.4) change 'nodeset' for running guest with mode of 'interleave' 'interleave' or 'preferred' numa mode 2.2.5) stop cgroup service """ try: utils_misc.find_command("numactl") except ValueError: raise error.TestNAError("Command 'numactl' is missing. You must " "install it.") # Run test case vm_name = params.get("vms") vm = env.get_vm(vm_name) original_vm_xml = libvirt_xml.VMXML.new_from_inactive_dumpxml(vm_name) cg = utils_cgroup.CgconfigService() status_error = params.get("status_error", "no") libvirtd = params.get("libvirtd", "on") cgconfig = params.get("cgconfig", "on") start_vm = params.get("start_vm", "no") change_parameters = params.get("change_parameters", "no") # Make sure vm is down if start not requested if start_vm == "no" and vm.is_alive(): vm.destroy() # positive and negative testing ######### cgstop = False try: if status_error == "no": if change_parameters == "no": get_numa_parameter(params, cgstop) else: set_numa_parameter(params, cgstop) if cgconfig == "off": # If running, then need to shutdown a running guest before # stopping cgconfig service and will start the guest after # restarting libvirtd service if cg.cgconfig_is_running(): if vm.is_alive(): vm.destroy() cg.cgconfig_stop() cgstop = True # If we stopped cg, then refresh libvirtd service # to get latest cgconfig service change; otherwise, # if no cg change restart of libvirtd is pointless if cgstop and libvirtd == "restart": try: utils_libvirtd.libvirtd_restart() finally: # Not running is not a good thing, but it does happen # and it will affect other tests if not utils_libvirtd.libvirtd_is_running(): raise error.TestNAError("libvirt service is not running!") # Recover previous running guest if (cgconfig == "off" and libvirtd == "restart" and not vm.is_alive() and start_vm == "yes"): vm.start() if status_error == "yes": if change_parameters == "no": get_numa_parameter(params, cgstop) else: set_numa_parameter(params, cgstop) finally: # Restore guest original_vm_xml.sync() # If we stopped cg, then recover and refresh libvirtd to recognize if cgstop: cg.cgconfig_start() utils_libvirtd.libvirtd_restart()
def run_virsh_dump(test, params, env): """ Test command: virsh dump. This command can dump the core of a domain to a file for analysis. 1. Positive testing 1.1 Dump domain with valid options. 1.2 Avoid file system cache when dumping. 1.3 Compress the dump images to valid/invalid formats. 2. Negative testing 2.1 Dump domain to a non-exist directory. 2.2 Dump domain with invalid option. 2.3 Dump a shut-off domain. """ vm_name = params.get("main_vm", "vm1") vm = env.get_vm(params["main_vm"]) options = params.get("dump_options") dump_file = params.get("dump_file", "vm.core") if os.path.dirname(dump_file) is "": dump_file = os.path.join(test.tmpdir, dump_file) dump_image_format = params.get("dump_image_format") start_vm = params.get("start_vm") status_error = params.get("status_error", "no") qemu_conf = "/etc/libvirt/qemu.conf" # prepare the vm state if vm.is_alive() and start_vm == "no": vm.destroy() if vm.is_dead() and start_vm == "yes": vm.start() def check_domstate(actual, options): """ Check the domain status according to dump options. """ if options.find('live') >= 0: domstate = "running" if options.find('crash') >= 0 or options.find('reset') >0: domstate = "running" elif options.find('crash') >=0: domstate = "shut off" if options.find('reset') >= 0: domstate = "running" elif options.find('reset') >= 0: domstate = "running" else: domstate = "running" if start_vm == "no": domstate = "shut off" logging.debug("Domain should %s after run dump %s", domstate, options) if domstate == actual: return True else: return False def check_dump_format(dump_image_format, dump_file): """ Check the format of dumped file. If 'dump_image_format' is not specified or invalid in qemu.conf, then the file shoule be normal raw file, otherwise it shoud be compress to specified format, the supported compress format including: lzop, gzip, bzip2, and xz. """ valid_format = ["lzop", "gzip", "bzip2", "xz"] if len(dump_image_format) == 0 or dump_image_format not in valid_format: logging.debug("No need check the dumped file format") return True else: file_cmd = "file %s" % dump_file (status, output) = commands.getstatusoutput(file_cmd) if status == 0: logging.debug("Run file %s output: %s", dump_file, output) actual_format = output.split(" ")[1] if actual_format == dump_image_format: if dump_image_format in valid_format: logging.info("Compress dumped file to %s successfully", dump_image_format) return True else: logging.error("Compress dumped file to %s fail", dump_image_format) return False else: logging.error("Fail to check dumped file %s", dump_file) return False # Configure dump_image_format in /etc/libvirt/qemu.conf. if len(dump_image_format) != 0: conf_cmd = ("echo dump_image_format = \\\"%s\\\" >> %s" % (dump_image_format, qemu_conf)) if os.system(conf_cmd): logging.error("Config dump_image_format to %s fail", dump_image_format) utils_libvirtd.libvirtd_restart() # Deal with bypass-cache option if options.find('bypass-cache') >= 0: thread.start_new_thread(check_bypass,(dump_file,)) # Guarantee check_bypass function has run before dump time.sleep(5) # Run virsh command cmd_result = virsh.dump(vm_name, dump_file, options, ignore_status=True, debug=True) status = cmd_result.exit_status # Check libvirtd status if utils_libvirtd.libvirtd_is_running(): if check_domstate(vm.state(), options): if status_error == "yes": if status == 0: raise error.TestFail("Expect fail, but run successfully") if status_error == "no": if status != 0: raise error.TestFail("Expect succeed, but run fail") else: if os.path.exists(dump_file): if check_dump_format(dump_image_format, dump_file): logging.info("Successfully dump domain to %s", dump_file) else: raise error.TestFail("The format of dumped file " "is wrong.") else: raise error.TestFail("Fail to find domain dumped file.") else: raise error.TestFail("Domain status check fail.") else: raise error.TestFail("Libvirtd service is dead.") if os.path.isfile(dump_file): os.remove(dump_file) if len(dump_image_format) != 0: clean_qemu_conf = "sed -i '$d' %s " % qemu_conf if os.system(clean_qemu_conf): raise error.TestFail("Fail to recover %s", qemu_conf)