From 7c72d8d5024df3c37503276a9e6232ff609c0edb Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 4 Jun 2024 03:41:05 -0400 Subject: [PATCH] virsh_setmem: skip dmidecode on s390x DMI/SMBIOS is not available on s390x. Since be1f9b835b760973dbfe2fe73c4768a59044dc13 the test tries to install the package if the command is not available. However, it will retry on failure, per default for utils_package.PKG_MGR_TIMEOUT (5min) slowing down the test unnecessarily. On s390x, just skip using dmidecode from the beginning. Also, log more information when calculating memory deviation for debug. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/memory/virsh_setmem.cfg | 1 + libvirt/tests/src/memory/virsh_setmem.py | 195 +++++++++++++--------- 2 files changed, 120 insertions(+), 76 deletions(-) diff --git a/libvirt/tests/cfg/memory/virsh_setmem.cfg b/libvirt/tests/cfg/memory/virsh_setmem.cfg index f7a6ba3730..cb589bd33b 100644 --- a/libvirt/tests/cfg/memory/virsh_setmem.cfg +++ b/libvirt/tests/cfg/memory/virsh_setmem.cfg @@ -20,6 +20,7 @@ reset_vm_memory = "yes" s390-virtio: reset_vm_memory = "no" + use_dmidecode = "no" vm_attrs = {'memory': 4, 'memory_unit': 'GiB', 'current_mem': 4, 'current_mem_unit': 'GiB'} variants: - valid_options: diff --git a/libvirt/tests/src/memory/virsh_setmem.py b/libvirt/tests/src/memory/virsh_setmem.py index 56d1d512be..19864e03b9 100644 --- a/libvirt/tests/src/memory/virsh_setmem.py +++ b/libvirt/tests/src/memory/virsh_setmem.py @@ -18,7 +18,7 @@ # Using as lower capital is not the best way to do, but this is just a # workaround to avoid changing the entire file. -logging = log.getLogger('avocado.' + __name__) +logging = log.getLogger("avocado." + __name__) def manipulate_domain(test, vm_name, action, recover=False): @@ -30,23 +30,27 @@ def manipulate_domain(test, vm_name, action, recover=False): if not recover: if action == "save": save_option = "" - result = virsh.save(vm_name, save_file, save_option, - ignore_status=True, debug=True) + result = virsh.save( + vm_name, save_file, save_option, ignore_status=True, debug=True + ) libvirt.check_exit_status(result) elif action == "managedsave": managedsave_option = "" - result = virsh.managedsave(vm_name, managedsave_option, - ignore_status=True, debug=True) + result = virsh.managedsave( + vm_name, managedsave_option, ignore_status=True, debug=True + ) libvirt.check_exit_status(result) elif action == "s3": suspend_target = "mem" - result = virsh.dompmsuspend(vm_name, suspend_target, - ignore_status=True, debug=True) + result = virsh.dompmsuspend( + vm_name, suspend_target, ignore_status=True, debug=True + ) libvirt.check_exit_status(result) elif action == "s4": suspend_target = "disk" - result = virsh.dompmsuspend(vm_name, suspend_target, - ignore_status=True, debug=True) + result = virsh.dompmsuspend( + vm_name, suspend_target, ignore_status=True, debug=True + ) libvirt.check_exit_status(result) # Wait domain state change: 'in shutdown' -> 'shut off' utils_misc.wait_for(lambda: virsh.is_dead(vm_name), 5) @@ -90,8 +94,7 @@ def get_vm_usable_mem(session): """ cmd = "cat /proc/meminfo" proc_mem = session.cmd_output(cmd) - total_usable_mem = re.search(r'MemTotal:\s+(\d+)\s+[kK]B', - proc_mem).group(1) + total_usable_mem = re.search(r"MemTotal:\s+(\d+)\s+[kK]B", proc_mem).group(1) return int(total_usable_mem) def vm_unusable_mem(session): @@ -101,18 +104,18 @@ def vm_unusable_mem(session): # Get total physical memory from dmidecode cmd = "dmidecode -t 17" dmi_mem = session.cmd_output(cmd) - dmi_mem_size = re.findall(r'Size:\s(\d+\s+[K|M|G]B)', dmi_mem) + dmi_mem_size = re.findall(r"Size:\s(\d+\s+[K|M|G]B)", dmi_mem) if not dmi_mem_size: test.fail("Cannot get memory size info inside VM.") total_physical_mem = 0 for size_info in dmi_mem_size: mem_size = int(size_info.split()[0].strip()) mem_unit = size_info.split()[1].strip() - if mem_unit.lower() == 'kb': + if mem_unit.lower() == "kb": total_physical_mem += mem_size - elif mem_unit.lower() == 'mb': + elif mem_unit.lower() == "mb": total_physical_mem += mem_size * 1024 - elif mem_unit.lower() == 'gb': + elif mem_unit.lower() == "gb": total_physical_mem += mem_size * 1048576 return total_physical_mem - get_vm_usable_mem(session) @@ -176,6 +179,7 @@ def cal_deviation(actual, expected): """ Calculate deviation of actual result and expected result """ + logging.debug(f"(actual, expected) = ({actual}, {expected})") numerator = float(actual) denominator = float(expected) if numerator > denominator: @@ -187,39 +191,49 @@ 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_outside_mem, expected_inside_mem, - delta_percentage, unusable_mem): + 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_outside_mem, + expected_inside_mem, + delta_percentage, + unusable_mem, + ): """ Print debug message for test """ # Calculate deviation inside_deviation = cal_deviation(test_inside_mem, expected_inside_mem) outside_deviation = cal_deviation(test_outside_mem, expected_outside_mem) - dbgmsg = ("Unusable memory of VM : %d KiB\n" - "Original inside memory : %d KiB\n" - "Expected inside memory : %d KiB\n" - "Actual inside memory : %d KiB\n" - "Inside memory deviation : %0.2f%%\n" - "Original outside memory : %d KiB\n" - "Expected outside memory : %d KiB\n" - "Actual outside memory : %d KiB\n" - "Outside memory deviation: %0.2f%%\n" - "Acceptable deviation : %0.2f%%" % ( - unusable_mem, - original_inside_mem, - expected_inside_mem, - test_inside_mem, - inside_deviation, - original_outside_mem, - expected_outside_mem, - test_outside_mem, - outside_deviation, - delta_percentage)) + dbgmsg = ( + "Unusable memory of VM : %d KiB\n" + "Original inside memory : %d KiB\n" + "Expected inside memory : %d KiB\n" + "Actual inside memory : %d KiB\n" + "Inside memory deviation : %0.2f%%\n" + "Original outside memory : %d KiB\n" + "Expected outside memory : %d KiB\n" + "Actual outside memory : %d KiB\n" + "Outside memory deviation: %0.2f%%\n" + "Acceptable deviation : %0.2f%%" + % ( + unusable_mem, + original_inside_mem, + expected_inside_mem, + test_inside_mem, + inside_deviation, + original_outside_mem, + expected_outside_mem, + test_outside_mem, + outside_deviation, + delta_percentage, + ) + ) for dbgline in dbgmsg.splitlines(): logging.debug(dbgline) @@ -239,9 +253,11 @@ def print_debug_stats(original_inside_mem, original_outside_mem, vm_name = params.get("main_vm", "avocado-vt-vm1") paused_after_start_vm = "yes" == params.get("paused_after_start_vm", "no") manipulate_dom_before_setmem = "yes" == params.get( - "manipulate_dom_before_setmem", "no") + "manipulate_dom_before_setmem", "no" + ) manipulate_dom_after_setmem = "yes" == params.get( - "manipulate_dom_after_setmem", "no") + "manipulate_dom_after_setmem", "no" + ) manipulate_action = params.get("manipulate_action", "") readonly = "yes" == params.get("setmem_readonly", "no") expect_msg = params.get("setmem_err_msg") @@ -250,6 +266,7 @@ def print_debug_stats(original_inside_mem, original_outside_mem, expect_xml_line = params.get("expect_xml_line") expect_qemu_line = params.get("expect_qemu_line") reset_vm_memory = "yes" == params.get("reset_vm_memory", "no") + use_dmidecode = "yes" == params.get("use_dmidecode", "yes") vm = env.get_vm(vm_name) # Back up domain XML @@ -258,15 +275,19 @@ def print_debug_stats(original_inside_mem, original_outside_mem, # filter out reset vm memory on s390x if reset_vm_memory: - vm_attrs = eval(params.get('vm_attrs')) - memory_size = vm_attrs['memory'] - memory_unit = vm_attrs['memory_unit'] + vm_attrs = eval(params.get("vm_attrs")) + memory_size = vm_attrs["memory"] + memory_unit = vm_attrs["memory_unit"] guest_memory = memory_base.convert_data_size( - str(memory_size) + memory_unit, dest_unit='KiB') + str(memory_size) + memory_unit, dest_unit="KiB" + ) host_free_mem = utils_memory.freememtotal() - logging.debug("The allocation memory for guest is %sKiB," - " the total free memory of host is %sKiB.", - guest_memory, host_free_mem) + logging.debug( + "The allocation memory for guest is %sKiB," + " the total free memory of host is %sKiB.", + guest_memory, + host_free_mem, + ) if host_free_mem < guest_memory: test.cancel("There is not enough memory for guest.") @@ -274,12 +295,14 @@ def print_debug_stats(original_inside_mem, original_outside_mem, vmxml.sync() if with_packed and not libvirt_version.version_compare(6, 3, 0): - test.cancel("The virtio packed attribute is not supported in" - " current libvirt version.") + test.cancel( + "The virtio packed attribute is not supported in" + " current libvirt version." + ) vmosxml = vmxml.os need_mkswap = False - if manipulate_action in ['s3', 's4']: + if manipulate_action in ["s3", "s4"]: vm.destroy() BIOS_BIN = "/usr/share/seabios/bios.bin" if os.path.isfile(BIOS_BIN): @@ -299,8 +322,8 @@ def print_debug_stats(original_inside_mem, original_outside_mem, memballoon_model = params.get("memballoon_model", "") if memballoon_model: vm.destroy() - vmxml.del_device('memballoon', by_tag=True) - memballoon_xml = vmxml.get_device_class('memballoon')() + vmxml.del_device("memballoon", by_tag=True) + memballoon_xml = vmxml.get_device_class("memballoon")() memballoon_xml.model = memballoon_model if with_packed: memballoon_xml.driver = {"packed": driver_packed} @@ -323,8 +346,9 @@ def print_debug_stats(original_inside_mem, original_outside_mem, cmd = "rmmod virtio_balloon" s_rmmod, o_rmmod = session.cmd_status_output(cmd) if s_rmmod != 0: - logging.error("Fail to remove module virtio_balloon in guest:\n%s", - o_rmmod) + logging.error( + "Fail to remove module virtio_balloon in guest:\n%s", o_rmmod + ) session.close() # Get original data domid = vm.get_id() @@ -333,11 +357,15 @@ def print_debug_stats(original_inside_mem, original_outside_mem, if not vm.is_alive(): vm.start() session = vm.wait_for_login() - if session.cmd_status('dmidecode') and not utils_package.package_install("dmidecode", session): - # if fail to install dmidecode then use memory size in vm xml - unusable_mem = int(vmxml.memory) - get_vm_usable_mem(session) - else: + if use_dmidecode: + # try make dmidecode available if not present + use_dmidecode &= 0 == session.cmd_status( + "dmidecode" + ) or utils_package.package_install("dmidecode", session) + if use_dmidecode: unusable_mem = vm_unusable_mem(session) + else: + unusable_mem = int(vmxml.memory) - get_vm_usable_mem(session) original_outside_mem = vm.get_used_mem() original_inside_mem = get_vm_usable_mem(session) session.close() @@ -356,10 +384,14 @@ def print_debug_stats(original_inside_mem, original_outside_mem, use_kilobytes = False # Argument pattern is complex, build with dargs - dargs = {'flagstr': flags, - 'use_kilobytes': use_kilobytes, - 'uri': uri, 'ignore_status': True, "debug": True, - 'readonly': readonly} + dargs = { + "flagstr": flags, + "use_kilobytes": use_kilobytes, + "uri": uri, + "ignore_status": True, + "debug": True, + "readonly": readonly, + } dargs.update(make_domref(domarg, vm_ref, domid, vm_name, domuuid)) dargs.update(make_sizeref(sizearg, mem_ref, original_outside_mem)) @@ -378,15 +410,14 @@ def print_debug_stats(original_inside_mem, original_outside_mem, memory_change = True if manipulate_dom_before_setmem: manipulate_domain(test, vm_name, manipulate_action) - if manipulate_action in ['save', 'managedsave', 's4']: + if manipulate_action in ["save", "managedsave", "s4"]: memory_change = False result = virsh.setmem(**dargs) status = result.exit_status if status is 0: - logging.info( - "Waiting %d seconds for VM memory to settle", quiesce_delay) + 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. Therefore, # extremely difficult to determine quiescence, so @@ -448,11 +479,17 @@ def get_vm_mem(): # Don't care about memory comparison on error test def verify_outside_result(): _, test_outside_mem = get_vm_mem() - return (cal_deviation(test_outside_mem, expected_outside_mem) <= delta_percentage) + return ( + cal_deviation(test_outside_mem, expected_outside_mem) + <= delta_percentage + ) def verify_inside_result(): test_inside_mem, _ = get_vm_mem() - return (cal_deviation(test_inside_mem, expected_inside_mem) <= delta_percentage) + return ( + cal_deviation(test_inside_mem, expected_inside_mem) + <= delta_percentage + ) msg = "test conditions not met: " error_flag = 0 @@ -467,10 +504,16 @@ def verify_inside_result(): msg += "Inside memory deviated. " test_inside_mem, test_outside_mem = get_vm_mem() - print_debug_stats(original_inside_mem, original_outside_mem, - test_inside_mem, test_outside_mem, - expected_outside_mem, expected_inside_mem, - delta_percentage, unusable_mem) + print_debug_stats( + original_inside_mem, + original_outside_mem, + test_inside_mem, + test_outside_mem, + expected_outside_mem, + expected_inside_mem, + delta_percentage, + unusable_mem, + ) if error_flag: test.fail(msg) elif not status_error and old_libvirt_fail: @@ -484,7 +527,7 @@ def verify_inside_result(): if status is 0: test.fail("Error test did not result in an error") if expect_msg: - libvirt.check_result(result, expect_msg.split(';')) + libvirt.check_result(result, expect_msg.split(";")) finally: if need_mkswap: vm.cleanup_swap()