From a9408caaa98a0779ee47bd1e165f7101022fcff3 Mon Sep 17 00:00:00 2001 From: Misbah Anjum N Date: Fri, 14 Feb 2025 14:55:25 +0530 Subject: [PATCH 1/8] libvirt-vm: Support for cmdline parameter for --boot Currently, kernel_args is not present in the output of "virt-install --boot help" as "--boot cmdline=%s" is the recommended way of passing kernel command line parameters. As a result, the import/install test is failiing since kernel and initrd parameter is being passed without kernel_args But --boot option supports both kernel_args and cmdline parameter for passing kernel arguments to the guest, i.e, --boot kernel=,initrd=,cmdline= (recommended way) (or) --boot kernel=,initrd=,kernel_args= This patch adds support of reading both cmdline and kernel_args parameter and passes whichever is available from config to the virt-install --boot option Signed-off-by: Misbah Anjum N --- virttest/libvirt_vm.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/virttest/libvirt_vm.py b/virttest/libvirt_vm.py index ee7050f7d3..250a3ae77a 100644 --- a/virttest/libvirt_vm.py +++ b/virttest/libvirt_vm.py @@ -987,6 +987,8 @@ def add_kernel( result += "initrd=%s," % initrd_path if has_sub_option("boot", "kernel_args") and kernel_args: result += 'kernel_args="%s",' % kernel_args + elif has_sub_option("boot", "cmdline") and kernel_args: + result += 'cmdline="%s",' % kernel_args else: result = "" LOG.warning("boot option is not supported") @@ -1450,6 +1452,8 @@ def add_tpmdevice(help_text, device_path, model=None, type=None): kernel = params.get("kernel", None) initrd = params.get("initrd", None) kernel_args = params.get("kernel_args", None) + if not kernel_args: + kernel_args = params.get("cmdline", None) if (kernel or initrd) and kernel_args: virt_install_cmd += add_kernel( help_text, virt_install_cmd, kernel, initrd, kernel_args From ddfc7386f5249b4c913db1d01cee6c31e7195b5f Mon Sep 17 00:00:00 2001 From: Misbah Anjum N Date: Fri, 14 Feb 2025 15:00:52 +0530 Subject: [PATCH 2/8] utils-stress:Update script to take vms parameter This patch will allow us to send vms as paramter to VMStressEvents Through this change, we can specify in which vms we want to run the stress_events If vms parameter is not specified, then default vms from env will be considered Thus, there will not be any error in the dependant files Signed-off-by: Misbah Anjum N --- virttest/utils_stress.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/virttest/utils_stress.py b/virttest/utils_stress.py index 58e61060c9..508e3eb4df 100644 --- a/virttest/utils_stress.py +++ b/virttest/utils_stress.py @@ -16,7 +16,7 @@ class VMStressEvents: - def __init__(self, params, env): + def __init__(self, params, env, vms=None): """ :param params: test param """ @@ -28,7 +28,10 @@ def __init__(self, params, env): self.event_sleep_time = int(params.get("event_sleep_time", 10)) self.itr_sleep_time = int(params.get("itr_sleep_time", 10)) self.ignore_status = params.get("ignore_status", "no") == "yes" - self.vms = env.get_all_vms() + if vms is None: + self.vms = env.get_all_vms() + else: + self.vms = vms self.params = params self.host_events = params.get("host_stress_events", "") if self.host_events: From bc277475a501ce722490c4086eaecf9d3830123b Mon Sep 17 00:00:00 2001 From: Misbah Anjum N Date: Fri, 14 Feb 2025 15:20:27 +0530 Subject: [PATCH 3/8] utils-test:Add htx-cmdline stress_type, fix invalid sequence This patch can be used to run htx mdts stress_type using htxcmdline tool Additionally, this patch fixes DeprecationWarning of invalid escape sequence 'x' W605 This patch introduces the following changes: Allow running of different stress types in different vms based on stress_type_%s parameter if provided in the cfg file, where %s is the name of the vm. This will allow us to introduce additional types of stress in the future. If the stress_type_%s paramter is not provided, then the default stress_type will be used. Define a new function load_htxstress_tool() to run htxcmdline tool in the guest. This function will be called whenever stress_type_vmname = htxcmdline_in_vms. The user can provide the link to the .rpm/.deb package and the function will handle the installation, followed by the running of the htxcmdline tool by using the htxcmdline_args parameter, all provided by user in the cfg file. Signed-off-by: Misbah Anjum N --- virttest/utils_test/__init__.py | 117 +++++++++++++++++++++++++------- 1 file changed, 91 insertions(+), 26 deletions(-) diff --git a/virttest/utils_test/__init__.py b/virttest/utils_test/__init__.py index d687fccbaf..7c4db826d8 100755 --- a/virttest/utils_test/__init__.py +++ b/virttest/utils_test/__init__.py @@ -371,10 +371,10 @@ def get_time(session, time_command, time_filter_re, time_format): msg += "'%s', output: %s" % (time_command, output) raise exceptions.TestError(msg) if re.search("PM|AM", guest_time): - hour = re.findall("\d+ (\d+):", guest_time)[0] + hour = re.findall(r"\d+ (\d+):", guest_time)[0] fix = 12 if re.search("PM", guest_time) else 0 hour = str(int(hour) % 12 + fix) - guest_time = re.sub("\s\d+:", " %s:" % hour, guest_time)[:-3] + guest_time = re.sub(r"\s\d+:", " %s:" % hour, guest_time)[:-3] else: guest_time = guest_time[:-3] guest_time = time.mktime(time.strptime(guest_time, time_format)) @@ -764,7 +764,7 @@ def transfer_data(session, host_cmd, guest_cmd, n_time, timeout, md5_check, acti else: LOG.warning(err) else: - md5_re = "md5_sum = (\w{32})" + md5_re = r"md5_sum = (\w{32})" try: md5_guest = re.findall(md5_re, g_output)[0] except Exception: @@ -784,7 +784,7 @@ def transfer_data(session, host_cmd, guest_cmd, n_time, timeout, md5_check, acti else: LOG.warning(err) else: - md5_re = "md5_sum = (\w{32})" + md5_re = r"md5_sum = (\w{32})" try: md5_host = re.findall(md5_re, output)[0] except Exception: @@ -1395,10 +1395,10 @@ def extract(vm, remote_path, dest_dir): def get_last_guest_results_index(): res_index = 0 for subpath in os.listdir(outputdir): - if re.search("guest_autotest_results\d+", subpath): + if re.search(r"guest_autotest_results\d+", subpath): res_index = max( res_index, - int(re.search("guest_autotest_results(\d+)", subpath).group(1)), + int(re.search(r"guest_autotest_results(\d+)", subpath).group(1)), ) return res_index @@ -1954,7 +1954,7 @@ def summary_up_result(result_file, ignore, row_head, column_mark): if len(re.findall(column_mark, eachLine)) != 0 and not head_flag: column = 0 _, row, eachLine = re.split(row_head, eachLine) - for i in re.split("\s+", eachLine): + for i in re.split(r"\s+", eachLine): if i: result_dict[i] = {} column_list[column] = i @@ -1971,7 +1971,7 @@ def summary_up_result(result_file, ignore, row_head, column_mark): row_list.append(row) for i in result_dict: result_dict[i][row] = [] - for i in re.split("\s+", eachLine): + for i in re.split(r"\s+", eachLine): if i: result_dict[column_list[column]][row].append(i) column += 1 @@ -2218,6 +2218,7 @@ def __init__( self.stress_wait_for_timeout = int( self.params.get("stress_wait_for_timeout", 60) ) + stress_type = stress_type.split('_')[0] self.stress_type = stress_type stress_cmds = stress_cmds or stress_type self.stress_cmds = self.params.get("stress_cmds_%s" % stress_type, stress_cmds) @@ -2292,6 +2293,45 @@ def load_stress_tool(self): ): raise exceptions.TestError("Stress app does not " "running as expected") + @session_handler + def load_htxstress_tool(self): + """ + load stress tool in guest + """ + # install htx strss tool + remove_old_package = "cd " + self.dst_path + " && rm -rf " + self.base_name + get_stress = "cd " + self.dst_path + " && wget " + self.download_url + if "rpm" in self.base_name: + install_stress = "cd " + self.dst_path + " && rpm -i " + self.base_name + elif "deb" in self.base_name: + install_stress = "cd " + self.dst_path + " && dpkg -i " + self.base_name + else: + raise exceptions.TestError("Could not install htx stress tool") + LOG.info("Installing htx rpm/deb in the guest") + self.cmd(remove_old_package) + self.cmd(get_stress) + self.cmd(install_stress) + + # start htx stress + launch_cmds = "nohup %s %s > /dev/null &" % (self.stress_cmds, self.stress_args) + LOG.info("Launch stress with command: %s", launch_cmds) + try: + self.cmd_launch(launch_cmds) + # The background process sometimes does not return to + # terminate, if timeout, send a blank line afterward + except aexpect.ShellTimeoutError: + self.cmd_launch("") + + # wait for stress to start and then check, if not raise TestError + if not utils_misc.wait_for( + self.app_running, + self.stress_wait_for_timeout, + first=2.0, + text="wait for stress app to start", + step=1.0, + ): + raise exceptions.TestError("Stress app does not " "running as expected") + @session_handler def unload_stress(self): """ @@ -2672,25 +2712,50 @@ def load_stress( :param download_type: currently support "git" or "file" download """ fail_info = [] - # Add stress/iozone tool in vms - if stress_type in ["stress_in_vms", "iozone_in_vms"]: + default_stress_type = stress_type + if stress_type in ["stress_in_vms", "iozone_in_vms", "htxcmdline_in_vms"]: for vm in vms: - try: - vstress = VMStress( - vm, - stress_type.split("_")[0], - params, - download_url, - make_cmds, - stress_cmds, - stress_args, - work_path, - uninstall_cmds, - download_type=download_type, - ) - vstress.load_stress_tool() - except StressError as detail: - fail_info.append("Launch stress in %s failed: %s" % (vm.name, detail)) + stress_type = params.get("stress_type_%s" % vm.name, default_stress_type) + if stress_type == "htxcmdline_in_vms": + # Add htx stress tool in vms + try: + vstress = VMStress( + vm, + stress_type.split("_")[0], + params, + download_url, + make_cmds, + stress_cmds, + stress_args, + work_path, + uninstall_cmds, + download_type=download_type, + ) + vstress.load_htxstress_tool() + except StressError as detail: + fail_info.append( + "Launch htxstress in %s failed: %s" % (vm.name, detail) + ) + else: + # Add stress/iozone tool in vms + try: + vstress = VMStress( + vm, + stress_type.split("_")[0], + params, + download_url, + make_cmds, + stress_cmds, + stress_args, + work_path, + uninstall_cmds, + download_type=download_type, + ) + vstress.load_stress_tool() + except StressError as detail: + fail_info.append( + "Launch stress in %s failed: %s" % (vm.name, detail) + ) # Add stress for host elif stress_type == "stress_on_host" or stress_type == "stress_on_remote_host": try: From 43ba57f24816cfb8b2f58e6d074a3ba0a9c09346 Mon Sep 17 00:00:00 2001 From: Tasmiya Nalatwad Date: Fri, 14 Feb 2025 16:23:14 +0530 Subject: [PATCH 4/8] Login timeout fix Signed-off-by: Tasmiya Nalatwad --- virttest/libvirt_vm.py | 10 ++++++++++ virttest/utils_net.py | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/virttest/libvirt_vm.py b/virttest/libvirt_vm.py index 250a3ae77a..b8f3220f12 100644 --- a/virttest/libvirt_vm.py +++ b/virttest/libvirt_vm.py @@ -31,6 +31,7 @@ test_setup, utils_logfile, utils_misc, + utils_net, utils_package, utils_selinux, virsh, @@ -379,6 +380,15 @@ def backup_xml(self, active=False): LOG.error("Failed to backup xml file:\n%s", detail) return "" + def _get_address(self, index=0, ip_version="ipv4", session=None, timeout=60.0): + try: + return super()._get_address(index, ip_version, session, timeout) + except virt_vm.VMIPAddressMissingError: + mac = self.get_mac_address(index).lower() + ipaddr = utils_net.obtain_guest_ip_from_dhcp_leases(mac) + self.address_cache[mac] = ipaddr + return ipaddr + def clone( self, name=None, diff --git a/virttest/utils_net.py b/virttest/utils_net.py index 74bfe73b58..aa6e1bcf4e 100644 --- a/virttest/utils_net.py +++ b/virttest/utils_net.py @@ -35,6 +35,7 @@ utils_misc, utils_package, utils_selinux, + virsh, ) from virttest.remote import RemoteRunner from virttest.staging import service, utils_memory @@ -4902,3 +4903,20 @@ def check_class_rules(ifname, rule_id, bandwidth, expect_none=False): stacktrace.log_exc_info(sys.exc_info()) return False return True + +def obtain_guest_ip_from_dhcp_leases(mac): + """ + Obtaining the guest ip address from virsh-net-dhcp-leases command + :param: Mac address of the guest + :return: return ip-address if found for given mac in the + virsh-net-dhcp-leases default table, else return None + """ + output = virsh.net_dhcp_leases("default") + lines = output.stdout.splitlines() + for line in lines: + if mac in line: + parts = line.split() + for part in parts: + if "/" in part: + return part.split("/")[0] + return None From fdb3a0322f002932f9fcdefa87f599fc373bb0e9 Mon Sep 17 00:00:00 2001 From: Misbah Anjum N Date: Wed, 26 Feb 2025 17:22:27 +0530 Subject: [PATCH 5/8] Fix Error from PR#1 utils_net.py --- virttest/utils_net.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/virttest/utils_net.py b/virttest/utils_net.py index aa6e1bcf4e..0b4f7b2dbb 100644 --- a/virttest/utils_net.py +++ b/virttest/utils_net.py @@ -4912,7 +4912,7 @@ def obtain_guest_ip_from_dhcp_leases(mac): virsh-net-dhcp-leases default table, else return None """ output = virsh.net_dhcp_leases("default") - lines = output.stdout.splitlines() + lines = output.stdout.splitlines() for line in lines: if mac in line: parts = line.split() From f2383792ff415419328a82faadc1cc0e552905f0 Mon Sep 17 00:00:00 2001 From: Misbah Anjum N Date: Wed, 26 Feb 2025 19:11:21 +0530 Subject: [PATCH 6/8] Update KVMCI libvirt link to lop-devops/tp-libvirt Change the KVMCI avocado-vt repo tp-libvirt link from autotest/tp-libvirt to lop-devops/tp-libvirt to support KVMCI workflows Signed-off-by: Misbah Anjum N --- virttest/test-providers.d/io-github-autotest-libvirt.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/virttest/test-providers.d/io-github-autotest-libvirt.ini b/virttest/test-providers.d/io-github-autotest-libvirt.ini index 075bce242a..a43e75179e 100644 --- a/virttest/test-providers.d/io-github-autotest-libvirt.ini +++ b/virttest/test-providers.d/io-github-autotest-libvirt.ini @@ -1,5 +1,6 @@ [provider] -uri: https://github.com/autotest/tp-libvirt.git +uri: https://github.com/lop-devops/tp-libvirt.git +branch: KVMCI [libvirt] subdir: libvirt/ [libguestfs] From cfef601a784e89392ae927a43a24c4ab0d43f69e Mon Sep 17 00:00:00 2001 From: Misbah Anjum N Date: Sat, 1 Mar 2025 01:31:26 +0530 Subject: [PATCH 7/8] Fix Error from PR#1 libvirt_vm.py --- virttest/libvirt_vm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/virttest/libvirt_vm.py b/virttest/libvirt_vm.py index b8f3220f12..22b0f2d63d 100644 --- a/virttest/libvirt_vm.py +++ b/virttest/libvirt_vm.py @@ -386,7 +386,7 @@ def _get_address(self, index=0, ip_version="ipv4", session=None, timeout=60.0): except virt_vm.VMIPAddressMissingError: mac = self.get_mac_address(index).lower() ipaddr = utils_net.obtain_guest_ip_from_dhcp_leases(mac) - self.address_cache[mac] = ipaddr + self.address_cache[mac] = ipaddr return ipaddr def clone( From ae479d14659da437cced91d0919cb43f3c61d0e4 Mon Sep 17 00:00:00 2001 From: Tasmiya Nalatwad Date: Wed, 5 Mar 2025 18:51:38 +0530 Subject: [PATCH 8/8] Patch to get the location code of any pci device Location code is used to trigger eeh injections on any pci device in kvm environment Patch is used to get the location code of the pci devices using there pci id's Signed-off-by: Tasmiya Nalatwad --- virttest/utils_misc.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/virttest/utils_misc.py b/virttest/utils_misc.py index 356cf1931c..d2619f91a1 100644 --- a/virttest/utils_misc.py +++ b/virttest/utils_misc.py @@ -4599,3 +4599,28 @@ def _md5(fd): if _md5(fd_a) == _md5(fd_b): return True return False + + +def get_location_code(pci_id): + """ + Retrieves the location code for a PCI device using the `cat` command. + :param device : The PCI device address in the format 'xxxx:xx:xx.x'. + :return: location code if available, or an error message. + """ + try: + # Construct the path + pci_id = pci_id.replace(":", "\\:") + loc_code_path = "/sys/bus/pci/devices/%s/of_node/ibm,loc-code" % pci_id + + # Execute the cat command and capture the output + loc_code = process.run("cat %s" % loc_code_path, shell=True) + loc_code = "".join( + c for c in loc_code.stdout_text.strip() if 0x20 <= ord(c) <= 0x7E + ) + logging.debug("The location code of the pci device is %s" % loc_code) + return loc_code + + except FileNotFoundError: + return "Location code file not found for device %s." % pci_id + except Exception as e: + return "An error occurred: %s" % e