From e120b54a390142fe10445c9c31c6dc482114bf93 Mon Sep 17 00:00:00 2001 From: Hu Shuai Date: Mon, 5 Dec 2022 18:04:51 +0800 Subject: [PATCH 0001/1055] incremental_backup: Fix backup job not canceled issue Based on #3625, genereate more data to slow down backup process. Signed-off-by: Hu Shuai --- .../cfg/incremental_backup/incremental_backup_push_mode.cfg | 6 ++++-- .../src/incremental_backup/incremental_backup_push_mode.py | 5 +---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg b/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg index 82c31862016..eb3d2f89a97 100644 --- a/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg +++ b/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg @@ -33,11 +33,13 @@ - destroy_vm: only original_disk_local.coldplug_disk.backup_to_raw.backup_to_block expect_backup_canceled = "yes" - original_disk_size = "1000M" + original_disk_size = "5000M" + dd_count = "4000" - kill_qemu: only original_disk_local.hotplug_disk.backup_to_qcow2.backup_to_block expect_backup_canceled = "yes" - original_disk_size = "1000M" + original_disk_size = "5000M" + dd_count = "4000" - positive_test: variants: - backup_to_qcow2: diff --git a/libvirt/tests/src/incremental_backup/incremental_backup_push_mode.py b/libvirt/tests/src/incremental_backup/incremental_backup_push_mode.py index 1c595c59f99..ba4604d4280 100644 --- a/libvirt/tests/src/incremental_backup/incremental_backup_push_mode.py +++ b/libvirt/tests/src/incremental_backup/incremental_backup_push_mode.py @@ -253,10 +253,7 @@ def backup_job_done(vm_name, vm_disk): backup_options = backup_xml.xml + " " + checkpoint_xml.xml # Create some data in vdb - dd_count = "1" - if expect_backup_canceled: - # Generate more data to extend the backup job duration - dd_count = "100" + dd_count = params.get("dd_count", "1") dd_seek = str(backup_index * 10 + 10) dd_bs = "1M" session = vm.wait_for_login() From 575cb64249819e4042de31ee8d8708ca65dfe1c0 Mon Sep 17 00:00:00 2001 From: Anushree Mathur Date: Wed, 13 Sep 2023 01:49:28 +0530 Subject: [PATCH 0002/1055] External snapshot deletion failure modification! In libvirt version lesser than 9.0.0 external snapshot deletion was unsupported, but the testcase is failing now with the error message as "Snapshot delete succeed but expect fail" because the deletion is supported now with external disk. For reference : https://libvirt.org/news.html#v9-0-0-2023-01-16 Signed-off-by: Anushree Mathur --- libvirt/tests/src/virsh_cmd/snapshot/virsh_snapshot_disk.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/snapshot/virsh_snapshot_disk.py b/libvirt/tests/src/virsh_cmd/snapshot/virsh_snapshot_disk.py index 3f7a26e4149..b54105d8da5 100644 --- a/libvirt/tests/src/virsh_cmd/snapshot/virsh_snapshot_disk.py +++ b/libvirt/tests/src/virsh_cmd/snapshot/virsh_snapshot_disk.py @@ -422,7 +422,7 @@ def run(test, params, env): session.close() # Test delete snapshot without "--metadata", delete external disk - # snapshot will fail for now. + # External snapshot deletion support added in libvirt_version >= 9.0.0 # Only do this when snapshot create succeed which filtered in cfg file. if snapshot_del_test: if snapshot_name: @@ -439,7 +439,7 @@ def run(test, params, env): test.fail("Snapshot xml file %s missing" % snap_xml_path) else: - if status_error: + if (not libvirt_version.version_compare(9, 0, 0)) and status_error: err_msg = "Snapshot delete succeed but expect fail." test.fail(err_msg) else: From 1202e20130e8dff637025468c513794af6a09c59 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Wed, 13 Sep 2023 02:03:58 -0400 Subject: [PATCH 0003/1055] Add case to cover default audit level and concurrent filters RHEL7-xx - [audit log] Use default audit_level or set audit level=1 when enable auditing on host RHEL-xx: [libvirtd log] Check "first" match performance if there are concurrent filters Signed-off-by: chunfuwen --- .../libvirtd_conf/set_audit_logging.cfg | 15 ++++- .../libvirtd_conf/set_audit_logging.py | 66 ++++++++++++++++--- 2 files changed, 70 insertions(+), 11 deletions(-) diff --git a/libvirt/tests/cfg/daemon/conf_file/libvirtd_conf/set_audit_logging.cfg b/libvirt/tests/cfg/daemon/conf_file/libvirtd_conf/set_audit_logging.cfg index 2178b2a1b0a..6892a29cae0 100644 --- a/libvirt/tests/cfg/daemon/conf_file/libvirtd_conf/set_audit_logging.cfg +++ b/libvirt/tests/cfg/daemon/conf_file/libvirtd_conf/set_audit_logging.cfg @@ -3,8 +3,21 @@ start_vm = no variants: - positive_test: - variants: + variants test_scenario: - disable_audit_log: enable_audit = no - enable_audit_log: enable_audit = yes + - default_audit_log: + enable_audit = yes + set_audit_level = "no" + ausearch_type_list = "VIRT_CONTROL VIRT_MACHINE_ID VIRT_RESOURCE" + - concurrent_filters: + enable_audit = yes + set_audit_level = "no" + log_filters="1:qemu 1:libvirt 4:object 4:json 4:event 1:util" + log_for_object = 'debug : virObject|info : virObject|warning : virObject' + log_for_json = 'debug : virJSON|info : virJSON|warning : virJSON' + log_for_event = 'debug : virEvent|info : virEvent|warning : virEvent' + log_for_filter_list = "["${log_for_object}", "${log_for_json}", "${log_for_event}"]" + log_for_util = 'virConf' diff --git a/libvirt/tests/src/daemon/conf_file/libvirtd_conf/set_audit_logging.py b/libvirt/tests/src/daemon/conf_file/libvirtd_conf/set_audit_logging.py index f2d45800830..e15272b3c7b 100644 --- a/libvirt/tests/src/daemon/conf_file/libvirtd_conf/set_audit_logging.py +++ b/libvirt/tests/src/daemon/conf_file/libvirtd_conf/set_audit_logging.py @@ -7,6 +7,7 @@ from virttest import data_dir from virttest import utils_libvirtd from virttest import utils_split_daemons +from virttest import virt_vm from virttest.utils_test import libvirt @@ -26,17 +27,25 @@ def run(test, params, env): """ # Here it needs manipulate libvird config as test step, so it doesn't use default config # enabled by avocado-vt framework at start - def config_libvirtd_log(enable_audit_logging=False): + def config_libvirtd_log(params): """ Configure audit log level" - :param enable_audit_logging: bool indicating enable/disable audit_logging + :param params: one dict wrapping parameters """ + # enable/disable audit_logging + enable_audit_logging = "yes" == params.get("enable_audit", "no") + # set audit level or not + set_audit_level = "yes" == params.get("set_audit_level", "yes") + log_filters = params.get('log_filters') libvirtd_config.log_outputs = "1:file:%s" % log_config_path libvirtd_config.log_level = 1 - libvirtd_config.audit_level = 1 + if set_audit_level: + libvirtd_config.audit_level = 1 if enable_audit_logging: libvirtd_config.audit_logging = 1 + if log_filters: + libvirtd_config.log_filters = log_filters utils_libvirtd.Libvirtd('virtqemud').restart() def ensure_auditd_started(): @@ -60,9 +69,9 @@ def check_virt_type_from_audit_log(): def clean_up_audit_log_file(): """ - Clean up audit message in log file. + Clean up audit message under /var/log/audit/. """ - cmd = "> /var/log/audit/audit.log; > %s" % log_config_path + cmd = "truncate -s 0 /var/log/audit/*" process.run(cmd, ignore_status=False, shell=True) @@ -75,28 +84,65 @@ def check_msg_in_libvirtd_log(str_to_grep): if not libvirt.check_logfile(str_to_grep, log_config_path, str_in_log=enable_audit_logging): test.fail("Check message log:%s failed in log file:%s" % (str_to_grep, log_config_path)) + def ausearch_audit_log(): + """ + Check ausearch output related to audit + + """ + ausearch_type_list = params.get("ausearch_type_list").split() + for type_item in ausearch_type_list: + cmd = "ausearch -m %s -ts recent" % type_item + type_message = "type=%s msg=audit" % type_item + cmd_result = process.run(cmd, shell=True).stdout_text.strip() + if type_message not in cmd_result: + test.fail("Check ausearch type:%s log failed in output:%s" % (type_item, cmd_result)) + + def check_concurrent_filters(): + """ + Check concurrent filters + + """ + log_for_util = params.get("log_for_util") + if not libvirt.check_logfile(log_for_util, log_config_path, str_in_log=True): + test.fail("Can not find expected message :%s in log file:%s" % (log_for_util, log_config_path)) + log_for_filter_list = eval(params.get("log_for_filter_list")) + for filter in log_for_filter_list: + str_to_grep = "%s" % filter + if not libvirt.check_logfile(str_to_grep, log_config_path, str_in_log=False): + test.fail("Find unexpected message :%s in log file:%s" % (str_to_grep, log_config_path)) + vm_name = params.get("main_vm", "avocado-vt-vm1") vm = env.get_vm(vm_name) enable_audit_logging = "yes" == params.get("enable_audit", "no") + set_audit_level = "yes" == params.get("set_audit_level", "yes") # Get LibvirtdConfig or VirtQemuConfig log_config_path = os.path.join(data_dir.get_tmp_dir(), "libvirtd.log") libvirtd_config = VirtQemudConfig() if utils_split_daemons.is_modular_daemon() else LibvirtdConfig() + test_scenario = params.get("test_scenario") + try: # Need stop VM first if vm.is_alive(): vm.destroy() - config_libvirtd_log(enable_audit_logging) + config_libvirtd_log(params) # Clean up old audit message from log file clean_up_audit_log_file() - # Check and start audit daemon service if necessary ensure_auditd_started() - vm.start() - check_virt_type_from_audit_log() - check_msg_in_libvirtd_log("virDomainAudit") + except virt_vm.VMStartError as e: + test.fail("VM failed to start." + "Error: %s" % str(e)) + else: + if test_scenario in ["disable_audit_log", "enable_audit_log"]: + check_virt_type_from_audit_log() + check_msg_in_libvirtd_log("virDomainAudit") + elif test_scenario == "default_audit_log": + ausearch_audit_log() + elif test_scenario == "concurrent_filters": + check_concurrent_filters() finally: libvirtd_config.restore() utils_libvirtd.Libvirtd('virtqemud').restart() From f8fc3c1829cc4474443ddaa8f08069dd2f10eb09 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Mon, 18 Sep 2023 05:02:25 -0400 Subject: [PATCH 0004/1055] guest_os_booing: add new case for sysinfo fwcfg feature It mainly implements the function of sysinfo fwcfg feature. Signed-off-by: Meina Li --- .../firmware_configuration/sysinfo_fwcfg.cfg | 28 +++++++ .../firmware_configuration/sysinfo_fwcfg.py | 77 +++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 libvirt/tests/cfg/guest_os_booting/firmware_configuration/sysinfo_fwcfg.cfg create mode 100644 libvirt/tests/src/guest_os_booting/firmware_configuration/sysinfo_fwcfg.py diff --git a/libvirt/tests/cfg/guest_os_booting/firmware_configuration/sysinfo_fwcfg.cfg b/libvirt/tests/cfg/guest_os_booting/firmware_configuration/sysinfo_fwcfg.cfg new file mode 100644 index 00000000000..a9d57e5fe1c --- /dev/null +++ b/libvirt/tests/cfg/guest_os_booting/firmware_configuration/sysinfo_fwcfg.cfg @@ -0,0 +1,28 @@ +- guest_os_booting.sysinfo_fwcfg: + type = sysinfo_fwcfg + start_vm = no + entry_value = "example value" + variants: + - positive_test: + variants: + - with_entry_value: + entry_name = "opt/com.example/name" + fwcfg_dict = {'type': 'fwcfg', 'entry_name': '%s', 'entry': '${entry_value}'} + - with_entry_file: + entry_file = "yes" + entry_name = "opt/com.coreos/config" + file_name = "provision.ign" + fwcfg_dict = {'type': 'fwcfg', 'entry_name': '%s', 'entry_file': '%s'} + - negative_test: + fwcfg_dict = {'type': 'fwcfg', 'entry_name': '%s', 'entry': '${entry_value}'} + variants: + - with_missing_value: + entry_name = "opt/com.rhel/name" + fwcfg_dict = {'type': 'fwcfg', 'entry_name': '%s'} + error_msg = "Firmware entry must have either value or 'file' attribute" + - without_correct_prefix: + entry_name = "tmp/com.rhel/name" + error_msg = "Invalid firmware name" + - with_exist_name: + entry_name = "opt/org.qemu/" + error_msg = "That firmware name is reserved" diff --git a/libvirt/tests/src/guest_os_booting/firmware_configuration/sysinfo_fwcfg.py b/libvirt/tests/src/guest_os_booting/firmware_configuration/sysinfo_fwcfg.py new file mode 100644 index 00000000000..bb17ffa2baf --- /dev/null +++ b/libvirt/tests/src/guest_os_booting/firmware_configuration/sysinfo_fwcfg.py @@ -0,0 +1,77 @@ +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Meina Li +# +import os + +from virttest import data_dir +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml import xcepts + +from provider.guest_os_booting import guest_os_booting_base as guest_os + + +def run(test, params, env): + """ + This case is to verify the sysinfo fwcfg feature. + 1) Prepare a guest with sysinfo fwcfg xml. + 2) Start the guest. + 3) Check the config in guest. + """ + + def result_check(): + """ + Check the firmware config in guest + """ + session = vm.wait_for_login() + test_cmd = ("grep \"%s\" /sys/firmware/qemu_fw_cfg/by_name/%s/raw" + % (entry_value, entry_name)) + status, output = session.cmd_status_output(test_cmd) + if status != 0: + test.fail("Failed due to: %s" % output) + session.close() + + vm_name = params.get("main_vm") + entry_name = params.get("entry_name") + entry_value = params.get("entry_value") + file_name = params.get("file_name") + entry_file = "yes" == params.get("entry_file", "no") + error_msg = params.get("error_msg") + + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + if entry_file: + file_path = os.path.join(data_dir.get_data_dir(), file_name) + entry_value = "This is a new feature" + with open(file_path, 'w') as file: + file.write(entry_value) + fwcfg_dict = eval(params.get("fwcfg_dict") % (entry_name, file_path)) + else: + fwcfg_dict = eval(params.get("fwcfg_dict") % entry_name) + + vmxml.setup_attrs(sysinfo=fwcfg_dict) + vmxml.sync() + guest_os.check_vm_startup(vm, vm_name) + test.log.info("The current dumpxml is %s.", vmxml) + result_check() + # Except condition for the vmxml.sync() step. + except xcepts.LibvirtXMLError as xml_error: + if error_msg and error_msg in str(xml_error): + test.log.info("Get expected error message: %s.", error_msg) + else: + test.fail("Failed to define the guest because error:%s" % xml_error) + + finally: + if vm.is_alive(): + vm.destroy(vm_name) + if entry_file and os.path.exists(file_path): + os.remove(file_path) + bkxml.sync() From 32ff4cb16a390dc5d7c714e049d750e48296e7de Mon Sep 17 00:00:00 2001 From: Hu Shuai Date: Wed, 1 Nov 2023 11:50:56 +0800 Subject: [PATCH 0005/1055] memory: Enable test for aarch64 Update hugepagesize and kernel pagesize for aarch64 Signed-off-by: Hu Shuai --- .../memory/memory_backing/page_locking_and_shared_pages.cfg | 6 ++++++ .../memory/memory_backing/page_locking_and_shared_pages.py | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_backing/page_locking_and_shared_pages.cfg b/libvirt/tests/cfg/memory/memory_backing/page_locking_and_shared_pages.cfg index cce39d35813..cffff2f10f6 100644 --- a/libvirt/tests/cfg/memory/memory_backing/page_locking_and_shared_pages.cfg +++ b/libvirt/tests/cfg/memory/memory_backing/page_locking_and_shared_pages.cfg @@ -3,6 +3,9 @@ start_vm = no pagesize = 2048 pagenum = 1024 + aarch64: + pagesize = 524288 + pagenum = 4 expect_exist = True variants lock_config: - lock_default: @@ -26,6 +29,9 @@ ksm_qemu_line = "mem-merge=off" variants page_config: - page_default: + kernel_pagesize = 4 + aarch64: + kernel_pagesize = 64 - hugepage: hugepages_dict = "'hugepages': {}" variants: diff --git a/libvirt/tests/src/memory/memory_backing/page_locking_and_shared_pages.py b/libvirt/tests/src/memory/memory_backing/page_locking_and_shared_pages.py index 7490cdd0505..abc68f67731 100644 --- a/libvirt/tests/src/memory/memory_backing/page_locking_and_shared_pages.py +++ b/libvirt/tests/src/memory/memory_backing/page_locking_and_shared_pages.py @@ -97,9 +97,9 @@ def run_test(): return else: if page_config == "page_default": - if (nr_unevictable_2 - nr_unevictable)*4 < mem_value: + if (nr_unevictable_2 - nr_unevictable)*kernel_pagesize < mem_value: test.fail("Unevictable memory pages should less than %d" % mem_value) - if (lock_pages_2 - lock_pages)*4 < mem_value: + if (lock_pages_2 - lock_pages)*kernel_pagesize < mem_value: test.fail("Locked memory pages should less than %d" % mem_value) elif page_config == "hugepage": if (nr_unevictable_2 - nr_unevictable) < 0: @@ -139,6 +139,7 @@ def teardown_test(): qemu_line = eval(params.get("qemu_line")) hard_limit = int(params.get("hard_limit", 0)) mem_value = int(params.get("mem_value", '')) + kernel_pagesize = int(params.get("kernel_pagesize", 0)) lock_dict = params.get("lock_dict", "") tune_dict = eval(params.get("tune_dict", "{}")) From f8ec95a7e7a43b7b1bef96432046e4f6f77cac97 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Thu, 2 Nov 2023 10:23:38 -0400 Subject: [PATCH 0006/1055] migration: test rng device updates with --xml 1. Test that changing the alias works 2. Test that changing the address fails gracefully Signed-off-by: Sebastian Mitterle --- .../cfg/migration/migration_xml_update.cfg | 48 +++++++++ .../src/migration/migration_xml_update.py | 102 ++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 libvirt/tests/cfg/migration/migration_xml_update.cfg create mode 100644 libvirt/tests/src/migration/migration_xml_update.py diff --git a/libvirt/tests/cfg/migration/migration_xml_update.cfg b/libvirt/tests/cfg/migration/migration_xml_update.cfg new file mode 100644 index 00000000000..5a227d9227f --- /dev/null +++ b/libvirt/tests/cfg/migration/migration_xml_update.cfg @@ -0,0 +1,48 @@ +- migration.xml_update: + type = migration_xml_update + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = "" + # SSH connection time out + ssh_timeout = 60 + start_vm = "yes" + virsh_migrate_dest_state = running + virsh_migrate_src_state = running + # Local URI + virsh_migrate_connect_uri = "qemu:///system" + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + status_error = "no" + transport_type = "ssh" + virsh_migrate_desturi = "qemu+ssh://${migrate_dest_host}/system" + variants: + - positive: + variants: + - update_rng_alias: + remove_all = rng + add_device = {"rng_model": "virtio", "backend": {"backend_model": "builtin"}} + status_error = no + modify = alias + - negative: + variants: + - update_rng_address: + remove_all = rng + add_device = {"rng_model": "virtio", "backend": {"backend_model": "builtin"}} + status_error = yes + err_msg = "unsupported configuration" + modify = address + new_address =
+ s390-virtio: + new_address =
+ diff --git a/libvirt/tests/src/migration/migration_xml_update.py b/libvirt/tests/src/migration/migration_xml_update.py new file mode 100644 index 00000000000..650a55a9742 --- /dev/null +++ b/libvirt/tests/src/migration/migration_xml_update.py @@ -0,0 +1,102 @@ +import logging as log +import tempfile +from xml.etree import ElementTree + +from virttest import data_dir +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml + +from provider.migration import base_steps + +logging = log.getLogger('avocado.' + __name__) + + +def prepare_vm(vm, vm_name, vmxml, params): + """ + Prepares the VM by adding the device under test + + :param vm: The VM object + :param vm_name: The VM name + :param vmxml: The VM XML + :param params: The test parameters + """ + + if vm.is_alive(): + vm.destroy() + dev_type = params.get("remove_all") + vmxml.remove_all_device_by_type(dev_type) + vmxml.sync() + dev_dir = eval(params.get("add_device")) + dev = libvirt_vmxml.create_vm_device_by_type(dev_type, dev_dir) + virsh.attach_device(vm_name, dev.xml, flagstr="--config", debug="True") + + +def create_migration_xml(test, vm_name, params): + """ + Creates the xml to be passed to '--xml' option + + :param test: The test object + :param vm_name: The VM name + :param params: The Test parameters + """ + tmp_file = xml_file = tempfile.mktemp(dir=data_dir.get_tmp_dir()) + params['virsh_migrate_extra'] = "--xml %s" % tmp_file + xmlout = virsh.dumpxml(vm_name, "--migratable", debug=True).stdout_text.strip() + vmxml = ElementTree.fromstring(xmlout) + modify = params.get("modify") + dev = vmxml.find(".//" + params.get("remove_all")) + if modify == "alias": + alias = ElementTree.SubElement(dev, "alias") + alias.attrib['name'] = "ua-otherName" + elif modify == "address": + new_address = ElementTree.fromstring(params.get("new_address")) + old_address = dev.find("address") + dev.remove(old_address) + dev.append(new_address) + ElementTree.ElementTree(vmxml).write(tmp_file) + + +def check_alias(vm_name, params, test): + """ + Checks if the alias on the destination is as set + in migration xml. + + :param vm_name: The VM name + :param params: The test parameters + :param test: The test object + """ + dest_xml = virsh.dumpxml(vm_name, uri=params.get("virsh_migrate_desturi")).stdout_text + if "ua-otherName" not in dest_xml: + test.fail("Expected rng alias 'ua-otherName' not found in " + "destination xml: %s" % dest_xml) + + +def run(test, params, env): + """ + Tests migration behavior when the destination xml + is altered for a device. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + + vm_name = params.get("migrate_main_vm") + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + backup_xml = vmxml.copy() + + prepare_vm(vm, vm_name, vmxml, params) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + migration_obj.setup_connection() + create_migration_xml(test, vm_name, params) + migration_obj.run_migration() + if params.get("modify") == "alias": + check_alias(vm_name, params, test) + finally: + migration_obj.cleanup_connection() + backup_xml.sync() From 98b0aea4907ad48be687dd1b1d688c01a6f98de6 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Sun, 5 Nov 2023 22:00:34 -0500 Subject: [PATCH 0007/1055] Fix scsi_hostdev.positive.qemu_pr_helper case failure Since it use uniform pattern: run_test_case(test, params, env) to trigger test method, so all test method has 3 parameters Signed-off-by: chunfuwen --- libvirt/tests/src/scsi/scsi_device.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/scsi/scsi_device.py b/libvirt/tests/src/scsi/scsi_device.py index 06a299ca7e1..9ebf4c23829 100644 --- a/libvirt/tests/src/scsi/scsi_device.py +++ b/libvirt/tests/src/scsi/scsi_device.py @@ -477,14 +477,16 @@ def check_hostdev_shareable_attr(test, params): test.fail("VM: % failed to find shareable attribute in output: %s" % (vm_name, str(hostdev_xml))) -def test_coldplug_scsi_hostdev_qemu_pr_helper(test, params): +def test_coldplug_scsi_hostdev_qemu_pr_helper(test, params, env): """ Test coldplug scsi hostdev and check qemu-pr-helper status :param test: one test object instance :param params: dict wrapped with params + :param env: environment instance """ vm_name = params.get("main_vm") + _ = env.get_vm(vm_name) block_device = setup_scsi_debug_block_device() disk_src_dict = {"attrs": {"dev": block_device}} From 353b82155bbe3f5ef0365e2013bb49dd4b685b49 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 6 Nov 2023 04:24:42 -0500 Subject: [PATCH 0008/1055] memory_tuning: add new case for memory tuning Signed-off-by: liang-cong-red-hat --- .../memory_tuning/memory_tuning_settings.cfg | 22 ++ .../memory_tuning/memory_tuning_settings.py | 221 ++++++++++++++++++ 2 files changed, 243 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_tuning/memory_tuning_settings.cfg create mode 100644 libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py diff --git a/libvirt/tests/cfg/memory/memory_tuning/memory_tuning_settings.cfg b/libvirt/tests/cfg/memory/memory_tuning/memory_tuning_settings.cfg new file mode 100644 index 00000000000..33e68b96ce7 --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_tuning/memory_tuning_settings.cfg @@ -0,0 +1,22 @@ +- memory.tuning: + type = memory_tuning_settings + start_vm = no + memtune_cmd_parameter_seq = ['hard_limit', 'soft_limit', 'swap_hard_limit'] + max_limit_dict = {'hard_limit':-1, 'soft_limit':-1, 'swap_hard_limit':-1} + vm_attrs = {'memory_unit':"KiB", 'memory':2097152, 'current_mem':2097152, 'current_mem_unit':'KiB'} + cgroupv1_error_for_zero_hard_limit = "Unable to write to '.*memory.limit_in_bytes': Device or resource busy" + variants test_target: + - normal: + target_limit_dict = {'hard_limit':3072005, 'soft_limit':2048003, 'swap_hard_limit':4096010} + - zero: + target_limit_dict = {'soft_limit':0, 'hard_limit':0} + shutdown_timeout = 2 + - minus: + init_hard_limit = 3072005 + init_soft_limit = 2048003 + init_swap_hard_limit = 4096010 + init_limit_dict = {'hard_limit':${init_hard_limit}, 'soft_limit':${init_soft_limit}, 'swap_hard_limit':${init_swap_hard_limit}} + init_memory_tuning_dict = "'memtune': {'hard_limit':${init_hard_limit}, 'hard_limit_unit':'KiB', 'soft_limit':${init_soft_limit}, 'soft_limit_unit':'KiB', 'swap_hard_limit':${init_swap_hard_limit}, 'swap_limit_unit':'KiB'}" + target_limit_dict = {'soft_limit':-1, 'swap_hard_limit':-1, 'hard_limit':-1} + vm_attrs = {'memory_unit':"KiB", 'memory':2097152, 'current_mem':2097152, 'current_mem_unit':'KiB', ${init_memory_tuning_dict}} + diff --git a/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py b/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py new file mode 100644 index 00000000000..9bc3b15960e --- /dev/null +++ b/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py @@ -0,0 +1,221 @@ +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: Liang Cong +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +import re + +from virttest import libvirt_cgroup +from virttest import utils_libvirtd +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml import xcepts +from virttest.utils_test import libvirt +from virttest.staging import utils_memory + + +def run(test, params, env): + """ + Verify memory tuning parameters take effect + """ + + def adjust_limit_for_memory_page(limit_dict): + """ + Limit value would be aligned to the default memory page size + """ + default_page_size = utils_memory.getpagesize() + return {key: (value // default_page_size * default_page_size) + if value != -1 else value for key, value in limit_dict.items()} + + def check_limit_by_virsh_memtune(limit_dict): + """ + Check the memtune limit is expected by virsh memtune + """ + expected_limit_dict = adjust_limit_for_memory_page(limit_dict) + for key, value in expected_limit_dict.items(): + actual_value = virsh.memtune_get(vm_name, key) + if actual_value != value: + test.fail("memtune limit %s expected %s, but get %s instead" + % (key, value, actual_value)) + + def set_limit_by_virsh_memtune_in_turn(limit_dict): + """ + Set memory limit by virsh memtune one by one + """ + vm_pid = vm.get_pid() + cg = libvirt_cgroup.CgroupTest(vm_pid) + for key, value in limit_dict.items(): + options = " --%s %s" % (re.sub('_', '-', key), value) + result = virsh.memtune_set(vm_name, options, debug=True) + if not cg.is_cgroup_v2_enabled() and 'hard_limit' == key and 0 == value: + libvirt.check_result( + result, expected_fails=cgroupv1_error_for_zero_hard_limit) + else: + libvirt.check_exit_status(result) + + def set_limit_by_virsh_memtune_once(limit_dict): + """ + Set memory limit by virsh memtune all together + """ + limit_value_list = [str(limit_dict[limit_name]) + for limit_name in memtune_cmd_parameter_seq] + options = " %s" % " ".join(limit_value_list) + virsh.memtune_set(vm_name, options, debug=True, ignore_status=False) + + def check_limit_by_cgroup(limit_dict): + """ + Check the memtune limit is expected by cgroup + """ + adjusted_limit_dict = adjust_limit_for_memory_page(limit_dict) + expected_limit_dict = {key: (value*1024) if value != -1 else 'max' + for key, value in adjusted_limit_dict.items()} + vm_pid = vm.get_pid() + cg = libvirt_cgroup.CgroupTest(vm_pid) + limit_cgroup_dict = cg.get_standardized_cgroup_info("memtune") + for key in expected_limit_dict: + if str(expected_limit_dict[key]) != limit_cgroup_dict[key]: + test.fail("cgroup memory limit %s expected %s, but get %s instead" + % (key, expected_limit_dict[key], limit_cgroup_dict[key])) + + def check_limit_by_virsh_dump(limit_dict): + """ + check the memtune limit is expected by virsh dump + """ + guest_xml = vm_xml.VMXML.new_from_dumpxml(vm.name) + if len(set(limit_dict.values())) == 1 and list(limit_dict.values())[0] == -1: + try: + if hasattr(guest_xml, "memtune"): + test.fail("memtune should not appear in config xml, " + "but found memtune XML:\n%s" % guest_xml.memtune) + except xcepts.LibvirtXMLNotFoundError: + pass + else: + memtune_element = guest_xml.memtune + for key, value in limit_dict.items(): + if int(getattr(memtune_element, key)) != value: + test.fail("memtune limit %s should be %s " + "in config xml, but found value:%s" + % (key, value, getattr(memtune_element, key))) + + def run_test(): + """ + Test steps + """ + + test.log.info("TEST_SETUP1: Define the guest") + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + vmxml.setup_attrs(**vm_attrs) + virsh.define(vmxml.xml, ignore_status=False, debug=True) + + test.log.info("TEST_STEP2: Start the guest") + if not vm.is_alive(): + vm.start() + vm_pid = vm.get_pid() + cg = libvirt_cgroup.CgroupTest(vm_pid) + + test.log.info("TEST_STEP3: Check the memtune setting") + if "minus" == test_target: + expected_limit_dict = init_limit_dict + else: + expected_limit_dict = max_limit_dict + check_limit_by_virsh_memtune(expected_limit_dict) + + test.log.info("TEST_STEP4: Change the memtune settings one by one") + set_limit_by_virsh_memtune_in_turn(target_limit_dict) + + test.log.info("TEST_STEP5: Check the guest status") + if 'zero' == test_target: + vm.wait_for_shutdown(shutdown_timeout) + actual_state = virsh.domstate( + vm_name, "--reason", debug=True).stdout.strip() + if 'zero' == test_target: + expected_state = "shut off (crashed)" if cg.is_cgroup_v2_enabled( + ) else "running (booted)" + if expected_state != actual_state: + test.fail("Guest state should be '%s', " + "but get %s instead" % (expected_state, actual_state)) + return + else: + if "running (booted)" != actual_state: + test.fail("Guest state should be 'running (booted)', " + "but get %s instead" % actual_state) + + test.log.info("TEST_STEP6: For scenarios with running guest, " + "check the memtune values") + check_limit_by_virsh_memtune(target_limit_dict) + + test.log.info("TEST_STEP7: For scenarios with running guest, " + "check the cgroup settings") + check_limit_by_cgroup(target_limit_dict) + + test.log.info("TEST_STEP8: For scenarios with running guest, " + "destroy and start the guest") + vm.destroy() + vm.start() + + test.log.info("TEST_STEP9: For scenarios with running guest, " + "change the memtune setting all together") + set_limit_by_virsh_memtune_once(target_limit_dict) + + test.log.info("TEST_STEP10: For scenarios with running guest, " + "check the memtune values") + check_limit_by_virsh_memtune(target_limit_dict) + + test.log.info("TEST_STEP11: For scenarios with running guest, " + "check the cgroup settings") + check_limit_by_cgroup(target_limit_dict) + + test.log.info("TEST_STEP12: For scenarios with running guest, " + "check the memtune config xml") + check_limit_by_virsh_dump(target_limit_dict) + + test.log.info("TEST_STEP13: For scenarios with running guest, " + "restart the libvirt daemon") + utils_libvirtd.libvirtd_restart() + + test.log.info("TEST_STEP14-1: For scenarios with running guest, " + "check the memtune values") + check_limit_by_virsh_memtune(target_limit_dict) + + test.log.info("TEST_STEP14-2: For scenarios with running guest, " + "check the cgroup settings") + check_limit_by_cgroup(target_limit_dict) + + test.log.info("TEST_STEP14-3: For scenarios with running guest, " + "check the memtune config xml") + check_limit_by_virsh_dump(target_limit_dict) + + def teardown_test(): + """ + Restore guest config xml. + """ + test.log.info("TEST_TEARDOWN: Restore guest config xml.") + bkxml.sync() + + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + vm_attrs = eval(params.get('vm_attrs', '{}')) + test_target = params.get('test_target') + max_limit_dict = eval(params.get('max_limit_dict', '{}')) + init_limit_dict = eval(params.get('init_limit_dict', '{}')) + target_limit_dict = eval(params.get('target_limit_dict', '{}')) + memtune_cmd_parameter_seq = eval( + params.get('memtune_cmd_parameter_seq', '[]')) + cgroupv1_error_for_zero_hard_limit = params.get( + 'cgroupv1_error_for_zero_hard_limit', '') + shutdown_timeout = int(params.get('shutdown_timeout', 0)) + + try: + run_test() + + finally: + teardown_test() From efbf91156dc3d3d7ebc8a0525957c00dc6ceb5bd Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Fri, 27 Oct 2023 04:43:31 -0400 Subject: [PATCH 0009/1055] Add new case of attach interface with boot order - VIRT-299227 - [attach-device][boot order] hotplug an interface with boot order Signed-off-by: Haijiao Zhao --- .../attach_iface_with_boot_order.cfg | 21 +++++++ .../attach_iface_with_boot_order.py | 61 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/attach_detach_device/attach_iface_with_boot_order.cfg create mode 100644 libvirt/tests/src/virtual_network/attach_detach_device/attach_iface_with_boot_order.py diff --git a/libvirt/tests/cfg/virtual_network/attach_detach_device/attach_iface_with_boot_order.cfg b/libvirt/tests/cfg/virtual_network/attach_detach_device/attach_iface_with_boot_order.cfg new file mode 100644 index 00000000000..5d052bf46e7 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/attach_detach_device/attach_iface_with_boot_order.cfg @@ -0,0 +1,21 @@ +- virtual_network.attach_detach_device.boot_order: + type = attach_iface_with_boot_order + start_vm = no + timeout = 240 + status_error = yes + variants scenario: + - vm_with_os_boot: + os_attrs = {'boots': ['hd']} + boot_order = 2 + err_msg = per-device boot elements cannot be used together with os/boot elements + - dup_boot_order: + boot_order = 1 + disk_attrs = {'boot': '${boot_order}'} + err_msg = unsupported configuration: boot order ${boot_order} is already used by another device + - neg_value: + boot_order = -1 + err_msg = Expected non-negative integer value + - str_value: + boot_order = ss + err_msg = Expected non-negative integer value + iface_attrs = {'source': {'network': 'default'}, 'model': 'virtio', 'type_name': 'network', 'boot': '${boot_order}'} diff --git a/libvirt/tests/src/virtual_network/attach_detach_device/attach_iface_with_boot_order.py b/libvirt/tests/src/virtual_network/attach_detach_device/attach_iface_with_boot_order.py new file mode 100644 index 00000000000..d0e4e0fedbf --- /dev/null +++ b/libvirt/tests/src/virtual_network/attach_detach_device/attach_iface_with_boot_order.py @@ -0,0 +1,61 @@ +import logging + +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test attach interface with boot order + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + status_error = 'yes' == params.get('status_error', 'no') + err_msg = params.get('err_msg') + iface_attrs = eval(params.get('iface_attrs', '{}')) + os_attrs = eval(params.get('os_attrs', '{}')) + disk_attrs = eval(params.get('disk_attrs', '{}')) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + vmxml.del_device('interface', by_tag=True) + vmxml.sync() + + if os_attrs: + vmxml.setup_attrs(os=os_attrs) + if disk_attrs: + osxml = vmxml.os + osxml.del_boots() + vmxml.os = osxml + vmxml.sync() + libvirt_vmxml.modify_vm_device(vmxml, 'disk', disk_attrs) + + LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + vm.start() + vm.wait_for_serial_login().close() + + iface = libvirt_vmxml.create_vm_device_by_type( + 'interface', iface_attrs) + LOG.debug(f'Interface to attach:\n{iface}') + + def check_attach(option=''): + at_result = virsh.attach_device(vm_name, iface.xml, flagstr=option, + debug=True) + libvirt.check_exit_status(at_result, status_error) + if err_msg: + libvirt.check_result(at_result, err_msg) + + check_attach() + check_attach('--config') + + finally: + bkxml.sync() From 2ff869d98ffbb92731b554ccf39ba898f27a1f49 Mon Sep 17 00:00:00 2001 From: Hu Shuai Date: Wed, 8 Nov 2023 16:29:26 +0800 Subject: [PATCH 0010/1055] virtual_network: remove acpi settings in connectivity_check_ethernet_interface arm does not support acpi index. remove acpi settings here as the scenario is not for acpi test. Signed-off-by: Hu Shuai --- .../connectivity/connectivity_check_ethernet_interface.cfg | 3 +-- .../connectivity/connectivity_check_ethernet_interface.py | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_ethernet_interface.cfg b/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_ethernet_interface.cfg index 9b42e952369..eddff741653 100644 --- a/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_ethernet_interface.cfg +++ b/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_ethernet_interface.cfg @@ -31,8 +31,7 @@ - macvtap: vm_ping_outside = pass vm_ping_host_public = fail - iface_attrs = {'target': {'dev': tap_name, 'managed': 'no'}, 'model': 'virtio', 'type_name': 'ethernet', **${mtu_attrs}, 'acpi': {'index': '1'}} - vm_iface = eno1 + iface_attrs = {'target': {'dev': tap_name, 'managed': 'no'}, 'model': 'virtio', 'type_name': 'ethernet', **${mtu_attrs}} - negative_test: status_error = yes variants: diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py index d97ad461eb3..2e6261f2aa2 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py @@ -11,6 +11,7 @@ from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_test import libvirt +from provider.interface import interface_base from provider.virtual_network import network_base LOG = logging.getLogger('avocado.' + __name__) @@ -50,10 +51,8 @@ def run(test, params, env): tap_name = tap_type + '_' + rand_id tap_mtu = params.get('tap_mtu') iface_mtu = params.get('iface_mtu') - vm_iface = params.get('vm_iface') host_ip = utils_net.get_host_ip_address(ip_ver='ipv4') iface_attrs = eval(params.get('iface_attrs')) - vm_iface = params.get('vm_iface', 'eno1') outside_ip = params.get('outside_ip') host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_net_if( @@ -113,6 +112,7 @@ def run(test, params, env): LOG.info('MTU check of vmxml PASS') # Check mtu inside vm + vm_iface = interface_base.get_vm_iface(session) vm_iface_info = utils_net.get_linux_iface_info(iface=vm_iface, session=session) vm_mtu = vm_iface_info['mtu'] From 22f409a7f11d877f82358647f5e73193dfed03b9 Mon Sep 17 00:00:00 2001 From: Hu Shuai Date: Wed, 28 Jun 2023 17:00:09 +0800 Subject: [PATCH 0011/1055] numa_topology_with_hugepage: Enable test for aarch64 For aarch64, the kernel pagesize for 8 is 64k. But for 9, both 4k and 64k are supported. Therefore, the huge pagesize supported on aarch64 will also vary based on the kernel pagesize. Signed-off-by: Hu Shuai --- .../numa_topology_with_hugepage.cfg | 35 ++++++++++++-- .../numa_topology_with_hugepage.py | 48 +++++++++++++++---- 2 files changed, 69 insertions(+), 14 deletions(-) diff --git a/libvirt/tests/cfg/numa/guest_numa_topology/numa_topology_with_hugepage.cfg b/libvirt/tests/cfg/numa/guest_numa_topology/numa_topology_with_hugepage.cfg index 3bedd9c61b0..06b0d644986 100644 --- a/libvirt/tests/cfg/numa/guest_numa_topology/numa_topology_with_hugepage.cfg +++ b/libvirt/tests/cfg/numa/guest_numa_topology/numa_topology_with_hugepage.cfg @@ -5,30 +5,55 @@ max_mem_value = "'max_mem_rt': 8388608, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'" target_hugepages_2M = 500 target_hugepages_1G = 1 - hugepage_path_1G = '/dev/hugepages1G' hugepage_path_2M = '/dev/hugepages' + hugepage_path_1G = '/dev/hugepages1G' pat_in_qemu_cmdline = '-object {"qom-type":".*","id":"ram-node0","mem-path":"%s","prealloc":true,"size":%d} .* -object {"qom-type":".*","id":"ram-node1",%s%s"size":%d}' variants hp_size: - 2M: mem_value = "'memory': 2097152, 'memory_unit': 'KiB'" vm_numa_node0_mem = 1024000 - vm_numa_node1_mem = 1073152 + vm_numa_node1_mem = 1073152 memory_backing = {'hugepages': {'pages': [{'size': '2048', 'unit': 'KiB', 'nodeset': '0'}]}} - 1G: + no kernelpagesize_64k mem_value = "'memory': 2121728, 'memory_unit': 'KiB'" vm_numa_node0_mem = 1048576 - vm_numa_node1_mem = 1073152 + vm_numa_node1_mem = 1073152 memory_backing = {'hugepages': {'pages': [{'size': '1048576', 'unit': 'KiB', 'nodeset': '0'}]}} + - 512M: + only kernelpagesize_64k + mem_value = "'memory': 2121728, 'memory_unit': 'KiB'" + vm_numa_node0_mem = 1048576 + vm_numa_node1_mem = 1073152 + memory_backing = {'hugepages': {'pages': [{'size': '524288', 'unit': 'KiB', 'nodeset': '0'}]}} + - 2M_512M: + only kernelpagesize_64k + mem_value = "'memory': 2072576, 'memory_unit': 'KiB'" + vm_numa_node0_mem = 1024000 + vm_numa_node1_mem = 1048576 + memory_backing = {'hugepages': {'pages': [{'size': '512', 'unit': 'M', 'nodeset': '1'}, {'size': '2', 'unit': 'M', 'nodeset': '0'}]}} - 2M_1G: + no kernelpagesize_64k mem_value = "'memory': 2072576, 'memory_unit': 'KiB'" vm_numa_node0_mem = 1024000 - vm_numa_node1_mem = 1048576 + vm_numa_node1_mem = 1048576 memory_backing = {'hugepages': {'pages': [{'size': '1', 'unit': 'G', 'nodeset': '1'}, {'size': '2', 'unit': 'M', 'nodeset': '0'}]}} - scarce_mem: mem_value = "'memory': 2097152, 'memory_unit': 'KiB'" vm_numa_node0_mem = 1048576 vm_numa_node1_mem = 1048576 - memory_backing = {'hugepages': {'pages': [{'size': '2048', 'unit': 'KiB', 'nodeset': '0'}]}} + memory_backing = {'hugepages': {'pages': [{'size': '2048', 'unit': 'KiB', 'nodeset': '0'}]}} + variants: + - kernelpagesize_64k: + only aarch64 + conf_pagesize = 65536 + hugepage_path_2M = '/dev/hugepages2M' + hugepage_path_512M = '/dev/hugepages' + target_hugepages_512M = 2 + - kernelpagesize_4k: + conf_pagesize = 4096 current_mem_value = ${mem_value} numa_cell = "'numa_cell': [{'cpus': '0-1', 'memory': '${vm_numa_node0_mem}'}, {'cpus': '2-3', 'memory': '${vm_numa_node1_mem}'}]" vm_attrs = {${max_mem_value}, ${mem_value}, ${current_mem_value}, 'vcpu': 4, 'cpu': {'mode': 'host-model', ${numa_cell}}} + aarch64: + vm_attrs = {${max_mem_value}, ${mem_value}, ${current_mem_value}, 'vcpu': 4, 'cpu': {'mode': 'host-passthrough', ${numa_cell}}} diff --git a/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_hugepage.py b/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_hugepage.py index 6de74855a33..d8e2d54e33c 100644 --- a/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_hugepage.py +++ b/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_hugepage.py @@ -42,16 +42,25 @@ def setup_default(test_obj): test_obj.setup() params_2M = {'hugepage_size': '2048', 'vm_hugepage_mountpoint': test_obj.params.get('hugepage_path_2M'), - 'target_hugepages': test_obj.params.get('target_hugepages_2M')} + 'target_hugepages': test_obj.params.get('target_hugepages_2M'), + 'kernel_hp_file': '/sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages'} + params_512M = {'hugepage_size': '524288', + 'vm_hugepage_mountpoint': test_obj.params.get('hugepage_path_512M'), + 'target_hugepages': test_obj.params.get('target_hugepages_512M'), + 'kernel_hp_file': '/sys/kernel/mm/hugepages/hugepages-524288kB/nr_hugepages'} params_1G = {'hugepage_size': '1048576', 'vm_hugepage_mountpoint': test_obj.params.get('hugepage_path_1G'), 'target_hugepages': test_obj.params.get('target_hugepages_1G'), 'kernel_hp_file': '/sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages'} hp_size = test_obj.params.get('hp_size') - if hp_size in ['2M', '2M_1G', 'scarce_mem']: + if hp_size in ['2M', '2M_1G', '2M_512M', 'scarce_mem']: test_obj.params.update(params_2M) hpconfig_2M = setup_hugepage(test_obj.params) test_obj.params['hp_config_2M'] = hpconfig_2M + if hp_size in ['512M', '2M_512M']: + test_obj.params.update(params_512M) + hpconfig_512M = setup_hugepage(test_obj.params) + test_obj.params['hp_config_512M'] = hpconfig_512M if hp_size in ['1G', '2M_1G']: test_obj.params.update(params_1G) hpconfig_1G = setup_hugepage(test_obj.params) @@ -110,12 +119,18 @@ def _check_numa_maps(mem_size, hugepage_num, pagesize): "numa_maps output '%s'" % (pat, out_numa_maps)) hp_size = test_obj.params.get('hp_size') - if hp_size in ['2M', '2M_1G']: + if hp_size in ['2M', '2M_512M', '2M_1G']: _check_numa_maps(test_obj.params.get('vm_numa_node0_mem'), test_obj.params.get('target_hugepages_2M'), '2048') + if hp_size == '512M': + _check_numa_maps(test_obj.params.get('vm_numa_node0_mem'), + test_obj.params.get('target_hugepages_512M'), '524288') if hp_size == '1G': _check_numa_maps(test_obj.params.get('vm_numa_node0_mem'), test_obj.params.get('target_hugepages_1G'), '1048576') + if hp_size == '2M_512M': + _check_numa_maps(test_obj.params.get('vm_numa_node1_mem'), + test_obj.params.get('target_hugepages_512M'), '524288') if hp_size == '2M_1G': _check_numa_maps(test_obj.params.get('vm_numa_node1_mem'), test_obj.params.get('target_hugepages_1G'), '1048576') @@ -131,13 +146,21 @@ def check_qemu_cmdline(test_obj): pat_in_qemu_cmdline = test_obj.params.get('pat_in_qemu_cmdline') hp_size = test_obj.params.get('hp_size') hugepage_path_1G = test_obj.params.get('hugepage_path_1G') + hugepage_path_512M = test_obj.params.get('hugepage_path_512M') hugepage_path_2M = test_obj.params.get('hugepage_path_2M') - node0_mem_path = '%s/libvirt/qemu/.*' % hugepage_path_2M \ - if hp_size in ['2M', '2M_1G'] else '%s/libvirt/qemu/.*' % hugepage_path_1G + if hp_size in ['2M', '2M_512M', '2M_1G']: + node0_mem_path = '%s/libvirt/qemu/.*' % hugepage_path_2M + if hp_size == "512M": + node0_mem_path = '%s/libvirt/qemu/.*' % hugepage_path_512M + if hp_size == "1G": + node0_mem_path = '%s/libvirt/qemu/.*' % hugepage_path_1G + node1_mem_path = '' + if hp_size == "2M_512M": + node1_mem_path = '"mem-path":"%s/libvirt/qemu/.*",' % hugepage_path_512M + if hp_size == "2M_1G": + node1_mem_path = '"mem-path":"%s/libvirt/qemu/.*",' % hugepage_path_1G node0_mem_size = int(test_obj.params.get('vm_numa_node0_mem')) * 1024 - node1_mem_path = '"mem-path":"%s/libvirt/qemu/.*",' % hugepage_path_1G \ - if hp_size == '2M_1G' else '' - node1_prealloc = '"prealloc":true,' if hp_size == '2M_1G' else '' + node1_prealloc = '"prealloc":true,' if hp_size == '2M_1G' or hp_size == '2M_512M' else '' node1_mem_size = int(test_obj.params.get('vm_numa_node1_mem')) * 1024 pat_in_qemu_cmdline = pat_in_qemu_cmdline % (node0_mem_path, node0_mem_size, @@ -182,8 +205,9 @@ def teardown_default(test_obj): """ test_obj.teardown() hpconfig_2M = test_obj.params.get('hp_config_2M') + hpconfig_512M = test_obj.params.get('hp_config_512M') hpconfig_1G = test_obj.params.get('hp_config_1G') - for hpconfig in [hpconfig_2M, hpconfig_1G]: + for hpconfig in [hpconfig_2M, hpconfig_512M, hpconfig_1G]: if hpconfig: hpconfig.cleanup() test_obj.test.log.debug("Step: hugepage is deallocated") @@ -194,9 +218,15 @@ def run(test, params, env): """ Test for numa memory binding with emulator thread pin """ + conf_pagesize = params.get("conf_pagesize") + kernel_pagesize = process.run("getconf PAGESIZE", shell=True).stdout_text.strip() + if kernel_pagesize != conf_pagesize: + test.cancel("The current test does not work with this kernel pagesize.") + vm_name = params.get("main_vm") vm = env.get_vm(vm_name) numatest_obj = numa_base.NumaTest(vm, params, test) + try: setup_default(numatest_obj) run_default(numatest_obj) From 8c140b1ca2c8eec0ac1112424676361e5b9290cd Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 12 Oct 2023 05:49:07 -0400 Subject: [PATCH 0012/1055] Remove irrelevant acpi settings Signed-off-by: Haijiao Zhao --- .../virtual_network/elements_and_attributes/element_model.cfg | 3 +-- .../virtual_network/elements_and_attributes/element_model.py | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/elements_and_attributes/element_model.cfg b/libvirt/tests/cfg/virtual_network/elements_and_attributes/element_model.cfg index 634314d458e..b2d7505c04d 100644 --- a/libvirt/tests/cfg/virtual_network/elements_and_attributes/element_model.cfg +++ b/libvirt/tests/cfg/virtual_network/elements_and_attributes/element_model.cfg @@ -30,5 +30,4 @@ - test: status_error = yes err_msg = is not a valid device model name - iface_attrs = {'source': {'network': 'default'}, 'model': '${model_type}', 'type_name': 'network', 'acpi': {'index': '1'}} - vm_iface = eno1 + iface_attrs = {'source': {'network': 'default'}, 'model': '${model_type}', 'type_name': 'network'} diff --git a/libvirt/tests/src/virtual_network/elements_and_attributes/element_model.py b/libvirt/tests/src/virtual_network/elements_and_attributes/element_model.py index 07071e54d4b..676da6dd255 100644 --- a/libvirt/tests/src/virtual_network/elements_and_attributes/element_model.py +++ b/libvirt/tests/src/virtual_network/elements_and_attributes/element_model.py @@ -6,6 +6,7 @@ from virttest.utils_test import libvirt from provider.virtual_network import network_base +from provider.interface import interface_base VIRSH_ARGS = {'ignore_status': False, 'debug': True} @@ -23,7 +24,6 @@ def run(test, params, env): err_msg = params.get('err_msg') pci_model = params.get('pci_model') iface_attrs = eval(params.get('iface_attrs', '{}')) - vm_iface = params.get('vm_iface') iface_driver = params.get('iface_driver') model_type = params.get('model_type') if model_type == 'default': @@ -58,6 +58,7 @@ def run(test, params, env): f'but got {iface_info["model"]}') session = vm.wait_for_serial_login() + vm_iface = interface_base.get_vm_iface(session) eth_output = session.cmd_output(f'ethtool -i {vm_iface} | grep driver') LOG.debug(eth_output) From db7401ae352e114848b94fd1f648cc0ec479a59d Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Sat, 28 Oct 2023 21:32:00 +0800 Subject: [PATCH 0013/1055] host_guest_mixed_memory_binding: add case Test scenario: Test mixed host and guest numa memory binding Signed-off-by: Dan Zheng --- .../host_guest_mixed_memory_binding.cfg | 51 +++ .../change_numa_tuning.py | 14 +- .../host_guest_mixed_memory_binding.py | 370 ++++++++++++++++++ provider/numa/numa_base.py | 42 +- 4 files changed, 459 insertions(+), 18 deletions(-) create mode 100644 libvirt/tests/cfg/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.cfg create mode 100644 libvirt/tests/src/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.py diff --git a/libvirt/tests/cfg/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.cfg b/libvirt/tests/cfg/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.cfg new file mode 100644 index 00000000000..9e608912d7b --- /dev/null +++ b/libvirt/tests/cfg/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.cfg @@ -0,0 +1,51 @@ +- guest_numa_node_tuning.host_guest_mixed_memory_binding: + type = host_guest_mixed_memory_binding + take_regular_screendumps = no + start_vm = "no" + max_mem_value = "'max_mem_rt': 8388608, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'" + mem_value = "'memory': 2072576, 'memory_unit': 'KiB'" + current_mem_value = ${mem_value} + vm_node0_mem = 1048576 + vm_node1_mem = 1024000 + numa_node0 = {'id': '0', 'cpus': '0', 'memory': '${vm_node0_mem}', 'unit': 'KiB'} + numa_node1 = {'id': '1', 'cpus': '1', 'memory': '${vm_node1_mem}', 'unit': 'KiB'} + numa_cell = "'numa_cell': [${numa_node0}, ${numa_node1}]" + cpu_mode = 'host-model' + no s390-virtio + aarch64: + mem_value = "'memory': 2097152, 'memory_unit': 'KiB'" + cpu_mode = 'host-passthrough' + variants host_numa: + - single_node: + single_host_node = yes + - multiple_nodes: + single_host_node = no + - no_node: + only no_mem_mode + variants memory_mode: + - mem_mode_strict: + mem_mode = 'strict' + numa_memory = {'mode': '${mem_mode}', 'nodeset': '%s'} + - mem_mode_interleave: + mem_mode = 'interleave' + numa_memory = {'mode': '${mem_mode}', 'nodeset': '%s'} + - mem_mode_preferred: + mem_mode = 'preferred' + numa_memory = {'mode': '${mem_mode}', 'nodeset': '%s'} + - mem_mode_restrictive: + func_supported_since_libvirt_ver = (9, 4, 0) + mem_mode = 'restrictive' + numa_memory = {'mode': '${mem_mode}', 'nodeset': '%s'} + - no_mem_mode: + variants memnode_mode: + - memnode_mode_strict: + memnode_mode = 'strict' + - memnode_mode_interleave: + memnode_mode = 'interleave' + - memnode_mode_preferred: + memnode_mode = 'preferred' + - memnode_mode_restrictive: + func_supported_since_libvirt_ver = (9, 4, 0) + memnode_mode = 'restrictive' + numa_memnode = [{'cellid': '0', 'mode': '${memnode_mode}', 'nodeset': '%s'}] + vm_attrs = {${max_mem_value}, ${mem_value}, ${current_mem_value}, 'vcpu': 2, 'cpu': {'mode': '${cpu_mode}', ${numa_cell}}} diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/change_numa_tuning.py b/libvirt/tests/src/numa/guest_numa_node_tuning/change_numa_tuning.py index 4c7d5b94141..045aeecae5f 100644 --- a/libvirt/tests/src/numa/guest_numa_node_tuning/change_numa_tuning.py +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/change_numa_tuning.py @@ -45,7 +45,7 @@ def prepare_vm_xml(test_obj): :return: VMXML object updated """ vmxml = test_obj.prepare_vm_xml() - all_nodes = test_obj.all_usable_numa_nodes + all_nodes = test_obj.online_nodes_withmem mem_total = test_obj.host_numa_info.read_from_node_meminfo(all_nodes[0], 'MemTotal') offset = 1000000 if int(mem_total) < offset: @@ -79,7 +79,7 @@ def verify_host_numa_memory_allocation(test_obj, check_N0=False): mem_size = get_memory_in_vmxml(test_obj) kernelpagesize_kB = test_obj.params.get('kernelpagesize_kB') out_numa_maps = numa_base.get_host_numa_memory_alloc_info(mem_size) - all_nodes = test_obj.all_usable_numa_nodes + all_nodes = test_obj.online_nodes_withmem N0_value = re.findall('N%s=(\d+)' % all_nodes[0], out_numa_maps) N1_value = re.findall('N%s=(\d+)' % all_nodes[1], out_numa_maps) has_kernelpage = bool(re.search('kernelpagesize_kB=%s' % kernelpagesize_kB, out_numa_maps)) @@ -173,10 +173,10 @@ def run_default(test_obj): another_mem_mode = select_different_mem_mode(mem_mode) verify_numatune(test_obj, mem_mode=another_mem_mode, - nodeset=str(test_obj.all_usable_numa_nodes[1])) + nodeset=str(test_obj.online_nodes_withmem[1])) numatune_result = virsh.numatune(test_obj.vm.name, mode=mem_mode, - nodeset=str(test_obj.all_usable_numa_nodes[0]), + nodeset=str(test_obj.online_nodes_withmem[0]), **test_obj.virsh_dargs).stdout_text.strip() test_obj.test.log.debug("Step: start vm") ret = virsh.start(test_obj.vm.name, **test_obj.virsh_dargs) @@ -187,7 +187,7 @@ def run_default(test_obj): error_expected = produce_expected_error(test_obj) verify_numatune(test_obj, mem_mode=another_mem_mode, - nodeset=test_obj.all_usable_numa_nodes[0], + nodeset=test_obj.online_nodes_withmem[0], error_expected=error_expected) @@ -211,9 +211,9 @@ def run_mem_mode_restrictive(test_obj): mem_mode = test_obj.params.get('mem_mode') run_default(test_obj) test_obj.test.log.debug("Step: change numatune nodeset on running vm when mode is restrictive") - verify_numatune(test_obj, mem_mode=mem_mode, nodeset=test_obj.all_usable_numa_nodes[1]) + verify_numatune(test_obj, mem_mode=mem_mode, nodeset=test_obj.online_nodes_withmem[1]) verify_host_numa_memory_allocation(test_obj) - nodeset = "%s,%s" % (test_obj.all_usable_numa_nodes[0], test_obj.all_usable_numa_nodes[1]) + nodeset = "%s,%s" % (test_obj.online_nodes_withmem[0], test_obj.online_nodes_withmem[1]) nodeset = numa_base.convert_to_string_with_dash(nodeset) test_obj.test.log.debug("Step: change numatune nodeset in range on running vm when mode is restrictive") verify_numatune(test_obj, mem_mode=mem_mode, nodeset=nodeset) diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.py b/libvirt/tests/src/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.py new file mode 100644 index 00000000000..6b217d1530f --- /dev/null +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.py @@ -0,0 +1,370 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: Dan Zheng +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +import os +import re + +from avocado.utils import process + +from virttest import libvirt_cgroup +from virttest import libvirt_version +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_memory + +from provider.numa import numa_base + + +def setup_default(numatest_obj): + """ + Default setup function for the test + + :param numatest_obj: NumaTest object + """ + numatest_obj.setup(expect_node_free_mem_min=1048576) + numatest_obj.test.log.debug("Step: setup is done") + + +def prepare_vm_xml(numatest_obj): + """ + Customize the vm xml + + :param numatest_obj: NumaTest object + + :return: VMXML object updated + """ + numa_memnode = numatest_obj.params.get('numa_memnode') + numa_memnode = numa_memnode % numatest_obj.online_nodes_withmem[1] + numatest_obj.params['numa_memnode'] = numa_memnode + vmxml = numatest_obj.prepare_vm_xml() + numatest_obj.test.log.debug("Step: vm xml before defining:\n%s", vmxml) + return vmxml + + +def generate_start_expected_error(numatest_obj): + """ + produce the expected error message + + :param numatest_obj: NumaTest object + + :return: str, error message to be checked + """ + err_msg = numatest_obj.produce_expected_error() + mem_mode = numatest_obj.params.get('mem_mode') + single_host_node = numatest_obj.params.get('single_host_node') + memnode_mode = numatest_obj.params.get('memnode_mode') + + if (not libvirt_version.version_compare(9, 4, 0) and + memnode_mode != 'restrictive' and + single_host_node == 'yes' and + mem_mode == 'strict'): + new_err_msg = "cannot bind memory to host NUMA nodes: Invalid argument" + err_msg = "%s|%s" % (err_msg, new_err_msg) if err_msg else new_err_msg + return err_msg + + +def generate_define_expected_error(numatest_obj): + """ + produce the expected error message + + :param numatest_obj: NumaTest object + + :return: str, error message to be checked + """ + mem_mode = numatest_obj.params.get('mem_mode') + single_host_node = numatest_obj.params.get('single_host_node') + memnode_mode = numatest_obj.params.get('memnode_mode') + err_msg = '' + msg = "'restrictive' mode is required in %s element when mode is 'restrictive' in %s element" + if mem_mode == 'restrictive' and memnode_mode != 'restrictive': + err_msg = msg % ('memnode', 'memory') + if (libvirt_version.version_compare(9, 4, 0) and + (mem_mode != 'restrictive' or single_host_node is None) and + memnode_mode == 'restrictive'): + err_msg = msg % ('memory', 'memnode') + + return err_msg + + +def check_vm_numa_1_memory_allocation(numatest_obj, mem_size): + """ + Check vm numa node 1's memory allocation information + + :param numatest_obj: NumaTest object + :param mem_size: int, vm node memory size + """ + out_numa_maps = numa_base.get_host_numa_memory_alloc_info(mem_size) + memnode_mode = numatest_obj.params.get('memnode_mode') + mem_mode = numatest_obj.params.get('mem_mode') + single_host_node = numatest_obj.params.get('single_host_node') + all_nodes = numatest_obj.online_nodes_withmem + node0_value = re.findall('N%s=(\d+)' % all_nodes[0], out_numa_maps) + node1_value = re.findall('N%s=(\d+)' % all_nodes[1], out_numa_maps) + numatest_obj.test.log.debug("all_nodes:%s, N0_value:%s, " + "N1_value:%s", all_nodes, node0_value, node1_value) + + def _check_N0_no_N1(): + if not node0_value: + numatest_obj.test.fail("Expect N%s > 0, but found not" % all_nodes[0]) + if node1_value: + numatest_obj.test.fail("Not expect N%s to exist, but found" % all_nodes[1]) + + def _check_N0_N1_sum(): + n0_value = 0 if not node0_value else int(node0_value[0]) + n1_value = 0 if not node1_value else int(node1_value[0]) + if n0_value + n1_value <= 0: + numatest_obj.test.fail("Expect N%s + N%s > 0, but found " + "not" % (all_nodes[0], all_nodes[1])) + + def _check_N0(): + if not node0_value: + numatest_obj.test.fail("Expect N%s > 0, but found not" % all_nodes[0]) + + if single_host_node == "yes": + if mem_mode == 'strict' and memnode_mode in ['strict', 'interleave', 'preferred']: + pat = "bind:%s" % all_nodes[0] + _check_N0_no_N1() + if mem_mode == 'strict' and memnode_mode == 'restrictive': + pat = "bind:%s" % all_nodes[0] + _check_N0_N1_sum() + if mem_mode == 'interleave': + pat = "interleave:%s" % all_nodes[0] + _check_N0() + if mem_mode == 'preferred': + pat = "prefer \(many\):%s" % all_nodes[0] \ + if libvirt_version.version_compare(9, 3, 0) \ + else "prefer:%s" % all_nodes[0] + _check_N0() + if mem_mode == 'restrictive': + pat = "default" + _check_N0_N1_sum() + elif single_host_node == 'no': + nodeset = numa_base.convert_to_string_with_dash(numatest_obj.params['nodeset']) + if mem_mode == 'strict': + pat = "bind:%s" % nodeset + if mem_mode == 'interleave': + pat = "interleave:%s" % nodeset + if mem_mode == 'preferred': + pat = "prefer \(many\):%s" % nodeset + if mem_mode == 'restrictive': + pat = "default" + _check_N0_N1_sum() + if mem_mode is None: + pat = "default" + _check_N0_N1_sum() + + search_pattern = r"\s+%s\s+anon=" % pat + if not re.findall(search_pattern, out_numa_maps): + numatest_obj.test.fail("Fail to find the pattern '%s' in " + "numa_maps output '%s'" % (search_pattern, + out_numa_maps)) + numatest_obj.test.log.debug("Step: verify vm numa node 1 memory allocation - PASS") + + +def check_vm_numa_0_memory_allocation(numatest_obj, mem_size): + """ + Check vm numa node 0's memory allocation information + + :param numatest_obj: NumaTest object + :param mem_size: int, vm node memory size + """ + out_numa_maps = numa_base.get_host_numa_memory_alloc_info(mem_size) + all_nodes = numatest_obj.online_nodes_withmem + node0_value = re.findall('N%s=(\d+)' % all_nodes[0], out_numa_maps) + node1_value = re.findall('N%s=(\d+)' % all_nodes[1], out_numa_maps) + memnode_mode = numatest_obj.params.get('memnode_mode') + + if memnode_mode == 'strict': + pat = "bind:%s" % all_nodes[1] + elif memnode_mode == 'interleave': + pat = "interleave:%s" % all_nodes[1] + elif memnode_mode == 'preferred': + if not libvirt_version.version_compare(9, 3, 0): + pat = "prefer:%s" % all_nodes[1] + else: + pat = "prefer \(many\):%s" % all_nodes[1] + else: + pat = "default" + node0_value = 0 if not node0_value else int(node0_value[0]) + node1_value = 0 if not node1_value else int(node1_value[0]) + if node0_value + node1_value <= 0: + numatest_obj.test.fail("Expect N%s + N%s > 0, but " + "found not" % (all_nodes[0], all_nodes[1])) + search_pattern = r"\s+%s\s+anon=" % pat + if not re.findall(search_pattern, out_numa_maps): + numatest_obj.test.fail("Fail to find the pattern '%s' in " + "numa_maps output '%s'" % (search_pattern, + out_numa_maps)) + numatest_obj.test.log.debug("Step: verify vm numa 0 memory allocation - PASS") + + +def check_cgroup(numatest_obj): + """ + Check vm cgroup information + + :param numatest_obj: NumaTest object + """ + memnode_mode = numatest_obj.params.get('memnode_mode') + mem_mode = numatest_obj.params.get('mem_mode') + single_host_node = numatest_obj.params.get('single_host_node') + all_nodes = numatest_obj.online_nodes_withmem + + vm_pid = numatest_obj.vm.get_pid() + cg = libvirt_cgroup.CgroupTest(vm_pid) + is_cgroup2 = cg.is_cgroup_v2_enabled() + surfix_emulator = 'emulator/cpuset.mems' if is_cgroup2 else 'cpuset.mems' + surfix_vcpu0 = 'vcpu0/cpuset.mems' if is_cgroup2 else '../vcpu0/cpuset.mems' + surfix_vcpu1 = 'vcpu1/cpuset.mems' if is_cgroup2 else '../vcpu1/cpuset.mems' + numatest_obj.test.log.debug("The cgroup_path for " + "controller 'cpuset':%s", cg.get_cgroup_path(controller='cpuset')) + emulator_cpuset_mems_cgroup_path = os.path.join(cg.get_cgroup_path(controller='cpuset'), + surfix_emulator) + vcpu0_cpuset_mems_cgroup_path = os.path.join(cg.get_cgroup_path(controller='cpuset'), + surfix_vcpu0) + vcpu1_cpuset_mems_cgroup_path = os.path.join(cg.get_cgroup_path(controller='cpuset'), + surfix_vcpu1) + cmd_emulator = 'cat %s' % re.escape(emulator_cpuset_mems_cgroup_path) + cmd_vcpu0 = 'cat %s' % re.escape(vcpu0_cpuset_mems_cgroup_path) + cmd_vcpu1 = 'cat %s' % re.escape(vcpu1_cpuset_mems_cgroup_path) + emulator_cpuset_mems = process.run(cmd_emulator, shell=True).stdout_text.strip() + vcpu0_cpuset_mems = process.run(cmd_vcpu0, shell=True).stdout_text.strip() + vcpu1_cpuset_mems = process.run(cmd_vcpu1, shell=True).stdout_text.strip() + nodeset_memnode = eval(numatest_obj.params['numa_memnode'])[0].get('nodeset') + if (single_host_node == 'yes' and mem_mode in ['strict', 'restrictive'] + and memnode_mode == 'restrictive'): + if (emulator_cpuset_mems != str(all_nodes[0]) or + vcpu1_cpuset_mems != str(all_nodes[0])): + numatest_obj.test.fail("Expect emulator/cpuset.mems and " + "vcpu1/cpuset.mems to be %s, but " + "found %s and %s" % (all_nodes[0], + emulator_cpuset_mems, + vcpu1_cpuset_mems)) + if vcpu0_cpuset_mems != nodeset_memnode: + numatest_obj.test.fail("Expect vcpu0/cpuset.mems to " + "be %s, but found %s" % (nodeset_memnode, + vcpu0_cpuset_mems)) + if mem_mode in ['interleave', 'preferred'] and memnode_mode == 'restrictive': + for item in [emulator_cpuset_mems, vcpu1_cpuset_mems]: + if item != '': + numatest_obj.test.fail("Expect cpuset.mems to be '', " + "but found %s" % item) + if vcpu0_cpuset_mems != nodeset_memnode: + numatest_obj.test.fail("Expect vcpu0/cpuset.mems to be %s, " + "but found %s" % (nodeset_memnode, + vcpu0_cpuset_mems)) + if ((not mem_mode or mem_mode in ['interleave', 'preferred']) and + memnode_mode == 'strict'): + if is_cgroup2: + if any([emulator_cpuset_mems, vcpu0_cpuset_mems, vcpu1_cpuset_mems]): + numatest_obj.test.fail("Expect emulator/cpuset.mems and " + "vcpu0/cpuset.mems and vcpu1/cpuset.mems " + "to be '', but found " + "%s %s %s" % (emulator_cpuset_mems, + vcpu0_cpuset_mems, + vcpu1_cpuset_mems)) + else: + numatest_obj.test.log.debug("emulator_cpuset_mems=%s, " + "vcpu0_cpuset_mems=%s, " + "vcpu1_cpuset_mems=%s", emulator_cpuset_mems, + vcpu0_cpuset_mems, vcpu1_cpuset_mems) + all_nodes_str = ['%s' % a_node for a_node in all_nodes] + nodeset = numa_base.convert_to_string_with_dash(','.join(all_nodes_str)) + for item in [emulator_cpuset_mems, vcpu0_cpuset_mems, vcpu1_cpuset_mems]: + if item != nodeset: + numatest_obj.test.fail("Expect cpuset.mems to be %s, " + "but found %s" % (nodeset, item)) + if (single_host_node == 'yes' and mem_mode == 'strict' and + memnode_mode != 'restrictive'): + mem_nodeset = numatest_obj.params['nodeset'] + memnode_nodeset = eval(numatest_obj.params['numa_memnode'])[0].get('nodeset') + nodeset = ','.join(list(set(mem_nodeset).union(set(memnode_nodeset)))) + nodeset = numa_base.convert_to_string_with_dash(nodeset) + for item in [emulator_cpuset_mems, vcpu0_cpuset_mems, vcpu1_cpuset_mems]: + if item != nodeset: + numatest_obj.test.fail("Expect cpuset.mems to be %s, " + "but found %s" % (nodeset, item)) + if (single_host_node == 'no' and mem_mode == 'strict' and + memnode_mode != 'restrictive'): + nodeset = numa_base.convert_to_string_with_dash(numatest_obj.params['nodeset']) + for item in [emulator_cpuset_mems, vcpu0_cpuset_mems, vcpu1_cpuset_mems]: + if item != nodeset: + numatest_obj.test.fail("Expect cpuset.mems to be %s, " + "but found %s" % (nodeset, item)) + if (single_host_node == 'no' and mem_mode in ['strict', 'restrictive'] and + memnode_mode == 'restrictive'): + nodeset = numa_base.convert_to_string_with_dash(numatest_obj.params['nodeset']) + for item in [emulator_cpuset_mems, vcpu1_cpuset_mems]: + if item != nodeset: + numatest_obj.test.fail("Expect cpuset.mems to be %s, " + "but found %s" % (nodeset, item)) + if vcpu0_cpuset_mems != nodeset_memnode: + numatest_obj.test.fail("Expect vcpu0/cpuset.mems to be %s, but " + "found %s" % (nodeset_memnode, + vcpu0_cpuset_mems)) + numatest_obj.test.log.debug("Step: verify vm cgroup - PASS") + + +def run_default(numatest_obj): + """ + Default run function for the test + + :param numatest_obj: NumaTest object + """ + numatest_obj.test.log.debug("Step: prepare vm xml") + vmxml = prepare_vm_xml(numatest_obj) + numatest_obj.test.log.debug("Step: define vm and check results") + numatest_obj.virsh_dargs.update({'ignore_status': True}) + ret = virsh.define(vmxml.xml, **numatest_obj.virsh_dargs) + err_msg_expected = generate_define_expected_error(numatest_obj) + libvirt.check_result(ret, expected_fails=err_msg_expected) + if err_msg_expected: + return + numatest_obj.test.log.debug("Step: start vm and check results") + ret = virsh.start(numatest_obj.vm.name, **numatest_obj.virsh_dargs) + err_msg_expected = generate_start_expected_error(numatest_obj) + libvirt.check_result(ret, expected_fails=err_msg_expected) + if err_msg_expected: + return + numatest_obj.test.log.debug("After vm is started, vm xml:\n" + "%s", vm_xml.VMXML.new_from_dumpxml(numatest_obj.vm.name)) + vm_session = numatest_obj.vm.wait_for_login() + libvirt_memory.consume_vm_freememory(vm_session) + vm_session.close() + numatest_obj.test.log.debug("Step: consume vm memory - PASS") + check_vm_numa_0_memory_allocation(numatest_obj, numatest_obj.params.get('vm_node0_mem')) + check_vm_numa_1_memory_allocation(numatest_obj, numatest_obj.params.get('vm_node1_mem')) + check_cgroup(numatest_obj) + + +def teardown_default(numatest_obj): + """ + Default teardown function for the test + + :param numatest_obj: NumaTest object + """ + numatest_obj.teardown() + + numatest_obj.test.log.debug("Step: teardown is done") + + +def run(test, params, env): + """ + Test mixed host and guest numa memory binding + """ + libvirt_version.is_libvirt_feature_supported(params) + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + numatest_obj = numa_base.NumaTest(vm, params, test) + try: + setup_default(numatest_obj) + run_default(numatest_obj) + finally: + teardown_default(numatest_obj) diff --git a/provider/numa/numa_base.py b/provider/numa/numa_base.py index d1eacc97843..627659ba1c9 100644 --- a/provider/numa/numa_base.py +++ b/provider/numa/numa_base.py @@ -36,18 +36,37 @@ def __init__(self, vm, params, test): test.error("Failed to get information from %s", cmd) self.host_numa_info = utils_misc.NumaInfo() self.online_nodes = self.host_numa_info.get_online_nodes().copy() - self.online_nodes_withmem = self.host_numa_info.get_online_nodes_withmem() - self.all_usable_numa_nodes = self.online_nodes_withmem.copy() + self.online_nodes_withmem = self.host_numa_info.get_online_nodes_withmem().copy() self.virsh_dargs = {'ignore_status': False, 'debug': True} - def check_numa_nodes_availability(self, expect_nodes_num=2): - if len(self.all_usable_numa_nodes) < expect_nodes_num: + def check_numa_nodes_availability(self, expect_nodes_num=2, expect_node_free_mem_min=None): + """ + Check if the host numa nodes are available for testing + + :param expect_nodes_num: int, the number of host numa nodes + :param expect_node_free_mem_min: int, the minimum of the node free memory + """ + if len(self.online_nodes_withmem) < expect_nodes_num: self.test.cancel("Expect %d numa nodes at " "least, but found %d" % (expect_nodes_num, - len(self.all_usable_numa_nodes))) - - def setup(self, node_index=0): - self.check_numa_nodes_availability() + len(self.online_nodes_withmem))) + self.test.log.debug("The number of host numa node with " + "memory is %s which meets the " + "requirement", len(self.online_nodes_withmem)) + if expect_node_free_mem_min: + for a_node in self.online_nodes_withmem: + free_mem_min = self.host_numa_info.read_from_node_meminfo(a_node, 'MemFree') + if int(free_mem_min) < expect_node_free_mem_min: + raise exceptions.TestError("Expect the numa node '%s' " + "free memory at least %s, " + "but found %s" % (a_node, + expect_node_free_mem_min, + free_mem_min)) + self.test.log.debug("Host numa node '%s' free memory " + "is %s which meets the requirement", a_node, free_mem_min) + + def setup(self, node_index=0, expect_nodes_num=2, expect_node_free_mem_min=None): + self.check_numa_nodes_availability(expect_nodes_num, expect_node_free_mem_min) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(self.vm.name) self.params['backup_vmxml'] = vmxml.copy() kernel_hp_file = self.params.get('kernel_hp_file') @@ -86,7 +105,7 @@ def prepare_vm_xml(self): # Setup numa tune attributes nodeset = None if single_host_node: - all_nodes = self.all_usable_numa_nodes + all_nodes = self.online_nodes_withmem if single_host_node == 'no': # When memory bind to multiple numa nodes, # the test only selects the first two numa nodes with memory on the host @@ -108,8 +127,9 @@ def prepare_vm_xml(self): numa_memory.update({'nodeset': nodeset}) numa_tune_dict.update({'numa_memory': numa_memory}) if numa_memnode: - numa_memnode = eval(numa_memnode % nodeset) - numa_tune_dict.update({'numa_memnode': numa_memnode}) + if numa_memnode.count('%s'): + numa_memnode = numa_memnode % nodeset + numa_tune_dict.update({'numa_memnode': eval(numa_memnode)}) if numa_tune_dict: vmxml.setup_attrs(**numa_tune_dict) From fcb9c9f93e5ff25aea4e183c72d847c19a07776d Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Thu, 16 Nov 2023 22:16:57 +0800 Subject: [PATCH 0014/1055] memory_binding_with_emulator_thread: fix cpu model for arm The cpu model supported on arm is host-passthrough instead of host-model Signed-off-by: Dan Zheng --- .../memory_binding_with_emulator_thread.cfg | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/libvirt/tests/cfg/numa/guest_numa_node_tuning/memory_binding_with_emulator_thread.cfg b/libvirt/tests/cfg/numa/guest_numa_node_tuning/memory_binding_with_emulator_thread.cfg index 58784a0ecc3..b79c8a8fbf0 100644 --- a/libvirt/tests/cfg/numa/guest_numa_node_tuning/memory_binding_with_emulator_thread.cfg +++ b/libvirt/tests/cfg/numa/guest_numa_node_tuning/memory_binding_with_emulator_thread.cfg @@ -2,15 +2,19 @@ func_supported_since_libvirt_ver = (9, 3, 0) type = memory_binding_with_emulator_thread take_regular_screendumps = no - start_vm = "no" + start_vm = "no" numa_cell = "'numa_cell': [{'id': '0', 'cpus': '0-3', 'memory': '2097152', 'unit': 'KiB'}]" max_mem_value = "'max_mem_rt': 15360000, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'" mem_value = "'memory': 2097152, 'memory_unit': 'KiB'" current_mem_value = ${mem_value} - vm_attrs = {${max_mem_value}, ${mem_value}, ${current_mem_value}, 'vcpu': 4, 'cpu': {'mode': 'host-model', ${numa_cell}}} + cpu_mode = 'host-model' + no s390-virtio + aarch64: + cpu_mode = 'host-passthrough' + vm_attrs = {${max_mem_value}, ${mem_value}, ${current_mem_value}, 'vcpu': 4, 'cpu': {'mode': '${cpu_mode}', ${numa_cell}}} mem_device_attrs = {'mem_model': 'dimm', 'target': {'size': 524288, 'node': 0, 'size_unit': 'KiB'}} qemu_line_hugepage_without_context = '-object {"qom-type":"memory-backend-file","id":"ram-node0".*"host-nodes":\[%s\].*-object {"qom-type":"memory-backend-file","id":"memdimm0".*"host-nodes":\[%s\]' - qemu_line_hugepage_with_context = '-object {"qom-type":"thread-context","id":"tc-ram-node0","node-affinity":\[%s\].*-object {"qom-type":"memory-backend-file","id":"ram-node0".*"host-nodes":\[%s\].*-object {"qom-type":"thread-context","id":"tc-memdimm0","node-affinity":\[%s\].*-object {"qom-type":"memory-backend-file","id":"memdimm0".*"host-nodes":\[%s\]' + qemu_line_hugepage_with_context = '-object {"qom-type":"thread-context","id":"tc-ram-node0","node-affinity":\[%s\].*-object {"qom-type":"memory-backend-file","id":"ram-node0".*"host-nodes":\[%s\].*-object {"qom-type":"thread-context","id":"tc-memdimm0","node-affinity":\[%s\].*-object {"qom-type":"memory-backend-file","id":"memdimm0".*"host-nodes":\[%s\]' qemu_line_default_mem_without_context = '-object {"qom-type":"memory-backend-ram","id":"ram-node0",.*"host-nodes":\[%s\].*-object {"qom-type":"memory-backend-ram","id":"memdimm0".*"host-nodes":\[%s\]' variants emulator_pin_cpu: - emulatorpin_single_node: @@ -24,7 +28,7 @@ overlap_emulatorpin_nodeset = yes variants memory_binding_mode: - mem_mode_strict: - mem_mode = 'strict' + mem_mode = 'strict' - mem_mode_interleave: mem_mode = 'interleave' - mem_mode_preferred: @@ -34,9 +38,9 @@ variants pagesize: - default_pagesize: - hugepage: - memory_backing = {'hugepages': {'pages': [{'size': '2', 'unit': 'M'}]}} + memory_backing = {'hugepages': {'pages': [{'size': '2', 'unit': 'M'}]}} hugepage_size = 2048 kernel_hp_file = '/sys/devices/system/node/node%s/hugepages/hugepages-${hugepage_size}kB/nr_hugepages' - target_hugepages = 1536 + target_hugepages = 1536 numa_memory = {'mode': '${mem_mode}', 'nodeset': '%s'} numa_memnode = [{'cellid': '0', 'mode': '${mem_mode}', 'nodeset': '%s'}] From f692c668026c5c0fddd619daf3c6a7c89132b8aa Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Tue, 7 Nov 2023 09:06:07 +0800 Subject: [PATCH 0015/1055] iothread: add case to set iothread inactively This is to test the iothread parameters could be set before vm starts Signed-off-by: Dan Zheng --- libvirt/tests/cfg/cpu/iothread.cfg | 21 +++- .../virsh_cmd/domain/virsh_iothreadadd.cfg | 1 + .../virsh_cmd/domain/virsh_iothreaddel.cfg | 1 + .../virsh_cmd/domain/virsh_iothreadinfo.cfg | 1 + .../virsh_cmd/domain/virsh_iothreadpin.cfg | 1 + libvirt/tests/src/cpu/iothread.py | 103 ++++++++++++++++-- .../src/virsh_cmd/domain/virsh_iothreadadd.py | 21 +++- .../src/virsh_cmd/domain/virsh_iothreaddel.py | 23 +++- 8 files changed, 150 insertions(+), 22 deletions(-) diff --git a/libvirt/tests/cfg/cpu/iothread.cfg b/libvirt/tests/cfg/cpu/iothread.cfg index 4c1589a579f..ad72ac143cb 100644 --- a/libvirt/tests/cfg/cpu/iothread.cfg +++ b/libvirt/tests/cfg/cpu/iothread.cfg @@ -5,7 +5,7 @@ - positive_test: variants: - iothread_config: - start_vm = "yes" + need_start_vm = "yes" variants: - only_iothread_id: iothread_ids = "6" @@ -15,7 +15,7 @@ iothread_ids = "2 4 6 8" iothread_num = "5" - defaultiothread_config: - start_vm = "yes" + need_start_vm = "yes" func_supported_since_libvirt_ver = (8, 5, 0) vm_attrs = {'defaultiothread': {'thread_pool_min': '8', 'thread_pool_max': '16'}} - thread_pool: @@ -30,7 +30,7 @@ - shutoff_vm: cmd_options = '--config' - live_vm: - start_vm = "yes" + need_start_vm = "yes" pre_vm_stats = "running" cmd_options = '' - iothreadpin: @@ -51,6 +51,19 @@ iothreadset_id = "1" iothreadset_val = "--poll-max-ns 2147483647 --poll-grow 2147483647 --poll-shrink 2147483647" test_operations = "iothreadset" + - iothread_cold_set: + func_supported_since_libvirt_ver = (9, 4, 0) + need_start_vm = "yes" + thread_pool_min = 2147483647 + thread-pool-max = 2147483647 + iothread_num = "2" + iothread_ids = "1 2" + iothreadset_id = "1" + iothreadset_val = "--thread-pool-min 2147483647 --thread-pool-max 2147483647 --poll-max-ns 2147483647 --poll-grow 2147483647 --poll-shrink 2147483647" + cmd_options = '--config' + iothread_config = {'iothread': [{'id': '2', 'thread_pool_min': '1', 'thread_pool_max': '1', 'poll': {'max': '1', 'grow': '1', 'shrink': '1'}}]} + test_operations = "iothreadset" + check_iotheadids_inactive = "yes" - disk_attach: pre_vm_stats = "running" create_disk = "yes" @@ -69,7 +82,7 @@ iothreadpins = "2:100" pseries, aarch64: iothreadpins = "2:300" - start_vm = "yes" + need_start_vm = "yes" err_msg = "Numerical result out of range|Invalid argument" - no_matchs_iothread: define_error = "yes" diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_iothreadadd.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_iothreadadd.cfg index 70fccddddcd..582b6d0629c 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_iothreadadd.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_iothreadadd.cfg @@ -10,6 +10,7 @@ iothreadpins = "2:1 1:0-1" iothreads = "2" iothread_id = "6" + start_vm = 'no' variants: - normal_test: status_error = "no" diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_iothreaddel.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_iothreaddel.cfg index 9219d4b8f03..9dbe54e2f3f 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_iothreaddel.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_iothreaddel.cfg @@ -10,6 +10,7 @@ iothreads = "2" iothreadpins = "2:1 1:0-1" iothread_id = "2" + start_vm = 'no' variants: - normal_test: status_error = "no" diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_iothreadinfo.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_iothreadinfo.cfg index 5eb1dafd25c..dc7ecb449fc 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_iothreadinfo.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_iothreadinfo.cfg @@ -9,6 +9,7 @@ # The format of iothreadpins is IOTHEADID:CPUSET iothreads = "2" iothreadpins = "2:1 1:0-1" + start_vm = 'no' variants: - normal_test: status_error = "no" diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_iothreadpin.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_iothreadpin.cfg index 66396d8f780..f05f60dcf3b 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_iothreadpin.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_iothreadpin.cfg @@ -9,6 +9,7 @@ iothreads = "2" iothreadpins = "2:1 1:0-1" iothread_id = "2" + start_vm = 'no' variants: - normal_test: cpuset = "1" diff --git a/libvirt/tests/src/cpu/iothread.py b/libvirt/tests/src/cpu/iothread.py index 13cde5619ce..48afd624431 100644 --- a/libvirt/tests/src/cpu/iothread.py +++ b/libvirt/tests/src/cpu/iothread.py @@ -45,6 +45,7 @@ def update_iothread_xml(define_error=False): """ vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) vm_attrs = eval(params.get("vm_attrs", "{}")) + iothread_config = eval(params.get("iothread_config", "{}")) del vmxml.cputune del vmxml.iothreadids del vmxml.iothreads @@ -55,6 +56,9 @@ def update_iothread_xml(define_error=False): if iothread_ids: ids_xml = vm_xml.VMIothreadidsXML() ids_xml.iothread = [{'id': id} for id in iothread_ids.split()] + if iothread_config: + ids_xml.iothread = iothread_config['iothread'] + vmxml.iothreadids = ids_xml # Set cputune if any([iothreadpins, iothreadscheds, iothread_quota, iothread_period]): @@ -226,9 +230,13 @@ def exec_iothreadadd(): iothreadadd, "add") # Check xml xml_info = vm_xml.VMXML.new_from_dumpxml(vm_name) - if {'id': iothreadadd} not in xml_info.iothreadids.iothread: - test.fail("The iothread id {} is not added into xml" - .format(iothreadadd)) + found = False + for a_iothread in xml_info.iothreadids.iothread: + if iothreadadd == a_iothread['id']: + found = True + if not found: + test.fail("The iothread id {} is not " + "added into xml".format(iothreadadd)) def exec_iothreadpin(): """ @@ -236,7 +244,6 @@ def exec_iothreadpin(): :raise: test.fail if virsh command failed """ - thread_id, cpuset = iothreadpin.split() virsh.iothreadpin(vm_name, thread_id, cpuset, debug=True) update_expected_iothreadinfo(exp_iothread_info, @@ -247,6 +254,73 @@ def exec_iothreadpin(): if item not in xml_info.cputune.iothreadpins: test.fail("Unable to get {} from xml".format(item)) + def _reassemble_iothread_config(mapping): + """ + Reassemble iothreads using configuration + + :param mapping: dict, mapping from command line option to object key + :return: dict, the assembled iothreads + """ + iothread_config = eval(params.get('iothread_config', '{}')) + iothreadset_val = params.get('iothreadset_val') + iothread1 = {'id': params.get('iothreadset_id')} + tmp_poll = {} + lst = iothreadset_val.split('--') + for item in lst: + if not item: + continue + if item.split()[0] in mapping: + tmp_poll.update({mapping[item.split()[0]]: item.split()[1]}) + else: + iothread1.update({re.sub('-', '_', item.split()[0]): item.split()[1]}) + iothread1.update({'poll': tmp_poll}) + iothread_config['iothread'].append(iothread1) + logging.debug("Configured iothreads:%s", iothread_config['iothread']) + return iothread_config + + def _verify_iothreadids_by_domstats(iothread_id, mapping, iothread_attrs): + """ + Verify domstats output for iothreads + + :param iothread_id: str, iothread id + :param mapping: dict, mapping from command line option to object key + :param iothread_attrs: dict, attributes for iothread + """ + current_poll_info = get_iothread_pool(vm_name, iothread_id) + converted_poll_dict = {} + for key, value in current_poll_info.items(): + key_iothread = mapping[key[key.rindex('.') + 1: len(key)]] + converted_poll_dict.update({key_iothread: value}) + + if converted_poll_dict != iothread_attrs['poll']: + test.fail("Expect iothread poll info to be '%s'," + " but found '%s'" % (iothread_attrs['poll'], + converted_poll_dict)) + logging.debug("Verify domstats output for iothread %s - PASS", iothread_id) + + def verify_iothread_by_vm_xml(): + """ + Verify iothreads by checking dump vm xml + """ + mapping = {'poll-max-ns': 'max', 'poll-grow': 'grow', 'poll-shrink': 'shrink'} + iothread_config = _reassemble_iothread_config(mapping) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + iothreadid_list = vmxml.iothreadids.iothread + for one_iothread in iothreadid_list: + iothread_attrs = one_iothread.fetch_attrs() + iothread_id = iothread_attrs['id'] + iothread_id_found = False + for iothread_cfg in iothread_config['iothread']: + if iothread_id == iothread_cfg['id']: + iothread_id_found = True + if iothread_attrs != iothread_cfg: + test.fail("Expect iothread to be '%s', " + "but found '%s'" % (iothread_cfg, iothread_attrs)) + if not iothread_id_found: + test.fail("The iothread '%s' is not expected in vm xml" % iothread_id) + _verify_iothreadids_by_domstats(iothread_id, mapping, iothread_attrs) + logging.debug("Verify iothread attributes by vm xml - PASS") + def verify_thread_pool(): """ Verify the thread pool values are updated correctly @@ -298,14 +372,16 @@ def verify_poll(): check_iothread_pool(UPDATE_IOTHREAD_POOL, exp_pool, True) logging.debug("Verify iothread poll: PASS") - def exec_iothreadset(): + def exec_iothreadset(need_verify=True): """ Run "virsh iothreadset" and do checking according to the parameters + :param need_verify: boolean, True to verify more, + False to only execute iothreadset """ test_poll = True if '--poll' in params.get('iothreadset_val') else False test_thread_pool = True if '--thread-pool' in params.get('iothreadset_val') else False - if test_poll: + if test_poll and need_verify: # Check domstats before run virsh iothreadset global ORG_IOTHREAD_POOL ORG_IOTHREAD_POOL = get_iothread_pool(vm_name, iothreadset_id) @@ -316,9 +392,9 @@ def exec_iothreadset(): if err_msg: libvirt.check_result(result, expected_fails=err_msg) - if test_poll: + if test_poll and need_verify: verify_poll() - if test_thread_pool: + if test_thread_pool and need_verify: verify_thread_pool() def exec_attach_disk(vm_name, source, target, thread_id, @@ -468,10 +544,12 @@ def _exec_schedinfo(items, update_error=False): pre_vm_stats = params.get("pre_vm_stats") restart_libvirtd = "yes" == params.get("restart_libvirtd", "no") restart_vm = "yes" == params.get("restart_vm", "no") - start_vm = "yes" == params.get("start_vm", "no") + need_start_vm = "yes" == params.get("need_start_vm", "no") test_operations = params.get("test_operations") cmd_options = params.get("cmd_options", '') + check_iotheadids_inactive = params.get("check_iotheadids_inactive") + status_error = "yes" == params.get("status_error", "no") define_error = "yes" == params.get("define_error", "no") err_msg = params.get("err_msg") @@ -517,7 +595,8 @@ def _exec_schedinfo(items, update_error=False): elif action == "iothreadpin": exec_iothreadpin() elif action == "iothreadset": - exec_iothreadset() + need_verify = False if check_iotheadids_inactive else True + exec_iothreadset(need_verify) elif action == "checkschedinfo": check_schedinfo() elif action == "attachdisk": @@ -542,7 +621,7 @@ def _exec_schedinfo(items, update_error=False): after_restart_domstas, True) # Check if vm could start successfully - if start_vm: + if need_start_vm: if vm.is_alive(): vm.destroy() result = virsh.start(vm_name, debug=True) @@ -550,6 +629,8 @@ def _exec_schedinfo(items, update_error=False): libvirt.check_exit_status(result, status_error) if err_msg: libvirt.check_result(result, expected_fails=err_msg) + if check_iotheadids_inactive: + verify_iothread_by_vm_xml() if not status_error: iothread_info = libvirt.get_iothreadsinfo(vm_name) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_iothreadadd.py b/libvirt/tests/src/virsh_cmd/domain/virsh_iothreadadd.py index df59d8077f4..81d5a4db3ef 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_iothreadadd.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_iothreadadd.py @@ -26,6 +26,23 @@ def get_xmlinfo(vm_name, options): return xml_info.iothreadids.iothread +def check_iothread_id(iothread_list, search_iothread_id, test): + """ + Check if the specified iothread id exists + + :param iothread_list: list, iothread id information + :param search_iothread_id: str, the iothread id to be searched + :param test: test object + """ + found = False + for a_iothread in iothread_list: + if search_iothread_id == a_iothread['id']: + found = True + if not found: + test.fail("Can not find iothread '%s' in " + "domain xml" % search_iothread_id) + + def run(test, params, env): """ Test command: virsh iothread. @@ -115,9 +132,7 @@ def run(test, params, env): # Check domainxml iothread_info = get_xmlinfo(vm_name, options) logging.debug("iothreadinfo: %s", iothread_info) - if {'id': iothread_id} not in iothread_info: - test.fail("Failed to add iothread '%s' in " - "domain xml" % iothread_id) + check_iothread_id(iothread_info, iothread_id, test) # Check iothreadinfo by virsh command iothread_info = libvirt.get_iothreadsinfo(dom_option, options) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_iothreaddel.py b/libvirt/tests/src/virsh_cmd/domain/virsh_iothreaddel.py index a4a6f63e6ba..90867b71eeb 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_iothreaddel.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_iothreaddel.py @@ -26,6 +26,23 @@ def get_xmlinfo(vm_name, options): return xml_info.iothreadids.iothread +def check_iothread_id(iothread_list, search_iothread_id, test): + """ + Check if the specified iothread id exists + + :param iothread_list: list, iothread id information + :param search_iothread_id: str, the iothread id to be searched + :param test: test object + """ + found = False + for a_iothread in iothread_list: + if search_iothread_id == a_iothread['id']: + found = True + if found: + test.fail("Can find iothread '%s' in " + "domain xml" % search_iothread_id) + + def run(test, params, env): """ Test command: virsh iothreaddel. @@ -115,15 +132,13 @@ def run(test, params, env): # Check domainxml iothread_info = get_xmlinfo(vm_name, options) logging.debug("iothreadinfo: %s", iothread_info) - if iothread_id in iothread_info: - raise exceptions.TestFail("Failed to add iothread %s in domain xml", - iothread_id) + check_iothread_id(iothread_info, iothread_id, test) # Check iothreadinfo by virsh command iothread_info = libvirt.get_iothreadsinfo(dom_option, options) logging.debug("iothreadinfo: %s", iothread_info) if iothread_id in iothread_info: - raise exceptions.TestFail("Failed to add iothread %s", iothread_id) + raise exceptions.TestFail("Failed to delete iothread %s", iothread_id) finally: # Cleanup From 64fc8f713ed997b03dd45f07cddb7bdfef989531 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Sun, 19 Nov 2023 19:27:54 +0800 Subject: [PATCH 0016/1055] auto_memory_placement_numad_fail: add case This is to verify expected error message when numad service fails. Signed-off-by: Dan Zheng --- .../auto_memory_placement_numad_fail.cfg | 15 +++ .../auto_memory_placement_numad_fail.py | 102 ++++++++++++++++++ provider/numa/numa_base.py | 5 +- 3 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 libvirt/tests/cfg/numa/guest_numa_node_tuning/auto_memory_placement_numad_fail.cfg create mode 100644 libvirt/tests/src/numa/guest_numa_node_tuning/auto_memory_placement_numad_fail.py diff --git a/libvirt/tests/cfg/numa/guest_numa_node_tuning/auto_memory_placement_numad_fail.cfg b/libvirt/tests/cfg/numa/guest_numa_node_tuning/auto_memory_placement_numad_fail.cfg new file mode 100644 index 00000000000..bd0d4085590 --- /dev/null +++ b/libvirt/tests/cfg/numa/guest_numa_node_tuning/auto_memory_placement_numad_fail.cfg @@ -0,0 +1,15 @@ +- guest_numa_node_tuning.auto_memory_placement_numad_fail: + type = auto_memory_placement_numad_fail + take_regular_screendumps = no + start_vm = "no" + err_msg = "Failed to query numad for the advisory nodeset" + variants memory_binding_mode: + - mem_mode_strict: + mem_mode = 'strict' + - mem_mode_interleave: + mem_mode = 'interleave' + - mem_mode_preferred: + mem_mode = 'preferred' + - mem_mode_restrictive: + mem_mode = 'restrictive' + numa_memory = {'mode': '${mem_mode}', 'placement': 'auto'} diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/auto_memory_placement_numad_fail.py b/libvirt/tests/src/numa/guest_numa_node_tuning/auto_memory_placement_numad_fail.py new file mode 100644 index 00000000000..31f5edff40c --- /dev/null +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/auto_memory_placement_numad_fail.py @@ -0,0 +1,102 @@ +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: Dan Zheng +# + +import os +import shutil + +from avocado.utils import process + +from virttest import data_dir +from virttest import virsh + +from virttest.utils_test import libvirt + +from provider.numa import numa_base + + +def modify_numad_executable_file(numatest_obj): + """ + Modify numad executable file + + :param numatest_obj: NumaTest object + """ + dest_dir = os.path.join(data_dir.get_tmp_dir(), 'numad') + numad_path_origin = '/usr/bin/numad' + shutil.copyfile(numad_path_origin, dest_dir) + new_numad_content = """ +#! /bin/sh +exit 1""" + + with open(numad_path_origin, 'w') as fp: + fp.write(new_numad_content) + + process.run('restorecon %s' % numad_path_origin, shell=True) + numatest_obj.test.log.debug("Backup the numad file to %s", dest_dir) + return dest_dir + + +def setup_default(numatest_obj): + """ + Default setup function for the test + + :param numatest_obj: NumaTest object + """ + dest_dir = modify_numad_executable_file(numatest_obj) + numatest_obj.test.params['numad_backup'] = dest_dir + numatest_obj.setup() + numatest_obj.test.log.debug("Step: setup is done") + + +def run_default(numatest_obj): + """ + Default run function for the test + + :param numatest_obj: NumaTest object + """ + numatest_obj.test.log.debug("Step: prepare vm xml") + vmxml = numatest_obj.prepare_vm_xml() + numatest_obj.test.log.debug("Step: define vm") + ret = virsh.define(vmxml.xml, **numatest_obj.virsh_dargs) + numatest_obj.test.log.debug("Step: start vm and check result") + numatest_obj.virsh_dargs.update({'ignore_status': True}) + ret = virsh.start(numatest_obj.vm.name, **numatest_obj.virsh_dargs) + err_msg_expected = numatest_obj.produce_expected_error() + libvirt.check_result(ret, expected_fails=err_msg_expected) + + +def teardown_default(numatest_obj): + """ + Default teardown function for the test + + :param numatest_obj: NumaTest object + """ + numatest_obj.teardown() + numad_backup = numatest_obj.test.params['numad_backup'] + numad_path_origin = '/usr/bin/numad' + with open(numad_path_origin) as fp: + numatest_obj.test.log.debug("Before recovering, " + "%s is%s", numad_path_origin, fp.read()) + shutil.copyfile(numad_backup, numad_path_origin) + process.run('restorecon %s' % numad_path_origin, shell=True) + numatest_obj.test.log.debug("Step: teardown is done") + + +def run(test, params, env): + """ + Test for numa memory binding with emulator thread pin + """ + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + numatest_obj = numa_base.NumaTest(vm, params, test) + try: + setup_default(numatest_obj) + run_default(numatest_obj) + finally: + teardown_default(numatest_obj) diff --git a/provider/numa/numa_base.py b/provider/numa/numa_base.py index d1eacc97843..dcb46cc157f 100644 --- a/provider/numa/numa_base.py +++ b/provider/numa/numa_base.py @@ -74,14 +74,15 @@ def prepare_vm_xml(self): :return: VMXML object """ single_host_node = self.params.get('single_host_node') - vm_attrs = eval(self.params.get('vm_attrs')) + vm_attrs = eval(self.params.get('vm_attrs', '{}')) numa_memory = self.params.get('numa_memory') numa_memnode = self.params.get('numa_memnode') memory_backing = eval(self.params.get('memory_backing', '{}')) # Setup vm basic attributes vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(self.vm.name) - vmxml.setup_attrs(**vm_attrs) + if vm_attrs: + vmxml.setup_attrs(**vm_attrs) # Setup numa tune attributes nodeset = None From 5ed53662bf2680f764f88dd98669097ab0b03850 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Sun, 19 Nov 2023 21:05:12 -0500 Subject: [PATCH 0017/1055] guest os booting: add hotplug case with boot order element This PR mainly implements the hotpluging of disk/usb/filesystem devices with boot order elements. Signed-off-by: Meina Li --- .../hotplug_device_with_boot_order.cfg | 20 ++++ .../hotplug_device_with_boot_order.py | 100 ++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 libvirt/tests/cfg/guest_os_booting/boot_order/hotplug_device_with_boot_order.cfg create mode 100644 libvirt/tests/src/guest_os_booting/boot_order/hotplug_device_with_boot_order.py diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/hotplug_device_with_boot_order.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/hotplug_device_with_boot_order.cfg new file mode 100644 index 00000000000..bdf0b26fdbc --- /dev/null +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/hotplug_device_with_boot_order.cfg @@ -0,0 +1,20 @@ +- guest_os_booting.boot_order.hotplug: + type = hotplug_device_with_boot_order + start_vm = no + target_dev = "vda" + boot_order = 1 + order_xpath = [{'element_attrs': ["./devices/disk/boot[@order='2']"]}] + variants device_type: + - disk_device: + bus_type = "virtio" + target_disk = "vdb" + device_dict = {"type_name":"file", "target":{"dev": "${target_disk}", "bus": "${bus_type}"}, 'boot': '2'} + - usb_device: + bus_type = "usb" + target_disk = "sda" + device_dict = {"type_name":"file", "target":{"dev": "${target_disk}", "bus": "${bus_type}"}, 'boot': '2'} + - filesystem_device: + target_dir = "mount_tag" + source_dir = "/tmp" + order_xpath = [{'element_attrs': ["./devices/filesystem/boot[@order='2']"]}] + device_dict = {'target': {'dir': '${target_dir}'}, 'type_name': 'mount', 'source': {'dir': '${source_dir}'}, 'binary': {'path': '/usr/libexec/virtiofsd'}, 'accessmode': 'passthrough', 'boot': '2', 'driver': {'type': 'virtiofs'}} diff --git a/libvirt/tests/src/guest_os_booting/boot_order/hotplug_device_with_boot_order.py b/libvirt/tests/src/guest_os_booting/boot_order/hotplug_device_with_boot_order.py new file mode 100644 index 00000000000..fad6486a6be --- /dev/null +++ b/libvirt/tests/src/guest_os_booting/boot_order/hotplug_device_with_boot_order.py @@ -0,0 +1,100 @@ +# Copyright Red Hat +# SPDX-License-Identifier: GPL-2.0 +# Author: Meina Li + +import os + +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.devices.filesystem import Filesystem +from virttest.utils_libvirt import libvirt_vmxml + +from provider.virtual_disk import disk_base + + +def run(test, params, env): + """ + This case is to verify hotplugging device with boot order element. + 1) Prepare a running guest. + 2) Hotplug the device with boot order element. + 3) Check the dumpxml. + 4) Hot-unplug the device. + """ + def prepare_device_xml(vm_xml, device_type): + """ + Prepare the hot-plugged device xml. + + :params vm_xml: the instance of VMXML class + :params device_type: the device type + :return: tuple, (device_xml, image_path) for the attached device + """ + image_path = '' + # Need to use shared memory for filesystem device + if device_type == "filesystem_device": + vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", + hpgs=False) + device_xml = Filesystem() + device_xml.setup_attrs(**device_dict) + else: + device_xml, image_path = disk_obj.prepare_disk_obj("file", device_dict) + return device_xml, image_path + + def check_dumpxml(device_type, image_path, exist): + """ + Check if the device is existed and included the boot order element. + + :params device_type: the device type + :params image_path: the disk path + :params exist: whether the device is existed + """ + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + test.log.debug(f"The current guest xml is: {vmxml}") + if device_type == "filesystem_device": + device_status = vmxml.devices.by_device_tag('filesystem') + else: + device_status = vm_xml.VMXML.check_disk_exist(vm_name, image_path) + if exist: + if not device_status: + test.fail(f"No {device_type} in guest xml after hotplug.") + # To make sure the boot order is also in device xml + libvirt_vmxml.check_guest_xml_by_xpaths(vmxml, order_xpath, ignore_status=False) + else: + if device_status: + test.fail(f"The {device_type} isn't detached successfully.") + + vm_name = params.get("main_vm") + device_type = params.get("device_type") + target_dev = params.get("target_dev") + boot_order = params.get("boot_order", "1") + device_dict = eval(params.get("device_dict")) + order_xpath = eval(params.get("order_xpath")) + virsh_dargs = {'debug': True, 'ignore_status': False} + + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + disk_obj = disk_base.DiskBase(test, vm, params) + + try: + test.log.info("STEP1: Prepare a guest with boot order.") + vmxml.remove_all_boots() + vmxml.set_boot_order_by_target_dev(target_dev, order=boot_order) + vmxml.sync() + + test.log.info(f"STEP2: Hotplug the {device_type}.") + device_xml, image_path = prepare_device_xml(vm_xml, device_type) + if not vm.is_alive(): + virsh.start(vm_name, **virsh_dargs) + vm.wait_for_login() + virsh.attach_device(vm_name, device_xml.xml, **virsh_dargs) + check_dumpxml(device_type, image_path, exist=True) + + test.log.info(f"STEP3: Hot-unplug the {device_type}.") + virsh.detach_device(vm_name, device_xml.xml, wait_for_event=True, **virsh_dargs) + check_dumpxml(device_type, image_path, exist=False) + finally: + if vm.is_alive(): + virsh.destroy(vm_name, **virsh_dargs) + if image_path and os.path.exists(image_path): + os.remove(image_path) + bkxml.sync() From 754a9a6dddbaed64568f6037c735d96ec86ee849 Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 20 Nov 2023 10:54:46 +0800 Subject: [PATCH 0018/1055] migration: Remove disk size checkpoint Since the image on source host will be compressed and the image on targe host will not be compressed, the disk size of the image will be inconsistent on the source host and target host. So remove disk size checkpoint. Signed-off-by: lcheng --- .../migration_with_backingchain.cfg | 1 - .../migration_with_backingchain.py | 25 ++++++------------- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/libvirt/tests/cfg/migration_with_copy_storage/migration_with_backingchain.cfg b/libvirt/tests/cfg/migration_with_copy_storage/migration_with_backingchain.cfg index c404c85f4b8..8f720bb4901 100644 --- a/libvirt/tests/cfg/migration_with_copy_storage/migration_with_backingchain.cfg +++ b/libvirt/tests/cfg/migration_with_copy_storage/migration_with_backingchain.cfg @@ -28,7 +28,6 @@ disk_target1 = "vdb" disk_target2 = "vdc" disk_size = "1G" - disk_diff_rate = "0.7" setup_nfs = "no" nfs_mount_dir = common_disk_dict = '"type_name":"file", "driver": {"name": "qemu", "type":"qcow2"}' diff --git a/libvirt/tests/src/migration_with_copy_storage/migration_with_backingchain.py b/libvirt/tests/src/migration_with_copy_storage/migration_with_backingchain.py index f942ceb2ef6..1a600b0e896 100644 --- a/libvirt/tests/src/migration_with_copy_storage/migration_with_backingchain.py +++ b/libvirt/tests/src/migration_with_copy_storage/migration_with_backingchain.py @@ -1,4 +1,3 @@ -import math import os import time @@ -123,7 +122,7 @@ def get_remote_disk_info(params, disk_img, test): return disk_info_dict -def check_disk_info(params, old_disk_info, disk_img, test, disk_diff_rate=None): +def check_disk_info(params, old_disk_info, disk_img, test): """ Check disk information @@ -131,18 +130,10 @@ def check_disk_info(params, old_disk_info, disk_img, test, disk_diff_rate=None): :param old_disk_info: disk information on source host :param disk_img: disk image path :param test: test object - :param disk_diff_rate: the different rate for disk image """ new_disk_info = get_remote_disk_info(params, disk_img, test) if old_disk_info['vsize'] != new_disk_info['vsize']: test.fail("Check virtual size failed: old: %s, new: %s." % (old_disk_info['vsize'], new_disk_info['vsize'])) - if disk_diff_rate: - if (math.fabs(float(new_disk_info['dsize']) - float(old_disk_info['dsize'])) // - float(old_disk_info['dsize']) > disk_diff_rate): - test.fail("Check disk size failed: old: %s, new: %s." % (old_disk_info['dsize'], new_disk_info['dsize'])) - else: - if old_disk_info['dsize'] != new_disk_info['dsize']: - test.fail("Check disk size failed: old: %s, new: %s." % (old_disk_info['dsize'], new_disk_info['dsize'])) def check_disk(params, vm): @@ -284,13 +275,12 @@ def verify_with_backing_chain(): top_img = params.get("top_img") top1_img = params.get("top1_img") top2_img = params.get("top2_img") - disk_diff_rate = float(params.get("disk_diff_rate")) test.log.debug("Verify step for backing chain case.") migration_obj.verify_default() - check_disk_info(params, old_disk_info["old_vda_info"], top_img, test, disk_diff_rate) - check_disk_info(params, old_disk_info["old_vdb_info"], top1_img, test, disk_diff_rate) - check_disk_info(params, old_disk_info["old_vdc_info"], top2_img, test, disk_diff_rate) + check_disk_info(params, old_disk_info["old_vda_info"], top_img, test) + check_disk_info(params, old_disk_info["old_vdb_info"], top1_img, test) + check_disk_info(params, old_disk_info["old_vdc_info"], top2_img, test) check_disk(params, vm) def verify_without_backing_chain(): @@ -299,14 +289,13 @@ def verify_without_backing_chain(): """ mig_disk1 = params.get("mig_disk1") mig_disk2 = params.get("mig_disk2") - disk_diff_rate = float(params.get("disk_diff_rate")) test.log.debug("Verify step for without backing chain case.") migration_obj.verify_default() source_file = vm.get_first_disk_devices()['source'] - check_disk_info(params, old_disk_info["old_vda_info"], source_file, test, disk_diff_rate=disk_diff_rate) - check_disk_info(params, old_disk_info["old_vdb_info"], mig_disk1, test, disk_diff_rate) - check_disk_info(params, old_disk_info["old_vdc_info"], mig_disk2, test, disk_diff_rate) + check_disk_info(params, old_disk_info["old_vda_info"], source_file, test) + check_disk_info(params, old_disk_info["old_vdb_info"], mig_disk1, test) + check_disk_info(params, old_disk_info["old_vdc_info"], mig_disk2, test) check_disk(params, vm) def cleanup_with_backing_chain(): From 74b0a6e162d270daa9f38fdd7bda149c99bbd631 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 20 Nov 2023 02:39:58 -0500 Subject: [PATCH 0019/1055] memory_tuning: add new case for memory tuning Signed-off-by: liang-cong-red-hat --- .../tests/src/memory/memory_tuning/memory_tuning_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py b/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py index 9bc3b15960e..5c333c49e62 100644 --- a/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py +++ b/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py @@ -109,7 +109,7 @@ def run_test(): Test steps """ - test.log.info("TEST_SETUP1: Define the guest") + test.log.info("TEST_STEP1: Define the guest") vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) vmxml.setup_attrs(**vm_attrs) virsh.define(vmxml.xml, ignore_status=False, debug=True) From 06a186534b0cdd595ab9571224222b38816b6ed2 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 20 Nov 2023 02:50:46 -0500 Subject: [PATCH 0020/1055] Add spell check ignore words Signed-off-by: liang-cong-red-hat --- spell.ignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spell.ignore b/spell.ignore index 1fa9be1a81c..98781bccb5f 100644 --- a/spell.ignore +++ b/spell.ignore @@ -150,6 +150,7 @@ conf config Config configs +Cong coredump corescount cpu @@ -492,6 +493,8 @@ kwargs lan lcheng lchown +lcong +Liang libexec libguestfs libnbd From 1bcec7b0c8454072c9a281744af0cf7d13b074f6 Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 21 Nov 2023 12:10:40 +0800 Subject: [PATCH 0021/1055] migration: Add case about heavy disk I/O load in vm XXX-298242 - VM live migration with copy storage - migrate vm with heavy disk I/O load in vm Signed-off-by: lcheng --- .../disk_io_load_in_vm.cfg | 40 ++++++++++ .../disk_io_load_in_vm.py | 80 +++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 libvirt/tests/cfg/migration_with_copy_storage/disk_io_load_in_vm.cfg create mode 100644 libvirt/tests/src/migration_with_copy_storage/disk_io_load_in_vm.py diff --git a/libvirt/tests/cfg/migration_with_copy_storage/disk_io_load_in_vm.cfg b/libvirt/tests/cfg/migration_with_copy_storage/disk_io_load_in_vm.cfg new file mode 100644 index 00000000000..73203b1a903 --- /dev/null +++ b/libvirt/tests/cfg/migration_with_copy_storage/disk_io_load_in_vm.cfg @@ -0,0 +1,40 @@ +- migration_with_copy_storage.disk_io_load_in_vm: + type = disk_io_load_in_vm + migration_setup = 'yes' + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = "" + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = "qemu:///system" + image_convert = "no" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + start_vm = "yes" + setup_nfs = "no" + nfs_mount_dir = + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + status_error = "no" + variants: + - p2p: + virsh_migrate_options = "--live --p2p --verbose" + - non_p2p: + virsh_migrate_options = "--live --verbose" + variants: + - with_sync_writes: + virsh_migrate_extra = "--copy-storage-synchronous-writes" + - without_sync_writes: + variants: + - copy_storage_all: + copy_storage_option = "--copy-storage-all" + - copy_storage_inc: + copy_storage_option = "--copy-storage-inc" diff --git a/libvirt/tests/src/migration_with_copy_storage/disk_io_load_in_vm.py b/libvirt/tests/src/migration_with_copy_storage/disk_io_load_in_vm.py new file mode 100644 index 00000000000..509e53e8631 --- /dev/null +++ b/libvirt/tests/src/migration_with_copy_storage/disk_io_load_in_vm.py @@ -0,0 +1,80 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: Liping Cheng +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from virttest import remote +from virttest import utils_package + +from provider.migration import base_steps + + +def run(test, params, env): + """ + To verify that vm migration can succeed when there is heavy disk I/O load + in vm. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def setup_test(): + """ + Setup steps + + """ + test.log.info("Setup steps.") + migration_obj.setup_connection() + session = vm.wait_for_login() + utils_package.package_install(["gcc", "fio"], session, 360) + shell_file = "/tmp/fio_test.sh" + fio_cmd = ['while true', + 'do', + ' fio -name=aaa -direct=1 -iodepth=32 -rw=randrw -ioengine=libaio -bs=16k -size=1G -numjobs=2 -group_reporting -directory=/ &>/dev/null', + 'done'] + remote_file = remote.RemoteFile(vm.get_address(), 'scp', 'root', + params.get('password'), 22, + shell_file) + remote_file.truncate() + remote_file.add(fio_cmd) + session.cmd('chmod 777 %s' % shell_file) + session.cmd('%s &' % shell_file) + session.close() + + def verify_test(): + """ + Verify steps + + """ + dest_uri = params.get("virsh_migrate_desturi") + + test.log.info("Verify steps.") + backup_uri, vm.connect_uri = vm.connect_uri, dest_uri + vm.cleanup_serial_console() + vm.create_serial_console() + remote_vm_session = vm.wait_for_serial_login(timeout=360) + remote_vm_dmesg = remote_vm_session.cmd_output("dmesg") + if "I/O error" in remote_vm_dmesg: + test.fail(f"Found I/O error in guest dmesg: {remote_vm_dmesg}") + remote_vm_session.close() + vm.connect_uri = backup_uri + + migration_obj.verify_default() + + vm_name = params.get("migrate_main_vm") + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + setup_test() + base_steps.prepare_disks_remote(params, vm) + migration_obj.run_migration() + verify_test() + finally: + migration_obj.cleanup_connection() + base_steps.cleanup_disks_remote(params, vm) From 92ec8a9781350518f84f85c5248931bd90fc2cad Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 10 Nov 2023 18:48:07 +0800 Subject: [PATCH 0022/1055] virtual_network: Add a case about mem_lock limit for vm with multiple vdpa interfaces This PR adds: VIRT-296169 - [vdpa] Check the mem_lock limit when start vm with multiple vdpa interfaces Signed-off-by: Yingshun Cui --- ...em_lock_limit_multiple_vdpa_interfaces.cfg | 10 +++ ...mem_lock_limit_multiple_vdpa_interfaces.py | 69 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/locked_memory_vdpa/mem_lock_limit_multiple_vdpa_interfaces.cfg create mode 100644 libvirt/tests/src/virtual_network/locked_memory_vdpa/mem_lock_limit_multiple_vdpa_interfaces.py diff --git a/libvirt/tests/cfg/virtual_network/locked_memory_vdpa/mem_lock_limit_multiple_vdpa_interfaces.cfg b/libvirt/tests/cfg/virtual_network/locked_memory_vdpa/mem_lock_limit_multiple_vdpa_interfaces.cfg new file mode 100644 index 00000000000..c03d03e9402 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/locked_memory_vdpa/mem_lock_limit_multiple_vdpa_interfaces.cfg @@ -0,0 +1,10 @@ +- virtual_network.locked_memory.vdpa_interfaceiface.multiple_interfaces: + type = mem_lock_limit_multiple_vdpa_interfaces + start_vm = no + only x86_64 + + func_supported_since_libvirt_ver = (8, 7, 0) + vm_attrs = {'max_mem_rt': 6291456, 'max_mem_rt_slots': 32, 'max_mem_rt_unit': 'K', 'current_mem':3, 'current_mem_unit': 'GiB','vcpu': 8, 'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-3', 'memory': '1', 'unit': 'GiB'}, {'id': '1', 'cpus': '4-7', 'memory': '1', 'unit': 'GiB'}]}} + iface_dict1 = {"source": {'dev':'/dev/vhost-vdpa-0'}} + iface_dict2 = {"source": {'dev':'/dev/vhost-vdpa-1'}} + iface_dict3 = {"source": {'dev':'/dev/vhost-vdpa-2'}} diff --git a/libvirt/tests/src/virtual_network/locked_memory_vdpa/mem_lock_limit_multiple_vdpa_interfaces.py b/libvirt/tests/src/virtual_network/locked_memory_vdpa/mem_lock_limit_multiple_vdpa_interfaces.py new file mode 100644 index 00000000000..794b288a645 --- /dev/null +++ b/libvirt/tests/src/virtual_network/locked_memory_vdpa/mem_lock_limit_multiple_vdpa_interfaces.py @@ -0,0 +1,69 @@ +from avocado.utils import process + +from virttest import libvirt_version +from virttest import utils_vdpa + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_memory +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.interface import interface_base + + +def run(test, params, env): + """ + Check mem_lock limit for vm with multiple vDPA interfaces. + """ + libvirt_version.is_libvirt_feature_supported(params) + # Variable assignment + dev_type = params.get('dev_type', 'vdpa') + iface_num = 3 + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + backup_vmxml = vmxml.copy() + + try: + pf_pci = utils_vdpa.get_vdpa_pci() + test_env_obj = utils_vdpa.VDPAOvsTest(pf_pci) + test_env_obj.setup() + qemu_log = "/var/log/libvirt/qemu/%s.log" % vm.name + process.run("echo > {}".format(qemu_log), shell=True) + + libvirt_vmxml.remove_vm_devices_by_type(vm, 'interface') + + vm_attrs = eval(params.get('vm_attrs', '{}')) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + vmxml.setup_attrs(**vm_attrs) + vmxml.sync() + test.log.debug("Updated VM xml: %s.", + vm_xml.VMXML.new_from_dumpxml(vm_name)) + for idx in range(iface_num): + default_iface = {'source': {'dev': '/dev/vhost-vdpa-%s' % str(idx)}} + iface_dict = eval(params.get( + 'iface_dict%s' % str(idx+1), str(default_iface))) + if iface_dict: + iface_dev = interface_base.create_iface(dev_type, iface_dict) + libvirt.add_vm_device(vm_xml.VMXML.new_from_dumpxml(vm_name), + iface_dev) + test.log.debug("VM xml after updating ifaces: %s.", + vm_xml.VMXML.new_from_dumpxml(vm_name)) + + test.log.info("TEST_STEP: Start the vm with 3 vDPA interfaces.") + vm.start() + vm.wait_for_serial_login(timeout=240).close() + + new_vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + expr_memlock = libvirt_memory.normalize_mem_size( + new_vmxml.get_current_mem(), + new_vmxml.get_current_mem_unit()) * 3 + 1073741824 + if not libvirt_memory.comp_memlock(expr_memlock): + test.fail("Unable to get correct MEMLOCK after VM startup!") + + test.log.info("TEST_STEP: Check qemu log.") + libvirt.check_logfile("fail|error", qemu_log, str_in_log=False) + finally: + backup_vmxml.sync() + test_env_obj.cleanup() From 7c027019c1ca0041844c118578bcb16016d5da6a Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 10 Nov 2023 16:44:23 +0800 Subject: [PATCH 0023/1055] virtual_network: Add a case about memlock limit for vdpa interfaces This PR adds: RHEL-283024 - [vdpa] hotplug memory to vm with vdpa type interface and check the memlock limit Signed-off-by: Yingshun Cui --- .../hotplug_mem_to_vm_with_vdpa.cfg | 30 +++ .../hotplug_mem_to_vm_with_vdpa.py | 207 ++++++++++++++++++ 2 files changed, 237 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/locked_memory_vdpa/hotplug_mem_to_vm_with_vdpa.cfg create mode 100644 libvirt/tests/src/virtual_network/locked_memory_vdpa/hotplug_mem_to_vm_with_vdpa.py diff --git a/libvirt/tests/cfg/virtual_network/locked_memory_vdpa/hotplug_mem_to_vm_with_vdpa.cfg b/libvirt/tests/cfg/virtual_network/locked_memory_vdpa/hotplug_mem_to_vm_with_vdpa.cfg new file mode 100644 index 00000000000..0a6809c426c --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/locked_memory_vdpa/hotplug_mem_to_vm_with_vdpa.cfg @@ -0,0 +1,30 @@ +- virtual_network.locked_memory.vdpa_interface.hotplug_mem: + type = hotplug_mem_to_vm_with_vdpa + start_vm = no + + current_mem = 2 + current_mem_unit = 'GiB' + cpu_setting = {'numa_cell': [{'id': '0', 'cpus': '0-3', 'memory': '1', 'unit': 'GiB'}, {'id': '1', 'cpus': '4-7', 'memory': '1', 'unit': 'GiB'}]} + max_mem_rt = 6291456 + max_mem_rt_unit = 'K' + max_mem_rt_slots = 32 + vcpu = 8 + func_supported_since_libvirt_ver = (7, 3, 0) + func_supported_since_qemu_kvm_ver = (6, 0, 0) + iface_dict = {"source": {'dev':'/dev/vhost-vdpa-0'}} + only x86_64 + + variants test_target: + - simulator: + - mellanox: + variants test_scenario: + - at_memory_to_vm_with_iface: + vm_attrs = {'max_mem_rt': ${max_mem_rt}, 'max_mem_rt_slots': ${max_mem_rt_slots}, 'max_mem_rt_unit': '${max_mem_rt_unit}', 'current_mem': ${current_mem}, 'current_mem_unit': '${current_mem_unit}','vcpu': ${vcpu}, 'cpu': ${cpu_setting}} + mem_dict = {'mem_model': 'dimm', 'target': {'size': 1, 'size_unit': 'G', 'node': 0}} + - at_memory_to_vm_with_iface_and_locked_mem: + vm_attrs = {'max_mem_rt': ${max_mem_rt}, 'max_mem_rt_slots': ${max_mem_rt_slots}, 'max_mem_rt_unit': '${max_mem_rt_unit}', 'current_mem': ${current_mem}, 'current_mem_unit': '${current_mem_unit}','vcpu': ${vcpu},'memtune':{'hard_limit': 10485760, 'hard_limit_unit': 'KiB'}, 'mb': {'locked': True}, 'cpu': ${cpu_setting}} + mem_dict = {'mem_model': 'dimm', 'target': {'size': 1, 'size_unit': 'G', 'node': 0}} + - at_iface_and_memory: + vm_attrs = {'max_mem_rt': ${max_mem_rt}, 'max_mem_rt_slots': ${max_mem_rt_slots}, 'max_mem_rt_unit': '${max_mem_rt_unit}', 'current_mem': ${current_mem}, 'current_mem_unit': '${current_mem_unit}','vcpu': ${vcpu}, 'cpu': ${cpu_setting}} + mem_dict1 = {'mem_model': 'dimm', 'target': {'size': 256, 'size_unit': 'M', 'node': 0}} + mem_dict2 = {'mem_model': 'dimm', 'target': {'size': 256, 'size_unit': 'M', 'node': 1}} diff --git a/libvirt/tests/src/virtual_network/locked_memory_vdpa/hotplug_mem_to_vm_with_vdpa.py b/libvirt/tests/src/virtual_network/locked_memory_vdpa/hotplug_mem_to_vm_with_vdpa.py new file mode 100644 index 00000000000..4537dbb5205 --- /dev/null +++ b/libvirt/tests/src/virtual_network/locked_memory_vdpa/hotplug_mem_to_vm_with_vdpa.py @@ -0,0 +1,207 @@ +from virttest import libvirt_version +from virttest import utils_misc +from virttest import utils_vdpa +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.devices.memory import Memory +from virttest.utils_libvirt import libvirt_memory +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.interface import interface_base + +VIRSH_ARGS = {'debug': True, 'ignore_status': False} + + +def run(test, params, env): + """ + Hotplug memory to vm with vDPA type interface and check the locked memory + """ + + def check_environment(params): + """ + Check the test environment + + :param params: Dictionary with the test parameters + """ + libvirt_version.is_libvirt_feature_supported(params) + utils_misc.is_qemu_function_supported(params) + + def setup_test(): + """ + Set up test + + 1) Remove interface devices + 2) Setup test environment for a specific interface if needed + 3) Set VM attrs + + :return: An object of special test environment + """ + test.log.debug("Remove VM's interface devices.") + libvirt_vmxml.remove_vm_devices_by_type(vm, 'interface') + test_env_obj = None + if test_target == "simulator": + test_env_obj = utils_vdpa.VDPASimulatorTest() + else: + pf_pci = utils_vdpa.get_vdpa_pci() + test_env_obj = utils_vdpa.VDPAOvsTest(pf_pci) + test_env_obj.setup() + + test.log.debug("Update VM's settings.") + vm_attrs = eval(params.get('vm_attrs', '{}')) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + vmxml.setup_attrs(**vm_attrs) + vmxml.sync() + test.log.debug("Updated VM xml: %s.", + vm_xml.VMXML.new_from_dumpxml(vm_name)) + return test_env_obj + + def teardown_test(): + """ + Cleanup vDPA environment + """ + if test_obj: + test_obj.cleanup() + + def setup_at_memory_to_vm_with_iface(): + """ + Prepare a vm with max memory, numa, and an interface + """ + test_env_obj = setup_test() + # Add interface device + iface_dict = eval(params.get('iface_dict', '{}')) + iface_dev = interface_base.create_iface(dev_type, iface_dict) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + libvirt.add_vm_device(vmxml, iface_dev) + test.log.debug("VM xml after updating ifaces: %s.", + vm_xml.VMXML.new_from_dumpxml(vm_name)) + return test_env_obj + + def test_at_memory_to_vm_with_iface(): + """ + hotplug memory device to vm with an interface + + 1) Start vm and check the locked memory + 2) Hotplug memory device and check the locked memory + """ + vm.start() + vm.wait_for_serial_login(timeout=240).close() + new_vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + + # MEMLOCK value is guest memory + 1G(for the passthrough device) + expr_memlock = libvirt_memory.normalize_mem_size( + new_vmxml.get_current_mem(), + new_vmxml.get_current_mem_unit()) + 1073741824 + if not libvirt_memory.comp_memlock(expr_memlock): + test.fail("Unable to get correct MEMLOCK after VM startup!") + + test.log.info("Hotplug memory device.") + mem_dict = eval(params.get('mem_dict', '{}')) + memxml = Memory() + memxml.setup_attrs(**mem_dict) + virsh.attach_device(vm_name, memxml.xml, **VIRSH_ARGS) + expr_memlock += libvirt_memory.normalize_mem_size( + mem_dict['target']['size'], mem_dict['target']['size_unit']) + if not libvirt_memory.comp_memlock(expr_memlock): + test.fail("Unable to get correct MEMLOCK after attaching a memory " + "device!") + + def test_at_iface_and_memory(): + """ + hotplug an interface and memory devices + + 1) Start vm and check the default locked memory + 2) Hotplug an interface and check the locked memory + 3) Hotplug 2 memory devices and check the locked memory + 4) Hot-unplug a memory device and check the locked memory + """ + vm.start() + vm.wait_for_serial_login(timeout=240).close() + expr_memlock = 67108864 + if not libvirt_memory.comp_memlock(expr_memlock): + test.fail("Unable to get correct default!") + + interface_base.attach_iface_device(vm_name, dev_type, params) + + new_vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + # MEMLOCK value is guest memory + 1G(for the passthrough device) + expr_memlock = libvirt_memory.normalize_mem_size( + new_vmxml.get_current_mem(), + new_vmxml.get_current_mem_unit()) + 1073741824 + if not libvirt_memory.comp_memlock(expr_memlock): + test.fail("Unable to get correct MEMLOCK after VM startup!") + + test.log.info("Hotplug memory devices.") + for mem_attrs in ['mem_dict1', 'mem_dict2']: + mem_dict = eval(params.get(mem_attrs, '{}')) + memxml = Memory() + memxml.setup_attrs(**mem_dict) + virsh.attach_device(vm_name, memxml.xml, **VIRSH_ARGS) + expr_memlock += libvirt_memory.normalize_mem_size( + mem_dict['target']['size'], mem_dict['target']['size_unit']) + if not libvirt_memory.comp_memlock(expr_memlock): + test.fail("Unable to get correct MEMLOCK after attaching a " + "memory device!") + + test.log.info("Detach a memory device and check memlock.") + memxml = vm_xml.VMXML.new_from_dumpxml( + vm_name).get_devices('memory')[-1] + cmd_result = virsh.detach_device(vm_name, memxml.xml, + wait_for_event=True, + debug=True) + if cmd_result.exit_status: + libvirt.check_result(cmd_result, 'unplug of device was rejected') + if not libvirt_memory.comp_memlock(expr_memlock): + test.fail("Detaching mem failed, MEMLOCK should not change!") + else: + if not libvirt_memory.comp_memlock(expr_memlock): + test.fail("Unable to get correct MEMLOCK after detaching a " + "memory device!") + + def setup_at_memory_to_vm_with_iface_and_locked_mem(): + """ + Prepare a vm with max memory, locked mem, numa, and an interface + """ + return setup_at_memory_to_vm_with_iface() + + def test_at_memory_to_vm_with_iface_and_locked_mem(): + """ + hotplug memory device + + 1) Start a guest with max memory + locked + interface + 2) Hotplug a memory device and check the locked memory + """ + vm.start() + vm.wait_for_serial_login(timeout=240).close() + new_vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + + expr_memlock = libvirt_memory.normalize_mem_size( + new_vmxml.memtune.hard_limit, new_vmxml.memtune.hard_limit_unit) + if not libvirt_memory.comp_memlock(expr_memlock): + test.fail("Unable to get correct MEMLOCK after VM startup!") + + check_environment(params) + # Variable assignment + test_scenario = params.get('test_scenario', '') + test_target = params.get('test_target', '') + dev_type = params.get('dev_type', 'vdpa') + run_test = eval("test_%s" % test_scenario) + setup_func = eval("setup_%s" % test_scenario) if "setup_%s" % \ + test_scenario in locals() else setup_test + + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + backup_vmxml = vmxml.copy() + + test_obj = None + try: + # Execute test + test_obj = setup_func() + run_test() + + finally: + backup_vmxml.sync() + teardown_test() From c3321b3c11e8ced545708b8ab59e97b389464f50 Mon Sep 17 00:00:00 2001 From: Aakanksha Date: Mon, 13 Nov 2023 10:26:40 -0500 Subject: [PATCH 0024/1055] Add new test case for SVE support This commit adds a new test case to check the SVE support on the host. Signed-off-by: Aakanksha Tripathi --- libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg | 6 +++++- libvirt/tests/src/cpu/aarch64_cpu_sve.py | 21 +++++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg b/libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg index ff8de345e32..5e9a5e5ffb7 100644 --- a/libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg +++ b/libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg @@ -41,9 +41,13 @@ vector_lenth_list = '[{"sve":"disable"}, {"sve128":"require"}]' define_error = "yes" expect_msg = "SVE disabled, but SVE vector lengths provided" + - no_host_sve_support: + only negative_test + host_without_sve = "yes" + status_error = "yes" variants: - positive_test: status_error = "no" - negative_test: - only invalid_length, conflict_length + only invalid_length, conflict_length, no_host_sve_support status_error = "yes" diff --git a/libvirt/tests/src/cpu/aarch64_cpu_sve.py b/libvirt/tests/src/cpu/aarch64_cpu_sve.py index f0bab842961..6a9228002fa 100644 --- a/libvirt/tests/src/cpu/aarch64_cpu_sve.py +++ b/libvirt/tests/src/cpu/aarch64_cpu_sve.py @@ -36,6 +36,7 @@ def run(test, params, env): status_error = "yes" == params.get("status_error", "no") define_error = "yes" == params.get("define_error", "no") + host_without_sve = "yes" == params.get("host_without_sve", "no") expect_sve = "yes" == params.get("expect_sve", "yes") expect_msg = params.get("expect_msg", "") vector_length = params.get("vector_length", "sve") @@ -57,10 +58,17 @@ def _prepare_env(vm): if (not utils_package.package_install("util-linux") or not utils_package.package_install("util-linux", session)): test.error("Failed to install util-linux") - # Cancel test if host doesn't support SVE - if process.run(check_sve, - ignore_status=True, shell=True).exit_status: - test.cancel("Host doesn't support SVE") + + # Cancel test if the Host doesn't support or supports SVE based on configuration + if process.run(check_sve, ignore_status=True, shell=True).exit_status: + if not host_without_sve: + test.cancel("Host doesn't support SVE") + else: + return + else: + if host_without_sve: + test.cancel("Host supports SVE") + # To enable SVE: Hardware support && enable kconfig # CONFIG_ARM64_SVE if session.cmd_status(check_sve_config % current_boot): @@ -86,7 +94,7 @@ def _get_maxium_sve_length(vm): session = vm.wait_for_login(timeout=120) ret = session.cmd(get_maxium_sve_length).strip() # dmesg record maximum sve length in bytes - sve_length_byte = re.search("length (\d+) bytes", ret).groups()[0] + sve_length_byte = re.search(r"length (\d+) bytes", ret).groups()[0] # Change max_length into sve + length(bit) E.g. sve512 sve_length_bit = "sve" + str(int(sve_length_byte) * 8) logging.debug("guest sve_length_bit is %s" % sve_length_bit) @@ -155,7 +163,8 @@ def _guest_has_sve(vm): except LibvirtXMLError as e: if define_error: if not re.search(expect_msg, str(e)): - test.fail("Expect definition failure: %s but got %s" % (expect_msg, str(e))) + test.fail("Expect definition failure: %s but got %s" % + (expect_msg, str(e))) return True else: test.error("Failed to define guest: %s" % str(e)) From 19e9ed9824890d2e7854d25c4bdfbac9d74558de Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Wed, 22 Nov 2023 22:19:20 -0500 Subject: [PATCH 0025/1055] Fix virt_admin_logouts.positive_test.libvirtd_virt_admin_log_output case failure The expected result diffs in different rhel version Signed-off-by: chunfuwen --- .../cfg/daemon/conf_file/libvirtd_conf/virt_admin_logging.cfg | 2 +- .../src/daemon/conf_file/libvirtd_conf/virt_admin_logging.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/daemon/conf_file/libvirtd_conf/virt_admin_logging.cfg b/libvirt/tests/cfg/daemon/conf_file/libvirtd_conf/virt_admin_logging.cfg index f0fb2b1490c..42727934073 100644 --- a/libvirt/tests/cfg/daemon/conf_file/libvirtd_conf/virt_admin_logging.cfg +++ b/libvirt/tests/cfg/daemon/conf_file/libvirtd_conf/virt_admin_logging.cfg @@ -18,7 +18,7 @@ str_to_grep = "journal" - libvirtd_virt_admin_log_output: enable_libvirtd_debug_log = "no" - log_outputs = "3:journald" + log_outputs = "3:journald|3:stderr" enable_journal_socket = "no" virt_disk_device_source = "/var/lib/libvirt/images/no_existed_libvirtd.qcow2" log_file_path = "/var/log/messages" diff --git a/libvirt/tests/src/daemon/conf_file/libvirtd_conf/virt_admin_logging.py b/libvirt/tests/src/daemon/conf_file/libvirtd_conf/virt_admin_logging.py index 4341e872825..297d360b9b9 100644 --- a/libvirt/tests/src/daemon/conf_file/libvirtd_conf/virt_admin_logging.py +++ b/libvirt/tests/src/daemon/conf_file/libvirtd_conf/virt_admin_logging.py @@ -11,6 +11,7 @@ import logging import os +import re from avocado.utils import process @@ -60,7 +61,7 @@ def check_log_outputs(params, test): log_output = params.get("log_outputs") vp = virt_admin.VirtadminPersistent() virt_admin_log = vp.daemon_log_outputs(ignore_status=True, debug=True).stdout_text.strip() - if log_output not in virt_admin_log: + if not re.search(r'%s' % log_output, virt_admin_log): test.fail("Can not find expected log output: %s from virt admin command output: %s" % (log_output, virt_admin_log)) From a46e4b9bcf7fa474e7c77c0dc968250326894dfc Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Thu, 23 Nov 2023 17:23:31 +0800 Subject: [PATCH 0026/1055] Fix typo issues Signed-off-by: Yingshun Cui --- .../migration_memory_copy_mode.py | 2 +- .../src/migration/migrate_options_shared.py | 4 ++-- .../src/sriov/vIOMMU/sriov_iommu_alias.py | 2 +- .../tests/src/virtual_interface/hotplug_mem.py | 14 +++++++------- ..._mem_to_vm_with_multiple_vdpa_interfaces.py | 18 +++++++++--------- ...mem_lock_limit_multiple_mixed_interfaces.py | 10 +++++----- provider/migration/migration_base.py | 2 +- 7 files changed, 26 insertions(+), 26 deletions(-) diff --git a/libvirt/tests/src/migration/memory_copy_mode/migration_memory_copy_mode.py b/libvirt/tests/src/migration/memory_copy_mode/migration_memory_copy_mode.py index 5eff29092b9..e2e7c8d736e 100644 --- a/libvirt/tests/src/migration/memory_copy_mode/migration_memory_copy_mode.py +++ b/libvirt/tests/src/migration/memory_copy_mode/migration_memory_copy_mode.py @@ -39,7 +39,7 @@ def verify_postcopy_migration(): src_output = event_session.get_stripped_output() test.log.debug("Event output on source: %s", src_output) if not re.findall(expected_event_src, src_output): - test.fail("Unalbe to find event {}".format(expected_event_src)) + test.fail("Unable to find event {}".format(expected_event_src)) migration_obj.verify_default() libvirt_version.is_libvirt_feature_supported(params) diff --git a/libvirt/tests/src/migration/migrate_options_shared.py b/libvirt/tests/src/migration/migrate_options_shared.py index 91b28743370..b62ba60c275 100644 --- a/libvirt/tests/src/migration/migrate_options_shared.py +++ b/libvirt/tests/src/migration/migrate_options_shared.py @@ -235,7 +235,7 @@ def check_output(output, expected_value_list): logging.debug("Actual output is %s", output) for item in expected_value_list: if not re.findall(item, output): - test.fail("Unalbe to find {}".format(item)) + test.fail("Unable to find {}".format(item)) def check_interval_not_fixed(search_str, log_file, interval=0.05, session=None): @@ -255,7 +255,7 @@ def check_interval_not_fixed(search_str, log_file, interval=0.05, session=session) if cmdStd: - test.fail("Unalbe to get {} from {}.".format(search_str, log_file)) + test.fail("Unable to get {} from {}.".format(search_str, log_file)) date_list = [] for line in cmdStdout.splitlines(): if line: diff --git a/libvirt/tests/src/sriov/vIOMMU/sriov_iommu_alias.py b/libvirt/tests/src/sriov/vIOMMU/sriov_iommu_alias.py index abedab04a3a..6e7ca196cc9 100644 --- a/libvirt/tests/src/sriov/vIOMMU/sriov_iommu_alias.py +++ b/libvirt/tests/src/sriov/vIOMMU/sriov_iommu_alias.py @@ -18,7 +18,7 @@ def check_xml(vm, exp_alias, iommu_pci_addr): cur_iommu = vm_xml.VMXML.new_from_dumpxml(vm.name)\ .devices.by_device_tag("iommu") if not cur_iommu: - test.fail("Unalbe to get iommu device!") + test.fail("Unable to get iommu device!") iommu_attrs = cur_iommu[0].fetch_attrs() test.log.debug("iommu_attrs: %s", iommu_attrs) diff --git a/libvirt/tests/src/virtual_interface/hotplug_mem.py b/libvirt/tests/src/virtual_interface/hotplug_mem.py index 08e654f72b1..e53cfad0566 100644 --- a/libvirt/tests/src/virtual_interface/hotplug_mem.py +++ b/libvirt/tests/src/virtual_interface/hotplug_mem.py @@ -188,7 +188,7 @@ def test_at_memory_to_vm_with_iface(dev_type): new_vmxml.get_current_mem(), new_vmxml.get_current_mem_unit()) + 1073741824 if not check_soft_memlock(expr_memlock): - test.fail("Unalbe to get correct MEMLOCK after VM startup!") + test.fail("Unable to get correct MEMLOCK after VM startup!") logging.info("Hotplug memory device.") mem_dict = eval(params.get('mem_dict', '{}')) @@ -198,7 +198,7 @@ def test_at_memory_to_vm_with_iface(dev_type): expr_memlock += normalize_mem_size( mem_dict['target']['size'], mem_dict['target']['size_unit']) if not check_soft_memlock(expr_memlock): - test.fail("Unalbe to get correct MEMLOCK after attaching a memory " + test.fail("Unable to get correct MEMLOCK after attaching a memory " "device!") def test_at_iface_and_memory(dev_type): @@ -216,7 +216,7 @@ def test_at_iface_and_memory(dev_type): vm.wait_for_serial_login(timeout=240).close() expr_memlock = 67108864 if not check_soft_memlock(expr_memlock): - test.fail("Unalbe to get correct default!") + test.fail("Unable to get correct default!") interface_base.attach_iface_device(vm_name, dev_type, params) @@ -226,7 +226,7 @@ def test_at_iface_and_memory(dev_type): new_vmxml.get_current_mem(), new_vmxml.get_current_mem_unit()) + 1073741824 if not check_soft_memlock(expr_memlock): - test.fail("Unalbe to get correct MEMLOCK after VM startup!") + test.fail("Unable to get correct MEMLOCK after VM startup!") logging.info("Hotplug memory devices.") for mem_attrs in ['mem_dict1', 'mem_dict2']: @@ -237,7 +237,7 @@ def test_at_iface_and_memory(dev_type): expr_memlock += normalize_mem_size( mem_dict['target']['size'], mem_dict['target']['size_unit']) if not check_soft_memlock(expr_memlock): - test.fail("Unalbe to get correct MEMLOCK after attaching a " + test.fail("Unable to get correct MEMLOCK after attaching a " "memory device!") logging.info("Detach a memory device and check memlock.") @@ -251,7 +251,7 @@ def test_at_iface_and_memory(dev_type): test.fail("Detaching mem failed, MEMLOCK should not change!") else: if not check_soft_memlock(expr_memlock): - test.fail("Unalbe to get correct MEMLOCK after detaching a " + test.fail("Unable to get correct MEMLOCK after detaching a " "memory device!") def setup_at_memory_to_vm_with_iface_and_locked_mem(dev_type): @@ -278,7 +278,7 @@ def test_at_memory_to_vm_with_iface_and_locked_mem(dev_type): expr_memlock = normalize_mem_size( new_vmxml.memtune.hard_limit, new_vmxml.memtune.hard_limit_unit) if not check_soft_memlock(expr_memlock): - test.fail("Unalbe to get correct MEMLOCK after VM startup!") + test.fail("Unable to get correct MEMLOCK after VM startup!") check_environment(params) # Variable assignment diff --git a/libvirt/tests/src/virtual_network/locked_memory_vdpa/hotplug_mem_to_vm_with_multiple_vdpa_interfaces.py b/libvirt/tests/src/virtual_network/locked_memory_vdpa/hotplug_mem_to_vm_with_multiple_vdpa_interfaces.py index 6de9538b8f9..a23e0509169 100644 --- a/libvirt/tests/src/virtual_network/locked_memory_vdpa/hotplug_mem_to_vm_with_multiple_vdpa_interfaces.py +++ b/libvirt/tests/src/virtual_network/locked_memory_vdpa/hotplug_mem_to_vm_with_multiple_vdpa_interfaces.py @@ -37,7 +37,7 @@ def setup_test(): 'iface_dict', "{'source': {'dev':'/dev/vhost-vdpa-0'}}")) iface_dev = interface_base.create_iface(dev_type, iface_dict) libvirt.add_vm_device(vm_xml.VMXML.new_from_dumpxml(vm_name), iface_dev) - test.log.debug("VM xml afater updating ifaces: %s.", + test.log.debug("VM xml after updating ifaces: %s.", vm_xml.VMXML.new_from_dumpxml(vm_name)) def run_test(): @@ -63,7 +63,7 @@ def run_test(): new_vmxml.get_current_mem(), new_vmxml.get_current_mem_unit()) + 1073741824 if not libvirt_memory.comp_memlock(expr_memlock): - test.fail("Unalbe to get correct MEMLOCK after VM startup!") + test.fail("Unable to get correct MEMLOCK after VM startup!") test.log.info("TEST_STEP2: Hotplug memory device.") mem_dict1 = eval(params.get('mem_dict1', '{}')) @@ -75,7 +75,7 @@ def run_test(): new_vmxml.get_current_mem(), new_vmxml.get_current_mem_unit()) + 1073741824 if not libvirt_memory.comp_memlock(expr_memlock): - test.fail("Unalbe to get correct MEMLOCK after attaching a memory " + test.fail("Unable to get correct MEMLOCK after attaching a memory " "device!") test.log.info("TEST_STEP3: Add one more vDPA interface.") @@ -89,7 +89,7 @@ def run_test(): new_vmxml.get_current_mem(), new_vmxml.get_current_mem_unit()) * 2 + 1073741824 if not libvirt_memory.comp_memlock(expr_memlock): - test.fail("Unalbe to get correct MEMLOCK after attaching the 2nd " + test.fail("Unable to get correct MEMLOCK after attaching the 2nd " "interface device!") test.log.info("TEST_STEP4: Hotplut one more memory device.") @@ -102,7 +102,7 @@ def run_test(): new_vmxml.get_current_mem(), new_vmxml.get_current_mem_unit()) * 2 + 1073741824 if not libvirt_memory.comp_memlock(expr_memlock): - test.fail("Unalbe to get correct MEMLOCK after attaching the 2nd " + test.fail("Unable to get correct MEMLOCK after attaching the 2nd " "interface device!") test.log.info("TEST_STEP5: Detach a memory device and vDPA interface.") @@ -110,7 +110,7 @@ def run_test(): vm_name).get_devices('memory')[-1] virsh.detach_device(vm_name, memxml.xml, debug=True) if not libvirt_memory.comp_memlock(expr_memlock): - test.fail("Unalbe to get correct MEMLOCK after detaching a memory " + test.fail("Unable to get correct MEMLOCK after detaching a memory " "device!") iface = vm_xml.VMXML.new_from_dumpxml(vm_name).get_devices( @@ -119,13 +119,13 @@ def run_test(): wait_for_event=True, **virsh_args) if not libvirt_memory.comp_memlock(expr_memlock): - test.fail("Unalbe to get correct MEMLOCK after detaching a vDPA " + test.fail("Unable to get correct MEMLOCK after detaching a vDPA " "interface!") test.log.info("TEST_STEP6: Hotplug a vDPA interface.") virsh.attach_device(vm_name, iface.xml, **virsh_args) if not libvirt_memory.comp_memlock(expr_memlock): - test.fail("Unalbe to get correct MEMLOCK after re-attaching a vDPA " + test.fail("Unable to get correct MEMLOCK after re-attaching a vDPA " "interface!") test.log.info("TEST_STEP7: Hotplug one more vDPA interface.") @@ -138,7 +138,7 @@ def run_test(): new_vmxml.get_current_mem(), new_vmxml.get_current_mem_unit()) * 3 + 1073741824 if not libvirt_memory.comp_memlock(expr_memlock): - test.fail("Unalbe to get correct MEMLOCK after attaching the 3rd " + test.fail("Unable to get correct MEMLOCK after attaching the 3rd " "interface device!") test.log.info("TEST_STEP8: Check qemu log.") diff --git a/libvirt/tests/src/virtual_network/locked_memory_vdpa/mem_lock_limit_multiple_mixed_interfaces.py b/libvirt/tests/src/virtual_network/locked_memory_vdpa/mem_lock_limit_multiple_mixed_interfaces.py index 625eb55c7cd..3ac34db0b59 100644 --- a/libvirt/tests/src/virtual_network/locked_memory_vdpa/mem_lock_limit_multiple_mixed_interfaces.py +++ b/libvirt/tests/src/virtual_network/locked_memory_vdpa/mem_lock_limit_multiple_mixed_interfaces.py @@ -40,7 +40,7 @@ def setup_test(dev_type): iface_dict = eval(params.get('iface_dict', "{'source': {'dev':'/dev/vhost-vdpa-0'}}")) iface_dev = interface_base.create_iface(dev_type, iface_dict) libvirt.add_vm_device(vm_xml.VMXML.new_from_dumpxml(vm_name), iface_dev) - test.log.debug("VM xml afater updating ifaces: %s.", + test.log.debug("VM xml after updating ifaces: %s.", vm_xml.VMXML.new_from_dumpxml(vm_name)) if test_scenario == "cold_plug": @@ -71,7 +71,7 @@ def run_test(dev_type): new_vmxml.get_current_mem(), new_vmxml.get_current_mem_unit()) * iface_no + 1073741824 if not libvirt_memory.comp_memlock(expr_memlock): - test.fail("Unalbe to get correct MEMLOCK after VM startup!") + test.fail("Unable to get correct MEMLOCK after VM startup!") if test_scenario == "cold_plug": return @@ -83,14 +83,14 @@ def run_test(dev_type): new_vmxml.get_current_mem(), new_vmxml.get_current_mem_unit()) * 2 + 1073741824 if not libvirt_memory.comp_memlock(expr_memlock): - test.fail("Unalbe to get correct MEMLOCK after attaching a hostdev " + test.fail("Unable to get correct MEMLOCK after attaching a hostdev " "interface!") test.log.info("TEST_STEP: Hotplug another hostdev interface.") virsh.attach_interface(vm.name, "hostdev --managed %s" % sriov_test_obj.vf_pci2, debug=True, ignore_status=False) if not libvirt_memory.comp_memlock(expr_memlock): - test.fail("Unalbe to get correct MEMLOCK after attaching a hostdev " + test.fail("Unable to get correct MEMLOCK after attaching a hostdev " "interface!") test.log.info("TEST_STEP: Add one more vDPA interface.") @@ -104,7 +104,7 @@ def run_test(dev_type): new_vmxml.get_current_mem(), new_vmxml.get_current_mem_unit()) * 3 + 1073741824 if not libvirt_memory.comp_memlock(expr_memlock): - test.fail("Unalbe to get correct MEMLOCK after attaching the 2nd " + test.fail("Unable to get correct MEMLOCK after attaching the 2nd " "vDPA interface device!") # Variable assignment diff --git a/provider/migration/migration_base.py b/provider/migration/migration_base.py index 8e3c473edba..342650f4eb0 100644 --- a/provider/migration/migration_base.py +++ b/provider/migration/migration_base.py @@ -220,7 +220,7 @@ def check_output(output, expected_value_list, test): logging.debug("Actual output is %s", output) for item in expected_value_list: if not re.findall(item, output): - test.fail("Unalbe to find {}".format(item)) + test.fail("Unable to find {}".format(item)) def check_event_output(params, test, virsh_session=None, remote_virsh_session=None): From 984b9b9f85de397b09107ee2c34ee48a95bf4053 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Thu, 23 Nov 2023 21:51:25 -0500 Subject: [PATCH 0027/1055] guest_os_booting: add new case for multiple boot dev attributes Automate case: VIRT-297198 - Boot vm with more than one boot dev elements Signed-off-by: Meina Li --- .../boot_with_multiple_boot_dev.cfg | 41 ++++++++ .../boot_order/boot_with_multiple_boot_dev.py | 97 +++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_dev.cfg create mode 100644 libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_dev.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_dev.cfg new file mode 100644 index 00000000000..08311721e27 --- /dev/null +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_dev.cfg @@ -0,0 +1,41 @@ +- guest_os_booting.boot_order.boot_with_multiple_boot_dev: + type = boot_with_multiple_boot_dev + start_vm = no + os_dict = {'boots': ['%s', '%s'], 'bootmenu_enable': 'yes', 'bios_useserial': 'yes'} + cdrom_dict = {'source': {'attrs': {'file': '%s'}}, 'type_name': 'file', 'device': 'cdrom', 'driver': {'name': 'qemu', 'type': 'raw'}, 'target': {'dev': 'sda', 'bus': 'sata'}} + check_prompt = ["begin the installation process|Install Red Hat Enterprise"] + variants first_dev: + - hd: + variants second_dev: + - cdrom: + variants bootable_device: + - hd_bootable: + - cdrom_bootable: + - network: + variants bootable_device: + - hd_bootable: + - network_bootable: + check_prompt = ["iPXE initialising devices|Start PXE over IPv4"] + - cdrom: + variants second_dev: + - hd: + variants bootable_device: + - hd_bootable: + - cdrom_bootable: + - network: + variants bootable_device: + - cdrom_bootable: + - network_bootable: + check_prompt = ["iPXE initialising devices|Start PXE over IPv4"] + - network: + variants second_dev: + - hd: + variants bootable_device: + - hd_bootable: + - network_bootable: + check_prompt = ["iPXE initialising devices|Start PXE over IPv4"] + - cdrom: + variants bootable_device: + - cdrom_bootable: + - network_bootable: + check_prompt = ["iPXE initialising devices|Start PXE over IPv4"] diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py new file mode 100644 index 00000000000..61a5b99a2ce --- /dev/null +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py @@ -0,0 +1,97 @@ +# Copyright Red Hat +# SPDX-License-Identifier: GPL-2.0 +# Author: Meina Li + +import os + +from avocado.utils import download +from avocado.utils import process + +from virttest import data_dir +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.guest_os_booting import guest_os_booting_base as guest_os + + +def get_vmxml_with_multiple_boot(params, vm_name): + """ + Prepare the os attributes with two boot dev attributes. + + :params params: wrapped dict with all parameters + :params vm_name: the guest name + :return: the guest xml + """ + first_dev = params.get("first_dev") + second_dev = params.get("second_dev") + os_dict = eval(params.get("os_dict") % (first_dev, second_dev)) + vmxml = guest_os.prepare_os_xml(vm_name, os_dict) + return vmxml + + +def prepare_device(params, vm_name, bootable_device): + """ + Prepare the device xml based on different test matrix. + + :params params: wrapped dict with all parameters + :params vm_name: the guest name + :params bootable_device: the device expected to boot from + :return: a tuple including the vmxml, disk_image and cdrom_path + """ + vmxml = get_vmxml_with_multiple_boot(params, vm_name) + disk_image = os.path.join(data_dir.get_data_dir(), 'images', 'test.img') + if bootable_device != "hd_bootable": + libvirt.create_local_disk("file", path=disk_image, size="500M", disk_format="qcow2") + disk_dict = {'source': {'attrs': {'file': disk_image}}} + libvirt_vmxml.modify_vm_device(vmxml, 'disk', disk_dict) + if bootable_device == "cdrom_bootable": + cdrom_path = os.path.join(data_dir.get_data_dir(), 'images', 'boot.iso') + cmd = "dnf repolist -v enabled |awk '/Repo-baseurl.*composes.*BaseOS.*os/ {print $NF}'" + repo_url = process.run(cmd, shell=True).stdout_text.strip() + boot_img_url = os.path.join(repo_url, 'images', 'boot.iso') + download.get_file(boot_img_url, cdrom_path) + else: + cdrom_path = os.path.join(data_dir.get_data_dir(), 'images', 'test.iso') + libvirt.create_local_disk("file", path=cdrom_path, size="500M", disk_format="raw") + cdrom_dict = eval(params.get("cdrom_dict") % cdrom_path) + cdrom_xml = libvirt_vmxml.create_vm_device_by_type("disk", cdrom_dict) + vmxml.add_device(cdrom_xml) + vmxml.sync() + return vmxml, disk_image, cdrom_path + + +def run(test, params, env): + """ + This case is to verify the boot order when more than one boot dev elements in guest. + 1) Start a guest with the necessary device xml. + 2) Check the guest boot status. + """ + vm_name = guest_os.get_vm(params) + check_prompt = eval(params.get("check_prompt", "[]")) + bootable_device = params.get("bootable_device") + + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) + bkxml = vmxml.copy() + + try: + test.log.info("TEST_SETUP: prepare a guest with necessary attributes.") + vmxml, disk_image, cdrom_path = prepare_device(params, vm_name, bootable_device) + test.log.info("TEST_STEP1: start the guest.") + if not vm.is_alive(): + vm.start() + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + test.log.debug(f"The current guest xml is: {vmxml}") + test.log.info("TEST_STEP2: check the guest boot from expected device.") + if bootable_device == "hd_bootable": + vm.wait_for_login(timeout=360).close() + test.log.debug("Succeed to boot %s", vm_name) + else: + vm.serial_console.read_until_output_matches(check_prompt, timeout=300, + internal_timeout=0.5) + finally: + bkxml.sync() + for file in [disk_image, cdrom_path]: + if os.path.exists(file): + os.remove(file) From ce3edf3fa6277ce52e78f5d26b75e9943bab96cd Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Wed, 15 Nov 2023 22:14:08 -0500 Subject: [PATCH 0028/1055] Add a command to check the current tap permission The chown command may fail in rhel 8 occasionally since the tap device is not ready. Add a command to check the tap before the chown command can workaround this issue. Signed-off-by: Yalan Zhang --- provider/virtual_network/network_base.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/provider/virtual_network/network_base.py b/provider/virtual_network/network_base.py index 0271f32c141..2d0b78e1bde 100644 --- a/provider/virtual_network/network_base.py +++ b/provider/virtual_network/network_base.py @@ -127,6 +127,8 @@ def create_macvtap(macvtap_name, iface, user): tap_index = process.run(cmd_get_tap, shell=True).stdout_text.strip() device_path = f'/dev/tap{tap_index}' logging.debug(f'device_path: {device_path}') + # Check the current permissions + process.run('ls -l %s' % device_path, shell=True) # Change owner and group for device process.run(f'chown {user} {device_path};chgrp {user} {device_path}', shell=True) From 333e885af10b4cb25fc78449bee56599420f7c28 Mon Sep 17 00:00:00 2001 From: lcheng Date: Thu, 16 Nov 2023 17:00:59 +0800 Subject: [PATCH 0029/1055] migration: Add case about image size XXX-298334 - VM live migration with copy storage - target image size is smaller than source image size Signed-off-by: lcheng --- .../target_image_smaller_than_source.cfg | 37 +++++++++++ .../target_image_smaller_than_source.py | 62 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 libvirt/tests/cfg/migration_with_copy_storage/target_image_smaller_than_source.cfg create mode 100644 libvirt/tests/src/migration_with_copy_storage/target_image_smaller_than_source.py diff --git a/libvirt/tests/cfg/migration_with_copy_storage/target_image_smaller_than_source.cfg b/libvirt/tests/cfg/migration_with_copy_storage/target_image_smaller_than_source.cfg new file mode 100644 index 00000000000..ab752b076dc --- /dev/null +++ b/libvirt/tests/cfg/migration_with_copy_storage/target_image_smaller_than_source.cfg @@ -0,0 +1,37 @@ +- migration_with_copy_storage.target_image_smaller_than_source: + type = target_image_smaller_than_source + migration_setup = 'yes' + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = "" + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = "qemu:///system" + image_convert = "no" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + setup_nfs = "no" + nfs_mount_dir = + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + status_error = "yes" + disk_size = "2G" + err_msg = "migration of disk vda failed: Source and target image have different sizes" + variants: + - p2p: + virsh_migrate_options = "--live --p2p --verbose" + - non_p2p: + virsh_migrate_options = "--live --verbose" + variants: + - copy_storage_all: + copy_storage_option = "--copy-storage-all" + - copy_storage_inc: + copy_storage_option = "--copy-storage-inc" diff --git a/libvirt/tests/src/migration_with_copy_storage/target_image_smaller_than_source.py b/libvirt/tests/src/migration_with_copy_storage/target_image_smaller_than_source.py new file mode 100644 index 00000000000..775ecd5e6a1 --- /dev/null +++ b/libvirt/tests/src/migration_with_copy_storage/target_image_smaller_than_source.py @@ -0,0 +1,62 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: Liping Cheng +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +import os + +from virttest import remote +from virttest import utils_misc + +from virttest.utils_libvirt import libvirt_disk + +from provider.migration import base_steps + + +def run(test, params, env): + """ + To verify that live migration with copying storage will fail when target + image size is smaller than source image size. + + :param test: test object + :param params: dictionary with the test parameters + :param env: dictionary with test environment. + """ + def setup_test(): + """ + Setup steps + + """ + server_ip = params.get("server_ip") + server_user = params.get("server_user") + server_pwd = params.get("server_pwd") + disk_size = params.get("disk_size") + + migration_obj.setup_connection() + remote_session = remote.remote_login("ssh", server_ip, "22", + server_user, server_pwd, + r'[$#%]') + first_disk = vm.get_first_disk_devices() + disk_path = first_disk["source"] + utils_misc.make_dirs(os.path.dirname(disk_path), remote_session) + libvirt_disk.create_disk(first_disk["type"], path=disk_path, + size=disk_size, disk_format="qcow2", + session=remote_session) + remote_session.close() + + vm_name = params.get("migrate_main_vm") + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + setup_test() + migration_obj.run_migration() + migration_obj.verify_default() + finally: + migration_obj.cleanup_connection() + base_steps.cleanup_disks_remote(params, vm) From aefe507a98457a7a694dcc839af71006cc9b23a5 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 27 Nov 2023 04:52:48 -0500 Subject: [PATCH 0030/1055] memory_backing/access_mode: fix on s390x 1. Enable activating hpage on s390x through kvm_module_parameters (will be set by CI). 2. Memory backing backend on s390x is s390.ram 3. Fix hpage size on s390x. 4. Exclude numa tests on s390x. 5. Exclude mount_path set because a. it is too tightly coupled with numa b. it assumes two different hpage sizes are available c. it assumes availability of mem devices Signed-off-by: Sebastian Mitterle --- .../memory_backing/discard_memory_content_setting.cfg | 4 ++++ .../cfg/memory/memory_backing/hugepage_mount_path.cfg | 1 + .../cfg/memory/memory_backing/memory_access_mode.cfg | 9 +++++++++ .../memory_backing/page_locking_and_shared_pages.cfg | 5 +++++ 4 files changed, 19 insertions(+) diff --git a/libvirt/tests/cfg/memory/memory_backing/discard_memory_content_setting.cfg b/libvirt/tests/cfg/memory/memory_backing/discard_memory_content_setting.cfg index 76f6e73db05..9eaaddc3a2e 100644 --- a/libvirt/tests/cfg/memory/memory_backing/discard_memory_content_setting.cfg +++ b/libvirt/tests/cfg/memory/memory_backing/discard_memory_content_setting.cfg @@ -5,6 +5,10 @@ set_pagenum = 1024 numa_mem = 2097152 qemu_line = '"discard-data":%s' + s390-virtio: + set_pagesize = 1024 + set_pagenum = 2048 + kvm_module_parameters = variants source: - file: source_type = 'file' diff --git a/libvirt/tests/cfg/memory/memory_backing/hugepage_mount_path.cfg b/libvirt/tests/cfg/memory/memory_backing/hugepage_mount_path.cfg index 978e7267351..e3679d5c095 100644 --- a/libvirt/tests/cfg/memory/memory_backing/hugepage_mount_path.cfg +++ b/libvirt/tests/cfg/memory/memory_backing/hugepage_mount_path.cfg @@ -1,5 +1,6 @@ - memory.backing.mount_path: type = hugepage_mount_path + no s390-virtio mem_value = 2097152 set_pagesize_1 = "1048576" set_pagenum_1 = "2" diff --git a/libvirt/tests/cfg/memory/memory_backing/memory_access_mode.cfg b/libvirt/tests/cfg/memory/memory_backing/memory_access_mode.cfg index 70842ab5b4f..cdd8c454cf7 100644 --- a/libvirt/tests/cfg/memory/memory_backing/memory_access_mode.cfg +++ b/libvirt/tests/cfg/memory/memory_backing/memory_access_mode.cfg @@ -11,6 +11,10 @@ qemu_monitor_cmd = 'info memdev' pattern_share = "share:\s*{}" mem_backend = "memory backend: ram-node0" + s390-virtio: + set_pagesize = 1024 + set_pagenum = 2048 + kvm_module_parameters = variants source: - file: source_type = 'file' @@ -37,19 +41,24 @@ - mem_access_default: variants numa_access: - numa_access_private: + no s390-virtio numa_access_mode = 'private' numa_attrs = {'vcpu': 4,'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-3', 'memory': '${numa_mem}', 'unit': 'KiB', 'memAccess':'${numa_access_mode}'}]}} numa_access_path = {'element_attrs': ['./cpu/numa/cell/[@memAccess="${numa_access_mode}"]', './cpu/numa/cell/[@memory="${numa_mem}"]']} - numa_access_shared: + no s390-virtio numa_access_mode = 'shared' numa_attrs = {'vcpu': 4,'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-3', 'memory': '${numa_mem}', 'unit': 'KiB', 'memAccess':'${numa_access_mode}'}]}} numa_access_path = {'element_attrs': ['./cpu/numa/cell/[@memAccess="${numa_access_mode}"]', './cpu/numa/cell/[@memory="${numa_mem}"]']} - numa_access_default: + no s390-virtio numa_attrs = {'vcpu': 4,'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-3', 'memory': '${numa_mem}', 'unit': 'KiB'}]}} - no_numa: mem_backend = "memory backend: pc.ram" aarch64: mem_backend = "memory backend: mach-virt.ram" + s390-virtio: + mem_backend = "memory backend: s390.ram" variants mem_pagesize: - without_hugepage: - with_hugepage: diff --git a/libvirt/tests/cfg/memory/memory_backing/page_locking_and_shared_pages.cfg b/libvirt/tests/cfg/memory/memory_backing/page_locking_and_shared_pages.cfg index cffff2f10f6..a0d27602025 100644 --- a/libvirt/tests/cfg/memory/memory_backing/page_locking_and_shared_pages.cfg +++ b/libvirt/tests/cfg/memory/memory_backing/page_locking_and_shared_pages.cfg @@ -6,6 +6,9 @@ aarch64: pagesize = 524288 pagenum = 4 + s390-virtio: + pagesize = 1024 + pagenum = 2048 expect_exist = True variants lock_config: - lock_default: @@ -34,6 +37,8 @@ kernel_pagesize = 64 - hugepage: hugepages_dict = "'hugepages': {}" + s390-virtio: + kvm_module_parameters = variants: - memory_allocation: mem_unit = "KiB" From f6de88ae6f5ec406169f2280de4ecf2946405535 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 27 Nov 2023 07:32:01 -0500 Subject: [PATCH 0031/1055] memory_balloon: diable new virtio-model tests on s390x The virtio models transitional and non-transitional are not available on s390x. Disable tests. Signed-off-by: Sebastian Mitterle --- .../tests/cfg/memory/memory_balloon/mem_balloon_autodeflate.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/cfg/memory/memory_balloon/mem_balloon_autodeflate.cfg b/libvirt/tests/cfg/memory/memory_balloon/mem_balloon_autodeflate.cfg index aa29005715e..684607d75f0 100644 --- a/libvirt/tests/cfg/memory/memory_balloon/mem_balloon_autodeflate.cfg +++ b/libvirt/tests/cfg/memory/memory_balloon/mem_balloon_autodeflate.cfg @@ -11,8 +11,10 @@ - virtio_model: memballoon_model = "virtio" - virtio_trans_model: + no s390-virtio memballoon_model = "virtio-transitional" - virtio_non_trans_model: + no s390-virtio memballoon_model = "virtio-non-transitional" variants: - autodeflate_undefined: From 6fb38ee86f93623192942b7af88fd92c1d1d0a13 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 27 Nov 2023 07:51:51 -0500 Subject: [PATCH 0032/1055] libvirt_rng: improve regex for virtio device The line intends to select the first virtio rng device that's available. Use a pattern to select it. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/libvirt_rng.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/libvirt_rng.py b/libvirt/tests/src/libvirt_rng.py index 58395f87d1c..4d431199b5e 100644 --- a/libvirt/tests/src/libvirt_rng.py +++ b/libvirt/tests/src/libvirt_rng.py @@ -364,7 +364,7 @@ def check_guest(session, expect_fail=False, test.fail("Failed to check rng file on guest." " The virtio device is not available.") if set_virtio_current: - virtio_dev = [x for x in rng_avail.split('\n') if 'virtio' in x][0] + virtio_dev = re.findall('virtio_rng.\d+', rng_avail)[0] _ = session.cmd_output(("echo -n %s > %s" % (virtio_dev, rng_files[1])), timeout=timeout) From 5ad7e8535cf33c6631cae5d6b1d0b88611cc8694 Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 28 Nov 2023 16:18:56 +0800 Subject: [PATCH 0033/1055] migration: Update error message Signed-off-by: lcheng --- ...tion_network_data_transport_tls_wrong_cert_configuration.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls_wrong_cert_configuration.cfg b/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls_wrong_cert_configuration.cfg index 1d191e04923..cc19de4a4b3 100644 --- a/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls_wrong_cert_configuration.cfg +++ b/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls_wrong_cert_configuration.cfg @@ -48,7 +48,7 @@ err_msg = "unable to execute QEMU command 'object-add': Unable to access credentials ${cert_path}" - wrong_hostname_in_cert: server_cn = "test.com.cn" - err_msg = "qemu-kvm: Cannot read from TLS channel: Input/output error|Certificate does not match the hostname|Domain not found: no domain with matching uuid" + err_msg = "qemu-kvm: Cannot read from TLS channel: Input/output error|Certificate does not match the hostname|Domain not found: no domain with matching uuid|qemu-kvm: load of migration failed: Invalid argument" - signed_by_diff_cert: new_ca_cn = "NEWCERT.VIRT" err_msg = "The certificate hasn't got a known issuer" From 5e8f898720865d2c76f022aa29d48ed737422679 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 28 Nov 2023 03:31:18 -0500 Subject: [PATCH 0034/1055] daemon/remove_pkgs: improve logging The command was executed in Bash and either true or false. Now log the output for easier debugging. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/daemon/check_daemon_after_remove_pkgs.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/daemon/check_daemon_after_remove_pkgs.py b/libvirt/tests/src/daemon/check_daemon_after_remove_pkgs.py index 67f19df1f78..4c669b645e5 100644 --- a/libvirt/tests/src/daemon/check_daemon_after_remove_pkgs.py +++ b/libvirt/tests/src/daemon/check_daemon_after_remove_pkgs.py @@ -46,8 +46,9 @@ def run(test, params, env): test.error("Failed to remove libvirt packages on guest") for daemon in daemons: - cmd = "systemctl -a | grep %s | grep -v not-found" % daemon - if not session.cmd_status(cmd): + err, out = session.cmd_status_output("systemctl -a| grep %s" % daemon) + LOGGER.debug(out) + if err or daemon in out and "not-found" not in out: test.fail("%s still exists after removing libvirt pkgs" % daemon) finally: From 611b31b2e8da1399c0729595f31e36bb556a61cd Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 28 Nov 2023 19:56:02 +0800 Subject: [PATCH 0035/1055] migration: Update postcopy and multifd case Disable postcopy + multifd migration in qemu-kvm-8.1.0. So update code. Signed-off-by: lcheng --- libvirt/tests/src/migration/migrate_options_shared.py | 8 ++++++++ .../migration_performance_tuning/migration_zerocopy.py | 8 ++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/migration/migrate_options_shared.py b/libvirt/tests/src/migration/migrate_options_shared.py index b62ba60c275..4cc5357beef 100644 --- a/libvirt/tests/src/migration/migrate_options_shared.py +++ b/libvirt/tests/src/migration/migrate_options_shared.py @@ -1400,6 +1400,14 @@ def cancel_bg_migration(): asynch_migration = False params.update({"status_error": "yes"}) + # Disable postcopy + multifd migration in qemu-kvm-8.1.0. + if extra.count("postcopy") and extra.count("parallel"): + if utils_misc.compare_qemu_version(8, 1, 0, is_rhev=False): + asynch_migration = False + params.update({"status_error": "yes"}) + params.update({"err_msg": "Postcopy is not yet compatible with multifd"}) + params.update({"action_during_mig": ""}) + # Execute migration process if not asynch_migration: mig_result = do_migration(vm, dest_uri, options, extra) diff --git a/libvirt/tests/src/migration/migration_performance_tuning/migration_zerocopy.py b/libvirt/tests/src/migration/migration_performance_tuning/migration_zerocopy.py index 81fcb2bc198..b0c9bbf0c47 100644 --- a/libvirt/tests/src/migration/migration_performance_tuning/migration_zerocopy.py +++ b/libvirt/tests/src/migration/migration_performance_tuning/migration_zerocopy.py @@ -1,3 +1,5 @@ +from avocado.utils import distro + from virttest import libvirt_version from virttest import utils_misc from virttest import virsh @@ -20,16 +22,18 @@ def setup_params(): """ According to bug 2169733, multifd and postcopy migration will fail on RHEL 8. So update some parameters for postcopy cases. + Disable postcopy + multifd migration in qemu-kvm-8.1.0. """ postcopy_options = params.get("postcopy_options") - if not utils_misc.compare_qemu_version(8, 0, 0, is_rhev=False): + if (utils_misc.compare_qemu_version(8, 1, 0, is_rhev=False) or + (distro.detect().name == 'rhel' and int(distro.detect().version) == 8)): if postcopy_options: params.update({'action_during_mig': ''}) params.update({'status_error': 'yes'}) params.update({'err_msg': 'Postcopy is not yet compatible with multifd'}) - params.update({'check_str_local_log': ''}) + params.update({'check_str_local_log': '[]'}) params.update({'migrate_again_status_error': 'yes'}) def setup_with_memtune(): From 81e371f3fdf5d4a7e0d526b25945779f621d0cb6 Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 29 Nov 2023 13:07:36 +0800 Subject: [PATCH 0036/1055] migration: Fix libvirtd service issue On latest libvirt version, running 'service libvirtd restart' command will cause virtnetworkd.socket, virtstoraged.socket, etc. to become inactive, which will cause subsequent cases to fail. So update code. Signed-off-by: lcheng --- libvirt/tests/src/migration/migrate_vm.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/libvirt/tests/src/migration/migrate_vm.py b/libvirt/tests/src/migration/migrate_vm.py index 0eb27ec04fc..29e0fc8743c 100644 --- a/libvirt/tests/src/migration/migrate_vm.py +++ b/libvirt/tests/src/migration/migrate_vm.py @@ -1871,12 +1871,8 @@ def get_target_hugepage_num(params): local_image_list.append(new_disk_source) if restart_libvirtd_remotely: - cmd = "service libvirtd restart" - status, output = run_remote_cmd(cmd, server_ip, server_user, - server_pwd) - if status: - test.fail("Failed to run '%s' on remote: %s" - % (cmd, output)) + libvirt.remotely_control_libvirtd(server_ip, server_user, + server_pwd, "restart", status_error) if remote_hugetlbfs_path: cmd = "ls %s" % remote_hugetlbfs_path @@ -2965,14 +2961,15 @@ def get_target_hugepage_num(params): if HUGETLBFS_MOUNT: cmds = ["umount -l %s" % remote_hugetlbfs_path, - "sysctl vm.nr_hugepages=0", - "service libvirtd restart"] + "sysctl vm.nr_hugepages=0"] for cmd in cmds: status, output = run_remote_cmd(cmd, server_ip, server_user, server_pwd) if status: test.fail("Failed to run '%s' on remote: %s" % (cmd, output)) + libvirt.remotely_control_libvirtd(server_ip, server_user, + server_pwd, "restart", status_error) if pool_created: pool_destroyed = create_destroy_pool_on_remote(test, "destroy", test_dict) if not pool_destroyed: From f979e9d6ef46a87a3f8ec6e98c9857ffd2f4d32f Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 29 Nov 2023 05:57:34 -0500 Subject: [PATCH 0037/1055] memory_backing: fix source and allocation on s390x 1. Fix hpage size 2. Add kvm_module_parameters to enable hpage on CI 3. Disable unsupported scenarios Signed-off-by: Sebastian Mitterle --- .../memory_backing/memory_source_and_allocation.cfg | 9 +++++++++ .../memory_backing/memory_source_and_allocation.py | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/memory/memory_backing/memory_source_and_allocation.cfg b/libvirt/tests/cfg/memory/memory_backing/memory_source_and_allocation.cfg index 2e6699fd470..853b97920cc 100644 --- a/libvirt/tests/cfg/memory/memory_backing/memory_source_and_allocation.cfg +++ b/libvirt/tests/cfg/memory/memory_backing/memory_source_and_allocation.cfg @@ -8,6 +8,10 @@ monitor_cmd = "info memdev" memory_name_pattern = 'memory backend: (\S+)' check_thread = '{"execute":"qom-get", "arguments":{"path": "/objects/%s", "property":"%s"}}' + s390-virtio: + set_pagesize = 1024 + kvm_module_parameters = + check_allocated_cmd = "grep -A20 '^Size:.*1048576' /proc/`pidof qemu-kvm`/smaps" aarch64: set_pagesize = 524288 set_pagenum = 4 @@ -59,6 +63,7 @@ alloc_mode_path = {'element_attrs': ["./memoryBacking/allocation[@mode=${mode}]", "./memoryBacking/allocation[@threads=${threads}]"]} variants numa_discard: - with_numa: + no s390-virtio numa_mem = 2097152 numa_attrs = {'vcpu': 4,'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-3', 'memory': '${numa_mem}', 'unit': 'KiB'}]}} - without_numa: @@ -69,3 +74,7 @@ current_mem = "2097152" mem_value = "2097152" mem_attrs = {'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} + s390-virtio: + current_mem = "1048576" + mem_value = "1048576" + mem_attrs = {'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} diff --git a/libvirt/tests/src/memory/memory_backing/memory_source_and_allocation.py b/libvirt/tests/src/memory/memory_backing/memory_source_and_allocation.py index 906d5124569..a87de5370a2 100644 --- a/libvirt/tests/src/memory/memory_backing/memory_source_and_allocation.py +++ b/libvirt/tests/src/memory/memory_backing/memory_source_and_allocation.py @@ -7,8 +7,8 @@ # Author: Nannan Li # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -import re import json +import re from avocado.utils import process From 90a904155d314466b214fc5b4c2b1275f8c8c643 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Tue, 21 Nov 2023 20:25:28 -0500 Subject: [PATCH 0038/1055] Add scenario of passt function test - VIRT-297101 - [user][passt] Passt backend interface - check the portforwarding feature Signed-off-by: Haijiao Zhao --- .../virtual_network/passt/passt_function.cfg | 64 +++++++++++++------ .../virtual_network/passt/passt_function.py | 3 +- provider/virtual_network/passt.py | 2 +- 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg index f8951abd3f9..e8103697ea9 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg @@ -19,33 +19,55 @@ socket_dir = f'/run/user/{user_id}/libvirt/qemu/run/passt/' variants scenario: - minimal: - iface_attrs = {'model': 'virtio', 'acpi': {'index': '1'}, 'type_name': 'user', 'backend': {'type': 'passt'}, 'source': {'dev': '${host_iface}'}} + iface_attrs = {'model': 'virtio', 'acpi': {'index': '1'}, 'type_name': 'user', 'backend': {'type': 'passt'}, 'source': {'dev': host_iface}} vm_iface = eno1 vm_ping_outside = pass - ip_portfw: + ipv6_prefix = 128 alias = {'name': 'ua-c87b89ff-b769-4abc-921f-30d42d7aec5b'} backend = {'type': 'passt'} ips = [{'address': '172.17.2.4', 'family': 'ipv4', 'prefix': '24'}, {'address': '2001:db8:ac10:fd01::20', 'family': 'ipv6'}] - portForward_0 = {'attrs': {'proto': 'tcp'}, 'ranges': [{'start': '31339', 'to': '41339'}]} - portForward_1 = {'attrs': {'proto': 'udp'}, 'ranges': [{'start': '2025'}]} - portForward_2 = {'attrs': {'proto': 'tcp', 'address': host_ip}, 'ranges': [{'start': '4025', 'end': '4035', 'to': '5025'},{'start': '9000'}, {'start': '4030', 'end': '4034', 'exclude': 'yes'}]} - portForward_3 = {'attrs': {'proto': 'udp', 'address': host_ip_v6}, 'ranges': [{'start': '8002'}, {'start': '4431', 'to': '4432'}]} - portForwards = [${portForward_0}, ${portForward_1}, ${portForward_2}, ${portForward_3}] - iface_attrs = {'model': 'virtio', 'acpi': {'index': '1'}, 'ips': ${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, 'alias': ${alias}, 'type_name': 'user', 'portForwards': ${portForwards}} - proc_checks = ['--tcp-ports 31339:41339', '--udp-ports 2025', f'--tcp-ports {host_ip}/4025-4035:5025-5035,9000,~4030-4034', f'--udp-ports {host_ip_v6}/8002,4431:4432'] - ipv6_prefix = 128 vm_iface = eno1 vm_ping_outside = pass vm_ping_host_public = pass - tcp_port_list = [4025, 4026, 4027, 4028, 4029, 4035, 9000, '*:31339'] - udp_port_list = ['0.0.0.0:2025', '[::]:2025', f'[{host_ip_v6}]:4431', f'[{host_ip_v6}]:8002'] - conn_check_args_0 = ('TCP4', 'localhost', 31339, 41339, True, None) - conn_check_args_1 = ('TCP4', host_ip, 31339, 41339, True, None) - conn_check_args_2 = ('TCP4', host_ip, 4025, 5025, True, None) - conn_check_args_3 = ('TCP4', 'localhost', 4025, 5025, False, 'Connection refused') - conn_check_args_4 = ('TCP4', host_ip, 4030, 4030, False, 'Connection refused') - conn_check_args_5 = ('TCP6', 'localhost', 31339, 41339, True, None) - conn_check_args_6 = ('TCP6', '::1', 31339, 41339, True, None) - conn_check_args_7 = ('UDP4', 'localhost', 2025, 2025, True, None) - conn_check_args_8 = ('UDP6', host_ip_v6, 4431, 4432, True, None) - conn_check_args_9 = ('UDP6', '::1', 4431, 4432, False, None) + variants: + - ip_addr: + portForward_0 = {'attrs': {'proto': 'tcp'}, 'ranges': [{'start': '31339', 'to': '41339'}]} + portForward_1 = {'attrs': {'proto': 'udp'}, 'ranges': [{'start': '2025'}]} + portForward_2 = {'attrs': {'proto': 'tcp', 'address': host_ip}, 'ranges': [{'start': '4025', 'end': '4035', 'to': '5025'},{'start': '9000'}, {'start': '4030', 'end': '4034', 'exclude': 'yes'}]} + portForward_3 = {'attrs': {'proto': 'udp', 'address': host_ip_v6}, 'ranges': [{'start': '8002'}, {'start': '4431', 'to': '4432'}]} + portForwards = [${portForward_0}, ${portForward_1}, ${portForward_2}, ${portForward_3}] + proc_checks = ['--tcp-ports 31339:41339', '--udp-ports 2025', f'--tcp-ports {host_ip}/4025-4035:5025-5035,9000,~4030-4034', f'--udp-ports {host_ip_v6}/8002,4431:4432'] + tcp_port_list = [4025, 4026, 4027, 4028, 4029, 4035, 9000, '*:31339'] + udp_port_list = ['0.0.0.0:2025', '[::]:2025', f'[{host_ip_v6}]:4431', f'[{host_ip_v6}]:8002'] + conn_check_args_0 = ('TCP4', host_ip, 31339, 41339, True, None) + conn_check_args_1 = ('TCP4', host_ip, 4025, 5025, True, None) + conn_check_args_2 = ('TCP4', 'localhost', 4025, 5025, False, 'Connection refused') + conn_check_args_3 = ('TCP4', 'localhost', 31339, 41339, True, None) + conn_check_args_4 = ('TCP4', host_ip, 4030, 4030, False, 'Connection refused') + conn_check_args_5 = ('TCP6', 'localhost', 31339, 41339, True, None) + conn_check_args_6 = ('TCP6', '::1', 31339, 41339, True, None) + conn_check_args_7 = ('UDP4', 'localhost', 2025, 2025, True, None) + conn_check_args_8 = ('UDP6', host_ip_v6, 4431, 4432, True, None) + conn_check_args_9 = ('UDP6', '::1', 4431, 4432, False, None) + - dev_only: + portForward_0 = {'attrs': {'proto': 'tcp', 'dev': host_iface}, 'ranges': [{'start': '31339', 'to': '41339'}]} + portForward_1 = {'attrs': {'proto': 'udp', 'dev': host_iface}, 'ranges': [{'start': '2025'}]} + portForwards = [${portForward_0}, ${portForward_1}] + tcp_port_list = [f'*%{vm_iface}:31339'] + udp_port_list = [f'0.0.0.0%{vm_iface}:2025', f'[::]%{vm_iface}:2025'] + conn_check_args_1 = ('TCP4', host_ip, 31339, 41339, True, None) + conn_check_args_2 = ('TCP6', host_ip_v6, 31339, 41339, True, None) + conn_check_args_3 = ('UDP4', host_ip, 2025, 2025, True, None) + conn_check_args_4 = ('UDP6', host_ip_v6, 2025, 2025, True, None) + - dev_and_ip: + portForward_0 = {'attrs': {'proto': 'tcp', 'address': host_ip, 'dev': host_iface}, 'ranges': [{'start': '31339', 'to': '41339'}]} + portForward_1 = {'attrs': {'proto': 'udp', 'address': host_ip, 'dev': host_iface}, 'ranges': [{'start': '2025'}]} + portForward_2 = {'attrs': {'proto': 'tcp', 'address': host_ip_v6, 'dev': host_iface}, 'ranges': [{'start': '51339'}]} + portForwards = [${portForward_0}, ${portForward_1}, ${portForward_2}] + tcp_port_list = [f'{host_ip}%{vm_iface}:31339', f'[{host_ip_v6}]%{vm_iface}:51339'] + udp_port_list = [f'{host_ip}%{vm_iface}:2025'] + conn_check_args_1 = ('TCP4', host_ip, 31339, 41339, True, None) + conn_check_args_2 = ('UDP4', host_ip, 2025, 2025, True, None) + conn_check_args_3 = ('TCP6', host_ip_v6, 51339, 51339, True, None) + iface_attrs = {'model': 'virtio', 'acpi': {'index': '1'}, 'ips': ${ips}, 'backend': ${backend}, 'source': {'dev': host_iface}, 'alias': ${alias}, 'type_name': 'user', 'portForwards': ${portForwards}} diff --git a/libvirt/tests/src/virtual_network/passt/passt_function.py b/libvirt/tests/src/virtual_network/passt/passt_function.py index 97c1425f413..b9d65d2535d 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_function.py +++ b/libvirt/tests/src/virtual_network/passt/passt_function.py @@ -55,7 +55,6 @@ def run(test, params, env): host_ip = utils_net.get_host_ip_address(ip_ver='ipv4') params['host_ip_v6'] = host_ip_v6 = utils_net.get_host_ip_address( ip_ver='ipv6') - iface_attrs = eval(params.get('iface_attrs')) params['socket_dir'] = socket_dir = eval(params.get('socket_dir')) params['proc_checks'] = proc_checks = eval(params.get('proc_checks', '{}')) vm_iface = params.get('vm_iface', 'eno1') @@ -65,8 +64,8 @@ def run(test, params, env): host_iface = host_iface if host_iface else utils_net.get_net_if( state="UP")[0] log_file = f'/run/user/{user_id}/passt.log' + iface_attrs = eval(params.get('iface_attrs')) iface_attrs['backend']['logFile'] = log_file - iface_attrs['source']['dev'] = host_iface vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name, virsh_instance=virsh_ins) diff --git a/provider/virtual_network/passt.py b/provider/virtual_network/passt.py index 5bcaa2f7a1d..14822134b89 100644 --- a/provider/virtual_network/passt.py +++ b/provider/virtual_network/passt.py @@ -156,7 +156,6 @@ def check_proc(target): failed_check.append(f'{target} should be in process CMD') check_list = [ - f'--mac-addr {mac}', f'--interface {host_iface}', f'--log-file {log_file}', f'--socket {socket_dir}', @@ -399,6 +398,7 @@ def check_portforward(vm, host_ip, params): :param params: test params """ host_ip_v6 = params.get('host_ip_v6') + vm_iface = params.get('vm_iface') tcp_port_list = eval(params.get('tcp_port_list', '[]')) tcp_port_list = [f'{host_ip}:{port}' if str(port).isdigit() else port for port in tcp_port_list] From 0ab198ee85e2ffdc0581e709c6e60a0a4c754734 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Thu, 30 Nov 2023 17:59:01 +0800 Subject: [PATCH 0039/1055] virtual_networks: Fix vdpa case name Signed-off-by: Yingshun Cui --- .../hotplug_mem_to_vm_with_multiple_vdpa_interfaces.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_network/locked_memory_vdpa/hotplug_mem_to_vm_with_multiple_vdpa_interfaces.cfg b/libvirt/tests/cfg/virtual_network/locked_memory_vdpa/hotplug_mem_to_vm_with_multiple_vdpa_interfaces.cfg index 4553e1341c3..e6e306af5b7 100644 --- a/libvirt/tests/cfg/virtual_network/locked_memory_vdpa/hotplug_mem_to_vm_with_multiple_vdpa_interfaces.cfg +++ b/libvirt/tests/cfg/virtual_network/locked_memory_vdpa/hotplug_mem_to_vm_with_multiple_vdpa_interfaces.cfg @@ -1,4 +1,4 @@ -- virtual_network.locked_memory.vdpa_interfaceiface.multiple_interfaces.hotplug_mem: +- virtual_network.locked_memory.vdpa_interface.multiple_interfaces.hotplug_mem: type = hotplug_mem_to_vm_with_multiple_vdpa_interfaces start_vm = no only x86_64 From f7ff6bb97e4f6a0a37725561e6a032a5c50b7ab5 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Thu, 30 Nov 2023 17:59:15 +0800 Subject: [PATCH 0040/1055] Check cpu status and drivers in win checkpoints Signed-off-by: Ming Xie --- provider/v2v_vmcheck_helper.py | 16 ++++++++++++++-- v2v/tests/src/function_test_esx.py | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/provider/v2v_vmcheck_helper.py b/provider/v2v_vmcheck_helper.py index c0b89a788a6..1941157fdb9 100644 --- a/provider/v2v_vmcheck_helper.py +++ b/provider/v2v_vmcheck_helper.py @@ -786,8 +786,12 @@ def check_windows_vm(self): LOG.info("Checking VirtIO drivers and display adapter") expect_video = self.get_expect_video_model() has_virtio_win, has_qxldod = self.get_virtio_win_config() + cpu_drivers = ['Intel Processor', 'AMD Processor'] expect_drivers = ["Red Hat VirtIO SCSI", - "Red Hat VirtIO Ethernet Adapte"] + "Red Hat VirtIO Ethernet Adapte", + "VirtIO RNG", + "VirtIO Serial", + "VirtIO Balloon"] expect_adapter = 'Microsoft Basic Display Driver' virtio_win_qxl_os = ['win2008r2', 'win7'] virtio_win_qxldod_os = ['win10', 'win2016', 'win2019'] @@ -830,7 +834,15 @@ def check_windows_vm(self): if expect_drivers: for driver in expect_drivers: self.log_err("Not find driver: %s" % driver) - + if re.search(r"(Intel|AMD) Processor", win_dirvers): + if re.search(r"(Intel|AMD) Processor", win_dirvers).group(0) in cpu_drivers: + LOG.info("CPU driver '%s' is found" % re.search(r"(Intel|AMD) Processor", win_dirvers).group(0)) + else: + err_msg = "CPU driver is not found" + self.log_err(err_msg) + cpu_status = self.checker.get_cpu_status() + if not re.search(r'OK', cpu_status): + self.log_err("cpu status is abnormal") # Check graphic and video type in VM XML self.check_vm_xml() diff --git a/v2v/tests/src/function_test_esx.py b/v2v/tests/src/function_test_esx.py index 4e7dcb5f81b..8dcc8c719bd 100644 --- a/v2v/tests/src/function_test_esx.py +++ b/v2v/tests/src/function_test_esx.py @@ -635,7 +635,7 @@ def vm_check(status_error): time_info = re.search(r'.*\d.*Finishing.*off', output).group(0) usetime = re.search(r'\d+\.\d+', str(time_info)).group(0).split('.')[0] LOG.info('use time is %s' % usetime) - if int(usetime) > 300: + if int(usetime) > 800: test.fail("conversion time is too long, please check v2v performance") # Log checking log_check = utils_v2v.check_log(params, output) From 07c257c08b48c9c928c16344424bf8f22972d095 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Tue, 29 Aug 2023 08:21:40 +0800 Subject: [PATCH 0041/1055] host_numa_info: add case host numa info Test scenario: allocate hugepages using supported hugepage size, check numa information by virsh commands, like capabilities, freepages... Signed-off-by: Dan Zheng --- .../cfg/numa/host_numa/host_numa_info.cfg | 10 + .../src/numa/host_numa/host_numa_info.py | 380 ++++++++++++++++++ spell.ignore | 1 + 3 files changed, 391 insertions(+) create mode 100644 libvirt/tests/cfg/numa/host_numa/host_numa_info.cfg create mode 100644 libvirt/tests/src/numa/host_numa/host_numa_info.py diff --git a/libvirt/tests/cfg/numa/host_numa/host_numa_info.cfg b/libvirt/tests/cfg/numa/host_numa/host_numa_info.cfg new file mode 100644 index 00000000000..da05de13e23 --- /dev/null +++ b/libvirt/tests/cfg/numa/host_numa/host_numa_info.cfg @@ -0,0 +1,10 @@ +- host_numa.numa_info: + type = host_numa_info + take_regular_screendumps = no + start_vm = "no" + no s390-virtio + variants: + - default: + allocate_dict = {2048: 200, 1048576: 2} + aarch64: + allocate_dict = {2048: 200, 524288: 4} diff --git a/libvirt/tests/src/numa/host_numa/host_numa_info.py b/libvirt/tests/src/numa/host_numa/host_numa_info.py new file mode 100644 index 00000000000..b687006a78e --- /dev/null +++ b/libvirt/tests/src/numa/host_numa/host_numa_info.py @@ -0,0 +1,380 @@ +import platform +import re + +from avocado.utils import memory as mem_utils + +from virttest import test_setup +from virttest import virsh +from virttest.libvirt_xml import capability_xml +from virttest.staging import utils_memory +from virttest.utils_misc import NumaNode + +from provider.numa import numa_base + + +def setup_default(test_obj): + """ + Default setup function for the test + + :param test_obj: NumaTest object + """ + test_obj.setup() + test_obj.test.log.debug("Step: setup is done") + + +def allocate_memory_on_host_nodes(test_obj): + """ + Allocate hugepage on all host nodes with memory + + :param test_obj: NumaTest object + :return: dict, allocated info, + like {'2048': '100', '1048576': '1'} + """ + def _allocate_test(page_num, node_id, page_size): + hpc.set_node_num_huge_pages(page_num, node_id, page_size, ignore_error=True) + allocated_num = hpc.get_node_num_huge_pages(node_id, page_size) + if allocated_num < 1: + test_obj.test.cancel("Can not set at least one page " + "with pagesize '%s' on " + "node '%s'" % (page_size, + node_id)) + return allocated_num + + ret = {} + all_nodes = test_obj.all_usable_numa_nodes + allocate_dict = eval(test_obj.params.get('allocate_dict')) + hpc = test_setup.HugePageConfig(test_obj.params) + pagesize_list = list(allocate_dict.keys()) + pagesize_list.sort(reverse=True) + for one_node in all_nodes: + allocated_info = {} + for pagesize in pagesize_list: + test_obj.test.log.debug("To allocate %s %s pages on node %s", allocate_dict[pagesize], pagesize, one_node) + allocated_num = _allocate_test(allocate_dict[pagesize], one_node, pagesize) + allocated_info.update({pagesize: allocated_num}) + ret.update({one_node: allocated_info}) + test_obj.test.log.debug("Get allocated information for node %s: '%s'", one_node, allocated_info) + test_obj.test.log.debug("Get allocated information '%s'", ret) + test_obj.params['allocate_result'] = ret + return ret + + +def verify_node_mem_by_capabilities(test_obj): + """ + Verify node memory by virsh capabilities + + :param test_obj: NumaTest object + :param capa_xml: CapabilityXML object + """ + def _check_cpu_pages(): + """ + Check pages information under + """ + pages_list = capa_xml.cpu_pages + not_match = [one_page['size'] for one_page in pages_list + if int(one_page['size']) not in supported_page_size_list] + if not_match: + test_obj.test.fail("The page size %s shown in virsh capabilities " + "do not exist in system " + "support list '%s'" % (not_match, + supported_page_size_list)) + + def _check_topo_cell(): + """ + Check memory, pages size and pages num under + """ + topo_xml = capa_xml.cells_topology + cells = topo_xml.get_cell(withmem=True) + for one_cell in cells: + total_mem = utils_memory.memtotal(node_id=one_cell.cell_id) + if one_cell.memory != total_mem: + test_obj.test.fail("Expect node memory '%s', " + "but found '%s'" % (total_mem, + one_cell.memory)) + pages_list = one_cell.pages + total_hugepage_mem = 0 + actual_default_page_num = None + for one_page in pages_list: + page_size = int(one_page.fetch_attrs()['size']) + page_num = int(one_page.fetch_attrs()['pages']) + test_obj.test.log.debug("allocate_result=%s", allocate_result) + test_obj.test.log.debug("one_page.fetch_attrs()=%s", one_page.fetch_attrs()) + if page_size != default_page_size: + pg_num = allocate_result[int(one_cell.cell_id)].get(page_size) + if pg_num is not None and pg_num != page_num: + test_obj.test.fail("Expect %s pages " + "with page size '%s', but " + "found %s" % (pg_num, + page_size, + page_num)) + total_hugepage_mem += int(page_size) * page_num + else: + actual_default_page_num = page_num + expect_default_page_num = (total_mem - total_hugepage_mem)//default_page_size + if expect_default_page_num != int(actual_default_page_num): + test_obj.test.fail("Expect %s pages with default " + "pagesize '%s', but " + "found '%s'" % (expect_default_page_num, + default_page_size, + actual_default_page_num)) + + supported_page_size_list = test_obj.params['supported_page_size_list'] + default_page_size = test_obj.params['default_page_size'] + allocate_result = test_obj.params['allocate_result'] + capa_xml = capability_xml.CapabilityXML() + _check_cpu_pages() + _check_topo_cell() + test_obj.test.log.debug("Verify memory value of each node " + "by virsh capabilities - PASS") + + +def common_test_freepages(test_obj, node_id, page_size, page_num, size_unit=''): + """ + Common function to check freepages + + :param test_obj: NumaTest object + :param node_id: str, host numa node id + :param page_size: str, hugepage size in KiB + :param page_num: str, page number + :param size_unit: str, page size unit, like KiB, M, G + """ + ret = virsh.freepages(cellno=node_id, + pagesize=page_size, + sizeunit=size_unit, + **test_obj.virsh_dargs).stdout_text.strip() + if size_unit == 'M': + page_size = page_size * 1024 + elif size_unit == 'G': + page_size = page_size * 1024 * 1024 + search_pattern = "%dKiB:\s+%s" % (page_size, page_num) + match = re.findall(search_pattern, ret) + if not match: + test_obj.test.error("Can not find '%s' in %s" % (search_pattern, ret)) + else: + test_obj.test.log.debug("Got match '%s' " + "for %s", match[0], search_pattern) + + +def verify_node_mem_by_freepages_all(test_obj): + """ + Verify node memory by virsh freepages --all + + :param test_obj: NumaTest object + """ + allocate_result = test_obj.params['allocate_result'] + output = virsh.freepages(options='--all', **test_obj.virsh_dargs).stdout_text.strip() + default_page_size = test_obj.params['default_page_size'] + all_freepages = {} + cell_freepages = {} + output += "\n\n" + node = None + for line in output.splitlines(): + if line: + key, value = line.split(":") + key = re.findall(r"(\d+)", key)[0] + if "Node" in line: + node = int(key) + else: + # Ignore to compare the default page size information + # because it changes all the time + if int(key) == default_page_size: + continue + else: + cell_freepages[int(key)] = int(value.strip()) + else: + all_freepages.update({node: cell_freepages}) + cell_freepages = {} + + test_obj.test.log.debug("Parsed all freepages " + "in 'virsh freepages --all': %s", all_freepages) + for node in all_freepages.keys(): + page_info = all_freepages[node] + for pgsize, pgnum in page_info.items(): + test_obj.test.log.debug("node %d, pgsize %d, pgnum %d", node, pgsize, pgnum) + if allocate_result[node].get(pgsize) is not None and pgnum != allocate_result[node][pgsize]: + test_obj.test.fail("Expect freepages " + "result has '%d' pages " + "for size '%d' on node %d, but " + "found '%d'" % (allocate_result[node][pgsize], + pgsize, node, pgnum)) + elif allocate_result[node].get(pgsize) is None and pgnum != 0: + test_obj.test.fail("Expect freepages " + "result has 0 page " + "for size '%d' on node %d, but " + "found '%d'" % (pgsize, node, pgnum)) + test_obj.test.log.debug("Verify node memory by freepages with --all - PASS") + + +def verify_node_mem_by_freepages(test_obj): + """ + Verify node memory by virsh freepages without options + + :param test_obj: NumaTest object + """ + allocate_result = test_obj.params['allocate_result'] + all_nodes = test_obj.all_usable_numa_nodes + for one_node in all_nodes: + for pgsize in allocate_result[one_node].keys(): + common_test_freepages(test_obj, + one_node, + pgsize, + allocate_result[one_node][pgsize]) + test_obj.test.log.debug("Verify huge page memory info on " + "each host numa node - PASS") + + +def verify_node_mem_by_freepages_various_unit(test_obj): + """ + Verify node memory by virsh freepages with different size units + + :param test_obj: NumaTest object + """ + allocate_result = test_obj.params['allocate_result'] + all_nodes = test_obj.all_usable_numa_nodes + for pgsize in allocate_result[all_nodes[1]].keys(): + common_test_freepages(test_obj, + all_nodes[1], + pgsize, allocate_result[all_nodes[1]][pgsize]) + common_test_freepages(test_obj, + all_nodes[1], + pgsize, + allocate_result[all_nodes[1]][pgsize], + size_unit='KiB') + if int(pgsize) >= 1024: + common_test_freepages(test_obj, + all_nodes[1], + int(pgsize)//1024, + allocate_result[all_nodes[1]][pgsize], + size_unit='M') + if int(pgsize) >= (1024*1024): + common_test_freepages(test_obj, + all_nodes[1], + int(pgsize)//(1024*1024), + allocate_result[all_nodes[1]][pgsize], + size_unit='G') + test_obj.test.log.debug("Verify huge page memory info on " + "the first host numa node with different " + "page size unit - PASS") + + +def verify_node_distance_by_capabilities(test_obj): + """ + Verify node distance by virsh capabilities + + :param test_obj: NumaTest object + """ + topo_xml = capability_xml.CapabilityXML().cells_topology + cells = topo_xml.get_cell(withmem=True) + for one_cell in cells: + siblings = [sibling['value'] for sibling in one_cell.sibling] + distances = test_obj.host_numa_info.get_node_distance(one_cell.cell_id) + if siblings != distances: + test_obj.test.fail("For node '%s', " + "expect the distances to " + "be '%s', but " + "found '%s'" % (one_cell.cell_id, + distances, + siblings)) + test_obj.test.log.debug("Verify node distance by " + "capabilities - PASS") + + +def verify_node_cpus_by_capabilities(test_obj): + """ + Verify node cpus by virsh capabilities + + :param test_obj: NumaTest object + """ + topo_xml = capability_xml.CapabilityXML().cells_topology + cells = topo_xml.get_cell(withmem=True) + node_cpus = test_obj.host_numa_info.online_nodes_cpus + for one_cell in cells: + expect_cpu_num = len(node_cpus[int(one_cell.cell_id)].strip().split()) + if int(one_cell.cpus_num) != expect_cpu_num: + test_obj.test.fail("For node '%s', expect " + "cpus number to be '%s', " + "but found '%s'" % (one_cell.cell_id, + expect_cpu_num, + one_cell.cpus_num)) + if len(one_cell.cpu) != expect_cpu_num: + test_obj.test.fail("for node '%s', expect " + "cpu flag number to be '%s', " + "but found '%s'" % (one_cell.cell_id, + expect_cpu_num, + len(one_cell.cpu))) + verify_node_cpus_under_cell(test_obj, one_cell.cpu, one_cell.cell_id) + + test_obj.test.log.debug("Verify node cpus by capabilities - PASS") + + +def verify_node_cpus_under_cell(test_obj, cpu_list, node_id): + """ + Verify node cpus under in virsh capabilities + + :param test_obj: NumaTest object + :param cpu_list: list, cpu list under + :param node_id: str, host numa node id + """ + one_numa_node = NumaNode(int(node_id) + 1) + for one_cpu_dict in cpu_list: + cpu_info_in_sys = one_numa_node.get_cpu_topology(one_cpu_dict['id']) + if one_cpu_dict != cpu_info_in_sys: + test_obj.test.fail("Expect cpu '%s' in node '%s' " + "to be '%s', but found " + "'%s'" % (one_cpu_dict['id'], + node_id, + cpu_info_in_sys, + one_cpu_dict)) + test_obj.test.log.debug("Verify node cpus under cell - PASS") + + +def run_default(test_obj): + """ + Default run function for the test + + :param test_obj: NumaTest object + """ + supported_hugepage_sizes = mem_utils.get_supported_huge_pages_size() + default_page_size = mem_utils.get_page_size()//1024 + supported_page_size_list = supported_hugepage_sizes + [default_page_size] + test_obj.params['default_page_size'] = default_page_size + test_obj.params['supported_page_size_list'] = supported_page_size_list + + allocate_memory_on_host_nodes(test_obj) + verify_node_mem_by_capabilities(test_obj) + verify_node_mem_by_freepages_all(test_obj) + verify_node_mem_by_freepages(test_obj) + verify_node_mem_by_freepages_various_unit(test_obj) + verify_node_distance_by_capabilities(test_obj) + if 'aarch64' not in platform.machine().lower(): + verify_node_cpus_by_capabilities(test_obj) + + +def teardown_default(test_obj): + """ + Default teardown function for the test + + :param test_obj: NumaTest object + """ + test_obj.teardown() + + allocate_dict = eval(test_obj.params.get('allocate_dict')) + hpc = test_setup.HugePageConfig(test_obj.params) + for one_psize in allocate_dict.keys(): + hpc.set_kernel_hugepages(one_psize, 0) + + test_obj.test.log.debug("Step: teardown is done") + + +def run(test, params, env): + """ + Test numa topology together with cpu topology + """ + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + numatest_obj = numa_base.NumaTest(vm, params, test) + try: + setup_default(numatest_obj) + run_default(numatest_obj) + finally: + teardown_default(numatest_obj) diff --git a/spell.ignore b/spell.ignore index 1fa9be1a81c..2a06ef3ea15 100644 --- a/spell.ignore +++ b/spell.ignore @@ -91,6 +91,7 @@ buf bz BZ cachetune +capabilities cartesian ccw CCW From 741a315bf3e8c04f7aa6647ffd8b7109ef693492 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Sun, 3 Dec 2023 22:39:52 -0500 Subject: [PATCH 0042/1055] memory_tuning: update scripts 1 add log message for error 2 merge the state checkpoint 3 merge dup check steps into one func Signed-off-by: liang-cong-red-hat --- .../memory_tuning/memory_tuning_settings.py | 102 +++++++++--------- 1 file changed, 48 insertions(+), 54 deletions(-) diff --git a/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py b/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py index 5c333c49e62..e595f3b61f4 100644 --- a/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py +++ b/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py @@ -94,8 +94,9 @@ def check_limit_by_virsh_dump(limit_dict): if hasattr(guest_xml, "memtune"): test.fail("memtune should not appear in config xml, " "but found memtune XML:\n%s" % guest_xml.memtune) - except xcepts.LibvirtXMLNotFoundError: - pass + except xcepts.LibvirtXMLNotFoundError as detail: + test.log.debug( + "Did not find the memtune xml, error is:%s" % detail) else: memtune_element = guest_xml.memtune for key, value in limit_dict.items(): @@ -104,6 +105,17 @@ def check_limit_by_virsh_dump(limit_dict): "in config xml, but found value:%s" % (key, value, getattr(memtune_element, key))) + def check_guest_memtune_related_values(limit_dict): + """ + check memtune by cmd virsh memtune, cgroup value and guest config xml + """ + test.log.info("Check the memtune value by virsh memtune") + check_limit_by_virsh_memtune(limit_dict) + test.log.info("Check the memtune value by cgroup") + check_limit_by_cgroup(limit_dict) + test.log.info("Check the memtune value by guest config xml") + check_limit_by_virsh_dump(limit_dict) + def run_test(): """ Test steps @@ -138,59 +150,41 @@ def run_test(): if 'zero' == test_target: expected_state = "shut off (crashed)" if cg.is_cgroup_v2_enabled( ) else "running (booted)" - if expected_state != actual_state: - test.fail("Guest state should be '%s', " - "but get %s instead" % (expected_state, actual_state)) - return else: - if "running (booted)" != actual_state: - test.fail("Guest state should be 'running (booted)', " - "but get %s instead" % actual_state) - - test.log.info("TEST_STEP6: For scenarios with running guest, " - "check the memtune values") - check_limit_by_virsh_memtune(target_limit_dict) - - test.log.info("TEST_STEP7: For scenarios with running guest, " - "check the cgroup settings") - check_limit_by_cgroup(target_limit_dict) - - test.log.info("TEST_STEP8: For scenarios with running guest, " - "destroy and start the guest") - vm.destroy() - vm.start() - - test.log.info("TEST_STEP9: For scenarios with running guest, " - "change the memtune setting all together") - set_limit_by_virsh_memtune_once(target_limit_dict) - - test.log.info("TEST_STEP10: For scenarios with running guest, " - "check the memtune values") - check_limit_by_virsh_memtune(target_limit_dict) - - test.log.info("TEST_STEP11: For scenarios with running guest, " - "check the cgroup settings") - check_limit_by_cgroup(target_limit_dict) - - test.log.info("TEST_STEP12: For scenarios with running guest, " - "check the memtune config xml") - check_limit_by_virsh_dump(target_limit_dict) - - test.log.info("TEST_STEP13: For scenarios with running guest, " - "restart the libvirt daemon") - utils_libvirtd.libvirtd_restart() - - test.log.info("TEST_STEP14-1: For scenarios with running guest, " - "check the memtune values") - check_limit_by_virsh_memtune(target_limit_dict) - - test.log.info("TEST_STEP14-2: For scenarios with running guest, " - "check the cgroup settings") - check_limit_by_cgroup(target_limit_dict) - - test.log.info("TEST_STEP14-3: For scenarios with running guest, " - "check the memtune config xml") - check_limit_by_virsh_dump(target_limit_dict) + expected_state = "running (booted)" + if expected_state != actual_state: + test.fail("Guest state should be '%s', " + "but get %s instead" % (expected_state, actual_state)) + + if 'zero' != test_target: + test.log.info("TEST_STEP6: For scenarios with running guest, " + "check the memtune values") + check_limit_by_virsh_memtune(target_limit_dict) + + test.log.info("TEST_STEP7: For scenarios with running guest, " + "check the cgroup settings") + check_limit_by_cgroup(target_limit_dict) + + test.log.info("TEST_STEP8: For scenarios with running guest, " + "destroy and start the guest") + vm.destroy() + vm.start() + + test.log.info("TEST_STEP9: For scenarios with running guest, " + "change the memtune setting all together") + set_limit_by_virsh_memtune_once(target_limit_dict) + + test.log.info("TEST_STEP10-12: For scenarios with running guest, " + "check the memtune values") + check_guest_memtune_related_values(target_limit_dict) + + test.log.info("TEST_STEP13: For scenarios with running guest, " + "restart the libvirt daemon") + utils_libvirtd.libvirtd_restart() + + test.log.info("TEST_STEP14: For scenarios with running guest, " + "check the memtune values") + check_guest_memtune_related_values(target_limit_dict) def teardown_test(): """ From c689f27ce1b6ef4617f0010879dc26277fcb7833 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Wed, 29 Nov 2023 01:13:11 -0500 Subject: [PATCH 0043/1055] Fix serial.pty.log.file failure Extend timeout to grab log since it may run under VM Signed-off-by: chunfuwen --- libvirt/tests/src/serial/serial_pty_log.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/serial/serial_pty_log.py b/libvirt/tests/src/serial/serial_pty_log.py index 62451f3f3ae..834a0b1e928 100644 --- a/libvirt/tests/src/serial/serial_pty_log.py +++ b/libvirt/tests/src/serial/serial_pty_log.py @@ -97,7 +97,7 @@ def update_qemu_conf(): # Need to wait for a while to get login prompt if not utils_misc.wait_for( - lambda: check_pty_log_file(log_file, boot_prompt), 6): + lambda: check_pty_log_file(log_file, boot_prompt), 15): test.fail("Failed to find the vm login prompt from %s" % log_file) except Exception as e: From 1b0f9df8b72f0ab8907d4df84f55131fa4588484 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Mon, 4 Dec 2023 18:14:44 +0800 Subject: [PATCH 0044/1055] vIOMMU: Add a case of intel iommu This PR adds: VIRT-294804 - Start vm with intel iommu and virtio devices with ats enabled Signed-off-by: Yingshun Cui --- .../intel_iommu_virtio_device_with_ats.cfg | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_virtio_device_with_ats.cfg diff --git a/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_virtio_device_with_ats.cfg b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_virtio_device_with_ats.cfg new file mode 100644 index 00000000000..37cd11613ff --- /dev/null +++ b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_virtio_device_with_ats.cfg @@ -0,0 +1,31 @@ +- vIOMMU.intel_iommu.virtio_device_with_ats: + type = iommu_device_settings + start_vm = "yes" + enable_guest_iommu = "yes" + iommu_dict = {'model': 'intel', 'driver': {'intremap': 'on', 'iotlb': 'on'}} + ping_dest = '8.8.8.8' + disk_driver = {'name': 'qemu', 'type': 'qcow2', 'iommu': 'on', 'ats': 'on'} + only q35 + + variants: + - virtio_muti_devices: + disk_dict = {'target': {'dev': 'vda', 'bus': 'virtio'}, 'device': 'disk', 'driver': ${disk_driver}} + video_dict = {'primary': 'yes', 'model_heads': '1', 'model_type': 'virtio', 'driver': {'iommu': 'on'}} + test_devices = ["Eth", "block", "gpu"] + variants: + - vhost_on: + interface_driver_name = "vhost" + - vhost_off: + interface_driver_name = "qemu" + interface_driver = {'driver_attr': {'name': '${interface_driver_name}', 'iommu': 'on', 'ats': 'on'}} + iface_dict = {'type_name': 'network', 'model': 'virtio', 'driver': ${interface_driver}, 'source': {'network': 'default'}} + - scsi_controller: + test_devices = ["scsi"] + controller_dicts = [{'type': 'scsi', 'model': 'virtio-scsi','driver': {'iommu': 'on', 'ats': 'on'}}] + disk_dict = {'target': {'dev': 'sda', 'bus': 'scsi'}} + cleanup_ifaces = no + - pcie_root_port_from_expander_bus: + test_devices = ["Eth", "block"] + root_port = {'type': 'pci', 'model': 'pcie-root-port', 'pre_controller': 'pcie-expander-bus'} + controller_dicts = [{'type': 'pci', 'model': 'pcie-expander-bus', 'pre_controller': 'pcie-root'}, ${root_port}, ${root_port}] + disk_dict = {'target': {'dev': 'vda', 'bus': 'virtio'}, 'device': 'disk', 'driver': ${disk_driver}} From c91473ac0b1f031fed94cb462c2180025745d1d1 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Mon, 4 Dec 2023 18:20:42 +0800 Subject: [PATCH 0045/1055] Change guests of esx6.7 and esx6.5 to esx7.0 Signed-off-by: Ming Xie --- v2v/tests/cfg/function_test_esx.cfg | 122 +++++++++--------- .../cfg/pyvmomi/query_changed_disk_areas.cfg | 2 +- 2 files changed, 62 insertions(+), 62 deletions(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index e32fc289a86..fd3cd8796ae 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -105,13 +105,13 @@ msg_content_yes = "windows: skipping qemufwcfg stub driver in favor of fwcfg driver" v2v_debug = force_on - program_files_2: - only esx_67 + only esx_70 os_version = 'PROGRAM_FILES_2_OS_VERSION_V2V_EXAMPLE' main_vm = 'PROGRAM_FILES_2_VM_NAME_V2V_EXAMPLE' expect_msg = 'no' msg_content = '.*case_sensitive_path: v2v: no file or directory.*' - rhev_file: - only esx_67 + only esx_70 no libvirt checkpoint = 'rhev_file' os_version = OS_VERSION_RHEV_FILE_V2V_EXAMPLE @@ -122,7 +122,7 @@ boottype = 3 variants: - win2019: - only esx_67 + only esx_70 main_vm = VM_NAME_ESX_UEFI_WINDOWS_V2V_EXAMPLE os_version = "win2019" checkpoint = 'fstrim_warning' @@ -135,7 +135,7 @@ os_version = VM_VERSION_WIN_SCHTASKS_V2V_EXAMPLE main_vm = VM_NAME_WIN_SCHTASKS_V2V_EXAMPLE - OGAC: - only esx_67 + only esx_70 checkpoint = "ogac" virtio_win_path = EXPORT_VIRTIO_WIN_PATH_V2V_EXAMPLE variants: @@ -164,7 +164,7 @@ main_vm = VM_NAME_WIN2019_V2V_EXAMPLE os_version = "win2019" - virtio_win: - only esx_67 + only esx_70 main_vm = 'ESX_VM_NAME_VIRTIO_WIN_V2V_EXAMPLE' os_version = 'OS_VERSION_VIRTIO_WIN_V2V_EXAMPLE' virtio_win_dir = '/usr/share/virtio-win/' @@ -182,7 +182,7 @@ - iso_file: checkpoint += 'iso_file' - virtio_iso_blk: - only esx_67 + only esx_70 checkpoint = "virtio_iso_blk" virtio_win_path = '/usr/share/virtio-win/virtio-win.iso' main_vm = VM_NAME_WIN2019_V2V_EXAMPLE @@ -191,11 +191,11 @@ checkpoint = 'mac_ip' variants: - 1_dhcp: - only esx_67 + only esx_70 main_vm = VM_NAME_WIN_1_DHCP_IP_V2V_EXAMPLE v2v_opts = VM_NAME_WIN_1_DHCP_IP_MAC_CONF_V2V_EXAMPLE - 1_static: - only esx_65 + only esx_70 main_vm = VM_NAME_WIN_1_STATIC_IP_V2V_EXAMPLE v2v_opts = VM_NAME_WIN_1_STATIC_IP_MAC_CONF_V2V_EXAMPLE - 3_dhcp: @@ -207,12 +207,12 @@ checkpoint = 'vmware_tools' main_vm = VM_NAME_WIN_VMWARE_TOOLS_V2V_EXAMPLE - rhsrvany_md5: - only esx_67 + only esx_70 checkpoint = 'rhsrvany_checksum' main_vm = VM_NAME_WIN2019_V2V_EXAMPLE os_version = 'win2019' - external_poweroff: - only esx_67 + only esx_70 only negative_test main_vm = VM_NAME_WIN_EXTERNAL_POWEROFF_V2V_EXAMPLE msg_content = "virt-v2v: error: filesystem was mounted read-only, even though we asked for it to be mounted read-write." @@ -266,7 +266,7 @@ msg_content_no = "VDDK_PhoneHome" msg_content_yes = "virt-v2v: error: this output module doesn't support copying more than 23 disks" - migrated_vm: - only esx_67 + only esx_70 main_vm = 'VM_NAME_ESX_MIGRATED_V2V_EXAMPLE' libguestfs_backend = 'direct' - local_storage: @@ -294,7 +294,7 @@ boottype = 3 main_vm = 'VM_NAME_ESX_TEMPLATE_V2V_EXAMPLE' - esx_snapshot: - only esx_65 + only esx_70 checkpoint = snapshot main_vm = VM_NAME_ESX_SNAPSHOT_V2V_EXAMPLE removed_file = ESX_REMOVED_FILE_V2V_EXAMPLE @@ -305,7 +305,7 @@ - ovmf: variants: - rhel7: - only esx_67 + only esx_70 main_vm = VM_NAME_ESX_UEFI_RHEL7_V2V_EXAMPLE - raid: variants: @@ -315,7 +315,7 @@ - uefi: boottype = 3 version_required = "[libguestfs-1.40,)" - only source_esx.esx_67 + only source_esx.esx_70 main_vm = VM_NAME_ESX_UEFI_RAID_V2V_EXAMPLE - iscsi_storage: only esx_70 @@ -329,7 +329,7 @@ skip_vm_check = yes skip_reason = 'guest version is too old' - AV_WIN7: - only esx_67 + only esx_70 main_vm = 'VM_NAME_AV_WIN7_V2V_EXAMPLE' msg_content = 'virt-v2v: warning: this guest has Anti-Virus \(AV\) software' expect_msg = yes @@ -376,30 +376,30 @@ msg_content = 'virt-v2v: warning: fstrim on guest filesystem' expect_msg = no - first: - only esx_67 + only esx_70 root_option = first skip_vm_check = yes skip_reason = "Can't boot into first os without selecting by user during booting after v2v conversion" - single: - only esx_67 + only esx_70 root_option = single only negative_test - dev_sdx: - only esx_67 + only esx_70 root_option = '/dev/sda1' skip_vm_check = yes skip_reason = "/dev/sda1 belongs to the first OS which can't boot into without selecting by user during booting after v2v conversion" - dev_vglv: - only esx_67 + only esx_70 root_option = '/dev/rhel/root' checkpoint += ,${root_option} - device_map: - only esx_67 + only esx_70 checkpoint = device_map main_vm = VM_NAME_ESX_RHEL7_V2V_EXAMPLE device_map_path = /boot/grub2/device.map - fstab_comma: - only esx_65 + only esx_70 checkpoint = fstab_comma main_vm = VM_NAME_ESX_FSTAB_SEPBY_COMMA msg_content = 'virt-v2v: warning: mount: mount exited with status 32: mount:.*? already mounted .*?\(ignored\)' @@ -422,39 +422,39 @@ expect_msg = yes v2v_debug = force_on - lvm_multiple_disks: - only esx_65 + only esx_70 only libvirt main_vm = VM_NAME_LVM_MULTIPLE_DISKS_V2V_EXAMPLE skip_vm_check = yes skip_reason = 'bz#1990808' - resume_rhel7: - only esx_65 + only esx_70 os_version = OS_VERSION_RESUME_RHEL7_V2V_EXAMPLE checkpoint = resume_swap main_vm = VM_NAME_RESUME_RHEL7_V2V_EXAMPLE - resume_rhel6: - only esx_67 + only esx_70 enable_legacy_policy = yes os_version = OS_VERSION_RESUME_RHEL6_V2V_EXAMPLE checkpoint = resume_swap main_vm = VM_NAME_RESUME_RHEL6_V2V_EXAMPLE - resume_mapper: - only esx_67 + only esx_70 msg_content = 'unknown device "mapper"' expect_msg = no main_vm = VM_NAME_RESUME_MAPPER_V2V_EXAMPLE - epoch: - only esx_67 + only esx_70 main_vm = 'VM_NAME_ESX_EPOCH_V2V_EXAMPLE' version_required = "[libguestfs-1.40.2-1,)" enable_legacy_policy = yes - without_file_architecture: - only esx_67 + only esx_70 main_vm = 'VM_NAME_NO_FILE_ARCHITECTURE_V2V_EXAMPLE' checkpoint = file_architecture version_required = "[libguestfs-1.40.2-4,)" - invalid_rhv_pem: - only esx_67 + only esx_70 only negative_test..rhev.rhv_upload main_vm = VM_NAME_RHEL7_V2V_EXAMPLE checkpoint = 'invalid_pem' @@ -462,7 +462,7 @@ msg_content = 'virt-v2v: error: failed server prechecks, see earlier errors' expect_msg = yes - no-copy-illegal: - only esx_67 + only esx_70 main_vm = VM_NAME_RHEL7_V2V_EXAMPLE only negative_test..rhev.rhv_upload expect_msg = yes @@ -495,7 +495,7 @@ v2v_opts = "" msg_content = "Disk with the UUID .*? already exists" - no-copy: - only esx_67 + only esx_70 only rhev.rhv_upload # Means version >= libguestfs-1.40.2-15 version_required = "[libguestfs-1.40.2-15,)" @@ -517,18 +517,18 @@ implementation_change_ver = "[virt-v2v-2.0.6-3,)" variants: - rhel6: - only esx_67 + only esx_70 enable_legacy_policy = yes qa_path = 'linux/el6' qa_url = QEMU_GUEST_AGENT_EL6_DOWNLOAD_URL_V2V_EXAMPLE main_vm = VM_NAME_RHEL6_V2V_EXAMPLE - rhel7: - only esx_67 + only esx_70 qa_path = 'linux/el7' qa_url = QEMU_GUEST_AGENT_EL7_DOWNLOAD_URL_V2V_EXAMPLE main_vm = VM_NAME_RHEL7_V2V_EXAMPLE - rhel8: - only esx_67 + only esx_70 qa_path = 'linux/el8' qa_url = QEMU_GUEST_AGENT_EL8_DOWNLOAD_URL_V2V_EXAMPLE main_vm = VM_NAME_RHEL8_V2V_EXAMPLE @@ -539,34 +539,34 @@ qa_url = QEMU_GUEST_AGENT_EL9_DOWNLOAD_URL_V2V_EXAMPLE main_vm = VM_NAME_ESX70_RHEL9_V2V_EXAMPLE - ubuntu: - only esx_67 + only esx_70 version_required = "[virt-v2v-2.0.6-3,)" qa_path = 'linux/debian' qa_url = QEMU_GUEST_AGENT_DEBIAN_DOWNLOAD_URL_V2V_EXAMPLE main_vm = VM_NAME_UBUNTU_V2V_EXAMPLE - debian: - only esx_67 + only esx_70 version_required = "[virt-v2v-2.0.6-3,)" qa_path = 'linux/debian' qa_url = QEMU_GUEST_AGENT_DEBIAN_DOWNLOAD_URL_V2V_EXAMPLE main_vm = VM_NAME_DEBIAN_V2V_EXAMPLE - sles: - only esx_67 + only esx_70 qa_path = 'linux/lp151' qa_url = QEMU_GUEST_AGENT_SUSE_DOWNLOAD_URL_V2V_EXAMPLE main_vm = VM_NAME_SLES_V2V_EXAMPLE - opensuse: - only esx_67 + only esx_70 boottype = 2 qa_path = 'linux/lp151' qa_url = QEMU_GUEST_AGENT_SUSE_DOWNLOAD_URL_V2V_EXAMPLE main_vm = VM_NAME_OPENSUSE_V2V_EXAMPLE - ubuntu-openvm-tools: - only esx_67 + only esx_70 main_vm = VM_NAME_UBUNTUTOOS_V2V_EXAMPLE checkpoint = "ubuntu_tools" - system_rhv_pem: - only esx_67 + only esx_70 only rhev.rhv_upload # Means version >= libguestfs-1.40.2-21 version_required = "[libguestfs-1.40.2-21,)" @@ -587,7 +587,7 @@ expect_msg = 'no' msg_content = 'Cannot remove Virtual Disk. Related operation is currently in progress' - log_size_decrease: - only esx_67 + only esx_70 version_requried = "[virt-v2v-1.42.0-3,);[nbdkit-server-1.17.4,)" v2v_debug = force_on checkpoint = 'log decrease' @@ -601,7 +601,7 @@ msg_content = 'v2v: add_drive.*?copyonread:true' main_vm = VM_NAME_ESX70_RHEL7_V2V_EXAMPLE - env_leak: - only esx_67 + only esx_70 only dest_json,local main_vm = VM_NAME_WIN2019_V2V_EXAMPLE env_settings = 'HOME=/root LIBGUESTFS_BACKEND=direct' @@ -623,12 +623,12 @@ - large: block_count = 1800 - without_ip_option: - only esx_67 + only esx_70 main_vm = VM_NAME_RHEL7_V2V_EXAMPLE cmd_has_ip = 'no' interaction_run = 'yes' - vmx_filename: - only esx_67 + only esx_70 main_vm = VM_NAME_VMX_FILENAME_OPTIONAL_V2V_EXAMPLE - luks: interaction_run = 'yes' @@ -641,20 +641,20 @@ main_vm = VM_NAME_ONLY_ROOT_LUKS_V2V_EXAMPLE luks_password = LUKS_PASSWORD1 - swap_3luks: - only esx_67 + only esx_70 main_vm = VM_NAME_SWAP_3LUKS_V2V_EXAMPLE luks_password = LUKS_PASSWORD1 - swap_luks: - only esx_67 + only esx_70 main_vm = VM_NAME_SWAP_LUKS_V2V_EXAMPLE luks_password = LUKS_PASSWORD1 - root_swap_2luks: - only esx_67 + only esx_70 main_vm = VM_NAME_ROOT_SWAP_2LUKS_V2V_EXAMPLE luks_password = LUKS_PASSWORD1 # set interaction to 'no' will fail because it requires to run in shell env. - keys_from_stdin: - only esx_67 + only esx_70 main_vm = VM_NAME_SWAP_3LUKS_V2V_EXAMPLE luks_password = LUKS_PASSWORD1 v2v_opts = ' --keys-from-stdin' @@ -668,7 +668,7 @@ luks_partition = VM_LUKS_PARTITION_EXAMPLE v2v_opts = "--key "${luks_partition}":clevis" - logs: - only esx_67 + only esx_70 main_vm = VM_NAME_ESX_DEFAULT_V2V_EXAMPLE variants: - open_source: @@ -697,7 +697,7 @@ v2v_opts = "--bandwidth-file ${bandwidth_file}" main_vm = VM_NAME_ESX70_RHEL8_V2V_EXAMPLE - buggy_selinux_context: - only esx_67 + only esx_70 enable_legacy_policy = yes main_vm = VM_NAME_ESX_BUGGY_SELINUX_CONTEXT_V2V_EXAMPLE - admin_account: @@ -707,7 +707,7 @@ expect_msg = 'no' msg_content = 'nbdkit:.*?503 Service Unavailable' - keys: - only esx_67 + only esx_70 main_vm = VM_NAME_SWAP_3LUKS_V2V_EXAMPLE checkpoint = 'luks_dev_keys' variants: @@ -744,17 +744,17 @@ main_vm = VM_NAME_WIN_BITLOCKER_V2V_EXAMPLE luks_keys = LUKS_WIN_BIT_LOCKER_DEV_KEYS - invalid_mac_ip: - only esx_67 + only esx_70 only negative_test version_required = "[virt-v2v-1.42.0-6,)" main_vm = VM_NAME_RHEL8_V2V_EXAMPLE variants: - addr: - v2v_opts = '--mac 00:50:56:ac:cd:56:ip:invalid_ip_addr' + v2v_opts = '--mac 00:50:56:b4:35:f0:ip:invalid_ip_addr' expect_msg = 'yes' msg_content = 'cannot parse --mac ip .*?: doesn’t look like .*? is an IP address' - prefix: - v2v_opts = '--mac 00:50:56:ac:cd:56:ip:192.168.1.1,192.168.1.2,129,10.1.1.1' + v2v_opts = '--mac 00:50:56:b4:35:f0:ip:192.168.1.1,192.168.1.2,129,10.1.1.1' expect_msg = 'yes' msg_content = 'virt-v2v: error: --mac ip prefix length field is out of range' - no_space: @@ -778,7 +778,7 @@ only esx_70 main_vm = 'VM_NAME_ESX_GT_16_DISKS_V2V_EXAMPLE' - must_ip: - only esx_67 + only esx_70 only it_default only negative_test version_required = "[virt-v2v-1.45.98-1,)" @@ -791,20 +791,20 @@ version_requried = "[libvirt-7.0.0-1,)" main_vm = VM_NAME_ESX70_NONEXIST_ISO_V2V_EXAMPLE - no_useless_info: - only esx_67 + only esx_70 version_required = '[nbdkit-server-1.12.5-1,)' main_vm = VM_NAME_RESUME_MAPPER_V2V_EXAMPLE expect_msg = 'no' msg_content = 'Exception AttributeError' - partionless_dev: - only esx_67 - main_vm = VM_NAME_ESX67_PARTIONLESS_DEV_V2V_EXAMPLE + only esx_70 + main_vm = VM_NAME_ESX70_PARTIONLESS_DEV_V2V_EXAMPLE msg_content = "virt-v2v: error: .*? inspect_os:" expect_msg = no skip_vm_check = yes skip_reason = 'special guest pariton and cannot get IP automatically' - no_ovirtsdk4_pkg: - only esx_67 + only esx_70 only negative_test only rhev.rhv_upload checkpoint = 'ovirtsdk4_pkg' @@ -812,8 +812,8 @@ msg_content = "virt-v2v: error: the Python module ‘ovirtsdk4’ could not be loaded" expect_msg = yes - rpmsave: - only esx_67 - main_vm = VM_NAME_ESX67_RPMSAVE_V2V_EXAMPLE + only esx_70 + main_vm = VM_NAME_ESX70_RPMSAVE_V2V_EXAMPLE - invalid_vddk_thumbprint: only esx_70 only negative_test @@ -884,7 +884,7 @@ checkpoint = 'large_disk' v2v_debug = false - cpu_topology: - only esx_67 + only esx_70 only it_vddk main_vm = VM_NAME_CPU_TOPOLOGY_V2V_EXAMPLE checkpoint = 'cpu_topology' diff --git a/v2v/tests/cfg/pyvmomi/query_changed_disk_areas.cfg b/v2v/tests/cfg/pyvmomi/query_changed_disk_areas.cfg index 944a82c70c3..12faa81bcb7 100644 --- a/v2v/tests/cfg/pyvmomi/query_changed_disk_areas.cfg +++ b/v2v/tests/cfg/pyvmomi/query_changed_disk_areas.cfg @@ -1,7 +1,7 @@ - query_changed_disk_areas: type = "query_changed_disk_areas" vms = '' - only source_esx.esx_67 + only source_esx.esx_70 only dest_none main_vm = VM_NAME_ESX_PYVMOMI_V2V_EXAMPLE From dc887380f25eea23a60db8735a12f5368c80d7d8 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 4 Dec 2023 13:49:07 -0500 Subject: [PATCH 0046/1055] iface_options: use multiline regex for checks On hosts with more than one NIC, the default gw is a multiline string with more than one line. Use regex to match those, too. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/virtual_network/iface_options.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_network/iface_options.py b/libvirt/tests/src/virtual_network/iface_options.py index edde0bcf39b..9ac1f94d6bc 100644 --- a/libvirt/tests/src/virtual_network/iface_options.py +++ b/libvirt/tests/src/virtual_network/iface_options.py @@ -404,7 +404,8 @@ def check_user_network(session): " on guest") # Check gateway address gateway = str(utils_net.get_default_gateway(False, session)) - if expect_gw not in gateway: + pattern = re.compile(expect_gw, re.MULTILINE) + if not pattern.search(gateway): test.fail("The gateway on guest is %s, while expect is %s" % (gateway, expect_gw)) # Check dns server address From f10246a114bb8651df4b7e44e50960af8ddb13a0 Mon Sep 17 00:00:00 2001 From: nanli Date: Tue, 26 Sep 2023 21:07:05 +0800 Subject: [PATCH 0047/1055] add case for period config of memballoon VIRT-299028: Period config of memory balloon Signed-off-by: nanli --- .../period_config_of_memory_balloon.cfg | 32 ++++ .../period_config_of_memory_balloon.py | 165 ++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_balloon/period_config_of_memory_balloon.cfg create mode 100644 libvirt/tests/src/memory/memory_balloon/period_config_of_memory_balloon.py diff --git a/libvirt/tests/cfg/memory/memory_balloon/period_config_of_memory_balloon.cfg b/libvirt/tests/cfg/memory/memory_balloon/period_config_of_memory_balloon.cfg new file mode 100644 index 00000000000..afa9a6ba3da --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_balloon/period_config_of_memory_balloon.cfg @@ -0,0 +1,32 @@ +- memory.balloon.period: + type = period_config_of_memory_balloon + start_vm = no + mem_unit = "KiB" + current_mem_unit = "KiB" + current_mem = "2097152" + mem_value = "2097152" + mem_operation = "swapoff -a; dd if=/dev/zero of=/tmp/temp bs=1024K count=10; memhog -r5 500M" + variants: + - virtio_model: + memballoon_model = "virtio" + - virtio_trans_model: + memballoon_model = "virtio-transitional" + - virtio_non_trans_model: + memballoon_model = "virtio-non-transitional" + variants: + - undefined_period: + period_value_1 = "undefined" + period_attr = "" + xpath = [{'element_attrs': [".//memballoon/stats"]}] + period_value_2 = "2" + period_cmd = "--period ${period_value_2}" + - int_period: + period_value_1 = "2" + period_attr = ",'stats_period':'${period_value_1}'" + xpath = [{'element_attrs': [".//stats[@period='${period_value_1}']"]}] + period_value_2 = "0" + period_cmd = "--period ${period_value_2}" + device_dict = "{'model':'${memballoon_model}' ${period_attr}}" + variants: + - memory_allocation: + mem_attrs = {'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} diff --git a/libvirt/tests/src/memory/memory_balloon/period_config_of_memory_balloon.py b/libvirt/tests/src/memory/memory_balloon/period_config_of_memory_balloon.py new file mode 100644 index 00000000000..57209ba9f5e --- /dev/null +++ b/libvirt/tests/src/memory/memory_balloon/period_config_of_memory_balloon.py @@ -0,0 +1,165 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import re + +from virttest import utils_misc +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml + + +def run(test, params, env): + """ + Verify memory statistics config "period" takes effect with various memory balloon models + + Scenario: + 1.memory balloon models: virtio, virtio-transitional, virtio-non-transitional. + 2.period: int period, undefined. + 3.mem config: mem, current mem. + """ + + def check_same_value(value1, value2, log_msg): + """ + This function checks whether two values are same or not. + + :param value1: First value to be checked. + :param value2: Second value to be checked. + :param log_msg: Log message to display in case of failure. + :raises: Test.Fail if values are not same. + """ + if value1 != value2: + test.fail("The %s should not change from '%s' to '%s'" + % (log_msg, value1, value2)) + + def get_memory_statistics(): + """ + Get memory statistics by virsh dommemstat + + :return: usable mem, last_update, disk_caches value in result. + """ + def _get_response(): + res = virsh.dommemstat(vm_name, ignore_status=False, + debug=True).stdout_text + return re.findall(r'usable (\d+)', res) + + if utils_misc.wait_for(_get_response, 30, 5): + res = virsh.dommemstat(vm_name, ignore_status=False, + debug=True).stdout_text + usable_mem = re.findall(r'usable (\d+)', res)[0] + last_update = re.findall(r'last_update (\d+)', res)[0] + disk_caches = re.findall(r'disk_caches (\d+)', res)[0] + return usable_mem, last_update, disk_caches + else: + test.fail("Not get virsh dommemstat result in 25s") + + def check_vm_dommemstat(period_config, usable_mem, last_update, + disk_caches): + """ + Check correct vm dommemstat result. + + :params: period_config: period config, undefined , 0 or number + :params: usable_mem, the usable mem value before consume mem + :params: last_update, the last update value before consume mem + :params: disk_caches, the disk caches value before consume mem + """ + usable_mem_new, last_update_new, disk_caches_new = get_memory_statistics() + + if period_config in ["undefined", "0"]: + check_same_value(usable_mem_new, usable_mem, "usable value") + check_same_value(last_update_new, last_update, "last update") + check_same_value(disk_caches_new, disk_caches, "disk caches") + + elif period_config.isdigit() and period_config != "0": + if usable_mem_new == usable_mem: + test.fail("The usable mem should be as '%s' instead of '%s'" + % (usable_mem_new, usable_mem)) + if last_update_new <= last_update: + test.fail("The last update '%s' should bigger than to '%s'" + % (last_update_new, last_update)) + if disk_caches_new == disk_caches: + test.fail("The disk caches mem '%s' should not same as '%s' " % + (disk_caches_new, disk_caches)) + + def check_xml_and_dommemstat(period_set): + """ + Check memory balloon xml and dommemstat after consume. + + :params: period_set, the period value. + """ + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + test.log.debug("Get current guest xml is :%s\n" % vmxml) + + xpath_existed = True + if period_set in ["undefined", "0"]: + xpath_existed = False + if not libvirt_vmxml.check_guest_xml_by_xpaths( + vmxml, expect_xpath, ignore_status=True) == xpath_existed: + test.fail("Expect to get '%s' in xml " % expect_xpath) + + usable_mem, last_update, disk_caches = get_memory_statistics() + + guest_session = vm.wait_for_login() + status, stdout = guest_session.cmd_status_output(mem_operation) + guest_session.close() + if status: + test.fail("Failed to consume memory: %s" % stdout) + + check_vm_dommemstat(period_set, usable_mem, last_update, disk_caches) + + def run_test(): + """ + Define and start guest + Check memTotal and memory allocation + """ + test.log.info("TEST_STEP1: Define guest with memballon") + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + vmxml.setup_attrs(**mem_attrs) + vmxml.del_device('memballoon', by_tag=True) + libvirt_vmxml.modify_vm_device(vmxml, 'memballoon', device_dict) + + test.log.info("TEST_STEP2: Start guest ") + vm.start() + + test.log.info("TEST_STEP3,4,5: Check memory balloon xml and dommemstat " + "after consume") + check_xml_and_dommemstat(period_value_1) + + test.log.info("TEST_STEP6: Change the period setting") + virsh.dommemstat(vm_name, period_cmd, ignore_status=False, debug=True) + + test.log.info("TEST_STEP7: Repeat TEST_STEP3-5") + check_xml_and_dommemstat(period_value_2) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bkxml.sync() + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + mem_attrs = eval(params.get("mem_attrs", "{}")) + device_dict = eval(params.get("device_dict", "{}")) + mem_operation = params.get("mem_operation") + period_value_1 = params.get("period_value_1") + period_value_2 = params.get("period_value_2") + period_cmd = params.get("period_cmd") + expect_xpath = eval(params.get("xpath")) + + try: + run_test() + + finally: + teardown_test() From 54535531a3703f48343df6207d9f2e3c3c8c1dfb Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 5 Dec 2023 04:09:33 -0500 Subject: [PATCH 0048/1055] connectivity_check/ethernet: Select host interface Get IP from configured host interface. This is important if more than one interface are available. Signed-off-by: Sebastian Mitterle --- .../connectivity/connectivity_check_ethernet_interface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py index 2e6261f2aa2..c81f44a9ed5 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py @@ -51,12 +51,12 @@ def run(test, params, env): tap_name = tap_type + '_' + rand_id tap_mtu = params.get('tap_mtu') iface_mtu = params.get('iface_mtu') - host_ip = utils_net.get_host_ip_address(ip_ver='ipv4') iface_attrs = eval(params.get('iface_attrs')) outside_ip = params.get('outside_ip') host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_net_if( state="UP")[0] + host_ip = utils_net.get_ip_address_by_interface(host_iface, ip_ver='ipv4') status_error = 'yes' == params.get('status_error', 'no') err_msg = params.get('err_msg') vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name, From adbb2f574aeb73d9e46ac479b7c1ded1b67043fc Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 5 Dec 2023 17:16:57 +0800 Subject: [PATCH 0049/1055] vIOMMU: Add a case about iommu address width This PR adds: Start vm with different iommu address width values Signed-off-by: Yingshun Cui --- .../cfg/sriov/vIOMMU/intel_iommu_aw_bits.cfg | 16 ++++++++ .../src/sriov/vIOMMU/intel_iommu_aw_bits.py | 40 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_aw_bits.cfg create mode 100644 libvirt/tests/src/sriov/vIOMMU/intel_iommu_aw_bits.py diff --git a/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_aw_bits.cfg b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_aw_bits.cfg new file mode 100644 index 00000000000..f5d73f13e93 --- /dev/null +++ b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_aw_bits.cfg @@ -0,0 +1,16 @@ +- vIOMMU.intel_iommu.aw_bits: + type = intel_iommu_aw_bits + start_vm = "yes" + enable_guest_iommu = "yes" + only q35 + + variants aw_bits_value: + - 48: + - 39: + - 36: + status_error = yes + err_msg = "Supported values for aw-bits are" + - 3423: + status_error = yes + err_msg = "Parameter 'aw-bits' expects uint8_t" + iommu_dict = {'model': 'intel', 'driver': {'intremap': 'on', 'caching_mode': 'on', 'iotlb': 'on', 'aw_bits': ${aw_bits_value}}} diff --git a/libvirt/tests/src/sriov/vIOMMU/intel_iommu_aw_bits.py b/libvirt/tests/src/sriov/vIOMMU/intel_iommu_aw_bits.py new file mode 100644 index 00000000000..48332df3f94 --- /dev/null +++ b/libvirt/tests/src/sriov/vIOMMU/intel_iommu_aw_bits.py @@ -0,0 +1,40 @@ +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt + +from provider.sriov import sriov_base + + +def run(test, params, env): + """ + Start vm with different iommu address width values. + """ + iommu_dict = eval(params.get('iommu_dict', '{}')) + aw_bits_value = params.get("aw_bits_value") + err_msg = params.get("err_msg") + status_error = "yes" == params.get("status_error", "no") + + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + test_obj = sriov_base.SRIOVTest(vm, test, params) + try: + test_obj.setup_iommu_test(iommu_dict=iommu_dict) + + test.log.info("TEST_STEP: Start the VM.") + result = virsh.start(vm.name, debug=True) + libvirt.check_exit_status(result, status_error) + if status_error: + if err_msg: + libvirt.check_result(result, err_msg) + return + vm.cleanup_serial_console() + vm.create_serial_console() + vm_session = vm.wait_for_serial_login( + timeout=int(params.get('login_timeout'))) + test.log.debug(vm_xml.VMXML.new_from_dumpxml(vm.name)) + + test.log.info("TEST_STEP: Check dmesg message.") + vm_session.cmd("dmesg | grep -i 'Host address width %s'" % aw_bits_value) + finally: + test_obj.teardown_iommu_test() From 192dc7483e9c2a0d070378832355813e927604fe Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 5 Dec 2023 05:15:11 -0500 Subject: [PATCH 0050/1055] connectivity_check/direct_interface: select host interface Use host interface selection for host IP detection to enable testing on hosts with more than one NIC. Signed-off-by: Sebastian Mitterle --- .../connectivity_check_direct_interface.py | 6 ++++-- provider/virtual_network/network_base.py | 10 ++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_direct_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_direct_interface.py index acfe38f2ecf..a68522669c4 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_direct_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_direct_interface.py @@ -46,10 +46,12 @@ def run(test, params, env): ips_v4 = network_base.get_test_ips(session, mac, ep_session, ep_mac, net_name=None, - ip_ver='ipv4') + ip_ver='ipv4', + host_iface=host_iface) ips_v6 = network_base.get_test_ips(session, mac, ep_session, ep_mac, net_name=None, - ip_ver='ipv6') + ip_ver='ipv6', + host_iface=host_iface) ips_v4['outside_ip'] = outside_ip ping_check_args = {'host_ping_outside': {'interface': host_iface}} diff --git a/provider/virtual_network/network_base.py b/provider/virtual_network/network_base.py index 2d0b78e1bde..09bc38d6f25 100644 --- a/provider/virtual_network/network_base.py +++ b/provider/virtual_network/network_base.py @@ -18,7 +18,7 @@ def get_test_ips(session, mac, ep_session, ep_mac, net_name=None, - ip_ver='ipv4'): + ip_ver='ipv4', host_iface=None): """ Get ips including vm ip, endpoint ip, host ip @@ -28,13 +28,19 @@ def get_test_ips(session, mac, ep_session, ep_mac, net_name=None, :param ep_mac: mac address of endpoint vm :param net_name: name of virtual network :param ip_ver: ip version, ipv4/ipv6 + :param host_iface: Host interface :return: a dict of ip addresses """ ips = {} ips['vm_ip'], ips['ep_vm_ip'] = [utils_net.get_guest_ip_addr( sess, mac_ad, ip_version=ip_ver) for sess, mac_ad in [(session, mac), (ep_session, ep_mac)]] - ips['host_public_ip'] = utils_net.get_host_ip_address(ip_ver=ip_ver) + if not host_iface: + host_public_ip = utils_net.get_host_ip_address(ip_ver=ip_ver) + else: + host_public_ip = utils_net.get_ip_address_by_interface(host_iface, + ip_ver=ip_ver) + ips['host_public_ip'] = host_public_ip if net_name: net_inst = network_xml.NetworkXML.new_from_net_dumpxml(net_name) From caff0c684d93194c2ecdf3c72698007b0b21b52d Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 4 Dec 2023 13:19:55 -0500 Subject: [PATCH 0051/1055] virtual_network/element_model: don't check pci model on s390x On s390x, interfaces are not PCI devices per default. Don't check the pci model. Signed-off-by: Sebastian Mitterle --- .../elements_and_attributes/element_model.cfg | 4 ++ .../elements_and_attributes/element_model.py | 41 ++++++++++++------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/elements_and_attributes/element_model.cfg b/libvirt/tests/cfg/virtual_network/elements_and_attributes/element_model.cfg index b2d7505c04d..a19086bc3b9 100644 --- a/libvirt/tests/cfg/virtual_network/elements_and_attributes/element_model.cfg +++ b/libvirt/tests/cfg/virtual_network/elements_and_attributes/element_model.cfg @@ -18,6 +18,8 @@ - virtio: iface_driver = virtio_net pci_model = pcie-root-port + s390-virtio: + check_pci_model = no - e1000e: iface_driver = e1000e pci_model = pcie-root-port @@ -30,4 +32,6 @@ - test: status_error = yes err_msg = is not a valid device model name + s390-virtio: + check_pci_model = no iface_attrs = {'source': {'network': 'default'}, 'model': '${model_type}', 'type_name': 'network'} diff --git a/libvirt/tests/src/virtual_network/elements_and_attributes/element_model.py b/libvirt/tests/src/virtual_network/elements_and_attributes/element_model.py index 676da6dd255..1cfb3f4e6a0 100644 --- a/libvirt/tests/src/virtual_network/elements_and_attributes/element_model.py +++ b/libvirt/tests/src/virtual_network/elements_and_attributes/element_model.py @@ -13,6 +13,30 @@ LOG = logging.getLogger('avocado.' + __name__) +def check_model_controller(vm_name, pci_model, test): + """ + Checks that the controllers are the expected pci model + + :param vm_name: VM name + :param pci_model: The expected pci model + :param test: Test instance + """ + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + iface = vmxml.get_devices('interface')[0] + LOG.debug(f'Interface xml after vm started:\n{iface}') + ctrl_index = int(iface.fetch_attrs()['address']['attrs']['bus'], 16) + controllers = vmxml.get_devices('controller') + iface_controller = [c for c in controllers if c.type == 'pci' and + c.index == str(ctrl_index)][0] + LOG.debug(f'Controller xml:\n{iface_controller}') + + if iface_controller.model == pci_model: + LOG.debug('XML controller model check: PASS') + else: + test.fail(f'Expect pci model: {pci_model}, ' + f'and got {iface_controller.model}') + + def run(test, params, env): """ Test 'model' element of interface @@ -26,6 +50,7 @@ def run(test, params, env): iface_attrs = eval(params.get('iface_attrs', '{}')) iface_driver = params.get('iface_driver') model_type = params.get('model_type') + check_pci_model = params.get('check_pci_model', 'yes') == "yes" if model_type == 'default': iface_attrs.pop('model') @@ -72,19 +97,7 @@ def run(test, params, env): network_base.ping_check(params, ips, session, force_ipv4=True) session.close() - vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) - iface = vmxml.get_devices('interface')[0] - LOG.debug(f'Interface xml after vm started:\n{iface}') - ctrl_index = int(iface.fetch_attrs()['address']['attrs']['bus'], 16) - controllers = vmxml.get_devices('controller') - iface_controller = [c for c in controllers if c.type == 'pci' and - c.index == str(ctrl_index)][0] - LOG.debug(f'Controller xml:\n{iface_controller}') - - if iface_controller.model == pci_model: - LOG.debug('XML controller model check: PASS') - else: - test.fail(f'Expect pci model: {pci_model}, ' - f'and got {iface_controller.model}') + if check_pci_model: + check_model_controller(vm_name, pci_model, test) finally: bkxml.sync() From f17e7152bd2920b5e9be0475f5c8f5b7f3f77346 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 5 Dec 2023 18:32:24 +0800 Subject: [PATCH 0052/1055] sriov: Add a scalability test This PR updates scalability test scenarios. Signed-off-by: Yingshun Cui --- .../scalability/sriov_scalability_max_vf.cfg | 6 ++++ .../scalability/sriov_scalability_max_vfs.py | 30 ++++++++++++------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/libvirt/tests/cfg/sriov/scalability/sriov_scalability_max_vf.cfg b/libvirt/tests/cfg/sriov/scalability/sriov_scalability_max_vf.cfg index a7ce6a099c9..eb455c368f6 100644 --- a/libvirt/tests/cfg/sriov/scalability/sriov_scalability_max_vf.cfg +++ b/libvirt/tests/cfg/sriov/scalability/sriov_scalability_max_vf.cfg @@ -3,3 +3,9 @@ start_vm = "no" vf_no = 63 net_forward = {"mode": "hostdev", "managed": "yes"} + variants: + - maximum: + iface_num = 64 + - exceed_maximum: + iface_num = 65 + start_error = yes diff --git a/libvirt/tests/src/sriov/scalability/sriov_scalability_max_vfs.py b/libvirt/tests/src/sriov/scalability/sriov_scalability_max_vfs.py index 85b44380e04..936561fa61b 100644 --- a/libvirt/tests/src/sriov/scalability/sriov_scalability_max_vfs.py +++ b/libvirt/tests/src/sriov/scalability/sriov_scalability_max_vfs.py @@ -1,7 +1,3 @@ -from provider.interface import interface_base -from provider.sriov import check_points -from provider.sriov import sriov_base - from virttest import utils_misc from virttest import utils_sriov from virttest import virsh @@ -11,6 +7,10 @@ from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_test import libvirt +from provider.interface import interface_base +from provider.sriov import check_points +from provider.sriov import sriov_base + def get_vm_iface_num(vm_name): """ @@ -79,7 +79,7 @@ def setup_test(): test.log.info("TEST_SETUP: Remove VM's interface devices.") libvirt_vmxml.remove_vm_devices_by_type(vm, 'interface') - test.log.info("TEST_SETUP: Cold plug 64 interfaces to VM.") + test.log.info(f"TEST_SETUP: Cold plug {iface_num} interfaces to VM.") opts = "network %s --config" % list(net_info.values())[0] for i in range(vf_no): iface_dict = { @@ -94,11 +94,13 @@ def setup_test(): if i % 8 == 0: iface_dict['address']['attrs'].update({'multifunction': 'on'}) iface_dev = interface_base.create_iface("network", iface_dict) - virsh.attach_device(vm.name, iface_dev.xml, flagstr="--config", debug=True, ignore_status=False) - net_name_2 = list(net_info.values())[1] - opts = "network %s --config" % net_name_2 - virsh.attach_interface(vm_name, opts, debug=True, ignore_status=False) - compare_vm_iface(test, get_vm_iface_num(vm_name), vf_no+1) + virsh.attach_device(vm.name, iface_dev.xml, flagstr="--config", + debug=True, ignore_status=False) + for i in range(iface_num - vf_no): + net_name_2 = list(net_info.values())[1] + opts = "network %s --config" % net_name_2 + virsh.attach_interface(vm_name, opts, debug=True, ignore_status=False) + compare_vm_iface(test, get_vm_iface_num(vm_name), iface_num) def teardown_test(): """ @@ -126,7 +128,11 @@ def run_test(): 5. Try to hot plug the 65th hostdev interface """ test.log.info("TEST_STEP1: Start the VM and check networks.") - vm.start() + result = virsh.start(vm.name, debug=True) + libvirt.check_exit_status(result, start_error) + if start_error: + return + vm.create_serial_console() vm_session = vm.wait_for_serial_login(timeout=240) res = vm_session.cmd_status_output( 'lspci |grep Ether')[1].strip().splitlines() @@ -180,6 +186,8 @@ def compare_vm_iface(test, vm_iface_num, expr_no): driver = utils_sriov.get_pf_info_by_pci(pf_pci).get('driver') net_info = get_net_dict(pf_info) vf_no = int(params.get("vf_no", "63")) + iface_num = int(params.get("iface_num", "64")) + start_error = "yes" == params.get("start_error", "no") vm_name = params.get("main_vm", "avocado-vt-vm1") vm = env.get_vm(vm_name) From bebb55e3317cf3b96f40876d26e47e71cbdbad0e Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 30 Oct 2023 15:57:31 +0800 Subject: [PATCH 0053/1055] migration: Add listen address case VIRT-297874 - VM live migration with copy storage - network data transport - TCP - --listen-address Signed-off-by: lcheng --- .../tcp_listen_address.cfg | 59 +++++++++++++++++++ .../network_data_transport/tcp.py | 34 +++++++++++ 2 files changed, 93 insertions(+) create mode 100644 libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_listen_address.cfg create mode 100644 libvirt/tests/src/migration_with_copy_storage/network_data_transport/tcp.py diff --git a/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_listen_address.cfg b/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_listen_address.cfg new file mode 100644 index 00000000000..a68e27b2e50 --- /dev/null +++ b/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_listen_address.cfg @@ -0,0 +1,59 @@ +- migration_with_copy_storage.network_data_transport.tcp_listen_address: + type = tcp + migration_setup = 'yes' + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + status_error = "no" + check_network_accessibility_after_mig = "yes" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + action_during_mig = '[{"func": "libvirt_network.check_listen_address", "func_param": "params", "need_sleep_time": "5"}]' + setup_nfs = "no" + nfs_mount_dir = + variants: + - p2p: + virsh_migrate_options = '--live --p2p --verbose' + - non_p2p: + virsh_migrate_options = '--live --verbose' + variants: + - target_ipv4_address: + listen_address = "${migrate_dest_host}" + virsh_migrate_extra = "--listen-address ${migrate_dest_host}" + - target_ipv6_address: + ipv6_config = "yes" + ipv6_addr_des = "ENTER.YOUR.IPv6.TRAGET" + listen_address = "${ipv6_addr_des}" + virsh_migrate_extra = "--migrateuri tcp://[${ipv6_addr_des}] --listen-address ${ipv6_addr_des}" + - all_ipv4: + listen_address = "0.0.0.0" + virsh_migrate_extra = "--listen-address ${listen_address}" + - all_ipv6: + listen_address = "*" + virsh_migrate_extra = "--listen-address ::" + - invalid_address: + status_error = "yes" + err_msg = "nbd-server-start.*Cannot assign requested address" + listen_address = "10.10.10.10" + virsh_migrate_extra = "--listen-address ${listen_address}" + variants: + - copy_storage_all: + copy_storage_option = "--copy-storage-all" + - copy_storage_inc: + copy_storage_option = "--copy-storage-inc" diff --git a/libvirt/tests/src/migration_with_copy_storage/network_data_transport/tcp.py b/libvirt/tests/src/migration_with_copy_storage/network_data_transport/tcp.py new file mode 100644 index 00000000000..83b3174afb6 --- /dev/null +++ b/libvirt/tests/src/migration_with_copy_storage/network_data_transport/tcp.py @@ -0,0 +1,34 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: Liping Cheng +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from provider.migration import base_steps + + +def run(test, params, env): + """ + Test VM live migration with copy storage - network data transport - TCP. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + vm_name = params.get("migrate_main_vm") + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + migration_obj.setup_connection() + base_steps.prepare_disks_remote(params, vm) + migration_obj.run_migration() + migration_obj.verify_default() + finally: + migration_obj.cleanup_connection() + base_steps.cleanup_disks_remote(params, vm) From 62bfc21931a7e9c8b3d50a0851587df8b5fc6b2d Mon Sep 17 00:00:00 2001 From: lcheng Date: Thu, 26 Oct 2023 12:04:13 +0800 Subject: [PATCH 0054/1055] migration: Add bandwidth limit case VIRT-297906 - VM live migration with copy storage - bandwidth limit Signed-off-by: lcheng --- .../migration_bandwidth_limit.cfg | 54 +++++++++++++++++ .../migration_bandwidth_limit.py | 59 +++++++++++++++++++ provider/migration/migration_base.py | 3 + 3 files changed, 116 insertions(+) create mode 100644 libvirt/tests/cfg/migration_with_copy_storage/migration_bandwidth_limit.cfg create mode 100644 libvirt/tests/src/migration_with_copy_storage/migration_bandwidth_limit.py diff --git a/libvirt/tests/cfg/migration_with_copy_storage/migration_bandwidth_limit.cfg b/libvirt/tests/cfg/migration_with_copy_storage/migration_bandwidth_limit.cfg new file mode 100644 index 00000000000..b95c10945eb --- /dev/null +++ b/libvirt/tests/cfg/migration_with_copy_storage/migration_bandwidth_limit.cfg @@ -0,0 +1,54 @@ +- migration_with_copy_storage.migration_bandwidth_limit: + type = migration_bandwidth_limit + migration_setup = 'yes' + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = "" + # SSH connection time out + ssh_timeout = 60 + start_vm = "yes" + # Local URI + virsh_migrate_connect_uri = "qemu:///system" + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = "no" + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + status_error = "no" + simple_disk_check_after_mig = "no" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + setup_nfs = "no" + nfs_mount_dir = + bandwidth = "20" + jobinfo_item = "Memory bandwidth:" + precopy_bandwidth = "${bandwidth}" + compare_to_value = "${bandwidth}" + check_item = "bandwidth" + check_item_value = "20971520" + action_during_mig = '[{"func": "libvirt_disk.check_item_by_blockjob", "after_event": "block-job", "before_event": "migration-iteration", "func_param": "params", "wait_for_after_event_timeout": "600"}, {"func": "check_domjobinfo_during_mig", "after_event": "migration-iteration", "func_param": "params"}]' + migrate_start_state = "running" + variants: + - p2p: + virsh_migrate_options = "--live --p2p --verbose" + - non_p2p: + virsh_migrate_options = "--live --verbose" + variants set_bandwidth: + - bandwidth: + virsh_migrate_extra = "--bandwidth ${bandwidth}" + - setspeed_before_migration: + - setspeed_during_migration: + virsh_migrate_extra = "--bandwidth 30" + action_during_mig = '[{"func": "set_bandwidth", "after_event": "block-job", "func_param": "params", "wait_for_after_event_timeout": "600"}, {"func": "libvirt_disk.check_item_by_blockjob", "func_param": "params"}, {"func": "check_domjobinfo_during_mig", "func_param": "params"}]' + variants: + - copy_storage_all: + copy_storage_option = "--copy-storage-all" + - copy_storage_inc: + copy_storage_option = "--copy-storage-inc" diff --git a/libvirt/tests/src/migration_with_copy_storage/migration_bandwidth_limit.py b/libvirt/tests/src/migration_with_copy_storage/migration_bandwidth_limit.py new file mode 100644 index 00000000000..85655ac5c7c --- /dev/null +++ b/libvirt/tests/src/migration_with_copy_storage/migration_bandwidth_limit.py @@ -0,0 +1,59 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: Liping Cheng +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from virttest import virsh + +from provider.migration import base_steps + + +def run(test, params, env): + """ + To verify that bandwidth limit can take effect for storage copying during + migration. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def setup_setspeed_before_migration(): + """ + Setup for setspeed_before_migration + + """ + bandwidth = params.get("bandwidth") + + test.log.info("Setup bandwidth limit before migration.") + migration_obj.setup_connection() + virsh.migrate_setspeed(vm_name, bandwidth, debug=True) + + def cleanup_test(): + """ + Cleanup steps + + """ + migration_obj.cleanup_connection() + base_steps.cleanup_disks_remote(params, vm) + + set_bandwidth = params.get('set_bandwidth', '') + vm_name = params.get("migrate_main_vm") + + vm = env.get_vm(vm_name) + params.update({'vm_obj': vm}) + migration_obj = base_steps.MigrationBase(test, vm, params) + setup_test = eval("setup_%s" % set_bandwidth) if "setup_%s" % set_bandwidth in \ + locals() else migration_obj.setup_connection + + try: + setup_test() + base_steps.prepare_disks_remote(params, vm) + migration_obj.run_migration() + migration_obj.verify_default() + finally: + cleanup_test() diff --git a/provider/migration/migration_base.py b/provider/migration/migration_base.py index 8e3c473edba..b9315453143 100644 --- a/provider/migration/migration_base.py +++ b/provider/migration/migration_base.py @@ -15,6 +15,7 @@ from virttest.libvirt_xml import vm_xml from virttest.migration import MigrationTest +from virttest.utils_libvirt import libvirt_disk # pylint: disable=W0611 from virttest.utils_libvirt import libvirt_memory from virttest.utils_libvirt import libvirt_monitor from virttest.utils_libvirt import libvirt_network # pylint: disable=W0611 @@ -71,6 +72,8 @@ def parse_funcs(action_during_mig, test, params): 'before_pause': one_action.get('before_pause'), 'need_sleep_time': one_action.get('need_sleep_time'), 'func_param': func_param}) + if one_action.get('wait_for_after_event_timeout'): + act_dict.update({'wait_for_after_event_timeout': one_action.get('wait_for_after_event_timeout')}) action_during_mig.append(act_dict) return action_during_mig else: From 68911cd7d387bd2e07b7ac99d32efd4dfdcaba26 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Wed, 6 Dec 2023 01:22:01 -0500 Subject: [PATCH 0055/1055] guest_os_booting: add new boot order case for usb device This PR mainly implements the boot order checking for the use block device, usb redirdev device and usb hostdev device. Signed-off-by: Meina Li --- .../boot_orer/boot_from_usb_device.cfg | 16 +++ .../boot_order/boot_from_usb_device.py | 117 ++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 libvirt/tests/cfg/guest_os_booting/boot_orer/boot_from_usb_device.cfg create mode 100644 libvirt/tests/src/guest_os_booting/boot_order/boot_from_usb_device.py diff --git a/libvirt/tests/cfg/guest_os_booting/boot_orer/boot_from_usb_device.cfg b/libvirt/tests/cfg/guest_os_booting/boot_orer/boot_from_usb_device.cfg new file mode 100644 index 00000000000..87745980e08 --- /dev/null +++ b/libvirt/tests/cfg/guest_os_booting/boot_orer/boot_from_usb_device.cfg @@ -0,0 +1,16 @@ +- guest_os_booting.boot_order.usb_device: + type = boot_from_usb_device + start_vm = no + bus_type = "usb" + bootmenu_dict = {'bootmenu_enable': 'yes', 'bootmenu_timeout': '3000', 'bios_useserial': 'yes'} + check_prompt = "UEFI .* USB|1. USB MSC Drive .*" + variants usb_device: + - block_device: + disk_type = "block" + target_disk = "sda" + device_attrs = {"type_name":"${disk_type}", "target":{"dev": "${target_disk}", "bus": "${bus_type}"}, 'boot': '1'} + - redirdev_device: + port_num = "4000" + device_attrs = {'source': {'host': 'localhost', 'service': '4000', 'mode': 'connect'}, 'protocol': {'type': 'raw'}, 'type_name': 'tcp', 'bus': '${bus_type}', 'type': 'tcp', 'boot': {'order': '1'}} + - hostdev_device: + device_attrs = {'type_name': 'usb', 'mode': 'subsystem', 'source': {'vendor_id': '%s', 'product_id': '%s'}, 'type': 'usb', 'managed': 'no', 'boot_order': '1'} diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_usb_device.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_usb_device.py new file mode 100644 index 00000000000..1c023a6f5a6 --- /dev/null +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_usb_device.py @@ -0,0 +1,117 @@ +# Copyright Red Hat +# SPDX-License-Identifier: GPL-2.0 +# Author: Meina Li + +import re +import shutil + +from avocado.utils import process + +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.devices import hostdev +from virttest.libvirt_xml.devices import redirdev +from virttest.utils_test import libvirt + +from provider.guest_os_booting import guest_os_booting_base as guest_os +from provider.backingchain import blockcommand_base +from provider.virtual_disk import disk_base + + +def run(test, params, env): + """ + This case is to verify the boot order of usb device. + 1) Prepare a guest with use device. + 2) Start the guest. + 3) Check the boot order of guest. + """ + def get_usb_source(): + """ + Get the usb list in host based on the output from command lsusb + + :return tuple: (vendor_id, product_id) for the usb device + """ + lsusb_list = process.run("lsusb").stdout_text.splitlines() + test.log.info("The lsusb command result: {}".format(lsusb_list)) + found_device = False + for line in lsusb_list: + if re.search('hub|Controller', line, re.IGNORECASE): + continue + if len(line.split()[5].split(':')) == 2: + vendor_id, product_id = line.split()[5].split(':') + if not (vendor_id and product_id): + test.fail("vendor/product id is not available") + found_device = True + break + if not found_device: + test.fail("There's no avaiable usb device.") + return vendor_id, product_id + + def check_boot_order(): + """ + Check the boot order of guest + """ + current_xml = vm_xml.VMXML.new_from_dumpxml(vm_name) + vm.create_serial_console() + vm.resume() + if not any([current_xml.os.fetch_attrs().get("os_firmware") == "efi", + current_xml.os.fetch_attrs().get('nvram')]): + for _ in range(3): + vm.serial_console.sendcontrol('[') + vm.serial_console.read_until_any_line_matches( + [check_prompt], timeout=30, internal_timeout=0.5) + + vm_name = params.get("main_vm") + disk_type = params.get("disk_type") + usb_device = params.get("usb_device") + bootmenu_dict = eval(params.get("bootmenu_dict", "{}")) + device_attrs = eval(params.get("device_attrs", "{}")) + port_num = params.get("port_num") + check_prompt = params.get("check_prompt") + + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + test_obj = blockcommand_base.BlockCommand(test, vm, params) + disk_obj = disk_base.DiskBase(test, vm, params) + + try: + if not (shutil.which("lsusb") and shutil.which("usbredirserver")): + test.error("Package related with usb command is not installed. Please install it.") + vmxml = guest_os.prepare_os_xml(vm_name, bootmenu_dict) + vmxml.remove_all_boots() + + if usb_device == "block_device": + device_xml, new_image_path = disk_obj.prepare_disk_obj(disk_type, device_attrs) + if usb_device == "redirdev_device": + vendor_id, product_id = get_usb_source() + device_xml = redirdev.Redirdev() + device_xml.setup_attrs(**device_attrs) + # start usbredirserver + ps = process.SubProcess("usbredirserver -p {} {}:{}".format + (port_num, vendor_id, product_id), + shell=True) + server_id = ps.start() + if usb_device == "hostdev_device": + vendor_id, product_id = get_usb_source() + vendor_id = "0x" + vendor_id + product_id = "0x" + product_id + device_attrs = eval(params.get("device_attrs") % (vendor_id, product_id)) + device_xml = hostdev.Hostdev() + device_xml.setup_attrs(**device_attrs) + + libvirt.add_vm_device(vmxml, device_xml) + test.log.info("The current xml is {}".format(vmxml)) + + if not vm.is_alive(): + virsh.start(vm_name, "--paused", debug=True, ignore_status=False) + test.log.info("Check the boot order of guest after starting") + check_boot_order() + finally: + if vm.is_alive(): + virsh.destroy(vm_name) + disk_obj.cleanup_disk_preparation(disk_type) + bkxml.sync() + if 'server_id' in locals(): + process.run("killall usbredirserver") From e0719b7d2cea183f84fbfc580c426ea616977988 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Wed, 6 Dec 2023 15:33:10 +0800 Subject: [PATCH 0056/1055] Move the guests of esx6.7 and esx6.5 to esx7.0 Signed-off-by: Ming Xie --- v2v/tests/cfg/specific_kvm.cfg | 38 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/v2v/tests/cfg/specific_kvm.cfg b/v2v/tests/cfg/specific_kvm.cfg index df25bcfb04c..7e49808aba3 100644 --- a/v2v/tests/cfg/specific_kvm.cfg +++ b/v2v/tests/cfg/specific_kvm.cfg @@ -73,14 +73,14 @@ variants: - default: - sata_disk: - only source_esx.esx_65 + only source_esx.esx_70 version_required = "[libvirt-7.8.0-1,)" main_vm = 'VM_SATA_DISK_V2V_EXAMPLE' libguestfs_backend = 'direct' - multi_disks: variants: - linux: - only source_esx.esx_67 + only source_esx.esx_70 os_type = 'linux' checkpoint = 'multi_disks' vm_user = 'root' @@ -91,9 +91,9 @@ checkpoint = 'multi_disks' os_version = 'OS_VERSION_MULTI_DISK_WIN_V2V_EXAMPLE' main_vm = 'VM_MULTI_DISK_WIN_V2V_EXAMPLE' - only source_esx.esx_65 + only source_esx.esx_70 - multi_kernel: - only source_esx.esx_67 + only source_esx.esx_70 # this case requires '-v -x' v2v_debug = force_on expect_msg = 'yes' @@ -101,10 +101,10 @@ checkpoint = 'multi_kernel' main_vm = 'VM_MULTI_KERNEL_V2V_EXAMPLE' - noyumrepo-rhn: - only esx_67 + only esx_70 main_vm = 'VM_NOYUMREPO_V2V_EXAMPLE' - kdump: - only esx_67 + only esx_70 checkpoint = 'kdump' main_vm = 'VM_KDUMP_V2V_EXAMPLE' expect_msg = 'no' @@ -112,28 +112,28 @@ - fstab: variants: - cdrom: - only source_esx.esx_65 + only source_esx.esx_70 msg_content = 'warning: /files/etc/fstab.*? references unknown device "cdrom"' expect_msg = 'no' main_vm = 'VM_FSTAB_WITH_CDROM_V2V_EXAMPLE' - label: - only source_esx.esx_65 + only source_esx.esx_70 msg_content = 'unknown filesystem label.*' expect_msg = 'no' main_vm = 'VM_FSTAB_WITH_LABEL_V2V_EXAMPLE' - uuid: - only source_esx.esx_65 + only source_esx.esx_70 msg_content = 'unknown filesystem UUID.*' expect_msg = 'no' main_vm = 'VM_FSTAB_WITH_UUID_V2V_EXAMPLE' - sr0: - only source_esx.esx_67 + only source_esx.esx_70 main_vm = 'VM_FSTAB_WITH_SR0_V2V_EXAMPLE' msg_content = 'virt-v2v: warning: /files/etc/fstab/.*? references unknown device "sr"' expect_msg = no skip_vm_check = yes - invalid: - only source_esx.esx_67 + only source_esx.esx_70 msg_content = 'virt-v2v: error: libguestfs error: inspect_os: .*?: augeas parse failure:' expect_msg = 'yes' main_vm = 'VM_INVALID_FSTAB_V2V_EXAMPLE' @@ -143,7 +143,7 @@ expect_msg = 'no' msg_content = 'error: rpmdb' - bogus_kernel: - only esx_67 + only esx_70 main_vm = 'VM_BOGUS_KERNEL_V2V_EXAMPLE' msg_content = 'kernel [\s\S]* in bootloader, as it does not exist' expect_msg = 'yes' @@ -157,14 +157,14 @@ - network: variants: - multi_netcards: - only source_esx.esx_67 + only source_esx.esx_70 main_vm = 'VM_NAME_ESX_MULTI_NETCARDS_V2V_EXAMPLE' checkpoint = 'multi_netcards' - rtl8139: only source_xen main_vm = 'VM_NET_RTL8139_V2V_EXAMPLE' - e1000: - only source_esx.esx_65 + only source_esx.esx_70 os_version = 'OS_VERSION_NET_E1000_V2V_EXAMPLE' main_vm = 'VM_NET_E1000_V2V_EXAMPLE' - only_net: @@ -212,7 +212,7 @@ - vm_disable: checkpoint = 'selinux_disabled' - selinuxtype: - only esx.esx_65 + only esx.esx_70 variants: - min: checkpoint = 'check_selinuxtype' @@ -246,14 +246,14 @@ - sync_ntp: checkpoint = 'sync_ntp' - no_space: - only esx.esx_67 + only esx.esx_70 checkpoint = 'host_no_space_setcache' main_vm = 'VM_ESX_DEFAULT_NAME_V2V_EXAMPLE' - mem_alloc: only source_kvm main_vm = VM_MEM_ACCLOC_V2V_EXAMPLE - no_libguestfs_backend: - only esx.esx_67 + only esx.esx_70 main_vm = 'VM_ESX_DEFAULT_NAME_V2V_EXAMPLE' checkpoint = no_libguestfs_backend - file_image: @@ -348,7 +348,7 @@ vm_state = 'paused' checkpoint = ${vm_state} - serial_terminal: - only default.esx.esx_65 + only default.esx.esx_70 only output_mode.rhev msg_content = 'virt-v2v: error: no kernels were found in the bootloader configuration' expect_msg = 'yes' @@ -358,7 +358,7 @@ expect_msg = 'yes' variants: - host: - only default.esx.esx_65 + only default.esx.esx_70 main_vm = "VM_GUEST_NO_SPACE_V2V_EXAMPLE" checkpoint = 'host_no_space' msg_content = 'virt-v2v: error: insufficient free space in the conversion server' From 137f2cbfcf3453215d65c02a537ecb82fd510b42 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Wed, 6 Dec 2023 03:20:35 -0500 Subject: [PATCH 0057/1055] guest_os_booting: add new case for multiple boot order attributes Automate case: VIRT-297237 - Boot vm with more than one devices with boot order elements Signed-off-by: Meina Li --- .../boot_with_multiple_boot_order.cfg | 50 ++++++++++ .../boot_with_multiple_boot_order.py | 99 +++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_order.cfg create mode 100644 libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_order.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_order.cfg new file mode 100644 index 00000000000..8e22903b451 --- /dev/null +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_order.cfg @@ -0,0 +1,50 @@ +- guest_os_booting.boot_order.boot_with_multiple_boot_order: + type = boot_with_multiple_boot_order + start_vm = no + os_dict = {'bootmenu_enable': 'yes', 'bios_useserial': 'yes'} + cdrom_dict = {'source': {'attrs': {'file': '%s'}}, 'type_name': 'file', 'device': 'cdrom', 'driver': {'name': 'qemu', 'type': 'raw'}, 'target': {'dev': 'sda', 'bus': 'sata'}} + check_prompt = ["begin the installation process|Install Red Hat Enterprise"] + variants first_dev: + - hd: + disk_order = {'boot': '1'} + variants second_dev: + - cdrom: + cdrom_order = {'boot': '2'} + variants bootable_device: + - hd_bootable: + - cdrom_bootable: + - network: + network_order = {'boot': '2'} + variants bootable_device: + - hd_bootable: + - network_bootable: + check_prompt = ["iPXE initialising devices|Start PXE over IPv4"] + - cdrom: + cdrom_order = {'boot': '1'} + variants second_dev: + - hd: + disk_order = {'boot': '2'} + variants bootable_device: + - hd_bootable: + - cdrom_bootable: + - network: + network_order = {'boot': '2'} + variants bootable_device: + - cdrom_bootable: + - network_bootable: + check_prompt = ["iPXE initialising devices|Start PXE over IPv4"] + - network: + network_order = {'boot': '1'} + variants second_dev: + - hd: + disk_order = {'boot': '2'} + variants bootable_device: + - hd_bootable: + - network_bootable: + check_prompt = ["iPXE initialising devices|Start PXE over IPv4"] + - cdrom: + cdrom_order = {'boot': '2'} + variants bootable_device: + - cdrom_bootable: + - network_bootable: + check_prompt = ["iPXE initialising devices|Start PXE over IPv4"] diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py new file mode 100644 index 00000000000..ba470396fbd --- /dev/null +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py @@ -0,0 +1,99 @@ +# Copyright Red Hat +# SPDX-License-Identifier: GPL-2.0 +# Author: Meina Li + +import os + +from avocado.utils import download +from avocado.utils import process + +from virttest import data_dir +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.guest_os_booting import guest_os_booting_base as guest_os + +# Prepare a list to record the file path which need to be removed +file_list = [] + + +def prepare_device_attrs(params, vm_name, bootable_device): + """ + Prepare the device xml based on different test matrix. + + :params params: wrapped dict with all parameters + :params vm_name: the guest name + :params bootable_device: the bootable device + """ + os_dict = eval(params.get("os_dict")) + first_dev = params.get("first_dev") + second_dev = params.get("second_dev") + disk_order = eval(params.get("disk_order", "{}")) + cdrom_order = eval(params.get("cdrom_order", "{}")) + network_order = eval(params.get("network_order", "{}")) + disk_image = os.path.join(data_dir.get_data_dir(), 'images', 'test.img') + vmxml = guest_os.prepare_os_xml(vm_name, os_dict) + vmxml.remove_all_boots() + if bootable_device != "hd_bootable": + libvirt.create_local_disk("file", path=disk_image, size="500M", disk_format="qcow2") + disk_dict = {'source': {'attrs': {'file': disk_image}}} + libvirt_vmxml.modify_vm_device(vmxml, 'disk', disk_dict) + file_list.append(disk_image) + if bootable_device == "cdrom_bootable": + cdrom_path = os.path.join(data_dir.get_data_dir(), 'images', 'boot.iso') + cmd = "dnf repolist -v enabled |awk '/Repo-baseurl.*composes.*BaseOS.*os/ {print $NF}'" + repo_url = process.run(cmd, shell=True).stdout_text.strip() + boot_img_url = os.path.join(repo_url, 'images', 'boot.iso') + download.get_file(boot_img_url, cdrom_path) + else: + cdrom_path = os.path.join(data_dir.get_data_dir(), 'images', 'test.iso') + libvirt.create_local_disk("file", path=cdrom_path, size="500M", disk_format="raw") + file_list.append(cdrom_path) + cdrom_dict = eval(params.get("cdrom_dict") % cdrom_path) + cdrom_dict.update(cdrom_order) + cdrom_xml = libvirt_vmxml.create_vm_device_by_type("disk", cdrom_dict) + vmxml.add_device(cdrom_xml) + vmxml.sync() + # Update boot order attributes + if "hd" in (first_dev, second_dev): + libvirt_vmxml.modify_vm_device(vmxml, 'disk', disk_order) + if "network" in (first_dev, second_dev): + libvirt_vmxml.modify_vm_device(vmxml, 'interface', network_order) + + +def run(test, params, env): + """ + This case is to verify the boot order when more than one boot dev elements in guest. + 1) Start a guest with the necessary device xml. + 2) Check the guest boot status. + """ + vm_name = guest_os.get_vm(params) + check_prompt = eval(params.get("check_prompt", "[]")) + bootable_device = params.get("bootable_device") + os_dict = eval(params.get("os_dict")) + + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) + bkxml = vmxml.copy() + + try: + test.log.info("TEST_SETUP: prepare a guest with necessary attributes.") + prepare_device_attrs(params, vm_name, bootable_device) + test.log.info("TEST_STEP1: start the guest.") + if not vm.is_alive(): + vm.start() + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + test.log.debug(f"The current guest xml is: {vmxml}") + test.log.info("TEST_STEP2: check the guest boot from expected device.") + if bootable_device == "hd_bootable": + vm.wait_for_login(timeout=360).close() + test.log.debug("Succeed to boot %s", vm_name) + else: + vm.serial_console.read_until_output_matches(check_prompt, timeout=300, + internal_timeout=0.5) + finally: + bkxml.sync() + for file in file_list: + if os.path.exists(file): + os.remove(file) From ac18e73aa910f88bb43409961df092f3e92e7b76 Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 14 Nov 2023 20:12:38 +0800 Subject: [PATCH 0058/1055] migration: Add case to test block disk VM live migration with copy stoarge - disk type=block Signed-off-by: lcheng --- .../disk_type_coverage/block_disk.cfg | 40 ++++++++ .../disk_type_coverage/block_disk.py | 99 +++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 libvirt/tests/cfg/migration_with_copy_storage/disk_type_coverage/block_disk.cfg create mode 100644 libvirt/tests/src/migration_with_copy_storage/disk_type_coverage/block_disk.py diff --git a/libvirt/tests/cfg/migration_with_copy_storage/disk_type_coverage/block_disk.cfg b/libvirt/tests/cfg/migration_with_copy_storage/disk_type_coverage/block_disk.cfg new file mode 100644 index 00000000000..1891f05b5dd --- /dev/null +++ b/libvirt/tests/cfg/migration_with_copy_storage/disk_type_coverage/block_disk.cfg @@ -0,0 +1,40 @@ +- migration_with_copy_storage.disk_type_coverage.block_disk: + type = block_disk + migration_setup = 'yes' + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = "" + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = "qemu:///system" + image_convert = "no" + status_error = "no" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + start_vm = "no" + setup_nfs = "no" + nfs_mount_dir = + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + target_type = "vdb" + attach_disk_args = "--config --driver qemu --subdriver raw" + scsi_disk_option = "lbpu=1 lbpws=1" + check_disk_after_mig = "yes" + variants: + - p2p: + virsh_migrate_options = "--live --p2p --verbose" + - non_p2p: + virsh_migrate_options = "--live --verbose" + variants: + - copy_storage_all: + copy_storage_option = "--copy-storage-all" + - copy_storage_inc: + copy_storage_option = "--copy-storage-inc" diff --git a/libvirt/tests/src/migration_with_copy_storage/disk_type_coverage/block_disk.py b/libvirt/tests/src/migration_with_copy_storage/disk_type_coverage/block_disk.py new file mode 100644 index 00000000000..9bf306b360d --- /dev/null +++ b/libvirt/tests/src/migration_with_copy_storage/disk_type_coverage/block_disk.py @@ -0,0 +1,99 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: Liping Cheng +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +import re + +from virttest import remote +from virttest import utils_disk +from virttest import virsh + +from virttest.utils_test import libvirt + +from provider.migration import base_steps + + +def setup_block_device_on_remote(params): + """ + Setup block device on remote host + + :param params: Dictionary with the test parameters + """ + cmd = "modprobe scsi_debug lbpu=1 lbpws=1 dev_size_mb=2048" + remote.run_remote_cmd(cmd, params, ignore_status=False) + + +def cleanup_block_device_on_remote(params): + """ + Cleanup block device on remote host + + :param params: Dictionary with the test parameters + """ + ret = remote.run_remote_cmd("lsscsi | grep scsi_debug", params, ignore_status=False) + if ret.exit_status == 0: + scsi_addr_pattern = '[0-9]+:[0-9]+:[0-9]+:[0-9]+' + for addr in re.findall(scsi_addr_pattern, ret.stdout_text): + remote.run_remote_cmd("echo 1>/sys/class/scsi_device/{}/device/delete".format(addr), + params, ignore_status=False) + + remote.run_remote_cmd("modprobe -r scsi_debug", params, ignore_status=False) + + +def run(test, params, env): + """ + To verify that live migration with copying storage can succeed for block + disk. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def setup_test(): + """ + Setup steps + + """ + test.log.info("Setup steps.") + attach_disk_args = params.get("attach_disk_args") + scsi_disk_option = params.get("scsi_disk_option") + target_type = params.get("target_type") + + migration_obj.setup_connection() + base_steps.prepare_disks_remote(params, vm) + setup_block_device_on_remote(params) + + disk_source = libvirt.create_scsi_disk(scsi_disk_option) + virsh.attach_disk(vm_name, disk_source, target_type, + attach_disk_args, debug=True, ignore_status=False) + vm.start() + vm_session = vm.wait_for_login() + utils_disk.linux_disk_check(vm_session, target_type) + vm_session.close() + + def cleanup_test(): + """ + Cleanup steps + + """ + test.log.info("Cleanup steps.") + migration_obj.cleanup_connection() + libvirt.delete_scsi_disk() + cleanup_block_device_on_remote(params) + base_steps.cleanup_disks_remote(params, vm) + + vm_name = params.get("migrate_main_vm") + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + setup_test() + migration_obj.run_migration() + migration_obj.verify_default() + finally: + cleanup_test() From 93a040709869d69b60325fddbe985256a074db36 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Thu, 7 Dec 2023 03:52:00 -0500 Subject: [PATCH 0059/1055] guest_os_booting: new case of booting vm with seclabel in backed nvram This case is to verify the seclabel source in backed nvram: VIRT-299960 Signed-off-by: Meina Li --- .../ovmf_firmware/ovmf_seclabel_in_nvram.cfg | 34 ++++++++ .../ovmf_firmware/ovmf_seclabel_in_nvram.py | 80 +++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_seclabel_in_nvram.cfg create mode 100644 libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_seclabel_in_nvram.py diff --git a/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_seclabel_in_nvram.cfg b/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_seclabel_in_nvram.cfg new file mode 100644 index 00000000000..eeff9ab041a --- /dev/null +++ b/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_seclabel_in_nvram.cfg @@ -0,0 +1,34 @@ +- guest_os_booting.ovmf_seclabel_in_nvram: + type = ovmf_seclabel_in_nvram + start_vm = no + loader_path = "/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd" + template_path = "/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd" + os_dict = {'secure': 'yes', 'loader_readonly': 'yes', 'loader_type': 'pflash', 'loader': '${loader_path}'} + nvram_attrs = {'nvram_attrs': {'template': '${template_path}', 'type': 'file'}} + nvram_source = {'nvram_source': {'seclabels': [{'label': '%s', 'model': '%s', 'relabel': 'yes'}], 'attrs': {'file': '%s'}}} + firmware_type = "ovmf" + func_supported_since_libvirt_ver = (8, 5, 0) + only q35 + only x86_64 + variants: + - positive_test: + variants: + - with_selinux_seclabel: + seclabel_model = "selinux" + seclabel_label = "system_u:object_r:svirt_image_t:s0" + - with_dac_seclabel: + seclabel_model = "dac" + seclabel_label = "qemu:qemu" + - negative_test: + error_msg = "Could not open .*: Permission denied" + variants: + - invalid_selinux_seclabel: + seclabel_model = "selinux" + seclabel_label = "unconfined_u:object_r:virt_image_t:s0" + - invalid_dac_seclabel: + seclabel_model = "dac" + seclabel_label = "test:test" + - with_no_relabel: + without_label = "yes" + seclabel_model = "selinux" + nvram_source = {'nvram_source': {'seclabels': [{'model': '%s', 'relabel': 'no'}], 'attrs': {'file': '%s'}}} diff --git a/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_seclabel_in_nvram.py b/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_seclabel_in_nvram.py new file mode 100644 index 00000000000..280d3f9f036 --- /dev/null +++ b/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_seclabel_in_nvram.py @@ -0,0 +1,80 @@ +# Copyright Red Hat +# SPDX-License-Identifier: GPL-2.0 +# Author: Meina Li + +import os + +from avocado.utils import process + +from virttest import libvirt_version +from virttest import virsh +from virttest.data_dir import get_data_dir +from virttest.libvirt_xml import vm_xml +from provider.guest_os_booting import guest_os_booting_base as guest_os + + +def run(test, params, env): + """ + This case is to verify the ovmf backed nvram. + 1) Prepare a guest with related backed nvram elements. + 2) Start and boot the guest. + 3) Check the dumpxml and the label if necessary. + """ + def compare_guest_xml(vmxml, os_attrs): + """ + Compare current xml with the configured values + + :params vmxml: the guest xml + :params os_attrs: the os attributes dict + """ + os_xml = vmxml.os + current_os_attrs = os_xml.fetch_attrs() + for key in os_attrs: + if key in current_os_attrs: + if os_attrs[key] != current_os_attrs[key]: + test.fail("Configured os xml value {} doesn't match the" + " entry {} in guest xml".format(os_attrs[key], current_os_attrs[key])) + else: + test.fail("Configured os attributes {} don't existed in guest.".format(key)) + + vm_name = guest_os.get_vm(params) + firmware_type = params.get("firmware_type") + nvram_file = os.path.join(get_data_dir(), "test.fd") + nvram_attrs = eval(params.get("nvram_attrs")) + os_dict = eval(params.get("os_dict")) + seclabel_label = params.get("seclabel_label") + seclabel_model = params.get("seclabel_model") + error_msg = params.get("error_msg", "") + without_label = "yes" == params.get("without_label", "no") + libvirt_version.is_libvirt_feature_supported(params) + + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + if without_label: + nvram_source = eval(params.get("nvram_source") % (seclabel_model, nvram_file)) + else: + nvram_source = eval(params.get("nvram_source") % (seclabel_label, seclabel_model, nvram_file)) + os_attrs = {**os_dict, **nvram_attrs, **nvram_source} + guest_os.prepare_os_xml(vm_name, os_attrs, firmware_type) + vmxml = guest_os.check_vm_startup(vm, vm_name, error_msg) + if error_msg: + return + test.log.info("Check the os xml in dumpxml") + compare_guest_xml(vmxml, os_attrs) + test.log.info("Check the nvram file label in host") + label_result = process.run("ls -lZ {}".format(nvram_file)).stdout_text + if seclabel_model == "dac": + seclabel_label = seclabel_label.replace(":", " ") + if seclabel_label in label_result: + test.log.info("Get expected nvram file label: {}".format(label_result)) + else: + test.fail("The nvram file label {} is not expected".format(label_result)) + finally: + if vm.is_alive(): + virsh.destroy(vm_name) + if os.path.exists(nvram_file): + os.remove(nvram_file) + bkxml.sync() From 874869c0e883b6050bd9908531ba21a8ba4c264b Mon Sep 17 00:00:00 2001 From: Hu Shuai Date: Fri, 8 Dec 2023 10:29:55 +0800 Subject: [PATCH 0060/1055] numa: Update the attribute for online nodes "all_usable_numa_nodes" has been deprecated in db7401a, it uses "online_nodes_withmem" now. Signed-off-by: Hu Shuai --- libvirt/tests/src/numa/host_numa/host_numa_info.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/src/numa/host_numa/host_numa_info.py b/libvirt/tests/src/numa/host_numa/host_numa_info.py index b687006a78e..df063ab7d26 100644 --- a/libvirt/tests/src/numa/host_numa/host_numa_info.py +++ b/libvirt/tests/src/numa/host_numa/host_numa_info.py @@ -41,7 +41,7 @@ def _allocate_test(page_num, node_id, page_size): return allocated_num ret = {} - all_nodes = test_obj.all_usable_numa_nodes + all_nodes = test_obj.online_nodes_withmem allocate_dict = eval(test_obj.params.get('allocate_dict')) hpc = test_setup.HugePageConfig(test_obj.params) pagesize_list = list(allocate_dict.keys()) @@ -212,7 +212,7 @@ def verify_node_mem_by_freepages(test_obj): :param test_obj: NumaTest object """ allocate_result = test_obj.params['allocate_result'] - all_nodes = test_obj.all_usable_numa_nodes + all_nodes = test_obj.online_nodes_withmem for one_node in all_nodes: for pgsize in allocate_result[one_node].keys(): common_test_freepages(test_obj, @@ -230,7 +230,7 @@ def verify_node_mem_by_freepages_various_unit(test_obj): :param test_obj: NumaTest object """ allocate_result = test_obj.params['allocate_result'] - all_nodes = test_obj.all_usable_numa_nodes + all_nodes = test_obj.online_nodes_withmem for pgsize in allocate_result[all_nodes[1]].keys(): common_test_freepages(test_obj, all_nodes[1], From 9f1150c853cab04e32017f71897999844e88203c Mon Sep 17 00:00:00 2001 From: Hu Shuai Date: Fri, 8 Dec 2023 17:14:28 +0800 Subject: [PATCH 0061/1055] libvirtd: Fix condition Based d9d6fb8, there are three results for `systemctl -a| grep virtlogd`: 1. status is 1, output is none --> pass 2. status is 0, output contains the daemon and 'not-found' --> pass 3. status is 0, output contains the daemon but no 'not-found' --> fail The previous condition will determine that the first case fails. Just judging the output should be enough here. Signed-off-by: Hu Shuai --- libvirt/tests/src/daemon/check_daemon_after_remove_pkgs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/daemon/check_daemon_after_remove_pkgs.py b/libvirt/tests/src/daemon/check_daemon_after_remove_pkgs.py index 4c669b645e5..b8f3f9eeaa7 100644 --- a/libvirt/tests/src/daemon/check_daemon_after_remove_pkgs.py +++ b/libvirt/tests/src/daemon/check_daemon_after_remove_pkgs.py @@ -46,9 +46,9 @@ def run(test, params, env): test.error("Failed to remove libvirt packages on guest") for daemon in daemons: - err, out = session.cmd_status_output("systemctl -a| grep %s" % daemon) + _, out = session.cmd_status_output("systemctl -a| grep %s" % daemon) LOGGER.debug(out) - if err or daemon in out and "not-found" not in out: + if daemon in out and "not-found" not in out: test.fail("%s still exists after removing libvirt pkgs" % daemon) finally: From 2e3d96bea8f0c1fcbaae4eb80790a2c06e26244d Mon Sep 17 00:00:00 2001 From: nanli Date: Thu, 23 Nov 2023 15:39:30 +0800 Subject: [PATCH 0062/1055] add case for invalid virtio-mem config xxxx-299162: Invalid virtio-mem memory device config values Signed-off-by: nanli --- .../invalid_virtio_mem_config.cfg | 60 +++++++ .../invalid_virtio_mem_config.py | 146 ++++++++++++++++++ provider/memory/memory_base.py | 29 ++++ 3 files changed, 235 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_devices/invalid_virtio_mem_config.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/invalid_virtio_mem_config.py diff --git a/libvirt/tests/cfg/memory/memory_devices/invalid_virtio_mem_config.cfg b/libvirt/tests/cfg/memory/memory_devices/invalid_virtio_mem_config.cfg new file mode 100644 index 00000000000..9f3dc29cc74 --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/invalid_virtio_mem_config.cfg @@ -0,0 +1,60 @@ +- memory.devices.invalid_virtio_mem: + type = invalid_virtio_mem_config + start_vm = 'no' + mem_model = 'virtio-mem' + node_mask = '0' + target_size = 524288 + request_size = 262144 + block_size = 2048 + aarch64: + request_size = 524288 + block_size = 524288 + guest_node = 0 + addr_base = '0x100000000' + pagesize_cmd = "getconf PAGE_SIZE" + pagesize_unit = 'b' + required_kernel = [5.14.0,) + guest_required_kernel = [5.8.0,) + func_supported_since_libvirt_ver = (8, 0, 0) + func_supported_since_qemu_kvm_ver = (6, 2, 0) + variants invalid_setting: + - over_request_mem: + request_size = 1048576 + define_error = "requested size must be smaller than or equal to @size" + - max_addr: + addr_base = '0xffffffffffffffff' + define_error = "memory device address must be aligned to blocksize" + - unexisted_node: + guest_node = '6' + define_error = "can't add memory backend for guest node '${guest_node}' as the guest has only '2' NUMA nodes configured" + - unexisted_nodemask: + node_mask = '7' + start_vm_error = "NUMA node ${node_mask} is unavailable" + - invalid_pagesize: + invalid_pagesize = '9216' + pagesize_unit = 'b' + start_vm_error = "Unable to find any usable hugetlbfs mount for 9 KiB" + - small_block: + block_size = '1024' + define_error = "block size too small, must be at least" + - invalid_block: + block_size = "3072" + define_error = "block size must be a power of two" + addr_dict = "'address':{'attrs': {'base': '${addr_base}','slot': '0'}}" + source_dict = "'source': {'nodemask': '${node_mask}','pagesize': %d, 'pagesize_unit':'${pagesize_unit}'}" + mem_dict = {'mem_model':'${mem_model}', ${source_dict}, 'target': {'size':${target_size}, 'size_unit':'KiB', ${addr_dict}, 'node':${guest_node},'requested_size': ${request_size}, 'block_size': ${block_size}}} + variants basic_memory: + - with_numa: + no s390-virtio + mem_value = 2097152 + mem_unit = 'KiB' + current_mem = 2097152 + current_mem_unit = 'KiB' + numa_mem = 1048576 + max_mem_slots = 16 + max_mem = 10485760 + max_mem_unit = 'KiB' + max_dict = '"max_mem_rt": ${max_mem}, "max_mem_rt_slots": ${max_mem_slots}, "max_mem_rt_unit": "${max_mem_unit}"' + numa_attrs = "'vcpu': 4,'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'},{'id':'1','cpus': '2-3','memory':'${numa_mem}','unit':'KiB'}]}" + vm_attrs = {${numa_attrs}, ${max_dict}, 'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':"KiB"} + diff --git a/libvirt/tests/src/memory/memory_devices/invalid_virtio_mem_config.py b/libvirt/tests/src/memory/memory_devices/invalid_virtio_mem_config.py new file mode 100644 index 00000000000..3367ae476e6 --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/invalid_virtio_mem_config.py @@ -0,0 +1,146 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from avocado.utils import process + +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.devices import memory +from virttest.utils_test import libvirt + +from provider.numa import numa_base +from provider.memory import memory_base + + +def get_page_size(params): + """ + Get pagesize value + + :param params: Dictionary with the test parameters + """ + invalid_pagesize = params.get("invalid_pagesize") + pagesize_cmd = params.get("pagesize_cmd") + + if invalid_pagesize: + page_size = invalid_pagesize + else: + page_size = process.run(pagesize_cmd, ignore_status=True, + shell=True).stdout_text.strip() + return int(page_size) + + +def get_mem_obj(mem_dict): + """ + Get mem object. + + :param mem_dict: memory dict value + :return: mem_obj, memory object. + """ + mem_obj = memory.Memory() + mem_obj.setup_attrs(**eval(mem_dict)) + return mem_obj + + +def define_guest(test, params, page_size): + """ + Define guest with specific + + :param test: test object + :param params: Dictionary with the test parameters. + :params: page_size, the pagesize that used when define guest. + """ + vm_name = params.get("main_vm") + vm_attrs = eval(params.get("vm_attrs")) + mem_dict = params.get("mem_dict") + define_error = params.get("define_error") + + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + vmxml.setup_attrs(**vm_attrs) + + virtio_mem = get_mem_obj(mem_dict % page_size) + vmxml.devices = vmxml.devices.append(virtio_mem) + test.log.debug("Define vm with %s." % vmxml) + + # Define guest + try: + vmxml.sync() + except Exception as e: + if define_error: + if define_error not in str(e): + test.fail("Expect to get '%s' error, but got '%s'" % (define_error, e)) + else: + test.fail("Expect define successfully, but failed with '%s'" % e) + + +def run(test, params, env): + """ + Verify error messages prompt with invalid virtio-mem device configs + + 1.invalid value: + over committed requested memory, max address base, nonexistent guest node + nonexistent node mask, invalid pagesize, small block size, invalid block size + 2.memory setting: with numa + """ + + def setup_test(): + """ + Check host has at least 2 numa nodes. + """ + test.log.info("TEST_SETUP: Check the numa nodes") + numa_obj = numa_base.NumaTest(vm, params, test) + numa_obj.check_numa_nodes_availability() + + def run_test(): + """ + Define vm with virtio-mem and start vm. + Define vm without virtio-mem and hotplug virtio-mem. + """ + test.log.info("TEST_STEP1: Define vm with virio-mem") + source_pagesize = get_page_size(params) + define_guest(test, params, source_pagesize) + + test.log.info("TEST_STEP2: Start guest") + start_result = virsh.start(vm_name, ignore_status=True, debug=True) + libvirt.check_result(start_result, start_vm_error) + + test.log.info("TEST_STEP3: Start guest without virtio-mem") + original_vmxml.setup_attrs(**vm_attrs) + test.log.debug("Define vm without virtio-mem by '%s' \n", original_vmxml) + original_vmxml.sync() + virsh.start(vm_name, debug=True) + + test.log.info("TEST_STEP4: Hotplug virtio-mem memory device") + mem_obj = get_mem_obj(mem_dict % source_pagesize) + result = virsh.attach_device(vm_name, mem_obj.xml, debug=True).stderr_text + if attach_error not in result: + test.fail("Expected get error '%s', but got '%s'" % (attach_error, result)) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bkxml.sync() + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + original_vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = original_vmxml.copy() + mem_dict = params.get("mem_dict") + vm_attrs = eval(params.get("vm_attrs")) + start_vm_error = params.get("start_vm_error") + attach_error = params.get("start_vm_error", params.get("define_error")) + + try: + memory_base.check_supported_version(params, test, vm) + setup_test() + run_test() + + finally: + teardown_test() diff --git a/provider/memory/memory_base.py b/provider/memory/memory_base.py index 2d3592826c6..8032a7ba3f1 100644 --- a/provider/memory/memory_base.py +++ b/provider/memory/memory_base.py @@ -1,5 +1,10 @@ import re +from virttest import libvirt_version +from virttest import utils_misc + +from virttest.utils_version import VersionInterval + from avocado.core import exceptions @@ -47,3 +52,27 @@ def convert_data_size(current_size, dest_unit="KiB"): if isinstance(dest_size, float): return dest_size return int(dest_size) + + +def check_supported_version(params, test, vm): + """ + Check the supported version + + :param params: Dictionary with the test parameters + :param test: Test object + :param vm: Vm object + """ + guest_required_kernel = params.get('guest_required_kernel') + libvirt_version.is_libvirt_feature_supported(params) + utils_misc.is_qemu_function_supported(params) + if not guest_required_kernel: + return + + if not vm.is_alive(): + vm.start() + vm_session = vm.wait_for_login() + vm_kerv = vm_session.cmd_output('uname -r').strip().split('-')[0] + vm_session.close() + if vm_kerv not in VersionInterval(guest_required_kernel): + test.cancel("Got guest kernel version:%s, which is not in %s" % + (vm_kerv, guest_required_kernel)) From 6fa505704f7e334076074987cebc32594feee02d Mon Sep 17 00:00:00 2001 From: nanli Date: Thu, 9 Nov 2023 17:49:53 +0800 Subject: [PATCH 0063/1055] add case for invalid dimm device config VIRT-299046: Verify error messages prompt with invalid memory device configs Signed-off-by: nanli --- .../invalid_dimm_memory_device_config.cfg | 50 +++++ .../invalid_dimm_memory_device_config.py | 171 ++++++++++++++++++ 2 files changed, 221 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_devices/invalid_dimm_memory_device_config.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/invalid_dimm_memory_device_config.py diff --git a/libvirt/tests/cfg/memory/memory_devices/invalid_dimm_memory_device_config.cfg b/libvirt/tests/cfg/memory/memory_devices/invalid_dimm_memory_device_config.cfg new file mode 100644 index 00000000000..452a0ffb895 --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/invalid_dimm_memory_device_config.cfg @@ -0,0 +1,50 @@ +- memory.devices.invalid_dimm: + type = invalid_dimm_memory_device_config + node_mask = '1' + target_size = 524288 + guest_node = 0 + slot = 0 + addr_type = 'dimm' + addr_base = '0x100000000' + pagesize_cmd = "getconf PAGE_SIZE" + pagesize_unit = 'b' + mem_value = 2097152 + mem_unit = 'KiB' + current_mem = 2097152 + current_mem_unit = 'KiB' + numa_mem = 1048576 + max_mem_slots = 16 + max_mem = 10485760 + max_mem_unit = 'KiB' + max_dict = '"max_mem_rt": ${max_mem}, "max_mem_rt_slots": ${max_mem_slots}, "max_mem_rt_unit": "${max_mem_unit}"' + variants invalid_setting: + - exceed_slot: + slot = '4294967295' + define_error = "memory device slot '${slot}' exceeds slots count" + - max_addr: + addr_base = '0xffffffffffffffff' + start_vm_error = "address must be aligned to" + - unexisted_node: + guest_node = '6' + start_vm_error = "can't add memory backend for guest node '${guest_node}' as the guest has only '2' NUMA nodes configured" + - unexisted_nodemask: + node_mask = '7' + start_vm_error = "NUMA node ${node_mask} is unavailable" + - invalid_pagesize: + invalid_pagesize = '9216' + pagesize_unit = 'b' + start_vm_error = "Unable to find any usable hugetlbfs mount for 9 KiB" + - invalid_addr_type: + addr_type = 'fakedimm' + define_error = "Invalid value for attribute 'type' in element 'address': '${addr_type}'" + define_error_8 = "unknown address type '${addr_type}'" + aarch64: + define_error = "unknown address type '${addr_type}'" + addr_dict = "'address':{'attrs': {'type': '${addr_type}', 'base': '${addr_base}', 'slot': '${slot}'}}" + source_dict = "'source': {'nodemask': '${node_mask}','pagesize': %d, 'pagesize_unit':'${pagesize_unit}'}" + dimm_dict = {'mem_model':'dimm', ${source_dict}, ${addr_dict}, 'target': {'size':${target_size}, 'size_unit':'KiB','node':${guest_node}}} + variants basic_memory: + - with_numa: + no s390-virtio + numa_attrs = "'vcpu': 4,'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'},{'id':'1','cpus': '2-3','memory':'${numa_mem}','unit':'KiB'}]}" + vm_attrs = {${numa_attrs}, ${max_dict}, 'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':"KiB"} diff --git a/libvirt/tests/src/memory/memory_devices/invalid_dimm_memory_device_config.py b/libvirt/tests/src/memory/memory_devices/invalid_dimm_memory_device_config.py new file mode 100644 index 00000000000..148040df382 --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/invalid_dimm_memory_device_config.py @@ -0,0 +1,171 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from avocado.utils import process + +from virttest import libvirt_version +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.devices import memory +from virttest.utils_test import libvirt + +from provider.numa import numa_base + + +def get_pagesize_value(params): + """ + Get pagesize value + + :param params: Dictionary with the test parameters + :return: page_size, The page size to set in original vmxml + """ + invalid_pagesize = params.get("invalid_pagesize") + pagesize_cmd = params.get("pagesize_cmd") + + if invalid_pagesize: + page_size = invalid_pagesize + else: + page_size = process.run(pagesize_cmd, ignore_status=True, + shell=True).stdout_text.strip() + return int(page_size) + + +def get_mem_obj(mem_dict): + """ + Get mem object. + + :param mem_dict: memory dict value. + :return mem_obj: object of memory devices. + """ + mem_obj = memory.Memory() + mem_obj.setup_attrs(**eval(mem_dict)) + return mem_obj + + +def define_guest(test, params, page_size): + """ + Define guest with specific + + :param test: test object. + :param params: dict, test parameters. + :param page_size: page size value in vm xml. + """ + vm_name = params.get("main_vm") + vm_attrs = eval(params.get("vm_attrs")) + dimm_dict = params.get("dimm_dict") + invalid_setting = params.get("invalid_setting") + + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + vmxml.setup_attrs(**vm_attrs) + + devices = vmxml.get_devices() + mem_obj = get_mem_obj(dimm_dict % page_size) + devices.append(mem_obj) + vmxml.set_devices(devices) + test.log.debug("Define vm with %s." % vmxml) + + # Check libvirt version + if libvirt_version.version_compare(9, 0, 0) and \ + invalid_setting == "unexisted_node": + define_error = params.get("start_vm_error") + elif not libvirt_version.version_compare(9, 0, 0) and \ + invalid_setting == "invalid_addr_type": + define_error = params.get("define_error_8") + else: + define_error = params.get("define_error") + # Redefine define_error for checking start_vm_error + params.update({"define_error": define_error}) + + # Define guest + try: + vmxml.sync() + except Exception as e: + if define_error: + if define_error not in str(e): + test.fail("Expect to get '%s' error, but got '%s'" % (define_error, e)) + else: + test.fail("Expect define successfully, but failed with '%s'" % e) + + +def run(test, params, env): + """ + Verify error messages prompt with invalid memory device configs + + 1.invalid value: + exceed slot number, max address base, nonexistent guest node + nonexistent node mask, invalid pagesize, invalid address type + 2.memory setting: with numa + """ + + def setup_test(): + """ + Check host has at least 2 numa nodes. + """ + test.log.info("TEST_SETUP: Check the numa nodes") + numa_obj = numa_base.NumaTest(vm, params, test) + numa_obj.check_numa_nodes_availability() + + def run_test(): + """ + Define vm with dimm. + Start vm. + Hotplug dimm. + """ + test.log.info("TEST_STEP1: Define vm and check result") + source_pagesize = get_pagesize_value(params) + define_guest(test, params, source_pagesize) + + test.log.info("TEST_STEP2: Start guest ") + start_result = virsh.start(vm_name, ignore_status=True) + if start_vm_error: + # Start success for unexisted_node scenario and version>9.0 + if libvirt_version.version_compare(9, 0, 0) and \ + invalid_setting == "unexisted_node": + libvirt.check_exit_status(start_result) + else: + libvirt.check_result(start_result, start_vm_error) + + test.log.info("TEST_STEP3: Start guest without dimm devices") + original_xml.setup_attrs(**vm_attrs) + test.log.debug("Define vm by '%s' \n", original_xml) + original_xml.sync() + virsh.start(vm_name, debug=True, ignore_status=False) + + test.log.info("TEST_STEP4: Hotplug dimm memory device") + attach_error = params.get("start_vm_error", params.get("define_error")) + + mem_obj = get_mem_obj(dimm_dict % source_pagesize) + result = virsh.attach_device(vm_name, mem_obj.xml, debug=True).stderr_text + if attach_error not in result: + test.fail("Expected get error '%s', but got '%s'" % (attach_error, result)) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bkxml.sync() + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = original_xml.copy() + dimm_dict = params.get("dimm_dict") + invalid_setting = params.get("invalid_setting") + vm_attrs = eval(params.get("vm_attrs")) + start_vm_error = params.get("start_vm_error") + + try: + setup_test() + run_test() + + finally: + teardown_test() From 9272d705799211e1cb9087ed40b4c329f4d8a4ae Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 11 Dec 2023 06:16:48 -0500 Subject: [PATCH 0064/1055] lifecycle_time: relax test condition When running this test several times it sometimes takes up to 1.029 seconds to sleep for 1 second. This is still a good test result for the original issue where we had deviations for 100-10000%. Use a less strict check to account for this variability. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/cpu/lifecycle_time.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/cpu/lifecycle_time.py b/libvirt/tests/src/cpu/lifecycle_time.py index 491617d43c9..6b506b60284 100644 --- a/libvirt/tests/src/cpu/lifecycle_time.py +++ b/libvirt/tests/src/cpu/lifecycle_time.py @@ -39,7 +39,7 @@ def run(test, params, env): session.close() lines = out.split('\n') - if len(lines) < 2 or 'real\t0m1.00' not in lines[1]: + if len(lines) < 2 or 'real\t0m1.0' not in lines[1]: test.fail("VM seems to have slept longer than expected: %s" % out) except Exception as e: test.error("Test error: %s" % e) From c8ba1d61f36a09a36434ccfe8a0e4d34448b9ac7 Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 11 Dec 2023 19:27:40 +0800 Subject: [PATCH 0065/1055] migration: Fix 'nc' command failure Run 'nc' command failed on remote host, so update code. Signed-off-by: lcheng --- ...igration_port_allocation_port_occupied_by_other_app.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/migration/migration_uri/tcp_migration_port_allocation_port_occupied_by_other_app.py b/libvirt/tests/src/migration/migration_uri/tcp_migration_port_allocation_port_occupied_by_other_app.py index 89ae5afbaf2..fef071955a1 100644 --- a/libvirt/tests/src/migration/migration_uri/tcp_migration_port_allocation_port_occupied_by_other_app.py +++ b/libvirt/tests/src/migration/migration_uri/tcp_migration_port_allocation_port_occupied_by_other_app.py @@ -14,13 +14,19 @@ def run(test, params, env): """ vm_name = params.get("migrate_main_vm") occupy_port_cmd = params.get("occupy_port_cmd") + server_ip = params.get("server_ip") + server_user = params.get("server_user", "root") + server_pwd = params.get("server_pwd") vm = env.get_vm(vm_name) migration_obj = base_steps.MigrationBase(test, vm, params) try: migration_obj.setup_connection() - remote.run_remote_cmd(occupy_port_cmd, params, ignore_status=False) + runner_on_target = remote.RemoteRunner(host=server_ip, + username=server_user, + password=server_pwd) + remote.run_remote_cmd(occupy_port_cmd, params, runner_on_target, ignore_status=False) migration_obj.run_migration() migration_obj.verify_default() finally: From 712d5c6df462f933ebfdc3ff7f79da280d947950 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Mon, 18 Sep 2023 03:12:13 -0400 Subject: [PATCH 0066/1055] Add cases to cover start virtlogd with various config VIRT-xx: virtlogd can be started with specified config by configuring VIRTLOGD_ARGS="--config /etc/libvirt/virtlogd-new.conf" in /etc/sysconfig/virtlogd VIRT-xx: [virtlogd][-t | --timeout] Start virtlogd with --timeout and without active guests VIRT-xx: [virtlogd] [Reload] [negative] Virtlogd.service reload failed with invalid configuration VIRT-xx: [virtlogd][Stop] Stop virtlogd service when guest is running VIRT-xx: [virtlogd]Check qemu log when guest fails to start due to "qemu process exits" error VIRT-xx: [virtlogd] Start virtlogd with default max_size and max_backups VIRT-xx: [virtlogd]Remove the qemu log file when guest is running VIRT-xx: [virtlogd] [start] [negative] Virtlogd.serivce start failed with invalid configuration VIRT-xx: [virtlogd] Check opened FDs of qemu log file when guest is running and destroyed VIRT-xx: [virtlogd] Check qemu log when guest shuts down VIRT-xx: [virtlogd] Check qemu log when guest starts for the second time VIRT-xx: [virtlogd]Check the qemu log when save&restore guest. Signed-off-by: chunfuwen --- .../conf_file/qemu_conf/set_virtlogd.cfg | 49 +++ .../conf_file/qemu_conf/set_virtlogd.py | 375 +++++++++++++++++- 2 files changed, 420 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/cfg/daemon/conf_file/qemu_conf/set_virtlogd.cfg b/libvirt/tests/cfg/daemon/conf_file/qemu_conf/set_virtlogd.cfg index 0805480214d..250b3cf987c 100644 --- a/libvirt/tests/cfg/daemon/conf_file/qemu_conf/set_virtlogd.cfg +++ b/libvirt/tests/cfg/daemon/conf_file/qemu_conf/set_virtlogd.cfg @@ -32,8 +32,57 @@ - disabled_virtlogd: expected_result = virtlogd_disabled start_vm = no + - specific_config_file: + expected_result = virtlogd_specific_config_file_enable + virtlogd_config_file = "/etc/sysconfig/virtlogd" + virtlogd_config_bak_file = "/etc/sysconfig/virtlogd.bak" + virtlogd_config_file_new = "/etc/libvirt/virtlogd-new.conf" + virtlogd_config_file_alternative_new = "/var/log/libvirt/virtlogd-new.log" + start_vm = no + - specific_timeout: + expected_result = virtlogd_specific_timeout + virtlogd_config_file = "/etc/sysconfig/virtlogd" + virtlogd_config_bak_file = "/etc/sysconfig/virtlogd.bak" + virtlogd_config_file_new = "/etc/libvirt/virtlogd-new.conf" + start_vm = no + - record_qenu_crash_log: + expected_result = record_qenu_crash_log + crash_information = "unable to map backing store for guest RAM: Cannot allocate memory" + start_vm = no + - stop_virtlogd: + expected_result = stop_virtlogd + start_vm = no + - default_max_size_max_backups: + expected_result = default_max_size_max_backups + max_backups = 3 + start_vm = no + - recreate_qemu_log: + expected_result = recreate_qemu_log + start_vm = no + - opened_fd_of_qemu_log_file: + expected_result = opened_fd_of_qemu_log_file + start_vm = no + - vm_destroy_log_into_qemu_log_file: + expected_result = vm_destroy_log_into_qemu_log_file + start_vm = no + - start_vm_twice_log_into_qemu_log_file: + expected_result = start_vm_twice_log_into_qemu_log_file + start_vm = no + - record_save_restore_guest_log: + expected_result = record_save_restore_guest_log + start_vm = no + save_vm_path = "/tmp/test1.save" - negative_test: variants: - invalid: expected_result = unbootable stdio_handler = 'invalid' + - invalid_virtlogd_conf: + start_vm = no + expected_result = 'invalid_virtlogd_conf' + max_clients = 'invalid' + variants: + - reload_virtlogd: + action = "reload" + - restart_virtlogd: + action = "restart" diff --git a/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py b/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py index b4eb55b1c20..81ba083f6cf 100644 --- a/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py +++ b/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py @@ -1,4 +1,5 @@ import logging as log +import glob import os import stat import time @@ -12,7 +13,10 @@ from virttest import utils_libvirtd from virttest import utils_package from virttest import virt_vm +from virttest import virsh + from virttest.staging import service +from virttest.utils_test import libvirt from virttest.libvirt_xml.vm_xml import VMXML from virttest.libvirt_xml.devices.console import Console from virttest.libvirt_xml.devices.graphics import Graphics @@ -222,6 +226,321 @@ def configure_spice(vm_name): vm_spice_xml.add_device(graphic) vm_spice_xml.sync() + def enable_virtlogd_specific_config_file(): + """ + Configure virtlogd using specific config file. + + """ + with open(virtlogd_config_file, "w") as fd: + fd.write('VIRTLOGD_ARGS="--config /etc/libvirt/virtlogd-new.conf"') + fd.write('\n') + + with open(virtlogd_config_file_new, "w") as fd: + fd.write('log_level = 2') + fd.write('\n') + fd.write('log_outputs="1:file:/var/log/libvirt/virtlogd-new.log"') + fd.write('\n') + # Modify the selinux context + cmd = "chcon system_u:object_r:virtlogd_etc_t:s0 %s" % virtlogd_config_file_new + process.run(cmd, ignore_status=True, shell=True) + # restart virtlogd + service.Factory.create_service("virtlogd").restart() + check_service_status("virtlogd", service_start=False) + + def check_virtlogd_started_with_config(): + """ + Check if virtlogd is started with --config argument + + """ + cmd = "ps -fC 'virtlogd'" + cmd_result = process.run(cmd, shell=True).stdout_text.strip() + matched_message = "--config %s" % virtlogd_config_file_new + if matched_message not in cmd_result: + test.fail("Check virtlogd is started with config :%s failed in output:%s" + % (matched_message, cmd_result)) + new_virtlogd_log_file = params.get("virtlogd_config_file_alternative_new") + if not os.path.exists(new_virtlogd_log_file): + test.fail("Failed to create new virtlogd log:%s" % new_virtlogd_log_file) + str_to_grep = "virObject" + if not libvirt.check_logfile(str_to_grep, new_virtlogd_log_file): + test.fail("Check message log:%s failed in log file:%s" + % (str_to_grep, new_virtlogd_log_file)) + + def enable_virtlogd_timeout(): + """ + Configure virtlogd using timeout parameter. + + """ + with open(virtlogd_config_file, "w") as fd: + fd.write('VIRTLOGD_ARGS="--timeout=30"') + fd.write('\n') + # restart virtlogd + service.Factory.create_service("virtlogd").restart() + check_service_status("virtlogd", service_start=False) + + def check_virtlogd_started_with_timeout(): + """ + Check if virtlogd is started with timeout=30 + + """ + cmd = "ps -fC 'virtlogd'" + cmd_result = process.run(cmd, shell=True).stdout_text.strip() + matched_message = "--timeout=30" + if matched_message not in cmd_result: + test.fail("Check virtlogd is started with config :%s failed in output:%s" + % (matched_message, cmd_result)) + # nothing to do in 40 seconds to make virtlogd timeout + time.sleep(40) + cmd = "ps aux|grep virtlogd" + if process.run(cmd, shell=True).exit_status == 0: + test.fail("Find unexpected virtlogd") + + def check_virtlogd_failed_invalid_config(): + """ + Check if virtlogd is failed status + + """ + virtlogd_config.max_clients = params.get("max_clients") + cmd = ("systemctl status virtlogd | grep 'Active: active'") + ret = process.run(cmd, ignore_status=True, shell=True, verbose=True) + if ret.exit_status != 0: + test.fail("virtlogd is not in active from log:%s" % ret.stdout_text.strip()) + + action = params.get("action") + process.run("systemctl %s virtlogd" % action, ignore_status=True, shell=True) + time.sleep(4) + cmd = ("systemctl status virtlogd | grep 'Active: failed'") + result = process.run(cmd, ignore_status=True, shell=True, verbose=True) + if result.exit_status != 0: + test.fail("virtlogd is not in failed state from output: %s" % result.stdout_text.strip()) + + def create_crash_vm(): + """ + create one VM which will crash when starting + + """ + # disable huge pages + cmd_hugepage = " sysctl vm.nr_hugepages=0" + process.run(cmd_hugepage, ignore_status=True, shell=True, verbose=True) + VMXML.set_memoryBacking_tag(vm_name) + + def check_record_qenu_crash_log(): + """ + check recorded qemu crash log + """ + # Start VM + try: + vm.start() + except virt_vm.VMStartError as detail: + logging.info("VM failed to start." + "Error: %s" % str(detail)) + crash_information = params.get("crash_information") + if not libvirt.check_logfile(crash_information, guest_log_file): + test.fail("Check expected message log:%s failed in log file:%s" + % (crash_information, guest_log_file)) + + def lsof_qemu_log_file(): + """ + use lsof command to check qemu log file + + :return: lsof command return value + """ + cmd_lsof = "lsof %s" % guest_log_file + lsof_output = process.run(cmd_lsof, ignore_status=True, shell=True, verbose=True).stdout_text.strip() + return lsof_output + + def stop_virtlogd(): + """ + Stop virtlogd service + + """ + # truncate qemu log file in order to avoid making later checking complex + truncate_log_file(guest_log_file, '0') + vm.start() + vm.wait_for_login().close() + lsof_output = lsof_qemu_log_file() + if "virtlogd" not in lsof_output: + test.fail("virtlogd does not open qemu log file:%s" + % guest_log_file) + + def check_stop_virtlogd(): + """ + Check something happen after stop virtlogd service + + """ + virtlogd_service = service.Factory.create_service("virtlogd") + virtlogd_service.stop() + vm.wait_for_login().close() + lsof_output = lsof_qemu_log_file() + if "virtlogd" in lsof_output: + test.fail("guest log still write into qemu log file:%s after virtlogd stop" + % guest_log_file) + vm.destroy() + shut_down_msg = "shutting down, reason=shutdown" + if not libvirt.check_logfile(shut_down_msg, guest_log_file): + test.fail("Check VM destroy message log:%s failed in log file:%s" + % (shut_down_msg, guest_log_file)) + qemu_msg = "qemu-kvm: terminating on signal" + if not libvirt.check_logfile(qemu_msg, guest_log_file, str_in_log=False): + test.fail("Find unexpected:%s failed in log file:%s" + % (qemu_msg, guest_log_file)) + + virtlogd_service.start() + + def check_file_exist(log_file): + """ + check whether specified file exist or not + + :param log_file: specified log file name. + """ + if not os.path.exists(log_file): + test.fail("failed to find qemu log file: %s" % log_file) + + def truncate_log_file(file_path, size_in_unit="2M"): + """ + truncate guest log file to default 2M + + :param file_path: specified file name. + :param size_in_unit: expected size after being truncated. + """ + truncate_2m_cmd = "truncate -s %s %s" % (size_in_unit, file_path) + process.run(truncate_2m_cmd, ignore_status=True, shell=True, verbose=True) + + def enable_default_max_size_max_backups(): + """ + Enable default qemu log file max size and max backups + + """ + def _start_stop_vm(): + """ + start and stop to generate large logs + """ + vm.start() + vm.wait_for_login().close() + vm.destroy() + + if vm.is_alive(): + vm.destroy(gracefully=False) + # clean up log file exclude /var/log/libvirt/qemu/$guest_name.log + file_list = glob.glob('%s/%s.log.*' % (QEMU_LOG_PATH, vm_name)) + for file_name in file_list: + if os.path.exists(file_name): + os.remove(file_name) + # increase log file size to 2M to trigger generating new log file + for i in range(0, 4): + truncate_log_file(guest_log_file) + _start_stop_vm() + # check /var/log/libvirt/qemu/$guest_name.log.1 is generated + if i < 3: + guest_log_file_index = os.path.join(QEMU_LOG_PATH, "%s.log.%s" % (vm_name, i)) + check_file_exist(guest_log_file_index) + + def check_default_max_size_max_backups(): + """ + check default qemu log file max size and max backups + + """ + max_backups = int(params.get("max_backups")) + # three are totally guest log file: max_backups + 1 + log_file_list = glob.glob('%s/%s.log*' % (QEMU_LOG_PATH, vm_name)) + if len(log_file_list) != (max_backups + 1): + test.fail("the total related log file is not expected, and actual are: %s" % log_file_list) + + def enable_recreate_qemu_log(): + """ + Enable create new qemu log file again + + """ + vm.start() + check_file_exist(guest_log_file) + os.remove(guest_log_file) + # trigger qemu log generation + virsh.qemu_monitor_command(name=vm.name, cmd="info block", options='--hmp', + **{'debug': True, 'ignore_status': True}) + if os.path.exists(guest_log_file): + test.fail("guest log file: %s is wrongly recreated" % guest_log_file) + + def check_recreate_qemu_log(): + """ + check default qemu log will be recreated after VM destroy + """ + # guest log file will be recreated once VM is destroyed, and log will be recorded accordingly + virsh.destroy(vm_name) + vm_destroy_msg = "shutting down, reason=destroyed" + if not libvirt.check_logfile(vm_destroy_msg, guest_log_file): + test.fail("Check VM destroy message log:%s failed in log file:%s" + % (vm_destroy_msg, guest_log_file)) + + def check_opened_fd_of_qemu_log_file(): + """ + Check whether qemu log file is opened by virtlogd correctly + + """ + vm.start() + vm.wait_for_login().close() + lsof_start_vm_output = lsof_qemu_log_file() + if "virtlogd" not in lsof_start_vm_output: + test.fail("virtlogd does not open qemu log file after VM start:%s" + % guest_log_file) + + vm.destroy(gracefully=False) + lsof_destroy_vm_output = lsof_qemu_log_file() + if "virtlogd" in lsof_destroy_vm_output: + test.fail("guest log still write into qemu log file:%s after VM stop" + % guest_log_file) + + def check_vm_destroy_log_into_qemu_log_file(): + """ + Check whether vm destroy log is written into qemu log file + + """ + # truncate qemu log file to size 0 in order to avoid making later checking complex + truncate_log_file(guest_log_file, '0') + vm.start() + vm.wait_for_login().close() + virsh.destroy(vm_name) + vm_destroy_msg = ".*qemu-kvm: terminating on signal.*\n.*shutting down, reason=destroyed.*" + if not libvirt.check_logfile(vm_destroy_msg, guest_log_file): + test.fail("Check VM destroy message log:%s failed in log file:%s" + % (vm_destroy_msg, guest_log_file)) + + def check_start_vm_twice_log_into_qemu_log_file(): + """ + Check whether vm start twice is written into qemu log file + + """ + vm.start() + vm.wait_for_login().close() + # truncate qemu log file to size 0 in order to avoid making later checking complex + truncate_log_file(guest_log_file, '0') + virsh.destroy(vm_name) + vm.start() + vm.wait_for_login().close() + vm_destroy_start_msg = ".*qemu-kvm: terminating on signal.*\n.*" + \ + "shutting down, reason=destroyed.*\n.*name guest=%s.*" % vm_name + if not libvirt.check_logfile(vm_destroy_start_msg, guest_log_file): + test.fail("Check VM destroy and start message log:%s failed in log file:%s" + % (vm_destroy_start_msg, guest_log_file)) + + def check_record_save_restore_guest_log(): + """ + Check whether vm save and restore is written into qemu log file + + """ + vm.start() + vm.wait_for_login().close() + # truncate qemu log file to size 0 in order to avoid making later checking complex + truncate_log_file(guest_log_file, '0') + save_path = params.get("save_vm_path") + virsh.save(vm_name, save_path) + virsh.restore(save_path) + vm.wait_for_login().close() + vm_save_restore_msg = ".*qemu-kvm: terminating on signal.*\n.*" + \ + "shutting down, reason=saved.*\n.*name guest=%s.*" % vm_name + if not libvirt.check_logfile(vm_save_restore_msg, guest_log_file): + test.fail("Check VM save and restore message log:%s failed in log file:%s" + % (vm_save_restore_msg, guest_log_file)) + vm_name = params.get("main_vm", "avocado-vt-vm1") expected_result = params.get("expected_result", "virtlogd_disabled") stdio_handler = params.get("stdio_handler", "not_set") @@ -245,6 +564,7 @@ def configure_spice(vm_name): config = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() + virtlogd_config = utils_config.VirtLogdConfig() try: if stdio_handler != 'not_set': config['stdio_handler'] = "'%s'" % stdio_handler @@ -266,13 +586,13 @@ def configure_spice(vm_name): if not start_vm: if reload_virtlogd: reload_and_check_virtlogd() - if expected_result == 'virtlogd_restart': + elif expected_result == 'virtlogd_restart': # check virtlogd status virtlogd_pid = check_service_status("virtlogd", service_start=True) logging.info("virtlogd PID: %s", virtlogd_pid) # restart virtlogd - ret = process.run("systemctl restart virtlogd", ignore_status=True, shell=True) - if ret.exit_status: + ret = service.Factory.create_service("virtlogd").restart() + if ret is False: test.fail("failed to restart virtlogd.") # check virtlogd status new_virtlogd_pid = check_service_status("virtlogd", service_start=False) @@ -283,7 +603,7 @@ def configure_spice(vm_name): ret = process.run(cmd, ignore_status=True, shell=True) if ret.exit_status: test.fail("virtlogd don't exist.") - if expected_result == 'virtlogd_disabled': + elif expected_result == 'virtlogd_disabled': # check virtlogd status virtlogd_pid = check_service_status("virtlogd", service_start=True) logging.info("virtlogd PID: %s", virtlogd_pid) @@ -297,6 +617,41 @@ def configure_spice(vm_name): ret = process.run(cmd, ignore_status=True, shell=True) if not ret.exit_status: test.fail("virtlogd still exist.") + elif expected_result in ['virtlogd_specific_config_file_enable', 'specific_timeout']: + virtlogd_config_file = params.get("virtlogd_config_file") + virtlogd_config_bak_file = params.get("virtlogd_config_bak_file") + if os.path.exists(virtlogd_config_file): + # backup config file + os.rename(virtlogd_config_file, virtlogd_config_bak_file) + virtlogd_config_file_new = params.get("virtlogd_config_file_new") + elif expected_result == 'virtlogd_specific_config_file_enable': + enable_virtlogd_specific_config_file() + check_virtlogd_started_with_config() + elif expected_result == 'specific_timeout': + enable_virtlogd_timeout() + check_virtlogd_started_with_timeout() + elif expected_result == "invalid_virtlogd_conf": + check_virtlogd_failed_invalid_config() + elif expected_result == "record_qenu_crash_log": + create_crash_vm() + check_record_qenu_crash_log() + elif expected_result == "stop_virtlogd": + stop_virtlogd() + check_stop_virtlogd() + elif expected_result == "default_max_size_max_backups": + enable_default_max_size_max_backups() + check_default_max_size_max_backups() + elif expected_result == "recreate_qemu_log": + enable_recreate_qemu_log() + check_recreate_qemu_log() + elif expected_result == "opened_fd_of_qemu_log_file": + check_opened_fd_of_qemu_log_file() + elif expected_result == "vm_destroy_log_into_qemu_log_file": + check_vm_destroy_log_into_qemu_log_file() + elif expected_result == "start_vm_twice_log_into_qemu_log_file": + check_start_vm_twice_log_into_qemu_log_file() + elif expected_result == "record_save_restore_guest_log": + check_record_save_restore_guest_log() else: # Stop all VMs if VMs are already started. for tmp_vm in env.get_all_vms(): @@ -425,3 +780,15 @@ def configure_spice(vm_name): config.restore() libvirtd.restart() vm_xml_backup.sync() + if expected_result in ['virtlogd_specific_config_file_enable', 'specific_timeout']: + if os.path.exists(virtlogd_config_file): + os.remove(virtlogd_config_file) + if os.path.exists(virtlogd_config_file_new): + os.remove(virtlogd_config_file_new) + if virtlogd_config_bak_file: + if os.path.exists(virtlogd_config_file): + os.rename(virtlogd_config_bak_file, virtlogd_config_file) + service.Factory.create_service("virtlogd").restart() + if expected_result == "invalid_virtlogd_conf": + virtlogd_config.restore() + service.Factory.create_service("virtlogd").restart() From 0e455faa86328a852fbee3d1af66c0a0be3c866e Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Tue, 12 Dec 2023 11:14:27 +0800 Subject: [PATCH 0067/1055] v2v:modify esx65/67 related testing for v2v-options Signed-off-by: vwu-vera --- v2v/tests/cfg/v2v_options.cfg | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/v2v/tests/cfg/v2v_options.cfg b/v2v/tests/cfg/v2v_options.cfg index c8d4b61e78a..11f6ae2b91f 100644 --- a/v2v/tests/cfg/v2v_options.cfg +++ b/v2v/tests/cfg/v2v_options.cfg @@ -111,11 +111,6 @@ main_vm = "VM_NAME_ESX_DEFAULT_V2V_EXAMPLE" checkpoint = 'tail_log' msg_content = 'cannot list vcpu pinning for an inactive domain' - - esx_67: - only source_esx.esx_67 - main_vm = "VM_NAME_ESX67_DEFAULT_V2V_EXAMPLE" - variants: - - default: - libvirtxml: only source_none input_mode = "libvirtxml" @@ -243,7 +238,7 @@ - vmx_ssh: only input_mode.none only output_mode.libvirt - esx_ip = ESX_65_HOSTNAME_V2V_EXAMPLE + esx_ip = ESX_70_HOSTNAME_V2V_EXAMPLE esx_host_user = "root" esx_host_passwd = RHV_NODE_PASSWORD checkpoint = vmx_ssh @@ -282,7 +277,7 @@ in_man = 'colours-option' - compress: only output_mode.libvirt - only input_mode.libvirt.esx.esx_67 + only input_mode.libvirt.esx.esx_70 checkpoint = compress new_vm_name = ${main_vm}_compress v2v_options = -of qcow2 --compressed -on ${new_vm_name} @@ -298,7 +293,7 @@ - br: checkpoint += _bridge - rhev_snapshot_id: - only input_mode.libvirt.esx.esx_67 + only input_mode.libvirt.esx.esx_70 only output_mode.rhev - format_convert: only input_mode.libvirtxml @@ -338,7 +333,7 @@ msg_content = "Remove 1 Package" - print_estimate: only output_mode.none - only input_mode.libvirt.esx.esx_67 + only input_mode.libvirt.esx.esx_70 v2v_options = '--print-estimate' version_required = "[libguestfs-1.40.1-1,)" variants: From ef3a7e9e937c82974dd9cfb89b11a9f878c9ef85 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 5 Dec 2023 13:09:50 -0500 Subject: [PATCH 0068/1055] virtual_disks_multivms: fix disk discovery The tests used the disk target as identifier for the disk inside of the VM. However, the target is not guaranteed to show up in the guest as-is, especially given that the /dev/XdY paths are not persistent and can change between boots. Use instead a function that identifies a new disk inside of a VM as the one disk that has no root mount on itself, its partitions or volumes. Finally, the `delete_scsi_disk` doesn't return any value so it was always looping for the full timeout. Wrap it into a function that confirms if both the module and device have been removed. Signed-off-by: Sebastian Mitterle --- .../virtual_disks/virtual_disks_multivms.py | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_multivms.py b/libvirt/tests/src/virtual_disks/virtual_disks_multivms.py index aea740128a6..2dad7283353 100644 --- a/libvirt/tests/src/virtual_disks/virtual_disks_multivms.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_multivms.py @@ -1,6 +1,7 @@ import os import logging as log import aexpect +import time from avocado.utils import process @@ -11,6 +12,7 @@ from virttest import remote from virttest import utils_disk from virttest import utils_misc +from virttest.utils_libvirt.libvirt_disk import get_non_root_disk_name from virttest.utils_test import libvirt from virttest.libvirt_xml import vm_xml from virttest.libvirt_xml.devices.disk import Disk @@ -36,6 +38,19 @@ def run(test, params, env): 6.Confirm the test result. """ + def _delete_scsi_disk(): + """ Helper function for wait_for in finally """ + libvirt.delete_scsi_disk() + cmd = "lsscsi|grep scsi_debug" + s1, _ = utils_misc.cmd_status_output(cmd, + shell=True, + ignore_status=False) + cmd = "lsmod|grep scsi_debug" + s2, _ = utils_misc.cmd_status_output(cmd, + shell=True, + ignore_status=False) + return s1 + s2 == 2 + def set_vm_controller_xml(vmxml): """ Set VM scsi controller xml. @@ -239,7 +254,8 @@ def get_vm_disk_xml(dev_type, dev_name, **options): test.fail('Failed to hotplug disk device') elif 0 == result and not vms_list[i]['status']: test.fail('Hotplug disk device unexpectedly.') - + time.sleep(5) + added_disk, _ = get_non_root_disk_name(session) # Check disk error_policy option in VMs. if test_error_policy: error_policy = vms_list[i]['disk'].driver["error_policy"] @@ -248,7 +264,7 @@ def get_vm_disk_xml(dev_type, dev_name, **options): if error_policy == "enospace": cmd = ("mount /dev/%s /mnt && dd if=/dev/zero of=/mnt/test" " bs=1M count=2000 2>&1 | grep 'No space left'" - % disk_target) + % added_disk) s, o = session.cmd_status_output(cmd) logging.debug("error_policy in vm0 exit %s; output: %s", s, o) if 0 != s: @@ -258,7 +274,7 @@ def get_vm_disk_xml(dev_type, dev_name, **options): break if session.cmd_status("fdisk -l /dev/%s && mount /dev/%s /mnt; ls /mnt" - % (disk_target, disk_target)): + % (added_disk, added_disk)): session.close() test.fail("Test error_policy: " "failed to mount disk") @@ -266,7 +282,7 @@ def get_vm_disk_xml(dev_type, dev_name, **options): try: session0 = vms_list[0]['vm'].wait_for_login(timeout=10) cmd = ("fdisk -l /dev/%s && mkfs.ext3 -F /dev/%s " - % (disk_target, disk_target)) + % (added_disk, added_disk)) s, o = session.cmd_status_output(cmd) logging.debug("error_policy in vm1 exit %s; output: %s", s, o) session.close() @@ -312,9 +328,10 @@ def _check_error(): test_str = "teststring" # Try to write on vm0. session0 = vms_list[0]['vm'].wait_for_login(timeout=10) + added_disk0, _ = get_non_root_disk_name(session0) cmd = ("fdisk -l /dev/%s && mount /dev/%s /mnt && echo '%s' " "> /mnt/test && umount /mnt" - % (disk_target, disk_target, test_str)) + % (added_disk0, added_disk0, test_str)) s, o = session0.cmd_status_output(cmd) logging.debug("session in vm0 exit %s; output: %s", s, o) if s: @@ -323,7 +340,7 @@ def _check_error(): # Try to read on vm1. cmd = ("fdisk -l /dev/%s && mount /dev/%s /mnt && grep %s" " /mnt/test && umount /mnt" - % (disk_target, disk_target, test_str)) + % (added_disk, added_disk, test_str)) s, o = session.cmd_status_output(cmd) logging.debug("session in vm1 exit %s; output: %s", s, o) if s: @@ -377,7 +394,7 @@ def _check_error(): for img in disks: if 'format' in img: if img["format"] == "scsi": - utils_misc.wait_for(libvirt.delete_scsi_disk, + utils_misc.wait_for(_delete_scsi_disk, 120, ignore_errors=True) elif img["format"] == "iscsi": libvirt.setup_or_cleanup_iscsi(is_setup=False) From 936d490afc01b5dd93d3ed038e40c6ba0fca8f41 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Wed, 13 Dec 2023 13:14:39 +0800 Subject: [PATCH 0069/1055] v2v:modify esx65/67 related testing for convert-from-file Signed-off-by: vwu-vera --- v2v/tests/cfg/convert_from_file.cfg | 36 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/v2v/tests/cfg/convert_from_file.cfg b/v2v/tests/cfg/convert_from_file.cfg index 84d1586e4ea..d6b2b3de58c 100644 --- a/v2v/tests/cfg/convert_from_file.cfg +++ b/v2v/tests/cfg/convert_from_file.cfg @@ -186,16 +186,16 @@ variants: - latest8: v2v_debug = force_on - only esx_67 + only esx_70 main_vm = 'VM_NAME_RHEL8_V2V_EXAMPLE' msg_content = 'scp -T' expect_msg = yes - latest7: - only esx_67 + only esx_70 main_vm = 'VM_NAME_RHEL7_V2V_EXAMPLE' - latest6: enable_legacy_policy = yes - only esx_67 + only esx_70 main_vm = 'VM_NAME_RHEL6_V2V_EXAMPLE' - regular_user_sudo: checkpoint = 'regular_user_sudo' @@ -203,13 +203,13 @@ env_settings = 'eval `ssh-agent`;ssh-add;sudo -E LIBGUESTFS_BACKEND=direct' unprivileged_user = 'USER_UNPRIVILEGED_V2V_EXAMPLE' #os_directory = '/home/${unprivileged_user}' - only esx_67 + only esx_70 - nvme_disk: - only esx_67 + only esx_70 #add required version due to bug2070530 version_required = "[virt-v2v-2.0.7-1.el9,)" main_vm = 'VM_NAME_NVME_RHEL8_V2V_EXAMPLE' - datastore = esx6.7-function + datastore = esx7.0-function #Skip pre-check by bz#2068992. Will modify once the bug fixed. skip_virsh_pre_conn = yes - percent_encode: @@ -220,7 +220,7 @@ datastore = esx7.0-function - vmx_default: # Default - vmx_nfs_src = NFS_ESX67_VMX_V2V_EXAMPLE + vmx_nfs_src = NFS_ESX70_VMX_V2V_EXAMPLE # Do not skip vm checking by default skip_vm_check = no # By default, v2v will try to connect to source hypervisor @@ -233,45 +233,45 @@ skip_virsh_pre_conn = no variants: - win2012r2: - only esx_60 + only esx_70 only windows os_version = 'win2012r2' has_genid = 'no' main_vm = 'VM_NAME_GENID_WIN2012R2_V2V_EXAMPLE' - vmx_nfs_src = NFS_ESX60_VMX_V2V_EXAMPLE + vmx_nfs_src = NFS_ESX70_VMX_V2V_EXAMPLE # genid only supports libvirt, local, qemu only output_mode.libvirt - win2019: - only esx_67 + only esx_70 only windows os_version = 'win2019' has_genid = 'yes' main_vm = 'VM_NAME_GENID_WIN2019_V2V_EXAMPLE' - vmx_nfs_src = NFS_ESX67_VMX_V2V_EXAMPLE + vmx_nfs_src = NFS_ESX70_VMX_V2V_EXAMPLE # genid only supports libvirt, local, qemu only output_mode.libvirt - win10: - only esx_67 + only esx_70 only windows os_version = 'win10' has_genid = 'yes' main_vm = 'VM_NAME_GENID_WIN10_V2V_EXAMPLE' - vmx_nfs_src = NFS_ESX67_VMX_V2V_EXAMPLE + vmx_nfs_src = NFS_ESX70_VMX_V2V_EXAMPLE # genid only supports libvirt, local, qemu only output_mode.libvirt - latest8: - only esx_67 + only esx_70 main_vm = 'VM_NAME_RHEL8_V2V_EXAMPLE' - latest7: - only esx_67 + only esx_70 main_vm = 'VM_NAME_RHEL7_V2V_EXAMPLE' - latest6: enable_legacy_policy = yes - only esx_67 + only esx_70 main_vm = 'VM_NAME_RHEL6_V2V_EXAMPLE' - cpu_topology: - only esx_67 - vmx_nfs_src = NFS_ESX67_VMX_V2V_EXAMPLE + only esx_70 + vmx_nfs_src = NFS_ESX70_FUNC_VMX_V2V_EXAMPLE main_vm = 'VM_NAME_CPU_TOPOLOGY_V2V_EXAMPLE' v2v_debug = force_on checkpoint = 'cpu_topology' From 04d633c37a85212409180f25e02e796496b7dc08 Mon Sep 17 00:00:00 2001 From: Yan Fu Date: Wed, 13 Dec 2023 15:40:53 +0800 Subject: [PATCH 0070/1055] Modify to start virtqemud for the modular daemon mode Signed-off-by: Yan Fu --- libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py b/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py index b4eb55b1c20..0fa1de4832c 100644 --- a/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py +++ b/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py @@ -11,6 +11,7 @@ from virttest import utils_config from virttest import utils_libvirtd from virttest import utils_package +from virttest import utils_split_daemons from virttest import virt_vm from virttest.staging import service from virttest.libvirt_xml.vm_xml import VMXML @@ -251,7 +252,8 @@ def configure_spice(vm_name): if restart_libvirtd or stop_libvirtd: virtlogd_pid = check_service_status("virtlogd", service_start=True) logging.info("virtlogd pid: %s", virtlogd_pid) - check_service_status("libvirtd", service_start=True) + service_name = "virtqemud" if utils_split_daemons.is_modular_daemon else "libvirtd" + check_service_status(service_name, service_start=True) # Restart libvirtd to make change valid. if not libvirtd.restart(): From 380433faf788d5e22bd7234f66420cb3da767e45 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Wed, 13 Dec 2023 15:54:57 +0800 Subject: [PATCH 0071/1055] virsh_cpu_compare_xml: add case change cpu vendor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test scenario: Test 'virsh cpu-compare' with capabilities XML by obtaining capabilities XML from ‘virsh capabilities’ on host and updating with with different vendor Signed-off-by: Dan Zheng --- .../domain => cpu}/virsh_cpu_compare_xml.cfg | 6 +++ .../domain => cpu}/virsh_cpu_compare_xml.py | 46 ++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) rename libvirt/tests/cfg/{virsh_cmd/domain => cpu}/virsh_cpu_compare_xml.cfg (88%) rename libvirt/tests/src/{virsh_cmd/domain => cpu}/virsh_cpu_compare_xml.py (74%) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_cpu_compare_xml.cfg b/libvirt/tests/cfg/cpu/virsh_cpu_compare_xml.cfg similarity index 88% rename from libvirt/tests/cfg/virsh_cmd/domain/virsh_cpu_compare_xml.cfg rename to libvirt/tests/cfg/cpu/virsh_cpu_compare_xml.cfg index 7bcc41ee5d6..a83cce44149 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_cpu_compare_xml.cfg +++ b/libvirt/tests/cfg/cpu/virsh_cpu_compare_xml.cfg @@ -8,6 +8,7 @@ compare_file_type = "domxml" variants: - custom_mode: + no aarch64 cpu_mode = "custom" status_error = "yes" msg_pattern = "incompatible" @@ -19,6 +20,11 @@ variants: - action_none: msg_pattern = "identical" + - change_vendor: + no s390_virtio, ppc64le + cpu_compare_mode = "modify" + msg_pattern = "incompatible" + status_error = "yes" - delete_features: cpu_compare_mode = "delete" status_error = "no" diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_cpu_compare_xml.py b/libvirt/tests/src/cpu/virsh_cpu_compare_xml.py similarity index 74% rename from libvirt/tests/src/virsh_cmd/domain/virsh_cpu_compare_xml.py rename to libvirt/tests/src/cpu/virsh_cpu_compare_xml.py index 50a60077c2b..ce9501d5212 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_cpu_compare_xml.py +++ b/libvirt/tests/src/cpu/virsh_cpu_compare_xml.py @@ -1,6 +1,8 @@ import os import logging as log +from avocado.utils import cpu + from virttest import virsh from virttest import libvirt_version from virttest.libvirt_xml import vm_xml @@ -66,11 +68,48 @@ def get_domcapa_xml(extract=False): return domcapa_xml -def get_capa_xml(operate='', extract=False): +def get_different_cpu_vendor(test, current_cpu_vendor): + """ + Get a different cpu vendor from current host cpu vendor + + :param test: test object + :param current_cpu_vendor: str, current host cpu vendor + :return: str, the selected cpu vendor + """ + arch_cpu_vendor_mapping = {'x86_64': ['GenuineIntel', 'AuthenticAMD'], + 'aarch64': ['Ampere(R)', 'Ampere(TM)', + 'AppliedMicro', 'ARM', 'NVIDIA', + 'FUJITSU', 'Cavium Inc.', + 'Marvell', 'Qualcomm', + 'CN8890-2000BG2601-AAP-PR-Y-G', + 'CN8880-1800BG2601-CP-Y-G']} + + host_arch = cpu.get_arch() + if host_arch.lower() not in arch_cpu_vendor_mapping: + test.error("The host arch '%s' is not supported for this case" % host_arch) + cpu_vendors = arch_cpu_vendor_mapping[host_arch] + new_vendor = '' + for vendor_index in range(0, len(cpu_vendors)): + if cpu_vendors[vendor_index].count(current_cpu_vendor): + if vendor_index == len(cpu_vendors) - 1: + new_vendor = cpu_vendors[0] + else: + new_vendor = cpu_vendors[vendor_index + 1] + break + if new_vendor: + test.log.debug("Found a different cpu vendor '%s'", new_vendor) + return new_vendor + else: + test.error("Can not find a different one from " + "current cpu vendor '%s'" % current_cpu_vendor) + + +def get_capa_xml(test, operate='', extract=False): """ Get full capabilities xml or the cpu definition from capabilities xml + :param test: test object :param operate: Operation mode, decide file's detail :param extract: Setting True means to extract cpu definition from capabilities xml @@ -79,6 +118,9 @@ def get_capa_xml(operate='', extract=False): capa_xml = capability_xml.CapabilityXML() if operate == 'delete': capa_xml.remove_feature(num=-1) + elif operate == 'modify': + new_vendor = get_different_cpu_vendor(test, capa_xml.vendor) + capa_xml.vendor = new_vendor if extract: capa_xml.xmltreefile = capa_xml.xmltreefile.reroot('/host/cpu') return capa_xml @@ -138,7 +180,7 @@ def run(test, params, env): cpu_compare_xml = get_domcapa_xml(is_extracted) if file_type == "capa_xml": - cpu_compare_xml = get_capa_xml(cpu_compare_mode, is_extracted) + cpu_compare_xml = get_capa_xml(test, cpu_compare_mode, is_extracted) if cpu_compare_mode == "invalid_test": cpu_compare_xml = get_invalid_xml(cpu_compare_xml) From ba2b3ed4d7319006eed80ebf451bfa311390de1a Mon Sep 17 00:00:00 2001 From: Yan Fu Date: Wed, 13 Dec 2023 16:22:52 +0800 Subject: [PATCH 0072/1055] Use 'systemctl list-units' to check daemons' status Signed-off-by: Yan Fu --- libvirt/tests/src/daemon/check_daemon_after_remove_pkgs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/daemon/check_daemon_after_remove_pkgs.py b/libvirt/tests/src/daemon/check_daemon_after_remove_pkgs.py index b8f3f9eeaa7..29bdefcd522 100644 --- a/libvirt/tests/src/daemon/check_daemon_after_remove_pkgs.py +++ b/libvirt/tests/src/daemon/check_daemon_after_remove_pkgs.py @@ -46,7 +46,7 @@ def run(test, params, env): test.error("Failed to remove libvirt packages on guest") for daemon in daemons: - _, out = session.cmd_status_output("systemctl -a| grep %s" % daemon) + _, out = session.cmd_status_output("systemctl list-units| grep %s" % daemon) LOGGER.debug(out) if daemon in out and "not-found" not in out: test.fail("%s still exists after removing libvirt pkgs" % daemon) From d4ac6607f4462667c606e12a921d539b0e96c316 Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 28 Nov 2023 14:21:23 +0800 Subject: [PATCH 0073/1055] migration: Add case about migrate-disk XXX-297901 - VM live migration with copy storage - specify which disks to migrate(-migrate-disks) Signed-off-by: lcheng --- .../migrate_disks.cfg | 75 +++++++ .../migrate_disks.py | 202 ++++++++++++++++++ 2 files changed, 277 insertions(+) create mode 100644 libvirt/tests/cfg/migration_with_copy_storage/migrate_disks.cfg create mode 100644 libvirt/tests/src/migration_with_copy_storage/migrate_disks.py diff --git a/libvirt/tests/cfg/migration_with_copy_storage/migrate_disks.cfg b/libvirt/tests/cfg/migration_with_copy_storage/migrate_disks.cfg new file mode 100644 index 00000000000..64b3bd5aa54 --- /dev/null +++ b/libvirt/tests/cfg/migration_with_copy_storage/migrate_disks.cfg @@ -0,0 +1,75 @@ +- migration_with_copy_storage.migrate_disks: + type = migrate_disks + migration_setup = 'yes' + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = "" + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = "qemu:///system" + image_convert = "no" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + start_vm = "no" + disk2_name = "mig_disk2.qcow2" + disk2_dict = {"device": "disk", "type_name":"file", "driver": {"name": "qemu", "type":"qcow2"}, "target":{"dev": "vdb", "bus": "virtio"}} + variants: + - copy_storage_all: + copy_storage_option = "--copy-storage-all" + - copy_storage_inc: + copy_storage_option = "--copy-storage-inc" + variants: + - p2p: + virsh_migrate_options = "--live --p2p --verbose" + - non_p2p: + virsh_migrate_options = "--live --verbose" + variants disks: + - disk1: + setup_nfs = "no" + nfs_mount_dir = + virsh_migrate_extra = "--migrate-disks vda" + status_error = "yes" + err_msg = "Unsafe migration: Migration without shared storage is unsafe" + - disk1_disk2: + setup_nfs = "no" + nfs_mount_dir = + virsh_migrate_extra = "--migrate-disks vda,vdb" + status_error = "no" + - disk1_disk2_disk3: + virsh_migrate_extra = "--migrate-disks vda,vdb,vdc" + storage_type = 'nfs' + setup_local_nfs = 'yes' + status_error = "no" + disk3_name = "mig_disk3.raw" + disk3_dict = {"device": "disk", "type_name":"file", "driver": {"name": "qemu", "type":"raw"}, "target":{"dev": "vdc", "bus": "virtio"}, "share": True} + - disk1_disk2_disk4: + virsh_migrate_extra = "--migrate-disks vda,vdb,vdd" + storage_type = 'nfs' + setup_local_nfs = 'yes' + status_error = "yes" + err_msg = "Operation not supported: Cannot migrate empty or read-only disk vdd" + disk4_name = "mig_disk4.raw" + disk4_dict = {"device": "disk", "type_name":"file", "driver": {"name": "qemu", "type":"raw"}, "target":{"dev": "vdd", "bus": "virtio"}, "readonly": True} + - disk1_disk2_disk_nonexist: + setup_nfs = "no" + nfs_mount_dir = + virsh_migrate_extra = "--migrate-disks vda,vdb,aaa" + status_error = "yes" + err_msg = "invalid argument: disk target aaa not found" + - disk1_disk2_disk5: + setup_nfs = "no" + nfs_mount_dir = + virsh_migrate_extra = "--migrate-disks vda,vdb,sda" + status_error = "yes" + err_msg = "Operation not supported: Cannot migrate empty or read-only disk sda" + disk5_dict = {"device": "cdrom", "type_name":"file", "driver": {"name": "qemu", "type":"raw"}, "target":{"dev": "sda", "bus": "sata"}, "readonly": True} diff --git a/libvirt/tests/src/migration_with_copy_storage/migrate_disks.py b/libvirt/tests/src/migration_with_copy_storage/migrate_disks.py new file mode 100644 index 00000000000..b9593fd43e8 --- /dev/null +++ b/libvirt/tests/src/migration_with_copy_storage/migrate_disks.py @@ -0,0 +1,202 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: Liping Cheng +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +import os + +from virttest import data_dir +from virttest import remote +from virttest import utils_misc + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_disk +from virttest.utils_libvirt import libvirt_vmxml + +from provider.migration import base_steps +from provider.migration import migration_base + + +def update_vm_with_additional_disk(disk_dict, disk_format, vm_name, disk_path=None): + """ + Update vm with additional disk + + :param disk_dict: disk parameter + :param disk_format: disk format + :param vm_name: vm name + :param disk_path: disk path + """ + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + if disk_path: + disk_dict.update({"source": {"attrs": {"file": "%s" % disk_path}}}) + if os.path.exists(disk_path): + os.remove(disk_path) + libvirt_disk.create_disk("file", disk_format=disk_format, path=disk_path) + vmxml.add_device(libvirt_vmxml.create_vm_device_by_type("disk", disk_dict)) + vmxml.sync() + + +def prepare_disk_local(blk_source, vm_name): + """ + Prepare disk on local host + + :param blk_source: first disk path + :param vm_name: vm name + """ + default_image_path = os.path.join(data_dir.get_data_dir(), 'images') + disk_dict = {'source': {'attrs': {'file': os.path.join(default_image_path, + os.path.basename(blk_source))}}} + libvirt_vmxml.modify_vm_device( + vm_xml.VMXML.new_from_inactive_dumpxml(vm_name), + 'disk', disk_dict) + + +def prepare_disk_remote(params, blk_source): + """ + Prepare disk on remote host + + :param params: dictionary with the test parameter + :param blk_source: first disk path + """ + server_ip = params.get("server_ip") + server_user = params.get("server_user") + server_pwd = params.get("server_pwd") + + remote_session = remote.remote_login("ssh", server_ip, "22", + server_user, server_pwd, + r'[$#%]') + + image_info = utils_misc.get_image_info(blk_source) + disk_size = image_info.get("vsize") + disk_format = image_info.get("format") + utils_misc.make_dirs(os.path.dirname(blk_source), remote_session) + libvirt_disk.create_disk("file", path=blk_source, + size=disk_size, disk_format=disk_format, + session=remote_session) + remote_session.close() + + +def prepare_disks(params, blk_source, vm_name): + """ + Prepare disk on local and remote host + + :param params: dictionary with the test parameter + :param blk_source: first disk path + :param vm_name: vm name + """ + disk2_dict = eval(params.get("disk2_dict")) + disk2_name = params.get("disk2_name") + disk_format = params.get("disk_format", "qcow2") + + disk2_path = os.path.join(os.path.dirname(blk_source), disk2_name) + update_vm_with_additional_disk(disk2_dict, disk_format, vm_name, disk2_path) + + prepare_disk_remote(params, blk_source) + prepare_disk_remote(params, disk2_path) + + +def run(test, params, env): + """ + To verify that libvirt can specifies which disks to migrate during + migration. + + :param test: test object + :param params: dictionary with the test parameters + :param env: dictionary with test environment. + """ + def setup_common(): + """ + Common setup steps + + """ + test.log.info("Common setup steps.") + migration_obj.setup_connection() + prepare_disks(params, blk_source, vm_name) + vm.start() + vm.wait_for_login().close() + + def setup_disk1_disk2_disk3(): + """ + Setup steps for disk1_disk2_disk3 case + + """ + disk3_dict = eval(params.get("disk3_dict")) + disk3_name = params.get("disk3_name") + nfs_mount_dir = params.get("nfs_mount_dir") + migrate_desturi_port = params.get("migrate_desturi_port") + migrate_desturi_type = params.get("migrate_desturi_type", "tcp") + + migration_obj.conn_list.append(migration_base.setup_conn_obj(migrate_desturi_type, params, test)) + migration_obj.remote_add_or_remove_port(migrate_desturi_port) + + test.log.info("Setup steps for disk1_disk2_disk3 case.") + prepare_disk_local(blk_source, vm_name) + prepare_disks(params, blk_source, vm_name) + + disk3_path = os.path.join(nfs_mount_dir, disk3_name) + update_vm_with_additional_disk(disk3_dict, disk_format, vm_name, disk3_path) + + vm.start() + vm.wait_for_login().close() + + def setup_disk1_disk2_disk4(): + """ + Setup steps for disk1_disk2_disk4 case + + """ + disk4_dict = eval(params.get("disk4_dict")) + disk4_name = params.get("disk4_name") + nfs_mount_dir = params.get("nfs_mount_dir") + migrate_desturi_port = params.get("migrate_desturi_port") + migrate_desturi_type = params.get("migrate_desturi_type", "tcp") + + migration_obj.conn_list.append(migration_base.setup_conn_obj(migrate_desturi_type, params, test)) + migration_obj.remote_add_or_remove_port(migrate_desturi_port) + + test.log.info("Setup steps for disk1_disk2_disk4 case.") + prepare_disk_local(blk_source, vm_name) + prepare_disks(params, blk_source, vm_name) + + disk4_path = os.path.join(nfs_mount_dir, disk4_name) + update_vm_with_additional_disk(disk4_dict, disk_format, vm_name, disk4_path) + + vm.start() + vm.wait_for_login().close() + + def setup_disk1_disk2_disk5(): + """ + Setup steps for disk1_disk2_disk5 case + + """ + disk5_dict = eval(params.get("disk5_dict")) + + test.log.info("Setup steps for disk1_disk2_disk5 case.") + migration_obj.setup_connection() + prepare_disks(params, blk_source, vm_name) + update_vm_with_additional_disk(disk5_dict, disk_format, vm_name) + + vm.start() + vm.wait_for_login().close() + + disks = params.get("disks") + vm_name = params.get("migrate_main_vm") + disk_format = params.get("disk_format", "qcow2") + + vm = env.get_vm(vm_name) + blk_source = vm.get_first_disk_devices()['source'] + migration_obj = base_steps.MigrationBase(test, vm, params) + setup_test = eval("setup_%s" % disks) if "setup_%s" % disks in \ + locals() else setup_common + + try: + setup_test() + migration_obj.run_migration() + migration_obj.verify_default() + finally: + migration_obj.cleanup_connection() + base_steps.cleanup_disks_remote(params, vm) From b5637b04496e78a7b54e066d60fd63f3aa5c7d8c Mon Sep 17 00:00:00 2001 From: lcheng Date: Thu, 16 Nov 2023 11:50:48 +0800 Subject: [PATCH 0074/1055] migration: Add case about pre-create target image XXX-297908 - VM live migration with copy storage - don't pre-create target image manually Signed-off-by: lcheng --- .../precreate_none_target_disk.cfg | 49 +++++++ .../precreate_none_target_disk.py | 132 ++++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 libvirt/tests/cfg/migration_with_copy_storage/precreate_none_target_disk.cfg create mode 100644 libvirt/tests/src/migration_with_copy_storage/precreate_none_target_disk.py diff --git a/libvirt/tests/cfg/migration_with_copy_storage/precreate_none_target_disk.cfg b/libvirt/tests/cfg/migration_with_copy_storage/precreate_none_target_disk.cfg new file mode 100644 index 00000000000..80e11cab698 --- /dev/null +++ b/libvirt/tests/cfg/migration_with_copy_storage/precreate_none_target_disk.cfg @@ -0,0 +1,49 @@ +- migration_with_copy_storage.precreate_none_target_disk: + type = precreate_none_target_disk + migration_setup = 'yes' + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = "" + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = "qemu:///system" + image_convert = "no" + status_error = "no" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + start_vm = "no" + setup_nfs = "no" + nfs_mount_dir = + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + target_pool_name = "no_precreate_target_disk_pool" + target_pool_target = "/var/lib/libvirt/migrate/" + target_pool_type = "dir" + disk_source_name = "/var/lib/libvirt/migrate/no_precreate_target_disk.img" + simple_disk_check_after_mig = "yes" + variants: + - p2p: + virsh_migrate_options = "--live --p2p --verbose" + - non_p2p: + virsh_migrate_options = "--live --verbose" + variants: + - raw_format: + disk_format = "raw" + - qcow2_format: + disk_format = "qcow2" + variants: + - copy_storage_all: + status_error = "no" + copy_storage_option = "--copy-storage-all" + - copy_storage_inc: + status_error = "yes" + err_msg = "Operation not supported: pre-creation of storage targets for incremental storage migration is not supported" + copy_storage_option = "--copy-storage-inc" diff --git a/libvirt/tests/src/migration_with_copy_storage/precreate_none_target_disk.py b/libvirt/tests/src/migration_with_copy_storage/precreate_none_target_disk.py new file mode 100644 index 00000000000..406c63162c2 --- /dev/null +++ b/libvirt/tests/src/migration_with_copy_storage/precreate_none_target_disk.py @@ -0,0 +1,132 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: Liping Cheng +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +import re + +from avocado.utils import process + +from virttest import remote +from virttest import virsh + +from virttest.utils_test import libvirt + +from provider.migration import base_steps +from provider.migration import migration_base + +src_image_info = None + + +def check_image_info(params, test): + """ + Check image info + + :param params: Dictionary with the test parameters + :param test: test object + """ + disk_source_name = params.get("disk_source_name") + disk_format = params.get("disk_format") + + cmd = "qemu-img info %s -U" % disk_source_name + target_image_info = remote.run_remote_cmd(cmd, params, + ignore_status=False).stdout_text.strip() + global src_image_info + for src_line in src_image_info.splitlines(): + if "disk size:" in src_line: + continue + if disk_format == "qcow2" and "file length:" in src_line: + continue + if (disk_format == "raw" and ("Format specific information:" in src_line or "extent size hint" in src_line)): + continue + if "virtual size:" in src_line or "file length:" in src_line: + src_line = re.sub('\(.*?\)', '', src_line) + if not re.search(src_line, target_image_info): + test.fail(f"Not found '{src_line}' in {target_image_info}") + + +def run(test, params, env): + """ + To verify that libvirt can create target image automatically when do live + migration with copying storage. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def setup_test(): + """ + Setup steps + + """ + pool_name = params.get("target_pool_name") + pool_type = params.get("target_pool_type") + pool_target = params.get("target_pool_target") + dest_uri = params.get("virsh_migrate_desturi") + disk_format = params.get("disk_format") + disk_source_name = params.get("disk_source_name") + migrate_desturi_port = params.get("migrate_desturi_port") + migrate_desturi_type = params.get("migrate_desturi_type", "tcp") + + test.log.info("Setup steps.") + cmd = "qemu-img convert -f qcow2 -O %s %s %s" % (disk_format, blk_source, disk_source_name) + process.run(cmd, shell=True) + + migration_obj.conn_list.append(migration_base.setup_conn_obj(migrate_desturi_type, params, test)) + migration_obj.remote_add_or_remove_port(migrate_desturi_port) + libvirt.set_vm_disk(vm, params) + + global src_image_info + cmd = "qemu-img info %s -U" % disk_source_name + src_image_info = process.run(cmd, ignore_status=True, shell=True).stdout_text.strip() + + virsh.pool_create_as(pool_name, pool_type, pool_target, uri=dest_uri, + ignore_status=True, debug=True) + + def verify_test(): + """ + Verify steps + + """ + disk_source_name = params.get("disk_source_name") + disk_format = params.get("disk_format") + copy_storage_option = params.get("copy_storage_option") + + test.log.info("Verify steps.") + migration_obj.verify_default() + if "copy-storage-all" in copy_storage_option: + check_image_info(params, test) + + def cleanup_test(): + """ + Cleanup steps + + """ + pool_name = params.get("target_pool_name") + dest_uri = params.get("virsh_migrate_desturi") + disk_source_name = params.get("disk_source_name") + + test.log.info("Cleanup steps.") + virsh.pool_destroy(pool_name, ignore_status=True, debug=True, uri=dest_uri) + cmd = "rm -rf %s" % disk_source_name + process.run(cmd, shell=True) + remote.run_remote_cmd(cmd, params) + migration_obj.cleanup_connection() + + vm_name = params.get("migrate_main_vm") + vm = env.get_vm(vm_name) + first_disk = vm.get_first_disk_devices() + blk_source = first_disk['source'] + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + setup_test() + migration_obj.run_migration() + verify_test() + finally: + cleanup_test() From 694f426c1b962cd1802a88464dbeb2d1e92296c1 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Wed, 13 Dec 2023 04:34:03 -0500 Subject: [PATCH 0075/1055] Fix error of failed to get iface in vm from cfg file Signed-off-by: Haijiao Zhao --- .../connectivity/connectivity_check_bridge_interface.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py index 803e3c9fb03..06f1100b185 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py @@ -49,7 +49,8 @@ def run(test, params, env): iface_attrs['source']['bridge'] = bridge_name vm_attrs = eval(params.get('vm_attrs', '{}')) nwfilter_attrs = parse_attrs('nwfilter_attrs', params) - iface_in_vm = params.get('iface_in_vm', 'eno') + iface_in_vm = params.get('iface_in_vm') + iface_in_vm = iface_in_vm if iface_in_vm else 'eno' host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_net_if( From 123b5ee825fffdadbd24582bb64feb8db4c33ee4 Mon Sep 17 00:00:00 2001 From: nanli Date: Wed, 22 Nov 2023 16:28:16 +0800 Subject: [PATCH 0076/1055] add case for virtio-mem access and discard setting xxxx-299163: Virtio-mem memory device with access and discard settings Signed-off-by: nanli --- .../virtio_mem_access_and_discard.cfg | 75 +++++++ .../virtio_mem_access_and_discard.py | 204 ++++++++++++++++++ 2 files changed, 279 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_devices/virtio_mem_access_and_discard.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/virtio_mem_access_and_discard.py diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_access_and_discard.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_access_and_discard.cfg new file mode 100644 index 00000000000..7fdfe3c64a4 --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_access_and_discard.cfg @@ -0,0 +1,75 @@ +- memory.devices.virtio_mem.access_and_discard: + type = virtio_mem_access_and_discard + start_vm = no + mem_model = "virtio-mem" + virtio_mem_num = 6 + share_0 = 'false' + discard_0 = 'False' + check_path = "ls -l /var/lib/libvirt/qemu/ram/%s" + target_size = 131072 + requested_size = 131072 + block_size = 2048 + aarch64: + target_size = 1048576 + requested_size = 524288 + block_size = 524288 + mem_basic = {'mem_model': '${mem_model}', 'target': {'requested_unit': 'KiB', 'size': ${target_size}, 'size_unit': 'KiB', 'requested_size': ${requested_size}, 'block_unit': 'KiB', 'block_size': ${block_size}}} + required_kernel = [5.14.0,) + guest_required_kernel = [5.8.0,) + func_supported_since_libvirt_ver = (8, 0, 0) + func_supported_since_qemu_kvm_ver = (6, 2, 0) + variants memory_backing: + - file: + source_type = 'file' + source_attr = "'source_type':'${source_type}'" + - anonymous: + source_type = 'anonymous' + source_attr = "'source_type':'${source_type}'" + - memfd: + source_type = 'memfd' + source_attr = "'source_type':'${source_type}'" + discard_error = 'yes' + discard_error_msg = "Property 'memory-backend-memfd.discard-data' not found" + variants: + - undefined: + memfd: + share_0 = 'true' + file: + discard_0 = 'False' + anonymous: + discard_error = 'yes' + discard_error_msg = "Property 'memory-backend-ram.discard-data' not found" + - shared_and_discard: + discard_attr = "'discard':'yes'" + access_attr = "'access_mode':'shared'" + share_0 = 'true' + file: + discard_0 = 'True' + anonymous: + discard_0 = 'True' + - private_and_no_discard: + access_attr = "'access_mode':'private'" + file: + discard_0 = 'False' + anonymous: + discard_0 = 'False' + expected_share = ['${share_0}', 'true', 'true', 'false', 'false', 'true'] + check_discard = '{"execute":"qom-get", "arguments":{"path":"/objects/%s", "property":"discard-data"}}' + expected_discard = ['${discard_0}', 'True', 'True', 'False', 'False', 'True'] + variants: + - with_numa: + no s390-virtio + mem_value = 3145728 + current_mem = 3145728 + max_mem = 10485760 + numa_mem = 1048576 + aarch64: + max_mem = 20971520 + mem_access_1 = "shared" + discard_1 = "yes" + mem_access_2 = "private" + discard_2 = "no" + base_attrs = "'vcpu': 6, 'placement': 'static', 'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'" + numa_attrs = "'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_mem}', 'unit': 'KiB', 'memAccess':'${mem_access_1}','discard':'${discard_1}'},{'id':'2','cpus': '4-5','memory':'${numa_mem}','unit':'KiB', 'memAccess':'${mem_access_2}','discard':'${discard_2}'}]}" + max_attrs = "'max_mem_rt': ${max_mem}, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'" + vm_attrs = {${base_attrs}, ${numa_attrs}, ${max_attrs}} diff --git a/libvirt/tests/src/memory/memory_devices/virtio_mem_access_and_discard.py b/libvirt/tests/src/memory/memory_devices/virtio_mem_access_and_discard.py new file mode 100644 index 00000000000..c5547708d13 --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/virtio_mem_access_and_discard.py @@ -0,0 +1,204 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import re +import json + +from avocado.utils import process + +from virttest import virsh + +from virttest.libvirt_xml.devices import memory +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirtd import Libvirtd + +from provider.memory import memory_base + + +def get_vm_attrs(test, params): + """ + Get vm attrs. + + :param test: test object + :param params: dictionary with the test parameters + :return vm_attrs: get updated vm attrs dict. + """ + vm_attrs = eval(params.get("vm_attrs", "{}")) + source_attr = params.get("source_attr", "") + discard_attr = params.get("discard_attr", "") + access_attr = params.get("access_attr", "") + + mb_value = "" + for item in [source_attr, discard_attr, access_attr]: + if item != "": + mb_value += item + "," + mb_attrs = eval("{'mb':{%s}}" % mb_value[:-1]) + + vm_attrs.update(mb_attrs) + test.log.debug("Get current vm attrs is :%s", vm_attrs) + + return vm_attrs + + +def get_virtio_mem(test, params): + """ + Get 6 basic different virtio-mem memory devices. + + :param test: test object. + :param params: dictionary with the test parameters. + :return mem_list: virtio-mem attr dict list. + """ + mem_list = [] + for item in [(None, None, 0), ('shared', 'yes', 0), + (None, None, 1), ('private', 'no', 1), + (None, None, 2), ('shared', 'yes', 2)]: + + single_mem = eval(params.get("mem_basic")) + target = single_mem['target'] + target.update({'node': item[2]}) + + if item[0] is not None: + single_mem.update({'mem_access': item[0]}) + if item[1] is not None: + single_mem.update({'mem_discard': item[1]}) + mem_list.append(single_mem) + + test.log.debug("Get all virtio-mem list:'%s'", mem_list) + return mem_list + + +def check_access_and_discard(test, params, vm, + expected_share, expected_discard): + """ + Check access and discard setting. + + :param test: test object. + :param params: dictionary with the test parameters. + :param vm: vm object. + :param expected_share: expected access shared value list. + :param expected_discard: expected discard value list. + """ + virtio_mem_num = int(params.get("virtio_mem_num")) + check_discard = params.get("check_discard") + discard_error_msg = params.get("discard_error_msg") + mem_name_list = [] + + # Check access share setting + ret = virsh.qemu_monitor_command(vm.name, "info memdev", "--hmp", + debug=True).stdout_text.replace("\r\n", "") + for index in range(virtio_mem_num): + mem_name = "memvirtiomem%d" % index + pattern = "memory backend: %s.*share: %s " % (mem_name, expected_share[index]) + if not re.search(pattern, ret): + test.fail("Expect '%s' exist, but not found" % pattern) + else: + test.log.debug("Check access shared value is '%s': PASS", pattern) + mem_name_list.append(mem_name) + + # Check discard setting + for index, mem_name in enumerate(mem_name_list): + res = virsh.qemu_monitor_command( + vm.name, check_discard % mem_name, debug=True).stdout_text + + if 'return' in json.loads(res): + actual_discard = str(json.loads(res)['return']) + if actual_discard != expected_discard[index]: + test.fail("Expect discard is '%s', but got '%s'" % ( + expected_discard[index], actual_discard)) + else: + test.log.debug("Check discard value is '%s' PASS", actual_discard) + else: + actual_error = json.loads(res)['error']['desc'] + if not re.search(discard_error_msg, actual_error): + test.fail("Expected to get '%s' in '%s'" % (discard_error_msg, + actual_error)) + else: + test.log.debug("Check '%s' PASS ", actual_error) + + +def run(test, params, env): + """ + Verify virtio-mem memory device works with access and discard settings. + """ + def run_test(): + """ + 1.Define vm with virtio-mem device + 2.Check the virtio-mem memory device access and discard setting + 3.Define vm without virtio-mem device and restart service, and hotplug + virtio-mem device. + """ + test.log.info("TEST_STEP1: Define vm with virtio-mem") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vm_attrs = get_vm_attrs(test, params) + vmxml.setup_attrs(**vm_attrs) + + virtio_mems = get_virtio_mem(test, params) + for mem in virtio_mems: + virtio_mem = memory.Memory() + virtio_mem.setup_attrs(**mem) + vmxml.devices = vmxml.devices.append(virtio_mem) + vmxml.sync() + + test.log.info("TEST_STEP2: Start guest") + vm.start() + + test.log.info("TEST_STEP3,4: Check virtio-mem access and discard") + check_access_and_discard(test, params, vm, expected_share, + expected_discard) + + test.log.info("TEST_STEP5: Destroy vm") + vm.destroy() + + test.log.info("TEST_STEP6: Check the host path for memory file backing") + res = process.run(check_path % vm_name, shell=True, ignore_status=True).stderr_text + if not re.search(path_error, res): + test.fail("Expected '%s', but got '%s'" % (path_error, res)) + + test.log.info("TEST_STEP7: Define guest without virtio-mem memory") + bkxml.setup_attrs(**vm_attrs) + bkxml.sync() + vm.start() + + test.log.info("TEST_STEP8: Restart service") + Libvirtd().restart() + + test.log.info("TEST_STEP9: Hot plug all memory device") + for mem in virtio_mems: + virtio_mem = memory.Memory() + virtio_mem.setup_attrs(**mem) + virsh.attach_device(vm_name, virtio_mem.xml, + debug=True, ignore_status=False) + + test.log.info("TEST_STEP10: Check discard and access again.") + check_access_and_discard(test, params, vm, + expected_share, expected_discard) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bkxml.sync() + + vm_name = params.get("main_vm") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + vm = env.get_vm(vm_name) + + expected_share = eval(params.get("expected_share")) + expected_discard = eval(params.get("expected_discard")) + check_path = params.get("check_path") + path_error = params.get("path_error", "No such file or directory") + + try: + memory_base.check_supported_version(params, test, vm) + run_test() + + finally: + teardown_test() From ba8cc1d91b4239b87f6d96f44d14d85e6c0c9ece Mon Sep 17 00:00:00 2001 From: nanli Date: Mon, 13 Nov 2023 17:24:02 +0800 Subject: [PATCH 0077/1055] add case for virtio mem auto placement VIRT-299160: Virtio-mem memory device with auto placement numatune Signed-off-by: nanli --- .../virtio_mem_auto_placement.cfg | 45 +++++++++ .../virtio_mem_auto_placement.py | 94 +++++++++++++++++++ provider/memory/memory_base.py | 29 ++++++ 3 files changed, 168 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_devices/virtio_mem_auto_placement.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/virtio_mem_auto_placement.py diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_auto_placement.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_auto_placement.cfg new file mode 100644 index 00000000000..f634e0eb3bf --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_auto_placement.cfg @@ -0,0 +1,45 @@ +- memory.devices.virtio_mem.auto_placement: + type = virtio_mem_auto_placement + no s390-virtio + start_vm = "no" + placement = "auto" + mem_model = "virtio-mem" + block_size = 2048 + set_size = 131072 + requested_size = 131072 + aarch64: + block_size = 524288 + set_size = 1048576 + requested_size = 524288 + virtio_mem_dict = {'mem_model': '${mem_model}', 'target': {'requested_unit': 'KiB', 'size': ${requested_size}, 'node': 0, 'size_unit': 'KiB', 'requested_size': ${requested_size}, 'block_unit': 'KiB', 'block_size': ${block_size}}} + required_kernel = [5.14.0,) + guest_required_kernel = [5.8.0,) + func_supported_since_libvirt_ver = (8, 0, 0) + func_supported_since_qemu_kvm_ver = (6, 2, 0) + variants: + - strict: + tuning_mode = "strict" + mode_attrs = "'mode': '${tuning_mode}'," + - interleave: + tuning_mode = "interleave" + mode_attrs = "'mode': '${tuning_mode}'," + - preferred: + tuning_mode = "preferred" + mode_attrs = "'mode': '${tuning_mode}'," + - restrictive: + tuning_mode = "restrictive" + mode_attrs = "'mode': '${tuning_mode}'," + - undefined: + mode_attrs = "" + tuning_attrs = "'numa_memory': {${mode_attrs} 'placement': '${placement}'}" + variants: + - with_2_numa_nodes: + numa_mem = 1048576 + mem_value = 2097152 + current_mem = 2097152 + max_mem = 15242880 + max_mem_slots = 16 + base_attrs = "'vcpu': 4, 'placement': '${placement}', 'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'" + numa_attrs = "'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'},{'id':'1','cpus': '2-3','memory':'${numa_mem}','unit':'KiB'}]}" + max_attrs = "'max_mem_rt': ${max_mem}, 'max_mem_rt_slots': ${max_mem_slots}, 'max_mem_rt_unit': 'KiB'" + vm_attrs = {${base_attrs}, ${numa_attrs}, ${max_attrs}, ${tuning_attrs}} diff --git a/libvirt/tests/src/memory/memory_devices/virtio_mem_auto_placement.py b/libvirt/tests/src/memory/memory_devices/virtio_mem_auto_placement.py new file mode 100644 index 00000000000..a8c3c371706 --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/virtio_mem_auto_placement.py @@ -0,0 +1,94 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import time + +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.devices import memory +from virttest.utils_libvirt import libvirt_vmxml + +from provider.memory import memory_base +from provider.numa import numa_base + + +def run(test, params, env): + """ + 1.Define guest with dimm devices. + 2.Attach dimm and check mem value + """ + + def setup_test(): + """ + Check available numa nodes num. + """ + memory_base.check_supported_version(params, test, vm) + test.log.info("TEST_SETUP: Check available numa nodes num") + numa_obj = numa_base.NumaTest(vm, params, test) + numa_obj.check_numa_nodes_availability() + + def run_test(): + """ + Define guest, check xml, check memory + """ + test.log.info("TEST_SETUP1: Define guest") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vmxml.setup_attrs(**vm_attrs) + virsh.define(vmxml.xml, debug=True, ignore_status=False) + + libvirt_vmxml.modify_vm_device( + vm_xml.VMXML.new_from_inactive_dumpxml(vm_name), 'memory', + virtio_mem_dict) + + test.log.info("TEST_STEP2: Start vm") + vm.start() + vm.wait_for_login().close() + + test.log.info("TEST_SETUP3: Hotplug a virtio-mem device") + mem_obj = memory.Memory() + mem_obj.setup_attrs(**virtio_mem_dict) + virsh.attach_device(vm.name, mem_obj.xml, debug=True, + wait_for_event=True, ignore_status=False) + + test.log.info("TEST_SETUP4: Check the virtio-mem device memory") + time.sleep(3) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + test.log.debug("The new xml is:\n%s", vmxml) + + mem_list = vmxml.devices.by_device_tag('memory') + for mem in mem_list: + actual_size = mem.fetch_attrs()['target']['current_size'] + if str(actual_size) != requested_size: + test.fail("Expected to get requested size '%s', " + "but got '%s'" % (requested_size, actual_size)) + else: + test.log.debug('Check requested size "%s" correctly' % requested_size) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bkxml.sync() + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + vm_attrs = eval(params.get('vm_attrs', '{}')) + virtio_mem_dict = eval(params.get('virtio_mem_dict', '{}')) + requested_size = params.get("requested_size") + + try: + setup_test() + run_test() + + finally: + teardown_test() diff --git a/provider/memory/memory_base.py b/provider/memory/memory_base.py index 2d3592826c6..8032a7ba3f1 100644 --- a/provider/memory/memory_base.py +++ b/provider/memory/memory_base.py @@ -1,5 +1,10 @@ import re +from virttest import libvirt_version +from virttest import utils_misc + +from virttest.utils_version import VersionInterval + from avocado.core import exceptions @@ -47,3 +52,27 @@ def convert_data_size(current_size, dest_unit="KiB"): if isinstance(dest_size, float): return dest_size return int(dest_size) + + +def check_supported_version(params, test, vm): + """ + Check the supported version + + :param params: Dictionary with the test parameters + :param test: Test object + :param vm: Vm object + """ + guest_required_kernel = params.get('guest_required_kernel') + libvirt_version.is_libvirt_feature_supported(params) + utils_misc.is_qemu_function_supported(params) + if not guest_required_kernel: + return + + if not vm.is_alive(): + vm.start() + vm_session = vm.wait_for_login() + vm_kerv = vm_session.cmd_output('uname -r').strip().split('-')[0] + vm_session.close() + if vm_kerv not in VersionInterval(guest_required_kernel): + test.cancel("Got guest kernel version:%s, which is not in %s" % + (vm_kerv, guest_required_kernel)) From 6d4452ec262e115febdbdc93f8f9b3ce752c9bc1 Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 13 Dec 2023 23:48:03 +0800 Subject: [PATCH 0078/1055] migration: Fix issue about assign requested address In some cases, the qemu conf is modified and it is restored after the test is completed. But the libvirtd serivce is not restarted which will cause other cases to fail. So update it. Signed-off-by: lcheng --- .../migration_uri/migration_network_data_transport_tcp.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libvirt/tests/src/migration/migration_uri/migration_network_data_transport_tcp.py b/libvirt/tests/src/migration/migration_uri/migration_network_data_transport_tcp.py index 6dbeaf1f3a3..dc55dd5e329 100644 --- a/libvirt/tests/src/migration/migration_uri/migration_network_data_transport_tcp.py +++ b/libvirt/tests/src/migration/migration_uri/migration_network_data_transport_tcp.py @@ -7,6 +7,7 @@ from virttest import utils_net from virttest.utils_libvirt import libvirt_config +from virttest.utils_test import libvirt from provider.migration import base_steps from provider.migration import migration_base @@ -174,6 +175,7 @@ def cleanup_migration_host(): global remove_key_remote if remove_key_remote: del remove_key_remote + libvirt.remotely_control_libvirtd(server_ip, server_user, server_pwd, "restart") def cleanup_migration_address(): """ @@ -190,6 +192,7 @@ def cleanup_migration_address(): global remove_key_remote if remove_key_remote: del remove_key_remote + libvirt.remotely_control_libvirtd(server_ip, server_user, server_pwd, "restart") if ipv4_env_on_target: cleanup_ipv4_env(params) @@ -198,6 +201,9 @@ def cleanup_migration_address(): test_case = params.get('test_case', '') vm_name = params.get("migrate_main_vm") migrate_again = "yes" == params.get("migrate_again", "no") + server_ip = params.get("server_ip") + server_user = params.get("server_user", "root") + server_pwd = params.get("server_pwd") vm = env.get_vm(vm_name) migration_obj = base_steps.MigrationBase(test, vm, params) From 2d98a14cc632b6a4f347db6fc9a6a2381c7dc9f3 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 13 Dec 2023 11:37:43 +0100 Subject: [PATCH 0079/1055] libvirt_rng: Add alternative expected error The error message has change but is still valid as it mentions the device model. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/libvirt_rng.cfg | 4 ++-- libvirt/tests/src/libvirt_rng.py | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/cfg/libvirt_rng.cfg b/libvirt/tests/cfg/libvirt_rng.cfg index 2e8b5165479..008268a6c03 100644 --- a/libvirt/tests/cfg/libvirt_rng.cfg +++ b/libvirt/tests/cfg/libvirt_rng.cfg @@ -59,10 +59,10 @@ driver_packed = "on" - invalid_address: address = "{ 'domain': '0x9999', 'bus': '0x00', 'slot': '0x00', 'function': '0x0'}" - expected_create_error = "Invalid PCI address" + expected_create_error = ".*Invalid PCI address.*" - invalid_model: rng_model = virtio-abc - expected_create_error = "RNG model" + expected_create_error = ".*(RNG model|model.*rng.*virtio-abc).*" - backend_udp: backend_model = "egd" backend_type = "udp" diff --git a/libvirt/tests/src/libvirt_rng.py b/libvirt/tests/src/libvirt_rng.py index 4d431199b5e..d6b0a4aa6c9 100644 --- a/libvirt/tests/src/libvirt_rng.py +++ b/libvirt/tests/src/libvirt_rng.py @@ -694,8 +694,9 @@ def have_rng_xml(): '\n%s' % details) except xcepts.LibvirtXMLError as details: logging.info(str(details)) - if expected_create_error not in str(details): - test.fail("Didn't find expected error:" + details = str(details).replace("\n", "") + if not re.match(expected_create_error, details): + test.fail("Didn't match expected error:" " %s" % expected_create_error) finally: # Delete snapshots. From 566535bbaecdf6750e6949c9455f724e912fdcd1 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Wed, 13 Dec 2023 18:34:20 +0800 Subject: [PATCH 0080/1055] v2v:modify esx65/67 related testing for function-test-esx Signed-off-by: vwu-vera --- v2v/tests/cfg/function_test_esx.cfg | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index fd3cd8796ae..d4c31948fa0 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -310,7 +310,7 @@ - raid: variants: - bios: - only esx_60 + only esx_80 main_vm = VM_NAME_ESX_RAID_V2V_EXAMPLE - uefi: boottype = 3 @@ -321,7 +321,7 @@ only esx_70 main_vm = "VM_NAME_ISCSI_STORAGE_V2V_EXAMPLE" - GPO_AV: - only esx_60 + only esx_70 main_vm = 'VM_NAME_GPO_AV_V2V_EXAMPLE' checkpoint = 'GPO_AV' msg_content = 'virt-v2v: warning: this guest has Windows Group Policy Objects%virt-v2v: warning: this guest has Anti-Virus \(AV\) software' @@ -343,7 +343,7 @@ checkpoint = vmtools removed_pkgs = vmware-tools-libraries-nox,vmware-tools-foundation,vmware-tools-libraries-x - service: - only esx_60 + only esx_70 main_vm = VM_NAME_VMTOOLS_SERVICE_V2V_EXAMPLE checkpoint = "vmtools,service service_name = vmware-tools @@ -357,9 +357,10 @@ only esx_70 main_vm = VM_NAME_DEVICE_PASSTHRU_V2V_EXAMPLE - empty_cdrom: - only esx_60 + only esx_80 main_vm = VM_NAME_EMPTY_CDROM_V2V_EXAMPLE checkpoint = empty_cdrom + boottype = 3 skip_vm_check = yes skip_reason = "No vm is created in this case" - option_root: @@ -405,7 +406,7 @@ msg_content = 'virt-v2v: warning: mount: mount exited with status 32: mount:.*? already mounted .*?\(ignored\)' expect_msg = yes - with_proxy: - only esx_60 + only esx_70 no libvirt main_vm = VM_NAME_ESX_WITH_PROXY checkpoint = with_proxy From ff2f10a4f3e87888715b42d54eff1d3cafda20c4 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Thu, 14 Dec 2023 14:45:00 +0800 Subject: [PATCH 0081/1055] memory: Fix up a virtio-mem device coldplug issue Introduced by 869c29ebc659c Signed-off-by: Yingshun Cui --- libvirt/tests/cfg/memory/memory_update_device.cfg | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/memory/memory_update_device.cfg b/libvirt/tests/cfg/memory/memory_update_device.cfg index 6ff1f277aa0..55b004d7baf 100644 --- a/libvirt/tests/cfg/memory/memory_update_device.cfg +++ b/libvirt/tests/cfg/memory/memory_update_device.cfg @@ -10,9 +10,11 @@ func_supported_since_libvirt_ver = (8, 0, 0) func_supported_since_qemu_kvm_ver = (6, 2, 0) vm_attrs = {'max_mem_rt': 10485760, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB', 'vcpu': 4, 'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '1048576', 'unit': 'KiB'}]}} + mem_device_attrs = {'mem_model': 'virtio-mem', 'target': {'requested_unit': 'KiB', 'size': 262144, 'node': 0, 'size_unit': 'KiB', 'requested_size': 131072, 'block_unit': 'KiB', 'block_size': 2048}} + requested_size = 160MiB aarch64: vm_attrs = {'max_mem_rt': 10485760, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB', 'vcpu': 4, 'cpu': {'mode': 'host-passthrough', 'numa_cell': [{'id': '0', 'cpus': '0-3', 'memory': '524288', 'unit': 'KiB'}]}} mem_device_attrs = {'mem_model': 'virtio-mem', 'target': {'requested_unit': 'KiB', 'size': 1048576, 'node': 0, 'size_unit': 'KiB', 'requested_size': 524288, 'block_unit': 'KiB', 'block_size': 524288}} - requested_size = 1048576KiB + requested_size = 1048576KiB check_log_str = "MEMORY_DEVICE_SIZE_CHANGE.*virtiomem" virsh_opts = "--alias %s --requested-size ${requested_size}" From 35927b36912712a4c4d22a5497f4c16c87bab5a5 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Thu, 14 Dec 2023 19:03:47 +0800 Subject: [PATCH 0082/1055] v2v:fix the failed case in 9.4 functional testing Signed-off-by: vwu-vera --- v2v/tests/cfg/convert_from_file.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2v/tests/cfg/convert_from_file.cfg b/v2v/tests/cfg/convert_from_file.cfg index d6b2b3de58c..4c459148c14 100644 --- a/v2v/tests/cfg/convert_from_file.cfg +++ b/v2v/tests/cfg/convert_from_file.cfg @@ -115,7 +115,7 @@ checkpoint = 'cpu_topology' v2v_debug = force_on ova_file_name = OVA_DIR_RHEL_LINUX_V2V_EXAMPLE.ova - ova_dir = OVA_DIR_ROOT_V2V_EXAMPLE/${ova_file_name} + ova_dir = ${ova_file_name} ova_copy_dir = 'OVA_DIR_COPY_V2V_EXAMPLE' input_file = ${ova_copy_dir}/${ova_file_name} msg_content_yes = '' From 21fb9853ea92bdb432bca316e8d15938cfa33e0d Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Wed, 13 Dec 2023 17:54:14 +0800 Subject: [PATCH 0083/1055] vm_feature: add case for hyperv Start windows VM with hyper-v newly available features and check qemu command line Signed-off-by: Dan Zheng --- libvirt/tests/src/cpu/vm_features.py | 40 ++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/libvirt/tests/src/cpu/vm_features.py b/libvirt/tests/src/cpu/vm_features.py index 0f45c97fed9..e4998c65dd6 100644 --- a/libvirt/tests/src/cpu/vm_features.py +++ b/libvirt/tests/src/cpu/vm_features.py @@ -77,7 +77,7 @@ def get_hyperv_features_in_domcapabilities(): def update_hyperv_features(vmxml, hyperv_attr, test): """ Update specified hyperv features in vmxml - Sample hyperv_attr: {'relaxed': {'state': 'on'}, 'spinlocks': {'state': 'on', 'retries': '4096'}} + Sample hyperv_attr: {'relaxed': {'state': 'on'}, 'spinlocks': {'state': 'on', 'retries': '4096'}} :param vmxml: VMXML instance :param hyperv_attr: dict, hyperv features and attributes @@ -145,6 +145,22 @@ def assemble_hyperv_feature_list(feature_list, params, test): return hyperv_attr +def get_expected_hyperv_values_in_qemu_line(feature_name): + """ + Get expected hyperv feature values in qemu command line + + :param feature_name: str, the hyperv feature name + :return: str, expected qemu command line for given feature + """ + feature_name_value_mapping = {'hv-spinlocks': 'hv-spinlocks=0x1000', + 'hv-stimer': 'hv-stimer=on,hv-stimer-direct=on', + 'hv-vendor-id': 'hv-vendor-id=KVM Hv'} + if feature_name in feature_name_value_mapping: + return feature_name_value_mapping[feature_name] + else: + return "%s=on" % feature_name + + def run(test, params, env): """ Test vm features @@ -198,19 +214,27 @@ def run(test, params, env): test.fail('VM failed to start:\n%s' % details) vm_session = vm.wait_for_login() - if hyperv_attr and not features_from_domcap: + if hyperv_attr and features_from_domcap == 'in': # Check hyperv settings in qemu command line + expect_exist_list = [] + expect_nonexist_list = [] for attr in hyperv_attr: + new_attr = re.sub('_', '-', attr) if libvirt_version.version_compare(5, 6, 0): - exp_str = 'hv-' + attr + exp_str = 'hv-' + new_attr else: - exp_str = 'hv_' + attr + exp_str = 'hv_' + new_attr if hyperv_attr[attr] == 'off': - if libvirt.check_qemu_cmd_line(exp_str, True): - test.fail("Unexpected '%s' was found in " - "qemu command line" % exp_str) + expect_nonexist_list.append(exp_str) else: - libvirt.check_qemu_cmd_line(exp_str) + exp_str = get_expected_hyperv_values_in_qemu_line(exp_str) + expect_exist_list.append(exp_str) + if expect_nonexist_list: + test.log.debug("Not expected list:%s", expect_nonexist_list) + libvirt.check_qemu_cmd_line(expect_nonexist_list, expect_exist=False) + if expect_exist_list: + test.log.debug("Expected list:%s", expect_exist_list) + libvirt.check_qemu_cmd_line(expect_exist_list) if pmu_attr: libvirt.check_qemu_cmd_line('pmu=' + pmu_attr['pmu']) From fe79507e78a843957eeb3173f765ad31feddc7ed Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 28 Nov 2023 13:22:29 -0500 Subject: [PATCH 0084/1055] virsh_domdirtyrate_calc: Relax test conditions Also, the dirty rate might take some time to be firstly available and some more time to converge to the expected test value. Use a wait_for loop a timeout instead. Signed-off-by: Sebastian Mitterle --- .../domain/virsh_domdirtyrate_calc.py | 48 ++++++++++++------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_domdirtyrate_calc.py b/libvirt/tests/src/virsh_cmd/domain/virsh_domdirtyrate_calc.py index 7570ee807fe..d5be7f6e664 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_domdirtyrate_calc.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_domdirtyrate_calc.py @@ -1,11 +1,11 @@ -import time import logging as log +import time from virttest import virsh from virttest import libvirt_version from virttest.libvirt_xml import vm_xml -from virttest.utils_test import libvirt from virttest.utils_stress import install_stressapptest +from virttest import utils_misc logging = log.getLogger('avocado.' + __name__) @@ -52,9 +52,11 @@ def check_dirty_rate(dirty_rate): tolerance = 0.75 if abs(int(dirty_rate)/int(ram_size) - 1) > tolerance: - test.fail("Dirty rate calculated %s has a big difference " - "with the ram size %s loaded in guest " - % (dirty_rate, ram_size)) + logging.debug("Dirty rate calculated %s has a big difference " + "with the ram size %s loaded in guest " + % (dirty_rate, ram_size)) + return False + return True def check_output(): """ @@ -64,10 +66,10 @@ def check_output(): out_list = res.stdout_text.strip().splitlines()[1:] out_dict = {} out_dict = dict(item.strip().split("=") for item in out_list) - if out_dict["dirtyrate.calc_status"] != calc_status: - test.fail("Calculating dirty rate should be completed " - "after %s seconds" % period) + logging.debug("Calculating dirty rate should be completed " + "after approx. %s seconds" % period) + return False if out_dict["dirtyrate.calc_period"] != period: test.fail("Calculating period is not the same with " "the setting period %s" % period) @@ -78,9 +80,20 @@ def check_output(): if mode == "dirty-ring": for cpu_num in range(vm.get_cpu_count()): dirty_rate = out_dict["dirtyrate.vcpu.%s.megabytes_per_second" % cpu_num] - check_dirty_rate(dirty_rate) + return check_dirty_rate(dirty_rate) else: - check_dirty_rate(dirty_rate) + return check_dirty_rate(dirty_rate) + + def wait_for_output(): + """ + Trigger calculation and wait for expected result + """ + result = virsh.domdirtyrate_calc(vm_name, + options=option, + ignore_status=False, + debug=True) + time.sleep(1.2*int(period)) + return check_output() vm_name = params.get("main_vm") status_error = "yes" == params.get("status_error", "no") @@ -108,15 +121,18 @@ def check_output(): load_stress(vm) - result = virsh.domdirtyrate_calc(vm_name, options=option, ignore_status=True, debug=True) - - time.sleep(int(period)) - libvirt.check_exit_status(result) - if status_error: return else: - check_output() + result = utils_misc.wait_for(lambda: wait_for_output(), + step=int(period), + text="Waiting for the dirty rate", + timeout=60, + ignore_errors=True) + if not result: + test.fail("Didn't get the right dirty rate.") + else: + logging.debug("Dirty rate as expected.") finally: if vm.is_alive(): From efb7981a98eff2a1f2b57ee7d9b12b45cfdacabc Mon Sep 17 00:00:00 2001 From: Meina Li Date: Thu, 14 Dec 2023 20:45:38 -0500 Subject: [PATCH 0085/1055] uest_os_booting: add new case of virtiofs device booting It mainly implements booting vm from virtiofs device: VIRT-297203 Signed-off-by: Meina Li --- .../boot_order/boot_from_virtiofs_device.cfg | 12 ++ .../boot_order/boot_from_virtiofs_device.py | 128 ++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_virtiofs_device.cfg create mode 100644 libvirt/tests/src/guest_os_booting/boot_order/boot_from_virtiofs_device.py diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_virtiofs_device.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_virtiofs_device.cfg new file mode 100644 index 00000000000..79f56c9b859 --- /dev/null +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_virtiofs_device.cfg @@ -0,0 +1,12 @@ +- guest_os_booting.boot_order.virtiofs_device: + type = boot_from_virtiofs_device + start_vm = no + access_cmd = "virsh console %s" + vm_memory = 15728640 + variants: + - start_guest: + target_dir = "mount_tag" + console_dev = "ttyS0,115200" + guest_cmd = "df -h" + os_dict = {'cmdline': 'root=virtiofs:${target_dir} console=${console_dev}', 'initrd': '%s', 'kernel': '%s'} + virtiofs_dict = {'target': {'dir': '${target_dir}'}, 'type_name': 'mount', 'source': {'dir': '%s'}, 'binary': {'path': '/usr/libexec/virtiofsd'}, 'accessmode': 'passthrough', 'boot': '1', 'driver': {'type': 'virtiofs'}} diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_virtiofs_device.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_virtiofs_device.py new file mode 100644 index 00000000000..9f4c9febbde --- /dev/null +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_virtiofs_device.py @@ -0,0 +1,128 @@ +# Copyright Red Hat +# SPDX-License-Identifier: GPL-2.0 +# Author: Meina Li + +import aexpect +import os +import re +import shutil + +from avocado.utils import process + +from virttest import data_dir +from virttest import utils_selinux +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.devices import filesystem +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.guest_os_booting import guest_os_booting_base as guest_os + +BOOT_PATH = data_dir.get_data_dir() + + +def run(test, params, env): + """ + This case is to verify to boot from virtiofs device. + 1) Prepare a virtiofs boot environment. + 2) Start a guest with virtiofs related xml. + 3) Login guest to check. + """ + def prepare_virtiofs_bootable_system(): + """ + Prepare a basic linux root file system. + """ + cmd1 = f"mkdir {install_root}" + cmd2 = f"dnf --installroot={install_root} --releasever=9 install "\ + "system-release vim-minimal systemd passwd dnf rootfiles sudo "\ + "kernel kernel-modules net-tools yum dhcp-client -y >/dev/null" + # Create the initramfs. + cmd3 = f"dracut {initrams_file} --early-microcode "\ + "--add virtiofs --filesystem virtiofs" + multi_cmd = f"{cmd1}; {cmd2}; {cmd3}" + process.run(multi_cmd, shell=True, ignore_status=False) + change_virtiofs_root_passwd() + # Copy vmlinuz from host to use in guest. + cmd5 = f"cp $(ls /boot/vmlinuz* | tail -n 1) {vmlinuz_file}" + process.run(cmd5, shell=True) + + def change_virtiofs_root_passwd(): + """ + After install virtiofs related linux root file system, the password of root + need to be changed + """ + selinux_mode = utils_selinux.get_status() + utils_selinux.set_status("permissive") + fd = os.open('/', os.R_OK, os.X_OK) + os.chroot(install_root) + os.chdir('/') + set_passwd_cmd = f"echo {passwd} | passwd --stdin {username} &>/dev/null; exit" + os.system(set_passwd_cmd) + os.fchdir(fd) + os.chroot('.') + test.log.info("The passwd has been changed and exit the chroot env.") + utils_selinux.set_status(selinux_mode) + + vm_name = params.get("main_vm") + install_root = os.path.join(BOOT_PATH, "virtio-fs-root") + initrams_file = os.path.join(BOOT_PATH, "initramfs-virtiofs.img") + vmlinuz_file = os.path.join(BOOT_PATH, "vmlinuz-virtiofs.img") + boot_img = os.path.join(data_dir.get_data_dir(), "test.img") + access_cmd = params.get("access_cmd") % vm_name + guest_cmd = params.get("guest_cmd") + target_dir = params.get("target_dir") + vm_memory = int(params.get("vm_memory")) + username = params.get("username") + passwd = params.get("password") + disk_dict = {} + + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + test.log.info("SETUP: Prepare a virtiofs bootable environment.") + prepare_virtiofs_bootable_system() + os_dict = eval(params.get("os_dict") % (initrams_file, vmlinuz_file)) + virtiofs_dict = eval(params.get("virtiofs_dict") % install_root) + + test.log.info("STEP1: Prepare a guest xml with memory and virtiofs.") + vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", hpgs=False) + vmxml = guest_os.prepare_os_xml(vm_name, os_dict) + test.log.info("Better to use big enough memory size, for example 15728640.") + vmxml.memory = vm_memory + vmxml.remove_all_boots() + virtiofs_dev = filesystem.Filesystem() + virtiofs_dev.setup_attrs(**virtiofs_dict) + test.log.debug(f"The filesystem device xml is {virtiofs_dev}") + vmxml.add_device(virtiofs_dev) + + test.log.info("STEP2: Start the guest with non-bootable disk image.") + libvirt.create_local_disk("file", path=boot_img, size="10G", disk_format="qcow2") + disk_dict.update({'source': {'attrs': {'file': boot_img}}}) + libvirt_vmxml.modify_vm_device(vmxml, 'disk', disk_dict) + if not vm.is_alive(): + virsh.start(vm_name, debug=True, ignore_status=False) + + test.log.info("STEP3: Login the guest") + access_session = aexpect.ShellSession(access_cmd) + libvirt.virsh_console_login(access_session, username, passwd, + debug=True, timeout=120) + result = access_session.cmd_output(guest_cmd) + test.log.debug("Send cmd: '%s' in console", guest_cmd) + if not re.search(target_dir, result): + test.fail(f"Expect {target_dir} in {result}, but not found") + else: + test.log.debug(f"Got {target_dir} in {result} as expected") + + finally: + if vm.is_alive(): + virsh.destroy(vm_name, debug=True, ignore_status=False) + test.log.info("Remove the linux root file system directory.") + if os.path.exists(install_root): + shutil.rmtree(install_root) + for file_path in [initrams_file, vmlinuz_file, boot_img]: + if os.path.exists(file_path): + os.remove(file_path) + bkxml.sync() From 525a392e7689230100560a4a429cbfb6ce189dbb Mon Sep 17 00:00:00 2001 From: Hu Shuai Date: Fri, 15 Dec 2023 10:51:16 +0800 Subject: [PATCH 0086/1055] cpu: Skip host-model for aarch64 aarch64 supports cpu_model "host-passthrough". Signed-off-by: Hu Shuai --- libvirt/tests/cfg/cpu/vcpu_cve.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/cfg/cpu/vcpu_cve.cfg b/libvirt/tests/cfg/cpu/vcpu_cve.cfg index 676966371b7..c8f4c4de6a9 100644 --- a/libvirt/tests/cfg/cpu/vcpu_cve.cfg +++ b/libvirt/tests/cfg/cpu/vcpu_cve.cfg @@ -4,6 +4,7 @@ start_vm = no variants cpu_mode: - host_model: + no aarch64 cpu_mode = 'host-model' - host_passthrough: cpu_mode = 'host-passthrough' From 2480aeb8107b10b4d3fd093b86d280d4e1d984af Mon Sep 17 00:00:00 2001 From: Hu Shuai Date: Fri, 15 Dec 2023 15:38:02 +0800 Subject: [PATCH 0087/1055] memory_misc: Enable test for aarch64 Update the hugepagesize to enable test for aarch64 Signed-off-by: Hu Shuai --- libvirt/tests/cfg/memory/memory_misc.cfg | 20 +++++++++++++++--- libvirt/tests/src/memory/memory_misc.py | 26 +++++++++++++++--------- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_misc.cfg b/libvirt/tests/cfg/memory/memory_misc.cfg index 4d6d10679e5..d0467a85753 100644 --- a/libvirt/tests/cfg/memory/memory_misc.cfg +++ b/libvirt/tests/cfg/memory/memory_misc.cfg @@ -40,6 +40,8 @@ numa_node_size = 512000 cpu_attrs = {'numa_cell': [{'id': '0', 'cpus': '0-7', 'memory': '${numa_node_size}', 'unit': 'KiB'}, {'id': '1', 'cpus': '8-15', 'memory': '${numa_node_size}', 'unit': 'KiB'}]} mem_device_attrs = {'source': {'pagesize_unit': 'KiB', 'pagesize': 2048, 'nodemask': '0'}, 'mem_model': 'dimm', 'target': {'size': 131072, 'node': 1, 'size_unit': 'KiB'}} + aarch64: + mem_device_attrs = {'source': {'pagesize_unit': 'KiB', 'pagesize': 524288, 'nodemask': '0'}, 'mem_model': 'dimm', 'target': {'size': 524288, 'node': 1, 'size_unit': 'KiB'}} - nodeset_specified: no s390-virtio pagesize = 1048576 @@ -58,19 +60,29 @@ no s390-virtio pagesize = 2048 pagenum = 5120 + aarch64: + pagesize = 524288 + pagenum = 20 vm_attrs = {'max_mem_rt': 83886080, 'max_mem_rt_slots': 8, 'max_mem_rt_unit': 'KiB', 'memory': 20971520, 'memory_unit': 'KiB', 'current_mem': 20971520, 'current_mem_unit': 'KiB'} mem_backing_attrs = {'hugepages': {}} cpu_attrs = {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '19922944', 'unit': 'KiB', 'discard': 'yes'}]} - mem_device_attrs = {'source': {'pagesize_unit': 'KiB', 'pagesize': 2048, 'nodemask': '0'}, 'mem_model': 'dimm', 'target': {'size': 1048576, 'node': 0, 'size_unit': 'KiB'}} + mem_device_attrs = {'source': {'pagesize_unit': 'KiB', 'pagesize': ${pagesize}, 'nodemask': '0'}, 'mem_model': 'dimm', 'target': {'size': 1048576, 'node': 0, 'size_unit': 'KiB'}} - mount_hp_running_vm: no s390-virtio pagesize = 2048 - hp_path = '/dev/hugepages1G' + mount_pagesize = 1048576 + mount_path = '/dev/hugepages1G' + mount_option = 'pagesize=1G' + aarch64: + pagesize = 524288 + mount_pagesize = 2048 + mount_path= '/dev/hugepages2M' + mount_option = 'pagesize=2M' vm_attrs = {'vcpu': 4, 'max_mem_rt': 15242880, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'} numa_node_size = 1048576 cpu_attrs = {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_node_size}', 'unit': 'KiB'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_node_size}', 'unit': 'KiB'}]} mem_backing_attrs = {'hugepages': {'pages': [{'unit': 'KiB', 'size': '${pagesize}'}]}} - mem_device_attrs = {'source': {'pagesize': 1048576, 'pagesize_unit': 'KiB'}, 'mem_model': 'dimm', 'target': {'size': 1048576, 'node': 0, 'size_unit': 'KiB'}} + mem_device_attrs = {'source': {'pagesize': ${mount_pagesize}, 'pagesize_unit': 'KiB'}, 'mem_model': 'dimm', 'target': {'size': 1048576, 'node': 0, 'size_unit': 'KiB'}} - edit_mem: variants case: - forbid_0: @@ -143,6 +155,8 @@ vmxml_current_mem = 1024000 vmxml_vcpu = 4 cpu_attrs = {'mode': 'host-model', 'numa_cell': [{'id': '0', 'cpus': '0,2', 'memory': '${numa_node_size}', 'unit': 'KiB'}, {'id': '1', 'cpus': '1,3', 'memory': '${numa_node_size}', 'unit': 'KiB'}]} + aarch64: + cpu_attrs = {'mode': 'host-passthrough', 'numa_cell': [{'id': '0', 'cpus': '0,2', 'memory': '${numa_node_size}', 'unit': 'KiB'}, {'id': '1', 'cpus': '1,3', 'memory': '${numa_node_size}', 'unit': 'KiB'}]} dimm_device_1_attrs = {'mem_model': 'dimm', 'target': {'size': ${at_size}, 'size_unit': 'KiB', 'node': 1}} dimm_device_0_attrs = {'mem_model': 'dimm', 'target': {'size': 0, 'size_unit': 'KiB', 'node': 0}} audit_cmd = ausearch -ts recent -m VIRT_RESOURCE| grep 'mem' diff --git a/libvirt/tests/src/memory/memory_misc.py b/libvirt/tests/src/memory/memory_misc.py index f0b7ddf489e..b5c6ed79753 100644 --- a/libvirt/tests/src/memory/memory_misc.py +++ b/libvirt/tests/src/memory/memory_misc.py @@ -246,10 +246,12 @@ def _setup_mbxml(): test.log.debug(virsh.dumpxml(vm_name).stdout_text) if case == 'mount_hp_running_vm': + pagesize = int(params.get('pagesize')) + mount_pagesize = int(params.get('mount_pagesize')) vm_mem_size = vmxml.memory hp_cfg = test_setup.HugePageConfig(params) - hp_cfg.set_kernel_hugepages(1048576, vm_mem_size // 1048576) - hp_cfg.set_kernel_hugepages(2048, vm_mem_size // 2048) + hp_cfg.set_kernel_hugepages(pagesize, vm_mem_size // pagesize) + hp_cfg.set_kernel_hugepages(mount_pagesize, vm_mem_size // mount_pagesize) set_vmxml(vmxml, params) _setup_mbxml() vmxml.sync() @@ -386,11 +388,15 @@ def run_test_memorybacking(case): if case == 'mount_hp_running_vm': vm.start() utils_libvirtd.Libvirtd('virtqemud').stop() - hp_path = params.get('hp_path') - if not os.path.exists(hp_path): - os.mkdir(hp_path) - utils_disk.mount('hugetlbfs', hp_path, 'hugetlbfs', - options='pagesize=1G', verbose=True) + mount_path = params.get('mount_path') + mount_option = params.get('mount_option') + + if not os.path.exists(mount_path): + os.mkdir(mount_path) + utils_disk.mount('hugetlbfs', mount_path, 'hugetlbfs', + options=mount_option, verbose=True) + libvirtd = utils_libvirtd.Libvirtd() + libvirtd.restart() vm_state = virsh.domstate(vm_name).stdout_text if 'running' not in vm_state: @@ -425,9 +431,9 @@ def cleanup_test_memorybacking(case): if case == 'hp_from_2_numa_nodes': restore_hugepages() if case == 'mount_hp_running_vm': - hp_path = params.get('hp_path') - utils_disk.umount('hugetlbfs', hp_path, 'hugetlbfs') - os.rmdir(hp_path) + mount_path = params.get('mount_path') + utils_disk.umount('hugetlbfs', mount_path, 'hugetlbfs') + os.rmdir(mount_path) def run_test_edit_mem(case): """ From 62430d9dd26bd27b018086db62124e5360fc7fca Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 18 Dec 2023 09:39:04 -0500 Subject: [PATCH 0088/1055] vcpu_affinity: fix expected error Error message have changed but are still valid. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/cpu/vcpu_affinity.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/cpu/vcpu_affinity.cfg b/libvirt/tests/cfg/cpu/vcpu_affinity.cfg index f2fd307f296..385c0e9a774 100644 --- a/libvirt/tests/cfg/cpu/vcpu_affinity.cfg +++ b/libvirt/tests/cfg/cpu/vcpu_affinity.cfg @@ -82,7 +82,7 @@ check = "vcpu_outrange_cpuset" config_xml = "vcpu" start_fail = "yes" - err_msg = "Numerical result out of range" + err_msg = "Numerical result out of range;Invalid value.*cpuset" - cputune: vcpu_cpuset = "0" variants: @@ -90,7 +90,7 @@ check = "cputune_outrange_cpuset" config_xml = "cputune" start_fail = "yes" - err_msg = "Numerical result out of range" + err_msg = "Numerical result out of range;Invalid value.*cpuset" - invalid_cpuset: check = "cputune_invalid_cpuset" config_xml = "cputune" From 1699089189ce59e5f0878988d5c1e03c94cc5693 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 18 Dec 2023 10:02:49 -0500 Subject: [PATCH 0089/1055] virtual_disks_transient_disk: fix disk discovery The tests used the disk target as identifier for the disk inside of the VM. However, the target is not guaranteed to show up in the guest as-is, especially given that the /dev/XdY paths are not persistent and can change between boots. Use instead a function that identifies a new disk inside of a VM as the one disk that has no root mount on itself, its partitions or volumes. Signed-off-by: Sebastian Mitterle --- .../src/virtual_disks/virtual_disks_transient_disk.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_transient_disk.py b/libvirt/tests/src/virtual_disks/virtual_disks_transient_disk.py index 3d898d56c7a..33ffb91f20c 100644 --- a/libvirt/tests/src/virtual_disks/virtual_disks_transient_disk.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_transient_disk.py @@ -66,13 +66,14 @@ def check_share_transient_disk(vms_list): try: test_str = "teststring" - sha_cmd = ("sha1sum /dev/%s" % disk_target) + session0 = vms_list[0]['vm'].wait_for_login(timeout=10) + new_disk0, _ = libvirt_disk.get_non_root_disk_name(session0) + sha_cmd = ("sha1sum /dev/%s" % new_disk0) cmd = ("fdisk -l /dev/%s && mkfs.ext4 -F /dev/%s && mount /dev/%s" " /mnt && echo '%s' > /mnt/test && umount /mnt" - % (disk_target, disk_target, disk_target, test_str)) + % (new_disk0, new_disk0, new_disk0, test_str)) # check on vm0. - session0 = vms_list[0]['vm'].wait_for_login(timeout=10) s, o = session0.cmd_status_output(cmd) logging.debug("session in vm0 exit %s; output: %s", s, o) if s: From b60d26e63865df9c8558cbf47274240f922de944 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Tue, 19 Dec 2023 01:19:13 -0500 Subject: [PATCH 0090/1055] Unify the name of the vdpa cases The jobs.yaml run vdpa related case in a separate job with a pattern "vdpa_interface". And these cases are excluded from the network job by the pattern "vdpa_interface" since it needs specific hardware. Signed-off-by: Yalan Zhang --- .../mem_lock_limit_multiple_vdpa_interfaces.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_network/locked_memory_vdpa/mem_lock_limit_multiple_vdpa_interfaces.cfg b/libvirt/tests/cfg/virtual_network/locked_memory_vdpa/mem_lock_limit_multiple_vdpa_interfaces.cfg index c03d03e9402..844ccde56b5 100644 --- a/libvirt/tests/cfg/virtual_network/locked_memory_vdpa/mem_lock_limit_multiple_vdpa_interfaces.cfg +++ b/libvirt/tests/cfg/virtual_network/locked_memory_vdpa/mem_lock_limit_multiple_vdpa_interfaces.cfg @@ -1,4 +1,4 @@ -- virtual_network.locked_memory.vdpa_interfaceiface.multiple_interfaces: +- virtual_network.locked_memory.vdpa_interface.multiple_interfaces: type = mem_lock_limit_multiple_vdpa_interfaces start_vm = no only x86_64 From 426de63d8bb0d608c72a3d2f22d918f0c4604391 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 18 Dec 2023 10:24:58 -0500 Subject: [PATCH 0091/1055] virtual_disks_multidisks: fix disk discovery The tests used the disk target as identifier for the disk inside of the VM. However, the target is not guaranteed to show up in the guest as-is, especially given that the /dev/XdY paths are not persistent and can change between boots. Use instead a function that identifies a new disk inside of a VM as the one disk that has no root mount on itself, its partitions or volumes. Also, the delete_scsi_disk doesn't return any value so it was always looping for the full timeout. Wrap it into a function that confirms if both the module and device have been removed. Finally, disable floppy testing for s390x. Signed-off-by: Sebastian Mitterle --- .../virtual_disks_multidisks.cfg | 6 ++++ .../virtual_disks/virtual_disks_multidisks.py | 31 +++++++++++++------ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_multidisks.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_multidisks.cfg index 07eeb4cf4b9..c14882c05e7 100644 --- a/libvirt/tests/cfg/virtual_disks/virtual_disks_multidisks.cfg +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_multidisks.cfg @@ -249,6 +249,7 @@ driver_option = "name=qemu,type=raw,iothread=4" variants: - ide_bus: + no s390-virtio virt_disk_device_target = "hdb" virt_disk_device_bus = "ide" - dom_iothreads: @@ -379,6 +380,7 @@ virt_disk_device_target = "hda" virt_disk_device_bus = "ide" - disk_bus_fdc: + no s390-virtio virt_disk_device = "floppy" virt_disk_device_target = "fda" virt_disk_device_bus = "fdc" @@ -581,6 +583,7 @@ virt_disk_at_dt_disk = "yes" disks_attach_option = "--mode readonly --sourcetype file;" - disk_readonly_nfs_floppy: + no s390-virtio only coldplug virt_disk_device_test_readonly = "yes" virt_disk_device = "floppy" @@ -700,6 +703,7 @@ virt_disk_device_bus = "scsi" virt_disk_device_target = "sda" - disk_floppy_update_boot_order: + no s390-virtio only coldplug floppy_path = '/var/lib/libvirt/images/fd2.img' disk_floppy_update_boot_order = "yes" @@ -716,6 +720,7 @@ only coldplug no q35 no aarch64 + no s390-virtio virt_disk_with_source = "yes" virt_disk_device = "disk" virt_disk_device_source = "ide1" @@ -1010,6 +1015,7 @@ only coldplug no q35 no aarch64 + no s390-virtio status_error = "yes" disk_virtio_multi_ide_controller = "yes" virt_disk_device = "disk" diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_multidisks.py b/libvirt/tests/src/virtual_disks/virtual_disks_multidisks.py index 45f2b5ddb4d..4796cc111cb 100644 --- a/libvirt/tests/src/virtual_disks/virtual_disks_multidisks.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_multidisks.py @@ -37,6 +37,7 @@ from virttest.libvirt_xml import pool_xml from virttest.staging import lv_utils from virttest.utils_libvirt import libvirt_pcicontr +from virttest.utils_libvirt import libvirt_disk from virttest import libvirt_version @@ -78,6 +79,19 @@ def run(test, params, env): virsh.detach_disk(vm_name, disk.target['dev'], extra='--config', debug=True) + def _delete_scsi_disk(): + """ Helper function for wait_for in finally """ + libvirt.delete_scsi_disk() + cmd = "lsscsi|grep scsi_debug" + s1, _ = utils_misc.cmd_status_output(cmd, + shell=True, + ignore_status=False) + cmd = "lsmod|grep scsi_debug" + s2, _ = utils_misc.cmd_status_output(cmd, + shell=True, + ignore_status=False) + return s1 + s2 == 2 + def check_disk_order(targets_name): """ Check VM disk's order on pci/ccw bus. @@ -412,15 +426,14 @@ def check_vm_block_size(targets_name, log_size, phy_size): logging.error(str(e)) return False - def check_vm_discard(target_name): + def check_vm_discard(): """ Check VM discard value. - - :param target_name. Device target name. """ logging.info("Checking VM discard...") try: session = vm.wait_for_login() + target_name, _ = libvirt_disk.get_non_root_disk_name(session) cmd = ("fdisk -l /dev/{0} && mkfs.ext4 -F /dev/{0} && " "mkdir -p test && mount /dev/{0} test && " "dd if=/dev/zero of=test/file bs=1M count=300 && sync" @@ -560,15 +573,14 @@ def check_transient_disk_keyword(): if process.system(cmd, ignore_status=False, shell=True): test.fail("Check transident disk failed") - def check_restart_transient_vm(target_name): + def check_restart_transient_vm(): """ Check VM transient feature. - - :param target_name. Device target name. """ logging.info("Checking VM transident...") try: session = vm.wait_for_login() + target_name, _ = libvirt_disk.get_non_root_disk_name(session) cmd = ("fdisk -l /dev/{0} && mkfs.ext4 -F /dev/{0} && " "mkdir -p /test && mount /dev/{0} /test && " "dd if=/dev/zero of=/test/transient.txt bs=1M count=300 && sync" @@ -1591,6 +1603,7 @@ def test_device_update_boot_order(disk_type, disk_path, error_msg): # Update disk cdrom/floppy with modified boot order,it expect fail. flopy_error_msg = params.get('flopy_error_msg', "") cdrom_error_msg = params.get('cdrom_error_msg', "") + stderr_output = None try: stderr_output = virsh.update_device(vm_name, addtional_disk.xml, debug=True).stderr_text except Exception as update_device_exception: @@ -1945,7 +1958,7 @@ def test_device_update_boot_order(disk_type, disk_path, error_msg): # Check discard in VM after command. if check_discard: - check_vm_discard(device_targets[0]) + check_vm_discard() # Check pci bridge in VM after command. if check_pci_bridge: @@ -1964,7 +1977,7 @@ def test_device_update_boot_order(disk_type, disk_path, error_msg): vm.wait_for_login() if disk_transient: check_transient_disk_keyword() - check_restart_transient_vm(device_targets[0]) + check_restart_transient_vm() # If we testing hotplug, detach the disk at last. if device_at_dt_disk: for i in list(range(len(disks))): @@ -2108,7 +2121,7 @@ def _check_disk_detach(): del img["disk_dev"] else: if img["format"] == "scsi": - utils_misc.wait_for(libvirt.delete_scsi_disk, + utils_misc.wait_for(_delete_scsi_disk, 120, ignore_errors=True) elif img["format"] == "iscsi" or network_iscsi_baseimg: libvirt.setup_or_cleanup_iscsi(is_setup=False) From 69290ada6fa7a0c0af5d841b31129f90624b18cb Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 19 Dec 2023 09:37:09 -0500 Subject: [PATCH 0092/1055] virsh_detach_device: fix device discovery The disk tests used the disk target as identifier for the disk inside of the VM. However, the target is not guaranteed to show up in the guest as-is, especially given that the /dev/XdY paths are not persistent and can change between boots. Use instead a function that identifies a new disk inside of a VM as the one disk that has no root mount on itself, its partitions or volumes. Signed-off-by: Sebastian Mitterle --- .../tests/src/virsh_cmd/domain/virsh_detach_device.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device.py b/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device.py index c9f7c8501a6..5e83837ec7b 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device.py @@ -11,6 +11,7 @@ from virttest import remote from virttest import data_dir from virttest import utils_misc +from virttest.utils_libvirt.libvirt_disk import get_non_root_disk_name from virttest.utils_test import libvirt from virttest.libvirt_xml import vm_xml @@ -246,6 +247,7 @@ def _detach_device(by_alias, detach_target): ignore_status=True) device_xml = create_device_xml(params, tmp_dir, device_source) + target_name = device_target if not no_attach: s_attach = virsh.attach_device(vm_name, device_xml, flagstr="--config", debug=True).exit_status @@ -254,7 +256,10 @@ def _detach_device(by_alias, detach_target): "detach-device") vm.start() - vm.wait_for_serial_login() + session = vm.wait_for_serial_login() + if not no_attach and device == 'disk' and s_attach == 0: + target_name, _ = get_non_root_disk_name(session) + session.close() # Add acpiphp module before testing if VM's os type is rhle5.* if device in ['disk', 'cdrom']: @@ -343,7 +348,7 @@ def __interface_exists(): check_vm_after_cmd = True if device in ['disk', 'cdrom']: check_vm_after_cmd = check_vm_partition(vm, device, os_type, - device_target) + target_name) # Destroy VM. if vm.is_alive(): From 4d9b7346294831fc0d7ad4b6611e4cbcc7b4cc60 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 19 Dec 2023 12:29:07 -0500 Subject: [PATCH 0093/1055] backingchain/blockcopy_options: fix added disk discovery The tests recorded the list of disks before and after attachment. However /dev/XdY names can change between boots leading to test errors. Use instead a function that identifies a new disk inside of a VM as the one disk that has no root mount on itself, its partitions or volumes. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/backingchain/blockcopy_options.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/src/backingchain/blockcopy_options.py b/libvirt/tests/src/backingchain/blockcopy_options.py index 079eedf7df9..ee97cdbd042 100644 --- a/libvirt/tests/src/backingchain/blockcopy_options.py +++ b/libvirt/tests/src/backingchain/blockcopy_options.py @@ -42,7 +42,6 @@ def setup_blockcopy_extended_l2(): test_obj.new_image_path = image_path # start get old parts session = vm.wait_for_login() - test_obj.old_parts = utils_disk.get_parts_list(session) session.close() # attach new disk if encryption_disk: @@ -84,9 +83,8 @@ def test_blockcopy_extended_l2(): expected_value='true') # Check domain write file session = vm.wait_for_login() - new_parts = utils_disk.get_parts_list(session) - added_parts = list(set(new_parts).difference(set(test_obj.old_parts))) - utils_disk.linux_disk_check(session, added_parts[0]) + added_disk, _ = libvirt_disk.get_non_root_disk_name(session) + utils_disk.linux_disk_check(session, added_disk) session.close() def teardown_blockcopy_extended_l2(): From 8bc73f5be9c89a477b925848692f1c69fc70bbba Mon Sep 17 00:00:00 2001 From: nanli Date: Wed, 20 Dec 2023 21:21:13 +0800 Subject: [PATCH 0094/1055] fix memory numa case name Signed-off-by: nanli --- .../cfg/memory/memory_devices/virtio_mem_auto_placement.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_auto_placement.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_auto_placement.cfg index f634e0eb3bf..d1fc1cd9110 100644 --- a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_auto_placement.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_auto_placement.cfg @@ -33,7 +33,7 @@ mode_attrs = "" tuning_attrs = "'numa_memory': {${mode_attrs} 'placement': '${placement}'}" variants: - - with_2_numa_nodes: + - with_numa: numa_mem = 1048576 mem_value = 2097152 current_mem = 2097152 From 2637f5a12e28ae7d8f88673e4b58ba5c2aef1f16 Mon Sep 17 00:00:00 2001 From: Yan Fu Date: Thu, 21 Dec 2023 10:55:54 +0800 Subject: [PATCH 0095/1055] Fix the error use of 'utils_split_daemons.is_modular_daemon()' Signed-off-by: Yan Fu --- libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py b/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py index 72dd17f32c6..09509cb194c 100644 --- a/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py +++ b/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py @@ -572,7 +572,7 @@ def check_record_save_restore_guest_log(): if restart_libvirtd or stop_libvirtd: virtlogd_pid = check_service_status("virtlogd", service_start=True) logging.info("virtlogd pid: %s", virtlogd_pid) - service_name = "virtqemud" if utils_split_daemons.is_modular_daemon else "libvirtd" + service_name = "virtqemud" if utils_split_daemons.is_modular_daemon() else "libvirtd" check_service_status(service_name, service_start=True) # Restart libvirtd to make change valid. From eb04dc3b665149c7a814c0ae36094c87d8a65382 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Fri, 22 Dec 2023 01:00:15 -0500 Subject: [PATCH 0096/1055] guest_os_booting: add new case of smbios feature This case is to verify the smbios element. Signed-off-by: Meina Li --- .../firmware_configuration/smbios_mode.cfg | 35 ++++ .../firmware_configuration/smbios_mode.py | 167 ++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 libvirt/tests/cfg/guest_os_booting/firmware_configuration/smbios_mode.cfg create mode 100644 libvirt/tests/src/guest_os_booting/firmware_configuration/smbios_mode.py diff --git a/libvirt/tests/cfg/guest_os_booting/firmware_configuration/smbios_mode.cfg b/libvirt/tests/cfg/guest_os_booting/firmware_configuration/smbios_mode.cfg new file mode 100644 index 00000000000..88eda2e886f --- /dev/null +++ b/libvirt/tests/cfg/guest_os_booting/firmware_configuration/smbios_mode.cfg @@ -0,0 +1,35 @@ +- guest_os_booting.smbios_mode: + type = smbios_mode + start_vm = no + variants: + - positive_test: + variants smbios_mode: + - emulate: + os_dict = {'smbios_mode': 'emulate'} + expected_system_info = {'Manufacturer': 'Red Hat', 'Product Name': 'KVM', 'UUID': '%s', 'Family': 'Red Hat Enterprise Linux'} + - host: + os_dict = {'smbios_mode': 'host'} + expected_system_info = {'Manufacturer': '%s', 'Product Name': '%s', 'SKU Number': '%s', 'Family': '%s'} + - sysinfo: + with_sysinfo = "yes" + os_dict = {'smbios_mode': 'sysinfo'} + sysinfo_type = {'type': 'smbios'} + sysinfo_bios = {'bios_entry': [{'entry': 'LENOVO', 'entry_name': 'vendor'}, {'entry': '6FET82WW (3.12 )', 'entry_name': 'version'}, {'entry': '02/08/2012', 'entry_name': 'date'}]} + sysinfo_system = {'system_entry': [{'entry': 'Fedora', 'entry_name': 'manufacturer'}, {'entry': 'Virt-Manager', 'entry_name': 'product'}, {'entry': '0.8.2-3.fc14', 'entry_name': 'version'}, {'entry': '32,dfcb37-5af1-552b-357c-be8c3aa38310', 'entry_name': 'serial'}, {'entry': '%s', 'entry_name': 'uuid'}, {'entry': '1234567890', 'entry_name': 'sku'}, {'entry': 'Red Hat', 'entry_name': 'family'}]} + sysinfo_baseBoard = {'baseBoard_entry': [{'entry': 'SUN', 'entry_name': 'manufacturer'}, {'entry': '20BE0061MC', 'entry_name': 'product'}, {'entry': '0B98401 Pro', 'entry_name': 'version'}, {'entry': 'W1KS427111E', 'entry_name': 'serial'}, {'entry': 'abcde', 'entry_name': 'asset'}, {'entry': 'edcba', 'entry_name': 'location'}]} + sysinfo_chassis = {'chassis_entry': [{'entry': 'Dell Inc.', 'entry_name': 'manufacturer'}, {'entry': '2.12', 'entry_name': 'version'}, {'entry': '65X0XF2', 'entry_name': 'serial'}, {'entry': '40000101', 'entry_name': 'asset'}, {'entry': 'Type3Sku1', 'entry_name': 'sku'}]} + sysinfo_oemStrings = {'oemStrings_entry': [{'entry': 'myappname:some arbitrary data'}, {'entry': 'otherappname:more arbitrary data'}]} + - negative_test: + variants: + - invalid_mode: + os_dict = {'smbios_mode': 'abc'} + error_msg = "unknown smbios mode 'abc'" + - without_sysinfo_snippet: + os_dict = {'smbios_mode': 'sysinfo'} + error_msg = "Domain .* sysinfo are not available" + - with_mismatch_uuid: + with_sysinfo = "yes" + os_dict = {'smbios_mode': 'sysinfo'} + sysinfo_type = {'type': 'smbios'} + sysinfo_system = {'system_entry': [{'entry': '11111111-1111-1111-1111-111111111111', 'entry_name': 'uuid'}]} + error_msg = "UUID mismatch between and " diff --git a/libvirt/tests/src/guest_os_booting/firmware_configuration/smbios_mode.py b/libvirt/tests/src/guest_os_booting/firmware_configuration/smbios_mode.py new file mode 100644 index 00000000000..d8f567af33e --- /dev/null +++ b/libvirt/tests/src/guest_os_booting/firmware_configuration/smbios_mode.py @@ -0,0 +1,167 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Meina Li +import re + +from avocado.utils import process + +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml import xcepts + +from provider.guest_os_booting import guest_os_booting_base as guest_os + + +def run(test, params, env): + """ + This case is to verity the smbios feature of os. + 1) Prepare a guest xml with smbios features. + 2) Start the guest and login it. + 3) Check smbios data in guest and compare it with expected one. + """ + def check_sysinfo_mode_result(): + """ + Get the expected smbios data + """ + sysinfo_elements = [bios_entry, system_entry, baseBoard_entry, + chassis_entry, oemStrings_entry] + for item in sysinfo_elements: + item_key = list(item)[0] + item_value = item[item_key] + expected_smbios_data = {} + for i in range(len(item_value)): + if item_key == "oemStrings_entry": + expected_smbios_data.update({i: item_value[i]['entry']}) + else: + expected_smbios_data.update({item_value[i]['entry_name']: item_value[i]['entry']}) + # Check sysinfo in guest + entry_type = item_key.split('_')[0] + compare_smbios_data(entry_type, expected_smbios_data) + + def get_smbios_data(entry_type, smbios_output): + """ + Get the smbios data for host or guest. + + :params entry_type: the entry type of smbios data + :params smbios_output: the output of dmidecode smbios data + :return: return the smbios data for from guest + """ + smbios_data = {} + for line in str(smbios_output).splitlines(): + line = line.strip() + # Exclude lines that cannot be parsed into dict + pattern = re.compile(r'^(.*?):\s+(.*)$') + match = pattern.match(line) + if match: + key, value = match.groups() + smbios_data[key] = value + return smbios_data + + def get_expected_smbios_data(vmxml, smbios_mode): + """ + Check the hardware and firmware info in guest by dmidecode. + + :params vmxml: the xml of guest + :params smbios_mode: the testing smbios mode + :return: a tuple with entry_type and expected_smbios_data + """ + entry_type = "system" + if smbios_mode == "emulate": + expected_smbios_data = eval(params.get("expected_system_info") % vmxml.uuid) + else: + dmidecode_cmd = "dmidecode -t %s" % entry_type + host_system = process.run(dmidecode_cmd).stdout_text + system_info = get_smbios_data(entry_type, host_system) + expected_smbios_data = eval(params.get("expected_system_info") % + (system_info["Manufacturer"], system_info["Product Name"], + system_info["SKU Number"], system_info["Family"])) + return entry_type, expected_smbios_data + + def compare_smbios_data(entry_type, expected_smbios_data): + """ + Compare the smbios data for from guest with the guest xml + + :params entry_type: the entry type of smbios data + :params expected_smbios_data: the expected smbios data got from guest xml + """ + if entry_type == "oemStrings": + dmidecode_cmd = "dmidecode -t 11" + else: + dmidecode_cmd = "dmidecode -t %s" % entry_type + session = vm.wait_for_login() + smbios_output = session.cmd_status_output(dmidecode_cmd) + smbios_data = get_smbios_data(entry_type, smbios_output[1]) + session.close() + test.log.debug(f"The smbios data of guest for {smbios_mode} mode is:" + f"{smbios_data}") + # The keys are not same for sysinfo smbios mode. For example, "date" and "Release Date". + # So here use length to check the matched status. + match_values = {} + test.log.debug(f"The expected smbios data for {smbios_mode} is: {expected_smbios_data}") + for key, value in expected_smbios_data.items(): + for actual_value in smbios_data.values(): + if value == actual_value: + match_values[key] = actual_value + if len(match_values) != len(expected_smbios_data): + test.fail(f"The {smbios_data} is not matched with the expected data {expected_smbios_data}.") + else: + test.log.debug(f"The smbios data of {entry_type} in guest is expected.") + + vm_name = params.get("main_vm") + os_dict = eval(params.get("os_dict", "{}")) + smbios_mode = params.get("smbios_mode") + error_msg = params.get("error_msg", "") + with_sysinfo = "yes" == params.get("with_sysinfo", "no") + type_entry = eval(params.get("sysinfo_type", "{}")) + bios_entry = eval(params.get("sysinfo_bios", "{}")) + baseBoard_entry = eval(params.get("sysinfo_baseBoard", "{}")) + chassis_entry = eval(params.get("sysinfo_chassis", "{}")) + oemStrings_entry = eval(params.get("sysinfo_oemStrings", "{}")) + + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + # Prepare sysinfo xml if necessary + sysinfo_dict = {} + if smbios_mode == "sysinfo": + system_entry = eval(params.get("sysinfo_system") % vmxml.uuid) + else: + system_entry = eval(params.get("sysinfo_system", "{}")) + if with_sysinfo: + sysinfo_dict = {**type_entry, **bios_entry, **system_entry, + **baseBoard_entry, **chassis_entry, **oemStrings_entry} + sysinfo_xml = vm_xml.VMSysinfoXML() + sysinfo_xml.setup_attrs(**sysinfo_dict) + vmxml.sysinfo = sysinfo_xml + # Prepare os xml with smbios + try: + vmxml.setup_attrs(os=os_dict) + vmxml.sync() + virsh.dumpxml(vm_name, debug=True) + except xcepts.LibvirtXMLError as details: + if error_msg and error_msg in str(details): + test.log.info("Get expected error message: %s.", error_msg) + return + else: + test.fail("Failed to define the guest because error:%s" % str(details)) + if error_msg: + guest_os.check_vm_startup(vm, vm_name, error_msg) + return + else: + guest_os.check_vm_startup(vm, vm_name) + test.log.debug(f"The current dumpxml is {vmxml}") + if smbios_mode == "sysinfo": + check_sysinfo_mode_result() + else: + entry_type, expected_smbios_data = get_expected_smbios_data(vmxml, smbios_mode) + compare_smbios_data(entry_type, expected_smbios_data) + finally: + if vm.is_alive(): + vm.destroy() + bkxml.sync() From 96515ad0c7a944b9a0090502c81cfb70edf8f704 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Fri, 22 Dec 2023 08:34:38 -0500 Subject: [PATCH 0097/1055] passt_attach_detach: fix for multi-arch Update test cases to run tests on specific host interface. Fix parameters for s390x. Signed-off-by: Sebastian Mitterle --- .../virtual_network/passt/passt_attach_detach.cfg | 3 +++ .../virtual_network/passt/passt_attach_detach.py | 15 ++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg index 4b0062b4d56..9003f3b0f14 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg @@ -45,3 +45,6 @@ conn_check_args_1 = ('TCP6', 'localhost', 31339, 41339, True, None) conn_check_args_2 = ('UDP4', 'localhost', 2025, 2025, True, None) conn_check_args_3 = ('UDP6', 'localhost', 2025, 2025, True, None) + s390-virtio: + iface_attrs = {'model': 'virtio', 'ips': ${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, 'alias': ${alias}, 'type_name': 'user', 'portForwards': ${portForwards}} + vm_iface = enc1 diff --git a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py index 153e644084c..e060a8a7816 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py +++ b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py @@ -65,17 +65,17 @@ def run(test, params, env): scenario = params.get('scenario') virsh_uri = params.get('virsh_uri') add_iface = 'yes' == params.get('add_iface', 'no') - host_ip = utils_net.get_host_ip_address(ip_ver='ipv4') - host_ip_v6 = utils_net.get_host_ip_address(ip_ver='ipv6') + host_iface = params.get('host_iface') + host_iface = host_iface if host_iface else utils_net.get_net_if( + state="UP")[0] + host_ip = utils_net.get_ip_address_by_interface(host_iface, ip_ver='ipv4') + host_ip_v6 = utils_net.get_ip_address_by_interface(host_iface, ip_ver='ipv6') iface_attrs = eval(params.get('iface_attrs')) params['socket_dir'] = socket_dir = eval(params.get('socket_dir')) params['proc_checks'] = proc_checks = eval(params.get('proc_checks', '{}')) vm_iface = params.get('vm_iface', 'eno1') mtu = params.get('mtu') outside_ip = params.get('outside_ip') - host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state="UP")[0] log_file = f'/run/user/{user_id}/passt.log' iface_attrs['backend']['logFile'] = log_file iface_attrs['source']['dev'] = host_iface @@ -124,7 +124,7 @@ def run(test, params, env): test.fail(f'Logfile of passt "{log_file}" not created') session = vm.wait_for_serial_login(timeout=60) - passt.check_vm_ip(iface_attrs, session, host_iface) + passt.check_vm_ip(iface_attrs, session, host_iface, vm_iface) passt.check_vm_mtu(session, vm_iface, mtu) passt.check_default_gw(session) passt.check_nameserver(session) @@ -138,7 +138,8 @@ def run(test, params, env): firewalld.stop() LOG.debug(f'Service status of firewalld: {firewalld.status()}') passt.check_connection(vm, vm_iface, - ['TCP4', 'TCP6', 'UDP4', 'UDP6']) + ['TCP4', 'TCP6', 'UDP4', 'UDP6'], + host_iface) if 'portForwards' in iface_attrs: passt.check_portforward(vm, host_ip, params) From 658e8224f45b79c9ea4340cc88f7c09b66c4453a Mon Sep 17 00:00:00 2001 From: Hu Shuai Date: Thu, 28 Dec 2023 14:44:59 +0800 Subject: [PATCH 0098/1055] memory: Fix property to correctly check hugepage size The **size** property should be used to check the size of hugepage intead of **hugetlbsize**. Signed-off-by: Hu Shuai --- .../src/memory/memory_backing/memory_source_and_allocation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/memory/memory_backing/memory_source_and_allocation.py b/libvirt/tests/src/memory/memory_backing/memory_source_and_allocation.py index a87de5370a2..e7180d87644 100644 --- a/libvirt/tests/src/memory/memory_backing/memory_source_and_allocation.py +++ b/libvirt/tests/src/memory/memory_backing/memory_source_and_allocation.py @@ -139,12 +139,12 @@ def check_hugepage(params, mem_name): hugepage = str(json.loads(result)['return']) result = virsh.qemu_monitor_command( - vm_name, check_thread % (mem_name, 'hugetlbsize'), debug=True).stdout_text + vm_name, check_thread % (mem_name, 'size'), debug=True).stdout_text hugepage_size = str(json.loads(result)['return']) if hugepage != 'True': test.fail("Expect to get hugepage 'True', but got '%s'" % hugepage) - if hugepage_size != memory_value: + if int(hugepage_size) != int(memory_value) * 1024: test.fail("Expect to get hugepage size '%s', but got '%s'" % ( hugepage_size, memory_value)) test.log.debug("Get correct hugepage '%s' and hugepage_size '%s'", From a44b0b192a8a53217d930c6578446db17c936008 Mon Sep 17 00:00:00 2001 From: Hu Shuai Date: Thu, 28 Dec 2023 16:32:35 +0800 Subject: [PATCH 0099/1055] numa: Fix nodeset sequence set() is unordered, list() cannot sort data, so there is no guarantee that nodes will be spliced in order. Use sort() instead. Signed-off-by: Hu Shuai --- .../guest_numa_node_tuning/host_guest_mixed_memory_binding.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.py b/libvirt/tests/src/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.py index 6b217d1530f..999c47c41fa 100644 --- a/libvirt/tests/src/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.py +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.py @@ -285,7 +285,7 @@ def check_cgroup(numatest_obj): memnode_mode != 'restrictive'): mem_nodeset = numatest_obj.params['nodeset'] memnode_nodeset = eval(numatest_obj.params['numa_memnode'])[0].get('nodeset') - nodeset = ','.join(list(set(mem_nodeset).union(set(memnode_nodeset)))) + nodeset = ','.join(sorted(set(mem_nodeset).union(set(memnode_nodeset)))) nodeset = numa_base.convert_to_string_with_dash(nodeset) for item in [emulator_cpuset_mems, vcpu0_cpuset_mems, vcpu1_cpuset_mems]: if item != nodeset: From a248efd546c8e75c518e332570832195ddf42d66 Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 20 Sep 2023 21:33:20 +0800 Subject: [PATCH 0100/1055] migration: Add case about abort migration VIRT-298383 - [VM migration][domjobabort] abort migration job with wrong API flag Signed-off-by: lcheng --- .../abort_by_domjobabort_on_target.cfg | 5 ++- .../abort_migration_with_wrong_api_flag.cfg | 39 +++++++++++++++++++ .../src/migration/async_job/async_job.py | 23 +++++++++++ provider/migration/migration_base.py | 10 +++-- 4 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 libvirt/tests/cfg/migration/async_job/abort_migration_with_wrong_api_flag.cfg create mode 100644 libvirt/tests/src/migration/async_job/async_job.py diff --git a/libvirt/tests/cfg/migration/abort_precopy_migration/abort_by_domjobabort_on_target.cfg b/libvirt/tests/cfg/migration/abort_precopy_migration/abort_by_domjobabort_on_target.cfg index 81072bab160..25e87fcaf3e 100644 --- a/libvirt/tests/cfg/migration/abort_precopy_migration/abort_by_domjobabort_on_target.cfg +++ b/libvirt/tests/cfg/migration/abort_precopy_migration/abort_by_domjobabort_on_target.cfg @@ -36,9 +36,10 @@ virsh_migrate_options = '--live --verbose' variants: - with_precopy: - action_during_mig = '[{"func": "libvirt_network.check_established", "after_event": "iteration: '1'", "func_param": "params"}, {"func": "do_domjobabort", "func_param": "params", "need_sleep_time": "5"}]' + action_during_mig = '[{"func": "do_domjobabort", "after_event": "iteration: '1'", "func_param": "params", "need_sleep_time": "5"}]' domjobabort_err_msg = "cannot acquire state change lock .*held by monitor=remoteDispatchDomainMigratePrepare3Params" - with_postcopy: postcopy_options = '--postcopy --timeout 10 --timeout-postcopy' - action_during_mig = '[{"func": "libvirt_network.check_established", "after_event": "iteration: '1'", "func_param": "params"}, {"func": "do_domjobabort", "func_param": "params", "need_sleep_time": "10"}]' + domjobabort_options = '--postcopy' + action_during_mig = '[{"func": "do_domjobabort", "after_event": "iteration: '1'", "func_param": "params", "need_sleep_time": "10"}]' domjobabort_err_msg = "cannot acquire state change lock .*held by monitor=remoteDispatchDomainMigrateFinish3Params" diff --git a/libvirt/tests/cfg/migration/async_job/abort_migration_with_wrong_api_flag.cfg b/libvirt/tests/cfg/migration/async_job/abort_migration_with_wrong_api_flag.cfg new file mode 100644 index 00000000000..6c0dd1972ba --- /dev/null +++ b/libvirt/tests/cfg/migration/async_job/abort_migration_with_wrong_api_flag.cfg @@ -0,0 +1,39 @@ +- migration.async_job.abort_migration_with_wrong_api_flag: + type = async_job + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + check_network_accessibility_after_mig = "yes" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + status_error = "no" + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + domjobabort_on_src = "yes" + variants: + - abort_postcopy_migration_by_domjobabort_without_postcopy: + virsh_migrate_options = '--live --p2p --verbose --postcopy --timeout 3 --timeout-postcopy --postcopy-bandwidth 10 --bandwidth 10' + domjobabort_err_msg = "cannot abort migration in post-copy mode" + action_during_mig = '[{"func": "do_domjobabort", "after_event": "iteration: '1'", "func_param": "params", "need_sleep_time": "5"}, {"func": "set_migrate_speed_to_high", "func_param": "params"}]' + - abort_precopy_migration_by_domjobabort_with_postcopy: + domjobabort_err_msg = "current job is not outgoing migration in post-copy mode" + virsh_migrate_options = '--live --p2p --verbose --bandwidth 3' + domjobabort_options = "--postcopy" + action_during_mig = '[{"func": "do_domjobabort", "func_param": "params"}, {"func": "set_migrate_speed_to_high", "func_param": "params"}]' diff --git a/libvirt/tests/src/migration/async_job/async_job.py b/libvirt/tests/src/migration/async_job/async_job.py new file mode 100644 index 00000000000..c0a8c885405 --- /dev/null +++ b/libvirt/tests/src/migration/async_job/async_job.py @@ -0,0 +1,23 @@ +from provider.migration import base_steps + + +def run(test, params, env): + """ + Test async job: + + 1. abort_migration_with_wrong_api_flag case: To verify that precopy + migration can't be aborted by domjobabort with --postcopy, postcopy + migration can't be aborted by domjobabort without --postcopy. + + """ + vm_name = params.get("migrate_main_vm") + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + migration_obj.setup_connection() + migration_obj.run_migration() + migration_obj.verify_default() + finally: + migration_obj.cleanup_connection() diff --git a/provider/migration/migration_base.py b/provider/migration/migration_base.py index 0d5198f1d4f..f14f26d8ec3 100644 --- a/provider/migration/migration_base.py +++ b/provider/migration/migration_base.py @@ -705,12 +705,14 @@ def do_domjobabort(params): dest_uri = params.get("virsh_migrate_desturi") vm_name = params.get("main_vm") domjobabort_err_msg = params.get("domjobabort_err_msg") - postcopy_options = params.get("postcopy_options") + domjobabort_on_src = "yes" == params.get("domjobabort_on_src", "no") + domjobabort_options = params.get("domjobabort_options", "") - if postcopy_options: - ret = virsh.domjobabort(vm_name, option="--postcopy", debug=True, uri=dest_uri) + if domjobabort_on_src: + uri = None else: - ret = virsh.domjobabort(vm_name, debug=True, uri=dest_uri) + uri = dest_uri + ret = virsh.domjobabort(vm_name, options=domjobabort_options, debug=True, uri=uri) libvirt.check_result(ret, expected_fails=domjobabort_err_msg, check_both_on_error=True) From fe10e1b49e4d7cf1e190daa03dca588a09523922 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 2 Jan 2024 06:56:13 -0500 Subject: [PATCH 0101/1055] passt/connection_between_2vms: fix config for s390x No acpi on s390x and interfaces are named differently (qeth and virtio enc+devno). Signed-off-by: Sebastian Mitterle --- .../passt/passt_connectivity_between_2vms.cfg | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_connectivity_between_2vms.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_connectivity_between_2vms.cfg index 09cf6bd6d07..239c98be175 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_connectivity_between_2vms.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_connectivity_between_2vms.cfg @@ -41,3 +41,11 @@ conn_check_args_1 = ('TCP6', server_default_gw_v6, vm_c_iface, 41335, 41335) conn_check_args_2 = ('UDP4', server_default_gw, None, 21335, 21335) conn_check_args_3 = ('UDP6', server_default_gw_v6, vm_c_iface, 21335, 21335) + s390-virtio: + iface_attrs = {'model': 'virtio', **${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, 'type_name': 'user', **${portForwards}} + iface_c_attrs = {'model': 'virtio', **${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, 'type_name': 'user'} + vm_c_iface = enc1 + conn_check_args_0 = ('TCP4', server_default_gw, None, 41335, 41335) + conn_check_args_1 = ('TCP6', server_default_gw_v6, vm_c_iface, 41335, 41335) + conn_check_args_2 = ('UDP4', server_default_gw, None, 21335, 21335) + conn_check_args_3 = ('UDP6', server_default_gw_v6, vm_c_iface, 21335, 21335) From d2e730a201428d8169f853994d45c9d5f51633e2 Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 3 Jan 2024 15:08:01 +0800 Subject: [PATCH 0102/1055] migration: Fix wrong event Wrong event in action_during_mig. Signed-off-by: lcheng --- .../migration_with_copy_storage/migration_bandwidth_limit.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration_with_copy_storage/migration_bandwidth_limit.cfg b/libvirt/tests/cfg/migration_with_copy_storage/migration_bandwidth_limit.cfg index b95c10945eb..097a3ee2072 100644 --- a/libvirt/tests/cfg/migration_with_copy_storage/migration_bandwidth_limit.cfg +++ b/libvirt/tests/cfg/migration_with_copy_storage/migration_bandwidth_limit.cfg @@ -33,7 +33,7 @@ compare_to_value = "${bandwidth}" check_item = "bandwidth" check_item_value = "20971520" - action_during_mig = '[{"func": "libvirt_disk.check_item_by_blockjob", "after_event": "block-job", "before_event": "migration-iteration", "func_param": "params", "wait_for_after_event_timeout": "600"}, {"func": "check_domjobinfo_during_mig", "after_event": "migration-iteration", "func_param": "params"}]' + action_during_mig = '[{"func": "libvirt_disk.check_item_by_blockjob", "after_event": "block-job", "func_param": "params", "wait_for_after_event_timeout": "600"}, {"func": "check_domjobinfo_during_mig", "after_event": "migration-iteration", "func_param": "params"}]' migrate_start_state = "running" variants: - p2p: From 58e0d9284d06d66a1b072ea9c5bc83534ef5decb Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 3 Jan 2024 04:14:39 -0500 Subject: [PATCH 0103/1055] passt/reconnect: fix on multi-arch No ACPI on s390x and interfaces are named differently. Pass VM interface name to avoid auto-naming. Pass Host interface name to restrict gateway selection. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg | 3 +++ libvirt/tests/src/virtual_network/passt/passt_reconnect.py | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg index 023d3911a4b..06f3bd3a99a 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg @@ -40,3 +40,6 @@ conn_check_args_1 = ('TCP6', 'localhost', 31339, 41339, True, None) conn_check_args_2 = ('UDP4', 'localhost', 2025, 2025, True, None) conn_check_args_3 = ('UDP6', 'localhost', 2025, 2025, True, None) + s390-virtio: + iface_attrs = {'model': 'virtio', **${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, **${alias}, 'type_name': 'user', **${portForwards}} + vm_iface = enc1 diff --git a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py index 0531d8806ba..733d5d2ce9f 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py +++ b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py @@ -109,7 +109,7 @@ def run(test, params, env): test.fail(f'Logfile of passt "{log_file}" not created') session = vm.wait_for_serial_login(timeout=60) - passt.check_vm_ip(iface_attrs, session, host_iface) + passt.check_vm_ip(iface_attrs, session, host_iface, vm_iface) passt.check_vm_mtu(session, vm_iface, mtu) passt.check_default_gw(session) passt.check_nameserver(session) @@ -124,7 +124,8 @@ def run(test, params, env): LOG.debug(f'Service status of firewalld: {firewalld.status()}') passt.check_connection(vm, vm_iface, - ['TCP4', 'TCP6', 'UDP4', 'UDP6']) + ['TCP4', 'TCP6', 'UDP4', 'UDP6'], + host_iface) if 'portForwards' in iface_attrs: passt.check_portforward(vm, host_ip, params) From 89580bc656493f86e3df0f5b6d237c9297bcc621 Mon Sep 17 00:00:00 2001 From: lcheng Date: Thu, 4 Jan 2024 11:31:55 +0800 Subject: [PATCH 0104/1055] migration: Fix no directory issue Update case to avoid "No such file or directory" issue. Signed-off-by: lcheng --- .../migration_with_copy_storage/precreate_none_target_disk.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libvirt/tests/src/migration_with_copy_storage/precreate_none_target_disk.py b/libvirt/tests/src/migration_with_copy_storage/precreate_none_target_disk.py index 406c63162c2..874911d5a25 100644 --- a/libvirt/tests/src/migration_with_copy_storage/precreate_none_target_disk.py +++ b/libvirt/tests/src/migration_with_copy_storage/precreate_none_target_disk.py @@ -8,6 +8,7 @@ # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import os import re from avocado.utils import process @@ -74,6 +75,9 @@ def setup_test(): migrate_desturi_type = params.get("migrate_desturi_type", "tcp") test.log.info("Setup steps.") + disk_source = os.path.dirname(disk_source_name) + if not os.path.exists(disk_source): + os.mkdir(disk_source) cmd = "qemu-img convert -f qcow2 -O %s %s %s" % (disk_format, blk_source, disk_source_name) process.run(cmd, shell=True) From 8c700cd0d6bfa61e667ac3256929a033057bc21f Mon Sep 17 00:00:00 2001 From: nanli Date: Thu, 30 Nov 2023 12:40:06 +0800 Subject: [PATCH 0105/1055] fix memory lifecycle memory allocation issue Feaure owner updated polarion case: Automate **-297048: modify steps for ****-15480 Signed-off-by: nanli --- .../lifecycle_with_memory_allocation.cfg | 3 +- .../lifecycle_with_memory_allocation.py | 59 ++++++++----------- 2 files changed, 26 insertions(+), 36 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_allocation/lifecycle_with_memory_allocation.cfg b/libvirt/tests/cfg/memory/memory_allocation/lifecycle_with_memory_allocation.cfg index 0e3e1cbb2fb..eb6ca860617 100644 --- a/libvirt/tests/cfg/memory/memory_allocation/lifecycle_with_memory_allocation.cfg +++ b/libvirt/tests/cfg/memory/memory_allocation/lifecycle_with_memory_allocation.cfg @@ -5,7 +5,7 @@ current_mem = 1843200 current_mem_unit = 'KiB' max_mem_slots = 16 - max_mem = 15242880 + max_mem = 15360000 max_mem_unit = 'KiB' numa_mem = 1048576 variants case: @@ -27,3 +27,4 @@ max_mem_attr = "'max_mem_rt': ${max_mem}, 'max_mem_rt_slots': ${max_mem_slots}, 'max_mem_rt_unit': '${max_mem_unit}'" vm_attrs = {${max_mem_attr},'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} error_msg = "At least one numa node has to be configured when enabling memory hotplug" + expect_xpath = [{'element_attrs':[".//currentMemory[@unit='${current_mem_unit}']"],'text':'${current_mem}'}, {'element_attrs':[".//memory[@unit='${mem_unit}']"],'text':'${mem_value}'}, {'element_attrs':[".//cell[@memory='${mem_value}']"]}] diff --git a/libvirt/tests/src/memory/memory_allocation/lifecycle_with_memory_allocation.py b/libvirt/tests/src/memory/memory_allocation/lifecycle_with_memory_allocation.py index 5a9ed6c38fd..c64e6b31f6e 100644 --- a/libvirt/tests/src/memory/memory_allocation/lifecycle_with_memory_allocation.py +++ b/libvirt/tests/src/memory/memory_allocation/lifecycle_with_memory_allocation.py @@ -9,6 +9,7 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ import os +import re from virttest import virsh from virttest import libvirt_version @@ -30,7 +31,7 @@ def run(test, params, env): 3:with numa topology """ - def run_positive_test(): + def run_test(): """ Start guest Check the qemu cmd line @@ -39,7 +40,16 @@ def run_positive_test(): test.log.info("TEST_STEP1: Define and start vm") vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) vmxml.setup_attrs(**vm_attrs) - vmxml.sync() + + try: + vmxml.sync() + except Exception as e: + if not libvirt_version.version_compare(9, 6, 0) and mem_config == "with_maxmemory": + if not re.search(error_msg, str(e)): + test.fail("Expected to get '%s', but got '%s'" % (error_msg, e)) + return + else: + test.fail("Expect define successfully, but failed with '%s'" % e) if not vm.is_alive(): vm.start() @@ -51,18 +61,21 @@ def run_positive_test(): check_dominfo() check_qemu_cmdline() - test.log.info("TEST_STEP3:Check vm reboot and memory config") + test.log.info("TEST_STEP3:Check vm memory config") + check_mem_config() + + test.log.info("TEST_STEP4:Check vm reboot and memory config") virsh.reboot(vm_name, ignore_status=False, debug=True) vm.wait_for_login().close() check_mem_config() - test.log.info("TEST_STEP4:Check vm suspend & resume and memory config") + test.log.info("TEST_STEP5:Check vm suspend & resume and memory config") virsh.suspend(vm_name, ignore_status=False, debug=True) virsh.resume(vm_name, ignore_status=False, debug=True) vm.wait_for_login().close() check_mem_config() - test.log.info("TEST_STEP5:Check vm save & restore and memory config") + test.log.info("TEST_STEP6:Check vm save & restore and memory config") if os.path.exists(save_file): os.remove(save_file) virsh.save(vm_name, save_file, ignore_status=False, debug=True) @@ -70,22 +83,22 @@ def run_positive_test(): vm.wait_for_login().close() check_mem_config() - test.log.info("TEST_STEP6:Check vm managedsave,start and memory config") + test.log.info("TEST_STEP7:Check vm managedsave,start and memory config") virsh.managedsave(vm_name, ignore_status=False, debug=True) vm.start() vm.wait_for_login().close() check_mem_config() - test.log.info("TEST_STEP7:Check libvirtd restart and memory config") + test.log.info("TEST_STEP8:Check libvirtd restart and memory config") libvirtd = utils_libvirtd.Libvirtd() libvirtd.restart() vm.wait_for_login().close() check_mem_config() - test.log.info("TEST_STEP8: Destroy vm ") + test.log.info("TEST_STEP9: Destroy vm ") virsh.destroy(vm_name, ignore_status=False, debug=True) - def teardown_positive_test(): + def teardown_test(): """ Clean data. """ @@ -95,27 +108,6 @@ def teardown_positive_test(): vm.undefine(options='--nvram --managed-save') bkxml.sync() - def run_negative_test(): - """ - Define vm and check result. - """ - test.log.info("TEST_STEP1: Define vm with maxMemory and no numa") - vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) - vmxml.setup_attrs(**vm_attrs) - test.log.debug("Define vm with %s.", vmxml) - - cmd_result = virsh.define(vmxml.xml, debug=True) - - test.log.info("TEST_STEP2: Check error message") - libvirt.check_result(cmd_result, error_msg) - - def teardown_negative_test(): - """ - Clean data. - """ - test.log.info("TEST_TEARDOWN: Clean up env.") - bkxml.sync() - def check_qemu_cmdline(): """ Check expected memory value in qemu cmd line. @@ -126,7 +118,8 @@ def check_qemu_cmdline(): expected_str = r"-m size=%sk" % mem_value else: expected_str = r"-m %s" % str(int(mem_value/1024)) - elif mem_config == "with_numa": + elif mem_config == "with_numa" or \ + mem_config == "with_maxmemory" and libvirt_version.version_compare(9, 6, 0): expected_str = r"-m size=%dk,slots=%d,maxmem=%dk" % ( int(mem_value), max_mem_slots, int(max_mem)) @@ -160,7 +153,6 @@ def check_mem_config(): vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) bkxml = vmxml.copy() - case = params.get("case") error_msg = params.get("error_msg") mem_value = int(params.get("mem_value")) current_mem = int(params.get("current_mem")) @@ -171,9 +163,6 @@ def check_mem_config(): vm_attrs = eval(params.get("vm_attrs")) save_file = "/tmp/%s.save" % vm_name - run_test = eval("run_%s" % case) - teardown_test = eval("teardown_%s" % case) - try: run_test() From 386a412dbf96bc850e1f34d2c56b85aeece695fa Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Thu, 4 Jan 2024 05:21:19 -0500 Subject: [PATCH 0106/1055] passt/negative_setting: create interface for testing The test assumed the existence of a specific interface on the host. Instead have the test create one for testing to make the test more host-independent. Signed-off-by: Sebastian Mitterle --- .../virtual_network/passt/passt_negative_setting.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py b/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py index 136f114019a..88a8b9ee52e 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py +++ b/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py @@ -18,6 +18,7 @@ from provider.virtual_network import passt LOG = logging.getLogger('avocado.' + __name__) +DOWN_IFACE_NAME = "br1234" def run(test, params, env): @@ -73,12 +74,9 @@ def run(test, params, env): if scenario == 'rm_passt_pgk': utils_package.package_remove('passt') elif scenario == 'inactive_host_iface': - inactive_iface_list = [iface for iface in host_iface_list - if iface['operstate'] == 'DOWN'] - if not inactive_iface_list: - test.error('No inactive interface on host') - host_iface = inactive_iface_list[0]['ifname'] - iface_attrs['source']['dev'] = host_iface + process.run(f'ip link add name {DOWN_IFACE_NAME} type bridge', + shell=True, ignore_status=False) + iface_attrs['source']['dev'] = DOWN_IFACE_NAME elif scenario == 'non_exist_bind_ip': bind_ip = '' @@ -142,3 +140,5 @@ def _get_test_ip(): else: del virsh_ins utils_selinux.set_status(selinux_status) + process.run(f'ip link del {DOWN_IFACE_NAME}', + shell=True, ignore_status=True) From 884a9b72f8149f96b2ddf89f7ceaf90153b541c0 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Sun, 7 Jan 2024 22:22:38 -0500 Subject: [PATCH 0107/1055] On S390, scm devices must be ignored, since they are only used in combination with z/OS as confirmed by IBM engineers and PO. Signed-off-by: liang-cong-red-hat --- .../virsh_cmd/nodedev/virsh_nodedev_list.cfg | 1 + .../virsh_cmd/nodedev/virsh_nodedev_list.py | 26 +++++++++++++++++++ spell.ignore | 1 + 3 files changed, 28 insertions(+) diff --git a/libvirt/tests/cfg/virsh_cmd/nodedev/virsh_nodedev_list.cfg b/libvirt/tests/cfg/virsh_cmd/nodedev/virsh_nodedev_list.cfg index 318ebb8c2f8..7e0d0cf166a 100644 --- a/libvirt/tests/cfg/virsh_cmd/nodedev/virsh_nodedev_list.cfg +++ b/libvirt/tests/cfg/virsh_cmd/nodedev/virsh_nodedev_list.cfg @@ -17,6 +17,7 @@ comparison_mode = exact s390-virtio: comparison_mode = similar + remove_scm_device = "yes" - multi_cap_option: cap_option = multi - long_cap_option: diff --git a/libvirt/tests/src/virsh_cmd/nodedev/virsh_nodedev_list.py b/libvirt/tests/src/virsh_cmd/nodedev/virsh_nodedev_list.py index 5dc19a22bf8..a85574edc1a 100644 --- a/libvirt/tests/src/virsh_cmd/nodedev/virsh_nodedev_list.py +++ b/libvirt/tests/src/virsh_cmd/nodedev/virsh_nodedev_list.py @@ -30,6 +30,26 @@ def get_avail_caps(all_caps): return avail_caps +def get_scm_devices(): + """ + Get all Storage Class Memory Increments devices, only for s390. + + :return: A list contains all available scm devices in string. + """ + scm_devices = [] + try: + utils_path.find_command('lsscm') + scm_output = process.run('lsscm', ignore_status=True, shell=True).stdout_text + scm_list = scm_output.split('\n')[2:-1] + for scm in scm_list: + scm_info_list = [info for info in scm.split(' ') if info != ''] + scm_devices.append('block_' + scm_info_list[2]) + except utils_path.CmdNotFoundError: + logging.warning('Cmd lsscm not found!') + logging.warning('You can try to install it by `yum install s390utils*`') + return scm_devices + + def get_storage_devices(): """ Retrieve storage devices list from sysfs. @@ -248,6 +268,7 @@ def _check_result(cap, ref_list, result, mode): return True mode = params.get("comparison_mode", "exact") + remove_scm_device = 'yes' == params.get("remove_scm_device", "no") all_caps = ['system', 'pci', 'usb_device', 'usb', 'net', 'scsi_host', 'scsi_target', 'scsi', 'storage', 'fc_host', 'vports', 'scsi_generic', 'ccw', 'css'] @@ -293,6 +314,11 @@ def _check_result(cap, ref_list, result, mode): break elif result.exit_status == 0 and expect_succeed == 'no': break + if cap == 'storage' and remove_scm_device: + scm_devices = get_scm_devices() + if scm_devices: + devices[cap] = [device for device in devices[cap] + if device not in scm_devices] if not _check_result(cap, devices[cap], result.stdout.strip(), mode): check_failed = True break diff --git a/spell.ignore b/spell.ignore index 2a06ef3ea15..dab9e71a3aa 100644 --- a/spell.ignore +++ b/spell.ignore @@ -869,6 +869,7 @@ sata scenaries schedinfo schid +scm scp scsi schid From 7824e76cc9d14903aa865b1e960a6547742eb823 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 8 Jan 2024 11:04:59 -0500 Subject: [PATCH 0108/1055] passt/transfer_file: update config for s390x Signed-off-by: Sebastian Mitterle --- .../tests/cfg/virtual_network/passt/passt_transfer_file.cfg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg index f5182c27464..7bf357beda4 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg @@ -29,6 +29,9 @@ iface_attrs = {'model': 'virtio', 'acpi': {'index': '1'}, **${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, **${alias}, 'type_name': 'user', **${portForwards}} ipv6_prefix = 128 vm_iface = eno1 + s390-virtio: + iface_attrs = {'model': 'virtio', **${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, **${alias}, 'type_name': 'user', **${portForwards}} + vm_iface = enc1 variants file_size: - 10M: bs = 1M From 4bc17fb34ed49fe79a1938e509b48275d3658d4f Mon Sep 17 00:00:00 2001 From: nanli Date: Tue, 2 Jan 2024 13:59:01 +0800 Subject: [PATCH 0109/1055] add case for invalid nvdimm config xxxx-299194: Invalid nvdimm memory device config values Signed-off-by: nanli --- .../invalid_nvdimm_memory_device_config.cfg | 69 ++++++++ .../invalid_nvdimm_memory_device_config.py | 151 ++++++++++++++++++ provider/memory/memory_base.py | 13 ++ 3 files changed, 233 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_devices/invalid_nvdimm_memory_device_config.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/invalid_nvdimm_memory_device_config.py diff --git a/libvirt/tests/cfg/memory/memory_devices/invalid_nvdimm_memory_device_config.cfg b/libvirt/tests/cfg/memory/memory_devices/invalid_nvdimm_memory_device_config.cfg new file mode 100644 index 00000000000..0a6fb1b468b --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/invalid_nvdimm_memory_device_config.cfg @@ -0,0 +1,69 @@ +- memory.devices.invalid_nvdimm: + type = invalid_nvdimm_memory_device_config + nvdimm_file_size = "512M" + target_size = 524288 + guest_node = 0 + slot = 0 + addr_type = 'dimm' + addr_base = '0x100000000' + nvdimm_path = "/tmp/nvdimm" + alignsize = 2048 + label_size = 128 + discard_attr = "" + label_attrs = "" + align_attrs = "'alignsize':${alignsize},'alignsize_unit': 'KiB'" + label_attrs = "'label':{'size_unit':'KiB','size':${label_size}}" + addr_attrs = "'address':{'attrs': {'type': '${addr_type}', 'base': '${addr_base}', 'slot': '${slot}'}}" + variants invalid_setting: + - exceed_slot: + slot = '4294967295' + define_error = "memory device slot '${slot}' exceeds slots count" + - max_addr: + addr_base = '0xffffffffffffffff' + start_vm_error = "address must be aligned to" + attach_error = "nvdimm is not enabled: missing 'nvdimm' in '-M'" + aarch64: + attach_error = "nvdimm is not enabled: add 'nvdimm=on' to '-M'" + - unexisted_node: + guest_node = '6' + start_vm_error = "can't add memory backend for guest node '${guest_node}' as the guest has only '2' NUMA nodes configured" + - unexisted_path: + nvdimm_path = "/tmp/nonexist.file" + start_vm_error = "No such file or directory" + - invalid_alignsize: + alignsize = '2' + align_attrs = "'alignsize':${alignsize},'alignsize_unit': 'KiB'" + start_vm_error = "must be multiples of page size 0x1000" + - invalid_addr_type: + addr_type = 'fakedimm' + define_error = "Invalid value for attribute 'type' in element 'address': '${addr_type}'" + define_error_8 = "unknown address type '${addr_type}'" + attach_error_8 = "unknown address type '${addr_type}'" + - small_label: + label_size = 100 + label_attrs = "'label':{'size_unit':'KiB','size':${label_size}}" + define_error ="nvdimm label must be at least 128KiB" + - bigger_label: + label_size = 524289 + label_attrs = "'label':{'size_unit':'KiB','size':${label_size}}" + define_error ="label size must be smaller than NVDIMM size" + - bigger_target_memory: + target_size = 1048576 + start_vm_error = "backing store size 0x20000000 does not match 'size' option 0x40000000" + - with_discard: + mem_discard = "yes" + discard_attr = " 'mem_discard':'${mem_discard}'," + define_error = "discard is not supported for nvdimms" + addr_attrs = "'address':{'attrs': {'type': '${addr_type}', 'base': '${addr_base}', 'slot': '${slot}'}}" + source_attrs = "'source': {${align_attrs},'path': '${nvdimm_path}'}" + target_attrs = "'target': {'size': ${target_size},'size_unit': 'KiB','node':${guest_node}, ${label_attrs}}" + nvdimm_dict = {'mem_model':'nvdimm', ${source_attrs}, ${target_attrs},${addr_attrs},${discard_attr}} + variants: + - with_numa: + no s390-virtio + mem_value = 2097152 + current_mem = 2097152 + numa_mem = 1048576 + max_dict = '"max_mem_rt": 10485760, "max_mem_rt_slots":16, "max_mem_rt_unit": "KiB"' + numa_attrs = "'vcpu': 4,'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'},{'id':'1','cpus': '2-3','memory':'${numa_mem}','unit':'KiB'}]}" + vm_attrs = {${numa_attrs}, ${max_dict}, 'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':"KiB"} diff --git a/libvirt/tests/src/memory/memory_devices/invalid_nvdimm_memory_device_config.py b/libvirt/tests/src/memory/memory_devices/invalid_nvdimm_memory_device_config.py new file mode 100644 index 00000000000..dda407db1e5 --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/invalid_nvdimm_memory_device_config.py @@ -0,0 +1,151 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import os + +from avocado.utils import process + +from virttest import libvirt_version +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt + +from provider.memory import memory_base + + +def define_guest(test, params): + """ + Define guest. + + :param test: test object. + :param params: dict, test parameters. + """ + vm_name = params.get("main_vm") + vm_attrs = eval(params.get("vm_attrs")) + nvdimm_dict = eval(params.get("nvdimm_dict")) + invalid_setting = params.get("invalid_setting") + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vmxml.setup_attrs(**vm_attrs) + mem_obj = memory_base.prepare_mem_obj(nvdimm_dict) + vmxml.devices = vmxml.devices.append(mem_obj) + test.log.debug("Define vm with %s." % vmxml) + + # Check libvirt version + if libvirt_version.version_compare(9, 0, 0) and \ + invalid_setting == "unexisted_node": + define_error = params.get("start_vm_error") + elif not libvirt_version.version_compare(9, 9, 0) and \ + invalid_setting == "invalid_addr_type": + define_error = params.get("define_error_8") + else: + define_error = params.get("define_error") + + # Redefine define_error for checking start_vm_error + params.update({"define_error": define_error}) + + try: + vmxml.sync() + except Exception as e: + if define_error: + if define_error not in str(e): + test.fail("Expect to get '%s' error, but got '%s'" % (define_error, e)) + else: + test.fail("Expect define successfully, but failed with '%s'" % e) + + +def run(test, params, env): + """ + Verify error messages prompt with invalid nvdimm memory device configs + + 1.invalid value: + exceed slot number, max address base, nonexistent guest node + nonexistent path, invalid pagesize, invalid address type, small label size + label size bigger than memory size, :memory size bigger than backing file size + discard. + 2.memory setting: with numa + """ + + def setup_test(): + """ + Create file backend for nvdimm device. + """ + test.log.info("Setup env.") + if invalid_setting != "unexisted_path": + process.run('truncate -s %s %s' % (nvdimm_file_size, nvdimm_path), + verbose=True, shell=True) + + def run_test(): + """ + Define vm with nvdimm and Start vm. + Hotplug nvdimm. + """ + test.log.info("TEST_STEP1: Define vm and check result") + define_guest(test, params) + + test.log.info("TEST_STEP2: Start guest ") + start_result = virsh.start(vm_name, debug=True, ignore_status=True) + if start_vm_error: + libvirt.check_result(start_result, start_vm_error) + else: + libvirt.check_exit_status(start_result) + + test.log.info("TEST_STEP3: Define guest without nvdimm devices") + original_xml.setup_attrs(**vm_attrs) + test.log.debug("Define vm without nvdimm by '%s' \n", original_xml) + original_xml.sync() + virsh.start(vm_name, debug=True, ignore_status=False) + vm.wait_for_login().close() + + test.log.info("TEST_STEP4: Hotplug nvdimm memory device") + mem_obj = memory_base.prepare_mem_obj(nvdimm_dict) + result = virsh.attach_device(vm_name, mem_obj.xml, debug=True).stderr_text + if attach_error not in result: + test.fail("Expected get error '%s', but got '%s'" % (attach_error, result)) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bkxml.sync() + if os.path.exists(nvdimm_path): + os.remove(nvdimm_path) + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = original_xml.copy() + invalid_setting = params.get("invalid_setting") + nvdimm_file_size = params.get("nvdimm_file_size") + nvdimm_path = params.get("nvdimm_path") + nvdimm_dict = eval(params.get("nvdimm_dict")) + vm_attrs = eval(params.get("vm_attrs")) + # Get start vm error + if libvirt_version.version_compare(9, 0, 0) and \ + invalid_setting == "unexisted_node": + start_vm_error = "" + else: + start_vm_error = params.get("start_vm_error") + + # Get attach error + if invalid_setting == "max_addr": + attach_error = params.get('attach_error') + elif not libvirt_version.version_compare(9, 9, 0) and \ + invalid_setting == "invalid_addr_type": + attach_error = params.get('attach_error_8') + else: + attach_error = params.get("start_vm_error", params.get("define_error")) + + try: + setup_test() + run_test() + + finally: + teardown_test() diff --git a/provider/memory/memory_base.py b/provider/memory/memory_base.py index 8032a7ba3f1..5500110e1e2 100644 --- a/provider/memory/memory_base.py +++ b/provider/memory/memory_base.py @@ -3,6 +3,7 @@ from virttest import libvirt_version from virttest import utils_misc +from virttest.libvirt_xml.devices import memory from virttest.utils_version import VersionInterval from avocado.core import exceptions @@ -76,3 +77,15 @@ def check_supported_version(params, test, vm): if vm_kerv not in VersionInterval(guest_required_kernel): test.cancel("Got guest kernel version:%s, which is not in %s" % (vm_kerv, guest_required_kernel)) + + +def prepare_mem_obj(dest_dict): + """ + Prepare memory object + :param dest_dict: dimm memory dict. + :return mem_obj, memory object. + """ + mem_obj = memory.Memory() + mem_obj.setup_attrs(**dest_dict) + + return mem_obj From 135f639c0700f6a3337fc24074598df52efe3d9a Mon Sep 17 00:00:00 2001 From: root Date: Mon, 4 Dec 2023 13:29:35 -0500 Subject: [PATCH 0110/1055] Start vm with gic feature Implemented verification of GIC version. Configured values in vm xml based on GIC versions 2, 3, and 'host,' ensuring compatibility. Signed-off-by: Aakanksha Tripathi Committer: aatripat --- libvirt/tests/cfg/cpu/aarch64_gic_version.cfg | 17 +++ libvirt/tests/src/cpu/aarch64_gic_version.py | 119 ++++++++++++++++++ spell.ignore | 2 + 3 files changed, 138 insertions(+) create mode 100644 libvirt/tests/cfg/cpu/aarch64_gic_version.cfg create mode 100644 libvirt/tests/src/cpu/aarch64_gic_version.py diff --git a/libvirt/tests/cfg/cpu/aarch64_gic_version.cfg b/libvirt/tests/cfg/cpu/aarch64_gic_version.cfg new file mode 100644 index 00000000000..12ecca07ada --- /dev/null +++ b/libvirt/tests/cfg/cpu/aarch64_gic_version.cfg @@ -0,0 +1,17 @@ +- aarch64_gic_version: + type = aarch64_gic_version + start_vm = "yes" + check_gic_command_host = "grep GIC /proc/interrupts | head -1" + check_gic_command_guest = "grep GIC /proc/interrupts | head -1" + only aarch64 + variants: + - gic_version_2: + gic_version = '2' + err_msg = "error: Failed to start domain" + status_error = "yes" + - gic_version_3: + gic_version = '3' + status_error = "no" + - gic_version_host: + gic_version = 'host' + status_error = "no" diff --git a/libvirt/tests/src/cpu/aarch64_gic_version.py b/libvirt/tests/src/cpu/aarch64_gic_version.py new file mode 100644 index 00000000000..e6ae67c4278 --- /dev/null +++ b/libvirt/tests/src/cpu/aarch64_gic_version.py @@ -0,0 +1,119 @@ +import re +import logging + +from avocado.utils import process +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt + + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test GIC version feature + + :param test: QEMU test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + + start_vm = params.get("start_vm", "no") + check_gic_command_host = params.get("check_gic_command_host", "") + check_gic_command_guest = params.get("check_gic_command_guest", "") + gic_version = params.get("gic_version", "") + + status_error = "yes" == params.get("status_error", "no") + err_msg = params.get("err_msg", "") + + def _check_host_support(vm): + """ + Check the host support for GIC + + :param vm: The virtual machine + """ + # Checks whether CPU has GIC + if not process.run( + check_gic_command_host, + ignore_status=True, + shell=True).stdout_text: + test.cancel("Host doesn't support CPU GIC") + + def _check_vm_start(vm): + """ + Verifies GIC version setting in VM XML works as expected. + + :param vm: The virtual machine + :param gic_version: The GIC version value to set and verify + """ + # Update VM XML with the specified GIC version + # Start the VM and capture the output + result = virsh.start(vm.name, debug=True) + libvirt.check_exit_status(result, status_error) + + def _check_gic_version(vm, gic_version): + """ + Check the host and guest gic version + + :param vm: The virtual machine + :param gic_version: The GIC version value to test (eg, "2", "3", or "host") + """ + if not vm.is_alive(): + LOG.debug("VM is not active, skipping GIC version check") + return + + session = None + try: + # Check GIC version on host + host_gic_version_output = process.run( + check_gic_command_host, shell=True).stdout_text + + match = re.search(r"(GICv\d+)", host_gic_version_output) + if not match: + test.fail("Could not determine host GIC version") + else: + actual_host_gic_version = match.group(1) + + # Verify guest GIC version based on GIC version + session = vm.wait_for_login(timeout=120) + ret_guest = session.cmd_output(check_gic_command_guest) + + exp_gic_version = actual_host_gic_version if gic_version == 'host' else 'GICv%s' % gic_version + if exp_gic_version not in ret_guest: + test.fail( + f"Guest GIC version mismatch for GICv{gic_version}. Expected: {exp_gic_version}, Actual: {ret_guest}") + + finally: + if session: + session.close() + + # Close guest and edit guest xml + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + original_vm_xml = vmxml.copy() + + try: + # Additional preparation steps for GIC tests can be added here + _check_host_support(vm) + + vm_features = vmxml.features + vm_features.add_feature('gic', 'version', gic_version) + vmxml.features = vm_features + LOG.debug(f"Testing GIC version: {gic_version}") + + LOG.debug("Original VM XML:\n{original_vm_xml}") + + LOG.debug("Updated VM XML:\n{vmxml}") + + vmxml.sync() + + _check_vm_start(vm) + _check_gic_version(vm, gic_version) + + finally: + # Restore guest + if vm.is_alive(): + vm.destroy(gracefully=False) + original_vm_xml.sync() diff --git a/spell.ignore b/spell.ignore index 1fa9be1a81c..02c25ef193c 100644 --- a/spell.ignore +++ b/spell.ignore @@ -339,6 +339,8 @@ getspeed gfxcard Gib GiB +gic +GIC gid gluster Gluster From de9e701ceac15165b9eb4bc70ed0cb63064b5d9e Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Thu, 21 Dec 2023 04:49:46 -0500 Subject: [PATCH 0111/1055] provider//passt: add changes for multiarch 'passt.avx2' is a specialization only for x86_64. On other architectures the process might just be "passt". Change the regular expression to match any process containing "passt". `check_vm_ip` calculated the guest interface name for x86_64 for other architectures allow for configuration of this value. Remove zone index when comparing routes as they might differ between host and guest (e.g. if the interfaces are named differently). Check gateways by confirming that routes in guest are available on host instead of confirming they must be exactly the same on both ends. Pass the target interface name to the check_connection function to allow for the correct selection of the gateway. When a host has two interfaces the function used a list and failed. `check_protocol_connection` sent a command to start listening to the server VM and the client send a message to quickly. We could establish a wait condition like checking ports of the machine but a static sleep seemed like a simpler and still reliable solution. The port list definition for `check_portforward` needs to contain the host interface, not the VM interface. Therefore, pass the parameter and remove the unused vm_iface. Signed-off-by: Sebastian Mitterle --- provider/virtual_network/passt.py | 49 ++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/provider/virtual_network/passt.py b/provider/virtual_network/passt.py index 14822134b89..00ac9fad006 100644 --- a/provider/virtual_network/passt.py +++ b/provider/virtual_network/passt.py @@ -1,6 +1,8 @@ import logging import os +import re import random +import time from socket import socket import aexpect @@ -169,15 +171,17 @@ def check_proc(target): raise exceptions.TestFail(';'.join(failed_check)) -def check_vm_ip(iface_attrs, session, host_iface): +def check_vm_ip(iface_attrs, session, host_iface, vm_iface=None): """ Check if vm ip and prefix meet expectation :param iface_attrs: attributes of interface :param session: shell session instance of vm :param host_iface: host interface + :param vm_iface: VM interface, can be omitted on x86_64 """ - vm_iface = 'eno' + iface_attrs.get('acpi', {'index': '1'})['index'] + if not vm_iface: + vm_iface = 'eno' + iface_attrs.get('acpi', {'index': '1'})['index'] vm_ip, prefix = get_iface_ip_and_prefix(vm_iface, session=session) LOG.debug(f'VM ip and prefix: {vm_ip}, {prefix}') if 'ips' in iface_attrs: @@ -232,21 +236,24 @@ def check_vm_mtu(session, iface, mtu): def check_default_gw(session): """ - Check whether default host gateways of host and guest are consistent + Check whether default host gateways of host and guest are consistent, + i.e. the guest's gateways are available on the host. :param session: vm shell session instance """ - host_gw = utils_net.get_default_gateway(force_dhcp=True) - vm_gw = utils_net.get_default_gateway(session=session, force_dhcp=True) + host_gw = utils_net.get_default_gateway(force_dhcp=True).split() + vm_gw = utils_net.get_default_gateway(session=session, + force_dhcp=True).split() LOG.debug(f'Host and vm default ipv4 gateway: {host_gw}, {vm_gw}') - host_gw_v6 = utils_net.get_default_gateway(ip_ver='ipv6') - vm_gw_v6 = utils_net.get_default_gateway(session=session, ip_ver='ipv6') + host_gw_v6 = utils_net.get_default_gateway(ip_ver='ipv6').split() + vm_gw_v6 = utils_net.get_default_gateway(session=session, + ip_ver='ipv6').split() LOG.debug(f'Host and vm default ipv6 gateway: {host_gw_v6}, {vm_gw_v6}') - if host_gw != vm_gw: + if [x for x in vm_gw if x not in host_gw]: raise exceptions.TestFail( 'Host default ipv4 gateway not consistent with vm.') - if host_gw_v6 != vm_gw_v6: + if [x for x in vm_gw_v6 if x not in host_gw_v6]: raise exceptions.TestFail( 'Host default ipv6 gateway not consistent with vm.') @@ -258,8 +265,11 @@ def check_nameserver(session): :param session: vm shell session instance """ get_cmd = 'cat /etc/resolv.conf|grep -vE "#|;"' - on_host = process.run(get_cmd, shell=True).stdout_text.strip() - on_vm = session.cmd_output(get_cmd).strip() + on_host = process.run(get_cmd, shell=True).stdout_text.strip().split() + on_vm = session.cmd_output(get_cmd).strip().split() + # remove zone index + on_host = [re.sub(r'%.*', '', x) for x in on_host] + on_vm = [re.sub(r'%.*', '', x) for x in on_vm] if on_host == on_vm: LOG.debug(f'Nameserver on vm is consistent with host:\n{on_host}') else: @@ -293,6 +303,7 @@ def check_protocol_connection(src_sess, tar_sess, protocol, addr, cmd_listen = f'socat {protocol}-LISTEN:{tar_port} -' LOG.debug(cmd_listen) tar_sess.sendline(cmd_listen) + time.sleep(1) msg = f'Message {utils_misc.generate_random_string(6)} '\ f'from source via {protocol}' if src_iface: @@ -320,16 +331,20 @@ def check_protocol_connection(src_sess, tar_sess, protocol, addr, f'actually is {conneted}') -def check_connection(vm, vm_iface, protocols): +def check_connection(vm, vm_iface, protocols, host_iface=None): """ Check connection of vm and host :param vm: vm instance :param vm_iface: interface of vm :param protocols: protocols to check + :param host_iface: host interface to get default gw for + if ommitted all default routes are returned """ - default_gw = utils_net.get_default_gateway(force_dhcp=True) - default_gw_v6 = utils_net.get_default_gateway(ip_ver='ipv6') + default_gw = utils_net.get_default_gateway(force_dhcp=True, + target_iface=host_iface) + default_gw_v6 = utils_net.get_default_gateway(ip_ver='ipv6', + target_iface=host_iface) for protocol in protocols: host_sess = aexpect.ShellSession('su') vm_sess = vm.wait_for_serial_login(timeout=60) @@ -379,7 +394,7 @@ def check_port_listen(ports, protocol, host_ip=None): """ if protocol.lower() not in ('tcp', 'udp'): raise exceptions.TestError(f'Unsupported protocol: {protocol}') - cmd_listen = process.run(f"ss -{protocol[0].lower()}lpn|egrep 'passt.avx2'", + cmd_listen = process.run(f"ss -{protocol[0].lower()}lpn|egrep 'passt'", shell=True).stdout_text for item in ports: if item in cmd_listen: @@ -389,16 +404,16 @@ def check_port_listen(ports, protocol, host_ip=None): 'listened to') -def check_portforward(vm, host_ip, params): +def check_portforward(vm, host_ip, params, host_iface=None): """ Check function for portforward :param vm: vm instance :param host_ip: host ipv4 address :param params: test params + :param host_iface: host interface for passt """ host_ip_v6 = params.get('host_ip_v6') - vm_iface = params.get('vm_iface') tcp_port_list = eval(params.get('tcp_port_list', '[]')) tcp_port_list = [f'{host_ip}:{port}' if str(port).isdigit() else port for port in tcp_port_list] From 30355b3df24c43fbfd59a5e3a3686d62d6b1cde5 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Wed, 18 Oct 2023 23:40:27 -0400 Subject: [PATCH 0112/1055] Add network case of update device:port isolated - VIRT-294993 - [update-device][port_isolated] live update the port isolated attribute Signed-off-by: Haijiao Zhao --- .../update_device/update_port_isolated.cfg | 36 +++++ .../update_device/update_port_isolated.py | 144 ++++++++++++++++++ spell.ignore | 1 + 3 files changed, 181 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/update_device/update_port_isolated.cfg create mode 100644 libvirt/tests/src/virtual_network/update_device/update_port_isolated.py diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_port_isolated.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_port_isolated.cfg new file mode 100644 index 00000000000..6419871abd2 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/update_device/update_port_isolated.cfg @@ -0,0 +1,36 @@ +- virtual_network.update_device.port_isolated: + type = update_port_isolated + vms = avocado-vt-vm1 vm2 + start_vm = no + timeout = 240 + outside_ip = 'www.redhat.com' + host_iface = + vm_ping_outside = pass + vm_ping_host_public = pass + func_supported_since_libvirt_ver = (6, 2, 0) + variants net: + - nat_network: + iface_source = "'default'" + - linux_br: + create_linux_br = yes + net_attrs = {'bridge': {'name': linux_br}, 'forward': {'mode': 'bridge'}, 'name': net_br} + iface_source = net_br + set_iface = yes + variants: + - default_to_yes: + port_attrs = {} + update_port_attrs = {'port': {'isolated': 'yes'}} + vm_ping_ep_vm = pass + ping_after_update = fail + - yes_to_no: + port_attrs = {'port': {'isolated': 'yes'}} + update_port_attrs = {'port': {'isolated': 'no'}} + vm_ping_ep_vm = fail + ping_after_update = pass + - yes_to_default: + port_attrs = {'port': {'isolated': 'yes'}} + update_port_attrs = {} + vm_ping_ep_vm = fail + ping_after_update = pass + iface_attrs = {'type_name': 'network', 'source': {'network': iface_source}, 'model': 'virtio', **${port_attrs}} + cli_iface_attrs = {'type_name': 'network', 'source': {'network': iface_source}, 'model': 'virtio', 'port': {'isolated': 'yes'}} diff --git a/libvirt/tests/src/virtual_network/update_device/update_port_isolated.py b/libvirt/tests/src/virtual_network/update_device/update_port_isolated.py new file mode 100644 index 00000000000..90d3f4c9313 --- /dev/null +++ b/libvirt/tests/src/virtual_network/update_device/update_port_isolated.py @@ -0,0 +1,144 @@ +import logging + +from virttest import libvirt_version +from virttest import utils_misc +from virttest import utils_net +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_network +from virttest.utils_libvirt import libvirt_vmxml + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test update of port isolated on interface with update-device command + """ + def setup_vms_ifaces(vmxml, cli_vmxml): + """ + Setup interface of vm xmls + + :param vmxml: vmxml instance + :param cli_vmxml: client vm xml instance + """ + for vmxml_i in [vmxml, cli_vmxml]: + vmxml_i.del_device('interface', by_tag=True) + + for vmxml_i, attrs in [(vmxml, iface_attrs), + (cli_vmxml, cli_iface_attrs)]: + libvirt_vmxml.modify_vm_device(vmxml_i, 'interface', attrs) + + for vm_x in vms: + LOG.debug(f'VMXML of {vm_x}:\n{virsh.dumpxml(vm_x).stdout_text}') + + for vm_i in [vm, cli_vm]: + vm_i.start() + + def get_ips(session, cli_session): + """ + Get test ips + + :param session: vm session + :param cli_session: client vm session + :return: test ips + """ + mac, cli_mac = list(map(vm_xml.VMXML.get_first_mac_by_name, vms)) + ips = network_base.get_test_ips(session, mac, cli_session, cli_mac, + ip_ver='ipv4') + ips['outside_ip'] = outside_ip + + return ips + + def test_ping(msg, ips=None): + """ + Test ping function + + :param msg: message to log + :param ips: test ips, defaults to None + :return: test ips if not given + """ + session, cli_session = (vm_inst.wait_for_serial_login() + for vm_inst in [vm, cli_vm]) + if ips is None: + ips = get_ips(session, cli_session) + + LOG.info(f'Ping check {msg}') + network_base.ping_check(params, ips, session, force_ipv4=True) + + session.close() + cli_session.close() + + if ips: + return ips + + def test_update_iface(): + """ + Test update interface + """ + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + iface = vmxml.get_devices('interface')[0] + LOG.debug(f'Interface xml on vm:\n{iface}') + + iface.del_port() + iface.setup_attrs(**update_port_attrs) + LOG.debug(f'Interface xml to update:\n{iface}') + + virsh.update_device(vm_name, iface.xml, **VIRSH_ARGS) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + iface_update = vmxml.get_devices('interface')[0] + LOG.debug(f'Interface after update:\n{iface_update}') + if iface_update.fetch_attrs().get('port') == update_port_attrs.get('port'): + LOG.debug('port isolated value check in xml after update: PASS') + else: + test.fail('port isolated value not updated in vmxml') + + vm_name = params.get('main_vm') + vms = params.get('vms').split() + vm, cli_vm = (env.get_vm(vm_i) for vm_i in vms) + rand_id = utils_misc.generate_random_string(3) + create_linux_br = 'yes' == params.get('create_linux_br', 'no') + linux_br = 'linux_br_' + rand_id + net_br = 'net_br_' + rand_id + outside_ip = params.get('outside_ip') + iface_source = eval(params.get('iface_source')) + iface_attrs = eval(params.get('iface_attrs', '{}')) + cli_iface_attrs = eval(params.get('cli_iface_attrs', '{}')) + net_attrs = eval(params.get('net_attrs', '{}')) + update_port_attrs = eval(params.get('update_port_attrs', '{}')) + host_iface = params.get('host_iface') + host_iface = host_iface if host_iface else utils_net.get_net_if( + state='UP')[0] + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxmls = list(map(vm_xml.VMXML.new_from_inactive_dumpxml, vms)) + + try: + libvirt_version.is_libvirt_feature_supported(params) + if create_linux_br: + LOG.info(f'Create linux bridge: {linux_br}') + utils_net.create_linux_bridge_tmux(linux_br, host_iface) + if net_attrs: + libvirt_network.create_or_del_network(net_attrs) + LOG.debug(f'Network xml:\n' + f'{virsh.net_dumpxml(net_attrs["name"]).stdout_text}') + + vmxml, cli_vmxml = list(map(vm_xml.VMXML.new_from_inactive_dumpxml, vms)) + + setup_vms_ifaces(vmxml, cli_vmxml) + ips = test_ping('before update', ips=None) + test_update_iface() + params['vm_ping_ep_vm'] = params.get('ping_after_update') + test_ping('After update', ips) + + finally: + for backup_xml in bkxmls: + backup_xml.sync() + if net_attrs: + libvirt_network.create_or_del_network(net_attrs, is_del=True) + if create_linux_br: + utils_net.delete_linux_bridge_tmux(linux_br, host_iface) diff --git a/spell.ignore b/spell.ignore index b916b264785..1d357c6ab41 100644 --- a/spell.ignore +++ b/spell.ignore @@ -452,6 +452,7 @@ ip IP ipaddress iperf +ips IPs iptable iptables From ad0189850e087068f3811506d1034c7d9dc9b102 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Thu, 11 Jan 2024 17:13:52 +0800 Subject: [PATCH 0113/1055] v2v: fix 9.4 func testing Signed-off-by: vwu-vera --- v2v/tests/cfg/function_test_esx.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index d4c31948fa0..7f6f3259805 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -558,7 +558,7 @@ main_vm = VM_NAME_SLES_V2V_EXAMPLE - opensuse: only esx_70 - boottype = 2 + boottype = 3 qa_path = 'linux/lp151' qa_url = QEMU_GUEST_AGENT_SUSE_DOWNLOAD_URL_V2V_EXAMPLE main_vm = VM_NAME_OPENSUSE_V2V_EXAMPLE From 1dccc588c9159744026c82d0204aac4f24c44d94 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Mon, 11 Dec 2023 04:27:01 -0500 Subject: [PATCH 0114/1055] Add new cases of network: update-device - VIRT-298315 - [update-device] Live update unsupported live update attributes or elements - alter - VIRT-298316 - [update-device] Live update unsupported live update attributes or elements - add optional setting - VIRT-298317 - [update-device] Live update unsupported live update attributes or elements - delete the optional elements/attributes Signed-off-by: Haijiao Zhao --- .../unsupported_live_update_add.cfg | 29 ++++++++ .../unsupported_live_update_alter.cfg | 49 ++++++++++++ .../unsupported_live_update_delete.cfg | 49 ++++++++++++ .../update_device/unsupported_live_update.py | 74 +++++++++++++++++++ provider/virtual_network/network_base.py | 14 ++++ 5 files changed, 215 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_add.cfg create mode 100644 libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_alter.cfg create mode 100644 libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg create mode 100644 libvirt/tests/src/virtual_network/update_device/unsupported_live_update.py diff --git a/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_add.cfg b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_add.cfg new file mode 100644 index 00000000000..343cfe2af2b --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_add.cfg @@ -0,0 +1,29 @@ +- virtual_network.update_device.unsupported_live_update.add: + type = unsupported_live_update + start_vm = no + timeout = 240 + base_iface_attrs = {'mac_address': mac, 'type_name': 'network', 'source': {'network': 'default'}, 'model': 'virtio'} + status_error = yes + variants: + - acpi_index: + update_attrs = {'acpi': {'index': '6'}} + err_msg = changing device 'acpi index' is not allowed + - sndbuf: + update_attrs = {'tune': {'sndbuf': 2000}} + err_msg = unable to change config on 'network' network type + - mtu: + update_attrs = {'mtu': {'size': '9000'}} + err_msg = cannot modify MTU + - boot_order: + set_boot = yes + update_attrs = {'boot': '3'} + err_msg = cannot modify network device boot index setting + - rom: + update_attrs = {'rom': {'enabled': 'yes'}} + err_msg = cannot modify network device rom enabled setting + - backend: + update_attrs = {'backend': {'tap': '/dev/net/tun'}} + err_msg = cannot modify network device backend settings + - driver: + update_attrs = {'driver': {'driver_attr': {'name': 'vhost', 'queues': '8', 'rx_queue_size': '1024'}}} + err_msg = cannot modify virtio network device driver attributes diff --git a/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_alter.cfg b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_alter.cfg new file mode 100644 index 00000000000..b3df1c2670e --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_alter.cfg @@ -0,0 +1,49 @@ +- virtual_network.update_device.unsupported_live_update.alter: + type = unsupported_live_update + start_vm = no + timeout = 240 + status_error = yes + variants: + - acpi_index: + extra_attrs = {'acpi': {'index': '4'}} + update_attrs = {'acpi': {'index': '6'}} + err_msg = changing device 'acpi index' is not allowed + - sndbuf: + extra_attrs = {'tune': {'sndbuf': 1600}} + update_attrs = {'tune': {'sndbuf': 2000}} + err_msg = unable to change config on 'network' network type + - mtu: + extra_attrs = {'mtu': {'size': '6000'}} + update_attrs = {'mtu': {'size': '9000'}} + err_msg = cannot modify MTU + - boot_order: + set_boot = yes + extra_attrs = {'boot': '2'} + update_attrs = {'boot': '3'} + err_msg = cannot modify network device boot index setting + - rom: + extra_attrs = {'rom': {'enabled': 'no'}} + update_attrs = {'rom': {'enabled': 'yes'}} + err_msg = cannot modify network device rom enabled setting + - target_dev: + extra_attrs = {'target': {'dev': 'test'}} + update_attrs = {'target': {'dev': 'newtap'}} + err_msg = cannot modify network device tap name + - model_type: + update_attrs = {'model': 'e1000e'} + err_msg = cannot modify network device model from .* to .* + - backend: + extra_attrs = {'backend': {'tap': '/dev/net/tun', 'vhost': '/dev/vhost-net'}} + update_attrs = {'backend': {'tap': '/dev/net/tun'}} + err_msg = cannot modify network device backend settings + - driver: + update_attrs = {'driver': {'driver_attr': {'name': 'vhost', 'queues': '8', 'rx_queue_size': '1024'}}} + err_msg = cannot modify virtio network device driver attributes + - alias_name: + extra_attrs = {'alias': {'name': 'ua-47034d36-5483-411c-86f8-7989d08d762b'}} + update_attrs = {'alias': {'name': 'ua-testnet888'}} + err_msg = device not found: no device found at address .* matching MAC address .* and alias .* + - mac: + update_attrs = {'mac_address': '52:54:00:44:e1:55'} + err_msg = device not found: no device found at address .* matching MAC address .* and alias .* + base_iface_attrs = {'mac_address': mac, 'type_name': 'network', 'source': {'network': 'default'}, 'model': 'virtio'} diff --git a/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg new file mode 100644 index 00000000000..a7b171ca1cb --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg @@ -0,0 +1,49 @@ +- virtual_network.update_device.unsupported_live_update.delete: + type = unsupported_live_update + start_vm = no + timeout = 240 + status_error = yes + variants: + - acpi_index: + extra_attrs = {'acpi': {'index': '4'}} + del_attr = acpi + err_msg = changing device 'acpi index' is not allowed + - sndbuf: + extra_attrs = {'tune': {'sndbuf': 1600}} + del_attr = tune + err_msg = unable to change config on 'network' network type + - mtu: + extra_attrs = {'mtu': {'size': '6000'}} + del_attr = mtu + err_msg = cannot modify MTU + - boot_order: + set_boot = yes + extra_attrs = {'boot': '2'} + del_attr = boot + err_msg = cannot modify network device boot index setting + - rom: + extra_attrs = {'rom': {'enabled': 'no'}} + del_attr = rom + err_msg = cannot modify network device rom enabled setting + - target_dev: + extra_attrs = {'target': {'dev': 'test'}} + del_attr = target + err_msg = cannot modify network device tap name + - model_type: + del_attr = model + err_msg = cannot modify network device model from .* to .* + - backend: + extra_attrs = {'backend': {'tap': '/dev/net/tun', 'vhost': '/dev/vhost-net'}} + del_attr = backend + err_msg = cannot modify network device backend settings + - driver: + del_attr = driver + err_msg = cannot modify virtio network device driver attributes + - alias_name: + extra_attrs = {'alias': {'name': 'ua-47034d36-5483-411c-86f8-7989d08d762b'}} + del_attr = alias + err_msg = device not found: no device found at address .* matching MAC address .* and alias .* + - mac: + del_attr = mac_address + err_msg = device not found: no device found at address .* matching MAC address .* and alias .* + base_iface_attrs = {'mac_address': mac, 'type_name': 'network', 'source': {'network': 'default'}, 'model': 'virtio'} diff --git a/libvirt/tests/src/virtual_network/update_device/unsupported_live_update.py b/libvirt/tests/src/virtual_network/update_device/unsupported_live_update.py new file mode 100644 index 00000000000..a997ea957c8 --- /dev/null +++ b/libvirt/tests/src/virtual_network/update_device/unsupported_live_update.py @@ -0,0 +1,74 @@ +import logging + +from virttest import utils_net +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test update-device command to update coalesce of interface + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + status_error = 'yes' == params.get('status_error', 'no') + err_msg = params.get('err_msg') + set_boot = 'yes' == params.get('set_boot', 'no') + + mac = utils_net.generate_mac_address_simple() + base_iface_attrs = eval(params.get('base_iface_attrs', '{}')) + extra_attrs = eval(params.get('extra_attrs', '{}')) + iface_attrs = {**base_iface_attrs, **extra_attrs} + + update_attrs = eval(params.get('update_attrs', '{}')) + del_attr = params.get('del_attr') + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + if set_boot: + osxml = vmxml.os + osxml.del_boots() + vmxml.os = osxml + libvirt_vmxml.modify_vm_device(vmxml, 'disk', {'boot': '1'}) + + vmxml.del_device('interface', by_tag=True) + libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs) + LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + vm.start() + vm.wait_for_serial_login().close() + + iface = network_base.get_iface_xml_inst(vmxml, 'on VM') + iface_original = iface.copy() + if del_attr: + if del_attr == 'boot': + iface.xmltreefile.remove_by_xpath('/boot') + else: + eval(f'iface.del_{del_attr}')() + else: + iface.setup_attrs(**update_attrs) + LOG.debug(f'Interface xml to update with:\n{iface}') + + up_result = virsh.update_device(vm_name, iface.xml, debug=True) + libvirt.check_exit_status(up_result, status_error) + if err_msg: + libvirt.check_result(up_result, err_msg) + + iface_update = network_base.get_iface_xml_inst(vmxml, + 'after update-device') + if iface_update != iface_original: + test.fail(f'Interface xml changed after unsuccessful update.\n' + f'Should be:\n{iface_original}\n' + f'Actually is:\n{iface_update}') + finally: + bkxml.sync() diff --git a/provider/virtual_network/network_base.py b/provider/virtual_network/network_base.py index 2d0b78e1bde..2321f2a8fd4 100644 --- a/provider/virtual_network/network_base.py +++ b/provider/virtual_network/network_base.py @@ -258,3 +258,17 @@ def set_static_ip(iface, ip, netmask, session): """ session.cmd('systemctl stop NetworkManager'), session.cmd(f'ifconfig {iface} {ip}/{netmask}') + + +def get_iface_xml_inst(vmxml, comment, index=0): + """ + Get iface xml instance with given vm and index + + :param vmxml: xml instance of vm + :param comment: comment to log + :param index: index of interface on vm, defaults to 0 + :return: xml instance of interface + """ + iface = vmxml.get_devices('interface')[index] + LOG.debug(f'Interface xml ({comment}):\n{iface}') + return iface From c2dc141b8eb8d2c9eedb33144a40a9e07c49e927 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 8 Jan 2024 12:45:28 -0500 Subject: [PATCH 0115/1055] passt/function: fix for multi-arch 1. Configure values for s390x 2. Get IP addresses by host interface to avoid issues when there's more than one functional NIC. 3. Use the host_iface in several functions to make sure the right interface is tested. 4. The test needs to check the ports on the host not in the guest. Therefore, configure the host_iface. Signed-off-by: Sebastian Mitterle --- .../virtual_network/passt/passt_function.cfg | 15 ++++++++++---- .../virtual_network/passt/passt_function.py | 20 ++++++++++--------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg index e8103697ea9..78468e5eb6a 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg @@ -22,6 +22,9 @@ iface_attrs = {'model': 'virtio', 'acpi': {'index': '1'}, 'type_name': 'user', 'backend': {'type': 'passt'}, 'source': {'dev': host_iface}} vm_iface = eno1 vm_ping_outside = pass + s390-virtio: + iface_attrs = {'model': 'virtio', 'type_name': 'user', 'backend': {'type': 'passt'}, 'source': {'dev': host_iface}} + vm_iface = enc1 - ip_portfw: ipv6_prefix = 128 alias = {'name': 'ua-c87b89ff-b769-4abc-921f-30d42d7aec5b'} @@ -30,6 +33,8 @@ vm_iface = eno1 vm_ping_outside = pass vm_ping_host_public = pass + s390-virtio: + vm_iface = enc1 variants: - ip_addr: portForward_0 = {'attrs': {'proto': 'tcp'}, 'ranges': [{'start': '31339', 'to': '41339'}]} @@ -54,8 +59,8 @@ portForward_0 = {'attrs': {'proto': 'tcp', 'dev': host_iface}, 'ranges': [{'start': '31339', 'to': '41339'}]} portForward_1 = {'attrs': {'proto': 'udp', 'dev': host_iface}, 'ranges': [{'start': '2025'}]} portForwards = [${portForward_0}, ${portForward_1}] - tcp_port_list = [f'*%{vm_iface}:31339'] - udp_port_list = [f'0.0.0.0%{vm_iface}:2025', f'[::]%{vm_iface}:2025'] + tcp_port_list = [f'*%{host_iface}:31339'] + udp_port_list = [f'0.0.0.0%{host_iface}:2025', f'[::]%{host_iface}:2025'] conn_check_args_1 = ('TCP4', host_ip, 31339, 41339, True, None) conn_check_args_2 = ('TCP6', host_ip_v6, 31339, 41339, True, None) conn_check_args_3 = ('UDP4', host_ip, 2025, 2025, True, None) @@ -65,9 +70,11 @@ portForward_1 = {'attrs': {'proto': 'udp', 'address': host_ip, 'dev': host_iface}, 'ranges': [{'start': '2025'}]} portForward_2 = {'attrs': {'proto': 'tcp', 'address': host_ip_v6, 'dev': host_iface}, 'ranges': [{'start': '51339'}]} portForwards = [${portForward_0}, ${portForward_1}, ${portForward_2}] - tcp_port_list = [f'{host_ip}%{vm_iface}:31339', f'[{host_ip_v6}]%{vm_iface}:51339'] - udp_port_list = [f'{host_ip}%{vm_iface}:2025'] + tcp_port_list = [f'{host_ip}%{host_iface}:31339', f'[{host_ip_v6}]%{host_iface}:51339'] + udp_port_list = [f'{host_ip}%{host_iface}:2025'] conn_check_args_1 = ('TCP4', host_ip, 31339, 41339, True, None) conn_check_args_2 = ('UDP4', host_ip, 2025, 2025, True, None) conn_check_args_3 = ('TCP6', host_ip_v6, 51339, 51339, True, None) iface_attrs = {'model': 'virtio', 'acpi': {'index': '1'}, 'ips': ${ips}, 'backend': ${backend}, 'source': {'dev': host_iface}, 'alias': ${alias}, 'type_name': 'user', 'portForwards': ${portForwards}} + s390-virtio: + iface_attrs = {'model': 'virtio', 'ips': ${ips}, 'backend': ${backend}, 'source': {'dev': host_iface}, 'alias': ${alias}, 'type_name': 'user', 'portForwards': ${portForwards}} diff --git a/libvirt/tests/src/virtual_network/passt/passt_function.py b/libvirt/tests/src/virtual_network/passt/passt_function.py index b9d65d2535d..ef57ffc6063 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_function.py +++ b/libvirt/tests/src/virtual_network/passt/passt_function.py @@ -52,17 +52,17 @@ def run(test, params, env): test_passwd) host_session.close() - host_ip = utils_net.get_host_ip_address(ip_ver='ipv4') - params['host_ip_v6'] = host_ip_v6 = utils_net.get_host_ip_address( - ip_ver='ipv6') + host_iface = params.get('host_iface') + host_iface = host_iface if host_iface else utils_net.get_net_if( + state="UP")[0] + host_ip = utils_net.get_ip_address_by_interface(host_iface, ip_ver='ipv4') + host_ip_v6 = utils_net.get_ip_address_by_interface(host_iface, ip_ver='ipv6') + params['host_ip_v6'] = host_ip_v6 params['socket_dir'] = socket_dir = eval(params.get('socket_dir')) params['proc_checks'] = proc_checks = eval(params.get('proc_checks', '{}')) vm_iface = params.get('vm_iface', 'eno1') mtu = params.get('mtu') outside_ip = params.get('outside_ip') - host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state="UP")[0] log_file = f'/run/user/{user_id}/passt.log' iface_attrs = eval(params.get('iface_attrs')) iface_attrs['backend']['logFile'] = log_file @@ -97,7 +97,7 @@ def run(test, params, env): test.fail(f'Logfile of passt "{log_file}" not created') session = vm.wait_for_serial_login(timeout=60) - passt.check_vm_ip(iface_attrs, session, host_iface) + passt.check_vm_ip(iface_attrs, session, host_iface, vm_iface) passt.check_vm_mtu(session, vm_iface, mtu) passt.check_default_gw(session) passt.check_nameserver(session) @@ -111,10 +111,12 @@ def run(test, params, env): firewalld.stop() LOG.debug(f'Status of firewalld: {firewalld.status()}') - passt.check_connection(vm, vm_iface, ['TCP4', 'TCP6', 'UDP4', 'UDP6']) + passt.check_connection(vm, vm_iface, + ['TCP4', 'TCP6', 'UDP4', 'UDP6'], + host_iface) if 'portForwards' in iface_attrs: - passt.check_portforward(vm, host_ip, params) + passt.check_portforward(vm, host_ip, params, host_iface) vm_sess = vm.wait_for_serial_login(timeout=60) vm_sess.cmd('systemctl start firewalld') From 2e590be5f3925c4f1c2256d543757dd7486f94dc Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Mon, 15 Jan 2024 15:19:26 +0800 Subject: [PATCH 0116/1055] cpu: Disable host dmesg checks To avoid an issue caused by the unexpected ip_set warning in dmesg. Signed-off-by: Yingshun Cui --- libvirt/tests/cfg/virsh_cmd/domain/virsh_cpu_compare.cfg | 1 + libvirt/tests/cfg/virsh_cmd/domain/virsh_cpu_stats.cfg | 1 + libvirt/tests/cfg/virsh_cmd/domain/virsh_cpu_xml.cfg | 1 + libvirt/tests/cfg/virsh_cmd/domain/virsh_vcpuinfo.cfg | 1 + 4 files changed, 4 insertions(+) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_cpu_compare.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_cpu_compare.cfg index bb4f3943fb6..ac2d3c68188 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_cpu_compare.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_cpu_compare.cfg @@ -7,6 +7,7 @@ cpu_compare_feature_num = -1 cpu_compare_file_name = "cpu.xml" cpu_compare_modify_invalid = "no" + verify_guest_dmesg = no variants: - default_feature: - delete_feature: diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_cpu_stats.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_cpu_stats.cfg index e1df3c19e4e..28e0027e8bd 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_cpu_stats.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_cpu_stats.cfg @@ -4,6 +4,7 @@ cpu_stats_vm_ref = "name" cpu_stats_options = "" start_vm = "yes" + verify_guest_dmesg = no variants: - positive_test: status_error = "no" diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_cpu_xml.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_cpu_xml.cfg index af94762f199..72c3f9ec953 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_cpu_xml.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_cpu_xml.cfg @@ -1,5 +1,6 @@ - virsh.cpu_xml: type = virsh_cpu_xml + verify_guest_dmesg = no variants: - positive: variants: diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_vcpuinfo.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_vcpuinfo.cfg index 3fcae002557..96eaaf01026 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_vcpuinfo.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_vcpuinfo.cfg @@ -8,6 +8,7 @@ kill_vm = "yes" # Test is not Guest OS dependent kill_vm_gracefully = "no" + verify_guest_dmesg = no variants: - normal_test: status_error = "no" From b32e529818676be838ea5fa3a137e3c4d6374bab Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 15 Jan 2024 22:19:59 -0500 Subject: [PATCH 0117/1055] Modify misuse for func test.log.debug Signed-off-by: liang-cong-red-hat --- .../tests/src/memory/memory_tuning/memory_tuning_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py b/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py index e595f3b61f4..637757dee95 100644 --- a/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py +++ b/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py @@ -96,7 +96,7 @@ def check_limit_by_virsh_dump(limit_dict): "but found memtune XML:\n%s" % guest_xml.memtune) except xcepts.LibvirtXMLNotFoundError as detail: test.log.debug( - "Did not find the memtune xml, error is:%s" % detail) + "Did not find the memtune xml, error is:%s", detail) else: memtune_element = guest_xml.memtune for key, value in limit_dict.items(): From 86d3f9ddd0f8cc76f95d6fc8129177e833d5786e Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 16 Jan 2024 12:24:58 +0800 Subject: [PATCH 0118/1055] migration: Fix no storage pool issue Signed-off-by: lcheng --- .../migration_with_copy_storage/precreate_none_target_disk.py | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/src/migration_with_copy_storage/precreate_none_target_disk.py b/libvirt/tests/src/migration_with_copy_storage/precreate_none_target_disk.py index 874911d5a25..2f66a87f747 100644 --- a/libvirt/tests/src/migration_with_copy_storage/precreate_none_target_disk.py +++ b/libvirt/tests/src/migration_with_copy_storage/precreate_none_target_disk.py @@ -89,6 +89,7 @@ def setup_test(): cmd = "qemu-img info %s -U" % disk_source_name src_image_info = process.run(cmd, ignore_status=True, shell=True).stdout_text.strip() + remote.run_remote_cmd("mkdir -p %s" % pool_target, params) virsh.pool_create_as(pool_name, pool_type, pool_target, uri=dest_uri, ignore_status=True, debug=True) From 59ee5cb78a7430a274be11380e9ead25b8cb9111 Mon Sep 17 00:00:00 2001 From: nanli Date: Tue, 19 Dec 2023 15:13:00 +0800 Subject: [PATCH 0119/1055] add case for dimm memory with auto placement numatune xxxx-299044:Dimm memory device with auto placement numatune Signed-off-by: nanli --- ...mm_memory_with_auto_placement_numatune.cfg | 36 +++++++++ ...imm_memory_with_auto_placement_numatune.py | 74 +++++++++++++++++++ .../virtio_mem_auto_placement.py | 4 +- 3 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_auto_placement_numatune.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/dimm_memory_with_auto_placement_numatune.py diff --git a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_auto_placement_numatune.cfg b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_auto_placement_numatune.cfg new file mode 100644 index 00000000000..7f67188cd79 --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_auto_placement_numatune.cfg @@ -0,0 +1,36 @@ +- memory.devices.dimm.auto_placement: + type = dimm_memory_with_auto_placement_numatune + start_vm = "no" + placement = "auto" + mem_model = "dimm" + set_size = 131072 + dimm_dict = {'mem_model': '${mem_model}', 'target': {'size': ${set_size}, 'node': 0, 'size_unit': 'KiB'}} + attach_dimm = {'mem_model': '${mem_model}', 'target': {'size': ${set_size}, 'node': 1, 'size_unit': 'KiB'}} + aarch64: + set_size = 1048576 + variants: + - strict: + tuning_mode = "strict" + mode_attrs = "'mode': '${tuning_mode}'," + - interleave: + tuning_mode = "interleave" + mode_attrs = "'mode': '${tuning_mode}'," + - preferred: + tuning_mode = "preferred" + mode_attrs = "'mode': '${tuning_mode}'," + - restrictive: + tuning_mode = "restrictive" + mode_attrs = "'mode': '${tuning_mode}'," + - undefined: + mode_attrs = "" + tuning_attrs = "'numa_memory': {${mode_attrs} 'placement': '${placement}'}" + variants: + - with_numa: + no s390-virtio + numa_mem = 1048576 + mem_value = 2490368 + current_mem = 2490368 + base_attrs = "'vcpu': 4, 'placement': '${placement}', 'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'" + numa_attrs = "'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'},{'id':'1','cpus': '2-3','memory':'${numa_mem}','unit':'KiB'}]}" + max_attrs = "'max_mem_rt': 15242880, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'" + vm_attrs = {${base_attrs}, ${numa_attrs}, ${max_attrs}, ${tuning_attrs}} diff --git a/libvirt/tests/src/memory/memory_devices/dimm_memory_with_auto_placement_numatune.py b/libvirt/tests/src/memory/memory_devices/dimm_memory_with_auto_placement_numatune.py new file mode 100644 index 00000000000..e4beeda8399 --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/dimm_memory_with_auto_placement_numatune.py @@ -0,0 +1,74 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml + +from provider.numa import numa_base + + +def run(test, params, env): + """ + 1.Define guest with dimm devices and start guest. + 2.Attach dimm memory. + """ + + def setup_test(): + """ + Check available numa nodes num. + """ + test.log.info("TEST_SETUP: Check available numa nodes num") + numa_obj = numa_base.NumaTest(vm, params, test) + numa_obj.check_numa_nodes_availability() + + def run_test(): + """ + Verify dimm memory device works with auto placement numatune. + """ + test.log.info("TEST_SETUP1: Define guest with dimm memory") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vmxml.setup_attrs(**vm_attrs) + new_dimm = libvirt_vmxml.create_vm_device_by_type('memory', dimm_dict) + vmxml.devices = vmxml.devices.append(new_dimm) + vmxml.sync() + + test.log.info("TEST_STEP2: Start vm") + vm.start() + vm.wait_for_login().close() + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + test.log.debug("Get guest xml is '%s' ", vmxml) + + test.log.info("TEST_SETUP3: Hotplug a dimm device") + attach_mem = libvirt_vmxml.create_vm_device_by_type('memory', attach_dimm) + virsh.attach_device(vm.name, attach_mem.xml, debug=True, + wait_for_event=True, ignore_status=False) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bkxml.sync() + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + vm_attrs = eval(params.get('vm_attrs', '{}')) + dimm_dict = eval(params.get('dimm_dict', '{}')) + attach_dimm = eval(params.get("attach_dimm", '{}')) + + try: + setup_test() + run_test() + + finally: + teardown_test() diff --git a/libvirt/tests/src/memory/memory_devices/virtio_mem_auto_placement.py b/libvirt/tests/src/memory/memory_devices/virtio_mem_auto_placement.py index a8c3c371706..f84970894e2 100644 --- a/libvirt/tests/src/memory/memory_devices/virtio_mem_auto_placement.py +++ b/libvirt/tests/src/memory/memory_devices/virtio_mem_auto_placement.py @@ -21,8 +21,8 @@ def run(test, params, env): """ - 1.Define guest with dimm devices. - 2.Attach dimm and check mem value + 1.Define guest with virtio-mem devices. + 2.Attach virtio-mem and check mem value """ def setup_test(): From f33556ae0d7c5b41554d26f33b33497d9669f573 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Wed, 17 Jan 2024 15:00:31 +0800 Subject: [PATCH 0120/1055] v2v:fix functional failed TC "luks-partition" Signed-off-by: vwu-vera --- v2v/tests/cfg/function_test_esx.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 7f6f3259805..34a68e4b580 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -667,7 +667,7 @@ version_required = "[virt-v2v-2.0.7-2,)" main_vm = VM_NAME_CLEVIS_LUKS_V2V_EXAMPLE luks_partition = VM_LUKS_PARTITION_EXAMPLE - v2v_opts = "--key "${luks_partition}":clevis" + v2v_opts = "--key ${luks_partition}:clevis" - logs: only esx_70 main_vm = VM_NAME_ESX_DEFAULT_V2V_EXAMPLE From 9c6308ffbb9cac99fc5e23c0c060020b819e578f Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Wed, 17 Jan 2024 02:13:06 -0500 Subject: [PATCH 0121/1055] Add new case of start vm with specific mac address - VIRT-296221 - [mac] Start vm or hotplug interface with specific mac address Signed-off-by: Haijiao Zhao --- .../element_mac_specific_addr.cfg | 38 +++++++ .../element_mac_specific_addr.py | 102 ++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/elements_and_attributes/element_mac_specific_addr.cfg create mode 100644 libvirt/tests/src/virtual_network/elements_and_attributes/element_mac_specific_addr.py diff --git a/libvirt/tests/cfg/virtual_network/elements_and_attributes/element_mac_specific_addr.cfg b/libvirt/tests/cfg/virtual_network/elements_and_attributes/element_mac_specific_addr.cfg new file mode 100644 index 00000000000..168ac563c4b --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/elements_and_attributes/element_mac_specific_addr.cfg @@ -0,0 +1,38 @@ +- virtual_network.elements_and_attributes.mac.specific_addr: + type = element_mac_specific_addr + start_vm = no + timeout = 240 + outside_ip = 'www.redhat.com' + vm_ping_outside = pass + variants scenario: + - pre_set: + - hotplug: + variants: + - default: + mac = {} + expect_xml_mac = 52:54:00.* + expect_tap_mac = fe: + - starts_with_0xfe: + set_mac = 'fe:54:00:70:58:07' + mac = {'mac_address': '${set_mac}'} + expect_xml_mac = ${set_mac} + expect_tap_mac = fa: + - all_zeros: + mac = {'mac_address': '00:00:00:00:00:00'} + expect_xml_mac = 52:54:00.* + expect_tap_mac = fe: + - multicast_addr: + mac = {'mac_address': '01:54:00:bc:f3:ec'} + status_error = yes + err_msg = expected unicast mac address, found multicast + - null_addr: + mac = {'mac_address': 'null'} + status_error = yes + err_msg = unable to parse mac address + - null_addr: + mac = {'mac_address': 'zero'} + status_error = yes + err_msg = unable to parse mac address + + iface_attrs = {**${mac}, 'model': 'virtio', 'type_name': 'network', 'source': {'network': 'default'}} + diff --git a/libvirt/tests/src/virtual_network/elements_and_attributes/element_mac_specific_addr.py b/libvirt/tests/src/virtual_network/elements_and_attributes/element_mac_specific_addr.py new file mode 100644 index 00000000000..9f68800016f --- /dev/null +++ b/libvirt/tests/src/virtual_network/elements_and_attributes/element_mac_specific_addr.py @@ -0,0 +1,102 @@ +import logging +import re + +from virttest import utils_net +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test start vm or hotplug interface with specific mac address + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + scenario = params.get('scenario') + outside_ip = params.get('outside_ip') + status_error = 'yes' == params.get('status_error', 'no') + err_msg = params.get('err_msg') + set_mac = eval(params.get('mac', {})).get('mac_address') + iface_attrs = eval(params.get('iface_attrs', '{}')) + expect_xml_mac = params.get('expect_xml_mac') + expect_tap_mac = params.get('expect_tap_mac') + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + vmxml.del_device('interface', by_tag=True) + if scenario == 'pre_set': + iface = libvirt_vmxml.create_vm_device_by_type('interface', + iface_attrs) + vmxml.add_device(iface) + LOG.debug(f'Interface to add to vm:\n{iface}') + + if status_error: + start_result = virsh.define(vmxml.xml, debug=True) + libvirt.check_exit_status(start_result, status_error) + if err_msg: + libvirt.check_result(start_result, expected_fails=err_msg) + return + else: + vmxml.sync() + vm.start() + + elif scenario == 'hotplug': + vmxml.sync() + vm.start() + if set_mac: + at_options = f'network default --mac {set_mac} --model virtio' + else: + at_options = f'network default --model virtio' + + at_result = virsh.attach_interface(vm_name, at_options, debug=True) + libvirt.check_exit_status(at_result, status_error) + if status_error: + if err_msg: + libvirt.check_result(at_result, expected_fails=err_msg) + return + + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + iface_xml = vmxml.get_devices('interface')[0] + LOG.debug(f'Interface in vmxml:\n{iface_xml}') + vmxml_mac = iface_xml.mac_address + if not re.match(expect_xml_mac, vmxml_mac): + test.fail(f'Expect mac address on vmxml: {expect_tap_mac}, ' + f'not {vmxml_mac}') + + virsh.domiflist(vm_name, **VIRSH_ARGS) + iflist = libvirt.get_interface_details(vm_name) + LOG.debug(f'iflist of vm: {iflist}') + tap_on_host = iflist[0]['interface'] + LOG.debug(f'Tap device on host: {tap_on_host}') + + # Get the expected mac address of tap device from mac address on vmxml + expect_tap_mac = re.sub('^\w+:', expect_tap_mac, vmxml_mac) + LOG.debug(f'Expect mac address of tap device on host: {expect_tap_mac}') + tap_mac = utils_net.get_linux_iface_info(iface=tap_on_host)['address'] + if not re.match(expect_tap_mac, tap_mac): + test.fail(f'Expect mac address of tap device: {expect_tap_mac} ' + f'not {tap_mac}') + + session = vm.wait_for_serial_login() + ip_in_vm = session.cmd_output('ip addr') + LOG.debug(f'ip addr output on vm:\n{ip_in_vm}') + if vmxml_mac not in ip_in_vm: + test.fail(f'Not found mac address from vmxml {vmxml_mac} in vm.') + + ips = {'outside_ip': outside_ip} + network_base.ping_check(params, ips, session, force_ipv4=True) + session.close() + + finally: + bkxml.sync() From 3bcb920974c4b87ec6884e99e7dea5870ab444a8 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Thu, 18 Jan 2024 11:46:09 +0800 Subject: [PATCH 0122/1055] Test guest with space name via vmx+ssh Signed-off-by: Ming Xie --- v2v/tests/cfg/convert_from_file.cfg | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/v2v/tests/cfg/convert_from_file.cfg b/v2v/tests/cfg/convert_from_file.cfg index 84d1586e4ea..772d403505f 100644 --- a/v2v/tests/cfg/convert_from_file.cfg +++ b/v2v/tests/cfg/convert_from_file.cfg @@ -218,6 +218,12 @@ version_required = "[virt-v2v-2.0.7-1.el9,)" main_vm = 'VM_NAME_PERCENT_ENCODING_RHEL9_V2V_EXAMPLE' datastore = esx7.0-function + - space_name: + only esx_80 + only output_mode.libvirt + boottype = 3 + version_required = "[virt-v2v-2.3.4-6.el9,)" + main_vm = "VM_NAME_SPACE_NAME_VMX_V2V_EXAMPLE" - vmx_default: # Default vmx_nfs_src = NFS_ESX67_VMX_V2V_EXAMPLE From 754c382bd54ed2998123d279ae3e5cfc49e8c4fd Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Sun, 21 Jan 2024 21:07:40 -0500 Subject: [PATCH 0123/1055] Add paramter description for functions Signed-off-by: liang-cong-red-hat --- .../memory_tuning/memory_tuning_settings.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py b/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py index 637757dee95..77d1ee1f5dd 100644 --- a/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py +++ b/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py @@ -29,6 +29,9 @@ def run(test, params, env): def adjust_limit_for_memory_page(limit_dict): """ Limit value would be aligned to the default memory page size + + :param params: dict of memory limitation + :return: dict, adjucted memory limitation dict from host page size """ default_page_size = utils_memory.getpagesize() return {key: (value // default_page_size * default_page_size) @@ -37,6 +40,8 @@ def adjust_limit_for_memory_page(limit_dict): def check_limit_by_virsh_memtune(limit_dict): """ Check the memtune limit is expected by virsh memtune + + :param params: dict of memory limitation """ expected_limit_dict = adjust_limit_for_memory_page(limit_dict) for key, value in expected_limit_dict.items(): @@ -48,6 +53,8 @@ def check_limit_by_virsh_memtune(limit_dict): def set_limit_by_virsh_memtune_in_turn(limit_dict): """ Set memory limit by virsh memtune one by one + + :param params: dict of memory limitation """ vm_pid = vm.get_pid() cg = libvirt_cgroup.CgroupTest(vm_pid) @@ -63,6 +70,8 @@ def set_limit_by_virsh_memtune_in_turn(limit_dict): def set_limit_by_virsh_memtune_once(limit_dict): """ Set memory limit by virsh memtune all together + + :param params: dict of memory limitation """ limit_value_list = [str(limit_dict[limit_name]) for limit_name in memtune_cmd_parameter_seq] @@ -72,6 +81,8 @@ def set_limit_by_virsh_memtune_once(limit_dict): def check_limit_by_cgroup(limit_dict): """ Check the memtune limit is expected by cgroup + + :param params: dict of memory limitation """ adjusted_limit_dict = adjust_limit_for_memory_page(limit_dict) expected_limit_dict = {key: (value*1024) if value != -1 else 'max' @@ -87,6 +98,8 @@ def check_limit_by_cgroup(limit_dict): def check_limit_by_virsh_dump(limit_dict): """ check the memtune limit is expected by virsh dump + + :param params: dict of memory limitation """ guest_xml = vm_xml.VMXML.new_from_dumpxml(vm.name) if len(set(limit_dict.values())) == 1 and list(limit_dict.values())[0] == -1: @@ -108,6 +121,8 @@ def check_limit_by_virsh_dump(limit_dict): def check_guest_memtune_related_values(limit_dict): """ check memtune by cmd virsh memtune, cgroup value and guest config xml + + :param params: dict of memory limitation """ test.log.info("Check the memtune value by virsh memtune") check_limit_by_virsh_memtune(limit_dict) From 5c9889c1aaad79464cc76b006dc3475b0a40033f Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Sun, 21 Jan 2024 21:13:10 -0500 Subject: [PATCH 0124/1055] Change typo Signed-off-by: liang-cong-red-hat --- .../tests/src/memory/memory_tuning/memory_tuning_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py b/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py index 77d1ee1f5dd..0a7aeae965e 100644 --- a/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py +++ b/libvirt/tests/src/memory/memory_tuning/memory_tuning_settings.py @@ -31,7 +31,7 @@ def adjust_limit_for_memory_page(limit_dict): Limit value would be aligned to the default memory page size :param params: dict of memory limitation - :return: dict, adjucted memory limitation dict from host page size + :return: dict, adjusted memory limitation dict from host page size """ default_page_size = utils_memory.getpagesize() return {key: (value // default_page_size * default_page_size) From b4f95fa8abf4da8d7211291f44ee20988f5adad9 Mon Sep 17 00:00:00 2001 From: Hu Shuai Date: Mon, 22 Jan 2024 16:27:14 +0800 Subject: [PATCH 0125/1055] memory: Fix the expected memory size after balloon For memory balloon: On 4k kernel guest, the memory will align up. On 64k kernel guest, the memory will align down. Signed-off-by: Hu Shuai --- .../memory_allocation/define_value_unit.py | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/libvirt/tests/src/memory/memory_allocation/define_value_unit.py b/libvirt/tests/src/memory/memory_allocation/define_value_unit.py index b27f17b9680..c88073c9ed9 100644 --- a/libvirt/tests/src/memory/memory_allocation/define_value_unit.py +++ b/libvirt/tests/src/memory/memory_allocation/define_value_unit.py @@ -50,12 +50,12 @@ def run_positive_test(): test.log.info("TEST_STEP4: Check guest memory value") session = vm.wait_for_login() guest_mem = utils_misc.get_mem_info(session) - session.close() test.log.debug("Get memory value in guest: %s", guest_mem) test.log.info("TEST_STEP5: Check currentmemory change to " "the value and round up to a multiple of default pagesize") - check_mem_after_operation('login') + check_mem_after_operation('login', session) + session.close() vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) current_mem_new = vmxml.get_current_mem() @@ -107,14 +107,14 @@ def check_mem_config(dest_unit): for item in eval(pattern): libvirt_vmxml.check_guest_xml_by_xpaths(vmxml, item) - def check_mem_after_operation(operation="start"): + def check_mem_after_operation(operation="start", session=None): """ Check mem after operation :param operation: guest operation """ new_vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) - result = get_expected_result(operation) + result = get_expected_result(operation, session) for attr in eval(params.get("vm_attrs")).keys(): if attr == "cpu": numa_memory = new_vmxml.cpu.numa_cell[0]['memory'] @@ -161,7 +161,7 @@ def set_negative_memory(case): cmd_result = virsh.define(vmxml.xml, debug=True) libvirt.check_result(cmd_result, error_msg) - def get_dest_size(source_size, operation="start", check_current_mem=False): + def get_dest_size(source_size, operation="start", check_current_mem=False, session=None): """ Round up the source size and convert dest size according to the operation @@ -194,7 +194,12 @@ def get_dest_size(source_size, operation="start", check_current_mem=False): dest_unit = 'KiB' convert_size = memory_base.convert_data_size(source_size, dest_unit) - round_up_size = math.ceil(convert_size/default_pagesize) + conf_page_size = session.cmd_output('getconf PAGE_SIZE') + test.log.debug('The PAGE_SIZE of guest is %s', conf_page_size) + if int(conf_page_size) == 65536: + round_up_size = math.floor(convert_size/default_pagesize) + else: + round_up_size = math.ceil(convert_size/default_pagesize) dest_size = round_up_size * default_pagesize else: @@ -210,7 +215,7 @@ def get_dest_size(source_size, operation="start", check_current_mem=False): return int(dest_size) - def get_expected_result(operation='start'): + def get_expected_result(operation='start', session=None): """ Get expected memory result. @@ -220,7 +225,8 @@ def get_expected_result(operation='start'): result_dict.update({ 'memory': get_dest_size(mem_value+mem_unit, operation), 'current_mem': get_dest_size(current_mem+current_mem_unit, - operation, check_current_mem=True), + operation, check_current_mem=True, + session=session), "max_mem_rt": get_dest_size(max_mem+max_mem_unit, operation), "numa_memory": get_dest_size(mem_value+mem_unit, operation), }) From fa34e06a66d18c2c2943c5a250df9a48f71e6590 Mon Sep 17 00:00:00 2001 From: nanli Date: Fri, 29 Dec 2023 10:22:24 +0800 Subject: [PATCH 0126/1055] add case for file backed nvdimm memory lifecycle VIRT-299192: Life cycle of file backed nvdimm memory device Signed-off-by: nanli --- ...ifecycle_for_file_backed_nvdimm_memory.cfg | 70 ++++ ...lifecycle_for_file_backed_nvdimm_memory.py | 305 ++++++++++++++++++ provider/memory/memory_base.py | 42 +++ 3 files changed, 417 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_devices/lifecycle_for_file_backed_nvdimm_memory.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/lifecycle_for_file_backed_nvdimm_memory.py diff --git a/libvirt/tests/cfg/memory/memory_devices/lifecycle_for_file_backed_nvdimm_memory.cfg b/libvirt/tests/cfg/memory/memory_devices/lifecycle_for_file_backed_nvdimm_memory.cfg new file mode 100644 index 00000000000..7ba8e42fb99 --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/lifecycle_for_file_backed_nvdimm_memory.cfg @@ -0,0 +1,70 @@ +- memory.devices.file_nvdimm.lifecycle: + no s390-virtio + type = lifecycle_for_file_backed_nvdimm_memory + start_vm = no + target_size = 524288 + nvdimm_file_size = "512M" + source_path = "/tmp/nvdimm1" + source_path_attach = "/tmp/nvdimm2" + addr_slot = "1" + addr_slot_attach = "2" + addr_base = "0x200000000" + addr_base_attach = "0x240000000" + check_alignment = '{"execute":"qom-get", "arguments":{"path": "/objects/mem%s", "property":"align"}}' + nvdimm_devices = "/dev/pmem0 /dev/pmem1" + check_nvdimm_devices = "ls ${nvdimm_devices}" + file_content = "test_text" + target_node = 0 + target_node_attach = 1 + nvdimm_path = "/mnt/nvdimm1" + nvdimm_path_attach = "/mnt/nvdimm2" + mount_file_1 = "${nvdimm_path}/file1" + mount_file_2 = "${nvdimm_path_attach}/file2" + paths = ["${nvdimm_path}", "${nvdimm_path_attach}"] + nodes = ["${target_node}", "${target_node_attach}"] + save_file = "/tmp/guest.save" + variants source_config: + - access_shared: + access = "shared" + access_attrs = "" + expected_align = "0" + content_existed = True + - access_private_alignsize: + alignsize = 2048 + access = "private" + access_attrs = "'alignsize':${alignsize},'alignsize_unit': 'KiB'," + expected_align = "2097152" + content_existed = "" + variants target_config: + - target_label: + label_size = 128 + label_attrs = "'label':{'size_unit':'KiB','size':${label_size}}," + readonly_attrs = "" + - target_readonly: + label_attrs = "" + readonly_attrs = "'readonly':True" + error_msg = "Operation not permitted" + variants address_config: + - addr_undefined: + addr_attrs = "" + addr_attach_attrs = "" + alias_name = ["nvdimm0", "nvdimm1"] + - addr_slot_base: + addr_attrs = "'address':{'attrs': {'base': '${addr_base}','slot': '${addr_slot}'}}" + addr_attach_attrs = "'address':{'attrs': {'base': '${addr_base_attach}','slot': '${addr_slot_attach}'}}" + alias_name = ["nvdimm${addr_slot}", "nvdimm${addr_slot_attach}"] + source_attrs = "'source': {${access_attrs} 'path': '${source_path}'}" + target_attrs = "'target': {'size': ${target_size},'size_unit': 'KiB','node':${target_node_attach}, ${label_attrs}${readonly_attrs}}" + nvdimm_dict = {'mem_model':'nvdimm', 'mem_access':'${access}',${source_attrs},${target_attrs},${addr_attrs}} + source_attach_attrs = "'source': {${access_attrs} 'path': '${source_path_attach}'}" + target_attach_attrs = "'target': {'size': ${target_size},'size_unit': 'KiB','node':${target_node}, ${label_attrs}${readonly_attrs}}" + nvdimm_attach_dict = {'mem_model':'nvdimm', 'mem_access':'${access}',${source_attach_attrs},${target_attach_attrs},${addr_attach_attrs}} + variants: + - with_numa: + numa_mem = 1048576 + mem_value = 2097152 + current_mem = 2097152 + base_attrs = "'vcpu': 4, 'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'" + numa_attrs = "'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'},{'id':'1','cpus': '2-3','memory':'${numa_mem}','unit':'KiB'}]}" + max_attrs = "'max_mem_rt': 15242880, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'" + vm_attrs = {${base_attrs}, ${numa_attrs}, ${max_attrs}} diff --git a/libvirt/tests/src/memory/memory_devices/lifecycle_for_file_backed_nvdimm_memory.py b/libvirt/tests/src/memory/memory_devices/lifecycle_for_file_backed_nvdimm_memory.py new file mode 100644 index 00000000000..44f8a64bb2f --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/lifecycle_for_file_backed_nvdimm_memory.py @@ -0,0 +1,305 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import os +import re +import json + +from avocado.utils import process + +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirtd import Libvirtd +from virttest.utils_libvirt import libvirt_vmxml + +from provider.memory import memory_base + + +def check_nvdimm_config(params, test, mem_index=0): + """ + Check nvdimm memory devices xml config. + + :param params: Optional new VM creation parameters. + :param test: test object. + :param mem_index: memory index in memory list, default 0. + """ + address_config = params.get("address_config") + addr_slot = [params.get("addr_slot"), params.get("addr_slot_attach")] + addr_base = [params.get("addr_base"), params.get("addr_base_attach")] + alias_name = eval(params.get("alias_name", "[]")) + target = [eval(params.get("target_attrs")[10:]), + eval(params.get("target_attach_attrs")[10:])] + source = [eval(params.get("source_attrs")[10:]), + eval(params.get("source_attach_attrs")[10:])] + + vmxml = vm_xml.VMXML.new_from_dumpxml(params.get("main_vm")) + actual_attrs = vmxml.devices.by_device_tag('memory')[mem_index].fetch_attrs() + test.log.debug("Get actual memory attrs: %s", actual_attrs) + + def _compare_values(expected, actual): + if expected != actual: + test.fail("Expect to get '%s' instead of '%s' " % (expected, actual)) + else: + test.log.debug("Check %s PASS", actual) + _compare_values(source[mem_index], actual_attrs['source']) + _compare_values(target[mem_index], actual_attrs['target']) + _compare_values(alias_name[mem_index], actual_attrs['alias']['name']) + if address_config != "addr_undefined": + _compare_values(addr_slot[mem_index], actual_attrs['address']['attrs']['slot']) + _compare_values(addr_base[mem_index], actual_attrs['address']['attrs']['base']) + + +def check_nvdimm_device_content(test, params, session, expected_content, + existed=True): + """ + Check the nvdimm device content exist or not. + + :param test: test object. + :param params: Optional new VM creation parameters. + :param session: guest session. + :param expected_content: expected file content. + :param existed: bool type, True if expected_content existed. + """ + mount_file_1 = params.get("mount_file_1") + mount_file_2 = params.get("mount_file_2") + nvdimm_devices = params.get("nvdimm_devices").split(" ") + paths = eval(params.get("paths")) + + def _get_uuid(vm_session): + uuids = [] + for dev in nvdimm_devices: + uuid_out = vm_session.cmd_output('blkid %s' % dev) + uuid = re.findall(r' UUID="(\S+)"', uuid_out)[0] + if not uuid: + test.fail("Expect to get uuid in '%s'" % uuid_out) + uuids.append(uuid) + params.update({'uuids': uuids}) + + if existed: + # Check if mounted and remount + for index in range(len(paths)): + if not session.cmd_output("mount | grep '%s'" % paths[index]): + if not params.get("uuids"): + _get_uuid(session) + session.cmd_output('mount -o dax -U {} {}'.format( + params.get('uuids')[index], paths[index])) + + # Check file content + for item in [mount_file_1, mount_file_2]: + output = session.cmd_output('cat %s ' % item).strip() + if expected_content not in output: + test.fail('"%s" should be in output:"%s"' % (expected_content, output)) + test.log.debug("Check '%s' in '%s' is '%s' PASS", + expected_content, output, [mount_file_1, mount_file_2]) + else: + # Check blkid is not existed. + for dev in nvdimm_devices: + output = session.cmd_output('blkid %s ' % dev).strip() + if output: + test.fail("Expect to get no blkid, but got:'%s'" % output) + + +def check_alignment_value(params, test, check_cmd): + """ + Check guest alignment value by virsh qemu_monitor_command + + :param params: dictionary with the test parameters + :param test: test object + :param check_cmd: the cmd option of virsh qemu_monitor_command + """ + vm_name = params.get("main_vm") + expected_align = params.get("expected_align") + + result = virsh.qemu_monitor_command(vm_name, check_cmd, debug=True).stdout_text + actual_align = str(json.loads(result)['return']) + if actual_align != expected_align: + test.fail("Expected alignment value '%s' instead of '%s'" % ( + expected_align, actual_align)) + + +def do_domain_lifecyle(params, vm, test): + """ + Do lifecycle for guest. + + :param params: Dictionary with the test parameters + :param vm: vm object + :param test: test object + """ + virsh_dargs = {'debug': True, 'ignore_status': False} + target_config = params.get("target_config") + file_content = params.get("file_content") + + def _check_after_operation(): + session = vm.wait_for_login() + if target_config != "target_readonly": + check_nvdimm_device_content(test, params, session, file_content) + check_nvdimm_config(params, test) + check_nvdimm_config(params, test, mem_index=1) + session.close() + + virsh.suspend(vm.name, **virsh_dargs) + virsh.resume(vm.name, **virsh_dargs) + _check_after_operation() + + virsh.reboot(vm.name, **virsh_dargs) + _check_after_operation() + + save_file = params.get("save_file") + if os.path.exists(save_file): + os.remove(save_file) + virsh.save(vm.name, save_file, **virsh_dargs) + virsh.restore(save_file, **virsh_dargs) + _check_after_operation() + + virsh.managedsave(vm.name, **virsh_dargs) + vm.start() + _check_after_operation() + + virsh.reboot(vm.name, **virsh_dargs) + _check_after_operation() + + Libvirtd().restart() + _check_after_operation() + + +def run(test, params, env): + """ + Verify various configs of file backed nvdimm memory device take effect + during the life cycle of guest vm. + """ + + def setup_test(): + """ + Create file backend for nvdimm device + """ + test.log.info("Setup env.") + for path in [source_path, source_path_attach]: + process.run('truncate -s %s %s' % (nvdimm_file_size, path), + verbose=True, shell=True) + + def run_test(): + """ + 1. Define a vm with a nvdimm memory device and check the nvdimm configuration. + 2. Hotplug an nvdimm memory device and check the nvdimm configuration. + 3. Check the alignment with the virsh qemu-monitor-command. + 4. Create a file system on two nvdimm devices in the guest. + 6. Lifecycle checks for a guest with an attached device. + 7. Hotplug another nvdimm device. + """ + test.log.info("TEST_STEP1: Define vm with nvdimm memory device") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vmxml.setup_attrs(**vm_attrs) + mem_obj = libvirt_vmxml.create_vm_device_by_type('memory', nvdimm_dict) + vmxml.devices = vmxml.devices.append(mem_obj) + vmxml.sync() + + test.log.info("TEST_STEP2: Start guest") + vm.start() + vm.wait_for_login().close() + + test.log.info("TEST_STEP3: Check nvdimm memory device xml") + check_nvdimm_config(params, test) + + test.log.info("TEST_STEP4: Hot plug all memory device") + attach_mem = libvirt_vmxml.create_vm_device_by_type('memory', nvdimm_attach_dict) + virsh.attach_device(vm_name, attach_mem.xml, **virsh_dargs) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + test.log.debug('Get xml after attaching memory is "%s"', vmxml) + + test.log.info("TEST_STEP5: Check nvdimm memory device xml") + check_nvdimm_config(params, test) + check_nvdimm_config(params, test, mem_index=1) + + test.log.info("TEST_STEP6:Check alignment by virsh.qemu-monitor-command") + check_alignment_value(params, test, check_alignment % alias_name[0]) + check_alignment_value(params, test, check_alignment % alias_name[1]) + + test.log.info("TEST_STEP7: Login guest and check nvdimm memory device") + session = vm.wait_for_login() + for dev in nvdimm_devices: + status, output = session.cmd_status_output("ls %s" % dev) + if status: + test.fail("Expect nvdimm device in guest, but got: %s" % output) + + test.log.info("TEST_STEP8: Create file system on two nvdimme device") + memory_base.create_file_within_nvdimm_disk( + test, session, test_device=nvdimm_devices[0], + mount_point=nvdimm_path, test_file=mount_file_1, + test_str=file_content, error_msg=error_msg) + memory_base.create_file_within_nvdimm_disk( + test, session, test_device=nvdimm_devices[1], + mount_point=nvdimm_path_attach, test_file=mount_file_2, + test_str=file_content, error_msg=error_msg) + session.close() + + test.log.info("TEST_STEP9: Do lifecycle") + do_domain_lifecyle(params, vm, test) + + if target_config != "target_readonly": + test.log.info("TEST_STEP10: Attach device again") + virsh.destroy(vm_name) + virsh.start(vm_name) + virsh.attach_device(vm_name, attach_mem.xml, **virsh_dargs) + + test.log.info("TEST_STEP11: Login the guest to check the file") + session = vm.wait_for_login() + check_nvdimm_device_content(test, params, session, file_content, + existed=content_existed) + session.close() + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bkxml.sync() + if not vm.is_alive(): + vm.start() + session = vm.wait_for_login() + for file in [mount_file_1, mount_file_2]: + session.cmd("rm -f %s " % file) + session.close() + + bkxml.sync() + + for file in [source_path, source_path_attach]: + if os.path.exists(file): + os.remove(file) + + vm_name = params.get("main_vm") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + vm = env.get_vm(vm_name) + + vm_attrs = eval(params.get("vm_attrs", "{}")) + nvdimm_dict = eval(params.get("nvdimm_dict")) + nvdimm_attach_dict = eval(params.get("nvdimm_attach_dict")) + error_msg = params.get("error_msg") + nvdimm_path = params.get("nvdimm_path") + nvdimm_path_attach = params.get("nvdimm_path_attach") + source_path = params.get("source_path") + source_path_attach = params.get("source_path_attach") + mount_file_1 = params.get("mount_file_1") + mount_file_2 = params.get("mount_file_2") + file_content = params.get("file_content") + nvdimm_file_size = params.get("nvdimm_file_size") + nvdimm_devices = params.get("nvdimm_devices").split(" ") + target_config = params.get("target_config",) + content_existed = bool(params.get("content_existed")) + check_alignment = params.get("check_alignment") + alias_name = eval(params.get("alias_name", "[]")) + virsh_dargs = {'debug': True, 'ignore_status': False} + + try: + setup_test() + run_test() + + finally: + teardown_test() diff --git a/provider/memory/memory_base.py b/provider/memory/memory_base.py index 5500110e1e2..db83b3c49dc 100644 --- a/provider/memory/memory_base.py +++ b/provider/memory/memory_base.py @@ -1,4 +1,5 @@ import re +import platform from virttest import libvirt_version from virttest import utils_misc @@ -89,3 +90,44 @@ def prepare_mem_obj(dest_dict): mem_obj.setup_attrs(**dest_dict) return mem_obj + + +def create_file_within_nvdimm_disk(test, vm_session, test_device, test_file, + mount_point, error_msg="", test_str="test_text", + block_size=4096): + """ + Create a test file in the nvdimm file disk + + :param test: test object + :param vm_session: VM session + :param test_device: str, device value + :param test_file: str, file name to be used + :param mount_point: mount point path. + :param error_msg: Error msg content when useing mkfs cmd + :param test_str: str to be written into the nvdimm file disk + :param block_size: int, block size for mkfs.xfs -b + """ + # Create a file system + bsize_str = '-b size={}'.format(block_size) if block_size != 0 else '' + if any(platform.platform().find(ver) for ver in ('el8', 'el9')): + cmd = 'mkfs.xfs -f {} {} -m reflink=0'.format(test_device, bsize_str) + else: + cmd = 'mkfs.xfs -f {} {}'.format(test_device, bsize_str) + + vm_session.cmd("mkdir -p %s" % mount_point) + output = vm_session.cmd_output(cmd) + if error_msg: + if error_msg not in output: + test.fail("Expect to get '%s' in '%s'" % (error_msg, output)) + else: + return + test.log.debug("Command '%s' output:%s", cmd, output) + + # Mount the file system + uuid = re.findall( + r' UUID="(\S+)"', vm_session.cmd_output('blkid %s' % test_device))[0] + vm_session.cmd_status_output('mount -o dax -U {} {}'.format(uuid, mount_point)) + + cmd = 'echo \"%s\" >%s' % (test_str, test_file) + vm_session.cmd(cmd) + vm_session.cmd_output('umount %s' % mount_point) From f2548d751b2c975611faa5c467b9339027aad15f Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Tue, 23 Jan 2024 02:19:37 -0500 Subject: [PATCH 0127/1055] Add hotplug empty source cdrom device VIRT-xx: Succeed to attach a CDROM without source Signed-off-by: chunfuwen --- .../virtual_disks_cdrom_device.cfg | 7 ++++++ .../virtual_disks_cdrom_device.py | 22 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_cdrom_device.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_cdrom_device.cfg index fd7f467d168..9a449da44f6 100755 --- a/libvirt/tests/cfg/virtual_disks/virtual_disks_cdrom_device.cfg +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_cdrom_device.cfg @@ -122,6 +122,13 @@ backend_device = "scsi_cdrom_hot_eject_backend" tray_state = "locked, tray closed" only hotplug..positive_test + - empty_source_cdrom_backend: + func_supported_since_libvirt_ver = (9, 10, 0) + type_name = "file" + target_format = "raw" + target_dev = "sdd" + backend_device = "empty_source_cdrom_backend" + only hotplug..positive_test variants: - hotplug: virt_device_hotplug = "yes" diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_cdrom_device.py b/libvirt/tests/src/virtual_disks/virtual_disks_cdrom_device.py index 35e4fc54fc6..fc85b56b11b 100755 --- a/libvirt/tests/src/virtual_disks/virtual_disks_cdrom_device.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_cdrom_device.py @@ -493,6 +493,23 @@ def _get_qemu_state(): test.fail("cdrom disk can not be detached successfully") +def check_empty_source_cdrom(vm, params, test): + """ + Check hotplug empty source cdrom + + :param vm: one object representing VM + :param params: wrapped parameters in dictionary format + :param test: test assert object + """ + vm.wait_for_login().close() + # hotplug cdrom device + device_obj = params.get("cdrom_xml") + virsh.attach_device(vm.name, device_obj.xml, flagstr="--live", ignore_status=False, debug=True) + + # Check cdrom is present in disk xml + check_source_in_cdrom_device(vm, None, test) + + def run(test, params, env): """ Test attach cdrom device with option. @@ -557,6 +574,9 @@ def run(test, params, env): ignore_status=False, debug=True) if backend_device == "block_lun_source": device_obj = create_block_lun_source_disk(params) + if backend_device == "empty_source_cdrom_backend": + device_obj = create_customized_disk(params) + params.update({'cdrom_xml': device_obj}) if not hotplug: # Sync VM xml. vmxml.add_device(device_obj) @@ -614,6 +634,8 @@ def run(test, params, env): check_cdrom_reboot_reset(vm, params, test) elif backend_device == "scsi_cdrom_hot_eject_backend": check_scsi_cdrom_hot_eject(vm, params, test) + elif backend_device == "empty_source_cdrom_backend": + check_empty_source_cdrom(vm, params, test) finally: # Recover VM. if vm.is_alive(): From 0f08bb6d7fdac05ac427c31d9a67bd76f8d229ba Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Tue, 23 Jan 2024 19:41:50 -0500 Subject: [PATCH 0128/1055] Fix get bootime timeout issue In some low performance guest, it takes more time to get uptime value Signed-off-by: chunfuwen --- libvirt/tests/src/virsh_cmd/domain/virsh_reboot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_reboot.py b/libvirt/tests/src/virsh_cmd/domain/virsh_reboot.py index a9c580b776d..3a4748893b9 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_reboot.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_reboot.py @@ -50,7 +50,7 @@ def get_boot_time(): logging.error("Get boot_time error:%s" % e) return boot_time - boot_time = utils_misc.wait_for(get_boot_time, 60) + boot_time = utils_misc.wait_for(get_boot_time, 120) session.close() return boot_time From 077331e734f8ffd10c46d2494b10f1a81c332d58 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Tue, 23 Jan 2024 22:25:36 -0500 Subject: [PATCH 0129/1055] Fix io_uring failure queue_size in driver is not supported Signed-off-by: chunfuwen --- libvirt/tests/cfg/virtual_disks/virtual_disks_io_tuning.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_io_tuning.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_io_tuning.cfg index 73deead6f3a..e2c65cebbf2 100755 --- a/libvirt/tests/cfg/virtual_disks/virtual_disks_io_tuning.cfg +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_io_tuning.cfg @@ -7,7 +7,7 @@ func_supported_since_libvirt_ver = (9, 3, 0) variants test_scenario: - normal_start: - driver_attribute = {'name': "qemu", 'type': "qcow2", 'queue_size': '1024', 'io': 'io_uring'} + driver_attribute = {'name': "qemu", 'type': "qcow2", 'io': 'io_uring'} source_file_path = "/var/lib/libvirt/images/io_uring.qcow2" target_device = "sdb" variants plug_mode: From 602282a12a551003fb55b57cbb5105a0c7079ca0 Mon Sep 17 00:00:00 2001 From: nanli Date: Wed, 24 Jan 2024 14:37:27 +0800 Subject: [PATCH 0130/1055] fix blockcopy too fast to test Signed-off-by: nanli --- .../blockjob/blockjob_pivot_after_irregular_operations.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/backingchain/blockjob/blockjob_pivot_after_irregular_operations.cfg b/libvirt/tests/cfg/backingchain/blockjob/blockjob_pivot_after_irregular_operations.cfg index 755d43cff14..675da48ad84 100644 --- a/libvirt/tests/cfg/backingchain/blockjob/blockjob_pivot_after_irregular_operations.cfg +++ b/libvirt/tests/cfg/backingchain/blockjob/blockjob_pivot_after_irregular_operations.cfg @@ -6,7 +6,7 @@ abort_option = " --abort" variants test_scenario: - before_finish: - blockcopy_options = "blockcopy %s %s %s --transient-job --bandwidth 2" + blockcopy_options = "blockcopy %s %s %s --transient-job --bytes 200" err_msg = "not ready for pivot yet" - delete_copy_file: blockcopy_options = " --transient-job --wait --verbose " From 40b1324887851acc3abc1c88bc250faea279b032 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Tue, 23 Jan 2024 19:16:25 -0500 Subject: [PATCH 0131/1055] Fix rng dd command timeout issue In some low performance VM, relative big write operation will lead to dd timeout Signed-off-by: chunfuwen --- libvirt/tests/src/libvirt_rng.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/libvirt_rng.py b/libvirt/tests/src/libvirt_rng.py index d6b0a4aa6c9..34267744031 100644 --- a/libvirt/tests/src/libvirt_rng.py +++ b/libvirt/tests/src/libvirt_rng.py @@ -377,7 +377,7 @@ def check_guest(session, expect_fail=False, rng_rate = params.get("rng_rate") # For rng rate test this command and return in a short time # but for other test it will hang - cmd = ("dd if=/dev/hwrng of=rng.test count=100" + cmd = ("dd if=/dev/hwrng of=rng.test bs=1M count=10" " && rm -f rng.test") try: ret, output = session.cmd_status_output(cmd, timeout=timeout) From 5edf372ecae8150f38c2db14f5fd560f1d5a0f69 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 24 Jan 2024 11:06:20 -0500 Subject: [PATCH 0132/1055] libvirtd_conf: improve test error `libvirt.check_logfile` will raise test failure if expectation unmet. However, the test code delivers more information, so let's not have it raise. Also, remove the libvirtd.log file at the end of the test so that the next test won't read those log messages. The 'data_dir.get_tmp_dir' seemingly creates a tmp dir per job, that is, tests might share the same tmp_dir. Signed-off-by: Sebastian Mitterle --- .../daemon/conf_file/libvirtd_conf/set_audit_logging.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/daemon/conf_file/libvirtd_conf/set_audit_logging.py b/libvirt/tests/src/daemon/conf_file/libvirtd_conf/set_audit_logging.py index e15272b3c7b..7ecf2db04c3 100644 --- a/libvirt/tests/src/daemon/conf_file/libvirtd_conf/set_audit_logging.py +++ b/libvirt/tests/src/daemon/conf_file/libvirtd_conf/set_audit_logging.py @@ -103,12 +103,14 @@ def check_concurrent_filters(): """ log_for_util = params.get("log_for_util") - if not libvirt.check_logfile(log_for_util, log_config_path, str_in_log=True): + if not libvirt.check_logfile(log_for_util, log_config_path, + ignore_status=True, str_in_log=True): test.fail("Can not find expected message :%s in log file:%s" % (log_for_util, log_config_path)) log_for_filter_list = eval(params.get("log_for_filter_list")) for filter in log_for_filter_list: str_to_grep = "%s" % filter - if not libvirt.check_logfile(str_to_grep, log_config_path, str_in_log=False): + if libvirt.check_logfile(str_to_grep, log_config_path, + ignore_status=True, str_in_log=True): test.fail("Find unexpected message :%s in log file:%s" % (str_to_grep, log_config_path)) vm_name = params.get("main_vm", "avocado-vt-vm1") @@ -146,3 +148,5 @@ def check_concurrent_filters(): finally: libvirtd_config.restore() utils_libvirtd.Libvirtd('virtqemud').restart() + if log_config_path and os.path.exists(log_config_path): + os.remove(log_config_path) From d48a87d4303f6768c7393441c03e39d710cb62a5 Mon Sep 17 00:00:00 2001 From: Misbah Anjum N Date: Thu, 25 Jan 2024 13:37:52 -0500 Subject: [PATCH 0133/1055] Fix virsh dump memory-only format kdump-* failure Since linux command 'file ' version 5.44, the memory-only dump formats: kdump-zlib, kdump-lzo and kdump-snappy are taken as 'flattened kdump compressed dump' In older 'file' version < 5.44 the same dump formats are taken as 'data' Updated virsh_dump.py to support the change in the format and fix the failure. Signed-off-by: Misbah Anjum N --- libvirt/tests/src/virsh_cmd/domain/virsh_dump.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_dump.py b/libvirt/tests/src/virsh_cmd/domain/virsh_dump.py index dedc78ef2c7..1ca2f332175 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_dump.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_dump.py @@ -183,7 +183,7 @@ def check_dump_format(dump_image_format, 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(): + if actual_format.lower() not in (dump_image_format.lower(), "flattened"): logging.error("Compress dumped file to %s fail: %s" % (dump_image_format, actual_format)) return False From 46e9ab121e1c06302f0dac551cfad6e230c13758 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 26 Jan 2024 09:36:03 +0800 Subject: [PATCH 0134/1055] save: Update to log a warning messgae for uptime mismatch The uptime since value may be changed slightly for some reasons, so update to log a warning message to avoid stopping tests directly. Signed-off-by: Yingshun Cui --- provider/save/save_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/provider/save/save_base.py b/provider/save/save_base.py index c003e3ee202..802d580ac1f 100644 --- a/provider/save/save_base.py +++ b/provider/save/save_base.py @@ -50,8 +50,8 @@ def post_save_check(vm, pid_ping, upsince): session.close() if upsince_restore != upsince: - raise exceptions.TestWarn(f'Uptime since {upsince_restore} is ' - f'incorrect, should be {upsince}') + LOG.warning(f'Uptime since {upsince_restore} is ' + f'incorrect, should be {upsince}') ping_cmd = 'ping 127.0.0.1' if ping_cmd not in proc_info: raise exceptions.TestFail('Cannot find running ping command ' From 04fe8e34bc2dc957bea2b3779989ac39d11c86ff Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 26 Jan 2024 14:59:04 +0800 Subject: [PATCH 0135/1055] vIOMMU: Add a case of attach iommu device This PR adds: VIRT-294818 - Hotplug or coldplug iommu device to guest Signed-off-by: Yingshun Cui --- .../cfg/sriov/vIOMMU/attach_iommu_device.cfg | 20 +++++++++++ .../src/sriov/vIOMMU/attach_iommu_device.py | 35 +++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 libvirt/tests/cfg/sriov/vIOMMU/attach_iommu_device.cfg create mode 100644 libvirt/tests/src/sriov/vIOMMU/attach_iommu_device.py diff --git a/libvirt/tests/cfg/sriov/vIOMMU/attach_iommu_device.cfg b/libvirt/tests/cfg/sriov/vIOMMU/attach_iommu_device.cfg new file mode 100644 index 00000000000..a0d420b4dc7 --- /dev/null +++ b/libvirt/tests/cfg/sriov/vIOMMU/attach_iommu_device.cfg @@ -0,0 +1,20 @@ +- vIOMMU.attach_iommu_device: + type = attach_iommu_device + start_vm = "no" + err_msg = "attach of device 'iommu' is not supported" + variants: + - virtio: + only q35, aarch64 + func_supported_since_libvirt_ver = (8, 3, 0) + iommu_dict = {'model': 'virtio'} + - intel: + only q35 + iommu_dict = {'model': 'intel', 'driver': {'intremap': 'on', 'caching_mode': 'on'}} + - smmuv3: + only aarch64 + func_supported_since_libvirt_ver = (5, 5, 0) + iommu_dict = {'model': 'smmuv3'} + variants: + - cold_plug: + attach_option = "--config" + - hot_plug: diff --git a/libvirt/tests/src/sriov/vIOMMU/attach_iommu_device.py b/libvirt/tests/src/sriov/vIOMMU/attach_iommu_device.py new file mode 100644 index 00000000000..f4a602692bf --- /dev/null +++ b/libvirt/tests/src/sriov/vIOMMU/attach_iommu_device.py @@ -0,0 +1,35 @@ +from virttest import libvirt_version +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + + +def run(test, params, env): + """ + Hotplug or coldplug iommu device to guest + """ + libvirt_version.is_libvirt_feature_supported(params) + iommu_dict = eval(params.get('iommu_dict', '{}')) + attach_option = params.get("attach_option", "") + err_msg = params.get("err_msg") + + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + backup_vmxml = vmxml.copy() + try: + if attach_option and vm.is_alive(): + vm.destroy() + elif not attach_option and not vm.is_alive(): + vm.start() + vm.wait_for_login().close() + + iommu_dev = libvirt_vmxml.create_vm_device_by_type('iommu', iommu_dict) + test.log.debug(f"iommu device: {iommu_dev}") + res = virsh.attach_device(vm.name, iommu_dev.xml, debug=True, + flagstr=attach_option) + libvirt.check_result(res, err_msg) + finally: + backup_vmxml.sync() From 564cf68dd32007e171684f86be9c945a72635731 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 26 Jan 2024 15:14:08 +0800 Subject: [PATCH 0136/1055] vIOMMU: Add a case about intel iommu This PR adds: VIRT-294734 - Check libvirt will prompt error when intel iommu device with hostdev interface/device but no caching_mode=on Signed-off-by: Yingshun Cui --- ...el_iommu_without_enabling_caching_mode.cfg | 16 +++++++ ...tel_iommu_without_enabling_caching_mode.py | 45 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_without_enabling_caching_mode.cfg create mode 100644 libvirt/tests/src/sriov/vIOMMU/intel_iommu_without_enabling_caching_mode.py diff --git a/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_without_enabling_caching_mode.cfg b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_without_enabling_caching_mode.cfg new file mode 100644 index 00000000000..ca97d6ac896 --- /dev/null +++ b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_without_enabling_caching_mode.cfg @@ -0,0 +1,16 @@ +- vIOMMU.intel_iommu.without_enabling_caching_mode: + type = intel_iommu_without_enabling_caching_mode + err_msg = "caching-mode=on for [i|I]ntel" + start_vm = "yes" + iommu_dict = {'model': 'intel', 'driver': {'intremap': 'on'}} + only q35 + + variants dev_type: + - hostdev_interface: + iface_dict = {'managed': 'yes', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}} + - hostdev_device: + hostdev_dict = {'mode': 'subsystem', 'type': 'pci', 'source': {'untyped_address': vf_pci_addr}, 'managed': 'yes'} + variants: + - cold_plug: + attach_option = "--config" + - hot_plug: diff --git a/libvirt/tests/src/sriov/vIOMMU/intel_iommu_without_enabling_caching_mode.py b/libvirt/tests/src/sriov/vIOMMU/intel_iommu_without_enabling_caching_mode.py new file mode 100644 index 00000000000..71c914ba0cc --- /dev/null +++ b/libvirt/tests/src/sriov/vIOMMU/intel_iommu_without_enabling_caching_mode.py @@ -0,0 +1,45 @@ +from virttest import virsh + +from virttest.utils_test import libvirt + +from provider.sriov import sriov_base + + +def run(test, params, env): + """ + This case is to test hostdev interface with IOMMU device but no + cache_mode=on. + """ + attach_option = params.get("attach_option", "") + err_msg = params.get("err_msg") + dev_type = params.get("dev_type", "") + iommu_dict = eval(params.get('iommu_dict', '{}')) + + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + + test_obj = sriov_base.SRIOVTest(vm, test, params) + iface_dict = test_obj.parse_iface_dict() + + try: + test_obj.setup_iommu_test(iommu_dict=iommu_dict, cleanup_ifaces=False) + + if attach_option and vm.is_alive(): + vm.destroy() + elif not attach_option and not vm.is_alive(): + vm.start() + vm.wait_for_login().close() + + iface_dev = test_obj.create_iface_dev(dev_type, iface_dict) + test.log.info("TEST_STEP: Attach hostdev interface.") + res = virsh.attach_device(vm.name, iface_dev.xml, debug=True, + flagstr=attach_option) + if attach_option: + libvirt.check_exit_status(res) + test.log.info("TEST_STEP: Start vm with hostdev.") + res = virsh.start(vm.name, debug=True) + + libvirt.check_result(res, err_msg) + + finally: + test_obj.teardown_iommu_test() From b284d753c8a874d748bead23d23172af7c6889fe Mon Sep 17 00:00:00 2001 From: Lili Zhu Date: Fri, 26 Jan 2024 12:38:45 +0900 Subject: [PATCH 0137/1055] Remove existing interfaces when testing timer Since RHEL8, the NTP protocol is implemented only by the chronyd daemon, which is enabled by default. Remove guest interface to prevent network connection, then guest will not sync time automatically to ntp server after boot. Otherwise, guest time will be synced to current real time regardless of guest configurations. Signed-off-by: Lili Zhu --- libvirt/tests/src/timer_management.py | 30 ++++++++++++++++++++------- spell.ignore | 1 + 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/src/timer_management.py b/libvirt/tests/src/timer_management.py index 1a1b4278851..9478068c826 100644 --- a/libvirt/tests/src/timer_management.py +++ b/libvirt/tests/src/timer_management.py @@ -71,6 +71,7 @@ def set_clock_xml(test, vm, params): newtimers.append(newtimer) vmclockxml.timers = newtimers vmxml.clock = vmclockxml + vmxml.remove_all_device_by_type('interface') logging.debug("New vm XML:\n%s", vmxml) vmxml.sync() # Return timer elements for test verify @@ -92,7 +93,7 @@ def vm_clock_source(vm, target, value=''): clock_file = 'current_clocksource' else: exceptions.TestError("Clock source target must be 'available' or 'current'") - session = vm.wait_for_login() + session = vm.wait_for_serial_login() session.cmd("cd %s" % CLOCK_SOURCE_PATH) set_clock = False if value: @@ -121,10 +122,11 @@ def get_time(vm=None, time_type=None, windows=False): :return: Epoch time or timezone """ if vm: - session = vm.wait_for_login() + session = vm.wait_for_serial_login() if time_type == "utc": cmd = "date -u +%Y/%m/%d/%H/%M/%S" ts, timestr = session.cmd_status_output(cmd) + logging.debug("VM UTC time is %s", timestr) elif windows is True: # Date in this format: Sun 09/14/2014 or 2014/09/14 Sun # So deal with it after getting date @@ -197,7 +199,7 @@ def set_vm_timezone(test, vm, timezone="America/New_York", windows=False): cmd_o = '' if not windows: timezone_file = "/usr/share/zoneinfo/%s" % timezone - session = vm.wait_for_login() + session = vm.wait_for_serial_login() if session.cmd_status("ls %s" % timezone_file): session.close() test.error("Not correct timezone:%s" % timezone_file) @@ -214,7 +216,7 @@ def set_vm_timezone(test, vm, timezone="America/New_York", windows=False): if timezone not in list(timezone_codes.keys()): test.error("Not supported timezone, please add it.") cmd = "tzutil /s \"%s\"" % timezone_codes[timezone] - session = vm.wait_for_login() + session = vm.wait_for_serial_login() cmd_s, cmd_o = session.cmd_status_output(cmd) session.close() if cmd_s: @@ -303,6 +305,8 @@ def manipulate_vm(vm, operation, params=None): os.remove(save_path) except OSError: pass + vm.cleanup_serial_console() + vm.create_serial_console() else: err_msg = "Unsupported operation in this function: %s" % operation return err_msg @@ -347,6 +351,7 @@ def test_timers_in_vm(test, vm, params): # Set host timezone set_host_timezone(test, host_tz) + syncup_host_time(test) # Confirm vm is down for editing if vm.is_alive(): @@ -357,7 +362,7 @@ def test_timers_in_vm(test, vm, params): # Logging vm to set time vm.start() - vm.wait_for_login() + vm.wait_for_serial_login() set_vm_timezone(test, vm, vm_tz, windows_test) # manipulate vm if necessary, linux guest only @@ -452,7 +457,7 @@ def test_specific_timer(test, vm, params): start_error = "yes" == params.get("timer_start_error", "no") if vm.is_dead(): vm.start() - vm.wait_for_login() + vm.wait_for_serial_login() # Not config VM clock if the timer is unsupported in VM config_clock_in_vm = True for timer in timers: @@ -472,7 +477,7 @@ def test_specific_timer(test, vm, params): # Logging vm to verify whether setting is work try: vm.start() - vm.wait_for_login() + vm.wait_for_serial_login() if start_error: test.fail("Start vm succeed, but expect fail.") except virt_vm.VMStartError as detail: @@ -522,6 +527,17 @@ def test_specific_timer(test, vm, params): " while present is yes" % t_name) +def syncup_host_time(test): + """ + Sync up host time to ntp server before testing. + """ + try: + process.run("chronyd -q 'server clock.redhat.com iburst'", shell=True) + process.run("hwclock --systohc", shell=True) + except Exception as e: + logging.error("sync up host time to ntp server error: %s", e) + + def run(test, params, env): """ Test vm time according timer management of XML configuration. diff --git a/spell.ignore b/spell.ignore index 2a06ef3ea15..229e748874a 100644 --- a/spell.ignore +++ b/spell.ignore @@ -1227,3 +1227,4 @@ hwrng buitin Meina meili +ntp From 8d89d6b636d063807e4fdc10dbef159c0c0a4117 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Fri, 26 Jan 2024 04:21:13 -0500 Subject: [PATCH 0138/1055] crypto_nodedev: improve reliability Waiting for udevadm settle doesn't seem to make sure Libvirt has the latest device information. Instead add a sleep. If this doesn't fix the brittleness we might want to restart virtqemud. Signed-off-by: Sebastian Mitterle --- .../src/virsh_cmd/nodedev/crypto_nodedev_create_destroy.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/nodedev/crypto_nodedev_create_destroy.py b/libvirt/tests/src/virsh_cmd/nodedev/crypto_nodedev_create_destroy.py index a08cd1c6e2f..13a8707dd0e 100644 --- a/libvirt/tests/src/virsh_cmd/nodedev/crypto_nodedev_create_destroy.py +++ b/libvirt/tests/src/virsh_cmd/nodedev/crypto_nodedev_create_destroy.py @@ -4,7 +4,6 @@ from uuid import uuid1 -from avocado.utils import process from virttest import libvirt_version from virttest import virsh from virttest import utils_misc @@ -119,7 +118,7 @@ def check_device_attributes_are_dumped(test, dev_name, adapter, domain): :param domain: domain number in base 16 """ - process.run("udevadm settle") + time.sleep(10) nodedevice_xml = nodedev_xml.NodedevXML.new_from_dumpxml(dev_name) mdev_cap_xml = nodedevice_xml.get_cap() logging.debug("MdevXML: %s", mdev_cap_xml) From d9cd38d877d05b409543f8d547555162d5ddb5d4 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Sun, 28 Jan 2024 21:01:32 -0500 Subject: [PATCH 0139/1055] Skip the ipv6 default route check There are some systems with multipath ipv6 route which passt can not recognize. Skip the ipv6 default route check on such system. Signed-off-by: Yalan Zhang --- provider/virtual_network/passt.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/provider/virtual_network/passt.py b/provider/virtual_network/passt.py index 00ac9fad006..3666165e969 100644 --- a/provider/virtual_network/passt.py +++ b/provider/virtual_network/passt.py @@ -253,6 +253,10 @@ def check_default_gw(session): if [x for x in vm_gw if x not in host_gw]: raise exceptions.TestFail( 'Host default ipv4 gateway not consistent with vm.') + if not host_gw_v6: + LOG.debug("Skip ipv6 route check as host has multipath ipv6 route " + "which Passt can not recognize.") + return if [x for x in vm_gw_v6 if x not in host_gw_v6]: raise exceptions.TestFail( 'Host default ipv6 gateway not consistent with vm.') From d98f86a92e188ad9c11f5b8e884b67a22c7d1f4f Mon Sep 17 00:00:00 2001 From: Hu Shuai Date: Thu, 4 Jan 2024 16:24:55 +0800 Subject: [PATCH 0140/1055] memory_nvdimm: Fix cpu mode to enable test for aarch64 The cpu mode is host-passthrough for arm. Internal snapshots of a VM with pflash based firmware are not supported on arm, so skip this check on arm. Signed-off-by: Hu Shuai --- libvirt/tests/cfg/memory/nvdimm.cfg | 9 ++++++--- libvirt/tests/src/memory/nvdimm.py | 16 +++++++++++++--- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/libvirt/tests/cfg/memory/nvdimm.cfg b/libvirt/tests/cfg/memory/nvdimm.cfg index d7c0d003f15..0a353d31848 100644 --- a/libvirt/tests/cfg/memory/nvdimm.cfg +++ b/libvirt/tests/cfg/memory/nvdimm.cfg @@ -2,10 +2,12 @@ type = nvdimm start_vm = no nvdimm_file_size = '512M' + cpuxml_mode = host-model + aarch64: + cpuxml_mode = host-passthrough variants: - back_file: nvdimm_file = /tmp/nvdimm - cpuxml_mode = host-model cpuxml_check = partial cpuxml_fallback = allow nvdimmxml_mem_model = nvdimm @@ -37,6 +39,8 @@ - default: - check_life_cycle: check_life_cycle = "yes" + error_msg_1 = "unsupported configuration: revert to external snapshot not supported yet" + error_msg_2 = "internal error: Invalid target domain state 'disk-snapshot'. Refusing snapshot reversion" - discard: check = discard nvdimmxml_discard = yes @@ -46,7 +50,7 @@ check = pmem_alignsize nvdimm_file_path = '/tmp/nvdimm' alignsize = 2048 - vm_attrs = {'max_mem_rt': 8192, 'max_mem_rt_slots': 8, 'max_mem_rt_unit': 'M', 'vcpu': 4, 'cpu': {'mode': 'host-model', 'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '2097152', 'unit': 'K'}, {'id': '1', 'cpus': '2-3', 'memory': '2097152', 'unit': 'K'}]}} + vm_attrs = {'max_mem_rt': 8192, 'max_mem_rt_slots': 8, 'max_mem_rt_unit': 'M', 'vcpu': 4, 'cpu': {'mode': '${cpuxml_mode}', 'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '2097152', 'unit': 'K'}, {'id': '1', 'cpus': '2-3', 'memory': '2097152', 'unit': 'K'}]}} mem_device_attrs = {'mem_model': 'nvdimm', 'source': {'path': '${nvdimm_file_path}', 'alignsize': ${alignsize}, 'alignsize_unit': 'K', 'pmem': True}, 'target': {'size': 512, 'size_unit': 'M', 'node': 1, 'readonly': True, 'label': {'size': 128, 'size_unit': 'KiB'}}} qemu_checks = "align.*pmem" error_msg = "['pwrite.* failed: Operation not permitted', 'wrong fs type, bad option, bad superblock on /dev/pmem0']" @@ -113,7 +117,6 @@ nvdimmxml2_label_size = 128 nvdimmxml2_label_size_unit = KiB nvdimmxml2_address_slot = 1 - cpuxml_mode = host-model cpuxml_check = partial cpuxml_fallback = allow cpuxml_topology = {'sockets': '2', 'cores': '2', 'threads': '1'} diff --git a/libvirt/tests/src/memory/nvdimm.py b/libvirt/tests/src/memory/nvdimm.py index 3eba7f00873..c0b585f1408 100644 --- a/libvirt/tests/src/memory/nvdimm.py +++ b/libvirt/tests/src/memory/nvdimm.py @@ -13,6 +13,7 @@ from virttest.libvirt_xml import vm_xml from virttest.libvirt_xml.devices import memory from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_disk # Using as lower capital is not the best way to do, but this is just a @@ -339,9 +340,18 @@ def test_with_label(vm, params, test): vm_session = vm.wait_for_login() check_nvdimm_file(test_str, test_file, vm_session, test) vm_session.close() - virsh.snapshot_create_as(vm_name, vm_s1, ignore_status=False, debug=True) - virsh.snapshot_revert(vm_name, vm_s1, ignore_status=False, debug=True) - virsh.snapshot_delete(vm_name, vm_s1, ignore_status=False, debug=True) + virsh.snapshot_create_as(vm_name, "%s --disk-only" % vm_s1, + ignore_status=False, debug=True) + revert_result = virsh.snapshot_revert(vm_name, vm_s1, debug=True) + libvirt.check_result(revert_result, expected_fails=([params.get('error_msg_1'), + params.get('error_msg_2')])) + if libvirt_version.version_compare(9, 10, 0): + virsh.snapshot_delete(vm_name, vm_s1, ignore_status=False, debug=True) + else: + virsh.snapshot_delete(vm_name, "%s --metadata" % vm_s1, ignore_status=False, debug=True) + snap_file_path = libvirt_disk.get_first_disk_source(vm) + if os.path.exists(snap_file_path): + os.remove(snap_file_path) def test_hotplug(vm, params, test): From e4f14c5957e50d8c42eed476e8c70fee55f1db6f Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Mon, 29 Jan 2024 11:10:04 +0800 Subject: [PATCH 0141/1055] Rename main name in v2v jobs Signed-off-by: Ming Xie --- v2v/tests/cfg/convert_vm_to_libvirt.cfg | 6 ++---- v2v/tests/cfg/convert_vm_to_ovirt.cfg | 6 ++---- v2v/tests/cfg/function_test_xen.cfg | 2 +- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/v2v/tests/cfg/convert_vm_to_libvirt.cfg b/v2v/tests/cfg/convert_vm_to_libvirt.cfg index a274d745736..268a3f1682c 100644 --- a/v2v/tests/cfg/convert_vm_to_libvirt.cfg +++ b/v2v/tests/cfg/convert_vm_to_libvirt.cfg @@ -163,8 +163,7 @@ vir_mode = "hvm" variants: - vm: - # main_vm = ${hypervisor}-${vir_mode}-${os_version}-${vm_arch} - main_vm = "XEN_VM_NAME_V2V_EXAMPLE" + main_vm = ${hypervisor}-${vir_mode}-${os_version}-${vm_arch} - esx: only source_esx vpx_pwd = ${vpx_password} @@ -190,5 +189,4 @@ hostname = ${esx_hostname} variants: - vm: - # main_vm = ${esx_version}-${os_version}-${vm_arch}${vm_boot} - main_vm = "ESX_VM_NAME_V2V_EXAMPLE" + main_vm = ${esx_version}-${os_version}-${vm_arch}${vm_boot} diff --git a/v2v/tests/cfg/convert_vm_to_ovirt.cfg b/v2v/tests/cfg/convert_vm_to_ovirt.cfg index 6292337d521..90db46add77 100644 --- a/v2v/tests/cfg/convert_vm_to_ovirt.cfg +++ b/v2v/tests/cfg/convert_vm_to_ovirt.cfg @@ -195,8 +195,7 @@ vir_mode = "hvm" variants: - vm: - # main_vm = ${hypervisor}-${vir_mode}-${os_version}-${vm_arch} - main_vm = "XEN_VM_NAME_V2V_EXAMPLE" + main_vm = ${hypervisor}-${vir_mode}-${os_version}-${vm_arch} - esx: only source_esx vpx_pwd = ${vpx_password} @@ -222,5 +221,4 @@ hostname = ${vpx_hostname} variants: - vm: - # main_vm = ${esx_version}-${os_version}-${vm_arch}${vm_boot} - main_vm = "ESX_VM_NAME_V2V_EXAMPLE" + main_vm = ${esx_version}-${os_version}-${vm_arch}${vm_boot} diff --git a/v2v/tests/cfg/function_test_xen.cfg b/v2v/tests/cfg/function_test_xen.cfg index 037281c3472..1d6b9c253cd 100644 --- a/v2v/tests/cfg/function_test_xen.cfg +++ b/v2v/tests/cfg/function_test_xen.cfg @@ -14,7 +14,7 @@ # Guest info os_type = 'linux' - main_vm = 'XEN_VM_NAME_V2V_EXAMPLE' + main_vm = ${hypervisor}-${vir_mode}-${os_version}-${vm_arch} username = 'root' password = GENERAL_GUEST_PASSWORD os_version = 'XEN_VM_OS_VERSION_V2V_EXAMPLE' From db766cbbbee5f1c81eef5f0df24437875a0f5e3d Mon Sep 17 00:00:00 2001 From: Meina Li Date: Sun, 28 Jan 2024 22:14:24 -0500 Subject: [PATCH 0142/1055] storage: add case for logical pool lifecycle from empty vg VIRT-300253: Logical pool lifecycle from empty vg and restart service. Also because the status of logical pool will keep active after restarting the service. So update another case together. Signed-off-by: Meina Li --- .../pool => storage}/virsh_pool_autostart.cfg | 3 +++ libvirt/tests/src/storage/virsh_pool.py | 2 +- .../pool => storage}/virsh_pool_autostart.py | 17 +++++++++++++++-- 3 files changed, 19 insertions(+), 3 deletions(-) rename libvirt/tests/cfg/{virsh_cmd/pool => storage}/virsh_pool_autostart.cfg (96%) rename libvirt/tests/src/{virsh_cmd/pool => storage}/virsh_pool_autostart.py (93%) diff --git a/libvirt/tests/cfg/virsh_cmd/pool/virsh_pool_autostart.cfg b/libvirt/tests/cfg/storage/virsh_pool_autostart.cfg similarity index 96% rename from libvirt/tests/cfg/virsh_cmd/pool/virsh_pool_autostart.cfg rename to libvirt/tests/cfg/storage/virsh_pool_autostart.cfg index 8f3466e9e80..3e39f26482f 100644 --- a/libvirt/tests/cfg/virsh_cmd/pool/virsh_pool_autostart.cfg +++ b/libvirt/tests/cfg/storage/virsh_pool_autostart.cfg @@ -54,6 +54,9 @@ source_format = "lvm2" - source_format_auto: source_format = "auto" + - with_empty_vg: + func_supported_since_libvirt_ver = (9, 9, 0) + with_empty_vg = "yes" - pool_type_netfs: pool_type = "netfs" pool_target = "/nfs-mount" diff --git a/libvirt/tests/src/storage/virsh_pool.py b/libvirt/tests/src/storage/virsh_pool.py index 01912f43ce7..b8c3fd8d4e1 100644 --- a/libvirt/tests/src/storage/virsh_pool.py +++ b/libvirt/tests/src/storage/virsh_pool.py @@ -422,7 +422,7 @@ def check_pool_info(pool_info, check_point, value): # pool as active. This is independent of autostart. # So a directory based storage pool is thus pretty much always active, # and so as the SCSI pool. - if pool_type not in ['dir', 'scsi']: + if pool_type not in ['dir', 'scsi', 'logical']: if pool_type == 'disk' and libvirt_version.version_compare(8, 1, 0): utlv.check_exit_status(result) else: diff --git a/libvirt/tests/src/virsh_cmd/pool/virsh_pool_autostart.py b/libvirt/tests/src/storage/virsh_pool_autostart.py similarity index 93% rename from libvirt/tests/src/virsh_cmd/pool/virsh_pool_autostart.py rename to libvirt/tests/src/storage/virsh_pool_autostart.py index c1662febe1e..3076a4b8874 100755 --- a/libvirt/tests/src/virsh_cmd/pool/virsh_pool_autostart.py +++ b/libvirt/tests/src/storage/virsh_pool_autostart.py @@ -6,6 +6,7 @@ from virttest import utils_libvirtd from virttest import libvirt_storage + from virttest import virsh from virttest.utils_test import libvirt as utlv from virttest.libvirt_xml import pool_xml @@ -45,10 +46,12 @@ def run(test, params, env): status_error = "yes" == params.get("status_error", "no") readonly_mode = "yes" == params.get("readonly_mode", "no") pre_def_pool = "yes" == params.get("pre_def_pool", "yes") + with_empty_vg = "yes" == params.get("with_empty_vg", "no") disk_type = params.get("disk_type", "") vg_name = params.get("vg_name", "") lv_name = params.get("lv_name", "") update_policy = params.get("update_policy") + libvirt_version.is_libvirt_feature_supported(params) # Readonly mode ro_flag = False @@ -90,7 +93,7 @@ def check_pool(pool_name, pool_type, checkpoint, actual_value = libvirt_pool.pool_autostart(pool_name) if actual_value != expect_value: if not expect_error: - if checkpoint == 'State' and pool_type in ("dir", "scsi", "disk"): + if checkpoint == 'State' and pool_type in ("dir", "scsi", "disk", "logical"): debug_msg = "Dir/scsi/disk pool should be active when libvirtd restart. " debug_msg += "See https://bugzilla.redhat.com/show_bug.cgi?id=1238610" logging.debug(debug_msg) @@ -129,7 +132,15 @@ def change_source_path(new_path, update_policy="set"): if pre_def_pool: # Step(1) # Pool define - pvt.pre_pool(**params) + if with_empty_vg and pool_type == "logical": + new_disk = utlv.setup_or_cleanup_iscsi(True) + pool_options = "--source-dev %s" % new_disk + virsh.pool_define_as(pool_name, pool_type, pool_target, + extra=pool_options, debug=True) + virsh.pool_build(pool_name, "--overwrite", debug=True) + virsh.pool_start(pool_name, ignore_status=False, debug=True) + else: + pvt.pre_pool(**params) # Remove the partition for disk pool # For sometimes the partition will cause pool start failed if pool_type == "disk": @@ -238,6 +249,8 @@ def change_source_path(new_path, update_policy="set"): utlv.delete_local_disk(disk_type, vgname=vg_name, lvname=lv_name) lv_utils.vg_remove(vg_name) utlv.setup_or_cleanup_iscsi(False) + if with_empty_vg: + utlv.setup_or_cleanup_iscsi(False) if os.path.exists(p_xml): os.remove(p_xml) except exceptions.TestFail as details: From 0606af6df3e11b77e53d88305184d87603b567fc Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Mon, 29 Jan 2024 14:20:02 +0800 Subject: [PATCH 0143/1055] v2v:fix cpu-topology TC Signed-off-by: vwu-vera --- v2v/tests/cfg/convert_from_file.cfg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/v2v/tests/cfg/convert_from_file.cfg b/v2v/tests/cfg/convert_from_file.cfg index aa12ff4e8c7..bc8a0cfc55f 100644 --- a/v2v/tests/cfg/convert_from_file.cfg +++ b/v2v/tests/cfg/convert_from_file.cfg @@ -114,10 +114,10 @@ - cpu_topology: checkpoint = 'cpu_topology' v2v_debug = force_on - ova_file_name = OVA_DIR_RHEL_LINUX_V2V_EXAMPLE.ova - ova_dir = ${ova_file_name} + ova_file_name = OVA_FILE_CPU_TOPOLOGY_V2V_EXAMPLE + ova_dir = OVA_DIR_ROOT_V2V_EXAMPLE ova_copy_dir = 'OVA_DIR_COPY_V2V_EXAMPLE' - input_file = ${ova_copy_dir}/${ova_file_name} + input_file = ${ova_dir}/${ova_file_name} msg_content_yes = '' - special: ova_dir = 'OVA_DIR_SPECIAL_V2V_EXAMPLE' From 2341e276bb9f0b5b5a7b1ecc34a6a21210f4eb79 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 29 Jan 2024 06:05:33 -0500 Subject: [PATCH 0144/1055] nmi_test: disable second inject for s390x On s390x the inject NMI behavior is different to other archs: It panics and if kdump is configured the kernel will be dumped and the guest reboots. Both will result in the NMI inject count 0. A second quick injection will result in a panic because kdump is not up yet. Skip the qemu-monitor command, only check the libvirt command. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/guest_kernel_debugging/nmi_test.cfg | 4 ++++ libvirt/tests/src/guest_kernel_debugging/nmi_test.py | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/guest_kernel_debugging/nmi_test.cfg b/libvirt/tests/cfg/guest_kernel_debugging/nmi_test.cfg index 6525485dc70..7ef69bc0d78 100644 --- a/libvirt/tests/cfg/guest_kernel_debugging/nmi_test.cfg +++ b/libvirt/tests/cfg/guest_kernel_debugging/nmi_test.cfg @@ -18,3 +18,7 @@ # using inject-nmi and qemu-monitor-command to send nmi, # so the expected times are 2 for Non-maskable interrupts expected_nmi_times = 2 + check_qemu_monitor = yes + s390-virtio: + expected_nmi_times = 0 + check_qemu_monitor = no diff --git a/libvirt/tests/src/guest_kernel_debugging/nmi_test.py b/libvirt/tests/src/guest_kernel_debugging/nmi_test.py index 1727689d787..95644515306 100644 --- a/libvirt/tests/src/guest_kernel_debugging/nmi_test.py +++ b/libvirt/tests/src/guest_kernel_debugging/nmi_test.py @@ -77,6 +77,7 @@ def run(test, params, env): expected_nmi_times = params.get("expected_nmi_times", '0') kernel_params = params.get("kernel_params", "") unprivileged_user = params.get('unprivileged_user') + check_qemu_monitor = "yes" == params.get("check_qemu_monitor", "yes") if unprivileged_user: if unprivileged_user.count('EXAMPLE'): unprivileged_user = 'testacl' @@ -115,8 +116,9 @@ def run(test, params, env): logging.info("Inject NMI to the guest via virsh inject_nmi") virsh.inject_nmi(vm_name, debug=True, ignore_status=False) - logging.info("Inject NMI to the guest via virsh qemu_monitor_command") - virsh.qemu_monitor_command(vm_name, '{"execute":"inject-nmi"}') + if check_qemu_monitor: + logging.info("Inject NMI to the guest via virsh qemu_monitor_command") + virsh.qemu_monitor_command(vm_name, '{"execute":"inject-nmi"}') # injects a Non-Maskable Interrupt into the default CPU (x86/s390) # or all CPUs (ppc64), as usual, the default CPU index is 0 From f2a7a2133955e04d62353a72748155257f9a8e46 Mon Sep 17 00:00:00 2001 From: Misbah Anjum N Date: Mon, 29 Jan 2024 08:45:56 -0600 Subject: [PATCH 0145/1055] Fix Error: bad escape \\s at position 0 From python3.7, using '\s' leads to re error In python3.6 and below, the same was treated as DeprecationWarning Hence replacing '\s' in the code simply with ' ' will work Signed-off-by: Misbah Anjum N --- libvirt/tests/src/virsh_cmd/domain/virsh_domxml_from_native.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_domxml_from_native.py b/libvirt/tests/src/virsh_cmd/domain/virsh_domxml_from_native.py index 7d665e70db4..ddd2b55ee93 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_domxml_from_native.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_domxml_from_native.py @@ -34,7 +34,7 @@ def virsh_convxml(guest_args): pid = vm.get_pid() cmdline = process.run("cat -v /proc/%d/cmdline" % pid).stdout_text cmdline = re.sub(r'\^@', ' ', cmdline) - cmdline_tmp = re.sub(r'\s-drive\s[^\s]+', '\s', cmdline) + cmdline_tmp = re.sub(r'\s-drive\s[^\s]+', ' ', cmdline) # Libvirt requires the binary path for domxml-from-native to succeed # /proc/pid/cmdline would give qemu cmdline with binary without From cbddd15508d8985e242fa6b84c18de60507dd07d Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 29 Jan 2024 10:07:54 -0500 Subject: [PATCH 0146/1055] blkdeviotune: improve test log The test case needs the output from 'blkdeviotune' on the disk in order to compare it with the XML values. It was trying to compare with an empty dictionary because the result was empty with an error that was ignored. Don't continue the test if the block I/O throttle parameters cannot be retrieved. This will show a test error indicating this. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/virsh_cmd/domain/virsh_blkdeviotune.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_blkdeviotune.py b/libvirt/tests/src/virsh_cmd/domain/virsh_blkdeviotune.py index 07eae2c3fc4..f71634eddc1 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_blkdeviotune.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_blkdeviotune.py @@ -25,7 +25,7 @@ def check_blkdeviotune(params): vm = params.get("vm") options = params.get("blkdevio_options") device = params.get("device_name", "") - result = virsh.blkdeviotune(vm_name, device) + result = virsh.blkdeviotune(vm_name, device, ignore_status=False) dicts = {} # Parsing command output and putting them into python dictionary. cmd_output = result.stdout.strip().splitlines() From 0489523259d49b1e930602140fcfa810731ab8df Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 30 Jan 2024 10:56:58 +0800 Subject: [PATCH 0147/1055] vIOMMU: Add a case of intel iommu This case adds: VIRT-300349 - [iommu][intel] Define VM with intel iommu but no defined Signed-off-by: Yingshun Cui --- .../vIOMMU/intel_iommu_without_ioapic.cfg | 8 ++++ .../vIOMMU/intel_iommu_without_ioapic.py | 41 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_without_ioapic.cfg create mode 100644 libvirt/tests/src/sriov/vIOMMU/intel_iommu_without_ioapic.py diff --git a/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_without_ioapic.cfg b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_without_ioapic.cfg new file mode 100644 index 00000000000..f4c9f5168bc --- /dev/null +++ b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_without_ioapic.cfg @@ -0,0 +1,8 @@ +- vIOMMU.intel_iommu.without_ioapic: + type = intel_iommu_without_ioapic + start_vm = "yes" + enable_guest_iommu = "yes" + feature_name = "ioapic" + err_msg = "IOMMU interrupt remapping requires split I/O APIC" + iommu_dict = {'model': 'intel', 'driver': {'intremap': 'on'}} + only q35 diff --git a/libvirt/tests/src/sriov/vIOMMU/intel_iommu_without_ioapic.py b/libvirt/tests/src/sriov/vIOMMU/intel_iommu_without_ioapic.py new file mode 100644 index 00000000000..1c9a321a62d --- /dev/null +++ b/libvirt/tests/src/sriov/vIOMMU/intel_iommu_without_ioapic.py @@ -0,0 +1,41 @@ +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml import xcepts +from virttest.utils_libvirt import libvirt_vmxml + + +def run(test, params, env): + """ + Check for the error message when using an Intel iommu device + but without defined in the VM + """ + iommu_dict = eval(params.get('iommu_dict', '{}')) + err_msg = params.get("err_msg", "I/O APIC") + feature_name = params.get("feature_name", "ioapic") + + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + backup_vmxml = vmxml.copy() + try: + test.log.info(f"TEST_STEP: Remove {feature_name} feature if needed.") + features = vmxml.features + if features.has_feature(feature_name): + features.remove_feature(feature_name) + vmxml.features = features + + test.log.info("TEST_STEP: Define VM with intel iommu device.") + iommu_dev = libvirt_vmxml.create_vm_device_by_type('iommu', iommu_dict) + vmxml.add_device(iommu_dev) + vmxml.xmltreefile.write() + try: + vmxml.sync() + except xcepts.LibvirtXMLError as details: + test.log.debug("Check '%s' in %s.", err_msg, details) + if not str(details).count(err_msg): + test.fail("Incorrect error message, it should be '{}', but " + "got '{}'.".format(err_msg, details)) + else: + test.fail("Vm is expected to fail on defining with intel iommu " + "without ioapic feature, while it succeeds.") + finally: + backup_vmxml.sync() From cd6f6dbb4322c023772cc817b100f59c00ce70af Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Mon, 22 Jan 2024 00:26:00 -0500 Subject: [PATCH 0148/1055] The error message changes with new libvirt version Update the error message pattern since it changes with new libvirt version. Signed-off-by: Yalan Zhang --- .../tests/cfg/virtual_network/passt/passt_negative_setting.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_negative_setting.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_negative_setting.cfg index 6dcec38bb14..97d030aec40 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_negative_setting.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_negative_setting.cfg @@ -27,7 +27,7 @@ log_file = /var/log/passt.log error_msg = "Couldn't open log file .*: Permission denied" - rm_passt_pgk: - error_msg = unable to get SELinux context for '/usr/bin/passt': No such file or directory + error_msg = "No such file or directory" - non_exist_host_iface: host_iface = eno999 error_msg = Invalid interface name .*: No such device From cd1e6c9e417b9684847e503753c5585b59e096c5 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Tue, 30 Jan 2024 04:36:20 -0500 Subject: [PATCH 0149/1055] numa_topology_with_hugepage:fix cpu model on arm - fix cpu model for arm - enhance to support checking default kernel pagesize instead of hardcoded in cfg Signed-off-by: Dan Zheng --- .../numa_topology_with_hugepage.cfg | 25 +++++++------------ .../numa_topology_with_hugepage.py | 8 +++--- provider/numa/numa_base.py | 22 ++++++++++++++++ 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/libvirt/tests/cfg/numa/guest_numa_topology/numa_topology_with_hugepage.cfg b/libvirt/tests/cfg/numa/guest_numa_topology/numa_topology_with_hugepage.cfg index 06b0d644986..509a9da1ba6 100644 --- a/libvirt/tests/cfg/numa/guest_numa_topology/numa_topology_with_hugepage.cfg +++ b/libvirt/tests/cfg/numa/guest_numa_topology/numa_topology_with_hugepage.cfg @@ -8,6 +8,10 @@ hugepage_path_2M = '/dev/hugepages' hugepage_path_1G = '/dev/hugepages1G' pat_in_qemu_cmdline = '-object {"qom-type":".*","id":"ram-node0","mem-path":"%s","prealloc":true,"size":%d} .* -object {"qom-type":".*","id":"ram-node1",%s%s"size":%d}' + cpu_mode = 'host-model' + no s390-virtio + aarch64: + cpu_mode = 'host-passthrough' variants hp_size: - 2M: mem_value = "'memory': 2097152, 'memory_unit': 'KiB'" @@ -15,25 +19,25 @@ vm_numa_node1_mem = 1073152 memory_backing = {'hugepages': {'pages': [{'size': '2048', 'unit': 'KiB', 'nodeset': '0'}]}} - 1G: - no kernelpagesize_64k mem_value = "'memory': 2121728, 'memory_unit': 'KiB'" vm_numa_node0_mem = 1048576 vm_numa_node1_mem = 1073152 memory_backing = {'hugepages': {'pages': [{'size': '1048576', 'unit': 'KiB', 'nodeset': '0'}]}} - 512M: - only kernelpagesize_64k + hugepage_path_512M = '/dev/hugepages512M' + target_hugepages_512M = 2 mem_value = "'memory': 2121728, 'memory_unit': 'KiB'" vm_numa_node0_mem = 1048576 vm_numa_node1_mem = 1073152 memory_backing = {'hugepages': {'pages': [{'size': '524288', 'unit': 'KiB', 'nodeset': '0'}]}} - 2M_512M: - only kernelpagesize_64k + hugepage_path_512M = '/dev/hugepages512M' + target_hugepages_512M = 2 mem_value = "'memory': 2072576, 'memory_unit': 'KiB'" vm_numa_node0_mem = 1024000 vm_numa_node1_mem = 1048576 memory_backing = {'hugepages': {'pages': [{'size': '512', 'unit': 'M', 'nodeset': '1'}, {'size': '2', 'unit': 'M', 'nodeset': '0'}]}} - 2M_1G: - no kernelpagesize_64k mem_value = "'memory': 2072576, 'memory_unit': 'KiB'" vm_numa_node0_mem = 1024000 vm_numa_node1_mem = 1048576 @@ -43,17 +47,6 @@ vm_numa_node0_mem = 1048576 vm_numa_node1_mem = 1048576 memory_backing = {'hugepages': {'pages': [{'size': '2048', 'unit': 'KiB', 'nodeset': '0'}]}} - variants: - - kernelpagesize_64k: - only aarch64 - conf_pagesize = 65536 - hugepage_path_2M = '/dev/hugepages2M' - hugepage_path_512M = '/dev/hugepages' - target_hugepages_512M = 2 - - kernelpagesize_4k: - conf_pagesize = 4096 current_mem_value = ${mem_value} numa_cell = "'numa_cell': [{'cpus': '0-1', 'memory': '${vm_numa_node0_mem}'}, {'cpus': '2-3', 'memory': '${vm_numa_node1_mem}'}]" - vm_attrs = {${max_mem_value}, ${mem_value}, ${current_mem_value}, 'vcpu': 4, 'cpu': {'mode': 'host-model', ${numa_cell}}} - aarch64: - vm_attrs = {${max_mem_value}, ${mem_value}, ${current_mem_value}, 'vcpu': 4, 'cpu': {'mode': 'host-passthrough', ${numa_cell}}} + vm_attrs = {${max_mem_value}, ${mem_value}, ${current_mem_value}, 'vcpu': 4, 'cpu': {'mode': '${cpu_mode}', ${numa_cell}}} diff --git a/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_hugepage.py b/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_hugepage.py index d8e2d54e33c..e041e3b1e93 100644 --- a/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_hugepage.py +++ b/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_hugepage.py @@ -39,6 +39,9 @@ def setup_default(test_obj): :param test_obj: NumaTest object """ + memory_backing = eval(test_obj.params.get('memory_backing', '{}')) + if memory_backing: + numa_base.check_hugepage_availability(memory_backing) test_obj.setup() params_2M = {'hugepage_size': '2048', 'vm_hugepage_mountpoint': test_obj.params.get('hugepage_path_2M'), @@ -218,11 +221,6 @@ def run(test, params, env): """ Test for numa memory binding with emulator thread pin """ - conf_pagesize = params.get("conf_pagesize") - kernel_pagesize = process.run("getconf PAGESIZE", shell=True).stdout_text.strip() - if kernel_pagesize != conf_pagesize: - test.cancel("The current test does not work with this kernel pagesize.") - vm_name = params.get("main_vm") vm = env.get_vm(vm_name) numatest_obj = numa_base.NumaTest(vm, params, test) diff --git a/provider/numa/numa_base.py b/provider/numa/numa_base.py index 627659ba1c9..524ff0c831c 100644 --- a/provider/numa/numa_base.py +++ b/provider/numa/numa_base.py @@ -10,6 +10,7 @@ import re from avocado.core import exceptions +from avocado.utils import memory from avocado.utils import process from virttest import cpu @@ -213,3 +214,24 @@ def convert_to_list_of_int(cpus_in_short, cpu_num): """ cpu_list = cpu.cpus_string_to_affinity_list(cpus_in_short, cpu_num) return [index for index in range(0, len(cpu_list)) if cpu_list[index] == 'y'] + + +def check_hugepage_availability(memory_backing): + """ + Check if the configured huge page size is supported on the system + + :param memory_backing: like {'hugepages': {'pages': [{'size': '1048576', 'unit': 'KiB', 'nodeset': '0'}]}} + :raises: exceptions.TestSkipError: when hugepage is not supported + """ + unit_mapping = {'G': 1048576, 'M': 1024, 'KiB': 1} + supported_hugepages = memory.get_supported_huge_pages_size() + pages_list = memory_backing['hugepages']['pages'] + for a_page in pages_list: + size = int(a_page['size']) + unit = a_page['unit'] + size *= unit_mapping[unit] + if size not in supported_hugepages: + raise exceptions.TestSkipError("The hugepage size '%s' is " + "not supported on current " + "arch (support: %s)" % (size, + supported_hugepages)) From 9f12d8ddd6e371ef7b7f76ec97d3d79758430fff Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Tue, 30 Jan 2024 06:00:15 -0500 Subject: [PATCH 0150/1055] guest_numa: fix incorrect cpu mode on arm Signed-off-by: Dan Zheng --- libvirt/tests/cfg/numa/guest_numa.cfg | 3 +++ libvirt/tests/src/numa/guest_numa.py | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/numa/guest_numa.cfg b/libvirt/tests/cfg/numa/guest_numa.cfg index 00461ed5d82..5218bf0377b 100644 --- a/libvirt/tests/cfg/numa/guest_numa.cfg +++ b/libvirt/tests/cfg/numa/guest_numa.cfg @@ -7,6 +7,9 @@ max_mem = 2097152 hugepage_force_allocate = "yes" numa_cells_with_memory_required = 2 + cpu_mode = 'host-model' + aarch64: + cpu_mode = 'host-passthrough' variants: - possitive_test: cell_id_0 = "0" diff --git a/libvirt/tests/src/numa/guest_numa.py b/libvirt/tests/src/numa/guest_numa.py index 3ece45dc093..1860860c73d 100644 --- a/libvirt/tests/src/numa/guest_numa.py +++ b/libvirt/tests/src/numa/guest_numa.py @@ -355,7 +355,8 @@ def _update_qemu_conf(): # guest numa cpu setting vmcpuxml = libvirt_xml.vm_xml.VMCPUXML() - vmcpuxml.xml = "" + cpu_mode = params.get('cpu_mode') + vmcpuxml.xml = "" % cpu_mode if topology: vmcpuxml.topology = topology logging.debug(vmcpuxml.numa_cell) From c98acec5f311d9ec6998a74d25522d75f0589aca Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Tue, 30 Jan 2024 07:14:12 -0500 Subject: [PATCH 0151/1055] numa_memory_spread: smaller memhog value Sometimes memhog fails to eat a big value of memory. In order to make case stable, we decrese the value again. Signed-off-by: Dan Zheng --- libvirt/tests/src/numa/numa_memory_spread.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/numa/numa_memory_spread.py b/libvirt/tests/src/numa/numa_memory_spread.py index 249c356982c..f525586bbe5 100644 --- a/libvirt/tests/src/numa/numa_memory_spread.py +++ b/libvirt/tests/src/numa/numa_memory_spread.py @@ -84,7 +84,7 @@ def prepare_host_for_test(params, test): # Decrease nodeset size by 25% undersize = int(nodeset_size * 0.25) # Memory to eat is a whole nodeset + 5% of neighbour size - memory_to_eat = int(nodeset_size + 0.05 * nodeset_nb_size) + memory_to_eat = int(nodeset_size + 0.005 * nodeset_nb_size) nodeset_string = '{},{}'.format(online_nodes[0], neighbour) process.run("swapoff -a", shell=True) From 75bcb45c14f109a68ae923e40729bd2ce8c3eb03 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 30 Jan 2024 07:35:57 -0500 Subject: [PATCH 0152/1055] memory: disable tests on s390x No memory hotplug or NUMA on s390x. Disable these. Signed-off-by: Sebastian Mitterle --- .../memory_allocation/lifecycle_with_memory_allocation.cfg | 1 + .../cfg/memory/memory_balloon/guest_without_mem_balloon.cfg | 2 ++ .../memory/memory_balloon/period_config_of_memory_balloon.cfg | 2 ++ 3 files changed, 5 insertions(+) diff --git a/libvirt/tests/cfg/memory/memory_allocation/lifecycle_with_memory_allocation.cfg b/libvirt/tests/cfg/memory/memory_allocation/lifecycle_with_memory_allocation.cfg index eb6ca860617..dfe04550418 100644 --- a/libvirt/tests/cfg/memory/memory_allocation/lifecycle_with_memory_allocation.cfg +++ b/libvirt/tests/cfg/memory/memory_allocation/lifecycle_with_memory_allocation.cfg @@ -24,6 +24,7 @@ - negative_test: variants mem_config: - with_maxmemory: + no s390-virtio max_mem_attr = "'max_mem_rt': ${max_mem}, 'max_mem_rt_slots': ${max_mem_slots}, 'max_mem_rt_unit': '${max_mem_unit}'" vm_attrs = {${max_mem_attr},'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} error_msg = "At least one numa node has to be configured when enabling memory hotplug" diff --git a/libvirt/tests/cfg/memory/memory_balloon/guest_without_mem_balloon.cfg b/libvirt/tests/cfg/memory/memory_balloon/guest_without_mem_balloon.cfg index 77c0e3a5933..ecdc4faa6d9 100644 --- a/libvirt/tests/cfg/memory/memory_balloon/guest_without_mem_balloon.cfg +++ b/libvirt/tests/cfg/memory/memory_balloon/guest_without_mem_balloon.cfg @@ -13,8 +13,10 @@ - virtio_model: memballoon_model = "virtio" - virtio_trans_model: + no s390-virtio memballoon_model = "virtio-transitional" - virtio_non_trans_model: + no s390-virtio memballoon_model = "virtio-non-transitional" device_dict = "{'model':'${memballoon_model}'}" variants: diff --git a/libvirt/tests/cfg/memory/memory_balloon/period_config_of_memory_balloon.cfg b/libvirt/tests/cfg/memory/memory_balloon/period_config_of_memory_balloon.cfg index afa9a6ba3da..abf6bfdd306 100644 --- a/libvirt/tests/cfg/memory/memory_balloon/period_config_of_memory_balloon.cfg +++ b/libvirt/tests/cfg/memory/memory_balloon/period_config_of_memory_balloon.cfg @@ -10,8 +10,10 @@ - virtio_model: memballoon_model = "virtio" - virtio_trans_model: + no s390-virtio memballoon_model = "virtio-transitional" - virtio_non_trans_model: + no s390-virtio memballoon_model = "virtio-non-transitional" variants: - undefined_period: From b97c335f07c79d34ebff9f06b6c11ba3bb84f014 Mon Sep 17 00:00:00 2001 From: nanli Date: Wed, 31 Jan 2024 10:55:26 +0800 Subject: [PATCH 0153/1055] fix incorrect memory negative case error msg Signed-off-by: nanli --- .../memory/memory_devices/invalid_dimm_memory_device_config.cfg | 2 -- 1 file changed, 2 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_devices/invalid_dimm_memory_device_config.cfg b/libvirt/tests/cfg/memory/memory_devices/invalid_dimm_memory_device_config.cfg index 452a0ffb895..9e71974045b 100644 --- a/libvirt/tests/cfg/memory/memory_devices/invalid_dimm_memory_device_config.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/invalid_dimm_memory_device_config.cfg @@ -38,8 +38,6 @@ addr_type = 'fakedimm' define_error = "Invalid value for attribute 'type' in element 'address': '${addr_type}'" define_error_8 = "unknown address type '${addr_type}'" - aarch64: - define_error = "unknown address type '${addr_type}'" addr_dict = "'address':{'attrs': {'type': '${addr_type}', 'base': '${addr_base}', 'slot': '${slot}'}}" source_dict = "'source': {'nodemask': '${node_mask}','pagesize': %d, 'pagesize_unit':'${pagesize_unit}'}" dimm_dict = {'mem_model':'dimm', ${source_dict}, ${addr_dict}, 'target': {'size':${target_size}, 'size_unit':'KiB','node':${guest_node}}} From 5fc3758aff81791d7acf5bf0306945c1375d5643 Mon Sep 17 00:00:00 2001 From: Hu Shuai Date: Wed, 27 Dec 2023 16:41:43 +0800 Subject: [PATCH 0154/1055] numa: Fix the check of guest numa cell allaction If the memory mode and memnode mode are not set, It is unpredictable on which host numa node a guest numa cell will be allocated. So all the host numa nodes should be checked. The current test only considers the case where the host has two numa nodes. This patch fixes this issue. Signed-off-by: Hu Shuai --- .../host_guest_mixed_memory_binding.py | 90 +++++++++++-------- 1 file changed, 51 insertions(+), 39 deletions(-) diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.py b/libvirt/tests/src/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.py index 999c47c41fa..37dc7621872 100644 --- a/libvirt/tests/src/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.py +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.py @@ -106,60 +106,72 @@ def check_vm_numa_1_memory_allocation(numatest_obj, mem_size): mem_mode = numatest_obj.params.get('mem_mode') single_host_node = numatest_obj.params.get('single_host_node') all_nodes = numatest_obj.online_nodes_withmem - node0_value = re.findall('N%s=(\d+)' % all_nodes[0], out_numa_maps) - node1_value = re.findall('N%s=(\d+)' % all_nodes[1], out_numa_maps) - numatest_obj.test.log.debug("all_nodes:%s, N0_value:%s, " - "N1_value:%s", all_nodes, node0_value, node1_value) + node_values = {} + numatest_obj.test.log.debug("all_nodes:%s", all_nodes) + for node_num in all_nodes: + node_value = re.findall('N%s=(\d+)' % node_num, out_numa_maps) + if not node_value: + continue + numatest_obj.test.log.debug("N%s_value:%s", node_num, node_value[0]) + node_values[node_num] = node_value[0] def _check_N0_no_N1(): - if not node0_value: + if all_nodes[0] not in node_values: numatest_obj.test.fail("Expect N%s > 0, but found not" % all_nodes[0]) - if node1_value: + if all_nodes[1] in node_values: numatest_obj.test.fail("Not expect N%s to exist, but found" % all_nodes[1]) def _check_N0_N1_sum(): - n0_value = 0 if not node0_value else int(node0_value[0]) - n1_value = 0 if not node1_value else int(node1_value[0]) + n0_value = 0 if all_nodes[0] not in node_values else int(node_values[all_nodes[0]]) + n1_value = 0 if all_nodes[1] not in node_values else int(node_values[all_nodes[1]]) if n0_value + n1_value <= 0: numatest_obj.test.fail("Expect N%s + N%s > 0, but found " "not" % (all_nodes[0], all_nodes[1])) + def _check_all_nodes_sum(): + node_value_sum = 0 + for node_value in node_values.values(): + node_value_sum += int(node_value) + if node_value_sum <= 0: + numatest_obj.test.fail("Expect the sum of all node values is greater than 0, but found not") + def _check_N0(): - if not node0_value: + if all_nodes[0] not in node_values: numatest_obj.test.fail("Expect N%s > 0, but found not" % all_nodes[0]) - if single_host_node == "yes": - if mem_mode == 'strict' and memnode_mode in ['strict', 'interleave', 'preferred']: - pat = "bind:%s" % all_nodes[0] - _check_N0_no_N1() - if mem_mode == 'strict' and memnode_mode == 'restrictive': - pat = "bind:%s" % all_nodes[0] + if mem_mode is not None: + if single_host_node == "yes": + if mem_mode == 'strict' and memnode_mode in ['strict', 'interleave', 'preferred']: + pat = "bind:%s" % all_nodes[0] + _check_N0_no_N1() + if mem_mode == 'strict' and memnode_mode == 'restrictive': + pat = "bind:%s" % all_nodes[0] + _check_N0_N1_sum() + if mem_mode == 'interleave': + pat = "interleave:%s" % all_nodes[0] + _check_N0() + if mem_mode == 'preferred': + pat = "prefer \(many\):%s" % all_nodes[0] \ + if libvirt_version.version_compare(9, 3, 0) \ + else "prefer:%s" % all_nodes[0] + _check_N0() + if mem_mode == 'restrictive': + pat = "default" + _check_N0_N1_sum() + elif single_host_node == 'no': + nodeset = numa_base.convert_to_string_with_dash(numatest_obj.params['nodeset']) + if mem_mode == 'strict': + pat = "bind:%s" % nodeset + if mem_mode == 'interleave': + pat = "interleave:%s" % nodeset + if mem_mode == 'preferred': + pat = "prefer \(many\):%s" % nodeset + if mem_mode == 'restrictive': + pat = "default" _check_N0_N1_sum() - if mem_mode == 'interleave': - pat = "interleave:%s" % all_nodes[0] - _check_N0() - if mem_mode == 'preferred': - pat = "prefer \(many\):%s" % all_nodes[0] \ - if libvirt_version.version_compare(9, 3, 0) \ - else "prefer:%s" % all_nodes[0] - _check_N0() - if mem_mode == 'restrictive': - pat = "default" - _check_N0_N1_sum() - elif single_host_node == 'no': - nodeset = numa_base.convert_to_string_with_dash(numatest_obj.params['nodeset']) - if mem_mode == 'strict': - pat = "bind:%s" % nodeset - if mem_mode == 'interleave': - pat = "interleave:%s" % nodeset - if mem_mode == 'preferred': - pat = "prefer \(many\):%s" % nodeset - if mem_mode == 'restrictive': - pat = "default" - _check_N0_N1_sum() - if mem_mode is None: + else: pat = "default" - _check_N0_N1_sum() + _check_all_nodes_sum() search_pattern = r"\s+%s\s+anon=" % pat if not re.findall(search_pattern, out_numa_maps): From 9ee38e403b5cc46cc7cd163d457c43fb9da1a430 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 30 Jan 2024 10:03:16 -0500 Subject: [PATCH 0155/1055] virtual_disks/file_descriptor: fix disk discovery The test identified new disks by comparing the list of disks before and after plug. However, a reboot can mess up the non-persistent disk namings /dev/vdX. Use instead a function that identifies a new disk inside of a VM as the one disk that has no root mount on itself, its partitions or volumes. Make sleep time arch-independent for simpler and more stable code on all archs. Signed-off-by: Sebastian Mitterle --- .../virtual_disks_filedescriptor.py | 42 ++----------------- 1 file changed, 4 insertions(+), 38 deletions(-) diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_filedescriptor.py b/libvirt/tests/src/virtual_disks/virtual_disks_filedescriptor.py index 54fc7199b68..3798fe1ede6 100644 --- a/libvirt/tests/src/virtual_disks/virtual_disks_filedescriptor.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_filedescriptor.py @@ -10,15 +10,12 @@ import logging import os -import platform import shutil import time from avocado.utils import process from virttest import libvirt_version -from virttest import utils_disk -from virttest import utils_misc from virttest import utils_selinux from virttest import virsh from virttest import virt_vm @@ -32,33 +29,6 @@ cleanup_files = [] -def get_added_disks(old_partitions, test, params, env): - """ - Get new virtual disks in VM after disk plug. - - :param old_partitions: already existing partitions in VM - :param test: test object - :param params: one dictionary wrapping parameters - :param env: environment representing running context - :return: New disks/partitions in VM - """ - vm_name = params.get("main_vm") - vm = env.get_vm(vm_name) - session = None - try: - session = vm.wait_for_login() - if platform.platform().count('ppc64'): - time.sleep(10) - added_partitions = utils_disk.get_added_parts(session, old_partitions) - LOG.debug("Newly added partition(s) is: %s", added_partitions) - return added_partitions - except Exception as err: - test.fail("Error happens when get new disk: %s" % str(err)) - finally: - if session: - session.close() - - def create_customized_disk(params): """ Create one customized disk with related attributes @@ -264,7 +234,6 @@ def run(test, params, env): if vm.is_dead(): vm.start() session = vm.wait_for_login() - old_partitions = utils_disk.get_parts_list(session) session.close() if not hotplug: vm.destroy(gracefully=False) @@ -305,13 +274,10 @@ def run(test, params, env): "Error: %s" % str(xml_error)) else: check_disk_file_selinux_label(test, params, "after_start") - utils_misc.wait_for(lambda: get_added_disks(old_partitions, test, params, env), 20) - new_disks = get_added_disks(old_partitions, test, params, env) - if len(new_disks) != 1: - test.fail("Attached 1 virtual disk but got %s." % len(new_disks)) - new_disk = new_disks[0] - if platform.platform().count('ppc64'): - time.sleep(10) + session = vm.wait_for_login() + new_disk, _ = libvirt_disk.get_non_root_disk_name(session) + session.close() + time.sleep(10) if disk_readonly: if libvirt_disk.check_virtual_disk_io(vm, new_disk, path=part_path): test.fail("Expect the newly added disk is not writable, but actually it is") From b39b5d6faf262a4ca0ddd1fae229f6fc23ebce06 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 31 Jan 2024 06:36:17 -0500 Subject: [PATCH 0156/1055] virsh_event: fix disk discovery The test identified new disks by their target name. However, a reboot can mess up the non-persistent disk namings /dev/vdX. Use instead a function that identifies a new disk inside of a VM as the one disk that has no root mount on itself, its partitions or volumes. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/event/virsh_event.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/src/event/virsh_event.py b/libvirt/tests/src/event/virsh_event.py index 3b4ccef1a63..6d2755e1523 100644 --- a/libvirt/tests/src/event/virsh_event.py +++ b/libvirt/tests/src/event/virsh_event.py @@ -21,6 +21,7 @@ from virttest.libvirt_xml.devices.interface import Interface from virttest.libvirt_xml.devices.panic import Panic from virttest.libvirt_xml.devices.watchdog import Watchdog +from virttest.utils_libvirt.libvirt_disk import get_non_root_disk_name from xml.dom.minidom import parseString @@ -378,8 +379,10 @@ def _check_disk(target): logging.debug(process.run('qemu-img info %s -U' % new_disk)) virsh.domblkthreshold(vm_name, 'vdb', '100M') session = dom.wait_for_login() - session.cmd("mkfs.ext4 /dev/vdb && mount /dev/vdb /mnt && ls /mnt && " - "dd if=/dev/urandom of=/mnt/bigfile bs=1M count=300 && sync", timeout=90) + disk_name, _ = get_non_root_disk_name(session) + session.cmd("mkfs.ext4 /dev/%s && mount /dev/%s /mnt && ls /mnt && " + "dd if=/dev/urandom of=/mnt/bigfile bs=1M count=300 && sync" + % (disk_name, disk_name), timeout=90) time.sleep(5) session.close() expected_events_list.append("'block-threshold' for %s:" @@ -558,8 +561,10 @@ def _check_disk(target): add_disk(dom.name, new_disk, 'vdb', '--subdriver qcow2 --config', 'qcow2') dom.start() session = dom.wait_for_login() - session.cmd("mkfs.ext4 /dev/vdb && mount /dev/vdb /mnt && ls /mnt && " - "dd if=/dev/zero of=/mnt/test.img bs=1M count=50", ignore_all_errors=True) + disk_name, _ = get_non_root_disk_name(session) + session.cmd("mkfs.ext4 /dev/%s && mount /dev/%s /mnt && ls /mnt && " + "dd if=/dev/zero of=/mnt/test.img bs=1M count=50" + % (disk_name, disk_name), ignore_all_errors=True) time.sleep(5) session.close() expected_events_list.append("'io-error' for %s: " + "%s" % new_disk + r" \(virtio-disk1\) pause") From e1f3afe35a1953404883514eba207ad7abcfac42 Mon Sep 17 00:00:00 2001 From: Hu Shuai Date: Thu, 1 Feb 2024 10:09:10 +0800 Subject: [PATCH 0157/1055] virtual_networks: Extend the timeout for obtaining guest IP The guest ip addr may not be obtained within 1 second, extend the timeout to 5. Signed-off-by: Hu Shuai --- libvirt/tests/src/virtual_network/virtual_network_multivms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_network/virtual_network_multivms.py b/libvirt/tests/src/virtual_network/virtual_network_multivms.py index 2ebbd27a299..22bd602b6a2 100644 --- a/libvirt/tests/src/virtual_network/virtual_network_multivms.py +++ b/libvirt/tests/src/virtual_network/virtual_network_multivms.py @@ -368,7 +368,7 @@ def pause_resume_vm(vm_name): for vm_i in vm_list: mac = vm_xml.VMXML.get_first_mac_by_name(vm_i.name) sess = vm_i.wait_for_serial_login() - vm_ip = utils_net.get_guest_ip_addr(sess, mac) + vm_ip = utils_net.get_guest_ip_addr(sess, mac, timeout=5) session_n_ip[sess] = vm_ip logging.debug('Vm %s ip: %s', vm_i.name, vm_ip) if not vm_ip: From 2844886e9a7cca2e3de77249077c974cfb15168e Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Thu, 1 Feb 2024 03:16:24 -0500 Subject: [PATCH 0158/1055] virtual_disk/multidisks: fix disk discovery 426de63d8bb0d608c72a3d2f22d918f0c4604391 fixed the disk discovery for most tests. However, the block size check still used the target device names and therefore sometimes failed. Use the function to discover new disks from within the VM. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/virtual_disks/virtual_disks_multidisks.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_multidisks.py b/libvirt/tests/src/virtual_disks/virtual_disks_multidisks.py index 4796cc111cb..3d05aea49f9 100644 --- a/libvirt/tests/src/virtual_disks/virtual_disks_multidisks.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_multidisks.py @@ -403,11 +403,13 @@ def check_vm_block_size(targets_name, log_size, phy_size): logging.info("Checking VM block size...") try: session = vm.wait_for_login() + new_disks = libvirt_disk.get_non_root_disk_names(session) + new_disk_names = [disk_info[0] for disk_info in new_disks] # Here the script needs wait for a while for the guest to # recognize the block on PPC add_sleep() - for target in targets_name: - cmd = "cat /sys/block/%s/queue/" % target + for disk_name in new_disk_names: + cmd = "cat /sys/block/%s/queue/" % disk_name s, o = session.cmd_status_output("%slogical_block_size" % cmd) logging.debug("logical block size in VM:\n%s", o) From c0bd331c7462b1de51c2edf3ee7c7840a60022f6 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Thu, 1 Feb 2024 04:23:19 -0500 Subject: [PATCH 0159/1055] Disable unsupport serial device hotplug case on S390 Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/svirt/dac/dac_seclabel_per_device.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/cfg/svirt/dac/dac_seclabel_per_device.cfg b/libvirt/tests/cfg/svirt/dac/dac_seclabel_per_device.cfg index 3319f870d80..42ce918c97f 100644 --- a/libvirt/tests/cfg/svirt/dac/dac_seclabel_per_device.cfg +++ b/libvirt/tests/cfg/svirt/dac/dac_seclabel_per_device.cfg @@ -7,6 +7,7 @@ - cold_plug: - hot_plug: serial: + no s390-virtio func_supported_since_libvirt_ver = (8, 7, 0) variants test_device: - disk: From 86979edc44501bf4346f4640abfcff9885cfbe1b Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Thu, 1 Feb 2024 13:19:34 -0500 Subject: [PATCH 0160/1055] passt: fix check_default_gw The default gateway function in utils_net now will return None when it detects ipv6 multipath. Update the provider code to fail the test if this is the case. If not, the test case will fail with "NoneType" object has no attribute 'split'". Also, pass the host interface to be tested to have more control. Signed-off-by: Sebastian Mitterle --- .../passt/passt_attach_detach.py | 2 +- .../virtual_network/passt/passt_function.py | 2 +- .../virtual_network/passt/passt_reconnect.py | 2 +- .../passt/passt_transfer_file.py | 2 +- provider/virtual_network/passt.py | 18 +++++++++++++----- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py index e060a8a7816..be12ffd6c1e 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py +++ b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py @@ -126,7 +126,7 @@ def run(test, params, env): session = vm.wait_for_serial_login(timeout=60) passt.check_vm_ip(iface_attrs, session, host_iface, vm_iface) passt.check_vm_mtu(session, vm_iface, mtu) - passt.check_default_gw(session) + passt.check_default_gw(session, host_iface) passt.check_nameserver(session) ips = { diff --git a/libvirt/tests/src/virtual_network/passt/passt_function.py b/libvirt/tests/src/virtual_network/passt/passt_function.py index ef57ffc6063..b430ca28c93 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_function.py +++ b/libvirt/tests/src/virtual_network/passt/passt_function.py @@ -99,7 +99,7 @@ def run(test, params, env): session = vm.wait_for_serial_login(timeout=60) passt.check_vm_ip(iface_attrs, session, host_iface, vm_iface) passt.check_vm_mtu(session, vm_iface, mtu) - passt.check_default_gw(session) + passt.check_default_gw(session, host_iface) passt.check_nameserver(session) ips = { diff --git a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py index 733d5d2ce9f..13ae4b6f439 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py +++ b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py @@ -111,7 +111,7 @@ def run(test, params, env): session = vm.wait_for_serial_login(timeout=60) passt.check_vm_ip(iface_attrs, session, host_iface, vm_iface) passt.check_vm_mtu(session, vm_iface, mtu) - passt.check_default_gw(session) + passt.check_default_gw(session, host_iface) passt.check_nameserver(session) ips = { diff --git a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py index 9d4e82bc50c..2fb33af5f8f 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py +++ b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py @@ -172,7 +172,7 @@ def run(test, params, env): LOG.debug(virsh_ins.dumpxml(vm_name).stdout_text) session = vm.wait_for_serial_login(timeout=60) - passt.check_default_gw(session) + passt.check_default_gw(session, host_iface) prot = 'TCP' if ip_ver == 'ipv4' else 'TCP6' if direction == 'host_to_vm': diff --git a/provider/virtual_network/passt.py b/provider/virtual_network/passt.py index 3666165e969..808e7597e8b 100644 --- a/provider/virtual_network/passt.py +++ b/provider/virtual_network/passt.py @@ -234,20 +234,28 @@ def check_vm_mtu(session, iface, mtu): raise exceptions.TestFail(f'Wrong vm mtu: {vm_mtu}, should be {mtu}') -def check_default_gw(session): +def check_default_gw(session, host_iface=None): """ Check whether default host gateways of host and guest are consistent, i.e. the guest's gateways are available on the host. :param session: vm shell session instance + :param host_iface: if given, only check gateway information on this + host interface """ - host_gw = utils_net.get_default_gateway(force_dhcp=True).split() + host_gw = utils_net.get_default_gateway(force_dhcp=True, + target_iface=host_iface).split() vm_gw = utils_net.get_default_gateway(session=session, force_dhcp=True).split() LOG.debug(f'Host and vm default ipv4 gateway: {host_gw}, {vm_gw}') - host_gw_v6 = utils_net.get_default_gateway(ip_ver='ipv6').split() - vm_gw_v6 = utils_net.get_default_gateway(session=session, - ip_ver='ipv6').split() + _host_gw_v6 = utils_net.get_default_gateway(ip_ver='ipv6', + target_iface=host_iface) + _vm_gw_v6 = utils_net.get_default_gateway(session=session, ip_ver='ipv6') + if not _host_gw_v6 or not _vm_gw_v6: + raise exceptions.TestFail( + 'Cannot recognize ipv6 multipath router!') + host_gw_v6 = _host_gw_v6.split() + vm_gw_v6 = _vm_gw_v6.split() LOG.debug(f'Host and vm default ipv6 gateway: {host_gw_v6}, {vm_gw_v6}') if [x for x in vm_gw if x not in host_gw]: From c0dab18c80e0fd52d148520bab3fc11f02e51d11 Mon Sep 17 00:00:00 2001 From: lcheng Date: Fri, 2 Feb 2024 12:38:23 +0800 Subject: [PATCH 0161/1055] migration: Add case about abort job VIRT-297945 - VM live migration with copy storage - abort job(domjobabort) - on src host Signed-off-by: lcheng --- .../async_job/abort_job.cfg | 77 +++++++++++++++++++ .../async_job/abort_job.py | 41 ++++++++++ 2 files changed, 118 insertions(+) create mode 100644 libvirt/tests/cfg/migration_with_copy_storage/async_job/abort_job.cfg create mode 100644 libvirt/tests/src/migration_with_copy_storage/async_job/abort_job.py diff --git a/libvirt/tests/cfg/migration_with_copy_storage/async_job/abort_job.cfg b/libvirt/tests/cfg/migration_with_copy_storage/async_job/abort_job.cfg new file mode 100644 index 00000000000..7452e865e02 --- /dev/null +++ b/libvirt/tests/cfg/migration_with_copy_storage/async_job/abort_job.cfg @@ -0,0 +1,77 @@ +- migration_with_copy_storage.async_job.abort_job: + type = abort_job + migration_setup = 'yes' + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = "" + # SSH connection time out + ssh_timeout = 60 + start_vm = "yes" + # Local URI + virsh_migrate_connect_uri = qemu:///system" + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = "no" + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + simple_disk_check_after_mig = "yes" + status_error = "yes" + setup_nfs = "no" + nfs_mount_dir = + setup_local_nfs = "no" + storage_type = "" + port_to_check = "49153" + migrate_again = "yes" + migrate_again_status_error = 'no' + stress_package = "stress" + stress_args = "--cpu 8 --io 4 --vm 4 --vm-bytes 128M --timeout 50s" + action_during_mig_again = '[{"func": "libvirt_network.check_established", "func_param": "params", "need_sleep_time": "1"}]' + domjobabort_on_src = "yes" + variants: + - p2p: + virsh_migrate_options = "--live --p2p --verbose" + - non_p2p: + virsh_migrate_options = "--live --verbose" + variants: + - with_precopy: + variants: + - tcp: + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + - unix_proxy: + desturi_socket_path = "/tmp/desturi-socket" + migrateuri_socket_path = "/var/lib/libvirt/qemu/migrateuri-socket" + disks_uri_socket_path = "/var/lib/libvirt/qemu/disks-uri-socket" + migrate_desturi_type = "unix_proxy" + virsh_migrate_desturi = "qemu+unix:///system?socket=${desturi_socket_path}" + variants: + - copy_storage_all: + virsh_migrate_extra = "--copy-storage-all" + - copy_storage_inc: + virsh_migrate_extra = "--copy-storage-inc" + variants: + - with_tls: + virsh_migrate_extra = "${virsh_migrate_extra} --tls" + transport_type = "tls" + custom_pki_path = "/etc/pki/qemu" + qemu_tls = "yes" + server_cn = "ENTER.YOUR.EXAMPLE.SERVER_CN" + client_cn = "ENTER.YOUR.EXAMPLE.CLIENT_CN" + - without_tls: + variants: + - abort_in_storage_copy_phase: + action_during_mig = '[{"func": "libvirt_network.check_established", "func_param": "params", "need_sleep_time": "3"}, {"func": "do_domjobabort", "func_param": "params"}]' + expected_event_src = ["block-job.*Block Copy for.* failed", "block-job-2.*Block Copy for vda failed"] + expected_event_target = ["lifecycle.*Stopped Failed"] + err_msg = "operation aborted: migration out: canceled by client" + - abort_in_memory_copy_phase: + action_during_mig = '[{"func": "libvirt_network.check_established", "after_event": "migration-iteration", "func_param": "params", "wait_for_after_event_timeout": "600"}, {"func": "do_domjobabort", "func_param": "params"}]' + expected_event_target = ["lifecycle.*Stopped Failed"] + err_msg = "operation aborted: job 'migration out' canceled by client" diff --git a/libvirt/tests/src/migration_with_copy_storage/async_job/abort_job.py b/libvirt/tests/src/migration_with_copy_storage/async_job/abort_job.py new file mode 100644 index 00000000000..22b24b22b14 --- /dev/null +++ b/libvirt/tests/src/migration_with_copy_storage/async_job/abort_job.py @@ -0,0 +1,41 @@ +from provider.migration import base_steps +from provider.migration import migration_base + + +def run(test, params, env): + """ + To verify that vm live migration with copying storage can be aborted + successfully, and related resource can be cleaned up so next migration + can succeed. + + """ + def verify_test(): + """ + Verify test + + """ + migration_obj.verify_default() + # Check event output + migration_base.check_event_output(params, test, virsh_session, remote_virsh_session) + + vm_name = params.get("migrate_main_vm") + migrate_again = "yes" == params.get("migrate_again", "no") + + virsh_session = None + remote_virsh_session = None + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + migration_obj.setup_connection() + base_steps.prepare_disks_remote(params, vm) + # Monitor event on source/target host + virsh_session, remote_virsh_session = migration_base.monitor_event(params) + migration_obj.run_migration() + if migrate_again: + migration_obj.run_migration_again() + verify_test() + finally: + base_steps.cleanup_disks_remote(params, vm) + migration_obj.cleanup_connection() From baef49e3ac48fc47b4e19344e458f6fc32dbeb38 Mon Sep 17 00:00:00 2001 From: Hu Shuai Date: Fri, 2 Feb 2024 10:24:36 +0800 Subject: [PATCH 0162/1055] virtual_networks: Fix the cutting of ip addr replace() here will cut "xxx.xxx.122.122" to "xxx.xxx" which is not expected. Signed-off-by: Hu Shuai --- .../connectivity/connectivity_check_mcast_interface.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_mcast_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_mcast_interface.py index fb3e38743fe..e73b88e4ea8 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_mcast_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_mcast_interface.py @@ -67,7 +67,7 @@ def run(test, params, env): # Build omping command ip_suf, ip_suf_c = (ip_i.split('.')[-1] for ip_i in (ip, ip_c)) - ip_pre = ip.replace(f'.{ip_suf}', '') + ip_pre = '.'.join(ip.split('.')[:3]) omping_cmd = f'omping -m {mcast_addr} {ip_pre}.{{{ip_suf},{ip_suf_c}}}' # omping from vm to vm_c @@ -75,7 +75,7 @@ def run(test, params, env): status, output = utils_net.raw_ping(omping_cmd, 5, session, output_func=LOG.debug) if 'response message never received' not in output: - test.fail('omping should fail with remote vm firewalld on') + test.fail(f'omping failed due to "{output}"') # Keep omping process alive on vm then omping from vm_c to vm session.sendline(omping_cmd) From fc2ea57bb34609cd8be6a20a7f9db0aa3a122a97 Mon Sep 17 00:00:00 2001 From: nanli Date: Fri, 8 Dec 2023 22:45:29 +0800 Subject: [PATCH 0163/1055] add case for dimm memory with access and discard setting xxxx-299048:Dimm memory device with access and discard settings Signed-off-by: nanli --- .../dimm_memory_with_access_and_discard.cfg | 70 ++++++ .../dimm_memory_with_access_and_discard.py | 221 ++++++++++++++++++ 2 files changed, 291 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_access_and_discard.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/dimm_memory_with_access_and_discard.py diff --git a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_access_and_discard.cfg b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_access_and_discard.cfg new file mode 100644 index 00000000000..44a991d5101 --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_access_and_discard.cfg @@ -0,0 +1,70 @@ +- memory.devices.dimm.access_and_discard: + type = dimm_memory_with_access_and_discard + start_vm = yes + mem_model = "dimm" + dimm_mem_num = 6 + share_0 = 'false' + discard_0 = 'False' + check_path = "ls -l /var/lib/libvirt/qemu/ram/%s" + target_size = 131072 + requested_size = 131072 + block_size = 2048 + aarch64: + target_size = 1048576 + requested_size = 524288 + block_size = 524288 + dimm_basic = {'mem_model': '${mem_model}', 'target': {'requested_unit': 'KiB', 'size': ${target_size}, 'size_unit': 'KiB', 'requested_size': ${requested_size}, 'block_unit': 'KiB', 'block_size': ${block_size}}} + kernel_params_add = "memhp_default_state=online_movable" + variants memory_backing: + - file: + source_type = 'file' + - anonymous: + source_type = 'anonymous' + - memfd: + source_type = 'memfd' + discard_error = 'yes' + discard_error_msg = "Property 'memory-backend-memfd.discard-data' not found" + variants: + - undefined: + memfd: + share_0 = 'true' + file: + discard_0 = 'False' + anonymous: + discard_error = 'yes' + discard_error_msg = "Property 'memory-backend-ram.discard-data' not found" + - shared_and_discard: + discard_attr = "'discard':'yes'" + access_attr = "'access_mode':'shared'" + share_0 = 'true' + file: + discard_0 = 'True' + anonymous: + discard_0 = 'True' + - private_and_no_discard: + access_attr = "'access_mode':'private'" + file: + discard_0 = 'False' + anonymous: + discard_0 = 'False' + source_attr = "'source_type':'${source_type}'" + expected_share = ['${share_0}', 'true', 'true', 'false', 'false', 'true'] + check_discard = '{"execute":"qom-get", "arguments":{"path":"/objects/%s", "property":"discard-data"}}' + expected_discard = ['${discard_0}', 'True', 'True', 'False', 'False', 'True'] + variants: + - with_numa: + no s390-virtio + mem_value = 3145728 + current_mem = 3145728 + max_mem = 10485760 + numa_mem = 1048576 + aarch64: + max_mem = 20971520 + mem_access_1 = "shared" + discard_1 = "yes" + mem_access_2 = "private" + discard_2 = "no" + base_attrs = "'vcpu': 6, 'placement': 'static', 'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'" + numa_attrs = "'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_mem}', 'unit': 'KiB', 'memAccess':'${mem_access_1}','discard':'${discard_1}'},{'id':'2','cpus': '4-5','memory':'${numa_mem}','unit':'KiB', 'memAccess':'${mem_access_2}','discard':'${discard_2}'}]}" + max_attrs = "'max_mem_rt': ${max_mem}, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'" + vm_attrs = {${base_attrs}, ${numa_attrs}, ${max_attrs}} diff --git a/libvirt/tests/src/memory/memory_devices/dimm_memory_with_access_and_discard.py b/libvirt/tests/src/memory/memory_devices/dimm_memory_with_access_and_discard.py new file mode 100644 index 00000000000..ed97fb81a99 --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/dimm_memory_with_access_and_discard.py @@ -0,0 +1,221 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import re +import json + +from avocado.utils import process + +from virttest import utils_test +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirtd import Libvirtd +from virttest.utils_libvirt import libvirt_vmxml + + +def get_vm_attrs(test, params): + """ + Get vm attrs. + + :param test: test object + :param params: dictionary with the test parameters + :return vm_attrs: get updated vm attrs dict. + """ + vm_attrs = eval(params.get("vm_attrs", "{}")) + source_attr = params.get("source_attr", "") + discard_attr = params.get("discard_attr", "") + access_attr = params.get("access_attr", "") + + mb_value = "" + for item in [source_attr, discard_attr, access_attr]: + if item != "": + mb_value += item + "," + mb_attrs = eval("{'mb':{%s}}" % mb_value[:-1]) + + vm_attrs.update(mb_attrs) + test.log.debug("Get current vm attrs is :%s", vm_attrs) + + return vm_attrs + + +def create_dimm_mem_list(test, params): + """ + Get 6 basic different dimm memory devices. + + :param test: test object. + :param params: dictionary with the test parameters. + :return mem_list: dimm memory attr dict list. + """ + mem_list = [] + for item in [(None, None, 0), ('shared', 'yes', 0), + (None, None, 1), ('private', 'no', 1), + (None, None, 2), ('shared', 'yes', 2)]: + + single_mem = eval(params.get("dimm_basic")) + target = single_mem['target'] + target.update({'node': item[2]}) + + if item[0] is not None: + single_mem.update({'mem_access': item[0]}) + if item[1] is not None: + single_mem.update({'mem_discard': item[1]}) + mem_list.append(single_mem) + + test.log.debug("Get all dimm list:'%s'", mem_list) + return mem_list + + +def check_access_and_discard(test, params, vm, + expected_share, expected_discard): + """ + Check access and discard setting. + + :param test: test object. + :param params: dictionary with the test parameters. + :param vm: vm object. + :param expected_share: expected access shared value list. + :param expected_discard: expected discard value list. + """ + dimm_mem_num = int(params.get("dimm_mem_num")) + check_discard = params.get("check_discard") + discard_error_msg = params.get("discard_error_msg") + mem_name_list = [] + + # Check access share setting + ret = virsh.qemu_monitor_command(vm.name, "info memdev", "--hmp", + debug=True).stdout_text.replace("\r\n", "") + for index in range(dimm_mem_num): + mem_name = "memdimm%d" % index + pattern = "memory backend: %s.*share: %s " % (mem_name, expected_share[index]) + if not re.search(pattern, ret): + test.fail("Expect '%s' exist, but not found" % pattern) + else: + test.log.debug("Check access shared value is '%s': PASS", pattern) + mem_name_list.append(mem_name) + + # Check discard setting + for index, mem_name in enumerate(mem_name_list): + res = virsh.qemu_monitor_command( + vm.name, check_discard % mem_name, debug=True).stdout_text + + if 'return' in json.loads(res): + actual_discard = str(json.loads(res)['return']) + if actual_discard != expected_discard[index]: + test.fail("Expect discard is '%s', but got '%s'" % ( + expected_discard[index], actual_discard)) + else: + test.log.debug("Check discard value is '%s' PASS", actual_discard) + else: + actual_error = json.loads(res)['error']['desc'] + if not re.search(discard_error_msg, actual_error): + test.fail("Expected to get '%s' in '%s'" % (discard_error_msg, + actual_error)) + else: + test.log.debug("Check '%s' PASS ", actual_error) + + +def run(test, params, env): + """ + Verify dimm memory device works with access and discard settings. + """ + def setup_test(): + """ + Set kernel parameter memhp_default_state to online_movable( + this would make hotunplug more reliable) + """ + utils_test.update_boot_option(vm, args_added=kernel_params_add, + need_reboot=True) + vm.destroy() + + def run_test(): + """ + 1.Define vm with dimm memory device. + 2.Check the dimm memory device access and discard setting. + 3.Define vm without dimm memory device and restart service, and hotplug + dimm device. + """ + test.log.info("TEST_STEP1: Define vm with dimm memory") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vmxml.remove_all_device_by_type("memory") + + vm_attrs = get_vm_attrs(test, params) + vmxml.setup_attrs(**vm_attrs) + + all_dimms = create_dimm_mem_list(test, params) + dimm_objs = [] + for mem in all_dimms: + dimm = libvirt_vmxml.create_vm_device_by_type('memory', mem) + vmxml.devices = vmxml.devices.append(dimm) + dimm_objs.append(dimm) + vmxml.sync() + + test.log.info("TEST_STEP2: Start guest") + vm.start() + vm.wait_for_login().close() + + test.log.info("TEST_STEP3,4: Check dimm memory access and discard") + check_access_and_discard(test, params, vm, expected_share, + expected_discard) + + test.log.info("TEST_STEP5: Hot unplug all dimm memory device") + for dimm in dimm_objs: + virsh.detach_device(vm_name, dimm.xml, + debug=True, ignore_status=False) + + test.log.info("TEST_STEP6: Destroy vm") + vm.destroy() + + test.log.info("TEST_STEP7: Check the host path for memory file backing") + res = process.run(check_path % vm_name, shell=True, ignore_status=True).stderr_text + if not re.search(path_error, res): + test.fail("Expected '%s', but got '%s'" % (path_error, res)) + + test.log.info("TEST_STEP8: Define guest without any dimm memory") + original_xml.setup_attrs(**vm_attrs) + original_xml.sync() + vm.start() + + test.log.info("TEST_STEP8: Restart service") + Libvirtd().restart() + + test.log.info("TEST_STEP9: Hot plug all dimm memory device") + for dimm in dimm_objs: + virsh.attach_device(vm_name, dimm.xml, + debug=True, ignore_status=False) + + test.log.info("TEST_STEP10: Check dimm discard and access again.") + check_access_and_discard(test, params, vm, + expected_share, expected_discard) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + utils_test.update_boot_option(vm, args_removed=kernel_params_add, + need_reboot=True) + bkxml.sync() + + vm_name = params.get("main_vm") + original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = original_xml.copy() + vm = env.get_vm(vm_name) + + kernel_params_add = params.get("kernel_params_add") + expected_share = eval(params.get("expected_share")) + expected_discard = eval(params.get("expected_discard")) + check_path = params.get("check_path") + path_error = params.get("path_error", "No such file or directory") + + try: + setup_test() + run_test() + + finally: + teardown_test() From e8617a710e59d10a45dcd03afe4e9d5035a576f9 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Sun, 4 Feb 2024 12:21:16 +0800 Subject: [PATCH 0164/1055] input_devices_plug_unplug: add case Test input device, like tablet, mouse, keyboard, hotplug and hotunplug with virtio and usb bus. Signed-off-by: Dan Zheng --- .../libvirt_usb_hotplug_controller.cfg | 0 .../{ => usb}/libvirt_usb_hotplug_device.cfg | 0 libvirt/tests/cfg/{ => usb}/usb_device.cfg | 0 .../{passthrough => }/usb/usb_passthrough.cfg | 0 .../input_devices_plug_unplug.cfg | 16 +++ .../libvirt_usb_hotplug_controller.py | 0 .../{ => usb}/libvirt_usb_hotplug_device.py | 0 libvirt/tests/src/{ => usb}/usb_device.py | 0 .../{passthrough => }/usb/usb_passthrough.py | 0 .../input_devices_plug_unplug.py | 104 ++++++++++++++++++ 10 files changed, 120 insertions(+) rename libvirt/tests/cfg/{ => usb}/libvirt_usb_hotplug_controller.cfg (100%) rename libvirt/tests/cfg/{ => usb}/libvirt_usb_hotplug_device.cfg (100%) rename libvirt/tests/cfg/{ => usb}/usb_device.cfg (100%) rename libvirt/tests/cfg/{passthrough => }/usb/usb_passthrough.cfg (100%) create mode 100644 libvirt/tests/cfg/virtual_device/input_devices_plug_unplug.cfg rename libvirt/tests/src/{ => usb}/libvirt_usb_hotplug_controller.py (100%) rename libvirt/tests/src/{ => usb}/libvirt_usb_hotplug_device.py (100%) rename libvirt/tests/src/{ => usb}/usb_device.py (100%) rename libvirt/tests/src/{passthrough => }/usb/usb_passthrough.py (100%) create mode 100644 libvirt/tests/src/virtual_device/input_devices_plug_unplug.py diff --git a/libvirt/tests/cfg/libvirt_usb_hotplug_controller.cfg b/libvirt/tests/cfg/usb/libvirt_usb_hotplug_controller.cfg similarity index 100% rename from libvirt/tests/cfg/libvirt_usb_hotplug_controller.cfg rename to libvirt/tests/cfg/usb/libvirt_usb_hotplug_controller.cfg diff --git a/libvirt/tests/cfg/libvirt_usb_hotplug_device.cfg b/libvirt/tests/cfg/usb/libvirt_usb_hotplug_device.cfg similarity index 100% rename from libvirt/tests/cfg/libvirt_usb_hotplug_device.cfg rename to libvirt/tests/cfg/usb/libvirt_usb_hotplug_device.cfg diff --git a/libvirt/tests/cfg/usb_device.cfg b/libvirt/tests/cfg/usb/usb_device.cfg similarity index 100% rename from libvirt/tests/cfg/usb_device.cfg rename to libvirt/tests/cfg/usb/usb_device.cfg diff --git a/libvirt/tests/cfg/passthrough/usb/usb_passthrough.cfg b/libvirt/tests/cfg/usb/usb_passthrough.cfg similarity index 100% rename from libvirt/tests/cfg/passthrough/usb/usb_passthrough.cfg rename to libvirt/tests/cfg/usb/usb_passthrough.cfg diff --git a/libvirt/tests/cfg/virtual_device/input_devices_plug_unplug.cfg b/libvirt/tests/cfg/virtual_device/input_devices_plug_unplug.cfg new file mode 100644 index 00000000000..120d4acd0cf --- /dev/null +++ b/libvirt/tests/cfg/virtual_device/input_devices_plug_unplug.cfg @@ -0,0 +1,16 @@ +- virtual_devices.input_devices_plug_unplug: + type = input_devices_plug_unplug + take_regular_screendumps = no + start_vm = no + + variants multiple_input_types: + - tablet_mouse_keyboard: + device_types = ['tablet', 'mouse', 'keyboard'] + variants: + - bus_usb: + no s390-virtio + bus_type = usb + - bus_virtio: + bus_type = virtio + variants: + - hot: diff --git a/libvirt/tests/src/libvirt_usb_hotplug_controller.py b/libvirt/tests/src/usb/libvirt_usb_hotplug_controller.py similarity index 100% rename from libvirt/tests/src/libvirt_usb_hotplug_controller.py rename to libvirt/tests/src/usb/libvirt_usb_hotplug_controller.py diff --git a/libvirt/tests/src/libvirt_usb_hotplug_device.py b/libvirt/tests/src/usb/libvirt_usb_hotplug_device.py similarity index 100% rename from libvirt/tests/src/libvirt_usb_hotplug_device.py rename to libvirt/tests/src/usb/libvirt_usb_hotplug_device.py diff --git a/libvirt/tests/src/usb_device.py b/libvirt/tests/src/usb/usb_device.py similarity index 100% rename from libvirt/tests/src/usb_device.py rename to libvirt/tests/src/usb/usb_device.py diff --git a/libvirt/tests/src/passthrough/usb/usb_passthrough.py b/libvirt/tests/src/usb/usb_passthrough.py similarity index 100% rename from libvirt/tests/src/passthrough/usb/usb_passthrough.py rename to libvirt/tests/src/usb/usb_passthrough.py diff --git a/libvirt/tests/src/virtual_device/input_devices_plug_unplug.py b/libvirt/tests/src/virtual_device/input_devices_plug_unplug.py new file mode 100644 index 00000000000..73a520906d1 --- /dev/null +++ b/libvirt/tests/src/virtual_device/input_devices_plug_unplug.py @@ -0,0 +1,104 @@ +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 +# Author: Dan Zheng +# + +from virttest.libvirt_xml.devices.input import Input +from virttest.libvirt_xml.vm_xml import VMXML +from virttest import virsh + + +def prepare_vm_xml(vm_xml, device_type, test): + """ + Remove specified devices from the vm xml for the test + + :param vm_xml: vm xml + :param device_type: str, device type + :param test: test object + """ + vm_xml.remove_all_device_by_type(device_type) + vm_xml.sync() + test.log.debug("The VM xml after preparation:" + "\n%s", VMXML.new_from_dumpxml(vm_xml.vm_name)) + + +def check_dumpxml(vm_name, expect_device_types, expect_bus, expect_exist, test): + """ + Check whether the specified devices are(or aren't) shown in the guest xml + + :param vm_name: str, vm name + :param expect_device_types: list, device types, like ['keyboard', 'mouse'] + :param expect_bus: str, device bus, like 'virtio' + :param expect_exist: boolean, True for existence, False for not + :param test: test object + """ + current_vmxml = VMXML.new_from_dumpxml(vm_name) + input_devices = current_vmxml.get_devices(device_type="input") + test.log.debug("Current vm xml:\n%s", current_vmxml) + for device_type in expect_device_types: + found = False + for dev in input_devices: + if dev.type_name == device_type and dev.input_bus == expect_bus: + found = True + test.log.debug("Found the expected %s device " + "with %s bus", device_type, expect_bus) + break + if found == expect_exist: + test.log.debug("Verify guest xml for the %s device " + "with %s bus - PASS", device_type, expect_bus) + + else: + test.fail("Expect the %s device with %s bus %s " + "exist." % (device_type, + expect_bus, + 'not' if not expect_exist else '')) + + +def run(test, params, env): + """ + Test the input virtual devices + + 1. Start a guest + 2. Test hotplug and hotunplug different input devices + 3. check the result + """ + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + vm_xml = VMXML.new_from_dumpxml(vm_name) + vm_xml_backup = vm_xml.copy() + + bus_type = params.get("bus_type") + device_types = eval(params.get("device_types")) + virsh_dargs = {'ignore_status': False, 'debug': True} + device_list = [] + + if vm.is_alive(): + vm.destroy() + + try: + test.log.info("STEP: Clean input devices from VM xml.") + prepare_vm_xml(vm_xml, 'input', test) + test.log.info("STEP: Start VM") + virsh.start(vm_name, **virsh_dargs) + vm.wait_for_login().close() + for input_type in device_types: + input_dev = Input(type_name=input_type) + input_dev.input_bus = bus_type + device_list.append(input_dev) + test.log.info("STEP: Hotplug device:%s", input_dev) + virsh.attach_device(vm_name, input_dev.xml, **virsh_dargs) + check_dumpxml(vm_name, device_types, bus_type, True, test) + for input_dev in device_list: + test.log.info("STEP: Hotunplug device:%s", input_dev) + virsh.detach_device(vm_name, input_dev.xml, + wait_for_event=True, event_timeout=10, + **virsh_dargs) + check_dumpxml(vm_name, device_types, bus_type, False, test) + finally: + if vm.is_alive(): + virsh.destroy(vm_name) + vm_xml_backup.sync() From 8280aadff81060141a827652f031a385c749ed3e Mon Sep 17 00:00:00 2001 From: nanli Date: Tue, 30 Jan 2024 16:32:26 +0800 Subject: [PATCH 0165/1055] fix not found threshold value Need hard wait after creating snaps Need to catch inappropriate error Signed-off-by: nanli --- .../domblkthreshold_with_backingchain_element.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libvirt/tests/src/backingchain/virsh_domblk/domblkthreshold_with_backingchain_element.py b/libvirt/tests/src/backingchain/virsh_domblk/domblkthreshold_with_backingchain_element.py index cce2f6acb2e..733ea35675e 100644 --- a/libvirt/tests/src/backingchain/virsh_domblk/domblkthreshold_with_backingchain_element.py +++ b/libvirt/tests/src/backingchain/virsh_domblk/domblkthreshold_with_backingchain_element.py @@ -1,7 +1,9 @@ import re +import time from virttest import utils_disk from virttest import virsh +from virttest import utils_misc from virttest.libvirt_xml import vm_xml from provider.backingchain import blockcommand_base @@ -45,6 +47,7 @@ def test_entire_disk(): Do domblkthreshold for the entire disk device target """ test.log.info("TEST_STEP1:Set domblkthreshold for the entire disk") + time.sleep(5) virsh.domblkthreshold(vm_name, '%s' % target_disk, domblk_threshold, debug=True, ignore_status=False) @@ -77,6 +80,12 @@ def check_domstats_threshold(options, threshold_value=None): :param threshold_value: domstats threshold value, if it is None, result should be no output """ + if not utils_misc.wait_for( + lambda: + bool(threshold_value) == ('threshold' in virsh.domstats( + vm_name, options, debug=True).stdout_text.strip()), 30, 2): + test.fail('Failed to get expected threshold value in 30s') + result = virsh.domstats(vm_name, options, debug=True, ignore_status=False).stdout_text.strip() if not threshold_value: From a58af02d3640e6b40ac5fc82b15b97085bd92a33 Mon Sep 17 00:00:00 2001 From: dzhengfy Date: Mon, 5 Feb 2024 12:53:08 +0800 Subject: [PATCH 0166/1055] Revert "Rename main name in v2v jobs" --- v2v/tests/cfg/convert_vm_to_libvirt.cfg | 6 ++++-- v2v/tests/cfg/convert_vm_to_ovirt.cfg | 6 ++++-- v2v/tests/cfg/function_test_xen.cfg | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/v2v/tests/cfg/convert_vm_to_libvirt.cfg b/v2v/tests/cfg/convert_vm_to_libvirt.cfg index 268a3f1682c..a274d745736 100644 --- a/v2v/tests/cfg/convert_vm_to_libvirt.cfg +++ b/v2v/tests/cfg/convert_vm_to_libvirt.cfg @@ -163,7 +163,8 @@ vir_mode = "hvm" variants: - vm: - main_vm = ${hypervisor}-${vir_mode}-${os_version}-${vm_arch} + # main_vm = ${hypervisor}-${vir_mode}-${os_version}-${vm_arch} + main_vm = "XEN_VM_NAME_V2V_EXAMPLE" - esx: only source_esx vpx_pwd = ${vpx_password} @@ -189,4 +190,5 @@ hostname = ${esx_hostname} variants: - vm: - main_vm = ${esx_version}-${os_version}-${vm_arch}${vm_boot} + # main_vm = ${esx_version}-${os_version}-${vm_arch}${vm_boot} + main_vm = "ESX_VM_NAME_V2V_EXAMPLE" diff --git a/v2v/tests/cfg/convert_vm_to_ovirt.cfg b/v2v/tests/cfg/convert_vm_to_ovirt.cfg index 90db46add77..6292337d521 100644 --- a/v2v/tests/cfg/convert_vm_to_ovirt.cfg +++ b/v2v/tests/cfg/convert_vm_to_ovirt.cfg @@ -195,7 +195,8 @@ vir_mode = "hvm" variants: - vm: - main_vm = ${hypervisor}-${vir_mode}-${os_version}-${vm_arch} + # main_vm = ${hypervisor}-${vir_mode}-${os_version}-${vm_arch} + main_vm = "XEN_VM_NAME_V2V_EXAMPLE" - esx: only source_esx vpx_pwd = ${vpx_password} @@ -221,4 +222,5 @@ hostname = ${vpx_hostname} variants: - vm: - main_vm = ${esx_version}-${os_version}-${vm_arch}${vm_boot} + # main_vm = ${esx_version}-${os_version}-${vm_arch}${vm_boot} + main_vm = "ESX_VM_NAME_V2V_EXAMPLE" diff --git a/v2v/tests/cfg/function_test_xen.cfg b/v2v/tests/cfg/function_test_xen.cfg index 1d6b9c253cd..037281c3472 100644 --- a/v2v/tests/cfg/function_test_xen.cfg +++ b/v2v/tests/cfg/function_test_xen.cfg @@ -14,7 +14,7 @@ # Guest info os_type = 'linux' - main_vm = ${hypervisor}-${vir_mode}-${os_version}-${vm_arch} + main_vm = 'XEN_VM_NAME_V2V_EXAMPLE' username = 'root' password = GENERAL_GUEST_PASSWORD os_version = 'XEN_VM_OS_VERSION_V2V_EXAMPLE' From 10f595eb3e8a12fe22cf4ca5db7317a7dafab15e Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 5 Feb 2024 00:35:35 -0500 Subject: [PATCH 0167/1055] Check the cpu topology from virsh capabilities is the subset of result from system Signed-off-by: liang-cong-red-hat --- libvirt/tests/src/numa/host_numa/host_numa_info.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/numa/host_numa/host_numa_info.py b/libvirt/tests/src/numa/host_numa/host_numa_info.py index df063ab7d26..6a4914f4739 100644 --- a/libvirt/tests/src/numa/host_numa/host_numa_info.py +++ b/libvirt/tests/src/numa/host_numa/host_numa_info.py @@ -318,9 +318,9 @@ def verify_node_cpus_under_cell(test_obj, cpu_list, node_id): one_numa_node = NumaNode(int(node_id) + 1) for one_cpu_dict in cpu_list: cpu_info_in_sys = one_numa_node.get_cpu_topology(one_cpu_dict['id']) - if one_cpu_dict != cpu_info_in_sys: + if not set(one_cpu_dict.items()).issubset(cpu_info_in_sys.items()): test_obj.test.fail("Expect cpu '%s' in node '%s' " - "to be '%s', but found " + "to be included in '%s', but found " "'%s'" % (one_cpu_dict['id'], node_id, cpu_info_in_sys, From 6fe0976bea912eb8315ce7937cb4511c26c9b418 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 26 Jan 2024 15:30:24 +0800 Subject: [PATCH 0168/1055] vIOMMU: Add a vm lifecycle test This PR adds: VIRT-294807 - [vIOMMU] Lifecycle test for vm with iommu device Signed-off-by: Yingshun Cui --- .../sriov/vIOMMU/iommu_device_lifecycle.cfg | 41 ++++++++++ .../sriov/vIOMMU/iommu_device_lifecycle.py | 82 +++++++++++++++++++ provider/save/save_base.py | 26 ++++-- 3 files changed, 141 insertions(+), 8 deletions(-) create mode 100644 libvirt/tests/cfg/sriov/vIOMMU/iommu_device_lifecycle.cfg create mode 100644 libvirt/tests/src/sriov/vIOMMU/iommu_device_lifecycle.py diff --git a/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_lifecycle.cfg b/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_lifecycle.cfg new file mode 100644 index 00000000000..1941ef66deb --- /dev/null +++ b/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_lifecycle.cfg @@ -0,0 +1,41 @@ +- vIOMMU.iommu_device_lifecycle: + type = iommu_device_lifecycle + start_vm = "no" + disk_driver = {'name': 'qemu', 'type': 'qcow2', 'iommu': 'on'} + variants: + - virtio: + only q35, aarch64 + func_supported_since_libvirt_ver = (8, 3, 0) + iommu_dict = {'model': 'virtio'} + - intel: + only q35 + start_vm = "yes" + enable_guest_iommu = "yes" + iommu_dict = {'model': 'intel', 'driver': {'intremap': 'on', 'caching_mode': 'on', 'eim': 'on', 'iotlb': 'on', 'aw_bits': '48'}} + - smmuv3: + only aarch64 + func_supported_since_libvirt_ver = (5, 5, 0) + iommu_dict = {'model': 'smmuv3'} + variants: + - e1000e: + only q35 + iface_model = 'e1000e' + iface_dict = {'type_name': 'network', 'model': '${iface_model}', 'source': {'network': 'default'}} + - virtio_muti_devices: + disk_dict = {'target': {'dev': 'vda', 'bus': 'virtio'}, 'device': 'disk', 'driver': ${disk_driver}} + video_dict = {'primary': 'yes', 'model_heads': '1', 'model_type': 'virtio', 'driver': {'iommu': 'on'}} + test_devices = ["Eth", "block", "gpu"] + variants: + - vhost_on: + interface_driver_name = "vhost" + interface_driver = {'driver_attr': {'name': '${interface_driver_name}', 'iommu': 'on'}} + iface_dict = {'type_name': 'network', 'model': 'virtio', 'driver': ${interface_driver}, 'source': {'network': 'default'}} + - hostdev_iface: + only virtio + no save_restore + iface_dict = {'managed': 'yes', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}} + variants test_scenario: + - save_restore: + - suspend_resume: + - reboot_many_times: + loop_time = 5 diff --git a/libvirt/tests/src/sriov/vIOMMU/iommu_device_lifecycle.py b/libvirt/tests/src/sriov/vIOMMU/iommu_device_lifecycle.py new file mode 100644 index 00000000000..0e88aaa8826 --- /dev/null +++ b/libvirt/tests/src/sriov/vIOMMU/iommu_device_lifecycle.py @@ -0,0 +1,82 @@ +import os + +from virttest import libvirt_version +from virttest import utils_misc +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml + +from provider.save import save_base +from provider.sriov import sriov_base +from provider.sriov import check_points + +VIRSH_ARGS = {'debug': True, 'ignore_status': False} + + +def run(test, params, env): + """ + Test lifecycle for vm with vIOMMU enabled with different devices. + """ + libvirt_version.is_libvirt_feature_supported(params) + cleanup_ifaces = "yes" == params.get("cleanup_ifaces", "yes") + ping_dest = params.get('ping_dest', "127.0.0.1") + iommu_dict = eval(params.get('iommu_dict', '{}')) + test_scenario = params.get("test_scenario") + + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + + rand_id = utils_misc.generate_random_string(3) + save_path = f'/var/tmp/{vm_name}_{rand_id}.save' + test_obj = sriov_base.SRIOVTest(vm, test, params) + try: + test.log.info("TEST_SETUP: Update VM XML.") + test_obj.setup_iommu_test(iommu_dict=iommu_dict, + cleanup_ifaces=cleanup_ifaces) + test_obj.prepare_controller() + for dev in ["disk", "video"]: + dev_dict = eval(params.get('%s_dict' % dev, '{}')) + if dev == "disk": + dev_dict = test_obj.update_disk_addr(dev_dict) + libvirt_vmxml.modify_vm_device( + vm_xml.VMXML.new_from_dumpxml(vm.name), dev, dev_dict) + iface_dict = test_obj.parse_iface_dict() + if cleanup_ifaces: + libvirt_vmxml.modify_vm_device( + vm_xml.VMXML.new_from_dumpxml(vm.name), + "interface", iface_dict) + + test.log.info("TEST_STEP: Start the VM.") + vm.start() + test.log.debug(vm_xml.VMXML.new_from_dumpxml(vm.name)) + if test_scenario == "reboot_many_times": + vm.cleanup_serial_console() + vm.create_serial_console() + for _ in range(int(params.get('loop_time', '5'))): + test.log.info("TEST_STEP: Reboot the VM.") + session = vm.wait_for_serial_login( + timeout=int(params.get('login_timeout'))) + session.sendline(params.get("reboot_command")) + _match, _text = session.read_until_last_line_matches( + [r"[Ll]ogin:\s*$"], timeout=240, internal_timeout=0.5) + session.close() + + session = vm.wait_for_serial_login( + timeout=int(params.get('login_timeout'))) + check_points.check_vm_network_accessed(session, ping_dest=ping_dest) + else: + pid_ping, upsince = save_base.pre_save_setup(vm, serial=True) + if test_scenario == "save_restore": + test.log.info("TEST_STEP: Save and restore the VM.") + virsh.save(vm.name, save_path, **VIRSH_ARGS) + virsh.restore(save_path, **VIRSH_ARGS) + elif test_scenario == "suspend_resume": + test.log.info("TEST_STEP: Suspend and resume the VM.") + virsh.suspend(vm.name, **VIRSH_ARGS) + virsh.resume(vm.name, **VIRSH_ARGS) + save_base.post_save_check(vm, pid_ping, upsince, serial=True) + finally: + test_obj.teardown_iommu_test() + if os.path.exists(save_path): + os.remove(save_path) diff --git a/provider/save/save_base.py b/provider/save/save_base.py index 802d580ac1f..92c73291146 100644 --- a/provider/save/save_base.py +++ b/provider/save/save_base.py @@ -8,29 +8,33 @@ VIRSH_ARGS = {'debug': True, 'ignore_status': False} -def pre_save_setup(vm): +def pre_save_setup(vm, serial=False): """ Setup vm before save: Start ping process and get uptime since when on vm :param vm: vm instance + :param serial: Whether to use a serial connection :return: a tuple of pid of ping and uptime since when """ - session = vm.wait_for_login() + if serial: + vm.cleanup_serial_console() + vm.create_serial_console() + session = vm.wait_for_serial_login() + else: + session = vm.wait_for_login() upsince = session.cmd_output('uptime --since').strip() LOG.debug(f'VM has been up since {upsince}') - ping_cmd = 'ping 127.0.0.1' + ping_cmd = 'ping 127.0.0.1 >/tmp/ping_out 2>&1' # This session shouldn't be closed or it will kill ping session.sendline(ping_cmd + '&') - check_session = vm.wait_for_login() - pid_ping = check_session.cmd_output('pidof ping').strip().split()[-1] - check_session.close() + pid_ping = session.cmd_output('pidof ping').strip().split()[-1] LOG.debug(f'Pid of ping: {pid_ping}') return pid_ping, upsince -def post_save_check(vm, pid_ping, upsince): +def post_save_check(vm, pid_ping, upsince, serial=False): """ Check vm status after save-restore: Whether ping is still running, uptime since when is the same as before @@ -39,8 +43,14 @@ def post_save_check(vm, pid_ping, upsince): :param vm: vm instance :param pid_ping: pid of ping :param upsince: uptime since when + :param serial: Whether to use a serial connection """ - session = vm.wait_for_login() + if serial: + vm.cleanup_serial_console() + vm.create_serial_console() + session = vm.wait_for_serial_login() + else: + session = vm.wait_for_login() upsince_restore = session.cmd_output('uptime --since').strip() LOG.debug(f'VM has been up (after restore) since {upsince_restore}') LOG.debug(session.cmd_output(f'pidof ping')) From c54992a84caf4acc7357ac45afbd5438154c2f53 Mon Sep 17 00:00:00 2001 From: nanli Date: Fri, 19 Jan 2024 13:05:21 +0800 Subject: [PATCH 0169/1055] add case for destroying storage pool with running vm and then restart libvirtd xxxx-196149: Destroy storage pool with running vm and then restart libvirtd - autostarted network based storage Signed-off-by: nanli --- .../cfg/storage/virsh_pool_autostart.cfg | 7 +++- .../tests/src/storage/virsh_pool_autostart.py | 37 +++++++++++++++++-- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/cfg/storage/virsh_pool_autostart.cfg b/libvirt/tests/cfg/storage/virsh_pool_autostart.cfg index 3e39f26482f..05b40489260 100644 --- a/libvirt/tests/cfg/storage/virsh_pool_autostart.cfg +++ b/libvirt/tests/cfg/storage/virsh_pool_autostart.cfg @@ -1,7 +1,5 @@ - virsh.pool_autostart: type = virsh_pool_autostart - vms = '' - main_vm = '' pool_name = "virsh_pool_test" pool_type = "dir" start_vm = "no" @@ -74,6 +72,11 @@ ip_protocal = "ipv4" - ipv6_target: ip_protocal = "ipv6" + - destroy_pool_used_by_guest: + destroy_pool_used_by_guest = "yes" + new_dev = 'sdc' + source_attr = "'source':{'attrs': {'pool': '%s', 'volume':'%s'}}" + disk_dict = {"type_name":"volume",'device':'disk',${source_attr},"target":{"dev": "${new_dev}", "bus": "virtio"}, "driver": {"name": "qemu", "type":"raw"}} - pool_type_scsi: pool_type = "scsi" pool_target = "/dev/disk/by-path" diff --git a/libvirt/tests/src/storage/virsh_pool_autostart.py b/libvirt/tests/src/storage/virsh_pool_autostart.py index 3076a4b8874..c267347e80c 100755 --- a/libvirt/tests/src/storage/virsh_pool_autostart.py +++ b/libvirt/tests/src/storage/virsh_pool_autostart.py @@ -1,15 +1,18 @@ import os +import re import logging as log from avocado.utils import process from avocado.core import exceptions -from virttest import utils_libvirtd from virttest import libvirt_storage - +from virttest import utils_libvirtd from virttest import virsh -from virttest.utils_test import libvirt as utlv from virttest.libvirt_xml import pool_xml +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt as utlv +from virttest.utils_libvirt import libvirt_disk from virttest.staging import lv_utils from virttest import libvirt_version @@ -52,6 +55,12 @@ def run(test, params, env): lv_name = params.get("lv_name", "") update_policy = params.get("update_policy") libvirt_version.is_libvirt_feature_supported(params) + destroy_pool_used_by_guest = params.get("destroy_pool_used_by_guest") + disk_dict = params.get("disk_dict") + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() # Readonly mode ro_flag = False @@ -148,6 +157,17 @@ def change_source_path(new_path, update_policy="set"): # Get pool uuid: if pool_ref == "uuid" and not pool_uuid: pool = pool_ins.get_pool_uuid(pool_name) + if destroy_pool_used_by_guest: + virsh.pool_start(pool_name, debug=True, ignore_status=False) + res = virsh.vol_list(pool_name, debug=True, + ignore_status=False).stdout_text + vol = re.findall(r"(\S+)\ +(\S+)", str(res.strip()))[1][0] + + libvirt_vmxml.modify_vm_device( + vmxml, 'disk', eval(disk_dict % (pool_name, vol)), index=1) + virsh.start(vm_name) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + test.log.debug("Get guest xml is:\n%s", vmxml) # Setup logical block device # Change pool source path @@ -202,6 +222,15 @@ def change_source_path(new_path, update_policy="set"): if not result.exit_status: check_pool(pool_name, pool_type, checkpoint='Autostart', expect_value="yes", expect_error=status_error) + if destroy_pool_used_by_guest: + session = vm.wait_for_login() + disk_name, _ = libvirt_disk.get_non_root_disk_name(session) + test.log.debug("Get new disk name is:%s", disk_name) + session.close() + + virsh.pool_destroy(pool_name, debug=True, ignore_status=False) + utils_libvirtd.Libvirtd().restart() + libvirt_disk.check_virtual_disk_io(vm, disk_name) # Step(3) # Restart libvirtd and check pool status @@ -240,6 +269,8 @@ def change_source_path(new_path, update_policy="set"): # Clean up logging.debug("Try to clean up env") try: + if destroy_pool_used_by_guest: + bkxml.sync() if clean_mount is True: for src in source_list: process.system("umount %s" % pool_target) From 08163245f259109e677952995dd31ea4b51599e3 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Wed, 24 Jan 2024 00:21:21 -0500 Subject: [PATCH 0170/1055] Fix folder exist issue on save_to_nfs In some extreme case, folder:nfs_mount_dir may already exist before mkdir() Signed-off-by: chunfuwen --- libvirt/tests/src/save_and_restore/save_to_nfs.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/save_and_restore/save_to_nfs.py b/libvirt/tests/src/save_and_restore/save_to_nfs.py index cfcdbb6f617..b457310512a 100644 --- a/libvirt/tests/src/save_and_restore/save_to_nfs.py +++ b/libvirt/tests/src/save_and_restore/save_to_nfs.py @@ -68,7 +68,8 @@ def run(test, params, env): os.chmod(save_path, mod) LOG.debug('Make nfs mount dir and mount nfs storage') - os.mkdir(nfs_mount_dir) + if not os.path.exists(nfs_mount_dir): + os.mkdir(nfs_mount_dir) utils_disk.mount('127.0.0.1:' + nfs['export_dir'], nfs_mount_dir, 'nfs', options='rw') From 9ae516998790a005eca4f6f92b2a8b49e4f395ae Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Tue, 23 Jan 2024 23:48:51 -0500 Subject: [PATCH 0171/1055] Filter CCW address cases on q35 can not use CCW address type for device on q35 Signed-off-by: chunfuwen --- libvirt/tests/cfg/virtual_disks/virtual_disks_ccw_addr.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_ccw_addr.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_ccw_addr.cfg index a885def8c6d..d35d0cfef2d 100755 --- a/libvirt/tests/cfg/virtual_disks/virtual_disks_ccw_addr.cfg +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_ccw_addr.cfg @@ -3,7 +3,7 @@ take_regular_screendumps = "no" start_vm = "no" target_bus = "virtio" - no s390-virtio + only s390-virtio variants: - start_vm: variants: From 86f757ead1b7b8e5d09edf2d97207d88c17b47b2 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Sun, 19 Nov 2023 20:50:38 -0500 Subject: [PATCH 0172/1055] Add network case of update-device:coalesce - VIRT-294752 - [update-device][coalesce] Live update coalesce settings for network and bridge type interface Signed-off-by: Haijiao Zhao --- .../update_device/update_device_coalesce.cfg | 35 ++++++ .../update_device/unsupported_live_update.py | 4 +- .../update_device/update_device_coalesce.py | 108 ++++++++++++++++++ provider/virtual_network/network_base.py | 39 ++++++- 4 files changed, 179 insertions(+), 7 deletions(-) create mode 100644 libvirt/tests/cfg/virtual_network/update_device/update_device_coalesce.cfg create mode 100644 libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_device_coalesce.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_device_coalesce.cfg new file mode 100644 index 00000000000..15c053c1371 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/update_device/update_device_coalesce.cfg @@ -0,0 +1,35 @@ +- virtual_network.update_device.coalesce: + type = update_device_coalesce + host_iface = + start_vm = no + timeout = 240 + outside_ip = 'www.redhat.com' + extra_attrs = {} + vm_ping_outside = pass + variants: + - delete_iface_coalesce: + rx_frames = 32 + coalesce = {'coalesce': {'max': '${rx_frames}'}} + - add_iface_coalesce: + coalesce = {} + updated_rx_frames = 64 + updated_coalesce = {'coalesce': {'max': '${updated_rx_frames}'}} + - update_iface_coalesce: + rx_frames = 64 + coalesce = {'coalesce': {'max': '${rx_frames}'}} + updated_rx_frames = 32 + updated_coalesce = {'coalesce': {'max': '${updated_rx_frames}'}} + variants: + - nat_net: + iface_type = network + iface_source = {'source': {'network': 'default'}} + - linux_br: + iface_type = bridge + br_type = linux_br + iface_source = {'source': {'bridge': br_name}} + - ovs_br: + iface_type = bridge + br_type = ovs_br + iface_source = {'source': {'bridge': br_name}} + extra_attrs = {'virtualport': {'type': 'openvswitch'}} + iface_attrs = {'type_name': '${iface_type}', **${coalesce}, **${iface_source}, 'model': 'virtio', 'mac_address': mac, **${extra_attrs}} diff --git a/libvirt/tests/src/virtual_network/update_device/unsupported_live_update.py b/libvirt/tests/src/virtual_network/update_device/unsupported_live_update.py index a997ea957c8..e981f635ae4 100644 --- a/libvirt/tests/src/virtual_network/update_device/unsupported_live_update.py +++ b/libvirt/tests/src/virtual_network/update_device/unsupported_live_update.py @@ -48,7 +48,7 @@ def run(test, params, env): vm.start() vm.wait_for_serial_login().close() - iface = network_base.get_iface_xml_inst(vmxml, 'on VM') + iface = network_base.get_iface_xml_inst(vm_name, 'on VM') iface_original = iface.copy() if del_attr: if del_attr == 'boot': @@ -64,7 +64,7 @@ def run(test, params, env): if err_msg: libvirt.check_result(up_result, err_msg) - iface_update = network_base.get_iface_xml_inst(vmxml, + iface_update = network_base.get_iface_xml_inst(vm_name, 'after update-device') if iface_update != iface_original: test.fail(f'Interface xml changed after unsuccessful update.\n' diff --git a/libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py b/libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py new file mode 100644 index 00000000000..bd87def340c --- /dev/null +++ b/libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py @@ -0,0 +1,108 @@ +import logging + +from avocado.utils import process +from virttest import utils_misc +from virttest import utils_net +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def check_coalesce_rx_frames(tap_device, rx_frames, test): + """ + Check whether coalesce rx-frames meets expectation + + :param tap_device: tap device to be checked + :param rx_frames: expected rx-frames + :param test: test instance + """ + coal_params = network_base.get_ethtool_coalesce(tap_device) + LOG.debug(f'coalesce parameters from ethtool: {coal_params}') + coal_rx_frames = coal_params.get('rx-frames') + if coal_rx_frames != rx_frames: + test.fail(f'rx-frames of {tap_device} should be {rx_frames}, ' + f'not {coal_rx_frames}') + + +def run(test, params, env): + """ + Test update-device command to update coalesce of interface + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + rand_id = utils_misc.generate_random_string(3) + br_type = params.get('br_type', '') + br_name = br_type + '_' + rand_id + mac = utils_net.generate_mac_address_simple() + iface_attrs = eval(params.get('iface_attrs', '{}')) + host_iface = params.get('host_iface') + host_iface = host_iface if host_iface else utils_net.get_net_if( + state='UP')[0] + rx_frames = params.get('rx_frames', '0') + updated_rx_frames = params.get('updated_rx_frames', '0') + updated_coalesce = eval(params.get('updated_coalesce', '{}')) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + LOG.info('Create bridge for test.') + if br_type == 'linux_br': + utils_net.create_linux_bridge_tmux(br_name, host_iface) + process.run(f'ip l show type bridge {br_name}', shell=True) + elif br_type == 'ovs_br': + utils_net.create_ovs_bridge(br_name) + + LOG.info('Setup interface on vm.') + vmxml.del_device('interface', by_tag=True) + libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs) + LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + vm.start() + session = vm.wait_for_serial_login() + + LOG.info('Check the rx-frames value for the tap device on the host.') + iflist = libvirt.get_interface_details(vm_name) + tap_device = iflist[0]['interface'] + check_coalesce_rx_frames(tap_device, rx_frames, test) + + LOG.info('Prepare interface xml to be updated with.') + iface = network_base.get_iface_xml_inst(vm_name, 'on VM') + if not updated_coalesce: + iface.del_coalesce() + else: + iface.setup_attrs(**updated_coalesce) + + virsh.update_device(vm_name, iface.xml, **VIRSH_ARGS) + + LOG.info('Check the live xml is updated.') + iface_update = network_base.get_iface_xml_inst( + vm_name, 'after update-device') + expect_coalesce = updated_coalesce.get('coalesce') + network_base.check_iface_attrs(iface_update, 'coalesce', + expect_coalesce) + + LOG.info('Check the rx-frames value for the tap device on the host.') + check_coalesce_rx_frames(tap_device, updated_rx_frames, test) + + LOG.info('Login vm to check whether the network works well via ping.') + ips = {'outside_ip': params.get('outside_ip')} + network_base.ping_check(params, ips, session, force_ipv4=True) + + finally: + if 'session' in locals(): + session.close() + bkxml.sync() + if br_type == 'linux_br': + LOG.debug(f'Delete linux bridge: {br_name}') + utils_net.delete_linux_bridge_tmux(br_name, host_iface) + if br_type == 'ovs_br': + LOG.debug(f'Delete ovs bridge: {br_name}') + utils_net.delete_ovs_bridge(br_name) diff --git a/provider/virtual_network/network_base.py b/provider/virtual_network/network_base.py index d86d38cd486..a2f856855c3 100644 --- a/provider/virtual_network/network_base.py +++ b/provider/virtual_network/network_base.py @@ -2,15 +2,13 @@ import shutil import aexpect - from avocado.core import exceptions from avocado.utils import process - from virttest import remote from virttest import utils_net from virttest import virsh - from virttest.libvirt_xml import network_xml +from virttest.libvirt_xml import vm_xml VIRSH_ARGS = {'ignore_status': False, 'debug': True} @@ -266,15 +264,46 @@ def set_static_ip(iface, ip, netmask, session): session.cmd(f'ifconfig {iface} {ip}/{netmask}') -def get_iface_xml_inst(vmxml, comment, index=0): +def get_iface_xml_inst(vm_name, comment, index=0): """ Get iface xml instance with given vm and index - :param vmxml: xml instance of vm + :param vm_name: name of vm :param comment: comment to log :param index: index of interface on vm, defaults to 0 :return: xml instance of interface """ + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) iface = vmxml.get_devices('interface')[index] LOG.debug(f'Interface xml ({comment}):\n{iface}') return iface + + +def get_ethtool_coalesce(iface): + """ + Get coalesce parameters from ethtool command output + + :param iface: interface name + :return: dict-type coalesce parameters + """ + eth_out = process.run(f'ethtool -c {iface}').stdout_text + items = [x.split(':') for x in eth_out.replace('\t', '').splitlines() if x] + coalesce = {item[0]: item[1] for item in items[1:] if len(item) == 2} + + return coalesce + + +def check_iface_attrs(iface, key, expect_val): + """ + Check whether interface attribute value meets expectation + + :param iface: interface name + :param key: interface attribute key + :param expect_val: expect attribute value + """ + actual_val = iface.fetch_attrs().get(key) + LOG.debug(f'Expect {key}: {expect_val}\n' + f'Actual {key}: {actual_val}') + if actual_val != expect_val: + raise exceptions.TestFail(f'Updated {key} of iface should be ' + f'{expect_val}, NOT {actual_val}') From 20e0766d694c04017ae041bc136bf67d1e04a59c Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 6 Feb 2024 07:41:53 -0500 Subject: [PATCH 0173/1055] at_dt_interface: fix test on hosts with vlan On a host with VLAN the parent device is in operstate UP and was selected for the test making it fail because the VLAN interface should be used. Require interface to have an IP for selection. Signed-off-by: Sebastian Mitterle --- .../src/virsh_cmd/domain/virsh_attach_detach_interface.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_attach_detach_interface.py b/libvirt/tests/src/virsh_cmd/domain/virsh_attach_detach_interface.py index 7d9eb530092..c0169c48ea0 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_attach_detach_interface.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_attach_detach_interface.py @@ -283,7 +283,13 @@ def run(test, params, env): # Get iface name if iface_type is direct if iface_type == "direct": - iface_source = utils_net.get_net_if(state="UP")[0] + links = utils_net.get_net_if(state="UP") + for link in links: + if utils_net.get_net_if_addrs(link)["ipv4"]: + iface_source = link + break + if not iface_source: + test.error("Couldn't find host interface with IP") # Get a bridge name for test if iface_type is bridge. # If there is no bridge other than virbr0, try to create one # or fail test From b6f14a8e954f89c04df3e2013e431f458a01de93 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 6 Feb 2024 08:59:48 -0500 Subject: [PATCH 0174/1055] emulatorpin: enable test case always The test case is valuable even if the number of host cpus is not a multiple of 8 which is a special subcase of issue reported in https://bugzilla.redhat.com/show_bug.cgi?id=1227180 Instead of skipping if this is not a case run it still. We'll have an internal test doc to document the behavior in case of multiple of 8. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/virsh_cmd/domain/virsh_emulatorpin.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_emulatorpin.py b/libvirt/tests/src/virsh_cmd/domain/virsh_emulatorpin.py index dadb85a6ad2..ecd49025fa9 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_emulatorpin.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_emulatorpin.py @@ -254,9 +254,6 @@ def run(test, params, env): check_cpus_allowed_list = "yes" == params.get("check_cpus_allowed_list", "") host_cpus_num = cpu.online_count() - if all_cpuset and int(host_cpus_num) % 8 != 0: - test.cancel("Host cpu number is expected to be multiple of 8, " - "but found %s" % host_cpus_num) # Backup original vm vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) vmxml_backup = vmxml.copy() From c43238479eb186185ed8d133e1e6c0b2c00ae6ea Mon Sep 17 00:00:00 2001 From: Meina Li Date: Wed, 7 Feb 2024 00:12:59 -0500 Subject: [PATCH 0175/1055] Storage: fix different results after restarting service for logical pool The logical pool will be active from libvirt-9.9.0 after restarting service. But before it the result is also expected. So all these test results need to be keeped. This PR mainly fix it here. Signed-off-by: Meina Li --- libvirt/tests/src/storage/virsh_pool.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/storage/virsh_pool.py b/libvirt/tests/src/storage/virsh_pool.py index b8c3fd8d4e1..8278aad5ac5 100644 --- a/libvirt/tests/src/storage/virsh_pool.py +++ b/libvirt/tests/src/storage/virsh_pool.py @@ -422,8 +422,9 @@ def check_pool_info(pool_info, check_point, value): # pool as active. This is independent of autostart. # So a directory based storage pool is thus pretty much always active, # and so as the SCSI pool. - if pool_type not in ['dir', 'scsi', 'logical']: - if pool_type == 'disk' and libvirt_version.version_compare(8, 1, 0): + if pool_type not in ['dir', 'scsi']: + if (pool_type == 'disk' and libvirt_version.version_compare(8, 1, 0)) or \ + (pool_type == 'logical' and libvirt_version.version_compare(9, 9, 0)): utlv.check_exit_status(result) else: result = virsh.pool_start(pool_name, ignore_status=True) From e6f0db9570a4c4c717e2ba1e7e3eccb63166d1e2 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Wed, 7 Feb 2024 14:14:13 +0800 Subject: [PATCH 0176/1055] controller_functional: add alias case - Add alias for some pcie related controllers and check in qemu command line. - Enable some cases on arm Signed-off-by: Dan Zheng --- .../cfg/controller/controller_functional.cfg | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/libvirt/tests/cfg/controller/controller_functional.cfg b/libvirt/tests/cfg/controller/controller_functional.cfg index c785f01a7fb..232632d5dd3 100644 --- a/libvirt/tests/cfg/controller/controller_functional.cfg +++ b/libvirt/tests/cfg/controller/controller_functional.cfg @@ -12,7 +12,7 @@ controller_type = pci variants: - pci_bridge_auto_add: - only i440fx + only i440fx remove_address = "no" variants: - no_pci_controller: @@ -36,7 +36,7 @@ controller_model = pci-root controller_pcihole64 = 1024 - pcie_root: - only q35 + only q35, aarch64 controller_type = pci controller_model = pcie-root - second_level_bridge: @@ -50,19 +50,33 @@ controller_type = virtio-serial controller_bus = ccw - controller_alias: - only i440fx - add_contrl_list = "[{'model': 'pci-root', 'index': '0', 'alias': 'ua-PCI_ROOT'},{'model': 'pci-bridge', 'alias': 'ua-PCI_BRIDGE'}, {'model': 'pci-expander-bus', 'alias': 'ua-PCI_EXPANDER_BUS'}]" - qemu_patterns = "[('-device', 'pci-bridge.*,.*,.*id.*ua-PCI_BRIDGE'), ('-device', 'pxb.*,.*,.*id.*ua-PCI_EXPANDER_BUS')]" + no s390-virtio, pseries + pcie_root_config = {'model': 'pcie-root', 'index': '0', 'alias': 'ua-ROOT'} + pcie_root_port_config = {'model': 'pcie-root-port', 'alias': 'ua-ROOT_PORT'} + pcie_root_port2_config = {'model': 'pcie-root-port', 'alias': 'ua-ROOT_PORT2'} + pcie_to_pci_bridge_config = {'model': 'pcie-to-pci-bridge', 'alias': 'ua-ROOT_PCIE_PCI'} + pci_bridge_config = {'model': 'pci-bridge', 'alias': 'ua-PCI_BRIDGE'} + pcie_switch_upstream_port = {'model': 'pcie-switch-upstream-port', 'alias': 'ua-UPSTREAM_PORT'} + pcie_switch_downstream_port = {'model': 'pcie-switch-downstream-port', 'alias': 'ua-DOWNSTREAM_PORT'} + pci_expander_bus_config = {'model': 'pcie-expander-bus', 'alias': 'ua-PCIE_EXPANDER_BUS'} + add_contrl_list = "[${pcie_root_config},${pcie_root_port_config}, ${pcie_root_port2_config}, ${pcie_to_pci_bridge_config}, ${pci_bridge_config}, ${pcie_switch_upstream_port}, ${pcie_switch_downstream_port}, ${pci_expander_bus_config}]" + pattern1 = "('-device', 'pcie-root-port.*,.*,.*id.*ua-ROOT_PORT'), ('-device', 'pcie-root-port.*,.*,.*id.*ua-ROOT_PORT2')" + pattern2 = "('-device', 'pcie-pci-bridge.*,.*id.*ua-ROOT_PCIE_PCI'), ('-device', 'pci-bridge.*,.*,.*id.*ua-PCI_BRIDGE')" + pattern3 = "('-device', 'upstream.*,.*id.*ua-UPSTREAM_PORT'),('-device', 'downstream.*,.*id.*ua-DOWNSTREAM_PORT')" + qemu_patterns = "[${pattern1},${pattern2},${pattern3},('-device', 'pxb-pcie.*,.*,.*id.*ua-PCIE_EXPANDER_BUS')]" + i440fx: + add_contrl_list = "[{'model': 'pci-root', 'index': '0', 'alias': 'ua-PCI_ROOT'},{'model': 'pci-bridge', 'alias': 'ua-PCI_BRIDGE'}, {'model': 'pci-expander-bus', 'alias': 'ua-PCI_EXPANDER_BUS'}]" + qemu_patterns = "[('-device', 'pci-bridge.*,.*,.*id.*ua-PCI_BRIDGE'), ('-device', 'pxb.*,.*,.*id.*ua-PCI_EXPANDER_BUS')]" check_contr_addr = "no" check_within_guest = "no" - pcie_root_port_model: - only q35 + only q35, aarch64 run_vm = "yes" check_contr_addr = "no" remove_contr = "no" new_model = pcie-root-port old_model = ioh3420 - auto_index = "yes" + auto_index= "yes" attach_option = "--address pci:0000.%s.00.0" qemu_patterns = "[('-device', 'pcie-root-port.*,.*id.*pci.%s.*,.*bus.*pcie.0.*,.*addr.*0x2')]" guest_patterns = "['00:.* PCI bridge: Red Hat']" @@ -168,7 +182,7 @@ controller_type = virtio-serial controller_vectors = '1' - virtio_serial_0_vectors: - no q35 + no q35, aarch64 controller_type = virtio-serial controller_vectors = '0' - usb_controller: @@ -177,10 +191,10 @@ variants: # ehci and ich9-ehci1 are USB2.0 controller model - ehci_model: - no pseries + no pseries, aarch64 controller_model = ehci - ich9_ehci1_model: - no pseries + no pseries, aarch64 controller_model = ich9-ehci1 companion_controller_model = ich9-uhci companion_controller_num = 3 @@ -188,7 +202,7 @@ controller_index = 0 # nec-xhci and qemu-xhci are USB3.0 controller model - nec_xhci_model: - no pseries + no pseries, aarch64 controller_model = nec-xhci - qemu_xhci_model: variants: @@ -217,7 +231,7 @@ only i440fx controller_model = pci-root - pcie_root: - only q35 + only q35, aarch64 controller_model = pcie-root - negative: controller_index = -1 @@ -226,7 +240,7 @@ - pci_bridge: controller_model = pci-bridge - pcie_root: - only q35 + only q35, aarch64 controller_model = pcie-root - zero: controller_index = 0 @@ -300,7 +314,7 @@ controller_model = 'pcie-root' err_msg = "The PCI controller.*index='0' must be model='pci-root'" - pci_root_model: - only q35 + only q35, aarch64 controller_model = 'pci-root' err_msg = "The PCI controller.*index='0' must be model='pcie-root'" - other_model: From 83cba348b55d62f80e87f1f8ea59d393ce9b2de8 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Thu, 8 Feb 2024 12:43:33 +0800 Subject: [PATCH 0177/1055] v2v:fix func TC "unset virtio-win" Signed-off-by: vwu-vera --- v2v/tests/cfg/function_test_esx.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 34a68e4b580..44aa8ada03e 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -173,7 +173,7 @@ variants: - unset: checkpoint += 'unset' - missing = 'Red Hat VirtIO SCSI,Red Hat VirtIO Ethernet Adapte' + missing = 'Red Hat VirtIO SCSI,Red Hat VirtIO Ethernet Adapte,VirtIO RNG,VirtIO Serial,VirtIO Balloon' only dest_libvirt - custom: checkpoint += 'custom' From 7b47a599750436ec3b05139fd4d193c8ea9e9376 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Thu, 8 Feb 2024 12:18:02 -0500 Subject: [PATCH 0178/1055] attach_detach_disk: fix disk discovery The code compared old and new listing of impersistent disk names, e.g. 'vdX'. Those names can change between reboots. Instead, use function to identify new disks that don't mount the root file system. The function raises an error if there is no such disk, so handle that to confirm that disks are detached correctly. Signed-off-by: Sebastian Mitterle --- .../domain/virsh_attach_detach_disk.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_attach_detach_disk.py b/libvirt/tests/src/virsh_cmd/domain/virsh_attach_detach_disk.py index 82b16fc11fa..52df542f751 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_attach_detach_disk.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_attach_detach_disk.py @@ -5,6 +5,7 @@ import aexpect from avocado.utils import process +from avocado.core import exceptions from virttest import virt_vm from virttest import virsh @@ -15,7 +16,7 @@ from virttest.staging.service import Factory from virttest.staging import lv_utils from virttest.utils_libvirt import libvirt_pcicontr -from virttest import utils_disk +from virttest.utils_libvirt import libvirt_disk from virttest import utils_misc from virttest import data_dir from virttest import libvirt_version @@ -49,7 +50,7 @@ def check_info_in_audit_log_file(test_cmd, device_source): % device_source) return process.run(cmd, ignore_status=True, shell=True).exit_status == 0 - def check_vm_partition(vm, device, os_type, target_name, old_parts): + def check_vm_partition(vm, device, os_type, target_name): """ Check VM disk's partition. @@ -65,8 +66,12 @@ def check_vm_partition(vm, device, os_type, target_name, old_parts): attached = False if os_type == "linux": session = vm.wait_for_login() - new_parts = utils_disk.get_parts_list(session) - added_parts = list(set(new_parts).difference(set(old_parts))) + added_parts = [] + try: + added_disks = libvirt_disk.get_non_root_disk_names(session) + added_parts = [x[0] for x in added_disks] + except exceptions.TestError as e: + logging.debug(e) logging.debug("Added parts: %s" % added_parts) for i in range(len(added_parts)): if device == "disk": @@ -225,9 +230,6 @@ def _check_disk(target): # Start vm and get all partitions in vm. if vm.is_dead(): vm.start() - session = vm.wait_for_login() - old_parts = utils_disk.get_parts_list(session) - session.close() vm.destroy(gracefully=False) # Back up xml file. @@ -464,7 +466,7 @@ def _check_disk(target): # Check in VM after command. check_vm_after_cmd = True check_vm_after_cmd = check_vm_partition(vm, device, os_type, - device_target, old_parts) + device_target) # Check disk type after attach. check_disk_type = True From a061752edb5e44f36169b171df25218291bddbd2 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 7 Feb 2024 17:44:36 +0800 Subject: [PATCH 0179/1055] virtual_network: Add igb model test This PR adds igb model test scenario. Signed-off-by: Yingshun Cui --- .../virtual_network/elements_and_attributes/element_model.cfg | 4 ++++ .../virtual_network/elements_and_attributes/element_model.py | 3 +++ 2 files changed, 7 insertions(+) diff --git a/libvirt/tests/cfg/virtual_network/elements_and_attributes/element_model.cfg b/libvirt/tests/cfg/virtual_network/elements_and_attributes/element_model.cfg index a19086bc3b9..5b720226c24 100644 --- a/libvirt/tests/cfg/virtual_network/elements_and_attributes/element_model.cfg +++ b/libvirt/tests/cfg/virtual_network/elements_and_attributes/element_model.cfg @@ -23,6 +23,10 @@ - e1000e: iface_driver = e1000e pci_model = pcie-root-port + - igb: + func_supported_since_libvirt_ver = (9, 3, 0) + iface_driver = igb + pci_model = pcie-root-port - rtl8139: iface_driver = 8139cp pci_model = pcie-to-pci-bridge diff --git a/libvirt/tests/src/virtual_network/elements_and_attributes/element_model.py b/libvirt/tests/src/virtual_network/elements_and_attributes/element_model.py index 1cfb3f4e6a0..c1fc2214246 100644 --- a/libvirt/tests/src/virtual_network/elements_and_attributes/element_model.py +++ b/libvirt/tests/src/virtual_network/elements_and_attributes/element_model.py @@ -1,5 +1,6 @@ import logging +from virttest import libvirt_version from virttest import virsh from virttest.libvirt_xml import vm_xml from virttest.utils_libvirt import libvirt_vmxml @@ -41,6 +42,8 @@ def run(test, params, env): """ Test 'model' element of interface """ + libvirt_version.is_libvirt_feature_supported(params) + vm_name = params.get('main_vm') vm = env.get_vm(vm_name) outside_ip = params.get('outside_ip') From 5ec880278ca1b934b2ff093433110b224ce3dbe5 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 8 Feb 2024 21:17:34 -0500 Subject: [PATCH 0180/1055] Add new case of update-device of iface qos:invalid value - VIRT-294768 - [update-device][qos] Live update the QoS setting by update-device with invalid values Signed-off-by: Haijiao Zhao --- .../update_iface_qos_invalid.cfg | 19 ++++++++ .../update_device/update_iface_qos_invalid.py | 47 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/update_device/update_iface_qos_invalid.cfg create mode 100644 libvirt/tests/src/virtual_network/update_device/update_iface_qos_invalid.py diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_iface_qos_invalid.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_iface_qos_invalid.cfg new file mode 100644 index 00000000000..323a872fbb4 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/update_device/update_iface_qos_invalid.cfg @@ -0,0 +1,19 @@ +- virtual_network.update_device.iface_qos.invalid: + type = update_iface_qos_invalid + start_vm = no + timeout = 240 + status_error = yes + iface_attrs = {'source': {'network': 'default'}, 'type_name': 'network', 'model': 'virtio'} + variants: + - neg_value: + update_attrs = {'bandwidth': {'inbound': {'average': '-1', 'peak': '5000', 'burst': '1024'}}} + err_msg = could not convert bandwidth average value|Expected non-negative integer value + - big_value: + update_attrs = {'bandwidth': {'inbound': {'average': '10000000000000000', 'peak': '5000', 'burst': '1024'}}} + err_msg = could not convert bandwidth average value|Expected non-negative integer value + - no_mandatory_average: + update_attrs = {'bandwidth': {'outbound': {'peak': '5000', 'burst': '1024'}}} + err_msg = Missing mandatory average or floor attributes + - floor_without_bandwidth: + update_attrs = {'bandwidth': {'outbound': {'average': '128', 'peak': '256', 'burst': '256'},'inbound': {'average': '1000', 'peak': '5000', 'floor': '200', 'burst': '1024'}}} + err_msg = Invalid use of 'floor' on interface with MAC address .* - network .* has no inbound QoS set diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_qos_invalid.py b/libvirt/tests/src/virtual_network/update_device/update_iface_qos_invalid.py new file mode 100644 index 00000000000..d13ef8eb2be --- /dev/null +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_qos_invalid.py @@ -0,0 +1,47 @@ +import logging + +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test live update interface bandwidth setting by update-device or domiftune + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + status_error = 'yes' == params.get('status_error', 'no') + err_msg = params.get('err_msg') + iface_attrs = eval(params.get('iface_attrs', '{}')) + update_attrs = eval(params.get('update_attrs', '{}')) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + vmxml.del_device('interface', by_tag=True) + libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs) + LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + vm.start() + vm.wait_for_serial_login().close() + + iface = network_base.get_iface_xml_inst(vm_name, 'on vm') + LOG.debug(f'Update iface with attrs: {update_attrs}') + iface.setup_attrs(**update_attrs) + + LOG.debug(f'Update iface with xml:\n{iface}') + up_result = virsh.update_device(vm_name, iface.xml, debug=True) + libvirt.check_exit_status(up_result, status_error) + if err_msg: + libvirt.check_result(up_result, err_msg) + finally: + bkxml.sync() From 752f31b6892971d74ad202d599dd20ecf85d1b96 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 7 Feb 2024 16:21:29 +0800 Subject: [PATCH 0181/1055] guest_agent: Add a case of session mode This PR adds: VIRT-300125: Start a guest without specified source path for guest agent Signed-off-by: Yingshun Cui --- ...enerated_unix_source_path_session_mode.cfg | 7 ++ ...generated_unix_source_path_session_mode.py | 111 ++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 libvirt/tests/cfg/guest_agent/unix_source_path/agent_auto_generated_unix_source_path_session_mode.cfg create mode 100644 libvirt/tests/src/guest_agent/unix_source_path/agent_auto_generated_unix_source_path_session_mode.py diff --git a/libvirt/tests/cfg/guest_agent/unix_source_path/agent_auto_generated_unix_source_path_session_mode.cfg b/libvirt/tests/cfg/guest_agent/unix_source_path/agent_auto_generated_unix_source_path_session_mode.cfg new file mode 100644 index 00000000000..7ee3887733d --- /dev/null +++ b/libvirt/tests/cfg/guest_agent/unix_source_path/agent_auto_generated_unix_source_path_session_mode.cfg @@ -0,0 +1,7 @@ +- agent.auto_generated.unix_source_path.session_mode: + type = agent_auto_generated_unix_source_path_session_mode + start_vm = "no" + test_user = USER.EXAMPLE + test_passwd = PASSWORD.EXAMPLE + unpr_vm_name = UNPRIVILEGED_VM.EXAMPLE + func_supported_since_libvirt_ver = (9, 9, 0) diff --git a/libvirt/tests/src/guest_agent/unix_source_path/agent_auto_generated_unix_source_path_session_mode.py b/libvirt/tests/src/guest_agent/unix_source_path/agent_auto_generated_unix_source_path_session_mode.py new file mode 100644 index 00000000000..6296f485158 --- /dev/null +++ b/libvirt/tests/src/guest_agent/unix_source_path/agent_auto_generated_unix_source_path_session_mode.py @@ -0,0 +1,111 @@ +import pwd +import os + +from virttest import libvirt_version +from virttest import remote +from virttest import utils_misc +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_unprivileged + + +def run(test, params, env): + """ + This case is to verify that if the source path of guest agent is not + specified in session mode, it will be set automatically by libvirt, + and the path matches certain pattern. + """ + def check_src_path(domid, vm_name, dir_name, chn_dir, tgt_name, + max_dir_length, cmp_path=None): + """Check the source path + + :param domid: domain id + :param vm_name: vm name + :param dir_name: directory name + :param chn_dir: libvirt dir for channel + :param tgt_name: target name + :param max_dir_length: max directory length + :param cmp_path: the path to compare, defaults to None + """ + vm_info = f"{domid}-{vm_name}" + tmp_path = os.path.join(dir_name, chn_dir, vm_info, tgt_name) + if cmp_path and tmp_path != cmp_path: + test.fail(f"The channel device's source path should be {tmp_path} " + f"but got {cmp_path}") + if len(tmp_path) > max_dir_length: + test.fail(f"The length of source path '{tmp_path}' should not " + f"exceed {max_dir_length}.") + + libvirt_version.is_libvirt_feature_supported(params) + + chn_dir = params.get("chn_dir", "libvirt/qemu/run/channel") + kube_dir = params.get("kube_dir", "/var/run/kubevirt-private") + max_dir_length = int(params.get("max_dir_length", "107")) + new_vm_name = 'vm' + utils_misc.generate_random_string(22) + test_passwd = params.get('test_passwd', '') + test_user = params.get('test_user', '') + tgt_name = params.get("tgt_name", "org.qemu.guest_agent.0") + up_domid = params.get("up_domid", "2147483647") + vm_name = params.get('unpr_vm_name') + + runtime_dir = remote.RemoteRunner( + username=test_user, password=test_passwd, host='localhost').run( + 'echo $XDG_RUNTIME_DIR').stdout_text.strip() + if not runtime_dir: + runtime_dir = os.path.join(pwd.getpwnam(test_user).pw_dir, '.cache') + + unpr_vm_args = {'username': params.get('username'), + 'password': params.get('password')} + vm = libvirt_unprivileged.get_unprivileged_vm(vm_name, test_user, + test_passwd, + **unpr_vm_args) + virsh_ins = virsh.VirshPersistent(uri=vm.connect_uri) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( + vm_name, virsh_instance=virsh_ins) + backup_xml = vmxml.copy() + try: + test.log.info("TEST_STEP: Create a vm in session mode.") + if vm.is_alive(): + vm.destroy() + virsh_ins.domrename( + vm.name, new_vm_name, debug=True, ignore_status=False) + vm_new = libvirt_unprivileged.get_unprivileged_vm( + new_vm_name, test_user, test_passwd, **unpr_vm_args) + + test.log.info("TEST_STEP: Prepare guest agent.") + vm_new.prepare_guest_agent(serial=True) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( + new_vm_name, virsh_instance=virsh_ins) + test.log.debug(f"vmxml after updating: {vmxml}") + inactive_src = vmxml.devices.by_device_tag( + "channel")[0].fetch_attrs().get('sources') + if inactive_src and inactive_src[0]['attrs'].get('path'): + test.fail( + "There should be no specified path in inactive domain xml.") + + test.log.info("TEST_STEP: Execute a guest agent command.") + virsh_ins.domtime(new_vm_name, debug=True, ignore_status=False) + + test.log.info("TEST_STEP: Execute a guest agent command.") + vmxml = vm_xml.VMXML.new_from_dumpxml( + new_vm_name, virsh_instance=virsh_ins) + + test.log.info("TEST_STEP: Check the guest agent socket path.") + chn_obj = vmxml.devices.by_device_tag("channel")[0] + test.log.debug(f"channel xml: {chn_obj}") + src_path = chn_obj.fetch_attrs()['sources'][0]['attrs']['path'] + check_src_path(virsh_ins.domid(new_vm_name).stdout_text.strip(), + vm_new.name[:20], runtime_dir, chn_dir, tgt_name, + max_dir_length, cmp_path=src_path) + + test.log.info("TEST_STEP: Check the length of the socket path " + "which will be used in cnv.") + check_src_path(up_domid, vm_new.name[:20], kube_dir, chn_dir, tgt_name, + max_dir_length) + + finally: + vm_new.destroy() + virsh_ins.domrename(vm_new.name, vm.name, debug=True) + backup_xml.sync(virsh_instance=virsh_ins) + virsh_ins.close_session() From a7e780304d59d952ff0ed531b890fe6810093d88 Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 25 Dec 2023 10:56:45 +0800 Subject: [PATCH 0182/1055] migration: Add case about disks-uri XXX-297892 - VM live migration with copy storage - network data transport - TCP - --disks-uri Signed-off-by: lcheng --- .../network_data_transport/tcp_disks_uri.cfg | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_disks_uri.cfg diff --git a/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_disks_uri.cfg b/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_disks_uri.cfg new file mode 100644 index 00000000000..bbcc6770d2d --- /dev/null +++ b/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_disks_uri.cfg @@ -0,0 +1,102 @@ +- migration_with_copy_storage.network_data_transport.tcp_disks_uri: + type = tcp + migration_setup = 'yes' + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + status_error = "no" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + port_to_check = "49160" + setup_nfs = "no" + nfs_mount_dir = + setup_local_nfs = "no" + storage_type = "" + start_vm = "yes" + ipv6_addr_des = "ENTER.YOUR.IPv6.TRAGET" + variants: + - p2p: + virsh_migrate_options = '--live --p2p --verbose' + - non_p2p: + virsh_migrate_options = '--live --verbose' + variants: + - copy_storage_all: + copy_storage_option = "--copy-storage-all" + - copy_storage_inc: + copy_storage_option = "--copy-storage-inc" + variants: + - tcp: + variants: + - ipv4_addr_and_port: + variants: + - with_migrateuri_and_listen_addr: + virsh_migrate_extra = "--migrateuri tcp://${migrate_dest_host} --listen-address 0.0.0.0 --disks-uri tcp://${migrate_dest_host}:${port_to_check}" + check_patterns = [r'ESTAB .*${migrate_dest_host}:${port_to_check}', r'LISTEN .*0.0.0.0:49152', r'LISTEN .*${migrate_dest_host}:${port_to_check}'] + - without_migrateuri_and_listen_addr: + virsh_migrate_extra = "--disks-uri tcp://${migrate_dest_host}:${port_to_check}" + check_patterns = [r'ESTAB .*${migrate_dest_host}:${port_to_check}', r'LISTEN .*${migrate_dest_host}:${port_to_check}'] + action_during_mig = '[{"func": "libvirt_network.check_sockets_statistics", "func_param": {"server_ip": "${server_ip}", "server_user": "${server_user}", "server_pwd": "${server_pwd}", "check_patterns": "${check_patterns}"}, "need_sleep_time": "5"}]' + - ipv6_addr_and_port: + variants: + - with_migrateuri_and_listen_addr: + virsh_migrate_extra = "--disks-uri tcp://[${ipv6_addr_des}]:${port_to_check} --migrateuri tcp://${migrate_dest_host} --listen-address 0.0.0.0" + check_patterns = [r'ESTAB .*${migrate_dest_host}:49152', r'ESTAB .*\[${ipv6_addr_des}\]:${port_to_check}', r'LISTEN .*0.0.0.0:49152', r'LISTEN .*\[${ipv6_addr_des}\]:${port_to_check}'] + - without_migrateuri_and_listen_addr: + virsh_migrate_extra = "--disks-uri tcp://[${ipv6_addr_des}]:${port_to_check}" + check_patterns = [r'ESTAB .*\[${ipv6_addr_des}\]:${port_to_check}', r'LISTEN .*\[${ipv6_addr_des}\]:${port_to_check}'] + action_during_mig = '[{"func": "libvirt_network.check_sockets_statistics", "after_event": "block-job", "func_param": {"server_ip": "${server_ip}", "server_user": "${server_user}", "server_pwd": "${server_pwd}", "check_patterns": "${check_patterns}"}, "wait_for_after_event_timeout": "600"}]' + - hostname_and_port: + dest_host = "ENTER.YOUR.EXAMPLE.SERVER_CN" + variants: + - with_migrateuri_and_listen_addr: + virsh_migrate_extra = "--disks-uri tcp://${dest_host}:${port_to_check} --migrateuri tcp://${migrate_dest_host} --listen-address 0.0.0.0" + check_patterns = [r'ESTAB .*${migrate_dest_host}:${port_to_check}', r'LISTEN .*0.0.0.0:49152', r'LISTEN .*${migrate_dest_host}:${port_to_check}'] + - without_migrateuri_and_listen_addr: + virsh_migrate_extra = "--disks-uri tcp://${dest_host}:${port_to_check}" + check_patterns = [r'ESTAB .*${migrate_dest_host}:${port_to_check}', r'LISTEN .*${migrate_dest_host}:${port_to_check}'] + - ipv4_addr: + variants: + - with_migrateuri_and_listen_addr: + virsh_migrate_extra = "--disks-uri tcp://${migrate_dest_host} --migrateuri tcp://${migrate_dest_host} --listen-address 0.0.0.0" + check_patterns = [r'ESTAB .*${migrate_dest_host}', r'LISTEN .*0.0.0.0:49152', r'LISTEN .*${migrate_dest_host}'] + - without_migrateuri_and_listen_addr: + virsh_migrate_extra = "--disks-uri tcp://${migrate_dest_host}" + check_patterns = [r'ESTAB .*${migrate_dest_host}', r'LISTEN .*${migrate_dest_host}'] + - ipv6_addr: + variants: + - with_migrateuri_and_listen_addr: + virsh_migrate_extra = "--disks-uri tcp://[${ipv6_addr_des}] --migrateuri tcp://${migrate_dest_host} --listen-address 0.0.0.0" + check_patterns = [r'ESTAB .*${migrate_dest_host}', r'ESTAB .*\[${ipv6_addr_des}\]', r'LISTEN .*0.0.0.0:49152', r'LISTEN .*\[${ipv6_addr_des}\]'] + - without_migrateuri_and_listen_addr: + virsh_migrate_extra = "--disks-uri tcp://[${ipv6_addr_des}]" + check_patterns = [r'ESTAB .*${migrate_dest_host}', r'ESTAB .*\[${ipv6_addr_des}\]', r'LISTEN .*\[${ipv6_addr_des}\]'] + action_during_mig = '[{"func": "libvirt_network.check_sockets_statistics", "after_event": "block-job", "func_param": {"server_ip": "${server_ip}", "server_user": "${server_user}", "server_pwd": "${server_pwd}", "check_patterns": "${check_patterns}"}, "wait_for_after_event_timeout": "600"}]' + - invalid_disks_uri: + status_error = "yes" + variants: + - invalid_ip_addr: + virsh_migrate_extra = "--disks-uri tcp://10.10.10.10" + err_msg = "Failed to bind socket: Cannot assign requested address" + - invalid_hostname: + virsh_migrate_extra = "--disks-uri tcp://aaaaa" + err_msg = "address resolution failed for .*: Name or service not known" + - with_disks_uri_and_disks_port: + status_error = "yes" + virsh_migrate_extra = "--disks-uri tcp://${migrate_dest_host} --disks-port 49888" + err_msg = "invalid argument: Both port and URI requested for disk migration while being mutually exclusive" From db416570292c0f02c41d14297f9a32df8d725e73 Mon Sep 17 00:00:00 2001 From: nanli Date: Mon, 19 Feb 2024 10:43:52 +0800 Subject: [PATCH 0183/1055] fix storage case inappropriate message Signed-off-by: nanli --- libvirt/tests/src/storage/virsh_pool_autostart.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/storage/virsh_pool_autostart.py b/libvirt/tests/src/storage/virsh_pool_autostart.py index c267347e80c..c484616bc9a 100755 --- a/libvirt/tests/src/storage/virsh_pool_autostart.py +++ b/libvirt/tests/src/storage/virsh_pool_autostart.py @@ -161,10 +161,12 @@ def change_source_path(new_path, update_policy="set"): virsh.pool_start(pool_name, debug=True, ignore_status=False) res = virsh.vol_list(pool_name, debug=True, ignore_status=False).stdout_text - vol = re.findall(r"(\S+)\ +(\S+)", str(res.strip()))[1][0] + vol = re.findall(r"(\S+)\ +(\S+)", str(res.strip()))[1] + if not vol: + test.fail('Expect to get vol in %s pool' % pool_name) libvirt_vmxml.modify_vm_device( - vmxml, 'disk', eval(disk_dict % (pool_name, vol)), index=1) + vmxml, 'disk', eval(disk_dict % (pool_name, vol[0])), index=1) virsh.start(vm_name) vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) test.log.debug("Get guest xml is:\n%s", vmxml) From 8bec82b5cedcab06e75915dcd7fcbb5765bdd79d Mon Sep 17 00:00:00 2001 From: Hu Shuai Date: Sun, 18 Feb 2024 16:19:45 +0800 Subject: [PATCH 0184/1055] virtual_networks: Update error message to match more distros The error messages for the negative tests are different on xxxx-8 and xxxx-9: On xxxx-8: XML error: Invalid value for attribute 'order' in element 'boot': '-1'. Expected integer value On xxxx-9: XML error: Invalid value for attribute 'order' in element 'boot': '-1'. Expected non-negative integer value Signed-off-by: Hu Shuai --- .../attach_detach_device/attach_iface_with_boot_order.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/attach_detach_device/attach_iface_with_boot_order.cfg b/libvirt/tests/cfg/virtual_network/attach_detach_device/attach_iface_with_boot_order.cfg index 5d052bf46e7..7b4be22f57e 100644 --- a/libvirt/tests/cfg/virtual_network/attach_detach_device/attach_iface_with_boot_order.cfg +++ b/libvirt/tests/cfg/virtual_network/attach_detach_device/attach_iface_with_boot_order.cfg @@ -14,8 +14,8 @@ err_msg = unsupported configuration: boot order ${boot_order} is already used by another device - neg_value: boot_order = -1 - err_msg = Expected non-negative integer value + err_msg = Expected non-negative integer value|Expected integer value - str_value: boot_order = ss - err_msg = Expected non-negative integer value + err_msg = Expected non-negative integer value|Expected integer value iface_attrs = {'source': {'network': 'default'}, 'model': 'virtio', 'type_name': 'network', 'boot': '${boot_order}'} From 1879af80ee6e47318aba5676036e45c979ab2867 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 20 Nov 2023 06:18:57 -0500 Subject: [PATCH 0185/1055] memory/gmap: add test for shadow memory counters KVM records shadow memory events for a nested guest. Confirm the counters go up. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/memory/gmap.cfg | 10 +++ libvirt/tests/src/memory/gmap.py | 139 ++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 libvirt/tests/cfg/memory/gmap.cfg create mode 100644 libvirt/tests/src/memory/gmap.py diff --git a/libvirt/tests/cfg/memory/gmap.cfg b/libvirt/tests/cfg/memory/gmap.cfg new file mode 100644 index 00000000000..f587821d2a7 --- /dev/null +++ b/libvirt/tests/cfg/memory/gmap.cfg @@ -0,0 +1,10 @@ +- gmap: + type = gmap + start_vm = no + only s390-virtio + kvm_module_parameters = 'nested=1' + variants: + - l3_shadow_table_counters: + l2_mem = 3906250 + target_tag = "mount_tag0" + fs_dict = {'accessmode': 'passthrough', 'source': {'dir': 'replace_in_code'}, "target": {'dir': '${target_tag}'}, 'binary': {'lock_posix':'off','flock':'off'}, 'driver': {'type': 'virtiofs'}} diff --git a/libvirt/tests/src/memory/gmap.py b/libvirt/tests/src/memory/gmap.py new file mode 100644 index 00000000000..e6d1551a455 --- /dev/null +++ b/libvirt/tests/src/memory/gmap.py @@ -0,0 +1,139 @@ +import logging as log +import os +from pathlib import Path + +from avocado.core.exceptions import TestError +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_misc import cmd_status_output + + +logging = log.getLogger('avocado.' + __name__) +cleanup_actions = [] + + +def parent(file_path): + """ + Returns the parent directory of a file path + + :param file_path: absolute file path + :return path: absolute path of parent directory + """ + return Path(file_path).parent.absolute() + + +def get_source_disk_path(vmxml): + """ + Returns the absolute path to a disk image for import. + Assume the boot image is the first disk and an image file. + + :param vmxml: VMXML instance + :return: absolute path to the guest's first disk image file + """ + disks = vmxml.get_disk_all() + disk_list = list(disks.values()) + first_disk = disk_list[0] + return first_disk.find('source').get('file') + + +def update_l2_vm(vmxml, l2_mem, fs_dict): + """ + Update the L2 VM to run L3 inside from virtiofs + + :param vmxml: The VMXML instance + :param l2_mem: The new memory size + :param fs_dict: The filesystem device attributes + """ + vmxml.memory = l2_mem + mb = vm_xml.VMMemBackingXML() + mb.access_mode = "shared" + vmxml.mb = mb + vmxml.sync() + fs = libvirt_vmxml.create_vm_device_by_type("filesystem", fs_dict) + source = fs["source"] + source.update({'dir': parent(get_source_disk_path(vmxml))}) + fs["source"] = source + virsh.attach_device(vmxml.vm_name, fs.xml, flagstr="--config", debug=True) + + +def prepare_l3(vmxml): + """ + Prepares the disk for the L3 guest + + :param vmxml: The L2 VMXML instance + """ + l2_disk_path = get_source_disk_path(vmxml) + l3_disk_path = os.path.join(parent(l2_disk_path), "test.qcow2") + cmd = ("qemu-img convert -f qcow2 -O qcow2 -o lazy_refcounts=on" + " {} {}".format(l2_disk_path, l3_disk_path)) + cmd_status_output(cmd) + cleanup_actions.append(lambda: os.unlink(l3_disk_path)) + + +def start_l3(session, target_tag): + """ + Mount the shared directory with the image file and start + the L3 guest with the qemu-kvm command + + :param session: VM session + :param target_tag: virtiofs mount tag + """ + mount_dir = "/mnt" + cmd = "mount -t virtiofs {} {}".format(target_tag, mount_dir) + cmd_status_output(cmd, session=session) + cmd = ("/usr/libexec/qemu-kvm -m 1024 -smp 1" + " -daemonize {}".format(os.path.join(mount_dir, "test.qcow2"))) + s, _ = cmd_status_output(cmd, session=session) + if s: + raise TestError("Couldn't start L3 guest.") + + +def l1_counters_go_up(): + """ + Check that the shadow memory counters go up + """ + base_path = "/sys/kernel/debug/kvm/" + for a in [ + "gmap_shadow_reuse", + "gmap_shadow_create", + "gmap_shadow_sg_entry", + "gmap_shadow_pg_entry" + ]: + with open(os.path.join(base_path, a), "r") as f: + if f.read().strip() == "0": + return False + return True + + +def run(test, params, env): + """ + Test kvm counters for L3 shadow memory + L1: LPAR + L2: KVM guest + L3: nested KVM guest + """ + vm_name = params.get('main_vm') + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + cleanup_actions.append(lambda: bkxml.sync()) + vm = env.get_vm(vm_name) + l2_mem = int(params.get("l2_mem", "3906250")) + target_tag = params.get("target_tag") + fs_dict = eval(params.get("fs_dict")) + + try: + update_l2_vm(vmxml, l2_mem, fs_dict) + prepare_l3(vmxml) + logging.debug("VMXML: %s", vm_xml.VMXML.new_from_dumpxml(vm_name)) + vm.start() + cleanup_actions.append(lambda: vm.destroy()) + session = vm.wait_for_login() + cleanup_actions.append(lambda: session.close()) + start_l3(session, target_tag) + if not l1_counters_go_up(): + test.fail("Gmap counters didn't go up.") + finally: + cleanup_actions.reverse() + for action in cleanup_actions: + action() From 2cf964cacd638c6dea731f9a0a0560a1e11ecfa1 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Thu, 14 Dec 2023 09:59:58 -0500 Subject: [PATCH 0186/1055] virsh_dump: add new case when no space left VMs should keep running if dumping them fails because there's no space. Signed-off-by: Sebastian Mitterle --- .../virsh_dump.cfg | 3 +++ .../virsh_dump.py | 22 ++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) rename libvirt/tests/cfg/{virsh_cmd/domain => guest_kernel_debugging}/virsh_dump.cfg (96%) rename libvirt/tests/src/{virsh_cmd/domain => guest_kernel_debugging}/virsh_dump.py (92%) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_dump.cfg b/libvirt/tests/cfg/guest_kernel_debugging/virsh_dump.cfg similarity index 96% rename from libvirt/tests/cfg/virsh_cmd/domain/virsh_dump.cfg rename to libvirt/tests/cfg/guest_kernel_debugging/virsh_dump.cfg index 163e930c580..3131aa58995 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_dump.cfg +++ b/libvirt/tests/cfg/guest_kernel_debugging/virsh_dump.cfg @@ -95,3 +95,6 @@ setup_libvirt_polkit = "yes" unprivileged_user = "EXAMPLE" virsh_uri = "qemu:///system" + - no_space_left: + dump_options = "--memory-only" + dump_dir = "/var/tmp/too_small" diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_dump.py b/libvirt/tests/src/guest_kernel_debugging/virsh_dump.py similarity index 92% rename from libvirt/tests/src/virsh_cmd/domain/virsh_dump.py rename to libvirt/tests/src/guest_kernel_debugging/virsh_dump.py index 1ca2f332175..2870d8aeee3 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_dump.py +++ b/libvirt/tests/src/guest_kernel_debugging/virsh_dump.py @@ -4,15 +4,17 @@ import time import platform import re - from avocado.utils import process from virttest import virsh from virttest import utils_libvirtd from virttest import utils_config from virttest import data_dir +from virttest import utils_misc from virttest import utils_package from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_disk +from virttest.utils_test import libvirt from provider import libvirt_version @@ -36,6 +38,7 @@ def run(test, params, env): 2.1 Dump domain to a non-exist directory. 2.2 Dump domain with invalid option. 2.3 Dump a shut-off domain. + 2.4 Dump onto directory that's too small. """ vm_name = params.get("main_vm", "vm1") @@ -46,6 +49,7 @@ def run(test, params, env): if os.path.dirname(dump_file) is "": dump_file = os.path.join(dump_dir, dump_file) dump_image_format = params.get("dump_image_format") + small_img = os.path.join(data_dir.get_tmp_dir(), "small.img") 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" @@ -132,6 +136,7 @@ def check_domstate(actual, options): Check the domain status according to dump options. """ + logging.debug("Actual VM status is %s", actual) if options.find('live') >= 0: domstate = "running" if options.find('crash') >= 0 or options.find('reset') > 0: @@ -268,6 +273,15 @@ def check_dump_format(dump_image_format, dump_file): args=(dump_file, result_dict)) child_process.start() + # Create too small a directory + if "too_small" in dump_dir: + libvirt_disk.create_disk("file", + small_img, + "100M", + "raw") + libvirt.mkfs(small_img, "ext3") + os.mkdir(dump_dir) + utils_misc.mount(small_img, dump_dir, None) # Run virsh command cmd_result = virsh.dump(vm_name, dump_file, options, unprivileged_user=unprivileged_user, @@ -279,6 +293,7 @@ def check_dump_format(dump_image_format, dump_file): params['bypass'] = result_dict['bypass'] logging.info("Start check result") + time.sleep(5) if not check_domstate(vm.state(), options): test.fail("Domain status check fail.") if status_error: @@ -299,5 +314,10 @@ def check_dump_format(dump_image_format, dump_file): backup_xml.sync() qemu_config.restore() libvirtd.restart() + if os.path.isfile(small_img): + # small_img is a file and will show as /dev/loop0 in /proc/mounts + utils_misc.umount("/dev/loop0", dump_dir, None, verbose=True) + os.rmdir(dump_dir) + os.remove(small_img) if os.path.isfile(dump_file): os.remove(dump_file) From 647f3ae5b6bf44aebe412acd4a7942d2dbe699a1 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 21 Feb 2024 15:56:18 +0800 Subject: [PATCH 0187/1055] vDPA: Add libvirt version check for save/restore Update code to check libvirt version for saving/restore the VM with vDPA Signed-off-by: Yingshun Cui --- .../lifecycle/lifecycle_vdpa_interface.cfg | 1 + .../lifecycle/lifecycle_vdpa_interface.py | 18 +++++++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/lifecycle/lifecycle_vdpa_interface.cfg b/libvirt/tests/cfg/virtual_network/lifecycle/lifecycle_vdpa_interface.cfg index 15ab0814e32..b2031b2ac3f 100644 --- a/libvirt/tests/cfg/virtual_network/lifecycle/lifecycle_vdpa_interface.cfg +++ b/libvirt/tests/cfg/virtual_network/lifecycle/lifecycle_vdpa_interface.cfg @@ -5,6 +5,7 @@ only x86_64 func_supported_since_libvirt_ver = (7, 3, 0) func_supported_since_qemu_kvm_ver = (6, 0, 0) + save_supported_ver = (8, 5, 0) iface_dict = {"source": {'dev':'/dev/vhost-vdpa-0'}} variants test_target: - simulator: diff --git a/libvirt/tests/src/virtual_network/lifecycle/lifecycle_vdpa_interface.py b/libvirt/tests/src/virtual_network/lifecycle/lifecycle_vdpa_interface.py index 9ef792c9b32..18f003c09db 100644 --- a/libvirt/tests/src/virtual_network/lifecycle/lifecycle_vdpa_interface.py +++ b/libvirt/tests/src/virtual_network/lifecycle/lifecycle_vdpa_interface.py @@ -55,13 +55,17 @@ def run_test(dev_type, params, test_obj=None): check_points.check_network_accessibility( vm, test_obj=test_obj, config_vdpa=True, **params) - test.log.info("Save the VM.") - save_path = os.path.join(data_dir.get_tmp_dir(), vm.name + '.save') - virsh.save(vm.name, save_path, **VIRSH_ARGS) - test.log.info("Restore vm.") - virsh.restore(save_path, **VIRSH_ARGS) - check_points.check_network_accessibility( - vm, test_obj=test_obj, config_vdpa=False, **params) + save_supported_ver = { + 'func_supported_since_libvirt_ver': params.get('save_supported_ver', + '(8,5,0)')} + if libvirt_version.is_libvirt_feature_supported(save_supported_ver, True): + test.log.info("Save the VM.") + save_path = os.path.join(data_dir.get_tmp_dir(), vm.name + '.save') + virsh.save(vm.name, save_path, **VIRSH_ARGS) + test.log.info("Restore vm.") + virsh.restore(save_path, **VIRSH_ARGS) + check_points.check_network_accessibility( + vm, test_obj=test_obj, config_vdpa=False, **params) test.log.info("Suspend and resume the vm.") virsh.suspend(vm.name, **VIRSH_ARGS) From 0c1956922f98e1800bd926bed1cbefedd3a67b73 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Wed, 21 Feb 2024 17:26:41 +0800 Subject: [PATCH 0188/1055] libvirt_mem: fix cpu mode on arm Signed-off-by: Dan Zheng --- libvirt/tests/cfg/libvirt_mem.cfg | 4 +++- libvirt/tests/src/libvirt_mem.py | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/libvirt_mem.cfg b/libvirt/tests/cfg/libvirt_mem.cfg index ca55880c45c..cc493e7ef00 100644 --- a/libvirt/tests/cfg/libvirt_mem.cfg +++ b/libvirt/tests/cfg/libvirt_mem.cfg @@ -10,6 +10,9 @@ host_known_unplug_errors = "'Memory unplug already in progress for device'" vcpu = 4 wait_before_save_secs = 0 + cpu_mode = "host-model" + aarch64: + cpu_mode = "host-passthrough" pseries: wait_before_save_secs = 10 variants: @@ -99,7 +102,6 @@ max_mem = "2609152" current_mem = "2609152" numa_cells = "{'id':'0','cpus':'0-1','memory':'1048576','unit':'KiB'} {'id':'1','cpus':'2-3','memory':'1048576','unit':'KiB'}" - cpu_mode = "host-model" model_fallback = "forbid" tg_size = 524288 tg_node = 0 diff --git a/libvirt/tests/src/libvirt_mem.py b/libvirt/tests/src/libvirt_mem.py index 69584fafc90..d3ca93f34bb 100644 --- a/libvirt/tests/src/libvirt_mem.py +++ b/libvirt/tests/src/libvirt_mem.py @@ -359,8 +359,8 @@ def modify_domain_xml(): align_to_value)) cells[cell]["memory"] = memory_value cpu_xml = vm_xml.VMCPUXML() - cpu_xml.xml = "" - cpu_mode = params.get("cpu_mode") + cpu_mode = params.get("cpu_mode", "host-model") + cpu_xml.xml = "" % cpu_mode model_fallback = params.get("model_fallback") if cpu_mode: cpu_xml.mode = cpu_mode From bca829ecbccd4cff5d5d4bc9b9a98cd155ff6c28 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Thu, 15 Feb 2024 09:38:04 -0500 Subject: [PATCH 0189/1055] libvirt_rng: revert commit to avoid timeouts Before commit 40b1324887851acc3abc1c88bc250faea279b032 dd read and wrote 512 bytes at a time (bs default), 100 times. This led to a total size of 51200 bytes = 0.512 KB = 0.000512 MB. The commit set instead 1M = 1MB to be written and read at a time, 10 times. This would result in a total size of 10 MB which seems to be a typo because 10 MB are 10 000 000 bytes and the set rate limit is 2500 bytes per second in the rng_rate test cases; the test would most definitely timeout because 'dd' will need at least 4000 seconds, that is, more than 1 hr, to finish. Because of this commit we now experience timeouts on VM that performed well, so revert it. If there are timeouts with the original command, it is likely because the backends don't create enough entropy. Making sure that rngd is running on the test host should solve this for two major backend scenarios that use /dev/random, that is: a) model='random', /dev/random b) model='egd' type='tcp': the test feeds it from /dev/random, s. code model='builtin' uses a QEMU-internal generator. The rate check tests the upper limit, so if a generator doesn't provide at a higher rate any rate is still valid, so in those cases we should test a lower rate limit. However, on request, to avoid timeouts on low performance systems set count to 10. This will create only 5KB and for the rate_limit cases this would mean with a limit of 2500 B/s ~ 2.4 KB/s 2-3 seconds will be sufficient. On the other hand, as the limiting can result in higher throughput initially, this amount might not be enough on some systems to average out the initial deviation. Therefore, make the throughput configurable in case the rate_limit check fails on specific systems. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/libvirt_rng.cfg | 1 + libvirt/tests/src/libvirt_rng.py | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/libvirt_rng.cfg b/libvirt/tests/cfg/libvirt_rng.cfg index 008268a6c03..593ffa24c29 100644 --- a/libvirt/tests/cfg/libvirt_rng.cfg +++ b/libvirt/tests/cfg/libvirt_rng.cfg @@ -8,6 +8,7 @@ # Devices that might be present though not configured via . # For example, devices that are provided by the CPU. ignored_devices = s390-trng,trng,tpm-rng-0 + dd_throughput = "bs=512 count=10" variants: - hotplug_unplug: only backend_rdm.default, backend_tcp, backend_udp, backend_builtin diff --git a/libvirt/tests/src/libvirt_rng.py b/libvirt/tests/src/libvirt_rng.py index 34267744031..2f4d618eba3 100644 --- a/libvirt/tests/src/libvirt_rng.py +++ b/libvirt/tests/src/libvirt_rng.py @@ -377,8 +377,8 @@ def check_guest(session, expect_fail=False, rng_rate = params.get("rng_rate") # For rng rate test this command and return in a short time # but for other test it will hang - cmd = ("dd if=/dev/hwrng of=rng.test bs=1M count=10" - " && rm -f rng.test") + cmd = ("dd if=/dev/hwrng of=rng.test %s" + " && rm -f rng.test" % dd_throughput) try: ret, output = session.cmd_status_output(cmd, timeout=timeout) if ret and expect_fail: @@ -488,6 +488,7 @@ def rotate_audit_log(): with_packed = "yes" == params.get("with_packed", "no") driver_packed = params.get("driver_packed", "on") urandom = "yes" == params.get("urandom", "no") + dd_throughput = params.get("dd_throughput") if params.get("backend_model") == "builtin" and not libvirt_version.version_compare(6, 2, 0): test.cancel("Builtin backend is not supported on this libvirt version") From d4f33871ca4b19dbb3f52d03e69c6c1f20d869ab Mon Sep 17 00:00:00 2001 From: Hu Shuai Date: Fri, 19 Jan 2024 15:20:20 +0800 Subject: [PATCH 0190/1055] memory: Increase guest memory to 4G The previous guest memory setting was 2G, but the half memory test would fail because 1G was not enough to maintain the normal operation of the guest. Signed-off-by: Hu Shuai --- .../domain => memory}/virsh_setmem.cfg | 1 + .../domain => memory}/virsh_setmem.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) rename libvirt/tests/cfg/{virsh_cmd/domain => memory}/virsh_setmem.cfg (98%) rename libvirt/tests/src/{virsh_cmd/domain => memory}/virsh_setmem.py (96%) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_setmem.cfg b/libvirt/tests/cfg/memory/virsh_setmem.cfg similarity index 98% rename from libvirt/tests/cfg/virsh_cmd/domain/virsh_setmem.cfg rename to libvirt/tests/cfg/memory/virsh_setmem.cfg index 244957e7283..e0ff04b22dc 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_setmem.cfg +++ b/libvirt/tests/cfg/memory/virsh_setmem.cfg @@ -17,6 +17,7 @@ # expected to fail on older libvirt. setmem_old_libvirt_fail = "no" take_regular_screendumps = no + vm_attrs = {'memory': 4, 'memory_unit': 'GiB', 'current_mem': 4, 'current_mem_unit': 'GiB'} variants: - valid_options: # These should not fail diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_setmem.py b/libvirt/tests/src/memory/virsh_setmem.py similarity index 96% rename from libvirt/tests/src/virsh_cmd/domain/virsh_setmem.py rename to libvirt/tests/src/memory/virsh_setmem.py index 0d5140b8e7b..1fafe829a7b 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_setmem.py +++ b/libvirt/tests/src/memory/virsh_setmem.py @@ -10,6 +10,9 @@ from virttest import libvirt_version from virttest.utils_test import libvirt from virttest.libvirt_xml import vm_xml +from virttest.staging import utils_memory + +from provider.memory import memory_base # Using as lower capital is not the best way to do, but this is just a @@ -251,6 +254,21 @@ def print_debug_stats(original_inside_mem, original_outside_mem, vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() + 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') + 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) + if host_free_mem < guest_memory: + test.cancel("There is not enough memory for guest.") + + vmxml.setup_attrs(**vm_attrs) + 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.") From 8518010de19edbc844cf67cb907f5a9f6f630bdd Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Sun, 18 Feb 2024 15:15:56 +0800 Subject: [PATCH 0191/1055] vcpu_misc: adjust some cases on arm - change cpu mode - no vendor information on arm now - maxphysaddr is not supported on arm Signed-off-by: Dan Zheng --- libvirt/tests/cfg/cpu/vcpu_misc.cfg | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/cfg/cpu/vcpu_misc.cfg b/libvirt/tests/cfg/cpu/vcpu_misc.cfg index 3250ea833e3..265dd10fd10 100644 --- a/libvirt/tests/cfg/cpu/vcpu_misc.cfg +++ b/libvirt/tests/cfg/cpu/vcpu_misc.cfg @@ -8,12 +8,15 @@ - snapshot: cpu_mode = "host-model" test_operations = "do_snapshot" - expected_str_before_startup = ${cpu_mode} expected_str_after_startup = 'mode="custom"' + aarch64: + cpu_mode = "host-passthrough" + expected_str_after_startup = ${cpu_mode} pseries: expected_str_after_startup = ${cpu_mode} + expected_str_before_startup = ${cpu_mode} - vendor_id: - no pseries, s390x + no pseries, s390x, aarch64 cpu_mode = "host-model" check_vendor_id = "yes" - with_topology: @@ -32,8 +35,8 @@ expected_str_after_startup = 'mode="host-passthrough"' customize_cpu_features = "yes" - with_maxphysaddr: - no s390-virtio - func_supported_since_libvirt_ver = (9, 3, 0) + no s390-virtio,aarch64 + func_supported_since_libvirt_ver = (9, 3, 0) maxphysaddr = {'mode': 'passthrough', 'limit':'%d'} expected_qemuline = "host-phys-bits-limit=%s" cmd_in_guest = "lscpu|grep Address" From db3d2f48f7443603aae4b7b3f1a5d8ced4a535be Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 30 Jan 2024 11:07:41 -0500 Subject: [PATCH 0192/1055] backingchain/snapshot_blockpull: fix disk disovery The test identified new disks by their target name. However, a reboot can mess up the non-persistent disk namings /dev/vdX. Use instead a function that identifies a new disk inside of a VM as the one disk that has no root mount on itself, its partitions or volumes. Signed-off-by: Sebastian Mitterle --- .../virtual_disks_snapshot_blockpull.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/libvirt/tests/src/backingchain/virtual_disks_snapshot_blockpull.py b/libvirt/tests/src/backingchain/virtual_disks_snapshot_blockpull.py index 842a73a7dd5..14b9087bd82 100644 --- a/libvirt/tests/src/backingchain/virtual_disks_snapshot_blockpull.py +++ b/libvirt/tests/src/backingchain/virtual_disks_snapshot_blockpull.py @@ -9,9 +9,6 @@ from virttest import virt_vm from virttest import virsh -from virttest import utils_disk - - from virttest.utils_test import libvirt from virttest.utils_libvirt import libvirt_disk @@ -335,12 +332,9 @@ def start_middletotop_blkpull_on_vm(): # Initialize one NbdExport object nbd = None - # Start VM and get all partitions in VM. + # Start VM if vm.is_dead(): vm.start() - session = vm.wait_for_login() - old_parts = utils_disk.get_parts_list(session) - session.close() vm.destroy(gracefully=False) # Back up xml file. @@ -359,7 +353,11 @@ def start_middletotop_blkpull_on_vm(): setup_nbd_env(params) try: vm.start() - vm.wait_for_login().close() + session = vm.wait_for_login() + disk_name = device_target + if additional_disk: + disk_name, _ = libvirt_disk.get_non_root_disk_name(session) + session.close() except virt_vm.VMStartError as details: # VM cannot be started if status_error: @@ -368,7 +366,7 @@ def start_middletotop_blkpull_on_vm(): test.fail("VM should start but failed: %s" % str(details)) if fill_in_vm: - libvirt_disk.fill_null_in_vm(vm, device_target) + libvirt_disk.fill_null_in_vm(vm, disk_name) if backend_path in ['native_path']: external_snapshot_disks = libvirt_disk.make_external_disk_snapshots(vm, device_target, "blockpull_snapshot", snapshot_take) From 93f2dbb358b26bd24fa5c010f24185e8842dfdae Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 12 Feb 2024 05:23:19 -0500 Subject: [PATCH 0193/1055] virtual_network/iface_network: fix rule expectation format iptables-libs changes it's output (at least on s390x) for empty fields: ``` MASQUERADE tcp 2001:db8:ca2:6::/64 !2001:db8:ca2:6::/64 masq ports: 1024-65535 MASQUERADE tcp -- 2001:db8:ca2:6::/64 !2001:db8:ca2:6::/64 masq ports: 1024-65535 ``` Update the regular expression to reflect this. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/virtual_network/iface_network.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/src/virtual_network/iface_network.py b/libvirt/tests/src/virtual_network/iface_network.py index 450ed51398e..a6d99917326 100644 --- a/libvirt/tests/src/virtual_network/iface_network.py +++ b/libvirt/tests/src/virtual_network/iface_network.py @@ -446,9 +446,9 @@ def check_ipt_rules(check_ipv4=True, check_ipv6=False): if "mode" in net_forward and net_forward["mode"] == "nat" \ and nat_attrs.get('ipv6') == 'yes': v6_nat_rules = [ - "MASQUERADE\s+tcp\s+{0}\s+!{0}".format(net_ipv6), - "MASQUERADE\s+udp\s+{0}\s+!{0}".format(net_ipv6), - "MASQUERADE\s+all\s+{0}\s+!{0}".format(net_ipv6), + "MASQUERADE.*tcp.*{0}.*!{0}".format(net_ipv6), + "MASQUERADE.*udp.*{0}.*!{0}".format(net_ipv6), + "MASQUERADE.*all.*{0}.*!{0}".format(net_ipv6) ] v6_output = process.run('ip6tables -t nat -L', shell=True).stdout_text for rule in v6_nat_rules: From 4ef276dd1612292f22b26e1ac86cf8ae822ed8a5 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Mon, 26 Feb 2024 14:13:29 +0800 Subject: [PATCH 0194/1055] Fix format error for nbdkit cases Signed-off-by: Ming Xie --- v2v/tests/cfg/nbdkit/nbdkit.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/v2v/tests/cfg/nbdkit/nbdkit.cfg b/v2v/tests/cfg/nbdkit/nbdkit.cfg index cb3eb820af6..0820c502b04 100644 --- a/v2v/tests/cfg/nbdkit/nbdkit.cfg +++ b/v2v/tests/cfg/nbdkit/nbdkit.cfg @@ -154,5 +154,5 @@ - cve_starttls: only source_none..dest_none checkpoint = 'cve_starttls' - rhel9_appsource_repo_url = RHEL9_APP_SOURCE_URL' - version_required = "[nbdkit-server-1.26.5-1,)" \ No newline at end of file + rhel9_appsource_repo_url = 'RHEL9_APP_SOURCE_URL' + version_required = "[nbdkit-server-1.26.5-1,)" From a7354122b010f8c687afbe2ede07c65d44c989fe Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 26 Feb 2024 14:39:08 +0800 Subject: [PATCH 0195/1055] migration: Update error message Signed-off-by: lcheng --- libvirt/tests/cfg/migration/migrate_vm.cfg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/migration/migrate_vm.cfg b/libvirt/tests/cfg/migration/migrate_vm.cfg index d4f713ff4ee..ce8f917522d 100644 --- a/libvirt/tests/cfg/migration/migrate_vm.cfg +++ b/libvirt/tests/cfg/migration/migrate_vm.cfg @@ -749,7 +749,7 @@ variants: - copy_storage_inc: virsh_options = "--live --verbose --copy-storage-inc" - err_msg = "error: Operation not supported: pre-creation of storage targets for incremental storage migration is not supported" + err_msg = "error: Operation not supported: pre-creation of storage targets for incremental storage migration is not supported|error: Operation not supported: pre-creation of storage target .* for incremental storage migration of .* is not supported" - backing_file_with_copy_storage_inc: create_target_image = "no" setup_nfs = "yes" @@ -770,7 +770,7 @@ check_disk_size_cmd = "qemu-img info ${new_disk_source}" local_image_source = "${new_disk_source}" virsh_options = "--live --verbose --copy-storage-inc" - err_msg = "error: Operation not supported: pre-creation of storage targets for incremental storage migration is not supported" + err_msg = "error: Operation not supported: pre-creation of storage targets for incremental storage migration is not supported|error: Operation not supported: pre-creation of storage target .* for incremental storage migration of .* is not supported" - mutually_exclusive_options: create_target_image = "yes" virsh_options = "--live --persistent --verbose --copy-storage-all --copy-storage-inc" @@ -790,7 +790,7 @@ virsh_options = "--live --verbose --persistent --copy-storage-all" - copy_storage_inc: virsh_options = "--live --verbose --persistent --copy-storage-inc" - err_msg = "error: Operation not supported: pre-creation of storage targets for incremental storage migration is not supported" + err_msg = "error: Operation not supported: pre-creation of storage targets for incremental storage migration is not supported|error: Operation not supported: pre-creation of storage target .* for incremental storage migration of .* is not supported" - cache_mode: only without_postcopy nfs_mount_dir = From e8854c022f8b89f98fd0cdd44c84ad98084bcf5b Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Mon, 26 Feb 2024 15:07:07 +0800 Subject: [PATCH 0196/1055] vIOMMU: Limit e1000e and rtl8139 tests to x86 Signed-off-by: Yingshun Cui --- libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg b/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg index 55044b87ed2..7164b4980b3 100644 --- a/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg +++ b/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg @@ -19,11 +19,11 @@ iommu_dict = {'model': 'smmuv3'} variants: - e1000e: - no smmuv3 + only q35 iface_model = 'e1000e' iface_dict = {'type_name': 'network', 'model': '${iface_model}', 'source': {'network': 'default'}} - rtl8139: - no smmuv3 + only q35 iface_model = 'rtl8139' iface_dict = {'type_name': 'network', 'model': '${iface_model}', 'source': {'network': 'default'}} - virtio_muti_devices: From 67cbfa8095603c5b518d5b9bfc9b6b2c31c7b1f7 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 26 Feb 2024 03:48:02 -0500 Subject: [PATCH 0197/1055] Increase current memory to avoid guest boot failure for short of memory Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/libvirt_mem.cfg | 1 + libvirt/tests/cfg/memory/memory_misc.cfg | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/libvirt_mem.cfg b/libvirt/tests/cfg/libvirt_mem.cfg index ca55880c45c..4e6f491bc18 100644 --- a/libvirt/tests/cfg/libvirt_mem.cfg +++ b/libvirt/tests/cfg/libvirt_mem.cfg @@ -185,6 +185,7 @@ max_mem_rt = max_mem = numa_cells = + current_mem = 2048000 attach_option = "--config" - attach_invalid_type: memory_addr = "{'type':'diee','slot':'16','base':'0x11fffffffff'}" diff --git a/libvirt/tests/cfg/memory/memory_misc.cfg b/libvirt/tests/cfg/memory/memory_misc.cfg index d0467a85753..0132038e74c 100644 --- a/libvirt/tests/cfg/memory/memory_misc.cfg +++ b/libvirt/tests/cfg/memory/memory_misc.cfg @@ -152,7 +152,7 @@ vmxml_max_mem_unit = 'KiB' vmxml_max_mem = 1024000 vmxml_current_mem_unit = 'KiB' - vmxml_current_mem = 1024000 + vmxml_current_mem = 2048000 vmxml_vcpu = 4 cpu_attrs = {'mode': 'host-model', 'numa_cell': [{'id': '0', 'cpus': '0,2', 'memory': '${numa_node_size}', 'unit': 'KiB'}, {'id': '1', 'cpus': '1,3', 'memory': '${numa_node_size}', 'unit': 'KiB'}]} aarch64: From 3b54ff1bc0be1439786ba00df027a26b75e73259 Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 26 Feb 2024 10:50:30 +0800 Subject: [PATCH 0198/1055] migration: Fix unix socket number issue QEMU open more connection in postcopy. So update code. Signed-off-by: lcheng --- libvirt/tests/src/migration/migrate_over_unix.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/migration/migrate_over_unix.py b/libvirt/tests/src/migration/migrate_over_unix.py index 69b8d719382..ec7cf55a23f 100644 --- a/libvirt/tests/src/migration/migrate_over_unix.py +++ b/libvirt/tests/src/migration/migrate_over_unix.py @@ -129,7 +129,7 @@ def _check_socket(): global sockets sockets = [x.strip() for x in _res if socket_pattern.match(x)] logging.debug("Found sockets: %s", sockets) - return len(sockets) == int(exp_num) + return len(sockets) >= int(exp_num) found_expected = utils_misc.wait_for(_check_socket, timeout=30) From d3d07494f8a8cf167f04d47cee5301403b9e9e69 Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 27 Feb 2024 14:20:45 +0800 Subject: [PATCH 0199/1055] migration: Update error message Signed-off-by: lcheng --- .../migration_with_copy_storage/precreate_none_target_disk.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration_with_copy_storage/precreate_none_target_disk.cfg b/libvirt/tests/cfg/migration_with_copy_storage/precreate_none_target_disk.cfg index 80e11cab698..db34ae77a04 100644 --- a/libvirt/tests/cfg/migration_with_copy_storage/precreate_none_target_disk.cfg +++ b/libvirt/tests/cfg/migration_with_copy_storage/precreate_none_target_disk.cfg @@ -45,5 +45,5 @@ copy_storage_option = "--copy-storage-all" - copy_storage_inc: status_error = "yes" - err_msg = "Operation not supported: pre-creation of storage targets for incremental storage migration is not supported" + err_msg = "Operation not supported: pre-creation of storage targets for incremental storage migration is not supported|Operation not supported: pre-creation of storage target .* for incremental storage migration of .* is not supported" copy_storage_option = "--copy-storage-inc" From 6ef21fbe1d8624eb5f7f2369c79b064e794a0b40 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Tue, 27 Feb 2024 01:42:07 -0500 Subject: [PATCH 0200/1055] Adapt to default huge page size automatically Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/memory/memory_misc.cfg | 3 +-- libvirt/tests/src/memory/memory_misc.py | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_misc.cfg b/libvirt/tests/cfg/memory/memory_misc.cfg index d0467a85753..e49461745c9 100644 --- a/libvirt/tests/cfg/memory/memory_misc.cfg +++ b/libvirt/tests/cfg/memory/memory_misc.cfg @@ -27,9 +27,8 @@ kvm_module_parameters = "hpage=1" - memfd_backed: mem_backing_attrs = {'hugepages': {}, 'source_type': 'memfd' ,'allocation': {'threads': '${threads_num}'}} - qemu_check = '"qom-type":"memory-backend-memfd".*"hugetlbsize":2097152.*"prealloc-threads":${threads_num}' + qemu_check = '"qom-type":"memory-backend-memfd".*"hugetlbsize":%s.*"prealloc-threads":${threads_num}' s390-virtio: - qemu_check = '"qom-type":"memory-backend-memfd".*"hugetlbsize":1048576.*"prealloc-threads":${threads_num}' kvm_module_parameters = "hpage=1" - ram_backed: mem_backing_attrs = {'allocation': {'mode': 'immediate', 'threads': '${threads_num}'}} diff --git a/libvirt/tests/src/memory/memory_misc.py b/libvirt/tests/src/memory/memory_misc.py index b5c6ed79753..8cee6932f3d 100644 --- a/libvirt/tests/src/memory/memory_misc.py +++ b/libvirt/tests/src/memory/memory_misc.py @@ -311,6 +311,9 @@ def run_test_memorybacking(case): if case == 'prealloc_thread': virsh.start(vm_name, ignore_status=False) vm.wait_for_login().close() + nonlocal qemu_check + if scenario == 'memfd_backed': + qemu_check = qemu_check % (utils_memory.get_huge_page_size() * 1024) libvirt.check_qemu_cmd_line(qemu_check) if case == 'no_mem_backing': From ea7a2d4745950fd79d99b0826ceeb172a65f73e7 Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 27 Feb 2024 14:44:55 +0800 Subject: [PATCH 0201/1055] migration: Update error message Signed-off-by: lcheng --- ...tion_network_data_transport_tls_wrong_cert_configuration.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls_wrong_cert_configuration.cfg b/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls_wrong_cert_configuration.cfg index cc19de4a4b3..3d18778bb24 100644 --- a/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls_wrong_cert_configuration.cfg +++ b/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls_wrong_cert_configuration.cfg @@ -42,7 +42,7 @@ variants cert_configuration: - no_client_cert_on_src: cert_path = "${custom_pki_path}/client-cert.pem" - err_msg = "Cannot write to TLS channel: Input/output error|unable to execute QEMU command 'object-add': Unable to access credentials ${cert_path}" + err_msg = "Cannot write to TLS channel: Input/output error|unable to execute QEMU command 'object-add': Unable to access credentials ${cert_path}|job 'migration out' failed: Cannot read from TLS channel: Software caused connection abort" - no_server_cert_on_target: cert_path = "${custom_pki_path}/server-cert.pem" err_msg = "unable to execute QEMU command 'object-add': Unable to access credentials ${cert_path}" From ac511e6c77174c708ffa5b60ceea21b2c7d6b220 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Tue, 27 Feb 2024 09:57:19 -0500 Subject: [PATCH 0202/1055] Fix the error message The error message changes for the negative scenario to update the mac address. Update the error message in the cfg file to match it. Signed-off-by: Yalan Zhang --- .../update_device/unsupported_live_update_delete.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg index a7b171ca1cb..753020ab9a6 100644 --- a/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg +++ b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg @@ -45,5 +45,5 @@ err_msg = device not found: no device found at address .* matching MAC address .* and alias .* - mac: del_attr = mac_address - err_msg = device not found: no device found at address .* matching MAC address .* and alias .* + err_msg = "cannot change network interface mac address|device not found" base_iface_attrs = {'mac_address': mac, 'type_name': 'network', 'source': {'network': 'default'}, 'model': 'virtio'} From 387bc569b11144ad178fbbf75c51a050ac653e1a Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 20 Feb 2024 03:08:15 -0500 Subject: [PATCH 0203/1055] domfstrim: grant guest agent SELinux permissions The guest agent won't be able to fstrim successfully if selinux is present and enforcing. Set the SELinux boolean persistently to enable access by the guest agent. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/virsh_cmd/domain/virsh_domfstrim.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_domfstrim.py b/libvirt/tests/src/virsh_cmd/domain/virsh_domfstrim.py index 526898f3d34..76edd2b1a53 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_domfstrim.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_domfstrim.py @@ -20,6 +20,16 @@ logging = log.getLogger('avocado.' + __name__) +def try_set_selinux_label(session): + """ + Per default selinux will block the guest agent + from trimming the device. Try to set label for this test + + :param session: VM console session + """ + session.cmd_output("setsebool -P virt_qemu_ga_read_nonsecurity_files on") + + def run(test, params, env): """ Test domfstrim command, make sure that all supported options work well @@ -100,6 +110,7 @@ def recompose_xml(vm_name, scsi_disk): if not vm.is_alive(): vm.start() session = vm.wait_for_login() + try_set_selinux_label(session) bef_list = session.cmd_output("fdisk -l|grep ^/dev|" "cut -d' ' -f1").split("\n") session.close() From 8eb18986ff97d02572a736de309a33815b92d7b5 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Thu, 29 Feb 2024 14:13:57 +0800 Subject: [PATCH 0204/1055] Fix nbdkit cases failures Signed-off-by: Ming Xie --- v2v/tests/src/nbdkit/nbdkit.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/v2v/tests/src/nbdkit/nbdkit.py b/v2v/tests/src/nbdkit/nbdkit.py index 34d858cf056..7910f603a9a 100644 --- a/v2v/tests/src/nbdkit/nbdkit.py +++ b/v2v/tests/src/nbdkit/nbdkit.py @@ -377,6 +377,7 @@ def annocheck_test_nbdkit(): tmp_path = data_dir.get_tmp_dir() process.run('yum download nbdkit-server nbdkit-server-debuginfo --destdir=%s' % tmp_path, shell=True, ignore_status=True) + process.run('rm -rf /etc/yum.repos.d/rhel9-debug.repo', shell=True, ignore_status=True) cmd_3 = 'annocheck -v --skip-cf-protection --skip-glibcxx-assertions --skip-glibcxx-assertions ' \ '--skip-stack-realign --section-size=.gnu.build.attributes --ignore-gaps ' \ '%s/%s --debug-rpm=%s/%s' % (tmp_path, (process.run('ls %s/nbdkit-server-1*' % tmp_path, @@ -387,7 +388,6 @@ def annocheck_test_nbdkit(): cmd_3_result = process.run(cmd_3, shell=True, ignore_status=True) if re.search('FAIL', cmd_3_result.stdout_text) and len(cmd_3_result.stdout_text) == 0: test.fail('fail to test ndbkit-server rpm package with annocheck tool') - process.run('rm -rf /etc/yum.repos.d/rhel9-debug.repo', shell=True, ignore_status=True) def statsfile_option(): tmp_path = data_dir.get_tmp_dir() @@ -558,6 +558,7 @@ def cve_starttls(): process.run('yum download --source nbdkit --destdir=%s' % tmp_path, shell=True, ignore_status=True) process.run('yum install libtool -y', shell=True, ignore_status=True) + process.run('rm -rf /etc/yum.repos.d/rhel9-appsource.repo', shell=True, ignore_status=True) process.run('cd %s ; rpmbuild -rp %s' % (tmp_path, (process.run('ls %s/nbdkit*.src.rpm' % tmp_path, shell=True). stdout_text.split('/'))[-1].strip('\n')), shell=True) check_file = process.run('ls /root/rpmbuild/BUILD/nbdkit-*/server/protocol-handshake-newstyle.c', From 44721c43cc189f5d15ad101fd59dc7c738b7b2ae Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Thu, 29 Feb 2024 15:42:03 +0800 Subject: [PATCH 0205/1055] Add nbdkit case about security label Signed-off-by: Ming Xie --- v2v/tests/cfg/nbdkit/nbdkit.cfg | 5 +++++ v2v/tests/src/nbdkit/nbdkit.py | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/v2v/tests/cfg/nbdkit/nbdkit.cfg b/v2v/tests/cfg/nbdkit/nbdkit.cfg index 0820c502b04..918fb5dad8c 100644 --- a/v2v/tests/cfg/nbdkit/nbdkit.cfg +++ b/v2v/tests/cfg/nbdkit/nbdkit.cfg @@ -57,6 +57,11 @@ - protect: version_required = "[nbdkit-server-1.30.8-1,)" checkpoint = 'test_protect_filter' + - ip: + variants: + - security_label: + version_required = "[nbdkit-server-1.36.1-1,)" + checkpoint = 'security_label' - plugin: variants: - file: diff --git a/v2v/tests/src/nbdkit/nbdkit.py b/v2v/tests/src/nbdkit/nbdkit.py index 7910f603a9a..a19de3b214d 100644 --- a/v2v/tests/src/nbdkit/nbdkit.py +++ b/v2v/tests/src/nbdkit/nbdkit.py @@ -589,6 +589,23 @@ def test_protect_filter(): if not re.search('Operation not permitted ', grep_stdout_2.decode()): test.fail('fail to test protect filter') + def security_label(): + tmp_path = data_dir.get_tmp_dir() + image_path = os.path.join(tmp_path, 'latest-rhel9.img') + process.run('qemu-img convert -f qcow2 -O raw /var/lib/avocado/data/avocado-vt/images/jeos-27-x86_64.qcow2' + ' %s' % image_path, shell=True) + label = process.run("ps -Z", shell=True, ignore_status=True) + LOG.info("label %s", label) + sec_label = re.search('unconfined_u:unconfined_r:unconfined.*\n', label.stdout_text).group(0).split(' ')[0] + LOG.info("seclabel %s", sec_label) + test_co_label = process.run("nbdkit --filter=ip file %s allow=security:%s deny=all --run 'nbdinfo $uri'" % + (image_path, sec_label), shell=True, ignore_status=True) + test_inco_label = process.run("nbdkit --filter=ip file %s allow=security:%s1 deny=all --run 'nbdinfo $uri'" % + (image_path, sec_label), shell=True, ignore_status=True) + if re.search(" error", test_co_label.stdout_text) or not re.search("error: client not permitted", + test_inco_label.stderr_text): + test.fail('fail to test security label of IP filter') + if version_required and not multiple_versions_compare( version_required): test.cancel("Testing requires version: %s" % version_required) @@ -648,5 +665,7 @@ def test_protect_filter(): cve_starttls() elif checkpoint == 'test_protect_filter': test_protect_filter() + elif checkpoint == 'security_label': + security_label() else: test.error('Not found testcase: %s' % checkpoint) From e6721acba5ad9c1a3209f81f77bbe76bff19a1ae Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Wed, 28 Feb 2024 20:43:59 -0500 Subject: [PATCH 0206/1055] Fix setmem failure on s390x Previously fixing by increasing memory doesn't apply on s390x ,which leads to some error:test conditions not met: Inside memory deviated Signed-off-by: chunfuwen --- libvirt/tests/cfg/memory/virsh_setmem.cfg | 3 +++ libvirt/tests/src/memory/virsh_setmem.py | 31 +++++++++++++---------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/libvirt/tests/cfg/memory/virsh_setmem.cfg b/libvirt/tests/cfg/memory/virsh_setmem.cfg index e0ff04b22dc..f7a6ba37306 100644 --- a/libvirt/tests/cfg/memory/virsh_setmem.cfg +++ b/libvirt/tests/cfg/memory/virsh_setmem.cfg @@ -17,6 +17,9 @@ # expected to fail on older libvirt. setmem_old_libvirt_fail = "no" take_regular_screendumps = no + reset_vm_memory = "yes" + s390-virtio: + reset_vm_memory = "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 1fafe829a7b..d261c4b973c 100644 --- a/libvirt/tests/src/memory/virsh_setmem.py +++ b/libvirt/tests/src/memory/virsh_setmem.py @@ -248,26 +248,29 @@ def print_debug_stats(original_inside_mem, original_outside_mem, with_packed = "yes" == params.get("with_packed", "no") 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") vm = env.get_vm(vm_name) # Back up domain XML vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() - 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') - 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) - if host_free_mem < guest_memory: - test.cancel("There is not enough memory for guest.") - - vmxml.setup_attrs(**vm_attrs) - vmxml.sync() + # 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'] + guest_memory = memory_base.convert_data_size( + 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) + if host_free_mem < guest_memory: + test.cancel("There is not enough memory for guest.") + + vmxml.setup_attrs(**vm_attrs) + vmxml.sync() if with_packed and not libvirt_version.version_compare(6, 3, 0): test.cancel("The virtio packed attribute is not supported in" From 3c42892fad68c13ae82029af120930778d1cdf4c Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Mon, 4 Mar 2024 01:10:11 -0500 Subject: [PATCH 0207/1055] Add a "udevadm settle" between the dasdfmt and fdasd This can help prevent error "DASD /dev/dasda is in use. Unmount it first!" Signed-off-by: chunfuwen --- provider/vfio/ccw.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/provider/vfio/ccw.py b/provider/vfio/ccw.py index d447a04ddd1..dda9bd02a48 100644 --- a/provider/vfio/ccw.py +++ b/provider/vfio/ccw.py @@ -116,6 +116,8 @@ def format_dasd(path, session): err, out = cmd_status_output(cmd, shell=True, session=session) if err: raise TestError("Couldn't format disk. %s" % out) + udev_cmd = "udevadm settle" + cmd_status_output(udev_cmd, shell=True, session=session) return True From 4512bd405370a94a84b4e83e3b9dd142348c0d9e Mon Sep 17 00:00:00 2001 From: Yan Fu Date: Mon, 4 Mar 2024 16:20:53 +0800 Subject: [PATCH 0208/1055] Support pvpanic model panic device for aarch64 Signed-off-by: Yan Fu --- libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py b/libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py index f0b67ee5f00..adc0e0dce48 100644 --- a/libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py +++ b/libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py @@ -168,6 +168,9 @@ def run(test, params, env): if "ppc" not in platform.machine(): panic_dev.addr_type = "isa" panic_dev.addr_iobase = "0x505" + if platform.machine() == 'aarch64': + panic_dev.model = "pvpanic" + panic_dev.addr_type = "pci" vmxml.add_device(panic_dev) vmxml.sync() # Config auto_dump_path in qemu.conf From 05e2534de3b4d718046a0b0fccfb5eb03c966012 Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 5 Mar 2024 11:39:42 +0800 Subject: [PATCH 0209/1055] migration: Update port reuse case Add scenario about --disks-port option. Signed-off-by: lcheng --- .../network_data_transport/tcp_port_reuse.cfg | 13 +++++++++---- .../network_data_transport/tcp_port_reuse.py | 5 +++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_port_reuse.cfg b/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_port_reuse.cfg index 9ab62113cdc..e9ac7dfd43a 100644 --- a/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_port_reuse.cfg +++ b/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_port_reuse.cfg @@ -24,14 +24,10 @@ migrate_desturi_port = "16509" migrate_desturi_type = "tcp" virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" - port_to_check = "49153" - action_during_mig = '[{"func": "libvirt_network.check_established", "before_pause": "yes", "func_param": "params"}]' - action_during_mig_again = '[{"func": "libvirt_network.check_established", "before_pause": "yes", "func_param": "params"}]' migrate_again = "yes" migrate_again_status_error = 'no' setup_nfs = "no" nfs_mount_dir = - variants: - p2p: virsh_migrate_options = '--live --p2p --verbose' @@ -40,3 +36,12 @@ variants: - copy_storage_all: copy_storage_option = "--copy-storage-all" + variants: + - specify_port: + disks_port = "49666" + check_patterns = [r'ESTAB .*${migrate_dest_host}]:${disks_port}', r'ESTAB .*${migrate_dest_host}]:49152'] + virsh_migrate_extra = "--disks-port ${disks_port}" + - default_port: + check_patterns = [r'ESTAB .*${migrate_dest_host}]:49153', r'ESTAB .*${migrate_dest_host}]:49152'] + action_during_mig = '[{"func": "libvirt_network.check_sockets_statistics", "after_event": "block-job", "func_param": {"server_ip": "${server_ip}", "server_user": "${server_user}", "server_pwd": "${server_pwd}", "check_patterns": "${check_patterns}"}, "wait_for_after_event_timeout": "600"}]' + action_during_mig_again = '[{"func": "libvirt_network.check_sockets_statistics", "after_event": "block-job", "func_param": {"server_ip": "${server_ip}", "server_user": "${server_user}", "server_pwd": "${server_pwd}", "check_patterns": "${check_patterns}"}, "wait_for_after_event_timeout": "600"}]' diff --git a/libvirt/tests/src/migration_with_copy_storage/network_data_transport/tcp_port_reuse.py b/libvirt/tests/src/migration_with_copy_storage/network_data_transport/tcp_port_reuse.py index 219603ef794..eef6894489d 100644 --- a/libvirt/tests/src/migration_with_copy_storage/network_data_transport/tcp_port_reuse.py +++ b/libvirt/tests/src/migration_with_copy_storage/network_data_transport/tcp_port_reuse.py @@ -28,17 +28,22 @@ def run_migration_again(): vm_name = params.get("migrate_main_vm") migrate_again = "yes" == params.get("migrate_again", "no") + disks_port = params.get("disks_port") vm = env.get_vm(vm_name) migration_obj = base_steps.MigrationBase(test, vm, params) try: migration_obj.setup_connection() + if disks_port: + migration_obj.remote_add_or_remove_port(disks_port) base_steps.prepare_disks_remote(params, vm) migration_obj.run_migration() if migrate_again: run_migration_again() migration_obj.verify_default() finally: + if disks_port: + migration_obj.remote_add_or_remove_port(disks_port, add=False) migration_obj.cleanup_connection() base_steps.cleanup_disks_remote(params, vm) From 82aa0952f6a70df575dd820d4f6aa0dacb609e23 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 4 Mar 2024 23:21:22 -0500 Subject: [PATCH 0210/1055] Change cpu mode to host-passthrough for aarch64 Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/memory/hmat.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/cfg/memory/hmat.cfg b/libvirt/tests/cfg/memory/hmat.cfg index 750c971ca78..6bb0276c0f1 100644 --- a/libvirt/tests/cfg/memory/hmat.cfg +++ b/libvirt/tests/cfg/memory/hmat.cfg @@ -2,6 +2,8 @@ type = hmat start_vm = no cpuxml_cpu_mode = "host-model" + aarch64: + cpuxml_cpu_mode = "host-passthrough" cpuxml_mode = "qemu64" cpuxml_fallback = "allow" cpuxml_numa_cell = [{'id': '0', 'cpus': '0-5', 'memory': '512', 'unit': 'M'}, {'id': '1', 'memory': '512', 'unit': 'M'}] From 97047a6e8bcb62e460f47ee510394b407c480710 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Tue, 27 Feb 2024 18:28:43 +0800 Subject: [PATCH 0211/1055] aarch64_cpu_sve: fix issues Some arm hardwares do not support sve512 and sve256. So we should handle this special condition. Signed-off-by: Dan Zheng --- libvirt/tests/src/cpu/aarch64_cpu_sve.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/src/cpu/aarch64_cpu_sve.py b/libvirt/tests/src/cpu/aarch64_cpu_sve.py index 6a9228002fa..719232c0b51 100644 --- a/libvirt/tests/src/cpu/aarch64_cpu_sve.py +++ b/libvirt/tests/src/cpu/aarch64_cpu_sve.py @@ -97,9 +97,9 @@ def _get_maxium_sve_length(vm): sve_length_byte = re.search(r"length (\d+) bytes", ret).groups()[0] # Change max_length into sve + length(bit) E.g. sve512 sve_length_bit = "sve" + str(int(sve_length_byte) * 8) - logging.debug("guest sve_length_bit is %s" % sve_length_bit) + logging.debug("The guest maximum SVE vector length is %s", sve_length_bit) except Exception as e: - test.fail("Failed to get guest SVE Vector length: %s" % e) + test.fail("Failed to get maximum guest SVE vector length: %s" % e) finally: if session: session.close() @@ -170,6 +170,9 @@ def _guest_has_sve(vm): test.error("Failed to define guest: %s" % str(e)) result = virsh.start(vm_name) + special_error_msg = "CPU does not support the vector length" + if re.search(special_error_msg, result.stderr_text): + test.cancel(result.stderr_text) libvirt.check_exit_status(result, status_error) if status_error: @@ -189,9 +192,10 @@ def _guest_has_sve(vm): # SVE available with only the selected vector expect_vector_length = vector_length + available_maxium_sve_length = _get_maxium_sve_length(vm) if vector_length == "sve": - expect_vector_length = "sve512" - if expect_vector_length != _get_maxium_sve_length(vm): + expect_vector_length = available_maxium_sve_length + if expect_vector_length != available_maxium_sve_length: test.fail("Expect guest support %s" % vector_length) else: # Disable SVE in domain xml From 5267227888eb89b43869236c67a67033b7e195e1 Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 5 Mar 2024 16:50:13 +0800 Subject: [PATCH 0212/1055] migration: Update postcopy case Add new step to check virtqemud log. Signed-off-by: lcheng --- .../migration_memory_copy_mode_precopy.cfg | 45 --------------- .../migration/memory_copy_mode/postcopy.cfg | 55 +++++++++++++++++++ ...ory_copy_mode_postcopy.cfg => precopy.cfg} | 28 ++++------ .../memory_copy_mode/memory_copy_mode.py | 29 ++++++++++ 4 files changed, 95 insertions(+), 62 deletions(-) delete mode 100644 libvirt/tests/cfg/migration/memory_copy_mode/migration_memory_copy_mode_precopy.cfg create mode 100644 libvirt/tests/cfg/migration/memory_copy_mode/postcopy.cfg rename libvirt/tests/cfg/migration/memory_copy_mode/{migration_memory_copy_mode_postcopy.cfg => precopy.cfg} (56%) create mode 100644 libvirt/tests/src/migration/memory_copy_mode/memory_copy_mode.py diff --git a/libvirt/tests/cfg/migration/memory_copy_mode/migration_memory_copy_mode_precopy.cfg b/libvirt/tests/cfg/migration/memory_copy_mode/migration_memory_copy_mode_precopy.cfg deleted file mode 100644 index f23c2e293a9..00000000000 --- a/libvirt/tests/cfg/migration/memory_copy_mode/migration_memory_copy_mode_precopy.cfg +++ /dev/null @@ -1,45 +0,0 @@ -- migration.migration_memory_copy_mode.precopy: - type = migration_memory_copy_mode - migration_setup = 'yes' - storage_type = 'nfs' - setup_local_nfs = 'yes' - disk_type = "file" - disk_source_protocol = "netfs" - mnt_path_name = ${nfs_mount_dir} - # Console output can only be monitored via virsh console output - only_pty = True - take_regular_screendumps = no - # Extra options to pass after - virsh_migrate_extra = '' - # SSH connection time out - ssh_timeout = 60 - # Local URI - virsh_migrate_connect_uri = 'qemu:///system' - virsh_migrate_dest_state = "running" - virsh_migrate_src_state = "shut off" - image_convert = 'no' - server_ip = "${migrate_dest_host}" - server_user = "root" - server_pwd = "${migrate_dest_pwd}" - status_error = "no" - check_network_accessibility_after_mig = "yes" - migrate_desturi_port = "16509" - migrate_desturi_type = "tcp" - virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" - - variants test_case: - - default: - migrate_speed = "10" - stress_package = "stress" - stress_args = "--cpu 8 --io 4 --vm 2 --vm-bytes 128M --timeout 20s" - port_to_check = "16509" - check_local_port = "yes" - migrate_speed_high = '8796093022207' - action_during_mig = '[{"func": "libvirt_network.check_established", "after_event": "iteration: \'1\'", "func_param": "params"}, {"func": "set_migrate_speed_to_high", "func_param": "params"}]' - variants: - - p2p: - service_to_check = "virtqemud|libvirtd" - virsh_migrate_options = '--live --p2p --verbose' - - non_p2p: - service_to_check = "virsh" - virsh_migrate_options = '--live --verbose' diff --git a/libvirt/tests/cfg/migration/memory_copy_mode/postcopy.cfg b/libvirt/tests/cfg/migration/memory_copy_mode/postcopy.cfg new file mode 100644 index 00000000000..54229467656 --- /dev/null +++ b/libvirt/tests/cfg/migration/memory_copy_mode/postcopy.cfg @@ -0,0 +1,55 @@ +- migration.memory_copy_mode.postcopy: + type = memory_copy_mode + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + status_error = "no" + check_network_accessibility_after_mig = "yes" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + stress_package = "stress" + stress_args = "--cpu 8 --io 4 --vm 2 --vm-bytes 128M --timeout 20s" + test_case = "postcopy" + libvirtd_file_type = "virtqemud" + libvirtd_debug_level = "1" + libvirtd_debug_filters = "1:*" + libvirtd_debug_file = '/var/log/libvirt/virtqemud.log' + check_str_local_log = '['{"capability":"postcopy-preempt","state":true}']' + expected_event_src = ["lifecycle.*Suspended Migrated", "lifecycle.*Suspended Post-copy", "lifecycle.*Stopped Migrated", "job-completed"] + expected_event_target = ["event 'lifecycle'.*: Started Migrated", "event 'lifecycle'.*: Resumed Post-copy", "event 'lifecycle'.*: Resumed Migrated"] + variants: + - p2p: + virsh_migrate_options = '--live --p2p --verbose' + - non_p2p: + virsh_migrate_options = '--live --verbose' + variants: + - default_postcopy: + postcopy_options = '--postcopy' + expected_event_src = ["lifecycle.*Suspended Migrated", "lifecycle.*Stopped Migrated", "job-completed"] + expected_event_target = ["event 'lifecycle'.*: Started Migrated", "event 'lifecycle'.*: Resumed Migrated"] + - migrate_postcopy: + postcopy_options = '--postcopy' + action_during_mig = '[{"func": "virsh.migrate_postcopy", "after_event": "iteration: '1'", "func_param": "'%s' % params.get('migrate_main_vm')"}]' + - postcopy_after_precopy: + postcopy_options = '--postcopy --postcopy-after-precopy' + - timeout_postcopy: + postcopy_options = '--postcopy --timeout 10 --timeout-postcopy' diff --git a/libvirt/tests/cfg/migration/memory_copy_mode/migration_memory_copy_mode_postcopy.cfg b/libvirt/tests/cfg/migration/memory_copy_mode/precopy.cfg similarity index 56% rename from libvirt/tests/cfg/migration/memory_copy_mode/migration_memory_copy_mode_postcopy.cfg rename to libvirt/tests/cfg/migration/memory_copy_mode/precopy.cfg index d79a1e7517b..aa2318a5582 100644 --- a/libvirt/tests/cfg/migration/memory_copy_mode/migration_memory_copy_mode_postcopy.cfg +++ b/libvirt/tests/cfg/migration/memory_copy_mode/precopy.cfg @@ -1,5 +1,5 @@ -- migration.migration_memory_copy_mode: - type = migration_memory_copy_mode +- migration.memory_copy_mode.precopy: + type = memory_copy_mode migration_setup = 'yes' storage_type = 'nfs' setup_local_nfs = 'yes' @@ -26,25 +26,19 @@ migrate_desturi_port = "16509" migrate_desturi_type = "tcp" virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + migrate_speed = "10" stress_package = "stress" stress_args = "--cpu 8 --io 4 --vm 2 --vm-bytes 128M --timeout 20s" + port_to_check = "16509" + check_local_port = "yes" + migrate_speed_high = '8796093022207' + action_during_mig = '[{"func": "libvirt_network.check_established", "after_event": "iteration: \'1\'", "func_param": "params"}, {"func": "set_migrate_speed_to_high", "func_param": "params"}]' + expected_event_src = ["migration-iteration.*iteration: '1'", "lifecycle.*Suspended Migrated", "lifecycle.*Stopped Migrated", "job-completed"] + expected_event_target = ["event 'lifecycle'.*: Started Migrated", "event 'lifecycle'.*: Resumed Migrated"] variants: - p2p: + service_to_check = "virtqemud|libvirtd" virsh_migrate_options = '--live --p2p --verbose' - non_p2p: + service_to_check = "virsh" virsh_migrate_options = '--live --verbose' - variants test_case: - - postcopy_migration: - variants: - - default_postcopy: - postcopy_options = '--postcopy' - - migrate_postcopy: - expected_event_src = 'Suspended Post-copy' - postcopy_options = '--postcopy' - action_during_mig = '[{"func": "virsh.migrate_postcopy", "after_event": "iteration: '1'", "func_param": "'%s' % params.get('migrate_main_vm')"}]' - - postcopy_after_precopy: - expected_event_src = 'Suspended Post-copy' - postcopy_options = '--postcopy --postcopy-after-precopy' - - timeout_postcopy: - expected_event_src = 'Suspended Post-copy' - postcopy_options = '--postcopy --timeout 10 --timeout-postcopy' diff --git a/libvirt/tests/src/migration/memory_copy_mode/memory_copy_mode.py b/libvirt/tests/src/migration/memory_copy_mode/memory_copy_mode.py new file mode 100644 index 00000000000..13c51f00b98 --- /dev/null +++ b/libvirt/tests/src/migration/memory_copy_mode/memory_copy_mode.py @@ -0,0 +1,29 @@ +from provider.migration import base_steps +from provider.migration import migration_base + + +def run(test, params, env): + """ + Test live migration with precopy/postcopy. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + vm_name = params.get("migrate_main_vm") + + virsh_session = None + remote_virsh_session = None + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + migration_obj.setup_connection() + # Monitor event on source/target host + virsh_session, remote_virsh_session = migration_base.monitor_event(params) + migration_obj.run_migration() + migration_obj.verify_default() + migration_base.check_event_output(params, test, virsh_session, remote_virsh_session) + finally: + migration_obj.cleanup_connection() From f15ee07e49d005702c2e3520cb5dba14ab004bf9 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Tue, 5 Mar 2024 18:30:44 +0800 Subject: [PATCH 0213/1055] libvirt_rng: fix unstable dd count When count is too small, the rng rate can not control accuratly. So we tune it bigger to make the case stable. Signed-off-by: Dan Zheng --- libvirt/tests/cfg/libvirt_rng.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/cfg/libvirt_rng.cfg b/libvirt/tests/cfg/libvirt_rng.cfg index 593ffa24c29..7dff40de025 100644 --- a/libvirt/tests/cfg/libvirt_rng.cfg +++ b/libvirt/tests/cfg/libvirt_rng.cfg @@ -90,6 +90,7 @@ - rng_rate: test_qemu_cmd = "yes" test_guest = "yes" + dd_throughput = "bs=512 count=100" variants: - back_rdm: rng_rate = "{'bytes':'5000','period':'2000'}" From 1b33ab71e958502ba7a7be8b53294c27783fd98f Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 5 Mar 2024 06:52:17 -0500 Subject: [PATCH 0214/1055] at_dt_iscsi_disk: fix disk_discovery The code found new disks by their target name, e.g. 'vdX'. Those names can change between reboots. Instead, use function to identify new disks that don't mount the root file system. The function raises an error if there is no such disk, so handle that to confirm that disks are detached correctly. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/virtual_disks/at_dt_iscsi_disk.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/src/virtual_disks/at_dt_iscsi_disk.py b/libvirt/tests/src/virtual_disks/at_dt_iscsi_disk.py index 6e2f9fa1991..1333bffc156 100644 --- a/libvirt/tests/src/virtual_disks/at_dt_iscsi_disk.py +++ b/libvirt/tests/src/virtual_disks/at_dt_iscsi_disk.py @@ -8,6 +8,7 @@ from aexpect import ShellError +from avocado.core.exceptions import TestError from avocado.utils import process from virttest import virsh @@ -16,6 +17,7 @@ from virttest.remote import LoginError from virttest.virt_vm import VMError from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_disk from virttest.libvirt_xml import vm_xml from virttest.libvirt_xml import pool_xml from virttest.libvirt_xml.secret_xml import SecretXML @@ -386,13 +388,10 @@ def find_attach_disk(expect=True): # recognize the hotplugged disk on PPC if on_ppc: time.sleep(10) - cmd = "grep %s /proc/partitions" % disk_target - s, o = session.cmd_status_output(cmd) - logging.info("%s output: %s", cmd, o) - session.close() - if s == 0: - found_disk = True - except (LoginError, VMError, ShellError) as e: + disk, _ = libvirt_disk.get_non_root_disk_name(session) + logging.debug("Found new disk in VM as %s", disk) + found_disk = True + except (LoginError, VMError, ShellError, TestError) as e: logging.error(str(e)) if found_disk == expect: logging.debug("Check disk inside the VM PASS as expected") From 5546dc21a2cae21e595a55db20b2da290c511e42 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 5 Mar 2024 07:49:30 -0500 Subject: [PATCH 0215/1055] virtual_disk/transient_disk: fix disk discovery for VM1 The second VM disk command reused the first one which could lead to the wrong disk name being used: "/dev/vda is apparently in use by the system; will not make a filesystem here!" Make sure to discover the disk again for the second VM. Signed-off-by: Sebastian Mitterle --- .../tests/src/virtual_disks/virtual_disks_transient_disk.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_transient_disk.py b/libvirt/tests/src/virtual_disks/virtual_disks_transient_disk.py index 33ffb91f20c..1ac4d556e6e 100644 --- a/libvirt/tests/src/virtual_disks/virtual_disks_transient_disk.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_transient_disk.py @@ -86,11 +86,16 @@ def check_share_transient_disk(vms_list): # check on vm1. session = vms_list[1]['vm'].wait_for_login(timeout=10) + new_disk, _ = libvirt_disk.get_non_root_disk_name(session) + sha_cmd = ("sha1sum /dev/%s" % new_disk) vm1_disk_sha1 = session.cmd_output(sha_cmd) if vm0_disk_sha1 == vm1_disk_sha1: session.close() test.fail("Still can find file created in transient disk of vm0") + cmd = ("fdisk -l /dev/%s && mkfs.ext4 -F /dev/%s && mount /dev/%s" + " /mnt && echo '%s' > /mnt/test && umount /mnt" + % (new_disk, new_disk, new_disk, test_str)) s, o = session.cmd_status_output(cmd) logging.debug("session in vm1 exit %s; output: %s", s, o) if s: From 668ec4ee7768398013a83adc09c717e9f710f339 Mon Sep 17 00:00:00 2001 From: Hu Shuai Date: Fri, 8 Dec 2023 13:35:24 +0800 Subject: [PATCH 0216/1055] numa: Fix parsing of more than two consecutive numa nodes Fix parsing of more than two consecutive numa nodes. Before fixing, [0, 1, 2, 3] --> "0-1" After fixing, [0, 1, 2, 3] --> "0-3" Signed-off-by: Hu Shuai --- .../guest_numa_node_tuning/host_guest_mixed_memory_binding.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.py b/libvirt/tests/src/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.py index 37dc7621872..c9412e918e6 100644 --- a/libvirt/tests/src/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.py +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/host_guest_mixed_memory_binding.py @@ -19,6 +19,7 @@ from virttest.libvirt_xml import vm_xml from virttest.utils_test import libvirt from virttest.utils_libvirt import libvirt_memory +from virttest.utils_libvirt import libvirt_numa from provider.numa import numa_base @@ -287,8 +288,7 @@ def check_cgroup(numatest_obj): "vcpu0_cpuset_mems=%s, " "vcpu1_cpuset_mems=%s", emulator_cpuset_mems, vcpu0_cpuset_mems, vcpu1_cpuset_mems) - all_nodes_str = ['%s' % a_node for a_node in all_nodes] - nodeset = numa_base.convert_to_string_with_dash(','.join(all_nodes_str)) + nodeset = libvirt_numa.convert_all_nodes_to_string(all_nodes) for item in [emulator_cpuset_mems, vcpu0_cpuset_mems, vcpu1_cpuset_mems]: if item != nodeset: numatest_obj.test.fail("Expect cpuset.mems to be %s, " From 27a352496205c7a2baa0dae5a406fef80593d775 Mon Sep 17 00:00:00 2001 From: Xiaodai Wang Date: Wed, 6 Mar 2024 10:39:04 +0800 Subject: [PATCH 0217/1055] libvirt_rng: fix variable 'output' referenced before assignment When aexpect.exceptions.ShellTimeoutError is raised and the case is rng_rate, the UnboundLocalError: local variable 'output' referenced before assignment will be reported. Because when the timeout happens, the dd rate will not be reported in dd cmdline, it has no way to calc the rate. So it's reasonable to fail the test when timeout happens. Signed-off-by: Xiaodai Wang --- libvirt/tests/src/libvirt_rng.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/src/libvirt_rng.py b/libvirt/tests/src/libvirt_rng.py index 2f4d618eba3..a88fb5634de 100644 --- a/libvirt/tests/src/libvirt_rng.py +++ b/libvirt/tests/src/libvirt_rng.py @@ -393,6 +393,8 @@ def check_guest(session, expect_fail=False, if expect_fail: test.fail("Still can find rng device in guest") + elif rng_rate: + test.fail("No way to calc rng rate due to dd timeout") else: logging.info("dd cmd do not fail with error") # Check if file have data From e1fbc62697c14ecf4ce63d56e9f9f1ec9ded8684 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Wed, 6 Mar 2024 11:30:14 +0800 Subject: [PATCH 0218/1055] libvirt_rng: fix count only for arm - dd count value too small on arm will not make the rate control take effect. Fix dd count only for arm and do not impact for other arches. - Reorg the rng related files into corresponding directory. Signed-off-by: Dan Zheng --- libvirt/tests/cfg/{ => security/rng}/libvirt_rng.cfg | 3 ++- .../tests/cfg/{virtual_device => security/rng}/virtio_rng.cfg | 0 libvirt/tests/src/{ => security/rng}/libvirt_rng.py | 0 .../tests/src/{virtual_device => security/rng}/virtio_rng.py | 0 4 files changed, 2 insertions(+), 1 deletion(-) rename libvirt/tests/cfg/{ => security/rng}/libvirt_rng.cfg (98%) rename libvirt/tests/cfg/{virtual_device => security/rng}/virtio_rng.cfg (100%) rename libvirt/tests/src/{ => security/rng}/libvirt_rng.py (100%) rename libvirt/tests/src/{virtual_device => security/rng}/virtio_rng.py (100%) diff --git a/libvirt/tests/cfg/libvirt_rng.cfg b/libvirt/tests/cfg/security/rng/libvirt_rng.cfg similarity index 98% rename from libvirt/tests/cfg/libvirt_rng.cfg rename to libvirt/tests/cfg/security/rng/libvirt_rng.cfg index 7dff40de025..3cc5376d804 100644 --- a/libvirt/tests/cfg/libvirt_rng.cfg +++ b/libvirt/tests/cfg/security/rng/libvirt_rng.cfg @@ -90,7 +90,8 @@ - rng_rate: test_qemu_cmd = "yes" test_guest = "yes" - dd_throughput = "bs=512 count=100" + aarch64: + dd_throughput = "bs=512 count=100" variants: - back_rdm: rng_rate = "{'bytes':'5000','period':'2000'}" diff --git a/libvirt/tests/cfg/virtual_device/virtio_rng.cfg b/libvirt/tests/cfg/security/rng/virtio_rng.cfg similarity index 100% rename from libvirt/tests/cfg/virtual_device/virtio_rng.cfg rename to libvirt/tests/cfg/security/rng/virtio_rng.cfg diff --git a/libvirt/tests/src/libvirt_rng.py b/libvirt/tests/src/security/rng/libvirt_rng.py similarity index 100% rename from libvirt/tests/src/libvirt_rng.py rename to libvirt/tests/src/security/rng/libvirt_rng.py diff --git a/libvirt/tests/src/virtual_device/virtio_rng.py b/libvirt/tests/src/security/rng/virtio_rng.py similarity index 100% rename from libvirt/tests/src/virtual_device/virtio_rng.py rename to libvirt/tests/src/security/rng/virtio_rng.py From 54ca180aa307a229045765c5c0c5e8a4b35cbe4a Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Wed, 6 Mar 2024 02:46:08 -0500 Subject: [PATCH 0219/1055] update audit_log_search case with more validation points /var/log/messages and auvirt --start recent --all-events should not contain error message related libvirtd or guest itself Signed-off-by: chunfuwen --- .../cfg/virsh_cmd/domain/virsh_start.cfg | 4 +++ .../tests/src/virsh_cmd/domain/virsh_start.py | 34 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_start.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_start.cfg index 4b4e2efcc38..68bf04daf1d 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_start.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_start.cfg @@ -38,6 +38,10 @@ vs_opt = "--force-boot" - audit_log_search: audit_log_search_string = "AVC" + libvirtd_error_message = "warning : virCgroupMoveTask.*no vm cgroup in controller" + message_log_file = "/var/log/messages" + tmp_auvirt_event_log = "/var/lib/libvirt/images/auvirt.log" + auvirt_error_msg = "%s.*failed" - status_error_yes: status_error = "yes" variants: diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_start.py b/libvirt/tests/src/virsh_cmd/domain/virsh_start.py index 5881d525663..167814d1b56 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_start.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_start.py @@ -9,6 +9,7 @@ from virttest import utils_libvirtd from virttest import ssh_key from virttest import libvirt_version +from virttest.utils_test import libvirt # Using as lower capital is not the best way to do, but this is just a @@ -30,6 +31,35 @@ def check_audit_log(test, audit_log_search_string, start_date, start_time): "in'{cmd_result.stdout_text}'") +def check_message_log(test, params): + """ + Check message in /var/log/messages file + + :param test: Test object for utility functions + :param params: one dictionary wrapping parameters + """ + str_to_grep = params.get("libvirtd_error_message") + message_log_file = params.get("message_log_file") + if not libvirt.check_logfile(str_to_grep, message_log_file, str_in_log=False): + test.fail('Get unexpected error message:%s in log file:%s' % (str_to_grep, message_log_file)) + + +def check_auvirt_log(test, params): + """ + Check message in output of virtualization audit + + :param test: Test object for utility functions + :param params: one dictionary wrapping parameters + """ + vm_name = params.get("main_vm", "avocado-vt-vm1") + str_to_grep = params.get("auvirt_error_msg") % vm_name + auvirt_log_file = params.get("tmp_auvirt_event_log") + generate_virt_log_cmd = "auvirt --start recent --all-events|tee %s" % auvirt_log_file + process.run(generate_virt_log_cmd, ignore_status=False, shell=True, verbose=True) + if not libvirt.check_logfile(str_to_grep, auvirt_log_file, str_in_log=False): + test.fail('Get unexpected audit error message:%s in log file:%s' % (str_to_grep, auvirt_log_file)) + + def run(test, params, env): """ Test command: virsh start. @@ -140,6 +170,8 @@ def run(test, params, env): if audit_log_search_string: if not service_mgr.status("auditd"): service_mgr.start("auditd") + truncate_2m_cmd = "truncate -s 0 /var/log/messages" + process.run(truncate_2m_cmd, ignore_status=True, shell=True, verbose=True) cmd_result = virsh.start(vm_ref, options=opt) if cmd_result.exit_status: if status_error == "no": @@ -174,7 +206,9 @@ def run(test, params, env): "but it is restored from a" " managedsave.") elif audit_log_search_string: + check_message_log(test, params) check_audit_log(test, audit_log_search_string, start_date, start_time) + check_auvirt_log(test, params) else: if status_error == "no" and not vm.is_alive() and pre_operation != "remote": test.fail("VM was started but it is not alive.") From 13aa59171d6dacc3f4be4742cdda1a047c5fdb83 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 6 Mar 2024 07:35:00 -0500 Subject: [PATCH 0220/1055] virsh_edit: add logs Sometimes the test failed with right command, no additional info. Add some additional logs to help debugging the next time it happens. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/virsh_cmd/domain/virsh_edit.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_edit.py b/libvirt/tests/src/virsh_cmd/domain/virsh_edit.py index b8e9b1dbac6..3e223c62d40 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_edit.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_edit.py @@ -117,8 +117,10 @@ def edit_vcpu(source): dic_mode["recover"]]) else: status = libvirt.exec_virsh_edit(vm_name, [dic_mode["recover"]]) + logging.info(status) vmxml.sync() if status and new_vcpus != expected_vcpu: + logging.debug("new_vcpus, expected_vcpu: %s, %s", new_vcpus, expected_vcpu) return False return status From 47dec9a2d079555581a8ff93111321ecc4b98dec Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 6 Mar 2024 09:52:17 -0500 Subject: [PATCH 0221/1055] virtual_network/update_device: don't test rom and acpi On s390x, ROM and ACPI are not available. Don't run these tests. Signed-off-by: Sebastian Mitterle --- .../update_device/unsupported_live_update_add.cfg | 2 ++ .../update_device/unsupported_live_update_alter.cfg | 2 ++ .../update_device/unsupported_live_update_delete.cfg | 2 ++ 3 files changed, 6 insertions(+) diff --git a/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_add.cfg b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_add.cfg index 343cfe2af2b..c9a8a4426ef 100644 --- a/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_add.cfg +++ b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_add.cfg @@ -6,6 +6,7 @@ status_error = yes variants: - acpi_index: + no s390-virtio update_attrs = {'acpi': {'index': '6'}} err_msg = changing device 'acpi index' is not allowed - sndbuf: @@ -19,6 +20,7 @@ update_attrs = {'boot': '3'} err_msg = cannot modify network device boot index setting - rom: + no s390-virtio update_attrs = {'rom': {'enabled': 'yes'}} err_msg = cannot modify network device rom enabled setting - backend: diff --git a/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_alter.cfg b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_alter.cfg index b3df1c2670e..e8956d8f4f9 100644 --- a/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_alter.cfg +++ b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_alter.cfg @@ -5,6 +5,7 @@ status_error = yes variants: - acpi_index: + no s390-virtio extra_attrs = {'acpi': {'index': '4'}} update_attrs = {'acpi': {'index': '6'}} err_msg = changing device 'acpi index' is not allowed @@ -22,6 +23,7 @@ update_attrs = {'boot': '3'} err_msg = cannot modify network device boot index setting - rom: + no s390-virtio extra_attrs = {'rom': {'enabled': 'no'}} update_attrs = {'rom': {'enabled': 'yes'}} err_msg = cannot modify network device rom enabled setting diff --git a/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg index 753020ab9a6..07bd0d29031 100644 --- a/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg +++ b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg @@ -5,6 +5,7 @@ status_error = yes variants: - acpi_index: + no s390-virtio extra_attrs = {'acpi': {'index': '4'}} del_attr = acpi err_msg = changing device 'acpi index' is not allowed @@ -22,6 +23,7 @@ del_attr = boot err_msg = cannot modify network device boot index setting - rom: + no s390-virtio extra_attrs = {'rom': {'enabled': 'no'}} del_attr = rom err_msg = cannot modify network device rom enabled setting From f185887e8c80f6780b613791fea679c3ccf7410d Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 6 Mar 2024 11:44:17 -0500 Subject: [PATCH 0222/1055] cpu_xml: fix negative case with missing feature 'ctop' has become part of host feature list with QEMU 8.2. Therefore the negative test with hypervisor-cpu-compare failed. Add another feature that's not part of host cpu feature list as returned by domcapabilities. To find this kind of condition: list all recognized features with qemu-kvm -cpu ?. Then get domcapabilities and check for features that are not listed there. Signed-off-by: Sebastian Mitterle --- libvirt/tests/deps/negative_domcapabilities_s390x.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/deps/negative_domcapabilities_s390x.xml b/libvirt/tests/deps/negative_domcapabilities_s390x.xml index f0839d5b7e0..34cc5bae07e 100644 --- a/libvirt/tests/deps/negative_domcapabilities_s390x.xml +++ b/libvirt/tests/deps/negative_domcapabilities_s390x.xml @@ -35,6 +35,7 @@ gen15a-base + From 58060194bb41a80d517440340d6c04ecc8053b49 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 1 Mar 2024 14:34:33 +0800 Subject: [PATCH 0223/1055] Enable sriov tests on arm Signed-off-by: Yingshun Cui --- .../sriov_capabilities_iommu_support.cfg | 2 +- ...eck_net_info_by_network_lifecycle_cmds.cfg | 2 +- ...v_define_or_start_network_with_pf_addr.cfg | 4 ++-- .../nodedev/sriov_nodedev_non_driver.cfg | 4 ++-- .../nodedev/sriov_nodedev_reattach_detach.cfg | 2 +- .../sriov_reattach_detach_nodedev_in_use.cfg | 2 +- .../sriov_attach_detach_device.cfg | 2 +- ...detach_device_after_restarting_service.cfg | 2 +- ...ttach_detach_device_special_situations.cfg | 2 +- .../sriov_attach_detach_device_with_flags.cfg | 2 +- ...etach_device_with_unsupported_settings.cfg | 2 +- .../sriov_attach_detach_interface.cfg | 2 +- ...ach_detach_interface_check_connections.cfg | 2 +- ...v_attach_detach_interface_from_network.cfg | 2 +- ...ch_detach_interface_special_situations.cfg | 2 +- ...iov_attach_detach_interface_with_flags.cfg | 2 +- .../sriov_attach_interface_to_vm_with_vf.cfg | 2 +- .../sriov_attach_released_hostdev.cfg | 2 +- .../scalability/sriov_scalability_max_vf.cfg | 1 + .../update_device/sriov_update_device.cfg | 2 +- ...fecycle_exclusive_check_offline_domain.cfg | 4 ++-- ...fecycle_exclusive_check_running_domain.cfg | 4 ++-- ...sriov_vm_lifecycle_iommu_at_dt_hostdev.cfg | 5 ++-- .../sriov_vm_lifecycle_managedsave.cfg | 2 +- .../sriov_vm_lifecycle_reboot.cfg | 9 ++++++- .../sriov_vm_lifecycle_start_destroy.cfg | 2 +- .../sriov_vm_lifecycle_start_negative.cfg | 4 +++- .../sriov_vm_lifecycle_suspend_resume.cfg | 7 +++++- .../sriov_vm_lifecycle_unmanaged.cfg | 2 +- .../sriov_capabilities_iommu_support.py | 8 ------- .../plug_unplug/sriov_attach_detach_device.py | 1 + ..._detach_device_after_restarting_service.py | 4 +++- provider/sriov/check_points.py | 3 +++ provider/sriov/sriov_base.py | 24 ++++++++++++++++++- 34 files changed, 79 insertions(+), 43 deletions(-) diff --git a/libvirt/tests/cfg/sriov/capabilities/sriov_capabilities_iommu_support.cfg b/libvirt/tests/cfg/sriov/capabilities/sriov_capabilities_iommu_support.cfg index fd69ca40cab..0fb5eae16c3 100644 --- a/libvirt/tests/cfg/sriov/capabilities/sriov_capabilities_iommu_support.cfg +++ b/libvirt/tests/cfg/sriov/capabilities/sriov_capabilities_iommu_support.cfg @@ -1,4 +1,4 @@ - sriov.capabilities.iommu_support: type = sriov_capabilities_iommu_support start_vm = "no" - only x86_64 + only x86_64, aarch64 diff --git a/libvirt/tests/cfg/sriov/network/sriov_check_net_info_by_network_lifecycle_cmds.cfg b/libvirt/tests/cfg/sriov/network/sriov_check_net_info_by_network_lifecycle_cmds.cfg index 551d4f99b5b..c7b0df841d4 100644 --- a/libvirt/tests/cfg/sriov/network/sriov_check_net_info_by_network_lifecycle_cmds.cfg +++ b/libvirt/tests/cfg/sriov/network/sriov_check_net_info_by_network_lifecycle_cmds.cfg @@ -1,6 +1,6 @@ - sriov.network.check_net_info_by_network_lifecycle_cmds: type = sriov_check_net_info_by_network_lifecycle_cmds - only x86_64 + only x86_64, aarch64 start_vm = "no" network_dict = {'forward': {'mode': 'hostdev', 'managed': 'yes'}, 'name': 'hostnet', 'vf_list': [{'type_name': 'pci', 'attrs': vf_pci_addr}], 'uuid': 'e6ddbb96-5be5-494d-92f0-f7473e185876'} network_update_dict = {'portgroups': [{'name': 'dontpanic'}]} diff --git a/libvirt/tests/cfg/sriov/network/sriov_define_or_start_network_with_pf_addr.cfg b/libvirt/tests/cfg/sriov/network/sriov_define_or_start_network_with_pf_addr.cfg index 8c6de9e0646..449d547fb71 100644 --- a/libvirt/tests/cfg/sriov/network/sriov_define_or_start_network_with_pf_addr.cfg +++ b/libvirt/tests/cfg/sriov/network/sriov_define_or_start_network_with_pf_addr.cfg @@ -1,6 +1,6 @@ - sriov.network.define_or_start_network_with_pf_addr: type = sriov_define_or_start_network_with_pf_addr - only x86_64 + only x86_64, aarch64 start_vm = "no" - err_msg = "SR-IOV Virtual Function" + err_msg = "SR-IOV Virtual Function" network_dict = {'forward': {'mode': 'hostdev', 'managed': 'yes'}, 'name': 'hostnet', 'vf_list': [{'type_name': 'pci', 'attrs': pf_pci_addr}], 'uuid': 'e6ddbb96-5be5-494d-92f0-f7473e185876'} diff --git a/libvirt/tests/cfg/sriov/nodedev/sriov_nodedev_non_driver.cfg b/libvirt/tests/cfg/sriov/nodedev/sriov_nodedev_non_driver.cfg index 736a1da56fb..4ec4df7c5da 100644 --- a/libvirt/tests/cfg/sriov/nodedev/sriov_nodedev_non_driver.cfg +++ b/libvirt/tests/cfg/sriov/nodedev/sriov_nodedev_non_driver.cfg @@ -1,4 +1,4 @@ - sriov.nodedev.non_driver: - type = sriov_nodedev_non_driver + type = sriov_nodedev_non_driver start_vm = "no" - only x86_64 + only x86_64, aarch64 diff --git a/libvirt/tests/cfg/sriov/nodedev/sriov_nodedev_reattach_detach.cfg b/libvirt/tests/cfg/sriov/nodedev/sriov_nodedev_reattach_detach.cfg index 06527657aea..81b62c9571f 100644 --- a/libvirt/tests/cfg/sriov/nodedev/sriov_nodedev_reattach_detach.cfg +++ b/libvirt/tests/cfg/sriov/nodedev/sriov_nodedev_reattach_detach.cfg @@ -1,7 +1,7 @@ - sriov.nodedev.nodedev_reattach_detach: type = sriov_nodedev_reattach_detach start_vm = "no" - only x86_64 + only x86_64, aarch64 variants dev_name: - vf: - pf: diff --git a/libvirt/tests/cfg/sriov/nodedev/sriov_reattach_detach_nodedev_in_use.cfg b/libvirt/tests/cfg/sriov/nodedev/sriov_reattach_detach_nodedev_in_use.cfg index 191cfdb2ac8..b84152fc9d9 100644 --- a/libvirt/tests/cfg/sriov/nodedev/sriov_reattach_detach_nodedev_in_use.cfg +++ b/libvirt/tests/cfg/sriov/nodedev/sriov_reattach_detach_nodedev_in_use.cfg @@ -2,7 +2,7 @@ type = sriov_reattach_detach_nodedev_in_use start_vm = "no" err_msg = "PCI device.* is in use by driver" - only x86_64 + only x86_64, aarch64 variants dev_type: - hostdev_interface: diff --git a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device.cfg b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device.cfg index 36475dcdcb7..58edefb2a44 100644 --- a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device.cfg +++ b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device.cfg @@ -2,7 +2,7 @@ type = sriov_attach_detach_device start_vm = "no" - only x86_64 + only x86_64, aarch64 variants dev_type: - hostdev_interface: variants dev_source: diff --git a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_after_restarting_service.cfg b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_after_restarting_service.cfg index 3335269c33d..f094be79fe2 100644 --- a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_after_restarting_service.cfg +++ b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_after_restarting_service.cfg @@ -4,7 +4,7 @@ network_dict = {'forward': {'mode': 'hostdev', 'managed': 'yes'}, 'name': 'hostnet', 'vf_list': [{'type_name': 'pci', 'attrs': vf_pci_addr}, {'type_name': 'pci', 'attrs': vf_pci_addr2}], 'uuid': 'e6ddbb96-5be5-494d-92f0-f7473e185876'} pre_iface_dict = {'type_name': 'network', 'source': {'network': 'hostnet'}} - only x86_64 + only x86_64, aarch64 variants dev_type: - hostdev_interface: iface_dict = {'managed': 'yes', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr2}, 'driver': {'driver_attr': {'name': 'vfio'}}, 'alias': {'name': 'ua-89cbe690-6c6c-4f2f-adac-5826fe52ea74'}, 'mac_address': mac_addr} diff --git a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_special_situations.cfg b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_special_situations.cfg index 26d5b369fcf..b5197768cca 100644 --- a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_special_situations.cfg +++ b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_special_situations.cfg @@ -2,7 +2,7 @@ type = sriov_attach_detach_device_special_situations start_vm = "no" - only x86_64 + only x86_64, aarch64 variants dev_type: - hostdev_interface: variants test_scenario: diff --git a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_with_flags.cfg b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_with_flags.cfg index 2076fca786e..d0365fc7488 100644 --- a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_with_flags.cfg +++ b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_with_flags.cfg @@ -1,6 +1,6 @@ - sriov.plug_unplug.attach_detach_device_with_flags: type = sriov_attach_detach_device_with_flags - only x86_64 + only x86_64, aarch64 variants: - offline_domain: diff --git a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_with_unsupported_settings.cfg b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_with_unsupported_settings.cfg index 20c45312784..5fe79f9e5a3 100644 --- a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_with_unsupported_settings.cfg +++ b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_with_unsupported_settings.cfg @@ -2,7 +2,7 @@ type = sriov_attach_detach_device_with_unsupported_settings start_vm = "no" - only x86_64 + only x86_64, aarch64 variants dev_type: - hostdev_interface: variants test_scenario: diff --git a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface.cfg b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface.cfg index 40fa3567657..280c1bb9a75 100644 --- a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface.cfg +++ b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface.cfg @@ -1,7 +1,7 @@ - sriov.plug_unplug.attach_detach_interface: type = sriov_attach_detach_interface start_vm = "no" - only x86_64 + only x86_64, aarch64 variants: - with_managed: diff --git a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface_check_connections.cfg b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface_check_connections.cfg index 7ab29341d72..dee2d44bf0b 100644 --- a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface_check_connections.cfg +++ b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface_check_connections.cfg @@ -1,6 +1,6 @@ - sriov.plug_unplug.attach_detach_interface_check_connections: type = sriov_attach_detach_interface_check_connections - only x86_64 + only x86_64, aarch64 start_vm = "no" vf_no = 4 diff --git a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface_from_network.cfg b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface_from_network.cfg index 518cad3d870..229b64f696a 100644 --- a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface_from_network.cfg +++ b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface_from_network.cfg @@ -2,4 +2,4 @@ type = sriov_attach_detach_interface_from_network start_vm = "no" network_dict = {'forward': {'mode': 'hostdev', 'managed': 'yes'}, 'name': 'hostdev_net', 'vf_list': [{'type_name': 'pci', 'attrs': vf_pci_addr}]} - only x86_64 + only x86_64, aarch64 diff --git a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface_special_situations.cfg b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface_special_situations.cfg index b9769092801..3c2efa9c472 100644 --- a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface_special_situations.cfg +++ b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface_special_situations.cfg @@ -1,7 +1,7 @@ - sriov.plug_unplug.attach_detach_interface_special_situations: type = sriov_attach_detach_interface_special_situations start_vm = "no" - only x86_64 + only x86_64, aarch64 attach_opt = "--managed" variants test_scenario: diff --git a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface_with_flags.cfg b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface_with_flags.cfg index fdec6a76da0..f8e07702bfa 100644 --- a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface_with_flags.cfg +++ b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_interface_with_flags.cfg @@ -1,6 +1,6 @@ - sriov.plug_unplug.attach_detach_interface_with_flags: type = sriov_attach_detach_interface_with_flags - only x86_64 + only x86_64, aarch64 variants: - offline_domain: diff --git a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_interface_to_vm_with_vf.cfg b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_interface_to_vm_with_vf.cfg index ac4e9504174..308ba9f837b 100644 --- a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_interface_to_vm_with_vf.cfg +++ b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_interface_to_vm_with_vf.cfg @@ -3,4 +3,4 @@ start_vm = "no" network_dict = {'forward': {'mode': 'hostdev', 'managed': 'yes'}, 'name': 'hostnet', 'vf_list': [{'type_name': 'pci', 'attrs': vf_pci_addr}, {'type_name': 'pci', 'attrs': vf_pci_addr2}]} pre_iface_dict = {'type_name': 'network', 'source': {'network': 'hostnet'}} - only x86_64 + only x86_64, aarch64 diff --git a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_released_hostdev.cfg b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_released_hostdev.cfg index 5d724125b07..2ed26edec73 100644 --- a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_released_hostdev.cfg +++ b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_released_hostdev.cfg @@ -3,7 +3,7 @@ start_vm = "no" dev_type = "hostdev_interface" iface_dict = {'managed': 'yes', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}} - only x86_64 + only x86_64, aarch64 variants test_scenario: - to_2nd_vm: vms = "ENTER.YOUR.VM1 ENTER.YOUR.VM2" diff --git a/libvirt/tests/cfg/sriov/scalability/sriov_scalability_max_vf.cfg b/libvirt/tests/cfg/sriov/scalability/sriov_scalability_max_vf.cfg index eb455c368f6..56c505f571a 100644 --- a/libvirt/tests/cfg/sriov/scalability/sriov_scalability_max_vf.cfg +++ b/libvirt/tests/cfg/sriov/scalability/sriov_scalability_max_vf.cfg @@ -1,6 +1,7 @@ - sriov.scalability.max_vfs: type = sriov_scalability_max_vfs start_vm = "no" + only x86_64 vf_no = 63 net_forward = {"mode": "hostdev", "managed": "yes"} variants: diff --git a/libvirt/tests/cfg/sriov/update_device/sriov_update_device.cfg b/libvirt/tests/cfg/sriov/update_device/sriov_update_device.cfg index ac8baec7d0f..a91be9ddaaa 100644 --- a/libvirt/tests/cfg/sriov/update_device/sriov_update_device.cfg +++ b/libvirt/tests/cfg/sriov/update_device/sriov_update_device.cfg @@ -4,4 +4,4 @@ iface_dict = {'managed': 'yes', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}} update_iface = {'managed': 'no'} err_msg = "cannot change config of 'hostdev'" - only x86_64 + only x86_64, aarch64 diff --git a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_exclusive_check_offline_domain.cfg b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_exclusive_check_offline_domain.cfg index 74bce0ccad3..9fd7f4763f5 100644 --- a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_exclusive_check_offline_domain.cfg +++ b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_exclusive_check_offline_domain.cfg @@ -1,7 +1,7 @@ - sriov.vm_lifecycle.exclusive_check.offline_domain: type = sriov_vm_lifecycle_exclusive_check_offline_domain start_vm = "no" - only x86_64 + only x86_64, aarch64 variants dev_type: - hostdev_interface: iface_dict = {'managed': 'yes', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}} @@ -12,7 +12,7 @@ err_msg = "Hostdev already exists" - hostdev_device: hostdev_dict2 = {'mode': 'subsystem', 'type': 'pci', 'source': {'untyped_address': pf_pci_addr}, 'managed': 'yes'} - err_msg = "interface of PCI device" + err_msg = "interface of PCI device" - hostdev_device: hostdev_dict = {'mode': 'subsystem', 'type': 'pci', 'source': {'untyped_address': vf_pci_addr}, 'managed': 'yes'} variants dev_type2: diff --git a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_exclusive_check_running_domain.cfg b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_exclusive_check_running_domain.cfg index bdb5251bf20..20be3cde79a 100644 --- a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_exclusive_check_running_domain.cfg +++ b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_exclusive_check_running_domain.cfg @@ -2,7 +2,7 @@ type = sriov_vm_lifecycle_exclusive_check_running_domain vms = "ENTER.YOUR.VM1 ENTER.YOUR.VM2" start_vm = "no" - only x86_64 + only x86_64, aarch64 dev_type = "hostdev_interface" iface_dict = {'managed': 'yes', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}} err_msg = "in use by driver" @@ -11,7 +11,7 @@ - start_2nd_vm: dev_type2 = hostdev_interface iface_dict2 = ${iface_dict} - - assigned_VF_to_host: + - assigned_VF_to_host: - hotplug: dev_type2 = "hostdev_device" hostdev_dict2 = {'mode': 'subsystem', 'type': 'pci', 'source': {'untyped_address': vf_pci_addr}, 'managed': 'yes'} diff --git a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_iommu_at_dt_hostdev.cfg b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_iommu_at_dt_hostdev.cfg index 72d23a24d90..4484fe92795 100644 --- a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_iommu_at_dt_hostdev.cfg +++ b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_iommu_at_dt_hostdev.cfg @@ -10,9 +10,10 @@ - hostdev_interface: variants test_scenario: - managed_yes: - iface_dict = {'managed': 'yes', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}} + iface_dict = {'managed': 'yes', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}} - failover: - expr_iface_no = 3 + no aarch64 + expr_iface_no = 3 br_dict = {'source': {'bridge': 'br0'}, 'teaming': {'type': 'persistent'}, 'alias': {'name': 'ua-3f13c36e-186b-4c6b-ba54-0ec483613931'}, 'mac_address': mac_addr, 'model': 'virtio', 'type_name': 'bridge'} iface_dict = {'teaming': {'type': 'transient', 'persistent': 'ua-3f13c36e-186b-4c6b-ba54-0ec483613931'}, 'mac_address': mac_addr, 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}} - hostdev_device: diff --git a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_managedsave.cfg b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_managedsave.cfg index b89f0f07d80..5703bbd38f7 100644 --- a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_managedsave.cfg +++ b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_managedsave.cfg @@ -3,7 +3,7 @@ start_vm = "no" status_error = "yes" err_msg = "cannot migrate.*domain.*(VFIO.*migration|with.*hostdev)" - only x86_64 + only x86_64, aarch64 variants dev_type: - hostdev_interface: variants dev_source: diff --git a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_reboot.cfg b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_reboot.cfg index 320a461cd21..2af6ece1e18 100644 --- a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_reboot.cfg +++ b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_reboot.cfg @@ -2,7 +2,7 @@ type = sriov_vm_lifecycle_reboot start_vm = "no" - only x86_64 + only x86_64, aarch64 variants: - with_iommu: only vf_address..managed_yes, failover @@ -10,6 +10,10 @@ start_vm = "yes" enable_guest_iommu = "yes" iommu_dict = {'driver': {'intremap': 'on', 'caching_mode': 'on'}, 'model': 'intel'} + aarch64: + start_vm = "no" + enable_guest_iommu = "no" + iommu_dict = {'model': 'virtio'} - without_iommu: no failover variants dev_type: @@ -21,6 +25,8 @@ iface_dict = {'managed': 'yes', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}, 'driver': {'driver_attr': {'name': 'vfio'}}, 'alias': {'name': 'ua-89cbe690-6c6c-4f2f-adac-5826fe52ea74'}, 'mac_address': mac_addr} iface_dict2 = {'managed': 'yes', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr2}, 'driver': {'driver_attr': {'name': 'vfio'}}} check_ping_time = "yes" + aarch64: + check_ping_time = "no" - managed_no: iface_dict = {'managed': 'no', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}, 'alias': {'name': 'ua-89cbe690-6c6c-4f2f-adac-5826fe52ea74'}} - without_managed: @@ -28,6 +34,7 @@ - vlan: iface_dict = {'type_name': 'hostdev', 'vlan': {'tags': [{'id': '42'}]}, 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}, 'alias': {'name': 'ua-89cbe690-6c6c-4f2f-adac-5826fe52ea74'}, 'managed': 'yes', 'driver': {'driver_attr': {'name': 'vfio'}}, 'mac_address': mac_addr} - failover: + no aarch64 br_dict = {'source': {'bridge': 'br0'}, 'teaming': {'type': 'persistent'}, 'alias': {'name': 'ua-3f13c36e-186b-4c6b-ba54-0ec483613931'}, 'mac_address': mac_addr, 'model': 'virtio', 'type_name': 'bridge'} iface_dict = {'teaming': {'type': 'transient', 'persistent': 'ua-3f13c36e-186b-4c6b-ba54-0ec483613931'}, 'mac_address': mac_addr, 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}} - hostdev_device: diff --git a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_start_destroy.cfg b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_start_destroy.cfg index a91fa70d35e..f02482e7787 100644 --- a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_start_destroy.cfg +++ b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_start_destroy.cfg @@ -2,7 +2,7 @@ type = sriov_vm_lifecycle_start_destroy start_vm = "no" - only x86_64 + only x86_64, aarch64 variants dev_type: - hostdev_interface: variants dev_source: diff --git a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_start_negative.cfg b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_start_negative.cfg index bd10d7bffb8..00209f84e2d 100644 --- a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_start_negative.cfg +++ b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_start_negative.cfg @@ -2,7 +2,7 @@ type = sriov_vm_lifecycle_start_negative start_vm = "no" status_error = "yes" - only x86_64 + only x86_64, aarch64 variants dev_type: - hostdev_interface: variants test_scenario: @@ -27,12 +27,14 @@ err_msg = "is supported only for hostdev" define_err = "yes" - iommu_without_caching: + no aarch64 iommu_dict = {'driver': {'intremap': 'on'}, 'model': 'intel'} iface_dict = {'managed': 'yes', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}} err_msg = "iommu to enable" - hostdev_device: variants test_scenario: - iommu_without_caching: + no aarch64 iommu_dict = {'driver': {'intremap': 'on'}, 'model': 'intel'} hostdev_dict = {'mode': 'subsystem', 'type': 'pci', 'source': {'untyped_address': vf_pci_addr}, 'managed': 'yes'} err_msg = "iommu to enable" diff --git a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_suspend_resume.cfg b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_suspend_resume.cfg index 1bd1bbea104..11fcdeb84f7 100644 --- a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_suspend_resume.cfg +++ b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_suspend_resume.cfg @@ -2,7 +2,7 @@ type = sriov_vm_lifecycle_suspend_resume start_vm = "no" - only x86_64 + only x86_64, aarch64 variants: - with_iommu: only vf_address..managed_yes, failover @@ -10,6 +10,10 @@ start_vm = "yes" enable_guest_iommu = "yes" iommu_dict = {'driver': {'intremap': 'on', 'caching_mode': 'on'}, 'model': 'intel'} + aarch64: + start_vm = "no" + enable_guest_iommu = "no" + iommu_dict = {'model': 'virtio'} - without_iommu: no failover variants dev_type: @@ -26,6 +30,7 @@ - vlan: iface_dict = {'type_name': 'hostdev', 'vlan': {'tags': [{'id': '42'}]}, 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}, 'alias': {'name': 'ua-89cbe690-6c6c-4f2f-adac-5826fe52ea74'}, 'managed': 'yes', 'driver': {'driver_attr': {'name': 'vfio'}}, 'mac_address': mac_addr} - failover: + no aarch64 br_dict = {'source': {'bridge': 'br0'}, 'teaming': {'type': 'persistent'}, 'alias': {'name': 'ua-3f13c36e-186b-4c6b-ba54-0ec483613931'}, 'mac_address': mac_addr, 'model': 'virtio', 'type_name': 'bridge'} iface_dict = {'teaming': {'type': 'transient', 'persistent': 'ua-3f13c36e-186b-4c6b-ba54-0ec483613931'}, 'mac_address': mac_addr, 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}} - hostdev_device: diff --git a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_unmanaged.cfg b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_unmanaged.cfg index 7a587c350d2..62433ffb1c3 100644 --- a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_unmanaged.cfg +++ b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_unmanaged.cfg @@ -3,7 +3,7 @@ status_error = "yes" err_msg = "Unmanaged PCI device.*must be manually detached from the host" - only x86_64 + only x86_64, aarch64 variants dev_type: - hostdev_interface: variants dev_source: diff --git a/libvirt/tests/src/sriov/capabilities/sriov_capabilities_iommu_support.py b/libvirt/tests/src/sriov/capabilities/sriov_capabilities_iommu_support.py index 282c5f224ac..039b48706ac 100644 --- a/libvirt/tests/src/sriov/capabilities/sriov_capabilities_iommu_support.py +++ b/libvirt/tests/src/sriov/capabilities/sriov_capabilities_iommu_support.py @@ -1,6 +1,3 @@ -import re - -from virttest import utils_misc from virttest.libvirt_xml import capability_xml @@ -8,11 +5,6 @@ def run(test, params, env): """ check virsh capabilities output includes iommu support element """ - kernel_cmd = utils_misc.get_ker_cmd() - res = re.search("iommu=on", kernel_cmd) - if not res: - test.error("iommu should be enabled in kernel cmd line - " - "'%s'." % kernel_cmd) cap_xml = capability_xml.CapabilityXML() if cap_xml.get_iommu().get('support') != 'yes': test.fail("IOMMU is disabled in capabilities: %s. " diff --git a/libvirt/tests/src/sriov/plug_unplug/sriov_attach_detach_device.py b/libvirt/tests/src/sriov/plug_unplug/sriov_attach_detach_device.py index f60530786a7..85cb4e49bc9 100644 --- a/libvirt/tests/src/sriov/plug_unplug/sriov_attach_detach_device.py +++ b/libvirt/tests/src/sriov/plug_unplug/sriov_attach_detach_device.py @@ -45,6 +45,7 @@ def run_test(): vm_hostdev = vm_xml.VMXML.new_from_dumpxml(vm.name)\ .devices.by_device_tag(device_type)[0] virsh.detach_device(vm.name, vm_hostdev.xml, debug=True, + wait_for_event=True, ignore_status=False) cur_hostdevs = vm_xml.VMXML.new_from_dumpxml(vm.name)\ .devices.by_device_tag(device_type) diff --git a/libvirt/tests/src/sriov/plug_unplug/sriov_attach_detach_device_after_restarting_service.py b/libvirt/tests/src/sriov/plug_unplug/sriov_attach_detach_device_after_restarting_service.py index ccb7cdfd304..868ace7a5ec 100644 --- a/libvirt/tests/src/sriov/plug_unplug/sriov_attach_detach_device_after_restarting_service.py +++ b/libvirt/tests/src/sriov/plug_unplug/sriov_attach_detach_device_after_restarting_service.py @@ -1,3 +1,5 @@ +import time + from provider.sriov import sriov_base from virttest import utils_libvirtd @@ -36,7 +38,7 @@ def run_test(): iface_dev = sriov_test_obj.create_iface_dev(dev_type, iface_dict) virsh.attach_device(vm.name, iface_dev.xml, debug=True, ignore_status=False) - + time.sleep(10) test.log.info("TEST_STEP3: Detach the hostdev interface/device") virsh.detach_device(vm.name, iface_dev.xml, debug=True, ignore_status=False) diff --git a/provider/sriov/check_points.py b/provider/sriov/check_points.py index 06231f64aea..22c4005e1a1 100644 --- a/provider/sriov/check_points.py +++ b/provider/sriov/check_points.py @@ -1,5 +1,6 @@ import aexpect import logging +import platform import re from avocado.core import exceptions @@ -139,6 +140,8 @@ def check_vm_network_accessed(vm_session, ping_count=3, ping_timeout=5, :raise: test.fail when ping fails. :return: Output of ping command """ + if platform.machine() != "x86_64": + return if not ping_dest: ping_dest = sriov_base.get_ping_dest(vm_session) if tcpdump_iface: diff --git a/provider/sriov/sriov_base.py b/provider/sriov/sriov_base.py index 289bd4044c5..3d449f2a3f7 100644 --- a/provider/sriov/sriov_base.py +++ b/provider/sriov/sriov_base.py @@ -1,5 +1,6 @@ -import re import os +import re +import time from avocado.core import exceptions from avocado.utils import process @@ -21,6 +22,8 @@ from provider.interface import interface_base +SKIP_CHECKS = False + def setup_vf(pf_pci, params, session=None): """ @@ -125,6 +128,8 @@ def __init__(self, vm, test, params, session=None): session=self.session) utils_sriov.set_vf(self.pf_pci_path, 0, session=self.session) + time.sleep(10) + self.host_linked_ifaces = utils_net.get_net_if(state="UP") setup_vf(self.pf_pci, self.params, session=self.session) self.pf_info = utils_sriov.get_pf_info_by_pci( self.pf_pci, session=self.session) @@ -145,6 +150,23 @@ def __init__(self, vm, test, params, session=None): self.vf_mac = "" self.dev_slot = None self.controller_dicts = eval(self.params.get("controller_dicts", "[]")) + + iface_attrs = self.params.get('iface_dict') if self.params.get( + 'iface_dict') else self.params.get('hostdev_dict') + + if self.pf_name not in self.host_linked_ifaces: + test.log.debug("skip connection check on this host") + global SKIP_CHECKS + SKIP_CHECKS = True + else: + if (self.params.get("dev_name", "vf") == "pf" or + (not self.params.get("network_dict") and iface_attrs + and iface_attrs.count("pf_"))): + self.host_linked_ifaces.remove(self.pf_name) + if not self.host_linked_ifaces: + self.test.cancel("This test needs at least 1 linked " + "interface(excluding PF) available " + "on the host.") new_xml = vm_xml.VMXML.new_from_inactive_dumpxml(self.vm.name) self.orig_config_xml = new_xml.copy() From 68bb127f844f919054b3e0498eaf73b204ff6b6a Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 27 Dec 2023 14:16:46 +0800 Subject: [PATCH 0224/1055] migration: Add case about migrateuri and disks-port XXX-297867 - VM live migration with copy storage - network data transport - TCP - --migrateuri & --disks-port Signed-off-by: lcheng --- .../tcp_migrateuri_and_disks_port.cfg | 83 +++++++++++++++++++ .../tcp_migrateuri_and_disks_port.py | 38 +++++++++ 2 files changed, 121 insertions(+) create mode 100644 libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_migrateuri_and_disks_port.cfg create mode 100644 libvirt/tests/src/migration_with_copy_storage/network_data_transport/tcp_migrateuri_and_disks_port.py diff --git a/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_migrateuri_and_disks_port.cfg b/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_migrateuri_and_disks_port.cfg new file mode 100644 index 00000000000..6c6ce6bce11 --- /dev/null +++ b/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_migrateuri_and_disks_port.cfg @@ -0,0 +1,83 @@ +- migration_with_copy_storage.network_data_transport.tcp_migrateuri_and_disks_port: + type = tcp_migrateuri_and_disks_port + migration_setup = 'yes' + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + status_error = "no" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + setup_nfs = "no" + nfs_mount_dir = + ipv6_addr_des = "ENTER.YOUR.IPv6.TRAGET" + variants: + - p2p: + virsh_migrate_options = '--live --p2p --verbose' + - non_p2p: + virsh_migrate_options = '--live --verbose' + variants: + - copy_storage_all: + copy_storage_option = "--copy-storage-all" + variants: + - migrateuri: + variants: + - ipv4_addr_and_port: + migrateuri_port = "49777" + variants: + - default_port: + virsh_migrate_extra = "--migrateuri tcp://${migrate_dest_host}:${migrateuri_port}" + check_patterns = [r'ESTAB .*${migrate_dest_host}\]:${migrateuri_port}', r'ESTAB .*${migrate_dest_host}\]:49152'] + - valid_port: + disks_port = "49888" + virsh_migrate_extra = "--migrateuri tcp://${migrate_dest_host}:${migrateuri_port} --disks-port ${disks_port}" + check_patterns = [r'ESTAB .*${migrate_dest_host}\]:${migrateuri_port}', r'ESTAB .*${migrate_dest_host}\]:${disks_port}'] + - ipv6_addr_and_port: + migrateuri_port = "49777" + variants: + - default_port: + virsh_migrate_extra = "--migrateuri tcp://[${ipv6_addr_des}]:${migrateuri_port}" + check_patterns = [r'ESTAB .*\[${ipv6_addr_des}\]:49152', r'ESTAB .*\[${ipv6_addr_des}\]:${migrateuri_port}'] + - valid_port: + disks_port = "49888" + virsh_migrate_extra = "--migrateuri tcp://[${ipv6_addr_des}]:${migrateuri_port} --disks-port ${disks_port}" + check_patterns = [r'ESTAB .*\[${ipv6_addr_des}\]:${migrateuri_port}', r'ESTAB .*\[${ipv6_addr_des}\]:${disks_port}'] + - ipv4_addr: + variants: + - default_port: + check_patterns = [r'ESTAB .*${migrate_dest_host}\]:49152', r'ESTAB .*${migrate_dest_host}\]:49153'] + virsh_migrate_extra = "--migrateuri tcp://${migrate_dest_host}" + - valid_port: + disks_port = "49888" + check_patterns = [r'ESTAB .*${migrate_dest_host}\]:49152', r'ESTAB .*${migrate_dest_host}\]:${disks_port}'] + virsh_migrate_extra = "--migrateuri tcp://${migrate_dest_host} --disks-port ${disks_port}" + action_during_mig = '[{"func": "libvirt_network.check_sockets_statistics", "after_event": "block-job", "func_param": {"server_ip": "${server_ip}", "server_user": "${server_user}", "server_pwd": "${server_pwd}", "check_patterns": "${check_patterns}"}, "wait_for_after_event_timeout": "600"}]' + - invalid_migrateuri: + status_error = "yes" + migrateuri_port = "49777" + virsh_migrate_extra = "--migrateuri tcp://10.10.10.10:${migrateuri_port}" + err_msg = "'blockdev-add'.* Connection timed out" + - invalid_disks_port: + status_error = "yes" + variants: + - no_permission_port: + virsh_migrate_extra = "--migrateuri tcp://${migrate_dest_host} --disks-port 1000" + err_msg = "unable to execute QEMU command 'nbd-server-start': Failed to bind socket: Permission denied" + - libvirt_reserved_port: + virsh_migrate_extra = "--migrateuri tcp://${migrate_dest_host} --disks-port 49152" + err_msg = "error: internal error: Failed to reserve port 49152" diff --git a/libvirt/tests/src/migration_with_copy_storage/network_data_transport/tcp_migrateuri_and_disks_port.py b/libvirt/tests/src/migration_with_copy_storage/network_data_transport/tcp_migrateuri_and_disks_port.py new file mode 100644 index 00000000000..807a90df9a7 --- /dev/null +++ b/libvirt/tests/src/migration_with_copy_storage/network_data_transport/tcp_migrateuri_and_disks_port.py @@ -0,0 +1,38 @@ +from provider.migration import base_steps + + +def run(test, params, env): + """ + To verify that the ip and port for copying storage can be specified by + --migrateuri and --disks-port respectively. + This cases starts vm with local storage, then do live migration with + copying storage with virsh options --migrateuri and --disks-port, + and checks the migration ip and port during migration. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + vm_name = params.get("migrate_main_vm") + migrateuri_port = params.get("migrateuri_port") + disks_port = params.get("disks_port") + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + migration_obj.setup_connection() + if migrateuri_port: + migration_obj.remote_add_or_remove_port(migrateuri_port) + if disks_port: + migration_obj.remote_add_or_remove_port(disks_port) + base_steps.prepare_disks_remote(params, vm) + migration_obj.run_migration() + migration_obj.verify_default() + finally: + if migrateuri_port: + migration_obj.remote_add_or_remove_port(migrateuri_port, add=False) + if disks_port: + migration_obj.remote_add_or_remove_port(disks_port, add=False) + migration_obj.cleanup_connection() + base_steps.cleanup_disks_remote(params, vm) From ba3b736ab209bbecd263a09e547c234408f4c810 Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 26 Dec 2023 15:25:29 +0800 Subject: [PATCH 0225/1055] migration: Update listen_address case Since libvirt_network.check_listen_address() function is updated, so update listen_address case. Signed-off-by: lcheng --- .../tcp_listen_address.cfg | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_listen_address.cfg b/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_listen_address.cfg index a68e27b2e50..3bbd925485f 100644 --- a/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_listen_address.cfg +++ b/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tcp_listen_address.cfg @@ -24,9 +24,11 @@ migrate_desturi_port = "16509" migrate_desturi_type = "tcp" virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" - action_during_mig = '[{"func": "libvirt_network.check_listen_address", "func_param": "params", "need_sleep_time": "5"}]' setup_nfs = "no" nfs_mount_dir = + setup_local_nfs = "no" + storage_type = "" + start_vm = "yes" variants: - p2p: virsh_migrate_options = '--live --p2p --verbose' @@ -34,24 +36,27 @@ virsh_migrate_options = '--live --verbose' variants: - target_ipv4_address: - listen_address = "${migrate_dest_host}" + check_patterns = [r'LISTEN .*${migrate_dest_host}'] virsh_migrate_extra = "--listen-address ${migrate_dest_host}" + action_during_mig = '[{"func": "libvirt_network.check_sockets_statistics", "func_param": {"server_ip": "${server_ip}", "server_user": "${server_user}", "server_pwd": "${server_pwd}", "check_patterns": "${check_patterns}"}, "need_sleep_time": "5"}]' - target_ipv6_address: ipv6_config = "yes" ipv6_addr_des = "ENTER.YOUR.IPv6.TRAGET" - listen_address = "${ipv6_addr_des}" + check_patterns = [r'LISTEN .*${ipv6_addr_des}'] virsh_migrate_extra = "--migrateuri tcp://[${ipv6_addr_des}] --listen-address ${ipv6_addr_des}" + action_during_mig = '[{"func": "libvirt_network.check_sockets_statistics", "func_param": {"server_ip": "${server_ip}", "server_user": "${server_user}", "server_pwd": "${server_pwd}", "check_patterns": "${check_patterns}"}, "need_sleep_time": "5"}]' - all_ipv4: - listen_address = "0.0.0.0" - virsh_migrate_extra = "--listen-address ${listen_address}" + check_patterns = [r'LISTEN .*0.0.0.0'] + virsh_migrate_extra = "--listen-address 0.0.0.0" + action_during_mig = '[{"func": "libvirt_network.check_sockets_statistics", "func_param": {"server_ip": "${server_ip}", "server_user": "${server_user}", "server_pwd": "${server_pwd}", "check_patterns": "${check_patterns}"}, "need_sleep_time": "5"}]' - all_ipv6: - listen_address = "*" + check_patterns = [r'LISTEN .*\*'] virsh_migrate_extra = "--listen-address ::" + action_during_mig = '[{"func": "libvirt_network.check_sockets_statistics", "func_param": {"server_ip": "${server_ip}", "server_user": "${server_user}", "server_pwd": "${server_pwd}", "check_patterns": "${check_patterns}"}, "need_sleep_time": "5"}]' - invalid_address: status_error = "yes" err_msg = "nbd-server-start.*Cannot assign requested address" - listen_address = "10.10.10.10" - virsh_migrate_extra = "--listen-address ${listen_address}" + virsh_migrate_extra = "--listen-address 10.10.10.10" variants: - copy_storage_all: copy_storage_option = "--copy-storage-all" From fa73b1d00be7e558bf3558962f1d7137c7ef6879 Mon Sep 17 00:00:00 2001 From: nanli Date: Mon, 4 Mar 2024 11:56:57 +0800 Subject: [PATCH 0226/1055] update version for memory only snap case xxxx-298190:delete memory only snapshot, it is a new case copied from a old case and only get a new version as snap rfe case in polarion, and the old case was set to be inactive. Signed-off-by: nanli --- libvirt/tests/cfg/snapshot/memory_snapshot_delete.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/snapshot/memory_snapshot_delete.cfg b/libvirt/tests/cfg/snapshot/memory_snapshot_delete.cfg index 4e4f45b0fb8..f31a376fc95 100644 --- a/libvirt/tests/cfg/snapshot/memory_snapshot_delete.cfg +++ b/libvirt/tests/cfg/snapshot/memory_snapshot_delete.cfg @@ -4,7 +4,7 @@ start_vm = no snapshot_disk_list = "[{'disk_name': 'vda', 'disk_snapshot': 'no'}, {'disk_name': 'vdb', 'disk_snapshot': 'no'}]" snapshot_dict = {'description': 'Snapshot test', 'snap_name': '%s', 'mem_snap_type': 'external', 'mem_file': '%s'} - func_supported_since_libvirt_ver = (9, 0, 0) + func_supported_since_libvirt_ver = (9, 10, 0) variants disk_format: - type_qcow2: disk_driver = {'driver': {'name': 'qemu', 'type': 'qcow2'}} From a754b26936e4e3387b6286c4fac39cacf06d01c9 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Tue, 12 Mar 2024 02:55:47 -0400 Subject: [PATCH 0227/1055] Fix attach-detach disk failure libvirt.create_disk_xml() return embedded object xml, and the parent object: disk_xml may be gc quickly because there is no reference to it libvirt_disk.create_primitive_disk_xml() return disk_xml itself, since it is assigned to one variable and the reference count is not zero, so it is not gced soon. Signed-off-by: chunfuwen --- .../virsh_cmd/domain/virsh_attach_device_matrix.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_attach_device_matrix.py b/libvirt/tests/src/virsh_cmd/domain/virsh_attach_device_matrix.py index 2efa57612af..18f283d045f 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_attach_device_matrix.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_attach_device_matrix.py @@ -7,6 +7,7 @@ from virttest import data_dir from virttest import utils_misc from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_disk from virttest.utils_test import libvirt @@ -225,11 +226,11 @@ def check_result(disk_source, disk_type, disk_target, libvirt.create_local_disk("file", device_source, "1") # Get disk xml file. - disk_params = {'type_name': "file", 'device_type': device, - 'target_dev': device_target, 'target_bus': "virtio", - 'source_file': device_source, 'driver_name': "qemu", - 'driver_type': "raw"} - disk_xml = libvirt.create_disk_xml(disk_params) + disk_xml_obj = libvirt_disk.create_primitive_disk_xml( + "file", device, + device_target, "virtio", + "raw", {"attrs": {"file": device_source}}, None) + disk_xml = disk_xml_obj.xml # Copy disk xml for virsh.detach in the following code new_xml_path = os.path.join(data_dir.get_tmp_dir(), "disk_copy.xml") From 11454bdb9e72a658bbf3587a1f2a7ba11797b20e Mon Sep 17 00:00:00 2001 From: Meina Li Date: Tue, 12 Mar 2024 04:35:47 -0400 Subject: [PATCH 0228/1055] incremental_backup: fix timeout issue of dd commands in guest Now the written size in guest is big that it may cause timeout sometimes: Timeout expired while waiting for shell command to complete: 'dd if=/dev/urandom of=/dev/vdb bs=1M seek=10 count=4000; sync'. This PR mainly reduce the size. Signed-off-by: Meina Li --- .../cfg/incremental_backup/incremental_backup_push_mode.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg b/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg index eb3d2f89a97..df50fe64402 100644 --- a/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg +++ b/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg @@ -34,12 +34,12 @@ only original_disk_local.coldplug_disk.backup_to_raw.backup_to_block expect_backup_canceled = "yes" original_disk_size = "5000M" - dd_count = "4000" + dd_count = "2000" - kill_qemu: only original_disk_local.hotplug_disk.backup_to_qcow2.backup_to_block expect_backup_canceled = "yes" original_disk_size = "5000M" - dd_count = "4000" + dd_count = "2000" - positive_test: variants: - backup_to_qcow2: From fe55d8e850e3e98196ec6ded41e19ca3ee0f0efc Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 12 Mar 2024 17:17:28 +0800 Subject: [PATCH 0229/1055] sriov: Update to remove vfio module The module list needs to update on some drivers, so update to remove 'vfio' module directly. Signed-off-by: Yingshun Cui --- .../sriov_attach_detach_interface_special_situations.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/src/sriov/plug_unplug/sriov_attach_detach_interface_special_situations.py b/libvirt/tests/src/sriov/plug_unplug/sriov_attach_detach_interface_special_situations.py index ebe0f4c2698..b6496258413 100644 --- a/libvirt/tests/src/sriov/plug_unplug/sriov_attach_detach_interface_special_situations.py +++ b/libvirt/tests/src/sriov/plug_unplug/sriov_attach_detach_interface_special_situations.py @@ -27,10 +27,8 @@ def setup_test(): debug=True, ignore_status=False) elif test_scenario == "module_auto_reload": - modules = ["vfio_pci", "vfio_iommu_type1"] - test.log.info("TEST_SETUP: Remove modules: %s." % modules) - for module_name in modules: - KernelModuleHandler(module_name).unload_module() + test.log.info("TEST_SETUP: Remove vfio module.") + KernelModuleHandler("vfio").unload_module() def check_vm_iface_after_detaching(test_scenario): """ From 7f133be699db9a3d402ce1020e47d13b26332626 Mon Sep 17 00:00:00 2001 From: Yan Fu Date: Tue, 12 Mar 2024 21:24:25 +0800 Subject: [PATCH 0230/1055] Fix issues with virtio_page_per_vq testcases 1. It's not reasonable to start guest without disk device. 2. There are 2 input devices by default both starting the guest directly and hotplugging Signed-off-by: Yan Fu --- libvirt/tests/src/virtio/virtio_page_per_vq.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/virtio/virtio_page_per_vq.py b/libvirt/tests/src/virtio/virtio_page_per_vq.py index 45fa5ae8ab5..daa7d7f1e41 100644 --- a/libvirt/tests/src/virtio/virtio_page_per_vq.py +++ b/libvirt/tests/src/virtio/virtio_page_per_vq.py @@ -4,6 +4,7 @@ from virttest import libvirt_version from virttest import utils_net from virttest import virsh +from virttest.utils_test import libvirt from virttest.libvirt_xml import vm_xml from virttest.libvirt_xml.devices.controller import Controller # pylint: disable=W0611 from virttest.libvirt_xml.devices.disk import Disk # pylint: disable=W0611 @@ -13,6 +14,7 @@ from virttest.libvirt_xml.devices.memballoon import Memballoon # pylint: disable=W0611 from virttest.libvirt_xml.devices.rng import Rng # pylint: disable=W0611 from virttest.libvirt_xml.devices.video import Video # pylint: disable=W0611 +from virttest.utils_test import libvirt def run(test, params, env): @@ -29,7 +31,8 @@ def prepare_test(vmxml): :params vmxml: the vm xml """ - vmxml.remove_all_device_by_type(device_type) + if not ((device_type == "disk" and hotplug) or device_type == "input"): + vmxml.remove_all_device_by_type(device_type) # For now, arm can not create USB controller automatically. if device_type == "controller" and platform.machine() == 'aarch64': usb_controller = Controller("controller") @@ -44,6 +47,12 @@ def prepare_test(vmxml): vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) # Prepare device xml by using device function, for example, Disk(). device_obj = device_type.capitalize() + if device_type == "disk" and hotplug: + disk_image_path = os.path.join(os.path.dirname(disk_image), "base.qcow2") + libvirt.create_local_disk( + "file", path=disk_image_path, + size="1G", disk_format="qcow2") + device_dict['source']['attrs']['file'] = disk_image_path if device_type == "input": device_xml = eval(device_obj)(input_type) else: @@ -91,11 +100,13 @@ def check_attribute(): af_vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) test.log.info("The current dumpxml is %s", virsh.dumpxml(af_vmxml)) # Keyboard and mouse input will be default in guest. So identify input device. - if device_type == "input" and hotplug: + if device_type == "input": dev_xml = af_vmxml.get_devices(device_type)[2] # Guest has many controllers, so also need to identify it. elif device_type == "controller": dev_xml = af_vmxml.get_devices(device_type) + elif device_type == "disk" and hotplug: + dev_xml = af_vmxml.get_devices(device_type)[1] else: dev_xml = af_vmxml.get_devices(device_type)[0] # Select the virtio-scsi/virtio-serial controller from all controllers From 6caa84da9a1864f6c0ed47cd5dc01b61fef912dd Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 12 Mar 2024 09:55:13 -0400 Subject: [PATCH 0231/1055] virsh_snapshot_disk: log vm state Sometimes tests in CI fail with """ error: XML error: memory state cannot be saved with offline or disk-only snapshot. """ but I cannot reproduce it. I assume the VM is not in the correct state as disk-only snasphot is not requested in the test case. Log the VM state before running the snapshot-create command to check it next time the issue arises. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/virsh_cmd/snapshot/virsh_snapshot_disk.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libvirt/tests/src/virsh_cmd/snapshot/virsh_snapshot_disk.py b/libvirt/tests/src/virsh_cmd/snapshot/virsh_snapshot_disk.py index b54105d8da5..bc0cf61e566 100644 --- a/libvirt/tests/src/virsh_cmd/snapshot/virsh_snapshot_disk.py +++ b/libvirt/tests/src/virsh_cmd/snapshot/virsh_snapshot_disk.py @@ -288,6 +288,7 @@ def run(test, params, env): if vm_state == "shut off": vm.destroy(gracefully=False) + logging.debug("VM state: %s", vm.state()) snapshot_result = virsh.snapshot_create( vm_name, options, debug=True) out_err = snapshot_result.stderr.strip() @@ -320,6 +321,7 @@ def run(test, params, env): if match_cluster_size not in img_info: test.fail("%s snapshot image doesn't have the same cluster size with backing file" % disk_path) else: + logging.debug("VM state: %s", vm.state()) snapshot_result = virsh.snapshot_create(vm_name, options, debug=True) if snapshot_result.exit_status: @@ -338,6 +340,7 @@ def run(test, params, env): # update an element new_snap.creation_time = snapshot_name snapshot_xml_path = new_snap.xml + logging.debug("VM state: %s", vm.state()) options += "--redefine %s --current" % snapshot_xml_path snapshot_result = virsh.snapshot_create(vm_name, options, debug=True) From c7523716832c5187e3df5be9968005bf83284d7a Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 20 Feb 2024 08:45:14 -0500 Subject: [PATCH 0232/1055] cpu/topology: add topology hotplug test Add new test case. There are some tests under guestpin but they are mostly PPC specific. This test was added for minimal coverage of newly introduced s390x guest topology on qemu level but libvirt level currently is still missing full support. We can add more tests in this script (e.g. pin cpu, coldplug, lifecycle) later. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/cpu/topology.cfg | 15 ++++++++ libvirt/tests/src/cpu/topology.py | 57 ++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 libvirt/tests/cfg/cpu/topology.cfg create mode 100644 libvirt/tests/src/cpu/topology.py diff --git a/libvirt/tests/cfg/cpu/topology.cfg b/libvirt/tests/cfg/cpu/topology.cfg new file mode 100644 index 00000000000..eb86f4b15d4 --- /dev/null +++ b/libvirt/tests/cfg/cpu/topology.cfg @@ -0,0 +1,15 @@ +- topology: + type = topology + only Linux + start_vm = no + current_vcpus = 4 + max_vcpus = 4 + cores = 2 + threads = 1 + sockets = 2 + variants: + - positive: + variants: + - hotplug: + current_vcpus = 3 + diff --git a/libvirt/tests/src/cpu/topology.py b/libvirt/tests/src/cpu/topology.py new file mode 100644 index 00000000000..3af517fefe2 --- /dev/null +++ b/libvirt/tests/src/cpu/topology.py @@ -0,0 +1,57 @@ +import logging +import re +import time + +from virttest import virsh +from virttest.libvirt_xml import VMXML + +LOG = logging.getLogger('avocado.' + __name__) + + +def get_cpus(session): + """ + Retrieves the CPU extended info + + :param session: VM session + """ + output = session.cmd_output("lscpu --extended") + LOG.debug("VM cpus:\n%s", output) + return [x for x in output.split("\n") if re.match(r"^\s+\d\s", x)] + + +def run(test, params, env): + """ + Confirm hotplugged VPCU is available and placed in topology. + + :param test: QEMU test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + + vm_name = params.get("main_vm") + max_vcpus = int(params.get("max_vcpus")) + current_vcpus = int(params.get("current_vcpus")) + cores = int(params.get("cores")) + threads = int(params.get("threads")) + sockets = int(params.get("sockets")) + vm = env.get_vm(vm_name) + vmxml = VMXML.new_from_inactive_dumpxml(vm_name) + orig_xml = vmxml.copy() + hotplug = current_vcpus != max_vcpus + + try: + VMXML.set_vm_vcpus(vm_name, max_vcpus, current_vcpus, + sockets, cores, threads, add_topology=True) + vm.start() + with vm.wait_for_login() as session: + cpus = get_cpus(session) + if current_vcpus != len(cpus): + test.fail("Unexpected number of cpus in guest: %s" % len(cpus)) + if hotplug: + virsh.setvcpus(vm_name, max_vcpus) + time.sleep(5) + cpus = get_cpus(session) + if max_vcpus != len(cpus): + test.fail("Unexpected number of cpus in guest: %s" % len(cpus)) + finally: + orig_xml.sync() From 8504d5fc4acb7da5f6e2539cac8b41f785ffa3dd Mon Sep 17 00:00:00 2001 From: Yan Fu Date: Wed, 13 Mar 2024 11:19:45 +0800 Subject: [PATCH 0233/1055] passt..detach: wait for guest os booting before detaching Signed-off-by: Yan Fu --- libvirt/tests/src/virtual_network/passt/passt_attach_detach.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py index be12ffd6c1e..61d2a81f15f 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py +++ b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py @@ -155,6 +155,8 @@ def run(test, params, env): LOG.debug(f'vmxml before detach:\n{vmxml}') iface_to_detach = vmxml.get_devices('interface')[0] mac = iface_to_detach.mac_address + # Wait for guest os to boot completely before detaching interface + vm.wait_for_serial_login(timeout=60).close() virsh.detach_device(vm_name, iface_to_detach.xml, wait_for_event=True, event_timeout=15, From 2646373675ada04c06e507a1d261cd6532797707 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Wed, 13 Mar 2024 17:25:23 +0800 Subject: [PATCH 0234/1055] v2v:delete esx6.0/6.5/6.7 from cfg files Signed-off-by: vwu-vera --- v2v/tests/cfg/convert_vm_to_libvirt.cfg | 10 ---------- v2v/tests/cfg/convert_vm_to_ovirt.cfg | 10 ---------- v2v/tests/cfg/function_test_esx.cfg | 10 ++-------- 3 files changed, 2 insertions(+), 28 deletions(-) diff --git a/v2v/tests/cfg/convert_vm_to_libvirt.cfg b/v2v/tests/cfg/convert_vm_to_libvirt.cfg index a274d745736..e61d6dff340 100644 --- a/v2v/tests/cfg/convert_vm_to_libvirt.cfg +++ b/v2v/tests/cfg/convert_vm_to_libvirt.cfg @@ -177,16 +177,6 @@ - 7_0: only source_esx.esx_70 esx_version = "esx7.0" - - 6_7: - only source_esx.esx_67 - esx_version = "esx6.7" - - 6_5: - only source_esx.esx_65 - esx_version = "esx6.5" - - 6_0: - only source_esx.esx_60 - esx_version = "esx6.0" - no win11,win2022,latest9 hostname = ${esx_hostname} variants: - vm: diff --git a/v2v/tests/cfg/convert_vm_to_ovirt.cfg b/v2v/tests/cfg/convert_vm_to_ovirt.cfg index 6292337d521..b53e711d0fb 100644 --- a/v2v/tests/cfg/convert_vm_to_ovirt.cfg +++ b/v2v/tests/cfg/convert_vm_to_ovirt.cfg @@ -209,16 +209,6 @@ - 7_0: only source_esx.esx_70 esx_version = "esx7.0" - - 6_7: - only source_esx.esx_67 - esx_version = "esx6.7" - - 6_5: - only source_esx.esx_65 - esx_version = "esx6.5" - - 6_0: - only source_esx.esx_60 - no win11,win2022,latest9 - esx_version = "esx6.0" hostname = ${vpx_hostname} variants: - vm: diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 44aa8ada03e..18f6baf0382 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -67,12 +67,6 @@ - rhv: output_method = "rhev" variants: - - esx_60: - only source_esx.esx_60 - - esx_65: - only source_esx.esx_65 - - esx_67: - only source_esx.esx_67 - esx_70: only source_esx.esx_70 - esx_80: @@ -348,8 +342,8 @@ checkpoint = "vmtools,service service_name = vmware-tools - modprobe: - only esx_60 - main_vm = VM_NAME_RHEL5_V2V_EXAMPLE + only esx_70 + main_vm = VM_NAME_RHEL6_V2V_EXAMPLE enable_legacy_policy = yes checkpoint = modprobe cfg_content = 'alias eth0 virtio_net' From b7024489b498c5bbb24644ee748cc8d55cadc56e Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Wed, 13 Mar 2024 06:12:52 -0400 Subject: [PATCH 0235/1055] Fixup: login timeout of virtio_page_per_vq test The line of vm login is not to create a session, but to wait for vm to bootup. Therefore replace it with serial login to solve the problem. Signed-off-by: Haijiao Zhao --- libvirt/tests/src/virtio/virtio_page_per_vq.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/virtio/virtio_page_per_vq.py b/libvirt/tests/src/virtio/virtio_page_per_vq.py index 45fa5ae8ab5..59a220ec1ce 100644 --- a/libvirt/tests/src/virtio/virtio_page_per_vq.py +++ b/libvirt/tests/src/virtio/virtio_page_per_vq.py @@ -67,7 +67,9 @@ def run_test(device_xml, vmxml): test.log.info("TEST_STEP1: hotplug %s device", device_type) start_guest() virsh.attach_device(vm_name, device_xml.xml, ignore_status=False, debug=True) - vm.wait_for_login() + vm.cleanup_serial_console() + vm.create_serial_console() + vm.wait_for_serial_login().close() test.log.info("TEST_STEP2: check the attribute in %s xml", device_type) check_attribute() @@ -120,7 +122,7 @@ def start_guest(): """ test.log.info("Start the guest") if not vm.is_alive(): - virsh.start(vm_name, ignore_status=False, debug=True) + vm.start() vm_name = params.get("main_vm") device_type = params.get("device_type") From 89bade8c3d64062be98d5129e06cebae4ad23093 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Thu, 14 Mar 2024 01:11:24 -0400 Subject: [PATCH 0236/1055] Fix setpool virt_qemu_ga_read_nonsecurity_files timeout issue virt_qemu_ga_read_nonsecurity_files need reboot guest, it takes more time to finish this in some extreme case Signed-off-by: chunfuwen --- libvirt/tests/src/virsh_cmd/domain/virsh_domfstrim.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_domfstrim.py b/libvirt/tests/src/virsh_cmd/domain/virsh_domfstrim.py index 76edd2b1a53..7535ce8f92d 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_domfstrim.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_domfstrim.py @@ -27,7 +27,7 @@ def try_set_selinux_label(session): :param session: VM console session """ - session.cmd_output("setsebool -P virt_qemu_ga_read_nonsecurity_files on") + session.cmd_output("setsebool -P virt_qemu_ga_read_nonsecurity_files on", timeout=120) def run(test, params, env): From 3ca2420089c206cea89a4db2a20f298c9c030597 Mon Sep 17 00:00:00 2001 From: Hu Shuai Date: Fri, 2 Feb 2024 14:19:04 +0800 Subject: [PATCH 0237/1055] numa: Enable test for ARM 16G hugepage memory There are relatively few arm machines with 2 numa nodes that can allocate 16G large pages, so the test for 16G hugepage memory was adjusted to the machine with one numa node. Signed-off-by: Hu Shuai --- .../cfg/numa/host_numa/host_numa_info.cfg | 5 +++ .../src/numa/host_numa/host_numa_info.py | 32 +++++++++++++------ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/libvirt/tests/cfg/numa/host_numa/host_numa_info.cfg b/libvirt/tests/cfg/numa/host_numa/host_numa_info.cfg index da05de13e23..62763d494ed 100644 --- a/libvirt/tests/cfg/numa/host_numa/host_numa_info.cfg +++ b/libvirt/tests/cfg/numa/host_numa/host_numa_info.cfg @@ -8,3 +8,8 @@ allocate_dict = {2048: 200, 1048576: 2} aarch64: allocate_dict = {2048: 200, 524288: 4} + - 16G: + only aarch64 + required_kernel = [5.14.0,) + expect_nodes_num = 1 + allocate_dict = {16777216: 1} diff --git a/libvirt/tests/src/numa/host_numa/host_numa_info.py b/libvirt/tests/src/numa/host_numa/host_numa_info.py index df063ab7d26..4f07ec13dde 100644 --- a/libvirt/tests/src/numa/host_numa/host_numa_info.py +++ b/libvirt/tests/src/numa/host_numa/host_numa_info.py @@ -18,7 +18,9 @@ def setup_default(test_obj): :param test_obj: NumaTest object """ - test_obj.setup() + expect_nodes_num = test_obj.params.get("expect_nodes_num", 2) + test_obj.params['expect_nodes_num'] = int(expect_nodes_num) + test_obj.setup(expect_nodes_num=int(expect_nodes_num)) test_obj.test.log.debug("Step: setup is done") @@ -31,6 +33,12 @@ def allocate_memory_on_host_nodes(test_obj): like {'2048': '100', '1048576': '1'} """ def _allocate_test(page_num, node_id, page_size): + # Drop caches to clean some usable memory + with open("/proc/sys/vm/drop_caches", "w") as caches: + caches.write('3') + # Compact memory to get more continual memory + with open("/proc/sys/vm/compact_memory", "w") as memory: + memory.write('1') hpc.set_node_num_huge_pages(page_num, node_id, page_size, ignore_error=True) allocated_num = hpc.get_node_num_huge_pages(node_id, page_size) if allocated_num < 1: @@ -231,26 +239,30 @@ def verify_node_mem_by_freepages_various_unit(test_obj): """ allocate_result = test_obj.params['allocate_result'] all_nodes = test_obj.online_nodes_withmem - for pgsize in allocate_result[all_nodes[1]].keys(): + if test_obj.params['expect_nodes_num'] == 1: + target_node = all_nodes[0] + else: + target_node = all_nodes[1] + for pgsize in allocate_result[target_node].keys(): common_test_freepages(test_obj, - all_nodes[1], - pgsize, allocate_result[all_nodes[1]][pgsize]) + target_node, + pgsize, allocate_result[target_node][pgsize]) common_test_freepages(test_obj, - all_nodes[1], + target_node, pgsize, - allocate_result[all_nodes[1]][pgsize], + allocate_result[target_node][pgsize], size_unit='KiB') if int(pgsize) >= 1024: common_test_freepages(test_obj, - all_nodes[1], + target_node, int(pgsize)//1024, - allocate_result[all_nodes[1]][pgsize], + allocate_result[target_node][pgsize], size_unit='M') if int(pgsize) >= (1024*1024): common_test_freepages(test_obj, - all_nodes[1], + target_node, int(pgsize)//(1024*1024), - allocate_result[all_nodes[1]][pgsize], + allocate_result[target_node][pgsize], size_unit='G') test_obj.test.log.debug("Verify huge page memory info on " "the first host numa node with different " From ec2866e69a8897c6f1170588ea6d735135e64fa3 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Thu, 14 Mar 2024 22:03:12 -0400 Subject: [PATCH 0238/1055] Skip ipv6 default route check with multipath route Some systems has ipv6 multipath route which will cause the passt check fail since passt can not recognize the format of it. Skip this check. Signed-off-by: Yalan Zhang --- provider/virtual_network/passt.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/provider/virtual_network/passt.py b/provider/virtual_network/passt.py index 808e7597e8b..f1a2eb6f4bc 100644 --- a/provider/virtual_network/passt.py +++ b/provider/virtual_network/passt.py @@ -248,23 +248,23 @@ def check_default_gw(session, host_iface=None): vm_gw = utils_net.get_default_gateway(session=session, force_dhcp=True).split() LOG.debug(f'Host and vm default ipv4 gateway: {host_gw}, {vm_gw}') + if [x for x in vm_gw if x not in host_gw]: + raise exceptions.TestFail( + 'Host default ipv4 gateway not consistent with vm.') + _host_gw_v6 = utils_net.get_default_gateway(ip_ver='ipv6', target_iface=host_iface) + if not _host_gw_v6: + LOG.debug("Skip ipv6 route check as host has no default route or has " + "multipath route which passt can not recognize!") + return _vm_gw_v6 = utils_net.get_default_gateway(session=session, ip_ver='ipv6') - if not _host_gw_v6 or not _vm_gw_v6: - raise exceptions.TestFail( - 'Cannot recognize ipv6 multipath router!') + if not _vm_gw_v6: + raise exceptions.TestFail('Guest has no ipv6 gateway!') host_gw_v6 = _host_gw_v6.split() vm_gw_v6 = _vm_gw_v6.split() LOG.debug(f'Host and vm default ipv6 gateway: {host_gw_v6}, {vm_gw_v6}') - if [x for x in vm_gw if x not in host_gw]: - raise exceptions.TestFail( - 'Host default ipv4 gateway not consistent with vm.') - if not host_gw_v6: - LOG.debug("Skip ipv6 route check as host has multipath ipv6 route " - "which Passt can not recognize.") - return if [x for x in vm_gw_v6 if x not in host_gw_v6]: raise exceptions.TestFail( 'Host default ipv6 gateway not consistent with vm.') From d2721924803ce7cc5f8c54540aa5153ad3adcf16 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Fri, 15 Mar 2024 05:09:35 -0400 Subject: [PATCH 0239/1055] Fixup:cannot find message in log Expand the search scope to find expected message. Signed-off-by: Haijiao Zhao --- libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py b/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py index 09509cb194c..5fcbaec4238 100644 --- a/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py +++ b/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py @@ -775,7 +775,7 @@ def check_record_save_restore_guest_log(): "Error: %s" % str(detail)) # Check the new VM start log is appended to the end of the VM log file. if not with_console_log: - check_info_in_vm_log_file(vm_name, guest_log_file, cmd="tail -n 5", + check_info_in_vm_log_file(vm_name, guest_log_file, matchedMsg="char device redirected to /dev/pts") finally: From cc51ffbe115b9f8b21d3bfd84d78cd68dee82917 Mon Sep 17 00:00:00 2001 From: Xiaodai Wang Date: Fri, 15 Mar 2024 18:02:32 +0800 Subject: [PATCH 0240/1055] Serial: Add a case for testing system-serial on aarch64 On arrch64, system-serial is supported. Signed-off-by: Xiaodai Wang --- libvirt/tests/cfg/serial/serial_functional.cfg | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libvirt/tests/cfg/serial/serial_functional.cfg b/libvirt/tests/cfg/serial/serial_functional.cfg index 1e22c394d95..678bc94ffbc 100644 --- a/libvirt/tests/cfg/serial/serial_functional.cfg +++ b/libvirt/tests/cfg/serial/serial_functional.cfg @@ -48,6 +48,10 @@ no s390-virtio serial_dev_type = pty target_type = pci-serial + - type_pty_system_serial: + only aarch64 + serial_dev_type = pty + target_type = system-serial - type_spicevmc: serial_dev_type = spicevmc - type_spiceport: From 51d150a285b0e1d719050f4195bab5b65cbeb4b3 Mon Sep 17 00:00:00 2001 From: Xiaodai Wang Date: Fri, 15 Mar 2024 20:19:59 +0800 Subject: [PATCH 0241/1055] fix cannot access '/dev/input/event*': No such file or directory Some host don't have input devices. So no /dev/input/event* files exist. If that happens, we just return test error. Signed-off-by: Xiaodai Wang --- .../tests/src/virsh_cmd/domain/virsh_detach_device_alias.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py b/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py index 0a3d047574c..8e49ca4a2ce 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py @@ -266,7 +266,9 @@ def start_usbredirserver(): vmxml.remove_all_device_by_type('input') input_dict.update({"alias": {"name": device_alias}}) if input_type == "passthrough": - event = process.run("ls /dev/input/event*", shell=True).stdout + event = process.run("ls /dev/input/event*", shell=True, ignore_status=True).stdout + if len(event) == 0: + test.error("Not found any input devices") input_dict.update({"source_evdev": event.decode('utf-8').split()[0]}) input_obj = Input(type_name=input_type) From e93ee58bdbacce59bf71b3871650c3ad643c8e6c Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Fri, 15 Mar 2024 10:54:37 -0400 Subject: [PATCH 0242/1055] seclabel/serial: disable unsupported hotplug scenario SCLP serial doesn't support hotplug. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/svirt/selinux/selinux_seclabel_per_device.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/cfg/svirt/selinux/selinux_seclabel_per_device.cfg b/libvirt/tests/cfg/svirt/selinux/selinux_seclabel_per_device.cfg index 7497aaa766b..b04262880b4 100644 --- a/libvirt/tests/cfg/svirt/selinux/selinux_seclabel_per_device.cfg +++ b/libvirt/tests/cfg/svirt/selinux/selinux_seclabel_per_device.cfg @@ -7,6 +7,7 @@ - cold_plug: - hot_plug: serial: + no s390-virtio func_supported_since_libvirt_ver = (8, 7, 0) variants test_device: - disk: From 39c2b80e8f93df3214eab4c49bcc78dc0f8f44a4 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Sun, 17 Mar 2024 23:00:47 -0400 Subject: [PATCH 0243/1055] storage_ceph: update the quotes of ceph variant from '' to "" to match the jobs.yaml. Now the ceph variants in virsh_pool.cfg can't be translated to the values in jobs.yaml. That's because the quotes of ceph variant are different between cfg file and jobs.yaml. Signed-off-by: Meina Li --- libvirt/tests/cfg/storage/virsh_pool.cfg | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/cfg/storage/virsh_pool.cfg b/libvirt/tests/cfg/storage/virsh_pool.cfg index 8a51c3109b7..49f688c3756 100644 --- a/libvirt/tests/cfg/storage/virsh_pool.cfg +++ b/libvirt/tests/cfg/storage/virsh_pool.cfg @@ -17,12 +17,12 @@ pool_type = 'rbd' required_commands = "['parallel', 'rbd']" auth_key = "EXAMPLE_AUTH_KEY" - auth_user = 'EXAMPLE_AUTH_USER' - client_name = 'EXAMPLE_CLIENT_NAME' - ceph_host_ip = 'EXAMPLE_MON_HOST_AUTHX' + auth_user = "EXAMPLE_AUTH_USER" + client_name = "EXAMPLE_CLIENT_NAME" + ceph_host_ip = "EXAMPLE_MON_HOST_AUTHX" mon_host = "${ceph_host_ip}" - pool_source_name = 'EXAMPLE_POOL_NAME' - pool_name = 'libvirt-rbd-pool' + pool_source_name = "EXAMPLE_POOL_NAME" + pool_name = "libvirt-rbd-pool" image_path = "${pool_source_name}/%s_rbd.img" rbd_image_size = '5M' pool_source_attrs = "'source': {'host_name': '${ceph_host_ip}', 'auth_type': 'ceph', 'auth_username': 'admin', 'vg_name': '${pool_source_name}', 'secret_uuid': '%s'}" From 967451c4aebed2db62e4570e87bd0b4eda7ab23a Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Sun, 17 Mar 2024 23:05:41 -0400 Subject: [PATCH 0244/1055] Add adaption for aarch64 Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/libvirt_mem.cfg | 16 +++++++++----- libvirt/tests/src/libvirt_mem.py | 35 ++++++++++++++++++++++--------- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/libvirt/tests/cfg/libvirt_mem.cfg b/libvirt/tests/cfg/libvirt_mem.cfg index e710b1cbab3..8c397a8005b 100644 --- a/libvirt/tests/cfg/libvirt_mem.cfg +++ b/libvirt/tests/cfg/libvirt_mem.cfg @@ -83,6 +83,7 @@ - no_attach: test_qemu_cmd = "no" - with_source: + max_mem_rt = 2621440 test_qemu_cmd = "no" tg_size = 524288 tg_node = 0 @@ -95,9 +96,6 @@ test_qemu_cmd = "no" test_mem_binding = "no" setup_hugepages = "yes" - huge_page_num = 2000 - pseries: - huge_page_num = 200 max_mem_rt = 25600000 max_mem = "2609152" current_mem = "2609152" @@ -105,7 +103,7 @@ model_fallback = "forbid" tg_size = 524288 tg_node = 0 - page_size = 2048 + total_huge_page_size = 4194304 page_unit = "KiB" node_mask = 0 huge_pages = "{'size':'2048','unit':'KiB','nodeset':'0'}" @@ -134,6 +132,7 @@ memory_addr = "{'type':'dimm','slot':'0','base':'0x100000000'}" node_mask = 0 - without_numa_save_restore: + no x86_64,aarch64 max_mem_rt = 20971520 numa_cells = "" tg_node = "" @@ -173,12 +172,19 @@ - invalid_address: memory_addr = "{'type':'dimm','slot':'1','base':'0x11fffffffff'}" - invalid_vm_node: + define_error = "yes" tg_node = 7 - invalid_host_node: node_mask = 1-3 tg_nddode = 1 page_size = 4 page_unit = "KiB" + - without_numa: + only x86_64,aarch64 + define_error = "yes" + max_mem_rt = 20971520 + numa_cells = "" + tg_node = "" - attach_error: attach_device = "yes" attach_error = "yes" @@ -187,7 +193,6 @@ max_mem_rt = max_mem = numa_cells = - current_mem = 2048000 attach_option = "--config" - attach_invalid_type: memory_addr = "{'type':'diee','slot':'16','base':'0x11fffffffff'}" @@ -238,3 +243,4 @@ - with_numa: set_max_mem = "2560001" max_mem_option = "--config" + diff --git a/libvirt/tests/src/libvirt_mem.py b/libvirt/tests/src/libvirt_mem.py index d3ca93f34bb..13ec3bdd5ae 100644 --- a/libvirt/tests/src/libvirt_mem.py +++ b/libvirt/tests/src/libvirt_mem.py @@ -55,6 +55,13 @@ def run(test, params, env): new_max_mem = None new_cur_mem = None + def get_hugepage_num(total_huge_page_size): + """ + Calculate huge page number according to total huge page size + """ + default_mem_huge_page_size = utils_memory.get_huge_page_size() + return int(total_huge_page_size) // default_mem_huge_page_size + def consume_vm_mem(size=1000, timeout=360): """ To consume guest memory, default size is 1000M @@ -436,7 +443,6 @@ def modify_domain_xml(): tg_node = params.get("tg_node", 0) pg_size = params.get("page_size") pg_unit = params.get("page_unit", "KiB") - huge_page_num = int(params.get('huge_page_num', 2000)) node_mask = params.get("node_mask", "0") mem_addr = ast.literal_eval(params.get("memory_addr", "{}")) huge_pages = [ast.literal_eval(x) @@ -448,15 +454,22 @@ def modify_domain_xml(): config = utils_config.LibvirtQemuConfig() setup_hugepages_flag = params.get("setup_hugepages") + total_huge_page_size = params.get("total_huge_page_size") + pg_size = str(utils_memory.getpagesize()) if pg_size else None if (setup_hugepages_flag == "yes"): - cpu_arch = cpu_util.get_family() if hasattr(cpu_util, 'get_family')\ - else cpu_util.get_cpu_arch() - if cpu_arch == 'power8': - pg_size = '16384' - huge_page_num = 200 - elif cpu_arch == 'power9': - pg_size = '2048' - huge_page_num = 2000 + pg_size = utils_memory.get_huge_page_size() + huge_page_num = get_hugepage_num(total_huge_page_size) + # Currently aarch64 host has issue with cpu model or family related info, + # so skip it. + if cpu_util.get_arch() != 'aarch64': + cpu_arch = cpu_util.get_family() if hasattr(cpu_util, 'get_family')\ + else cpu_util.get_cpu_arch() + if cpu_arch == 'power8': + pg_size = '16384' + huge_page_num = 200 + elif cpu_arch == 'power9': + pg_size = '2048' + huge_page_num = 2000 [x.update({'size': pg_size}) for x in huge_pages] setup_hugepages(int(pg_size), shp_num=huge_page_num) @@ -727,9 +740,11 @@ def _wait_for_vm_start(): # Remove dmesg temp file if os.path.exists(dmesg_file): os.remove(dmesg_file) - except xcepts.LibvirtXMLError: + except xcepts.LibvirtXMLError as e: if define_error: pass + else: + raise e finally: # Delete snapshots. snapshot_lists = virsh.snapshot_list(vm_name) From 07eee5ba23fbda7c1625f6c9c4851dcbe6b6d64e Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Mon, 18 Mar 2024 12:04:00 +0800 Subject: [PATCH 0245/1055] boot_from_usb_device: correct file path BTW, exclude cases from ARM because bios_useserial is only supported on x86 Signed-off-by: Dan Zheng Signed-off-by: Dan Zheng --- .../{boot_orer => boot_order}/boot_from_usb_device.cfg | 1 + 1 file changed, 1 insertion(+) rename libvirt/tests/cfg/guest_os_booting/{boot_orer => boot_order}/boot_from_usb_device.cfg (98%) diff --git a/libvirt/tests/cfg/guest_os_booting/boot_orer/boot_from_usb_device.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg similarity index 98% rename from libvirt/tests/cfg/guest_os_booting/boot_orer/boot_from_usb_device.cfg rename to libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg index 87745980e08..bd911d81e92 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_orer/boot_from_usb_device.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg @@ -4,6 +4,7 @@ bus_type = "usb" bootmenu_dict = {'bootmenu_enable': 'yes', 'bootmenu_timeout': '3000', 'bios_useserial': 'yes'} check_prompt = "UEFI .* USB|1. USB MSC Drive .*" + only q35 variants usb_device: - block_device: disk_type = "block" From f6232b925df650c55ee96e92b78929d5dc6620a3 Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 18 Mar 2024 12:08:53 +0800 Subject: [PATCH 0246/1055] migartion: Add libvirt version check for domjobabort Add libvirt version check for 'domjobabort --postcopy' command. Signed-off-by: lcheng --- .../abort_by_domjobabort_on_target.cfg | 1 + .../abort_precopy_migration/abort_by_domjobabort_on_target.py | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/libvirt/tests/cfg/migration/abort_precopy_migration/abort_by_domjobabort_on_target.cfg b/libvirt/tests/cfg/migration/abort_precopy_migration/abort_by_domjobabort_on_target.cfg index 25e87fcaf3e..e09cd62ce45 100644 --- a/libvirt/tests/cfg/migration/abort_precopy_migration/abort_by_domjobabort_on_target.cfg +++ b/libvirt/tests/cfg/migration/abort_precopy_migration/abort_by_domjobabort_on_target.cfg @@ -39,6 +39,7 @@ action_during_mig = '[{"func": "do_domjobabort", "after_event": "iteration: '1'", "func_param": "params", "need_sleep_time": "5"}]' domjobabort_err_msg = "cannot acquire state change lock .*held by monitor=remoteDispatchDomainMigratePrepare3Params" - with_postcopy: + func_supported_since_libvirt_ver = (8, 5, 0) postcopy_options = '--postcopy --timeout 10 --timeout-postcopy' domjobabort_options = '--postcopy' action_during_mig = '[{"func": "do_domjobabort", "after_event": "iteration: '1'", "func_param": "params", "need_sleep_time": "10"}]' diff --git a/libvirt/tests/src/migration/abort_precopy_migration/abort_by_domjobabort_on_target.py b/libvirt/tests/src/migration/abort_precopy_migration/abort_by_domjobabort_on_target.py index 7793d3d08b6..5420665be62 100644 --- a/libvirt/tests/src/migration/abort_precopy_migration/abort_by_domjobabort_on_target.py +++ b/libvirt/tests/src/migration/abort_precopy_migration/abort_by_domjobabort_on_target.py @@ -1,3 +1,5 @@ +from virttest import libvirt_version + from provider.migration import base_steps @@ -11,6 +13,8 @@ def run(test, params, env): """ vm_name = params.get("migrate_main_vm") + libvirt_version.is_libvirt_feature_supported(params) + vm = env.get_vm(vm_name) migration_obj = base_steps.MigrationBase(test, vm, params) From a913dbd93e9ad9f329e2168f7afd79f120f939e5 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 18 Mar 2024 01:36:04 -0400 Subject: [PATCH 0247/1055] Change content comparison to subset Signed-off-by: liang-cong-red-hat --- libvirt/tests/src/numa/numa_capabilities.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/src/numa/numa_capabilities.py b/libvirt/tests/src/numa/numa_capabilities.py index 5a8cd83cabe..fe39e923887 100644 --- a/libvirt/tests/src/numa/numa_capabilities.py +++ b/libvirt/tests/src/numa/numa_capabilities.py @@ -52,8 +52,9 @@ def run(test, params, env): cpu_topo_list.append(cpu_dict) logging.debug("cpu topology list from capabilities xml is %s", cpu_list_from_xml) - if cpu_list_from_xml != cpu_topo_list: - test.fail("cpu list %s from capabilities xml not " - "expected.") + for i, cpu_dict in enumerate(cpu_list_from_xml): + if not set(cpu_dict.items()).issubset(set(cpu_topo_list[i].items())): + test.fail("cpu list %s from capabilities xml is not subset from " + "system %s" % (cpu_list_from_xml, cpu_topo_list)) finally: libvirtd.restart() From 6d4a5f3c76f80ed349e8a5a89e138e2db940ec59 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Mon, 18 Mar 2024 03:33:09 -0400 Subject: [PATCH 0248/1055] Add version check for interface with all zeros mac Since the issue is fixed on libvirt-9.9.0, add the version check for interface with all zeros mac. Signed-off-by: Yalan Zhang --- .../elements_and_attributes/element_mac_specific_addr.cfg | 1 + .../elements_and_attributes/element_mac_specific_addr.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/libvirt/tests/cfg/virtual_network/elements_and_attributes/element_mac_specific_addr.cfg b/libvirt/tests/cfg/virtual_network/elements_and_attributes/element_mac_specific_addr.cfg index 168ac563c4b..40f1eb3708d 100644 --- a/libvirt/tests/cfg/virtual_network/elements_and_attributes/element_mac_specific_addr.cfg +++ b/libvirt/tests/cfg/virtual_network/elements_and_attributes/element_mac_specific_addr.cfg @@ -18,6 +18,7 @@ expect_xml_mac = ${set_mac} expect_tap_mac = fa: - all_zeros: + func_supported_since_libvirt_ver = (9, 9, 0) mac = {'mac_address': '00:00:00:00:00:00'} expect_xml_mac = 52:54:00.* expect_tap_mac = fe: diff --git a/libvirt/tests/src/virtual_network/elements_and_attributes/element_mac_specific_addr.py b/libvirt/tests/src/virtual_network/elements_and_attributes/element_mac_specific_addr.py index 9f68800016f..f8feb63f6e4 100644 --- a/libvirt/tests/src/virtual_network/elements_and_attributes/element_mac_specific_addr.py +++ b/libvirt/tests/src/virtual_network/elements_and_attributes/element_mac_specific_addr.py @@ -3,6 +3,7 @@ from virttest import utils_net from virttest import virsh +from virttest import libvirt_version from virttest.libvirt_xml import vm_xml from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_test import libvirt @@ -18,6 +19,7 @@ def run(test, params, env): """ Test start vm or hotplug interface with specific mac address """ + libvirt_version.is_libvirt_feature_supported(params) vm_name = params.get('main_vm') vm = env.get_vm(vm_name) scenario = params.get('scenario') From 2f19e1d4426be622c75d88d3ca84245c2d30c1c4 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 18 Mar 2024 05:49:57 -0400 Subject: [PATCH 0249/1055] libvirt_mem add adaption for aarch64 Signed-off-by: liang-cong-red-hat --- libvirt/tests/src/libvirt_mem.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/libvirt_mem.py b/libvirt/tests/src/libvirt_mem.py index 13ec3bdd5ae..6d70835d505 100644 --- a/libvirt/tests/src/libvirt_mem.py +++ b/libvirt/tests/src/libvirt_mem.py @@ -57,7 +57,10 @@ def run(test, params, env): def get_hugepage_num(total_huge_page_size): """ - Calculate huge page number according to total huge page size + Calculate huge page number according to total huge page size. + + :param total_huge_page_size: required total huge page size in KiB + :return: huge page number required """ default_mem_huge_page_size = utils_memory.get_huge_page_size() return int(total_huge_page_size) // default_mem_huge_page_size From 256f5497d9fb7e2f62631536c7acf7cf3dfe82cc Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Mon, 26 Feb 2024 21:56:56 +0800 Subject: [PATCH 0250/1055] lifecycle_for_hugepage: update for arm hugepage Enable different hugepages supported on ARM. 4k kernel: 2M, 1G, 32M, 64K 64k kernel: 512M, 2M, 16G Signed-off-by: Dan Zheng --- .../memory_backing/lifecycle_for_hugepage.cfg | 64 +++- .../memory_backing/lifecycle_for_hugepage.py | 321 +++++++++++------- .../numa_topology_with_hugepage.py | 2 +- provider/numa/numa_base.py | 7 +- 4 files changed, 264 insertions(+), 130 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_backing/lifecycle_for_hugepage.cfg b/libvirt/tests/cfg/memory/memory_backing/lifecycle_for_hugepage.cfg index 9db45e9d58f..aa03fc5f369 100644 --- a/libvirt/tests/cfg/memory/memory_backing/lifecycle_for_hugepage.cfg +++ b/libvirt/tests/cfg/memory/memory_backing/lifecycle_for_hugepage.cfg @@ -1,5 +1,6 @@ - memory.backing.lifecycle: type = lifecycle_for_hugepage + total_hugepage_mem = 2097152 vm_nr_hugepages = 1024 mount_size = "1048576" current_mem = 2097152 @@ -9,9 +10,7 @@ target_hugepages = 2 set_pagesize ="1048576" set_pagenum = "2" - free_hugepages_cmd= "cat /sys/kernel/mm/hugepages/hugepages-1048576kB/free_hugepages" s390-virtio: - free_hugepages_cmd= "cat /sys/kernel/mm/hugepages/hugepages-1024kB/free_hugepages" set_pagesize = "1024" mount_size = "1024" set_pagenum = "2048" @@ -19,34 +18,80 @@ kvm_module_parameters = variants: - memory_hugepage: - variants: - - 4k: + variants scenario: + - default_page_size: no s390-virtio page_size = "4" page_unit = "KiB" memory_backing_dict = "'mb': {'hugepages': {'pages': [{'unit': '${page_unit}', 'size': '${page_size}'}]}}" vm_attrs = {${memory_backing_dict}, 'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} - HugePages_Free = "1024" - free_hugepages = "2" + HugePages_Free = ${vm_nr_hugepages} + free_hugepages = ${set_pagenum} - 1M: only s390-virtio memory_backing_dict = "'mb': {'hugepages': {}}" vm_attrs = {${memory_backing_dict}, 'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} HugePages_Free = "0" free_hugepages = "0" - - 2M: + - default_hugepage_size: no s390-virtio memory_backing_dict = "'mb': {'hugepages': {}}" vm_attrs = {${memory_backing_dict}, 'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} HugePages_Free = "0" - free_hugepages = "2" + free_hugepages = ${set_pagenum} - 1G: no s390-virtio page_size = "1" page_unit = "G" memory_backing_dict = "'mb': {'hugepages': {'pages': [{'unit': '${page_unit}', 'size': '${page_size}'}]}}" vm_attrs = {${memory_backing_dict}, 'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} - HugePages_Free = "1024" + HugePages_Free = ${vm_nr_hugepages} + free_hugepages = "0" + - 2M: + only aarch64 + page_size = "2" + page_unit = "M" + set_pagesize ="2048" + set_pagenum = "1024" + mount_size = ${set_pagesize} + memory_backing_dict = "'mb': {'hugepages': {'pages': [{'unit': '${page_unit}', 'size': '${page_size}'}]}}" + vm_attrs = {${memory_backing_dict}, 'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} + HugePages_Free = + free_hugepages = "0" + - 16G: + only aarch64 + page_size = "16" + page_unit = "G" + set_pagesize ="16777216" + set_pagenum = "1" + mount_size = ${set_pagesize} + mem_value = 16777216 + current_mem = 16777216 + memory_backing_dict = "'mb': {'hugepages': {'pages': [{'unit': '${page_unit}', 'size': '${page_size}'}]}}" + vm_attrs = {${memory_backing_dict}, 'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} + HugePages_Free = + free_hugepages = "0" + - 64K: + only aarch64 + page_size = "64" + page_unit = "KiB" + set_pagesize ="64" + set_pagenum = "32768" + mount_size = ${set_pagesize} + memory_backing_dict = "'mb': {'hugepages': {'pages': [{'unit': '${page_unit}', 'size': '${page_size}'}]}}" + vm_attrs = {${memory_backing_dict}, 'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} + HugePages_Free = + free_hugepages = "0" + - 32M: + only aarch64 + page_size = "32" + page_unit = "M" + set_pagesize ="32768" + set_pagenum = "64" + mount_size = ${set_pagesize} + memory_backing_dict = "'mb': {'hugepages': {'pages': [{'unit': '${page_unit}', 'size': '${page_size}'}]}}" + vm_attrs = {${memory_backing_dict}, 'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} + HugePages_Free = free_hugepages = "0" - 0: page_size = "0" @@ -60,4 +105,3 @@ memory_backing_dict = "'mb': {'hugepages': {}}" vm_attrs = {${memory_backing_dict}, 'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} start_error = "unable to map backing store for guest RAM: Cannot allocate memory" - diff --git a/libvirt/tests/src/memory/memory_backing/lifecycle_for_hugepage.py b/libvirt/tests/src/memory/memory_backing/lifecycle_for_hugepage.py index 72d4f9de90a..905fe53661c 100644 --- a/libvirt/tests/src/memory/memory_backing/lifecycle_for_hugepage.py +++ b/libvirt/tests/src/memory/memory_backing/lifecycle_for_hugepage.py @@ -8,23 +8,220 @@ # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import math import os -import re -from avocado.utils import process +from avocado.utils import memory +from avocado.utils import cpu from virttest import utils_libvirtd from virttest import virsh -from virttest import virt_vm from virttest import test_setup from virttest.libvirt_xml import vm_xml from virttest.utils_test import libvirt from virttest.staging import utils_memory +from virttest.utils_libvirt import libvirt_memory + +from provider.numa import numa_base + VIRSH_ARGS = {'debug': True, 'ignore_status': False} +def check_hugepage_support(params, test): + """ + Check if the specified hugepage size is supported on current environment + + :param params: dict, test parameters + :param test: test object + """ + scenario = params.get('scenario') + if scenario in ['1G', '2M', '32M', '64K', '16G']: + if scenario == '2M' and memory.get_huge_page_size()//1024 == 2: + test.cancel("2M is the default huge page size and tested in another test scenario") + vm_attrs = eval(params.get('vm_attrs', '{}')) + if vm_attrs.get('mb'): + numa_base.check_hugepage_availability(vm_attrs["mb"]["hugepages"]["pages"]) + + +def adjust_parameters(params, test): + """ + Update the test parameters according to different architecture + + :param params: dict, test parameters + :param test: test object + :ret: dict, the updated test parameters + """ + def sub_update(): + set_pagesize = default_pgsize_set_mapping[default_pagesize] + params['set_pagesize'] = set_pagesize + params['mount_size'] = set_pagesize + params['set_pagenum'] = int(math.floor(total_hugepage_mem/set_pagesize)) + + vm_attrs = eval(params.get("vm_attrs", "{}")) + scenario = params.get('scenario') + + current_arch = cpu.get_arch() + default_pagesize = memory.get_page_size()//1024 + total_hugepage_mem = int(params.get('total_hugepage_mem')) + if scenario == 'default_page_size': + vm_attrs['mb']['hugepages']['pages'][0]['size'] = default_pagesize + + if current_arch == 'aarch64': + # kernel page size vs. huge page size to be set for kernel mm file + # like if kernel page size 64K, then huge page size to be set is 2048K + default_pgsize_set_mapping = {64: 2048, 4: 1048576} + default_hugepage_size = memory.get_huge_page_size() + params['vm_nr_hugepages'] = int(math.floor(total_hugepage_mem/default_hugepage_size)) + + if scenario == 'default_page_size': + sub_update() + params['HugePages_Free'] = params['vm_nr_hugepages'] + params['free_hugepages'] = params['set_pagenum'] + elif scenario in ['default_hugepage_size', 'scarce_mem']: + sub_update() + params['free_hugepages'] = params['set_pagenum'] + elif scenario == '1G': + params['HugePages_Free'] = params['vm_nr_hugepages'] + elif scenario == '0': + sub_update() + elif scenario in ['2M', '16G', '64K', '32M']: + params['HugePages_Free'] = params['vm_nr_hugepages'] + test.log.debug("params['HugePages_Free']=%s", params.get('HugePages_Free')) + test.log.debug("params['free_hugepages']=%s", params.get('free_hugepages')) + test.log.debug("params['vm_nr_hugepages']=%s", params.get('vm_nr_hugepages')) + test.log.debug("params['set_pagesize']=%s", params.get('set_pagesize')) + test.log.debug("params['set_pagenum']=%s", params.get('set_pagenum')) + test.log.debug("params['mount_size']=%s", params.get('mount_size')) + + params['vm_attrs'] = vm_attrs + test.log.debug("Updated vm_attrs:%s", vm_attrs) + + return params + + +def setup_test(vm_name, params, test): + """ + Set hugepage on host + + :param vm_name: str, vm name + :param params: dict, test parameters + :param test: test object + """ + test.log.info("TEST_SETUP: Set hugepage on host") + vm_nr_hugepages = params.get("vm_nr_hugepages") + set_pagesize = params.get("set_pagesize") + set_pagenum = params.get("set_pagenum") + mount_size = params.get("mount_size") + + utils_memory.set_num_huge_pages(int(vm_nr_hugepages)) + hp_cfg = test_setup.HugePageConfig(params) + hp_cfg.set_kernel_hugepages(set_pagesize, set_pagenum) + hp_cfg.hugepage_size = mount_size + hp_cfg.mount_hugepage_fs() + utils_libvirtd.Libvirtd().restart() + virsh.destroy(vm_name) + + +def run_test(vm, params, test): + """ + Define guest, start guest and check mem. + + :param vm: vm instance + :param params: dict, test parameters + :param test: test object + """ + define_error = params.get("define_error") + start_error = params.get("start_error") + save_file = params.get("save_file", "/tmp/guest.save") + HugePages_Free = params.get("HugePages_Free") + free_hugepages = params.get("free_hugepages") + vm_nr_hugepages = params.get("vm_nr_hugepages") + set_pagesize = params.get("set_pagesize") + set_pagenum = params.get("set_pagenum") + vm_attrs = params.get("vm_attrs") + + test.log.info("TEST_STEP1: Define guest") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) + if vm_attrs: + vmxml.setup_attrs(**vm_attrs) + cmd_result = virsh.define(vmxml.xml, debug=True) + if define_error: + # check scenario: 0 + libvirt.check_result(cmd_result, define_error) + return + + test.log.info("TEST_STEP2: Start guest") + ret = virsh.start(vm.name, debug=True, ignore_error=True) + libvirt.check_result(ret, expected_fails=start_error) + if start_error: + return + vmxml = vm_xml.VMXML.new_from_dumpxml(vm.name) + test.log.debug("After start vm, get vmxml is :%s", vmxml) + + test.log.info("TEST_STEP3: Check the huge page memory usage") + hp_cfg = test_setup.HugePageConfig(params) + if int(utils_memory.get_num_huge_pages()) != int(vm_nr_hugepages): + test.fail("HugePages_Total should be %s instead of %s" % ( + vm_nr_hugepages, utils_memory.get_num_huge_pages())) + + actural_nr = hp_cfg.get_kernel_hugepages(set_pagesize) + if int(actural_nr) != int(set_pagenum): + test.fail("nr_hugepages should be %s instead of %s" % ( + set_pagenum, actural_nr)) + + if int(utils_memory.get_num_huge_pages_free()) != int(HugePages_Free): + test.fail("HugePages_Free should be %s instead of %s" % ( + HugePages_Free, utils_memory.get_num_huge_pages_free())) + + actural_freepg = hp_cfg.get_kernel_hugepages(set_pagesize, 'free') + if int(actural_freepg) != int(free_hugepages): + test.fail("free_hugepages should be %s instead of %s" % ( + free_hugepages, actural_freepg)) + + test.log.info("TEST_STEP4: Check the vm lifecycle with hugepage setting") + virsh.suspend(vm.name, **VIRSH_ARGS) + virsh.resume(vm.name, **VIRSH_ARGS) + vm.wait_for_login().close() + + if os.path.exists(save_file): + os.remove(save_file) + virsh.save(vm.name, save_file, **VIRSH_ARGS) + virsh.restore(save_file, **VIRSH_ARGS) + vm.wait_for_login().close() + + virsh.managedsave(vm.name, **VIRSH_ARGS) + vm.start() + vm.wait_for_login().close() + + virsh.reboot(vm.name, **VIRSH_ARGS) + session = vm.wait_for_login() + + test.log.info("TEST_STEP5: Verify guest memory could be consumed") + libvirt_memory.consume_vm_freememory(session, 204800) + + virsh.destroy(vm.name, **VIRSH_ARGS) + + +def teardown_test(vmxml, params, test): + """ + Clean data. + + :param vmxml: VMXML instance + :param params: dict, test parameters + :param test: test object + """ + save_file = params.get("save_file", "/tmp/guest.save") + + test.log.info("TEST_TEARDOWN: Clean up env.") + vmxml.sync() + if os.path.exists(save_file): + os.remove(save_file) + hp_cfg = test_setup.HugePageConfig(params) + hp_cfg.cleanup() + + def run(test, params, env): """ 1.Verify different size huge page take effect for guest vm @@ -33,124 +230,16 @@ def run(test, params, env): Scenario: Huge page memory status: 4k, 2M, 1G, 0, scarce. """ - def setup_test(): - """ - Set hugepage on host - """ - test.log.info("TEST_SETUP: Set hugepage on host") - utils_memory.set_num_huge_pages(int(vm_nr_hugepages)) - - hp_cfg = test_setup.HugePageConfig(params) - hp_cfg.set_kernel_hugepages(set_pagesize, set_pagenum) - hp_cfg.hugepage_size = mount_size - hp_cfg.mount_hugepage_fs() - utils_libvirtd.libvirtd_restart() - virsh.destroy(vm_name) - - def run_test(): - """ - Define guest, start guest and check mem. - """ - test.log.info("TEST_STEP1: Define guest") - vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) - vmxml.setup_attrs(**vm_attrs) - cmd_result = virsh.define(vmxml.xml, debug=True) - if define_error: - # check scenario: 0 - libvirt.check_result(cmd_result, define_error) - return - - test.log.info("TEST_STEP2: Start guest") - try: - vm.start() - vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) - test.log.debug("After start vm, get vmxml is :%s", vmxml) - except virt_vm.VMStartError as details: - # check scenario: scarce_mem - if not re.search(start_error, str(details)): - test.fail("Failed to start guest: {}".format(str(details))) - else: - return - - test.log.info("TEST_STEP3: Check the huge page memory usage") - hp_cfg = test_setup.HugePageConfig(params) - if int(utils_memory.get_num_huge_pages()) != int(vm_nr_hugepages): - test.fail("HugePages_Total should be %s instead of %s" % ( - vm_nr_hugepages, utils_memory.get_num_huge_pages())) - - actural_nr = hp_cfg.get_kernel_hugepages(set_pagesize) - if int(actural_nr) != int(set_pagenum): - test.fail("nr_hugepages should be %s instead of %s" % ( - set_pagenum, actural_nr)) - - if int(utils_memory.get_num_huge_pages_free()) != int(HugePages_Free): - test.fail("HugePages_Free should be %s instead of %s" % ( - HugePages_Free, utils_memory.get_num_huge_pages_free())) - - free_page_num = process.run(free_hugepages_cmd, shell=True, - verbose=True).stdout_text.strip() - if int(free_page_num) != int(free_hugepages): - test.fail("free_hugepages should be %s instead of %s" % ( - free_hugepages, free_page_num)) - - test.log.info("TEST_STEP4: Check the huge page memory usage") - virsh.suspend(vm.name, **VIRSH_ARGS) - virsh.resume(vm.name, **VIRSH_ARGS) - vm.wait_for_login().close() - - if os.path.exists(save_file): - os.remove(save_file) - virsh.save(vm.name, save_file, **VIRSH_ARGS) - virsh.restore(save_file, **VIRSH_ARGS) - vm.wait_for_login().close() - - virsh.managedsave(vm.name, **VIRSH_ARGS) - vm.start() - vm.wait_for_login().close() - - virsh.reboot(vm.name, **VIRSH_ARGS) - session = vm.wait_for_login() - - test.log.info("TEST_STEP5: Verify guest memory could be consumed") - mem_free = utils_memory.freememtotal(session) - status, stdout = session.cmd_status_output("swapoff -a; memhog %s" % ( - mem_free - 204800)) - if status: - raise test.fail("Failed to consume memory:%s" % stdout) - - virsh.destroy(vm.name, **VIRSH_ARGS) - - def teardown_test(): - """ - Clean data. - """ - test.log.info("TEST_TEARDOWN: Clean up env.") - bkxml.sync() - if os.path.exists(save_file): - os.remove(save_file) - hp_cfg = test_setup.HugePageConfig(params) - hp_cfg.cleanup() - + check_hugepage_support(params, test) vm_name = params.get("main_vm") + params = adjust_parameters(params, test) vm = env.get_vm(vm_name) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) bkxml = vmxml.copy() - define_error = params.get("define_error") - vm_nr_hugepages = params.get("vm_nr_hugepages") - free_hugepages_cmd = params.get("free_hugepages_cmd") - set_pagesize = params.get("set_pagesize") - set_pagenum = params.get("set_pagenum") - HugePages_Free = params.get("HugePages_Free") - mount_size = params.get("mount_size") - free_hugepages = params.get("free_hugepages") - start_error = params.get("start_error") - vm_attrs = eval(params.get("vm_attrs", "{}")) - save_file = params.get("save_file", "/tmp/guest.save") - try: - setup_test() - run_test() + setup_test(vm_name, params, test) + run_test(vm, params, test) finally: - teardown_test() + teardown_test(bkxml, params, test) diff --git a/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_hugepage.py b/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_hugepage.py index e041e3b1e93..dce1771f92f 100644 --- a/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_hugepage.py +++ b/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_hugepage.py @@ -41,7 +41,7 @@ def setup_default(test_obj): """ memory_backing = eval(test_obj.params.get('memory_backing', '{}')) if memory_backing: - numa_base.check_hugepage_availability(memory_backing) + numa_base.check_hugepage_availability(memory_backing["hugepages"]["pages"]) test_obj.setup() params_2M = {'hugepage_size': '2048', 'vm_hugepage_mountpoint': test_obj.params.get('hugepage_path_2M'), diff --git a/provider/numa/numa_base.py b/provider/numa/numa_base.py index b7ece0d32c3..81655fc0f5b 100644 --- a/provider/numa/numa_base.py +++ b/provider/numa/numa_base.py @@ -217,17 +217,18 @@ def convert_to_list_of_int(cpus_in_short, cpu_num): return [index for index in range(0, len(cpu_list)) if cpu_list[index] == 'y'] -def check_hugepage_availability(memory_backing): +def check_hugepage_availability(pages_list): """ Check if the configured huge page size is supported on the system - :param memory_backing: like {'hugepages': {'pages': [{'size': '1048576', 'unit': 'KiB', 'nodeset': '0'}]}} + :param pages_list: list, like [{'size': '1048576', 'unit': 'KiB'}] :raises: exceptions.TestSkipError: when hugepage is not supported """ unit_mapping = {'G': 1048576, 'M': 1024, 'KiB': 1} supported_hugepages = memory.get_supported_huge_pages_size() - pages_list = memory_backing['hugepages']['pages'] for a_page in pages_list: + if a_page.get("size") is None or a_page.get("unit") is None: + raise exceptions.TestError("'size' and 'unit' are required") size = int(a_page['size']) unit = a_page['unit'] size *= unit_mapping[unit] From e9d18541015eed312d492a5870abcfa6e0aa5ba1 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Fri, 19 Jan 2024 06:03:01 -0500 Subject: [PATCH 0251/1055] Get the vm_iface name from the guest OS With acpi feature, we can assume that the vm_iface is "eno1" with the setting. But it only works on x86 now. Update it to get the vm_iface name from the guest OS instead. Signed-off-by: Yalan Zhang --- libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg | 1 - libvirt/tests/src/virtual_network/passt/passt_attach_detach.py | 2 +- libvirt/tests/src/virtual_network/passt/passt_function.py | 2 +- libvirt/tests/src/virtual_network/passt/passt_reconnect.py | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg index 9003f3b0f14..649effd1823 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg @@ -36,7 +36,6 @@ iface_attrs = {'model': 'virtio', 'acpi': {'index': '1'}, 'ips': ${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, 'alias': ${alias}, 'type_name': 'user', 'portForwards': ${portForwards}} proc_checks = ['--tcp-ports 31339:41339', '--udp-ports 2025', f'--tcp-ports {host_ip}/9000'] ipv6_prefix = 128 - vm_iface = eno1 vm_ping_outside = pass vm_ping_host_public = pass tcp_port_list = [9000, '*:31339'] diff --git a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py index e060a8a7816..ee5b8373a05 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py +++ b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py @@ -73,7 +73,6 @@ def run(test, params, env): iface_attrs = eval(params.get('iface_attrs')) params['socket_dir'] = socket_dir = eval(params.get('socket_dir')) params['proc_checks'] = proc_checks = eval(params.get('proc_checks', '{}')) - vm_iface = params.get('vm_iface', 'eno1') mtu = params.get('mtu') outside_ip = params.get('outside_ip') log_file = f'/run/user/{user_id}/passt.log' @@ -124,6 +123,7 @@ def run(test, params, env): test.fail(f'Logfile of passt "{log_file}" not created') session = vm.wait_for_serial_login(timeout=60) + vm_iface = utils_net.get_linux_ifname(session, mac) passt.check_vm_ip(iface_attrs, session, host_iface, vm_iface) passt.check_vm_mtu(session, vm_iface, mtu) passt.check_default_gw(session) diff --git a/libvirt/tests/src/virtual_network/passt/passt_function.py b/libvirt/tests/src/virtual_network/passt/passt_function.py index ef57ffc6063..47a47c92347 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_function.py +++ b/libvirt/tests/src/virtual_network/passt/passt_function.py @@ -60,7 +60,6 @@ def run(test, params, env): params['host_ip_v6'] = host_ip_v6 params['socket_dir'] = socket_dir = eval(params.get('socket_dir')) params['proc_checks'] = proc_checks = eval(params.get('proc_checks', '{}')) - vm_iface = params.get('vm_iface', 'eno1') mtu = params.get('mtu') outside_ip = params.get('outside_ip') log_file = f'/run/user/{user_id}/passt.log' @@ -97,6 +96,7 @@ def run(test, params, env): test.fail(f'Logfile of passt "{log_file}" not created') session = vm.wait_for_serial_login(timeout=60) + vm_iface = utils_net.get_linux_ifname(session, mac) passt.check_vm_ip(iface_attrs, session, host_iface, vm_iface) passt.check_vm_mtu(session, vm_iface, mtu) passt.check_default_gw(session) diff --git a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py index 733d5d2ce9f..b75dabfa942 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py +++ b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py @@ -59,7 +59,6 @@ def run(test, params, env): iface_attrs = eval(params.get('iface_attrs')) params['socket_dir'] = socket_dir = eval(params.get('socket_dir')) params['proc_checks'] = proc_checks = eval(params.get('proc_checks', '{}')) - vm_iface = params.get('vm_iface', 'eno1') mtu = params.get('mtu') qemu_cmd_check = params.get('qemu_cmd_check') outside_ip = params.get('outside_ip') @@ -109,6 +108,7 @@ def run(test, params, env): test.fail(f'Logfile of passt "{log_file}" not created') session = vm.wait_for_serial_login(timeout=60) + vm_iface = utils_net.get_linux_ifname(session, mac) passt.check_vm_ip(iface_attrs, session, host_iface, vm_iface) passt.check_vm_mtu(session, vm_iface, mtu) passt.check_default_gw(session) From c6945ea00495fb0512f44afd27b01edcbfb0504b Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Wed, 13 Mar 2024 22:12:16 -0400 Subject: [PATCH 0252/1055] Change huge page assignment automatically to adapt for aarch64. Signed-off-by: liang-cong-red-hat --- .../lifecycle_of_mixed_memory_devices.cfg | 27 ++++++++++--------- .../lifecycle_of_mixed_memory_devices.py | 25 ++++++++++++++--- 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_devices/lifecycle_of_mixed_memory_devices.cfg b/libvirt/tests/cfg/memory/memory_devices/lifecycle_of_mixed_memory_devices.cfg index a259785a326..8485223986f 100644 --- a/libvirt/tests/cfg/memory/memory_devices/lifecycle_of_mixed_memory_devices.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/lifecycle_of_mixed_memory_devices.cfg @@ -8,26 +8,26 @@ nvdimm_path_1 = "/tmp/nvdimm1" nvdimm_path_2 = "/tmp/nvdimm2" save_file = "/tmp/guest.save" - nr_hugepages = 256 + total_hugepage_size = 1048576 kernel_hp_file = "/proc/sys/vm/nr_hugepages" truncate_cmd = "truncate -s 512M ${nvdimm_path_1} && truncate -s 512M ${nvdimm_path_2}" kernel_params_remove = "memhp_default_state" kernel_params_add = "memhp_default_state=online_movable" page_size = 2048 - dimm_1 = [262144, 262144, 1, "", 1, "dimm_dict_1"] + dimm_1 = [524288, 524288, 1, "", 1, "dimm_dict_1"] nvdimm_1 = [524288, 0, 2, "", "", "nvdimm_dict_1"] virtio_mem_1 = [2097152, 1048576, 3, "", "", "virtio_mem_dict_1"] - dimm_2 = [262144, 262144,"", 1, "", "dimm_dict_2"] + dimm_2 = [524288, 524288,"", 1, "", "dimm_dict_2"] nvdimm_2 = [524288, 0, "", 2, "", "nvdimm_dict_2"] - virtio_mem_2 = [262144, 262144, "", 3, "","virtio_mem_dict_2"] + virtio_mem_2 = [524288, 524288, "", 3, "","virtio_mem_dict_2"] set_items = ["memory_affected", "current_mem_affected","init_seq","hotplug_seq","hotunplug_seq", "dev_dict"] set_value = [${dimm_1}, ${nvdimm_1}, ${virtio_mem_1}, ${dimm_2}, ${nvdimm_2}, ${virtio_mem_2}] - dimm_target_dize = 262144 - nvdimm_target_dize = 524288 + dimm_target_size = 524288 + nvdimm_target_size = 524288 virtio_mem_target_size = 2097152 - dimm_dict_1 = {'mem_model': 'dimm', 'mem_access':'private','mem_discard':'no','source': {"pagesize":${page_size}, "pagesize_unit":"KiB"},'target': {'size': ${dimm_target_dize}, 'size_unit': 'KiB','node':0}} - nvdimm_dict_1 = {'mem_model': 'nvdimm', 'source': {"path":"${nvdimm_path_1}"}, 'target': {'size': ${nvdimm_target_dize}, 'size_unit': 'KiB','node':1 }} - virtio_mem_dict_1 = {'mem_model': 'virtio-mem', 'target': {'size': ${virtio_mem_target_size}, 'size_unit': 'KiB','node':0, 'block_unit':'KiB','block_size':2048,'requested_size':1048576, 'requested_unit':'KiB'}} + dimm_dict_1 = {'mem_model': 'dimm', 'mem_access':'private','mem_discard':'no','source': {"pagesize":${page_size}, "pagesize_unit":"KiB"},'target': {'size': ${dimm_target_size}, 'size_unit': 'KiB','node':0}} + nvdimm_dict_1 = {'mem_model': 'nvdimm', 'source': {"path":"${nvdimm_path_1}"}, 'target': {'size': ${nvdimm_target_size}, 'size_unit': 'KiB','node':1 }} + virtio_mem_dict_1 = {'mem_model': 'virtio-mem', 'target': {'size': ${virtio_mem_target_size}, 'size_unit': 'KiB','node':0, 'block_unit':'KiB','block_size':${page_size},'requested_size':1048576, 'requested_unit':'KiB'}} variants: - mutiple_mem: no s390-virtio @@ -35,12 +35,13 @@ guest_required_kernel = [5.8.0,) func_supported_since_libvirt_ver = (8, 0, 0) func_supported_since_qemu_kvm_ver = (6, 2, 0) - dimm_dict_2 = {'mem_model': 'dimm', 'mem_access':'shared','mem_discard':'yes','target': {'size': ${dimm_target_dize}, 'size_unit': 'KiB','node':1}} - nvdimm_dict_2 = {'mem_model': 'nvdimm', 'source': {"path":"${nvdimm_path_2}"}, 'target': {'size': ${nvdimm_target_dize}, 'size_unit': 'KiB','node':1, 'label':{'size':128, 'size_unit':'KiB'} }} - virtio_mem_dict_2 = {'mem_model': 'virtio-mem','source': {"pagesize":${page_size}, "pagesize_unit":"KiB"}, 'target': {'size': 262144, 'size_unit': 'KiB','node':0, 'block_unit':'KiB','block_size':2048,'requested_size':262144, 'requested_unit':'KiB'}} - xpath_basic = {'element_attrs': [".//memory[@unit='${default_unit}']"],'text': '%s'},{'element_attrs': [".//currentMemory[@unit='${default_unit}']"],'text': '%s'},{'element_attrs': [".//alias[@name='dimm0']"]},{'element_attrs': [".//address[@slot='0']",".//address[@type='dimm']"]},{'element_attrs': [".//alias[@name='nvdimm1']"]},{'element_attrs': [".//address[@slot='1']",".//address[@type='dimm']"]},{'element_attrs': [".//alias[@name='virtiomem0']"]} + dimm_dict_2 = {'mem_model': 'dimm', 'mem_access':'shared','mem_discard':'yes','target': {'size': ${dimm_target_size}, 'size_unit': 'KiB','node':1}} + nvdimm_dict_2 = {'mem_model': 'nvdimm', 'source': {"path":"${nvdimm_path_2}"}, 'target': {'size': ${nvdimm_target_size}, 'size_unit': 'KiB','node':1, 'label':{'size':128, 'size_unit':'KiB'} }} + virtio_mem_dict_2 = {'mem_model': 'virtio-mem','source': {"pagesize":${page_size}, "pagesize_unit":"KiB"}, 'target': {'size': 524288, 'size_unit': 'KiB','node':0, 'block_unit':'KiB','block_size':${page_size},'requested_size':524288, 'requested_unit':'KiB'}} + xpath_basic = {'element_attrs': [".//memory[@unit='${default_unit}']"],'text':'%s'},{'element_attrs': [".//currentMemory[@unit='${default_unit}']"],'text': '%s'},{'element_attrs': [".//alias[@name='dimm0']"]},{'element_attrs': [".//address[@slot='0']",".//address[@type='dimm']"]},{'element_attrs': [".//alias[@name='nvdimm1']"]},{'element_attrs': [".//address[@slot='1']",".//address[@type='dimm']"]},{'element_attrs': [".//alias[@name='virtiomem0']"]} xpath_after_start = [${xpath_basic}] xpath_after_attached = [${xpath_basic},{'element_attrs': [".//alias[@name='dimm2']"]},{'element_attrs': [".//address[@slot='2']",".//address[@type='dimm']"]},{'element_attrs': [".//alias[@name='nvdimm3']"]}, {'element_attrs': [".//address[@slot='3']",".//address[@type='dimm']"]},{'element_attrs': [".//alias[@name='virtiomem1']"]}] xpath_after_detached = [${xpath_basic}, {'element_attrs': [".//alias[@name='dimm2']"]},{'element_attrs': [".//address[@slot='2']",".//address[@type='dimm']"]},{'element_attrs': [".//alias[@name='nvdimm3']"]},{'element_attrs': [".//address[@slot='3']",".//address[@type='dimm']"]},{'element_attrs': [".//alias[@name='virtiomem1']"]}] del_head = 2 del_tail = 4 + diff --git a/libvirt/tests/src/memory/memory_devices/lifecycle_of_mixed_memory_devices.py b/libvirt/tests/src/memory/memory_devices/lifecycle_of_mixed_memory_devices.py index 0868e463e27..63a9d50b16b 100644 --- a/libvirt/tests/src/memory/memory_devices/lifecycle_of_mixed_memory_devices.py +++ b/libvirt/tests/src/memory/memory_devices/lifecycle_of_mixed_memory_devices.py @@ -8,6 +8,7 @@ # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import math import os import re @@ -127,6 +128,7 @@ def attach_all_memory_devices(vm, params, operate_flag): vm.start() for mem in mem_list: dev_dict = globals()[mem] + update_mem_device_pagesize(dev_dict) mem_dev = memory.Memory() mem_dev.setup_attrs(**dev_dict) virsh.attach_device(vm.name, mem_dev.xml, debug=True, @@ -146,6 +148,7 @@ def detach_all_memory_devices(vm_name, params, operate_flag): for index, value in enumerate(set_value): if value[get_index(params, operate_flag)] != "": dev_dict = globals()[value[-1]] + update_mem_device_pagesize(dev_dict) mem_xml = memory.Memory() mem_xml.setup_attrs(**dev_dict) virsh.detach_device(vm_name, mem_xml.xml, debug=True, @@ -260,6 +263,19 @@ def get_affected_mem(params, operation): return memory_affected, current_mem_affected +def update_mem_device_pagesize(mem_device_dict): + """ + update memory device page size and block size to default hugepage size. + + :param mem_device_dict: memory device dictionary. + """ + page_size = int(utils_memory.get_huge_page_size()) + if 'source' in mem_device_dict and 'pagesize' in mem_device_dict['source']: + mem_device_dict['source']['pagesize'] = page_size + if 'target' in mem_device_dict and 'block_size' in mem_device_dict['target']: + mem_device_dict['target']['block_size'] = page_size + + def update_vm_devices(vmxml, params): """ Update vm devices. @@ -276,6 +292,7 @@ def update_vm_devices(vmxml, params): mem_list.append(value[-1]) for index, mem in enumerate(mem_list): dev_dict = globals()[mem] + update_mem_device_pagesize(dev_dict) new_mem = memory.Memory() new_mem.setup_attrs(**dev_dict) devices.append(new_mem) @@ -293,10 +310,12 @@ def setup_test(): """ test.log.info("TEST_SETUP: Set hugepage and guest boot ") process.run(truncate_cmd, ignore_status=False, shell=True) - utils_memory.set_num_huge_pages(int(nr_hugepages)) + nr_hugepages = math.ceil( + int(total_hugepage_size) / utils_memory.get_huge_page_size()) + utils_memory.set_num_huge_pages(nr_hugepages) result = process.run("cat %s" % kernel_hp_file, ignore_status=True, verbose=False).stdout_text.strip() - if nr_hugepages != result: + if str(nr_hugepages) != result: test.fail("Hugepage set failed, should be %s instead of %s" % ( nr_hugepages, result)) @@ -408,7 +427,7 @@ def teardown_test(): kernel_params_remove = params.get("kernel_params_remove") kernel_params_add = params.get("kernel_params_add") truncate_cmd = params.get("truncate_cmd") - nr_hugepages = params.get("nr_hugepages") + total_hugepage_size = params.get("total_hugepage_size") kernel_hp_file = params.get("kernel_hp_file") nvdimm_path_1 = params.get("nvdimm_path_1") nvdimm_path_2 = params.get("nvdimm_path_2") From c6981872835ac37075b71d1b6c7b80e99ee71842 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Tue, 19 Mar 2024 05:48:14 -0400 Subject: [PATCH 0253/1055] Increase current memory size to avoid guest crash during bootup Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/libvirt_mem.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/cfg/libvirt_mem.cfg b/libvirt/tests/cfg/libvirt_mem.cfg index 8c397a8005b..7be0e5a6d79 100644 --- a/libvirt/tests/cfg/libvirt_mem.cfg +++ b/libvirt/tests/cfg/libvirt_mem.cfg @@ -193,6 +193,7 @@ max_mem_rt = max_mem = numa_cells = + current_mem = 2048000 attach_option = "--config" - attach_invalid_type: memory_addr = "{'type':'diee','slot':'16','base':'0x11fffffffff'}" From ecba7e454660047d3b968873da379236918ca9eb Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 19 Mar 2024 07:41:33 -0400 Subject: [PATCH 0254/1055] virtual_network/coalesce: normalize ethtool output Test runs would fail if * there were spaces in the values (e.g. ' 32' instead of '32') * missing setting would expect value '0' instead of 'n/a' but consider these equivalent Therefore, normalize the ethtool output in the function. The function is only used in the update_device_coalesce script add test run log to PR. Signed-off-by: Sebastian Mitterle --- provider/virtual_network/network_base.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/provider/virtual_network/network_base.py b/provider/virtual_network/network_base.py index a2f856855c3..61038423629 100644 --- a/provider/virtual_network/network_base.py +++ b/provider/virtual_network/network_base.py @@ -1,4 +1,5 @@ import logging +import re import shutil import aexpect @@ -287,7 +288,9 @@ def get_ethtool_coalesce(iface): :return: dict-type coalesce parameters """ eth_out = process.run(f'ethtool -c {iface}').stdout_text - items = [x.split(':') for x in eth_out.replace('\t', '').splitlines() if x] + eth_out = re.sub("[\t ]+", "", eth_out) + eth_out = re.sub("n/a", "0", eth_out) + items = [x.split(':') for x in eth_out.splitlines() if x] coalesce = {item[0]: item[1] for item in items[1:] if len(item) == 2} return coalesce From 8f2118b8e66c601974018c32e6b77592a22da711 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 6 Mar 2024 07:17:12 -0500 Subject: [PATCH 0255/1055] rerror_policy: fix disk selection The disk was originally selected by its target name but those names are impersistent and might change in the guest. The test would then sometimes fail as it would read (without I/O errors) from the system disk instead of the new nbd disk when the system was at vdb. Instead, discover the new disk as the one that doesn't have the root filesystem. Signed-off-by: Sebastian Mitterle --- .../src/virtual_disks/virtual_disks_rerror_policy.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_rerror_policy.py b/libvirt/tests/src/virtual_disks/virtual_disks_rerror_policy.py index fda67c34778..6795f6ec231 100755 --- a/libvirt/tests/src/virtual_disks/virtual_disks_rerror_policy.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_rerror_policy.py @@ -57,19 +57,19 @@ def create_customized_nbd_disk(params, nbd_server_host): return customized_disk -def operate_guest_disk_after_killing_nbdserver(vm, device_target): +def operate_guest_disk_after_killing_nbdserver(vm): """ Operate guest disk after killing nbd server. :params vm: VM instance - :params device_target: VM device target """ try: session = vm.wait_for_login() + nbd_disk_name, _ = libvirt_disk.get_non_root_disk_name(session) process.run("pidof qemu-nbd && killall qemu-nbd", ignore_status=True, shell=True) # Execute read disk operation - cmd = "dd if=/dev/%s of=file" % device_target + cmd = "dd if=/dev/%s of=file" % nbd_disk_name session.cmd_status_output(cmd) session.close() except (remote.LoginError, virt_vm.VMError, aexpect.ShellError) as e: @@ -89,7 +89,7 @@ def check_dmeg_and_domblkerror(params, vm, test, check_error_msg=True): error_msg = params.get("error_msg") device_target = params.get("target_dev") - operate_guest_disk_after_killing_nbdserver(vm, device_target) + operate_guest_disk_after_killing_nbdserver(vm) def _check_dmeg_msg(error_msg): """ From 466aaff5f0f65924557067cf6fd92677ae73caff Mon Sep 17 00:00:00 2001 From: Xiaodai Wang Date: Thu, 21 Mar 2024 14:49:03 +0800 Subject: [PATCH 0256/1055] Fix build domain xml error 1) aarch64 doesn't support 'host-model', change it to host-passthrough. 2) Let the script return error instead of cancel when build xml fails. Signed-off-by: Xiaodai Wang --- libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave.cfg | 2 ++ libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave.cfg index af4c5b71855..ef10d641fc9 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave.cfg @@ -43,6 +43,8 @@ - cpu_mode: managedsave_cpumode = "yes" cpu_mode = "host-model" + aarch64: + cpu_mode = "host-passthrough" cpu_match = "exact" cpu_fallback = "forbid" cpu_topology_sockets = "2" diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py index 733303977a2..9688f9a12ad 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py @@ -314,7 +314,7 @@ def build_vm_xml(vm_name, **dargs): vm.start() except Exception as e: logging.error(str(e)) - test.cancel("Build domain xml failed") + test.error("Build domain xml failed") status_error = ("yes" == params.get("status_error", "no")) vm_ref = params.get("managedsave_vm_ref", "name") From c3fd526ba2d45b87b3b5d42356384b55ad8131fc Mon Sep 17 00:00:00 2001 From: Qian Jianhua Date: Fri, 22 Mar 2024 12:43:34 +0800 Subject: [PATCH 0257/1055] virtual_networks: remove spaces before comparing rx_frames Fixed a bug related to rx_frames comparison. The issue was that the collected rx_frames contained spaces, while the expected rx_frames did not. Signed-off-by: Qian Jianhua --- provider/virtual_network/network_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provider/virtual_network/network_base.py b/provider/virtual_network/network_base.py index 61038423629..20d51ac7716 100644 --- a/provider/virtual_network/network_base.py +++ b/provider/virtual_network/network_base.py @@ -291,7 +291,7 @@ def get_ethtool_coalesce(iface): eth_out = re.sub("[\t ]+", "", eth_out) eth_out = re.sub("n/a", "0", eth_out) items = [x.split(':') for x in eth_out.splitlines() if x] - coalesce = {item[0]: item[1] for item in items[1:] if len(item) == 2} + coalesce = {item[0]: item[1].strip() for item in items[1:] if len(item) == 2} return coalesce From b0208aa4436f642b8f8cc2cf6710886bd3659c55 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Fri, 22 Mar 2024 02:51:43 -0400 Subject: [PATCH 0258/1055] Virsh event add adaption for aarch64 Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/event/virsh_event.cfg | 4 ++++ libvirt/tests/src/event/virsh_event.py | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/event/virsh_event.cfg b/libvirt/tests/cfg/event/virsh_event.cfg index 623d255f51e..3cd6b3c73a0 100644 --- a/libvirt/tests/cfg/event/virsh_event.cfg +++ b/libvirt/tests/cfg/event/virsh_event.cfg @@ -120,6 +120,10 @@ current_mem = 4048896 dimm_unit = "m" dimm_size = 128 + cpu_mode = 'host-model' + aarch64: + cpu_mode = 'host-passthrough' + dimm_size = 512 expected_fails = "unplug of device was rejected by the guest" - watchdog_event: event_all_option = "yes" diff --git a/libvirt/tests/src/event/virsh_event.py b/libvirt/tests/src/event/virsh_event.py index 6d2755e1523..1729b5ed0ba 100644 --- a/libvirt/tests/src/event/virsh_event.py +++ b/libvirt/tests/src/event/virsh_event.py @@ -153,6 +153,7 @@ def prepare_vmxml_mem(vmxml): vmxml.max_mem_rt_slots = int(params.get("maxmem_slots")) mem_unit = params.get("mem_unit") vmxml.max_mem_rt_unit = mem_unit + cpu_mode = params.get("cpu_mode") current_mem = int(params.get("current_mem")) vmxml.current_mem = current_mem vmxml.current_mem_unit = mem_unit @@ -177,10 +178,10 @@ def prepare_vmxml_mem(vmxml): if vmxml.xmltreefile.find('cpu'): vmxml_cpu = vmxml.cpu logging.debug("Existing cpu configuration in guest xml:\n%s", vmxml_cpu) - vmxml_cpu.mode = 'host-model' + vmxml_cpu.mode = cpu_mode else: vmxml_cpu = vm_xml.VMCPUXML() - vmxml_cpu.xml = "" + vmxml_cpu.xml = "" % cpu_mode vmxml.vcpu = numa_nodes * 2 vmxml_cpu.numa_cell = vmxml_cpu.dicts_to_cells(numa_dict_list) logging.debug(vmxml_cpu.numa_cell) From 513ffd155efe1df3ee66e9bd09a89dc7c734d8d3 Mon Sep 17 00:00:00 2001 From: lcheng Date: Fri, 12 Jan 2024 17:32:19 +0800 Subject: [PATCH 0259/1055] migration: Add case about query domain job info XXXX - 297944 - VM live migration with copy storage - query domain job info(domjobinfo) Signed-off-by: lcheng --- .../async_job/migration_domjobinfo.cfg | 4 +- .../async_job/query_domain_job_info.cfg | 54 +++++++++++++++++++ .../async_job/migration_domjobinfo.py | 12 +++-- .../async_job/query_domain_job_info.py | 49 +++++++++++++++++ provider/migration/migration_base.py | 12 +++-- 5 files changed, 122 insertions(+), 9 deletions(-) create mode 100644 libvirt/tests/cfg/migration_with_copy_storage/async_job/query_domain_job_info.cfg create mode 100644 libvirt/tests/src/migration_with_copy_storage/async_job/query_domain_job_info.py diff --git a/libvirt/tests/cfg/migration/async_job/migration_domjobinfo.cfg b/libvirt/tests/cfg/migration/async_job/migration_domjobinfo.cfg index eed5f6ccb47..18b8a5910ee 100644 --- a/libvirt/tests/cfg/migration/async_job/migration_domjobinfo.cfg +++ b/libvirt/tests/cfg/migration/async_job/migration_domjobinfo.cfg @@ -36,11 +36,11 @@ virsh_migrate_options = '--live --verbose' variants: - with_precopy: - action_during_mig = '[{"func": "libvirt_monitor.check_domjobinfo_output", "after_event": "iteration: '1'", "func_param": "params", "need_sleep_time": "5"}, {"func": "set_migrate_speed_to_high", "func_param": "params"}]' expected_domjobinfo = {"src_items": {"str_items": {"Job type": "Unbounded", "Operation": "Outgoing migration"}, "int_items": {"Postcopy requests": "0"}, "all_items": ["Time elapsed", "Data processed", "Data remaining", "Data total", "Memory processed", "Memory remaining", "Memory total", "Memory bandwidth", "Dirty rate", "Page size", "Iteration", "Constant pages", "Normal pages", "Normal data", "Expected downtime", "Setup time"]}, "dest_items": {"error_msg": "migration statistics are available only on the source host"}} + action_during_mig = [{"func": "libvirt_monitor.check_domjobinfo_output", "after_event": "iteration: '1'", "func_param": {"vm_name": "${main_vm}", "expected_domjobinfo": ${expected_domjobinfo}, "remote_ip": "${server_ip}"}, "need_sleep_time": "5"}, {"func": "set_migrate_speed_to_high", "func_param": "params"}] expected_domjobinfo_complete = {"src_items": {"str_items": {"Job type": "Completed", "Operation": "Outgoing migration"}, "int_items": {"Postcopy requests": "0", "Memory remaining": "0", "Data remaining": "0", "Dirty rate": "0"}, "all_items": ["Time elapsed", "Data processed", "Data total", "Memory processed", "Memory total", "Memory bandwidth", "Page size", "Iteration", "Constant pages", "Normal pages", "Normal data", "Total downtime", "Setup time"]}, "dest_items": {"str_items": {"Job type": "Completed", "Operation": "Incoming migration"}, "int_items": {"Postcopy requests": "0", "Memory remaining": "0", "Data remaining": "0", "Dirty rate": "0"}, "all_items": ["Time elapsed", "Data processed", "Data total", "Memory processed", "Memory total", "Memory bandwidth", "Page size", "Iteration", "Constant pages", "Normal pages", "Normal data", "Total downtime", "Setup time"]}} - with_postcopy: postcopy_options = '--postcopy --timeout 10 --timeout-postcopy' - action_during_mig = '[{"func": "libvirt_monitor.check_domjobinfo_output", "after_event": "iteration: '1'", "func_param": "params", "need_sleep_time": "15"}, {"func": "set_migrate_speed_to_high", "func_param": "params"}]' expected_domjobinfo = {"src_items": {"str_items": {"Job type": "Unbounded", "Operation": "Outgoing migration"}, "all_items": ["Time elapsed", "Data processed", "Data remaining", "Data total", "Memory processed", "Memory remaining", "Memory total", "Memory bandwidth", "Dirty rate", "Page size", "Iteration", "Postcopy requests", "Constant pages", "Normal pages", "Normal data", "Expected downtime", "Setup time"]}, "dest_items": {"error_msg": "migration statistics are available only on the source host"}} + action_during_mig = [{"func": "libvirt_monitor.check_domjobinfo_output", "after_event": "iteration: '1'", "func_param": {"vm_name": "${main_vm}", "expected_domjobinfo": ${expected_domjobinfo}, "remote_ip": "${server_ip}"}, "need_sleep_time": "15"}, {"func": "set_migrate_speed_to_high", "func_param": "params"}] expected_domjobinfo_complete = {"src_items": {"str_items": {"Job type": "Completed", "Operation": "Outgoing migration"}, "int_items": {"Memory remaining": "0", "Data remaining": "0", "Dirty rate": "0"}, "all_items": ["Time elapsed", "Data processed", "Data total", "Memory processed", "Memory total", "Memory bandwidth", "Page size", "Iteration", "Postcopy requests", "Constant pages", "Normal pages", "Normal data", "Total downtime", "Setup time"]}, "dest_items": {"str_items": {"Job type": "None"}}} diff --git a/libvirt/tests/cfg/migration_with_copy_storage/async_job/query_domain_job_info.cfg b/libvirt/tests/cfg/migration_with_copy_storage/async_job/query_domain_job_info.cfg new file mode 100644 index 00000000000..d23c26fdd60 --- /dev/null +++ b/libvirt/tests/cfg/migration_with_copy_storage/async_job/query_domain_job_info.cfg @@ -0,0 +1,54 @@ +- migration_with_copy_storage.async_job.query_domain_job_info: + type = query_domain_job_info + migration_setup = 'yes' + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + check_network_accessibility_after_mig = "yes" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + setup_nfs = "no" + nfs_mount_dir = + status_error = "no" + str_items = {"Job type": "Unbounded", "Operation": "Outgoing migration"} + s_all_items = ["Time elapsed", "Data processed", "Data remaining", "Data total", "File processed", "File remaining", "File total"] + m_all_items = ["Time elapsed", "Data remaining", "Memory processed", "Memory remaining", "Memory total", "Memory bandwidth", "Page size", "Iteration", "File processed", "File total", "Constant pages", "Normal pages", "Normal data", "Expected downtime", "Setup time"] + m_int_items = {"Dirty rate": "0", "Postcopy requests": "0", "File remaining": "0"} + m_sum_items = {"Data processed": "Memory processed+File processed", "Data total": "Memory total+File total"} + dest_items = {"error_msg": "migration statistics are available only on the source host"} + s_domjobinfo = {"src_items": {"str_items": ${str_items}, "all_items": ${s_all_items}}, "dest_items": ${dest_items}} + m_domjobinfo = {"src_items": {"str_items": ${str_items}, "all_items": ${m_all_items}, "int_items": ${m_int_items}, "sum_items": ${m_sum_items}}, "dest_items": ${dest_items}} + action_during_mig = [{"func": "libvirt_monitor.check_domjobinfo_output", "func_param": {"vm_name": "${main_vm}", "expected_domjobinfo": ${s_domjobinfo}, "remote_ip": "${server_ip}"}, "need_sleep_time": "5"}, {"func": "libvirt_monitor.check_domjobinfo_output", "after_event": "migration-iteration", "func_param": {"vm_name": "${main_vm}", "expected_domjobinfo": ${m_domjobinfo}, "remote_ip": "${server_ip}"}, "wait_for_after_event_timeout": 120}] + src_str_items_complete = {"Job type": "Completed", "Operation": "Outgoing migration"} + src_all_items_complete = ["Time elapsed", "Time elapsed w/o network", "Data processed", "Data total", "Memory processed", "Memory total", "Memory bandwidth", "Page size", "Iteration", "File processed", "File total", "Constant pages", "Normal pages", "Normal data", "Total downtime", "Downtime w/o network", "Setup time"] + src_int_items_complete = {"Data remaining": "0", "Memory remaining": "0", "Dirty rate": "0", "Postcopy requests": "0", "File remaining": "0"} + dest_str_items_complete = {"Job type": "Completed", "Operation": "Incoming migration"} + dest_all_items_complete = ["Time elapsed", "Time elapsed w/o network", "Data processed", "Data total", "Memory processed", "Memory total", "Memory bandwidth", "Page size", "Iteration", "Constant pages", "Normal pages", "Normal data", "Total downtime", "Downtime w/o network", "Setup time"] + dest_int_items_complete = {"Data remaining": "0", "Memory remaining": "0", "Dirty rate": "0", "Postcopy requests": "0"} + expected_domjobinfo_complete = {"src_items": {"str_items": ${src_str_items_complete}, "all_items": ${src_all_items_complete}, "int_items": ${src_int_items_complete}}, "dest_items": {"str_items": ${dest_str_items_complete}, "all_items": ${dest_all_items_complete}, "int_items": ${dest_int_items_complete}}} + variants: + - p2p: + virsh_migrate_options = '--live --p2p --verbose' + - non_p2p: + virsh_migrate_options = '--live --verbose' + variants: + - copy_storage_all: + copy_storage_option = "--copy-storage-all" + - copy_storage_inc: + copy_storage_option = "--copy-storage-inc" diff --git a/libvirt/tests/src/migration/async_job/migration_domjobinfo.py b/libvirt/tests/src/migration/async_job/migration_domjobinfo.py index 434a7873e70..6a6cea9f17e 100644 --- a/libvirt/tests/src/migration/async_job/migration_domjobinfo.py +++ b/libvirt/tests/src/migration/async_job/migration_domjobinfo.py @@ -16,12 +16,18 @@ def verify_test(): Verify steps """ - expected_domjobinfo_complete = params.get("expected_domjobinfo_complete") + expected_domjobinfo_complete = eval(params.get("expected_domjobinfo_complete")) + remote_ip = params.get("server_ip") + postcopy_options = params.get("postcopy_options") + test.log.info("Verify test.") migration_obj.verify_default() if expected_domjobinfo_complete: - params.update({"domjobinfo_options": "--completed"}) - libvirt_monitor.check_domjobinfo_output(params) + libvirt_monitor.check_domjobinfo_output(vm_name, + expected_domjobinfo_complete=expected_domjobinfo_complete, + options="--completed", + postcopy_options=postcopy_options, + remote_ip=remote_ip) vm_name = params.get("migrate_main_vm") diff --git a/libvirt/tests/src/migration_with_copy_storage/async_job/query_domain_job_info.py b/libvirt/tests/src/migration_with_copy_storage/async_job/query_domain_job_info.py new file mode 100644 index 00000000000..a7c15f9575f --- /dev/null +++ b/libvirt/tests/src/migration_with_copy_storage/async_job/query_domain_job_info.py @@ -0,0 +1,49 @@ +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Liping Cheng +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from virttest.utils_libvirt import libvirt_monitor + +from provider.migration import base_steps + + +def run(test, params, env): + """ + To verify that domain job info can be queried during and after live + migration with copy storage. + + """ + def verify_test(): + """ + Verify test + + """ + expected_domjobinfo_complete = eval(params.get("expected_domjobinfo_complete")) + remote_ip = params.get("server_ip") + + test.log.info("Verify test.") + libvirt_monitor.check_domjobinfo_output(vm_name, + expected_domjobinfo_complete=expected_domjobinfo_complete, + options="--completed", + remote_ip=remote_ip) + migration_obj.verify_default() + + vm_name = params.get("migrate_main_vm") + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + migration_obj.setup_connection() + base_steps.prepare_disks_remote(params, vm) + migration_obj.run_migration() + verify_test() + finally: + migration_obj.cleanup_connection() + base_steps.cleanup_disks_remote(params, vm) diff --git a/provider/migration/migration_base.py b/provider/migration/migration_base.py index f14f26d8ec3..dce29036721 100644 --- a/provider/migration/migration_base.py +++ b/provider/migration/migration_base.py @@ -63,7 +63,7 @@ def parse_funcs(action_during_mig, test, params): "action_during_mig_again' is required") act_dict = {} func_param = one_action.get('func_param') - if func_param: + if func_param and isinstance(func_param, str): func_param = eval(func_param) act_dict.update({'func': eval(one_action.get('func')), @@ -513,14 +513,18 @@ def do_common_check(params): second_bandwidth = params.get("second_bandwidth") migration_obj = params.get("migration_obj") vm_name = params.get("main_vm") + remote_ip = params.get("server_ip") + postcopy_options = params.get("postcopy_options") if migration_options == "postcopy_bandwidth" and second_bandwidth: libvirt_domjobinfo.check_domjobinfo(migration_obj.vm, params) # check job info when migration is in paused status - expected_domjobinfo = '{"src_items": {"str_items": {"Job type": "Unbounded", "Operation": "Outgoing migration"}}}' - params.update({"expected_domjobinfo": expected_domjobinfo}) - libvirt_monitor.check_domjobinfo_output(params) + expected_domjobinfo = {"src_items": {"str_items": {"Job type": "Unbounded", "Operation": "Outgoing migration"}}} + libvirt_monitor.check_domjobinfo_output(vm_name, + expected_domjobinfo=expected_domjobinfo, + postcopy_options=postcopy_options, + remote_ip=remote_ip) # check domain state with reason check_vm_state(params) From 92a720e6bbe330d4cc7397cd90a1d794a5ce3967 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Fri, 1 Mar 2024 18:12:18 +0800 Subject: [PATCH 0260/1055] Fix multiple numa hugepage cases on arm This is to make the script adapted to different huge pages provided by different arches. Enable support for kernel 4k and 64k with different default huge page size on ARM. Signed-off-by: Dan Zheng --- .../memory_binding_setting.cfg | 20 +++----- .../memory_binding_with_emulator_thread.cfg | 7 ++- .../specific_numa_memory_bind_hugepage.cfg | 19 ++++---- .../memory_binding_setting.py | 6 ++- .../memory_binding_with_emulator_thread.py | 7 ++- .../specific_numa_memory_bind_hugepage.py | 4 +- provider/numa/numa_base.py | 46 +++++++++++++++++-- 7 files changed, 72 insertions(+), 37 deletions(-) diff --git a/libvirt/tests/cfg/numa/guest_numa_node_tuning/memory_binding_setting.cfg b/libvirt/tests/cfg/numa/guest_numa_node_tuning/memory_binding_setting.cfg index 51be2e216d1..3eea87a728f 100644 --- a/libvirt/tests/cfg/numa/guest_numa_node_tuning/memory_binding_setting.cfg +++ b/libvirt/tests/cfg/numa/guest_numa_node_tuning/memory_binding_setting.cfg @@ -1,14 +1,14 @@ - guest_numa_node_tuning.memory_binding_setting: type = memory_binding_setting take_regular_screendumps = no - start_vm = "no" + start_vm = "no" mem_value = "'memory': 2072576, 'memory_unit': 'KiB'" - target_hugepages = "512" + hugepage_mem = 1048576 cpu_mode = 'host-model' aarch64: mem_value = "'memory': 2097152, 'memory_unit': 'KiB'" - target_hugepages = "3" cpu_mode = 'host-passthrough' + hugepage_mem = 1572864 current_mem_value = ${mem_value} vm_attrs = {${mem_value}, ${current_mem_value}, 'cpu': {'mode': '${cpu_mode}'}} variants memory_binding_nodeset: @@ -18,22 +18,16 @@ single_host_node = no variants memory_binding_mode: - mem_mode_strict: - mem_mode = 'strict' + mem_mode = 'strict' - mem_mode_interleave: - mem_mode = 'interleave' + mem_mode = 'interleave' - mem_mode_preferred: - mem_mode = 'preferred' + mem_mode = 'preferred' - mem_mode_restrictive: - mem_mode = 'restrictive' + mem_mode = 'restrictive' variants pagesize: - default_pagesize: only single_host_node - default_pagesize = 4 - aarch64: - default_pagesize = 64 - hugepage: memory_backing = {'hugepages': {}} - expected_hugepage_size = 2048 - aarch64: - expected_hugepage_size = 524288 numa_memory = {'mode': '${mem_mode}', 'nodeset': '%s'} diff --git a/libvirt/tests/cfg/numa/guest_numa_node_tuning/memory_binding_with_emulator_thread.cfg b/libvirt/tests/cfg/numa/guest_numa_node_tuning/memory_binding_with_emulator_thread.cfg index b79c8a8fbf0..4136b619fa6 100644 --- a/libvirt/tests/cfg/numa/guest_numa_node_tuning/memory_binding_with_emulator_thread.cfg +++ b/libvirt/tests/cfg/numa/guest_numa_node_tuning/memory_binding_with_emulator_thread.cfg @@ -38,9 +38,8 @@ variants pagesize: - default_pagesize: - hugepage: - memory_backing = {'hugepages': {'pages': [{'size': '2', 'unit': 'M'}]}} - hugepage_size = 2048 - kernel_hp_file = '/sys/devices/system/node/node%s/hugepages/hugepages-${hugepage_size}kB/nr_hugepages' - target_hugepages = 1536 + hugepage_mem = 3145728 + memory_backing = {'hugepages': {'pages': [{'size': '%s', 'unit': 'KiB'}]}} + kernel_hp_file = '/sys/devices/system/node/node%s/hugepages/hugepages-%skB/nr_hugepages' numa_memory = {'mode': '${mem_mode}', 'nodeset': '%s'} numa_memnode = [{'cellid': '0', 'mode': '${mem_mode}', 'nodeset': '%s'}] diff --git a/libvirt/tests/cfg/numa/guest_numa_node_tuning/specific_numa_memory_bind_hugepage.cfg b/libvirt/tests/cfg/numa/guest_numa_node_tuning/specific_numa_memory_bind_hugepage.cfg index 9c83599718a..becb317ad9a 100644 --- a/libvirt/tests/cfg/numa/guest_numa_node_tuning/specific_numa_memory_bind_hugepage.cfg +++ b/libvirt/tests/cfg/numa/guest_numa_node_tuning/specific_numa_memory_bind_hugepage.cfg @@ -1,14 +1,13 @@ - guest_numa_node_tuning.specific_numa_memory_bind_hugepage: type = specific_numa_memory_bind_hugepage take_regular_screendumps = no - start_vm = "no" + start_vm = "no" max_mem_value = "'max_mem_rt': 15360000, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'" mem_value = "'memory': 2097152, 'memory_unit': 'KiB'" - current_mem_value = ${mem_value} - hugepage_size = 2048 - memory_backing = {'hugepages': {'pages': [{'size': '${hugepage_size}', 'unit': 'KiB', 'nodeset': '0'}]}} - kernel_hp_file = '/sys/devices/system/node/node%s/hugepages/hugepages-${hugepage_size}kB/nr_hugepages' - target_hugepages = 500 + current_mem_value = ${mem_value} + hugepage_mem = 1048576 + memory_backing = {'hugepages': {'pages': [{'size': '%s', 'unit': 'KiB', 'nodeset': '0'}]}} + kernel_hp_file = '/sys/devices/system/node/node%s/hugepages/hugepages-%skB/nr_hugepages' single_host_node = yes cpu_mode = 'host-model' no s390x @@ -16,7 +15,7 @@ cpu_mode = 'host-passthrough' variants memory_binding_mode: - mem_mode_strict: - mem_mode = 'strict' + mem_mode = 'strict' - mem_mode_interleave: mem_mode = 'interleave' - mem_mode_preferred: @@ -26,12 +25,12 @@ numa_memory = {'mode': '${mem_mode}', 'nodeset': '%s'} variants: - enough_numa_mem: - vm_node0_mem = 1024000 + vm_node0_mem = 1048576 vm_node1_mem = 1073152 - scarce_numa_mem: - vm_node0_mem = 1048576 + vm_node0_mem = 1572864 vm_node1_mem = 1048576 err_msg = 'unable to map backing store for guest RAM: Cannot allocate memory' - numa_cell = "'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${vm_node0_mem}', 'unit': 'KiB'}, {'id': '1', 'cpus': '2-3', 'memory': '${vm_node1_mem}', 'unit': 'KiB'}]" + numa_cell = "'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${vm_node0_mem}', 'unit': 'KiB'}, {'id': '1', 'cpus': '2-3', 'memory': '${vm_node1_mem}', 'unit': 'KiB'}]" numa_memnode = [{'cellid': '0', 'mode': '${mem_mode}', 'nodeset': '%s'}] vm_attrs = {${max_mem_value}, ${mem_value}, ${current_mem_value}, 'vcpu': 4, 'cpu': {'mode': '${cpu_mode}', ${numa_cell}}} diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py b/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py index 1973261281e..4bfd28f3e02 100644 --- a/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py @@ -13,6 +13,7 @@ import re import platform +from avocado.utils import memory from avocado.utils import process from virttest import libvirt_cgroup @@ -34,6 +35,8 @@ def setup_default(test_obj): """ test_obj.setup() if test_obj.params.get('memory_backing'): + numa_base.adjust_parameters(test_obj.params, + hugepage_mem=int(test_obj.params.get("hugepage_mem"))) expected_hugepage_size = test_obj.params.get('expected_hugepage_size') hpc = test_setup.HugePageConfig(test_obj.params) all_nodes = test_obj.online_nodes_withmem @@ -101,9 +104,8 @@ def verify_host_numa_memory_allocation(test_obj): has_huge = True if re.search('huge', out_numa_maps) else False N0_value = re.findall('N%s=(\d+)' % all_nodes[0], out_numa_maps) N1_value = re.findall('N%s=(\d+)' % all_nodes[1], out_numa_maps) - default_pagesize = test_obj.params.get('default_pagesize') expected_hugepage_size = test_obj.params.get('expected_hugepage_size') - psize = expected_hugepage_size if memory_backing else default_pagesize + psize = expected_hugepage_size if memory_backing else memory.get_page_size() has_kernelpage = True if re.search('kernelpagesize_kB=%s' % psize, out_numa_maps) else False def _check_values(expect_huge, expect_N0, expect_N1, expect_sum=None): diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_with_emulator_thread.py b/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_with_emulator_thread.py index 915c6a27ffd..b97efea87ff 100644 --- a/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_with_emulator_thread.py +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_with_emulator_thread.py @@ -26,12 +26,15 @@ def setup_default(test_obj): :param test_obj: NumaTest object """ - test_obj.setup(node_index=1) + test_obj.setup() if test_obj.params.get('memory_backing'): + numa_base.adjust_parameters(test_obj.params, + node_index='1', + hugepage_mem=int(test_obj.params.get("hugepage_mem"))) hpc = test_setup.HugePageConfig(test_obj.params) hpc.setup() utils_libvirtd.Libvirtd().restart() - test_obj.params['hp_config_2M'] = hpc + test_obj.params['hpc_list'] = [hpc] test_obj.test.log.debug("Step: setup is done") diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/specific_numa_memory_bind_hugepage.py b/libvirt/tests/src/numa/guest_numa_node_tuning/specific_numa_memory_bind_hugepage.py index 5bc9b2dafd8..d4ece274c47 100644 --- a/libvirt/tests/src/numa/guest_numa_node_tuning/specific_numa_memory_bind_hugepage.py +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/specific_numa_memory_bind_hugepage.py @@ -25,10 +25,12 @@ def setup_default(test_obj): :param test_obj: NumaTest object """ test_obj.setup() + numa_base.adjust_parameters(test_obj.params, + hugepage_mem=int(test_obj.params.get("hugepage_mem"))) hpc = test_setup.HugePageConfig(test_obj.params) hpc.setup() utils_libvirtd.Libvirtd().restart() - test_obj.params['hp_config_2M'] = hpc + test_obj.params['hpc_list'] = [hpc] test_obj.test.log.debug("Step: setup is done") diff --git a/provider/numa/numa_base.py b/provider/numa/numa_base.py index 81655fc0f5b..cd7d6baa549 100644 --- a/provider/numa/numa_base.py +++ b/provider/numa/numa_base.py @@ -66,13 +66,10 @@ def check_numa_nodes_availability(self, expect_nodes_num=2, expect_node_free_mem self.test.log.debug("Host numa node '%s' free memory " "is %s which meets the requirement", a_node, free_mem_min) - def setup(self, node_index=0, expect_nodes_num=2, expect_node_free_mem_min=None): + def setup(self, expect_nodes_num=2, expect_node_free_mem_min=None): self.check_numa_nodes_availability(expect_nodes_num, expect_node_free_mem_min) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(self.vm.name) self.params['backup_vmxml'] = vmxml.copy() - kernel_hp_file = self.params.get('kernel_hp_file') - if kernel_hp_file and kernel_hp_file.count('/sys/devices/system/node/'): - self.params['kernel_hp_file'] = kernel_hp_file % self.online_nodes_withmem[node_index] def teardown(self): if self.vm.is_alive(): @@ -83,7 +80,9 @@ def teardown(self): backup_vmxml.sync() hpc_2M = self.params.get('hp_config_2M') hpc_1G = self.params.get('hp_config_1G') - for hpc in [hpc_2M, hpc_1G]: + hpc_list = self.params.get('hpc_list', []) + hpc_list.extend([hpc_2M, hpc_1G]) + for hpc in hpc_list: if hpc: hpc.cleanup() @@ -237,3 +236,40 @@ def check_hugepage_availability(pages_list): "not supported on current " "arch (support: %s)" % (size, supported_hugepages)) + + +def adjust_parameters(params, hugepage_size=None, node_index='0', hugepage_mem=1048576): + """ + This function will adjust parameters according to current + architecture and given hugepage size and parameters. + + Used parameters: + - memory_backing: optional + - kernel_hp_file: optional + + Adjusted parameters: + - hugepage_size: hugepage size in KiB to be allocated + - kernel_hp_file: huge page kernel file, + like /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages + - expected_hugepage_size: expected hugepage size for the test + - target_hugepages: hugepage numbers to be allocated + Above four parameters are used by test_setup.HugePageConfig() + - memory_backing: memory backing dict used by test case, like + {'hugepages': {'pages': [{'size': '%s', 'unit': 'KiB'}]}} + + :param params: dict, test parameters + :param hugepage_size: int, huge page size in KiB + :param node_index: str, the numa node index + :param hugepage_mem: int, the hugepage memory in KiB to be allocated + """ + default_hugepage_size = memory.get_huge_page_size() + page_size = default_hugepage_size if hugepage_size is None else hugepage_size + params['hugepage_size'] = page_size + memory_backing = params['memory_backing'] + if memory_backing and memory_backing.count('%s'): + params['memory_backing'] = memory_backing % str(page_size) + kernel_hp_file = params.get('kernel_hp_file', '') + if kernel_hp_file.count('/sys/devices/system/node/'): + params['kernel_hp_file'] = kernel_hp_file % (node_index, str(page_size)) + params['expected_hugepage_size'] = page_size + params['target_hugepages'] = hugepage_mem//page_size From 5d6a4bb3a69e803acd6ac5e92607d9afb01eb0ef Mon Sep 17 00:00:00 2001 From: Yan Fu Date: Fri, 22 Mar 2024 11:09:27 +0800 Subject: [PATCH 0261/1055] Wait for 'virsh event' session to start Signed-off-by: Yan Fu --- libvirt/tests/src/virtual_disks/virtual_disks_cdrom_device.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_cdrom_device.py b/libvirt/tests/src/virtual_disks/virtual_disks_cdrom_device.py index fc85b56b11b..87d5b77ef0b 100755 --- a/libvirt/tests/src/virtual_disks/virtual_disks_cdrom_device.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_cdrom_device.py @@ -4,6 +4,7 @@ import re import string import aexpect +import time from avocado.utils import linux_modules from avocado.utils import process @@ -452,7 +453,7 @@ def check_scsi_cdrom_hot_eject(vm, params, test): virsh_session = aexpect.ShellSession(virsh.VIRSH_EXEC, auto_close=True) event_cmd = "event --domain %s --event tray-change --loop" % vm.name virsh_session.sendline(event_cmd) - + time.sleep(60) device_target = params.get("target_dev") virsh.change_media(vm.name, device_target, " --eject --live", ignore_status=False, debug=True) @@ -478,6 +479,7 @@ def _get_qemu_state(): # check tray-change event virsh_session.send_ctrl("^C") ret_output = virsh_session.get_stripped_output().replace("\n", "").strip() + LOG.debug("event:\n%s", ret_output) event_matched_opened = r"event 'tray-change' for domain '%s' disk .*opened" % vm.name if not re.search(event_matched_opened, ret_output): From 404b32aa0a11fdab63b4102484e8464af01bf541 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Fri, 26 Jan 2024 02:40:14 -0500 Subject: [PATCH 0262/1055] Add new case of update interface source - VIRT-294747 - [update-device][source] Live update interface source setting Signed-off-by: Haijiao Zhao --- .../update_device/update_iface_source.cfg | 28 ++++++ .../update_device/update_iface_source.py | 91 +++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/update_device/update_iface_source.cfg create mode 100644 libvirt/tests/src/virtual_network/update_device/update_iface_source.py diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_iface_source.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_iface_source.cfg new file mode 100644 index 00000000000..8f179d20612 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/update_device/update_iface_source.cfg @@ -0,0 +1,28 @@ +- virtual_network.update_device.iface_source: + type = update_iface_source + host_iface = + start_vm = no + outside_ip = 'www.redhat.com' + vm_ping_outside = pass + timeout = 240 + nat_net_attrs = {'name': net_name, 'forward': {'mode': 'nat'}, 'ips': [{'dhcp_ranges': {'attrs': {'start': '192.168.120.2', 'end': '192.168.120.254'}}, 'address': '192.168.120.1', 'netmask': '255.255.255.0'}]} + variants scenario: + - default_net_to_nat: + iface_attrs = {'source': {'network': 'default'}, 'type_name': 'network'} + net_attrs = ${nat_net_attrs} + update_attrs = {'source': {'network': net_name}} + - br_to_br: + iface_attrs = {'source': {'bridge': 'virbr0'}, 'type_name': 'bridge'} + net_attrs = ${nat_net_attrs} + update_attrs = {'source': {'bridge': net_br}} + - direct_vepa_to_br: + status_error = yes + err_msg = Operation not supported: unable to change config on 'direct' network type + iface_attrs = {'type_name': 'direct', 'source': {'dev': host_iface, 'mode': 'vepa'}} + update_attrs = {'source': {'dev': host_iface, 'mode': 'bridge'}} + - default_net_to_direct_net: + status_error = yes + err_msg = Operation not supported: unable to change config on 'network' network type + iface_attrs = {'source': {'network': 'default'}, 'type_name': 'network'} + net_attrs = {'name': net_name, 'forward': {'mode': 'bridge'}, 'forward_interface': [{'dev': host_iface}]} + update_attrs = {'source': {'network': net_name}} diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_source.py b/libvirt/tests/src/virtual_network/update_device/update_iface_source.py new file mode 100644 index 00000000000..a3e21bd93da --- /dev/null +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_source.py @@ -0,0 +1,91 @@ +import logging + +from virttest import utils_misc +from virttest import utils_net +from virttest import virsh +from virttest.libvirt_xml import network_xml +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_network +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test live update interface source setting + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + rand_id = utils_misc.generate_random_string(3) + net_name = 'net_' + rand_id + host_iface = params.get('host_iface') + host_iface = host_iface if host_iface else utils_net.get_net_if( + state='UP')[0] + iface_attrs = eval(params.get('iface_attrs', '{}')) + net_attrs = eval(params.get('net_attrs', '{}')) + status_error = 'yes' == params.get('status_error', 'no') + err_msg = params.get('err_msg') + ips = {'outside_ip': params.get('outside_ip')} + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + vmxml.del_device('interface', by_tag=True) + libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs) + LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + if net_attrs: + libvirt_network.create_or_del_network(net_attrs) + net_xml = network_xml.NetworkXML.new_from_net_dumpxml( + net_attrs["name"]) + net_xml.debug_xml() + if net_xml.forward['mode'] == 'nat': + net_br = net_xml.bridge['name'] + + vm.start() + session = vm.wait_for_serial_login() + network_base.ping_check(params, ips, session, force_ipv4=True) + + iface = network_base.get_iface_xml_inst(vm_name, 'on vm') + update_attrs = eval(params.get('update_attrs', '{}')) + LOG.debug(f'Update iface with attrs: {update_attrs}') + iface.setup_attrs(**update_attrs) + LOG.debug(f'Update iface with xml:\n{iface}') + + up_result = virsh.update_device(vm_name, iface.xml, debug=True) + libvirt.check_exit_status(up_result, status_error) + if err_msg: + libvirt.check_result(up_result, err_msg) + return + + iface_update = network_base.get_iface_xml_inst(vm_name, 'after update') + LOG.debug(f'iface source after update: {iface_update.source}') + if not iface_update.source.items() >= update_attrs['source'].items(): + test.fail('Source of interface xml not correctly updated') + + mac = iface.mac_address + vm_iface = utils_net.get_linux_ifname(session, mac) + LOG.debug(f'Interface inside vm: {vm_iface}') + + LOG.info('Run dhclient to refresh network.') + utils_net.restart_guest_network(session, mac) + + vm_iface_info = utils_net.get_linux_iface_info( + vm_iface, session=session) + LOG.debug(f'iface info inside vm:\n{vm_iface_info}') + + network_base.ping_check(params, ips, session, force_ipv4=True) + + finally: + bkxml.sync() + if 'session' in locals(): + session.close() + if net_attrs: + libvirt_network.create_or_del_network(net_attrs, is_del=True) From e2d865639f1c04e5c55c4f00689862e1c721e433 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Mon, 25 Mar 2024 22:53:12 -0400 Subject: [PATCH 0263/1055] Skip ipv6 test once host has multipath ipv6 route Passt can not recognize the multipath ipv6 route. Skip the ipv6 test once the host has multipath ipv6 route. Signed-off-by: Yalan Zhang --- .../src/virtual_network/passt/passt_transfer_file.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py index 2fb33af5f8f..6dae58ad615 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py +++ b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py @@ -116,6 +116,15 @@ def run(test, params, env): Test file transfer between host and vm with passt backend interface """ libvirt_version.is_libvirt_feature_supported(params) + # Since passt can not handle the multipath route on the host, skip the ipv6 + # related test if host has multipath route. When there is multipath route, + # the utils_net.get_default_gateway() will return none. + ip_ver = params.get('ip_ver') + if ip_ver == "ipv6": + if not utils_net.get_default_gateway(ip_ver=ip_ver): + test.cancel("Host has multipath route which can not be " + "recognized by passt and passt will disable ipv6.") + root = 'root_user' == params.get('user_type', '') if root: vm_name = params.get('main_vm') @@ -153,7 +162,6 @@ def run(test, params, env): iface_attrs['backend']['logFile'] = log_file iface_attrs['source']['dev'] = host_iface direction = params.get('direction') - ip_ver = params.get('ip_ver') vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name, virsh_instance=virsh_ins) From efbd81b130454f4df5921fac2e3b715168246624 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Tue, 26 Mar 2024 01:09:48 -0400 Subject: [PATCH 0264/1055] Stop guest start before case execution Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/virsh_cmd/domain/virsh_memtune.cfg | 1 + libvirt/tests/src/virsh_cmd/domain/virsh_memtune.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_memtune.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_memtune.cfg index 079e35d2014..f462eaa9734 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_memtune.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_memtune.cfg @@ -1,5 +1,6 @@ - virsh.memtune: install setup image_copy unattended_install.cdrom type = virsh_memtune + start_vm = no # Values are in KiB variants: - positive_test: diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_memtune.py b/libvirt/tests/src/virsh_cmd/domain/virsh_memtune.py index 45057a1da7e..68e422c1423 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_memtune.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_memtune.py @@ -178,7 +178,8 @@ def run(test, params, env): # Get the vm name, pid of vm and check for alive vm = env.get_vm(params["main_vm"]) - vm.verify_alive() + if not vm.is_alive(): + vm.start() pid = vm.get_pid() # Resolve the memory cgroup path for a domain From 66cc8c571e755894f1c463c53dbbe5fabf1375a0 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Tue, 26 Mar 2024 05:17:44 -0400 Subject: [PATCH 0265/1055] Fixup:Shell command timeout error when running curl Ignore errors when trying to download a large file. The purpose was not to actually get the file, but to create a lot of network trafic, therefore whether the command succeeds or not doesn't matter. Signed-off-by: Haijiao Zhao --- libvirt/tests/src/virtual_network/iface_stat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_network/iface_stat.py b/libvirt/tests/src/virtual_network/iface_stat.py index 5f117b9b4eb..cdc558feef8 100644 --- a/libvirt/tests/src/virtual_network/iface_stat.py +++ b/libvirt/tests/src/virtual_network/iface_stat.py @@ -140,7 +140,7 @@ def _collect_and_compare_stat(vm_name, session, **virsh_args): for _ in range(3): session.cmd('curl -O https://avocado-project.org/data/' 'assets/jeos/27/jeos-27-64.qcow2.xz -L', - timeout=240) + timeout=240, ignore_all_errors=True) host_iface_stat = get_host_iface_stat(vm_name, iface_target_dev, **virsh_args) From d4976fa0c15e41db2a18abb110a35f38ad9210b9 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Mon, 25 Mar 2024 21:09:49 +0800 Subject: [PATCH 0266/1055] numa_topology_with_hugepage: fix hugepage for arm This is to enable hugepage test for ARM - 64k: 512M and 2M - 4k: 2M and 1G Signed-off-by: Dan Zheng --- .../numa_topology_with_hugepage.cfg | 46 +++---- .../numa_topology_with_hugepage.py | 123 ++++++++---------- provider/numa/numa_base.py | 19 ++- 3 files changed, 90 insertions(+), 98 deletions(-) diff --git a/libvirt/tests/cfg/numa/guest_numa_topology/numa_topology_with_hugepage.cfg b/libvirt/tests/cfg/numa/guest_numa_topology/numa_topology_with_hugepage.cfg index 509a9da1ba6..4f5fe193e4c 100644 --- a/libvirt/tests/cfg/numa/guest_numa_topology/numa_topology_with_hugepage.cfg +++ b/libvirt/tests/cfg/numa/guest_numa_topology/numa_topology_with_hugepage.cfg @@ -3,50 +3,50 @@ take_regular_screendumps = no start_vm = "no" max_mem_value = "'max_mem_rt': 8388608, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'" - target_hugepages_2M = 500 - target_hugepages_1G = 1 - hugepage_path_2M = '/dev/hugepages' - hugepage_path_1G = '/dev/hugepages1G' pat_in_qemu_cmdline = '-object {"qom-type":".*","id":"ram-node0","mem-path":"%s","prealloc":true,"size":%d} .* -object {"qom-type":".*","id":"ram-node1",%s%s"size":%d}' cpu_mode = 'host-model' no s390-virtio aarch64: cpu_mode = 'host-passthrough' variants hp_size: - - 2M: - mem_value = "'memory': 2097152, 'memory_unit': 'KiB'" - vm_numa_node0_mem = 1024000 - vm_numa_node1_mem = 1073152 - memory_backing = {'hugepages': {'pages': [{'size': '2048', 'unit': 'KiB', 'nodeset': '0'}]}} - - 1G: + - default_hugepage: mem_value = "'memory': 2121728, 'memory_unit': 'KiB'" vm_numa_node0_mem = 1048576 vm_numa_node1_mem = 1073152 - memory_backing = {'hugepages': {'pages': [{'size': '1048576', 'unit': 'KiB', 'nodeset': '0'}]}} - - 512M: - hugepage_path_512M = '/dev/hugepages512M' - target_hugepages_512M = 2 + hugepage_mem = 1048576 + memory_backing = {'hugepages': {'pages': [{'size': '%s', 'unit': 'KiB', 'nodeset': '0'}]}} + kernel_hp_file = "/sys/kernel/mm/hugepages/hugepages-%skB/nr_hugepages" + - 1G: mem_value = "'memory': 2121728, 'memory_unit': 'KiB'" vm_numa_node0_mem = 1048576 vm_numa_node1_mem = 1073152 - memory_backing = {'hugepages': {'pages': [{'size': '524288', 'unit': 'KiB', 'nodeset': '0'}]}} - - 2M_512M: - hugepage_path_512M = '/dev/hugepages512M' - target_hugepages_512M = 2 + hugepage_mem_by_size = {1048576: 1048576} + memory_backing = {'hugepages': {'pages': [{'size': '1048576', 'unit': 'KiB', 'nodeset': '0'}]}} + kernel_hp_file = "/sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages" + - 512M_2M: + only aarch64 mem_value = "'memory': 2072576, 'memory_unit': 'KiB'" - vm_numa_node0_mem = 1024000 - vm_numa_node1_mem = 1048576 - memory_backing = {'hugepages': {'pages': [{'size': '512', 'unit': 'M', 'nodeset': '1'}, {'size': '2', 'unit': 'M', 'nodeset': '0'}]}} + vm_numa_node0_mem = 1048576 + vm_numa_node1_mem = 1024000 + hugepage_mem_by_size = {524288: 1048576, 2048: 1024000} + memory_backing = {'hugepages': {'pages': [{'size': '512', 'unit': 'M', 'nodeset': '0'}, {'size': '2', 'unit': 'M', 'nodeset': '1'}]}} + kernel_hp_file = "/sys/kernel/mm/hugepages/hugepages-%skB/nr_hugepages" - 2M_1G: + only q35,aarch64 mem_value = "'memory': 2072576, 'memory_unit': 'KiB'" vm_numa_node0_mem = 1024000 vm_numa_node1_mem = 1048576 - memory_backing = {'hugepages': {'pages': [{'size': '1', 'unit': 'G', 'nodeset': '1'}, {'size': '2', 'unit': 'M', 'nodeset': '0'}]}} + hugepage_mem_by_size = {2048: 1024000, 1048576: 1048576} + memory_backing = {'hugepages': {'pages': [{'size': '2', 'unit': 'M', 'nodeset': '0'}, {'size': '1', 'unit': 'G', 'nodeset': '1'}]}} + kernel_hp_file = "/sys/kernel/mm/hugepages/hugepages-%skB/nr_hugepages" - scarce_mem: mem_value = "'memory': 2097152, 'memory_unit': 'KiB'" vm_numa_node0_mem = 1048576 vm_numa_node1_mem = 1048576 - memory_backing = {'hugepages': {'pages': [{'size': '2048', 'unit': 'KiB', 'nodeset': '0'}]}} + hugepage_mem = 1024000 + memory_backing = {'hugepages': {'pages': [{'size': '%s', 'unit': 'KiB', 'nodeset': '0'}]}} + kernel_hp_file = "/sys/kernel/mm/hugepages/hugepages-%skB/nr_hugepages" + err_msg = "unable to map backing store for guest RAM: Cannot allocate memory" current_mem_value = ${mem_value} numa_cell = "'numa_cell': [{'cpus': '0-1', 'memory': '${vm_numa_node0_mem}'}, {'cpus': '2-3', 'memory': '${vm_numa_node1_mem}'}]" vm_attrs = {${max_mem_value}, ${mem_value}, ${current_mem_value}, 'vcpu': 4, 'cpu': {'mode': '${cpu_mode}', ${numa_cell}}} diff --git a/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_hugepage.py b/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_hugepage.py index dce1771f92f..64b72c575ff 100644 --- a/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_hugepage.py +++ b/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_hugepage.py @@ -10,6 +10,7 @@ import re +from avocado.utils import memory from avocado.utils import process from virttest import utils_libvirtd @@ -43,31 +44,26 @@ def setup_default(test_obj): if memory_backing: numa_base.check_hugepage_availability(memory_backing["hugepages"]["pages"]) test_obj.setup() - params_2M = {'hugepage_size': '2048', - 'vm_hugepage_mountpoint': test_obj.params.get('hugepage_path_2M'), - 'target_hugepages': test_obj.params.get('target_hugepages_2M'), - 'kernel_hp_file': '/sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages'} - params_512M = {'hugepage_size': '524288', - 'vm_hugepage_mountpoint': test_obj.params.get('hugepage_path_512M'), - 'target_hugepages': test_obj.params.get('target_hugepages_512M'), - 'kernel_hp_file': '/sys/kernel/mm/hugepages/hugepages-524288kB/nr_hugepages'} - params_1G = {'hugepage_size': '1048576', - 'vm_hugepage_mountpoint': test_obj.params.get('hugepage_path_1G'), - 'target_hugepages': test_obj.params.get('target_hugepages_1G'), - 'kernel_hp_file': '/sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages'} hp_size = test_obj.params.get('hp_size') - if hp_size in ['2M', '2M_1G', '2M_512M', 'scarce_mem']: - test_obj.params.update(params_2M) - hpconfig_2M = setup_hugepage(test_obj.params) - test_obj.params['hp_config_2M'] = hpconfig_2M - if hp_size in ['512M', '2M_512M']: - test_obj.params.update(params_512M) - hpconfig_512M = setup_hugepage(test_obj.params) - test_obj.params['hp_config_512M'] = hpconfig_512M - if hp_size in ['1G', '2M_1G']: - test_obj.params.update(params_1G) - hpconfig_1G = setup_hugepage(test_obj.params) - test_obj.params['hp_config_1G'] = hpconfig_1G + hpc_list = [] + if hp_size in ['default_hugepage', 'scarce_mem']: + numa_base.adjust_parameters(test_obj.params, + hugepage_mem=int(test_obj.params.get('hugepage_mem'))) + hpconfig = setup_hugepage(test_obj.params) + hpc_list.append(hpconfig) + mapping_hp_kib = {'2M': 2048, '512M': 524288, '1G': 1048576} + for pg_size in ['2M', '512M', '1G']: + if hp_size.count(pg_size): + hugepage_size = mapping_hp_kib[pg_size] + hugepage_mem_by_size = eval(test_obj.params.get("hugepage_mem_by_size")) + new_params = test_obj.params.copy() + numa_base.adjust_parameters(new_params, + hugepage_size=hugepage_size, + hugepage_mem=hugepage_mem_by_size[hugepage_size]) + hpconfig = setup_hugepage(new_params) + hpc_list.append(hpconfig) + test_obj.params[pg_size] = new_params + test_obj.params['hpc_list'] = hpc_list utils_libvirtd.Libvirtd().restart() test_obj.test.log.debug("Step: setup is done") @@ -86,21 +82,6 @@ def prepare_vm_xml(test_obj): return vmxml -def produce_expected_error(test_obj): - """ - produce the expected error message - - :param test_obj: NumaTest object - - :return: str, error message to be checked - """ - hugepage_size = test_obj.params.get('hp_size') - err_msg = "" - if hugepage_size == 'scarce_mem': - err_msg = "unable to map backing store for guest RAM: Cannot allocate memory" - return err_msg - - def verify_hugepage_memory_in_numa_maps(test_obj): """ Verify hugepage memory in numa_maps is correct @@ -122,21 +103,26 @@ def _check_numa_maps(mem_size, hugepage_num, pagesize): "numa_maps output '%s'" % (pat, out_numa_maps)) hp_size = test_obj.params.get('hp_size') - if hp_size in ['2M', '2M_512M', '2M_1G']: + params_2M = test_obj.params.get('2M') + params_512M = test_obj.params.get('512M') + params_1G = test_obj.params.get('1G') + if hp_size in ['default_hugepage']: _check_numa_maps(test_obj.params.get('vm_numa_node0_mem'), - test_obj.params.get('target_hugepages_2M'), '2048') - if hp_size == '512M': + test_obj.params.get('target_hugepages'), str(memory.get_huge_page_size())) + if hp_size in ['512M_2M']: _check_numa_maps(test_obj.params.get('vm_numa_node0_mem'), - test_obj.params.get('target_hugepages_512M'), '524288') - if hp_size == '1G': - _check_numa_maps(test_obj.params.get('vm_numa_node0_mem'), - test_obj.params.get('target_hugepages_1G'), '1048576') - if hp_size == '2M_512M': + params_512M.get('target_hugepages'), '524288') _check_numa_maps(test_obj.params.get('vm_numa_node1_mem'), - test_obj.params.get('target_hugepages_512M'), '524288') - if hp_size == '2M_1G': + params_2M.get('target_hugepages'), '2048') + if hp_size in ['2M_1G']: + _check_numa_maps(test_obj.params.get('vm_numa_node0_mem'), + params_2M.get('target_hugepages'), '2048') _check_numa_maps(test_obj.params.get('vm_numa_node1_mem'), - test_obj.params.get('target_hugepages_1G'), '1048576') + params_1G.get('target_hugepages'), '1048576') + if hp_size == '1G': + _check_numa_maps(test_obj.params.get('vm_numa_node0_mem'), + params_1G.get('target_hugepages'), '1048576') + test_obj.test.log.debug("Step: verify hugepage memory in numa_maps: PASS") @@ -148,22 +134,23 @@ def check_qemu_cmdline(test_obj): """ pat_in_qemu_cmdline = test_obj.params.get('pat_in_qemu_cmdline') hp_size = test_obj.params.get('hp_size') - hugepage_path_1G = test_obj.params.get('hugepage_path_1G') - hugepage_path_512M = test_obj.params.get('hugepage_path_512M') - hugepage_path_2M = test_obj.params.get('hugepage_path_2M') - if hp_size in ['2M', '2M_512M', '2M_1G']: - node0_mem_path = '%s/libvirt/qemu/.*' % hugepage_path_2M - if hp_size == "512M": - node0_mem_path = '%s/libvirt/qemu/.*' % hugepage_path_512M - if hp_size == "1G": - node0_mem_path = '%s/libvirt/qemu/.*' % hugepage_path_1G + params_2M = test_obj.params.get('2M') + params_512M = test_obj.params.get('512M') + params_1G = test_obj.params.get('1G') node1_mem_path = '' - if hp_size == "2M_512M": - node1_mem_path = '"mem-path":"%s/libvirt/qemu/.*",' % hugepage_path_512M - if hp_size == "2M_1G": - node1_mem_path = '"mem-path":"%s/libvirt/qemu/.*",' % hugepage_path_1G + if hp_size == 'default_hugepage': + node0_mem_path = '%s/libvirt/qemu/.*' % test_obj.params['vm_hugepage_mountpoint'] + elif hp_size == '512M_2M': + node0_mem_path = '%s/libvirt/qemu/.*' % params_512M.get('vm_hugepage_mountpoint') + node1_mem_path = '"mem-path":"%s/libvirt/qemu/.*",' % params_2M.get('vm_hugepage_mountpoint') + elif hp_size == '2M_1G': + node0_mem_path = '%s/libvirt/qemu/.*' % params_2M.get('vm_hugepage_mountpoint') + node1_mem_path = '"mem-path":"%s/libvirt/qemu/.*",' % params_1G.get('vm_hugepage_mountpoint') + elif hp_size == '1G': + node0_mem_path = '%s/libvirt/qemu/.*' % params_1G.get('vm_hugepage_mountpoint') + node0_mem_size = int(test_obj.params.get('vm_numa_node0_mem')) * 1024 - node1_prealloc = '"prealloc":true,' if hp_size == '2M_1G' or hp_size == '2M_512M' else '' + node1_prealloc = '"prealloc":true,' if hp_size == '2M_1G' or hp_size == '512M_2M' else '' node1_mem_size = int(test_obj.params.get('vm_numa_node1_mem')) * 1024 pat_in_qemu_cmdline = pat_in_qemu_cmdline % (node0_mem_path, node0_mem_size, @@ -189,7 +176,7 @@ def run_default(test_obj): test_obj.test.log.debug("Step: start vm and check results") test_obj.virsh_dargs.update({'ignore_status': True}) ret = virsh.start(test_obj.vm.name, **test_obj.virsh_dargs) - err_msg_expected = produce_expected_error(test_obj) + err_msg_expected = test_obj.params.get("err_msg") libvirt.check_result(ret, expected_fails=err_msg_expected) if err_msg_expected: return @@ -207,12 +194,6 @@ def teardown_default(test_obj): :param test_obj: NumaTest object """ test_obj.teardown() - hpconfig_2M = test_obj.params.get('hp_config_2M') - hpconfig_512M = test_obj.params.get('hp_config_512M') - hpconfig_1G = test_obj.params.get('hp_config_1G') - for hpconfig in [hpconfig_2M, hpconfig_512M, hpconfig_1G]: - if hpconfig: - hpconfig.cleanup() test_obj.test.log.debug("Step: hugepage is deallocated") test_obj.test.log.debug("Step: teardown is done") diff --git a/provider/numa/numa_base.py b/provider/numa/numa_base.py index cd7d6baa549..0ca1482448d 100644 --- a/provider/numa/numa_base.py +++ b/provider/numa/numa_base.py @@ -84,6 +84,7 @@ def teardown(self): hpc_list.extend([hpc_2M, hpc_1G]) for hpc in hpc_list: if hpc: + self.test.log.debug("Teardown: clean up hugepage setting for %d", hpc.hugepage_size) hpc.cleanup() def prepare_vm_xml(self): @@ -228,6 +229,8 @@ def check_hugepage_availability(pages_list): for a_page in pages_list: if a_page.get("size") is None or a_page.get("unit") is None: raise exceptions.TestError("'size' and 'unit' are required") + if a_page['size'].count("%s"): + continue size = int(a_page['size']) unit = a_page['unit'] size *= unit_mapping[unit] @@ -268,8 +271,16 @@ def adjust_parameters(params, hugepage_size=None, node_index='0', hugepage_mem=1 memory_backing = params['memory_backing'] if memory_backing and memory_backing.count('%s'): params['memory_backing'] = memory_backing % str(page_size) - kernel_hp_file = params.get('kernel_hp_file', '') - if kernel_hp_file.count('/sys/devices/system/node/'): - params['kernel_hp_file'] = kernel_hp_file % (node_index, str(page_size)) + kernel_hp_file = params.get('kernel_hp_file') + if kernel_hp_file: + if kernel_hp_file.count('/sys/devices/system/node/node%s/hugepages/hugepages-%s'): + params['kernel_hp_file'] = kernel_hp_file % (node_index, str(page_size)) + elif kernel_hp_file.count('/sys/kernel/mm/hugepages/hugepages-%s'): + params['kernel_hp_file'] = kernel_hp_file % str(page_size) params['expected_hugepage_size'] = page_size - params['target_hugepages'] = hugepage_mem//page_size + params['target_hugepages'] = hugepage_mem // page_size + if page_size == default_hugepage_size: + hugepage_path = "/dev/hugepages" + else: + hugepage_path = "/dev/hugepages%d" % page_size + params['vm_hugepage_mountpoint'] = hugepage_path From 64994ba03e577d443dd2bb931b5afd5afa313975 Mon Sep 17 00:00:00 2001 From: nanli Date: Mon, 25 Mar 2024 15:01:49 +0800 Subject: [PATCH 0267/1055] add case for revert memory only snap xxxx-300470:Revert guest to memory only snapshot. Signed-off-by: nanli --- .../cfg/snapshot/revert_memory_only_snap.cfg | 8 ++ .../src/snapshot/revert_memory_only_snap.py | 89 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 libvirt/tests/cfg/snapshot/revert_memory_only_snap.cfg create mode 100644 libvirt/tests/src/snapshot/revert_memory_only_snap.py diff --git a/libvirt/tests/cfg/snapshot/revert_memory_only_snap.cfg b/libvirt/tests/cfg/snapshot/revert_memory_only_snap.cfg new file mode 100644 index 00000000000..0de26981c8a --- /dev/null +++ b/libvirt/tests/cfg/snapshot/revert_memory_only_snap.cfg @@ -0,0 +1,8 @@ +- snapshot_revert.memory_only_snap: + type = revert_memory_only_snap + start_vm = no + snap_names = ['s1', 's2', 's3'] + target_disk = 'vda' + disk_type = 'file' + snap_options = "%s --memspec snapshot=external,file=/tmp/mem.%s --diskspec ${target_disk},snapshot=no" + func_supported_since_libvirt_ver = (9, 10, 0) diff --git a/libvirt/tests/src/snapshot/revert_memory_only_snap.py b/libvirt/tests/src/snapshot/revert_memory_only_snap.py new file mode 100644 index 00000000000..272ec433bba --- /dev/null +++ b/libvirt/tests/src/snapshot/revert_memory_only_snap.py @@ -0,0 +1,89 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from virttest import libvirt_version +from virttest import virsh +from virttest.libvirt_xml import vm_xml + +from provider.snapshot import snapshot_base +from provider.virtual_disk import disk_base + + +def run(test, params, env): + """ + Revert guest to memory only snapshot. + """ + def setup_test(): + """ + Check libvirt version + """ + libvirt_version.is_libvirt_feature_supported(params) + + def run_test(): + """ + Revert guest to memory only snapshot. + """ + test.log.info("TEST_STEP1:Create memory only snaps for running guest.") + virsh.start(vm_name) + vm.wait_for_login().close() + for sname in snap_names: + virsh.snapshot_create_as(vm.name, snap_options % (sname, sname), + **virsh_dargs) + snap_lists = virsh.snapshot_list(vm_name, **virsh_dargs) + if sname not in snap_lists: + test.fail("Expect to get '%s' in snap list" % sname) + + test.log.info("TEST_STEP2:Revert the second snap and check source path") + virsh.snapshot_revert(vm_name, snap_names[1], **virsh_dargs) + + def _check_source_num(): + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + source_list = disk_obj.get_source_list(vmxml, disk_type, target_disk) + if len(source_list) != 2: + test.fail('Expected disk source num should be 2 instead of %s ' + 'in xml %s' % (len(source_list), vmxml)) + _check_source_num() + + test.log.info("TEST_STEP3:Revert the first snap and check source path") + virsh.snapshot_revert(vm_name, snap_names[0], **virsh_dargs) + _check_source_num() + + test.log.info("TEST_STEP4:Revert the last snap and check source path") + virsh.snapshot_revert(vm_name, snap_names[2], **virsh_dargs) + _check_source_num() + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + snap_names.reverse() + test_obj.delete_snapshot(snap_names) + bkxml.sync() + + vm_name = params.get("main_vm") + original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = original_xml.copy() + vm = env.get_vm(vm_name) + + virsh_dargs = {"debug": True, "ignore_status": True} + snap_names = eval(params.get("snap_names", '[]')) + snap_options = params.get("snap_options") + disk_type = params.get("disk_type") + target_disk = params.get("target_disk") + test_obj = snapshot_base.SnapshotTest(vm, test, params) + disk_obj = disk_base.DiskBase(test, vm, params) + + try: + setup_test() + run_test() + + finally: + teardown_test() From 9ec4226cb40d0eab50d82cda3abc8fcac2e0a23d Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Thu, 28 Mar 2024 14:03:57 +0800 Subject: [PATCH 0268/1055] memory_binding_setting: fix kernelpagesize Signed-off-by: Dan Zheng --- .../src/numa/guest_numa_node_tuning/memory_binding_setting.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py b/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py index 4bfd28f3e02..9959238c614 100644 --- a/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py @@ -105,7 +105,7 @@ def verify_host_numa_memory_allocation(test_obj): N0_value = re.findall('N%s=(\d+)' % all_nodes[0], out_numa_maps) N1_value = re.findall('N%s=(\d+)' % all_nodes[1], out_numa_maps) expected_hugepage_size = test_obj.params.get('expected_hugepage_size') - psize = expected_hugepage_size if memory_backing else memory.get_page_size() + psize = expected_hugepage_size if memory_backing else memory.get_page_size() // 1024 has_kernelpage = True if re.search('kernelpagesize_kB=%s' % psize, out_numa_maps) else False def _check_values(expect_huge, expect_N0, expect_N1, expect_sum=None): From 2340dad43d9e1e989a76ca127ef0752549b3f7cc Mon Sep 17 00:00:00 2001 From: Meina Li Date: Thu, 28 Mar 2024 02:57:35 -0400 Subject: [PATCH 0269/1055] startup_policy: update creating internal snapshot to external snapshot This PR fixes the following several issues: 1) Mainly update creating internal snapshot to external snapshot 2) Update restore_error and revert_error status, the previous ones are incorrect because of the unreasonable test steps in script. 3) Add necessary steps in python file: restarting the guest with optional disk because the previous attached disk will be lost so the following save/restore/revert steps are using the wrong guest xml. Signed-off-by: Meina Li --- .../tests/cfg/virtual_disks/startup_policy.cfg | 6 +++++- .../tests/src/virtual_disks/startup_policy.py | 18 ++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/virtual_disks/startup_policy.cfg b/libvirt/tests/cfg/virtual_disks/startup_policy.cfg index 54fc056296e..09bf8e9857e 100644 --- a/libvirt/tests/cfg/virtual_disks/startup_policy.cfg +++ b/libvirt/tests/cfg/virtual_disks/startup_policy.cfg @@ -73,6 +73,7 @@ - disk: device_type = "disk" image_size = "100M" + snapshot_options = "--memspec snapshot=external,file=/tmp/mem.%s --diskspec %s,file=/tmp/test.%s --diskspec vda,snapshot=no" only file dir_pool variants: - virtio_bus: @@ -89,13 +90,16 @@ update_policy_list = "optional requisite" start_error = "yes" restore_error = "yes" + revert_error = "yes" - optional: policy = "optional" update_policy_list = "mandatory requisite" start_error = "no" - restore_error = "no" + restore_error = "yes" + revert_error = "yes" - requisite: policy = "requisite" update_policy_list = "mandatory optional" start_error = "yes" restore_error = "no" + revert_error = "no" diff --git a/libvirt/tests/src/virtual_disks/startup_policy.py b/libvirt/tests/src/virtual_disks/startup_policy.py index dc3ae6527ca..d77daf46784 100644 --- a/libvirt/tests/src/virtual_disks/startup_policy.py +++ b/libvirt/tests/src/virtual_disks/startup_policy.py @@ -351,6 +351,7 @@ def rename_file(source_file, target_file, revert=False): # Get start,restore configuration parameters. start_error = "yes" == params.get("start_error", "no") restore_error = "yes" == params.get("restore_error", "no") + revert_error = "yes" == params.get("revert_error", "no") virsh_dargs = {'debug': True, 'ignore_status': True} attach_option = params.get("attach_option") @@ -415,6 +416,9 @@ def rename_file(source_file, target_file, revert=False): logging.debug("Attach device throws exception:%s", str(attach_device_exception)) os.remove(media_file) test.error("Attach %s fail" % device_type) + # The guest can restore successfully for optional cdrom disk. + if device_type == "cdrom" and startup_policy == "optional": + restore_error = False # Check update policy operations. if disk_type == "file" and update_policy: vm.start() @@ -445,6 +449,10 @@ def rename_file(source_file, target_file, revert=False): # Step 4. Save the domain normally, then remove the source file # and restore it back + if startup_policy == "optional": + # Restart the guest with optional disk because the previous optional disk will be lost after the above steps + vm.destroy() + vm.start() vm.save_to_file(save_file) rename_file(media_file, media_file_new) result = virsh.restore(save_file, **virsh_dargs) @@ -485,6 +493,10 @@ def rename_file(source_file, target_file, revert=False): vm.start() # Step 4 Save the domain normally, then remove the source file,then restore domain. + if startup_policy == "optional": + # Restart the guest with optional disk because the previous optional disk will be lost after the above steps + vm.destroy() + vm.start() vm.save_to_file(save_file) rename_file(vol_path, vol_path_new) cmd_result = virsh.pool_refresh(pool_name) @@ -500,10 +512,12 @@ def rename_file(source_file, target_file, revert=False): if restore_error: result = virsh.restore(save_file, **virsh_dargs) libvirt.check_exit_status(result) - ret = virsh.snapshot_create_as(vm_name, snapshot_name, **virsh_dargs) + snapshot_options = params.get("snapshot_options", "") % (snapshot_name, target_dev, snapshot_name) + ret = virsh.snapshot_create_as(vm_name, "%s %s" % (snapshot_name, snapshot_options), **virsh_dargs) libvirt.check_exit_status(ret) rename_file(vol_path, vol_path_new) - ret = virsh.snapshot_revert(vm_name, snapshot_name, **virsh_dargs) + result = virsh.snapshot_revert(vm_name, snapshot_name, **virsh_dargs) + libvirt.check_exit_status(result, expect_error=revert_error) # Clean up snapshot. libvirt.clean_up_snapshots(vm_name, domxml=vmxml_backup) finally: From 705b710f57f83bb1b48332b57cfdda9e1f2cabd2 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Thu, 28 Mar 2024 16:14:19 +0800 Subject: [PATCH 0270/1055] scsi_controller_driver_plug_unplug: add case test scenarios: - test scsi controllers wi/o driver with plug and unplug operations Signed-off-by: Dan Zheng --- .../scsi_controller_driver_plug_unplug.cfg | 27 +++ .../scsi_controller_driver_plug_unplug.py | 201 ++++++++++++++++++ 2 files changed, 228 insertions(+) create mode 100644 libvirt/tests/cfg/scsi/scsi_controller_driver_plug_unplug.cfg create mode 100644 libvirt/tests/src/scsi/scsi_controller_driver_plug_unplug.py diff --git a/libvirt/tests/cfg/scsi/scsi_controller_driver_plug_unplug.cfg b/libvirt/tests/cfg/scsi/scsi_controller_driver_plug_unplug.cfg new file mode 100644 index 00000000000..8eea456d46e --- /dev/null +++ b/libvirt/tests/cfg/scsi/scsi_controller_driver_plug_unplug.cfg @@ -0,0 +1,27 @@ +- scsi_controller.driver.plug_unplug: + type = scsi_controller_driver_plug_unplug + start_vm = no + take_regular_screendumps = no + controller_dict = {'type': 'scsi', 'model': 'virtio-scsi', 'index': '%s'} + no s390-virtio + variants driver_config: + - with_driver: + iothread_num = 1 + iothread_id = 1 + - without_driver: + variants contr_num: + - one_contr: + contr_index = [0] + - two_contrs: + only with_driver + contr_index = [0, 1] + variants scenarios: + - cold_first_hot_second: + - hotplug_same_index: + only two_contrs + same_index = 0 + err_msg = "target scsi:${same_index} already exists" + - hotplug_same_address: + only two_contrs + same_address = { "domain": '0x0000', 'funtion': '0x0', 'bus': '0x08', 'slot': '0x00'} + err_msg = "Attempted double use of PCI Address" diff --git a/libvirt/tests/src/scsi/scsi_controller_driver_plug_unplug.py b/libvirt/tests/src/scsi/scsi_controller_driver_plug_unplug.py new file mode 100644 index 00000000000..64e95a8ee47 --- /dev/null +++ b/libvirt/tests/src/scsi/scsi_controller_driver_plug_unplug.py @@ -0,0 +1,201 @@ +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Dan Zheng +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import time + +from virttest import virsh + +from virttest.libvirt_xml.devices.controller import Controller +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_pcicontr +from virttest.utils_test import libvirt + + +def prepare_vm_xml(params, test): + """ + Prepare vm xml for the test + + :param params: dict, test parameters + :param test: test object + """ + iothread_num = params.get('iothread_num') + iothread_id = params.get('iothread_id') + vm_name = params.get("main_vm") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + devices = vmxml.get_devices() + controllers = vmxml.get_devices(device_type='controller') + for one_device in controllers: + if one_device.type == 'scsi': + test.log.debug("Remove the existing scsi controller") + devices.remove(one_device) + vmxml.set_devices(devices) + if iothread_num: + vmxml.setup_attrs(iothreads=int(iothread_num), iothreadids={'iothread': [{'id': iothread_id}]}) + vmxml.sync() + libvirt_pcicontr.reset_pci_num(vm_name) + test.log.debug("The VM xml after preparation:" + "\n%s", vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)) + + +def check_dumpxml(vm_name, options, controllers_dicts, expect_exist, test): + """ + Check vm xml by virsh dumpxml + + :param vm_name: str, vm name + :param options: str, virsh dumpxml options + :param controllers_dicts: dict, controller's configurations + :param expect_exist: boolean, True if expect existence, otherwise False + :param test: test object + """ + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name, options=options) + controllers = vmxml.get_devices(device_type="controller") + for one_ctl_dict in controllers_dicts: + found = False + for one_ctl in controllers: + if (one_ctl.type == one_ctl_dict['type'] and + one_ctl.model == one_ctl_dict['model'] and + one_ctl.index == one_ctl_dict['index']): + found = True + break + if found != expect_exist: + test.fail("Expect controller (%s) %s exist " + "in vm xml" % (one_ctl_dict, + '' if expect_exist else 'not')) + test.log.debug("Verify controller (%s) in VM " + "xml - PASS", one_ctl_dict) + + +def _create_controllers(params): + """ + Create controllers for the tests + + :param params: dict, test parameters + :return: tuple, (list of controller objects, + list of controller parameters) + """ + contr_indexes = eval(params.get('contr_index')) + iothread_id = params.get('iothread_id') + same_address = eval(params.get('same_address', '{}')) + controller_dicts = [] + controllers = [] + for an_index in contr_indexes: + controller_dict = params.get('controller_dict') + controller_dict = eval(controller_dict % an_index) + if iothread_id: + controller_dict['driver'] = {'iothread': '%s' % iothread_id} + if same_address: + controller_dict['address'] = {'attrs': same_address} + ctrl = Controller(type_name=controller_dict['type']) + ctrl.setup_attrs(**controller_dict) + controller_dicts.append(controller_dict) + controllers.append(ctrl) + return (controllers, controller_dicts) + + +def test_default(vm_name, params, test): + """ + The common test function for plug and unplug + + :param vm_name: str, vm name + :param params: dict, test parameters + :param test: test object + """ + virsh_dargs = {'ignore_status': False, 'debug': True} + controllers, controller_dicts = _create_controllers(params) + for ctrl in controllers: + test.log.info("Step: Coldplug a controller %s", ctrl) + virsh.attach_device(vm_name, ctrl.xml, flagstr='--config', **virsh_dargs) + check_dumpxml(vm_name, '--inactive', controller_dicts, True, test) + for ctrl in controllers: + test.log.info("Step: Hotplug a controller %s", ctrl) + virsh.attach_device(vm_name, ctrl.xml, **virsh_dargs) + check_dumpxml(vm_name, '', controller_dicts, True, test) + for ctrl in controllers: + test.log.info("Step: Coldunplug a controller %s", ctrl) + virsh.detach_device(vm_name, ctrl.xml, flagstr='--config', **virsh_dargs) + time.sleep(10) + check_dumpxml(vm_name, '--inactive', controller_dicts, False, test) + for ctrl in controllers: + test.log.info("Step: Hotunplug a controller %s", ctrl) + virsh.detach_device(vm_name, ctrl.xml, **virsh_dargs) + time.sleep(10) + check_dumpxml(vm_name, '', controller_dicts, False, test) + + +def test_two_contrs_with_driver_hotplug_same_index(vm_name, params, test): + """ + Test hot plug with two controllers with driver in same index + + :param vm_name: str, vm name + :param params: dict, test parameters + :param test: test object + """ + virsh_dargs = {'ignore_status': False, 'debug': True} + same_index = params.get('same_index') + params['contr_index'] = '[%s, %s]' % (same_index, same_index) + controllers, _ = _create_controllers(params) + test.log.info("Step: Hotplug a controller %s", controllers[0]) + virsh.attach_device(vm_name, controllers[0].xml, **virsh_dargs) + virsh_dargs.update({'ignore_status': True}) + test.log.info("Step: Hotplug a controller %s", controllers[1]) + ret = virsh.attach_device(vm_name, controllers[1].xml, **virsh_dargs) + err_msg = params.get('err_msg') + libvirt.check_result(ret, expected_fails=err_msg) + + +def test_two_contrs_with_driver_hotplug_same_address(vm_name, params, test): + """ + Test hot plug with two controllers with driver in same address + + :param vm_name: str, vm name + :param params: dict, test parameters + :param test: test object + """ + virsh_dargs = {'ignore_status': False, 'debug': True} + controllers, _ = _create_controllers(params) + test.log.info("Step: Hotplug a controller %s", controllers[0]) + virsh.attach_device(vm_name, controllers[0].xml, **virsh_dargs) + virsh_dargs.update({'ignore_status': True}) + test.log.info("Step: Hotplug a controller %s", controllers[1]) + ret = virsh.attach_device(vm_name, controllers[1].xml, **virsh_dargs) + err_msg = params.get('err_msg') + libvirt.check_result(ret, expected_fails=err_msg) + + +def run(test, params, env): + """ + Test scsi controller plug unplug operations with different configurations. + + 1.Prepare VM xml. + 2.Do plug unplug scsi controller + 3.Check the test result. + """ + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + vmxml_backup = vmxml.copy() + + contr_num = params.get("contr_num") + driver_config = params.get("driver_config") + test_scenario = params.get("scenarios") + case_name = "test_%s_%s_%s" % (contr_num, driver_config, test_scenario) + run_test_case = eval(case_name) if case_name in globals() else test_default + + try: + test.log.info("Step: Prepare the VM xml") + prepare_vm_xml(params, test) + test.log.info("Step: Start the VM") + vm.start() + vm.wait_for_login().close() + run_test_case(vm_name, params, test) + finally: + if vm.is_alive(): + virsh.destroy(vm_name) + vmxml_backup.sync() From 3d076319b815e8ccb06bd90d9bc048e526058807 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 29 Mar 2024 10:12:10 +0800 Subject: [PATCH 0271/1055] guest_agent: Add a case about socket path This PR adds a test about a socket path belonging to part of auto-generated path. Signed-off-by: Yingshun Cui --- libvirt/tests/cfg/guest_agent/guest_agent.cfg | 6 +++++- libvirt/tests/src/guest_agent/guest_agent.py | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/guest_agent/guest_agent.cfg b/libvirt/tests/cfg/guest_agent/guest_agent.cfg index c63fa507fff..8628dddb338 100644 --- a/libvirt/tests/cfg/guest_agent/guest_agent.cfg +++ b/libvirt/tests/cfg/guest_agent/guest_agent.cfg @@ -10,8 +10,12 @@ only ga_started hotunplug_ga = "yes" - customize_source_path: - src_path = '/test/agent' con_label = "system_u:object_r:qemu_var_run_t:s0" + variants: + - auto_gen_path: + src_path = "/40-a/org.qemu.guest_agent.0" + - random: + src_path = "/test/agent" - hotplug_ga_without_tgt_type: only ga_started hotplug_ga_without_tgt_type = "yes" diff --git a/libvirt/tests/src/guest_agent/guest_agent.py b/libvirt/tests/src/guest_agent/guest_agent.py index 6246ca03339..83c43545455 100644 --- a/libvirt/tests/src/guest_agent/guest_agent.py +++ b/libvirt/tests/src/guest_agent/guest_agent.py @@ -91,10 +91,12 @@ def run(test, params, env): label = params.get("con_label") vm = env.get_vm(vm_name) + socket_file_dir_created = False if src_path: socket_file_dir = os.path.dirname(src_path) if not os.path.exists(socket_file_dir): os.mkdir(socket_file_dir) + socket_file_dir_created = True shutil.chown(socket_file_dir, "qemu", "qemu") utils_selinux.set_context_of_file(filename=socket_file_dir, context=label) @@ -142,3 +144,5 @@ def run(test, params, env): finally: vm.destroy() backup_xml.sync() + if socket_file_dir_created and os.path.exists(socket_file_dir): + os.rmdir(socket_file_dir) From 364fd11ffa6ea31434cbecbc8bc455bd0e1880ec Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Mon, 18 Mar 2024 18:46:47 +0800 Subject: [PATCH 0272/1055] virtual_network: Add a hotplug case This pr adds: VIRT-298404: Attach/Detach interface with different model, and --alias, --mac, --print-xml Signed-off-by: Yingshun Cui --- .../attach_interface_with_model.cfg | 26 ++++ .../attach_interface_with_model.py | 123 ++++++++++++++++++ provider/interface/interface_base.py | 9 +- 3 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 libvirt/tests/cfg/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.cfg create mode 100644 libvirt/tests/src/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.py diff --git a/libvirt/tests/cfg/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.cfg b/libvirt/tests/cfg/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.cfg new file mode 100644 index 00000000000..271d3ffe5fb --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.cfg @@ -0,0 +1,26 @@ +- virtual_network.hotplug.attach_interface.model: + type = attach_interface_with_model + start_vm = no + timeout = 240 + outside_ip = 'www.redhat.com' + host_iface = + vm_ping_outside = pass + variants model_type: + - virtio: + iface_driver = virtio_net + pci_model = pcie-root-port + s390-virtio: + check_pci_model = no + - e1000e: + only x86_64 + iface_driver = e1000e + pci_model = pcie-root-port + - igb: + only x86_64 + func_supported_since_libvirt_ver = (9, 3, 0) + iface_driver = igb + pci_model = pcie-root-port + - rtl8139: + only x86_64 + iface_driver = 8139cp + pci_model = pcie-to-pci-bridge diff --git a/libvirt/tests/src/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.py b/libvirt/tests/src/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.py new file mode 100644 index 00000000000..8d7092c7785 --- /dev/null +++ b/libvirt/tests/src/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.py @@ -0,0 +1,123 @@ +import uuid + +from virttest import libvirt_version +from virttest import utils_net +from virttest import virsh +from virttest.libvirt_xml import vm_xml + +from virttest.utils_libvirt import libvirt_vmxml +from virttest.libvirt_xml.devices import interface +from virttest.utils_test import libvirt + +from provider.virtual_network import network_base +from provider.interface import interface_base + +VIRSH_ARGS = {"ignore_status": False, "debug": True} + + +def check_model_controller(vm_name, pci_model, test): + """ + Checks that the controllers are the expected pci model + + :param vm_name: VM name + :param pci_model: The expected pci model + :param test: Test instance + """ + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + iface = vmxml.get_devices("interface")[0] + test.log.debug(f"Interface xml after vm started:\n{iface}") + ctrl_index = int(iface.fetch_attrs()["address"]["attrs"]["bus"], 16) + controllers = vmxml.get_devices("controller") + iface_controller = [c for c in controllers if c.type == "pci" and + c.index == str(ctrl_index)][0] + test.log.debug(f"Controller xml:\n{iface_controller}") + + if iface_controller.model == pci_model: + test.log.debug("XML controller model check: PASS") + else: + test.fail(f"Expect pci model: {pci_model}, " + f"and got {iface_controller.model}") + + +def run(test, params, env): + """ + Attach-interface with different models and options + """ + libvirt_version.is_libvirt_feature_supported(params) + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + outside_ip = params.get("outside_ip") + pci_model = params.get("pci_model") + iface_driver = params.get("iface_driver") + model_type = params.get("model_type") + check_pci_model = params.get("check_pci_model", "yes") == "yes" + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + pci_controllers = vmxml.get_controllers("pci") + for controller in pci_controllers: + if controller.get("model") == "pcie-to-pci-bridge": + break + else: + controller_dict = {"model": "pcie-to-pci-bridge"} + libvirt_vmxml.modify_vm_device(vmxml, "controller", controller_dict, 50) + libvirt_vmxml.remove_vm_devices_by_type(vm, "interface") + test.log.debug(f"VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}") + + vm.start() + session = vm.wait_for_serial_login() + + mac = utils_net.generate_mac_address_simple() + alias_name = "ua-" + str(uuid.uuid1()) + options = "network default --model {} --alias {} --mac {}".format( + model_type, alias_name, mac) + iface = interface.Interface() + iface.xml = virsh.attach_interface(vm_name, f"{options} --print-xml", **VIRSH_ARGS).stdout_text.strip() + test.log.debug(iface.fetch_attrs()) + exp_iface = {'model': model_type, 'source': {'network': 'default'}, + 'type_name': 'network', + 'alias': {'name': alias_name}, + 'mac_address': mac} + iface_attrs = iface.fetch_attrs() + + if exp_iface != iface_attrs: + test.fail("Failed to print xml! Expected: %s, Got: %s." % (exp_iface, iface_attrs)) + virsh.attach_interface(vm_name, options, **VIRSH_ARGS) + iflist = libvirt.get_interface_details(vm_name) + test.log.debug(f"iflist of vm: {iflist}") + iface_info = iflist[0] + if iface_info["model"] == model_type: + test.log.debug("Model check of domiflist: PASS") + else: + test.fail(f"Expect interface model {model_type}, " + f"but got {iface_info['model']}") + + session = vm.wait_for_serial_login() + vm_iface_info = interface_base.get_vm_iface_info(session) + if vm_iface_info.get("driver") != iface_driver: + test.fail("Failed to get expected driver \"{iface_driver}\" in ethtool output") + + ips = {"outside_ip": outside_ip} + network_base.ping_check(params, ips, session, force_ipv4=True) + + if check_pci_model: + check_model_controller(vm_name, pci_model, test) + + virsh.detach_device_alias(vm_name, alias_name, + wait_for_event=True, **VIRSH_ARGS) + iflist = libvirt.get_interface_details(vm_name) + test.log.debug(f"iflist of vm: {iflist}") + if iflist: + test.fail("Found unexpected interface in %s." % iflist) + vm_iface = interface_base.get_vm_iface(session, True) + if vm_iface: + test.fail("Found unexpected interface in %s." % vm_iface) + else: + test.log.debug(vm_iface) + session.close() + + finally: + bkxml.sync() diff --git a/provider/interface/interface_base.py b/provider/interface/interface_base.py index f632e802aea..36f0d447d0a 100644 --- a/provider/interface/interface_base.py +++ b/provider/interface/interface_base.py @@ -47,17 +47,22 @@ def create_hostdev(hostdev_dict): return hostdev_dev -def get_vm_iface(vm_session): +def get_vm_iface(vm_session, ignore_status=False): """ Get VM's 1st interface :param vm_session: An session to VM + :param ignore_status: Whether to raise an exception if there is no interface :return: VM's first interface """ p_iface, _v_ifc = utils_net.get_remote_host_net_ifs(vm_session) vm_iface = p_iface[:1:] if not vm_iface: - raise exceptions.TestFail("Failed to get vm's iface!") + if ignore_status: + logging.debug("There is no interface in VM!") + return + else: + raise exceptions.TestFail("Failed to get vm's iface!") return vm_iface[0] From 1fcea8ae86fdd35e36bf57a355d91bb0f6c622cc Mon Sep 17 00:00:00 2001 From: Qian Jianhua Date: Wed, 27 Mar 2024 17:47:31 +0800 Subject: [PATCH 0273/1055] misc_virtual_devices: fix "No more available PCI slots" error Signed-off-by: Qian Jianhua --- libvirt/tests/src/virtual_device/input_devices_plug_unplug.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/src/virtual_device/input_devices_plug_unplug.py b/libvirt/tests/src/virtual_device/input_devices_plug_unplug.py index 73a520906d1..08ccc9e697f 100644 --- a/libvirt/tests/src/virtual_device/input_devices_plug_unplug.py +++ b/libvirt/tests/src/virtual_device/input_devices_plug_unplug.py @@ -10,6 +10,7 @@ from virttest.libvirt_xml.devices.input import Input from virttest.libvirt_xml.vm_xml import VMXML from virttest import virsh +from virttest.utils_libvirt import libvirt_pcicontr def prepare_vm_xml(vm_xml, device_type, test): @@ -67,6 +68,7 @@ def run(test, params, env): 3. check the result """ vm_name = params.get("main_vm", "avocado-vt-vm1") + libvirt_pcicontr.reset_pci_num(vm_name) vm = env.get_vm(vm_name) vm_xml = VMXML.new_from_dumpxml(vm_name) vm_xml_backup = vm_xml.copy() From 1715ba2ff738dfbeed13eed37d40f7f49a588ff3 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Fri, 29 Mar 2024 03:47:08 -0400 Subject: [PATCH 0274/1055] SRIOV: add new negative scenario when start vm with hostdev interface This PR mainly automates a new negative scenatio with invalid driver model for hostdev interface in VIRT-293914. Signed-off-by: Meina Li --- .../sriov/vm_lifecycle/sriov_vm_lifecycle_start_negative.cfg | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_start_negative.cfg b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_start_negative.cfg index bd10d7bffb8..04590f86338 100644 --- a/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_start_negative.cfg +++ b/libvirt/tests/cfg/sriov/vm_lifecycle/sriov_vm_lifecycle_start_negative.cfg @@ -30,6 +30,10 @@ iommu_dict = {'driver': {'intremap': 'on'}, 'model': 'intel'} iface_dict = {'managed': 'yes', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}} err_msg = "iommu to enable" + - invalid_driver_model: + driver_model = "test" + iface_dict = {'managed': 'yes', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}, 'driver': {'driver_attr': {'name': 'vfio', 'model': '${driver_model}'}}} + err_msg = "Failed to load PCI driver module ${driver_model}" - hostdev_device: variants test_scenario: - iommu_without_caching: From fd7af4feb2556e771e76cfd55af42dc72480f57a Mon Sep 17 00:00:00 2001 From: nanli Date: Mon, 11 Mar 2024 11:37:25 +0800 Subject: [PATCH 0275/1055] add case for reverting snap based on domain and snap status xxxx-300468: Revert snapshots based on different domain and snapshot status Signed-off-by: nanli --- .../snapshot/revert_snap_based_on_status.cfg | 19 +++++ .../snapshot/revert_snap_based_on_status.py | 81 +++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 libvirt/tests/cfg/snapshot/revert_snap_based_on_status.cfg create mode 100644 libvirt/tests/src/snapshot/revert_snap_based_on_status.py diff --git a/libvirt/tests/cfg/snapshot/revert_snap_based_on_status.cfg b/libvirt/tests/cfg/snapshot/revert_snap_based_on_status.cfg new file mode 100644 index 00000000000..c5eec301d7d --- /dev/null +++ b/libvirt/tests/cfg/snapshot/revert_snap_based_on_status.cfg @@ -0,0 +1,19 @@ +- snapshot_revert.snap_and_domain_status: + type = revert_snap_based_on_status + start_vm = no + snap_name = 's1' + func_supported_since_libvirt_ver = (9, 10, 0) + variants : + - snap_running: + snap_status = "running" + expected_status = "${snap_status}" + snap_options = " %s --memspec snapshot=external,file=/tmp/mem.s1 --diskspec vda,snapshot=external,file=/tmp/vda.s1" + - snap_shutoff: + snap_status = "shutoff" + expected_status = "shut off" + snap_options = " %s --diskspec vda,snapshot=external,file=/tmp/vda.s1" + variants: + - vm_running: + vm_status = "running" + - vm_shutoff: + vm_status = "shut off" diff --git a/libvirt/tests/src/snapshot/revert_snap_based_on_status.py b/libvirt/tests/src/snapshot/revert_snap_based_on_status.py new file mode 100644 index 00000000000..2fcad459afc --- /dev/null +++ b/libvirt/tests/src/snapshot/revert_snap_based_on_status.py @@ -0,0 +1,81 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +from virttest import libvirt_version +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt + +from provider.snapshot import snapshot_base + + +def run(test, params, env): + """ + Revert snapshots based on different domain status. + """ + def run_test(): + """ + Revert snapshots based on different domain status. + """ + test.log.info("TEST_STEP1: Prepare a snap.") + if snap_status == "running": + virsh.start(vm_name, **virsh_dargs) + vm.wait_for_login().close() + virsh.snapshot_create_as(vm_name, snap_options % snap_name, + **virsh_dargs) + status_result = virsh.snapshot_status(vm_name, **virsh_dargs) + if status_result[snap_name] != snap_status: + test.fail("%s status should be '%s' instead of '%s'" % ( + snap_name, snap_status, status_result[snap_name])) + else: + test.log.debug("Check snap status '%s' is correct" % snap_status) + + test.log.info("TEST_STEP2: Set domain status.") + if vm_status.replace(' ', '') != snap_status: + if vm_status == "shut off": + virsh.destroy(vm_name, **virsh_dargs) + elif vm_status == "running": + virsh.start(vm_name, **virsh_dargs) + vm.wait_for_login().close() + + test.log.info("TEST_STEP3: Revert the snapshot") + virsh.snapshot_revert(vm_name, snap_name, **virsh_dargs) + + test.log.info("TEST_STEP5: Check expected domain status") + if not libvirt.check_vm_state(vm_name, expected_status): + test.fail("VM status should be '%s' after reverting." % expected_status) + else: + test.log.debug("Check vm status '%s' is correct", expected_status) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + test_obj.delete_snapshot(snap_name) + bkxml.sync() + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = original_xml.copy() + virsh_dargs = {"debug": True, "ignore_status": True} + snap_name = params.get("snap_name") + snap_options = params.get("snap_options") + snap_status = params.get("snap_status") + vm_status = params.get("vm_status") + expected_status = params.get("expected_status") + test_obj = snapshot_base.SnapshotTest(vm, test, params) + + try: + libvirt_version.is_libvirt_feature_supported(params) + run_test() + + finally: + teardown_test() From eb153b0e06a7ac628d39068429c32e9bb8a8e1c1 Mon Sep 17 00:00:00 2001 From: nanli Date: Mon, 1 Apr 2024 12:31:05 +0800 Subject: [PATCH 0276/1055] snapshot case enhancement original pr is merged before fixed over, leaving some update Signed-off-by: nanli --- .../src/snapshot/revert_memory_only_snap.py | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/libvirt/tests/src/snapshot/revert_memory_only_snap.py b/libvirt/tests/src/snapshot/revert_memory_only_snap.py index 272ec433bba..e54f8fac194 100644 --- a/libvirt/tests/src/snapshot/revert_memory_only_snap.py +++ b/libvirt/tests/src/snapshot/revert_memory_only_snap.py @@ -20,12 +20,6 @@ def run(test, params, env): """ Revert guest to memory only snapshot. """ - def setup_test(): - """ - Check libvirt version - """ - libvirt_version.is_libvirt_feature_supported(params) - def run_test(): """ Revert guest to memory only snapshot. @@ -36,10 +30,7 @@ def run_test(): for sname in snap_names: virsh.snapshot_create_as(vm.name, snap_options % (sname, sname), **virsh_dargs) - snap_lists = virsh.snapshot_list(vm_name, **virsh_dargs) - if sname not in snap_lists: - test.fail("Expect to get '%s' in snap list" % sname) - + test_obj.check_snap_list(sname) test.log.info("TEST_STEP2:Revert the second snap and check source path") virsh.snapshot_revert(vm_name, snap_names[1], **virsh_dargs) @@ -65,12 +56,12 @@ def teardown_test(): """ test.log.info("TEST_TEARDOWN: Clean up env.") snap_names.reverse() - test_obj.delete_snapshot(snap_names) - bkxml.sync() + test_obj.teardown_test() vm_name = params.get("main_vm") original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) - bkxml = original_xml.copy() + params['backup_vmxml'] = original_xml.copy() + vm = env.get_vm(vm_name) virsh_dargs = {"debug": True, "ignore_status": True} @@ -82,7 +73,7 @@ def teardown_test(): disk_obj = disk_base.DiskBase(test, vm, params) try: - setup_test() + libvirt_version.is_libvirt_feature_supported(params) run_test() finally: From 51b896ee7509964b97e61baaa4561b8ebc2aec3e Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 18 Dec 2023 05:25:32 -0500 Subject: [PATCH 0277/1055] memory/secure_dump: add test for s390x SE decryption Add test case that 1. Dumps the SE memory 2. Decrypts the memory 3. Does a minimal check on the decrypted content. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/memory/secure_dump.cfg | 7 ++ libvirt/tests/src/memory/secure_dump.py | 83 ++++++++++++++++++++++++ spell.ignore | 3 + 3 files changed, 93 insertions(+) create mode 100644 libvirt/tests/cfg/memory/secure_dump.cfg create mode 100644 libvirt/tests/src/memory/secure_dump.py diff --git a/libvirt/tests/cfg/memory/secure_dump.cfg b/libvirt/tests/cfg/memory/secure_dump.cfg new file mode 100644 index 00000000000..46fbe9e88fb --- /dev/null +++ b/libvirt/tests/cfg/memory/secure_dump.cfg @@ -0,0 +1,7 @@ +- secure_dump: + type = secure_dump + start_vm = yes + only s390-virtio + variants: + - decrypt: + comm_key = 0123456789012345678901234567890 diff --git a/libvirt/tests/src/memory/secure_dump.py b/libvirt/tests/src/memory/secure_dump.py new file mode 100644 index 00000000000..32bf9dfbc99 --- /dev/null +++ b/libvirt/tests/src/memory/secure_dump.py @@ -0,0 +1,83 @@ +import logging as log +import os + +from virttest.utils_misc import cmd_status_output +from virttest import virsh + +logging = log.getLogger('avocado.' + __name__) +cleanup = [] + + +def get_kernel_cmdline(vm): + """ + Returns /proc/cmdline + + :param vm: VM instance + """ + with vm.wait_for_login() as session: + _, o = cmd_status_output("cat /proc/cmdline", + session=session, + ignore_status=False, + shell=True) + return o.strip() + + +def decrypt(dump_file, decrypted_dump_dir, comm_key): + """ + Decrypt the dumped file with a communication key. + + :param dump_file: path to the memory dump + :param decrypted_dump_dir: where to mount the decrypted + dump + :param comm_key: string with the communication key + """ + cmd = "echo %s > %s" % (comm_key, "comm_key.txt") + cmd_status_output(cmd, ignore_status=False, shell=True) + cmd = "zgetdump -k comm_key.txt %s -m %s" % (dump_file, decrypted_dump_dir) + cmd_status_output(cmd, ignore_status=False, shell=True) + cleanup.append(lambda: cmd_status_output("umount %s" % decrypted_dump_dir)) + + +def confirm_contains(decrypted_dump_file, text, test): + """ + Confirm that given text can be found in file. + This confirms the file has been decrypted correctly. + + :param decrypted_dump_file: The path of the .elf file + of the decrypted dump + :param text: string to be found + :param test: test instance + """ + s, _ = cmd_status_output("strings -d %s|grep -m 1 '%s'" % (decrypted_dump_file, text), + shell=True) + if s: + test.fail("Couldn't find expected text in dump file.") + + +def run(test, params, env): + """ + Decrypt encrypted memory dump. + Assumes the guest is running in with + SE and has been encrypted with the tested + communication key. + """ + + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + comm_key = params.get("comm_key") + dump_file = "/tmp/DUMP" + decrypted_dump_dir = "/mnt" + decrypted_dump_file = os.path.join(decrypted_dump_dir, "dump.elf") + + try: + cmdline = get_kernel_cmdline(vm) + virsh.dump(vm_name, dump_file, "--memory-only", + ignore_status=False, debug=True) + cleanup.append(lambda: os.remove(dump_file)) + + decrypt(dump_file, decrypted_dump_dir, comm_key) + confirm_contains(decrypted_dump_file, cmdline, test) + + finally: + for c in reversed(cleanup): + c() diff --git a/spell.ignore b/spell.ignore index b97ffbb03c2..ffd6ad5ed09 100644 --- a/spell.ignore +++ b/spell.ignore @@ -180,6 +180,9 @@ datetime DAX dbus de +decrypt +decrypted +decryption deduplicate del deplist From 3ff5edee5e7055f31a18bba55137f15fd81b09e9 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Tue, 20 Feb 2024 20:56:31 -0500 Subject: [PATCH 0278/1055] Add new case of update interface: update-device with options - VIRT-298326 - [update-device] Update an interface by update-device with --live/--config/--current/--persistent on active domain - VIRT-298319 - [update-device] Update an interface by update-device with --live/--config/--current/--persistent on inactive domain Signed-off-by: Haijiao Zhao --- .../update_iface_with_options_active.cfg | 32 +++++++ .../update_iface_with_options_inactive.cfg | 38 ++++++++ .../update_iface_with_options.py | 90 +++++++++++++++++++ provider/virtual_network/network_base.py | 4 +- 4 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 libvirt/tests/cfg/virtual_network/update_device/update_iface_with_options_active.cfg create mode 100644 libvirt/tests/cfg/virtual_network/update_device/update_iface_with_options_inactive.cfg create mode 100644 libvirt/tests/src/virtual_network/update_device/update_iface_with_options.py diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_options_active.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_options_active.cfg new file mode 100644 index 00000000000..8bc7942e8d1 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_options_active.cfg @@ -0,0 +1,32 @@ +- virtual_network.update_device.with_options.active_vm: + type = update_iface_with_options + start_vm = no + timeout = 240 + vm_active = True + iface_attrs = {'link_state': 'up'} + update_attrs = {'link_state': 'down'} + variants options: + - live: + update_expect = {'active': True, 'inactive': False} + - live_persistent: + update_expect = {'active': True, 'inactive': True} + - live_config: + update_expect = {'active': True, 'inactive': True} + - live_current: + status_error = yes + err_msg = Options .* and .* are mutually exclusive + update_expect = {'active': False, 'inactive': False} + - current: + update_expect = {'active': True, 'inactive': False} + - persistent: + update_expect = {'active': True, 'inactive': True} + - persistent_current: + status_error = yes + err_msg = Options .* and .* are mutually exclusive + update_expect = {'active': False, 'inactive': False} + - config: + update_expect = {'active': False, 'inactive': True} + - config_persistent: + update_expect = {'active': True, 'inactive': True} + - none: + update_expect = {'active': True, 'inactive': False} diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_options_inactive.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_options_inactive.cfg new file mode 100644 index 00000000000..93422f8e06b --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_options_inactive.cfg @@ -0,0 +1,38 @@ +- virtual_network.update_device.with_options.inactive_vm: + type = update_iface_with_options + start_vm = no + timeout = 240 + vm_active = False + iface_attrs = {'link_state': 'up'} + update_attrs = {'link_state': 'down'} + variants options: + - live: + status_error = yes + err_msg = Requested operation is not valid: domain is not running + update_expect = {'inactive': False} + - live_persistent: + status_error = yes + err_msg = Requested operation is not valid: domain is not running + update_expect = {'inactive': False} + - live_config: + status_error = yes + err_msg = Requested operation is not valid: domain is not running + update_expect = {'inactive': False} + - live_current: + status_error = yes + err_msg = Options --current and --live are mutually exclusive + update_expect = {'inactive': False} + - current: + update_expect = {'inactive': True} + - persistent: + update_expect = {'inactive': True} + - persistent_current: + status_error = yes + err_msg = Options --persistent and --current are mutually exclusive + update_expect = {'inactive': False} + - config: + update_expect = {'inactive': True} + - config_persistent: + update_expect = {'inactive': True} + - none: + update_expect = {'inactive': True} diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_with_options.py b/libvirt/tests/src/virtual_network/update_device/update_iface_with_options.py new file mode 100644 index 00000000000..0dfea8f2ada --- /dev/null +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_with_options.py @@ -0,0 +1,90 @@ +import logging + +from virttest import utils_net +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test Update an interface by update-device + with --live/--config/--current/--persistent on active/inactive domain + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + status_error = 'yes' == params.get('status_error', 'no') + err_msg = params.get('err_msg') + iface_attrs = eval(params.get('iface_attrs', '{}')) + update_attrs = eval(params.get('update_attrs', '{}')) + update_expect = eval(params.get('update_expect', '{}')) + options = params.get('options') + vm_active = eval(params.get('vm_active')) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs) + LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + if vm_active: + vm.start() + vm.wait_for_serial_login().close() + + iface = network_base.get_iface_xml_inst(vm_name, 'on vm') + mac = iface.mac_address + LOG.debug(f'Mac address of iface: {mac}') + LOG.debug(f'Update iface with attrs: {update_attrs}') + iface.setup_attrs(**update_attrs) + + # Generate options for update-device command + options = options.split('_') if 'none' not in options else [] + options = ' '.join([f'--{opt}' for opt in options]) + LOG.debug(f'Update iface with xml:\n{iface}') + up_result = virsh.update_device(vm_name, iface.xml, flagstr=options, + debug=True) + libvirt.check_exit_status(up_result, status_error) + if err_msg: + libvirt.check_result(up_result, err_msg) + + if vm_active: + iface_active = network_base.get_iface_xml_inst( + vm_name, 'on active vm after update') + LOG.debug(f'link state on active xml should be ' + f'{"down" if update_expect["active"] else "up"}') + if (iface_active.link_state == 'down') is not update_expect['active']: + test.fail('update result of iface xml on active vm ' + 'not met expectation.') + + iface_inactive = network_base.get_iface_xml_inst( + vm_name, 'on inactive vm after update', options='--inactive') + LOG.debug(f'link state on inactive xml should be ' + f'{"down" if update_expect["inactive"] else "up"}') + if (iface_inactive.link_state == 'down') is not update_expect['inactive']: + test.fail('update result of iface xml on inactive vm ' + 'not met expectation.') + + # Check update result on vm with ethtool + if vm_active: + session = vm.wait_for_serial_login() + vm_iface_info = utils_net.get_linux_iface_info( + mac=mac, session=session) + LOG.debug(f'iface info on vm: {vm_iface_info}') + ethtool_output = session.cmd_output( + f'ethtool {vm_iface_info["ifname"]}') + LOG.debug(f'ethtool output:\n{ethtool_output}') + LOG.debug(f'"Link detected" should be ' + f'{"no" if update_expect["active"] else "yes"}') + if ('Link detected: no' in ethtool_output) is not \ + update_expect['active']: + test.fail('ethtool check inside vm failed.') + finally: + bkxml.sync() diff --git a/provider/virtual_network/network_base.py b/provider/virtual_network/network_base.py index 61038423629..aaf67db2b8d 100644 --- a/provider/virtual_network/network_base.py +++ b/provider/virtual_network/network_base.py @@ -265,7 +265,7 @@ def set_static_ip(iface, ip, netmask, session): session.cmd(f'ifconfig {iface} {ip}/{netmask}') -def get_iface_xml_inst(vm_name, comment, index=0): +def get_iface_xml_inst(vm_name, comment, index=0, options=''): """ Get iface xml instance with given vm and index @@ -274,7 +274,7 @@ def get_iface_xml_inst(vm_name, comment, index=0): :param index: index of interface on vm, defaults to 0 :return: xml instance of interface """ - vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name, options=options) iface = vmxml.get_devices('interface')[index] LOG.debug(f'Interface xml ({comment}):\n{iface}') return iface From 909d705dd3b80ad2a4f4557c7af661f26f724ac1 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Wed, 6 Mar 2024 21:15:27 -0500 Subject: [PATCH 0279/1055] Add new cases of libvirtd - VIRT-300392 - Enable/disable daemons socket services - VIRT-300393 - Check the socket files after start/stop daemons' socket service - VIRT-300394 - Check virsh connection after switching between the legacy monolithic daemon and the modular daemon Signed-off-by: Haijiao Zhao --- .../check_socket_files_with_services.cfg | 5 ++ ..._switch_between_monolithic_and_modular.cfg | 3 + .../enable_disable_daemon_socket_services.cfg | 17 ++++++ .../check_socket_files_with_services.py | 58 +++++++++++++++++++ ...n_switch_between_monolithic_and_modular.py | 33 +++++++++++ .../enable_disable_daemon_socket_services.py | 52 +++++++++++++++++ provider/libvirtd/libvirtd_base.py | 54 +++++++++++++++++ 7 files changed, 222 insertions(+) create mode 100644 libvirt/tests/cfg/daemon/check_socket_files_with_services.cfg create mode 100644 libvirt/tests/cfg/daemon/check_virsh_connection_switch_between_monolithic_and_modular.cfg create mode 100644 libvirt/tests/cfg/daemon/enable_disable_daemon_socket_services.cfg create mode 100644 libvirt/tests/src/daemon/check_socket_files_with_services.py create mode 100644 libvirt/tests/src/daemon/check_virsh_connection_switch_between_monolithic_and_modular.py create mode 100644 libvirt/tests/src/daemon/enable_disable_daemon_socket_services.py create mode 100644 provider/libvirtd/libvirtd_base.py diff --git a/libvirt/tests/cfg/daemon/check_socket_files_with_services.cfg b/libvirt/tests/cfg/daemon/check_socket_files_with_services.cfg new file mode 100644 index 00000000000..717aa8c87c7 --- /dev/null +++ b/libvirt/tests/cfg/daemon/check_socket_files_with_services.cfg @@ -0,0 +1,5 @@ +- daemon.check_socket_files_with_services: + type = check_socket_files_with_services + start_vm = no + service_list = ['qemu', 'interface', 'network', 'nodedev', 'nwfilter', 'secret', 'storage', 'proxy'] + other_socket_files = ['virtlockd-sock', 'virtlogd-sock'] diff --git a/libvirt/tests/cfg/daemon/check_virsh_connection_switch_between_monolithic_and_modular.cfg b/libvirt/tests/cfg/daemon/check_virsh_connection_switch_between_monolithic_and_modular.cfg new file mode 100644 index 00000000000..b1e24099973 --- /dev/null +++ b/libvirt/tests/cfg/daemon/check_virsh_connection_switch_between_monolithic_and_modular.cfg @@ -0,0 +1,3 @@ +- daemon.check_virsh_connection_switch_between_monolithic_and_modular: + type = check_virsh_connection_switch_between_monolithic_and_modular + start_vm = no diff --git a/libvirt/tests/cfg/daemon/enable_disable_daemon_socket_services.cfg b/libvirt/tests/cfg/daemon/enable_disable_daemon_socket_services.cfg new file mode 100644 index 00000000000..eeabd3d5951 --- /dev/null +++ b/libvirt/tests/cfg/daemon/enable_disable_daemon_socket_services.cfg @@ -0,0 +1,17 @@ +- daemon.enable_disable_daemon_socket_services: + type = enable_disable_daemon_socket_services + start_vm = no + service_list = ['qemu', 'interface', 'network', 'nodedev', 'nwfilter', 'secret', 'storage', 'proxy'] + variants: + - main_socket: + service_list = ['qemu', 'interface', 'network', 'nodedev', 'nwfilter', 'secret', 'storage'] + sock_type = + - ro_socket: + service_list = ['qemu', 'interface', 'network', 'nodedev', 'nwfilter', 'secret', 'storage'] + sock_type = -ro + - admin_socket: + service_list = ['qemu', 'interface', 'network', 'nodedev', 'nwfilter', 'secret', 'storage'] + sock_type = -admin + - only_virtproxyd: + service_list = ['proxy'] + sock_type = diff --git a/libvirt/tests/src/daemon/check_socket_files_with_services.py b/libvirt/tests/src/daemon/check_socket_files_with_services.py new file mode 100644 index 00000000000..e3bc3837e30 --- /dev/null +++ b/libvirt/tests/src/daemon/check_socket_files_with_services.py @@ -0,0 +1,58 @@ +import logging +import os + +from virttest.staging import service + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Check the socket files are cleaned or created after stop/start + daemons' service. + """ + daemon_list = eval(params.get('service_list')) + other_socket_files = eval(params.get('other_socket_files')) + + try: + daemon_srv_list = [] + daemon_list = [f'virt{sub_daemon}d' for sub_daemon in daemon_list] + for daemon in daemon_list: + daemon_srv = service.Factory.create_service(daemon) + daemon_srv_list.append(daemon_srv) + daemon_srv.start() + + all_sock_files = os.listdir('/var/run/libvirt') + + daemons = daemon_list.copy() + daemons.remove('virtqemud') + daemons.remove('virtproxyd') + daemons.append('libvirt') + expect_s_files = [[f'{x}-admin-sock', + f'{x}-sock', + f'{x}-sock-ro'] for x in daemons] + expect_s_files = [x for y in expect_s_files for x in y] + expect_s_files.extend(other_socket_files) + LOG.debug(f'Expect socket files:\n{expect_s_files}') + diff = set(expect_s_files).difference(set(all_sock_files)) + if diff: + test.fail(f'Not found expected socket files: {diff}') + + for daemon in daemon_list: + daemon_sock_srv = service.Factory.create_service( + daemon + '.socket') + daemon_sock_srv.stop() + + all_sock_files = os.listdir('/var/run/libvirt') + LOG.debug(f'All files in /var/run/libvirt\n{all_sock_files}') + left_s_files = set(expect_s_files).intersection(set(all_sock_files)) + LOG.debug(f'Socket files left: {left_s_files}') + unexpect = left_s_files.difference(set(other_socket_files)) + if unexpect: + test.fail(f'Found unexpected socket files left: {unexpect}') + + finally: + for daemon in daemon_list: + daemon_sock_srv = service.Factory.create_service( + daemon + '.socket') + daemon_sock_srv.start() diff --git a/libvirt/tests/src/daemon/check_virsh_connection_switch_between_monolithic_and_modular.py b/libvirt/tests/src/daemon/check_virsh_connection_switch_between_monolithic_and_modular.py new file mode 100644 index 00000000000..3cebe243b3c --- /dev/null +++ b/libvirt/tests/src/daemon/check_virsh_connection_switch_between_monolithic_and_modular.py @@ -0,0 +1,33 @@ +import logging + +from virttest.staging import service + +from provider.libvirtd import libvirtd_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Verify virsh connection can work well after switching between the legacy + monolithic daemon and the modular daemon + """ + try: + libvirtd_srv = service.Factory.create_service('libvirtd') + virtqemud_srv = service.Factory.create_service('virtqemud') + libvirtd_base.check_virsh_connection('before test') + libvirtd_base.check_service_status('virtqemud', True) + libvirtd_srv.start() + libvirtd_base.check_service_status('libvirtd', True) + libvirtd_base.check_service_status('virtqemud', False) + libvirtd_base.check_virsh_connection( + 'after switch to legacy monolithic daemon mode') + virtqemud_srv.start() + libvirtd_base.check_service_status('libvirtd', False) + libvirtd_base.check_service_status('virtqemud', True) + libvirtd_base.check_virsh_connection( + 'after switch back to modular daemon mode') + finally: + virtqemud_srv.start() diff --git a/libvirt/tests/src/daemon/enable_disable_daemon_socket_services.py b/libvirt/tests/src/daemon/enable_disable_daemon_socket_services.py new file mode 100644 index 00000000000..c06e4b16eee --- /dev/null +++ b/libvirt/tests/src/daemon/enable_disable_daemon_socket_services.py @@ -0,0 +1,52 @@ +import logging + +from virttest.staging import service + +from provider.libvirtd import libvirtd_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Verify socket services will be in expected status after enable/disable + """ + service_list = eval(params.get('service_list')) + sock_type = params.get('sock_type') + '.socket' + daemon_list = [f'virt{ser}d' for ser in service_list] + + # Disable main socket before test + for daemon in daemon_list: + socket_srv = service.Factory.create_service(daemon + '.socket') + socket_srv.disable() + + try: + LOG.info('Test enable socket services') + for daemon in daemon_list: + socket_srv = service.Factory.create_service(daemon + sock_type) + LOG.debug(f'Enable service [{socket_srv}]') + socket_srv.enable() + libvirtd_base.check_service_status(daemon + '.socket', + expect_enabled=True) + libvirtd_base.check_service_status(daemon + '-ro.socket', + expect_enabled=True) + libvirtd_base.check_service_status(daemon + '-admin.socket', + expect_enabled=True) + + LOG.info('Test disable socket services') + for daemon in daemon_list: + socket_srv = service.Factory.create_service(daemon + sock_type) + LOG.debug(f'Disable service [{socket_srv}]') + socket_srv.disable() + libvirtd_base.check_service_status(daemon + '.socket', + expect_enabled=False) + libvirtd_base.check_service_status(daemon + '-ro.socket', + expect_enabled=False) + libvirtd_base.check_service_status(daemon + '-admin.socket', + expect_enabled=False) + finally: + for daemon in daemon_list: + socket_srv = service.Factory.create_service(daemon + '.socket') + socket_srv.enable() diff --git a/provider/libvirtd/libvirtd_base.py b/provider/libvirtd/libvirtd_base.py new file mode 100644 index 00000000000..3850930dc49 --- /dev/null +++ b/provider/libvirtd/libvirtd_base.py @@ -0,0 +1,54 @@ + +import logging + +from avocado.core import exceptions +from virttest import virsh +from virttest.staging import service + +LOG = logging.getLogger('avocado.' + __name__) + + +def check_service_status(service_name, expect_active=None, + expect_enabled=None): + """ + Check status of service + + :param service_name: name of service to be checked + :param expect_active: expect service status, True if active, + False if inactive, defaults to None + :param expect_enabled: expect service enablement, True if enabled + False if disenabled, defaults to None + """ + LOG.info(f'Check service status of {service_name}') + srvc = service.Factory.create_service(service_name) + LOG.debug(f'Service [{service_name}] status is ' + f'{"active" if srvc.status() else "inactive"}.\n' + f'Service [{service_name}] is ' + f'{"enabled" if srvc.is_enabled() else "disabled"}') + if expect_active is not None: + if srvc.status() == expect_active: + LOG.info(f'Service status check PASSED') + else: + raise exceptions.TestFail(f'Expect service [{service_name}] to be ' + f'{"active" if expect_active else "inactive"}') + if expect_enabled is not None: + if srvc.is_enabled() is expect_enabled: + LOG.info(f'Service enable check PASSED') + else: + raise exceptions.TestFail(f'Expect service [{service_name}] to be ' + f'{"enabled" if expect_enabled else "disabled"}') + + +def check_virsh_connection(msg): + """ + Check virsh connection by running virsh list + + :param msg: message to display + """ + LOG.info(f'Check virsh connection {msg}') + conn_result = virsh.dom_list(debug=True) + if conn_result.exit_status == 0: + LOG.info(f'Virsh connection check {msg} PASSED') + else: + raise exceptions.TestFail(f'Virsh connection {msg} FAILED:\n' + f'{conn_result.stderr_text}') From 3a47431e28c9c7e5daa3b9522aff4db9be2cadc5 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Fri, 26 Jan 2024 21:10:29 -0500 Subject: [PATCH 0280/1055] Add new case of update-device of interface qos - VIRT-294746 - [update-device][qos] Live update interface bandwidth setting by update-device or domiftune Signed-off-by: Haijiao Zhao --- .../update_device/update_iface_qos.cfg | 38 ++++ .../update_device/update_iface_qos.py | 173 ++++++++++++++++++ 2 files changed, 211 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/update_device/update_iface_qos.cfg create mode 100644 libvirt/tests/src/virtual_network/update_device/update_iface_qos.py diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_iface_qos.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_iface_qos.cfg new file mode 100644 index 00000000000..4d846fc23b4 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/update_device/update_iface_qos.cfg @@ -0,0 +1,38 @@ +- virtual_network.update_device.iface_qos: + type = update_iface_qos + start_vm = no + timeout = 240 + host_iface = + extra_attrs = {} + variants: + - inbound_outbound: + scope = ['inbound', 'outbound'] + - inbound_only: + scope = ['outbound'] + - outbound_only: + scope = ['outbound'] + variants operation: + - add: + update_attrs = {'bandwidth': {'outbound': {'average': '200', 'peak': '400', 'burst': '600'},'inbound': {'average': '100', 'peak': '300', 'burst': '500'}}} + - update: + extra_attrs = {'bandwidth': {'outbound': {'average': '200', 'peak': '400', 'burst': '600'},'inbound': {'average': '100', 'peak': '300', 'burst': '500'}}} + update_attrs = {'bandwidth': {'outbound': {'average': '300', 'peak': '400', 'burst': '500'},'inbound': {'average': '500', 'peak': '700', 'burst': '900'}}} + - delete: + extra_attrs = {'bandwidth': {'outbound': {'average': '200', 'peak': '400', 'burst': '600'},'inbound': {'average': '100', 'peak': '300', 'burst': '500'}}} + update_attrs = {'bandwidth': {'outbound': {'average': '0', 'peak': '0', 'burst': '0'},'inbound': {'average': '0', 'peak': '0', 'burst': '0'}}} + variants method: + - update-device: + delete: + only inbound_outbound + - domiftune: + variants iface_setting: + - net_iface_default_net: + iface_attrs = {'source': {'network': 'default'}, 'type_name': 'network'} + - br_iface_linux_br: + br_type = linux_br + iface_attrs = {'type_name': 'bridge', 'source': {'bridge': br_name}} + - br_iface_ovs_br: + br_type = ovs_br + iface_attrs = {'type_name': 'bridge', 'source': {'bridge': br_name}, 'virtualport': {'type': 'openvswitch'}} + - direct_bridge_iface: + iface_attrs = {'type_name': 'direct', 'source': {'dev': host_iface, 'mode': 'bridge'}} diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_qos.py b/libvirt/tests/src/virtual_network/update_device/update_iface_qos.py new file mode 100644 index 00000000000..a5b95e3d1b7 --- /dev/null +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_qos.py @@ -0,0 +1,173 @@ +import logging + +from avocado.utils import process +from virttest import utils_misc +from virttest import utils_net +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_misc +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def domiftune_to_dict(output): + """ + Convert domiftune output to dict + + :param output: domiftune output + :return: converted dict + """ + tmp_dict = libvirt_misc.convert_to_dict(output, '(\S+)\s*:\s*(\d+)') + final = {} + final['inbound'] = {k.split('.')[-1]: v for k, v in tmp_dict.items() + if k.startswith('inbound')} + final['outbound'] = {k.split('.')[-1]: v for k, v in tmp_dict.items() + if k.startswith('outbound')} + return final + + +def run(test, params, env): + """ + Test live update interface bandwidth setting by update-device or domiftune + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + br_type = params.get('br_type', '') + rand_id = utils_misc.generate_random_string(3) + br_name = br_type + '_' + rand_id + host_iface = params.get('host_iface') + host_iface = host_iface if host_iface else utils_net.get_net_if( + state='UP')[0] + iface_attrs = eval(params.get('iface_attrs', '{}')) + extra_attrs = eval(params.get('extra_attrs', '{}')) + net_attrs = eval(params.get('net_attrs', '{}')) + + scope = eval(params.get('scope', '[]')) + method = params.get('method', '') + operation = params.get('operation', '') + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + if br_type == 'linux_br': + utils_net.create_linux_bridge_tmux(br_name, host_iface) + process.run(f'ip l show type bridge {br_name}', shell=True) + elif br_type == 'ovs_br': + utils_net.create_ovs_bridge(br_name) + + vmxml.del_device('interface', by_tag=True) + + # Update iface_attrs with certain bandwidth settings + extra_attrs = {'bandwidth': {k: extra_attrs['bandwidth'][k] + for k in scope} + } if extra_attrs else extra_attrs + iface_attrs.update(extra_attrs) + libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs) + LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + # For direct interface type, "tc class show dev" will show the outbound + # instead of the inbound setting, and "tc filter show dev" will show + # the inbound instead of the outbound setting + iface_type = iface_attrs['type_name'] + class_key = 'outbound' if iface_type == 'direct' else 'inbound' + filter_key = 'inbound' if iface_type == 'direct' else 'outbound' + + vm.start() + session = vm.wait_for_serial_login() + + iface = network_base.get_iface_xml_inst(vm_name, 'on vm') + mac = iface.mac_address + tap_device = libvirt.get_ifname_host(vm_name, mac) + LOG.debug(f'tap device on host with mac {mac} is: {tap_device}.') + + if 'bandwidth' in iface_attrs: + if class_key in scope and not utils_net.check_class_rules( + tap_device, '1:1', iface_attrs['bandwidth'][class_key]): + test.fail( + 'Class rule check before update failed. Please check log.') + if filter_key in scope and not utils_net.check_filter_rules( + tap_device, iface_attrs['bandwidth'][filter_key]): + test.fail( + 'Filter rule check before update failed. Please check log.') + + # Remove out-of-scope settings + update_attrs = eval(params.get('update_attrs', '{}')) + update_attrs['bandwidth'] = {k: update_attrs['bandwidth'][k] + for k in scope} + LOG.debug(f'Update iface with attrs: {update_attrs}') + if method == 'update-device': + if operation == 'delete': + iface.del_bandwidth() + else: + iface.setup_attrs(**update_attrs) + LOG.debug(f'Update iface with xml:\n{iface}') + virsh.update_device(vm_name, iface.xml, **VIRSH_ARGS) + + elif method == 'domiftune': + domiftune_args = {} + if 'inbound' in scope: + bw_in = update_attrs['bandwidth']['inbound'] + inbound = f'{bw_in["average"]},{bw_in["peak"]},{bw_in["burst"]}' + domiftune_args.update({'inbound': inbound}) + if 'outbound' in scope: + bw_out = update_attrs['bandwidth']['outbound'] + outbound = f'{bw_out["average"]},{bw_out["peak"]},{bw_out["burst"]}' + domiftune_args.update({'outbound': outbound}) + virsh.domiftune(vm_name, tap_device, ** + domiftune_args, **VIRSH_ARGS) + else: + test.error(f'Unsupported method: {method}.') + + iface_update = network_base.get_iface_xml_inst(vm_name, 'after update') + if operation == 'delete': + if 'bandwidth' in iface_update.fetch_attrs(): + test.fail('Bandwidth of interface xml not deleted') + else: + LOG.debug(iface_update.bandwidth) + for key in scope: + if iface_update.fetch_attrs()['bandwidth'][key] != update_attrs['bandwidth'][key]: + test.fail( + 'Bandwidth of interface xml not correctly updated') + + if operation == 'delete': + out_c = process.run(f'tc class show dev {tap_device}' + ).stdout_text.strip() + out_f = process.run(f'tc filter show dev {tap_device} parent ffff' + ).stdout_text.strip() + if any([out_c, out_f]): + test.fail('There should not be output of tc class/filter ' + 'command when bandwidth settings is deleted.') + else: + if class_key in scope and not utils_net.check_class_rules( + tap_device, '1:1', update_attrs['bandwidth'][class_key]): + test.fail( + 'Class rule check after update failed. Please check log.') + if filter_key in scope and not utils_net.check_filter_rules( + tap_device, update_attrs['bandwidth'][filter_key]): + test.fail( + 'Filter rule check after update failed. Please check log.') + + domiftune_output = virsh.domiftune(vm_name, tap_device, + **VIRSH_ARGS).stdout_text + domiftune_dict = domiftune_to_dict(domiftune_output) + LOG.debug(f'domiftune to dict: {domiftune_dict}') + for key in scope: + if not update_attrs['bandwidth'][key].items() <= \ + domiftune_dict[key].items(): + test.fail(f'domiftune {key} check fail.') + + finally: + if 'session' in locals(): + session.close() + bkxml.sync() + if br_type == 'linux_br': + utils_net.delete_linux_bridge_tmux(br_name, host_iface) + if br_type == 'ovs_br': + utils_net.delete_ovs_bridge(br_name) From 323ab258c19b356a7ae43f262c2ad11c0f66463b Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Wed, 27 Mar 2024 23:09:42 -0400 Subject: [PATCH 0281/1055] Add network case of update-device:trustGuestRxFilters - VIRT-300484 - [update-device][trustGuestRxFilters] update the trustGuestRxFilters by update-device Signed-off-by: Haijiao Zhao --- .../update_iface_trustGuestRxFilters.cfg | 18 ++++ .../update_iface_trustGuestRxFilters.py | 85 +++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/update_device/update_iface_trustGuestRxFilters.cfg create mode 100644 libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_iface_trustGuestRxFilters.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_iface_trustGuestRxFilters.cfg new file mode 100644 index 00000000000..9ac73138f41 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/update_device/update_iface_trustGuestRxFilters.cfg @@ -0,0 +1,18 @@ +- virtual_network.update_device.update_iface_trustGuestRxFilters: + type = update_iface_trustGuestRxFilters + start_vm = no + timeout = 240 + host_iface = + outside_ip = 'www.redhat.com' + variants: + - yes_to_no: + trustGRF = 'yes' + update_attrs = {'trustGuestRxFilters': 'no'} + vm_ping_outside = fail + err_msg = f'Mac address of {target_dev} on host should not change' + - no_to_yes: + trustGRF = 'no' + update_attrs = {'trustGuestRxFilters': 'yes'} + vm_ping_outside = pass + err_msg = f'Mac address of {target_dev} on host should be the same as vm' + iface_attrs = {'type_name': 'direct', 'trustGuestRxFilters': '${trustGRF}', 'model': 'virtio', 'source': {'dev': host_iface, 'mode': 'bridge'}} diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py b/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py new file mode 100644 index 00000000000..c41eab8da90 --- /dev/null +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py @@ -0,0 +1,85 @@ +import logging + +from avocado.utils import process +from virttest import utils_net +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test live update trustGuestRxFilters for direct type interface + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + host_iface = params.get('host_iface') + host_iface = host_iface if host_iface else utils_net.get_net_if( + state='UP')[0] + iface_attrs = eval(params.get('iface_attrs', '{}')) + ips = {'outside_ip': params.get('outside_ip')} + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + vmxml.del_device('interface', by_tag=True) + libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs) + LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + vm.start() + + iface = network_base.get_iface_xml_inst(vm_name, 'on vm') + target_dev = iface.target['dev'] + update_attrs = eval(params.get('update_attrs', '{}')) + LOG.debug(f'Update iface with attrs: {update_attrs}') + iface.setup_attrs(**update_attrs) + LOG.debug(f'Update iface with xml:\n{iface}') + + virsh.update_device(vm_name, iface.xml, **VIRSH_ARGS) + + iface_update = network_base.get_iface_xml_inst(vm_name, 'after update') + LOG.debug(f'iface trustGuestRxFilters after update: ' + f'{iface_update.trustGuestRxFilters}') + + mac_host = utils_net.get_linux_iface_info(iface=target_dev)['address'] + + session = vm.wait_for_serial_login() + mac = iface.mac_address + vm_iface = utils_net.get_linux_ifname(session, mac) + LOG.debug(f'Interface inside vm: {vm_iface}') + + vm_iface_info = utils_net.get_linux_iface_info( + vm_iface, session=session) + LOG.debug(f'iface info inside vm:\n{vm_iface_info}') + new_mac = utils_net.generate_mac_address_simple() + session.cmd(f'ip l set dev {vm_iface} address {new_mac}') + + network_base.ping_check(params, ips, session, force_ipv4=True) + session.close() + mac_host_after = utils_net.get_linux_iface_info( + iface=target_dev)['address'] + + expect_mac = mac_host if update_attrs[ + 'trustGuestRxFilters'] == 'no' else new_mac + if mac_host_after != expect_mac: + test.fail(eval(params.get('err_msg'))) + + virsh.shutdown(vm_name, **VIRSH_ARGS) + if not vm.wait_for_shutdown(): + test.error('VM failed to shutdown in 60s') + + output = process.run(f' ip addr show {target_dev}', + shell=True, ignore_status=True) + libvirt.check_exit_status(output, expect_error=True) + libvirt.check_result(output, 'does not exist') + + finally: + bkxml.sync() From 956a91f05e1af34ebb0b6aa19c9f800f9e4ccacb Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Tue, 26 Mar 2024 07:16:58 +0800 Subject: [PATCH 0282/1055] guest_numa: fix out of date qemu cmd line update The excluded libvirt version and machine types are out of date. Those old versions should not in our test scope and should be given up. Instead, we should use new qemu command line not only on q35, but also other arches, like aarch64. Signed-off-by: Dan Zheng --- libvirt/tests/cfg/numa/guest_numa.cfg | 4 ++-- libvirt/tests/src/numa/guest_numa.py | 30 --------------------------- 2 files changed, 2 insertions(+), 32 deletions(-) diff --git a/libvirt/tests/cfg/numa/guest_numa.cfg b/libvirt/tests/cfg/numa/guest_numa.cfg index 5218bf0377b..df09f0e14a0 100644 --- a/libvirt/tests/cfg/numa/guest_numa.cfg +++ b/libvirt/tests/cfg/numa/guest_numa.cfg @@ -28,8 +28,8 @@ - no_numatune_mem: variants: - no_numatune_memnode: - qemu_cmdline_numa_cell_0 = "node,nodeid=0,cpus=0-1,mem=1024" - qemu_cmdline_numa_cell_1 = "node,nodeid=1,cpus=2-3,mem=1024" + qemu_cmdline_numa_cell_0 = "node,nodeid=0,cpus=0-1,memdev=ram-node0" + qemu_cmdline_numa_cell_1 = "node,nodeid=1,cpus=2-3,memdev=ram-node1" - numatune_memnode: memnode_nodeset_0 = 1 pseries: diff --git a/libvirt/tests/src/numa/guest_numa.py b/libvirt/tests/src/numa/guest_numa.py index 1860860c73d..8038e8d9ff2 100644 --- a/libvirt/tests/src/numa/guest_numa.py +++ b/libvirt/tests/src/numa/guest_numa.py @@ -97,35 +97,6 @@ def run(test, params, env): """ Test guest numa setting """ - - def replace_qemu_cmdline(cmdline_list): - """ - Replace the expected qemu command line for new machine type - - :param cmdline_list: The list for expected qemu command lines - :return: The list contains the updated qemu command lines if any - """ - os_xml = getattr(vmxml, "os") - machine_ver = getattr(os_xml, 'machine') - if (machine_ver.startswith("pc-q35-rhel") and - machine_ver > 'pc-q35-rhel8.2.0' and - libvirt_version.version_compare(6, 4, 0)): - # Replace 'node,nodeid=0,cpus=0-1,mem=1024' with - # 'node,nodeid=0,cpus=0-1,memdev=ram-node0' - # Replace 'node,nodeid=1,cpus=2-3,mem=1024' with - # 'node,nodeid=1,cpus=2-3,memdev=ram-node1' - for cmd in cmdline_list: - line = cmd['cmdline'] - try: - node = line.split(',')[1][-1] - cmd['cmdline'] = line.replace('mem=1024', - 'memdev=ram-node{}'.format(node)) - # We can skip replacing, when the cmdline parameter is empty. - except IndexError: - pass - - return cmdline_list - host_numa_node = utils_misc.NumaInfo() node_list = host_numa_node.online_nodes arch = platform.machine() @@ -430,7 +401,6 @@ def _update_qemu_conf(): with open("/proc/%s/cmdline" % vm_pid) as f_cmdline: q_cmdline_list = f_cmdline.read().split("\x00") logging.debug("vm qemu cmdline list is %s" % q_cmdline_list) - cmdline_list = replace_qemu_cmdline(cmdline_list) for cmd in cmdline_list: logging.debug("checking '%s' in qemu cmdline", cmd['cmdline']) p_found = False From fa154d862273144e6963a7cc179af52dc3dd1971 Mon Sep 17 00:00:00 2001 From: nanli Date: Tue, 12 Mar 2024 13:52:44 +0800 Subject: [PATCH 0283/1055] add case for revert snap for guest with genid xxxx-300460:Revert snapshot for guest which includes genid. Signed-off-by: nanli --- .../revert_snap_for_guest_with_genid.cfg | 7 ++ .../revert_snap_for_guest_with_genid.py | 94 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 libvirt/tests/cfg/snapshot/revert_snap_for_guest_with_genid.cfg create mode 100644 libvirt/tests/src/snapshot/revert_snap_for_guest_with_genid.py diff --git a/libvirt/tests/cfg/snapshot/revert_snap_for_guest_with_genid.cfg b/libvirt/tests/cfg/snapshot/revert_snap_for_guest_with_genid.cfg new file mode 100644 index 00000000000..ceb14a6ceaf --- /dev/null +++ b/libvirt/tests/cfg/snapshot/revert_snap_for_guest_with_genid.cfg @@ -0,0 +1,7 @@ +- snapshot_revert.with_genid: + type = revert_snap_for_guest_with_genid + start_vm = no + func_supported_since_libvirt_ver = (9, 10, 0) + snap_names = ['s1', 's2'] + snap_options = "%s --memspec snapshot=external,file=/tmp/mem.%s --diskspec vda,snapshot=external,file=/tmp/vda.%s" + diff --git a/libvirt/tests/src/snapshot/revert_snap_for_guest_with_genid.py b/libvirt/tests/src/snapshot/revert_snap_for_guest_with_genid.py new file mode 100644 index 00000000000..e633ad85fda --- /dev/null +++ b/libvirt/tests/src/snapshot/revert_snap_for_guest_with_genid.py @@ -0,0 +1,94 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import uuid + +from virttest import libvirt_version +from virttest import virsh +from virttest.libvirt_xml import vm_xml + +from provider.snapshot import snapshot_base + + +def check_genid(vm, test, old_genid, changed=False): + """ + Check if genid is changed. + + :params vm: vm object + :params test: test object + :params old_genid: the old genid value to compare + :params changed: Checking is new genid is changed, default False + """ + vmxml = vm_xml.VMXML.new_from_dumpxml(vm.name) + test.log.debug("The new xml is:\n%s", vmxml) + + new_genid = vmxml.get_genid() + if changed: + if new_genid == old_genid: + test.fail("Genid '%s' is same as old genid '%s'" % (new_genid, old_genid)) + else: + if new_genid != old_genid: + test.fail("Genid is updated from '%s' to '%s'" % (old_genid, new_genid)) + test.log.debug("Check genid successfully") + + +def run(test, params, env): + """ + Revert snapshot for guest which includes genid. + """ + def run_test(): + """ + Revert snapshot for guest which includes genid. + """ + test.log.info("TEST_STEP1:Prepare a running guest with genid.") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + original_genid = str(uuid.uuid4()) + vmxml.setup_attrs(**{'genid': original_genid}) + vmxml.sync() + virsh.start(vm_name) + vm.wait_for_login().close() + + test.log.info("TEST_STEP2,3:Create disk snapshots and memory snapshots." + "Check snapshots and genid is not changed") + for sname in snap_names: + virsh.snapshot_create_as(vm.name, snap_options % (sname, sname, sname), + **virsh_dargs) + test_obj.check_snap_list(sname) + check_genid(vm, test, original_genid) + + test.log.info("TEST_STEP4: Revert snapshot to the first snap") + virsh.snapshot_revert(vm_name, snap_names[0], **virsh_dargs) + + test.log.info("TEST_STEP6:Check genid which has already been changed.") + check_genid(vm, test, original_genid, changed=True) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + snap_names.reverse() + test_obj.teardown_test() + + vm_name = params.get("main_vm") + original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + params['backup_vmxml'] = original_xml.copy() + vm = env.get_vm(vm_name) + + virsh_dargs = {"debug": True, "ignore_status": True} + snap_names = eval(params.get("snap_names", '[]')) + snap_options = params.get("snap_options") + test_obj = snapshot_base.SnapshotTest(vm, test, params) + + try: + libvirt_version.is_libvirt_feature_supported(params) + run_test() + + finally: + teardown_test() From d532c609f0e677f48f2122c24102c6fd449c78af Mon Sep 17 00:00:00 2001 From: nanli Date: Wed, 3 Apr 2024 17:54:00 +0800 Subject: [PATCH 0284/1055] fix snapshot case to use appropirate get snap state function no need to use the new created function: virsh.snapshot_status Signed-off-by: nanli --- ...tus.cfg => revert_snap_based_on_state.cfg} | 18 +++--- ...tatus.py => revert_snap_based_on_state.py} | 55 ++++++++++++------- 2 files changed, 45 insertions(+), 28 deletions(-) rename libvirt/tests/cfg/snapshot/{revert_snap_based_on_status.cfg => revert_snap_based_on_state.cfg} (55%) rename libvirt/tests/src/snapshot/{revert_snap_based_on_status.py => revert_snap_based_on_state.py} (51%) diff --git a/libvirt/tests/cfg/snapshot/revert_snap_based_on_status.cfg b/libvirt/tests/cfg/snapshot/revert_snap_based_on_state.cfg similarity index 55% rename from libvirt/tests/cfg/snapshot/revert_snap_based_on_status.cfg rename to libvirt/tests/cfg/snapshot/revert_snap_based_on_state.cfg index c5eec301d7d..aabdc2c963b 100644 --- a/libvirt/tests/cfg/snapshot/revert_snap_based_on_status.cfg +++ b/libvirt/tests/cfg/snapshot/revert_snap_based_on_state.cfg @@ -1,19 +1,19 @@ -- snapshot_revert.snap_and_domain_status: - type = revert_snap_based_on_status +- snapshot_revert.snap_and_domain_state: + type = revert_snap_based_on_state start_vm = no snap_name = 's1' func_supported_since_libvirt_ver = (9, 10, 0) - variants : + variants: - snap_running: - snap_status = "running" - expected_status = "${snap_status}" + snap_state = "running" + expected_state = "${snap_state}" snap_options = " %s --memspec snapshot=external,file=/tmp/mem.s1 --diskspec vda,snapshot=external,file=/tmp/vda.s1" - snap_shutoff: - snap_status = "shutoff" - expected_status = "shut off" + snap_state = "shutoff" + expected_state = "shut off" snap_options = " %s --diskspec vda,snapshot=external,file=/tmp/vda.s1" variants: - vm_running: - vm_status = "running" + vm_state = "running" - vm_shutoff: - vm_status = "shut off" + vm_state = "shut off" diff --git a/libvirt/tests/src/snapshot/revert_snap_based_on_status.py b/libvirt/tests/src/snapshot/revert_snap_based_on_state.py similarity index 51% rename from libvirt/tests/src/snapshot/revert_snap_based_on_status.py rename to libvirt/tests/src/snapshot/revert_snap_based_on_state.py index 2fcad459afc..04b55d6b890 100644 --- a/libvirt/tests/src/snapshot/revert_snap_based_on_status.py +++ b/libvirt/tests/src/snapshot/revert_snap_based_on_state.py @@ -11,47 +11,64 @@ from virttest import virsh from virttest.libvirt_xml import vm_xml from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_misc from provider.snapshot import snapshot_base def run(test, params, env): """ - Revert snapshots based on different domain status. + Revert snapshots based on different domain state. """ + + def get_snap_state(vm_name): + """ + Get list of snapshots state of domain. + + :param vm_name: name of domain + :return: dict of snapshot names and snapshot state, + e.g.: get {'s1': 'running', 's2': 'running'} + """ + result = virsh.command("snapshot-list %s" % vm_name, + **virsh_dargs).stdout_text.strip() + state_dict = libvirt_misc.convert_to_dict( + result, r"(\S*) *\d+.* \d*:\d*:\d* .\d* *(\S*)") + test.log.debug("Get snap name and state dict is :%s", state_dict) + return state_dict + def run_test(): """ - Revert snapshots based on different domain status. + Revert snapshots based on different domain state. """ test.log.info("TEST_STEP1: Prepare a snap.") - if snap_status == "running": + if snap_state == "running": virsh.start(vm_name, **virsh_dargs) vm.wait_for_login().close() virsh.snapshot_create_as(vm_name, snap_options % snap_name, **virsh_dargs) - status_result = virsh.snapshot_status(vm_name, **virsh_dargs) - if status_result[snap_name] != snap_status: - test.fail("%s status should be '%s' instead of '%s'" % ( - snap_name, snap_status, status_result[snap_name])) + state_result = get_snap_state(vm_name) + if state_result[snap_name] != snap_state: + test.fail("%s state should be '%s' instead of '%s'" % ( + snap_name, snap_state, state_result[snap_name])) else: - test.log.debug("Check snap status '%s' is correct" % snap_status) + test.log.debug("Check snap state '%s' is correct" % snap_state) - test.log.info("TEST_STEP2: Set domain status.") - if vm_status.replace(' ', '') != snap_status: - if vm_status == "shut off": + test.log.info("TEST_STEP2: Set domain state.") + if vm_state.replace(' ', '') != snap_state: + if vm_state == "shut off": virsh.destroy(vm_name, **virsh_dargs) - elif vm_status == "running": + elif vm_state == "running": virsh.start(vm_name, **virsh_dargs) vm.wait_for_login().close() test.log.info("TEST_STEP3: Revert the snapshot") virsh.snapshot_revert(vm_name, snap_name, **virsh_dargs) - test.log.info("TEST_STEP5: Check expected domain status") - if not libvirt.check_vm_state(vm_name, expected_status): - test.fail("VM status should be '%s' after reverting." % expected_status) + test.log.info("TEST_STEP5: Check expected domain state") + if not libvirt.check_vm_state(vm_name, expected_state): + test.fail("VM state should be '%s' after reverting." % expected_state) else: - test.log.debug("Check vm status '%s' is correct", expected_status) + test.log.debug("Check vm state '%s' is correct", expected_state) def teardown_test(): """ @@ -68,9 +85,9 @@ def teardown_test(): virsh_dargs = {"debug": True, "ignore_status": True} snap_name = params.get("snap_name") snap_options = params.get("snap_options") - snap_status = params.get("snap_status") - vm_status = params.get("vm_status") - expected_status = params.get("expected_status") + snap_state = params.get("snap_state") + vm_state = params.get("vm_state") + expected_state = params.get("expected_state") test_obj = snapshot_base.SnapshotTest(vm, test, params) try: From 36654d1eeb4ff622404acee86f730ada83ae2119 Mon Sep 17 00:00:00 2001 From: nanli Date: Tue, 9 Apr 2024 14:58:24 +0800 Subject: [PATCH 0285/1055] fix snapshot case the libvirt version issue teardown step should not be executed after check vesrion function is executed Signed-off-by: nanli --- libvirt/tests/src/snapshot/revert_memory_only_snap.py | 2 +- libvirt/tests/src/snapshot/revert_snap_based_on_state.py | 3 +-- libvirt/tests/src/snapshot/revert_snap_for_guest_with_genid.py | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/src/snapshot/revert_memory_only_snap.py b/libvirt/tests/src/snapshot/revert_memory_only_snap.py index e54f8fac194..44138d05ba9 100644 --- a/libvirt/tests/src/snapshot/revert_memory_only_snap.py +++ b/libvirt/tests/src/snapshot/revert_memory_only_snap.py @@ -71,9 +71,9 @@ def teardown_test(): target_disk = params.get("target_disk") test_obj = snapshot_base.SnapshotTest(vm, test, params) disk_obj = disk_base.DiskBase(test, vm, params) + libvirt_version.is_libvirt_feature_supported(params) try: - libvirt_version.is_libvirt_feature_supported(params) run_test() finally: diff --git a/libvirt/tests/src/snapshot/revert_snap_based_on_state.py b/libvirt/tests/src/snapshot/revert_snap_based_on_state.py index 04b55d6b890..468773efdfc 100644 --- a/libvirt/tests/src/snapshot/revert_snap_based_on_state.py +++ b/libvirt/tests/src/snapshot/revert_snap_based_on_state.py @@ -90,9 +90,8 @@ def teardown_test(): expected_state = params.get("expected_state") test_obj = snapshot_base.SnapshotTest(vm, test, params) + libvirt_version.is_libvirt_feature_supported(params) try: - libvirt_version.is_libvirt_feature_supported(params) run_test() - finally: teardown_test() diff --git a/libvirt/tests/src/snapshot/revert_snap_for_guest_with_genid.py b/libvirt/tests/src/snapshot/revert_snap_for_guest_with_genid.py index e633ad85fda..c3a967c039b 100644 --- a/libvirt/tests/src/snapshot/revert_snap_for_guest_with_genid.py +++ b/libvirt/tests/src/snapshot/revert_snap_for_guest_with_genid.py @@ -86,8 +86,8 @@ def teardown_test(): snap_options = params.get("snap_options") test_obj = snapshot_base.SnapshotTest(vm, test, params) + libvirt_version.is_libvirt_feature_supported(params) try: - libvirt_version.is_libvirt_feature_supported(params) run_test() finally: From 07dc8b1ce8273fd98cf47d998694b36bf27cc316 Mon Sep 17 00:00:00 2001 From: Qian Jianhua Date: Wed, 10 Apr 2024 11:53:04 +0800 Subject: [PATCH 0286/1055] fix a typo in _trim_completed Signed-off-by: Qian Jianhua --- libvirt/tests/src/virsh_cmd/domain/virsh_domfstrim.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_domfstrim.py b/libvirt/tests/src/virsh_cmd/domain/virsh_domfstrim.py index 76edd2b1a53..bf78f762d3e 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_domfstrim.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_domfstrim.py @@ -197,7 +197,7 @@ def _full_mapped(): def _trim_completed(): """ Do empty fstrim check - :return: True of False + :return: True or False """ cmd_result = virsh.domfstrim(vm_name, minimum, mountpoint, options, unprivileged_user=unprivileged_user, From f5a3e65c9f78089f9f012f8875dc8e5711d6ede2 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Mon, 18 Mar 2024 04:56:45 -0400 Subject: [PATCH 0287/1055] Ensure the permission is set correctly Sometimes the permissoin is not set successfully. Update it to ensure it is set correctly. Signed-off-by: Yalan Zhang --- .../src/virtual_network/iface_unprivileged.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/libvirt/tests/src/virtual_network/iface_unprivileged.py b/libvirt/tests/src/virtual_network/iface_unprivileged.py index 428b615bfe7..a5d1d41d4c4 100644 --- a/libvirt/tests/src/virtual_network/iface_unprivileged.py +++ b/libvirt/tests/src/virtual_network/iface_unprivileged.py @@ -159,12 +159,18 @@ def check_ping(dest_ip, ping_count, timeout, src_ip=None, session=None, tap_index = process.run(cmd_get_tap, shell=True, verbose=True).stdout_text.strip() device_path = '/dev/tap{}'.format(tap_index) logging.debug('device_path: {}'.format(device_path)) - # Change owner and group for device - process.run('chown {user} {path};chgrp {user} {path}'.format( - user=up_user, path=device_path), - shell=True, verbose=True) - # Check if device owner is changed to unprivileged user - process.run('ls -l %s' % device_path, shell=True, verbose=True) + # Change owner and group for device and ensure it is changed successfully + + def ensure_permission_ready(): + """ + check if the permission set ready + """ + process.run('chown {user} {path};chgrp {user} {path}'.format( + user=up_user, path=device_path), shell=True, verbose=True) + res = process.run('ls -l %s' % device_path, shell=True, verbose=True) + return "%s %s" % (up_user, up_user) in str(res) + + utils_misc.wait_for(ensure_permission_ready, timeout=10) # Modify interface all_devices = upu_vmxml.devices From 4a632da3519f8b314f55985d0596526548a67537 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 10 Apr 2024 22:15:51 +0800 Subject: [PATCH 0288/1055] virtual_network: Add a case of update-device This PR adds: VIRT-294737 - Live update interface link state by update-device Signed-off-by: Yingshun Cui --- .../update_device/update_iface_link_state.cfg | 37 ++++++ .../update_device/update_iface_link_state.py | 110 ++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/update_device/update_iface_link_state.cfg create mode 100644 libvirt/tests/src/virtual_network/update_device/update_iface_link_state.py diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_iface_link_state.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_iface_link_state.cfg new file mode 100644 index 00000000000..361d86b2c4d --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/update_device/update_iface_link_state.cfg @@ -0,0 +1,37 @@ +- virtual_network.update_device.iface_link_state: + type = update_iface_link_state + start_vm = no + timeout = 240 + outside_ip = "www.redhat.com" + vm_ping_outside = pass + variants test_scenario: + - add: + updated_link_state = "down" + - delete: + initial_link_state = "down" + updated_link_state = + - update: + initial_link_state = "down" + updated_link_state = "up" + variants model_type: + - virtio: + - e1000e: + only x86_64 + - igb: + only x86_64 + func_supported_since_libvirt_ver = (9, 3, 0) + - rtl8139: + only x86_64 + variants interface_type: + - network: + iface_base_attrs = {"type_name": "network", "source": {"network": "default"}} + - direct: + only virtio + host_iface = + iface_base_attrs = {"type_name": "direct", "source": {"dev": host_iface, "mode": "bridge"}} + - ethernet: + only virtio + create_tap = "yes" + iface_base_attrs = {"type_name": "ethernet", "target": {"dev": tap_name, "managed": "no"}} + + iface_attrs = {"model": "${model_type}", **${iface_base_attrs}} diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_link_state.py b/libvirt/tests/src/virtual_network/update_device/update_iface_link_state.py new file mode 100644 index 00000000000..dfc30f33864 --- /dev/null +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_link_state.py @@ -0,0 +1,110 @@ +from virttest import libvirt_version +from virttest import virsh +from virttest import utils_misc +from virttest import utils_net + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.interface import interface_base +from provider.virtual_network import network_base + +VIRSH_ARGS = {"ignore_status": False, "debug": True} + + +def run(test, params, env): + """ + Test update-device for interface link state + """ + libvirt_version.is_libvirt_feature_supported(params) + + outside_ip = params.get("outside_ip") + host_iface = params.get("host_iface") + host_iface = host_iface if host_iface else utils_net.get_net_if( + state="UP")[0] + rand_id = utils_misc.generate_random_string(3) + bridge_name = "br_" + rand_id + tap_name = "tap_" + rand_id + interface_type = params.get("interface_type") + iface_attrs = eval(params.get("iface_attrs", "{}")) + initial_link_state = params.get("initial_link_state", "") + if initial_link_state: + iface_attrs.update({"link_state": initial_link_state}) + test_states = [("yes", "up"), ("no", "down")] + if initial_link_state == "down": + test_states.reverse() + updated_link_state = params.get("updated_link_state") + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + if interface_type == "ethernet": + utils_net.create_linux_bridge_tmux(bridge_name, host_iface) + network_base.create_tap(tap_name, bridge_name, "root") + + vmxml.del_device('interface', by_tag=True) + libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs) + test.log.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + vm.start() + session = vm.wait_for_serial_login() + vm_iface = interface_base.get_vm_iface(session) + + test.log.info("TEST_STEP: Check the link state in vm.") + iflist = libvirt.get_interface_details(vm_name) + test.log.debug(f'iflist of vm: {iflist}') + iface_info = iflist[0] + iface_mac = iface_info['mac'] + for exp_link_state, exp_domiflik_state in test_states: + if exp_link_state == test_states[-1][0]: + iface = vm_xml.VMXML.new_from_dumpxml( + vm.name).devices.by_device_tag("interface")[0] + if updated_link_state: + iface.setup_attrs(**{"link_state": updated_link_state}) + else: + iface.del_link_state() + test.log.debug(f"iface xml to be updated: {iface}") + test.log.info("TEST_STEP: Update interface device.") + virsh.update_device(vm_name, iface.xml, **VIRSH_ARGS) + + link_info = virsh.domif_getlink( + vm_name, iface_mac, **VIRSH_ARGS).stdout_text + if exp_domiflik_state not in link_info: + test.fail("Failed to get expected interface link state '%s'!" + % exp_domiflik_state) + + if exp_link_state == "yes": + if exp_link_state == test_states[-1][0]: + utils_net.restart_guest_network(session) + ips = {'outside_ip': outside_ip} + network_base.ping_check(params, ips, session, force_ipv4=True) + + output = session.cmd_output("ethtool %s" % vm_iface) + test.log.debug(output) + if "Link detected: %s" % exp_link_state not in output: + test.fail("Failed to get expected link state '%s' in ethtool " + "cmd!" % exp_link_state) + vm_iface = vm_xml.VMXML.new_from_dumpxml(vm.name)\ + .devices.by_device_tag("interface")[0] + + test.log.info("TEST_STEP: Check the live xml for the current link state.") + iface_attrs = vm_iface.fetch_attrs() + test.log.debug(f"iface attrs: {iface_attrs}") + if iface_attrs.get("link_state"): + if iface_attrs.get("link_state") != exp_domiflik_state: + test.fail("Failed to get expected link state '%s' in live xml." + % exp_domiflik_state) + else: + if updated_link_state: + test.fail("There should be no link state in live xml.") + session.close() + + finally: + bkxml.sync() + if interface_type == "ethernet": + network_base.delete_tap(tap_name) + utils_net.delete_linux_bridge_tmux(bridge_name, host_iface) From 7bac60dbbecf00ef3e9f054b4282045ffc602d1d Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Thu, 11 Apr 2024 03:38:16 -0400 Subject: [PATCH 0289/1055] guest numa add aarch64 hugep page adaption Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/numa/guest_numa.cfg | 6 +++--- libvirt/tests/src/numa/guest_numa.py | 20 ++++++++++++++------ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/libvirt/tests/cfg/numa/guest_numa.cfg b/libvirt/tests/cfg/numa/guest_numa.cfg index df09f0e14a0..552ec2fcd29 100644 --- a/libvirt/tests/cfg/numa/guest_numa.cfg +++ b/libvirt/tests/cfg/numa/guest_numa.cfg @@ -40,7 +40,6 @@ variants: - m_strict: memnode_mode_0 = "strict" - kernel_hp_file = "/sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages" - m_preferred: memnode_mode_0 = "preferred" - m_interleave: @@ -61,7 +60,6 @@ - mem_backend: no no_numatune_memnode..numatune_mem - hugepage: - vmpage_size_0 = "2048" vmpage_unit_0 = "KiB" vmpage_nodeset_0 = "0" qemu_cmdline_numa_cell_0 = "node,nodeid=0,cpus=0-1,memdev=ram-node0" @@ -72,6 +70,7 @@ cell_memory_1 = "1048576" variants: - 2M: + vmpage_size_0 = "2048" hugepage_size_0 = "2048" page_num_0 = "512" page_nodenum_0 = "1" @@ -94,7 +93,8 @@ pseries: page_nodenum_0 = "0" - host_total: - nr_pagesize_total = "1024" + vmpage_size_0 = "2048" + hugepage_mem_total = "2097152" - negative_test: status_error = "yes" cell_id_0 = "0" diff --git a/libvirt/tests/src/numa/guest_numa.py b/libvirt/tests/src/numa/guest_numa.py index 8038e8d9ff2..fc591b957d9 100644 --- a/libvirt/tests/src/numa/guest_numa.py +++ b/libvirt/tests/src/numa/guest_numa.py @@ -12,6 +12,7 @@ from virttest import test_setup from virttest import utils_params from virttest import libvirt_version +from virttest.staging import utils_memory # Using as lower capital is not the best way to do, but this is just a @@ -201,9 +202,17 @@ def run(test, params, env): backup_list = [] page_tuple = ('vmpage_size', 'vmpage_unit', 'vmpage_nodeset') page_list = handle_param(page_tuple, params) - nr_pagesize_total = params.get("nr_pagesize_total") + hugepage_mem_total = params.get("hugepage_mem_total") deallocate = False + # Calculate huge page number and change huge page size to + # default huge page size + if hugepage_mem_total and page_list: + default_mem_huge_page_size = utils_memory.get_huge_page_size() + hugepage_num = int(hugepage_mem_total) // default_mem_huge_page_size + for page in page_list: + page['size'] = str(default_mem_huge_page_size) + if page_list: if not libvirt_version.version_compare(1, 2, 5): test.cancel("Setting hugepages more specifically per " @@ -221,7 +230,7 @@ def _update_qemu_conf(): """ Mount hugepage path, update qemu conf then restart libvirtd """ - size_dict = {'2048': '2M', '1048576': '1G', '16384': '16M'} + size_dict = {'2048': '2M', '1048576': '1G', '16384': '16M', '524288': '512M'} for page in page_list: if page['size'] not in supported_hp_size: test.cancel("Hugepage size [%s] isn't supported, " @@ -268,11 +277,10 @@ def _update_qemu_conf(): qemu_conf_restore = True # set hugepage with total number or per-node number - if nr_pagesize_total: - # Only set total 2M size huge page number as total 1G size runtime - # update not supported now. + if hugepage_mem_total and page_list: + # Only set default huge page memory deallocate = True - hp_cl.target_hugepages = int(nr_pagesize_total) + hp_cl.target_hugepages = hugepage_num hp_cl.set_hugepages() if page_list: hp_size = [h_list[p_size]['size'] for p_size in range(len(h_list))] From f1b05e4b4448d36a93570f2418b9e4ae77a46f4a Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Thu, 11 Apr 2024 17:54:11 +0800 Subject: [PATCH 0290/1055] virsh_save: print out error message Signed-off-by: Dan Zheng --- libvirt/tests/src/virsh_cmd/domain/virsh_save.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_save.py b/libvirt/tests/src/virsh_cmd/domain/virsh_save.py index d8d50cc5521..071a865a652 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_save.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_save.py @@ -131,7 +131,7 @@ def create_alter_xml(vm_name): else: if status: test.fail("virsh run failed with a " - "correct command") + "correct command: %s" % err_msg) if progress and not err_msg.count("Save:"): test.fail("No progress information outputted!") if "--xml" in options and 'test.img' not in xml_after_save: From 5fe232fb86a936d68a94566ea757ac6a796bdeac Mon Sep 17 00:00:00 2001 From: Qian Jianhua Date: Fri, 12 Apr 2024 14:20:46 +0800 Subject: [PATCH 0291/1055] guest_kernel_debugging: aarch64 supports panic since libvirt-9.1.0 Signed-off-by: Qian Jianhua --- libvirt/tests/cfg/virsh_cmd/monitor/virsh_domstate.cfg | 8 ++++++++ libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py | 1 + 2 files changed, 9 insertions(+) diff --git a/libvirt/tests/cfg/virsh_cmd/monitor/virsh_domstate.cfg b/libvirt/tests/cfg/virsh_cmd/monitor/virsh_domstate.cfg index 7a4a78a4ffc..5a46a57a8a8 100644 --- a/libvirt/tests/cfg/virsh_cmd/monitor/virsh_domstate.cfg +++ b/libvirt/tests/cfg/virsh_cmd/monitor/virsh_domstate.cfg @@ -42,8 +42,12 @@ variants: - oncrash_destroy: domstate_vm_oncrash = "destroy" + aarch64: + func_supported_since_libvirt_ver = (9, 1, 0) - oncrash_restart: domstate_vm_oncrash = "restart" + aarch64: + func_supported_since_libvirt_ver = (9, 1, 0) - oncrash_preserve: domstate_vm_oncrash = "preserve" variants: @@ -55,10 +59,14 @@ memory_value = "2097152" memory_unit = "KiB" domstate_vm_oncrash = "coredump-destroy" + aarch64: + func_supported_since_libvirt_ver = (9, 1, 0) - oncrash_coredump_restart: memory_value = "2097152" memory_unit = "KiB" domstate_vm_oncrash = "coredump-restart" + aarch64: + func_supported_since_libvirt_ver = (9, 1, 0) - oncrash_rename_restart: domstate_vm_oncrash = "rename-restart" variants: diff --git a/libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py b/libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py index adc0e0dce48..d9e990993c5 100644 --- a/libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py +++ b/libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py @@ -159,6 +159,7 @@ def run(test, params, env): vmxml.sync() if vm_action == "crash": + libvirt_version.is_libvirt_feature_supported(params) if vm.is_alive(): vm.destroy(gracefully=False) vmxml.on_crash = vm_oncrash_action From 93b5cdc66a01543e218b5ffbdde352f3714a4685 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Mon, 8 Apr 2024 17:13:12 +0800 Subject: [PATCH 0292/1055] virtual_network: Add a case of link state This PR adds: VIRT-298009 - Start vm with different interface type with various model type and link state setting Signed-off-by: Yingshun Cui --- .../link_state/link_state_model_type.cfg | 49 ++++++++ .../link_state/link_state_model_type.py | 110 ++++++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/link_state/link_state_model_type.cfg create mode 100644 libvirt/tests/src/virtual_network/link_state/link_state_model_type.py diff --git a/libvirt/tests/cfg/virtual_network/link_state/link_state_model_type.cfg b/libvirt/tests/cfg/virtual_network/link_state/link_state_model_type.cfg new file mode 100644 index 00000000000..2a5e6d1694b --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/link_state/link_state_model_type.cfg @@ -0,0 +1,49 @@ +- virtual_network.link_state.model: + type = link_state_model_type + start_vm = no + timeout = 240 + outside_ip = "www.redhat.com" + vm_ping_outside = pass + variants: + - initial_up: + initial_link_state = "up" + - initial_down: + initial_link_state = "down" + - without_state: + variants model_type: + - virtio: + - e1000e: + only x86_64 + - igb: + only x86_64 + func_supported_since_libvirt_ver = (9, 3, 0) + - rtl8139: + only x86_64 + variants interface_type: + - network: + iface_base_attrs = {"type_name": "network", "source": {"network": "default"}} + - direct: + only virtio + host_iface = + iface_base_attrs = {"type_name": "direct", "source": {"dev": host_iface, "mode": "bridge"}} + - user: + only virtio + variants: + - root: + iface_base_attrs = {"type_name": "user"} + - passt: + host_iface = + iface_base_attrs = {"backend": {"type": "passt"}, "source": {"dev": host_iface}, "type_name": "user"} + variants: + - root: + test_user = "root" + - unprivileged_user: + test_user = USER.EXAMPLE + test_passwd = PASSWORD.EXAMPLE + unpr_vm_name = UNPRIVILEGED_VM.EXAMPLE + - ethernet: + only virtio + create_tap = "yes" + iface_base_attrs = {"type_name": "ethernet", "target": {"dev": tap_name, "managed": "no"}} + + iface_attrs = {"model": "${model_type}", **${iface_base_attrs}} diff --git a/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py b/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py new file mode 100644 index 00000000000..b142451e565 --- /dev/null +++ b/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py @@ -0,0 +1,110 @@ +from virttest import libvirt_version +from virttest import virsh +from virttest import utils_misc +from virttest import utils_net + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_unprivileged +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.interface import interface_base +from provider.virtual_network import network_base + +VIRSH_ARGS = {"ignore_status": False, "debug": True} + + +def run(test, params, env): + """ + Start vm with different interface type with various model type and link + state setting + """ + libvirt_version.is_libvirt_feature_supported(params) + + outside_ip = params.get("outside_ip") + host_iface = params.get("host_iface") + host_iface = host_iface if host_iface else utils_net.get_net_if( + state="UP")[0] + rand_id = utils_misc.generate_random_string(3) + bridge_name = "br_" + rand_id + tap_name = "tap_" + rand_id + interface_type = params.get("interface_type") + iface_attrs = eval(params.get("iface_attrs", "{}")) + initial_link_state = params.get("initial_link_state", "") + if initial_link_state: + iface_attrs.update({"link_state": initial_link_state}) + test_states = [("yes", "up"), ("no", "down")] + if initial_link_state == "down": + test_states.reverse() + + virsh_ins = virsh + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + test_passwd = params.get("test_passwd", "") + test_user = params.get("test_user", "root") + if test_user != "root": + unpr_vm_args = {"username": params.get("username"), + "password": params.get("password")} + vm_name = params.get("unpr_vm_name") + vm = libvirt_unprivileged.get_unprivileged_vm( + vm_name, test_user, test_passwd, **unpr_vm_args) + virsh_ins = virsh.VirshPersistent(uri=vm.connect_uri) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( + vm_name, virsh_instance=virsh_ins) + bkxml = vmxml.copy() + + try: + if interface_type == "ethernet": + utils_net.create_linux_bridge_tmux(bridge_name, host_iface) + network_base.create_tap(tap_name, bridge_name, "root") + + vmxml.del_device('interface', by_tag=True) + libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs, virsh_instance=virsh_ins) + test.log.debug(f'VMXML of {vm_name}:\n{virsh_ins.dumpxml(vm_name).stdout_text}') + vm.start() + session = vm.wait_for_serial_login() + vm_iface = interface_base.get_vm_iface(session) + + test.log.info("TEST_STEP: Check the link state in vm.") + iflist = libvirt.get_interface_details(vm_name, virsh_instance=virsh_ins) + test.log.debug(f'iflist of vm: {iflist}') + iface_info = iflist[0] + iface_mac = iface_info['mac'] + for exp_link_state, exp_domiflik_state in test_states: + if exp_link_state == test_states[-1][0]: + virsh_ins.domif_setlink( + vm_name, iface_mac, exp_domiflik_state, **VIRSH_ARGS) + link_info = virsh_ins.domif_getlink( + vm_name, iface_mac, **VIRSH_ARGS).stdout_text + if exp_domiflik_state not in link_info: + test.fail("Failed to get expected interface link state '%s'!" + % exp_domiflik_state) + + output = session.cmd_output("ethtool %s" % vm_iface) + test.log.debug(output) + if "Link detected: %s" % exp_link_state not in output: + test.fail("Failed to get expected link state '%s' in ethtool " + "cmd!" % exp_link_state) + + if exp_link_state == "yes": + if exp_link_state == test_states[-1][0]: + utils_net.restart_guest_network(session) + ips = {'outside_ip': outside_ip} + network_base.ping_check(params, ips, session, force_ipv4=True) + vm_iface = vm_xml.VMXML.new_from_dumpxml(vm.name, + virsh_instance=virsh_ins)\ + .devices.by_device_tag("interface")[0] + + test.log.info("TEST_STEP: Check the live xml for the current link state.") + iface_attrs = vm_iface.fetch_attrs() + test.log.debug(f"iface attrs: {iface_attrs}") + if iface_attrs.get("link_state") != exp_domiflik_state: + test.fail("Failed to get expected link state '%s'." % exp_domiflik_state) + session.close() + + finally: + bkxml.sync() + if interface_type == "ethernet": + network_base.delete_tap(tap_name) + utils_net.delete_linux_bridge_tmux(bridge_name, host_iface) From 251ca966c668d193b6e675e1deb7e12e596d5105 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Fri, 12 Apr 2024 07:37:03 -0400 Subject: [PATCH 0293/1055] virtio_page_per_vq: select input device on type The tests statically selected the input element of various by its expected list index. This failed if the domain xml was different. Select now the input element by its type and the expected driver subelement to avoid relying on order which is not defined by the XML schema here. Finally, print more info to log for easier debugging. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/virtio/virtio_page_per_vq.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/src/virtio/virtio_page_per_vq.py b/libvirt/tests/src/virtio/virtio_page_per_vq.py index e5eb536b178..bb47458b88f 100644 --- a/libvirt/tests/src/virtio/virtio_page_per_vq.py +++ b/libvirt/tests/src/virtio/virtio_page_per_vq.py @@ -100,10 +100,15 @@ def check_attribute(): Check the page_per_vq attribute after starting the guest """ af_vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) - test.log.info("The current dumpxml is %s", virsh.dumpxml(af_vmxml)) + test.log.info("The current dumpxml is %s", af_vmxml) # Keyboard and mouse input will be default in guest. So identify input device. if device_type == "input": - dev_xml = af_vmxml.get_devices(device_type)[2] + input_element = [x for x in af_vmxml.get_devices(device_type) + if x['input_type'] == input_type + and 'driver' in x.fetch_attrs()] + if not input_element: + test.fail("The expected input device was not found.") + dev_xml = input_element[0] # Guest has many controllers, so also need to identify it. elif device_type == "controller": dev_xml = af_vmxml.get_devices(device_type) @@ -115,9 +120,13 @@ def check_attribute(): if device_type == "controller": for controller in dev_xml: if controller.type == controller_type: - cur_dict = controller.fetch_attrs()["driver"] + controller_attrs = controller.fetch_attrs() + test.log.debug("controller attrs: %s", controller_attrs) + cur_dict = controller_attrs["driver"] else: - cur_dict = dev_xml.fetch_attrs()["driver"] + dev_attrs = dev_xml.fetch_attrs() + test.log.debug("dev attrs: %s", dev_attrs) + cur_dict = dev_attrs["driver"] pre_dict = driver_dict["driver"] for key, value in pre_dict.items(): if cur_dict.get(key) != value: From b3a478eab2a4db0c85fefdc66d38cf6cf82eedc7 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Sun, 14 Apr 2024 12:38:41 +0800 Subject: [PATCH 0294/1055] virtual_disks: Add 2 cases of vhostvdpa_block This pr adds: VIRT-300428 - Define&Start vm with disk of vhostvdpa backend VIRT-300445 - Define/start vm with disk of vhostvdpa backend - invalid configuration Signed-off-by: Yingshun Cui --- ...e_start_vm_with_vhostvdpa_backend_disk.cfg | 26 +++++++ ...ne_start_vm_with_vhostvdpa_backend_disk.py | 75 +++++++++++++++++++ spell.ignore | 1 + 3 files changed, 102 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_vhostvdpa_backend_disk.cfg create mode 100644 libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_vhostvdpa_backend_disk.py diff --git a/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_vhostvdpa_backend_disk.cfg b/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_vhostvdpa_backend_disk.cfg new file mode 100644 index 00000000000..489ebf9835e --- /dev/null +++ b/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_vhostvdpa_backend_disk.cfg @@ -0,0 +1,26 @@ +- virtual_disk.vhostvdpa.define_start: + type = define_start_vm_with_vhostvdpa_backend_disk + start_vm = no + simulator = "yes" + driver_type = "raw" + disk_vdpa_attrs = {"source": {"attrs": {"dev": "/dev/vhost-vdpa-0"}}, "type_name": "vhostvdpa"} + func_supported_since_libvirt_ver = (9, 10, 0) + only x86_64 + variants cache_mode: + - none: + - directsync: + - no_specified_value: + define_error = "yes" + variants: + - default: + - without_shared_memory: + only none + without_shared_memory = "yes" + define_error = "yes" + - qcow2_dirver: + only none + driver_type = "qcow2" + start_error = "yes" + + disk_driver = {"driver": {"name": "qemu", "type": "${driver_type}", "cache": "${cache_mode}", "io": "threads", "copy_on_read": "on", "discard": "unmap", "detect_zeroes": "on"}} + disk_attrs = {"device": "disk", "target": {"dev": "vdb", "bus": "virtio"}, **${disk_vdpa_attrs}, **${disk_driver}} diff --git a/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_vhostvdpa_backend_disk.py b/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_vhostvdpa_backend_disk.py new file mode 100644 index 00000000000..f4cd20b5cb3 --- /dev/null +++ b/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_vhostvdpa_backend_disk.py @@ -0,0 +1,75 @@ +from virttest import libvirt_version +from virttest import utils_vdpa +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_disk +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +VIRSH_ARGS = {'debug': True, 'ignore_status': False} + + +def run(test, params, env): + """ + Verify that vm can be defined and started with vhost-vdpa backend disk, + and disk I/O in guest can work + """ + libvirt_version.is_libvirt_feature_supported(params) + disk_attrs = eval(params.get("disk_attrs", "{}")) + without_shared_memory = "yes" == params.get("without_shared_memory", "no") + define_error = "yes" == params.get("define_error", "no") + start_error = "yes" == params.get("start_error", "no") + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + test.log.info("TEST_STEP: Define a VM with vhostvdpa disk.") + test_env_obj = utils_vdpa.VDPASimulatorTest(sim_dev_module="vdpa_sim_blk", mgmtdev="vdpasim_blk") + test_env_obj.setup() + if not without_shared_memory: + vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", hpgs=False) + disk_dev = libvirt_vmxml.create_vm_device_by_type("disk", disk_attrs) + vmxml_new = vm_xml.VMXML.new_from_dumpxml(vm_name) + vmxml_new.add_device(disk_dev) + + test.log.debug(f'VMXML of {vm_name}:\n{vmxml_new}') + cmd_result = virsh.define(vmxml_new.xml, debug=True) + libvirt.check_exit_status(cmd_result, define_error) + if define_error: + return + + test.log.info("TEST_STEP: Start the VM.") + cmd_result = virsh.start(vm_name) + libvirt.check_exit_status(cmd_result, start_error) + if start_error: + return + vm_session = vm.wait_for_login() + + test.log.info("TEST_STEP: Check VM's xml.") + vdpa_device = vm_xml.VMXML.new_from_dumpxml(vm.name)\ + .devices.by_device_tag("disk")[-1] + vdpa_dev_attrs = vdpa_device.fetch_attrs() + test.log.debug(vdpa_dev_attrs) + for k, v in disk_attrs.items(): + if k == "source": + act_dev = vdpa_dev_attrs[k]["attrs"].get("dev") + exp_dev = v["attrs"]["dev"] + test.log.debug(f"Actual dev: {act_dev}") + test.log.debug(f"Expected dev: {exp_dev}") + if act_dev != exp_dev: + test.fail("Incorrect disk dev!") + elif vdpa_dev_attrs[k] != v: + test.fail("Failed to get expected disk attributes(%s) in live xml!" + "It should be %s." % (vdpa_dev_attrs[k], v)) + + test.log.info("TEST_STEP: Check r/w operations on vhostvdpa disk.") + new_disk = libvirt_disk.get_non_root_disk_name(vm_session)[0] + if not libvirt_disk.check_virtual_disk_io(vm, new_disk): + test.fail("Failed to check disk io for %s!" % new_disk) + + finally: + bkxml.sync() + test_env_obj.cleanup() diff --git a/spell.ignore b/spell.ignore index b97ffbb03c2..38dba6e342d 100644 --- a/spell.ignore +++ b/spell.ignore @@ -1118,6 +1118,7 @@ vdb vdb's vdc vddk +vdpa vdsm vdx vepa From 02f530c3522d5c7d965dc2ef9ac8252da12a6072 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Mon, 15 Apr 2024 23:58:02 -0400 Subject: [PATCH 0295/1055] Fixup:trustGuestRxFilters:Add version check and xml check - Add version check - Add xml check after update-device Signed-off-by: Haijiao Zhao --- .../update_device/update_iface_trustGuestRxFilters.cfg | 1 + .../update_device/update_iface_trustGuestRxFilters.py | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_iface_trustGuestRxFilters.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_iface_trustGuestRxFilters.cfg index 9ac73138f41..9716f98a9b1 100644 --- a/libvirt/tests/cfg/virtual_network/update_device/update_iface_trustGuestRxFilters.cfg +++ b/libvirt/tests/cfg/virtual_network/update_device/update_iface_trustGuestRxFilters.cfg @@ -4,6 +4,7 @@ timeout = 240 host_iface = outside_ip = 'www.redhat.com' + func_supported_since_libvirt_ver = (10, 0, 0) variants: - yes_to_no: trustGRF = 'yes' diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py b/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py index c41eab8da90..8bb32c61403 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py @@ -1,6 +1,7 @@ import logging from avocado.utils import process +from virttest import libvirt_version from virttest import utils_net from virttest import virsh from virttest.libvirt_xml import vm_xml @@ -18,6 +19,7 @@ def run(test, params, env): """ Test live update trustGuestRxFilters for direct type interface """ + libvirt_version.is_libvirt_feature_supported(params) vm_name = params.get('main_vm') vm = env.get_vm(vm_name) host_iface = params.get('host_iface') @@ -48,6 +50,10 @@ def run(test, params, env): iface_update = network_base.get_iface_xml_inst(vm_name, 'after update') LOG.debug(f'iface trustGuestRxFilters after update: ' f'{iface_update.trustGuestRxFilters}') + if iface_update.trustGuestRxFilters != update_attrs[ + 'trustGuestRxFilters']: + test.fail(f'Interface trustGuestRxFilters not successfully updated ' + f'to {update_attrs["trustGuestRxFilters"]}') mac_host = utils_net.get_linux_iface_info(iface=target_dev)['address'] From 68c20d02c4c395e5170703aa6322c96dc560075b Mon Sep 17 00:00:00 2001 From: nanli Date: Thu, 28 Mar 2024 15:31:00 +0800 Subject: [PATCH 0296/1055] add case for delete snap in parent external snap with muti children xxxx-300472:Delete snapshots in the parent external snapshots with multiple children. Signed-off-by: nanli --- .../delete_external_snap_with_references.cfg | 21 ++++ .../delete_external_snap_with_references.py | 111 ++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 libvirt/tests/cfg/snapshot/delete_external_snap_with_references.cfg create mode 100644 libvirt/tests/src/snapshot/delete_external_snap_with_references.py diff --git a/libvirt/tests/cfg/snapshot/delete_external_snap_with_references.cfg b/libvirt/tests/cfg/snapshot/delete_external_snap_with_references.cfg new file mode 100644 index 00000000000..50314b30582 --- /dev/null +++ b/libvirt/tests/cfg/snapshot/delete_external_snap_with_references.cfg @@ -0,0 +1,21 @@ +- snapshot_delete.multiple_children: + type = delete_external_snap_with_references + start_vm = no + snap_options = "%s --memspec snapshot=external,file=/tmp/mem.%s --diskspec vda,snapshot=external,file=/tmp/vda.%s" + func_supported_since_libvirt_ver = (9, 10, 0) + variants case: + - del_parent_snap: + del_snap = 's1' + error_msg = "unsupported configuration: deletion of external disk snapshot with multiple children snapshots not supported" + - del_current_branch: + del_index = [2, 1, 0] + error_msg = "unsupported configuration: deletion of active external snapshot that is not a leaf snapshot is not supported" + - del_non_current_branch: + func_supported_since_libvirt_ver = (10, 0, 0) + error_msg = "deletion of non-leaf external snapshot that is not in active chain is not supported" + variants: + - tail_to_head: + del_index = [4, 3, 0] +# - head_to_tail: +# del_index = [0, 3, 4] + diff --git a/libvirt/tests/src/snapshot/delete_external_snap_with_references.py b/libvirt/tests/src/snapshot/delete_external_snap_with_references.py new file mode 100644 index 00000000000..28ab3ce50a5 --- /dev/null +++ b/libvirt/tests/src/snapshot/delete_external_snap_with_references.py @@ -0,0 +1,111 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +from virttest import libvirt_version +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt + +from provider.snapshot import snapshot_base + + +def run(test, params, env): + """ + :params test: test object + :params params: wrapped dict with all parameters + :params env: test object + """ + def setup_test(): + """ + Delete snapshots in the parent external snapshots + with multiple children. + """ + test.log.info("TEST_SETUP: Prepare the parent external snapshot" + " with multiple children") + virsh.start(vm_name) + vm.wait_for_login().close() + for sname in snap_names: + virsh.snapshot_create_as(vm.name, snap_options % (sname, sname, sname), + **virsh_dargs) + if sname == 's3': + virsh.snapshot_revert(vm_name, snap_names[0], **virsh_dargs) + res = virsh.snapshot_current(vm_name, **virsh_dargs).stdout.strip() + if res != snap_names[-1]: + test.fail("Expect the current snap name is '%s' instead of" + " '%s'" % (snap_names[-1], res)) + virsh.snapshot_list(vm_name, **virsh_dargs, options='--tree') + + def run_test_del_parent_snap(): + """ + Delete the parent snapshot with multiple children. + """ + test.log.info("TEST_STEP:Delete the parent snapshot with multi-child.") + virsh.start(vm_name) + vm.wait_for_login().close() + del_res = virsh.snapshot_delete(vm.name, snap_names[0], debug=True) + libvirt.check_exit_status(del_res, error_msg) + + def run_test_del_current_branch(): + """ + Delete the snapshots of current branch. + """ + test.log.info("TEST_STEP: Delete the snapshots of current branch.") + for times in range(1, 4): + curr_sname = virsh.snapshot_current(vm_name, **virsh_dargs).stdout.strip() + del_res = virsh.snapshot_delete(vm_name, curr_sname, debug=True) + if times == 3: + libvirt.check_exit_status(del_res, error_msg) + for index in del_index: + res = virsh.snapshot_delete(vm_name, snap_names[index], **virsh_dargs) + libvirt.check_exit_status(res) + + def run_test_del_non_current_branch(): + """ + Delete the snapshots of non-current branch + """ + test.log.info("TEST_STEP: Delete the snapshots of non-current branch.") + res = virsh.snapshot_delete(vm_name, snap_names[1], debug=True) + libvirt.check_exit_status(res, error_msg) + + for index in [2, 1] + del_index: + res = virsh.snapshot_delete(vm_name, snap_names[index], **virsh_dargs) + libvirt.check_exit_status(res) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + snap_names.reverse() + test_obj.virsh_dargs = {'ignore_status': True, 'debug': True} + test_obj.delete_snapshot(snap_names) + bkxml.sync() + + vm_name = params.get("main_vm") + original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = original_xml.copy() + vm = env.get_vm(vm_name) + + snap_options = params.get("snap_options") + case = params.get("case") + run_test = eval("run_test_%s" % case) + error_msg = params.get("error_msg") + + test_obj = snapshot_base.SnapshotTest(vm, test, params) + virsh_dargs = {"debug": True, "ignore_status": False} + snap_names = ['s1', 's2', 's3', 's4', 's5'] + del_index = eval(params.get('del_index', '[]')) + libvirt_version.is_libvirt_feature_supported(params) + + try: + setup_test() + run_test() + + finally: + teardown_test() From f9a32d57914c5812d41b1e370217edd1f295091e Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Mon, 8 Apr 2024 21:39:21 -0400 Subject: [PATCH 0297/1055] Add network case of update-device - VIRT-298320 - [update-device] update an interface by update-device match by mac address, and alias & pci address together Signed-off-by: Haijiao Zhao --- .../update_iface_with_identifier.cfg | 40 ++++++ .../update_iface_with_identifier.py | 114 ++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/update_device/update_iface_with_identifier.cfg create mode 100644 libvirt/tests/src/virtual_network/update_device/update_iface_with_identifier.py diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_identifier.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_identifier.cfg new file mode 100644 index 00000000000..157befdc4a1 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_identifier.cfg @@ -0,0 +1,40 @@ +- virtual_network.update_device.iface_with_identifier: + type = update_iface_with_identifier + start_vm = no + timeout = 240 + iface_a_attrs = {'source': {'network': 'default'}, 'model': 'virtio', 'type_name': 'network', 'alias': {'name': alias_a}} + iface_b_attrs = {'source': {'network': 'default'}, 'model': 'virtio', 'type_name': 'network', 'alias': {'name': alias_b}} + update_attrs = {'link_state': 'down'} + err_msg_matching = device not found: no device found at address .* matching MAC address .* and alias .* + variants scenario: + - mac_only: + del_tags = ['alias', 'address'] + status_error = no + - alias_only: + del_tags = ['address', 'mac'] + status_error = no + update: + status_error = yes + err_msg = cannot change network interface mac address from .* to .* + - pci_address_only: + del_tags = ['alias', 'mac'] + status_error = no + update: + status_error = yes + err_msg = cannot change network interface mac address from .* to .* + - right_mac_alias_wrong_pci: + status_error = yes + err_msg = ${err_msg_matching} + update_attrs = {'link_state': 'down'} + update_pci = yes + - right_mac_pci_wrong_alias: + status_error = yes + err_msg = ${err_msg_matching} + update_attrs = {'link_state': 'down', 'alias': {'name': rand_alias}} + - wrong_mac_right_alias_pci: + status_error = yes + err_msg = ${err_msg_matching} + update_attrs = {'link_state': 'down', 'mac_address': rand_mac} + variants operation: + - update: + - hotunplug: diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_with_identifier.py b/libvirt/tests/src/virtual_network/update_device/update_iface_with_identifier.py new file mode 100644 index 00000000000..ebaf060cb58 --- /dev/null +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_with_identifier.py @@ -0,0 +1,114 @@ +import logging + +from virttest import utils_misc +from virttest import utils_net +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def check_cmd_result(cmd_result, status_error, err_msg=None): + """ + Check command result including exit status and error message + + :param cmd_result: command result instance + :param status_error: expect error of command + :param err_msg: error message of command, defaults to None + """ + libvirt.check_exit_status(cmd_result, status_error) + if err_msg: + libvirt.check_result(cmd_result, err_msg) + + +def run(test, params, env): + """ + Verify updating interface can identify by each of the mac/alias/PCI address, + and also by them together. + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + status_error = 'yes' == params.get('status_error', 'no') + err_msg = params.get('err_msg') + alias_a = 'ua-' + utils_misc.generate_random_string(6) + alias_b = 'ua-' + utils_misc.generate_random_string(6) + rand_mac = utils_net.generate_mac_address_simple() + rand_alias = 'randa-' + utils_misc.generate_random_string(6) + iface_a_attrs = eval(params.get('iface_a_attrs', '{}')) + iface_b_attrs = eval(params.get('iface_b_attrs', '{}')) + update_attrs = eval(params.get('update_attrs', '{}')) + update_pci = 'yes' == params.get('update_pci', 'no') + del_tags = eval(params.get('del_tags', '[]')) + operation = params.get('operation') + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + vmxml.del_device('interface', by_tag=True) + for attrs in (iface_a_attrs, iface_b_attrs): + iface_x = libvirt_vmxml.create_vm_device_by_type( + 'interface', attrs) + libvirt.add_vm_device(vmxml, iface_x) + LOG.debug(f'VMXMLof {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + vm.start() + + # Get target iface + iface = network_base.get_iface_xml_inst(vm_name, '1st on vm') + mac = iface.mac_address + + LOG.debug(f'Update iface with attrs: {update_attrs}') + iface.setup_attrs(**update_attrs) + + if update_pci: + LOG.debug('Update iface xml pci address') + pci_addr_attrs = iface.address['attrs'] + pci_addr_attrs['slot'] = str(hex(int(pci_addr_attrs['slot'], + 16) + 3)) + iface.setup_attrs(address={'attrs': pci_addr_attrs}) + LOG.debug(f'Update iface pci address to: {iface.address}') + + for tag in del_tags: + LOG.debug(f'Remove <{tag}> from iface xml.') + iface.xmltreefile.remove_by_xpath(tag) + iface.xmltreefile.write() + LOG.debug(f'Update iface with xml:\n{iface}') + + if operation == 'update': + up_result = virsh.update_device(vm_name, iface.xml, debug=True) + check_cmd_result(up_result, status_error, err_msg) + if status_error: + return + iface_update = network_base.get_iface_xml_inst(vm_name, + 'after update') + if iface_update.link_state == update_attrs['link_state']: + LOG.info('link_state of interface after update check PASS') + else: + test.fail(f'Interface link_state after update should be ' + f'{update_attrs["link_state"]}') + + elif operation == 'hotunplug': + dt_result = virsh.detach_device(vm_name, iface.xml, + wait_for_event=True, + event_timeout=20, + debug=True) + check_cmd_result(dt_result, status_error, err_msg) + if status_error: + return + iflist = virsh.domiflist(vm_name, debug=True).stdout_text + if mac not in iflist: + LOG.info('Interface successfully detached:checked by domiflist') + else: + test.fail(f'Interface with mac {mac} not detached') + else: + test.error(f'Unknown operation: {operation}') + + finally: + bkxml.sync() From 029c06efbc0e15def5cb805a9e633360f3596dd0 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Wed, 17 Apr 2024 22:01:34 -0400 Subject: [PATCH 0298/1055] Adaption for rhel8 aarch64 Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/event/virsh_event.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/event/virsh_event.cfg b/libvirt/tests/cfg/event/virsh_event.cfg index 3cd6b3c73a0..d41c7d63e42 100644 --- a/libvirt/tests/cfg/event/virsh_event.cfg +++ b/libvirt/tests/cfg/event/virsh_event.cfg @@ -123,7 +123,7 @@ cpu_mode = 'host-model' aarch64: cpu_mode = 'host-passthrough' - dimm_size = 512 + dimm_size = 1024 expected_fails = "unplug of device was rejected by the guest" - watchdog_event: event_all_option = "yes" From 8119f2157d77764f5e68448917340bed989e68f5 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Thu, 18 Apr 2024 03:22:38 -0400 Subject: [PATCH 0299/1055] virtual_disk: fix snapshot issue for ovmf guest There are two problems in virtual_disks_multidisks.py script: 1) The os xml will change to seabios guest when we testing ovmf guest because of incorrectos xml configuration 2) Internal snapshot is not supportted in ovmf guest. Fix the above problems by adding os_firmware attribute and skip internal snapshot test for ovmf guest. Signed-off-by: Meina Li --- .../tests/src/virtual_disks/virtual_disks_multidisks.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_multidisks.py b/libvirt/tests/src/virtual_disks/virtual_disks_multidisks.py index 3d05aea49f9..1a1849ef3ee 100644 --- a/libvirt/tests/src/virtual_disks/virtual_disks_multidisks.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_multidisks.py @@ -518,8 +518,10 @@ def check_bootorder_snapshot(disk_name): snapshot1 = "s1" snapshot2 = "s2" snapshot2_file = os.path.join(data_dir.get_data_dir(), "s2") - ret = virsh.snapshot_create(vm_name, "", **virsh_dargs) - libvirt.check_exit_status(ret) + # Skip internal snapshot for ovmf guest + if "os_firmware" not in vmxml.os.fetch_attrs(): + ret = virsh.snapshot_create(vm_name, "", **virsh_dargs) + libvirt.check_exit_status(ret) ret = virsh.snapshot_create_as(vm_name, "%s --disk-only" % snapshot1, **virsh_dargs) @@ -1364,6 +1366,8 @@ def add_backingstore_element_to_disk_xml(disk_xml): osxml.type = vmxml.os.type osxml.arch = vmxml.os.arch osxml.machine = vmxml.os.machine + if vmxml.os.fetch_attrs().get("os_firmware") == "efi": + osxml.os_firmware = vmxml.os.os_firmware if test_boot_console: osxml.loader = "/usr/share/seabios/bios.bin" osxml.bios_useserial = "yes" From 7d2bda1ee1000d400ba493e2ab0e3832a127c5f2 Mon Sep 17 00:00:00 2001 From: lcheng Date: Thu, 25 Jan 2024 16:41:36 +0800 Subject: [PATCH 0300/1055] migration: Add case to test auto-skipped disks XXXX-296262 - VM live migration with copy storage - auto-skipped disks Signed-off-by: lcheng --- .../autoskipped_disks.cfg | 77 ++++++++++++ .../autoskipped_disks.py | 117 ++++++++++++++++++ 2 files changed, 194 insertions(+) create mode 100644 libvirt/tests/cfg/migration_with_copy_storage/autoskipped_disks.cfg create mode 100644 libvirt/tests/src/migration_with_copy_storage/autoskipped_disks.py diff --git a/libvirt/tests/cfg/migration_with_copy_storage/autoskipped_disks.cfg b/libvirt/tests/cfg/migration_with_copy_storage/autoskipped_disks.cfg new file mode 100644 index 00000000000..2acba347c5e --- /dev/null +++ b/libvirt/tests/cfg/migration_with_copy_storage/autoskipped_disks.cfg @@ -0,0 +1,77 @@ +- migration_with_copy_storage.autoskipped_disks: + type = autoskipped_disks + migration_setup = 'yes' + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = "" + # SSH connection time out + ssh_timeout = 60 + start_vm = "no" + # Local URI + virsh_migrate_connect_uri = qemu:///system" + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = "no" + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + simple_disk_check_after_mig = "yes" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + status_error = "no" + variants: + - p2p: + virsh_migrate_options = "--live --p2p --verbose" + - non_p2p: + virsh_migrate_options = "--live --verbose" + variants: + - local_storage: + setup_nfs = "no" + nfs_mount_dir = + setup_local_nfs = "no" + storage_type = "" + - shared_storage: + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + variants: + - copy_storage_all: + virsh_migrate_extra = "--copy-storage-all" + - copy_storage_inc: + virsh_migrate_extra = "--copy-storage-inc" + variants test_case: + - disk_with_shareable: + second_disk_dict = {"device": "disk", "type_name": "file", "driver": {"name": "qemu", "type": "raw", "cache": "none"}, "target": {"dev": "vdb", "bus": "virtio"}, "share": True} + second_disk_name = "shareable.raw" + local_storage: + status_error = "yes" + err_msg = "Unsafe migration: Migration without shared storage is unsafe" + - disk_with_readonly: + second_disk_dict = {"device": "disk", "type_name": "file", "driver": {"name": "qemu", "type": "raw"}, "target": {"dev": "vdb", "bus": "virtio"}, "readonly": True} + second_disk_name = "readonly.raw" + local_storage: + status_error = "yes" + err_msg = "Path .* is not accessible: No such file or directory" + - cdrom_with_empty_source: + second_disk_dict = {"device": "cdrom", "type_name": "file", "driver": {"name": "qemu"}, "target": {"dev": "sda", "bus": "sata"}, "readonly": True} + - cdrom_with_startuppolicy: + second_disk_name = "cdrom.iso" + variants: + - optional: + startup_policy = {"startupPolicy": "optional"} + - requisite: + startup_policy = {"startupPolicy": "requisite"} + - mandatory: + startup_policy = {"startupPolicy": "mandatory"} + local_storage: + status_error = "yes" + err_msg = "Cannot access storage file.*: No such file or directory" + second_disk_dict = {"device": "cdrom", "type_name": "file", "driver": {"name": "qemu", "type": "raw"}, "target": {"dev": "sda", "bus": "sata"}, "source": {"attrs": ${startup_policy}}, "readonly": True} diff --git a/libvirt/tests/src/migration_with_copy_storage/autoskipped_disks.py b/libvirt/tests/src/migration_with_copy_storage/autoskipped_disks.py new file mode 100644 index 00000000000..699e2af16b9 --- /dev/null +++ b/libvirt/tests/src/migration_with_copy_storage/autoskipped_disks.py @@ -0,0 +1,117 @@ +import os + +from avocado.utils import process + +from virttest import data_dir +from virttest import remote +from virttest import utils_misc + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_disk +from virttest.utils_libvirt import libvirt_vmxml + +from provider.migration import base_steps +from provider.migration import migration_base + + +def run(test, params, env): + """ + To verify that libvirt will skip specific disks when do vm live migration + with copy storage. This case starts vm with specific disks, then do vm live + migration with copy storage; migration may fail or succeed according to the + disk configuration. + + """ + def setup_common(): + """ + Common setup step. + + """ + migrate_desturi_port = params.get("migrate_desturi_port") + migrate_desturi_type = params.get("migrate_desturi_type", "tcp") + + test.log.info("Common setup step.") + migration_obj.conn_list.append(migration_base.setup_conn_obj(migrate_desturi_type, params, test)) + migration_obj.remote_add_or_remove_port(migrate_desturi_port) + + first_image_path = os.path.join(data_dir.get_data_dir(), 'images') + first_disk_dict = {'source': {'attrs': {'file': os.path.join(first_image_path, + os.path.basename(vm.get_first_disk_devices()['source']))}}} + + libvirt_vmxml.modify_vm_device( + vm_xml.VMXML.new_from_inactive_dumpxml(vm_name), + 'disk', first_disk_dict) + + def setup_test(): + """ + Setup step. + + """ + second_disk_dict = eval(params.get("second_disk_dict")) + nfs_mount_dir = params.get("nfs_mount_dir") + second_disk_name = params.get("second_disk_name") + + test.log.info("Setup step.") + source_file = vm.get_first_disk_devices()['source'] + if test_case in ["disk_with_shareable", "disk_with_readonly", "cdrom_with_startuppolicy"]: + if nfs_mount_dir: + second_disk_img = os.path.join(nfs_mount_dir, second_disk_name) + else: + second_disk_img = os.path.join(os.path.dirname(source_file), second_disk_name) + if os.path.exists(second_disk_img): + os.remove(second_disk_img) + if test_case in ["disk_with_shareable", "disk_with_readonly"]: + libvirt_disk.create_disk("file", disk_format="raw", path=second_disk_img) + second_disk_dict.update({"source": {"attrs": {"file": "%s" % second_disk_img}}}) + else: + startup_policy = eval(params.get("startup_policy")) + if nfs_mount_dir: + cdrom_iso = nfs_mount_dir + "/test.iso" + else: + cdrom_iso = os.path.dirname(source_file) + "/test.iso" + process.run("dd if=/dev/urandom of=%s bs=1M count=10" % cdrom_iso, shell=True) + process.run("mkisofs -o %s %s" % (second_disk_img, cdrom_iso), shell=True) + startup_policy.update({"file": "%s" % second_disk_img}) + second_disk_dict.update({"source": {"attrs": startup_policy}}) + + if test_case == "disk_with_shareable": + base_steps.prepare_disks_remote(params, vm) + else: + server_ip = params.get("server_ip") + server_user = params.get("server_user") + server_pwd = params.get("server_pwd") + + remote_session = remote.remote_login("ssh", server_ip, "22", + server_user, server_pwd, + r'[$#%]') + + image_info = utils_misc.get_image_info(source_file) + disk_size = image_info.get("vsize") + disk_format = image_info.get("format") + utils_misc.make_dirs(os.path.dirname(source_file), remote_session) + libvirt_disk.create_disk("file", path=source_file, + size=disk_size, disk_format=disk_format, + session=remote_session) + remote_session.close() + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vmxml.add_device(libvirt_vmxml.create_vm_device_by_type("disk", second_disk_dict)) + vmxml.sync() + + vm.start() + vm.wait_for_login().close() + + vm_name = params.get("migrate_main_vm") + test_case = params.get("test_case") + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + setup_common() + setup_test() + migration_obj.run_migration() + migration_obj.verify_default() + finally: + base_steps.cleanup_disks_remote(params, vm) + migration_obj.cleanup_connection() From 8630b193bab6bb39afc92d9a803d5aac836ce9f4 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 19 Apr 2024 19:43:21 +0800 Subject: [PATCH 0301/1055] Fixup the name typo Signed-off-by: Yingshun Cui --- .../define_start_vm_with_vhostvdpa_backend_disk.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_vhostvdpa_backend_disk.cfg b/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_vhostvdpa_backend_disk.cfg index 489ebf9835e..fd298ec8798 100644 --- a/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_vhostvdpa_backend_disk.cfg +++ b/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_vhostvdpa_backend_disk.cfg @@ -1,4 +1,4 @@ -- virtual_disk.vhostvdpa.define_start: +- virtual_disks.vhostvdpa.define_start: type = define_start_vm_with_vhostvdpa_backend_disk start_vm = no simulator = "yes" From 17912b132f239ff327d40d3dbaf8e54f4a92d4d0 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 23 Apr 2024 14:27:37 +0800 Subject: [PATCH 0302/1055] virtual_network: Extend event_timeout for arm Waiting for device-removed event takes more time than x86. Signed-off-by: Yingshun Cui --- .../attach_detach_interface/attach_interface_with_model.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.py b/libvirt/tests/src/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.py index 8d7092c7785..72f574cd1fc 100644 --- a/libvirt/tests/src/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.py +++ b/libvirt/tests/src/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.py @@ -107,7 +107,9 @@ def run(test, params, env): check_model_controller(vm_name, pci_model, test) virsh.detach_device_alias(vm_name, alias_name, - wait_for_event=True, **VIRSH_ARGS) + wait_for_event=True, + event_timeout=20, + **VIRSH_ARGS) iflist = libvirt.get_interface_details(vm_name) test.log.debug(f"iflist of vm: {iflist}") if iflist: From 23929a16852be0d31aa7357ca1950810a606c21b Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Wed, 24 Apr 2024 19:04:58 +0800 Subject: [PATCH 0303/1055] v2v: add guests for rhel9.5/10 Signed-off-by: vwu-vera --- v2v/tests/cfg/convert_vm_to_libvirt.cfg | 15 +++++++++------ v2v/tests/cfg/convert_vm_to_ovirt.cfg | 13 ++++++++----- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/v2v/tests/cfg/convert_vm_to_libvirt.cfg b/v2v/tests/cfg/convert_vm_to_libvirt.cfg index e61d6dff340..f39888c8c43 100644 --- a/v2v/tests/cfg/convert_vm_to_libvirt.cfg +++ b/v2v/tests/cfg/convert_vm_to_libvirt.cfg @@ -38,27 +38,27 @@ - boot_uefi: vm_boot = "-efi" boottype = 3 - only 8_0.linux.latest9_dev, 8_0.linux.latest8_dev, 8_0.linux.latest9, 8_0.linux.latest8, 8_0.linux.8_7, 8_0.linux.8_6, 8_0.linux.ubuntu_lts, 8_0.linux.sles_latest, 8_0.windows.win2022, 8_0.windows.win11, 8_0.windows.win2016 + only 8_0.linux.latest10_dev, 8_0.linux.latest9_dev, 8_0.linux.latest9, 8_0.linux.latest8, 8_0.linux.8_8, 8_0.linux.8_6, 8_0.linux.ubuntu_lts, 8_0.linux.sles_latest, 8_0.windows.win2022, 8_0.windows.win11, 8_0.windows.win2016, 8_0.windows.win2025 variants: - linux: os_type = "linux" vm_user = ${username} vm_pwd = ${password} variants: + - latest10_dev: + os_short_id = "RHEL9_DEV_SHORT_ID" + os_version = "LATEST_DEV_10" - latest9_dev: os_short_id = "RHEL9_DEV_SHORT_ID" os_version = "LATEST_DEV_9" - - latest8_dev: - os_short_id = "RHEL8_DEV_SHORT_ID" - os_version = "LATEST_DEV_8" - latest9: os_short_id = "RHEL9_SHORT_ID" os_version = "LATEST9" - latest8: os_short_id = "RHEL8_SHORT_ID" os_version = "LATEST8" - - 8_7: - os_version = "rhel8.7" + - 8_8: + os_version = "rhel8.8" - 8_6: os_version = "rhel8.6" - latest7: @@ -147,6 +147,9 @@ - win11: only esx os_version = "win11" + - win2025: + only esx + os_version = "win2025" variants: - xen: only source_xen diff --git a/v2v/tests/cfg/convert_vm_to_ovirt.cfg b/v2v/tests/cfg/convert_vm_to_ovirt.cfg index b53e711d0fb..868af9fa343 100644 --- a/v2v/tests/cfg/convert_vm_to_ovirt.cfg +++ b/v2v/tests/cfg/convert_vm_to_ovirt.cfg @@ -81,23 +81,23 @@ - boot_uefi: vm_boot = "-efi" boottype = 3 - only 8_0.linux.latest9_dev, 8_0.linux.latest8_dev, 8_0.linux.latest9, 8_0.linux.latest8, 8_0.linux.8_7, 8_0.linux.8_6, 8_0.linux.ubuntu_lts, 8_0.linux.sles_latest, 8_0.windows.win2022, 8_0.windows.win11, 8_0.windows.win2016 + only 8_0.linux.latest10_dev, 8_0.linux.latest9_dev, 8_0.linux.latest9, 8_0.linux.latest8, 8_0.linux.8_8, 8_0.linux.8_6, 8_0.linux.ubuntu_lts, 8_0.linux.sles_latest, 8_0.windows.win2022, 8_0.windows.win11, 8_0.windows.win2016, 8_0.windows.win2025 variants: - linux: os_type = "linux" vm_user = ${username} vm_pwd = GENERAL_GUEST_PASSWORD variants: + - latest10_dev: + os_version = "LATEST_DEV_10" - latest9_dev: os_version = "LATEST_DEV_9" - - latest8_dev: - os_version = "LATEST_DEV_8" - latest9: os_version = "LATEST9" - latest8: os_version = "LATEST8" - - 8_7: - os_version = "rhel8.7" + - 8_8: + os_version = "rhel8.8" - 8_6: os_version = "rhel8.6" - latest7: @@ -179,6 +179,9 @@ - win11: no xen os_version = "win11" + - win2025: + no xen + os_version = "win2025" variants: - xen: only source_xen From 43cbd6b0d22fba241f3c37d84a09b76fae21ae53 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Thu, 25 Apr 2024 10:42:09 +0800 Subject: [PATCH 0304/1055] Fix failures and simplify code for nbdkit cases Signed-off-by: Ming Xie --- v2v/tests/cfg/nbdkit/nbdkit.cfg | 2 - v2v/tests/src/nbdkit/nbdkit.py | 66 ++++++++++++++++++--------------- 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/v2v/tests/cfg/nbdkit/nbdkit.cfg b/v2v/tests/cfg/nbdkit/nbdkit.cfg index 918fb5dad8c..8fcfb6c2c96 100644 --- a/v2v/tests/cfg/nbdkit/nbdkit.cfg +++ b/v2v/tests/cfg/nbdkit/nbdkit.cfg @@ -155,9 +155,7 @@ - annocheck_test_nbdkit: only source_none..dest_none checkpoint = 'annocheck_test_nbdkit' - rhel9_debug_repo_url = 'RHEL9_DEBUG_REPO_URL' - cve_starttls: only source_none..dest_none checkpoint = 'cve_starttls' - rhel9_appsource_repo_url = 'RHEL9_APP_SOURCE_URL' version_required = "[nbdkit-server-1.26.5-1,)" diff --git a/v2v/tests/src/nbdkit/nbdkit.py b/v2v/tests/src/nbdkit/nbdkit.py index a19de3b214d..3c39a64b6cd 100644 --- a/v2v/tests/src/nbdkit/nbdkit.py +++ b/v2v/tests/src/nbdkit/nbdkit.py @@ -11,6 +11,7 @@ from virttest.utils_v2v import multiple_versions_compare from virttest.utils_v2v import params_get from virttest import utils_v2v +from virttest.utils_conn import update_crypto_policy LOG = logging.getLogger('avocado.v2v.' + __name__) @@ -361,23 +362,9 @@ def check_vddk_create_options(): utils_misc.umount(vddk_libdir_src, vddk_libdir, 'nfs') def annocheck_test_nbdkit(): - lines = """ -[rhel9-debug] -baseurl = pattern -enabled = 1 -gpgcheck = 0 -name = rhel9-debug - """ - rhel9_debug_repo = os.path.join('/etc/yum.repos.d', 'rhel9-debug.repo') - with open(rhel9_debug_repo, "w") as f: - f.write(lines) - rhel9_debug_repo_url = params.get('rhel9_debug_repo_url') - process.run("sed -i 's/pattern/%s/' /etc/yum.repos.d/rhel9-debug.repo" % rhel9_debug_repo_url, - shell=True, ignore_status=True) tmp_path = data_dir.get_tmp_dir() process.run('yum download nbdkit-server nbdkit-server-debuginfo --destdir=%s' % tmp_path, shell=True, ignore_status=True) - process.run('rm -rf /etc/yum.repos.d/rhel9-debug.repo', shell=True, ignore_status=True) cmd_3 = 'annocheck -v --skip-cf-protection --skip-glibcxx-assertions --skip-glibcxx-assertions ' \ '--skip-stack-realign --section-size=.gnu.build.attributes --ignore-gaps ' \ '%s/%s --debug-rpm=%s/%s' % (tmp_path, (process.run('ls %s/nbdkit-server-1*' % tmp_path, @@ -405,11 +392,43 @@ def test_rate_filter(): if re.search('error', cmd.stdout_text): test.fail('fail to test rate filter') + def enable_legacy_cryptography(hostname): + """ + Enable the legacy sha1 algorithm. + """ + ssh_config = ("Host %s\n" + " KexAlgorithms +diffie-hellman-group14-sha1\n" + " MACs +hmac-sha1\n" + " HostKeyAlgorithms +ssh-rsa\n" + " PubkeyAcceptedKeyTypes +ssh-rsa\n" + " PubkeyAcceptedAlgorithms +ssh-rsa") % hostname + + openssl_cnf = (".include /etc/ssl/openssl.cnf\n" + "[openssl_init]\n" + "alg_section = evp_properties\n" + "[evp_properties]\n" + "rh-allow-sha1-signatures = yes") + + with open(os.path.expanduser('~/.ssh/config'), 'w') as fd: + fd.write(ssh_config) + + with open(os.path.expanduser('~/openssl-sha1.cnf'), 'w') as fd: + fd.write(openssl_cnf) + + # export the environment variable + os.environ['OPENSSL_CONF'] = os.path.expanduser('~/openssl-sha1.cnf') + LOG.debug('OPENSSL_CONF is %s' % os.getenv('OPENSSL_CONF')) + def test_ssh_create_option(): xen_host_user = params_get(params, "xen_host_user") xen_host_passwd = params_get(params, "xen_host_passwd") xen_host = params_get(params, "xen_host") # Setup ssh-agent access to xen hypervisor + support_ver = '[virt-v2v-2.0.7-4,)' + if utils_v2v.multiple_versions_compare(support_ver): + enable_legacy_cryptography(xen_host) + else: + update_crypto_policy("LEGACY") LOG.info('set up ssh-agent access ') xen_pubkey, xen_session = utils_v2v.v2v_setup_ssh_key( xen_host, xen_host_user, xen_host_passwd, auto_close=False) @@ -541,23 +560,10 @@ def cache_min_block_size(): test.fail('fail to test cache-min-block-size option') def cve_starttls(): - lines = """ -[rhel9-appsource] -baseurl = pattern -enabled = 1 -gpgcheck = 0 -name = rhel9-appsource - """ - rhel9_appsource_repo = os.path.join('/etc/yum.repos.d', 'rhel9-appsource.repo') - with open(rhel9_appsource_repo, "w") as f: - f.write(lines) - rhel9_appsource_repo_url = params.get('rhel9_appsource_repo_url') - process.run("sed -i 's/pattern/%s/' /etc/yum.repos.d/rhel9-appsource.repo" % rhel9_appsource_repo_url, - shell=True, ignore_status=True) tmp_path = data_dir.get_tmp_dir() + process.run("yum install libtool 'dnf-command(download)' -y", shell=True, ignore_status=True) process.run('yum download --source nbdkit --destdir=%s' % tmp_path, shell=True, ignore_status=True) - process.run('yum install libtool -y', shell=True, ignore_status=True) process.run('rm -rf /etc/yum.repos.d/rhel9-appsource.repo', shell=True, ignore_status=True) process.run('cd %s ; rpmbuild -rp %s' % (tmp_path, (process.run('ls %s/nbdkit*.src.rpm' % tmp_path, shell=True). stdout_text.split('/'))[-1].strip('\n')), shell=True) @@ -575,13 +581,13 @@ def cve_starttls(): def test_protect_filter(): from subprocess import Popen, PIPE, STDOUT protect_data = '"AB" * 32768' - p1 = Popen("nbdkit -f --filter=protect data '%s' protect=0-1023 --run 'nbdsh -u nbd://localhost'" % + p1 = Popen("nbdkit -f --filter=protect data '%s' protect=0-1023 --run 'nbdsh -u $uri'" % protect_data, shell=True, stdout=PIPE, stdin=PIPE, stderr=STDOUT) grep_stdout_1 = p1.communicate(input=b"buf=b'01'*256\nh.pwrite(buf,32768)\nprint(h.pread(512,32768))\n")[0] if re.search('AB', grep_stdout_1.decode()): test.fail('the data is incorrect when write data with protect filter') - p2 = Popen("nbdkit -f --filter=protect data '%s' protect=0-1023 --run 'nbdsh -u nbd://localhost'" % + p2 = Popen("nbdkit -f --filter=protect data '%s' protect=0-1023 --run 'nbdsh -u $uri'" % protect_data, shell=True, stdout=PIPE, stdin=PIPE, stderr=STDOUT) grep_stdout_2 = p2.communicate(input=b"buf=b'01'*256\nh.pwrite(buf,32768)\nprint(h.pread(512,32768))\n" From 1b33fb149887dc3730166069e69fef0fec0e8c6f Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Fri, 26 Apr 2024 14:23:56 +0800 Subject: [PATCH 0305/1055] Add nbdkit case about partition-sectorsize option Signed-off-by: Ming Xie --- v2v/tests/cfg/nbdkit/nbdkit.cfg | 7 +++++++ v2v/tests/src/nbdkit/nbdkit.py | 24 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/v2v/tests/cfg/nbdkit/nbdkit.cfg b/v2v/tests/cfg/nbdkit/nbdkit.cfg index 8fcfb6c2c96..82becb1bd45 100644 --- a/v2v/tests/cfg/nbdkit/nbdkit.cfg +++ b/v2v/tests/cfg/nbdkit/nbdkit.cfg @@ -62,6 +62,13 @@ - security_label: version_required = "[nbdkit-server-1.36.1-1,)" checkpoint = 'security_label' + - partition: + variants: + - partition_sectorsize: + sector_size = '512 4k' + version_required = "[nbdkit-server-1.36.2-1,)" + checkpoint = 'partition_sectorsize' + guest_images = 'SECTORSIZE_IMAGES_NFS_V2V_EXAMPLE' - plugin: variants: - file: diff --git a/v2v/tests/src/nbdkit/nbdkit.py b/v2v/tests/src/nbdkit/nbdkit.py index 3c39a64b6cd..f81491b629a 100644 --- a/v2v/tests/src/nbdkit/nbdkit.py +++ b/v2v/tests/src/nbdkit/nbdkit.py @@ -612,6 +612,28 @@ def security_label(): test_inco_label.stderr_text): test.fail('fail to test security label of IP filter') + def partition_sectorsize(): + sector_size = params_get(params, "sector_size") + guest_images = params_get(params, "guest_images") + with tempfile.TemporaryDirectory(prefix='guestimages_') as images_dir: + utils_misc.mount(guest_images, images_dir, 'nfs') + img_dir = data_dir.get_tmp_dir() + process.run('cp -R %s/* %s' % (images_dir, img_dir), shell=True, ignore_status=True) + utils_misc.umount(guest_images, images_dir, 'nfs') + image_list = process.run('ls %s' % img_dir, shell=True).stdout_text.strip('env').split('\n')[1:-1] + for image in image_list: + for size in list(sector_size.split(' ')): + cmd = process.run("nbdkit --filter=partition file %s/%s partition=1 partition-sectorsize=%s --run " + "'nbdinfo $uri'" % (img_dir, image, size), shell=True, ignore_status=True) + if 'non-efi' not in image and '512' in image and size == '4k' and \ + not re.search('.*try using partition-sectorsize=512', cmd.stderr_text): + test.fail('fail to test 512 image and partition-sectorsize=4k') + if '4k' in image and size == '512' and \ + not re.search('.*try using partition-sectorsize=4k', cmd.stderr_text): + test.fail('fail to test 4k image and partition-sectorsize=512') + elif re.search('nbdkit.*error', cmd.stdout_text): + test.fail('fail to test partition-sectorsize') + if version_required and not multiple_versions_compare( version_required): test.cancel("Testing requires version: %s" % version_required) @@ -673,5 +695,7 @@ def security_label(): test_protect_filter() elif checkpoint == 'security_label': security_label() + elif checkpoint == 'partition_sectorsize': + partition_sectorsize() else: test.error('Not found testcase: %s' % checkpoint) From d9faafacde1aea574dcfef5e88740c7efa8ecfab Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Fri, 26 Apr 2024 17:00:03 +0800 Subject: [PATCH 0306/1055] Add nbdkit case for ones plugin's byte option Signed-off-by: Ming Xie --- v2v/tests/cfg/nbdkit/nbdkit.cfg | 7 +++++++ v2v/tests/src/nbdkit/nbdkit.py | 13 +++++++++++++ 2 files changed, 20 insertions(+) diff --git a/v2v/tests/cfg/nbdkit/nbdkit.cfg b/v2v/tests/cfg/nbdkit/nbdkit.cfg index 82becb1bd45..46d1cab99dd 100644 --- a/v2v/tests/cfg/nbdkit/nbdkit.cfg +++ b/v2v/tests/cfg/nbdkit/nbdkit.cfg @@ -101,6 +101,13 @@ - create_options: version_required = "[nbdkit-server-1.32.5-4,)" checkpoint = 'test_ssh_create_option' + - ones: + only source_none..dest_none + variants: + - byte: + byte_size = '1 0xff 256' + version_required = "[nbdkit-server-1.36.1-1,)" + checkpoint = 'ones_byte' - run: variants: - vddk7_0: diff --git a/v2v/tests/src/nbdkit/nbdkit.py b/v2v/tests/src/nbdkit/nbdkit.py index f81491b629a..f11feb2c602 100644 --- a/v2v/tests/src/nbdkit/nbdkit.py +++ b/v2v/tests/src/nbdkit/nbdkit.py @@ -634,6 +634,17 @@ def partition_sectorsize(): elif re.search('nbdkit.*error', cmd.stdout_text): test.fail('fail to test partition-sectorsize') + def ones_byte(): + byte_size = params_get(params, "byte_size") + for size in list(byte_size.split(' ')): + cmd = process.run("nbdkit ones size=4M byte=%s --run 'nbdinfo $uri'" % size, shell=True, ignore_status=True) + if size == '1' and not re.search(r'.*\\001\\001', cmd.stdout_text): + test.fail('fail to test ones plugin with byte=1') + if size == 'oxff' and not re.search('ISO-8859 text', cmd.stdout_text): + test.fail('fail to test ones plugin with byte=oxff') + if size == '256' and not re.search('could not parse number', cmd.stderr_text): + test.fail('fail to test ones plugin with byte=256') + if version_required and not multiple_versions_compare( version_required): test.cancel("Testing requires version: %s" % version_required) @@ -697,5 +708,7 @@ def partition_sectorsize(): security_label() elif checkpoint == 'partition_sectorsize': partition_sectorsize() + elif checkpoint == 'ones_byte': + ones_byte() else: test.error('Not found testcase: %s' % checkpoint) From a2ce01f6f6244e156cdd1ad99a241b9b1abfea62 Mon Sep 17 00:00:00 2001 From: nanli Date: Thu, 30 Nov 2023 17:48:09 +0800 Subject: [PATCH 0307/1055] add case for virtio-mem with memory backing type VIRT-299164: Virtio-mem memory device with various memory backing type Signed-off-by: nanli --- .../virtio_mem_with_memory_backing_type.cfg | 73 ++++++ .../virtio_mem_with_memory_backing_type.py | 234 ++++++++++++++++++ provider/memory/memory_base.py | 23 +- 3 files changed, 327 insertions(+), 3 deletions(-) create mode 100644 libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_backing_type.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_backing_type.py diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_backing_type.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_backing_type.cfg new file mode 100644 index 00000000000..5c4c44ee160 --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_backing_type.cfg @@ -0,0 +1,73 @@ +- memory.devices.virtio_mem.memory_backing_type: + type = virtio_mem_with_memory_backing_type + no s390-virtio + start_vm = no + mem_model = "virtio-mem" + virtio_mem_num = 2 + allocate_huge_pages = "3145728KiB" + consume_value = 102400 + mem_value = 2097152 + current_mem = 2097152 + max_mem = 4194304 + numa_mem = 1048576 + aarch_max_mem = 20971520 + base_attrs = "'vcpu': 4, 'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'" + numa_attrs = "'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_mem}', 'unit': 'KiB'}]}" + max_attrs = "'max_mem_rt': %s, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'" + vm_attrs = {${base_attrs}, ${numa_attrs}, ${max_attrs}} + target_size = 524288 + request_size = 524288 + type0 = "memory-backend-ram" + type1 = "memory-backend-file" + path0 = "" + path1 = "/dev/hugepages/libvirt/qemu/" + required_kernel = [5.14.0,) + guest_required_kernel = [5.8.0,) + func_supported_since_libvirt_ver = (8, 0, 0) + func_supported_since_qemu_kvm_ver = (6, 2, 0) + variants memory_backing: + - file: + source_type = 'file' + source_attr = "'source_type':'${source_type}'" + type0 = "memory-backend-file" + type1 = ${type0} + - anonymous: + no set_hugepage + source_type = 'anonymous' + source_attr = "'source_type':'${source_type}'" + - memfd: + source_type = 'memfd' + source_attr = "'source_type':'${source_type}'" + type0 = "memory-backend-memfd" + type1 = ${type0} + - undefined: + variants allocation_mode: + - alloc_ondemand: + mode = "ondemand" + alloc_attr = "'allocation':{'mode':'${mode}'}" + file: + path0 = "/var/lib/libvirt/qemu/ram/" + - alloc_immediate_with_threads: + func_supported_since_libvirt_ver = (8, 2, 0) + mode = "immediate" + threads = 8 + alloc_attr = "'allocation':{'mode':'${mode}', 'threads':${threads}}" + file: + path0 = "/var/lib/libvirt/qemu/ram/" + - set_hugepage: + hugepages_attr = "'hugepages': {}" + undefined: + type0 = "memory-backend-file" + type1 = ${type0} + file: + path0 = "/dev/hugepages/libvirt/qemu/" + undefined: + path0 = "/dev/hugepages/libvirt/qemu/" + check_backing_type = '{"execute":"qom-get", "arguments":{"path":"/objects/%s", "property":"type"}}' + check_mem_path = '{"execute":"qom-get", "arguments":{"path":"/objects/%s", "property":"mem-path"}}' + expected_allocated = ['false', 'false'] + expected_backing_type = ['${type0}', '${type1}'] + expected_mem_path = ['${path0}', '${path1}'] + variants attach_type: + - hot_plug: + - cold_plug: diff --git a/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_backing_type.py b/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_backing_type.py new file mode 100644 index 00000000000..589e0ec0ad8 --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_backing_type.py @@ -0,0 +1,234 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import re +import json + +from avocado.utils import cpu +from avocado.utils import memory as avocado_mem + +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirtd import Libvirtd +from virttest.utils_libvirt import libvirt_memory +from virttest.utils_libvirt import libvirt_vmxml +from virttest.staging import utils_memory + +from provider.memory import memory_base + +VIRSH_ARGS = {'debug': True, 'ignore_status': False} + + +def get_vm_attrs(test, params): + """ + Get vm attrs. + :param test: test object + :param params: dictionary with the test parameters + :return vm_attrs: get updated vm attrs dict. + """ + max_mem = params.get("max_mem") + if cpu.get_arch().startswith("aarch"): + max_mem = params.get("aarch_max_mem") + vm_attrs = eval(params.get("vm_attrs", "{}") % max_mem) + source_attr = params.get("source_attr", "") + alloc_attr = params.get("alloc_attr", "") + hugepages_attr = params.get("hugepages_attr", "") + + mb_value = "" + for item in [source_attr, alloc_attr, hugepages_attr]: + if item != "": + mb_value += item + "," + mb_attrs = eval("{'mb':{%s}}" % mb_value[:-1]) + + vm_attrs.update(mb_attrs) + test.log.debug("Get current vm attrs is :%s", vm_attrs) + + return vm_attrs + + +def get_virtio_objs(test, params): + """ + Get all virtio-mem memory device objects. + + :param test: test object. + :param params: dictionary with the test parameters. + :return mem_objs: virtio memory device object list. + """ + default_pagesize = params.get('default_pagesize') + mem_objs = [] + for item in [(None, 0), (default_pagesize, 1)]: + single_mem = {'mem_model': 'virtio-mem'} + if item[0] is not None: + single_mem.update({'source': {'pagesize': item[0]}}) + single_mem.update( + {'target': {'node': item[1], 'size': int(params.get('target_size')), + 'requested_size': int(params.get('request_size')), + 'block_size': int(default_pagesize)}}) + test.log.debug("Get the virtio-mem dict: %s", single_mem) + mem_obj = libvirt_vmxml.create_vm_device_by_type('memory', single_mem) + mem_objs.append(mem_obj) + return mem_objs + + +def check_qemu_monitor_json(test, params, mem_names, check_item, check_cmd, + expected_list): + """ + Check virsh qemu_monitor_command result. + + :param test: test object. + :param params: dictionary with the test parameters. + :param mem_names: virtio memory memory name list. + :param check_item: check item, such as memory backing type or path. + :param check_cmd: the command to check qemu monitor. + :param expected_list: expected list. + """ + vm_name = params.get("main_vm") + for index, mem_name in enumerate(mem_names): + res = virsh.qemu_monitor_command( + vm_name, check_cmd % mem_name, **VIRSH_ARGS).stdout_text + + if 'return' in json.loads(res): + actual_value = str(json.loads(res)['return']) + if expected_list[index] in actual_value: + test.log.debug("Check '%s' is '%s' PASS", check_item, actual_value) + else: + test.fail("Expect '%s' for '%s' is '%s', but got '%s'" % ( + check_item, mem_name, expected_list[index], actual_value)) + else: + test.fail("Checking '%s' failed" % res) + + +def check_mb_setting(test, params): + """ + Check memory backing pre-allocated value, memory backing type and + memory backing path. + + :param test: test object. + :param params: dictionary with the test parameters. + """ + virtio_mem_num = int(params.get("virtio_mem_num")) + expected_allocated = eval(params.get("expected_allocated", "{}")) + expected_backing_type = eval(params.get("expected_backing_type", "{}")) + expected_mem_path = eval(params.get("expected_mem_path", "{}")) + memory_backing = params.get("memory_backing") + check_backing_type = params.get("check_backing_type") + check_mem_path = params.get("check_mem_path") + allocation_mode = params.get("allocation_mode") + vm_name = params.get("main_vm") + file_backend_scenario =\ + memory_backing == "file" or \ + memory_backing == "undefined" and allocation_mode == "set_hugepage" + + mem_name_list = [] + # Check virtio memory pre-allocated value + ret = virsh.qemu_monitor_command(vm_name, "info memdev", "--hmp", + debug=True).stdout_text.replace("\r\n", "") + for index in range(virtio_mem_num): + mem_name = "memvirtiomem%d" % index + pattern = "memory backend: %s.*prealloc: %s " % ( + mem_name, expected_allocated[index]) + + if not re.search(pattern, ret): + test.fail("Expect '%s' exist, but not found" % pattern) + else: + test.log.debug("Check access pre-allocated value is '%s': PASS", pattern) + mem_name_list.append(mem_name) + + # Check virtio memory backing type. + check_qemu_monitor_json(test, params, mem_name_list, + 'memory backing type', check_backing_type, + expected_backing_type) + + # Check virtio memory backing path. + if file_backend_scenario: + check_qemu_monitor_json(test, params, mem_name_list, + 'memory backing path', check_mem_path, + expected_mem_path) + + +def run(test, params, env): + """ + Verify virtio-mem memory device works with various memory backing type + """ + def setup_test(): + """ + Allocate huge page memory: + """ + test.log.info("TEST_SETUP: Set hugepage and add kernel parameter") + default_pagesize = avocado_mem.get_huge_page_size() + params.update({'default_pagesize': default_pagesize}) + utils_memory.set_num_huge_pages(int(allocate_huge_pages)/default_pagesize) + + def run_test(): + """ + Test virtio-mem memory device under various memory backing types + """ + test.log.info("TEST_STEP1: Define vm with virtio-mem") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vm_attrs = get_vm_attrs(test, params) + vmxml.setup_attrs(**vm_attrs) + vmxml.sync() + + mem_objs = get_virtio_objs(test, params) + + if attach_type == "cold_plug": + test.log.info("TEST_STEP2: Cold-plug virtio-mem devices") + for mem in mem_objs: + virsh.attach_device(vm.name, mem.xml, flagstr="--config", + **VIRSH_ARGS) + + test.log.info("TEST_STEP3: Start guest") + vm.start() + vm.wait_for_login().close() + + test.log.info("TEST_STEP4: Restart the service") + Libvirtd().restart() + + if attach_type == "hot_plug": + test.log.info("TEST_STEP5: Hot-plug virtio-mem devices") + for mem in mem_objs: + virsh.attach_device(vm.name, mem.xml, + wait_for_event=True, **VIRSH_ARGS) + test.log.info("TEST_STEP 6-9:Check virtio memory backend pre-allocated " + "value, memory backing type and memory backing path.") + check_mb_setting(test, params) + + test.log.info("TEST_STEP10: Consume guest memory successfully") + session = vm.wait_for_login() + status, output = libvirt_memory.consume_vm_freememory( + session, consume_value=consume_value) + if status: + test.fail("Fail to consume guest memory. Error:%s" % output) + session.close() + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + utils_memory.set_num_huge_pages(0) + bkxml.sync() + + vm_name = params.get("main_vm") + original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = original_xml.copy() + vm = env.get_vm(vm_name) + memory_base.adjust_memory_size(params) + + allocate_huge_pages = re.findall(r'\d+', params.get("allocate_huge_pages"))[0] + attach_type = params.get("attach_type") + consume_value = int(params.get("consume_value")) + + try: + memory_base.check_supported_version(params, test, vm) + setup_test() + run_test() + + finally: + teardown_test() diff --git a/provider/memory/memory_base.py b/provider/memory/memory_base.py index db83b3c49dc..fa125faedb8 100644 --- a/provider/memory/memory_base.py +++ b/provider/memory/memory_base.py @@ -1,19 +1,20 @@ import re import platform +from avocado.utils import cpu +from avocado.utils import memory as avocado_mem +from avocado.core import exceptions + from virttest import libvirt_version from virttest import utils_misc from virttest.libvirt_xml.devices import memory from virttest.utils_version import VersionInterval -from avocado.core import exceptions - def convert_data_size(current_size, dest_unit="KiB"): """ Convert source value to expected value - :param current_size: current size str, eg: 1024MB :param dest_unit: dest size unit, eg: KiB, MiB :return: dest_size: The size is converted, eg: 1(the dest unit is given, @@ -131,3 +132,19 @@ def create_file_within_nvdimm_disk(test, vm_session, test_device, test_file, cmd = 'echo \"%s\" >%s' % (test_str, test_file) vm_session.cmd(cmd) vm_session.cmd_output('umount %s' % mount_point) + + +def adjust_memory_size(params): + """ + Adjust the memory device size for different arch hugepage size + :param params: a dict for parameters + eg: In arm, we need to consider: + 2M on 4k kernel package. + 512M on 64k kernel package. + """ + default_pagesize_KiB = avocado_mem.get_huge_page_size() + + if cpu.get_arch().startswith("aarch"): + params.update({'block_size': default_pagesize_KiB}) + params.update({'request_size': default_pagesize_KiB}) + params.update({'target_size': default_pagesize_KiB*2}) From 611bc24795fb3b59b02989ff68a2d1ff179069e0 Mon Sep 17 00:00:00 2001 From: nanli Date: Fri, 17 Nov 2023 17:33:32 +0800 Subject: [PATCH 0308/1055] add case for changing requested size value of virtio-mem xxxx-299165: Change requested memory of virtio-mem memory device Signed-off-by: nanli --- .../change_virtio_mem_request_size.cfg | 63 +++ .../change_virtio_mem_request_size.py | 361 ++++++++++++++++++ provider/memory/memory_base.py | 3 +- 3 files changed, 426 insertions(+), 1 deletion(-) create mode 100644 libvirt/tests/cfg/memory/memory_devices/change_virtio_mem_request_size.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py diff --git a/libvirt/tests/cfg/memory/memory_devices/change_virtio_mem_request_size.cfg b/libvirt/tests/cfg/memory/memory_devices/change_virtio_mem_request_size.cfg new file mode 100644 index 00000000000..da6a1724def --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/change_virtio_mem_request_size.cfg @@ -0,0 +1,63 @@ +- memory.devices.virtio_mem.change_memory: + type = change_virtio_mem_request_size + no s390-virtio + start_vm = yes + kernel_extra_params_add = "memhp_default_state=online_movable" + kernel_extra_params_remove = "memhp_default_state" + mem_model = "virtio-mem" + allocate_huge_pages = "4194304KiB" + target_size = 1048576 + block_size = 2048 + request_size = 524288 + requested_unit = "KiB" + basic_request = "${request_size}${requested_unit}" + basic_node = 0 + basic_device = "--node ${basic_node} --config" + virsh_opts = "%s --requested-size %s " + expected_event = "memory-device-size-change" + required_kernel = [5.14.0,) + guest_required_kernel = [5.8.0,) + func_supported_since_libvirt_ver = (8, 0, 0) + func_supported_since_qemu_kvm_ver = (6, 2, 0) + mem_value = 2097152 + memory_unit = 'KiB' + current_mem = 2097152 + max_mem = 10485760 + max_mem_slots = 16 + numa_mem = 1048576 + base_attrs = "'memory_unit':'${memory_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'" + numa_attrs = "'vcpu': 4, 'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'},{'id':'1','cpus': '2-3','memory':'${numa_mem}','unit':'KiB'}]}" + max_attrs = "'max_mem_rt': ${max_mem}, 'max_mem_rt_slots': ${max_mem_slots}, 'max_mem_rt_unit': 'KiB'" + vm_attrs = {${base_attrs}, ${numa_attrs}, ${max_attrs}} + expect_xpath = [{'element_attrs':[".//memory[@unit='${memory_unit}']"],'text':'%d'},{'element_attrs':[".//currentMemory[@unit='KiB']"],'text':'%d'}] + variants guest_state: + - shutoff_guest: + no file hugepages memfd + mem_basic = {'mem_model': '${mem_model}', 'target': {'requested_unit': '${requested_unit}', 'size': %s, 'node': ${basic_node}, 'size_unit': 'KiB', 'requested_size': %s, 'block_unit': 'KiB', 'block_size': %s}} + - running_guest: + attach_node = 1 + attached_device = "--node ${attach_node}" + basic_device_alias = "--alias virtiomem0" + mem_basic = {'mem_model': '${mem_model}', 'target': {'requested_unit': '${requested_unit}', 'size': %s, 'node': ${basic_node}, 'size_unit': 'KiB', 'requested_size': %s, 'block_unit': 'KiB', 'block_size': %s}} + mem_attach = {'mem_model': '${mem_model}', 'target': {'requested_unit': '${requested_unit}', 'size': %s, 'node': ${attach_node}, 'size_unit': 'KiB', 'requested_size': %s, 'block_unit': 'KiB', 'block_size': %s}} + variants requested_setting: + - normal_requested: + update_request_size = '1024MiB' + - zero_requested: + update_request_size = "0MiB" + - bigger_requested: + update_request_size = '2048MiB' + error_msg = "requested size must be smaller than or equal to" + - not_mutiple_of_block_requested: + update_request_size = '513MiB' + error_msg = "requested size must be an integer multiple of block size" + variants memory_backing: + - file: + source_type = 'file' + source_attr = "'source_type':'${source_type}'" + - hugepages: + hugepages_attr = "'hugepages': {}" + - memfd: + source_type = 'memfd' + source_attr = "'source_type':'${source_type}'" + - undefined: diff --git a/libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py b/libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py new file mode 100644 index 00000000000..8f5bdd6b5fe --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py @@ -0,0 +1,361 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import re +import time + +from avocado.utils import cpu +from avocado.utils import memory + +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_vmxml +from virttest.staging import utils_memory + +from provider.memory import memory_base + +VIRSH_ARGS = {'debug': True, 'ignore_status': False} + + +def get_vm_attrs(test, params): + """ + Get vm attrs. + + :param test: test object + :param params: dictionary with the test parameters + :return vm_attrs: get updated vm attrs dict. + """ + vm_attrs = eval(params.get("vm_attrs", "{}")) + source_attr = params.get("source_attr", "") + hugepages_attr = params.get("hugepages_attr", "") + mb_value = "" + + for item in [source_attr, hugepages_attr]: + if item != "": + mb_value += item + "," + mb_attrs = eval("{'mb':{%s}}" % mb_value[:-1]) + + vm_attrs.update(mb_attrs) + test.log.debug("Get current vm attrs is :%s", vm_attrs) + + return vm_attrs + + +def define_guest_with_basic_virtio_mem(test, params, vm_name, mem_basic_dict): + """ + Define guest with virtio memory device. + + :param test: test object. + :param params: dictionary with the test parameters. + :param vm_name: vm name. + :param mem_basic_dict: the virtio memory device dict. + """ + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vm_attrs = get_vm_attrs(test, params) + vmxml.setup_attrs(**vm_attrs) + + libvirt_vmxml.modify_vm_device( + vmxml, "memory", + dev_dict=eval(mem_basic_dict % (params.get('target_size'), + params.get('request_size'), + params.get('default_pagesize')))) + test.log.debug("Define vm with %s.", vm_xml.VMXML.new_from_inactive_dumpxml( + vm_name)) + + +def get_various_size(test, vm_name, check_item='requested_size', index=0): + """ + Get various memory size. + + :param test: test object. + :param vm_name: vm name. + :param check_item: The item you want to check, eg: requested_size. + :param index: memory index of memory list in devices. + :return actual_size, the actual size in xml. + """ + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + mem_list = vmxml.devices.by_device_tag('memory') + actual_attrs = mem_list[index].fetch_attrs() + test.log.debug("Get memory attrs list is: '%s'", actual_attrs) + actual_size = actual_attrs['target'][check_item] + + return actual_size + + +def check_various_size(test, vm_name, expected_size, + check_item='requested_size', index=0): + """ + Check Various size in vmxml memory device + + :param test: test object. + :param vm_name: vm name. + :param expected_size: expected size value. + :param check_item: The item you want to check, eg: requested_size. + :param index: memory index of memory list in devices. + """ + actual_size = get_various_size(test, vm_name, check_item=check_item, + index=index) + + if int(actual_size) != int(expected_size): + test.fail("Expect to get '%s':'%s', but got:'%s' in '%sth' " + "memory" % (check_item, str(expected_size), actual_size, index+1)) + else: + test.log.debug("Check '%s' is '%s' successfully", (check_item, expected_size)) + + +def update_virtio_mem_request_size(test, params, vm_name, device_opt, target_requested): + """ + Update specified virtio memory request value. + + :param test: test object. + :param params: dictionary with the test parameters. + :param vm_name: vm name. + :param device_opt: the device option to update. + :param target_requested: the request value to update. + """ + error_msg = params.get("error_msg") + expected_event = params.get("expected_event") + virsh_opts = params.get("virsh_opts") + guest_state = params.get("guest_state") + + event_session = virsh.EventTracker.start_get_event(vm_name) + res = virsh.update_memory_device( + vm_name, options=virsh_opts % (device_opt, target_requested), debug=True) + libvirt.check_result(res, error_msg) + + event_output = virsh.EventTracker.finish_get_event(event_session) + pattern = r"%s\S+ \S+ \S+ '\S+\s+\S+ virtiomem%s" % ( + expected_event, re.findall(r"\d+", device_opt)[0]) + + def _check_event_output(patt, output, expect_exist=True): + is_existed = bool(re.findall(patt, output)) + if is_existed != expect_exist: + test.fail('Expect %s to get: %s from the event output:%s' % ( + '' if expect_exist else 'not', patt, output)) + else: + test.log.debug("Check event %s success in the event output", patt) + + if guest_state != "shutoff_guest": + _check_event_output(pattern, event_output, expect_exist=error_msg is None) + + +def check_mem_total(test, params, session, old_mem_total): + """ + Compare mem total value in different scenarios. + + :param test: test object. + :param params: dictionary with the test parameters. + :param session: vm session. + :param old_mem_total: The old mem total value to compare. + :return: new_mem_total, current mem total value. + """ + + update_req = int(memory_base.convert_data_size( + params.get("update_request_size"), 'KiB')) + basic_req = int(memory_base.convert_data_size( + params.get("basic_request"), 'KiB')) + new_mem_total = int(utils_memory.memtotal(session)) + if params.get('normal_or_zero_request'): + if new_mem_total - old_mem_total != update_req - basic_req: + test.fail("Expect two memTotal values(%s and %s) difference is " + "(%s - %s)" % (new_mem_total, old_mem_total, + update_req, basic_req)) + + elif params.get('bigger_or_not_muti_request'): + if new_mem_total != old_mem_total: + test.fail("Expect mem total to be '%s', but found '%s'" % ( + old_mem_total, new_mem_total)) + test.log.debug("Check memtotal success") + + return new_mem_total + + +def check_guest_xml(test, vm_name, params): + """ + Check correct memory size in guest xml. + + :param test: test object. + :param vm_name: vm name + :param params: dictionary with the test parameters. + """ + expect_xpath = params.get("expect_xpath") + target_size = int(params.get("target_size")) + mem_value = int(params.get("mem_value")) + current_mem = int(params.get("current_mem")) + basic_request = int(re.findall(r'\d+', params.get("basic_request"))[0]) + update_request_size = int(memory_base.convert_data_size( + params.get("update_request_size"), 'KiB')) + + test.log.debug("Start checking memory size and current memory size") + virtio_mem_value = current_0 = current_1 = 0 + if params.get('normal_or_zero_request'): + virtio_mem_value = current_0 = current_1 = update_request_size + elif params.get('bigger_or_not_muti_request'): + virtio_mem_value = current_0 = current_1 = basic_request + xpath = expect_xpath % (mem_value + target_size * 2, + current_mem + current_0 + current_1) + test.log.debug("Checking xml pathern is :%s", xpath) + + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + test.log.debug("Current mem xml is :%s\n", vmxml) + libvirt_vmxml.check_guest_xml_by_xpaths(vmxml, eval(xpath)) + + test.log.debug("Start checking all memory device size") + check_list = [(params.get('default_pagesize'), 'block_size', 0), + (params.get('default_pagesize'), 'block_size', 1), + (virtio_mem_value, 'requested_size', 0), + (virtio_mem_value, 'requested_size', 1), + (virtio_mem_value, 'current_size', 0), + (virtio_mem_value, 'current_size', 1)] + for items in check_list: + check_various_size(test, vm_name, items[0], check_item=items[1], + index=items[2]) + + +def update_and_check_memory_size(test, params, session, update_device, + update_size, old_mem_total): + """ + Update request size and check memory size. + + :param test: test object. + :param params: dictionary with the test parameters. + :param session: vm session + :param update_device: the device to update + :param update_size: the size to update + :param old_mem_total: the old mem total value to compare with new mem total. + :return new_mem_total: return the current mem total + """ + vm_name = params.get("main_vm") + update_virtio_mem_request_size(test, params, vm_name, update_device, + update_size) + new_mem_total = check_mem_total(test, params, session, old_mem_total) + return new_mem_total + + +def run(test, params, env): + """ + Verify virtio-mem memory device requested memory size could be changed + """ + def setup_test(): + """ + Allocate huge page memory and update kernel parameter. + """ + test.log.info("TEST_SETUP: Set hugepage and add kernel parameter") + default_pagesize = memory.get_huge_page_size() + params.update({'default_pagesize': default_pagesize}) + utils_memory.set_num_huge_pages(int(allocate_huge_pages)/default_pagesize) + + def run_test_shutoff_guest(): + """ + 1.Define vm. + 2.Change virtio-mem requested size and check virtio-mem config + """ + test.log.info("TEST_STEP1: Define vm with numa and virtio-mem device") + if vm.is_alive(): + virsh.destroy(vm_name, **VIRSH_ARGS) + define_guest_with_basic_virtio_mem(test, params, vm_name, mem_basic) + + test.log.info("TEST_STEP2: Change the requested size of the virtio-mem") + update_virtio_mem_request_size(test, params, vm_name, + basic_device, update_request_size) + if params.get('bigger_or_not_muti_request'): + return + + test.log.info("TEST_STEP3: Check the virtio-mem memory device config") + converted_req = int(memory_base.convert_data_size(update_request_size, requested_unit)) + check_list = [(target_size, 'size'), (converted_req, 'requested_size'), + (basic_node, 'node'), (block_size, 'block_size')] + for items in check_list: + check_various_size(test, vm_name, items[0], check_item=items[1]) + + def run_test_running_guest(): + """ + 1.Define vm. + 2.Change virtio-mem requested size and check virtio-mem config + 3.Hotplug a virtio-mem device and check virtio-mem config + """ + test.log.info("TEST_STEP1: Define vm with numa and virtio-mem device") + define_guest_with_basic_virtio_mem(test, params, vm_name, mem_basic) + + test.log.info("TEST_STEP2: Start guest") + virsh.start(vm_name, **VIRSH_ARGS) + session = vm.wait_for_login() + + test.log.info("TEST_STEP3: Attach a new virtio-memory device") + mem_obj = libvirt_vmxml.create_vm_device_by_type( + "memory", eval(mem_attach % (params.get('target_size'), + params.get('request_size'), + params.get('default_pagesize')))) + virsh.attach_device(vm.name, mem_obj.xml, wait_for_event=True, **VIRSH_ARGS) + + test.log.info("TEST_STEP4: Get the first time total memory in guest") + if cpu.get_arch().startswith("aarch"): + time.sleep(7) + mem_total_1 = int(utils_memory.memtotal(session)) + + test.log.info("TEST_STEP5,6: Change the first virtio-mem requested size" + "with alias name and check total memory") + mem_total_2 = update_and_check_memory_size( + test, params, session, basic_device_alias, update_request_size, + mem_total_1) + + test.log.info("TEST_STEP7,8: Change the second virtio-mem requested " + "size with node id and check total memory") + update_and_check_memory_size(test, params, session, attached_device, + update_request_size, mem_total_2) + session.close() + + test.log.info("TEST_STEP9: Check the memory allocation and virtio-mem " + "device active config by virsh dumpxml") + check_guest_xml(test, vm.name, params) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + utils_memory.set_num_huge_pages(0) + bkxml.sync() + + vm_name = params.get("main_vm") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + vm = env.get_vm(vm_name) + memory_base.adjust_memory_size(params) + + allocate_huge_pages = re.findall(r'\d+', params.get("allocate_huge_pages"))[0] + guest_state = params.get("guest_state") + basic_node = params.get("basic_node") + target_size = int(params.get("target_size")) + block_size = params.get("block_size") + mem_basic = params.get("mem_basic", "{}") + mem_attach = params.get("mem_attach", "{}") + attached_device = params.get("attached_device") + basic_device = params.get("basic_device") + basic_device_alias = params.get("basic_device_alias") + update_request_size = params.get("update_request_size") + requested_unit = params.get("requested_unit") + requested_setting = params.get("requested_setting") + params.update( + {'normal_or_zero_request': requested_setting in [ + "normal_requested", "zero_requested"]}) + params.update( + {'bigger_or_not_muti_request': requested_setting in [ + "bigger_requested", "not_mutiple_of_block_requested"]}) + + run_test = eval('run_test_%s' % guest_state) + memory_base.check_supported_version(params, test, vm) + try: + setup_test() + run_test() + + finally: + teardown_test() diff --git a/provider/memory/memory_base.py b/provider/memory/memory_base.py index fa125faedb8..f878fc9f6bc 100644 --- a/provider/memory/memory_base.py +++ b/provider/memory/memory_base.py @@ -1,9 +1,9 @@ import re import platform +from avocado.core import exceptions from avocado.utils import cpu from avocado.utils import memory as avocado_mem -from avocado.core import exceptions from virttest import libvirt_version from virttest import utils_misc @@ -137,6 +137,7 @@ def create_file_within_nvdimm_disk(test, vm_session, test_device, test_file, def adjust_memory_size(params): """ Adjust the memory device size for different arch hugepage size + :param params: a dict for parameters eg: In arm, we need to consider: 2M on 4k kernel package. From 6215d8f7e642c357008bc6a4d1a9bd0d8c614ac4 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Mon, 29 Apr 2024 13:13:56 +0800 Subject: [PATCH 0309/1055] Change guests for v2v vmx_ssh cases Signed-off-by: Ming Xie --- v2v/tests/cfg/convert_from_file.cfg | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/v2v/tests/cfg/convert_from_file.cfg b/v2v/tests/cfg/convert_from_file.cfg index bc8a0cfc55f..41e2bb276a9 100644 --- a/v2v/tests/cfg/convert_from_file.cfg +++ b/v2v/tests/cfg/convert_from_file.cfg @@ -186,38 +186,46 @@ variants: - latest8: v2v_debug = force_on - only esx_70 + only esx_80 main_vm = 'VM_NAME_RHEL8_V2V_EXAMPLE' - msg_content = 'scp -T' + msg_content = "nbdcopy .*?" + version_required = "[virt-v2v-2.0.7-1.el9,)" expect_msg = yes + boottype = 3 - latest7: - only esx_70 + only esx_80 main_vm = 'VM_NAME_RHEL7_V2V_EXAMPLE' - latest6: enable_legacy_policy = yes - only esx_70 + only esx_80 main_vm = 'VM_NAME_RHEL6_V2V_EXAMPLE' + boottype = 3 + #skip check guest because of bug1647352 + skip_vm_check = yes - regular_user_sudo: checkpoint = 'regular_user_sudo' main_vm = 'VM_NAME_RHEL8_V2V_EXAMPLE' env_settings = 'eval `ssh-agent`;ssh-add;sudo -E LIBGUESTFS_BACKEND=direct' unprivileged_user = 'USER_UNPRIVILEGED_V2V_EXAMPLE' + boottype = 3 #os_directory = '/home/${unprivileged_user}' - only esx_70 + only esx_80 - nvme_disk: - only esx_70 + only esx_80 #add required version due to bug2070530 version_required = "[virt-v2v-2.0.7-1.el9,)" main_vm = 'VM_NAME_NVME_RHEL8_V2V_EXAMPLE' - datastore = esx7.0-function + datastore = esx8.0-function + boottype = 3 #Skip pre-check by bz#2068992. Will modify once the bug fixed. skip_virsh_pre_conn = yes - percent_encode: - only esx_70 + only esx_80 only output_mode.libvirt version_required = "[virt-v2v-2.0.7-1.el9,)" main_vm = 'VM_NAME_PERCENT_ENCODING_RHEL9_V2V_EXAMPLE' - datastore = esx7.0-function + datastore = esx8.0-function + boottype = 3 - space_name: only esx_80 only output_mode.libvirt From 982f01654e95e4552fc8bc8963a2cda40fd8a558 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Mon, 18 Mar 2024 21:28:49 +0800 Subject: [PATCH 0310/1055] virtual_disks_driver_iothreads: add case Test disk driver iothread feature like below Scenarios: - start vm with iothreads - hotplug a disk with iothreads - update disk with iothreads - delete iothread Signed-off-by: Dan Zheng --- .../virtual_disks_iothreads_queue.cfg | 95 +++++ .../virtual_disks_iothreads_queue.py | 330 ++++++++++++++++++ 2 files changed, 425 insertions(+) create mode 100755 libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg create mode 100755 libvirt/tests/src/virtual_disks/virtual_disks_iothreads_queue.py diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg new file mode 100755 index 00000000000..efbbbab0f5f --- /dev/null +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg @@ -0,0 +1,95 @@ +- virtual_disks.iothreads.queue: + type = virtual_disks_iothreads_queue + status_error = "no" + start_vm = "no" + func_supported_since_libvirt_ver = (10, 0, 0) + check_vm_dumpxml = yes + target_dev = "vda" + vm_attrs = {'iothreads': 4} + variants method: + - user_defined: + queue_num = "3" + driver = {'name': 'qemu', 'queues': '${queue_num}'} + driver_iothreads = {'iothread': [{'queue': [{'id': '0'}, {'id': '1'}], 'id': '1'}, {'queue': [{'id': '2'}], 'id': '2'}]} + check_qemu_pattern = '"driver":"virtio-blk-pci","num-queues":3,"iothread-vq-mapping":\[{"iothread":"iothread1","vqs":\[0,1\]},{"iothread":"iothread2","vqs":\[2\]}\]' + - round_robin: + driver = {'name': 'qemu', 'type': 'qcow2'} + driver_iothreads = {'iothread': [{'id': '1'}, {'id': '2'}, {'id': '3'}]} + check_qemu_pattern = '"driver":"virtio-blk-pci","iothread-vq-mapping":\[{"iothread":"iothread1"},{"iothread":"iothread2"},{"iothread":"iothread3"}\]' + variants scenario: + - define_start: + - define_invalid: + status_error = yes + variants: + - both_attribute_subelement: + only coldplug..round_robin + queue_num = "3" + driver = {'name': 'qemu', 'queues': '${queue_num}', 'iothread': '4'} + driver_iothreads = {'iothread': [{'id': '1'}, {'id': '2'}]} + err_msg = "disk driver 'iothread' attribute can't be used together with 'iothreads' subelement" + - part_iothreads_mapped: + only coldplug..user_defined + queue_num = "3" + driver = {'name': 'qemu', 'queues': '${queue_num}'} + driver_iothreads = {'iothread': [{'queue': [{'id': '0'}, {'id': '1'}], 'id': '1'}, {'id': '2'}]} + err_msg = "unsupported configuration: iothread to queue mapping must be provided for all iothreads or for none" + - no_iothreads_define: + only coldplug..round_robin + vm_attrs = {'iothreads': 0} + queue_num = "2" + driver = {'name': 'qemu', 'queues': '${queue_num}'} + driver_iothreads = {'iothread': [{'id': '1'}, {'id': '2'}]} + err_msg = "unsupported configuration: Disk iothread '1' not defined in iothreadid" + - dup_mapping_same_iothread: + only coldplug..round_robin + queue_num = "3" + driver = {'name': 'qemu', 'queues': '${queue_num}'} + driver_iothreads = {'iothread': [{'id': '1'}, {'id': '1'}]} + err_msg = "unsupported configuration: Duplicate mapping for iothread '1'" + - dup_queue_assigned: + only coldplug..user_defined + queue_num = "2" + driver = {'name': 'qemu', 'queues': '${queue_num}'} + driver_iothreads = {'iothread': [{'queue': [{'id': '0'}], 'id': '1'}, {'queue': [{'id': '1'}], 'id': '2'}, {'queue': [{'id': '1'}], 'id': '3'}]} + err_msg = "unsupported configuration: disk iothread queue '1' is already assigned" + - no_queue_number: + only coldplug..user_defined + driver = {'name': 'qemu', 'type': 'qcow2'} + driver_iothreads = {'iothread': [{'queue': [{'id': '0'}], 'id': '1'}, {'queue': [{'id': '2'}], 'id': '2'}]} + err_msg = "unsupported configuration: disk 'queue' count must be configured for explicit iothread to queue mapping" + - missing_iothread_mapping: + only coldplug..user_defined + queue_num = "3" + driver = {'name': 'qemu', 'queues': '${queue_num}'} + driver_iothreads = {'iothread': [{'queue': [{'id': '2'}], 'id': '1'}, {'queue': [{'id': '1'}], 'id': '2'}]} + err_msg = "unsupported configuration: missing iothread mapping for queue '0'" + - queue_id_out_of_range: + only coldplug..user_defined + queue_num = "2" + driver = {'name': 'qemu', 'queues': '${queue_num}'} + driver_iothreads = {'iothread': [{'queue': [{'id': '0'}], 'id': '1'}, {'queue': [{'id': '1'}], 'id': '2'}, {'queue': [{'id': '2'}], 'id': '3'}]} + err_msg = "unsupported configuration: disk iothread queue '${queue_num}'.*out of range" + - update_delete_iothread: + only coldplug..round_robin + status_error = yes + driver = {'name': 'qemu', 'type': 'qcow2'} + driver_iothreads = {'iothread': [{'id': '1'}, {'id': '2'}, {'id': '3'}]} + new_driver_iothreads = {'iothread': [{'id': '1'}, {'id': '2'}]} + del_iothread_id = 2 + check_qemu_pattern = + err_msg = "cannot remove IOThread ${del_iothread_id} since it is being used by disk" + variants plug_type: + - coldplug: + - hotplug: + new_target_dev = "vdb" + new_driver_iothreads = {'iothread': [{'id': '1'}, {'id': '2'}, {'id': '3'}]} + new_image_name = "hotplug_disk.qcow2" + new_target = {'dev': '${new_target_dev}', 'bus': 'virtio'} + new_source = {'attrs': {'file': '%s'}} + new_disk_dict = {'target': ${new_target}, 'device': 'disk', 'driver': {'name': 'qemu', 'type': 'qcow2'}, 'driver_iothreads': ${new_driver_iothreads}, 'source': ${new_source}} + check_libvirtd_log = '"driver":"virtio-blk-pci","iothread-vq-mapping":\[{"iothread":"iothread1"},{"iothread":"iothread2"},{"iothread":"iothread3"}\]' + log_level = "1" + variants disk_bus: + - virtio: + target = {'dev': '${target_dev}', 'bus': 'virtio'} + disk_dict = {'target': ${target}, 'device': 'disk', 'driver': ${driver}, 'driver_iothreads': ${driver_iothreads}} diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_iothreads_queue.py b/libvirt/tests/src/virtual_disks/virtual_disks_iothreads_queue.py new file mode 100755 index 00000000000..31738e9bef9 --- /dev/null +++ b/libvirt/tests/src/virtual_disks/virtual_disks_iothreads_queue.py @@ -0,0 +1,330 @@ +import os +import time + +from virttest import data_dir +from virttest import utils_disk +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.devices.disk import Disk +from virttest.utils_libvirt import libvirt_disk +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + + +def prepare_vm_xml(params, vmxml, test): + """ + Configure the XML definition of the VM + + :param params: dict, test parameters + :param vmxml: VMXML instance + :param test: test object + :return: updated VMXML instance + """ + vm_attrs = eval(params.get("vm_attrs")) + plug_type = params.get("plug_type") + vmxml.setup_attrs(**vm_attrs) + if plug_type == 'coldplug': + disk_dict = eval(params.get("disk_dict", "{}")) + if disk_dict: + libvirt_vmxml.modify_vm_device(vmxml, + 'disk', + dev_dict=disk_dict, + sync_vm=False) + test.log.debug("Updated vm xml is %s", vmxml) + return vmxml + + +def teardown_test(vm, params, vmxml, test): + """ + Clean up the test + + :param params: dict, test parameters + :param vm: VM instance + :param vmxml: VMXML instance + """ + if vm.is_alive(): + virsh.destroy(vm.name) + vmxml.sync() + disks = params.get('remove_disks', []) + for a_disk in disks: + libvirt.delete_local_disk("file", a_disk) + test.log.debug("Remove disk %s", a_disk) + + +def run_common(params, vmxml, test): + """ + Common test steps + + :param params: dict, test parameters + :param vmxml: VMXML instance + :param test: test object + """ + vm_name = params.get("main_vm") + virsh_dargs = {"debug": True, "ignore_status": False} + + test.log.debug("Step: define the vm") + virsh.define(vmxml.xml, **virsh_dargs) + test.log.debug("Step: start the vm") + virsh.start(vm_name, **virsh_dargs) + test.log.debug("After vm is started, " + "vm xml:%s\n", vm_xml.VMXML.new_from_dumpxml(vm_name)) + + +def run_test_define_invalid(vm, params, vmxml, test): + """ + Test vm definition with invalid configurations + + :param vm: vm instance + :param params: dict, test parameters + :param vmxml: VMXML instance + :param test: test object + """ + err_msg = params.get("err_msg") + virsh_dargs = {"debug": True, "ignore_status": True} + test.log.debug("Step: define the vm") + ret = virsh.define(vmxml.xml, **virsh_dargs) + libvirt.check_result(ret, expected_fails=err_msg) + + +def prepare_disk_for_hotplug(params): + """ + Prepare a disk object for hotplugging + + :param params: dict, test parameters + :return Disk: disk object + """ + new_image_name = params.get("new_image_name") + disk_source_path = \ + os.path.join(data_dir.get_data_dir(), new_image_name) + libvirt.create_local_disk("file", path=disk_source_path, + size="1", disk_format='qcow2') + params['remove_disks'] = [disk_source_path] + new_disk_dict = eval(params.get("new_disk_dict") % disk_source_path) + disk_obj = Disk(type_name='file') + disk_obj.setup_attrs(**new_disk_dict) + return disk_obj + + +def verify_hotplugged_disk(vm_name, params, session, old_part_list, test): + """ + Verify the hotplugged disk within the vm and in vm xml + + :param vm_name: str, vm name + :param params: dict, test parameters + :param session: ShellSession instance + :param old_part_list: list, disk partition list + :param test: test object + :return list: added partition list + """ + new_driver_iothreads = eval(params.get("new_driver_iothreads")) + added_part = utils_disk.get_added_parts(session, old_part_list) + if not added_part: + test.fail("Can not find the hotplugged disk in VM") + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + disks = vmxml.get_devices('disk') + if len(disks) < 2: + test.fail("Can not find the hotplugged disk in VM xml") + plugged_disk = vmxml.get_devices('disk')[1] + plugged_disk_driver_iothreads = plugged_disk.driver_iothreads.fetch_attrs() + if plugged_disk_driver_iothreads != new_driver_iothreads: + test.fail("Expect the plugged disk driver " + "iothreads to be '%s', " + "but found '%s'" % (new_driver_iothreads, + plugged_disk_driver_iothreads)) + test.log.debug("Verify: the disk driver iothreads information " + "is as expected after hotplugging - PASS") + return added_part + + +def verify_hotunplugged_disk(vm_name, params, added_part, session, test): + """ + Verify the hotplugged disk information within vm and vm xml + + :param vm_name: str, vm name + :param params: dict, test parameters + :param added_part: str, disk newly added, like vdb + :param session: ShellSession instance + :param test: test object + """ + new_target_dev = params.get("new_target_dev") + non_root_disks = libvirt_disk.get_non_root_disk_names(session, ignore_status=True) + if non_root_disks and added_part[0] in non_root_disks: + test.fail("The unplugged disk '%s' is still found in VM" % added_part) + test.log.debug("Verify: Check lsblk in VM after hotunlug the disk - PASS") + + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + current_disks = vmxml.get_devices('disk') + for a_disk in current_disks: + if a_disk.target['dev'] == new_target_dev: + test.fail("The hotunplugged disk '%s' is " + "still found in VM XML" % new_target_dev) + test.log.debug("Verify: Check hotplugged disk in " + "VM xml after unhotplug the disk - PASS") + + +def test_with_hotplug(vm, params, vmxml, test): + """ + Test hotplug unplug a disk with driver iothreads to the vm + + :param vm: vm instance + :param params: dict, test parameters + :param vmxml: VMXML instance + :param test: test object + """ + virsh_dargs = {"debug": True, "ignore_status": False} + vm_name = params.get("main_vm") + check_libvirtd_log = params.get("check_libvirtd_log") + new_target_dev = params.get("new_target_dev") + + run_common(params, vmxml, test) + session = vm.wait_for_login() + old_part_list = utils_disk.get_parts_list(session) + + test.log.debug("Step: prepare a disk") + disk_obj = prepare_disk_for_hotplug(params) + + test.log.debug("Step: hotplug the disk to the vm") + virsh.attach_device(vm_name, disk_obj.xml, **virsh_dargs) + time.sleep(20) + added_part = verify_hotplugged_disk(vm_name, + params, + session, + old_part_list, + test) + libvirtd_log_file = os.path.join(test.debugdir, "libvirtd.log") + libvirt.check_logfile(check_libvirtd_log, libvirtd_log_file) + test.log.debug("Verify: Check libvirtd log - PASS") + + test.log.debug("Step: unhotplug the disk from the vm") + virsh.detach_disk(vm_name, new_target_dev, wait_for_event=True, **virsh_dargs) + verify_hotunplugged_disk(vm_name, params, added_part, session, test) + + +def test_with_coldplug(vm, params, vmxml, test): + """ + Test coldplug a disk (define) with driver iothreads to the vm + + :param vm: vm instance + :param params: dict, test parameters + :param vmxml: VMXML instance + :param test: test object + """ + driver_conf = eval(params.get("driver", "{}")) + driver_iothreads_conf = eval(params.get("driver_iothreads", "{}")) + check_qemu_pattern = params.get("check_qemu_pattern") + + run_common(params, vmxml, test) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm.name) + first_disk = vmxml.get_devices('disk')[0] + expect_value = driver_conf.get("queues", '') + if expect_value and first_disk.driver.get("queues") != expect_value: + test.fail("Expect the disk driver " + "'queues' to be '%s', " + "but found '%s'" % (expect_value, + first_disk.driver.get("queues"))) + test.log.debug("Verify: Check disk driver queues number - PASS") + actual_driver_iothreads = first_disk.driver_iothreads.fetch_attrs() + if driver_iothreads_conf and actual_driver_iothreads != driver_iothreads_conf: + test.fail("Expect the disk " + "driver iothreads to be '%s', " + "but found '%s'" % (driver_iothreads_conf, + actual_driver_iothreads)) + test.log.debug("Verify: Check disk driver iothreads - PASS") + if check_qemu_pattern: + libvirt.check_qemu_cmd_line(check_qemu_pattern) + + +def run_test_define_start(vm, params, vmxml, test): + """ + Test define and start vm with specified driver iothreads configuration + + :param vm: vm instance + :param params: dict, test parameters + :param vmxml: VMXML instance + :param test: test object + """ + plug_type = params.get("plug_type") + if plug_type == "coldplug": + test_with_coldplug(vm, params, vmxml, test) + else: + test_with_hotplug(vm, params, vmxml, test) + + +def run_test_update_delete_iothread(vm, params, vmxml, test): + """ + Test to delete an iothread being used by a disk and + update the disk with new driver iothreads information + + :param vm: vm instance + :param params: dict, test parameters + :param vmxml: VMXML instance + :param test: test object + """ + def _get_driver_iothreads(vmxml): + """ + Utility function for getting the device object and driver iothreads + + :param vmxml: VMXML instance + :return tuple: device xml object, dict of driver_iothreads + """ + dev_obj, _ = libvirt.get_vm_device(vmxml, 'disk') + iothreads = dev_obj.driver_iothreads + return dev_obj, iothreads + + vm_name = params.get("main_vm") + err_msg = params.get("err_msg") + del_iothread_id = params.get("del_iothread_id") + old_driver_iothreads = eval(params.get("driver_iothreads")) + new_driver_iothreads = eval(params.get("new_driver_iothreads")) + virsh_dargs = {"debug": True, "ignore_status": True} + + run_common(params, vmxml, test) + test.log.debug("Step: delete an iothread") + ret = virsh.iothreaddel(vm_name, del_iothread_id, **virsh_dargs) + libvirt.check_result(ret, expected_fails=err_msg) + + test.log.debug("Step: update the disk with new driver iothreads") + dev_obj, iothreads = _get_driver_iothreads(vmxml) + iothreads.update(**new_driver_iothreads) + dev_obj.driver_iothreads = iothreads + test.log.debug("After updated with driver iothreads, " + "the disk is:\n%s", dev_obj) + ret = virsh.update_device(vm_name, dev_obj.xml, **virsh_dargs) + updated_vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + _, new_iothreads = _get_driver_iothreads(updated_vmxml) + if new_iothreads.fetch_attrs() != old_driver_iothreads: + test.fail("Expect driver iothreads in the disk " + "to be '%s', but found '%s'" % (old_driver_iothreads, + new_iothreads.fetch_attrs())) + else: + test.log.debug("Verify: the disk's driver iothreads " + "is not changed - PASS") + libvirt.check_exit_status(ret, True) + + +def run(test, params, env): + """ + Test disk driver iothreads + + 1.Update vm xml using given parameters + 2.Perform test operation and verify checkpoints + 3.Recover test environment + """ + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vmxml_backup = vmxml.copy() + test_scenario = params.get("scenario") + case_name = "run_test_%s" % test_scenario + run_test_case = eval(case_name) + try: + if vm.is_alive(): + vm.destroy() + test.log.info("Step: Prepare VM XML") + vmxml = prepare_vm_xml(params, vmxml, test) + run_test_case(vm, params, vmxml, test) + + finally: + teardown_test(vm, params, vmxml_backup, test) From 27a938bd75c45cac719ed4a80e3aab5149862800 Mon Sep 17 00:00:00 2001 From: nanli Date: Mon, 1 Apr 2024 20:26:25 +0800 Subject: [PATCH 0311/1055] add case for delete snapshot metadata xxxx-298194:delete snapshot's metadata Signed-off-by: nanli --- .../cfg/snapshot/delete_snapshot_metadata.cfg | 19 +++ .../src/snapshot/delete_snapshot_metadata.py | 115 ++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 libvirt/tests/cfg/snapshot/delete_snapshot_metadata.cfg create mode 100644 libvirt/tests/src/snapshot/delete_snapshot_metadata.py diff --git a/libvirt/tests/cfg/snapshot/delete_snapshot_metadata.cfg b/libvirt/tests/cfg/snapshot/delete_snapshot_metadata.cfg new file mode 100644 index 00000000000..602037d0847 --- /dev/null +++ b/libvirt/tests/cfg/snapshot/delete_snapshot_metadata.cfg @@ -0,0 +1,19 @@ +- snapshot_delete.metadata: + type = delete_snapshot_metadata + start_vm = no + snap_name = ['s1', 's2', 's3'] + func_supported_since_libvirt_ver = (9, 10, 0) + del_option = " --metadata" + variants disk_format: + - type_qcow2: + format = "qcow2" + disk_type = "file" + original_disk = 'vda' + new_disk = "vdb" + disk_driver = {'driver': {'name': 'qemu', 'type': '${format}'}} + disk_target = {'target': {'dev': '${new_disk}', 'bus': 'virtio'}} + disk_dict = {"type_name": '${disk_type}', 'device': 'disk', **${disk_target}, **${disk_driver}} + mem_path = "/tmp/mem.s" + disk_path = "/tmp/vdb.s" + snap_options = "%s --diskspec vda,snapshot=no --diskspec vdb,snapshot=external,file=${disk_path}%d --memspec snapshot=external,file=${mem_path}%d" + diff --git a/libvirt/tests/src/snapshot/delete_snapshot_metadata.py b/libvirt/tests/src/snapshot/delete_snapshot_metadata.py new file mode 100644 index 00000000000..291e71ed6f1 --- /dev/null +++ b/libvirt/tests/src/snapshot/delete_snapshot_metadata.py @@ -0,0 +1,115 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import os + +from virttest import libvirt_version +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_disk + +from provider.snapshot import snapshot_base +from provider.virtual_disk import disk_base + +virsh_dargs = {"debug": True, "ignore_status": False} + + +def check_source_and_mem_file(test, params, new_disk_source, disk_files, mem_files): + """ + Check current vm two disks source path and mem file. + + :param: test: test object. + :param params: Dictionary with the test parameters + :param: new_disk_source: source path of new disk. + :param: disk_files: disk source files. + :param: mem_file: memory snapshot files. + """ + new_disk = params.get("new_disk") + original_disk = params.get("original_disk") + disk_type = params.get("disk_type") + original_disk_source = params.get("original_disk_source") + + vmxml = vm_xml.VMXML.new_from_dumpxml(params.get("main_vm")) + test.log.debug("Get current xml is :%s", vmxml) + + disk1_sources = disk_base.DiskBase.get_source_list(vmxml, disk_type, original_disk)[0] + disk2_sources = disk_base.DiskBase.get_source_list(vmxml, disk_type, new_disk)[::-1] + if disk1_sources != original_disk_source: + test.fail("Expect to get '%s' in system disk instead of '%s'" % ( + original_disk_source, disk1_sources)) + test.log.debug('Check system disk source list success') + if disk2_sources != [new_disk_source] + disk_files: + test.fail("Expect to get '%s' in new disk but get '%s'" % ( + [new_disk_source] + disk_files, disk2_sources)) + test.log.debug('Check the new disk source list success') + + for mf in mem_files: + if not os.path.exists(mf): + test.fail("Mem file '%s' does not exist" % mf) + + +def run(test, params, env): + """ + Test deleting snapshot's metadata. + """ + + def run_test(): + """ + Test deleting snapshot's metadata. + """ + del_option = params.get('del_option') + snap_name = eval(params.get("snap_name")) + snap_options = params.get("snap_options") + mem_path = params.get("mem_path") + disk_path = params.get("disk_path") + disk_dict = eval(params.get("disk_dict")) + disk_type = params.get("disk_type") + + test.log.info("TEST_STEP1: Prepare a new disk vdb") + new_disk_source = disk_obj.add_vm_disk(disk_type, disk_dict) + virsh.start(vm_name, **virsh_dargs) + vm.wait_for_login().close() + + test.log.info("TEST_STEP2:Create 3 external disk+memory snapshots," + "check the new disk source list and memory snapshot file.") + mem_files, disk_files = [], [] + for index, sname in enumerate(snap_name): + virsh.snapshot_create_as(vm_name, snap_options % (sname, index + 1, + index + 1), + **virsh_dargs) + mem_files.append(mem_path + str(index + 1)) + disk_files.append(disk_path + str(index + 1)) + check_source_and_mem_file(test, params, new_disk_source, disk_files, mem_files) + + test.log.info("TEST_STEP3: Delete the first snapshot with --metadata" + "check the new disk source list and memory snapshot file.") + virsh.snapshot_delete(vm_name, snap_name[0], options=del_option, **virsh_dargs) + check_source_and_mem_file(test, params, new_disk_source, disk_files, mem_files) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + test_obj.teardown_test() + + libvirt_version.is_libvirt_feature_supported(params) + try: + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + params['backup_vmxml'] = original_xml.copy() + params.update({"original_disk_source": libvirt_disk.get_first_disk_source(vm)}) + test_obj = snapshot_base.SnapshotTest(vm, test, params) + disk_obj = disk_base.DiskBase(test, vm, params) + + run_test() + + finally: + teardown_test() From edce2ec8e3446d539cc8b26a25f8b43e4471084c Mon Sep 17 00:00:00 2001 From: nanli Date: Mon, 8 Apr 2024 20:07:18 +0800 Subject: [PATCH 0312/1055] add case for delete snap after disk attached xxxx-298191: delete snapshot after disk attached Signed-off-by: nanli --- .../delete_snapshot_after_disk_attached.cfg | 15 ++ .../delete_snapshot_after_disk_attached.py | 137 ++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 libvirt/tests/cfg/snapshot/delete_snapshot_after_disk_attached.cfg create mode 100644 libvirt/tests/src/snapshot/delete_snapshot_after_disk_attached.py diff --git a/libvirt/tests/cfg/snapshot/delete_snapshot_after_disk_attached.cfg b/libvirt/tests/cfg/snapshot/delete_snapshot_after_disk_attached.cfg new file mode 100644 index 00000000000..2fa03e263bf --- /dev/null +++ b/libvirt/tests/cfg/snapshot/delete_snapshot_after_disk_attached.cfg @@ -0,0 +1,15 @@ +- snapshot_delete.disk_attached: + type = delete_snapshot_after_disk_attached + func_supported_since_libvirt_ver = (9, 10, 0) + start_vm = yes + snap_names = ['s1', 's2', 's3','s4'] + disk1 = 'vda' + disk1_snap_option = " %s --disk-only" + disk2 = 'vdb' + mem_path = "/tmp/mem." + snap_deleting_ongoing_tag = "" + disk2_snap_option = "%s --memspec ${mem_path}%s,snapshot=external --diskspec ${disk1},snapshot=external ${disk2},snapshot=external" + disk_type = 'file' + disk_driver = {'driver': {'name': 'qemu', 'type': 'qcow2'}} + disk_target = {'target': {'dev': '${disk2}', 'bus': 'virtio'}} + disk_dict = {"type_name": '${disk_type}', 'device': 'disk', **${disk_target}, **${disk_driver}} diff --git a/libvirt/tests/src/snapshot/delete_snapshot_after_disk_attached.py b/libvirt/tests/src/snapshot/delete_snapshot_after_disk_attached.py new file mode 100644 index 00000000000..784b7076e7d --- /dev/null +++ b/libvirt/tests/src/snapshot/delete_snapshot_after_disk_attached.py @@ -0,0 +1,137 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import os +import re + +from virttest import libvirt_version +from virttest import virsh +from virttest.libvirt_xml import vm_xml + +from provider.snapshot import snapshot_base +from provider.virtual_disk import disk_base + +virsh_dargs = {"debug": True, "ignore_status": False} + + +def check_guest_domblklist(test, params, vm_name): + """ + Check current guest domblklist. + + :params: test, test object. + :params: params, cfg parameter dict. + :params: vm_name, guest name. + """ + disk_type = params.get('disk_type') + disk1, disk2 = params.get("disk1"), params.get("disk2") + + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + test.log.debug("Current vm xml is %s\n", vmxml) + disk1_sources = disk_base.DiskBase.get_source_list(vmxml, disk_type, disk1)[::-1] + disk2_sources = disk_base.DiskBase.get_source_list(vmxml, disk_type, disk2)[::-1] + if disk2_sources: + pattern = [r'%s\s*%s' % (disk1, disk1_sources[-1]), + r'%s\s*%s' % (disk2, disk2_sources[-1])] + else: + pattern = [r'%s\s*%s' % (disk1, disk1_sources[-1])] + + domblk_res = virsh.domblklist(vm_name, **virsh_dargs).stdout_text.strip() + for pat in pattern: + if not re.search(pat, domblk_res): + test.fail('Expected to get "%s" in "%s"' % (pat, domblk_res)) + + +def run(test, params, env): + """ + Verify deleting snapshot after disk attached. + """ + def run_test(): + """ + Verify deleting snapshot after disk attached. + """ + vm_name = params.get("main_vm") + original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + params['backup_vmxml'] = original_xml.copy() + vm = env.get_vm(vm_name) + disk_type = params.get('disk_type') + snap_names = eval(params.get("snap_names", '[]')) + mem_path = params.get("mem_path") + disk1_snap_option = params.get("disk1_snap_option") + disk2_snap_option = params.get("disk2_snap_option") + disk_type, disk_dict = params.get("disk_type"), eval(params.get("disk_dict", '{}')) + disk1, disk2 = params.get("disk1"), params.get("disk2") + snap_deleting_ongoing_tag = params.get("snap_deleting_ongoing_tag") + + test.log.info("TEST_STEP1:Start guest with just system disk.") + vm.wait_for_login().close() + check_guest_domblklist(test, params, vm_name) + + test.log.info("TEST_STEP2: Create two disk only snaps for guest") + for sname in snap_names[0:2]: + virsh.snapshot_create_as(vm.name, disk1_snap_option % sname, + **virsh_dargs) + + test.log.info("TEST_STEP3: Attach a virtual disk ") + new_disk, disk2_path = disk_obj.prepare_disk_obj(disk_type, disk_dict) + virsh.attach_device(vm_name, new_disk.xml, **virsh_dargs) + check_guest_domblklist(test, params, vm_name) + + test.log.info("TEST_STEP4: Create disk and mem snapshot for new disk") + virsh.snapshot_create_as(vm_name, disk2_snap_option % ( + snap_names[2], snap_names[2]), **virsh_dargs) + check_guest_domblklist(test, params, vm_name) + if not os.path.exists(mem_path + snap_names[2]): + test.fail("Mem file '%s' does not exist" % mem_path + snap_names[2]) + + test.log.info("TEST_STEP5: Create disk only snapshot for guest.") + virsh.snapshot_create_as(vm.name, disk1_snap_option % snap_names[3], + **virsh_dargs) + check_guest_domblklist(test, params, vm_name) + + test.log.info("TEST_STEP6: Delete the third snap and check it " + "actually removed") + virsh.snapshot_delete(vm_name, snap_names[2], **virsh_dargs) + test_obj.check_snap_list(snap_names[2], expect_exist=False) + + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + disk2_sources = disk_obj.get_source_list(vmxml, disk_type, disk2) + snap3_path = disk2_path + ".%s" % snap_names[2] + if snap3_path in disk2_sources: + test.fail("Expect '%s' does not exist in new disk source list '%s'" % ( + snap3_path, disk2_sources)) + + expect_path = os.path.join(mem_path, snap_names[2]) + if os.path.exists(expect_path): + test.fail("Expect the mem file '%s' does not exist, but still found" % expect_path) + + snap_xml = virsh.snapshot_dumpxml( + vm_name, snap_names[1], **virsh_dargs).stdout_text.strip("\n") + if re.search(snap_deleting_ongoing_tag, snap_xml): + test.fail("Expect no '%s' in guest xml, but still found" % snap_deleting_ongoing_tag) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + test_obj.teardown_test() + disk_type = params.get('disk_type') + disk_obj.cleanup_disk_preparation(disk_type) + + vm = env.get_vm(params.get("main_vm")) + test_obj = snapshot_base.SnapshotTest(vm, test, params) + disk_obj = disk_base.DiskBase(test, vm, params) + + libvirt_version.is_libvirt_feature_supported(params) + + try: + run_test() + + finally: + teardown_test() From a5a7050f7b9c11259621d0f9452ccfb9fea04579 Mon Sep 17 00:00:00 2001 From: nanli Date: Fri, 19 Apr 2024 13:09:57 +0800 Subject: [PATCH 0313/1055] add case for snap revert with flags xxxx-300469:Revert snapshots with different flags Signed-off-by: nanli --- .../cfg/snapshot/revert_snap_with_flags.cfg | 12 +++ .../src/snapshot/revert_snap_with_flags.py | 99 +++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 libvirt/tests/cfg/snapshot/revert_snap_with_flags.cfg create mode 100644 libvirt/tests/src/snapshot/revert_snap_with_flags.py diff --git a/libvirt/tests/cfg/snapshot/revert_snap_with_flags.cfg b/libvirt/tests/cfg/snapshot/revert_snap_with_flags.cfg new file mode 100644 index 00000000000..1c2a377b5ae --- /dev/null +++ b/libvirt/tests/cfg/snapshot/revert_snap_with_flags.cfg @@ -0,0 +1,12 @@ +- snapshot_revert.with_flags: + type = revert_snap_with_flags + start_vm = no + snap_names = ['s1', 's2'] + target_disk = 'vda' + disk_type = 'file' + vars_path = "/var/lib/libvirt/qemu/nvram/${main_vm}_VARS.fd" + snap1_options = "%s --diskspec vda,snapshot=external,file=/tmp/vda.%s" + snap2_options = "%s --memspec snapshot=external,file=/tmp/mem.%s --diskspec vda,snapshot=external,file=/tmp/vda.%s" + flags = [" --current --paused"," --running --reset-nvram", " --force"] + func_supported_since_libvirt_ver = (9, 10, 0) + diff --git a/libvirt/tests/src/snapshot/revert_snap_with_flags.py b/libvirt/tests/src/snapshot/revert_snap_with_flags.py new file mode 100644 index 00000000000..f4569163076 --- /dev/null +++ b/libvirt/tests/src/snapshot/revert_snap_with_flags.py @@ -0,0 +1,99 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import re + +from avocado.utils import process + +from virttest import libvirt_version +from virttest import virsh +from virttest.libvirt_xml import vm_xml + +from provider.snapshot import snapshot_base + + +def check_vm_state_in_dom_list(test, vm_name, vm_state): + """ + Check vm state in virsh domain list. + + :param test: test object. + :param vm_name: vm name. + :param vm_state: expected vm state. + """ + doms = virsh.dom_list("--all", debug=True).stdout.strip() + if not re.search(r".*%s.*%s.*" % (vm_name, vm_state), doms): + test.fail( + "VM '%s' with the state %s is not found" % (vm_name, vm_state)) + + +def run(test, params, env): + """ + Revert snapshot for guest with different flags. + """ + def run_test(): + """ + Revert snapshot with --current --paused --running + --reset-nvram --force in order. + """ + test.log.info("TEST_STEP1:Prepare shutoff guest and create a snapshot.") + virsh.snapshot_create_as(vm_name, + snap1_options % (snap_names[0], snap_names[0]), + **virsh_dargs) + test_obj.check_snap_list(snap_names[0]) + + test.log.info("TEST_STEP2:Start guest and create a snapshot.") + vm.start() + vm.wait_for_login().close() + virsh.snapshot_create_as(vm_name, snap2_options % ( + snap_names[1], snap_names[1], snap_names[1]), **virsh_dargs) + test_obj.check_snap_list(snap_names[1]) + + test.log.info("TEST_STEP3: Revert to the second snap.") + virsh.snapshot_revert(vm_name, revert_flags[0], **virsh_dargs) + check_vm_state_in_dom_list(test, vm_name, vm_state="paused") + + test.log.info("TEST_STEP4: Revert snapshot to the first snap") + vars_hash1 = process.run("sha256sum %s" % vars_path, ignore_status=False) + virsh.snapshot_revert(vm_name, snap_names[0], + options=revert_flags[1], **virsh_dargs) + vars_hash2 = process.run("sha256sum %s" % vars_path, ignore_status=False) + if vars_hash1 == vars_hash2: + test.fail("Expect to get different hash values for '%s', " + "but got both '%s' " % (vars_path, vars_hash1)) + + test.log.info("TEST_STEP5: Revert snapshot to the second snap force") + virsh.snapshot_revert(vm_name, snap_names[1], + options=revert_flags[2], **virsh_dargs) + check_vm_state_in_dom_list(test, vm_name, vm_state="running") + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + snap_names.reverse() + test_obj.teardown_test() + + libvirt_version.is_libvirt_feature_supported(params) + vm_name = params.get("main_vm") + original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + params['backup_vmxml'] = original_xml.copy() + vm = env.get_vm(vm_name) + virsh_dargs = {"debug": True, "ignore_status": False} + snap_names = eval(params.get("snap_names", '[]')) + revert_flags = eval(params.get("flags", "[]")) + vars_path = params.get("vars_path") + snap1_options, snap2_options = params.get("snap1_options"), params.get('snap2_options') + test_obj = snapshot_base.SnapshotTest(vm, test, params) + + try: + run_test() + + finally: + teardown_test() From 691645d2ae3f0abf55bb9a8ce14ae6940cc1c3d1 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Tue, 30 Apr 2024 09:31:36 +0800 Subject: [PATCH 0314/1055] v2v:add TC "Extend virt-v2v option for LUKS - implement --key all:" Signed-off-by: vwu-vera --- v2v/tests/cfg/function_test_esx.cfg | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 18f6baf0382..5b41f1097e3 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -723,6 +723,19 @@ luks_keys = LUkS_DEV_INVALID_KEYS_FILE expect_msg = 'yes' msg_content = 'virt-v2v: fopen: \S+: No such file or directory' + - keys_all: + only esx_70 + version_required = "[virt-v2v-2.3.7-2,)" + main_vm = VM_NAME_ROOT_SWAP_2LUKS_V2V_EXAMPLE + checkpoint = 'luks_dev_keys' + skip_vm_check = yes + skip_reason = 'luks encryped, cannot boots up without password' + variants: + - luks_all_key: + luks_keys = LUKS_ALL_KEYS + - luks_clevis: + luks_keys = LUKS_UUID_KEYS + v2v_opts += "--key all:clevis" - win_bitlocker: only esx_70 version_required = "[virt-v2v-1.42.0-15,)" From 97be187569995837b657bf93ad584a4c413bef26 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Tue, 30 Apr 2024 15:55:44 +0800 Subject: [PATCH 0315/1055] Add nbdkit cases about evil and tar filter Signed-off-by: Ming Xie --- v2v/tests/cfg/nbdkit/nbdkit.cfg | 12 +++++++++ v2v/tests/src/nbdkit/nbdkit.py | 43 +++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/v2v/tests/cfg/nbdkit/nbdkit.cfg b/v2v/tests/cfg/nbdkit/nbdkit.cfg index 46d1cab99dd..5f07038b81b 100644 --- a/v2v/tests/cfg/nbdkit/nbdkit.cfg +++ b/v2v/tests/cfg/nbdkit/nbdkit.cfg @@ -69,6 +69,18 @@ version_required = "[nbdkit-server-1.36.2-1,)" checkpoint = 'partition_sectorsize' guest_images = 'SECTORSIZE_IMAGES_NFS_V2V_EXAMPLE' + - evil: + version_required = "[nbdkit-server-1.36.1-1,)" + option_evil = 'cosmic-rays stuck-bits stuck-wires' + option_evil_probability = '0.001 1e-6 1:1000000 3.33:100000 1%' + option_evil_seed = '0 1 10000000' + option_evil_stuck_probability = '0.01 0.5 1 20% 100%' + checkpoint = 'test_evil_filter' + - tar: + version_required = "[nbdkit-server-1.36.1-1,)" + option_tar_limit = '0 100K 100G' + option_tar_entry = '0 latest-rhel9.img fake-entry' + checkpoint = 'test_tar_filter' - plugin: variants: - file: diff --git a/v2v/tests/src/nbdkit/nbdkit.py b/v2v/tests/src/nbdkit/nbdkit.py index f11feb2c602..3e70fea5f58 100644 --- a/v2v/tests/src/nbdkit/nbdkit.py +++ b/v2v/tests/src/nbdkit/nbdkit.py @@ -645,6 +645,45 @@ def ones_byte(): if size == '256' and not re.search('could not parse number', cmd.stderr_text): test.fail('fail to test ones plugin with byte=256') + def test_evil_filter(): + tmp_path = data_dir.get_tmp_dir() + image_path = os.path.join(tmp_path, 'latest-rhel9.img') + process.run('qemu-img convert -f qcow2 -O raw /var/lib/avocado/data/avocado-vt/images/jeos-27-x86_64.qcow2' + ' %s' % image_path, shell=True) + option_evil = params_get(params, "option_evil") + option_evil_probability = params_get(params, "option_evil_probability") + option_evil_seed = params_get(params, "option_evil_seed") + option_evil_stuck_probability = params_get(params, "option_evil_stuck_probability") + for mode in list(option_evil.split(' ')): + for probability in list(option_evil_probability.split(' ')): + for seed in list(option_evil_seed.split(' ')): + for stuck_probability in list(option_evil_stuck_probability.split(' ')): + cmd = process.run("nbdkit --filter=evil file %s evil=%s evil-probability=%s evil-seed=%s " + "evil-stuck-probability=%s --run 'nbdcopy -p $uri null:'" % + (image_path, mode, probability, seed, stuck_probability), + shell=True, ignore_status=True) + output = cmd.stdout_text + cmd.stderr_text + if re.search('nbdkit.*error', output): + test.fail('fail to test evil filter') + + def test_tar_filter(): + tmp_path = data_dir.get_tmp_dir() + image_path = os.path.join(tmp_path, 'latest-rhel9.img') + process.run('qemu-img convert -f qcow2 -O raw /var/lib/avocado/data/avocado-vt/images/jeos-27-x86_64.qcow2' + ' %s' % image_path, shell=True) + process.run('cd %s ; tar cvf latest-rhel9-image.tar latest-rhel9.img' % tmp_path, shell=True) + option_tar_limit = params_get(params, "option_tar_limit") + option_tar_entry = params_get(params, "option_tar_entry") + for limit in list(option_tar_limit.split(' ')): + for entry in list(option_tar_entry.split(' ')): + cmd = process.run(" nbdkit file %s/latest-rhel9-image.tar --filter=tar tar-entry=%s tar-limit=%s " + "--run 'nbdcopy -p $uri null:'" % (tmp_path, entry, limit), shell=True, ignore_status=True) + output = cmd.stdout_text + cmd.stderr_text + if entry == 'latest-rhel9.img' and re.search('nbdkit.*error', output): + test.fail('fail to test tar filter') + elif entry != 'latest-rhel9.img' and not re.search('nbdkit.*error', output): + test.fail('fail to test tar filter') + if version_required and not multiple_versions_compare( version_required): test.cancel("Testing requires version: %s" % version_required) @@ -710,5 +749,9 @@ def ones_byte(): partition_sectorsize() elif checkpoint == 'ones_byte': ones_byte() + elif checkpoint == 'test_evil_filter': + test_evil_filter() + elif checkpoint == 'test_tar_filter': + test_tar_filter() else: test.error('Not found testcase: %s' % checkpoint) From ea21882dc446b3677f8f090cebd5357898193dd5 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 24 Apr 2024 11:01:36 +0800 Subject: [PATCH 0316/1055] virtual_disks: Add a vhostvdpa disk nodedev test This PR adds: VIRT-300446 - Test nodedev related operations against vhostvdpa disk Signed-off-by: Yingshun Cui --- .../nodedev_vhostvdpa_disk.cfg | 6 +++ .../nodedev_vhostvdpa_disk.py | 50 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/nodedev_vhostvdpa_disk.cfg create mode 100644 libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/nodedev_vhostvdpa_disk.py diff --git a/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/nodedev_vhostvdpa_disk.cfg b/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/nodedev_vhostvdpa_disk.cfg new file mode 100644 index 00000000000..5a548bbcd6a --- /dev/null +++ b/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/nodedev_vhostvdpa_disk.cfg @@ -0,0 +1,6 @@ +- virtual_disks.vhostvdpa.nodedev: + type = nodedev_vhostvdpa_disk + start_vm = no + simulator = "yes" + func_supported_since_libvirt_ver = (9, 10, 0) + only x86_64 diff --git a/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/nodedev_vhostvdpa_disk.py b/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/nodedev_vhostvdpa_disk.py new file mode 100644 index 00000000000..8016649d5ce --- /dev/null +++ b/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/nodedev_vhostvdpa_disk.py @@ -0,0 +1,50 @@ +from virttest import libvirt_version +from virttest import utils_vdpa +from virttest import virsh +from virttest.libvirt_xml import nodedev_xml + +VIRSH_ARGS = {'debug': True, 'ignore_status': False} + + +def run(test, params, env): + """ + Verify nodedev related operations against vhost-vdpa disk. + """ + def check_nodedev_xml(dev_name): + """ + Check nodedev xml for vhost-vdpa device. + + :param dev_name: Device name + """ + test.log.info(f"TEST_STEP: Check xml for node device - {dev_name}.") + nodexml = nodedev_xml.NodedevXML.new_from_dumpxml(dev_name) + nodedev_attrs = nodexml.fetch_attrs() + idx = nodedev_attrs["path"][-1] + exp_attrs = {"driver_name": "vhost_vdpa", "cap_type": "vdpa", + "cap": {"chardev": f"/dev/vhost-vdpa-{idx}"}} + test.log.debug(f"Exptected: {exp_attrs}") + test.log.debug(f"Actual: {nodedev_attrs}") + for k, v in exp_attrs.items(): + if nodedev_attrs.get(k) != v: + test.fail("Failed to check node device xml!") + + libvirt_version.is_libvirt_feature_supported(params) + + try: + test.log.info("TEST_STEP: Prepare vhost-vdpa disks.") + test_env_obj = utils_vdpa.VDPASimulatorTest( + sim_dev_module="vdpa_sim_blk", mgmtdev="vdpasim_blk") + test_env_obj.setup(dev_num=2) + + test.log.info("TEST_STEP: List node devices with vdpa capability on host.") + vdpa_devices = [d for d in test_env_obj.get_vdpa_dev_info()['dev']] + devs = virsh.nodedev_list( + cap="vdpa", **VIRSH_ARGS).stdout_text.strip().splitlines() + if devs != ["vdpa_" + d for d in vdpa_devices]: + test.fail("Failed to get vdpa devices!") + + for dev_name in devs: + check_nodedev_xml(dev_name) + + finally: + test_env_obj.cleanup() From 01fd28a8149e3aebd9bcb1f92fe4f18dbe3cd957 Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 6 May 2024 16:45:51 +0800 Subject: [PATCH 0317/1055] migration: Fix parameter issue Missing 'postcopy_options' in action_during_mig parameter. Signed-off-by: lcheng --- libvirt/tests/cfg/migration/async_job/migration_domjobinfo.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration/async_job/migration_domjobinfo.cfg b/libvirt/tests/cfg/migration/async_job/migration_domjobinfo.cfg index 18b8a5910ee..1ffb3bb651a 100644 --- a/libvirt/tests/cfg/migration/async_job/migration_domjobinfo.cfg +++ b/libvirt/tests/cfg/migration/async_job/migration_domjobinfo.cfg @@ -42,5 +42,5 @@ - with_postcopy: postcopy_options = '--postcopy --timeout 10 --timeout-postcopy' expected_domjobinfo = {"src_items": {"str_items": {"Job type": "Unbounded", "Operation": "Outgoing migration"}, "all_items": ["Time elapsed", "Data processed", "Data remaining", "Data total", "Memory processed", "Memory remaining", "Memory total", "Memory bandwidth", "Dirty rate", "Page size", "Iteration", "Postcopy requests", "Constant pages", "Normal pages", "Normal data", "Expected downtime", "Setup time"]}, "dest_items": {"error_msg": "migration statistics are available only on the source host"}} - action_during_mig = [{"func": "libvirt_monitor.check_domjobinfo_output", "after_event": "iteration: '1'", "func_param": {"vm_name": "${main_vm}", "expected_domjobinfo": ${expected_domjobinfo}, "remote_ip": "${server_ip}"}, "need_sleep_time": "15"}, {"func": "set_migrate_speed_to_high", "func_param": "params"}] + action_during_mig = [{"func": "libvirt_monitor.check_domjobinfo_output", "after_event": "iteration: '1'", "func_param": {"vm_name": "${main_vm}", "expected_domjobinfo": ${expected_domjobinfo}, "postcopy_options": "${postcopy_options}", "remote_ip": "${server_ip}"}, "need_sleep_time": "15"}, {"func": "set_migrate_speed_to_high", "func_param": "params"}] expected_domjobinfo_complete = {"src_items": {"str_items": {"Job type": "Completed", "Operation": "Outgoing migration"}, "int_items": {"Memory remaining": "0", "Data remaining": "0", "Dirty rate": "0"}, "all_items": ["Time elapsed", "Data processed", "Data total", "Memory processed", "Memory total", "Memory bandwidth", "Page size", "Iteration", "Postcopy requests", "Constant pages", "Normal pages", "Normal data", "Total downtime", "Setup time"]}, "dest_items": {"str_items": {"Job type": "None"}}} From a3b4c3d28e7caa2467724dd1dcc1e27a8de2fdc9 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Mon, 6 May 2024 17:26:07 +0800 Subject: [PATCH 0318/1055] v2v: fix the issue "failed to install virtio drivers on rhel8.10" Signed-off-by: vwu-vera --- provider/v2v_vmcheck_helper.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/provider/v2v_vmcheck_helper.py b/provider/v2v_vmcheck_helper.py index 1941157fdb9..e99d168cba2 100644 --- a/provider/v2v_vmcheck_helper.py +++ b/provider/v2v_vmcheck_helper.py @@ -37,7 +37,8 @@ 'virtio_rng': '2.6.26', 'cache_none': 'virt-v2v-1.42.0-4', 'q35': 'virt-v2v-1.43.3-2', - 'virtio_model': 'virt-v2v-1.45.97-4'} + 'virtio_model': 'virt-v2v-1.45.97-4', + 'virtio_skip': 'virt-v2v-2.0.0-1'} # bz#1961107 V2V_ADAPTE_SPICE_REMOVAL_VER = "[virt-v2v-1.45.92,)" V2V_VSOCK_SUPPORT_LINUX_VER = "[virt-v2v-2.0.2-1,)" @@ -783,6 +784,11 @@ def check_windows_vm(self): self.log_err(err_msg) # Check Red Hat VirtIO drivers and display adapter + if not compare_version(FEATURE_SUPPORT['virtio_skip']): + reason = "Unsupported if v2v < %s" % FEATURE_SUPPORT['virtio_skip'] + LOG.info('Skip Checking VirtIO drivers: %s' % reason) + return + LOG.info("Checking VirtIO drivers and display adapter") expect_video = self.get_expect_video_model() has_virtio_win, has_qxldod = self.get_virtio_win_config() From a5f14a579e553f1dad449689146ca17c118618a6 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Tue, 7 May 2024 00:16:42 +0800 Subject: [PATCH 0319/1055] Fix a ova file path mistake Signed-off-by: Ming Xie --- v2v/tests/src/convert_from_file.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/v2v/tests/src/convert_from_file.py b/v2v/tests/src/convert_from_file.py index bc2975aa27f..2c0a96bbc67 100644 --- a/v2v/tests/src/convert_from_file.py +++ b/v2v/tests/src/convert_from_file.py @@ -265,8 +265,9 @@ def vm_check(): shutil.copy(src_dir, dest_dir) LOG.info('Copy ova from %s to %s', src_dir, dest_dir) if checkpoint == 'cpu_topology': - dest_ova = os.path.join(dest_dir, input_file) - process.run('tar xvf %s -C %s' % (dest_ova, dest_dir), shell=True) + ova_file = params.get('ova_file_name') + dest_ova = os.path.join(dest_dir, ova_file) + process.run('tar xvf %s -C %s' % (input_file, dest_dir), shell=True) with open(dest_ova[:-1] + 'f') as fd: buf = fd.read() res = re.search('(\d+) virtual CPU', buf) From 88c79c28827f8d806b89f8b0506586825790ddc7 Mon Sep 17 00:00:00 2001 From: nanli Date: Tue, 23 Apr 2024 11:08:28 +0800 Subject: [PATCH 0320/1055] add case for delete disk only snapshot xxxx-298192: delete disk only snapshot Signed-off-by: nanli --- .../snapshot/delete_disk_only_snapshot.cfg | 17 ++ .../src/snapshot/delete_disk_only_snapshot.py | 165 ++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 libvirt/tests/cfg/snapshot/delete_disk_only_snapshot.cfg create mode 100644 libvirt/tests/src/snapshot/delete_disk_only_snapshot.py diff --git a/libvirt/tests/cfg/snapshot/delete_disk_only_snapshot.cfg b/libvirt/tests/cfg/snapshot/delete_disk_only_snapshot.cfg new file mode 100644 index 00000000000..00dbd60fc53 --- /dev/null +++ b/libvirt/tests/cfg/snapshot/delete_disk_only_snapshot.cfg @@ -0,0 +1,17 @@ +- snapshot_delete.disk_only_snap: + type = delete_disk_only_snapshot + func_supported_since_libvirt_ver = (9, 10, 0) + start_vm = no + snap_names = ['s1', 's2'] + snap_options = " --disk-only" + disk1 = 'vda' + disk2 = 'vdb' + file_name = '/tmp/test.txt' + mem_path = "/tmp/mem." + disk_type = 'file' + disk_driver = {'driver': {'name': 'qemu', 'type': 'qcow2'}} + disk_target = {'target': {'dev': '${disk2}', 'bus': 'virtio'}} + disk_dict = {"type_name": '${disk_type}', 'device': 'disk', **${disk_target}, **${disk_driver}} + snapshot_disk_list = "[{'disk_name': 'vda', 'disk_snapshot': 'no'}, {'disk_name': '${disk2}', 'disk_snapshot': 'external', 'source':{'attrs': {'file': '%s'}}}]" + snapshot_dict = {'description': 'Snapshot test', 'snap_name': '%s'} + diff --git a/libvirt/tests/src/snapshot/delete_disk_only_snapshot.py b/libvirt/tests/src/snapshot/delete_disk_only_snapshot.py new file mode 100644 index 00000000000..b7d3180100e --- /dev/null +++ b/libvirt/tests/src/snapshot/delete_disk_only_snapshot.py @@ -0,0 +1,165 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +from virttest import libvirt_version +from virttest import utils_disk +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_disk + +from provider.backingchain import blockcommand_base +from provider.snapshot import snapshot_base +from provider.virtual_disk import disk_base + + +def create_data_in_guest(params, session, partition=False): + """ + Create data in guest. + + :param params: dict, test parameters + :param session: vm session + :param partition: the flag to confirm if need do partition. + """ + disk2 = params.get("disk2") + file_name = params.get("file_name") + + if partition: + cmd = "mkfs.ext4 /dev/%s;mount /dev/%s /mnt" % (disk2, disk2) + session.cmd_status_output(cmd) + utils_disk.dd_data_to_vm_disk(session, file_name) + + +def check_xml_and_hash(params, test, session, disk_path, hash_value, + del_second_snap=False): + """ + Check guest xml and data file expected hash value + + :param params: dict, test parameters + :param test: test object + :param session: guest session + :param disk_path: disk path + :param hash_value: disk path + :param del_second_snap: the flag to confirm if it's after the step of deleting + the 2nd snap. + """ + disk_type = params.get("disk_type") + file_name = params.get("file_name") + disk1, disk2 = params.get("disk1"), params.get("disk2") + + new_xml = vm_xml.VMXML.new_from_dumpxml(params.get("main_vm")) + disk2_source = disk_base.DiskBase.get_source_list(new_xml, disk_type, disk2)[::-1] + disk1_source = disk_base.DiskBase.get_source_list(new_xml, disk_type, disk1) + + # Check new disk source. + if del_second_snap: + if disk2_source != [disk_path]: + test.fail("Expect to get %s in new disk, but got '%s'" % ( + [disk_path], disk2_source)) + else: + if disk2_source != [disk_path, params.get("snap_file2")]: + test.fail("Expect to get %s in new disk, but got '%s'" % ( + [disk_path, params.get("snap_file2")], disk2_source)) + + # Check system disk source. + if params.get("first_disk_source") != disk1_source[0]: + test.fail("Expect to get %s in system disk, but got '%s'" % ( + params.get("first_disk_source"), disk1_source[0])) + + # Check file hash value. + file_hash_new, _ = params.get("block_obj").get_hash_value( + session, check_item=file_name) + if hash_value != file_hash_new: + test.fail("Expect to get the same file hash value but got" + " '%s' and '%s'" % (hash_value, file_hash_new)) + test.log.debug("Check guest two disk xml and guest file hash successfully") + + +def run(test, params, env): + """ + Delete guest to disk only snapshot. + """ + def run_test(): + """ + Delete guest to disk only snapshot. + """ + test.log.info("TEST_STEP1:Prepare a running vm with new non-OS disk.") + new_path = disk_obj.add_vm_disk(disk_type, disk_dict) + virsh.start(vm_name) + vm_session = vm.wait_for_login() + + test.log.info("TEST_STEP2:Mount new disk to and generate random data.") + create_data_in_guest(params, vm_session, partition=True) + + test.log.info("TEST_STEP3:Create the 1st snapshot with snapshot xml.") + snap_file1 = disk_obj.base_dir+"."+snap_names[0] + test_obj.create_snapshot_by_xml( + eval(snapshot_dict % snap_names[0]), + eval(snapshot_disk_list % snap_file1), options=snap_options) + + test.log.info("TEST_STEP4:Generate random data to new disk") + create_data_in_guest(params, vm_session) + + test.log.info("TEST_STEP5:Create the 2nd snapshot with snapshot xml.") + params.update({"snap_file2": disk_obj.base_dir+"."+snap_names[1]}) + test_obj.create_snapshot_by_xml( + eval(snapshot_dict % snap_names[1]), + eval(snapshot_disk_list % params.get("snap_file2")), options=snap_options) + + test.log.info("TEST_STEP6:Generate random data to new disk for the same" + "file and And get the file's sha256sum value") + create_data_in_guest(params, vm_session) + file_hash, _ = block_obj.get_hash_value(vm_session, check_item=file_name) + + test.log.info("TEST_STEP7:Delete the inactive snapshot (1st snapshot)" + "and check guest xml, hash value") + virsh.snapshot_delete(vm_name, snap_names[0], **virsh_dargs) + check_xml_and_hash(params, test, vm_session, new_path, file_hash) + + test.log.info("TEST_STEP8:Delete the active snapshot (2nd snapshot) " + "and check guest xml, hash value") + virsh.snapshot_delete(vm_name, snap_names[1], **virsh_dargs) + check_xml_and_hash(params, test, vm_session, new_path, file_hash, + del_second_snap=True) + vm_session.close() + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + snap_names.reverse() + test_obj.teardown_test() + + vm_name = params.get("main_vm") + original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + params['backup_vmxml'] = original_xml.copy() + vm = env.get_vm(vm_name) + + virsh_dargs = {"debug": True, "ignore_status": False} + disk_dict = eval(params.get("disk_dict", "{}")) + snap_names = eval(params.get("snap_names", '[]')) + snap_options = params.get("snap_options") + file_name = params.get("file_name") + disk_type = params.get("disk_type") + snapshot_dict = params.get("snapshot_dict") + snapshot_disk_list = params.get("snapshot_disk_list") + params.update({"first_disk_source": libvirt_disk.get_first_disk_source(vm)}) + + test_obj = snapshot_base.SnapshotTest(vm, test, params) + disk_obj = disk_base.DiskBase(test, vm, params) + block_obj = blockcommand_base.BlockCommand(test, vm, params) + params.update({"block_obj": block_obj}) + + libvirt_version.is_libvirt_feature_supported(params) + + try: + run_test() + + finally: + teardown_test() From 9812859a7768e140fc3780b64c1eacb33366a517 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 8 May 2024 18:10:09 +0800 Subject: [PATCH 0321/1055] guest_os_booting: Fix a hardcode arch type issue The arch type should be obtained from the host. Signed-off-by: Yingshun Cui --- .../os_configuration/without_default_os_attributes.cfg | 4 ++-- .../os_configuration/without_default_os_attributes.py | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/guest_os_booting/os_configuration/without_default_os_attributes.cfg b/libvirt/tests/cfg/guest_os_booting/os_configuration/without_default_os_attributes.cfg index a5fabc7271b..5f0ff42b3c0 100644 --- a/libvirt/tests/cfg/guest_os_booting/os_configuration/without_default_os_attributes.cfg +++ b/libvirt/tests/cfg/guest_os_booting/os_configuration/without_default_os_attributes.cfg @@ -2,11 +2,11 @@ type = without_default_os_attributes start_vm = no firmware_type = "ovmf" - only q35 + only q35, aarch64 variants: - without_arch: os_dict = {'type': 'hvm', 'boots': ['hd'], 'machine': 'q35', 'os_firmware': 'efi'} - os_xpath = [{'element_attrs': ["./os/type[@arch='x86_64']"]}] + os_xpath = [{"element_attrs": [f"./os/type[@arch='{host_arch}']"]}] - without_boot_dev: os_dict = {'type': 'hvm', 'arch': 'x86_64', 'machine': 'q35', 'os_firmware': 'efi'} os_xpath = [{'element_attrs': ["./os/boot[@dev='hd']"]}] diff --git a/libvirt/tests/src/guest_os_booting/os_configuration/without_default_os_attributes.py b/libvirt/tests/src/guest_os_booting/os_configuration/without_default_os_attributes.py index 65f766bae7b..2f288839db2 100644 --- a/libvirt/tests/src/guest_os_booting/os_configuration/without_default_os_attributes.py +++ b/libvirt/tests/src/guest_os_booting/os_configuration/without_default_os_attributes.py @@ -2,6 +2,8 @@ # SPDX-License-Identifier: GPL-2.0 # Author: Meina Li +import platform + from virttest import virsh from virttest.libvirt_xml import vm_xml @@ -20,6 +22,7 @@ def run(test, params, env): vm_name = guest_os.get_vm(params) firmware_type = params.get("firmware_type") os_dict = eval(params.get("os_dict")) + host_arch = platform.machine() os_xpath = eval(params.get("os_xpath")) vm = env.get_vm(vm_name) From a973d4ec0587b355f1dc8d115e2fa70832619cb1 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 10 May 2024 18:04:03 +0800 Subject: [PATCH 0322/1055] virtual_disks: Fix vhostvdpa_disk nodedev xml issue Signed-off-by: Yingshun Cui --- .../vhostvdpa_block_backend_type/nodedev_vhostvdpa_disk.py | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/nodedev_vhostvdpa_disk.py b/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/nodedev_vhostvdpa_disk.py index 8016649d5ce..8543a75eb84 100644 --- a/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/nodedev_vhostvdpa_disk.py +++ b/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/nodedev_vhostvdpa_disk.py @@ -19,6 +19,7 @@ def check_nodedev_xml(dev_name): test.log.info(f"TEST_STEP: Check xml for node device - {dev_name}.") nodexml = nodedev_xml.NodedevXML.new_from_dumpxml(dev_name) nodedev_attrs = nodexml.fetch_attrs() + nodedev_attrs.update({"cap": {"chardev": nodexml.cap.get_chardev()}}) idx = nodedev_attrs["path"][-1] exp_attrs = {"driver_name": "vhost_vdpa", "cap_type": "vdpa", "cap": {"chardev": f"/dev/vhost-vdpa-{idx}"}} From 7853cda4c8f9b8adfb57d90184ad3613286c368a Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 13 May 2024 12:25:41 +0800 Subject: [PATCH 0323/1055] migration: Update error message Signed-off-by: lcheng --- libvirt/tests/cfg/migration/migrate_service_control.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration/migrate_service_control.cfg b/libvirt/tests/cfg/migration/migrate_service_control.cfg index 556b7c9f0e9..84e4e7caea4 100644 --- a/libvirt/tests/cfg/migration/migrate_service_control.cfg +++ b/libvirt/tests/cfg/migration/migrate_service_control.cfg @@ -40,7 +40,7 @@ - kill_qemu_on_dst: service_name = "qemu-kvm" service_on_dst = "yes" - err_msg = 'qemu unexpectedly closed the monitor|domain is no longer running|Domain not found|Unable to write to socket: Bad file descriptor' + err_msg = 'qemu unexpectedly closed the monitor|domain is no longer running|Domain not found|Unable to write to socket: Bad file descriptor|Channel error: Input/output error' - kill_libvirtd_on_src: service_name = "libvirtd" err_msg = 'End of file while reading data: Input/output error' From a135c2651a957546746b90265f91f27cbbc9e774 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Mon, 13 May 2024 15:46:55 +0800 Subject: [PATCH 0324/1055] virtual_disks_iothreads_queue: fix version checking Add the libvirt version checking. Signed-off-by: Dan Zheng --- .../tests/src/virtual_disks/virtual_disks_iothreads_queue.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_iothreads_queue.py b/libvirt/tests/src/virtual_disks/virtual_disks_iothreads_queue.py index 31738e9bef9..d1882905a87 100755 --- a/libvirt/tests/src/virtual_disks/virtual_disks_iothreads_queue.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_iothreads_queue.py @@ -2,6 +2,7 @@ import time from virttest import data_dir +from virttest import libvirt_version from virttest import utils_disk from virttest import virsh @@ -311,6 +312,7 @@ def run(test, params, env): 2.Perform test operation and verify checkpoints 3.Recover test environment """ + libvirt_version.is_libvirt_feature_supported(params) vm_name = params.get("main_vm") vm = env.get_vm(vm_name) From 64043805ff65a96b74947be42fd4eae3b14daa12 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 13 May 2024 07:31:32 -0400 Subject: [PATCH 0325/1055] libvirt_ccw_passthrough: add sleep The test fails sometimes in CI when trying to start the VM. The mediated device doesn't seem to be present yet. I can't reproduce this but adding sleep of 2 secs to confirm in future runs that it's really about timing. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py b/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py index 758632e5c39..9d24f609ebd 100644 --- a/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py +++ b/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py @@ -1,3 +1,4 @@ +from time import sleep from uuid import uuid4 from virttest.utils_zchannels import ChannelPaths @@ -56,6 +57,7 @@ def run(test, params, env): ccw.set_override(schid) ccw.start_device(uuid, schid) + sleep(2) vm.start() session = vm.wait_for_login() From 788ce878a90eded9bbf8f4918373265667189e50 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 14 May 2024 10:28:22 +0800 Subject: [PATCH 0326/1055] guest_ob_booting: Fixup an error of UnboundLocalError: disk_image Signed-off-by: Yingshun Cui --- .../guest_os_booting/boot_order/boot_with_multiple_boot_dev.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py index 61a5b99a2ce..46087f1462a 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py @@ -70,6 +70,8 @@ def run(test, params, env): vm_name = guest_os.get_vm(params) check_prompt = eval(params.get("check_prompt", "[]")) bootable_device = params.get("bootable_device") + disk_image = "" + cdrom_path = "" vm = env.get_vm(vm_name) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) From e26e7f34b717714a437756a661b6952757be7771 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 13 May 2024 09:08:37 -0400 Subject: [PATCH 0327/1055] libvirt_ccw_passthrough: add hotplug and unplug scenarios Only coldplug was covered, add hotplug scenario and for both also unplug the device. Create __init__ for function that can be used in all vfio tests with mediated devices. If added to mdev_handlers it would create a circular dependency. Signed-off-by: Sebastian Mitterle --- .../libvirt_ccw_passthrough_read_write.cfg | 5 ++ .../ccw/libvirt_ccw_passthrough_read_write.py | 12 +++- provider/vfio/__init__.py | 19 ++++++ provider/vfio/ccw.py | 61 +++++++++++-------- spell.ignore | 2 + 5 files changed, 71 insertions(+), 28 deletions(-) create mode 100644 provider/vfio/__init__.py diff --git a/libvirt/tests/cfg/passthrough/ccw/libvirt_ccw_passthrough_read_write.cfg b/libvirt/tests/cfg/passthrough/ccw/libvirt_ccw_passthrough_read_write.cfg index 20ef06b6563..a8ef3345f90 100644 --- a/libvirt/tests/cfg/passthrough/ccw/libvirt_ccw_passthrough_read_write.cfg +++ b/libvirt/tests/cfg/passthrough/ccw/libvirt_ccw_passthrough_read_write.cfg @@ -2,5 +2,10 @@ type = libvirt_ccw_passthrough_read_write only s390-virtio devid = + start_vm = yes variants: - happy_path: + variants plugmethod: + - hotplug_unplug: + - coldplug_unplug: + diff --git a/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough_read_write.py b/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough_read_write.py index b9aefd3210f..21c2b445782 100644 --- a/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough_read_write.py +++ b/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough_read_write.py @@ -24,10 +24,12 @@ def run(test, params, env): uuid = None chpids = None + plugmethod = params.get("plugmethod") + try: ccw.assure_preconditions() - if vm.is_alive(): + if vm.is_alive() and plugmethod == "coldplug": vm.destroy() schid, chpids = ccw.get_device_info(devid) @@ -37,12 +39,18 @@ def run(test, params, env): ccw.start_device(uuid, schid) ccw.attach_hostdev(vm_name, uuid) - vm.start() + if vm.is_dead() and plugmethod == "coldplug": + vm.start() session = vm.wait_for_login() if not ccw.read_write_operations_work(session, chpids): test.fail("Read/write operation failing inside guest.") + if vm.is_alive() and plugmethod == "coldplug": + vm.destroy() + + ccw.detach_hostdev(vm_name, uuid) + finally: if uuid: ccw.stop_device(uuid) diff --git a/provider/vfio/__init__.py b/provider/vfio/__init__.py new file mode 100644 index 00000000000..0ab09595037 --- /dev/null +++ b/provider/vfio/__init__.py @@ -0,0 +1,19 @@ +from virttest.libvirt_xml.devices.hostdev import Hostdev + + +def get_hostdev_xml(uuid, model): + """ + Creates a hostdev instance for a mediated device + with given uuid. + + :param uuid: UUID of the mediated device + :param model: mediated device type model, e.g. 'vfio-ccw' + """ + + hostdev_xml = Hostdev() + hostdev_xml.mode = "subsystem" + hostdev_xml.model = model + hostdev_xml.type = "mdev" + hostdev_xml.source = hostdev_xml.new_source(**{"uuid": uuid}) + hostdev_xml.xmltreefile.write() + return hostdev_xml diff --git a/provider/vfio/ccw.py b/provider/vfio/ccw.py index d447a04ddd1..9febba8d373 100644 --- a/provider/vfio/ccw.py +++ b/provider/vfio/ccw.py @@ -1,13 +1,12 @@ import logging as log from avocado.core.exceptions import TestError - -from virttest import utils_package -from virttest import virsh -from virttest.utils_zchannels import SubchannelPaths +from virttest import utils_package, virsh from virttest.utils_misc import cmd_status_output -from virttest.libvirt_xml.devices.hostdev import Hostdev from virttest.utils_test.libvirt import mkfs +from virttest.utils_zchannels import SubchannelPaths + +from provider.vfio import get_hostdev_xml # default disk paths supposing only one DASD is passed through DASD_DISK = "/dev/dasda" @@ -18,7 +17,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 read_write_operations_work(session, chpids, makefs=True): @@ -67,8 +66,9 @@ def read_write(session): if err: raise TestError("Some read/write operation failed. %s" % out) if cmd == cmd3 and "kaixo" not in out: - raise TestError("Didn't get the written value '%s'" - " from file '%s'" % ("kaixo", out)) + raise TestError( + "Didn't get the written value '%s'" " from file '%s'" % ("kaixo", out) + ) def make_dasd_part(path, session): @@ -83,8 +83,7 @@ def make_dasd_part(path, session): cmd = "fdasd -a %s" % path err, out = cmd_status_output(cmd, shell=True, session=session) if err: - raise TestError("Couldn't create partition. Status code '%s'. %s." - % (err, out)) + raise TestError("Couldn't create partition. Status code '%s'. %s." % (err, out)) return True @@ -189,11 +188,11 @@ def get_first_device_identifiers(chpids, session): paths = SubchannelPaths(session) paths.get_info() - devices_inside_guest = [x for x in paths.devices - if x[paths.HEADER["CHPIDs"]] == chpids] + devices_inside_guest = [ + x for x in paths.devices if x[paths.HEADER["CHPIDs"]] == chpids + ] if not devices_inside_guest: - raise TestError("Device with chpids %s wasn't" - " found inside guest" % chpids) + raise TestError("Device with chpids %s wasn't" " found inside guest" % chpids) first = devices_inside_guest[0] return first[paths.HEADER["Device"]], first[paths.HEADER["Subchan."]] @@ -210,8 +209,9 @@ def device_is_listed(session, chpids): paths = SubchannelPaths(session) paths.get_info() - devices_inside_guest = [x for x in paths.devices - if x[paths.HEADER["CHPIDs"]] == chpids] + devices_inside_guest = [ + x for x in paths.devices if x[paths.HEADER["CHPIDs"]] == chpids + ] return len(devices_inside_guest) > 0 @@ -272,6 +272,20 @@ def stop_device(uuid): logging.warning("Couldn't stop device. %s", out) +def detach_hostdev(vm_name, uuid): + """ + Detaches the mdev to the machine. + + :param vm_name: VM name + :param uuid: mdev uuid + """ + + hostdev_xml = get_hostdev_xml(uuid, "vfio-ccw") + virsh.detach_device( + vm_name, hostdev_xml.xml, flagstr="--current", ignore_status=False + ) + + def attach_hostdev(vm_name, uuid): """ Attaches the mdev to the machine. @@ -280,14 +294,10 @@ def attach_hostdev(vm_name, uuid): :param uuid: mdev uuid """ - hostdev_xml = Hostdev() - hostdev_xml.mode = "subsystem" - hostdev_xml.model = "vfio-ccw" - hostdev_xml.type = "mdev" - hostdev_xml.source = hostdev_xml.new_source(**{"uuid": uuid}) - hostdev_xml.xmltreefile.write() - virsh.attach_device(vm_name, hostdev_xml.xml, flagstr="--current", - ignore_status=False) + hostdev_xml = get_hostdev_xml(uuid, "vfio-ccw") + virsh.attach_device( + vm_name, hostdev_xml.xml, flagstr="--current", ignore_status=False + ) def assure_preconditions(): @@ -295,8 +305,7 @@ def assure_preconditions(): Makes sure that preconditions are established. """ - utils_package.package_install(["mdevctl", - "driverctl"]) + utils_package.package_install(["mdevctl", "driverctl"]) def get_device_info(devid=None): diff --git a/spell.ignore b/spell.ignore index cf81c8305ab..bf44654c12e 100644 --- a/spell.ignore +++ b/spell.ignore @@ -191,6 +191,7 @@ desc dest desturi dev +devid devname devno devnode @@ -538,6 +539,7 @@ lspci lstat lstatlist lsusb +lszcrypt lszdev luks Luks From 98ac758006ab73a63877882b8c234deb71fafb61 Mon Sep 17 00:00:00 2001 From: nanli Date: Mon, 29 Apr 2024 13:54:27 +0800 Subject: [PATCH 0328/1055] add case for checking delete and revert snap event in multiple branch xxxx-300473: Delete and revert snapshots and check events in two snapshot branches Signed-off-by: nanli --- ...d_revert_snap_event_in_multiple_branch.cfg | 14 ++ ...nd_revert_snap_event_in_multiple_branch.py | 155 ++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 libvirt/tests/cfg/snapshot/check_delete_and_revert_snap_event_in_multiple_branch.cfg create mode 100644 libvirt/tests/src/snapshot/check_delete_and_revert_snap_event_in_multiple_branch.py diff --git a/libvirt/tests/cfg/snapshot/check_delete_and_revert_snap_event_in_multiple_branch.cfg b/libvirt/tests/cfg/snapshot/check_delete_and_revert_snap_event_in_multiple_branch.cfg new file mode 100644 index 00000000000..f7c9b242d1e --- /dev/null +++ b/libvirt/tests/cfg/snapshot/check_delete_and_revert_snap_event_in_multiple_branch.cfg @@ -0,0 +1,14 @@ +- snapshot_event.multiple_branch: + type = check_delete_and_revert_snap_event_in_multiple_branch + start_vm = no + snap_names = ['s1', 's2', 's3', 's4', 's5'] + system_disk = "vda" + external_path = "/tmp/${system_disk}" + snap_options = "%s --memspec snapshot=external,file=/tmp/mem.%s --diskspec ${system_disk},snapshot=external,file=${external_path}.%s" + func_supported_since_libvirt_ver = (9, 10, 0) + variants case: + - del_and_revert: + del_event = ["block-job.*${external_path}.* completed", "block-job-2.*${system_disk} completed"] + extra_del_devent = ["block-job.*%s completed"] + revert_event1 = ["lifecycle.*Stopped Snapshot", "lifecycle.*Started Snapshot","lifecycle.*Resumed Snapshot", "lifecycle.*Defined Snapshot"] + revert_event2 = ["agent-lifecycle.*'disconnected' reason: 'domain started'", "agent-lifecycle.*state: 'connected' reason: 'channel event'"] diff --git a/libvirt/tests/src/snapshot/check_delete_and_revert_snap_event_in_multiple_branch.py b/libvirt/tests/src/snapshot/check_delete_and_revert_snap_event_in_multiple_branch.py new file mode 100644 index 00000000000..2523562ec3d --- /dev/null +++ b/libvirt/tests/src/snapshot/check_delete_and_revert_snap_event_in_multiple_branch.py @@ -0,0 +1,155 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import re + +from virttest import libvirt_version +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_disk + +from provider.snapshot import snapshot_base + +virsh_dargs = {"debug": True, "ignore_status": False} + + +def check_event_output(test, pattern, event_session, expect_exist=True): + """ + Check event output. + + :param test: test object + :param pattern: the check event pattern, list type + :param event_session: event session to get event output + :param expect_exist: expect the pattern exist or not + """ + output = virsh.EventTracker.finish_get_event(event_session) + event_session.close() + for check_patt in pattern: + is_existed = bool(re.findall(check_patt, output)) + if is_existed != expect_exist: + test.fail('Expect %s to get: %s from the event output:%s' % ( + '' if expect_exist else 'not', check_patt, output)) + else: + test.log.debug("Check event %s success in the event output", check_patt) + + +def delete_snap_and_check_event(test, params, del_snap, expected_event, + expect_exist=True): + """ + Delete snap and check expected event + + :param test: test object. + :param params: wrapped dict with all parameters + :param del_snap: the snapshot to be deleted + :param expected_event: expected event value + :param expect_exist: expected event exist or not. + """ + vm_name = params.get("main_vm") + + event_session = virsh.EventTracker.start_get_event(vm_name) + virsh.snapshot_delete(vm_name, del_snap, **virsh_dargs) + check_event_output(test, expected_event, event_session, expect_exist) + + +def run(test, params, env): + """ + :params test: test object + :params params: wrapped dict with all parameters + :params env: test object + """ + def setup_test(): + """ + Prepare the parent external snapshot with multiple children. + snapshot tree is like this + s1 + | + +- s2 + | | + | +- s3 + | + +- s4 + | + +- s5 + """ + test.log.info("TEST_SETUP: Prepare the parent external snapshot " + "with multiple children:") + virsh.start(vm_name) + vm.wait_for_login().close() + for sname in snap_names: + virsh.snapshot_create_as(vm.name, snap_options % (sname, sname, sname), + **virsh_dargs) + if sname == 's3': + virsh.snapshot_revert(vm_name, snap_names[0], **virsh_dargs) + + virsh.snapshot_list(vm_name, **virsh_dargs, options='--tree') + res = virsh.snapshot_current(vm_name, **virsh_dargs).stdout.strip() + if res != snap_names[-1]: + test.fail("Expect the current snap name is '%s' instead of" + " '%s'" % (snap_names[-1], res)) + + def run_test(): + """ + Delete the snapshots of current branch. + """ + test.log.info("TEST_STEP1,2,3: Delete the snap of active chain " + "and check event.") + delete_snap_and_check_event(test, params, snap_names[-1], del_event) + + test.log.info("TEST_STEP4: Revert the snap of inactive chain " + "and check event.") + event_session = virsh.EventTracker.start_get_event(vm_name) + virsh.snapshot_revert(vm_name, snap_names[1], **virsh_dargs) + check_event_output(test, revert_event, event_session) + + test.log.info("TEST_STEP5: Delete the third snap and check event.") + delete_snap_and_check_event(test, params, snap_names[2], + del_event, expect_exist=False) + + test.log.info("TEST_STEP6: Delete the third snap and check event.") + delete_snap_and_check_event(test, params, snap_names[3], + del_event, expect_exist=False) + + test.log.info("TEST_STEP7: Delete the first snap and check event.") + delete_snap_and_check_event(test, params, snap_names[0], + del_event) + + test.log.info("TEST_STEP8: Delete the first snap and check event.") + delete_snap_and_check_event(test, params, snap_names[1], + [del_event[1]] + extra_del_devent) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + snap_names.reverse() + test_obj.virsh_dargs = {'ignore_status': True, 'debug': True} + test_obj.delete_snapshot(snap_names) + bkxml.sync() + + vm_name = params.get("main_vm") + bkxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vm = env.get_vm(vm_name) + + snap_options = params.get("snap_options") + snap_names = eval(params.get("snap_names")) + del_event = eval(params.get("del_event")) + disk_source = libvirt_disk.get_first_disk_source(vm) + extra_del_devent = eval(params.get("extra_del_devent") % disk_source) + revert_event = eval(params.get("revert_event1"))+eval(params.get("revert_event2")) + + test_obj = snapshot_base.SnapshotTest(vm, test, params) + libvirt_version.is_libvirt_feature_supported(params) + + try: + setup_test() + run_test() + + finally: + teardown_test() From 596db06daa0fafebd771bdb31f7d836272535b13 Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 15 May 2024 12:04:19 +0800 Subject: [PATCH 0329/1055] migration: Fix xml error Fix following error: LibvirtXMLError: ... Failed to define domain from ... error: unsupported configuration: Attribute migratable is only allowed for 'host-passthrough' / 'maximum' CPU mode Signed-off-by: lcheng --- libvirt/tests/cfg/migration/migrate_mem.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration/migrate_mem.cfg b/libvirt/tests/cfg/migration/migrate_mem.cfg index 5f35452bc72..dafb5101a33 100644 --- a/libvirt/tests/cfg/migration/migrate_mem.cfg +++ b/libvirt/tests/cfg/migration/migrate_mem.cfg @@ -56,7 +56,7 @@ - mem_nvdimm: nvdimm_file_path = '${nfs_mount_dir}/nvdimm' nvdimm_file_size = '512M' - vm_attrs = {'max_mem_rt': 4096, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'M', 'vcpu': 4, 'cpu': {'mode': 'host-model', 'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '1024', 'unit': 'M'}, {'id': '1', 'cpus': '2-3', 'memory': '1024', 'unit': 'M'}]}} + vm_attrs = {'max_mem_rt': 4096, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'M', 'vcpu': 4, 'cpu': {'mode': 'host-passthrough', 'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '1024', 'unit': 'M'}, {'id': '1', 'cpus': '2-3', 'memory': '1024', 'unit': 'M'}]}} mem_device_attrs = {'mem_model': 'nvdimm', 'mem_access': 'shared', 'source': {'path': '${nvdimm_file_path}'}, 'target': {'size': 512, 'size_unit': 'M', 'node': 1, 'label': {'size': 256, 'size_unit': 'KiB'}}} qemu_checks = "nvdimm=on.*mem-path=${nvdimm_file_path.*share=yes.*size=536870912.*device.*nvdimm,node=1,label-size=262144}" migrate_vm_back = "yes" From f47d60ad7a65bc7a10f1b2601a656becc8240416 Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 13 May 2024 19:07:46 +0800 Subject: [PATCH 0330/1055] migration: Update error message Signed-off-by: lcheng --- libvirt/tests/cfg/migration/migrate_vm.cfg | 6 +++--- .../precreate_none_target_disk.cfg | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/cfg/migration/migrate_vm.cfg b/libvirt/tests/cfg/migration/migrate_vm.cfg index ce8f917522d..d979727e5a5 100644 --- a/libvirt/tests/cfg/migration/migrate_vm.cfg +++ b/libvirt/tests/cfg/migration/migrate_vm.cfg @@ -749,7 +749,7 @@ variants: - copy_storage_inc: virsh_options = "--live --verbose --copy-storage-inc" - err_msg = "error: Operation not supported: pre-creation of storage targets for incremental storage migration is not supported|error: Operation not supported: pre-creation of storage target .* for incremental storage migration of .* is not supported" + err_msg = "error: Operation not supported: pre-creation of storage targets for incremental storage migration is not supported|error: Operation not supported: pre-creation of storage target.*for incremental storage migration of .* is not supported" - backing_file_with_copy_storage_inc: create_target_image = "no" setup_nfs = "yes" @@ -770,7 +770,7 @@ check_disk_size_cmd = "qemu-img info ${new_disk_source}" local_image_source = "${new_disk_source}" virsh_options = "--live --verbose --copy-storage-inc" - err_msg = "error: Operation not supported: pre-creation of storage targets for incremental storage migration is not supported|error: Operation not supported: pre-creation of storage target .* for incremental storage migration of .* is not supported" + err_msg = "error: Operation not supported: pre-creation of storage targets for incremental storage migration is not supported|error: Operation not supported: pre-creation of storage target.*for incremental storage migration of .* is not supported" - mutually_exclusive_options: create_target_image = "yes" virsh_options = "--live --persistent --verbose --copy-storage-all --copy-storage-inc" @@ -790,7 +790,7 @@ virsh_options = "--live --verbose --persistent --copy-storage-all" - copy_storage_inc: virsh_options = "--live --verbose --persistent --copy-storage-inc" - err_msg = "error: Operation not supported: pre-creation of storage targets for incremental storage migration is not supported|error: Operation not supported: pre-creation of storage target .* for incremental storage migration of .* is not supported" + err_msg = "error: Operation not supported: pre-creation of storage targets for incremental storage migration is not supported|error: Operation not supported: pre-creation of storage target.*for incremental storage migration of .* is not supported" - cache_mode: only without_postcopy nfs_mount_dir = diff --git a/libvirt/tests/cfg/migration_with_copy_storage/precreate_none_target_disk.cfg b/libvirt/tests/cfg/migration_with_copy_storage/precreate_none_target_disk.cfg index db34ae77a04..e3246e10497 100644 --- a/libvirt/tests/cfg/migration_with_copy_storage/precreate_none_target_disk.cfg +++ b/libvirt/tests/cfg/migration_with_copy_storage/precreate_none_target_disk.cfg @@ -45,5 +45,5 @@ copy_storage_option = "--copy-storage-all" - copy_storage_inc: status_error = "yes" - err_msg = "Operation not supported: pre-creation of storage targets for incremental storage migration is not supported|Operation not supported: pre-creation of storage target .* for incremental storage migration of .* is not supported" + err_msg = "Operation not supported: pre-creation of storage targets for incremental storage migration is not supported|Operation not supported: pre-creation of storage target.*for incremental storage migration of .* is not supported" copy_storage_option = "--copy-storage-inc" From be0f1b988095a7b05b3da5a0b77a302ff6a5eec6 Mon Sep 17 00:00:00 2001 From: Qian Jianhua Date: Wed, 15 May 2024 15:51:34 +0800 Subject: [PATCH 0331/1055] numa: replace parse_numa_nodeset_to_str() to convert_all_nodes_to_string() Signed-off-by: Qian Jianhua --- .../guest_numa_node_tuning/auto_memory_nodeset_placement.py | 2 +- .../src/numa/guest_numa_node_tuning/memory_binding_setting.py | 2 +- libvirt/tests/src/numa/numa_memory.py | 4 +--- libvirt/tests/src/numa/numa_memory_migrate.py | 3 +-- libvirt/tests/src/virsh_cmd/domain/virsh_numatune.py | 3 +-- 5 files changed, 5 insertions(+), 9 deletions(-) diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/auto_memory_nodeset_placement.py b/libvirt/tests/src/numa/guest_numa_node_tuning/auto_memory_nodeset_placement.py index abe4bf3eff7..37501c940c3 100644 --- a/libvirt/tests/src/numa/guest_numa_node_tuning/auto_memory_nodeset_placement.py +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/auto_memory_nodeset_placement.py @@ -114,7 +114,7 @@ def verify_cgroup_mem_binding(test_obj): """ mem_mode = test_obj.params.get('mem_mode') nodeset = test_obj.params.get('nodeset') - online_nodes = libvirt_numa.parse_numa_nodeset_to_str('x-y', test_obj.online_nodes) + online_nodes = libvirt_numa.convert_all_nodes_to_string(test_obj.online_nodes) vcpu_placement = eval(test_obj.params.get('vm_attrs')).get('placement') vm_pid = test_obj.vm.get_pid() cg = libvirt_cgroup.CgroupTest(vm_pid) diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py b/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py index 9959238c614..54e8bfe589c 100644 --- a/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py @@ -179,7 +179,7 @@ def verify_cgroup(test_obj): """ mem_mode = test_obj.params.get('mem_mode') nodeset = numa_base.convert_to_string_with_dash(test_obj.params.get('nodeset')) - online_nodes = libvirt_numa.parse_numa_nodeset_to_str('x-y', test_obj.online_nodes) + online_nodes = libvirt_numa.convert_all_nodes_to_string(test_obj.online_nodes) vm_pid = test_obj.vm.get_pid() cg = libvirt_cgroup.CgroupTest(vm_pid) surfix = 'emulator/cpuset.mems' if cg.is_cgroup_v2_enabled() else 'cpuset.mems' diff --git a/libvirt/tests/src/numa/numa_memory.py b/libvirt/tests/src/numa/numa_memory.py index b47e448a40d..d7cda36b629 100644 --- a/libvirt/tests/src/numa/numa_memory.py +++ b/libvirt/tests/src/numa/numa_memory.py @@ -200,9 +200,7 @@ def run(test, params, env): if numa_memory.get('nodeset'): numa_nodeset_format = numa_memory.get('nodeset') - numa_memory['nodeset'] = libvirt_numa.parse_numa_nodeset_to_str(numa_nodeset_format, - node_list, - ignore_error=True) + numa_memory['nodeset'] = libvirt_numa.convert_all_nodes_to_string(node_list) used_node = cpu.cpus_parser(numa_memory['nodeset']) logging.debug("set node list is %s", used_node) if not status_error: diff --git a/libvirt/tests/src/numa/numa_memory_migrate.py b/libvirt/tests/src/numa/numa_memory_migrate.py index cb51637762c..044190fff44 100644 --- a/libvirt/tests/src/numa/numa_memory_migrate.py +++ b/libvirt/tests/src/numa/numa_memory_migrate.py @@ -64,8 +64,7 @@ def mem_compare(used_node, left_node): try: if numa_memory.get('nodeset'): numa_nodeset_format = numa_memory.get('nodeset') - numa_memory['nodeset'] = libvirt_numa.parse_numa_nodeset_to_str(numa_nodeset_format, - node_list) + numa_memory['nodeset'] = libvirt_numa.convert_all_nodes_to_string(node_list) used_node = cpu.cpus_parser(numa_memory['nodeset']) logging.debug("set node list is %s", used_node) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_numatune.py b/libvirt/tests/src/virsh_cmd/domain/virsh_numatune.py index dda489868cd..b808d1ed1da 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_numatune.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_numatune.py @@ -197,8 +197,7 @@ def dynamic_node_replacement(params, numa_info, test_obj): numa_nodeset_format = params.get('numa_nodeset') dynamic_nodeset = params.get('dynamic_nodeset', 'no') == 'yes' if dynamic_nodeset and 'numa_nodeset' in params: - params['numa_nodeset'] = libvirt_numa.parse_numa_nodeset_to_str(numa_nodeset_format, - node_list) + params['numa_nodeset'] = libvirt_numa.convert_all_nodes_to_string(node_list) logging.debug('The parameter "numa_nodeset" from config file is going to be replaced by: {} ' 'available on this system'.format(params['numa_nodeset'])) From 8dbe0cb149132987eb3b99736afdce9d713966d2 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 15 May 2024 17:53:15 +0800 Subject: [PATCH 0332/1055] guest_os_booting: Skip smm and serial console to enable tests on arm Signed-off-by: Yingshun Cui --- .../guest_os_booting/boot_order/boot_from_cdrom_device.py | 6 ++++-- .../tests/src/guest_os_booting/ovmf_firmware/ovmf_loader.py | 5 +++-- .../tests/src/guest_os_booting/ovmf_firmware/ovmf_nvram.py | 5 +++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py index 3ae748bcb5e..8503e131e81 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py @@ -1,4 +1,5 @@ import os +import platform from avocado.utils import download from avocado.utils import process @@ -57,9 +58,10 @@ def update_vm_xml(vm, params, cdrom_attrs_list): vm_os.del_boots() vmxml.os = vm_os if "yes" == params.get("check_bootable_iso", "no"): - os_attrs.update({'bios_useserial': 'yes', - 'bootmenu_enable': 'yes', + os_attrs.update({'bootmenu_enable': 'yes', 'bootmenu_timeout': '3000'}) + if platform.machine() == "x86_64": + os_attrs.update({'bios_useserial': 'yes'}) vmxml.setup_attrs(os=os_attrs) index = 0 diff --git a/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_loader.py b/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_loader.py index 518c08a66a0..aec32bbf39f 100644 --- a/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_loader.py +++ b/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_loader.py @@ -28,7 +28,7 @@ def run(test, params, env): firmware_type = params.get("firmware_type") loader_dict = eval(params.get("loader_dict", "{}")) loader_xpath = eval(params.get("loader_xpath", "[]")) - smm_state = params.get("smm_state", "off") + smm_state = params.get("smm_state") error_msg = params.get("error_msg") incorrect_loader_path = params.get("incorrect_loader_path", "") use_file = "yes" == params.get("use_file", "no") @@ -40,7 +40,8 @@ def run(test, params, env): bkxml = vmxml.copy() try: - guest_os.prepare_smm_xml(vm_name, smm_state, "") + if smm_state: + guest_os.prepare_smm_xml(vm_name, smm_state, "") vmxml = guest_os.prepare_os_xml(vm_name, loader_dict, firmware_type) # stateless='yes' only use for AMD test, so here we only check the dumpxml for it to avoid the machine issue if stateless: diff --git a/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_nvram.py b/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_nvram.py index be711ae6af0..4139fdae2e9 100644 --- a/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_nvram.py +++ b/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_nvram.py @@ -19,7 +19,7 @@ def run(test, params, env): """ vm_name = guest_os.get_vm(params) firmware_type = params.get("firmware_type") - smm_state = params.get("smm_state", "off") + smm_state = params.get("smm_state") error_msg = params.get("error_msg", "") template_path = params.get("template_path", "") if template_path: @@ -32,7 +32,8 @@ def run(test, params, env): bkxml = vmxml.copy() try: - guest_os.prepare_smm_xml(vm_name, smm_state, smm_size=None) + if smm_state: + guest_os.prepare_smm_xml(vm_name, smm_state, smm_size=None) guest_os.prepare_os_xml(vm_name, nvram_dict, firmware_type) guest_os.check_vm_startup(vm, vm_name, error_msg) finally: From 1e25071232090c243b11f87099025f23725e8b40 Mon Sep 17 00:00:00 2001 From: lcheng Date: Thu, 18 Apr 2024 11:18:47 +0800 Subject: [PATCH 0333/1055] migration: Add case about vhostvdpa XXX-300493 - [vhostvdpa-blk] Migrate vm with disk of vhostvdpa backend Signed-off-by: lcheng --- .../migration_with_vhostvdpa.cfg | 41 ++++++ .../migration_with_vhostvdpa.py | 118 ++++++++++++++++++ spell.ignore | 1 + 3 files changed, 160 insertions(+) create mode 100644 libvirt/tests/cfg/migration_with_copy_storage/migration_with_vhostvdpa.cfg create mode 100644 libvirt/tests/src/migration_with_copy_storage/migration_with_vhostvdpa.py diff --git a/libvirt/tests/cfg/migration_with_copy_storage/migration_with_vhostvdpa.cfg b/libvirt/tests/cfg/migration_with_copy_storage/migration_with_vhostvdpa.cfg new file mode 100644 index 00000000000..69581dfc57c --- /dev/null +++ b/libvirt/tests/cfg/migration_with_copy_storage/migration_with_vhostvdpa.cfg @@ -0,0 +1,41 @@ +- migration_with_copy_storage.migration_with_vhostvdpa: + type = migration_with_vhostvdpa + migration_setup = 'yes' + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = "" + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = "qemu:///system" + image_convert = "no" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + server_ip = "${migrate_dest_host}" + server_user = "${remote_user}" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "${remote_user}" + client_pwd = "${migrate_source_pwd}" + start_vm = "yes" + setup_local_nfs = "yes" + storage_type = "nfs" + mnt_path_name = ${nfs_mount_dir} + virsh_migrate_extra = "--migrate-disks vdb" + status_error = "no" + check_disk_after_mig = "yes" + vhost_vdpa_disk = "/dev/vhost-vdpa-0" + disk_dict = {"device": "disk", "type_name": "vhostvdpa", "driver": {"name": "qemu", "type": "raw", "cache": "none", "io": "threads", "copy_on_read": "on", "discard": "unmap", "detect_zeroes": "on"}, "target": {"dev": "vdb", "bus": "virtio"}, "source": {"attrs": {"dev": "${vhost_vdpa_disk}"}}} + func_supported_since_libvirt_ver = (10, 0, 0) + only x86_64 + variants: + - p2p: + virsh_migrate_options = "--live --p2p --verbose" + - non_p2p: + virsh_migrate_options = "--live --verbose" + variants: + - copy_storage_all: + copy_storage_option = "--copy-storage-all" diff --git a/libvirt/tests/src/migration_with_copy_storage/migration_with_vhostvdpa.py b/libvirt/tests/src/migration_with_copy_storage/migration_with_vhostvdpa.py new file mode 100644 index 00000000000..dfad2fbb944 --- /dev/null +++ b/libvirt/tests/src/migration_with_copy_storage/migration_with_vhostvdpa.py @@ -0,0 +1,118 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: Liping Cheng +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from virttest import libvirt_version +from virttest import remote +from virttest import utils_vdpa + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_disk +from virttest.utils_libvirt import libvirt_vmxml + +from provider.migration import base_steps + + +def setup_vhost_vdpa_simulator_disk(params, run_on_target, vdpa_obj): + """ + Setup vhostvdpa disk + + :param params: dictionary with the test parameters + :param run_on_target: remote runner object + :param vdpa_obj: vdpa simulator object + """ + vdpa_obj.setup() + + cmd = "modprobe vhost-vdpa" + remote.run_remote_cmd(cmd, params, run_on_target) + + cmd = "modprobe vdpa-sim-blk" + remote.run_remote_cmd(cmd, params, run_on_target) + + cmd = "vdpa dev add mgmtdev vdpasim_blk name blk0" + remote.run_remote_cmd(cmd, params, run_on_target) + + +def cleanup_vhost_vdpa_simulator_disk(params, run_on_target, vdpa_obj): + """ + Cleanup vhostvdpa disk + + :param params: dictionary with the test parameters + :param run_on_target: remote runner object + :param vdpa_obj: vdpa simulator object + """ + vdpa_obj.cleanup() + + cmd = "modprobe -r vdpa-sim-blk" + remote.run_remote_cmd(cmd, params, run_on_target) + + cmd = "modprobe -r vhost-vdpa" + remote.run_remote_cmd(cmd, params, run_on_target) + + +def run(test, params, env): + """ + To verify that migrate vm with copying vhostvdpa backend disk can succeed. + + :param test: test object + :param params: dictionary with the test parameters + :param env: dictionary with test environment. + """ + def setup_test(): + """ + Setup steps + + """ + vhost_vdpa_disk = params.get("vhost_vdpa_disk") + disk_dict = eval(params.get("disk_dict")) + + test.log.info("Setup steps.") + migration_obj.setup_connection() + + setup_vhost_vdpa_simulator_disk(params, run_on_target, vdpa_obj) + # Set shared memory + vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", hpgs=False) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + vmxml.add_device(libvirt_vmxml.create_vm_device_by_type("disk", disk_dict)) + vmxml.sync() + vm.start() + vm_session = vm.wait_for_login() + new_disk = libvirt_disk.get_non_root_disk_name(vm_session)[0] + vm_session.close() + if not libvirt_disk.check_virtual_disk_io(vm, new_disk): + test.fail("Failed to check disk io for %s!" % new_disk) + + def cleanup_test(): + """ + Cleanup steps + + """ + test.log.info("Cleanup steps.") + if vm.is_alive(): + vm.destroy() + cleanup_vhost_vdpa_simulator_disk(params, run_on_target, vdpa_obj) + migration_obj.cleanup_connection() + + vm_name = params.get("migrate_main_vm") + server_ip = params.get("server_ip") + server_user = params.get("server_user", "root") + server_pwd = params.get("server_pwd") + + libvirt_version.is_libvirt_feature_supported(params) + run_on_target = remote.RemoteRunner(host=server_ip, username=server_user, password=server_pwd) + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + vdpa_obj = utils_vdpa.VDPASimulatorTest(sim_dev_module="vdpa_sim_blk", mgmtdev="vdpasim_blk") + + try: + setup_test() + migration_obj.run_migration() + migration_obj.verify_default() + finally: + cleanup_test() diff --git a/spell.ignore b/spell.ignore index cf81c8305ab..d4f4440882f 100644 --- a/spell.ignore +++ b/spell.ignore @@ -1148,6 +1148,7 @@ vhbas vhost vhostuer vhostuser +vhostvdpa vid viostor vir From 1208b78966852adc7c72866fd097f838d1cf72a6 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Mon, 15 Apr 2024 10:08:51 +0800 Subject: [PATCH 0334/1055] guest_os_booting: Correct the supported arch types To enable tests on arm, correct the cfg files in this PR. Signed-off-by: Yingshun Cui --- .../cfg/guest_os_booting/boot_menu/bootmenu.cfg | 5 ++++- .../boot_order/boot_from_cdrom_device.cfg | 6 +++++- .../boot_order/boot_from_disk_device.cfg | 4 +++- .../boot_order/boot_from_usb_device.cfg | 2 +- .../boot_order/boot_with_multiple_boot_dev.cfg | 6 +++++- .../boot_with_multiple_boot_order.cfg | 6 +++++- .../ovmf_firmware/ovmf_backed_nvram.cfg | 12 +++++++++--- .../ovmf_firmware/ovmf_firmware_feature.cfg | 7 ++++++- .../ovmf_firmware/ovmf_loader.cfg | 17 ++++++++++++----- .../ovmf_firmware/ovmf_nvram.cfg | 14 +++++++++++--- .../ovmf_firmware/ovmf_seclabel_in_nvram.cfg | 11 ++++++++--- .../seabios_firmware/seabios_loader.cfg | 1 + .../guest_os_booting/useserial/useserial.cfg | 1 + 13 files changed, 71 insertions(+), 21 deletions(-) diff --git a/libvirt/tests/cfg/guest_os_booting/boot_menu/bootmenu.cfg b/libvirt/tests/cfg/guest_os_booting/boot_menu/bootmenu.cfg index a2ac19afc1f..e94a6d46cc0 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_menu/bootmenu.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_menu/bootmenu.cfg @@ -3,6 +3,8 @@ start_vm = no bootmenu_enable = "yes" bootmenu_dict = {'bootmenu_enable': '%s', 'bootmenu_timeout': '%s', 'bios_useserial': 'yes'} + aarch64: + bootmenu_dict = {'bootmenu_enable': '%s', 'bootmenu_timeout': '%s'} variants: - positive_test: status_error = "no" @@ -31,9 +33,10 @@ error_msg = "invalid value for boot menu timeout, must be in range [0,65535]" variants: - by_ovmf: - only q35 + only q35, aarch64 firmware_type = "ovmf" check_prompt = "BdsDxe: loading Boot0000 "UiApp" from Fv" - by_seabios: + only x86_64 firmware_type = "seabios" check_prompt = "Select boot device" diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg index 25a8596ac68..35dfe78e81d 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg @@ -9,12 +9,16 @@ only os_dev - with_cdrom_with_no_src: cdrom1_attrs = {'target': {'dev': 'sda', 'bus': 'sata'}, **${cdrom_attrs}} + aarch64: + cdrom1_attrs = {'target': {'dev': 'sda', 'bus': 'scsi'}, **${cdrom_attrs}} - with_cdrom: check_bootable_iso = "yes" cdrom1_attrs = {'source': {'attrs': {'file': boot_img_path}}, 'target': {'dev': 'sda', 'bus': 'scsi'}, **${cdrom_attrs}} - multi_cdroms: cdrom1_attrs = {'target': {'dev': 'sda', 'bus': 'scsi'}, **${cdrom_attrs}} cdrom2_attrs = {'source': {'attrs': {'file': boot_img_path}}, 'target': {'dev': 'sdb', 'bus': 'sata'}, **${cdrom_attrs}} + aarch64: + cdrom2_attrs = {'source': {'attrs': {'file': boot_img_path}}, 'target': {'dev': 'sdb', 'bus': 'scsi'}, **${cdrom_attrs}} cdrom_boot_order: check_bootable_iso = "yes" os_dev: @@ -29,4 +33,4 @@ with_cdrom_with_no_src: status_error = "yes" - ovmf: - only q35 + only q35, aarch64 diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_disk_device.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_disk_device.cfg index c11b36e8459..0f913912b45 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_disk_device.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_disk_device.cfg @@ -12,6 +12,8 @@ disk1_img = "non-bootable.qcow2" disk2_attrs = {'target': {'dev': 'sda', 'bus': 'sata'}} status_error = "yes" + aarch64: + disk2_attrs = {'target': {'dev': 'sda', 'bus': 'scsi'}} - disk_boot_order: variants: - single_disk: @@ -26,4 +28,4 @@ - seabios: only x86_64 - ovmf: - only q35 + only q35, aarch64 diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg index bd911d81e92..0f62a062bb7 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg @@ -4,7 +4,7 @@ bus_type = "usb" bootmenu_dict = {'bootmenu_enable': 'yes', 'bootmenu_timeout': '3000', 'bios_useserial': 'yes'} check_prompt = "UEFI .* USB|1. USB MSC Drive .*" - only q35 + only q35, aarch64 variants usb_device: - block_device: disk_type = "block" diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_dev.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_dev.cfg index 08311721e27..ad60e5d8c9f 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_dev.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_dev.cfg @@ -2,7 +2,11 @@ type = boot_with_multiple_boot_dev start_vm = no os_dict = {'boots': ['%s', '%s'], 'bootmenu_enable': 'yes', 'bios_useserial': 'yes'} - cdrom_dict = {'source': {'attrs': {'file': '%s'}}, 'type_name': 'file', 'device': 'cdrom', 'driver': {'name': 'qemu', 'type': 'raw'}, 'target': {'dev': 'sda', 'bus': 'sata'}} + target_bus = 'sata' + aarch64: + target_bus = 'scsi' + os_dict = {'boots': ['%s', '%s'], 'bootmenu_enable': 'yes'} + cdrom_dict = {'source': {'attrs': {'file': '%s'}}, 'type_name': 'file', 'device': 'cdrom', 'driver': {'name': 'qemu', 'type': 'raw'}, 'target': {'dev': 'sda', 'bus': '${target_bus}'}} check_prompt = ["begin the installation process|Install Red Hat Enterprise"] variants first_dev: - hd: diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_order.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_order.cfg index 8e22903b451..8821b5f6f64 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_order.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_order.cfg @@ -2,7 +2,11 @@ type = boot_with_multiple_boot_order start_vm = no os_dict = {'bootmenu_enable': 'yes', 'bios_useserial': 'yes'} - cdrom_dict = {'source': {'attrs': {'file': '%s'}}, 'type_name': 'file', 'device': 'cdrom', 'driver': {'name': 'qemu', 'type': 'raw'}, 'target': {'dev': 'sda', 'bus': 'sata'}} + target_bus = 'sata' + aarch64: + os_dict = {'bootmenu_enable': 'yes'} + target_bus = 'scsi' + cdrom_dict = {'source': {'attrs': {'file': '%s'}}, 'type_name': 'file', 'device': 'cdrom', 'driver': {'name': 'qemu', 'type': 'raw'}, 'target': {'dev': 'sda', 'bus': '${target_bus}'}} check_prompt = ["begin the installation process|Install Red Hat Enterprise"] variants first_dev: - hd: diff --git a/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.cfg b/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.cfg index 2b8e554e547..92ed6752f7d 100644 --- a/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.cfg +++ b/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.cfg @@ -3,12 +3,18 @@ start_vm = no loader_path = "/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd" template_path = "/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd" - os_dict = {'secure': 'yes', 'loader_readonly': 'yes', 'loader_type': 'pflash', 'loader': '${loader_path}'} + os_secure = "yes" firmware_type = "ovmf" nvram_attrs = {'nvram_attrs': {'template': '${template_path}', 'type': '%s'}} func_supported_since_libvirt_ver = (8, 5, 0) - only q35 - only x86_64 + only q35, aarch64 + aarch64: + loader_path = "/usr/share/edk2/aarch64/QEMU_EFI-silent-pflash.qcow2" + template_path = "/usr/share/edk2/aarch64/vars-template-pflash.qcow2" + os_secure = "no" + nvram_attrs = {'nvram_attrs': {'template': '${template_path}', 'type': '%s', 'format': 'qcow2'}} + os_dict = {'secure': '${os_secure}', 'loader_readonly': 'yes', 'loader_type': 'pflash', 'loader': '${loader_path}'} + variants source_type: - file: nvram_source = {'nvram_source': {'attrs': {'file': '%s'}}} diff --git a/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_firmware_feature.cfg b/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_firmware_feature.cfg index c83da06e461..85653780fac 100644 --- a/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_firmware_feature.cfg +++ b/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_firmware_feature.cfg @@ -4,15 +4,17 @@ loader_path = "/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd" nvram_template = "/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd" firmware_type = "ovmf" - only q35 + only q35, aarch64 variants: - positive_test: status_error = "no" variants: - enable_secure_boot: + no aarch64 firmware_dict = {'os_firmware': 'efi', 'firmware': {'feature': [{'enabled': 'yes', 'name': 'enrolled-keys'}, {'enabled': 'yes', 'name': 'secure-boot'}]}} firmware_xpath = [{'element_attrs': ["./os/nvram[@template='${nvram_template}']"]}, {'element_attrs': ["./os/loader[@type='pflash']"], 'text': '${loader_path}'}] - disable_secure_boot: + no aarch64 nvram_template = "/usr/share/edk2/ovmf/OVMF_VARS.fd" firmware_dict = {'os_firmware': 'efi', 'firmware': {'feature': [{'enabled': 'no', 'name': 'enrolled-keys'}, {'enabled': 'yes', 'name': 'secure-boot'}]}} firmware_xpath = [{'element_attrs': ["./os/nvram[@template='${nvram_template}']"]}, {'element_attrs': ["./os/loader[@type='pflash']"], 'text': '${loader_path}'}] @@ -20,6 +22,9 @@ func_supported_since_libvirt_ver = (9, 0, 0) loader_path = "/usr/share/edk2/ovmf/OVMF_CODE.fd" nvram_template = "/usr/share/edk2/ovmf/OVMF_VARS.fd" + aarch64: + loader_path = "/usr/share/edk2/aarch64/QEMU_EFI-silent-pflash.qcow2" + nvram_template = "/usr/share/edk2/aarch64/vars-template-pflash.qcow2" firmware_dict = {'os_firmware': 'efi', 'firmware': {'feature': [{'enabled': 'no', 'name': 'enrolled-keys'}, {'enabled': 'no', 'name': 'secure-boot'}]}} firmware_xpath = [{'element_attrs': ["./os/nvram[@template='${nvram_template}']"]}, {'element_attrs': ["./os/loader[@readonly='yes']"], 'text': '${loader_path}'}] - negative_test: diff --git a/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_loader.cfg b/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_loader.cfg index 540d0c6c828..be655099894 100644 --- a/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_loader.cfg +++ b/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_loader.cfg @@ -4,17 +4,24 @@ loader_path = "/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd" smm_state = "on" firmware_type = "ovmf" - only q35 + os_secure = "yes" + aarch64: + os_secure = "no" + smm_state = + loader_path = "/usr/share/edk2/aarch64/QEMU_EFI-silent-pflash.qcow2" + only q35, aarch64 variants: - positive_test: variants: - default_value: - loader_dict = {'secure': 'yes', 'loader_readonly': 'yes', 'loader_type': 'pflash', 'loader': '${loader_path}'} + loader_dict = {'secure': '${os_secure}', 'loader_readonly': 'yes', 'loader_type': 'pflash', 'loader': '${loader_path}'} - secure_no: + no aarch64 nvram_path = "/var/lib/libvirt/qemu/nvram/nvram_VARS.fd" nvram_template = "/usr/share/edk2/ovmf/OVMF_VARS.fd" loader_dict = {'loader': '${loader_path}', 'nvram': '${nvram_path}', 'nvram_attrs': {'template': '${nvram_template}'}, 'secure': 'no', 'loader_readonly': 'yes', 'loader_type': 'pflash'} - stateless_yes: + no aarch64 stateless = "yes" func_supported_since_libvirt_ver = (8, 6, 0) loader_path = "/usr/share/edk2/ovmf/OVMF.amdsev.fd" @@ -24,13 +31,13 @@ variants: - readonly_no: func_supported_since_libvirt_ver = (9, 5, 0) - loader_dict = {'secure': 'yes', 'loader_readonly': 'no', 'loader_type': 'pflash', 'loader': '${loader_path}'} + loader_dict = {'secure': '${os_secure}', 'loader_readonly': 'no', 'loader_type': 'pflash', 'loader': '${loader_path}'} error_msg = "Could not open .+: Permission denied" - type_rom: - loader_dict = {'secure': 'yes', 'loader_readonly': 'yes', 'loader_type': 'rom', 'loader': '${loader_path}'} + loader_dict = {'secure': '${os_secure}', 'loader_readonly': 'yes', 'loader_type': 'rom', 'loader': '${loader_path}'} error_msg = "could not load PC BIOS" - incorrect_loader_path: use_file = "yes" incorrect_loader_path = "/tmp/test" - loader_dict = {'secure': 'yes', 'loader_readonly': 'yes', 'loader_type': 'pflash', 'loader': '${incorrect_loader_path}'} + loader_dict = {'secure': '${os_secure}', 'loader_readonly': 'yes', 'loader_type': 'pflash', 'loader': '${incorrect_loader_path}'} error_msg = "Could not open .+: Permission denied" || "unable to find any master var store for loader" diff --git a/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_nvram.cfg b/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_nvram.cfg index bc5486e9c64..4a1fd4a15f4 100644 --- a/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_nvram.cfg +++ b/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_nvram.cfg @@ -3,19 +3,27 @@ start_vm = no smm_state = "on" loader_path = "/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd" - nvram_dict = {'secure': 'yes', 'loader_readonly': 'yes', 'loader_type': 'pflash', 'loader': '${loader_path}', 'nvram_attrs': {'template': '%s'}} + os_secure = "yes" + aarch64: + smm_state = + os_secure = "no" + loader_path = "/usr/share/edk2/aarch64/QEMU_EFI-silent-pflash.qcow2" + nvram_dict = {'secure': '${os_secure}', 'loader_readonly': 'yes', 'loader_type': 'pflash', 'loader': '${loader_path}', 'nvram_attrs': {'template': '%s'}} firmware_type = "ovmf" - only q35 + only q35, aarch64 variants: - positive_test: variants: - template_enable_secure: + no aarch64 template_path = "/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd" - template_disable_secure: template_path = "/usr/share/edk2/ovmf/OVMF_VARS.fd" + aarch64: + template_path = "/usr/share/edk2/aarch64/vars-template-pflash.qcow2" - manual_nvram_file: nvram_file = "/tmp/nvram" - nvram_dict = {'secure': 'yes', 'loader_readonly': 'yes', 'loader_type': 'pflash', 'loader': '${loader_path}', 'nvram': '${nvram_file}'} + nvram_dict = {'secure': '${os_secure}', 'loader_readonly': 'yes', 'loader_type': 'pflash', 'loader': '${loader_path}', 'nvram': '${nvram_file}'} - negative_test: variants: - nonexist_template: diff --git a/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_seclabel_in_nvram.cfg b/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_seclabel_in_nvram.cfg index eeff9ab041a..adeac1a01b7 100644 --- a/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_seclabel_in_nvram.cfg +++ b/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_seclabel_in_nvram.cfg @@ -3,13 +3,18 @@ start_vm = no loader_path = "/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd" template_path = "/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd" - os_dict = {'secure': 'yes', 'loader_readonly': 'yes', 'loader_type': 'pflash', 'loader': '${loader_path}'} + os_secure = "yes" nvram_attrs = {'nvram_attrs': {'template': '${template_path}', 'type': 'file'}} + aarch64: + loader_path = "/usr/share/edk2/aarch64/QEMU_EFI-silent-pflash.qcow2" + template_path = "/usr/share/edk2/aarch64/vars-template-pflash.qcow2" + os_secure = "no" + nvram_attrs = {'nvram_attrs': {'template': '${template_path}', 'type': 'file', 'format': 'qcow2'}} nvram_source = {'nvram_source': {'seclabels': [{'label': '%s', 'model': '%s', 'relabel': 'yes'}], 'attrs': {'file': '%s'}}} + os_dict = {'secure': '${os_secure}', 'loader_readonly': 'yes', 'loader_type': 'pflash', 'loader': '${loader_path}'} firmware_type = "ovmf" func_supported_since_libvirt_ver = (8, 5, 0) - only q35 - only x86_64 + only q35, aarch64 variants: - positive_test: variants: diff --git a/libvirt/tests/cfg/guest_os_booting/seabios_firmware/seabios_loader.cfg b/libvirt/tests/cfg/guest_os_booting/seabios_firmware/seabios_loader.cfg index 9586cd37d42..2c3d4319b52 100644 --- a/libvirt/tests/cfg/guest_os_booting/seabios_firmware/seabios_loader.cfg +++ b/libvirt/tests/cfg/guest_os_booting/seabios_firmware/seabios_loader.cfg @@ -5,6 +5,7 @@ loader_type = "rom" loader_dict = {'loader_type': '%s', 'loader': '%s'} firmware_type = "seabios" + only x86_64 variants: - positive_test: variants: diff --git a/libvirt/tests/cfg/guest_os_booting/useserial/useserial.cfg b/libvirt/tests/cfg/guest_os_booting/useserial/useserial.cfg index b1b39538ce2..0545c98be3d 100644 --- a/libvirt/tests/cfg/guest_os_booting/useserial/useserial.cfg +++ b/libvirt/tests/cfg/guest_os_booting/useserial/useserial.cfg @@ -13,5 +13,6 @@ only q35 firmware_type = "ovmf" - by_seabios: + only x86_64 firmware_type = "seabios" check_prompt = "Press ESC for boot menu" From b9c8e663084484e185f1419ce91c8ad3af716bed Mon Sep 17 00:00:00 2001 From: nanli Date: Thu, 16 May 2024 10:26:42 +0800 Subject: [PATCH 0335/1055] add case for delete disk and memory snapshot xxxx-298193: Verify snapshot-delete disk and memory snapshot. Signed-off-by: nanli --- .../delete_disk_and_memory_snapshot.cfg | 16 ++ .../delete_disk_and_memory_snapshot.py | 179 ++++++++++++++++++ 2 files changed, 195 insertions(+) create mode 100644 libvirt/tests/cfg/snapshot/delete_disk_and_memory_snapshot.cfg create mode 100644 libvirt/tests/src/snapshot/delete_disk_and_memory_snapshot.py diff --git a/libvirt/tests/cfg/snapshot/delete_disk_and_memory_snapshot.cfg b/libvirt/tests/cfg/snapshot/delete_disk_and_memory_snapshot.cfg new file mode 100644 index 00000000000..67feadf19e3 --- /dev/null +++ b/libvirt/tests/cfg/snapshot/delete_disk_and_memory_snapshot.cfg @@ -0,0 +1,16 @@ +- snapshot_delete.disk_and_memory_snap: + type = delete_disk_and_memory_snapshot + start_vm = no + func_supported_since_libvirt_ver = (9, 10, 0) + snap_names = ["s1", "s2"] + file_path = "/mnt/data.txt" + target_disk = "vdb" + snapshot_disk_list = "[{'disk_name': 'vda', 'disk_snapshot': 'no'}, {'disk_name': '${target_disk}', 'disk_snapshot': 'external', 'source':{'attrs': {'file': '%s'}}}]" + snapshot_dict = {'description': 'Snapshot test', 'snap_name': '%s', 'mem_snap_type': 'external', 'mem_file': '%s'} + variants disk: + - qcow2_format: + disk_type = "file" + disk_dict = {"type_name":"${disk_type}", "target":{"dev": "${target_disk}", "bus": "virtio"}, "driver": {"name": "qemu", "type":"qcow2"}} + variants vm_status: + - vm_running: + - vm_paused: diff --git a/libvirt/tests/src/snapshot/delete_disk_and_memory_snapshot.py b/libvirt/tests/src/snapshot/delete_disk_and_memory_snapshot.py new file mode 100644 index 00000000000..5d6f1f75a35 --- /dev/null +++ b/libvirt/tests/src/snapshot/delete_disk_and_memory_snapshot.py @@ -0,0 +1,179 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import os.path + +from virttest import virsh +from virttest import libvirt_version +from virttest import utils_disk +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_disk + +from provider.backingchain import blockcommand_base +from provider.backingchain import check_functions +from provider.virtual_disk import disk_base +from provider.snapshot import snapshot_base + +virsh_dargs = {"debug": True, "ignore_status": False} + + +def write_file(vm, params, file_name, format_disk=False): + """ + Write file to target disk + + :param vm: vm object. + :param params: Dictionary with the test parameters. + :param file_name: file name. + :param format_disk: only format disk for one time in vm. + """ + vm_status = params.get("vm_status") + target_disk = params.get("target_disk") + + if vm_status == "vm_paused" and vm.state() != "running": + virsh.resume(vm.name, **virsh_dargs) + session = vm.wait_for_login() + if format_disk: + cmd = "mkfs.ext4 /dev/%s;mount /dev/%s /mnt" % ( + target_disk, target_disk) + session.cmd_status_output(cmd) + utils_disk.dd_data_to_vm_disk(session, file_name, bs='1M', + count='2') + session.close() + + +def check_after_deleting_snap(test, vm, params, expected_hash, del_snap): + """ + Check two disks xml, guest file hash value, snapshot memory file. + + :param test: test object. + :param vm: vm object. + :param params: Dictionary with the test parameters. + :param expected_hash: expected file hash value in guest. + :param del_snap: the deleted snap order in snap names. + """ + disk_type = params.get("disk_type") + target_disk = params.get("target_disk") + file_path = params.get("file_path") + vm_status = params.get("vm_status") + check_obj = check_functions.Checkfunction(test, vm, params) + mem_file = params.get("mem_files")[int(del_snap)-1] + expected_source_len = 2 if del_snap == "1" else 1 + if vm_status == "vm_paused" and vm.state() != "running": + virsh.resume(vm.name, **virsh_dargs) + + vmxml = vm_xml.VMXML.new_from_dumpxml(vm.name) + new_disk_sources = disk_base.DiskBase.get_source_list( + vmxml, disk_type, target_disk) + + if len(new_disk_sources) != expected_source_len: + test.fail("New disk source list length should be %s, instead of %s " % + (new_disk_sources, expected_source_len)) + + new_source = libvirt_disk.get_first_disk_source(vm) + if params.get("original_disk_source") != new_source: + test.fail("Disk source should not change to %s" % new_source) + + session = vm.wait_for_login() + check_obj.check_hash_list([file_path], [expected_hash], session=session) + session.close() + + if os.path.exists(mem_file): + test.fail("The snap memory file %s is existed " % mem_file) + test.log.debug("Checking disks xml, file hash value, and snapshot " + "memory file were successful.") + + +def run(test, params, env): + """ + :params test: test object + :params params: wrapped dict with all parameters + :params env: test object + """ + def run_test(): + """ + Verify snapshot-delete disk and memory snapshot. + """ + test.log.info("TEST_STEP1: Attach a new disk to guest.") + vm.start() + vm.wait_for_login().close() + new_disk, _ = disk_obj.prepare_disk_obj(disk_type, disk_dict) + virsh.attach_device(vm_name, new_disk.xml, **virsh_dargs) + + test.log.info("TEST_STEP2: Mount new disk and write random data.") + write_file(vm, params, file_name=file_path, format_disk=True) + + test.log.info("TEST_STEP3,4: Create the 1st snapshot with snapshot xml") + if vm_status == "vm_paused": + virsh.suspend(vm_name, **virsh_dargs) + test_obj.create_snapshot_by_xml( + eval(snapshot_dict % (snap_names[0], params.get("mem_files")[0])), + eval(snapshot_disk_list % snap_file1)) + + test.log.info("TEST_STEP5: Write random data to new disk again.") + write_file(vm, params, file_name=file_path) + + test.log.info("TEST_STEP6,7:Create the 2nd snapshot with snapshot xml.") + if vm_status == "vm_paused": + virsh.suspend(vm_name, **virsh_dargs) + test_obj.create_snapshot_by_xml( + eval(snapshot_dict % (snap_names[1], params.get("mem_files")[1])), + eval(snapshot_disk_list % snap_file2)) + + test.log.info("TEST_STEP8: Write random data to new disk again.") + write_file(vm, params, file_name=file_path) + expected_hash, _ = block_obj.get_hash_value(check_item=file_path) + + test.log.info("TEST_STEP9: Update vm status.") + if vm_status == "vm_paused": + virsh.suspend(vm_name, **virsh_dargs) + + test.log.info("TEST_STEP10: Delete the 1st snapshot and check xml.") + virsh.snapshot_delete(vm_name, snap_names[0], **virsh_dargs) + check_after_deleting_snap(test, vm, params, expected_hash, "1") + + test.log.info("TEST_STEP11: Delete the 2nd snapshot and check xml.") + virsh.snapshot_delete(vm_name, snap_names[1], **virsh_dargs) + check_after_deleting_snap(test, vm, params, expected_hash, "2") + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + snap_names.reverse() + test_obj.teardown_test() + + vm_name = params.get("main_vm") + bkxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + params.update({"backup_vmxml": bkxml.copy()}) + vm = env.get_vm(vm_name) + + params.update({"original_disk_source": libvirt_disk.get_first_disk_source(vm)}) + snap_names = eval(params.get("snap_names")) + params.update({"mem_files": ["/tmp/%s" % snap_names[0], "/tmp/%s" % snap_names[1]]}) + disk_type = params.get("disk_type") + vm_status = params.get("vm_status") + file_path = params.get("file_path") + disk_dict = eval(params.get('disk_dict', '{}')) + snapshot_dict = params.get("snapshot_dict") + snapshot_disk_list = params.get("snapshot_disk_list") + + test_obj = snapshot_base.SnapshotTest(vm, test, params) + disk_obj = disk_base.DiskBase(test, vm, params) + block_obj = blockcommand_base.BlockCommand(test, vm, params) + snap_file1 = disk_obj.base_dir + "." + snap_names[0] + snap_file2 = disk_obj.base_dir + "." + snap_names[1] + + libvirt_version.is_libvirt_feature_supported(params) + + try: + run_test() + + finally: + teardown_test() From f5ccf5d502740e26ae1cb3c484924649fd735a38 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Thu, 29 Feb 2024 01:23:35 -0500 Subject: [PATCH 0336/1055] Automate discard_granularity disk attribute cases scenarios cover normal, negative, boundary and updates xx-300179 - Live update disk with //disk/blockio[@discard_granularity] xx-300180 - Define&&Start vm with //disk/blockio[@discard_granularity] xx-300181 - Hotplug/unplug disk with //disk/blockio[@discard_granularity] xx-300202 - Define&&Start vm with //disk/blockio[@discard_granularity] - invalid values xx-300203 - Define&&Start vm with //disk/blockio[@discard_granularity] - boundary values Signed-off-by: chunfuwen --- .../virtual_disks_discard_granularity.cfg | 87 ++++++ .../virtual_disks_discard_granularity.py | 283 ++++++++++++++++++ 2 files changed, 370 insertions(+) create mode 100755 libvirt/tests/cfg/virtual_disks/virtual_disks_discard_granularity.cfg create mode 100644 libvirt/tests/src/virtual_disks/virtual_disks_discard_granularity.py diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_discard_granularity.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_discard_granularity.cfg new file mode 100755 index 00000000000..c04eff57b14 --- /dev/null +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_discard_granularity.cfg @@ -0,0 +1,87 @@ +- virtual_disks.discard_granularity: + type = virtual_disks_discard_granularity + take_regular_screendumps = "no" + start_vm = "no" + target_format = "raw" + type_name = "file" + driver_type = 'raw' + device_type = "disk" + target_dev = "vdb" + status_error = "no" + define_error = "no" + func_supported_since_libvirt_ver = (10, 0, 0) + variants target_bus: + - virtio: + target_dev = "vdb" + discard_granularity = '1024' + discard_granularity_in_unit = '1K' + invalid_discard_granularity = '1000' + - sata: + no aarch64, s390x + only coldplug + target_dev = "sdb" + discard_granularity = '512' + discard_granularity_in_unit = '512B' + invalid_discard_granularity = '1024' + - scsi: + target_dev = "sdb" + discard_granularity = '1024' + discard_granularity_in_unit = '1K' + invalid_discard_granularity = '1000' + - usb: + target_dev = "sdb" + discard_granularity = '512' + discard_granularity_in_unit = '512B' + invalid_discard_granularity = '1000' + variants test_scenario: + - normal_vm_start: + - failure_vm_start: + only coldplug + define_error = "yes" + status_error = "yes" + status_error_msg = "discard_granularity must be a multiple|discard_granularity must be 512" + - boundary_vm_start: + only coldplug..virtio + define_error_msg = "Invalid value for attribute.*discard_granularity.*" + expected_attribute = "no" + variants: + - value_zero: + discard_granularity = '0' + discard_granularity_in_unit = '0K' + - value_minus: + discard_granularity = '-1' + define_error = "yes" + - value_max: + discard_granularity = '4294967296' + define_error = "yes" + - value_max_minus_one: + discard_granularity = '4294967295' + discard_granularity_in_unit = '1K' + expected_attribute = "yes" + - live_update_discard_granularity: + only coldplug..virtio + error_msg = "cannot modify field .*blockio discard_granularity.*" + variants: + - add_discard_granularity: + discard_granularity = '0' + new_discard_granularity = '512' + - modify_discard_granularity: + new_discard_granularity = '2048' + - remove_discard_granularity: + new_discard_granularity = '0' + variants disk_type: + - file: + source_file_path = "/var/lib/libvirt/images/discard_granularity" + - vhostuser: + only coldplug..virtio..failure_vm_tart + type_name = "vhostuser" + vhost_source_file_path = "/var/lib/libvirt/images/discard_granularity_vhost" + socket_file = "/tmp/vhost.sock" + define_error = "yes" + define_error_msg = "blockio is not supported with vhostuser disk" + variants: + - coldplug: + virt_device_hotplug = "no" + - hotplug: + virt_device_hotplug = "yes" + diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_discard_granularity.py b/libvirt/tests/src/virtual_disks/virtual_disks_discard_granularity.py new file mode 100644 index 00000000000..5a3b1d33f25 --- /dev/null +++ b/libvirt/tests/src/virtual_disks/virtual_disks_discard_granularity.py @@ -0,0 +1,283 @@ +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Chunfu Wen +# + +import logging +import os +import re +import time + +from avocado.utils import process + +from virttest import libvirt_version +from virttest import virsh +from virttest import virt_vm + +from virttest.libvirt_xml import vm_xml, xcepts +from virttest.utils_libvirt import libvirt_disk +from virttest.utils_test import libvirt + +LOG = logging.getLogger('avocado.' + __name__) +cleanup_files = [] + + +def create_customized_disk(params): + """ + Create one customized disk with related attributes + + :param params: dict wrapped with params + :return: disk if create successfully + """ + type_name = params.get("type_name") + disk_device = params.get("device_type") + device_target = params.get("target_dev") + device_bus = params.get("target_bus") + device_format = params.get("target_format") + discard_granularity = params.get("discard_granularity") + source_file_path = params.get("source_file_path") + sock_path = params.get("socket_file") + source_dict = {} + + if source_file_path: + libvirt.create_local_disk("file", source_file_path, 1, device_format) + cleanup_files.append(source_file_path) + source_dict.update({"file": source_file_path}) + elif sock_path: + source_dict.update({"type": "unix", "path": sock_path}) + + disk_src_dict = {"attrs": source_dict} + customized_disk = libvirt_disk.create_primitive_disk_xml( + type_name, disk_device, + device_target, device_bus, + device_format, disk_src_dict, None) + if discard_granularity: + customized_disk.blockio = {'logical_block_size': "512", "discard_granularity": discard_granularity} + LOG.debug("create customized xml: %s", customized_disk) + return customized_disk + + +def create_vhostuser_image_file(vhost_image_path): + """ + Create vhostuser image file + + :param vhost_image_path: image file path + """ + libvirt.create_local_disk("file", vhost_image_path, size="100M") + chown_cmd = "chown qemu:qemu %s" % vhost_image_path + process.run(chown_cmd, ignore_status=False, shell=True) + + +def start_vhost_sock_service(file_path, socket_path): + """ + Start one vhost sock service + + :param file_path: image file path + :param socket_path: socket file path + :return: command output + """ + start_sock_service_cmd = ( + 'systemd-run --uid qemu --gid qemu /usr/bin/qemu-storage-daemon' + ' --blockdev \'{"driver":"file","filename":"%s","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}\'' + ' --blockdev \'{"node-name":"libvirt-1-format","read-only":false,"driver":"raw","file":"libvirt-1-storage"}\'' + ' --export vhost-user-blk,id=vhost-user-blk0,node-name=libvirt-1-format,addr.type=unix,addr.path=%s,writable=on' + ' --chardev stdio,mux=on,id=char0; sleep 3' + % (file_path, socket_path)) + cmd_output = process.run(start_sock_service_cmd, ignore_status=False, shell=True).stdout_text.strip() + ch_seccontext_cmd = "chcon -t svirt_image_t %s" % socket_path + process.run(ch_seccontext_cmd, ignore_status=False, shell=True) + set_bool_mmap_cmd = "setsebool domain_can_mmap_files 1 -P" + process.run(set_bool_mmap_cmd, ignore_status=False, shell=True) + return cmd_output + + +def check_blockio_discard_granularity(vm, new_disk, discard_granularity_in_unit): + """ + Check disk discard granularity in guest internal + + :param vm: vm object + :param new_disk: newly vm disk + :param discard_granularity_in_unit: discard granularity in unit + :return: boolean value indicating whether succeed or not + """ + session = None + try: + session = vm.wait_for_login() + cmd = ("lsblk --discard|grep {0}" + .format(new_disk)) + status, output = session.cmd_status_output(cmd) + LOG.debug("Disk operation in VM:\nexit code:\n%s\noutput:\n%s", + status, output) + return discard_granularity_in_unit in output + except Exception as err: + LOG.debug("Error happens when check disk io in vm: %s", str(err)) + return False + finally: + if session: + session.close() + + +def modify_line_with_pattern(file_path, pattern, replacement): + """ + Modify line with pattern, then write back to file + + :param file_path: file path + :param pattern: matched pattern + :param replacement: replaced content + """ + with open(file_path, 'r') as file: + lines = file.readlines() + for i, line in enumerate(lines): + if re.search(pattern, line): + lines[i] = re.sub(pattern, replacement, line) + break + with open(file_path, 'w') as file: + file.writelines(lines) + + +def check_vm_dumpxml(params, test, expected_attribute=True): + """ + Common method to check source in cdrom device + + :param params: one collective object representing wrapped parameters + :param test: test object + :param expected_attribute: bool indicating whether expected attribute exists or not + """ + vm_name = params.get("main_vm") + disk_vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + target_dev = params.get('target_dev') + disk = disk_vmxml.get_disk_all()[target_dev] + actual_discard_granularity = disk.find('blockio').get('discard_granularity') + if not expected_attribute: + if actual_discard_granularity is not None: + test.fail("unexpected value for blockio in VM disk XML") + else: + if actual_discard_granularity is None: + test.fail("discard_granularity can not be found in vm disk xml") + else: + expected_discard_granularity = params.get("discard_granularity") + if actual_discard_granularity != expected_discard_granularity: + test.fail("actual discard_granularity: %s is not equal to expected: %s" % (actual_discard_granularity, expected_discard_granularity)) + + +def run(test, params, env): + """ + Test disk with discard_granularity. + + 1.Prepare a vm with discard_granularity disk + 2.Attach the virtual disk to the vm + 3.Start vm + 4.Check discard_granularity in vm + 5.Detach disk device + """ + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + + hotplug = "yes" == params.get("virt_device_hotplug") + part_path = "/dev/%s" + + # Skip test if version not match expected one + libvirt_version.is_libvirt_feature_supported(params) + + if vm.is_alive(): + vm.destroy(gracefully=False) + + # Backup vm xml + vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vmxml = vmxml_backup.copy() + + test_scenario = params.get("test_scenario") + vhost_source_file_path = params.get("vhost_source_file_path") + discard_granularity_in_unit = params.get("discard_granularity_in_unit") + + vsock_service_id = None + target_bus = params.get("target_bus") + status_error = "yes" == params.get("status_error") + define_error = "yes" == params.get("define_error") + + try: + # For vhost user disk, it need setup socket first + if vhost_source_file_path: + create_vhostuser_image_file(vhost_source_file_path) + socket_path = params.get("socket_file") + vsock_service_id = start_vhost_sock_service(vhost_source_file_path, socket_path) + # For invalid discard granularity test, it need update value accordingly + elif test_scenario in ["failure_vm_tart"]: + params.update({'discard_granularity': params.get('invalid_discard_granularity')}) + + device_obj = create_customized_disk(params) + if test_scenario in ["live_update_discard_granularity"]: + device_obj_backup = device_obj.copy() + new_discard_granularity = params.get('new_discard_granularity') + discard_granularity = params.get('discard_granularity') + pattern = r'discard_granularity="%s"' % discard_granularity + replacement = 'discard_granularity="%s"' % new_discard_granularity + modify_line_with_pattern(device_obj_backup.xml, pattern, replacement) + if not hotplug: + vmxml.add_device(device_obj) + vmxml.sync() + vm.start() + vm.wait_for_login() + if hotplug: + virsh.attach_device(vm_name, device_obj.xml, + ignore_status=False, debug=True) + except xcepts.LibvirtXMLError as xml_error: + if not define_error: + test.fail("Failed to define VM:\n%s" % str(xml_error)) + else: + item_matched = params.get("define_error_msg") + if not re.search(r'%s' % item_matched, str(xml_error)): + test.fail("Get unexpected define error message from: %s" % str(xml_error)) + except virt_vm.VMStartError as details: + if not status_error: + test.fail("VM failed to start." + "Error: %s" % str(details)) + else: + status_error_msg = params.get("status_error_msg") + if not re.search(r'%s' % status_error_msg, str(details)): + test.fail("Get unexpected define error message from: %s" % str(details)) + else: + session = vm.wait_for_login() + time.sleep(20) + new_disk, _ = libvirt_disk.get_non_root_disk_name(session) + session.close() + + if not libvirt_disk.check_virtual_disk_io(vm, new_disk, path=part_path): + test.fail("fail to execute write operations on newly added disk:%s" % new_disk) + if test_scenario in ["live_update_discard_granularity"]: + result = virsh.update_device(vm_name, device_obj_backup.xml, flagstr="--live", + debug=True, ignore_status=True) + error_msg = params.get("error_msg") + libvirt.check_result(result, error_msg) + elif test_scenario in ["boundary_vm_tart"]: + expected_attribute = "yes" == params.get("expected_attribute") + check_vm_dumpxml(params, test, expected_attribute) + else: + if not check_blockio_discard_granularity(vm, new_disk, discard_granularity_in_unit): + test.fail("fail to check discard granularity on newly added disk:%s" % new_disk) + if hotplug: + virsh.detach_device(vm_name, device_obj.xml, flagstr="--live", + debug=True, ignore_status=False) + finally: + if vm.is_alive(): + vm.destroy(gracefully=False) + # Restoring vm + vmxml_backup.sync() + + if vhost_source_file_path: + # Kill all qemu-storage-daemon process on host + process.run("pidof qemu-storage-daemon && killall qemu-storage-daemon", + ignore_status=True, verbose=True, shell=True) + + if vsock_service_id: + stop_vsock_service_cmd = "systemctl stop %s" % vsock_service_id + process.run(stop_vsock_service_cmd, ignore_status=True, verbose=True, shell=True) + # Clean up files + for file_path in cleanup_files: + if os.path.exists(file_path): + os.remove(file_path) From bdd6aed4cdab0b934a61141469e176ba940f8d02 Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 10 Apr 2024 18:59:32 +0800 Subject: [PATCH 0337/1055] migration: Add case to test disk size XXX-300490 - VM live migration with copy storage - migrate a disk to an equal or larger disk size Signed-off-by: lcheng --- .../target_image_larger_than_source.cfg | 60 ++++ .../target_image_larger_than_source.py | 272 ++++++++++++++++++ 2 files changed, 332 insertions(+) create mode 100644 libvirt/tests/cfg/migration_with_copy_storage/target_image_larger_than_source.cfg create mode 100644 libvirt/tests/src/migration_with_copy_storage/target_image_larger_than_source.py diff --git a/libvirt/tests/cfg/migration_with_copy_storage/target_image_larger_than_source.cfg b/libvirt/tests/cfg/migration_with_copy_storage/target_image_larger_than_source.cfg new file mode 100644 index 00000000000..399a239ab64 --- /dev/null +++ b/libvirt/tests/cfg/migration_with_copy_storage/target_image_larger_than_source.cfg @@ -0,0 +1,60 @@ +- migration_with_copy_storage.target_image_larger_than_source: + type = target_image_larger_than_source + migration_setup = 'yes' + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = "" + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = "qemu:///system" + image_convert = "no" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + setup_nfs = "no" + server_ip = "${migrate_dest_host}" + server_user = "${remote_user}" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "${remote_user}" + client_pwd = "${migrate_source_pwd}" + status_error = "no" + start_vm = "no" + disk_size = "10G" + target_disk_size = "20G" + disk_format = "raw" + slice_offset = "0" + slice_size = "10737418240" + disk_source_name = "${nfs_mount_dir}/target_image_larger_than_source.raw" + disk_slice = {"slice_type": "storage", "slice_offset": "${slice_offset}", "slice_size": "${slice_size}"} + simple_disk_check_after_mig = "yes" + variants: + - p2p: + virsh_migrate_options = "--live --p2p --verbose --copy-storage-all" + - non_p2p: + virsh_migrate_options = "--live --verbose --copy-storage-all" + variants: + - src_disk_raw: + disk_type = "file" + src_disk_dict = {"type_name": "${disk_type}", "device": "disk", "driver": {"name": "qemu", "type":"raw"}, "source": {"attrs": {"file": "${disk_source_name}"}, "slices": ${disk_slice}}, "target":{"dev": "vda", "bus": "virtio"}} + - src_disk_block: + disk_type = "block" + src_iscsi_size = "11000M" + src_lv_name = "src_test_image" + src_vg_name = "src_copy_migration" + src_block_path = "/dev/${src_vg_name}/${src_lv_name}" + src_disk_dict = {"type_name": "${disk_type}", "device": "disk", "driver": {"name": "qemu", "type":"raw"}, "source": {"attrs": {"dev": "${src_block_path}"}, "slices": ${disk_slice}}, "target":{"dev": "vda", "bus": "virtio"}} + variants: + - target_disk_raw: + target_disk_type = "file" + target_disk_dict = {"type_name": "${target_disk_type}", "device": "disk", "driver": {"name": "qemu", "type":"raw"}, "source": {"attrs": {"file": "${disk_source_name}"}, "slices": ${disk_slice}}, "target":{"dev": "vda", "bus": "virtio"}} + - target_disk_block: + target_disk_type = "block" + target_iscsi_size = "21000M" + target_lv_name = "target_test_image" + target_vg_name = "target_copy_migration" + target_block_path = "/dev/${target_vg_name}/${target_lv_name}" + target_disk_dict = {"type_name": "${target_disk_type}", "device": "disk", "driver": {"name": "qemu", "type":"raw"}, "source": {"attrs": {"dev": "${target_block_path}"}, "slices": ${disk_slice}}, "target":{"dev": "vda", "bus": "virtio"}} diff --git a/libvirt/tests/src/migration_with_copy_storage/target_image_larger_than_source.py b/libvirt/tests/src/migration_with_copy_storage/target_image_larger_than_source.py new file mode 100644 index 00000000000..3829e3e7169 --- /dev/null +++ b/libvirt/tests/src/migration_with_copy_storage/target_image_larger_than_source.py @@ -0,0 +1,272 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: Liping Cheng +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +import os +import shutil + +from avocado.utils import process + +from virttest import data_dir +from virttest import remote +from virttest import utils_misc +from virttest import utils_test +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.devices import disk +from virttest.staging import lv_utils +from virttest.utils_libvirt import libvirt_disk +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.migration import base_steps +from provider.migration import migration_base + +dev_target = None + + +def setup_disk_on_source(vm, params, test): + """ + Setup disk on source host + + :param vm: VM object + :param params: dictionary with the test parameters + :param test: test object + """ + disk_size = params.get("disk_size") + disk_format = params.get("disk_format") + src_iscsi_size = params.get("src_iscsi_size") + src_lv_name = params.get("src_lv_name") + src_vg_name = params.get("src_vg_name") + disk_type = params.get("disk_type") + disk_source_name = params.get("disk_source_name") + src_block_path = params.get("src_block_path") + client_ip = params.get("client_ip") + slice_offset = params.get("slice_offset") + slice_size = params.get("slice_size") + + test.log.info("Prepare disk on source.") + blk_source = vm.get_first_disk_devices()['source'] + if disk_type == "block": + dev_src = libvirt.setup_or_cleanup_iscsi(is_setup=True, is_login=True, image_size=src_iscsi_size, emulated_image="emulated-iscsi1", portal_ip=client_ip) + if not lv_utils.vg_check(src_vg_name): + lv_utils.vg_create(src_vg_name, dev_src) + if not lv_utils.lv_check(src_vg_name, src_lv_name): + lv_utils.lv_create(src_vg_name, src_lv_name, disk_size) + cmd = "qemu-img convert -f qcow2 -O %s %s %s" % (disk_format, blk_source, src_block_path) + else: + cmd = "qemu-img convert -f qcow2 -O %s %s %s" % (disk_format, blk_source, disk_source_name) + process.run(cmd, shell=True) + + +def setup_migratable_xml(vm_name, params): + """ + Set migratable xml + + :param vm_name: vm name + :param params: dictionary with the test parameters + """ + target_disk_type = params.get("target_disk_type") + target_disk_dict = eval(params.get("target_disk_dict")) + + mig_disk = disk.Disk(type_name=target_disk_type) + mig_disk.setup_attrs(**target_disk_dict) + + guest_xml = vm_xml.VMXML.new_from_dumpxml(vm_name, options="--migratable") + guest_xml.remove_all_device_by_type("disk") + guest_xml.add_device(mig_disk) + guest_xml.xmltreefile.write() + tmp_dir = data_dir.get_tmp_dir() + xmlfile = os.path.join(tmp_dir, "xml_file") + shutil.copyfile(guest_xml.xml, xmlfile) + params.update({"virsh_migrate_extra": "--xml %s" % xmlfile}) + + +def setup_disk_on_target(params, test, block_dev): + """ + Setup disk on target host + + :param params: dictionary with the test parameters + :param test: test object + :param block_dev: remote disk manager object + """ + disk_format = params.get("disk_format") + target_iscsi_size = params.get("target_iscsi_size") + target_lv_name = params.get("target_lv_name") + target_vg_name = params.get("target_vg_name") + target_disk_size = params.get("target_disk_size") + target_disk_type = params.get("target_disk_type") + disk_source_name = params.get("disk_source_name") + target_block_path = params.get("target_block_path") + server_ip = params.get("server_ip") + server_user = params.get("server_user", "root") + server_pwd = params.get("server_pwd") + client_ip = params.get("client_ip") + + test.log.info("Prepare disk on target.") + if target_disk_type == "block": + dev_target, _ = libvirt.setup_or_cleanup_iscsi(is_setup=True, is_login=False, image_size=target_iscsi_size, emulated_image="emulated-iscsi2", portal_ip=client_ip) + remote_dev = block_dev.iscsi_login_setup(client_ip, dev_target) + block_dev.create_vg(target_vg_name, remote_dev) + block_dev.create_image("lvm", size=target_disk_size, vgname=target_vg_name, lvname=target_lv_name, sparse=False, timeout=60) + else: + test.log.info("Prepare a raw format image on target.") + remote_session = remote.remote_login("ssh", server_ip, "22", + server_user, server_pwd, + r'[$#%]') + utils_misc.make_dirs(os.path.dirname(disk_source_name), remote_session) + libvirt_disk.create_disk("file", path=disk_source_name, + size=target_disk_size, disk_format=disk_format, + session=remote_session) + remote_session.close() + + +def cleanup_disk_on_source(params, test): + """ + Cleanup disk on source host + + :param params: dictionary with the test parameters + :param test: test object + """ + src_lv_name = params.get("src_lv_name") + src_vg_name = params.get("src_vg_name") + disk_type = params.get("disk_type") + disk_source_name = params.get("disk_source_name") + client_ip = params.get("client_ip") + + test.log.info("Cleanup disk on source.") + if disk_type == "block": + if lv_utils.lv_check(src_vg_name, src_lv_name): + lv_utils.lv_remove(src_vg_name, src_lv_name) + if lv_utils.vg_check(src_vg_name): + lv_utils.vg_remove(src_vg_name) + libvirt.setup_or_cleanup_iscsi(is_setup=False, emulated_image="emulated-iscsi1", portal_ip=client_ip) + cmd = "dmsetup ls" + ret = process.run(cmd, shell=True).stdout_text.strip() + dev_name = "%s-%s" % (src_vg_name, src_lv_name) + if dev_name in ret: + cmd = "dmsetup remove %s" % dev_name + process.run(cmd, shell=True) + else: + cmd = "rm -rf %s" % disk_source_name + process.run(cmd, shell=True) + + +def cleanup_disk_on_target(params, test, block_dev): + """ + Cleanup disk on target host + + :param params: dictionary with the test parameters + :param test: test object + :param block_dev: remote disk manager object + """ + target_lv_name = params.get("target_lv_name") + target_vg_name = params.get("target_vg_name") + target_disk_type = params.get("target_disk_type") + disk_source_name = params.get("disk_source_name") + server_ip = params.get("server_ip") + server_user = params.get("server_user", "root") + server_pwd = params.get("server_pwd") + client_ip = params.get("client_ip") + + test.log.info("Cleanup disk on target.") + run_on_target = remote.RemoteRunner(host=server_ip, username=server_user, password=server_pwd) + if target_disk_type == "block": + block_dev.remove_path("lvm", "/dev/%s/%s" % (target_vg_name, target_lv_name)) + block_dev.remove_vg(target_vg_name) + block_dev.iscsi_login_setup(client_ip, dev_target, is_login=False) + libvirt.setup_or_cleanup_iscsi(is_setup=False, emulated_image="emulated-iscsi2", portal_ip=client_ip) + cmd = "dmsetup ls" + ret = remote.run_remote_cmd(cmd, params, run_on_target, ignore_status=False).stdout_text.strip() + dev_name = "%s-%s" % (target_vg_name, target_lv_name) + if dev_name in ret: + cmd = "dmsetup remove %s" % dev_name + remote.run_remote_cmd(cmd, params, run_on_target, ignore_status=False) + else: + cmd = "rm -rf %s" % disk_source_name + remote.run_remote_cmd(cmd, params, run_on_target, ignore_status=False) + + +def run(test, params, env): + """ + To verify that live migration with copying storage when target image size + is larger than source image size. + + :param test: test object + :param params: dictionary with the test parameters + :param env: dictionary with test environment. + """ + def setup_test(): + """ + Setup steps + + """ + migrate_desturi_port = params.get("migrate_desturi_port") + migrate_desturi_type = params.get("migrate_desturi_type", "tcp") + src_disk_dict = eval(params.get("src_disk_dict")) + + test.log.info("Setup steps.") + migration_obj.conn_list.append(migration_base.setup_conn_obj(migrate_desturi_type, params, test)) + migration_obj.remote_add_or_remove_port(migrate_desturi_port) + + setup_disk_on_source(vm, params, test) + + new_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + new_xml.remove_all_device_by_type('disk') + libvirt_vmxml.modify_vm_device(new_xml, 'disk', src_disk_dict) + + vm.start() + vm.wait_for_login().close() + + setup_disk_on_target(params, test, block_dev) + setup_migratable_xml(vm_name, params) + + def verify_test(): + """ + Verify steps + + """ + test.log.info("Verify steps.") + target_disk_size = params.get("target_disk_size") + desturi = params.get("virsh_migrate_desturi") + + virsh.blockresize(vm_name, "vda", target_disk_size, ignore_status=False, uri=desturi) + migration_obj.verify_default() + + def cleanup_test(): + """ + Cleanup steps + + """ + test.log.info("Cleanup steps.") + srcuri = params.get("virsh_migrate_connect_uri") + desturi = params.get("virsh_migrate_desturi") + + vm.connect_uri = desturi + if vm.is_alive(): + vm.destroy() + vm.connect_uri = srcuri + + cleanup_disk_on_target(params, test, block_dev) + cleanup_disk_on_source(params, test) + + vm_name = params.get("migrate_main_vm") + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + block_dev = utils_test.RemoteDiskManager(params) + + try: + setup_test() + migration_obj.run_migration() + verify_test() + finally: + cleanup_test() + migration_obj.cleanup_connection() From 140d496f00297043de2a1ceef711b4f63d8fea8a Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 19 Apr 2024 11:03:57 +0800 Subject: [PATCH 0338/1055] virtual_disks: Add a vhostvdpa-blk test This PR adds: VIRT-300441: Define&Start vm with two disks of vhostvdpa backend Signed-off-by: Yingshun Cui --- ..._vm_with_multi_vhostvdpa_backend_disks.cfg | 12 +++++ ...t_vm_with_multi_vhostvdpa_backend_disks.py | 45 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_multi_vhostvdpa_backend_disks.cfg create mode 100644 libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_multi_vhostvdpa_backend_disks.py diff --git a/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_multi_vhostvdpa_backend_disks.cfg b/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_multi_vhostvdpa_backend_disks.cfg new file mode 100644 index 00000000000..9ae52ba2c33 --- /dev/null +++ b/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_multi_vhostvdpa_backend_disks.cfg @@ -0,0 +1,12 @@ +- virtual_disks.vhostvdpa.define_start_multi_disks: + type = define_start_vm_with_multi_vhostvdpa_backend_disks + start_vm = no + simulator = "yes" + func_supported_since_libvirt_ver = (9, 10, 0) + only x86_64 + + disk_vdpa_attrs = {"source": {"attrs": {"dev": "/dev/vhost-vdpa-0"}}, "type_name": "vhostvdpa"} + disk2_vdpa_attrs = {"source": {"attrs": {"dev": "/dev/vhost-vdpa-1"}}, "type_name": "vhostvdpa"} + disk_driver = {"driver": {"name": "qemu", "type": "raw", "cache": "none", "io": "threads", "copy_on_read": "on", "discard": "unmap", "detect_zeroes": "on"}} + disk_attrs = {"device": "disk", "target": {"dev": "vdb", "bus": "virtio"}, **${disk_vdpa_attrs}, **${disk_driver}} + disk2_attrs = {"device": "disk", "target": {"dev": "vdc", "bus": "virtio"}, **${disk2_vdpa_attrs}, **${disk_driver}} diff --git a/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_multi_vhostvdpa_backend_disks.py b/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_multi_vhostvdpa_backend_disks.py new file mode 100644 index 00000000000..d26b545dc4a --- /dev/null +++ b/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/define_start_vm_with_multi_vhostvdpa_backend_disks.py @@ -0,0 +1,45 @@ +from virttest import libvirt_version +from virttest import utils_vdpa +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_disk +from virttest.utils_libvirt import libvirt_vmxml + +VIRSH_ARGS = {'debug': True, 'ignore_status': False} + + +def run(test, params, env): + """ + Verify that a vm can have more than one vhost-vdpa backend disks, + and both the two disks can be successfully written to/read from. + """ + libvirt_version.is_libvirt_feature_supported(params) + disk_attrs = eval(params.get("disk_attrs", "{}")) + disk2_attrs = eval(params.get("disk2_attrs", "{}")) + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + test.log.info("TEST_STEP: Define a VM with vhost-vdpa disk.") + test_env_obj = utils_vdpa.VDPASimulatorTest(sim_dev_module="vdpa_sim_blk", mgmtdev="vdpasim_blk") + test_env_obj.setup(dev_num=2) + vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", hpgs=False) + libvirt_vmxml.modify_vm_device(vm_xml.VMXML.new_from_dumpxml(vm_name), "disk", disk_attrs, 1) + libvirt_vmxml.modify_vm_device(vm_xml.VMXML.new_from_dumpxml(vm_name), "disk", disk2_attrs, 2) + + vm.start() + vm_session = vm.wait_for_login() + + test.log.info("TEST_STEP: Check r/w operations on vhost-vdpa disk.") + new_disks = libvirt_disk.get_non_root_disk_names(vm_session) + vm_session.close() + for disk in new_disks: + if not libvirt_disk.check_virtual_disk_io(vm, disk[0]): + test.fail("Failed to check disk io for %s!" % disk[0]) + + finally: + bkxml.sync() + test_env_obj.cleanup() From bb53ea1359d2a3c59134ffb0876f87a07449eb66 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Tue, 19 Mar 2024 06:10:54 -0400 Subject: [PATCH 0339/1055] Update the check about coalesce On latest rhel 8 system, when coalesce is not set, the default value for rx_frames change to n/a. While on rhel 9, it's 0. Both of them are expectable. Update the check. Signed-off-by: Yalan Zhang --- .../update_device/update_device_coalesce.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py b/libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py index bd87def340c..15d0a926acf 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py +++ b/libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py @@ -25,10 +25,14 @@ def check_coalesce_rx_frames(tap_device, rx_frames, test): """ coal_params = network_base.get_ethtool_coalesce(tap_device) LOG.debug(f'coalesce parameters from ethtool: {coal_params}') - coal_rx_frames = coal_params.get('rx-frames') + coal_rx_frames = str(coal_params.get('rx-frames')).strip() if coal_rx_frames != rx_frames: - test.fail(f'rx-frames of {tap_device} should be {rx_frames}, ' - f'not {coal_rx_frames}') + if rx_frames == '0' and coal_rx_frames == 'n/a': + LOG.debug("The expected value is 0, but got n/a, which is " + "also acceptable.") + else: + test.fail(f'rx-frames of {tap_device} should be {rx_frames}, ' + f'not {coal_rx_frames}') def run(test, params, env): From 0bfa24bd58786b7d011ee0d4bc73755efb5e1a57 Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 20 May 2024 14:08:06 +0800 Subject: [PATCH 0340/1055] migration: Update tls case Add precopy/postcopy scenarios. Signed-off-by: lcheng --- .../network_data_transport/tls.cfg | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tls.cfg b/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tls.cfg index fd963fad808..12d801f0a98 100644 --- a/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tls.cfg +++ b/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tls.cfg @@ -37,8 +37,6 @@ libvirtd_file_type = "virtqemud" libvirtd_debug_level = "1" libvirtd_debug_filters = "1:*" - check_str_local_log = '["blockdev-add.*tls-creds.*tls-hostname", "migrate-set-parameters.*tls-creds.*tls-hostname"]' - variants: - p2p: virsh_migrate_options = '--live --p2p --verbose' @@ -49,3 +47,9 @@ copy_storage_option = "--copy-storage-all" - copy_storage_inc: copy_storage_option = "--copy-storage-inc" + variants: + - with_precopy: + check_str_local_log = '["blockdev-add.*tls-creds.*tls-hostname", "migrate-set-parameters.*tls-creds.*tls-hostname"]' + - with_postcopy: + postcopy_options = '--postcopy --timeout 10 --timeout-postcopy' + check_str_local_log = '["blockdev-add.*tls-creds", "migrate-set-parameters.*tls-creds.*tls-hostname"]' From 29dd0cd186fab2f70a206817cbb7a3d359d19830 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 18 Apr 2024 06:29:01 -0400 Subject: [PATCH 0341/1055] Add new network case of attach user type interface - VIRT-296615 - [attach-device][user][slirp] attach-device with user type interface Signed-off-by: Haijiao Zhao --- .../attach_user_type_iface.cfg | 17 +++ .../attach_user_type_iface.py | 116 ++++++++++++++++++ provider/virtual_network/network_base.py | 5 +- 3 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 libvirt/tests/cfg/virtual_network/attach_detach_device/attach_user_type_iface.cfg create mode 100644 libvirt/tests/src/virtual_network/attach_detach_device/attach_user_type_iface.py diff --git a/libvirt/tests/cfg/virtual_network/attach_detach_device/attach_user_type_iface.cfg b/libvirt/tests/cfg/virtual_network/attach_detach_device/attach_user_type_iface.cfg new file mode 100644 index 00000000000..ffa08de2292 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/attach_detach_device/attach_user_type_iface.cfg @@ -0,0 +1,17 @@ +- virtual_network.attach_device.user_type_iface: + type = attach_user_type_iface + start_vm = no + outside_ip = 'www.redhat.com' + vm_ping_outside = pass + variants user_type: + - root_user: + test_user = root + virsh_uri = 'qemu:///system' + - non_root_user: + test_user = USER.EXAMPLE + test_passwd = PASSWORD.EXAMPLE + unpr_vm_name = UNPRIVILEGED_VM.EXAMPLE + virsh_uri = 'qemu+ssh://${test_user}@localhost/session' + iface_attrs = {'type_name': 'user', 'mac_address': '00:11:22:33:44:55', 'model': 'virtio', 'ips': [{'family': 'ipv4', 'address': '172.17.2.0', 'prefix': '24'}, {'family': 'ipv6', 'address': '2001:db8:ac10:fd01::', 'prefix': '64'}]} + expect_ipv4 = 172.17.2.15 + expect_ipv6 = 2001:db8:ac10:fd01: diff --git a/libvirt/tests/src/virtual_network/attach_detach_device/attach_user_type_iface.py b/libvirt/tests/src/virtual_network/attach_detach_device/attach_user_type_iface.py new file mode 100644 index 00000000000..8ad797654af --- /dev/null +++ b/libvirt/tests/src/virtual_network/attach_detach_device/attach_user_type_iface.py @@ -0,0 +1,116 @@ +import logging + +import aexpect +from virttest import remote +from virttest import utils_net +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_unprivileged +from virttest.utils_libvirt import libvirt_vmxml + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test attach interface with user type + """ + root = 'root_user' == params.get('user_type', '') + if root: + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + virsh_ins = virsh + else: + vm_name = params.get('unpr_vm_name') + test_user = params.get('test_user', '') + test_passwd = params.get('test_passwd', '') + unpr_vm_args = { + 'username': params.get('username'), + 'password': params.get('password'), + } + vm = libvirt_unprivileged.get_unprivileged_vm(vm_name, test_user, + test_passwd, + **unpr_vm_args) + uri = f'qemu+ssh://{test_user}@localhost/session' + virsh_ins = virsh.VirshPersistent(uri=uri) + host_session = aexpect.ShellSession('su') + remote.VMManager.set_ssh_auth(host_session, 'localhost', test_user, + test_passwd) + host_session.close() + + iface_attrs = eval(params.get('iface_attrs', '{}')) + expect_ipv4 = params.get('expect_ipv4') + expect_ipv6 = params.get('expect_ipv6') + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( + vm_name, virsh_instance=virsh_ins) + bkxml = vmxml.copy() + + try: + vmxml.del_device('interface', by_tag=True) + vmxml.sync(virsh_instance=virsh_ins) + mac = iface_attrs['mac_address'] + LOG.debug( + f'VMXML of {vm_name}:\n{virsh_ins.dumpxml(vm_name).stdout_text}') + + vm.start() + vm.wait_for_serial_login().close() + + iface = libvirt_vmxml.create_vm_device_by_type( + 'interface', iface_attrs) + LOG.debug(f'Interface to attach:\n{iface}') + + virsh_ins.attach_device(vm_name, iface.xml, **VIRSH_ARGS) + LOG.debug(virsh_ins.dumpxml(vm_name).stdout_text) + + # Check attached xml + iface_at = network_base.get_iface_xml_inst( + vm_name, 'after attached on vm', virsh_ins=virsh_ins) + if iface_at.mac_address != iface.mac_address: + test.fail(f'Mac address of attached iface xml does not match with ' + f'original xml, attach might failed') + + # log in the guest, and check the network function, it works well, + # ip and ping + session = vm.wait_for_serial_login() + vm_iface_info = utils_net.get_linux_iface_info( + mac=mac, session=session) + LOG.debug(f'Interface in vm: {vm_iface_info}') + for addr in vm_iface_info['addr_info']: + if addr['scope'] != 'global': + continue + if addr['family'] == 'inet': + if addr['local'] != expect_ipv4: + test.fail(f'Wrong ipv4 addr: {addr["local"]}') + if addr['family'] == 'inet6': + if not addr['local'].startswith(expect_ipv6): + test.fail(f'Wrong ipv6 addr {addr["local"]}') + + LOG.info('Login vm to check whether the network works well via ping.') + ips = {'outside_ip': params.get('outside_ip')} + network_base.ping_check(params, ips, session, force_ipv4=True) + + # Detach iface + virsh_ins.detach_device( + vm_name, iface.xml, wait_for_event=True, **VIRSH_ARGS) + + # Check iface in vm disappeared + vm_iface_info_unplug = utils_net.get_linux_iface_info( + mac=mac, session=session) + LOG.debug(vm_iface_info_unplug) + if vm_iface_info_unplug is not None: + test.fail(f'iface should be removed, should not found ' + f'{vm_iface_info_unplug} in vm') + + # Check xml disappeared + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( + vm_name, virsh_instance=virsh_ins) + iface_list = vmxml.devices.by_device_tag('interface') + if len(iface_list): + test.fail('Found interface xml on vm which should be detached:' + f'{iface_list}') + finally: + bkxml.sync(virsh_instance=virsh_ins) diff --git a/provider/virtual_network/network_base.py b/provider/virtual_network/network_base.py index 0793be72256..ddbe21634c7 100644 --- a/provider/virtual_network/network_base.py +++ b/provider/virtual_network/network_base.py @@ -265,7 +265,7 @@ def set_static_ip(iface, ip, netmask, session): session.cmd(f'ifconfig {iface} {ip}/{netmask}') -def get_iface_xml_inst(vm_name, comment, index=0, options=''): +def get_iface_xml_inst(vm_name, comment, index=0, options='', virsh_ins=virsh): """ Get iface xml instance with given vm and index @@ -274,7 +274,8 @@ def get_iface_xml_inst(vm_name, comment, index=0, options=''): :param index: index of interface on vm, defaults to 0 :return: xml instance of interface """ - vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name, options=options) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name, options=options, + virsh_instance=virsh_ins) iface = vmxml.get_devices('interface')[index] LOG.debug(f'Interface xml ({comment}):\n{iface}') return iface From c5af877a1bf726fdd531dc07171f0277f372e508 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 25 Apr 2024 00:13:19 -0400 Subject: [PATCH 0342/1055] Add new case of update iface with unchangable config - VIRT-294999 - [update-device][link state] update link state with other exsiting unchangable configuration Signed-off-by: Haijiao Zhao --- .../update_iface_with_unchangable.cfg | 19 +++++ .../update_iface_with_unchangable.py | 73 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/update_device/update_iface_with_unchangable.cfg create mode 100644 libvirt/tests/src/virtual_network/update_device/update_iface_with_unchangable.py diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_unchangable.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_unchangable.cfg new file mode 100644 index 00000000000..8eb2748953a --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_unchangable.cfg @@ -0,0 +1,19 @@ +- virtual_network.update_device.with_unchangable: + type = update_iface_with_unchangable + start_vm = no + host_iface = + iface_attrs_boot = 2 + iface_attrs_model = virtio + iface_attrs_rom = {'bar': 'on', 'file': '/usr/share/ipxe/1af41000.rom'} + driver_host = {'driver_host': {'csum': 'off', 'gso': 'off', 'tso4': 'off', 'tso6': 'off', 'ecn': 'off', 'ufo': 'off', 'mrg_rxbuf': 'off'}} + driver_guest = {'driver_guest': {'csum': 'off', 'tso4': 'off', 'tso6': 'off', 'ecn': 'off', 'ufo': 'off'}} + driver_attr = {'driver_attr': {'name': 'vhost', 'txmode': 'iothread', 'ioeventfd': 'on', 'event_idx': 'off', 'queues': '5', 'rx_queue_size': '256', 'tx_queue_size': '256'}} + iface_attrs_driver = {**${driver_host}, **${driver_guest}, **${driver_attr}} + iface_attrs_link_state = up + iface_attrs_target = {'dev': 'tar'} + iface_attrs_mtu = {'size': '1500'} + iface_attrs_type_name = network + iface_attrs_source = {'network': 'default', 'bridge': 'virbr0'} + iface_attrs_tune = {'sndbuf': 1600} + iface_attrs_alias = {'name': 'ua-823c76fa-ee1d-4278-a613-2ba8ba179b61'} + update_attrs = {'link_state': 'down'} diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_with_unchangable.py b/libvirt/tests/src/virtual_network/update_device/update_iface_with_unchangable.py new file mode 100644 index 00000000000..6aa0bec5099 --- /dev/null +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_with_unchangable.py @@ -0,0 +1,73 @@ +import logging + +from virttest import utils_net +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + To test that libvirt can compare current xml and the xml to be updated correctly. + keep all the attributes which do not support live update in the xml unchanged, + also with that can be live updated changed, try to update it. It should succeed. + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + # Setup boot config of vmxml + osxml = vmxml.os + osxml.del_boots() + vmxml.os = osxml + libvirt_vmxml.modify_vm_device(vmxml, 'disk', {'boot': '1'}) + + vmxml.del_device('interface', by_tag=True) + + iface_attrs = {k.replace('iface_attrs_', ''): v + if v[0].isalnum() else eval(v) + for k, v in params.items() + if k.startswith('iface_attrs_')} + + libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs) + LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + vm.start() + + iface = network_base.get_iface_xml_inst(vm_name, 'on vm') + mac = iface.mac_address + update_attrs = eval(params.get('update_attrs', '{}')) + LOG.debug(f'Update iface with attrs: {update_attrs}') + iface.setup_attrs(**update_attrs) + LOG.debug(f'Update iface with xml:\n{iface}') + + virsh.update_device(vm_name, iface.xml, **VIRSH_ARGS) + + iface_update = network_base.get_iface_xml_inst(vm_name, 'after update') + LOG.debug(f'link state after update: {iface_update.link_state}') + if iface_update.link_state != 'down': + test.fail('Link state of interface should be down after update') + + # Check update result on vm with ethtool + session = vm.wait_for_serial_login() + vm_iface_info = utils_net.get_linux_iface_info( + mac=mac, session=session) + LOG.debug(f'iface info on vm: {vm_iface_info}') + ethtool_output = session.cmd_output( + f'ethtool {vm_iface_info["ifname"]}') + LOG.debug(f'ethtool output:\n{ethtool_output}') + LOG.debug(f'"Link detected" should be no') + if 'Link detected: no' not in ethtool_output: + test.fail('ethtool check inside vm failed.') + + finally: + bkxml.sync() From 68a0062720b8ded6410c5c45bfe7f1026c26918c Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Mon, 20 May 2024 18:43:41 +0800 Subject: [PATCH 0343/1055] Add nbdkit case about curl.time option Signed-off-by: Ming Xie --- v2v/tests/cfg/nbdkit/nbdkit.cfg | 7 +++++++ v2v/tests/src/nbdkit/nbdkit.py | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/v2v/tests/cfg/nbdkit/nbdkit.cfg b/v2v/tests/cfg/nbdkit/nbdkit.cfg index 5f07038b81b..96a0ef766a8 100644 --- a/v2v/tests/cfg/nbdkit/nbdkit.cfg +++ b/v2v/tests/cfg/nbdkit/nbdkit.cfg @@ -120,6 +120,13 @@ byte_size = '1 0xff 256' version_required = "[nbdkit-server-1.36.1-1,)" checkpoint = 'ones_byte' + - curl: + only source_none..dest_none + variants: + - time: + version_required = "[nbdkit-server-1.36.1-1,)" + checkpoint = 'check_curl_time_option' + external_image_url = EXTERNAL_IMAGE_FAKE_URL - run: variants: - vddk7_0: diff --git a/v2v/tests/src/nbdkit/nbdkit.py b/v2v/tests/src/nbdkit/nbdkit.py index 3e70fea5f58..b0793f8974c 100644 --- a/v2v/tests/src/nbdkit/nbdkit.py +++ b/v2v/tests/src/nbdkit/nbdkit.py @@ -684,6 +684,13 @@ def test_tar_filter(): elif entry != 'latest-rhel9.img' and not re.search('nbdkit.*error', output): test.fail('fail to test tar filter') + def check_curl_time_option(): + image_url = params_get(params, 'external_image_url') + cmd = process.run("nbdkit -rvf -U - curl %s -D curl.times=1 -D curl.verbose=1 -D curl.verbose.ids=1 " + "--run 'nbdcopy -p $uri null:'" % image_url, shell=True, ignore_status=True) + if not re.search(r'nbdkit: debug: times .*-D curl.times=1.*', cmd.stderr_text): + test.fail('fail to test curl.time option') + if version_required and not multiple_versions_compare( version_required): test.cancel("Testing requires version: %s" % version_required) @@ -753,5 +760,7 @@ def test_tar_filter(): test_evil_filter() elif checkpoint == 'test_tar_filter': test_tar_filter() + elif checkpoint == 'check_curl_time_option': + check_curl_time_option() else: test.error('Not found testcase: %s' % checkpoint) From 0060a8ae811045fc65cce9b500cff26ad669a0e4 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Mon, 20 May 2024 07:01:53 -0400 Subject: [PATCH 0344/1055] Fixup:SoftwareManager not found Fix ERROR: module 'avocado.utils.software_manager' has no attribute 'SoftwareManager' Signed-off-by: Haijiao Zhao --- libvirt/tests/src/libvirt_package.py | 2 +- libvirt/tests/src/libvirtd_start.py | 2 +- libvirt/tests/src/save_and_restore/restore_from_local_file.py | 2 +- libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py | 2 +- libvirt/tests/src/virt_cmd/virt_top.py | 2 +- v2v/tests/src/install.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libvirt/tests/src/libvirt_package.py b/libvirt/tests/src/libvirt_package.py index 8ef95a06dfb..31a775f78cb 100644 --- a/libvirt/tests/src/libvirt_package.py +++ b/libvirt/tests/src/libvirt_package.py @@ -37,7 +37,7 @@ def run(test, params, env): elif libvirtd_state == "off": utils_libvirtd.libvirtd_stop() # if package exist, remove it - sm = software_manager.SoftwareManager() + sm = software_manager.manager.SoftwareManager() pkg_exist = [] for item in pkg_list: if sm.check_installed(item): diff --git a/libvirt/tests/src/libvirtd_start.py b/libvirt/tests/src/libvirtd_start.py index b6e17c3efe7..03a02855704 100644 --- a/libvirt/tests/src/libvirtd_start.py +++ b/libvirt/tests/src/libvirtd_start.py @@ -82,7 +82,7 @@ def _check_errors(): # In RHEL6 iptables-services and firewalld is not supported # So try to install all required packages but ignore failures logging.info('Preparing firewall related packages') - software_mgr = software_manager.SoftwareManager() + software_mgr = software_manager.manager.SoftwareManager() for pkg in ['iptables', 'iptables-services', 'firewalld']: if not software_mgr.check_installed(pkg): software_mgr.install(pkg) diff --git a/libvirt/tests/src/save_and_restore/restore_from_local_file.py b/libvirt/tests/src/save_and_restore/restore_from_local_file.py index e45d5f42c2b..52398dca326 100644 --- a/libvirt/tests/src/save_and_restore/restore_from_local_file.py +++ b/libvirt/tests/src/save_and_restore/restore_from_local_file.py @@ -57,7 +57,7 @@ def setup_bypass_cache(check_cmd, test): :param test: test instance :return: subprocess instance to run check command """ - sm = software_manager.SoftwareManager() + sm = software_manager.manager.SoftwareManager() if not sm.check_installed('lsof'): test.error("Need to install lsof on host") sp = process.SubProcess(check_cmd, shell=True) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py index 9688f9a12ad..c45ae7bb96a 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py @@ -432,7 +432,7 @@ def build_vm_xml(vm_name, **dargs): # For bypass_cache test. Run a shell command to check fd flags while # executing managedsave command - software_mgr = software_manager.SoftwareManager() + software_mgr = software_manager.manager.SoftwareManager() if not software_mgr.check_installed('lsof'): logging.info('Installing lsof package:') software_mgr.install('lsof') diff --git a/libvirt/tests/src/virt_cmd/virt_top.py b/libvirt/tests/src/virt_cmd/virt_top.py index 9c692f37649..e2d03421635 100644 --- a/libvirt/tests/src/virt_cmd/virt_top.py +++ b/libvirt/tests/src/virt_cmd/virt_top.py @@ -21,7 +21,7 @@ def run(test, params, env): machine. """ # Install virt-top package if missing. - software_mgr = software_manager.SoftwareManager() + software_mgr = software_manager.manager.SoftwareManager() if not software_mgr.check_installed('virt-top'): logging.info('Installing virt-top package:') software_mgr.install('virt-top') diff --git a/v2v/tests/src/install.py b/v2v/tests/src/install.py index c3930e955be..9c7db511e63 100644 --- a/v2v/tests/src/install.py +++ b/v2v/tests/src/install.py @@ -23,7 +23,7 @@ def run(test, params, env): minor_failure = False minor_failure_reasons = [] - sm = software_manager.SoftwareManager() + sm = software_manager.manager.SoftwareManager() for name in params.get("installers", "").split(): installer_obj = installer.make_installer(name, params, test) From 79f6010911973a126b703b5ed699da4b1be4b6e5 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 17 Apr 2024 17:50:50 +0200 Subject: [PATCH 0345/1055] filesystem_device: test usage for unprivileged users Add new test cases checking that non-root users can mount and use a host directory. Variants: 2 vms, 1 filesystem 1 vm, 1 filesystem 1 vm, 2 filesystems Notes: 1. use wait_for_serial login because the unprivileged user's VMs are created with interface type 'user' per default, so there's no vnet nic and therefore wait_for_login can't get the address 2. Due to 1. it's better to use the 'safe' command functions to avoid timeouts because there might be kernel messages breaking the output scan. 3. For hugepages, the unprivileged user needs access to a hugetlbfs and update their local libvirt configuration. After updating the configuration, the process needs to be killed to force the daemon to be loaded with the new configuration. This is expected. 4. Make sure to close and reopen sessions for the virsh instance of the unprivileged user to avoid running into issues when setting up hugepages. 5. virsh_sysinfo: update reference after change in avocado-vt that this test implementation depends on. Signed-off-by: Sebastian Mitterle --- .../filesystem_device_unprivileged.cfg | 35 ++ .../tests/src/virsh_cmd/host/virsh_sysinfo.py | 2 +- .../filesystem_device_unprivileged.py | 408 ++++++++++++++++++ spell.ignore | 1 + 4 files changed, 445 insertions(+), 1 deletion(-) create mode 100644 libvirt/tests/cfg/virtual_device/filesystem_device_unprivileged.cfg create mode 100644 libvirt/tests/src/virtual_device/filesystem_device_unprivileged.py diff --git a/libvirt/tests/cfg/virtual_device/filesystem_device_unprivileged.cfg b/libvirt/tests/cfg/virtual_device/filesystem_device_unprivileged.cfg new file mode 100644 index 00000000000..50e57312c70 --- /dev/null +++ b/libvirt/tests/cfg/virtual_device/filesystem_device_unprivileged.cfg @@ -0,0 +1,35 @@ +- virtual_devices.filesystem_device_unprivileged: + type = filesystem_device_unprivileged + # 10.0.0-6 + func_supported_since_libvirt_ver = (10, 0, 0) + take_regular_screendumps = "no" + start_vm = no + vcpus_per_cell = 2 + extra_hugepages = 128 + test_user = test + test_passwd = test + pseries: + vcpus_per_cell = 5 + aarch64: + extra_hugepages = 0 + s390-virtio: + with_numa = no + variants plugmode: + - hotplug: + - coldplug: + variants: + - one_guest: + unpr_vms = unpr-vm + - two_guests: + unpr_vms = unpr-vm,unpr-vm2 + variants memorybacking: + - with_hugepages: + s390-virtio: + kvm_module_parameters = hpage=1 + - with_memfd: + - with_shm: + variants: + - one_fs: + fs_dicts = [{'accessmode': 'passthrough', 'source': {'dir': '/tmp/dir1'}, "target": {'dir': 'mount_tag1'}, 'binary': {'path':'/usr/libexec/virtiofsd', 'lock_posix':'off','flock':'off', 'sandbox_mode':'namespace', 'xattr':'on', 'cache_mode':'none'}, 'driver': {'type': 'virtiofs', 'queue':'1024'}}] + - two_fs: + fs_dicts = [{'accessmode': 'passthrough', 'source': {'dir': '/tmp/dir1'}, "target": {'dir': 'mount_tag1'}, 'binary': {'lock_posix':'off','flock':'off', 'sandbox_mode':'namespace'}, 'driver': {'type': 'virtiofs'}}, {'accessmode': 'passthrough', 'source': {'dir': '/tmp/dir2'}, "target": {'dir': 'mount_tag2'}, 'binary': {'lock_posix':'off','flock':'off', 'sandbox_mode':'namespace', 'xattr':'on', 'cache_mode':'none'}, 'driver': {'type': 'virtiofs'}}] diff --git a/libvirt/tests/src/virsh_cmd/host/virsh_sysinfo.py b/libvirt/tests/src/virsh_cmd/host/virsh_sysinfo.py index 4f66dd1951f..1c621e77020 100644 --- a/libvirt/tests/src/virsh_cmd/host/virsh_sysinfo.py +++ b/libvirt/tests/src/virsh_cmd/host/virsh_sysinfo.py @@ -60,7 +60,7 @@ def run(test, params, env): dmidecode_version = get_processor_version() if dmidecode_version: # Get processor version from result - sysinfo_xml = libvirt_xml.SysinfoXML() + sysinfo_xml = libvirt_xml.VMSysinfoXML() sysinfo_xml['xml'] = output sysinfo_xml.xmltreefile.write() diff --git a/libvirt/tests/src/virtual_device/filesystem_device_unprivileged.py b/libvirt/tests/src/virtual_device/filesystem_device_unprivileged.py new file mode 100644 index 00000000000..2b466b2b6cc --- /dev/null +++ b/libvirt/tests/src/virtual_device/filesystem_device_unprivileged.py @@ -0,0 +1,408 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: smitterl@redhat.com +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import logging +import os +import shutil +import stat + +from aexpect import ShellSession + +from avocado.core.exceptions import TestError +from avocado.utils import process + +from virttest import libvirt_version +from virttest import remote +from virttest import utils_ids +from virttest import virsh +from virttest.staging import utils_memory +from virttest.libvirt_xml.vm_xml import VMXML +from virttest.utils_config import LibvirtQemuConfig +from virttest.utils_libvirt.libvirt_unprivileged import get_unprivileged_vm +from virttest.utils_libvirt.libvirt_vmxml import create_vm_device_by_type + +LOG = logging.getLogger('avocado.' + __name__) +allow_all = stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO + +unpr_virsh = "" +vmxmls = {} +backupxmls = [] +vms = [] +test_user = "" +test_passwd = "" +_params = {} +backup_huge_pages_num = 0 +user_config_path = "" +hugepages_user_path = "/user_hugepages" +with_hugepages = False +qemu_config = None + + +def get_unprivileged_vms(): + """ + Store the unprivileged user's VMs and the virsh + object for interaction as unprivileged user. + + Assumes that the non-root user exists on the system + and that they have VMs of given names. + """ + + global vmxmls, backupxmls, vms + + vm_names = _params.get("unpr_vms").split(",") + unpr_vm_args = { + "username": _params.get("username"), + "password": _params.get("password"), + } + + vms = [get_unprivileged_vm(vm_name, test_user, test_passwd, **unpr_vm_args) + for vm_name in vm_names] + + for vm_name in vm_names: + vmxmls[vm_name] = VMXML.new_from_inactive_dumpxml( + vm_name, + virsh_instance=unpr_virsh, + ) + + backupxmls = [vmxmls[name].copy() for name in vmxmls] + + +def _initialize_unpr_virsh(): + """ + Initializes the global instance of the virsh commands object. + """ + + global unpr_virsh + unpr_uri = f"qemu+ssh://{test_user}@localhost/session" + unpr_virsh = virsh.VirshPersistent(uri=unpr_uri, safe=True) + + host_session = ShellSession("su") + remote.VMManager.set_ssh_auth(host_session, "localhost", + test_user, test_passwd) + host_session.close() + + +def _refresh_vmxmls(): + """ + Refreshes the global list of VMXML instances under test + so they are up-to-date after changes. + """ + global vmxmls + for name in vmxmls: + vmxmls[name] = VMXML.new_from_dumpxml(name, virsh_instance=unpr_virsh) + LOG.debug("Current XML: %s", vmxmls[name]) + + +def configure_hugepages_for_unprivileged_user(mem): + """ + Allocates hugepages and creates a mount for the unprivileged + test user. + + Assume that all VMs have the same max_mem value so if + the QEMU configuration has already been altered it assumes + hugepages have already been set up and will return. + + It kills the user's process at the end to force reload + with the new configuration. + + :param mem: The memory size that needs to be allocated + in the same unit as the VMXML + """ + global backup_huge_pages_num, qemu_config + if qemu_config: + return + if not os.path.exists(user_config_path): + shutil.copyfile(LibvirtQemuConfig.conf_path, user_config_path) + os.chmod(user_config_path, allow_all) + extra_hugepages = _params.get_numeric("extra_hugepages") + host_hp_size = utils_memory.get_huge_page_size() + backup_huge_pages_num = utils_memory.get_num_huge_pages() + huge_pages_num = 0 + huge_pages_num += mem // host_hp_size + extra_hugepages + utils_memory.set_num_huge_pages(huge_pages_num) + process.run(f"mkdir {hugepages_user_path}", + ignore_status=False) + process.run(f"mount -t hugetlbfs hugetlbfs {hugepages_user_path}", + ignore_status=False) + process.run(f"chmod a+wrx {hugepages_user_path}", + ignore_status=False) + qemu_config = LibvirtQemuConfig(user_config_path) + qemu_config.hugetlbfs_mount = [hugepages_user_path] + process.run(f"killall --user {test_user} virtqemud", shell=True) + + +def clean_up_hugepages_for_unprivileged_user(): + """ + Cleans up the set up for hugepages + """ + qemu_config.restore() + process.run(f"killall --user {test_user} virtqemud", shell=True) + utils_memory.set_num_huge_pages(backup_huge_pages_num) + process.run(f"umount {hugepages_user_path}") + process.run(f"rm -rf {hugepages_user_path}") + + +def add_memory_backing(): + """ + Adds and removes all present filesystem devices + It also sets up hugepages for the unprivileged user assuming + that all VMs would require the same number of memory + """ + + global backup_huge_pages_num, with_hugepages + memorybacking = _params.get("memorybacking") + with_hugepages = "with_hugepages" == memorybacking + with_memfd = "with_memfd" == memorybacking + with_numa = "yes" == _params.get("with_numa") + vcpus_per_cell = _params.get("vcpus_per_cell") + + for name in vmxmls.copy(): + vmxml = vmxmls[name] + if vmxml.max_mem < 1024000: + vmxml.max_mem = 1024000 + if with_hugepages: + configure_hugepages_for_unprivileged_user(len(vms)*vmxml.max_mem) + numa_no = None + if with_numa: + numa_no = vmxml.vcpu // vcpus_per_cell if vmxml.vcpu != 1 else 1 + + vmxml.remove_all_device_by_type("filesystem") + + VMXML.set_vm_vcpus( + vmxml.vm_name, + vmxml.vcpu, + numa_number=numa_no, + virsh_instance=None, + vmxml=vmxml, + ) + VMXML.set_memoryBacking_tag( + vmxml.vm_name, + access_mode="shared", + hpgs=with_hugepages, + memfd=with_memfd, + virsh_instance=None, + vmxml=vmxml, + ) + + _initialize_unpr_virsh() + vmxml.sync(virsh_instance=unpr_virsh) + vmxmls[vmxml.vm_name] = vmxml + + +def cold_or_hot_plug_filesystem(): + """ + Cold or hot plugs the filesystem and + starts the VMs. + + It handles the VM state and makes sure + they are running for further testing. + """ + + for vm in vms: + if "hotplug" == _params.get("plugmode") and not vm.is_alive(): + vm.start() + vm.wait_for_serial_login().close() + if "coldplug" == _params.get("plugmode") and vm.is_alive(): + vm.destroy() + + for fs_dict in fs_dicts: + source_dir = fs_dict["source"]["dir"] + if not os.path.exists(source_dir): + os.mkdir(source_dir) + os.chmod(source_dir, allow_all) + + fs = create_vm_device_by_type("filesystem", fs_dict) + os.chmod(fs.xml, allow_all) + unpr_virsh.attach_device( + vm.name, + fs.xml, + flagstr="--current", + debug=True, + ignore_status=False + ) + + if not vm.is_alive(): + vm.start() + _refresh_vmxmls() + + +def check_virtiofs_idmap(): + """ + Checks if the unprivileged VM is running with the correct + user related ids. + """ + + user_info = utils_ids.get_user_ids(test_user) + for name in vmxmls: + for fs in vmxmls[name].get_devices("filesystem"): + utils_ids.check_idmap_xml_filesystem_device(user_info, fs) + + +def mount_fs(session): + """ + Mounts the folder inside of the guest + + :param session: Guest console session + """ + + for fs_dict in fs_dicts: + mount_tag = fs_dict["target"]["dir"] + mount_dir = f"/mnt/{mount_tag}" + session.cmd_output_safe(f"mkdir {mount_dir}") + session.cmd_output_safe(f"mount -t virtiofs {mount_tag} {mount_dir}") + + +def create_file(session): + """ + Creates a file in the guest's mounted filesystem(s) + + :param session: guest console session + """ + + for fs_dict in fs_dicts: + mount_tag = fs_dict["target"]["dir"] + mount_dir = f"/mnt/{mount_tag}" + session.cmd_output_safe(f"dd if=/dev/zero of={mount_dir}/testfile bs=1M count=10") + session.cmd_output_safe("sync") + + +def check_md5sum(sessions): + """ + Returns the md5sum of the created file + + :param sessions: a list of two console sessions + to take md5sum from and compare + them; the second session might + be a host session (if there is only + 1 vm in the test scenario) + """ + + sums = {0: [], 1: []} + for fs_dict in fs_dicts: + for i in range(len(sessions)): + mount_tag = fs_dict["target"]["dir"] + mount_dir = f"/mnt/{mount_tag}" + source_dir = fs_dict["source"]["dir"] + cmd = f"md5sum {mount_dir}/testfile" + if i == 1 and len(vms) == 1: + cmd = f"md5sum {source_dir}/testfile" + o = sessions[i].cmd_output_safe(cmd) + sums[i].append(o.split()[0]) + + if sums[0] != sums[1]: + raise TestError("The md5sums don't match: %s" % sums) + + +def check_filesystem(after="attach"): + """ + Prepares the filesystems in the guest(s) and runs some checks + + This assumes that the filesystem is shared either between guest + and host or between two guests. + + :param after: if "attach" expect commands to succeed + if "detach" expect commands to fail + """ + + session1 = vms[0].wait_for_serial_login() + if len(vms) == 2: + session2 = vms[1].wait_for_serial_login() + else: + session2 = ShellSession("su") + + try: + mount_fs(session1) + create_file(session1) + if len(vms) == 2: + mount_fs(session2) + check_md5sum([session1, session2]) + + except TestError as e: + if after == "detach": + pass + else: + raise e + + finally: + session1.close() + session2.close() + + +def cold_or_hot_unplug_filesystem(): + """ + Cold or hot unplugs the filesystem and + starts the VMs. + + It handles the VM state and makes sure they are + running for further checks. + """ + + for vm in vms: + if "coldplug" == _params.get("plugmode") and vm.is_alive(): + vm.destroy() + + for fs_dict in fs_dicts: + fs = create_vm_device_by_type("filesystem", fs_dict) + os.chmod(fs.xml, allow_all) + unpr_virsh.detach_device( + vm.name, + fs.xml, + flagstr="--current", + debug=True, + ignore_status=False + ) + + if not vm.is_alive(): + vm.start() + + +def initialize(params): + """ + Initializes parameters that are needed globally for all test + variants. + + :param params: the test parameters + """ + + global _params, fs_dicts, test_user, user_config_path, test_passwd + libvirt_version.is_libvirt_feature_supported(params) + _params = params + fs_dicts = eval(_params.get("fs_dicts")) + test_user = _params.get("test_user", "") + test_passwd = _params.get("test_passwd", "") + user_config_path = f"/home/{test_user}/.config/libvirt/qemu.conf" + _initialize_unpr_virsh() + + +def run(test, params, env): + """ + Test running VMs with a filesystem device as unprivileged users. + """ + + global backupxmls, unpr_virsh, fs_dicts, with_hugepages + initialize(params) + try: + get_unprivileged_vms() + add_memory_backing() + cold_or_hot_plug_filesystem() + check_virtiofs_idmap() + check_filesystem(after="attach") + cold_or_hot_unplug_filesystem() + check_filesystem(after="detach") + finally: + for xml in backupxmls: + xml.sync(virsh_instance=unpr_virsh) + if unpr_virsh: + del unpr_virsh + for fs_dict in fs_dicts: + source_dir = fs_dict["source"]["dir"] + if os.path.exists(source_dir): + shutil.rmtree(source_dir) + if with_hugepages: + clean_up_hugepages_for_unprivileged_user() diff --git a/spell.ignore b/spell.ignore index ffd6ad5ed09..808b27ec0a7 100644 --- a/spell.ignore +++ b/spell.ignore @@ -585,6 +585,7 @@ mdev mdevctl mellanox mem +memoryBacking mems memballoon memhog From 8d6a23de039f670fdde11c4bb38662e561a90aa6 Mon Sep 17 00:00:00 2001 From: nanli Date: Thu, 22 Feb 2024 15:50:17 +0800 Subject: [PATCH 0346/1055] add case for dimm with memory allocation and numa xxxx-299047: Dimm memory with various memory allocation and guest numa settings Signed-off-by: nanli --- ...emory_with_memory_alloccation_and_numa.cfg | 65 ++++++ ...memory_with_memory_alloccation_and_numa.py | 195 ++++++++++++++++++ 2 files changed, 260 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_memory_alloccation_and_numa.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/dimm_memory_with_memory_alloccation_and_numa.py diff --git a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_memory_alloccation_and_numa.cfg b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_memory_alloccation_and_numa.cfg new file mode 100644 index 00000000000..ab2d6e486da --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_memory_alloccation_and_numa.cfg @@ -0,0 +1,65 @@ +- memory.devices.dimm.memory_allocation_and_numa: + type = dimm_memory_with_memory_alloccation_and_numa + no s390-virtio + start_vm = no + mem_model = "dimm" + mem_value = 2097152 + current_mem = 2097152 + numa_mem = 2097152 + mem_dict = "'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'" + target_size = 524288 + target_size_big = 3145728 + format_size = "params.get('target_size')" + basic_xpath = [{'element_attrs':[".//memory[@unit='KiB']"],'text':'${mem_value}'},{'element_attrs':[".//currentMemory[@unit='KiB']"],'text':'${current_mem}'}] + dimm_numa_xpath = [{'element_attrs':[".//cell[@memory='%s']"]},{'element_attrs':[".//memory/target/size[@unit='KiB']"],'text':'%s'},{'element_attrs':[".//memory/target/node"],'text':'0'}] + dimm_dict = "{'mem_model':'${mem_model}','target': {'size': %s, 'size_unit': 'KiB'}}" + dimm_node_dict = "{'mem_model':'${mem_model}','target': {'size': %s, 'size_unit': 'KiB','node':0}}" + variants memory_allocation: + - no_maxmemory: + max_dict = "" + define_error = "cannot use/hotplug a memory device when domain 'maxMemory' is not defined" + hotplug_error = "${define_error}" + hotplug_error_2 = "can't add memory backend as guest has no NUMA nodes configured" + - no_slot: + max_mem = 10485760 + max_dict = '"max_mem_rt": ${max_mem}, "max_mem_rt_unit": "KiB"' + define_error = "failed to find an empty memory slot" + redefine_error = "both maximum memory size and memory slot count must be specified" + coldplug_error = "no free memory device slot available" + - with_slot: + max_mem = 10485760 + max_mem_slots = 16 + max_dict = '"max_mem_rt": ${max_mem}, "max_mem_rt_slots": ${max_mem_slots}, "max_mem_rt_unit": "KiB"' + variants numa_setting: + - no_numa: + numa_dict = "" + with_slot: + define_error = "At least one numa node has to be configured when enabling memory hotplug" + big_size_msg = "Total size of memory devices exceeds the total memory size" + no_maxmemory: + coldplug_error = "can't add memory backend as guest has no NUMA nodes configured" + - with_numa: + numa_dict = "'vcpu': 6,'cpu':{'numa_cell': [{'id': '0', 'cpus': '0-3', 'memory': '${numa_mem}'}]}" + with_slot: + define_error = "target NUMA node needs to be specified for memory device" + no_maxmemory: + coldplug_error = "cannot use/hotplug a memory device when domain 'maxMemory' is not defined" + variants device_operation: + - init_define_with_dimm: + - init_define_with_big_dimm: + only with_slot..no_numa + format_size = "" + dimm_dict = "{'mem_model':'${mem_model}','target': {'size': ${target_size_big}, 'size_unit': 'KiB'}, %s}" + - hotplug_without_node: + no_slot: + hotplug_error = "target NUMA node needs to be specified for memory device" + with_slot: + hotplug_error = "target NUMA node needs to be specified for memory device" + - hotplug_with_node: + dimm_dict = ${dimm_node_dict} + no_slot: + hotplug_error = "count of memory devices requiring memory slots '1' exceeds slots count '0'" + - coldplug_without_node: + coldplug_error_2 = "cannot use/hotplug a memory device when domain 'maxMemory' is not defined" + - coldplug_with_node: + dimm_dict = ${dimm_node_dict} diff --git a/libvirt/tests/src/memory/memory_devices/dimm_memory_with_memory_alloccation_and_numa.py b/libvirt/tests/src/memory/memory_devices/dimm_memory_with_memory_alloccation_and_numa.py new file mode 100644 index 00000000000..ad3ccfe555a --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/dimm_memory_with_memory_alloccation_and_numa.py @@ -0,0 +1,195 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.memory import memory_base + +virsh_dargs = {'debug': True, 'ignore_status': False} + + +def get_vm_attrs(test, params): + """ + Get vm attrs. + + :param test: test object + :param params: dictionary with the test parameters + :return vm_attrs: get updated vm attrs dict. + """ + mem_dict = params.get("mem_dict") + max_dict = params.get("max_dict") + numa_dict = params.get("numa_dict") + all_attrs = "" + for item in [mem_dict, max_dict, numa_dict]: + if item != "": + all_attrs += item + "," + + vm_attrs = eval("{"+all_attrs+"}") + test.log.debug("Get current vm attrs is :%s", vm_attrs) + + return vm_attrs + + +def define_guest(params, guest_xml): + """ + Define guest and check result. + + :param params: dictionary with the test parameters. + :param guest_xml: the xml you want to define. + """ + define_error = params.get("define_error") + device_operation = params.get("device_operation") + big_size_msg = params.get("big_size_msg") + + res = virsh.define(guest_xml.xml, debug=True) + if params.get('slot_no_numa'): + if device_operation == "init_define_with_big_dimm": + libvirt.check_result(res, big_size_msg) + else: + libvirt.check_exit_status(res) + else: + libvirt.check_result(res, define_error) + + +def check_hotplug_result(params, result): + """ + Check guest hot plug result + + :param params: dict wrapped with params. + :param result: hot plug result. + """ + mem_alloc = params.get("memory_allocation") + device_operation = params.get("device_operation") + numa_setting = params.get("numa_setting") + hotplug_error = params.get("hotplug_error") + hotplug_error_2 = params.get("hotplug_error_2") + + if mem_alloc == "no_maxmemory": + if numa_setting == "no_numa" and device_operation == "hotplug_with_node": + libvirt.check_result(result, hotplug_error_2) + elif mem_alloc == "with_slot" and device_operation == "hotplug_with_node": + libvirt.check_exit_status(result) + else: + libvirt.check_result(result, hotplug_error) + + +def check_coldplug_result(params, result): + """ + Check guest cold plug result + + :param params: dict wrapped with params. + :param result: cold plug result. + """ + mem_alloc = params.get("memory_allocation") + device_operation = params.get("device_operation") + coldplug_error = params.get("coldplug_error") + coldplug_error_2 = params.get("coldplug_error_2") + + if mem_alloc == "with_slot": + libvirt.check_exit_status(result) + elif mem_alloc == "no_slot": + libvirt.check_result(result, coldplug_error) + elif mem_alloc == "no_maxmemory": + if device_operation == "coldplug_without_node": + libvirt.check_result(result, coldplug_error_2) + else: + libvirt.check_result(result, coldplug_error) + + +def run(test, params, env): + """ + Verify dimm memory device works with various memory allocation + and guest numa settings. + """ + def run_test_init_define(): + """ + Test when define guest with dimm memory. + """ + test.log.info("TEST_STEP1: Define vm with dimm and memory allocation") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vmxml.setup_attrs(**vm_attrs) + vmxml.devices = vmxml.devices.append(mem_obj) + define_guest(params, vmxml) + + if params.get('slot_no_numa') and device_operation == "init_define_with_dimm": + test.log.info("TEST_STEP2,3: Start vm and check guest xml") + vm.start() + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + test.log.debug("Get guest xml:%s\n" % vmxml) + libvirt_vmxml.check_guest_xml_by_xpaths(vmxml, basic_xpath) + libvirt_vmxml.check_guest_xml_by_xpaths( + vmxml, eval(dimm_numa_xpath % (str(mem_value-int(target_size)), + target_size))) + + def run_test_coldplug(): + """ + Test guest cold plug with dimm memory. + """ + test.log.info("TEST_STEP1: Define vm without dimm") + original_vmxml.setup_attrs(**vm_attrs) + virsh.define(original_vmxml.xml, **virsh_dargs) + + test.log.info("TEST_STEP2: Cold plug vm with dimm") + ret = virsh.attach_device(vm_name, mem_obj.xml, debug=True, + flagstr="--config") + check_coldplug_result(params, ret) + + def run_test_hotplug(): + """ + Test guest hot plug with dimm memory. + """ + test.log.info("TEST_STEP1: Define vm without dimm") + original_vmxml.setup_attrs(**vm_attrs) + virsh.define(original_vmxml.xml, **virsh_dargs) + virsh.start(vm_name, **virsh_dargs) + vm.wait_for_login().close() + + test.log.info("TEST_STEP2: Hot plug vm with dimm") + res = virsh.attach_device(vm_name, mem_obj.xml, debug=True) + check_hotplug_result(params, res) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bkxml.sync() + + vm_name = params.get("main_vm") + original_vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = original_vmxml.copy() + vm = env.get_vm(vm_name) + memory_base.adjust_memory_size(params) + + vm_attrs = get_vm_attrs(test, params) + device_operation = params.get("device_operation") + fs = eval(params.get("format_size")) if params.get("format_size") else "" + dimm_dict = eval(params.get("dimm_dict") % fs) + mem_obj = libvirt_vmxml.create_vm_device_by_type('memory', dimm_dict) + + target_size = params.get("target_size") + mem_value = int(params.get("mem_value")) + basic_xpath = eval(params.get("basic_xpath")) + dimm_numa_xpath = params.get("dimm_numa_xpath") + run_test = eval('run_test_%s' % device_operation.split('_with')[0]) + + memory_allocation = params.get("memory_allocation") + numa_setting = params.get("numa_setting") + params.update( + {'slot_no_numa': memory_allocation == "with_slot" and numa_setting == "no_numa"}) + + try: + run_test() + + finally: + teardown_test() From 105c66867615a4fce32692d98cc76e0ddeffc356 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 21 May 2024 05:25:22 -0400 Subject: [PATCH 0347/1055] guest_os_booting/boot_order: expect error on s390x On s390x, booting from virtiofs is not supported. Expect an error message. Disable one other test. It would prepare the bootable environment before trying to set/use the boot from virtiofs. The preparation would take about 2 minutes. For this negative error message test on s390x, it's not necessary. Disable instead. Signed-off-by: Sebastian Mitterle --- .../boot_order/boot_from_virtiofs_device.cfg | 1 + .../hotplug_device_with_boot_order.cfg | 2 ++ .../hotplug_device_with_boot_order.py | 27 ++++++++++++++----- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_virtiofs_device.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_virtiofs_device.cfg index 79f56c9b859..f4a03b87540 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_virtiofs_device.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_virtiofs_device.cfg @@ -3,6 +3,7 @@ start_vm = no access_cmd = "virsh console %s" vm_memory = 15728640 + no s390-virtio variants: - start_guest: target_dir = "mount_tag" diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/hotplug_device_with_boot_order.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/hotplug_device_with_boot_order.cfg index bdf0b26fdbc..2722ca402f8 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/hotplug_device_with_boot_order.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/hotplug_device_with_boot_order.cfg @@ -18,3 +18,5 @@ source_dir = "/tmp" order_xpath = [{'element_attrs': ["./devices/filesystem/boot[@order='2']"]}] device_dict = {'target': {'dir': '${target_dir}'}, 'type_name': 'mount', 'source': {'dir': '${source_dir}'}, 'binary': {'path': '/usr/libexec/virtiofsd'}, 'accessmode': 'passthrough', 'boot': '2', 'driver': {'type': 'virtiofs'}} + s390-virtio: + expected_error = unsupported configuration: setting virtiofs boot order is supported only with PCI bus diff --git a/libvirt/tests/src/guest_os_booting/boot_order/hotplug_device_with_boot_order.py b/libvirt/tests/src/guest_os_booting/boot_order/hotplug_device_with_boot_order.py index fad6486a6be..e3320c3be25 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/hotplug_device_with_boot_order.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/hotplug_device_with_boot_order.py @@ -8,6 +8,7 @@ from virttest.libvirt_xml import vm_xml from virttest.libvirt_xml.devices.filesystem import Filesystem from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt from provider.virtual_disk import disk_base @@ -20,6 +21,7 @@ def run(test, params, env): 3) Check the dumpxml. 4) Hot-unplug the device. """ + def prepare_device_xml(vm_xml, device_type): """ Prepare the hot-plugged device xml. @@ -28,11 +30,12 @@ def prepare_device_xml(vm_xml, device_type): :params device_type: the device type :return: tuple, (device_xml, image_path) for the attached device """ - image_path = '' + image_path = "" # Need to use shared memory for filesystem device if device_type == "filesystem_device": - vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", - hpgs=False) + vm_xml.VMXML.set_memoryBacking_tag( + vm_name, access_mode="shared", hpgs=False + ) device_xml = Filesystem() device_xml.setup_attrs(**device_dict) else: @@ -50,14 +53,16 @@ def check_dumpxml(device_type, image_path, exist): vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) test.log.debug(f"The current guest xml is: {vmxml}") if device_type == "filesystem_device": - device_status = vmxml.devices.by_device_tag('filesystem') + device_status = vmxml.devices.by_device_tag("filesystem") else: device_status = vm_xml.VMXML.check_disk_exist(vm_name, image_path) if exist: if not device_status: test.fail(f"No {device_type} in guest xml after hotplug.") # To make sure the boot order is also in device xml - libvirt_vmxml.check_guest_xml_by_xpaths(vmxml, order_xpath, ignore_status=False) + libvirt_vmxml.check_guest_xml_by_xpaths( + vmxml, order_xpath, ignore_status=False + ) else: if device_status: test.fail(f"The {device_type} isn't detached successfully.") @@ -66,9 +71,10 @@ def check_dumpxml(device_type, image_path, exist): device_type = params.get("device_type") target_dev = params.get("target_dev") boot_order = params.get("boot_order", "1") + expected_error = params.get("expected_error", None) device_dict = eval(params.get("device_dict")) order_xpath = eval(params.get("order_xpath")) - virsh_dargs = {'debug': True, 'ignore_status': False} + virsh_dargs = {"debug": True, "ignore_status": False} vm = env.get_vm(vm_name) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) @@ -85,8 +91,15 @@ def check_dumpxml(device_type, image_path, exist): device_xml, image_path = prepare_device_xml(vm_xml, device_type) if not vm.is_alive(): virsh.start(vm_name, **virsh_dargs) + vm.wait_for_login() - virsh.attach_device(vm_name, device_xml.xml, **virsh_dargs) + ret = virsh.attach_device( + vm_name, device_xml.xml, debug=True, ignore_status=True + ) + libvirt.check_result(ret, expected_fails=expected_error) + if expected_error: + return + check_dumpxml(device_type, image_path, exist=True) test.log.info(f"STEP3: Hot-unplug the {device_type}.") From e0435470e2cac477ad0d6b53ab3ac5827ba0d274 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 15 May 2024 18:12:25 +0800 Subject: [PATCH 0348/1055] guest_os_booting: Update to take the 1st matching vm There may be many vms in env. For different types, update to take the 1st matching vm. Signed-off-by: Yingshun Cui --- .../guest_os_booting/guest_os_booting_base.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/provider/guest_os_booting/guest_os_booting_base.py b/provider/guest_os_booting/guest_os_booting_base.py index 0e70009febd..2c543952d4e 100644 --- a/provider/guest_os_booting/guest_os_booting_base.py +++ b/provider/guest_os_booting/guest_os_booting_base.py @@ -22,11 +22,18 @@ def get_vm(params): vms = params.get('vms').split() firmware_type = params.get('firmware_type') detected_distro = distro.detect() - os_type_dict = { - ('ovmf' if any([vm_xml.VMXML.new_from_dumpxml(v).os.fetch_attrs(). - get('os_firmware') == "efi", vm_xml.VMXML. - new_from_dumpxml(v).os.fetch_attrs().get('nvram')]) - else 'seabios'): v for v in vms} + os_type_dict = {} + for _vm in vms: + if os_type_dict.get("seabios") and os_type_dict.get("ovmf"): + break + vm_os_attrs = vm_xml.VMXML.new_from_dumpxml(_vm).os.fetch_attrs() + is_ovmf = any([vm_os_attrs.get('os_firmware') == "efi", vm_os_attrs.get('nvram')]) + if is_ovmf: + if not os_type_dict.get("ovmf"): + os_type_dict["ovmf"] = _vm + elif not os_type_dict.get("seabios"): + os_type_dict["seabios"] = _vm + LOG.debug(f"VMS: {os_type_dict}") if not firmware_type: LOG.debug("Get default vm") if detected_distro.name == 'rhel': From 7f3acd28625bf3e9229d67964ffab06ecdec93eb Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 22 May 2024 11:33:51 +0800 Subject: [PATCH 0349/1055] libvirtd: Add case to check max_anonymous_clients XXXX-55237 - [libvirtd][config]Check the default value of max_anonymous_clients Signed-off-by: lcheng --- .../tests/cfg/daemon/libvirtd/libvirtd.cfg | 28 +++++++++ libvirt/tests/src/daemon/libvirtd/libvirtd.py | 62 ++++++++++++++++++- 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/daemon/libvirtd/libvirtd.cfg b/libvirt/tests/cfg/daemon/libvirtd/libvirtd.cfg index 540a5eb105d..5fa7f02f23d 100644 --- a/libvirt/tests/cfg/daemon/libvirtd/libvirtd.cfg +++ b/libvirt/tests/cfg/daemon/libvirtd/libvirtd.cfg @@ -19,3 +19,31 @@ libvirtd_conf_dict = {'listen_tls': '0'} daemons_masked = 'libvirtd.socket libvirtd-ro.socket libvirtd-admin.socket libvirtd-tls.socket libvirtd-tcp.socket' sysconfig_conf_path = '/etc/sysconfig/libvirtd' + - check_max_anonymous_clients: + start_vm = no + log_level = 1 + log_filters = "1:*" + conf_list = ["max_anonymous_clients"] + check_string_in_log = "nclients_unauth_max=20" + require_modular_daemon = "yes" + variants daemon_name: + - libvirtd: + virsh_uri = "qemu:///system" + require_modular_daemon = "no" + - virtqemud: + virsh_uri = "qemu:///system" + - virtnwfilterd: + virsh_uri = "nwfilter:///system" + - virtinterfaced: + virsh_uri = "interface:///system" + - virtsecretd: + virsh_uri = "secret:///system" + - virtproxyd: + virsh_uri = "qemu+tcp:///system" + - virtstoraged: + virsh_uri = "storage:///system" + - virtnodedevd: + virsh_uri = "nodedev:///system" + - virtnetworkd: + virsh_uri = "network:///system" + log_file = "/var/log/libvirt/${daemon_name}.log" diff --git a/libvirt/tests/src/daemon/libvirtd/libvirtd.py b/libvirt/tests/src/daemon/libvirtd/libvirtd.py index 84848f5d805..bb2fde6b4cb 100644 --- a/libvirt/tests/src/daemon/libvirtd/libvirtd.py +++ b/libvirt/tests/src/daemon/libvirtd/libvirtd.py @@ -12,7 +12,9 @@ from avocado.utils import process +from virttest import utils_config from virttest import utils_libvirtd +from virttest import utils_split_daemons from virttest import utils_misc from virttest import utils_package from virttest import virsh @@ -22,7 +24,8 @@ msg_queue = Queue.Queue() - +daemon_conf = None +daemon = None # Using as lower capital is not the best way to do, but this is just a # workaround to avoid changing the entire file. @@ -291,6 +294,63 @@ def teardown_default(params, test): pass +def test_check_max_anonymous_clients(params, test): + """ + Test the default value of max_anonymous_clients. + + :param params: dict, test parameters + :param test: test object + """ + check_string_in_log = params.get("check_string_in_log") + daemon_name = params.get("daemon_name") + conf_list = eval(params.get("conf_list")) + log_level = params.get("log_level") + log_file = params.get("log_file") + log_filters = params.get("log_filters") + virsh_uri = params.get("virsh_uri") + require_modular_daemon = params.get('require_modular_daemon', "no") == "yes" + vm_name = params.get("main_vm", "avocado-vt-vm1") + + utils_split_daemons.daemon_mode_check(require_modular_daemon) + global daemon + global daemon_conf + daemon = utils_libvirtd.Libvirtd(daemon_name) + daemon_conf = utils_config.get_conf_obj(daemon_name) + + for item in conf_list: + try: + del daemon_conf[item] + except utils_config.ConfigNoOptionError: + test.log.info("No '%s' in config file.", item) + + daemon_conf.log_level = log_level + daemon_conf.log_outputs = "1:file:%s" % log_file + daemon_conf.log_filters = log_filters + daemon.restart() + + if daemon_name == "virtproxyd": + virtproxy_tcp = utils_libvirtd.DaemonSocket("virtproxyd-tcp.socket") + virtproxy_tcp.restart() + + virsh.start(vm_name, uri=virsh_uri, debug=True, ignore_status=True) + libvirt.check_logfile(check_string_in_log, log_file, str_in_log=True) + + +def teardown_check_max_anonymous_clients(params, test): + """ + Teardown for test the default value of max_anonymous_clients. + + :param params: dict, test parameters + :param test: test object + """ + global daemon + global daemon_conf + if daemon_conf: + daemon_conf.restore() + if daemon: + daemon.restart() + + def run(test, params, env): """ libvirtd daemon related tests. From b7573db8dab6c6b7fe000b893e37f72fd3a3fbd1 Mon Sep 17 00:00:00 2001 From: Qian Jianhua Date: Wed, 22 May 2024 16:14:37 +0800 Subject: [PATCH 0350/1055] numa: remove 'kernelpagesize_kB' parameter remove 'kernelpagesize_KB' parameter, and get pagesize with getpagesize(). Signed-off-by: Qian Jianhua --- .../cfg/numa/guest_numa_node_tuning/change_numa_tuning.cfg | 3 --- .../src/numa/guest_numa_node_tuning/change_numa_tuning.py | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/cfg/numa/guest_numa_node_tuning/change_numa_tuning.cfg b/libvirt/tests/cfg/numa/guest_numa_node_tuning/change_numa_tuning.cfg index fb602b2837b..63fac1b29de 100644 --- a/libvirt/tests/cfg/numa/guest_numa_node_tuning/change_numa_tuning.cfg +++ b/libvirt/tests/cfg/numa/guest_numa_node_tuning/change_numa_tuning.cfg @@ -17,7 +17,4 @@ mem_mode = 'preferred' - mem_mode_restrictive: mem_mode = 'restrictive' - kernelpagesize_kB = '4' - aarch64: - kernelpagesize_kB = '64' numa_memory = {'mode': '${mem_mode}', 'nodeset': '%s'} diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/change_numa_tuning.py b/libvirt/tests/src/numa/guest_numa_node_tuning/change_numa_tuning.py index 045aeecae5f..8b3acf760fb 100644 --- a/libvirt/tests/src/numa/guest_numa_node_tuning/change_numa_tuning.py +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/change_numa_tuning.py @@ -21,6 +21,7 @@ from virttest.utils_libvirt import libvirt_misc from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_test import libvirt +from virttest.staging import utils_memory from provider.numa import numa_base @@ -77,7 +78,7 @@ def verify_host_numa_memory_allocation(test_obj, check_N0=False): :param test_obj: NumaTest object """ mem_size = get_memory_in_vmxml(test_obj) - kernelpagesize_kB = test_obj.params.get('kernelpagesize_kB') + kernelpagesize_kB = utils_memory.getpagesize() out_numa_maps = numa_base.get_host_numa_memory_alloc_info(mem_size) all_nodes = test_obj.online_nodes_withmem N0_value = re.findall('N%s=(\d+)' % all_nodes[0], out_numa_maps) From 450f2047d6eae08322aaccf37a60d12d298e1523 Mon Sep 17 00:00:00 2001 From: nanli Date: Sun, 19 May 2024 21:14:26 +0800 Subject: [PATCH 0351/1055] add case for dimm memory hotplug xxxx-300402 Dimm memory device hot-plug Signed-off-by: nanli --- .../memory_devices/dimm_memory_hotplug.cfg | 68 +++++ .../memory_devices/dimm_memory_hotplug.py | 245 ++++++++++++++++++ provider/memory/memory_base.py | 78 +++++- 3 files changed, 390 insertions(+), 1 deletion(-) create mode 100644 libvirt/tests/cfg/memory/memory_devices/dimm_memory_hotplug.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/dimm_memory_hotplug.py diff --git a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hotplug.cfg b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hotplug.cfg new file mode 100644 index 00000000000..e6691180e6e --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hotplug.cfg @@ -0,0 +1,68 @@ +- memory.devices.dimm.hotplug: + no s390-virtio + type = dimm_memory_hotplug + start_vm = yes + mem_model = 'dimm' + allocate_size = "1572864" + allocate_memory = "${allocate_size}KiB" + target_size = "524288" + size_unit = 'KiB' + slot = '0' + node = 0 + plug_node = 0 + plug_slot = 1 + mem_value = 2097152 + current_mem = 2097152 + numa_mem = 1048576 + max_mem = 4194304 + max_mem_slots = 16 + plug_event = "device-added" + audit_cmd = "ausearch --start today -m VIRT_RESOURCE | grep 'mem'" + ausearch_check = 'old-mem=%d new-mem=%d' + expected_log = "ACPI_DEVICE_OST|device_add" + kernel_hp_file = '/sys/devices/system/node/node0/hugepages/hugepages-%skB/nr_hugepages' + max_dict = '"max_mem_rt": ${max_mem}, "max_mem_rt_slots": ${max_mem_slots}, "max_mem_rt_unit": "KiB"' + numa_dict = "'vcpu': 4,'cpu':{'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_mem}'}]}" + vm_attrs = {${numa_dict},${max_dict},'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'} + variants plug_dimm_type: + - target_and_address: + plug_node = 1 + plug_target_size = '1048576' + addr_dict = {'attrs': {'type':'dimm','slot':'${slot}'}} + plug_addr = {'attrs': {'type':'dimm','slot':'${plug_slot}'}} + plug_size_unit = "${size_unit}" + - source_and_mib: + target_size = "1024" + size_unit = 'MiB' + node = 1 + plug_node = 1 + plug_target_size = "512" + plug_size_unit = "MiB" + source_dict = {'nodemask': '0','pagesize': %d, 'pagesize_unit':'KiB'} + - plug_exceeded_max_mem: + plug_size_unit = "G" + plug_target_size = "2" + plug_error = "exceed domain's maxMemory config size '${max_mem}'" + - duplicate_addr: + plug_size_unit = "${size_unit}" + plug_target_size = "${target_size}" + base = "0x100000000" + addr_dict = {'attrs': {'type':'dimm','base': '${base}', 'slot':'${slot}'}} + plug_addr = {'attrs': {'type':'dimm','base': '${base}', 'slot':'${plug_slot}'}} + plug_error = "same address|overlaps" + - duplicate_slot: + base = "0x100000000" + plug_size_unit = "${size_unit}" + plug_slot = 0 + plug_target_size = "${target_size}" + addr_dict = {'attrs': {'type':'dimm','slot':'${slot}'}} + plug_addr = {'attrs': {'type':'dimm','base': '${base}', 'slot':'${plug_slot}'}} + plug_error = "memory device slot '0' is already being used by another memory device" + - zero_memory_unit_gb: + plug_size_unit = "G" + plug_target_size = "0" + plug_error = "property 'size' of memory-backend-ram doesn't take value '0'" + dimm_dict = {'mem_model':'${mem_model}','target': {'size':${target_size}, 'size_unit':'${size_unit}', 'node':${node}}} + plug_dimm_dict = {'mem_model':'${mem_model}','target': {'size':${plug_target_size}, 'size_unit':'${plug_size_unit}', 'node':${plug_node}}} + base_xpath = [{'element_attrs':[".//memory[@unit='KiB']"],'text':'%d'},{'element_attrs':[".//currentMemory[@unit='KiB']"],'text':'%d'}] + dimm_xpath = [{'element_attrs':[".//target/size[@unit='KiB']"],'text':'%s'},{'element_attrs':[".//address[@slot='%s']"]}] diff --git a/libvirt/tests/src/memory/memory_devices/dimm_memory_hotplug.py b/libvirt/tests/src/memory/memory_devices/dimm_memory_hotplug.py new file mode 100644 index 00000000000..e00b410306d --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/dimm_memory_hotplug.py @@ -0,0 +1,245 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import os + +from avocado.utils import process +from avocado.utils import memory + +from virttest import utils_misc + +from virttest.utils_test import libvirt +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml + +from provider.memory import memory_base +from virttest.staging import utils_memory + +virsh_dargs = {"ignore_status": False, "debug": True} + + +def adjust_dimm_dict(params): + """ + Adjust dimm memory dict and plugging dimm dict. + + :param params: dictionary with the test parameters + """ + source_dict = params.get("source_dict", "") + addr_dict = params.get("addr_dict", "") + plug_addr = params.get("plug_addr", "") + dimm_dict = eval(params.get("dimm_dict", "{}")) + plug_dimm_dict = eval(params.get("plug_dimm_dict", "{}")) + default_hugepage_size = memory.get_huge_page_size() + + if source_dict: + dimm_dict['source'] = eval(source_dict % default_hugepage_size) + plug_dimm_dict['source'] = eval(source_dict % default_hugepage_size) + if addr_dict: + dimm_dict['address'] = eval(addr_dict) + plug_dimm_dict['address'] = eval(plug_addr) + params.update({'dimm_dict': dimm_dict}) + params.update({'plug_dimm_dict': plug_dimm_dict}) + + +def adjust_size_unit(params, plugged=False): + """ + Adjust the unit of dimm target size and plugged dimm target size. + + :param params: cartesian config parameters. + :param plugged: the flag of after plugging. + :return target_size, plugged_size, init define dimm target size and + plugged dimm target size + """ + plug_dimm_type = params.get("plug_dimm_type") + if plug_dimm_type in ["source_and_mib", "zero_memory_unit_gb"]: + target_size = memory_base.convert_data_size( + params.get("target_size") + params.get('size_unit'), 'KiB') + else: + target_size = params.get("target_size") + + if plugged: + if plug_dimm_type in ["source_and_mib", "zero_memory_unit_gb"]: + plugged_size = memory_base.convert_data_size( + params.get("plug_target_size") + params.get('plug_size_unit'), 'KiB') + else: + plugged_size = params.get('plug_target_size') + else: + plugged_size = 0 + return int(target_size), int(plugged_size) + + +def attach_dimm_and_check_result(test, params): + """ + Attach dimm memory and check result. + + :param test: test object. + :param params: dictionary with the test parameters. + """ + plug_error = params.get('plug_error') + plug_event = params.get('plug_event') + plug_dict = params.get("plug_dimm_dict") + memory_base.plug_memory_and_check_result( + test, params, mem_dict=plug_dict, operation='attach', + expected_error=plug_error, expected_event=plug_event) + + +def check_guest_virsh_dominfo(vm, test, params, plugged=False): + """ + Check current memory value and memory value in virsh dominfo result. + + :param vm: vm object. + :param test: test object. + :param params: dictionary with the test parameters. + :param plugged: the flag of checking after plugging dimm. + """ + mem_value = int(params.get("mem_value")) + current_mem = int(params.get("current_mem")) + target_size, plugged_size = adjust_size_unit(params, plugged=plugged) + expected_mem = str(mem_value + target_size + plugged_size) + expected_curr = str(current_mem + plugged_size) + + memory_base.check_dominfo(vm, test, expected_mem, expected_curr) + + +def check_after_attach(vm, test, params): + """ + Check the below points after plugging or unplugging + 1. Check the audit log by ausearch. + 2. Check the libvirtd log. + 3. Check the memory allocation and memory device config. + 4. Check the memory info by virsh dominfo. + 5. Check the guest memory. + + :param vm: vm object. + :param test: test object. + :param params: dictionary with the test parameters. + :param operation: string, the flag for attaching or detaching. + """ + mem_value = int(params.get("mem_value")) + current_mem = int(params.get("current_mem")) + expected_log = params.get("expected_log") + audit_cmd = params.get("audit_cmd") + plug_slot = params.get("plug_slot") + libvirtd_log_file = os.path.join(test.debugdir, "libvirtd.log") + target_size, plugged_size = adjust_size_unit(params, plugged=True) + base_xpath, dimm_xpath = params.get("base_xpath"), params.get("dimm_xpath") + ausearch_check = params.get("ausearch_check") % ( + mem_value+target_size, mem_value+target_size+plugged_size) + + # Check the audit log by ausearch. + ausearch_result = process.run(audit_cmd, shell=True) + libvirt.check_result(ausearch_result, expected_match=ausearch_check) + test.log.debug("Check audit log %s successfully." % ausearch_check) + + # Check the libvirtd log. + result = utils_misc.wait_for( + lambda: libvirt.check_logfile(expected_log, libvirtd_log_file), timeout=20) + if not result: + test.fail("Can't get expected log %s in %s" % (expected_log, libvirtd_log_file)) + + # Check the memory allocation and memory device config. + vmxml = vm_xml.VMXML.new_from_dumpxml(vm.name) + libvirt_vmxml.check_guest_xml_by_xpaths( + vmxml, eval(base_xpath % (mem_value + target_size + plugged_size, + current_mem + plugged_size))) + libvirt_vmxml.check_guest_xml_by_xpaths( + vmxml.devices.by_device_tag("memory")[1], eval(dimm_xpath % (plugged_size, plug_slot))) + + # Check the memory info by virsh dominfo. + check_guest_virsh_dominfo(vm, test, params, plugged=True) + + # Check the guest memory. + session = vm.wait_for_login() + new_memtotal = utils_memory.memtotal(session) + session.close() + expected_memtotal = params.get('old_memtotal') + plugged_size + if new_memtotal != expected_memtotal: + test.fail("Memtotal is %s, should be %s " % (new_memtotal, expected_memtotal)) + test.log.debug("Check Memtotal successfully.") + + +def run(test, params, env): + """ + Verify dimm memory device hot-plug with different configs. + """ + def setup_test(): + """ + Allocate memory on the host. + """ + process.run("echo %d > %s" % ( + allocate_size / default_hugepage_size, + kernel_hp_file % default_hugepage_size), shell=True) + + def run_test(): + """ + 1. Define vm with dimm memory device. + 2. Hotplug dimm memory. + 3. Check audit log, libvirtd log, memory allocation and memory device + config. + """ + test.log.info("TEST_STEP1: Define vm with dimm memory") + memory_base.define_guest_with_memory_device(params, params.get("dimm_dict"), vm_attrs) + + test.log.info("TEST_STEP2: Start guest") + vm.start() + session = vm.wait_for_login() + + test.log.info("TEST_STEP3: Get the guest memory") + params.update({'old_memtotal': utils_memory.memtotal(session)}) + session.close() + + test.log.info("TEST_STEP4: Check the memory allocation and dimm config") + target_size, _ = adjust_size_unit(params) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + libvirt_vmxml.check_guest_xml_by_xpaths( + vmxml, eval(base_xpath % (mem_value + target_size, current_mem))) + libvirt_vmxml.check_guest_xml_by_xpaths( + vmxml.devices.by_device_tag("memory")[0], eval(dimm_xpath % (target_size, slot))) + + test.log.info("TEST_STEP5: Check the memory info by virsh dominfo") + check_guest_virsh_dominfo(vm, test, params) + + test.log.info("TEST_STEP6: Hot plug one dimm memory device") + attach_dimm_and_check_result(test, params) + + if plug_dimm_type in ["target_and_address", "source_and_mib"]: + test.log.info("TEST_STEP7:Check audit and libvirt log, memory " + "allocation and memory device config ") + check_after_attach(vm, test, params) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bkxml.sync() + process.run("echo 0 > %s" % (kernel_hp_file % default_hugepage_size), shell=True) + + vm_name = params.get("main_vm") + original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = original_xml.copy() + vm = env.get_vm(vm_name) + adjust_dimm_dict(params) + + slot = params.get("slot") + kernel_hp_file = params.get("kernel_hp_file") + vm_attrs = eval(params.get("vm_attrs", "{}")) + allocate_size = int(params.get("allocate_size")) + mem_value = int(params.get("mem_value")) + current_mem = int(params.get("current_mem")) + base_xpath, dimm_xpath = params.get("base_xpath"), params.get("dimm_xpath") + plug_dimm_type = params.get("plug_dimm_type") + default_hugepage_size = memory.get_huge_page_size() + + try: + setup_test() + run_test() + + finally: + teardown_test() diff --git a/provider/memory/memory_base.py b/provider/memory/memory_base.py index f878fc9f6bc..18171d4259e 100644 --- a/provider/memory/memory_base.py +++ b/provider/memory/memory_base.py @@ -5,11 +5,17 @@ from avocado.utils import cpu from avocado.utils import memory as avocado_mem +from virttest import virsh from virttest import libvirt_version from virttest import utils_misc - from virttest.libvirt_xml.devices import memory +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt from virttest.utils_version import VersionInterval +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_libvirt import libvirt_misc + +virsh_dargs = {"ignore_status": False, "debug": True} def convert_data_size(current_size, dest_unit="KiB"): @@ -149,3 +155,73 @@ def adjust_memory_size(params): params.update({'block_size': default_pagesize_KiB}) params.update({'request_size': default_pagesize_KiB}) params.update({'target_size': default_pagesize_KiB*2}) + + +def define_guest_with_memory_device(params, mem_attr_list, vm_attrs=None): + """ + Define guest with specified memory device. + + :param params: a dict for parameters. + :param mem_attr_list: memory device attributes list. + :param vm_attrs: basic vm attributes to define. + """ + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(params.get("main_vm")) + if vm_attrs: + vmxml.setup_attrs(**vm_attrs) + + if not isinstance(mem_attr_list, list): + mem_attr_list = [mem_attr_list] + for mem in mem_attr_list: + memory_object = libvirt_vmxml.create_vm_device_by_type('memory', mem) + vmxml.devices = vmxml.devices.append(memory_object) + vmxml.sync() + + +def plug_memory_and_check_result(test, params, mem_dict, operation='attach', + expected_error='', expected_event='', **kwargs): + """ + Hot plug or hot unplug memory and check event. + + :param test: test object. + :param params: dictionary with the test parameters. + :param mem_dict: the memory dict to plug. + :param operation: the operation of plug or unplug. + :param expected_error: expected error after plug or unplug. + :param expected_event: expected event for plug or unplug. + """ + vm_name = params.get('main_vm') + plug_dimm = libvirt_vmxml.create_vm_device_by_type('memory', mem_dict) + + wait_event = True if expected_event else False + if operation == "attach": + res = virsh.attach_device(vm_name, plug_dimm.xml, wait_for_event=wait_event, + event_type=expected_event, debug=True, **kwargs) + elif operation == "detach": + res = virsh.detach_device(vm_name, plug_dimm.xml, wait_for_event=wait_event, + event_type=expected_event, debug=True, **kwargs) + + if expected_error: + libvirt.check_result(res, expected_fails=expected_error) + else: + libvirt.check_exit_status(res) + + +def check_dominfo(vm, test, expected_max, expected_used): + """ + Check Max memory value and Used memory in virsh dominfo result. + + :param vm: vm object. + :param test: test object. + :param params: dictionary with the test parameters. + :param expected_max: expected Max memory in virsh dominfo. + :param expected_used: expected Used memory in virsh dominfo. + """ + result = virsh.dominfo(vm.name, **virsh_dargs).stdout_text.strip() + + dominfo_dict = libvirt_misc.convert_to_dict( + result, pattern=r'(\S+ \S+):\s+(\S+)') + if dominfo_dict["Max memory"] != expected_max: + test.fail("Memory value should be %s " % expected_max) + if dominfo_dict["Used memory"] != expected_used: + test.fail("Current memory should be %s " % expected_used) + test.log.debug("Check virsh dominfo successfully.") From 9c787bd0c13f1b5dedb907e2ef08a244a5f445ec Mon Sep 17 00:00:00 2001 From: nanli Date: Mon, 4 Mar 2024 17:31:45 +0800 Subject: [PATCH 0352/1055] add case for virtio-mem coldplug and cold unplug xxxx-299161:Virtio-mem memory device cold-plug and cold-unplug Signed-off-by: nanli --- .../virtio_mem_coldplug_and_unplug.cfg | 84 ++++++++ .../virtio_mem_coldplug_and_unplug.py | 193 ++++++++++++++++++ 2 files changed, 277 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_devices/virtio_mem_coldplug_and_unplug.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/virtio_mem_coldplug_and_unplug.py diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_coldplug_and_unplug.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_coldplug_and_unplug.cfg new file mode 100644 index 00000000000..9b7b4b416ca --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_coldplug_and_unplug.cfg @@ -0,0 +1,84 @@ +- memory.devices.virtio_mem.coldplug_and_unplug: + type = virtio_mem_coldplug_and_unplug + no s390-virtio + start_vm = "no" + mem_model = "virtio-mem" + target_size = 524288 + request_size = 524288 + size_unit = 'KiB' + request_unit = 'KiB' + block_unit = 'KiB' + plug_size_unit = 'KiB' + plug_request_unit = 'KiB' + plug_block_unit = 'KiB' + mem_value = 2097152 + current_mem = 2097152 + numa_mem = 1048576 + max_mem = 4194304 + max_mem_slots = 16 + max_dict = '"max_mem_rt": ${max_mem}, "max_mem_rt_slots": ${max_mem_slots}, "max_mem_rt_unit": "KiB"' + numa_dict = "'vcpu': 4,'cpu':{'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_mem}'}]}" + vm_attrs = {${numa_dict},${max_dict},'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'} + numa_xpath = [{'element_attrs':[".//cell[@unit='KiB']",".//cell[@id='0']",".//cell[@memory='${numa_mem}']"]}] + base = '0x100000000' + plug_option = " --config" + required_kernel = [5.14.0,) + guest_required_kernel = [5.8.0,) + func_supported_since_libvirt_ver = (8, 0, 0) + func_supported_since_qemu_kvm_ver = (6, 2, 0) + variants case: + - with_addr: + plug_target_size = 1048576 + plug_request_size = 1048576 + addr_dict = "'address':{'attrs': {'base': '${base}'}}" + virtio_dict = {'mem_model':'${mem_model}','target': {${addr_dict},'size':${target_size}, 'size_unit':'${size_unit}', 'node':0,'requested_size': ${request_size},'requested_unit':'${request_unit}', 'block_size': %s, 'block_unit':'${block_unit}'}} + unplug_dict = ${virtio_dict} + plug_dict = {'mem_model':'${mem_model}','target': {${addr_dict},'size':${plug_target_size},'requested_size': ${plug_request_size}, 'block_size': %s, 'size_unit':'${plug_size_unit}','requested_unit':'${plug_request_unit}','block_unit':'${plug_block_unit}','node':0}} + virtio_xpath = [{'element_attrs':["./devices/memory/target/size[@unit='${size_unit}']"],'text':'${target_size}'},{'element_attrs':[".//memory/target/block[@unit='${block_unit}']"],'text':'%s'}, {'element_attrs':[".//memory/target/requested[@unit='${request_unit}']"],'text':'${request_size}'},{'element_attrs':[".//memory/target/address[@base='${base}']"]}] + unplug_xpath = ${virtio_xpath} + plug_xpath = [{'element_attrs':[".//memory/target/size[@unit='${plug_size_unit}']"],'text':'${plug_target_size}'},{'element_attrs':[".//memory/target/block[@unit='${block_unit}']"],'text':'%s'}, {'element_attrs':[".//memory/target/requested[@unit='${plug_request_unit}']"],'text':'${plug_request_size}'},{'element_attrs':[".//memory/target/address[@base='${base}']"]}] + - source_and_mib: + target_size = 512 + request_size = 512 + size_unit = 'MiB' + request_unit = 'MiB' + plug_target_size = 1024 + plug_request_size = 1024 + plug_size_unit = 'MiB' + plug_request_unit = 'MiB' + plug_block_unit = 'KiB' + nodemask = '0' + source_dict = "'source': {'nodemask': '0','pagesize': 4, 'pagesize_unit':'KiB'}" + virtio_dict = {'mem_model':'${mem_model}',${source_dict}, 'target': {'size':${target_size}, 'size_unit':'${size_unit}','requested_unit':'${request_unit}','block_unit':'${block_unit}','node':1,'requested_size': ${request_size}, 'block_size': %s}} + unplug_dict = ${virtio_dict} + plug_dict = {'mem_model':'${mem_model}',${source_dict},'target': {'size':${plug_target_size},'requested_size': ${plug_request_size}, 'block_size': %s, 'size_unit':'${plug_size_unit}','requested_unit':'${plug_request_unit}','block_unit':'${plug_block_unit}','node':1}} + virtio_xpath = [{'element_attrs':[".//memory/target/size[@unit='KiB']"],'text':'%s'},{'element_attrs':[".//memory/target/block[@unit='KiB']"],'text':'%s'}, {'element_attrs':[".//memory/target/requested[@unit='KiB']"],'text':'%s'}, {'element_attrs':[".//memory/source/pagesize"]}, {'element_attrs':[".//memory/source/nodemask"],'text':'${nodemask}'}] + unplug_xpath = ${virtio_xpath} + plug_xpath = [{'element_attrs':[".//memory/target/size[@unit='KiB']"],'text':'%s'},{'element_attrs':[".//memory/target/block[@unit='KiB']"],'text':'%s'}, {'element_attrs':[".//memory/target/requested[@unit='KiB']"],'text':'%s'}] + - unplug_none_dev: + addr_dict = "'address':{'attrs': {'base': '${base}'}}" + virtio_dict = {'mem_model':'${mem_model}', 'target': {'size':${target_size}, 'size_unit':'KiB', ${addr_dict}, 'node':0,'requested_size': ${request_size}, 'block_size': %s}} + unplug_request_size = 0 + unplug_dict = {'mem_model':'${mem_model}', 'target': {'requested_size': ${unplug_request_size}, 'size':${target_size}, 'size_unit':'KiB', ${addr_dict}, 'node':0,'block_size': %s}} + unplug_error = "matching memory device was not found" + virtio_xpath = [{'element_attrs':[".//memory/target/size[@unit='${size_unit}']"],'text':'${target_size}'},{'element_attrs':[".//memory/target/block[@unit='${block_unit}']"],'text':'%s'}, {'element_attrs':[".//memory/target/requested[@unit='${request_unit}']"],'text':'${request_size}'},{'element_attrs':[".//memory/target/address[@base='${base}']"]}] + unplug_xpath = [{'element_attrs':[".//memory/target/size[@unit='${size_unit}']"],'text':'${target_size}'},{'element_attrs':[".//memory/target/block[@unit='${plug_block_unit}']"],'text':'%s'}, {'element_attrs':[".//memory/target/requested[@unit='${plug_request_unit}']"],'text':'${unplug_request_size}'},{'element_attrs':[".//memory/target/address[@base='${base}']"]}] + - plug_exceeded_max_mem: + target_size = 1572864 + request_size = 1572864 + plug_target_size = 1024 + plug_request_size = 1024 + virtio_dict = {'mem_model':'${mem_model}', 'target': {'size':${target_size}, 'size_unit':'KiB','node':1,'requested_size': ${request_size}, 'block_size': %s}} + plug_size_unit = 'MiB' + plug_request_unit = 'MiB' + plug_dict = {'mem_model':'${mem_model}','target': {'size':${plug_target_size},'requested_size': ${plug_request_size}, 'block_size': %s, 'size_unit':'${plug_size_unit}','requested_unit':'${plug_request_unit}','block_unit':'${plug_block_unit}','node':1}} + virtio_xpath = [{'element_attrs':[".//memory/target/size[@unit='${size_unit}']"],'text':'${target_size}'},{'element_attrs':[".//memory/target/block[@unit='${block_unit}']"],'text':'%s'}, {'element_attrs':[".//memory/target/requested[@unit='${request_unit}']"],'text':'${request_size}'}] + plug_xpath = [{'element_attrs':[".//memory/target/size[@unit='${size_unit}']"],'text':'%s'},{'element_attrs':[".//memory/target/block[@unit='${block_unit}']"],'text':'%s'}, {'element_attrs':[".//memory/target/requested[@unit='${request_unit}']"],'text':'%s'}] + plug_error = "Attaching memory device with size '\S+' would exceed domain's maxMemory config size '${max_mem}'" + - duplicate_addr: + addr_dict = "'address':{'attrs': {'base': '0x100000000'}}" + virtio_dict = {'mem_model':'${mem_model}', 'target': {${addr_dict},'size':${target_size}, 'size_unit':'KiB', ${addr_dict}, 'node':0,'requested_size': ${request_size}, 'block_size': %s}} + plug_dict = ${virtio_dict} + plug_error = "unsupported configuration: memory device address [0x100000000:0x108000000] overlaps with other memory device (0x100000000)" + virtio_xpath = [{'element_attrs':[".//memory/target/size[@unit='${size_unit}']"],'text':'${target_size}'},{'element_attrs':[".//memory/target/block[@unit='${block_unit}']"],'text':'%s'}, {'element_attrs':[".//memory/target/requested[@unit='${request_unit}']"],'text':'${request_size}'},{'element_attrs':[".//memory/target/address[@base='${base}']"]}] + plug_xpath = ${virtio_xpath} diff --git a/libvirt/tests/src/memory/memory_devices/virtio_mem_coldplug_and_unplug.py b/libvirt/tests/src/memory/memory_devices/virtio_mem_coldplug_and_unplug.py new file mode 100644 index 00000000000..4e6c4cba762 --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/virtio_mem_coldplug_and_unplug.py @@ -0,0 +1,193 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from avocado.utils import memory + +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_vmxml + +from provider.memory import memory_base + + +def adjust_virtio_params(params): + """ + Adjust all virtio related size and xpath. + + :param params: dict wrapped with params. + """ + plug_target_size = int(params.get('plug_target_size', 0)) + plug_request_size = int(params.get('plug_request_size', 0)) + target_size, request_size = int(params.get('target_size')), int(params.get('request_size')) + plug_size_unit = params.get('plug_size_unit') + plug_request_unit = params.get('plug_request_unit') + size_unit, request_unit = params.get('size_unit'), params.get('request_unit') + + def _convert_size(curr_size, curr_unit, var_str): + if curr_unit != "KiB": + new_size = memory_base.convert_data_size(str(curr_size) + curr_unit) + params.update({var_str: int(new_size)}) + + _convert_size(target_size, size_unit, 'target_size') + _convert_size(request_size, request_unit, 'request_size') + _convert_size(plug_target_size, plug_size_unit, 'plug_target_size') + _convert_size(plug_request_size, plug_request_unit, 'plug_request_size') + + +def adjust_virtio_xpath(params): + """ + Adjust all expected virtio xpath in different scenarios. + + :param params: dict wrapped with params. + :return virtio_xpath, unplug_xpath, plug_xpath, expected defined virtio xpath, + expected plugged virtio xpath, expected unplugged virtio xpath. + """ + default_hugepage_size = memory.get_huge_page_size() + adjust_virtio_params(params) + + plug_target_size = params.get('plug_target_size') + plug_request_size = params.get('plug_request_size') + target_size, request_size = params.get('target_size'), params.get('request_size') + case = params.get("case") + virtio_xpath = params.get("virtio_xpath") + unplug_xpath = params.get("unplug_xpath") + plug_xpath = params.get("plug_xpath") + + if case == "source_and_mib": + virtio_xpath = virtio_xpath % (target_size, default_hugepage_size, + request_size) + unplug_xpath = eval(virtio_xpath) + plug_xpath = eval(plug_xpath % (plug_target_size, default_hugepage_size, + plug_request_size)) + elif case == "plug_exceeded_max_mem": + virtio_xpath = virtio_xpath % default_hugepage_size + plug_xpath = eval(plug_xpath % (plug_target_size, default_hugepage_size, + plug_request_size)) + else: + virtio_xpath = virtio_xpath % default_hugepage_size + if unplug_xpath: + unplug_xpath = eval(unplug_xpath % default_hugepage_size) + if plug_xpath: + plug_xpath = eval(plug_xpath % default_hugepage_size) + return eval(virtio_xpath), unplug_xpath, plug_xpath + + +def check_xpath_unexist(test, vmxml, not_exist_path): + """ + Check specific xpath info not exist in guest xml. + + :param test: test object. + :param vmxml: current guest xml. + :param not_exist_path: The xpath that should not exist in guest. + """ + if libvirt_vmxml.check_guest_xml_by_xpaths( + vmxml, not_exist_path, ignore_status=True): + test.fail("Expect to not get %s in guest" % not_exist_path) + + +def run(test, params, env): + """ + Verify virtio-mem memory device cold-plug and cold-unplug + with different configs + """ + def setup_test(): + """ + Check Versions. + """ + test.log.info("TEST_SETUP: Check related version") + memory_base.check_supported_version(params, test, vm) + + def run_test(): + """ + Define guest, then cold unplug and cold plug virtio mem device. + """ + test.log.info("TEST_SETUP1: Define guest") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vmxml.setup_attrs(**vm_attrs) + vmxml.devices = vmxml.devices.append( + libvirt_vmxml.create_vm_device_by_type('memory', virtio_dict)) + virsh.define(vmxml.xml, debug=True, ignore_status=False) + + test.log.info("TEST_STEP2: Check guest xml") + virtio_xpath, unplug_xpath, plug_xpath = adjust_virtio_xpath(params) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + libvirt_vmxml.check_guest_xml_by_xpaths(vmxml, numa_xpath+virtio_xpath) + + if unplug_dict: + test.log.info("TEST_SETUP3,4:Cold unplug a virtio-mem and check xml") + cold_unplug_obj = libvirt_vmxml.create_vm_device_by_type( + 'memory', unplug_dict) + ret = virsh.detach_device(vm.name, cold_unplug_obj.xml, + flagstr=plug_option, debug=True) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + if unplug_error: + libvirt.check_result(ret, unplug_error) + libvirt_vmxml.check_guest_xml_by_xpaths(vmxml, numa_xpath+virtio_xpath) + else: + libvirt.check_exit_status(ret) + check_xpath_unexist(test, vmxml, unplug_xpath) + + if plug_dict: + test.log.info("TEST_SETUP5-7: Cold plug virtio-mem and check xml") + cold_plug_obj = libvirt_vmxml.create_vm_device_by_type( + 'memory', plug_dict) + ret = virsh.attach_device(vm.name, cold_plug_obj.xml, + flagstr=plug_option, debug=True) + if case in ["with_addr", "source_and_mib", "duplicate_addr"]: + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + if plug_error: + libvirt.check_result(ret, plug_error, any_error=True) + libvirt_vmxml.check_guest_xml_by_xpaths(vmxml, numa_xpath+virtio_xpath) + if case != "duplicate_addr": + check_xpath_unexist(test, vmxml, plug_xpath) + else: + libvirt.check_exit_status(ret) + libvirt_vmxml.check_guest_xml_by_xpaths(vmxml, numa_xpath+plug_xpath) + elif case in ["plug_exceeded_max_mem"]: + for plug_time in range(0, 3): + ret = virsh.attach_device(vm.name, cold_plug_obj.xml, + flagstr=plug_option, debug=True) + if plug_time == 2: + libvirt.check_result(ret, plug_error) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bkxml.sync() + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + case = params.get("case") + default_hugepage_size = memory.get_huge_page_size() + + plug_option = params.get("plug_option") + vm_attrs = eval(params.get('vm_attrs', '{}')) + numa_xpath = eval(params.get("numa_xpath", "")) + unplug_error = params.get("unplug_error") + plug_error = params.get("plug_error") + virtio_dict = eval(params.get('virtio_dict', '{}') % default_hugepage_size) + unplug_dict = params.get('unplug_dict') + plug_dict = params.get('plug_dict') + + unplug_dict = eval(unplug_dict % default_hugepage_size) if unplug_dict else '' + plug_dict = eval(plug_dict % default_hugepage_size) if plug_dict else '' + + try: + setup_test() + run_test() + + finally: + teardown_test() From e8e4e0c5205bdc900db8d79433b96d8a5a9ec6a4 Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 27 May 2024 11:55:18 +0800 Subject: [PATCH 0353/1055] graphics: Update for vnc port Update case: XXXX-34824 - [vnc] Start a guest with vnc port set to an out-of-range value Signed-off-by: lcheng --- libvirt/tests/cfg/graphics/graphics_functional.cfg | 2 ++ libvirt/tests/src/graphics/graphics_functional.py | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/libvirt/tests/cfg/graphics/graphics_functional.cfg b/libvirt/tests/cfg/graphics/graphics_functional.cfg index 36f6aba92db..6fb70ad4585 100644 --- a/libvirt/tests/cfg/graphics/graphics_functional.cfg +++ b/libvirt/tests/cfg/graphics/graphics_functional.cfg @@ -425,10 +425,12 @@ - port_-2: vnc_port = -2 - port_0: + check_dom_xml = "yes" vnc_port = 0 - port_1: vnc_port = 1 - port_65536: + check_dom_xml = "yes" vnc_port = 65536 - without_cert: vnc_tls = 1 diff --git a/libvirt/tests/src/graphics/graphics_functional.py b/libvirt/tests/src/graphics/graphics_functional.py index 4248179e0dd..3c5e9b41379 100644 --- a/libvirt/tests/src/graphics/graphics_functional.py +++ b/libvirt/tests/src/graphics/graphics_functional.py @@ -1006,6 +1006,8 @@ def handle_auto_filled_items(given_graphic_attrs, vm, params): """ vnc_listen_address = params.get("vnc_listen_address") vnc_listen_type = params.get("vnc_listen_type") + vnc_port = params.get("vnc_port") + if vnc_listen_address == '': given_graphic_attrs['listen_attrs'].update({'address': '127.0.0.1'}) elif vnc_listen_address == 'none': @@ -1018,6 +1020,11 @@ def handle_auto_filled_items(given_graphic_attrs, vm, params): given_graphic_attrs['listen_attrs'].update({'address': utils_net.get_host_ip_address()}) elif vnc_network_type == 'vnet': given_graphic_attrs['listen_attrs'].update({'address': params.get('vnet_address')}) + if vnc_port and vnc_port == '0': + del given_graphic_attrs['port'] + given_graphic_attrs.update({'listen_attrs': {'type': 'address'}}) + if vnc_port and vnc_port == '65536': + given_graphic_attrs.update({'listen_attrs': {'type': 'address'}}) return given_graphic_attrs @@ -1705,6 +1712,7 @@ def run(test, params, env): vm.start() logging.debug("After starting, vm xml:\n%s", VMXML.new_from_dumpxml(vm_name)) except virt_vm.VMStartError as detail: + compare_guest_xml(vnc_graphic, vm, params, test) if not fail_patts: test.fail( "Expect VM can be started, but failed with: %s" % detail) From be1f9b835b760973dbfe2fe73c4768a59044dc13 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 27 May 2024 01:04:35 -0400 Subject: [PATCH 0354/1055] Fix pkg dmidecode missing issue in guest image Signed-off-by: liang-cong-red-hat --- libvirt/tests/src/memory/virsh_setmem.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/src/memory/virsh_setmem.py b/libvirt/tests/src/memory/virsh_setmem.py index d261c4b973c..56d1d512be9 100644 --- a/libvirt/tests/src/memory/virsh_setmem.py +++ b/libvirt/tests/src/memory/virsh_setmem.py @@ -7,6 +7,7 @@ from virttest import utils_libvirtd from virttest import data_dir from virttest import utils_misc +from virttest import utils_package from virttest import libvirt_version from virttest.utils_test import libvirt from virttest.libvirt_xml import vm_xml @@ -332,10 +333,9 @@ 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'): - # The physical memory size is in vm xml, use it when dmidecode not - # supported - unusable_mem = int(vmxml.max_mem) - get_vm_usable_mem(session) + 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: unusable_mem = vm_unusable_mem(session) original_outside_mem = vm.get_used_mem() From 7d79f6535285066dbbb487bb0ff9c6f09a1652f0 Mon Sep 17 00:00:00 2001 From: Xiaodai Wang Date: Mon, 27 May 2024 17:33:52 +0800 Subject: [PATCH 0355/1055] [virsh_cmd:domain] Fix list index out of range issue In commit a9211f84bf, 'host bridge' filter was added for aarch64, But on some host, lspci doesn't include any 'host bridge' strings. So the way by get_pci_id_using_filter will return an empty list. This patch checks the pci_id, if it's empty, return test error. And also changes the way to get the host bridge on a host Signed-off-by: Xiaodai Wang --- .../cfg/virsh_cmd/domain/virsh_detach_device_alias.cfg | 2 -- .../src/virsh_cmd/domain/virsh_detach_device_alias.py | 8 +++++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_detach_device_alias.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_detach_device_alias.cfg index a868a855170..a937e79af2f 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_detach_device_alias.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_detach_device_alias.cfg @@ -13,8 +13,6 @@ - pci: detach_hostdev_type = "pci" index = 35 - aarch64: - pci_filter = "Host bridge" detach_hostdev_managed = "yes" controller_dict = {'type': 'pci', 'model': 'pcie-to-pci-bridge','index':'${index}'} no s390-virtio diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py b/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py index 8e49ca4a2ce..b48bc7d38f8 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py @@ -5,6 +5,7 @@ from virttest import data_dir from virttest import virsh from virttest import utils_misc +from virttest import utils_sys from virttest.libvirt_xml import vm_xml from virttest.libvirt_xml.devices.disk import Disk from virttest.libvirt_xml.devices.watchdog import Watchdog @@ -39,7 +40,6 @@ def run(test, params, env): hostdev_type = params.get("detach_hostdev_type", "") hostdev_managed = params.get("detach_hostdev_managed") controller_dict = eval(params.get('controller_dict', '{}')) - pci_filter = params.get("pci_filter", "") # controller params contr_type = params.get("detach_controller_type") contr_model = params.get("detach_controller_mode") @@ -160,8 +160,10 @@ def start_usbredirserver(): dev_dict=controller_dict, index=int(params.get("index"))) - pci_id = utils_misc.get_full_pci_id( - utils_misc.get_pci_id_using_filter(pci_filter)[-1]) + pci_ids = utils_sys.get_host_bridge_id() + if not pci_ids: + test.error("Not Found any pci devices") + pci_id = utils_misc.get_full_pci_id(pci_ids[-1]) if not vm.is_alive(): vm.start() From 0255229e6e8209903d79706d2498ee4feba58604 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Tue, 28 May 2024 01:25:24 -0400 Subject: [PATCH 0356/1055] Memory backing related cases change huge page mult arch config Signed-off-by: liang-cong-red-hat --- .../discard_memory_content_setting.cfg | 30 +++++++--- .../memory_backing/hugepage_mount_path.cfg | 58 +++++++++++-------- .../memory_backing/memory_access_mode.cfg | 30 +++++++--- .../memory_source_and_allocation.cfg | 31 +++++++--- .../page_locking_and_shared_pages.cfg | 32 ++++++---- .../discard_memory_content_setting.py | 5 ++ .../memory_backing/hugepage_mount_path.py | 6 +- .../memory_backing/memory_access_mode.py | 5 ++ .../memory_source_and_allocation.py | 5 ++ .../page_locking_and_shared_pages.py | 5 ++ 10 files changed, 145 insertions(+), 62 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_backing/discard_memory_content_setting.cfg b/libvirt/tests/cfg/memory/memory_backing/discard_memory_content_setting.cfg index 9eaaddc3a2e..aab732d515b 100644 --- a/libvirt/tests/cfg/memory/memory_backing/discard_memory_content_setting.cfg +++ b/libvirt/tests/cfg/memory/memory_backing/discard_memory_content_setting.cfg @@ -1,14 +1,28 @@ - memory.backing.discard: type = discard_memory_content_setting start_vm = "no" - set_pagesize = 2048 - set_pagenum = 1024 numa_mem = 2097152 qemu_line = '"discard-data":%s' - s390-virtio: - set_pagesize = 1024 - set_pagenum = 2048 - kvm_module_parameters = + variants kernel_pagesize: + - 4k: + default_page_size = 4 + variants huge_pagesize: + - 2048: + no s390-virtio + set_pagesize = 2048 + set_pagenum = 1024 + - 1024: + only s390-virtio + set_pagesize = 1024 + set_pagenum = 2048 + kvm_module_parameters = + - 64k: + only aarch64 + default_page_size = 64 + variants huge_pagesize: + - 524288: + set_pagesize = 524288 + set_pagenum = 4 variants source: - file: source_type = 'file' @@ -23,9 +37,6 @@ source_attr = "'source_type':'${source_type}'" source_path = {'element_attrs': ['./memoryBacking/source/[@type="${source_type}"]']} - hugepaged_file: - aarch64: - set_pagesize = 524288 - set_pagenum = 4 source_type = 'hugepage' hugepages_attr = "'hugepages': {}" hugepages_path = {'element_attrs': ['./memoryBacking/hugepages']} @@ -57,3 +68,4 @@ current_mem = "2097152" mem_value = "2097152" mem_attrs = {'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} + diff --git a/libvirt/tests/cfg/memory/memory_backing/hugepage_mount_path.cfg b/libvirt/tests/cfg/memory/memory_backing/hugepage_mount_path.cfg index e3679d5c095..9c3ac8eb91e 100644 --- a/libvirt/tests/cfg/memory/memory_backing/hugepage_mount_path.cfg +++ b/libvirt/tests/cfg/memory/memory_backing/hugepage_mount_path.cfg @@ -2,47 +2,55 @@ type = hugepage_mount_path no s390-virtio mem_value = 2097152 - set_pagesize_1 = "1048576" - set_pagenum_1 = "2" - set_pagesize_2 = "2048" - set_pagenum_2 = "3072" - aarch64: - set_pagesize_1 = "2048" - set_pagenum_1 = "1024" - set_pagesize_2 = "524288" - set_pagenum_2 = "6" security_context = "drwxr-xr-x. 3 root root system_u:object_r:hugetlbfs_t:s0" log_path = "/var/log/libvirt/qemu/%s.log" guest_log_error1 = "hugepage is not mounted" guest_log_error2 = "unable to create backing store for hugepages: Permission denied" page_unit = "KiB" - page_size = "2048" - aarch64: - page_size = "524288" numa_size = 1048576 mem_unit = "KiB" mem_value = 2097152 current_mem = 2097152 max_mem = 15242880 - memory_backing_dict = "'mb': {'hugepages': {'pages': [{'unit': '${page_unit}', 'size': '${page_size}'}]}}" - numa_cpu = {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_size}', 'unit': 'KiB'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_size}', 'unit': 'KiB'}]} - vm_attrs = {${memory_backing_dict},"cpu":${numa_cpu},'vcpu': 4,'max_mem_rt_slots': 16,'memory_unit':"${mem_unit}",'memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB','max_mem_rt': ${max_mem}, 'max_mem_rt_unit': "KiB"} start_vm = "no" consume_value = 204800 + variants kernel_pagesize: + - 4k: + default_page_size = 4 + variants huge_pagesize: + - 2M: + page_size = "2048" + set_pagesize_2 = "2048" + set_pagenum_2 = "3072" + variants ext_huge_pagesize: + - 1G: + other_huge_pagesize = 1048576 + vm_hugepage_mountpoint = "/dev/hugepages1G" + mount_pagesize = "1G" + set_pagesize_1 = "1048576" + set_pagenum_1 = "2" + - 64k: + only aarch64 + default_page_size = 64 + variants huge_pagesize: + - 512M: + page_size = "524288" + set_pagesize_2 = "524288" + set_pagenum_2 = "6" + variants ext_huge_pagesize: + - 2M: + other_huge_pagesize = 2048 + vm_hugepage_mountpoint = "/dev/hugepages2M" + mount_pagesize = "2M" + set_pagesize_1 = "2048" + set_pagenum_1 = "1024" variants case: - default: path = "/dev/hugepages" - vm_hugepage_mountpoint = "/dev/hugepages1G" - mount_pagesize = "1G" - aarch64: - vm_hugepage_mountpoint = "/dev/hugepages2M" - mount_pagesize = "2M" expect_active = "True" expect_state = "active" check_qemu = ['"mem-path":"${path}/libvirt/qemu/','"prealloc":true'] - attach_dict = {'mem_model': 'dimm', 'source': {"pagesize":1048576, "pagesize_unit":"KiB"},'target': {'size': 1048576, 'size_unit': 'KiB','node':0}} - aarch64: - attach_dict = {'mem_model': 'dimm', 'source': {"pagesize":2048, "pagesize_unit":"KiB"},'target': {'size': 1048576, 'size_unit': 'KiB','node':0}} + attach_dict = {'mem_model': 'dimm', 'source': {"pagesize":${other_huge_pagesize}, "pagesize_unit":"KiB"},'target': {'size': 1048576, 'size_unit': 'KiB','node':0}} check_security_cmd = "ls -l -Z ${path}/libvirt/qemu/ -d" - disabled: hugetlbfs_mount = '""' @@ -57,3 +65,7 @@ expect_state = "active" check_security_cmd = "ls -l -Z ${path}/libvirt/qemu -d" check_qemu = ['"mem-path":"${path}/libvirt/qemu/','"prealloc":true'] + memory_backing_dict = "'mb': {'hugepages': {'pages': [{'unit': '${page_unit}', 'size': '${page_size}'}]}}" + numa_cpu = {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_size}', 'unit': 'KiB'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_size}', 'unit': 'KiB'}]} + vm_attrs = {${memory_backing_dict},"cpu":${numa_cpu},'vcpu': 4,'max_mem_rt_slots': 16,'memory_unit':"${mem_unit}",'memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB','max_mem_rt': ${max_mem}, 'max_mem_rt_unit': "KiB"} + diff --git a/libvirt/tests/cfg/memory/memory_backing/memory_access_mode.cfg b/libvirt/tests/cfg/memory/memory_backing/memory_access_mode.cfg index cdd8c454cf7..3c7f3efb7c3 100644 --- a/libvirt/tests/cfg/memory/memory_backing/memory_access_mode.cfg +++ b/libvirt/tests/cfg/memory/memory_backing/memory_access_mode.cfg @@ -1,20 +1,31 @@ - memory.backing.access_mode: type = memory_access_mode - set_pagesize = 2048 - set_pagenum = 1024 numa_mem = 2097152 - aarch64: - set_pagesize = 524288 - set_pagenum = 4 start_vm = no qemu_monitor_option = '--hmp' qemu_monitor_cmd = 'info memdev' pattern_share = "share:\s*{}" mem_backend = "memory backend: ram-node0" - s390-virtio: - set_pagesize = 1024 - set_pagenum = 2048 - kvm_module_parameters = + variants kernel_pagesize: + - 4k: + default_page_size = 4 + variants huge_pagesize: + - 2048: + no s390-virtio + set_pagesize = 2048 + set_pagenum = 1024 + - 1024: + only s390-virtio + set_pagesize = 1024 + set_pagenum = 2048 + kvm_module_parameters = + - 64k: + only aarch64 + default_page_size = 64 + variants huge_pagesize: + - 524288: + set_pagesize = 524288 + set_pagenum = 4 variants source: - file: source_type = 'file' @@ -72,3 +83,4 @@ current_mem = "2097152" mem_value = "2097152" mem_attrs = {'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} + diff --git a/libvirt/tests/cfg/memory/memory_backing/memory_source_and_allocation.cfg b/libvirt/tests/cfg/memory/memory_backing/memory_source_and_allocation.cfg index 853b97920cc..5eff829f764 100644 --- a/libvirt/tests/cfg/memory/memory_backing/memory_source_and_allocation.cfg +++ b/libvirt/tests/cfg/memory/memory_backing/memory_source_and_allocation.cfg @@ -2,19 +2,31 @@ type = memory_source_and_allocation start_vm = no check_allocated_cmd = "grep -A20 '^Size:.*2097152' /proc/`pidof qemu-kvm`/smaps" - set_pagesize = 2048 - set_pagenum = 1024 monitor_option = "--hmp" monitor_cmd = "info memdev" memory_name_pattern = 'memory backend: (\S+)' check_thread = '{"execute":"qom-get", "arguments":{"path": "/objects/%s", "property":"%s"}}' - s390-virtio: - set_pagesize = 1024 - kvm_module_parameters = - check_allocated_cmd = "grep -A20 '^Size:.*1048576' /proc/`pidof qemu-kvm`/smaps" - aarch64: - set_pagesize = 524288 - set_pagenum = 4 + variants kernel_pagesize: + -4k: + default_page_size = 4 + variants huge_pagesize: + - 2048: + no s390-virtio + set_pagesize = 2048 + set_pagenum = 1024 + - 1024: + only s390-virtio + set_pagesize = 1024 + set_pagenum = 1024 + kvm_module_parameters = + check_allocated_cmd = "grep -A20 '^Size:.*1048576' /proc/`pidof qemu-kvm`/smaps" + -64k: + only aarch64 + default_page_size = 64 + variants huge_pagesize: + - 524288: + set_pagesize = 524288 + set_pagenum = 4 variants source: - file: source_type = 'file' @@ -78,3 +90,4 @@ current_mem = "1048576" mem_value = "1048576" mem_attrs = {'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} + diff --git a/libvirt/tests/cfg/memory/memory_backing/page_locking_and_shared_pages.cfg b/libvirt/tests/cfg/memory/memory_backing/page_locking_and_shared_pages.cfg index a0d27602025..d379af0248c 100644 --- a/libvirt/tests/cfg/memory/memory_backing/page_locking_and_shared_pages.cfg +++ b/libvirt/tests/cfg/memory/memory_backing/page_locking_and_shared_pages.cfg @@ -1,15 +1,27 @@ - memory.backing.page_locking_and_shared_pages: type = page_locking_and_shared_pages start_vm = no - pagesize = 2048 - pagenum = 1024 - aarch64: - pagesize = 524288 - pagenum = 4 - s390-virtio: - pagesize = 1024 - pagenum = 2048 expect_exist = True + variants default_pagesize: + - 4k: + kernel_pagesize = 4 + variants huge_pagesize: + - 1024: + only s390-virtio + pagesize = 1024 + pagenum = 2048 + - 2048: + no s390-virtio + pagesize = 2048 + pagenum = 1024 + - 64k: + only aarch64 + kernel_pagesize = 64 + variants huge_pagesize: + - 524288: + only aarch64 + pagesize = 524288 + pagenum = 4 variants lock_config: - lock_default: only ksm_disabled @@ -32,9 +44,6 @@ ksm_qemu_line = "mem-merge=off" variants page_config: - page_default: - kernel_pagesize = 4 - aarch64: - kernel_pagesize = 64 - hugepage: hugepages_dict = "'hugepages': {}" s390-virtio: @@ -47,3 +56,4 @@ mem_value = "2097152" mem_attrs = {'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} qemu_line = ["${lock_qemu_line}", "${ksm_qemu_line}"] + diff --git a/libvirt/tests/src/memory/memory_backing/discard_memory_content_setting.py b/libvirt/tests/src/memory/memory_backing/discard_memory_content_setting.py index a03aebe77b6..3c929f8037f 100644 --- a/libvirt/tests/src/memory/memory_backing/discard_memory_content_setting.py +++ b/libvirt/tests/src/memory/memory_backing/discard_memory_content_setting.py @@ -15,6 +15,8 @@ from virttest.utils_test import libvirt from virttest.utils_libvirt import libvirt_vmxml +from provider.memory import memory_base + def run(test, params, env): """ @@ -97,6 +99,8 @@ def setup_test(): Prepare memory device """ test.log.info("TEST_SETUP: Set hugepage.") + memory_base.check_mem_page_sizes( + test, int(default_page_size), int(set_pagesize)) hp_cfg.set_kernel_hugepages(set_pagesize, set_pagenum) def run_test(): @@ -140,6 +144,7 @@ def teardown_test(): qemu_line = params.get("qemu_line") numa_discard = params.get("numa_discard") mem_discard = params.get("mem_discard") + default_page_size = params.get("default_page_size") set_pagesize = params.get("set_pagesize") set_pagenum = params.get("set_pagenum") diff --git a/libvirt/tests/src/memory/memory_backing/hugepage_mount_path.py b/libvirt/tests/src/memory/memory_backing/hugepage_mount_path.py index 5d1477ca7f6..e79015ba2de 100644 --- a/libvirt/tests/src/memory/memory_backing/hugepage_mount_path.py +++ b/libvirt/tests/src/memory/memory_backing/hugepage_mount_path.py @@ -22,6 +22,8 @@ from virttest.utils_libvirt import libvirt_memory from virttest.staging import service +from provider.memory import memory_base + def run(test, params, env): """ @@ -33,7 +35,8 @@ def setup_test(): Set hugepage on host and prepare guest """ test.log.info("TEST_SETUP: Set hugepage on host and prepare guest") - + memory_base.check_mem_page_sizes( + test, default_page_size, int(set_pagesize_2), [int(set_pagesize_1)]) hp_cfg = test_setup.HugePageConfig(params) if case == "customized": process.run("umount %s" % default_path, ignore_status=True) @@ -162,6 +165,7 @@ def teardown_test(): default_path = params.get("default_path") consume_value = int(params.get("consume_value")) + default_page_size = int(params.get('default_page_size')) mount_pagesize = params.get("mount_pagesize", '{}') set_pagesize_1 = params.get("set_pagesize_1") set_pagenum_1 = params.get("set_pagenum_1") diff --git a/libvirt/tests/src/memory/memory_backing/memory_access_mode.py b/libvirt/tests/src/memory/memory_backing/memory_access_mode.py index 34af5b28c6e..5bbfbeb1f3a 100644 --- a/libvirt/tests/src/memory/memory_backing/memory_access_mode.py +++ b/libvirt/tests/src/memory/memory_backing/memory_access_mode.py @@ -17,6 +17,8 @@ from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_libvirt import libvirt_memory +from provider.memory import memory_base + def get_vm_attrs(test, params): """ @@ -152,6 +154,8 @@ def setup_test(): """ Setup pagesize """ + memory_base.check_mem_page_sizes( + test, pg_size=int(default_page_size), hp_size=int(set_pagesize)) hp_cfg.set_kernel_hugepages(set_pagesize, set_pagenum) def run_test(): @@ -220,6 +224,7 @@ def teardown_test(): mem_backend = params.get("mem_backend") qemu_monitor_cmd = params.get('qemu_monitor_cmd') qemu_monitor_option = params.get('qemu_monitor_option') + default_page_size = params.get("default_page_size") set_pagesize = params.get("set_pagesize") set_pagenum = params.get("set_pagenum") diff --git a/libvirt/tests/src/memory/memory_backing/memory_source_and_allocation.py b/libvirt/tests/src/memory/memory_backing/memory_source_and_allocation.py index e7180d87644..e557485cafb 100644 --- a/libvirt/tests/src/memory/memory_backing/memory_source_and_allocation.py +++ b/libvirt/tests/src/memory/memory_backing/memory_source_and_allocation.py @@ -21,6 +21,8 @@ from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_libvirt import libvirt_memory +from provider.memory import memory_base + def run(test, params, env): """ @@ -154,6 +156,8 @@ def setup_test(): """ Setup pagesize """ + memory_base.check_mem_page_sizes( + test, pg_size=int(default_page_size), hp_size=int(set_pagesize)) hp_cfg.set_kernel_hugepages(set_pagesize, set_pagenum) def run_test(): @@ -242,6 +246,7 @@ def teardown_test(): memory_name_pattern = params.get("memory_name_pattern") check_allocated_cmd = params.get("check_allocated_cmd") numa_attrs = eval(params.get("numa_attrs", '{}')) + default_page_size = params.get("default_page_size") set_pagesize = params.get("set_pagesize") set_pagenum = params.get("set_pagenum") source_attr = params.get("source_attr", "") diff --git a/libvirt/tests/src/memory/memory_backing/page_locking_and_shared_pages.py b/libvirt/tests/src/memory/memory_backing/page_locking_and_shared_pages.py index abc68f67731..1f0877a49df 100644 --- a/libvirt/tests/src/memory/memory_backing/page_locking_and_shared_pages.py +++ b/libvirt/tests/src/memory/memory_backing/page_locking_and_shared_pages.py @@ -17,6 +17,8 @@ from virttest.utils_libvirt import libvirt_memory from virttest.staging import utils_memory +from provider.memory import memory_base + def run(test, params, env): """ @@ -47,6 +49,9 @@ def setup_test(): Prepare init xml """ test.log.info("TEST_SETUP: Set hugepage") + + memory_base.check_mem_page_sizes( + test, kernel_pagesize, int(pagesize)) hp_cfg = test_setup.HugePageConfig(params) hp_cfg.set_kernel_hugepages(pagesize, pagenum) From d1d3f980c6f09f8be197d172f7f2176e8a937cad Mon Sep 17 00:00:00 2001 From: Qian Jianhua Date: Tue, 28 May 2024 15:04:57 +0800 Subject: [PATCH 0357/1055] numa: use dynamic expected value for different architectures Signed-off-by: Qian Jianhua --- .../numa/guest_numa_node_tuning/memory_binding_setting.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py b/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py index 54e8bfe589c..5689eb77241 100644 --- a/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py @@ -164,10 +164,7 @@ def _check_values(expect_huge, expect_N0, expect_N1, expect_sum=None): else: _check_values(True, 506, 506) elif not single_host_node and mem_mode in ['strict', 'restrictive']: - if platform.machine() == 'aarch64': - _check_values(True, 0, 0, 4) - else: - _check_values(True, 0, 0, 1012) + _check_values(True, 0, 0, int(mem_size/psize)) test_obj.test.log.debug("Step: verify host numa node memory allocation PASS") From 800de37144d6737969dbbfc0396a82415a7b97b0 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Tue, 28 May 2024 04:28:47 -0400 Subject: [PATCH 0358/1055] Memory misc add multi huge page size config Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/memory/memory_misc.cfg | 96 ++++++++++++++++++------ libvirt/tests/src/memory/memory_misc.py | 23 +++++- 2 files changed, 91 insertions(+), 28 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_misc.cfg b/libvirt/tests/cfg/memory/memory_misc.cfg index cf820b5f9eb..28490ee83d5 100644 --- a/libvirt/tests/cfg/memory/memory_misc.cfg +++ b/libvirt/tests/cfg/memory/memory_misc.cfg @@ -38,15 +38,36 @@ vm_attrs = {'max_mem_rt': 2124800, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB', 'memory': 1155072, 'memory_unit': 'KiB', 'current_mem': 1048576, 'current_mem_unit': 'KiB', 'vcpu': 16} numa_node_size = 512000 cpu_attrs = {'numa_cell': [{'id': '0', 'cpus': '0-7', 'memory': '${numa_node_size}', 'unit': 'KiB'}, {'id': '1', 'cpus': '8-15', 'memory': '${numa_node_size}', 'unit': 'KiB'}]} - mem_device_attrs = {'source': {'pagesize_unit': 'KiB', 'pagesize': 2048, 'nodemask': '0'}, 'mem_model': 'dimm', 'target': {'size': 131072, 'node': 1, 'size_unit': 'KiB'}} - aarch64: - mem_device_attrs = {'source': {'pagesize_unit': 'KiB', 'pagesize': 524288, 'nodemask': '0'}, 'mem_model': 'dimm', 'target': {'size': 524288, 'node': 1, 'size_unit': 'KiB'}} + variants kernel_pagesize: + - 4k: + default_page_size = 4 + variants huge_pagesize: + - 2048: + default_hugepage_size = 2048 + mem_device_attrs = {'source': {'pagesize_unit': 'KiB', 'pagesize': 2048, 'nodemask': '0'}, 'mem_model': 'dimm', 'target': {'size': 131072, 'node': 1, 'size_unit': 'KiB'}} + - 64k: + only aarch64 + default_page_size = 64 + variants huge_pagesize: + - 524288: + default_hugepage_size = 524288 + mem_device_attrs = {'source': {'pagesize_unit': 'KiB', 'pagesize': 524288, 'nodemask': '0'}, 'mem_model': 'dimm', 'target': {'size': 524288, 'node': 1, 'size_unit': 'KiB'}} - nodeset_specified: no s390-virtio - pagesize = 1048576 - aarch64: - pagesize = 524288 - pagenum = 10 + variants kernel_pagesize: + - 4k: + default_page_size = 4 + variants huge_pagesize: + - 1048576: + pagesize = 1048576 + pagenum = 10 + - 64k: + only aarch64 + default_page_size = 64 + variants huge_pagesize: + - 16777216: + pagesize = 16777216 + pagenum = 1 variants scenario: - nodeset_0: mem_backing_attrs = {'hugepages': {'pages': [{'unit': 'KiB', 'nodeset': '0', 'size': '${pagesize}'}]}, 'locked': True} @@ -57,31 +78,55 @@ expect_msg = 'hugepages: node 0 not found' - hp_from_2_numa_nodes: no s390-virtio - pagesize = 2048 - pagenum = 5120 - aarch64: - pagesize = 524288 - pagenum = 20 - vm_attrs = {'max_mem_rt': 83886080, 'max_mem_rt_slots': 8, 'max_mem_rt_unit': 'KiB', 'memory': 20971520, 'memory_unit': 'KiB', 'current_mem': 20971520, 'current_mem_unit': 'KiB'} + variants kernel_pagesize: + - 4k: + default_page_size = 4 + variants huge_pagesize: + - 2048: + pagesize = 2048 + pagenum = 2560 + - 64k: + only aarch64 + default_page_size = 64 + variants huge_pagesize: + - 524288: + pagesize = 524288 + pagenum = 10 + vm_attrs = {'max_mem_rt': 83886080, 'max_mem_rt_slots': 8, 'max_mem_rt_unit': 'KiB', 'memory': 10485760, 'memory_unit': 'KiB', 'current_mem': 10485760, 'current_mem_unit': 'KiB'} mem_backing_attrs = {'hugepages': {}} - cpu_attrs = {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '19922944', 'unit': 'KiB', 'discard': 'yes'}]} + cpu_attrs = {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '9437184', 'unit': 'KiB', 'discard': 'yes'}]} mem_device_attrs = {'source': {'pagesize_unit': 'KiB', 'pagesize': ${pagesize}, 'nodemask': '0'}, 'mem_model': 'dimm', 'target': {'size': 1048576, 'node': 0, 'size_unit': 'KiB'}} - mount_hp_running_vm: no s390-virtio - pagesize = 2048 - mount_pagesize = 1048576 - mount_path = '/dev/hugepages1G' - mount_option = 'pagesize=1G' - aarch64: - pagesize = 524288 - mount_pagesize = 2048 - mount_path= '/dev/hugepages2M' - mount_option = 'pagesize=2M' - vm_attrs = {'vcpu': 4, 'max_mem_rt': 15242880, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'} + variants kernel_pagesize: + - 4k: + default_page_size = 4 + variants huge_pagesize: + - 2048: + pagesize = 2048 + variants ext_huge_pagesize: + - 1048576: + mount_pagesize = 1048576 + mount_path = '/dev/hugepages1G' + mount_option = 'pagesize=1G' + mem_device_size = 1048576 + - 64k: + only aarch64 + default_page_size = 64 + variants huge_pagesize: + - 524288: + pagesize = 524288 + variants ext_huge_pagesize: + - 16777216: + mount_pagesize = 16777216 + mount_path= '/dev/hugepages16G' + mount_option = 'pagesize=16G' + mem_device_size = 16777216 + vm_attrs = {'vcpu': 4, 'max_mem_rt': 20971520, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'} numa_node_size = 1048576 cpu_attrs = {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_node_size}', 'unit': 'KiB'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_node_size}', 'unit': 'KiB'}]} mem_backing_attrs = {'hugepages': {'pages': [{'unit': 'KiB', 'size': '${pagesize}'}]}} - mem_device_attrs = {'source': {'pagesize': ${mount_pagesize}, 'pagesize_unit': 'KiB'}, 'mem_model': 'dimm', 'target': {'size': 1048576, 'node': 0, 'size_unit': 'KiB'}} + mem_device_attrs = {'source': {'pagesize': ${mount_pagesize}, 'pagesize_unit': 'KiB'}, 'mem_model': 'dimm', 'target': {'size': ${mem_device_size}, 'node': 0, 'size_unit': 'KiB'}} - edit_mem: variants case: - forbid_0: @@ -183,3 +228,4 @@ vmxml_memory = 3145760 vmxml_current_mem = 3045760 cpu_attrs = {'mode': 'host-passthrough', 'numa_cell': [{'id': '0', 'cpus': '0,2', 'memory': '${numa_node_size}', 'unit': 'KiB'}, {'id': '1', 'cpus': '1,3', 'memory': '${numa_node_size}', 'unit': 'KiB'}]} + diff --git a/libvirt/tests/src/memory/memory_misc.py b/libvirt/tests/src/memory/memory_misc.py index 8cee6932f3d..3f8369fbee8 100644 --- a/libvirt/tests/src/memory/memory_misc.py +++ b/libvirt/tests/src/memory/memory_misc.py @@ -14,6 +14,8 @@ from virttest.staging import utils_memory from virttest.utils_test import libvirt +from provider.memory import memory_base + VIRSH_ARGS = {'debug': True, 'ignore_status': False} @@ -176,6 +178,10 @@ def _setup_mbxml(): test.log.debug(virsh.dumpxml(vm_name).stdout_text) if case == 'no_mem_backing': + default_page_size = int(params.get('default_page_size')) + default_hugepage_size = params.get('default_hugepage_size') + memory_base.check_mem_page_sizes( + test, pg_size=default_page_size, hp_size=int(default_hugepage_size)) vm_mem_size = vmxml.memory set_hugepage(vm_mem_size) @@ -190,8 +196,11 @@ def _setup_mbxml(): test.log.debug(virsh.dumpxml(vm_name).stdout_text) if case == 'nodeset_specified': + default_page_size = int(params.get('default_page_size')) pagesize = int(params.get('pagesize')) pagenum = int(params.get('pagenum')) + memory_base.check_mem_page_sizes( + test, pg_size=default_page_size, hp_list=[pagesize]) hp_cfg = test_setup.HugePageConfig(params) params['page_num_bk'] = hp_cfg.get_kernel_hugepages(pagesize) test.log.debug('Current number of pages: %s', params['page_num_bk']) @@ -211,6 +220,9 @@ def _setup_mbxml(): # Setup hugepage pagesize = int(params.get('pagesize')) pagenum = int(params.get('pagenum')) + default_page_size = int(params.get('default_page_size')) + memory_base.check_mem_page_sizes( + test, pg_size=default_page_size, hp_size=pagesize) setup_hugepages(pagesize, pagenum * 2) hp_cfg = test_setup.HugePageConfig(params) @@ -246,12 +258,16 @@ def _setup_mbxml(): test.log.debug(virsh.dumpxml(vm_name).stdout_text) if case == 'mount_hp_running_vm': + default_page_size = int(params.get('default_page_size')) pagesize = int(params.get('pagesize')) mount_pagesize = int(params.get('mount_pagesize')) + mem_device_size = int(params.get('mem_device_size')) + memory_base.check_mem_page_sizes( + test, pg_size=default_page_size, hp_size=pagesize, hp_list=[mount_pagesize]) vm_mem_size = vmxml.memory hp_cfg = test_setup.HugePageConfig(params) hp_cfg.set_kernel_hugepages(pagesize, vm_mem_size // pagesize) - hp_cfg.set_kernel_hugepages(mount_pagesize, vm_mem_size // mount_pagesize) + hp_cfg.set_kernel_hugepages(mount_pagesize, mem_device_size // mount_pagesize) set_vmxml(vmxml, params) _setup_mbxml() vmxml.sync() @@ -414,7 +430,7 @@ def run_test_memorybacking(case): # e.g. 100MiB less than free memory size free_mem = utils_memory.freememtotal(session) test.log.debug('Free mem on vm: %d kB', free_mem) - session.cmd('memhog %dM' % (free_mem // 1024 - 100)) + session.cmd('memhog %dM' % (free_mem // 1024 * 2 // 3)) vm.destroy() utils_libvirtd.Libvirtd('virtqemud').restart() virsh.start(vm_name, **VIRSH_ARGS) @@ -436,7 +452,8 @@ def cleanup_test_memorybacking(case): if case == 'mount_hp_running_vm': mount_path = params.get('mount_path') utils_disk.umount('hugetlbfs', mount_path, 'hugetlbfs') - os.rmdir(mount_path) + if os.path.exists(mount_path): + os.rmdir(mount_path) def run_test_edit_mem(case): """ From bca59698f45f190050d988efedc06e6fd19624f2 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Tue, 28 May 2024 04:41:52 -0400 Subject: [PATCH 0359/1055] Change memory verification to adapt to different page size Signed-off-by: liang-cong-red-hat --- .../memory_allocation/define_value_unit.cfg | 4 +--- .../memory_allocation/define_value_unit.py | 20 +++++++++---------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_allocation/define_value_unit.cfg b/libvirt/tests/cfg/memory/memory_allocation/define_value_unit.cfg index 7fd6f4dcb00..0e5e8a5de8e 100644 --- a/libvirt/tests/cfg/memory/memory_allocation/define_value_unit.cfg +++ b/libvirt/tests/cfg/memory/memory_allocation/define_value_unit.cfg @@ -6,9 +6,6 @@ default_unit = "KiB" status_error = "no" result_dict = {'memory_unit': 'KiB', 'current_mem_unit': 'KiB', 'max_mem_rt_slots': ${max_mem_slots}, "max_mem_rt_unit":"KiB","numa_unit":"KiB"} - default_pagesize = 4 - aarch64: - default_pagesize = 64 variants case: - positive_test: variants: @@ -79,3 +76,4 @@ vm_attrs = {'max_mem_rt': ${max_mem}, 'max_mem_rt_slots': ${max_mem_slots}, 'max_mem_rt_unit': "${max_mem_unit}",'memory_unit':"${mem_unit}",'memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}',"cpu":${numa_cpu}} xpaths = [[{'element_attrs':['.//memory[@unit="${default_unit}"]'],'text':'%s'}],[{'element_attrs':['.//currentMemory[@unit="${default_unit}"]'],'text':'%s'}],[{'element_attrs':['.//maxMemory[@unit="${default_unit}"]'],'text':'%s'}],[{'element_attrs':['.//cell[@unit="${default_unit}"]','.//cell[@memory="%s"]']}]] numa_dict = {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${mem_value}'}]} + diff --git a/libvirt/tests/src/memory/memory_allocation/define_value_unit.py b/libvirt/tests/src/memory/memory_allocation/define_value_unit.py index c88073c9ed9..97cee49e695 100644 --- a/libvirt/tests/src/memory/memory_allocation/define_value_unit.py +++ b/libvirt/tests/src/memory/memory_allocation/define_value_unit.py @@ -26,7 +26,6 @@ def run(test, params, env): 1:byte/KB/KiB/MB/MiB/GB/GiB/invalid 2:with numa/without numa """ - def run_positive_test(): """ Start guest @@ -177,10 +176,10 @@ def get_dest_size(source_size, operation="start", check_current_mem=False, sessi 1) When the operation is guest login, Verify the current memory value would change to the value set in defined xml and round up to a - multiple of 4KiB(default pagesize), other memory value same as 2): + multiple of 4KiB(default guest pagesize), other memory value same as 2): - 2000000KB = 1953125 KiB, and divide default_pagesize = 488281.25 - rounds up to 488282, than 488282 * default_page = 1953128 KiB + 2000000KB = 1953125 KiB, and divide default guest pagesize = 488281.25 + rounds up to 488282, than 488282 * default guest page = 1953128 KiB 2) When the operation is guest start or login and non-current memory, Verify the memory value @@ -195,13 +194,15 @@ def get_dest_size(source_size, operation="start", check_current_mem=False, sessi convert_size = memory_base.convert_data_size(source_size, dest_unit) conf_page_size = session.cmd_output('getconf PAGE_SIZE') + balloon_pagesize = 4 test.log.debug('The PAGE_SIZE of guest is %s', conf_page_size) - if int(conf_page_size) == 65536: - round_up_size = math.floor(convert_size/default_pagesize) + pagesize_kib = int(conf_page_size) // 1024 + remainder = convert_size % pagesize_kib + if pagesize_kib - remainder < balloon_pagesize: + round_up_size = math.ceil(convert_size / pagesize_kib) else: - round_up_size = math.ceil(convert_size/default_pagesize) - dest_size = round_up_size * default_pagesize - + round_up_size = math.floor(convert_size / pagesize_kib) + dest_size = round_up_size * pagesize_kib else: dest_unit = 'MiB' convert_size = memory_base.convert_data_size(source_size, @@ -239,7 +240,6 @@ def get_expected_result(operation='start', session=None): case = params.get("case") error_msg = params.get("error_msg") - default_pagesize = int(params.get("default_pagesize")) mem_value = params.get("mem_value") mem_unit = params.get("mem_unit") current_mem = params.get("current_mem") From e41be7184f45cafe80b16c735d44f9597709e426 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Tue, 28 May 2024 04:55:58 -0400 Subject: [PATCH 0360/1055] Decrease memory size to make unplug memory device more reliable Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/event/virsh_event.cfg | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/event/virsh_event.cfg b/libvirt/tests/cfg/event/virsh_event.cfg index d41c7d63e42..cadaec24f05 100644 --- a/libvirt/tests/cfg/event/virsh_event.cfg +++ b/libvirt/tests/cfg/event/virsh_event.cfg @@ -116,8 +116,8 @@ max_mem = 25600000 maxmem_slots = "16" mem_unit = "KiB" - memory = 4048896 - current_mem = 4048896 + memory = 1572864 + current_mem = 1572864 dimm_unit = "m" dimm_size = 128 cpu_mode = 'host-model' @@ -198,3 +198,4 @@ # Test virsh qemu_monitor_event no invalid_event qemu_monitor_test = "yes" + From f25097cf86af565201675074d9461b066786709d Mon Sep 17 00:00:00 2001 From: nanli Date: Wed, 29 May 2024 10:44:33 +0800 Subject: [PATCH 0361/1055] enable one snap multi children case it's related bug,bug fixed now Signed-off-by: nanli --- .../cfg/snapshot/delete_external_snap_with_references.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/snapshot/delete_external_snap_with_references.cfg b/libvirt/tests/cfg/snapshot/delete_external_snap_with_references.cfg index 50314b30582..771117f1121 100644 --- a/libvirt/tests/cfg/snapshot/delete_external_snap_with_references.cfg +++ b/libvirt/tests/cfg/snapshot/delete_external_snap_with_references.cfg @@ -16,6 +16,6 @@ variants: - tail_to_head: del_index = [4, 3, 0] -# - head_to_tail: -# del_index = [0, 3, 4] + - head_to_tail: + del_index = [0, 3, 4] From d0d22825de0606f57079a81c07735fd52e27fe33 Mon Sep 17 00:00:00 2001 From: Yanqiu Zhang Date: Wed, 29 May 2024 03:09:23 -0400 Subject: [PATCH 0362/1055] link_state_model_type:Sleep to wait setlink change 2 cases always failed due to not detected 'Link state yes' after domif-setlink. Add sleep before later checkings to wait it taking effect. Signed-off-by: Yanqiu Zhang --- .../src/virtual_network/link_state/link_state_model_type.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py b/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py index b142451e565..4dde3ee9aa5 100644 --- a/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py +++ b/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py @@ -11,6 +11,8 @@ from provider.interface import interface_base from provider.virtual_network import network_base +import time + VIRSH_ARGS = {"ignore_status": False, "debug": True} @@ -75,6 +77,7 @@ def run(test, params, env): if exp_link_state == test_states[-1][0]: virsh_ins.domif_setlink( vm_name, iface_mac, exp_domiflik_state, **VIRSH_ARGS) + time.sleep(3) link_info = virsh_ins.domif_getlink( vm_name, iface_mac, **VIRSH_ARGS).stdout_text if exp_domiflik_state not in link_info: From 600b7bd38fb2c9983532131b04d3a19570e891ca Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 29 May 2024 15:47:35 +0800 Subject: [PATCH 0363/1055] guest_os_booting: Skip unsupported cases for aarch64 Signed-off-by: Yingshun Cui --- .../cfg/guest_os_booting/firmware_configuration/os_acpi.cfg | 1 + libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_loader.cfg | 1 + 2 files changed, 2 insertions(+) diff --git a/libvirt/tests/cfg/guest_os_booting/firmware_configuration/os_acpi.cfg b/libvirt/tests/cfg/guest_os_booting/firmware_configuration/os_acpi.cfg index 90e0174b992..20d6384228b 100644 --- a/libvirt/tests/cfg/guest_os_booting/firmware_configuration/os_acpi.cfg +++ b/libvirt/tests/cfg/guest_os_booting/firmware_configuration/os_acpi.cfg @@ -4,6 +4,7 @@ acpi_url = "EXAMPLE_ACPI_URL" acpi_file = "slic.dat" acpi_dict = {'acpi': {'table_type': 'slic', 'table': '%s'}} + no aarch64 variants: - start_guest: cmd_in_guest = "acpidump" diff --git a/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_loader.cfg b/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_loader.cfg index be655099894..0ba2ac78936 100644 --- a/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_loader.cfg +++ b/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_loader.cfg @@ -34,6 +34,7 @@ loader_dict = {'secure': '${os_secure}', 'loader_readonly': 'no', 'loader_type': 'pflash', 'loader': '${loader_path}'} error_msg = "Could not open .+: Permission denied" - type_rom: + no aarch64 loader_dict = {'secure': '${os_secure}', 'loader_readonly': 'yes', 'loader_type': 'rom', 'loader': '${loader_path}'} error_msg = "could not load PC BIOS" - incorrect_loader_path: From 785a911193e6b0244675d4029f2b8a9520f176e0 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Wed, 29 May 2024 00:01:51 -0400 Subject: [PATCH 0364/1055] passt:support tests when host has multi-path default gateway - Check whether default gateway of vm is in the list of default gateway of host - Use vm's default gateway which is unique instead of host's default gateway when checking connection Signed-off-by: Haijiao Zhao --- provider/virtual_network/passt.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/provider/virtual_network/passt.py b/provider/virtual_network/passt.py index f1a2eb6f4bc..47a622762be 100644 --- a/provider/virtual_network/passt.py +++ b/provider/virtual_network/passt.py @@ -253,19 +253,18 @@ def check_default_gw(session, host_iface=None): 'Host default ipv4 gateway not consistent with vm.') _host_gw_v6 = utils_net.get_default_gateway(ip_ver='ipv6', - target_iface=host_iface) + target_iface=host_iface, + json=True) if not _host_gw_v6: - LOG.debug("Skip ipv6 route check as host has no default route or has " - "multipath route which passt can not recognize!") - return - _vm_gw_v6 = utils_net.get_default_gateway(session=session, ip_ver='ipv6') - if not _vm_gw_v6: raise exceptions.TestFail('Guest has no ipv6 gateway!') - host_gw_v6 = _host_gw_v6.split() - vm_gw_v6 = _vm_gw_v6.split() + vm_gw_v6 = utils_net.get_default_gateway(session=session, ip_ver='ipv6', + json=True) + if not vm_gw_v6: + raise exceptions.TestFail('Guest has no ipv6 gateway!') + host_gw_v6 = _host_gw_v6 if isinstance(_host_gw_v6, list) else [_host_gw_v6] LOG.debug(f'Host and vm default ipv6 gateway: {host_gw_v6}, {vm_gw_v6}') - if [x for x in vm_gw_v6 if x not in host_gw_v6]: + if vm_gw_v6 not in host_gw_v6: raise exceptions.TestFail( 'Host default ipv6 gateway not consistent with vm.') @@ -355,12 +354,13 @@ def check_connection(vm, vm_iface, protocols, host_iface=None): """ default_gw = utils_net.get_default_gateway(force_dhcp=True, target_iface=host_iface) - default_gw_v6 = utils_net.get_default_gateway(ip_ver='ipv6', - target_iface=host_iface) + vm_session = vm.wait_for_serial_login() + default_gw_v6_vm = utils_net.get_default_gateway( + session=vm_session, ip_ver='ipv6', json=True) for protocol in protocols: host_sess = aexpect.ShellSession('su') vm_sess = vm.wait_for_serial_login(timeout=60) - gw = default_gw if protocol[-1] == '4' else default_gw_v6 + gw = default_gw if protocol[-1] == '4' else default_gw_v6_vm src_iface = None if protocol[-1] == '4' else vm_iface try: check_protocol_connection(vm_sess, host_sess, protocol, gw, From 51c1a6934d5fbb77cb3f57213d0a84ef7fd7a047 Mon Sep 17 00:00:00 2001 From: Chunfu Wen Date: Mon, 22 Apr 2024 23:35:39 -0400 Subject: [PATCH 0365/1055] Automate blockresize cases Cover blockresize in various scenarios Signed-off-by: Chunfu Wen --- .../virtual_disks_blockresize.cfg | 55 ++++ .../virtual_disks_blockresize.py | 234 ++++++++++++++++++ 2 files changed, 289 insertions(+) create mode 100755 libvirt/tests/cfg/virtual_disks/virtual_disks_blockresize.cfg create mode 100644 libvirt/tests/src/virtual_disks/virtual_disks_blockresize.py diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_blockresize.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_blockresize.cfg new file mode 100755 index 00000000000..ea6d3974279 --- /dev/null +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_blockresize.cfg @@ -0,0 +1,55 @@ +- virtual_disks.blockresize: + type = virtual_disks_blockresize + take_regular_screendumps = "no" + start_vm = "no" + target_format = "raw" + type_name = "block" + driver_type = 'raw' + device_type = "disk" + target_dev = "sdb" + status_error = "no" + define_error = "no" + func_supported_since_libvirt_ver = (10, 0, 0) + offset = "512" + size_in_mb = "100" + block_size_in_bytes = "104857600" + disk_slice_attrs = "{'slice_type': 'storage', 'slice_offset': '0', 'slice_size': '512'}" + variants test_scenario: + - capacity: + resize_value = "--capacity" + - specific: + resize_value = "104857600B" + - save_restore: + only coldplug..virtio + resize_value = "--capacity" + vm_save = "/var/lib/libvirt/images/%s.save" + - not_equal_actual_size: + only coldplug..virtio + resize_value = "1024B" + status_error = "yes" + status_error_msg = "Operation not supported: block device backed disk must be resized to its actual size" + - not_zero_offset: + only coldplug..virtio + disk_slice_attrs = "{'slice_type': 'storage', 'slice_offset': '512', 'slice_size': '1024'}" + status_error = "yes" + resize_value = "--capacity" + status_error_msg = "Operation not supported: resize of a disk with storage slice with non-zero .*offset.*" + - non_raw_block_device: + only coldplug..virtio + overlay_source_file_path = "/var/lib/libvirt/images/qcow2" + driver_type = 'qcow2' + target_format = "qcow2" + status_error = "yes" + resize_value = "--capacity" + status_error_msg = "Operation not supported: block resize to full capacity supported only with.*raw.*local block-based disks" + variants target_bus: + - virtio: + - sata: + only coldplug + no s390-virtio,aarch64 + - scsi: + variants: + - coldplug: + virt_device_hotplug = "no" + - hotplug: + virt_device_hotplug = "yes" diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_blockresize.py b/libvirt/tests/src/virtual_disks/virtual_disks_blockresize.py new file mode 100644 index 00000000000..e7380dd73b9 --- /dev/null +++ b/libvirt/tests/src/virtual_disks/virtual_disks_blockresize.py @@ -0,0 +1,234 @@ +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Chunfu Wen +# + +import logging +import os +import time + +from virttest import libvirt_version +from virttest import virsh +from virttest import virt_vm +from virttest import utils_misc + +from virttest.libvirt_xml import vm_xml, xcepts +from virttest.utils_libvirt import libvirt_disk +from virttest.utils_test import libvirt + +from avocado.utils import process + + +LOG = logging.getLogger('avocado.' + __name__) +cleanup_files = [] + + +def setup_scsi_debug_block_device(): + """ + Setup one scsi_debug block device + + :return: device name + """ + source_disk = libvirt.create_scsi_disk(scsi_option="", + scsi_size="100") + return source_disk + + +def check_image_virtual_size(image_file, expected_size, test): + """ + Check whether image virtual size queried by qemu-img is matched + + :param image_file: image file path + :param expected_size: expected size + :param test: test case itself + """ + disk_info_dict = utils_misc.get_image_info(image_file) + actual_size_in_bytes = str(disk_info_dict.get("vsize")) + if actual_size_in_bytes != expected_size: + test.fail(f"actual size of block disk is {actual_size_in_bytes}, but expected is : {expected_size}") + + +def create_customized_disk(params, test): + """ + Create one customized disk with related attributes + + :param params: dict wrapped with params + :param test: test case itself + """ + type_name = params.get("type_name") + disk_device = params.get("device_type") + device_target = params.get("target_dev") + device_bus = params.get("target_bus") + device_format = params.get("target_format") + source_file_path = setup_scsi_debug_block_device() + overlay_source_file_path = params.get("overlay_source_file_path") + expected_size = params.get("block_size_in_bytes") + source_dict = {} + + # check block size + check_image_virtual_size(source_file_path, expected_size, test) + + if source_file_path: + source_dict.update({"dev": source_file_path}) + + if overlay_source_file_path: + libvirt.create_local_disk("file", overlay_source_file_path, "100M", device_format) + cleanup_files.append(overlay_source_file_path) + convert_cmd = "qemu-img convert -f qcow2 -O qcow2 %s %s" % (overlay_source_file_path, source_file_path) + process.run(convert_cmd, shell=True, verbose=True, ignore_status=False) + + disk_src_dict = {"attrs": source_dict} + + customized_disk = libvirt_disk.create_primitive_disk_xml( + type_name, disk_device, + device_target, device_bus, + device_format, disk_src_dict, None) + + # Sometimes, slice size can be gotten by command (du -b source_file_path), but here not necessary + disk_slice_attrs = params.get('disk_slice_attrs') + if disk_slice_attrs: + disk_source = customized_disk.source + disk_source.slices = customized_disk.new_slices(**eval(disk_slice_attrs)) + customized_disk.source = disk_source + + LOG.debug("create customized xml: %s", customized_disk) + return customized_disk + + +def check_slice_within_vm(vm, new_disk, slice_value): + """ + Check disk slices attributes in guest internal + + :param vm: vm object + :param new_disk: newly vm disk + :param slice_value: slice value + """ + session = None + try: + session = vm.wait_for_login() + cmd = ("lsblk |grep {0}" + .format(new_disk)) + status, output = session.cmd_status_output(cmd) + LOG.debug("Disk operation in VM:\nexit code:\n%s\noutput:\n%s", + status, output) + return slice_value in output + except Exception as err: + LOG.debug("Error happens when check slices in vm: %s", str(err)) + return False + finally: + if session: + session.close() + + +def check_vm_dumpxml(params, test, expected_attribute=True): + """ + Common method to check source in cdrom device + + :param params: one collective object representing wrapped parameters + :param test: test object + :param expected_attribute: bool indicating whether expected attribute exists or not + """ + vm_name = params.get("main_vm") + disk_vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + target_dev = params.get('target_dev') + disk = disk_vmxml.get_disk_all()[target_dev] + slices = disk.find('source').find('slices') + if not expected_attribute: + if slices is not None: + test.fail("unexpected slices appear in vm disk xml") + else: + if slices is None: + test.fail("slices can not be found in vm disk xml") + + +def run(test, params, env): + """ + Test resize disk with slices. + + 1.Prepare a vm with block disk + 2.Attach block disk with slice attribute to the vm + 3.Start vm + 4.Resize the block disk + 5.Check resize operations + 6.Check status in VM internal + 7.Detach device + """ + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + virsh_dargs = {'debug': True} + + hotplug = "yes" == params.get("virt_device_hotplug") + part_path = "/dev/%s" + + # Skip test if version not match expected one + libvirt_version.is_libvirt_feature_supported(params) + + # Get disk partitions info before hot/cold plug virtual disk + if vm.is_alive(): + vm.destroy(gracefully=False) + + # Backup vm xml + vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vmxml = vmxml_backup.copy() + + test_scenario = params.get("test_scenario") + target_bus = params.get("target_bus") + target_dev = params.get('target_dev') + status_error = "yes" == params.get("status_error") + try: + device_obj = create_customized_disk(params, test) + if not hotplug: + vmxml.add_device(device_obj) + vmxml.sync() + vm.start() + vm.wait_for_login() + if hotplug: + virsh.attach_device(vm_name, device_obj.xml, + ignore_status=False, debug=True) + except xcepts.LibvirtXMLError as xml_error: + test.fail("Failed to define VM:\n%s" % str(xml_error)) + except virt_vm.VMStartError as details: + test.fail("VM failed to start." + "Error: %s" % str(details)) + else: + session = vm.wait_for_login() + time.sleep(20) + new_disk, _ = libvirt_disk.get_non_root_disk_name(session) + session.close() + check_vm_dumpxml(params, test, True) + + slice_value = params.get("offset") + check_slice_within_vm(vm, new_disk, slice_value) + + if test_scenario in ["blockresize_save_restore"]: + vm_save = params.get("vm_save") + cleanup_files.append(vm_save) + virsh.save(vm_name, vm_save) + virsh.restore(vm_save) + vm.wait_for_login().close() + + resize_value = params.get("resize_value") + result = virsh.blockresize(vm_name, target_dev, + resize_value, **virsh_dargs) + libvirt.check_exit_status(result, status_error) + + if not status_error: + check_vm_dumpxml(params, test, False) + slice_value = params.get("size_in_mb") + check_slice_within_vm(vm, new_disk, slice_value) + if hotplug: + virsh.detach_device(vm_name, device_obj.xml, flagstr="--live", + debug=True, ignore_status=False) + finally: + if vm.is_alive(): + vm.destroy(gracefully=False) + vmxml_backup.sync() + libvirt.delete_scsi_disk() + for file_path in cleanup_files: + if os.path.exists(file_path): + os.remove(file_path) From ddfefdfd58a4a18b5059f6c58910a034d219d58a Mon Sep 17 00:00:00 2001 From: Qian Jianhua Date: Thu, 30 May 2024 13:23:10 +0800 Subject: [PATCH 0366/1055] numa: use dynamic expected value for different architectures Signed-off-by: Qian Jianhua --- .../memory_binding_setting.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py b/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py index 5689eb77241..e2f663ce3a4 100644 --- a/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py @@ -11,7 +11,6 @@ import os import re -import platform from avocado.utils import memory from avocado.utils import process @@ -154,15 +153,12 @@ def _check_values(expect_huge, expect_N0, expect_N1, expect_sum=None): mem_mode == 'prefered' and not single_host_node) or \ (mem_mode in ['interleave', 'preferred'] and single_host_node): - if platform.machine() == 'aarch64': - _check_values(True, 3, 1) - else: - _check_values(True, 512, 500) + hpc = test_setup.HugePageConfig(test_obj.params) + N0_expect = hpc.get_node_num_huge_pages(all_nodes[0], expected_hugepage_size) + _check_values(True, N0_expect, int(mem_size/psize)-N0_expect) elif not single_host_node and mem_mode == 'interleave': - if platform.machine() == 'aarch64': - _check_values(True, 2, 2) - else: - _check_values(True, 506, 506) + avg_value = int(mem_size/psize/2) + _check_values(True, avg_value, avg_value) elif not single_host_node and mem_mode in ['strict', 'restrictive']: _check_values(True, 0, 0, int(mem_size/psize)) test_obj.test.log.debug("Step: verify host numa node memory allocation PASS") From 9458bfe5f6fc0d63093368d7023fb60559393138 Mon Sep 17 00:00:00 2001 From: Chunfu Wen Date: Thu, 30 May 2024 04:08:54 -0400 Subject: [PATCH 0367/1055] Fix virsh.set_user_password.normal_test.normal_user.encrypted This case fail due to the fact that "openssl passwd -crypt %s" % new_passwd is not supported now, and use openssl passwd %s" % new_passwd directly Signed-off-by: Chunfu Wen --- .../tests/src/virsh_cmd/domain/virsh_set_user_password.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_set_user_password.py b/libvirt/tests/src/virsh_cmd/domain/virsh_set_user_password.py index 13d4737c443..af596ee33e0 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_set_user_password.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_set_user_password.py @@ -74,12 +74,7 @@ def run(test, params, env): # Set the user password in vm if encrypted: - openssl_version = process.run("openssl version", - ignore_status=False) - if "OpenSSL 3.0." in openssl_version.stdout_text: - cmd = "openssl passwd %s" % new_passwd - else: - cmd = "openssl passwd -crypt %s" % new_passwd + cmd = "openssl passwd %s" % new_passwd ret = process.run(cmd, shell=True) libvirt.check_exit_status(ret) en_passwd = str(ret.stdout_text.strip()) From dc14a80a8987352196748a1d7547ff70d6cc1a4e Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Fri, 31 May 2024 01:32:19 -0400 Subject: [PATCH 0368/1055] Resume the test with ipv6 multipath route Since passt support multipath route, resume the test in such situation. And get the guest interface name from the guest os instead of assume it since "acpi index" is not supported by aarch64. Signed-off-by: Yalan Zhang --- .../cfg/virtual_network/passt/passt_transfer_file.cfg | 2 -- .../tests/src/virtual_network/passt/passt_transfer_file.py | 7 ++----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg index 7bf357beda4..104c8fcd5da 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg @@ -28,10 +28,8 @@ portForwards = {'portForwards': [${portForward_0}]} iface_attrs = {'model': 'virtio', 'acpi': {'index': '1'}, **${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, **${alias}, 'type_name': 'user', **${portForwards}} ipv6_prefix = 128 - vm_iface = eno1 s390-virtio: iface_attrs = {'model': 'virtio', **${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, **${alias}, 'type_name': 'user', **${portForwards}} - vm_iface = enc1 variants file_size: - 10M: bs = 1M diff --git a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py index 6dae58ad615..e765e38bc68 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py +++ b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py @@ -120,10 +120,6 @@ def run(test, params, env): # related test if host has multipath route. When there is multipath route, # the utils_net.get_default_gateway() will return none. ip_ver = params.get('ip_ver') - if ip_ver == "ipv6": - if not utils_net.get_default_gateway(ip_ver=ip_ver): - test.cancel("Host has multipath route which can not be " - "recognized by passt and passt will disable ipv6.") root = 'root_user' == params.get('user_type', '') if root: @@ -154,7 +150,6 @@ def run(test, params, env): iface_attrs = eval(params.get('iface_attrs')) params['socket_dir'] = socket_dir = eval(params.get('socket_dir')) params['proc_checks'] = proc_checks = eval(params.get('proc_checks', '{}')) - vm_iface = params.get('vm_iface', 'eno1') host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_net_if( state="UP")[0] @@ -186,6 +181,8 @@ def run(test, params, env): if direction == 'host_to_vm': transfer_host_to_vm(session, prot, ip_ver, params, test) if direction == 'vm_to_host': + mac = vm.get_virsh_mac_address() + vm_iface = utils_net.get_linux_ifname(session, mac) transfer_vm_to_host(session, prot, ip_ver, vm_iface, firewalld, params, test) finally: From 08ec2f10da447fec12cf13a72bf655e04773ed69 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Fri, 31 May 2024 02:39:37 -0400 Subject: [PATCH 0369/1055] Get the iface name from the guest os Get the iface name from the guest os instead of assume it's interface name. Signed-off-by: Yalan Zhang --- .../virtual_network/passt/passt_connectivity_between_2vms.cfg | 2 -- .../virtual_network/passt/passt_connectivity_between_2vms.py | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_connectivity_between_2vms.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_connectivity_between_2vms.cfg index 239c98be175..2df722f8527 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_connectivity_between_2vms.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_connectivity_between_2vms.cfg @@ -36,7 +36,6 @@ ipv6_addr_c = '2001:db8:ac10:fd01::20' ips = {'ips': [{'address': '${ipv4_addr_c}', 'family': 'ipv4', 'prefix': '24'}, {'address': '${ipv6_addr_c}', 'family': 'ipv6'}]} iface_c_attrs = {'model': 'virtio', 'acpi': {'index': '1'}, **${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, 'type_name': 'user'} - vm_c_iface = eno1 conn_check_args_0 = ('TCP4', server_default_gw, None, 41335, 41335) conn_check_args_1 = ('TCP6', server_default_gw_v6, vm_c_iface, 41335, 41335) conn_check_args_2 = ('UDP4', server_default_gw, None, 21335, 21335) @@ -44,7 +43,6 @@ s390-virtio: iface_attrs = {'model': 'virtio', **${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, 'type_name': 'user', **${portForwards}} iface_c_attrs = {'model': 'virtio', **${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, 'type_name': 'user'} - vm_c_iface = enc1 conn_check_args_0 = ('TCP4', server_default_gw, None, 41335, 41335) conn_check_args_1 = ('TCP6', server_default_gw_v6, vm_c_iface, 41335, 41335) conn_check_args_2 = ('UDP4', server_default_gw, None, 21335, 21335) diff --git a/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py b/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py index d4ea9a86d38..b09fa04c18d 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py +++ b/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py @@ -64,7 +64,6 @@ def run(test, params, env): iface_c_attrs = eval(params.get('iface_c_attrs')) params['socket_dir'] = socket_dir = eval(params.get('socket_dir')) params['proc_checks'] = proc_checks = eval(params.get('proc_checks', '{}')) - vm_c_iface = params.get('vm_c_iface', 'eno1') host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_net_if( state="UP")[0] @@ -97,6 +96,8 @@ def run(test, params, env): server_session = vm.wait_for_serial_login(60) client_session = vm_c.wait_for_serial_login(60) + mac = vm_c.get_virsh_mac_address() + vm_c_iface = utils_net.get_linux_ifname(client_session, mac) [LOG.debug(session.cmd_output('ip a')) for session in (server_session, client_session)] From 2ff82055d2b2de8cf9442a4f19d60ca51fc34dfe Mon Sep 17 00:00:00 2001 From: Qian Jianhua Date: Mon, 3 Jun 2024 11:10:00 +0800 Subject: [PATCH 0370/1055] numa: fix no enough memory On aarch64 with pagesize=4K, the hugepages count is too small to start VM. Signed-off-by: Qian Jianhua --- .../various_numa_topology_settings.cfg | 1 - .../various_numa_topology_settings.py | 10 ++++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/numa/guest_numa_topology/various_numa_topology_settings.cfg b/libvirt/tests/cfg/numa/guest_numa_topology/various_numa_topology_settings.cfg index f3865ae789b..4371b1d32a4 100644 --- a/libvirt/tests/cfg/numa/guest_numa_topology/various_numa_topology_settings.cfg +++ b/libvirt/tests/cfg/numa/guest_numa_topology/various_numa_topology_settings.cfg @@ -11,7 +11,6 @@ target_hugepages = 1024 aarch64: cpu_mode = 'host-passthrough' - target_hugepages = 32 hugepage_size = 2048 numa_cell_0 = {'id': '0', 'memory': '1048576', 'cpus': '0-1'} numa_cell_1 = {'id': '1', 'memory': '1048576', 'cpus': '2-3'} diff --git a/libvirt/tests/src/numa/guest_numa_topology/various_numa_topology_settings.py b/libvirt/tests/src/numa/guest_numa_topology/various_numa_topology_settings.py index d22c42a0ad6..c4668527644 100644 --- a/libvirt/tests/src/numa/guest_numa_topology/various_numa_topology_settings.py +++ b/libvirt/tests/src/numa/guest_numa_topology/various_numa_topology_settings.py @@ -27,6 +27,16 @@ def setup_default(test_obj): """ test_obj.setup() hpc = test_setup.HugePageConfig(test_obj.params) + + numa_cells = eval(test_obj.params.get('numa_cells', '[]')) + if numa_cells: + #set target_hugepages according to the setting of 'numa_cells'. + total_mem = 0 + for i in range(len(numa_cells)): + total_mem += int(numa_cells[i]['memory']) + test_obj.params["target_hugepages"] = int(total_mem/hpc.get_hugepage_size()) + hpc = test_setup.HugePageConfig(test_obj.params) + hpc.setup() test_obj.params['hp_config_obj'] = hpc test_obj.test.log.debug("Step: setup is done") From b2d5327f3b8da4b4a197c476bf6c02a9127f80cc Mon Sep 17 00:00:00 2001 From: Xiaodai Wang Date: Mon, 3 Jun 2024 14:31:42 +0800 Subject: [PATCH 0371/1055] v2v: fix a minor typo Signed-off-by: Xiaodai Wang --- provider/v2v_vmcheck_helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provider/v2v_vmcheck_helper.py b/provider/v2v_vmcheck_helper.py index e99d168cba2..f1a1f45562c 100644 --- a/provider/v2v_vmcheck_helper.py +++ b/provider/v2v_vmcheck_helper.py @@ -422,7 +422,7 @@ def _id_short_to_long(short_id): verbose=False) short_id_all = output.stdout_text.splitlines() if short_id not in [os_id.strip() for os_id in short_id_all]: - LOG.info("Not found shourt_id '%s' on host", short_id) + LOG.info("Not found short_id '%s' on host", short_id) long_id = _guess_long_id(short_id) else: cmd = "osinfo-query os --fields=id short-id='%s'| tail -n +3" % short_id From fcedf0fcffe1c15c6594442a299912b99017d911 Mon Sep 17 00:00:00 2001 From: Xiaodai Wang Date: Mon, 3 Jun 2024 16:31:57 +0800 Subject: [PATCH 0372/1055] v2v: fix ovirt module import issue Only import ovirt module when necessary Signed-off-by: Xiaodai Wang --- v2v/tests/src/function_test_esx.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2v/tests/src/function_test_esx.py b/v2v/tests/src/function_test_esx.py index 8dcc8c719bd..8c07c1aac65 100644 --- a/v2v/tests/src/function_test_esx.py +++ b/v2v/tests/src/function_test_esx.py @@ -4,7 +4,6 @@ import uuid import shutil import tempfile -import ovirtsdk4 import xml.etree.ElementTree as ET from virttest import data_dir @@ -750,6 +749,7 @@ def vm_check(status_error): os.environ['http_proxy'] = http_proxy os.environ['https_proxy'] = https_proxy if 'ovirtsdk4_pkg' in checkpoint: + import ovirtsdk4 ovirt4_path = os.path.dirname(ovirtsdk4.__file__) dst_ovirt4_path = ovirt4_path + '.bak' os.rename(ovirt4_path, dst_ovirt4_path) From fc0515e5719879b495f3c3aa48466aa33cedcbec Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Mon, 3 Jun 2024 17:38:46 +0800 Subject: [PATCH 0373/1055] virtual_disks: Add a vhostvdpa-blk test This pr adds: VIRT-300442 - Define&Start two vms with disk of a same vhostvdpa backend Signed-off-by: Yingshun Cui --- ...t_vms_with_same_vhostvdpa_backend_disk.cfg | 12 +++++ ...rt_vms_with_same_vhostvdpa_backend_disk.py | 48 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/define_start_vms_with_same_vhostvdpa_backend_disk.cfg create mode 100644 libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/define_start_vms_with_same_vhostvdpa_backend_disk.py diff --git a/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/define_start_vms_with_same_vhostvdpa_backend_disk.cfg b/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/define_start_vms_with_same_vhostvdpa_backend_disk.cfg new file mode 100644 index 00000000000..a539534bfb6 --- /dev/null +++ b/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/define_start_vms_with_same_vhostvdpa_backend_disk.cfg @@ -0,0 +1,12 @@ +- virtual_disks.vhostvdpa.define_start_multi_vms_with_same_disk: + type = define_start_vms_with_same_vhostvdpa_backend_disk + start_vm = no + simulator = "yes" + func_supported_since_libvirt_ver = (9, 10, 0) + only x86_64 + + vms = avocado-vt-vm1 vm2 + disk_vdpa_attrs = {"source": {"attrs": {"dev": "/dev/vhost-vdpa-0"}}, "type_name": "vhostvdpa"} + disk_driver = {"driver": {"name": "qemu", "type": "raw", "cache": "none", "io": "threads", "copy_on_read": "on", "discard": "unmap", "detect_zeroes": "on"}} + disk_attrs = {"device": "disk", "target": {"dev": "vdb", "bus": "virtio"}, **${disk_vdpa_attrs}, **${disk_driver}} + err_msg = "vdpa device.*Device or resource busy" diff --git a/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/define_start_vms_with_same_vhostvdpa_backend_disk.py b/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/define_start_vms_with_same_vhostvdpa_backend_disk.py new file mode 100644 index 00000000000..cff4b87a732 --- /dev/null +++ b/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/define_start_vms_with_same_vhostvdpa_backend_disk.py @@ -0,0 +1,48 @@ +from virttest import libvirt_version +from virttest import utils_vdpa +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +VIRSH_ARGS = {'debug': True, 'ignore_status': False} + + +def run(test, params, env): + """ + Verify that if two vms use the same vhost-vdpa backend, the second one will + fail to start + """ + libvirt_version.is_libvirt_feature_supported(params) + + disk_attrs = eval(params.get("disk_attrs", "{}")) + err_msg = params.get("err_msg") + vms = params.get('vms').split() + vm_list = [env.get_vm(v_name) for v_name in vms] + vm, vm2 = vm_list[:2] + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) + vm2_xml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm2.name) + + bkxml = vmxml.copy() + + try: + test.log.info("TEST_STEP: Define two VMs with the same vhostvdpa disk.") + test_env_obj = utils_vdpa.VDPASimulatorTest( + sim_dev_module="vdpa_sim_blk", mgmtdev="vdpasim_blk") + test_env_obj.setup() + for _vm in [vm, vm2]: + vm_xml.VMXML.set_memoryBacking_tag( + _vm.name, access_mode="shared", hpgs=False) + libvirt_vmxml.modify_vm_device( + vm_xml.VMXML.new_from_dumpxml(_vm.name), "disk", disk_attrs, 1) + test.log.debug(f'VMXML of {_vm.name}:\n{virsh.dumpxml(_vm.name).stdout_text}') + + test.log.info("TEST_STEP: Start the VMs.") + vm.start() + cmd_result = virsh.start(vm2.name) + libvirt.check_result(cmd_result, err_msg) + finally: + bkxml.sync() + vm2_xml_backup.sync() + test_env_obj.cleanup() From 52fdc135f4311c4dc4483899d8e552ea4788b14f Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 3 Jun 2024 17:48:41 +0800 Subject: [PATCH 0374/1055] migration: Update error message Signed-off-by: lcheng --- libvirt/tests/cfg/migration/migrate_vm.cfg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/migration/migrate_vm.cfg b/libvirt/tests/cfg/migration/migrate_vm.cfg index d979727e5a5..150c59df045 100644 --- a/libvirt/tests/cfg/migration/migrate_vm.cfg +++ b/libvirt/tests/cfg/migration/migrate_vm.cfg @@ -831,19 +831,19 @@ hard_limit_value = "1048576" swap_hard_limit_value = "2097152" memtune_options = "--hard-limit ${hard_limit_value} --swap-hard-limit ${swap_hard_limit_value} --config" - err_msg = "unable to execute QEMU command 'migrate-incoming': RDMA ERROR: could not create rdma event channel" + err_msg = "unable to execute QEMU command 'migrate-incoming': RDMA ERROR: could not create rdma event channel|unable to execute QEMU command 'migrate-incoming': Migration requires multi-channel URIs" - no_rdma_env_rdma_pin_all: hard_limit_value = "2097152" swap_hard_limit_value = "2097152" memtune_options = "--hard-limit ${hard_limit_value} --swap-hard-limit ${swap_hard_limit_value} --config" virsh_options = "--live --verbose --rdma-pin-all --migrateuri rdma://${server_ip} --listen-address 0.0.0.0" - err_msg = "unable to execute QEMU command 'migrate-incoming': RDMA ERROR: could not create rdma event channel" + err_msg = "unable to execute QEMU command 'migrate-incoming': RDMA ERROR: could not create rdma event channel|unable to execute QEMU command 'migrate-incoming': Migration requires multi-channel URIs" - no_rdma_env_turn_off_rdma_pin_all: hard_limit_value = "1048576" swap_hard_limit_value = "1048576" memtune_options = "--hard-limit ${hard_limit_value} --swap-hard-limit ${swap_hard_limit_value} --config" virsh_options = "--live --verbose --rdma-pin-all --migrateuri rdma://${server_ip}" - err_msg = "unable to execute QEMU command 'migrate-incoming': RDMA ERROR: could not create rdma event channel" + err_msg = "unable to execute QEMU command 'migrate-incoming': RDMA ERROR: could not create rdma event channel|unable to execute QEMU command 'migrate-incoming': Migration requires multi-channel URIs" - cross_rhel_platform_migration: # only work well on RHEL platform migration_timeout = 600 From 736126c67f22d3817a54d2f1fcdfc79da6c88d5a Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Mon, 3 Jun 2024 18:03:10 +0800 Subject: [PATCH 0375/1055] virtual_disks: Add a vhostvdpa disk hotplug case This PR adds: VIRT-300429 - Hotplug&unplug disk of vhostvdpa backend Signed-off-by: Yingshun Cui --- .../hotplug_vhostvdpa_backend_disk.cfg | 16 +++++ .../hotplug_vhostvdpa_backend_disk.py | 72 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/hotplug_vhostvdpa_backend_disk.cfg create mode 100644 libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/hotplug_vhostvdpa_backend_disk.py diff --git a/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/hotplug_vhostvdpa_backend_disk.cfg b/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/hotplug_vhostvdpa_backend_disk.cfg new file mode 100644 index 00000000000..299fe4b2771 --- /dev/null +++ b/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/hotplug_vhostvdpa_backend_disk.cfg @@ -0,0 +1,16 @@ +- virtual_disks.vhostvdpa.hotplug: + type = hotplug_vhostvdpa_backend_disk + start_vm = no + simulator = "yes" + disk_vdpa_attrs = {"source": {"attrs": {"dev": "/dev/vhost-vdpa-0"}}, "type_name": "vhostvdpa"} + func_supported_since_libvirt_ver = (9, 10, 0) + only x86_64 + + variants cache_mode: + - none: + - directsync: + - no_specified_value: + status_error = "yes" + + disk_driver = {"driver": {"name": "qemu", "type": "raw", "cache": "${cache_mode}", "io": "threads", "copy_on_read": "on", "discard": "unmap", "detect_zeroes": "on"}} + disk_attrs = {"device": "disk", "target": {"dev": "vdb", "bus": "virtio"}, **${disk_vdpa_attrs}, **${disk_driver}} diff --git a/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/hotplug_vhostvdpa_backend_disk.py b/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/hotplug_vhostvdpa_backend_disk.py new file mode 100644 index 00000000000..869e2d19780 --- /dev/null +++ b/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/hotplug_vhostvdpa_backend_disk.py @@ -0,0 +1,72 @@ +from virttest import libvirt_version +from virttest import utils_vdpa +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_disk +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +VIRSH_ARGS = {'debug': True, 'ignore_status': False} + + +def run(test, params, env): + """ + Hotplug/unplug vhost-vdpa backend disk + """ + libvirt_version.is_libvirt_feature_supported(params) + disk_attrs = eval(params.get("disk_attrs", "{}")) + status_error = "yes" == params.get("status_error", "no") + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + test.log.info("TEST_SETUP: Prepare a simulated vhost-vdpa disk on host.") + test_env_obj = utils_vdpa.VDPASimulatorTest( + sim_dev_module="vdpa_sim_blk", mgmtdev="vdpasim_blk") + test_env_obj.setup() + + test.log.info("TEST_STEP: Define a VM with shared memory.") + vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", hpgs=False) + vm.start() + vm_session = vm.wait_for_login() + + test.log.info("TEST_STEP: Hotplug a vhost-vdpa disk to VM.") + disk_dev = libvirt_vmxml.create_vm_device_by_type("disk", disk_attrs) + cmd_result = virsh.attach_device(vm_name, disk_dev.xml, debug=True) + libvirt.check_exit_status(cmd_result, status_error) + if status_error: + return + + test.log.info("TEST_STEP: Check VM's xml.") + vdpa_device = vm_xml.VMXML.new_from_dumpxml(vm.name)\ + .devices.by_device_tag("disk")[-1] + vdpa_dev_attrs = vdpa_device.fetch_attrs() + test.log.debug(vdpa_dev_attrs) + for k, v in disk_attrs.items(): + if k == "source": + act_dev = vdpa_dev_attrs[k]["attrs"].get("dev") + exp_dev = v["attrs"]["dev"] + if act_dev != exp_dev: + test.fail("Incorrect disk dev! Expected: %s, Actual: %s." + % (exp_dev, act_dev)) + elif vdpa_dev_attrs[k] != v: + test.fail("Failed to get expected disk attributes(%s) in live xml!" + "It should be %s." % (vdpa_dev_attrs[k], v)) + + test.log.info("TEST_STEP: Check r/w operations on vhostvdpa disk.") + new_disk = libvirt_disk.get_non_root_disk_name(vm_session)[0] + if not libvirt_disk.check_virtual_disk_io(vm, new_disk): + test.fail("Failed to check disk io for %s!" % new_disk) + + test.log.info("TEST_STEP: Hotunplug a vhost-vdpa disk from VM.") + target_dev = disk_attrs['target']['dev'] + virsh.detach_disk(vm_name, target_dev, **VIRSH_ARGS) + vm_disks = vm_xml.VMXML.new_from_dumpxml(vm.name).devices.by_device_tag("disk") + if len(vm_disks) != 1: + test.fail("There should be only one disk but got %s." % vm_disks) + finally: + bkxml.sync() + test_env_obj.cleanup() From 46c058dc3e0132724b3440c0f51c4543ebd59f50 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Mon, 3 Jun 2024 22:25:03 +0800 Subject: [PATCH 0376/1055] virtual_disks: Add a blockcopy test for vhostvdpa disk This PR adds: VIRT-300444 - Blockcopy a disk of vhostvdpa backend Signed-off-by: Yingshun Cui --- .../blockcopy_vhostvdpa_backend_disk.cfg | 14 ++++ .../blockcopy_vhostvdpa_backend_disk.py | 73 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/blockcopy_vhostvdpa_backend_disk.cfg create mode 100644 libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/blockcopy_vhostvdpa_backend_disk.py diff --git a/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/blockcopy_vhostvdpa_backend_disk.cfg b/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/blockcopy_vhostvdpa_backend_disk.cfg new file mode 100644 index 00000000000..737b7444ffe --- /dev/null +++ b/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/blockcopy_vhostvdpa_backend_disk.cfg @@ -0,0 +1,14 @@ +- virtual_disks.vhostvdpa.blockcopy: + type = blockcopy_vhostvdpa_backend_disk + start_vm = no + only x86_64 + + func_supported_since_libvirt_ver = (9, 10, 0) + simulator = "yes" + disk_target = "vdb" + disk_vdpa_attrs = {"source": {"attrs": {"dev": "/dev/vhost-vdpa-0"}}, "type_name": "vhostvdpa"} + disk_driver = {"driver": {"name": "qemu", "type": "raw", "cache": "none", "io": "threads", "copy_on_read": "on", "discard": "unmap", "detect_zeroes": "on"}} + disk_attrs = {"device": "disk", "target": {"dev": "${disk_target}", "bus": "virtio"}, **${disk_vdpa_attrs}, **${disk_driver}} + bc_disk_vdpa_attrs = {"source": {"attrs": {"dev": "/dev/vhost-vdpa-1"}}, "type_name": "vhostvdpa"} + bc_disk_attrs = {"device": "disk", "target": {"dev": "${disk_target}", "bus": "virtio"}, **${bc_disk_vdpa_attrs}, **${disk_driver}} + bc_options = "--xml {} --pivot --transient-job" diff --git a/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/blockcopy_vhostvdpa_backend_disk.py b/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/blockcopy_vhostvdpa_backend_disk.py new file mode 100644 index 00000000000..a9cf26ae4a8 --- /dev/null +++ b/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/blockcopy_vhostvdpa_backend_disk.py @@ -0,0 +1,73 @@ +from virttest import libvirt_version +from virttest import utils_disk +from virttest import utils_misc +from virttest import utils_vdpa +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_disk +from virttest.utils_libvirt import libvirt_vmxml + +VIRSH_ARGS = {'debug': True, 'ignore_status': False} + + +def run(test, params, env): + """ + Verify that blockcopy a disk of vhostvdpa backend can succeed + """ + libvirt_version.is_libvirt_feature_supported(params) + disk_attrs = eval(params.get("disk_attrs", "{}")) + bc_disk_attrs = eval(params.get("bc_disk_attrs", "{}")) + disk_target = params.get("disk_target", "vdb") + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + test.log.info("TEST_STEP: Prepare two simulated vhost-vdpa disks on host.") + test_env_obj = utils_vdpa.VDPASimulatorTest(sim_dev_module="vdpa_sim_blk", mgmtdev="vdpasim_blk") + test_env_obj.setup(dev_num=2) + + test.log.info("TEST_STEP: Define a VM with vhost-vdpa disk.") + vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", hpgs=False) + libvirt_vmxml.modify_vm_device(vm_xml.VMXML.new_from_dumpxml(vm_name), "disk", disk_attrs, 1) + vm.start() + vm_session = vm.wait_for_login() + + test.log.info("TEST_STEP: Check r/w operations on vhostvdpa disk.") + new_disk = libvirt_disk.get_non_root_disk_name(vm_session)[0] + utils_disk.mount(f"/dev/{new_disk}", "/mnt", session=vm_session) + before_bc_string = utils_misc.generate_random_string(8) + cmd_in_vm = "echo {0} >> /mnt/test ;sync; grep {0} /mnt/test".format(before_bc_string) + vm_session.cmd(cmd_in_vm) + + test.log.info("TEST_STEP: Blockcopy the vhostvdpa disk to a new vhostdisk location.") + bc_xml_obj = libvirt_vmxml.create_vm_device_by_type("disk", bc_disk_attrs) + bc_options = params.get("bc_options").format(bc_xml_obj.xml) + virsh.blockcopy(vm_name, disk_target, "", options=bc_options, **VIRSH_ARGS) + + test.log.info("TEST_STEP: Check VM's xml.") + vdpa_device = vm_xml.VMXML.new_from_dumpxml(vm.name)\ + .devices.by_device_tag("disk")[-1] + vdpa_dev_attrs = vdpa_device.fetch_attrs() + test.log.debug(vdpa_dev_attrs) + vdpa_dev_source = vdpa_dev_attrs["source"]["attrs"].get("dev") + exp_dev_source = bc_disk_attrs["source"]["attrs"].get("dev") + if vdpa_dev_source != exp_dev_source: + test.fail("Incorrect disk dev after blockcopy! Expected: '%s', " + "Actual: '%s'." % (exp_dev_source, vdpa_dev_source)) + + test.log.info("TEST_STEP: Check r/w operations on vhostvdpa disk after blockcopy") + vm_session = vm.wait_for_login() + utils_disk.mount(f"/dev/{new_disk}", "/mnt", session=vm_session) + cmd_in_vm = "grep {0} /mnt/test".format(before_bc_string) + vm_session.cmd(cmd_in_vm) + after_bc_string = utils_misc.generate_random_string(8) + cmd_in_vm = "echo {0} >> /mnt/test ;sync; grep {0} /mnt/test".format(after_bc_string) + vm_session.cmd(cmd_in_vm) + + finally: + bkxml.sync() + test_env_obj.cleanup() From 608173b049f0d1f14ec0f4459c1370a9adb7b806 Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 4 Jun 2024 11:32:16 +0800 Subject: [PATCH 0377/1055] migration: Update error message Signed-off-by: lcheng --- libvirt/tests/cfg/migration/migrate_options_shared.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/migration/migrate_options_shared.cfg b/libvirt/tests/cfg/migration/migrate_options_shared.cfg index c5e9714ed8e..915164c85c2 100644 --- a/libvirt/tests/cfg/migration/migrate_options_shared.cfg +++ b/libvirt/tests/cfg/migration/migrate_options_shared.cfg @@ -610,7 +610,7 @@ variants: - without_option: virsh_migrate_extra = "--tls" - err_msg = "error: internal error: qemu unexpectedly closed the monitor|Domain not found|QEMU unexpectedly closed the monitor" + err_msg = "error: internal error: qemu unexpectedly closed the monitor|Domain not found|QEMU unexpectedly closed the monitor|Certificate does not match the hostname" - empty_str: virsh_migrate_extra = "--tls --tls-destination ''" err_msg = "error: Failed to get option 'tls-destination': Option argument is empty" @@ -619,7 +619,7 @@ err_msg = "error: Option --tls is required by option --tls-destination" - incorrect_hostname: virsh_migrate_extra = "--tls --tls-destination fake${server_cn}" - err_msg = "error: internal error: qemu unexpectedly closed the monitor|Domain not found|QEMU unexpectedly closed the monitor" + err_msg = "error: internal error: qemu unexpectedly closed the monitor|Domain not found|QEMU unexpectedly closed the monitor|Certificate does not match the hostname" - tunnelled_migration: only without_postcopy virsh_migrate_options = "--live --p2p --tunnelled --verbose" From 87ae212f4e5a814164e09a04d723453b1af98767 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Tue, 7 May 2024 23:08:46 -0400 Subject: [PATCH 0378/1055] Add adaption to support different huge page size for multi arch Signed-off-by: liang-cong-red-hat --- .../memory_backing/hugepage_nodeset.cfg | 36 ++++--- .../memory/memory_backing/hugepage_nodeset.py | 5 + provider/memory/memory_base.py | 101 +++++++++++++++++- 3 files changed, 128 insertions(+), 14 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_backing/hugepage_nodeset.cfg b/libvirt/tests/cfg/memory/memory_backing/hugepage_nodeset.cfg index 314b863cc7e..d04a1af0154 100644 --- a/libvirt/tests/cfg/memory/memory_backing/hugepage_nodeset.cfg +++ b/libvirt/tests/cfg/memory/memory_backing/hugepage_nodeset.cfg @@ -2,21 +2,30 @@ type = hugepage_nodeset no s390-virtio start_vm = no - page_size = "2048" page_unit = "KiB" - current_mem = 2072576 - mem_value = 2072576 mem_unit = "KiB" current_mem_unit = "KiB" - set_pagesize = "2048" - set_pagenum = "1024" expect_str = "huge" - aarch64: - page_size = "524288" - current_mem = 1572864 - mem_value = 1572864 - set_pagesize = "524288" - set_pagenum = "4" + variants kernel_pagesize: + - 4k: + default_page_size = 4 + variants huge_pagesize: + - 2048: + page_size = "2048" + current_mem = 2072576 + mem_value = 2072576 + set_pagesize = "2048" + set_pagenum = "1024" + - 64k: + default_page_size = 64 + only aarch64 + variants huge_pagesize: + - 524288: + page_size = "524288" + current_mem = 1572864 + mem_value = 1572864 + set_pagesize = "524288" + set_pagenum = "4" variants: - nodeset_0: nodeset = "0" @@ -30,7 +39,7 @@ - with_numa: numa_size_1 = 1048576 numa_size_2 = 1024000 - aarch64: + 524288: numa_size_2 = 524288 numa_cpu = {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_size_1}', 'unit': 'KiB'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_size_2}', 'unit': 'KiB'}]} vm_attrs = {${memory_backing_dict},"cpu":${numa_cpu},'vcpu': 4,'max_mem_rt_slots': 16,'memory_unit':"${mem_unit}",'memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}','max_mem_rt': 3145728, 'max_mem_rt_unit': "KiB"} @@ -40,5 +49,6 @@ vm_attrs = {${memory_backing_dict}, 'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} expect_xpath = [{'element_attrs':[".//page[@size='${page_size}']", ".//page[@unit='${page_unit}']"]}] allocated_mem = "2072576" - aarch64: + 524288: allocated_mem = "1572864" + diff --git a/libvirt/tests/src/memory/memory_backing/hugepage_nodeset.py b/libvirt/tests/src/memory/memory_backing/hugepage_nodeset.py index 90a728885db..2f3a590ba53 100644 --- a/libvirt/tests/src/memory/memory_backing/hugepage_nodeset.py +++ b/libvirt/tests/src/memory/memory_backing/hugepage_nodeset.py @@ -19,6 +19,8 @@ from virttest.utils_test import libvirt from virttest.utils_libvirt import libvirt_vmxml +from provider.memory import memory_base + def check_numa_maps(test, params, result): """ @@ -69,6 +71,8 @@ def setup_test(): Allocate hugepage memory """ test.log.info("TEST_SETUP: Allocate hugepage memory") + memory_base.check_mem_page_sizes( + test, pg_size=int(default_page_size), hp_size=int(set_pagesize)) hp_cfg = test_setup.HugePageConfig(params) hp_cfg.set_kernel_hugepages(set_pagesize, set_pagenum) @@ -127,6 +131,7 @@ def teardown_test(): vm_attrs = eval(params.get('vm_attrs', '{}')) allocated_mem = params.get('allocated_mem') + default_page_size = params.get("default_page_size") set_pagesize = params.get("set_pagesize") set_pagenum = params.get("set_pagenum") expect_xpath = eval(params.get("expect_xpath")) diff --git a/provider/memory/memory_base.py b/provider/memory/memory_base.py index f878fc9f6bc..3ea45906c01 100644 --- a/provider/memory/memory_base.py +++ b/provider/memory/memory_base.py @@ -5,11 +5,17 @@ from avocado.utils import cpu from avocado.utils import memory as avocado_mem +from virttest import virsh from virttest import libvirt_version from virttest import utils_misc - from virttest.libvirt_xml.devices import memory +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt from virttest.utils_version import VersionInterval +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_libvirt import libvirt_misc + +virsh_dargs = {"ignore_status": False, "debug": True} def convert_data_size(current_size, dest_unit="KiB"): @@ -149,3 +155,96 @@ def adjust_memory_size(params): params.update({'block_size': default_pagesize_KiB}) params.update({'request_size': default_pagesize_KiB}) params.update({'target_size': default_pagesize_KiB*2}) + + +def define_guest_with_memory_device(params, mem_attr_list, vm_attrs=None): + """ + Define guest with specified memory device. + + :param params: a dict for parameters. + :param mem_attr_list: memory device attributes list. + :param vm_attrs: basic vm attributes to define. + """ + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(params.get("main_vm")) + if vm_attrs: + vmxml.setup_attrs(**vm_attrs) + + if not isinstance(mem_attr_list, list): + mem_attr_list = [mem_attr_list] + for mem in mem_attr_list: + memory_object = libvirt_vmxml.create_vm_device_by_type('memory', mem) + vmxml.devices = vmxml.devices.append(memory_object) + vmxml.sync() + + +def plug_memory_and_check_result(test, params, mem_dict, operation='attach', + expected_error='', expected_event='', **kwargs): + """ + Hot plug or hot unplug memory and check event. + + :param test: test object. + :param params: dictionary with the test parameters. + :param mem_dict: the memory dict to plug. + :param operation: the operation of plug or unplug. + :param expected_error: expected error after plug or unplug. + :param expected_event: expected event for plug or unplug. + """ + vm_name = params.get('main_vm') + plug_dimm = libvirt_vmxml.create_vm_device_by_type('memory', mem_dict) + + wait_event = True if expected_event else False + if operation == "attach": + res = virsh.attach_device(vm_name, plug_dimm.xml, wait_for_event=wait_event, + event_type=expected_event, debug=True, **kwargs) + elif operation == "detach": + res = virsh.detach_device(vm_name, plug_dimm.xml, wait_for_event=wait_event, + event_type=expected_event, debug=True, **kwargs) + + if expected_error: + libvirt.check_result(res, expected_fails=expected_error) + else: + libvirt.check_exit_status(res) + + +def check_dominfo(vm, test, expected_max, expected_used): + """ + Check Max memory value and Used memory in virsh dominfo result. + + :param vm: vm object. + :param test: test object. + :param params: dictionary with the test parameters. + :param expected_max: expected Max memory in virsh dominfo. + :param expected_used: expected Used memory in virsh dominfo. + """ + result = virsh.dominfo(vm.name, **virsh_dargs).stdout_text.strip() + + dominfo_dict = libvirt_misc.convert_to_dict( + result, pattern=r'(\S+ \S+):\s+(\S+)') + if dominfo_dict["Max memory"] != expected_max: + test.fail("Memory value should be %s " % expected_max) + if dominfo_dict["Used memory"] != expected_used: + test.fail("Current memory should be %s " % expected_used) + test.log.debug("Check virsh dominfo successfully.") + + +def check_mem_page_sizes(test, pg_size=None, hp_size=None, hp_list=None): + """ + Check host is suitable for various memory page sizes + + :param test: test object + :param pg_size: int, default memory page size in KiB unit + :param hp_size: int, default memory huge page size in KiB unit + :param hp_list: list, huge page size int list in KiB unit + """ + default_page_size = avocado_mem.get_page_size() / 1024 + if pg_size and pg_size != default_page_size: + test.cancel("Expected host default page size is %s KiB, but get %s KiB" % + (pg_size, default_page_size)) + default_huge_page_size = avocado_mem.get_huge_page_size() + if hp_size and hp_size != default_huge_page_size: + test.cancel("Expected host default huge page size is %s KiB, but get %s KiB" % + (hp_size, default_huge_page_size)) + supported_hp_size_list = avocado_mem.get_supported_huge_pages_size() + if hp_list and not set(hp_list).issubset(set(supported_hp_size_list)): + test.cancel("Expected huge page size list is %s, but get %s" % + (hp_list, supported_hp_size_list)) From 7c72d8d5024df3c37503276a9e6232ff609c0edb Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 4 Jun 2024 03:41:05 -0400 Subject: [PATCH 0379/1055] 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 f7a6ba37306..cb589bd33bb 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 56d1d512be9..19864e03b99 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() From 0ba7c975382ef96395ba1ec6da87ffed761bec3b Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 4 Jun 2024 09:38:23 -0400 Subject: [PATCH 0380/1055] libvirt_ccw_passthrough: use wait_for instead of sleep The device_remove test case sometimes still fails. Instead now allow for up to 10 seconds for device to appear and instead use wait_for. Signed-off-by: Sebastian Mitterle --- .../ccw/libvirt_ccw_passthrough.py | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py b/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py index 9d24f609ebd..a68a2f5d52b 100644 --- a/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py +++ b/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py @@ -1,12 +1,31 @@ -from time import sleep from uuid import uuid4 +from virttest.utils_misc import wait_for, cmd_status_output from virttest.utils_zchannels import ChannelPaths from virttest.libvirt_xml.vm_xml import VMXML from provider.vfio import ccw +def mdev_listed(uuid): + """ + Returns a function that will check if the mediated device + with given uuid is listed + + :param uuid: uuid of the mediated device + """ + + def _mdev_listed(): + """ + True if uuid is listed, False else + """ + cmd = "lsmdev" + _, o = cmd_status_output(cmd) + return uuid in o + + return _mdev_listed + + def run(test, params, env): """ Test for CCW, esp. DASD disk passthrough on s390x. @@ -56,8 +75,7 @@ def run(test, params, env): ccw.set_override(schid) ccw.start_device(uuid, schid) - - sleep(2) + wait_for(lambda: mdev_listed(uuid), timeout=10) vm.start() session = vm.wait_for_login() From 077f8ba878a8185c91d1cb7081844dcc50731d6c Mon Sep 17 00:00:00 2001 From: Qian Jianhua Date: Wed, 5 Jun 2024 15:43:24 +0800 Subject: [PATCH 0381/1055] cpu: fix ACPI requires UEFI on aarch64 Don't remove the os loader attributes if vmx has acpi feature on aarch64 Signed-off-by: Qian Jianhua --- libvirt/tests/src/cpu/vcpu_metrics.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libvirt/tests/src/cpu/vcpu_metrics.py b/libvirt/tests/src/cpu/vcpu_metrics.py index 3c18b9c4855..2bcaa863171 100644 --- a/libvirt/tests/src/cpu/vcpu_metrics.py +++ b/libvirt/tests/src/cpu/vcpu_metrics.py @@ -16,6 +16,7 @@ import re import shutil import stat +import platform from avocado.utils import process @@ -134,7 +135,16 @@ def setup_with_unprivileged_user(vm, params, test): unprivileged_boot_disk_path = os.path.join(unprivileged_boot_disk_path, os.path.basename(first_disk_source)) disk_attrs = {'source': {'attrs': {'file': unprivileged_boot_disk_path}}} libvirt_vmxml.modify_vm_device(vmxml, 'disk', disk_attrs) + os_attrs = { + "loader": vmxml.os.loader, + "loader_readonly": vmxml.os.loader_readonly, + "loader_type": vmxml.os.loader_type + } vmxml.os = libvirt_bios.remove_bootconfig_items_from_vmos(vmxml.os) + if vmxml.xmltreefile.find('features'): + arch = platform.machine().lower() + if vmxml.features.has_feature('acpi') and 'aarch64' in arch: + vmxml.set_os_attrs(**os_attrs) test.log.debug('VM XML after updating:\n%s', vmxml) test.log.debug("Step: Prepare boot disk image in unprivileged user's home directory") From 2497f03f9fc216f15bf09d497e6b7152b4d6facc Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 5 Jun 2024 07:51:33 -0400 Subject: [PATCH 0382/1055] filesystem_device_unprivileged: fix wrong import The function was moved to another module. Also apply black to improve formatting. Signed-off-by: Sebastian Mitterle --- .../filesystem_device_unprivileged.py | 69 +++++++++---------- 1 file changed, 32 insertions(+), 37 deletions(-) diff --git a/libvirt/tests/src/virtual_device/filesystem_device_unprivileged.py b/libvirt/tests/src/virtual_device/filesystem_device_unprivileged.py index 2b466b2b6cc..33ee714ac3a 100644 --- a/libvirt/tests/src/virtual_device/filesystem_device_unprivileged.py +++ b/libvirt/tests/src/virtual_device/filesystem_device_unprivileged.py @@ -24,10 +24,11 @@ from virttest.staging import utils_memory from virttest.libvirt_xml.vm_xml import VMXML from virttest.utils_config import LibvirtQemuConfig +from virttest.utils_libvirt.libvirt_filesystem import check_idmap_xml_filesystem_device from virttest.utils_libvirt.libvirt_unprivileged import get_unprivileged_vm from virttest.utils_libvirt.libvirt_vmxml import create_vm_device_by_type -LOG = logging.getLogger('avocado.' + __name__) +LOG = logging.getLogger("avocado." + __name__) allow_all = stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO unpr_virsh = "" @@ -61,13 +62,15 @@ def get_unprivileged_vms(): "password": _params.get("password"), } - vms = [get_unprivileged_vm(vm_name, test_user, test_passwd, **unpr_vm_args) - for vm_name in vm_names] + vms = [ + get_unprivileged_vm(vm_name, test_user, test_passwd, **unpr_vm_args) + for vm_name in vm_names + ] for vm_name in vm_names: vmxmls[vm_name] = VMXML.new_from_inactive_dumpxml( - vm_name, - virsh_instance=unpr_virsh, + vm_name, + virsh_instance=unpr_virsh, ) backupxmls = [vmxmls[name].copy() for name in vmxmls] @@ -83,8 +86,7 @@ def _initialize_unpr_virsh(): unpr_virsh = virsh.VirshPersistent(uri=unpr_uri, safe=True) host_session = ShellSession("su") - remote.VMManager.set_ssh_auth(host_session, "localhost", - test_user, test_passwd) + remote.VMManager.set_ssh_auth(host_session, "localhost", test_user, test_passwd) host_session.close() @@ -126,12 +128,11 @@ def configure_hugepages_for_unprivileged_user(mem): huge_pages_num = 0 huge_pages_num += mem // host_hp_size + extra_hugepages utils_memory.set_num_huge_pages(huge_pages_num) - process.run(f"mkdir {hugepages_user_path}", - ignore_status=False) - process.run(f"mount -t hugetlbfs hugetlbfs {hugepages_user_path}", - ignore_status=False) - process.run(f"chmod a+wrx {hugepages_user_path}", - ignore_status=False) + process.run(f"mkdir {hugepages_user_path}", ignore_status=False) + process.run( + f"mount -t hugetlbfs hugetlbfs {hugepages_user_path}", ignore_status=False + ) + process.run(f"chmod a+wrx {hugepages_user_path}", ignore_status=False) qemu_config = LibvirtQemuConfig(user_config_path) qemu_config.hugetlbfs_mount = [hugepages_user_path] process.run(f"killall --user {test_user} virtqemud", shell=True) @@ -167,7 +168,7 @@ def add_memory_backing(): if vmxml.max_mem < 1024000: vmxml.max_mem = 1024000 if with_hugepages: - configure_hugepages_for_unprivileged_user(len(vms)*vmxml.max_mem) + configure_hugepages_for_unprivileged_user(len(vms) * vmxml.max_mem) numa_no = None if with_numa: numa_no = vmxml.vcpu // vcpus_per_cell if vmxml.vcpu != 1 else 1 @@ -175,19 +176,19 @@ def add_memory_backing(): vmxml.remove_all_device_by_type("filesystem") VMXML.set_vm_vcpus( - vmxml.vm_name, - vmxml.vcpu, - numa_number=numa_no, - virsh_instance=None, - vmxml=vmxml, + vmxml.vm_name, + vmxml.vcpu, + numa_number=numa_no, + virsh_instance=None, + vmxml=vmxml, ) VMXML.set_memoryBacking_tag( - vmxml.vm_name, - access_mode="shared", - hpgs=with_hugepages, - memfd=with_memfd, - virsh_instance=None, - vmxml=vmxml, + vmxml.vm_name, + access_mode="shared", + hpgs=with_hugepages, + memfd=with_memfd, + virsh_instance=None, + vmxml=vmxml, ) _initialize_unpr_virsh() @@ -220,11 +221,7 @@ def cold_or_hot_plug_filesystem(): fs = create_vm_device_by_type("filesystem", fs_dict) os.chmod(fs.xml, allow_all) unpr_virsh.attach_device( - vm.name, - fs.xml, - flagstr="--current", - debug=True, - ignore_status=False + vm.name, fs.xml, flagstr="--current", debug=True, ignore_status=False ) if not vm.is_alive(): @@ -241,7 +238,7 @@ def check_virtiofs_idmap(): user_info = utils_ids.get_user_ids(test_user) for name in vmxmls: for fs in vmxmls[name].get_devices("filesystem"): - utils_ids.check_idmap_xml_filesystem_device(user_info, fs) + check_idmap_xml_filesystem_device(user_info, fs) def mount_fs(session): @@ -268,7 +265,9 @@ def create_file(session): for fs_dict in fs_dicts: mount_tag = fs_dict["target"]["dir"] mount_dir = f"/mnt/{mount_tag}" - session.cmd_output_safe(f"dd if=/dev/zero of={mount_dir}/testfile bs=1M count=10") + session.cmd_output_safe( + f"dd if=/dev/zero of={mount_dir}/testfile bs=1M count=10" + ) session.cmd_output_safe("sync") @@ -351,11 +350,7 @@ def cold_or_hot_unplug_filesystem(): fs = create_vm_device_by_type("filesystem", fs_dict) os.chmod(fs.xml, allow_all) unpr_virsh.detach_device( - vm.name, - fs.xml, - flagstr="--current", - debug=True, - ignore_status=False + vm.name, fs.xml, flagstr="--current", debug=True, ignore_status=False ) if not vm.is_alive(): From 7ee6b91efec34917caf8937b4db16390f01046b5 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 6 Jun 2024 11:25:50 +0800 Subject: [PATCH 0383/1055] v2v: delete pyvmomi cases due to lack of pkg on RHEL9/10 Signed-off-by: root --- .../cfg/pyvmomi/query_changed_disk_areas.cfg | 18 --- .../src/pyvmomi/query_changed_disk_areas.py | 124 ------------------ 2 files changed, 142 deletions(-) delete mode 100644 v2v/tests/cfg/pyvmomi/query_changed_disk_areas.cfg delete mode 100644 v2v/tests/src/pyvmomi/query_changed_disk_areas.py diff --git a/v2v/tests/cfg/pyvmomi/query_changed_disk_areas.cfg b/v2v/tests/cfg/pyvmomi/query_changed_disk_areas.cfg deleted file mode 100644 index 12faa81bcb7..00000000000 --- a/v2v/tests/cfg/pyvmomi/query_changed_disk_areas.cfg +++ /dev/null @@ -1,18 +0,0 @@ -- query_changed_disk_areas: - type = "query_changed_disk_areas" - vms = '' - only source_esx.esx_70 - only dest_none - - main_vm = VM_NAME_ESX_PYVMOMI_V2V_EXAMPLE - vsphere_host = ${vpx_hostname} - vsphere_user = 'root' - vsphere_pwd = ${vpx_password} - - vm_client = "ssh" - vm_port = 22 - vm_user = 'root' - vm_pwd = GENERAL_GUEST_PASSWORD - vm_prompt = "^\w:\\.*>\s*$|^\[.*\][\#\$]\s*$" - - diff --git a/v2v/tests/src/pyvmomi/query_changed_disk_areas.py b/v2v/tests/src/pyvmomi/query_changed_disk_areas.py deleted file mode 100644 index 746baffe59e..00000000000 --- a/v2v/tests/src/pyvmomi/query_changed_disk_areas.py +++ /dev/null @@ -1,124 +0,0 @@ -import logging - -from virttest.utils_pyvmomi import VSphere, vim -from virttest.remote import wait_for_login -from virttest.utils_misc import wait_for - -LOG = logging.getLogger('avocado.v2v.' + __name__) - - -def run(test, params, env): - """ - Basic pyvmomi test - - 1) create a snapshot - 2) power on the VM, write some fixed length data to - the second disk. - 3) power off the VM, query the changes and compare - the length of changed area. - """ - - def safe_power_off(conn): - """ - Power off safely - - If the VM is poweroff state, the power_off call - will fail, this function checks the state before - power off operation. - """ - power_state = conn.get_vm_summary()['power_state'] - if power_state != 'poweredOff': - conn.power_off() - - vm_name = params.get("main_vm") - if not vm_name: - test.error('No VM specified') - - # vsphere server's host name or IP address - vsphere_host = params.get("vsphere_host") - # vsphere user - vsphere_user = params.get("vsphere_user") - # vsphere password - vsphere_pwd = params.get("vsphere_pwd") - - # vm boots up timeout value, default is 5 mins - vm_bootup_timeout = params.get("vm_bootup_timeout ", 300) - # vm user - vm_user = params.get("vm_user", 'root') - # vm password - vm_pwd = params.get("vm_pwd") - - # vm remote login client arguments setting - vm_client = params.get("vm_client", 'ssh') - vm_port = params.get("vm_port", 22) - vm_prompt = params.get("vm_prompt", r"[\#\$\[\]%]") - - try: - connect_args = { - 'host': vsphere_host, - 'user': vsphere_user, - 'pwd': vsphere_pwd} - conn = VSphere(**connect_args) - conn.target_vm = vm_name - - # Poweroff the guest first if it is Up. - safe_power_off(conn) - # Remove all snapshots first - conn.remove_all_snapshots() - - # Get disk counts of the VM - if len( - conn.get_hardware_devices( - dev_type=vim.vm.device.VirtualDisk)) < 2: - test.error('The main_vm must have at least two disks') - - # Create a snapshot - conn.create_snapshot() - # Poweron the guest - conn.power_on() - # Wait for VM totally boots up to get the IP address - vm_ipaddr = wait_for( - lambda: conn.get_vm_summary()['ip_address'], - vm_bootup_timeout) - if not vm_ipaddr: - test.fail('Get VM IP address failed') - - LOG.info("VM's (%s) IP address is %s", vm_name, vm_ipaddr) - - conn_kwargs = { - 'client': vm_client, - 'host': vm_ipaddr, - 'port': vm_port, - 'username': vm_user, - 'password': vm_pwd, - 'prompt': vm_prompt} - - vm_session = wait_for_login(**conn_kwargs) - - # Write some fixed length of data - cmd = 'dd if=/dev/urandom of=/dev/sdb bs=6000 count=10000 seek=1000' - res = vm_session.cmd_output(cmd) - LOG.debug('Session outputs:\n%s', res) - - # Power off at once - conn.power_off() - - # Query the changed area - disk_change_info = conn.query_changed_disk_areas( - disk_label='Hard disk 2') - if not disk_change_info.changedArea: - test.fail('Not found any changes') - - total = 0 - for change in disk_change_info.changedArea: - total += change.length - - LOG.info('total change length is %s', total) - if not 60000000 <= total <= 61000000: - test.fail('Unexpected change size') - - finally: - safe_power_off(conn) - # Remove all snapshots first - conn.remove_all_snapshots() - conn.close() From fec0f51f535f04a0209cd5ba701dfab472c01952 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Thu, 6 Jun 2024 19:22:11 +0800 Subject: [PATCH 0384/1055] virsh_emulatorpin: Fix ValueError: invalid mode: 'rU' Signed-off-by: Yingshun Cui --- libvirt/tests/src/virsh_cmd/domain/virsh_emulatorpin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_emulatorpin.py b/libvirt/tests/src/virsh_cmd/domain/virsh_emulatorpin.py index ecd49025fa9..47cdfa3beae 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_emulatorpin.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_emulatorpin.py @@ -38,7 +38,7 @@ def get_emulatorpin_from_cgroup(params, test): cpuset_file = os.path.join(cpuset_path, "cpuset.cpus") try: - with open(cpuset_file, "rU") as f_emulatorpin_params: + with open(cpuset_file, "r") as f_emulatorpin_params: emulatorpin_params_from_cgroup = f_emulatorpin_params.readline() return emulatorpin_params_from_cgroup except IOError: From 81c322d321b1ecaa9d75b28d9f186f964cc5a3cf Mon Sep 17 00:00:00 2001 From: Meina Li Date: Fri, 7 Jun 2024 02:28:43 -0400 Subject: [PATCH 0385/1055] virtual_disk: add new cases for starting guest with multiple driver attributes These two cases are to match the cnv scenarios: VIRT-300872 and VIRT-300727. Signed-off-by: Meina Li --- .../virtual_disks_multiattributes.cfg | 17 +++ .../virtual_disks_multiattributes.py | 122 ++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_disks/virtual_disks_multiattributes.cfg create mode 100644 libvirt/tests/src/virtual_disks/virtual_disks_multiattributes.py diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_multiattributes.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_multiattributes.cfg new file mode 100644 index 00000000000..9e3728e4236 --- /dev/null +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_multiattributes.cfg @@ -0,0 +1,17 @@ +- virtual_disks.multiattributes: + type = virtual_disks_multiattributes + start_vm = no + disk_target_dev = "vda" + dom_iothreads = "1" + driver_attributes = {'name': 'qemu', 'type': 'raw', 'cache': 'none', 'error_policy': 'stop',} + variants: + - start_guest: + variants: + - file_disk: + disk_type = "file" + another_disk_dev = "vdb" + disk1_dict = {'type_name': '${disk_type}', 'model': 'virtio-non-transitional', 'driver': {**${driver_attributes}, 'discard': 'unmap'}, 'device': 'disk', 'target': {'dev': '${disk_target_dev}', 'bus': 'virtio'}} + disk2_dict = {'type_name': '${disk_type}', 'model': 'virtio-non-transitional', 'driver': {**${driver_attributes}, 'discard': 'unmap'}, 'device': 'disk', 'target': {'dev': '${another_disk_dev}', 'bus': 'virtio'}} + - block_disk: + disk_type = "block" + disk_dict = {'type_name': '${disk_type}', 'model': 'virtio-non-transitional', 'driver': {**${driver_attributes}, 'io': 'native'}, 'device': 'disk', 'boot': '1', 'target': {'dev': '${disk_target_dev}', 'bus': 'virtio'}} diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_multiattributes.py b/libvirt/tests/src/virtual_disks/virtual_disks_multiattributes.py new file mode 100644 index 00000000000..56d0dccbd5b --- /dev/null +++ b/libvirt/tests/src/virtual_disks/virtual_disks_multiattributes.py @@ -0,0 +1,122 @@ +# Copyright Red Hat +# SPDX-License-Identifier: GPL-2.0 +# Author: Meina Li + +import os + +from avocado.utils import process + +from virttest import data_dir +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.devices import disk +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.virtual_disk import disk_base + + +def update_bootable_disk(vm, vmxml, disk_obj, params): + """ + Prepare a guest with multiple disk attributes. + + :params vm: vm instance + :params vmxml: the vm xml + :params disk_obj: the disk objective + :params return: return the image list to delete after test + """ + disk_type = params.get("disk_type") + disk_dict = eval(params.get("disk_dict", "{}")) + disk1_dict = eval(params.get("disk1_dict", "{}")) + disk_target_dev = params.get("disk_target_dev") + dom_iothreads = params.get("dom_iothreads") + bootable_image = disk_obj.get_source_list(vmxml, disk_type, disk_target_dev)[0] + libvirt_vmxml.remove_vm_devices_by_type(vm, "disk") + vmxml = vm_xml.VMXML.new_from_dumpxml(vm.name) + vmxml.iothreads = int(dom_iothreads) + vmxml.sync() + if disk_type == "file": + cmd1 = "echo %s | sed s/qcow2/raw/g" % bootable_image + bootable_raw_image = process.run(cmd1, ignore_status=False, shell=True).stdout_text.strip() + cmd2 = "qemu-img convert -f qcow2 %s -O raw %s" % (bootable_image, bootable_raw_image) + process.run(cmd2, ignore_status=False, shell=True) + disk1_dict.update({'source': {'attrs': {'file': bootable_raw_image}}}) + disk_obj.add_vm_disk(disk_type, disk1_dict, bootable_raw_image) + image_list.append(bootable_raw_image) + if disk_type == "block": + device = libvirt.setup_or_cleanup_iscsi(is_setup=True, + image_size='10G') + cmd = "qemu-img convert -f qcow2 %s -O raw %s; sync" % (bootable_image, device) + process.run(cmd, ignore_status=False, shell=True) + disk_dict.update({'source': {'attrs': {'dev': device}}}) + disk_add = disk.Disk(disk_dict) + disk_add.setup_attrs(**disk_dict) + vmxml.remove_all_boots() + vmxml.add_device(disk_add) + vmxml.sync() + return image_list + + +def add_second_disk(image_list, disk_obj, params): + """ + Prepare a guest with multiple disk attributes. + + :params disk_obj: the disk objective + :params image_list: get the image of bootable disk + :params return: return the image list to delete after test + """ + disk_type = params.get("disk_type") + disk2_dict = eval(params.get("disk2_dict", "{}")) + if disk_type == "file": + new_image_path = data_dir.get_data_dir() + '/test.img' + libvirt.create_local_disk("file", path=new_image_path, size="500M", disk_format="raw") + disk_obj.add_vm_disk(disk_type, disk2_dict, new_image_path) + image_list.append(new_image_path) + return image_list + + +def run(test, params, env): + """ + This case is to verify starting a guest with file/block disk which has multiple driver attributes. + 1) Prepare a guest with multiple disk attributes. + 2) Start the guest. + 3) Login the guest and read/write disk. + """ + vm_name = params.get("main_vm") + disk_type = params.get("disk_type") + disk_dev = params.get("another_disk_dev") + + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) + bkxml = vmxml.copy() + disk_obj = disk_base.DiskBase(test, vm, params) + global image_list + image_list = [] + + try: + test.log.info("STEP1: prepare a guest with multiple disk attributes.") + image_list = update_bootable_disk(vm, vmxml, disk_obj, params) + image_list = add_second_disk(image_list, disk_obj, params) + test.log.info("STEP2: start the guest.") + test.log.debug("The current guest xml is: %s" % virsh.dumpxml(vm_name).stdout_text.strip()) + if not vm.is_alive(): + vm.start() + test.log.info("STEP3: login the guest and read/write.") + session = vm.wait_for_login() + if disk_type == "file": + session.cmd("mkfs.ext4 /dev/%s && mount /dev/%s /mnt" % (disk_dev, disk_dev)) + status, output = session.cmd_status_output("dd if=/dev/zero of=/mnt/file bs=1M count=100") + if status: + test.error("Failed to read/write in guest: %s" % output) + else: + test.log.debug("Read/write in guest successfully") + session.close + + finally: + bkxml.sync() + if disk_type == "block": + libvirt.setup_or_cleanup_iscsi(is_setup=False) + if image_list: + for image in image_list: + if os.path.exists(image): + os.remove(image) From f96ce25634203ce30bdca0bc8abac232c2101c60 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Fri, 7 Jun 2024 05:24:12 -0400 Subject: [PATCH 0386/1055] virsh_reboot: disable acpi test on s390x No ACPI on s390x. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/virsh_cmd/domain/virsh_reboot.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_reboot.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_reboot.cfg index 15449abafb5..58ada50b7da 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_reboot.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_reboot.cfg @@ -15,7 +15,7 @@ - no_mode: - acpi_mode: reboot_mode = "acpi" - no ppc64,ppc64le + no ppc64,ppc64le,s390-virtio - agent_mode: no lxc reboot_mode = "agent" From 8a1d6f45c133cf0797cce24d80b0da2fa4d1b2db Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 10 Jun 2024 06:36:18 -0400 Subject: [PATCH 0387/1055] migrate_over_unix: fix disk selection The code used the target name to identify disks inside of the VM with their impersistent names (vda, vdb, ...). However, they might change between boots. Instead use a function to identify new disks as not containing the system root partition. Signed-off-by: Sebastian Mitterle --- .../tests/src/migration/migrate_over_unix.py | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/libvirt/tests/src/migration/migrate_over_unix.py b/libvirt/tests/src/migration/migrate_over_unix.py index ec7cf55a23f..1d35cf84910 100644 --- a/libvirt/tests/src/migration/migrate_over_unix.py +++ b/libvirt/tests/src/migration/migrate_over_unix.py @@ -46,6 +46,15 @@ def run(test, params, env): :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ + def get_vm_did_list(session): + """ + Get the list of newly attached disks + + :param session: guest console session + """ + info = libvirt_disk.get_non_root_disk_names(session, ignore_status=True) + return [x[0] for x in info] + def update_disk(vm, params): """ Update disk for testing. @@ -56,7 +65,6 @@ def update_disk(vm, params): """ local_image_list = [] remote_image_list = [] - vm_did_list = [] # Change the disk of the vm if storage_type == "nfs": libvirt.set_vm_disk(vm, params) @@ -103,10 +111,9 @@ def update_disk(vm, params): session=remote_session) remote_image_list.append(disk_path) - vm_did_list.append(target_dev) remote_session.close() - return local_image_list, remote_image_list, vm_did_list + return local_image_list, remote_image_list def check_socket(params): """ @@ -166,7 +173,6 @@ def _check_socket(): mig_result = None local_image_list = [] remote_image_list = [] - vm_did_list = [] if not libvirt_version.version_compare(6, 6, 0): test.cancel("This libvirt version doesn't support " @@ -214,7 +220,7 @@ def _check_socket(): unix_obj.conn_setup() unix_obj.auto_recover = True - local_image_list, remote_image_list, vm_did_list = update_disk(vm, params) + local_image_list, remote_image_list = update_disk(vm, params) if not vm.is_alive(): vm.start() @@ -224,6 +230,7 @@ def _check_socket(): vm_session = vm.wait_for_login() + vm_did_list = get_vm_did_list(vm_session) for did in vm_did_list: utils_disk.linux_disk_check(vm_session, did) @@ -265,13 +272,13 @@ def _check_socket(): lambda: virsh.is_alive(vm_name, uri=dest_uri_ssh, debug=True), 60): test.fail("The migrated VM should be alive!") - if vm_did_list: - if vm.serial_console is None: - vm.create_serial_console() - vm_session_after_mig = vm.wait_for_serial_login(timeout=240) - for did in vm_did_list: - vm_session_after_mig.cmd( - "echo mytest >> /mnt/%s1/mytest" % did) + if vm.serial_console is None: + vm.create_serial_console() + vm_session_after_mig = vm.wait_for_serial_login(timeout=240) + vm_did_list = get_vm_did_list(vm_session_after_mig) + for did in vm_did_list: + vm_session_after_mig.cmd( + "echo mytest >> /mnt/%s1/mytest" % did) finally: logging.info("Recover test environment") vm.connect_uri = bk_uri From 15c5afc786aebca81be3eb422809a88790121a32 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 10 Jun 2024 08:46:19 -0400 Subject: [PATCH 0388/1055] revert_snap_with_flags: skip secure boot check On s390x, we don't have the vars file for secure boot. Don't check it. Also, no nvram, so don't run that flag. Signed-off-by: Sebastian Mitterle --- .../tests/cfg/snapshot/revert_snap_with_flags.cfg | 5 +++-- libvirt/tests/src/snapshot/revert_snap_with_flags.py | 12 +++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/cfg/snapshot/revert_snap_with_flags.cfg b/libvirt/tests/cfg/snapshot/revert_snap_with_flags.cfg index 1c2a377b5ae..3ca0439c02d 100644 --- a/libvirt/tests/cfg/snapshot/revert_snap_with_flags.cfg +++ b/libvirt/tests/cfg/snapshot/revert_snap_with_flags.cfg @@ -7,6 +7,7 @@ vars_path = "/var/lib/libvirt/qemu/nvram/${main_vm}_VARS.fd" snap1_options = "%s --diskspec vda,snapshot=external,file=/tmp/vda.%s" snap2_options = "%s --memspec snapshot=external,file=/tmp/mem.%s --diskspec vda,snapshot=external,file=/tmp/vda.%s" - flags = [" --current --paused"," --running --reset-nvram", " --force"] func_supported_since_libvirt_ver = (9, 10, 0) - + s390-virtio: + vars_path = + flags = [" --current --paused"," --running", " --force"] diff --git a/libvirt/tests/src/snapshot/revert_snap_with_flags.py b/libvirt/tests/src/snapshot/revert_snap_with_flags.py index f4569163076..17b46812a09 100644 --- a/libvirt/tests/src/snapshot/revert_snap_with_flags.py +++ b/libvirt/tests/src/snapshot/revert_snap_with_flags.py @@ -59,13 +59,15 @@ def run_test(): check_vm_state_in_dom_list(test, vm_name, vm_state="paused") test.log.info("TEST_STEP4: Revert snapshot to the first snap") - vars_hash1 = process.run("sha256sum %s" % vars_path, ignore_status=False) + if vars_path: + vars_hash1 = process.run("sha256sum %s" % vars_path, ignore_status=False) virsh.snapshot_revert(vm_name, snap_names[0], options=revert_flags[1], **virsh_dargs) - vars_hash2 = process.run("sha256sum %s" % vars_path, ignore_status=False) - if vars_hash1 == vars_hash2: - test.fail("Expect to get different hash values for '%s', " - "but got both '%s' " % (vars_path, vars_hash1)) + if vars_path: + vars_hash2 = process.run("sha256sum %s" % vars_path, ignore_status=False) + if vars_hash1 == vars_hash2: + test.fail("Expect to get different hash values for '%s', " + "but got both '%s' " % (vars_path, vars_hash1)) test.log.info("TEST_STEP5: Revert snapshot to the second snap force") virsh.snapshot_revert(vm_name, snap_names[1], From a91badf10f84efd0fade1c0da9aacc82eca918be Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 10 Jun 2024 09:03:34 -0400 Subject: [PATCH 0389/1055] snapshot_with_genid: not supported on s390x is not supported on s390x. (s390x has no ACPI and is Big-Endian, no BIOS, no UEFI.) Disable the test. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/snapshot/revert_snap_for_guest_with_genid.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/cfg/snapshot/revert_snap_for_guest_with_genid.cfg b/libvirt/tests/cfg/snapshot/revert_snap_for_guest_with_genid.cfg index ceb14a6ceaf..11e22677b49 100644 --- a/libvirt/tests/cfg/snapshot/revert_snap_for_guest_with_genid.cfg +++ b/libvirt/tests/cfg/snapshot/revert_snap_for_guest_with_genid.cfg @@ -1,4 +1,5 @@ - snapshot_revert.with_genid: + no s390-virtio type = revert_snap_for_guest_with_genid start_vm = no func_supported_since_libvirt_ver = (9, 10, 0) From 1690ea61d944b7b4856abf26100e878875e7ffb6 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 10 Jun 2024 09:18:20 -0400 Subject: [PATCH 0390/1055] managedsave_cpu_mode: fix for s390x On s390x, there are no threads, the value must be 1. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave.cfg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave.cfg index ef10d641fc9..7c763143498 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave.cfg @@ -51,6 +51,9 @@ cpu_topology_cores = "4" cpu_topology_threads = "2" vcpu_nums = "16" + s390-virtio: + cpu_topology_threads = "1" + vcpu_nums = "8" - undefine: managedsave_undefine = "yes" - bypass_cache: From 2fde3cdffd9def25e2acf7553129e878f8809767 Mon Sep 17 00:00:00 2001 From: nanli Date: Tue, 11 Jun 2024 11:37:01 +0800 Subject: [PATCH 0391/1055] fix not found vmx need to get vmxml again to get vmx Signed-off-by: nanli --- libvirt/tests/src/cpu/vcpu_nested.py | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/src/cpu/vcpu_nested.py b/libvirt/tests/src/cpu/vcpu_nested.py index 6c732d59956..caa416ca8ce 100644 --- a/libvirt/tests/src/cpu/vcpu_nested.py +++ b/libvirt/tests/src/cpu/vcpu_nested.py @@ -109,6 +109,7 @@ def test_check_nested_capability(): Check whether the feature nested virt is enabled """ vm.wait_for_login() + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) cpu_feature = vmxml.cpu.get_dict_type_feature() if cpu_feature['vmx'] != 'require': test.fail("The feature policy of 'vmx' should not be %s, but require." % cpu_feature['vmx']) From c1628a728b50f10bf51f5b647108a0ec0ff79f4b Mon Sep 17 00:00:00 2001 From: nanli Date: Mon, 13 May 2024 15:43:25 +0800 Subject: [PATCH 0392/1055] add case for revert disk external snapshot xxxx-16604: Revert guest to disk external snapshot Signed-off-by: nanli --- .../snapshot/revert_disk_external_snap.cfg | 11 ++ .../src/snapshot/revert_disk_external_snap.py | 108 ++++++++++++++++++ provider/snapshot/snapshot_base.py | 12 ++ 3 files changed, 131 insertions(+) create mode 100644 libvirt/tests/cfg/snapshot/revert_disk_external_snap.cfg create mode 100644 libvirt/tests/src/snapshot/revert_disk_external_snap.py diff --git a/libvirt/tests/cfg/snapshot/revert_disk_external_snap.cfg b/libvirt/tests/cfg/snapshot/revert_disk_external_snap.cfg new file mode 100644 index 00000000000..7bc00edbf1f --- /dev/null +++ b/libvirt/tests/cfg/snapshot/revert_disk_external_snap.cfg @@ -0,0 +1,11 @@ +- snapshot_revert.disk_external_snap: + type = revert_disk_external_snap + start_vm = no + snap_names = ['s1', 's2', 's3'] + file_list = ["/mnt/s1", "/mnt/s2", "/mnt/s3"] + func_supported_since_libvirt_ver = (9, 10, 0) + variants snap_type: + - disk_only: + snap_options = " %s --disk-only %s" + - disk_and_memory: + snap_options = "%s --memspec snapshot=external,file=/tmp/mem.%s" diff --git a/libvirt/tests/src/snapshot/revert_disk_external_snap.py b/libvirt/tests/src/snapshot/revert_disk_external_snap.py new file mode 100644 index 00000000000..8cf81c86419 --- /dev/null +++ b/libvirt/tests/src/snapshot/revert_disk_external_snap.py @@ -0,0 +1,108 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from virttest import libvirt_version +from virttest import virsh +from virttest.libvirt_xml import vm_xml + +from provider.snapshot import snapshot_base + +virsh_dargs = {"debug": True, "ignore_status": False} + + +def revert_snap_and_check_files(params, vm, test, snap_name, expected_files): + """ + Revert the snapshot name and check expected file. + + :param params: dict wrapped with params. + :param vm: vm object. + :param test: test object. + :param snap_name: snapshot name. + :param expected_files: expected file list. + """ + virsh.snapshot_revert(vm.name, snap_name, **virsh_dargs) + + session = vm.wait_for_login() + for file in expected_files: + output = session.cmd('ls %s' % file) + if file not in output: + test.fail("File %s not exist in %s" % (file, output)) + params.get("test_obj").check_current_snapshot(snap_name) + + test.log.debug("File %s exist in guest" % expected_files) + session.close() + + +def run(test, params, env): + """ + Revert guest to a disk external snapshot. + """ + def setup_test(): + """ + Prepare file and snapshot. + """ + test.log.info("TEST_SETUP: Create files and snaps in running guest.") + virsh.start(vm_name) + session = vm.wait_for_login() + mem_file = " " + for index, sname in enumerate(snap_names): + session.cmd("touch %s" % file_list[index]) + if snap_type == "disk_and_memory": + mem_file = sname + virsh.snapshot_create_as(vm.name, snap_options % (sname, mem_file), + **virsh_dargs) + test_obj.check_snap_list(sname) + + session.close() + + def run_test(): + """ + Revert guest and check file list. + """ + test.log.info("TEST_STEP1:Revert the 2nd snapshot and check files.") + revert_snap_and_check_files(params, vm, test, snap_names[1], + file_list[:2]) + + test.log.info("TEST_STEP2:Revert the first snapshot and check files.") + revert_snap_and_check_files(params, vm, test, snap_names[0], + [file_list[0]]) + + test.log.info("TEST_STEP3:Revert the last snap and check source files") + revert_snap_and_check_files(params, vm, test, snap_names[-1], + file_list) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + snap_names.reverse() + test_obj.teardown_test() + + vm_name = params.get("main_vm") + original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + params['backup_vmxml'] = original_xml.copy() + vm = env.get_vm(vm_name) + + snap_names = eval(params.get("snap_names", '[]')) + snap_type = params.get("snap_type") + snap_options = params.get("snap_options") + file_list = eval(params.get("file_list")) + test_obj = snapshot_base.SnapshotTest(vm, test, params) + params.update({"test_obj": test_obj}) + + libvirt_version.is_libvirt_feature_supported(params) + + try: + setup_test() + run_test() + + finally: + teardown_test() diff --git a/provider/snapshot/snapshot_base.py b/provider/snapshot/snapshot_base.py index 8f0af052cfc..bf124a754a4 100644 --- a/provider/snapshot/snapshot_base.py +++ b/provider/snapshot/snapshot_base.py @@ -62,6 +62,18 @@ def create_snapshot_by_xml(self, snap_dict, snap_disk_list, options=''): virsh.snapshot_create(self.vm.name, snap_options, **self.virsh_dargs) virsh.snapshot_dumpxml(self.vm.name, snap_dict['snap_name'], **self.virsh_dargs) + def check_current_snapshot(self, snap_name): + """ + Check vm current snapshot name is expected + + :param snap_name, expected snapshot name. + """ + current_name = virsh.snapshot_current( + self.vm.name, **self.virsh_dargs).stdout.strip() + if current_name != snap_name: + self.test.fail("Current snapshot name is %s, should be %s" % ( + current_name, snap_name)) + def delete_snapshot(self, snap_names, options=''): """ Delete snapshots of the vm From cba7493befc6f35b08c37883788936466ff53355 Mon Sep 17 00:00:00 2001 From: nanli Date: Fri, 31 May 2024 17:59:01 +0800 Subject: [PATCH 0393/1055] add case for virtio memory hotplug xxxx-300399: Virtio-mem memory device hot-plug Signed-off-by: nanli --- .../memory_devices/virtio_mem_hotplug.cfg | 71 ++++ .../memory_devices/virtio_mem_hotplug.py | 376 ++++++++++++++++++ 2 files changed, 447 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_devices/virtio_mem_hotplug.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/virtio_mem_hotplug.py diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hotplug.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hotplug.cfg new file mode 100644 index 00000000000..adbde97b91f --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hotplug.cfg @@ -0,0 +1,71 @@ +- memory.devices.virtio_mem.hotplug: + no s390-virtio + type = virtio_mem_hotplug + start_vm = no + mem_model = "virtio-mem" + allocate_size = "1048576" + allocate_memory = "${allocate_size}KiB" + target_size = "1048576" + request_size = "1048576" + size_unit = 'KiB' + block_unit = 'KiB' + request_unit = 'KiB' + plug_size_unit = 'KiB' + plug_block_unit = 'KiB' + plug_request_unit = 'KiB' + node = 0 + plug_node = 0 + slot = 0 + base = "0x100000000" + mem_value = 2097152 + current_mem = 2097152 + numa_mem = 1048576 + max_mem = 4194304 + max_mem_slots = 16 + plug_event = "device-added" + audit_cmd = "ausearch --start today -m VIRT_RESOURCE | grep 'mem'" + ausearch_check = 'old-mem=%d new-mem=%d' + expected_log = "device_add" + kernel_hp_file = '/sys/devices/system/node/node0/hugepages/hugepages-%skB/nr_hugepages' + max_dict = '"max_mem_rt": ${max_mem}, "max_mem_rt_slots": ${max_mem_slots}, "max_mem_rt_unit": "KiB"' + numa_dict = "'vcpu': 4,'cpu':{'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_mem}'}]}" + vm_attrs = {${numa_dict},${max_dict},'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'} + required_kernel = [5.14.0,) + guest_required_kernel = [5.8.0,) + func_supported_since_libvirt_ver = (8, 0, 0) + func_supported_since_qemu_kvm_ver = (6, 2, 0) + variants case: + - target_and_address: + plug_target_size = '524288' + plug_request_size = '524288' + addr_dict = {'attrs': {'base':'${base}'}} + plug_base = "0x140000000" + plug_addr_dict = {'attrs': {'base':'${plug_base}'}} + - source_mib_and_hugepages: + target_size = "512" + request_size = "512" + size_unit = 'MiB' + request_unit = "MiB" + node = 1 + plug_target_size = "1024" + plug_request_size = "1024" + plug_size_unit = "MiB" + plug_request_unit = "MiB" + plug_node = 1 + source_dict = {'nodemask': '0','pagesize': %d, 'pagesize_unit':'KiB'} + - plug_exceeded_max_mem: + node = 1 + plug_node = 1 + plug_target_size = "2097152" + plug_request_size = "1048576" + plug_error = "exceed domain's maxMemory config size '${max_mem}'" + - duplicate_addr: + target_size = '524288' + request_size = '524288' + addr_dict = {'attrs': {'base':'${base}'}} + plug_error = "address range conflicts|overlaps" + plug_target_size = ${target_size} + plug_request_size = ${request_size} + plug_addr_dict = ${addr_dict} + virtio_dict = {'mem_model':'${mem_model}','target': {'size':${target_size}, 'size_unit':'${size_unit}', 'node':${node},'requested_size': ${request_size},'requested_unit':'${request_unit}', 'block_size': %s, 'block_unit':'${block_unit}'}} + plug_dict = {'mem_model':'${mem_model}','target': {'size':${plug_target_size},'requested_size': ${plug_request_size}, 'block_size': %s, 'size_unit':'${plug_size_unit}','requested_unit':'${plug_request_unit}','block_unit':'${plug_block_unit}','node':${plug_node}}} diff --git a/libvirt/tests/src/memory/memory_devices/virtio_mem_hotplug.py b/libvirt/tests/src/memory/memory_devices/virtio_mem_hotplug.py new file mode 100644 index 00000000000..77891771d81 --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/virtio_mem_hotplug.py @@ -0,0 +1,376 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import os + +from avocado.utils import process +from avocado.utils import memory + +from virttest import utils_misc +from virttest.libvirt_xml import vm_xml +from virttest.staging import utils_memory +from virttest.utils_test import libvirt + +from provider.memory import memory_base + +virsh_dargs = {"ignore_status": False, "debug": True} + + +def adjust_virtio_dict(params): + """ + Adjust virtio memory dict and plugging dict. + + :param params: dictionary with the test parameters. + """ + + default_page_size = utils_memory.getpagesize() + default_hugepage_size = memory.get_huge_page_size() + + case = params.get("case") + source_dict = params.get("source_dict", "") + addr_dict = params.get("addr_dict", "") + plug_addr_dict = params.get("plug_addr_dict", "") + virtio_dict = eval(params.get("virtio_dict", "{}") % default_hugepage_size) + plug_dict = eval(params.get("plug_dict") % default_hugepage_size) + + if source_dict: + if case == "source_mib_and_hugepages": + virtio_dict['source'] = eval(source_dict % default_page_size) + else: + virtio_dict['source'] = eval(source_dict % default_hugepage_size) + plug_dict['source'] = eval(source_dict % default_hugepage_size) + if addr_dict: + target = virtio_dict["target"] + target['address'] = eval(addr_dict) + + plug_target = plug_dict['target'] + plug_target['address'] = eval(plug_addr_dict) + + return virtio_dict, plug_dict + + +def adjust_virtio_size(params): + """ + Adjust all virtio related size to KiB. + + :param params: dict wrapped with params. + """ + plug_target_size = int(params.get('plug_target_size', 0)) + plug_request_size = int(params.get('plug_request_size', 0)) + target_size, request_size = int(params.get('target_size')), int( + params.get('request_size')) + plug_size_unit = params.get('plug_size_unit') + plug_request_unit = params.get('plug_request_unit') + size_unit, request_unit = params.get('size_unit'), params.get( + 'request_unit') + + def _convert_size(curr_size, curr_unit): + if curr_unit != "KiB": + new_size = memory_base.convert_data_size(str(curr_size) + curr_unit) + return int(new_size) + else: + return int(curr_size) + + target_size = _convert_size(target_size, size_unit) + request_size = _convert_size(request_size, request_unit) + plug_target_size = _convert_size(plug_target_size, plug_size_unit) + plug_request_size = _convert_size(plug_request_size, plug_request_unit) + + return target_size, request_size, plug_target_size, plug_request_size + + +def compare_two_values(test, expected, actual, item_name=''): + """ + Compare two value should be equal + + :param test: test object + :param expected, expected value + :param actual, actual value + :param item_name,checking item name, such as memory value, current memory + """ + if actual != expected: + test.fail( + "Expect %s is %s , but got %s" % (item_name, expected, actual)) + else: + test.log.debug("Checked the %s successfully", item_name) + + +def check_source_and_addr_xml(test, params, virtio_mem_xml, mem_index=0): + """ + Check virtio memory source and address xml if existed. + + :param test: test object + :param params: dictionary with the test parameters + :param virtio_mem_xml, virtio memory xml + :param mem_index, Check after or before attaching memory device. + """ + addr_dict = params.get("addr_dict", "") + source_dict = params.get("source_dict", "") + expected_base = params.get("plug_base") if mem_index == 1 \ + else params.get("base") + expected_source_pgsize = memory.get_huge_page_size() if mem_index == 1 \ + else utils_memory.getpagesize() + + if source_dict: + if virtio_mem_xml.source.pagesize != expected_source_pgsize: + test.fail("Got virtio memory source pagesize %s, should be %s" % ( + virtio_mem_xml.source.pagesize, expected_source_pgsize)) + if addr_dict: + actual_base = virtio_mem_xml.target.address.attrs.get("base") + if actual_base != expected_base: + test.fail("Got virtio memory address base %s, should be %s" % ( + actual_base, expected_base)) + + +def check_delayed_current(test, params, mem_index, expected_current_size): + """ + Check the virtio memory current value. + + :param test: test object. + :param params: dictionary with the test parameters. + :param expected_current_size, expected current size value. + :param mem_index, Check after or before attaching memory device. + """ + vm_name = params.get("main_vm") + + def _get_virtio_current(): + return vm_xml.VMXML.new_from_dumpxml( + vm_name).devices.by_device_tag("memory")[ + mem_index].target.current_size + + if not utils_misc.wait_for( + lambda: expected_current_size == _get_virtio_current(), 20): + test.fail( + "Attached virtio memory current size should be %s" % expected_current_size) + test.log.debug("Checked attached virtio memory current size successfully") + + params.update({"second_virtio_curr": _get_virtio_current()}) + params.update({"acutal_curr": vm_xml.VMXML.new_from_dumpxml(vm_name).current_mem}) + + +def check_guest_xml(test, params, mem_index=0): + """ + Check guest xml. + + :param test: test object. + :param params: dictionary with the test parameters. + :param mem_index, the memory order in the guest, set 1 when checking the + plugged virtio memory. + """ + vm_name = params.get("main_vm") + mem_value = int(params.get("mem_value")) + current_mem = int(params.get("current_mem")) + + target_size, request_size, plug_target_size, plug_request_size = \ + adjust_virtio_size(params) + default_hugepage_size = memory.get_huge_page_size() + + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + virtio_mem_xml = vmxml.devices.by_device_tag("memory")[mem_index] + acutal_mem = vmxml.memory + acutal_curr = vmxml.current_mem + acutal_virtio_target = virtio_mem_xml.target.size + acutal_virtio_block = virtio_mem_xml.target.block_size + acutal_virtio_requested = virtio_mem_xml.target.requested_size + acutal_virtio_current = virtio_mem_xml.target.current_size + + check_source_and_addr_xml(test, params, virtio_mem_xml, mem_index) + if mem_index == 0: + params.update({"first_virtio_curr": acutal_virtio_current}) + params.update({"expected_mem0": mem_value + target_size}) + params.update({"expected_curr0": current_mem + acutal_virtio_current}) + + compare_two_values( + test, params.get("expected_mem0"), acutal_mem, 'memory') + compare_two_values( + test, params.get("expected_curr0"), acutal_curr, 'current memory') + compare_two_values( + test, target_size, acutal_virtio_target, 'virtio memory target size') + compare_two_values( + test, default_hugepage_size, acutal_virtio_block, 'virtio memory block size') + compare_two_values( + test, request_size, acutal_virtio_requested, 'virtio memory requested size') + compare_two_values( + test, acutal_virtio_current, request_size, 'virtio memory current size') + + elif mem_index == 1: + compare_two_values( + test, plug_target_size, acutal_virtio_target, + 'Attached virtio memory target size') + compare_two_values( + test, default_hugepage_size, acutal_virtio_block, + 'Attached virtio memory block size') + compare_two_values( + test, plug_request_size, acutal_virtio_requested, + 'Attached virtio memory requested size') + + check_delayed_current(test, params, mem_index, plug_request_size) + + curr1, curr2 = params.get("first_virtio_curr"), params.get("second_virtio_curr") + params.update( + {"expected_mem1": mem_value + target_size + plug_target_size}) + params.update({"expected_curr1": current_mem + curr1 + curr2}) + compare_two_values( + test, params.get("expected_mem1"), acutal_mem, 'memory') + compare_two_values( + test, params.get("expected_curr1"), params.get("acutal_curr"), + 'current memory') + + +def check_guest_virsh_dominfo(vm, test, params, hot_plugged=False): + """ + Check memory value and current memory value in virsh dominfo result. + + :param vm: vm object. + :param test: test object. + :param params: dictionary with the test parameters. + :param hot_plugged: boolean, the flag of hotplugging. + """ + if hot_plugged: + expected_mem = params.get("expected_mem1") + expected_curr = params.get("expected_curr1") + else: + expected_mem = params.get("expected_mem0") + expected_curr = params.get("expected_curr0") + + memory_base.check_dominfo(vm, test, str(expected_mem), str(expected_curr)) + + +def check_after_attach(vm, test, params): + """ + Check the below points after plugging. + + 1. Check the audit log by ausearch. + 2. Check the libvirtd log. + 3. Check the memory allocation and memory device config. + 4. Check the memory info by virsh dominfo. + 5. Check the guest memory. + :param vm: vm object. + :param test: test object. + :param params: dictionary with the test parameters. + :param operation: string, the flag for attaching or detaching. + """ + mem_value = int(params.get("mem_value")) + expected_log = params.get("expected_log") + audit_cmd = params.get("audit_cmd") + target_size, request_size, plug_target_size, plug_request_size = \ + adjust_virtio_size(params) + + libvirtd_log_file = os.path.join(test.debugdir, "libvirtd.log") + ausearch_check = params.get("ausearch_check") % ( + mem_value + target_size, mem_value + target_size + plug_target_size) + + # Check the audit log by ausearch. + ausearch_result = process.run(audit_cmd, shell=True) + libvirt.check_result(ausearch_result, expected_match=ausearch_check) + test.log.debug("Check audit log %s successfully." % ausearch_check) + + # Check the libvirtd log. + result = utils_misc.wait_for( + lambda: libvirt.check_logfile(expected_log, libvirtd_log_file), timeout=20) + if not result: + test.fail("Can't get expected log %s in %s" % ( + expected_log, libvirtd_log_file)) + + # Check the memory allocation and memory device config. + check_guest_xml(test, params, mem_index=1) + + # Check the memory info by virsh dominfo. + check_guest_virsh_dominfo(vm, test, params, hot_plugged=True) + + # Check the guest memory. + session = vm.wait_for_login() + new_memtotal = utils_memory.memtotal(session) + session.close() + expected_memtotal = params.get('old_memtotal') + params.get("second_virtio_curr") + if new_memtotal != expected_memtotal: + test.fail("Memtotal is %s, should be %s " % (new_memtotal, expected_memtotal)) + test.log.debug("Check guest mem total successfully.") + + +def run(test, params, env): + """ + Verify virtio-mem memory device hot-plug with different configs. + """ + + def setup_test(): + """ + Allocate memory on the host. + """ + process.run( + "echo %d > %s" % (allocate_size / default_hugepage_size, + kernel_hp_file % default_hugepage_size), + shell=True) + + def run_test(): + """ + 1. Define vm with virtio memory device. + 2. Hot plug another virtio memory. + 3. Check audit log, libvirtd log, memory allocation and memory device + config. + """ + test.log.info("TEST_STEP1: Define vm with virtio memory") + memory_base.define_guest_with_memory_device(params, virtio_dict, + vm_attrs) + + test.log.info("TEST_STEP2: Start guest") + vm.start() + session = vm.wait_for_login() + + test.log.info("TEST_STEP3: Get the guest memory") + params.update({'old_memtotal': utils_memory.memtotal(session)}) + session.close() + + test.log.info("TEST_STEP4: Check guest xml") + check_guest_xml(test, params) + + test.log.info("TEST_STEP5: Check the memory info by virsh dominfo") + check_guest_virsh_dominfo(vm, test, params) + + test.log.info("TEST_STEP6: Hot plug one virtio memory device") + memory_base.plug_memory_and_check_result( + test, params, mem_dict=plug_dict, operation='attach', + expected_error=plug_error, expected_event=plug_event) + + if case in ["target_and_address", "source_mib_and_hugepages"]: + test.log.info("TEST_STEP7: Check audit and libvirt log, " + "memory allocation and memory device config") + check_after_attach(vm, test, params) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bkxml.sync() + process.run("echo 0 > %s" % (kernel_hp_file % default_hugepage_size), + shell=True) + + vm_name = params.get("main_vm") + original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = original_xml.copy() + vm = env.get_vm(vm_name) + + virtio_dict, plug_dict = adjust_virtio_dict(params) + default_hugepage_size = memory.get_huge_page_size() + case = params.get("case") + allocate_size = int(params.get("allocate_size")) + vm_attrs = eval(params.get("vm_attrs", "{}")) + kernel_hp_file = params.get("kernel_hp_file") + plug_error = params.get("plug_error") + plug_event = params.get('plug_event') + + memory_base.check_supported_version(params, test, vm) + + try: + setup_test() + run_test() + + finally: + teardown_test() From 461a34a87330b9ce6e117ad8545d731779a2652f Mon Sep 17 00:00:00 2001 From: Chunfu Wen Date: Wed, 12 Jun 2024 04:16:58 -0400 Subject: [PATCH 0394/1055] Fix virsh.start.status_error_no.audit_log_search failure in checking auvirt log In some case, previous auvirt legacy log may include some log information, which impact test result. So better truncate the log first before any checking Signed-off-by: Chunfu Wen --- libvirt/tests/src/virsh_cmd/domain/virsh_start.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_start.py b/libvirt/tests/src/virsh_cmd/domain/virsh_start.py index 167814d1b56..dc582bcf0af 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_start.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_start.py @@ -1,3 +1,4 @@ +import os import logging as log from avocado.utils import process @@ -54,6 +55,9 @@ def check_auvirt_log(test, params): vm_name = params.get("main_vm", "avocado-vt-vm1") str_to_grep = params.get("auvirt_error_msg") % vm_name auvirt_log_file = params.get("tmp_auvirt_event_log") + if os.path.exists(auvirt_log_file): + cmd = f"truncate -s 0 {auvirt_log_file}" + process.run(cmd, ignore_status=True, shell=True, verbose=True) generate_virt_log_cmd = "auvirt --start recent --all-events|tee %s" % auvirt_log_file process.run(generate_virt_log_cmd, ignore_status=False, shell=True, verbose=True) if not libvirt.check_logfile(str_to_grep, auvirt_log_file, str_in_log=False): From b8e998fad928edfc8daebcae07906c092f9d5db5 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Mon, 15 Apr 2024 23:58:02 -0400 Subject: [PATCH 0395/1055] Fixup:trustGuestRxFilters:Add version check and xml check - Add version check - Add xml check after update-device Signed-off-by: Haijiao Zhao --- .../update_device/update_iface_trustGuestRxFilters.cfg | 1 + .../update_device/update_iface_trustGuestRxFilters.py | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_iface_trustGuestRxFilters.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_iface_trustGuestRxFilters.cfg index 9ac73138f41..9716f98a9b1 100644 --- a/libvirt/tests/cfg/virtual_network/update_device/update_iface_trustGuestRxFilters.cfg +++ b/libvirt/tests/cfg/virtual_network/update_device/update_iface_trustGuestRxFilters.cfg @@ -4,6 +4,7 @@ timeout = 240 host_iface = outside_ip = 'www.redhat.com' + func_supported_since_libvirt_ver = (10, 0, 0) variants: - yes_to_no: trustGRF = 'yes' diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py b/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py index c41eab8da90..8bb32c61403 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py @@ -1,6 +1,7 @@ import logging from avocado.utils import process +from virttest import libvirt_version from virttest import utils_net from virttest import virsh from virttest.libvirt_xml import vm_xml @@ -18,6 +19,7 @@ def run(test, params, env): """ Test live update trustGuestRxFilters for direct type interface """ + libvirt_version.is_libvirt_feature_supported(params) vm_name = params.get('main_vm') vm = env.get_vm(vm_name) host_iface = params.get('host_iface') @@ -48,6 +50,10 @@ def run(test, params, env): iface_update = network_base.get_iface_xml_inst(vm_name, 'after update') LOG.debug(f'iface trustGuestRxFilters after update: ' f'{iface_update.trustGuestRxFilters}') + if iface_update.trustGuestRxFilters != update_attrs[ + 'trustGuestRxFilters']: + test.fail(f'Interface trustGuestRxFilters not successfully updated ' + f'to {update_attrs["trustGuestRxFilters"]}') mac_host = utils_net.get_linux_iface_info(iface=target_dev)['address'] From e89e248c9198a948d9f48ad5254195a269d39c19 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Mon, 3 Jun 2024 21:48:47 +0800 Subject: [PATCH 0396/1055] aarch64_cpu_sve: add more tests - Refine the codes structure - Dynamically test with all supported sve lengths instead of hardcodes - Add sve stress test suite in vm - Add optimized routines test suite in vm - Add discontinuous enabled sve length test Signed-off-by: Dan Zheng --- libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg | 69 ++- libvirt/tests/src/cpu/aarch64_cpu_sve.py | 527 ++++++++++++++++------ 2 files changed, 428 insertions(+), 168 deletions(-) diff --git a/libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg b/libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg index 5e9a5e5ffb7..f050e4a7757 100644 --- a/libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg +++ b/libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg @@ -4,50 +4,69 @@ check_cmd_lscpu = "which lscpu" check_sve = "lscpu | grep sve" check_sve_config = "grep CONFIG_ARM64_SVE=y /boot/config-%s" - get_maxium_sve_length = "dmesg | grep 'SVE: maximum available vector length'" + get_maximum_sve_length = "dmesg | grep 'SVE: maximum available vector length'" cpu_xml_policy = "require" cpu_xml_mode = "host-passthrough" only aarch64 variants: - boot_test: + status_error = "no" variants: - enable_sve: - expect_sve = "yes" - disable_sve: cpu_xml_policy = "disable" expect_sve = "no" - - vector_length_test: + - with_vector_length: variants: - valid_length: - expect_sve = "yes" + status_error = "no" variants: - - single_vector: - variants: - - sve128: - vector_length = "sve128" - - sve256: - vector_length = "sve256" - - sve512: - vector_length = "sve512" - - mutiple_vector: - vector_lenth_list = '[{"sve128":"require"}, {"sve256":"require"}, {"sve384":"disable"}, {"sve512":"require"}]' + - 128: + vector_length = "sve128" + - 256: + vector_length = "sve256" + - 512: + vector_length = "sve512" + - all_supported_lengths: + all_supports = "yes" - invalid_length: - only negative_test - expect_sve = "no" + status_error = "yes" vector_length = "sve1234" expect_msg = "unsupported configuration: unknown CPU feature: sve1234" - conflict_length: - only negative_test - vector_lenth_list = '[{"sve":"disable"}, {"sve128":"require"}]' + status_error = "yes" + vector_length_list = '[{"sve":"disable"}, {"sve128":"require"}]' define_error = "yes" expect_msg = "SVE disabled, but SVE vector lengths provided" + - unsupported_length: + unsupported_len = yes + status_error = "yes" + expect_msg = "does not support the vector length" + - discontinous_length: + status_error = "yes" + discontinous_len = "yes" + expect_msg = "KVM host requires all supported vector lengths smaller than .* bits .* enabled" + - optimized-routines: + status_error = "no" + all_supports = "yes" + install_pkgs = ["git", "gcc", "make", "glibc-static", "mpfr-devel", "libmpc-devel"] + target_dir = "/home/optimized_routines" + optimized_repo_cmd = "git clone --depth=1 https://github.com/ARM-software/optimized-routines ${target_dir}" + optimized_echo_cmd = "echo 'CFLAGS += -march=armv8.2-a+sve' >> config.mk" + optimized_compile_cmd = "cd ${target_dir}; cp config.mk.dist config.mk; ${optimized_echo_cmd}; make" + optimized_execute_cmd = "cd ${target_dir}; make check 2>/dev/null" + - sve_stress: + status_error = "no" + all_supports = "yes" + install_pkgs = ["git", "gcc", "make", "kernel-devel", "kernel-headers", "rsync", "brewkoji", "tar"] + target_dir = "/home/sve_stress" + suite_dir = "${target_dir}/tools/testing/selftests/arm64/fp" + sve_exec_timeout = 360 + sve_stress_download_cmd = "cd /var/tmp && brew download-build --rpm %s && rpm2cpio %s | cpio -idm" + sve_stress_tar_cmd = "cd /var/tmp && tar Jxf %s --strip-components 1 -C ${target_dir}" + sve_stress_compile_cmd = "cd ${suite_dir}; make" + sve_stress_get_lenths = "${suite_dir}/sve-probe-vls" + sve_stress_exec_cmd = "cd ${suite_dir}; timeout ${sve_exec_timeout} ./vlset --inherit %s ./sve-stress 2>/dev/null" - no_host_sve_support: - only negative_test host_without_sve = "yes" status_error = "yes" - variants: - - positive_test: - status_error = "no" - - negative_test: - only invalid_length, conflict_length, no_host_sve_support - status_error = "yes" diff --git a/libvirt/tests/src/cpu/aarch64_cpu_sve.py b/libvirt/tests/src/cpu/aarch64_cpu_sve.py index 719232c0b51..023f939f939 100644 --- a/libvirt/tests/src/cpu/aarch64_cpu_sve.py +++ b/libvirt/tests/src/cpu/aarch64_cpu_sve.py @@ -1,8 +1,9 @@ +import json import re import logging as log -from avocado.utils import process from avocado.core import exceptions +from avocado.utils import process from virttest import virsh from virttest import utils_package @@ -16,146 +17,376 @@ logging = log.getLogger('avocado.' + __name__) -def run(test, params, env): +def get_vector_lengths(vm_name): """ - Test aarch64 SVE feature + Get the supported and unsupported vector lengths on the host - :param test: QEMU test object - :param params: Dictionary with the test parameters - :param env: Dictionary with test environment. + :param vm_name: str, the vm name + :return: (dict, dict), the supported and unsupported vector list + """ + cmd = '{"execute":"query-cpu-model-expansion", "arguments": {"type": "full", "model": {"name":"host"}}}' + virsh_opt = {"debug": True, "ignore_status": False} + unsupported_list = [] + supported_list = [] + ret = virsh.qemu_monitor_command(vm_name, cmd, **virsh_opt) + length_obj = json.loads(ret.stdout_text.strip()) + props_dict = length_obj.get("return").get("model").get("props") + for v_length, status in props_dict.items(): + match = re.findall("sve(\d+)", v_length) + if not match: + continue + if not status: + unsupported_list.append(int(match[0])) + elif status: + supported_list.append(int(match[0])) + supported_list.sort(reverse=True) + unsupported_list.sort(reverse=True) + logging.debug("The unsupported vector length in the vm:%s", unsupported_list) + logging.debug("The supported vector length in the vm:%s", supported_list) + return (supported_list, unsupported_list) + + +def prepare_env(vm, params, test): + """ + Prepare test env + + :param vm: The virtual machine + :param params: dict, test parameters + :param test: test object """ - vm_name = params.get("main_vm", "avocado-vt-vm1") - vm = env.get_vm(vm_name) - start_vm = params.get("start_vm", "no") check_sve = params.get("check_sve", "") + host_without_sve = "yes" == params.get("host_without_sve", "no") check_sve_config = params.get("check_sve_config", "") - get_maxium_sve_length = params.get("get_maxium_sve_length", "") + session = None + try: + # Cancel test if the Host doesn't support or supports SVE based on configuration + if process.run(check_sve, ignore_status=True, shell=True).exit_status: + if not host_without_sve: + test.cancel("Host doesn't support SVE") + else: + return + else: + if host_without_sve: + test.cancel("Host supports SVE") - cpu_xml_mode = params.get("cpu_xml_mode", "host-passthrough") - cpu_xml_policy = params.get("cpu_xml_policy", "require") + if not vm.is_alive(): + vm.start() + session = vm.wait_for_login(timeout=120) + current_boot = session.cmd("uname -r").strip() + # To enable SVE: Hardware support && enable kconfig + # CONFIG_ARM64_SVE + if session.cmd_status(check_sve_config % current_boot): + test.cancel("Guest kernel doesn't enable CONFIG_ARM64_SVE") - status_error = "yes" == params.get("status_error", "no") - define_error = "yes" == params.get("define_error", "no") - host_without_sve = "yes" == params.get("host_without_sve", "no") - expect_sve = "yes" == params.get("expect_sve", "yes") - expect_msg = params.get("expect_msg", "") - vector_length = params.get("vector_length", "sve") - vector_lenth_list = params.get("vector_lenth_list", "") + # Install lscpu tool that check whether CPU has SVE + if (not utils_package.package_install("util-linux") + or not utils_package.package_install("util-linux", session)): + test.error("Failed to install util-linux") - def _prepare_env(vm): - """ - Prepare test env + except (exceptions.TestCancel, exceptions.TestError): + raise + except Exception as e: + test.error("Failed to prepare test env: %s" % e) + finally: + if session: + session.close() - :param vm: The virtual machine - """ - try: - if not vm.is_alive(): - vm.start() - session = vm.wait_for_login(timeout=120) - current_boot = session.cmd('uname -r').strip() - # Install lscpu tool that check whether CPU has SVE - if (not utils_package.package_install("util-linux") - or not utils_package.package_install("util-linux", session)): - test.error("Failed to install util-linux") +def get_max_sve_len_in_guest(vm_session, params, test): + """ + Get the maximum supported sve length of guest - # Cancel test if the Host doesn't support or supports SVE based on configuration - if process.run(check_sve, ignore_status=True, shell=True).exit_status: - if not host_without_sve: - test.cancel("Host doesn't support SVE") - else: - return + :param vm_session: The virtual machine session + :param params: dict, test parameters + :param test: test object + :return: str, maximum vector length. Format: e.g sve512 + """ + get_maximum_sve_len = params.get("get_maximum_sve_length", "") + sve_length_bit = "" + try: + ret = vm_session.cmd(get_maximum_sve_len).strip() + # dmesg record maximum sve length in bytes + sve_length_byte = re.search(r"length (\d+) bytes", ret).groups()[0] + # Change max_length into sve + length(bit) E.g. sve512 + sve_length_bit = "sve" + str(int(sve_length_byte) * 8) + logging.debug("The guest maximum SVE vector length is %s", sve_length_bit) + except Exception as e: + test.fail("Failed to get maximum guest SVE vector length: %s" % e) + + return sve_length_bit + + +def guest_has_sve(vm_session, params, test): + """ + Check whether guest has SVE + + :param vm_session: The virtual machine session + :param params: dict, test parameters + :param test: test object + + :return True if guest has sve + """ + check_sve = params.get("check_sve", "") + ret = False + try: + if not vm_session.cmd_status(check_sve): + ret = True + except Exception as e: + test.error("Failed to check guest SVE: %s" % e) + return ret + + +def check_vector_length_supported(vector_length, supported_list): + """ + Check if a given vector length is supported on the host + + :param vector_length: str, sve length + :param supported_list: list, sve lengths supported + :return: bool, True if supported, otherwise False + """ + match = re.findall("sve(\d+)", vector_length) + if match and int(match[0]) in supported_list: + return True + else: + logging.warning("The vector length %s (in bits) is " + "unsupported on the host" % vector_length) + return False + + +def gen_disable_features(enable_length, supported_list): + """ + Generate the cpu features to be disabled + + :param enable_length: str, sve length to be enabled + :param supported_list: dict, sve lengths supported + :return: list, disabled cpu features + """ + result = [] + enable_length = re.findall("sve(\d+)", enable_length)[0] + for a_length in supported_list: + if a_length > int(enable_length): + result.append({"sve%d" % a_length: "disable"}) + return result + + +def gen_cpu_features(supported_list, unsupported_list, params, test): + """ + Generate cpu features + + :param supported_list: dict, sve lengths supported + :param unsupported_list: dict, sve lengths unsupported + :param params: dict, test parameters + :param test: test object + :return: list, cpu features + """ + all_supports = params.get("all_supports", "no") == "yes" + status_error = "yes" == params.get("status_error", "no") + vector_length = params.get("vector_length") + cpu_xml_policy = params.get("cpu_xml_policy", "require") + unsupported_len = params.get("unsupported_len") + discontinous_len = params.get("discontinous_len") + result = [] + + if not status_error: + if all_supports: + result.append({"sve": cpu_xml_policy}) + for a_length in supported_list: + result.append({"sve%d" % a_length: cpu_xml_policy}) + return result + if vector_length: + if not check_vector_length_supported(vector_length, supported_list): + test.cancel("The vector length is not supported on the host") + result.append({vector_length: cpu_xml_policy}) + result.extend(gen_disable_features(vector_length, supported_list)) + else: + result.append({"sve": cpu_xml_policy}) + else: + vector_length_list = params.get("vector_length_list") + if unsupported_len: + if len(unsupported_list) > 1: + result.append({"sve%d" % unsupported_list[0]: cpu_xml_policy}) else: - if host_without_sve: - test.cancel("Host supports SVE") - - # To enable SVE: Hardware support && enable kconfig - # CONFIG_ARM64_SVE - if session.cmd_status(check_sve_config % current_boot): - test.cancel("Guest kernel doesn't enable CONFIG_ARM64_SVE") - except (exceptions.TestCancel, exceptions.TestError): - raise - except Exception as e: - test.error("Failed to prepare test env: %s" % e) - finally: - if session: - session.close() + test.cancel("No unsupported vector length by the host is available") + elif discontinous_len: + if len(supported_list) == 1: + test.cancel("Require at least two supported " + "sve lengths for the test, but only one is found") + result.append({"sve%d" % supported_list[0]: "require"}) + result.append({"sve%d" % supported_list[len(supported_list) - 1]: "disable"}) + elif vector_length_list: + vector_length_list = eval(vector_length_list) + for one_len in vector_length_list: + result.append(one_len) + else: + if vector_length: + result.append({vector_length: cpu_xml_policy}) + return result - def _get_maxium_sve_length(vm): - """ - Get the maximum supported sve length of guest - : return maximum vector length. Format: e.g sve512 - """ - try: - session = None - if not vm.is_alive(): - vm.start() - session = vm.wait_for_login(timeout=120) - ret = session.cmd(get_maxium_sve_length).strip() - # dmesg record maximum sve length in bytes - sve_length_byte = re.search(r"length (\d+) bytes", ret).groups()[0] - # Change max_length into sve + length(bit) E.g. sve512 - sve_length_bit = "sve" + str(int(sve_length_byte) * 8) - logging.debug("The guest maximum SVE vector length is %s", sve_length_bit) - except Exception as e: - test.fail("Failed to get maximum guest SVE vector length: %s" % e) - finally: - if session: - session.close() - return sve_length_bit +def update_cpu_xml(cpu_xml, params, test, supported_list, unsupported_list): + """ + Update vm cpu xml object - def _guest_has_sve(vm): - """ - Check whether guest has SVE + :param cpu_xml: VMCPUXML instance + :param params: dict, test parameters + :param test: test object + :param supported_list: list, sve lengths supported + :param unsupported_list: list, sve lengths unsupported + """ + # For sve, each SVE vector_length is a feature name + # E.g. sve128 sve256 sve512 + # Test unsupported vector length + vector_list = gen_cpu_features(supported_list, unsupported_list, params, test) + for vector in vector_list: + for length, policy in vector.items(): + cpu_xml.add_feature(length, policy) + logging.debug("cpu_xml is %s" % cpu_xml) - :param vm: The virtual machine - :return True if guest has sve - """ - try: - ret = False - session = None - if not vm.is_alive(): - vm.start() - session = vm.wait_for_login(timeout=120) - if not session.cmd_status(check_sve): - ret = True - except Exception as e: - test.error("Failed to check guest SVE: %s" % e) - finally: - if session: - session.close() - return ret +def execute_cmds(cmd, session, test, timeout=360, ignore_status=False): + """ + Execute a command with vm session + + :param cmd: str, the command to be executed + :param session: vm session + :param test: test object + :param timeout: int, defaults to 360 + :param ignore_status: bool, defaults to False + :return: str, the output of the command + """ + status, output = session.cmd_status_output(cmd, timeout=timeout) + if status: + msg = "Fail to execute %s with error %s,\ + message: %s" % (cmd, status, output) + if not ignore_status: + test.fail(msg) + else: + test.log.error(msg) + return output - # Close guest and edit guest xml - if vm.is_alive() and start_vm == "no": + +def run_optimized_routines_in_guest(session, params, test): + """ + Run optimized routines test suite within the guest + + :param session: vm session + :param params: dict, test parameters + :param test: test object + """ + execute_cmds(params.get("optimized_repo_cmd"), session, test) + execute_cmds(params.get("optimized_compile_cmd"), session, test) + output = execute_cmds(params.get("optimized_execute_cmd"), session, test) + results = re.findall(r"^(\w+) \w+sve$", output, re.M) + if not all([result == "PASS" for result in results]): + test.fail("The optimized-routines sve tests have failures in log\n%s" % results) + else: + test.log.debug("Verify optimized-routines sve tests in guest - PASS") + + +def execute_sve_stress_by_suite(length_list, session, params, test): + """ + Execute sve_stress test suite within the guest + + :param length_list: list, sve lengths + :param session: vm session + :param params: dict, test parameters + :param test: test object + """ + sve_stress_exec_cmd = params.get("sve_stress_exec_cmd") + sve_exec_timeout = int(params.get("sve_exec_timeout")) + + for a_length in length_list: + exec_cmd = sve_stress_exec_cmd % a_length + output = session.cmd_output(exec_cmd, + timeout=sve_exec_timeout + 10) + results_lines = [result for result in output.splitlines() if + result.startswith("Terminated by")] + if len(re.findall(r"no error", output, re.M)) != len(results_lines): + test.log.debug("Test results: %s", results_lines) + test.fail("SVE stress test failed") + test.log.debug("Verify sve stress test for length %s (in bytes) - PASS" % a_length) + + +def verify_sve_length_by_suite(supported_list, session, params, test): + """ + Verify the supported sve lengths are same with test suite output + + :param supported_list: list, supported sve length (in bits), like [128, 256] + :param session: vm session + :param params: dict, test parameters + :param test: test object + :return: list, sve length (in bytes) list from test suite command + like ['16', '32'] + """ + sve_stress_get_lenths = params.get("sve_stress_get_lenths") + output = execute_cmds(sve_stress_get_lenths, session, test) + results = re.findall(r"# (\d+)$", output, re.M) + new_results = [int(result) * 8 for result in results] + if set(new_results) != set(supported_list): + test.fail("The sve-probe-vls output %s does " + "not match the supported sve lenths %s" % (results, + supported_list)) + else: + test.log.debug("Verify sve-probe-vls output in guest - PASS") + return results + + +def run_sve_stress_test_in_guest(supported_list, session, params, test): + """ + Run sve stress test suite within the guest + + :param supported_list: list, supported sve lengths + :param session: vm session + :param params: dict, test parameters + :param test: test object + """ + kernel_version = session.cmd_output("uname -r").rsplit('.', 1)[0] + srpm = "kernel-%s.src.rpm" % kernel_version + linux_name = "linux-%s.tar.xz" % kernel_version + sve_stress_download_cmd = params.get("sve_stress_download_cmd") % (srpm, + srpm) + sve_stress_tar_cmd = params.get("sve_stress_tar_cmd") % linux_name + sve_stress_compile_cmd = params.get("sve_stress_compile_cmd") + + execute_cmds(sve_stress_download_cmd, session, test) + execute_cmds(sve_stress_tar_cmd, session, test) + execute_cmds(sve_stress_compile_cmd, session, test) + sve_lengths = verify_sve_length_by_suite(supported_list, session, params, test) + execute_sve_stress_by_suite(sve_lengths, session, params, test) + + +def run(test, params, env): + """ + Test aarch64 SVE feature + + :param test: QEMU test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + cpu_xml_mode = params.get("cpu_xml_mode", "host-passthrough") + status_error = "yes" == params.get("status_error", "no") + define_error = "yes" == params.get("define_error", "no") + expect_sve = "yes" == params.get("expect_sve", "yes") + expect_msg = params.get("expect_msg", "") + vector_length = params.get("vector_length", "sve") + sve_stress_exec_cmd = params.get("sve_stress_exec_cmd") + optimized_execute_cmd = params.get("optimized_execute_cmd") + target_dir = params.get("target_dir") + + prepare_env(vm, params, test) + supported_list, unsupported_list = get_vector_lengths(vm_name) + + if vm.is_alive(): vm.destroy(gracefully=False) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) original_vm_xml = vmxml.copy() - try: - # Install lscpu && Check host sve support && - # Check guest guest kernel support - _prepare_env(vm) - - # Create cpu xml and modify SVE cpu_xml = vm_xml.VMCPUXML() cpu_xml.mode = cpu_xml_mode - # For sve, each SVE vector_length is a feature name - # E.g. sve128 sve256 sve512 - if vector_lenth_list: - vector_list = eval(vector_lenth_list) - for vector in vector_list: - for length, policy in vector.items(): - cpu_xml.add_feature(length, policy) - else: - cpu_xml.add_feature(vector_length, cpu_xml_policy) - - logging.debug("cpu_xml is %s" % cpu_xml) - - # Updae vm's cpu + update_cpu_xml(cpu_xml, params, test, supported_list, unsupported_list) vmxml.cpu = cpu_xml try: vmxml.sync() @@ -165,45 +396,55 @@ def _guest_has_sve(vm): if not re.search(expect_msg, str(e)): test.fail("Expect definition failure: %s but got %s" % (expect_msg, str(e))) - return True + else: + test.log.debug("Verify the expected vm definition error - PASS") + return else: test.error("Failed to define guest: %s" % str(e)) - result = virsh.start(vm_name) - special_error_msg = "CPU does not support the vector length" - if re.search(special_error_msg, result.stderr_text): - test.cancel(result.stderr_text) - libvirt.check_exit_status(result, status_error) - - if status_error: - # Test boot failed - if result.exit_status: - if not re.search(expect_msg, result.stderr.strip()): - logging.debug(result.stderr.strip()) - test.fail("Failed to get expect err msg: %s" % expect_msg) - else: - logging.info("Get expected err msg %s" % expect_msg) - else: - # Test boot successfully + result = virsh.start(vm_name, debug=True, ignore_status=True) + libvirt.check_result(result, expected_fails=expect_msg) + # Test boot successfully + if not status_error: + session = vm.wait_for_login(timeout=120) if expect_sve: - # Enable SVE in domain xml - if not _guest_has_sve(vm): + # Expect SVE is enabled in domain xml + if not guest_has_sve(session, params, test): test.fail("Expect guest cpu enable SVE") - - # SVE available with only the selected vector + else: + test.log.debug("Verify sve is enabled in guest - PASS") + # Expect SVE is available with only the selected vector expect_vector_length = vector_length - available_maxium_sve_length = _get_maxium_sve_length(vm) + available_maximum_sve_length = get_max_sve_len_in_guest(session, params, test) if vector_length == "sve": - expect_vector_length = available_maxium_sve_length - if expect_vector_length != available_maxium_sve_length: + expect_vector_length = "sve%d" % supported_list[0] + if expect_vector_length != available_maximum_sve_length: test.fail("Expect guest support %s" % vector_length) + else: + test.log.debug("Verify the supported maximum " + "vector length is %s in guest " + "- PASS" % expect_vector_length) + + install_pkgs = eval(params.get("install_pkgs", "[]")) + if install_pkgs and not utils_package.package_install(install_pkgs, session, 360): + test.error("Failed to install %s on guest." % install_pkgs) + + if target_dir: + execute_cmds("mkdir -p %s" % target_dir, session, test) + if sve_stress_exec_cmd: + run_sve_stress_test_in_guest(supported_list, session, params, test) + if optimized_execute_cmd: + run_optimized_routines_in_guest(session, params, test) + execute_cmds("rm -rf %s" % target_dir, session, test) else: # Disable SVE in domain xml - if _guest_has_sve(vm): + if guest_has_sve(session, params, test): test.fail("Expect guest cpu disable SVE") - + else: + test.log.debug("Verify sve is disabled in guest - PASS") + if session: + session.close() finally: - # Restore guest if vm.is_alive(): vm.destroy(gracefully=False) original_vm_xml.sync() From b7da87041ac8e7170e95026846d3c153e6766e04 Mon Sep 17 00:00:00 2001 From: Qian Jianhua Date: Thu, 13 Jun 2024 13:37:00 +0800 Subject: [PATCH 0397/1055] remove unused parameters --- .../numa/guest_numa_topology/various_numa_topology_settings.cfg | 2 -- 1 file changed, 2 deletions(-) diff --git a/libvirt/tests/cfg/numa/guest_numa_topology/various_numa_topology_settings.cfg b/libvirt/tests/cfg/numa/guest_numa_topology/various_numa_topology_settings.cfg index 4371b1d32a4..9bc241d7039 100644 --- a/libvirt/tests/cfg/numa/guest_numa_topology/various_numa_topology_settings.cfg +++ b/libvirt/tests/cfg/numa/guest_numa_topology/various_numa_topology_settings.cfg @@ -8,10 +8,8 @@ qemu_monitor_option = '--hmp' qemu_monitor_cmd = 'info memdev' cpu_mode = 'host-model' - target_hugepages = 1024 aarch64: cpu_mode = 'host-passthrough' - hugepage_size = 2048 numa_cell_0 = {'id': '0', 'memory': '1048576', 'cpus': '0-1'} numa_cell_1 = {'id': '1', 'memory': '1048576', 'cpus': '2-3'} numa_cells = [${numa_cell_0}, ${numa_cell_1}] From 4f71bf0675dfb4d73e4c95e8bec92d9962e21c4f Mon Sep 17 00:00:00 2001 From: Chunfu Wen Date: Wed, 12 Jun 2024 21:06:37 -0400 Subject: [PATCH 0398/1055] Fix qemu-img convert system disk to ceph timeout issue Previously use qemu-img convert local system disk to ceph server, it is time costing,and sometime it takes more than 1 hour to finish converting operations. And it leads to ci job timeouts related to them rbd tool provides one function: rbd import, which has stable and reliable uplink feature,so switch to use rbd import to upload system disk to ceph server Signed-off-by: Chunfu Wen --- .../src/virtual_disks/virtual_disks_ceph.py | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_ceph.py b/libvirt/tests/src/virtual_disks/virtual_disks_ceph.py index 5e05de2171b..716b411dc15 100755 --- a/libvirt/tests/src/virtual_disks/virtual_disks_ceph.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_ceph.py @@ -573,6 +573,7 @@ def get_secret_list(): key_opt = "" secret_uuid = None snapshot_path = None + converted_raw_file = "" key_file = os.path.join(TMP_DATA_DIR, "ceph.key") img_file = os.path.join(TMP_DATA_DIR, "%s_test.img" % vm_name) @@ -743,11 +744,19 @@ def get_secret_list(): first_disk = vm.get_first_disk_devices() blk_source = first_disk['source'] # Convert the image to remote storage - disk_cmd = ("rbd -m %s %s info %s 2> /dev/null|| qemu-img convert" - " -O %s %s %s" % (mon_host, key_opt, - disk_src_name, disk_format, - blk_source, disk_path)) - process.run(disk_cmd, ignore_status=False, shell=True) + directory = os.path.dirname(blk_source) + filename_with_extension = os.path.basename(blk_source) + + # Get the file name without extension and the extension + filename, _ = os.path.splitext(filename_with_extension) + converted_raw_file = os.path.join(directory, "%s.raw" % filename) + convert_cmd = ("qemu-img convert" + " -O %s %s %s" % (disk_format, blk_source, converted_raw_file)) + process.run(convert_cmd, ignore_status=False, verbose=True, shell=True) + disk_cmd = ("rbd -m %s %s info %s 2> /dev/null|| rbd -m %s %s import " + " %s %s" % (mon_host, key_opt, disk_src_name, mon_host, key_opt, converted_raw_file, + disk_src_name)) + process.run(disk_cmd, ignore_status=False, verbose=True, shell=True) elif create_volume: vol_params = {"name": vol_name, "capacity": int(vol_cap), @@ -1043,6 +1052,8 @@ def _check_slice_in_xml(): os.remove(key_file) if os.path.exists(img_file): os.remove(img_file) + if converted_raw_file and os.path.exists(converted_raw_file): + os.remove(converted_raw_file) # Clean up volume, pool if vol_name and vol_name in str(virsh.vol_list(pool_name).stdout): virsh.vol_delete(vol_name, pool_name) From 8733c48c0d6186fc6acb0b0a029f18843ec4d794 Mon Sep 17 00:00:00 2001 From: Chunfu Wen Date: Thu, 13 Jun 2024 02:33:04 -0400 Subject: [PATCH 0399/1055] Fix migration ceph timeout issue Previously it use qemu-img convert to upload system disk to ceph server, it is time cost. Instead here it use rbd import function,and it is much reliable and fast Signed-off-by: Chunfu Wen --- libvirt/tests/src/migration/migrate_ceph.py | 24 ++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/src/migration/migrate_ceph.py b/libvirt/tests/src/migration/migrate_ceph.py index 4d6c5d08b72..9eb422fb20a 100644 --- a/libvirt/tests/src/migration/migrate_ceph.py +++ b/libvirt/tests/src/migration/migrate_ceph.py @@ -359,11 +359,22 @@ def prepare_ceph_disk(ceph_params, remote_virsh_dargs, test, runner_on_target): if auth_user and auth_key: disk_path += (":id=%s:key=%s" % (auth_user, auth_key)) - disk_cmd = ("rbd -m %s %s info %s || qemu-img convert" - " -O %s %s %s" % (mon_host, key_opt, - disk_src_name, disk_format, - blk_source, disk_path)) - process.run(disk_cmd, ignore_status=False, shell=True) + + # Convert the image to remote storage + directory = os.path.dirname(blk_source) + filename_with_extension = os.path.basename(blk_source) + + # Get the file name without extension and the extension + filename, _ = os.path.splitext(filename_with_extension) + converted_raw_file = os.path.join(directory, "%s.raw" % filename) + convert_cmd = ("qemu-img convert" + " -O %s %s %s" % (disk_format, blk_source, converted_raw_file)) + process.run(convert_cmd, ignore_status=False, verbose=True, shell=True) + disk_cmd = ("rbd -m %s %s info %s 2> /dev/null|| rbd -m %s %s import " + " %s %s" % (mon_host, key_opt, disk_src_name, mon_host, key_opt, converted_raw_file, + disk_src_name)) + process.run(disk_cmd, ignore_status=False, verbose=True, shell=True) + return (key_opt, secret_uuid) @@ -455,6 +466,7 @@ def run(test, params, env): mon_host = params.get("mon_host") ceph_key_opt = "" attach_disk = False + converted_raw_file = "" # Disk XML file disk_xml = None # Define ceph_disk conditional variable @@ -590,6 +602,8 @@ def run(test, params, env): test.fail("Failed to run '%s' on remote: %s" % (cmd, output)) finally: + if converted_raw_file and os.path.exists(converted_raw_file): + os.remove(converted_raw_file) logging.info("Recovery test environment") # Clean up of pre migration setup for local machine if migrate_vm_back: From bcc84ff09daff70ed65c0a521cecf624738b098f Mon Sep 17 00:00:00 2001 From: Vera Wu Date: Thu, 13 Jun 2024 16:16:55 +0800 Subject: [PATCH 0400/1055] v2v: fix the failed cases of specific-kvm on rhel9.5 Signed-off-by: Vera Wu --- v2v/tests/cfg/specific_kvm.cfg | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/v2v/tests/cfg/specific_kvm.cfg b/v2v/tests/cfg/specific_kvm.cfg index 7e49808aba3..fff9ba70d1a 100644 --- a/v2v/tests/cfg/specific_kvm.cfg +++ b/v2v/tests/cfg/specific_kvm.cfg @@ -92,6 +92,8 @@ os_version = 'OS_VERSION_MULTI_DISK_WIN_V2V_EXAMPLE' main_vm = 'VM_MULTI_DISK_WIN_V2V_EXAMPLE' only source_esx.esx_70 + skip_vm_check = yes + skip_reason = "bz#RHEL-17685 on win2016 guest" - multi_kernel: only source_esx.esx_70 # this case requires '-v -x' @@ -286,6 +288,8 @@ only source_esx.esx_80 boottype = 2 main_vm = 'VM_NON_EXIST_NETWORK_V2V_EXAMPLE' + skip_vm_check = yes + skip_reason = "bz#RHEL-1718 on win11 guest" variants: - positive_test: status_error = 'no' From aab32e6c0edfa9df00a67496300753da3a811300 Mon Sep 17 00:00:00 2001 From: Chunfu Wen Date: Thu, 13 Jun 2024 05:07:33 -0400 Subject: [PATCH 0401/1055] Fix mklabel issue in multple VMs case By specifying label to gpt, instead of msdos Signed-off-by: Chunfu Wen --- libvirt/tests/src/virtual_disks/virtual_disks_multivms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_multivms.py b/libvirt/tests/src/virtual_disks/virtual_disks_multivms.py index 2dad7283353..4f58410cf93 100644 --- a/libvirt/tests/src/virtual_disks/virtual_disks_multivms.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_multivms.py @@ -165,7 +165,7 @@ def get_vm_disk_xml(dev_type, dev_name, **options): is_setup=True, is_login=True, image_size=image_size) logging.debug("iscsi dev name: %s", disk_source) # Format the disk and make the file system. - libvirt.mk_label(disk_source) + libvirt.mk_label(disk_source, "gpt") libvirt.mk_part(disk_source, size="10M") if not utils_misc.wait_for(lambda: "%s1" % disk_source.split("/")[-1] in utils_disk.get_parts_list(), timeout=5): test.fail("Partition %s1 can not be ready" % disk_source) From a70a51d491e09d53104c7ae43e2c57b233a1a081 Mon Sep 17 00:00:00 2001 From: nanli Date: Mon, 3 Jun 2024 18:17:04 +0800 Subject: [PATCH 0402/1055] fix virsh domstats block.allocation not changing issue during blockcommit add utils_misc.wait for function --- ...llocation_watermark_during_blockcommit.cfg | 26 +++++-- ...allocation_watermark_during_blockcommit.py | 74 +++++++++---------- provider/virtual_disk/disk_base.py | 9 ++- 3 files changed, 62 insertions(+), 47 deletions(-) diff --git a/libvirt/tests/cfg/backingchain/blockcommit/check_allocation_watermark_during_blockcommit.cfg b/libvirt/tests/cfg/backingchain/blockcommit/check_allocation_watermark_during_blockcommit.cfg index 5609f7f89a2..cd28feb36ec 100644 --- a/libvirt/tests/cfg/backingchain/blockcommit/check_allocation_watermark_during_blockcommit.cfg +++ b/libvirt/tests/cfg/backingchain/blockcommit/check_allocation_watermark_during_blockcommit.cfg @@ -2,24 +2,40 @@ type = check_allocation_watermark_during_blockcommit target_disk = "vdb" domstats_option = " --block --backing | grep allocation " + changing_index = "4" + changing_alloc = "block.${changing_index}.allocation" disappear_index = "4" disappear_alloc = "block.${disappear_index}.allocation" lvm_num = 3 snap_nums = 3 - virsh_opt = " -k0" + write_file_bs = "1M" + write_file_count = "400" + lv_size = "200M" variants case: - inactive_layer: - commit_option = "--top ${target_disk}[3] --base ${target_disk}[1] --wait --verbose --bandwidth 10" + commit_option = "--top ${target_disk}[3] --base ${target_disk}[1] --wait --verbose --bandwidth 1" commit_success_msg = "Commit complete" - active_layer: - commit_option = " --wait --verbose --pivot --bandwidth 10" + commit_option = " --wait --verbose --pivot --bandwidth 1" commit_success_msg = "Successfully pivoted" variants: - file_disk: + storage_type = nfs + set_sebool_local = 'yes' + local_boolean_varible = 'virt_use_nfs' + setup_local_nfs = "yes" + nfs_mount_src = "/var/lib/avocado/data/avocado-vt/nfs-export" + nfs_mount_dir = "/var/lib/avocado/data/avocado-vt/nfs-mount" + nfs_mount_options = "rw" + export_ip = "*" + export_dir = "/var/lib/avocado/data/avocado-vt/nfs-export" + export_options= "rw,root_squash" + local_boolean_value = "on" disk_type = "nfs" disk_dict = {"type_name":"file", "target":{"dev": "${target_disk}", "bus": "virtio"}, "driver": {"name": "qemu", "type":"qcow2"}} extra_option = ",snapshot=external --diskspec vda,snapshot=no " - block_disk: disk_type = "block" - disk_dict = {"type_name":"${disk_type}", "target":{"dev": "${target_disk}", "bus": "virtio"}, "driver": {"name": "qemu", "type":"raw"}} - extra_option = ",snapshot=external,stype=block --diskspec vda,snapshot=no --reuse-external " + convert_format = "qcow2" + disk_dict = {"type_name":"${disk_type}", "target":{"dev": "${target_disk}", "bus": "virtio"}, "driver": {"name": "qemu", "type":"qcow2"}} + extra_option = ",snapshot=external,stype=block --diskspec vda,snapshot=no --reuse-external" diff --git a/libvirt/tests/src/backingchain/blockcommit/check_allocation_watermark_during_blockcommit.py b/libvirt/tests/src/backingchain/blockcommit/check_allocation_watermark_during_blockcommit.py index 1bed6dfcd76..c01d2008f81 100644 --- a/libvirt/tests/src/backingchain/blockcommit/check_allocation_watermark_during_blockcommit.py +++ b/libvirt/tests/src/backingchain/blockcommit/check_allocation_watermark_during_blockcommit.py @@ -1,8 +1,7 @@ -import time +import re from avocado.utils import lv_utils -from virttest import data_dir from virttest import utils_disk from virttest import utils_misc from virttest import virsh @@ -14,6 +13,8 @@ from provider.backingchain import blockcommand_base from provider.virtual_disk import disk_base +virsh_debug = {'debug': True, 'ignore_status': False} + def run(test, params, env): """ @@ -29,7 +30,7 @@ def run(test, params, env): def setup_test(): """ - Set disk + Set disk. """ test_obj.new_image_path = disk_obj.add_vm_disk( disk_type, disk_dict) @@ -49,7 +50,6 @@ def run_test(): snap_num=1, extra=extra_option, snap_path=path_list[index], clean_snap_file=False) - alloc_new_dict_1 = get_alloc_result() write_file(format_disk, "/mnt/file_%s" % index) format_disk = False @@ -63,42 +63,34 @@ def run_test(): test_obj.new_dev) test.log.debug("After creating snaps, The xml is:\n%s", vmxml) - # Manual case requires to sleep 5 seconds and check the domstats again - time.sleep(5) - test.log.info("TEST_STEP2: Check %s keep changing " - "during blockcommit.", disappear_alloc) - cmd = "blockcommit %s %s %s " % (vm_name, target_disk, - commit_option) + test.log.info("TEST_STEP2: Check %s keep changing during blockcommit.", changing_alloc) + alloc_value = get_alloc_result().get(changing_index) + cmd = "blockcommit %s %s %s " % (vm_name, target_disk, commit_option) virsh_session = virsh.VirshSession(virsh_exec=virsh.VIRSH_EXEC, auto_close=True) virsh_session.sendline(cmd) test.log.debug("blockcommit cmd: %s", cmd) - alloc_dict = {} - for i in range(0, 2): - alloc_new_dict = get_alloc_result() - test.log.debug('Current alloc dict is:%s, last alloc dict is :%s', - alloc_new_dict, alloc_dict) - if alloc_new_dict.get(disappear_index) == \ - alloc_dict.get(disappear_index, ""): - test.fail("%s should keep changing during blockcommit %s." % ( - disappear_alloc, virsh_session.get_stripped_output())) - alloc_dict = alloc_new_dict - time.sleep(1) + def _alloc_changed(): + new_alloc = get_alloc_result() + test.log.debug("Commit result:%s", virsh_session.get_stripped_output()) + test.log.debug("Currently, %s changes from %s to %s" % ( + changing_alloc, alloc_value, new_alloc[changing_index])) + return new_alloc[changing_index] != alloc_value + + if not utils_misc.wait_for(_alloc_changed, timeout=120, step=0.1): + test.fail("%s is not changing during blockcommit in 120s." % changing_alloc) + test.log.debug("Checked the %s changing successfully" % changing_alloc) test.log.info("TEST_STEP3: Check %s should disappear" % disappear_alloc) - if utils_misc.wait_for(lambda: commit_success_msg in - virsh_session.get_stripped_output(), 40, step=0.01): - alloc_new_dict = get_alloc_result() - if disappear_alloc in alloc_new_dict: - test.fail("The % should not be in %s" % (disappear_alloc, - alloc_new_dict)) - else: - test.log.debug("Current commit result:%s ", - virsh_session.get_stripped_output()) - test.fail("Blockcommit still not finish in 40s, " - "Please control commit speed to test :%s", - (virsh_session.get_stripped_output())) + if not utils_misc.wait_for( + lambda: commit_success_msg in virsh_session.get_stripped_output(), + 30, step=0.01): + virsh.blockjob(vm_name, target_disk, options=" --abort", **virsh_debug) + alloc_new_dict = get_alloc_result() + if disappear_alloc in alloc_new_dict: + test.fail("The % should not be in %s" % (disappear_alloc, + alloc_new_dict)) def teardown_test(): """ @@ -125,8 +117,8 @@ def prepare_snap_path(): disk_format="qcow2") path.append(source_path) elif disk_type == "nfs": - for item in range(0, snap_nums): - source_path = data_dir.get_data_dir() + "/images/snap_%s" % ( + for item in range(1, snap_nums+1): + source_path = params.get("nfs_mount_dir") + "/snap_%s" % ( item) path.append(source_path) return path @@ -142,8 +134,7 @@ def write_file(format_disk, file_name): if format_disk: cmd = "mkfs.ext4 /dev/%s;mount /dev/%s /mnt" % (target_disk, target_disk) session.cmd_status_output(cmd) - utils_disk.dd_data_to_vm_disk(session, file_name, bs='1M', - count='50') + utils_disk.dd_data_to_vm_disk(session, file_name, bs=bs, count=count) session.close() def get_alloc_result(): @@ -165,14 +156,14 @@ def get_alloc_result(): disk_dict = eval(params.get('disk_dict', '{}')) target_disk = params.get('target_disk') commit_option = params.get('commit_option') - disappear_index = params.get('disappear_index') disappear_alloc = params.get('disappear_alloc') + changing_index = params.get('changing_index') + changing_alloc = params.get('changing_alloc') commit_success_msg = params.get('commit_success_msg') extra_option = params.get('extra_option') disk_type = params.get('disk_type') domstats_option = params.get('domstats_option') snap_nums = int(params.get('snap_nums')) - vg_name, lv_name, lv_size = 'vg0', 'lv', "200M" vm = env.get_vm(vm_name) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) @@ -180,7 +171,10 @@ def get_alloc_result(): test_obj = blockcommand_base.BlockCommand(test, vm, params) disk_obj = disk_base.DiskBase(test, vm, params) - + disk_obj.disk_size = "1G" + vg_name = disk_obj.vg_name + lv_name, lv_size = re.findall(r"\D+", disk_obj.lv_name)[0], params.get("lv_size") + bs, count = params.get("write_file_bs"), params.get("write_file_count") try: setup_test() run_test() diff --git a/provider/virtual_disk/disk_base.py b/provider/virtual_disk/disk_base.py index 6ba294dcfbe..e5079b8403b 100644 --- a/provider/virtual_disk/disk_base.py +++ b/provider/virtual_disk/disk_base.py @@ -48,6 +48,7 @@ def __init__(self, test, vm, params): self.new_image_path = '' self.path_list = '' self.disk_backend = '' + self.disk_size = "50M" @staticmethod def get_source_list(vmxml, disk_type, target_dev): @@ -129,6 +130,10 @@ def prepare_disk_obj(self, disk_type, disk_dict, new_image_path='', **kwargs): if not new_image_path: new_image_path = self.create_lvm_disk_path( vg_name=self.vg_name, lv_name=self.lv_name, **kwargs) + if self.params.get('convert_format'): + process.run("qemu-img create -f %s /dev/%s/%s %s" % ( + self.params.get('convert_format'), self.vg_name, + self.lv_name, self.disk_size), shell=True) disk_dict.update({'source': {'attrs': {'dev': new_image_path}}}) elif disk_type == 'volume': @@ -146,7 +151,7 @@ def prepare_disk_obj(self, disk_type, disk_dict, new_image_path='', **kwargs): new_image_path = nfs_res['mount_dir'] + '/test.img' libvirt.create_local_disk("file", path=new_image_path, - size='50M', + size=self.disk_size, disk_format="qcow2", **kwargs) disk_dict.update({'source': {'attrs': {'file': new_image_path}}}) @@ -288,7 +293,7 @@ def create_lvm_disk_path(vg_name='vg0', lv_name='lv0', **kwargs): if kwargs.get("size"): kwargs.pop("size") path = libvirt.create_local_disk("lvm", size=size, vgname=vg_name, - lvname=lv_name, **kwargs) + lvname=lv_name) return path From e639a8d99e5c48ccd58c5ad0f282739def9d9c4d Mon Sep 17 00:00:00 2001 From: Vera Wu Date: Fri, 14 Jun 2024 12:14:05 +0800 Subject: [PATCH 0403/1055] v2v: fix failed case in v2v-options Signed-off-by: Vera Wu --- v2v/tests/cfg/v2v_options.cfg | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/v2v/tests/cfg/v2v_options.cfg b/v2v/tests/cfg/v2v_options.cfg index 11f6ae2b91f..c4ff7d73ad6 100644 --- a/v2v/tests/cfg/v2v_options.cfg +++ b/v2v/tests/cfg/v2v_options.cfg @@ -342,12 +342,6 @@ - default: expect_msg = yes msg_content = "disk \d+: \d+%total: \d+" - - remote_libvirt_conn: - only output_mode.null - only input_mode.libvirt.kvm.default - checkpoint = 'remote_libvirt_conn' - expect_msg = yes - msg_content = "no support for remote libvirt connections" - copy_to_local: cmd_free = yes only input_mode.libvirt.xen @@ -362,6 +356,12 @@ - negative_test: status_error = "yes" variants: + - remote_libvirt_conn: + only output_mode.null + only input_mode.libvirt.kvm.default + checkpoint = 'remote_libvirt_conn' + expect_msg = yes + msg_content = "no support for remote libvirt connections" - conflict_options: only input_mode.none only output_mode.none From 473ecaf8bf23d589a25efe8a15e29091c10191c6 Mon Sep 17 00:00:00 2001 From: nanli Date: Wed, 15 May 2024 17:57:55 +0800 Subject: [PATCH 0404/1055] add case for revert snap after the guest xml updated xxxx-300471: Revert snapshots after the guest xml is updated Signed-off-by: nanli --- .../revert_snapshot_after_xml_updated.cfg | 26 ++ .../revert_snapshot_after_xml_updated.py | 241 ++++++++++++++++++ 2 files changed, 267 insertions(+) create mode 100644 libvirt/tests/cfg/snapshot/revert_snapshot_after_xml_updated.cfg create mode 100644 libvirt/tests/src/snapshot/revert_snapshot_after_xml_updated.py diff --git a/libvirt/tests/cfg/snapshot/revert_snapshot_after_xml_updated.cfg b/libvirt/tests/cfg/snapshot/revert_snapshot_after_xml_updated.cfg new file mode 100644 index 00000000000..28bac6d4e01 --- /dev/null +++ b/libvirt/tests/cfg/snapshot/revert_snapshot_after_xml_updated.cfg @@ -0,0 +1,26 @@ +- snapshot_revert.xml_updated: + type = revert_snapshot_after_xml_updated + start_vm = no + snap_names = ["s1", "s2"] + file_list = ["/mnt/s1", "/mnt/s2"] + snap_options = "%s --memspec snapshot=external,file=/tmp/mem.%s --diskspec vda,snapshot=external,file=/tmp/vda.%s" + func_supported_since_libvirt_ver = (9, 10, 0) + variants updated_type: + - hotplug_disk: + disk_type = "file" + system_disk = "vda" + new_disk = "vdb" + disk_dict = {"type_name":"${disk_type}", "target":{"dev": "${new_disk}", "bus": "virtio"}, "driver": {"name": "qemu", "type":"qcow2"}} + system_disk_pattern ="${system_disk}\s+.*\d{2,}\s*" + new_disk_pattern ="${new_disk}\s+.*\d{2,}\s*" + - hotplug_vcpus: + vm_attrs = {"vcpu":4, "vcpus": {"vcpu": [{"id":"0", "enabled":"yes", "hotpluggable":"no"}, {"id":"1", "enabled":"no", "hotpluggable":"yes"},{"id":"2", "enabled":"no", "hotpluggable":"yes"}, {"id":"3", "enabled":"no", "hotpluggable":"yes"}]}} + vcpus_ele = "" + set_cpu = 1 + original_vcpu = {"enabled":'no', 'hotpluggable':'yes'} + new_vcpu = {"enabled":'yes', 'hotpluggable':'yes'} + - blkiotune: + mode_cmd = "modprobe scsi_debug dev_size_mb=500" + weight = "400" + setting_type = "device-write-bytes-sec" + blkiotune_cmd = "${setting_type} %s,${weight}" diff --git a/libvirt/tests/src/snapshot/revert_snapshot_after_xml_updated.py b/libvirt/tests/src/snapshot/revert_snapshot_after_xml_updated.py new file mode 100644 index 00000000000..af1ecd84d05 --- /dev/null +++ b/libvirt/tests/src/snapshot/revert_snapshot_after_xml_updated.py @@ -0,0 +1,241 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import re + +from avocado.utils import process + +from virttest import libvirt_version +from virttest import virsh +from virttest.libvirt_xml import vm_xml + +from provider.snapshot import snapshot_base +from provider.virtual_disk import disk_base + +virsh_dargs = {"debug": True, "ignore_status": False} + + +def compare_value(test, actual_value, expected_value2): + if actual_value != expected_value2: + test.fail("Expect to get %s, but got %s" % (expected_value2, actual_value)) + + +def check_existed(test, res, pattern): + """ + Check if pattern exist in virsh.domblklist result. + + :param test: test object. + :param res: the result. + :param pattern: expected pattern. + """ + search = re.findall(pattern, res) + if not search: + test.fail("%s not exist in %s" % (pattern, res)) + else: + test.log.debug("Matched %s" % search) + + +def create_file(vm, file, session=None): + """ + Create specific file in guest + + :param vm: vm object. + :param file: the file to create. + :param session: the guest session. + """ + if not session: + session = vm.wait_for_login() + session.cmd("touch %s" % file) + session.close() + + +def check_file_exist(test, vm, params, revert_snap): + """ + Check file existed + + :param test: test object. + :param vm: file list to be checked. + :param params: Dictionary with the test parameters + :param revert_snap: the reverted snapshot order. + """ + vm_name = params.get("main_vm") + + if not vm.is_alive(): + virsh.start(vm_name) + session = vm.wait_for_login() + + if revert_snap == "1": + file_list = eval(params.get("file_list"))[0:1] + elif revert_snap == "2": + file_list = eval(params.get("file_list")) + + for file in file_list: + status, _ = session.cmd_status_output("cat %s " % file) + if status: + test.fail("%s not exist" % file) + session.close() + + +def update_xml(params, test, vm): + """ + Update guest xml according to the scenarios. + + :param params: test parameters object + :param test: test object + :param vm: vm object + """ + updated_type = params.get("updated_type") + disk_dict = eval(params.get("disk_dict", "{}")) + disk_type = params.get("disk_type") + vm_name = params.get("main_vm") + set_cpu = params.get("set_cpu") + mode_cmd = params.get("mode_cmd") + blkiotune_cmd = params.get("blkiotune_cmd") + + disk_obj = disk_base.DiskBase(test, vm, params) + if updated_type == "hotplug_disk": + disk, image_path = disk_obj.prepare_disk_obj(disk_type, disk_dict) + virsh.attach_device(vm_name, disk.xml, **virsh_dargs) + + elif updated_type == "hotplug_vcpus": + virsh.setvcpu(vm_name, set_cpu, "--enable", **virsh_dargs) + + elif updated_type == "blkiotune": + process.run(mode_cmd, shell=True) + + res = process.run("lsscsi", shell=True).stdout_text.strip() + params.update( + {"dev": re.findall(r"Linux\s*scsi_debug\s*\d+\s+(\S+)\s*", res)[0]}) + virsh.blkiotune(vm_name, options=blkiotune_cmd % params.get("dev"), + **virsh_dargs) + + +def check_result_after_revert(params, test, vm, revert_snap): + """ + Check the result after revert corresponding snapshot + + :param params: test parameters object + :param test: test object + :param vm: vm object + :param revert_snap: the reverted snapshot order + """ + vm_name = params.get("main_vm") + updated_type = params.get("updated_type") + original_vcpu = eval(params.get("original_vcpu", "{}")) + new_vcpu = eval(params.get("new_vcpu", "{}")) + system_disk_pattern = params.get("system_disk_pattern") + new_disk_pattern = params.get("new_disk_pattern") + blkiotune_weight = params.get("weight") + + if updated_type == "hotplug_disk": + res = virsh.domblklist(vm_name, debug=True).stdout_text.strip() + if revert_snap == "1": + check_existed(test, res, system_disk_pattern) + elif revert_snap == "2": + check_existed(test, res, system_disk_pattern) + check_existed(test, res, new_disk_pattern) + + elif updated_type == "hotplug_vcpus": + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + actual_vcpu = vmxml.vcpus.vcpu[1] + if revert_snap == "1": + compare_value(test, actual_vcpu["enabled"], original_vcpu["enabled"]) + compare_value(test, actual_vcpu["hotpluggable"], original_vcpu["hotpluggable"]) + elif revert_snap == "2": + compare_value(test, actual_vcpu["enabled"], new_vcpu["enabled"]) + compare_value(test, actual_vcpu["hotpluggable"], new_vcpu["hotpluggable"]) + + elif updated_type == "blkiotune": + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + blkiotune = vmxml.xmltreefile.find(".//blkiotune") + if revert_snap == "1": + compare_value(test, blkiotune != '', True) + elif revert_snap == "2": + compare_value( + test, blkiotune.find('.//device/write_bytes_sec').text, + blkiotune_weight + ) + check_file_exist(test, vm, params, revert_snap) + + +def run(test, params, env): + """ + Revert snapshots after the guest xml is updated. + """ + def setup_test(): + """ + Define guest if needed. + """ + if updated_type == "hotplug_vcpus": + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vmxml.setup_attrs(**vm_attrs) + virsh.define(vmxml.xml, **virsh_dargs) + test.log.debug("New guest xml is:\n%s", + vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)) + + def run_test(): + """ + Revert snapshots after the guest xml is updated. + Update guest xml scenario: + hotplug disk/hotplug vcpus/blkiotune + """ + test.log.info("TEST_STEP1:Prepare a running guest and create file.") + virsh.start(vm_name) + session = vm.wait_for_login() + create_file(vm, file_list[0], session) + + test.log.info("TEST_STEP2: Create snapshot.") + virsh.snapshot_create_as( + vm_name, snap_options % (snap_names[0], snap_names[0], + snap_names[0]), **virsh_dargs) + test.log.info("TEST_STEP3: Update xml by %s and create file in guest." % updated_type) + update_xml(params, test, vm) + create_file(vm, file_list[1]) + + test.log.info("TEST_STEP4: Create another snapshot after xml updated.") + virsh.snapshot_create_as( + vm_name, snap_options % (snap_names[1], snap_names[1], + snap_names[1]), **virsh_dargs) + + test.log.info("TEST_STEP5: Revert to the 1st snapshot and check file.") + virsh.snapshot_revert(vm_name, snap_names[0], **virsh_dargs) + check_result_after_revert(params, test, vm, "1") + + test.log.info("TEST_STEP6: Revert to the 2nd snapshot and check file.") + virsh.snapshot_revert(vm_name, snap_names[1], **virsh_dargs) + check_result_after_revert(params, test, vm, "2") + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + snap_names.reverse() + test_obj.teardown_test() + + vm_name = params.get("main_vm") + original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + params['backup_vmxml'] = original_xml.copy() + vm = env.get_vm(vm_name) + + snap_names = eval(params.get("snap_names", '[]')) + updated_type = params.get("updated_type") + snap_options = params.get("snap_options") + vm_attrs = eval(params.get("vm_attrs", "{}")) + file_list = eval(params.get("file_list", '[]')) + test_obj = snapshot_base.SnapshotTest(vm, test, params) + + libvirt_version.is_libvirt_feature_supported(params) + + try: + setup_test() + run_test() + + finally: + teardown_test() From abec2c389dc2872dcc27510f3771f4ab077041b5 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Fri, 14 Jun 2024 06:59:25 -0400 Subject: [PATCH 0405/1055] Fixup:get vm ip address with unexpected characters Add a function to get ip address with ip --json to fix the issue Signed-off-by: Haijiao Zhao --- provider/virtual_network/network_base.py | 32 +++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/provider/virtual_network/network_base.py b/provider/virtual_network/network_base.py index 0793be72256..cd3bc43a9c0 100644 --- a/provider/virtual_network/network_base.py +++ b/provider/virtual_network/network_base.py @@ -16,6 +16,33 @@ LOG = logging.getLogger('avocado.' + __name__) +def get_vm_ip(session, mac, ip_ver="ipv4"): + """ + Get vm ip address + + :param session: vm session + :param mac: mac address of vm + :param ip_ver: ip version, defaults to "ipv4" + :return: ip address of given mac + """ + iface_info = utils_net.get_linux_iface_info(mac=mac, session=session) + addr_list = iface_info['addr_info'] + if ip_ver == "ipv4": + target_addr = [addr for addr in addr_list if addr['family'] == 'inet'] + elif ip_ver == "ipv6": + target_addr = [addr for addr in addr_list if addr['family'] == 'inet6' + and addr['scope'] == 'global' + and addr.get('mngtmpaddr') is not True] + + if len(target_addr) == 0: + raise exceptions.TestError( + f'Cannot find ip addr with given mac: {mac}') + elif len(target_addr) > 1: + LOG.warn(f'Multiple ip addr: {target_addr}') + else: + return target_addr[0]['local'] + + def get_test_ips(session, mac, ep_session, ep_mac, net_name=None, ip_ver='ipv4', host_iface=None): """ @@ -31,9 +58,8 @@ def get_test_ips(session, mac, ep_session, ep_mac, net_name=None, :return: a dict of ip addresses """ ips = {} - ips['vm_ip'], ips['ep_vm_ip'] = [utils_net.get_guest_ip_addr( - sess, mac_ad, ip_version=ip_ver) - for sess, mac_ad in [(session, mac), (ep_session, ep_mac)]] + ips['vm_ip'] = get_vm_ip(session, mac, ip_ver=ip_ver) + ips['ep_vm_ip'] = get_vm_ip(ep_session, ep_mac, ip_ver=ip_ver) if not host_iface: host_public_ip = utils_net.get_host_ip_address(ip_ver=ip_ver) else: From b970515122026865b3a98e7c1196537bed737136 Mon Sep 17 00:00:00 2001 From: Yanqiu Zhang Date: Fri, 14 Jun 2024 12:45:20 -0400 Subject: [PATCH 0406/1055] tpm_device.cfg: update tpm1.2 error msg Update tpm1.2 error msg Signed-off-by: Yanqiu Zhang --- libvirt/tests/cfg/virtual_device/tpm_device.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_device/tpm_device.cfg b/libvirt/tests/cfg/virtual_device/tpm_device.cfg index dee9a38346f..f97a71037a5 100644 --- a/libvirt/tests/cfg/virtual_device/tpm_device.cfg +++ b/libvirt/tests/cfg/virtual_device/tpm_device.cfg @@ -194,7 +194,7 @@ variants: - version_1.2: backend_version = '1.2' - xml_errmsg = "Unsupported interface tpm-crb for TPM 1.2|TPM version '1.2' is not supported" + xml_errmsg = "Unsupported interface.*tpm-crb.*for TPM 1.2|TPM version '1.2' is not supported" pseries: xml_errmsg = 'TPM 1.2 is not supported with the SPAPR device mode' - version_2: From 2388da5fbbcab6d67bc3659f1cd48d15e69ea9e2 Mon Sep 17 00:00:00 2001 From: Yanqiu Zhang Date: Fri, 14 Jun 2024 13:28:08 -0400 Subject: [PATCH 0407/1055] tpm_device: install wget in guest wget is not installed in guest by default on new product version, add it here. Signed-off-by: Yanqiu Zhang --- libvirt/tests/src/virtual_device/tpm_device.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/src/virtual_device/tpm_device.py b/libvirt/tests/src/virtual_device/tpm_device.py index fa82e8913e5..bc94dad11cb 100644 --- a/libvirt/tests/src/virtual_device/tpm_device.py +++ b/libvirt/tests/src/virtual_device/tpm_device.py @@ -572,6 +572,8 @@ def run_test_suite_in_guest(session): # Download test suite if tpm_testsuite_url.count("EXAMPLE"): test.error("Please provide the URL %s" % tpm_testsuite_url) + if not utils_package.package_install('wget', session, 60): + test.fail("Failed to install wget in guest OS.") download_cmd = "wget %s -O %s" % (tpm_testsuite_url, "/root/linux.tar.xz") output = session.cmd_output(download_cmd, timeout=480) logging.debug("Command output: %s", output) From 6938cfadc596953882401898d5c5ef4c3dc5017e Mon Sep 17 00:00:00 2001 From: nanli Date: Sat, 15 Jun 2024 09:14:51 +0800 Subject: [PATCH 0408/1055] fix incorrect source path after blockcopy Need wait some time to check after blockcopy Signed-off-by: nanli --- .../blockcopy/blockcopy_with_async_option.py | 14 ++++++++++---- provider/backingchain/check_functions.py | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/src/backingchain/blockcopy/blockcopy_with_async_option.py b/libvirt/tests/src/backingchain/blockcopy/blockcopy_with_async_option.py index 336e852c6f5..2b9ce8aeefe 100644 --- a/libvirt/tests/src/backingchain/blockcopy/blockcopy_with_async_option.py +++ b/libvirt/tests/src/backingchain/blockcopy/blockcopy_with_async_option.py @@ -74,11 +74,17 @@ def _check_res(case, virsh_session=None): event_output)) elif case == 'async': + def _check_path(): + try: + check_obj.check_backingchain_from_vmxml( + disk_type, target_disk, [test_obj.copy_image]) + return True + except Exception as e: + return False + test.log.info("TEST_STEP2: Check expected chain") - expected_chain = test_obj.\ - convert_expected_chain(expected_chain_index) - check_obj.check_backingchain_from_vmxml(disk_type, target_disk, - expected_chain) + if not utils_misc.wait_for(_check_path, 60): + test.fail('Expect source file to be %s' % [test_obj.copy_image]) def _get_session(): """ diff --git a/provider/backingchain/check_functions.py b/provider/backingchain/check_functions.py index c7e20b84a37..ed90223517b 100644 --- a/provider/backingchain/check_functions.py +++ b/provider/backingchain/check_functions.py @@ -37,12 +37,12 @@ def check_backingchain_from_vmxml(self, disk_type, target_dev, expected_chain): vmxml = vm_xml.VMXML.new_from_dumpxml(self.vm.name) LOG.debug("Current vmxml is:\n%s", vmxml) source_list = DiskBase.get_source_list(vmxml, disk_type, target_dev) - if source_list != expected_chain: self.test.fail('Expect source file to be %s, ' 'but got %s' % (expected_chain, source_list)) else: LOG.debug('Get correct backingchin') + return True def check_block_operation_result(self, vmxml, blockcommand, target_dev, bc_chain): From eb5f6f34a65e32e3341ddbf21ecbc3e5c6dacbdd Mon Sep 17 00:00:00 2001 From: Yanqiu Zhang Date: Sun, 16 Jun 2024 12:52:45 -0400 Subject: [PATCH 0409/1055] domif_setlink_getlink: get accurate ifstate in vm the session cmd result of 'ip addr show dev' includes extra escape characters, use utils_net.get_linux_iface_info dict to get accurate 'operstate':'DOWN/UP' instead. Implement it in a new funciton: guest_ifstate_check(). And rename another link state function from guest_if_state() to guest_link_state() Signed-off-by: Yanqiu Zhang --- .../domain/virsh_domif_setlink_getlink.py | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_domif_setlink_getlink.py b/libvirt/tests/src/virsh_cmd/domain/virsh_domif_setlink_getlink.py index a59e2c2cc5d..a541af206c4 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_domif_setlink_getlink.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_domif_setlink_getlink.py @@ -68,7 +68,18 @@ def guest_cmd_check(cmd, session, pattern): logging.debug(e) return re.search(pattern, str(e.__str__)) - def guest_if_state(if_name, session): + def guest_ifstate_check(ifname, expected_state, session): + """ + Check guest interface dev state in session + """ + iface_info = utils_net.get_linux_iface_info(mac=mac_address, session=session) + logging.debug("guest iface %s info: %s" % (ifname, iface_info)) + if iface_info['ifname'] == ifname: + return iface_info['operstate'] == expected_state + else: + test.fail("Did not get expected % from mac %s" % (ifname, mac_address)) + + def guest_link_state(if_name, session): """ Get the domain link state from the guest """ @@ -100,7 +111,7 @@ def check_update_device(vm, if_name, session): if ret.exit_status: logging.error("Failed to update device to up state") return False - if not utils_misc.wait_for(lambda: guest_if_state(if_name, session), 5): + if not utils_misc.wait_for(lambda: guest_link_state(if_name, session), 5): logging.error("Guest link should be up now") return False @@ -112,7 +123,7 @@ def check_update_device(vm, if_name, session): if ret.exit_status: logging.error("Failed to update device to down state") return False - if utils_misc.wait_for(lambda: guest_if_state(if_name, session), 5): + if utils_misc.wait_for(lambda: guest_link_state(if_name, session), 5): logging.error("Guest link should be down now") return False @@ -248,10 +259,10 @@ def check_update_device(vm, if_name, session): # Check link state in guest if check_link_state: if (if_operation == "up" and - not guest_if_state(guest_if_name, session)): + not guest_link_state(guest_if_name, session)): error_msg = "Link state should be up in guest" if (if_operation == "down" and - guest_if_state(guest_if_name, session)): + guest_link_state(guest_if_name, session)): error_msg = "Link state should be down in guest" if error_msg: test.fail(error_msg) @@ -264,21 +275,18 @@ def check_update_device(vm, if_name, session): # Set the link up make host connect with vm domif_setlink(vm_name[0], device, "up", "") if not utils_misc.wait_for( - lambda: guest_if_state(guest_if_name, session), 5): + lambda: guest_link_state(guest_if_name, session), 5): test.fail("Link state isn't up in guest") # Ignore status of this one cmd = 'ip link set %s down;' % guest_if_name session.cmd_status_output(cmd, timeout=10) - pattern = "%s:.*state DOWN.*" % guest_if_name - pattern_cmd = 'ip addr show dev %s' % guest_if_name - guest_cmd_check(pattern_cmd, session, pattern) + guest_ifstate_check(guest_if_name, 'DOWN', session) cmd = 'ip link set %s up;' % guest_if_name session.cmd_status_output(cmd, timeout=10) - pattern = "%s:.*state UP.*" % guest_if_name - if not utils_misc.wait_for(lambda: guest_cmd_check( - pattern_cmd, session, pattern), timeout=20): + if not utils_misc.wait_for(lambda: guest_ifstate_check( + guest_if_name, 'UP', session), timeout=20): test.fail("Could not bring up interface %s inside guest" % guest_if_name) else: # negative test From e843526c0844765a6e4fcade266146466fdec92c Mon Sep 17 00:00:00 2001 From: Yanqiu Zhang Date: Sun, 16 Jun 2024 10:06:33 -0400 Subject: [PATCH 0410/1055] net_update: get accurate ip Fix ping failures by getting accurate ip. Signed-off-by: Yanqiu Zhang --- libvirt/tests/src/virsh_cmd/network/virsh_net_update.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/network/virsh_net_update.py b/libvirt/tests/src/virsh_cmd/network/virsh_net_update.py index 6f2ab4ea62a..18e3d27c08d 100644 --- a/libvirt/tests/src/virsh_cmd/network/virsh_net_update.py +++ b/libvirt/tests/src/virsh_cmd/network/virsh_net_update.py @@ -13,6 +13,7 @@ from virttest.libvirt_xml import xcepts from virttest.libvirt_xml import vm_xml from avocado.utils import process +from provider.virtual_network import network_base # Using as lower capital is not the best way to do, but this is just a @@ -832,9 +833,7 @@ def section_update(ori_pre, new_pre): "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) + iface_ip = network_base.get_vm_ip(session, mac, ip_ver=ip_version) 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]", From 0ad965d679a3801de0e0695da312c1e8f2abe6d8 Mon Sep 17 00:00:00 2001 From: Yanqiu Zhang Date: Sun, 16 Jun 2024 09:05:30 -0400 Subject: [PATCH 0411/1055] net_dhcp_leases: get accurate vm ip, install dhcp Fix failures by getting accurate vm ip and install dhcp tool. Signed-off-by: Yanqiu Zhang --- .../src/virsh_cmd/network/virsh_net_dhcp_leases.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/network/virsh_net_dhcp_leases.py b/libvirt/tests/src/virsh_cmd/network/virsh_net_dhcp_leases.py index 108551377fd..eb2a2699a28 100644 --- a/libvirt/tests/src/virsh_cmd/network/virsh_net_dhcp_leases.py +++ b/libvirt/tests/src/virsh_cmd/network/virsh_net_dhcp_leases.py @@ -11,8 +11,9 @@ from avocado.utils import process from datetime import datetime, timedelta from virttest.libvirt_xml import LibvirtXMLError +from provider.virtual_network import network_base -from virttest import libvirt_version +from virttest import libvirt_version, utils_package # Using as lower capital is not the best way to do, but this is just a @@ -154,7 +155,9 @@ def f(): if ip_addr is None: iface_name = utils_net.get_linux_ifname(session, mac_addr) if try_dhclint: - session.cmd("dhclient %s" % iface_name) + if not utils_package.package_install('dhcpcd', session, 60): + test.fail("Failed to install dhcpcd in guest OS.") + session.cmd("dhcpcd %s" % iface_name) ip_addr = utils_misc.wait_for(f, 10) else: # No IP for the interface, just print the interface name @@ -189,7 +192,8 @@ def check_net_lease(net_leases, expected_find=True): else: logging.debug("Not find '%s' in domain XML", net_mac) continue - iface_ip = get_ip_by_mac(net_mac) + session = vm.wait_for_login(login_nic_index, timeout=120, serial=True) + iface_ip = network_base.get_vm_ip(session, net_mac) if iface_ip and iface_ip != net_ip: test.fail("Address '%s' is not expected" % iface_ip) #check if lease time is correct From bf0686b2ad459071e05da230976bfc44e992954a Mon Sep 17 00:00:00 2001 From: Vera Wu Date: Mon, 17 Jun 2024 17:28:43 +0800 Subject: [PATCH 0412/1055] v2v: add latest 3rd-party guests in matrix Signed-off-by: Vera Wu --- v2v/tests/cfg/convert_vm_to_libvirt.cfg | 31 +++++++++++++++++-------- v2v/tests/cfg/convert_vm_to_ovirt.cfg | 30 +++++++++++++++++------- 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/v2v/tests/cfg/convert_vm_to_libvirt.cfg b/v2v/tests/cfg/convert_vm_to_libvirt.cfg index f39888c8c43..8bddc7b440c 100644 --- a/v2v/tests/cfg/convert_vm_to_libvirt.cfg +++ b/v2v/tests/cfg/convert_vm_to_libvirt.cfg @@ -38,7 +38,7 @@ - boot_uefi: vm_boot = "-efi" boottype = 3 - only 8_0.linux.latest10_dev, 8_0.linux.latest9_dev, 8_0.linux.latest9, 8_0.linux.latest8, 8_0.linux.8_8, 8_0.linux.8_6, 8_0.linux.ubuntu_lts, 8_0.linux.sles_latest, 8_0.windows.win2022, 8_0.windows.win11, 8_0.windows.win2016, 8_0.windows.win2025 + only 8_0.linux.latest10_dev, 8_0.linux.latest9_dev, 8_0.linux.latest9, 8_0.linux.latest8, 8_0.linux.8_8, 8_0.linux.8_6, 8_0.linux.ubuntu22_04, 8_0.linux.ubuntu_lts, 8_0.linux.sles15sp4, 8_0.linux.sles_lts, 8_0.linux.opensuse15_5, 8_0.windows.win2022, 8_0.windows.win11, 8_0.windows.win2016, 8_0.windows.win2025 variants: - linux: os_type = "linux" @@ -70,32 +70,43 @@ - 5_11: os_version = "rhel5.11" enable_legacy_policy = yes - - debian: + - debian11_7: + only source_esx.esx_80 + #os_short_id = "debian11" + os_version = "debian11.7.0" + - debian_lts: only source_esx.esx_80 #os_short_id = "DEBIAN_SHORT_ID" - os_version = "DEBIAN_VERSION" + os_version = "DEBIAN_LTS_VERSION" + - ubuntu22_04: + only source_esx.esx_80 + os_short_id = "ubuntu22.04" + os_version = "ubuntu22.04" - ubuntu_lts: only source_esx.esx_80 os_short_id = "UBUNTU_LTS_SHORT_ID" os_version = "UBUNTU_LTS_VERSION" - - sles12sp4: - only source_esx.esx_67, source_esx.esx_70 - os_short_id = "sles12sp4" - os_version = "sles12sp4" - sles12sp5: only source_esx.esx_80 os_short_id = "sles12sp5" os_version = "sles12sp5" - - sles_latest: + - sles15sp4: + only source_esx.esx_80 + os_short_id = "sles15sp4" + os_version = "sles15sp4" + - sles_lts: only source_esx.esx_80 os_version = "SLES_LATEST_VERSION" - opensuse_latest: - only source_esx.esx_67, source_esx.esx_70, source_esx.esx_80 + only source_esx.esx_70, source_esx.esx_80 os_short_id = "OPENSUSE_LATEST_SHORT_ID" os_version = "OPENSUSE_LATEST_VERSION" - opensuse15_4: - only source_esx.esx_67, source_esx.esx_70 + only source_esx.esx_70 os_version = "opensuse15.4" + - opensuse15_5: + only source_esx.esx_80 + os_version = "opensuse15.5" - windows: no pv os_type = "windows" diff --git a/v2v/tests/cfg/convert_vm_to_ovirt.cfg b/v2v/tests/cfg/convert_vm_to_ovirt.cfg index 868af9fa343..47e62a75f04 100644 --- a/v2v/tests/cfg/convert_vm_to_ovirt.cfg +++ b/v2v/tests/cfg/convert_vm_to_ovirt.cfg @@ -81,7 +81,7 @@ - boot_uefi: vm_boot = "-efi" boottype = 3 - only 8_0.linux.latest10_dev, 8_0.linux.latest9_dev, 8_0.linux.latest9, 8_0.linux.latest8, 8_0.linux.8_8, 8_0.linux.8_6, 8_0.linux.ubuntu_lts, 8_0.linux.sles_latest, 8_0.windows.win2022, 8_0.windows.win11, 8_0.windows.win2016, 8_0.windows.win2025 + only 8_0.linux.latest10_dev, 8_0.linux.latest9_dev, 8_0.linux.latest9, 8_0.linux.latest8, 8_0.linux.8_8, 8_0.linux.8_6, 8_0.linux.ubuntu22_04, 8_0.linux.ubuntu_lts, 8_0.linux.sles15sp4, 8_0.linux.sles_lts, 8_0.linux.opensuse15_5, 8_0.windows.win2022, 8_0.windows.win11, 8_0.windows.win2016, 8_0.windows.win2025 variants: - linux: os_type = "linux" @@ -108,27 +108,39 @@ - 5_11: os_version = "rhel5.11" enable_legacy_policy = yes - - debian: + - debian11_7: only source_esx.esx_80 - os_version = "DEBIAN_VERSION" + #os_short_id = "debian11" + os_version = "debian11.7.0" + - debian_lts: + only source_esx.esx_80 + os_version = "DEBIAN_LTS_VERSION" + - ubuntu22_04: + only source_esx.esx_80 + os_short_id = "ubuntu22.04" + os_version = "ubuntu22.04" - ubuntu_lts: only source_esx.esx_80 os_version = "UBUNTU_LTS_VERSION" - - sles12sp4: - only source_esx.esx_67, source_esx.esx_70 - os_version = "sles12sp4" - sles12sp5: only source_esx.esx_80 os_version = "sles12sp5" - - sles_latest: + - sles15sp4: + only source_esx.esx_80 + os_short_id = "sles15sp4" + os_version = "sles15sp4" + - sles_lts: only source_esx.esx_80 os_version = "SLES_LATEST_VERSION" - opensuse_latest: - only source_esx.esx_67, source_esx.esx_70, source_esx.esx_80 + only source_esx.esx_70, source_esx.esx_80 os_version = "OPENSUSE_LATEST_VERSION" - opensuse15_4: - only source_esx.esx_67, source_esx.esx_70 + only source_esx.esx_70 os_version = "opensuse15.4" + - opensuse15_5: + only source_esx.esx_80 + os_version = "opensuse15.5" - windows: no pv os_type = "windows" From 222ca05147268fd7c6f8213b3e0f5dd7091a8e89 Mon Sep 17 00:00:00 2001 From: slancast Date: Mon, 17 Jun 2024 10:31:40 -0400 Subject: [PATCH 0413/1055] vcpu_misc.cfg, fix for cpu model on maxphysaddr case --- libvirt/tests/cfg/cpu/vcpu_misc.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/cfg/cpu/vcpu_misc.cfg b/libvirt/tests/cfg/cpu/vcpu_misc.cfg index 265dd10fd10..4a03b27fcb4 100644 --- a/libvirt/tests/cfg/cpu/vcpu_misc.cfg +++ b/libvirt/tests/cfg/cpu/vcpu_misc.cfg @@ -35,6 +35,7 @@ expected_str_after_startup = 'mode="host-passthrough"' customize_cpu_features = "yes" - with_maxphysaddr: + cpu_mode = "host-model" no s390-virtio,aarch64 func_supported_since_libvirt_ver = (9, 3, 0) maxphysaddr = {'mode': 'passthrough', 'limit':'%d'} From e2cc5198370f7672e2f862537f5a7f96411848b1 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Mon, 17 Jun 2024 21:58:25 -0400 Subject: [PATCH 0414/1055] Snapshot_revert: fix "list index out of range" issue Now the revert_snap_with_flags test can not be tested in x86 because no flags list in cfg file. Now add it to fix. Signed-off-by: Meina Li --- libvirt/tests/cfg/snapshot/revert_snap_with_flags.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/cfg/snapshot/revert_snap_with_flags.cfg b/libvirt/tests/cfg/snapshot/revert_snap_with_flags.cfg index 3ca0439c02d..ceb62c9de10 100644 --- a/libvirt/tests/cfg/snapshot/revert_snap_with_flags.cfg +++ b/libvirt/tests/cfg/snapshot/revert_snap_with_flags.cfg @@ -7,6 +7,7 @@ vars_path = "/var/lib/libvirt/qemu/nvram/${main_vm}_VARS.fd" snap1_options = "%s --diskspec vda,snapshot=external,file=/tmp/vda.%s" snap2_options = "%s --memspec snapshot=external,file=/tmp/mem.%s --diskspec vda,snapshot=external,file=/tmp/vda.%s" + flags = [" --current --paused"," --running --reset-nvram", " --force"] func_supported_since_libvirt_ver = (9, 10, 0) s390-virtio: vars_path = From 60c123bc0165e8aa0a3862ce444b000fe6602e6a Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Mon, 3 Jun 2024 22:06:50 +0800 Subject: [PATCH 0415/1055] virtual_disks: Add vm lifecycle test for vhostvdpa disk This PR adds: VIRT-300443 - Vm lifecycle test with disk of vhostvdpa backend Signed-off-by: Yingshun Cui --- .../vm_lifecycle_vhostvdpa_backend_disk.cfg | 9 ++ .../vm_lifecycle_vhostvdpa_backend_disk.py | 85 +++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/vm_lifecycle_vhostvdpa_backend_disk.cfg create mode 100644 libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/vm_lifecycle_vhostvdpa_backend_disk.py diff --git a/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/vm_lifecycle_vhostvdpa_backend_disk.cfg b/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/vm_lifecycle_vhostvdpa_backend_disk.cfg new file mode 100644 index 00000000000..fea95cd88b0 --- /dev/null +++ b/libvirt/tests/cfg/virtual_disks/vhostvdpa_block_backend_type/vm_lifecycle_vhostvdpa_backend_disk.cfg @@ -0,0 +1,9 @@ +- virtual_disks.vhostvdpa.lifecycle: + type = vm_lifecycle_vhostvdpa_backend_disk + start_vm = no + simulator = "yes" + disk_vdpa_attrs = {"source": {"attrs": {"dev": "/dev/vhost-vdpa-0"}}, "type_name": "vhostvdpa"} + disk_driver = {"driver": {"name": "qemu", "type": "raw", "cache": "none", "io": "threads", "copy_on_read": "on", "discard": "unmap", "detect_zeroes": "on"}} + disk_attrs = {"device": "disk", "target": {"dev": "vdb", "bus": "virtio"}, **${disk_vdpa_attrs}, **${disk_driver}} + func_supported_since_libvirt_ver = (9, 10, 0) + only x86_64 diff --git a/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/vm_lifecycle_vhostvdpa_backend_disk.py b/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/vm_lifecycle_vhostvdpa_backend_disk.py new file mode 100644 index 00000000000..b3620271bc6 --- /dev/null +++ b/libvirt/tests/src/virtual_disks/vhostvdpa_block_backend_type/vm_lifecycle_vhostvdpa_backend_disk.py @@ -0,0 +1,85 @@ +import os +from virttest import data_dir +from virttest import libvirt_version +from virttest import utils_disk +from virttest import utils_vdpa +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_disk +from virttest.utils_libvirt import libvirt_vmxml + +VIRSH_ARGS = {'debug': True, 'ignore_status': False} + + +def run(test, params, env): + """ + Verify vm lifecycle operations + """ + def check_disk_io(vm_session, disk, cmd_in_vm, mount_dst="/mnt", is_mount=True): + """ + Check disk I/O in guest + + :param vm_session: vm session + :param disk: disk name + :param cmd_in_vm: cmd to check disk io + :param mount_dst: mount destination + :param is_mount: Whether the disk is mounted + """ + if is_mount: + if not utils_disk.is_mount(f"/dev/{disk}", mount_dst, session=vm_session): + test.fail("%s should be mounted!" % disk) + else: + utils_disk.mount(f"/dev/{disk}", mount_dst, session=vm_session) + vm_session.cmd(cmd_in_vm) + + libvirt_version.is_libvirt_feature_supported(params) + disk_attrs = eval(params.get("disk_attrs", "{}")) + cmd_in_vm = "d=`date +%s`; echo $d >> /mnt/test ;sync; grep $d /mnt/test" + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + test.log.info("TEST_STEP: Define a VM with vhostvdpa disk.") + test_env_obj = utils_vdpa.VDPASimulatorTest( + sim_dev_module="vdpa_sim_blk", mgmtdev="vdpasim_blk") + test_env_obj.setup() + vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", hpgs=False) + libvirt_vmxml.modify_vm_device(vm_xml.VMXML.new_from_dumpxml(vm_name), "disk", disk_attrs, 1) + + test.log.info("TEST_STEP: Start the VM, and check vhostvdpa disk r/w.") + vm.start() + vm_session = vm.wait_for_login() + new_disk = libvirt_disk.get_non_root_disk_name(vm_session)[0] + vm_session.cmd(f"mkfs.ext4 /dev/{new_disk}") + check_disk_io(vm_session, new_disk, cmd_in_vm, is_mount=False) + + test.log.info("TEST_STEP: Save and restore VM, check vhostvdpa disk r/w.") + save_path = os.path.join(data_dir.get_tmp_dir(), vm.name + '.save') + virsh.save(vm.name, save_path, **VIRSH_ARGS) + virsh.restore(save_path, **VIRSH_ARGS) + check_disk_io(vm_session, new_disk, cmd_in_vm) + + test.log.info("TEST_STEP: ManagedSave and Start VM, check vhostvdpa disk r/w.") + virsh.managedsave(vm.name, **VIRSH_ARGS) + virsh.start(vm.name, **VIRSH_ARGS) + check_disk_io(vm_session, new_disk, cmd_in_vm) + + test.log.info("TEST_STEP: Reboot VM, check vhostvdpa disk r/w.") + virsh.reboot(vm.name, **VIRSH_ARGS) + vm_session = vm.wait_for_login() + check_disk_io(vm_session, new_disk, cmd_in_vm, is_mount=False) + + test.log.info("TEST_STEP: Shutdown and start VM, check vhostvdpa disk r/w.") + virsh.shutdown(vm.name, wait_for_event=True, + event_type="disconnected.*(\n.*)*Shutdown Finished.*(\n.*)*Stopped", + **VIRSH_ARGS) + virsh.start(vm.name, **VIRSH_ARGS) + vm_session = vm.wait_for_login() + check_disk_io(vm_session, new_disk, cmd_in_vm, is_mount=False) + utils_disk.umount(f"/dev/{new_disk}", "/mnt", session=vm_session) + finally: + bkxml.sync() + test_env_obj.cleanup() From 2480c1776c54f6ad98372574b85e1e4851d75876 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Tue, 18 Jun 2024 15:22:04 +0800 Subject: [PATCH 0416/1055] aarch64_cpu_sve: fix to add err msg checking Add the error message checking when enable sve in a guest while the host does not support sve feature Signed-off-by: Dan Zheng --- libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg | 1 + libvirt/tests/src/cpu/aarch64_cpu_sve.py | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg b/libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg index f050e4a7757..de729917ac7 100644 --- a/libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg +++ b/libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg @@ -70,3 +70,4 @@ - no_host_sve_support: host_without_sve = "yes" status_error = "yes" + expect_msg = ".*sve.* feature not supported by KVM" diff --git a/libvirt/tests/src/cpu/aarch64_cpu_sve.py b/libvirt/tests/src/cpu/aarch64_cpu_sve.py index 023f939f939..7a21053ed3a 100644 --- a/libvirt/tests/src/cpu/aarch64_cpu_sve.py +++ b/libvirt/tests/src/cpu/aarch64_cpu_sve.py @@ -233,10 +233,16 @@ def update_cpu_xml(cpu_xml, params, test, supported_list, unsupported_list): :param supported_list: list, sve lengths supported :param unsupported_list: list, sve lengths unsupported """ - # For sve, each SVE vector_length is a feature name - # E.g. sve128 sve256 sve512 - # Test unsupported vector length - vector_list = gen_cpu_features(supported_list, unsupported_list, params, test) + if not supported_list and not unsupported_list: + # There is no sve support on the host. + # This is to expect an error message with sve=require + # when starting the vm. + vector_list = [{'sve': params.get("cpu_xml_policy")}] + else: + vector_list = gen_cpu_features(supported_list, + unsupported_list, + params, + test) for vector in vector_list: for length, policy in vector.items(): cpu_xml.add_feature(length, policy) @@ -374,9 +380,13 @@ def run(test, params, env): sve_stress_exec_cmd = params.get("sve_stress_exec_cmd") optimized_execute_cmd = params.get("optimized_execute_cmd") target_dir = params.get("target_dir") + host_without_sve = "yes" == params.get("host_without_sve") + supported_list = None + unsupported_list = None prepare_env(vm, params, test) - supported_list, unsupported_list = get_vector_lengths(vm_name) + if not host_without_sve: + supported_list, unsupported_list = get_vector_lengths(vm_name) if vm.is_alive(): vm.destroy(gracefully=False) From 443710e9fa8354205cc00e42624e28f80236cc92 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Wed, 19 Jun 2024 12:18:06 +0800 Subject: [PATCH 0417/1055] aarch64_cpu_sve: add sve-ptrace test Signed-off-by: Dan Zheng --- libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg | 14 +++--- libvirt/tests/src/cpu/aarch64_cpu_sve.py | 59 ++++++++++++++++++----- 2 files changed, 56 insertions(+), 17 deletions(-) diff --git a/libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg b/libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg index f050e4a7757..d084ac24778 100644 --- a/libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg +++ b/libvirt/tests/cfg/cpu/aarch64_cpu_sve.cfg @@ -55,18 +55,20 @@ optimized_echo_cmd = "echo 'CFLAGS += -march=armv8.2-a+sve' >> config.mk" optimized_compile_cmd = "cd ${target_dir}; cp config.mk.dist config.mk; ${optimized_echo_cmd}; make" optimized_execute_cmd = "cd ${target_dir}; make check 2>/dev/null" - - sve_stress: + - sve_selftests_in_kernel: status_error = "no" all_supports = "yes" install_pkgs = ["git", "gcc", "make", "kernel-devel", "kernel-headers", "rsync", "brewkoji", "tar"] target_dir = "/home/sve_stress" - suite_dir = "${target_dir}/tools/testing/selftests/arm64/fp" - sve_exec_timeout = 360 - sve_stress_download_cmd = "cd /var/tmp && brew download-build --rpm %s && rpm2cpio %s | cpio -idm" - sve_stress_tar_cmd = "cd /var/tmp && tar Jxf %s --strip-components 1 -C ${target_dir}" - sve_stress_compile_cmd = "cd ${suite_dir}; make" + kernel_testing_dir = "${target_dir}/tools/testing" + suite_dir = "${kernel_testing_dir}/selftests/arm64/fp" + sve_exec_timeout = 240 + kernel_download_cmd = "cd /var/tmp && brew download-build --rpm %s && rpm2cpio %s | cpio -idm" + kernel_tar_cmd = "cd /var/tmp && tar Jxf %s --strip-components 1 -C ${target_dir}" + kernel_selftest_compile_cmd = "cd ${kernel_testing_dir}; make all -C selftests/ TARGETS=arm64" sve_stress_get_lenths = "${suite_dir}/sve-probe-vls" sve_stress_exec_cmd = "cd ${suite_dir}; timeout ${sve_exec_timeout} ./vlset --inherit %s ./sve-stress 2>/dev/null" + sve_ptrace_exec_cmd = "cd ${suite_dir}; ./sve-ptrace" - no_host_sve_support: host_without_sve = "yes" status_error = "yes" diff --git a/libvirt/tests/src/cpu/aarch64_cpu_sve.py b/libvirt/tests/src/cpu/aarch64_cpu_sve.py index 023f939f939..057eb33d999 100644 --- a/libvirt/tests/src/cpu/aarch64_cpu_sve.py +++ b/libvirt/tests/src/cpu/aarch64_cpu_sve.py @@ -307,6 +307,28 @@ def execute_sve_stress_by_suite(length_list, session, params, test): test.log.debug("Verify sve stress test for length %s (in bytes) - PASS" % a_length) +def run_sve_ptrace_test_in_guest(session, params, test): + """ + Run sve_ptrace test suite within the guest + + :param session: vm session + :param params: dict, test parameters + :param test: test object + """ + sve_ptrace_exec_cmd = params.get("sve_ptrace_exec_cmd") + output = session.cmd_output(sve_ptrace_exec_cmd) + results_lines = [result for result in output.splitlines() if + result.startswith("# Totals:")] + pat = "fail:(\d+).*xfail:(\d+).*error:(\d+)" + match = re.findall(pat, results_lines[0]) + if match: + if any([int(match[0][0]), int(match[0][1]), int(match[0][2])]): + test.fail("The sve-ptrace test fail with errors:%s" % results_lines[0]) + else: + test.error("Can not get Totals: line from test result") + test.log.debug("Verify sve ptrace test - PASS") + + def verify_sve_length_by_suite(supported_list, session, params, test): """ Verify the supported sve lengths are same with test suite output @@ -331,11 +353,10 @@ def verify_sve_length_by_suite(supported_list, session, params, test): return results -def run_sve_stress_test_in_guest(supported_list, session, params, test): +def prepare_kernel_selftest_in_guest(session, params, test): """ - Run sve stress test suite within the guest + Prepare the kernel self test repo in the guest - :param supported_list: list, supported sve lengths :param session: vm session :param params: dict, test parameters :param test: test object @@ -343,14 +364,25 @@ def run_sve_stress_test_in_guest(supported_list, session, params, test): kernel_version = session.cmd_output("uname -r").rsplit('.', 1)[0] srpm = "kernel-%s.src.rpm" % kernel_version linux_name = "linux-%s.tar.xz" % kernel_version - sve_stress_download_cmd = params.get("sve_stress_download_cmd") % (srpm, - srpm) - sve_stress_tar_cmd = params.get("sve_stress_tar_cmd") % linux_name - sve_stress_compile_cmd = params.get("sve_stress_compile_cmd") - - execute_cmds(sve_stress_download_cmd, session, test) - execute_cmds(sve_stress_tar_cmd, session, test) - execute_cmds(sve_stress_compile_cmd, session, test) + kernel_download_cmd = params.get("kernel_download_cmd") % (srpm, + srpm) + kernel_tar_cmd = params.get("kernel_tar_cmd") % linux_name + kernel_selftest_compile_cmd = params.get("kernel_selftest_compile_cmd") + + execute_cmds(kernel_download_cmd, session, test) + execute_cmds(kernel_tar_cmd, session, test) + execute_cmds(kernel_selftest_compile_cmd, session, test) + + +def run_sve_stress_test_in_guest(supported_list, session, params, test): + """ + Run sve stress test suite within the guest + + :param supported_list: list, supported sve lengths + :param session: vm session + :param params: dict, test parameters + :param test: test object + """ sve_lengths = verify_sve_length_by_suite(supported_list, session, params, test) execute_sve_stress_by_suite(sve_lengths, session, params, test) @@ -372,6 +404,7 @@ def run(test, params, env): expect_msg = params.get("expect_msg", "") vector_length = params.get("vector_length", "sve") sve_stress_exec_cmd = params.get("sve_stress_exec_cmd") + sve_ptrace_exec_cmd = params.get("sve_ptrace_exec_cmd") optimized_execute_cmd = params.get("optimized_execute_cmd") target_dir = params.get("target_dir") @@ -431,8 +464,12 @@ def run(test, params, env): if target_dir: execute_cmds("mkdir -p %s" % target_dir, session, test) + if params.get("kernel_testing_dir"): + prepare_kernel_selftest_in_guest(session, params, test) if sve_stress_exec_cmd: run_sve_stress_test_in_guest(supported_list, session, params, test) + if sve_ptrace_exec_cmd: + run_sve_ptrace_test_in_guest(session, params, test) if optimized_execute_cmd: run_optimized_routines_in_guest(session, params, test) execute_cmds("rm -rf %s" % target_dir, session, test) From 25cfefeb723e903e8d8bf11fffa318ee28900775 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Wed, 19 Jun 2024 22:02:57 -0400 Subject: [PATCH 0418/1055] Wait for virtio-mem device memory to be allocated for guest Signed-off-by: liang-cong-red-hat --- .../change_virtio_mem_request_size.py | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py b/libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py index 8f5bdd6b5fe..98b4463089a 100644 --- a/libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py +++ b/libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py @@ -8,11 +8,10 @@ # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ import re -import time -from avocado.utils import cpu from avocado.utils import memory +from virttest import utils_misc from virttest import virsh from virttest.libvirt_xml import vm_xml @@ -240,6 +239,28 @@ def update_and_check_memory_size(test, params, session, update_device, return new_mem_total +def check_delayed_current(test, params, mem_index, expected_current_size): + """ + Check the virtio memory current value. + :param test: test object. + :param params: dictionary with the test parameters. + :param expected_current_size, expected current size value. + :param mem_index, Check after or before attaching memory device. + """ + vm_name = params.get("main_vm") + + def _get_virtio_current(): + return vm_xml.VMXML.new_from_dumpxml( + vm_name).devices.by_device_tag("memory")[ + mem_index].target.current_size + + if not utils_misc.wait_for( + lambda: expected_current_size == _get_virtio_current(), 20): + test.fail( + "Attached virtio memory current size should be %s" % expected_current_size) + test.log.debug("Checked attached virtio memory current size successfully") + + def run(test, params, env): """ Verify virtio-mem memory device requested memory size could be changed @@ -295,10 +316,9 @@ def run_test_running_guest(): params.get('request_size'), params.get('default_pagesize')))) virsh.attach_device(vm.name, mem_obj.xml, wait_for_event=True, **VIRSH_ARGS) + check_delayed_current(test, params, 1, int(params.get('request_size'))) test.log.info("TEST_STEP4: Get the first time total memory in guest") - if cpu.get_arch().startswith("aarch"): - time.sleep(7) mem_total_1 = int(utils_memory.memtotal(session)) test.log.info("TEST_STEP5,6: Change the first virtio-mem requested size" From 00960a5a317f138f302f9c7c7f571524668069d3 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Thu, 20 Jun 2024 10:20:10 +0800 Subject: [PATCH 0419/1055] host_numa_info: enable 4k test Signed-off-by: Dan Zheng --- .../cfg/numa/host_numa/host_numa_info.cfg | 26 ++++++++++++------- .../src/numa/host_numa/host_numa_info.py | 6 +++++ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/libvirt/tests/cfg/numa/host_numa/host_numa_info.cfg b/libvirt/tests/cfg/numa/host_numa/host_numa_info.cfg index 62763d494ed..811e5695cbc 100644 --- a/libvirt/tests/cfg/numa/host_numa/host_numa_info.cfg +++ b/libvirt/tests/cfg/numa/host_numa/host_numa_info.cfg @@ -3,13 +3,21 @@ take_regular_screendumps = no start_vm = "no" no s390-virtio - variants: - - default: - allocate_dict = {2048: 200, 1048576: 2} - aarch64: - allocate_dict = {2048: 200, 524288: 4} - - 16G: + variants kernel_size: + - 4k: + default_pagesize = 4 + variants: + - all_hugepages: + allocate_dict = {2048: 200, 1048576: 2} + aarch64: + allocate_dict = {64: 100, 2048: 100, 32768: 4, 1048576: 1} + - 64k: only aarch64 - required_kernel = [5.14.0,) - expect_nodes_num = 1 - allocate_dict = {16777216: 1} + default_pagesize = 64 + variants: + - all_hugepages: + required_kernel = [5.14.0,) + expect_nodes_num = 1 + allocate_dict = {2048: 200, 524288: 4, 16777216: 1} + - 512M_2M: + allocate_dict = {2048: 200, 524288: 4} diff --git a/libvirt/tests/src/numa/host_numa/host_numa_info.py b/libvirt/tests/src/numa/host_numa/host_numa_info.py index 2dbedc5ba21..98eeff27d4e 100644 --- a/libvirt/tests/src/numa/host_numa/host_numa_info.py +++ b/libvirt/tests/src/numa/host_numa/host_numa_info.py @@ -382,6 +382,12 @@ def run(test, params, env): """ Test numa topology together with cpu topology """ + default_pagesize = int(params.get("default_pagesize")) * 1024 + default_kernel_pagesize = mem_utils.get_page_size() + if default_pagesize != default_kernel_pagesize: + test.cancel("The case does not support on " + "current host kernel " + "size %d" % default_kernel_pagesize) vm_name = params.get("main_vm") vm = env.get_vm(vm_name) numatest_obj = numa_base.NumaTest(vm, params, test) From dce6bbf6e6127b185f70bdf444031462a9fbe925 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Thu, 20 Jun 2024 05:03:09 -0400 Subject: [PATCH 0420/1055] storage_ceph: use xargs instead of parallel as a tool of parallel testing Parallel package sometimes is not included in the new compose. So use xargs to have a stable test for tihs case. Signed-off-by: Meina Li --- libvirt/tests/cfg/storage/virsh_pool.cfg | 2 +- libvirt/tests/deps/cve_2023_3750.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/storage/virsh_pool.cfg b/libvirt/tests/cfg/storage/virsh_pool.cfg index 49f688c3756..f7a85cad26e 100644 --- a/libvirt/tests/cfg/storage/virsh_pool.cfg +++ b/libvirt/tests/cfg/storage/virsh_pool.cfg @@ -15,7 +15,7 @@ func_supported_since_libvirt_ver = (9, 5, 0) parallel_executable_path = '../../deps/cve_2023_3750.sh' pool_type = 'rbd' - required_commands = "['parallel', 'rbd']" + required_commands = "['rbd']" auth_key = "EXAMPLE_AUTH_KEY" auth_user = "EXAMPLE_AUTH_USER" client_name = "EXAMPLE_CLIENT_NAME" diff --git a/libvirt/tests/deps/cve_2023_3750.sh b/libvirt/tests/deps/cve_2023_3750.sh index 63ef3b29caa..2f46c84c87c 100644 --- a/libvirt/tests/deps/cve_2023_3750.sh +++ b/libvirt/tests/deps/cve_2023_3750.sh @@ -7,7 +7,7 @@ POOL=$1 VOL=$2 function test_run() { while true;do - parallel -N0 "virsh -r 'pool-list; vol-info --pool $1 $2'" ::: {1..100} + seq 1 100 | xargs -n 1 -P 10 -I {} sh -c 'virsh -r "pool-list; vol-info --pool $1 --vol $2"' -- $1 $2 done } From 062b69d1465fbc2d51869dcc6849f60437794aea Mon Sep 17 00:00:00 2001 From: Kowshik Jois B S Date: Thu, 20 Jun 2024 20:39:27 +0530 Subject: [PATCH 0421/1055] Fixed a spelling mistake Description: remote_ip was wrongly typed as rempte_ip. Have fixed it with this PR Signed-off-by: Kowshik Jois B S --- libvirt/tests/src/virsh_cmd/host/virsh_hostname.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/host/virsh_hostname.py b/libvirt/tests/src/virsh_cmd/host/virsh_hostname.py index 74ba887aed2..e667b537b18 100644 --- a/libvirt/tests/src/virsh_cmd/host/virsh_hostname.py +++ b/libvirt/tests/src/virsh_cmd/host/virsh_hostname.py @@ -30,7 +30,7 @@ def run(test, params, env): remote_uri = params.get("remote_uri", None) if remote_uri and remote_ip.count("EXAMPLE"): - test.cancel("Pls configure rempte_ip first") + test.cancel("Pls configure remote_ip first") session = None if remote_uri: From 7e342ac5663083f3a17ea5f78e0b3fba22d8ed25 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Fri, 21 Jun 2024 03:21:01 -0400 Subject: [PATCH 0422/1055] Add nvdimm pmem support check Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/memory/nvdimm.cfg | 1 + libvirt/tests/src/memory/nvdimm.py | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/libvirt/tests/cfg/memory/nvdimm.cfg b/libvirt/tests/cfg/memory/nvdimm.cfg index 0a353d31848..3e636a835a3 100644 --- a/libvirt/tests/cfg/memory/nvdimm.cfg +++ b/libvirt/tests/cfg/memory/nvdimm.cfg @@ -48,6 +48,7 @@ error_msg = 'discard is not supported for nvdimms' - pmem_alignsize: check = pmem_alignsize + pmem_support_check_cmd = "yum deplist qemu-kvm-core | grep libpmem" nvdimm_file_path = '/tmp/nvdimm' alignsize = 2048 vm_attrs = {'max_mem_rt': 8192, 'max_mem_rt_slots': 8, 'max_mem_rt_unit': 'M', 'vcpu': 4, 'cpu': {'mode': '${cpuxml_mode}', 'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '2097152', 'unit': 'K'}, {'id': '1', 'cpus': '2-3', 'memory': '2097152', 'unit': 'K'}]}} diff --git a/libvirt/tests/src/memory/nvdimm.py b/libvirt/tests/src/memory/nvdimm.py index c0b585f1408..0fa0d8aba6e 100644 --- a/libvirt/tests/src/memory/nvdimm.py +++ b/libvirt/tests/src/memory/nvdimm.py @@ -133,6 +133,18 @@ def check_nvdimm_file(test_str, file_name, vm_session, test): test.fail('"%s" should be in output' % test_str) +def is_pmem_supported(params): + """ + check if pmem is supported by qemu-kvm + + :param params: dict, test parameters + :return: whether pmem is supported + """ + pmem_support_check_cmd = params.get('pmem_support_check_cmd') + cmd_result = process.run(pmem_support_check_cmd, ignore_status=True, shell=True) + return not cmd_result.exit_status + + def setup_test_pmem_alignsize(guest_xml, params): """ Setup steps for pmem and alignsize test @@ -143,6 +155,10 @@ def setup_test_pmem_alignsize(guest_xml, params): """ vm_attrs = eval(params.get('vm_attrs', '{}')) mem_device_attrs = eval(params.get('mem_device_attrs', '{}')) + if not is_pmem_supported(params): + mem_device_attrs['source']['pmem'] = False + params.update({'qemu_checks': params.get('qemu_checks').replace('pmem', '')}) + if vm_attrs: guest_xml.setup_attrs(**vm_attrs) if mem_device_attrs: From 8c817ccad89c7b98a32a5a469db975bb4f20eb0f Mon Sep 17 00:00:00 2001 From: Meina Li Date: Fri, 21 Jun 2024 03:26:51 -0400 Subject: [PATCH 0423/1055] graphical_framebuffers: fix virtqemud service failed issue with vnc_tls_x509_verify The virtqemud service restarts failed when testing vnc_only.vnc_tls_x509_verify related issues. That's because the vnc_tls_x509_verify in qemu_config will be deleted in the next "if vnc_tls_x509_secret_uuid == "not_set" statement. Here update it to the correct one vnc_tls_x509_secret_uuid. Signed-off-by: Meina Li --- libvirt/tests/src/graphics/graphics_functional.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/graphics/graphics_functional.py b/libvirt/tests/src/graphics/graphics_functional.py index 3c5e9b41379..23d933071c1 100644 --- a/libvirt/tests/src/graphics/graphics_functional.py +++ b/libvirt/tests/src/graphics/graphics_functional.py @@ -209,7 +209,7 @@ def __init__(self, params, expected_result): self.qemu_config.vnc_tls_x509_verify = tls_x509_verify if vnc_tls_x509_secret_uuid == "not_set": - del self.qemu_config.vnc_tls_x509_verify + del self.qemu_config.vnc_tls_x509_secret_uuid else: self.qemu_config.vnc_tls = "1" if vnc_secret_uuid == "invalid": From 065a94050aeb8d6c644ed227e6a6a19926634b8d Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Mon, 24 Jun 2024 11:15:50 +0800 Subject: [PATCH 0424/1055] Refactor iommu migration case Signed-off-by: Yingshun Cui --- libvirt/tests/src/sriov/vIOMMU/migration_iommu_device.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/src/sriov/vIOMMU/migration_iommu_device.py b/libvirt/tests/src/sriov/vIOMMU/migration_iommu_device.py index f9bc95a9751..d58ad868d88 100644 --- a/libvirt/tests/src/sriov/vIOMMU/migration_iommu_device.py +++ b/libvirt/tests/src/sriov/vIOMMU/migration_iommu_device.py @@ -1,11 +1,10 @@ -from virttest import libvirt_version from virttest import virsh from virttest.libvirt_xml import vm_xml from virttest.utils_libvirt import libvirt_vmxml -from provider.sriov import sriov_base from provider.migration import base_steps +from provider.viommu import viommu_base def run(test, params, env): @@ -65,14 +64,13 @@ def setup_test(): "interface", iface_dict) migration_obj.setup_default() - libvirt_version.is_libvirt_feature_supported(params) cleanup_ifaces = "yes" == params.get("cleanup_ifaces", "yes") iommu_dict = eval(params.get('iommu_dict', '{}')) iface_dict = eval(params.get('iface_dict', '{}')) vm_name = params.get("main_vm", "avocado-vt-vm1") vm = env.get_vm(vm_name) - test_obj = sriov_base.SRIOVTest(vm, test, params) + test_obj = viommu_base.VIOMMUTest(vm, test, params) migration_obj = base_steps.MigrationBase(test, vm, params) try: From 7dcd8c62435afadef3e741bfa879bebfbcff2ea0 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Mon, 24 Jun 2024 17:39:00 +0800 Subject: [PATCH 0425/1055] Check v2v version correctly Signed-off-by: Ming Xie --- v2v/tests/cfg/v2v_options.cfg | 1 + v2v/tests/src/v2v_options.py | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/v2v/tests/cfg/v2v_options.cfg b/v2v/tests/cfg/v2v_options.cfg index c4ff7d73ad6..ed90842f18e 100644 --- a/v2v/tests/cfg/v2v_options.cfg +++ b/v2v/tests/cfg/v2v_options.cfg @@ -136,6 +136,7 @@ only input_mode.none only output_mode.none v2v_options = "--version" + checkpoint = check_version - option_help: only input_mode.none only output_mode.none diff --git a/v2v/tests/src/v2v_options.py b/v2v/tests/src/v2v_options.py index 1cedbb26827..2fc89a5dfa0 100644 --- a/v2v/tests/src/v2v_options.py +++ b/v2v/tests/src/v2v_options.py @@ -582,6 +582,12 @@ def check_alloc(): if not check_result: test.fail( 'Not found disk or xml created by virt-v2v-copy-to-local') + if checkpoint == 'check_version': + get_v2v_version = process.run('rpm -q virt-v2v', shell=True, ignore_status=True) + if (''.join(filter(str.isdigit, str(output_stdout)))[1:4] + + ''.join(filter(str.isdigit, str(output_stdout)))[5]) != \ + ''.join(filter(str.isdigit, str(get_v2v_version.stdout)))[1:5]: + test.fail('v2v version is incorrect in v2v version option') log_check = utils_v2v.check_log(params, output) if log_check: From 65b0922aa97a428d301e124d5bd9ebe1b96724ea Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 24 Jun 2024 18:20:09 +0800 Subject: [PATCH 0426/1055] migration: Add step to check userfaultfd 1. Add a new step to Check libvirt pass userfaultfd in vm namespace and qemu can access this file correctly after postcopy migration on target host. 2. Remove a redundant file. Signed-off-by: lcheng --- .../memory_copy_mode/memory_copy_mode.py | 23 ++++++- .../migration_memory_copy_mode.py | 62 ------------------- spell.ignore | 1 + 3 files changed, 23 insertions(+), 63 deletions(-) delete mode 100644 libvirt/tests/src/migration/memory_copy_mode/migration_memory_copy_mode.py diff --git a/libvirt/tests/src/migration/memory_copy_mode/memory_copy_mode.py b/libvirt/tests/src/migration/memory_copy_mode/memory_copy_mode.py index 13c51f00b98..c4f2f6f699d 100644 --- a/libvirt/tests/src/migration/memory_copy_mode/memory_copy_mode.py +++ b/libvirt/tests/src/migration/memory_copy_mode/memory_copy_mode.py @@ -1,3 +1,6 @@ +from virttest import libvirt_version +from virttest import remote + from provider.migration import base_steps from provider.migration import migration_base @@ -10,7 +13,22 @@ def run(test, params, env): :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ + def verify_postcopy(): + """ + Verify for postcopy migration + + """ + test.log.info("Verify steps.") + migration_obj.verify_default() + + if libvirt_version.version_compare(10, 1, 0): + # Check libvirt pass userfaultfd in vm namespace and qemu can access + # this file correctly after postcopy migration on target host. + cmd = "nsenter -a -t `pidof qemu-kvm` lsof /dev/userfaultfd" + remote.run_remote_cmd(cmd, params, ignore_status=False) + vm_name = params.get("migrate_main_vm") + test_case = params.get('test_case', '') virsh_session = None remote_virsh_session = None @@ -18,12 +36,15 @@ def run(test, params, env): vm = env.get_vm(vm_name) migration_obj = base_steps.MigrationBase(test, vm, params) + verify_test = eval("verify_%s" % test_case) if "verify_%s" % test_case in \ + locals() else migration_obj.verify_default + try: migration_obj.setup_connection() # Monitor event on source/target host virsh_session, remote_virsh_session = migration_base.monitor_event(params) migration_obj.run_migration() - migration_obj.verify_default() + verify_test() migration_base.check_event_output(params, test, virsh_session, remote_virsh_session) finally: migration_obj.cleanup_connection() diff --git a/libvirt/tests/src/migration/memory_copy_mode/migration_memory_copy_mode.py b/libvirt/tests/src/migration/memory_copy_mode/migration_memory_copy_mode.py deleted file mode 100644 index e2e7c8d736e..00000000000 --- a/libvirt/tests/src/migration/memory_copy_mode/migration_memory_copy_mode.py +++ /dev/null @@ -1,62 +0,0 @@ -import re - -from virttest import libvirt_version -from virttest import virsh - -from provider.migration import base_steps - -event_session = None - - -def run(test, params, env): - """ - Test live migration with precopy/postcopy. - - :param test: test object - :param params: Dictionary with the test parameters - :param env: Dictionary with test environment. - """ - def setup_postcopy_migration(): - """ - Setup for postcopy migration - """ - expected_event_src = params.get("expected_event_src") - if expected_event_src: - cmd = "event --loop --all" - global event_session - event_session = virsh.VirshSession(virsh_exec=virsh.VIRSH_EXEC, - auto_close=True) - event_session.sendline(cmd) - migration_obj.setup_connection() - - def verify_postcopy_migration(): - """ - Verify for postcopy migration - """ - expected_event_src = params.get("expected_event_src") - if expected_event_src: - global event_session - src_output = event_session.get_stripped_output() - test.log.debug("Event output on source: %s", src_output) - if not re.findall(expected_event_src, src_output): - test.fail("Unable to find event {}".format(expected_event_src)) - migration_obj.verify_default() - - libvirt_version.is_libvirt_feature_supported(params) - - test_case = params.get('test_case', '') - vm_name = params.get("migrate_main_vm") - - vm = env.get_vm(vm_name) - migration_obj = base_steps.MigrationBase(test, vm, params) - setup_test = eval("setup_%s" % test_case) if "setup_%s" % test_case in \ - locals() else migration_obj.setup_connection - verify_test = eval("verify_%s" % test_case) if "verify_%s" % test_case in \ - locals() else migration_obj.verify_default - - try: - setup_test() - migration_obj.run_migration() - verify_test() - finally: - migration_obj.cleanup_connection() diff --git a/spell.ignore b/spell.ignore index 940180c5af6..2428d253562 100644 --- a/spell.ignore +++ b/spell.ignore @@ -1243,3 +1243,4 @@ buitin Meina meili ntp +userfaultfd From d6bf2b6731a4582c72b6fe19917f9a8a65292e7a Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 21 Jun 2024 15:44:38 +0800 Subject: [PATCH 0427/1055] Refactor vIOMMU test code Signed-off-by: Yingshun Cui --- ...{sriov_iommu_alias.cfg => iommu_alias.cfg} | 4 +- .../sriov/vIOMMU/iommu_device_lifecycle.cfg | 1 + .../sriov/vIOMMU/iommu_device_settings.cfg | 2 + ...irtio_iommu_with_addtional_attributes.cfg} | 4 +- .../src/sriov/vIOMMU/intel_iommu_aw_bits.py | 4 +- .../{sriov_iommu_alias.py => iommu_alias.py} | 8 +- .../sriov/vIOMMU/iommu_device_lifecycle.py | 23 ++- .../src/sriov/vIOMMU/iommu_device_settings.py | 31 +++- ...virtio_iommu_with_addtional_attributes.py} | 6 +- provider/sriov/sriov_base.py | 70 -------- provider/viommu/__init__.py | 0 provider/viommu/viommu_base.py | 152 ++++++++++++++++++ 12 files changed, 211 insertions(+), 94 deletions(-) rename libvirt/tests/cfg/sriov/vIOMMU/{sriov_iommu_alias.cfg => iommu_alias.cfg} (92%) rename libvirt/tests/cfg/sriov/vIOMMU/{sriov_virtio_iommu_with_addtional_attributes.cfg => virtio_iommu_with_addtional_attributes.cfg} (84%) rename libvirt/tests/src/sriov/vIOMMU/{sriov_iommu_alias.py => iommu_alias.py} (88%) rename libvirt/tests/src/sriov/vIOMMU/{sriov_virtio_iommu_with_addtional_attributes.py => virtio_iommu_with_addtional_attributes.py} (85%) create mode 100644 provider/viommu/__init__.py create mode 100644 provider/viommu/viommu_base.py diff --git a/libvirt/tests/cfg/sriov/vIOMMU/sriov_iommu_alias.cfg b/libvirt/tests/cfg/sriov/vIOMMU/iommu_alias.cfg similarity index 92% rename from libvirt/tests/cfg/sriov/vIOMMU/sriov_iommu_alias.cfg rename to libvirt/tests/cfg/sriov/vIOMMU/iommu_alias.cfg index 104abcc8b74..566fe590693 100644 --- a/libvirt/tests/cfg/sriov/vIOMMU/sriov_iommu_alias.cfg +++ b/libvirt/tests/cfg/sriov/vIOMMU/iommu_alias.cfg @@ -1,5 +1,5 @@ -- sriov.vIOMMU.iommu.alias: - type = sriov_iommu_alias +- vIOMMU.iommu.alias: + type = iommu_alias enable_guest_iommu = "yes" func_supported_since_libvirt_ver = (8, 7, 0) start_vm = "no" diff --git a/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_lifecycle.cfg b/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_lifecycle.cfg index 1941ef66deb..b23e8ab2385 100644 --- a/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_lifecycle.cfg +++ b/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_lifecycle.cfg @@ -33,6 +33,7 @@ - hostdev_iface: only virtio no save_restore + need_sriov = "yes" iface_dict = {'managed': 'yes', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}} variants test_scenario: - save_restore: diff --git a/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg b/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg index 7164b4980b3..6886ab547a7 100644 --- a/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg +++ b/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg @@ -39,6 +39,7 @@ iface_dict = {'type_name': 'network', 'model': 'virtio', 'driver': ${interface_driver}, 'source': {'network': 'default'}} - hostdev_iface: only virtio + need_sriov = yes ping_dest = '' test_devices = ["Eth"] iface_dict = {'managed': 'yes', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}} @@ -56,6 +57,7 @@ iface_dict = {'source': {'network': 'default'}, 'driver': {'driver_attr': {'iommu': 'on'}},'type_name': 'network', 'model': 'virtio-non-transitional'} - hostdev_iface: only virtio + need_sriov = yes ping_dest = '' iface_dict = {'managed': 'yes', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}} - pcie_root_port_from_expander_bus: diff --git a/libvirt/tests/cfg/sriov/vIOMMU/sriov_virtio_iommu_with_addtional_attributes.cfg b/libvirt/tests/cfg/sriov/vIOMMU/virtio_iommu_with_addtional_attributes.cfg similarity index 84% rename from libvirt/tests/cfg/sriov/vIOMMU/sriov_virtio_iommu_with_addtional_attributes.cfg rename to libvirt/tests/cfg/sriov/vIOMMU/virtio_iommu_with_addtional_attributes.cfg index 352904ef7a0..7811bc087c2 100644 --- a/libvirt/tests/cfg/sriov/vIOMMU/sriov_virtio_iommu_with_addtional_attributes.cfg +++ b/libvirt/tests/cfg/sriov/vIOMMU/virtio_iommu_with_addtional_attributes.cfg @@ -1,5 +1,5 @@ -- sriov.vIOMMU.virtio_iommu.addtional_attributes: - type = sriov_virtio_iommu_with_addtional_attributes +- vIOMMU.virtio_iommu.addtional_attributes: + type = virtio_iommu_with_addtional_attributes start_vm = "no" enable_guest_iommu = "yes" err_msg = "iommu model 'virtio' doesn't support additional attributes" diff --git a/libvirt/tests/src/sriov/vIOMMU/intel_iommu_aw_bits.py b/libvirt/tests/src/sriov/vIOMMU/intel_iommu_aw_bits.py index 48332df3f94..fabd465b5a2 100644 --- a/libvirt/tests/src/sriov/vIOMMU/intel_iommu_aw_bits.py +++ b/libvirt/tests/src/sriov/vIOMMU/intel_iommu_aw_bits.py @@ -3,7 +3,7 @@ from virttest.libvirt_xml import vm_xml from virttest.utils_test import libvirt -from provider.sriov import sriov_base +from provider.viommu import viommu_base def run(test, params, env): @@ -17,7 +17,7 @@ def run(test, params, env): vm_name = params.get("main_vm", "avocado-vt-vm1") vm = env.get_vm(vm_name) - test_obj = sriov_base.SRIOVTest(vm, test, params) + test_obj = viommu_base.VIOMMUTest(vm, test, params) try: test_obj.setup_iommu_test(iommu_dict=iommu_dict) diff --git a/libvirt/tests/src/sriov/vIOMMU/sriov_iommu_alias.py b/libvirt/tests/src/sriov/vIOMMU/iommu_alias.py similarity index 88% rename from libvirt/tests/src/sriov/vIOMMU/sriov_iommu_alias.py rename to libvirt/tests/src/sriov/vIOMMU/iommu_alias.py index 6e7ca196cc9..d436842e6f6 100644 --- a/libvirt/tests/src/sriov/vIOMMU/sriov_iommu_alias.py +++ b/libvirt/tests/src/sriov/vIOMMU/iommu_alias.py @@ -1,4 +1,4 @@ -from provider.sriov import sriov_base +from provider.viommu import viommu_base from virttest.libvirt_xml import vm_xml @@ -41,11 +41,11 @@ def check_xml(vm, exp_alias, iommu_pci_addr): vm_name = params.get("main_vm", "avocado-vt-vm1") vm = env.get_vm(vm_name) - sriov_test_obj = sriov_base.SRIOVTest(vm, test, params) + test_obj = viommu_base.VIOMMUTest(vm, test, params) try: - sriov_test_obj.setup_iommu_test(iommu_dict=iommu_dict) + test_obj.setup_iommu_test(iommu_dict=iommu_dict) vm.start() check_xml(vm, exp_alias, iommu_has_addr) finally: - sriov_test_obj.teardown_default() + test_obj.teardown_iommu_test() diff --git a/libvirt/tests/src/sriov/vIOMMU/iommu_device_lifecycle.py b/libvirt/tests/src/sriov/vIOMMU/iommu_device_lifecycle.py index 0e88aaa8826..9b406db09be 100644 --- a/libvirt/tests/src/sriov/vIOMMU/iommu_device_lifecycle.py +++ b/libvirt/tests/src/sriov/vIOMMU/iommu_device_lifecycle.py @@ -1,7 +1,7 @@ import os -from virttest import libvirt_version from virttest import utils_misc +from virttest import utils_net from virttest import virsh from virttest.libvirt_xml import vm_xml @@ -9,7 +9,8 @@ from provider.save import save_base from provider.sriov import sriov_base -from provider.sriov import check_points +from provider.viommu import viommu_base +from provider.sriov import check_points as sriov_check_points VIRSH_ARGS = {'debug': True, 'ignore_status': False} @@ -18,18 +19,20 @@ def run(test, params, env): """ Test lifecycle for vm with vIOMMU enabled with different devices. """ - libvirt_version.is_libvirt_feature_supported(params) cleanup_ifaces = "yes" == params.get("cleanup_ifaces", "yes") ping_dest = params.get('ping_dest', "127.0.0.1") iommu_dict = eval(params.get('iommu_dict', '{}')) test_scenario = params.get("test_scenario") + need_sriov = "yes" == params.get("need_sriov", "no") vm_name = params.get("main_vm", "avocado-vt-vm1") vm = env.get_vm(vm_name) rand_id = utils_misc.generate_random_string(3) save_path = f'/var/tmp/{vm_name}_{rand_id}.save' - test_obj = sriov_base.SRIOVTest(vm, test, params) + test_obj = viommu_base.VIOMMUTest(vm, test, params) + if need_sriov: + sroiv_test_obj = sriov_base.SRIOVTest(vm, test, params) try: test.log.info("TEST_SETUP: Update VM XML.") test_obj.setup_iommu_test(iommu_dict=iommu_dict, @@ -41,6 +44,10 @@ def run(test, params, env): dev_dict = test_obj.update_disk_addr(dev_dict) libvirt_vmxml.modify_vm_device( vm_xml.VMXML.new_from_dumpxml(vm.name), dev, dev_dict) + if need_sriov: + iface_dicts = sroiv_test_obj.parse_iface_dict() + test.log.debug(iface_dicts) + test_obj.params["iface_dict"] = str(sroiv_test_obj.parse_iface_dict()) iface_dict = test_obj.parse_iface_dict() if cleanup_ifaces: libvirt_vmxml.modify_vm_device( @@ -64,7 +71,13 @@ def run(test, params, env): session = vm.wait_for_serial_login( timeout=int(params.get('login_timeout'))) - check_points.check_vm_network_accessed(session, ping_dest=ping_dest) + + if need_sriov: + sriov_check_points.check_vm_network_accessed(session, ping_dest=ping_dest) + else: + s, o = utils_net.ping(ping_dest, count=5, timeout=10, session=session) + if s: + test.fail("Failed to ping %s! status: %s, output: %s." % (ping_dest, s, o)) else: pid_ping, upsince = save_base.pre_save_setup(vm, serial=True) if test_scenario == "save_restore": diff --git a/libvirt/tests/src/sriov/vIOMMU/iommu_device_settings.py b/libvirt/tests/src/sriov/vIOMMU/iommu_device_settings.py index b29fa03da1c..3a43ceb43d7 100644 --- a/libvirt/tests/src/sriov/vIOMMU/iommu_device_settings.py +++ b/libvirt/tests/src/sriov/vIOMMU/iommu_device_settings.py @@ -1,11 +1,13 @@ -from virttest import libvirt_version from virttest import utils_disk +from virttest import utils_net from virttest.libvirt_xml import vm_xml from virttest.utils_libvirt import libvirt_vmxml from provider.sriov import sriov_base -from provider.sriov import check_points +from provider.viommu import viommu_base + +from provider.sriov import check_points as sriov_check_points def run(test, params, env): @@ -13,25 +15,37 @@ def run(test, params, env): Start vm with iommu device and kinds of virtio devices with iommu=on, and check network and disk function. """ - libvirt_version.is_libvirt_feature_supported(params) cleanup_ifaces = "yes" == params.get("cleanup_ifaces", "yes") ping_dest = params.get('ping_dest') iommu_dict = eval(params.get('iommu_dict', '{}')) test_devices = eval(params.get("test_devices", "[]")) + need_sriov = "yes" == params.get("need_sriov", "no") vm_name = params.get("main_vm", "avocado-vt-vm1") vm = env.get_vm(vm_name) - test_obj = sriov_base.SRIOVTest(vm, test, params) + sroiv_test_obj = None + + test_obj = viommu_base.VIOMMUTest(vm, test, params) + if need_sriov: + sroiv_test_obj = sriov_base.SRIOVTest(vm, test, params) + try: test_obj.setup_iommu_test(iommu_dict=iommu_dict, cleanup_ifaces=cleanup_ifaces) test_obj.prepare_controller() + for dev in ["disk", "video"]: dev_dict = eval(params.get('%s_dict' % dev, '{}')) if dev == "disk": dev_dict = test_obj.update_disk_addr(dev_dict) + libvirt_vmxml.modify_vm_device( vm_xml.VMXML.new_from_dumpxml(vm.name), dev, dev_dict) + if need_sriov: + iface_dicts = sroiv_test_obj.parse_iface_dict() + test.log.debug(iface_dicts) + test_obj.params["iface_dict"] = str(sroiv_test_obj.parse_iface_dict()) iface_dict = test_obj.parse_iface_dict() + if cleanup_ifaces: libvirt_vmxml.modify_vm_device( vm_xml.VMXML.new_from_dumpxml(vm.name), @@ -47,10 +61,15 @@ def run(test, params, env): test.log.info("TEST_STEP: Check dmesg message about iommu inside the vm.") vm_session.cmd("dmesg | grep -i 'Adding to iommu group'") - check_points.check_vm_iommu_group(vm_session, test_devices) + viommu_base.check_vm_iommu_group(vm_session, test_devices) test.log.info("TEST_STEP: Check if the VM disk and network are woring well.") utils_disk.dd_data_to_vm_disk(vm_session, "/mnt/test") - check_points.check_vm_network_accessed(vm_session, ping_dest=ping_dest) + if need_sriov: + sriov_check_points.check_vm_network_accessed(vm_session, ping_dest=ping_dest) + else: + s, o = utils_net.ping(ping_dest, count=5, timeout=10, session=vm_session) + if s: + test.fail("Failed to ping %s! status: %s, output: %s." % (ping_dest, s, o)) finally: test_obj.teardown_iommu_test() diff --git a/libvirt/tests/src/sriov/vIOMMU/sriov_virtio_iommu_with_addtional_attributes.py b/libvirt/tests/src/sriov/vIOMMU/virtio_iommu_with_addtional_attributes.py similarity index 85% rename from libvirt/tests/src/sriov/vIOMMU/sriov_virtio_iommu_with_addtional_attributes.py rename to libvirt/tests/src/sriov/vIOMMU/virtio_iommu_with_addtional_attributes.py index 708daf29b06..9bb77833952 100644 --- a/libvirt/tests/src/sriov/vIOMMU/sriov_virtio_iommu_with_addtional_attributes.py +++ b/libvirt/tests/src/sriov/vIOMMU/virtio_iommu_with_addtional_attributes.py @@ -1,4 +1,4 @@ -from provider.sriov import sriov_base +from provider.viommu import viommu_base from virttest.libvirt_xml import xcepts from virttest.utils_libvirt import libvirt_virtio @@ -13,7 +13,7 @@ def run(test, params, env): vm_name = params.get("main_vm", "avocado-vt-vm1") vm = env.get_vm(vm_name) - sriov_test_obj = sriov_base.SRIOVTest(vm, test, params) + test_obj = viommu_base.VIOMMUTest(vm, test, params) try: libvirt_virtio.add_iommu_dev(vm, iommu_dict) @@ -26,4 +26,4 @@ def run(test, params, env): else: test.fail("Defining the VM should fail, but run successfully!") finally: - sriov_test_obj.teardown_default() + test_obj.teardown_iommu_test() diff --git a/provider/sriov/sriov_base.py b/provider/sriov/sriov_base.py index 3d449f2a3f7..a908fa75ce3 100644 --- a/provider/sriov/sriov_base.py +++ b/provider/sriov/sriov_base.py @@ -18,7 +18,6 @@ from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_libvirt import libvirt_virtio from virttest.utils_libvirt import libvirt_network -from virttest.utils_libvirt import libvirt_pcicontr from provider.interface import interface_base @@ -148,8 +147,6 @@ def __init__(self, vm, test, params, session=None): self.default_vf_mac = utils_sriov.get_vf_mac( self.pf_name, session=self.session) self.vf_mac = "" - self.dev_slot = None - self.controller_dicts = eval(self.params.get("controller_dicts", "[]")) iface_attrs = self.params.get('iface_dict') if self.params.get( 'iface_dict') else self.params.get('hostdev_dict') @@ -173,30 +170,6 @@ def __init__(self, vm, test, params, session=None): def __del__(self): recover_vf(self.pf_pci, self.params, 0, session=self.session) - def update_disk_addr(self, disk_dict): - """ - Update disk address - - :param disk_dict: The original disk attrs - :return: The updated disk attrs - """ - if self.controller_dicts: - dev_bus = self.controller_dicts[-1].get('index') - dev_attrs = {'bus': dev_bus} - if disk_dict['target']['bus'] != "scsi": - dev_attrs.update({'type': self.controller_dicts[-1].get('type')}) - if self.controller_dicts[-1].get('model') == 'pcie-to-pci-bridge': - self.dev_slot = 1 - dev_attrs.update({'slot': self.dev_slot}) - - disk_dict.update({"address": {'attrs': dev_attrs}}) - if disk_dict['target']['bus'] == "scsi": - disk_dict['address']['attrs'].update({'type': 'drive'}) - - if self.controller_dicts[-1]['model'] == 'pcie-root-port': - self.controller_dicts.pop() - return disk_dict - def parse_iface_dict(self): """ Parse iface_dict from params @@ -219,15 +192,6 @@ def parse_iface_dict(self): if vf_pci_addr2.get('type'): del vf_pci_addr2['type'] iface_dict = eval(self.params.get('hostdev_dict', '{}')) - - if self.controller_dicts and iface_dict: - iface_bus = "%0#4x" % int(self.controller_dicts[-1].get('index')) - iface_attrs = {'bus': iface_bus} - if isinstance(self.dev_slot, int): - self.dev_slot += 1 - iface_attrs.update({'slot': self.dev_slot}) - iface_dict.update({"address": {'attrs': iface_attrs}}) - self.test.log.debug("iface_dict: %s.", iface_dict) return iface_dict def parse_network_dict(self): @@ -265,40 +229,6 @@ def parse_iommu_test_params(self): "br_dict": br_dict, "dev_type": dev_type} return iommu_params - def prepare_controller(self): - """ - Prepare controller(s) - - :return: Updated controller attrs - """ - if not self.controller_dicts: - return - - for contr_dict in self.controller_dicts: - pre_controller = contr_dict.get("pre_controller") - if pre_controller: - pre_contrs = list( - filter(None, [c.get('index') for c in self.controller_dicts - if c['type'] == contr_dict['type'] and - c['model'] == pre_controller])) - if pre_contrs: - pre_idx = pre_contrs[0] - else: - pre_idx = libvirt_pcicontr.get_max_contr_indexes( - vm_xml.VMXML.new_from_dumpxml(self.vm.name), - contr_dict['type'], pre_controller) - if not pre_idx: - self.test.error( - f"Unable to get index of {pre_controller} controller!") - contr_dict.pop("pre_controller") - libvirt_vmxml.modify_vm_device( - vm_xml.VMXML.new_from_dumpxml(self.vm.name), 'controller', - contr_dict, 100) - contr_dict['index'] = libvirt_pcicontr.get_max_contr_indexes( - vm_xml.VMXML.new_from_dumpxml(self.vm.name), - contr_dict['type'], contr_dict['model'])[-1] - return self.controller_dicts - def get_dev_name(self): """ Get device name diff --git a/provider/viommu/__init__.py b/provider/viommu/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/provider/viommu/viommu_base.py b/provider/viommu/viommu_base.py new file mode 100644 index 00000000000..83fd6dfb455 --- /dev/null +++ b/provider/viommu/viommu_base.py @@ -0,0 +1,152 @@ +from avocado.core import exceptions + +from virttest import libvirt_version +from virttest import utils_net + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_libvirt import libvirt_virtio +from virttest.utils_libvirt import libvirt_pcicontr + + +def check_vm_iommu_group(vm_session, test_devices): + """ + Check the devices with iommu enabled are located in a separate iommu group + + :param vm_session: VM session + :param test_devices: test devices to check + """ + for dev in test_devices: + s, o = vm_session.cmd_status_output( + "lspci | awk 'BEGIN{IGNORECASE=1} /%s/ {print $1}'" % dev) + if s: + exceptions.TestFail("Failed to get pci address!") + + cmd = ("find /sys/kernel/iommu_groups/ -type l | xargs ls -l | awk -F " + "'/' '/%s / {print(\"\",$2,$3,$4,$5,$6)}' OFS='/' " % o.strip()) + s, o = vm_session.cmd_status_output(cmd) + if s: + exceptions.TestFail("Failed to find iommu group!") + s, o = vm_session.cmd_status_output("ls %s" % o) + if s: + exceptions.TestFail("Failed to get the device in the iommu group!") + + +class VIOMMUTest(object): + def __init__(self, vm, test, params, session=None): + self.vm = vm + self.test = test + self.params = params + self.session = session + self.remote_virsh_dargs = None + self.controller_dicts = eval(self.params.get("controller_dicts", "[]")) + + libvirt_version.is_libvirt_feature_supported(self.params) + new_xml = vm_xml.VMXML.new_from_inactive_dumpxml(self.vm.name) + self.orig_config_xml = new_xml.copy() + + def parse_iface_dict(self): + """ + Parse iface_dict from params + + :return: The updated iface_dict + """ + mac_addr = utils_net.generate_mac_address_simple() + iface_dict = eval(self.params.get('iface_dict', '{}')) + self.test.log.debug("iface_dict2: %s.", iface_dict) + + if self.controller_dicts and iface_dict: + iface_bus = "%0#4x" % int(self.controller_dicts[-1].get('index')) + iface_attrs = {'bus': iface_bus} + if isinstance(self.dev_slot, int): + self.dev_slot += 1 + iface_attrs.update({'slot': self.dev_slot}) + iface_dict.update({"address": {'attrs': iface_attrs}}) + self.test.log.debug("iface_dict: %s.", iface_dict) + return iface_dict + + def prepare_controller(self): + """ + Prepare controller(s) + + :return: Updated controller attrs + """ + if not self.controller_dicts: + return + + for contr_dict in self.controller_dicts: + pre_controller = contr_dict.get("pre_controller") + if pre_controller: + pre_contrs = list( + filter(None, [c.get('index') for c in self.controller_dicts + if c['type'] == contr_dict['type'] and + c['model'] == pre_controller])) + if pre_contrs: + pre_idx = pre_contrs[0] + else: + pre_idx = libvirt_pcicontr.get_max_contr_indexes( + vm_xml.VMXML.new_from_dumpxml(self.vm.name), + contr_dict['type'], pre_controller) + if not pre_idx: + self.test.error( + f"Unable to get index of {pre_controller} controller!") + contr_dict.pop("pre_controller") + libvirt_vmxml.modify_vm_device( + vm_xml.VMXML.new_from_dumpxml(self.vm.name), 'controller', + contr_dict, 100) + contr_dict['index'] = libvirt_pcicontr.get_max_contr_indexes( + vm_xml.VMXML.new_from_dumpxml(self.vm.name), + contr_dict['type'], contr_dict['model'])[-1] + return self.controller_dicts + + def update_disk_addr(self, disk_dict): + """ + Update disk address + + :param disk_dict: The original disk attrs + :return: The updated disk attrs + """ + if self.controller_dicts: + dev_bus = self.controller_dicts[-1].get('index') + dev_attrs = {'bus': dev_bus} + if disk_dict['target']['bus'] != "scsi": + dev_attrs.update({'type': self.controller_dicts[-1].get('type')}) + if self.controller_dicts[-1].get('model') == 'pcie-to-pci-bridge': + self.dev_slot = 1 + dev_attrs.update({'slot': self.dev_slot}) + + disk_dict.update({"address": {'attrs': dev_attrs}}) + if disk_dict['target']['bus'] == "scsi": + disk_dict['address']['attrs'].update({'type': 'drive'}) + + if self.controller_dicts[-1]['model'] == 'pcie-root-port': + self.controller_dicts.pop() + return disk_dict + + def setup_iommu_test(self, **dargs): + """ + iommu test environment setup + + :param dargs: Other test keywords + """ + iommu_dict = dargs.get('iommu_dict', {}) + dev_type = dargs.get("dev_type", "interface") + cleanup_ifaces = "yes" == dargs.get("cleanup_ifaces", "yes") + + if cleanup_ifaces: + libvirt_vmxml.remove_vm_devices_by_type(self.vm, 'interface') + libvirt_vmxml.remove_vm_devices_by_type(self.vm, 'hostdev') + if iommu_dict: + self.test.log.info("TEST_SETUP: Add iommu device.") + libvirt_virtio.add_iommu_dev(self.vm, iommu_dict) + + def teardown_iommu_test(self, **dargs): + """ + Cleanup iommu test environment + + :param dargs: Other test keywords + """ + self.test.log.info("TEST_TEARDOWN: Recover test environment.") + if self.vm.is_alive(): + self.vm.destroy(gracefully=False) + self.orig_config_xml.sync() From d4915b8b759ae77c58e3b9208cf999ef51583087 Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 25 Jun 2024 14:55:39 +0800 Subject: [PATCH 0428/1055] migration: Update error message Signed-off-by: lcheng --- libvirt/tests/cfg/migration/migrate_vm.cfg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/migration/migrate_vm.cfg b/libvirt/tests/cfg/migration/migrate_vm.cfg index 150c59df045..47591e3cd03 100644 --- a/libvirt/tests/cfg/migration/migrate_vm.cfg +++ b/libvirt/tests/cfg/migration/migrate_vm.cfg @@ -831,19 +831,19 @@ hard_limit_value = "1048576" swap_hard_limit_value = "2097152" memtune_options = "--hard-limit ${hard_limit_value} --swap-hard-limit ${swap_hard_limit_value} --config" - err_msg = "unable to execute QEMU command 'migrate-incoming': RDMA ERROR: could not create rdma event channel|unable to execute QEMU command 'migrate-incoming': Migration requires multi-channel URIs" + err_msg = "unable to execute QEMU command 'migrate-incoming': RDMA ERROR: could not create rdma event channel|unable to execute QEMU command 'migrate-incoming': Migration requires multi-channel URIs|unable to execute QEMU command 'migrate-incoming': unknown migration protocol: rdma" - no_rdma_env_rdma_pin_all: hard_limit_value = "2097152" swap_hard_limit_value = "2097152" memtune_options = "--hard-limit ${hard_limit_value} --swap-hard-limit ${swap_hard_limit_value} --config" virsh_options = "--live --verbose --rdma-pin-all --migrateuri rdma://${server_ip} --listen-address 0.0.0.0" - err_msg = "unable to execute QEMU command 'migrate-incoming': RDMA ERROR: could not create rdma event channel|unable to execute QEMU command 'migrate-incoming': Migration requires multi-channel URIs" + err_msg = "unable to execute QEMU command 'migrate-incoming': RDMA ERROR: could not create rdma event channel|unable to execute QEMU command 'migrate-incoming': Migration requires multi-channel URIs|unable to execute QEMU command 'migrate-incoming': unknown migration protocol: rdma" - no_rdma_env_turn_off_rdma_pin_all: hard_limit_value = "1048576" swap_hard_limit_value = "1048576" memtune_options = "--hard-limit ${hard_limit_value} --swap-hard-limit ${swap_hard_limit_value} --config" virsh_options = "--live --verbose --rdma-pin-all --migrateuri rdma://${server_ip}" - err_msg = "unable to execute QEMU command 'migrate-incoming': RDMA ERROR: could not create rdma event channel|unable to execute QEMU command 'migrate-incoming': Migration requires multi-channel URIs" + err_msg = "unable to execute QEMU command 'migrate-incoming': RDMA ERROR: could not create rdma event channel|unable to execute QEMU command 'migrate-incoming': Migration requires multi-channel URIs|unable to execute QEMU command 'migrate-incoming': unknown migration protocol: rdma" - cross_rhel_platform_migration: # only work well on RHEL platform migration_timeout = 600 From fcec746836bb5db3a8c3091f01aebaa11d0d0271 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Tue, 25 Jun 2024 15:23:40 +0800 Subject: [PATCH 0429/1055] Check required patch in v2v --- v2v/tests/cfg/v2v_options.cfg | 3 +++ v2v/tests/src/v2v_options.py | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/v2v/tests/cfg/v2v_options.cfg b/v2v/tests/cfg/v2v_options.cfg index ed90842f18e..084eedebb54 100644 --- a/v2v/tests/cfg/v2v_options.cfg +++ b/v2v/tests/cfg/v2v_options.cfg @@ -332,6 +332,9 @@ checkpoint = 'weak_dendency' expect_msg = yes msg_content = "Remove 1 Package" + - required_patch: + check_command = "rpm -q --changelog %s" + checkpoint = check_patch - print_estimate: only output_mode.none only input_mode.libvirt.esx.esx_70 diff --git a/v2v/tests/src/v2v_options.py b/v2v/tests/src/v2v_options.py index 2fc89a5dfa0..7bd7efe7c62 100644 --- a/v2v/tests/src/v2v_options.py +++ b/v2v/tests/src/v2v_options.py @@ -515,6 +515,9 @@ def check_alloc(): if checkpoint == 'no_dcpath': if '--dcpath' in output: test.fail('"--dcpath" is not removed') + if checkpoint == 'check_patch': + if not re.search('Fix off-by-one error causing rare crash.*', output): + test.fail('required patch not found') if checkpoint == 'debug_overlays': search = re.search('Overlay saved as(.*)', output) if not search: @@ -866,6 +869,9 @@ def check_alloc(): # only set error to 'ignore' to avoid exception for RHEL7-84978 if "guestfish" in cmd: error_flag = "replace" + if "changelog" in cmd: + get_v2v_version = process.run('rpm -q virt-v2v', shell=True, ignore_status=True) + cmd = cmd % to_text(get_v2v_version.stdout, errors=error_flag) # Set timeout to kill v2v process before conversion succeed if checkpoint == 'disk_not_exist': From 59a4add98b1b02883f1dbe5577427b0a7690d9c6 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 30 May 2024 23:21:30 -0400 Subject: [PATCH 0430/1055] Add network case of qos - VIRT-296329 - [Qos][floor] Check the floor setting in bandwidth setting Signed-off-by: Haijiao Zhao --- .../virtual_network/qos/check_qos_floor.cfg | 16 ++++ .../virtual_network/qos/check_qos_floor.py | 78 +++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/qos/check_qos_floor.cfg create mode 100644 libvirt/tests/src/virtual_network/qos/check_qos_floor.py diff --git a/libvirt/tests/cfg/virtual_network/qos/check_qos_floor.cfg b/libvirt/tests/cfg/virtual_network/qos/check_qos_floor.cfg new file mode 100644 index 00000000000..4ef075f6174 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/qos/check_qos_floor.cfg @@ -0,0 +1,16 @@ +- virtual_network.qos.check_qos_floor: + type = check_qos_floor + start_vm = no + timeout = 240 + net_attrs = {'name': net_name, 'forward': {'mode': 'nat'}, 'ips': [{'dhcp_ranges': {'attrs': {'start': '192.168.100.2', 'end': '192.168.100.254'}}, 'netmask': '255.255.255.0', 'address': '192.168.100.1'}]} + iface_attrs = {'source': {'network': net_name}, 'type_name': 'network', 'model': 'virtio'} + variants net_type: + - with_floor: + bw = {'bandwidth_outbound': {'average': '400', 'peak': '800', 'burst': '512'}, 'bandwidth_inbound': {'average': '500', 'peak': '400', 'burst': '512'}} + net_attrs = {**${net_attrs}, **${bw}} + iface_bw = {'bandwidth': {'inbound': {'average': '300', 'peak': '200', 'floor': '100', 'burst': '256'}, 'outbound': {'average': '200', 'peak': '400', 'burst': '256'}}} + - without_floor: + status_error = yes + err_msg = Invalid use of 'floor' on interface with MAC address .* - network .* has no inbound QoS set + iface_bw = {'bandwidth': {'inbound': {'average': '150', 'peak': '200', 'floor': '100', 'burst': '256'}, 'outbound': {'average': '200', 'peak': '400', 'burst': '256'}}} + iface_attrs = {**${iface_attrs}, **${iface_bw}} diff --git a/libvirt/tests/src/virtual_network/qos/check_qos_floor.py b/libvirt/tests/src/virtual_network/qos/check_qos_floor.py new file mode 100644 index 00000000000..4ff3d1d6110 --- /dev/null +++ b/libvirt/tests/src/virtual_network/qos/check_qos_floor.py @@ -0,0 +1,78 @@ +import logging + +from virttest import utils_misc +from virttest import utils_net +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_network +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Check the floor setting in bandwidth setting + + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + status_error = 'yes' == params.get('status_error', 'no') + err_msg = params.get('err_msg') + + rand_id = utils_misc.generate_random_string(3) + net_name = params.get('net_type') + '_' + rand_id + net_attrs = eval(params.get('net_attrs', '{}')) + iface_attrs = eval(params.get('iface_attrs', '{}')) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + if net_attrs: + libvirt_network.create_or_del_network(net_attrs) + LOG.debug(f'Network xml:\n' + f'{virsh.net_dumpxml(net_attrs["name"]).stdout_text}') + + vmxml.del_device('interface', by_tag=True) + iface = libvirt_vmxml.create_vm_device_by_type( + 'interface', iface_attrs) + libvirt.add_vm_device(vmxml, iface) + LOG.debug(f'VMXMLof {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + start_result = virsh.start(vm_name, debug=True) + libvirt.check_exit_status(start_result, status_error) + if err_msg: + libvirt.check_result(start_result, err_msg) + if status_error: + return + + iface = network_base.get_iface_xml_inst(vm_name, '1st on vm') + mac = iface.mac_address + source_br = iface.source['bridge'] + + tap_device = libvirt.get_ifname_host(vm_name, mac) + LOG.debug(f'tap device on host with mac {mac} is: {tap_device}.') + + bw_floor = iface_attrs['bandwidth']['inbound']['floor'] + iface_attrs['bandwidth']['inbound'].pop('floor') + + if not utils_net.check_class_rules( + source_br, '1:3', {'floor': bw_floor}): + test.fail('Class rule check (floor) failed') + if not utils_net.check_class_rules( + tap_device, '1:1', iface_attrs['bandwidth']['inbound']): + test.fail('Class rule check failed') + if not utils_net.check_filter_rules( + tap_device, iface_attrs['bandwidth']['outbound']): + test.fail('Filter rule check failed') + + finally: + bkxml.sync() + if net_attrs: + libvirt_network.create_or_del_network(net_attrs, is_del=True) From 33153848cae475c3bb8ea0787507ba11f59b37d0 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Tue, 4 Jun 2024 06:29:07 -0400 Subject: [PATCH 0431/1055] Add network case of qos - VIRT-299277 - [Qos][domiftune] Check and tune the bandwidth of a interface via domiftune Signed-off-by: Haijiao Zhao --- .../qos/check_bandwidth_by_domiftune.cfg | 18 +++ .../qos/check_bandwidth_by_domiftune.py | 144 ++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/qos/check_bandwidth_by_domiftune.cfg create mode 100644 libvirt/tests/src/virtual_network/qos/check_bandwidth_by_domiftune.py diff --git a/libvirt/tests/cfg/virtual_network/qos/check_bandwidth_by_domiftune.cfg b/libvirt/tests/cfg/virtual_network/qos/check_bandwidth_by_domiftune.cfg new file mode 100644 index 00000000000..03718250ee0 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/qos/check_bandwidth_by_domiftune.cfg @@ -0,0 +1,18 @@ +- virtual_network.qos.check_bandwidth_by_domiftune: + type = check_bandwidth_by_domiftune + start_vm = no + timeout = 240 + host_iface = + net_attrs = {'bandwidth_outbound': {'average': '500', 'peak': '1000', 'burst': '1024'}, 'bandwidth_inbound': {'average': '1000', 'peak': '5000', 'burst': '5120'}} + update_bw = {'inbound': {'average': '100', 'peak': '200', 'burst': '300'}, 'outbound': {'average': '200', 'peak': '300', 'burst': '200'}} + variants iface_type: + - nat: + iface_attrs = {'source': {'network': 'default'}, 'model': 'virtio', 'type_name': 'network'} + bw_with_floor = + update_bw = {'inbound': {'average': '100', 'peak': '200', 'burst': '300', 'floor': '150'}, 'outbound': {'average': '200', 'peak': '300', 'burst': '200'}} + - direct: + iface_attrs = {'source': {'dev': host_iface, 'mode': 'bridge'}, 'model': 'virtio', 'type_name': 'direct'} + - br: + br_type = linux_br + iface_type = bridge + iface_attrs = {'source': {'bridge': br_name}, 'model': 'virtio', 'type_name': 'bridge'} diff --git a/libvirt/tests/src/virtual_network/qos/check_bandwidth_by_domiftune.py b/libvirt/tests/src/virtual_network/qos/check_bandwidth_by_domiftune.py new file mode 100644 index 00000000000..9c329da1b5f --- /dev/null +++ b/libvirt/tests/src/virtual_network/qos/check_bandwidth_by_domiftune.py @@ -0,0 +1,144 @@ +import logging + +from avocado.utils import process +from virttest import utils_misc +from virttest import utils_net +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.network_xml import NetworkXML +from virttest.utils_libvirt import libvirt_misc +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Check and tune the bandwidth of a interface via domiftune + + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + br_type = params.get('br_type', '') + rand_id = utils_misc.generate_random_string(3) + br_name = br_type + '_' + rand_id + host_iface = params.get('host_iface') + host_iface = host_iface if host_iface else utils_net.get_net_if( + state='UP')[0] + iface_attrs = eval(params.get('iface_attrs', '{}')) + net_attrs = eval(params.get('net_attrs', '{}')) + update_bw = eval(params.get('update_bw', '{}')) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + net_xml = NetworkXML.new_from_net_dumpxml('default') + bk_net_xml = net_xml.copy() + + try: + if br_type == 'linux_br': + utils_net.create_linux_bridge_tmux(br_name, host_iface) + process.run(f'ip l show type bridge {br_name}', shell=True) + + net_xml.setup_attrs(**net_attrs) + net_xml.sync() + LOG.debug(f'Network xml of default: {net_xml}') + + vmxml.del_device('interface', by_tag=True) + + libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs) + LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + vm.start() + session = vm.wait_for_serial_login() + + iface = network_base.get_iface_xml_inst(vm_name, 'on vm') + mac = iface.mac_address + tap_device = libvirt.get_ifname_host(vm_name, mac) + LOG.debug(f'tap device on host with mac {mac} is: {tap_device}.') + + domiftune_out = virsh.domiftune( + vm_name, tap_device, debug=True).stdout_text + domiftune_ori = libvirt_misc.convert_to_dict( + domiftune_out, '(\S+)\s*:\s*(\d+)') + if not all([v == '0' for v in domiftune_ori.values()]): + test.fail('All value of domiftune output should be "0"') + + domiftune_args = {} + bw_in = update_bw['inbound'] + inbound = f'{bw_in["average"]},{bw_in["peak"]},{bw_in["burst"]}' + if 'floor' in bw_in: + inbound = inbound + f',{bw_in["floor"]}' + domiftune_args.update({'inbound': inbound}) + bw_out = update_bw['outbound'] + outbound = f'{bw_out["average"]},{bw_out["peak"]},{bw_out["burst"]}' + domiftune_args.update({'outbound': outbound}) + virsh.domiftune(vm_name, tap_device, **domiftune_args, **VIRSH_ARGS) + + iface_update = network_base.get_iface_xml_inst(vm_name, 'after update') + LOG.debug(iface_update.bandwidth) + for key in ['inbound', 'outbound']: + if iface_update.fetch_attrs()['bandwidth'][key] != update_bw[key]: + test.fail( + f'Bandwidth of interface xml not correctly updated:\n' + f'{iface_update.fetch_attrs()["bandwidth"][key]} != ' + f'{update_bw[key]}') + LOG.debug(f'{key} bandwidth check in xml: PASS') + + # For direct interface type, "tc class show dev" will show the outbound + # instead of the inbound setting, and "tc filter show dev" will show + # the inbound instead of the outbound setting + iface_type = iface_attrs['type_name'] + class_key = 'outbound' if iface_type == 'direct' else 'inbound' + filter_key = 'inbound' if iface_type == 'direct' else 'outbound' + + if iface_type == 'network': + source_br = iface.source['bridge'] + bw_floor = update_bw['inbound']['floor'] + update_bw['inbound'].pop('floor') + if not utils_net.check_class_rules( + source_br, '1:3', {'floor': bw_floor}): + test.fail('Class rule check (floor) after domiftune failed') + if not utils_net.check_class_rules( + tap_device, '1:1', update_bw[class_key]): + test.fail( + 'Class rule check after domiftune failed. Please check log.') + LOG.debug('Class rule check after domiftune: PASS') + if not utils_net.check_filter_rules( + tap_device, update_bw[filter_key]): + test.fail( + 'Filter rule check after domiftune failed. Please check log.') + LOG.debug('Filter rule check after domiftune: PASS') + + virsh.domiftune(vm_name, tap_device, inbound='0', + outbound='0', **VIRSH_ARGS) + iface_del_bw = network_base.get_iface_xml_inst( + vm_name, 'after delete bandwidth') + + if 'bandwidth' in iface_del_bw.fetch_attrs(): + test.fail('Bandwidth of interface xml not deleted') + out_c = utils_net.check_class_rules( + tap_device, "1:1", update_bw["inbound"], expect_none=True + ) + out_f = utils_net.check_filter_rules( + tap_device, update_bw["outbound"], expect_none=True + ) + if not all([out_c, out_f]): + test.fail( + "There should not be output of tc class/filter " + "command when bandwidth settings is deleted." + ) + LOG.debug('Class and Filter rule check with "tc" ' + 'after delete bandwidth with domiftune: PASS') + + finally: + if 'session' in locals(): + session.close() + bkxml.sync() + bk_net_xml.sync() + if br_type == 'linux_br': + utils_net.delete_linux_bridge_tmux(br_name, host_iface) From 02038fde5eb7715fa4f0318e3d7c93ab3498b135 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Wed, 26 Jun 2024 13:34:30 +0800 Subject: [PATCH 0432/1055] Test vmx file with special character at the end Signed-off-by: Ming Xie --- v2v/tests/cfg/convert_from_file.cfg | 12 ++++++++++-- v2v/tests/src/convert_from_file.py | 7 +++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/v2v/tests/cfg/convert_from_file.cfg b/v2v/tests/cfg/convert_from_file.cfg index 41e2bb276a9..c7af03560c5 100644 --- a/v2v/tests/cfg/convert_from_file.cfg +++ b/v2v/tests/cfg/convert_from_file.cfg @@ -232,6 +232,14 @@ boottype = 3 version_required = "[virt-v2v-2.3.4-6.el9,)" main_vm = "VM_NAME_SPACE_NAME_VMX_V2V_EXAMPLE" + - special_character: + only esx_80 + boottype = 3 + version_required = "[virt-v2v-2.4.0-2.el9,)" + main_vm = "VM_NAME_SPACE_NAME_VMX_V2V_EXAMPLE" + checkpoint = 'special_character' + expect_msg = 'yes' + msg_content = 'nbd_connect_uri.*No such file or directory.*' - vmx_default: # Default vmx_nfs_src = NFS_ESX70_VMX_V2V_EXAMPLE @@ -293,13 +301,13 @@ variants: - negative_test: status_error = 'yes' - only parse.SHA1,parse.SHA256 + only parse.SHA1,parse.SHA256,special_character - positive_test: status_error = 'no' variants: - linux: only ova,vmx,disk - no win2008r2_ostk,aws.win2019 + no win2008r2_ostk,aws.win2019,special_character - windows: os_type = 'windows' shutdown_command = 'shutdown /s /f /t 0' diff --git a/v2v/tests/src/convert_from_file.py b/v2v/tests/src/convert_from_file.py index 2c0a96bbc67..2b8431255d1 100644 --- a/v2v/tests/src/convert_from_file.py +++ b/v2v/tests/src/convert_from_file.py @@ -317,8 +317,11 @@ def vm_check(): if checkpoint == 'permission': os.environ['LIBGUESTFS_BACKEND'] = '' process.run('echo $LIBGUESTFS_BACKEND', shell=True) - - v2v_result = utils_v2v.v2v_cmd(v2v_params) + if checkpoint == 'special_character': + v2v_result = utils_v2v.cmd_run(str(utils_v2v.v2v_cmd(v2v_params, cmd_only=True)).replace('.vmx', '.vm*'), + params.get('v2v_dirty_resources')) + else: + v2v_result = utils_v2v.v2v_cmd(v2v_params) if 'new_name' in v2v_params: vm_name = params['main_vm'] = v2v_params['new_name'] From a5996097747a71656070ec6c798186fdeec4a606 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Wed, 26 Jun 2024 01:50:40 -0400 Subject: [PATCH 0433/1055] Change cgroup check to avoid special charachter issue of cmd "systemd-cgls cpuset" output Signed-off-by: liang-cong-red-hat --- .../numa/numa_config_with_auto_placement.py | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/libvirt/tests/src/numa/numa_config_with_auto_placement.py b/libvirt/tests/src/numa/numa_config_with_auto_placement.py index 468566154e4..2e1363e8571 100644 --- a/libvirt/tests/src/numa/numa_config_with_auto_placement.py +++ b/libvirt/tests/src/numa/numa_config_with_auto_placement.py @@ -177,33 +177,19 @@ def check_iothreadinfo(vm_name, cpu_range, config=''): 'iothreadinfo command.'.format(cpu_range)) -def check_cgget_output(test, expected_value): +def check_cgget_output(test, vm, expected_value): """ Get the cgget output and check it for required value :param test: test object + :param vm: virtual machine :param cgget_message: expected message string in output """ - # Find the slice and print it with the cgget - cpuset_slices = process.run('systemd-cgls cpuset') - machine_found = False - slice_line = None - cpuset_lines = re.split('\s', cpuset_slices.stdout_text) - for line in cpuset_lines: - if re.search('machine-qemu', line): - slice_line = line.strip() - # No more lines need to be checked - break - if not slice_line: - test.error("'machine-qemu' is not found in 'systemd-cgls cpuset' output") - slice_line = slice_line.replace('\\', '\\\\')[2:] - + vm_pid = vm.get_pid() + cg = libvirt_cgroup.CgroupTest(vm_pid) + cg_path = cg.get_cgroup_path(controller='cpuset').split('emulator')[0] for item in ['emulator', 'vcpu0']: - if libvirt_cgroup.CgroupTest('').is_cgroup_v2_enabled(): - cmd = 'cat /sys/fs/cgroup/machine.slice/{}/libvirt/{}/cpuset.mems'.format(slice_line, item) - else: - cmd = 'cat /sys/fs/cgroup/cpuset/machine.slice/{}/libvirt/{}/cpuset.mems'.format(slice_line, item) - + cmd = 'cat {}{}/cpuset.mems'.format(re.escape(cg_path), item) result = process.run(cmd, shell=True, ignore_status=False, verbose=True) if expected_value != result.stdout_text.strip(): test.fail('{} is not found in the cpuset.mems file'.format(expected_value)) @@ -257,7 +243,7 @@ def run(test, params, env): test.fail("The used nodeset is not the same after the libvirtd " "restart.{} is not as expected: {}". format(nodeset_after, nodeset)) - check_cgget_output(test, nodeset) + check_cgget_output(test, vm, nodeset) except Exception as e: test.fail('Unexpected failure during the test: {}'.format(e)) From 331715eb9a355f36559a24ab0578bdb4241440ef Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Wed, 26 Jun 2024 02:25:11 -0400 Subject: [PATCH 0434/1055] Decrease memory balloon period to make memory info collection more frequent Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/memory/memory_misc.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/memory/memory_misc.cfg b/libvirt/tests/cfg/memory/memory_misc.cfg index cf820b5f9eb..72e7a7a83a3 100644 --- a/libvirt/tests/cfg/memory/memory_misc.cfg +++ b/libvirt/tests/cfg/memory/memory_misc.cfg @@ -109,7 +109,7 @@ variants case: - disk_caches: membal_model = 'virtio' - membal_stats_period = 2 + membal_stats_period = 1 membal_alias_name = 'balloon0' allow_error = 15 - xml_check: From 893ea25896ace81e44dccd2496d2d317eca644d2 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 26 Jun 2024 15:06:08 +0800 Subject: [PATCH 0435/1055] vdpa: Fix an issue due to cmd output change Signed-off-by: Yingshun Cui --- provider/interface/vdpa_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provider/interface/vdpa_base.py b/provider/interface/vdpa_base.py index d2463ac0e46..4ceeb6b367c 100644 --- a/provider/interface/vdpa_base.py +++ b/provider/interface/vdpa_base.py @@ -143,7 +143,7 @@ def get_multiplier(vm_session, pci_id): :return: The multiplier of VM's interface """ cmd = "lspci -vvv -s %s | awk -F '=' '/multiplier=/ {print $NF}'" % pci_id - act_mul = vm_session.cmd_output(cmd).strip() + act_mul = vm_session.cmd_output(cmd).splitlines()[-1] LOG.debug("Actual multiplier: %s", act_mul) return act_mul From 3aac99cceb6683f431cc4d30c8f973456d031a9f Mon Sep 17 00:00:00 2001 From: lcheng Date: Fri, 24 May 2024 18:46:43 +0800 Subject: [PATCH 0436/1055] graphics: Add case to test no specified listen type for vnc graphic XXX-60228 - [vnc][ no listen type] Define a guest with no specified listen type for vnc graphic Signed-off-by: lcheng --- .../cfg/graphics/graphics_functional.cfg | 5 +++ .../tests/src/graphics/graphics_functional.py | 43 +++++++++++-------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/libvirt/tests/cfg/graphics/graphics_functional.cfg b/libvirt/tests/cfg/graphics/graphics_functional.cfg index 6fb70ad4585..628ac0b47f0 100644 --- a/libvirt/tests/cfg/graphics/graphics_functional.cfg +++ b/libvirt/tests/cfg/graphics/graphics_functional.cfg @@ -225,6 +225,11 @@ need_vnc_dict = "no" check_dom_xml = "yes" check_qemu_pattern = '-vnc none' + - listen_type_non_exist: + vnc_listen_type = "not_exist" + vnc_autoport = "not_set" + need_vnc_dict = "no" + check_dom_xml = "yes" - listen_type_address: vnc_listen_type = 'address' variants: diff --git a/libvirt/tests/src/graphics/graphics_functional.py b/libvirt/tests/src/graphics/graphics_functional.py index 23d933071c1..51168283408 100644 --- a/libvirt/tests/src/graphics/graphics_functional.py +++ b/libvirt/tests/src/graphics/graphics_functional.py @@ -1020,6 +1020,9 @@ def handle_auto_filled_items(given_graphic_attrs, vm, params): given_graphic_attrs['listen_attrs'].update({'address': utils_net.get_host_ip_address()}) elif vnc_network_type == 'vnet': given_graphic_attrs['listen_attrs'].update({'address': params.get('vnet_address')}) + elif vnc_listen_type == 'not_exist': + given_graphic_attrs.update({'listen_attrs': {'type': 'address'}}) + if vnc_port and vnc_port == '0': del given_graphic_attrs['port'] given_graphic_attrs.update({'listen_attrs': {'type': 'address'}}) @@ -1707,26 +1710,28 @@ def run(test, params, env): if spice_listen_type == "network" or vnc_listen_type == "network": for ip in all_ips: ip.addr = ipaddress.ip_address(ip.addr).compressed - try: - logging.debug("Before starting, vm xml:\n%s", VMXML.new_from_dumpxml(vm_name)) - vm.start() - logging.debug("After starting, vm xml:\n%s", VMXML.new_from_dumpxml(vm_name)) - except virt_vm.VMStartError as detail: - compare_guest_xml(vnc_graphic, vm, params, test) - if not fail_patts: - test.fail( - "Expect VM can be started, but failed with: %s" % detail) - for patt in fail_patts: - if re.search(patt, str(detail)): - return - test.fail( - "Expect fail with error in %s, but failed with: %s" - % (fail_patts, detail)) - else: - if fail_patts: + + logging.debug("Before starting, vm xml:\n%s", VMXML.new_from_dumpxml(vm_name)) + if vnc_listen_type != "not_exist": + try: + vm.start() + logging.debug("After starting, vm xml:\n%s", VMXML.new_from_dumpxml(vm_name)) + except virt_vm.VMStartError as detail: + compare_guest_xml(vnc_graphic, vm, params, test) + if not fail_patts: + test.fail( + "Expect VM can be started, but failed with: %s" % detail) + for patt in fail_patts: + if re.search(patt, str(detail)): + return test.fail( - "Expect VM can't be started with %s, but started." - % fail_patts) + "Expect fail with error in %s, but failed with: %s" + % (fail_patts, detail)) + else: + if fail_patts: + test.fail( + "Expect VM can't be started with %s, but started." + % fail_patts) if spice_xml: spice_opts, plaintext_channels, tls_channels = qemu_spice_options(vm) From bb796e568658224faa165f0fa428b864972d841e Mon Sep 17 00:00:00 2001 From: Yan Fu Date: Wed, 26 Jun 2024 19:45:58 +0800 Subject: [PATCH 0437/1055] Remove pid file under /run dir after daemon exits Signed-off-by: Yan Fu --- libvirt/tests/src/daemon/daemon_functional.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libvirt/tests/src/daemon/daemon_functional.py b/libvirt/tests/src/daemon/daemon_functional.py index 950f170472e..8a57fa34d99 100644 --- a/libvirt/tests/src/daemon/daemon_functional.py +++ b/libvirt/tests/src/daemon/daemon_functional.py @@ -172,6 +172,11 @@ def check_config_file(): finally: libvirtd.exit() Libvirtd(daemon_name).stop() + # Remove pid file under /run dir + default_pid_path = "/run/" + daemon_name + ".pid" + if os.path.exists(default_pid_path): + os.remove(default_pid_path) + Libvirtd(daemon_name).stop() socket_name = daemon_name + ".socket" Libvirtd(socket_name).restart() Libvirtd(daemon_name).start() From 9a27b9def8b7143f835c417a7b0b130c13fde8cd Mon Sep 17 00:00:00 2001 From: Meina Li Date: Wed, 26 Jun 2024 23:14:36 -0400 Subject: [PATCH 0438/1055] Virtual_disk: fix no scsi_generic file issue The error of "error: cannot open directory '/sys/bus/scsi/devices/11:0:0:0/scsi_generic': No such file or directory" is caused by the missing sg module. So add it in script. Signed-off-by: Meina Li --- libvirt/tests/src/scsi/scsi_device.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/src/scsi/scsi_device.py b/libvirt/tests/src/scsi/scsi_device.py index 9ebf4c23829..f4911571431 100644 --- a/libvirt/tests/src/scsi/scsi_device.py +++ b/libvirt/tests/src/scsi/scsi_device.py @@ -612,6 +612,8 @@ def run(test, params, env): params.pop('boot_order') try: + # Load sg module + process.run("modprobe sg", shell=True, ignore_status=True, verbose=True) run_test_case(test, params, env) if coldplug: vm.start() From 6645592f35eaff8e847d2071d5f1f9689dad867d Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Thu, 27 Jun 2024 14:28:00 +0800 Subject: [PATCH 0439/1055] guest_os_booting: Fix up issues of entering uefi shell Update to check ouput during os startup, because some cases will enter to uefi shell instead of os system in aarch64. Signed-off-by: Yingshun Cui --- .../guest_os_booting/boot_order/boot_from_cdrom_device.cfg | 4 +++- .../src/guest_os_booting/boot_order/boot_from_cdrom_device.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg index 35dfe78e81d..0b820f8dadb 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg @@ -3,7 +3,6 @@ start_vm = no disk1_attrs_target = {'dev': 'vda', 'bus': 'virtio'} cdrom_attrs = "{'type_name': 'file', 'device': 'cdrom', 'driver': {'name': 'qemu', 'type': 'raw', 'cache': 'none'}, 'readonly': True}" - bootable_patterns = ["begin the installation process|Install Red Hat Enterprise"] variants: - without_cdrom: only os_dev @@ -11,9 +10,11 @@ cdrom1_attrs = {'target': {'dev': 'sda', 'bus': 'sata'}, **${cdrom_attrs}} aarch64: cdrom1_attrs = {'target': {'dev': 'sda', 'bus': 'scsi'}, **${cdrom_attrs}} + bootable_patterns = ["Shell>"] - with_cdrom: check_bootable_iso = "yes" cdrom1_attrs = {'source': {'attrs': {'file': boot_img_path}}, 'target': {'dev': 'sda', 'bus': 'scsi'}, **${cdrom_attrs}} + bootable_patterns = ["begin the installation process|Install Red Hat Enterprise"] - multi_cdroms: cdrom1_attrs = {'target': {'dev': 'sda', 'bus': 'scsi'}, **${cdrom_attrs}} cdrom2_attrs = {'source': {'attrs': {'file': boot_img_path}}, 'target': {'dev': 'sdb', 'bus': 'sata'}, **${cdrom_attrs}} @@ -21,6 +22,7 @@ cdrom2_attrs = {'source': {'attrs': {'file': boot_img_path}}, 'target': {'dev': 'sdb', 'bus': 'scsi'}, **${cdrom_attrs}} cdrom_boot_order: check_bootable_iso = "yes" + bootable_patterns = ["begin the installation process|Install Red Hat Enterprise"] os_dev: status_error = "yes" variants: diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py index 8503e131e81..8a675f0b5a2 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py @@ -98,7 +98,7 @@ def run(test, params, env): test.log.debug(vm_xml.VMXML.new_from_dumpxml(vm.name)) vm.start() - if check_bootable_iso: + if bootable_patterns: vm.serial_console.read_until_output_matches( bootable_patterns, timeout=60, internal_timeout=0.5) else: From de3a1f8b920ce35539fe7b1914d118300fb6ca3c Mon Sep 17 00:00:00 2001 From: nanli Date: Thu, 27 Jun 2024 19:10:58 +0800 Subject: [PATCH 0440/1055] fix controller case use elem.address while no addr ele need to check if addr exist and then to get addr Signed-off-by: nanli --- .../src/controller/controller_functional.py | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/libvirt/tests/src/controller/controller_functional.py b/libvirt/tests/src/controller/controller_functional.py index 2fc99baa89a..c1990521bee 100644 --- a/libvirt/tests/src/controller/controller_functional.py +++ b/libvirt/tests/src/controller/controller_functional.py @@ -281,23 +281,24 @@ def get_controller_addr(cntlr_type=None, model=None, index=None, cntlr_bus=None) (cntlr_type is None or elem.type == cntlr_type) and (model is None or elem.model == model) and (index is None or elem.index == index)): - addr_elem = elem.address - if addr_elem is None: - test.error("Can not find 'Address' " - "element for the controller") - p4 = None - if 'ccw' == cntlr_bus: - p1 = int(addr_elem.attrs.get('cssid'), 0) - p2 = int(addr_elem.attrs.get('ssid'), 0) - p3 = int(addr_elem.attrs.get('devno'), 0) - else: - p1 = int(addr_elem.attrs.get('bus'), 0) - p2 = int(addr_elem.attrs.get('slot'), 0) - p3 = int(addr_elem.attrs.get('function'), 0) - p4 = addr_elem.attrs.get('multifunction') - addr_str = '%02d:%02x.%1d' % (p1, p2, p3) - logging.debug("Controller address is %s", addr_str) - return (addr_str, p1, p2, p3, p4) + if elem._get_list("address"): + addr_elem = elem.address + if addr_elem is None: + test.error("Can not find 'Address' " + "element for the controller") + p4 = None + if 'ccw' == cntlr_bus: + p1 = int(addr_elem.attrs.get('cssid'), 0) + p2 = int(addr_elem.attrs.get('ssid'), 0) + p3 = int(addr_elem.attrs.get('devno'), 0) + else: + p1 = int(addr_elem.attrs.get('bus'), 0) + p2 = int(addr_elem.attrs.get('slot'), 0) + p3 = int(addr_elem.attrs.get('function'), 0) + p4 = addr_elem.attrs.get('multifunction') + addr_str = '%02d:%02x.%1d' % (p1, p2, p3) + logging.debug("Controller address is %s", addr_str) + return (addr_str, p1, p2, p3, p4) return (None, None, None, None, None) From f046813e818ee1c9d318b0d9507f9046901aa9ee Mon Sep 17 00:00:00 2001 From: Yanqiu Zhang Date: Thu, 27 Jun 2024 07:36:35 -0400 Subject: [PATCH 0441/1055] iface_network: use nft for new product Replace an ip6tables usage with nft for new product which use the default firewall_backend='nftables'. Signed-off-by: Yanqiu Zhang --- .../src/virtual_network/iface_network.py | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/libvirt/tests/src/virtual_network/iface_network.py b/libvirt/tests/src/virtual_network/iface_network.py index a6d99917326..93208b72714 100644 --- a/libvirt/tests/src/virtual_network/iface_network.py +++ b/libvirt/tests/src/virtual_network/iface_network.py @@ -11,6 +11,8 @@ from aexpect.exceptions import ExpectTimeoutError +from provider.virtual_network import network_base + from virttest import virt_vm from virttest import virsh from virttest import utils_net @@ -45,6 +47,7 @@ def run(test, params, env): vm_name = params.get("main_vm") vm = env.get_vm(vm_name) host_arch = platform.machine() + firewall_backend = network_base.check_firewall_backend() def prepare_pxe_boot(): """ @@ -445,12 +448,21 @@ def check_ipt_rules(check_ipv4=True, check_ipv6=False): ipv6_rules.extend(rules) if "mode" in net_forward and net_forward["mode"] == "nat" \ and nat_attrs.get('ipv6') == 'yes': - v6_nat_rules = [ - "MASQUERADE.*tcp.*{0}.*!{0}".format(net_ipv6), - "MASQUERADE.*udp.*{0}.*!{0}".format(net_ipv6), - "MASQUERADE.*all.*{0}.*!{0}".format(net_ipv6) - ] - v6_output = process.run('ip6tables -t nat -L', shell=True).stdout_text + + if firewall_backend == "nftables": + v6_nat_rules = [ + "tcp ip6 saddr {0} ip6 daddr != {0}.*masquerade to".format(net_ipv6), + "udp ip6 saddr {0} ip6 daddr != {0}.*masquerade to".format(net_ipv6), + "ip6 saddr {0} ip6 daddr != {0}.*masquerade".format(net_ipv6), + ] + v6_output = process.run('nft list chain ip6 libvirt_network guest_nat', shell=True).stdout_text + else: + v6_nat_rules = [ + "MASQUERADE.*tcp.*{0}.*!{0}".format(net_ipv6), + "MASQUERADE.*udp.*{0}.*!{0}".format(net_ipv6), + "MASQUERADE.*all.*{0}.*!{0}".format(net_ipv6) + ] + v6_output = process.run('ip6tables -t nat -L', shell=True).stdout_text for rule in v6_nat_rules: if not re.search(rule, v6_output): test.fail('Rule %s missing from ip6tables output.' % rule) From 39b1b84549dab4f406c4e8dfbe5f5fe117058741 Mon Sep 17 00:00:00 2001 From: Slancast1 Date: Thu, 20 Jun 2024 12:25:25 -0400 Subject: [PATCH 0442/1055] Fix for aarch64/rhel.guest_os_booting.boot_order.usb_device.hostdev_device Signed-off-by: Slancast1 -- The Issue A test related to boot_from_usb_device.py would not pass: guest_os_booting.boot_order.usb_device.hostdev_device The test would fail with the following error message LibvirtXMLError: Failed to define avocado-vt-vm1 for reason:error: Failed to define domain from /tmp/xml_utils_temp_l7acogze.xmlerror: unsupported configuration: BIOS serial console only supported on x86 architectures This test would not pass for two reasons: 1) The 'bios_useserial' flag is not compatible with aarch64/edk2 2) The UEFI prints a different string on aarch64 than it does on other platforms. The test looks at this output, so this is bad. -- The Fix 1) Remove the 'bios_useserial' flag from bootmenu_dict in the *.cfg file for aarch64 2) Redefine check_prompt to include "UsbBootDetectMedia: UsbBootIsUnitReady .*" so the proper message can be detected --- .../cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg | 5 ++++- .../src/guest_os_booting/boot_order/boot_from_usb_device.py | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg index 0f62a062bb7..4b25adba0c2 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg @@ -3,8 +3,10 @@ start_vm = no bus_type = "usb" bootmenu_dict = {'bootmenu_enable': 'yes', 'bootmenu_timeout': '3000', 'bios_useserial': 'yes'} - check_prompt = "UEFI .* USB|1. USB MSC Drive .*" + check_prompt = "UEFI .* USB|1. USB MSC Drive .*|UsbBootDetectMedia: UsbBootIsUnitReady .*" only q35, aarch64 + aarch64: + bootmenu_dict = {'bootmenu_enable': 'yes', 'bootmenu_timeout': '3000'} variants usb_device: - block_device: disk_type = "block" @@ -13,5 +15,6 @@ - redirdev_device: port_num = "4000" device_attrs = {'source': {'host': 'localhost', 'service': '4000', 'mode': 'connect'}, 'protocol': {'type': 'raw'}, 'type_name': 'tcp', 'bus': '${bus_type}', 'type': 'tcp', 'boot': {'order': '1'}} + only q35 - hostdev_device: device_attrs = {'type_name': 'usb', 'mode': 'subsystem', 'source': {'vendor_id': '%s', 'product_id': '%s'}, 'type': 'usb', 'managed': 'no', 'boot_order': '1'} diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_usb_device.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_usb_device.py index 1c023a6f5a6..ccabdaf1cd5 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_usb_device.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_usb_device.py @@ -35,7 +35,7 @@ def get_usb_source(): test.log.info("The lsusb command result: {}".format(lsusb_list)) found_device = False for line in lsusb_list: - if re.search('hub|Controller', line, re.IGNORECASE): + if re.search('hub|Controller|Keyboard|Mouse|Cdrom|Floppy', line, re.IGNORECASE): continue if len(line.split()[5].split(':')) == 2: vendor_id, product_id = line.split()[5].split(':') @@ -59,7 +59,7 @@ def check_boot_order(): for _ in range(3): vm.serial_console.sendcontrol('[') vm.serial_console.read_until_any_line_matches( - [check_prompt], timeout=30, internal_timeout=0.5) + [check_prompt], timeout=100, internal_timeout=5.0) vm_name = params.get("main_vm") disk_type = params.get("disk_type") From 9c69bc38f7b5b72d5d63e83740efd02d19f033f1 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 27 Jun 2024 10:17:38 -0400 Subject: [PATCH 0443/1055] Modify the watchdog expire time From libvirt-9.1, iTCO watchdog are the default watchdog device for q35 guests. The default expirt time of iTCO watchdog are about 60s. As for the event case, we just need to verify that there would be corresponding watchdog events after we trigger the watchdog. It has nothing to do with how much time watchdog devices need to expire. So I extend the watchdog expirt time here. Signed-off-by: root --- libvirt/tests/src/event/virsh_event.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/event/virsh_event.py b/libvirt/tests/src/event/virsh_event.py index 1729b5ed0ba..b0fb59033ca 100644 --- a/libvirt/tests/src/event/virsh_event.py +++ b/libvirt/tests/src/event/virsh_event.py @@ -543,7 +543,7 @@ def _check_disk(target): test.fail("Failed to trigger watchdog: %s" % details) session.close() # watchdog acts slowly, waiting for it. - time.sleep(30) + time.sleep(60) expected_events_list.append("'watchdog' for %s: " + "%s" % action) if action == 'pause': expected_events_list.append("'lifecycle' for %s: Suspended Watchdog") From 5445c3356ce783732f724f01ebf2d89ff88a6936 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Thu, 2 May 2024 09:28:12 +0800 Subject: [PATCH 0444/1055] virsh_capabilities: add case to check cpu topo - New scenario to check cpu topology in capabilities output including die_id, socket_id, cluster_id, core_id and siblings - Refine the code structure for better readability Signed-off-by: Dan Zheng --- .../src/virsh_cmd/host/virsh_capabilities.py | 267 ++++++++++++------ 1 file changed, 173 insertions(+), 94 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/host/virsh_capabilities.py b/libvirt/tests/src/virsh_cmd/host/virsh_capabilities.py index 4486c85601d..d8b8b70a60f 100644 --- a/libvirt/tests/src/virsh_cmd/host/virsh_capabilities.py +++ b/libvirt/tests/src/virsh_cmd/host/virsh_capabilities.py @@ -4,119 +4,198 @@ from avocado.utils import path from avocado.utils import process +from avocado.utils import cpu from virttest import libvirt_vm from virttest import virsh from virttest.libvirt_xml import capability_xml - # 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__) -def run(test, params, env): +def check_host_arch(cap_xml, test): """ - Test the command virsh capabilities + Check host arch information in virsh capabilities output - (1) Call virsh capabilities - (2) Call virsh capabilities with an unexpected option - (3) Call virsh capabilities with libvirtd service stop + :param cap_xml: CapabilityXML instance + :param test: test object + """ + xml_arch = cap_xml.arch + logging.debug("Host arch (capabilities_xml): %s", xml_arch) + exp_arch = platform.machine() + if xml_arch != exp_arch: + test.fail("The host arch in capabilities_xml is " + "expected to be %s, but get %s" % + (exp_arch, xml_arch)) + + +def check_host_cpu_count(cap_xml, test): + """ + Check host cpu number in virsh capabilities output + + :param cap_xml: CapabilityXML instance + :param test: test object + """ + xml_cpu_count = cap_xml.cpu_count + logging.debug("Host cpus count (capabilities_xml): %s", xml_cpu_count) + exp_cpu_count = cpu.online_count() + if xml_cpu_count != exp_cpu_count: + test.fail("Host cpus count is expected to be %s, " + "but get %s" % + (exp_cpu_count, xml_cpu_count)) + + +def check_host_cpu_topology(cap_xml, test): + """ + Check host cpu topology information in virsh capabilities output + + :param cap_xml: CapabilityXML instance + :param test: test object + """ + def _compare_value(cmd, value_in_capxml, key_in_cpu): + """ + Compare a pair of cpu key and value in capabilities to sysfs + + :param cmd: str, command to execute + :param value_in_capxml: str, key value in + :param key_in_cpu: str, key name in + """ + sys_value = process.run(cmd, shell=True).stdout_text.strip() + if sys_value != value_in_capxml: + test.fail("Expect '%s' to be '%s', " + "but found '%s'" % (key_in_cpu, + sys_value, + value_in_capxml)) + + cell_list = cap_xml.cells_topology.cell + current_arch = platform.machine() + is_x8664 = True if current_arch == "x86_64" else False + is_aarch64 = True if current_arch == "aarch64" else False + prefix_cmd = "cat /sys/devices/system/cpu/cpu%s/topology/%s" + file_name_key_mapping = {"physical_package_id": "socket_id", + "cluster_id": "cluster_id", + "core_id": "core_id", + "thread_siblings_list": "siblings"} + if is_x8664: + file_name_key_mapping.update({"die_id": "die_id"}) + if is_aarch64 or is_x8664: + file_name_key_mapping.update({"cluster_id": "cluster_id"}) + for a_cell in cell_list: + cpu_list = a_cell.cpu + for a_cpu in cpu_list: + for file_name, key_in_cap in file_name_key_mapping.items(): + cmd = prefix_cmd % (a_cpu['id'], file_name) + _compare_value(cmd, a_cpu[key_in_cap], key_in_cap) + logging.debug("Verify cpu%s with sysfs - PASS", a_cpu['id']) + + +def check_arch_guest_support(cap_xml, test): + """ + Check arch guest support information in virsh capabilities output + + :param cap_xml: CapabilityXML instance + :param test: test object """ - def compare_capabilities_xml(source): - cap_xml = capability_xml.CapabilityXML() - cap_xml.xml = source - - # Check that host has a non-empty UUID tag. - xml_uuid = cap_xml.uuid - logging.debug("Host UUID (capabilities_xml): %s", xml_uuid) - if xml_uuid == "": - test.fail("The host uuid in capabilities_xml is none!") - - # Check the host arch. - xml_arch = cap_xml.arch - logging.debug("Host arch (capabilities_xml): %s", xml_arch) - exp_arch = process.run("arch", shell=True).stdout_text.strip() - if xml_arch != exp_arch: - test.fail("The host arch in capabilities_xml is " - "expected to be %s, but get %s" % - (exp_arch, xml_arch)) - - # Check the host cpu count. - xml_cpu_count = cap_xml.cpu_count - logging.debug("Host cpus count (capabilities_xml): %s", xml_cpu_count) - search_str = 'processor' - if platform.machine() == 's390x': - search_str = 'cpu number' - cmd = "grep '%s' /proc/cpuinfo | wc -l" % search_str - exp_cpu_count = int(process.run(cmd, shell=True).stdout_text.strip()) - if xml_cpu_count != exp_cpu_count: - test.fail("Host cpus count is expected to be %s, " - "but get %s" % - (exp_cpu_count, xml_cpu_count)) - - # Check the arch of guest supported. - guest_capa = cap_xml.get_guest_capabilities() - logging.debug(guest_capa) - - # libvirt track wordsize in hardcode struct virArchData - wordsize = {} - wordsize['64'] = ['alpha', 'aarch64', 'ia64', 'mips64', 'mips64el', - 'parisc64', 'ppc64', 'ppc64le', 's390x', 'sh4eb', - 'sparc64', 'x86_64'] - wordsize['32'] = ['armv6l', 'armv7l', 'armv7b', 'cris', 'i686', 'lm32', - 'm68k', 'microblaze', 'microblazeel', 'mips', - 'mipsel', 'openrisc', 'parisc', 'ppc', 'ppcle', - 'ppcemb', 's390', 'sh4', 'sparc', 'unicore32', - 'xtensa', 'xtensaeb'] - uri_type = process.run( - "virsh uri", shell=True).stdout_text.split(':')[0] - domain_type = "domain_" + uri_type - for arch_dict in list(itervalues(guest_capa)): - for arch, val_dict in list(iteritems(arch_dict)): - # Check wordsize - if arch not in wordsize[val_dict['wordsize']]: - test.fail("'%s' wordsize '%s' in " - "capabilities_xml not expected" % - (arch, val_dict['wordsize'])) - # Check the type of hypervisor - if domain_type not in list(val_dict.keys()): - if (arch == "ppc64" or arch == "ppc64le"): - tcg_check = process.run("qemu-system-ppc64 --accel help", - shell=True).stdout_text.split('\n') - if "tcg" not in tcg_check: - logging.info("expected to fail as tcg is disabled") - else: - test.fail("domain type '%s' is not matched" - " under arch '%s' in " - "capabilities_xml" % - (uri_type, arch)) + guest_capa = cap_xml.get_guest_capabilities() + logging.debug(guest_capa) + + # libvirt track wordsize in hardcode struct virArchData + wordsize = {} + wordsize['64'] = ['alpha', 'aarch64', 'ia64', 'mips64', 'mips64el', + 'parisc64', 'ppc64', 'ppc64le', 's390x', 'sh4eb', + 'sparc64', 'x86_64'] + wordsize['32'] = ['armv6l', 'armv7l', 'armv7b', 'cris', 'i686', 'lm32', + 'm68k', 'microblaze', 'microblazeel', 'mips', + 'mipsel', 'openrisc', 'parisc', 'ppc', 'ppcle', + 'ppcemb', 's390', 'sh4', 'sparc', 'unicore32', + 'xtensa', 'xtensaeb'] + uri_type = virsh.command('uri').stdout_text.split(':')[0] + domain_type = "domain_" + uri_type + for arch_dict in list(itervalues(guest_capa)): + for arch, val_dict in list(iteritems(arch_dict)): + # Check wordsize + if arch not in wordsize[val_dict['wordsize']]: + test.fail("'%s' wordsize '%s' in " + "capabilities_xml not expected" % + (arch, val_dict['wordsize'])) + # Check the type of hypervisor + if domain_type not in list(val_dict.keys()): + if (arch == "ppc64" or arch == "ppc64le"): + tcg_check = process.run("qemu-system-ppc64 --accel help", + shell=True).stdout_text.split('\n') + if "tcg" not in tcg_check: + logging.info("expected to fail as tcg is disabled") else: test.fail("domain type '%s' is not matched" " under arch '%s' in " "capabilities_xml" % (uri_type, arch)) + else: + test.fail("domain type '%s' is not matched" + " under arch '%s' in " + "capabilities_xml" % + (uri_type, arch)) + + +def check_power_management_suuport(cap_xml, test): + """ + Check power management support in virsh capabilities output - # check power management support. - try: - pm_cmd = path.find_command('pm-is-supported') - pm_cap_map = {'suspend': 'suspend_mem', - 'hibernate': 'suspend_disk', - 'suspend-hybrid': 'suspend_hybrid'} - exp_pms = [] - for opt in pm_cap_map: - cmd = '%s --%s' % (pm_cmd, opt) - res = process.run(cmd, ignore_status=True, shell=True) - if res.exit_status == 0: - exp_pms.append(pm_cap_map[opt]) - pms = cap_xml.power_management_list - if set(exp_pms) != set(pms): - test.fail("Expected supported PMs are %s, got %s " - "instead." % (exp_pms, pms)) - except path.CmdNotFoundError: - logging.debug('Power management checking is skipped, since command' - ' pm-is-supported is not found.') + :param cap_xml: CapabilityXML instance + :param test: test object + """ + try: + pm_cmd = path.find_command('pm-is-supported') + pm_cap_map = {'suspend': 'suspend_mem', + 'hibernate': 'suspend_disk', + 'suspend-hybrid': 'suspend_hybrid'} + exp_pms = [] + for opt in pm_cap_map: + cmd = '%s --%s' % (pm_cmd, opt) + res = process.run(cmd, ignore_status=True, shell=True) + if res.exit_status == 0: + exp_pms.append(pm_cap_map[opt]) + pms = cap_xml.power_management_list + if set(exp_pms) != set(pms): + test.fail("Expected supported PMs are %s, got %s " + "instead." % (exp_pms, pms)) + except path.CmdNotFoundError: + logging.debug('Power management checking is skipped, since command' + ' pm-is-supported is not found.') + + +def compare_capabilities_xml(source, test): + """ + Check virsh capabilities output + + :param source: CapabilityXML instance + :param test: test object + """ + cap_xml = capability_xml.CapabilityXML() + cap_xml.xml = source + # Check that host has a non-empty UUID tag. + xml_uuid = cap_xml.uuid + logging.debug("Host UUID (capabilities_xml): %s", xml_uuid) + if xml_uuid == "": + test.fail("The host uuid in capabilities_xml is none!") + + check_host_arch(cap_xml, test) + check_host_cpu_count(cap_xml, test) + check_host_cpu_topology(cap_xml, test) + check_arch_guest_support(cap_xml, test) + check_power_management_suuport(cap_xml, test) + + +def run(test, params, env): + """ + Test the command virsh capabilities + + (1) Call virsh capabilities + (2) Call virsh capabilities with an unexpected option + """ connect_uri = libvirt_vm.normalize_connect_uri(params.get("connect_uri", "default")) # Run test case @@ -136,7 +215,7 @@ def compare_capabilities_xml(source): test.fail("Command virsh capabilities %s succeeded (incorrect \ command)" % option) elif status_error == "no": - compare_capabilities_xml(output) + compare_capabilities_xml(output, test) if status != 0: test.fail("Command 'virsh capabilities %s' failed " "(correct command)" % option) From 7dc67efa4ab9175b8539f01952fda625e663fbfc Mon Sep 17 00:00:00 2001 From: lcheng Date: Fri, 28 Jun 2024 12:39:22 +0800 Subject: [PATCH 0445/1055] migration: Update error message Signed-off-by: lcheng --- libvirt/tests/cfg/migration/migrate_service_control.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration/migrate_service_control.cfg b/libvirt/tests/cfg/migration/migrate_service_control.cfg index 84e4e7caea4..85fccaecc76 100644 --- a/libvirt/tests/cfg/migration/migrate_service_control.cfg +++ b/libvirt/tests/cfg/migration/migrate_service_control.cfg @@ -40,7 +40,7 @@ - kill_qemu_on_dst: service_name = "qemu-kvm" service_on_dst = "yes" - err_msg = 'qemu unexpectedly closed the monitor|domain is no longer running|Domain not found|Unable to write to socket: Bad file descriptor|Channel error: Input/output error' + err_msg = 'qemu unexpectedly closed the monitor|domain is no longer running|Domain not found|Unable to write to socket: Bad file descriptor|Channel error: Input/output error|QEMU unexpectedly closed the monitor' - kill_libvirtd_on_src: service_name = "libvirtd" err_msg = 'End of file while reading data: Input/output error' From f0074c624ba470120487bdf3290d4fcad98e56c7 Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 22 May 2024 18:56:17 +0800 Subject: [PATCH 0446/1055] libvirtd: Add case about negative value for parameters in libvirtd conf XXXX-34455 - [libvirtd][config]Start libvirtd with negative value for parameters which require positive integer value in libvirtd.conf Signed-off-by: lcheng --- .../check_negative_parameter.cfg | 47 ++++++++++++++++++ .../libvirtd_conf/check_negative_parameter.py | 49 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 libvirt/tests/cfg/daemon/conf_file/libvirtd_conf/check_negative_parameter.cfg create mode 100644 libvirt/tests/src/daemon/conf_file/libvirtd_conf/check_negative_parameter.py diff --git a/libvirt/tests/cfg/daemon/conf_file/libvirtd_conf/check_negative_parameter.cfg b/libvirt/tests/cfg/daemon/conf_file/libvirtd_conf/check_negative_parameter.cfg new file mode 100644 index 00000000000..13099069b9e --- /dev/null +++ b/libvirt/tests/cfg/daemon/conf_file/libvirtd_conf/check_negative_parameter.cfg @@ -0,0 +1,47 @@ +- conf_file.libvirtd_conf.check_negative_parameter: + type = check_negative_parameter + start_vm = no + log_file = "/var/log/messages" + require_modular_daemon = "yes" + variants parameter_name: + - listen_tcp: + only virtproxyd + parameter_value = "-1" + - listen_tls: + only virtproxyd + parameter_value = "-40" + - tls_no_sanity_certificate: + only virtproxyd + parameter_value = "-1" + - max_clients: + parameter_value = "-1" + - max_queued_clients: + parameter_value = "-1" + - max_anonymous_clients: + parameter_value = "-1" + - max_workers: + parameter_value = "-1" + - min_workers: + parameter_value = "-1" + - prio_workers: + parameter_value = "-1" + - max_client_requests: + parameter_value = "-5" + - audit_level: + parameter_value = "-2" + - audit_logging: + parameter_value = "-1" + - log_level: + parameter_value = "-1" + - keepalive_count: + parameter_value = "-5" + variants daemon_name: + - virtqemud: + - virtnwfilterd: + - virtinterfaced: + - virtsecretd: + - virtproxyd: + - virtstoraged: + - virtnodedevd: + - virtnetworkd: + check_string_in_log = "load config file: internal error: /etc/libvirt/${daemon_name}.conf" diff --git a/libvirt/tests/src/daemon/conf_file/libvirtd_conf/check_negative_parameter.py b/libvirt/tests/src/daemon/conf_file/libvirtd_conf/check_negative_parameter.py new file mode 100644 index 00000000000..7f59e457475 --- /dev/null +++ b/libvirt/tests/src/daemon/conf_file/libvirtd_conf/check_negative_parameter.py @@ -0,0 +1,49 @@ +import logging +import time + +from avocado.utils import process + +from virttest import utils_config +from virttest import utils_libvirtd +from virttest import utils_split_daemons + +from virttest.utils_test import libvirt + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test libvirt should disallow negative value for options needed positive + integer etc in libvirtd.conf. + + """ + check_string_in_log = params.get("check_string_in_log") + daemon_name = params.get("daemon_name") + parameter_name = params.get("parameter_name") + parameter_value = params.get("parameter_value") + log_file = params.get("log_file") + require_modular_daemon = params.get('require_modular_daemon', "no") == "yes" + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + + utils_split_daemons.daemon_mode_check(require_modular_daemon) + daemon = utils_libvirtd.Libvirtd(daemon_name) + daemon_conf = utils_config.get_conf_obj(daemon_name) + + try: + cmd = "echo ' ' > %s" % log_file + process.run(cmd, shell=True) + + daemon_conf[parameter_name] = parameter_value + if not daemon.restart(wait_for_start=False): + LOG.info("%s restart failed as expected.", daemon_name) + else: + test.fail("Expect %s restart failed, but successfully." % daemon_name) + + time.sleep(1) + libvirt.check_logfile(check_string_in_log, log_file, str_in_log=True) + + finally: + daemon_conf.restore() + daemon.restart() From 4503bb304d890fe416ac875293f73b723c258667 Mon Sep 17 00:00:00 2001 From: Xiaodai Wang Date: Fri, 28 Jun 2024 15:46:13 +0800 Subject: [PATCH 0447/1055] aarch64: fix console connection issue on ARM Signed-off-by: Xiaodai Wang --- libvirt/tests/cfg/virsh_cmd/domain/virsh_console.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_console.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_console.cfg index 6b91c0af296..b1a8fdc9434 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_console.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_console.cfg @@ -11,6 +11,8 @@ console_password_not_root = "" update_console = "yes" console_device = "ttyS0" + aarch64: + console_device = "ttyAMA0" console_speed = "115200" variants: - normal_test: From 3b65a4130bfada66e672485d7cae99c8ca3dedbc Mon Sep 17 00:00:00 2001 From: lcheng Date: Fri, 21 Jun 2024 16:59:55 +0800 Subject: [PATCH 0448/1055] migration: Add case to verify panic device XXXX-301745 - Trigger guest os crash with coredump-restart on_crash event after migartion Signed-off-by: lcheng --- .../migration/migrate_with_panic_device.cfg | 33 +++++++ .../migration/migrate_with_panic_device.py | 96 +++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 libvirt/tests/cfg/migration/migrate_with_panic_device.cfg create mode 100644 libvirt/tests/src/migration/migrate_with_panic_device.py diff --git a/libvirt/tests/cfg/migration/migrate_with_panic_device.cfg b/libvirt/tests/cfg/migration/migrate_with_panic_device.cfg new file mode 100644 index 00000000000..0dd426652f9 --- /dev/null +++ b/libvirt/tests/cfg/migration/migrate_with_panic_device.cfg @@ -0,0 +1,33 @@ +- migrate.panic_device: + type = migrate_with_panic_device + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + migrate_desturi_port = "22" + migrate_desturi_type = "ssh" + virsh_migrate_desturi = "qemu+ssh://${migrate_dest_host}/system" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "${remote_user}" + server_pwd = "${migrate_dest_pwd}" + start_vm = 'no' + crash_action = "coredump-restart" + expected_match = "crashed.*(panicked).*" + dump_file_path = "/var/lib/libvirt/qemu/dump" + panic_dev = {"model": "isa", "addr_type": "isa", "addr_iobase": "0x505"} + aarch64: + panic_dev = {"model": "pvpanic", "addr_type": "pci"} diff --git a/libvirt/tests/src/migration/migrate_with_panic_device.py b/libvirt/tests/src/migration/migrate_with_panic_device.py new file mode 100644 index 00000000000..3d3ba30a1d6 --- /dev/null +++ b/libvirt/tests/src/migration/migrate_with_panic_device.py @@ -0,0 +1,96 @@ +import aexpect + +from virttest import remote +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.migration import base_steps + + +def run(test, params, env): + """ + Verify panic device works well after migration. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def setup_test(): + """ + Setup step + + """ + panic_model = params.get("panic_model") + addr_type = params.get("addr_type") + addr_iobase = params.get("addr_iobase") + dump_file_path = params.get("dump_file_path") + crash_action = params.get("crash_action") + panic_dev = eval(params.get("panic_dev")) + + test.log.info("Setup steps.") + migration_obj.setup_connection() + # Cleanup dump file + cmd = "rm -f %s/*" % dump_file_path + remote.run_remote_cmd(cmd, params) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + libvirt_vmxml.modify_vm_device(vmxml, 'panic', panic_dev) + vmxml.on_crash = crash_action + vmxml.sync() + test.log.info("Guest xml now is: %s", vmxml) + vm.start() + vm.wait_for_login().close() + + def verify_test(): + """ + Verify step + + """ + dest_uri = params.get("virsh_migrate_desturi") + expected_match = params.get("expected_match") + dump_file_path = params.get("dump_file_path") + + test.log.info("Verify steps.") + migration_obj.verify_default() + + backup_uri, vm.connect_uri = vm.connect_uri, dest_uri + vm.cleanup_serial_console() + vm.create_serial_console() + remote_vm_session = vm.wait_for_serial_login(timeout=360) + try: + remote_vm_session.cmd("systemctl stop kdump", ignore_all_errors=True) + remote_vm_session.cmd("echo 1 > /proc/sys/kernel/sysrq") + remote_vm_session.cmd_status_output("echo c > /proc/sysrq-trigger", timeout=3) + except aexpect.ShellTimeoutError: + # This is expected + pass + except Exception: + # This is unexpected + raise + + remote_vm_session.close() + ret = virsh.domstate(vm_name, extra="--reason", uri=dest_uri, debug=True) + libvirt.check_result(ret, expected_match=expected_match) + + # Check dump file + cmd = "ls %s" % dump_file_path + ret = remote.run_remote_cmd(cmd, params, ignore_status=False) + if vm_name not in ret.stdout_text.strip(): + test.fail("Not found dump file.") + + vm.destroy() + vm.connect_uri = backup_uri + + vm_name = params.get("migrate_main_vm") + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + setup_test() + migration_obj.run_migration() + verify_test() + finally: + migration_obj.cleanup_connection() From faf3d4be9500e5977205be5b30b1f345117c90f4 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Mon, 1 Jul 2024 15:11:46 +0800 Subject: [PATCH 0449/1055] Converting a guest via vmx+ssh without ssh-agent Signed-off-by: Ming Xie --- v2v/tests/cfg/convert_from_file.cfg | 8 ++++++++ v2v/tests/src/convert_from_file.py | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/v2v/tests/cfg/convert_from_file.cfg b/v2v/tests/cfg/convert_from_file.cfg index c7af03560c5..a6fed2b72e3 100644 --- a/v2v/tests/cfg/convert_from_file.cfg +++ b/v2v/tests/cfg/convert_from_file.cfg @@ -240,6 +240,14 @@ checkpoint = 'special_character' expect_msg = 'yes' msg_content = 'nbd_connect_uri.*No such file or directory.*' + - no_ssh_agent: + only esx_80 + version_required = "[virt-v2v-2.4.0-2.el9,)" + boottype = 3 + main_vm = VM_NAME_RHEL9_V2V_EXAMPLE + expect_msg = 'no' + msg_content = 'scp -T.*source.vmx' + checkpoint = 'no_ssh_agent' - vmx_default: # Default vmx_nfs_src = NFS_ESX70_VMX_V2V_EXAMPLE diff --git a/v2v/tests/src/convert_from_file.py b/v2v/tests/src/convert_from_file.py index 2b8431255d1..ffbb6499336 100644 --- a/v2v/tests/src/convert_from_file.py +++ b/v2v/tests/src/convert_from_file.py @@ -320,6 +320,12 @@ def vm_check(): if checkpoint == 'special_character': v2v_result = utils_v2v.cmd_run(str(utils_v2v.v2v_cmd(v2v_params, cmd_only=True)).replace('.vmx', '.vm*'), params.get('v2v_dirty_resources')) + elif checkpoint == 'no_ssh_agent': + esxi_passwd_file = "/tmp/v2v_esxi_passwd" + with open(esxi_passwd_file, 'w') as f: + f.write(esxi_password) + v2v_cmd = str(utils_v2v.v2v_cmd(v2v_params, cmd_only=True) + ' -ip %s' % esxi_passwd_file) + v2v_result = utils_v2v.cmd_run(v2v_cmd, params.get('v2v_dirty_resources')) else: v2v_result = utils_v2v.v2v_cmd(v2v_params) From 9a4df283ac76403d0ae8b4da8945f9a06efcc41b Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Mon, 1 Jul 2024 20:23:45 +0800 Subject: [PATCH 0450/1055] Exclude cases for aarch64 - SATA is not supported on ARM - genid is not support on ARM Signed-off-by: Dan Zheng --- libvirt/tests/cfg/migration_with_copy_storage/migrate_disks.cfg | 1 + libvirt/tests/cfg/snapshot/revert_snap_for_guest_with_genid.cfg | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration_with_copy_storage/migrate_disks.cfg b/libvirt/tests/cfg/migration_with_copy_storage/migrate_disks.cfg index 64b3bd5aa54..d4ba15bd32a 100644 --- a/libvirt/tests/cfg/migration_with_copy_storage/migrate_disks.cfg +++ b/libvirt/tests/cfg/migration_with_copy_storage/migrate_disks.cfg @@ -67,6 +67,7 @@ status_error = "yes" err_msg = "invalid argument: disk target aaa not found" - disk1_disk2_disk5: + no aarch64 setup_nfs = "no" nfs_mount_dir = virsh_migrate_extra = "--migrate-disks vda,vdb,sda" diff --git a/libvirt/tests/cfg/snapshot/revert_snap_for_guest_with_genid.cfg b/libvirt/tests/cfg/snapshot/revert_snap_for_guest_with_genid.cfg index 11e22677b49..0091b1c9f96 100644 --- a/libvirt/tests/cfg/snapshot/revert_snap_for_guest_with_genid.cfg +++ b/libvirt/tests/cfg/snapshot/revert_snap_for_guest_with_genid.cfg @@ -1,5 +1,5 @@ - snapshot_revert.with_genid: - no s390-virtio + no s390-virtio,aarch64 type = revert_snap_for_guest_with_genid start_vm = no func_supported_since_libvirt_ver = (9, 10, 0) From 6bcf793fdc0955e209445b746a06a2105e331d3d Mon Sep 17 00:00:00 2001 From: Yanqiu Zhang Date: Mon, 1 Jul 2024 22:47:57 -0400 Subject: [PATCH 0451/1055] tpm_device.cfg: update tpm1.2 errmsg again Update tpm1.2 errmsg again. Signed-off-by: Yanqiu Zhang --- libvirt/tests/cfg/virtual_device/tpm_device.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_device/tpm_device.cfg b/libvirt/tests/cfg/virtual_device/tpm_device.cfg index f97a71037a5..af25a725a43 100644 --- a/libvirt/tests/cfg/virtual_device/tpm_device.cfg +++ b/libvirt/tests/cfg/virtual_device/tpm_device.cfg @@ -194,7 +194,7 @@ variants: - version_1.2: backend_version = '1.2' - xml_errmsg = "Unsupported interface.*tpm-crb.*for TPM 1.2|TPM version '1.2' is not supported" + xml_errmsg = "Unsupported interface.*tpm-crb.*for TPM 1.2|TPM .*1.2.* is not supported" pseries: xml_errmsg = 'TPM 1.2 is not supported with the SPAPR device mode' - version_2: From f7ddb36655ecbfeb114eb6a3c85e184ab488ce32 Mon Sep 17 00:00:00 2001 From: lcheng Date: Fri, 31 May 2024 09:50:24 +0800 Subject: [PATCH 0452/1055] graphics: Add two cases about disable fips XXX-103778 - [vnc] Start guest with fips disabled and with vnc password XXX-103777 - [vnc] Start guest with fips disabled and without vnc password Signed-off-by: lcheng --- .../cfg/graphics/graphics_functional.cfg | 10 ++++++++++ .../tests/src/graphics/graphics_functional.py | 19 ++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/graphics/graphics_functional.cfg b/libvirt/tests/cfg/graphics/graphics_functional.cfg index 628ac0b47f0..7aa777a274d 100644 --- a/libvirt/tests/cfg/graphics/graphics_functional.cfg +++ b/libvirt/tests/cfg/graphics/graphics_functional.cfg @@ -339,6 +339,16 @@ valid_time = 60 opt_str = " --gtk-vnc-debug" rv_log_auth = "Authentication failed" + - disable_fips: + vnc_autoport = "yes" + check_fips = "yes" + check_qemu_pattern = "-enable-fips" + expect_exist = False + variants: + - without_passwd: + - with_passwd: + graphic_passwd = "PASSWORD.EXAMPLE" + vnc_passwd_place = "guest" - spice_vnc: spice_xml = yes vnc_xml = yes diff --git a/libvirt/tests/src/graphics/graphics_functional.py b/libvirt/tests/src/graphics/graphics_functional.py index 51168283408..84be3f1c830 100644 --- a/libvirt/tests/src/graphics/graphics_functional.py +++ b/libvirt/tests/src/graphics/graphics_functional.py @@ -989,10 +989,11 @@ def check_qemu_command_line(params): :param params: dict for parameters """ check_qemu_pattern = params.get('check_qemu_pattern') + expect_exist = eval(params.get('expect_exist', 'True')) if check_qemu_pattern: logging.debug("Checking qemu command line with " "pattern:%s", check_qemu_pattern) - libvirt.check_qemu_cmd_line(check_qemu_pattern) + libvirt.check_qemu_cmd_line(check_qemu_pattern, expect_exist=expect_exist) def handle_auto_filled_items(given_graphic_attrs, vm, params): @@ -1590,6 +1591,17 @@ def cleanup(params): libvirtd.restart() +def is_enable_fips(): + """ + Check FIPS status + + :param return: True or False, True for enable FIPS + """ + cmd = "cat /proc/sys/crypto/fips_enabled" + ret = process.run(cmd, shell=True) + return True if ret.stdout_text.strip() else False + + def run(test, params, env): """ Test of libvirt SPICE related features. @@ -1647,6 +1659,11 @@ def run(test, params, env): insecure_channels = params.get("insecure_channels", "not_set") autoport = params.get("spice_autoport", "yes") spice_tls = params.get("spice_tls", "not_set") + check_fips = params.get("check_fips", "no") == 'yes' + + if check_fips: + if not is_enable_fips(): + test.cancel("This test need to disable FIPS.") sockets = block_ports(params) networks = setup_networks(params, test) From e2a8fc8069291648e098042f0519598acc3a49c8 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 2 Jul 2024 18:22:03 +0800 Subject: [PATCH 0453/1055] vIOMMU: Update iommu cold plug cases Feature changed to support iommu device cold plug, so update the code. Signed-off-by: Yingshun Cui --- libvirt/tests/src/sriov/vIOMMU/attach_iommu_device.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libvirt/tests/src/sriov/vIOMMU/attach_iommu_device.py b/libvirt/tests/src/sriov/vIOMMU/attach_iommu_device.py index f4a602692bf..bf208b9acd8 100644 --- a/libvirt/tests/src/sriov/vIOMMU/attach_iommu_device.py +++ b/libvirt/tests/src/sriov/vIOMMU/attach_iommu_device.py @@ -25,6 +25,14 @@ def run(test, params, env): elif not attach_option and not vm.is_alive(): vm.start() vm.wait_for_login().close() + if libvirt_version.version_compare(10, 5, 0) and attach_option: + vmxml = vm_xml.VMXML.new_from_dumpxml(vm.name) + features = vmxml.features + if not features.has_feature('ioapic') and iommu_dict.get('model') == "intel": + features.add_feature('ioapic', 'driver', 'qemu') + vmxml.features = features + vmxml.sync() + err_msg = '' iommu_dev = libvirt_vmxml.create_vm_device_by_type('iommu', iommu_dict) test.log.debug(f"iommu device: {iommu_dev}") From e580e5555dce9d8c9af1f583a7581d1ade5417b0 Mon Sep 17 00:00:00 2001 From: Yan Fu Date: Wed, 3 Jul 2024 10:25:41 +0800 Subject: [PATCH 0454/1055] Remove pid file under /dir for daemon.kill_starting Signed-off-by: Yan Fu --- libvirt/tests/src/daemon/kill_starting.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/daemon/kill_starting.py b/libvirt/tests/src/daemon/kill_starting.py index fc9327a8e28..5aaedb9eb64 100644 --- a/libvirt/tests/src/daemon/kill_starting.py +++ b/libvirt/tests/src/daemon/kill_starting.py @@ -1,3 +1,4 @@ +import os import logging as log from virttest import utils_misc @@ -60,9 +61,14 @@ def get_service(send_signal_at): libvirtd.start(wait_for_working=False) - if not utils_misc.wait_for(lambda: bundle['recieved'], 20, 0.5): + if not utils_misc.wait_for(lambda: bundle['recieved'], 60, 0.5): test.fail("Expect receive signal, but not.") finally: libvirtd.exit() + # Remove pid file under /run + if serv_name: + default_pid_path = "/run/" + serv_name + ".pid" + if os.path.exists(default_pid_path): + os.remove(default_pid_path) # Need to restart libvirtd.socket after starting libvirtd in the foreground Libvirtd("libvirtd.socket").restart() From 5dd6536f87b3f1be121bd7cb71871ef82107af8f Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Tue, 2 Jul 2024 23:40:06 -0400 Subject: [PATCH 0455/1055] Fixup:Failed to return ip when there're more than one Signed-off-by: Haijiao Zhao --- provider/virtual_network/network_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/provider/virtual_network/network_base.py b/provider/virtual_network/network_base.py index cd3bc43a9c0..6f45b80ec5a 100644 --- a/provider/virtual_network/network_base.py +++ b/provider/virtual_network/network_base.py @@ -39,8 +39,8 @@ def get_vm_ip(session, mac, ip_ver="ipv4"): f'Cannot find ip addr with given mac: {mac}') elif len(target_addr) > 1: LOG.warn(f'Multiple ip addr: {target_addr}') - else: - return target_addr[0]['local'] + + return target_addr[0]['local'] def get_test_ips(session, mac, ep_session, ep_mac, net_name=None, From fb25e6fcc50ebcd38d0927a3483e7238b06641fe Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Wed, 3 Jul 2024 02:34:25 -0400 Subject: [PATCH 0456/1055] Add adaption for aarch64 4k kernel Signed-off-by: liang-cong-red-hat --- .../memory/memory_devices/change_virtio_mem_request_size.cfg | 5 ++--- .../memory/memory_devices/change_virtio_mem_request_size.py | 4 +--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_devices/change_virtio_mem_request_size.cfg b/libvirt/tests/cfg/memory/memory_devices/change_virtio_mem_request_size.cfg index da6a1724def..3626a1eeaa3 100644 --- a/libvirt/tests/cfg/memory/memory_devices/change_virtio_mem_request_size.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/change_virtio_mem_request_size.cfg @@ -2,12 +2,9 @@ type = change_virtio_mem_request_size no s390-virtio start_vm = yes - kernel_extra_params_add = "memhp_default_state=online_movable" - kernel_extra_params_remove = "memhp_default_state" mem_model = "virtio-mem" allocate_huge_pages = "4194304KiB" target_size = 1048576 - block_size = 2048 request_size = 524288 requested_unit = "KiB" basic_request = "${request_size}${requested_unit}" @@ -35,6 +32,8 @@ no file hugepages memfd mem_basic = {'mem_model': '${mem_model}', 'target': {'requested_unit': '${requested_unit}', 'size': %s, 'node': ${basic_node}, 'size_unit': 'KiB', 'requested_size': %s, 'block_unit': 'KiB', 'block_size': %s}} - running_guest: + kernel_extra_params_add = "memhp_default_state=online_movable" + kernel_extra_params_remove = "memhp_default_state" attach_node = 1 attached_device = "--node ${attach_node}" basic_device_alias = "--alias virtiomem0" diff --git a/libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py b/libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py index 98b4463089a..8e7bb6155f9 100644 --- a/libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py +++ b/libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py @@ -293,7 +293,7 @@ def run_test_shutoff_guest(): test.log.info("TEST_STEP3: Check the virtio-mem memory device config") converted_req = int(memory_base.convert_data_size(update_request_size, requested_unit)) check_list = [(target_size, 'size'), (converted_req, 'requested_size'), - (basic_node, 'node'), (block_size, 'block_size')] + (basic_node, 'node'), (params.get('default_pagesize'), 'block_size')] for items in check_list: check_various_size(test, vm_name, items[0], check_item=items[1]) @@ -349,13 +349,11 @@ def teardown_test(): vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) bkxml = vmxml.copy() vm = env.get_vm(vm_name) - memory_base.adjust_memory_size(params) allocate_huge_pages = re.findall(r'\d+', params.get("allocate_huge_pages"))[0] guest_state = params.get("guest_state") basic_node = params.get("basic_node") target_size = int(params.get("target_size")) - block_size = params.get("block_size") mem_basic = params.get("mem_basic", "{}") mem_attach = params.get("mem_attach", "{}") attached_device = params.get("attached_device") From 2d49575cacf5d5db38af25a4257b2e3b9e9914dd Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 3 Jul 2024 19:47:22 +0800 Subject: [PATCH 0457/1055] migration: Update for stress Update to use run_stress_in_vm() to install stress package. Signed-off-by: lcheng --- .../src/migration/migrate_options_shared.py | 14 ++--------- .../domain/virsh_migrate_option_mix.py | 23 ++----------------- 2 files changed, 4 insertions(+), 33 deletions(-) diff --git a/libvirt/tests/src/migration/migrate_options_shared.py b/libvirt/tests/src/migration/migrate_options_shared.py index 4cc5357beef..b5ebdd52941 100644 --- a/libvirt/tests/src/migration/migrate_options_shared.py +++ b/libvirt/tests/src/migration/migrate_options_shared.py @@ -3,7 +3,6 @@ import time import math import re -import threading import platform import tempfile import copy @@ -1324,17 +1323,8 @@ def cancel_bg_migration(): test.error("Failed to install tpm2-tools in vm") if stress_in_vm: - pkg_name = 'stress' - logging.debug("Check if stress tool is installed") - pkg_mgr = utils_package.package_manager(vm_session, pkg_name) - if not pkg_mgr.is_installed(pkg_name): - logging.debug("Stress tool will be installed") - if not pkg_mgr.install(): - test.error("Package '%s' installation fails" % pkg_name) - - stress_thread = threading.Thread(target=run_stress_in_vm, - args=()) - stress_thread.start() + params.update({"stress_package": "stress"}) + migration_test.run_stress_in_vm(vm, params) # Check maxdowntime before migration if check_default_maxdowntime: diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_migrate_option_mix.py b/libvirt/tests/src/virsh_cmd/domain/virsh_migrate_option_mix.py index f0857f7f360..2faab30e70f 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_migrate_option_mix.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_migrate_option_mix.py @@ -7,7 +7,6 @@ from virttest import utils_selinux from virttest import virsh -from virttest import utils_package from virttest import migration from virttest.utils_conn import TLSConnection from virttest.utils_test import libvirt @@ -227,26 +226,8 @@ def cleanup_vm(vm, vm_name='', uri=''): # Prepare for postcopy migration: install and run stress in VM if postcopy and src_vm_status == "running": logging.debug("Install and run stress in vm for postcopy migration") - pkg_name = 'stress' - - # Get a vm session - logging.debug("Get a vm session") - vm_session = vm.wait_for_login() - if not vm_session: - test.error("Can't get a vm session successfully") - - # Install package stress if it is not installed in vm - logging.debug("Check if stress tool is installed for postcopy migration") - pkg_mgr = utils_package.package_manager(vm_session, pkg_name) - if not pkg_mgr.is_installed(pkg_name): - logging.debug("Stress tool will be installed") - if not pkg_mgr.install(): - test.error("Package '%s' installation fails" % pkg_name) - - # Run stress in vm - logging.debug("Run stress in vm") - stress_args = params.get("stress_args") - vm_session.cmd('stress %s' % stress_args) + params.update({"stress_package": "stress"}) + obj_migration.run_stress_in_vm(vm, params) # Prepare for --xml . if xml_option: From 5f0c0fe30ae2c4dee724d1070dda67011d5e9c7a Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Thu, 4 Jul 2024 10:20:40 +0800 Subject: [PATCH 0458/1055] vIOMMU: Fixup a timeout issue There might be some other outputs after showing 'login:', so update the pattern for checking vm reboot. Signed-off-by: Yingshun Cui --- libvirt/tests/src/sriov/vIOMMU/iommu_device_lifecycle.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/sriov/vIOMMU/iommu_device_lifecycle.py b/libvirt/tests/src/sriov/vIOMMU/iommu_device_lifecycle.py index 9b406db09be..7b82bcb1c3b 100644 --- a/libvirt/tests/src/sriov/vIOMMU/iommu_device_lifecycle.py +++ b/libvirt/tests/src/sriov/vIOMMU/iommu_device_lifecycle.py @@ -65,8 +65,8 @@ def run(test, params, env): session = vm.wait_for_serial_login( timeout=int(params.get('login_timeout'))) session.sendline(params.get("reboot_command")) - _match, _text = session.read_until_last_line_matches( - [r"[Ll]ogin:\s*$"], timeout=240, internal_timeout=0.5) + _match, _text = session.read_until_output_matches( + [r"[Ll]ogin:\s*"], timeout=240, internal_timeout=0.5) session.close() session = vm.wait_for_serial_login( From 81251a279806daebdcdd8a69c37e454db37aa135 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Wed, 3 Jul 2024 22:37:01 -0400 Subject: [PATCH 0459/1055] Virtual_disk: fix persistent reservation failed issue BZ1652220 give a workaround to fix the "Device not ready". To reduce the frequency of problems, add this workaround to script. Signed-off-by: Meina Li --- .../virtual_disks_scsi3_persistent_reservation.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_scsi3_persistent_reservation.py b/libvirt/tests/src/virtual_disks/virtual_disks_scsi3_persistent_reservation.py index 992a96213e2..c17ccf61796 100644 --- a/libvirt/tests/src/virtual_disks/virtual_disks_scsi3_persistent_reservation.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_scsi3_persistent_reservation.py @@ -1,8 +1,10 @@ import logging as log import time import shutil +import os from avocado.utils import service +from avocado.utils import process from virttest import virt_vm from virttest import virsh @@ -143,6 +145,11 @@ def ppc_controller_update(): vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) try: + # Prepare a /etc/target/pr directory based on BZ1652220 + target_pr = "/etc/target/pr" + if not os.path.exists(target_pr): + process.run("mkdir -p %s" % target_pr, shell=True, ignore_status=False) + # Setup iscsi target blk_dev = libvirt.setup_or_cleanup_iscsi(is_setup=True, is_login=True, @@ -206,3 +213,5 @@ def ppc_controller_update(): libvirt.setup_or_cleanup_iscsi(is_setup=False) # Stop qemu-pr-helper daemon start_or_stop_qemu_pr_helper(is_start=False) + if os.path.exists(target_pr): + shutil.rmtree(target_pr) From fddac607820516c8d66860adc4de5695dcca92a0 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Tue, 2 Jul 2024 01:08:53 -0400 Subject: [PATCH 0460/1055] Update the error message match Update the error message for passt negative scenarios since the error messages changes now. Signed-off-by: Yalan Zhang --- .../cfg/virtual_network/passt/passt_negative_setting.cfg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_negative_setting.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_negative_setting.cfg index 97d030aec40..5dbe4ecdc17 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_negative_setting.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_negative_setting.cfg @@ -35,13 +35,13 @@ error_msg = External interface not usable - non_exist_bind_ip: portForwards = {'portForwards': [{'ranges': [{'start': '9000'}], 'attrs': {'proto': 'tcp', 'address': 'IP_EXAMPLE'}}]} - error_msg = Failed to bind any port for '-t .*', exiting + error_msg = Failed to bind port - port_occupied: portForwards = {'portForwards': [{'ranges': [{'start': 'PORT_EXAMPLE'}], 'attrs': {'proto': 'tcp'}}]} - error_msg = Failed to bind any port for '-t .*', exiting + error_msg = Failed to bind port - port_under_1024: portForwards = {'portForwards': [{'ranges': [{'start': 'PORT_EXAMPLE'}], 'attrs': {'proto': 'tcp'}}]} - error_msg = Failed to bind any port for '-t .*', exiting + error_msg = Failed to bind port - port_outofrange: port = 65536 portForwards = {'portForwards': [{'ranges': [{'start': '${port}'}], 'attrs': {'proto': 'tcp'}}]} From 7ca1ebd6a1b99e71e2b8432ca9eec945b036b588 Mon Sep 17 00:00:00 2001 From: Yan Fu Date: Thu, 4 Jul 2024 14:45:35 +0800 Subject: [PATCH 0461/1055] Wait for guest os booting before hotunplug devices Signed-off-by: Yan Fu --- .../update_device/update_iface_with_identifier.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_with_identifier.py b/libvirt/tests/src/virtual_network/update_device/update_iface_with_identifier.py index ebaf060cb58..24e305d55ba 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_with_identifier.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_with_identifier.py @@ -95,9 +95,10 @@ def run(test, params, env): f'{update_attrs["link_state"]}') elif operation == 'hotunplug': + vm.wait_for_serial_login().close() dt_result = virsh.detach_device(vm_name, iface.xml, wait_for_event=True, - event_timeout=20, + event_timeout=120, debug=True) check_cmd_result(dt_result, status_error, err_msg) if status_error: From 903cc13ba4c714dac5ae65fa5c62adec3781751c Mon Sep 17 00:00:00 2001 From: nanli Date: Fri, 5 Jul 2024 10:43:42 +0800 Subject: [PATCH 0462/1055] fix not running error when save domain give login when first start domain Signed-off-by: nanli --- .../tests/src/memory/memory_backing/lifecycle_for_hugepage.py | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/src/memory/memory_backing/lifecycle_for_hugepage.py b/libvirt/tests/src/memory/memory_backing/lifecycle_for_hugepage.py index 905fe53661c..82bb54b5efa 100644 --- a/libvirt/tests/src/memory/memory_backing/lifecycle_for_hugepage.py +++ b/libvirt/tests/src/memory/memory_backing/lifecycle_for_hugepage.py @@ -157,6 +157,7 @@ def run_test(vm, params, test): libvirt.check_result(ret, expected_fails=start_error) if start_error: return + vm.wait_for_login().close() vmxml = vm_xml.VMXML.new_from_dumpxml(vm.name) test.log.debug("After start vm, get vmxml is :%s", vmxml) From 67c055ed8741c87ce0c4bbb5d77e4cbd5b1a21dc Mon Sep 17 00:00:00 2001 From: lcheng Date: Fri, 5 Jul 2024 16:11:10 +0800 Subject: [PATCH 0463/1055] migration: Fix missing lsof package issue on target host Signed-off-by: lcheng --- libvirt/tests/src/migration/memory_copy_mode/memory_copy_mode.py | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/src/migration/memory_copy_mode/memory_copy_mode.py b/libvirt/tests/src/migration/memory_copy_mode/memory_copy_mode.py index c4f2f6f699d..5d06e056fd6 100644 --- a/libvirt/tests/src/migration/memory_copy_mode/memory_copy_mode.py +++ b/libvirt/tests/src/migration/memory_copy_mode/memory_copy_mode.py @@ -22,6 +22,7 @@ def verify_postcopy(): migration_obj.verify_default() if libvirt_version.version_compare(10, 1, 0): + remote.run_remote_cmd("yum install lsof -y", params) # Check libvirt pass userfaultfd in vm namespace and qemu can access # this file correctly after postcopy migration on target host. cmd = "nsenter -a -t `pidof qemu-kvm` lsof /dev/userfaultfd" From e81afc891a523a6a258065e587d40992cc7e6cfd Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 5 Jul 2024 16:43:52 +0800 Subject: [PATCH 0464/1055] virsh_guestinfo: Remove color of "ip" output The output of ip command in the VM needs to be updated to avoid format issues. Signed-off-by: Yingshun Cui --- libvirt/tests/src/virsh_cmd/domain/virsh_guestinfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_guestinfo.py b/libvirt/tests/src/virsh_cmd/domain/virsh_guestinfo.py index e40087a4a32..255bba0c9d5 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_guestinfo.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_guestinfo.py @@ -304,7 +304,7 @@ def check_guest_interface_info(): if_info = {} session = vm.wait_for_login() try: - ip_cmd = 'ip a' + ip_cmd = 'ip -c=never a' ip_lines = session.cmd_output(ip_cmd).strip().splitlines() if_info = parse_interface_info(ip_lines) finally: From 199755bf4762d7902f3e87a2fe8e1a1ea70034d4 Mon Sep 17 00:00:00 2001 From: Slancaster1 Date: Fri, 5 Jul 2024 09:24:20 -0400 Subject: [PATCH 0465/1055] virsh_event: Fix leaked cluster error on kill_qemu -- The Issue The kill_qemu test case sends a SIGKILL signal to qemu, then checks to make sure the signal is properly detected Killing qemu sometimes results in corruption of the qcow2 image in the form of leaked clusters. This is a natural side effect of the test. So, this should not result in a test failure -- The Fix Suppress the error by setting the skip_cluster_leak_warn option to "yes" Signed-off-by: Slancaster1 --- libvirt/tests/cfg/event/virsh_event.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/cfg/event/virsh_event.cfg b/libvirt/tests/cfg/event/virsh_event.cfg index d41c7d63e42..e73af6bf4e6 100644 --- a/libvirt/tests/cfg/event/virsh_event.cfg +++ b/libvirt/tests/cfg/event/virsh_event.cfg @@ -57,6 +57,7 @@ only test_events events_list = "kill_qemu" signal = 'SIGKILL' + skip_cluster_leak_warn = "yes" - reboot_event: event_name = "reboot" events_list = "reset" From 3586edb72093df2f6be3f194e0157d6c01351920 Mon Sep 17 00:00:00 2001 From: Slancaster1 Date: Tue, 2 Jul 2024 10:54:49 -0400 Subject: [PATCH 0466/1055] boot_from_usb_device: Package is not installed - The Issue: Regardless of which subtest is run, boot_from_usb_device checks for the existance of usbredirdev and lsusb. This check is not required for the block_device test. But this test still fails on platforms that do not support usbredirdev, such as aarch64. - The Fix Paramaterize the test, so that each subtest can specify a list of required commands. This way block_device and usbredirdev tests can specify their required packages individually. And the lack of a required command for redirdev will not fail block_device --- .../guest_os_booting/boot_order/boot_from_usb_device.cfg | 1 + .../src/guest_os_booting/boot_order/boot_from_usb_device.py | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg index 4b25adba0c2..b3e6924fa5f 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg @@ -16,5 +16,6 @@ port_num = "4000" device_attrs = {'source': {'host': 'localhost', 'service': '4000', 'mode': 'connect'}, 'protocol': {'type': 'raw'}, 'type_name': 'tcp', 'bus': '${bus_type}', 'type': 'tcp', 'boot': {'order': '1'}} only q35 + required_cmds = ['usbredirserver', 'lsusb'] - hostdev_device: device_attrs = {'type_name': 'usb', 'mode': 'subsystem', 'source': {'vendor_id': '%s', 'product_id': '%s'}, 'type': 'usb', 'managed': 'no', 'boot_order': '1'} diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_usb_device.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_usb_device.py index ccabdaf1cd5..5c1d47cf463 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_usb_device.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_usb_device.py @@ -68,6 +68,7 @@ def check_boot_order(): device_attrs = eval(params.get("device_attrs", "{}")) port_num = params.get("port_num") check_prompt = params.get("check_prompt") + required_cmds = eval(params.get("required_cmds", "[]")) vm = env.get_vm(vm_name) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) @@ -77,8 +78,9 @@ def check_boot_order(): disk_obj = disk_base.DiskBase(test, vm, params) try: - if not (shutil.which("lsusb") and shutil.which("usbredirserver")): - test.error("Package related with usb command is not installed. Please install it.") + for cmd in required_cmds: + if not (shutil.which(cmd)): + test.fail("Command '{}' is not available. Please install the relevant package(s)".format(cmd)) vmxml = guest_os.prepare_os_xml(vm_name, bootmenu_dict) vmxml.remove_all_boots() From 32d904d6b5d77338dcde3381b161f6dca5cc7faa Mon Sep 17 00:00:00 2001 From: nanli Date: Mon, 8 Jul 2024 21:21:09 +0800 Subject: [PATCH 0467/1055] update internal snapshot with external snapshot xxxx-17255 Snapshot of shutoff guest with random backend virtio-rng device. Signed-off-by: nanli --- libvirt/tests/cfg/security/rng/libvirt_rng.cfg | 2 ++ libvirt/tests/src/security/rng/libvirt_rng.py | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/security/rng/libvirt_rng.cfg b/libvirt/tests/cfg/security/rng/libvirt_rng.cfg index 3cc5376d804..b3654e6bbb4 100644 --- a/libvirt/tests/cfg/security/rng/libvirt_rng.cfg +++ b/libvirt/tests/cfg/security/rng/libvirt_rng.cfg @@ -9,6 +9,7 @@ # For example, devices that are provided by the CPU. ignored_devices = s390-trng,trng,tpm-rng-0 dd_throughput = "bs=512 count=10" + snap_options = " %s" variants: - hotplug_unplug: only backend_rdm.default, backend_tcp, backend_udp, backend_builtin @@ -118,6 +119,7 @@ variants: - back_rdm: backend_dev = "/dev/random" + snap_options = "%s --disk-only" - back_tcp_connect: backend_model = "egd" backend_type = "tcp" diff --git a/libvirt/tests/src/security/rng/libvirt_rng.py b/libvirt/tests/src/security/rng/libvirt_rng.py index a88fb5634de..0c0a0ab340f 100644 --- a/libvirt/tests/src/security/rng/libvirt_rng.py +++ b/libvirt/tests/src/security/rng/libvirt_rng.py @@ -38,6 +38,7 @@ def run(test, params, env): """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) + snap_options = params.get("snap_options") def check_rng_xml(xml_set, exists=True): """ @@ -272,7 +273,8 @@ def check_snapshot(bgjob=None): snapshot_name2 = "snap.s2" if not snapshot_vm_running: vm.destroy(gracefully=False) - ret = virsh.snapshot_create_as(vm_name, snapshot_name1, debug=True) + ret = virsh.snapshot_create_as( + vm_name, options=snap_options % snapshot_name1, debug=True) libvirt.check_exit_status(ret) snap_lists = virsh.snapshot_list(vm_name, debug=True) if snapshot_name not in snap_lists: @@ -548,7 +550,8 @@ def rotate_audit_log(): if snapshot_vm_running: vm.start() vm.wait_for_login().close() - ret = virsh.snapshot_create_as(vm_name, snapshot_name, debug=True) + ret = virsh.snapshot_create_as( + vm_name, options=snap_options % snapshot_name, debug=True) libvirt.check_exit_status(ret) # Destroy VM first From ba1aaf2a3350df69974c88ce39b781f4432f78f9 Mon Sep 17 00:00:00 2001 From: nanli Date: Mon, 8 Jul 2024 15:17:20 +0800 Subject: [PATCH 0468/1055] add rbd with luks scenario in blockcopy with dest xml case xxxx-294410: Do blockcopy with different dest XML - rbd with luks and auth Signed-off-by: nanli --- .../blockcopy_with_different_dest_xml.cfg | 17 ++++++ provider/virtual_disk/disk_base.py | 55 ++++++++++++++++--- 2 files changed, 63 insertions(+), 9 deletions(-) diff --git a/libvirt/tests/cfg/backingchain/blockcopy/blockcopy_with_different_dest_xml.cfg b/libvirt/tests/cfg/backingchain/blockcopy/blockcopy_with_different_dest_xml.cfg index cbbc22b7d37..c7262e47ef9 100644 --- a/libvirt/tests/cfg/backingchain/blockcopy/blockcopy_with_different_dest_xml.cfg +++ b/libvirt/tests/cfg/backingchain/blockcopy/blockcopy_with_different_dest_xml.cfg @@ -30,6 +30,23 @@ rbd_image_size = "${image_size}" sec_dict = {"secret_ephemeral": "no", "secret_private": "yes", "description": "sec_desc", "usage": "ceph", "usage_name": "cephlibvirt"} dest_disk_dict = {"type_name":"network", "target":{"dev": "${target_disk}", "bus": "scsi"}, "driver": {"name": "qemu", "type":"raw"}} + - rbd_with_luks_and_auth: + source_disk_dict = {"type_name":"${source_disk_type}", "target":{"dev": "${target_disk}", "bus": "scsi"}, "driver": {"name": "qemu", "type":"qcow2"}} + dest_disk_type = "rbd_with_luks_and_auth" + mon_host = "EXAMPLE_MON_HOST" + auth_key = "EXAMPLE_AUTH_KEY" + auth_user = "EXAMPLE_AUTH_USER" + image_path = "EXAMPLE_IMAGE_PATH" + client_name = "EXAMPLE_CLIENT_NAME" + rbd_image_size = "${image_size}" + ceph_usage_name="cephlibvirt" + sec_dict = {"secret_ephemeral": "no", "secret_private": "yes", "description": "sec_desc_auth", "usage": "ceph", "usage_name": "${ceph_usage_name}"} + dest_disk_dict = {"type_name":"network", "target":{"dev": "${target_disk}", "bus": "scsi"}, "driver": {"name": "qemu", "type":"raw"}} + private_key_password = "EXAMPLE_PWD" + secret_pwd = "`printf %s ${private_key_password} | base64`" + rbd_image_format = "luks" + rbd_image_parameter = "--object secret,id=luks1.img_luks0,data=${secret_pwd},format=base64 -o key-secret=luks1.img_luks0 rbd:{}:id={}:key={}:auth_supported=cephx:mon_host={}" + luks_sec_dict = {"secret_ephemeral": "no", "secret_private": "yes", "description": "sec_desc_luks", "usage": "volume", "volume":"%s", "uuid":"198784e8-f977-40ac-8d0d-4d0fcca70588"} - nbd_disk: dest_disk_type = "nbd" nbd_server_port = "10808" diff --git a/provider/virtual_disk/disk_base.py b/provider/virtual_disk/disk_base.py index 6ba294dcfbe..a98ad7614e0 100644 --- a/provider/virtual_disk/disk_base.py +++ b/provider/virtual_disk/disk_base.py @@ -120,9 +120,10 @@ def prepare_disk_obj(self, disk_type, disk_dict, new_image_path='', **kwargs): size = kwargs.get("size", "50M") if kwargs.get("size"): kwargs.pop("size") - libvirt.create_local_disk("file", path=new_image_path, size=size, - disk_format=self.params.get("disk_image_format", 'qcow2'), - **kwargs) + libvirt.create_local_disk( + "file", path=new_image_path, size=size, + disk_format=self.params.get("disk_image_format", 'qcow2'), + **kwargs) disk_dict.update({'source': {'attrs': {'file': new_image_path}}}) elif disk_type == 'block': @@ -163,6 +164,17 @@ def prepare_disk_obj(self, disk_type, disk_dict, new_image_path='', **kwargs): "auth": {"auth_user": auth_username, "secret_usage": "cephlibvirt", "secret_type": "ceph"}}}) + elif disk_type == 'rbd_with_luks_and_auth': + mon_host, auth_username, new_image_path, _ = \ + self.create_rbd_disk_path(self.params, create_img_by_qemu_cmd=True) + disk_dict.update({'source': { + 'attrs': {'protocol': "rbd", "name": new_image_path}, + "hosts": [{"name": mon_host}], + "auth": {"auth_user": auth_username, + "secret_usage": self.params.get("ceph_usage_name"), + "secret_type": "ceph"}}}) + self.add_luks_encryption_to_disk_dict( + disk_dict, self.params.get("luks_sec_dict") % new_image_path) elif disk_type == "nbd": nbd_server_host = process.run('hostname', ignore_status=False, @@ -198,6 +210,22 @@ def prepare_disk_obj(self, disk_type, disk_dict, new_image_path='', **kwargs): return disk_obj, new_image_path + def add_luks_encryption_to_disk_dict(self, disk_dict, secret_dict): + """ + Add luks encryption to disk dict. + + :param disk_dict: disk dict. + :param secret_dict: secret dict to define a secret. + """ + sec_uuid = libvirt_secret.create_secret(sec_dict=eval(secret_dict)) + virsh.secret_set_value(sec_uuid, self.params.get("secret_pwd"), + debug=True, ignore_status=False) + disk_source = disk_dict["source"] + disk_source.update( + {"encryption": {"secret": {"type": "passphrase", "uuid": sec_uuid}, + "encryption": "luks", "attrs": {"engine": "librbd"}}}) + return disk_dict + def cleanup_disk_preparation(self, disk_type): """ Clean up the preparation of different type disk @@ -219,7 +247,7 @@ def cleanup_disk_preparation(self, disk_type): elif disk_type == 'nfs': libvirt.setup_or_cleanup_nfs(is_setup=False) - elif disk_type == "rbd_with_auth": + elif disk_type in ["rbd_with_auth", "rbd_with_luks_and_auth"]: self.cleanup_rbd_disk_path(self.params) elif disk_type == "nbd": @@ -311,11 +339,13 @@ def cleanup_rbd_disk_path(params): os.remove(params.get('configfile')) @staticmethod - def create_rbd_disk_path(params): + def create_rbd_disk_path(params, create_img_by_qemu_cmd=False): """ Prepare rbd type disk image path :params params: Dict with the test parameters. + :params create_img_by_qemu_cmd: The flag for whether creating rbd type + image by qemu, default False :return: tuple, include monitor host, auth username, new image path and secret uuid """ @@ -337,10 +367,17 @@ def create_rbd_disk_path(params): sec_uuid = libvirt_secret.create_secret(sec_dict=sec_dict) virsh.secret_set_value(sec_uuid, auth_key, debug=True) - ceph.rbd_image_rm(mon_host, new_image_path.split("/")[0], - new_image_path.split("/")[1]) - ceph.rbd_image_create(mon_host, new_image_path.split("/")[0], - new_image_path.split("/")[1], rbd_image_size) + if not create_img_by_qemu_cmd: + ceph.rbd_image_rm(mon_host, new_image_path.split("/")[0], + new_image_path.split("/")[1]) + ceph.rbd_image_create(mon_host, new_image_path.split("/")[0], + new_image_path.split("/")[1], rbd_image_size) + else: + libvirt.create_local_disk( + disk_type="file", path='', + extra=params.get("rbd_image_parameter").format( + new_image_path, auth_username, auth_key, mon_host), + disk_format=params.get("rbd_image_format"), size=rbd_image_size) return mon_host, auth_username, new_image_path, sec_uuid From 93e71c495bb1f1175da616b23c57d4f8659f23c7 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Tue, 9 Jul 2024 17:32:53 +0800 Subject: [PATCH 0469/1055] revert_snap_with_flags: fix incorrect nvram file on arm On aarm64, the default nvram file name is different from the one on x86_64. Signed-off-by: Dan Zheng --- libvirt/tests/cfg/snapshot/revert_snap_with_flags.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/cfg/snapshot/revert_snap_with_flags.cfg b/libvirt/tests/cfg/snapshot/revert_snap_with_flags.cfg index ceb62c9de10..367823378b0 100644 --- a/libvirt/tests/cfg/snapshot/revert_snap_with_flags.cfg +++ b/libvirt/tests/cfg/snapshot/revert_snap_with_flags.cfg @@ -5,6 +5,8 @@ target_disk = 'vda' disk_type = 'file' vars_path = "/var/lib/libvirt/qemu/nvram/${main_vm}_VARS.fd" + aarch64: + vars_path = "/var/lib/libvirt/qemu/nvram/${main_vm}_VARS.qcow2" snap1_options = "%s --diskspec vda,snapshot=external,file=/tmp/vda.%s" snap2_options = "%s --memspec snapshot=external,file=/tmp/mem.%s --diskspec vda,snapshot=external,file=/tmp/vda.%s" flags = [" --current --paused"," --running --reset-nvram", " --force"] From f1296094c091a1f913dfb369849d2dcb192f0268 Mon Sep 17 00:00:00 2001 From: Slancaster1 Date: Fri, 21 Jun 2024 14:12:13 -0400 Subject: [PATCH 0470/1055] vm_start_destroy_repeatedly: Test for vm reliablity In order to test vm start-login-destroy reliability, this test executes the following test: 1) Start the vm 2) Verify the vm is alive 3) Log into the vm 4) Log out of the vm 5) Destroy the vm This process is executed 'num_cycles' number of times, as specified in the configuration file. Signed-off-by: Slancaster1 --- .../tests/cfg/vm_start_destroy_repeatedly.cfg | 4 ++ .../tests/src/vm_start_destroy_repeatedly.py | 60 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 libvirt/tests/cfg/vm_start_destroy_repeatedly.cfg create mode 100644 libvirt/tests/src/vm_start_destroy_repeatedly.py diff --git a/libvirt/tests/cfg/vm_start_destroy_repeatedly.cfg b/libvirt/tests/cfg/vm_start_destroy_repeatedly.cfg new file mode 100644 index 00000000000..b4e510f38e9 --- /dev/null +++ b/libvirt/tests/cfg/vm_start_destroy_repeatedly.cfg @@ -0,0 +1,4 @@ +- vm_start_destroy_repeatedly: + type = vm_start_destroy_repeatedly + num_cycles = 2000 + start_vm = no diff --git a/libvirt/tests/src/vm_start_destroy_repeatedly.py b/libvirt/tests/src/vm_start_destroy_repeatedly.py new file mode 100644 index 00000000000..366e25f56b1 --- /dev/null +++ b/libvirt/tests/src/vm_start_destroy_repeatedly.py @@ -0,0 +1,60 @@ +import logging +import time +from virttest import virsh +from virttest import utils_misc + + +def power_cycle_vm(test, vm, vm_name, login_timeout, startup_wait, resume_wait): + """ + Cycle vm through start-login-shutdown loop + + :param vm: vm object + :param vm_name: vm name + :param login_timeout: timeout given to vm.wait_for_login + :param startup_wait: how long to wait after the vm has been started + :param resume_wait: how long to wait after the paused vm is resumed + + This tests the vm startup and destroy sequences by: + 1) Starting the vm + 2) Verifying the vm is alive + 3) Logging into vm + 4) Logging out of the vm + 5) Destroying the vm + """ + + virsh.start(vm_name, options="--paused", ignore_status=False) + time.sleep(startup_wait) + + virsh.resume(vm_name, ignore_status=False) + time.sleep(resume_wait) + + session = vm.wait_for_login(timeout=login_timeout) + session.close() + + virsh.shutdown(vm_name, ignore_status=False) + + utils_misc.wait_for(lambda: vm.state() == "shut off", 360) + if vm.state() != "shut off": + test.fail("Failed to shutdown VM") + + +def run(test, params, env): + """ + Test qemu-kvm startup reliability + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + num_cycles = int(params.get("num_cycles")) # Parameter to control the number of times to start/restart the vm + login_timeout = float(params.get("login_timeout", 240)) # Controls vm.wait_for_login() timeout + startup_wait = float(params.get("startup_wait", 2)) # Controls wait time for virsh.start() + resume_wait = float(params.get("resume_wait", 40)) # Controls wait for virsh.resume() + + for i in range(num_cycles): + logging.info("Starting vm '%s' -- attempt #%d", vm_name, i+1) + power_cycle_vm(test, vm, vm_name, login_timeout, startup_wait, resume_wait) + logging.info("\t-> Completed vm '%s' power cycle #%d", vm_name, i+1) From 1398d6a35b91bf61e9d96181ac3e2210b6b4c9a9 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Tue, 9 Jul 2024 23:03:23 -0400 Subject: [PATCH 0471/1055] Fix err prompt for no numa node in memory device xml Signed-off-by: liang-cong-red-hat --- .../dimm_memory_with_memory_alloccation_and_numa.cfg | 2 ++ .../dimm_memory_with_memory_alloccation_and_numa.py | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_memory_alloccation_and_numa.cfg b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_memory_alloccation_and_numa.cfg index ab2d6e486da..c1c1f018add 100644 --- a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_memory_alloccation_and_numa.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_memory_alloccation_and_numa.cfg @@ -61,5 +61,7 @@ hotplug_error = "count of memory devices requiring memory slots '1' exceeds slots count '0'" - coldplug_without_node: coldplug_error_2 = "cannot use/hotplug a memory device when domain 'maxMemory' is not defined" + with_slot: + coldplug_error_2 = "target NUMA node needs to be specified for memory device" - coldplug_with_node: dimm_dict = ${dimm_node_dict} diff --git a/libvirt/tests/src/memory/memory_devices/dimm_memory_with_memory_alloccation_and_numa.py b/libvirt/tests/src/memory/memory_devices/dimm_memory_with_memory_alloccation_and_numa.py index ad3ccfe555a..a80e1f07bd2 100644 --- a/libvirt/tests/src/memory/memory_devices/dimm_memory_with_memory_alloccation_and_numa.py +++ b/libvirt/tests/src/memory/memory_devices/dimm_memory_with_memory_alloccation_and_numa.py @@ -96,7 +96,10 @@ def check_coldplug_result(params, result): coldplug_error_2 = params.get("coldplug_error_2") if mem_alloc == "with_slot": - libvirt.check_exit_status(result) + if device_operation == "coldplug_without_node": + libvirt.check_result(result, coldplug_error_2) + else: + libvirt.check_exit_status(result) elif mem_alloc == "no_slot": libvirt.check_result(result, coldplug_error) elif mem_alloc == "no_maxmemory": From c370c1ecd15307ac9f33bdec4bcc04fd5cbd7b35 Mon Sep 17 00:00:00 2001 From: Yan Fu Date: Wed, 10 Jul 2024 15:25:19 +0800 Subject: [PATCH 0472/1055] Remove the pid file of virtnetworkd starting at foreground Signed-off-by: Yan Fu --- libvirt/tests/src/libvirtd_start.py | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/src/libvirtd_start.py b/libvirt/tests/src/libvirtd_start.py index 03a02855704..08210ced845 100644 --- a/libvirt/tests/src/libvirtd_start.py +++ b/libvirt/tests/src/libvirtd_start.py @@ -149,6 +149,7 @@ def _check_errors(): _check_errors() finally: logging.info('Recovering services status') + process.run("rm -rf /run/virtnetworkd.pid", ignore_status=True) #Restart socket service after starting process at foreground utils_libvirtd.Libvirtd("virtnetworkd.socket").restart() # If service do not exists, then backup status and current status From 0a159606384d5240c24dd9606dd7b1e1f601e1d5 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Wed, 10 Jul 2024 16:32:16 +0800 Subject: [PATCH 0473/1055] Delete unnecessary output restrictions for v2v Signed-off-by: Ming Xie --- v2v/tests/cfg/function_test_esx.cfg | 2 +- v2v/tests/cfg/specific_kvm.cfg | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 5b41f1097e3..298cdd47cee 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -55,7 +55,6 @@ only uefi.win2019 - libvirt: only dest_libvirt - only uefi,GPO_AV,special_name,suse,local_storage,unset,lvm_multiple_disks,genid_xml - rhev: only dest_rhev.NFS variants: @@ -66,6 +65,7 @@ rhv_upload_opts = "-oc ${ovirt_engine_url} -op ${rhv_upload_passwd_file} -oo rhv-cafile=${local_ca_file_path} -oo rhv-cluster=${cluster_name}" - rhv: output_method = "rhev" + no uefi,GPO_AV,special_name,suse,local_storage,unset,lvm_multiple_disks,genid_xml variants: - esx_70: only source_esx.esx_70 diff --git a/v2v/tests/cfg/specific_kvm.cfg b/v2v/tests/cfg/specific_kvm.cfg index fff9ba70d1a..da9b5e08dad 100644 --- a/v2v/tests/cfg/specific_kvm.cfg +++ b/v2v/tests/cfg/specific_kvm.cfg @@ -304,7 +304,6 @@ no display.mix no win_rootonlinux no non_exist_network - only output_mode.rhev - windows: os_type = 'windows' shutdown_command = 'shutdown /s /f /t 0' @@ -324,7 +323,6 @@ restart_network = 'ipconfig /renew' vm_user = 'Administrator' vm_pwd = DEFAULT_WIN_VM_PASSWORD - only output_mode.rhev variants: - multi_disks: only multi_disks.windows @@ -353,12 +351,10 @@ checkpoint = ${vm_state} - serial_terminal: only default.esx.esx_70 - only output_mode.rhev msg_content = 'virt-v2v: error: no kernels were found in the bootloader configuration' expect_msg = 'yes' main_vm = "VM_GUEST_SERIAL_TERMINAL_V2V_EXAMPLE" - no_space: - only output_mode.rhev expect_msg = 'yes' variants: - host: @@ -368,7 +364,5 @@ msg_content = 'virt-v2v: error: insufficient free space in the conversion server' - unclean_file_system: only unclean_fs - only output_mode.rhev - fstab_invalid: only fstab.invalid - only output_mode.rhev From 301cf4127ab7b0e72b7b3884f3a0ab1267904318 Mon Sep 17 00:00:00 2001 From: Xiaodai Wang Date: Wed, 10 Jul 2024 17:54:29 +0800 Subject: [PATCH 0474/1055] [virsh_pool_autostart] avoid running vol-list too quickly after pool start From the log, we can see the pool-start and vol-list command execute in 1us. It may fail for ISCSI storage. We could use utils_misc.wait, but the command will be too complicated. Just use sleep to wait a second. 2024-07-01 09:09:52,851 process L0739 INFO | Command '/usr/bin/virsh pool-start 2024-07-01 09:09:52,852 virsh L0873 DEBUG| status: 0 2024-07-01 09:09:52,852 virsh L0874 DEBUG| stdout: Pool virsh_pool_test started 2024-07-01 09:09:52,852 virsh L0875 DEBUG| stderr: 2024-07-01 09:09:52,852 virsh L0822 DEBUG| Running virsh command: vol-list virsh_pool_test 2024-07-01 09:09:52,852 process L0658 INFO | Running '/usr/bin/virsh vol-list virsh_pool_test ' 2024-07-01 09:09:52,874 process L0470 DEBUG| [stdout] Name Path 2024-07-01 09:09:52,874 process L0470 DEBUG| [stdout] -------------- 2024-07-01 09:09:52,874 process L0470 DEBUG| [stdout] 2024-07-01 09:09:52,874 process L0739 INFO | Command '/usr/bin/virsh vol-list virsh_pool_test 2024-07-01 09:09:52,875 virsh L0873 DEBUG| status: 0 2024-07-01 09:09:52,875 virsh L0874 DEBUG| stdout: Name Path-------------- Signed-off-by: Xiaodai Wang --- libvirt/tests/src/storage/virsh_pool_autostart.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/storage/virsh_pool_autostart.py b/libvirt/tests/src/storage/virsh_pool_autostart.py index c484616bc9a..6f193e0b0dd 100755 --- a/libvirt/tests/src/storage/virsh_pool_autostart.py +++ b/libvirt/tests/src/storage/virsh_pool_autostart.py @@ -1,5 +1,6 @@ import os import re +import time import logging as log from avocado.utils import process @@ -159,9 +160,10 @@ def change_source_path(new_path, update_policy="set"): pool = pool_ins.get_pool_uuid(pool_name) if destroy_pool_used_by_guest: virsh.pool_start(pool_name, debug=True, ignore_status=False) + # Avoid running vol_list too quickly + time.sleep(3) res = virsh.vol_list(pool_name, debug=True, ignore_status=False).stdout_text - vol = re.findall(r"(\S+)\ +(\S+)", str(res.strip()))[1] if not vol: test.fail('Expect to get vol in %s pool' % pool_name) From 6bd72a0e0eae9b806640349259d7ef62e41ba8a7 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 9 May 2024 20:58:45 -0400 Subject: [PATCH 0475/1055] Add case of cgroup vhost - VIRT-300725 - [cgroup][vhost] Check the vhost* thread's cpu affinity with emulatorpin setting Signed-off-by: Haijiao Zhao --- ...ck_vhost_cpu_affinity_with_emulatorpin.cfg | 7 ++ ...eck_vhost_cpu_affinity_with_emulatorpin.py | 104 ++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/driver/check_vhost_cpu_affinity_with_emulatorpin.cfg create mode 100644 libvirt/tests/src/virtual_network/driver/check_vhost_cpu_affinity_with_emulatorpin.py diff --git a/libvirt/tests/cfg/virtual_network/driver/check_vhost_cpu_affinity_with_emulatorpin.cfg b/libvirt/tests/cfg/virtual_network/driver/check_vhost_cpu_affinity_with_emulatorpin.cfg new file mode 100644 index 00000000000..5287ac45b03 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/driver/check_vhost_cpu_affinity_with_emulatorpin.cfg @@ -0,0 +1,7 @@ +- virtual_network.check_vhost_cpu_affinity_with_emulatorpin: + type = check_vhost_cpu_affinity_with_emulatorpin + start_vm = no + timeout = 240 + vcpu_set = 0 + vm_attrs = {'vcpu': 1, 'cputune': {'vcpupins': [{'vcpu': '0', 'cpuset': '${vcpu_set}'}], 'emulatorpin': epin_set}} + iface_attrs = {'model': 'virtio'} diff --git a/libvirt/tests/src/virtual_network/driver/check_vhost_cpu_affinity_with_emulatorpin.py b/libvirt/tests/src/virtual_network/driver/check_vhost_cpu_affinity_with_emulatorpin.py new file mode 100644 index 00000000000..ba0fba3bbd0 --- /dev/null +++ b/libvirt/tests/src/virtual_network/driver/check_vhost_cpu_affinity_with_emulatorpin.py @@ -0,0 +1,104 @@ +import logging +import random +import re + +from avocado.core import exceptions +from avocado.utils import process +from virttest import cpu +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_misc +from virttest.utils_libvirt import libvirt_vmxml + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def get_online_cpus(): + """ + Get online cpus + + :return: a list of online cpus + """ + cpu_range = cpu.get_cpu_info().get('On-line CPU(s) list') + online_cpus = [ + (lambda x: range(x[0], x[-1] + 1))(list(map(int, r.split('-')))) + for r in cpu_range.split(',') + ] + online_cpus = [cpu for r in online_cpus for cpu in r] + LOG.debug(f'Online cpus: {online_cpus}') + + return online_cpus + + +def check_cpu_affinity(vm_name, pid, epin_set): + """ + Check cpu affinity with virsh emulatorpin and taskset + + :param vm_name: vm name + :param pid: pid of vhost + :param epin_set: pre-set emulatorpin + """ + epin = libvirt_misc.convert_to_dict( + virsh.emulatorpin(vm_name, **VIRSH_ARGS).stdout_text, + r'\s+(\S+):\s+(\S+)') + + if epin['*'] != epin_set: + raise exceptions.TestFail(f'Incorrect cpu affinity (emulatorpin): ' + f'{epin["*"]}, Should be {epin_set}.') + + taskset_output = process.run( + f'taskset -cap {pid}', shell=True).stdout_text + search_pattern = "pid \d+'s current affinity list:\s(\S+)" + search_result = re.search(search_pattern, taskset_output) + if not search_result or search_result.group(1) != epin_set: + raise exceptions.TestFail(f'Expect current affinity to be {epin_set}, ' + f'not {search_result.group(1)}.') + + +def run(test, params, env): + """ + Check the vhost* thread's cpu affinity with emulatorpin setting + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + vcpu_set = params.get('vcpu_set') + iface_attrs = eval(params.get('iface_attrs', '{}')) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + online_cpus = get_online_cpus() + epin_set = str(random.choice(online_cpus)) + online_cpus.remove(int(epin_set)) + epin_reset = str(random.choice(online_cpus)) + vm_attrs = eval(params.get('vm_attrs', '{}')) + + try: + vmxml.setup_attrs(**vm_attrs) + libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs) + LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + vm.start() + + cpu_affi = libvirt_misc.convert_to_dict( + virsh.vcpupin(vm_name, **VIRSH_ARGS).stdout_text) + + if cpu_affi['0'] != vcpu_set: + test.fail(f'Incorrect cpu affinity (vcpu): {cpu_affi["0"]},' + f'Should be {vcpu_set}.') + + pid = process.run( + "ps -eL|awk '/vhost/{print $2}'", shell=True).stdout_text.strip() + + check_cpu_affinity(vm_name, pid, epin_set) + + # Update the emulator pin to other cpu, + # and check the vhost thread's cpu affinity + virsh.emulatorpin(vm_name, epin_reset, **VIRSH_ARGS) + + check_cpu_affinity(vm_name, pid, epin_reset) + + finally: + bkxml.sync() From 2f6f481510d50a069a5eb3b78208eb18cefaa925 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Wed, 10 Jul 2024 23:25:25 -0400 Subject: [PATCH 0476/1055] Virtual_disk: add new cases for disk driver discard_no_unref attribute Automate cases of discard_no_unref attribute: VIRT-301646 VIRT-301647 VIRT-301651 Signed-off-by: Meina Li --- .../virtual_disks_discard_no_unref.cfg | 42 +++++ .../virtual_disks_discard_no_unref.py | 167 ++++++++++++++++++ 2 files changed, 209 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_disks/virtual_disks_discard_no_unref.cfg create mode 100644 libvirt/tests/src/virtual_disks/virtual_disks_discard_no_unref.py diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_discard_no_unref.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_discard_no_unref.cfg new file mode 100644 index 00000000000..060210a8a68 --- /dev/null +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_discard_no_unref.cfg @@ -0,0 +1,42 @@ +- virtual_disks.discard_no_unref: + type = virtual_disks_discard_no_unref + start_vm = "no" + status_error = "no" + func_supported_since_libvirt_ver = (9, 5, 0) + target_dev = "vdb" + + variants: + - file_disk: + disk_type = "file" + - block_disk: + disk_type = "block" + variants: + - with_discard_unmap: + discard = "unmap" + - with_discard_ignore: + discard = "ignore" + variants: + - enable: + discard_no_unref = "on" + qemu_output = "true" + - disable: + discard_no_unref = "off" + qemu_output = "false" + variants test_scenario: + - start_vm: + check_qemu_pattern = '"discard":"${discard}","driver":"qcow2","discard-no-unref":${qemu_output}' + expect_xml_line = 'discard_no_unref="${discard_no_unref}"' + - define_invalid: + only enable..with_discard_unmap.file_disk + status_error = "yes" + variants: + - raw_format: + invalid_format = "yes" + expect_error = "unsupported configuration: 'discard_no_unref' only works with qcow2 disk format" + - readonly_mode: + expect_error = "unsupported configuration: 'discard_no_unref' is not compatible with read-only disk" + - hotplug_disk: + only enable..with_discard_unmap.file_disk + hotplug = "yes" + check_libvirtd_log = '"driver":"qcow2","discard-no-unref":true' + disk_dict = {'type_name': '${disk_type}', 'driver': {'name': 'qemu', 'type': 'qcow2', 'discard': '${discard}', 'discard_no_unref': '${discard_no_unref}'}, 'target': {'dev': '${target_dev}'}} diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_discard_no_unref.py b/libvirt/tests/src/virtual_disks/virtual_disks_discard_no_unref.py new file mode 100644 index 00000000000..334c23e64f9 --- /dev/null +++ b/libvirt/tests/src/virtual_disks/virtual_disks_discard_no_unref.py @@ -0,0 +1,167 @@ +# Copyright Red Hat +# SPDX-License-Identifier: GPL-2.0 +# Author: Meina Li + +import os + +from avocado.utils import process + +from virttest import libvirt_version +from virttest import virsh +from virttest.libvirt_xml import vm_xml, xcepts +from virttest.utils_libvirt import libvirt_disk +from virttest.utils_test import libvirt + +from provider.virtual_disk import disk_base + + +def check_result(vm, params, test): + """ + Check the dumpxml/qemu command line and read/write data in guest + 1) Check the guest dumpxml with expected driver attribute. + 2) Check the qemu command line after starting the guest. + 3) Read/write the data in guest. + + :param vm: vm instance + :param params: dict, test parameters + :param test: test object + """ + check_qemu_pattern = params.get("check_qemu_pattern", "") + expect_xml_line = params.get("expect_xml_line", "") + check_libvirtd_log = params.get("check_libvirtd_log", "") + target_dev = params.get("target_dev") + hotplug = "yes" == params.get("hotplug", "no") + test.log.info("Check the dumpxml.") + libvirt.check_dumpxml(vm, expect_xml_line) + if check_qemu_pattern: + test.log.info("Check the qemu command line.") + libvirt.check_qemu_cmd_line(check_qemu_pattern) + if hotplug: + test.log.info("Check the libvirtd log.") + libvirtd_log_file = os.path.join(test.debugdir, "libvirtd.log") + libvirt.check_logfile(check_libvirtd_log, libvirtd_log_file) + test.log.info("Check read/write in guest.") + libvirt_disk.check_virtual_disk_io(vm, target_dev) + + +def run_test_start_vm(vm, params, test): + """ + Scenario: start guest with discard_no_unref attribute + + :param vm: vm instance + :param params: dict, test parameters + :param test: test object + """ + vm_name = params.get("main_vm") + disk_dict = eval(params.get("disk_dict", "{}")) + disk_type = params.get("disk_type") + disk_obj = disk_base.DiskBase(test, vm, params) + + test.log.info("STEP1: prepare the guest xml.") + new_image_path = disk_obj.add_vm_disk(disk_type, disk_dict) + if disk_type == "block": + cmd = "qemu-img create -f qcow2 %s 50M" % new_image_path + process.run(cmd, shell=True, ignore_status=False) + test.log.info("STEP2: start the guest.") + virsh.start(vm_name, debug=True, ignore_status=False) + test.log.debug("The current guest xml is: %s" % virsh.dumpxml(vm_name).stdout_text) + test.log.info("STEP3: check the dumpxml and the qemu command line and read/write in guest.") + check_result(vm, params, test) + + +def run_test_define_invalid(vm, params, test): + """ + Scenario: start guest with invalid discard_no_unref configuration + + :param vm: vm instance + :param params: dict, test parameters + :param test: test object + """ + status_error = "yes" == params.get("status_error", "no") + invalid_format = "yes" == params.get("invalid_format", "no") + expect_error = params.get("expect_error") + disk_dict = eval(params.get("disk_dict", "{}")) + disk_type = params.get("disk_type") + disk_obj = disk_base.DiskBase(test, vm, params) + if status_error: + if invalid_format: + disk_dict['driver']['type'] = 'raw' + else: + disk_dict.update({'readonly': True}) + try: + disk_obj.add_vm_disk(disk_type, disk_dict) + except xcepts.LibvirtXMLError as xml_error: + if not status_error: + test.fail("Failed to define VM:\n%s" % str(xml_error)) + else: + test.log.debug("Get expecct error message:\n%s" % expect_error) + + +def run_test_hotplug_disk(vm, params, test): + """ + Scenario: hotplug/unplug disk with discard_no_unref enabled + + :param vm: vm instance + :param params: dict, test parameters + :param test: test object + """ + vm_name = params.get("main_vm") + disk_type = params.get("disk_type") + target_dev = params.get("target_dev") + disk_dict = eval(params.get("disk_dict", "{}")) + disk_obj = disk_base.DiskBase(test, vm, params) + + test.log.debug("STEP1&2: prepare hotplugged disk image and xml.") + disk_xml, _ = disk_obj.prepare_disk_obj(disk_type, disk_dict) + if not vm.is_alive(): + vm.start() + test.log.debug("STEP3: attach disk xml.") + virsh.attach_device(vm_name, disk_xml.xml, debug=True, ignore_status=False) + test.log.debug("STEP4: check the result.") + check_result(vm, params, test) + test.log.debug("STEP5: detach disk.") + virsh.detach_device(vm_name, disk_xml.xml, debug=True, ignore_status=False) + domblklist_result = virsh.domblklist(vm_name, debug=True).stdout_text.strip() + if target_dev in domblklist_result: + test.fail("The target disk % can't be detached in guest." % target_dev) + + +def teardown_test(vm, vmxml, params, test): + """ + :param vm: vm instance + :params vmxml: the guest xml + :param params: dict, test parameters + :param test: test object + """ + disk_type = params.get("disk_type") + if vm.is_alive(): + vm.destroy() + vmxml.sync() + disk_obj = disk_base.DiskBase(test, vm, params) + disk_obj.cleanup_disk_preparation(disk_type) + + +def run(test, params, env): + """ + Test driver attribute: discard_no_unref + + Scenarios: + 1) Start guest with disk discard_no_unref attribute. + 2) Define guest with invalid disk discard_no_unref attribute. + 3) Hotplug disk with discard_no_unref attribute. + """ + vm_name = params.get("main_vm") + libvirt_version.is_libvirt_feature_supported(params) + + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + test_scenario = params.get("test_scenario") + case_name = "run_test_%s" % test_scenario + run_test_case = eval(case_name) + try: + if vm.is_alive(): + vm.destroy() + run_test_case(vm, params, test) + finally: + teardown_test(vm, bkxml, params, test) From 178915037b6afaad52489d5ce0b7b3e06bd56ff4 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Thu, 11 Jul 2024 03:00:09 -0400 Subject: [PATCH 0477/1055] Update the file path to "/" In this case, we need to create a temporary file to test the file transfer function. The original /tmp directroy is not enough some times since we need to creat 1G file. So update the file path to be under "/". Signed-off-by: Yalan Zhang --- libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg index 104c8fcd5da..81ff28300de 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg @@ -35,7 +35,7 @@ bs = 1M - 1G: bs = 100M - test_file = /tmp/${file_size}_file + test_file = /${file_size}_file rec_file = out_${file_size} cmd_create_file = dd if=/dev/urandom bs=${bs} count=10 > ${test_file} cmd_listen = f'socat -u {prot}-LISTEN:{port},reuseaddr OPEN:${rec_file},create' From 2dc6b20aa21041a6f9babb6fb9bffdbfb2cead58 Mon Sep 17 00:00:00 2001 From: nanli Date: Wed, 10 Jul 2024 22:12:44 +0800 Subject: [PATCH 0478/1055] fix serial pty log case not found vm login prompt login prompt is changing Signed-off-by: nanli --- libvirt/tests/cfg/serial/serial_pty_log.cfg | 5 +---- libvirt/tests/src/serial/serial_pty_log.py | 8 ++++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/libvirt/tests/cfg/serial/serial_pty_log.cfg b/libvirt/tests/cfg/serial/serial_pty_log.cfg index b0002048c8c..36c35f4c1fd 100644 --- a/libvirt/tests/cfg/serial/serial_pty_log.cfg +++ b/libvirt/tests/cfg/serial/serial_pty_log.cfg @@ -2,6 +2,7 @@ type = serial_pty_log start_vm = no remove_devices = "['serial','console']" + boot_prompt = 'localhost login,Login Prompts' variants: - file: serial_dev_type = pty @@ -11,11 +12,9 @@ aarch64: target_type = system-serial target_model = pl011 - boot_prompt = 'localhost login' s390x: target_type = sclp-serial target_model = sclpconsole - boot_prompt = 'localhost login' stdio_handler = 'file' - logd: serial_dev_type = pty @@ -25,9 +24,7 @@ aarch64: target_type = system-serial target_model = pl011 - boot_prompt = 'localhost login' s390x: target_type = sclp-serial target_model = sclpconsole - boot_prompt = 'localhost login' stdio_handler = 'logd' diff --git a/libvirt/tests/src/serial/serial_pty_log.py b/libvirt/tests/src/serial/serial_pty_log.py index 834a0b1e928..ce49ebc231c 100644 --- a/libvirt/tests/src/serial/serial_pty_log.py +++ b/libvirt/tests/src/serial/serial_pty_log.py @@ -27,10 +27,10 @@ def check_pty_log_file(file_path, boot_prompt): with open(file_path, errors='ignore') as fp: contents = fp.read() logging.debug("The contents of log file are : %s" % contents) - ret = contents.find(boot_prompt) - if ret == -1: - return False - return True + ret = [] + for prompt in boot_prompt.split(','): + ret.append(contents.find(prompt) != -1) + return any(ret) def run(test, params, env): From 1db0d5a064d6cfbbaad15a4ca6d92635db7d046f Mon Sep 17 00:00:00 2001 From: Yan Fu Date: Thu, 11 Jul 2024 12:04:47 +0800 Subject: [PATCH 0479/1055] Debug for the unix_sock Signed-off-by: Yan Fu --- .../src/daemon/conf_file/libvirtd_conf/unix_sock.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/daemon/conf_file/libvirtd_conf/unix_sock.py b/libvirt/tests/src/daemon/conf_file/libvirtd_conf/unix_sock.py index 1ab0b1ee372..c0d65773acc 100644 --- a/libvirt/tests/src/daemon/conf_file/libvirtd_conf/unix_sock.py +++ b/libvirt/tests/src/daemon/conf_file/libvirtd_conf/unix_sock.py @@ -10,6 +10,7 @@ from virttest import data_dir from virttest import utils_config from virttest import utils_libvirtd +from virttest import utils_split_daemons from virttest import libvirt_version @@ -95,6 +96,7 @@ def check_unix_sock(group, perms, path, readonly=False): result = virsh.net_define(xml_path, uri=uri, ignore_status=True) logging.debug('Result of virsh test run is:\n %s' % result) + process.run("ls -lZ /run/libvirt/", shell=True, ignore_status=True) try: if result.exit_status and not readonly: logging.error('Error encountered when running virsh net-define ' @@ -123,12 +125,16 @@ def check_all_unix_sock(group, ro_perms, rw_perms, root_path): :param root_path: Absolute path of the directory that target file in. :return : True if success or False if any test fails. """ - rw_path = os.path.join(root_path, 'libvirt-sock') + if utils_split_daemons.is_modular_daemon(): + rw_path = os.path.join(root_path, 'virtqemud-sock') + ro_path = os.path.join(root_path, 'virtqemud-sock-ro') + else: + rw_path = os.path.join(root_path, 'libvirt-sock') + ro_path = os.path.join(root_path, 'libvirt-sock-ro') logging.debug("Checking read-write socket file %s" % rw_path) if not check_unix_sock(group, rw_perms, rw_path): return False - ro_path = os.path.join(root_path, 'libvirt-sock-ro') logging.debug("Checking read-only socket file %s" % ro_path) return check_unix_sock(group, ro_perms, ro_path, readonly=True) From d047e1838871261f23be22388462831aedbc6d45 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Thu, 11 Jul 2024 09:11:58 -0400 Subject: [PATCH 0480/1055] Fix the login timeout issue Some passt related cases failed since login timeout issue. It's beacuase the serial login sendkey which paused booting. Sleep 5s in these cases to skip the interruption. Signed-off-by: Yalan Zhang --- libvirt/tests/src/virtual_network/passt/passt_attach_detach.py | 3 +++ .../virtual_network/passt/passt_connectivity_between_2vms.py | 3 +++ libvirt/tests/src/virtual_network/passt/passt_reconnect.py | 3 +++ 3 files changed, 9 insertions(+) diff --git a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py index 62ff3b26125..3535f3c04db 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py +++ b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py @@ -1,6 +1,7 @@ import logging import os import shutil +import time import aexpect from virttest import libvirt_version @@ -122,6 +123,8 @@ def run(test, params, env): if not os.path.exists(log_file): test.fail(f'Logfile of passt "{log_file}" not created') + # wait for the vm boot before first time to try serial login + time.sleep(5) session = vm.wait_for_serial_login(timeout=60) vm_iface = utils_net.get_linux_ifname(session, mac) passt.check_vm_ip(iface_attrs, session, host_iface, vm_iface) diff --git a/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py b/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py index d4ea9a86d38..27008a54f00 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py +++ b/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py @@ -1,5 +1,6 @@ import logging import shutil +import time import aexpect from virttest import libvirt_version @@ -95,6 +96,8 @@ def run(test, params, env): [LOG.debug(virsh.dumpxml(vm_name, uri=virsh_uri).stdout_text) for vm_name in (vm_name, vm_c.name)] + # wait for the vm boot before first time to try serial login + time.sleep(5) server_session = vm.wait_for_serial_login(60) client_session = vm_c.wait_for_serial_login(60) diff --git a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py index fa82db2ea68..98fe1acedb8 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py +++ b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py @@ -1,6 +1,7 @@ import logging import os import shutil +import time import aexpect from avocado.utils import process @@ -107,6 +108,8 @@ def run(test, params, env): if not os.path.exists(log_file): test.fail(f'Logfile of passt "{log_file}" not created') + # wait for the vm boot before first time to try serial login + time.sleep(5) session = vm.wait_for_serial_login(timeout=60) vm_iface = utils_net.get_linux_ifname(session, mac) passt.check_vm_ip(iface_attrs, session, host_iface, vm_iface) From 552567e530a7d649dff885ed1821c21011daa4e0 Mon Sep 17 00:00:00 2001 From: nanli Date: Tue, 21 May 2024 13:45:37 +0800 Subject: [PATCH 0481/1055] add case for dimm hot unplug xxxx-300403:Verify dimm memory device hot-unplug with different configs Signed-off-by: nanli --- .../memory_devices/dimm_memory_hot_unplug.cfg | 55 +++++ .../memory_devices/dimm_memory_hot_unplug.py | 212 ++++++++++++++++++ 2 files changed, 267 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/dimm_memory_hot_unplug.py diff --git a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg new file mode 100644 index 00000000000..6760b130675 --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg @@ -0,0 +1,55 @@ +- memory.devices.dimm.hot_unplug: + type = dimm_memory_hot_unplug + start_vm = yes + mem_model = 'dimm' + allocate_size = "1048576" + allocate_memory = "${allocate_size}KiB" + target_size = "524288" + size_unit = 'KiB' + node = 0 + mem_value = 2097152 + current_mem = 2097152 + numa_mem = 1048576 + max_mem = 4194304 + max_mem_slots = 16 + slot = '0' + audit_cmd = "ausearch --start today -m VIRT_RESOURCE | grep 'mem'" + ausearch_check = 'old-mem=%d new-mem=%d' + expected_log = "ACPI_DEVICE_OST|device_del" + kernel_hp_file = '/sys/devices/system/node/node0/hugepages/hugepages-%skB/nr_hugepages' + max_dict = '"max_mem_rt": ${max_mem}, "max_mem_rt_slots": ${max_mem_slots}, "max_mem_rt_unit": "KiB"' + numa_dict = "'vcpu': 4,'cpu':{'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_mem}'}]}" + vm_attrs = {${numa_dict},${max_dict},'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'} + variants plug_dimm_type: + - target_and_address: + base = "0x100000000" + addr_dict = "'address':{'attrs': {'type':'dimm','slot':'${slot}','base':'${base}'}}" + dimm_dict = {'mem_model':'${mem_model}',${addr_dict},'target': {'size':${target_size}, 'size_unit':'${size_unit}', 'node':${node}}} + unplug_dimm_dict = ${dimm_dict} + - source_and_mib: + target_size = "1024" + size_unit = 'MiB' + node = 1 + source_dict = "'source':{'nodemask': '0','pagesize': %d, 'pagesize_unit':'KiB'}" + dimm_dict = {'mem_model':'${mem_model}',${source_dict},'target': {'size':${target_size}, 'size_unit':'${size_unit}', 'node':${node}}} + unplug_dimm_dict = ${dimm_dict} + - unexisted_device: + unplug_node = 1 + dimm_dict = {'mem_model':'${mem_model}','target': {'size':${target_size}, 'size_unit':'${size_unit}', 'node':${node}}} + unplug_dimm_dict = {'mem_model':'${mem_model}','target': {'size':${target_size}, 'size_unit':'${size_unit}', 'node':${unplug_node}}} + base_xpath = [{'element_attrs':[".//memory[@unit='KiB']"],'text':'%d'},{'element_attrs':[".//currentMemory[@unit='KiB']"],'text':'%d'}] + dimm_xpath = [{'element_attrs':[".//target/size[@unit='KiB']"],'text':'%s'},{'element_attrs':[".//address[@slot='%s']"]}] + variants mem_state: + - default_mem: + target_and_address: + unplug_event = "device-removal-failed" + unplug_error = "unplug of device was rejected by the guest" + source_and_mib: + unplug_event = "device-removal-failed" + unplug_error = "unplug of device was rejected by the guest" + unexisted_device: + unplug_error = "model 'dimm' memory device not present in the domain configuration" + - online_movable_mem: + no unexisted_device + unplug_event = "device-removed" + kernel_extra_params_add = "memhp_default_state=online_movable" diff --git a/libvirt/tests/src/memory/memory_devices/dimm_memory_hot_unplug.py b/libvirt/tests/src/memory/memory_devices/dimm_memory_hot_unplug.py new file mode 100644 index 00000000000..73af8744469 --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/dimm_memory_hot_unplug.py @@ -0,0 +1,212 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import os + +from avocado.utils import process +from avocado.utils import memory + +from virttest import utils_misc +from virttest.utils_test import libvirt +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml + +from provider.memory import memory_base +from virttest.staging import utils_memory + +virsh_dargs = {"ignore_status": False, "debug": True} + + +def adjust_size_unit(params): + """ + Adjust the unit of dimm target size. + + :param params: cartesian config parameters. + :return target_size, init define dimm target size. + """ + plug_dimm_type = params.get("plug_dimm_type") + if plug_dimm_type in ["source_and_mib"]: + target_size = memory_base.convert_data_size( + params.get("target_size") + params.get('size_unit'), 'KiB') + else: + target_size = params.get("target_size") + + return int(target_size) + + +def check_guest_virsh_dominfo(vm, test, params, unplugged=False): + """ + Check current memory value and memory value in virsh dominfo result. + + :param vm: vm object. + :param test: test object. + :param params: dictionary with the test parameters. + :param unplugged: boolean, the flag of unplugging. + """ + mem_value = int(params.get("mem_value")) + current_mem = int(params.get("current_mem")) + + target_size = adjust_size_unit(params) + if unplugged: + expected_mem = str(mem_value) + expected_curr = str(current_mem - target_size) + else: + expected_mem = str(mem_value + target_size) + expected_curr = str(current_mem) + + memory_base.check_dominfo(vm, test, expected_mem, expected_curr) + + +def check_after_detach(vm, test, params): + """ + Check the below points after unplugging. + + 1. Check the audit log by ausearch. + 2. Check the libvirtd log. + 3. Check the memory allocation and memory device config. + 4. Check the memory info by virsh dominfo. + 5. Check the guest memory. + + :param vm: vm object. + :param test: test object. + :param params: dictionary with the test parameters. + :param operation: string, the flag for attaching or detaching. + """ + mem_value = int(params.get("mem_value")) + current_mem = int(params.get("current_mem")) + expected_log = params.get("expected_log") + audit_cmd = params.get("audit_cmd") + base_xpath, dimm_xpath = params.get("base_xpath"), params.get("dimm_xpath") + + target_size = adjust_size_unit(params) + libvirtd_log_file = os.path.join(test.debugdir, "libvirtd.log") + ausearch_check = params.get("ausearch_check") % (mem_value+target_size, mem_value) + + # Check the audit log by ausearch. + ausearch_result = process.run(audit_cmd, shell=True) + libvirt.check_result(ausearch_result, expected_match=ausearch_check) + test.log.debug("Check audit log %s successfully." % ausearch_check) + + # Check the libvirtd log. + result = utils_misc.wait_for( + lambda: libvirt.check_logfile(expected_log, libvirtd_log_file), timeout=20) + if not result: + test.fail("Can't get expected log %s in %s" % (expected_log, libvirtd_log_file)) + + # Check the memory allocation and memory device config. + vmxml = vm_xml.VMXML.new_from_dumpxml(vm.name) + libvirt_vmxml.check_guest_xml_by_xpaths( + vmxml, eval(base_xpath % (mem_value, current_mem-target_size))) + if vmxml.devices.by_device_tag("memory"): + test.fail("Dimm memory still exist after unplugging") + + # Check the memory info by virsh dominfo. + check_guest_virsh_dominfo(vm, test, params, unplugged=True) + + # Check the guest memory. + session = vm.wait_for_login() + new_memtotal = utils_memory.memtotal(session) + session.close() + expected_memtotal = params.get('old_memtotal') - target_size + if new_memtotal != expected_memtotal: + test.fail("Memtotal is %s, should be %s " % (new_memtotal, expected_memtotal)) + test.log.debug("Check Memtotal successfully.") + + +def run(test, params, env): + """ + Verify dimm memory device hot unplug with different configs. + """ + def setup_test(): + """ + Allocate memory on the host. + """ + process.run("echo %d > %s" % ( + allocate_size / default_hugepage_size, + kernel_hp_file % default_hugepage_size), shell=True) + + def run_test(): + """ + 1. Define vm with dimm memory device. + 2. Hot unplug dimm memory. + 3. Check audit log, libvirtd log, memory allocation and memory device + config. + """ + test.log.info("TEST_STEP1: Define vm with dimm memory") + memory_base.define_guest_with_memory_device(params, dimm_dict, vm_attrs) + + test.log.info("TEST_STEP2: Start guest") + vm.start() + session = vm.wait_for_login() + + test.log.info("TEST_STEP3: Get the guest memory") + params.update({'old_memtotal': utils_memory.memtotal(session)}) + session.close() + + test.log.info("TEST_STEP4: Check the memory allocation and dimm config") + target_size = adjust_size_unit(params) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + libvirt_vmxml.check_guest_xml_by_xpaths( + vmxml, eval(base_xpath % (mem_value + target_size, current_mem))) + libvirt_vmxml.check_guest_xml_by_xpaths( + vmxml.devices.by_device_tag("memory")[0], eval(dimm_xpath % (target_size, slot))) + + test.log.info("TEST_STEP5: Check the memory info by virsh dominfo") + check_guest_virsh_dominfo(vm, test, params) + + test.log.info("TEST_STEP6: Hot unplug one dimm memory device") + memory_base.plug_memory_and_check_result( + test, params, mem_dict=unplug_dict, operation='detach', + expected_error=unplug_error, expected_event=unplug_event, + event_timeout=20) + + if mem_state in ["online_movable_mem"]: + test.log.info("TEST_STEP7: Check audit and libvirt log, " + "memory allocation and memory device config") + check_after_detach(vm, test, params) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bkxml.sync() + process.run("echo 0 > %s" % (kernel_hp_file % default_hugepage_size), shell=True) + + vm_name = params.get("main_vm") + original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = original_xml.copy() + vm = env.get_vm(vm_name) + default_hugepage_size = memory.get_huge_page_size() + + slot = params.get("slot") + plug_dimm_type = params.get("plug_dimm_type") + if plug_dimm_type == "source_and_mib": + dimm_dict = eval(params.get("dimm_dict") % default_hugepage_size) + unplug_dict = dimm_dict + else: + dimm_dict = eval(params.get("dimm_dict")) + unplug_dict = eval(params.get("unplug_dimm_dict", "{}")) + + unplug_error = params.get('unplug_error') + unplug_event = params.get('unplug_event') + kernel_hp_file = params.get("kernel_hp_file") + vm_attrs = eval(params.get("vm_attrs", "{}")) + allocate_size = int(params.get("allocate_size")) + mem_value = int(params.get("mem_value")) + current_mem = int(params.get("current_mem")) + base_xpath, dimm_xpath = params.get("base_xpath"), params.get("dimm_xpath") + mem_state = params.get("mem_state") + + try: + setup_test() + run_test() + + finally: + teardown_test() From 340af006a5d59773dd07eb4182cafb8a5b55826f Mon Sep 17 00:00:00 2001 From: nanli Date: Sun, 2 Jun 2024 20:56:17 +0800 Subject: [PATCH 0482/1055] add case for virtio memory hot unplug xxxx-300401:Virtio-mem memory device hot-unplug Signed-off-by: nanli --- .../memory_devices/virtio_mem_hot_unplug.cfg | 86 +++++ .../memory_devices/virtio_mem_hot_unplug.py | 342 ++++++++++++++++++ provider/memory/memory_base.py | 14 +- 3 files changed, 438 insertions(+), 4 deletions(-) create mode 100644 libvirt/tests/cfg/memory/memory_devices/virtio_mem_hot_unplug.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/virtio_mem_hot_unplug.py diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hot_unplug.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hot_unplug.cfg new file mode 100644 index 00000000000..cad69fddb20 --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hot_unplug.cfg @@ -0,0 +1,86 @@ +- memory.devices.virtio_mem.hot_unplug: + no s390-virtio + type = virtio_mem_hot_unplug + start_vm = yes + mem_model = "virtio-mem" + allocate_size = "1048576" + allocate_memory = "${allocate_size}KiB" + target_size = "1048576" + request_size = "1048576" + unplug_target_size = '1048576' + unplug_request_size = '1048576' + size_unit = 'KiB' + block_unit = 'KiB' + request_unit = 'KiB' + unplug_size_unit = 'KiB' + unplug_block_unit = 'KiB' + unplug_request_unit = 'KiB' + node = 0 + unplug_node = 0 + slot = 0 + mem_value = 2097152 + current_mem = 2097152 + numa_mem = 1048576 + max_mem = 4194304 + max_mem_slots = 16 + base = "0x100000000" + addr_dict = "'address':{'attrs': {'base': '${base}'}}" + kernel_extra_params_add = "memhp_default_state=online_movable" + unplug_event = "device-removed" + audit_cmd = "ausearch --start today -m VIRT_RESOURCE | grep 'mem'" + ausearch_check = 'old-mem=%d new-mem=%d' + expected_log = "device_del" + kernel_hp_file = '/sys/devices/system/node/node0/hugepages/hugepages-%skB/nr_hugepages' + max_dict = '"max_mem_rt": ${max_mem}, "max_mem_rt_slots": ${max_mem_slots}, "max_mem_rt_unit": "KiB"' + numa_dict = "'vcpu': 4,'cpu':{'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_mem}'}]}" + vm_attrs = {${numa_dict},${max_dict},'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'} + required_kernel = [5.14.0,) + guest_required_kernel = [5.8.0,) + func_supported_since_libvirt_ver = (10, 0, 0) + func_supported_since_qemu_kvm_ver = (8, 2, 0) + machine_version = "9.4.0" + variants case: + - target_and_address: + unplug_request_size = '0' + updated_request_option = "--requested-size 0" + - source_mib_and_hugepages: + target_size = "1024" + request_size = "512" + size_unit = 'MiB' + request_unit = "MiB" + node = 1 + unplug_target_size = "1024" + unplug_request_size = "0" + unplug_size_unit = "MiB" + unplug_request_unit = "MiB" + unplug_node = 1 + source_dict = {'nodemask': '0','pagesize': %d, 'pagesize_unit':'KiB'} + updated_request_option = "--requested-size 0" + - nonexistent_mem: + node = 1 + unplug_node = 1 + target_size = "524288" + request_size = "524288" + unplug_target_size = "1048576" + unplug_request_size = "524288" + - none_zero_current: + - none_zero_request: + source_dict = {'nodemask': '0','pagesize': %d, 'pagesize_unit':'KiB'} + virtio_dict = {'mem_model':'${mem_model}','alias': {'name': '%s'},'target': {${addr_dict},'size':${target_size}, 'size_unit':'${size_unit}', 'node':${node},'requested_size': ${request_size},'requested_unit':'${request_unit}', 'block_size': %s, 'block_unit':'${block_unit}'}} + unplug_dict = {'mem_model':'${mem_model}','alias': {'name': '%s'},'target': {${addr_dict},'size':${unplug_target_size},'requested_size': ${unplug_request_size}, 'block_size': %s, 'size_unit':'${unplug_size_unit}','requested_unit':'${unplug_request_unit}','block_unit':'${unplug_block_unit}','node':${unplug_node}}} + variants plug_way: + - detach: + detach_method = "detach" + nonexistent_mem: + unplug_error = "model 'virtio-mem' memory device not present in the domain configuration" + none_zero_current: + unplug_error = "virtio-mem device cannot get unplugged while 'size' != '0'" + none_zero_request: + unplug_error = "virtio-mem device cannot get unplugged while 'requested-size' != '0'" + - detach_alias: + no nonexistent_mem + detach_method = "detach_alias" + none_zero_current: + unplug_error = "virtio-mem device cannot get unplugged while 'size' != '0'" + none_zero_request: + unplug_error = "virtio-mem device cannot get unplugged while 'requested-size' != '0'" diff --git a/libvirt/tests/src/memory/memory_devices/virtio_mem_hot_unplug.py b/libvirt/tests/src/memory/memory_devices/virtio_mem_hot_unplug.py new file mode 100644 index 00000000000..c20cec221fc --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/virtio_mem_hot_unplug.py @@ -0,0 +1,342 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import os +import uuid + +from avocado.utils import memory + +from virttest import virsh +from virttest import utils_misc +from virttest import utils_sys +from virttest import test_setup +from virttest.libvirt_xml import vm_xml +from virttest.staging import utils_memory +from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_vmxml + +from provider.memory import memory_base + +virsh_dargs = {"ignore_status": False, "debug": True} +default_hugepage_size = memory.get_huge_page_size() + + +def adjust_virtio_dict(params): + """ + Adjust virtio memory dict and unplugging dict. + + :param params: dictionary with the test parameters. + :return virtio_dict, unplug_dict , the virtio memory dict when define guest + and unplug. + """ + alias_name = "ua-" + str(uuid.uuid1()) + params.update({"alias": alias_name}) + + source_dict = params.get("source_dict", "") + virtio_dict, unplug_dict = params.get("virtio_dict"), params.get("unplug_dict") + virtio_dict = eval(virtio_dict % (alias_name, default_hugepage_size)) + unplug_dict = eval(unplug_dict % (alias_name, default_hugepage_size)) + + if source_dict: + virtio_dict['source'] = eval(source_dict % default_hugepage_size) + unplug_dict['source'] = eval(source_dict % default_hugepage_size) + + return virtio_dict, unplug_dict + + +def adjust_virtio_size(params, test): + """ + Adjust all virtio related size to KiB. + + :param params: dict wrapped with params. + :param test: test object. + :return target_size, request_size, unplug_target_size, unplug_request_size. + virtio target size, virtio requested size, unplugged virtio target size, + unplugged virtio requested size. + """ + unplug_target_size = int(params.get('unplug_target_size', 0)) + unplug_request_size = int(params.get('unplug_request_size', 0)) + target_size, request_size = int(params.get('target_size')), int( + params.get('request_size')) + unplug_size_unit = params.get('unplug_size_unit') + unplug_request_unit = params.get('unplug_request_unit') + size_unit, request_unit = params.get('size_unit'), params.get( + 'request_unit') + + def _convert_size(curr_size, curr_unit, item): + if curr_unit != "KiB": + new_size = memory_base.convert_data_size(str(curr_size) + curr_unit) + test.log.debug("Convert %s %s to be %s", item, curr_size, new_size) + return int(new_size) + else: + return int(curr_size) + target_size = _convert_size(target_size, size_unit, "target_size") + request_size = _convert_size(request_size, request_unit, "request_size") + unplug_target_size = _convert_size(unplug_target_size, unplug_size_unit, "unplug_target_size") + unplug_request_size = _convert_size(unplug_request_size, unplug_request_unit, "unplug_request_size") + return target_size, request_size, unplug_target_size, unplug_request_size + + +def compare_two_values(test, expected, actual, item_name=''): + """ + Compare two value should be equal + + :param test: test object + :param expected, expected value + :param actual, actual value + :param item_name,checking item name, such as memory value, current memory + """ + if actual != expected: + test.fail( + "Expect %s is %s , but got %s" % (item_name, expected, actual)) + test.log.debug("Checked the %s successfully", item_name) + + +def check_source_and_addr_xml(test, params, virtio_mem_xml): + """ + Check virtio memory source and address xml if existed. + + :param test: test object + :param params: dictionary with the test parameters + :param virtio_mem_xml, virtio memory xml + """ + expected_base = params.get("base") + addr_dict = params.get("addr_dict", "") + source_dict = params.get("source_dict", "") + expected_source_pgsize = default_hugepage_size + + if source_dict: + if virtio_mem_xml.source.pagesize != expected_source_pgsize: + test.fail("Got virtio memory source pagesize %s, should be %s" % ( + virtio_mem_xml.source.pagesize, expected_source_pgsize)) + test.log.debug("Check virtio memory source xml successfully") + if addr_dict: + actual_base = virtio_mem_xml.target.address.attrs.get("base") + if actual_base != expected_base: + test.fail("Got virtio memory address base %s, should be %s" % ( + actual_base, expected_base)) + test.log.debug("Check virtio memory address xml successfully") + + +def check_guest_xml(test, params, hot_unplugged=False): + """ + Check guest xml. + + :param test: test object. + :param params: dictionary with the test parameters. + :param hot_unplugged: boolean, the flag of hot unplugging or not. + + """ + case = params.get("case") + vm_name = params.get("main_vm") + mem_value = int(params.get("mem_value")) + current_mem = int(params.get("current_mem")) + + target_size, request_size, unplug_target_size, unplug_request_size = \ + adjust_virtio_size(params, test) + expected_virito_curr = 0 if case == "none_zero_request" else request_size + + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + acutal_mem = vmxml.memory + acutal_curr = vmxml.current_mem + virtio_mem_xml = vmxml.devices.by_device_tag("memory") + + if not hot_unplugged: + acutal_virtio_target = virtio_mem_xml[0].target.size + acutal_virtio_block = virtio_mem_xml[0].target.block_size + acutal_virtio_requested = virtio_mem_xml[0].target.requested_size + acutal_virtio_current = virtio_mem_xml[0].target.current_size + params.update({"expected_mem0": mem_value + target_size}) + params.update({"expected_curr0": current_mem + acutal_virtio_current}) + params.update({"curr1": acutal_virtio_current}) + + check_source_and_addr_xml(test, params, virtio_mem_xml[0]) + compare_two_values( + test, params.get("expected_mem0"), acutal_mem, 'memory') + compare_two_values( + test, params.get("expected_curr0"), acutal_curr, 'current memory') + + compare_two_values( + test, target_size, acutal_virtio_target, 'virtio memory target size') + compare_two_values( + test, default_hugepage_size, acutal_virtio_block, 'virtio memory block size') + compare_two_values( + test, request_size, acutal_virtio_requested, 'virtio memory requested size') + compare_two_values( + test, expected_virito_curr, acutal_virtio_current, 'virtio memory current size') + + else: + if virtio_mem_xml: + test.fail("Guest virtio memory xml is not empty, but got %s", virtio_mem_xml) + test.log.debug("Check unplugged virtio memory unexisted successfully") + + params.update( + {"expected_mem1": params.get("expected_mem0") - unplug_target_size}) + params.update( + {"expected_curr1": params.get("expected_curr0") - params.get("curr1")}) + + compare_two_values(test, params.get("expected_mem1"), acutal_mem, 'memory') + compare_two_values(test, params.get("expected_curr1"), acutal_curr, 'current memory') + + +def check_guest_virsh_dominfo(vm, test, params, hot_unplugged=False): + """ + Check memory value and current memory value in virsh dominfo result. + + :param vm: vm object. + :param test: test object. + :param params: dictionary with the test parameters. + :param hot_unplugged: boolean, the flag of hot unplugging or not. + """ + if hot_unplugged: + expected_mem = params.get("expected_mem1") + expected_curr = params.get("expected_curr1") + else: + expected_mem = params.get("expected_mem0") + expected_curr = params.get("expected_curr0") + memory_base.check_dominfo(vm, test, str(expected_mem), str(expected_curr)) + + +def check_after_detach(vm, test, params): + """ + Check the below points after unplugging. + + 1. Check the audit log by ausearch. + 2. Check the libvirtd log. + 3. Check the memory allocation and memory device config. + 4. Check the memory info by virsh dominfo. + 5. Check the guest memory. + :param vm: vm object. + :param test: test object. + :param params: dictionary with the test parameters. + :param operation: string, the flag for attaching or detaching. + """ + expected_log = params.get("expected_log") + audit_cmd = params.get("audit_cmd") + target_size, request_size, unplug_target_size, unplug_request_size = \ + adjust_virtio_size(params, test) + libvirtd_log_file = os.path.join(test.debugdir, "libvirtd.log") + ausearch_check = params.get("ausearch_check") % ( + params.get("expected_mem0"), params.get("expected_mem0") - unplug_target_size) + # Check the audit log by ausearch. + utils_sys.check_audit_log(audit_cmd, ausearch_check) + + # Check the libvirtd log. + result = utils_misc.wait_for( + lambda: libvirt.check_logfile(expected_log, libvirtd_log_file), timeout=20) + if not result: + test.fail("Can't get expected log %s in %s" % ( + expected_log, libvirtd_log_file)) + + # Check the memory allocation and memory device config. + check_guest_xml(test, params, hot_unplugged=True) + + # Check the memory info by virsh dominfo. + check_guest_virsh_dominfo(vm, test, params, hot_unplugged=True) + + # Check the guest memory. + session = vm.wait_for_login() + new_memtotal = utils_memory.memtotal(session) + session.close() + expected_memtotal = params.get('old_memtotal') - params.get("curr1") + if new_memtotal != expected_memtotal: + test.fail("Memtotal is %s, should be %s " % (new_memtotal, expected_memtotal)) + test.log.debug("Check guest mem total successfully.") + + +def run(test, params, env): + """ + Verify virtio-mem memory device hot-unplug with different configs. + """ + def setup_test(): + """ + Allocate memory on the host. + """ + if case == "source_mib_and_hugepages": + if not libvirt_vmxml.check_guest_machine_type(vmxml, machine_version): + test.fail("Guest config machine should be >= rhel{}".format( + machine_version)) + hpc.setup() + + def run_test(): + """ + 1. Define vm with virtio memory device. + 2. Hot unplug another virtio memory. + 3. Check audit log, libvirtd log, memory allocation and memory device + config. + """ + test.log.info("TEST_STEP1: Define vm with virtio memory") + memory_base.define_guest_with_memory_device(params, virtio_dict, vm_attrs) + + test.log.info("TEST_STEP2: Start guest") + vm.start() + session = vm.wait_for_login() + + test.log.info("TEST_STEP3: Get the guest memory") + params.update({'old_memtotal': utils_memory.memtotal(session)}) + session.close() + + test.log.info("TEST_STEP4: Check guest xml") + check_guest_xml(test, params) + + test.log.info("TEST_STEP5: Check the memory info by virsh dominfo") + check_guest_virsh_dominfo(vm, test, params) + + if case in ["target_and_address", "source_mib_and_hugepages"]: + test.log.info("TEST_STEP6: Update the requested memory size to 0") + virsh.update_memory_device( + vm_name, options=updated_request_option, wait_for_event=True, + **virsh_dargs) + + test.log.info("TEST_STEP7: Hot unplug one virtio memory device") + memory_base.plug_memory_and_check_result( + test, params, mem_dict=unplug_dict, alias=params.get("alias"), + operation=detach_method, expected_error=unplug_error, + expected_event=unplug_event, event_timeout=15) + + if case in ["target_and_address", "source_mib_and_hugepages"]: + test.log.info("TEST_STEP8: Check audit and libvirt log, " + "memory allocation and memory device config") + check_after_detach(vm, test, params) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bkxml.sync() + hpc.cleanup() + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + memory_base.check_supported_version(params, test, vm) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + virtio_dict, unplug_dict = adjust_virtio_dict(params) + case = params.get("case") + machine_version = params.get("machine_version") + allocate_size = int(params.get("allocate_size")) + vm_attrs = eval(params.get("vm_attrs", "{}")) + kernel_hp_file = params.get("kernel_hp_file") + updated_request_option = params.get("updated_request_option") + detach_method = params.get("detach_method") + unplug_error = params.get("unplug_error") + unplug_event = params.get('unplug_event') + + params.update({"kernel_hp_file": kernel_hp_file % default_hugepage_size}) + params.update({"target_hugepages": allocate_size / default_hugepage_size}) + hpc = test_setup.HugePageConfig(params) + + try: + setup_test() + run_test() + + finally: + teardown_test() diff --git a/provider/memory/memory_base.py b/provider/memory/memory_base.py index 18171d4259e..b82afa990b4 100644 --- a/provider/memory/memory_base.py +++ b/provider/memory/memory_base.py @@ -178,7 +178,8 @@ def define_guest_with_memory_device(params, mem_attr_list, vm_attrs=None): def plug_memory_and_check_result(test, params, mem_dict, operation='attach', - expected_error='', expected_event='', **kwargs): + expected_error='', expected_event='', + alias='', **kwargs): """ Hot plug or hot unplug memory and check event. @@ -188,17 +189,22 @@ def plug_memory_and_check_result(test, params, mem_dict, operation='attach', :param operation: the operation of plug or unplug. :param expected_error: expected error after plug or unplug. :param expected_event: expected event for plug or unplug. + :param alias: the plugged device alias """ vm_name = params.get('main_vm') - plug_dimm = libvirt_vmxml.create_vm_device_by_type('memory', mem_dict) + plug_mem = libvirt_vmxml.create_vm_device_by_type('memory', mem_dict) wait_event = True if expected_event else False if operation == "attach": - res = virsh.attach_device(vm_name, plug_dimm.xml, wait_for_event=wait_event, + res = virsh.attach_device(vm_name, plug_mem.xml, wait_for_event=wait_event, event_type=expected_event, debug=True, **kwargs) elif operation == "detach": - res = virsh.detach_device(vm_name, plug_dimm.xml, wait_for_event=wait_event, + res = virsh.detach_device(vm_name, plug_mem.xml, wait_for_event=wait_event, event_type=expected_event, debug=True, **kwargs) + elif operation == "detach_alias": + res = virsh.detach_device_alias( + vm_name, alias=alias, wait_for_event=wait_event, + event_type=expected_event, debug=True, **kwargs) if expected_error: libvirt.check_result(res, expected_fails=expected_error) From fd38d2fcaeb7f35c100534a05cbb25a1a7aa92ce Mon Sep 17 00:00:00 2001 From: nanli Date: Wed, 19 Jun 2024 11:54:37 +0800 Subject: [PATCH 0483/1055] add case for virtio memory dynamic slots xxxx-300535:Dynamic memory slots for virtio-mem device Signed-off-by: nanli --- .../virtio_mem_dynamic_slots.cfg | 46 +++++++ .../virtio_mem_dynamic_slots.py | 125 ++++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_devices/virtio_mem_dynamic_slots.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/virtio_mem_dynamic_slots.py diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_dynamic_slots.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_dynamic_slots.cfg new file mode 100644 index 00000000000..a92a2c93067 --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_dynamic_slots.cfg @@ -0,0 +1,46 @@ +- memory.devices.virtio_mem.dynamic_slots: + type = virtio_mem_dynamic_slots + no s390-virtio + start_vm = "no" + mem_model = "virtio-mem" + allocate_size = "3145728" + allocate_memory = "${allocate_size}KiB" + mem_value = 2097152 + current_mem = 2097152 + max_mem = 4194304 + numa_mem = 1048576 + base_attrs = "'vcpu': 4, 'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'" + numa_attrs = "'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'},{'id':'1','cpus': '2-3','memory':'${numa_mem}','unit':'KiB'}]}" + max_attrs = "'max_mem_rt': ${max_mem}, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'" + vm_attrs = {${base_attrs}, ${numa_attrs}, ${max_attrs}} + required_kernel = [5.14.0,) + guest_required_kernel = [5.8.0,) + func_supported_since_libvirt_ver = (10, 0, 0) + func_supported_since_qemu_kvm_ver = (8, 2, 0) + machine_version = "9.4.0" + monitor_cmd = " info mtree" + monitor_option = " --hmp" + variants: + - basic_virtio: + target_size = 524288 + request_size = 524288 + virtio_mem_dict = {'mem_model':'${mem_model}','target': {'size':${target_size}, 'requested_size': ${request_size},'block_size': %s, 'node':0}} + variants dynamic_memory_slots: + - undefined_dynamic_memory_slots: + slots_pattern = ["alias memslot-0 @memvirtiomem0", "alias memslot-0 @memvirtiomem1"] + - enable_dynamic_memory_slots: + dynamic_slot_attr = {"dynamicMemslots":"yes"} + slots_pattern = ["alias memslot-0 @memvirtiomem0", "alias memslot-0 @memvirtiomem1"] + - disable_dynamic_memory_slots: + dynamic_slot_attr = {"dynamicMemslots":"no"} + slots_pattern = ["memvirtiomem0", "memvirtiomem1"] + variants memory_backing: + - default_mb: + - file_mb: + source_type = 'file' + source_attr = "'source_type':'${source_type}'" + - hugepages_mb: + hugepages_attr = "'hugepages': {}" + - memfd_mb: + source_type = 'memfd' + source_attr = "'source_type':'${source_type}'" diff --git a/libvirt/tests/src/memory/memory_devices/virtio_mem_dynamic_slots.py b/libvirt/tests/src/memory/memory_devices/virtio_mem_dynamic_slots.py new file mode 100644 index 00000000000..32bbb9c8a0c --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/virtio_mem_dynamic_slots.py @@ -0,0 +1,125 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import re + +from avocado.utils import memory + +from virttest import virsh +from virttest import test_setup +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml + +from provider.memory import memory_base + + +def update_vm_attrs(test, params): + """ + Update vm attrs. + + :param test: Virt test object. + :param params: Dict with test params. + :return vm_attrs: expected vm attrs dict. + """ + source_attr = params.get('source_attr') + hugepages_attr = params.get('hugepages_attr') + vm_attrs = eval(params.get("vm_attrs")) + + mb_value = "" + for item in [source_attr, hugepages_attr]: + if item is not None: + mb_value = mb_value + item + "," + mb = eval("{'mb':{%s}}" % mb_value[:-1]) + vm_attrs.update(mb) + test.log.debug("Get current vm attrs is :%s", vm_attrs) + + return vm_attrs + + +def run(test, params, env): + """ + Verify dynamic memory slots attribute works with virtio-mem memory device + """ + def setup_test(): + """ + Allocate huge page memory + """ + if memory_backing == "hugepages_mb": + test.log.info("TEST_SETUP: Allocate huge page memory") + params["target_hugepages"] = allocate_size/default_hugepage_size + hp_cfg = test_setup.HugePageConfig(params) + params["hpc_cfg"] = hp_cfg + hp_cfg.setup() + + def run_test(): + """ + Verify dynamic memory slots attribute works with virtio-mem memory device + """ + test.log.info("TEST_STEP1: Define guest with virtio memory") + vm_attrs = update_vm_attrs(test, params) + memory_base.define_guest_with_memory_device( + params, virtio_mem_dict, vm_attrs) + + test.log.info("TEST_STEP2: Start vm") + vm.start() + vm.wait_for_login().close() + test.log.debug("Get xml after starting vm:%s", + vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)) + + test.log.info("TEST_SETUP3: Hotplug a virtio-mem device") + mem_obj = libvirt_vmxml.create_vm_device_by_type("memory", virtio_mem_dict) + virsh.attach_device( + vm.name, mem_obj.xml, wait_for_event=True, **virsh_dargs) + + test.log.info("TEST_SETUP4: Check qemu-monitor-command") + output = virsh.qemu_monitor_command( + vm_name, monitor_cmd, monitor_option, **virsh_dargs + ) + for pattern in slots_pattern: + if not re.search(pattern, output.stdout_text.strip()): + test.fail("Expect '%s' in qemu-monitor-command" % pattern) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bkxml.sync() + if memory_backing == "hugepages_mb": + params["hpc_cfg"].cleanup() + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + memory_base.check_supported_version(params, test, vm) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + virsh_dargs = {"debug": True, "ignore_status": False} + + default_hugepage_size = memory.get_huge_page_size() + allocate_size = int(params.get("allocate_size")) + memory_backing = params.get("memory_backing") + machine_version = params.get("machine_version") + monitor_cmd = params.get("monitor_cmd") + monitor_option = params.get("monitor_option") + slots_pattern = eval(params.get("slots_pattern")) + dynamic_slot_attr = eval(params.get("dynamic_slot_attr", "{}")) + virtio_mem_dict = eval(params.get('virtio_mem_dict') % default_hugepage_size) + if dynamic_slot_attr: + virtio_mem_dict['target']['attrs'] = dynamic_slot_attr + + if not libvirt_vmxml.check_guest_machine_type(vmxml, machine_version): + test.fail("Guest config machine should be >= rhel{}".format( + machine_version)) + try: + setup_test() + run_test() + + finally: + teardown_test() From cd40442f94e3d8765d2767f36092538f069c8916 Mon Sep 17 00:00:00 2001 From: nanli Date: Tue, 9 Jul 2024 21:23:34 +0800 Subject: [PATCH 0484/1055] add mem file for vcpu_misc: snapshot scenario add --memspec MEM_FILE when virsh snapshot-create-as Signed-off-by: nanli --- libvirt/tests/cfg/cpu/vcpu_misc.cfg | 2 ++ libvirt/tests/src/cpu/vcpu_misc.py | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/cfg/cpu/vcpu_misc.cfg b/libvirt/tests/cfg/cpu/vcpu_misc.cfg index 4a03b27fcb4..da9788bc779 100644 --- a/libvirt/tests/cfg/cpu/vcpu_misc.cfg +++ b/libvirt/tests/cfg/cpu/vcpu_misc.cfg @@ -8,6 +8,8 @@ - snapshot: cpu_mode = "host-model" test_operations = "do_snapshot" + mem_file = " /tmp/mem_file" + snapshot_options = "{} --memspec ${mem_file}" expected_str_after_startup = 'mode="custom"' aarch64: cpu_mode = "host-passthrough" diff --git a/libvirt/tests/src/cpu/vcpu_misc.py b/libvirt/tests/src/cpu/vcpu_misc.py index 1264ab79a7a..46eb7f1107b 100644 --- a/libvirt/tests/src/cpu/vcpu_misc.py +++ b/libvirt/tests/src/cpu/vcpu_misc.py @@ -189,20 +189,24 @@ def run(test, params, env): :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ - def do_snapshot(vm_name, expected_str): + def do_snapshot(vm_name, expected_str, params): """ Run snapshot related commands: snapshot-create-as, snapshot-list snapshot-dumpxml, snapshot-revert :param vm_name: vm name :param expected_str: expected string in snapshot-dumpxml + :param params: dict, test parameters :raise: test.fail if virsh command failed """ snapshot_name = vm_name + "-snap" + snapshot_options = params.get("snapshot_options") virsh_dargs = {'debug': True} - cmd_result = virsh.snapshot_create_as(vm_name, snapshot_name, - **virsh_dargs) + vm.start() + vm.wait_for_login().close() + cmd_result = virsh.snapshot_create_as( + vm_name, snapshot_options.format(snapshot_name), **virsh_dargs) libvirt.check_exit_status(cmd_result) try: @@ -219,6 +223,7 @@ def do_snapshot(vm_name, expected_str): cmd_result = virsh.snapshot_revert(vm_name, "", "--current", **virsh_dargs) libvirt.check_exit_status(cmd_result) + vm.destroy() libvirt_version.is_libvirt_feature_supported(params) vm_name = params.get('main_vm') @@ -238,6 +243,7 @@ def do_snapshot(vm_name, expected_str): bkxml = vmxml.copy() managed_save_file = "/var/lib/libvirt/qemu/save/%s.save" % vm_name maxphysaddr = params.get('maxphysaddr') + mem_file = params.get('mem_file') try: if check_vendor_id: @@ -269,8 +275,7 @@ def do_snapshot(vm_name, expected_str): if test_operations: for action in test_operations.split(","): if action == "do_snapshot": - do_snapshot(vm_name, expected_str_before_startup) - + do_snapshot(vm_name, expected_str_before_startup, params) if virsh_edit_cmd: status = libvirt.exec_virsh_edit(vm_name, virsh_edit_cmd.split(",")) if status == status_error: @@ -310,6 +315,8 @@ def do_snapshot(vm_name, expected_str): logging.debug("Recover test environment") if os.path.exists(managed_save_file): virsh.managedsave_remove(vm_name, debug=True) + if os.path.exists(mem_file): + os.remove(mem_file) if vm.is_alive(): vm.destroy() libvirt.clean_up_snapshots(vm_name, domxml=bkxml) From a59b1735448fcf2e8547806dfa18835577f14ebf Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 16 Jul 2024 10:18:43 +0800 Subject: [PATCH 0485/1055] migration: Fix parameters issue Fix following issue: TypeError: do_migration() got an unexpected keyword argument 'vm' Signed-off-by: lcheng --- libvirt/tests/src/migration/live_migration.py | 4 +-- libvirt/tests/src/migration/migrate_event.py | 2 +- .../src/migration/migrate_service_control.py | 4 +-- .../migrate_with_various_hostname.py | 4 +-- provider/migration/base_steps.py | 4 +-- provider/migration/migration_base.py | 32 +++++++++---------- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/libvirt/tests/src/migration/live_migration.py b/libvirt/tests/src/migration/live_migration.py index c737c838f76..eda5de10fee 100644 --- a/libvirt/tests/src/migration/live_migration.py +++ b/libvirt/tests/src/migration/live_migration.py @@ -325,7 +325,7 @@ def run(test, params, env): do_mig_param = {"vm": vm, "mig_test": migration_test, "src_uri": None, "dest_uri": dest_uri, "options": options, "virsh_options": virsh_options, "extra": extra, "action_during_mig": action_during_mig, "extra_args": extra_args} - migration_base.do_migration(do_mig_param) + migration_base.do_migration(**do_mig_param) func_returns = dict(migration_test.func_ret) migration_test.func_ret.clear() @@ -370,7 +370,7 @@ def run(test, params, env): do_mig_param = {"vm": vm, "mig_test": migration_test, "src_uri": None, "dest_uri": dest_uri, "options": options, "virsh_options": virsh_options, "extra": extra, "action_during_mig": action_during_mig, "extra_args": extra_args} - migration_base.do_migration(do_mig_param) + migration_base.do_migration(**do_mig_param) if return_port: func_returns = dict(migration_test.func_ret) logging.debug("Migration returns function " diff --git a/libvirt/tests/src/migration/migrate_event.py b/libvirt/tests/src/migration/migrate_event.py index 301432a19ff..b5762a4a5a0 100644 --- a/libvirt/tests/src/migration/migrate_event.py +++ b/libvirt/tests/src/migration/migrate_event.py @@ -81,7 +81,7 @@ def run(test, params, env): do_mig_param = {"vm": vm, "mig_test": migration_test, "src_uri": None, "dest_uri": dest_uri, "options": options, "virsh_options": virsh_options, "extra": extra, "action_during_mig": action_during_mig, "extra_args": extra_args} - migration_base.do_migration(do_mig_param) + migration_base.do_migration(**do_mig_param) func_returns = dict(migration_test.func_ret) migration_test.func_ret.clear() diff --git a/libvirt/tests/src/migration/migrate_service_control.py b/libvirt/tests/src/migration/migrate_service_control.py index 201851efd81..acf7882e895 100644 --- a/libvirt/tests/src/migration/migrate_service_control.py +++ b/libvirt/tests/src/migration/migrate_service_control.py @@ -137,7 +137,7 @@ def run(test, params, env): do_mig_param = {"vm": vm, "mig_test": migration_test, "src_uri": None, "dest_uri": dest_uri, "options": options, "virsh_options": virsh_options, "extra": extra, "action_during_mig": action_during_mig, "extra_args": extra_args} - migration_base.do_migration(do_mig_param) + migration_base.do_migration(**do_mig_param) func_returns = dict(migration_test.func_ret) migration_test.func_ret.clear() @@ -157,7 +157,7 @@ def run(test, params, env): do_mig_param = {"vm": vm, "mig_test": migration_test, "src_uri": None, "dest_uri": dest_uri, "options": options, "virsh_options": virsh_options, "extra": extra, "action_during_mig": action_during_mig, "extra_args": extra_args} - migration_base.do_migration(do_mig_param) + migration_base.do_migration(**do_mig_param) if int(migration_test.ret.exit_status) == 0: migration_test.post_migration_check([vm], params, dest_uri=dest_uri) finally: diff --git a/libvirt/tests/src/migration/migrate_with_various_hostname.py b/libvirt/tests/src/migration/migrate_with_various_hostname.py index 586da396c1a..66ad27b9760 100644 --- a/libvirt/tests/src/migration/migrate_with_various_hostname.py +++ b/libvirt/tests/src/migration/migrate_with_various_hostname.py @@ -197,7 +197,7 @@ def run(test, params, env): do_mig_param = {"vm": vm, "mig_test": migration_test, "src_uri": None, "dest_uri": dest_uri, "options": options, "virsh_options": virsh_options, "extra": extra, "action_during_mig": None, "extra_args": extra_args} - migration_base.do_migration(do_mig_param) + migration_base.do_migration(**do_mig_param) func_returns = dict(migration_test.func_ret) migration_test.func_ret.clear() @@ -215,7 +215,7 @@ def run(test, params, env): do_mig_param = {"vm": vm, "mig_test": migration_test, "src_uri": None, "dest_uri": dest_uri, "options": options, "virsh_options": virsh_options, "extra": extra, "action_during_mig": None, "extra_args": extra_args} - migration_base.do_migration(do_mig_param) + migration_base.do_migration(**do_mig_param) if int(migration_test.ret.exit_status) == 0: migration_test.post_migration_check([vm], params, dest_uri=dest_uri, src_uri=bk_uri) finally: diff --git a/provider/migration/base_steps.py b/provider/migration/base_steps.py index 661ce6c59c0..49c4259033f 100644 --- a/provider/migration/base_steps.py +++ b/provider/migration/base_steps.py @@ -171,7 +171,7 @@ def run_migration(self): do_mig_param = {"vm": self.vm, "mig_test": self.migration_test, "src_uri": None, "dest_uri": dest_uri, "options": options, "virsh_options": virsh_options, "extra": extra, "action_during_mig": action_during_mig, "extra_args": extra_args} - migration_base.do_migration(do_mig_param) + migration_base.do_migration(**do_mig_param) def run_migration_again(self): """ @@ -222,7 +222,7 @@ def run_migration_again(self): do_mig_param = {"vm": self.vm, "mig_test": self.migration_test, "src_uri": None, "dest_uri": dest_uri, "options": options, "virsh_options": virsh_options, "extra": extra, "action_during_mig": action_during_mig, "extra_args": extra_args} - migration_base.do_migration(do_mig_param) + migration_base.do_migration(**do_mig_param) def run_migration_back(self): """ diff --git a/provider/migration/migration_base.py b/provider/migration/migration_base.py index dce29036721..2c1b08dd7c6 100644 --- a/provider/migration/migration_base.py +++ b/provider/migration/migration_base.py @@ -81,24 +81,24 @@ def parse_funcs(action_during_mig, test, params): "function name and list are supported") -def do_migration(do_mig_param): +def do_migration(**kwargs): """ The wrapper function to call migration - :param do_mig_param: do migration parameters, dict, contains vm object, - MigrationTest object, source uri, target uri, migration - options, virsh options, extra options for migration, list - or single function to run during migration, arguments for test - """ - vm = do_mig_param['vm'] - mig_test = do_mig_param['mig_test'] - src_uri = do_mig_param['src_uri'] - dest_uri = do_mig_param['dest_uri'] - options = do_mig_param['options'] - virsh_options = do_mig_param['virsh_options'] - extra = do_mig_param['extra'] - action_during_mig = do_mig_param['action_during_mig'] - extra_args = do_mig_param['extra_args'] + :param kwargs: do migration parameters, dict, contains vm object, + MigrationTest object, source uri, target uri, migration + options, virsh options, extra options for migration, list + or single function to run during migration, arguments for test + """ + vm = kwargs.get('vm') + mig_test = kwargs.get('mig_test') + src_uri = kwargs.get('src_uri') + dest_uri = kwargs.get('dest_uri') + options = kwargs.get('options') + virsh_options = kwargs.get('virsh_options') + extra = kwargs.get('extra') + action_during_mig = kwargs.get('action_during_mig') + extra_args = kwargs.get('extra_args') vm_name = None if extra and "--dname" in extra: @@ -571,7 +571,7 @@ def resume_migration_again(params): do_mig_param = {"vm": migration_obj.vm, "mig_test": migration_obj.migration_test, "src_uri": None, "dest_uri": dest_uri, "options": options, "virsh_options": virsh_options, "extra": extra_twice_during_mig, "action_during_mig": None, "extra_args": extra_args_twice_during_mig} - do_migration(do_mig_param) + do_migration(**do_mig_param) def check_event_before_unattended(params): From 300271deb5e3ba08b1ab4b1b5aab7e7449f8f532 Mon Sep 17 00:00:00 2001 From: Xiaodai Wang Date: Thu, 18 Jul 2024 17:01:06 +0800 Subject: [PATCH 0486/1055] arm: ignore smccc_trng device Signed-off-by: Xiaodai Wang --- libvirt/tests/cfg/security/rng/libvirt_rng.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/security/rng/libvirt_rng.cfg b/libvirt/tests/cfg/security/rng/libvirt_rng.cfg index b3654e6bbb4..98907f2f49c 100644 --- a/libvirt/tests/cfg/security/rng/libvirt_rng.cfg +++ b/libvirt/tests/cfg/security/rng/libvirt_rng.cfg @@ -7,7 +7,7 @@ set_virtio_current = yes # Devices that might be present though not configured via . # For example, devices that are provided by the CPU. - ignored_devices = s390-trng,trng,tpm-rng-0 + ignored_devices = s390-trng,trng,tpm-rng-0,smccc_trng dd_throughput = "bs=512 count=10" snap_options = " %s" variants: From 5eb844149354699b65588a54dedc7d053f584b94 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Fri, 19 Jul 2024 15:36:39 +0800 Subject: [PATCH 0487/1055] Solve no space problem and make skip vm check work Signed-off-by: Ming Xie --- v2v/tests/src/nbdkit/nbdkit.py | 10 ++++------ v2v/tests/src/specific_kvm.py | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/v2v/tests/src/nbdkit/nbdkit.py b/v2v/tests/src/nbdkit/nbdkit.py index b0793f8974c..d533cc9662f 100644 --- a/v2v/tests/src/nbdkit/nbdkit.py +++ b/v2v/tests/src/nbdkit/nbdkit.py @@ -564,7 +564,6 @@ def cve_starttls(): process.run("yum install libtool 'dnf-command(download)' -y", shell=True, ignore_status=True) process.run('yum download --source nbdkit --destdir=%s' % tmp_path, shell=True, ignore_status=True) - process.run('rm -rf /etc/yum.repos.d/rhel9-appsource.repo', shell=True, ignore_status=True) process.run('cd %s ; rpmbuild -rp %s' % (tmp_path, (process.run('ls %s/nbdkit*.src.rpm' % tmp_path, shell=True). stdout_text.split('/'))[-1].strip('\n')), shell=True) check_file = process.run('ls /root/rpmbuild/BUILD/nbdkit-*/server/protocol-handshake-newstyle.c', @@ -617,14 +616,13 @@ def partition_sectorsize(): guest_images = params_get(params, "guest_images") with tempfile.TemporaryDirectory(prefix='guestimages_') as images_dir: utils_misc.mount(guest_images, images_dir, 'nfs') - img_dir = data_dir.get_tmp_dir() - process.run('cp -R %s/* %s' % (images_dir, img_dir), shell=True, ignore_status=True) + process.run('cp -R %s/* %s' % (images_dir, '/home'), shell=True, ignore_status=True) utils_misc.umount(guest_images, images_dir, 'nfs') - image_list = process.run('ls %s' % img_dir, shell=True).stdout_text.strip('env').split('\n')[1:-1] + image_list = process.run('ls %s/rhel*sector*' % '/home', shell=True).stdout_text.strip(' ').split('\n')[:-1] for image in image_list: for size in list(sector_size.split(' ')): - cmd = process.run("nbdkit --filter=partition file %s/%s partition=1 partition-sectorsize=%s --run " - "'nbdinfo $uri'" % (img_dir, image, size), shell=True, ignore_status=True) + cmd = process.run("nbdkit --filter=partition file %s partition=1 partition-sectorsize=%s --run " + "'nbdinfo $uri'" % (image, size), shell=True, ignore_status=True) if 'non-efi' not in image and '512' in image and size == '4k' and \ not re.search('.*try using partition-sectorsize=512', cmd.stderr_text): test.fail('fail to test 512 image and partition-sectorsize=4k') diff --git a/v2v/tests/src/specific_kvm.py b/v2v/tests/src/specific_kvm.py index 29ea3d34b41..2021eb70641 100644 --- a/v2v/tests/src/specific_kvm.py +++ b/v2v/tests/src/specific_kvm.py @@ -596,7 +596,7 @@ def check_result(result, status_error): if checkpoint == 'multi_kernel': check_boot_kernel(vmchecker.checker) check_vmlinuz_initramfs(output) - if checkpoint == 'multi_disks': + if checkpoint == 'multi_disks' and params.get('skip_vm_check') != 'yes': check_disks(vmchecker.checker) if checkpoint == 'multi_netcards': check_multi_netcards(params['mac_address'], From ea1b5cc41489bbcceede7b08d2726addedc347c9 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Fri, 19 Jul 2024 03:43:56 -0400 Subject: [PATCH 0488/1055] Remove vm destroy right after vm start to avoid destroy cmd failure Signed-off-by: liang-cong-red-hat --- .../tests/cfg/memory/memory_backing/lifecycle_for_hugepage.cfg | 1 + .../tests/src/memory/memory_backing/lifecycle_for_hugepage.py | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/memory/memory_backing/lifecycle_for_hugepage.cfg b/libvirt/tests/cfg/memory/memory_backing/lifecycle_for_hugepage.cfg index aa03fc5f369..79d9476ac82 100644 --- a/libvirt/tests/cfg/memory/memory_backing/lifecycle_for_hugepage.cfg +++ b/libvirt/tests/cfg/memory/memory_backing/lifecycle_for_hugepage.cfg @@ -1,5 +1,6 @@ - memory.backing.lifecycle: type = lifecycle_for_hugepage + start_vm = no total_hugepage_mem = 2097152 vm_nr_hugepages = 1024 mount_size = "1048576" diff --git a/libvirt/tests/src/memory/memory_backing/lifecycle_for_hugepage.py b/libvirt/tests/src/memory/memory_backing/lifecycle_for_hugepage.py index 82bb54b5efa..8397a0e99d9 100644 --- a/libvirt/tests/src/memory/memory_backing/lifecycle_for_hugepage.py +++ b/libvirt/tests/src/memory/memory_backing/lifecycle_for_hugepage.py @@ -121,7 +121,6 @@ def setup_test(vm_name, params, test): hp_cfg.hugepage_size = mount_size hp_cfg.mount_hugepage_fs() utils_libvirtd.Libvirtd().restart() - virsh.destroy(vm_name) def run_test(vm, params, test): From ab87f2bd263bd8b4646af19fe8875a8aecb38696 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Sat, 20 Jul 2024 10:43:25 +0800 Subject: [PATCH 0489/1055] v2v: only support 32 disks for v2v to rhev Signed-off-by: vwu-vera --- v2v/tests/cfg/function_test_esx.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 298cdd47cee..0caa9b44947 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -251,6 +251,7 @@ expect_msg = no - vddk_errors_41_disks: only negative_test + only rhev only esx_70 #add required version due to bug2051564 version_requried = "[virt-v2v-2.0.7-1,)" From 39d8e985021d69f251ad826b92cd569dff94b6de Mon Sep 17 00:00:00 2001 From: Slancaster1 Date: Fri, 12 Jul 2024 12:57:41 -0400 Subject: [PATCH 0490/1055] libvirt_hooks.py: Fix string matching -- The Issue The hook log for the hook "release end" can sometimes provide a reason for the release. /etc/libvirt/hooks/qemu guest_name release end The test currently looks for a logline that does not provide a reason for relase. This appears like this: /etc/libvirt/hooks/qemu guest_name release end - This results in the test failing if a reason is provided. E.G. the test will fail if this log line is given: /etc/libvirt/hooks/qemu guest_name release end shutdown -- The Fix Alter test such that it only looks for "release end" with or without a reason Signed-off-by: Slancaster1 --- libvirt/tests/cfg/libvirt_hooks.cfg | 1 + libvirt/tests/src/libvirt_hooks.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/libvirt_hooks.cfg b/libvirt/tests/cfg/libvirt_hooks.cfg index f109e54e778..29c75fccb5e 100644 --- a/libvirt/tests/cfg/libvirt_hooks.cfg +++ b/libvirt/tests/cfg/libvirt_hooks.cfg @@ -24,6 +24,7 @@ variants: - start_stop: test_start_stop = "yes" + release_reason = "shutdown" - libvirtd_t: test_libvirtd = "yes" - save_restore: diff --git a/libvirt/tests/src/libvirt_hooks.py b/libvirt/tests/src/libvirt_hooks.py index 4809eb4c47e..055d2a618a5 100644 --- a/libvirt/tests/src/libvirt_hooks.py +++ b/libvirt/tests/src/libvirt_hooks.py @@ -85,6 +85,7 @@ def start_stop_hook(): """ Do start/stop operation and check the results. """ + release_reason = params.get("release_reason", "-") logging.info("Try to test start/stop hooks...") hook_para = "%s %s" % (hook_file, vm_name) prepare_hook_file(hook_script % @@ -102,7 +103,7 @@ def start_stop_hook(): vm.destroy() hook_str = hook_para + " stopped end -" assert check_hooks(hook_str) - hook_str = hook_para + " release end -" + hook_str = hook_para + " release end " + release_reason assert check_hooks(hook_str) except AssertionError: utils_misc.log_last_traceback() From a92766abd60466c48a9c9d18bac655d2e41fadaa Mon Sep 17 00:00:00 2001 From: Vera Wu Date: Tue, 23 Jul 2024 11:43:29 +0800 Subject: [PATCH 0491/1055] v2v: fix verify_certificate func case on rhel10 Signed-off-by: Vera Wu --- v2v/tests/src/function_test_esx.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2v/tests/src/function_test_esx.py b/v2v/tests/src/function_test_esx.py index 8c07c1aac65..766e8ee7518 100644 --- a/v2v/tests/src/function_test_esx.py +++ b/v2v/tests/src/function_test_esx.py @@ -498,7 +498,7 @@ def _get_real_checksums(algorithm, file): test.fail('%s of rhsrvany.exe is not correct' % key) def verify_certificate(certs_src_dir, certs_dest_dir, vcenter_fdqn, vcenter_ip): - process.run('yum install ca-certificates -y | update-ca-trust enable', shell=True) + process.run('yum install ca-certificates -y | update-ca-trust', shell=True) mount_cert_dir = utils_v2v.v2v_mount(certs_src_dir, 'certs_src_dir') if not os.path.exists(certs_dest_dir): os.makedirs(certs_dest_dir) From d9b9827b795cdf444a55994616a984344da6da05 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Mon, 15 Jul 2024 01:57:58 -0400 Subject: [PATCH 0492/1055] Fix virsh nodedev list failure on s390x after libvirt-10.5.0,virsh nodedev list will list out all ccw devices regardless of device state Signed-off-by: chunfuwen --- libvirt/tests/src/virsh_cmd/nodedev/virsh_nodedev_list.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libvirt/tests/src/virsh_cmd/nodedev/virsh_nodedev_list.py b/libvirt/tests/src/virsh_cmd/nodedev/virsh_nodedev_list.py index a85574edc1a..34807b8a13e 100644 --- a/libvirt/tests/src/virsh_cmd/nodedev/virsh_nodedev_list.py +++ b/libvirt/tests/src/virsh_cmd/nodedev/virsh_nodedev_list.py @@ -145,6 +145,9 @@ def get_ccw_io_devices(): timeout=5, ignore_status=True, shell=True).stdout_text is_online = "1" == online_value.strip() + # After libvirt version 10.5.0, virsh nodedev list will list all of ccw devices regardless of its state + if libvirt_version.version_compare(10, 5, 0): + is_online = True if is_online: dev_name = re.sub(r'\W', '_', 'ccw_' + device) devices.append(dev_name) From 6cf8d94a940bc77c7acbe1acfbf421bde5903a41 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 22 Jul 2024 09:07:34 -0400 Subject: [PATCH 0493/1055] libvirt_ap_passthrough/autostart: wait for device come up Previously, the device was available immediately after login. Now, it can take another second. Expect a maximum of 5seconds for it to come up. Signed-off-by: Sebastian Mitterle --- .../ap/libvirt_ap_passthrough_autostart.py | 19 +++++++++++++------ spell.ignore | 1 + 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/libvirt/tests/src/passthrough/ap/libvirt_ap_passthrough_autostart.py b/libvirt/tests/src/passthrough/ap/libvirt_ap_passthrough_autostart.py index 2ec18207ff1..176395a6a14 100644 --- a/libvirt/tests/src/passthrough/ap/libvirt_ap_passthrough_autostart.py +++ b/libvirt/tests/src/passthrough/ap/libvirt_ap_passthrough_autostart.py @@ -11,15 +11,19 @@ # # Copyright: Red Hat Inc. 2022 # Author: Sebastian Mitterle +import logging + from avocado.core.exceptions import TestFail from virttest.libvirt_xml.vm_xml import VMXML -from virttest.utils_misc import cmd_status_output +from virttest.utils_misc import cmd_status_output, wait_for from virttest.utils_zcrypt import load_vfio_ap from provider.vfio import ap from provider.vfio.mdev_handlers import MdevHandler +LOG = logging.getLogger("avocado." + __name__) + def confirm_device_is_running(uuid, session=None): """ @@ -30,11 +34,14 @@ def confirm_device_is_running(uuid, session=None): be executed on the host. :raises TestFail: if the device isn't running. """ - cmd = "mdevctl list -u %s" % uuid - err, out = cmd_status_output(cmd, shell=True, session=session) - if uuid not in out: - raise TestFail("Mediated device UUID(%s) not listed in output:" - " %s. Exit code: %s" % (uuid, out, err)) + def _is_listed(): + """Parameterless helper function to use with wait_for""" + cmd = "mdevctl list -u %s" % uuid + err, out = cmd_status_output(cmd, shell=True, session=session) + LOG.debug(err, out) + return uuid in out + if not wait_for(_is_listed, timeout=5): + raise TestFail("Mediated device UUID(%s) not listed" % uuid) def run(test, params, env): diff --git a/spell.ignore b/spell.ignore index 2428d253562..c632c689787 100644 --- a/spell.ignore +++ b/spell.ignore @@ -733,6 +733,7 @@ ovs OVS ovsbridge pagesize +parameterless params paravirtual parma From 83dca6cae3ad55061e7f78df56f93ba9b1bccbcd Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 23 Jul 2024 05:19:11 -0400 Subject: [PATCH 0494/1055] memory: disable memory device tests on s390x On s390x memory devices are not available. Disable test cases. Signed-off-by: Sebastian Mitterle --- .../tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg | 1 + .../memory_devices/dimm_memory_with_access_and_discard.cfg | 1 + .../memory_devices/dimm_memory_with_auto_placement_numatune.cfg | 2 +- .../cfg/memory/memory_devices/virtio_mem_access_and_discard.cfg | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg index 6760b130675..3c3109ae56a 100644 --- a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg @@ -1,4 +1,5 @@ - memory.devices.dimm.hot_unplug: + no s390-virtio type = dimm_memory_hot_unplug start_vm = yes mem_model = 'dimm' diff --git a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_access_and_discard.cfg b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_access_and_discard.cfg index 44a991d5101..fadfd4b2c34 100644 --- a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_access_and_discard.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_access_and_discard.cfg @@ -9,6 +9,7 @@ target_size = 131072 requested_size = 131072 block_size = 2048 + no s390-virtio aarch64: target_size = 1048576 requested_size = 524288 diff --git a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_auto_placement_numatune.cfg b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_auto_placement_numatune.cfg index 7f67188cd79..a974fd409b6 100644 --- a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_auto_placement_numatune.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_auto_placement_numatune.cfg @@ -6,6 +6,7 @@ set_size = 131072 dimm_dict = {'mem_model': '${mem_model}', 'target': {'size': ${set_size}, 'node': 0, 'size_unit': 'KiB'}} attach_dimm = {'mem_model': '${mem_model}', 'target': {'size': ${set_size}, 'node': 1, 'size_unit': 'KiB'}} + no s390-virtio aarch64: set_size = 1048576 variants: @@ -26,7 +27,6 @@ tuning_attrs = "'numa_memory': {${mode_attrs} 'placement': '${placement}'}" variants: - with_numa: - no s390-virtio numa_mem = 1048576 mem_value = 2490368 current_mem = 2490368 diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_access_and_discard.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_access_and_discard.cfg index 7fdfe3c64a4..a73695f2bf8 100644 --- a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_access_and_discard.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_access_and_discard.cfg @@ -9,6 +9,7 @@ target_size = 131072 requested_size = 131072 block_size = 2048 + no s390-virtio aarch64: target_size = 1048576 requested_size = 524288 @@ -58,7 +59,6 @@ expected_discard = ['${discard_0}', 'True', 'True', 'False', 'False', 'True'] variants: - with_numa: - no s390-virtio mem_value = 3145728 current_mem = 3145728 max_mem = 10485760 From a9e94bfa6cbca5e56d0e9b5bef7a3bf3062a4116 Mon Sep 17 00:00:00 2001 From: Lili Zhu Date: Tue, 23 Jul 2024 21:39:30 -0400 Subject: [PATCH 0495/1055] Update the lock options and virtiofsd options format 1. For bug RHEL-7108, virtiofsd options format has been updated, we need to update the script. 2. In the commit for fix bug RHEL-7108, lock options are not allowed to config any more, so we need to remove them thoroughly. 3. Cache mode "none" can not be used from virtiofsd-1.11.1, it should be replaced as "never" from now on. RFE bug about mode "never" will be filed later. Signed-off-by: Lili Zhu --- .../cfg/virtual_device/filesystem_device.cfg | 32 ++++++----------- .../src/virtual_device/filesystem_device.py | 35 ++++++++----------- 2 files changed, 24 insertions(+), 43 deletions(-) diff --git a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg index f4ccfea94d6..76a1352cc9b 100644 --- a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg +++ b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg @@ -3,9 +3,7 @@ take_regular_screendumps = "no" vms = "avocado-vt-vm1" start_vm = no - cache_mode = "none" - lock_posix = "off" - flock = "off" + cache_mode = "auto" virtiofsd_path = "/usr/libexec/virtiofsd" queue_size = "512" driver_type = "virtiofs" @@ -32,17 +30,17 @@ - two_guests: vms = "avocado-vt-vm1 avocado-vt-vm2" guest_num = 2 - only nop.fs_test.xattr_on.flock_off.lock_posix_off.cache_mode_none..one_fs, hotplug_unplug..fs_test.xattr_on.flock_off.lock_posix_off.cache_mode_none..one_fs + only nop.fs_test.xattr_on.cache_mode_auto..one_fs, hotplug_unplug..fs_test.xattr_on.cache_mode_auto..one_fs variants: - one_fs: fs_num = 1 - multiple_fs: fs_num = 2 - only xattr_on.flock_off.lock_posix_off.cache_mode_none + only xattr_on.cache_mode_auto variants: - thread_pool_16: thread_pool_size = 16 - only positive_test..nop..xattr_on.flock_off.lock_posix_off.cache_mode_none, positive_test..detach_device..xattr_on.flock_off.lock_posix_off.cache_mode_none + only positive_test..nop..xattr_on.cache_mode_auto, positive_test..detach_device..xattr_on.cache_mode_auto - thread_pool_noset: variants: - cache_mode_none: @@ -51,16 +49,6 @@ cache_mode = "always" - cache_mode_auto: cache_mode = "auto" - variants: - - lock_posix_off: - lock_posix = "off" - - lock_posix_on: - lock_posix = "on" - variants: - - flock_on: - flock = "on" - - flock_off: - flock = "off" variants: - xattr_on: xattr = "on" @@ -72,9 +60,9 @@ - nop: - socket_file_checking: socket_file_checking = "yes" - only xattr_on.flock_off.lock_posix_off.cache_mode_none, externally_launched_fs_test + only xattr_on.cache_mode_auto, externally_launched_fs_test - lifecycle: - only xattr_on.flock_off.lock_posix_off.cache_mode_none..one_fs + only xattr_on.cache_mode_auto..one_fs variants: - suspend_resume: suspend_resume = "yes" @@ -93,16 +81,16 @@ source_dir = "/var/tmp/mount_tag0" dev_type = "filesystem" vm_attrs = {'mb': {"source_type":"file", 'access_mode': 'shared'}} - fs_dict = {'accessmode':'passthrough', 'driver': {'type': 'virtiofs', 'queue':'512'}, 'source':{'dir': '${source_dir}'}, "target": {'dir': 'mount_tag0'}, 'binary': {'path': '/usr/libexec/virtiofsd', 'xattr': 'on','cache_mode':'none','lock_posix':'off','flock':'off'}} + fs_dict = {'accessmode':'passthrough', 'driver': {'type': 'virtiofs', 'queue':'512'}, 'source':{'dir': '${source_dir}'}, "target": {'dir': 'mount_tag0'}, 'binary': {'path': '/usr/libexec/virtiofsd', 'xattr': 'on','cache_mode':'always'}} - coldplug_coldunplug: - only xattr_on.flock_off.lock_posix_off.cache_mode_none..one_fs + only xattr_on.cache_mode_auto..one_fs coldplug = "yes" - hotplug_unplug: hotplug_unplug = "yes" variants: - detach_device_alias: detach_device_alias = "yes" - only xattr_on.flock_off.lock_posix_off.cache_mode_none + only xattr_on.cache_mode_auto variants: - stdio_handler: variants: @@ -127,7 +115,7 @@ with_hugepages = no with_memfd = yes - negative_test: - only fs_test.xattr_on.flock_off.lock_posix_off.cache_mode_none..one_fs.one_guest + only fs_test.xattr_on.cache_mode_auto..one_fs.one_guest status_error = "yes" variants: - invalid_queue_size: diff --git a/libvirt/tests/src/virtual_device/filesystem_device.py b/libvirt/tests/src/virtual_device/filesystem_device.py index 4d9327345cb..9f09c4b1fd7 100644 --- a/libvirt/tests/src/virtual_device/filesystem_device.py +++ b/libvirt/tests/src/virtual_device/filesystem_device.py @@ -37,26 +37,23 @@ def run(test, params, env): 5.Lifecycle for guest with virtiofs filesystem device. """ - def generate_expected_process_option(expected_results): + def generate_expected_process_option(): """ Generate expected virtiofsd process option """ + expected_results = "" if cache_mode != "auto": - expected_results = "cache=%s" % cache_mode + expected_results += "cache(\s|=)%s" % cache_mode if xattr == "on": - expected_results += ",xattr" - elif xattr == "off": + expected_results += "(\s--|,)xattr" + elif xattr == "off" and not libvirt_version.version_compare(10, 5, 0): expected_results += ",no_xattr" - if flock == "on": - expected_results += ",flock" - else: - expected_results += ",no_flock" - if lock_posix == "on": - expected_results += ",posix_lock" - else: - expected_results += ",no_posix_lock" if thread_pool_size: - expected_results += " --thread-pool-size=%s" % thread_pool_size + # Even through there is a equal mark between --thread-pool-size and + # its value for libvirt format. But there is no equal mark in + # virtiofsd man pages. Add another kind of pattern here to avoid + # possible change in the future again. + expected_results += " --thread-pool-size(\s|=)%s" % thread_pool_size logging.debug(expected_results) return expected_results @@ -223,8 +220,6 @@ def check_filesystem_hotplug_with_mem_setup(): vm_names = params.get("vms", "avocado-vt-vm1").split() cache_mode = params.get("cache_mode", "none") xattr = params.get("xattr", "on") - lock_posix = params.get("lock_posix", "on") - flock = params.get("flock", "on") xattr = params.get("xattr", "on") path = params.get("virtiofsd_path", "/usr/libexec/virtiofsd") thread_pool_size = params.get("thread_pool_size") @@ -260,7 +255,6 @@ def check_filesystem_hotplug_with_mem_setup(): vms = [] vmxml_backups = [] expected_fails_msg = [] - expected_results = "" host_hp_size = utils_memory.get_huge_page_size() backup_huge_pages_num = utils_memory.get_num_huge_pages() huge_pages_num = 0 @@ -292,10 +286,8 @@ def check_filesystem_hotplug_with_mem_setup(): source = {'socket': source_socket} target = {'dir': target_dir} if launched_mode == "auto": - binary_keys = ['path', 'cache_mode', 'xattr', 'lock_posix', - 'flock', 'thread_pool_size'] - binary_values = [path, cache_mode, xattr, lock_posix, - flock, thread_pool_size] + binary_keys = ['path', 'cache_mode', 'xattr', 'thread_pool_size'] + binary_values = [path, cache_mode, xattr, thread_pool_size] binary_dict = dict(zip(binary_keys, binary_values)) source = {'dir': source_dir} accessmode = "passthrough" @@ -318,6 +310,7 @@ def check_filesystem_hotplug_with_mem_setup(): vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_names[index]) vmxml_backup = vmxml.copy() vmxml_backups.append(vmxml_backup) + logging.debug(fs_dev) if vmxml.max_mem < 1024000: vmxml.max_mem = 1024000 if with_hugepages: @@ -365,7 +358,7 @@ def check_filesystem_hotplug_with_mem_setup(): return else: utils_test.libvirt.check_exit_status(result, expect_error=False) - expected_results = generate_expected_process_option(expected_results) + expected_results = generate_expected_process_option() if launched_mode == "auto": cmd = 'ps aux | grep /usr/libexec/virtiofsd' utils_test.libvirt.check_cmd_output(cmd, content=expected_results) From 3dd8d63e3c2475ea1f48cf4987d5a4123025a173 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Fri, 19 Jul 2024 06:45:02 -0400 Subject: [PATCH 0496/1055] network_base:Add timeout for get_vm_ip Signed-off-by: Haijiao Zhao --- provider/virtual_network/network_base.py | 40 +++++++++++++++--------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/provider/virtual_network/network_base.py b/provider/virtual_network/network_base.py index 8a70be4e1d8..b0fab06b875 100644 --- a/provider/virtual_network/network_base.py +++ b/provider/virtual_network/network_base.py @@ -6,6 +6,7 @@ from avocado.core import exceptions from avocado.utils import process from virttest import remote +from virttest import utils_misc from virttest import utils_net from virttest import virsh from virttest.libvirt_xml import network_xml @@ -16,7 +17,7 @@ LOG = logging.getLogger('avocado.' + __name__) -def get_vm_ip(session, mac, ip_ver="ipv4"): +def get_vm_ip(session, mac, ip_ver="ipv4", timeout=5): """ Get vm ip address @@ -25,22 +26,31 @@ def get_vm_ip(session, mac, ip_ver="ipv4"): :param ip_ver: ip version, defaults to "ipv4" :return: ip address of given mac """ - iface_info = utils_net.get_linux_iface_info(mac=mac, session=session) - addr_list = iface_info['addr_info'] - if ip_ver == "ipv4": - target_addr = [addr for addr in addr_list if addr['family'] == 'inet'] - elif ip_ver == "ipv6": - target_addr = [addr for addr in addr_list if addr['family'] == 'inet6' - and addr['scope'] == 'global' - and addr.get('mngtmpaddr') is not True] - - if len(target_addr) == 0: + def _get_vm_ip(): + iface_info = utils_net.get_linux_iface_info(mac=mac, session=session) + addr_list = iface_info['addr_info'] + if ip_ver == "ipv4": + target_addr = [addr for addr in addr_list if addr['family'] == 'inet'] + elif ip_ver == "ipv6": + target_addr = [addr for addr in addr_list if addr['family'] == 'inet6' + and addr['scope'] == 'global' + and addr.get('mngtmpaddr') is not True] + + if len(target_addr) == 0: + LOG.warn(f'No ip addr of given mac: {mac}') + return + elif len(target_addr) > 1: + LOG.warn(f'Multiple ip addr: {target_addr}') + + return target_addr[0]['local'] + + vm_ip = utils_misc.wait_for(_get_vm_ip, timeout, ignore_errors=True) + + if not vm_ip: raise exceptions.TestError( - f'Cannot find ip addr with given mac: {mac}') - elif len(target_addr) > 1: - LOG.warn(f'Multiple ip addr: {target_addr}') + f'Cannot find {ip_ver} addr with given mac: {mac}') - return target_addr[0]['local'] + return vm_ip def get_test_ips(session, mac, ep_session, ep_mac, net_name=None, From e5c3f2c45adaf5e09ec7c14eb50646a42b3b2550 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Mon, 1 Jul 2024 23:19:02 -0400 Subject: [PATCH 0497/1055] Add new case of resolvectl - VIRT-301738 - resolve guest hostname from host by resolvectl Signed-off-by: Haijiao Zhao --- .../resolve_vm_hostname_by_resolvectl.cfg | 28 +++++ .../resolve_vm_hostname_by_resolvectl.py | 112 ++++++++++++++++++ provider/virtual_network/network_base.py | 8 +- spell.ignore | 2 + 4 files changed, 143 insertions(+), 7 deletions(-) create mode 100644 libvirt/tests/cfg/virtual_network/resolve_vm_hostname_by_resolvectl.cfg create mode 100644 libvirt/tests/src/virtual_network/resolve_vm_hostname_by_resolvectl.py diff --git a/libvirt/tests/cfg/virtual_network/resolve_vm_hostname_by_resolvectl.cfg b/libvirt/tests/cfg/virtual_network/resolve_vm_hostname_by_resolvectl.cfg new file mode 100644 index 00000000000..b4398266fa8 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/resolve_vm_hostname_by_resolvectl.cfg @@ -0,0 +1,28 @@ +- virtual_network.resolve_vm_hostname_by_resolvectl: + type = resolve_vm_hostname_by_resolvectl + start_vm = no + vms = avocado-vt-vm1 vm2 + timeout = 240 + func_supported_since_libvirt_ver = (10, 3, 0) + localonly = yes + register_attr = {} + ip_attrs = {'hosts': [{'attrs': {'mac': mac_a, 'name': 'vm1', 'ip': '192.168.122.32'}}]} + ips = {'vm_ip': 'vm1', 'vm_with_domain_ip': 'vm1.example.com', 'vmtest_ip': 'vmtest', 'vmtest_with_domain_ip': 'vmtest.example.com'} + variants register: + - yes: + register_attr = {'register': '${register}'} + host_ping_vm = fail + host_ping_vm_with_domain = pass + host_ping_vmtest = fail + host_ping_vmtest_with_domain = pass + - no: + register_attr = {'register': '${register}'} + host_ping_vm_with_domain = fail + - omitted: + host_ping_vm_with_domain = fail + - localonly_no: + localonly = no + register_attr = {'register': 'yes'} + status_error = yes + err_msg = Failed to define network + net_attrs = {'domain': {'name': 'example.com', 'localOnly': '${localonly}', **${register_attr}}} diff --git a/libvirt/tests/src/virtual_network/resolve_vm_hostname_by_resolvectl.py b/libvirt/tests/src/virtual_network/resolve_vm_hostname_by_resolvectl.py new file mode 100644 index 00000000000..c46e12703c3 --- /dev/null +++ b/libvirt/tests/src/virtual_network/resolve_vm_hostname_by_resolvectl.py @@ -0,0 +1,112 @@ +import logging +import re + +from avocado.utils import process +from virttest import libvirt_version +from virttest import utils_misc +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.network_xml import NetworkXML +from virttest.staging import service +from virttest.utils_test import libvirt + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test resolve guest hostname from host by resolvectl + + """ + libvirt_version.is_libvirt_feature_supported(params) + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + vm_b = env.get_vm(params.get('vms').split()[-1]) + status_error = 'yes' == params.get('status_error', 'no') + err_msg = params.get('err_msg', '') + rand_id = utils_misc.generate_random_string(3) + register = 'yes' == params.get('register', 'no') + net_attrs = eval(params.get('net_attrs', '{}')) + ips = eval(params.get('ips', '{}')) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + net_xml = NetworkXML.new_from_net_dumpxml('default') + bk_net_xml = net_xml.copy() + sys_resolved = service.Factory.create_service("systemd-resolved") + conf_path = '/etc/resolv.conf' + conf_path_bk = f'{conf_path}.bk_{rand_id}' + + try: + sys_resolved.start() + iface_a = network_base.get_iface_xml_inst(vm_name, 'on vm') + mac_a = iface_a.mac_address + + ip_attrs = eval(params.get('ip_attrs', '{}')) + net_ips = net_xml.ips + net_ips[0].update(**ip_attrs) + net_xml.ips = net_ips + + net_xml.setup_attrs(**net_attrs) + if status_error: + net_xml.xmltreefile.write() + LOG.debug(net_xml) + def_result = virsh.net_define(net_xml.xml, debug=True) + libvirt.check_exit_status(def_result, status_error) + libvirt.check_result(def_result, err_msg) + return + + net_xml.sync() + LOG.debug(virsh.net_dumpxml('default').stdout_text) + + LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + br = net_xml.bridge['name'] + domain_output = process.run(f'resolvectl domain {br}').stdout_text + dns_output = process.run(f'resolvectl dns {br}').stdout_text + if register: + dom_pattern = re.compile(rf'Link \d+ \({br}\): ~example.com\s*$') + dns_pattern = re.compile( + rf'Link \d+ \({br}\): {net_ips[0].address}\s*$') + else: + dom_pattern = re.compile(r'Link \d+ \(.*\):\s*$') + dns_pattern = dom_pattern + + if not dom_pattern.search(domain_output): + test.fail(f'Unexpected output of resolvectl:\n{domain_output}') + if not dns_pattern.search(dns_output): + test.fail(f'Unexpected output of resolvectl:\n{dns_output}') + + # Backup the /etc/resolv.conf file + process.run(f'cp {conf_path} {conf_path_bk}') + # Make /etc/resolve.conf as symbolic file + process.run( + f'ln -f -r -s /run/systemd/resolve/stub-resolv.conf {conf_path}') + process.run(f'file {conf_path}') + name_serv_output = process.run(f'cat {conf_path}').stdout_text + if not re.search(r'nameserver\s+127.0.0.53', name_serv_output): + test.fail('Nameserver output check failed') + + vm.start() + vm_b.start() + # Wait for vm to get dhcp lease + vm.wait_for_serial_login().close() + + session_b = vm_b.wait_for_serial_login() + session_b.cmd('hostnamectl set-hostname vmtest') + session_b.cmd('systemctl restart NetworkManager') + session_b.close() + + virsh.net_dhcp_leases('default', **VIRSH_ARGS) + network_base.ping_check(params, ips) + + finally: + vm.destroy() + vm_b.destroy() + bkxml.sync() + bk_net_xml.sync() + process.run(f'mv {conf_path_bk} {conf_path}', ignore_status=True) diff --git a/provider/virtual_network/network_base.py b/provider/virtual_network/network_base.py index cd3bc43a9c0..0cd055c2cfa 100644 --- a/provider/virtual_network/network_base.py +++ b/provider/virtual_network/network_base.py @@ -88,12 +88,6 @@ def ping_check(params, ips, session=None, force_ipv4=True, **args): :param force_ipv4: whether to force ping with ipv4 :param args: other kwargs """ - outside_ip = ips.get('outside_ip') - vm_ip = ips.get('vm_ip') - ep_vm_ip = ips.get('ep_vm_ip') - host_public_ip = ips.get('host_public_ip') - host_virbr_ip = ips.get('host_virbr_ip') - outside_ip = ips.get('outside_ip') ping_patterns = {k: v for k, v in params.items() if '_ping_' in k} for pattern, expect_result in ping_patterns.items(): @@ -101,7 +95,7 @@ def ping_check(params, ips, session=None, force_ipv4=True, **args): if destination == 'outside' and not force_ipv4: LOG.debug('No need to test ping outside with ipv6') continue - dest_ip = eval(f'{destination}_ip') + dest_ip = ips.get(f'{destination}_ip') if dest_ip is None: raise exceptions.TestError(f'IP of {destination} is None') diff --git a/spell.ignore b/spell.ignore index 2428d253562..7d553df711c 100644 --- a/spell.ignore +++ b/spell.ignore @@ -848,6 +848,8 @@ resize Resize resized resizing +resolv +resolvectl restared restorecon ret From 0bc6f6793c2c60cd7e83c20626cff7e1a0d8c2c3 Mon Sep 17 00:00:00 2001 From: Vera Wu Date: Wed, 24 Jul 2024 14:21:43 +0800 Subject: [PATCH 0498/1055] v2v: fix rhel10.0 failed func TCs of convert-from-file Signed-off-by: Vera Wu --- v2v/tests/cfg/convert_from_file.cfg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/v2v/tests/cfg/convert_from_file.cfg b/v2v/tests/cfg/convert_from_file.cfg index a6fed2b72e3..9b8c589f7fe 100644 --- a/v2v/tests/cfg/convert_from_file.cfg +++ b/v2v/tests/cfg/convert_from_file.cfg @@ -266,7 +266,7 @@ only esx_70 only windows os_version = 'win2012r2' - has_genid = 'no' + has_genid = 'yes' main_vm = 'VM_NAME_GENID_WIN2012R2_V2V_EXAMPLE' vmx_nfs_src = NFS_ESX70_VMX_V2V_EXAMPLE # genid only supports libvirt, local, qemu @@ -290,14 +290,14 @@ # genid only supports libvirt, local, qemu only output_mode.libvirt - latest8: - only esx_70 + only esx_80 main_vm = 'VM_NAME_RHEL8_V2V_EXAMPLE' - latest7: - only esx_70 + only esx_80 main_vm = 'VM_NAME_RHEL7_V2V_EXAMPLE' - latest6: enable_legacy_policy = yes - only esx_70 + only esx_80 main_vm = 'VM_NAME_RHEL6_V2V_EXAMPLE' - cpu_topology: only esx_70 From d7ec29a976f7712993821df7740d79b2088907f3 Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 22 Jul 2024 17:25:27 +0800 Subject: [PATCH 0499/1055] migration: Update error message Signed-off-by: lcheng --- .../tests/cfg/migration_with_copy_storage/autoskipped_disks.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration_with_copy_storage/autoskipped_disks.cfg b/libvirt/tests/cfg/migration_with_copy_storage/autoskipped_disks.cfg index 2acba347c5e..234d7f691f1 100644 --- a/libvirt/tests/cfg/migration_with_copy_storage/autoskipped_disks.cfg +++ b/libvirt/tests/cfg/migration_with_copy_storage/autoskipped_disks.cfg @@ -59,7 +59,7 @@ second_disk_name = "readonly.raw" local_storage: status_error = "yes" - err_msg = "Path .* is not accessible: No such file or directory" + err_msg = "No such file or directory" - cdrom_with_empty_source: second_disk_dict = {"device": "cdrom", "type_name": "file", "driver": {"name": "qemu"}, "target": {"dev": "sda", "bus": "sata"}, "readonly": True} - cdrom_with_startuppolicy: From 5173539a6d007c10254c468458d6e8bc5d720aaa Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 24 Jul 2024 19:27:59 +0800 Subject: [PATCH 0500/1055] sriov: Add a case about network connections This PR adds: VIRT-301829 - Check the number of connections on hostdev network during vm destroy/start Signed-off-by: Yingshun Cui --- .../sriov_check_network_connections.cfg | 8 ++++ .../sriov_check_network_connections.py | 46 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 libvirt/tests/cfg/sriov/network/sriov_check_network_connections.cfg create mode 100644 libvirt/tests/src/sriov/network/sriov_check_network_connections.py diff --git a/libvirt/tests/cfg/sriov/network/sriov_check_network_connections.cfg b/libvirt/tests/cfg/sriov/network/sriov_check_network_connections.cfg new file mode 100644 index 00000000000..d38f5ca79b0 --- /dev/null +++ b/libvirt/tests/cfg/sriov/network/sriov_check_network_connections.cfg @@ -0,0 +1,8 @@ +- sriov.network.check_connections: + type = sriov_check_network_connections + only x86_64, aarch64 + + start_vm = "no" + network_dict = {'forward': {'mode': 'hostdev', 'managed': 'yes'}, 'name': 'hostdev_net', 'pf': {'dev': pf_name}} + iface_dict = {'type_name': 'network', 'source': {'network': 'hostdev_net'}} + iface_nums = 2 diff --git a/libvirt/tests/src/sriov/network/sriov_check_network_connections.py b/libvirt/tests/src/sriov/network/sriov_check_network_connections.py new file mode 100644 index 00000000000..ade32808a2a --- /dev/null +++ b/libvirt/tests/src/sriov/network/sriov_check_network_connections.py @@ -0,0 +1,46 @@ +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_network +from virttest.utils_libvirt import libvirt_vmxml + +from provider.sriov import sriov_base + + +def run(test, params, env): + """ + Check the number of connections on hostdev network + """ + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + sriov_test_obj = sriov_base.SRIOVTest(vm, test, params) + network_dict = sriov_test_obj.parse_network_dict() + net_name = network_dict.get("name") + iface_dict = eval(params.get("iface_dict", "{}")) + iface_nums = int(params.get("iface_nums", "2")) + + try: + sriov_test_obj.setup_default(network_dict=network_dict) + for idx in range(iface_nums): + libvirt_vmxml.modify_vm_device( + vm_xml.VMXML.new_from_inactive_dumpxml(vm_name), + 'interface', iface_dict, idx) + test.log.debug(f"vm xml: {vm_xml.VMXML.new_from_dumpxml(vm_name)}") + + test.log.info("TEST_STEP: Start a VM with hostdev interfaces.") + vm.start() + vm.wait_for_serial_login().close() + + test.log.info(f"TEST_STEP: Check if there are {iface_nums} network connections.") + libvirt_network.check_network_connection(net_name, iface_nums) + + test.log.info(f"TEST_STEP: Destroy and start network and vm.") + virsh.net_destroy(net_name, debug=True, ignore_status=False) + virsh.net_start(net_name, debug=True, ignore_status=False) + vm.destroy() + vm.start() + + test.log.info(f"TEST_STEP: Check if there are {iface_nums} network connections.") + libvirt_network.check_network_connection(net_name, iface_nums) + finally: + sriov_test_obj.teardown_default(network_dict=network_dict) From 28578d4aad168886e7714dde86f153ef8837c2da Mon Sep 17 00:00:00 2001 From: Vera Wu Date: Wed, 24 Jul 2024 19:42:33 +0800 Subject: [PATCH 0501/1055] v2v: fix cpu-topology case on rhel10 Signed-off-by: Vera Wu --- v2v/tests/cfg/convert_from_file.cfg | 2 ++ v2v/tests/cfg/function_test_esx.cfg | 1 + 2 files changed, 3 insertions(+) diff --git a/v2v/tests/cfg/convert_from_file.cfg b/v2v/tests/cfg/convert_from_file.cfg index 9b8c589f7fe..235911d61a1 100644 --- a/v2v/tests/cfg/convert_from_file.cfg +++ b/v2v/tests/cfg/convert_from_file.cfg @@ -112,6 +112,7 @@ ova_dir = OVA_DIR_BUG_2069768_V2V_EXAMPLE input_file = '${ova_copy_dir}/OVA_FILE_BUG_2069768_V2V_EXAMPLE' - cpu_topology: + only output_mode.rhev checkpoint = 'cpu_topology' v2v_debug = force_on ova_file_name = OVA_FILE_CPU_TOPOLOGY_V2V_EXAMPLE @@ -301,6 +302,7 @@ main_vm = 'VM_NAME_RHEL6_V2V_EXAMPLE' - cpu_topology: only esx_70 + only output_mode.rhev vmx_nfs_src = NFS_ESX70_FUNC_VMX_V2V_EXAMPLE main_vm = 'VM_NAME_CPU_TOPOLOGY_V2V_EXAMPLE' v2v_debug = force_on diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 0caa9b44947..772742e9de3 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -895,6 +895,7 @@ - cpu_topology: only esx_70 only it_vddk + only rhev main_vm = VM_NAME_CPU_TOPOLOGY_V2V_EXAMPLE checkpoint = 'cpu_topology' v2v_debug = force_on From 527b75cbea4a4cb85667dd8ef5dc72a56b3a919f Mon Sep 17 00:00:00 2001 From: Vera Wu Date: Wed, 24 Jul 2024 16:05:27 +0800 Subject: [PATCH 0502/1055] v2v: fix rhel10.0 failed func TCs of function_test_esx Signed-off-by: Vera Wu --- v2v/tests/cfg/function_test_esx.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 0caa9b44947..22951353122 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -425,6 +425,7 @@ skip_reason = 'bz#1990808' - resume_rhel7: only esx_70 + only rhev os_version = OS_VERSION_RESUME_RHEL7_V2V_EXAMPLE checkpoint = resume_swap main_vm = VM_NAME_RESUME_RHEL7_V2V_EXAMPLE From 4b4b3bad40a97ba37ba1afce292d9b334aa4f0ba Mon Sep 17 00:00:00 2001 From: Vera Wu Date: Thu, 25 Jul 2024 11:57:14 +0800 Subject: [PATCH 0503/1055] v2v: fix ogac and without_default_net cases on functional testing Signed-off-by: Vera Wu --- v2v/tests/cfg/function_test_esx.cfg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 099c23cfd64..ca3824e1380 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -542,7 +542,7 @@ qa_url = QEMU_GUEST_AGENT_DEBIAN_DOWNLOAD_URL_V2V_EXAMPLE main_vm = VM_NAME_UBUNTU_V2V_EXAMPLE - debian: - only esx_70 + only esx_80 version_required = "[virt-v2v-2.0.6-3,)" qa_path = 'linux/debian' qa_url = QEMU_GUEST_AGENT_DEBIAN_DOWNLOAD_URL_V2V_EXAMPLE @@ -553,8 +553,7 @@ qa_url = QEMU_GUEST_AGENT_SUSE_DOWNLOAD_URL_V2V_EXAMPLE main_vm = VM_NAME_SLES_V2V_EXAMPLE - opensuse: - only esx_70 - boottype = 3 + only esx_80 qa_path = 'linux/lp151' qa_url = QEMU_GUEST_AGENT_SUSE_DOWNLOAD_URL_V2V_EXAMPLE main_vm = VM_NAME_OPENSUSE_V2V_EXAMPLE @@ -578,6 +577,7 @@ expect_msg = no - without_default_net: only esx_70 + only rhev main_vm = VM_NAME_ESX70_RHEL7_V2V_EXAMPLE checkpoint = "without_default_net" v2v_debug = force_on From aae76b53967f7a2717ca5a1acbd8099076dcde8a Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Wed, 12 Jun 2024 06:57:20 -0400 Subject: [PATCH 0504/1055] Add network case of qos - VIRT-296327 - [Qos] Check the actual network throughput per bandwidth settings in network/interface Signed-off-by: Haijiao Zhao --- .../qos/check_actual_network_throughput.cfg | 35 +++++ .../qos/check_actual_network_throughput.py | 132 ++++++++++++++++++ provider/virtual_network/network_base.py | 27 ++++ 3 files changed, 194 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput.cfg create mode 100644 libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py diff --git a/libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput.cfg b/libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput.cfg new file mode 100644 index 00000000000..5b89e7244e1 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput.cfg @@ -0,0 +1,35 @@ +- virtual_network.qos.check_actual_network_throughput: + type = check_actual_network_throughput + start_vm = no + timeout = 240 + host_iface = + inbound = {'average': '512', 'peak': '1024', 'burst': '32'} + outbound = {'average': '128', 'peak': '1024', 'burst': '32'} + iface_bw_attrs = {'bandwidth': {'inbound': ${inbound}, 'outbound': ${outbound}}} + variants iface_type: + - network: + net_bw_attrs = {'bandwidth_inbound': ${inbound}, 'bandwidth_outbound': ${outbound}} + variants net_fwm: + - nat: + variants: + - net_with_qos: + net_attrs = ${net_bw_attrs} + iface_bw_attrs = {} + - iface_with_qos: + iface_attrs = {'source': {'network': 'default'}, 'model': 'virtio', 'type_name': 'network', **${iface_bw_attrs}} + - br: + net_fwm = bridge + iface_attrs = {'type_name': 'network', 'model': 'virtio', 'source': {'network': net_name}} + variants br_type: + - linux_br: + net_attrs = {'name': net_name, 'forward': {'mode': 'bridge'}, 'bridge': {'name': br_name}, **${net_bw_attrs}} + - ovs_br: + net_attrs = {'name': net_name, 'forward': {'mode': 'bridge'}, 'bridge': {'name': br_name}, **${net_bw_attrs}, 'virtualport_type': 'openvswitch'} + - br: + iface_type = bridge + variants br_type: + - linux_br: + iface_attrs = {'type_name': 'bridge', 'source': {'bridge': br_name}, 'model': 'virtio', **${iface_bw_attrs}} + - ovs_br: + iface_attrs = {'type_name': 'bridge', 'source': {'bridge': br_name}, 'model': 'virtio', **${iface_bw_attrs}, 'virtualport': {'type': 'openvswitch'}} + diff --git a/libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py b/libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py new file mode 100644 index 00000000000..59977f1b7fe --- /dev/null +++ b/libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py @@ -0,0 +1,132 @@ +import logging + +from avocado.utils import process +from virttest import utils_misc +from virttest import utils_net +from virttest import utils_package +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.network_xml import NetworkXML +from virttest.staging import service +from virttest.utils_libvirt import libvirt_network +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Check the actual network throughput + per bandwidth settings in network/interface + + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + br_type = params.get('br_type', '') + rand_id = utils_misc.generate_random_string(3) + br_name = br_type + '_' + rand_id + net_name = 'net_' + rand_id + host_iface = params.get('host_iface') + host_iface = host_iface if host_iface else utils_net.get_net_if( + state='UP')[0] + iface_attrs = eval(params.get('iface_attrs', '{}')) + net_attrs = eval(params.get('net_attrs', '{}')) + inbound = eval(params.get('inbound')) + outbound = eval(params.get('outbound')) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + net_xml = NetworkXML.new_from_net_dumpxml('default') + bk_net_xml = net_xml.copy() + firewalld = service.Factory.create_service("firewalld") + + try: + if br_type == 'linux_br': + utils_net.create_linux_bridge_tmux(br_name, host_iface) + process.run(f'ip l show type bridge {br_name}', shell=True) + elif br_type == 'ovs_br': + utils_net.create_ovs_bridge(br_name) + + if 'name' in net_attrs: + libvirt_network.create_or_del_network(net_attrs) + else: + net_xml.setup_attrs(**net_attrs) + net_xml.sync() + LOG.debug(f'Network xml of default: {net_xml}') + + vmxml.del_device('interface', by_tag=True) + libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs) + LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + vm.start() + vm_sess = vm.wait_for_serial_login() + + iface = network_base.get_iface_xml_inst(vm_name, 'on vm') + mac = iface.mac_address + tap_device = libvirt.get_ifname_host(vm_name, mac) + LOG.debug(f'tap device on host with mac {mac} is: {tap_device}.') + source_br = iface.source['bridge'] + LOG.debug(f'source bridge of interface is: {source_br}.') + + if 'bandwidth' in iface_attrs: + tc_args = [tap_device, '1:1', iface_attrs['bandwidth']['inbound']] + filter_bw = iface_attrs['bandwidth']['outbound'] + else: + tc_args = [source_br, '1:2', net_attrs['bandwidth_inbound']] + filter_bw = net_attrs['bandwidth_outbound'] + + if not utils_net.check_class_rules(*tc_args): + test.fail('Class rule check failed. Please check log.') + LOG.debug('Class rule check: PASS') + + if not utils_net.check_filter_rules(tc_args[0], filter_bw): + test.fail('Filter rule check failed. Please check log.') + LOG.debug('Filter rule check: PASS') + + if not utils_package.package_install('netperf', session=vm_sess): + test.error('Failed to install netperf on VM.') + + vm_sess.close() + vm_sess = vm.wait_for_serial_login() + + host_ip = utils_net.get_linux_iface_info( + iface=source_br)['addr_info'][0]['local'] + vm_ip = network_base.get_vm_ip(vm_sess, mac) + LOG.debug(f'Host ip address with br {source_br}: {host_ip}\n' + f'Vm ip address: {vm_ip}') + + firewalld.stop() + vm_sess.cmd('systemctl stop firewalld') + + network_base.check_throughput( + vm_sess.cmd, lambda x: process.run(x).stdout_text, + vm_ip, inbound["average"], 'inbound' + ) + + network_base.check_throughput( + lambda x: process.run(x).stdout_text, + vm_sess.cmd, host_ip, outbound["average"], 'outbound' + ) + vm_sess.close() + vm.destroy() + ovs_list_cmd = 'ovs-vsctl list qos' + ovs_list_output = process.run(ovs_list_cmd).stdout_text + if ovs_list_output: + test.fail(f'There should be no output of command {ovs_list_cmd}.' + f'But we got {ovs_list_output}') + + finally: + bkxml.sync() + bk_net_xml.sync() + if 'name' in net_attrs: + libvirt_network.create_or_del_network(net_attrs, is_del=True) + if br_type == 'linux_br': + utils_net.delete_linux_bridge_tmux(br_name, host_iface) + if br_type == 'ovs_br': + utils_net.delete_ovs_bridge(br_name) + firewalld.start() diff --git a/provider/virtual_network/network_base.py b/provider/virtual_network/network_base.py index cd3bc43a9c0..4854ca43eab 100644 --- a/provider/virtual_network/network_base.py +++ b/provider/virtual_network/network_base.py @@ -1,4 +1,5 @@ import logging +import math import re import shutil @@ -336,3 +337,29 @@ def check_iface_attrs(iface, key, expect_val): if actual_val != expect_val: raise exceptions.TestFail(f'Updated {key} of iface should be ' f'{expect_val}, NOT {actual_val}') + + +def check_throughput(serv_runner, cli_runner, ip_addr, bw, th_type): + """ + Check actual thoughput of network using netperf + + :param serv_runner: runner of netserver + :param cli_runner: runner of netperf client + :param ip_addr: ip address + :param bw: bandwidth setting + :param th_type: inbound or outbound + """ + + serv_runner('netserver') + netperf_out = cli_runner(f'netperf -H {ip_addr}') + LOG.debug(netperf_out) + serv_runner('pkill netserver') + + actual_throu = float(netperf_out.strip().splitlines()[-1].split()[-1]) + expect_throu = int(bw) * 8 / 1024 + + msg = f'Expected {th_type}: {expect_throu}, actual {th_type}: {actual_throu}' + if not math.isclose(expect_throu, actual_throu, rel_tol=0.1): + raise exceptions.TestFail(f'Actual {th_type} is not close to expected ' + f'{th_type}:\n{msg}') + LOG.debug(msg) From 0825548c439549ffa0b2b217166881f3cdec3f93 Mon Sep 17 00:00:00 2001 From: nanli Date: Thu, 25 Jul 2024 18:40:27 +0800 Subject: [PATCH 0505/1055] vcpu_misc: add_default_value_for_mem_file mem_file param needs a default value to not influence other cases Signed-off-by: nanli --- libvirt/tests/src/cpu/vcpu_misc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/cpu/vcpu_misc.py b/libvirt/tests/src/cpu/vcpu_misc.py index 46eb7f1107b..616a493f551 100644 --- a/libvirt/tests/src/cpu/vcpu_misc.py +++ b/libvirt/tests/src/cpu/vcpu_misc.py @@ -243,7 +243,7 @@ def do_snapshot(vm_name, expected_str, params): bkxml = vmxml.copy() managed_save_file = "/var/lib/libvirt/qemu/save/%s.save" % vm_name maxphysaddr = params.get('maxphysaddr') - mem_file = params.get('mem_file') + mem_file = params.get('mem_file', "") try: if check_vendor_id: From 7c45b4a46a2bf1632e4a7dab26e2b8f7f1e96f97 Mon Sep 17 00:00:00 2001 From: Vera Wu Date: Fri, 26 Jul 2024 09:50:32 +0800 Subject: [PATCH 0506/1055] v2v:fix fstab-comma TC Signed-off-by: Vera Wu --- v2v/tests/cfg/function_test_esx.cfg | 3 --- 1 file changed, 3 deletions(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index ca3824e1380..d9853fa4ee2 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -396,10 +396,7 @@ device_map_path = /boot/grub2/device.map - fstab_comma: only esx_70 - checkpoint = fstab_comma main_vm = VM_NAME_ESX_FSTAB_SEPBY_COMMA - msg_content = 'virt-v2v: warning: mount: mount exited with status 32: mount:.*? already mounted .*?\(ignored\)' - expect_msg = yes - with_proxy: only esx_70 no libvirt From a2fb5fc2e7b9d381faab3d6e85a0acf2e8600982 Mon Sep 17 00:00:00 2001 From: nanli Date: Thu, 11 Jul 2024 20:31:04 +0800 Subject: [PATCH 0507/1055] add refining steps for dimm with access and discrad scenario xxx-299048:Dimm memory device with access and discard settings Signed-off-by: nanli --- .../dimm_memory_with_access_and_discard.cfg | 42 +++----- .../dimm_memory_with_access_and_discard.py | 102 ++++++++++-------- 2 files changed, 73 insertions(+), 71 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_access_and_discard.cfg b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_access_and_discard.cfg index fadfd4b2c34..9ba22d069a6 100644 --- a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_access_and_discard.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_with_access_and_discard.cfg @@ -1,21 +1,23 @@ - memory.devices.dimm.access_and_discard: type = dimm_memory_with_access_and_discard + no s390-virtio start_vm = yes mem_model = "dimm" dimm_mem_num = 6 share_0 = 'false' discard_0 = 'False' check_path = "ls -l /var/lib/libvirt/qemu/ram/%s" - target_size = 131072 - requested_size = 131072 - block_size = 2048 - no s390-virtio - aarch64: - target_size = 1048576 - requested_size = 524288 - block_size = 524288 - dimm_basic = {'mem_model': '${mem_model}', 'target': {'requested_unit': 'KiB', 'size': ${target_size}, 'size_unit': 'KiB', 'requested_size': ${requested_size}, 'block_unit': 'KiB', 'block_size': ${block_size}}} + target_size = 524288 + requested_size = 1048576 + dimm_basic = {'mem_model': '${mem_model}', 'target': {'requested_unit': 'KiB', 'size': ${target_size}, 'size_unit': 'KiB', 'requested_size': ${requested_size}, 'block_unit': 'KiB', 'block_size': %s}} kernel_params_add = "memhp_default_state=online_movable" + max_mem = 10485760 + aarch64: + max_mem = 20971520 + base_attrs = "'vcpu': 6, 'placement': 'static', 'memory_unit':'KiB','memory':3145728,'current_mem':3145728,'current_mem_unit':'KiB'" + numa_attrs = "'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '1048576', 'unit': 'KiB'}, {'id': '1', 'cpus': '2-3', 'memory': '1048576', 'unit': 'KiB', 'memAccess':'shared','discard':'yes'},{'id':'2','cpus': '4-5','memory':'1048576','unit':'KiB', 'memAccess':'private','discard':'no'}]}" + max_attrs = "'max_mem_rt': ${max_mem}, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'" + vm_attrs = {${base_attrs}, ${numa_attrs}, ${max_attrs}} variants memory_backing: - file: source_type = 'file' @@ -52,20 +54,8 @@ expected_share = ['${share_0}', 'true', 'true', 'false', 'false', 'true'] check_discard = '{"execute":"qom-get", "arguments":{"path":"/objects/%s", "property":"discard-data"}}' expected_discard = ['${discard_0}', 'True', 'True', 'False', 'False', 'True'] - variants: - - with_numa: - no s390-virtio - mem_value = 3145728 - current_mem = 3145728 - max_mem = 10485760 - numa_mem = 1048576 - aarch64: - max_mem = 20971520 - mem_access_1 = "shared" - discard_1 = "yes" - mem_access_2 = "private" - discard_2 = "no" - base_attrs = "'vcpu': 6, 'placement': 'static', 'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'" - numa_attrs = "'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_mem}', 'unit': 'KiB', 'memAccess':'${mem_access_1}','discard':'${discard_1}'},{'id':'2','cpus': '4-5','memory':'${numa_mem}','unit':'KiB', 'memAccess':'${mem_access_2}','discard':'${discard_2}'}]}" - max_attrs = "'max_mem_rt': ${max_mem}, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'" - vm_attrs = {${base_attrs}, ${numa_attrs}, ${max_attrs}} + variants operation: + - cold_plug: + attach_option = "--config" + - hot_plug: + attach_option = " " diff --git a/libvirt/tests/src/memory/memory_devices/dimm_memory_with_access_and_discard.py b/libvirt/tests/src/memory/memory_devices/dimm_memory_with_access_and_discard.py index ed97fb81a99..1b0fc451745 100644 --- a/libvirt/tests/src/memory/memory_devices/dimm_memory_with_access_and_discard.py +++ b/libvirt/tests/src/memory/memory_devices/dimm_memory_with_access_and_discard.py @@ -10,6 +10,7 @@ import re import json +from avocado.utils import memory from avocado.utils import process from virttest import utils_test @@ -18,6 +19,8 @@ from virttest.utils_libvirtd import Libvirtd from virttest.utils_libvirt import libvirt_vmxml +virsh_dargs = {"ignore_status": False, "debug": True} + def get_vm_attrs(test, params): """ @@ -44,20 +47,21 @@ def get_vm_attrs(test, params): return vm_attrs -def create_dimm_mem_list(test, params): +def create_dimm_objects(test, params): """ - Get 6 basic different dimm memory devices. + Get 6 basic different dimm memory devices object. :param test: test object. :param params: dictionary with the test parameters. - :return mem_list: dimm memory attr dict list. + :return mem_list: dimm memory device object list. """ + default_hugepage_size = memory.get_huge_page_size() mem_list = [] for item in [(None, None, 0), ('shared', 'yes', 0), (None, None, 1), ('private', 'no', 1), (None, None, 2), ('shared', 'yes', 2)]: - single_mem = eval(params.get("dimm_basic")) + single_mem = eval(params.get("dimm_basic") % default_hugepage_size) target = single_mem['target'] target.update({'node': item[2]}) @@ -65,12 +69,44 @@ def create_dimm_mem_list(test, params): single_mem.update({'mem_access': item[0]}) if item[1] is not None: single_mem.update({'mem_discard': item[1]}) - mem_list.append(single_mem) + test.log.debug("Get one dimm dict is:'%s'\n", single_mem) + + dimm_obj = libvirt_vmxml.create_vm_device_by_type( + 'memory', single_mem) + mem_list.append(dimm_obj) - test.log.debug("Get all dimm list:'%s'", mem_list) return mem_list +def plug_dimm(test, params, vm, operation): + """ + Hot plug or Cold plug dimm + + :param test: test object. + :param params: dictionary with the test parameters. + :param vm: vm object. + :param operation: flag for hot plugging or cold plugging. + """ + vm_name = params.get("main_vm") + attach_option = params.get("attach_option") + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vmxml.remove_all_device_by_type("memory") + + all_dimms = create_dimm_objects(test, params) + if operation == "cold_plug": + pass + elif operation == "hot_plug": + vm.start() + vm.wait_for_login().close() + Libvirtd().restart() + + for mem in all_dimms: + virsh.attach_device(vm_name, mem.xml, + flagstr=attach_option, + **virsh_dargs) + + def check_access_and_discard(test, params, vm, expected_share, expected_discard): """ @@ -87,6 +123,8 @@ def check_access_and_discard(test, params, vm, discard_error_msg = params.get("discard_error_msg") mem_name_list = [] + if not vm.is_alive(): + vm.start() # Check access share setting ret = virsh.qemu_monitor_command(vm.name, "info memdev", "--hmp", debug=True).stdout_text.replace("\r\n", "") @@ -140,66 +178,39 @@ def run_test(): 3.Define vm without dimm memory device and restart service, and hotplug dimm device. """ - test.log.info("TEST_STEP1: Define vm with dimm memory") + test.log.info("TEST_STEP1: Define vm with numa") vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) - vmxml.remove_all_device_by_type("memory") - vm_attrs = get_vm_attrs(test, params) vmxml.setup_attrs(**vm_attrs) - - all_dimms = create_dimm_mem_list(test, params) - dimm_objs = [] - for mem in all_dimms: - dimm = libvirt_vmxml.create_vm_device_by_type('memory', mem) - vmxml.devices = vmxml.devices.append(dimm) - dimm_objs.append(dimm) vmxml.sync() - test.log.info("TEST_STEP2: Start guest") - vm.start() - vm.wait_for_login().close() + test.log.info("TEST_STEP2-5: Plug dimm memory devices") + plug_dimm(test, params, vm, operation) - test.log.info("TEST_STEP3,4: Check dimm memory access and discard") + test.log.info("TEST_STEP6,7: Check dimm memory access and discard") check_access_and_discard(test, params, vm, expected_share, expected_discard) - test.log.info("TEST_STEP5: Hot unplug all dimm memory device") - for dimm in dimm_objs: - virsh.detach_device(vm_name, dimm.xml, - debug=True, ignore_status=False) + test.log.info("TEST_STEP8:Hot unplug all dimm memory device") + for dimm in create_dimm_objects(test, params): + virsh.detach_device(vm_name, dimm.xml, **virsh_dargs) - test.log.info("TEST_STEP6: Destroy vm") + test.log.info("TEST_STEP9: Destroy vm") vm.destroy() - test.log.info("TEST_STEP7: Check the host path for memory file backing") + test.log.info("TEST_STEP10: Check the host path for memory file backing") res = process.run(check_path % vm_name, shell=True, ignore_status=True).stderr_text if not re.search(path_error, res): test.fail("Expected '%s', but got '%s'" % (path_error, res)) - test.log.info("TEST_STEP8: Define guest without any dimm memory") - original_xml.setup_attrs(**vm_attrs) - original_xml.sync() - vm.start() - - test.log.info("TEST_STEP8: Restart service") - Libvirtd().restart() - - test.log.info("TEST_STEP9: Hot plug all dimm memory device") - for dimm in dimm_objs: - virsh.attach_device(vm_name, dimm.xml, - debug=True, ignore_status=False) - - test.log.info("TEST_STEP10: Check dimm discard and access again.") - check_access_and_discard(test, params, vm, - expected_share, expected_discard) - def teardown_test(): """ Clean data. """ test.log.info("TEST_TEARDOWN: Clean up env.") - utils_test.update_boot_option(vm, args_removed=kernel_params_add, - need_reboot=True) + if not vm.is_alive(): + vm.start() + utils_test.update_boot_option(vm, args_removed=kernel_params_add) bkxml.sync() vm_name = params.get("main_vm") @@ -207,6 +218,7 @@ def teardown_test(): bkxml = original_xml.copy() vm = env.get_vm(vm_name) + operation = params.get("operation") kernel_params_add = params.get("kernel_params_add") expected_share = eval(params.get("expected_share")) expected_discard = eval(params.get("expected_discard")) From 0b12c7f7c30e99dda8b2ab7c5cbbdf0534037081 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 26 Jun 2024 05:52:43 -0400 Subject: [PATCH 0508/1055] control_cgroup: move controller check The controller check was executed before the controller was updated. The VM start will do that. So move the check after the VM is started. This enables the test run under valid conditions when previously it was cancelled. Signed-off-by: Sebastian Mitterle --- .../guest_resource_control/control_cgroup.py | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/libvirt/tests/src/guest_resource_control/control_cgroup.py b/libvirt/tests/src/guest_resource_control/control_cgroup.py index 94964830cbf..88951c7ba33 100644 --- a/libvirt/tests/src/guest_resource_control/control_cgroup.py +++ b/libvirt/tests/src/guest_resource_control/control_cgroup.py @@ -20,6 +20,25 @@ logging = log.getLogger('avocado.' + __name__) +def cancel_if_cpu_controller_not_mounted(test): + """ + Following is to deal the situation when realtime task existing. + In this situation, cpu controller cannot be enabled. + FYI: https://bugzilla.redhat.com/show_bug.cgi?id=1513930#c21 + + :param test: the test instance for failure reporting + """ + with open('/proc/mounts', 'r') as mnts: + cg_mount_point = re.findall(r"\s(\S*cgroup)\s", mnts.read())[0] + cg_subtree_file = os.path.join(cg_mount_point, + "cgroup.subtree_control") + with open(cg_subtree_file, 'r') as cg_subtree: + if "cpu" not in cg_subtree.read().replace("cpuset", ""): + test.cancel("CPU controller not mounted. This is a " + "limitation of cgroup v2 when realtime task " + "existing on host.") + + def run(test, params, env): """ Cgroup related cases in function 'guest resource control' @@ -165,21 +184,9 @@ def do_extra_operations(operations="daemon-reload"): vmxml_backup = vmxml.copy() cgtest = CgroupTest(None) - if cgtest.is_cgroup_v2_enabled(): + is_cgroup_v2 = cgtest.is_cgroup_v2_enabled() + if is_cgroup_v2: logging.info("The case executed on cgroup v2 environment.") - # Following is to deal the situation when realtime task existing. - # In this situation, cpu controller cannot be enabled. - # FYI: https://bugzilla.redhat.com/show_bug.cgi?id=1513930#c21 - if "schedinfo" in virsh_cmd: - with open('/proc/mounts', 'r') as mnts: - cg_mount_point = re.findall(r"\s(\S*cgroup)\s", mnts.read())[0] - cg_subtree_file = os.path.join(cg_mount_point, - "cgroup.subtree_control") - with open(cg_subtree_file, 'r') as cg_subtree: - if "cpu" not in cg_subtree.read().replace("cpuset", ""): - test.cancel("CPU controller not mounted. This is a " - "limitation of cgroup v2 when realtime task " - "existing on host.") else: logging.info("The case executed on cgroup v1 environment.") @@ -212,6 +219,8 @@ def do_extra_operations(operations="daemon-reload"): try: if start_vm == "yes" and not vm.is_alive(): vm.start() + if "schedinfo" in virsh_cmd and is_cgroup_v2: + cancel_if_cpu_controller_not_mounted(test) vm.wait_for_login().close() virsh_cmd_line = prepare_virsh_cmd(vm_name, virsh_cmd, virsh_cmd_param, @@ -230,6 +239,8 @@ def do_extra_operations(operations="daemon-reload"): if "--config" in virsh_cmd_options: try: vm.start() + if "schedinfo" in virsh_cmd and is_cgroup_v2: + cancel_if_cpu_controller_not_mounted(test) vm.wait_for_login().close() if "iothread" in virsh_cmd_line: add_iothread(vm) From 08a8446e65beeb560e67c29170298e1a787d442d Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 29 Jul 2024 08:39:12 +0200 Subject: [PATCH 0509/1055] requirements-travis: fix dependencies The systems can't be set up anymore for python versions since 3.8. Update depdendencies. There will be a later pylint version producing new errors. Ignore these as we didn't check them before. Update pip to latest to avoid other dependency issues. Allow for pylint to exit with code 32 if there are no files to check. Otherwise the build will fail. For that, the exit-on-error must be temporarily switched off (set +e) in the run commands. Signed-off-by: Sebastian Mitterle --- .github/workflows/ci.yml | 11 +++++++++-- requirements-travis.txt | 12 ++++++++---- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 523e7a4be44..7fc25a3f05e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,12 +29,19 @@ jobs: uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} + - name: Update pip + run: pip install --upgrade pip - name: Install dependencies run: | pip install sphinx${SPHINX_VERSION:+==$SPHINX_VERSION} pip install -r requirements-travis.txt - name: Run inspekt - run: inspekt checkall --disable-style E501,E265,W601,W605,E402,E722,E741 --no-license-check + run: inspekt checkall --disable-style E501,E265,W601,W605,E402,E722,E741 --disable-lint W,R,C,E1002,E1101,E1103,E1120,F0401,I0011,E0601,E0602,E0606 --no-license-check - run: echo "This job's status is ${{ job.status }}." - name: Run spellchecker - run: pylint --errors-only --disable=all --enable=spelling --spelling-dict=en_US --spelling-private-dict-file=spell.ignore * + run: | + set +e + pylint --errors-only --disable=all --enable=spelling --spelling-dict=en_US --spelling-private-dict-file=spell.ignore * + exitcode=$? + set -e + test $exitcode == 32 -o $exitcode == 0 diff --git a/requirements-travis.txt b/requirements-travis.txt index ad5bff09681..1f83bf6df41 100644 --- a/requirements-travis.txt +++ b/requirements-travis.txt @@ -1,10 +1,14 @@ coverage==5.1 nose==1.3.0 nosexcover==1.0.8 -tox==1.5.0 -virtualenv==1.9.1 +tox==1.5.0; python_version < '3.8' +tox==4.16.0; python_version > '3.7' +virtualenv==1.9.1; python_version < '3.8' +virtualenv==20.26.3; python_version > '3.7' simplejson==3.8.1 -inspektor==0.5.2 -pylint==2.11.1 +inspektor==0.5.2; python_version < '3.8' +inspektor==0.5.3; python_version > '3.7' +pylint==2.11.1; python_version < '3.8' +pylint==3.2.6; python_version > '3.7' pyenchant importlib-metadata==4.13.0; python_version == '3.7' From c956a3b54adab76c07b1ec30443f885955fc692e Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Mon, 29 Jul 2024 04:33:22 -0400 Subject: [PATCH 0510/1055] Reuse interface's mac address to save ip resource Signed-off-by: Haijiao Zhao --- .../connectivity/connectivity_check_bridge_interface.py | 9 ++++++--- .../connectivity/connectivity_check_direct_interface.py | 9 ++++++--- .../connectivity_check_ethernet_interface.py | 4 ++-- .../connectivity_check_tcp_tunnel_interface.py | 4 ++++ .../connectivity_check_udp_tunnel_interface.py | 5 ++++- .../connectivity/connectivity_check_user_interface.py | 3 ++- .../elements_and_attributes/attribute_port_isolated.py | 7 ++++++- .../elements_and_attributes/element_coalesce.py | 4 +++- .../virtual_network/link_state/link_state_model_type.py | 5 ++++- .../update_device/update_device_coalesce.py | 4 +++- .../update_device/update_iface_link_state.py | 4 +++- .../virtual_network/update_device/update_iface_source.py | 4 +++- .../update_device/update_iface_trustGuestRxFilters.py | 4 +++- .../update_device/update_port_isolated.py | 4 ++++ 14 files changed, 53 insertions(+), 17 deletions(-) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py index 06f1100b185..b9272643558 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py @@ -77,10 +77,14 @@ def run(test, params, env): if vm_attrs: [vmxml_i.setup_attrs(**vm_attrs) for vmxml_i in [vmxml, ep_vmxml]] + mac, ep_mac = list(map(vm_xml.VMXML.get_first_mac_by_name, vms)) + [vmxml_i.del_device('interface', by_tag=True) for vmxml_i in [vmxml, ep_vmxml]] - [libvirt_vmxml.modify_vm_device(vmxml_i, 'interface', iface_attrs) - for vmxml_i in [vmxml, ep_vmxml]] + libvirt_vmxml.modify_vm_device( + vmxml, 'interface', {**iface_attrs, **{'mac_address': mac}}) + libvirt_vmxml.modify_vm_device( + ep_vmxml, 'interface', {**iface_attrs, **{'mac_address': ep_mac}}) [LOG.debug(f'VMXML of {vm_x}:\n{virsh.dumpxml(vm_x).stdout_text}') for vm_x in vms] @@ -88,7 +92,6 @@ def run(test, params, env): [vm_i.start() for vm_i in [vm, ep_vm]] session, ep_session = (vm_inst.wait_for_serial_login() for vm_inst in [vm, ep_vm]) - mac, ep_mac = list(map(vm_xml.VMXML.get_first_mac_by_name, vms)) ips_v4 = network_base.get_test_ips(session, mac, ep_session, ep_mac, net_name=None, diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_direct_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_direct_interface.py index a68522669c4..02cfb5d6668 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_direct_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_direct_interface.py @@ -31,10 +31,14 @@ def run(test, params, env): try: vmxml, ep_vmxml = list( map(vm_xml.VMXML.new_from_inactive_dumpxml, vms)) + mac, ep_mac = list(map(vm_xml.VMXML.get_first_mac_by_name, vms)) [vmxml_i.del_device('interface', by_tag=True) for vmxml_i in [vmxml, ep_vmxml]] - [libvirt_vmxml.modify_vm_device(vmxml_i, 'interface', iface_attrs) - for vmxml_i in [vmxml, ep_vmxml]] + + libvirt_vmxml.modify_vm_device( + vmxml, 'interface', {**iface_attrs, **{'mac_address': mac}}) + libvirt_vmxml.modify_vm_device( + ep_vmxml, 'interface', {**iface_attrs, **{'mac_address': ep_mac}}) [LOG.debug(f'VMXML of {vm_x}:\n{virsh.dumpxml(vm_x).stdout_text}') for vm_x in vms] @@ -42,7 +46,6 @@ def run(test, params, env): [vm_i.start() for vm_i in [vm, ep_vm]] session, ep_session = (vm_inst.wait_for_serial_login() for vm_inst in [vm, ep_vm]) - mac, ep_mac = list(map(vm_xml.VMXML.get_first_mac_by_name, vms)) ips_v4 = network_base.get_test_ips(session, mac, ep_session, ep_mac, net_name=None, diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py index c81f44a9ed5..25c5098e65d 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py @@ -64,6 +64,7 @@ def run(test, params, env): bkxml = vmxml.copy() try: + mac_addr = vm_xml.VMXML.get_first_mac_by_name(vm_name, virsh_ins) if tap_type: if tap_type == 'tap': @@ -72,11 +73,10 @@ def run(test, params, env): elif tap_type == 'macvtap': mac_addr = network_base.create_macvtap(tap_name, host_iface, test_user) - iface_attrs['mac_address'] = mac_addr - if tap_mtu: network_base.set_tap_mtu(tap_name, tap_mtu) + iface_attrs['mac_address'] = mac_addr vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=virsh_ins) vmxml.del_device('interface', by_tag=True) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_tcp_tunnel_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_tcp_tunnel_interface.py index 7d3ebc9e2b3..8f2106b65f5 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_tcp_tunnel_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_tcp_tunnel_interface.py @@ -32,9 +32,13 @@ def run(test, params, env): try: vmxml, cli_vmxml = list( map(vm_xml.VMXML.new_from_inactive_dumpxml, vms)) + mac, cli_mac = list(map(vm_xml.VMXML.get_first_mac_by_name, vms)) [vmxml_i.del_device('interface', by_tag=True) for vmxml_i in [vmxml, cli_vmxml]] + iface_attrs.update({'mac_address': mac}) + cli_iface_attrs.update({'mac_address': cli_mac}) + [libvirt_vmxml.modify_vm_device(vmxml_i, 'interface', attrs) for vmxml_i, attrs in [(vmxml, iface_attrs), (cli_vmxml, cli_iface_attrs)]] diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_udp_tunnel_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_udp_tunnel_interface.py index 5ea0759fc3d..e8bf6a20f35 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_udp_tunnel_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_udp_tunnel_interface.py @@ -31,9 +31,13 @@ def run(test, params, env): try: vmxml, cli_vmxml = list( map(vm_xml.VMXML.new_from_inactive_dumpxml, vms)) + mac, cli_mac = list(map(vm_xml.VMXML.get_first_mac_by_name, vms)) [vmxml_i.del_device('interface', by_tag=True) for vmxml_i in [vmxml, cli_vmxml]] + iface_attrs.update({'mac_address': mac}) + cli_iface_attrs.update({'mac_address': cli_mac}) + [libvirt_vmxml.modify_vm_device(vmxml_i, 'interface', attrs) for vmxml_i, attrs in [(vmxml, iface_attrs), (cli_vmxml, cli_iface_attrs)]] @@ -44,7 +48,6 @@ def run(test, params, env): [vm_i.start() for vm_i in [vm, cli_vm]] session, cli_session = (vm_inst.wait_for_serial_login() for vm_inst in [vm, cli_vm]) - mac, cli_mac = list(map(vm_xml.VMXML.get_first_mac_by_name, vms)) iface_info = utils_net.get_linux_iface_info(mac=mac, session=session) cli_iface_info = utils_net.get_linux_iface_info( diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py index aba514d1bf0..605c7849412 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py @@ -91,10 +91,11 @@ def run(test, params, env): bkxml = vmxml.copy() try: + mac = vm_xml.VMXML.get_first_mac_by_name(vm_name, virsh_ins) vmxml.del_device('interface', by_tag=True) vmxml.sync(virsh_instance=virsh_ins) iface = libvirt_vmxml.create_vm_device_by_type( - 'interface', iface_attrs) + 'interface', {**iface_attrs, **{'mac_address': mac}}) vmxml.add_device(iface) define_result = virsh.define(vmxml.xml, debug=True, uri=virsh_uri) libvirt.check_exit_status(define_result, expect_error) diff --git a/libvirt/tests/src/virtual_network/elements_and_attributes/attribute_port_isolated.py b/libvirt/tests/src/virtual_network/elements_and_attributes/attribute_port_isolated.py index 3efab3c7dd1..9be3f16d5cc 100644 --- a/libvirt/tests/src/virtual_network/elements_and_attributes/attribute_port_isolated.py +++ b/libvirt/tests/src/virtual_network/elements_and_attributes/attribute_port_isolated.py @@ -55,7 +55,7 @@ def run(test, params, env): net_attrs = {**net_attrs, **port_attrs} if not (set_iface and cli_iface_attrs): - cli_iface_attrs = iface_attrs + cli_iface_attrs = iface_attrs.copy() if create_linux_br: LOG.info(f'Create linux bridge: {linux_br}') @@ -65,10 +65,15 @@ def run(test, params, env): LOG.debug(f'Network xml:\n' f'{virsh.net_dumpxml(net_attrs["name"]).stdout_text}') + mac, cli_mac = list(map(vm_xml.VMXML.get_first_mac_by_name, vms)) + vmxml, cli_vmxml = list(map(vm_xml.VMXML.new_from_inactive_dumpxml, vms)) [vmxml_i.del_device('interface', by_tag=True) for vmxml_i in [vmxml, cli_vmxml]] + iface_attrs.update({'mac_address': mac}) + cli_iface_attrs.update({'mac_address': cli_mac}) + [libvirt_vmxml.modify_vm_device(vmxml_i, 'interface', attrs) for vmxml_i, attrs in [(vmxml, iface_attrs), (cli_vmxml, cli_iface_attrs)]] diff --git a/libvirt/tests/src/virtual_network/elements_and_attributes/element_coalesce.py b/libvirt/tests/src/virtual_network/elements_and_attributes/element_coalesce.py index d32c6d0a93a..99e8e33d41e 100644 --- a/libvirt/tests/src/virtual_network/elements_and_attributes/element_coalesce.py +++ b/libvirt/tests/src/virtual_network/elements_and_attributes/element_coalesce.py @@ -45,8 +45,10 @@ def run(test, params, env): elif br_type == 'ovs_br': utils_net.create_ovs_bridge(br_name) + mac = vm_xml.VMXML.get_first_mac_by_name(vm_name) vmxml.del_device('interface', by_tag=True) - iface = libvirt_vmxml.create_vm_device_by_type('interface', iface_attrs) + iface = libvirt_vmxml.create_vm_device_by_type( + 'interface', {**iface_attrs, **{'mac_address': mac}}) vmxml.add_device(iface) LOG.debug(f'Interface to add to vm:\n{iface}') diff --git a/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py b/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py index 4dde3ee9aa5..ea441d345f0 100644 --- a/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py +++ b/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py @@ -61,8 +61,11 @@ def run(test, params, env): utils_net.create_linux_bridge_tmux(bridge_name, host_iface) network_base.create_tap(tap_name, bridge_name, "root") + mac = vm_xml.VMXML.get_first_mac_by_name(vm_name, virsh_ins) vmxml.del_device('interface', by_tag=True) - libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs, virsh_instance=virsh_ins) + libvirt_vmxml.modify_vm_device( + vmxml, 'interface', {**iface_attrs, **{'mac_address': mac}}, + virsh_instance=virsh_ins) test.log.debug(f'VMXML of {vm_name}:\n{virsh_ins.dumpxml(vm_name).stdout_text}') vm.start() session = vm.wait_for_serial_login() diff --git a/libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py b/libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py index 15d0a926acf..ebfb66cc853 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py +++ b/libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py @@ -65,8 +65,10 @@ def run(test, params, env): utils_net.create_ovs_bridge(br_name) LOG.info('Setup interface on vm.') + mac = vm_xml.VMXML.get_first_mac_by_name(vm_name) vmxml.del_device('interface', by_tag=True) - libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs) + libvirt_vmxml.modify_vm_device( + vmxml, 'interface', {**iface_attrs, **{'mac_address': mac}}) LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') vm.start() diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_link_state.py b/libvirt/tests/src/virtual_network/update_device/update_iface_link_state.py index dfc30f33864..4d0a233d44b 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_link_state.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_link_state.py @@ -47,8 +47,10 @@ def run(test, params, env): utils_net.create_linux_bridge_tmux(bridge_name, host_iface) network_base.create_tap(tap_name, bridge_name, "root") + mac = vm_xml.VMXML.get_first_mac_by_name(vm_name) vmxml.del_device('interface', by_tag=True) - libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs) + libvirt_vmxml.modify_vm_device( + vmxml, 'interface', {**iface_attrs, **{'mac_address': mac}}) test.log.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') vm.start() session = vm.wait_for_serial_login() diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_source.py b/libvirt/tests/src/virtual_network/update_device/update_iface_source.py index a3e21bd93da..40ac77ac088 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_source.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_source.py @@ -37,8 +37,10 @@ def run(test, params, env): bkxml = vmxml.copy() try: + mac = vm_xml.VMXML.get_first_mac_by_name(vm_name) vmxml.del_device('interface', by_tag=True) - libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs) + libvirt_vmxml.modify_vm_device( + vmxml, 'interface', {**iface_attrs, **{'mac_address': mac}}) LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') if net_attrs: diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py b/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py index 8bb32c61403..58360ebf88b 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py @@ -32,8 +32,10 @@ def run(test, params, env): bkxml = vmxml.copy() try: + mac = vm_xml.VMXML.get_first_mac_by_name(vm_name) vmxml.del_device('interface', by_tag=True) - libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs) + libvirt_vmxml.modify_vm_device( + vmxml, 'interface', {**iface_attrs, **{'mac_address': mac}}) LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') vm.start() diff --git a/libvirt/tests/src/virtual_network/update_device/update_port_isolated.py b/libvirt/tests/src/virtual_network/update_device/update_port_isolated.py index 90d3f4c9313..645ff880109 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_port_isolated.py +++ b/libvirt/tests/src/virtual_network/update_device/update_port_isolated.py @@ -29,6 +29,10 @@ def setup_vms_ifaces(vmxml, cli_vmxml): for vmxml_i in [vmxml, cli_vmxml]: vmxml_i.del_device('interface', by_tag=True) + mac, cli_mac = list(map(vm_xml.VMXML.get_first_mac_by_name, vms)) + iface_attrs.update({'mac_address': mac}) + cli_iface_attrs.update({'mac_address': cli_mac}) + for vmxml_i, attrs in [(vmxml, iface_attrs), (cli_vmxml, cli_iface_attrs)]: libvirt_vmxml.modify_vm_device(vmxml_i, 'interface', attrs) From f8cddfd9406938fdb7e7abef864aac1a43d17bbc Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Mon, 29 Jul 2024 23:05:42 -0400 Subject: [PATCH 0511/1055] Fix ccw test cases failures in s390x attach_disk,attach_controller,attach_rng is supported on s390x, so it is positive cases Signed-off-by: chunfuwen --- libvirt/tests/cfg/virtual_disks/virtual_disks_ccw_addr.cfg | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_ccw_addr.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_ccw_addr.cfg index d35d0cfef2d..d9205d7a584 100755 --- a/libvirt/tests/cfg/virtual_disks/virtual_disks_ccw_addr.cfg +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_ccw_addr.cfg @@ -11,9 +11,10 @@ status_error = "yes" define_error = "yes" error_msg = "cannot use CCW address type for device" + only attach_no_exist_disk - positive_test: status_error = "no" - only attach_same_pci_slot + no attach_no_exist_disk variants: - attach_no_exist_disk: only coldplug @@ -37,7 +38,7 @@ addr_attrs = "{'type': 'ccw', 'cssid': '0x0', 'ssid': '0x0', 'devno': '0x0000'}" - attach_rng: backend_device = "rng" - backend_dev = "/dev/hwrng" + backend_dev = "/dev/random" rng_model = "virtio" addr_attrs = "{'type': 'ccw', 'cssid': '0x0', 'ssid': '0x0', 'devno': '0x0000'}" - attach_same_pci_slot: From 5ccce75914d8730600f556dd1e46ef5a8f43eb33 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Tue, 30 Jul 2024 02:17:57 -0400 Subject: [PATCH 0512/1055] Virtual_disk: add new negative case of discard_no_unref VIRT-301835 - [virtual_disk][discard_no_unref][negative] Update device for guest with discard_no_unref attribute Signed-off-by: Meina Li --- .../virtual_disks_discard_no_unref.cfg | 11 +++++--- .../virtual_disks_discard_no_unref.py | 25 +++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_discard_no_unref.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_discard_no_unref.cfg index 060210a8a68..af789687448 100644 --- a/libvirt/tests/cfg/virtual_disks/virtual_disks_discard_no_unref.cfg +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_discard_no_unref.cfg @@ -26,6 +26,10 @@ - start_vm: check_qemu_pattern = '"discard":"${discard}","driver":"qcow2","discard-no-unref":${qemu_output}' expect_xml_line = 'discard_no_unref="${discard_no_unref}"' + - hotplug_disk: + only enable..with_discard_unmap.file_disk + hotplug = "yes" + check_libvirtd_log = '"driver":"qcow2","discard-no-unref":true' - define_invalid: only enable..with_discard_unmap.file_disk status_error = "yes" @@ -35,8 +39,9 @@ expect_error = "unsupported configuration: 'discard_no_unref' only works with qcow2 disk format" - readonly_mode: expect_error = "unsupported configuration: 'discard_no_unref' is not compatible with read-only disk" - - hotplug_disk: + - update_negative: only enable..with_discard_unmap.file_disk - hotplug = "yes" - check_libvirtd_log = '"driver":"qcow2","discard-no-unref":true' + func_supported_since_libvirt_ver = (10, 5, 0) + status_error = "yes" + expect_error = "cannot modify field 'discard_no_unref' of the disk" disk_dict = {'type_name': '${disk_type}', 'driver': {'name': 'qemu', 'type': 'qcow2', 'discard': '${discard}', 'discard_no_unref': '${discard_no_unref}'}, 'target': {'dev': '${target_dev}'}} diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_discard_no_unref.py b/libvirt/tests/src/virtual_disks/virtual_disks_discard_no_unref.py index 334c23e64f9..d72b26cd5ee 100644 --- a/libvirt/tests/src/virtual_disks/virtual_disks_discard_no_unref.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_discard_no_unref.py @@ -126,6 +126,31 @@ def run_test_hotplug_disk(vm, params, test): test.fail("The target disk % can't be detached in guest." % target_dev) +def run_test_update_negative(vm, params, test): + """ + Scenario: update device for guest with discard_no_unref attribute + + :param vm: vm instance + :param params: dict, test parameters + :param test: test object + """ + vm_name = params.get("main_vm") + expect_error = params.get("expect_error") + + test.log.debug("STEP1: start a guest.") + if not vm.is_alive(): + vm.start() + test.log.debug("STEP2: prepare the disk xml.") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + disk = vmxml.get_devices(device_type="disk")[0] + disk_driver = disk['driver'] + disk_driver.update({'discard_no_unref': 'on'}) + disk['driver'] = disk_driver + test.log.debug("STEP3: update the disk device.") + result = virsh.update_device(vm_name, disk.xml, debug=True) + libvirt.check_result(result, expect_error) + + def teardown_test(vm, vmxml, params, test): """ :param vm: vm instance From cdc147c59e94901c7f6db9a2af16f847e566de18 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Tue, 30 Jul 2024 04:51:01 -0400 Subject: [PATCH 0513/1055] Fix iothread failures in s390x Use wild matching characters to match expected result, instead of hard-coded string for specific arches Signed-off-by: chunfuwen --- .../cfg/virtual_disks/virtual_disks_iothreads_queue.cfg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg index efbbbab0f5f..8d0518e1cd1 100755 --- a/libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg @@ -11,11 +11,11 @@ queue_num = "3" driver = {'name': 'qemu', 'queues': '${queue_num}'} driver_iothreads = {'iothread': [{'queue': [{'id': '0'}, {'id': '1'}], 'id': '1'}, {'queue': [{'id': '2'}], 'id': '2'}]} - check_qemu_pattern = '"driver":"virtio-blk-pci","num-queues":3,"iothread-vq-mapping":\[{"iothread":"iothread1","vqs":\[0,1\]},{"iothread":"iothread2","vqs":\[2\]}\]' + check_qemu_pattern = '"driver":"virtio-blk-.*","num-queues":3,"iothread-vq-mapping":\[{"iothread":"iothread1","vqs":\[0,1\]},{"iothread":"iothread2","vqs":\[2\]}\]' - round_robin: driver = {'name': 'qemu', 'type': 'qcow2'} driver_iothreads = {'iothread': [{'id': '1'}, {'id': '2'}, {'id': '3'}]} - check_qemu_pattern = '"driver":"virtio-blk-pci","iothread-vq-mapping":\[{"iothread":"iothread1"},{"iothread":"iothread2"},{"iothread":"iothread3"}\]' + check_qemu_pattern = '"driver":"virtio-blk-.*","iothread-vq-mapping":\[{"iothread":"iothread1"},{"iothread":"iothread2"},{"iothread":"iothread3"}\]' variants scenario: - define_start: - define_invalid: @@ -87,7 +87,7 @@ new_target = {'dev': '${new_target_dev}', 'bus': 'virtio'} new_source = {'attrs': {'file': '%s'}} new_disk_dict = {'target': ${new_target}, 'device': 'disk', 'driver': {'name': 'qemu', 'type': 'qcow2'}, 'driver_iothreads': ${new_driver_iothreads}, 'source': ${new_source}} - check_libvirtd_log = '"driver":"virtio-blk-pci","iothread-vq-mapping":\[{"iothread":"iothread1"},{"iothread":"iothread2"},{"iothread":"iothread3"}\]' + check_libvirtd_log = '"driver":"virtio-blk-.*","iothread-vq-mapping":\[{"iothread":"iothread1"},{"iothread":"iothread2"},{"iothread":"iothread3"}\]' log_level = "1" variants disk_bus: - virtio: From e0f94c18a190aebffa52fc4ca70f99dff8bc2caa Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Tue, 30 Jul 2024 04:59:07 -0400 Subject: [PATCH 0514/1055] Fix multiattributes.file_disk.start_guest failure on s390x multiattributes on disk is not supported on s390x Signed-off-by: chunfuwen --- .../tests/cfg/virtual_disks/virtual_disks_multiattributes.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_multiattributes.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_multiattributes.cfg index 9e3728e4236..f6710214ca0 100644 --- a/libvirt/tests/cfg/virtual_disks/virtual_disks_multiattributes.cfg +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_multiattributes.cfg @@ -4,6 +4,7 @@ disk_target_dev = "vda" dom_iothreads = "1" driver_attributes = {'name': 'qemu', 'type': 'raw', 'cache': 'none', 'error_policy': 'stop',} + no s390-virtio variants: - start_guest: variants: From dd6cb3eb8be217fbccdff98bdb26168d112bfb76 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 29 Jul 2024 04:11:03 -0400 Subject: [PATCH 0515/1055] gmap: remove lock options Recent Libvirt versions don't allow for these attributes. As they are not needed in this test, remove them. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/memory/gmap.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/memory/gmap.cfg b/libvirt/tests/cfg/memory/gmap.cfg index f587821d2a7..87005acaad3 100644 --- a/libvirt/tests/cfg/memory/gmap.cfg +++ b/libvirt/tests/cfg/memory/gmap.cfg @@ -7,4 +7,4 @@ - l3_shadow_table_counters: l2_mem = 3906250 target_tag = "mount_tag0" - fs_dict = {'accessmode': 'passthrough', 'source': {'dir': 'replace_in_code'}, "target": {'dir': '${target_tag}'}, 'binary': {'lock_posix':'off','flock':'off'}, 'driver': {'type': 'virtiofs'}} + fs_dict = {'accessmode': 'passthrough', 'source': {'dir': 'replace_in_code'}, "target": {'dir': '${target_tag}'}, 'driver': {'type': 'virtiofs'}} From eb7c869057c65763a63e7a54ed78e78e1717a9dd Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Fri, 26 Jul 2024 17:52:37 +0200 Subject: [PATCH 0516/1055] ism_pci_passthrough: add hotplug case 1. Extract check the device is ISM to reuse between hotplug and coldplug functions. 2. Create new test config and test step. 3. Add hotplug function. 4. Change provider function to create pci host device XML, too. Signed-off-by: Sebastian Mitterle --- .../passthrough/pci/ism_pci_passthrough.cfg | 4 +- .../passthrough/pci/ism_pci_passthrough.py | 63 ++++++++++++++----- provider/vfio/__init__.py | 17 +++-- 3 files changed, 64 insertions(+), 20 deletions(-) diff --git a/libvirt/tests/cfg/passthrough/pci/ism_pci_passthrough.cfg b/libvirt/tests/cfg/passthrough/pci/ism_pci_passthrough.cfg index d9d09e9b7c4..1ed996cd576 100644 --- a/libvirt/tests/cfg/passthrough/pci/ism_pci_passthrough.cfg +++ b/libvirt/tests/cfg/passthrough/pci/ism_pci_passthrough.cfg @@ -1,7 +1,7 @@ - libvirt_pci_passthrough.ism: only s390-virtio type = ism_pci_passthrough - start_vm = no + start_vm = yes pci_dev = LIBVIRT_PCI_NAME guest_iface = enc1 variants: @@ -13,3 +13,5 @@ check = start_after_reboot - connect: check = smc_functional + - hotplug: + check = available_hotplug diff --git a/libvirt/tests/src/passthrough/pci/ism_pci_passthrough.py b/libvirt/tests/src/passthrough/pci/ism_pci_passthrough.py index 0fe12c5549c..907e73d20c1 100644 --- a/libvirt/tests/src/passthrough/pci/ism_pci_passthrough.py +++ b/libvirt/tests/src/passthrough/pci/ism_pci_passthrough.py @@ -5,27 +5,29 @@ from avocado.core.exceptions import TestError, TestFail from avocado.utils import process +from virttest import virsh from virttest.libvirt_xml.vm_xml import VMXML from virttest.libvirt_xml.nodedev_xml import NodedevXML +from provider.vfio import get_hostdev_xml -logging = log.getLogger('avocado.' + __name__) + +logging = log.getLogger("avocado." + __name__) smc_port = 37373 -def attach_device(pci_dev, vmxml): +def get_ism_address(pci_dev): """ - Attaches the pci device if it's an ISM device. + Get the ISM device address. - :param pci_dev: The node device name of the ISM device. - :param vmxml: VMXML instance of the VM + :param pci_dev: libvirt's node device name + :return: the address element + :raises TestError: if the device is not an ISM device """ pci_xml = NodedevXML.new_from_dumpxml(pci_dev) if "ism" != pci_xml.driver_name: raise TestError("Device %s is not an ISM device: %s" % (pci_dev, pci_xml)) - pci_address = pci_xml.cap.get_address_dict() - vmxml.add_hostdev(pci_address) - vmxml.sync() + return pci_xml.cap.get_address_dict() def check_device_is_available(vm): @@ -37,7 +39,7 @@ def check_device_is_available(vm): session = vm.wait_for_login() output = session.cmd_output("lspci") session.close() - devices = output.split('\n') + devices = output.split("\n") if not len(devices) >= 1 or "ISM" not in devices[0]: raise TestFail("Expected 1 ISM PCI device but got: %s" % output) @@ -63,6 +65,31 @@ def check_guest_and_host_can_communicate(vm, guest_iface): raise TestFail("SMC-D is not functional: %s" % output) +def hotplug_device(pci_dev, vm_name): + """ + Hotplug the device + + :param vm_name: the VM name + :param pci_dev: the node device name + """ + pci_address = get_ism_address(pci_dev) + hostdev_xml = get_hostdev_xml(pci_address) + virsh.attach_device(vm_name, hostdev_xml.xml, flagstr="--live", debug=True) + time.sleep(1) + + +def coldplug_device(pci_dev, vmxml): + """ + Updates the VMXML with the given PCI device if it's an ISM device. + + :param pci_dev: The node device name of the ISM device. + :param vmxml: VMXML instance of the VM + """ + pci_address = get_ism_address(pci_dev) + vmxml.add_hostdev(pci_address) + vmxml.sync() + + def start_test_server(session): """ Starts the server part in a different thread. @@ -71,7 +98,9 @@ def start_test_server(session): """ session.cmd("systemctl stop firewalld") - server = Thread(target=lambda: session.cmd("timeout 10s smc_chk -S -p %s" % smc_port)) + server = Thread( + target=lambda: session.cmd("timeout 10s smc_chk -S -p %s" % smc_port) + ) server.start() time.sleep(1) return server @@ -119,10 +148,16 @@ def run(test, params, env): backup_xml = vmxml.copy() try: - attach_device(pci_dev, vmxml) - vm.start() - - if check == "available": + if "hotplug" not in check: + if vm.is_alive(): + vm.destroy() + coldplug_device(pci_dev, vmxml) + vm.start() + + if check == "available_hotplug": + hotplug_device(pci_dev, vm_name) + check_device_is_available(vm) + elif check == "available": check_device_is_available(vm) elif check == "available_after_reboot": check_device_is_available_after_reboot(vm) diff --git a/provider/vfio/__init__.py b/provider/vfio/__init__.py index 0ab09595037..845be79786d 100644 --- a/provider/vfio/__init__.py +++ b/provider/vfio/__init__.py @@ -1,19 +1,26 @@ from virttest.libvirt_xml.devices.hostdev import Hostdev -def get_hostdev_xml(uuid, model): +def get_hostdev_xml(address, model=""): """ Creates a hostdev instance for a mediated device with given uuid. - :param uuid: UUID of the mediated device + :param address: For mediated devices, the UUID of the mediated device + For PCI devices, the full address element :param model: mediated device type model, e.g. 'vfio-ccw' + If omitted, treat as PCI device """ hostdev_xml = Hostdev() hostdev_xml.mode = "subsystem" - hostdev_xml.model = model - hostdev_xml.type = "mdev" - hostdev_xml.source = hostdev_xml.new_source(**{"uuid": uuid}) + if "vfio" in model: + hostdev_xml.model = model + hostdev_xml.type = "mdev" + hostdev_xml.source = hostdev_xml.new_source(**{"uuid": address}) + else: + hostdev_xml.type = "pci" + hostdev_xml.managed = "yes" + hostdev_xml.source = hostdev_xml.new_source(**address) hostdev_xml.xmltreefile.write() return hostdev_xml From 72f6957872d7732e49a4d4baebf38e1de728dfbe Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Thu, 20 Jun 2024 06:26:48 -0400 Subject: [PATCH 0517/1055] virsh/nodedev: fix chain test 1. Fix test name, subtest should be nodedev_dumpxml.chain for better discoverability and set definition. 2. Update test to run against a specific device. 3. Allow for a list of devices to be physically present. The test will configure the first one to establish the test precondition. Signed-off-by: Sebastian Mitterle --- .../nodedev/virsh_nodedev_dumpxml_chain.cfg | 3 +- .../nodedev/virsh_nodedev_dumpxml_chain.py | 50 ++++++++++++------- provider/vfio/ccw.py | 18 +++++++ 3 files changed, 51 insertions(+), 20 deletions(-) diff --git a/libvirt/tests/cfg/virsh_cmd/nodedev/virsh_nodedev_dumpxml_chain.cfg b/libvirt/tests/cfg/virsh_cmd/nodedev/virsh_nodedev_dumpxml_chain.cfg index 1fa84e9e9bb..3403d36106a 100644 --- a/libvirt/tests/cfg/virsh_cmd/nodedev/virsh_nodedev_dumpxml_chain.cfg +++ b/libvirt/tests/cfg/virsh_cmd/nodedev/virsh_nodedev_dumpxml_chain.cfg @@ -1,8 +1,9 @@ -- virsh.nodedev_dumpxml_chain: +- virsh.nodedev_dumpxml.chain: type = virsh_nodedev_dumpxml_chain vms = "" main_vm = "" start_vm = "no" + device_ids = 0.0.1234,0.0.4567 variants: - device_type_dasd: only s390-virtio diff --git a/libvirt/tests/src/virsh_cmd/nodedev/virsh_nodedev_dumpxml_chain.py b/libvirt/tests/src/virsh_cmd/nodedev/virsh_nodedev_dumpxml_chain.py index aa2716bd38d..9fd2d3a3ea3 100644 --- a/libvirt/tests/src/virsh_cmd/nodedev/virsh_nodedev_dumpxml_chain.py +++ b/libvirt/tests/src/virsh_cmd/nodedev/virsh_nodedev_dumpxml_chain.py @@ -3,6 +3,9 @@ from virttest import virsh from virttest.libvirt_xml.base import LibvirtXMLBase +from virttest.utils_zchannels import SubchannelPaths as paths + +from provider.vfio import ccw # Using as lower capital is not the best way to do, but this is just a @@ -16,28 +19,37 @@ def run(test, params, env): going up per parent. """ + device_ids = params.get("device_ids", "").split(",") + device = None chain_start_device_pattern = params.get("chain_start_device_pattern") checks = eval(params.get("checks")) - result = virsh.nodedev_list(ignore_status=False) - selected_device = get_device(result.stdout_text.strip().splitlines(), - chain_start_device_pattern) - if not selected_device: - test.error("No suitable device found for test." - "Pattern: %s. Available devices: %s." % - (chain_start_device_pattern, result.stdout)) - - xml = get_nodedev_dumpxml(selected_device) - validate_nodedev_xml(test, xml) - for check in checks: - for xpath, pattern in check.items(): - value = xml.xmltreefile.findtext(xpath) - value = value if value else "" - if not re.search(pattern, value): - test.fail("Unexpected value on xpath '%s':" - " '%s' does not match '%s'" % - (xpath, value, pattern)) - xml = get_nodedev_dumpxml(xml.xmltreefile.findtext("parent")) + try: + device = ccw.select_first_available_device(device_ids) + if device[paths.HEADER["Use"]] != "yes": + ccw.set_device_online(device[paths.HEADER["Device"]]) + result = virsh.nodedev_list(ignore_status=False) + selected_device = get_device(result.stdout_text.strip().splitlines(), + chain_start_device_pattern) + if not selected_device: + test.error("No suitable device found for test." + "Pattern: %s. Available devices: %s." % + (chain_start_device_pattern, result.stdout)) + + xml = get_nodedev_dumpxml(selected_device) validate_nodedev_xml(test, xml) + for check in checks: + for xpath, pattern in check.items(): + value = xml.xmltreefile.findtext(xpath) + value = value if value else "" + if not re.search(pattern, value): + test.fail("Unexpected value on xpath '%s':" + " '%s' does not match '%s'" % + (xpath, value, pattern)) + xml = get_nodedev_dumpxml(xml.xmltreefile.findtext("parent")) + validate_nodedev_xml(test, xml) + finally: + if device and device[paths.HEADER["Use"]] == "yes": + ccw.set_device_offline(device[paths.HEADER["Device"]]) def validate_nodedev_xml(test, xml): diff --git a/provider/vfio/ccw.py b/provider/vfio/ccw.py index 227bb41b556..01973c2d71e 100644 --- a/provider/vfio/ccw.py +++ b/provider/vfio/ccw.py @@ -310,6 +310,24 @@ def assure_preconditions(): utils_package.package_install(["mdevctl", "driverctl"]) +def select_first_available_device(device_ids): + """ + Loops through the given device identifiers and selects + the first device that exists on the system. + + :param device_ids: list of potential device identifiers. + :return device: device info as defined by SubchannelPaths + :raise TestError: if no available devices is found. + """ + paths = SubchannelPaths() + paths.get_info() + for device in paths.devices: + for device_id in device_ids: + if device[paths.HEADER["Device"]] == device_id: + return device + raise TestError(f"None of the devices is available, {device_ids}") + + def get_device_info(devid=None): """ Gets the device info for passthrough. From ee3c70fcba1a141af524252961d8473d8a8b0a22 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 31 Jul 2024 07:35:29 -0400 Subject: [PATCH 0518/1055] svirt/selinux: don't update boot disk The test usually updates the attributes of an existing device. However, in case of disks this means that the boot disk is substituted. s390x behaves here differently from x86_64, for example. x86_64 would have a running VM even if it doesn't boot (the test creates an empty image to boot from) whereas on s390x the VM doesn't start. Therefore, in case of x86_64 the file is relabeled but on s390x it isn't. For disks, instead of updating the device, attach it. The test should only try to start the VM if the coldplug worked. If not use the coldplug result to check the test condition. Signed-off-by: Sebastian Mitterle --- .../selinux/selinux_seclabel_per_device.py | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/src/svirt/selinux/selinux_seclabel_per_device.py b/libvirt/tests/src/svirt/selinux/selinux_seclabel_per_device.py index d15ef5dcfaf..c79aa10fa09 100644 --- a/libvirt/tests/src/svirt/selinux/selinux_seclabel_per_device.py +++ b/libvirt/tests/src/svirt/selinux/selinux_seclabel_per_device.py @@ -39,6 +39,20 @@ def get_dev_dict(device_type, params): return dev_dict, seclabel_attr +def attach_device(vm, test_device, dev_dict): + """ + Attaches the device as specified to the VM. + + :param vm: VM instance + :param test_device: the device type, e.g. disk + :param dev_dict: the device definition + """ + + dev_obj = libvirt_vmxml.create_vm_device_by_type(test_device, dev_dict) + dev_obj.setup_attrs(**dev_dict) + return virsh.attach_device(vm.name, dev_obj.xml, flagstr="--current", debug=True) + + def run(test, params, env): """ Start VM or hotplug a device with per-device selinux setting @@ -67,12 +81,16 @@ def run(test, params, env): if test_scenario != "hot_plug": test.log.info("TEST_STEP: Start VM with per-device dac setting.") try: - libvirt_vmxml.modify_vm_device(vmxml, test_device, dev_dict) + if test_device != 'disk': + libvirt_vmxml.modify_vm_device(vmxml, test_device, dev_dict) + else: + res = attach_device(vm, test_device, dev_dict) except xcepts.LibvirtXMLError as details: if not status_error: test.fail(details) test.log.debug("VM XML: %s.", VMXML.new_from_inactive_dumpxml(vm_name)) - res = virsh.start(vm.name) + if res.exit_status == 0: + res = virsh.start(vm.name) else: test.log.info("TEST_STEP: Hot plug a device with dac setting.") if test_device == 'serial': @@ -81,9 +99,7 @@ def run(test, params, env): vm.start() vm.wait_for_login().close() - dev_obj = libvirt_vmxml.create_vm_device_by_type(test_device, dev_dict) - dev_obj.setup_attrs(**dev_dict) - res = virsh.attach_device(vm.name, dev_obj.xml, debug=True) + res = attach_device(vm, test_device, dev_dict) libvirt.check_exit_status(res, status_error) if seclabel_attr.get("label") and not status_error: From 4ee2a59f72f275ec37e6943b173ebe989bb0ef12 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Tue, 30 Jul 2024 22:59:14 -0400 Subject: [PATCH 0519/1055] Add network case of passt lifecycle - VIRT-297078 - [user][passt] Test the lifecycle of the vm with passt backend interface Signed-off-by: Haijiao Zhao --- .../virtual_network/passt/passt_lifecycle.cfg | 57 ++++++ .../virtual_network/passt/passt_lifecycle.py | 163 ++++++++++++++++++ 2 files changed, 220 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/passt/passt_lifecycle.cfg create mode 100644 libvirt/tests/src/virtual_network/passt/passt_lifecycle.py diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_lifecycle.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_lifecycle.cfg new file mode 100644 index 00000000000..d155c6566b7 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/passt/passt_lifecycle.cfg @@ -0,0 +1,57 @@ +- virtual_network.passt.lifecycle: + type = passt_lifecycle + func_supported_since_libvirt_ver = (9, 0, 0) + host_iface = + outside_ip = 'www.redhat.com' + start_vm = no + mtu = 65520 + variants operation: + - save_restore: + operation_a = save + operation_b = restore + options_a = {'name': vm_name, 'path': save_path} + options_b = {'path': save_path} + passt_running = no + - managedsave_start: + operation_a = managedsave + operation_b = start + passt_running = no + - suspend_resume: + operation_a = suspend + operation_b = resume + passt_running = yes + variants user_type: + - non_root_user: + test_user = USER.EXAMPLE + test_passwd = PASSWORD.EXAMPLE + user_id = + unpr_vm_name = UNPRIVILEGED_VM.EXAMPLE + socket_dir = f'/run/user/{user_id}/libvirt/qemu/run/passt/' + variants scenario: + - ip_portfw: + ipv6_prefix = 128 + alias = {'name': 'ua-c87b89ff-b769-4abc-921f-30d42d7aec5b'} + backend = {'type': 'passt'} + ips = [{'address': '172.17.2.4', 'family': 'ipv4', 'prefix': '24'}, {'address': '2001:db8:ac10:fd01::20', 'family': 'ipv6'}] + vm_iface = eno1 + vm_ping_outside = pass + vm_ping_host_public = pass + portForward_0 = {'attrs': {'proto': 'tcp'}, 'ranges': [{'start': '31339', 'to': '41339'}]} + portForward_1 = {'attrs': {'proto': 'udp'}, 'ranges': [{'start': '2025'}]} + portForward_2 = {'attrs': {'proto': 'tcp', 'address': host_ip}, 'ranges': [{'start': '4025', 'end': '4035', 'to': '5025'},{'start': '9000'}, {'start': '4030', 'end': '4034', 'exclude': 'yes'}]} + portForwards = [${portForward_0}, ${portForward_1}, ${portForward_2}] + proc_checks = ['--tcp-ports 31339:41339', '--udp-ports 2025', f'--tcp-ports {host_ip}/4025-4035:5025-5035,9000,~4030-4034'] + tcp_port_list = [4025, 4026, 4027, 4028, 4029, 4035, 9000, '*:31339'] + udp_port_list = ['0.0.0.0:2025', '[::]:2025'] + conn_check_args_0 = ('TCP4', host_ip, 31339, 41339, True, None) + conn_check_args_1 = ('TCP4', host_ip, 4025, 5025, True, None) + conn_check_args_2 = ('TCP4', 'localhost', 4025, 5025, False, 'Connection refused') + conn_check_args_3 = ('TCP4', 'localhost', 31339, 41339, True, None) + conn_check_args_4 = ('TCP4', host_ip, 4030, 4030, False, 'Connection refused') + conn_check_args_5 = ('TCP6', 'localhost', 31339, 41339, True, None) + conn_check_args_6 = ('TCP6', '::1', 31339, 41339, True, None) + conn_check_args_7 = ('UDP4', 'localhost', 2025, 2025, True, None) + iface_attrs = {'model': 'virtio', 'acpi': {'index': '1'}, 'ips': ${ips}, 'backend': ${backend}, 'source': {'dev': host_iface}, 'alias': ${alias}, 'type_name': 'user', 'portForwards': ${portForwards}} + s390-virtio: + vm_iface = enc1 + iface_attrs = {'model': 'virtio', 'ips': ${ips}, 'backend': ${backend}, 'source': {'dev': host_iface}, 'alias': ${alias}, 'type_name': 'user', 'portForwards': ${portForwards}} diff --git a/libvirt/tests/src/virtual_network/passt/passt_lifecycle.py b/libvirt/tests/src/virtual_network/passt/passt_lifecycle.py new file mode 100644 index 00000000000..be846bdb412 --- /dev/null +++ b/libvirt/tests/src/virtual_network/passt/passt_lifecycle.py @@ -0,0 +1,163 @@ +import logging +import os +import shutil + +import aexpect +from virttest import libvirt_version +from virttest import remote +from virttest import utils_misc +from virttest import utils_net +from virttest import utils_selinux +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.staging import service +from virttest.utils_libvirt import libvirt_unprivileged +from virttest.utils_libvirt import libvirt_vmxml + +from provider.virtual_network import network_base +from provider.virtual_network import passt + +LOG = logging.getLogger('avocado.' + __name__) + +IPV6_LENGTH = 128 +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + + +def run(test, params, env): + """ + Test passt lifecycle + """ + libvirt_version.is_libvirt_feature_supported(params) + root = 'root_user' == params.get('user_type', '') + if root: + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + virsh_ins = virsh + log_dir = params.get('log_dir') + user_id = params.get('user_id') + else: + vm_name = params.get('unpr_vm_name') + test_user = params.get('test_user', '') + test_passwd = params.get('test_passwd', '') + user_id = passt.get_user_id(test_user) + unpr_vm_args = { + 'username': params.get('username'), + 'password': params.get('password'), + } + vm = libvirt_unprivileged.get_unprivileged_vm(vm_name, test_user, + test_passwd, + **unpr_vm_args) + uri = f'qemu+ssh://{test_user}@localhost/session' + virsh_ins = virsh.VirshPersistent(uri=uri) + host_session = aexpect.ShellSession('su') + remote.VMManager.set_ssh_auth(host_session, 'localhost', test_user, + test_passwd) + host_session.close() + + host_iface = params.get('host_iface') + host_iface = host_iface if host_iface else utils_net.get_net_if( + state="UP")[0] + host_ip = utils_net.get_ip_address_by_interface(host_iface, ip_ver='ipv4') + host_ip_v6 = utils_net.get_ip_address_by_interface( + host_iface, ip_ver='ipv6') + params['host_ip_v6'] = host_ip_v6 + params['socket_dir'] = socket_dir = eval(params.get('socket_dir')) + params['proc_checks'] = proc_checks = eval(params.get('proc_checks', '{}')) + mtu = params.get('mtu') + outside_ip = params.get('outside_ip') + log_file = f'/run/user/{user_id}/passt.log' + iface_attrs = eval(params.get('iface_attrs')) + iface_attrs['backend']['logFile'] = log_file + operation_a = params.get('operation_a') + operation_b = params.get('operation_b') + save_path = f'/home/{test_user}/save_{utils_misc.generate_random_string(3)}' + options_a = eval(params.get('options_a', '{}')) + options_b = eval(params.get('options_b', '{}')) + passt_running = 'yes' == params.get('passt_running', 'no') + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name, + virsh_instance=virsh_ins) + bkxml = vmxml.copy() + + selinux_status = passt.ensure_selinux_enforcing() + passt.check_socat_installed() + + firewalld = service.Factory.create_service("firewalld") + try: + operation_a = eval(f'virsh_ins.{operation_a}') + operation_b = eval(f'virsh_ins.{operation_b}') + + if root: + passt.make_log_dir(user_id, log_dir) + + default_gw = utils_net.get_default_gateway() + default_gw_v6 = utils_net.get_default_gateway(ip_ver='ipv6') + + vmxml.del_device('interface', by_tag=True) + vmxml.sync(virsh_instance=virsh_ins) + libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs, + virsh_instance=virsh_ins) + LOG.debug(virsh_ins.dumpxml(vm_name).stdout_text) + mac = vm.get_virsh_mac_address() + + vm.start() + passt.check_proc_info(params, log_file, mac) + + options_a = {'name': vm_name} if not options_a else options_a + options_b = {'name': vm_name} if not options_b else options_b + operation_a(**options_a, **VIRSH_ARGS) + if passt_running: + passt.check_proc_info(params, log_file, mac) + else: + passt.check_passt_pid_not_exist() + operation_b(**options_b, **VIRSH_ARGS) + + # Check the passt log + if not os.path.exists(log_file): + test.fail(f'Logfile of passt "{log_file}" not created') + + # Re-create console since vm has been restored/resumed + vm.cleanup_serial_console() + vm.create_serial_console() + session = vm.wait_for_serial_login(timeout=60) + + vm_iface = utils_net.get_linux_ifname(session, mac) + passt.check_vm_ip(iface_attrs, session, host_iface, vm_iface) + passt.check_vm_mtu(session, vm_iface, mtu) + passt.check_default_gw(session, host_iface) + passt.check_nameserver(session) + + ips = { + 'outside_ip': outside_ip, + 'host_public_ip': host_ip, + } + network_base.ping_check(params, ips, session, force_ipv4=True) + session.close() + + firewalld.stop() + LOG.debug(f'Status of firewalld: {firewalld.status()}') + passt.check_connection(vm, vm_iface, + ['TCP4', 'TCP6', 'UDP4', 'UDP6'], + host_iface) + + if 'portForwards' in iface_attrs: + passt.check_portforward(vm, host_ip, params, host_iface) + + vm_sess = vm.wait_for_serial_login(timeout=60) + vm_sess.cmd('systemctl start firewalld') + vm.destroy() + + passt.check_passt_pid_not_exist() + if os.listdir(socket_dir): + test.fail(f'Socket dir is not empty: {os.listdir(socket_dir)}') + + finally: + firewalld.start() + bkxml.sync(virsh_instance=virsh_ins) + if root: + shutil.rmtree(log_dir) + else: + del virsh_ins + utils_selinux.set_status(selinux_status) + if os.path.exists(save_path): + os.remove(save_path) From e0d65ec2f7cb50af88874be2183c80761c40697f Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 1 Aug 2024 04:23:43 -0400 Subject: [PATCH 0520/1055] virtual_network:Use get_default_gateway to get host iface name The original way is to get the 1st iface that is UP which is not reliable since an interface might be UP even if it doesn't have an ip address. Signed-off-by: Haijiao Zhao --- .../attach_detach_device/attach_mtu_malformed.py | 4 ++-- .../connectivity/connectivity_check_bridge_interface.py | 4 ++-- .../connectivity_check_bridge_interface_unprivileged.py | 4 ++-- .../connectivity/connectivity_check_direct_interface.py | 4 ++-- .../connectivity/connectivity_check_ethernet_interface.py | 4 ++-- .../connectivity/connectivity_check_user_interface.py | 4 ++-- .../elements_and_attributes/attribute_port_isolated.py | 4 ++-- .../elements_and_attributes/element_coalesce.py | 4 ++-- libvirt/tests/src/virtual_network/iface_stat.py | 3 ++- .../src/virtual_network/link_state/link_state_model_type.py | 4 ++-- .../tests/src/virtual_network/passt/passt_attach_detach.py | 4 ++-- .../passt/passt_connectivity_between_2vms.py | 4 ++-- libvirt/tests/src/virtual_network/passt/passt_function.py | 4 ++-- .../src/virtual_network/passt/passt_negative_setting.py | 4 ++-- libvirt/tests/src/virtual_network/passt/passt_reconnect.py | 4 ++-- .../tests/src/virtual_network/passt/passt_transfer_file.py | 4 ++-- .../src/virtual_network/qos/check_bandwidth_by_domiftune.py | 4 ++-- .../virtual_network/update_device/update_device_coalesce.py | 4 ++-- .../update_device/update_iface_link_state.py | 4 ++-- .../src/virtual_network/update_device/update_iface_qos.py | 4 ++-- .../virtual_network/update_device/update_iface_source.py | 4 ++-- .../update_device/update_iface_trustGuestRxFilters.py | 4 ++-- .../virtual_network/update_device/update_iface_type_live.py | 4 ++-- .../virtual_network/update_device/update_port_isolated.py | 4 ++-- provider/virtual_network/passt.py | 6 +++--- 25 files changed, 51 insertions(+), 50 deletions(-) diff --git a/libvirt/tests/src/virtual_network/attach_detach_device/attach_mtu_malformed.py b/libvirt/tests/src/virtual_network/attach_detach_device/attach_mtu_malformed.py index d8c9529f5bf..b2ca4f92eb9 100644 --- a/libvirt/tests/src/virtual_network/attach_detach_device/attach_mtu_malformed.py +++ b/libvirt/tests/src/virtual_network/attach_detach_device/attach_mtu_malformed.py @@ -25,8 +25,8 @@ def run(test, params, env): net_name = 'net_' + rand_id source_net = params.get('source_net', net_name) host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state='UP')[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] iface_attrs = eval(params.get('iface_attrs', '{}')) net_attrs = eval(params.get('net_attrs', '{}')) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py index 06f1100b185..f8b7ed7e4c0 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py @@ -53,8 +53,8 @@ def run(test, params, env): iface_in_vm = iface_in_vm if iface_in_vm else 'eno' host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state="UP")[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] bkxmls = list(map(vm_xml.VMXML.new_from_inactive_dumpxml, vms)) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface_unprivileged.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface_unprivileged.py index f8873524ffb..d11b55a4c0f 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface_unprivileged.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface_unprivileged.py @@ -29,8 +29,8 @@ def run(test, params, env): linux_bridge = 'br_' + rand_id br_conf_file = '/etc/qemu-kvm/bridge.conf' host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state="UP")[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] unpr_user = params.get('unpr_user', 'test_unpr') + rand_id diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_direct_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_direct_interface.py index a68522669c4..fe0b2915ddc 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_direct_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_direct_interface.py @@ -22,8 +22,8 @@ def run(test, params, env): vm, ep_vm = (env.get_vm(vm_i) for vm_i in vms) outside_ip = params.get('outside_ip') host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state="UP")[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] iface_attrs = eval(params.get('iface_attrs', '{}')) bkxmls = list(map(vm_xml.VMXML.new_from_inactive_dumpxml, vms)) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py index c81f44a9ed5..5b76d5a4208 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py @@ -54,8 +54,8 @@ def run(test, params, env): iface_attrs = eval(params.get('iface_attrs')) outside_ip = params.get('outside_ip') host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state="UP")[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] host_ip = utils_net.get_ip_address_by_interface(host_iface, ip_ver='ipv4') status_error = 'yes' == params.get('status_error', 'no') err_msg = params.get('err_msg') diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py index aba514d1bf0..8fd26349458 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py @@ -76,8 +76,8 @@ def run(test, params, env): iface_attrs = eval(params.get('iface_attrs')) outside_ip = params.get('outside_ip') host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state='UP')[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] ipv4_addr = params.get('ipv4_addr') ipv4_prefix = params.get('ipv4_prefix') diff --git a/libvirt/tests/src/virtual_network/elements_and_attributes/attribute_port_isolated.py b/libvirt/tests/src/virtual_network/elements_and_attributes/attribute_port_isolated.py index 3efab3c7dd1..c0fd1e9199c 100644 --- a/libvirt/tests/src/virtual_network/elements_and_attributes/attribute_port_isolated.py +++ b/libvirt/tests/src/virtual_network/elements_and_attributes/attribute_port_isolated.py @@ -35,8 +35,8 @@ def run(test, params, env): net_attrs = eval(params.get('net_attrs', '{}')) port_attrs = eval(params.get('port_attrs', '{}')) host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state='UP')[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) bkxmls = list(map(vm_xml.VMXML.new_from_inactive_dumpxml, vms)) diff --git a/libvirt/tests/src/virtual_network/elements_and_attributes/element_coalesce.py b/libvirt/tests/src/virtual_network/elements_and_attributes/element_coalesce.py index d32c6d0a93a..70844dfc53a 100644 --- a/libvirt/tests/src/virtual_network/elements_and_attributes/element_coalesce.py +++ b/libvirt/tests/src/virtual_network/elements_and_attributes/element_coalesce.py @@ -31,8 +31,8 @@ def run(test, params, env): br_name = br_type + '_' + rand_id host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state="UP")[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] iface_attrs = eval(params.get('iface_attrs', '{}')) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) diff --git a/libvirt/tests/src/virtual_network/iface_stat.py b/libvirt/tests/src/virtual_network/iface_stat.py index cdc558feef8..8c62774fa72 100644 --- a/libvirt/tests/src/virtual_network/iface_stat.py +++ b/libvirt/tests/src/virtual_network/iface_stat.py @@ -151,7 +151,8 @@ def _collect_and_compare_stat(vm_name, session, **virsh_args): host_iface = params.get("host_iface") if not host_iface: - host_iface = utils_net.get_net_if(state="UP")[0] + host_iface = utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] if iface_type == 'direct': iface_dict = {k.replace('new_iface_', ''): v for k, v in params.items() diff --git a/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py b/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py index 4dde3ee9aa5..39c27605ed0 100644 --- a/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py +++ b/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py @@ -25,8 +25,8 @@ def run(test, params, env): outside_ip = params.get("outside_ip") host_iface = params.get("host_iface") - host_iface = host_iface if host_iface else utils_net.get_net_if( - state="UP")[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] rand_id = utils_misc.generate_random_string(3) bridge_name = "br_" + rand_id tap_name = "tap_" + rand_id diff --git a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py index 3535f3c04db..ba4f5805421 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py +++ b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py @@ -67,8 +67,8 @@ def run(test, params, env): virsh_uri = params.get('virsh_uri') add_iface = 'yes' == params.get('add_iface', 'no') host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state="UP")[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] host_ip = utils_net.get_ip_address_by_interface(host_iface, ip_ver='ipv4') host_ip_v6 = utils_net.get_ip_address_by_interface(host_iface, ip_ver='ipv6') iface_attrs = eval(params.get('iface_attrs')) diff --git a/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py b/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py index 27008a54f00..725464fce41 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py +++ b/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py @@ -67,8 +67,8 @@ def run(test, params, env): params['proc_checks'] = proc_checks = eval(params.get('proc_checks', '{}')) vm_c_iface = params.get('vm_c_iface', 'eno1') host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state="UP")[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] iface_attrs['backend']['logFile'] = log_file iface_c_attrs['backend']['logFile'] = log_file_c iface_attrs['source']['dev'] = host_iface diff --git a/libvirt/tests/src/virtual_network/passt/passt_function.py b/libvirt/tests/src/virtual_network/passt/passt_function.py index 1b3dcd80626..b8a201f53e5 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_function.py +++ b/libvirt/tests/src/virtual_network/passt/passt_function.py @@ -53,8 +53,8 @@ def run(test, params, env): host_session.close() host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state="UP")[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] host_ip = utils_net.get_ip_address_by_interface(host_iface, ip_ver='ipv4') host_ip_v6 = utils_net.get_ip_address_by_interface(host_iface, ip_ver='ipv6') params['host_ip_v6'] = host_ip_v6 diff --git a/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py b/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py index 88a8b9ee52e..f2f98199f7a 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py +++ b/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py @@ -50,8 +50,8 @@ def run(test, params, env): error_msg = params.get('error_msg') iface_attrs = eval(params.get('iface_attrs')) host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state="UP")[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] log_file = f'/run/user/{user_id}/passt.log' \ if not params.get('log_file') else params['log_file'] iface_attrs['backend']['logFile'] = log_file diff --git a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py index 98fe1acedb8..d7397fbb7ed 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py +++ b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py @@ -64,8 +64,8 @@ def run(test, params, env): qemu_cmd_check = params.get('qemu_cmd_check') outside_ip = params.get('outside_ip') host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state="UP")[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] log_file = f'/run/user/{user_id}/passt.log' iface_attrs['backend']['logFile'] = log_file iface_attrs['source']['dev'] = host_iface diff --git a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py index e765e38bc68..3f99e33f938 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py +++ b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py @@ -151,8 +151,8 @@ def run(test, params, env): params['socket_dir'] = socket_dir = eval(params.get('socket_dir')) params['proc_checks'] = proc_checks = eval(params.get('proc_checks', '{}')) host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state="UP")[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] log_file = f'/run/user/{user_id}/passt.log' iface_attrs['backend']['logFile'] = log_file iface_attrs['source']['dev'] = host_iface diff --git a/libvirt/tests/src/virtual_network/qos/check_bandwidth_by_domiftune.py b/libvirt/tests/src/virtual_network/qos/check_bandwidth_by_domiftune.py index 9c329da1b5f..39a0e150126 100644 --- a/libvirt/tests/src/virtual_network/qos/check_bandwidth_by_domiftune.py +++ b/libvirt/tests/src/virtual_network/qos/check_bandwidth_by_domiftune.py @@ -28,8 +28,8 @@ def run(test, params, env): rand_id = utils_misc.generate_random_string(3) br_name = br_type + '_' + rand_id host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state='UP')[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] iface_attrs = eval(params.get('iface_attrs', '{}')) net_attrs = eval(params.get('net_attrs', '{}')) update_bw = eval(params.get('update_bw', '{}')) diff --git a/libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py b/libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py index 15d0a926acf..ce775643239 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py +++ b/libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py @@ -47,8 +47,8 @@ def run(test, params, env): mac = utils_net.generate_mac_address_simple() iface_attrs = eval(params.get('iface_attrs', '{}')) host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state='UP')[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] rx_frames = params.get('rx_frames', '0') updated_rx_frames = params.get('updated_rx_frames', '0') updated_coalesce = eval(params.get('updated_coalesce', '{}')) diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_link_state.py b/libvirt/tests/src/virtual_network/update_device/update_iface_link_state.py index dfc30f33864..a7823504021 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_link_state.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_link_state.py @@ -21,8 +21,8 @@ def run(test, params, env): outside_ip = params.get("outside_ip") host_iface = params.get("host_iface") - host_iface = host_iface if host_iface else utils_net.get_net_if( - state="UP")[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] rand_id = utils_misc.generate_random_string(3) bridge_name = "br_" + rand_id tap_name = "tap_" + rand_id diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_qos.py b/libvirt/tests/src/virtual_network/update_device/update_iface_qos.py index a5b95e3d1b7..4db5aa7d18c 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_qos.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_qos.py @@ -42,8 +42,8 @@ def run(test, params, env): rand_id = utils_misc.generate_random_string(3) br_name = br_type + '_' + rand_id host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state='UP')[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] iface_attrs = eval(params.get('iface_attrs', '{}')) extra_attrs = eval(params.get('extra_attrs', '{}')) net_attrs = eval(params.get('net_attrs', '{}')) diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_source.py b/libvirt/tests/src/virtual_network/update_device/update_iface_source.py index a3e21bd93da..cafc7eddaa6 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_source.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_source.py @@ -25,8 +25,8 @@ def run(test, params, env): rand_id = utils_misc.generate_random_string(3) net_name = 'net_' + rand_id host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state='UP')[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] iface_attrs = eval(params.get('iface_attrs', '{}')) net_attrs = eval(params.get('net_attrs', '{}')) status_error = 'yes' == params.get('status_error', 'no') diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py b/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py index 8bb32c61403..35b78d9a8cc 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py @@ -23,8 +23,8 @@ def run(test, params, env): vm_name = params.get('main_vm') vm = env.get_vm(vm_name) host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state='UP')[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] iface_attrs = eval(params.get('iface_attrs', '{}')) ips = {'outside_ip': params.get('outside_ip')} diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_type_live.py b/libvirt/tests/src/virtual_network/update_device/update_iface_type_live.py index bc3ce6bf7f1..3e26ab6e625 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_type_live.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_type_live.py @@ -27,8 +27,8 @@ def run(test, params, env): iface_attrs = eval(params.get('iface_attrs', '{}')) iface_type = params.get('iface_type') host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state='UP')[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] net_attrs = eval(params.get('net_attrs', '{}')) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) diff --git a/libvirt/tests/src/virtual_network/update_device/update_port_isolated.py b/libvirt/tests/src/virtual_network/update_device/update_port_isolated.py index 90d3f4c9313..e91a5f8a40d 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_port_isolated.py +++ b/libvirt/tests/src/virtual_network/update_device/update_port_isolated.py @@ -111,8 +111,8 @@ def test_update_iface(): net_attrs = eval(params.get('net_attrs', '{}')) update_port_attrs = eval(params.get('update_port_attrs', '{}')) host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state='UP')[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) bkxmls = list(map(vm_xml.VMXML.new_from_inactive_dumpxml, vms)) diff --git a/provider/virtual_network/passt.py b/provider/virtual_network/passt.py index 47a622762be..72049e1aec1 100644 --- a/provider/virtual_network/passt.py +++ b/provider/virtual_network/passt.py @@ -1,7 +1,7 @@ import logging import os -import re import random +import re import time from socket import socket @@ -138,8 +138,8 @@ def check_proc_info(params, log_file, mac): socket_dir = params.get('socket_dir') host_iface = params.get('host_iface') - host_iface = host_iface if host_iface else utils_net.get_net_if( - state="UP")[0] + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] proc_info = get_proc_info('passt') LOG.debug(proc_info) From 11d52f89b98d3082fc934be46648067bacc21616 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 31 Jul 2024 08:42:39 -0400 Subject: [PATCH 0521/1055] Remove lock options and update cache mode 1. In the commit for fix bug RHEL-7108, lock options are not allowed to config any more, so we need to remove them thoroughly. 2. Cache mode "none" can not be used from virtiofsd-1.11.1, it should be replaced as "never" from now on. 3. syntax of test.log need to be updated, or it will report error like: "TypeError: not enough arguments for format string" Signed-off-by: Lili Zhu --- libvirt/tests/cfg/virtio/virtio_page_per_vq.cfg | 2 +- .../cfg/virtual_device/filesystem_device_unprivileged.cfg | 4 ++-- libvirt/tests/src/virtio/virtio_page_per_vq.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/cfg/virtio/virtio_page_per_vq.cfg b/libvirt/tests/cfg/virtio/virtio_page_per_vq.cfg index a06382e9159..44a6a7c12bd 100644 --- a/libvirt/tests/cfg/virtio/virtio_page_per_vq.cfg +++ b/libvirt/tests/cfg/virtio/virtio_page_per_vq.cfg @@ -47,4 +47,4 @@ device_dict = {'model_type': 'virtio', **${driver_dict}, 'model_heads': '1'} - filesystem: driver_dict = {'driver': {'type': 'virtiofs', 'page_per_vq': 'on'}} - device_dict = {'source': {'dir': '/tmp'}, **${driver_dict}, 'type_name': 'mount', 'accessmode': 'passthrough', 'target': {'dir': 'mount_tag'}, 'binary': {'xattr': 'on', 'path': '/usr/libexec/virtiofsd', 'cache_mode': 'none'}} + device_dict = {'source': {'dir': '/tmp'}, **${driver_dict}, 'type_name': 'mount', 'accessmode': 'passthrough', 'target': {'dir': 'mount_tag'}, 'binary': {'xattr': 'on', 'path': '/usr/libexec/virtiofsd', 'cache_mode': 'always'}} diff --git a/libvirt/tests/cfg/virtual_device/filesystem_device_unprivileged.cfg b/libvirt/tests/cfg/virtual_device/filesystem_device_unprivileged.cfg index 50e57312c70..c90f7a48d03 100644 --- a/libvirt/tests/cfg/virtual_device/filesystem_device_unprivileged.cfg +++ b/libvirt/tests/cfg/virtual_device/filesystem_device_unprivileged.cfg @@ -30,6 +30,6 @@ - with_shm: variants: - one_fs: - fs_dicts = [{'accessmode': 'passthrough', 'source': {'dir': '/tmp/dir1'}, "target": {'dir': 'mount_tag1'}, 'binary': {'path':'/usr/libexec/virtiofsd', 'lock_posix':'off','flock':'off', 'sandbox_mode':'namespace', 'xattr':'on', 'cache_mode':'none'}, 'driver': {'type': 'virtiofs', 'queue':'1024'}}] + fs_dicts = [{'accessmode': 'passthrough', 'source': {'dir': '/tmp/dir1'}, "target": {'dir': 'mount_tag1'}, 'binary': {'path':'/usr/libexec/virtiofsd', 'sandbox_mode':'namespace', 'xattr':'on', 'cache_mode':'always'}, 'driver': {'type': 'virtiofs', 'queue':'1024'}}] - two_fs: - fs_dicts = [{'accessmode': 'passthrough', 'source': {'dir': '/tmp/dir1'}, "target": {'dir': 'mount_tag1'}, 'binary': {'lock_posix':'off','flock':'off', 'sandbox_mode':'namespace'}, 'driver': {'type': 'virtiofs'}}, {'accessmode': 'passthrough', 'source': {'dir': '/tmp/dir2'}, "target": {'dir': 'mount_tag2'}, 'binary': {'lock_posix':'off','flock':'off', 'sandbox_mode':'namespace', 'xattr':'on', 'cache_mode':'none'}, 'driver': {'type': 'virtiofs'}}] + fs_dicts = [{'accessmode': 'passthrough', 'source': {'dir': '/tmp/dir1'}, "target": {'dir': 'mount_tag1'}, 'binary': {'sandbox_mode':'namespace'}, 'driver': {'type': 'virtiofs'}}, {'accessmode': 'passthrough', 'source': {'dir': '/tmp/dir2'}, "target": {'dir': 'mount_tag2'}, 'binary': {'sandbox_mode':'namespace', 'xattr':'on', 'cache_mode':'always'}, 'driver': {'type': 'virtiofs'}}] diff --git a/libvirt/tests/src/virtio/virtio_page_per_vq.py b/libvirt/tests/src/virtio/virtio_page_per_vq.py index bb47458b88f..f39435fde90 100644 --- a/libvirt/tests/src/virtio/virtio_page_per_vq.py +++ b/libvirt/tests/src/virtio/virtio_page_per_vq.py @@ -134,7 +134,7 @@ def check_attribute(): "got '%s'" % (pre_dict, cur_dict)) else: test.log.debug("Driver XML compare successfully. The '%s' matches" - " the '%s'", (pre_dict, cur_dict)) + " the '%s'", pre_dict, cur_dict) def start_guest(): """ From dd01b6909afa5c7a9295257f9c30c7f6e75ead22 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 29 Jul 2024 08:58:11 -0400 Subject: [PATCH 0522/1055] update_iface_link_state: wait for guest network reset On our nested systems backed by a virtual NAT network it takes longer for the guest to get a reachable network. The test was failing at the ping intent with ping: connect: Network is unreachable Instead, retry for several seconds to succeed. Signed-off-by: Sebastian Mitterle --- provider/virtual_network/network_base.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/provider/virtual_network/network_base.py b/provider/virtual_network/network_base.py index 8a70be4e1d8..cf3bfcbc386 100644 --- a/provider/virtual_network/network_base.py +++ b/provider/virtual_network/network_base.py @@ -6,6 +6,7 @@ from avocado.core import exceptions from avocado.utils import process from virttest import remote +from virttest import utils_misc from virttest import utils_net from virttest import virsh from virttest.libvirt_xml import network_xml @@ -110,15 +111,23 @@ def ping_check(params, ips, session=None, force_ipv4=True, **args): LOG.info(f'TEST_STEP: Ping from {source} to {destination} ' f'(ip: {dest_ip})') ping_session = session if source == 'vm' else None - status, _ = utils_net.ping(dest=dest_ip, count=5, - timeout=10, - session=ping_session, - force_ipv4=force_ipv4, - **ping_args) + + def _ping(): + """ Helper function to make use of wait_for """ + status, output = utils_net.ping(dest=dest_ip, count=5, + timeout=10, + session=ping_session, + force_ipv4=force_ipv4, + **ping_args) + if status and "unreachable" in output and expect_result == 'pass': + return False + return status == 0 + + status = utils_misc.wait_for(_ping, timeout=15) + ping_result = (status is True) == (expect_result == 'pass') msg = f'Expect ping from {source} to {destination} should ' \ f'{expect_result.upper()}, actual result is ' \ - f'{"PASS" if status == 0 else "FAIL"}' - ping_result = (status == 0) == (expect_result == 'pass') + f'{"PASS" if ping_result else "FAIL"}' if ping_result: LOG.debug(msg) else: From a73fc3b4b079d3f4872646a81627619a21d40911 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Mon, 5 Aug 2024 06:54:20 -0400 Subject: [PATCH 0523/1055] update_iface_qos:Fix typo of tc command Missing `:` from tc command Signed-off-by: Haijiao Zhao --- .../tests/src/virtual_network/update_device/update_iface_qos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_qos.py b/libvirt/tests/src/virtual_network/update_device/update_iface_qos.py index a5b95e3d1b7..2aada8e64a4 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_qos.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_qos.py @@ -139,7 +139,7 @@ def run(test, params, env): if operation == 'delete': out_c = process.run(f'tc class show dev {tap_device}' ).stdout_text.strip() - out_f = process.run(f'tc filter show dev {tap_device} parent ffff' + out_f = process.run(f'tc filter show dev {tap_device} parent ffff:' ).stdout_text.strip() if any([out_c, out_f]): test.fail('There should not be output of tc class/filter ' From a731b0dfeec4dcf6f382d690b9c945112a95d335 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Tue, 6 Aug 2024 23:39:46 -0400 Subject: [PATCH 0524/1055] Wait for hot-plugged virtio-mem memory allocation Signed-off-by: liang-cong-red-hat --- .../memory_devices/virtio_mem_dynamic_slots.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/libvirt/tests/src/memory/memory_devices/virtio_mem_dynamic_slots.py b/libvirt/tests/src/memory/memory_devices/virtio_mem_dynamic_slots.py index 32bbb9c8a0c..51f83b7b165 100644 --- a/libvirt/tests/src/memory/memory_devices/virtio_mem_dynamic_slots.py +++ b/libvirt/tests/src/memory/memory_devices/virtio_mem_dynamic_slots.py @@ -11,6 +11,7 @@ from avocado.utils import memory +from virttest import utils_misc from virttest import virsh from virttest import test_setup from virttest.libvirt_xml import vm_xml @@ -46,6 +47,19 @@ def run(test, params, env): """ Verify dynamic memory slots attribute works with virtio-mem memory device """ + def check_current_mem_size(mem_index, expect_current_size): + """ + Check if virtio-mem memory of mem_index has expected current memory size + + :param mem_index (int): index of the virtio-mem device + :param expect_current_size (int): expected current memory size of the virtio-mem device + + :return (bool): true virtio-mem memory of index has expected current memory size + """ + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + memory_devices = vmxml.devices.by_device_tag('memory') + return memory_devices[mem_index].target.current_size == expect_current_size + def setup_test(): """ Allocate huge page memory @@ -76,6 +90,9 @@ def run_test(): mem_obj = libvirt_vmxml.create_vm_device_by_type("memory", virtio_mem_dict) virsh.attach_device( vm.name, mem_obj.xml, wait_for_event=True, **virsh_dargs) + if not utils_misc.wait_for(lambda: check_current_mem_size(1, request_size), 20): + test.fail('Hot-plugged virtio-mem mem device should have ' + 'current memory size %d' % request_size) test.log.info("TEST_SETUP4: Check qemu-monitor-command") output = virsh.qemu_monitor_command( @@ -104,6 +121,7 @@ def teardown_test(): default_hugepage_size = memory.get_huge_page_size() allocate_size = int(params.get("allocate_size")) + request_size = int(params.get("request_size")) memory_backing = params.get("memory_backing") machine_version = params.get("machine_version") monitor_cmd = params.get("monitor_cmd") From 49406a24c72888a3b296353159af5a1a7aa5f418 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Tue, 6 Aug 2024 23:45:45 -0400 Subject: [PATCH 0525/1055] Check multiple vhost thread When interface is configured with multiple driver queues, there would be more than one process of vhost. Update test code to check all vhost thread in test. Signed-off-by: Haijiao Zhao --- .../check_vhost_cpu_affinity_with_emulatorpin.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/src/virtual_network/driver/check_vhost_cpu_affinity_with_emulatorpin.py b/libvirt/tests/src/virtual_network/driver/check_vhost_cpu_affinity_with_emulatorpin.py index ba0fba3bbd0..6cf55b086d1 100644 --- a/libvirt/tests/src/virtual_network/driver/check_vhost_cpu_affinity_with_emulatorpin.py +++ b/libvirt/tests/src/virtual_network/driver/check_vhost_cpu_affinity_with_emulatorpin.py @@ -89,16 +89,20 @@ def run(test, params, env): test.fail(f'Incorrect cpu affinity (vcpu): {cpu_affi["0"]},' f'Should be {vcpu_set}.') - pid = process.run( - "ps -eL|awk '/vhost/{print $2}'", shell=True).stdout_text.strip() + process.run("ps -eL | grep vhost", shell=True) + pids = process.run( + "ps -eL|awk '/vhost/{print $2}'", shell=True + ).stdout_text.strip().split() - check_cpu_affinity(vm_name, pid, epin_set) + for pid in pids: + check_cpu_affinity(vm_name, pid, epin_set) # Update the emulator pin to other cpu, # and check the vhost thread's cpu affinity virsh.emulatorpin(vm_name, epin_reset, **VIRSH_ARGS) - check_cpu_affinity(vm_name, pid, epin_reset) + for pid in pids: + check_cpu_affinity(vm_name, pid, epin_reset) finally: bkxml.sync() From 3c5e430cc1c9f48336a852a8fe504ac58a2588fe Mon Sep 17 00:00:00 2001 From: nanli Date: Wed, 7 Aug 2024 18:18:07 +0800 Subject: [PATCH 0526/1055] fix detach memory device event not found issue increase the memory size Signed-off-by: nanli --- .../cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg index 3c3109ae56a..d6e173a808c 100644 --- a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg @@ -8,9 +8,9 @@ target_size = "524288" size_unit = 'KiB' node = 0 - mem_value = 2097152 - current_mem = 2097152 - numa_mem = 1048576 + mem_value = 3145728 + current_mem = 3145728 + numa_mem = 1572864 max_mem = 4194304 max_mem_slots = 16 slot = '0' From 0ba6bda44a3bf74e24dbcad73d935bcd359c4605 Mon Sep 17 00:00:00 2001 From: Xiaodai Wang Date: Thu, 8 Aug 2024 14:54:53 +0800 Subject: [PATCH 0527/1055] virsh_console: add some comments to explain the code Signed-off-by: Xiaodai Wang --- libvirt/tests/src/virsh_cmd/domain/virsh_console.py | 4 ++++ spell.ignore | 1 + 2 files changed, 5 insertions(+) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_console.py b/libvirt/tests/src/virsh_cmd/domain/virsh_console.py index 58e8a7928d0..8260239537a 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_console.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_console.py @@ -132,6 +132,10 @@ def check_disconnect_on_shutdown(vm, command, status_error, login_user, log = "" console_cmd = "shutdown -h now" try: + # Do not use remote.handle_prompts here because it will inhibit + # errors. + # Login will fail if extra kernel messages are printed after login + # prompt. We should keep the failure to force QE do the check. while True: match, text = session.read_until_last_line_matches( [r"[E|e]scape character is", r"login:", diff --git a/spell.ignore b/spell.ignore index 2428d253562..7a31e2a6568 100644 --- a/spell.ignore +++ b/spell.ignore @@ -817,6 +817,7 @@ qed qem qemu qmp +QE QMP quiesce qxl From 8ad070375326112e046c161255b9cd93dd257a99 Mon Sep 17 00:00:00 2001 From: zhentang-tz Date: Wed, 7 Aug 2024 23:13:12 -0400 Subject: [PATCH 0528/1055] replace bidirectional pipe with 2 pipes (in/out) ovmf guest boot would failed when having a char device with bidirectional pipe. So replace it with 2 unidirectional pipe files Signed-off-by: zhentang-tz --- .../src/virsh_cmd/domain/virsh_attach_device.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_attach_device.py b/libvirt/tests/src/virsh_cmd/domain/virsh_attach_device.py index 01b8555b699..b8f9daacdf1 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_attach_device.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_attach_device.py @@ -463,14 +463,17 @@ class SerialPipe(SerialFile): identifier = None type_name = "pipe" + pipe_suffixes=[".in",".out"] @staticmethod def make_source(filepath): - try: - os.unlink(filepath) - except OSError: - pass - os.mkfifo(filepath) + for suffix in pipe_suffixes: + pipe_path=filepath+suffix + try: + os.unlink(pipe_path) + except OSError: + pass + os.mkfifo(pipe_path) def init_device(self, index): return super(SerialPipe, self).init_device(index) # stub for now From f8f65c6b0437d788b30533f1cea15393578b73a1 Mon Sep 17 00:00:00 2001 From: zhentang-tz Date: Thu, 8 Aug 2024 04:29:00 -0400 Subject: [PATCH 0529/1055] modify a param error move the misplaced param into method Signed-off-by: zhentang-tz --- libvirt/tests/src/virsh_cmd/domain/virsh_attach_device.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_attach_device.py b/libvirt/tests/src/virsh_cmd/domain/virsh_attach_device.py index b8f9daacdf1..fe40ae5950f 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_attach_device.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_attach_device.py @@ -463,12 +463,12 @@ class SerialPipe(SerialFile): identifier = None type_name = "pipe" - pipe_suffixes=[".in",".out"] - + @staticmethod def make_source(filepath): + pipe_suffixes= [".in",".out"] for suffix in pipe_suffixes: - pipe_path=filepath+suffix + pipe_path = filepath + suffix try: os.unlink(pipe_path) except OSError: From e924dbe7d4b0633e2528fc20abe1ff9ff286a28e Mon Sep 17 00:00:00 2001 From: zhentang-tz Date: Thu, 8 Aug 2024 04:48:35 -0400 Subject: [PATCH 0530/1055] remove spaces modified to fix format Signed-off-by: zhentang-tz --- libvirt/tests/src/virsh_cmd/domain/virsh_attach_device.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_attach_device.py b/libvirt/tests/src/virsh_cmd/domain/virsh_attach_device.py index fe40ae5950f..8e5d521306d 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_attach_device.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_attach_device.py @@ -463,10 +463,10 @@ class SerialPipe(SerialFile): identifier = None type_name = "pipe" - + @staticmethod def make_source(filepath): - pipe_suffixes= [".in",".out"] + pipe_suffixes = [".in", ".out"] for suffix in pipe_suffixes: pipe_path = filepath + suffix try: From f41c8a0798cd3b1778ada0fcb45a90a434b04b61 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Sun, 14 Jul 2024 23:32:48 -0400 Subject: [PATCH 0531/1055] Skip checking vcpuinfo when numad active Signed-off-by: liang-cong-red-hat --- .../tests/src/numa/guest_numa_topology/change_vcpu_pin.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/numa/guest_numa_topology/change_vcpu_pin.py b/libvirt/tests/src/numa/guest_numa_topology/change_vcpu_pin.py index a001bf9d750..a6f66cdcf31 100644 --- a/libvirt/tests/src/numa/guest_numa_topology/change_vcpu_pin.py +++ b/libvirt/tests/src/numa/guest_numa_topology/change_vcpu_pin.py @@ -160,7 +160,10 @@ def run_default(test_obj): test_obj.vm.wait_for_login().close() online_cpus = cpuutils.online_list() host_online_cpu_num = len(online_cpus) - verify_vcpuinfo(test_obj, online_cpus, host_online_cpu_num) + # For vcpuinfo would be impacted by numad changing cpu affinity of guest process, + # so we skip testing the numad impact. + if test_obj.params.get('numad_active') == 'no': + verify_vcpuinfo(test_obj, online_cpus, host_online_cpu_num) verify_vcpupin(test_obj, online_cpus, host_online_cpu_num) From 42e6038c8f70dcf2b8fc139431b0018cefa522d6 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Sun, 5 May 2024 23:32:49 -0400 Subject: [PATCH 0532/1055] Optimize the host node memory checking function Signed-off-by: liang-cong-red-hat --- provider/numa/numa_base.py | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/provider/numa/numa_base.py b/provider/numa/numa_base.py index 0ca1482448d..16f4188ea7e 100644 --- a/provider/numa/numa_base.py +++ b/provider/numa/numa_base.py @@ -40,6 +40,25 @@ def __init__(self, vm, params, test): self.online_nodes_withmem = self.host_numa_info.get_online_nodes_withmem().copy() self.virsh_dargs = {'ignore_status': False, 'debug': True} + def get_available_numa_nodes(self, expect_node_free_mem_min=None): + """ + Get availbe host numa nodes accroding to min free memory + + :param expect_node_free_mem_min: int, the minimum of the node free memory + :return: list, available host numa nodes + """ + expected_numa_list = self.online_nodes_withmem.copy() + if expect_node_free_mem_min: + for a_node in self.online_nodes_withmem: + node_free_mem = self.host_numa_info.read_from_node_meminfo(a_node, 'MemFree') + if int(node_free_mem) < expect_node_free_mem_min: + expected_numa_list.remove(a_node) + self.test.log.debug("Host numa node '%s' free memory is %s" + "which doesn't meet requirement", a_node, node_free_mem) + self.test.log.debug("Host numa nodes in list %s have free memory bigger than %s" % (expected_numa_list, + (str(expect_node_free_mem_min) if expect_node_free_mem_min else "0"))) + return expected_numa_list + def check_numa_nodes_availability(self, expect_nodes_num=2, expect_node_free_mem_min=None): """ Check if the host numa nodes are available for testing @@ -47,24 +66,15 @@ def check_numa_nodes_availability(self, expect_nodes_num=2, expect_node_free_mem :param expect_nodes_num: int, the number of host numa nodes :param expect_node_free_mem_min: int, the minimum of the node free memory """ - if len(self.online_nodes_withmem) < expect_nodes_num: + self.online_nodes_withmem = self.get_available_numa_nodes(expect_node_free_mem_min) + available_node_num = len(self.online_nodes_withmem) + if available_node_num < expect_nodes_num: self.test.cancel("Expect %d numa nodes at " "least, but found %d" % (expect_nodes_num, - len(self.online_nodes_withmem))) + available_node_num)) self.test.log.debug("The number of host numa node with " "memory is %s which meets the " - "requirement", len(self.online_nodes_withmem)) - if expect_node_free_mem_min: - for a_node in self.online_nodes_withmem: - free_mem_min = self.host_numa_info.read_from_node_meminfo(a_node, 'MemFree') - if int(free_mem_min) < expect_node_free_mem_min: - raise exceptions.TestError("Expect the numa node '%s' " - "free memory at least %s, " - "but found %s" % (a_node, - expect_node_free_mem_min, - free_mem_min)) - self.test.log.debug("Host numa node '%s' free memory " - "is %s which meets the requirement", a_node, free_mem_min) + "requirement", available_node_num) def setup(self, expect_nodes_num=2, expect_node_free_mem_min=None): self.check_numa_nodes_availability(expect_nodes_num, expect_node_free_mem_min) From 783c2a27a487d4cc1df1be701079655fdf2f25a1 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Tue, 6 Aug 2024 01:20:51 -0400 Subject: [PATCH 0533/1055] Increase numa memory to avoid guest start failure for lack of memory Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/memory/memory_attach_device.cfg | 2 +- libvirt/tests/cfg/memory/memory_update_device.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_attach_device.cfg b/libvirt/tests/cfg/memory/memory_attach_device.cfg index 701031386b9..f547ed22d53 100644 --- a/libvirt/tests/cfg/memory/memory_attach_device.cfg +++ b/libvirt/tests/cfg/memory/memory_attach_device.cfg @@ -16,5 +16,5 @@ vm_attrs = {'max_mem_rt': 10485760, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB', 'vcpu': 4, 'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '1048576', 'unit': 'KiB'}]}} mem_device_attrs = {'mem_model': 'virtio-mem', 'target': {'requested_unit': 'KiB', 'size': 262144, 'node': 0, 'size_unit': 'KiB', 'requested_size': 131072, 'block_unit': 'KiB', 'block_size': 2048}} aarch64: - vm_attrs = {'max_mem_rt': 10485760, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB', 'vcpu': 4, 'cpu': {'mode': 'host-passthrough', 'numa_cell': [{'id': '0', 'cpus': '0-3', 'memory': '524288', 'unit': 'KiB'}]}} + vm_attrs = {'max_mem_rt': 20971520, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB', 'vcpu': 4, 'cpu': {'mode': 'host-passthrough', 'numa_cell': [{'id': '0', 'cpus': '0-3', 'memory': '8388608', 'unit': 'KiB'}]}} mem_device_attrs = {'mem_model': 'virtio-mem', 'target': {'requested_unit': 'KiB', 'size': 1048576, 'node': 0, 'size_unit': 'KiB', 'requested_size': 524288, 'block_unit': 'KiB', 'block_size': 524288}} diff --git a/libvirt/tests/cfg/memory/memory_update_device.cfg b/libvirt/tests/cfg/memory/memory_update_device.cfg index 55b004d7baf..1f93a0644e9 100644 --- a/libvirt/tests/cfg/memory/memory_update_device.cfg +++ b/libvirt/tests/cfg/memory/memory_update_device.cfg @@ -13,7 +13,7 @@ mem_device_attrs = {'mem_model': 'virtio-mem', 'target': {'requested_unit': 'KiB', 'size': 262144, 'node': 0, 'size_unit': 'KiB', 'requested_size': 131072, 'block_unit': 'KiB', 'block_size': 2048}} requested_size = 160MiB aarch64: - vm_attrs = {'max_mem_rt': 10485760, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB', 'vcpu': 4, 'cpu': {'mode': 'host-passthrough', 'numa_cell': [{'id': '0', 'cpus': '0-3', 'memory': '524288', 'unit': 'KiB'}]}} + vm_attrs = {'max_mem_rt': 20971520, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB', 'vcpu': 4, 'cpu': {'mode': 'host-passthrough', 'numa_cell': [{'id': '0', 'cpus': '0-3', 'memory': '8388608', 'unit': 'KiB'}]}} mem_device_attrs = {'mem_model': 'virtio-mem', 'target': {'requested_unit': 'KiB', 'size': 1048576, 'node': 0, 'size_unit': 'KiB', 'requested_size': 524288, 'block_unit': 'KiB', 'block_size': 524288}} requested_size = 1048576KiB check_log_str = "MEMORY_DEVICE_SIZE_CHANGE.*virtiomem" From ac93e09280389b7de9d2ac3ef64c1309d9aee5c1 Mon Sep 17 00:00:00 2001 From: Yanqiu Zhang Date: Mon, 12 Aug 2024 01:47:40 -0400 Subject: [PATCH 0534/1055] network: revert ip6 masquerade check by nft The depending check_firewall_backend can not be approved. But new cases exist and not check rules anymore. Just skip but not fix. Signed-off-by: Yanqiu Zhang --- .../src/virtual_network/iface_network.py | 23 +++++-------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/libvirt/tests/src/virtual_network/iface_network.py b/libvirt/tests/src/virtual_network/iface_network.py index 93208b72714..9f264b962fd 100644 --- a/libvirt/tests/src/virtual_network/iface_network.py +++ b/libvirt/tests/src/virtual_network/iface_network.py @@ -11,8 +11,6 @@ from aexpect.exceptions import ExpectTimeoutError -from provider.virtual_network import network_base - from virttest import virt_vm from virttest import virsh from virttest import utils_net @@ -47,7 +45,6 @@ def run(test, params, env): vm_name = params.get("main_vm") vm = env.get_vm(vm_name) host_arch = platform.machine() - firewall_backend = network_base.check_firewall_backend() def prepare_pxe_boot(): """ @@ -449,20 +446,12 @@ def check_ipt_rules(check_ipv4=True, check_ipv6=False): if "mode" in net_forward and net_forward["mode"] == "nat" \ and nat_attrs.get('ipv6') == 'yes': - if firewall_backend == "nftables": - v6_nat_rules = [ - "tcp ip6 saddr {0} ip6 daddr != {0}.*masquerade to".format(net_ipv6), - "udp ip6 saddr {0} ip6 daddr != {0}.*masquerade to".format(net_ipv6), - "ip6 saddr {0} ip6 daddr != {0}.*masquerade".format(net_ipv6), - ] - v6_output = process.run('nft list chain ip6 libvirt_network guest_nat', shell=True).stdout_text - else: - v6_nat_rules = [ - "MASQUERADE.*tcp.*{0}.*!{0}".format(net_ipv6), - "MASQUERADE.*udp.*{0}.*!{0}".format(net_ipv6), - "MASQUERADE.*all.*{0}.*!{0}".format(net_ipv6) - ] - v6_output = process.run('ip6tables -t nat -L', shell=True).stdout_text + v6_nat_rules = [ + "MASQUERADE.*tcp.*{0}.*!{0}".format(net_ipv6), + "MASQUERADE.*udp.*{0}.*!{0}".format(net_ipv6), + "MASQUERADE.*all.*{0}.*!{0}".format(net_ipv6) + ] + v6_output = process.run('ip6tables -t nat -L', shell=True).stdout_text for rule in v6_nat_rules: if not re.search(rule, v6_output): test.fail('Rule %s missing from ip6tables output.' % rule) From 9b064f3e1999173284903aeb855ee71ff8fb3998 Mon Sep 17 00:00:00 2001 From: nanli Date: Tue, 23 Jul 2024 15:32:40 +0800 Subject: [PATCH 0535/1055] add case for virtio memory with various memory allocation and guest numa xxxx-299031 Virtio-mem device with various memory allocation and guest numa settings Signed-off-by: nanli --- ...io_mem_with_memory_allocation_and_numa.cfg | 81 ++++++++ ...tio_mem_with_memory_allocation_and_numa.py | 194 ++++++++++++++++++ provider/memory/memory_base.py | 16 ++ 3 files changed, 291 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.py diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.cfg new file mode 100644 index 00000000000..b3fd48b4a7b --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.cfg @@ -0,0 +1,81 @@ +- memory.devices.virtio_mem.memory_allocation_and_numa: + type = virtio_mem_with_memory_allocation_and_numa + no s390-virtio + start_vm = no + mem_model = "virtio-mem" + mem_value = 8388608 + current_mem = 8388608 + request_size = "512" + target_size = "512" + target_size_unit = "MiB" + request_size_unit = "MiB" + take_regular_screendumps = no + base_attrs = "'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'," + err_msg1 = "cannot use/hotplug a memory device when domain 'maxMemory' is not defined" + err_msg2 = "target NUMA node needs to be specified for memory device" + err_msg3 = "can't add memory backend as guest has no NUMA nodes configured" + required_kernel = [5.14.0,) + guest_required_kernel = [5.8.0,) + func_supported_since_libvirt_ver = (8, 0, 0) + func_supported_since_qemu_kvm_ver = (6, 2, 0) + variants memory_allocation: + - no_maxmemory: + max_attrs = "" + define_error = "${err_msg1}" + - with_maxmemory: + max_mem = 20971520 + max_attrs = '"max_mem_rt": ${max_mem}, "max_mem_rt_unit": "KiB",' + variants numa_topology: + - without_numa: + numa_attrs = "" + - with_numa: + numa_mem = 8388608 + numa_attrs = "'vcpu': 4, 'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-3', 'memory': '${numa_mem}', 'unit': 'KiB'}]}," + vm_attrs = {${base_attrs} ${max_attrs} ${numa_attrs}} + variants: + - virtio_mem_with_node: + node = 0 + virtio_mem_dict = {'mem_model': '${mem_model}', 'target': {'requested_unit': '${request_size_unit}', 'size': ${target_size}, 'node': ${node}, 'size_unit': '${target_size_unit}', 'requested_size': ${request_size}, 'block_unit': 'KiB', 'block_size': %s}} + no_maxmemory: + with_numa: + cold_plug_error = "${err_msg1}" + hot_plug_error = "${err_msg1}" + without_numa: + cold_plug_error = "${err_msg3}" + hot_plug_error = "${err_msg3}" + - virtio_mem_without_node: + virtio_mem_dict = {'mem_model': '${mem_model}', 'target': {'requested_unit': '${request_size_unit}', 'size': ${target_size}, 'size_unit': '${target_size_unit}', 'requested_size': ${request_size}, 'block_unit': 'KiB', 'block_size': %s}} + coldplug_start_error = "${err_msg1}" + with_numa: + cold_plug_error = "${err_msg1}" + with_maxmemory: + define_error = "${err_msg2}" + hot_plug_error = "${err_msg1}" + with_maxmemory: + hot_plug_error = "${err_msg2}" + cold_plug_error = "${err_msg2}" + no_maxmemory: + cold_plug_error = "${err_msg1}" + without_numa,with_numa: + hot_plug_error = "${err_msg1}" + - virtio_mem_with_exceed_size: + only without_numa.with_maxmemory + target_size = "10485760" + request_size = "256" + target_size_unit = "KiB" + virtio_mem_dict = {'mem_model': '${mem_model}', 'target': {'requested_unit': '${request_size_unit}', 'size': ${target_size}, 'size_unit': '${target_size_unit}', 'requested_size': ${request_size}, 'block_unit': 'KiB', 'block_size': %s}} + coldplug_start_error = "${err_msg2}" + with_maxmemory: + hot_plug_error = "${err_msg2}" + cold_plug_error = "${err_msg2}" + without_numa: + with_maxmemory: + define_error = "Total size of memory devices exceeds the total memory size" + variants plug_type: + - define_guest: + - cold_plug: + operation = "attach" + plug_option = " --config" + - hot_plug: + operation = "attach" + plug_option = " " diff --git a/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.py b/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.py new file mode 100644 index 00000000000..71a59b30aeb --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.py @@ -0,0 +1,194 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import re + +from avocado.utils import memory as avocado_mem + +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt + +from provider.memory import memory_base + + +def adjust_virtio_mem_size_unit(params, test): + """ + Adjust the virtio memory target size and request size to KiB unit. + + :param params: dict, test parameters + :param test: test object. + """ + target_size = int(memory_base.convert_data_size( + params.get("target_size") + params.get("target_size_unit"))) + request_size = int(memory_base.convert_data_size( + params.get("request_size") + params.get("request_size_unit"))) + + params.update({"target_size": target_size}) + params.update({"request_size": request_size}) + + test.log.debug("Convert params: target_size to be %s, request_size to be", + target_size, request_size) + + +def check_guest_xml(vm, params, test): + """ + Check guest xml. + + :param vm: vm object. + :param params: test parameters object + :param test: test object. + """ + expect_mem = int(params.get("mem_value")) + expect_curr = int(params.get("current_mem")) + memory_allocation = params.get("memory_allocation") + numa_topology = params.get("numa_topology") + no_numa_and_max_mem = \ + memory_allocation == "with_maxmemory" and numa_topology == "without_numa" + + vmxml = vm_xml.VMXML.new_from_dumpxml(vm.name) + test.log.debug("Current guest xml is %s\n", vmxml) + memory = vmxml.get_memory() + current_mem = vmxml.get_current_mem() + virtio_mem = vmxml.get_devices("memory")[0] + target = virtio_mem.target + target_size = int(target.get_size()) + target_node = target.get_node() + target_block = target.get_block_size() + target_request = target.get_requested_size() + target_current = int(target.get_current_size()) + + adjust_virtio_mem_size_unit(params, test) + + test.log.debug("Check guest memory and current memory value") + if not no_numa_and_max_mem: + expect_mem = int(params.get("mem_value")) + target_size + expect_curr = int(params.get("current_mem")) + target_current + memory_base.compare_values(test, expect_mem, memory, "memory") + memory_base.compare_values(test, expect_curr, current_mem, "current memory") + + test.log.debug("Check virtio memory size") + memory_base.compare_values(test, params.get("target_size"), + target_size, "virtio mem target size") + memory_base.compare_values(test, params.get('default_hp'), + target_block, "virtio mem block size") + memory_base.compare_values(test, params.get("request_size"), + target_request, "virtio mem request size") + memory_base.compare_values(test, params.get("request_size"), + target_current, "virtio mem current size") + if params.get("node"): + memory_base.compare_values( + test, int(params.get("node")), target_node, "numa node") + if params.get("numa_mem"): + memory_base.compare_values(test, params.get("numa_mem"), + vmxml.cpu.numa_cell[0].memory, "numa memory") + + +def run(test, params, env): + """ + Verify virtio-mem memory device works with various + memory allocation and numa setting. + """ + def run_test_define_guest(): + """ + Define guest with memory allocation and numa, virtio memory. + """ + test.log.info("TEST_STEP1: Define guest with one virtio-mem device") + try: + memory_base.define_guest_with_memory_device( + params, virtio_mem_dict, vm_attrs) + + except Exception as e: + if define_error: + if not re.search(define_error, str(e)): + test.fail("Except %s error msg, but got %s" % (define_error, e)) + else: + test.log.debug("Define guest with expected error:\n%s", e) + return + else: + test.fail("Define guest failed") + + test.log.info("TEST_STEP2: Start guest") + virsh.start(vm_name) + vm.wait_for_login().close() + + test.log.info("TEST_STEP3: Check guest memory xml") + check_guest_xml(vm, params, test) + + def run_test_cold_plug(): + """ + Check guest with various memory allocation and numa setting, + and cold plug virtio-mem memory device successfully. + """ + test.log.info("TEST_STEP1: Define guest without virtio-mem devices") + vmxml.setup_attrs(**vm_attrs) + vmxml.sync() + + test.log.info("TEST_STEP2: Cold-plug one virtio-mem device") + memory_base.plug_memory_and_check_result( + test, params, mem_dict=virtio_mem_dict, operation=operation, + expected_error=cold_plug_error, flagstr=plug_option) + if cold_plug_error: + return + + test.log.info("TEST_STEP3: Start guest and check result") + res = virsh.start(vm_name) + libvirt.check_result(res, expected_fails=coldplug_start_error) + + def run_test_hot_plug(): + """ + Check guest with various memory allocation and numa setting, + and hot plug virtio-mem memory device successfully. + """ + test.log.info("TEST_STEP1: Define guest without virtio-mem devices") + vmxml.setup_attrs(**vm_attrs) + vmxml.sync() + + test.log.info("TEST_STEP2: Start guest") + vm.start() + vm.wait_for_login().close() + + test.log.info("TEST_STEP3: Hot-plug one virtio-mem device") + memory_base.plug_memory_and_check_result( + test, params, mem_dict=virtio_mem_dict, operation=operation, + expected_error=hot_plug_error, flagstr=plug_option) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bkxml.sync() + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + memory_base.check_supported_version(params, test, vm) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + default_hugepage_size = avocado_mem.get_huge_page_size() + vm_attrs = eval(params.get('vm_attrs', '{}')) + params.update({"default_hp": default_hugepage_size}) + virtio_mem_dict = eval(params.get("virtio_mem_dict") % default_hugepage_size) + operation = params.get("operation") + plug_option = params.get("plug_option") + plug_type = params.get("plug_type") + define_error = params.get("define_error") + coldplug_start_error = params.get("coldplug_start_error") + hot_plug_error = params.get("hot_plug_error") + cold_plug_error = params.get("cold_plug_error") + + run_test = eval("run_test_%s" % plug_type) + + try: + run_test() + + finally: + teardown_test() diff --git a/provider/memory/memory_base.py b/provider/memory/memory_base.py index 3ea45906c01..377e4db1cbb 100644 --- a/provider/memory/memory_base.py +++ b/provider/memory/memory_base.py @@ -248,3 +248,19 @@ def check_mem_page_sizes(test, pg_size=None, hp_size=None, hp_list=None): if hp_list and not set(hp_list).issubset(set(supported_hp_size_list)): test.cancel("Expected huge page size list is %s, but get %s" % (hp_list, supported_hp_size_list)) + + +def compare_values(test, expected, actual, check_item=''): + """ + Compare two values are the same. + + :params test, test object. + :params expected, expected value. + :params actual, actual value. + :params check_item, the item to be checked. + """ + if expected != actual: + test.fail("Expect %s to get '%s' instead of '%s' " % ( + check_item, expected, actual)) + else: + test.log.debug("Check %s %s PASS", check_item, actual) From eb8e3563d55894d66d061ff3f77f613d3f18e434 Mon Sep 17 00:00:00 2001 From: nanli Date: Sun, 4 Aug 2024 22:40:50 +0800 Subject: [PATCH 0536/1055] add case for virtio mem with numa node tunning xxxx-299159 Virtio-mem memory device with numa node tuning Signed-off-by: nanli --- .../virtio_memory_with_numa_node_tuning.cfg | 60 +++ .../virtio_memory_with_numa_node_tuning.py | 462 ++++++++++++++++++ provider/memory/memory_base.py | 16 + 3 files changed, 538 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_devices/virtio_memory_with_numa_node_tuning.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/virtio_memory_with_numa_node_tuning.py diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_memory_with_numa_node_tuning.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_memory_with_numa_node_tuning.cfg new file mode 100644 index 00000000000..332583d7f61 --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_memory_with_numa_node_tuning.cfg @@ -0,0 +1,60 @@ +- memory.devices.virtio.with_numa_tuning: + no s390-virtio + type = virtio_memory_with_numa_node_tuning + start_vm = "yes" + mem_model = "virtio-mem" + allocate_huge_mem = "1048576KiB" + allocate_huge_mem_1 = "2097152KiB" + hugepage_path = "/dev/hugepages-%s" + kernel_hp_tmpl_file = "/sys/devices/system/node/node%s/hugepages/hugepages-%skB/nr_hugepages" + memory_backing_dict = "'mb': {'hugepages': {'pages': [{'size': '%s','unit': 'KiB','nodeset':'0'}]}}" + base_attrs = "'vcpu': 4, 'memory_unit':'KiB','memory':2097152,'current_mem':2097152" + numa_attrs = "'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '1048576', 'unit': 'KiB'},{'id':'1','cpus': '2-3','memory':'1048576','unit':'KiB'}]}" + max_attrs = "'max_mem_rt': 15242880, 'max_mem_rt_slots': 16" + required_kernel = [5.14.0,) + guest_required_kernel = [5.8.0,) + func_supported_since_libvirt_ver = (8, 0, 0) + func_supported_since_qemu_kvm_ver = (6, 2, 0) + variants numa_tuning: + - strict: + tuning_mode = "strict" + mode_attrs = "'numa_memory': {'mode': '${tuning_mode}','nodeset': '%s'}," + memnode_mode = "interleave" + numa_memnode = "'numa_memnode':[{'cellid': '0', 'mode': '${memnode_mode}', 'nodeset': '%s'}]" + - interleave: + tuning_mode = "interleave" + mode_attrs = "'numa_memory': {'mode': '${tuning_mode}','nodeset': '%s'}," + memnode_mode = "preferred" + numa_memnode = "'numa_memnode':[{'cellid': '0', 'mode': '${memnode_mode}', 'nodeset': '%s'}]" + - preferred: + tuning_mode = "preferred" + memnode_mode = "strict" + mode_attrs = "'numa_memory': {'mode': '${tuning_mode}','nodeset': '%s'}," + numa_memnode = "'numa_memnode':[{'cellid': '0', 'mode': '${memnode_mode}', 'nodeset': '%s'}]" + - undefined: + mode_attrs = "" + numa_memnode = "" + tuning_attrs = "${mode_attrs}${numa_memnode}" + vm_attrs = {${memory_backing_dict},${base_attrs}, ${numa_attrs}, ${max_attrs}, ${tuning_attrs}} + variants case: + - with_source_virtio_mem: + request_size = 1048576 + target_size = 1048576 + virtio_mem_1 = {'mem_model': '${mem_model}', 'source': {'nodemask': '1', 'pagesize': %s, 'pagesize_unit': 'KiB'},'target': {'size': ${target_size}, 'node': 1, 'requested_size': ${request_size}, 'block_size': %s}} + virtio_mem_2 = {'mem_model': '${mem_model}', 'source': {'nodemask': '0', 'pagesize': %s, 'pagesize_unit': 'KiB'},'target': {'size': ${target_size}, 'node': 0, 'requested_size': ${request_size}, 'block_size': %s}} + virtio_mem_list = [${virtio_mem_1}, ${virtio_mem_2}] + - no_source_virtio_mem: + target_size_1 = 524288 + kernel_extra_params_add = "memhp_default_state=online_movable" + virtio_mem_1 = {'mem_model': '${mem_model}', 'target': {'size': ${target_size_1}, 'node': 1, 'requested_size': 524288, 'block_size': %s}} + virtio_mem_2 = {'mem_model': '${mem_model}', 'target': {'size': 1048576, 'node': 0, 'requested_size': 1048576, 'block_size': %s}} + virtio_mem_list = [${virtio_mem_1}, ${virtio_mem_2}] + - requested_bigger_than_host_numa: + request_size = 2097152 + target_size = 2097152 + virtio_mem_list = [{'mem_model': '${mem_model}', 'target': {'size': ${target_size}, 'node': 0, 'requested_size': ${request_size}, 'block_size':%s}}] + variants operation: + - cold_plug: + attach_option = "--config" + - hot_plug: + attach_option = " " diff --git a/libvirt/tests/src/memory/memory_devices/virtio_memory_with_numa_node_tuning.py b/libvirt/tests/src/memory/memory_devices/virtio_memory_with_numa_node_tuning.py new file mode 100644 index 00000000000..3fce77bf768 --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/virtio_memory_with_numa_node_tuning.py @@ -0,0 +1,462 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import copy +import re + +from avocado.utils import memory +from avocado.utils import process + +from virttest import virsh +from virttest import test_setup +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirtd import Libvirtd +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_libvirt import libvirt_memory + +from provider.memory import memory_base +from provider.numa import numa_base + +virsh_dargs = {"ignore_status": False, "debug": True} +default_hugepage_size = memory.get_huge_page_size() + + +def get_two_hugepage_sizes(test, params): + """ + Get two huge page sizes + + :param test: test object + :param params: Dictionary with the test parameters + :return default_hugepage_size, current default hugepage size value + max(hugepage_sizes), the max hugepage size that is closed to upper_limit and + different from default hugepage size. + """ + upper_limit = params.get("upper_limit", 1048576) + + hpc = test_setup.HugePageConfig(params) + supported_hugepage_size = hpc.get_multi_supported_hugepage_size() + supported_hugepage_size.remove(str(default_hugepage_size)) + + hugepage_sizes = [] + for size in supported_hugepage_size: + if upper_limit % int(size) == 0: + hugepage_sizes.append(int(size)) + + test.log.debug("Get default huge page size:%s, another huge page size %s", + default_hugepage_size, max(hugepage_sizes)) + + return default_hugepage_size, max(hugepage_sizes) + + +def _allocate_huge_memory(params, test, allocate_mem, + hugepage_size, hugepage_path=None): + """ + Allocate hugepage memory. + + :param params: Dictionary with the test parameters + :param test: test object. + :param allocate_mem, total allocate memory on each numa node. + :param hugepage_size: the hugepage size to allocate. + :param hugepage_path: the hugepage path to allocate. + """ + kernel_hp_file = params.get("kernel_hp_tmpl_file") + cleanup_file = params.get("cleanup_file", []) + + target_nodes = params.get("numa_obj").online_nodes_withmem + params.update({"all_nodes": target_nodes}) + + test.log.debug("Allocate %sKiB on %s pagesize", allocate_mem, hugepage_size) + params.update({'target_nodes': ' '.join(str(n) for n in target_nodes)}) + for node in target_nodes: + params.update({ + 'target_num_node%s' % node: allocate_mem / hugepage_size}) + params.update( + {"kernel_hp_file": kernel_hp_file % (node, hugepage_size)}) + cleanup_file.append(params.get("kernel_hp_file")) + params.update({"cleanup_file": cleanup_file}) + + hpc = test_setup.HugePageConfig(params) + hpc.hugepage_size = hugepage_size + if hugepage_path: + hpc.hugepage_path = hugepage_path % hugepage_size + params.update({"hg_path": hpc.hugepage_path}) + else: + # Give a always mounted path to avoid mount in HugePageConfig + hpc.hugepage_path = '/' + hpc.setup() + Libvirtd().restart() + + +def allocate_huge_memory(params, test): + """ + Allocate hugepage memory with two hugepage sizes on each numa node. + + :param params: instance of avocado params class + :param test: test object. + """ + hugepage_path = params.get("hugepage_path") + default_hp_size = params.get("default_hp_size") + another_hp_size = params.get("another_hp_size") + allocate_huge_mem = int(re.findall(r"\d+", params.get("allocate_huge_mem"))[0]) + allocate_huge_mem_1 = int(re.findall(r"\d+", params.get("allocate_huge_mem_1"))[0]) + + _allocate_huge_memory( + params, test, allocate_huge_mem, default_hp_size) + _allocate_huge_memory( + params, test, allocate_huge_mem_1, another_hp_size, hugepage_path) + + params.update( + {"allocate_mem_and_hp_match": {default_hp_size: allocate_huge_mem, + another_hp_size: allocate_huge_mem_1}}) + + +def create_vm_attrs(params): + """ + Create vm defined attrs. + + :param params: instance of avocado params class + """ + vm_attrs = params.get('vm_attrs', '{}') + another_hp_size = params.get("another_hp_size") + with_numa_tuning = params.get("numa_tuning") != "undefined" + + if with_numa_tuning: + all_nodes = params.get('all_nodes') + define_attrs = eval( + vm_attrs % (another_hp_size, all_nodes[0], all_nodes[1])) + else: + define_attrs = eval(vm_attrs % another_hp_size) + + return define_attrs + + +def create_mem_objects(params): + """ + create memory objects list. + + :param params: instance of avocado params class + :return mem_obj: memory objects list. + """ + case = params.get("case") + virtio_mem_list = params.get("virtio_mem_list") + default_hp_size = params.get("default_hp_size") + another_hp_size = params.get("another_hp_size") + block_size = max(default_hp_size, another_hp_size) + + if case == "with_source_virtio_mem": + virtio_mem_list = virtio_mem_list % ( + default_hp_size, default_hp_size, another_hp_size, block_size) + elif case == "no_source_virtio_mem": + virtio_mem_list = virtio_mem_list % (default_hp_size, block_size) + elif case == "requested_bigger_than_host_numa": + virtio_mem_list = virtio_mem_list % block_size + + mem_obj = [] + for mem in eval(virtio_mem_list): + obj = libvirt_vmxml.create_vm_device_by_type("memory", mem) + mem_obj.append(obj) + + return mem_obj + + +def plug_virtio_mem(params, vm, operation, mem_obj_list): + """ + Hot plug or Cold plug memory + + :param params: dictionary with the test parameters. + :param vm: vm object. + :param operation: flag for hot plugging or cold plugging. + :param mem_obj_list: memory device object list to plug. + """ + vm_name = params.get("main_vm") + attach_option = params.get("attach_option") + + if operation == "cold_plug": + pass + elif operation == "hot_plug": + vm.start() + vm.wait_for_login().close() + + for mem in mem_obj_list: + virsh.attach_device(vm_name, mem.xml, flagstr=attach_option, + **virsh_dargs) + + +def consume_guest_mem(vm, test): + """ + Consume guest memory + + :param vm, vm object + :param test: test instance. + """ + if not vm.is_alive(): + vm.start() + + session = vm.wait_for_login() + status, output = libvirt_memory.consume_vm_freememory(session) + if status: + test.fail("Fail to consume guest memory. Got error:%s" % output) + session.close() + + +def check_numa_memory_allocation(params, test, dest_size): + """ + Check the numa node memory. + + :param params: dictionary with the test parameters. + :param test: test instance + :param dest_size: target size of virtio mem device + """ + all_nodes = params.get('all_nodes') + + numa_maps = numa_base.get_host_numa_memory_alloc_info(dest_size) + N0_value = re.findall(r'N%s=(\d+)' % all_nodes[0], numa_maps) + N1_value = re.findall(r'N%s=(\d+)' % all_nodes[1], numa_maps) + if not N0_value: + test.fail( + "The numa_maps should include 'N%s=', but not found" % all_nodes[0]) + if N1_value: + test.fail( + "The numa_maps should not include 'N%s=', but found" % all_nodes[1]) + + +def _get_freepages(node, pagesize): + """ + Get virsh freepages for each node and pagesize + + :param node: host numa node value. + :param pagesize: hugepage size value. + :return free pages number + """ + res = virsh.freepages(node, pagesize, debug=True).stdout_text + return int(res.split()[-1]) + + +def _get_another_node(params, node): + """ + Get another numa node except current node + + :param params: dictionary with the test parameters. + :param node: current node. + :return another numa node except current node. + """ + all_nodes = params.get("all_nodes") + nodes = copy.deepcopy(all_nodes) + nodes.remove(node) + + return nodes[0] + + +def _get_left_mem(vm, params, test, host_numa_node, hp_size): + """ + Get specific host numa node left memory value for specific hugepage size + + :param vm: vm object + :param params: dict wrapped with params + :param test: test object + :param host_numa_node: host numa node + :param hp_size: hugepage size + """ + with_numa_tuning = params.get("numa_tuning") != "undefined" + match = params.get("allocate_mem_and_hp_match") + each_node_total_mem = match[hp_size] + used_mem = 0 + vmxml = vm_xml.VMXML.new_from_dumpxml(vm.name) + + # Get memory backing hugepage size + mb_pagesize = int(vmxml.mb.hugepages.pages[0]['size']) + mb_guest_node = int(vmxml.mb.hugepages.pages[0]['nodeset']) + + # Calculate virtio memory used memory. + for mem in vmxml.devices.by_device_tag('memory'): + requested = mem.target.requested_size + mem_attrs = mem.fetch_attrs() + mem_source = mem_attrs.get("source") + if mem_source: + used_host_numa_node = int(mem_source['nodemask']) + used_pagesize = int(mem_source['pagesize']) + else: + guest_node = int(mem_attrs['target']['node']) + used_pagesize = mb_pagesize + used_host_numa_node = '' + if guest_node == mb_guest_node: + if with_numa_tuning: + used_host_numa_node = _get_another_node(params, guest_node) + + else: + used_host_numa_node = guest_node + + if host_numa_node == used_host_numa_node and used_pagesize == hp_size: + used_mem += requested + + # Calculate numa topology used memory. + if with_numa_tuning: + used_host_numa_node = _get_another_node(params, mb_guest_node) + else: + used_host_numa_node = mb_guest_node + if host_numa_node == used_host_numa_node and mb_pagesize == hp_size: + for cell in vmxml.cpu.numa_cell: + if int(cell.id) == mb_guest_node: + used_mem += int(cell.memory) + + test.log.debug("Get left memory:%s for %s hugepage size " + "on host numa node:%s", int(each_node_total_mem - used_mem), + hp_size, host_numa_node) + + return each_node_total_mem - used_mem + + +def get_expected_freepages(vm, params, test, hugepage_size): + """ + Get the expected freepages for two numa nodes. + + :param vm: vm object + :param params: dict wrapped with params + :param test: test object + :param hugepage_size: huge page size + """ + all_nodes = params.get("all_nodes") + vmxml = vm_xml.VMXML.new_from_dumpxml(vm.name) + numa_tuning = params.get("numa_tuning") + numa_memnode = vmxml.numa_memnode[0]['mode'] if numa_tuning != "undefined" else '' + + fp0 = int(_get_left_mem( + vm, params, test, all_nodes[0], hugepage_size) / hugepage_size) + fp1 = int(_get_left_mem( + vm, params, test, all_nodes[1], hugepage_size) / hugepage_size) + + fp_list = [fp0, fp1] + for index, fp in enumerate(fp_list): + if numa_memnode == "strict" and fp < 0: + # Check if used virtio memory over total numa node memory, and with + # strict numa mem mode, it will not use another numa node memory and + # get 0 free pages. + fp_list[index] = 0 + return sum(fp_list) + + +def check_freepages(params, vm, test): + """ + Check host free pages. + + :param params: dict wrapped with params + :param vm: vm object + :param test: test object + """ + all_nodes = params.get('all_nodes') + another_hp_size = params.get("another_hp_size") + no_numa_tuning = params.get("numa_tuning") == "undefined" + bigger_requested = params.get("case") == "requested_bigger_than_host_numa" + + for node, hp in zip(all_nodes+all_nodes, params.get("hp_list")): + if hp == another_hp_size and (no_numa_tuning or bigger_requested): + expected_freepages = get_expected_freepages(vm, params, test, hp) + actual_freepages = _get_freepages(all_nodes[0], hp) + _get_freepages(all_nodes[1], hp) + check_item = f"node{all_nodes} hugepage size:{hp} free pages number" + else: + expected_freepages = int(_get_left_mem(vm, params, test, node, hp) / hp) + actual_freepages = _get_freepages(node, hp) + check_item = f"node{node} hugepage size:{hp} free pages number" + + memory_base.compare_values( + test, + expected_freepages, + actual_freepages, + check_item=check_item + ) + + +def run(test, params, env): + """ + 1.Define guest with virtio-mem devices. + 2.Attach virtio-mem and check memory usage by virsh freepages. + """ + def setup_test(): + """ + Check available numa nodes num. + """ + test.log.info("TEST_SETUP: Check available numa nodes num") + params.get("numa_obj").check_numa_nodes_availability() + + test.log.info("TEST_SETUP: Allocate hugepage memory") + allocate_huge_memory(params, test) + + def run_test(): + """ + Define guest, check xml, check memory + """ + test.log.info("TEST_STEP: Define guest with numa") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + define_attrs = create_vm_attrs(params) + vmxml.setup_attrs(**define_attrs) + vmxml.sync() + + test.log.info("TEST_STEP: Plug virtio memory devices.") + mem_objs = create_mem_objects(params) + plug_virtio_mem(params, vm, operation, mem_objs) + + test.log.info("TEST_STEP:Login the guest and consume guest memory") + consume_guest_mem(vm, test) + + test.log.info("TEST_STEP: Check the memory usage by virsh freepages") + check_freepages(params, vm, test) + + if case == "no_source_virtio_mem" and numa_tuning != "undefined": + test.log.info("TEST_STEP: Check host numa node memory") + check_numa_memory_allocation(params, test, target_size_1) + + test.log.info("TEST_STEP: Destroy the guest") + virsh.destroy(vm_name, ignore_status=False) + + test.log.info("TEST_STEP: Check freepages after destroying the guest") + all_nodes = params.get("all_nodes") + for node, hp in zip(all_nodes + all_nodes, params.get("hp_list")): + memory_base.compare_values( + test, + expected=params.get("allocate_mem_and_hp_match")[hp]/hp, + actual=_get_freepages(node, hp), + check_item=f"node{node} hugepage size:{hp} free pages number" + ) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bkxml.sync() + for file in params.get("cleanup_file"): + process.run("echo 0 > %s" % file) + hg_path = params.get("hg_path") + if hg_path: + process.run("umount %s; rm %s" % (hg_path, hg_path), ignore_status=True) + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + memory_base.check_supported_version(params, test, vm) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + case = params.get("case") + numa_tuning = params.get("numa_tuning") + operation = params.get("operation") + target_size_1 = params.get("target_size_1") + + params.update({"numa_obj": numa_base.NumaTest(vm, params, test)}) + default_hp_size, another_hp_size = get_two_hugepage_sizes(test, params) + params.update({"default_hp_size": default_hp_size}) + params.update({"another_hp_size": another_hp_size}) + params.update({"hp_list": [default_hp_size, default_hp_size, + another_hp_size, another_hp_size]}) + + try: + setup_test() + run_test() + + finally: + teardown_test() diff --git a/provider/memory/memory_base.py b/provider/memory/memory_base.py index e0595a05a46..68d5c47ceed 100644 --- a/provider/memory/memory_base.py +++ b/provider/memory/memory_base.py @@ -254,3 +254,19 @@ def check_mem_page_sizes(test, pg_size=None, hp_size=None, hp_list=None): if hp_list and not set(hp_list).issubset(set(supported_hp_size_list)): test.cancel("Expected huge page size list is %s, but get %s" % (hp_list, supported_hp_size_list)) + + +def compare_values(test, expected, actual, check_item=''): + """ + Compare two values are the same. + + :params test, test object. + :params expected, expected value. + :params actual, actual value. + :params check_item, the item to be checked. + """ + if expected != actual: + test.fail("Expect %s to get '%s' instead of '%s' " % ( + check_item, expected, actual)) + else: + test.log.debug("Check %s %s PASS", check_item, actual) From a01894db2ef29f8cdff0df20179ffdbfa13af3ed Mon Sep 17 00:00:00 2001 From: root Date: Mon, 5 Aug 2024 08:48:20 -0400 Subject: [PATCH 0537/1055] vm_start_destroy_repeatedly: Refinement Ran test 'vm_start_destroy_repeatedly' multiple times, and fixed some test-script related errors Signed-off-by: slancast --- libvirt/tests/cfg/vm_start_destroy_repeatedly.cfg | 3 ++- libvirt/tests/src/vm_start_destroy_repeatedly.py | 13 +++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/cfg/vm_start_destroy_repeatedly.cfg b/libvirt/tests/cfg/vm_start_destroy_repeatedly.cfg index b4e510f38e9..909c7a4a102 100644 --- a/libvirt/tests/cfg/vm_start_destroy_repeatedly.cfg +++ b/libvirt/tests/cfg/vm_start_destroy_repeatedly.cfg @@ -1,4 +1,5 @@ - vm_start_destroy_repeatedly: type = vm_start_destroy_repeatedly - num_cycles = 2000 + num_cycles = 3000 start_vm = no + test_timeout = 288000 diff --git a/libvirt/tests/src/vm_start_destroy_repeatedly.py b/libvirt/tests/src/vm_start_destroy_repeatedly.py index 366e25f56b1..4aae9f1f113 100644 --- a/libvirt/tests/src/vm_start_destroy_repeatedly.py +++ b/libvirt/tests/src/vm_start_destroy_repeatedly.py @@ -1,5 +1,4 @@ import logging -import time from virttest import virsh from virttest import utils_misc @@ -23,10 +22,10 @@ def power_cycle_vm(test, vm, vm_name, login_timeout, startup_wait, resume_wait): """ virsh.start(vm_name, options="--paused", ignore_status=False) - time.sleep(startup_wait) + utils_misc.wait_for(lambda: vm.state() == "paused", startup_wait) virsh.resume(vm_name, ignore_status=False) - time.sleep(resume_wait) + utils_misc.wait_for(lambda: vm.state() == "running", resume_wait) session = vm.wait_for_login(timeout=login_timeout) session.close() @@ -51,10 +50,12 @@ def run(test, params, env): vm = env.get_vm(vm_name) num_cycles = int(params.get("num_cycles")) # Parameter to control the number of times to start/restart the vm login_timeout = float(params.get("login_timeout", 240)) # Controls vm.wait_for_login() timeout - startup_wait = float(params.get("startup_wait", 2)) # Controls wait time for virsh.start() - resume_wait = float(params.get("resume_wait", 40)) # Controls wait for virsh.resume() + startup_wait = float(params.get("startup_wait", 240)) # Controls wait time for virsh.start() + resume_wait = float(params.get("resume_wait", 240)) # Controls wait for virsh.resume() for i in range(num_cycles): logging.info("Starting vm '%s' -- attempt #%d", vm_name, i+1) + power_cycle_vm(test, vm, vm_name, login_timeout, startup_wait, resume_wait) - logging.info("\t-> Completed vm '%s' power cycle #%d", vm_name, i+1) + + logging.info("Completed vm '%s' power cycle #%d", vm_name, i+1) From f96f23d9704c498f4e9c74debe2dbac3addf32fc Mon Sep 17 00:00:00 2001 From: Slancaster1 Date: Tue, 13 Aug 2024 13:38:16 -0400 Subject: [PATCH 0538/1055] vcpu_metrics.py: Set number of queues for interface - The Problem libvirt does not support more than one interface queue for hosts using If the xml that is being used for this test sets the number of queues higher, then the test will fail. - Solution By removing the part of the XML that sets the number of queues. Libvirt can default to a working number of queues Signed-off-by: Slancaster1 --- libvirt/tests/src/cpu/vcpu_metrics.py | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/src/cpu/vcpu_metrics.py b/libvirt/tests/src/cpu/vcpu_metrics.py index 2bcaa863171..5baf6944915 100644 --- a/libvirt/tests/src/cpu/vcpu_metrics.py +++ b/libvirt/tests/src/cpu/vcpu_metrics.py @@ -130,6 +130,7 @@ def setup_with_unprivileged_user(vm, params, test): test.log.debug("Remove 'dac' security driver for unprivileged user") vmxml.del_seclabel(by_attr=[('model', 'dac')]) libvirt_vmxml.modify_vm_device(vmxml, 'interface', interface_attrs) + vmxml.xmltreefile.remove_by_xpath("/devices/interface/driver", True) boot_disk = vmxml.devices.by_device_tag('disk')[0] first_disk_source = boot_disk.fetch_attrs()['source']['attrs']['file'] unprivileged_boot_disk_path = os.path.join(unprivileged_boot_disk_path, os.path.basename(first_disk_source)) From b16678a047bbd78ec216cd0b4661975b6c00ad07 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Sun, 26 May 2024 23:24:55 -0400 Subject: [PATCH 0539/1055] Add new case of update interface portgroup - VIRT-294740 - [update-device][portgroup] Update interface portgroup for nat and bridge network(Qos) Signed-off-by: Haijiao Zhao --- .../update_device/update_iface_portgroup.cfg | 17 +++ .../update_device/update_iface_portgroup.py | 117 ++++++++++++++++++ spell.ignore | 1 + 3 files changed, 135 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/update_device/update_iface_portgroup.cfg create mode 100644 libvirt/tests/src/virtual_network/update_device/update_iface_portgroup.py diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_iface_portgroup.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_iface_portgroup.cfg new file mode 100644 index 00000000000..d4748a4aa6c --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/update_device/update_iface_portgroup.cfg @@ -0,0 +1,17 @@ +- virtual_network.update_device.iface_portgroup.qos: + type = update_iface_portgroup + start_vm = no + timeout = 240 + host_iface = + pg_a = {'default': 'yes', 'name': 'sales', 'bandwidth_inbound': {'average': '100', 'peak': '200', 'burst': '512'}, 'bandwidth_outbound': {'average': '50', 'peak': '100', 'burst': '256'}} + pg_b = {'name': 'engineering', 'bandwidth_inbound': {'average': '200', 'peak': '300', 'burst': '256'}, 'bandwidth_outbound': {'average': '100', 'peak': '200', 'burst': '128'}} + pg_attrs = {'portgroups': [${pg_a}, ${pg_b}]} + update_attrs = {'portgroup': 'engineering'} + variants net_type: + - nat: + net_attrs = ${pg_attrs} + - linux_br: + net_attrs = {'name': net_name, 'forward': {'mode': 'bridge'}, 'bridge': {'name': br_name}, **${pg_attrs}} + - ovs_br: + net_attrs = {'name': net_name, 'forward': {'mode': 'bridge'}, 'virtualport_type': 'openvswitch', 'bridge': {'name': br_name}, **${pg_attrs}} + iface_attrs = {'model': 'virtio', 'type_name': 'network', 'source': {'network': net_name}} diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_portgroup.py b/libvirt/tests/src/virtual_network/update_device/update_iface_portgroup.py new file mode 100644 index 00000000000..fc05f9089bf --- /dev/null +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_portgroup.py @@ -0,0 +1,117 @@ +import logging + +from avocado.utils import process +from virttest import utils_misc +from virttest import utils_net +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.network_xml import NetworkXML +from virttest.utils_libvirt import libvirt_network +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Update interface portgroup for nat and bridge network(Qos) + + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + + rand_id = utils_misc.generate_random_string(3) + net_type = params.get('net_type', '') + br_name = net_type + '_' + rand_id + net_name = params.get('net_type') + '_' + rand_id + net_attrs = eval(params.get('net_attrs', '{}')) + pg_a = eval(params.get('pg_a', '{}')) + pg_b = eval(params.get('pg_b', '{}')) + update_attrs = eval(params.get('update_attrs', '{}')) + + net_name = 'default' if 'name' not in net_attrs else net_name + iface_attrs = eval(params.get('iface_attrs', '{}')) + + host_iface = params.get('host_iface') + host_iface = host_iface if host_iface else utils_net.get_net_if( + state="UP")[0] + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + net_xml = NetworkXML.new_from_net_dumpxml('default') + bk_net_xml = net_xml.copy() + + try: + LOG.info('Create bridge for test.') + if net_type == 'linux_br': + utils_net.create_linux_bridge_tmux(br_name, host_iface) + process.run(f'ip l show type bridge {br_name}', shell=True) + elif net_type == 'ovs_br': + utils_net.create_ovs_bridge(br_name) + + if 'name' in net_attrs: + libvirt_network.create_or_del_network(net_attrs) + virsh.net_dumpxml(net_attrs['name'], **VIRSH_ARGS) + else: + net_xml.setup_attrs(**net_attrs) + net_xml.sync() + LOG.debug(f'Network xml of default: {net_xml}') + + vmxml.del_device('interface', by_tag=True) + iface = libvirt_vmxml.create_vm_device_by_type( + 'interface', iface_attrs) + libvirt.add_vm_device(vmxml, iface) + LOG.debug(f'VMXMLof {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + iface = network_base.get_iface_xml_inst(vm_name, '1st on vm') + mac = iface.mac_address + + vm.start() + network_base.get_iface_xml_inst(vm_name, 'on vm after vm start') + tap_device = libvirt.get_ifname_host(vm_name, mac) + LOG.debug(f'tap device on host with mac {mac} is: {tap_device}.') + + if not utils_net.check_class_rules( + tap_device, '1:1', pg_a['bandwidth_inbound']): + test.fail('class rule check failed') + if not utils_net.check_filter_rules( + tap_device, pg_a['bandwidth_outbound']): + test.fail('filter rule check failed') + + # Update device + update_attrs = {'source': {**iface_attrs['source'], **update_attrs}} + LOG.debug(f'Update iface with attrs: {update_attrs}') + iface.setup_attrs(**update_attrs) + iface.xmltreefile.write() + + LOG.debug(f'Update iface with xml: {iface}') + virsh.update_device(vm_name, iface.xml, **VIRSH_ARGS) + + # Check updated iface xml + iface_update = network_base.get_iface_xml_inst(vm_name, 'after update') + if iface_update.source.get( + 'portgroup') != update_attrs['source']['portgroup']: + test.fail('Update iface xml portgroup failed') + + # Check rules + if not utils_net.check_class_rules( + tap_device, '1:1', pg_b['bandwidth_inbound']): + test.fail('class rule check failed-') + if not utils_net.check_filter_rules( + tap_device, pg_b['bandwidth_outbound']): + test.fail('filter rule check failed-') + + finally: + bkxml.sync() + bk_net_xml.sync() + if 'name' in net_attrs: + libvirt_network.create_or_del_network(net_attrs, is_del=True) + if net_type == 'linux_br': + utils_net.delete_linux_bridge_tmux(br_name, host_iface) + if net_type == 'ovs_br': + utils_net.delete_ovs_bridge(br_name) diff --git a/spell.ignore b/spell.ignore index d4f4440882f..a71ea8dfc1f 100644 --- a/spell.ignore +++ b/spell.ignore @@ -815,6 +815,7 @@ qem qemu qmp QMP +qos quiesce qxl QXL From de0c35be84951f72eee3b0244256cae682a51a22 Mon Sep 17 00:00:00 2001 From: Lili Zhu Date: Wed, 14 Aug 2024 22:11:56 -0400 Subject: [PATCH 0540/1055] Update the command line of cache_mode Bug RHEL-50329 had been fixed, we should update script accordingly. Signed-off-by: Lili Zhu --- libvirt/tests/src/virtual_device/filesystem_device.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_device/filesystem_device.py b/libvirt/tests/src/virtual_device/filesystem_device.py index 9f09c4b1fd7..a8153682414 100644 --- a/libvirt/tests/src/virtual_device/filesystem_device.py +++ b/libvirt/tests/src/virtual_device/filesystem_device.py @@ -43,7 +43,10 @@ def generate_expected_process_option(): """ expected_results = "" if cache_mode != "auto": - expected_results += "cache(\s|=)%s" % cache_mode + if cache_mode == "none": + expected_results += "cache(\s|=)(none|never)" + else: + expected_results += "cache(\s|=)%s" % cache_mode if xattr == "on": expected_results += "(\s--|,)xattr" elif xattr == "off" and not libvirt_version.version_compare(10, 5, 0): From 19658c14a81dcfd9e7535c718ae6bc6ff755e4ab Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Mon, 1 Jul 2024 23:03:05 -0400 Subject: [PATCH 0541/1055] Add net work case of qos - VIRT-296328 - [Qos] Check the actual network throughput for direct type interface Signed-off-by: Haijiao Zhao --- ...check_actual_network_throughput_direct.cfg | 18 +++ .../check_actual_network_throughput_direct.py | 127 ++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput_direct.cfg create mode 100644 libvirt/tests/src/virtual_network/qos/check_actual_network_throughput_direct.py diff --git a/libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput_direct.cfg b/libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput_direct.cfg new file mode 100644 index 00000000000..ef704d5599f --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput_direct.cfg @@ -0,0 +1,18 @@ +- virtual_network.qos.check_actual_network_throughput.direct: + type = check_actual_network_throughput_direct + start_vm = no + vm2_name = vm2 + vms = avocado-vt-vm1 vm2 + timeout = 240 + host_iface = + inbound = {'average': '128', 'peak': '1024', 'burst': '32'} + outbound = {'average': '128', 'peak': '1024', 'burst': '32'} + iface_bw_attrs = {'bandwidth': {'inbound': ${inbound}, 'outbound': ${outbound}}} + variants: + - with_network: + net_attrs = {'name': net_name, 'forward_interface': [{'dev': host_iface}], 'forward': {'mode': 'bridge'}} + iface_attrs = {'type_name': 'network', 'source': {'network': net_name}, 'model': 'virtio', **${iface_bw_attrs}} + iface_attrs_2 = {'type_name': 'network', 'source': {'network': net_name}, 'model': 'virtio'} + - without_network: + iface_attrs = {'type_name': 'direct', 'source': {'dev': host_iface, 'mode': 'bridge'}, 'model': 'virtio', **${iface_bw_attrs}} + iface_attrs_2 = {'type_name': 'direct', 'source': {'dev': host_iface, 'mode': 'bridge'}, 'model': 'virtio'} diff --git a/libvirt/tests/src/virtual_network/qos/check_actual_network_throughput_direct.py b/libvirt/tests/src/virtual_network/qos/check_actual_network_throughput_direct.py new file mode 100644 index 00000000000..649013f6968 --- /dev/null +++ b/libvirt/tests/src/virtual_network/qos/check_actual_network_throughput_direct.py @@ -0,0 +1,127 @@ +import logging + +from virttest import utils_misc +from virttest import utils_net +from virttest import utils_package +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.staging import service +from virttest.utils_libvirt import libvirt_network +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Check the actual network throughput for direct type interface + + """ + vm_name = params.get('main_vm') + vm2_name = params.get('vm2_name') + vm = env.get_vm(vm_name) + vm2 = env.get_vm(vm2_name) + rand_id = utils_misc.generate_random_string(3) + net_name = 'net_' + rand_id + host_iface = params.get('host_iface') + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] + iface_attrs = eval(params.get('iface_attrs', '{}')) + iface_attrs_2 = eval(params.get('iface_attrs_2', '{}')) + net_attrs = eval(params.get('net_attrs', '{}')) + inbound = eval(params.get('inbound')) + outbound = eval(params.get('outbound')) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + vmxml_2 = vm_xml.VMXML.new_from_inactive_dumpxml(vm2_name) + bkxml_2 = vmxml_2.copy() + firewalld = service.Factory.create_service("firewalld") + + try: + + if 'name' in net_attrs: + libvirt_network.create_or_del_network(net_attrs) + virsh.net_dumpxml(net_attrs['name'], **VIRSH_ARGS) + + mac = network_base.get_iface_xml_inst( + vm_name, f'on VM:{vm_name}').mac_address + mac_2 = network_base.get_iface_xml_inst( + vm2_name, f'on VM:{vm2_name}').mac_address + iface_attrs.update({'mac_address': mac}) + iface_attrs_2.update({'mac_address': mac_2}) + + vmxml.del_device('interface', by_tag=True) + libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs) + LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + vmxml_2.del_device('interface', by_tag=True) + libvirt_vmxml.modify_vm_device(vmxml_2, 'interface', iface_attrs_2) + LOG.debug( + f'VMXML of {vm2_name}:\n{virsh.dumpxml(vm2_name).stdout_text}') + + vm.start() + vm_sess = vm.wait_for_serial_login() + + vm2.start() + vm_sess_2 = vm2.wait_for_serial_login() + + network_base.get_iface_xml_inst(vm_name, f'on VM:{vm_name}') + network_base.get_iface_xml_inst(vm2_name, f'on VM:{vm2_name}') + + tap_device = libvirt.get_ifname_host(vm_name, mac) + LOG.debug(f'tap device on host with mac {mac} is: {tap_device}.') + + tc_args = [tap_device, '1:1', iface_attrs['bandwidth']['outbound']] + filter_bw = iface_attrs['bandwidth']['inbound'] + + if not utils_net.check_class_rules(*tc_args): + test.fail('Class rule check failed. Please check log.') + LOG.debug('Class rule check: PASS') + + if not utils_net.check_filter_rules(tc_args[0], filter_bw): + test.fail('Filter rule check failed. Please check log.') + LOG.debug('Filter rule check: PASS') + + if not utils_package.package_install('netperf', session=vm_sess): + test.error(f'Failed to install netperf on VM:{vm_name}.') + if not utils_package.package_install('netperf', session=vm_sess_2): + test.error(f'Failed to install netperf on VM:{vm2_name}.') + + vm_sess.close() + vm_sess = vm.wait_for_serial_login() + vm_sess_2.close() + vm_sess_2 = vm2.wait_for_serial_login() + + vm_ip = network_base.get_vm_ip(vm_sess, mac) + vm_ip_2 = network_base.get_vm_ip(vm_sess_2, mac_2) + LOG.debug(f'Vm {vm_name} ip address: {vm_ip}\n' + f'Vm {vm2_name} ip address: {vm_ip_2}') + + firewalld.stop() + vm_sess.cmd('systemctl stop firewalld') + vm_sess_2.cmd('systemctl stop firewalld') + + network_base.check_throughput( + vm_sess.cmd, vm_sess_2.cmd, + vm_ip, outbound["average"], 'outbound' + ) + + network_base.check_throughput( + vm_sess_2.cmd, + vm_sess.cmd, vm_ip_2, inbound["average"], 'inbound' + ) + vm_sess.close() + vm_sess_2.close() + + finally: + bkxml.sync() + bkxml_2.sync() + if 'name' in net_attrs: + libvirt_network.create_or_del_network(net_attrs, is_del=True) + firewalld.start() From 431759397cb7d2e3575752a5e9ebd16afb8fc082 Mon Sep 17 00:00:00 2001 From: lcheng Date: Fri, 16 Aug 2024 13:47:03 +0800 Subject: [PATCH 0542/1055] migration: Update migration_poweroff_vm case Add a new attribute in test matrix part: New attribute NBD non-NBD Signed-off-by: lcheng --- .../migration_poweroff_vm.cfg | 35 ++++++++++++------- .../migration_poweroff_vm.py | 19 +++++++++- 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/libvirt/tests/cfg/migration/guest_lifecycle_operations_during_migration/migration_poweroff_vm.cfg b/libvirt/tests/cfg/migration/guest_lifecycle_operations_during_migration/migration_poweroff_vm.cfg index fa12a1e9d16..b204b0898c2 100644 --- a/libvirt/tests/cfg/migration/guest_lifecycle_operations_during_migration/migration_poweroff_vm.cfg +++ b/libvirt/tests/cfg/migration/guest_lifecycle_operations_during_migration/migration_poweroff_vm.cfg @@ -1,11 +1,6 @@ - migration.guest_lifecycle_operations_during_migration.migration_poweroff_vm: type = migration_poweroff_vm migration_setup = 'yes' - storage_type = 'nfs' - setup_local_nfs = 'yes' - disk_type = "file" - disk_source_protocol = "netfs" - mnt_path_name = ${nfs_mount_dir} # Console output can only be monitored via virsh console output only_pty = True take_regular_screendumps = no @@ -20,6 +15,9 @@ server_ip = "${migrate_dest_host}" server_user = "root" server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" status_error = "yes" check_network_accessibility_after_mig = "yes" migrate_desturi_port = "16509" @@ -27,11 +25,10 @@ stress_package = "stress" stress_args = "--cpu 8 --io 4 --vm 2 --vm-bytes 128M --timeout 20s" virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" - action_during_mig = '[{"func": "libvirt_network.check_established", "after_event": "iteration: '1'", "func_param": 'params'}, {"func": "poweroff_vm", "func_param": "params", "need_sleep_time": "70"}]' err_msg = "error: operation failed: domain is not running" - virsh_migrate_extra = "--bandwidth 5" test_case = "poweroff_vm" - + action_during_mig = '[{"func": "poweroff_vm", "func_param": "params", "need_sleep_time": "70"}]' + virsh_migrate_src_state = "shut off" variants: - p2p: virsh_migrate_options = '--live --p2p --verbose' @@ -39,8 +36,22 @@ virsh_migrate_options = '--live --verbose' variants: - with_precopy: - virsh_migrate_src_state = "shut off" - with_postcopy: - postcopy_options = '--postcopy --timeout 10 --timeout-postcopy --postcopy-bandwidth 5' - virsh_migrate_src_state = "paused" - poweroff_vm_dest = "yes" + postcopy_options = '--postcopy --timeout 5 --timeout-postcopy --postcopy-bandwidth 5' + variants: + - nbd: + virsh_migrate_extra = "--bandwidth 5 --copy-storage-all --migrate-disks vda" + setup_nfs = "no" + nfs_mount_dir = + setup_local_nfs = "no" + storage_type = "" + - non_nbd: + virsh_migrate_extra = "--bandwidth 5" + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + with_postcopy: + poweroff_vm_dest = "yes" + virsh_migrate_src_state = "paused" diff --git a/libvirt/tests/src/migration/guest_lifecycle_operations_during_migration/migration_poweroff_vm.py b/libvirt/tests/src/migration/guest_lifecycle_operations_during_migration/migration_poweroff_vm.py index e75fea420c2..841eaf826df 100644 --- a/libvirt/tests/src/migration/guest_lifecycle_operations_during_migration/migration_poweroff_vm.py +++ b/libvirt/tests/src/migration/guest_lifecycle_operations_during_migration/migration_poweroff_vm.py @@ -25,6 +25,7 @@ def setup_poweroff_vm(): test.log.info("Setup for poweroff vm.") migrate_desturi_port = params.get("migrate_desturi_port") migrate_desturi_type = params.get("migrate_desturi_type", "tcp") + virsh_migrate_extra = params.get("virsh_migrate_extra") if migrate_desturi_type: migration_obj.conn_list.append(migration_base.setup_conn_obj(migrate_desturi_type, params, test)) @@ -33,6 +34,9 @@ def setup_poweroff_vm(): migration_obj.remote_add_or_remove_port(migrate_desturi_port) libvirt.set_vm_disk(vm, params) + if "copy-storage-all" in virsh_migrate_extra: + base_steps.prepare_disks_remote(params, vm) + if not vm.is_alive(): vm.start() vm_session = vm.wait_for_login() @@ -57,6 +61,17 @@ def verify_poweroff_vm(): test.log.info("Guest state is '%s' at source is as expected", vm_state_src) migration_obj.verify_default() + def cleanup_poweroff_vm(): + """ + Cleanup for poweroff vm + + """ + virsh_migrate_extra = params.get("virsh_migrate_extra") + + if "copy-storage-all" in virsh_migrate_extra: + base_steps.cleanup_disks_remote(params, vm) + migration_obj.cleanup_connection() + test_case = params.get('test_case', '') vm_name = params.get("migrate_main_vm") @@ -67,10 +82,12 @@ def verify_poweroff_vm(): locals() else migration_obj.setup_connection verify_test = eval("verify_%s" % test_case) if "verify_%s" % test_case in \ locals() else migration_obj.verify_default + cleanup_test = eval("cleanup_%s" % test_case) if "cleanup_%s" % test_case in \ + locals() else migration_obj.cleanup_connection try: setup_test() migration_obj.run_migration() verify_test() finally: - migration_obj.cleanup_connection() + cleanup_test() From 67afd0f0a5781cf7f3f72f8b55b247789298694a Mon Sep 17 00:00:00 2001 From: Meina Li Date: Fri, 16 Aug 2024 05:23:41 -0400 Subject: [PATCH 0543/1055] Virtual_disk: fix "unable to open /dev/sdb" error For virtual_disks.multiattributes.block_disk.start_guest, the created sdb disk usually doesn't exist because of known exception. So change to use scsi_debug to setup scsi disk to test. Signed-off-by: Meina Li --- .../tests/src/virtual_disks/virtual_disks_multiattributes.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_multiattributes.py b/libvirt/tests/src/virtual_disks/virtual_disks_multiattributes.py index 56d0dccbd5b..6a9293d422a 100644 --- a/libvirt/tests/src/virtual_disks/virtual_disks_multiattributes.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_multiattributes.py @@ -44,8 +44,7 @@ def update_bootable_disk(vm, vmxml, disk_obj, params): disk_obj.add_vm_disk(disk_type, disk1_dict, bootable_raw_image) image_list.append(bootable_raw_image) if disk_type == "block": - device = libvirt.setup_or_cleanup_iscsi(is_setup=True, - image_size='10G') + device = libvirt.create_scsi_disk(scsi_option="", scsi_size="10240") cmd = "qemu-img convert -f qcow2 %s -O raw %s; sync" % (bootable_image, device) process.run(cmd, ignore_status=False, shell=True) disk_dict.update({'source': {'attrs': {'dev': device}}}) @@ -115,7 +114,7 @@ def run(test, params, env): finally: bkxml.sync() if disk_type == "block": - libvirt.setup_or_cleanup_iscsi(is_setup=False) + libvirt.delete_scsi_disk() if image_list: for image in image_list: if os.path.exists(image): From 051f667c69c46dbbc3e7d87b52f1619394ef003e Mon Sep 17 00:00:00 2001 From: nanli Date: Thu, 8 Aug 2024 14:18:31 +0800 Subject: [PATCH 0544/1055] fix checking nvdimm target issue remove other unrelated attrs Signed-off-by: nanli --- ...lifecycle_for_file_backed_nvdimm_memory.py | 38 +++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/src/memory/memory_devices/lifecycle_for_file_backed_nvdimm_memory.py b/libvirt/tests/src/memory/memory_devices/lifecycle_for_file_backed_nvdimm_memory.py index 44f8a64bb2f..bae4536330b 100644 --- a/libvirt/tests/src/memory/memory_devices/lifecycle_for_file_backed_nvdimm_memory.py +++ b/libvirt/tests/src/memory/memory_devices/lifecycle_for_file_backed_nvdimm_memory.py @@ -22,6 +22,22 @@ from provider.memory import memory_base +def delete_extra_attr(dict1, dict2): + """ + Delete extra different attributes between two dictionaries. + + :param dict1, first dictionary. + :param dict2, second dictionary. + """ + keys_to_remove = set(dict1.keys()).symmetric_difference(set(dict2.keys())) + for key in keys_to_remove: + if key in dict1: + del dict1[key] + if key in dict2: + del dict2[key] + return dict1, dict2 + + def check_nvdimm_config(params, test, mem_index=0): """ Check nvdimm memory devices xml config. @@ -31,6 +47,7 @@ def check_nvdimm_config(params, test, mem_index=0): :param mem_index: memory index in memory list, default 0. """ address_config = params.get("address_config") + expected_access = params.get("access") addr_slot = [params.get("addr_slot"), params.get("addr_slot_attach")] addr_base = [params.get("addr_base"), params.get("addr_base_attach")] alias_name = eval(params.get("alias_name", "[]")) @@ -42,18 +59,25 @@ def check_nvdimm_config(params, test, mem_index=0): vmxml = vm_xml.VMXML.new_from_dumpxml(params.get("main_vm")) actual_attrs = vmxml.devices.by_device_tag('memory')[mem_index].fetch_attrs() test.log.debug("Get actual memory attrs: %s", actual_attrs) + delete_extra_attr(source[mem_index], actual_attrs['source']) + delete_extra_attr(target[mem_index], actual_attrs['target']) - def _compare_values(expected, actual): + def _compare_values(expected, actual, check_item=''): if expected != actual: test.fail("Expect to get '%s' instead of '%s' " % (expected, actual)) else: - test.log.debug("Check %s PASS", actual) - _compare_values(source[mem_index], actual_attrs['source']) - _compare_values(target[mem_index], actual_attrs['target']) - _compare_values(alias_name[mem_index], actual_attrs['alias']['name']) + test.log.debug("Check %s=%s PASS", check_item, actual) + + # check nvdimm memory device source and target config + _compare_values(source[mem_index], actual_attrs['source'], 'source attrs') + _compare_values(target[mem_index], actual_attrs['target'], 'target attrs') + + # check nvdimm memory device alias, access mode and address config + _compare_values(alias_name[mem_index], actual_attrs['alias']['name'], 'alias') + _compare_values(expected_access, actual_attrs['mem_access'], 'access mode') if address_config != "addr_undefined": - _compare_values(addr_slot[mem_index], actual_attrs['address']['attrs']['slot']) - _compare_values(addr_base[mem_index], actual_attrs['address']['attrs']['base']) + _compare_values(addr_slot[mem_index], actual_attrs['address']['attrs']['slot'], 'addr slot') + _compare_values(addr_base[mem_index], actual_attrs['address']['attrs']['base'], 'addr base') def check_nvdimm_device_content(test, params, session, expected_content, From 9a11ab01c6a200ae67f74fff73f429f4ca3b7319 Mon Sep 17 00:00:00 2001 From: Vera Wu Date: Sat, 17 Aug 2024 10:37:04 +0800 Subject: [PATCH 0545/1055] v2v:fix v2v-options failed case Signed-off-by: Vera Wu --- v2v/tests/cfg/v2v_options.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/v2v/tests/cfg/v2v_options.cfg b/v2v/tests/cfg/v2v_options.cfg index 084eedebb54..8927c8eafb9 100644 --- a/v2v/tests/cfg/v2v_options.cfg +++ b/v2v/tests/cfg/v2v_options.cfg @@ -333,6 +333,7 @@ expect_msg = yes msg_content = "Remove 1 Package" - required_patch: + version_required = "(,virt-v2v-2.4.0-1)" check_command = "rpm -q --changelog %s" checkpoint = check_patch - print_estimate: From e722ea0e347e9927ad043308a68263ffb93de6eb Mon Sep 17 00:00:00 2001 From: Vera Wu Date: Mon, 19 Aug 2024 10:31:18 +0800 Subject: [PATCH 0546/1055] v2v: fix rhel10 failed case of convt-from-file Signed-off-by: Vera Wu --- v2v/tests/cfg/convert_from_file.cfg | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/v2v/tests/cfg/convert_from_file.cfg b/v2v/tests/cfg/convert_from_file.cfg index 235911d61a1..1546632d79f 100644 --- a/v2v/tests/cfg/convert_from_file.cfg +++ b/v2v/tests/cfg/convert_from_file.cfg @@ -291,15 +291,15 @@ # genid only supports libvirt, local, qemu only output_mode.libvirt - latest8: - only esx_80 - main_vm = 'VM_NAME_RHEL8_V2V_EXAMPLE' + only esx_70 + main_vm = 'VM_NAME_ESX70_RHEL8_V2V_EXAMPLE' - latest7: - only esx_80 - main_vm = 'VM_NAME_RHEL7_V2V_EXAMPLE' + only esx_70 + main_vm = 'VM_NAME_ESX70_RHEL7_V2V_EXAMPLE' - latest6: enable_legacy_policy = yes - only esx_80 - main_vm = 'VM_NAME_RHEL6_V2V_EXAMPLE' + only esx_70 + main_vm = 'VM_NAME_ESX70_RHEL6_V2V_EXAMPLE' - cpu_topology: only esx_70 only output_mode.rhev From 9a9e30693e95f597215140d951b7e7d6477b031c Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Sun, 18 Aug 2024 22:28:24 -0400 Subject: [PATCH 0547/1055] Automate virtlogd maxclients related cases xx-59118,xx-86131,xx-86144,xx-86515 Signed-off-by: chunfuwen --- .../conf_file/qemu_conf/set_virtlogd.cfg | 69 ++++ .../conf_file/qemu_conf/set_virtlogd.py | 353 +++++++++++++++++- 2 files changed, 414 insertions(+), 8 deletions(-) diff --git a/libvirt/tests/cfg/daemon/conf_file/qemu_conf/set_virtlogd.cfg b/libvirt/tests/cfg/daemon/conf_file/qemu_conf/set_virtlogd.cfg index 250b3cf987c..808f5723212 100644 --- a/libvirt/tests/cfg/daemon/conf_file/qemu_conf/set_virtlogd.cfg +++ b/libvirt/tests/cfg/daemon/conf_file/qemu_conf/set_virtlogd.cfg @@ -72,11 +72,80 @@ expected_result = record_save_restore_guest_log start_vm = no save_vm_path = "/tmp/test1.save" + - valid_max_clients: + expected_result = valid_max_clients + max_clients = 20 + start_vm = no + action = "restart" + virtlogd_log_file = "/var/log/libvirt/virtlogd.log" + - valid_boundary_max_clients: + expected_result = valid_boundary_max_clients + low_max_clients = 0 + high_max_clients = 4294967295 + start_vm = no + virtlogd_log_file = "/var/log/libvirt/virtlogd.log" + action = "restart" + - nclients_occupied_released: + expected_result = nclients_occupied_released + max_clients = 20 + virtlogd_log_file = "/var/log/libvirt/virtlogd.log" + nclients = 'nclients=1.*nclients_unauth=0' + save_vm_path = "/tmp/test1.save" + action = "restart" + start_vm = no + - guest_runnning_after_virtlogd_crash: + expected_result = guest_runnning_after_virtlogd_crash + start_vm = no + stdio_handler = "logd" + - reload_new_config: + expected_result = reload_new_config + start_vm = no + action = "reload" + virtlogd_file_new = "/var/log/libvirt/virtlogd_new.log" + virtlogd_log_file = "/var/log/libvirt/virtlogd.log" + - log_filters_not_same_with_loglevel: + expected_result = log_filters_not_same_with_loglevel + start_vm = no + action = "restart" + filter_loglevel_1 = "debug.*virLogDaemonClientFree" + filter_loglevel_2 = "info.*virEventGLibHandleUpdate" + filter_loglevel_3 = "debug.*virNetServerProgramNew" + filter_loglevel_4 = "error : virPidFileAcquirePath" + log_filters = "1:+logging 2:event 3:rpc" + log_level = 4 + virtlogd_file = "/var/log/libvirt/virtlogd.log" + - reload_max_size_config: + expected_result = reload_max_size_config + start_vm = no + action = "reload" + max_size = 204800 + - set_max_size_config: + expected_result = set_max_size_config + start_vm = no + action = "restart" + max_size = 204800 + - set_max_backups: + expected_result = set_max_backups + max_backups = 2 + start_vm = no + action = "restart" + - reload_max_backups: + expected_result = reload_max_backups + max_backups = 4 + max_size = 204800 + action = "reload" + start_vm = no - negative_test: variants: - invalid: expected_result = unbootable stdio_handler = 'invalid' + - invalid_boundary_max_clients: + expected_result = invalid_boundary_max_clients + low_max_clients = -1 + high_max_clients = 4294967296 + start_vm = no + action = "restart" - invalid_virtlogd_conf: start_vm = no expected_result = 'invalid_virtlogd_conf' diff --git a/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py b/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py index 5fcbaec4238..c80f4de93a1 100644 --- a/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py +++ b/libvirt/tests/src/daemon/conf_file/qemu_conf/set_virtlogd.py @@ -13,6 +13,7 @@ from virttest import utils_libvirtd from virttest import utils_package from virttest import utils_split_daemons +from virttest import utils_misc from virttest import virt_vm from virttest import virsh @@ -232,6 +233,12 @@ def enable_virtlogd_specific_config_file(): Configure virtlogd using specific config file. """ + virtlogd_config_file = params.get("virtlogd_config_file") + virtlogd_config_bak_file = params.get("virtlogd_config_bak_file") + if os.path.exists(virtlogd_config_file): + # backup config file + os.rename(virtlogd_config_file, virtlogd_config_bak_file) + virtlogd_config_file_new = params.get("virtlogd_config_file_new") with open(virtlogd_config_file, "w") as fd: fd.write('VIRTLOGD_ARGS="--config /etc/libvirt/virtlogd-new.conf"') fd.write('\n') @@ -255,6 +262,7 @@ def check_virtlogd_started_with_config(): """ cmd = "ps -fC 'virtlogd'" cmd_result = process.run(cmd, shell=True).stdout_text.strip() + virtlogd_config_file_new = params.get("virtlogd_config_file_new") matched_message = "--config %s" % virtlogd_config_file_new if matched_message not in cmd_result: test.fail("Check virtlogd is started with config :%s failed in output:%s" @@ -272,6 +280,12 @@ def enable_virtlogd_timeout(): Configure virtlogd using timeout parameter. """ + virtlogd_config_file = params.get("virtlogd_config_file") + virtlogd_config_bak_file = params.get("virtlogd_config_bak_file") + if os.path.exists(virtlogd_config_file): + # backup config file + os.rename(virtlogd_config_file, virtlogd_config_bak_file) + with open(virtlogd_config_file, "w") as fd: fd.write('VIRTLOGD_ARGS="--timeout=30"') fd.write('\n') @@ -542,6 +556,314 @@ def check_record_save_restore_guest_log(): test.fail("Check VM save and restore message log:%s failed in log file:%s" % (vm_save_restore_msg, guest_log_file)) + def set_valid_max_clients(max_clients, check_max_clients=True): + """ + set valid max clients in virtlogd config file + + :param max_clients: max clients in integer + :param check_max_clients: boolean value indicating whether need check max clients value + """ + virtlogd_log_file = params.get("virtlogd_log_file") + if os.path.exists(virtlogd_log_file): + truncate_log_file(virtlogd_log_file, '0') + virtlogd_config.log_level = 1 + virtlogd_config.log_outputs = f"1:file:{virtlogd_log_file}" + virtlogd_config.max_clients = max_clients + action = params.get("action") + process.run("systemctl %s virtlogd" % action, ignore_status=True, shell=True) + cmd = ("systemctl status virtlogd | grep 'Active: active'") + ret = process.run(cmd, **debug_param) + if ret.exit_status != 0: + test.fail("virtlogd is not in active from log:%s" % ret.stdout_text.strip()) + + if check_max_clients: + vm.start() + vm.wait_for_login().close() + nclients_max_msg = "nclients_max=%s" % max_clients + if not libvirt.check_logfile(nclients_max_msg, virtlogd_log_file): + test.fail("Check VM nclients max value :%s failed in log file:%s" + % (nclients_max_msg, virtlogd_log_file)) + + def check_valid_max_clients(): + """ + Check whether virtlogd can work normally when set valid max clients + + """ + max_clients = params.get("max_clients") + set_valid_max_clients(max_clients) + + def check_valid_boundary_max_clients(): + """ + Check whether virtlogd can work normally when set valid boundary max clients + + """ + max_clients = params.get("low_max_clients") + set_valid_max_clients(max_clients, check_max_clients=False) + max_clients = params.get("high_max_clients") + set_valid_max_clients(max_clients) + + def check_nclients_occupied_released(): + """ + Check connection clients value can be reflected when VM is different life cycle state + + """ + max_clients = params.get("max_clients") + set_valid_max_clients(max_clients) + + save_path = params.get("save_vm_path") + virsh.save(vm_name, save_path) + nclients_msg = params.get("nclients") + virtlogd_log_file = params.get("virtlogd_log_file") + if not libvirt.check_logfile(nclients_msg, virtlogd_log_file): + test.fail("Check nclients value after save :%s failed in log file:%s" + % (nclients_msg, virtlogd_log_file)) + + truncate_log_file(virtlogd_log_file, '0') + virsh.restore(save_path) + vm.wait_for_login().close() + if not libvirt.check_logfile(nclients_msg, virtlogd_log_file): + test.fail("Check nclients value after restore :%s failed in log file:%s" + % (nclients_msg, virtlogd_log_file)) + + def check_invalid_boundary_max_clients(): + """ + Check whether virtlogd can work normally when set invalid boundary max clients + + """ + virtlogd_config.max_clients = params.get("low_max_clients") + cmd = ("systemctl status virtlogd | grep 'Active: active'") + ret = process.run(cmd, **debug_param) + if ret.exit_status != 0: + test.fail("virtlogd is not in active from log:%s" % ret.stdout_text.strip()) + + def _restart_virtlogd(): + """ + restart virtlogd and check its state + """ + action = params.get("action") + process.run("systemctl %s virtlogd" % action, ignore_status=True, shell=True) + time.sleep(4) + cmd = ("systemctl status virtlogd | grep 'Active: failed'") + result = process.run(cmd, ignore_status=True, shell=True, verbose=True) + if result.exit_status != 0: + test.fail("virtlogd is not in failed state from output: %s" % result.stdout_text.strip()) + + _restart_virtlogd() + virtlogd_config.max_clients = params.get("high_max_clients") + _restart_virtlogd() + + def check_guest_runnning_after_virtlogd_crash(): + """ + Check whether guest still in running after virtlogd crash + + """ + vm.start() + vm.wait_for_login().close() + utils_package.package_install(['lsof']) + lsof_output = lsof_qemu_log_file() + if "virtlogd" not in lsof_output: + test.fail("virtlogd does not open qemu log file:%s" + % guest_log_file) + + before_pid_virtlogd = process.getoutput("pidof virtlogd") + process.run(f'kill -9 {before_pid_virtlogd}', **debug_param) + + after_pid_virtlogd = process.getoutput("pidof virtlogd") + if after_pid_virtlogd: + test.fail(f"virtlogd: {after_pid_virtlogd} is not killed as expected") + vm.wait_for_login().close() + + def check_reload_new_config(virtlogd_config): + """ + Check whether new virtlogd configuration can be reloaded + + :param virtlogd_config: virtlogd configuration file + """ + virtlogd_file_new = params.get("virtlogd_file_new") + virtlogd_log_file = params.get("virtlogd_log_file") + virtlogd_config.log_level = 2 + virtlogd_config.log_filters = "1:+rpc" + virtlogd_config.log_outputs = f"1:file:{virtlogd_file_new}" + + action = params.get("action") + process.run("systemctl %s virtlogd" % action, ignore_status=True, shell=True) + time.sleep(4) + + if not os.path.exists(virtlogd_file_new): + test.fail(f"Failed to reload new virtlogd file: {virtlogd_file_new} specified in config") + + vm.start() + vm.wait_for_login().close() + rpm_msg = "debug.*virNetSocketNew" + if not libvirt.check_logfile(rpm_msg, virtlogd_file_new): + test.fail("Check rpc message :%s failed in log file:%s" + % (rpm_msg, virtlogd_log_file)) + + def check_log_filters_not_same_with_loglevel(): + """ + Check whether new virtlogd filter configuration can work as expected + + """ + virtlogd_file = params.get("virtlogd_file") + virtlogd_service = service.Factory.create_service("virtlogd") + virtlogd_service.stop() + if os.path.exists(virtlogd_file): + truncate_log_file(virtlogd_file, '0') + + virtlogd_config.log_level = params.get("log_level") + virtlogd_config.log_filters = params.get("log_filters") + virtlogd_config.log_outputs = f"1:file:{virtlogd_file}" + + action = params.get("action") + process.run("systemctl %s virtlogd" % action, ignore_status=True, shell=True) + time.sleep(4) + + vm.start() + vm.wait_for_login().close() + + filter_loglevel_1 = params.get("filter_loglevel_1") + filter_loglevel_2 = params.get("filter_loglevel_2") + filter_loglevel_4 = params.get("filter_loglevel_4") + process.run("virtlogd", ignore_status=True, shell=True) + for log_level in [filter_loglevel_1, filter_loglevel_2, filter_loglevel_4]: + if not libvirt.check_logfile(log_level, virtlogd_file): + test.fail("Check related message :%s failed in log file:%s" + % (log_level, virtlogd_file)) + + filter_loglevel_3 = params.get("filter_loglevel_3") + if not libvirt.check_logfile(filter_loglevel_3, virtlogd_file, str_in_log=False): + test.fail("Find unexpected event message:%s in log file:%s" + % (filter_loglevel_3, virtlogd_file)) + + def remove_backup_logfiles(): + """ + Clean up backup log files + + """ + file_list = glob.glob('%s/%s.log.*' % (QEMU_LOG_PATH, vm_name)) + for file_name in file_list: + if os.path.exists(file_name): + os.remove(file_name) + + def set_max_size_in_virtlogd_config(): + """ + set max_size in virtlogd config + + """ + max_size = params.get("max_size") + max_backups = params.get("max_backups", 3) + virtlogd_config.__option_types__.update({'max_size': 'int'}) + virtlogd_config.__option_types__.update({'max_backups': 'int'}) + if max_size: + virtlogd_config.max_size = max_size + virtlogd_config.max_backups = max_backups + + logging.info("take actions to make new virtlogd config effective") + action = params.get("action") + process.run("systemctl %s virtlogd" % action, **debug_param) + + def wait_until_file_present(file_path): + """ + wait for certain time until file is present + + :param file_path: file path + """ + def _file_present(): + vm.start() + vm.wait_for_login().close() + vm.destroy() + return os.path.exists(file_path) + + utils_misc.wait_for(lambda: _file_present(), timeout=300) + + def check_reload_max_size_config(): + """ + Check whether new max size configuration can take effect after reload + + """ + vm.start() + vm.wait_for_login().close() + vm.destroy() + + remove_backup_logfiles() + truncate_log_file(guest_log_file, '180K') + + set_max_size_in_virtlogd_config() + + guest_log = "%s/%s.log.0" % (QEMU_LOG_PATH, vm_name) + wait_until_file_present(guest_log) + + ls_file_size_cmd = "ls -lh %s/%s.log*" % (QEMU_LOG_PATH, vm_name) + output = process.run(ls_file_size_cmd, **debug_param).stdout_text + if "200K" not in output: + test.fail(f"max size not take effect after reload") + + def check_set_max_size_config(): + """ + Check whether new max size configuration can take effect after set + + """ + check_reload_max_size_config() + + def ls_log_files(): + """ + ls all logs files,and check total numbers + + """ + max_backups = int(params.get("max_backups")) + time_start = 0 + time_end = 60 + max_backup_plus_one = max_backups + 1 + while time_start <= time_end: + ls_logfile_number_cmd = "ls -lh %s/%s.log* | wc -l" % (QEMU_LOG_PATH, vm_name) + number = process.run(ls_logfile_number_cmd, **debug_param).stdout_text.strip() + if max_backup_plus_one != int(number): + test.fail(f"actual logs files number: {number} is not equals to expected:{max_backup_plus_one}") + time.sleep(10) + time_start += 20 + + def check_set_max_backups(): + """ + Check whether backup files has exact numbers as described in max_backup + + """ + vm.start() + vm.wait_for_login().close() + vm.destroy() + + remove_backup_logfiles() + truncate_log_file(guest_log_file, '3M') + + set_max_size_in_virtlogd_config() + + max_backups = int(params.get("max_backups")) + for index in range(max_backups): + guest_log = "%s/%s.log.%d" % (QEMU_LOG_PATH, vm_name, index) + wait_until_file_present(guest_log) + truncate_log_file(guest_log_file, '3M') + ls_log_files() + + def check_reload_max_backups(): + """ + Check whether backup files has exact numbers as reloading configuration + + """ + vm.start() + vm.wait_for_login().close() + vm.destroy() + + remove_backup_logfiles() + truncate_log_file(guest_log_file, '180K') + + set_max_size_in_virtlogd_config() + + max_backups = int(params.get("max_backups")) + for index in range(max_backups): + guest_log = "%s/%s.log.%d" % (QEMU_LOG_PATH, vm_name, index) + wait_until_file_present(guest_log) + truncate_log_file(guest_log_file, '180K') + ls_log_files() + vm_name = params.get("main_vm", "avocado-vt-vm1") expected_result = params.get("expected_result", "virtlogd_disabled") stdio_handler = params.get("stdio_handler", "not_set") @@ -552,6 +874,8 @@ def check_record_save_restore_guest_log(): stop_libvirtd = "yes" == params.get("stop_libvirtd", "no") with_spice = "yes" == params.get("with_spice", "no") with_console_log = "yes" == params.get("with_console_log", "no") + pipe_node = None + debug_param = {'ignore_status': True, 'shell': True, 'verbose': True} vm = env.get_vm(vm_name) vm_xml = VMXML.new_from_inactive_dumpxml(vm_name) @@ -586,6 +910,8 @@ def check_record_save_restore_guest_log(): 'with stdio_handler=%s' % stdio_handler) if not start_vm: + if vm.is_alive(): + vm.destroy(gracefully=False) if reload_virtlogd: reload_and_check_virtlogd() elif expected_result == 'virtlogd_restart': @@ -619,13 +945,6 @@ def check_record_save_restore_guest_log(): ret = process.run(cmd, ignore_status=True, shell=True) if not ret.exit_status: test.fail("virtlogd still exist.") - elif expected_result in ['virtlogd_specific_config_file_enable', 'specific_timeout']: - virtlogd_config_file = params.get("virtlogd_config_file") - virtlogd_config_bak_file = params.get("virtlogd_config_bak_file") - if os.path.exists(virtlogd_config_file): - # backup config file - os.rename(virtlogd_config_file, virtlogd_config_bak_file) - virtlogd_config_file_new = params.get("virtlogd_config_file_new") elif expected_result == 'virtlogd_specific_config_file_enable': enable_virtlogd_specific_config_file() check_virtlogd_started_with_config() @@ -654,6 +973,14 @@ def check_record_save_restore_guest_log(): check_start_vm_twice_log_into_qemu_log_file() elif expected_result == "record_save_restore_guest_log": check_record_save_restore_guest_log() + elif expected_result in ["valid_max_clients", "valid_boundary_max_clients", "nclients_occupied_released", + "invalid_boundary_max_clients", "guest_runnning_after_virtlogd_crash" + "log_filters_not_same_with_loglevel", "reload_max_size_config", "set_max_size_config", + "set_max_backups", "reload_max_backups"]: + check_test = eval("check_%s" % expected_result) + check_test() + elif expected_result == "reload_new_config": + check_reload_new_config(virtlogd_config) else: # Stop all VMs if VMs are already started. for tmp_vm in env.get_all_vms(): @@ -781,8 +1108,13 @@ def check_record_save_restore_guest_log(): finally: config.restore() libvirtd.restart() + if vm.is_alive(): + vm.destroy(gracefully=False) vm_xml_backup.sync() if expected_result in ['virtlogd_specific_config_file_enable', 'specific_timeout']: + virtlogd_config_file = params.get("virtlogd_config_file") + virtlogd_config_bak_file = params.get("virtlogd_config_bak_file") + virtlogd_config_file_new = params.get("virtlogd_config_file_new") if os.path.exists(virtlogd_config_file): os.remove(virtlogd_config_file) if os.path.exists(virtlogd_config_file_new): @@ -791,6 +1123,11 @@ def check_record_save_restore_guest_log(): if os.path.exists(virtlogd_config_file): os.rename(virtlogd_config_bak_file, virtlogd_config_file) service.Factory.create_service("virtlogd").restart() - if expected_result == "invalid_virtlogd_conf": + if expected_result in ["invalid_virtlogd_conf", "valid_max_clients", + "valid_boundary_max_clients", "nclients_occupied_released", + "invalid_boundary_max_clients", "reload_new_config", + "log_filters_not_same_with_loglevel", "reload_max_size_config", + "set_max_size_config", + "set_max_backups", "reload_max_backups"]: virtlogd_config.restore() service.Factory.create_service("virtlogd").restart() From 925ce45f0956f843601f471dfd0ac2c459267151 Mon Sep 17 00:00:00 2001 From: Vera Wu Date: Tue, 20 Aug 2024 10:06:50 +0800 Subject: [PATCH 0548/1055] v2v:add new case on vddk8.x support Signed-off-by: Vera Wu --- v2v/tests/cfg/nbdkit/nbdkit.cfg | 39 ++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/v2v/tests/cfg/nbdkit/nbdkit.cfg b/v2v/tests/cfg/nbdkit/nbdkit.cfg index 96a0ef766a8..b0808b58181 100644 --- a/v2v/tests/cfg/nbdkit/nbdkit.cfg +++ b/v2v/tests/cfg/nbdkit/nbdkit.cfg @@ -96,7 +96,7 @@ version_required = "[nbdkit-server-1.32.5-4,)" filters = 'cow cacheextents rate readahead scan readahead blocksize' checkpoint = 'check_vddk_filters_thread_model' - - create_options: + - create_options_7: vddk_libdir_src = 'MOUNT_SRC_VDDK70_LIB_DIR_V2V_EXAMPLE' version_required = "[nbdkit-server-1.30.8-1,)" # create_types: vmfs-thin and vmfs-sparse aren't supported @@ -104,6 +104,14 @@ create_adapter_types = 'ide scsi-buslogic scsi-lsilogic' create_hwversions = 'workstation4 workstation5 workstation6 esx30 esx4x esx50 esx51 esx55 esx60 esx65 20' checkpoint = 'check_vddk_create_options' + - create_options_8: + vddk_libdir_src = 'MOUNT_SRC_VDDK80_LIB_DIR_V2V_EXAMPLE' + version_required = "[nbdkit-server-1.38.0-1,)" + # create_types: vmfs-thin and vmfs-sparse aren't supported + create_types = 'monolithic-sparse monolithic-flat split-sparse split-flat vmfs-flat stream-optimized' + create_adapter_types = 'ide scsi-buslogic scsi-lsilogic' + create_hwversions = 'workstation4 workstation5 workstation6 esx30 esx4x esx50 esx51 esx55 esx60 esx65 20' + checkpoint = 'check_vddk_create_options' - ssh: only source_xen..dest_none xen_host_user = 'root' @@ -162,6 +170,35 @@ vsphere_host = ${esx_hostname} vsphere_user = 'root' vsphere_pwd = ${esxi_password} + - vddk8_0: + only source_esx.esx_80..dest_none + version_required = "[nbdkit-server-1.38.0-1,)" + checkpoint = 'has_run_againt_vddk7_0' + vpx_passwd_file = "/tmp/v2v_vpx_passwd" + main_vm = VM_NAME_ESX_NBDKIT_V2V_EXAMPLE + variants: + - vpx: + vsphere_host = ${vpx_hostname} + vsphere_user = 'root' + vsphere_pwd = ${vpx_password} + variants: + - vddk_stats_1: + checkpoint = 'vddk_stats' + vddk_stats = 1 + - vddk_stats_0: + checkpoint = 'vddk_stats' + vddk_stats = 0 + - no_vddk_stats: + - datapath_controlpath: + checkpoint = 'backend_datapath_controlpath' + - scan_readahead_blocksize: + checkpoint = 'scan_readahead_blocksize' + - delay_close_open_options: + checkpoint = 'vddk_with_delay_close_open_option' + - esx: + vsphere_host = ${esx_hostname} + vsphere_user = 'root' + vsphere_pwd = ${esxi_password} - memory: only source_none..dest_none variants: From 0c43460a776cc314dfd52ac6b75270e98dd29028 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Tue, 20 Aug 2024 22:21:54 -0400 Subject: [PATCH 0549/1055] Add new network case of rx tx queue size - VIRT-296306 - [driver][rx_queue_size][tx_queue_size] start vm with rx_queue_size and tx_queue_size setting Signed-off-by: Haijiao Zhao --- .../driver/rx_tx_queue_size.cfg | 33 +++++++ .../driver/rx_tx_queue_size.py | 85 +++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/driver/rx_tx_queue_size.cfg create mode 100644 libvirt/tests/src/virtual_network/driver/rx_tx_queue_size.py diff --git a/libvirt/tests/cfg/virtual_network/driver/rx_tx_queue_size.cfg b/libvirt/tests/cfg/virtual_network/driver/rx_tx_queue_size.cfg new file mode 100644 index 00000000000..d3d7a974a0d --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/driver/rx_tx_queue_size.cfg @@ -0,0 +1,33 @@ +- virtual_network.driver.rx_tx_queue_size: + type = rx_tx_queue_size + start_vm = no + timeout = 240 + outside_ip = 'www.redhat.com' + vm_ping_outside = pass + variants: + - positive: + variants: + - rx_256_tx_256: + rx_tx_attrs = {'rx_queue_size': '256', 'tx_queue_size': '256'} + - rx_512_tx_256: + rx_tx_attrs = {'rx_queue_size': '512', 'tx_queue_size': '256'} + - rx_1024_tx_unset: + rx_tx_attrs = {'rx_queue_size': '1024'} + - negative: + status_error = yes + variants: + - rx_128_tx_unset: + rx_tx_attrs = {'rx_queue_size': '128'} + - rx_2048_tx_unset: + rx_tx_attrs = {'rx_queue_size': '2048'} + - rx_511_tx_unset: + fail_operation = define + rx_tx_attrs = {'rx_queue_size': '511'} + - rx_unset_tx_128: + rx_tx_attrs = {'tx_queue_size': '128'} + - rx_unset_tx_2048: + rx_tx_attrs = {'tx_queue_size': '2048'} + - rx_unset_tx_512: + rx_tx_attrs = {'tx_queue_size': '512'} + + iface_attrs = {'source': {'network': 'default'}, 'type_name': 'network', 'model': 'virtio', 'driver': {'driver_attr': {'name': 'vhost', 'queues': '5', **${rx_tx_attrs}}}} diff --git a/libvirt/tests/src/virtual_network/driver/rx_tx_queue_size.py b/libvirt/tests/src/virtual_network/driver/rx_tx_queue_size.py new file mode 100644 index 00000000000..21b70b98845 --- /dev/null +++ b/libvirt/tests/src/virtual_network/driver/rx_tx_queue_size.py @@ -0,0 +1,85 @@ +import json +import logging + +from avocado.utils import process +from virttest import utils_net +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Start vm with rx_queue_size and tx_queue_size setting + + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + iface_attrs = eval(params.get('iface_attrs', '{}')) + status_error = 'yes' == params.get('status_error', 'no') + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + mac = vm_xml.VMXML.get_first_mac_by_name(vm_name) + iface_attrs['mac_address'] = mac + + vmxml.del_device('interface', by_tag=True) + libvirt_vmxml.modify_vm_device( + vmxml, 'interface', iface_attrs, sync_vm=False) + LOG.debug(f'Modify vmxml to:\n{vmxml}') + + if status_error: + if params.get('fail_operation') == 'define': + virsh_result = virsh.define(vmxml.xml, debug=True) + else: + vmxml.sync() + virsh_result = virsh.start(vm_name, debug=True) + libvirt.check_exit_status(virsh_result, status_error) + return + + vmxml.sync() + vm.start() + LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + vm_sess = vm.wait_for_serial_login() + + iface = network_base.get_iface_xml_inst(vm_name, 'after vm start') + actual_rx = int(iface.driver.driver_attr.get('rx_queue_size')) + actual_tx = int(iface.driver.driver_attr.get('tx_queue_size')) + LOG.debug( + f'Actual rx_queue_size={actual_rx} tx_queue_size={actual_tx}') + if str(actual_rx) != iface_attrs['driver']['driver_attr']['rx_queue_size']: + test.fail(f"Wrong rx_queue_size {actual_rx}, should be " + f"{iface_attrs['driver']['driver_attr']['rx_queue_size']}") + if actual_tx != 256: + test.fail(f'Wrong tx_queue_size {actual_tx}, should be 256') + + process.run('ps -ef|grep qemu', shell=True) + + vm_iface = utils_net.get_linux_iface_info( + mac=mac, session=vm_sess)['ifname'] + + eth_output = vm_sess.cmd(f'ethtool -g {vm_iface}') + LOG.debug(eth_output) + eth_output_json = vm_sess.cmd_output(f'ethtool --json -g {vm_iface}') + LOG.debug(eth_output_json) + eth_info = json.loads(eth_output_json)[0] + if eth_info['rx-max'] != actual_rx or eth_info['rx'] != actual_rx: + test.fail('Wrong rx from vm, please check log') + if eth_info['tx-max'] != actual_tx or eth_info['tx'] != actual_tx: + test.fail('Wrong tx from vm, please check log') + + ips = {'outside_ip': params.get('outside_ip')} + network_base.ping_check(params, ips, vm_sess) + vm_sess.close() + + finally: + bkxml.sync() From ebcd099e82ba3713ea22a2d4159f690dd6163c86 Mon Sep 17 00:00:00 2001 From: Slancaster1 Date: Wed, 14 Aug 2024 09:39:48 -0400 Subject: [PATCH 0550/1055] virsh_console.py: Fix prompt regex - The Issue When looking for a console prompt, the script uses a regex. However this regex will not match the prompt if there is garbage in the console. This garbage often appears as kernel debug messages. EG: [root@localhost ~]# [ 24.552883] block dm-0: the capability attribute has been deprecated - The Solution Update the regex to allow for garbage in the console Signed-off-by: Slancaster1 --- .../tests/src/virsh_cmd/domain/virsh_console.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_console.py b/libvirt/tests/src/virsh_cmd/domain/virsh_console.py index 58e8a7928d0..112c016c8f9 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_console.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_console.py @@ -81,7 +81,7 @@ def vm_console_config(vm, test, device='ttyS0', def check_duplicated_console(command, force_command, status_error, login_user, - login_passwd, test): + login_passwd, test, prompt_regex): """ Test opening a second console with another console active using --force option or not. @@ -93,7 +93,7 @@ def check_duplicated_console(command, force_command, status_error, login_user, :param login_passwd: Password for logging into the VM. :param test: Test Object """ - session = aexpect.ShellSession(command) + session = aexpect.ShellSession(command, prompt=prompt_regex) if not status_error: # Test duplicated console session res = process.run(command, timeout=CMD_TIMEOUT, @@ -104,7 +104,7 @@ def check_duplicated_console(command, force_command, status_error, login_user, "but succeeded with:\n%s" % res) # Test duplicated console session with force option - force_session = aexpect.ShellSession(force_command) + force_session = aexpect.ShellSession(force_command, prompt=prompt_regex) force_status = utils_test.libvirt.verify_virsh_console( force_session, login_user, login_passwd, timeout=CMD_TIMEOUT, debug=True) @@ -116,7 +116,7 @@ def check_duplicated_console(command, force_command, status_error, login_user, def check_disconnect_on_shutdown(vm, command, status_error, login_user, - login_passwd, test): + login_passwd, test, prompt_regex): """ Test whether an active console will disconnect after shutting down the VM. @@ -127,7 +127,7 @@ def check_disconnect_on_shutdown(vm, command, status_error, login_user, :param login_passwd: Password for logging into the VM. :param test: Test Object """ - session = aexpect.ShellSession(command) + session = aexpect.ShellSession(command, prompt=prompt_regex) if not status_error: log = "" console_cmd = "shutdown -h now" @@ -200,6 +200,7 @@ def run(test, params, env): domid = "" uri = params.get("virsh_uri") unprivileged_user = params.get('unprivileged_user') + prompt_regex = params.get("prompt_regex", r"(.*)(\[.+@.+\]#)\s(.*)$") # PAPR guests don't usually have a true serial device (ttyS0), # they only have the hypervisor console (/dev/hvc0) @@ -260,7 +261,7 @@ def run(test, params, env): else: command = "virsh console %s" % vm_ref force_command = "virsh console %s --force" % vm_ref - console_session = aexpect.ShellSession(command) + console_session = aexpect.ShellSession(command, prompt=prompt_regex) status = utils_test.libvirt.verify_virsh_console( console_session, login_user, login_passwd, @@ -268,9 +269,9 @@ def run(test, params, env): console_session.close() check_duplicated_console(command, force_command, status_error, - login_user, login_passwd, test) + login_user, login_passwd, test, prompt_regex) check_disconnect_on_shutdown(vm, command, status_error, login_user, - login_passwd, test) + login_passwd, test, prompt_regex) finally: # Recover state of vm. if vm_state == "paused": From b49c23c31b25ba14eab305d96f978b25420d3526 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Thu, 22 Aug 2024 09:30:25 -0400 Subject: [PATCH 0551/1055] security/virt_what: add test for expected value Since virt-what-1.25-9, there's an additional command 'virt-what-cvm' that gives information about if and which confidential VM mode is running. The test per default assumes that the VM runs without confidentiality. It can be configured to cover other values depending on the guest. The supported outputs are listed on the man virt-what-cvm. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/security/virt_what_cvm.cfg | 9 +++++++ libvirt/tests/src/security/virt_what_cvm.py | 27 ++++++++++++++++++++ spell.ignore | 1 + 3 files changed, 37 insertions(+) create mode 100644 libvirt/tests/cfg/security/virt_what_cvm.cfg create mode 100644 libvirt/tests/src/security/virt_what_cvm.py diff --git a/libvirt/tests/cfg/security/virt_what_cvm.cfg b/libvirt/tests/cfg/security/virt_what_cvm.cfg new file mode 100644 index 00000000000..bf61a130b08 --- /dev/null +++ b/libvirt/tests/cfg/security/virt_what_cvm.cfg @@ -0,0 +1,9 @@ +- virt_what.cvm: + type = virt_what_cvm + start_vm = yes + variants: + - expected_value: + # The EXPECTED_VALUE depends on the VM. A normal VM would have "". + # man virt-what-cvm lists the available values for VM where + # confidentiality is enabled + expected_cvm = diff --git a/libvirt/tests/src/security/virt_what_cvm.py b/libvirt/tests/src/security/virt_what_cvm.py new file mode 100644 index 00000000000..24299023dd5 --- /dev/null +++ b/libvirt/tests/src/security/virt_what_cvm.py @@ -0,0 +1,27 @@ +import logging as log + +from virttest import utils_misc, utils_package + + +logging = log.getLogger("avocado." + __name__) + + +def run(test, params, env): + """ + Confirms that the output of virt-what-cvm is as expected. + + :params test: The avocado test object + :params params: Parameters for the test + :params env: The avocado test environment object + """ + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + expected_cvm = params.get("expected_cvm") + session = vm.wait_for_login() + utils_package.package_install("virt-what", session=session) + _, o = utils_misc.cmd_status_output("virt-what-cvm", session=session) + if o.strip() != expected_cvm.strip(): + test.fail( + f"Unexpected value '{o.strip()}' instead of {expected_cvm.strip()}." + " Note that the command is supported since virt-what-1.25-10." + ) diff --git a/spell.ignore b/spell.ignore index 50d968b579f..8d86f0bfb8b 100644 --- a/spell.ignore +++ b/spell.ignore @@ -170,6 +170,7 @@ ctrl currentvcpu curvcpu CVE +cvm dac DAC darget From 158ea6ed88048fb8b4a75b0750219da972b9e319 Mon Sep 17 00:00:00 2001 From: Vera Wu Date: Mon, 26 Aug 2024 10:30:00 +0800 Subject: [PATCH 0552/1055] v2v: fix failed case on checking v2v version for rhel10 Signed-off-by: Vera Wu --- v2v/tests/src/v2v_options.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/v2v/tests/src/v2v_options.py b/v2v/tests/src/v2v_options.py index 7bd7efe7c62..acaaec9834d 100644 --- a/v2v/tests/src/v2v_options.py +++ b/v2v/tests/src/v2v_options.py @@ -587,9 +587,11 @@ def check_alloc(): 'Not found disk or xml created by virt-v2v-copy-to-local') if checkpoint == 'check_version': get_v2v_version = process.run('rpm -q virt-v2v', shell=True, ignore_status=True) - if (''.join(filter(str.isdigit, str(output_stdout)))[1:4] + - ''.join(filter(str.isdigit, str(output_stdout)))[5]) != \ - ''.join(filter(str.isdigit, str(get_v2v_version.stdout)))[1:5]: + get_rpm_version = re.search(r'(\d+\.\d+\.\d+-\d+\.el\d+)', str(get_v2v_version.stdout)) + rpm_version = get_rpm_version.group(1) + get_virt_v2v_version = re.search(r'(\d+\.\d+\.\d+).*(\d+\.el\d+)', str(output_stdout)) + virt_v2v_version = get_virt_v2v_version.group(1) + '-' + get_virt_v2v_version.group(2) + if (rpm_version != virt_v2v_version): test.fail('v2v version is incorrect in v2v version option') log_check = utils_v2v.check_log(params, output) From 66b6ba386c98f68d55700f95117903f81f8f5e61 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 23 Jul 2024 20:11:50 +0800 Subject: [PATCH 0553/1055] vIOMMU: Add a hotplug case This PR adds: VIRT-296710: [vIOMMU] hotplug/unplug devices with iommu enabled Signed-off-by: Yingshun Cui --- .../hotplug_device_with_iommu_enabled.cfg | 59 +++++++++ .../hotplug_device_with_iommu_enabled.py | 116 ++++++++++++++++++ provider/viommu/viommu_base.py | 11 +- 3 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 libvirt/tests/cfg/sriov/vIOMMU/hotplug_device_with_iommu_enabled.cfg create mode 100644 libvirt/tests/src/sriov/vIOMMU/hotplug_device_with_iommu_enabled.py diff --git a/libvirt/tests/cfg/sriov/vIOMMU/hotplug_device_with_iommu_enabled.cfg b/libvirt/tests/cfg/sriov/vIOMMU/hotplug_device_with_iommu_enabled.cfg new file mode 100644 index 00000000000..de76500888f --- /dev/null +++ b/libvirt/tests/cfg/sriov/vIOMMU/hotplug_device_with_iommu_enabled.cfg @@ -0,0 +1,59 @@ +- vIOMMU.hotplug_device_with_iommu_enabled: + type = hotplug_device_with_iommu_enabled + start_vm = "no" + ping_dest = '8.8.8.8' + disk_driver = {'name': 'qemu', 'type': 'qcow2', 'iommu': 'on'} + variants: + - virtio: + only q35, aarch64 + no ats_on + func_supported_since_libvirt_ver = (8, 3, 0) + iommu_dict = {'model': 'virtio'} + - intel: + only q35 + start_vm = "yes" + enable_guest_iommu = "yes" + iommu_dict = {'model': 'intel', 'driver': {'intremap': 'on', 'caching_mode': 'on', 'eim': 'on', 'iotlb': 'on', 'aw_bits': '48'}} + - smmuv3: + only aarch64 + no ats_on + func_supported_since_libvirt_ver = (5, 5, 0) + iommu_dict = {'model': 'smmuv3'} + variants: + - e1000e: + only q35 + iface_model = 'e1000e' + iface_dict = {'type_name': 'network', 'model': '${iface_model}', 'source': {'network': 'default'}} + test_devices = ["Eth"] + - rtl8139: + only q35 + iface_model = 'rtl8139' + iface_dict = {'type_name': 'network', 'model': '${iface_model}', 'source': {'network': 'default'}} + controller_dicts = [{'type': 'pci', 'model': 'pcie-to-pci-bridge'}] + - virtio_muti_devices: + disk_dict = {'target': {'dev': 'vdb', 'bus': 'virtio'}, 'device': 'disk', 'driver': ${disk_driver}} + test_devices = ["Eth", "block"] + variants: + - vhost_on: + interface_driver_name = "vhost" + - vhost_off: + interface_driver_name = "qemu" + interface_driver = {'driver_attr': {'name': '${interface_driver_name}', 'iommu': 'on'}} + iface_dict = {'type_name': 'network', 'model': 'virtio', 'driver': ${interface_driver}, 'source': {'network': 'default'}} + - hostdev_iface: + only virtio + need_sriov = yes + ping_dest = '' + test_devices = ["Eth"] + iface_dict = {'managed': 'yes', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}} + - scsi_controller: + test_devices = ["scsi"] + controller_dicts = [{'type': 'scsi', 'model': 'virtio-scsi','driver': {'iommu': 'on'}}] + disk_dict = {'target': {'dev': 'sda', 'bus': 'scsi'}} + cleanup_ifaces = no + - ats_on: + test_devices = ["Eth", "block"] + disk_driver = {'name': 'qemu', 'type': 'qcow2', 'iommu': 'on', 'ats': 'on'} + disk_dict = {'target': {'dev': 'vdb', 'bus': 'virtio'}, 'device': 'disk', 'driver': ${disk_driver}} + interface_driver = {'driver_attr': {'name': 'vhost', 'iommu': 'on', 'ats': 'on'}} + iface_dict = {'type_name': 'network', 'model': 'virtio', 'driver': ${interface_driver}, 'source': {'network': 'default'}} diff --git a/libvirt/tests/src/sriov/vIOMMU/hotplug_device_with_iommu_enabled.py b/libvirt/tests/src/sriov/vIOMMU/hotplug_device_with_iommu_enabled.py new file mode 100644 index 00000000000..5e4b493cce4 --- /dev/null +++ b/libvirt/tests/src/sriov/vIOMMU/hotplug_device_with_iommu_enabled.py @@ -0,0 +1,116 @@ +import os +import time + +from virttest import data_dir +from virttest import utils_disk +from virttest import utils_net +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_disk +from virttest.utils_libvirt import libvirt_vmxml + +from provider.sriov import sriov_base +from provider.viommu import viommu_base +from provider.sriov import check_points as sriov_check_points + + +def run(test, params, env): + """ + Hotplug devices with iommu enabled to a vm with an iommu device + """ + def detach_dev(device_type, dev_iommu_info, vm_session): + """ + Detach device and check iommu group if needed + + :param device_type: Device type + :param dev_iommu_info: Device's iommu group info + :param vm_session: VM session + """ + dev_obj = vm_xml.VMXML.new_from_dumpxml(vm_name).get_devices(device_type)[-1] + virsh.detach_device(vm_name, dev_obj.xml, wait_for_event=True, + debug=True, ignore_status=False) + if dev_iommu_info: + res = vm_session.cmd_status_output('ifconfig') + test.log.debug(res) + s, o = vm_session.cmd_status_output("ls %s" % dev_iommu_info) + test.log.debug(f"{device_type} iommu check: {o}") + if not s: + test.fail("The %s should be removed from the iommu group" % device_type) + + cleanup_ifaces = params.get("cleanup_ifaces", "yes") + disk_dict = eval(params.get('disk_dict', '{}')) + + ping_dest = params.get('ping_dest') + iommu_dict = eval(params.get('iommu_dict', '{}')) + test_devices = eval(params.get("test_devices", "[]")) + need_sriov = "yes" == params.get("need_sriov", "no") + + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + sroiv_test_obj = None + new_disk_path = None + + test_obj = viommu_base.VIOMMUTest(vm, test, params) + if need_sriov: + sroiv_test_obj = sriov_base.SRIOVTest(vm, test, params) + + try: + test_obj.setup_iommu_test(iommu_dict=iommu_dict, cleanup_ifaces=cleanup_ifaces) + test_obj.prepare_controller() + test.log.info("TEST_STEP: Start the VM.") + if not vm.is_alive(): + vm.start() + vm.cleanup_serial_console() + vm.create_serial_console() + vm_session = vm.wait_for_serial_login( + timeout=int(params.get('login_timeout'))) + + if disk_dict: + test.log.info("TEST_STEP: Attach a disk device to VM.") + disk_dict = test_obj.update_disk_addr(disk_dict) + disk_size = params.get("size", "200M") + new_disk_path = os.path.join(data_dir.get_data_dir(), "images", "test.qcow2") + libvirt_disk.create_disk("file", new_disk_path, disk_size, disk_format="qcow2") + disk_dict.update({'source': {'attrs': {'file': new_disk_path}}}) + disk_obj = libvirt_vmxml.create_vm_device_by_type('disk', disk_dict) + virsh.attach_device(vm.name, disk_obj.xml, debug=True, ignore_status=False) + + if need_sriov: + test_obj.params["iface_dict"] = str(sroiv_test_obj.parse_iface_dict()) + iface_dict = test_obj.parse_iface_dict() + + if cleanup_ifaces == "yes": + iface_obj = libvirt_vmxml.create_vm_device_by_type("interface", iface_dict) + virsh.attach_device(vm.name, iface_obj.xml, debug=True, ignore_status=False) + # Sleep 20s to stabilize the attached interface + time.sleep(20) + + test.log.info("TEST_STEP: Check dmesg message about iommu inside the vm.") + vm_session.cmd("dmesg | grep -i 'Adding to iommu group'", timeout=300) + dev_iommu_groups = viommu_base.check_vm_iommu_group(vm_session, test_devices) + test.log.debug(f"Device iommu groups info: {dev_iommu_groups}") + + if "block" in test_devices: + test.log.info("TEST_STEP: Check VM disk io.") + new_disk = libvirt_disk.get_non_root_disk_name(vm_session)[0] + utils_disk.dd_data_to_vm_disk(vm_session, new_disk) + test.log.info("TEST_STEP: Detach the disk.") + detach_dev("disk", dev_iommu_groups["block"], vm_session) + + test.log.info("TEST_STEP: Check VM network.") + if need_sriov: + sriov_check_points.check_vm_network_accessed(vm_session, ping_dest=ping_dest) + else: + + s, o = utils_net.ping(ping_dest, count=5, timeout=240, session=vm_session) + if s: + test.fail("Failed to ping %s! status: %s, output: %s." % (ping_dest, s, o)) + + test.log.info("TEST_STEP: Detach the interface.") + detach_dev("interface", dev_iommu_groups.get("Eth"), vm_session) + + finally: + test_obj.teardown_iommu_test() + if new_disk_path and os.path.exists(new_disk_path): + os.remove(new_disk_path) diff --git a/provider/viommu/viommu_base.py b/provider/viommu/viommu_base.py index 83fd6dfb455..9326d98b109 100644 --- a/provider/viommu/viommu_base.py +++ b/provider/viommu/viommu_base.py @@ -1,3 +1,5 @@ +import os + from avocado.core import exceptions from virttest import libvirt_version @@ -16,6 +18,7 @@ def check_vm_iommu_group(vm_session, test_devices): :param vm_session: VM session :param test_devices: test devices to check """ + result = {} for dev in test_devices: s, o = vm_session.cmd_status_output( "lspci | awk 'BEGIN{IGNORECASE=1} /%s/ {print $1}'" % dev) @@ -23,13 +26,16 @@ def check_vm_iommu_group(vm_session, test_devices): exceptions.TestFail("Failed to get pci address!") cmd = ("find /sys/kernel/iommu_groups/ -type l | xargs ls -l | awk -F " - "'/' '/%s / {print(\"\",$2,$3,$4,$5,$6)}' OFS='/' " % o.strip()) + "'/' '/%s / {print(\"\",$2,$3,$4,$5,$6)}' OFS='/' " % o.splitlines()[0]) s, o = vm_session.cmd_status_output(cmd) if s: exceptions.TestFail("Failed to find iommu group!") - s, o = vm_session.cmd_status_output("ls %s" % o) + device_dir = o.strip().splitlines()[-1] + s, dev_pci = vm_session.cmd_status_output("ls %s" % device_dir) if s: exceptions.TestFail("Failed to get the device in the iommu group!") + result.update({dev: os.path.join(device_dir, dev_pci.strip())}) + return result class VIOMMUTest(object): @@ -40,6 +46,7 @@ def __init__(self, vm, test, params, session=None): self.session = session self.remote_virsh_dargs = None self.controller_dicts = eval(self.params.get("controller_dicts", "[]")) + self.dev_slot = 0 libvirt_version.is_libvirt_feature_supported(self.params) new_xml = vm_xml.VMXML.new_from_inactive_dumpxml(self.vm.name) From e3cc1f765b84ec9325542a5f5e254800668d9dec Mon Sep 17 00:00:00 2001 From: Yanqiu Zhang Date: Mon, 26 Aug 2024 08:30:46 -0400 Subject: [PATCH 0554/1055] tpm_device: add tpm2_sign test Test tpm2_sign with different hash algorithms. Signed-off-by: Yanqiu Zhang --- .../tests/cfg/virtual_device/tpm_device.cfg | 4 +++ .../tests/src/virtual_device/tpm_device.py | 35 ++++++++++++++++--- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/cfg/virtual_device/tpm_device.cfg b/libvirt/tests/cfg/virtual_device/tpm_device.cfg index af25a725a43..4fd10772321 100644 --- a/libvirt/tests/cfg/virtual_device/tpm_device.cfg +++ b/libvirt/tests/cfg/virtual_device/tpm_device.cfg @@ -32,6 +32,10 @@ only encrypted only pcrbank_default test_rsaencypt = 'yes' + - sign_test: + only encrypted + only pcrbank_default + test_sign = 'yes' - version_default: only plain backend_version = 'none' diff --git a/libvirt/tests/src/virtual_device/tpm_device.py b/libvirt/tests/src/virtual_device/tpm_device.py index bc94dad11cb..b8627650d4f 100644 --- a/libvirt/tests/src/virtual_device/tpm_device.py +++ b/libvirt/tests/src/virtual_device/tpm_device.py @@ -86,6 +86,7 @@ def run(test, params, env): remove_pcrbank = ('yes' == params.get("remove_pcrbank", "no")) pcrbank_change = params.get("pcrbank_change") test_rsaencypt = ('yes' == params.get("test_rsaencypt", "no")) + test_sign = ('yes' == params.get("test_sign", "no")) active_pcr_banks = params.get("active_pcr_banks") statedir = params.get("statedir") audit_cmd = params.get("audit_cmd") @@ -608,19 +609,28 @@ def run_test_suite_in_guest(session): test.fail("test suite check failed.") logging.info("------PASS on kernel test suite check------") - def test_rsaencypt_in_guest(session): + def prepare_rsa_key(session, test_msg="my message"): """ - Test tpm RSA encryption in guest. + Create RSA key and load it, also prepare data file. :param session: Guest session to be tested + :param test_msg: message to put in data file """ if not utils_package.package_install(["tpm2-tools"], session, 360): test.error("Failed to install tpm2-tools package in guest") - session.cmd_status_output("tpm2_createprimary -c primary.ctx") - session.cmd("tpm2_create -C primary.ctx -Grsa2048 -u key.pub -r key.priv") + session.cmd_status_output("tpm2_createprimary -C e -c primary.ctx") + session.cmd("tpm2_create -C primary.ctx -G rsa2048 -u key.pub -r key.priv") session.cmd("tpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx") - test_msg = 'my message' session.cmd("echo %s > msg.dat" % test_msg) + + def test_rsaencypt_in_guest(session): + """ + Test tpm RSA encryption in guest. + + :param session: Guest session to be tested + """ + test_msg = 'my encrypt decrypt test message' + prepare_rsa_key(session, test_msg) for padding_scheme in ['oaep', 'rsaes', 'null']: status, output = session.cmd_status_output("tpm2_rsaencrypt -c key.ctx -o msg.enc -s %s msg.dat" % padding_scheme) if status: @@ -635,6 +645,19 @@ def test_rsaencypt_in_guest(session): session.cmd("rm -f msg.enc msg.ptext") session.cmd("rm -f primary.ctx key.pub key.priv key.ctx msg.dat") + def test_sign_in_guest(session): + """ + Test tpm signature in guest. + + :param session: Guest session to be tested + """ + prepare_rsa_key(session) + for hash_algorithm in ['sha1', 'sha256', 'sha384', 'sha512']: + status, output = session.cmd_status_output("tpm2_sign -c key.ctx -g %s -o sig.rssa msg.dat" % hash_algorithm) + if status: + test.fail("tpm2_sign failed with %s hash algorithm: %s" % (hash_algorithm, output)) + session.cmd("rm -f primary.ctx key.pub key.priv key.ctx msg.dat sig.rssa") + def persistent_test(vm, vm_xml): """ Test vtpm with persistent_state for transient vm. @@ -939,6 +962,8 @@ def check_swtpmpidfile(vm_name, test_stage): run_test_suite_in_guest(session) elif test_rsaencypt: test_rsaencypt_in_guest(session) + elif test_sign: + test_sign_in_guest(session) else: test_guest_tpm(expect_version, session, expect_fail) session.close() From 2fc307739440e1cd022cfbe748a0229c19b78314 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Tue, 27 Aug 2024 00:13:53 -0400 Subject: [PATCH 0555/1055] Change memory size, memory address and guest node Signed-off-by: liang-cong-red-hat --- .../memory/memory_devices/dimm_memory_hot_unplug.cfg | 10 +++++----- .../memory/memory_devices/dimm_memory_hot_unplug.py | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg index d6e173a808c..ac22b4bd5f2 100644 --- a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg @@ -8,8 +8,8 @@ target_size = "524288" size_unit = 'KiB' node = 0 - mem_value = 3145728 - current_mem = 3145728 + mem_value = 3670016 + current_mem = 3670016 numa_mem = 1572864 max_mem = 4194304 max_mem_slots = 16 @@ -23,14 +23,14 @@ vm_attrs = {${numa_dict},${max_dict},'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'} variants plug_dimm_type: - target_and_address: - base = "0x100000000" + base = "0x140000000" addr_dict = "'address':{'attrs': {'type':'dimm','slot':'${slot}','base':'${base}'}}" dimm_dict = {'mem_model':'${mem_model}',${addr_dict},'target': {'size':${target_size}, 'size_unit':'${size_unit}', 'node':${node}}} unplug_dimm_dict = ${dimm_dict} - source_and_mib: - target_size = "1024" + target_size = "512" size_unit = 'MiB' - node = 1 + node = 0 source_dict = "'source':{'nodemask': '0','pagesize': %d, 'pagesize_unit':'KiB'}" dimm_dict = {'mem_model':'${mem_model}',${source_dict},'target': {'size':${target_size}, 'size_unit':'${size_unit}', 'node':${node}}} unplug_dimm_dict = ${dimm_dict} diff --git a/libvirt/tests/src/memory/memory_devices/dimm_memory_hot_unplug.py b/libvirt/tests/src/memory/memory_devices/dimm_memory_hot_unplug.py index 73af8744469..05420240d0c 100644 --- a/libvirt/tests/src/memory/memory_devices/dimm_memory_hot_unplug.py +++ b/libvirt/tests/src/memory/memory_devices/dimm_memory_hot_unplug.py @@ -54,10 +54,10 @@ def check_guest_virsh_dominfo(vm, test, params, unplugged=False): target_size = adjust_size_unit(params) if unplugged: - expected_mem = str(mem_value) + expected_mem = str(mem_value - target_size) expected_curr = str(current_mem - target_size) else: - expected_mem = str(mem_value + target_size) + expected_mem = str(mem_value) expected_curr = str(current_mem) memory_base.check_dominfo(vm, test, expected_mem, expected_curr) @@ -86,7 +86,7 @@ def check_after_detach(vm, test, params): target_size = adjust_size_unit(params) libvirtd_log_file = os.path.join(test.debugdir, "libvirtd.log") - ausearch_check = params.get("ausearch_check") % (mem_value+target_size, mem_value) + ausearch_check = params.get("ausearch_check") % (mem_value, mem_value - target_size) # Check the audit log by ausearch. ausearch_result = process.run(audit_cmd, shell=True) @@ -102,7 +102,7 @@ def check_after_detach(vm, test, params): # Check the memory allocation and memory device config. vmxml = vm_xml.VMXML.new_from_dumpxml(vm.name) libvirt_vmxml.check_guest_xml_by_xpaths( - vmxml, eval(base_xpath % (mem_value, current_mem-target_size))) + vmxml, eval(base_xpath % (mem_value - target_size, current_mem - target_size))) if vmxml.devices.by_device_tag("memory"): test.fail("Dimm memory still exist after unplugging") @@ -153,7 +153,7 @@ def run_test(): target_size = adjust_size_unit(params) vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) libvirt_vmxml.check_guest_xml_by_xpaths( - vmxml, eval(base_xpath % (mem_value + target_size, current_mem))) + vmxml, eval(base_xpath % (mem_value, current_mem))) libvirt_vmxml.check_guest_xml_by_xpaths( vmxml.devices.by_device_tag("memory")[0], eval(dimm_xpath % (target_size, slot))) From 0209dd769b8aa03df4555099313ca50cc4129aec Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Tue, 27 Aug 2024 01:58:04 -0400 Subject: [PATCH 0556/1055] Change grep pattern to avoid occasional memory size and address conflicts Signed-off-by: liang-cong-red-hat --- provider/numa/numa_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provider/numa/numa_base.py b/provider/numa/numa_base.py index 16f4188ea7e..0d009697ed3 100644 --- a/provider/numa/numa_base.py +++ b/provider/numa/numa_base.py @@ -192,7 +192,7 @@ def get_host_numa_memory_alloc_info(mem_size): :param mem_size: int, the vm memory size :return: str, the matched output in numa_maps """ - cmd = 'grep -B1 %s /proc/`pidof qemu-kvm`/smaps' % mem_size + cmd = 'grep -B1 "%s " /proc/`pidof qemu-kvm`/smaps' % mem_size out = process.run(cmd, shell=True, verbose=True).stdout_text.strip() matches = re.findall('(\w+)-', out) if not matches: From e070c2334a329a04109e869748124fc18a97b7c7 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Tue, 27 Aug 2024 04:43:47 -0400 Subject: [PATCH 0557/1055] Change comparison logic, including xml element without child element Signed-off-by: liang-cong-red-hat --- .../guest_numa_topology/numa_topology_with_cpu_topology.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_cpu_topology.py b/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_cpu_topology.py index 5881dcc4578..8d097376123 100644 --- a/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_cpu_topology.py +++ b/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_cpu_topology.py @@ -37,9 +37,9 @@ def prepare_vm_xml(test_obj): cpu_topology = eval(test_obj.params.get('cpu_topology', '{}')) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(test_obj.vm.name) if numa_cells: - if vmxml.xmltreefile.find('cpu'): + if vmxml.xmltreefile.find('cpu') is not None: cpuxml = vmxml.cpu - if cpuxml.xmltreefile.find('topology'): + if cpuxml.xmltreefile.find('topology') is not None: del cpuxml.topology else: cpuxml = vm_xml.VMCPUXML() From 10597a7545ea55156c28f85ec2533fe39d89f2ff Mon Sep 17 00:00:00 2001 From: Meina Li Date: Tue, 27 Aug 2024 22:58:12 -0400 Subject: [PATCH 0558/1055] Virtio_packed: add new test scenarios of driver packed attribute Automate VIRT-293723 - [packed] Start vm with virtio packed attribute and check the bit. After discussion, we don't need to add the checkpoint of bit. Also because this attribute have already been covered in some devices but not filesystem, video and others. So I covered all them directly in the previous test script. Signed-off-by: Meina Li --- libvirt/tests/cfg/virtio/virtio_page_per_vq.cfg | 10 +++++----- libvirt/tests/src/virtio/virtio_page_per_vq.py | 13 +++++++------ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/libvirt/tests/cfg/virtio/virtio_page_per_vq.cfg b/libvirt/tests/cfg/virtio/virtio_page_per_vq.cfg index 44a6a7c12bd..d754301cce7 100644 --- a/libvirt/tests/cfg/virtio/virtio_page_per_vq.cfg +++ b/libvirt/tests/cfg/virtio/virtio_page_per_vq.cfg @@ -1,7 +1,7 @@ - virtio_attributes.virtio_page_per_vq: type = virtio_page_per_vq start_vm = no - driver_dict = {'driver': {'page_per_vq': 'on'}} + driver_dict = {'driver': {'page_per_vq': 'on', 'packed': 'on'}} ping_outside = 'www.google.com' func_supported_since_libvirt_ver = (8, 5, 0) no s390-virtio @@ -15,7 +15,7 @@ disk_image = '/var/lib/avocado/data/avocado-vt/images/jeos-27-x86_64.qcow2' aarch64: disk_image = '/var/lib/avocado/data/avocado-vt/images/jeos-27-aarch64.qcow2' - driver_dict = {'driver': {'name': 'qemu', 'type': 'qcow2', 'page_per_vq': 'on'}} + driver_dict = {'driver': {'name': 'qemu', 'type': 'qcow2', 'page_per_vq': 'on', 'packed': 'on'}} device_dict = {'device': 'disk', 'type_name': 'file', **${driver_dict}, 'source': {'attrs': {'file': '${disk_image}'}}, 'target': {'dev': 'vdb', 'bus': 'virtio'}} - controller: variants: @@ -27,7 +27,7 @@ controller_type = "virtio-serial" device_dict = {**${driver_dict}, 'type': 'virtio-serial', 'index': '0', 'type_name': 'virtio-serial'} - interface: - driver_dict = {'driver': {'driver_attr': {'page_per_vq': 'on'}}} + driver_dict = {'driver': {'driver_attr': {'page_per_vq': 'on', 'packed': 'on'}}} device_dict = {'type_name': 'network', 'model': 'virtio', 'source': {'network': 'default'}, **${driver_dict}, 'mac_address': '52:54:00:26:08:7b'} - rng: device_dict = {'backend': {'backend_dev': '/dev/urandom', 'backend_model': 'random'}, **${driver_dict}, 'rng_model': 'virtio'} @@ -41,10 +41,10 @@ - mouse: - tablet: - passthrough: - device_dict = {**${device_dict}, 'source_evdev': '/dev/input/event1'} + device_dict = {**${device_dict}, 'source_evdev': '/dev/input/event0'} - video: only default_start device_dict = {'model_type': 'virtio', **${driver_dict}, 'model_heads': '1'} - filesystem: - driver_dict = {'driver': {'type': 'virtiofs', 'page_per_vq': 'on'}} + driver_dict = {'driver': {'type': 'virtiofs', 'page_per_vq': 'on', 'packed': 'on'}} device_dict = {'source': {'dir': '/tmp'}, **${driver_dict}, 'type_name': 'mount', 'accessmode': 'passthrough', 'target': {'dir': 'mount_tag'}, 'binary': {'xattr': 'on', 'path': '/usr/libexec/virtiofsd', 'cache_mode': 'always'}} diff --git a/libvirt/tests/src/virtio/virtio_page_per_vq.py b/libvirt/tests/src/virtio/virtio_page_per_vq.py index f39435fde90..f05ec43d731 100644 --- a/libvirt/tests/src/virtio/virtio_page_per_vq.py +++ b/libvirt/tests/src/virtio/virtio_page_per_vq.py @@ -47,6 +47,7 @@ def prepare_test(vmxml): vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) # Prepare device xml by using device function, for example, Disk(). device_obj = device_type.capitalize() + disk_image_path = None if device_type == "disk" and hotplug: disk_image_path = os.path.join(os.path.dirname(disk_image), "base.qcow2") libvirt.create_local_disk( @@ -58,7 +59,7 @@ def prepare_test(vmxml): else: device_xml = eval(device_obj)() device_xml.setup_attrs(**device_dict) - return device_xml, vmxml + return device_xml, vmxml, disk_image_path def run_test(device_xml, vmxml): """ @@ -87,13 +88,13 @@ def run_test(device_xml, vmxml): test.log.info("TEST_STEP3: check the network by ping") utils_net.ping(dest=ping_outside, count='3', timeout=10, session=vm.session, force_ipv4=True) - def teardown_test(): + def teardown_test(disk_image_path): """ Clean up the test environment. """ bkxml.sync() - if hotplug and os.path.exists(disk_image): - os.remove(disk_image) + if disk_image_path and os.path.exists(disk_image_path): + os.remove(disk_image_path) def check_attribute(): """ @@ -160,7 +161,7 @@ def start_guest(): bkxml = vmxml.copy() try: - device_xml, vmxml = prepare_test(vmxml) + device_xml, vmxml, disk_image_path = prepare_test(vmxml) run_test(device_xml, vmxml) finally: - teardown_test() + teardown_test(disk_image_path) From fdf6c6a382e7faf0ec7a9148cdcbec196c8bd8c7 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Wed, 28 Aug 2024 03:17:06 -0400 Subject: [PATCH 0559/1055] Snapshot: add new auto case for snapshot-list Automate case VIRT-16603 - [Disk snapshot][External] Get guest snapshot list with option Signed-off-by: Meina Li --- .../snapshot/snapshot_list_with_options.cfg | 38 ++++++++ .../snapshot/snapshot_list_with_options.py | 92 +++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 libvirt/tests/cfg/snapshot/snapshot_list_with_options.cfg create mode 100644 libvirt/tests/src/snapshot/snapshot_list_with_options.py diff --git a/libvirt/tests/cfg/snapshot/snapshot_list_with_options.cfg b/libvirt/tests/cfg/snapshot/snapshot_list_with_options.cfg new file mode 100644 index 00000000000..079241a0075 --- /dev/null +++ b/libvirt/tests/cfg/snapshot/snapshot_list_with_options.cfg @@ -0,0 +1,38 @@ +- snapshot_list.with_options: + type = snapshot_list_with_options + start_vm = "no" + snap_names = ['s1', 's2', 's3', 's4'] + snap_options = "%s --memspec snapshot=external,file=/tmp/mem.%s" + variants: + - roots: + list_options = "--roots" + expected_list = ['s1'] + - leaves: + list_options = "--leaves" + expected_list = ['s4'] + - no_leaves: + option = "--no-leaves" + variants: + - with_external: + list_options = "${option} --external" + expected_list = ['s1', 's2'] + - with_inactive: + list_options = "${option} --inactive" + expected_list = ['s1'] + - with_active: + list_options = "${option} --active" + expected_list = ['s3'] + - with_disk_only: + list_options = "${option} --disk-only" + expected_list = ['s2'] + - from_and_descendants: + list_options = "--from s2 --descendants" + expected_list = ['s3', 's4'] + - topological: + list_options = "--topological" + expected_list = ['s1', 's2', 's3', 's4'] + - parent: + func_supported_since_libvirt_ver = (10, 3, 0) + special_check = "yes" + list_options = "--name --parent" + expected_dict = {'s1':'', 's2':'s1', 's3':'s2', 's4':'s3'} diff --git a/libvirt/tests/src/snapshot/snapshot_list_with_options.py b/libvirt/tests/src/snapshot/snapshot_list_with_options.py new file mode 100644 index 00000000000..7b4b7788ce7 --- /dev/null +++ b/libvirt/tests/src/snapshot/snapshot_list_with_options.py @@ -0,0 +1,92 @@ +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Meina Li + +from virttest import libvirt_version +from virttest import virsh +from virttest.libvirt_xml import vm_xml + +from provider.snapshot import snapshot_base + + +def run(test, params, env): + """ + Get guest snapshot list with different options. + """ + def create_snapshots(vm_name, snap_names): + """ + Create snapshots for guest. + + :params vm_name: the vm name + :params snap_names: the created snapshot names + """ + test.log.info("TEST_SETUP: Prepare shutoff guest and create a snapshot.") + virsh.snapshot_create_as(vm_name, "%s --disk-only" % snap_names[0], **virsh_dargs) + test.log.info("TEST_SETUP: Prepare running guest and create a disk only snapshot.") + if not vm.is_alive(): + vm.start() + vm.wait_for_login().close() + virsh.snapshot_create_as(vm_name, "%s --disk-only" % snap_names[1], **virsh_dargs) + test.log.info("TEST_SETUP: Prepare running guest and create a disk and mempry snapshot.") + for i in range(2, 4): + virsh.snapshot_create_as(vm_name, + "%s" % (snap_options % (snap_names[i], snap_names[i])), + **virsh_dargs) + for snap_name in snap_names: + test_obj.check_snap_list(snap_name) + + def check_snap_list(snap_list): + """ + Check the list snapshots of guest to match expected ones. + + :params snap_list: the snapshots created in setup + """ + if special_check: + list_dict = {} + cmd = "snapshot-list %s %s" % (vm_name, list_options) + list_result = virsh.command(cmd, **virsh_dargs).stdout_text.split() + list_dict[list_result[0]] = '' + for num in range(1, len(list_result), 2): + key = list_result[num] + value = list_result[num+1] + list_dict[key] = value + for key, value in expected_dict.items(): + if list_dict.get(key) != value: + test.fail("Get incorrect result %s, the expected result is %s" % + (list_result, expected_dict)) + test.log.debug("Get expected result for snapshot-list options %s", + list_options) + for snap_name in expected_list: + if snap_name not in snap_list: + test.fail("Snapshot %s doesn't exist" % snap_name) + else: + test.log.info("Snapshot %s is in expected snapshot list.", snap_name) + + vm_name = params.get("main_vm") + snap_names = eval(params.get("snap_names", "[]")) + snap_options = params.get("snap_options") + list_options = params.get("list_options") + expected_list = eval(params.get("expected_list", "[]")) + expected_dict = eval(params.get("expected_dict", "{}")) + special_check = "yes" == params.get("special_check", "no") + libvirt_version.is_libvirt_feature_supported(params) + + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + virsh_dargs = {"debug": True, "ignore_status": False} + test_obj = snapshot_base.SnapshotTest(vm, test, params) + + try: + test.log.info("STEP1: Create snapshots.") + create_snapshots(vm_name, snap_names) + test.log.info("STEP2: List snapshots.") + snap_list = virsh.snapshot_list(vm_name, list_options, **virsh_dargs) + test.log.info("STEP3: Check the listed snapshots.") + check_snap_list(snap_list) + finally: + snap_names.reverse() + test_obj.teardown_test() + bkxml.sync() From 7bc181152b3828d740e497155daad66d4afd2bba Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Wed, 28 Aug 2024 03:18:09 -0400 Subject: [PATCH 0560/1055] Add current memory config to replace default Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/memory/memory_attach_device.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_attach_device.cfg b/libvirt/tests/cfg/memory/memory_attach_device.cfg index f547ed22d53..a6680cf1907 100644 --- a/libvirt/tests/cfg/memory/memory_attach_device.cfg +++ b/libvirt/tests/cfg/memory/memory_attach_device.cfg @@ -13,8 +13,8 @@ guest_required_kernel = [5.8.0,) func_supported_since_libvirt_ver = (8, 0, 0) func_supported_since_qemu_kvm_ver = (6, 2, 0) - vm_attrs = {'max_mem_rt': 10485760, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB', 'vcpu': 4, 'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '1048576', 'unit': 'KiB'}]}} + vm_attrs = {'max_mem_rt': 10485760, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB', 'current_mem': 2097152, 'current_mem_unit':'KiB', 'vcpu': 4, 'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '2097152', 'unit': 'KiB'}]}} mem_device_attrs = {'mem_model': 'virtio-mem', 'target': {'requested_unit': 'KiB', 'size': 262144, 'node': 0, 'size_unit': 'KiB', 'requested_size': 131072, 'block_unit': 'KiB', 'block_size': 2048}} aarch64: - vm_attrs = {'max_mem_rt': 20971520, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB', 'vcpu': 4, 'cpu': {'mode': 'host-passthrough', 'numa_cell': [{'id': '0', 'cpus': '0-3', 'memory': '8388608', 'unit': 'KiB'}]}} + vm_attrs = {'max_mem_rt': 20971520, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB', 'current_mem': 8388608, 'current_mem_unit':'KiB', 'vcpu': 4, 'cpu': {'mode': 'host-passthrough', 'numa_cell': [{'id': '0', 'cpus': '0-3', 'memory': '8388608', 'unit': 'KiB'}]}} mem_device_attrs = {'mem_model': 'virtio-mem', 'target': {'requested_unit': 'KiB', 'size': 1048576, 'node': 0, 'size_unit': 'KiB', 'requested_size': 524288, 'block_unit': 'KiB', 'block_size': 524288}} From 1a20a4a3a386b6d634772e8fbbdb525558d3becb Mon Sep 17 00:00:00 2001 From: nanli Date: Tue, 16 Jul 2024 11:00:37 +0800 Subject: [PATCH 0561/1055] fix package upated for usb case usbredirserver is updated to usbredirect Signed-off-by: nanli --- .../boot_order/boot_from_usb_device.cfg | 2 +- libvirt/tests/cfg/usb/usb_device.cfg | 4 +- .../boot_order/boot_from_usb_device.py | 14 ++---- libvirt/tests/src/usb/usb_device.py | 14 +++--- provider/usb/usb_base.py | 49 +++++++++++++++++++ 5 files changed, 66 insertions(+), 17 deletions(-) create mode 100644 provider/usb/usb_base.py diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg index b3e6924fa5f..a5e8d366a0d 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg @@ -16,6 +16,6 @@ port_num = "4000" device_attrs = {'source': {'host': 'localhost', 'service': '4000', 'mode': 'connect'}, 'protocol': {'type': 'raw'}, 'type_name': 'tcp', 'bus': '${bus_type}', 'type': 'tcp', 'boot': {'order': '1'}} only q35 - required_cmds = ['usbredirserver', 'lsusb'] + required_cmds = ['lsusb'] - hostdev_device: device_attrs = {'type_name': 'usb', 'mode': 'subsystem', 'source': {'vendor_id': '%s', 'product_id': '%s'}, 'type': 'usb', 'managed': 'no', 'boot_order': '1'} diff --git a/libvirt/tests/cfg/usb/usb_device.cfg b/libvirt/tests/cfg/usb/usb_device.cfg index 4928e88485e..a9f11b03844 100644 --- a/libvirt/tests/cfg/usb/usb_device.cfg +++ b/libvirt/tests/cfg/usb/usb_device.cfg @@ -68,7 +68,9 @@ - redirdev: only companion only pcie-to-pci-bridge,pci-root - pkgs_host = "usbutils,usbredir-server" + pkgs_host = "usbutils" +# pkgs_host_rhel9 = ",usbredir-server" +# pkgs_host_rhel10 = ",usbredir-tools" device_name = "redirdev" variants: - spicevmc: diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_usb_device.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_usb_device.py index 5c1d47cf463..4222ec00a58 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_usb_device.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_usb_device.py @@ -15,6 +15,7 @@ from provider.guest_os_booting import guest_os_booting_base as guest_os from provider.backingchain import blockcommand_base +from provider.usb import usb_base from provider.virtual_disk import disk_base @@ -66,9 +67,7 @@ def check_boot_order(): usb_device = params.get("usb_device") bootmenu_dict = eval(params.get("bootmenu_dict", "{}")) device_attrs = eval(params.get("device_attrs", "{}")) - port_num = params.get("port_num") check_prompt = params.get("check_prompt") - required_cmds = eval(params.get("required_cmds", "[]")) vm = env.get_vm(vm_name) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) @@ -76,6 +75,8 @@ def check_boot_order(): test_obj = blockcommand_base.BlockCommand(test, vm, params) disk_obj = disk_base.DiskBase(test, vm, params) + extra_usb_cmd = usb_base.get_host_pkg_and_cmd()[1] + required_cmds = eval(params.get("required_cmds", "[]")) + [extra_usb_cmd] try: for cmd in required_cmds: @@ -90,11 +91,7 @@ def check_boot_order(): vendor_id, product_id = get_usb_source() device_xml = redirdev.Redirdev() device_xml.setup_attrs(**device_attrs) - # start usbredirserver - ps = process.SubProcess("usbredirserver -p {} {}:{}".format - (port_num, vendor_id, product_id), - shell=True) - server_id = ps.start() + usb_base.start_redirect_server(params, extra_usb_cmd, vendor_id, product_id) if usb_device == "hostdev_device": vendor_id, product_id = get_usb_source() vendor_id = "0x" + vendor_id @@ -115,5 +112,4 @@ def check_boot_order(): virsh.destroy(vm_name) disk_obj.cleanup_disk_preparation(disk_type) bkxml.sync() - if 'server_id' in locals(): - process.run("killall usbredirserver") + usb_base.kill_redirect_server(extra_usb_cmd) diff --git a/libvirt/tests/src/usb/usb_device.py b/libvirt/tests/src/usb/usb_device.py index e938c831abf..b790f3fa4f1 100644 --- a/libvirt/tests/src/usb/usb_device.py +++ b/libvirt/tests/src/usb/usb_device.py @@ -10,6 +10,8 @@ from virttest.libvirt_xml.devices.controller import Controller from virttest.libvirt_xml.devices.hub import Hub +from provider.usb import usb_base + # Using as lower capital is not the best way to do, but this is just a # workaround to avoid changing the entire file. @@ -57,6 +59,9 @@ def run(test, params, env): device_type = params.get("device_type", "") device_mode = params.get("device_mode", "") port_num = params.get("port_num", "") + if device_name == "redirdev": + add_pkg, usb_cmd = usb_base.get_host_pkg_and_cmd() + pkgs_host = params.get("pkgs_host", "") + add_pkg pkgs_host = params.get("pkgs_host", "") pkgs_guest = params.get("pkgs_guest", "") usb_hub = "yes" == params.get("usb_hub", "no") @@ -321,10 +326,8 @@ def check_alias(device_alias): # start usbredirserver vendor_id = addr['vendor_id'].lstrip("0x") product_id = addr['product_id'].lstrip("0x") - ps = process.SubProcess("usbredirserver -p {} {}:{}".format - (port, vendor_id, product_id), - shell=True) - server_id = ps.start() + usb_base.start_redirect_server(params, usb_cmd, + vendor_id, product_id) if redirdev_alias: alias_str = "ua-redir" + str(i) + random_id device_alias[port] = alias_str @@ -400,6 +403,5 @@ def check_alias(device_alias): finally: if 'session' in locals(): session.close() - if 'server_id' in locals(): - process.run("killall usbredirserver") + usb_base.kill_redirect_server(usb_cmd) vmxml_backup.sync() diff --git a/provider/usb/usb_base.py b/provider/usb/usb_base.py new file mode 100644 index 00000000000..333c93a2fff --- /dev/null +++ b/provider/usb/usb_base.py @@ -0,0 +1,49 @@ +from avocado.utils import distro +from avocado.utils import process + + +def get_host_pkg_and_cmd(): + """ + Get package and related command on the host. + + :return: pkg_and_cmd, extra usb package name and command. + """ + if int(distro.detect().version) <= 9: + pkg_and_cmd = ("usbredir-server", "usbredirserver") + else: + pkg_and_cmd = ("usbredir-tools", "usbredirect") + return pkg_and_cmd + + +def start_redirect_server(params, usb_cmd, vendor_id, product_id): + """ + Start redirect server + + :param params: Dict with test params. + :param usb_cmd, the usb command to confirm how to start server. + :param vendor_id, vendor id. + :param product_id, produce id. + :return server_id, redirect server id + """ + port_num = params.get("port_num") + if usb_cmd == "usbredirserver": + ps = process.SubProcess("usbredirserver -p {} {}:{}".format + (port_num, vendor_id, product_id), + shell=True) + elif usb_cmd == "usbredirect": + ps = process.SubProcess( + "usbredirect --device {}:{} --as {}:{}".format + (vendor_id, product_id, "127.0.0.1", port_num), + shell=True) + server_id = ps.start() + return server_id + + +def kill_redirect_server(usb_cmd): + """ + Kill redirect server + + :param usb_cmd, the usb command to kill server. + """ + if 'server_id' in globals(): + process.run("killall {}".format(usb_cmd), ignore_status=True) From a0f32de8024c022feb864dd2d28bd10a22346866 Mon Sep 17 00:00:00 2001 From: Slancaster1 Date: Fri, 12 Jul 2024 15:12:19 -0400 Subject: [PATCH 0562/1055] vm_create_destroy_concurrently: Reliability Test -- The Issue Libvirt provides unique UUIDs to every VM, in order to uniquely identify the VMs. When transient VMs are created, libvirt allows it to have a non-unique name/UUID. So long as any other VM with the same name/UUID is a persistant VM, that is not running If a race condition occurs, and two transient VMs with the same name/UUID are created. Libvirt my crash, and orphan VMs will be crated -- The Test: 1. Create several loops that continuosly start and destroy a transient VM. 1a. Python's GIL prevents the same bytecodes from executing at the same time 1b. To ensure that a race condition can happen, the vms are created from an external bash script 2. Wait for a given number of seconds (run_time in cfg file), stop the loops 3. Make sure that libvirtd has not crashed 3a. This is done by check to make sure the libvirt daemon(s) have the same pid at the start and end of the test 4. Ensure there are no orphan VMs Signed-off-by: Slancaster1 --- .../cfg/vm_create_destroy_concurrently.cfg | 5 + .../src/vm_create_destroy_concurrently.py | 141 ++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 libvirt/tests/cfg/vm_create_destroy_concurrently.cfg create mode 100644 libvirt/tests/src/vm_create_destroy_concurrently.py diff --git a/libvirt/tests/cfg/vm_create_destroy_concurrently.cfg b/libvirt/tests/cfg/vm_create_destroy_concurrently.cfg new file mode 100644 index 00000000000..5f78d9bdfd3 --- /dev/null +++ b/libvirt/tests/cfg/vm_create_destroy_concurrently.cfg @@ -0,0 +1,5 @@ +- vm_create_destroy_concurrently: + type = vm_create_destroy_concurrently + start_vm = no + num_threads = 3 + run_time = 1800 diff --git a/libvirt/tests/src/vm_create_destroy_concurrently.py b/libvirt/tests/src/vm_create_destroy_concurrently.py new file mode 100644 index 00000000000..6794665c340 --- /dev/null +++ b/libvirt/tests/src/vm_create_destroy_concurrently.py @@ -0,0 +1,141 @@ +from virttest.libvirt_xml import vm_xml +from virttest import data_dir, utils_libvirtd, utils_sys + +import logging +import subprocess + + +def create_scripts(vmxml, num_scripts, timeout): + """ + Create scripts for creating and destroying + VMs. We create separate scripts so we can + execute them concurrently, and overcome + python's GIL + + :param vmxml: Base xml for the VMs + that will be created + + :param num_scripts: number of scripts to + create + + :param timeout: amount of time to spend creating + and destroying VMs + """ + tmp_dir = data_dir.get_tmp_dir(public=False) + vm_name = vmxml.vm_name + script_names = [] + + for i in range(num_scripts): + xml_path = tmp_dir + "/xml_" + str(i) + ".xml" + sh_path = tmp_dir + "/script_" + str(i) + ".sh" + + # SELinux does not allow multiple VM operations the same qcow2 files + vmxml.remove_all_disk() + + for item in ["loader", "nvram"]: + if item in str(vmxml): + vmxml.xmltreefile.remove_by_xpath("/os/%s" % item, remove_all=True) + + with open(xml_path, "w") as outfile: + outfile.write(str(vmxml)) + + logging.debug("Written vm xml file to {}".format(xml_path)) + logging.info("VM XML Contents: \n{}".format(str(vmxml))) + + with open(sh_path, "w") as outfile: + script = """ + end=$((SECONDS+{})); + while [ $SECONDS -lt $end ] ; do + virsh create {} || continue ; + virsh destroy {} ; + done ; + """.format(timeout, xml_path, vm_name) + outfile.write(script) + logging.debug("Script file contents {}".format(script)) + + logging.debug("Written script file to {}".format(sh_path)) + + script_names.append(sh_path) + + return script_names + + +def get_pids_for(names): + """ + Given a list of names, retrieve the + PIDs for matching processes + + Sort of equivalent to: 'ps aux | grep name' + + :param names: List of process names to look for + """ + + pids = utils_sys.get_pids_for(names) + logging.info("Processes and Pids matching {}: {}".format(names, pids)) + + return pids + + +def get_libvirt_pids(test, daemon): + """ + Given a Libvirtd daemon object, retrieve the + pids relevant to the libvirt services + + :param test: Avocado test object + :param daemon: Avocado-vt libvirtd daemon + object. Provides list of libvirt services + """ + if not daemon.is_running(): + test.fail("No libvirt daemon running") + + return get_pids_for(daemon.service_list) + + +def run(test, params, env): + """ + This test ensures that VMs can be created concurrently. + Test Process: + 1) Create bash scripts to create and destroy transient VMs + 2) Execute the scripts simultaneously for a given number of seconds + 3) Check that libvirt daemon(s) have not changed PID + 4) Check to ensure there are no orphan VMs + """ + + daemon = utils_libvirtd.Libvirtd() + pids_before_test = get_libvirt_pids(test, daemon) + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + + num_threads = int(params.get("num_threads", 3)) + wait_time = int(params.get("run_time", 60)) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + scripts = create_scripts(vmxml, num_threads, wait_time) + + processes = [] + for i in range(num_threads): + process = subprocess.Popen(["/bin/bash", scripts[i]], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + processes.append(process) + + exit_codes = [p.wait() for p in processes] + + for i in range(len(exit_codes)): + if exit_codes[i] != 0: + fail = processes[i] + logging.debug("Script did not exit cleanly") + logging.debug("\tstderr: {}".format(fail.stderr.read())) + logging.debug("\tstdout: {}".format(fail.stdout.read())) + + if [x for x in exit_codes if x != 0] != []: + test.fail("Test Failed with script errors") + + pids_after_test = get_libvirt_pids(test, daemon) + if pids_before_test != pids_after_test: + logging.debug("Pids Before Test: {}".format(pids_before_test)) + logging.debug("Pids After Test: {}".format(pids_after_test)) + test.fail("Libvirt pids changed") + + vm_pids = get_pids_for([vm_name]) + if vm_pids != []: + test.fail("Orphan VM(s): PID(s) {} belonging to {}".format(vm_pids, vm_name)) From 578c68aed31552d55d73b053554a69a3bcec5a2b Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Fri, 9 Aug 2024 03:55:07 -0400 Subject: [PATCH 0563/1055] Add virtio-mem device lifecycle test case Signed-off-by: liang-cong-red-hat --- .../virtio_mem_device_lifecycle.cfg | 70 ++++++ .../virtio_mem_device_lifecycle.py | 221 ++++++++++++++++++ 2 files changed, 291 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_devices/virtio_mem_device_lifecycle.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/virtio_mem_device_lifecycle.py diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_device_lifecycle.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_device_lifecycle.cfg new file mode 100644 index 00000000000..cd62f1a8744 --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_device_lifecycle.cfg @@ -0,0 +1,70 @@ +- memory.devices.virtio_mem.lifecycle: + type = virtio_mem_device_lifecycle + no s390-virtio + start_vm = no + state_file = "/tmp/%s.save" + numa_mem_val = 1048576 + memory_val = 2097152 + current_mem_val = 2097152 + aarch64: + numa_mem_val = 4194304 + memory_val = 8388608 + current_mem_val = 8388608 + vm_attrs = {'max_mem_rt': 15428800, 'max_mem_rt_unit': 'KiB','memory_unit':"KiB", 'memory':${memory_val}, 'current_mem':${current_mem_val}, 'current_mem_unit':'KiB', 'vcpu': 4,'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem_val}', 'unit': 'KiB'},{'id':'1','cpus': '2-3','memory':'${numa_mem_val}','unit':'KiB'}]}} + init_alias_name = virtiomem0 + plug_alias_name = virtiomem1 + required_kernel = [5.14.0,) + guest_required_kernel = [5.8.0,) + func_supported_since_libvirt_ver = (8, 0, 0) + func_supported_since_qemu_kvm_ver = (6, 2, 0) + variants kernel_pagesize: + - 4k: + only x86_64, aarch64 + page_size = 4 + default_hp_size = 2048 + - 64k: + only aarch64 + page_size = 64 + default_hp_size = 524288 + variants memory_source: + - no_source: + source_dict = {} + source_xpath = [] + - nodemask: + nodeset_num = 1 + source_dict = {'nodemask':'%s'} + source_xpath = [{'element_attrs':[".//source/nodemask"],'text':'%s'}] + - pagesize: + source_dict = {'pagesize':${page_size}, 'pagesize_unit':'KiB'} + source_xpath = [{'element_attrs':[".//source/pagesize[@unit='KiB']"],'text':'${page_size}'}] + - nodemask_pagesize: + nodeset_num = 2 + use_huge_page = "yes" + source_dict = {'nodemask':'%s', 'pagesize':${default_hp_size}, 'pagesize_unit':'KiB'} + source_xpath = [{'element_attrs':[".//source/nodemask"],'text':'%s'}, {'element_attrs':[".//source/pagesize[@unit='KiB']"],'text':'${default_hp_size}'}] + variants memory_target: + - all_requested_and_address: + init_size = 524288 + init_requested = ${init_size} + init_address = '0x240000000' + plug_size = 1048576 + plug_requested = ${plug_size} + plug_address = '0x300000000' + init_target_dict = {'size':${init_size}, 'size_unit':'KiB', 'node':0, 'requested_size':${init_requested}, 'requested_unit':'KiB', 'block_size':${default_hp_size}, 'address':{'attrs':{'base':'${init_address}'}}} + init_target_xpath = [{'element_attrs':[".//target/size[@unit='KiB']"],'text':'${init_size}'}, {'element_attrs':[".//target/requested[@unit='KiB']"],'text':'${init_requested}'}, {'element_attrs':[".//target/block[@unit='KiB']"],'text':'${default_hp_size}'}, {'element_attrs':[".//target/current[@unit='KiB']"],'text':'${init_requested}'}, {'element_attrs':[".//target/node"],'text':'0'}, {'element_attrs':[".//target/address[@base='${init_address}']"]}] + plug_target_dict = {'size':${plug_size}, 'size_unit':'KiB', 'node':1, 'requested_size':${plug_requested}, 'requested_unit':'KiB', 'block_size':${default_hp_size}, 'address':{'attrs':{'base':'${plug_address}'}}} + plug_target_xpath = [{'element_attrs':[".//target/size[@unit='KiB']"],'text':'${plug_size}'}, {'element_attrs':[".//target/requested[@unit='KiB']"],'text':'${plug_requested}'}, {'element_attrs':[".//target/block[@unit='KiB']"],'text':'${default_hp_size}'}, {'element_attrs':[".//target/current[@unit='KiB']"],'text':'${plug_requested}'}, {'element_attrs':[".//target/node"],'text':'1'}, {'element_attrs':[".//target/address[@base='${plug_address}']"]}] + - part_requested_and_no_address: + init_size = 1048576 + init_requested = 524288 + plug_size = 2097152 + plug_requested = 1048576 + init_target_dict = {'size':${init_size}, 'size_unit':'KiB', 'node':0, 'requested_size':${init_requested}, 'requested_unit':'KiB', 'block_size':${default_hp_size}} + init_target_xpath = [{'element_attrs':[".//target/size[@unit='KiB']"],'text':'${init_size}'}, {'element_attrs':[".//target/requested[@unit='KiB']"],'text':'${init_requested}'}, {'element_attrs':[".//target/block[@unit='KiB']"],'text':'${default_hp_size}'}, {'element_attrs':[".//target/current[@unit='KiB']"],'text':'${init_requested}'}, {'element_attrs':[".//target/node"],'text':'0'}, {'element_attrs':[".//target/address"]}] + plug_target_dict = {'size':${plug_size}, 'size_unit':'KiB', 'node':1, 'requested_size':${plug_requested}, 'requested_unit':'KiB', 'block_size':${default_hp_size}} + plug_target_xpath = [{'element_attrs':[".//target/size[@unit='KiB']"],'text':'${plug_size}'}, {'element_attrs':[".//target/requested[@unit='KiB']"],'text':'${plug_requested}'}, {'element_attrs':[".//target/block[@unit='KiB']"],'text':'${default_hp_size}'}, {'element_attrs':[".//target/current[@unit='KiB']"],'text':'${plug_requested}'}, {'element_attrs':[".//target/node"],'text':'1'}, {'element_attrs':[".//target/address"]}] + init_mem_device_dict = {'mem_model':'virtio-mem', 'source':${source_dict}, 'target':${init_target_dict}} + init_xpath_list = [${source_xpath}, ${init_target_xpath}] + plug_mem_device_dict = {'mem_model':'virtio-mem', 'source':${source_dict}, 'target':${plug_target_dict}} + plug_xpath_list = [${source_xpath}, ${plug_target_xpath}] + diff --git a/libvirt/tests/src/memory/memory_devices/virtio_mem_device_lifecycle.py b/libvirt/tests/src/memory/memory_devices/virtio_mem_device_lifecycle.py new file mode 100644 index 00000000000..388fac4d96a --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/virtio_mem_device_lifecycle.py @@ -0,0 +1,221 @@ +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: Liang Cong +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +import os + +from virttest import utils_libvirtd +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.devices import memory +from virttest import test_setup +from virttest import utils_misc +from virttest.utils_libvirt import libvirt_memory +from virttest.utils_libvirt import libvirt_vmxml + +from provider.memory import memory_base +from provider.numa import numa_base + + +def run(test, params, env): + """ + Verify various config of dimm memory device settings take effect + during the life cycle of guest vm. + """ + + def clean_empty_memory_device_config(mem_device_dict): + """ + Clean empty config of the memory device + + :param mem_device_dict (dict): memory device config dictionary + """ + for key in list(mem_device_dict.keys()): + if not mem_device_dict[key]: + del mem_device_dict[key] + + def check_virtio_mem_device_xml(xpath_dict): + """ + Check the virtio-mem memory device config by xpath + + :param xpath_dict (dict): xpath dict to check if the memory config is correct, + like {"alias_name":[xpath1, xpath2]},...} + """ + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + memory_devices = vmxml.devices.by_device_tag('memory') + target_memory_num = 0 + for alias_name, xpath_list in xpath_dict.items(): + for memory_device in memory_devices: + if alias_name == memory_device.alias.get('name'): + target_memory_num = target_memory_num + 1 + for xpath in xpath_list: + libvirt_vmxml.check_guest_xml_by_xpaths(memory_device, xpath) + if target_memory_num != len(xpath_dict): + test.fail('Expected %d virtio-mem mem devices with required alias name, but found %d' + % (len(xpath_dict), target_memory_num)) + + def check_current_mem_size(alias_name, expect_current_size): + """ + Check if virtio-mem memory with alias_name has expected current memory size + + :param alias_name (str): alias name of the virtio-mem device + :param expect_current_size (int): expected current memory size of the virtio-mem device + + :return: bool, true if virtio-mem memory with alias_name has expected current memory size + """ + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + memory_devices = vmxml.devices.by_device_tag('memory') + for memory_device in memory_devices: + if alias_name == memory_device.alias.get('name') and memory_device.target.current_size == expect_current_size: + return True + return False + + def check_case_availability(): + """ + Check whether the case is available + """ + memory_base.check_mem_page_sizes(test, page_size, default_hp_size) + memory_base.check_supported_version(params, test, vm) + + def setup_test(): + """ + Setup for the case: + 1. Get host available numa nodes + 2. Change parameters according to available numa nodes + 3. Allocate huge page memory for target host node if needs + """ + if nodeset_num: + numatest_obj = numa_base.NumaTest(vm, params, test) + if 1 == nodeset_num: + min_memory_size = init_size + plug_size + elif 2 == nodeset_num: + min_memory_size = init_size if init_size >= plug_size else plug_size + numatest_obj.check_numa_nodes_availability(nodeset_num, min_memory_size) + numa_list = numatest_obj.get_available_numa_nodes(min_memory_size)[:nodeset_num] + nodeset_str = numa_base.convert_to_string_with_dash( + ','.join([str(node) for node in numa_list])) + source_dict = params.get("source_dict") + source_xpath = params.get("source_xpath") + source_dict = eval(source_dict % nodeset_str) + source_xpath = eval(source_xpath % nodeset_str) + init_mem_device_dict["source"] = source_dict + plug_mem_device_dict["source"] = source_dict + init_xpath_list[0] = source_xpath + plug_xpath_list[0] = source_xpath + test.log.debug("Selected numa nodeset is:%s", nodeset_str) + + if use_huge_page: + params["target_nodes"] = " ".join([str(node) for node in numa_list]) + params["target_hugepages"] = (init_size + plug_size) / default_hp_size + hpc = test_setup.HugePageConfig(params) + hpc.setup() + + if vm.is_alive(): + vm.destroy() + + def run_test(): + """ + Test steps + """ + test.log.info("TEST_STEP1: Define the guest") + clean_empty_memory_device_config(init_mem_device_dict) + memory_base.define_guest_with_memory_device(params, init_mem_device_dict, vm_attrs) + + test.log.info("TEST_STEP2: Start the guest") + vm.start() + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + test.log.debug("Guest config xml after start is:\n%s", vmxml) + + test.log.info("TEST_STEP3: Wait for the guest os is boot up," + "Check virtio-mem memory device config by virsh dumpxml") + vm.wait_for_login().close() + check_virtio_mem_device_xml({init_alias_name: init_xpath_list}) + + test.log.info("TEST_STEP4: Hotplug a virtio-mem memory device") + clean_empty_memory_device_config(plug_mem_device_dict) + mem_device = memory.Memory() + mem_device.setup_attrs(**plug_mem_device_dict) + virsh.attach_device(vm_name, mem_device.xml, debug=True, ignore_status=False) + if not utils_misc.wait_for( + lambda: check_current_mem_size(plug_alias_name, plug_requested), 20): + test.fail('Hot-plugged virtio-mem mem devices with alias name %s should have ' + 'current memory size %d' % (plug_alias_name, plug_requested)) + + test.log.info("TEST_STEP5: Consume the guest memory") + session = vm.wait_for_login() + libvirt_memory.consume_vm_freememory(session) + + test.log.info( + "TEST_STEP6: Check virtio-mem memory device config by virsh dumpxml") + check_virtio_mem_device_xml({init_alias_name: init_xpath_list, plug_alias_name: plug_xpath_list}) + + test.log.info("TEST_STEP7: Life cycle test") + virsh.suspend(vm_name, ignore_status=False, debug=True) + virsh.resume(vm_name, ignore_status=False, debug=True) + check_virtio_mem_device_xml({init_alias_name: init_xpath_list, plug_alias_name: plug_xpath_list}) + + virsh.save(vm_name, state_file, ignore_status=False, debug=True) + virsh.restore(state_file, ignore_status=False, debug=True) + check_virtio_mem_device_xml({init_alias_name: init_xpath_list, plug_alias_name: plug_xpath_list}) + + virsh.managedsave(vm_name, ignore_status=False, debug=True) + vm.start() + check_virtio_mem_device_xml({init_alias_name: init_xpath_list, plug_alias_name: plug_xpath_list}) + + vm.reboot() + vm.wait_for_login().close() + check_virtio_mem_device_xml({init_alias_name: init_xpath_list, plug_alias_name: plug_xpath_list}) + + utils_libvirtd.libvirtd_restart() + check_virtio_mem_device_xml({init_alias_name: init_xpath_list, plug_alias_name: plug_xpath_list}) + + def teardown_test(): + """ + 1. Restore guest config xml + 2. Clean huge page memory + 3. Remove state file + """ + bkxml.sync() + if use_huge_page: + hpc = test_setup.HugePageConfig(params) + hpc.cleanup() + if os.path.exists(state_file): + os.remove(state_file) + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + vm_attrs = eval(params.get("vm_attrs", "{}")) + init_mem_device_dict = eval( + params.get("init_mem_device_dict", "{}")) + plug_mem_device_dict = eval( + params.get("plug_mem_device_dict", "{}")) + init_xpath_list = eval(params.get("init_xpath_list")) + plug_xpath_list = eval(params.get("plug_xpath_list")) + init_alias_name = params.get("init_alias_name") + plug_alias_name = params.get("plug_alias_name") + plug_requested = int(params.get("plug_requested")) + page_size = int(params.get("page_size")) + default_hp_size = int(params.get("default_hp_size")) + init_size = int(params.get("init_size")) + plug_size = int(params.get("plug_size")) + nodeset_num = int(params.get("nodeset_num", "0")) + use_huge_page = "yes" == params.get("use_huge_page") + state_file = params.get('state_file', '/tmp/%s.save') % vm_name + + try: + check_case_availability() + setup_test() + run_test() + + finally: + teardown_test() From 70a545f1e5050e84aad46ab8580154106d6f7eca Mon Sep 17 00:00:00 2001 From: Meina Li Date: Wed, 28 Aug 2024 22:30:53 -0400 Subject: [PATCH 0564/1055] Transitional_memballoon: update memory size to test in aarch64 With the default memory size, the guest can't boot in aarch64. So update it to be also covered in aarch64. Signed-off-by: Meina Li --- .../tests/cfg/virtio_transitional/virtio_transitional_blk.cfg | 1 - .../virtio_transitional/virtio_transitional_mem_balloon.cfg | 4 +++- .../tests/cfg/virtio_transitional/virtio_transitional_nic.cfg | 2 +- .../tests/cfg/virtio_transitional/virtio_transitional_rng.cfg | 1 - .../cfg/virtio_transitional/virtio_transitional_vsock.cfg | 1 - .../virtio_transitional/virtio_transitional_mem_balloon.py | 3 +++ 6 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_blk.cfg b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_blk.cfg index 610be54b504..9acf8a2f686 100644 --- a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_blk.cfg +++ b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_blk.cfg @@ -45,7 +45,6 @@ at_disk_bus = scsi variants: - @default: - only q35 only boot_test no virtio_transitional - rhel6_guest: diff --git a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_mem_balloon.cfg b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_mem_balloon.cfg index 8897edf68b4..54a45813e42 100644 --- a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_mem_balloon.cfg +++ b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_mem_balloon.cfg @@ -1,7 +1,7 @@ - virtio_transitional_mem_balloon: type = virtio_transitional_mem_balloon - only q35 start_vm = no + vm_memory = 8388608 variants: - virtio: virtio_model = "virtio" @@ -13,7 +13,9 @@ virtio_model = "virtio-non-transitional" variants: - @default: + no virtio_transitional - rhel6_guest: + only q35 os_variant = rhel6 image_path = images/rhel6-x86_64-latest.qcow2 guest_src_url = "http://download.libvirt.redhat.com/libvirt-CI-resources/RHEL-6.10-x86_64-latest.qcow2" diff --git a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_nic.cfg b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_nic.cfg index 23ccd230968..ab1e7985527 100644 --- a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_nic.cfg +++ b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_nic.cfg @@ -26,10 +26,10 @@ virtio_model = "virtio-non-transitional" variants: - @default: - only q35 only boot_test no virtio_transitional - rhel6_guest: + only q35 os_variant = rhel6 only virtio_transitional no Windows diff --git a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_rng.cfg b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_rng.cfg index 9795928c29d..9d21214f0ca 100644 --- a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_rng.cfg +++ b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_rng.cfg @@ -18,7 +18,6 @@ hotplug = yes variants: - @default: - only q35 only boot_test no virtio_transitional disk_model = ${virtio_model} diff --git a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_vsock.cfg b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_vsock.cfg index c647734bd4a..4200c1ff4fc 100644 --- a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_vsock.cfg +++ b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_vsock.cfg @@ -20,7 +20,6 @@ hotplug = yes variants: - @default: - only q35 only boot_test no virtio_transitional - rhel6_guest: diff --git a/libvirt/tests/src/virtio_transitional/virtio_transitional_mem_balloon.py b/libvirt/tests/src/virtio_transitional/virtio_transitional_mem_balloon.py index 3946c86e187..3e275dc37eb 100644 --- a/libvirt/tests/src/virtio_transitional/virtio_transitional_mem_balloon.py +++ b/libvirt/tests/src/virtio_transitional/virtio_transitional_mem_balloon.py @@ -45,6 +45,7 @@ def run(test, params, env): os_variant = params.get("os_variant", "") params["disk_model"] = virtio_model set_crypto_policy = params.get("set_crypto_policy") + vm_memory = int(params.get("vm_memory")) if not libvirt_version.version_compare(5, 0, 0): test.cancel("This libvirt version doesn't support " @@ -68,6 +69,8 @@ def run(test, params, env): libvirt.modify_vm_iface(vm_name, "update_iface", iface_params) # Remove nvram setting for rhel6 guest virtio_transitional_base.remove_rhel6_nvram(vm_name) + vmxml.memory = vm_memory + vmxml.sync() libvirt.set_vm_disk(vm, params) # The local variable "vmxml" will not be updated since set_vm_disk # sync with another dumped xml inside the function From d7c29026fc00a1b738eaf50ffa2d134193d96048 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 27 Aug 2024 14:46:09 +0800 Subject: [PATCH 0565/1055] viommu: Add a test scenario about 'virsh reset' This pr adds 'virsh reset' into viommu lifecycle testing. Signed-off-by: Yingshun Cui --- .../sriov/vIOMMU/iommu_device_lifecycle.cfg | 1 + .../sriov/vIOMMU/iommu_device_lifecycle.py | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_lifecycle.cfg b/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_lifecycle.cfg index b23e8ab2385..1950bda758e 100644 --- a/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_lifecycle.cfg +++ b/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_lifecycle.cfg @@ -40,3 +40,4 @@ - suspend_resume: - reboot_many_times: loop_time = 5 + - reset: diff --git a/libvirt/tests/src/sriov/vIOMMU/iommu_device_lifecycle.py b/libvirt/tests/src/sriov/vIOMMU/iommu_device_lifecycle.py index 7b82bcb1c3b..4d77baf66b4 100644 --- a/libvirt/tests/src/sriov/vIOMMU/iommu_device_lifecycle.py +++ b/libvirt/tests/src/sriov/vIOMMU/iommu_device_lifecycle.py @@ -57,17 +57,26 @@ def run(test, params, env): test.log.info("TEST_STEP: Start the VM.") vm.start() test.log.debug(vm_xml.VMXML.new_from_dumpxml(vm.name)) - if test_scenario == "reboot_many_times": + if test_scenario in ["reboot_many_times", "reset"]: vm.cleanup_serial_console() vm.create_serial_console() - for _ in range(int(params.get('loop_time', '5'))): - test.log.info("TEST_STEP: Reboot the VM.") + if test_scenario == "reset": + test.log.info("TEST_STEP: Reset the VM.") session = vm.wait_for_serial_login( timeout=int(params.get('login_timeout'))) - session.sendline(params.get("reboot_command")) - _match, _text = session.read_until_output_matches( + virsh.reset(vm.name, **VIRSH_ARGS) + _match, _text = session.read_until_last_line_matches( [r"[Ll]ogin:\s*"], timeout=240, internal_timeout=0.5) session.close() + else: + for _ in range(int(params.get('loop_time', '5'))): + test.log.info("TEST_STEP: Reboot the VM.") + session = vm.wait_for_serial_login( + timeout=int(params.get('login_timeout'))) + session.sendline(params.get("reboot_command")) + _match, _text = session.read_until_last_line_matches( + [r"[Ll]ogin:\s*"], timeout=240, internal_timeout=0.5) + session.close() session = vm.wait_for_serial_login( timeout=int(params.get('login_timeout'))) From 3e59b177b03d41e6deb03d8480d7ad101cfe49eb Mon Sep 17 00:00:00 2001 From: Yanqiu Zhang Date: Thu, 29 Aug 2024 03:37:53 -0400 Subject: [PATCH 0566/1055] tpm_device: fix source_socket error source_socket accessed when it's not exist, which blocking real vm start error. Signed-off-by: Yanqiu Zhang --- libvirt/tests/src/virtual_device/tpm_device.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_device/tpm_device.py b/libvirt/tests/src/virtual_device/tpm_device.py index b8627650d4f..a546f798946 100644 --- a/libvirt/tests/src/virtual_device/tpm_device.py +++ b/libvirt/tests/src/virtual_device/tpm_device.py @@ -833,7 +833,7 @@ def check_swtpmpidfile(vm_name, test_stage): try: vm.start() except VMStartError as detail: - if secret_value == 'none' or secret_uuid == 'nonexist' or not source_socket: + if secret_value == 'none' or secret_uuid == 'nonexist' or (source_attrs_str and not source_socket): logging.debug("Expected failure: %s", detail) return else: From 6f43ed4dd93ee600809527921fed5805e957801b Mon Sep 17 00:00:00 2001 From: lcheng Date: Fri, 30 Aug 2024 14:54:11 +0800 Subject: [PATCH 0567/1055] migration: Add two case about migrate_tls_x509_verify XXX-298257 - [VM migration] network data transport - TLS - default/migrate_tls_x509_verify on src host XXX-293815 - [VM migration] network data transport - TLS - default/migrate_tls_x509_verify on target host(enable/disable verify client) Signed-off-by: lcheng --- .../tls_migrate_tls_x509_verify_on_src.cfg | 44 ++++++ .../tls_migrate_tls_x509_verify_on_target.cfg | 75 +++++++++ .../tls_migrate_tls_x509_verify.py | 149 ++++++++++++++++++ 3 files changed, 268 insertions(+) create mode 100644 libvirt/tests/cfg/migration/migration_uri/tls_migrate_tls_x509_verify_on_src.cfg create mode 100644 libvirt/tests/cfg/migration/migration_uri/tls_migrate_tls_x509_verify_on_target.cfg create mode 100644 libvirt/tests/src/migration/migration_uri/tls_migrate_tls_x509_verify.py diff --git a/libvirt/tests/cfg/migration/migration_uri/tls_migrate_tls_x509_verify_on_src.cfg b/libvirt/tests/cfg/migration/migration_uri/tls_migrate_tls_x509_verify_on_src.cfg new file mode 100644 index 00000000000..88111031671 --- /dev/null +++ b/libvirt/tests/cfg/migration/migration_uri/tls_migrate_tls_x509_verify_on_src.cfg @@ -0,0 +1,44 @@ +- migration.migration_uri.network_data_transport.tls.migrate_tls_x509_verify_on_src: + type = tls_migrate_tls_x509_verify + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + status_error = "no" + check_network_accessibility_after_mig = "yes" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + custom_pki_path = "/etc/pki/qemu" + qemu_tls = "yes" + server_cn = "wrong-hostname" + client_cn = "ENTER.YOUR.EXAMPLE.CLIENT_CN" + qemu_conf_path = '/etc/libvirt/qemu.conf' + transport_type = "tls" + test_case = "migrate_tls_x509_verify_on_src" + err_msg = "Certificate does not match the hostname" + status_error = "yes" + qemu_conf_src = '{"default_tls_x509_verify": "0", "migrate_tls_x509_verify": "0"}' + virsh_migrate_extra = "--tls" + variants: + - p2p: + virsh_migrate_options = '--live --p2p --verbose' + - non_p2p: + virsh_migrate_options = '--live --verbose' diff --git a/libvirt/tests/cfg/migration/migration_uri/tls_migrate_tls_x509_verify_on_target.cfg b/libvirt/tests/cfg/migration/migration_uri/tls_migrate_tls_x509_verify_on_target.cfg new file mode 100644 index 00000000000..16e6a474895 --- /dev/null +++ b/libvirt/tests/cfg/migration/migration_uri/tls_migrate_tls_x509_verify_on_target.cfg @@ -0,0 +1,75 @@ +- migration.migration_uri.network_data_transport.tls.migrate_tls_x509_verify_on_target: + type = tls_migrate_tls_x509_verify + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + status_error = "no" + check_network_accessibility_after_mig = "yes" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + custom_pki_path = "/etc/pki/qemu" + qemu_tls = "yes" + server_cn = "ENTER.YOUR.EXAMPLE.SERVER_CN" + client_cn = "ENTER.YOUR.EXAMPLE.CLIENT_CN" + qemu_conf_path = '/etc/libvirt/qemu.conf' + cert_path = "${custom_pki_path}/client-cert.pem" + tmp_cert_path = "/tmp/client-cert.pem" + transport_type = "tls" + test_case = "migrate_tls_x509_verify_on_target" + virsh_migrate_extra = "--tls" + variants: + - p2p: + virsh_migrate_options = '--live --p2p --verbose' + - non_p2p: + virsh_migrate_options = '--live --verbose' + variants: + - both_to_default: + # Use default value for default_tls_x509_verify and migrate_tls_x509_verify + default_qemu_conf = ["default_tls_x509_verify", "migrate_tls_x509_verify"] + err_msg = "Cannot read from TLS channel: Software caused connection abort" + migrate_again = "yes" + status_error = "yes" + migrate_again_status_error = "no" + - set_migrate_to_0: + default_qemu_conf = ["default_tls_x509_verify"] + qemu_conf_dest = '{r".*migrate_tls_x509_verify\s*=.*": "migrate_tls_x509_verify=0"}' + status_error = "no" + - set_default_to_0: + default_qemu_conf = ["migrate_tls_x509_verify"] + qemu_conf_dest = '{r".*default_tls_x509_verify\s*=.*": "default_tls_x509_verify=0"}' + status_error = "no" + - set_default_to_0_and_migrate_to_1: + qemu_conf_dest = '{r".*default_tls_x509_verify\s*=.*": "default_tls_x509_verify=0", r".*migrate_tls_x509_verify\s*=.*": "migrate_tls_x509_verify=1"}' + err_msg = "Cannot read from TLS channel: Software caused connection abort" + migrate_again = "yes" + status_error = "yes" + migrate_again_status_error = "no" + - set_default_to_1_and_migrate_to_0: + qemu_conf_dest = '{r".*default_tls_x509_verify\s*=.*": "default_tls_x509_verify=1", r".*migrate_tls_x509_verify\s*=.*": "migrate_tls_x509_verify=0"}' + status_error = "no" + - set_default_to_1: + default_qemu_conf = ["migrate_tls_x509_verify"] + qemu_conf_dest = '{r".*default_tls_x509_verify\s*=.*": "default_tls_x509_verify=1"}' + err_msg = "Cannot read from TLS channel: Software caused connection abort" + migrate_again = "yes" + status_error = "yes" + migrate_again_status_error = "no" diff --git a/libvirt/tests/src/migration/migration_uri/tls_migrate_tls_x509_verify.py b/libvirt/tests/src/migration/migration_uri/tls_migrate_tls_x509_verify.py new file mode 100644 index 00000000000..66453d80b08 --- /dev/null +++ b/libvirt/tests/src/migration/migration_uri/tls_migrate_tls_x509_verify.py @@ -0,0 +1,149 @@ +import os +import shutil + +from virttest import libvirt_remote + +from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_config + +from provider.migration import base_steps + + +def update_qemu_conf_on_src(params, test, local_obj): + """ + Update qemu configure file on source + + :param params: Dictionary with the test parameter + :param test: Test object + :param local_obj: Local qemu conf object + """ + qemu_conf_src = eval(params.get("qemu_conf_src", "{}")) + + local_obj.append(libvirt.customize_libvirt_config(qemu_conf_src, + "qemu", + remote_host=False, + extra_params=params)) + + +def update_qemu_conf_on_target(params, test, remote_obj): + """ + Update qemu configure file on target + + :param params: Dictionary with the test parameter + :param test: Test object + :param remote_obj: Remote qemu conf object + """ + default_qemu_conf = params.get("default_qemu_conf") + qemu_conf_path = params.get("qemu_conf_path") + qemu_conf_dest = params.get("qemu_conf_dest", "{}") + + if default_qemu_conf: + params['file_path'] = qemu_conf_path + remote_obj.append(libvirt_config.remove_key_in_conf(eval(default_qemu_conf), + "qemu", + remote_params=params, + restart_libvirt=True)) + if qemu_conf_dest: + remote_obj.append(libvirt_remote.update_remote_file(params, + qemu_conf_dest, + qemu_conf_path)) + + +def run(test, params, env): + """ + Test default_tls_x509_verify/migrate_tls_x509_verify on source/target host. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def setup_migrate_tls_x509_verify_on_target(): + """ + Setup steps for migrate_tls_x509_verify_on_target + + """ + test.log.info("Setup steps for migrate_tls_x509_verify_on_target.") + cert_path = params.get("cert_path") + tmp_cert_path = params.get("tmp_cert_path") + + update_qemu_conf_on_target(params, test, remote_obj) + migration_obj.setup_connection() + if os.path.exists(tmp_cert_path): + os.remove(tmp_cert_path) + shutil.move(cert_path, tmp_cert_path) + + def setup_migrate_tls_x509_verify_on_src(): + """ + Setup steps for migrate_tls_x509_verify_on_src + + """ + test.log.info("Setup steps for migrate_tls_x509_verify_on_src.") + + update_qemu_conf_on_src(params, test, local_obj) + migration_obj.setup_connection() + + def run_migration_again_migrate_tls_x509_verify_on_target(): + """ + Run migration again for migrate_tls_x509_verify_on_target + + """ + test.log.info("Run migration again for migrate_tls_x509_verify_on_target.") + cert_path = params.get("cert_path") + tmp_cert_path = params.get("tmp_cert_path") + + if os.path.exists(cert_path): + os.remove(cert_path) + shutil.move(tmp_cert_path, cert_path) + migration_obj.run_migration_again() + + def cleanup_migrate_tls_x509_verify_on_target(): + """ + Cleanup steps for migrate_tls_x509_verify_on_target + + """ + test.log.info("Cleanup steps migrate_tls_x509_verify_on_target.") + migration_obj.cleanup_connection() + if remote_obj: + for obj in remote_obj: + del obj + + def cleanup_migrate_tls_x509_verify_on_src(): + """ + Cleanup steps for migrate_tls_x509_verify_on_src + + """ + test.log.info("Cleanup steps migrate_tls_x509_verify_on_src.") + migration_obj.cleanup_connection() + if local_obj: + for obj in local_obj: + libvirt.customize_libvirt_config(None, + config_type="qemu", + remote_host=False, + is_recover=True, + extra_params=params, + config_object=obj) + + migrate_again = "yes" == params.get("migrate_again", "no") + vm_name = params.get("migrate_main_vm") + test_case = params.get('test_case', '') + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + setup_test = eval("setup_%s" % test_case) if "setup_%s" % test_case in \ + locals() else migration_obj.setup_connection + run_migration_again_test = eval("run_migration_again_%s" % test_case) if "run_migration_again_%s" % test_case in \ + locals() else migration_obj.run_migration_again + cleanup_test = eval("cleanup_%s" % test_case) if "cleanup_%s" % test_case in \ + locals() else migration_obj.cleanup_connection + + remote_obj = [] + local_obj = [] + + try: + setup_test() + migration_obj.run_migration() + if migrate_again: + run_migration_again_test() + migration_obj.verify_default() + finally: + cleanup_test() From 988771d6005200a43a3be00c43e0338c17b56ce9 Mon Sep 17 00:00:00 2001 From: lcheng Date: Sat, 31 Aug 2024 21:27:46 +0800 Subject: [PATCH 0568/1055] migration: Add case to test host_uuid XXX-298377 - [VM migration] migrate vm between two hosts with same host_uuid Signed-off-by: lcheng --- .../migration_with_host_uuid.cfg | 32 +++++++++++ .../migration_with_host_uuid.py | 54 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 libvirt/tests/cfg/migration/migration_misc/migration_with_host_uuid.cfg create mode 100644 libvirt/tests/src/migration/migration_misc/migration_with_host_uuid.py diff --git a/libvirt/tests/cfg/migration/migration_misc/migration_with_host_uuid.cfg b/libvirt/tests/cfg/migration/migration_misc/migration_with_host_uuid.cfg new file mode 100644 index 00000000000..3425e38c185 --- /dev/null +++ b/libvirt/tests/cfg/migration/migration_misc/migration_with_host_uuid.cfg @@ -0,0 +1,32 @@ +- migration.migration_misc.migration_with_host_uuid: + type = migration_with_host_uuid + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + status_error = "yes" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + err_msg = "Attempt to migrate guest to the same host" + libvirtd_conf = {"host_uuid": '"00000000-0000-0000-0000-000000000001"'} + variants: + - p2p: + virsh_migrate_options = '--live --p2p --verbose' + - non_p2p: + virsh_migrate_options = '--live --verbose' diff --git a/libvirt/tests/src/migration/migration_misc/migration_with_host_uuid.py b/libvirt/tests/src/migration/migration_misc/migration_with_host_uuid.py new file mode 100644 index 00000000000..a71eb146a01 --- /dev/null +++ b/libvirt/tests/src/migration/migration_misc/migration_with_host_uuid.py @@ -0,0 +1,54 @@ +from virttest.utils_test import libvirt + +from provider.migration import base_steps + +local_obj = None + + +def run(test, params, env): + """ + To verify that migration will fail if source host and target host have + same host_uuid. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def setup_test(): + """ + Setup steps for cases + + """ + test.log.info("Setup steps for cases.") + libvirtd_conf = eval(params.get("libvirtd_conf")) + + local_obj = libvirt.customize_libvirt_config(libvirtd_conf, + remote_host=True, + extra_params=params) + migration_obj.setup_connection() + + def cleanup_test(): + """ + Cleanup steps for cases + + """ + migration_obj.cleanup_connection() + global local_obj + if local_obj: + libvirt.customize_libvirt_config(None, + remote_host=True, + is_recover=True, + extra_params=params, + config_object=local_obj) + + vm_name = params.get("migrate_main_vm") + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + setup_test() + migration_obj.run_migration() + migration_obj.verify_default() + finally: + cleanup_test() From cd8036c16924fbd6ee24dbcc7b428b18622bfde6 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 27 Aug 2024 14:58:56 +0800 Subject: [PATCH 0569/1055] viommu: Add a case for file transfers This PR adds: VIRT-301880: Transfer a file between host and vm with iommu device Signed-off-by: Yingshun Cui --- .../cfg/sriov/vIOMMU/viommu_transfer_file.cfg | 27 +++++++++++++ .../src/sriov/vIOMMU/viommu_transfer_file.py | 39 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 libvirt/tests/cfg/sriov/vIOMMU/viommu_transfer_file.cfg create mode 100644 libvirt/tests/src/sriov/vIOMMU/viommu_transfer_file.py diff --git a/libvirt/tests/cfg/sriov/vIOMMU/viommu_transfer_file.cfg b/libvirt/tests/cfg/sriov/vIOMMU/viommu_transfer_file.cfg new file mode 100644 index 00000000000..681ac9aaf5a --- /dev/null +++ b/libvirt/tests/cfg/sriov/vIOMMU/viommu_transfer_file.cfg @@ -0,0 +1,27 @@ +- vIOMMU.transfer_file: + type = viommu_transfer_file + start_vm = "no" + disk_driver = {'name': 'qemu', 'type': 'qcow2', 'iommu': 'on'} + variants: + - virtio: + only q35, aarch64 + func_supported_since_libvirt_ver = (8, 3, 0) + iommu_dict = {'model': 'virtio'} + - intel: + only q35 + start_vm = "yes" + enable_guest_iommu = "yes" + iommu_dict = {'model': 'intel', 'driver': {'intremap': 'on', 'caching_mode': 'on', 'eim': 'on', 'iotlb': 'on', 'aw_bits': '48'}} + - smmuv3: + only aarch64 + func_supported_since_libvirt_ver = (5, 5, 0) + iommu_dict = {'model': 'smmuv3'} + variants: + - e1000e: + only q35 + iface_model = 'e1000e' + iface_dict = {'type_name': 'network', 'model': '${iface_model}', 'source': {'network': 'default'}} + - virtio_interface: + interface_driver_name = "vhost" + interface_driver = {'driver_attr': {'name': '${interface_driver_name}', 'iommu': 'on'}} + iface_dict = {'type_name': 'network', 'model': 'virtio', 'driver': ${interface_driver}, 'source': {'network': 'default'}} diff --git a/libvirt/tests/src/sriov/vIOMMU/viommu_transfer_file.py b/libvirt/tests/src/sriov/vIOMMU/viommu_transfer_file.py new file mode 100644 index 00000000000..956feb8367d --- /dev/null +++ b/libvirt/tests/src/sriov/vIOMMU/viommu_transfer_file.py @@ -0,0 +1,39 @@ +from virttest import utils_test + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml + +from provider.viommu import viommu_base + + +def run(test, params, env): + """ + Transfer a file between host and vm with iommu device + """ + cleanup_ifaces = "yes" == params.get("cleanup_ifaces", "yes") + iommu_dict = eval(params.get('iommu_dict', '{}')) + + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + + test_obj = viommu_base.VIOMMUTest(vm, test, params) + + try: + test.log.info("TEST_SETUP: Update VM XML.") + test_obj.setup_iommu_test(iommu_dict=iommu_dict, + cleanup_ifaces=cleanup_ifaces) + + iface_dict = test_obj.parse_iface_dict() + if cleanup_ifaces: + libvirt_vmxml.modify_vm_device( + vm_xml.VMXML.new_from_dumpxml(vm.name), + "interface", iface_dict) + + test.log.info("TEST_STEP: Start the VM.") + vm.start() + test.log.debug(vm_xml.VMXML.new_from_dumpxml(vm.name)) + + test.log.info("TEST_STEP: Transfer a file between host and vm.") + utils_test.run_file_transfer(test, params, env) + finally: + test_obj.teardown_iommu_test() From 18757f3a23693084393919ce54751bd81246dd99 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Tue, 3 Sep 2024 03:30:56 -0400 Subject: [PATCH 0570/1055] Check qemu-ga in v2v supported windows guests Signed-off-by: Ming Xie --- v2v/tests/cfg/function_test_esx.cfg | 29 +++++++++++++---------------- v2v/tests/src/function_test_esx.py | 4 ++-- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index d9853fa4ee2..3cde48a725c 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -129,25 +129,21 @@ os_version = VM_VERSION_WIN_SCHTASKS_V2V_EXAMPLE main_vm = VM_NAME_WIN_SCHTASKS_V2V_EXAMPLE - OGAC: - only esx_70 + only esx_80 checkpoint = "ogac" virtio_win_path = EXPORT_VIRTIO_WIN_PATH_V2V_EXAMPLE variants: - - win2008r2: - os_version = "win2008r2" - main_vm = VM_NAME_WIN2008R2_V2V_EXAMPLE - - win8: - os_version = "win8" - main_vm = VM_NAME_WIN8_V2V_EXAMPLE - - win8_1: - os_version = "win8.1" - main_vm = VM_NAME_WIN81_V2V_EXAMPLE - - win2012: - os_version = "win2012" - main_vm = VM_NAME_WIN2012_V2V_EXAMPLE - - win2012r2: - os_version = "win2012r2" - main_vm = VM_NAME_WIN2012R2_V2V_EXAMPLE + - win2022: + os_version = "win2022" + main_vm = "VM_NAME_WIN2022_V2V_EXAMPLE" + - win2025: + os_version = "win2025" + main_vm = "VM_NAME_WIN2025_V2V_EXAMPLE" + boottype = 3 + - win11: + os_version = "win11" + main_vm = "VM_NAME_WIN11_V2V_EXAMPLE" + boottype = 3 - win10: os_version = "win10" main_vm = VM_NAME_WIN10_V2V_EXAMPLE @@ -157,6 +153,7 @@ - win2019: main_vm = VM_NAME_WIN2019_V2V_EXAMPLE os_version = "win2019" + boottype = 3 - virtio_win: only esx_70 main_vm = 'ESX_VM_NAME_VIRTIO_WIN_V2V_EXAMPLE' diff --git a/v2v/tests/src/function_test_esx.py b/v2v/tests/src/function_test_esx.py index 766e8ee7518..1777aa739ff 100644 --- a/v2v/tests/src/function_test_esx.py +++ b/v2v/tests/src/function_test_esx.py @@ -258,7 +258,7 @@ def check_windows_service(vmcheck, service_name): 'running', vmcheck.get_service_info(service_name), re.I), - 600, + 900, step=30) except (ShellProcessTerminatedError, ShellStatusError): # Windows guest may reboot after installing qemu-ga service @@ -274,7 +274,7 @@ def check_windows_service(vmcheck, service_name): 'running', vmcheck.get_service_info(service_name), re.I), - 600, + 900, step=30) if not res: From 36d4cdf4472f5967bc26e1a738b6a8b39cbdf6dc Mon Sep 17 00:00:00 2001 From: Yanqiu Zhang Date: Mon, 2 Sep 2024 04:54:44 -0400 Subject: [PATCH 0571/1055] libvirt_rng: update rng to use external snapshot Only external snapshot is officially supported, and it supports revert now. Update rng cases to use this. Since every step is external snapshot now, no need to do the 3rd snapshot test which was called snapshot_with_rng. Signed-off-by: Yanqiu Zhang --- .../tests/cfg/security/rng/libvirt_rng.cfg | 6 +- libvirt/tests/src/security/rng/libvirt_rng.py | 71 ++++++++----------- 2 files changed, 31 insertions(+), 46 deletions(-) diff --git a/libvirt/tests/cfg/security/rng/libvirt_rng.cfg b/libvirt/tests/cfg/security/rng/libvirt_rng.cfg index 98907f2f49c..aaaf450a036 100644 --- a/libvirt/tests/cfg/security/rng/libvirt_rng.cfg +++ b/libvirt/tests/cfg/security/rng/libvirt_rng.cfg @@ -110,16 +110,16 @@ snapshot_name = "rng.s" variants: - snapshot_running: + snap_options = "%s --memspec " + mem_files = ["/var/lib/libvirt/images/avocado-memory.s1", "/var/lib/libvirt/images/avocado-memory.s2"] snapshot_vm_running = "yes" test_snapshot = "yes" - snapshot_with_rng = "yes" - snapshot_shutoff: + snap_options = "%s --disk-only" test_snapshot = "yes" - snapshot_with_rng = "no" variants: - back_rdm: backend_dev = "/dev/random" - snap_options = "%s --disk-only" - back_tcp_connect: backend_model = "egd" backend_type = "tcp" diff --git a/libvirt/tests/src/security/rng/libvirt_rng.py b/libvirt/tests/src/security/rng/libvirt_rng.py index 0c0a0ab340f..87781e65af8 100644 --- a/libvirt/tests/src/security/rng/libvirt_rng.py +++ b/libvirt/tests/src/security/rng/libvirt_rng.py @@ -39,6 +39,7 @@ def run(test, params, env): vm_name = params.get("main_vm") vm = env.get_vm(vm_name) snap_options = params.get("snap_options") + mem_files = eval(params.get("mem_files", '[]')) def check_rng_xml(xml_set, exists=True): """ @@ -270,21 +271,22 @@ def check_snapshot(bgjob=None): Do snapshot operation and check the results """ snapshot_name1 = "snap.s1" - snapshot_name2 = "snap.s2" if not snapshot_vm_running: vm.destroy(gracefully=False) + snap_options = params.get("snap_options") + if "--memspec" in snap_options: + snap_options += mem_files[1] ret = virsh.snapshot_create_as( vm_name, options=snap_options % snapshot_name1, debug=True) libvirt.check_exit_status(ret) + snap_info = virsh.snapshot_info(vm_name, snapshot_name1, debug=True) + check_snap_info(snap_info) snap_lists = virsh.snapshot_list(vm_name, debug=True) if snapshot_name not in snap_lists: test.fail("Snapshot %s doesn't exist" % snapshot_name) - if snapshot_vm_running: - options = "--force" - else: - options = "" + options = "" ret = virsh.snapshot_revert( vm_name, ("%s %s" % (snapshot_name, options)), debug=True) libvirt.check_exit_status(ret) @@ -292,39 +294,6 @@ def check_snapshot(bgjob=None): if ret.stdout.strip().count(" 0: libvirt.clean_up_snapshots(vm_name, snapshot_lists) - for snapshot in snapshot_lists: - virsh.snapshot_delete(vm_name, snapshot, "--metadata", debug=True) - + for snapshot in reversed(snapshot_lists): + virsh.snapshot_delete(vm_name, snapshot, "", debug=True) + if mem_files: + for memspec in mem_files: + if os.path.exists(memspec): + os.remove(memspec) # Recover VM. if vm.is_alive(): vm.destroy(gracefully=False) From 304b4a6b17905bc601abcf90a3fa18c453b68ec6 Mon Sep 17 00:00:00 2001 From: Slancaster1 Date: Tue, 3 Sep 2024 12:53:27 -0400 Subject: [PATCH 0572/1055] virsh_detach_device_alias: Skip test when no input - The Problem Tests rhel.virsh.detach_device_alias.live.input.passthrough and rhel.virsh.detach_device_alias.config.input.passthrough do not pass if there is not input device, as they require a device to passthrough to the vm - The Solution Skip the test if no input device can be found Signed-off-by: Slancaster1 --- libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py b/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py index b48bc7d38f8..1ac27c41088 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py @@ -270,7 +270,7 @@ def start_usbredirserver(): if input_type == "passthrough": event = process.run("ls /dev/input/event*", shell=True, ignore_status=True).stdout if len(event) == 0: - test.error("Not found any input devices") + test.skip("Not found any input devices") input_dict.update({"source_evdev": event.decode('utf-8').split()[0]}) input_obj = Input(type_name=input_type) From 39ca1280b88d20d204d8c13e8f6bf04f12562f5d Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 19 Aug 2024 13:16:19 -0400 Subject: [PATCH 0573/1055] passthrough: add robustness test suite Add test suite that will execute configured actions on passthrough devices and VMs. | Scenarios (edge coverage) | | | |------------------------------------------------------------------------------ |------------ |------------------------- | | VM | | | | all should end with "check_present" if applicable | | | | edge coverage: 1 | | | | RUNNING -> attach -> pause resume | 1 dev | all dev | | RUNNING -> attach -> reboot | 1 dev | all dev | | RUNNING -> attach -> detach attach | 1 dev | all dev | | RUNNING -> attach -> detach attach -> reboot | 1 dev | all dev | | RUNNING -> attach -> shutdown start -> attach | 1 dev | all dev | | STOPPED -> attach -> start -> RUNNING -> detach attach | 1 dev | all dev | | STOPPED -> attach -> start -> RUNNING -> reboot | 1 dev | all dev | | STOPPED -> attach -> start -> RUNNING -> shutdown start | 1 dev | all dev | | STOPPED -> attach -> start -> RUNNING -> destroy start | 1 dev | all dev | | STOPPED -> attach -> start -> RUNNING -> pause resume | 1 dev | all dev | | RUNNING -> attach -> 10x detach attach | 1 dev | all dev | | STOPPED -> attach -> start -> 10x detach attach reboot | 1 dev | all dev | | RUNNING -> attach -> attach | 1 dev type | all supported dev types | | RUNNING -> attach -> attach -> reboot | 1 dev type | all supported dev types | | RUNNING -> attach -> attach -> pause resume | 1 dev type | all supported dev types | | RUNNING -> attach -> attach -> detach attach -> detach attach | 1 dev type | all supported dev types | | RUNNING -> attach -> attach -> reboot -> detach attach -> detach attach | 1 dev type | all supported dev types | | Device | | | | Mediated devices need to be restarted, only possible when not used in VM | | | | RUNNING -> attach -> detach -> restart dev -> attach | 1 dev | all dev | | Migrate device between VMs | | | | (RUNNING0 -> attach detach) -> (RUNNING1 attach) | 1 dev | all dev | | (RUNNING0 -> attach detach) -> (RUNNING1 attach detach) -> (RUNNING0 attach) | 1 dev | all dev | The MdevHandler classes had to be updated to retain state, so that reusing them would create the same conditions as using the first time both for device creation (ids and driver overrides) and checks. Apply black, inspekt and isort tools for code quality. Signed-off-by: Sebastian Mitterle --- .../robustness/passthrough_robustness.cfg | 1427 +++++++++++++++++ .../ccw/libvirt_ccw_passthrough.py | 1 + .../robustness/passthrough_robustness.py | 311 ++++ provider/vfio/__init__.py | 88 +- provider/vfio/ccw.py | 23 +- provider/vfio/mdev_handlers.py | 149 +- 6 files changed, 1936 insertions(+), 63 deletions(-) create mode 100644 libvirt/tests/cfg/passthrough/robustness/passthrough_robustness.cfg create mode 100644 libvirt/tests/src/passthrough/robustness/passthrough_robustness.py diff --git a/libvirt/tests/cfg/passthrough/robustness/passthrough_robustness.cfg b/libvirt/tests/cfg/passthrough/robustness/passthrough_robustness.cfg new file mode 100644 index 00000000000..033f8884a8f --- /dev/null +++ b/libvirt/tests/cfg/passthrough/robustness/passthrough_robustness.cfg @@ -0,0 +1,1427 @@ +- passthrough.robustness: + type = passthrough_robustness + only s390-virtio + start_vm = no + vms = avocado-vt-vm1 vm2 + variants: + - start_stop_ap: + cmds = start;ap-00.000e, + cmds += stop;ap-00.000e, + - start_stop_ism: + cmds = start;ism-0000:00:00.0, + cmds += stop;ism-0000:00:00.0, + - start_stop_roce: + cmds = start;roce-0002:00:00.0, + cmds += stop;roce-0002:00:00.0, + - start_stop_ccw: + cmds = start;ccw-0.0.401c, + cmds += stop;ccw-0.0.401c, + - start_destroy_vm: + cmds = vm_start;0, + cmds += vm_destroy;0, + - start_stop_all: + cmds = start;ap-00.000e, + cmds += start;ism-0000:00:00.0, + cmds += start;roce-0002:00:00.0, + cmds += start;ccw-0.0.401c, + cmds += stop;ap-00.000e, + cmds += stop;ism-0000:00:00.0, + cmds += stop;roce-0002:00:00.0, + cmds += stop;ccw-0.0.401c, + - hotplug_hotunplug_all: + cmds = start;ap-00.000e, + cmds += start;ism-0000:00:00.0, + cmds += start;roce-0002:00:00.0, + cmds += start;ccw-0.0.401c, + cmds += vm_start;0, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_detach;0;ccw-0.0.401c, + - hotplug_check_all: + cmds = start;ap-00.000e, + cmds += start;ism-0000:00:00.0, + cmds += start;roce-0002:00:00.0, + cmds += start;ccw-0.0.401c, + cmds += vm_start;0, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_check_present;0;ap-00.000e, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + cmds += vm_check_present;0;ccw-0.0.401c, + - hotplug_all_distribute_over_two: + cmds = start;ap-00.000e, + cmds += start;ism-0000:00:00.0, + cmds += start;roce-0002:00:00.0, + cmds += start;ccw-0.0.401c, + cmds += vm_start;0, + cmds += vm_start;1, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;1;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_attach;1;ccw-0.0.401c, + cmds += vm_check_present;0;ap-00.000e, + cmds += vm_check_present;1;ism-0000:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + cmds += vm_check_present;1;ccw-0.0.401c, + - vm_running_attach_pause_resume.ap: + cmds = vm_start;0, + cmds += start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_pause;0, + cmds += vm_resume;0, + cmds += vm_check_present;0;ap-00.000e, + - vm_running_attach_pause_resume.ccw: + cmds = vm_start;0, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_pause;0, + cmds += vm_resume;0, + cmds += vm_check_present;0;ccw-0.0.401c, + - vm_running_attach_pause_resume.ism: + cmds = vm_start;0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_pause;0, + cmds += vm_resume;0, + cmds += vm_check_present;0;ism-0000:00:00.0, + - vm_running_attach_pause_resume.roce: + cmds = vm_start;0, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_pause;0, + cmds += vm_resume;0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_running_attach_pause_resume.all: + cmds = vm_start;0, + cmds += start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_pause;0, + cmds += vm_resume;0, + cmds += vm_check_present;0;ap-00.000e, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_running_attach_reboot.ap: + cmds = vm_start;0, + cmds += start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_reboot;0, + cmds += vm_check_present;0;ap-00.000e, + - vm_running_attach_reboot.ccw: + cmds = vm_start;0, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_reboot;0, + cmds += vm_check_present;0;ccw-0.0.401c, + - vm_running_attach_reboot.ism: + cmds = vm_start;0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_reboot;0, + cmds += vm_check_present;0;ism-0000:00:00.0, + - vm_running_attach_reboot.roce: + cmds = vm_start;0, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_running_attach_reboot.all: + cmds = vm_start;0, + cmds += start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_check_present;0;ap-00.000e, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_running_attach_detach_attach.ap: + cmds = vm_start;0, + cmds += start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_check_present;0;ap-00.000e, + - vm_running_attach_detach_attach.ccw: + cmds = vm_start;0, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_check_present;0;ccw-0.0.401c, + - vm_running_attach_detach_attach.ism: + cmds = vm_start;0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_check_present;0;ism-0000:00:00.0, + - vm_running_attach_detach_attach.roce: + cmds = vm_start;0, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_running_attach_detach_attach.all: + cmds = vm_start;0, + cmds += start;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += start;roce-0002:00:00.0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_check_present;0;ap-00.000e, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_running_attach_detach_attach_reboot.ap: + cmds = vm_start;0, + cmds += start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_reboot;0, + cmds += vm_check_present;0;ap-00.000e, + - vm_running_attach_detach_attach_reboot.ccw: + cmds = vm_start;0, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_reboot;0, + cmds += vm_check_present;0;ccw-0.0.401c, + - vm_running_attach_detach_attach_reboot.ism: + cmds = vm_start;0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_reboot;0, + cmds += vm_check_present;0;ism-0000:00:00.0, + - vm_running_attach_detach_attach_reboot.roce: + cmds = vm_start;0, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_running_attach_detach_attach_reboot.all: + cmds = vm_start;0, + cmds += start;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += start;roce-0002:00:00.0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_check_present;0;ap-00.000e, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_running_attach_shutdown_start_attach.ap: + cmds = vm_start;0, + cmds += start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_shutdown;0, + cmds += vm_start;0, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_check_present;0;ap-00.000e, + - vm_running_attach_shutdown_start_attach.ccw: + cmds = vm_start;0, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_shutdown;0, + cmds += vm_start;0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_check_present;0;ccw-0.0.401c, + - vm_running_attach_shutdown_start_attach.ism: + cmds = vm_start;0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_shutdown;0, + cmds += vm_start;0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_check_present;0;ism-0000:00:00.0, + - vm_running_attach_shutdown_start_attach.roce: + cmds = vm_start;0, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_shutdown;0, + cmds += vm_start;0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_running_attach_shutdown_start_attach.all: + cmds = vm_start;0, + cmds += start;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += start;roce-0002:00:00.0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_shutdown;0, + cmds += vm_start;0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_check_present;0;ap-00.000e, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_stopped_attach_start_detach_attach.ap: + cmds = start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_start;0, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_check_present;0;ap-00.000e, + - vm_stopped_attach_start_detach_attach.ccw: + cmds = start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_start;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_check_present;0;ccw-0.0.401c, + - vm_stopped_attach_start_detach_attach.ism: + cmds = start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_start;0, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_check_present;0;ism-0000:00:00.0, + - vm_stopped_attach_start_detach_attach.roce: + cmds = start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_start;0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_stopped_attach_start_detach_attach.all: + cmds = start;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += start;roce-0002:00:00.0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_start;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_check_present;0;ap-00.000e, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_stopped_attach_start_reboot.ap: + cmds = start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_start;0, + cmds += vm_reboot;0, + cmds += vm_check_present;0;ap-00.000e, + - vm_stopped_attach_start_reboot.ccw: + cmds = start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_start;0, + cmds += vm_reboot;0, + cmds += vm_check_present;0;ccw-0.0.401c, + - vm_stopped_attach_start_reboot.ism: + cmds = start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_start;0, + cmds += vm_reboot;0, + cmds += vm_check_present;0;ism-0000:00:00.0, + - vm_stopped_attach_start_reboot.roce: + cmds = start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_start;0, + cmds += vm_reboot;0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_stopped_attach_start_reboot.all: + cmds = start;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += start;roce-0002:00:00.0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_start;0, + cmds += vm_reboot;0, + cmds += vm_check_present;0;ap-00.000e, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_stopped_attach_start_shutdown_start.ap: + cmds = start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_start;0, + cmds += vm_shutdown;0, + cmds += vm_start;0, + cmds += vm_check_present;0;ap-00.000e, + - vm_stopped_attach_start_shutdown_start.ccw: + cmds = start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_start;0, + cmds += vm_shutdown;0, + cmds += vm_start;0, + cmds += vm_check_present;0;ccw-0.0.401c, + - vm_stopped_attach_start_shutdown_start.ism: + cmds = start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_start;0, + cmds += vm_shutdown;0, + cmds += vm_start;0, + cmds += vm_check_present;0;ism-0000:00:00.0, + - vm_stopped_attach_start_shutdown_start.roce: + cmds = start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_start;0, + cmds += vm_shutdown;0, + cmds += vm_start;0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_stopped_attach_start_shutdown_start.all: + cmds = start;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += start;roce-0002:00:00.0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_start;0, + cmds += vm_shutdown;0, + cmds += vm_start;0, + cmds += vm_check_present;0;ap-00.000e, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_stopped_attach_start_destroy_start.ap: + cmds = start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_start;0, + cmds += vm_destroy;0, + cmds += vm_start;0, + cmds += vm_check_present;0;ap-00.000e, + - vm_stopped_attach_start_destroy_start.ccw: + cmds = start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_start;0, + cmds += vm_destroy;0, + cmds += vm_start;0, + cmds += vm_check_present;0;ccw-0.0.401c, + - vm_stopped_attach_start_destroy_start.ism: + cmds = start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_start;0, + cmds += vm_destroy;0, + cmds += vm_start;0, + cmds += vm_check_present;0;ism-0000:00:00.0, + - vm_stopped_attach_start_destroy_start.roce: + cmds = start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_start;0, + cmds += vm_destroy;0, + cmds += vm_start;0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_stopped_attach_start_destroy_start.all: + cmds = start;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += start;roce-0002:00:00.0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_start;0, + cmds += vm_destroy;0, + cmds += vm_start;0, + cmds += vm_check_present;0;ap-00.000e, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_stopped_attach_start_pause_resume.ap: + cmds = start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_start;0, + cmds += vm_pause;0, + cmds += vm_resume;0, + cmds += vm_check_present;0;ap-00.000e, + - vm_stopped_attach_start_pause_resume.ccw: + cmds = start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_start;0, + cmds += vm_pause;0, + cmds += vm_resume;0, + cmds += vm_check_present;0;ccw-0.0.401c, + - vm_stopped_attach_start_pause_resume.ism: + cmds = start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_start;0, + cmds += vm_pause;0, + cmds += vm_resume;0, + cmds += vm_check_present;0;ism-0000:00:00.0, + - vm_stopped_attach_start_pause_resume.roce: + cmds = start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_start;0, + cmds += vm_pause;0, + cmds += vm_resume;0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_stopped_attach_start_pause_resume.all: + cmds = start;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += start;roce-0002:00:00.0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_start;0, + cmds += vm_pause;0, + cmds += vm_resume;0, + cmds += vm_check_present;0;ap-00.000e, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_running_attach_10_times_detach_attach.ap: + cmds = vm_start;0, + cmds += start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_check_present;0;ap-00.000e, + - vm_running_attach_10_times_detach_attach.ccw: + cmds = vm_start;0, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_check_present;0;ccw-0.0.401c, + - vm_running_attach_10_times_detach_attach.ism: + cmds = vm_start;0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_check_present;0;ism-0000:00:00.0, + - vm_running_attach_10_times_detach_attach.roce: + cmds = vm_start;0, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_running_attach_10_times_detach_attach.all: + cmds = vm_start;0, + cmds += start;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += start;roce-0002:00:00.0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_check_present;0;ap-00.000e, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_stopped_attach_start_10_times_detach_attach_reboot.ap: + cmds = start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_start;0, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_reboot;0, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_reboot;0, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_reboot;0, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_reboot;0, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_reboot;0, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_reboot;0, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_reboot;0, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_reboot;0, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_reboot;0, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_reboot;0, + cmds += vm_check_present;0;ap-00.000e, + - vm_stopped_attach_start_10_times_detach_attach_reboot.ccw: + cmds = start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_start;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_reboot;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_reboot;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_reboot;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_reboot;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_reboot;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_reboot;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_reboot;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_reboot;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_reboot;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_reboot;0, + cmds += vm_check_present;0;ccw-0.0.401c, + - vm_stopped_attach_start_10_times_detach_attach_reboot.ism: + cmds = start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_start;0, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_reboot;0, + cmds += vm_reboot;0, + cmds += vm_reboot;0, + cmds += vm_reboot;0, + cmds += vm_reboot;0, + cmds += vm_reboot;0, + cmds += vm_reboot;0, + cmds += vm_reboot;0, + cmds += vm_reboot;0, + cmds += vm_reboot;0, + cmds += vm_check_present;0;ism-0000:00:00.0, + - vm_stopped_attach_start_10_times_detach_attach_reboot.roce: + cmds = start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_start;0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_stopped_attach_start_10_times_detach_attach_reboot.all: + cmds = start;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += start;roce-0002:00:00.0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_start;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_reboot;0, + cmds += vm_check_present;0;ap-00.000e, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_running_attach_attach.ccw: + cmds = vm_start;0, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += start;ccw-0.0.401d, + cmds += vm_attach;0;ccw-0.0.401d, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ccw-0.0.401d, + - vm_running_attach_attach.ism: + cmds = vm_start;0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += start;ism-0001:00:00.0, + cmds += vm_attach;0;ism-0001:00:00.0, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;ism-0001:00:00.0, + - vm_running_attach_attach.roce: + cmds = vm_start;0, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += start;roce-0003:00:00.0, + cmds += vm_attach;0;roce-0003:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + cmds += vm_check_present;0;roce-0003:00:00.0, + - vm_running_attach_attach.all: + cmds = vm_start;0, + cmds += start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += start;ccw-0.0.401d, + cmds += vm_attach;0;ccw-0.0.401d, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += start;ism-0001:00:00.0, + cmds += vm_attach;0;ism-0001:00:00.0, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += start;roce-0003:00:00.0, + cmds += vm_attach;0;roce-0003:00:00.0, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ccw-0.0.401d, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;ism-0001:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + cmds += vm_check_present;0;roce-0003:00:00.0, + cmds += vm_check_present;0;ap-00.000e, + - vm_running_attach_attach_reboot.ccw: + cmds = vm_start;0, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += start;ccw-0.0.401d, + cmds += vm_attach;0;ccw-0.0.401d, + cmds += vm_reboot;0, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ccw-0.0.401d, + - vm_running_attach_attach_reboot.ism: + cmds = vm_start;0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += start;ism-0001:00:00.0, + cmds += vm_attach;0;ism-0001:00:00.0, + cmds += vm_reboot;0, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;ism-0001:00:00.0, + - vm_running_attach_attach_reboot.roce: + cmds = vm_start;0, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += start;roce-0003:00:00.0, + cmds += vm_attach;0;roce-0003:00:00.0, + cmds += vm_reboot;0, + cmds += vm_check_present;0;roce-0002:00:00.0, + cmds += vm_check_present;0;roce-0003:00:00.0, + - vm_running_attach_attach_reboot.all: + cmds = vm_start;0, + cmds += start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += start;ccw-0.0.401d, + cmds += vm_attach;0;ccw-0.0.401d, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += start;ism-0001:00:00.0, + cmds += vm_attach;0;ism-0001:00:00.0, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += start;roce-0003:00:00.0, + cmds += vm_attach;0;roce-0003:00:00.0, + cmds += vm_reboot;0, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ccw-0.0.401d, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;ism-0001:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + cmds += vm_check_present;0;roce-0003:00:00.0, + cmds += vm_check_present;0;ap-00.000e, + - vm_running_attach_attach_pause_resume.ccw: + cmds = vm_start;0, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += start;ccw-0.0.401d, + cmds += vm_attach;0;ccw-0.0.401d, + cmds += vm_pause;0, + cmds += vm_resume;0, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ccw-0.0.401d, + - vm_running_attach_attach_pause_resume.ism: + cmds = vm_start;0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += start;ism-0001:00:00.0, + cmds += vm_attach;0;ism-0001:00:00.0, + cmds += vm_pause;0, + cmds += vm_resume;0, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;ism-0001:00:00.0, + - vm_running_attach_attach_pause_resume.roce: + cmds = vm_start;0, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += start;roce-0003:00:00.0, + cmds += vm_attach;0;roce-0003:00:00.0, + cmds += vm_pause;0, + cmds += vm_resume;0, + cmds += vm_check_present;0;roce-0002:00:00.0, + cmds += vm_check_present;0;roce-0003:00:00.0, + - vm_running_attach_attach_pause_resume.all: + cmds = vm_start;0, + cmds += start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += start;ccw-0.0.401d, + cmds += vm_attach;0;ccw-0.0.401d, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += start;ism-0001:00:00.0, + cmds += vm_attach;0;ism-0001:00:00.0, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += start;roce-0003:00:00.0, + cmds += vm_attach;0;roce-0003:00:00.0, + cmds += vm_pause;0, + cmds += vm_resume;0, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ccw-0.0.401d, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;ism-0001:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + cmds += vm_check_present;0;roce-0003:00:00.0, + cmds += vm_check_present;0;ap-00.000e, + - vm_running_attach_attach_detach_attach_detach_attach.ccw: + cmds = vm_start;0, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += start;ccw-0.0.401d, + cmds += vm_attach;0;ccw-0.0.401d, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ccw-0.0.401d, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401d, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ccw-0.0.401d, + - vm_running_attach_attach_detach_attach_detach_attach.ism: + cmds = vm_start;0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += start;ism-0001:00:00.0, + cmds += vm_attach;0;ism-0001:00:00.0, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;ism-0001:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0001:00:00.0, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;ism-0001:00:00.0, + - vm_running_attach_attach_detach_attach_detach_attach.roce: + cmds = vm_start;0, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += start;roce-0003:00:00.0, + cmds += vm_attach;0;roce-0003:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_detach;0;roce-0003:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0003:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + cmds += vm_check_present;0;roce-0003:00:00.0, + - vm_running_attach_attach_detach_attach_detach_attach.all: + cmds = vm_start;0, + cmds += start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += start;ccw-0.0.401d, + cmds += vm_attach;0;ccw-0.0.401d, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += start;ism-0001:00:00.0, + cmds += vm_attach;0;ism-0001:00:00.0, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += start;roce-0003:00:00.0, + cmds += vm_attach;0;roce-0003:00:00.0, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ccw-0.0.401d, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;ism-0001:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_detach;0;roce-0003:00:00.0, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401d, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0001:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0003:00:00.0, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ccw-0.0.401d, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;ism-0001:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + cmds += vm_check_present;0;roce-0003:00:00.0, + cmds += vm_check_present;0;ap-00.000e, + - vm_running_attach_attach_reboot_detach_attach_detach_attach.ccw: + cmds = vm_start;0, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += start;ccw-0.0.401d, + cmds += vm_attach;0;ccw-0.0.401d, + cmds += vm_reboot;0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ccw-0.0.401d, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401d, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ccw-0.0.401d, + - vm_running_attach_attach_reboot_detach_attach_detach_attach.ism: + cmds = vm_start;0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += start;ism-0001:00:00.0, + cmds += vm_attach;0;ism-0001:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;ism-0001:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0001:00:00.0, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;ism-0001:00:00.0, + - vm_running_attach_attach_reboot_detach_attach_detach_attach.roce: + cmds = vm_start;0, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += start;roce-0003:00:00.0, + cmds += vm_attach;0;roce-0003:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_detach;0;roce-0003:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0003:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + cmds += vm_check_present;0;roce-0003:00:00.0, + - vm_running_attach_attach_reboot_detach_attach_detach_attach.all: + cmds = vm_start;0, + cmds += start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += start;ccw-0.0.401d, + cmds += vm_attach;0;ccw-0.0.401d, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += start;ism-0001:00:00.0, + cmds += vm_attach;0;ism-0001:00:00.0, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += start;roce-0003:00:00.0, + cmds += vm_attach;0;roce-0003:00:00.0, + cmds += vm_reboot;0, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ccw-0.0.401d, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;ism-0001:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_detach;0;roce-0003:00:00.0, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401d, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0001:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0003:00:00.0, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ccw-0.0.401d, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;ism-0001:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + cmds += vm_check_present;0;roce-0003:00:00.0, + cmds += vm_check_present;0;ap-00.000e, + - vm_running_attach_detach_mdevrestart_attach.ap: + cmds = vm_start;0, + cmds += start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_detach;0;ap-00.000e, + cmds += stop;ap-00.000e, + cmds += start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_check_present;0;ap-00.000e, + - vm_running_attach_detach_mdevrestart_attach.ccw: + cmds = vm_start;0, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += stop;ccw-0.0.401c, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_check_present;0;ccw-0.0.401c, + - vm_running_attach_detach_mdevrestart_attach.all: + cmds = vm_start;0, + cmds += start;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += start;roce-0002:00:00.0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += stop;ap-00.000e, + cmds += start;ap-00.000e, + cmds += stop;ccw-0.0.401c, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_check_present;0;ap-00.000e, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_running_attach_detach_vm2_attach.ap: + cmds = vm_start;0, + cmds += vm_start;1, + cmds += start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;1;ap-00.000e, + cmds += vm_check_present;1;ap-00.000e, + - vm_running_attach_detach_vm2_attach.ccw: + cmds = vm_start;0, + cmds += vm_start;1, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;1;ccw-0.0.401c, + cmds += vm_check_present;1;ccw-0.0.401c, + - vm_running_attach_detach_vm2_attach.ism: + cmds = vm_start;0, + cmds += vm_start;1, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_attach;1;ism-0000:00:00.0, + cmds += vm_check_present;1;ism-0000:00:00.0, + - vm_running_attach_detach_vm2_attach.roce: + cmds = vm_start;0, + cmds += vm_start;1, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;1;roce-0002:00:00.0, + cmds += vm_check_present;1;roce-0002:00:00.0, + - vm_running_attach_detach_vm2_attach.all: + cmds = vm_start;0, + cmds += vm_start;1, + cmds += start;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += start;roce-0002:00:00.0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;1;ccw-0.0.401c, + cmds += vm_attach;1;ap-00.000e, + cmds += vm_attach;1;ism-0000:00:00.0, + cmds += vm_attach;1;roce-0002:00:00.0, + cmds += vm_check_present;1;ap-00.000e, + cmds += vm_check_present;1;ccw-0.0.401c, + cmds += vm_check_present;1;ism-0000:00:00.0, + cmds += vm_check_present;1;roce-0002:00:00.0, + - vm_running_attach_detach_vm2_attach_detach_vm_attach.ap: + cmds = vm_start;0, + cmds += vm_start;1, + cmds += start;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_attach;1;ap-00.000e, + cmds += vm_detach;1;ap-00.000e, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_check_present;0;ap-00.000e, + - vm_running_attach_detach_vm2_attach_detach_vm_attach.ccw: + cmds = vm_start;0, + cmds += vm_start;1, + cmds += start;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_attach;1;ccw-0.0.401c, + cmds += vm_detach;1;ccw-0.0.401c, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_check_present;0;ccw-0.0.401c, + - vm_running_attach_detach_vm2_attach_detach_vm_attach.ism: + cmds = vm_start;0, + cmds += vm_start;1, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_attach;1;ism-0000:00:00.0, + cmds += vm_detach;1;ism-0000:00:00.0, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_check_present;0;ism-0000:00:00.0, + - vm_running_attach_detach_vm2_attach_detach_vm_attach.roce: + cmds = vm_start;0, + cmds += vm_start;1, + cmds += start;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;1;roce-0002:00:00.0, + cmds += vm_detach;1;roce-0002:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, + - vm_running_attach_detach_vm2_attach_detach_vm_attach.all: + cmds = vm_start;0, + cmds += vm_start;1, + cmds += start;ap-00.000e, + cmds += start;ccw-0.0.401c, + cmds += start;roce-0002:00:00.0, + cmds += start;ism-0000:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_detach;0;ccw-0.0.401c, + cmds += vm_detach;0;ap-00.000e, + cmds += vm_detach;0;ism-0000:00:00.0, + cmds += vm_detach;0;roce-0002:00:00.0, + cmds += vm_attach;1;ccw-0.0.401c, + cmds += vm_attach;1;ap-00.000e, + cmds += vm_attach;1;ism-0000:00:00.0, + cmds += vm_attach;1;roce-0002:00:00.0, + cmds += vm_detach;1;ccw-0.0.401c, + cmds += vm_detach;1;ap-00.000e, + cmds += vm_detach;1;ism-0000:00:00.0, + cmds += vm_detach;1;roce-0002:00:00.0, + cmds += vm_attach;0;ccw-0.0.401c, + cmds += vm_attach;0;ap-00.000e, + cmds += vm_attach;0;ism-0000:00:00.0, + cmds += vm_attach;0;roce-0002:00:00.0, + cmds += vm_check_present;0;ap-00.000e, + cmds += vm_check_present;0;ccw-0.0.401c, + cmds += vm_check_present;0;ism-0000:00:00.0, + cmds += vm_check_present;0;roce-0002:00:00.0, diff --git a/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py b/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py index a68a2f5d52b..581401da42b 100644 --- a/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py +++ b/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py @@ -21,6 +21,7 @@ def _mdev_listed(): """ cmd = "lsmdev" _, o = cmd_status_output(cmd) + LOG.debug(o) return uuid in o return _mdev_listed diff --git a/libvirt/tests/src/passthrough/robustness/passthrough_robustness.py b/libvirt/tests/src/passthrough/robustness/passthrough_robustness.py new file mode 100644 index 00000000000..0b12ed36a6e --- /dev/null +++ b/libvirt/tests/src/passthrough/robustness/passthrough_robustness.py @@ -0,0 +1,311 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# See LICENSE for more details. +# +# Copyright: Red Hat Inc. 2024 +# Author: Sebastian Mitterle +import logging + +from avocado.core.exceptions import TestError, TestFail +from virttest import virsh +from virttest.libvirt_xml.nodedev_xml import NodedevXML +from virttest.libvirt_xml.vm_xml import VMXML + +from provider import vfio +from provider.vfio.mdev_handlers import MdevHandler + +LOG = logging.getLogger("avocado." + __name__) + + +class VMHandler(object): + """Handles usage of VMs in this test""" + + def __init__(self, vms): + """ + Initializes the instance fields and stores VMXML + for later backup. + + :param vms: list of VM instances as obtained from env + """ + self.vms = vms + self.vmxml_backups = [] + for vm in self.vms: + self.vmxml_backups.append(VMXML.new_from_inactive_dumpxml(vm.name)) + + def run(self, action, vm_idx, device, handlers): + """ + Delegates actions to VMs. + + :param action: the name of the method to call on the VM instance + :param vm_idx: the index of the VM to call the method on + :param device: the device identifier if action involves a device + :param handlers: a reference to the NodeDevHandlerAggregator instance that + holds all device handlers + """ + if action in ["reboot", "start", "destroy", "shutdown", "pause", "resume"]: + getattr(self.vms[vm_idx], action)() + elif action in ["attach", "detach"]: + hostdev_xml = handlers.get_hostdev_xml(device) + getattr(virsh, action + "_device")( + self.vms[vm_idx].name, + hostdev_xml, + flagstr="--current", + ignore_status=False, + debug=True, + ) + + elif action == "check_present": + session = self.vms[vm_idx].wait_for_login() + try: + handlers.run("check_present", device, session) + except TestFail as e: + raise e + finally: + session.close() + else: + raise TestError(f"Unknown action: {action}") + + def clean_up(self): + """Restores the VMXML""" + for xml in self.vmxml_backups: + xml.sync() + + +class NodeDevHandlerAggregator(object): + """ + Holds NodeDevHandler singletons per device identifier + and delegates actions + """ + + def __init__(self): + """Initializes the instance""" + self.handlers = [] + + def add_once(self, device): + """ + Creates and stores a single NodeDevHandler instance per device identifier. + + :param device: the device identifier as used in the commands, e.g. "ap-0.0.000e" + more info in NodeDevHandler.__init__ + """ + device_type, device_id = device.split("-") + if [h for h in self.handlers if h.type == device_type and h.id == device_id]: + pass + else: + self.handlers.append(NodeDevHandler(device_type, device_id)) + + def run(self, action, device, session=None): + """ + Delegates the action to the given device handler + + :param action: method implemented by the device handler, e.g. 'start' + :param device: the device identifier as used in the commands, e.g. "ap-0.0.000e" + more info in NodeDevHandler.__init__ + :param session: logged-in guest session, e.g. for checking if device is present inside + """ + device_type, device_id = device.split("-") + handler = [ + h for h in self.handlers if h.type == device_type and h.id == device_id + ][0] + if session: + getattr(handler, action)(session=session) + else: + getattr(handler, action)() + + def get_hostdev_xml(self, device): + """ + Retrieves the existing host device XML file reference for a given device + + :param device: the device identifier as used in the commands, e.g. "ap-0.0.000e" + more info in NodeDevHandler.__init__ + """ + device_type, device_id = device.split("-") + handler = [ + h for h in self.handlers if h.type == device_type and h.id == device_id + ][0] + return handler.hostdev_xml.xml + + +class NodeDevHandler(object): + """An object to handle actions on node devices""" + + device_address_counter = 10 + + def __init__(self, device_type, device_id): + """ + Holds the initial identifiers and prepares + fields for future use. + It also prepares the device identifiers for + the host device xml and check inside the guest. + + Examples: + vfio_ap: device_type=ap, device_id=00.000e + vfio_ccw: device_type=ccw, device_id=0.0.5200 + pci_ism: device_type=ism, device_id=0000.00.00.0 + pci_roce: device_type=roce, device_id=0000.00.00.2 + """ + self.type = device_type + if self.type not in ["ap", "ccw", "ism", "roce"]: + raise TestError(f"Unknown device type {self.type}") + self.id = device_id + self.nodedev_name = None + self.hostdev_xml = None + self.mdev_handler = None + self.guest_id = None + self.devno = None + self.uid = None + self.fid = None + self.previously_started = False + + if self.type in ["ism", "roce"]: + self.uid = f"{NodeDevHandler.device_address_counter:#0{6}x}" + self.fid = f"{NodeDevHandler.device_address_counter:#0{10}x}" + self.guest_id = f"{NodeDevHandler.device_address_counter:#0{6}x}:00:00.0".replace("0x", "") + NodeDevHandler.device_address_counter += 1 + elif self.type in ["ccw"]: + self.devno = f"{NodeDevHandler.device_address_counter:#0{6}x}" + NodeDevHandler.device_address_counter += 1 + + def start(self): + """Starts the device""" + if self.type == "ap": + if not self.previously_started: + self.mdev_handler = MdevHandler.from_type("vfio_ap-passthrough") + self.nodedev_name = self.mdev_handler.create_nodedev("nodedev", [self.id]) + self.hostdev_xml = vfio.get_hostdev_xml(self.mdev_handler.uuid, "vfio-ap") + self.previously_started = True + elif self.type == "ccw": + if not self.previously_started: + self.mdev_handler = MdevHandler.from_type("vfio_ccw-io") + self.mdev_handler.expected_device_address = f"0.0.{self.devno}".replace( + "0x", "" + ) + self.nodedev_name = self.mdev_handler.create_nodedev( + api="nodedev", devid=self.id + ) + hostdev_xml = vfio.get_hostdev_xml(self.mdev_handler.uuid, "vfio-ccw") + addr = hostdev_xml.Address.new_from_dict( + { + "type_name": "ccw", + "cssid": "0xfe", + "ssid": "0x0", + "devno": self.devno, + } + ) + hostdev_xml.address = addr + hostdev_xml.xmltreefile.write() + self.hostdev_xml = hostdev_xml + self.previously_started = True + else: + if not self.previously_started: + self.nodedev_name = "pci_" + self.id.replace(":", "_").replace(".", "_") + pci_xml = NodedevXML.new_from_dumpxml(self.nodedev_name) + hostdev_xml = vfio.get_hostdev_xml(pci_xml.cap.get_address_dict()) + addr = hostdev_xml.Address.new_from_dict( + { + "type_name": "pci", + "domain": "0x0000", + "bus": "0x00", + "slot": "0x00", + "function": "0x0", + } + ) + zpci = addr.Zpci.new_from_dict({"uid": self.uid, "fid": self.fid}) + addr.set_zpci_attrs(zpci) + hostdev_xml.address = addr + hostdev_xml.xmltreefile.write() + self.hostdev_xml = hostdev_xml + self.previously_started = True + + def stop(self, ignore_status=False): + """ + Stops the device + + :param ignore_status: if to ignore if device can't be stopped + this avoids issues during test teardown + """ + if self.type in ["ism", "roce"]: + return + virsh.nodedev_destroy( + self.nodedev_name, debug=True, ignore_status=ignore_status + ) + + def check_present(self, session): + """ + Checks if the device is present inside the guest. + + :param session: the guest console session + """ + if self.type in ["ap", "ccw"]: + self.mdev_handler.check_device_present_inside_guest(session) + elif self.type in ["ism", "roce"]: + name_part = "ISM" if self.type == "ism" else "Ethernet" + vfio.check_pci_device_present(self.guest_id, name_part, session) + + def clean_up(self): + """Cleans the handler up""" + if self.mdev_handler: + self.mdev_handler.clean_up() + + +def run(test, params, env): + """ + These tests execute workflows over passthrough devices + and VMs. + + The test steps are configured in the test configuration via + the parameter `cmds`. It holds all steps to be executed. + + All steps are terminated with ",". + There are two kind of steps: + action;device_identifier - this is an action to be executed on the node + device by the NodeDevHandler instance, e.g. start + or stop the device + action;vm_idx[;device_identifier] - this is an action prefixed with "vm_"; + the action is executed on the VM or delegated, + s. VMHandler; the vm_idx determines which VM is used + and the optional parameter `device_identifier` is passed + for actions that involve both, VM and the node device, + e.g. `vm_attach;0;ap-0.0.000e` + """ + vm_handler = VMHandler(env.get_all_vms()) + + try: + cmds = params.get("cmds").split(",") + handlers = NodeDevHandlerAggregator() + parts = None + action = None + vm_idx = None + device = None + hostdev_xml = None + for cmd in cmds: + if not cmd.strip(): + continue + LOG.debug(f"Run {cmd}.") + parts = cmd.split(";") + action = parts[0] + if not action.startswith("vm"): + device = parts[1] + handlers.add_once(device) + handlers.run(action, device) + else: + action = parts[0].replace("vm_", "") + vm_idx = parts[1] + if len(parts) > 2: + device = parts[2] + vm_handler.run(action, int(vm_idx), device, handlers) + + finally: + if vm_handler: + vm_handler.clean_up() + if handlers: + for handler in handlers.handlers: + handler.stop(ignore_status=True) + handler.clean_up() diff --git a/provider/vfio/__init__.py b/provider/vfio/__init__.py index 0ab09595037..d59409523b3 100644 --- a/provider/vfio/__init__.py +++ b/provider/vfio/__init__.py @@ -1,19 +1,97 @@ +import logging +import re + +from avocado.core.exceptions import TestFail from virttest.libvirt_xml.devices.hostdev import Hostdev +from virttest.libvirt_xml.nodedev_xml import MdevXML, NodedevXML + +LOG = logging.getLogger("avcoado." + __name__) -def get_hostdev_xml(uuid, model): +def get_hostdev_xml(address, model=""): """ Creates a hostdev instance for a mediated device with given uuid. - :param uuid: UUID of the mediated device + :param address: For mediated devices, the UUID of the mediated device + For PCI devices, the full address element :param model: mediated device type model, e.g. 'vfio-ccw' + If omitted, treat as PCI device """ hostdev_xml = Hostdev() hostdev_xml.mode = "subsystem" - hostdev_xml.model = model - hostdev_xml.type = "mdev" - hostdev_xml.source = hostdev_xml.new_source(**{"uuid": uuid}) + if "vfio" in model: + hostdev_xml.model = model + hostdev_xml.type = "mdev" + hostdev_xml.source = hostdev_xml.new_source(**{"uuid": address}) + else: + hostdev_xml.type = "pci" + hostdev_xml.managed = "yes" + hostdev_xml.source = hostdev_xml.new_source(**address) hostdev_xml.xmltreefile.write() return hostdev_xml + + +def get_nodedev_xml(device_type, parent, uuid, domains=[]): + """ + Create and return the node device XML for Mediated Devices. + + :param device_type: //capabilities/type@id + :param parent: //parent + :param uuid: //capability/uuid + :param domains: for vfio_ap-passthrough, the domains to be passed through + e.g. ["00.000e", "00.000f", "01.000e", "01.000f"] + """ + device_xml = NodedevXML() + device_xml["parent"] = parent + mdev_xml = MdevXML() + attributes = { + "type_id": device_type, + "uuid": uuid, + } + if domains: + attrs = [] + cards = [] + doms = [] + for domain in domains: + card, dom = domain.split(".") + if card not in cards: + attrs.append({"name": "assign_adapter", "value": "0x" + card}) + cards.append(card) + if dom not in doms: + attrs.append({"name": "assign_domain", "value": "0x" + dom}) + doms.append(dom) + attributes["attrs"] = attrs + mdev_xml.setup_attrs(**attributes) + device_xml.set_cap(mdev_xml) + LOG.debug("Device XML: %s", device_xml) + return device_xml + + +def get_parent_device(device_name): + """ + Gets the parent device name for the given device name + as known by libvirt + + :param device_name: node device name + """ + xml = NodedevXML.new_from_dumpxml(device_name) + return xml["parent"] + + +def check_pci_device_present(guest_pci_id, name_part, session): + """ + Checks if the pci device with id and given part of its name + are present in the guest + + :param guest_pci_id: expected device id inside of the guest, + e.g. '0000:00:00.0' + :param name_part: part of it's name e.g. "Mellanox Technologies" + :param session: guest session + :raises TestFail: if the device is not listed + """ + s, o = session.cmd_status_output("lspci", print_func=LOG.debug) + pattern = guest_pci_id + ".*" + name_part + if s or not [x for x in o.split("\n") if re.search(pattern, x)]: + raise TestFail(f"Couldn't find {guest_pci_id} with {name_part} in {o}") diff --git a/provider/vfio/ccw.py b/provider/vfio/ccw.py index 01973c2d71e..2975e94e399 100644 --- a/provider/vfio/ccw.py +++ b/provider/vfio/ccw.py @@ -178,6 +178,17 @@ def set_device_online(device_id, session=None): raise TestError("Could not set device online. %s" % out) +def get_subchannel_info(session=None): + """ + Gets the subchannel path info + + :param session: if given, get info inside guest + """ + paths = SubchannelPaths(session) + paths.get_info() + return paths + + def get_first_device_identifiers(chpids, session): """ Gets the usual device identifier cssid.ssid.devno @@ -188,8 +199,7 @@ def get_first_device_identifiers(chpids, session): :raises TestError: if the device can't be found inside guest """ - paths = SubchannelPaths(session) - paths.get_info() + paths = get_subchannel_info(session) devices_inside_guest = [ x for x in paths.devices if x[paths.HEADER["CHPIDs"]] == chpids ] @@ -209,8 +219,7 @@ def device_is_listed(session, chpids): :return: True if device is listed """ - paths = SubchannelPaths(session) - paths.get_info() + paths = get_subchannel_info(session) devices_inside_guest = [ x for x in paths.devices if x[paths.HEADER["CHPIDs"]] == chpids ] @@ -319,8 +328,7 @@ def select_first_available_device(device_ids): :return device: device info as defined by SubchannelPaths :raise TestError: if no available devices is found. """ - paths = SubchannelPaths() - paths.get_info() + paths = get_subchannel_info() for device in paths.devices: for device_id in device_ids: if device[paths.HEADER["Device"]] == device_id: @@ -338,8 +346,7 @@ def get_device_info(devid=None): :return: Subchannel and Channel path ids (schid, chpids) """ - paths = SubchannelPaths() - paths.get_info() + paths = get_subchannel_info() device = None if devid: device = paths.get_device(devid) diff --git a/provider/vfio/mdev_handlers.py b/provider/vfio/mdev_handlers.py index 67982185040..61e33c9d376 100644 --- a/provider/vfio/mdev_handlers.py +++ b/provider/vfio/mdev_handlers.py @@ -1,26 +1,25 @@ """ This module contains classes and functions for handling mediated devices """ -import logging +import logging +import re from time import sleep from uuid import uuid4 -from avocado.core.exceptions import TestError -from avocado.core.exceptions import TestFail - +from avocado.core.exceptions import TestError, TestFail from virttest import virsh from virttest.utils_misc import wait_for -from virttest.utils_zcrypt import CryptoDeviceInfoBuilder, \ - APMaskHelper, MatrixDevice, load_vfio_ap, unload_vfio_ap +from virttest.utils_zcrypt import (APMaskHelper, CryptoDeviceInfoBuilder, + MatrixDevice, load_vfio_ap, unload_vfio_ap) -from provider.vfio import ccw +from provider.vfio import ccw, get_nodedev_xml, get_parent_device -LOG = logging.getLogger('avocado.' + __name__) +LOG = logging.getLogger("avocado." + __name__) class MdevHandler(object): - """ Base class for mdev type specific implementations """ + """Base class for mdev type specific implementations""" def create_nodedev(self, api="nodedev"): """ @@ -37,7 +36,7 @@ def create_nodedev(self, api="nodedev"): raise NotImplementedError() def get_target_address(self): - """ Returns a target address to use for hostdev """ + """Returns a target address to use for hostdev""" raise NotImplementedError() def check_device_present_inside_guest(self, session): @@ -49,7 +48,7 @@ def check_device_present_inside_guest(self, session): raise NotImplementedError() def clean_up(self): - """ Stops the mediated device and returns resources to the host """ + """Stops the mediated device and returns resources to the host""" raise NotImplementedError() @staticmethod @@ -76,22 +75,25 @@ def get_first_mdev_nodedev_name(): result = virsh.nodedev_list(cap="mdev", debug=True) device_names = result.stdout.strip().splitlines() if result.exit_status or len(device_names) == 0: - raise TestError("Couldn't create nodedev. %s. %s." % - (result.stderr, result.stdout)) + raise TestError( + "Couldn't create nodedev. %s. %s." % (result.stderr, result.stdout) + ) return device_names[0] class CcwMdevHandler(MdevHandler): - """ Class implementing test methods for vfio_ccw-io """ + """Class implementing test methods for vfio_ccw-io""" def __init__(self): - self.uuid = None + self.uuid = str(uuid4()) self.chpids = None self.schid = None self.target_address = None self.expected_device_address = None self.device_id = None + self.nodedev_pattern = r"mdev.*\d{4}" self.session = None + self.parent = None def create_nodedev(self, api="mdevctl", devid=None): """ @@ -100,24 +102,39 @@ def create_nodedev(self, api="mdevctl", devid=None): :return: name of mdev device as node device """ - if api != "mdevctl": + previously_run = self.schid is not None + if not previously_run: + self.schid, self.chpids = ccw.get_device_info(devid) + self.parent = get_parent_device("ccw_" + devid.replace(".", "_")) + ccw.set_override(self.schid) + + if api == "mdevctl": + return self._mdevctl_start() + elif api == "nodedev": + device_xml = get_nodedev_xml("vfio_ccw-io", self.parent, self.uuid) + return self._nodedev_create(device_xml.xml) + else: raise TestError("Handling mdev via '%s' is not implemented." % api) - self.schid, self.chpids = ccw.get_device_info(devid) - self.device_id, _ = ccw.get_first_device_identifiers(self.chpids, None) - ccw.set_override(self.schid) - self.uuid = str(uuid4()) + def _mdevctl_start(self): ccw.start_device(self.uuid, self.schid) return get_first_mdev_nodedev_name() + def _nodedev_create(self, xml): + res = virsh.nodedev_create(xml, debug=True, ignore_status=False) + o = res.stdout_text + return re.search(self.nodedev_pattern, o)[0] + def get_target_address(self): """ Returns a valid target device address :return: hostdev target address """ - self.target_address = "address.type=ccw,address.cssid=0xfe,address.ssid=0x0,address.devno=0x1111" + self.target_address = ( + "address.type=ccw,address.cssid=0xfe,address.ssid=0x0,address.devno=0x1111" + ) self.expected_device_address = "0.0.1111" return self.target_address @@ -129,13 +146,21 @@ def check_device_present_inside_guest(self, session): :raises: TestFail if device not found """ self.session = session - device, _ = ccw.get_first_device_identifiers(self.chpids, session) - if device != self.expected_device_address: - raise TestFail("Couldn't find device inside guest." - "Expected address %s, found %s." % - (self.expected_device_address, device)) - LOG.debug("Device was found inside guest with" - " expected id %s." % device) + paths = ccw.get_subchannel_info(session) + found_devices = [ + x + for x in paths.devices + if x[paths.HEADER["Device"]] == self.expected_device_address + ] + if not found_devices: + raise TestFail( + "Couldn't find device inside guest." + "Expected address %s, found %s." + % (self.expected_device_address, paths.devices) + ) + LOG.debug( + "Device was found inside guest with" " expected id %s." % found_devices[0] + ) def clean_up(self): """ @@ -155,41 +180,60 @@ def clean_up(self): class ApMdevHandler(MdevHandler): - """ Class implementing test methods for vfio_ap-passthrough """ + """Class implementing test methods for vfio_ap-passthrough""" def __init__(self): + self.uuid = str(uuid4()) self.mask_helper = None self.matrix_dev = None self.session = None self.devices = None + self.nodedev_pattern = "mdev.*matrix" # minimal supported hwtype self.MIN_HWTYPE = 10 self.vfio_ap_loaded = None - def create_nodedev(self, api="sysfs"): + def create_nodedev(self, api="sysfs", domains=[]): """ Creates a mediated device of a specific type and returns its name from libvirt. :return: name of mdev device as node device """ - if api != "sysfs": + previously_run = self.devices is not None + if not previously_run: + load_vfio_ap() + self.vfio_ap_loaded = True + + info = CryptoDeviceInfoBuilder.get() + LOG.debug("Host lszcrypt got %s", info) + + if not info.entries or int(info.domains[0].hwtype) < self.MIN_HWTYPE: + raise TestError( + "vfio-ap requires at least HWTYPE %s." % self.MIN_HWTYPE + ) + + if not domains: + self.devices = [info.domains[0]] + else: + self.devices = [x for x in info.domains if ".".join(x.id) in domains] + self.mask_helper = APMaskHelper.from_infos(self.devices) + + if api == "sysfs": + self.matrix_dev = MatrixDevice.from_infos(self.devices) + return get_first_mdev_nodedev_name() + elif api == "nodedev": + device_xml = get_nodedev_xml( + "vfio_ap-passthrough", "ap_matrix", self.uuid, domains + ) + return self._nodedev_create(device_xml.xml) + else: raise TestError("Handling mdev via '%s' is not implemented." % api) - load_vfio_ap() - self.vfio_ap_loaded = True - - info = CryptoDeviceInfoBuilder.get() - LOG.debug("Host lszcrypt got %s", info) - - if not info.entries or int(info.domains[0].hwtype) < self.MIN_HWTYPE: - raise TestError("vfio-ap requires at least HWTYPE %s." % self.MIN_HWTYPE) - - self.devices = [info.domains[0]] - self.mask_helper = APMaskHelper.from_infos(self.devices) - self.matrix_dev = MatrixDevice.from_infos(self.devices) - - return get_first_mdev_nodedev_name() + def _nodedev_create(self, xml): + res = virsh.nodedev_create(xml, debug=True, ignore_status=False) + o = res.stdout_text + return re.search(self.nodedev_pattern, o)[0] def create_blank_nodedev(self): """ @@ -231,15 +275,20 @@ def verify_passed_through(): if guest_info.domains: default_driver_on_host = self.devices[0].driver driver_in_guest = guest_info.domains[0].driver - LOG.debug("Expecting default drivers from host and guest" - " to be the same: { host: %s, guest: %s }", - default_driver_on_host, driver_in_guest) + LOG.debug( + "Expecting default drivers from host and guest" + " to be the same: { host: %s, guest: %s }", + default_driver_on_host, + driver_in_guest, + ) return default_driver_on_host == driver_in_guest return False if not wait_for(verify_passed_through, timeout=60, step=10): - raise TestFail("Crypto domain not attached correctly in guest." - " Please, check the test log for details.") + raise TestFail( + "Crypto domain not attached correctly in guest." + " Please, check the test log for details." + ) def clean_up(self): """ From 9f20b0eace88e2c9c1bc155869c6c7953741cd2c Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 4 Sep 2024 15:53:37 +0200 Subject: [PATCH 0574/1055] update_iface_link_state: make host_iface configurable Need to run this test against the second interface on our host. Signed-off-by: Sebastian Mitterle --- .../virtual_network/update_device/update_iface_link_state.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_iface_link_state.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_iface_link_state.cfg index 361d86b2c4d..a5a0f9d5134 100644 --- a/libvirt/tests/cfg/virtual_network/update_device/update_iface_link_state.cfg +++ b/libvirt/tests/cfg/virtual_network/update_device/update_iface_link_state.cfg @@ -31,6 +31,7 @@ iface_base_attrs = {"type_name": "direct", "source": {"dev": host_iface, "mode": "bridge"}} - ethernet: only virtio + host_iface = create_tap = "yes" iface_base_attrs = {"type_name": "ethernet", "target": {"dev": tap_name, "managed": "no"}} From 50c275f0889ec20333b76be2002941915c420b0a Mon Sep 17 00:00:00 2001 From: Slancaster1 Date: Wed, 4 Sep 2024 10:35:46 -0400 Subject: [PATCH 0575/1055] boot_from_usb_device.cfg: Update regex - The Problem The test guest_os_booting.boot_order.usb_device.block_device looks for a regex to see if the usb boot device is being booted first. If the usb device is blank, edk2 will reorder the boot order, to deprioritize the usb device. And it won't print it first in the boot order. - The Solution We can see that it attempts to boot from the usb if we see edk2 printing the "USB_BOOT_TEST_UNIT_READY" command output. ``` UsbBootExecCmd: Success to Exec 0x0 Cmd (Result = 1) ``` Cmd 0x0: Test Unit Ready Opcode Result = 1: The unit was ready for further commands This is printed when edk2 is asking the USB device if it is ready to recieve further commands. We can simply test for this output to see if edk2 considered the usb device for booting. Signed-off-by: Slancaster1 --- .../cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg index b3e6924fa5f..0c3232fdb5e 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_usb_device.cfg @@ -3,7 +3,7 @@ start_vm = no bus_type = "usb" bootmenu_dict = {'bootmenu_enable': 'yes', 'bootmenu_timeout': '3000', 'bios_useserial': 'yes'} - check_prompt = "UEFI .* USB|1. USB MSC Drive .*|UsbBootDetectMedia: UsbBootIsUnitReady .*" + check_prompt = "UEFI .* USB|1. USB MSC Drive .*|UsbBootDetectMedia: UsbBootIsUnitReady .*|.*UsbBootExecCmd: Success to Exec 0x0 Cmd \(Result = 1\).*" only q35, aarch64 aarch64: bootmenu_dict = {'bootmenu_enable': 'yes', 'bootmenu_timeout': '3000'} From 8381d075a65450104a34ae1ff04c80570f6d76b7 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 4 Sep 2024 11:20:25 -0400 Subject: [PATCH 0576/1055] update_iface_with_identifier: disable test on s390x On s390x, virtio addresses are ccw not pci. Disable test case. Signed-off-by: Sebastian Mitterle --- .../update_device/update_iface_with_identifier.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_identifier.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_identifier.cfg index 157befdc4a1..00450effbdd 100644 --- a/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_identifier.cfg +++ b/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_identifier.cfg @@ -23,6 +23,7 @@ status_error = yes err_msg = cannot change network interface mac address from .* to .* - right_mac_alias_wrong_pci: + no s390-virtio status_error = yes err_msg = ${err_msg_matching} update_attrs = {'link_state': 'down'} From a217a59d95de95dcc434173028ea40459bc38ee6 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Thu, 5 Sep 2024 06:19:44 -0400 Subject: [PATCH 0577/1055] attach_interface_with_model: don't attach incompatible controller On s390x, pcie-to-pci-bridge is not available. Don't attach this. Signed-off-by: Sebastian Mitterle --- .../attach_interface_with_model.cfg | 1 + .../attach_interface_with_model.py | 17 ++++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.cfg b/libvirt/tests/cfg/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.cfg index 271d3ffe5fb..7535c6dc3c0 100644 --- a/libvirt/tests/cfg/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.cfg +++ b/libvirt/tests/cfg/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.cfg @@ -11,6 +11,7 @@ pci_model = pcie-root-port s390-virtio: check_pci_model = no + bridge_controller_needed = no - e1000e: only x86_64 iface_driver = e1000e diff --git a/libvirt/tests/src/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.py b/libvirt/tests/src/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.py index 72f574cd1fc..b249c2392b8 100644 --- a/libvirt/tests/src/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.py +++ b/libvirt/tests/src/virtual_network/hotplug/attach_detach_interface/attach_interface_with_model.py @@ -52,18 +52,21 @@ def run(test, params, env): iface_driver = params.get("iface_driver") model_type = params.get("model_type") check_pci_model = params.get("check_pci_model", "yes") == "yes" + bridge_controller_needed = params.get("bridge_controller_needed", "yes") == "yes" vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) bkxml = vmxml.copy() try: - pci_controllers = vmxml.get_controllers("pci") - for controller in pci_controllers: - if controller.get("model") == "pcie-to-pci-bridge": - break - else: - controller_dict = {"model": "pcie-to-pci-bridge"} - libvirt_vmxml.modify_vm_device(vmxml, "controller", controller_dict, 50) + if bridge_controller_needed: + pci_controllers = vmxml.get_controllers("pci") + for controller in pci_controllers: + if controller.get("model") == "pcie-to-pci-bridge": + break + else: + controller_dict = {"model": "pcie-to-pci-bridge"} + libvirt_vmxml.modify_vm_device(vmxml, "controller", controller_dict, 50) + libvirt_vmxml.remove_vm_devices_by_type(vm, "interface") test.log.debug(f"VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}") From f49eef78be9334ec0a7aadc33bf9985b84619a44 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Fri, 6 Sep 2024 01:12:13 -0400 Subject: [PATCH 0578/1055] Add debug info and libvirt daemon restart check Signed-off-by: liang-cong-red-hat --- .../memory/memory_devices/virtio_mem_device_lifecycle.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/memory/memory_devices/virtio_mem_device_lifecycle.py b/libvirt/tests/src/memory/memory_devices/virtio_mem_device_lifecycle.py index 388fac4d96a..f794354e22a 100644 --- a/libvirt/tests/src/memory/memory_devices/virtio_mem_device_lifecycle.py +++ b/libvirt/tests/src/memory/memory_devices/virtio_mem_device_lifecycle.py @@ -11,7 +11,7 @@ import os -from virttest import utils_libvirtd +from virttest.utils_libvirtd import Libvirtd from virttest import virsh from virttest.libvirt_xml import vm_xml @@ -49,6 +49,7 @@ def check_virtio_mem_device_xml(xpath_dict): like {"alias_name":[xpath1, xpath2]},...} """ vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + test.log.debug("Current guest config xml is:\n%s", vmxml) memory_devices = vmxml.devices.by_device_tag('memory') target_memory_num = 0 for alias_name, xpath_list in xpath_dict.items(): @@ -173,7 +174,9 @@ def run_test(): vm.wait_for_login().close() check_virtio_mem_device_xml({init_alias_name: init_xpath_list, plug_alias_name: plug_xpath_list}) - utils_libvirtd.libvirtd_restart() + libvirt_daemon = Libvirtd() + if not libvirt_daemon.restart(reset_failed=False): + test.fail('libvirt deamon restarts failed or is not working properly') check_virtio_mem_device_xml({init_alias_name: init_xpath_list, plug_alias_name: plug_xpath_list}) def teardown_test(): From 8a4c61408bed3c30dcbb916f0653bd9d35666a6b Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Fri, 6 Sep 2024 04:09:51 -0400 Subject: [PATCH 0579/1055] selinux_seclabel_per_device:Fix UnboundLocalError Signed-off-by: Haijiao Zhao --- libvirt/tests/src/svirt/selinux/selinux_seclabel_per_device.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/svirt/selinux/selinux_seclabel_per_device.py b/libvirt/tests/src/svirt/selinux/selinux_seclabel_per_device.py index c79aa10fa09..e3fcd426bc0 100644 --- a/libvirt/tests/src/svirt/selinux/selinux_seclabel_per_device.py +++ b/libvirt/tests/src/svirt/selinux/selinux_seclabel_per_device.py @@ -89,7 +89,7 @@ def run(test, params, env): if not status_error: test.fail(details) test.log.debug("VM XML: %s.", VMXML.new_from_inactive_dumpxml(vm_name)) - if res.exit_status == 0: + if not ('res' in locals() and res.exit_status != 0): res = virsh.start(vm.name) else: test.log.info("TEST_STEP: Hot plug a device with dac setting.") From adc534e7dc71f4edef2a3c94651a6b2f0e608000 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 9 Sep 2024 02:44:46 -0400 Subject: [PATCH 0580/1055] pxe_installation: add flag to void certificate error Installation media might not have a valid certificate for our testing. This is not critical for the test case. Append kernel parameter to skip verification. Signed-off-by: Sebastian Mitterle --- virttools/tests/src/virt_install/pxe_installation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/virttools/tests/src/virt_install/pxe_installation.py b/virttools/tests/src/virt_install/pxe_installation.py index 3c9945ed991..64f961ddb8a 100644 --- a/virttools/tests/src/virt_install/pxe_installation.py +++ b/virttools/tests/src/virt_install/pxe_installation.py @@ -35,7 +35,7 @@ def create_tftp_content(install_tree_url, kickstart_url): label linux kernel kernel.img initrd initrd.img -append ip=dhcp inst.repo=%s inst.ks=%s +append ip=dhcp inst.repo=%s inst.ks=%s inst.noverifyssl """ % (install_tree_url, kickstart_url) with open(os.path.join(tftp_dir, boot_file), "w") as f: From 17bd4cee898c0db241db40060cf2d6f9dbdde355 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 9 Sep 2024 02:56:14 -0400 Subject: [PATCH 0581/1055] capabilities: don't check cluster_id on s390x Attributes on s390x are: thread, core, book, drawer. Skip check cluster information as it doesn't apply. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/virsh_cmd/host/virsh_capabilities.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libvirt/tests/src/virsh_cmd/host/virsh_capabilities.py b/libvirt/tests/src/virsh_cmd/host/virsh_capabilities.py index d8b8b70a60f..cc959291420 100644 --- a/libvirt/tests/src/virsh_cmd/host/virsh_capabilities.py +++ b/libvirt/tests/src/virsh_cmd/host/virsh_capabilities.py @@ -73,6 +73,7 @@ def _compare_value(cmd, value_in_capxml, key_in_cpu): current_arch = platform.machine() is_x8664 = True if current_arch == "x86_64" else False is_aarch64 = True if current_arch == "aarch64" else False + is_s390x = True if current_arch == "s390x" else False prefix_cmd = "cat /sys/devices/system/cpu/cpu%s/topology/%s" file_name_key_mapping = {"physical_package_id": "socket_id", "cluster_id": "cluster_id", @@ -82,6 +83,8 @@ def _compare_value(cmd, value_in_capxml, key_in_cpu): file_name_key_mapping.update({"die_id": "die_id"}) if is_aarch64 or is_x8664: file_name_key_mapping.update({"cluster_id": "cluster_id"}) + if is_s390x: + del file_name_key_mapping["cluster_id"] for a_cell in cell_list: cpu_list = a_cell.cpu for a_cpu in cpu_list: From 1a72e042eee0187ef43d53979696763f2fca9ede Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 9 Sep 2024 03:40:39 -0400 Subject: [PATCH 0582/1055] Change guest memory statistics checking timeline Signed-off-by: liang-cong-red-hat --- .../period_config_of_memory_balloon.cfg | 2 +- .../period_config_of_memory_balloon.py | 18 ++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_balloon/period_config_of_memory_balloon.cfg b/libvirt/tests/cfg/memory/memory_balloon/period_config_of_memory_balloon.cfg index abf6bfdd306..2052f49ed8d 100644 --- a/libvirt/tests/cfg/memory/memory_balloon/period_config_of_memory_balloon.cfg +++ b/libvirt/tests/cfg/memory/memory_balloon/period_config_of_memory_balloon.cfg @@ -5,7 +5,7 @@ current_mem_unit = "KiB" current_mem = "2097152" mem_value = "2097152" - mem_operation = "swapoff -a; dd if=/dev/zero of=/tmp/temp bs=1024K count=10; memhog -r5 500M" + mem_operation = "swapoff -a && dd if=/dev/zero of=/tmp/temp bs=1024K count=10 && timeout 5s memhog -r5000 500M" variants: - virtio_model: memballoon_model = "virtio" diff --git a/libvirt/tests/src/memory/memory_balloon/period_config_of_memory_balloon.py b/libvirt/tests/src/memory/memory_balloon/period_config_of_memory_balloon.py index 57209ba9f5e..a5dc82ad8ef 100644 --- a/libvirt/tests/src/memory/memory_balloon/period_config_of_memory_balloon.py +++ b/libvirt/tests/src/memory/memory_balloon/period_config_of_memory_balloon.py @@ -9,7 +9,6 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ import re -from virttest import utils_misc from virttest import virsh from virttest.libvirt_xml import vm_xml @@ -45,20 +44,15 @@ def get_memory_statistics(): :return: usable mem, last_update, disk_caches value in result. """ - def _get_response(): - res = virsh.dommemstat(vm_name, ignore_status=False, - debug=True).stdout_text - return re.findall(r'usable (\d+)', res) - - if utils_misc.wait_for(_get_response, 30, 5): - res = virsh.dommemstat(vm_name, ignore_status=False, - debug=True).stdout_text + res = virsh.dommemstat(vm_name, ignore_status=False, + debug=True).stdout_text + if re.findall(r'usable (\d+)', res): usable_mem = re.findall(r'usable (\d+)', res)[0] last_update = re.findall(r'last_update (\d+)', res)[0] disk_caches = re.findall(r'disk_caches (\d+)', res)[0] return usable_mem, last_update, disk_caches else: - test.fail("Not get virsh dommemstat result in 25s") + test.fail("Fail to get virsh dommemstat result") def check_vm_dommemstat(period_config, usable_mem, last_update, disk_caches): @@ -104,12 +98,12 @@ def check_xml_and_dommemstat(period_set): vmxml, expect_xpath, ignore_status=True) == xpath_existed: test.fail("Expect to get '%s' in xml " % expect_xpath) + guest_session = vm.wait_for_login() usable_mem, last_update, disk_caches = get_memory_statistics() - guest_session = vm.wait_for_login() status, stdout = guest_session.cmd_status_output(mem_operation) guest_session.close() - if status: + if status != 0 and status != 124: test.fail("Failed to consume memory: %s" % stdout) check_vm_dommemstat(period_set, usable_mem, last_update, disk_caches) From 2e9b8889b8816f363f5102b1c5a1dd2d0137dee9 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Mon, 9 Sep 2024 16:14:23 +0800 Subject: [PATCH 0583/1055] virsh_domstate: Update panic device's xml Update to use to ask libvirt to configure the model attribute automatically. Signed-off-by: Yingshun Cui --- libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py b/libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py index d9e990993c5..14d0350a70c 100644 --- a/libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py +++ b/libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py @@ -2,7 +2,6 @@ import os import shutil import logging as log -import platform import time import signal @@ -166,12 +165,6 @@ def run(test, params, env): if not vmxml.xmltreefile.find('devices').findall('panic'): # Add device to domain panic_dev = Panic() - if "ppc" not in platform.machine(): - panic_dev.addr_type = "isa" - panic_dev.addr_iobase = "0x505" - if platform.machine() == 'aarch64': - panic_dev.model = "pvpanic" - panic_dev.addr_type = "pci" vmxml.add_device(panic_dev) vmxml.sync() # Config auto_dump_path in qemu.conf From 1bf68b7aa7a97a745e95cd42bac45e1d4eddb77e Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Mon, 9 Sep 2024 11:15:49 -0400 Subject: [PATCH 0584/1055] Add test scenarios to v2v windows vmtools case Signed-off-by: Ming Xie --- v2v/tests/cfg/function_test_esx.cfg | 32 ++++++++++++++++++++++----- v2v/tests/src/function_test_esx.py | 34 ++++++++++++++++++++--------- 2 files changed, 51 insertions(+), 15 deletions(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 3cde48a725c..27589048f73 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -138,11 +138,11 @@ main_vm = "VM_NAME_WIN2022_V2V_EXAMPLE" - win2025: os_version = "win2025" - main_vm = "VM_NAME_WIN2025_V2V_EXAMPLE" + main_vm = "VM_NAME_WIN2025_EFI_V2V_EXAMPLE" boottype = 3 - win11: os_version = "win11" - main_vm = "VM_NAME_WIN11_V2V_EXAMPLE" + main_vm = "VM_NAME_WIN11_EFI_V2V_EXAMPLE" boottype = 3 - win10: os_version = "win10" @@ -151,7 +151,7 @@ main_vm = VM_NAME_WIN2016_V2V_EXAMPLE os_version = "win2016" - win2019: - main_vm = VM_NAME_WIN2019_V2V_EXAMPLE + main_vm = VM_NAME_WIN2019_EFI_V2V_EXAMPLE os_version = "win2019" boottype = 3 - virtio_win: @@ -194,9 +194,31 @@ main_vm = VM_NAME_WIN_3_DHCP_IP_V2V_EXAMPLE v2v_opts = VM_NAME_WIN_3_DHCP_IP_MAC_CONF_V2V_EXAMPLE - vmware_tools: - only esx_70 + only esx_80 checkpoint = 'vmware_tools' - main_vm = VM_NAME_WIN_VMWARE_TOOLS_V2V_EXAMPLE + variants: + - win2022: + os_version = "win2022" + main_vm = "VM_NAME_WIN2022_V2V_EXAMPLE" + - win2025: + os_version = "win2025" + main_vm = "VM_NAME_WIN2025_EFI_V2V_EXAMPLE" + boottype = 3 + - win11: + os_version = "win11" + main_vm = VM_NAME_WIN11_EFI_V2V_EXAMPLE + boottype = 3 + - win10: + os_version = "win10" + main_vm = VM_NAME_WIN10_EFI_V2V_EXAMPLE + boottype = 3 + - win2016: + main_vm = VM_NAME_WIN2016_V2V_EXAMPLE + os_version = "win2016" + - win2019: + main_vm = VM_NAME_WIN2019_EFI_V2V_EXAMPLE + os_version = "win2019" + boottype = 3 - rhsrvany_md5: only esx_70 checkpoint = 'rhsrvany_checksum' diff --git a/v2v/tests/src/function_test_esx.py b/v2v/tests/src/function_test_esx.py index 1777aa739ff..8ecaa71955d 100644 --- a/v2v/tests/src/function_test_esx.py +++ b/v2v/tests/src/function_test_esx.py @@ -232,18 +232,32 @@ def check_windows_vmware_tools(vmcheck): :param vmcheck: VMCheck object for vm checking """ - def _get_vmware_info(cmd): + def _get_vmtools_info(cmd): _, res = vmcheck.run_cmd(cmd) - if res and not re.search('vmtools', res, re.I): - return True - return False + exit_code = re.search(r'uninstalling VMware Tools\s+.*exit code\s+(\d+)', res).group(1) + return int(exit_code) - cmds = ['tasklist', 'sc query vmtools'] - for cmd in cmds: - res = utils_misc.wait_for( - lambda: _get_vmware_info(cmd), 600, step=30) - if not res: - test.fail("Failed to verification vmtools uninstallation") + cmd = r'type "C:\Program Files\Guestfs\Firstboot\log.txt"' + + try: + res = utils_misc.wait_for(lambda: _get_vmtools_info(cmd), 900, step=30) + except (ShellProcessTerminatedError, ShellStatusError): + # Windows guest may reboot after installing qemu-ga service + LOG.debug('Windows guest is rebooting') + if vmcheck.session: + vmcheck.session.close() + vmcheck.session = None + # VM boots up is extremely slow when all testing in running on + # rhv server simultaneously, so set timeout to 1200. + vmcheck.create_session(timeout=1200) + res = utils_misc.wait_for(lambda: _get_vmtools_info(cmd), 900, step=30) + + if res: + if os_version in ['win2025', 'win2019'] and str(res) == '1603': + #Some windows guests fail to uninstall vmware tools due to bug RHEL-51169 + LOG.info('%s guest fail to unintall VMware tools with exit code 1603 which is known issue' % os_version) + else: + test.fail("Fail to uninstall VMware-tools with exit code %s" % res) def check_windows_service(vmcheck, service_name): """ From a33e2c6f9a97aa81dee9437e392b0149ca1a2c48 Mon Sep 17 00:00:00 2001 From: Slancaster1 Date: Thu, 29 Aug 2024 14:57:51 -0400 Subject: [PATCH 0585/1055] vm_start_destroy_repeatedly: Add Hugepage Variant Add variant to vm_start_destroy_repeatedly.py for handling a vm with hugepages Signed-off-by: Slancaster1 --- .../tests/cfg/vm_start_destroy_repeatedly.cfg | 8 ++ .../tests/src/vm_start_destroy_repeatedly.py | 87 +++++++++++++++++-- 2 files changed, 88 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/cfg/vm_start_destroy_repeatedly.cfg b/libvirt/tests/cfg/vm_start_destroy_repeatedly.cfg index 909c7a4a102..1cd0e48689e 100644 --- a/libvirt/tests/cfg/vm_start_destroy_repeatedly.cfg +++ b/libvirt/tests/cfg/vm_start_destroy_repeatedly.cfg @@ -3,3 +3,11 @@ num_cycles = 3000 start_vm = no test_timeout = 288000 + check_hugepage_status = False + variants: + - hugepage: + num_cycles = 100 + check_hugepage_status = True + mb_params = {'hugepages': {}, 'source_type': 'memfd', 'access_mode': 'shared'} + vm_attrs = {'memory': 8388608, 'memory_unit': 'KiB'} + - @default: diff --git a/libvirt/tests/src/vm_start_destroy_repeatedly.py b/libvirt/tests/src/vm_start_destroy_repeatedly.py index 4aae9f1f113..603e292c104 100644 --- a/libvirt/tests/src/vm_start_destroy_repeatedly.py +++ b/libvirt/tests/src/vm_start_destroy_repeatedly.py @@ -1,6 +1,9 @@ import logging +from virttest import test_setup from virttest import virsh from virttest import utils_misc +from virttest.staging import utils_memory +from virttest.libvirt_xml import vm_xml def power_cycle_vm(test, vm, vm_name, login_timeout, startup_wait, resume_wait): @@ -37,6 +40,61 @@ def power_cycle_vm(test, vm, vm_name, login_timeout, startup_wait, resume_wait): test.fail("Failed to shutdown VM") +def setup_hugepage(vm, params): + vm_attrs = eval(params.get("vm_attrs", "{}")) + memory_amount = int(vm_attrs["memory"]) + + #Reserve memory for hugepages + hugepage_size = utils_memory.get_huge_page_size() + hugepage_nr = int(memory_amount) / hugepage_size + + config_params = params.copy() + config_params["mem"] = memory_amount + config_params["target_hugepages"] = hugepage_nr + hpc = test_setup.HugePageConfig(config_params) + hpc.setup() + + #Prepare VM XML + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) + backup_xml = vmxml.copy() + + #Remove old memory tags + vmxml.xmltreefile.remove_by_xpath("/memory") + vmxml.xmltreefile.remove_by_xpath("/currentMemory") + + #Include memory backing + mb_xml = vm_xml.VMMemBackingXML() + mb_params = eval(params.get("mb_params", "{}")) + mb_xml.setup_attrs(**mb_params) + vmxml.setup_attrs(**vm_attrs) + vmxml.mb = mb_xml + + #The relevant bug only appears if disk cache='none' + xmltreefile = vmxml.__dict_get__('xml') + disk_nodes = xmltreefile.find("devices").findall("disk") + qcow_disk = [disk for disk in disk_nodes if disk.find("driver").get("type") == "qcow2"][0] + if qcow_disk.find("driver").get("cache") != "none": + qcow_disk.find("driver").set("cache", "none") + + vmxml.xmltreefile.write() + vmxml.sync() + logging.info("New XML for Hugepage testing: {}".format(vmxml)) + + return hugepage_nr, backup_xml, hpc + + +def check_hugepage_status(test, hugepage_nr): + if hugepage_nr != utils_memory.get_num_huge_pages(): + test.fail("Total number of hugepages does not match. Expected: {}. Actual: {}" + .format(hugepage_nr, utils_memory.get_num_huge_pages())) + if hugepage_nr != utils_memory.get_num_huge_pages_free(): + test.fail("Number of free huge pages does not match. Expected: {}. Actual: {}" + .format(hugepage_nr, utils_memory.get_num_huge_pages_free())) + if utils_memory.get_num_huge_pages_rsvd() != 0: + test.fail("Huge pages still reserved. Expected: 0. Actual: {}" + .format(utils_memory.get_num_huge_pages_rsvd())) + + def run(test, params, env): """ Test qemu-kvm startup reliability @@ -52,10 +110,25 @@ def run(test, params, env): login_timeout = float(params.get("login_timeout", 240)) # Controls vm.wait_for_login() timeout startup_wait = float(params.get("startup_wait", 240)) # Controls wait time for virsh.start() resume_wait = float(params.get("resume_wait", 240)) # Controls wait for virsh.resume() - - for i in range(num_cycles): - logging.info("Starting vm '%s' -- attempt #%d", vm_name, i+1) - - power_cycle_vm(test, vm, vm_name, login_timeout, startup_wait, resume_wait) - - logging.info("Completed vm '%s' power cycle #%d", vm_name, i+1) + hugepage_check = bool(params.get("check_hugepage_status", False)) + vm_memory = int(params.get("vm_memory", 8388608)) + + backup_xml = None + hugepage_nr = None + hpc = None + if hugepage_check: + hugepage_nr, backup_xml, hpc = setup_hugepage(vm, params) + logging.info("hugepage_nr: {}".format(hugepage_nr)) + + try: + for i in range(num_cycles): + logging.info("Starting vm '%s' -- attempt #%d", vm_name, i+1) + + power_cycle_vm(test, vm, vm_name, login_timeout, startup_wait, resume_wait) + + logging.info("Completed vm '%s' power cycle #%d", vm_name, i+1) + finally: + if hugepage_check: + check_hugepage_status(test, hugepage_nr) + backup_xml.sync() + hpc.cleanup() From be7dddb59bd9c2ea40af9045986e56f479c848d4 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Thu, 29 Aug 2024 03:56:11 -0400 Subject: [PATCH 0586/1055] Add hugepage allocation checking Signed-off-by: liang-cong-red-hat --- .../tests/src/memory/memory_backing/lifecycle_for_hugepage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/memory/memory_backing/lifecycle_for_hugepage.py b/libvirt/tests/src/memory/memory_backing/lifecycle_for_hugepage.py index 8397a0e99d9..4877f9f853b 100644 --- a/libvirt/tests/src/memory/memory_backing/lifecycle_for_hugepage.py +++ b/libvirt/tests/src/memory/memory_backing/lifecycle_for_hugepage.py @@ -117,7 +117,7 @@ def setup_test(vm_name, params, test): utils_memory.set_num_huge_pages(int(vm_nr_hugepages)) hp_cfg = test_setup.HugePageConfig(params) - hp_cfg.set_kernel_hugepages(set_pagesize, set_pagenum) + hp_cfg.set_kernel_hugepages(set_pagesize, set_pagenum, False) hp_cfg.hugepage_size = mount_size hp_cfg.mount_hugepage_fs() utils_libvirtd.Libvirtd().restart() From 4ddbe02f09325e6b688c1e59f757d532129e8284 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Thu, 29 Aug 2024 23:10:38 -0400 Subject: [PATCH 0587/1055] Raise exception when huge page fail to set up Signed-off-by: liang-cong-red-hat --- libvirt/tests/src/memory/memory_misc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/memory/memory_misc.py b/libvirt/tests/src/memory/memory_misc.py index 3f8369fbee8..667f3084af1 100644 --- a/libvirt/tests/src/memory/memory_misc.py +++ b/libvirt/tests/src/memory/memory_misc.py @@ -266,8 +266,8 @@ def _setup_mbxml(): test, pg_size=default_page_size, hp_size=pagesize, hp_list=[mount_pagesize]) vm_mem_size = vmxml.memory hp_cfg = test_setup.HugePageConfig(params) - hp_cfg.set_kernel_hugepages(pagesize, vm_mem_size // pagesize) - hp_cfg.set_kernel_hugepages(mount_pagesize, mem_device_size // mount_pagesize) + hp_cfg.set_kernel_hugepages(pagesize, vm_mem_size // pagesize, False) + hp_cfg.set_kernel_hugepages(mount_pagesize, mem_device_size // mount_pagesize, False) set_vmxml(vmxml, params) _setup_mbxml() vmxml.sync() From 14c7dd7f0e88f74764744f17c4ddf30b2f6185ea Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Tue, 10 Sep 2024 04:52:12 -0400 Subject: [PATCH 0588/1055] virsh_domif_setlink_getlink:Remove driver settings from iface when model is not virtio 'driver' is only supported by virtio Signed-off-by: Haijiao Zhao --- .../tests/src/virsh_cmd/domain/virsh_domif_setlink_getlink.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_domif_setlink_getlink.py b/libvirt/tests/src/virsh_cmd/domain/virsh_domif_setlink_getlink.py index a541af206c4..10f48c203b9 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_domif_setlink_getlink.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_domif_setlink_getlink.py @@ -10,6 +10,7 @@ from virttest import utils_misc from virttest import utils_libvirtd from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_test import libvirt @@ -160,6 +161,9 @@ def check_update_device(vm, if_name, session): # generate a new one suitable for the model if vm.is_alive(): vm.destroy() + if model_type != 'virtio': + vmxml = vm_xml.VMXML.new_from_dumpxml(vm.name) + libvirt_vmxml.modify_vm_device(vmxml, 'interface', {'driver': None}) iface_dict = {'model': model_type, 'del_addr': 'yes'} libvirt.modify_vm_iface(vm_name[0], "update_iface", iface_dict) # Vm status From 8ca3f5db64ace91097f56a0a376e2524b744bf99 Mon Sep 17 00:00:00 2001 From: Julia Graham Date: Fri, 6 Sep 2024 15:49:46 -0400 Subject: [PATCH 0589/1055] Boot_order: ensure only 1 repo is used to get boot.iso Issue: VMStartError: VM 'avocado-vt-vm1' failed to start: error: Failed to start domain 'avocado-vt-vm1'error: Cannot access storage file '/var/lib/avocado/data/avocado-vt/boot.iso': No such file or directory(exit status: 1) Fix: This issue is caused by multiple repos being fetched and then their urls being concatenated together. The fix is to ensure that only 1 repo is fetched (the last result), which can in turn get the boot.iso file. --- .../src/guest_os_booting/boot_order/boot_from_cdrom_device.py | 2 +- .../guest_os_booting/boot_order/boot_with_multiple_boot_dev.py | 2 +- .../boot_order/boot_with_multiple_boot_order.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py index 8a675f0b5a2..e2f6d7b13d9 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py @@ -30,7 +30,7 @@ def parse_cdroms_attrs(params): cdrom_attrs_list.append(cdrom2_attrs) if cdrom1_attrs.get('source') or cdrom2_attrs.get('source'): - cmd = "dnf repolist -v enabled |awk '/Repo-baseurl.*composes.*BaseOS.*os/ {print $NF}'" + cmd = "dnf repolist -v enabled |awk '/Repo-baseurl.*composes.*BaseOS.*os/ {res=$NF} END{print res}'" repo_url = process.run(cmd, shell=True).stdout_text.strip() boot_img_url = os.path.join(repo_url, 'images', 'boot.iso') if os.path.exists(boot_img_path): diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py index 46087f1462a..2afb6b432be 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py @@ -47,7 +47,7 @@ def prepare_device(params, vm_name, bootable_device): libvirt_vmxml.modify_vm_device(vmxml, 'disk', disk_dict) if bootable_device == "cdrom_bootable": cdrom_path = os.path.join(data_dir.get_data_dir(), 'images', 'boot.iso') - cmd = "dnf repolist -v enabled |awk '/Repo-baseurl.*composes.*BaseOS.*os/ {print $NF}'" + cmd = "dnf repolist -v enabled |awk '/Repo-baseurl.*composes.*BaseOS.*os/ {res=$NF} END{print res}'" repo_url = process.run(cmd, shell=True).stdout_text.strip() boot_img_url = os.path.join(repo_url, 'images', 'boot.iso') download.get_file(boot_img_url, cdrom_path) diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py index ba470396fbd..6dc8b2704b9 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py @@ -42,7 +42,7 @@ def prepare_device_attrs(params, vm_name, bootable_device): file_list.append(disk_image) if bootable_device == "cdrom_bootable": cdrom_path = os.path.join(data_dir.get_data_dir(), 'images', 'boot.iso') - cmd = "dnf repolist -v enabled |awk '/Repo-baseurl.*composes.*BaseOS.*os/ {print $NF}'" + cmd = "dnf repolist -v enabled |awk '/Repo-baseurl.*composes.*BaseOS.*os/ {res=$NF} END{print res}'" repo_url = process.run(cmd, shell=True).stdout_text.strip() boot_img_url = os.path.join(repo_url, 'images', 'boot.iso') download.get_file(boot_img_url, cdrom_path) From 111c03ab86905bda722246092175c92ec5b87bda Mon Sep 17 00:00:00 2001 From: Yan Fu Date: Wed, 11 Sep 2024 20:32:47 +0800 Subject: [PATCH 0590/1055] Wait for hotunplug event to ensure device removed successfully Signed-off-by: Yan Fu --- .../tests/src/virtual_disks/virtual_disks_discard_no_unref.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_discard_no_unref.py b/libvirt/tests/src/virtual_disks/virtual_disks_discard_no_unref.py index d72b26cd5ee..57a910c8e4f 100644 --- a/libvirt/tests/src/virtual_disks/virtual_disks_discard_no_unref.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_discard_no_unref.py @@ -120,7 +120,8 @@ def run_test_hotplug_disk(vm, params, test): test.log.debug("STEP4: check the result.") check_result(vm, params, test) test.log.debug("STEP5: detach disk.") - virsh.detach_device(vm_name, disk_xml.xml, debug=True, ignore_status=False) + virsh.detach_device(vm_name, disk_xml.xml, debug=True, + wait_for_event=True, ignore_status=False) domblklist_result = virsh.domblklist(vm_name, debug=True).stdout_text.strip() if target_dev in domblklist_result: test.fail("The target disk % can't be detached in guest." % target_dev) From dc01d05212f4f9b50af90ff9b56cfcadd8d81ada Mon Sep 17 00:00:00 2001 From: Julia Graham Date: Tue, 10 Sep 2024 09:11:02 -0400 Subject: [PATCH 0591/1055] filesystem_device: Updated test.cancel to test.error Changed for the lsof command not being installed error and the not the correct amount of vms error. --- libvirt/tests/src/virtual_device/filesystem_device.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/virtual_device/filesystem_device.py b/libvirt/tests/src/virtual_device/filesystem_device.py index a8153682414..cf4d9361b20 100644 --- a/libvirt/tests/src/virtual_device/filesystem_device.py +++ b/libvirt/tests/src/virtual_device/filesystem_device.py @@ -263,10 +263,10 @@ def check_filesystem_hotplug_with_mem_setup(): huge_pages_num = 0 if hotplug_unplug and not utils_path.find_command("lsof", default=False): - test.cancel("Lsof command is required to run test, but not installed") + test.error("Lsof command is required to run test, but not installed") if len(vm_names) != guest_num: - test.cancel("This test needs exactly %d vms." % guest_num) + test.error("This test needs exactly %d vms." % guest_num) if not libvirt_version.version_compare(7, 0, 0) and not with_numa: test.cancel("Not supported without NUMA before 7.0.0") From 9101d4cc1bfb6575f0bbbe0210952210e68ff484 Mon Sep 17 00:00:00 2001 From: Chunfu Wen Date: Sat, 23 Mar 2024 03:41:24 -0400 Subject: [PATCH 0592/1055] Add bootc image builder case utilities and case scripts are provided, and cover Image type:ami vmdk qcow2 anaconda-iso raw container image reference: quay.io/centos-bootc/centos-bootc:stream9, quay.io/centos-bootc/fedora-bootc:eln, localhost/bootc:eln Signed-off-by: Chunfu Wen --- provider/bootc_image_builder/aws_utils.py | 197 ++++ .../bootc_image_build_utils.py | 856 ++++++++++++++++++ .../bootc_disk_image_build.cfg | 160 ++++ .../bootc_disk_image_install.cfg | 170 ++++ .../bootc_disk_image_build.py | 130 +++ .../bootc_disk_image_install.py | 147 +++ 6 files changed, 1660 insertions(+) create mode 100644 provider/bootc_image_builder/aws_utils.py create mode 100644 provider/bootc_image_builder/bootc_image_build_utils.py create mode 100644 virttools/tests/cfg/bootc_image_builder/bootc_disk_image_build.cfg create mode 100644 virttools/tests/cfg/bootc_image_builder/bootc_disk_image_install.cfg create mode 100644 virttools/tests/src/bootc_image_builder/bootc_disk_image_build.py create mode 100644 virttools/tests/src/bootc_image_builder/bootc_disk_image_install.py diff --git a/provider/bootc_image_builder/aws_utils.py b/provider/bootc_image_builder/aws_utils.py new file mode 100644 index 00000000000..9e306e75c84 --- /dev/null +++ b/provider/bootc_image_builder/aws_utils.py @@ -0,0 +1,197 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: chwen@redhat.com +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +"""Helper functions for aws management""" + +import logging +import os +import shutil +import textwrap +import pathlib + +from avocado.utils import process +from avocado.core import exceptions + +LOG = logging.getLogger('avocado.' + __name__) + + +def install_aws_cli_tool(params): + """ + Download AWS command line tool and install it + + :param params: wrap up all parameters + """ + vm_arch_name = params.get("vm_arch_name", "x86_64") + aws_install_cmd = f"curl https://awscli.amazonaws.com/awscli-exe-linux-{vm_arch_name}.zip -o awscliv2.zip " \ + f" && unzip awscliv2.zip -d ./ && ./aws/install " + if not os.path.exists("/usr/local/bin/aws"): + if os.path.exists("/usr/local/aws-cli"): + shutil.rmtree("/usr/local/aws-cli") + if os.path.exists("/usr/local/bin/aws_completer"): + shutil.rmtree("/usr/local/bin/aws_completer") + if os.path.exists("aws"): + shutil.rmtree("aws") + if os.path.exists("awscliv2.zip"): + os.remove("awscliv2.zip") + process.run(aws_install_cmd, shell=True, ignore_status=False) + + +def create_aws_credentials_file(aws_access_key_id, aws_access_key): + """ + Create AWS credentials file + + :param aws_access_key_id: AWS access key id + :param aws_access_key: AWS access key + """ + folder = os.path.expanduser("~/.aws") + if not os.path.exists(folder): + os.mkdir(folder) + secret_path = pathlib.Path(folder) / "credentials" + secret_path.write_text(textwrap.dedent(f""" + [default] + AWS_ACCESS_KEY_ID={aws_access_key_id} + AWS_SECRET_ACCESS_KEY={aws_access_key} + """), encoding="utf8") + + return os.path.join(folder, "credentials") + + +def create_aws_config_file(aws_region): + """ + Create AWS configuration file + + :param aws_region: AWS region + """ + folder = os.path.expanduser("~/.aws") + if not os.path.exists(folder): + os.mkdir(folder) + secret_path = pathlib.Path(folder) / "config" + secret_path.write_text(textwrap.dedent(f""" + [default] + region={aws_region} + """), encoding="utf8") + + return os.path.join(folder, "config") + + +def delete_aws_ami_id(params): + """ + delete AWS AMI id + + @param params: one dictionary wrapping various parameter + """ + ami_id = params.get("aws_ami_id") + if ami_id: + delete_cmd = "aws ec2 deregister-image --image-id %s" % ami_id + process.run(delete_cmd, shell=True, verbose=True, ignore_status=True) + + +def delete_aws_ami_snapshot_id(params): + """ + delete AWS AMI snapshot id + + @param params: one dictionary wrapping various parameter + """ + aws_ami_snapshot_id = params.get("aws_ami_snapshot_id") + if aws_ami_snapshot_id: + delete_cmd = "aws ec2 delete-snapshot --snapshot-id %s" % aws_ami_snapshot_id + process.run(delete_cmd, shell=True, verbose=True, ignore_status=True) + + +def delete_aws_key_pair(params): + """ + delete AWS key pair + + @param params: one dictionary wrapping various parameter + """ + aws_key_name = params.get("aws_key_name") + delete_key_pair_cmd = f"aws ec2 delete-key-pair --key-name {aws_key_name}" + process.run(delete_key_pair_cmd, shell=True, ignore_status=True).exit_status + + +def import_aws_key_pair(params): + """ + Import key into AWS key pair + + @param params: one dictionary wrapping various parameter + """ + aws_key_name = params.get("aws_key_name") + check_key_pair_cmd = f"aws ec2 describe-key-pairs --key-name {aws_key_name}" + status = process.run(check_key_pair_cmd, shell=True, ignore_status=True).exit_status + if status != 0: + public_key_path = os.path.join(os.path.expanduser("~/.ssh/"), "id_rsa.pub") + import_cmd = "aws ec2 import-key-pair --key-name {aws_key_name}--public-key-material fileb://{public_key_path}" + process.run(import_cmd, shell=True, verbose=True, ignore_status=True) + + +def create_aws_instance(params): + """ + create AWS instance + + @param params: one dictionary wrapping various parameter + """ + import_aws_key_pair(params) + vm_name = params.get("vm_name_bootc") + aws_key_name = params.get("aws_key_name") + aws_ami_id = params.get("aws_ami_id") + aws_subnet_id = params.get("aws_subnet_id") + aws_security_group = params.get("aws_security_group") + aws_instance_type = params.get("aws_instance_type") + create_aws_instance_cmd = "aws ec2 run-instances --image-id %s --count 1" \ + " --security-group-ids %s" \ + " --instance-type %s --key-name %s --subnet-id %s" \ + " --associate-public-ip-address --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=%s}]'" \ + " --block-device-mappings '[{\"DeviceName\":\"/dev/xvda\",\"Ebs\":{\"VolumeSize\":20,\"VolumeType\":\"gp2\"}}]'" \ + " --query 'Instances[0].InstanceId' --output text" % (aws_ami_id, aws_security_group, aws_instance_type, aws_key_name, aws_subnet_id, vm_name) + instance_id = process.run(create_aws_instance_cmd, shell=True, ignore_status=True).stdout_text.strip() + params.update({"aws_instance_id": "%s" % instance_id}) + return instance_id + + +def wait_aws_instance_running(params): + """ + wait for AWS instance running + + @param params: one dictionary wrapping various parameter + """ + aws_instance_id = params.get("aws_instance_id") + if aws_instance_id: + wait_aws_instance_cmd = f"timeout 30 aws ec2 wait instance-running --instance-ids {aws_instance_id}" + process.run(wait_aws_instance_cmd, shell=True, ignore_status=True) + + +def get_aws_instance_privateip(params): + """ + Get AWS instance private ip + + @param params: one dictionary wrapping various parameter + """ + wait_aws_instance_running(params) + aws_instance_id = params.get("aws_instance_id") + if aws_instance_id: + get_aws_instance_privateip_cmd = f"aws ec2 describe-instances --instance-ids {aws_instance_id}" \ + f" --query 'Reservations[*].Instances[*].PrivateIpAddress' --output text" + private_ip = process.run(get_aws_instance_privateip_cmd, shell=True, ignore_status=True).stdout_text.strip() + return private_ip + else: + raise exceptions.TestFail(f"AWS instance not existed yet") + + +def terminate_aws_instance(params): + """ + terminate AWS instance + + @param params: one dictionary wrapping various parameter + """ + aws_instance_id = params.get("aws_instance_id") + if aws_instance_id: + terminate_aws_instance_cmd = f"aws ec2 terminate-instances --instance-ids {aws_instance_id}" + process.run(terminate_aws_instance_cmd, shell=True, ignore_status=True) + wait_instance_terminated = f"timeout 20 aws ec2 wait instance-terminated --instance-ids {aws_instance_id}" + process.run(wait_instance_terminated, shell=True, ignore_status=True) diff --git a/provider/bootc_image_builder/bootc_image_build_utils.py b/provider/bootc_image_builder/bootc_image_build_utils.py new file mode 100644 index 00000000000..5d369fbd46d --- /dev/null +++ b/provider/bootc_image_builder/bootc_image_build_utils.py @@ -0,0 +1,856 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: chwen@redhat.com +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +"""Helper functions for bootc image builder""" + +import logging +import json +import os +import random +import shutil +import time +import textwrap +import pathlib + +from avocado.utils import path, process +from avocado.core import exceptions +from virttest import utils_package +from virttest import remote + +from provider.bootc_image_builder import aws_utils + +LOG = logging.getLogger('avocado.' + __name__) + + +def install_bib_packages(): + """ + install necessary bootc image builder necessary packages + + """ + package_list = ["podman", "skopeo", "virt-install", "curl", "virt-manager"] + for pkg in package_list: + try: + path.find_command(pkg) + except path.CmdNotFoundError: + utils_package.package_install(pkg) + + +def podman_command_build(bib_image_url, disk_image_type, image_ref, config=None, local_container=False, tls_verify="true", chownership=None, + key_store_mounted=None, target_arch=None, rootfs=None, options=None, **dargs): + """ + Use podman run command to launch bootc image builder + + :param bib_image_url: bootc image builder url + :param disk_image_type: image type to build [qcow2, ami] (default "qcow2") + :param image_ref: image reference + :param config: config file + :param local_container: whether use local container image + :param tls_verify: whether verify tls connection + :param local_container: whether use local container image + :param chownership: whether change output ownership + :param key_store_mounted: whether mount keystore folder + :param target_arch: whether specify architecture + :param rootfs: whether specify rootfs type + :param options: additional options if needed + :param dargs: standardized function API keywords + :return: CmdResult object + """ + if not os.path.exists("/var/lib/libvirt/images/output"): + os.makedirs("/var/lib/libvirt/images/output") + cmd = "sudo podman run --rm -it --privileged --pull=newer --security-opt label=type:unconfined_t -v /var/lib/libvirt/images/output:/output" + if config: + cmd += " -v %s:/config.json " % config + + if local_container: + cmd += " -v /var/lib/containers/storage:/var/lib/containers/storage " + + if options is not None: + cmd += " -v %s:/run/containers/0/auth.json " % options + + if key_store_mounted: + cmd += " -v %s " % key_store_mounted + + if dargs.get('aws.secrets'): + cmd += " --env-file=%s " % dargs.get('aws.secrets') + + cmd += " %s " \ + " --type %s --tls-verify=%s " % (bib_image_url, disk_image_type, tls_verify) + + if config: + cmd += " --config /config.json " + + if target_arch: + cmd += " --target-arch=%s " % target_arch + + aws_ami_name = dargs.get('aws_ami_name') + if aws_ami_name: + random_int = random.randint(1, 1000) + vm_arch_name = dargs.get("vm_arch_name", "x86_64") + LOG.debug(f"vm_arch_name value in podman build is : {vm_arch_name}") + aws_ami_name = f"{aws_ami_name}_{vm_arch_name}_{random_int}" + cmd += f" --aws-ami-name {aws_ami_name} --aws-bucket {dargs.get('aws_bucket')} --aws-region {dargs.get('aws_region')} " + + if local_container: + cmd += " --local %s " % image_ref + else: + cmd += " %s " % image_ref + + if chownership: + cmd += " --chown %s " % chownership + + if rootfs: + cmd += " --rootfs %s " % rootfs + + debug = dargs.get("debug", True) + + ignore_status = dargs.get("ignore_status", False) + timeout = int(dargs.get("timeout", "1800")) + LOG.debug("the whole podman command: %s\n" % cmd) + + ret = process.run( + cmd, timeout=timeout, verbose=debug, ignore_status=ignore_status, shell=True) + + return ret + + +def podman_login(podman_username, podman_password, registry): + """ + Use podman to login in registry + + :param podman_username: podman username + :param podman_password: podman password + :param registry: registry to login + :return: CmdResult object + """ + command = "sudo podman login -u='%s' -p='%s' %s " % (podman_username, podman_password, registry) + process.run( + command, timeout=60, verbose=True, ignore_status=False, shell=True) + + +def podman_login_with_auth(auth_file, registry): + """ + Use podman to login in registry with auth file + + :param auth_file: auth file + :param registry: registry to login + :return: CmdResult object + """ + command = "sudo podman login --authfile=%s %s " % (auth_file, registry) + process.run( + command, timeout=60, verbose=True, ignore_status=False, shell=True) + + +def podman_push(podman_username, podman_password, registry, container_url): + """ + Use podman image to registry + + :param podman_username: podman username + :param podman_password: podman password + :param registry: registry to login + :param container_url: image url + :return: CmdResult object + """ + podman_login(podman_username, podman_password, registry) + command = "sudo podman push %s " % container_url + process.run( + command, timeout=1200, verbose=True, ignore_status=False, shell=True) + + +def create_config_json_file(params): + """ + create json configuration file + + :param params: one dictionary to pass in configuration + """ + folder = params.get("config_file_path") + username = params.get("os_username") + password = params.get("os_password") + kickstart = "yes" == params.get("kickstart") + public_key_path = os.path.join(os.path.expanduser("~/.ssh/"), "id_rsa.pub") + if not os.path.exists(public_key_path): + LOG.debug("public key doesn't exist, will help create one") + key_gen_cmd = "ssh-keygen -q -t rsa -N '' <<< $'\ny' >/dev/null 2>&1" + process.run(key_gen_cmd, shell=True, ignore_status=False) + + with open(public_key_path, 'r') as ssh: + key_value = ssh.read().rstrip() + if not kickstart: + cfg = { + "blueprint": { + "customizations": { + "user": [ + { + "name": username, + "password": password, + "groups": ["wheel"], + "key": "%s" % key_value, + }, + ], + "kernel": {"append": "mitigations=auto,nosmt"}, + }, + }, + } + else: + cfg = { + "blueprint": { + "customizations": { + "kernel": {"append": "mitigations=auto,nosmt"}, + "installer": { + "modules": {"enable": [ + "org.fedoraproject.Anaconda.Modules.Localization", + # disable takes precedence + "org.fedoraproject.Anaconda.Modules.Timezone", + ], + "disable": [ + # disable takes precedence + "org.fedoraproject.Anaconda.Modules.Timezone", + ] + }, + "kickstart": {"contents": "user --name %s --password %s --groups wheel\n" + "sshkey --username %s \"%s\"\ntext --non-interactive\nzerombr\n" + "clearpart --all --initlabel --disklabel=gpt\nautopart --noswap --type=lvm\n" + "network --bootproto=dhcp --device=link --activate --onboot=on\n reboot" % (username, password, username, key_value) + } + } + } + } + } + + LOG.debug("what is cfg:%s", cfg) + config_json_path = pathlib.Path(folder) / "config.json" + config_json_path.write_text(json.dumps(cfg), encoding="utf-8") + return os.path.join(folder, "config.json") + + +def create_auth_json_file(params): + """ + create authentication json configuration file + + :param params: one dictionary to pass in configuration + """ + folder = params.get("config_file_path") + redhat_registry = params.get("redhat_registry") + registry_key = params.get("registry_key") + + cfg = { + "auths": { + "%s" % redhat_registry: { + "auth": "%s" % registry_key + } + } + } + + LOG.debug("what is auth cfg:%s", cfg) + config_json_path = pathlib.Path(folder) / "auth.json" + config_json_path.write_text(json.dumps(cfg), encoding="utf-8") + final_config_file = os.path.join(folder, "auth.json") + return final_config_file + + +def create_aws_secret_file(folder, aws_access_key_id, aws_access_key): + """ + Create aws secret key file + + :param folder: folder is used to have secret file + :param aws_access_key_id: aws access key id + :param aws_access_key: aws access key + """ + secret_path = pathlib.Path(folder) / "aws.secrets" + secret_path.write_text(textwrap.dedent(f""" + AWS_ACCESS_KEY_ID={aws_access_key_id} + AWS_SECRET_ACCESS_KEY={aws_access_key} + """), encoding="utf8") + + return os.path.join(folder, "aws.secrets") + + +def create_and_build_container_file(params): + """ + Create container file and build container tag + + :param params: one dictionary to wrap up all parameters + """ + folder = params.get("container_base_folder") + build_container = params.get("build_container") + container_tag = params.get("container_url") + + # clean up existed image + clean_image_cmd = "sudo podman rmi %s" % container_tag + process.run(clean_image_cmd, shell=True, ignore_status=True) + etc_config = '' + dnf_vmware_tool = '' + dnf_fips_install = '' + + # create VMware tool + if params.get("add_vmware_tool") == "yes": + vmware_tool_path = os.path.join(folder, "etc/vmware-tools/") + if not os.path.exists(vmware_tool_path): + os.makedirs(vmware_tool_path) + etc_config = "COPY etc/ /etc/" + dnf_vmware_tool = "dnf -y install open-vm-tools && dnf clean all && systemctl enable vmtoolsd.service && " + + download_vmware_config_cmd = "curl https://gitlab.com/fedora/bootc/" \ + "examples/-/raw/main/vmware/etc/vmware-tools/tools.conf > %s/tools.conf" % vmware_tool_path + process.run(download_vmware_config_cmd, shell=True, verbose=True, ignore_status=True) + + if params.get("fips_enable") == "yes": + dnf_fips_install = "RUN cat > /usr/lib/bootc/kargs.d/01-fips.toml <<'EOF'\n" \ + "kargs = ['fips=1']\n" \ + "match-architectures = ['x86_64']\n" \ + "EOF\n" \ + "RUN dnf install -y crypto-policies-scripts && " \ + "update-crypto-policies --no-reload --set FIPS " + + container_path = pathlib.Path(folder) / "Containerfile_tmp" + shutil.copy("/etc/yum.repos.d/beaker-BaseOS.repo", folder) + shutil.copy("/etc/yum.repos.d/beaker-AppStream.repo", folder) + + create_sudo_file = "RUN echo '%wheel ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/wheel-passwordless-sudo" + enable_root_ssh = "RUN echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config.d/01-permitrootlogin.conf" + + container_file_content = f"""\n + FROM {build_container} + {etc_config} + COPY beaker-BaseOS.repo /etc/yum.repos.d/ + COPY beaker-AppStream.repo /etc/yum.repos.d/ + {create_sudo_file} + {enable_root_ssh} + {dnf_fips_install} + RUN {dnf_vmware_tool} dnf install -y vim && dnf clean all + """ + + custom_repo = params.get("custom_repo") + if custom_repo: + repo_path = pathlib.Path(folder) / "rhel-9.4.repo" + repo_prefix = "rhel-9.4" + if "rhel-9.5" in custom_repo: + repo_path = pathlib.Path(folder) / "rhel-9.5.repo" + repo_prefix = "rhel-9.5" + if "rhel-10.0" in custom_repo: + repo_path = pathlib.Path(folder) / "rhel-10.0.repo" + repo_prefix = "rhel-10.0" + compose_url = params.get("compose_url") + baseurl = get_baseurl_from_repo_file("/etc/yum.repos.d/beaker-AppStream.repo") + if baseurl: + compose_url = baseurl + vm_arch_name = params.get("vm_arch_name", "x86_64") + repo_content = f"""\n + [{repo_prefix}-baseos] + name=beaker-BaseOS\n + baseurl={compose_url}/compose/BaseOS/{vm_arch_name}/os/ + enabled=1 + gpgcheck=0 + sslverify=0\n + [{repo_prefix}-appstream] + name=beaker-appstream\n + baseurl={compose_url}/compose/AppStream/{vm_arch_name}/os/ + enabled=1 + gpgcheck=0 + sslverify=0\n + """ + nfv_repo_content = f""" + [{repo_prefix}-nfv] + name=beaker-NFV\n + baseurl={compose_url}/compose/NFV/{vm_arch_name}/os/ + enabled=1 + gpgcheck=0 + sslverify=0\n + """ + crb_repo_content = f""" + [{repo_prefix}-crb] + name=beaker-CRB\n + baseurl={compose_url}/compose/CRB/{vm_arch_name}/os/ + enabled=1 + gpgcheck=0 + sslverify=0\n + """ + + if "x86_64" in vm_arch_name: + repo_content = repo_content + nfv_repo_content + crb_repo_content + repo_path.write_text(textwrap.dedent(repo_content), encoding="utf8") + container_file_content = f"""\n + FROM {build_container} + COPY {custom_repo} /etc/yum.repos.d/ + {create_sudo_file} + {enable_root_ssh} + {dnf_fips_install} + Run dnf clean all + """ + + container_path.write_text(textwrap.dedent(container_file_content), encoding="utf8") + build_cmd = "sudo podman build -t %s -f %s" % (container_tag, str(container_path)) + process.run(build_cmd, shell=True, ignore_status=False) + + +def create_and_start_vmware_vm(params): + """ + prepare environment, upload vmdk, create and start vm + + @param params: one dictionary wrapping various parameter + """ + image_type = params.get("disk_image_type") + try: + install_vmware_govc_tool(params) + setup_vCenter_env(params) + (params) + if image_type == "vmdk": + import_vmdk_to_vCenter(params) + elif image_type == "anaconda-iso": + import_iso_to_vCenter(params) + create_vm_in_vCenter(params) + if image_type == "vmdk": + attach_disk_to_vm(params) + elif image_type == "anaconda-iso": + attach_iso_to_vm(params) + create_vmdk_on_vm(params) + + power_on_vm(params) + add_vmware_tool = "yes" == params.get("add_vmware_tool") + if add_vmware_tool: + verify_ssh_login_vm(params) + finally: + delete_vm_if_present(params) + + +def create_and_start_cloud_vm(params): + """ + prepare environment, create and start VM in cloud + + @param params: one dictionary wrapping various parameter + """ + try: + aws_utils.create_aws_instance(params) + verify_ssh_login_vm(params) + finally: + cleanup_aws_env(params) + + +def install_vmware_govc_tool(params): + """ + Download VmWare govc tool and install it + + :param params: wrap up test parameters + """ + vm_arch_name = params.get("vm_arch_name", "x86_64") + if "arm64" in vm_arch_name: + vm_arch_name = "arm64" + govc_install_cmd = f"curl -L -o - 'https://github.com/vmware/govmomi/releases/latest/download/govc_Linux_{vm_arch_name}.tar.gz' " \ + f"| tar -C /usr/local/bin -xvzf - govc" + if not os.path.exists("/usr/local/bin/govc"): + process.run(govc_install_cmd, shell=True, ignore_status=False) + + +def setup_vCenter_env(params): + """ + Download VmWare govc tool and install it + + @param params: one dictionary wrapping various parameter + """ + # vCenter information + os.environ["GOVC_URL"] = params.get("GOVC_URL") + os.environ["GOVC_USERNAME"] = params.get("GOVC_USERNAME") + os.environ["GOVC_PASSWORD"] = params.get("GOVC_PASSWORD") + os.environ["DATA_CENTER"] = params.get("DATA_CENTER") + os.environ["GOVC_DATASTORE"] = "%s" % params.get("DATA_STORE") + os.environ["GOVC_INSECURE"] = "true" + process.run("govc about", shell=True, ignore_status=False) + + +def import_vmdk_to_vCenter(params): + """ + import vmdk into vCenter + + @param params: one dictionary wrapping various parameter + """ + delete_datastore_if_existed(params) + import_cmd = f"govc import.vmdk -force=true {params.get('vm_disk_image_path')}" + process.run(import_cmd, shell=True, verbose=True, ignore_status=False) + + +def create_vmdk_on_vm(params): + """ + create empty vmdk on VM + + @param params: one dictionary wrapping various parameters + """ + vm_name = params.get("vm_name_bootc") + create_vmdk_cmd = f"govc vm.disk.create -vm {vm_name} -name {vm_name}.vmdk 10G" + process.run(create_vmdk_cmd, shell=True, verbose=True, ignore_status=False) + + +def import_iso_to_vCenter(params): + """ + import iso into vCenter + + @param params: one dictionary wrapping various parameter + """ + boot = params.get("vm_name_bootc") + iso_location = params.get("vm_disk_image_path") + check_iso_cmd = f"govc datastore.ls {boot}" + if process.run(check_iso_cmd, shell=True, verbose=True, ignore_status=True).exit_status == 0: + delete_iso_cmd = f"govc datastore.rm -f {boot}" + process.run(delete_iso_cmd, shell=True, verbose=True, ignore_status=False) + + import_iso_cmd = f"govc datastore.upload {iso_location} {boot}" + process.run(import_iso_cmd, shell=True, verbose=True, ignore_status=False) + + +def create_vm_in_vCenter(params): + """ + create VM in vCenter + + @param params: one dictionary wrapping various parameter + """ + create_cmd = "govc vm.create -net='VM Network' -on=false -c=2 " \ + "-m=4096 -g=centos9_64Guest -firmware=%s %s" % (params.get("firmware"), params.get("vm_name_bootc")) + process.run(create_cmd, shell=True, verbose=True, ignore_status=False) + + +def attach_disk_to_vm(params): + """ + attach disk to VM in vCenter + + @param params: one dictionary wrapping various parameter + """ + vm_name = params.get("vm_name_bootc") + attach_cmd = "govc vm.disk.attach -vm %s" \ + " -controller %s -link=false -disk=%s/%s.vmdk" % (vm_name, params.get("controller"), vm_name, vm_name) + process.run(attach_cmd, shell=True, verbose=True, ignore_status=False) + + +def attach_iso_to_vm(params): + """ + attach ISO to VM in vCenter + + @param params: one dictionary wrapping various parameter + """ + vm_name = params.get("vm_name_bootc") + add_cdrom_cmd = f"govc device.cdrom.add -vm {vm_name}" + id = process.run(add_cdrom_cmd, shell=True, verbose=True, ignore_status=False).stdout_text.strip() + + #insert ISO into CDROM + attach_cmd = f"govc device.cdrom.insert -vm {vm_name} -device {id} {vm_name}" + process.run(attach_cmd, shell=True, verbose=True, ignore_status=False) + + +def power_on_vm(params): + """ + power on VM in vCenter + + @param params: one dictionary wrapping various parameter + """ + vm_name = params.get("vm_name_bootc") + wait_boot_time = int(params.get("wait_boot_time", "40")) + power_on_cmd = "govc vm.power -on=true %s" % vm_name + process.run(power_on_cmd, shell=True, verbose=True, ignore_status=False) + time.sleep(wait_boot_time) + state_cmd = "govc vm.info -json %s |jq -r .virtualMachines[0].summary.runtime.powerState" % vm_name + result = process.run(state_cmd, shell=True, verbose=True, ignore_status=False).stdout_text.strip() + if result not in "poweredOn": + raise exceptions.TestFail(f"The VM state is not powered on, real state is: {result}") + + +def verify_ssh_login_vm(params): + """ + Verify ssh login VM successfully + + @param params: one dictionary wrapping various parameter + """ + ip_address = params.get("ip_address") + disk_image_type = params.get("disk_image_type") + aws_config_dict = eval(params.get("aws_config_dict", '{}')) + if ip_address is None: + if disk_image_type in ['ami'] and len(aws_config_dict) != 0: + ip_address = aws_utils.get_aws_instance_privateip(params) + else: + ip_address = get_vm_ip_address(params) + user = params.get("os_username") + passwd = params.get("os_password") + vm_params = {} + vm_params.update({"server_ip": ip_address}) + vm_params.update({"server_user": user}) + vm_params.update({"server_pwd": passwd}) + vm_params.update({"vm_ip": ip_address}) + vm_params.update({"vm_user": user}) + vm_params.update({"vm_pwd": passwd}) + remote_vm_obj = remote.VMManager(vm_params) + remote_vm_obj.check_network() + remote_vm_obj.setup_ssh_auth() + result = remote_vm_obj.cmd_status_output("whoami")[1].strip() + LOG.debug(f" remote VM test is: {result} ") + if result not in user: + raise exceptions.TestFail(f"The expected user name should be: {user}, but actually is: {result}") + return remote_vm_obj + + +def get_vm_ip_address(params): + """ + Get VM ip_address in vCenter + + @param params: one dictionary wrapping various parameter + """ + vm_name = params.get("vm_name_bootc") + get_ip_cmd = "govc vm.ip -v4 -wait=3m %s" % vm_name + result = process.run(get_ip_cmd, shell=True, verbose=True, ignore_status=False) + LOG.debug("result wcf: {result.stdout_text}") + if result.stdout_text.strip() == "" or result.stdout_text.strip() is None: + raise exceptions.TestFail(f"Can not get ip address") + return result.stdout_text.strip() + + +def delete_vm_if_present(params): + """ + delete vm if present + + @param params: one dictionary wrapping various parameter + """ + vm_name = params.get("vm_name_bootc") + find_cmd = "govc find / -type m -name %s" % vm_name + cmd_result = process.run(find_cmd, shell=True, verbose=True, ignore_status=True).stdout_text + LOG.debug(f"find vm in vsphere is:{cmd_result}") + if cmd_result: + vm_path = cmd_result.strip() + delete_cmd = "govc vm.destroy %s && govc datastore.rm -f %s" % (vm_name, vm_name) + process.run(delete_cmd, shell=True, verbose=True, ignore_status=True) + + +def delete_datastore_if_existed(params): + """ + delete data store if existed + + @param params: one dictionary wrapping various parameter + """ + vm_name = params.get("vm_name_bootc") + find_cmd = "govc datastore.ls %s" % vm_name + cmd_result = process.run(find_cmd, shell=True, verbose=True, ignore_status=True).stdout_text + if cmd_result: + delete_cmd = "govc datastore.rm -f %s" % vm_name + process.run(delete_cmd, shell=True, verbose=True, ignore_status=True) + + +def parse_container_url(params): + """ + Parse repository information from container url + + @param params: wrapped dictionary containing url + """ + container_url = params.get("container_url") + repository_info = container_url.split('/')[-1] + repository_name = repository_info.split(':')[0] + if "localhost" in container_url: + repository_name = "localhost-%s" % repository_name + return repository_name + + +def convert_disk_image_name(params): + """ + Convert disk type image name + + @param params: wrapped dictionary containing parameters + """ + repository_name = parse_container_url(params) + origin_disk_name, extension = os.path.splitext(params.get("output_name")) + dest_disk_name = "%s-%s%s" % (origin_disk_name, repository_name, extension) + return dest_disk_name + + +def set_root_passwd(remote_vm_obj, params): + """ + Use passwd to change root password + + @param remote_vm_obj: remote vm object + @param params: one dictionary containing parameters + """ + disk_image_type = params.get("disk_image_type") + root_passwd = params.get("root_passwd", "redhat") + fips_enable = params.get("fips_enable") == "yes" + if fips_enable: + change_passwd = remote_vm_obj.cmd_status_output("echo root:%s|sudo chpasswd" % root_passwd)[1].strip() + LOG.debug(f"change remote VM root password is: {change_passwd} ") + remote_vm_obj = None + + +def virt_install_vm(params): + """ + Use virt install tool to install vm + + @param params: one dictionary containing parameters + """ + vm_name = params.get("vm_name_bootc") + disk_image_type = params.get("disk_image_type") + image_ref = params.get("image_ref") + disk_path = params.get("vm_disk_image_path") + iso_install_path = params.get("iso_install_path") + format = params.get("disk_image_type") + firmware = params.get("firmware") + ovmf_code_path = params.get("ovmf_code_path") + ovmf_vars_path = params.get("ovmf_vars_path") + boot_option = '' + vm_arch_name = params.get("vm_arch_name", "x86_64") + machine_type = " --machine q35 " + secure_boot_feature0_enable = "yes" + if "aarch64" in vm_arch_name: + machine_type = "" + secure_boot_feature0_enable = "no" + if firmware in ['efi']: + if image_ref in ["centos", "fedora"]: + boot_option = f"--boot uefi,firmware.feature0.name=secure-boot,firmware.feature0.enabled={secure_boot_feature0_enable}," \ + f"firmware.feature1.name=enrolled-keys,firmware.feature1.enabled=no" + else: + boot_option = " --boot uefi" + if disk_image_type in ["anaconda-iso"]: + if os.path.exists(iso_install_path): + os.remove(iso_install_path) + cmd = ("virt-install --name %s" + " --disk path=%s,bus=virtio,format=qcow2,size=12" + " --vcpus 3 --memory 3096" + " --osinfo detect=on,require=off" + " --graphics vnc" + " --video virtio" + " --serial pty" + " --wait 10" + " --cdrom %s" + " --debug" + " %s " + " %s " + " --noreboot" % + (vm_name, iso_install_path, disk_path, machine_type, boot_option)) + else: + cmd = ("virt-install --name %s" + " --disk path=%s,bus=virtio,format=%s" + " --import " + " --vcpus 3 --memory 3096" + " --osinfo detect=on,require=off" + " --graphics vnc --video virtio --noautoconsole --serial pty" + " --wait 10" + " --debug" + " %s " + " %s " + " --noreboot" % + (vm_name, disk_path, format, machine_type, boot_option)) + process.run(cmd, shell=True, verbose=True, ignore_status=True) + + +def verify_in_vm_internal(vm, params): + """ + Verify something by login Vm + + @param vm: vm object + @param params: one dictionary wrapping various parameter + """ + root_user = "root" + root_passwd = params.get("root_passwd", "redhat") + fips_enable = params.get("fips_enable") == "yes" + disk_image_type = params.get("disk_image_type") + vm_arch_name = params.get("vm_arch_name", "x86_64") + if fips_enable and "x86_64" in vm_arch_name and disk_image_type not in ["anaconda-iso"]: + vm_session = vm.wait_for_login(username=root_user, password=root_passwd) + cmd = "fips-mode-setup --check" + res = vm_session.cmd_output(cmd) + vm_session.close() + LOG.debug('Session outputs:\n%s', res) + if "FIPS mode is enabled" not in res: + raise exceptions.TestFail(f"FIPS mode is not enabled") + + +def create_qemu_vm(params, env, test): + """ + prepare environment, virt install, and login vm + + @param params: one dictionary wrapping various parameters + @param env: environment + @param test: test case itself + """ + try: + virt_install_vm(params) + vm_name = params.get("vm_name_bootc") + env.create_vm(vm_type='libvirt', target=None, name=vm_name, params=params, bindir=test.bindir) + vm = env.get_vm(vm_name) + if vm.is_dead(): + LOG.debug("VM is dead, starting") + vm.start() + ip_address = vm.wait_for_get_address(nic_index=0) + params.update({"ip_address": ip_address.strip()}) + remote_vm_obj = verify_ssh_login_vm(params) + LOG.debug(f"ip addressis wcf: {ip_address}") + set_root_passwd(remote_vm_obj, params) + verify_in_vm_internal(vm, params) + finally: + if vm and vm.is_alive(): + vm.destroy(gracefully=False) + vm.undefine(options='--nvram') + + +def get_group_and_user_ids(folder_path): + try: + stat_info = os.stat(folder_path) + gid = stat_info.st_gid + uid = stat_info.st_uid + return gid, uid + except FileNotFoundError: + LOG.debug(f"Folder '{folder_path}' not found.") + return None, None + except Exception as ex: + LOG.debug(f"Error occurred: {ex}") + return None, None + + +def prepare_aws_env(params): + """ + One method to prepare AWS environment for image build + + :param params: one collective object representing wrapped parameters + """ + aws_access_key_id = params.get("aws_access_key_id") + aws_access_key = params.get("aws_access_key") + aws_secret_folder = params.get("aws_secret_folder") + aws_region = params.get("aws_region") + create_aws_secret_file(aws_secret_folder, aws_access_key_id, aws_access_key) + aws_utils.create_aws_credentials_file(aws_access_key_id, aws_access_key) + aws_utils.create_aws_config_file(aws_region) + aws_utils.install_aws_cli_tool(params) + + +def cleanup_aws_env(params): + """ + One method to clean up AWS environment for image build + + :param params: one collective object representing wrapped parameters + """ + aws_utils.terminate_aws_instance(params) + aws_utils.delete_aws_ami_id(params) + aws_utils.delete_aws_ami_snapshot_id(params) + + +def cleanup_aws_ami_and_snapshot(params): + """ + One method to clean up AWS ami and snapshot for image build + + :param params: one collective object representing wrapped parameters + """ + aws_utils.delete_aws_ami_id(params) + aws_utils.delete_aws_ami_snapshot_id(params) + + +def get_baseurl_from_repo_file(repo_file_path): + """ + One method to get compose url from current repository file + + :param repo_file_path: file path to repository + """ + try: + with open(repo_file_path, 'r') as f: + for line in f: + line = line.strip() + if line.startswith("baseurl"): + baseurl = line.split("=")[1].strip() + return baseurl.split('/compose/')[0].strip() + return None + except FileNotFoundError: + return None diff --git a/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_build.cfg b/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_build.cfg new file mode 100644 index 00000000000..5bd0b929cd1 --- /dev/null +++ b/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_build.cfg @@ -0,0 +1,160 @@ +- bootc_image_builder.bib.disk_image_generation: + type = bootc_disk_image_build + only x86_64, aarch64 + start_vm = False + take_regular_screendumps = "no" + start_vm = "no" + output_base_folder = "/var/lib/libvirt/images/output" + # vCenter information + GOVC_URL = "example_url" + GOVC_USERNAME = "username" + GOVC_PASSWORD = "userpassword" + DATA_CENTER = "example_datacenter" + DATA_STORE = "example_datastore" + bib_image_url = "quay.io/centos-bootc/bootc-image-builder:latest" + registry = "quay.io" + config_file_path = "/var/lib/libvirt/images" + variants: + - tls_verify_enable: + enable_tls_verify="true" + - tls_verify_disable: + enable_tls_verify="false" + variants config_json: + - use_config_json: + os_username = "alice" + os_password = "bob" + anaconda-iso..upstream_bib..fedora_40: + kickstart = "yes" + anaconda-iso..rhel_9.5_nightly_bib..local_image: + kickstart = "yes" + - unuse_config_json: + variants image_ref: + - centos: + variants centos_bootc_image: + - centos9: + container_url = "quay.io/centos-bootc/centos-bootc:stream9" + only use_config_json..tls_verify_disable + - centos10: + container_url = "quay.io/centos-bootc/centos-bootc:stream10" + only upstream_bib..use_config_json..tls_verify_enable, rhel_9.5_nightly_bib..use_config_json..tls_verify_enable, rhel_9.4_nightly_bib..use_config_json..tls_verify_enable + roofs = "xfs" + rhel_9.4_nightly_bib..use_config_json..tls_verify_enable: + roofs = "" + - fedora: + variants fedora_bootc_image: + - fedora_40: + only upstream_bib..tls_verify_enable + ownership ="107:107" + container_url = "quay.io/fedora/fedora-bootc:40" + roofs = "ext4" + qcow..upstream_bib: + roofs = "xfs" + - fedora_latest: + only upstream_bib..tls_verify_disable + container_url = "quay.io/fedora/fedora-bootc:latest" + roofs = "xfs" + raw..upstream_bib: + roofs = "ext4" + - local_image: + container_base_folder = "/var/lib/libvirt/images" + container_url = "localhost/bootc:eln" + local_container = "yes" + build_container = "registry.stage.redhat.io/rhel9/rhel-bootc:rhel-9.4" + rhel_9.5_nightly_bib: + build_container = "registry.stage.redhat.io/rhel9/rhel-bootc:rhel-9.5" + rhel_10.0_bib: + build_container = "registry.stage.redhat.io/rhel10-beta/rhel-bootc:rhel-10.0-beta" + - rhel_9.4: + build_container = "registry.redhat.io/rhel9/rhel-bootc:9.4" + container_url = "quay.io/wenbaoxin/rhel9test" + only rhel_9.4_bib + - rhel_9.5_nightly: + container_url = "registry.stage.redhat.io/rhel9/rhel-bootc:rhel-9.5" + only rhel_9.5_nightly_bib + no anaconda-iso + - rhel_10.0_nightly: + container_url = "registry.stage.redhat.io/rhel10-beta/rhel-bootc:rhel-10.0-beta" + enable_tls_verify = "false" + only rhel_10.0_bib + no anaconda-iso + - cross_build: + container_url = "quay.io/centos-bootc/centos-bootc:stream9" + target_arch = "aarch64" + only qcow..upstream_bib..use_config_json..tls_verify_enable + variants bib_ref: + - upstream_bib: + registry_key = "example_stage_key" + redhat_registry = "registry.stage.redhat.io" + bib_image_url = "quay.io/centos-bootc/bootc-image-builder:latest" + podman_stage_username = "11009103|stage" + podman_stage_password = "example_stage_password" + - rhel_9.4_bib: + podman_redhat_username = "podman_redhat_username" + podman_redhat_password = "podman_redhat_password" + redhat_registry = "registry.redhat.io" + container_base_folder = "/var/lib/libvirt/images" + bib_image_url = "registry.redhat.io/rhel9/bootc-image-builder:9.4" + podman_quay_username = "podman_quay_username" + podman_quay_password = "podman_quay_password" + only rhel_9.4..use_config_json..tls_verify_enable + anaconda-iso..rhel_9.4: + custom_repo = "rhel-9.4.repo" + - rhel_9.4_nightly_bib: + registry_key = "example_stage_key" + redhat_registry = "registry.stage.redhat.io" + bib_image_url = "registry.stage.redhat.io/rhel9/bootc-image-builder:rhel-9.4" + key_store_mounted = "/etc/pki:/etc/pki" + podman_stage_username = "11009103|stage" + podman_stage_password = "example_stage_password" + anaconda-iso..local_image: + custom_repo = "rhel-9.4.repo" + compose_url = "example_compose_url" + no cross_build + - rhel_9.5_nightly_bib: + registry_key = "example_stage_key" + redhat_registry = "registry.stage.redhat.io" + bib_image_url = "registry.stage.redhat.io/rhel9/bootc-image-builder:rhel-9.5" + key_store_mounted = "/etc/pki:/etc/pki" + podman_stage_username = "11009103|stage" + podman_stage_password = "example_stage_password" + anaconda-iso..local_image: + custom_repo = "rhel-9.5.repo" + compose_url = "example_compose_url" + - rhel_10.0_bib: + registry_key = "example_stage_key" + redhat_registry = "registry.stage.redhat.io" + bib_image_url = "registry.stage.redhat.io/rhel10-beta/bootc-image-builder:rhel-10.0-beta" + key_store_mounted = "/etc/pki:/etc/pki" + podman_stage_username = "11009103|stage" + podman_stage_password = "example_stage_password" + anaconda-iso..local_image: + custom_repo = "rhel-10.0.repo" + compose_url = "https://download.eng.bos.redhat.com/rhel-10/nightly/RHEL-10-Public-Beta/RHEL-10.0-20240522.76" + variants: + - ami: + disk_image_type = "ami" + output_sub_folder = "image" + output_name = "disk.raw" + aws_secret_folder = "/var/lib/libvirt/images" + aws_access_key_id = "example_aws_access_key_id" + aws_access_key = "example_aws_access_key" + aws_region = "us-east-1" + aws_ami_name = "build_${bib_ref}-${image_ref}-component-bootc-${disk_image_type}" + use_config_json..tls_verify_enable: + aws_config_dict = "{'aws.secrets':'${aws_secret_folder}/aws.secrets','aws_ami_name':'${aws_ami_name}','aws_bucket':'bib-component-test','aws_region':'${aws_region}'}" + - qcow: + disk_image_type = "qcow2" + output_sub_folder = "qcow2" + output_name = "disk.qcow2" + - vmdk: + disk_image_type = "vmdk" + output_sub_folder = "vmdk" + output_name = "disk.vmdk" + - anaconda-iso: + disk_image_type = "anaconda-iso" + output_sub_folder = "bootiso" + output_name = "install.iso" + - raw: + disk_image_type = "raw" + output_sub_folder = "image" + output_name = "disk.raw" diff --git a/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_install.cfg b/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_install.cfg new file mode 100644 index 00000000000..800f6f1fad8 --- /dev/null +++ b/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_install.cfg @@ -0,0 +1,170 @@ +- bootc_image_builder.bib.disk_image_install: + type = bootc_disk_image_install + only x86_64, aarch64 + start_vm = False + take_regular_screendumps = "no" + start_vm = "no" + output_base_folder = "/var/lib/libvirt/images/output" + libvirt_base_folder = "/var/lib/libvirt/images" + # vCenter information + GOVC_URL = "example_url" + GOVC_USERNAME = "username" + GOVC_PASSWORD = "userpassword" + DATA_CENTER = "example_datacenter" + DATA_STORE = "example_datastore" + bib_image_url = "quay.io/centos-bootc/bootc-image-builder:latest" + registry = "quay.io" + ownership ="107:107" + config_file_path = "/var/lib/libvirt/images" + os_username = "alice" + os_password = "bob" + variants: + - efi: + controller = "scsi" + firmware = "efi" + aws_instance_type = "t3.medium" + aarch64: + aws_instance_type = "c7g.medium" + - bios: + controller = "ide" + firmware = "bios" + aws_instance_type = "m4.large" + aarch64: + aws_instance_type = "m6g.medium" + variants image_ref: + - centos: + variants centos_bootc_image: + - centos9: + container_url = "quay.io/centos-bootc/centos-bootc:stream9" + - centos10: + container_url = "quay.io/centos-bootc/centos-bootc:stream10" + only upstream_bib, rhel_9.5_nightly_bib, rhel_9.4_nightly_bib + roofs = "ext4" + rhel_9.4_nightly_bib: + roofs = "" + - fedora: + variants fedora_bootc_image: + - fedora_40: + only upstream_bib + container_url = "quay.io/fedora/fedora-bootc:40" + roofs = "ext4" + qcow..upstream_bib: + roofs = "xfs" + anaconda-iso..upstream_bib: + kickstart = "yes" + - fedora_latest: + only upstream_bib + container_url = "quay.io/fedora/fedora-bootc:latest" + roofs = "xfs" + raw..upstream_bib: + roofs = "ext4" + - rhel_9.4: + build_container = "registry.redhat.io/rhel9/rhel-bootc:9.4" + container_url = "quay.io/wenbaoxin/rhel9test" + only rhel_9.4_bib + - local_image: + container_base_folder = "/var/lib/libvirt/images" + container_url = "localhost/bootc:eln" + local_container = "yes" + build_container = "registry.stage.redhat.io/rhel9/rhel-bootc:rhel-9.4" + rhel_9.5_nightly_bib: + build_container = "registry.stage.redhat.io/rhel9/rhel-bootc:rhel-9.5" + fips_enable = "yes" + rhel_10.0_bib: + build_container = "registry.stage.redhat.io/rhel10-beta/rhel-bootc:rhel-10.0-beta" + - rhel_9.5_nightly: + container_url = "registry.stage.redhat.io/rhel9/rhel-bootc:rhel-9.5" + enable_tls_verify = "false" + only rhel_9.5_nightly_bib + no anaconda-iso + - rhel_10.0_nightly: + container_url = "registry.stage.redhat.io/rhel10-beta/rhel-bootc:rhel-10.0-beta" + enable_tls_verify = "false" + only rhel_10.0_bib + no anaconda-iso + variants bib_ref: + - upstream_bib: + registry_key = "example_stage_key" + redhat_registry = "registry.stage.redhat.io" + bib_image_url = "quay.io/centos-bootc/bootc-image-builder:latest" + podman_stage_username = "11009103|stage" + podman_stage_password = "example_stage_password" + - rhel_9.4_bib: + podman_redhat_username = "podman_redhat_username" + podman_redhat_password = "podman_redhat_password" + redhat_registry = "registry.redhat.io" + container_base_folder = "/var/lib/libvirt/images" + bib_image_url = "registry.redhat.io/rhel9/bootc-image-builder:9.4" + podman_quay_username = "podman_quay_username" + podman_quay_password = "podman_quay_password" + anaconda-iso..rhel_9.4: + custom_repo = "rhel-9.4.repo" + only rhel_9.4 + - rhel_9.4_nightly_bib: + registry_key = "example_stage_key" + redhat_registry = "registry.stage.redhat.io" + bib_image_url = "registry.stage.redhat.io/rhel9/bootc-image-builder:rhel-9.4" + key_store_mounted = "/etc/pki:/etc/pki" + podman_stage_username = "11009103|stage" + podman_stage_password = "example_stage_password" + anaconda-iso..local_image: + custom_repo = "rhel-9.4.repo" + compose_url = "example_compose_url" + - rhel_9.5_nightly_bib: + registry_key = "example_stage_key" + redhat_registry = "registry.stage.redhat.io" + bib_image_url = "registry.stage.redhat.io/rhel9/bootc-image-builder:rhel-9.5" + key_store_mounted = "/etc/pki:/etc/pki" + podman_stage_username = "11009103|stage" + podman_stage_password = "example_stage_password" + anaconda-iso..local_image: + custom_repo = "rhel-9.5.repo" + compose_url = "example_compose_url" + - rhel_10.0_bib: + registry_key = "example_stage_key" + redhat_registry = "registry.stage.redhat.io" + bib_image_url = "registry.stage.redhat.io/rhel10-beta/bootc-image-builder:rhel-10.0-beta" + key_store_mounted = "/etc/pki:/etc/pki" + podman_stage_username = "11009103|stage" + podman_stage_password = "example_stage_password" + anaconda-iso..local_image: + custom_repo = "rhel-10.0.repo" + compose_url = "https://download.eng.bos.redhat.com/rhel-10/nightly/RHEL-10-Public-Beta/RHEL-10.0-20240522.76" + variants: + - ami: + disk_image_type = "ami" + output_sub_folder = "image" + output_name = "disk.raw" + aws_secret_folder = "/var/lib/libvirt/images" + aws_access_key_id = "example_aws_access_key_id" + aws_access_key = "example_aws_access_key" + aws_region = "us-east-1" + aws_ami_name = "install_${bib_ref}-${image_ref}-component-bootc-${disk_image_type}" + aws_key_name = "component-bootc-key" + aws_security_group = "example_sg" + aws_vpc_id = "example_vpc" + aws_subnet_id = "example_subnet" + aws_config_dict = "{'aws.secrets':'${aws_secret_folder}/aws.secrets','aws_ami_name':'${aws_ami_name}','aws_bucket':'bib-component-test','aws_region':'${aws_region}'}" + rhel_9.5_nightly_bib..centos.centos9, rhel_9.5_nightly_bib..fedora_eln, rhel_9.5_nightly_bib..local_image: + aws_config_dict = {} + - qcow: + disk_image_type = "qcow2" + output_sub_folder = "qcow2" + output_name = "disk.qcow2" + - vmdk: + disk_image_type = "vmdk" + output_sub_folder = "vmdk" + output_name = "disk.vmdk" + local_image: + add_vmware_tool = "yes" + rhel_9.4: + add_vmware_tool = "yes" + - anaconda-iso: + wait_boot_time = 240 + disk_image_type = "anaconda-iso" + output_sub_folder = "bootiso" + output_name = "install.iso" + - raw: + disk_image_type = "raw" + output_sub_folder = "image" + output_name = "disk.raw" diff --git a/virttools/tests/src/bootc_image_builder/bootc_disk_image_build.py b/virttools/tests/src/bootc_image_builder/bootc_disk_image_build.py new file mode 100644 index 00000000000..7fe6ebe5c3e --- /dev/null +++ b/virttools/tests/src/bootc_image_builder/bootc_disk_image_build.py @@ -0,0 +1,130 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Chunfu Wen +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +import logging +import re +import os + +from avocado.utils import distro +from provider.bootc_image_builder import bootc_image_build_utils as bib_utils + +LOG = logging.getLogger('avocado.' + __name__) +cleanup_files = [] + + +def validate_bib_output(params, test): + """ + Common method to check whether image build output exists + + :param params: class params representing the test parameters + :param test: test object + """ + base_folder = params.get("output_base_folder") + output_sub_folder = params.get("output_sub_folder") + output_name = params.get("output_name") + ownership = params.get("ownership") + full_path = os.path.join(base_folder, output_sub_folder, output_name) + if not os.path.exists(full_path): + test.fail("bootc image build fail to generate outputs for image type: %s" % params.get("disk_image_type")) + if ownership: + formatted_group_user = ':'.join([f"{item}" for item in bib_utils.get_group_and_user_ids(base_folder)]) + if formatted_group_user != ownership: + test.fail(f"The output folder:{base_folder} has wrong setting in group and user ids: {formatted_group_user}") + + +def prepare_env_and_execute_bib(params, test): + """ + One method to prepare environment for image build + + :param params: class params representing the test parameters + :param test: test object + """ + disk_image_type = params.get("disk_image_type") + bib_image_url = params.get("bib_image_url", "quay.io/centos-bootc/bootc-image-builder:latest") + image_ref = params.get("image_ref") + bib_ref = params.get("bib_ref") + container_url = params.get("container_url") + local_container = "yes" == params.get("local_container") + build_container = params.get("build_container") + + enable_tls_verify = params.get("enable_tls_verify") + config_json = params.get("config_json") + config_json_file = None + + ownership = params.get("ownership") + key_store_mounted = params.get("key_store_mounted") + target_arch = params.get("target_arch") + roofs = params.get("roofs") + + aws_config_dict = eval(params.get("aws_config_dict", '{}')) + options = None + + if image_ref in ['cross_build'] and distro.detect().name in ['rhel']: + test.cancel("rhel doesn't support cross build, it is supported on fedora only") + + bib_utils.install_bib_packages() + if config_json == "use_config_json": + config_json_file = bib_utils.create_config_json_file(params) + if disk_image_type in ["ami"]: + bib_utils.prepare_aws_env(params) + + if bib_ref in ["upstream_bib", "rhel_9.4_nightly_bib", "rhel_9.5_nightly_bib", "rhel_10.0_bib"]: + auth_file = bib_utils.create_auth_json_file(params) + bib_utils.podman_login_with_auth(auth_file, params.get("redhat_registry")) + options = auth_file + bib_utils.podman_login(params.get("podman_stage_username"), params.get("podman_stage_password"), + params.get("redhat_registry")) + + # pull base image and build local image after change + if build_container: + if bib_ref == "rhel_9.4_bib": + bib_utils.podman_login(params.get("podman_redhat_username"), params.get("podman_redhat_password"), + params.get("redhat_registry")) + bib_utils.create_and_build_container_file(params) + if bib_ref == "rhel_9.4_bib": + bib_utils.podman_push(params.get("podman_quay_username"), params.get("podman_quay_password"), + params.get("registry"), container_url) + + result = bib_utils.podman_command_build(bib_image_url, disk_image_type, container_url, config_json_file, + local_container, enable_tls_verify, ownership, + key_store_mounted, target_arch, roofs, options, **aws_config_dict) + if disk_image_type in ['ami'] and len(aws_config_dict) != 0: + match_ami_id_obj = re.search(r'AMI registered:\s(.*)', result.stdout_text) + if match_ami_id_obj is None: + test.fail("Failed to get AWS AMI id") + aws_ami_id = match_ami_id_obj.group(1).strip() + LOG.debug(f"aws_ami_id is: {aws_ami_id}") + params.update({"aws_ami_id": aws_ami_id}) + match_aws_ami_snapshot_id_obj = re.search(r'Snapshot ID:\s(.*)', result.stdout_text) + if match_aws_ami_snapshot_id_obj is None: + test.fail("Failed to get AWS AMI snapshot id") + aws_ami_snapshot_id = match_aws_ami_snapshot_id_obj.group(1).strip() + LOG.debug(f"aws_ami_snapshot_id is: {aws_ami_snapshot_id}") + params.update({"aws_ami_snapshot_id": aws_ami_snapshot_id}) + bib_utils.cleanup_aws_ami_and_snapshot(params) + + +def run(test, params, env): + """ + Test boot container image builder. + Add existing BOOTABLE image to PODMAN (cover RHEL, FEDORA) + Build image from BOOTABLE image with PODMAAN (AWS, QCOW2,RAW, ISO). + Validate PODMAN build image command output. + """ + try: + prepare_env_and_execute_bib(params, test) + # validate build output + validate_bib_output(params, test) + except Exception as ex: + raise ex + finally: + # Clean up files + for file_path in cleanup_files: + if os.path.exists(file_path): + os.remove(file_path) diff --git a/virttools/tests/src/bootc_image_builder/bootc_disk_image_install.py b/virttools/tests/src/bootc_image_builder/bootc_disk_image_install.py new file mode 100644 index 00000000000..419555403ac --- /dev/null +++ b/virttools/tests/src/bootc_image_builder/bootc_disk_image_install.py @@ -0,0 +1,147 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Chunfu Wen +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import logging +import re +import os +import shutil + +from virttest import virsh +from provider.bootc_image_builder import bootc_image_build_utils as bib_utils + +LOG = logging.getLogger('avocado.' + __name__) +cleanup_files = [] + + +def update_bib_env_info(params, test): + """ + Common method to update environment when image build output exists + + :param params: class params representing the test parameters + :param test: test object + """ + base_folder = params.get("output_base_folder") + libvirt_base_folder = params.get("libvirt_base_folder") + output_sub_folder = params.get("output_sub_folder") + output_name = params.get("output_name") + bib_ref = params.get("bib_ref") + firmware = params.get("firmware") + + full_path = os.path.join(base_folder, output_sub_folder, output_name) + if not os.path.exists(full_path): + test.fail("bootc image build fail to generate outputs for image type: %s" % params.get("disk_image_type")) + converted_disk_image = f"install_{bib_ref}_{firmware}_{bib_utils.convert_disk_image_name(params)}" + disk_name, _ = os.path.splitext(converted_disk_image) + full_path_dest = os.path.join(libvirt_base_folder, converted_disk_image) + shutil.move(full_path, full_path_dest) + LOG.debug("vm_disk_image_path: %s", full_path_dest) + LOG.debug("vm_name_bootc: %s", disk_name) + cleanup_files.append(full_path_dest) + params.update({'vm_disk_image_path': full_path_dest}) + params.update({'vm_name_bootc': disk_name}) + + iso_install_path = os.path.join(libvirt_base_folder, f"{disk_name}_{firmware}.qcow2") + params.update({'iso_install_path': iso_install_path}) + cleanup_files.append(iso_install_path) + + +def prepare_env_and_execute_bib(params, test): + """ + One method to prepare environment for image build + + :param params: class params representing the test parameters + :param test: test object + """ + disk_image_type = params.get("disk_image_type") + bib_image_url = params.get("bib_image_url", "quay.io/centos-bootc/bootc-image-builder:latest") + image_ref = params.get("image_ref") + bib_ref = params.get("bib_ref") + container_url = params.get("container_url") + local_container = "yes" == params.get("local_container") + build_container = params.get("build_container") + + enable_tls_verify = params.get("enable_tls_verify", "true") + ownership = params.get("ownership") + key_store_mounted = params.get("key_store_mounted") + roofs = params.get("roofs") + aws_config_dict = eval(params.get("aws_config_dict", '{}')) + options = None + + bib_utils.install_bib_packages() + config_json_file = bib_utils.create_config_json_file(params) + if disk_image_type in ["ami"]: + bib_utils.prepare_aws_env(params) + + if bib_ref in ["upstream_bib", "rhel_9.4_nightly_bib", "rhel_9.5_nightly_bib", "rhel_10.0_bib"]: + auth_file = bib_utils.create_auth_json_file(params) + bib_utils.podman_login_with_auth(auth_file, params.get("redhat_registry")) + options = auth_file + bib_utils.podman_login(params.get("podman_stage_username"), params.get("podman_stage_password"), + params.get("redhat_registry")) + + # pull base image and build local image after change + if build_container: + if bib_ref == "rhel_9.4_bib": + bib_utils.podman_login(params.get("podman_redhat_username"), params.get("podman_redhat_password"), + params.get("redhat_registry")) + bib_utils.create_and_build_container_file(params) + if bib_ref == "rhel_9.4_bib": + ownership = None + bib_utils.podman_push(params.get("podman_quay_username"), params.get("podman_quay_password"), + params.get("registry"), container_url) + + result = bib_utils.podman_command_build(bib_image_url, disk_image_type, container_url, config_json_file, + local_container, enable_tls_verify, ownership, + key_store_mounted, None, roofs, options, **aws_config_dict) + if disk_image_type in ['ami'] and len(aws_config_dict) != 0: + match_ami_id_obj = re.search(r'AMI registered:\s(.*)', result.stdout_text) + if match_ami_id_obj is None: + test.fail("Failed to get AWS AMI id") + aws_ami_id = match_ami_id_obj.group(1).strip() + LOG.debug(f"aws_ami_id is: {aws_ami_id}") + params.update({"aws_ami_id": aws_ami_id}) + match_aws_ami_snapshot_id_obj = re.search(r'Snapshot ID:\s(.*)', result.stdout_text) + if match_aws_ami_snapshot_id_obj is None: + test.fail("Failed to get AWS AMI snapshot id") + aws_ami_snapshot_id = match_aws_ami_snapshot_id_obj.group(1).strip() + LOG.debug(f"aws_ami_snapshot_id is: {aws_ami_snapshot_id}") + params.update({"aws_ami_snapshot_id": aws_ami_snapshot_id}) + + +def run(test, params, env): + """ + Test install disk image generated by boot container image builder. + Add existing BOOTABLE image to PODMAN (cover RHEL, FEDORA) + Build image from BOOTABLE image with PODMAAN (AWS, QCOW2,RAW, ISO). + Validate install built out images + """ + disk_image_type = params.get("disk_image_type") + aws_config_dict = eval(params.get("aws_config_dict", '{}')) + try: + prepare_env_and_execute_bib(params, test) + # validate build output + update_bib_env_info(params, test) + if disk_image_type in ["vmdk"]: + bib_utils.create_and_start_vmware_vm(params) + elif disk_image_type in ["qcow2", "raw", "anaconda-iso"]: + bib_utils.create_qemu_vm(params, env, test) + elif disk_image_type in ["ami"]: + if len(aws_config_dict) != 0: + bib_utils.create_and_start_cloud_vm(params) + else: + bib_utils.create_qemu_vm(params, env, test) + except Exception as ex: + raise ex + finally: + vm_name = params.get("vm_name_bootc") + if vm_name and vm_name in virsh.dom_list().stdout_text: + virsh.undefine(vm_name, options="--nvram", ignore_status=True) + # Clean up files + for file_path in cleanup_files: + if os.path.exists(file_path): + os.remove(file_path) From 5b7ac4919f61770fbdf736b24865640c7c28dff4 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Thu, 12 Sep 2024 03:34:58 -0400 Subject: [PATCH 0593/1055] Fix change media update device failure This may happen in case VM is not real ready to update device Signed-off-by: chunfuwen --- libvirt/tests/src/virsh_cmd/domain/virsh_change_media.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_change_media.py b/libvirt/tests/src/virsh_cmd/domain/virsh_change_media.py index e5a4c23d458..16dc261a094 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_change_media.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_change_media.py @@ -242,6 +242,8 @@ def update_device(vm_name, init_iso, options, start_vm): process.run("mkfs.ext3 -F %s" % source, shell=True) all_options = action + options + " " + source + if vm.is_alive(): + vm.wait_for_login().close() result = virsh.change_media(vm_ref, target_device, all_options, ignore_status=True, debug=True) if status_error: From 5d96e5a999709da52177164ea1c590ff48cb5ac5 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 9 Sep 2024 03:21:47 -0400 Subject: [PATCH 0594/1055] vcpu_metrics: handle missing element //os/loader* might not exist on the domain definition leading to an exception. In this case, skip the step that tries to remove those attributes. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/cpu/vcpu_metrics.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/src/cpu/vcpu_metrics.py b/libvirt/tests/src/cpu/vcpu_metrics.py index 5baf6944915..a538ada69ba 100644 --- a/libvirt/tests/src/cpu/vcpu_metrics.py +++ b/libvirt/tests/src/cpu/vcpu_metrics.py @@ -24,6 +24,7 @@ from virttest import virsh from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.xcepts import LibvirtXMLNotFoundError from virttest.utils_libvirt import libvirt_bios from virttest.utils_libvirt import libvirt_vmxml @@ -136,11 +137,14 @@ def setup_with_unprivileged_user(vm, params, test): unprivileged_boot_disk_path = os.path.join(unprivileged_boot_disk_path, os.path.basename(first_disk_source)) disk_attrs = {'source': {'attrs': {'file': unprivileged_boot_disk_path}}} libvirt_vmxml.modify_vm_device(vmxml, 'disk', disk_attrs) - os_attrs = { - "loader": vmxml.os.loader, - "loader_readonly": vmxml.os.loader_readonly, - "loader_type": vmxml.os.loader_type - } + try: + os_attrs = { + "loader": vmxml.os.loader, + "loader_readonly": vmxml.os.loader_readonly, + "loader_type": vmxml.os.loader_type + } + except LibvirtXMLNotFoundError: + pass vmxml.os = libvirt_bios.remove_bootconfig_items_from_vmos(vmxml.os) if vmxml.xmltreefile.find('features'): arch = platform.machine().lower() From 960f6c0dd623f212f4e507ad5ad569232c1441f3 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Fri, 13 Sep 2024 04:26:46 -0400 Subject: [PATCH 0595/1055] Add case about virt-v2v-in-place Signed-off-by: Ming Xie --- v2v/tests/cfg/convert_from_file.cfg | 10 ++++++++++ v2v/tests/src/convert_from_file.py | 9 +++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/v2v/tests/cfg/convert_from_file.cfg b/v2v/tests/cfg/convert_from_file.cfg index 1546632d79f..9673cc847ea 100644 --- a/v2v/tests/cfg/convert_from_file.cfg +++ b/v2v/tests/cfg/convert_from_file.cfg @@ -37,6 +37,8 @@ output_method = "rhev" - local: only dest_local + - none: + only dest_none variants: - input_mode: variants: @@ -50,6 +52,14 @@ - latest8: boottype = 3 image_url = "LATEST_RHEL8_IMAGE_URL_V2V_EXAMPLE" + - virt_v2v_in_place: + only output_mode.none + boottype = 3 + image_url = "LATEST_RHEL9_IMAGE_URL_V2V_EXAMPLE" + checkpoint = 'virt_v2v_in_place' + msg_content = 'virt-v2v-in-place: warning: virt-v2v-in-place is NOT SUPPORTED .*? use virt-v2v instead of this tool.' + expect_msg = yes + skip_vm_check = yes - libvirtxml: only source_none input_mode = "libvirtxml" diff --git a/v2v/tests/src/convert_from_file.py b/v2v/tests/src/convert_from_file.py index ffbb6499336..4a41a29e8de 100644 --- a/v2v/tests/src/convert_from_file.py +++ b/v2v/tests/src/convert_from_file.py @@ -288,6 +288,11 @@ def vm_check(): log_fail('fail to download guest image from libvirt-ci resource') image_name = re.search(r'RHEL-\S*\w*.qcow2', params.get('image_url')).group() v2v_params.update({'input_file': os.path.join(tmp_path, image_name)}) + if checkpoint == 'virt_v2v_in_place': + output = utils_v2v.cmd_run('/usr/libexec/virt-v2v-in-place -i disk %s/%s' % (tmp_path, image_name)) + log_check = utils_v2v.check_log(params, output.stdout_text) + if log_check: + log_fail(log_check) if output_format: v2v_params.update({'of_format': output_format}) # Create libvirt dir pool @@ -331,8 +336,8 @@ def vm_check(): if 'new_name' in v2v_params: vm_name = params['main_vm'] = v2v_params['new_name'] - - check_result(v2v_result, status_error) + if checkpoint != 'virt_v2v_in_place': + check_result(v2v_result, status_error) finally: # Cleanup constant files utils_v2v.cleanup_constant_files(params) From 4f7fe50da291430d2fa3179108504268552b3f77 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Fri, 13 Sep 2024 05:59:26 -0400 Subject: [PATCH 0596/1055] Fixup:passt_negative:sync vmxml after deleting vm ifaces Signed-off-by: Haijiao Zhao --- .../src/virtual_network/passt/passt_negative_setting.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py b/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py index f2f98199f7a..cf97ffa54f3 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py +++ b/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py @@ -17,6 +17,7 @@ from provider.virtual_network import passt +VIRSH_ARGS = {'ignore_status': False, 'debug': True} LOG = logging.getLogger('avocado.' + __name__) DOWN_IFACE_NAME = "br1234" @@ -119,9 +120,14 @@ def _get_test_ip(): if operation == 'start_vm': vmxml.add_device(iface_device) vmxml.sync(virsh_instance=virsh_ins) + LOG.debug( + f'VMXML: {virsh.dumpxml(vm_name, uri=virsh_uri).stdout_text}') result = virsh.start(vm_name, uri=virsh_uri, debug=True) if operation == 'hotplug': - virsh.start(vm_name, uri=virsh_uri) + vmxml.sync(virsh_instance=virsh_ins) + LOG.debug( + f'VMXML: {virsh.dumpxml(vm_name, uri=virsh_uri).stdout_text}') + virsh.start(vm_name, uri=virsh_uri, **VIRSH_ARGS) result = virsh.attach_device(vm_name, iface_device.xml, uri=virsh_uri, debug=True) From 1ddaaebb44f290f91182edc2afbe2c5cbcca732c Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Fri, 13 Sep 2024 11:30:36 -0400 Subject: [PATCH 0597/1055] svirt/selinux/per_device: return if expected error is found `status_error` expected to be `yes` on invalid configuration, that is, either during xml setup a) through `vmxml.sync` which undefines and tries to define the VM, or b) through attach through `virsh.attach_device`. Both will raise LibvirtXMLError on failure. So, if as expected this error is raised for coldplug, we can stop the test execution by returning and considering the test PASS. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/svirt/selinux/selinux_seclabel_per_device.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/src/svirt/selinux/selinux_seclabel_per_device.py b/libvirt/tests/src/svirt/selinux/selinux_seclabel_per_device.py index e3fcd426bc0..760dea7b06b 100644 --- a/libvirt/tests/src/svirt/selinux/selinux_seclabel_per_device.py +++ b/libvirt/tests/src/svirt/selinux/selinux_seclabel_per_device.py @@ -88,6 +88,8 @@ def run(test, params, env): except xcepts.LibvirtXMLError as details: if not status_error: test.fail(details) + else: + return test.log.debug("VM XML: %s.", VMXML.new_from_inactive_dumpxml(vm_name)) if not ('res' in locals() and res.exit_status != 0): res = virsh.start(vm.name) From 4836a40c48f4a5db6e3783ffcf256df9dc31e8ba Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Wed, 18 Sep 2024 11:34:54 +0800 Subject: [PATCH 0598/1055] v2v: fix shortID for rhel10.0 Signed-off-by: vwu-vera --- v2v/tests/cfg/convert_vm_to_libvirt.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2v/tests/cfg/convert_vm_to_libvirt.cfg b/v2v/tests/cfg/convert_vm_to_libvirt.cfg index 8bddc7b440c..33d760e165c 100644 --- a/v2v/tests/cfg/convert_vm_to_libvirt.cfg +++ b/v2v/tests/cfg/convert_vm_to_libvirt.cfg @@ -46,7 +46,7 @@ vm_pwd = ${password} variants: - latest10_dev: - os_short_id = "RHEL9_DEV_SHORT_ID" + os_short_id = "RHEL10_DEV_SHORT_ID" os_version = "LATEST_DEV_10" - latest9_dev: os_short_id = "RHEL9_DEV_SHORT_ID" From 60fde9b453701977574f873a985df819e87f6591 Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 28 May 2024 14:52:01 +0800 Subject: [PATCH 0599/1055] graphics: Add case to check domdisplay output XXXX-62543 - [vnc] Query display URI of vnc that has password with/without --include-password Signed-off-by: lcheng --- .../tests/cfg/graphics/graphics_functional.cfg | 8 ++++++++ libvirt/tests/src/graphics/graphics_functional.py | 15 ++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/graphics/graphics_functional.cfg b/libvirt/tests/cfg/graphics/graphics_functional.cfg index 7aa777a274d..8bbea5789c2 100644 --- a/libvirt/tests/cfg/graphics/graphics_functional.cfg +++ b/libvirt/tests/cfg/graphics/graphics_functional.cfg @@ -339,6 +339,14 @@ valid_time = 60 opt_str = " --gtk-vnc-debug" rv_log_auth = "Authentication failed" + - check_with_domdisplay: + check_with_domdisplay = "yes" + vnc_passwd_place = "guest" + vnc_autoport = "yes" + variants: + - include_password_no: + - include_password_yes: + domdisplay_options = "--include-password" - disable_fips: vnc_autoport = "yes" check_fips = "yes" diff --git a/libvirt/tests/src/graphics/graphics_functional.py b/libvirt/tests/src/graphics/graphics_functional.py index 84be3f1c830..41e8e91bae3 100644 --- a/libvirt/tests/src/graphics/graphics_functional.py +++ b/libvirt/tests/src/graphics/graphics_functional.py @@ -1463,7 +1463,7 @@ def check_xml(vm_name, filetransfer, test): test.fail('The attribute of filetransfer error.') -def check_domdisplay_result(graphic_type, vm_name, expected_result, test): +def check_domdisplay_result(graphic_type, vm_name, expected_result, test, options="", passwd=None): """ Check domdisplay result @@ -1471,8 +1471,10 @@ def check_domdisplay_result(graphic_type, vm_name, expected_result, test): :param vm_name: name of the VM domain :param expected_result: expected result :param test: test object + :param options: domdisplay options + :param passwd: graphic password """ - domdisplay_out = virsh.domdisplay(vm_name, debug=True) + domdisplay_out = virsh.domdisplay(vm_name, options=options, debug=True) if domdisplay_out.exit_status: test.fail("Fail to get domain display info. Error:" "%s." % domdisplay_out.stderr.strip()) @@ -1483,8 +1485,10 @@ def check_domdisplay_result(graphic_type, vm_name, expected_result, test): if expected_result['spice_tls_port'] != 'not_set': expected_uri += "?tls-port=%s" % expected_result['spice_tls_port'] if graphic_type == 'vnc': + if "include-password" in options: + expected_uri += ":%s@" % passwd expected_uri += "%s:" % expected_result['vnc_options']['addr'] - expected_uri += "%s" % expected_result['vnc_port'] + expected_uri += "%s" % str(int(expected_result['vnc_port']) - 5900) if domdisplay_out.stdout.strip() != expected_uri: test.fail("Use domdisplay to check URI failed. Expected uri: %s" % expected_uri) @@ -1660,6 +1664,7 @@ def run(test, params, env): autoport = params.get("spice_autoport", "yes") spice_tls = params.get("spice_tls", "not_set") check_fips = params.get("check_fips", "no") == 'yes' + check_with_domdisplay = params.get("check_with_domdisplay", "no") == 'yes' if check_fips: if not is_enable_fips(): @@ -1776,6 +1781,10 @@ def run(test, params, env): check_qemu_command_line(params) vnc_opts = qemu_vnc_options(vm, params) check_vnc_result(vnc_opts, expected_result, all_ips, test) + if check_with_domdisplay: + domdisplay_options = params.get("domdisplay_options", "") + check_domdisplay_result('vnc', vm_name, expected_result, test, + options=domdisplay_options, passwd=graphic_passwd) if params.get("hook_path"): test_passwd_hook(params, vm, test) From d168af8fad9a7eec661e134a2a29ff0caf30be6b Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 18 Sep 2024 16:02:40 +0800 Subject: [PATCH 0600/1055] vIOMMU: Remove the iommu device before attaching it Update to remove the iommu device before attaching it to avoid failures. Signed-off-by: Yingshun Cui --- libvirt/tests/src/sriov/vIOMMU/attach_iommu_device.py | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/src/sriov/vIOMMU/attach_iommu_device.py b/libvirt/tests/src/sriov/vIOMMU/attach_iommu_device.py index bf208b9acd8..7ff0bb3f169 100644 --- a/libvirt/tests/src/sriov/vIOMMU/attach_iommu_device.py +++ b/libvirt/tests/src/sriov/vIOMMU/attach_iommu_device.py @@ -34,6 +34,7 @@ def run(test, params, env): vmxml.sync() err_msg = '' + libvirt_vmxml.remove_vm_devices_by_type(vm, 'iommu') iommu_dev = libvirt_vmxml.create_vm_device_by_type('iommu', iommu_dict) test.log.debug(f"iommu device: {iommu_dev}") res = virsh.attach_device(vm.name, iommu_dev.xml, debug=True, From 39fbcacee5131ff057f9f2abe50a57ba93223074 Mon Sep 17 00:00:00 2001 From: Misbah Anjum N Date: Thu, 19 Sep 2024 02:51:22 -0500 Subject: [PATCH 0601/1055] Change login method for interface verification Use wait_for_login(serial=True) method to login into the guest through ssh first and then try serial login if failed. Using vm.wait_for_serial_login(username, password) as the primary method is leading to Login Timeout Issues. In order to check if network iface exists, using the wait_for_login method is faster and successful. If failed, serial=True will result in fallback to serial login. Signed-off-by: Misbah Anjum N --- libvirt/tests/src/virtual_network/iface_hotplug.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/src/virtual_network/iface_hotplug.py b/libvirt/tests/src/virtual_network/iface_hotplug.py index 1019d4d8581..dac8387ded9 100644 --- a/libvirt/tests/src/virtual_network/iface_hotplug.py +++ b/libvirt/tests/src/virtual_network/iface_hotplug.py @@ -235,8 +235,7 @@ def get_all_mac_in_vm(): def check_iface_exist(): try: - session = vm.wait_for_serial_login(username=username, - password=password) + session = vm.wait_for_login(serial=True) if utils_net.get_linux_ifname(session, iface['mac']): return True else: @@ -291,8 +290,7 @@ def check_iface_exist(): # Start the domain if needed if vm.is_dead(): vm.start() - session = vm.wait_for_serial_login(username=username, - password=password) + session = vm.wait_for_login(serial=True) # check if interface is attached for iface in iface_list: From 55bb71699388b3b5e01bd1f001d5241dd0d8dd03 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Thu, 19 Sep 2024 17:45:31 +0800 Subject: [PATCH 0602/1055] viommu: Fixup incorrect disk xml issues The disk and scsi controller may enable iommu by default, so update to use the proper disk and controller settings. Signed-off-by: Yingshun Cui --- .../sriov/vIOMMU/iommu_device_settings.cfg | 3 +- .../src/sriov/vIOMMU/iommu_device_settings.py | 5 +- provider/viommu/viommu_base.py | 51 ++++++++++--------- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg b/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg index 6886ab547a7..6130f050c20 100644 --- a/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg +++ b/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg @@ -46,7 +46,8 @@ - scsi_controller: test_devices = ["scsi"] controller_dicts = [{'type': 'scsi', 'model': 'virtio-scsi','driver': {'iommu': 'on'}}] - disk_dict = {'target': {'dev': 'sda', 'bus': 'scsi'}} + disk_driver = {'name': 'qemu', 'type': 'qcow2'} + disk_dict = {'target': {'dev': 'sda', 'bus': 'scsi'}, 'driver': ${disk_driver}} cleanup_ifaces = no - pcie_to_pci_bridge_controller: test_devices = ["Eth", "block"] diff --git a/libvirt/tests/src/sriov/vIOMMU/iommu_device_settings.py b/libvirt/tests/src/sriov/vIOMMU/iommu_device_settings.py index 3a43ceb43d7..207e5e00784 100644 --- a/libvirt/tests/src/sriov/vIOMMU/iommu_device_settings.py +++ b/libvirt/tests/src/sriov/vIOMMU/iommu_device_settings.py @@ -35,8 +35,11 @@ def run(test, params, env): for dev in ["disk", "video"]: dev_dict = eval(params.get('%s_dict' % dev, '{}')) - if dev == "disk": + if dev == "disk" and dev_dict: dev_dict = test_obj.update_disk_addr(dev_dict) + if dev_dict["target"].get("bus") != "virtio": + libvirt_vmxml.modify_vm_device( + vm_xml.VMXML.new_from_dumpxml(vm.name), dev, {'driver': None}) libvirt_vmxml.modify_vm_device( vm_xml.VMXML.new_from_dumpxml(vm.name), dev, dev_dict) diff --git a/provider/viommu/viommu_base.py b/provider/viommu/viommu_base.py index 9326d98b109..62d2255f34b 100644 --- a/provider/viommu/viommu_base.py +++ b/provider/viommu/viommu_base.py @@ -59,16 +59,16 @@ def parse_iface_dict(self): :return: The updated iface_dict """ mac_addr = utils_net.generate_mac_address_simple() - iface_dict = eval(self.params.get('iface_dict', '{}')) + iface_dict = eval(self.params.get("iface_dict", "{}")) self.test.log.debug("iface_dict2: %s.", iface_dict) if self.controller_dicts and iface_dict: - iface_bus = "%0#4x" % int(self.controller_dicts[-1].get('index')) - iface_attrs = {'bus': iface_bus} + iface_bus = "%0#4x" % int(self.controller_dicts[-1].get("index")) + iface_attrs = {"bus": iface_bus} if isinstance(self.dev_slot, int): self.dev_slot += 1 - iface_attrs.update({'slot': self.dev_slot}) - iface_dict.update({"address": {'attrs': iface_attrs}}) + iface_attrs.update({"slot": self.dev_slot}) + iface_dict.update({"address": {"attrs": iface_attrs}}) self.test.log.debug("iface_dict: %s.", iface_dict) return iface_dict @@ -85,25 +85,25 @@ def prepare_controller(self): pre_controller = contr_dict.get("pre_controller") if pre_controller: pre_contrs = list( - filter(None, [c.get('index') for c in self.controller_dicts - if c['type'] == contr_dict['type'] and - c['model'] == pre_controller])) + filter(None, [c.get("index") for c in self.controller_dicts + if c["type"] == contr_dict["type"] and + c["model"] == pre_controller])) if pre_contrs: pre_idx = pre_contrs[0] else: pre_idx = libvirt_pcicontr.get_max_contr_indexes( vm_xml.VMXML.new_from_dumpxml(self.vm.name), - contr_dict['type'], pre_controller) + contr_dict["type"], pre_controller) if not pre_idx: self.test.error( f"Unable to get index of {pre_controller} controller!") contr_dict.pop("pre_controller") libvirt_vmxml.modify_vm_device( - vm_xml.VMXML.new_from_dumpxml(self.vm.name), 'controller', + vm_xml.VMXML.new_from_dumpxml(self.vm.name), "controller", contr_dict, 100) - contr_dict['index'] = libvirt_pcicontr.get_max_contr_indexes( + contr_dict["index"] = libvirt_pcicontr.get_max_contr_indexes( vm_xml.VMXML.new_from_dumpxml(self.vm.name), - contr_dict['type'], contr_dict['model'])[-1] + contr_dict["type"], contr_dict["model"])[-1] return self.controller_dicts def update_disk_addr(self, disk_dict): @@ -114,19 +114,20 @@ def update_disk_addr(self, disk_dict): :return: The updated disk attrs """ if self.controller_dicts: - dev_bus = self.controller_dicts[-1].get('index') - dev_attrs = {'bus': dev_bus} - if disk_dict['target']['bus'] != "scsi": - dev_attrs.update({'type': self.controller_dicts[-1].get('type')}) - if self.controller_dicts[-1].get('model') == 'pcie-to-pci-bridge': + dev_bus = self.controller_dicts[-1].get("index") + dev_attrs = {"bus": "0"} + if disk_dict["target"]["bus"] != "scsi": + dev_attrs = {"bus": dev_bus} + dev_attrs.update({"type": self.controller_dicts[-1].get("type")}) + if self.controller_dicts[-1].get("model") == "pcie-to-pci-bridge": self.dev_slot = 1 - dev_attrs.update({'slot': self.dev_slot}) + dev_attrs.update({"slot": self.dev_slot}) - disk_dict.update({"address": {'attrs': dev_attrs}}) - if disk_dict['target']['bus'] == "scsi": - disk_dict['address']['attrs'].update({'type': 'drive'}) + disk_dict.update({"address": {"attrs": dev_attrs}}) + if disk_dict["target"]["bus"] == "scsi": + disk_dict["address"]["attrs"].update({"type": "drive", "controller": dev_bus}) - if self.controller_dicts[-1]['model'] == 'pcie-root-port': + if self.controller_dicts[-1]["model"] == "pcie-root-port": self.controller_dicts.pop() return disk_dict @@ -136,13 +137,13 @@ def setup_iommu_test(self, **dargs): :param dargs: Other test keywords """ - iommu_dict = dargs.get('iommu_dict', {}) + iommu_dict = dargs.get("iommu_dict", {}) dev_type = dargs.get("dev_type", "interface") cleanup_ifaces = "yes" == dargs.get("cleanup_ifaces", "yes") if cleanup_ifaces: - libvirt_vmxml.remove_vm_devices_by_type(self.vm, 'interface') - libvirt_vmxml.remove_vm_devices_by_type(self.vm, 'hostdev') + libvirt_vmxml.remove_vm_devices_by_type(self.vm, "interface") + libvirt_vmxml.remove_vm_devices_by_type(self.vm, "hostdev") if iommu_dict: self.test.log.info("TEST_SETUP: Add iommu device.") libvirt_virtio.add_iommu_dev(self.vm, iommu_dict) From c452f460000c86c037212a928384be1167c93aa5 Mon Sep 17 00:00:00 2001 From: Han Han Date: Fri, 20 Sep 2024 14:54:07 +0800 Subject: [PATCH 0603/1055] usb_device: Fix the unassigned variable 'usb_cmd' Fixes the regression from 1a20a4a3a. It will cause this error for non-redirect device caes: UnboundLocalError: cannot access local variable 'usb_cmd' where it is not associated with a value Signed-off-by: Han Han --- libvirt/tests/src/usb/usb_device.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/usb/usb_device.py b/libvirt/tests/src/usb/usb_device.py index b790f3fa4f1..7e0279fae47 100644 --- a/libvirt/tests/src/usb/usb_device.py +++ b/libvirt/tests/src/usb/usb_device.py @@ -59,6 +59,7 @@ def run(test, params, env): device_type = params.get("device_type", "") device_mode = params.get("device_mode", "") port_num = params.get("port_num", "") + usb_cmd = None if device_name == "redirdev": add_pkg, usb_cmd = usb_base.get_host_pkg_and_cmd() pkgs_host = params.get("pkgs_host", "") + add_pkg @@ -403,5 +404,6 @@ def check_alias(device_alias): finally: if 'session' in locals(): session.close() - usb_base.kill_redirect_server(usb_cmd) + if usb_cmd: + usb_base.kill_redirect_server(usb_cmd) vmxml_backup.sync() From d17c130ea3aa0ff712ed514fe5d7c67ecf9e6bcd Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 23 Sep 2024 00:52:28 -0400 Subject: [PATCH 0604/1055] Add numa node free memory page debug info Signed-off-by: liang-cong-red-hat --- .../specific_numa_memory_bind_hugepage.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/specific_numa_memory_bind_hugepage.py b/libvirt/tests/src/numa/guest_numa_node_tuning/specific_numa_memory_bind_hugepage.py index d4ece274c47..080d81bf645 100644 --- a/libvirt/tests/src/numa/guest_numa_node_tuning/specific_numa_memory_bind_hugepage.py +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/specific_numa_memory_bind_hugepage.py @@ -32,6 +32,8 @@ def setup_default(test_obj): utils_libvirtd.Libvirtd().restart() test_obj.params['hpc_list'] = [hpc] test_obj.test.log.debug("Step: setup is done") + test_obj.test.log.debug("Host memory page status is:\n%s" + % virsh.freepages(options='--all').stdout_text) def prepare_vm_xml(test_obj): From 5f82e6d3fa0d15ac81923c3b17528222aacc072c Mon Sep 17 00:00:00 2001 From: Misbah Anjum N Date: Mon, 23 Sep 2024 01:55:37 -0500 Subject: [PATCH 0605/1055] libvirt-mem: Update testcases for ppc64le arch On ppc64le arch, xml does not support numa with memory device same as x86_64 or aarch64. Hence, removing the testcase for ppc64le Similarly, negative test scenario is added for checking the same on ppc64le Signed-off-by: Misbah Anjum N --- libvirt/tests/cfg/libvirt_mem.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/libvirt_mem.cfg b/libvirt/tests/cfg/libvirt_mem.cfg index 7be0e5a6d79..69db0e75506 100644 --- a/libvirt/tests/cfg/libvirt_mem.cfg +++ b/libvirt/tests/cfg/libvirt_mem.cfg @@ -132,7 +132,7 @@ memory_addr = "{'type':'dimm','slot':'0','base':'0x100000000'}" node_mask = 0 - without_numa_save_restore: - no x86_64,aarch64 + no x86_64,aarch64,ppc64le max_mem_rt = 20971520 numa_cells = "" tg_node = "" @@ -180,7 +180,7 @@ page_size = 4 page_unit = "KiB" - without_numa: - only x86_64,aarch64 + only x86_64,aarch64,ppc64le define_error = "yes" max_mem_rt = 20971520 numa_cells = "" From 894dac1dbb7aff0e33b957b9509ee73cac2a27af Mon Sep 17 00:00:00 2001 From: Misbah Anjum N Date: Mon, 23 Sep 2024 02:28:21 -0500 Subject: [PATCH 0606/1055] libvirt-mem: Enable check for test_qemu_cmd The following testcases are failing because because of the check for test_qemu_cmd is not added in the script 1. type_specific.io-github-autotest-libvirt.libvirt_mem. positive_test.align_256m.cold_plug: FAIL: Qemu command check fail. (205.37 s) 2. type_specific.io-github-autotest-libvirt.libvirt_mem. positive_test.align_256m.hot_plug: FAIL: Qemu command check fail. (209.51 s) In the libvirt_mem.cfg, the following parameter is set to no - "test_qemu_cmd = no" Hence, the check must be added in all places Signed-off-by: Misbah Anjum N --- libvirt/tests/src/libvirt_mem.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/libvirt_mem.py b/libvirt/tests/src/libvirt_mem.py index 6d70835d505..d37006e5309 100644 --- a/libvirt/tests/src/libvirt_mem.py +++ b/libvirt/tests/src/libvirt_mem.py @@ -515,7 +515,8 @@ def modify_domain_xml(): elif discard: vm.start() session = vm.wait_for_login() - check_qemu_cmd(max_mem_rt, tg_size) + if test_qemu_cmd: + check_qemu_cmd(max_mem_rt, tg_size) dev_xml = None # To attach the memory device. @@ -605,7 +606,8 @@ def modify_domain_xml(): if mem_align: dom_mem = check_mem_align() - check_qemu_cmd(dom_mem['maxMemory'], dom_mem['attached_mem']) + if test_qemu_cmd: + check_qemu_cmd(dom_mem['maxMemory'], dom_mem['attached_mem']) if hot_plug and params['delta'] != dom_mem['attached_mem']: test.fail('Memory after attach not equal to original mem + attached mem') From c9b6c58b3a300c9ca27a6489b62a1e754ce49c39 Mon Sep 17 00:00:00 2001 From: Xiaodai Wang Date: Mon, 23 Sep 2024 17:29:29 +0800 Subject: [PATCH 0607/1055] RAS: add new case for RAS feature support Signed-off-by: Xiaodai Wang --- libvirt/tests/cfg/features/ras.cfg | 14 +++++++ libvirt/tests/src/features/ras.py | 62 ++++++++++++++++++++++++++++++ spell.ignore | 1 + 3 files changed, 77 insertions(+) create mode 100644 libvirt/tests/cfg/features/ras.cfg create mode 100644 libvirt/tests/src/features/ras.py diff --git a/libvirt/tests/cfg/features/ras.cfg b/libvirt/tests/cfg/features/ras.cfg new file mode 100644 index 00000000000..ecab1808fd4 --- /dev/null +++ b/libvirt/tests/cfg/features/ras.cfg @@ -0,0 +1,14 @@ +- features.ras: + type = ras + start_vm = no + only aarch64 + func_supported_since_libvirt_ver = (10, 4, 0) + unsupported_err_msg = "Ras feature is not supported on current version." + variants: + - on: + ras_state = on + - off: + ras_state = off + variants: + - positive_test: + status_error = "no" diff --git a/libvirt/tests/src/features/ras.py b/libvirt/tests/src/features/ras.py new file mode 100644 index 00000000000..ed9af4a8502 --- /dev/null +++ b/libvirt/tests/src/features/ras.py @@ -0,0 +1,62 @@ +import logging + +from virttest import virsh +from virttest import libvirt_version +from virttest.libvirt_xml.vm_xml import VMXML +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test the ras feature + 1. Enable 'ras=on/off' in a guest + 2. check the xml and qemu cmd line + """ + # Ras feature supported since 10.4.0. + libvirt_version.is_libvirt_feature_supported(params) + + ras_state = params.get("ras_state") + + def check_dumpxml(): + """ + Check whether the added devices are shown in the guest xml + """ + xpath = [{'element_attrs': [".//ras[@state='%s']" % ras_state]}] + # Check ras state + vm_xml = VMXML.new_from_dumpxml(vm_name) + libvirt_vmxml.check_guest_xml_by_xpaths(vm_xml, xpath) + + def check_qemu_cmd_line(): + """ + Check whether the ras feature is shown in the qemu cmd line + """ + pattern = r"-machine.*ras=%s" % ras_state + libvirt.check_qemu_cmd_line(pattern) + + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + + vm_xml = VMXML.new_from_dumpxml(vm_name) + vm_xml_backup = vm_xml.copy() + LOG.debug("vm xml is %s", vm_xml_backup) + + if vm.is_alive(): + vm.destroy() + + try: + features_xml = vm_xml.features + if features_xml.has_feature('ras'): + features_xml.remove_feature('ras') + features_xml.ras = ras_state + vm_xml.features = features_xml + vm_xml.sync() + virsh.start(vm_name, ignore_status=False) + check_dumpxml() + check_qemu_cmd_line() + finally: + if vm.is_alive(): + virsh.destroy(vm_name) + vm_xml_backup.sync() diff --git a/spell.ignore b/spell.ignore index c18394405c4..902e06e8898 100644 --- a/spell.ignore +++ b/spell.ignore @@ -826,6 +826,7 @@ qxl QXL qxldod Radix +ras rases rawio rbd From 616b1fff3c43998bc63a577af0aa820d7bf176aa Mon Sep 17 00:00:00 2001 From: lcheng Date: Thu, 23 May 2024 18:00:48 +0800 Subject: [PATCH 0608/1055] libvirtd: Add case to test qemu monitor socket XXXX-37948 - [libvirtd] Start vm - with qemu monitor socket creation delay Signed-off-by: lcheng --- .../qemu_monitor_socket_creation_delay.cfg | 7 +++ libvirt/tests/deps/qemu_wrapper.py | 12 ++++++ .../qemu_monitor_socket_creation_delay.py | 43 +++++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 libvirt/tests/cfg/daemon/qemu_monitor_socket_creation_delay.cfg create mode 100755 libvirt/tests/deps/qemu_wrapper.py create mode 100644 libvirt/tests/src/daemon/qemu_monitor_socket_creation_delay.py diff --git a/libvirt/tests/cfg/daemon/qemu_monitor_socket_creation_delay.cfg b/libvirt/tests/cfg/daemon/qemu_monitor_socket_creation_delay.cfg new file mode 100644 index 00000000000..ab6b3389cea --- /dev/null +++ b/libvirt/tests/cfg/daemon/qemu_monitor_socket_creation_delay.cfg @@ -0,0 +1,7 @@ +- daemon.qemu_monitor_socket_creation_delay: + type = qemu_monitor_socket_creation_delay + start_vm = no + check_image = no + take_regular_screendumps = no + qemu_wrapper_path = "../../deps/qemu_wrapper.py" + tmp_qemu_wrapper_path = "/tmp/qemu_wrapper.py" diff --git a/libvirt/tests/deps/qemu_wrapper.py b/libvirt/tests/deps/qemu_wrapper.py new file mode 100755 index 00000000000..08943968ff4 --- /dev/null +++ b/libvirt/tests/deps/qemu_wrapper.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python + +import os +import sys +import time + +TIMEOUT = 5 +QEMU_PATH = "/usr/libexec/qemu-kvm" + +time.sleep(TIMEOUT) +sys.argv[0] = QEMU_PATH +os.execv(QEMU_PATH, sys.argv) diff --git a/libvirt/tests/src/daemon/qemu_monitor_socket_creation_delay.py b/libvirt/tests/src/daemon/qemu_monitor_socket_creation_delay.py new file mode 100644 index 00000000000..ed3f20eada2 --- /dev/null +++ b/libvirt/tests/src/daemon/qemu_monitor_socket_creation_delay.py @@ -0,0 +1,43 @@ +import os +import shutil + +from avocado.utils import process + +from virttest import virt_vm + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml + + +def run(test, params, env): + """ + Write a wrapper for qemu to wait several seconds (>3) before starts. + + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + emulator_dict = eval(params.get("emulator_dict")) + qemu_wrapper_path = params.get("qemu_wrapper_path") + tmp_qemu_wrapper_path = params.get("tmp_qemu_wrapper_path") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + xml_backup = vmxml.copy() + + try: + qemu_wrapper_path = os.path.join(os.path.dirname(__file__), qemu_wrapper_path) + shutil.copyfile(qemu_wrapper_path, tmp_qemu_wrapper_path) + os.chown(tmp_qemu_wrapper_path, 107, 107) + os.chmod(tmp_qemu_wrapper_path, 0o755) + process.run("chcon system_u:object_r:qemu_exec_t:s0 %s" % tmp_qemu_wrapper_path, shell=True) + + emulator_dict = {"path": "%s" % tmp_qemu_wrapper_path} + libvirt_vmxml.modify_vm_device(vmxml, "emulator", emulator_dict) + vm.start() + except virt_vm.VMStartError as e: + test.fail("Fail to Start vm with qemu monitor socket creation delay: %s" % e) + + finally: + if vm.is_alive(): + vm.destroy(gracefully=False) + if os.path.exists(tmp_qemu_wrapper_path): + os.remove(tmp_qemu_wrapper_path) + xml_backup.sync() From 7fab98f27db35f2c9796487f43d6c91c8736475b Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Mon, 23 Sep 2024 11:32:56 -0400 Subject: [PATCH 0609/1055] Add v2v cases about guests with extra online disks Signed-off-by: Ming Xie --- v2v/tests/cfg/function_test_esx.cfg | 21 +++++++++++++--- v2v/tests/src/function_test_esx.py | 37 +++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 27589048f73..887b890d568 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -219,6 +219,24 @@ main_vm = VM_NAME_WIN2019_EFI_V2V_EXAMPLE os_version = "win2019" boottype = 3 + - multiple_online_disks: + only esx_80 + checkpoint = 'check_online_disks' + variants: + - win2022: + os_version = "win2022" + main_vm = VM_NAME_WIN2022_ONLINE_DISKS_V2V_EXAMPLE + - win2025: + os_version = "win2025" + main_vm = VM_NAME_WIN2025_ONLINE_DISKS_V2V_EXAMPLE + boottype = 3 + - win11: + os_version = "win11" + main_vm = VM_NAME_WIN11_ONLINE_DISKS_V2V_EXAMPLE + - win2019: + main_vm = VM_NAME_WIN2019_ONLINE_DISKS_V2V_EXAMPLE + os_version = "win2019" + boottype = 3 - rhsrvany_md5: only esx_70 checkpoint = 'rhsrvany_checksum' @@ -286,9 +304,6 @@ - local_storage: only esx_70 main_vm = "VM_NAME_ESX_LOCALSTORAGE_V2V_EXAMPLE" - - multiple_disks: - only esx_70 - main_vm = 'VM_NAME_ESX_MULDISKS_V2V_EXAMPLE' - multiple_cpus: only esx_70 main_vm = 'VM_NAME_ESX_MULCPUS_V2V_EXAMPLE' diff --git a/v2v/tests/src/function_test_esx.py b/v2v/tests/src/function_test_esx.py index 8ecaa71955d..f0f386981ea 100644 --- a/v2v/tests/src/function_test_esx.py +++ b/v2v/tests/src/function_test_esx.py @@ -4,6 +4,7 @@ import uuid import shutil import tempfile +import time import xml.etree.ElementTree as ET from virttest import data_dir @@ -522,6 +523,40 @@ def verify_certificate(certs_src_dir, certs_dest_dir, vcenter_fdqn, vcenter_ip): with open('/etc/hosts', "w") as f: f.write('%s %s' % (vcenter_ip, vcenter_fdqn)) + def check_online_disks(vmcheck): + """ + Check if status of disks are online in VM + + :param vmcheck: VMCheck object for vm checking + """ + def _get_disk_status(cmd): + + for i in range(9): + _, res = vmcheck.run_cmd(cmd) + if re.search('Offline', res): + time.sleep(100) + else: + return res + return res + + cmd = r'cmd /c echo list disk^> "%temp%\answer.tmp" ^& (diskpart ^< "%temp%\answer.tmp") ^& ' \ + r'del "%temp%\answer.tmp"' + try: + res = utils_misc.wait_for(lambda: _get_disk_status(cmd), 900) + except (ShellProcessTerminatedError, ShellStatusError): + # Windows guest may reboot after installing qemu-ga service + LOG.debug('Windows guest is rebooting') + if vmcheck.session: + vmcheck.session.close() + vmcheck.session = None + # VM boots up is extremely slow when all testing in running on + # rhv server simultaneously, so set timeout to 1200. + vmcheck.create_session(timeout=1200) + res = utils_misc.wait_for(lambda: _get_disk_status(cmd), 900) + LOG.info('disk status is %s', res) + if re.search('Offline', res): + test.fail("there is offline additional disk") + def check_result(result, status_error): """ Check virt-v2v command result @@ -603,6 +638,8 @@ def vm_check(status_error): check_ubuntools(vmchecker.checker) if 'vmware_tools' in checkpoint: check_windows_vmware_tools(vmchecker.checker) + if 'check_online_disks' in checkpoint: + check_online_disks(vmchecker.checker) if 'without_default_net' in checkpoint: if virsh.net_state_dict()[net_name]['active']: log_fail("Bridge virbr0 already started during conversion") From bd643c471999041d46974ffc57522b333a8a0b03 Mon Sep 17 00:00:00 2001 From: nanli Date: Mon, 23 Sep 2024 10:14:44 +0800 Subject: [PATCH 0610/1055] case update: blockcopy dest xml for block disk with iscsi preparation xxxx-294410:Do blockcopy with different dest XML Signed-off-by: nanli --- .../blockcopy_with_different_dest_xml.cfg | 1 + provider/virtual_disk/disk_base.py | 44 +++++++++++++++---- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/libvirt/tests/cfg/backingchain/blockcopy/blockcopy_with_different_dest_xml.cfg b/libvirt/tests/cfg/backingchain/blockcopy/blockcopy_with_different_dest_xml.cfg index cbbc22b7d37..744140adb4e 100644 --- a/libvirt/tests/cfg/backingchain/blockcopy/blockcopy_with_different_dest_xml.cfg +++ b/libvirt/tests/cfg/backingchain/blockcopy/blockcopy_with_different_dest_xml.cfg @@ -20,6 +20,7 @@ - block_disk: dest_disk_type = "block" dest_disk_dict = {"type_name":"${dest_disk_type}", "target":{"dev": "${target_disk}", "bus": "virtio"}, "driver": {"name": "qemu", "type":"raw"}} + simulated_iscsi = "modprobe scsi_debug dev_size_mb=800" - rbd_with_auth_disk: dest_disk_type = "rbd_with_auth" mon_host = "EXAMPLE_MON_HOST" diff --git a/provider/virtual_disk/disk_base.py b/provider/virtual_disk/disk_base.py index e5079b8403b..dfd31bbd1ea 100644 --- a/provider/virtual_disk/disk_base.py +++ b/provider/virtual_disk/disk_base.py @@ -1,5 +1,7 @@ import logging import os +import re +import time from avocado.utils import lv_utils from avocado.utils import process @@ -129,7 +131,8 @@ def prepare_disk_obj(self, disk_type, disk_dict, new_image_path='', **kwargs): elif disk_type == 'block': if not new_image_path: new_image_path = self.create_lvm_disk_path( - vg_name=self.vg_name, lv_name=self.lv_name, **kwargs) + vg_name=self.vg_name, lv_name=self.lv_name, + simulated_iscsi=self.params.get("simulated_iscsi"), **kwargs) if self.params.get('convert_format'): process.run("qemu-img create -f %s /dev/%s/%s %s" % ( self.params.get('convert_format'), self.vg_name, @@ -210,7 +213,9 @@ def cleanup_disk_preparation(self, disk_type): :param disk_type: disk type """ if disk_type == 'block': - self.cleanup_block_disk_preparation(self.vg_name, self.lv_name) + self.cleanup_block_disk_preparation( + self.vg_name, self.lv_name, + simulated_iscsi=self.params.get("simulated_iscsi")) elif disk_type == 'file': if os.path.exists(self.new_image_path): @@ -234,18 +239,24 @@ def cleanup_disk_preparation(self, disk_type): self.test.log.debug("Clean Up nbd failed: %s", str(ndbEx)) @staticmethod - def cleanup_block_disk_preparation(vg_name, lv_name): + def cleanup_block_disk_preparation(vg_name, lv_name, **kwargs): """ Clean up volume group, logical volume, iscsi target. - :params vg_name: volume group name - :params lv_name: volume name + :param vg_name: volume group name + :param lv_name: volume name + :param kwargs: optional keyword arguments. """ lv_utils.lv_remove(vg_name, lv_name) lv_utils.vg_remove(vg_name) - libvirt.setup_or_cleanup_iscsi(is_setup=False) - if os.path.exists('/dev/%s' % vg_name): - os.rmdir('/dev/%s' % vg_name) + if kwargs.get("simulated_iscsi"): + time.sleep(3) + process.run("modprobe %s -r" % re.findall( + r"modprobe (\S+)", kwargs.get("simulated_iscsi"))[0]) + else: + libvirt.setup_or_cleanup_iscsi(is_setup=False) + if os.path.exists('/dev/%s' % vg_name): + os.rmdir('/dev/%s' % vg_name) @staticmethod def create_volume_for_disk_path(test, params, pool_name='pool_name', @@ -287,7 +298,11 @@ def create_lvm_disk_path(vg_name='vg0', lv_name='lv0', **kwargs): :params lv_name: volume name :return path: path for disk image """ - device_name = libvirt.setup_or_cleanup_iscsi(is_setup=True) + if kwargs.get("simulated_iscsi"): + process.run(kwargs.get("simulated_iscsi"), shell=True) + device_name = get_simulated_iscsi() + else: + device_name = libvirt.setup_or_cleanup_iscsi(is_setup=True) lv_utils.vg_create(vg_name, device_name) size = kwargs.get("size", "200M") if kwargs.get("size"): @@ -488,3 +503,14 @@ def prepare_backing_file(self, disk_type, backing_file_type, backing_format): process.run(backing_cmd, shell=True, verbose=True) return based_image, backing_file + + +def get_simulated_iscsi(): + """ + Get simulated iscsi device. + + :return simulated iscsi device name. + """ + res = process.run("lsscsi", shell=True).stdout_text.strip() + device_name = re.findall(r"Linux\s*scsi_debug\s*\d+\s+(\S+)\s*", res)[0] + return device_name From 8c7383b4c1046186a00afd92697e5e7413ccad99 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Tue, 24 Sep 2024 03:58:01 -0400 Subject: [PATCH 0611/1055] Change memory size according to case update Signed-off-by: liang-cong-red-hat --- .../memory_backing/lifecycle_for_hugepage.cfg | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_backing/lifecycle_for_hugepage.cfg b/libvirt/tests/cfg/memory/memory_backing/lifecycle_for_hugepage.cfg index 79d9476ac82..c63fe910152 100644 --- a/libvirt/tests/cfg/memory/memory_backing/lifecycle_for_hugepage.cfg +++ b/libvirt/tests/cfg/memory/memory_backing/lifecycle_for_hugepage.cfg @@ -1,17 +1,20 @@ - memory.backing.lifecycle: type = lifecycle_for_hugepage start_vm = no - total_hugepage_mem = 2097152 - vm_nr_hugepages = 1024 + total_hugepage_mem = 8388608 + vm_nr_hugepages = 4096 mount_size = "1048576" - current_mem = 2097152 - mem_value = 2097152 + current_mem = 8388608 + mem_value = 8388608 mem_unit = "KiB" current_mem_unit = "KiB" - target_hugepages = 2 + target_hugepages = 8 set_pagesize ="1048576" - set_pagenum = "2" + set_pagenum = "8" s390-virtio: + total_hugepage_mem = 2097152 + current_mem = 2097152 + mem_value = 2097152 set_pagesize = "1024" mount_size = "1024" set_pagenum = "2048" @@ -53,7 +56,7 @@ page_size = "2" page_unit = "M" set_pagesize ="2048" - set_pagenum = "1024" + set_pagenum = "4096" mount_size = ${set_pagesize} memory_backing_dict = "'mb': {'hugepages': {'pages': [{'unit': '${page_unit}', 'size': '${page_size}'}]}}" vm_attrs = {${memory_backing_dict}, 'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} @@ -77,7 +80,7 @@ page_size = "64" page_unit = "KiB" set_pagesize ="64" - set_pagenum = "32768" + set_pagenum = "131072" mount_size = ${set_pagesize} memory_backing_dict = "'mb': {'hugepages': {'pages': [{'unit': '${page_unit}', 'size': '${page_size}'}]}}" vm_attrs = {${memory_backing_dict}, 'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} @@ -88,7 +91,7 @@ page_size = "32" page_unit = "M" set_pagesize ="32768" - set_pagenum = "64" + set_pagenum = "256" mount_size = ${set_pagesize} memory_backing_dict = "'mb': {'hugepages': {'pages': [{'unit': '${page_unit}', 'size': '${page_size}'}]}}" vm_attrs = {${memory_backing_dict}, 'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} @@ -101,8 +104,9 @@ vm_attrs = {${memory_backing_dict}, 'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} define_error = "hugepage size can't be zero" - scarce_mem: - current_mem = 3145728 - mem_value = 3145728 + current_mem = 9437184 + mem_value = 9437184 memory_backing_dict = "'mb': {'hugepages': {}}" vm_attrs = {${memory_backing_dict}, 'memory_unit':'${mem_unit}','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'${current_mem_unit}'} start_error = "unable to map backing store for guest RAM: Cannot allocate memory" + From ae7bc138d9eea08c329cc51c9c3a45ed8773508c Mon Sep 17 00:00:00 2001 From: hholoubk Date: Wed, 25 Sep 2024 09:15:07 +0200 Subject: [PATCH 0612/1055] cfg change and test config check of default hp size --- .../svirt_umask_files_accessed_by_qemu.cfg | 2 ++ .../svirt_umask_files_accessed_by_qemu.py | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/libvirt/tests/cfg/svirt/umask_value/svirt_umask_files_accessed_by_qemu.cfg b/libvirt/tests/cfg/svirt/umask_value/svirt_umask_files_accessed_by_qemu.cfg index fed7c586519..77e57f083fb 100644 --- a/libvirt/tests/cfg/svirt/umask_value/svirt_umask_files_accessed_by_qemu.cfg +++ b/libvirt/tests/cfg/svirt/umask_value/svirt_umask_files_accessed_by_qemu.cfg @@ -3,8 +3,10 @@ start_vm = "no" umask_value = '027' mem_backing_attrs = {'hugepages': {}} + default_hp_size = 2048 target_hugepages = 1024 aarch64: + default_hp_size = 524288 target_hugepages = 4 s390-virtio: kvm_module_parameters = "hpage=1" diff --git a/libvirt/tests/src/svirt/umask_value/svirt_umask_files_accessed_by_qemu.py b/libvirt/tests/src/svirt/umask_value/svirt_umask_files_accessed_by_qemu.py index cab63676bc5..a8a9d59115c 100644 --- a/libvirt/tests/src/svirt/umask_value/svirt_umask_files_accessed_by_qemu.py +++ b/libvirt/tests/src/svirt/umask_value/svirt_umask_files_accessed_by_qemu.py @@ -7,6 +7,7 @@ from virttest import utils_libvirtd from virttest.libvirt_xml import vm_xml from virttest.libvirt_xml.vm_xml import VMXML +from avocado.utils import memory as avocado_mem def run(test, params, env): @@ -30,6 +31,19 @@ def run(test, params, env): if os.path.exists(hp_path): shutil.rmtree(hp_path) utils_libvirtd.Libvirtd().restart() + + # verify test runs on machine with expected hugepagesize + # and recalculate the target_hugepage if necessary + default_hp_size = int(params.get("default_hp_size", 2048)) + target_hugepages = int(params.get("target_hugepages", 1024)) + actual_hp_size = avocado_mem.get_huge_page_size() + if actual_hp_size != default_hp_size: + # actual hp size is different that is expected for defined number of hupages + # as the size is not the main focus of the test, we have to recalculate and replace + new_target_hugepages = int((default_hp_size * target_hugepages) / actual_hp_size) + test.log.warn(f"Default HP size is different than expected. Parameter 'target_hugepagees' was updated: {new_target_hugepages}") + params["target_hugepages"] = new_target_hugepages + hp_cfg = test_setup.HugePageConfig(params) hp_cfg.set_hugepages() From f07809d2254540fadb71b400616b76cd8485b63d Mon Sep 17 00:00:00 2001 From: hholoubk Date: Wed, 25 Sep 2024 16:56:23 +0200 Subject: [PATCH 0613/1055] resolving typos --- .../svirt/umask_value/svirt_umask_files_accessed_by_qemu.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/svirt/umask_value/svirt_umask_files_accessed_by_qemu.py b/libvirt/tests/src/svirt/umask_value/svirt_umask_files_accessed_by_qemu.py index a8a9d59115c..a3e9162d987 100644 --- a/libvirt/tests/src/svirt/umask_value/svirt_umask_files_accessed_by_qemu.py +++ b/libvirt/tests/src/svirt/umask_value/svirt_umask_files_accessed_by_qemu.py @@ -32,13 +32,13 @@ def run(test, params, env): shutil.rmtree(hp_path) utils_libvirtd.Libvirtd().restart() - # verify test runs on machine with expected hugepagesize + # verify test runs on machine with expected size of hugepages # and recalculate the target_hugepage if necessary default_hp_size = int(params.get("default_hp_size", 2048)) target_hugepages = int(params.get("target_hugepages", 1024)) actual_hp_size = avocado_mem.get_huge_page_size() if actual_hp_size != default_hp_size: - # actual hp size is different that is expected for defined number of hupages + # actual hp size is different that is expected for defined number of hugepages # as the size is not the main focus of the test, we have to recalculate and replace new_target_hugepages = int((default_hp_size * target_hugepages) / actual_hp_size) test.log.warn(f"Default HP size is different than expected. Parameter 'target_hugepagees' was updated: {new_target_hugepages}") From 3b51e5d4d57e0b1f35f3db5830e85f755b35ba2a Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Wed, 25 Sep 2024 22:54:36 -0400 Subject: [PATCH 0614/1055] Fail test case when huge page is not enough, and add huge page cleanup. Signed-off-by: liang-cong-red-hat --- libvirt/tests/src/memory/memory_misc.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/memory/memory_misc.py b/libvirt/tests/src/memory/memory_misc.py index 3f8369fbee8..c4a0adb5e79 100644 --- a/libvirt/tests/src/memory/memory_misc.py +++ b/libvirt/tests/src/memory/memory_misc.py @@ -266,8 +266,8 @@ def _setup_mbxml(): test, pg_size=default_page_size, hp_size=pagesize, hp_list=[mount_pagesize]) vm_mem_size = vmxml.memory hp_cfg = test_setup.HugePageConfig(params) - hp_cfg.set_kernel_hugepages(pagesize, vm_mem_size // pagesize) - hp_cfg.set_kernel_hugepages(mount_pagesize, mem_device_size // mount_pagesize) + hp_cfg.set_kernel_hugepages(pagesize, vm_mem_size // pagesize, False) + hp_cfg.set_kernel_hugepages(mount_pagesize, mem_device_size // mount_pagesize, False) set_vmxml(vmxml, params) _setup_mbxml() vmxml.sync() @@ -454,6 +454,9 @@ def cleanup_test_memorybacking(case): utils_disk.umount('hugetlbfs', mount_path, 'hugetlbfs') if os.path.exists(mount_path): os.rmdir(mount_path) + hp_cfg = test_setup.HugePageConfig(params) + hp_cfg.set_kernel_hugepages(int(params.get('mount_pagesize')), 0) + hp_cfg.cleanup() def run_test_edit_mem(case): """ From 8e99456d085d7b4e36c1f9b00fdab4b58b5d40f0 Mon Sep 17 00:00:00 2001 From: lcheng Date: Thu, 26 Sep 2024 15:51:21 +0800 Subject: [PATCH 0615/1055] remote_access: Update filter pattern Signed-off-by: lcheng --- libvirt/tests/cfg/remote_access/remote_with_tls.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/remote_access/remote_with_tls.cfg b/libvirt/tests/cfg/remote_access/remote_with_tls.cfg index de0d07681e1..939c10c343a 100644 --- a/libvirt/tests/cfg/remote_access/remote_with_tls.cfg +++ b/libvirt/tests/cfg/remote_access/remote_with_tls.cfg @@ -55,7 +55,7 @@ server_ip = "${ipv6_addr_des}" - default_tls_port_and_auth_tls: - default_tls_priority_specifier: - filter_pattern = "Setting priority string \'@LIBVIRT\,SYSTEM\'" + filter_pattern = "Setting priority string '@LIBVIRT,SYSTEM'" log_level= "LIBVIRT_DEBUG=1" - no_verify_certificate: tls_verify_cert = "no" From c308e3efb3147159ebeaac3c1638918a80b34cf9 Mon Sep 17 00:00:00 2001 From: lcheng Date: Thu, 26 Sep 2024 18:45:44 +0800 Subject: [PATCH 0616/1055] libvirt_hooks: Fix string matching Before libvirt 10.5.0, hook_str is '...release end -'. After libvirt 10.5.0, hook_str is '...release end shutdown'. Reference: https://github.com/autotest/tp-libvirt/pull/5782 Signed-off-by: lcheng --- libvirt/tests/src/libvirt_hooks.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/libvirt_hooks.py b/libvirt/tests/src/libvirt_hooks.py index 055d2a618a5..08fc2e3ad6c 100644 --- a/libvirt/tests/src/libvirt_hooks.py +++ b/libvirt/tests/src/libvirt_hooks.py @@ -103,7 +103,10 @@ def start_stop_hook(): vm.destroy() hook_str = hook_para + " stopped end -" assert check_hooks(hook_str) - hook_str = hook_para + " release end " + release_reason + if libvirt_version.version_compare(10, 5, 0): + hook_str = hook_para + " release end " + release_reason + else: + hook_str = hook_para + " release end -" assert check_hooks(hook_str) except AssertionError: utils_misc.log_last_traceback() From 6493425e76a21a5f92ccea105dcde14fc0d2ef4a Mon Sep 17 00:00:00 2001 From: Yanqiu Zhang Date: Tue, 24 Sep 2024 00:06:47 -0400 Subject: [PATCH 0617/1055] tpm_device.py: clean audit before vm start Cleaning audit logs should be before vm start, and need clean all audit.log*(.1, .2, etc) files. Also move it later to wait more time. And replace ausearch cmd since it can not capture well sometimes, audit.log can reflect actual info instead. Signed-off-by: Yanqiu Zhang --- libvirt/tests/cfg/virtual_device/tpm_device.cfg | 2 +- libvirt/tests/src/virtual_device/tpm_device.py | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/cfg/virtual_device/tpm_device.cfg b/libvirt/tests/cfg/virtual_device/tpm_device.cfg index 4fd10772321..bd3c6f10fab 100644 --- a/libvirt/tests/cfg/virtual_device/tpm_device.cfg +++ b/libvirt/tests/cfg/virtual_device/tpm_device.cfg @@ -141,7 +141,7 @@ swtpm_path = '/usr/bin/swtpm' variants: - start_vm: - audit_cmd = ausearch -ts recent -m VIRT_RESOURCE| grep 'tpm-external' + audit_cmd = "cat /var/log/audit/audit.log| grep 'tpm-external'" ausearch_check = 'reason=start.*device="/var/tmp/guest-swtpm.sock".*res=success' - suspend_resume: vm_operate = 'resume' diff --git a/libvirt/tests/src/virtual_device/tpm_device.py b/libvirt/tests/src/virtual_device/tpm_device.py index a546f798946..24b5a4f40f1 100644 --- a/libvirt/tests/src/virtual_device/tpm_device.py +++ b/libvirt/tests/src/virtual_device/tpm_device.py @@ -830,6 +830,12 @@ def check_swtpmpidfile(vm_name, test_stage): return if tpm_model and backend_version != 'default': expect_fail = False + if ausearch_check: + cmd = "truncate -s 0 /var/log/audit/audit.log*" + process.run(cmd, shell=True) + ausearch_ret = process.run(audit_cmd, verbose=True, shell=True, ignore_status=True) + if not ausearch_ret: + test.fail('audit log is not cleaned well.') try: vm.start() except VMStartError as detail: @@ -838,10 +844,6 @@ def check_swtpmpidfile(vm_name, test_stage): return else: test.fail(detail) - if ausearch_check: - process.run("echo > /var/log/audit/audit.log", ignore_status=True) - ausearch_result = process.run(audit_cmd, verbose=True, shell=True) - libvirt.check_result(ausearch_result, expected_match=ausearch_check) if undefine_flag: time.sleep(5) vm.destroy() @@ -946,6 +948,9 @@ def check_swtpmpidfile(vm_name, test_stage): return domid = vm.get_id() check_qemu_cmd_line(vm, vm_name, domid) + if ausearch_check: + ausearch_result = process.run(audit_cmd, verbose=True, shell=True) + libvirt.check_result(ausearch_result, expected_match=ausearch_check) if backend_type == "passthrough": if tpm_real_v == "1.2" and tpm_model == "tpm-crb": expect_fail = True From de3b02a62e50c39df629d7badd645028bdd66cd5 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Fri, 27 Sep 2024 05:22:17 -0400 Subject: [PATCH 0618/1055] Check balloon service in windows guests Signed-off-by: Ming Xie --- v2v/tests/cfg/function_test_esx.cfg | 4 ++-- v2v/tests/src/function_test_esx.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 887b890d568..afa5ebaf34a 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -128,9 +128,9 @@ virtio_win_path = "/usr/share/virtio-win/" os_version = VM_VERSION_WIN_SCHTASKS_V2V_EXAMPLE main_vm = VM_NAME_WIN_SCHTASKS_V2V_EXAMPLE - - OGAC: + - OGAC_balloon: only esx_80 - checkpoint = "ogac" + checkpoint = "ogac_balloon" virtio_win_path = EXPORT_VIRTIO_WIN_PATH_V2V_EXAMPLE variants: - win2022: diff --git a/v2v/tests/src/function_test_esx.py b/v2v/tests/src/function_test_esx.py index f0f386981ea..737d6ce7c29 100644 --- a/v2v/tests/src/function_test_esx.py +++ b/v2v/tests/src/function_test_esx.py @@ -598,7 +598,7 @@ def vm_check(status_error): # Check guest following the checkpoint document after conversion LOG.info('Checking common checkpoints for v2v') - if 'ogac' in checkpoint: + if 'ogac_balloon' in checkpoint: # windows guests will reboot at any time after qemu-ga is # installed. The process cannot be controlled. In order to # don't break vmchecker.run() process, It's better to put @@ -606,7 +606,7 @@ def vm_check(status_error): # check_windows_ogac, it waits until rebooting completes. vmchecker.checker.create_session() if os_type == 'windows': - services = ['qemu-ga'] + services = ['qemu-ga', 'balloon'] virtio_win_env = os.getenv('VIRTIO_WIN') if virtio_win_env and 'rhv-guest-tools' in virtio_win_env: services.append('spice-ga') @@ -804,7 +804,7 @@ def vm_check(status_error): ovirt4_path = os.path.dirname(ovirtsdk4.__file__) dst_ovirt4_path = ovirt4_path + '.bak' os.rename(ovirt4_path, dst_ovirt4_path) - if 'ogac' in checkpoint: + if 'ogac_balloon' in checkpoint: os.environ['VIRTIO_WIN'] = virtio_win_path if os_type == 'linux' and not utils_v2v.multiple_versions_compare(implementation_change_ver) and os.path.isdir(os.getenv('VIRTIO_WIN')): export_path = os.getenv('VIRTIO_WIN') From 41449e908f684943e58f68c5f9450b3fc4de21cc Mon Sep 17 00:00:00 2001 From: lcheng Date: Fri, 27 Sep 2024 20:37:11 +0800 Subject: [PATCH 0619/1055] virsh_domstate: Update the way to kill qemu-kvm Signed-off-by: lcheng --- libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py b/libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py index 14d0350a70c..e5d5a82e3f7 100644 --- a/libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py +++ b/libvirt/tests/src/virsh_cmd/monitor/virsh_domstate.py @@ -201,7 +201,7 @@ def run(test, params, env): if kill_action == "stop_libvirtd": libvirtd.stop() time.sleep(1) - utils_misc.kill_process_by_pattern(vm_name) + process.run('pkill -9 qemu-kvm', ignore_status=True, shell=True) time.sleep(1) libvirtd.restart() elif kill_action == "reboot_vm": From de8ff9e1436a57ef94e7aa57d14da26f18ed43e1 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Sun, 29 Sep 2024 00:03:53 -0400 Subject: [PATCH 0620/1055] Add v2v case about dvs net and correct a mistake Signed-off-by: Ming Xie --- v2v/tests/cfg/function_test_esx.cfg | 5 +++++ v2v/tests/src/function_test_esx.py | 7 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index afa5ebaf34a..67d889ec8b3 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -938,6 +938,11 @@ main_vm = VM_NAME_NO_ENTRY_NETWORKNAME_V2V_EXAMPLE skip_vm_check = yes skip_reason = 'The VM doesn\'t have a network' + - dvs_net_no_portid_connectionid: + only esx_80 + main_vm = VM_NAME_DVS_NET_NO_PORTID_CONNECTIONID_V2V_EXAMPLE + skip_vm_check = yes + skip_reason = 'Bug RHEL-732 is not fixed' variants: - positive_test: status_error = 'no' diff --git a/v2v/tests/src/function_test_esx.py b/v2v/tests/src/function_test_esx.py index 737d6ce7c29..200633592ac 100644 --- a/v2v/tests/src/function_test_esx.py +++ b/v2v/tests/src/function_test_esx.py @@ -598,7 +598,7 @@ def vm_check(status_error): # Check guest following the checkpoint document after conversion LOG.info('Checking common checkpoints for v2v') - if 'ogac_balloon' in checkpoint: + if checkpoint[0].startswith('ogac'): # windows guests will reboot at any time after qemu-ga is # installed. The process cannot be controlled. In order to # don't break vmchecker.run() process, It's better to put @@ -804,9 +804,10 @@ def vm_check(status_error): ovirt4_path = os.path.dirname(ovirtsdk4.__file__) dst_ovirt4_path = ovirt4_path + '.bak' os.rename(ovirt4_path, dst_ovirt4_path) - if 'ogac_balloon' in checkpoint: + if checkpoint[0].startswith('ogac'): os.environ['VIRTIO_WIN'] = virtio_win_path - if os_type == 'linux' and not utils_v2v.multiple_versions_compare(implementation_change_ver) and os.path.isdir(os.getenv('VIRTIO_WIN')): + if os_type == 'linux' and not utils_v2v.multiple_versions_compare(implementation_change_ver) and \ + os.path.isdir(os.getenv('VIRTIO_WIN')): export_path = os.getenv('VIRTIO_WIN') qemu_guest_agent_dir = os.path.join(export_path, qa_path) if not os.path.exists(qemu_guest_agent_dir) and os.access( From 9aba8a0f8cd0385ad8afdfc413ea73d2f3a90555 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Sun, 29 Sep 2024 22:15:33 -0400 Subject: [PATCH 0621/1055] Ignore the numa node without cpu Signed-off-by: liang-cong-red-hat --- .../guest_numa_node_tuning/auto_memory_nodeset_placement.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/auto_memory_nodeset_placement.py b/libvirt/tests/src/numa/guest_numa_node_tuning/auto_memory_nodeset_placement.py index 37501c940c3..5699f101b55 100644 --- a/libvirt/tests/src/numa/guest_numa_node_tuning/auto_memory_nodeset_placement.py +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/auto_memory_nodeset_placement.py @@ -391,8 +391,6 @@ def get_cpus_by_numad_advisory(test_obj): if cpus_from_numactl: cpus_from_numactl = cpus_from_numactl[0].strip().split(' ') cpus_from_numactl = [int(item) for item in cpus_from_numactl] - else: - test_obj.test.error("Can not find node %s's cpus" % nodeset_numad) cpus += cpus_from_numactl test_obj.test.log.debug("The cpus on the node advised by numad: %s", cpus) return sorted(cpus) From 3678c349ff0be62435fcfb3aee314024c678e2bd Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Sun, 29 Sep 2024 22:53:46 -0400 Subject: [PATCH 0622/1055] Allow hugepage memory allocated on only one numa node Signed-off-by: liang-cong-red-hat --- libvirt/tests/src/numa/host_numa/host_numa_info.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/src/numa/host_numa/host_numa_info.py b/libvirt/tests/src/numa/host_numa/host_numa_info.py index 98eeff27d4e..44694e17cd8 100644 --- a/libvirt/tests/src/numa/host_numa/host_numa_info.py +++ b/libvirt/tests/src/numa/host_numa/host_numa_info.py @@ -40,15 +40,10 @@ def _allocate_test(page_num, node_id, page_size): with open("/proc/sys/vm/compact_memory", "w") as memory: memory.write('1') hpc.set_node_num_huge_pages(page_num, node_id, page_size, ignore_error=True) - allocated_num = hpc.get_node_num_huge_pages(node_id, page_size) - if allocated_num < 1: - test_obj.test.cancel("Can not set at least one page " - "with pagesize '%s' on " - "node '%s'" % (page_size, - node_id)) - return allocated_num + return hpc.get_node_num_huge_pages(node_id, page_size) ret = {} + sum_page_num = {} all_nodes = test_obj.online_nodes_withmem allocate_dict = eval(test_obj.params.get('allocate_dict')) hpc = test_setup.HugePageConfig(test_obj.params) @@ -60,9 +55,12 @@ def _allocate_test(page_num, node_id, page_size): test_obj.test.log.debug("To allocate %s %s pages on node %s", allocate_dict[pagesize], pagesize, one_node) allocated_num = _allocate_test(allocate_dict[pagesize], one_node, pagesize) allocated_info.update({pagesize: allocated_num}) + sum_page_num[pagesize] = sum_page_num[pagesize] + allocated_num if sum_page_num.get(pagesize) else allocated_num ret.update({one_node: allocated_info}) test_obj.test.log.debug("Get allocated information for node %s: '%s'", one_node, allocated_info) test_obj.test.log.debug("Get allocated information '%s'", ret) + if not all(sum_page_num.values()): + test_obj.test.cancel("At least one page size memory could not be allocated") test_obj.params['allocate_result'] = ret return ret From 7280415777098dc10926268c9d342a6dd0ed52cc Mon Sep 17 00:00:00 2001 From: Yanqiu Zhang Date: Fri, 27 Sep 2024 12:13:35 -0400 Subject: [PATCH 0623/1055] Add new: Start virtual network with static route Automate VIRT-298910 - [Static route] Start virtual networks with static route defined. Signed-off-by: Yanqiu Zhang --- .../network_static_route.cfg | 12 +++++ .../network_static_route.py | 49 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/network/elements_and_attributes/network_static_route.cfg create mode 100644 libvirt/tests/src/virtual_network/network/elements_and_attributes/network_static_route.py diff --git a/libvirt/tests/cfg/virtual_network/network/elements_and_attributes/network_static_route.cfg b/libvirt/tests/cfg/virtual_network/network/elements_and_attributes/network_static_route.cfg new file mode 100644 index 00000000000..4e47a588a16 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/network/elements_and_attributes/network_static_route.cfg @@ -0,0 +1,12 @@ +- virtual_network.network.static_route: + type = network_static_route + start_vm = "no" + variants: + - start_test: + net_name = "network_def" + net_attrs = {'name': net_name, 'forward': {'mode': 'nat'}, 'ips': [{'dhcp_ranges': {'attrs': {'start': '192.168.120.2', 'end': '192.168.120.254'}}, 'address': '192.168.120.1', 'netmask': '255.255.255.0'}, {'family': 'ipv6', 'address': '2001:db8:ca2:2::1', 'prefix': '64'}], 'routes': [{'address':'192.168.222.0','prefix':'24','gateway':'192.168.120.2'}, {'family':'ipv6','address':'2001:db8:ca2:3::','prefix':'64','gateway':'2001:db8:ca2:2::2'},{'family':'ipv6','address':'2001:db9:4:1::','prefix':'64','gateway':'2001:db8:ca2:2::3','metric':'2'}]} + ipv4_associated_route = '192.168.120.0/24' + ipv4_defined_route = '192.168.222.0/24' + ipv6_associated_route = '2001:db8:ca2:2::/64' + ipv6_defined_routes = "['2001:db8:ca2:3::/64', '2001:db9:4:1::/64']" + diff --git a/libvirt/tests/src/virtual_network/network/elements_and_attributes/network_static_route.py b/libvirt/tests/src/virtual_network/network/elements_and_attributes/network_static_route.py new file mode 100644 index 00000000000..741d253914b --- /dev/null +++ b/libvirt/tests/src/virtual_network/network/elements_and_attributes/network_static_route.py @@ -0,0 +1,49 @@ +import re + +from avocado.utils import process + +from virttest import virsh +from virttest.utils_libvirt import libvirt_network + + +def run(test, params, env): + """ + Test network static route. + """ + net_name = params.get("net_name") + net_attrs = eval(params.get('net_attrs', '{}')) + ipv4_associated_route = params.get("ipv4_associated_route") + ipv4_defined_route = params.get("ipv4_defined_route") + ipv6_associated_route = params.get("ipv6_associated_route") + ipv6_defined_routes = eval(params.get("ipv6_defined_routes")) + + def get_ip_route(bridge, ipv6=False): + """ + get ipv4 or ipv6 route on host for vnet bridge. + + :param ipv6: get ipv6 route or not(ipv4) + :param bridge: vnet bridge name + """ + ip_route_cmd = "ip -6 route" if ipv6 else "ip route" + ip_route_cmd += "|grep %s" % bridge + result = process.run(ip_route_cmd, shell=True, ignore_status=False) + return result + + try: + libvirt_network.create_or_del_network(net_attrs) + virsh.net_dumpxml(net_name, ignore_status=True) + net_info = virsh.net_info(net_name).stdout.strip() + bridge = re.search(r'Bridge:\s+(\S+)', net_info).group(1) + cmd_ret1 = get_ip_route(bridge) + if not re.search(ipv4_associated_route, cmd_ret1.stdout_text): + test.fail("The ip addr associated route '%s' is not in result." % ipv4_associated_route) + if not re.search(ipv4_defined_route, cmd_ret1.stdout_text): + test.fail("The defined static route '%s' is not in result." % ipv4_defined_route) + cmd_ret2 = get_ip_route(bridge, True) + if not re.search(ipv6_associated_route, cmd_ret2.stdout_text): + test.fail("The ipv6 addr associated route '%s' is not in result." % ipv6_associated_route) + for ipv6_def_route in ipv6_defined_routes: + if not re.search(ipv6_def_route, cmd_ret2.stdout_text): + test.fail("The defined ipv6 static route '%s' is not in result." % ipv6_def_route) + finally: + libvirt_network.create_or_del_network(net_attrs, is_del=True) From cba66e9685a593d8c562134c41b240dcc99226e8 Mon Sep 17 00:00:00 2001 From: lcheng Date: Thu, 26 Sep 2024 11:17:28 +0800 Subject: [PATCH 0624/1055] migration: Add 4 cases about keepalive XXX-298208 - [VM migration] p2p migration with default keepalive configuration XXX-298209 - [VM migration] p2p migration with src keepalive disabled XXX-298211 - [VM migration] p2p migration with src and target keepalive disabled XXX-298214 - [VM migration] p2p migration with customized keepalive_* settings Signed-off-by: lcheng --- .../migration_network_data_transport_tls.cfg | 1 + .../migration_with_shared_tpm.cfg | 1 + .../p2p_keepalive/customized_keepalive.cfg | 76 +++++++ .../p2p_keepalive/default_keepalive.cfg | 76 +++++++ .../src_and_dest_keepalive_disabled.cfg | 57 +++++ .../p2p_keepalive/src_keepalive_disabled.cfg | 71 ++++++ .../migration/p2p_keepalive/p2p_keepalive.py | 215 ++++++++++++++++++ provider/migration/base_steps.py | 38 +++- spell.ignore | 1 + 9 files changed, 526 insertions(+), 10 deletions(-) create mode 100644 libvirt/tests/cfg/migration/p2p_keepalive/customized_keepalive.cfg create mode 100644 libvirt/tests/cfg/migration/p2p_keepalive/default_keepalive.cfg create mode 100644 libvirt/tests/cfg/migration/p2p_keepalive/src_and_dest_keepalive_disabled.cfg create mode 100644 libvirt/tests/cfg/migration/p2p_keepalive/src_keepalive_disabled.cfg create mode 100644 libvirt/tests/src/migration/p2p_keepalive/p2p_keepalive.py diff --git a/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls.cfg b/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls.cfg index 16d6ec87753..e085a2bb8f3 100644 --- a/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls.cfg +++ b/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls.cfg @@ -48,6 +48,7 @@ client_cn = "ENTER.YOUR.EXAMPLE.CLIENT_CN" set_remote_libvirtd_log = "yes" libvirtd_file_type = "virtqemud" + remote_file_type = "virtqemud" libvirtd_debug_level = "1" libvirtd_debug_filters = "1:*" check_str_local_log = '['"dir":"/etc/pki/qemu","endpoint":"client","verify-peer":true']' diff --git a/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg index 330781b12de..21b74119b86 100644 --- a/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg +++ b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg @@ -26,6 +26,7 @@ check_str_remote_log = "migration release-lock-outgoing,incoming" set_remote_libvirtd_log = "yes" libvirtd_file_type = "virtqemud" + remote_file_type = "virtqemud" libvirtd_debug_level = "1" libvirtd_debug_filters = "1:*" libvirtd_debug_file = '/var/log/libvirt/virtqemud.log' diff --git a/libvirt/tests/cfg/migration/p2p_keepalive/customized_keepalive.cfg b/libvirt/tests/cfg/migration/p2p_keepalive/customized_keepalive.cfg new file mode 100644 index 00000000000..3bc9bff1697 --- /dev/null +++ b/libvirt/tests/cfg/migration/p2p_keepalive/customized_keepalive.cfg @@ -0,0 +1,76 @@ +- migration.p2p_keepalive.customized_keepalive: + type = p2p_keepalive + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + libvirtd_file_type = "virtqemud" + libvirtd_debug_level = "1" + libvirtd_debug_filters = "1:*" + set_remote_libvirtd_log = "yes" + virsh_migrate_options = "--live --p2p --timeout 2 --timeout-suspend --verbose" + virsh_migrate_extra = "--bandwidth 10" + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + variants: + - with_precopy: + variants: + - desturi_ssh: + migrate_desturi_type = "ssh" + new_ssh_port = "6666" + migrate_desturi_port = "${new_ssh_port}" + conf_on_src = '{"keepalive_interval": "3", "keepalive_count": "3"}' + src_conf_type = "qemu" + conf_on_target = '{r".*keepalive_interval\s*=.*": "keepalive_interval = 2", r".*keepalive_count\s*=.*": "keepalive_count = 4"}' + target_conf_type = "virtqemud" + remote_file_type = "virtqemud" + firewall_rule_on_dest = "ipv4 filter INPUT 0 -p tcp -j DROP --dport ${migrate_desturi_port} -s ${migrate_source_host}" + firewall_rule_on_src = "ipv4 filter INPUT 0 -p tcp -j DROP --sport ${migrate_desturi_port} -s ${migrate_dest_host}" + virsh_migrate_desturi = "qemu+${migrate_desturi_type}://${migrate_dest_host}:${new_ssh_port}/system" + - desturi_tcp: + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + conf_on_src = '{"keepalive_interval": "3", "keepalive_count": "3"}' + src_conf_type = "qemu" + conf_on_target = '{r".*keepalive_interval\s*=.*": "keepalive_interval = 2", r".*keepalive_count\s*=.*": "keepalive_count = 4"}' + target_conf_type = "virtproxyd" + remote_file_type = "virtproxyd" + firewall_rule_on_dest = "ipv4 filter INPUT 0 -p tcp -j DROP --dport ${migrate_desturi_port} -s ${migrate_source_host}" + firewall_rule_on_src = "ipv4 filter INPUT 0 -p tcp -j DROP --sport ${migrate_desturi_port} -s ${migrate_dest_host}" + virsh_migrate_desturi = "qemu+${migrate_desturi_type}://${migrate_dest_host}/system" + variants test_case: + - after_keepalive_timeout: + status_error = "yes" + migrate_again = "yes" + migrate_again_status_error = "no" + expected_event_src = ["lifecycle.*Suspended Migrated", "lifecycle.*Resumed Migrated"] + expected_event_target = ["lifecycle.*: Stopped Destroyed|lifecycle.*: Stopped Failed"] + check_str_local_log = '["countToDeath=3 idle=3", "countToDeath=2 idle=6", "countToDeath=1 idle=9", "countToDeath=0 idle=12", "No response from client.*after 4 keepalive messages in 12 seconds", "internal error: connection closed due to keepalive timeout"]' + check_str_remote_log = '["countToDeath=4 idle=2", "countToDeath=3 idle=4", "countToDeath=2 idle=6", "countToDeath=1 idle=8", "countToDeath=0 idle=10", "No response from client.*after 5 keepalive messages in 10 seconds", "internal error: connection closed due to keepalive timeout"]' + migrate_src_state = "running" + migrate_dest_state = "nonexist" + virsh_migrate_extra_mig_again = " " + action_during_mig = '[{"func": "libvirt_network.setup_firewall_rule", "after_event": "iteration: '1'", "func_param": "params", "need_sleep_time": "4"}]' + - before_keepalive_timeout: + status_error = "no" + check_str_local_log = '["client=.* countToDeath=3 idle=3", "client=.* countToDeath=2 idle=6", "client=.* countToDeath=3 idle=3", "client=.* countToDeath=3 idle=3"]' + check_str_remote_log = '["client=.* countToDeath=4 idle=2", "client=.* countToDeath=3 idle=4", "client=.* countToDeath=4 idle=2", "client=.* countToDeath=4 idle=2"]' + action_during_mig = [{"func": "libvirt_network.setup_firewall_rule", "after_event": "iteration: '1'", "func_param": "params"}, {"func": "libvirt_network.cleanup_firewall_rule", "func_param": "params", "need_sleep_time": "3"}] diff --git a/libvirt/tests/cfg/migration/p2p_keepalive/default_keepalive.cfg b/libvirt/tests/cfg/migration/p2p_keepalive/default_keepalive.cfg new file mode 100644 index 00000000000..11cbc763962 --- /dev/null +++ b/libvirt/tests/cfg/migration/p2p_keepalive/default_keepalive.cfg @@ -0,0 +1,76 @@ +- migration.p2p_keepalive.default_keepalive: + type = p2p_keepalive + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + libvirtd_file_type = "virtqemud" + libvirtd_debug_level = "1" + libvirtd_debug_filters = "1:*" + set_remote_libvirtd_log = "yes" + virsh_migrate_options = "--live --p2p --timeout 2 --timeout-suspend --verbose" + virsh_migrate_extra = "--bandwidth 10" + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + variants: + - with_precopy: + variants: + - desturi_ssh: + migrate_desturi_type = "ssh" + new_ssh_port = "6666" + migrate_desturi_port = ${new_ssh_port} + default_conf_on_src = ["keepalive_interval", "keepalive_count"] + src_conf_type = "qemu" + default_conf_on_target = ["keepalive_interval", "keepalive_count"] + target_conf_type = "virtqemud" + remote_file_type = "virtqemud" + firewall_rule_on_dest = "ipv4 filter INPUT 0 -p tcp -j DROP --dport ${migrate_desturi_port} -s ${migrate_source_host}" + firewall_rule_on_src = "ipv4 filter INPUT 0 -p tcp -j DROP --sport ${migrate_desturi_port} -s ${migrate_dest_host}" + virsh_migrate_desturi = "qemu+${migrate_desturi_type}://${migrate_dest_host}:${migrate_desturi_port}/system" + - desturi_tcp: + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + default_conf_on_src = ["keepalive_interval", "keepalive_count"] + src_conf_type = "qemu" + default_conf_on_target = ["keepalive_interval", "keepalive_count"] + target_conf_type = "virtproxyd" + remote_file_type = "virtproxyd" + firewall_rule_on_dest = "ipv4 filter INPUT 0 -p tcp -j DROP --dport ${migrate_desturi_port} -s ${migrate_source_host}" + firewall_rule_on_src = "ipv4 filter INPUT 0 -p tcp -j DROP --sport ${migrate_desturi_port} -s ${migrate_dest_host}" + virsh_migrate_desturi = "qemu+${migrate_desturi_type}://${migrate_dest_host}/system" + variants keepalive_timeout: + - after_keepalive_timeout: + status_error = "yes" + migrate_again = "yes" + migrate_again_status_error = "no" + expected_event_src = ["lifecycle.*Suspended Migrated", "lifecycle.*Resumed Migrated"] + expected_event_target = ["lifecycle.*: Stopped Failed|lifecycle.*: Stopped Destroyed"] + check_str_local_log = '["countToDeath=5 idle=5", "countToDeath=4 idle=10", "countToDeath=3 idle=15", "countToDeath=2 idle=20", "countToDeath=1 idle=25", "countToDeath=0 idle=30", "No response from client.*after 5 keepalive messages in 30 seconds", "internal error: connection closed due to keepalive timeout"]' + check_str_remote_log = '["countToDeath=5 idle=5", "countToDeath=4 idle=10", "countToDeath=3 idle=15", "countToDeath=2 idle=20", "countToDeath=1 idle=25", "countToDeath=0 idle=30", "No response from client.*after 5 keepalive messages in 30 seconds", "internal error: connection closed due to keepalive timeout"]' + migrate_src_state = "running" + migrate_dest_state = "nonexist" + virsh_migrate_extra_mig_again = " " + action_during_mig = '[{"func": "libvirt_network.setup_firewall_rule", "after_event": "iteration: '1'", "func_param": "params", "need_sleep_time": "5"}]' + - before_keepalive_timeout: + status_error = "no" + check_str_local_log = '["client=.* countToDeath=5 idle=5", "client=.* countToDeath=4 idle=10", "client=.* countToDeath=5 idle=5", "client=.* countToDeath=5 idle=5"]' + check_str_remote_log = '["client=.* countToDeath=5 idle=5", "client=.* countToDeath=4 idle=10", "client=.* countToDeath=5 idle=5", "client=.* countToDeath=5 idle=5"]' + action_during_mig = [{"func": "libvirt_network.setup_firewall_rule", "after_event": "iteration: '1'", "func_param": "params"}, {"func": "libvirt_network.cleanup_firewall_rule", "func_param": "params", "need_sleep_time": "10"}] diff --git a/libvirt/tests/cfg/migration/p2p_keepalive/src_and_dest_keepalive_disabled.cfg b/libvirt/tests/cfg/migration/p2p_keepalive/src_and_dest_keepalive_disabled.cfg new file mode 100644 index 00000000000..3bbc34e1802 --- /dev/null +++ b/libvirt/tests/cfg/migration/p2p_keepalive/src_and_dest_keepalive_disabled.cfg @@ -0,0 +1,57 @@ +- migration.p2p_keepalive.src_and_dest_keepalive_disabled: + type = p2p_keepalive + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + virsh_migrate_options = "--live --p2p --timeout 2 --timeout-suspend --verbose" + virsh_migrate_extra = "--bandwidth 10" + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + status_error = "no" + action_during_mig = '[{"func": "libvirt_network.setup_firewall_rule", "after_event": "iteration: '1'", "func_param": "params", "need_sleep_time": "5"}, {"func": "libvirt_network.cleanup_firewall_rule", "func_param": "params", "need_sleep_time": "30"}]' + test_case = "src_and_dest_keepalive_disabled" + variants: + - with_precopy: + variants: + - desturi_ssh: + migrate_desturi_type = "ssh" + new_ssh_port = "6666" + migrate_desturi_port = "${new_ssh_port}" + conf_on_src = '{"keepalive_interval": "-1"}' + src_conf_type = "qemu" + conf_on_target = '{r".*keepalive_interval\s*=.*": "keepalive_interval = -1"}' + target_conf_type = "virtqemud" + remote_file_type = "virtqemud" + firewall_rule_on_dest = "ipv4 filter INPUT 0 -p tcp -j DROP --dport ${migrate_desturi_port} -s ${migrate_source_host}" + firewall_rule_on_src = "ipv4 filter INPUT 0 -p tcp -j DROP --sport ${migrate_desturi_port} -s ${migrate_dest_host}" + virsh_migrate_desturi = "qemu+${migrate_desturi_type}://${migrate_dest_host}:${new_ssh_port}/system" + - desturi_tcp: + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + conf_on_src = '{"keepalive_interval": "-1"}' + src_conf_type = "qemu" + conf_on_target = '{r".*keepalive_interval\s*=.*": "keepalive_interval = -1"}' + target_conf_type = "virtproxyd" + remote_file_type = "virtproxyd" + firewall_rule_on_dest = "ipv4 filter INPUT 0 -p tcp -j DROP --dport ${migrate_desturi_port} -s ${migrate_source_host}" + firewall_rule_on_src = "ipv4 filter INPUT 0 -p tcp -j DROP --sport ${migrate_desturi_port} -s ${migrate_dest_host}" + virsh_migrate_desturi = "qemu+${migrate_desturi_type}://${migrate_dest_host}/system" diff --git a/libvirt/tests/cfg/migration/p2p_keepalive/src_keepalive_disabled.cfg b/libvirt/tests/cfg/migration/p2p_keepalive/src_keepalive_disabled.cfg new file mode 100644 index 00000000000..61052432426 --- /dev/null +++ b/libvirt/tests/cfg/migration/p2p_keepalive/src_keepalive_disabled.cfg @@ -0,0 +1,71 @@ +- migration.p2p_keepalive.src_keepalive_disabled: + type = p2p_keepalive + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + libvirtd_file_type = "virtqemud" + libvirtd_debug_level = "1" + libvirtd_debug_filters = "1:*" + set_remote_libvirtd_log = "yes" + virsh_migrate_options = "--live --p2p --timeout 2 --timeout-suspend --verbose" + virsh_migrate_extra = "--bandwidth 10" + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + variants: + - with_precopy: + variants: + - desturi_ssh: + migrate_desturi_type = "ssh" + new_ssh_port = "6666" + migrate_desturi_port = "${new_ssh_port}" + conf_on_src = '{"keepalive_interval": "-1"}' + src_conf_type = "qemu" + remote_file_type = "virtqemud" + firewall_rule_on_dest = "ipv4 filter INPUT 0 -p tcp -j DROP --dport ${migrate_desturi_port} -s ${migrate_source_host}" + firewall_rule_on_src = "ipv4 filter INPUT 0 -p tcp -j DROP --sport ${migrate_desturi_port} -s ${migrate_dest_host}" + virsh_migrate_desturi = "qemu+${migrate_desturi_type}://${migrate_dest_host}:${new_ssh_port}/system" + - desturi_tcp: + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + conf_on_src = '{"keepalive_interval": "-1"}' + src_conf_type = "qemu" + remote_file_type = "virtproxyd" + firewall_rule_on_dest = "ipv4 filter INPUT 0 -p tcp -j DROP --dport ${migrate_desturi_port} -s ${migrate_source_host}" + firewall_rule_on_src = "ipv4 filter INPUT 0 -p tcp -j DROP --sport ${migrate_desturi_port} -s ${migrate_dest_host}" + virsh_migrate_desturi = "qemu+${migrate_desturi_type}://${migrate_dest_host}/system" + variants keepalive_timeout: + - after_keepalive_timeout: + status_error = "yes" + migrate_again = "yes" + migrate_again_status_error = "no" + expected_event_src = ["lifecycle.*Suspended Migrated", "lifecycle.*Resumed Migrated"] + expected_event_target = ["lifecycle.*: Stopped Destroyed|lifecycle.*: Stopped Failed"] + check_no_str_local_log = '["No response.*after 5 keepalive messages in 30 seconds"]' + check_str_remote_log = '["countToDeath=5 idle=5", "countToDeath=4 idle=10", "countToDeath=3 idle=15", "countToDeath=2 idle=20", "countToDeath=1 idle=25", "countToDeath=0 idle=30", "No response from client.*after 5 keepalive messages in 30 seconds", "internal error: connection closed due to keepalive timeout"]' + migrate_src_state = "running" + migrate_dest_state = "nonexist" + virsh_migrate_extra_mig_again = " " + action_during_mig = '[{"func": "libvirt_network.setup_firewall_rule", "after_event": "iteration: '1'", "func_param": "params", "need_sleep_time": "5"}]' + - before_keepalive_timeout: + status_error = "no" + check_str_remote_log = '["client=.* countToDeath=5 idle=5", "client=.* countToDeath=4 idle=10", "client=.* countToDeath=5 idle=5", "client=.* countToDeath=5 idle=5"]' + action_during_mig = [{"func": "libvirt_network.setup_firewall_rule", "after_event": "iteration: '1'", "func_param": "params"}, {"func": "libvirt_network.cleanup_firewall_rule", "func_param": "params", "need_sleep_time": "10"}] diff --git a/libvirt/tests/src/migration/p2p_keepalive/p2p_keepalive.py b/libvirt/tests/src/migration/p2p_keepalive/p2p_keepalive.py new file mode 100644 index 00000000000..913cc242f15 --- /dev/null +++ b/libvirt/tests/src/migration/p2p_keepalive/p2p_keepalive.py @@ -0,0 +1,215 @@ +from virttest import libvirt_remote +from virttest import remote +from virttest import utils_config +from virttest import virsh + +from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_config +from virttest.utils_libvirt import libvirt_network + +from provider.migration import base_steps +from provider.migration import migration_base + + +def update_conf_on_src(params, test, local_obj): + """ + Update configure file on source host + + :param params: Dictionary with the test parameters + :param test: test object + :param local_obj: local conf object + """ + default_conf_on_src = eval(params.get("default_conf_on_src", "[]")) + src_conf_type = params.get("src_conf_type") + conf_on_src = eval(params.get("conf_on_src", "{}")) + + if default_conf_on_src: + local_obj.append(libvirt_config.remove_key_in_conf(default_conf_on_src, + conf_type=src_conf_type, + restart_libvirt=True)) + + if conf_on_src: + local_obj.append(libvirt.customize_libvirt_config(conf_on_src, + config_type=src_conf_type, + remote_host=False, + extra_params=params)) + + +def update_conf_on_target(params, test, remote_obj): + """ + Update configure file on target host + + :param params: Dictionary with the test parameters + :param test: test object + :param remote_obj: remote conf object + """ + default_conf_on_target = eval(params.get("default_conf_on_target", "[]")) + target_conf_type = params.get("target_conf_type") + conf_on_target = params.get("conf_on_target") + + if default_conf_on_target: + file_path = utils_config.get_conf_obj(target_conf_type).conf_path + params["file_path"] = file_path + remote_obj.append(libvirt_config.remove_key_in_conf(default_conf_on_target, + conf_type=target_conf_type, + remote_params=params, + restart_libvirt=True)) + if conf_on_target: + file_path = utils_config.get_conf_obj(target_conf_type).conf_path + remote_obj.append(libvirt_remote.update_remote_file(params, + conf_on_target, + file_path)) + + +def add_port_for_ssh(params): + """ + Add new port for sshd + + :param params: Dictionary with the test parameters + """ + new_ssh_port = params.get("new_ssh_port") + server_ip = params.get("server_ip") + server_user = params.get("server_user") + server_pwd = params.get("server_pwd") + + remote_session = remote.remote_login("ssh", server_ip, "22", + server_user, server_pwd, + r'[$#%]') + cmd = "echo 'Port 22' >> /etc/ssh/sshd_config; echo 'Port %s' >> /etc/ssh/sshd_config" % new_ssh_port + remote_session.cmd(cmd) + cmd = "semanage port -a -t ssh_port_t -p tcp %s" % new_ssh_port + remote_session.cmd(cmd) + cmd = "firewall-cmd --add-port=%s/tcp" % new_ssh_port + remote_session.cmd(cmd) + cmd = "systemctl restart sshd" + remote_session.cmd(cmd) + remote_session.close() + + +def del_port_for_ssh(params): + """ + Delete new port for sshd + + :param params: Dictionary with the test parameters + """ + new_ssh_port = params.get("new_ssh_port") + server_ip = params.get("server_ip") + server_user = params.get("server_user") + server_pwd = params.get("server_pwd") + + remote_session = remote.remote_login("ssh", server_ip, "22", + server_user, server_pwd, + r'[$#%]') + cmd = "sed -i '/^Port .*/d' /etc/ssh/sshd_config" + remote_session.cmd(cmd) + cmd = "firewall-cmd --remove-port=%s/tcp" % new_ssh_port + remote_session.cmd(cmd) + cmd = "systemctl restart sshd" + remote_session.cmd(cmd) + remote_session.close() + + +def run(test, params, env): + """ + Test P2P migration with different keepalive configuration. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def setup_test(): + """ + Setup steps + + """ + test.log.info("Setup steps.") + new_ssh_port = params.get("new_ssh_port") + + if new_ssh_port: + add_port_for_ssh(params) + migration_obj.setup_connection() + update_conf_on_src(params, test, local_obj) + update_conf_on_target(params, test, remote_obj) + + def verify_test(): + """ + Verify steps + + """ + migrate_dest_state = params.get("migrate_dest_state") + migrate_src_state = params.get("migrate_src_state") + dest_uri = params.get("virsh_migrate_desturi") + keepalive_timeout = params.get("keepalive_timeout") + + test.log.info("Verify steps.") + if keepalive_timeout == "after_keepalive_timeout": + libvirt_network.cleanup_firewall_rule(params) + func_returns = dict(migration_obj.migration_test.func_ret) + migration_obj.migration_test.func_ret.clear() + test.log.debug("Migration returns function results:%s", func_returns) + if int(migration_obj.migration_test.ret.exit_status) == 0: + test.fail("Expected failed, but migrate successfully.") + if not libvirt.check_vm_state(vm.name, migrate_src_state, uri=migration_obj.src_uri): + test.faile("Check vm state on source host fail.") + dest_vm_list = virsh.dom_list(options="--all --persistent", debug=True, uri=dest_uri) + if migrate_dest_state == "nonexist": + if vm_name in dest_vm_list.stdout.strip(): + test.fail("%s should not exist." % vm_name) + else: + migration_obj.verify_default() + + def cleanup_test(): + """ + Cleanup steps + + """ + test.log.info("Cleanup steps.") + src_conf_type = params.get("src_conf_type") + new_ssh_port = params.get("new_ssh_port") + dest_uri = params.get("virsh_migrate_desturi") + + libvirt_network.cleanup_firewall_rule(params) + if new_ssh_port: + if virsh.is_alive(vm_name, uri=dest_uri): + virsh.destroy(vm_name, uri=dest_uri) + del_port_for_ssh(params) + migration_obj.cleanup_connection() + if remote_obj: + for obj in remote_obj: + del obj + if local_obj: + for obj in local_obj: + libvirt.customize_libvirt_config(None, + config_type=src_conf_type, + remote_host=False, + is_recover=True, + extra_params=params, + config_object=obj) + + test_case = params.get('test_case', '') + migrate_again = "yes" == params.get("migrate_again", "no") + vm_name = params.get("migrate_main_vm") + + virsh_session = None + remote_virsh_session = None + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + remote_obj = [] + local_obj = [] + + try: + setup_test() + if test_case != "src_and_dest_keepalive_disabled": + # Monitor event on source/target host + virsh_session, remote_virsh_session = migration_base.monitor_event(params) + migration_obj.run_migration() + verify_test() + if test_case != "src_and_dest_keepalive_disabled": + migration_base.check_event_output(params, test, virsh_session, remote_virsh_session) + if migrate_again: + migration_obj.run_migration_again() + migration_obj.verify_default() + finally: + cleanup_test() diff --git a/provider/migration/base_steps.py b/provider/migration/base_steps.py index 49c4259033f..c23c9c487ab 100644 --- a/provider/migration/base_steps.py +++ b/provider/migration/base_steps.py @@ -343,9 +343,9 @@ def set_remote_log(self): log_level = self.params.get("libvirtd_debug_level") log_file = self.params.get("libvirtd_debug_file") log_filters = self.params.get("libvirtd_debug_filters") - file_type = self.params.get("libvirtd_file_type") + remote_file_type = self.params.get("remote_file_type") - service_name = utils_libvirtd.Libvirtd(file_type).service_name + service_name = utils_libvirtd.Libvirtd(remote_file_type).service_name file_path = utils_config.get_conf_obj(service_name).conf_path self.test.log.debug("Config file path: %s" % file_path) cmd = "ls {0} || mkdir -p {0}".format(os.path.dirname(log_file)) @@ -365,24 +365,42 @@ def check_local_and_remote_log(self, local_str_in_log=True, remote_str_in_log=Tr otherwise, False """ check_str_local_log = eval(self.params.get("check_str_local_log", "[]")) - check_str_remote_log = self.params.get("check_str_remote_log", "") + check_no_str_local_log = eval(self.params.get("check_no_str_local_log", "[]")) + check_str_remote_log = eval(self.params.get("check_str_remote_log", "[]")) + check_no_str_remote_log = eval(self.params.get("check_no_str_remote_log", "[]")) log_file = self.params.get("libvirtd_debug_file") + runner_on_target = None + if check_str_local_log: for check_log in check_str_local_log: libvirt.check_logfile(check_log, log_file, str_in_log=local_str_in_log) - if check_str_remote_log: - runner_on_target = None + if check_no_str_local_log: + for check_log in check_no_str_local_log: + local_str_in_log = False + libvirt.check_logfile(check_log, log_file, str_in_log=local_str_in_log) + if check_str_remote_log or check_no_str_remote_log: server_ip = self.params.get("server_ip") server_user = self.params.get("server_user", "root") server_pwd = self.params.get("server_pwd") runner_on_target = remote.RemoteRunner(host=server_ip, username=server_user, password=server_pwd) - libvirt.check_logfile(check_str_remote_log, - log_file, - str_in_log=remote_str_in_log, - cmd_parms=self.params, - runner_on_target=runner_on_target) + + if check_str_remote_log: + for check_log in check_str_remote_log: + libvirt.check_logfile(check_log, + log_file, + str_in_log=remote_str_in_log, + cmd_parms=self.params, + runner_on_target=runner_on_target) + if check_no_str_remote_log: + remote_str_in_log = False + for check_log in check_no_str_remote_log: + libvirt.check_logfile(check_log, + log_file, + str_in_log=remote_str_in_log, + cmd_parms=self.params, + runner_on_target=runner_on_target) def remote_add_or_remove_port(self, port, add=True): """ diff --git a/spell.ignore b/spell.ignore index c18394405c4..5d3f8c4683d 100644 --- a/spell.ignore +++ b/spell.ignore @@ -482,6 +482,7 @@ kallsysm kb kconfig kdump +keepalive kexec keycodes keypresses From 79fc4216ded80926876a8e9dacfaf39eb4fb376f Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 30 Sep 2024 22:04:28 +0800 Subject: [PATCH 0625/1055] migration: Add two cases about kill qemu XXX-298187 - [VM migration] kill qemu process during PerformPhase of migration XXX-298189 - [VM migration] kill qemu process during FinishPhase of postcopy migration Signed-off-by: lcheng --- .../kill_qemu_during_finishphase.cfg | 53 ++++++++++++++ .../kill_qemu_during_performphase.cfg | 69 ++++++++++++++++++ .../kill_qemu_during_finishphase.py | 72 +++++++++++++++++++ .../kill_qemu_during_performphase.py | 71 ++++++++++++++++++ 4 files changed, 265 insertions(+) create mode 100644 libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_finishphase.cfg create mode 100644 libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_performphase.cfg create mode 100644 libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_qemu_during_finishphase.py create mode 100644 libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_qemu_during_performphase.py diff --git a/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_finishphase.cfg b/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_finishphase.cfg new file mode 100644 index 00000000000..15a2aa71637 --- /dev/null +++ b/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_finishphase.cfg @@ -0,0 +1,53 @@ +- migration.destructive_operations_around_live_migration.kill_qemu_during_finishphase: + type = kill_qemu_during_finishphase + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + check_network_accessibility_after_mig = "yes" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + status_error = "yes" + migrate_again = "yes" + service_name = "qemu-kvm" + migrate_again_status_error = "no" + variants: + - p2p: + virsh_migrate_options = '--live --p2p --verbose' + - non_p2p: + virsh_migrate_options = '--live --verbose' + variants: + - with_postcopy: + postcopy_options = "--timeout 2 --timeout-postcopy --postcopy --postcopy-bandwidth 10 --bandwidth 10" + variants test_case: + - kill_dest_qemu: + service_on_dst = "yes" + expected_event_src = ["Suspended Post-copy", "Suspended Post-copy Error"] + expected_event_target = ["Stopped Failed"] + action_during_mig = '[{"func": "libvirt.check_vm_state", "func_param": {"vm_name": "${main_vm}", "state": "paused", "reason":"post-copy"}, "need_sleep_time": "5"}, {"func": "libvirt_service.kill_service", "func_param": "params"}]' + expected_dest_state = "nonexist" + expected_src_state = "paused" + - kill_src_qemu: + expected_dest_state = "running" + expected_src_state = "shut off" + expected_event_src = ["Suspended Post-copy Error", "Stopped Failed"] + expected_event_target = ["Resumed Post-copy Error"] + action_during_mig = '[{"func": "libvirt.check_vm_state", "func_param": {"vm_name": "${main_vm}", "state": "paused", "reason":"post-copy"}, "need_sleep_time": "8"}, {"func": "libvirt_service.kill_service", "func_param": "params"}]' diff --git a/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_performphase.cfg b/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_performphase.cfg new file mode 100644 index 00000000000..9af9a89cd43 --- /dev/null +++ b/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_performphase.cfg @@ -0,0 +1,69 @@ +- migration.destructive_operations_around_live_migration.kill_qemu_during_performphase: + type = kill_qemu_during_performphase + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + check_network_accessibility_after_mig = "yes" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + status_error = "yes" + migrate_again = "yes" + service_name = "qemu-kvm" + migrate_again_status_error = "no" + migrate_speed = "10" + simple_disk_check_after_mig = "yes" + variants: + - p2p: + virsh_migrate_options = '--live --p2p --verbose' + - non_p2p: + virsh_migrate_options = '--live --verbose' + variants: + - with_precopy: + variants test_case: + - kill_dest_qemu_before_vm_paused: + service_on_dst = "yes" + expected_event_src = ["migration-iteration"] + expected_event_target = ["lifecycle", "lifecycle.*: Stopped Failed"] + action_during_mig = '[{"func": "libvirt_service.kill_service", "func_param": "params", "need_sleep_time": "1"}]' + expected_dest_state = "nonexist" + expected_src_state = "running" + migrate_speed = "1" + err_msg = "QEMU unexpectedly closed the monitor" + check_disk_on_dest = "no" + virsh_migrate_extra = "--bandwidth 1000" + - kill_dest_qemu_after_vm_paused: + service_on_dst = "yes" + expected_event_src = ["migration-iteration", "lifecycle.*: Suspended Migrated", "lifecycle.*: Resumed Migrated"] + expected_event_target = ["lifecycle", "lifecycle.*: Stopped Failed"] + action_during_mig = '[{"func": "libvirt_service.kill_service", "after_event": "migration-iteration", "func_param": "params"}]' + expected_dest_state = "nonexist" + expected_src_state = "running" + virsh_migrate_extra = "--timeout 2 --timeout-suspend --bandwidth 1000" + err_msg = "QEMU unexpectedly closed the monitor" + - kill_src_qemu: + expected_dest_state = "nonexist" + expected_src_state = "shut off" + expected_event_src = ["migration-iteration", "lifecycle.*: Stopped Failed"] + expected_event_target = ["lifecycle", "lifecycle.*: Stopped Failed"] + action_during_mig = '[{"func": "libvirt_service.kill_service", "after_event": "migration-iteration", "func_param": "params"}]' + virsh_migrate_extra = "--bandwidth 1000" + err_msg = "operation failed: domain is not running" diff --git a/libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_qemu_during_finishphase.py b/libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_qemu_during_finishphase.py new file mode 100644 index 00000000000..456b987069a --- /dev/null +++ b/libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_qemu_during_finishphase.py @@ -0,0 +1,72 @@ +from virttest import virsh + +from virttest.utils_test import libvirt + +from provider.migration import base_steps +from provider.migration import migration_base + + +def run(test, params, env): + """ + This case is to verify that if killing qemu process during FinishPhase of + postcopy migration, migration will fail. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def verify_test(): + """ + Verify migration result + + """ + dest_uri = params.get("virsh_migrate_desturi") + expected_src_state = params.get("expected_src_state") + expected_dest_state = params.get("expected_dest_state") + + func_returns = dict(migration_obj.migration_test.func_ret) + migration_obj.migration_test.func_ret.clear() + test.log.debug("Migration returns function results: %s", func_returns) + if expected_src_state: + if not libvirt.check_vm_state(vm.name, expected_src_state, uri=migration_obj.src_uri): + test.fail("Migrated VM failed to be in %s state at source." % expected_src_state) + if expected_dest_state and expected_dest_state == "nonexist": + virsh.domstate(vm_name, uri=dest_uri, debug=True) + if virsh.domain_exists(vm_name, uri=dest_uri): + test.fail("The domain on target host is found, but expected not") + if expected_src_state == "shut off": + vm.start() + vm.wait_for_login().close() + elif expected_src_state == "paused": + vm.destroy() + vm.start() + vm.wait_for_login().close() + + if expected_dest_state == "running": + virsh.destroy(vm_name, uri=dest_uri) + + vm_name = params.get("migrate_main_vm") + test_case = params.get("test_case", "") + migrate_again = "yes" == params.get("migrate_again", "no") + + virsh_session = None + remote_virsh_session = None + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + setup_test = eval("setup_%s" % test_case) if "setup_%s" % test_case in \ + locals() else migration_obj.setup_connection + migration_test_again = eval("migration_%s_again" % test_case) if "migration_%s_again" % test_case in \ + locals() else migration_obj.run_migration_again + + try: + setup_test() + virsh_session, remote_virsh_session = migration_base.monitor_event(params) + migration_obj.run_migration() + verify_test() + migration_base.check_event_output(params, test, virsh_session, remote_virsh_session) + if migrate_again: + migration_test_again() + migration_obj.verify_default() + finally: + migration_obj.cleanup_connection() diff --git a/libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_qemu_during_performphase.py b/libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_qemu_during_performphase.py new file mode 100644 index 00000000000..6b93af23f58 --- /dev/null +++ b/libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_qemu_during_performphase.py @@ -0,0 +1,71 @@ +from virttest import virsh + +from virttest.utils_test import libvirt + +from provider.migration import base_steps +from provider.migration import migration_base + + +def run(test, params, env): + """ + This case is to verify that if killing qemu process during PerformPhase of + migration, migration will fail. If dst qemu is killed, src qemu will keep + running. If src qemu is killed, dst qemu will be closed. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def verify_test(): + """ + Verify migration result + + """ + dest_uri = params.get("virsh_migrate_desturi") + expected_src_state = params.get("expected_src_state") + expected_dest_state = params.get("expected_dest_state") + + func_returns = dict(migration_obj.migration_test.func_ret) + migration_obj.migration_test.func_ret.clear() + test.log.debug("Migration returns function results: %s", func_returns) + virsh.domstate(vm_name, uri=migration_obj.src_uri, debug=True) + if expected_src_state: + if not libvirt.check_vm_state(vm.name, expected_src_state, uri=migration_obj.src_uri): + test.fail("Migrated VM failed to be in %s state at source." % expected_src_state) + if expected_dest_state and expected_dest_state == "nonexist": + virsh.domstate(vm_name, uri=dest_uri, debug=True) + if virsh.domain_exists(vm_name, uri=dest_uri): + test.fail("The domain on target host is found, but expected not") + # Check disk on source + if test_case == "kill_src_qemu_before_vm_paused": + migration_obj.migration_test.post_migration_check([vm], params) + if expected_src_state == "shut off": + vm.start() + vm.wait_for_login().close() + #migration_base.set_migrate_speed_to_high(params) + + vm_name = params.get("migrate_main_vm") + test_case = params.get("test_case", "") + migrate_again = "yes" == params.get("migrate_again", "no") + + virsh_session = None + remote_virsh_session = None + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + setup_test = eval("setup_%s" % test_case) if "setup_%s" % test_case in \ + locals() else migration_obj.setup_connection + migration_test_again = eval("migration_%s_again" % test_case) if "migration_%s_again" % test_case in \ + locals() else migration_obj.run_migration_again + + try: + setup_test() + virsh_session, remote_virsh_session = migration_base.monitor_event(params) + migration_obj.run_migration() + verify_test() + migration_base.check_event_output(params, test, virsh_session, remote_virsh_session) + if migrate_again: + migration_test_again() + migration_obj.verify_default() + finally: + migration_obj.cleanup_connection() From ccfcf3a535249a8845e87baa98c41f1d270f5635 Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 8 Oct 2024 21:42:02 +0800 Subject: [PATCH 0626/1055] migration: Add case to test pause/resume vm XXX-298197 - [VM migration][async ops] pause/resume vm during migration Signed-off-by: lcheng --- .../pause_resume_vm_during_migration.cfg | 45 +++++++++++++++++++ .../pause_resume_vm_during_migration.py | 31 +++++++++++++ provider/migration/migration_base.py | 18 ++++++++ 3 files changed, 94 insertions(+) create mode 100644 libvirt/tests/cfg/migration/async_ops/pause_resume_vm_during_migration.cfg create mode 100644 libvirt/tests/src/migration/async_ops/pause_resume_vm_during_migration.py diff --git a/libvirt/tests/cfg/migration/async_ops/pause_resume_vm_during_migration.cfg b/libvirt/tests/cfg/migration/async_ops/pause_resume_vm_during_migration.cfg new file mode 100644 index 00000000000..50ea21413cc --- /dev/null +++ b/libvirt/tests/cfg/migration/async_ops/pause_resume_vm_during_migration.cfg @@ -0,0 +1,45 @@ +- migration.async_ops.pause_resume_vm_during_migration: + type = pause_resume_vm_during_migration + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + status_error = "no" + check_network_accessibility_after_mig = "yes" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + migrate_speed = "5" + action_during_mig = [{"func": "virsh.suspend", "after_event": "iteration: '1'", "func_param": {"name": "${main_vm}"}}, {"func": "check_resume", "func_param": "params"}] + variants: + - p2p: + virsh_migrate_options = '--live --p2p --verbose' + - non_p2p: + virsh_migrate_options = '--live --verbose' + variants: + - with_precopy: + expected_event_src = ["lifecycle.*: Suspended Migrated"] + resume_err_msg_src = "cannot acquire state change lock .*held by monitor=remoteDispatchDomainMigratePerform3Params" + resume_err_msg_target = "cannot acquire state change lock .*held by monitor=remoteDispatchDomainMigratePrepare3Params" + - with_postcopy: + postcopy_options = '--postcopy --timeout 5 --timeout-postcopy' + expected_event_src = ["lifecycle.*: Suspended Post-copy"] + resume_err_msg_src = "cannot acquire state change lock .*held by monitor=remoteDispatchDomainMigratePerform3Params" + resume_err_msg_target = "cannot acquire state change lock .*held by monitor=remoteDispatchDomainMigrateFinish3Params" diff --git a/libvirt/tests/src/migration/async_ops/pause_resume_vm_during_migration.py b/libvirt/tests/src/migration/async_ops/pause_resume_vm_during_migration.py new file mode 100644 index 00000000000..75311f3e2c4 --- /dev/null +++ b/libvirt/tests/src/migration/async_ops/pause_resume_vm_during_migration.py @@ -0,0 +1,31 @@ +from provider.migration import base_steps +from provider.migration import migration_base + + +def run(test, params, env): + """ + This case is to verify that during migration, vm: + can be paused by user on src host during PerformPhase of precopy + can't be resumed by user on src/target host during PerformPhase of precopy + can't be paused by user on target host during FinishPhase of postcopy + can't be resumed by user on src host during FinishPhase of postcopy + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + vm_name = params.get("migrate_main_vm") + + virsh_session = None + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + migration_obj.setup_connection() + virsh_session, _ = migration_base.monitor_event(params) + migration_obj.run_migration() + migration_obj.verify_default() + migration_base.check_event_output(params, test, virsh_session) + finally: + migration_obj.cleanup_connection() diff --git a/provider/migration/migration_base.py b/provider/migration/migration_base.py index 2c1b08dd7c6..b88762f2437 100644 --- a/provider/migration/migration_base.py +++ b/provider/migration/migration_base.py @@ -735,3 +735,21 @@ def get_vm_serial_session_on_dest(params): vm_session = migration_obj.vm.wait_for_serial_login(timeout=120) params.update({"vm_session": vm_session}) migration_obj.vm.connect_uri = backup_uri + + +def check_resume(params): + """ + Check resume result + + :param params: dictionary with the test parameter, get vm name, dest uri + and error message. + """ + vm_name = params.get("main_vm") + desturi = params.get("virsh_migrate_desturi") + resume_err_msg_src = params.get("resume_err_msg_src") + resume_err_msg_target = params.get("resume_err_msg_target") + + ret = virsh.resume(vm_name, debug=True) + libvirt.check_result(ret, expected_fails=resume_err_msg_src, check_both_on_error=True) + ret = virsh.resume(vm_name, debug=True, uri=desturi) + libvirt.check_result(ret, expected_fails=resume_err_msg_target, check_both_on_error=True) From 4bc7bdc6f040878e0427b9d6a34a3f4b4604f6a6 Mon Sep 17 00:00:00 2001 From: Julia Graham Date: Thu, 26 Sep 2024 13:49:56 -0400 Subject: [PATCH 0627/1055] boot_order: waiting for the boot.iso file to download --- .../boot_order/boot_from_cdrom_device.py | 14 ++++++++------ .../boot_order/boot_with_multiple_boot_dev.py | 10 ++++++---- .../boot_order/boot_with_multiple_boot_order.py | 10 ++++++---- provider/guest_os_booting/guest_os_booting_base.py | 13 +++++++++++++ 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py index e2f6d7b13d9..d9f7572f3bb 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py @@ -1,21 +1,22 @@ import os import platform -from avocado.utils import download from avocado.utils import process from virttest import data_dir from virttest import remote +from virttest import utils_misc from virttest.libvirt_xml import vm_xml from virttest.libvirt_xml.devices import disk -from provider.guest_os_booting import guest_os_booting_base +from provider.guest_os_booting import guest_os_booting_base as guest_os -def parse_cdroms_attrs(params): +def parse_cdroms_attrs(test, params): """ Parse cdrom devices' attrs + :param test: test object :param params: Dictionary with the test parameters :return: (boot image path, list of cdrom devices' attrs) """ @@ -35,7 +36,8 @@ def parse_cdroms_attrs(params): boot_img_url = os.path.join(repo_url, 'images', 'boot.iso') if os.path.exists(boot_img_path): os.remove(boot_img_path) - download.get_file(boot_img_url, boot_img_path) + if not utils_misc.wait_for(lambda: guest_os.test_file_download(boot_img_url, boot_img_path), 60): + test.fail('Unable to download boot image') return boot_img_path, cdrom_attrs_list @@ -82,7 +84,7 @@ def run(test, params, env): Boot VM from cdrom devices This case covers per-device(cdrom) boot elements and os/boot elements. """ - vm_name = guest_os_booting_base.get_vm(params) + vm_name = guest_os.get_vm(params) status_error = "yes" == params.get("status_error", "no") check_bootable_iso = "yes" == params.get("check_bootable_iso", "no") bootable_patterns = eval(params.get('bootable_patterns', '[]')) @@ -93,7 +95,7 @@ def run(test, params, env): boot_img_path = None try: - boot_img_path, cdrom_attrs_list = parse_cdroms_attrs(params) + boot_img_path, cdrom_attrs_list = parse_cdroms_attrs(test, params) update_vm_xml(vm, params, cdrom_attrs_list) test.log.debug(vm_xml.VMXML.new_from_dumpxml(vm.name)) diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py index 2afb6b432be..11f879312cd 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py @@ -4,10 +4,10 @@ import os -from avocado.utils import download from avocado.utils import process from virttest import data_dir +from virttest import utils_misc from virttest.libvirt_xml import vm_xml from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_test import libvirt @@ -30,10 +30,11 @@ def get_vmxml_with_multiple_boot(params, vm_name): return vmxml -def prepare_device(params, vm_name, bootable_device): +def prepare_device(test, params, vm_name, bootable_device): """ Prepare the device xml based on different test matrix. + :params test: test object :params params: wrapped dict with all parameters :params vm_name: the guest name :params bootable_device: the device expected to boot from @@ -50,7 +51,8 @@ def prepare_device(params, vm_name, bootable_device): cmd = "dnf repolist -v enabled |awk '/Repo-baseurl.*composes.*BaseOS.*os/ {res=$NF} END{print res}'" repo_url = process.run(cmd, shell=True).stdout_text.strip() boot_img_url = os.path.join(repo_url, 'images', 'boot.iso') - download.get_file(boot_img_url, cdrom_path) + if not utils_misc.wait_for(lambda: guest_os.test_file_download(boot_img_url, cdrom_path), 60): + test.fail('Unable to download boot image') else: cdrom_path = os.path.join(data_dir.get_data_dir(), 'images', 'test.iso') libvirt.create_local_disk("file", path=cdrom_path, size="500M", disk_format="raw") @@ -79,7 +81,7 @@ def run(test, params, env): try: test.log.info("TEST_SETUP: prepare a guest with necessary attributes.") - vmxml, disk_image, cdrom_path = prepare_device(params, vm_name, bootable_device) + vmxml, disk_image, cdrom_path = prepare_device(test, params, vm_name, bootable_device) test.log.info("TEST_STEP1: start the guest.") if not vm.is_alive(): vm.start() diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py index 6dc8b2704b9..b3469f6bdd8 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py @@ -4,10 +4,10 @@ import os -from avocado.utils import download from avocado.utils import process from virttest import data_dir +from virttest import utils_misc from virttest.libvirt_xml import vm_xml from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_test import libvirt @@ -18,10 +18,11 @@ file_list = [] -def prepare_device_attrs(params, vm_name, bootable_device): +def prepare_device_attrs(test, params, vm_name, bootable_device): """ Prepare the device xml based on different test matrix. + :params test: test object :params params: wrapped dict with all parameters :params vm_name: the guest name :params bootable_device: the bootable device @@ -45,7 +46,8 @@ def prepare_device_attrs(params, vm_name, bootable_device): cmd = "dnf repolist -v enabled |awk '/Repo-baseurl.*composes.*BaseOS.*os/ {res=$NF} END{print res}'" repo_url = process.run(cmd, shell=True).stdout_text.strip() boot_img_url = os.path.join(repo_url, 'images', 'boot.iso') - download.get_file(boot_img_url, cdrom_path) + if not utils_misc.wait_for(lambda: guest_os.test_file_download(boot_img_url, cdrom_path), 60): + test.fail('Unable to download boot image') else: cdrom_path = os.path.join(data_dir.get_data_dir(), 'images', 'test.iso') libvirt.create_local_disk("file", path=cdrom_path, size="500M", disk_format="raw") @@ -79,7 +81,7 @@ def run(test, params, env): try: test.log.info("TEST_SETUP: prepare a guest with necessary attributes.") - prepare_device_attrs(params, vm_name, bootable_device) + prepare_device_attrs(test, params, vm_name, bootable_device) test.log.info("TEST_STEP1: start the guest.") if not vm.is_alive(): vm.start() diff --git a/provider/guest_os_booting/guest_os_booting_base.py b/provider/guest_os_booting/guest_os_booting_base.py index 2c543952d4e..90c64d62172 100644 --- a/provider/guest_os_booting/guest_os_booting_base.py +++ b/provider/guest_os_booting/guest_os_booting_base.py @@ -2,6 +2,8 @@ from avocado.core import exceptions from avocado.utils import distro +from avocado.utils import download +from avocado.utils import process from virttest import virsh from virttest.libvirt_xml import vm_xml @@ -102,3 +104,14 @@ def check_vm_startup(vm, vm_name, error_msg=None): vm.wait_for_login().close() LOG.debug("Succeed to boot %s", vm_name) return vmxml + + +def test_file_download(url, path): + """ + Returns true if the file could be successfully downloaded + + :param url: source URL + :param path: destination path + """ + download.get_file(url, path) + return process.run('ls -d ' + path, ignore_status="yes").exit_status == 0 From 5c2c8579f2aecbb7298243c48f48d38d5e631cfa Mon Sep 17 00:00:00 2001 From: Julia Graham Date: Tue, 17 Sep 2024 17:28:45 -0400 Subject: [PATCH 0628/1055] Guestvcpus: enable/disable max vcpu by guest agent --- .../cfg/virsh_cmd/domain/virsh_guestvcpus.cfg | 4 + .../src/virsh_cmd/domain/virsh_guestvcpus.py | 175 +++++++++++------- 2 files changed, 108 insertions(+), 71 deletions(-) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_guestvcpus.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_guestvcpus.cfg index 80494b2f72e..9072b8996b1 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_guestvcpus.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_guestvcpus.cfg @@ -8,6 +8,7 @@ take_regular_screendumps="no" vcpus_num = "20" vcpus_placement = "static" + max_test_combine = "" option = "" combine = "" error_msg = [] @@ -26,6 +27,9 @@ option = "--enable" - combine: combine = "yes" + - max_test: + status_error = "no" + max_test_combine = "yes" - error_test: status_error = "yes" variants: diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_guestvcpus.py b/libvirt/tests/src/virsh_cmd/domain/virsh_guestvcpus.py index 2e61860cb46..84b124ba653 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_guestvcpus.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_guestvcpus.py @@ -1,5 +1,6 @@ import logging as log +from avocado.utils import cpu from virttest import virsh from virttest import cpu as cpuutil @@ -19,109 +20,62 @@ def run(test, params, env): The command query or modify state of vcpu in the vm 1. Prepare test environment, start vm with guest agent 2. Perform virsh guestvcpus query/enable/disable operation - 3. Check the cpus in the vm - 4. Recover test environment + 3. Check the vcpu number by virsh command via guest agent + 4. Check the vcpu number within the guest + 5. In combine tests, repeat steps 2-4 + 6. Recover test environment """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vcpus_num = int(params.get("vcpus_num", "20")) vcpus_placement = params.get("vcpus_placement", "static") + max_test_combine = params.get("max_test_combine", "") option = params.get("option", "") combine = params.get("combine", "") - invalid_domain = params.get("invalid_domain", "") - domain_name = params.get("domain_name", "") - invalid_cpulist = params.get("invalid_cpulist", "") status_error = params.get("status_error", "no") - error_msg = eval(params.get('error_msg', '[]')) vcpus_list = "" - offline_vcpus = "" # Back up domain XML vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) vmxml_bakup = vmxml.copy() + # Max test: set vcpus_num to the host online cpu number + if max_test_combine == "yes": + vcpus_num = cpu.online_count() + logging.debug("Host online CPU number: %s", str(vcpus_num)) + try: # Modify vm with static vcpus if vm.is_alive(): vm.destroy() vmxml.placement = vcpus_placement vmxml.set_vm_vcpus(vm_name, vcpus_num, vcpus_num, topology_correction=True) - logging.debug("Define guest with '%s' vcpus" % str(vcpus_num)) + logging.debug("Define guest with '%s' vcpus", str(vcpus_num)) # Start guest agent in vm vm.prepare_guest_agent() - # Normal test: disable/ enable guest vcpus + # Normal test: disable/enable guest vcpus if option and status_error == "no": - for cpu in range(1, vcpus_num): - virsh.guestvcpus(vm_name, str(cpu), option, debug=True) + for vcpu in range(1, vcpus_num): + virsh.guestvcpus(vm_name, str(vcpu), option, debug=True) + check_cpu_count(test, params, env, vcpus_num, option) - # Normal test: combine: --disable 1-max then --enable 1 - if combine == "yes" and status_error == "no": + # Combine: --disable 1-max then --enable + if (max_test_combine == "yes" or combine == "yes") and status_error == "no": vcpus_list = '1' + '-' + str(vcpus_num - 1) option = "--disable" virsh.guestvcpus(vm_name, vcpus_list, option, debug=True) - vcpus_list = '1' - option = "--enable" - virsh.guestvcpus(vm_name, vcpus_list, option, debug=True) - - # Error test: invalid_domain - if invalid_domain == "yes": - vm_name = domain_name - # Error test: invalid_cpulist - if invalid_cpulist == "yes": - if option == "--enable": - vcpus_list = str(vcpus_num) - else: - vcpus_list = '0' + '-' + str(vcpus_num - 1) - ret = virsh.guestvcpus(vm_name, vcpus_list, option) - else: - # Query guest vcpus - ret = virsh.guestvcpus(vm_name) - output = ret.stdout.strip() + check_cpu_count(test, params, env, vcpus_num, option) - # Check test results - if status_error == "yes": - libvirt.check_result(ret, error_msg) - else: - # Check the test result of query - ret_output = dict([item.strip() for item in line.split(":")] - for line in output.split("\n")) + # Max test: --enable 1-max (no change to vcpus_list) + # Normal test: --enable 1 if combine == "yes": - online_vcpus = '0-1' - elif option == "--disable": - online_vcpus = '0' - else: - online_vcpus = '0' + '-' + str(vcpus_num - 1) - - if ret_output["online"] != online_vcpus: - test.fail("Query result is different from" - " the '%s' command." % option) + vcpus_list = '1' - # Check the cpu in guest - session = vm.wait_for_login() - vm_cpu_info = cpuutil.get_cpu_info(session) - session.close() - - if combine == "yes": - online_vcpus = '0,1' - elif option == "--disable": - online_vcpus = '0' - offline_vcpus = '1' + '-' + str(vcpus_num - 1) - else: - online_vcpus = '0' + '-' + str(vcpus_num - 1) - - if offline_vcpus: - if (vm_cpu_info["Off-line CPU(s) list"] != offline_vcpus or - vm_cpu_info["On-line CPU(s) list"] != online_vcpus): - test.fail("CPUs in vm is different from" - " the %s command." % option) - elif vm_cpu_info["On-line CPU(s) list"] != online_vcpus: - test.fail("On-line CPUs in vm is different" - " from the %s command." % option) - else: - logging.debug("lscpu in vm '%s' is: \n '%s'" % - (vm_name, vm_cpu_info)) + option = "--enable" + virsh.guestvcpus(vm_name, vcpus_list, option, debug=True) + check_cpu_count(test, params, env, vcpus_num, option) finally: # Recover VM @@ -129,3 +83,82 @@ def run(test, params, env): vm.destroy(gracefully=False) logging.info("Restoring vm...") vmxml_bakup.sync() + + +def check_cpu_count(test, params, env, vcpus_num, option=""): + """ + Makes any changes necessary for the error test and then + runs the vcpu checks specified in steps 3 and 4 of run() + + 3. Check the vcpu number by virsh command via guest agent + 4. Check the vcpu number within the guest + """ + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + combine = params.get("combine", "") + invalid_domain = params.get("invalid_domain", "") + domain_name = params.get("domain_name", "") + invalid_cpulist = params.get("invalid_cpulist", "") + status_error = params.get("status_error", "no") + error_msg = eval(params.get('error_msg', '[]')) + vcpus_list = "" + offline_vcpus = "" + + # Error test: invalid_domain + if invalid_domain == "yes": + vm_name = domain_name + # Error test: invalid_cpulist + if invalid_cpulist == "yes": + if option == "--enable": + vcpus_list = str(vcpus_num) + else: + vcpus_list = '0' + '-' + str(vcpus_num - 1) + ret = virsh.guestvcpus(vm_name, vcpus_list, option) + else: + # Query guest vcpus + ret = virsh.guestvcpus(vm_name) + output = ret.stdout.strip() + + # Check test results + if status_error == "yes": + libvirt.check_result(ret, error_msg) + else: + # Check the test result of query + ret_output = dict([item.strip() for item in line.split(":")] + for line in output.split("\n")) + if combine == "yes" and option == "--enable": + online_vcpus = '0-1' + elif option == "--disable": + online_vcpus = '0' + else: + # either normal --enable test or max test on the --enable step + online_vcpus = '0' + '-' + str(vcpus_num - 1) + + if ret_output["online"] != online_vcpus: + test.fail("Expected online vcpus to be %s, " + "but found %s." % (online_vcpus, ret_output["online"])) + + # Check the vcpu number within the guest + session = vm.wait_for_login() + vm_cpu_info = cpuutil.get_cpu_info(session) + session.close() + + if combine == "yes" and option == "--enable": + online_vcpus = '0,1' + elif option == "--disable": + online_vcpus = '0' + offline_vcpus = '1' + '-' + str(vcpus_num - 1) + else: + # either normal --enable test or max test on the --enable step + online_vcpus = '0' + '-' + str(vcpus_num - 1) + + if offline_vcpus: + if (vm_cpu_info["Off-line CPU(s) list"] != offline_vcpus or + vm_cpu_info["On-line CPU(s) list"] != online_vcpus): + test.fail("CPUs in vm is different from" + " the `virsh guestvcpus %s` command." % option) + elif vm_cpu_info["On-line CPU(s) list"] != online_vcpus: + test.fail("On-line CPUs in vm is different" + " from the `virsh guestvcpus %s` command." % option) + logging.debug("lscpu in vm '%s' is: \n '%s'", + vm_name, vm_cpu_info) From 4c1852ef304f52a9184e1c6d6f2be8c97b5d1d71 Mon Sep 17 00:00:00 2001 From: hholoubk Date: Thu, 10 Oct 2024 09:45:19 +0200 Subject: [PATCH 0629/1055] Updating the test to calculate necessary target_hugepages based on actual hp size and required VM memory. Therefore some configuration settings are no more necessary. --- .../svirt_umask_files_accessed_by_qemu.cfg | 5 ----- .../svirt_umask_files_accessed_by_qemu.py | 14 ++++---------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/libvirt/tests/cfg/svirt/umask_value/svirt_umask_files_accessed_by_qemu.cfg b/libvirt/tests/cfg/svirt/umask_value/svirt_umask_files_accessed_by_qemu.cfg index 77e57f083fb..f38ae0a6afc 100644 --- a/libvirt/tests/cfg/svirt/umask_value/svirt_umask_files_accessed_by_qemu.cfg +++ b/libvirt/tests/cfg/svirt/umask_value/svirt_umask_files_accessed_by_qemu.cfg @@ -3,10 +3,5 @@ start_vm = "no" umask_value = '027' mem_backing_attrs = {'hugepages': {}} - default_hp_size = 2048 - target_hugepages = 1024 - aarch64: - default_hp_size = 524288 - target_hugepages = 4 s390-virtio: kvm_module_parameters = "hpage=1" diff --git a/libvirt/tests/src/svirt/umask_value/svirt_umask_files_accessed_by_qemu.py b/libvirt/tests/src/svirt/umask_value/svirt_umask_files_accessed_by_qemu.py index a3e9162d987..0aaceab9c30 100644 --- a/libvirt/tests/src/svirt/umask_value/svirt_umask_files_accessed_by_qemu.py +++ b/libvirt/tests/src/svirt/umask_value/svirt_umask_files_accessed_by_qemu.py @@ -32,17 +32,11 @@ def run(test, params, env): shutil.rmtree(hp_path) utils_libvirtd.Libvirtd().restart() - # verify test runs on machine with expected size of hugepages - # and recalculate the target_hugepage if necessary - default_hp_size = int(params.get("default_hp_size", 2048)) - target_hugepages = int(params.get("target_hugepages", 1024)) + # calculate the target_hugepage from VM memory and actual HP size actual_hp_size = avocado_mem.get_huge_page_size() - if actual_hp_size != default_hp_size: - # actual hp size is different that is expected for defined number of hugepages - # as the size is not the main focus of the test, we have to recalculate and replace - new_target_hugepages = int((default_hp_size * target_hugepages) / actual_hp_size) - test.log.warn(f"Default HP size is different than expected. Parameter 'target_hugepagees' was updated: {new_target_hugepages}") - params["target_hugepages"] = new_target_hugepages + target_hugepages = int(vmxml.memory / actual_hp_size) + params["target_hugepages"] = target_hugepages + test.log.debug(f"Requred VM memory {vmxml.memory}, calculated tareget_hugepages: {target_hugepages}") hp_cfg = test_setup.HugePageConfig(params) hp_cfg.set_hugepages() From faa8f2aca69e7c65f39bfc1a171476da6e33d4ff Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Mon, 30 Sep 2024 11:03:17 +0800 Subject: [PATCH 0630/1055] v2v: add new case on --mac Signed-off-by: vwu-vera --- v2v/tests/cfg/function_test_esx.cfg | 44 +++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 67d889ec8b3..852e479022d 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -179,20 +179,40 @@ main_vm = VM_NAME_WIN2019_V2V_EXAMPLE os_version = "win2019" - mac_ip: - checkpoint = 'mac_ip' + only libvirt variants: - - 1_dhcp: - only esx_70 - main_vm = VM_NAME_WIN_1_DHCP_IP_V2V_EXAMPLE - v2v_opts = VM_NAME_WIN_1_DHCP_IP_MAC_CONF_V2V_EXAMPLE + - 3_mac: + only esx_80 + boottype = 3 + variants: + - win2016: + main_vm = VM_NAME_WIN2016_EFI_V2V_EXAMPLE + v2v_opts = VM_NAME_WIN_3_DHCP_IP_MAC_CONF_V2V_EXAMPLE + - win2022: + main_vm = VM_NAME_WIN2022_EFI_V2V_EXAMPLE + v2v_opts = VM_NAME_WIN_3_DHCP_IP_MAC_CONF_V2V_EXAMPLE + - 0_gw: + only esx_80 + boottype = 3 + variants: + - win10: + main_vm = VM_NAME_WIN10_EFI_V2V_EXAMPLE + v2v_opts = VM_NAME_WIN_0_GW_IP_MAC_CONF_V2V_EXAMPLE + - win2025: + main_vm = VM_NAME_WIN2025_EFI_V2V_EXAMPLE + v2v_opts = VM_NAME_WIN_0_GW_IP_MAC_CONF_V2V_EXAMPLE - 1_static: - only esx_70 - main_vm = VM_NAME_WIN_1_STATIC_IP_V2V_EXAMPLE - v2v_opts = VM_NAME_WIN_1_STATIC_IP_MAC_CONF_V2V_EXAMPLE - - 3_dhcp: - only esx_70 - main_vm = VM_NAME_WIN_3_DHCP_IP_V2V_EXAMPLE - v2v_opts = VM_NAME_WIN_3_DHCP_IP_MAC_CONF_V2V_EXAMPLE + only esx_80 + checkpoint = 'mac_ip' + variants: + - win2019: + main_vm = VM_NAME_ESX80_WIN2019_V2V_EXAMPLE + v2v_opts = VM_NAME_WIN_1_STATIC_IP_MAC_CONF_V2V_EXAMPLE_1 + iface_macs = VM_MAC_ADDR_1_STATIC_IP_MAC_CONF_V2V_EXAMPLE_1 + - win2022: + main_vm = VM_NAME_ESX80_WIN2022_V2V_EXAMPLE + v2v_opts = VM_NAME_WIN_1_STATIC_IP_MAC_CONF_V2V_EXAMPLE_2 + iface_macs = VM_MAC_ADDR_1_STATIC_IP_MAC_CONF_V2V_EXAMPLE_2 - vmware_tools: only esx_80 checkpoint = 'vmware_tools' From 336e870829b62efe61b36fd103d1f25480755911 Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 16 Oct 2024 10:28:59 +0800 Subject: [PATCH 0631/1055] migration: Add case about internally launched virtiofs device XXX-301966 - [virtiofs] Migrate guest with internally launched virtiofs device Signed-off-by: lcheng --- ..._with_internally_launched_virtiofs_dev.cfg | 37 +++++++ ...n_with_internally_launched_virtiofs_dev.py | 100 ++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 libvirt/tests/cfg/migration/migration_with_virtiofs/migration_with_internally_launched_virtiofs_dev.cfg create mode 100644 libvirt/tests/src/migration/migration_with_virtiofs/migration_with_internally_launched_virtiofs_dev.py diff --git a/libvirt/tests/cfg/migration/migration_with_virtiofs/migration_with_internally_launched_virtiofs_dev.cfg b/libvirt/tests/cfg/migration/migration_with_virtiofs/migration_with_internally_launched_virtiofs_dev.cfg new file mode 100644 index 00000000000..c08a6b10927 --- /dev/null +++ b/libvirt/tests/cfg/migration/migration_with_virtiofs/migration_with_internally_launched_virtiofs_dev.cfg @@ -0,0 +1,37 @@ +- migration.migration_with_virtiofs.migration_with_internally_launched_virtiofs_dev: + type = migration_with_internally_launched_virtiofs_dev + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + status_error = "no" + migrate_desturi_port = "22" + migrate_desturi_type = "ssh" + virsh_migrate_desturi = "qemu+ssh://${migrate_dest_host}/system" + func_supported_since_libvirt_ver = (10, 5, 0) + vm_attrs = {'mb': {"source_type":"file", 'access_mode': 'shared'}} + dev_type = "filesystem" + mount_tag = "mount_tag1" + mount_dir = "/mnt/${mount_tag}" + test_file = "${mount_dir}/test_file" + fs_dict = {'accessmode':'passthrough', 'type_name': 'mount', 'driver': {'type': 'virtiofs', 'queue':'1024'}, 'source':{'dir': '${mnt_path_name}'}, "target": {'dir': '${mount_tag}'}, 'binary': {'path': '/usr/libexec/virtiofsd', 'xattr': 'on','cache_mode':'none'}} + expect_str = "${mount_tag}.*${mount_dir}" + variants: + - with_precopy: diff --git a/libvirt/tests/src/migration/migration_with_virtiofs/migration_with_internally_launched_virtiofs_dev.py b/libvirt/tests/src/migration/migration_with_virtiofs/migration_with_internally_launched_virtiofs_dev.py new file mode 100644 index 00000000000..798b0604d54 --- /dev/null +++ b/libvirt/tests/src/migration/migration_with_virtiofs/migration_with_internally_launched_virtiofs_dev.py @@ -0,0 +1,100 @@ +import re + +from avocado.utils import process + +from virttest import libvirt_version +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml + +from provider.migration import base_steps + + +def run(test, params, env): + """ + Verify that guest with internally launched virtiofs device can be migrated. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def setup_test(): + """ + Setup steps + + """ + test.log.info("Setup steps.") + vm_attrs = eval(params.get("vm_attrs", "{}")) + fs_dict = eval(params.get("fs_dict", "{}")) + dev_type = params.get("dev_type") + mount_tag = params.get("mount_tag") + mount_dir = params.get("mount_dir") + expect_str = params.get("expect_str") + + migration_obj.setup_connection() + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vmxml.setup_attrs(**vm_attrs) + vmxml.remove_all_device_by_type('tpm') + vmxml.sync() + if not vm.is_alive(): + vm.start() + fs = libvirt_vmxml.create_vm_device_by_type(dev_type, fs_dict) + virsh.attach_device(vm_name, fs.xml, debug=True, ignore_status=False) + + vm_session = vm.wait_for_login() + vm_session.cmd_output_safe(f"mkdir {mount_dir}") + vm_session.cmd_output_safe(f"mount -t virtiofs {mount_tag} {mount_dir}") + output = vm_session.cmd_output("df -h") + vm_session.close() + test.log.debug("output: %s", output) + if not re.search(expect_str, output): + test.fail(f'Expect content "{expect_str}" not in output: {output}') + + def verify_test(): + """ + Verify steps for cases + + """ + test.log.info("Verify steps.") + desturi = params.get("virsh_migrate_desturi") + expect_str = params.get("expect_str") + test_file = params.get("test_file") + mnt_path_name = params.get("mnt_path_name") + + backup_uri, vm.connect_uri = vm.connect_uri, desturi + vm.cleanup_serial_console() + vm.create_serial_console() + vm_session = vm.wait_for_serial_login(timeout=120) + output = vm_session.cmd_output("df -h") + test.log.debug("output: %s", output) + if not re.search(expect_str, output): + test.fail(f'Expect content "{expect_str}" not in output: {output}') + cmd1 = f"dd if=/dev/zero of={test_file} bs=1M count=10; sync" + vm_session.cmd_output(cmd1) + cmd2 = f"md5sum {test_file}" + ret_in_vm = vm_session.cmd_output(cmd2) + test.log.debug("md5sum result: %s", ret_in_vm) + vm_session.close() + vm.connect_uri = backup_uri + + cmd3 = f"md5sum {mnt_path_name}/test_file" + ret_in_host = process.run(cmd3, shell=True, ignore_status=False) + if ret_in_vm.split()[0] != ret_in_host.stdout_text.split()[0]: + test.fail("md5 value in host is different from in vm.") + + migration_obj.verify_default() + + libvirt_version.is_libvirt_feature_supported(params) + vm_name = params.get("migrate_main_vm") + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + setup_test() + migration_obj.run_migration() + verify_test() + finally: + migration_obj.cleanup_connection() From 0e0ccc25f33d9e01f4a8a897208b747c786f942c Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 16 Oct 2024 10:23:00 +0800 Subject: [PATCH 0632/1055] migration: Add case about externally launched virtiofs device XXX-301927 - [virtiofs] Migrate guest with externally launched virtiofs device Signed-off-by: lcheng --- ..._with_externally_launched_virtiofs_dev.cfg | 37 +++++++ ...n_with_externally_launched_virtiofs_dev.py | 102 ++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 libvirt/tests/cfg/migration/migration_with_virtiofs/migration_with_externally_launched_virtiofs_dev.cfg create mode 100644 libvirt/tests/src/migration/migration_with_virtiofs/migration_with_externally_launched_virtiofs_dev.py diff --git a/libvirt/tests/cfg/migration/migration_with_virtiofs/migration_with_externally_launched_virtiofs_dev.cfg b/libvirt/tests/cfg/migration/migration_with_virtiofs/migration_with_externally_launched_virtiofs_dev.cfg new file mode 100644 index 00000000000..a5cb0cb418e --- /dev/null +++ b/libvirt/tests/cfg/migration/migration_with_virtiofs/migration_with_externally_launched_virtiofs_dev.cfg @@ -0,0 +1,37 @@ +- migration.migration_with_virtiofs.migration_with_externally_launched_virtiofs_dev: + type = migration_with_externally_launched_virtiofs_dev + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + status_error = "no" + migrate_desturi_port = "22" + migrate_desturi_type = "ssh" + virsh_migrate_desturi = "qemu+ssh://${migrate_dest_host}/system" + func_supported_since_libvirt_ver = (10, 5, 0) + vm_attrs = {'mb': {"source_type":"file", 'access_mode': 'shared'}} + socket_path = "/vm001-vhost-fs.sock" + dev_type = "filesystem" + mount_tag = "mount_tag1" + mount_dir = "/mnt/${mount_tag}" + fs_dict = {'accessmode':'passthrough', 'type_name': 'mount', 'driver': {'type': 'virtiofs', 'queue':'1024'}, 'source':{'socket': '${socket_path}'}, "target": {'dir': '${mount_tag}'}} + expect_str = "${mount_tag}.*${mount_dir}" + variants: + - with_precopy: diff --git a/libvirt/tests/src/migration/migration_with_virtiofs/migration_with_externally_launched_virtiofs_dev.py b/libvirt/tests/src/migration/migration_with_virtiofs/migration_with_externally_launched_virtiofs_dev.py new file mode 100644 index 00000000000..1634bcc3b1e --- /dev/null +++ b/libvirt/tests/src/migration/migration_with_virtiofs/migration_with_externally_launched_virtiofs_dev.py @@ -0,0 +1,102 @@ +import re + +from avocado.utils import process + +from virttest import libvirt_version +from virttest import remote +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml + +from provider.migration import base_steps + + +def run(test, params, env): + """ + Verify that guest with externally launched virtiofs device can be migrated. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def setup_test(): + """ + Setup steps + + """ + test.log.info("Setup steps.") + mnt_path_name = params.get("mnt_path_name") + socket_path = params.get("socket_path") + vm_attrs = eval(params.get("vm_attrs", "{}")) + fs_dict = eval(params.get("fs_dict", "{}")) + dev_type = params.get("dev_type") + mount_tag = params.get("mount_tag") + mount_dir = params.get("mount_dir") + expect_str = params.get("expect_str") + + cmd1 = f"chcon -t virtd_exec_t /usr/libexec/virtiofsd" + cmd2 = f"mkdir -p {mnt_path_name}" + cmd3 = f"systemd-run /usr/libexec/virtiofsd --socket-path={socket_path} -o source={mnt_path_name}" + multi_cmd1 = f"{cmd1}; {cmd2}; {cmd3}" + process.run(multi_cmd1, shell=True, ignore_status=False) + remote.run_remote_cmd(multi_cmd1, params, ignore_status=False) + cmd4 = f"chcon -t svirt_image_t {socket_path}" + cmd5 = f"chown qemu:qemu {socket_path}" + multi_cmd2 = f"{cmd4}; {cmd5}" + process.run(multi_cmd2, shell=True, ignore_status=False) + remote.run_remote_cmd(multi_cmd2, params, ignore_status=False) + + migration_obj.setup_connection() + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vmxml.setup_attrs(**vm_attrs) + vmxml.remove_all_device_by_type('tpm') + vmxml.sync() + if not vm.is_alive(): + vm.start() + fs = libvirt_vmxml.create_vm_device_by_type(dev_type, fs_dict) + virsh.attach_device(vm_name, fs.xml, debug=True, ignore_status=False) + + vm_session = vm.wait_for_login() + vm_session.cmd_output_safe(f"mkdir {mount_dir}") + vm_session.cmd_output_safe(f"mount -t virtiofs {mount_tag} {mount_dir}") + output = vm_session.cmd_output("df -h") + vm_session.close() + test.log.debug("output: %s", output) + if not re.search(expect_str, output): + test.fail(f'Expect content "{expect_str}" not in output: {output}') + + def verify_test(): + """ + Verify steps for cases + + """ + test.log.info("Verify steps.") + desturi = params.get("virsh_migrate_desturi") + expect_str = params.get("expect_str") + + backup_uri, vm.connect_uri = vm.connect_uri, desturi + vm.cleanup_serial_console() + vm.create_serial_console() + vm_session = vm.wait_for_serial_login(timeout=120) + output = vm_session.cmd_output("df -h") + vm_session.close() + test.log.debug("output: %s", output) + if not re.search(expect_str, output): + test.fail(f'Expect content "{expect_str}" not in output: {output}') + vm.connect_uri = backup_uri + migration_obj.verify_default() + + libvirt_version.is_libvirt_feature_supported(params) + vm_name = params.get("migrate_main_vm") + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + setup_test() + migration_obj.run_migration() + verify_test() + finally: + migration_obj.cleanup_connection() From 7dbe09c87c1691678ffb44500e2388ee40175cf3 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 16 Oct 2024 19:36:33 +0800 Subject: [PATCH 0633/1055] vIOMMU: Fix incorrect disk driver setting issue The value of disk driver will be removed before setting disk xml, so add driver settings in cfg. Signed-off-by: Yingshun Cui --- .../cfg/sriov/vIOMMU/intel_iommu_virtio_device_with_ats.cfg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_virtio_device_with_ats.cfg b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_virtio_device_with_ats.cfg index 37cd11613ff..043be96aa73 100644 --- a/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_virtio_device_with_ats.cfg +++ b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_virtio_device_with_ats.cfg @@ -22,7 +22,8 @@ - scsi_controller: test_devices = ["scsi"] controller_dicts = [{'type': 'scsi', 'model': 'virtio-scsi','driver': {'iommu': 'on', 'ats': 'on'}}] - disk_dict = {'target': {'dev': 'sda', 'bus': 'scsi'}} + disk_driver = {'name': 'qemu', 'type': 'qcow2'} + disk_dict = {'target': {'dev': 'sda', 'bus': 'scsi'}, 'driver': ${disk_driver}} cleanup_ifaces = no - pcie_root_port_from_expander_bus: test_devices = ["Eth", "block"] From 92eb4be592960c123a1a5d138cc0a91ef71aebb3 Mon Sep 17 00:00:00 2001 From: Julia Graham Date: Wed, 16 Oct 2024 19:42:53 -0400 Subject: [PATCH 0634/1055] Virt_admin_logging: create local disk and clear messages log --- .../conf_file/libvirtd_conf/virt_admin_logging.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libvirt/tests/src/daemon/conf_file/libvirtd_conf/virt_admin_logging.py b/libvirt/tests/src/daemon/conf_file/libvirtd_conf/virt_admin_logging.py index 297d360b9b9..edd83f8c06f 100644 --- a/libvirt/tests/src/daemon/conf_file/libvirtd_conf/virt_admin_logging.py +++ b/libvirt/tests/src/daemon/conf_file/libvirtd_conf/virt_admin_logging.py @@ -21,6 +21,7 @@ from virttest.libvirt_xml import vm_xml from virttest.utils_libvirt import libvirt_disk +from virttest.utils_test import libvirt from virttest.staging import service @@ -82,6 +83,10 @@ def create_customized_disk(params): source_dict.update({"file": source_file}) disk_src_dict = {"attrs": source_dict} + libvirt.create_local_disk("file", source_file, 1, disk_format="qcow2") + + cleanup_files.append(source_file) + customized_disk = libvirt_disk.create_primitive_disk_xml( type_name, disk_device, device_target, device_bus, @@ -132,6 +137,11 @@ def run(test, params, env): vm_name = params.get("main_vm") vm = env.get_vm(vm_name) + # Clear log file + log_config_path = params.get("log_file_path") + truncate_log = "truncate -s 0 %s" % log_config_path + process.run(truncate_log, ignore_status=True, shell=True, verbose=True) + # Back up xml file if vm.is_alive(): vm.destroy(gracefully=False) From 10ed26a5632a9416ae054bc8a2ae6b470d4b8ac8 Mon Sep 17 00:00:00 2001 From: Julia Graham Date: Mon, 23 Sep 2024 17:11:27 -0400 Subject: [PATCH 0635/1055] Max_vcpus_topology: ensure that the VM gets correct topology with maximum vcpus --- libvirt/tests/cfg/cpu/vcpu_max_topology.cfg | 28 +++ libvirt/tests/src/cpu/vcpu_max_topology.py | 185 ++++++++++++++++++++ 2 files changed, 213 insertions(+) create mode 100644 libvirt/tests/cfg/cpu/vcpu_max_topology.cfg create mode 100644 libvirt/tests/src/cpu/vcpu_max_topology.py diff --git a/libvirt/tests/cfg/cpu/vcpu_max_topology.cfg b/libvirt/tests/cfg/cpu/vcpu_max_topology.cfg new file mode 100644 index 00000000000..cb82d45e257 --- /dev/null +++ b/libvirt/tests/cfg/cpu/vcpu_max_topology.cfg @@ -0,0 +1,28 @@ +- vcpu.max_topology: + type = vcpu_max_topology + memory = 4194304 + vcpus_placement = "static" + sockets = "" + cores = "" + clusters = "" + variants: + - one_socket: + sockets = "one" + cores = "many" + variants: + - default_clusters: + clusters = "" + - many_clusters: + clusters = "many" + - one_core_per_socket: + sockets = "many" + cores = "one" + clusters = "" + - many_cores_per_socket: + sockets = "many" + cores = "many" + variants: + - default_clusters: + clusters = "" + - many_clusters: + clusters = "many" diff --git a/libvirt/tests/src/cpu/vcpu_max_topology.py b/libvirt/tests/src/cpu/vcpu_max_topology.py new file mode 100644 index 00000000000..2614f1dee6d --- /dev/null +++ b/libvirt/tests/src/cpu/vcpu_max_topology.py @@ -0,0 +1,185 @@ +import logging as log + +from avocado.utils import cpu + +from virttest import cpu as cpuutil +from virttest.libvirt_xml import vm_xml + + +LOG = log.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test that the vm can start with vcpus which is equal to host online cpu number + and vm topology is consistent to those configured. + + Steps: + 1. Configure the vm topology with specified number of sockets, cores, and clusters + 2. Start configured vm with guest agent + 3. Check that the vm setup is consistent with the topology configured + 3a. Check the lscpu output + 3b. Check the kernel file for core id for each vcpu + 3c. Check the vcpu cluster number + 3d. Check the cluster cpu list + """ + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + memory = params.get("memory", "4194304") + vcpus_placement = params.get("vcpus_placement", "static") + sockets_param = params.get("sockets", "") + cores_param = params.get("cores", "") + clusters_param = params.get("clusters", "") + + vcpus_num = 0 + sockets_list = [] + cores_list = [] + clusters_list = [] + + # Back up domain XML + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vmxml_backup = vmxml.copy() + + try: + # Modify vm + if vm.is_alive(): + vm.destroy() + vmxml.placement = vcpus_placement + vmxml.memory = int(memory) + vmxml.current_mem = int(memory) + vmxml.sync() + + # Set vcpus_num to the host online cpu number + vcpus_num = cpu.online_count() + LOG.debug("Host online CPU number: %s", str(vcpus_num)) + + # Setting number of sockets, cores, and clusters + # one_socket case + # cores = vcpus_num // number of clusters + if sockets_param == "one": + sockets_list = [1] + + # many_clusters case + if clusters_param == "many": + # Ensure that vcpus_num is evenly divisible by the number of clusters + clusters_list = [clusters for clusters in [2, 4, 6] if vcpus_num % clusters == 0] + cores_list = [vcpus_num // clusters for clusters in clusters_list] + # default_clusters case + else: + cores_list = [vcpus_num] + + # one_core_per_socket case + elif sockets_param == "many" and cores_param == "one": + sockets_list = [vcpus_num] + cores_list = [1] + + # many_cores_per_socket + # Ensure that vcpus_num is evenly divisible by the number of cores + else: + # many_clusters case + # sockets = vcpus_num // number of cores // number of clusters + if clusters_param == "many": + # defaulting to either 2 or 3 cores + cores = 2 if vcpus_num % 2 == 0 else 3 + clusters_list = [clusters for clusters in [2, 4, 6] if (vcpus_num / cores) % clusters == 0] + cores_list = [cores] * (len(clusters_list)) + sockets_list = [(vcpus_num // cores) // clusters for clusters in clusters_list] + # default_clusters case + # sockets * cores = vcpus_num + else: + cores_list = [cores for cores in [2, 4, 6] if vcpus_num % cores == 0] + sockets_list = [vcpus_num // cores for cores in cores_list] + + if not sockets_list or not cores_list: + test.error("The number of sockets or cores is not valid") + elif (len(cores_list) == 1): + # len(sockets_list) will also be 1 + set_and_check_topology(test, vm, vcpus_num, sockets_list[0], cores_list[0]) + else: + for i, cores in enumerate(cores_list): + if (cores == 0): + continue + if (len(sockets_list) == 1): + if clusters_list: + set_and_check_topology(test, vm, vcpus_num, sockets_list[0], cores, clusters_list[i]) + else: + set_and_check_topology(test, vm, vcpus_num, sockets_list[0], cores) + else: + if (sockets_list[i] == 0): + continue + if clusters_list: + set_and_check_topology(test, vm, vcpus_num, sockets_list[i], cores, clusters_list[i]) + else: + set_and_check_topology(test, vm, vcpus_num, sockets_list[i], cores) + + finally: + # Recover VM + if vm.is_alive(): + vm.destroy(gracefully=False) + LOG.info("Restoring vm...") + vmxml_backup.sync() + + +def set_and_check_topology(test, vm, vcpus_num, sockets, cores, clusters=1): + ''' + Perform steps 2-3 for each vm topology configuration + + :param test: test object + :param vm: defined vm + :param vcpus_num: number of vcpus to set + :param sockets: number of sockets to set + :param cores: number of cores to set + :param clusters: number of clusters to set, default 1 + ''' + vm_xml.VMXML.new_from_dumpxml(vm.name).set_vm_vcpus( + vm.name, + vcpus_num, + sockets=sockets, + cores=cores, + threads=1, + clusters=clusters, + add_topology=True + ) + LOG.debug("Defined guest with '%s' vcpu(s), '%s' socket(s), and '%s' core(s), and '%s' cluster(s)", + str(vcpus_num), str(sockets), str(cores), str(clusters)) + + # Start guest agent in vm and wait for login + vm.prepare_guest_agent() + session = vm.wait_for_login() + + # Check kernel file for core id for each vcpu in the vm + for vcpu in range(vcpus_num): + cmd_coreid = f'cat /sys/devices/system/cpu/cpu{vcpu}/topology/core_id' + ret_coreid = session.cmd_output(cmd_coreid).strip() + if (str(vcpu) != ret_coreid): + test.fail("In the vm kernel file, the core id for vcpu %s should not be %s" % (vcpu, ret_coreid)) + + # Check vcpu cluster number + cmd_clusterid = 'cat /sys/devices/system/cpu/cpu*/topology/cluster_id | sort | uniq -c | wc -l' + ret_clusterid = session.cmd_output(cmd_clusterid).strip() + # The result should be equal to sockets * clusters + if (str(sockets * clusters) != ret_clusterid): + test.fail("In the vm kernel file, the vcpu cluster number should be %s, not %s" % (str(sockets * clusters), ret_clusterid)) + + # Check cluster cpu list + cmd_cluster_cpu_list = 'cat /sys/devices/system/cpu/cpu*/topology/cluster_cpus_list | sort | uniq -c | wc -l' + ret_cluster_cpu_list = session.cmd_output(cmd_cluster_cpu_list).strip() + # The result should be equal to sockets * clusters + if (str(sockets * clusters) != ret_cluster_cpu_list): + test.fail("In the vm kernel file, the cluster cpu list should be %s, not %s" % (str(sockets * clusters), ret_cluster_cpu_list)) + + # Check lscpu output within the vm is consistent with the topology configured + lscpu_output = cpuutil.get_cpu_info(session) + # get_cpu_info() should close the session + session.close() + lscpu_check_fail = "The configured topology is not consistent with the lscpu output within the vm for " + if (str(vcpus_num) != lscpu_output["CPU(s)"]): + test.fail(lscpu_check_fail + "CPU(s)") + elif (('0' + '-' + str(vcpus_num - 1)) != lscpu_output["On-line CPU(s) list"]): + test.fail(lscpu_check_fail + "on-line CPU(s) list") + elif ("1" != lscpu_output["Thread(s) per core"]): + test.fail(lscpu_check_fail + "thread(s) per core") + elif (str(sockets) != lscpu_output["Socket(s)"]): + test.fail(lscpu_check_fail + "socket(s)") + elif (str(cores * clusters) != lscpu_output["Core(s) per socket"]): + test.fail(lscpu_check_fail + "core(s) per socket") From 2264d1eb167dd6a5aa79ee56a43d9a7c18f7a43e Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 22 Oct 2024 03:24:46 -0400 Subject: [PATCH 0636/1055] iface_network: select iface model on s390x On s390x, select virtio model. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/virtual_network/iface_network.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_network/iface_network.cfg b/libvirt/tests/cfg/virtual_network/iface_network.cfg index 3b3f7efa6ff..3574082566d 100644 --- a/libvirt/tests/cfg/virtual_network/iface_network.cfg +++ b/libvirt/tests/cfg/virtual_network/iface_network.cfg @@ -328,7 +328,7 @@ portgroup_bandwidth_inbound = "{'average':'1000','peak':'5000','burst':'5120'} {'average':'500','peak':'2000','burst':'2560'}" portgroup_bandwidth_outbound = "{'average':'1000','peak':'5000','burst':'5120'} {'average':'128','peak':'256','burst':'256'}" iface_model = "rtl8139" - aarch64: + aarch64, s390-virtio: iface_model = "virtio" variants: - default_portgroup: From 7fc1c2842d2b6040fa3e19609653b712131fa0fa Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 9 Oct 2024 09:16:00 +0800 Subject: [PATCH 0637/1055] migration: Add case about destroy vm XXX-298199 - [VM migration][async ops] destroy vm during PerformPhase of migration Signed-off-by: lcheng --- .../destroy_vm_during_performphase.cfg | 65 +++++++++++++++++++ .../destroy_vm_during_performphase.py | 53 +++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 libvirt/tests/cfg/migration/async_ops/destroy_vm_during_performphase.cfg create mode 100644 libvirt/tests/src/migration/async_ops/destroy_vm_during_performphase.py diff --git a/libvirt/tests/cfg/migration/async_ops/destroy_vm_during_performphase.cfg b/libvirt/tests/cfg/migration/async_ops/destroy_vm_during_performphase.cfg new file mode 100644 index 00000000000..a31660f2cf8 --- /dev/null +++ b/libvirt/tests/cfg/migration/async_ops/destroy_vm_during_performphase.cfg @@ -0,0 +1,65 @@ +- migration.async_ops.destroy_vm_during_performphase: + type = destroy_vm_during_performphase + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + check_network_accessibility_after_mig = "yes" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + status_error = "yes" + migrate_again = "yes" + migrate_again_status_error = "no" + variants: + - p2p: + virsh_migrate_options = '--live --p2p --verbose' + - non_p2p: + virsh_migrate_options = '--live --verbose' + variants: + - with_precopy: + variants: + - destroy_dst_vm_before_vm_paused: + virsh_migrate_extra = "--bandwidth 1" + expected_event_src = ["migration-iteration"] + expected_event_target = ["lifecycle.*Stopped Destroyed"] + expected_dest_state = "nonexist" + expected_src_state = "running" + action_during_mig = [{"func": "virsh.destroy", "after_event": "iteration: '1'", "func_param": {"name": "${main_vm}", "uri": "${virsh_migrate_desturi}"}, "need_sleep_time": "1"}] + err_msg = "domain is not running|Unable to read from socket: Connection reset by peer|domain.* is not processing incoming migration" + virsh_migrate_extra_mig_again = " " + - destroy_dst_vm_after_vm_paused: + migrate_speed = "10" + action_during_mig = [{"func": "virsh.destroy", "after_event": "Suspended Migrated", "func_param": {"name": "${main_vm}", "uri": "${virsh_migrate_desturi}"}}] + virsh_migrate_extra = "--timeout 2 --timeout-suspend" + expected_event_src = ["lifecycle.*Suspended Migrated", "lifecycle.*Resumed Migrated"] + expected_event_target = ["lifecycle.*Stopped Destroyed"] + expected_dest_state = "nonexist" + expected_src_state = "running" + err_msg = "domain is no longer running|Unable to read from socket: Connection reset by peer|domain.* is not processing incoming migration" + - destroy_src_vm: + migrate_speed = "10" + virsh_migrate_extra = "--timeout 2 --timeout-suspend" + expected_event_src = ["lifecycle.*Stopped Destroyed"] + expected_event_target = ["lifecycle.*Started Migrated", "lifecycle.*Stopped Failed"] + expected_dest_state = "nonexist" + expected_src_state = "shut off" + action_during_mig = [{"func": "virsh.destroy", "after_event": "iteration: '1'", "func_param": {"name": "${main_vm}"}}] + err_msg = "domain is not running" diff --git a/libvirt/tests/src/migration/async_ops/destroy_vm_during_performphase.py b/libvirt/tests/src/migration/async_ops/destroy_vm_during_performphase.py new file mode 100644 index 00000000000..76659b751fa --- /dev/null +++ b/libvirt/tests/src/migration/async_ops/destroy_vm_during_performphase.py @@ -0,0 +1,53 @@ +from virttest import virsh + +from virttest.utils_test import libvirt + +from provider.migration import base_steps +from provider.migration import migration_base + + +def run(test, params, env): + """ + This case is to verify that if destroying vm during PerformPhase of precopy + migration, migration will fail. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def verify_test(): + """ + Verify steps + """ + expected_dest_state = params.get("expected_dest_state") + expected_src_state = params.get("expected_src_state") + dest_uri = params.get("virsh_migrate_desturi") + + test.log.info("Verify steps.") + if not libvirt.check_vm_state(vm.name, expected_src_state, uri=migration_obj.src_uri): + test.faile("Check vm state on source host fail.") + dest_vm_list = virsh.dom_list(options="--all --persistent", debug=True, uri=dest_uri) + if expected_dest_state == "nonexist": + if vm_name in dest_vm_list.stdout.strip(): + test.fail("%s should not exist." % vm_name) + + vm_name = params.get("migrate_main_vm") + migrate_again = "yes" == params.get("migrate_again", "no") + + virsh_session = None + remote_virsh_session = None + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + migration_obj.setup_connection() + virsh_session, remote_virsh_session = migration_base.monitor_event(params) + migration_obj.run_migration() + verify_test() + if migrate_again: + migration_obj.run_migration_again() + migration_obj.verify_default() + migration_base.check_event_output(params, test, virsh_session, remote_virsh_session) + finally: + migration_obj.cleanup_connection() From 25371b800cc34b4747c5d166a8e08c2f6fafec90 Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 22 Oct 2024 15:30:53 +0800 Subject: [PATCH 0638/1055] migration: Add case to test migrate vm again XXX-298375 - [VM migration][async ops] migrate vm again during migration Signed-off-by: lcheng --- .../migrate_vm_again_during_migration.cfg | 37 +++++++++++++++++++ .../migrate_vm_again_during_migration.py | 23 ++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 libvirt/tests/cfg/migration/async_ops/migrate_vm_again_during_migration.cfg create mode 100644 libvirt/tests/src/migration/async_ops/migrate_vm_again_during_migration.py diff --git a/libvirt/tests/cfg/migration/async_ops/migrate_vm_again_during_migration.cfg b/libvirt/tests/cfg/migration/async_ops/migrate_vm_again_during_migration.cfg new file mode 100644 index 00000000000..886f17248d0 --- /dev/null +++ b/libvirt/tests/cfg/migration/async_ops/migrate_vm_again_during_migration.cfg @@ -0,0 +1,37 @@ +- migration.async_ops.migrate_vm_again_during_migration: + type = migrate_vm_again_during_migration + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + status_error = "no" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + migrate_speed = "20" + do_migration_during_mig = "yes" + action_during_mig = [{"func": "do_migration", "after_event": "iteration: '1'", "func_param": "params"}] + status_error_during_mig = "yes" + err_msg_during_mig = "another migration job is already running for domain" + variants: + - p2p: + virsh_migrate_options = '--live --p2p --verbose' + - non_p2p: + virsh_migrate_options = '--live --verbose' diff --git a/libvirt/tests/src/migration/async_ops/migrate_vm_again_during_migration.py b/libvirt/tests/src/migration/async_ops/migrate_vm_again_during_migration.py new file mode 100644 index 00000000000..77024c3184e --- /dev/null +++ b/libvirt/tests/src/migration/async_ops/migrate_vm_again_during_migration.py @@ -0,0 +1,23 @@ +from provider.migration import base_steps + + +def run(test, params, env): + """ + To verify that libvirt can report clear error when migrating vm again + before the last migration completes. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + vm_name = params.get("migrate_main_vm") + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + migration_obj.setup_connection() + migration_obj.run_migration() + migration_obj.verify_default() + finally: + migration_obj.cleanup_connection() From ec05d07b5fd44f88abcd2895a932cf85e61bf92a Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 22 Oct 2024 04:08:21 -0400 Subject: [PATCH 0639/1055] iface_stat: fix test on s390x 1. No ACPI, remove from definition 2. Our domain uses security driver 'dac' which is not available for unprivileged users. Remove it. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/virtual_network/iface_stat.cfg | 2 ++ libvirt/tests/src/virtual_network/iface_stat.py | 1 + 2 files changed, 3 insertions(+) diff --git a/libvirt/tests/cfg/virtual_network/iface_stat.cfg b/libvirt/tests/cfg/virtual_network/iface_stat.cfg index 9694b64722c..ec031c55329 100644 --- a/libvirt/tests/cfg/virtual_network/iface_stat.cfg +++ b/libvirt/tests/cfg/virtual_network/iface_stat.cfg @@ -22,3 +22,5 @@ - macvtap: func_supported_since_libvirt_ver = (9, 2, 0) iface_attrs = {'acpi': {'index': '5'}, 'target': {'dev': tap_name, 'managed': 'no'}, 'model': 'virtio', 'type_name': 'ethernet'} + s390-virtio: + iface_attrs = {'target': {'dev': tap_name, 'managed': 'no'}, 'model': 'virtio', 'type_name': 'ethernet'} diff --git a/libvirt/tests/src/virtual_network/iface_stat.py b/libvirt/tests/src/virtual_network/iface_stat.py index 8c62774fa72..18c4553f87a 100644 --- a/libvirt/tests/src/virtual_network/iface_stat.py +++ b/libvirt/tests/src/virtual_network/iface_stat.py @@ -187,6 +187,7 @@ def _collect_and_compare_stat(vm_name, session, **virsh_args): unpr_vmxml.del_device('interface', by_tag=True) libvirt_vmxml.modify_vm_device(unpr_vmxml, 'interface', iface_attrs) + unpr_vmxml.del_seclabel(by_attr=[('model', 'dac')]) network_base.define_vm_for_unprivileged_user(unpr_user, unpr_vmxml) unpr_vm_name = unpr_vmxml.vm_name From 855e516c465e0d5bae91312e9b42e67ed3c2e741 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 22 Oct 2024 09:13:47 +0800 Subject: [PATCH 0640/1055] vIOMMU: Add a test about driver load/unload This PR adds: VIRT-301883 - [vIOMMU] Test driver load/unload (disable/enable) Signed-off-by: Yingshun Cui --- .../cfg/sriov/vIOMMU/viommu_unload_driver.cfg | 27 ++++ .../src/sriov/vIOMMU/viommu_unload_driver.py | 138 ++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 libvirt/tests/cfg/sriov/vIOMMU/viommu_unload_driver.cfg create mode 100644 libvirt/tests/src/sriov/vIOMMU/viommu_unload_driver.py diff --git a/libvirt/tests/cfg/sriov/vIOMMU/viommu_unload_driver.cfg b/libvirt/tests/cfg/sriov/vIOMMU/viommu_unload_driver.cfg new file mode 100644 index 00000000000..59aa9c11aea --- /dev/null +++ b/libvirt/tests/cfg/sriov/vIOMMU/viommu_unload_driver.cfg @@ -0,0 +1,27 @@ +- vIOMMU.unload_driver: + type = viommu_unload_driver + start_vm = "no" + + variants: + - virtio: + only q35, aarch64 + func_supported_since_libvirt_ver = (8, 3, 0) + iommu_dict = {'model': 'virtio'} + - intel: + only q35 + start_vm = "yes" + enable_guest_iommu = "yes" + iommu_dict = {'model': 'intel', 'driver': {'intremap': 'on', 'caching_mode': 'on', 'eim': 'on', 'iotlb': 'on', 'aw_bits': '48'}} + - smmuv3: + only aarch64 + func_supported_since_libvirt_ver = (5, 5, 0) + iommu_dict = {'model': 'smmuv3'} + variants: + - virtio_interface: + variants: + - vhost_on: + interface_driver_name = "vhost" + - vhost_off: + interface_driver_name = "qemu" + interface_driver = {'driver_attr': {'name': '${interface_driver_name}', 'iommu': 'on'}} + iface_dict = {'type_name': 'network', 'model': 'virtio', 'driver': ${interface_driver}, 'source': {'network': 'default'}} diff --git a/libvirt/tests/src/sriov/vIOMMU/viommu_unload_driver.py b/libvirt/tests/src/sriov/vIOMMU/viommu_unload_driver.py new file mode 100644 index 00000000000..f943b838e00 --- /dev/null +++ b/libvirt/tests/src/sriov/vIOMMU/viommu_unload_driver.py @@ -0,0 +1,138 @@ +import os +import time + +from avocado.utils import crypto +from avocado.utils import process + +from virttest import data_dir +from virttest import utils_misc +from virttest import utils_net + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml + +from provider.viommu import viommu_base + + +def run(test, params, env): + """ + Verify the vm with iommu enabled interface work properly + after loading/unloading the driver. + """ + def all_threads_done(threads): + """ + Check whether all threads have finished + """ + for thread in threads: + if thread.is_alive(): + return False + else: + continue + return True + + def all_threads_alive(threads): + """ + Check whether all threads is alive + """ + for thread in threads: + if not thread.is_alive(): + return False + else: + continue + return True + + cleanup_ifaces = "yes" == params.get("cleanup_ifaces", "yes") + iommu_dict = eval(params.get('iommu_dict', '{}')) + filesize = int(params.get("filesize", 512)) + transfer_timeout = int(params.get("transfer_timeout", 1000)) + + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + + test_obj = viommu_base.VIOMMUTest(vm, test, params) + + try: + test.log.info("TEST_SETUP: Update VM XML.") + test_obj.setup_iommu_test(iommu_dict=iommu_dict, + cleanup_ifaces=cleanup_ifaces) + + iface_dict = test_obj.parse_iface_dict() + if cleanup_ifaces: + libvirt_vmxml.modify_vm_device( + vm_xml.VMXML.new_from_dumpxml(vm.name), + "interface", iface_dict) + + test.log.info("TEST_STEP: Start the VM.") + vm.start() + vm_session = vm.wait_for_login() + test.log.debug(vm_xml.VMXML.new_from_dumpxml(vm.name)) + + test.log.info("TEST_STEP: Get interface driver.") + ethname = utils_net.get_linux_ifname(vm_session, vm.get_mac_address(0)) + output = vm_session.cmd_output(f"readlink -f /sys/class/net/{ethname}/device/driver") + nic_driver = os.path.basename(output) + + test.log.info("TEST_STEP: Prepare file on host and guest.") + tmp_dir = data_dir.get_tmp_dir() + host_path = os.path.join(tmp_dir, "host_file_%s" % + utils_misc.generate_random_string(8)) + guest_path = os.path.join("/home", "guest_file_%s" % + utils_misc.generate_random_string(8)) + cmd = "dd if=/dev/zero of=%s bs=1M count=%d" % (host_path, filesize) + process.run(cmd) + file_checksum = crypto.hash_file(host_path, algorithm="md5") + vm.copy_files_to(host_path, guest_path, timeout=transfer_timeout) + if vm_session.cmd_status("md5sum %s | grep %s" % + (guest_path, file_checksum)): + test.cancel("File MD5SUMs changed after copy to guest") + + test.log.info("TEST_STEP: Transfer files between host and guest.") + threads = [] + file_paths = [] + host_file_paths = [] + for sess_index in range(int(params.get("sessions_num", "5"))): + sess_path = os.path.join("/home", "dst-%s" % sess_index) + host_sess_path = os.path.join(tmp_dir, "dst-%s" % sess_index) + thread1 = utils_misc.InterruptedThread( + vm.copy_files_to, (host_path, sess_path), + {"timeout": transfer_timeout}) + + thread2 = utils_misc.InterruptedThread( + vm.copy_files_from, (guest_path, host_sess_path), + {"timeout": transfer_timeout}) + thread1.start() + threads.append(thread1) + thread2.start() + threads.append(thread2) + file_paths.append(sess_path) + host_file_paths.append(host_sess_path) + + utils_misc.wait_for(lambda: all_threads_alive(threads), 60, 10, 1, text="check if all threads are alive") + time.sleep(5) + + test.log.info("TEST_STEP: Unload and load the driver.") + vm.cleanup_serial_console() + vm.create_serial_console() + vm_serial = vm.wait_for_serial_login(timeout=120) + while not all_threads_done(threads): + vm_serial.cmd("modprobe -r %s" % nic_driver, timeout=120) + time.sleep(2) + vm_serial.cmd("modprobe %s" % nic_driver, timeout=120) + time.sleep(2) + + for copied_file in file_paths: + if vm_serial.cmd_status("md5sum %s | grep %s" % (copied_file, file_checksum)): + test.fail("Guest file MD5SUMs changed after copying %s" % copied_file) + for copied_file in host_file_paths: + if process.run("md5sum %s | grep %s" % + (copied_file, file_checksum), shell=True, verbose=True, + ignore_status=True).exit_status: + test.fail("Host file MD5SUMs changed after copying %s" % copied_file) + + finally: + test.log.info("TEST_TEARDOWN: Cleanup the env.") + for thread in threads: + thread.join() + for copied_file in host_file_paths: + process.system("rm -rf %s" % copied_file) + test_obj.teardown_iommu_test() From 66b5a82c6a5179e79761ff17a38e6ca3e01c53a2 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Tue, 22 Oct 2024 05:51:46 -0400 Subject: [PATCH 0641/1055] Add case update of net-update: - VIRT-298984 - [net-update] Add/delete dns section (dns-srv dns-txt dns-host) by net-update Signed-off-by: Haijiao Zhao --- .../network/net_update_dns.cfg | 37 +++++++ .../virtual_network/network/net_update_dns.py | 100 ++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/network/net_update_dns.cfg create mode 100644 libvirt/tests/src/virtual_network/network/net_update_dns.py diff --git a/libvirt/tests/cfg/virtual_network/network/net_update_dns.cfg b/libvirt/tests/cfg/virtual_network/network/net_update_dns.cfg new file mode 100644 index 00000000000..b33c0aa12b1 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/network/net_update_dns.cfg @@ -0,0 +1,37 @@ +- virtual_network.network.net_update_dns: + type = net_update_dns + start_vm = no + timeout = 240 + host_iface = + dns_host = {'host': {'host_ip': '192.168.10.2', 'hostnames': [{'hostname': 'myhost'}, {'hostname': 'myhostalias'}]}} + dns_txt = {'txt': {'name': 'example', 'value': 'example value'}} + dns_srv = {'srv': {'service': 'name', 'protocol': 'tcp', 'domain': 'test-domain-name', 'target': 'englab.nay.redhat.com', 'port': '1024', 'priority': '10', 'weight': '10'}} + dns_attrs = {**${dns_host}, **${dns_txt}, **${dns_srv}} + func_supported_since_libvirt_ver = (10, 6, 0) + variants dns_ele: + - dns-txt: + variants: + - default: + update_xml = '''''''' + update_attrs = {'name': 'example', 'value': 'new value'} + conf_val = txt-record=example,new value + - incomplete: + status_error = yes + err_msg = Failed to update network + variants: + - no_value: + update_xml = '''''''' + - no_name: + update_xml = '''''''' + - dns-host: + variants: + - default: + update_attrs = {'host_ip': '192.168.10.2', 'hostnames': [{'hostname': 'myserver'}, {'hostname': 'my_new_server'}, {'hostname': 'my_new_dhcp_server'}]} + conf_val = '192.168.10.2\s+myserver\s+my_new_server\s+my_new_dhcp_server' + - not_match: + status_error = yes + err_msg = Failed to update network + update_attrs = {'host_ip': '192.168.10.5', 'hostnames': ['myhost', 'myhostalias']} + post_check = check_pid_not_change + variants operation: + - modify: diff --git a/libvirt/tests/src/virtual_network/network/net_update_dns.py b/libvirt/tests/src/virtual_network/network/net_update_dns.py new file mode 100644 index 00000000000..10deb8a97e9 --- /dev/null +++ b/libvirt/tests/src/virtual_network/network/net_update_dns.py @@ -0,0 +1,100 @@ +import logging +import re + +from avocado.utils import process +from virttest import libvirt_version +from virttest import utils_net +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.network_xml import DNSXML +from virttest.libvirt_xml.network_xml import NetworkXML +from virttest.utils_test import libvirt + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + 'net_update_dns') + + +def check_pid_not_change(test, target_pids): + LOG.debug(f'Pids before operation: {target_pids}') + pids = process.run( + 'pidof virtnetworkd; pidof virtqemud', shell=True).stdout_text + if set(pids.split()) != set(target_pids.split()): + test.fail('Pids changed after operation') + + +def run(test, params, env): + """ + Check the actual network throughput for direct type interface + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + net_name = 'default' + host_iface = params.get('host_iface') + host_iface = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] + operation = params.get('operation') + dns_ele = params.get('dns_ele') + update_xml = params.get('update_xml') + update_attrs = eval(params.get('update_attrs', '{}')) + conf_val = params.get('conf_val') + post_check = params.get('post_check') + status_error = 'yes' == params.get('status_error', 'no') + err_msg = params.get('err_msg') + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + dns_attrs = eval(params.get('dns_attrs')) + default_net = NetworkXML.new_from_net_dumpxml('default') + bk_net = default_net.copy() + + try: + libvirt_version.is_libvirt_feature_supported(params) + + default_net.setup_attrs(dns=dns_attrs) + default_net.sync() + + virsh.net_dumpxml(net_name, **VIRSH_ARGS) + + if dns_ele == 'dns-txt': + cmd_ori_val = f'cat /var/lib/libvirt/dnsmasq/{net_name}.conf | grep txt' + if dns_ele == 'dns-host': + cmd_ori_val = f'cat /var/lib/libvirt/dnsmasq/{net_name}.addnhosts' + host_xml = DNSXML.HostXML() + host_xml.setup_attrs(**update_attrs) + update_xml = host_xml.xml + + ori_val = process.run(cmd_ori_val, shell=True).stdout_text + pids = process.run( + 'pidof virtnetworkd; pidof virtqemud', shell=True).stdout_text + + up_result = virsh.net_update( + net_name, operation, dns_ele, update_xml, debug=True) + libvirt.check_exit_status(up_result, status_error) + if err_msg: + libvirt.check_result(up_result, err_msg) + + virsh.net_dumpxml(net_name, **VIRSH_ARGS) + + if not status_error: + new_net = NetworkXML.new_from_net_dumpxml(net_name) + new_dns = new_net.dns.fetch_attrs() + dns_key = dns_ele.split('-')[-1] + for k in update_attrs.keys(): + msg = f'expect key [{k}] has value [{update_attrs[k]}], actually got [{new_dns[dns_key].get(k)}]' + LOG.debug(msg) + if new_dns[dns_key].get(k) != update_attrs[k]: + test.fail(f'Compare updated xml failed, {msg}') + + new_val = process.run(cmd_ori_val, shell=True).stdout_text + LOG.debug(f'Expect to find {conf_val} in conf file') + if not re.search(conf_val, new_val): + test.fail(f'Failed to find expected {conf_val} in conf file') + if post_check: + if post_check == 'check_pid_not_change': + check_pid_not_change(test, pids) + + finally: + bk_net.sync() + bkxml.sync() From 11474d271ff491449f1713731ee581589780cab0 Mon Sep 17 00:00:00 2001 From: Julia Graham Date: Tue, 22 Oct 2024 20:59:32 -0400 Subject: [PATCH 0642/1055] Closing and establishing connection with serial console before login --- .../tests/src/virsh_cmd/domain/virsh_domif_setlink_getlink.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_domif_setlink_getlink.py b/libvirt/tests/src/virsh_cmd/domain/virsh_domif_setlink_getlink.py index 10f48c203b9..87d3fb509b2 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_domif_setlink_getlink.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_domif_setlink_getlink.py @@ -254,6 +254,9 @@ def check_update_device(vm, if_name, session): error_msg = None if status_error == "no" and not post_action: + # Close then establish a connection with the serial console + vm.cleanup_serial_console() + vm.create_serial_console() # Serial login the vm to check link status # Start vm check the link statue session = vm.wait_for_serial_login(username=username, From eee30fdb2790393998105494bf575b04b170cc0b Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 22 Oct 2024 18:51:35 +0800 Subject: [PATCH 0643/1055] network: Add netperf testing This PR adds: VIRT-302078 - Do netperf stress test for iommu enabled interface VIRT-301971 - Do netperf stress test for nat network interface Signed-off-by: Yingshun Cui --- libvirt/tests/cfg/viommu_netperf.cfg | 49 ++++++++++++ .../connectivity/netperf_nat_interface.cfg | 27 +++++++ .../tests/src/sriov/vIOMMU/viommu_netperf.py | 39 ++++++++++ .../connectivity/netperf_nat_interface.py | 36 +++++++++ provider/virtual_network/network_base.py | 75 +++++++++++++++++++ 5 files changed, 226 insertions(+) create mode 100644 libvirt/tests/cfg/viommu_netperf.cfg create mode 100644 libvirt/tests/cfg/virtual_network/connectivity/netperf_nat_interface.cfg create mode 100644 libvirt/tests/src/sriov/vIOMMU/viommu_netperf.py create mode 100644 libvirt/tests/src/virtual_network/connectivity/netperf_nat_interface.py diff --git a/libvirt/tests/cfg/viommu_netperf.cfg b/libvirt/tests/cfg/viommu_netperf.cfg new file mode 100644 index 00000000000..950667f8ea3 --- /dev/null +++ b/libvirt/tests/cfg/viommu_netperf.cfg @@ -0,0 +1,49 @@ +- vIOMMU.netperf: + type = viommu_netperf + vms = avocado-vt-vm1 + net_name = network_conn + ip_attrs = {"netmask": "255.255.255.0", "address": "192.168.144.1", "dhcp_ranges": {"attrs": {"end": "192.168.144.254", "start": "192.168.144.2"}}} + iface_attrs = {"source": {"network": "${net_name}"}, "type_name": "network", "model": "virtio"} + network_attrs = {"name": "${net_name}", "forward": {"mode": "nat"}, "ips": [${ip_attrs}]} + start_vm = "no" + variants: + - virtio: + only q35, aarch64 + func_supported_since_libvirt_ver = (8, 3, 0) + iommu_dict = {'model': 'virtio'} + - intel: + only q35 + start_vm = "yes" + enable_guest_iommu = "yes" + iommu_dict = {'model': 'intel', 'driver': {'intremap': 'on', 'caching_mode': 'on', 'eim': 'on', 'iotlb': 'on', 'aw_bits': '48'}} + - smmuv3: + only aarch64 + func_supported_since_libvirt_ver = (5, 5, 0) + iommu_dict = {'model': 'smmuv3'} + variants: + - e1000e: + only q35 + iface_model = 'e1000e' + iface_dict = {'type_name': 'network', 'model': '${iface_model}', 'source': {'network': 'default'}} + - virtio_interface: + interface_driver_name = "vhost" + interface_driver = {'driver_attr': {'name': '${interface_driver_name}', 'iommu': 'on'}} + iface_dict = {'type_name': 'network', 'model': 'virtio', 'driver': ${interface_driver}, 'source': {'network': 'default'}} + variants: + - guest2guest: + vms = avocado-vt-vm1 vm2 + netperf_client = avocado-vt-vm1 + netperf_server = vm2 + - host2guest: + netperf_client = ${local_ip} + netperf_server = ${main_vm} + - guest2host: + netperf_client = ${main_vm} + netperf_server = ${local_ip} + UDP_STREAM: + extra_cmd_opts = "-- -R 1" + variants: + - TCP_STREAM: + test_protocol = TCP_STREAM + - UDP_STREAM: + test_protocol = UDP_STREAM diff --git a/libvirt/tests/cfg/virtual_network/connectivity/netperf_nat_interface.cfg b/libvirt/tests/cfg/virtual_network/connectivity/netperf_nat_interface.cfg new file mode 100644 index 00000000000..8b5890da0df --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/connectivity/netperf_nat_interface.cfg @@ -0,0 +1,27 @@ +- virtual_network.netperf.nat_interface: + type = netperf_nat_interface + vms = avocado-vt-vm1 + start_vm = no + net_name = network_conn + ip_attrs = {"netmask": "255.255.255.0", "address": "192.168.144.1", "dhcp_ranges": {"attrs": {"end": "192.168.144.254", "start": "192.168.144.2"}}} + iface_attrs = {"source": {"network": "${net_name}"}, "type_name": "network", "model": "virtio"} + network_attrs = {"name": "${net_name}", "forward": {"mode": "nat"}, "ips": [${ip_attrs}]} + + variants: + - guest2guest: + vms = avocado-vt-vm1 vm2 + netperf_client = avocado-vt-vm1 + netperf_server = vm2 + - host2guest: + netperf_client = ${local_ip} + netperf_server = ${main_vm} + - guest2host: + netperf_client = ${main_vm} + netperf_server = ${local_ip} + UDP_STREAM: + extra_cmd_opts = "-- -R 1" + variants: + - TCP_STREAM: + test_protocol = TCP_STREAM + - UDP_STREAM: + test_protocol = UDP_STREAM diff --git a/libvirt/tests/src/sriov/vIOMMU/viommu_netperf.py b/libvirt/tests/src/sriov/vIOMMU/viommu_netperf.py new file mode 100644 index 00000000000..b8c20a2893a --- /dev/null +++ b/libvirt/tests/src/sriov/vIOMMU/viommu_netperf.py @@ -0,0 +1,39 @@ +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml + +from provider.viommu import viommu_base +from provider.virtual_network import network_base + + +def run(test, params, env): + """ + Run netperf testing between host and vm with iommu device + """ + cleanup_ifaces = "yes" == params.get("cleanup_ifaces", "yes") + iommu_dict = eval(params.get('iommu_dict', '{}')) + + vms = params.get('vms').split() + vm_objs = [env.get_vm(vm_i) for vm_i in vms] + + test_objs = [viommu_base.VIOMMUTest(vm, test, params) for vm in vm_objs] + + try: + test.log.info("TEST_SETUP: Update VM XML.") + for test_obj in test_objs: + test_obj.setup_iommu_test(iommu_dict=iommu_dict, + cleanup_ifaces=cleanup_ifaces) + + iface_dict = test_objs[0].parse_iface_dict() + if cleanup_ifaces: + vmxml_lists = list(map(vm_xml.VMXML.new_from_inactive_dumpxml, vms)) + [libvirt_vmxml.modify_vm_device(vmxml_i, 'interface', iface_dict) for vmxml_i in vmxml_lists] + + test.log.info('TEST_STEP: Start the VM(s)') + [vm_inst.start() for vm_inst in vm_objs] + [vm_inst.wait_for_login() for vm_inst in vm_objs] + + test.log.info("TEST_STEP: Run netperf testing between host(vm) and vm.") + network_base.exec_netperf_test(params, env) + finally: + for test_obj in test_objs: + test_obj.teardown_iommu_test() diff --git a/libvirt/tests/src/virtual_network/connectivity/netperf_nat_interface.py b/libvirt/tests/src/virtual_network/connectivity/netperf_nat_interface.py new file mode 100644 index 00000000000..1e350dc901c --- /dev/null +++ b/libvirt/tests/src/virtual_network/connectivity/netperf_nat_interface.py @@ -0,0 +1,36 @@ +from provider.virtual_network import network_base + +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_network +from virttest.utils_libvirt import libvirt_vmxml + + +def run(test, params, env): + """ + Verify the guest can work well under the netperf stress test + """ + vms = params.get('vms').split() + vm_objs = [env.get_vm(vm_i) for vm_i in vms] + network_attrs = eval(params.get('network_attrs')) + iface_attrs = eval(params.get('iface_attrs')) + + bkxmls = list(map(vm_xml.VMXML.new_from_inactive_dumpxml, vms)) + + try: + libvirt_network.create_or_del_network(network_attrs) + test.log.debug(f'Network xml:\n' + f'{virsh.net_dumpxml(network_attrs["name"]).stdout_text}') + vmxml_lists = list(map(vm_xml.VMXML.new_from_inactive_dumpxml, vms)) + [libvirt_vmxml.modify_vm_device(vmxml_i, 'interface', iface_attrs) + for vmxml_i in vmxml_lists] + + test.log.info('TEST_STEP: Start the VM(s)') + [vm_inst.start() for vm_inst in vm_objs] + [vm_inst.wait_for_login() for vm_inst in vm_objs] + network_base.exec_netperf_test(params, env) + + finally: + [backup_xml.sync() for backup_xml in bkxmls] + libvirt_network.create_or_del_network(network_attrs, is_del=True) diff --git a/provider/virtual_network/network_base.py b/provider/virtual_network/network_base.py index d2e380a9465..f3ff7410961 100644 --- a/provider/virtual_network/network_base.py +++ b/provider/virtual_network/network_base.py @@ -9,6 +9,7 @@ from virttest import remote from virttest import utils_misc from virttest import utils_net +from virttest import utils_package from virttest import virsh from virttest.libvirt_xml import network_xml from virttest.libvirt_xml import vm_xml @@ -376,3 +377,77 @@ def check_throughput(serv_runner, cli_runner, ip_addr, bw, th_type): raise exceptions.TestFail(f'Actual {th_type} is not close to expected ' f'{th_type}:\n{msg}') LOG.debug(msg) + + +def exec_netperf_test(params, env): + """ + Verify the guest can work well under the netperf stress test + + :param params: Dictionary with the test parameters. + :param env: Dictionary with test environment. + """ + netperf_client = params.get("netperf_client") + netperf_server = params.get("netperf_server") + extra_cmd_opts = params.get("extra_cmd_opts", "") + netperf_timeout = params.get("netperf_timeout", "60") + test_protocol = params.get("test_protocol") + vms = params.get('vms').split() + vm_objs = {vm_i: env.get_vm(vm_i) for vm_i in vms} + before_test_cores = process.run("coredumpctl list", ignore_status=True, verbose=True).stdout_text + + def _get_access_info(netperf_address): + LOG.debug(f"check {netperf_address}...") + session = None + if re.match(r"((\d){1,3}\.){3}(\d){1,3}", netperf_address): + func = process.run + test_ip = netperf_address + else: + if netperf_address not in vms: + raise exceptions.TestError(f"Unable to get {netperf_address} from {vms}!") + vm = vm_objs.get(netperf_address) + if not vm.is_alive(): + vm.start() + session = vm.wait_for_login() + test_ip = vm.get_address() + func = session.cmd + return func, test_ip, session + + c_func, c_ip, c_session = _get_access_info(netperf_client) + s_func, s_ip, s_session = _get_access_info(netperf_server) + + try: + if not utils_package.package_install("netperf", c_session): + raise exceptions.TestError("Unable to install netperf in the client host!") + if not utils_package.package_install("netperf", s_session): + raise exceptions.TestError("Unable to install netperf in the server host!") + c_func("systemctl stop firewalld") + s_func("systemctl stop firewalld") + + LOG.debug("Start netserver...") + if s_ip == netperf_server: + s_func("killall netserver", ignore_status=True) + s_func("netserver") + + LOG.debug("Run netperf command...") + test_cmd = f"netperf -H {s_ip} -l {netperf_timeout} -C -c -t {test_protocol} {extra_cmd_opts}" + c_func(test_cmd, timeout=120) + + for vm in vm_objs.values(): + try: + vm.wait_for_login().close() + except (remote.LoginError, aexpect.ShellError) as e: + LOG.error(f"Unable to access to {vm.name}, guest os may have crashed - {e}") + vm.destroy() + vm.start() + vm.wait_for_login().close() + after_test_cores = process.run("coredumpctl list", + ignore_status=True, verbose=True).stdout_text + if after_test_cores != before_test_cores: + raise exceptions.TestFail("There are coredump files during the test!") + + finally: + LOG.info("Test teardown: Cleanup env.") + s_func("killall netserver") + s_func("systemctl start firewalld") + # TODO: Start firewalld on guest + process.run("systemctl start firewalld", ignore_status=True) From 101b75f0add1e6b7d0ac1661fc688674a05254c7 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Wed, 23 Oct 2024 03:24:03 -0400 Subject: [PATCH 0644/1055] Fix libvirt_ap_passthrough_autostart failure due to incorrectly string format in LOG.debug Typically, it will throw TypeError: not all arguments converted during string formatting Signed-off-by: chunfuwen --- .../src/passthrough/ap/libvirt_ap_passthrough_autostart.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/passthrough/ap/libvirt_ap_passthrough_autostart.py b/libvirt/tests/src/passthrough/ap/libvirt_ap_passthrough_autostart.py index 176395a6a14..628f49b1e51 100644 --- a/libvirt/tests/src/passthrough/ap/libvirt_ap_passthrough_autostart.py +++ b/libvirt/tests/src/passthrough/ap/libvirt_ap_passthrough_autostart.py @@ -38,7 +38,7 @@ def _is_listed(): """Parameterless helper function to use with wait_for""" cmd = "mdevctl list -u %s" % uuid err, out = cmd_status_output(cmd, shell=True, session=session) - LOG.debug(err, out) + LOG.debug("mediated device status - {}, output - {}.".format(err, out)) return uuid in out if not wait_for(_is_listed, timeout=5): raise TestFail("Mediated device UUID(%s) not listed" % uuid) From 59f046d63c1b68ec6994b763afba4791670ca7f7 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Fri, 11 Oct 2024 03:46:49 -0400 Subject: [PATCH 0645/1055] Update case of save_with_options Add steps to monitor with domjobinfo and check domstate reason Signed-off-by: Haijiao Zhao --- .../save_and_restore/save_with_options.cfg | 6 +++ .../src/save_and_restore/save_with_options.py | 41 ++++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/save_and_restore/save_with_options.cfg b/libvirt/tests/cfg/save_and_restore/save_with_options.cfg index 1e2d8056768..606b78223e9 100644 --- a/libvirt/tests/cfg/save_and_restore/save_with_options.cfg +++ b/libvirt/tests/cfg/save_and_restore/save_with_options.cfg @@ -3,6 +3,10 @@ variants scenario: - no_opt: options = + check_reason = yes + check_reason_cmd = "while true; do virsh domjobinfo avocado-vt-vm1; done" + pattern_running = "Job type:\s*Unbounded\s*Operation:\s*Save" + pattern_completed = "Job type:\s*Completed\s*Operation:\s*Save" - verbose_opt: options = --verbose expect_msg = 'Save:\s\[100.*%\]' @@ -21,9 +25,11 @@ variants: - running_vm: pre_state = running + domst_reason = restored - paused_vm: no verbose_opt, xml_opt, bypass_cache_opt pre_state = paused + domst_reason = migrating variants mode: - readonly: only running_vm.no_opt diff --git a/libvirt/tests/src/save_and_restore/save_with_options.py b/libvirt/tests/src/save_and_restore/save_with_options.py index fa776edf392..e77555539ca 100644 --- a/libvirt/tests/src/save_and_restore/save_with_options.py +++ b/libvirt/tests/src/save_and_restore/save_with_options.py @@ -3,7 +3,6 @@ import re from avocado.utils import process - from virttest import utils_misc from virttest import utils_package from virttest import virsh @@ -18,6 +17,12 @@ def run(test, params, env): + def check_output(pattern, output, cmd): + msg = f'to find [{pattern}] in {cmd} output' + LOG.debug(f'Expect {msg}') + if not re.search(pattern, output): + test.fail(f'Failed {msg}') + vm_name = params.get('main_vm') vm = env.get_vm(vm_name) @@ -33,7 +38,14 @@ def run(test, params, env): rand_id = utils_misc.generate_random_string(3) save_path = f'/var/tmp/{vm_name}_{rand_id}.save' check_cmd = params.get('check_cmd', '') - check_cmd = check_cmd.format(save_path, save_path) if check_cmd else check_cmd + check_cmd = check_cmd.format( + save_path, save_path) if check_cmd else check_cmd + check_reason = 'yes' == params.get('check_reason', 'no') + check_reason = check_reason and not status_error + check_reason_cmd = params.get('check_reason_cmd') + pattern_running = params.get('pattern_running') + pattern_completed = params.get('pattern_completed') + domst_reason = params.get('domst_reason') vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) bkxml = vmxml.copy() @@ -60,10 +72,24 @@ def run(test, params, env): sp = process.SubProcess(check_cmd, shell=True) sp.start() + if check_reason: + monitor_sp = process.SubProcess(check_reason_cmd, shell=True) + monitor_sp.start() + save_result = virsh.save(vm_name, save_path, options=options, debug=True, virsh_opt=virsh_options) libvirt.check_exit_status(save_result, status_error) + if check_reason: + domjobinfo_output = monitor_sp.get_stdout().decode() + monitor_sp.terminate() + LOG.debug(f'domjobinfo output:\n{domjobinfo_output}') + check_output(pattern_running, domjobinfo_output, 'domjobinfo') + + domjobinfo_completed = virsh.domjobinfo( + vm_name, '--completed', **VIRSH_ARGS).stdout_text + check_output(pattern_completed, domjobinfo_completed, 'domjobinfo') + if status_error: libvirt.check_result(save_result, error_msg) if vm.state() != pre_state: @@ -80,6 +106,12 @@ def run(test, params, env): test.fail(f'Expect content "{expect_msg}" not in output: ' f'{save_output}') + if check_reason: + domst_save = virsh.domstate( + vm_name, '--reason', **VIRSH_ARGS).stdout_text + pattern_save = 'shut off \(saved\)' + check_output(pattern_save, domst_save, 'domstate') + if scenario == 'bypass_cache_opt': output = sp.get_stdout().decode() LOG.debug(f'bypass-cache check output:\n{output}') @@ -103,6 +135,11 @@ def run(test, params, env): timeout=timeout): test.fail(f'VM should be {after_state} after restore, but current ' f'state is {vm.state()}') + if check_reason: + domst_restore = virsh.domstate( + vm_name, '--reason', **VIRSH_ARGS).stdout_text + pattern_restore = f'{pre_state}\s*\({domst_reason}\)' + check_output(pattern_restore, domst_restore, 'domstate') if vm.state() == 'paused': virsh.resume(vm_name, **VIRSH_ARGS) From 5836e6f07f251915aedf0e5a18a09b44fe1e8abd Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Wed, 23 Oct 2024 06:49:50 -0400 Subject: [PATCH 0646/1055] Update case of connectivity check of ethernet interface - VIRT-296218 - [ethernet] Check connectivity for ethernet type interface with managed='no' Signed-off-by: Haijiao Zhao --- .../connectivity_check_ethernet_interface.cfg | 16 +++++- .../connectivity_check_ethernet_interface.py | 49 ++++++++++++++++++- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_ethernet_interface.cfg b/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_ethernet_interface.cfg index ff057c59d03..9602523eb8b 100644 --- a/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_ethernet_interface.cfg +++ b/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_ethernet_interface.cfg @@ -4,11 +4,11 @@ timeout = 240 outside_ip = 'www.redhat.com' host_iface = + extra_attrs = {} variants user_type: - non_root_user: test_user = USER.EXAMPLE test_passwd = PASSWORD.EXAMPLE - user_id = unpr_vm_name = UNPRIVILEGED_VM.EXAMPLE variants: - positive_test: @@ -24,14 +24,26 @@ tap_mtu = 1400 iface_mtu = 1200 mtu_attrs = {'mtu': {'size': ${iface_mtu}}} + - smaller_mtu_multi_ifaces: + only two_ifaces + tap_mtu = 1400 + iface_mtu = 1200 + iface_mtu_2 = 1150 + mtu_attrs = {'mtu': {'size': ${iface_mtu}}} variants tap_type: - tap: vm_ping_outside = pass vm_ping_host_public = pass + variants iface_amount: + - one_iface: + - two_ifaces: + only smaller_mtu_multi_ifaces + extra_attrs = {'rom': {'enabled': 'no'}} + iface_attrs_2 = {'type_name': 'ethernet', 'target': {'dev': tap_name_2, 'managed': 'no'}, 'model': 'virtio', 'mtu': {'size': '${iface_mtu_2}'}, 'driver': {'driver_attr': {'name': 'vhost'}}, 'rom': {'enabled': 'no'}} - macvtap: vm_ping_outside = pass vm_ping_host_public = fail - iface_attrs = {'target': {'dev': tap_name, 'managed': 'no'}, 'model': 'virtio', 'type_name': 'ethernet', **${mtu_attrs}} + iface_attrs = {'target': {'dev': tap_name, 'managed': 'no'}, 'model': 'virtio', 'type_name': 'ethernet', **${mtu_attrs}, **${extra_attrs}} - negative_test: status_error = yes variants: diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py index 6b5e683fdde..7f0d5b5fd45 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py @@ -1,6 +1,7 @@ import logging import aexpect +from avocado.utils import process from virttest import libvirt_version from virttest import remote from virttest import utils_misc @@ -49,9 +50,13 @@ def run(test, params, env): bridge_name = 'br_' + rand_id tap_type = params.get('tap_type', '') tap_name = tap_type + '_' + rand_id + tap_name_2 = tap_name + '_2' tap_mtu = params.get('tap_mtu') iface_mtu = params.get('iface_mtu') + iface_mtu_2 = params.get('iface_mtu_2') iface_attrs = eval(params.get('iface_attrs')) + iface_attrs_2 = eval(params.get('iface_attrs_2')) + iface_amount = params.get('iface_amount') outside_ip = params.get('outside_ip') host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( @@ -70,11 +75,17 @@ def run(test, params, env): if tap_type == 'tap': utils_net.create_linux_bridge_tmux(bridge_name, host_iface) network_base.create_tap(tap_name, bridge_name, test_user) + if iface_amount == 'two_ifaces': + network_base.create_tap(tap_name_2, 'virbr0', test_user) elif tap_type == 'macvtap': mac_addr = network_base.create_macvtap(tap_name, host_iface, test_user) if tap_mtu: network_base.set_tap_mtu(tap_name, tap_mtu) + if iface_amount == 'two_ifaces': + network_base.set_tap_mtu(tap_name_2, tap_mtu) + + process.run('ip a') iface_attrs['mac_address'] = mac_addr vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( @@ -82,6 +93,14 @@ def run(test, params, env): vmxml.del_device('interface', by_tag=True) libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs, virsh_instance=virsh_ins) + if iface_attrs_2: + mac_addr_2 = utils_net.generate_mac_address_simple() + iface_attrs_2['mac_address'] = mac_addr_2 + LOG.debug('Adding a 2nd interface to vm xml') + libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs_2, 1, + virsh_instance=virsh_ins) + + LOG.debug(f'VMxml is:\n{virsh_ins.dumpxml(vm_name).stdout_text}') start_result = virsh.start(vm_name, debug=True, uri=uri) libvirt.check_exit_status(start_result, status_error) @@ -97,7 +116,33 @@ def run(test, params, env): 'outside_ip': outside_ip, 'host_public_ip': host_ip, } - network_base.ping_check(params, ips, session, force_ipv4=True) + vm_default_gw = utils_net.get_default_gateway(session=session) + + if iface_amount == 'two_ifaces': + ping_params = { + mac_addr: + {'vm_ping_outside': params.get('vm_ping_outside'), + 'vm_ping_host_public': params.get('vm_ping_host_public'), }, + mac_addr_2: + {'vm_ping_outside': params.get('vm_ping_outside')} + } + ips_2 = { + mac_addr: ips, + mac_addr_2: {'outside_ip': vm_default_gw} + } + for mac in (mac_addr, mac_addr_2): + iface_vm_info = utils_net.get_linux_iface_info( + mac=mac, session=session) + iface_vm = iface_vm_info['ifname'] + LOG.debug(f'Check connetivity of iface {iface_vm}({mac})') + ping_args = { + 'vm_ping_outside': {'interface': iface_vm}, + 'vm_ping_host_public': {'interface': iface_vm}, + } + network_base.ping_check(ping_params[mac], ips_2[mac], session, + force_ipv4=True, **ping_args) + else: + network_base.ping_check(params, ips, session, force_ipv4=True) if iface_mtu: # Check mtu of live vmxml @@ -139,5 +184,7 @@ def run(test, params, env): del virsh_ins if tap_type: network_base.delete_tap(tap_name) + if iface_amount == 'two_ifaces': + network_base.delete_tap(tap_name_2) if tap_type == 'tap': utils_net.delete_linux_bridge_tmux(bridge_name, host_iface) From c74e40280b5570f992e14cc0c290071d04b36091 Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 23 Oct 2024 19:58:34 +0800 Subject: [PATCH 0647/1055] migration: Fix a typo Signed-off-by: lcheng --- .../src/migration/async_ops/destroy_vm_during_performphase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/migration/async_ops/destroy_vm_during_performphase.py b/libvirt/tests/src/migration/async_ops/destroy_vm_during_performphase.py index 76659b751fa..96b9d88a7bd 100644 --- a/libvirt/tests/src/migration/async_ops/destroy_vm_during_performphase.py +++ b/libvirt/tests/src/migration/async_ops/destroy_vm_during_performphase.py @@ -25,7 +25,7 @@ def verify_test(): test.log.info("Verify steps.") if not libvirt.check_vm_state(vm.name, expected_src_state, uri=migration_obj.src_uri): - test.faile("Check vm state on source host fail.") + test.fail(f"Check of expected VM state ({expected_src_state}) on source host failed.") dest_vm_list = virsh.dom_list(options="--all --persistent", debug=True, uri=dest_uri) if expected_dest_state == "nonexist": if vm_name in dest_vm_list.stdout.strip(): From c47ddc14e9f406670e69fd41101858f8cf3f226c Mon Sep 17 00:00:00 2001 From: hholoubk Date: Tue, 22 Oct 2024 13:07:43 +0200 Subject: [PATCH 0648/1055] Added better logging of VM start error --- libvirt/tests/src/libvirt_hooks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/libvirt_hooks.py b/libvirt/tests/src/libvirt_hooks.py index 08fc2e3ad6c..97b1ea5ebc3 100644 --- a/libvirt/tests/src/libvirt_hooks.py +++ b/libvirt/tests/src/libvirt_hooks.py @@ -492,11 +492,11 @@ def run_scale_test(): lxc_hook() except virt_vm.VMStartError as e: - logging.info(str(e)) if start_error: + logging.info(str(e)) pass else: - test.fail('VM Failed to start for some reason!') + test.fail(f"VM Failed to start: {str(e)}") else: if start_error: test.fail('VM started unexpected') From d478446695686330b5c39071a85daaa8ed157f9f Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 24 Oct 2024 02:59:51 -0400 Subject: [PATCH 0649/1055] iface_update:Update error message Signed-off-by: Haijiao Zhao --- libvirt/tests/cfg/virtual_network/iface_update.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_network/iface_update.cfg b/libvirt/tests/cfg/virtual_network/iface_update.cfg index 33644f42f56..cc06f08bdc0 100644 --- a/libvirt/tests/cfg/virtual_network/iface_update.cfg +++ b/libvirt/tests/cfg/virtual_network/iface_update.cfg @@ -142,7 +142,7 @@ new_iface_rom = "{'enabled':'no'}" del_address = "yes" del_rom = "yes" - expect_err_msg = "Operation not supported: cannot modify network device rom enabled setting" + expect_err_msg = "Operation not supported:.*rom" - del_rom_enable: no s390-virtio iface_rom = "{'enabled':'yes'}" From 53c3e5aa478808d60797f2924cd6fc59d0562fa2 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 25 Oct 2024 09:56:02 +0800 Subject: [PATCH 0650/1055] memory: Fixup 'No case to run' issue The variant 'config' in hugepage_nodeset.cfg makes avocado impossible to obtain normal cases. Signed-off-by: Yingshun Cui --- libvirt/tests/cfg/memory/memory_backing/hugepage_nodeset.cfg | 2 +- libvirt/tests/src/memory/memory_backing/hugepage_nodeset.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_backing/hugepage_nodeset.cfg b/libvirt/tests/cfg/memory/memory_backing/hugepage_nodeset.cfg index d04a1af0154..1e48871dbc6 100644 --- a/libvirt/tests/cfg/memory/memory_backing/hugepage_nodeset.cfg +++ b/libvirt/tests/cfg/memory/memory_backing/hugepage_nodeset.cfg @@ -35,7 +35,7 @@ memory_backing_dict = "'mb': {'hugepages': {'pages': [{'unit': '${page_unit}', 'size': '${page_size}','nodeset':'${nodeset}'}]}}" with_numa_error = "error: hugepages: node 2 not found" without_numa_error = "error: hugepages: node 0 not found" - variants config: + variants numa_config: - with_numa: numa_size_1 = 1048576 numa_size_2 = 1024000 diff --git a/libvirt/tests/src/memory/memory_backing/hugepage_nodeset.py b/libvirt/tests/src/memory/memory_backing/hugepage_nodeset.py index 2f3a590ba53..80697440e09 100644 --- a/libvirt/tests/src/memory/memory_backing/hugepage_nodeset.py +++ b/libvirt/tests/src/memory/memory_backing/hugepage_nodeset.py @@ -135,8 +135,8 @@ def teardown_test(): set_pagesize = params.get("set_pagesize") set_pagenum = params.get("set_pagenum") expect_xpath = eval(params.get("expect_xpath")) - config = params.get("config") - globals()["config_error"] = params.get("%s_error" % config, None) + numa_config = params.get("numa_config") + globals()["config_error"] = params.get("%s_error" % numa_config, None) try: setup_test() From bd920276b4baef989a5a5f5f21dc9c4b05d3a46e Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Thu, 24 Oct 2024 22:02:35 -0400 Subject: [PATCH 0651/1055] Change variants name to avoid avocado list test case failure Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/memory/memory_backing/hugepage_nodeset.cfg | 2 +- libvirt/tests/src/memory/memory_backing/hugepage_nodeset.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_backing/hugepage_nodeset.cfg b/libvirt/tests/cfg/memory/memory_backing/hugepage_nodeset.cfg index d04a1af0154..1e48871dbc6 100644 --- a/libvirt/tests/cfg/memory/memory_backing/hugepage_nodeset.cfg +++ b/libvirt/tests/cfg/memory/memory_backing/hugepage_nodeset.cfg @@ -35,7 +35,7 @@ memory_backing_dict = "'mb': {'hugepages': {'pages': [{'unit': '${page_unit}', 'size': '${page_size}','nodeset':'${nodeset}'}]}}" with_numa_error = "error: hugepages: node 2 not found" without_numa_error = "error: hugepages: node 0 not found" - variants config: + variants numa_config: - with_numa: numa_size_1 = 1048576 numa_size_2 = 1024000 diff --git a/libvirt/tests/src/memory/memory_backing/hugepage_nodeset.py b/libvirt/tests/src/memory/memory_backing/hugepage_nodeset.py index 2f3a590ba53..80697440e09 100644 --- a/libvirt/tests/src/memory/memory_backing/hugepage_nodeset.py +++ b/libvirt/tests/src/memory/memory_backing/hugepage_nodeset.py @@ -135,8 +135,8 @@ def teardown_test(): set_pagesize = params.get("set_pagesize") set_pagenum = params.get("set_pagenum") expect_xpath = eval(params.get("expect_xpath")) - config = params.get("config") - globals()["config_error"] = params.get("%s_error" % config, None) + numa_config = params.get("numa_config") + globals()["config_error"] = params.get("%s_error" % numa_config, None) try: setup_test() From 6c0b42c9837ceef247f05e3967025015f0adde53 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Mon, 28 Oct 2024 13:51:44 +0800 Subject: [PATCH 0652/1055] viommu: Fix pcie_to_pci_bridge_controller for aarch64 1. Remove a case due to a WONTFIX issue(BZ2181309) 2. Remove incorrect checks Signed-off-by: Yingshun Cui --- libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg b/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg index 6130f050c20..0110f0eef49 100644 --- a/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg +++ b/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg @@ -50,11 +50,11 @@ disk_dict = {'target': {'dev': 'sda', 'bus': 'scsi'}, 'driver': ${disk_driver}} cleanup_ifaces = no - pcie_to_pci_bridge_controller: - test_devices = ["Eth", "block"] controller_dicts = [{'type': 'pci', 'model': 'pcie-to-pci-bridge', 'pre_controller': 'pcie-root-port'}] disk_dict = {'target': {'dev': 'vda', 'bus': 'virtio'}, 'device': 'disk', 'driver': ${disk_driver}, 'model': 'virtio-non-transitional'} variants: - virtio_non_transitional: + no smmuv3 iface_dict = {'source': {'network': 'default'}, 'driver': {'driver_attr': {'iommu': 'on'}},'type_name': 'network', 'model': 'virtio-non-transitional'} - hostdev_iface: only virtio From e3b4157b469e2d0e4ccf5ee4920cdbceff353f40 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 9 Oct 2024 11:26:17 -0400 Subject: [PATCH 0653/1055] domtime: update for s390x hwclock is not available on s390x and guest agent operators that modify the time either. 1. Don't try to restore time (with --now flag) during teardown. 2. Disable test cases that try to modify time. 3. Skip step that uses hwclock. Signed-off-by: Sebastian Mitterle --- .../cfg/virsh_cmd/domain/virsh_domtime.cfg | 7 +++ .../src/virsh_cmd/domain/virsh_domtime.py | 62 ++++++++++--------- spell.ignore | 1 + 3 files changed, 42 insertions(+), 28 deletions(-) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_domtime.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_domtime.cfg index e96298283e6..ca2e337bf9a 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_domtime.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_domtime.cfg @@ -3,6 +3,13 @@ start_vm = no take_regular_screendumps = "no" vm_stop_duration = 10 + s390-virtio: + positive: + only get_time,with_pretty,suspend_vm,managedsave_vm + negative: + only shutdown_vm,get_time_readonly,no_agent_channel,no_agent + restore_time = no + get_local_hw = no variants: - positive: variants: diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_domtime.py b/libvirt/tests/src/virsh_cmd/domain/virsh_domtime.py index c4eaec7567c..b699a3a6898 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_domtime.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_domtime.py @@ -74,7 +74,7 @@ def run_cmd(session, cmd): cmd, duration, output.strip()) return output, duration - def get_guest_times(session): + def get_guest_times(session, get_local_hw): """ Retrieve different guest time as a dict for checking. Keys: @@ -84,34 +84,37 @@ def get_guest_times(session): domtime: Guest system time in UTC got from virsh domtime command :param session: Session from which to access guest + :param get_local_hw: if to use hwclock to get info """ times = {} get_begin = time.time() - # Guest RTC local timezone time - output, _ = run_cmd(session, 'hwclock') - try: - time_str, _ = re.search(r"(.+) (\S+ seconds)", output).groups() + # Guest RTC local timezone time + if get_local_hw: + output, _ = run_cmd(session, 'hwclock') try: - # output format 1: Tue 01 Mar 2016 01:53:46 PM CST - # Remove timezone info from output - new_str = re.sub(r'\s+\S+$', '', time_str) - times['local_hw'] = datetime.datetime.strptime( - new_str, r"%a %d %b %Y %I:%M:%S %p") - except ValueError: - # There are known three possible output format for `hwclock` - # output format 2: Sat Feb 14 07:31:33 2009 - times['local_hw'] = datetime.datetime.strptime( - time_str, r"%a %b %d %H:%M:%S %Y") - except AttributeError: - try: # output format 3: 2019-03-22 05:16:18.224511-04:00 - time_str = output.split(".")[0] - times['local_hw'] = datetime.datetime.strptime( - time_str, r"%Y-%m-%d %H:%M:%S") - except ValueError: - test.fail("Unknown hwclock output format in guest: %s", output) - delta = time.time() - get_begin - times['local_hw'] -= datetime.timedelta(seconds=delta) + time_str, _ = re.search(r"(.+) (\S+ seconds)", output).groups() + + try: + # output format 1: Tue 01 Mar 2016 01:53:46 PM CST + # Remove timezone info from output + new_str = re.sub(r'\s+\S+$', '', time_str) + times['local_hw'] = datetime.datetime.strptime( + new_str, r"%a %d %b %Y %I:%M:%S %p") + except ValueError: + # There are known three possible output format for `hwclock` + # output format 2: Sat Feb 14 07:31:33 2009 + times['local_hw'] = datetime.datetime.strptime( + time_str, r"%a %b %d %H:%M:%S %Y") + except AttributeError: + try: # output format 3: 2019-03-22 05:16:18.224511-04:00 + time_str = output.split(".")[0] + times['local_hw'] = datetime.datetime.strptime( + time_str, r"%Y-%m-%d %H:%M:%S") + except ValueError: + test.fail("Unknown hwclock output format in guest: %s", output) + delta = time.time() - get_begin + times['local_hw'] -= datetime.timedelta(seconds=delta) # Guest system local timezone time try: @@ -353,6 +356,9 @@ def stop_vm(): vm = env.get_vm(vm_name) readonly = (params.get("readonly_test", "no") == "yes") + restore_time = "yes" == params.get("restore_time", "yes") + get_local_hw = "yes" == params.get("get_local_hw", "yes") + # Backup domain XML xml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) try: @@ -365,7 +371,7 @@ def stop_vm(): # have day light savings, to affect the time session.cmd("timedatectl set-timezone Asia/Kolkata") try: - init_guest_times, _ = get_guest_times(session) + init_guest_times, _ = get_guest_times(session, get_local_hw) guest_tz_diff = init_guest_times['local_sys'] - init_guest_times['utc_sys'] logging.debug("Timezone diff on guest is %d hours.", (guest_tz_diff.total_seconds() // 3600)) @@ -393,7 +399,7 @@ def stop_vm(): org_host_loc_time = datetime.datetime.strptime(time_st, r"%a %b %d %H:%M:%S %Y") # Get original guest times - org_times, guest_duration = get_guest_times(session) + org_times, guest_duration = get_guest_times(session, get_local_hw) # Run some operations to stop guest system stop_time = stop_vm() @@ -410,7 +416,7 @@ def stop_vm(): if not shutdown: # Get current guest times - cur_times, _ = get_guest_times(session) + cur_times, _ = get_guest_times(session, get_local_hw) check_time(res, org_times, cur_times) finally: @@ -420,7 +426,7 @@ def stop_vm(): utils_time.sync_timezone_linux(vm) # Sync guest time with host if channel and agent and not shutdown: - res = virsh.domtime(vm_name, now=True) + res = virsh.domtime(vm_name, now=restore_time) if res.exit_status: session.close() test.error("Failed to recover guest time:\n%s" diff --git a/spell.ignore b/spell.ignore index c18394405c4..ef22029e8e3 100644 --- a/spell.ignore +++ b/spell.ignore @@ -401,6 +401,7 @@ hugepage Hugepage hugepages hugetlbfs +hwclock hwinfo hwtype hyperv From 17a25029a390a15bd7c1d362970adebb57a2c0bb Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Mon, 28 Oct 2024 15:23:21 +0800 Subject: [PATCH 0654/1055] save_base: Update to log output of ping command Sometimes getting the wrong pid, but I haven't reproduced the issue, so update to log the output of ping command for further debugging. Signed-off-by: Yingshun Cui --- provider/save/save_base.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/provider/save/save_base.py b/provider/save/save_base.py index 92c73291146..843df0b416e 100644 --- a/provider/save/save_base.py +++ b/provider/save/save_base.py @@ -28,7 +28,9 @@ def pre_save_setup(vm, serial=False): ping_cmd = 'ping 127.0.0.1 >/tmp/ping_out 2>&1' # This session shouldn't be closed or it will kill ping session.sendline(ping_cmd + '&') - pid_ping = session.cmd_output('pidof ping').strip().split()[-1] + ping_output = session.cmd_output('pidof ping') + LOG.debug(f'ping cmd output: {ping_output}') + pid_ping = ping_output.strip().split()[-1] LOG.debug(f'Pid of ping: {pid_ping}') return pid_ping, upsince From 14601486d8142ea2ea76bca98079bd8d3d0964c4 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Tue, 29 Oct 2024 09:27:52 +0800 Subject: [PATCH 0655/1055] tpm_device: fix model on arm Signed-off-by: Dan Zheng --- libvirt/tests/cfg/virtual_device/tpm_device.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/cfg/virtual_device/tpm_device.cfg b/libvirt/tests/cfg/virtual_device/tpm_device.cfg index bd3c6f10fab..d77fc9692ce 100644 --- a/libvirt/tests/cfg/virtual_device/tpm_device.cfg +++ b/libvirt/tests/cfg/virtual_device/tpm_device.cfg @@ -191,6 +191,8 @@ - emulator: backend_type='emulator' tpm_model = 'tpm-crb' + aarch64: + tpm_model = 'tpm-tis' pseries: tpm_model = 'tpm-spapr' variants: From 21f717b334bfc8e4651c94980123db182ed4e03f Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 29 Oct 2024 10:58:53 +0800 Subject: [PATCH 0656/1055] migratpm-tistion: Fix tpm model on aarch64 Update to use 'tpm-tis' to avoide unsupported tpm model issue. Signed-off-by: Yingshun Cui --- .../migration_with_vtpm/migration_with_shared_tpm.cfg | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg index 330781b12de..f9974f78a45 100644 --- a/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg +++ b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg @@ -30,17 +30,20 @@ libvirtd_debug_filters = "1:*" libvirtd_debug_file = '/var/log/libvirt/virtqemud.log' func_supported_since_libvirt_ver = (9, 0, 0) + tpm_model = "tpm-crb" + aarch64: + tpm_model = "tpm-tis" variants: - persistent_and_p2p: virsh_migrate_options = "--live --p2p --verbose --undefinesource --persistent" - tpm_dict = {'tpm_model': 'tpm-crb', 'backend': {'backend_type': 'emulator', 'backend_version': '2.0', 'encryption_secret': '0051c505-1ad0-4d77-9b3e-360c8f5e3b86', 'active_pcr_banks': {'sha256': 'True'}}} + tpm_dict = {'tpm_model': '${tpm_model}', 'backend': {'backend_type': 'emulator', 'backend_version': '2.0', 'encryption_secret': '0051c505-1ad0-4d77-9b3e-360c8f5e3b86', 'active_pcr_banks': {'sha256': 'True'}}} - persistent_and_non_p2p: virsh_migrate_options = "--live --verbose" - tpm_dict = {'tpm_model': 'tpm-crb', 'backend': {'backend_type': 'emulator', 'backend_version': '2.0', 'encryption_secret': '0051c505-1ad0-4d77-9b3e-360c8f5e3b86', 'active_pcr_banks': {'sha256': 'True'}}} + tpm_dict = {'tpm_model': '${tpm_model}', 'backend': {'backend_type': 'emulator', 'backend_version': '2.0', 'encryption_secret': '0051c505-1ad0-4d77-9b3e-360c8f5e3b86', 'active_pcr_banks': {'sha256': 'True'}}} - transient_and_non_p2p: virsh_migrate_options = "--live --verbose" - tpm_dict = {'tpm_model': 'tpm-crb', 'backend': {'backend_type': 'emulator', 'backend_version': '2.0', 'persistent_state': 'yes', 'encryption_secret': '0051c505-1ad0-4d77-9b3e-360c8f5e3b86', 'active_pcr_banks': {'sha256': 'True'}}} + tpm_dict = {'tpm_model': '${tpm_model}', 'backend': {'backend_type': 'emulator', 'backend_version': '2.0', 'persistent_state': 'yes', 'encryption_secret': '0051c505-1ad0-4d77-9b3e-360c8f5e3b86', 'active_pcr_banks': {'sha256': 'True'}}} transient_vm = "yes" variants shared_storage_type: - nfs: From 6cc654a4b264d68879f0b6e831b2ed643fcc5563 Mon Sep 17 00:00:00 2001 From: zhenyzha Date: Tue, 29 Oct 2024 17:57:10 +0800 Subject: [PATCH 0657/1055] change_virtio_mem_request_size:Fix parameter matching issue Fix parameter matching issue, add % to format the string Signed-off-by: zhenyzha --- .../src/memory/memory_devices/change_virtio_mem_request_size.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py b/libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py index 8e7bb6155f9..56bdd209554 100644 --- a/libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py +++ b/libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py @@ -107,7 +107,7 @@ def check_various_size(test, vm_name, expected_size, test.fail("Expect to get '%s':'%s', but got:'%s' in '%sth' " "memory" % (check_item, str(expected_size), actual_size, index+1)) else: - test.log.debug("Check '%s' is '%s' successfully", (check_item, expected_size)) + test.log.debug("Check '%s' is '%s' successfully", check_item, expected_size) def update_virtio_mem_request_size(test, params, vm_name, device_opt, target_requested): From e8540a540015ece4b6894c288d479b1b5f1808b7 Mon Sep 17 00:00:00 2001 From: Julia Graham Date: Mon, 28 Oct 2024 21:14:30 -0400 Subject: [PATCH 0658/1055] Libvirt_rng: update codes for hotplug rng_current check --- .../tests/cfg/security/rng/libvirt_rng.cfg | 2 ++ libvirt/tests/src/security/rng/libvirt_rng.py | 24 ++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/security/rng/libvirt_rng.cfg b/libvirt/tests/cfg/security/rng/libvirt_rng.cfg index aaaf450a036..590e48547c6 100644 --- a/libvirt/tests/cfg/security/rng/libvirt_rng.cfg +++ b/libvirt/tests/cfg/security/rng/libvirt_rng.cfg @@ -17,6 +17,8 @@ variants: - positive: rng_random_source = "yes" + test_guest_rng_file = "yes" + guest_required_kernel = [5.14.0,) variants: - no_options: - persistent: diff --git a/libvirt/tests/src/security/rng/libvirt_rng.py b/libvirt/tests/src/security/rng/libvirt_rng.py index 87781e65af8..9ea18452b96 100644 --- a/libvirt/tests/src/security/rng/libvirt_rng.py +++ b/libvirt/tests/src/security/rng/libvirt_rng.py @@ -16,6 +16,7 @@ from virttest import utils_misc from virttest import libvirt_version from virttest.utils_test import libvirt +from virttest.utils_version import VersionInterval from virttest.libvirt_xml import vm_xml from virttest.libvirt_xml import xcepts from virttest.libvirt_xml.devices import rng @@ -315,6 +316,20 @@ def check_guest_dump(session, exists=True): else: logging.info("Hexdump do not fail with error") + def check_guest_rng_file(session): + """ + Check random device no longer on guest + + :param session: ssh session to guest + """ + rng_file = "/sys/devices/virtual/misc/hw_random/rng_available" + rng_avail = session.cmd_output("cat %s" % rng_file, + timeout=timeout).strip() + logging.debug("rng avail:%s", rng_avail) + if rng_avail.count("virtio"): + test.fail("Failed to check rng file on guest." + " The virtio device should no longer be an available rng device.") + def check_guest(session, expect_fail=False, set_virtio_current=False): """ @@ -334,6 +349,10 @@ def check_guest(session, expect_fail=False, if not rng_avail.count("virtio"): test.fail("Failed to check rng file on guest." " The virtio device is not available.") + guest_required_kernel = params.get('guest_required_kernel', '') + if guest_required_kernel and not set_virtio_current: + vm_kerv = session.cmd_output('uname -r').strip().split('-')[0] + set_virtio_current = vm_kerv in VersionInterval(guest_required_kernel) if set_virtio_current: virtio_dev = re.findall('virtio_rng.\d+', rng_avail)[0] _ = session.cmd_output(("echo -n %s > %s" % @@ -453,6 +472,7 @@ def rotate_audit_log(): expected_audit_message = params.get("expected_audit_message", "VIRT_RESOURCE") set_virtio_current = "yes" == params.get("set_virtio_current", "no") test_guest_dump = "yes" == params.get("test_guest_dump", "no") + test_guest_rng_file = "yes" == params.get("test_guest_rng_file", "no") test_qemu_cmd = "yes" == params.get("test_qemu_cmd", "no") test_snapshot = "yes" == params.get("test_snapshot", "no") snapshot_vm_running = "yes" == params.get("snapshot_vm_running", @@ -669,7 +689,9 @@ def have_rng_xml(): else: test.fail("Rng device still exists after detach!") - if test_guest_dump: + if test_guest_rng_file: + check_guest_rng_file(session) + elif test_guest_dump: check_guest_dump(session, False) session.close() From 3888270df5e4848e8e137a0cda2ad340049ead80 Mon Sep 17 00:00:00 2001 From: Julia Graham Date: Tue, 29 Oct 2024 17:33:59 -0400 Subject: [PATCH 0659/1055] virsh_nodecpustats: test_disable_enable_cpu() check if cpu online --- libvirt/tests/src/virsh_cmd/host/virsh_nodecpustats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/host/virsh_nodecpustats.py b/libvirt/tests/src/virsh_cmd/host/virsh_nodecpustats.py index 4efec85cc14..a035b471336 100755 --- a/libvirt/tests/src/virsh_cmd/host/virsh_nodecpustats.py +++ b/libvirt/tests/src/virsh_cmd/host/virsh_nodecpustats.py @@ -242,7 +242,7 @@ def test_disable_enable_cpu(test, host_cpus_list, params): libvirt.check_result(output, expected_fails=[err_msg]) logging.debug("Online host cpu %s" % host_cpus_list[-1]) - if cpuutil.online(host_cpus_list[-1]): + if not cpuutil.online(host_cpus_list[-1]): test.error("Failed to online host cpu %s" % host_cpus_list[-1]) subtest_cpu_percentage_option(test, host_cpus_list[-1], with_cpu_option=False) From 5c125c2ce78b2b59860017bee29975f889808834 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Wed, 30 Oct 2024 04:48:41 -0400 Subject: [PATCH 0660/1055] Workaround:Remove multi-queue setting Signed-off-by: Haijiao Zhao --- .../restore_from_local_file.cfg | 1 + .../save_and_restore/save_with_options.cfg | 1 + .../restore_from_local_file.py | 5 +++++ .../src/save_and_restore/save_to_block.py | 4 ++++ .../tests/src/save_and_restore/save_to_nfs.py | 4 ++++ .../src/save_and_restore/save_with_formats.py | 4 ++++ .../src/save_and_restore/save_with_options.py | 5 +++++ .../src/virsh_cmd/domain/virsh_managedsave.py | 19 +++++++++++-------- 8 files changed, 35 insertions(+), 8 deletions(-) diff --git a/libvirt/tests/cfg/save_and_restore/restore_from_local_file.cfg b/libvirt/tests/cfg/save_and_restore/restore_from_local_file.cfg index 7e070ba44f2..94fbd576d9a 100644 --- a/libvirt/tests/cfg/save_and_restore/restore_from_local_file.cfg +++ b/libvirt/tests/cfg/save_and_restore/restore_from_local_file.cfg @@ -1,6 +1,7 @@ - save_and_restore.restore_from_local_file: type = restore_from_local_file save_opt = + start_vm = no variants scenario: - file_opt: pre_path_options = --file diff --git a/libvirt/tests/cfg/save_and_restore/save_with_options.cfg b/libvirt/tests/cfg/save_and_restore/save_with_options.cfg index 1e2d8056768..8ef74d17e15 100644 --- a/libvirt/tests/cfg/save_and_restore/save_with_options.cfg +++ b/libvirt/tests/cfg/save_and_restore/save_with_options.cfg @@ -1,5 +1,6 @@ - save_and_restore.save_with_options: type = save_with_options + start_vm = no variants scenario: - no_opt: options = diff --git a/libvirt/tests/src/save_and_restore/restore_from_local_file.py b/libvirt/tests/src/save_and_restore/restore_from_local_file.py index 52398dca326..f8234629a93 100644 --- a/libvirt/tests/src/save_and_restore/restore_from_local_file.py +++ b/libvirt/tests/src/save_and_restore/restore_from_local_file.py @@ -7,6 +7,7 @@ from virttest import utils_misc from virttest import virsh from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_test import libvirt from provider.save import save_base @@ -112,6 +113,10 @@ def run(test, params, env): bkxml = vmxml.copy() try: + # Workaround bug: Remove multi-queue setting + libvirt_vmxml.modify_vm_device(vmxml, 'interface', {'driver': None}) + vm.start() + pid_ping, upsince = save_base.pre_save_setup(vm) virsh.save(vm_name, save_path, options=save_opt, **VIRSH_ARGS) diff --git a/libvirt/tests/src/save_and_restore/save_to_block.py b/libvirt/tests/src/save_and_restore/save_to_block.py index a0a79b4eeec..0886135b0a3 100644 --- a/libvirt/tests/src/save_and_restore/save_to_block.py +++ b/libvirt/tests/src/save_and_restore/save_to_block.py @@ -7,6 +7,7 @@ from virttest import utils_selinux from virttest import virsh from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_test import libvirt from provider.save import save_base @@ -33,6 +34,9 @@ def run(test, params, env): libvirtd = utils_libvirtd.Libvirtd() try: + # Workaround bug: Remove multi-queue setting + libvirt_vmxml.modify_vm_device(vmxml, 'interface', {'driver': None}) + selinux_status = passt.ensure_selinux_enforcing() if namespaces: qemu_conf.namespaces = eval(namespaces) diff --git a/libvirt/tests/src/save_and_restore/save_to_nfs.py b/libvirt/tests/src/save_and_restore/save_to_nfs.py index b457310512a..1df4c9dd056 100644 --- a/libvirt/tests/src/save_and_restore/save_to_nfs.py +++ b/libvirt/tests/src/save_and_restore/save_to_nfs.py @@ -8,6 +8,7 @@ from virttest import utils_misc from virttest import virsh from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_test import libvirt from provider.save import save_base @@ -39,6 +40,9 @@ def run(test, params, env): libvirtd = utils_libvirtd.Libvirtd() try: + # Workaround bug: Remove multi-queue setting + libvirt_vmxml.modify_vm_device(vmxml, 'interface', {'driver': None}) + qemu_conf.dynamic_ownership = 0 if vmxml.devices.by_device_tag('tpm') is not None: qemu_conf.swtpm_user = 'qemu' diff --git a/libvirt/tests/src/save_and_restore/save_with_formats.py b/libvirt/tests/src/save_and_restore/save_with_formats.py index 0679390120e..af9aed13e76 100644 --- a/libvirt/tests/src/save_and_restore/save_with_formats.py +++ b/libvirt/tests/src/save_and_restore/save_with_formats.py @@ -6,6 +6,7 @@ from virttest import utils_misc from virttest import virsh from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_test import libvirt from provider.save import save_base @@ -33,6 +34,9 @@ def run(test, params, env): bkxml = vmxml.copy() try: + # Workaround bug: Remove multi-queue setting + libvirt_vmxml.modify_vm_device(vmxml, 'interface', {'driver': None}) + qemu_conf = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() qemu_conf.save_image_format = save_format diff --git a/libvirt/tests/src/save_and_restore/save_with_options.py b/libvirt/tests/src/save_and_restore/save_with_options.py index fa776edf392..8aab446512c 100644 --- a/libvirt/tests/src/save_and_restore/save_with_options.py +++ b/libvirt/tests/src/save_and_restore/save_with_options.py @@ -8,6 +8,7 @@ from virttest import utils_package from virttest import virsh from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_test import libvirt from provider.save import save_base @@ -39,6 +40,10 @@ def run(test, params, env): bkxml = vmxml.copy() try: + # Workaround bug: Remove multi-queue setting + libvirt_vmxml.modify_vm_device(vmxml, 'interface', {'driver': None}) + vm.start() + pid_ping, upsince = save_base.pre_save_setup(vm) if pre_state == 'paused': virsh.suspend(vm_name, **VIRSH_ARGS) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py index c45ae7bb96a..f0d5ad95d8b 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py @@ -1,22 +1,21 @@ +import logging as log import os import re import time -import logging as log from avocado.utils import process from avocado.utils import software_manager - -from virttest import virsh -from virttest import utils_libvirtd +from virttest import libvirt_version from virttest import utils_config -from virttest import utils_misc from virttest import utils_libguestfs -from virttest import libvirt_version +from virttest import utils_libvirtd +from virttest import utils_misc +from virttest import virsh from virttest.libvirt_xml import vm_xml -from virttest.utils_test import libvirt from virttest.staging.service import Factory from virttest.staging.utils_memory import drop_caches - +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt # Using as lower capital is not the best way to do, but this is just a # workaround to avoid changing the entire file. @@ -363,6 +362,10 @@ def build_vm_xml(vm_name, **dargs): # Destroy vm first for setting configuration file if vm.state() == "running": vm.destroy(gracefully=False) + + # Workaround bug: Remove multi-queue setting + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + libvirt_vmxml.modify_vm_device(vmxml, 'interface', {'driver': None}) # Prepare test environment. if libvirtd_state == "off": libvirtd.stop() From 046f24f96f38672ccf18c3d467f2ca98441845c8 Mon Sep 17 00:00:00 2001 From: lcheng Date: Thu, 31 Oct 2024 09:14:07 +0800 Subject: [PATCH 0661/1055] qemu_monitor_socket_creation_delay: Fix a parameter issue Update cfg file to add a missing 'emulator_dict' parameter. Signed-off-by: lcheng --- libvirt/tests/cfg/daemon/qemu_monitor_socket_creation_delay.cfg | 1 + libvirt/tests/src/daemon/qemu_monitor_socket_creation_delay.py | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/daemon/qemu_monitor_socket_creation_delay.cfg b/libvirt/tests/cfg/daemon/qemu_monitor_socket_creation_delay.cfg index ab6b3389cea..04845cfa529 100644 --- a/libvirt/tests/cfg/daemon/qemu_monitor_socket_creation_delay.cfg +++ b/libvirt/tests/cfg/daemon/qemu_monitor_socket_creation_delay.cfg @@ -5,3 +5,4 @@ take_regular_screendumps = no qemu_wrapper_path = "../../deps/qemu_wrapper.py" tmp_qemu_wrapper_path = "/tmp/qemu_wrapper.py" + emulator_dict = {"path": "${tmp_qemu_wrapper_path}"} diff --git a/libvirt/tests/src/daemon/qemu_monitor_socket_creation_delay.py b/libvirt/tests/src/daemon/qemu_monitor_socket_creation_delay.py index ed3f20eada2..99c8c440f59 100644 --- a/libvirt/tests/src/daemon/qemu_monitor_socket_creation_delay.py +++ b/libvirt/tests/src/daemon/qemu_monitor_socket_creation_delay.py @@ -29,7 +29,6 @@ def run(test, params, env): os.chmod(tmp_qemu_wrapper_path, 0o755) process.run("chcon system_u:object_r:qemu_exec_t:s0 %s" % tmp_qemu_wrapper_path, shell=True) - emulator_dict = {"path": "%s" % tmp_qemu_wrapper_path} libvirt_vmxml.modify_vm_device(vmxml, "emulator", emulator_dict) vm.start() except virt_vm.VMStartError as e: From cf39cc06ab1121316cd0bc58a13c359a73b4dffb Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Thu, 31 Oct 2024 15:23:29 +0800 Subject: [PATCH 0662/1055] migration: Fix cpu mode and feature for aarch64 1. cpu mode should be host-passthrough on aarch64 2. sve disabled feature is not needed on both aarch64 and x86_64 Signed-off-by: Yingshun Cui --- libvirt/tests/cfg/migration/migrate_mem.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/migration/migrate_mem.cfg b/libvirt/tests/cfg/migration/migrate_mem.cfg index dafb5101a33..06c97aa1197 100644 --- a/libvirt/tests/cfg/migration/migrate_mem.cfg +++ b/libvirt/tests/cfg/migration/migrate_mem.cfg @@ -29,10 +29,10 @@ variants case: - mem_device: cpuxml_cpu_mode = "host-model" + aarch64: + cpuxml_cpu_mode = "host-passthrough" cpuxml_fallback = "allow" cpuxml_model = "qemu64" - cpu_feature = "svm" - cpu_feature_policy = "disable" cpuxml_numa_cell = [{'id': '0', 'cpus': '0-1', 'memory': '1024', 'unit': 'MiB', 'discard': 'yes'}, {'id': '1', 'cpus': '2-3', 'memory': '1024', 'unit': 'MiB'}] setvm_max_mem_rt_slots = "16" setvm_max_mem_rt = 8192 From 6139accd1ed5c4e49616dffcaee3940756db34f3 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 31 Oct 2024 22:40:40 -0400 Subject: [PATCH 0663/1055] Fixup:no default value when trying to get parameter value Signed-off-by: Haijiao Zhao --- .../connectivity/connectivity_check_ethernet_interface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py index 7f0d5b5fd45..77800e05a6b 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py @@ -55,7 +55,7 @@ def run(test, params, env): iface_mtu = params.get('iface_mtu') iface_mtu_2 = params.get('iface_mtu_2') iface_attrs = eval(params.get('iface_attrs')) - iface_attrs_2 = eval(params.get('iface_attrs_2')) + iface_attrs_2 = eval(params.get('iface_attrs_2', '{}')) iface_amount = params.get('iface_amount') outside_ip = params.get('outside_ip') host_iface = params.get('host_iface') From 38936a7fb508da55f0695dd920f2cb40515276d4 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Fri, 1 Nov 2024 06:03:00 -0400 Subject: [PATCH 0664/1055] iface_stat:Fix error of command timeout Send control+c to cancel previous command to make sure the next command could be executed correctly. Signed-off-by: Haijiao Zhao --- libvirt/tests/src/virtual_network/iface_stat.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_network/iface_stat.py b/libvirt/tests/src/virtual_network/iface_stat.py index 18c4553f87a..92ec87e8bb4 100644 --- a/libvirt/tests/src/virtual_network/iface_stat.py +++ b/libvirt/tests/src/virtual_network/iface_stat.py @@ -140,7 +140,8 @@ def _collect_and_compare_stat(vm_name, session, **virsh_args): for _ in range(3): session.cmd('curl -O https://avocado-project.org/data/' 'assets/jeos/27/jeos-27-64.qcow2.xz -L', - timeout=240, ignore_all_errors=True) + timeout=60, ignore_all_errors=True) + session.sendcontrol("c") host_iface_stat = get_host_iface_stat(vm_name, iface_target_dev, **virsh_args) From 1043d40315638a8d947c492875800ea8ff47daec Mon Sep 17 00:00:00 2001 From: Julia Graham Date: Tue, 8 Oct 2024 17:16:03 -0400 Subject: [PATCH 0665/1055] Multi_vms_with_stress: add a test about starting VMs with stress workload on host This PR adds: VIRT-301893 - [aarch64 only] Start VMs with maximum vcpus and stress on host Signed-off-by: Julia Graham --- .../tests/cfg/cpu/multi_vms_with_stress.cfg | 5 ++ .../tests/src/cpu/multi_vms_with_stress.py | 82 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 libvirt/tests/cfg/cpu/multi_vms_with_stress.cfg create mode 100644 libvirt/tests/src/cpu/multi_vms_with_stress.py diff --git a/libvirt/tests/cfg/cpu/multi_vms_with_stress.cfg b/libvirt/tests/cfg/cpu/multi_vms_with_stress.cfg new file mode 100644 index 00000000000..128fca6b241 --- /dev/null +++ b/libvirt/tests/cfg/cpu/multi_vms_with_stress.cfg @@ -0,0 +1,5 @@ +- multi_vms_with_stress: + type = multi_vms_with_stress + memory = 4194304 + vm_names = vm2 vm3 + stress_args = '--cpu 4 --io 4 --vm 2 --vm-bytes 128M &' diff --git a/libvirt/tests/src/cpu/multi_vms_with_stress.py b/libvirt/tests/src/cpu/multi_vms_with_stress.py new file mode 100644 index 00000000000..fec03d42e7c --- /dev/null +++ b/libvirt/tests/src/cpu/multi_vms_with_stress.py @@ -0,0 +1,82 @@ +import logging as log + +from avocado.utils import cpu + +from virttest import utils_test +from virttest.libvirt_xml import vm_xml + +LOG = log.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test that multiple vms can start when stress workload is running on the host. + + Steps: + 1. Prepare 3 vms that each have even vcpu number around 2/3 of # host_online_cpu + 2. Start stress workload on the host + 3. Start all vms and verify vms could be logged in normally + 4. Verify all vms could be gracefully shutdown successfully + """ + memory = params.get("memory", "4194304") + main_vm_name = params.get("main_vm") + main_vm = env.get_vm(main_vm_name) + vm_names = params.get("vm_names").split() + vms = [main_vm] + vmxml_backups = [] + + # Get vms + for i, vm_name in enumerate(vm_names): + vms.append(main_vm.clone(vm_name)) + + for vm in vms: + # Back up domain XMLs + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) + vmxml_backups.append(vmxml.copy()) + # Increase memory + vmxml.memory = int(memory) + vmxml.current_mem = int(memory) + vmxml.sync() + + try: + # Get host online cpu number + host_online_cpus = cpu.online_count() + LOG.debug("Host online CPU number: %s", str(host_online_cpus)) + + # Prepare 3 vms and each vm has even vcpus number which is about 2/3 of # host_online_cpu + for i, vm in enumerate(vms): + if vm.is_alive(): + vm.destroy() + vcpus_num = host_online_cpus * 2 // int(len(vms)) + if (vcpus_num % 2 != 0): + vcpus_num += 1 + vm_xml.VMXML.new_from_inactive_dumpxml(vm.name).set_vm_vcpus(vm.name, vcpus_num, vcpus_num, topology_correction=True) + LOG.debug("Defined vm %s with '%s' vcpu(s)", vm.name, str(vcpus_num)) + + # Start stress workload on the host + # params must include stress_args + utils_test.load_stress("stress_on_host", params=params) + + # Start all vms and verify vms could be logged in normally + for vm in vms: + vm.prepare_guest_agent() + vm.wait_for_login() + if (vm.state() != "running"): + test.fail("VM %s should be running, not %s" % (vm.name, vm.state())) + + # Verify all vms could be gracefully shutdown successfully + for vm in vms: + vm.shutdown() + if (vm.state() != "shut off"): + test.fail("VM %s should be shut off, not %s" % (vm.name, vm.state())) + + finally: + # Stop stress workload + utils_test.unload_stress("stress_on_host", params=params) + + # Recover VMs + for i, vm in enumerate(vms): + if vm.is_alive(): + vm.destroy(gracefully=False) + LOG.info("Restoring vm %s...", vm.name) + vmxml_backups[i].sync() From f9851b55502d4366fd6c1da2fed7411d1b4810bf Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Mon, 4 Nov 2024 15:53:38 +0800 Subject: [PATCH 0666/1055] migrate: Set start_vm to "yes" Add 'start_vm' to migrate_graphics.cfg and migrate_network.cfg. Signed-off-by: Yingshun Cui --- libvirt/tests/cfg/migration/migrate_graphics.cfg | 1 + libvirt/tests/cfg/migration/migrate_network.cfg | 1 + 2 files changed, 2 insertions(+) diff --git a/libvirt/tests/cfg/migration/migrate_graphics.cfg b/libvirt/tests/cfg/migration/migrate_graphics.cfg index 422f3e846d8..63c18164dd6 100644 --- a/libvirt/tests/cfg/migration/migrate_graphics.cfg +++ b/libvirt/tests/cfg/migration/migrate_graphics.cfg @@ -1,5 +1,6 @@ - migration.migrate_graphics: type = migrate_graphics + start_vm = "yes" migration_setup = 'yes' storage_type = 'nfs' setup_local_nfs = 'yes' diff --git a/libvirt/tests/cfg/migration/migrate_network.cfg b/libvirt/tests/cfg/migration/migrate_network.cfg index 94ae10bf57f..b79596b4e3b 100644 --- a/libvirt/tests/cfg/migration/migrate_network.cfg +++ b/libvirt/tests/cfg/migration/migrate_network.cfg @@ -1,5 +1,6 @@ - virsh.migrate_network: type = migrate_network + start_vm = "yes" # Console output can only be monitored via virsh console output only_pty = True take_regular_screendumps = no From 761cd27a34040d248c6cfc13db5c37171a33e06b Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Tue, 29 Oct 2024 06:07:07 -0400 Subject: [PATCH 0667/1055] Update case:connectivity check of ethernet type interface - VIRT-296218 - [ethernet] Check connectivity for ethernet type interface with managed='no' Signed-off-by: Haijiao Zhao --- .../connectivity_check_ethernet_interface.cfg | 8 +++++++- .../connectivity_check_ethernet_interface.py | 13 +++++++++++-- provider/virtual_network/network_base.py | 4 ++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_ethernet_interface.cfg b/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_ethernet_interface.cfg index 9602523eb8b..c24780f0042 100644 --- a/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_ethernet_interface.cfg +++ b/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_ethernet_interface.cfg @@ -52,11 +52,17 @@ err_msg = target dev must be supplied when managed='no' - target_dev_not_exist: iface_attrs = {'model': 'virtio', 'type_name': 'ethernet', 'target': {'dev': 'test', 'managed': 'no'}} - err_msg = target managed='no' but specified dev doesn't exist + err_msg = "target managed='no' but specified dev doesn't exist" - managed_yes: func_supported_since_libvirt_ver = (9,0,0) tap_type = tap iface_attrs = {'model': 'virtio', 'type_name': 'ethernet', 'target': {'dev': tap_name, 'managed': 'yes'}} err_msg = The .* interface already exists + - no_multi_queue_flag: + func_supported_since_libvirt_ver = (10,8,0) + tap_type = tap + tap_flag = + iface_attrs = {'model': 'virtio', 'type_name': 'ethernet', 'target': {'dev': tap_name, 'managed': 'no'}, 'driver': {'driver_attr': {'queues': '2'}}} + err_msg = Unable to create multiple fds for tap device .*\(maybe existing device was created without multi_queue flag\) variants: - managed_no: diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py index 77800e05a6b..2227eabd9dc 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py @@ -70,13 +70,22 @@ def run(test, params, env): try: mac_addr = vm_xml.VMXML.get_first_mac_by_name(vm_name, virsh_ins) + tap_flag = '' + for attr in (iface_attrs, iface_attrs_2): + if attr.get('driver', {}).get('driver_attr', {}).get('queues'): + tap_flag = 'multi_queue' + break + if params.get('tap_flag') is not None: + tap_flag = params.get('tap_flag') if tap_type: if tap_type == 'tap': utils_net.create_linux_bridge_tmux(bridge_name, host_iface) - network_base.create_tap(tap_name, bridge_name, test_user) + network_base.create_tap( + tap_name, bridge_name, test_user, flag=tap_flag) if iface_amount == 'two_ifaces': - network_base.create_tap(tap_name_2, 'virbr0', test_user) + network_base.create_tap( + tap_name_2, 'virbr0', test_user, flag=tap_flag) elif tap_type == 'macvtap': mac_addr = network_base.create_macvtap(tap_name, host_iface, test_user) diff --git a/provider/virtual_network/network_base.py b/provider/virtual_network/network_base.py index f3ff7410961..4360c1b1b52 100644 --- a/provider/virtual_network/network_base.py +++ b/provider/virtual_network/network_base.py @@ -139,7 +139,7 @@ def _ping(): raise exceptions.TestFail(msg) -def create_tap(tap_name, bridge_name, user): +def create_tap(tap_name, bridge_name, user, flag=''): """ Create tap device @@ -149,7 +149,7 @@ def create_tap(tap_name, bridge_name, user): """ # Create tap device with ip command tap_cmd = f'ip tuntap add mode tap user {user} group {user} name ' \ - f'{tap_name};ip link set {tap_name} up;' \ + f'{tap_name} {flag};ip link set {tap_name} up;' \ f'ip link set {tap_name} master {bridge_name}' # Execute command as root process.run(tap_cmd, shell=True, verbose=True) From 0d6e344f93dd9136555e6a3d7877e8e3177c73d1 Mon Sep 17 00:00:00 2001 From: Kowshik Jois B S Date: Mon, 4 Nov 2024 16:34:56 +0530 Subject: [PATCH 0668/1055] Removed python2 imports Signed-off-by: Kowshik Jois B S --- libvirt/tests/src/daemon/libvirtd/libvirtd.py | 7 ++----- libvirt/tests/src/graphics/graphics_functional.py | 7 ++----- libvirt/tests/src/virsh_cmd/volume/vol_concurrent.py | 7 ++----- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/libvirt/tests/src/daemon/libvirtd/libvirtd.py b/libvirt/tests/src/daemon/libvirtd/libvirtd.py index bb2fde6b4cb..cc7540f4940 100644 --- a/libvirt/tests/src/daemon/libvirtd/libvirtd.py +++ b/libvirt/tests/src/daemon/libvirtd/libvirtd.py @@ -5,10 +5,7 @@ import re import threading -try: - import queue as Queue -except ImportError: - import Queue +import queue from avocado.utils import process @@ -23,7 +20,7 @@ from virttest.utils_test import libvirt -msg_queue = Queue.Queue() +msg_queue = queue.Queue() daemon_conf = None daemon = None diff --git a/libvirt/tests/src/graphics/graphics_functional.py b/libvirt/tests/src/graphics/graphics_functional.py index 41e8e91bae3..7e81cdaf013 100644 --- a/libvirt/tests/src/graphics/graphics_functional.py +++ b/libvirt/tests/src/graphics/graphics_functional.py @@ -13,10 +13,7 @@ import locale import base64 import ipaddress -try: - import queue as Queue -except ImportError: - import Queue +import queue import stat @@ -39,7 +36,7 @@ from virttest.utils_test import libvirt -q = Queue.Queue() +q = queue.Queue() # Using as lower capital is not the best way to do, but this is just a diff --git a/libvirt/tests/src/virsh_cmd/volume/vol_concurrent.py b/libvirt/tests/src/virsh_cmd/volume/vol_concurrent.py index 3b965c6fcda..5d0497d36b4 100644 --- a/libvirt/tests/src/virsh_cmd/volume/vol_concurrent.py +++ b/libvirt/tests/src/virsh_cmd/volume/vol_concurrent.py @@ -2,10 +2,7 @@ import os import threading import re -try: - import queue as Queue -except ImportError: - import Queue +import queue from avocado.core import exceptions @@ -15,7 +12,7 @@ from virttest.utils_test import libvirt as utlv -q = Queue.Queue() +q = queue.Queue() # Using as lower capital is not the best way to do, but this is just a From 25a28fa47794990fff576ecc0549b65b73b0f546 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 5 Nov 2024 09:32:18 +0800 Subject: [PATCH 0669/1055] migrate_vm: Fixup umount failure To avoid clearing the nfs environment twice, clear storage_type in the test to skip setup/cleanup nfs parts. Signed-off-by: Yingshun Cui --- libvirt/tests/cfg/migration/migrate_vm.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration/migrate_vm.cfg b/libvirt/tests/cfg/migration/migrate_vm.cfg index 47591e3cd03..646c8a44789 100644 --- a/libvirt/tests/cfg/migration/migrate_vm.cfg +++ b/libvirt/tests/cfg/migration/migrate_vm.cfg @@ -11,10 +11,10 @@ client_user = "root" client_pwd = "${migrate_source_pwd}" start_vm = "no" + storage_type = transport = "ssh" port = "22" client = "ssh" - start_vm = "no" ssh_port = "${port}" # setup NFS test environment nfs_client_ip = "${server_ip}" From 10db4eba1539593e050d1e2b12c86fbc80c8af8d Mon Sep 17 00:00:00 2001 From: nanli Date: Tue, 5 Nov 2024 16:44:02 +0800 Subject: [PATCH 0670/1055] fix memory case failed due to empty clean file in teardown give default value for clean file Signed-off-by: nanli --- .../memory_devices/virtio_memory_with_numa_node_tuning.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/memory/memory_devices/virtio_memory_with_numa_node_tuning.py b/libvirt/tests/src/memory/memory_devices/virtio_memory_with_numa_node_tuning.py index 3fce77bf768..cb35ec81ea7 100644 --- a/libvirt/tests/src/memory/memory_devices/virtio_memory_with_numa_node_tuning.py +++ b/libvirt/tests/src/memory/memory_devices/virtio_memory_with_numa_node_tuning.py @@ -430,8 +430,8 @@ def teardown_test(): """ test.log.info("TEST_TEARDOWN: Clean up env.") bkxml.sync() - for file in params.get("cleanup_file"): - process.run("echo 0 > %s" % file) + for file in params.get("cleanup_file", []): + process.run("echo 0 > %s" % file, ignore_status=True) hg_path = params.get("hg_path") if hg_path: process.run("umount %s; rm %s" % (hg_path, hg_path), ignore_status=True) From f8f5a6c639ea14055f916962540cd45af6effd94 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Mon, 29 Jul 2024 15:33:40 +0800 Subject: [PATCH 0671/1055] pci_controller_memreserve: add new case Case ID: XXXX-301516 XXXX-301654 Test scenarios: test memReserve option for a controller is functional. - pcie-root-port - pci-bridge Signed-off-by: Dan Zheng --- .../controller/pci_controller_memreserve.cfg | 38 +++ .../controller/pci_controller_memreserve.py | 220 ++++++++++++++++++ 2 files changed, 258 insertions(+) create mode 100644 libvirt/tests/cfg/controller/pci_controller_memreserve.cfg create mode 100644 libvirt/tests/src/controller/pci_controller_memreserve.py diff --git a/libvirt/tests/cfg/controller/pci_controller_memreserve.cfg b/libvirt/tests/cfg/controller/pci_controller_memreserve.cfg new file mode 100644 index 00000000000..4f44dc1f84f --- /dev/null +++ b/libvirt/tests/cfg/controller/pci_controller_memreserve.cfg @@ -0,0 +1,38 @@ +- pci_controller_memreserve: + type = pci_controller_memreserve + start_vm = no + func_supported_since_libvirt_ver = (10, 3, 0) + # Two vms are required for the tests, one for ovmf and the other for seabios + vms = "avocado-vt-vm1 vm2" + only q35 + variants: + - 8M: + memReserve = 8192 + - 10M: + memReserve = 10240 + ovmf: + expect_memReserve = 16384 + - 16M: + memReserve = 16384 + - 32M: + memReserve = 32768 + variants: + - firmware: + variants: + - ovmf: + firmware_type = "ovmf" + loader_dict = {'os_firmware': 'efi'} + - seabios: + firmware_type = "seabios" + variants: + - controller: + variants: + - pci_bridge: + only q35 + contr_model = "pci-bridge" + depend_contr_dict = {"type": "pci", "model": "pcie-to-pci-bridge", "index": "%s"} + contr_pattern = ".*PCI-PCI bridge" + - pcie_root_port: + contr_model = "pcie-root-port" + contr_pattern = "%s.*PCIe Root port" + contr_dict = {"type": "pci", "model": "${contr_model}", "index": "%s", "target": {"memReserve":"${memReserve}"}} diff --git a/libvirt/tests/src/controller/pci_controller_memreserve.py b/libvirt/tests/src/controller/pci_controller_memreserve.py new file mode 100644 index 00000000000..45dc3fd4e47 --- /dev/null +++ b/libvirt/tests/src/controller/pci_controller_memreserve.py @@ -0,0 +1,220 @@ +import logging as log +import re + +from virttest import libvirt_version +from virttest import virsh + +from virttest.libvirt_xml.vm_xml import VMXML +from virttest.utils_libvirt import libvirt_pcicontr +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.guest_os_booting import guest_os_booting_base as guest_os + +# 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__) + + +def get_mem_reserve_size_in_vm(test, contr_addr, params, session): + """ + Get mem reserve size of specified controller within vm + + :param test: test object + :param contr_addr: str, the controller address + :param params: dict, test parameters + :param session: vm session + :return: int, the controller's memory reserve size + """ + contr_pattern = params.get("contr_pattern") + # According to test results, pcie root port's address in vm xml + # is consistent with the one within the vm, but pci-bridge doesn't. + # For example, + # Pci-bridge address in vm xml: + #
+ # But + # lspci shows in the vm: + # 08:01.0 PCI bridge: Red Hat, Inc. QEMU PCI-PCI bridge + # So codes do not match the address for pci-bridge so far + if contr_pattern.count("%s"): + contr_pattern = params.get("contr_pattern") % contr_addr + + lspci_output = session.cmd_output("lspci").strip() + test.log.debug("The lspci in vm:\n%s", lspci_output) + + found_contr = re.findall(contr_pattern, lspci_output) + if not found_contr: + test.fail("Can not find the controller with pattern %s" % contr_pattern) + test.log.debug("Found the controller:%s", found_contr[0]) + contr_addr = found_contr[0].split(" ")[0] + cmd = "lspci -vvv -s %s | grep 'Memory behind bridge:'" % contr_addr + contr_info = session.cmd_output(cmd).strip() + test.log.debug("Got the controller detailed information:%s", contr_info) + mem_reserve_size = re.findall("\[size=(.*)M\]", contr_info)[0] + test.log.debug("Got the default memory reserve size: %sM", mem_reserve_size) + return int(mem_reserve_size) + + +def get_controller_address(controller_xml, test): + """ + Get the controller's address from vm xml. + It only applies to pcie-root-port controller because pci-bridge's + address in vm xml is different with the one within the vm. + + For example, bus='0x00' slot='0x02' function='0x7' + In the lspci, the device address: 00:02.7 + + :param controller_xml: the controller's xml object + :param test: test object + :return: str, the expected controller's address within the vm + """ + test.log.debug("The controller:%s", controller_xml) + cntl_attrs = controller_xml.fetch_attrs()["address"]["attrs"] + bus = cntl_attrs["bus"].removeprefix("0x") + slot = cntl_attrs["slot"].removeprefix("0x") + func = cntl_attrs["function"].removeprefix("0x") + addr_in_vm = bus + ":" + slot + "." + func + test.log.debug("The address for this controller:%s", addr_in_vm) + return addr_in_vm + + +def get_controller(test, vm_xml, contr_dict): + """ + Get the controller from the vm xml + + :param test: test object + :param vm_xml: VMXML object + :param contr_dict: dict, the controller's configuration + :return: controller xml object + """ + contr_index = contr_dict["index"] + contr_model = contr_dict["model"] + contr_type = contr_dict["type"] + for cntl in vm_xml.devices.by_device_tag('controller'): + if (cntl.type == contr_type and + cntl.model == contr_model and + cntl.index == contr_index): + logging.debug("Found the controller:%s", cntl) + return cntl + test.error("Fail to get the controller in guest xml with " + "index %s, model %s, type %s" % (contr_index, + contr_model, + contr_type)) + + +def check__memReserve_by_controller_xml(test, params, vm_name, target_cntl): + """ + Check memory reserve value of specified controller in vm xml + + :param test: test object + :param params: dict, test parameters + :param vm_name: str, vm name + :param target_cntl: controller's xml + """ + cur_vm_xml = VMXML.new_from_dumpxml(vm_name) + expect_memReserve = params.get("memReserve") + cntl = get_controller(test, cur_vm_xml, target_cntl) + actual_memReserve = cntl.target.get("memReserve") + if not actual_memReserve or int(actual_memReserve) != int(expect_memReserve): + test.fail("Expect memReserve to be %s, " + "but found %s" % (expect_memReserve, actual_memReserve)) + else: + test.log.debug("Verify: The memReserve value in guest xml - PASS") + + +def update_vm_xml(test, params, vm_xml): + """ + Update vm xml with necessary controllers + + :param test: test object + :param params: dict, test parameters + :param vm_xml: VMXML object + """ + def _add_contr(controller_dict): + """ + Common function for adding a controller to vm xml + + :param controller_dict: dict, controller configuration + """ + dev_obj = libvirt_vmxml.create_vm_device_by_type("controller", controller_dict) + libvirt.add_vm_device( + vm_xml, dev_obj, virsh_instance=virsh + ) + test.log.debug("Add controller configuration:%s", controller_dict) + + test.log.debug("Step: Get maximum index of specified controller") + depend_contr_dict = params.get("depend_contr_dict") + contr_dict = params.get("contr_dict") + ret_indexes = libvirt_pcicontr.get_max_contr_indexes(vm_xml, + 'pci', + "pcie-root-port") + cntr_index = int(ret_indexes[0]) + if depend_contr_dict: + cntr_index += 1 + depend_contr_dict = eval(depend_contr_dict % cntr_index) + _add_contr(depend_contr_dict) + + test.log.debug("Step: Add controller with specified configuration") + contr_dict = contr_dict % (cntr_index + 1) + params["contr_dict"] = contr_dict + _add_contr(eval(contr_dict)) + + +def run(test, params, env): + """ + Test PCI controllers' memory reserve option + 1. Backup guest xml before the tests + 2. Modify guest xml and define the guest + 3. Start guest + 4. Do checking in vm xml and within vm + """ + libvirt_version.is_libvirt_feature_supported(params) + + firmware_type = params.get("firmware_type") + loader_dict = eval(params.get("loader_dict", "{}")) + new_memReserve = params.get("memReserve") + expect_memReserve = params.get("expect_memReserve", new_memReserve) + params['expect_memReserve'] = expect_memReserve + virsh_options = {'debug': True, 'ignore_status': False} + + vm_name = guest_os.get_vm(params) + vm = env.get_vm(vm_name) + vm_xml_obj = VMXML.new_from_inactive_dumpxml(vm_name) + vm_xml_backup = vm_xml_obj.copy() + try: + test.log.debug("Step: Update vm firmware configuration") + vmxml = guest_os.prepare_os_xml(vm_name, loader_dict, firmware_type=firmware_type) + test.log.debug("Step: Configure the controller with specified memReserve value") + update_vm_xml(test, params, vmxml) + cur_vm_xml = VMXML.new_from_inactive_dumpxml(vm_name) + contr_dict = eval(params.get("contr_dict")) + test.log.debug("Step: Get the added controller xml") + target_cntl = get_controller(test, cur_vm_xml, contr_dict) + test.log.debug("Step: Get the address of the added controller") + contr_address = get_controller_address(target_cntl, test) + + test.log.debug("Step: Start vm") + virsh.start(vm_name, **virsh_options) + logging.debug("Test VM XML after starting:" + "\n%s", VMXML.new_from_dumpxml(vm_name)) + + test.log.debug("Step: Check vm dumpxml for specified memReserve value") + check__memReserve_by_controller_xml(test, params, vm_name, target_cntl) + test.log.debug("Step: Check the controller's new reserved memory value in vm") + session = vm.wait_for_login() + actual_reserve_size = get_mem_reserve_size_in_vm(test, + contr_address, + params, + session + ) + actual_reserve_size = int(actual_reserve_size) * 1024 + if actual_reserve_size != int(expect_memReserve): + test.fail("Expect mem reserve size " + "in vm to be %d, but found %d" % (expect_memReserve, + actual_reserve_size)) + else: + test.log.debug("Verify: The mem reserve size " + "in vm is %d as expected - PASS", actual_reserve_size) + session.close() + finally: + vm_xml_backup.sync() From 25f0cddd86c518cb74f61f26f856e2a08fe6ba69 Mon Sep 17 00:00:00 2001 From: nanli Date: Wed, 6 Nov 2024 15:01:17 +0800 Subject: [PATCH 0672/1055] fix virtio memory unplug case error msg compability issue unplug error msg needs to get compability Signed-off-by: nanli --- .../memory/memory_devices/virtio_mem_hot_unplug.cfg | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hot_unplug.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hot_unplug.cfg index cad69fddb20..0e042b46b47 100644 --- a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hot_unplug.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hot_unplug.cfg @@ -39,6 +39,9 @@ func_supported_since_libvirt_ver = (10, 0, 0) func_supported_since_qemu_kvm_ver = (8, 2, 0) machine_version = "9.4.0" + zero_size_error_msg = "virtio-mem device cannot get unplugged while 'size' != '0'" + zero_request_error_msg = "virtio-mem device cannot get unplugged while 'requested-size' != '0'" + basic_error_msg = "virtio-mem device cannot get unplugged while some of its memory is still plugged" variants case: - target_and_address: unplug_request_size = '0' @@ -74,13 +77,13 @@ nonexistent_mem: unplug_error = "model 'virtio-mem' memory device not present in the domain configuration" none_zero_current: - unplug_error = "virtio-mem device cannot get unplugged while 'size' != '0'" + unplug_error = "${zero_size_error_msg}|${basic_error_msg}" none_zero_request: - unplug_error = "virtio-mem device cannot get unplugged while 'requested-size' != '0'" + unplug_error = "${zero_request_error_msg}|${basic_error_msg}" - detach_alias: no nonexistent_mem detach_method = "detach_alias" none_zero_current: - unplug_error = "virtio-mem device cannot get unplugged while 'size' != '0'" + unplug_error = "${zero_size_error_msg}|${basic_error_msg}" none_zero_request: - unplug_error = "virtio-mem device cannot get unplugged while 'requested-size' != '0'" + unplug_error = "${zero_request_error_msg}|${basic_error_msg}" From 3078a053b37201df77ea2516d431f8a97747eb6b Mon Sep 17 00:00:00 2001 From: nanli Date: Mon, 14 Oct 2024 11:33:27 +0800 Subject: [PATCH 0673/1055] case update: add new disk to check domblkthreshold xxxx-294599: Do domblkthreshold for device with backing chain element Signed-off-by: nanli --- ...blkthreshold_with_backingchain_element.cfg | 8 +- ...mblkthreshold_with_backingchain_element.py | 73 +++++++++++++------ 2 files changed, 56 insertions(+), 25 deletions(-) diff --git a/libvirt/tests/cfg/backingchain/virsh_domblk/domblkthreshold_with_backingchain_element.cfg b/libvirt/tests/cfg/backingchain/virsh_domblk/domblkthreshold_with_backingchain_element.cfg index 487c3484441..8c327f6ac1a 100644 --- a/libvirt/tests/cfg/backingchain/virsh_domblk/domblkthreshold_with_backingchain_element.cfg +++ b/libvirt/tests/cfg/backingchain/virsh_domblk/domblkthreshold_with_backingchain_element.cfg @@ -1,8 +1,14 @@ - backingchain.virsh_domblk: type = domblkthreshold_with_backingchain_element start_vm = 'yes' - target_disk = 'vda' + target_disk = 'vdb' domblk_threshold = '1' + actual_threshold = "1" + disk_type = "file" + disk_image_format = "raw" + disk_dict = {"type_name":"${disk_type}", "target":{"dev": "${target_disk}", "bus": "virtio"}, "driver": {"name": "qemu", "type": "raw"}} + disk_size = "3G" + snap_extra = " -diskspec vda,snapshot=no" variants case_name: - backing_target: domblk_index = 3 diff --git a/libvirt/tests/src/backingchain/virsh_domblk/domblkthreshold_with_backingchain_element.py b/libvirt/tests/src/backingchain/virsh_domblk/domblkthreshold_with_backingchain_element.py index 733ea35675e..ddfce7a2781 100644 --- a/libvirt/tests/src/backingchain/virsh_domblk/domblkthreshold_with_backingchain_element.py +++ b/libvirt/tests/src/backingchain/virsh_domblk/domblkthreshold_with_backingchain_element.py @@ -7,6 +7,7 @@ from virttest.libvirt_xml import vm_xml from provider.backingchain import blockcommand_base +from provider.virtual_disk import disk_base def run(test, params, env): @@ -18,27 +19,34 @@ def setup(): Prepare active domain and backingchain """ test.log.info("Setup env.") + test_obj.new_image_path = disk_obj.add_vm_disk(disk_type, disk_dict, + size=disk_size) test_obj.backingchain_common_setup(create_snap=True, - snap_num=4) + snap_num=4, extra=snap_extra) + test.log.debug("Preparing xml is:\n %s", vm_xml.VMXML.new_from_dumpxml(vm.name)) def test_backing_target(): """ Do domblkthreshold for the backing file device target """ - test.log.info("TEST_STEP1:Set domblkthreshold for backing file device") + test.log.info("TEST_STEP1-2:Set domblkthreshold for backing file device") + time.sleep(5) virsh.domblkthreshold(vm_name, '%s[%s]' % (target_disk, domblk_index), domblk_threshold, debug=True, ignore_status=False) - check_domstats_threshold(domstats_option, domblk_threshold) + check_domstats_threshold(domstats_option, actual_threshold) - test.log.info("TEST_STEP2:Do blockcommit and check event") + test.log.info("TEST_STEP3-4:Write file and check event") + expected_event = event % (vm_name, target_disk, domblk_index, + actual_threshold) event_session = virsh.EventTracker.start_get_event(vm_name) write_file() + check_event(event_session, expected_event, existed=False) + + test.log.info("TEST_STEP5-7:Do blockcommit and check event") virsh.blockcommit(vm.name, target_disk, - commit_options % test_obj.snap_path_list[1], + commit_options % test_obj.snap_path_list[0], ignore_status=False, debug=True) - expected_event = event % (vm_name, target_disk, domblk_index, - domblk_threshold) check_event(event_session, expected_event) check_domstats_threshold(domstats_option) @@ -51,14 +59,13 @@ def test_entire_disk(): virsh.domblkthreshold(vm_name, '%s' % target_disk, domblk_threshold, debug=True, ignore_status=False) - check_domstats_threshold(domstats_option, domblk_threshold) + check_domstats_threshold(domstats_option, actual_threshold) test.log.info("TEST_STEP2:Write file in guest and check event") event_session = virsh.EventTracker.start_get_event(vm_name) write_file() - expected_event = event % (vm_name, target_disk, domblk_threshold) + expected_event = event % (vm_name, target_disk, actual_threshold) check_event(event_session, expected_event) - check_domstats_threshold(domstats_option) def teardown(): """ @@ -80,19 +87,20 @@ def check_domstats_threshold(options, threshold_value=None): :param threshold_value: domstats threshold value, if it is None, result should be no output """ - if not utils_misc.wait_for( - lambda: - bool(threshold_value) == ('threshold' in virsh.domstats( - vm_name, options, debug=True).stdout_text.strip()), 30, 2): - test.fail('Failed to get expected threshold value in 30s') - - result = virsh.domstats(vm_name, options, debug=True, - ignore_status=False).stdout_text.strip() if not threshold_value: + result = virsh.domstats(vm_name, options, debug=True, + ignore_status=False).stdout_text.strip() pattern = "block.*.threshold" if re.search(pattern, result): test.fail("Threshold: %s should not be in %s" % (pattern, result)) else: + if not utils_misc.wait_for( + lambda: + bool(threshold_value) == ('threshold' in virsh.domstats( + vm_name, options, debug=True).stdout_text.strip()), 30, 2): + test.fail('Failed to get expected threshold value in 30s') + result = virsh.domstats(vm_name, options, debug=True, + ignore_status=False).stdout_text.strip() pattern = r"block.*.threshold=%s" % threshold_value if not re.search(pattern, result): test.fail("Not get correct threshold: %s should be in %s" % ( @@ -103,21 +111,31 @@ def write_file(): Write file in guest """ session = vm.wait_for_login() - utils_disk.dd_data_to_vm_disk(session, large_file, bs='4M', count='200') + cmd = "mkfs.ext4 /dev/%s;mount /dev/%s /mnt" % (target_disk, target_disk) + session.cmd_status_output(cmd) + utils_disk.dd_data_to_vm_disk(session, mount_file, bs='8M', count='400') session.close() - def check_event(event_session, expected_event): + def check_event(event_session, expected_event, existed=True): """ Check event correct :param event_session: virsh session :param expected_event: expected event pattern + :param existed: if event existed, default True """ test.log.debug('Checking event pattern is -> %s', expected_event) - event_output = virsh.EventTracker.finish_get_event(event_session) - if not re.search(expected_event, event_output): - test.fail('Not find: %s from event output:%s' % ( - expected_event, event_output)) + event_output = event_session.get_stripped_output() + search_res = re.search(expected_event, event_output) + if existed: + if not search_res: + test.fail('Not find: %s from event output:%s' % ( + expected_event, event_output)) + else: + if search_res: + test.fail('Event:%s should not exist in output:%s' % ( + expected_event, event_output)) + test.log.debug("Checking event successfully") # Process cartesian parameters vm_name = params.get("main_vm") @@ -126,11 +144,18 @@ def check_event(event_session, expected_event): case_name = params.get('case_name', '') target_disk = params.get('target_disk') domblk_threshold = params.get('domblk_threshold') + actual_threshold = params.get('actual_threshold') domblk_index = params.get('domblk_index') domstats_option = params.get('domstats_option') commit_options = params.get('commit_options') + disk_dict = eval(params.get('disk_dict', '{}')) + disk_type = params.get("disk_type") + disk_size = params.get("disk_size") + mount_file = params.get("mount_file", "/mnt/file") + snap_extra = params.get("snap_extra") test_obj = blockcommand_base.BlockCommand(test, vm, params) + disk_obj = disk_base.DiskBase(test, vm, params) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) bkxml = vmxml.copy() From e70489a0b0e04e44dd0c650c50cbd362ebd71499 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Thu, 7 Nov 2024 01:19:22 -0500 Subject: [PATCH 0674/1055] Blkiotune: update test result checking Move script files from virsh_cmd to guest_resource_control. Now the test result for change_device_weights.options.none.vm_fail_start has been changed. Based on the new test design in blkiotune(RHEL-45185), both expected error message and successcul run are expected. The updated lines are from L215 to L219. Signed-off-by: Meina Li --- .../domain => guest_resource_control}/virsh_blkiotune.cfg | 0 .../domain => guest_resource_control}/virsh_blkiotune.py | 7 +++++-- 2 files changed, 5 insertions(+), 2 deletions(-) rename libvirt/tests/cfg/{virsh_cmd/domain => guest_resource_control}/virsh_blkiotune.cfg (100%) rename libvirt/tests/src/{virsh_cmd/domain => guest_resource_control}/virsh_blkiotune.py (97%) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_blkiotune.cfg b/libvirt/tests/cfg/guest_resource_control/virsh_blkiotune.cfg similarity index 100% rename from libvirt/tests/cfg/virsh_cmd/domain/virsh_blkiotune.cfg rename to libvirt/tests/cfg/guest_resource_control/virsh_blkiotune.cfg diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_blkiotune.py b/libvirt/tests/src/guest_resource_control/virsh_blkiotune.py similarity index 97% rename from libvirt/tests/src/virsh_cmd/domain/virsh_blkiotune.py rename to libvirt/tests/src/guest_resource_control/virsh_blkiotune.py index 23c89d2f021..9fa4c2f0134 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_blkiotune.py +++ b/libvirt/tests/src/guest_resource_control/virsh_blkiotune.py @@ -212,8 +212,11 @@ def set_blkio_parameter(test, params, cgstop): if validate_vm_not_start: result = virsh.start(vm_name, debug=True) vm_not_start_error_msg = params.get("vm_not_start_error_msg") - if vm_not_start_error_msg not in result.stderr_text: - test.fail("can not find error message: %s" % vm_not_start_error_msg) + if result.exit_status: + if vm_not_start_error_msg in result.stderr_text: + logging.info("Get the expected error message: %s" % vm_not_start_error_msg) + else: + test.fail("Get unexpected result: %s" % result.stderr_text) def prepare_scheduler(params, test, vm): From 64fc4321df192589b5985fecebcf487716b0370a Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Fri, 18 Oct 2024 15:11:22 +0800 Subject: [PATCH 0675/1055] v2v: add new case on ubuntu22.04 partial efi Signed-off-by: vwu-vera --- v2v/tests/cfg/specific_kvm.cfg | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/v2v/tests/cfg/specific_kvm.cfg b/v2v/tests/cfg/specific_kvm.cfg index da9b5e08dad..4709d4d5be8 100644 --- a/v2v/tests/cfg/specific_kvm.cfg +++ b/v2v/tests/cfg/specific_kvm.cfg @@ -290,6 +290,12 @@ main_vm = 'VM_NON_EXIST_NETWORK_V2V_EXAMPLE' skip_vm_check = yes skip_reason = "bz#RHEL-1718 on win11 guest" + - partial_efi: + only source_esx.esx_80 + boottype = 2 + main_vm = 'VM_NAME_80_UBUNTU_PARTIAL_EFI_V2V_EXAMPLE' + skip_vm_check = yes + skip_reason = "Special configuration. No console available" variants: - positive_test: status_error = 'no' From d477e59018ba32889ddf2f3b75418a8393a6f582 Mon Sep 17 00:00:00 2001 From: lcheng Date: Sun, 10 Nov 2024 23:43:11 +0800 Subject: [PATCH 0676/1055] migration: Update check vm state method When vm state is wrong, libvirt.check_vm_state don't report the error. So update check_vm_status_during_mig() and use it to check vm state. Signed-off-by: lcheng --- .../kill_qemu_during_finishphase.cfg | 9 +++---- .../migration_timeout_action.cfg | 3 +-- .../kill_qemu_during_finishphase.py | 18 ++++++++------ provider/migration/migration_base.py | 24 +++++++++---------- 4 files changed, 29 insertions(+), 25 deletions(-) diff --git a/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_finishphase.cfg b/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_finishphase.cfg index 15a2aa71637..b55789a6f36 100644 --- a/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_finishphase.cfg +++ b/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_finishphase.cfg @@ -29,6 +29,9 @@ migrate_again = "yes" service_name = "qemu-kvm" migrate_again_status_error = "no" + virsh_migrate_extra = "--postcopy-bandwidth 10 --bandwidth 10" + virsh_migrate_extra_mig_again = " " + action_during_mig = '[{"func": "virsh.migrate_postcopy", "func_param": "'%s' % params.get('migrate_main_vm')", "need_sleep_time": "10"}, {"func": "check_vm_status_during_mig", "func_param": {"vm_name": "${main_vm}", "src_state":"paused", "src_reason": "post-copy"}, "need_sleep_time": "5"}, {"func": "libvirt_service.kill_service", "func_param": "params"}]' variants: - p2p: virsh_migrate_options = '--live --p2p --verbose' @@ -36,18 +39,16 @@ virsh_migrate_options = '--live --verbose' variants: - with_postcopy: - postcopy_options = "--timeout 2 --timeout-postcopy --postcopy --postcopy-bandwidth 10 --bandwidth 10" + postcopy_options = "--postcopy" variants test_case: - kill_dest_qemu: service_on_dst = "yes" expected_event_src = ["Suspended Post-copy", "Suspended Post-copy Error"] expected_event_target = ["Stopped Failed"] - action_during_mig = '[{"func": "libvirt.check_vm_state", "func_param": {"vm_name": "${main_vm}", "state": "paused", "reason":"post-copy"}, "need_sleep_time": "5"}, {"func": "libvirt_service.kill_service", "func_param": "params"}]' expected_dest_state = "nonexist" expected_src_state = "paused" - kill_src_qemu: expected_dest_state = "running" expected_src_state = "shut off" - expected_event_src = ["Suspended Post-copy Error", "Stopped Failed"] + expected_event_src = ["Suspended Post-copy", "Stopped Failed"] expected_event_target = ["Resumed Post-copy Error"] - action_during_mig = '[{"func": "libvirt.check_vm_state", "func_param": {"vm_name": "${main_vm}", "state": "paused", "reason":"post-copy"}, "need_sleep_time": "8"}, {"func": "libvirt_service.kill_service", "func_param": "params"}]' diff --git a/libvirt/tests/cfg/migration/migration_performance_tuning/migration_timeout_action.cfg b/libvirt/tests/cfg/migration/migration_performance_tuning/migration_timeout_action.cfg index e3d0baa0fc4..7da49fd69a8 100644 --- a/libvirt/tests/cfg/migration/migration_performance_tuning/migration_timeout_action.cfg +++ b/libvirt/tests/cfg/migration/migration_performance_tuning/migration_timeout_action.cfg @@ -29,8 +29,7 @@ test_case = "timeout_action" migrate_speed = "5" timeout_value = "8" - action_during_mig = '[{"func": "check_vm_status_during_mig", "after_event": "iteration: '1'", "func_param": 'params'}, {"func": "set_migrate_speed_to_high", "func_param": "params"}]' - vm_status_during_mig = "paused" + action_during_mig = '[{"func": "check_vm_status_during_mig", "after_event": "iteration: '1'", "func_param": {"vm_name": "${main_vm}", "dest_state": "paused", "src_state":"paused", "dest_uri": "${virsh_migrate_desturi}"}, "need_sleep_time": "${timeout_value}"}, {"func": "set_migrate_speed_to_high", "func_param": "params"}]' stress_package = "stress" stress_args = "--cpu 8 --io 4 --vm 2 --vm-bytes 128M --timeout 20s" variants: diff --git a/libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_qemu_during_finishphase.py b/libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_qemu_during_finishphase.py index 456b987069a..8436ff452de 100644 --- a/libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_qemu_during_finishphase.py +++ b/libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_qemu_during_finishphase.py @@ -30,10 +30,17 @@ def verify_test(): if expected_src_state: if not libvirt.check_vm_state(vm.name, expected_src_state, uri=migration_obj.src_uri): test.fail("Migrated VM failed to be in %s state at source." % expected_src_state) - if expected_dest_state and expected_dest_state == "nonexist": - virsh.domstate(vm_name, uri=dest_uri, debug=True) - if virsh.domain_exists(vm_name, uri=dest_uri): - test.fail("The domain on target host is found, but expected not") + if expected_dest_state: + if expected_dest_state == "nonexist": + virsh.domstate(vm_name, uri=dest_uri, debug=True) + if virsh.domain_exists(vm_name, uri=dest_uri): + test.fail("The domain on target host is found, but expected not") + else: + if not libvirt.check_vm_state(vm.name, expected_dest_state, uri=dest_uri): + test.fail("Migrated VM failed to be in %s state at dest." % expected_dest_state) + + if expected_dest_state == "running": + virsh.destroy(vm_name, uri=dest_uri) if expected_src_state == "shut off": vm.start() vm.wait_for_login().close() @@ -42,9 +49,6 @@ def verify_test(): vm.start() vm.wait_for_login().close() - if expected_dest_state == "running": - virsh.destroy(vm_name, uri=dest_uri) - vm_name = params.get("migrate_main_vm") test_case = params.get("test_case", "") migrate_again = "yes" == params.get("migrate_again", "no") diff --git a/provider/migration/migration_base.py b/provider/migration/migration_base.py index b88762f2437..5efe665e464 100644 --- a/provider/migration/migration_base.py +++ b/provider/migration/migration_base.py @@ -453,23 +453,23 @@ def set_bandwidth(params): virsh.migrate_getspeed(vm_name, debug=True) -def check_vm_status_during_mig(params): +def check_vm_status_during_mig(vm_name, dest_state=None, src_state=None, dest_uri=None, src_reason=None): """ Check vm status during migration - :param params: dict, get expected status of vm, vm name, destination uri, source uri and timeout value + :param vm_name: vm name + :param dest_state: expected status of vm on target host + :param src_state: expected status of vm on source host + :param dest_uri: destination uri + :param src_reason: expected reason of vm state on source host :raise: test fail when check vm status failed """ - vm_status_during_mig = params.get("vm_status_during_mig") - vm_name = params.get("migrate_main_vm") - dest_uri = params.get("virsh_migrate_desturi") - src_uri = params.get("virsh_migrate_connect_uri") - timeout_value = params.get("timeout_value") - if timeout_value: - time.sleep(int(timeout_value)) - for uri in [dest_uri, src_uri]: - if not libvirt.check_vm_state(vm_name, vm_status_during_mig, uri=uri): - raise exceptions.TestFail("VM status is not '%s' during migration on %s." % (vm_status_during_mig, uri)) + if dest_state: + if not libvirt.check_vm_state(vm_name, dest_state, uri=dest_uri): + raise exceptions.TestFail("VM status is not '%s' during migration on target." % dest_state) + if src_state: + if not libvirt.check_vm_state(vm_name, src_state, src_reason): + raise exceptions.TestFail("VM status is not '%s' during migration on source." % src_state) def check_vm_state(params): From b952328f486209455942f7b97f3b296265422c23 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 11 Nov 2024 03:05:19 -0500 Subject: [PATCH 0677/1055] Fix test log related irregular usage Signed-off-by: liang-cong-red-hat --- libvirt/tests/src/numa/numa_memAccess.py | 2 +- .../auto_mem_placement_with_incompatible_host_nodeset.py | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/src/numa/numa_memAccess.py b/libvirt/tests/src/numa/numa_memAccess.py index a046e7e8bee..47e434dbe3c 100644 --- a/libvirt/tests/src/numa/numa_memAccess.py +++ b/libvirt/tests/src/numa/numa_memAccess.py @@ -26,7 +26,7 @@ def define_and_check_xml(vmxml, params): if "cell_id" in key: numa_cells.append(eval(params[key])) pages = [eval(params["page_id_0"])] - logging.debug(numa_cells, pages) + logging.debug("numa cell is: %s, pages are: %s", numa_cells, pages) del vmxml.numa_memory vmcpuxml = libvirt_xml.vm_xml.VMCPUXML() diff --git a/libvirt/tests/src/numa/numa_node_tuning/auto_mem_placement_with_incompatible_host_nodeset.py b/libvirt/tests/src/numa/numa_node_tuning/auto_mem_placement_with_incompatible_host_nodeset.py index ac899195c61..10e7b899f8d 100644 --- a/libvirt/tests/src/numa/numa_node_tuning/auto_mem_placement_with_incompatible_host_nodeset.py +++ b/libvirt/tests/src/numa/numa_node_tuning/auto_mem_placement_with_incompatible_host_nodeset.py @@ -52,7 +52,7 @@ def run_test(): session.send('ZZ') _, text = session.read_until_any_line_matches( [r"%s" % error_msg], timeout=10, internal_timeout=1) - test.log.debug("Checked '%s' exists in '%s'", (error_msg, text)) + test.log.debug("Checked '%s' exists in '%s'", error_msg, text) test.log.debug("Input 'i' to turn off validation") session.sendline('i') @@ -60,8 +60,7 @@ def run_test(): _, text = session.read_until_any_line_matches( [r"%s" % (success_msg % vm_name)], timeout=10, internal_timeout=1) session.close() - test.log.debug("Checked '%s' exists in '%s'", (success_msg % vm_name, - text)) + test.log.debug("Checked '%s' exists in '%s'", success_msg % vm_name, text) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) libvirt_vmxml.check_guest_xml_by_xpaths( From 91846f3431d497c7883a4142cd8000ba4e7e3394 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Mon, 11 Nov 2024 21:51:19 -0500 Subject: [PATCH 0678/1055] Update case of rejecting big inbound average values - VIRT-294768 - update-device qos Live update the QoS setting by update-device with invalid values Signed-off-by: Haijiao Zhao --- .../update_device/update_iface_qos_invalid.cfg | 9 +++++++-- .../update_device/update_iface_qos_invalid.py | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_iface_qos_invalid.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_iface_qos_invalid.cfg index 323a872fbb4..4890a3608b4 100644 --- a/libvirt/tests/cfg/virtual_network/update_device/update_iface_qos_invalid.cfg +++ b/libvirt/tests/cfg/virtual_network/update_device/update_iface_qos_invalid.cfg @@ -9,8 +9,13 @@ update_attrs = {'bandwidth': {'inbound': {'average': '-1', 'peak': '5000', 'burst': '1024'}}} err_msg = could not convert bandwidth average value|Expected non-negative integer value - big_value: - update_attrs = {'bandwidth': {'inbound': {'average': '10000000000000000', 'peak': '5000', 'burst': '1024'}}} - err_msg = could not convert bandwidth average value|Expected non-negative integer value + func_supported_since_libvirt_ver = (10,8,0) + update_attrs = {'bandwidth': {'inbound': {'average': '100000000000000000', 'peak': '5000', 'burst': '1024'}}} + err_msg = numerical overflow: value .* is too big for 'average' parameter, maximum is + - max_value: + func_supported_since_libvirt_ver = (10,8,0) + update_attrs = {'bandwidth': {'inbound': {'average': '18014398509481984', 'peak': '5000', 'burst': '1024'}}} + status_error = no - no_mandatory_average: update_attrs = {'bandwidth': {'outbound': {'peak': '5000', 'burst': '1024'}}} err_msg = Missing mandatory average or floor attributes diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_qos_invalid.py b/libvirt/tests/src/virtual_network/update_device/update_iface_qos_invalid.py index d13ef8eb2be..6ef2be49db7 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_qos_invalid.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_qos_invalid.py @@ -1,5 +1,6 @@ import logging +from virttest import libvirt_version from virttest import virsh from virttest.libvirt_xml import vm_xml from virttest.utils_libvirt import libvirt_vmxml @@ -16,6 +17,7 @@ def run(test, params, env): """ Test live update interface bandwidth setting by update-device or domiftune """ + libvirt_version.is_libvirt_feature_supported(params) vm_name = params.get('main_vm') vm = env.get_vm(vm_name) status_error = 'yes' == params.get('status_error', 'no') From 6b18a9252b6bed3ab91d37b29bea32f286764de2 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Thu, 14 Nov 2024 01:20:49 -0500 Subject: [PATCH 0679/1055] virtio_attributes: fix an argument failure for virtio_page_per_vq Fix the failure of "argument must be an int, or have a fileno() method" occasionally because the script didn't use an open session in utils_net function(). Signed-off-by: Meina Li --- libvirt/tests/src/virtio/virtio_page_per_vq.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/virtio/virtio_page_per_vq.py b/libvirt/tests/src/virtio/virtio_page_per_vq.py index f05ec43d731..c3b8855ffcd 100644 --- a/libvirt/tests/src/virtio/virtio_page_per_vq.py +++ b/libvirt/tests/src/virtio/virtio_page_per_vq.py @@ -79,14 +79,15 @@ def run_test(device_xml, vmxml): virsh.attach_device(vm_name, device_xml.xml, ignore_status=False, debug=True) vm.cleanup_serial_console() vm.create_serial_console() - vm.wait_for_serial_login().close() + vm_session = vm.wait_for_serial_login() test.log.info("TEST_STEP2: check the attribute in %s xml", device_type) check_attribute() if hotplug: virsh.detach_device(vm_name, device_xml.xml, ignore_status=False, debug=True) test.log.info("TEST_STEP3: check the network by ping") - utils_net.ping(dest=ping_outside, count='3', timeout=10, session=vm.session, force_ipv4=True) + utils_net.ping(dest=ping_outside, count='3', timeout=10, session=vm_session, force_ipv4=True) + vm_session.close() def teardown_test(disk_image_path): """ From 4b52c3a5c015fce528bd5327c0410a4996cfefb6 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Wed, 13 Nov 2024 22:56:33 -0500 Subject: [PATCH 0680/1055] Prepare certain state before managedsave For the case "managedsave.status_error_no.name_option.paused_status" we need to prepare the VM to be in paused state before managedsave. Signed-off-by: Yalan Zhang --- libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py index f0d5ad95d8b..3ae522e1b69 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py @@ -427,6 +427,9 @@ def build_vm_xml(vm_name, **dargs): vm_ref = params.get(vm_ref) elif vm_ref == "name": vm_ref = vm_name + # Prepare the certain state before managedsave + if params.get('paused_after_start_vm'): + virsh.suspend(vm_ref) # Ignore exception with "ignore_status=True" if progress: From 0a3a4e47bdc7224d078c9156560855b706b869f5 Mon Sep 17 00:00:00 2001 From: nanli Date: Wed, 21 Aug 2024 21:32:06 +0800 Subject: [PATCH 0681/1055] add case for suspend or shutdown vm via libvirt-guest service xxxx-300726:suspend or shutdown VM with PERSISTENT_ONLY - via restarting libvirt-guests.service Signed-off-by: nanli --- .../libvirt_guests.cfg | 32 +++++++ .../libvirt_guests.py | 84 ++++++++++++++----- 2 files changed, 95 insertions(+), 21 deletions(-) diff --git a/libvirt/tests/cfg/daemon/conf_file/sysconfig_libvirt_guests/libvirt_guests.cfg b/libvirt/tests/cfg/daemon/conf_file/sysconfig_libvirt_guests/libvirt_guests.cfg index f4fd29e6b4e..376c61326bd 100644 --- a/libvirt/tests/cfg/daemon/conf_file/sysconfig_libvirt_guests/libvirt_guests.cfg +++ b/libvirt/tests/cfg/daemon/conf_file/sysconfig_libvirt_guests/libvirt_guests.cfg @@ -5,11 +5,43 @@ - positive_test: status_error = "no" shutdown_timeout = 300 + variants: + - without_transient_vm: + - with_transient_vm: + only no_parallel_shutdown.suspend_on_shutdown.default_vol.none_on_boot, no_parallel_shutdown.shutdown_on_shutdown.none_on_boot + func_supported_since_libvirt_ver = (10, 3, 0) + start_vm = "no" + transient_vm = "yes" + additional_vms = 1 + on_boot = "" + shutdown_timeout = "" + parallel_shutdown = "" + variants: + - persistent_only_none: + persistent_only = "" + shutdown_on_shutdown: + transient_vm_operation = "shutdown" + suspend_on_shutdown: + transient_vm_operation = "nothing" + - persistent_only_true: + persistent_only = "true" + transient_vm_operation = "nothing" + - persistent_only_false: + persistent_only = "false" + transient_vm_operation = ${on_shutdown} + - persistent_only_default: + persistent_only = "default" + shutdown_on_shutdown: + transient_vm_operation = "shutdown" + suspend_on_shutdown: + transient_vm_operation = "nothing" variants: - start_on_boot: on_boot = "start" - ignore_on_boot: on_boot = "ignore" + - none_on_boot: + on_boot = "" variants: - suspend_on_shutdown: on_shutdown = "suspend" diff --git a/libvirt/tests/src/daemon/conf_file/sysconfig_libvirt_guests/libvirt_guests.py b/libvirt/tests/src/daemon/conf_file/sysconfig_libvirt_guests/libvirt_guests.py index 6d87b7985c5..995f592aa10 100644 --- a/libvirt/tests/src/daemon/conf_file/sysconfig_libvirt_guests/libvirt_guests.py +++ b/libvirt/tests/src/daemon/conf_file/sysconfig_libvirt_guests/libvirt_guests.py @@ -8,12 +8,14 @@ from avocado.utils import path as utils_path from avocado.utils import process +from virttest import libvirt_version from virttest import utils_libguestfs from virttest import utils_misc from virttest import virsh from virttest import utils_config from virttest.libvirt_xml import vm_xml from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_disk from virttest.staging import service @@ -65,13 +67,22 @@ def chk_on_shutdown(status_error, on_shutdown, parallel_shutdown, output): expect_msg = expect_shutdown_msg(status_error, on_shutdown) logging.debug("The expected messages when host shutdown is: %s ", expect_msg) for dom in vms: - if not re.search(expect_msg[dom.name], output): - logging.debug("expect_mesg is: %s", expect_msg[dom.name]) - if status_error == "no": - test.fail("guest should be %s on shutdown" % on_shutdown) - else: - test.fail("Shutdown of guest should be failed to " - "complete in time") + check_res = re.search(expect_msg[dom.name], output) + no_operation = (transient_vm_operation == "nothing" and not dom.is_persistent()) + if no_operation: + if check_res: + test.fail("Expect msg '%s' does not exist." % expect_msg) + test.log.debug("Check transient guest:%s did nothing successfully", dom.name) + else: + if not check_res: + logging.debug("expect_mesg is: %s", expect_msg[dom.name]) + if status_error == "no": + test.fail("guest:%s should be %s on shutdown" % (dom.name, on_shutdown)) + else: + test.fail("Shutdown of guest should be failed to " + "complete in time") + test.log.debug("Check guest:%s did '%s' successfully", + dom.name, expect_msg[dom.name]) if (on_shutdown == "shutdown") and int(parallel_shutdown) > 0: chk_parallel_shutdown(output, parallel_shutdown) @@ -85,12 +96,11 @@ def chk_on_boot(status_error, on_boot): :param on_boot: action taking on host booting """ if status_error == "no": - if on_boot == "start": + if on_boot == "start" or transient_vm: for dom in vms: if not dom.is_alive(): - test.fail("Since on_boot is setting to 'start', " - "guest should be running after " - "restarting libvirt-guests.") + test.fail("guest:%s should be running after " + "restarting libvirt-guests." % dom.name) else: for dom in vms: if dom.is_alive(): @@ -98,6 +108,7 @@ def chk_on_boot(status_error, on_boot): "unless guests are autostart, " "guest should be shut off after " "restarting libvirt-guests, ") + test.log.debug("Check all guests state successfully") def check_on_shutdown_vm_status(): for dom in vms: @@ -190,12 +201,13 @@ def chk_save_files(status_error, on_shutdown, on_boot): if os.path.exists(save_files[dom]): test.fail("There should be no save files since " "guests are restored on host shutdown.") - else: + elif on_boot == "ignore": for dom in vms: if not os.path.exists(save_files[dom]): test.fail("Guests are suspended on host shutdown, " "and been ignored on host boot, there " "should be save files for the guests.") + test.log.debug("Check all guests file successfully") def boot_time(): booting_time = [] @@ -242,11 +254,28 @@ def cleanup_nfs_backend_guest(vmxml_backup): nfs_server = libvirt.setup_or_cleanup_nfs(False) + def transfer_to_transient(per_guest_name): + """ + Transfer one persistent vm to transient guest. + + :param per_guest_name: persistent guest name. + """ + virsh.start(per_guest_name, ignore_status=False) + vmxml = vm_xml.VMXML.new_from_dumpxml(per_guest_name) + virsh.undefine(per_guest_name, options='--nvram', debug=True, ignore_status=False) + virsh.create(vmxml.xml, debug=True) + test.log.debug("Transfer guest %s to be transient type", per_guest_name) + main_vm_name = params.get("main_vm") main_vm = env.get_vm(main_vm_name) on_boot = params.get("on_boot") on_shutdown = params.get("on_shutdown") + persistent_only = params.get("persistent_only", "") + transient_vm = "yes" == params.get("transient_vm", "no") + if transient_vm: + libvirt_version.is_libvirt_feature_supported(params) + transient_vm_operation = params.get("transient_vm_operation") nfs_vol = params.get("nfs_vol") == "yes" virt_use_nfs = params.get("virt_use_nfs") == "on" parallel_shutdown = params.get("parallel_shutdown") @@ -287,9 +316,10 @@ def cleanup_nfs_backend_guest(vmxml_backup): utils_libguestfs.virt_clone_cmd(main_vm_name, guest_name, True, timeout=360, ignore_status=False) + if transient_vm: + transfer_to_transient(guest_name) vms.append(main_vm.clone(guest_name)) logging.debug("Now the vms is: %s", [dom.name for dom in vms]) - if nfs_vol: # info collected for clear env finally vmxml_backup = [] @@ -299,7 +329,7 @@ def cleanup_nfs_backend_guest(vmxml_backup): if not dom.is_alive(): dom.start() for dom in vms: - dom.wait_for_login() + dom.wait_for_login().close() first_boot_time = [] if on_shutdown == "shutdown" and on_boot == "start": first_boot_time = boot_time() @@ -307,13 +337,20 @@ def cleanup_nfs_backend_guest(vmxml_backup): try: # Config the libvirt-guests file - config.ON_BOOT = on_boot - config.ON_SHUTDOWN = on_shutdown - config.PARALLEL_SHUTDOWN = parallel_shutdown - config.SHUTDOWN_TIMEOUT = shutdown_timeout + if on_boot: + config.ON_BOOT = on_boot + if on_shutdown: + config.ON_SHUTDOWN = on_shutdown + if persistent_only: + config.PERSISTENT_ONLY = persistent_only + if parallel_shutdown: + config.PARALLEL_SHUTDOWN = parallel_shutdown + if shutdown_timeout: + config.SHUTDOWN_TIMEOUT = shutdown_timeout process.run("sed -i -e 's/ = /=/g' " "/etc/sysconfig/libvirt-guests", shell=True) + process.run("cat /etc/sysconfig/libvirt-guests", shell=True) tail_messages = get_log() # Even though libvirt-guests was designed to operate guests when @@ -325,11 +362,13 @@ def cleanup_nfs_backend_guest(vmxml_backup): time.sleep(30) output = tail_messages.get_output() logging.debug("Get messages in /var/log/messages: %s" % output) - + virsh.dom_list("--all", debug=True) # check the guests state when host shutdown chk_on_shutdown(status_error, on_shutdown, parallel_shutdown, output) - # check the guests state when host rebooted - chk_on_boot(status_error, on_boot) + virsh.dom_list("--all", debug=True) + if not (transient_vm and on_shutdown == "shutdown"): + # check the guests state when host rebooted + chk_on_boot(status_error, on_boot) # check the guests save files chk_save_files(status_error, on_shutdown, on_boot) @@ -353,3 +392,6 @@ def cleanup_nfs_backend_guest(vmxml_backup): if libvirt_guests_service.status(): libvirt_guests_service.stop() + + source_path = os.path.dirname(libvirt_disk.get_first_disk_source(vms[0])) + process.run("cd %s; rm -rf *-clone*" % source_path, shell=True) From 041df6b9ecaa6105e98fc3e85a60ffb1ebad8f1c Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Mon, 18 Nov 2024 09:30:43 +0800 Subject: [PATCH 0682/1055] v2v: adjust guest matrix for rhel9.6/10.0 Signed-off-by: vwu-vera --- v2v/tests/cfg/convert_vm_to_libvirt.cfg | 16 ++++++++-------- v2v/tests/cfg/convert_vm_to_ovirt.cfg | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/v2v/tests/cfg/convert_vm_to_libvirt.cfg b/v2v/tests/cfg/convert_vm_to_libvirt.cfg index 33d760e165c..640c527c768 100644 --- a/v2v/tests/cfg/convert_vm_to_libvirt.cfg +++ b/v2v/tests/cfg/convert_vm_to_libvirt.cfg @@ -38,7 +38,7 @@ - boot_uefi: vm_boot = "-efi" boottype = 3 - only 8_0.linux.latest10_dev, 8_0.linux.latest9_dev, 8_0.linux.latest9, 8_0.linux.latest8, 8_0.linux.8_8, 8_0.linux.8_6, 8_0.linux.ubuntu22_04, 8_0.linux.ubuntu_lts, 8_0.linux.sles15sp4, 8_0.linux.sles_lts, 8_0.linux.opensuse15_5, 8_0.windows.win2022, 8_0.windows.win11, 8_0.windows.win2016, 8_0.windows.win2025 + only 8_0.linux.latest10_dev, 8_0.linux.latest9_dev, 8_0.linux.latest9, 8_0.linux.latest8, 8_0.linux.8_8, 8_0.linux.8_6, 8_0.linux.ubuntu22_04, 8_0.linux.ubuntu_lts, 8_0.linux.sles15sp5, 8_0.linux.sles_lts, 8_0.linux.opensuse15_5, 8_0.linux.opensuse_latest, 8_0.windows.win2022, 8_0.windows.win11, 8_0.windows.win2016, 8_0.windows.win2025 variants: - linux: os_type = "linux" @@ -90,20 +90,20 @@ only source_esx.esx_80 os_short_id = "sles12sp5" os_version = "sles12sp5" - - sles15sp4: + - sles15sp5: only source_esx.esx_80 - os_short_id = "sles15sp4" - os_version = "sles15sp4" + os_short_id = "sles15sp5" + os_version = "sles15sp5" - sles_lts: only source_esx.esx_80 os_version = "SLES_LATEST_VERSION" - opensuse_latest: - only source_esx.esx_70, source_esx.esx_80 + only source_esx.esx_80 os_short_id = "OPENSUSE_LATEST_SHORT_ID" os_version = "OPENSUSE_LATEST_VERSION" - - opensuse15_4: - only source_esx.esx_70 - os_version = "opensuse15.4" + - opensuse42_3: + only source_esx.esx_70,source_esx.esx_80 + os_version = "opensuse42.3" - opensuse15_5: only source_esx.esx_80 os_version = "opensuse15.5" diff --git a/v2v/tests/cfg/convert_vm_to_ovirt.cfg b/v2v/tests/cfg/convert_vm_to_ovirt.cfg index 47e62a75f04..b97ff3d86a1 100644 --- a/v2v/tests/cfg/convert_vm_to_ovirt.cfg +++ b/v2v/tests/cfg/convert_vm_to_ovirt.cfg @@ -81,7 +81,7 @@ - boot_uefi: vm_boot = "-efi" boottype = 3 - only 8_0.linux.latest10_dev, 8_0.linux.latest9_dev, 8_0.linux.latest9, 8_0.linux.latest8, 8_0.linux.8_8, 8_0.linux.8_6, 8_0.linux.ubuntu22_04, 8_0.linux.ubuntu_lts, 8_0.linux.sles15sp4, 8_0.linux.sles_lts, 8_0.linux.opensuse15_5, 8_0.windows.win2022, 8_0.windows.win11, 8_0.windows.win2016, 8_0.windows.win2025 + only 8_0.linux.latest10_dev, 8_0.linux.latest9_dev, 8_0.linux.latest9, 8_0.linux.latest8, 8_0.linux.8_8, 8_0.linux.8_6, 8_0.linux.ubuntu22_04, 8_0.linux.ubuntu_lts, 8_0.linux.sles15sp5, 8_0.linux.sles_lts, 8_0.linux.opensuse15_5, 8_0.linux.opensuse_latest, 8_0.windows.win2022, 8_0.windows.win11, 8_0.windows.win2016, 8_0.windows.win2025 variants: - linux: os_type = "linux" @@ -125,19 +125,19 @@ - sles12sp5: only source_esx.esx_80 os_version = "sles12sp5" - - sles15sp4: + - sles15sp5: only source_esx.esx_80 - os_short_id = "sles15sp4" - os_version = "sles15sp4" + os_short_id = "sles15sp5" + os_version = "sles15sp5" - sles_lts: only source_esx.esx_80 os_version = "SLES_LATEST_VERSION" - opensuse_latest: - only source_esx.esx_70, source_esx.esx_80 + only source_esx.esx_80 os_version = "OPENSUSE_LATEST_VERSION" - - opensuse15_4: - only source_esx.esx_70 - os_version = "opensuse15.4" + - opensuse42_3: + only source_esx.esx_70, source_esx.esx_80 + os_version = "opensuse42.3" - opensuse15_5: only source_esx.esx_80 os_version = "opensuse15.5" From 7942c15ce3902f9b2905d3ce354a2f1a1abca4c3 Mon Sep 17 00:00:00 2001 From: Yanqiu Zhang Date: Thu, 14 Nov 2024 08:05:45 -0500 Subject: [PATCH 0683/1055] tpm_device: add swtpm debug logging test Add two classical values '5','20' test, and a negative '-1' test. Swtpm/libtpms debugging is very much non-stable/non-contract thing according to developer, our QE can first check sth different from non-setting, not sure the obvious difference between each level. Signed-off-by: Yanqiu Zhang --- .../tests/cfg/virtual_device/tpm_device.cfg | 14 +++++++++++ .../tests/src/virtual_device/tpm_device.py | 24 ++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_device/tpm_device.cfg b/libvirt/tests/cfg/virtual_device/tpm_device.cfg index d77fc9692ce..45b618567c7 100644 --- a/libvirt/tests/cfg/virtual_device/tpm_device.cfg +++ b/libvirt/tests/cfg/virtual_device/tpm_device.cfg @@ -39,6 +39,15 @@ - version_default: only plain backend_version = 'none' + - debug: + func_supported_since_libvirt_ver = (10, 6, 0) + only encrypted + only pcrbank_default + variants: + - lvl_5: + backend_debug = '5' + - lvl_20: + backend_debug = '20' - persistent_state: persistent_state = 'yes' func_supported_since_libvirt_ver = (7, 0, 0) @@ -209,6 +218,11 @@ - version_textdefault: backend_version = 'default' xml_errmsg = "Invalid value for attribute 'version' in element 'backend': 'default'" + - invalid_debug: + func_supported_since_libvirt_ver = (10, 6, 0) + backend_debug = '-1' + backend_version = '2.0' + xml_errmsg = "Invalid.*'debug' in element 'backend'.*Expected non-negative integer value" - encrypt_secret: backend_version = '2.0' variants: diff --git a/libvirt/tests/src/virtual_device/tpm_device.py b/libvirt/tests/src/virtual_device/tpm_device.py index 24b5a4f40f1..687d795bdd9 100644 --- a/libvirt/tests/src/virtual_device/tpm_device.py +++ b/libvirt/tests/src/virtual_device/tpm_device.py @@ -15,7 +15,6 @@ from virttest import utils_misc from virttest import utils_libguestfs from virttest import utils_libvirtd -from virttest import libvirt_version from virttest.libvirt_xml.devices.tpm import Tpm from virttest.libvirt_xml.vm_xml import VMXML @@ -54,6 +53,7 @@ def run(test, params, env): tpm_model = params.get("tpm_model") backend_type = params.get("backend_type") backend_version = params.get("backend_version") + backend_debug = params.get("backend_debug") device_path = params.get("device_path") tpm_num = int(params.get("tpm_num", 1)) # After first start of vm with vtpm, do operations, check it still works @@ -284,6 +284,8 @@ def check_dumpxml(vm_name): if backend_version: check_ver = backend_version if backend_version not in ["none", "default"] else '2.0' xpaths.append({'element_attrs': [".//backend[@version='%s']" % check_ver]}) + if backend_debug: + xpaths.append({'element_attrs': [".//backend[@debug='%s']" % backend_debug]}) if active_pcr_banks and not remove_pcrbank: check_active_pcr_banks(xml_after_adding_device) if backend_type == "passthrough": @@ -398,6 +400,8 @@ def check_swtpm(domid, domuuid, vm_name): pattern_list.remove("--log") if prepare_secret: pattern_list.extend(["--key", "--migration-key"]) + if backend_debug: + pattern_list.extend(["level=%s" % backend_debug]) for pattern in pattern_list: if not re.search(pattern, cmdline): test.fail("Can not find the %s for tpm device " @@ -749,6 +753,20 @@ def check_swtpmpidfile(vm_name, test_stage): if swtpm_pidfile and libvirt_version.version_compare(8, 7, 0): test.error('swtpm.pid still exists after %s: %s' % (test_stage, swtpm_pidfile)) + def test_swtpm_logging(): + """ + test logging level for swtpm when backend_debug is set + """ + log_pattern_list = ["SWTPM_IO_Read", "SWTPM_IO_Write"] + swtpm_log = "/var/log/swtpm/libvirt/qemu/" + vm.name + "-swtpm.log" + with open(swtpm_log) as f: + lines = "".join(f.readlines()) + for log_pattern in log_pattern_list: + if re.search(log_pattern, lines): + logging.info("Finding msg<%s> in swtpm log", log_pattern) + else: + test.fail("Can not find msg:<%s> in swtpm log" % log_pattern) + try: tpm_real_v = None sec_uuids = [] @@ -776,6 +794,8 @@ def check_swtpmpidfile(vm_name, test_stage): if backend_type == "emulator": if backend_version != 'none': backend.backend_version = backend_version + if backend_debug: + backend.backend_debug = backend_debug if persistent_state: backend.persistent_state = "yes" if prepare_secret: @@ -972,6 +992,8 @@ def check_swtpmpidfile(vm_name, test_stage): else: test_guest_tpm(expect_version, session, expect_fail) session.close() + if backend_debug: + test_swtpm_logging() if multi_vms: reuse_by_vm2(tpm_dev) if backend_type != "passthrough": From b1e88733f6c9deff68106df78917ef25c0e8ba49 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Mon, 18 Nov 2024 09:24:40 +0800 Subject: [PATCH 0684/1055] vIOMMU: Update to wait events after disk is attached Update to check the events to make sure the disk is attached correctly. Signed-off-by: Yingshun Cui --- .../tests/src/sriov/vIOMMU/hotplug_device_with_iommu_enabled.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/sriov/vIOMMU/hotplug_device_with_iommu_enabled.py b/libvirt/tests/src/sriov/vIOMMU/hotplug_device_with_iommu_enabled.py index 5e4b493cce4..73491fbe171 100644 --- a/libvirt/tests/src/sriov/vIOMMU/hotplug_device_with_iommu_enabled.py +++ b/libvirt/tests/src/sriov/vIOMMU/hotplug_device_with_iommu_enabled.py @@ -74,7 +74,7 @@ def detach_dev(device_type, dev_iommu_info, vm_session): libvirt_disk.create_disk("file", new_disk_path, disk_size, disk_format="qcow2") disk_dict.update({'source': {'attrs': {'file': new_disk_path}}}) disk_obj = libvirt_vmxml.create_vm_device_by_type('disk', disk_dict) - virsh.attach_device(vm.name, disk_obj.xml, debug=True, ignore_status=False) + virsh.attach_device(vm.name, disk_obj.xml, debug=True, ignore_status=False, wait_for_event=True) if need_sriov: test_obj.params["iface_dict"] = str(sroiv_test_obj.parse_iface_dict()) From b9de13d4cce073b19cf3159b74be5e8e6b00d01d Mon Sep 17 00:00:00 2001 From: nanli Date: Sat, 16 Nov 2024 08:11:00 +0800 Subject: [PATCH 0685/1055] case update: virsh domstats with vcpu.x.wait_sum is not 0 xxxx-21749:domstats - get statistics about one or multiple or all domains Signed-off-by: nanli --- .../src/virsh_cmd/monitor/virsh_domstats.py | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/monitor/virsh_domstats.py b/libvirt/tests/src/virsh_cmd/monitor/virsh_domstats.py index ca6ded49bf5..c5f0780c94a 100644 --- a/libvirt/tests/src/virsh_cmd/monitor/virsh_domstats.py +++ b/libvirt/tests/src/virsh_cmd/monitor/virsh_domstats.py @@ -6,6 +6,7 @@ from multiprocessing.pool import ThreadPool +from virttest import utils_disk from virttest import virsh from virttest.utils_test import libvirt from virttest.libvirt_xml import vm_xml @@ -86,7 +87,7 @@ def prepare_vm_state(vm, vm_state): logging.error("Unknown state for this test") -def check_output(output, vm, vm_state, options): +def check_output(output, vm, vm_state, options, params): """ Check virsh domstats output according to vm state and command options; For now, we only check given state domain can be find by list option. @@ -95,6 +96,7 @@ def check_output(output, vm, vm_state, options): :param vm: Libvirt VM instance :param vm_state: Domain state :param options: Virsh command options + :param params: Dictionary with the test parameters """ check_pass = [] list_option = "" @@ -105,6 +107,7 @@ def check_output(output, vm, vm_state, options): block_option_pass = False cpu_option = "" cpu_option_pass = False + vcpu_wait_sum_pass = False balloon_option = "" balloon_option_pass = False nowait_option = "" @@ -188,6 +191,12 @@ def check_output(output, vm, vm_state, options): if 'vcpu' in output: cpu_option_pass = True check_pass.append(cpu_option_pass) + if params.get("vcpu_wait_sum"): + wait_sum = re.findall(r"vcpu.\d+.wait=(\d+)", output) + for sum in wait_sum: + if sum != "0": + vcpu_wait_sum_pass = True + check_pass.append(vcpu_wait_sum_pass) if balloon_option == '--balloon': if 'balloon' in output: balloon_option_pass = True @@ -295,6 +304,8 @@ def run(test, params, env): iothread_add_ids = eval(params.get("iothread_add_ids", '[]')) iothread_del_ids = eval(params.get("iothread_del_ids", '[]')) status_error = (params.get("status_error", "no") == "yes") + params.update( + {"vcpu_wait_sum": vm_state == "running" and domstats_option == "--vcpu"}) if "--nowait" in domstats_option and not libvirt_version.version_compare(4, 5, 0): test.cancel("--nowait option is supported until libvirt 4.5.0 version...") @@ -328,6 +339,11 @@ def run(test, params, env): test.cancel("No 'panic' device in the guest, maybe " "your libvirt version doesn't support it.") prepare_vm_state(vm, vm_state) + if params.get("vcpu_wait_sum"): + session = vm.wait_for_login() + utils_disk.dd_data_to_vm_disk(session, "/tmp/file1") + session.close() + if enforce_command: domstats_option += " --enforce" if raw_print: @@ -355,8 +371,9 @@ def run(test, params, env): test.fail("Run failed with right command") else: for vm in vms: - if not check_output(output, vm, vm_state, domstats_option): - test.fail("Check command output failed") + if not check_output(output, vm, vm_state, domstats_option, params): + test.fail("Check command output failed " + "due to %s option" % domstats_option) if "--iothread" in domstats_option: test_iothread(vm_list, iothread_add_ids, iothread_del_ids, output, test) From 6c1fd9bbd5b9d2c1ab912da2976baa837cd3766d Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 19 Nov 2024 11:58:31 -0500 Subject: [PATCH 0686/1055] virtual_network: fix test cases on s390x test environment On s390x, only per-device is supported. Disable test expecting conflict with //os/boot Signed-off-by: Sebastian Mitterle --- .../attach_detach_device/attach_iface_with_boot_order.cfg | 1 + libvirt/tests/cfg/virtual_network/iface_attach_detach.cfg | 1 + libvirt/tests/cfg/virtual_network/iface_update.cfg | 1 + 3 files changed, 3 insertions(+) diff --git a/libvirt/tests/cfg/virtual_network/attach_detach_device/attach_iface_with_boot_order.cfg b/libvirt/tests/cfg/virtual_network/attach_detach_device/attach_iface_with_boot_order.cfg index 7b4be22f57e..1b59a6ca9b9 100644 --- a/libvirt/tests/cfg/virtual_network/attach_detach_device/attach_iface_with_boot_order.cfg +++ b/libvirt/tests/cfg/virtual_network/attach_detach_device/attach_iface_with_boot_order.cfg @@ -5,6 +5,7 @@ status_error = yes variants scenario: - vm_with_os_boot: + no s390-virtio os_attrs = {'boots': ['hd']} boot_order = 2 err_msg = per-device boot elements cannot be used together with os/boot elements diff --git a/libvirt/tests/cfg/virtual_network/iface_attach_detach.cfg b/libvirt/tests/cfg/virtual_network/iface_attach_detach.cfg index 77f1bab5001..54d16028bdc 100644 --- a/libvirt/tests/cfg/virtual_network/iface_attach_detach.cfg +++ b/libvirt/tests/cfg/virtual_network/iface_attach_detach.cfg @@ -12,6 +12,7 @@ virsh_options = ' --config' variants scenario: - with_os_boot: + no s390-virtio error_msg = 'per-device boot elements cannot be used together with os/boot elements' - with_boot_disk: error_msg = 'boot order 1 is already used by another device' diff --git a/libvirt/tests/cfg/virtual_network/iface_update.cfg b/libvirt/tests/cfg/virtual_network/iface_update.cfg index cc06f08bdc0..c6d38c46249 100644 --- a/libvirt/tests/cfg/virtual_network/iface_update.cfg +++ b/libvirt/tests/cfg/virtual_network/iface_update.cfg @@ -200,6 +200,7 @@ - update_boot_order: variants: - with_os_boot: + no s390-virtio new_iface_boot = '1' expect_err_msg = 'per-device boot elements cannot be used together with os/boot elements' - boot_order_occupied: From 090aef43121f75c31218bc189f89c34d78798690 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Wed, 20 Nov 2024 01:12:04 -0500 Subject: [PATCH 0687/1055] Auto three v2v cases about virsh dump bugs Signed-off-by: Ming Xie --- v2v/tests/cfg/function_test_esx.cfg | 5 ++--- v2v/tests/cfg/specific_kvm.cfg | 13 +++++++++++++ v2v/tests/src/function_test_esx.py | 2 -- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 852e479022d..684ae508213 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -407,11 +407,10 @@ main_vm = VM_NAME_DEVICE_PASSTHRU_V2V_EXAMPLE - empty_cdrom: only esx_80 - main_vm = VM_NAME_EMPTY_CDROM_V2V_EXAMPLE - checkpoint = empty_cdrom boottype = 3 + main_vm = VM_NAME_EMPTY_IDE_SATA_CDROM_V2V_EXAMPLE skip_vm_check = yes - skip_reason = "No vm is created in this case" + skip_reason = 'bug RHEL-38633 is not fixed' - option_root: main_vm = VM_NAME_MULTIPLE_LINUX_V2V_EXAMPLE checkpoint = root diff --git a/v2v/tests/cfg/specific_kvm.cfg b/v2v/tests/cfg/specific_kvm.cfg index 4709d4d5be8..44a1de140b0 100644 --- a/v2v/tests/cfg/specific_kvm.cfg +++ b/v2v/tests/cfg/specific_kvm.cfg @@ -296,6 +296,19 @@ main_vm = 'VM_NAME_80_UBUNTU_PARTIAL_EFI_V2V_EXAMPLE' skip_vm_check = yes skip_reason = "Special configuration. No console available" + - serial_port: + only esx_80 + variants: + - chars_telnet: + boottype = 2 + main_vm = VM_NAME_SERVIAL_PORT_CHARACTERS_TELNET_URL_V2V_EXAMPLE + - empty_info: + boottype = 2 + main_vm = VM_NAME_SERVIAL_PORT_EMPTY_V2V_EXAMPLE + - vmx_char: + only esx_80 + boottype = 2 + main_vm = VM_NAME_VMX_CONTAINS_CHAR_V2V_EXAMPLE variants: - positive_test: status_error = 'no' diff --git a/v2v/tests/src/function_test_esx.py b/v2v/tests/src/function_test_esx.py index 200633592ac..ace087f7eb9 100644 --- a/v2v/tests/src/function_test_esx.py +++ b/v2v/tests/src/function_test_esx.py @@ -949,8 +949,6 @@ def vm_check(status_error): params['msg_content_yes'] += '' + res_cpu_topology.get('sockets') + '%' params['msg_content_yes'] += '' + res_cpu_topology.get('cores') + '%' params['msg_content_yes'] += '' + res_cpu_topology.get('threads') - if 'empty_cdrom' in checkpoint: - v2v_result = raw_dumpxml else: if 'exist_uuid' in checkpoint: auto_clean = False From 4bfe826b4451ff5a7a97ca1b3ab820141b2b13bd Mon Sep 17 00:00:00 2001 From: Tasmiya Nalatwad Date: Mon, 11 Nov 2024 17:45:25 +0530 Subject: [PATCH 0688/1055] Get the proper numa nodes configuration from the system. The Patch fixes almost 67 cases which were failing as Nn numa nodes available in the system. The provided fix check for all the available numa nodes in the system and figures out which numa node has memory an cpus. Even the system is having randome numa nodes configurations the fix works for all the manners and gets the list nodes which has memory and cpus. Signed-off-by: Tasmiya Nalatwad --- libvirt/tests/src/numa/guest_numa.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/libvirt/tests/src/numa/guest_numa.py b/libvirt/tests/src/numa/guest_numa.py index fc591b957d9..e58d4d58cf2 100644 --- a/libvirt/tests/src/numa/guest_numa.py +++ b/libvirt/tests/src/numa/guest_numa.py @@ -62,8 +62,11 @@ def dynamic_node_replacement(params, numa_info, test_obj): key_names = ['memnode_nodeset_', 'page_nodenum_'] for param in params: if 'numa_cells_with_memory_required' in param: - if int(params['numa_cells_with_memory_required']) > len(node_list): - test_obj.cancel("There is no enough NUMA nodes available on this system to perform the test.") + if 'ppc64' in arch: + if not node_list: + test_obj.cancel("No NUMA nodes available on this system to perform the test.") + elif int(params['numa_cells_with_memory_required']) > len(node_list): + test_obj.cancel("There is no enough NUMA nodes available on this system to perform the test.") if 'memory_nodeset' in param: params['memory_nodeset'] = ','.join([str(elem) for elem in node_list]) logging.debug('The parameter "memory_nodeset" from config file is going to be replaced by: {} available ' @@ -112,9 +115,11 @@ def run(test, params, env): ppc_memory_nodeset += str(node_list[int(nodes.split('-')[1])]) else: node_lst = nodes.split(',') - for n in range(len(node_lst) - 1): - ppc_memory_nodeset += str(node_list[int(node_lst[n])]) + ',' - ppc_memory_nodeset += str(node_list[int(node_lst[-1])]) + for n in range(len(node_lst)): + if int(node_lst[n]) in node_list: + ppc_memory_nodeset += str(node_lst[n]) + if n < len(node_lst) - 1: + ppc_memory_nodeset += ',' params['memory_nodeset'] = ppc_memory_nodeset except IndexError: test.cancel("No of numas in config does not match with no of " @@ -125,7 +130,11 @@ def run(test, params, env): for pkey in pkeys: for key in params.keys(): if pkey in key: - params[key] = str(node_list[int(params[key])]) + index = int(params[key]) + if index < len(node_list): + params[key] = str(node_list[index]) + else: + params[key] = str(node_list[-1]) # Modify qemu command line try: if params['qemu_cmdline_mem_backend_1']: From 19a515302daeb5df7ca494279a8bcdf96738916b Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Wed, 20 Nov 2024 04:26:06 -0500 Subject: [PATCH 0689/1055] Update network case of defining net without ip - VIRT-63196 - [virtual network] define a network with forward mode 'open' Signed-off-by: Haijiao Zhao --- libvirt/tests/cfg/virtual_network/iface_network.cfg | 1 + libvirt/tests/src/virtual_network/iface_network.py | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/libvirt/tests/cfg/virtual_network/iface_network.cfg b/libvirt/tests/cfg/virtual_network/iface_network.cfg index 3574082566d..4c338770c9e 100644 --- a/libvirt/tests/cfg/virtual_network/iface_network.cfg +++ b/libvirt/tests/cfg/virtual_network/iface_network.cfg @@ -196,6 +196,7 @@ no_mac = "yes" - negative_without_ip: define_error = "yes" + only_test_define = "yes" no_ip = "yes" - negative_with_dev: define_error = "yes" diff --git a/libvirt/tests/src/virtual_network/iface_network.py b/libvirt/tests/src/virtual_network/iface_network.py index 9f264b962fd..91a745a317e 100644 --- a/libvirt/tests/src/virtual_network/iface_network.py +++ b/libvirt/tests/src/virtual_network/iface_network.py @@ -673,6 +673,7 @@ def dig_test(session): ipt6_rules = [] define_macvtap = "yes" == params.get("define_macvtap", "no") net_dns_forwarders = params.get("net_dns_forwarders", "").split() + only_test_define = "yes" == params.get("only_test_define", "no") # Cancel if not yet supported in libvirt version under test if "floor" in ast.literal_eval(iface_bandwidth_inbound): @@ -795,10 +796,14 @@ def dig_test(session): netxml.sync() except xcepts.LibvirtXMLError as details: logging.info(str(details)) + if only_test_define and libvirt_version.version_compare(10, 8, 0): + define_error = False if define_error: return else: test.fail("Failed to define network") + if only_test_define: + return # Check open mode network xml if "mode" in forward and forward["mode"] == "open": From 14bdd85c75d61ddd3cb770f519dae5a9c3145fc4 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 20 Nov 2024 07:04:25 -0500 Subject: [PATCH 0690/1055] virsh_boot: disable seabios on s390x No SeaBIOS on s390x, disable tests. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/bios/virsh_boot.cfg | 1 + libvirt/tests/cfg/bios/virsh_boot_sysinfo.cfg | 1 + libvirt/tests/cfg/bios/virsh_boot_tseg.cfg | 1 + 3 files changed, 3 insertions(+) diff --git a/libvirt/tests/cfg/bios/virsh_boot.cfg b/libvirt/tests/cfg/bios/virsh_boot.cfg index 03f42982221..3ec1418374f 100644 --- a/libvirt/tests/cfg/bios/virsh_boot.cfg +++ b/libvirt/tests/cfg/bios/virsh_boot.cfg @@ -186,6 +186,7 @@ uefi_target_dev = "sda" check_prompt = ".*has invalid signature" || "'Verification failed: (0x1A) Security Violation'" - by_seabios: + no s390-virtio boot_type = "seabios" loader = "/usr/share/seabios/bios-256k.bin" loader_type = "rom" diff --git a/libvirt/tests/cfg/bios/virsh_boot_sysinfo.cfg b/libvirt/tests/cfg/bios/virsh_boot_sysinfo.cfg index 9429c7d7866..37f819d4b1f 100644 --- a/libvirt/tests/cfg/bios/virsh_boot_sysinfo.cfg +++ b/libvirt/tests/cfg/bios/virsh_boot_sysinfo.cfg @@ -39,6 +39,7 @@ error_msg = "Firmware entry must have either value or 'file' attribute" variants: - by_seabios: + no s390-virtio boot_type = "seabios" - by_ovmf: only q35 diff --git a/libvirt/tests/cfg/bios/virsh_boot_tseg.cfg b/libvirt/tests/cfg/bios/virsh_boot_tseg.cfg index d3497270b8a..7b7ea713439 100644 --- a/libvirt/tests/cfg/bios/virsh_boot_tseg.cfg +++ b/libvirt/tests/cfg/bios/virsh_boot_tseg.cfg @@ -52,4 +52,5 @@ loader = "/usr/share/OVMF/OVMF_CODE.secboot.fd" loader_type = "pflash" - by_seabios: + no s390-virtio boot_type = "seabios" From f10d5e46f95ae7368664904b73c0c1b4fabd2449 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Thu, 21 Nov 2024 02:10:02 -0500 Subject: [PATCH 0691/1055] Snapshot: fix console failure when using the console for the second time Fix "No console available" issues in some snapshot scripts: 1) delete_external_snap_with_references.py: this script starts the guest twice. So I added an if statement to check vm.is_alive in the second time. 2) Another two scripts, to make sure the second console is same and pure. I added vm.cleanup_serial_console and vm.create_serial_console before the second time. Signed-off-by: Meina Li --- .../src/snapshot/delete_external_snap_with_references.py | 5 +++-- libvirt/tests/src/snapshot/revert_disk_external_snap.py | 8 +++++--- .../src/snapshot/revert_snapshot_after_xml_updated.py | 8 +++++--- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/libvirt/tests/src/snapshot/delete_external_snap_with_references.py b/libvirt/tests/src/snapshot/delete_external_snap_with_references.py index 28ab3ce50a5..522ab1c179c 100644 --- a/libvirt/tests/src/snapshot/delete_external_snap_with_references.py +++ b/libvirt/tests/src/snapshot/delete_external_snap_with_references.py @@ -46,8 +46,9 @@ def run_test_del_parent_snap(): Delete the parent snapshot with multiple children. """ test.log.info("TEST_STEP:Delete the parent snapshot with multi-child.") - virsh.start(vm_name) - vm.wait_for_login().close() + if not vm.is_alive(): + virsh.start(vm_name) + vm.wait_for_login().close() del_res = virsh.snapshot_delete(vm.name, snap_names[0], debug=True) libvirt.check_exit_status(del_res, error_msg) diff --git a/libvirt/tests/src/snapshot/revert_disk_external_snap.py b/libvirt/tests/src/snapshot/revert_disk_external_snap.py index 8cf81c86419..12226500645 100644 --- a/libvirt/tests/src/snapshot/revert_disk_external_snap.py +++ b/libvirt/tests/src/snapshot/revert_disk_external_snap.py @@ -29,7 +29,9 @@ def revert_snap_and_check_files(params, vm, test, snap_name, expected_files): """ virsh.snapshot_revert(vm.name, snap_name, **virsh_dargs) - session = vm.wait_for_login() + vm.cleanup_serial_console() + vm.create_serial_console() + session = vm.wait_for_serial_login() for file in expected_files: output = session.cmd('ls %s' % file) if file not in output: @@ -49,8 +51,8 @@ def setup_test(): Prepare file and snapshot. """ test.log.info("TEST_SETUP: Create files and snaps in running guest.") - virsh.start(vm_name) - session = vm.wait_for_login() + vm.start() + session = vm.wait_for_serial_login() mem_file = " " for index, sname in enumerate(snap_names): session.cmd("touch %s" % file_list[index]) diff --git a/libvirt/tests/src/snapshot/revert_snapshot_after_xml_updated.py b/libvirt/tests/src/snapshot/revert_snapshot_after_xml_updated.py index af1ecd84d05..cd7d6c5c0fa 100644 --- a/libvirt/tests/src/snapshot/revert_snapshot_after_xml_updated.py +++ b/libvirt/tests/src/snapshot/revert_snapshot_after_xml_updated.py @@ -68,7 +68,9 @@ def check_file_exist(test, vm, params, revert_snap): if not vm.is_alive(): virsh.start(vm_name) - session = vm.wait_for_login() + vm.cleanup_serial_console() + vm.create_serial_console() + session = vm.wait_for_serial_login() if revert_snap == "1": file_list = eval(params.get("file_list"))[0:1] @@ -186,8 +188,8 @@ def run_test(): hotplug disk/hotplug vcpus/blkiotune """ test.log.info("TEST_STEP1:Prepare a running guest and create file.") - virsh.start(vm_name) - session = vm.wait_for_login() + vm.start() + session = vm.wait_for_serial_login() create_file(vm, file_list[0], session) test.log.info("TEST_STEP2: Create snapshot.") From 1e888415145500e417d1f18568dc5cbe7b2d0d6b Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 21 Nov 2024 01:44:08 -0500 Subject: [PATCH 0692/1055] iface_options:Fix error of get wrong ip addr Signed-off-by: Haijiao Zhao --- libvirt/tests/src/virtual_network/iface_bridge.py | 4 +++- libvirt/tests/src/virtual_network/iface_network.py | 11 ++++++----- libvirt/tests/src/virtual_network/iface_options.py | 5 +++-- .../src/virtual_network/virtual_network_multivms.py | 4 +++- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/libvirt/tests/src/virtual_network/iface_bridge.py b/libvirt/tests/src/virtual_network/iface_bridge.py index 25ed63dae25..115fc954d1c 100644 --- a/libvirt/tests/src/virtual_network/iface_bridge.py +++ b/libvirt/tests/src/virtual_network/iface_bridge.py @@ -17,6 +17,8 @@ from virttest.libvirt_xml.devices import interface from virttest.libvirt_xml import network_xml +from provider.virtual_network import network_base + NETWORK_SCRIPT = "/etc/sysconfig/network-scripts/ifcfg-" @@ -249,7 +251,7 @@ def check_net_functions(guest_ip, ping_count, ping_timeout, guest_session, host_ remote_url = params.get("remote_ip", "www.google.com") try: - vm1_ip = utils_net.get_guest_ip_addr(session1, mac) + vm1_ip = network_base.get_vm_ip(session1, mac) except Exception as errs: test.fail("vm1 can't get IP with the new create bridge: %s" % errs) if test_qos: diff --git a/libvirt/tests/src/virtual_network/iface_network.py b/libvirt/tests/src/virtual_network/iface_network.py index 9f264b962fd..8c9a9088248 100644 --- a/libvirt/tests/src/virtual_network/iface_network.py +++ b/libvirt/tests/src/virtual_network/iface_network.py @@ -26,6 +26,8 @@ from virttest.libvirt_xml.devices.interface import Interface from virttest import libvirt_version +from provider.virtual_network import network_base + # Using as lower capital is not the best way to do, but this is just a # workaround to avoid changing the entire file. @@ -482,8 +484,8 @@ def run_ip_test(session, ip_ver): # It may take some time to get the ip address def get_ip_func(): - return utils_net.get_guest_ip_addr(session, iface_mac, - ip_version=ip_ver) + return network_base.get_vm_ip(session, iface_mac, + ip_ver=ip_ver) utils_misc.wait_for(get_ip_func, 5) if not get_ip_func(): @@ -1086,7 +1088,7 @@ def _check_lease(loop): if test_dhcp_range: dhcp_range = int(params.get("dhcp_range", "252")) utils_net.restart_guest_network(session, iface_mac) - vm_ip = utils_net.get_guest_ip_addr(session, iface_mac) + vm_ip = network_base.get_vm_ip(session, iface_mac) logging.debug("Guest has ip: %s", vm_ip) if not vm_ip and dhcp_range: test.fail("Guest has invalid ip address") @@ -1100,8 +1102,7 @@ def _check_lease(loop): vms_mac = vms.get_virsh_mac_address() # restart guest network to get ip addr utils_net.restart_guest_network(sess, vms_mac) - vms_ip = utils_net.get_guest_ip_addr(sess, - vms_mac) + vms_ip = network_base.get_vm_ip(sess, vms_mac) if not vms_ip and dhcp_range: test.fail("Guest has invalid ip address") elif vms_ip and not dhcp_range: diff --git a/libvirt/tests/src/virtual_network/iface_options.py b/libvirt/tests/src/virtual_network/iface_options.py index 9ac1f94d6bc..f2c28632f2b 100644 --- a/libvirt/tests/src/virtual_network/iface_options.py +++ b/libvirt/tests/src/virtual_network/iface_options.py @@ -29,6 +29,7 @@ from virttest.staging import utils_memory from virttest import libvirt_version +from provider.virtual_network import network_base # Using as lower capital is not the best way to do, but this is just a @@ -382,8 +383,8 @@ def get_guest_ip(session, mac): utils_net.restart_guest_network(session, mac) # Wait for IP address is ready utils_misc.wait_for( - lambda: utils_net.get_guest_ip_addr(session, mac), 10) - return utils_net.get_guest_ip_addr(session, mac) + lambda: network_base.get_vm_ip(session, mac), 10) + return network_base.get_vm_ip(session, mac) def check_user_network(session): """ diff --git a/libvirt/tests/src/virtual_network/virtual_network_multivms.py b/libvirt/tests/src/virtual_network/virtual_network_multivms.py index 22bd602b6a2..6b5f84c1770 100644 --- a/libvirt/tests/src/virtual_network/virtual_network_multivms.py +++ b/libvirt/tests/src/virtual_network/virtual_network_multivms.py @@ -15,6 +15,8 @@ from virttest.libvirt_xml import vm_xml from virttest.libvirt_xml.devices import interface +from provider.virtual_network import network_base + # Using as lower capital is not the best way to do, but this is just a # workaround to avoid changing the entire file. @@ -368,7 +370,7 @@ def pause_resume_vm(vm_name): for vm_i in vm_list: mac = vm_xml.VMXML.get_first_mac_by_name(vm_i.name) sess = vm_i.wait_for_serial_login() - vm_ip = utils_net.get_guest_ip_addr(sess, mac, timeout=5) + vm_ip = network_base.get_vm_ip(sess, mac, timeout=5) session_n_ip[sess] = vm_ip logging.debug('Vm %s ip: %s', vm_i.name, vm_ip) if not vm_ip: From 0264c27460e40f71472750934241ad7b8db70375 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 21 Nov 2024 04:02:25 -0500 Subject: [PATCH 0693/1055] passt:Fix error of getting wrong gateway Signed-off-by: Haijiao Zhao --- .../passt/passt_connectivity_between_2vms.py | 4 ++-- provider/virtual_network/passt.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py b/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py index f5b53031d2b..eca15eff4f0 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py +++ b/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py @@ -106,9 +106,9 @@ def run(test, params, env): for session in (server_session, client_session)] server_default_gw = utils_net.get_default_gateway( - session=server_session, force_dhcp=True) + session=server_session, force_dhcp=True, json=True) server_default_gw_v6 = utils_net.get_default_gateway( - session=server_session, ip_ver='ipv6') + session=server_session, ip_ver='ipv6', json=True) firewalld.stop() server_session.cmd('systemctl stop firewalld') diff --git a/provider/virtual_network/passt.py b/provider/virtual_network/passt.py index 72049e1aec1..5ece902d511 100644 --- a/provider/virtual_network/passt.py +++ b/provider/virtual_network/passt.py @@ -243,10 +243,10 @@ def check_default_gw(session, host_iface=None): :param host_iface: if given, only check gateway information on this host interface """ - host_gw = utils_net.get_default_gateway(force_dhcp=True, - target_iface=host_iface).split() - vm_gw = utils_net.get_default_gateway(session=session, - force_dhcp=True).split() + host_gw = utils_net.get_default_gateway( + force_dhcp=True, target_iface=host_iface, json=True).split() + vm_gw = utils_net.get_default_gateway( + session=session, force_dhcp=True, json=True).split() LOG.debug(f'Host and vm default ipv4 gateway: {host_gw}, {vm_gw}') if [x for x in vm_gw if x not in host_gw]: raise exceptions.TestFail( From 3030cc6780f1e31934f77622db1b0bc243328041 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Thu, 21 Nov 2024 04:35:31 -0500 Subject: [PATCH 0694/1055] Fix irregular usage of test log Signed-off-by: liang-cong-red-hat --- libvirt/tests/src/memory/memory_allocation/define_value_unit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/memory/memory_allocation/define_value_unit.py b/libvirt/tests/src/memory/memory_allocation/define_value_unit.py index 97cee49e695..3455a31eb28 100644 --- a/libvirt/tests/src/memory/memory_allocation/define_value_unit.py +++ b/libvirt/tests/src/memory/memory_allocation/define_value_unit.py @@ -133,7 +133,7 @@ def check_mem_after_operation(operation="start", session=None): test.fail('%s should be %s instead of %s ' % (attr, result[attr], new_value)) else: - test.log.debug("Get correct %s=%s in xml", (attr, result[attr])) + test.log.debug("Get correct %s=%s in xml", attr, result[attr]) def set_negative_memory(case): """ From 027b7f5d1692605dddb225b92669c07b6c8d2539 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Thu, 21 Nov 2024 01:51:09 -0500 Subject: [PATCH 0695/1055] Fix fs-freezed failure by refined error message Signed-off-by: chunfuwen --- libvirt/tests/cfg/virsh_cmd/domain/virsh_domfsinfo.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_domfsinfo.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_domfsinfo.cfg index b68a7724494..24ecdfc56a5 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_domfsinfo.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_domfsinfo.cfg @@ -37,4 +37,4 @@ check_point_msg = "error: operation forbidden: read only access prevents virDomainGetFSInfo" - fs_freezed: domfsfreeze = "yes" - check_point_msg = "The command guest-get-fsinfo has been disabled for this instance;Command guest-get-fsinfo has been disabled: the agent is in frozen state" + check_point_msg = "The command guest-get-fsinfo has been disabled for this instance;Command guest-get-fsinfo has been disabled: the agent is in frozen state;Command guest-get-fsinfo has been disabled: the command is not allowed" From 593d6b7f574c687decff89c5d65d55eae77d5979 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Fri, 22 Nov 2024 04:16:28 -0500 Subject: [PATCH 0696/1055] interface_base:Add --color=never to ip command Signed-off-by: Haijiao Zhao --- provider/interface/interface_base.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/provider/interface/interface_base.py b/provider/interface/interface_base.py index 36f0d447d0a..3aa12e76662 100644 --- a/provider/interface/interface_base.py +++ b/provider/interface/interface_base.py @@ -55,7 +55,8 @@ def get_vm_iface(vm_session, ignore_status=False): :param ignore_status: Whether to raise an exception if there is no interface :return: VM's first interface """ - p_iface, _v_ifc = utils_net.get_remote_host_net_ifs(vm_session) + p_iface, _v_ifc = utils_net.get_remote_host_net_ifs( + vm_session, ip_options='-color=never') vm_iface = p_iface[:1:] if not vm_iface: if ignore_status: From 28b6e3a3d320fcf7cbe35a3cb2252833f234dcd1 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Mon, 25 Nov 2024 00:46:10 -0500 Subject: [PATCH 0697/1055] Fix setvirtlog failure due to not completion start of VM Add vm.wait_for_login().close() before calling on check log Signed-off-by: chunfuwen --- .../src/daemon/conf_file/libvirtd_conf/set_audit_logging.py | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/src/daemon/conf_file/libvirtd_conf/set_audit_logging.py b/libvirt/tests/src/daemon/conf_file/libvirtd_conf/set_audit_logging.py index 7ecf2db04c3..0add0138d9d 100644 --- a/libvirt/tests/src/daemon/conf_file/libvirtd_conf/set_audit_logging.py +++ b/libvirt/tests/src/daemon/conf_file/libvirtd_conf/set_audit_logging.py @@ -142,6 +142,7 @@ def check_concurrent_filters(): check_virt_type_from_audit_log() check_msg_in_libvirtd_log("virDomainAudit") elif test_scenario == "default_audit_log": + vm.wait_for_login().close() ausearch_audit_log() elif test_scenario == "concurrent_filters": check_concurrent_filters() From 2a37fc72ac76cf9b3b52195ebfb6c37f6d225da0 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Mon, 25 Nov 2024 01:08:31 -0500 Subject: [PATCH 0698/1055] Fix virt-admin check log failure Use utils_misc.wait_for to wait for expected message log Signed-off-by: chunfuwen --- .../conf_file/libvirtd_conf/virt_admin_logging.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/src/daemon/conf_file/libvirtd_conf/virt_admin_logging.py b/libvirt/tests/src/daemon/conf_file/libvirtd_conf/virt_admin_logging.py index 297d360b9b9..fc6b559ab8b 100644 --- a/libvirt/tests/src/daemon/conf_file/libvirtd_conf/virt_admin_logging.py +++ b/libvirt/tests/src/daemon/conf_file/libvirtd_conf/virt_admin_logging.py @@ -16,7 +16,7 @@ from avocado.utils import process from virttest import utils_libvirtd -from virttest import virt_vm +from virttest import virt_vm, utils_misc from virttest import virt_admin from virttest.libvirt_xml import vm_xml @@ -117,8 +117,7 @@ def check_msg_in_var_log_message(params, test): log_config_path = params.get("log_file_path") str_to_grep = params.get("str_to_grep") cmd = "grep -E -l '%s' %s" % (str_to_grep, log_config_path) - if process.run(cmd, shell=True, ignore_status=True).exit_status != 0: - test.fail("Check message log:%s failed in log file:%s" % (str_to_grep, log_config_path)) + return process.run(cmd, shell=True, ignore_status=True).exit_status == 0 def run(test, params, env): @@ -144,7 +143,11 @@ def run(test, params, env): except virt_vm.VMStartError as e: LOG.debug("VM failed to start as expected." "Error: %s", str(e)) - check_msg_in_var_log_message(params, test) + result = utils_misc.wait_for(lambda: check_msg_in_var_log_message(params, test), timeout=20) + if not result: + log_config_path = params.get("log_file_path") + str_to_grep = params.get("str_to_grep") + test.fail("Check message log:%s failed in log file:%s" % (str_to_grep, log_config_path)) finally: # Recover VM LOG.info("Restoring vm...") From babc3acae37be2af7463a037d44fe5684dbd1c53 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Mon, 25 Nov 2024 01:36:28 -0500 Subject: [PATCH 0699/1055] Fix crash_regression_mix_boot_order_os_boot failure os_xml.boots support list instead of dictionary Signed-off-by: chunfuwen --- libvirt/tests/src/daemon/crash_regression.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/daemon/crash_regression.py b/libvirt/tests/src/daemon/crash_regression.py index 9a4dd99c9d4..c2f7cd79723 100644 --- a/libvirt/tests/src/daemon/crash_regression.py +++ b/libvirt/tests/src/daemon/crash_regression.py @@ -83,7 +83,7 @@ def run_mix_boot_order_os_boot(params, libvirtd, vm): try: if not vm_xml.os.boots: os_xml = vm_xml.os - os_xml.boots = {'dev': 'hd'} + os_xml.boots = ['hd'] vm_xml.os = os_xml else: logging.debug(vm_xml.os.boots) From 0e192f5c565afd13eec2c8ded4f15ada2527c5d4 Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 22 Jul 2024 15:27:15 +0800 Subject: [PATCH 0700/1055] migration: Update vtpm device migration case Update for following case: XXX-177314 - Migrate[p2p/tunnelled/postcopy] a guest with vtpm device Signed-off-by: lcheng --- .../cfg/migration/migrate_options_shared.cfg | 3 - .../migration_with_vtpm_dev.cfg | 66 +++++ .../migration_with_external_tpm.py | 3 + .../migration_with_shared_tpm.py | 3 + .../migration_with_vtpm_dev.py | 240 ++++++++++++++++++ provider/migration/base_steps.py | 39 +++ 6 files changed, 351 insertions(+), 3 deletions(-) create mode 100644 libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_vtpm_dev.cfg create mode 100644 libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_dev.py diff --git a/libvirt/tests/cfg/migration/migrate_options_shared.cfg b/libvirt/tests/cfg/migration/migrate_options_shared.cfg index 915164c85c2..888c88afaa9 100644 --- a/libvirt/tests/cfg/migration/migrate_options_shared.cfg +++ b/libvirt/tests/cfg/migration/migrate_options_shared.cfg @@ -23,12 +23,9 @@ virsh_migrate_dest_state = running virsh_migrate_src_state = running virsh_migrate_libvirtd_state = 'on' - # Local URI virsh_migrate_connect_uri = "qemu:///system" - log_outputs = "/var/log/libvirt/libvirtd.log" - variants: - with_postcopy: postcopy_options = "--postcopy" diff --git a/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_vtpm_dev.cfg b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_vtpm_dev.cfg new file mode 100644 index 00000000000..2c1722b020e --- /dev/null +++ b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_vtpm_dev.cfg @@ -0,0 +1,66 @@ +- migration_with_vtpm.migration_with_vtpm_dev: + type = migration_with_vtpm_dev + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = "" + # SSH connection time out + ssh_timeout = 60 + start_vm = "no" + # Local URI + virsh_migrate_connect_uri = "qemu:///system" + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + transport_type = "ssh" + migrate_desturi_type = "ssh" + virsh_migrate_desturi = "qemu+ssh://${migrate_dest_host}/system" + tpm_cmd = "tpm2_getrandom --hex 16" + auth_sec_dict = {"sec_ephemeral": "no", "sec_private": "yes", "sec_desc": "sample vTPM secret", "sec_usage": "vtpm", "sec_name": "VTPM_example"} + src_secret_value = "sec value test" + src_secret_value_path = "/var/tmp/src_secretinfile" + dst_secret_value = ${src_secret_value} + dst_secret_value_path = "/var/tmp/dst_secretinfile" + swtpm_path = "/var/lib/libvirt/swtpm/" + swtpm_log = "/var/log/swtpm/libvirt/qemu/${migrate_main_vm}-swtpm.log" + status_error = "yes" + err_msg = "guest CPU doesn't match specification: missing features" + status_error_again = "no" + migrate_again = "yes" + tpm_model = "tpm-crb" + aarch64: + tpm_model = "tpm-tis" + tpm_dict = {'tpm_model': '${tpm_model}', 'backend': {'backend_type': 'emulator', 'backend_version': '2.0', 'encryption_secret': '0051c505-1ad0-4d77-9b3e-360c8f5e3b86'}} + variants: + - p2p: + virsh_migrate_options = '--live --p2p --verbose' + - non_p2p: + virsh_migrate_options = '--live --verbose' + variants: + - with_precopy: + - with_postcopy: + postcopy_options = '--postcopy --postcopy-bandwidth 10 --bandwidth 10' + action_during_mig_again = '[{"func": "virsh.migrate_postcopy", "func_param": "'%s' % params.get('migrate_main_vm')", "need_sleep_time": "5"}]' + variants test_case: + - default: + - tunnelled: + only with_precopy + only p2p + virsh_migrate_extra = "--tunnelled" + - diff_secret_on_src_and_dst: + only with_precopy + status_error = "yes" + migrate_again = "no" + src_secret_value = "sec value test" + dst_secret_value = "sec value diff" + err_msg = "qemu-kvm: tpm-emulator: Setting the stateblob \(type 1\) failed with a TPM error 0x21 decryption error" diff --git a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_external_tpm.py b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_external_tpm.py index bfcb6c0d081..0f399ce09b0 100644 --- a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_external_tpm.py +++ b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_external_tpm.py @@ -224,12 +224,15 @@ def cleanup_test(): migration_obj.cleanup_connection() vm_name = params.get("migrate_main_vm") + desturi = params.get("virsh_migrate_desturi") libvirt_version.is_libvirt_feature_supported(params) vm = env.get_vm(vm_name) migration_obj = base_steps.MigrationBase(test, vm, params) try: + if not base_steps.check_cpu_for_mig(desturi): + base_steps.sync_cpu_for_mig(params) setup_test() migration_obj.run_migration() verify_test() diff --git a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py index a920f52a475..e6ceb2c84be 100644 --- a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py +++ b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py @@ -268,6 +268,7 @@ def cleanup_ceph(): vm_name = params.get("migrate_main_vm") shared_storage_type = params.get('shared_storage_type', '') + desturi = params.get("virsh_migrate_desturi") libvirt_version.is_libvirt_feature_supported(params) vm = env.get_vm(vm_name) @@ -279,6 +280,8 @@ def cleanup_ceph(): try: set_secret(params) + if not base_steps.check_cpu_for_mig(desturi): + base_steps.sync_cpu_for_mig(params) setup_test() migration_obj.run_migration() verify_test() diff --git a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_dev.py b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_dev.py new file mode 100644 index 00000000000..dee89010cc5 --- /dev/null +++ b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_dev.py @@ -0,0 +1,240 @@ +import os + +from avocado.utils import process + +from virttest import remote +from virttest import utils_package +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_secret +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.migration import base_steps + +src_sec_uuid = None +dst_sec_uuid = None + + +def check_vtpm_func(params, vm, test, remote=False): + """ + Check vtpm function + + :param params: dict, test parameters + :param vm: VM object + :param test: test object + :param remote: True to check context on remote + """ + tpm_cmd = params.get("tpm_cmd") + dest_uri = params.get("virsh_migrate_desturi") + src_uri = params.get("virsh_migrate_connect_uri") + test.log.debug("Check vtpm func: %s (remote).", remote) + if remote: + if vm.serial_console is not None: + vm.cleanup_serial_console() + vm.connect_uri = dest_uri + if vm.serial_console is None: + vm.create_serial_console() + vm_session = vm.wait_for_serial_login(timeout=240) + if not utils_package.package_install("tpm2-tools", vm_session): + test.error("Failed to install tpm2-tools in vm") + cmd_result = vm_session.cmd_status(tpm_cmd) + vm_session.close() + if remote: + if vm.serial_console is not None: + vm.cleanup_serial_console() + vm.connect_uri = src_uri + if cmd_result: + test.fail("Fail to run '%s': %s." % (tpm_cmd, cmd_result)) + + +def set_secret(params): + """ + Set secret + + :param params: dict, test parameters + """ + auth_sec_dict = eval(params.get("auth_sec_dict")) + src_secret_value = params.get("src_secret_value") + src_secret_value_path = params.get("src_secret_value_path") + dst_secret_value = params.get("dst_secret_value") + dst_secret_value_path = params.get("dst_secret_value_path") + remote_pwd = params.get("migrate_dest_pwd") + remote_ip = params.get("migrate_dest_host") + remote_user = params.get("remote_user", "root") + + def _create_secret(session=None, remote_args=None, secret_value_path=None): + """ + create secret + + :param session: a session object of remote host + :param remote_args: remote host parameters + :param secret_value_path: the path of secret value + """ + libvirt_secret.clean_up_secrets(session) + global dst_sec_uuid + global src_sec_uuid + if remote_args: + dst_sec_uuid = libvirt.create_secret(auth_sec_dict, remote_args=remote_args) + else: + src_sec_uuid = libvirt.create_secret(auth_sec_dict) + auth_sec_dict.update({"sec_uuid": src_sec_uuid}) + if os.path.exists(secret_value_path): + os.remove(secret_value_path) + if session: + cmd = "echo '%s' > %s" % (dst_secret_value, secret_value_path) + process.run(cmd, shell=True) + remote.scp_to_remote(remote_ip, '22', remote_user, remote_pwd, + secret_value_path, secret_value_path, + limit="", log_filename=None, timeout=60, + interface=None) + cmd = f"virsh secret-set-value {dst_sec_uuid} --file {secret_value_path} --plain" + remote.run_remote_cmd(cmd, params) + else: + cmd = "echo '%s' > %s" % (src_secret_value, secret_value_path) + process.run(cmd, shell=True) + cmd = f"virsh secret-set-value {src_sec_uuid} --file {secret_value_path} --plain" + process.run(cmd, shell=True) + + _create_secret(secret_value_path=src_secret_value_path) + params.update({"auth_sec_dict": auth_sec_dict}) + virsh_dargs = {'remote_ip': remote_ip, 'remote_user': remote_user, + 'remote_pwd': remote_pwd, 'unprivileged_user': None, + 'ssh_remote_auth': True} + remote_virsh_session = None + remote_virsh_session = virsh.VirshPersistent(**virsh_dargs) + _create_secret(session=remote_virsh_session, remote_args=virsh_dargs, + secret_value_path=dst_secret_value_path) + + +def setup_vtpm(params, test, vm, migration_obj): + """ + Setup vTPM device in guest xml + + :param params: dict, test parameters + :param vm: VM object + :param test: test object + :param migration_obj: migration object + """ + vm_name = params.get("migrate_main_vm") + tpm_dict = eval(params.get('tpm_dict', '{}')) + auth_sec_dict = params.get("auth_sec_dict") + + test.log.info("Setup vTPM device in guest xml.") + if vm.is_alive(): + vm.destroy(gracefully=False) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + # Remove all existing tpm devices + vmxml.remove_all_device_by_type('tpm') + + tpm_dict['backend']['encryption_secret'] = auth_sec_dict['sec_uuid'] + libvirt_vmxml.modify_vm_device(vmxml, 'tpm', tpm_dict) + + vm.start() + vm.wait_for_login().close() + + +def check_ownership(swtpm_log, expected_ownership, test): + """ + Check ownership + + :param swtpm_log: swtpm log path + :param expected_ownership: Expected ownership + :param test: test object + """ + cmd = "ls -lZ %s" % swtpm_log + ret = process.run(cmd, shell=True).stdout_text.strip() + if expected_ownership not in ret: + test.fail("Swtpm log ownership not correct: %s" % ret) + + +def run(test, params, env): + """ + Test migration with vtpm device. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + + def setup_test(): + """ + Setup steps + + """ + test.log.info("Setup steps.") + set_secret(params) + migration_obj.setup_connection() + setup_vtpm(params, test, vm, migration_obj) + + def verify_test(): + """ + Verify steps + + """ + swtpm_log = params.get("swtpm_log") + + test.log.info("Verify steps.") + check_ownership(swtpm_log, "svirt_image_t", test) + virsh.shutdown(vm_name, debug=True) + if not vm.wait_for_shutdown(): + test.error('VM failed to shutdown in 60s') + check_ownership(swtpm_log, "virt_log_t", test) + + def cleanup_test(): + """ + Cleanup steps + + """ + desturi = params.get("virsh_migrate_desturi") + swtpm_path = params.get("swtpm_path") + dst_secret_value_path = params.get("dst_secret_value_path") + src_secret_value_path = params.get("src_secret_value_path") + + test.log.info("Cleanup steps.") + global src_sec_uuid + if src_sec_uuid: + virsh.secret_undefine(src_sec_uuid, debug=True, ignore_status=True) + global dst_sec_uuid + if dst_sec_uuid: + virsh.secret_undefine(dst_sec_uuid, debug=True, ignore_status=True, uri=desturi) + + migration_obj.cleanup_connection() + cmd = f"rm -rf {swtpm_path}/*" + remote.run_remote_cmd(cmd, params) + cmd = f"rm -rf {dst_secret_value_path}" + remote.run_remote_cmd(cmd, params) + process.run(cmd, shell=True, ignore_status=True) + cmd = f"rm -rf {src_secret_value_path}" + process.run(cmd, shell=True, ignore_status=True) + + vm_name = params.get("migrate_main_vm") + test_case = params.get("test_case", "") + migrate_again = "yes" == params.get("migrate_again", "no") + desturi = params.get("virsh_migrate_desturi") + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + if base_steps.check_cpu_for_mig(desturi): + if test_case != "diff_secret_on_src_and_dst": + test.cancel("Need to use machines with different cpu to test this case.") + else: + if test_case == "diff_secret_on_src_and_dst": + base_steps.sync_cpu_for_mig(params) + + try: + setup_test() + migration_obj.run_migration() + if test_case != "negative": + verify_test() + base_steps.sync_cpu_for_mig(params) + else: + migration_obj.verify_default() + if migrate_again: + migration_obj.run_migration_again() + migration_obj.verify_default() + check_vtpm_func(params, vm, test, remote=True) + finally: + cleanup_test() diff --git a/provider/migration/base_steps.py b/provider/migration/base_steps.py index 49c4259033f..03d5e23352e 100644 --- a/provider/migration/base_steps.py +++ b/provider/migration/base_steps.py @@ -13,6 +13,7 @@ from virttest import utils_libvirtd from virttest import utils_iptables from virttest import utils_misc +from virttest import virsh from virttest.utils_libvirt import libvirt_disk from virttest.utils_libvirt import libvirt_vmxml @@ -475,3 +476,41 @@ def cleanup_disks_remote(params, vm): disk_path = disk.get("source") cmd = "rm -f %s" % disk_path remote.run_remote_cmd(cmd, params, ignore_status=False) + + +def sync_cpu_for_mig(params): + """ + Sync cpu xml for migration + + :param params: Dictionary with the test parameters + """ + dest_uri = params.get("virsh_migrate_desturi") + vm_name = params.get("main_vm") + + cpu_dest_xml = virsh.domcapabilities(uri=dest_uri) + cpu_src_xml = virsh.domcapabilities() + mig_cpu_xml = os.path.join(data_dir.get_tmp_dir(), "cpu_xml") + with open(mig_cpu_xml, 'w+') as fd: + fd.write(cpu_dest_xml.stdout.strip()) + fd.write(cpu_src_xml.stdout.strip()) + out = virsh.hypervisor_cpu_baseline(mig_cpu_xml, options="--migratable") + dom_xml = vm_xml.VMXML.new_from_dumpxml(vm_name) + cpuxml = vm_xml.VMCPUXML() + cpuxml.xml = out.stdout.strip() + dom_xml.cpu = cpuxml + dom_xml.sync() + + +def check_cpu_for_mig(dest_uri): + """ + Check cpu for migration + + :param dest_uri: connect uri for destination machine + :return: if the cpu on the source and target hosts are the same, return True + """ + cpu_dest_xml = virsh.domcapabilities(uri=dest_uri, debug=True).stdout_text.strip() + cpu_src_xml = virsh.domcapabilities(debug=True).stdout_text.strip() + if cpu_dest_xml == cpu_src_xml: + return True + else: + return False From a0fe46d25dc1be31c1c51da86bb74b53ff3056ed Mon Sep 17 00:00:00 2001 From: Misbah Anjum N Date: Tue, 26 Nov 2024 02:57:09 -0600 Subject: [PATCH 0701/1055] virsh-snapshot: Update logic to verify snapshot check_snaplist function is used to verify the created snapshot by checking it's presence in the guest xml. But since there might be multiple disk name values, drivers, source files, snapshot types, etc, the verification is failing leading to false negative test result. This patch will allow us to check the disk values by checking if it is present in the list of xml parameter values. Signed-off-by: Misbah Anjum N --- .../snapshot/virsh_snapshot_create_as.py | 67 ++++++++++--------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/snapshot/virsh_snapshot_create_as.py b/libvirt/tests/src/virsh_cmd/snapshot/virsh_snapshot_create_as.py index fa629d49187..8a2caa1699b 100644 --- a/libvirt/tests/src/virsh_cmd/snapshot/virsh_snapshot_create_as.py +++ b/libvirt/tests/src/virsh_cmd/snapshot/virsh_snapshot_create_as.py @@ -73,7 +73,7 @@ def check_snap_in_image(vm_name, snap_name, backing_file=False): search_str = os.path.join(os.path.dirname(snap_file_path), os.path.basename(snap_file_path).replace(snap_name, file_suffix)) - search_str = "backing file:\s*%s" % search_str + search_str = "backing file:\\s*%s" % search_str if re.search(search_str, img_info): logging.info("Find snapshot or backing file info in image with '%s'", search_str) @@ -241,45 +241,52 @@ def check_snapslist(test, vm_name, options, option_dict, output, # For no metadata snapshot do not check name and # snapshot if no_metadata < 0: - dname = disks[num].get('name') - logging.debug("dname is %s", dname) - if dname == disk_dict['name']: - logging.info("get disk%d name same as set in " - "diskspec", num) + dnames = [] + for each in range(len(disks)): + dnames.append(disks[each].get('name')) + logging.debug("All disk names: %s", dnames) + if disk_dict['name'] in dnames: + logging.info("Found disk %s in diskspec", + disk_dict['name']) else: - test.fail("Get wrong disk%d name %s" - % (num, dname)) + test.fail("%s disk not present" + % disk_dict['name']) if option_disk.find('snapshot=') >= 0: - dsnap = disks[num].get('snapshot') - logging.debug("dsnap is %s", dsnap) - if dsnap == disk_dict['snapshot']: - logging.info("get disk%d snapshot type same" - " as set in diskspec", num) + dsnaps = [] + for each in range(len(disks)): + dsnaps.append(disks[each].get('snapshot')) + logging.debug("All snapshots are %s", dsnaps) + if disk_dict['snapshot'] in dsnaps: + logging.info("Found snapshot %s in diskspec", + disk_dict['snapshot']) else: - test.fail("Get wrong disk%d " - "snapshot type %s" % - (num, dsnap)) + test.fail("%s snapshot not present" + % disk_dict['snapshot']) if option_disk.find('driver=') >= 0: - dtype = disks[num].find('driver').get('type') - if dtype == disk_dict['driver']: - logging.info("get disk%d driver type same as " - "set in diskspec", num) + dtypes = [] + for each in range(len(disks)): + dtypes.append(disks[each].find('driver').get('type')) + logging.debug("All drivers are %s", dtypes) + if disk_dict['driver'] in dtypes: + logging.info("Found driver %s in diskspec", + disk_dict['driver']) else: - test.fail("Get wrong disk%d driver " - "type %s" % (num, dtype)) + test.fail("%s driver not present" + % disk_dict['driver']) if option_disk.find('file=') >= 0: - sfile = disks[num].find('source').get('file') - if sfile == disk_dict['file']: - logging.info("get disk%d source file same as " - "set in diskspec", num) - if os.path.exists(sfile): - os.unlink(sfile) + sfiles = [] + for each in range(len(disks)): + sfiles.append(disks[each].find('source').get('file')) + logging.debug("All sources are %s", sfiles) + if disk_dict['file'] in sfiles: + logging.info("Found source %s in diskspec", + disk_dict['file']) else: - test.fail("Get wrong disk%d source " - "file %s" % (num, sfile)) + test.fail("%s source not present" + % disk_dict['file']) # For memspec check if the xml is same as setting # Also check if the mem file exists From f6821e8fcfb33b4171d9f0d9d0aeaf22990014a5 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 26 Nov 2024 04:37:40 -0500 Subject: [PATCH 0702/1055] s390x/migrate: disable some unsupported tests 1. No timer support on s390x 2. No mem device support (nv)dimm on s390x Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/migration/migrate_mem.cfg | 2 ++ libvirt/tests/cfg/migration/migrate_options_shared.cfg | 1 + 2 files changed, 3 insertions(+) diff --git a/libvirt/tests/cfg/migration/migrate_mem.cfg b/libvirt/tests/cfg/migration/migrate_mem.cfg index 06c97aa1197..866553f38c8 100644 --- a/libvirt/tests/cfg/migration/migrate_mem.cfg +++ b/libvirt/tests/cfg/migration/migrate_mem.cfg @@ -28,6 +28,7 @@ start_vm = "no" variants case: - mem_device: + no s390-virtio cpuxml_cpu_mode = "host-model" aarch64: cpuxml_cpu_mode = "host-passthrough" @@ -54,6 +55,7 @@ - mem_balloon: ballooned_mem = "716800" - mem_nvdimm: + no s390-virtio nvdimm_file_path = '${nfs_mount_dir}/nvdimm' nvdimm_file_size = '512M' vm_attrs = {'max_mem_rt': 4096, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'M', 'vcpu': 4, 'cpu': {'mode': 'host-passthrough', 'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '1024', 'unit': 'M'}, {'id': '1', 'cpus': '2-3', 'memory': '1024', 'unit': 'M'}]}} diff --git a/libvirt/tests/cfg/migration/migrate_options_shared.cfg b/libvirt/tests/cfg/migration/migrate_options_shared.cfg index 915164c85c2..92db677aa84 100644 --- a/libvirt/tests/cfg/migration/migrate_options_shared.cfg +++ b/libvirt/tests/cfg/migration/migrate_options_shared.cfg @@ -493,6 +493,7 @@ dst_secret_value = ${src_secret_value} cmd_in_vm_after_migration = "tpm2_getrandom 10" - timer: + no s390-virtio timer_migration = "yes" asynch_migrate = "yes" actions_during_migration = "setmaxdowntime" From 67c27457cf62ca5ff91ec53f182aa15782087b1c Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 26 Nov 2024 10:49:20 -0500 Subject: [PATCH 0703/1055] migrate_network: enable configuration of host interface direct-macvtap uses host interfaces on source and target. Make them configurable by their name. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/migration/migrate_network.cfg | 2 ++ libvirt/tests/src/migration/migrate_network.py | 12 ++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/cfg/migration/migrate_network.cfg b/libvirt/tests/cfg/migration/migrate_network.cfg index b79596b4e3b..1e9216bfdd9 100644 --- a/libvirt/tests/cfg/migration/migrate_network.cfg +++ b/libvirt/tests/cfg/migration/migrate_network.cfg @@ -16,6 +16,8 @@ virsh_migrate_dest_state = running virsh_migrate_src_state = running virsh_migrate_options = "--live --p2p --verbose" + host_iface_src = + host_iface_dst = # Local URI virsh_migrate_connect_uri = "qemu:///system" migrate_vm_back = "yes" diff --git a/libvirt/tests/src/migration/migrate_network.py b/libvirt/tests/src/migration/migrate_network.py index 3a1bfa3756e..6c8f8aff778 100644 --- a/libvirt/tests/src/migration/migrate_network.py +++ b/libvirt/tests/src/migration/migrate_network.py @@ -92,17 +92,19 @@ def update_iface_xml(vm_name, iface_dict, virsh_instance=virsh): vm_sync(vmxml, vm_name, virsh_instance=virsh_instance) logging.debug("VM XML after updating interface: %s" % vmxml) - def update_net_dict(net_dict, runner=utils_net.local_runner): + def update_net_dict(net_dict, iface_name, runner=utils_net.local_runner): """ Update network dict :param net_dict: The network dict to be updated + :param iface_name: host iface name to use for direct network :param runner: Command runner :return: Updated network dict """ if net_dict.get("name", "") == "direct-macvtap": logging.info("Updating network iface name") - iface_name = utils_net.get_net_if(runner=runner, state="UP")[0] + if not iface_name: + iface_name = utils_net.get_net_if(runner=runner, state="UP")[0] net_dict.update({'forward_interface': [{'dev': iface_name}]}) else: # TODO: support other types @@ -204,6 +206,8 @@ def create_fake_tap(remote_session): params.get("migrate_source_host")) src_uri = params.get("virsh_migrate_connect_uri") dest_uri = params.get("virsh_migrate_desturi") + host_iface_src = params.get("host_iface_src") + host_iface_dst = params.get("host_iface_dst") vm_name = params.get("migrate_main_vm") vm = env.get_vm(vm_name) @@ -257,11 +261,11 @@ def create_fake_tap(remote_session): test.fail("Failed to create ovs bridge on remote. Status: %s" "Stdout: %s" % (status, stdout)) if network_dict: - update_net_dict(network_dict, runner=remote_session.cmd) + update_net_dict(network_dict, host_iface_src, runner=remote_session.cmd) libvirt_network.create_or_del_network( network_dict, remote_args=remote_virsh_dargs) logging.info("dest: network created") - update_net_dict(network_dict) + update_net_dict(network_dict, host_iface_dst) libvirt_network.create_or_del_network(network_dict) logging.info("localhost: network created") From 4071f494931de9db881cc4f8dac3176f9a5d48fe Mon Sep 17 00:00:00 2001 From: nanli Date: Wed, 27 Nov 2024 14:50:33 +0800 Subject: [PATCH 0704/1055] fix memory cases format output fail due regex issue missing one format label Signed-off-by: nanli --- .../virtio_mem_with_memory_allocation_and_numa.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.py b/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.py index 71a59b30aeb..961c3f8dfbd 100644 --- a/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.py +++ b/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.py @@ -33,7 +33,7 @@ def adjust_virtio_mem_size_unit(params, test): params.update({"target_size": target_size}) params.update({"request_size": request_size}) - test.log.debug("Convert params: target_size to be %s, request_size to be", + test.log.debug("Convert params: target_size to be %s, request_size to be %s", target_size, request_size) From e0f34a7d13fd22d3a7e83c797a078931fe08ba74 Mon Sep 17 00:00:00 2001 From: nanli Date: Wed, 27 Nov 2024 16:40:05 +0800 Subject: [PATCH 0705/1055] make cpu topology error msg be more compatible give one more error msg Signed-off-by: nanli --- libvirt/tests/cfg/cpu/max_vcpus.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/cpu/max_vcpus.cfg b/libvirt/tests/cfg/cpu/max_vcpus.cfg index f2bca771803..0d479677b48 100644 --- a/libvirt/tests/cfg/cpu/max_vcpus.cfg +++ b/libvirt/tests/cfg/cpu/max_vcpus.cfg @@ -60,4 +60,4 @@ only q35 check = "ioapic_iommu_ne" guest_vcpu = "711" - err_msg = "unsupported configuration: Maximum CPUs greater than specified machine type limit|exceeds the maximum cpus supported" + err_msg = "unsupported configuration: Maximum CPUs greater than specified machine type limit|exceeds the maximum cpus supported|CPU topology doesn't match maximum vcpu count" From 378e8f269fa278ea9eabcf3656c7310f102e996d Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Wed, 27 Nov 2024 02:56:53 -0500 Subject: [PATCH 0706/1055] Fix guest agent get illegal character when gettting ip address Previously,it attempts to login guest and use command to get ipaddress, in some s390x guest, it may pop up some illegal characters while executing those commands, such as [35m192.168.122.21[0m' Moreover, before install guest-agent, make sure VM can be accessed Signed-off-by: chunfuwen --- .../src/virsh_cmd/domain/virsh_set_user_password.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_set_user_password.py b/libvirt/tests/src/virsh_cmd/domain/virsh_set_user_password.py index af596ee33e0..48d14a63604 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_set_user_password.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_set_user_password.py @@ -2,7 +2,6 @@ from avocado.utils import process -from virttest import utils_net from virttest import remote from virttest import virsh from virttest.utils_test import libvirt @@ -60,8 +59,7 @@ def run(test, params, env): else: # Get guest ip address session = vm.wait_for_login(timeout=30, username="root", password=ori_passwd) - vm_mac = vm.get_virsh_mac_address() - vm_ip = utils_net.get_guest_ip_addr(session, vm_mac) + vm_ip = vm.wait_for_get_address(nic_index=0, timeout=120) # Add user if add_user: @@ -127,7 +125,11 @@ def run(test, params, env): (set_user_name, output)) session.close() finally: - vmxml_bak.sync() # Recover VM if vm.is_alive(): + # always restore root password in case previously case execution is broken + if status_error != "yes": + virsh.set_user_password(vm_name, set_user_name, ori_passwd, False, + option=option, debug=True) vm.destroy(gracefully=False) + vmxml_bak.sync() From e7eda30bb3edd37466ff3631fd3b9e805aa3ae01 Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 27 Nov 2024 23:07:26 +0800 Subject: [PATCH 0707/1055] migration: Using migrate_vm_back option Use migrate_vm_back option in avocado-vt/share/cfg/base.cfg to determine whether to migrate vm back to source host. Signed-off-by: lcheng --- .../guest_os_booting/migration/migration_boot.py | 14 ++++++++++++-- .../migration_with_external_tpm.py | 3 +++ .../migration_with_shared_tpm.py | 4 ++++ provider/migration/base_steps.py | 3 +++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/guest_os_booting/migration/migration_boot.py b/libvirt/tests/src/guest_os_booting/migration/migration_boot.py index e8362e95683..4cd0818270a 100644 --- a/libvirt/tests/src/guest_os_booting/migration/migration_boot.py +++ b/libvirt/tests/src/guest_os_booting/migration/migration_boot.py @@ -49,6 +49,17 @@ def setup_test(): update_vm_xml(vm, params) migration_obj.setup_default() + def verify_test_again(): + """ + Test verify + """ + migrate_vm_back = "yes" == params.get("migrate_vm_back", "yes") + if not migrate_vm_back: + return + test.log.info("Verify test again.") + dargs = {"check_disk_on_dest": "no"} + migration_obj.migration_test.post_migration_check([vm], dargs) + vm_name = guest_os_booting_base.get_vm(params) vm = env.get_vm(vm_name) @@ -62,8 +73,7 @@ def setup_test(): test.log.info("TEST_STEP: Migrate back the VM to the source host.") migration_obj.run_migration_back() - dargs = {"check_disk_on_dest": "no"} - migration_obj.migration_test.post_migration_check([vm], dargs) + verify_test_again() finally: migration_obj.cleanup_default() diff --git a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_external_tpm.py b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_external_tpm.py index bfcb6c0d081..a8b170cdc92 100644 --- a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_external_tpm.py +++ b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_external_tpm.py @@ -197,6 +197,9 @@ def verify_test_again(): """ tpm_security_contexts = params.get("tpm_security_contexts") + migrate_vm_back = "yes" == params.get("migrate_vm_back", "yes") + if not migrate_vm_back: + return check_vtpm_func(params, vm, test) vm.shutdown() diff --git a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py index a920f52a475..0a60cf961ab 100644 --- a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py +++ b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py @@ -250,6 +250,10 @@ def verify_test_again(): Verify steps for migration back """ + migrate_vm_back = "yes" == params.get("migrate_vm_back", "yes") + if not migrate_vm_back: + return + tpm_security_contexts_restore = params.get("tpm_security_contexts_restore") check_vtpm_func(params, vm, test) vm.shutdown() diff --git a/provider/migration/base_steps.py b/provider/migration/base_steps.py index 49c4259033f..efc8f430116 100644 --- a/provider/migration/base_steps.py +++ b/provider/migration/base_steps.py @@ -228,6 +228,9 @@ def run_migration_back(self): """ Execute migration from target host to source host """ + migrate_vm_back = "yes" == self.params.get("migrate_vm_back", "yes") + if not migrate_vm_back: + return virsh_options = self.params.get("virsh_options", "") extra = self.params.get("virsh_migrate_extra") options = self.params.get("virsh_migrate_options", "--live --verbose") From ad58794c23a8b90158f8ff2854e2cfbbe7187d25 Mon Sep 17 00:00:00 2001 From: Yan Fu Date: Thu, 28 Nov 2024 10:01:50 +0800 Subject: [PATCH 0708/1055] Modify passt udp listen socket to a shared ipv4/ipv6 one Signed-off-by: Yan Fu --- .../tests/cfg/virtual_network/passt/passt_attach_detach.cfg | 2 +- libvirt/tests/cfg/virtual_network/passt/passt_function.cfg | 6 +++--- libvirt/tests/cfg/virtual_network/passt/passt_lifecycle.cfg | 2 +- libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg index 649effd1823..eafee0b3439 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg @@ -39,7 +39,7 @@ vm_ping_outside = pass vm_ping_host_public = pass tcp_port_list = [9000, '*:31339'] - udp_port_list = ['0.0.0.0:2025', '[::]:2025'] + udp_port_list = ['*:2025'] conn_check_args_0 = ('TCP4', 'localhost', 31339, 41339, True, None) conn_check_args_1 = ('TCP6', 'localhost', 31339, 41339, True, None) conn_check_args_2 = ('UDP4', 'localhost', 2025, 2025, True, None) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg index 78468e5eb6a..a2803e50729 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg @@ -14,7 +14,7 @@ - non_root_user: test_user = USER.EXAMPLE test_passwd = PASSWORD.EXAMPLE - user_id = + user_id = unpr_vm_name = UNPRIVILEGED_VM.EXAMPLE socket_dir = f'/run/user/{user_id}/libvirt/qemu/run/passt/' variants scenario: @@ -44,7 +44,7 @@ portForwards = [${portForward_0}, ${portForward_1}, ${portForward_2}, ${portForward_3}] proc_checks = ['--tcp-ports 31339:41339', '--udp-ports 2025', f'--tcp-ports {host_ip}/4025-4035:5025-5035,9000,~4030-4034', f'--udp-ports {host_ip_v6}/8002,4431:4432'] tcp_port_list = [4025, 4026, 4027, 4028, 4029, 4035, 9000, '*:31339'] - udp_port_list = ['0.0.0.0:2025', '[::]:2025', f'[{host_ip_v6}]:4431', f'[{host_ip_v6}]:8002'] + udp_port_list = ['*:2025', f'[{host_ip_v6}]:4431', f'[{host_ip_v6}]:8002'] conn_check_args_0 = ('TCP4', host_ip, 31339, 41339, True, None) conn_check_args_1 = ('TCP4', host_ip, 4025, 5025, True, None) conn_check_args_2 = ('TCP4', 'localhost', 4025, 5025, False, 'Connection refused') @@ -60,7 +60,7 @@ portForward_1 = {'attrs': {'proto': 'udp', 'dev': host_iface}, 'ranges': [{'start': '2025'}]} portForwards = [${portForward_0}, ${portForward_1}] tcp_port_list = [f'*%{host_iface}:31339'] - udp_port_list = [f'0.0.0.0%{host_iface}:2025', f'[::]%{host_iface}:2025'] + udp_port_list = [f'*%{host_iface}:2025'] conn_check_args_1 = ('TCP4', host_ip, 31339, 41339, True, None) conn_check_args_2 = ('TCP6', host_ip_v6, 31339, 41339, True, None) conn_check_args_3 = ('UDP4', host_ip, 2025, 2025, True, None) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_lifecycle.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_lifecycle.cfg index d155c6566b7..edac5f3569c 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_lifecycle.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_lifecycle.cfg @@ -42,7 +42,7 @@ portForwards = [${portForward_0}, ${portForward_1}, ${portForward_2}] proc_checks = ['--tcp-ports 31339:41339', '--udp-ports 2025', f'--tcp-ports {host_ip}/4025-4035:5025-5035,9000,~4030-4034'] tcp_port_list = [4025, 4026, 4027, 4028, 4029, 4035, 9000, '*:31339'] - udp_port_list = ['0.0.0.0:2025', '[::]:2025'] + udp_port_list = ['*:2025'] conn_check_args_0 = ('TCP4', host_ip, 31339, 41339, True, None) conn_check_args_1 = ('TCP4', host_ip, 4025, 5025, True, None) conn_check_args_2 = ('TCP4', 'localhost', 4025, 5025, False, 'Connection refused') diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg index 06f3bd3a99a..20444a0b981 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg @@ -35,7 +35,7 @@ vm_ping_outside = pass vm_ping_host_public = pass tcp_port_list = ['*:31339'] - udp_port_list = ['0.0.0.0:2025', '[::]:2025'] + udp_port_list = ['*:2025'] conn_check_args_0 = ('TCP4', 'localhost', 31339, 41339, True, None) conn_check_args_1 = ('TCP6', 'localhost', 31339, 41339, True, None) conn_check_args_2 = ('UDP4', 'localhost', 2025, 2025, True, None) From ee3a5bf36de2779dc149d10e6a48a73dbeb5c960 Mon Sep 17 00:00:00 2001 From: Yan Fu Date: Thu, 28 Nov 2024 10:45:29 +0800 Subject: [PATCH 0709/1055] Increate wait time to ensure passt process can restart successfully Signed-off-by: Yan Fu --- libvirt/tests/src/virtual_network/passt/passt_reconnect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py index d7397fbb7ed..3f3456b3251 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py +++ b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py @@ -94,7 +94,7 @@ def run(test, params, env): ignore_status=True).stdout_text.strip() process.run(f'kill -9 {pid_passt}', shell=True) - utils_misc.wait_for(lambda: passt.get_proc_info('passt'), 10, + utils_misc.wait_for(lambda: passt.get_proc_info('passt'), 30, ignore_errors=True) passt_proc_r = passt.get_proc_info('passt') LOG.debug(f'passt process info after reconnect: {passt_proc_r}') From 6a351d5c1da96a0367f2c8851b7ef0f764dbc1ad Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Thu, 28 Nov 2024 04:10:18 -0500 Subject: [PATCH 0710/1055] Fix virtio_win_dir issue and change cases target Signed-off-by: Ming Xie --- v2v/tests/cfg/function_test_esx.cfg | 10 +++++++--- v2v/tests/src/function_test_esx.py | 5 +---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 684ae508213..3bc6e5c206c 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -130,8 +130,10 @@ main_vm = VM_NAME_WIN_SCHTASKS_V2V_EXAMPLE - OGAC_balloon: only esx_80 + only dest_libvirt checkpoint = "ogac_balloon" - virtio_win_path = EXPORT_VIRTIO_WIN_PATH_V2V_EXAMPLE + #Not use virtio_win_path due to bug RHEL-69035 + #virtio_win_path = EXPORT_VIRTIO_WIN_PATH_V2V_EXAMPLE variants: - win2022: os_version = "win2022" @@ -215,6 +217,7 @@ iface_macs = VM_MAC_ADDR_1_STATIC_IP_MAC_CONF_V2V_EXAMPLE_2 - vmware_tools: only esx_80 + only dest_libvirt checkpoint = 'vmware_tools' variants: - win2022: @@ -241,6 +244,7 @@ boottype = 3 - multiple_online_disks: only esx_80 + only dest_libvirt checkpoint = 'check_online_disks' variants: - win2022: @@ -648,9 +652,9 @@ msg_content = 'v2v: add_drive.*?copyonread:true' main_vm = VM_NAME_ESX70_RHEL7_V2V_EXAMPLE - env_leak: - only esx_70 + only esx_80 only dest_json,local - main_vm = VM_NAME_WIN2019_V2V_EXAMPLE + main_vm = VM_NAME_ESX80_WIN2019_V2V_EXAMPLE env_settings = 'HOME=/root LIBGUESTFS_BACKEND=direct' unprivileged_user = 'USER_UNPRIVILEGED_V2V_EXAMPLE' os_directory = '/home/${unprivileged_user}' diff --git a/v2v/tests/src/function_test_esx.py b/v2v/tests/src/function_test_esx.py index ace087f7eb9..30a9db45de9 100644 --- a/v2v/tests/src/function_test_esx.py +++ b/v2v/tests/src/function_test_esx.py @@ -607,9 +607,6 @@ def vm_check(status_error): vmchecker.checker.create_session() if os_type == 'windows': services = ['qemu-ga', 'balloon'] - virtio_win_env = os.getenv('VIRTIO_WIN') - if virtio_win_env and 'rhv-guest-tools' in virtio_win_env: - services.append('spice-ga') for ser in services: check_windows_service(vmchecker.checker, ser) else: @@ -804,7 +801,7 @@ def vm_check(status_error): ovirt4_path = os.path.dirname(ovirtsdk4.__file__) dst_ovirt4_path = ovirt4_path + '.bak' os.rename(ovirt4_path, dst_ovirt4_path) - if checkpoint[0].startswith('ogac'): + if checkpoint[0].startswith('ogac') and 'ogac_balloon' not in checkpoint: os.environ['VIRTIO_WIN'] = virtio_win_path if os_type == 'linux' and not utils_v2v.multiple_versions_compare(implementation_change_ver) and \ os.path.isdir(os.getenv('VIRTIO_WIN')): From a4db6dd9600c4b7ae02fcdd3cb8a9d97e5bcfcd9 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Fri, 29 Nov 2024 17:53:26 +0800 Subject: [PATCH 0711/1055] virsh_detach_device_alias: remove test.skip test.skip is not used any more. Signed-off-by: Dan Zheng --- .../tests/src/virsh_cmd/domain/virsh_detach_device_alias.py | 2 +- libvirt/tests/src/virtual_disks/virtual_disks_gluster.py | 2 +- libvirt/tests/src/virtual_network/iface_coalesce.py | 2 +- libvirt/tests/src/vm_boot_with_kernel_param.py | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py b/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py index 1ac27c41088..92528d47d09 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py @@ -270,7 +270,7 @@ def start_usbredirserver(): if input_type == "passthrough": event = process.run("ls /dev/input/event*", shell=True, ignore_status=True).stdout if len(event) == 0: - test.skip("Not found any input devices") + test.cancel("Not found any input devices") input_dict.update({"source_evdev": event.decode('utf-8').split()[0]}) input_obj = Input(type_name=input_type) diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_gluster.py b/libvirt/tests/src/virtual_disks/virtual_disks_gluster.py index f404e37f501..8107f648c39 100644 --- a/libvirt/tests/src/virtual_disks/virtual_disks_gluster.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_gluster.py @@ -231,7 +231,7 @@ def test_pmsuspend(vm_name): virsh.undefine(vm_name, '--nvram', ignore_status=False) if virsh.create(vmxml_for_test.xml, **virsh_dargs).exit_status: vmxml_backup.define() - test.skip("can't create the domain") + test.cancel("can't create the domain") # Run the tests. if pm_enabled: diff --git a/libvirt/tests/src/virtual_network/iface_coalesce.py b/libvirt/tests/src/virtual_network/iface_coalesce.py index 4e47a463491..6096cea83e1 100644 --- a/libvirt/tests/src/virtual_network/iface_coalesce.py +++ b/libvirt/tests/src/virtual_network/iface_coalesce.py @@ -191,7 +191,7 @@ def run(test, params, env): """ if not libvirt_version.version_compare(3, 3, 0): - test.skip("Coalesce setting is only supported by libvirt3.3.0 and above") + test.cancel("Coalesce setting is only supported by libvirt3.3.0 and above") vm_name = params.get("main_vm") vm = env.get_vm(vm_name) diff --git a/libvirt/tests/src/vm_boot_with_kernel_param.py b/libvirt/tests/src/vm_boot_with_kernel_param.py index 1c79775ebf6..1d8fb68c038 100644 --- a/libvirt/tests/src/vm_boot_with_kernel_param.py +++ b/libvirt/tests/src/vm_boot_with_kernel_param.py @@ -53,7 +53,7 @@ def run(test, params, env): cpu_model = cpu.get_cpu_info()['Model name'].upper() if cpu_check not in cpu_model: logging.info("This test will work for %s", cpu_check) - test.skip("Test is not applicable for %s" % cpu_model) + test.cancel("Test is not applicable for %s" % cpu_model) # back up vmxml for vm_name in vms: vm_dict[vm_name] = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) @@ -78,7 +78,7 @@ def run(test, params, env): test.error("couldn't get cpu information from guest " "%s" % vm.name) if cpu_check not in output.upper() and "radix" in boot_log: - test.skip("radix MMU not supported in %s" % output) + test.cancel("radix MMU not supported in %s" % output) status, output = session.cmd_status_output("dmesg") if status: logging.error(output) From 7382b768b8fc3e7bdcbf06f12a4f9227338ecc74 Mon Sep 17 00:00:00 2001 From: nanli Date: Thu, 28 Nov 2024 12:23:31 +0800 Subject: [PATCH 0712/1055] fix maxvcpu num due to qemu update need change expected num Signed-off-by: nanli --- libvirt/tests/cfg/cpu/max_vcpus.cfg | 1 + libvirt/tests/src/cpu/max_vcpus.py | 24 +++++++++++------------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/libvirt/tests/cfg/cpu/max_vcpus.cfg b/libvirt/tests/cfg/cpu/max_vcpus.cfg index f2bca771803..dbea3e023e3 100644 --- a/libvirt/tests/cfg/cpu/max_vcpus.cfg +++ b/libvirt/tests/cfg/cpu/max_vcpus.cfg @@ -14,6 +14,7 @@ report_num_q35_7_8 = "384" report_num_q35_8_3 = "512" report_num_q35_8_4 = "710" + report_num_q35_9_6 = "4096" - positive_test: status_error = "no" variants: diff --git a/libvirt/tests/src/cpu/max_vcpus.py b/libvirt/tests/src/cpu/max_vcpus.py index 339bac3f2eb..6debbdb6cd6 100644 --- a/libvirt/tests/src/cpu/max_vcpus.py +++ b/libvirt/tests/src/cpu/max_vcpus.py @@ -88,6 +88,7 @@ def set_iommu(vmxml, **dargs): report_num_q35_7_8 = params.get('report_num_q35_7_8', '') report_num_q35_8_3 = params.get('report_num_q35_8_3', '') report_num_q35_8_4 = params.get('report_num_q35_8_4', '') + report_num_q35_9_6 = params.get('report_num_q35_9_6', '') logging.info('Check the output of virsh capabilities') xmltreefile = capability_xml.CapabilityXML().xmltreefile machtype_vcpunum_dict = {} @@ -108,25 +109,22 @@ def set_iommu(vmxml, **dargs): .format(report_num_pc_7, machtype_vcpunum_dict[key])) if key.startswith('pc-q35') or key == 'q35': + exp_val = report_num_q35_7_8 if key == "pc-q35-rhel7.3.0": - if machtype_vcpunum_dict[key] != report_num_q35_73: - test.fail('Test failed as q35_rhel73_max_vcpus_num ' - 'in virsh_capa is wrong. Expected: {} ' - 'Actual: {}.' - .format(report_num_q35_73, - machtype_vcpunum_dict[key])) + exp_val = report_num_q35_73 + elif key == "pc-q35-rhel9.6.0" or key == 'q35': + exp_val = report_num_q35_9_6 else: - exp_val = report_num_q35_7_8 if libvirt_version.version_compare(7, 0, 0): exp_val = report_num_q35_8_4 elif libvirt_version.version_compare(6, 6, 0): exp_val = report_num_q35_8_3 - if machtype_vcpunum_dict[key] != exp_val: - test.fail('Test failed as the q35_max_vcpus_num in ' - 'virsh_capa is wrong. Expected: {} ' - 'Actual: {}.' - .format(exp_val, - machtype_vcpunum_dict[key])) + if machtype_vcpunum_dict[key] != exp_val: + test.fail('Test failed as the q35_max_vcpus_num for' + ' machine type:{} in virsh_capa is wrong.' + ' Expected: {}, Actual: {}.' + .format(key, exp_val, + machtype_vcpunum_dict[key])) # Test i440fx VM starts with 240(positive)/241(negative) vcpus and hot-plugs vcpus to 240 if check.startswith('i440fx_test'): From c0b2055253d811bf9629a63eeaf11230a0aebdaf Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Fri, 6 Sep 2024 17:09:07 +0800 Subject: [PATCH 0713/1055] virtio_page_per_vq: enhance input event file Regarding /dev/input/event* files, there might be some different situation. For example, - No event file exsit at all - Only /dev/input/event0 exists - Only /dev/input/event1 exists - Both /dev/input/event0 and /dev/input/event1 exists - and more ... So this patch is intending to support above situations instead of hardcoding with event1. Signed-off-by: Dan Zheng --- .../tests/cfg/virtio/virtio_page_per_vq.cfg | 2 +- .../tests/src/virtio/virtio_page_per_vq.py | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtio/virtio_page_per_vq.cfg b/libvirt/tests/cfg/virtio/virtio_page_per_vq.cfg index d754301cce7..eee6c38c750 100644 --- a/libvirt/tests/cfg/virtio/virtio_page_per_vq.cfg +++ b/libvirt/tests/cfg/virtio/virtio_page_per_vq.cfg @@ -41,7 +41,7 @@ - mouse: - tablet: - passthrough: - device_dict = {**${device_dict}, 'source_evdev': '/dev/input/event0'} + device_dict = {**${device_dict}, 'source_evdev': '%s'} - video: only default_start device_dict = {'model_type': 'virtio', **${driver_dict}, 'model_heads': '1'} diff --git a/libvirt/tests/src/virtio/virtio_page_per_vq.py b/libvirt/tests/src/virtio/virtio_page_per_vq.py index c3b8855ffcd..ac0f8d407f6 100644 --- a/libvirt/tests/src/virtio/virtio_page_per_vq.py +++ b/libvirt/tests/src/virtio/virtio_page_per_vq.py @@ -1,6 +1,8 @@ import os import platform +from avocado.utils import process + from virttest import libvirt_version from virttest import utils_net from virttest import virsh @@ -17,6 +19,24 @@ from virttest.utils_test import libvirt +def get_input_event_file(test): + """ + Get the input event file on the host + + :return: str, the last file path if exists, otherwise skip the test + """ + ret = process.run("ls /dev/input/event*", + shell=True, + verbose=True, + ignore_status=True) + if ret.exit_status != 0: + if ret.stderr_text.count("No such file or directory"): + test.cancel(ret.stderr_text) + else: + test.fail(ret.stderr_text) + return ret.stdout_text.splitlines()[-1] + + def run(test, params, env): """ Start guest with virtio page_per_vq attribute - various virtio devices @@ -56,6 +76,8 @@ def prepare_test(vmxml): device_dict['source']['attrs']['file'] = disk_image_path if device_type == "input": device_xml = eval(device_obj)(input_type) + if input_type == "passthrough": + device_dict['source_evdev'] = get_input_event_file(test) else: device_xml = eval(device_obj)() device_xml.setup_attrs(**device_dict) From 3aa5cc8f7902d7764c044d8dff186439ec6362f6 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 3 Dec 2024 11:10:50 -0500 Subject: [PATCH 0714/1055] migrate_options_shared: stabilize auto-converge The auto-converge test scenarios are brittle. In order to cause auto-converge to kick in we need to reduce allowed downtime and bandwidth and increase creation of dirty-pages. However, by setting unrealisticly restrictive values we might cause the migration to never converge. Therefore, once auto-converge has kicked in, reset bandwidth and maxdowntime so that the migration can finish more easily. Only help the migration speed up if the auto-converge throttle value has increased once. Furthermore, remove function `run_stress_in_vm` as it's not used anywhere. Instead avocado-vt/virttest/migration/run_stress_in_vm is used. Signed-off-by: Sebastian Mitterle --- .../src/migration/migrate_options_shared.py | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/libvirt/tests/src/migration/migrate_options_shared.py b/libvirt/tests/src/migration/migrate_options_shared.py index b5ebdd52941..02202456c12 100644 --- a/libvirt/tests/src/migration/migrate_options_shared.py +++ b/libvirt/tests/src/migration/migrate_options_shared.py @@ -181,18 +181,6 @@ def cleanup_libvirtd_log(log_file): logging.debug("Delete remote libvirt log file '%s'", log_file) remote.run_remote_cmd(cmd, cmd_parms, runner_on_target) - def run_stress_in_vm(): - """ - The function to load stress in VM - """ - stress_args = params.get("stress_args", "--cpu 8 --io 4 " - "--vm 2 --vm-bytes 128M " - "--timeout 20s") - try: - vm_session.cmd('stress %s' % stress_args) - except Exception as detail: - logging.debug(detail) - def control_migrate_speed(to_speed=1, opts=""): """ Control migration duration @@ -742,6 +730,23 @@ def check_timeout_postcopy(params): "be 'running', but '%s' found" % (timeout, vm_state)) remote_virsh_session.close_session() + def help_migration_converge(): + """ + This function will allow for more downtime and bandwidth + in order to help the migration converge. + + This is useful in cases like auto-converge check where we + usually lower these values a lot so we can cause the + auto-converge feature to kick in. + """ + one_second = 1000 + virsh.migrate_setmaxdowntime(vm_name, one_second, **virsh_args) + maxspeed = 8796093022207 + opts = "" + if postcopy_options: + opts = postcopy_options + virsh.migrate_setspeed(vm_name, maxspeed, extra=opts, **virsh_args) + def check_converge(params): """ Handle option '--auto-converge --auto-converge-initial @@ -765,6 +770,7 @@ def check_converge(params): "is %s", allow_throttle_list) throttle = 0 + old_throttle = 0 jobtype = "None" while throttle < 100: @@ -788,8 +794,12 @@ def check_converge(params): if key.count("Job type"): jobtype = line.split(':')[-1].strip() elif key.count("Auto converge throttle"): + if throttle > 0: + old_throttle = throttle throttle = int(line.split(':')[-1].strip()) logging.debug("Auto converge throttle:%s", str(throttle)) + if old_throttle > 0 and throttle > old_throttle: + help_migration_converge() if throttle and throttle not in allow_throttle_list: test.fail("Invalid auto converge throttle " "value '%s'" % throttle) @@ -797,6 +807,7 @@ def check_converge(params): logging.debug("'Auto converge throttle' reaches maximum " "allowed value 99") break + if jobtype == "None" or jobtype == "Completed": logging.debug("Jobtype:%s", jobtype) if not throttle: From b6c8db2efff56a47e1cd3ee8e7f5928c2f1713b3 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Tue, 3 Dec 2024 23:52:15 -0500 Subject: [PATCH 0715/1055] Fix failures for some v2v fun esx cases Signed-off-by: Ming Xie --- v2v/tests/cfg/function_test_esx.cfg | 15 ++++++++------- v2v/tests/cfg/nbdkit/nbdkit.cfg | 8 ++++---- v2v/tests/src/nbdkit/nbdkit.py | 23 +++++++++++++---------- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 3bc6e5c206c..27c03ee5b4c 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -175,10 +175,10 @@ - iso_file: checkpoint += 'iso_file' - virtio_iso_blk: - only esx_70 + only esx_80 checkpoint = "virtio_iso_blk" virtio_win_path = '/usr/share/virtio-win/virtio-win.iso' - main_vm = VM_NAME_WIN2019_V2V_EXAMPLE + main_vm = VM_NAME_ESX80_WIN2019_V2V_EXAMPLE os_version = "win2019" - mac_ip: only libvirt @@ -262,9 +262,9 @@ os_version = "win2019" boottype = 3 - rhsrvany_md5: - only esx_70 + only esx_80 checkpoint = 'rhsrvany_checksum' - main_vm = VM_NAME_WIN2019_V2V_EXAMPLE + main_vm = VM_NAME_ESX80_WIN2019_V2V_EXAMPLE os_version = 'win2019' - external_poweroff: only esx_70 @@ -478,8 +478,8 @@ skip_vm_check = yes skip_reason = 'bz#1990808' - resume_rhel7: - only esx_70 - only rhev + only esx_80 + only dest_libvirt os_version = OS_VERSION_RESUME_RHEL7_V2V_EXAMPLE checkpoint = resume_swap main_vm = VM_NAME_RESUME_RHEL7_V2V_EXAMPLE @@ -885,7 +885,8 @@ version_required = "[nbdkit-1.30.8-1,)" main_vm = VM_NAME_ESX70_RHEL8_V2V_EXAMPLE vddk_thumbprint = 'AA:2B:AD' - msg_content_yes = "error: Please verify whether the "thumbprint" parameter" + #bug RHEL-55742 was closed as NOTABUG + msg_content_yes = "server reported: VDDK "Unknown error" can be caused by several problems" - non_admin_user: only esx_80 main_vm = VM_NAME_NON_ADMIN_V2V_EXAMPLE diff --git a/v2v/tests/cfg/nbdkit/nbdkit.cfg b/v2v/tests/cfg/nbdkit/nbdkit.cfg index b0808b58181..1e13f0f0cc1 100644 --- a/v2v/tests/cfg/nbdkit/nbdkit.cfg +++ b/v2v/tests/cfg/nbdkit/nbdkit.cfg @@ -140,9 +140,9 @@ - vddk7_0: only source_esx.esx_70..dest_none version_required = "[nbdkit-server-1.20.4-2,)" - checkpoint = 'has_run_againt_vddk7_0' + checkpoint = 'has_run_againt_vddk' vpx_passwd_file = "/tmp/v2v_vpx_passwd" - main_vm = VM_NAME_ESX_NBDKIT_V2V_EXAMPLE + main_vm = VM_NAME_ESX70_NBDKIT_V2V_EXAMPLE variants: - vpx: vsphere_host = ${vpx_hostname} @@ -173,9 +173,9 @@ - vddk8_0: only source_esx.esx_80..dest_none version_required = "[nbdkit-server-1.38.0-1,)" - checkpoint = 'has_run_againt_vddk7_0' + checkpoint = 'has_run_againt_vddk' vpx_passwd_file = "/tmp/v2v_vpx_passwd" - main_vm = VM_NAME_ESX_NBDKIT_V2V_EXAMPLE + main_vm = VM_NAME_ESX80_NBDKIT_V2V_EXAMPLE variants: - vpx: vsphere_host = ${vpx_hostname} diff --git a/v2v/tests/src/nbdkit/nbdkit.py b/v2v/tests/src/nbdkit/nbdkit.py index d533cc9662f..26c326c7508 100644 --- a/v2v/tests/src/nbdkit/nbdkit.py +++ b/v2v/tests/src/nbdkit/nbdkit.py @@ -54,7 +54,7 @@ def test_filter_stats_fd_leak(): if count > 0: test.fail('nbdkit-stats-filter leaks %d fd' % count) - def test_has_run_againt_vddk7_0(): + def test_has_run_againt_vddk(): """ check if nbdkit --run + vddk + esx7.0 works. """ @@ -89,12 +89,15 @@ def test_has_run_againt_vddk7_0(): vddk_libdir_src = params_get(params, "vddk_libdir_src") with tempfile.TemporaryDirectory(prefix='vddklib_') as vddk_libdir: utils_misc.mount(vddk_libdir_src, vddk_libdir, 'nfs') + process.run('mkdir /home/vddk_libdir;cp -R %s/* %s' % (vddk_libdir, '/home/vddk_libdir'), + shell=True, ignore_status=True) + utils_misc.umount(vddk_libdir_src, vddk_libdir, 'nfs') vddk_thumbprint = '11' nbdkit_cmd = """ nbdkit -rfv -U - --exportname / \ --filter=cacheextents --filter=retry vddk server=%s user=%s password=+%s vm=%s \ - file='%s' libdir=%s --run 'nbdinfo $uri' thumbprint=%s -""" % (vsphere_host, vsphere_user, vsphere_passwd_file, nbdkit_vm_name, nbdkit_file, vddk_libdir, vddk_thumbprint) + file='%s' libdir=/home/vddk_libdir --run 'nbdinfo $uri' thumbprint=%s +""" % (vsphere_host, vsphere_user, vsphere_passwd_file, nbdkit_vm_name, nbdkit_file, vddk_thumbprint) # get thumbprint by a trick cmd_result = process.run( nbdkit_cmd, shell=True, ignore_status=True) @@ -119,11 +122,10 @@ def test_has_run_againt_vddk7_0(): ' scan-ahead=true scan-clock=true scan-size=2048 scan-forever=true' LOG.info('nbdkit command with scan, readahead and blocksize filters:\n%s' % nbdkit_cmd) if checkpoint == 'vddk_with_delay_close_open_option': - nbdkit_cmd = nbdkit_cmd + ' --filter=delay delay-close=40000ms delay-open=40000ms' + nbdkit_cmd = nbdkit_cmd + ' --filter=delay delay-close=400ms delay-open=400ms' LOG.info('nbdkit command with delay-close and delay-open options:\n%s' % nbdkit_cmd) # Run the final nbdkit command output = process.run(nbdkit_cmd, shell=True).stdout_text - utils_misc.umount(vddk_libdir_src, vddk_libdir, 'nfs') if checkpoint == 'vddk_stats': if vddk_stats == 1 and not re.search( r'VDDK function stats', output): @@ -131,9 +133,9 @@ def test_has_run_againt_vddk7_0(): if vddk_stats == 0 and re.search( r'VDDK function stats', output): test.fail('failed to test vddk_stats') - if checkpoint == 'has_run_againt_vddk7_0' and not re.search( + if checkpoint == 'has_run_againt_vddk' and not re.search( r'export-size', output): - test.fail('failed to test has_run_againt_vddk7_0') + test.fail('failed to test has_run_againt_vddk') if checkpoint == 'backend_datapath_controlpath' and re.search(r'vddk: (open|pread)', output): test.fail('fail to test nbdkit.backend.datapath and nbdkit.backend.controlpath option') if checkpoint == 'scan_readahead_blocksize' and re.search('error', output): @@ -561,7 +563,7 @@ def cache_min_block_size(): def cve_starttls(): tmp_path = data_dir.get_tmp_dir() - process.run("yum install libtool 'dnf-command(download)' -y", shell=True, ignore_status=True) + process.run("yum install libtool rpm-build 'dnf-command(download)' -y", shell=True, ignore_status=True) process.run('yum download --source nbdkit --destdir=%s' % tmp_path, shell=True, ignore_status=True) process.run('cd %s ; rpmbuild -rp %s' % (tmp_path, (process.run('ls %s/nbdkit*.src.rpm' % tmp_path, shell=True). @@ -665,6 +667,7 @@ def test_evil_filter(): test.fail('fail to test evil filter') def test_tar_filter(): + process.run('yum install nbdkit-tar-filter -y', shell=True, ignore_status=True) tmp_path = data_dir.get_tmp_dir() image_path = os.path.join(tmp_path, 'latest-rhel9.img') process.run('qemu-img convert -f qcow2 -O raw /var/lib/avocado/data/avocado-vt/images/jeos-27-x86_64.qcow2' @@ -695,9 +698,9 @@ def check_curl_time_option(): if checkpoint == 'filter_stats_fd_leak': test_filter_stats_fd_leak() - elif checkpoint in ['has_run_againt_vddk7_0', 'vddk_stats', 'backend_datapath_controlpath', + elif checkpoint in ['has_run_againt_vddk', 'vddk_stats', 'backend_datapath_controlpath', 'scan_readahead_blocksize', 'vddk_with_delay_close_open_option']: - test_has_run_againt_vddk7_0() + test_has_run_againt_vddk() elif checkpoint == 'memory_max_disk_size': test_memory_max_disk_size() elif checkpoint == 'data_corruption': From 9a4fac2cd2e9409cf8a31cc3fb9ce667b14cd14f Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Thu, 5 Dec 2024 17:55:37 +0800 Subject: [PATCH 0716/1055] v2v: fix ntpd related tcs Signed-off-by: vwu-vera --- v2v/tests/src/specific_kvm.py | 1 + 1 file changed, 1 insertion(+) diff --git a/v2v/tests/src/specific_kvm.py b/v2v/tests/src/specific_kvm.py index 2021eb70641..4e367b7ad2f 100644 --- a/v2v/tests/src/specific_kvm.py +++ b/v2v/tests/src/specific_kvm.py @@ -835,6 +835,7 @@ def check_result(result, status_error): LOG.info('Set service chronyd on') cmd = ['yum -y install chrony', 'systemctl start chronyd', + 'systemctl enable chronyd', 'chronyc add server %s' % ntp_server] vm_cmd(cmd) if checkpoint == 'sync_ntp': From 3ea36b36a722e8c8eb877e50af12dd859c78fc8c Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Thu, 5 Dec 2024 06:37:39 -0500 Subject: [PATCH 0717/1055] migrate_vm: fix cpu list on s390x On s390x the /proc/cpuinfo output looks different from the one on x86_64. This could apply to other archs, too. So, if the first regex doesn't match, try the other one. Output on x86_64 F40 6.11 kernel: ``` grep processor /proc/cpuinfo processor : 0 processor : 1 processor : 2 processor : 3 processor : 4 ... ``` Output on s390x RHEL 9 kernel 5.14: ``` processor 0: version = FF, identification = 2EB428, machine = 8561 processor 1: version = FF, identification = 2EB428, machine = 8561 processor 2: version = FF, identification = 2EB428, machine = 8561 processor 3: version = FF, identification = 2EB428, machine = 8561 ``` Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/migration/migrate_vm.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/src/migration/migrate_vm.py b/libvirt/tests/src/migration/migrate_vm.py index 29e0fc8743c..0671b68a49f 100644 --- a/libvirt/tests/src/migration/migrate_vm.py +++ b/libvirt/tests/src/migration/migrate_vm.py @@ -507,6 +507,8 @@ def get_same_processor(test, server_ip, server_user, server_pwd, verbose): if status: test.fail("Failed to run '%s' on the remote: %s" % (cmd, output)) remote_processors = re.findall(r'processor\s+: (\d+)', output) + if not remote_processors: + remote_processors = re.findall(r'processor\s+(\d+):', output) if verbose: logging.debug("Local processors: %s", local_processors) logging.debug("Remote processors: %s", remote_processors) From d49f868b7eacf9612c85402948340890ff7299e3 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 5 Dec 2024 22:23:43 -0500 Subject: [PATCH 0718/1055] unsupported_live_update:Remove interface backend settings before setting new value Since the original dict value won't be deleted automatically, but we want to remove one attribute. And don't remove interfaces on vmxml before test setting. And remove 2 test cases that are no need to test (bug won't do) Signed-off-by: Haijiao Zhao --- .../update_device/unsupported_live_update_alter.cfg | 1 + .../update_device/unsupported_live_update_delete.cfg | 8 -------- .../update_device/unsupported_live_update.py | 4 +++- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_alter.cfg b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_alter.cfg index e8956d8f4f9..b46a0c3b44d 100644 --- a/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_alter.cfg +++ b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_alter.cfg @@ -36,6 +36,7 @@ err_msg = cannot modify network device model from .* to .* - backend: extra_attrs = {'backend': {'tap': '/dev/net/tun', 'vhost': '/dev/vhost-net'}} + tmp_attrs = {'backend': None} update_attrs = {'backend': {'tap': '/dev/net/tun'}} err_msg = cannot modify network device backend settings - driver: diff --git a/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg index 07bd0d29031..faa80241ca6 100644 --- a/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg +++ b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg @@ -27,10 +27,6 @@ extra_attrs = {'rom': {'enabled': 'no'}} del_attr = rom err_msg = cannot modify network device rom enabled setting - - target_dev: - extra_attrs = {'target': {'dev': 'test'}} - del_attr = target - err_msg = cannot modify network device tap name - model_type: del_attr = model err_msg = cannot modify network device model from .* to .* @@ -41,10 +37,6 @@ - driver: del_attr = driver err_msg = cannot modify virtio network device driver attributes - - alias_name: - extra_attrs = {'alias': {'name': 'ua-47034d36-5483-411c-86f8-7989d08d762b'}} - del_attr = alias - err_msg = device not found: no device found at address .* matching MAC address .* and alias .* - mac: del_attr = mac_address err_msg = "cannot change network interface mac address|device not found" diff --git a/libvirt/tests/src/virtual_network/update_device/unsupported_live_update.py b/libvirt/tests/src/virtual_network/update_device/unsupported_live_update.py index e981f635ae4..1211a3fb75f 100644 --- a/libvirt/tests/src/virtual_network/update_device/unsupported_live_update.py +++ b/libvirt/tests/src/virtual_network/update_device/unsupported_live_update.py @@ -29,6 +29,7 @@ def run(test, params, env): iface_attrs = {**base_iface_attrs, **extra_attrs} update_attrs = eval(params.get('update_attrs', '{}')) + tmp_attrs = eval(params.get('tmp_attrs', '{}')) del_attr = params.get('del_attr') vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) @@ -41,7 +42,6 @@ def run(test, params, env): vmxml.os = osxml libvirt_vmxml.modify_vm_device(vmxml, 'disk', {'boot': '1'}) - vmxml.del_device('interface', by_tag=True) libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs) LOG.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') @@ -56,6 +56,8 @@ def run(test, params, env): else: eval(f'iface.del_{del_attr}')() else: + if tmp_attrs: + iface.setup_attrs(**tmp_attrs) iface.setup_attrs(**update_attrs) LOG.debug(f'Interface xml to update with:\n{iface}') From 2ba2bff7bf23dc8d6a8702546d35fc417ca35250 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Fri, 6 Dec 2024 02:36:36 -0500 Subject: [PATCH 0719/1055] rx_tx_queue_size:Skip getting tx size from interface xml Cannot get tx size from interface xml when it's not set Signed-off-by: Haijiao Zhao --- libvirt/tests/cfg/virtual_network/driver/rx_tx_queue_size.cfg | 1 + libvirt/tests/src/virtual_network/driver/rx_tx_queue_size.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_network/driver/rx_tx_queue_size.cfg b/libvirt/tests/cfg/virtual_network/driver/rx_tx_queue_size.cfg index d3d7a974a0d..c2b5e17be15 100644 --- a/libvirt/tests/cfg/virtual_network/driver/rx_tx_queue_size.cfg +++ b/libvirt/tests/cfg/virtual_network/driver/rx_tx_queue_size.cfg @@ -13,6 +13,7 @@ rx_tx_attrs = {'rx_queue_size': '512', 'tx_queue_size': '256'} - rx_1024_tx_unset: rx_tx_attrs = {'rx_queue_size': '1024'} + actual_tx = 256 - negative: status_error = yes variants: diff --git a/libvirt/tests/src/virtual_network/driver/rx_tx_queue_size.py b/libvirt/tests/src/virtual_network/driver/rx_tx_queue_size.py index 21b70b98845..7285900c487 100644 --- a/libvirt/tests/src/virtual_network/driver/rx_tx_queue_size.py +++ b/libvirt/tests/src/virtual_network/driver/rx_tx_queue_size.py @@ -53,7 +53,7 @@ def run(test, params, env): iface = network_base.get_iface_xml_inst(vm_name, 'after vm start') actual_rx = int(iface.driver.driver_attr.get('rx_queue_size')) - actual_tx = int(iface.driver.driver_attr.get('tx_queue_size')) + actual_tx = int(params.get('actual_tx') or iface.driver.driver_attr.get('tx_queue_size')) LOG.debug( f'Actual rx_queue_size={actual_rx} tx_queue_size={actual_tx}') if str(actual_rx) != iface_attrs['driver']['driver_attr']['rx_queue_size']: From 7f37c792b91abecaa794183adb7da7c6999220d4 Mon Sep 17 00:00:00 2001 From: zhenyzha Date: Fri, 6 Dec 2024 18:13:13 +0800 Subject: [PATCH 0720/1055] virsh_memtune: Expanding memtune values on ARM platforms Expanding memtune values on ARM platforms Signed-off-by: zhenyzha --- libvirt/tests/cfg/virsh_cmd/domain/virsh_memtune.cfg | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_memtune.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_memtune.cfg index f462eaa9734..df4739d6828 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_memtune.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_memtune.cfg @@ -23,6 +23,10 @@ mt_hard_limit = 1111111 mt_soft_limit = 222222 mt_swap_hard_limit = 3333333 + aarch64: + mt_hard_limit = 4194304 + mt_soft_limit = 8388608 + mt_swap_hard_limit = 12582912 - step_increment: mt_step_mem = "yes" mt_base_mem = 1048576 From f660c59feaa2c558ac01b814bdfcab06fd189c6e Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Fri, 6 Dec 2024 06:11:31 -0500 Subject: [PATCH 0721/1055] check_user_interface: fix color code in ip command ip command might print color codes causing comparison to fail. Use new json option to avoid. Signed-off-by: Sebastian Mitterle --- .../connectivity/connectivity_check_user_interface.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py index 46589a89eb2..331abb81731 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py @@ -77,7 +77,7 @@ def run(test, params, env): outside_ip = params.get('outside_ip') host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True).split()[0] ipv4_addr = params.get('ipv4_addr') ipv4_prefix = params.get('ipv4_prefix') @@ -123,7 +123,7 @@ def run(test, params, env): check_val(ipv6_prefix, str(vm_ipv6_pfx), 'vm ipv6 prefix', test) default_gw_v4 = utils_net.get_default_gateway( - session=session, ip_ver='ipv4', force_dhcp=True) + session=session, ip_ver='ipv4', force_dhcp=True, json=True) LOG.debug(f'vm default gateway ipv4: {default_gw_v4}') check_val(ipv4_default_gw, default_gw_v4, 'default ipv4 gateway', test) vm_nameserver = utils_net.get_guest_nameserver(session) From e6f88692fff11a0d55ee1ad2e8b2eec2c1f2b646 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Sat, 7 Dec 2024 02:37:32 -0500 Subject: [PATCH 0722/1055] Fix failures for some nbdkit cases Signed-off-by: Ming Xie --- v2v/tests/src/nbdkit/nbdkit.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/v2v/tests/src/nbdkit/nbdkit.py b/v2v/tests/src/nbdkit/nbdkit.py index 26c326c7508..fa95c94e925 100644 --- a/v2v/tests/src/nbdkit/nbdkit.py +++ b/v2v/tests/src/nbdkit/nbdkit.py @@ -27,6 +27,7 @@ def test_filter_stats_fd_leak(): """ check if nbdkit-stats-filter leaks an fd """ + process.run('yum install nbdkit-stats-filter -y', shell=True, ignore_status=True) tmp_logfile = os.path.join(data_dir.get_tmp_dir(), "nbdkit-test.log") cmd = """ nbdkit -U - --filter=log --filter=stats sh - \ @@ -212,7 +213,7 @@ def get_size(h): def pread(h, count, offset): raise RuntimeError("pread") """ - + process.run('yum install nbdkit-python-plugin -y', shell=True, ignore_status=True) python_file_path = os.path.join(data_dir.get_tmp_dir(), "python_check.py") with open(python_file_path, "w") as f: f.write(lines) @@ -379,6 +380,7 @@ def annocheck_test_nbdkit(): test.fail('fail to test ndbkit-server rpm package with annocheck tool') def statsfile_option(): + process.run('yum install nbdkit-stats-filter -y', shell=True, ignore_status=True) tmp_path = data_dir.get_tmp_dir() process.run('nbdkit --filter=exitlast --filter=stats memory 2G statsfile=%s/example.txt' % tmp_path, shell=True, ignore_status=True) @@ -461,7 +463,7 @@ def delay_close_delay_open_options(): for value in values: cmd_num = process.run("nbdkit null --filter=delay delay-open=%s --run 'nbdinfo $uri'" % value, shell=True, ignore_status=True) - if not re.search('could not parse number', cmd_num.stderr_text): + if not re.search('could not parse', cmd_num.stderr_text): test.fail('get unexpected result when set invalid value for nbdkit delay options)') #Check error when nbdkit aborts early cmd_aborts = process.run("nbdkit --filter=delay null delay-close=3 --run 'nbdinfo --size $uri; " From 353bf506705e4bd78de3d4d74e1fbbe5fb08f507 Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 9 Dec 2024 23:34:38 +0800 Subject: [PATCH 0723/1055] migration: Add test about qemu fails with incoming migration XXX-298341 - [VM migration] qemu fails with incoming migration Signed-off-by: lcheng --- .../qemu_err_incoming_migration.cfg | 36 ++++++++++ .../qemu_err_incoming_migration.py | 68 +++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 libvirt/tests/cfg/migration/migration_misc/qemu_err_incoming_migration.cfg create mode 100644 libvirt/tests/src/migration/migration_misc/qemu_err_incoming_migration.py diff --git a/libvirt/tests/cfg/migration/migration_misc/qemu_err_incoming_migration.cfg b/libvirt/tests/cfg/migration/migration_misc/qemu_err_incoming_migration.cfg new file mode 100644 index 00000000000..fb3b2fb9b67 --- /dev/null +++ b/libvirt/tests/cfg/migration/migration_misc/qemu_err_incoming_migration.cfg @@ -0,0 +1,36 @@ +- migration.migration_misc.qemu_err_incoming_migration: + type = qemu_err_incoming_migration + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + status_error = "yes" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + err_msg = "unable to map backing store for guest RAM: Cannot allocate memory" + setup_hugepages = "yes" + start_vm = "no" + nr_hugepages_src = "2500" + nr_hugepages_dest = "0" + memory_backing = {'hugepages': {'pages': [{'size': '2048', 'unit': 'KiB'}]}} + variants: + - p2p: + virsh_migrate_options = '--live --p2p --verbose' + - non_p2p: + virsh_migrate_options = '--live --verbose' diff --git a/libvirt/tests/src/migration/migration_misc/qemu_err_incoming_migration.py b/libvirt/tests/src/migration/migration_misc/qemu_err_incoming_migration.py new file mode 100644 index 00000000000..ec935c3b969 --- /dev/null +++ b/libvirt/tests/src/migration/migration_misc/qemu_err_incoming_migration.py @@ -0,0 +1,68 @@ +from avocado.utils import process + +from virttest import remote + +from virttest.libvirt_xml import vm_xml + +from provider.migration import base_steps + +hugepage_num = None + + +def run(test, params, env): + """ + This case is to verify that libvirt can report reasonable error when QEMU + fails with incoming migration. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def setup_test(): + """ + Setup steps + + """ + memory_backing = eval(params.get("memory_backing", "{}")) + hugepage_file = params.get("kernel_hp_file", "/proc/sys/vm/nr_hugepages") + nr_hugepages_src = params.get("nr_hugepages_src") + nr_hugepages_dest = params.get("nr_hugepages_dest") + + test.log.info("Setup steps for cases.") + migration_obj.setup_connection() + global hugepage_num + with open(hugepage_file, 'r') as fp: + hugepage_num = int(fp.readline().strip()) + + process.run(f"sysctl vm.nr_hugepages={nr_hugepages_src}", shell=True) + remote.run_remote_cmd(f"sysctl vm.nr_hugepages={nr_hugepages_dest}", params) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + mem_backing = vm_xml.VMMemBackingXML() + mem_backing.setup_attrs(**memory_backing) + vmxml.mb = mem_backing + vmxml.sync() + vm.start() + vm.wait_for_login().close() + + def cleanup_test(): + """ + Cleanup steps for cases + + """ + test.log.info("Cleanup steps for cases.") + global hugepage_num + process.run(f"sysctl vm.nr_hugepages={hugepage_num}", shell=True) + remote.run_remote_cmd(f"sysctl vm.nr_hugepages={hugepage_num}", params) + migration_obj.cleanup_connection() + + vm_name = params.get("migrate_main_vm") + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + setup_test() + migration_obj.run_migration() + migration_obj.verify_default() + finally: + cleanup_test() From 8c1a3592dcdc2f6d1e5a97a26ed186050eaf3e06 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Wed, 26 Jun 2024 06:34:56 -0400 Subject: [PATCH 0724/1055] Change guest cpu topology checking methods Signed-off-by: liang-cong-red-hat --- .../numa_topology_with_cpu_topology.py | 36 ++++++------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_cpu_topology.py b/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_cpu_topology.py index 5881dcc4578..e596c28b110 100644 --- a/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_cpu_topology.py +++ b/libvirt/tests/src/numa/guest_numa_topology/numa_topology_with_cpu_topology.py @@ -51,30 +51,21 @@ def prepare_vm_xml(test_obj): return vmxml -def verify_vm_cpu_info(vm_session, test_obj, cpu_info_type, cmd): +def verify_vm_cpu_info(test_obj): """ Verify vm's cpu information - :param vm_session: vm session :param test_obj: NumaTest object - :param cpu_info_type: str, specified cpu info type, like 'cores', 'threads' - :param cmd: str, the command used to check the cpu info """ - status, output = vm_session.cmd_status_output(cmd, timeout=300) - if status: - test_obj.test.error("Can't get cpu info with command '%s'" % cmd) - cpu_info = eval(test_obj.params.get('cpu_topology'))[cpu_info_type] - if cpu_info_type == 'cores': - dies = eval(test_obj.params.get('cpu_topology'))['dies'] - cpu_info = str(int(cpu_info) * int(dies)) - if cpu_info != output.strip(): - test_obj.test.fail('Guest cpu %s is expected ' - 'to be %s, but found %s' % (cpu_info_type, - cpu_info, - output.strip())) - else: - test_obj.test.log.debug("Step: check vm cpu %s " - "to be '%s': PASS", cpu_info_type, cpu_info) + vm_topology = test_obj.vm.get_cpu_topology_in_vm() + expect_topology = eval(test_obj.params.get('cpu_topology')) + expect_topology['cores'] = str(int(expect_topology['cores']) * int(expect_topology['dies'])) + for key in expect_topology: + if expect_topology[key] != vm_topology[key]: + test_obj.test.fail('Guest cpu %s is expected ' + 'to be %s, but found %s' % (key, + expect_topology[key], + vm_topology[key])) def verify_vm_numa_node(vm_session, test_obj): @@ -163,12 +154,7 @@ def run_default(test_obj): test_obj.test.log.debug("After vm is started, vm xml:\n" "%s", vm_xml.VMXML.new_from_dumpxml(test_obj.vm.name)) vm_session = test_obj.vm.wait_for_login() - cmds = {'sockets': 'cat /proc/cpuinfo|grep "physical id"|sort -u|wc -l', - 'cores': 'cat /proc/cpuinfo|grep "core id"|sort|uniq|wc -l', - 'dies': 'cat /sys/devices/system/cpu/cpu*/topology/die_id|sort|uniq|wc -l', - 'threads': 'lscpu|grep Thread|cut -d":" -f2'} - for cpu_info_type, cpu_cmd in cmds.items(): - verify_vm_cpu_info(vm_session, test_obj, cpu_info_type, cpu_cmd) + verify_vm_cpu_info(test_obj) verify_vm_numa_node(vm_session, test_obj) verify_dmesg_vm_numa_mem(vm_session, test_obj) From 4838d398707fa405c0088f33c89118583908717e Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Tue, 10 Dec 2024 02:09:43 -0500 Subject: [PATCH 0725/1055] check_actual_network_throughput_direct:Reduce average value Reduce average value to avoid test failure Signed-off-by: Haijiao Zhao --- .../qos/check_actual_network_throughput_direct.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput_direct.cfg b/libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput_direct.cfg index ef704d5599f..6c75ae87695 100644 --- a/libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput_direct.cfg +++ b/libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput_direct.cfg @@ -5,8 +5,8 @@ vms = avocado-vt-vm1 vm2 timeout = 240 host_iface = - inbound = {'average': '128', 'peak': '1024', 'burst': '32'} - outbound = {'average': '128', 'peak': '1024', 'burst': '32'} + inbound = {'average': '64', 'peak': '1024', 'burst': '32'} + outbound = {'average': '64', 'peak': '1024', 'burst': '32'} iface_bw_attrs = {'bandwidth': {'inbound': ${inbound}, 'outbound': ${outbound}}} variants: - with_network: From fb04c809a980090bcfd3a333afa5afa1f1bbdb26 Mon Sep 17 00:00:00 2001 From: hholoubk Date: Tue, 10 Dec 2024 10:24:56 +0100 Subject: [PATCH 0726/1055] Resolve No migration result issue on aarch64 caused by low migration speed --- .../abort_precopy_migration/abort_by_domjobabort_on_target.cfg | 2 ++ libvirt/tests/cfg/migration/migration_uri/migration_desturi.cfg | 2 ++ 2 files changed, 4 insertions(+) diff --git a/libvirt/tests/cfg/migration/abort_precopy_migration/abort_by_domjobabort_on_target.cfg b/libvirt/tests/cfg/migration/abort_precopy_migration/abort_by_domjobabort_on_target.cfg index e09cd62ce45..fb3b4f5660d 100644 --- a/libvirt/tests/cfg/migration/abort_precopy_migration/abort_by_domjobabort_on_target.cfg +++ b/libvirt/tests/cfg/migration/abort_precopy_migration/abort_by_domjobabort_on_target.cfg @@ -27,6 +27,8 @@ virsh_migrate_dest_state = "running" virsh_migrate_src_state = "shut off" migrate_speed = "10" + aarch64: + migrate_speed = "15" stress_package = "stress" stress_args = "--cpu 8 --io 4 --vm 2 --vm-bytes 128M --timeout 20s" variants: diff --git a/libvirt/tests/cfg/migration/migration_uri/migration_desturi.cfg b/libvirt/tests/cfg/migration/migration_uri/migration_desturi.cfg index bf10c658750..7b9e70d4a1c 100644 --- a/libvirt/tests/cfg/migration/migration_uri/migration_desturi.cfg +++ b/libvirt/tests/cfg/migration/migration_uri/migration_desturi.cfg @@ -24,6 +24,8 @@ status_error = "no" check_network_accessibility_after_mig = "yes" migrate_speed = "5" + aarch64: + migrate_speed = "15" action_during_mig = '[{"func": "libvirt_network.check_established", "after_event": "iteration: \'1\'", "func_param": "params"}]' check_local_port = "yes" test_case = "desturi" From 7765ff73d366bd85dfa13c6f8862d1e72f8ff3ff Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 10 Dec 2024 18:38:23 +0800 Subject: [PATCH 0727/1055] migration: Add non-live migration case XXX-298167 - [VM migration] non-live migration Signed-off-by: lcheng --- .../non_live_migration/non_live_migration.cfg | 40 +++++++++++++++++++ .../non_live_migration/non_live_migration.py | 30 ++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 libvirt/tests/cfg/migration/non_live_migration/non_live_migration.cfg create mode 100644 libvirt/tests/src/migration/non_live_migration/non_live_migration.py diff --git a/libvirt/tests/cfg/migration/non_live_migration/non_live_migration.cfg b/libvirt/tests/cfg/migration/non_live_migration/non_live_migration.cfg new file mode 100644 index 00000000000..f4324c651f0 --- /dev/null +++ b/libvirt/tests/cfg/migration/non_live_migration/non_live_migration.cfg @@ -0,0 +1,40 @@ +- migration.non_live_migration: + type = non_live_migration + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + status_error = "no" + start_vm = "yes" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + check_network_accessibility_after_mig = "yes" + variants: + - p2p: + virsh_migrate_options = "--p2p --verbose" + - non_p2p: + virsh_migrate_options = "--verbose" + variants: + - with_precopy: + expected_event_src = ["lifecycle.*Suspended Migrated", "migration-iteration.*iteration"] + - with_postcopy: + postcopy_options = "--postcopy" + status_error = "yes" + err_msg = "post-copy migration is not supported with non-live or paused migration" diff --git a/libvirt/tests/src/migration/non_live_migration/non_live_migration.py b/libvirt/tests/src/migration/non_live_migration/non_live_migration.py new file mode 100644 index 00000000000..d650cbb7aa3 --- /dev/null +++ b/libvirt/tests/src/migration/non_live_migration/non_live_migration.py @@ -0,0 +1,30 @@ +from provider.migration import base_steps +from provider.migration import migration_base + + +def run(test, params, env): + """ + This case is to verify that non-live vm migration can succeed. + "non-live migration" means vm is paused before its memory is migrated. + To start a non-live migration, don't add "--live" in virsh migrate option. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + vm_name = params.get("migrate_main_vm") + + virsh_session = None + remote_virsh_session = None + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + migration_obj.setup_connection() + virsh_session, remote_virsh_session = migration_base.monitor_event(params) + migration_obj.run_migration() + migration_obj.verify_default() + migration_base.check_event_output(params, test, virsh_session, remote_virsh_session) + finally: + migration_obj.cleanup_connection() From d6746ad043538d8be1a6f1f900377ac76c7c0b39 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Tue, 10 Dec 2024 07:02:49 -0500 Subject: [PATCH 0728/1055] Fix managedsave cases about fake managed file Delete one case 'not_saved_with_file' as the bug https://bugzilla.redhat.com/show_bug.cgi?id=1689809 is closed as won't fix, so it's not a valid test scenario. And update one parameter in the file. Signed-off-by: Yalan Zhang --- libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave.cfg | 2 -- libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py | 6 ++++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave.cfg index 7c763143498..8a05992ed08 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave.cfg @@ -80,8 +80,6 @@ - rm_test: remove_test = 'yes' variants: - - not_saved_with_file: - case = 'not_saved_with_file' - not_saved_without_file: case = 'not_saved_without_file' - saved_without_file: diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py index 3ae522e1b69..770d7f64d63 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py @@ -82,7 +82,7 @@ def vm_recover_check(option, libvirtd, check_shutdown=False): " paused after started" " because of '--paused' option") else: - if params.get("paused_after_start_vm") == "yes": + if paused_after_start_vm: if not vm.is_paused(): test.fail("Guest state should be" " paused after started" @@ -337,6 +337,7 @@ def build_vm_xml(vm_name, **dargs): remove_test = 'yes' == params.get('remove_test', 'no') case = params.get('case', '') msave_rm_error = "yes" == params.get("msave_rm_error", "no") + paused_after_start_vm = "yes" == params.get('paused_after_start_vm', "no") if option: if not virsh.has_command_help_match('managedsave', option): # Older libvirt does not have this option @@ -428,7 +429,8 @@ def build_vm_xml(vm_name, **dargs): elif vm_ref == "name": vm_ref = vm_name # Prepare the certain state before managedsave - if params.get('paused_after_start_vm'): + if paused_after_start_vm: + logging.debug("Suspend the VM!") virsh.suspend(vm_ref) # Ignore exception with "ignore_status=True" From ded1ec648063efe67fb4783a815e440003ce7200 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Tue, 10 Dec 2024 23:59:26 -0500 Subject: [PATCH 0729/1055] Extend the time for blockcopy to finish Current blockcopy will timeout in 100s. Extend the time to be 300s which is enough for the operation to finish. Signed-off-by: Yalan Zhang --- .../src/backingchain/blockjob/blockjob_with_raw_option.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/backingchain/blockjob/blockjob_with_raw_option.py b/libvirt/tests/src/backingchain/blockjob/blockjob_with_raw_option.py index ff920fb645c..7a53bd0ddd8 100644 --- a/libvirt/tests/src/backingchain/blockjob/blockjob_with_raw_option.py +++ b/libvirt/tests/src/backingchain/blockjob/blockjob_with_raw_option.py @@ -87,12 +87,12 @@ def _abort_job(): test.log.info("Check if the job can be aborted successfully") if utils_misc.wait_for( lambda: libvirt.check_blockjob(vm_name, - dev, "progress", "100(.00)?"), 100): + dev, "progress", "100(.00)?"), 300): virsh.blockjob(vm_name, dev, options=' --pivot', debug=True, ignore_status=False) else: - test.fail("Blockjob timeout in 100 sec.") + test.fail("Blockjob timeout in 300 sec.") test.log.info("TEST_STEP3: Check the output of 'blockjob --raw' " "after aborting the job") From 599cb4173602b91eeb5571e6fcc71011e9099753 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Wed, 11 Dec 2024 03:40:38 -0500 Subject: [PATCH 0730/1055] virsh_domiftune:Update max boundary test RHEL-65372 has set clear boundary and error message Signed-off-by: Haijiao Zhao --- libvirt/tests/cfg/virsh_cmd/domain/virsh_domiftune.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_domiftune.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_domiftune.cfg index ee51b8f7ed9..af9fcc2bf40 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_domiftune.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_domiftune.cfg @@ -42,7 +42,7 @@ - inside_boundary: inbound = 1024,1024,1024 - maximum_boundary: - inbound = 4294967,4294967,4294967 + inbound = 4194303,4194303,4194303 - with_floor: only none pre_vmstate = "shutoff" @@ -66,7 +66,7 @@ - inside_boundary: outbound = '65535,65535,65535' - maximum_boundary: - outbound = '4294967,4294967,4294967' + outbound = '4194303,4194303,4194303' variants: - options: variants: From 9d1545e2e270bc63d16cced0b767df21e07f5c87 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Wed, 11 Dec 2024 06:50:23 -0500 Subject: [PATCH 0731/1055] SRIOV: add new test case of dma_translation for vIOMMU Automate new dma_translation attribute for vIOMMU: VIRT-302220 - [vIOMMU][intel] Start VM with intel iommu and dma_translation attribute Signed-off-by: Meina Li --- .../intel_iommu_with_dma_translation.cfg | 17 +++++++ .../intel_iommu_with_dma_translation.py | 47 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_with_dma_translation.cfg create mode 100644 libvirt/tests/src/sriov/vIOMMU/intel_iommu_with_dma_translation.py diff --git a/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_with_dma_translation.cfg b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_with_dma_translation.cfg new file mode 100644 index 00000000000..ed796ca7496 --- /dev/null +++ b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_with_dma_translation.cfg @@ -0,0 +1,17 @@ +- vIOMMU.intel_iommu_with_dma_translation: + type = intel_iommu_with_dma_translation + start_vm = "yes" + enable_guest_iommu = "yes" + func_supported_since_libvirt_ver = (10, 7, 0) + only q35 + variants: + - enable_dma_translation: + dma_translation = "on" + - disable_dma_translation: + dma_translation = "off" + - disable_dma_translation_with_more_vcpus: + with_more_vcpus = "yes" + dma_translation = "off" + eim_dict = {'eim': 'on'} + guest_vcpus = 256 + iommu_dict = {'model': 'intel', 'driver': {'intremap': 'on', 'caching_mode': 'on', 'iotlb': 'on', 'dma_translation': '${dma_translation}'}} diff --git a/libvirt/tests/src/sriov/vIOMMU/intel_iommu_with_dma_translation.py b/libvirt/tests/src/sriov/vIOMMU/intel_iommu_with_dma_translation.py new file mode 100644 index 00000000000..4b057ed4842 --- /dev/null +++ b/libvirt/tests/src/sriov/vIOMMU/intel_iommu_with_dma_translation.py @@ -0,0 +1,47 @@ +from virttest import virsh +from virttest.libvirt_xml import vm_xml + +from provider.viommu import viommu_base + + +def run(test, params, env): + """ + Start vm with Intel iommu and dma_translation attribute. + """ + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + dma_translation = params.get("dma_translation") + guest_vcpus = params.get("guest_vcpus") + eim_dict = eval(params.get("eim_dict", "{}")) + iommu_dict = eval(params.get("iommu_dict", "{}")) + with_more_vcpus = "yes" == params.get("with_more_vcpus", "no") + test_obj = viommu_base.VIOMMUTest(vm, test, params) + + try: + iommu_dict['driver'].update(eim_dict) + test.log.info("TEST STEP1: Prepare guest xml with intel iommu device.") + test_obj.setup_iommu_test(iommu_dict=iommu_dict) + if with_more_vcpus: + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + vmxml.vcpu = int(guest_vcpus) + vmxml.sync() + test.log.info("TEST STEP2: Start the guest.") + vm.start() + test.log.debug("The current guest xml ls: %s", + virsh.dumpxml(vm_name).stdout_text) + test.log.info("TEST STEP3: Check the message for iommu group and DMA.") + vm.cleanup_serial_console() + vm.create_serial_console() + vm_session = vm.wait_for_serial_login(timeout=1000) + dma_status, dma_o = vm_session.cmd_status_output("dmesg | grep -i 'Not attempting DMA translation'") + iommu_status, iommu_o = vm_session.cmd_status_output("dmesg | grep -i 'Adding to iommu group'") + if dma_translation == "on" and (not dma_status or iommu_status): + test.fail("Can't get expected dma message %s when enabling dma_translation." % dma_o) + if dma_translation == "off" and (dma_status or not iommu_status): + test.fail("Can't get expected iommu message %s when disabling dma_translation." % iommu_o) + if with_more_vcpus: + s, o = vm_session.cmd_status_output("cat /proc/cpuinfo | grep processor| wc -l") + if int(o) != int(guest_vcpus): + test.fail("Can't get expected vCPU number, the actual number is %s" % o) + finally: + test_obj.teardown_iommu_test() From b18d3a2e8c703f864f88d11cb9922e8e523f5722 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 11 Dec 2024 12:31:52 -0500 Subject: [PATCH 0732/1055] virtio_transitional_nic: don't attach incompatible controller On s390x, pci bridge is not available. Don't attach this. Signed-off-by: Sebastian Mitterle --- .../virtio_transitional_nic.cfg | 3 +++ .../virtio_transitional_nic.py | 23 +++++++++++-------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_nic.cfg b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_nic.cfg index ab1e7985527..9e69346f6c5 100644 --- a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_nic.cfg +++ b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_nic.cfg @@ -18,6 +18,9 @@ variants: - virtio: virtio_model = "virtio" + s390-virtio: + check_pci_bridge = no + bridge_controller_needed = no - virtio_transitional: no s390-virtio virtio_model = "virtio-transitional" diff --git a/libvirt/tests/src/virtio_transitional/virtio_transitional_nic.py b/libvirt/tests/src/virtio_transitional/virtio_transitional_nic.py index 892b9d932ef..275be100218 100644 --- a/libvirt/tests/src/virtio_transitional/virtio_transitional_nic.py +++ b/libvirt/tests/src/virtio_transitional/virtio_transitional_nic.py @@ -209,7 +209,7 @@ def create_iface_xml(mac): if cold_plug == "yes": reboot() # Reboot guest if it is cold plug test detect_new_nic(mac) - if plug_method == 'interface' and cold_plug == 'no': + if plug_method == 'interface' and cold_plug == 'no' and check_pci_bridge: check_plug_to_pci_bridge(vm_name, mac) session = vm.wait_for_login(serial=True) # Add nic to VM object for further check @@ -278,6 +278,8 @@ def ping_test(restart_network=False): params['disk_model'] = params['virtio_model'] guest_os_type = params['os_type'] set_crypto_policy = params.get("set_crypto_policy") + bridge_controller_needed = params.get("bridge_controller_needed", "yes") == "yes" + check_pci_bridge = params.get("check_pci_bridge", "yes") == "yes" target_path = None @@ -301,15 +303,16 @@ def ping_test(restart_network=False): libvirt.set_vm_disk(vm, params) # Add pcie-to-pci-bridge when there is no one - pci_controllers = vmxml.get_controllers('pci') - for controller in pci_controllers: - if controller.get('model') == 'pcie-to-pci-bridge': - break - else: - contr_dict = {'controller_type': 'pci', - 'controller_model': 'pcie-to-pci-bridge'} - cntl_add = libvirt.create_controller_xml(contr_dict) - libvirt.add_controller(vm_name, cntl_add) + if bridge_controller_needed: + pci_controllers = vmxml.get_controllers('pci') + for controller in pci_controllers: + if controller.get('model') == 'pcie-to-pci-bridge': + break + else: + contr_dict = {'controller_type': 'pci', + 'controller_model': 'pcie-to-pci-bridge'} + cntl_add = libvirt.create_controller_xml(contr_dict) + libvirt.add_controller(vm_name, cntl_add) try: # Update interface model as defined iface_params = {'model': params['virtio_model']} libvirt.modify_vm_iface(vm_name, "update_iface", iface_params) From ab182c3a673e780f7ee432cff40da4ab22656c31 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 19 Nov 2024 13:04:09 -0500 Subject: [PATCH 0733/1055] iface_bridge: make host interface configurable On our test environment we must use not the first host interface. Make configurable but maintain default behavior if not configured. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/virtual_network/iface_bridge.cfg | 1 + libvirt/tests/src/virtual_network/iface_bridge.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_network/iface_bridge.cfg b/libvirt/tests/cfg/virtual_network/iface_bridge.cfg index 803a9ad166a..d2e413a0d78 100644 --- a/libvirt/tests/cfg/virtual_network/iface_bridge.cfg +++ b/libvirt/tests/cfg/virtual_network/iface_bridge.cfg @@ -4,6 +4,7 @@ vms = avocado-vt-vm1 vm2 bridge_name = "test_br0" netdst_nic1 = ${bridge_name} + host_iface = # Replace remote_ip by a actual IP address remote_ip = "www.google.com" ping_count = 3 diff --git a/libvirt/tests/src/virtual_network/iface_bridge.py b/libvirt/tests/src/virtual_network/iface_bridge.py index 25ed63dae25..aa512c6fdaf 100644 --- a/libvirt/tests/src/virtual_network/iface_bridge.py +++ b/libvirt/tests/src/virtual_network/iface_bridge.py @@ -113,7 +113,9 @@ def check_net_functions(guest_ip, ping_count, ping_timeout, guest_session, host_ filter_name = params.get("filter_name", "vdsm-no-mac-spoofing") ping_count = params.get("ping_count", "5") ping_timeout = float(params.get("ping_timeout", "10")) - iface_name = utils_net.get_net_if(state="UP")[0] + host_iface = params.get("host_iface") + iface_name = host_iface if host_iface else utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] bridge_script = NETWORK_SCRIPT + bridge_name iface_script = NETWORK_SCRIPT + iface_name iface_script_bk = os.path.join(data_dir.get_tmp_dir(), "iface-%s.bk" % iface_name) From 7fbf039e3c8b03c3a053a2e43202eac97f4a0fbf Mon Sep 17 00:00:00 2001 From: nanli Date: Thu, 12 Dec 2024 08:25:58 +0800 Subject: [PATCH 0734/1055] fix virsh create use incorrect log operation virsh cmd should use debug=True , not shell=True Signed-off-by: nanli --- .../backingchain/blockcopy/blockcopy_with_zero_length_disk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/backingchain/blockcopy/blockcopy_with_zero_length_disk.py b/libvirt/tests/src/backingchain/blockcopy/blockcopy_with_zero_length_disk.py index 67ce1f01fbc..c738fda1cb7 100644 --- a/libvirt/tests/src/backingchain/blockcopy/blockcopy_with_zero_length_disk.py +++ b/libvirt/tests/src/backingchain/blockcopy/blockcopy_with_zero_length_disk.py @@ -53,7 +53,7 @@ def prepare_transient_guest(): test.log.debug("Define guest by xml:\n%s", vmxml) virsh.undefine(vm_name, options='--nvram', debug=True, ignore_status=False) - virsh.create(vmxml.xml, shell=True) + virsh.create(vmxml.xml, debug=True, ignore_status=False) def run_test(): """ From 79f22139a664c41d0d11de4bf6ff6f951e014fe4 Mon Sep 17 00:00:00 2001 From: nanli Date: Thu, 12 Dec 2024 11:57:08 +0800 Subject: [PATCH 0735/1055] fix virsh hypervisor-cpu-compare case due to feature update Signed-off-by: nanli --- .../cfg/virsh_cmd/domain/virsh_hypervisor_cpu_compare.cfg | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_hypervisor_cpu_compare.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_hypervisor_cpu_compare.cfg index 4f1984b8884..48e2ffa5ede 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_hypervisor_cpu_compare.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_hypervisor_cpu_compare.cfg @@ -70,8 +70,7 @@ - capa_xml: no s390-virtio, aarch64 compare_file_type = "capa_xml" - status_error = "yes" - msg_pattern = "incompatible" + status_error = "no" - cpu_xml: extract_mode = "yes" variants: @@ -81,8 +80,7 @@ - f_capa_xml: no s390-virtio, aarch64 compare_file_type = "capa_xml" - status_error = "yes" - msg_pattern = "incompatible" + status_error = "no" - f_domcapa_xml: compare_file_type = "domcapa_xml" msg_pattern = "identical" From 3832af5ac4beaaea7ec784772619bae2e0b8fe23 Mon Sep 17 00:00:00 2001 From: Fangge Jin Date: Thu, 12 Dec 2024 11:14:37 +0800 Subject: [PATCH 0736/1055] set-user-password: Fix the wrong logic of set encrypted password 1. Escape "$" in the encrypted password If "$" is not escaped in the virsh command parameter, libvirt will parse it to wrong value and set wrong password in guest. 2. Fail the test case if it can't login guest with new password Previsouly, the code only logged the message and doesn't fail the case. Signed-off-by: Fangge Jin --- libvirt/tests/src/virsh_cmd/domain/virsh_set_user_password.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_set_user_password.py b/libvirt/tests/src/virsh_cmd/domain/virsh_set_user_password.py index 48d14a63604..94794fbfcd7 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_set_user_password.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_set_user_password.py @@ -76,19 +76,21 @@ def run(test, params, env): ret = process.run(cmd, shell=True) libvirt.check_exit_status(ret) en_passwd = str(ret.stdout_text.strip()) - passwd = en_passwd + passwd = en_passwd.replace('$', r'\$') ret = virsh.set_user_password(vm_name, set_user_name, passwd, encrypted=encrypted, option=option, debug=True) libvirt.check_exit_status(ret) # Login with new password + logging.debug("Trying to log in with new password") try: session = remote.wait_for_login("ssh", vm_ip, "22", set_user_name, new_passwd, r"[\#\$]\s*$", timeout=30) session.close() except remote.LoginAuthenticationError as e: logging.debug(e) + test.fail("Failed to login with new password") # Login with old password try: From 6174892452b17fd5a34091418cf5e77281fdafb3 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Thu, 28 Nov 2024 12:40:39 -0500 Subject: [PATCH 0737/1055] libvirt_rng: fix snapshot with egd Refactor: 1. variant rng_snapshot always has 'test_snapshot', move to top 2. snapshot_name was used as indicator for snapshot test variants, hence synonymous with 'test_snapshot', remove it from config 3. 'modify_rng_xml' had a very complicated logic, split into two functions to make it simpler to understand; when there are snapshots then the VM can't by 'sync'd, ie. re-defined; in those cases, 'edit' is used instead - both are coldplug 4. check_snapshot didn't use bgjob, remove it from parameters 5. check_snapshot must revert to the first snapshot 's1' where there was no rng device 6. move logic into functions so that the test steps are clearer - clear rng devices - take snapshot if testing snapshots - update xml in case of coldplug - create fake egd if necessary (connect mode) - start vm - update xml in case of hotplug - run test checks 7. remove definition and usage of `start_error`: it seems to have been introduced originally in ec3aaf016e39d7bf501b497ac267f545223dd9f9 to control expected failure but not used; then at some time it seems it was intended to be used to handle https://bugzilla.redhat.com/show_bug.cgi?id=1220252 that issue was found in qemu-kvm-rhev 2.4 RHEL 7.2 and fixed in the same distro version; therefore, let's remove its definition and usage in code Furthermore, a. explicitly start fake egd also for snapshot test b. wait a bit after launching fake edg for connect mode to make sure VM doesn't start before it's up c. wait a bit more after booting VM for it to listen in bind mode before starting fake egd in bind mode Finally, apply `black` for standard formatting. Signed-off-by: Sebastian Mitterle --- .../tests/cfg/security/rng/libvirt_rng.cfg | 8 +- libvirt/tests/src/security/rng/libvirt_rng.py | 615 +++++++++++------- spell.ignore | 4 + 3 files changed, 377 insertions(+), 250 deletions(-) diff --git a/libvirt/tests/cfg/security/rng/libvirt_rng.cfg b/libvirt/tests/cfg/security/rng/libvirt_rng.cfg index 590e48547c6..76a44c0ce4b 100644 --- a/libvirt/tests/cfg/security/rng/libvirt_rng.cfg +++ b/libvirt/tests/cfg/security/rng/libvirt_rng.cfg @@ -109,16 +109,14 @@ rng_rate = "{'bytes':'5000','period':'2000'}" backend_model = "builtin" - rng_snapshot: - snapshot_name = "rng.s" + test_snapshot = "yes" variants: - snapshot_running: snap_options = "%s --memspec " mem_files = ["/var/lib/libvirt/images/avocado-memory.s1", "/var/lib/libvirt/images/avocado-memory.s2"] snapshot_vm_running = "yes" - test_snapshot = "yes" - snapshot_shutoff: snap_options = "%s --disk-only" - test_snapshot = "yes" variants: - back_rdm: backend_dev = "/dev/random" @@ -135,13 +133,13 @@ - back_udp: backend_model = "egd" backend_type = "udp" - backend_source = "{'mode':'bind','service':'1234'} {'mode':'connect','host':'1.2.3.4','service':'1234'}" + backend_source = "{'mode':'bind','service':'1024'} {'mode':'connect','host':'127.0.0.1','service':'1234'}" - multiple_rng: device_num = 3 backend_dev_0 = "/dev/random" backend_dev_1 = "/dev/random" backend_model_2 = "egd" backend_type_2 = "udp" - backend_source_2 = "{'mode':'connect','host':'1.2.3.4','service':'1234'}" + backend_source_2 = "{'mode':'connect','host':'127.0.0.1','service':'1234'}" test_qemu_cmd = "yes" test_guest = "yes" diff --git a/libvirt/tests/src/security/rng/libvirt_rng.py b/libvirt/tests/src/security/rng/libvirt_rng.py index 9ea18452b96..3956c4ce50a 100644 --- a/libvirt/tests/src/security/rng/libvirt_rng.py +++ b/libvirt/tests/src/security/rng/libvirt_rng.py @@ -24,7 +24,8 @@ # 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__) +background_jobs = [] def run(test, params, env): @@ -39,8 +40,7 @@ def run(test, params, env): """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) - snap_options = params.get("snap_options") - mem_files = eval(params.get("mem_files", '[]')) + mem_files = eval(params.get("mem_files", "[]")) def check_rng_xml(xml_set, exists=True): """ @@ -89,38 +89,58 @@ def get_compare_values(xml_set, xml_get, rng_attr): get_value = xml_get[rng_attr] except xcepts.LibvirtXMLNotFoundError: get_value = None - logging.debug("get xml_set value(%s) is %s, get xml_get value is %s", - rng_attr, set_value, get_value) + logging.debug( + "get xml_set value(%s) is %s, get xml_get value is %s", + rng_attr, + set_value, + get_value, + ) return (set_value, get_value) match = True for rng_attr in xml_set.__slots__: set_value, get_value = get_compare_values(xml_set, xml_get, rng_attr) - logging.debug("rng_attr=%s, set_value=%s, get_value=%s", rng_attr, set_value, get_value) + logging.debug( + "rng_attr=%s, set_value=%s, get_value=%s", + rng_attr, + set_value, + get_value, + ) if set_value and set_value != get_value: - if rng_attr == 'backend': + if rng_attr == "backend": for bak_attr in xml_set.backend.__slots__: - set_backend, get_backend = get_compare_values(xml_set.backend, xml_get.backend, bak_attr) + set_backend, get_backend = get_compare_values( + xml_set.backend, xml_get.backend, bak_attr + ) if set_backend and set_backend != get_backend: - if bak_attr == 'source': + if bak_attr == "source": set_source = xml_set.backend.source get_source = xml_get.backend.source find = False for i in range(len(set_source)): for j in get_source: - if set(set_source[i].items()).issubset(j.items()): + if set(set_source[i].items()).issubset( + j.items() + ): find = True break if not find: - logging.debug("set source(%s) not in get source(%s)", - set_source[i], get_source) + logging.debug( + "set source(%s) not in get source(%s)", + set_source[i], + get_source, + ) match = False break else: continue else: - logging.debug("set backend(%s)- %s not equal to get backend-%s", - rng_attr, set_backend, get_backend) + logging.debug( + "set backend(%s)- %s not equal to get backend-%s", + rng_attr, + set_backend, + get_backend, + ) match = False break else: @@ -128,8 +148,12 @@ def get_compare_values(xml_set, xml_get, rng_attr): if not match: break else: - logging.debug("set value(%s)-%s not equal to get value-%s", - rng_attr, set_value, get_value) + logging.debug( + "set value(%s)-%s not equal to get value-%s", + rng_attr, + set_value, + get_value, + ) match = False break else: @@ -138,30 +162,26 @@ def get_compare_values(xml_set, xml_get, rng_attr): break if match: - logging.info("Find same rng xml as hotpluged") + logging.info("Found the same rng xml as hotplugged") else: - test.fail("Rng xml in VM not same with attached xml") + test.fail("Rng xml in VM not same as attached xml") return True - def modify_rng_xml(dparams, sync=True, get_xml=False): + def get_rng_xml(dparams): """ - Modify interface xml options + Get rng device xml :params dparams: parameters for organize xml - :params sync: whether sync to domain xml, if get_xml is True, - then sync will not take effect - :params get_xml: whether get device xml - :return: if get_xml=True, return xml file + :return: return rng xml file """ rng_model = dparams.get("rng_model", "virtio") rng_rate = dparams.get("rng_rate") backend_model = dparams.get("backend_model", "random") backend_type = dparams.get("backend_type") backend_dev = dparams.get("backend_dev", "") - backend_source_list = dparams.get("backend_source", - "").split() backend_protocol = dparams.get("backend_protocol") + backend_source_list = dparams.get("backend_source", "").split() rng_alias = dparams.get("rng_alias") device_address = dparams.get("address") vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) @@ -176,8 +196,7 @@ def modify_rng_xml(dparams, sync=True, get_xml=False): if backend_dev: backend.backend_dev = backend_dev if backend_source_list: - source_list = [ast.literal_eval(source) for source in - backend_source_list] + source_list = [ast.literal_eval(source) for source in backend_source_list] backend.source = source_list if backend_protocol: backend.backend_protocol = backend_protocol @@ -187,23 +206,41 @@ def modify_rng_xml(dparams, sync=True, get_xml=False): if with_packed: rng_xml.driver = dict(packed=driver_packed) if device_address: - rng_xml.address = rng_xml.new_rng_address(**{"attrs": ast.literal_eval(device_address)}) + rng_xml.address = rng_xml.new_rng_address( + **{"attrs": ast.literal_eval(device_address)} + ) logging.debug("Rng xml: %s", rng_xml) - if get_xml: - return rng_xml - if sync: + return rng_xml + + def modify_rng_xml(rng_xml, sync_or_edit="sync"): + """ + Modify rng xml + + :params rng_xml: the rng device xml + :params sync_or_edit: "sync" will redefine the VM with the rng + "edit" will edit the VM + """ + if sync_or_edit == "sync": vmxml.add_device(rng_xml) vmxml.xmltreefile.write() vmxml.sync() - else: + elif sync_or_edit == "edit": status = libvirt.exec_virsh_edit( - vm_name, [(r"://s/$/%s" % - re.findall(r"", - str(rng_xml), re.M - )[0].replace("/", "\/"))]) + vm_name, + [ + ( + r"://s/$/%s" + % re.findall(r"", str(rng_xml), re.M)[0].replace( + "/", "\/" + ) + ) + ], + ) if not status: test.fail("Failed to edit vm xml") + else: + test.error(f"Can't modify XML with method '{sync_or_edit}'.") def check_qemu_cmd(dparams): """ @@ -213,9 +250,7 @@ def check_qemu_cmd(dparams): rng_rate = dparams.get("rng_rate") backend_type = dparams.get("backend_type") backend_model = dparams.get("backend_model") - backend_source_list = dparams.get("backend_source", - "").split() - cmd = ("ps -ef | grep %s | grep -v grep" % vm_name) + cmd = "ps -ef | grep %s | grep -v grep" % vm_name logging.debug("Qemu cmd line info:\n") process.run(cmd, ignore_status=True, shell=True) chardev = src_host = src_port = None @@ -225,34 +260,32 @@ def check_qemu_cmd(dparams): chardev = "udp" for bc_source in backend_source_list: source = ast.literal_eval(bc_source) - if "mode" in source and source['mode'] == "connect": - src_host = source['host'] - src_port = source['service'] + if "mode" in source and source["mode"] == "connect": + src_host = source["host"] + src_port = source["service"] result = process.run(cmd, ignore_status=True, shell=True) if result.exit_status: - test.fail("Got error obtaining qemu cmdline:" - " %s" % result.stderr_text) + test.fail("Got error obtaining qemu cmdline: %s" % result.stderr_text) expected_matches = [] if backend_model == "builtin": expected_matches.append("rng-builtin") if chardev and src_host and src_port: - expected_matches.append("chardev %s,.*host=%s,port=%s" - % (chardev, src_host, src_port)) + expected_matches.append( + "chardev %s,.*host=%s,port=%s" % (chardev, src_host, src_port) + ) if rng_model == "virtio": expected_matches.append("%s" % dparams.get("rng_device")) if rng_rate: rate = ast.literal_eval(rng_rate) - expected_matches.append("max-bytes.*%s" % rate['bytes']) - expected_matches.append("period.*%s" % rate['period']) + expected_matches.append("max-bytes.*%s" % rate["bytes"]) + expected_matches.append("period.*%s" % rate["period"]) if with_packed: expected_matches.append("packed.*%s" % driver_packed) - if not all([re.findall(x, result.stdout_text) - for x in expected_matches]): + if not all([re.findall(x, result.stdout_text) for x in expected_matches]): logging.debug("Expected matches: %s" % expected_matches) logging.debug("QEMU cmdline: %s" % result.stdout_text) - test.fail("Can't see rng option" - " in command line. Please check the log.") + test.fail("Can't see rng option in command line. Please check the log.") def check_host(): """ @@ -263,33 +296,33 @@ def check_host(): cmd = "lsof |grep %s" % backend_dev ret = process.run(cmd, ignore_status=True, shell=True) if ret.exit_status or not ret.stdout_text.count("qemu"): - test.fail("Failed to check random device" - " on host, command output: %s" % - ret.stdout_text) + test.fail( + "Failed to check random device" + " on host, command output: %s" % ret.stdout_text + ) - def check_snapshot(bgjob=None): + def check_snapshot(): """ Do snapshot operation and check the results """ - snapshot_name1 = "snap.s1" + # we only check_snapshot + snapshot_name = "s2" if not snapshot_vm_running: vm.destroy(gracefully=False) snap_options = params.get("snap_options") if "--memspec" in snap_options: snap_options += mem_files[1] ret = virsh.snapshot_create_as( - vm_name, options=snap_options % snapshot_name1, debug=True) + vm_name, options=snap_options % snapshot_name, debug=True + ) libvirt.check_exit_status(ret) - snap_info = virsh.snapshot_info(vm_name, snapshot_name1, debug=True) + snap_info = virsh.snapshot_info(vm_name, snapshot_name, debug=True) check_snap_info(snap_info) snap_lists = virsh.snapshot_list(vm_name, debug=True) if snapshot_name not in snap_lists: - test.fail("Snapshot %s doesn't exist" - % snapshot_name) + test.fail("Snapshot %s doesn't exist" % snapshot_name) - options = "" - ret = virsh.snapshot_revert( - vm_name, ("%s %s" % (snapshot_name, options)), debug=True) + ret = virsh.snapshot_revert(vm_name, "s1", debug=True) libvirt.check_exit_status(ret) ret = virsh.dumpxml(vm_name, debug=True) if ret.stdout.strip().count(" %s" % - (virtio_dev, rng_files[1])), - timeout=timeout) + virtio_dev = re.findall("virtio_rng.\d+", rng_avail)[0] + _ = session.cmd_output( + ("echo -n %s > %s" % (virtio_dev, rng_files[1])), timeout=timeout + ) rng_currt = virtio_dev if not rng_currt.count("virtio") or rng_currt not in rng_avail: - test.fail("Failed to check rng file on guest." - " The virtio device is not the current rng device.") + test.fail( + "Failed to check rng file on guest." + " The virtio device is not the current rng device." + ) # Read the random device rng_rate = params.get("rng_rate") # For rng rate test this command and return in a short time # but for other test it will hang - cmd = ("dd if=/dev/hwrng of=rng.test %s" - " && rm -f rng.test" % dd_throughput) + cmd = "dd if=/dev/hwrng of=rng.test %s && rm -f rng.test" % dd_throughput try: ret, output = session.cmd_status_output(cmd, timeout=timeout) if ret and expect_fail: @@ -398,17 +433,14 @@ def check_guest(session, expect_fail=False, if rng_rate: rate_bytes, rate_period = list(ast.literal_eval(rng_rate).values()) - rate_conf = float(rate_bytes) / (float(rate_period)/1000) - ret = re.search(r"(\d+) bytes.*copied, (\d+.\d+) s", - output, re.M) + rate_conf = float(rate_bytes) / (float(rate_period) / 1000) + ret = re.search(r"(\d+) bytes.*copied, (\d+.\d+) s", output, re.M) if not ret: test.fail("Can't find rate from output") rate_real = float(ret.group(1)) / float(ret.group(2)) - logging.debug("Found rate: %s, config rate: %s", - rate_real, rate_conf) + logging.debug("Found rate: %s, config rate: %s", rate_real, rate_conf) if rate_real > rate_conf * 1.2: - test.fail("The rate of reading exceed" - " the limitation of configuration") + test.fail("The rate of reading exceed the limitation of configuration") if device_num > 1: rng_dev = rng_avail.split() compare_device_numbers(ignored_devices, rng_dev, device_num) @@ -428,9 +460,11 @@ def compare_device_numbers(ignored_devices, rng_dev, device_num): """ filtered_rng_dev = [x for x in rng_dev if x not in ignored_devices] if len(filtered_rng_dev) != device_num: - test.fail("Number of rng devices defined and available does not match.\n" - "Rng devices: %s\n" - "Number of devices: %i" % (rng_dev, device_num)) + test.fail( + "Number of rng devices defined and available does not match.\n" + "Rng devices: %s\n" + "Number of devices: %i" % (rng_dev, device_num) + ) def get_rng_device(guest_arch, rng_model): """ @@ -451,7 +485,7 @@ def check_snap_info(snap_info): :param snap_info: result get from vm snapshot info """ snap_state = "running" if snapshot_vm_running else "shutoff" - if snap_info["State"] != snap_state or snap_info['Location'] != "external": + if snap_info["State"] != snap_state or snap_info["Location"] != "external": test.fail("Snapshot info about State or Location checking failed!") def rotate_audit_log(): @@ -461,7 +495,201 @@ def rotate_audit_log(): """ process.run("systemctl kill --signal SIGUSR1 auditd") - start_error = "yes" == params.get("start_error", "no") + def handle_egd_connect_mode(): + """ + Creates source for egd in connect mode, i.e. a server where the VM + connects to when started. + + It ignores external hosts and instead runs everything locally. + + After starting the fake egd in the background, wait a second to make + sure it's up when VM starts. + + Feed entropy from /dev/urandom to avoid blocking. + """ + connect_sources = [ + eval(source) + for source in backend_source_list + if eval(source)["mode"] == "connect" + ] + if not connect_sources: + return + for source in connect_sources: + + connect_port = source["service"] + + if params.get("backend_type") == "tcp" and ( + test_snapshot or (random_source and not test_guest_dump) + ): + cmd = f"cat /dev/urandom | nc -4 -l 127.0.0.1 {connect_port}" + job = utils_misc.AsyncJob(cmd) + background_jobs.append(job) + + if params.get("backend_type") == "udp" and ( + test_snapshot or (random_source and test_guest_dump) + ): + if not utils_package.package_install("socat"): + test.error("Failed to install socat on host") + cmd = f"cat /dev/urandom | socat udp-listen:{connect_port},reuseaddr,fork -" + job = utils_misc.AsyncJob(cmd) + background_jobs.append(job) + + time.sleep(1) + + logging.info(f"{background_jobs}") + for job in background_jobs: + logging.info(f"fake egd: {job.get_stderr()} {job.get_stdout()}") + + def handle_egd_bind_mode(): + """ + Provides entropy to the given port that's listening on the VM. + For test cases that use tcp bind mode only because we can't test + udp bind connect with external server. + + Feed entropy from /dev/urandom to avoid blocking. + """ + if not params.get("backend_type") == "tcp": + return + + if not backend_source_list: + return + + bind_sources = [ + eval(source) + for source in backend_source_list + if eval(source)["mode"] == "bind" + ] + + for source in bind_sources: + time.sleep(3) # extra time for VM to start listening + connect_port = source["service"] + cmd = f"cat /dev/random | nc -4 localhost {connect_port}" + job = utils_misc.AsyncJob(cmd) + background_jobs.append(job) + logging.info(f"fake egd: {job.get_stderr()} {job.get_stdout()}") + + def try_use_rngd(): + """ + Try to install rng-tools on host, it can speed up random rate + if installation failed, ignore the error and continue the test + """ + if utils_package.package_install(["rng-tools"]): + rngd_conf = "/etc/sysconfig/rngd" + rngd_srv = "/usr/lib/systemd/system/rngd.service" + if os.path.exists(rngd_conf): + # For rhel6 host, add extra options + with open(rngd_conf, "w") as f_rng: + f_rng.write('EXTRAOPTIONS="--rng-device /dev/urandom"') + elif os.path.exists(rngd_srv): + # For rhel7 host, modify start options + rngd_srv_conf = "/etc/systemd/system/rngd.service" + if not os.path.exists(rngd_srv_conf): + shutil.copy(rngd_srv, rngd_srv_conf) + process.run( + "sed -i -e 's#^ExecStart=.*#ExecStart=/sbin/rngd" + " -f -r /dev/urandom -o /dev/random#' %s" % rngd_srv_conf, + shell=True, + ) + process.run("systemctl daemon-reload") + process.run("service rngd start") + + def build_vm_xml(): + """ + Build the VM XML. + + :return: rng_xml + """ + rng_xml = None + if device_num > 1: + for i in xrange(device_num): + rng_model = params.get("rng_model_%s" % i, "virtio") + dparams[i] = {"rng_model": rng_model} + dparams[i].update( + {"backend_model": params.get("backend_model_%s" % i, "random")} + ) + dparams[i].update({"rng_device": get_rng_device(guest_arch, rng_model)}) + bk_type = params.get("backend_type_%s" % i) + if bk_type: + dparams[i].update({"backend_type": bk_type}) + bk_dev = params.get("backend_dev_%s" % i) + if bk_dev: + dparams[i].update({"backend_dev": bk_dev}) + bk_src = params.get("backend_source_%s" % i) + if bk_src: + dparams[i].update({"backend_source": bk_src}) + bk_pro = params.get("backend_protocol_%s" % i) + if bk_pro: + dparams[i].update({"backend_protocol": bk_pro}) + rng_xml = get_rng_xml(dparams[i]) + modify_rng_xml(rng_xml, "edit") + else: + params.update( + { + "rng_device": get_rng_device( + guest_arch, params.get("rng_model", "virtio") + ) + } + ) + + if urandom or detach_alias: + device_alias = "ua-" + str(uuid.uuid4()) + params.update({"rng_alias": device_alias}) + + rng_xml = get_rng_xml(params) + if not attach_rng: + sync_or_edit = "edit" if test_snapshot else "sync" + modify_rng_xml(rng_xml, sync_or_edit) + return rng_xml + + def handle_first_snapshot(): + """ + test_snapshot will take two snapshots: + s1: without rng + s2: with rng + """ + if test_snapshot: + snapshot_name = "s1" + if snapshot_vm_running: + vm.start() + vm.wait_for_login().close() + snap_options = params.get("snap_options") + if "--memspec" in snap_options: + snap_options += mem_files[0] + ret = virsh.snapshot_create_as( + vm_name, options=snap_options % snapshot_name, debug=True + ) + libvirt.check_exit_status(ret) + snap_info = virsh.snapshot_info(vm_name, snapshot_name, debug=True) + check_snap_info(snap_info) + + def handle_hotplug(): + """ + Hotplugs device if requested + """ + if attach_rng: + ret = virsh.attach_device( + vm_name, + rng_xml.xml, + flagstr=attach_options, + wait_remove_event=True, + debug=True, + ignore_status=True, + ) + libvirt.check_exit_status(ret, status_error) + if status_error: + return "pass_test_on_error" + if not check_rng_xml(rng_xml, True): + test.fail("Can not find rng device in xml") + return "" + + def remove_all_rng_devices(): + """ + Make sure no extra rng devices interfere. + """ + vmxml.remove_all_device_by_type("rng") + vmxml.sync() + logging.debug("Prepared vm xml without rng dev is %s", vmxml) + expected_create_error = params.get("expected_create_error", "") status_error = "yes" == params.get("status_error", "no") @@ -475,9 +703,7 @@ def rotate_audit_log(): test_guest_rng_file = "yes" == params.get("test_guest_rng_file", "no") test_qemu_cmd = "yes" == params.get("test_qemu_cmd", "no") test_snapshot = "yes" == params.get("test_snapshot", "no") - snapshot_vm_running = "yes" == params.get("snapshot_vm_running", - "no") - snapshot_name = params.get("snapshot_name") + snapshot_vm_running = "yes" == params.get("snapshot_vm_running", "no") device_num = int(params.get("device_num", 1)) ignored_devices = params.get("ignored_devices", "").split(",") detach_alias = "yes" == params.get("rng_detach_alias", "no") @@ -491,152 +717,53 @@ def rotate_audit_log(): driver_packed = params.get("driver_packed", "on") urandom = "yes" == params.get("urandom", "no") dd_throughput = params.get("dd_throughput") + backend_source_list = params.get("backend_source", "").split() - if params.get("backend_model") == "builtin" and not libvirt_version.version_compare(6, 2, 0): + if params.get("backend_model") == "builtin" and not libvirt_version.version_compare( + 6, 2, 0 + ): test.cancel("Builtin backend is not supported on this libvirt version") if device_num > 1 and not libvirt_version.version_compare(1, 2, 7): - test.cancel("Multiple virtio-rng devices not " - "supported on this libvirt version") + test.cancel("Multiple virtio-rng devices not supported on this libvirt version") 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." + ) guest_arch = params.get("vm_arch_name", "x86_64") - # Back up xml file. - vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) - - # Try to install rng-tools on host, it can speed up random rate - # if installation failed, ignore the error and continue the test - if utils_package.package_install(["rng-tools"]): - rngd_conf = "/etc/sysconfig/rngd" - rngd_srv = "/usr/lib/systemd/system/rngd.service" - if os.path.exists(rngd_conf): - # For rhel6 host, add extra options - with open(rngd_conf, 'w') as f_rng: - f_rng.write('EXTRAOPTIONS="--rng-device /dev/urandom"') - elif os.path.exists(rngd_srv): - # For rhel7 host, modify start options - rngd_srv_conf = "/etc/systemd/system/rngd.service" - if not os.path.exists(rngd_srv_conf): - shutil.copy(rngd_srv, rngd_srv_conf) - process.run("sed -i -e 's#^ExecStart=.*#ExecStart=/sbin/rngd" - " -f -r /dev/urandom -o /dev/random#' %s" - % rngd_srv_conf, shell=True) - process.run('systemctl daemon-reload') - process.run("service rngd start") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vmxml_backup = vmxml.copy() - # Build the xml and run test. - try: - bgjob = None - bgjob2 = None + try_use_rngd() + try: if test_audit: rotate_audit_log() - # Prepare xml, make sure no extra rng dev. - vmxml = vmxml_backup.copy() - vmxml.remove_all_device_by_type('rng') - vmxml.sync() - logging.debug("Prepared vm xml without rng dev is %s", vmxml) - - # Take snapshot if needed - if snapshot_name: - if snapshot_vm_running: - vm.start() - vm.wait_for_login().close() - if "--memspec" in snap_options: - snap_options += mem_files[0] - ret = virsh.snapshot_create_as( - vm_name, options=snap_options % snapshot_name, debug=True) - libvirt.check_exit_status(ret) - snap_info = virsh.snapshot_info(vm_name, snapshot_name, debug=True) - check_snap_info(snap_info) - - # Destroy VM first - if vm.is_alive(): - vm.destroy(gracefully=False) + remove_all_rng_devices() + handle_first_snapshot() try: - # Build vm xml. dparams = {} - if device_num > 1: - for i in xrange(device_num): - rng_model = params.get("rng_model_%s" % i, "virtio") - dparams[i] = {"rng_model": rng_model} - dparams[i].update({"backend_model": params.get( - "backend_model_%s" % i, "random")}) - dparams[i].update({"rng_device": get_rng_device( - guest_arch, rng_model)}) - bk_type = params.get("backend_type_%s" % i) - if bk_type: - dparams[i].update({"backend_type": bk_type}) - bk_dev = params.get("backend_dev_%s" % i) - if bk_dev: - dparams[i].update({"backend_dev": bk_dev}) - bk_src = params.get("backend_source_%s" % i) - if bk_src: - dparams[i].update({"backend_source": bk_src}) - bk_pro = params.get("backend_protocol_%s" % i) - if bk_pro: - dparams[i].update({"backend_protocol": bk_pro}) - modify_rng_xml(dparams[i], False) - else: - params.update({"rng_device": get_rng_device( - guest_arch, params.get("rng_model", "virtio"))}) - - if detach_alias: - device_alias = "ua-" + str(uuid.uuid4()) - params.update({"rng_alias": device_alias}) - - rng_xml = modify_rng_xml(params, not test_snapshot, attach_rng) + if vm.is_alive(): + vm.destroy(gracefully=False) - if urandom: - device_alias = "ua-" + str(uuid.uuid4()) - params.update({"rng_alias": device_alias}) - rng_xml = modify_rng_xml(params, False, True) - vmxml.add_device(rng_xml) - vmxml.sync() + rng_xml = build_vm_xml() - # Add tcp random server - if random_source and params.get("backend_type") == "tcp" and not test_guest_dump: - cmd = "cat /dev/random | nc -4 -l localhost 1024" - bgjob = utils_misc.AsyncJob(cmd) - - if all([random_source, params.get("backend_type") == "udp", test_guest_dump]): - if not utils_package.package_install("socat"): - test.error("Failed to install socat on host") - cmd1 = "cat /dev/urandom|nc -l 127.0.0.1 1235" - bgjob = utils_misc.AsyncJob(cmd1) - cmd2 = "socat udp-listen:1234,reuseaddr,fork tcp:127.0.0.1:1235" - bgjob2 = utils_misc.AsyncJob(cmd2) + handle_egd_connect_mode() vm.start() - # Wait guest to enter boot stage - time.sleep(3) virsh.dumpxml(vm_name, "--xpath //rng", debug=True) + time.sleep(3) # Wait guest to enter boot stage - if attach_rng: - ret = virsh.attach_device(vm_name, rng_xml.xml, - flagstr=attach_options, - wait_remove_event=True, - debug=True, ignore_status=True) - libvirt.check_exit_status(ret, status_error) - if status_error: - return - if not check_rng_xml(rng_xml, True): - test.fail("Can not find rng device in xml") - else: - # Start the VM. - if start_error: - test.fail("VM started unexpectedly") + if "pass_test_on_error" == handle_hotplug(): + return - # Feed the tcp random device some data - if test_guest_dump and params.get("backend_type") == "tcp": - cmd = "cat /dev/random | nc -4 localhost 1024" - bgjob = utils_misc.AsyncJob(cmd) + handle_egd_bind_mode() if test_qemu_cmd and not attach_rng: if device_num > 1: @@ -647,22 +774,22 @@ def rotate_audit_log(): if test_host: check_host() if test_audit: - libvirt.check_logfile(expected_audit_message, - audit_log_file) + libvirt.check_logfile(expected_audit_message, audit_log_file) session = vm.wait_for_login() if test_guest: check_guest(session, set_virtio_current=set_virtio_current) if test_guest_dump: check_guest_dump(session, True) if test_snapshot: - check_snapshot(bgjob) + check_snapshot() if urandom: check_rng_xml(rng_xml, True) if detach_alias: - result = virsh.detach_device_alias(vm_name, device_alias, - detach_alias_options, debug=True) + result = virsh.detach_device_alias( + vm_name, params.get("rng_alias"), detach_alias_options, debug=True + ) if "--config" in detach_alias_options: vm.destroy() @@ -680,11 +807,17 @@ def have_rng_xml(): # Detach after attach if attach_rng: - ret = virsh.detach_device(vm_name, rng_xml.xml, - flagstr=attach_options, - debug=True, ignore_status=True) + ret = virsh.detach_device( + vm_name, + rng_xml.xml, + flagstr=attach_options, + debug=True, + ignore_status=True, + ) libvirt.check_exit_status(ret, status_error) - if utils_misc.wait_for(lambda: check_rng_xml(rng_xml, False), wait_timeout): + if utils_misc.wait_for( + lambda: check_rng_xml(rng_xml, False), wait_timeout + ): logging.info("Find same rng xml as hotpluged") else: test.fail("Rng device still exists after detach!") @@ -697,17 +830,11 @@ def have_rng_xml(): session.close() except virt_vm.VMStartError as details: logging.info(str(details)) - if not start_error: - test.fail('VM failed to start, ' - 'please refer to https://bugzilla.' - 'redhat.com/show_bug.cgi?id=1220252:' - '\n%s' % details) except xcepts.LibvirtXMLError as details: logging.info(str(details)) details = str(details).replace("\n", "") if not re.match(expected_create_error, details): - test.fail("Didn't match expected error:" - " %s" % expected_create_error) + test.fail("Didn't match expected error: %s" % expected_create_error) finally: # Delete snapshots. snapshot_lists = virsh.snapshot_list(vm_name, debug=True) @@ -724,7 +851,5 @@ def have_rng_xml(): vm.destroy(gracefully=False) logging.info("Restoring vm...") vmxml_backup.sync() - if bgjob2: - bgjob2.kill_func() - if bgjob: - bgjob.kill_func() + for job in background_jobs: + job.kill_func() diff --git a/spell.ignore b/spell.ignore index 12c425d7c84..205ad637e84 100644 --- a/spell.ignore +++ b/spell.ignore @@ -267,6 +267,7 @@ dzheng ebtables efi eg +egd els embeddedqemu emulatorbin @@ -384,7 +385,9 @@ hostfile hostname hostnuma hotplug +hotplugs Hotplug +Hotplugs hotpluggable hotplugged Hotplugged @@ -1101,6 +1104,7 @@ upadte Updae uperf uptime +urandom uri URI uris From 8e62241ef758a9e27617a567df289d72a5c350c0 Mon Sep 17 00:00:00 2001 From: Fangge Jin Date: Thu, 12 Dec 2024 11:46:12 +0800 Subject: [PATCH 0738/1055] set-user-password: Refine the code logic 1. Remove the code of logging in guest with old password as it is meaningless 2. Move the restore vm logic to finally block Signed-off-by: Fangge Jin --- .../domain/virsh_set_user_password.py | 34 ++++--------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_set_user_password.py b/libvirt/tests/src/virsh_cmd/domain/virsh_set_user_password.py index 94794fbfcd7..96921ec4944 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_set_user_password.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_set_user_password.py @@ -92,26 +92,13 @@ def run(test, params, env): logging.debug(e) test.fail("Failed to login with new password") - # Login with old password - try: - session = remote.wait_for_login("ssh", vm_ip, "22", set_user_name, ori_passwd, - r"[\#\$]\s*$", timeout=10) - session.close() - except remote.LoginAuthenticationError: - logging.debug("Login with old password failed as expected.") - - # Change the password back in VM - ret = virsh.set_user_password(vm_name, set_user_name, ori_passwd, False, - option=option, debug=True) - libvirt.check_exit_status(ret) - - # Login with the original password - try: - session = remote.wait_for_login("ssh", vm_ip, "22", set_user_name, ori_passwd, - r"[\#\$]\s*$", timeout=30) - session.close() - except remote.LoginAuthenticationError as e: - logging.debug(e) + finally: + # Recover VM + if vm.is_alive(): + # always restore root password in case previously case execution is broken + if status_error != "yes": + virsh.set_user_password(vm_name, set_user_name, ori_passwd, False, + option=option, debug=True) if start_ga: # Stop guest agent in vm @@ -126,12 +113,5 @@ def run(test, params, env): test.error("Deleting user '%s' got failed: '%s'" % (set_user_name, output)) session.close() - finally: - # Recover VM - if vm.is_alive(): - # always restore root password in case previously case execution is broken - if status_error != "yes": - virsh.set_user_password(vm_name, set_user_name, ori_passwd, False, - option=option, debug=True) vm.destroy(gracefully=False) vmxml_bak.sync() From 95e26736f2787260022c155f58615905666d0716 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Fri, 13 Dec 2024 05:00:36 -0500 Subject: [PATCH 0739/1055] update_iface_with_unchangable: remove rom for s390x On s390x ROM not available. Remove from config. Signed-off-by: Sebastian Mitterle --- .../update_device/update_iface_with_unchangable.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_unchangable.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_unchangable.cfg index 8eb2748953a..95e8d02da6e 100644 --- a/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_unchangable.cfg +++ b/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_unchangable.cfg @@ -17,3 +17,5 @@ iface_attrs_tune = {'sndbuf': 1600} iface_attrs_alias = {'name': 'ua-823c76fa-ee1d-4278-a613-2ba8ba179b61'} update_attrs = {'link_state': 'down'} + s390-virtio: + iface_attrs_rom = {} From f97afd391767ad024bd15943fa94dd6488d25ad9 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Fri, 13 Dec 2024 07:06:00 -0500 Subject: [PATCH 0740/1055] virtual_network/link_state: configure host_iface for all tests ethernet was missing host-iface and failed move the parameter to the top to apply it to all tests Signed-off-by: Sebastian Mitterle --- .../cfg/virtual_network/link_state/link_state_model_type.cfg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/link_state/link_state_model_type.cfg b/libvirt/tests/cfg/virtual_network/link_state/link_state_model_type.cfg index 2a5e6d1694b..4b3aefe0057 100644 --- a/libvirt/tests/cfg/virtual_network/link_state/link_state_model_type.cfg +++ b/libvirt/tests/cfg/virtual_network/link_state/link_state_model_type.cfg @@ -4,6 +4,7 @@ timeout = 240 outside_ip = "www.redhat.com" vm_ping_outside = pass + host_iface = variants: - initial_up: initial_link_state = "up" @@ -24,7 +25,6 @@ iface_base_attrs = {"type_name": "network", "source": {"network": "default"}} - direct: only virtio - host_iface = iface_base_attrs = {"type_name": "direct", "source": {"dev": host_iface, "mode": "bridge"}} - user: only virtio @@ -32,7 +32,6 @@ - root: iface_base_attrs = {"type_name": "user"} - passt: - host_iface = iface_base_attrs = {"backend": {"type": "passt"}, "source": {"dev": host_iface}, "type_name": "user"} variants: - root: From 2651cbfb5433f80c7473b30e70544d54c9c40929 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Fri, 13 Dec 2024 07:46:21 -0500 Subject: [PATCH 0741/1055] migration: disable test with vtpm No vTPM on s390x. Disable tests. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/migration/migrate_options_shared.cfg | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libvirt/tests/cfg/migration/migrate_options_shared.cfg b/libvirt/tests/cfg/migration/migrate_options_shared.cfg index 92db677aa84..2709a2f2647 100644 --- a/libvirt/tests/cfg/migration/migrate_options_shared.cfg +++ b/libvirt/tests/cfg/migration/migrate_options_shared.cfg @@ -319,6 +319,7 @@ actions_after_migration = "save_restore" actions_during_migration = "setmaxdowntime,setmigratepostcopy" - vtpm_emulator: + no s390-virtio tpm_args = "{"tpm_model": "tpm-crb", "backend_type": "emulator", "backend_version": "2.0"}" pseries: tpm_args = "{"tpm_model": "tpm-spapr", "backend_type": "emulator", "backend_version": "2.0"}" @@ -453,6 +454,7 @@ server_cn = "test.com.cn" virsh_migrate_extra = "--tls --tls-destination ${server_cn}" - vtpm_emulator: + no s390-virtio only without_postcopy tpm_args = "{"tpm_model": "tpm-crb", "backend_type": "emulator", "backend_version": "2.0"}" update_tpm_secret = yes @@ -487,6 +489,7 @@ virsh_migrate_options = "--live --p2p --tunnelled --verbose" variants: - vtpm_emulator: + no s390-virtio tpm_args = "{"tpm_model": "tpm-crb", "backend_type": "emulator", "backend_version": "2.0"}" update_tpm_secret = yes src_secret_value = "sec value test" @@ -545,6 +548,7 @@ client_cn = "ENTER.YOUR.CLIENT_CN" disable_verify_peer = "yes" - vtpm_emulator: + no s390-virtio only without_postcopy tpm_args = "{"tpm_model": "tpm-crb", "backend_type": "emulator", "backend_version": "2.0"}" update_tpm_secret = yes From 1261ac130025e53be37c84de33aa02f9cfd1ae9f Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Fri, 13 Dec 2024 08:15:04 -0500 Subject: [PATCH 0742/1055] migrate_vm: disable negative test The test creates an unbootable disk. On s390x, the VM will immediately stop running. So, the rest of the test steps can't execute. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/migration/migrate_vm.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/cfg/migration/migrate_vm.cfg b/libvirt/tests/cfg/migration/migrate_vm.cfg index 646c8a44789..da305753fd2 100644 --- a/libvirt/tests/cfg/migration/migrate_vm.cfg +++ b/libvirt/tests/cfg/migration/migrate_vm.cfg @@ -751,6 +751,7 @@ virsh_options = "--live --verbose --copy-storage-inc" err_msg = "error: Operation not supported: pre-creation of storage targets for incremental storage migration is not supported|error: Operation not supported: pre-creation of storage target.*for incremental storage migration of .* is not supported" - backing_file_with_copy_storage_inc: + no s390-virtio create_target_image = "no" setup_nfs = "yes" enable_virt_use_nfs = "yes" From 04bb0dfb35ab37071f99aeaf0a70a4adbf55a92e Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Thu, 19 Sep 2024 01:21:25 -0400 Subject: [PATCH 0743/1055] Add new image type:vdh and gce support in bootc image builder vdh and gce are newly introduced support disk image type, and are only supported on upstream Signed-off-by: chunfuwen --- .../bootc_image_build_utils.py | 503 +++++++++++++++++- .../bootc_disk_image_build.cfg | 111 +++- .../bootc_disk_image_install.cfg | 105 +++- .../bootc_disk_image_build.py | 33 +- .../bootc_disk_image_install.py | 38 +- 5 files changed, 719 insertions(+), 71 deletions(-) diff --git a/provider/bootc_image_builder/bootc_image_build_utils.py b/provider/bootc_image_builder/bootc_image_build_utils.py index 5d369fbd46d..0439842a76e 100644 --- a/provider/bootc_image_builder/bootc_image_build_utils.py +++ b/provider/bootc_image_builder/bootc_image_build_utils.py @@ -14,6 +14,7 @@ import os import random import shutil +import subprocess import time import textwrap import pathlib @@ -65,13 +66,16 @@ def podman_command_build(bib_image_url, disk_image_type, image_ref, config=None, os.makedirs("/var/lib/libvirt/images/output") cmd = "sudo podman run --rm -it --privileged --pull=newer --security-opt label=type:unconfined_t -v /var/lib/libvirt/images/output:/output" if config: - cmd += " -v %s:/config.json " % config + if "toml" in config: + cmd += " -v %s:/config.toml " % config + else: + cmd += " -v %s:/config.json " % config if local_container: cmd += " -v /var/lib/containers/storage:/var/lib/containers/storage " if options is not None: - cmd += " -v %s:/run/containers/0/auth.json " % options + cmd += " %s " % options if key_store_mounted: cmd += " -v %s " % key_store_mounted @@ -83,7 +87,10 @@ def podman_command_build(bib_image_url, disk_image_type, image_ref, config=None, " --type %s --tls-verify=%s " % (bib_image_url, disk_image_type, tls_verify) if config: - cmd += " --config /config.json " + if "toml" in config: + cmd += " --config /config.toml " + else: + cmd += " --config /config.json " if target_arch: cmd += " --target-arch=%s " % target_arch @@ -173,6 +180,115 @@ def create_config_json_file(params): password = params.get("os_password") kickstart = "yes" == params.get("kickstart") public_key_path = os.path.join(os.path.expanduser("~/.ssh/"), "id_rsa.pub") + filesystem_size_set = "yes" == params.get("filesystem_size_set") + enable_lvm_disk_partitions = "yes" == params.get("enable_lvm_disk_partitions") + enable_plain_disk_partitions = "yes" == params.get("enable_plain_disk_partitions") + enable_btrf_disk_partitions = "yes" == params.get("enable_btrf_disk_partitions") + + filesystem_dict = {"filesystem": [ + { + "mountpoint": "/", + "minsize": "10 GiB" + }, + { + "mountpoint": "/var/data", + "minsize": "15 GiB" + } + ] + } + + enable_lvm_disk_partitions_dict = {"disk": { + "partitions": [ + { + "type": "plain", + "label": "data", + "minsize": "4 GiB", + "fs_type": "xfs", + "mountpoint": "/data" + }, + { + "type": "lvm", + "minsize": "15 GiB", + "name": "mainvg", + "logical_volumes": [ + { + "name": "rootlv", + "label": "root", + "minsize": "10 GiB", + "fs_type": "xfs", + "mountpoint": "/" + }, + { + "name": "swaplv", + "label": "swap", + "minsize": "1 GiB", + "fs_type": "swap" + }, + { + "name": "homelv", + "label": "home", + "minsize": "3 GiB", + "fs_type": "xfs", + "mountpoint": "/home" + }, + { + "name": "varloglv", + "label": "var", + "minsize": "2 GiB", + "fs_type": "xfs", + "mountpoint": "/var/log" + } + ] + } + ] + } + } + + enable_plain_disk_partitions_dict = {"disk": { + "partitions": [ + { + "type": "plain", + "label": "root", + "minsize": "10 GiB", + "minsize": "10 GiB", + "fs_type": "xfs", + "mountpoint": "/", + "minsize": "1 GiB", + "fs_type": "swap", + "minsize": "2 GiB", + "fs_type": "xfs", + "mountpoint": "/var/log" + } + ] + } + } + + enable_btrf_disk_partitions_dict = {"disk": { + "partitions": [ + { + "type": "plain", + "label": "swap", + "minsize": "4 GiB", + "fs_type": "swap" + }, + { + "type": "btrfs", + "minsize": "10 GiB", + "subvolumes": [ + { + "name": "root", + "mountpoint": "/" + }, + { + "name": "varlog", + "mountpoint": "/var/log" + } + ] + } + ] + } + } + if not os.path.exists(public_key_path): LOG.debug("public key doesn't exist, will help create one") key_gen_cmd = "ssh-keygen -q -t rsa -N '' <<< $'\ny' >/dev/null 2>&1" @@ -222,12 +338,104 @@ def create_config_json_file(params): } } + if enable_lvm_disk_partitions: + filesystem_size_set = False + cfg['blueprint']['customizations'].update(enable_lvm_disk_partitions_dict) + + if enable_plain_disk_partitions: + filesystem_size_set = False + cfg['blueprint']['customizations'].update(enable_plain_disk_partitions_dict) + + if enable_btrf_disk_partitions: + cfg['blueprint']['customizations'].update(enable_btrf_disk_partitions_dict) + + if filesystem_size_set: + cfg['blueprint']['customizations'].update(filesystem_dict) + LOG.debug("what is cfg:%s", cfg) config_json_path = pathlib.Path(folder) / "config.json" config_json_path.write_text(json.dumps(cfg), encoding="utf-8") return os.path.join(folder, "config.json") +def create_config_toml_file(params): + """ + create toml configuration file + + :param params: one dictionary to pass in configuration + """ + folder = params.get("config_file_path") + username = params.get("os_username") + password = params.get("os_password") + kickstart = "yes" == params.get("kickstart") + public_key_path = os.path.join(os.path.expanduser("~/.ssh/"), "id_rsa.pub") + filesystem_size_set = "yes" == params.get("filesystem_size_set") + filesystem_size_str = "" + fips_content = "" + + if not os.path.exists(public_key_path): + LOG.debug("public key doesn't exist, will help create one") + key_gen_cmd = "ssh-keygen -q -t rsa -N '' <<< $'\ny' >/dev/null 2>&1" + process.run(key_gen_cmd, shell=True, ignore_status=False) + + with open(public_key_path, 'r') as ssh: + key_value = ssh.read().rstrip() + + if filesystem_size_set: + filesystem_size_str = f""" + [[customizations.filesystem]] + mountpoint = "/" + minsize = "10 GiB" + + [[customizations.filesystem]] + mountpoint = "/var/data" + minsize = "20 GiB" + """ + if not kickstart: + container_file_content = f"""\n + [[customizations.user]] + name = "{username}" + password = "{password}" + key = "{key_value}" + groups = ["wheel"] + {filesystem_size_str} + [customizations.kernel] + append = "mitigations=auto,nosmt" + """ + else: + kick_start = {"contents": "user --name %s --password %s --groups wheel\n" + "rootpw --lock --iscrypted locked\n" + "sshkey --username %s \"%s\"\ntext --non-interactive\nzerombr\n" + "clearpart --all --initlabel --disklabel=gpt\nautopart --noswap --type=lvm\n" + "network --bootproto=dhcp --device=eno1 --activate --onboot=on\n reboot" % (username, password, username, key_value) + } + if params.get("fips_enable") == "yes": + fips_content = f""" + [customizations] + fips = true + """ + + container_file_content = f"""\n + [customizations.kernel] + append = "mitigations=auto,nosmt" + {fips_content} + [customizations.installer.modules] + enable = [ + "org.fedoraproject.Anaconda.Modules.Localization" + ] + disable = [ + "org.fedoraproject.Anaconda.Modules.Timezone" + ] + {filesystem_size_str} + [customizations.installer.kickstart] + contents = \"""{kick_start.get("contents")}\""" + """ + LOG.debug("what is toml content:%s", container_file_content) + config_toml_path = pathlib.Path(folder) / "config.toml" + config_toml_path.write_text(textwrap.dedent(container_file_content), encoding="utf8") + return os.path.join(folder, "config.toml") + + def create_auth_json_file(params): """ create authentication json configuration file @@ -235,18 +443,18 @@ def create_auth_json_file(params): :param params: one dictionary to pass in configuration """ folder = params.get("config_file_path") - redhat_registry = params.get("redhat_registry") - registry_key = params.get("registry_key") + redhat_stage_registry = params.get("redhat_stage_registry") + registry_stage_key = params.get("registry_stage_key") cfg = { "auths": { - "%s" % redhat_registry: { - "auth": "%s" % registry_key + "%s" % redhat_stage_registry: { + "auth": "%s" % registry_stage_key } } } - LOG.debug("what is auth cfg:%s", cfg) + LOG.debug("what is auth json:%s", cfg) config_json_path = pathlib.Path(folder) / "auth.json" config_json_path.write_text(json.dumps(cfg), encoding="utf-8") final_config_file = os.path.join(folder, "auth.json") @@ -279,9 +487,12 @@ def create_and_build_container_file(params): folder = params.get("container_base_folder") build_container = params.get("build_container") container_tag = params.get("container_url") + manifest = params.get("manifest") # clean up existed image clean_image_cmd = "sudo podman rmi %s" % container_tag + if manifest: + clean_image_cmd = "sudo podman manifest rm %s" % container_tag process.run(clean_image_cmd, shell=True, ignore_status=True) etc_config = '' dnf_vmware_tool = '' @@ -299,7 +510,7 @@ def create_and_build_container_file(params): "examples/-/raw/main/vmware/etc/vmware-tools/tools.conf > %s/tools.conf" % vmware_tool_path process.run(download_vmware_config_cmd, shell=True, verbose=True, ignore_status=True) - if params.get("fips_enable") == "yes": + if params.get("fips_enable") == "yes" and params.get("enable_fips_enable_repo") == "yes": dnf_fips_install = "RUN cat > /usr/lib/bootc/kargs.d/01-fips.toml <<'EOF'\n" \ "kargs = ['fips=1']\n" \ "match-architectures = ['x86_64']\n" \ @@ -308,8 +519,10 @@ def create_and_build_container_file(params): "update-crypto-policies --no-reload --set FIPS " container_path = pathlib.Path(folder) / "Containerfile_tmp" - shutil.copy("/etc/yum.repos.d/beaker-BaseOS.repo", folder) - shutil.copy("/etc/yum.repos.d/beaker-AppStream.repo", folder) + if os.path.exists("/etc/yum.repos.d/beaker-BaseOS.repo"): + shutil.copy("/etc/yum.repos.d/beaker-BaseOS.repo", folder) + if os.path.exists("/etc/yum.repos.d/beaker-AppStream.repo"): + shutil.copy("/etc/yum.repos.d/beaker-AppStream.repo", folder) create_sudo_file = "RUN echo '%wheel ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/wheel-passwordless-sudo" enable_root_ssh = "RUN echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config.d/01-permitrootlogin.conf" @@ -332,6 +545,9 @@ def create_and_build_container_file(params): if "rhel-9.5" in custom_repo: repo_path = pathlib.Path(folder) / "rhel-9.5.repo" repo_prefix = "rhel-9.5" + if "rhel-9.6" in custom_repo: + repo_path = pathlib.Path(folder) / "rhel-9.6.repo" + repo_prefix = "rhel-9.6" if "rhel-10.0" in custom_repo: repo_path = pathlib.Path(folder) / "rhel-10.0.repo" repo_prefix = "rhel-10.0" @@ -382,9 +598,16 @@ def create_and_build_container_file(params): {dnf_fips_install} Run dnf clean all """ + build_cmd = "sudo podman build -t %s -f %s" % (container_tag, str(container_path)) + if manifest: + container_file_content = f"""\n + FROM {build_container} + {create_sudo_file} + {enable_root_ssh} + """ + build_cmd = "sudo podman build --platform linux/arm64,linux/amd64 --manifest %s -f %s" % (manifest, str(container_path)) container_path.write_text(textwrap.dedent(container_file_content), encoding="utf8") - build_cmd = "sudo podman build -t %s -f %s" % (container_tag, str(container_path)) process.run(build_cmd, shell=True, ignore_status=False) @@ -774,8 +997,13 @@ def create_qemu_vm(params, env, test): vm = env.get_vm(vm_name) if vm.is_dead(): LOG.debug("VM is dead, starting") - vm.start() - ip_address = vm.wait_for_get_address(nic_index=0) + # workaround VM can not start in the first time on rhel10 + try: + vm.start() + except Exception as ex: + LOG.debug("start vm in retries") + vm.start() + ip_address = vm.wait_for_get_address(nic_index=0, timeout=120) params.update({"ip_address": ip_address.strip()}) remote_vm_obj = verify_ssh_login_vm(params) LOG.debug(f"ip addressis wcf: {ip_address}") @@ -814,7 +1042,9 @@ def prepare_aws_env(params): create_aws_secret_file(aws_secret_folder, aws_access_key_id, aws_access_key) aws_utils.create_aws_credentials_file(aws_access_key_id, aws_access_key) aws_utils.create_aws_config_file(aws_region) - aws_utils.install_aws_cli_tool(params) + vm_arch_name = params.get("vm_arch_name", "x86_64") + if "s390x" not in vm_arch_name: + aws_utils.install_aws_cli_tool(params) def cleanup_aws_env(params): @@ -838,6 +1068,249 @@ def cleanup_aws_ami_and_snapshot(params): aws_utils.delete_aws_ami_snapshot_id(params) +def convert_vhd_to_qcow2(params): + """ + Convert vhd disk format into qcow2 + + @param params: one dictionary wrapping various parameter + :return: Converted image path + """ + original_image_path = params.get('vm_disk_image_path') + converted_image_path = original_image_path.replace("vhd", "qcow2") + LOG.debug(f"converted vhd to qcow2 output is : {converted_image_path}") + + convert_cmd = f"qemu-img convert -p -f vpc -O qcow2 {original_image_path} {converted_image_path}" + process.run(convert_cmd, shell=True, verbose=True, ignore_status=False) + return converted_image_path + + +def untar_tgz_to_raw(params): + """ + extract image.tgz for GCP format to raw format:disk.raw + + @param params: one dictionary wrapping various parameter + """ + original_image_path = params.get('vm_disk_image_path') + tar_image_folder = os.path.dirname(original_image_path) + untar_image_path = os.path.join(tar_image_folder, "disk.raw") + LOG.debug(f"untar image.tgz to gce output is : {tar_image_folder}") + + tar_cmd = f"tar -xvzf {original_image_path} -C {tar_image_folder}" + process.run(tar_cmd, shell=True, verbose=True, ignore_status=False) + return untar_image_path + + +def check_bootc_image_version_id(params): + """ + check bootc image version id + + @param params: one dictionary wrapping various parameter + """ + expected_redhat_version_id = params.get("redhat_version_id") + if expected_redhat_version_id is None: + LOG.debug("don't need to check redhat version id") + else: + bootc_meta_info_dict = get_bootc_image_meta_info(params) + redhat_version_id = bootc_meta_info_dict.get("redhat.version-id") + compose_id = bootc_meta_info_dict.get("redhat.compose-id") + expected_compose_id = "RHEL-{}".format(expected_redhat_version_id) + if "-beta" in expected_compose_id: + expected_compose_id = expected_compose_id[0:expected_compose_id.index("-beta")] + if expected_redhat_version_id != redhat_version_id: + raise exceptions.TestFail(f"Expected redhat version id :{expected_redhat_version_id}, real version id is: {redhat_version_id}") + if expected_compose_id not in compose_id: + raise exceptions.TestFail(f"Expected compose id :{expected_compose_id}, real compose id is: {compose_id}") + + +def get_bootc_image_meta_info(params): + """ + get bootc image meta information + + @param params: one dictionary wrapping various parameter + """ + container_url = params.get('container_url') + cmd = "sudo skopeo inspect --retry-times=5 --tls-verify=false docker://%s |jq -r '.Labels'" % container_url + ret = process.run(cmd, timeout=40, verbose=True, ignore_status=True, shell=True).stdout_text + LOG.debug(f"skopeo inspect bootc image output is : {ret}") + + bootc_meta_info_dict = eval(ret) + return bootc_meta_info_dict + + +def create_registry_policy_file(params): + """ + create registry policy file + + @param params: one dictionary wrapping various parameter + """ + base_dir = params.get("config_file_path") + policy_file = os.path.join(base_dir, "policy.json") + pub_key_file = os.path.join(base_dir, "key.gpg") + local_registry = "localhost:5000" + + registry_policy = { + "default": [{"type": "insecureAcceptAnything"}], + "transports": { + "docker": { + f"{local_registry}": [ + { + "type": "signedBy", + "keyType": "GPGKeys", + "keyPath": f"{pub_key_file}" + } + ] + }, + "docker-daemon": { + "": [{"type": "insecureAcceptAnything"}] + } + } + } + + with open(policy_file, mode="w", encoding="utf-8") as f: + f.write(json.dumps(registry_policy)) + + +def create_lookaside_config_file(params): + """ + create look aside config file + + @param params: one dictionary wrapping various parameter + """ + base_dir = params.get("config_file_path") + lookaside_file = os.path.join(base_dir, "bib_lookaside.yaml") + lookaside_file_config = """ + docker: + localhost:5000: + lookaside: file:///var/lib/containers/sigstore + """ + with open(lookaside_file, mode="w", encoding="utf-8") as f: + f.write(lookaside_file_config) + + +def gpg_gen_key(params): + """ + generate gpg key + + @param params: one dictionary wrapping various parameter + """ + base_dir = params.get("config_file_path") + home_dir = f"{base_dir}/.gnupg" + pub_key_file = os.path.join(base_dir, "key.gpg") + if os.path.exists(home_dir): + return + + os.makedirs(home_dir, mode=0o700, exist_ok=False) + key_params = """ + %no-protection + Key-Type: RSA + Key-Length: 3072 + Key-Usage: sign + Name-Real: Bootc Image Builder Test usage + Name-Email: bib_test@redhat.com + Expire-Date: 0 + """ + email = "bib_test@redhat.com" + + subprocess.run( + ["gpg", "--gen-key", "--batch"], + check=True, capture_output=True, + env={"GNUPGHOME": home_dir}, + input=key_params, + text=True) + + subprocess.run( + ["gpg", "--output", pub_key_file, + "--armor", "--export", email], + check=True, capture_output=True, + env={"GNUPGHOME": home_dir}) + + +def retag_container_image_to_local_registry(params): + """ + re-tag the image to point it to our local registry + + @param params: one dictionary wrapping various parameter + """ + container_url = params.get('container_url') + pull_image_cmd = f"podman pull {container_url}" + process.run(pull_image_cmd, timeout=600, verbose=True, ignore_status=False, shell=True) + + index = container_url.index(":") + 1 + image_name = container_url[index:] + + delete_img_cmd = f"podman rmi localhost:5000/{image_name} -f " + process.run(delete_img_cmd, timeout=60, verbose=True, ignore_status=True, shell=True) + + cmd = f"podman tag {container_url} localhost:5000/{image_name}" + ret = process.run(cmd, timeout=40, verbose=True, ignore_status=False, shell=True).stdout_text + + list_image = "podman images localhost:5000/{image_name}" + ret = process.run(cmd, timeout=40, verbose=True, ignore_status=True, shell=True).stdout_text + LOG.debug(f"pomdman list image output is : {ret}") + return f"localhost:5000/{image_name}" + + +def ensure_registry(params): + """ + ensure registry is running + + @param params: one dictionary wrapping various parameter + """ + registry_container_name = subprocess.run([ + "podman", "ps", "-a", "--filter", "name=registry", "--format", "{{.Names}}" + ], check=True, capture_output=True).stdout.decode("utf-8").strip() + + if registry_container_name != "registry": + subprocess.run([ + "podman", "run", "-d", "-p", "5000:5000", "--restart", "always", "--name", "registry", "registry:2" + ], check=True, capture_output=True) + + registry_container_state = subprocess.run([ + "podman", "ps", "-a", "--filter", "name=registry", "--format", "{{.State}}" + ], check=True, capture_output=True).stdout.decode("utf-8").strip() + + if registry_container_state in ("paused", "exited"): + subprocess.run([ + "podman", "start", "registry" + ], check=True, capture_output=True) + time.sleep(20) + cmd = "podman ps" + output = process.run(cmd, timeout=40, verbose=True, ignore_status=True, shell=True).stdout_text + LOG.debug(f"pomdman list running container output is : {output}") + + +def sign_image(params): + """ + sign container image + + @param params: one dictionary wrapping various parameter + """ + gpg_gen_key(params) + ensure_registry(params) + local_registry_url = retag_container_image_to_local_registry(params) + create_registry_policy_file(params) + create_lookaside_config_file(params) + base_dir = params.get("config_file_path") + home_dir = f"{base_dir}/.gnupg" + email = "bib_test@redhat.com" + base_dir = params.get("config_file_path") + lookaside_file = os.path.join(base_dir, "bib_lookaside.yaml") + system_lookaside_conf_file = os.path.join( + "/etc/containers/registries.d", + os.path.basename(lookaside_file) + ) + shutil.copy(lookaside_file, system_lookaside_conf_file) + + subprocess.run([ + "podman", "push", + "--tls-verify=false", + "--sign-by", email, + f"{local_registry_url}", + ], check=True, capture_output=True, env={"GNUPGHOME": home_dir}) + os.unlink(system_lookaside_conf_file) + return local_registry_url + + def get_baseurl_from_repo_file(repo_file_path): """ One method to get compose url from current repository file diff --git a/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_build.cfg b/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_build.cfg index 5bd0b929cd1..3075aae8b08 100644 --- a/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_build.cfg +++ b/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_build.cfg @@ -1,6 +1,6 @@ - bootc_image_builder.bib.disk_image_generation: type = bootc_disk_image_build - only x86_64, aarch64 + only x86_64, aarch64, s390x, ppc64le start_vm = False take_regular_screendumps = "no" start_vm = "no" @@ -23,10 +23,14 @@ - use_config_json: os_username = "alice" os_password = "bob" + qcow..upstream_bib: + filesystem_size_set = "yes" anaconda-iso..upstream_bib..fedora_40: kickstart = "yes" - anaconda-iso..rhel_9.5_nightly_bib..local_image: + use_toml_config = "yes" + anaconda-iso..rhel_9.5_nightly_bib..local_image, anaconda-iso..rhel_9.6_nightly_bib..local_image: kickstart = "yes" + filesystem_size_set = "yes" - unuse_config_json: variants image_ref: - centos: @@ -34,15 +38,20 @@ - centos9: container_url = "quay.io/centos-bootc/centos-bootc:stream9" only use_config_json..tls_verify_disable + x86_64, aarch64: + anaconda-iso.upstream_bib: + signed_container = "yes" + local_container = "yes" - centos10: container_url = "quay.io/centos-bootc/centos-bootc:stream10" - only upstream_bib..use_config_json..tls_verify_enable, rhel_9.5_nightly_bib..use_config_json..tls_verify_enable, rhel_9.4_nightly_bib..use_config_json..tls_verify_enable + only upstream_bib..use_config_json..tls_verify_enable, rhel_9.5_nightly_bib..use_config_json..tls_verify_enable, rhel_9.6_nightly_bib..use_config_json..tls_verify_enable, rhel_9.4_nightly_bib..use_config_json..tls_verify_enable roofs = "xfs" rhel_9.4_nightly_bib..use_config_json..tls_verify_enable: roofs = "" - fedora: variants fedora_bootc_image: - fedora_40: + no s390-virtio only upstream_bib..tls_verify_enable ownership ="107:107" container_url = "quay.io/fedora/fedora-bootc:40" @@ -55,36 +64,61 @@ roofs = "xfs" raw..upstream_bib: roofs = "ext4" + enable_lvm_disk_partitions = "yes" + anaconda-iso..upstream_bib: + enable_plain_disk_partitions = "yes" + s390-virtio: + container_url = "quay.io/fedora/fedora-bootc:41" - local_image: container_base_folder = "/var/lib/libvirt/images" container_url = "localhost/bootc:eln" local_container = "yes" build_container = "registry.stage.redhat.io/rhel9/rhel-bootc:rhel-9.4" rhel_9.5_nightly_bib: - build_container = "registry.stage.redhat.io/rhel9/rhel-bootc:rhel-9.5" + build_container = "registry.stage.redhat.io/rhel9/rhel-bootc:9.5" + rhel_9.6_nightly_bib, upstream_bib: + build_container = "registry.stage.redhat.io/rhel9/rhel-bootc:9.6" rhel_10.0_bib: - build_container = "registry.stage.redhat.io/rhel10-beta/rhel-bootc:rhel-10.0-beta" + build_container = "registry.stage.redhat.io/rhel10/rhel-bootc:10.0" - rhel_9.4: - build_container = "registry.redhat.io/rhel9/rhel-bootc:9.4" + build_container = "registry.redhat.io/rhel9-eus/rhel-9.4-bootc:9.4" container_url = "quay.io/wenbaoxin/rhel9test" only rhel_9.4_bib + - rhel_9.5: + build_container = "registry.redhat.io/rhel9/rhel-bootc:9.5" + container_url = "quay.io/wenbaoxin/rhel9-rhel_bootc" + only rhel_9.5_bib - rhel_9.5_nightly: - container_url = "registry.stage.redhat.io/rhel9/rhel-bootc:rhel-9.5" + container_url = "registry.stage.redhat.io/rhel9/rhel-bootc:9.5" only rhel_9.5_nightly_bib + redhat_version_id = "9.5" + no anaconda-iso + - rhel_9.6_nightly: + container_url = "registry.stage.redhat.io/rhel9/rhel-bootc:9.6" + only rhel_9.6_nightly_bib + redhat_version_id = "9.6" no anaconda-iso - rhel_10.0_nightly: - container_url = "registry.stage.redhat.io/rhel10-beta/rhel-bootc:rhel-10.0-beta" + container_url = "registry.stage.redhat.io/rhel10/rhel-bootc:10.0" enable_tls_verify = "false" + redhat_version_id = "10.0" only rhel_10.0_bib no anaconda-iso - cross_build: - container_url = "quay.io/centos-bootc/centos-bootc:stream9" + local_container = "yes" + manifest = "manifest-test" + container_base_folder = "/var/lib/libvirt/images" + build_container = "quay.io/centos-bootc/centos-bootc-dev:stream9" + container_url = "localhost/manifest-test" target_arch = "aarch64" + roofs = "btrfs" + enable_btrf_disk_partitions = "yes" + filesystem_size_set = "no" only qcow..upstream_bib..use_config_json..tls_verify_enable variants bib_ref: - upstream_bib: - registry_key = "example_stage_key" - redhat_registry = "registry.stage.redhat.io" + registry_stage_key = "example_stage_key" + redhat_stage_registry = "registry.stage.redhat.io" bib_image_url = "quay.io/centos-bootc/bootc-image-builder:latest" podman_stage_username = "11009103|stage" podman_stage_password = "example_stage_password" @@ -100,9 +134,9 @@ anaconda-iso..rhel_9.4: custom_repo = "rhel-9.4.repo" - rhel_9.4_nightly_bib: - registry_key = "example_stage_key" - redhat_registry = "registry.stage.redhat.io" - bib_image_url = "registry.stage.redhat.io/rhel9/bootc-image-builder:rhel-9.4" + registry_stage_key = "example_stage_key" + redhat_stage_registry = "registry.stage.redhat.io" + bib_image_url = "registry.stage.redhat.io/rhel9/bootc-image-builder:9.4" key_store_mounted = "/etc/pki:/etc/pki" podman_stage_username = "11009103|stage" podman_stage_password = "example_stage_password" @@ -110,20 +144,41 @@ custom_repo = "rhel-9.4.repo" compose_url = "example_compose_url" no cross_build + - rhel_9.5_bib: + podman_redhat_username = "podman_redhat_username" + podman_redhat_password = "podman_redhat_password" + redhat_registry = "registry.redhat.io" + container_base_folder = "/var/lib/libvirt/images" + bib_image_url = "registry.redhat.io/rhel9/bootc-image-builder:9.5" + podman_quay_username = "podman_quay_username" + podman_quay_password = "podman_quay_password" + only rhel_9.5..use_config_json..tls_verify_enable + anaconda-iso..rhel_9.5: + custom_repo = "rhel-9.5.repo" - rhel_9.5_nightly_bib: - registry_key = "example_stage_key" - redhat_registry = "registry.stage.redhat.io" - bib_image_url = "registry.stage.redhat.io/rhel9/bootc-image-builder:rhel-9.5" + registry_stage_key = "example_stage_key" + redhat_stage_registry = "registry.stage.redhat.io" + bib_image_url = "registry.stage.redhat.io/rhel9/bootc-image-builder:9.5" key_store_mounted = "/etc/pki:/etc/pki" podman_stage_username = "11009103|stage" podman_stage_password = "example_stage_password" anaconda-iso..local_image: custom_repo = "rhel-9.5.repo" compose_url = "example_compose_url" + - rhel_9.6_nightly_bib: + registry_stage_key = "example_stage_key" + redhat_stage_registry = "registry.stage.redhat.io" + bib_image_url = "registry.stage.redhat.io/rhel9/bootc-image-builder:9.6" + key_store_mounted = "/etc/pki:/etc/pki" + podman_stage_username = "11009103|stage" + podman_stage_password = "example_stage_password" + anaconda-iso..local_image: + custom_repo = "rhel-9.6.repo" + compose_url = "example_compose_url" - rhel_10.0_bib: - registry_key = "example_stage_key" - redhat_registry = "registry.stage.redhat.io" - bib_image_url = "registry.stage.redhat.io/rhel10-beta/bootc-image-builder:rhel-10.0-beta" + registry_stage_key = "example_stage_key" + redhat_stage_registry = "registry.stage.redhat.io" + bib_image_url = "registry.stage.redhat.io/rhel10/bootc-image-builder:10.0" key_store_mounted = "/etc/pki:/etc/pki" podman_stage_username = "11009103|stage" podman_stage_password = "example_stage_password" @@ -133,6 +188,7 @@ variants: - ami: disk_image_type = "ami" + no s390-virtio output_sub_folder = "image" output_name = "disk.raw" aws_secret_folder = "/var/lib/libvirt/images" @@ -140,7 +196,7 @@ aws_access_key = "example_aws_access_key" aws_region = "us-east-1" aws_ami_name = "build_${bib_ref}-${image_ref}-component-bootc-${disk_image_type}" - use_config_json..tls_verify_enable: + rhel_9.5_nightly_bib..use_config_json..tls_verify_enable, rhel_9.5_nightly_bib..use_config_json..tls_verify_enable, upstream_bib.centos.centos10.use_config_json.tls_verify_enable: aws_config_dict = "{'aws.secrets':'${aws_secret_folder}/aws.secrets','aws_ami_name':'${aws_ami_name}','aws_bucket':'bib-component-test','aws_region':'${aws_region}'}" - qcow: disk_image_type = "qcow2" @@ -150,6 +206,7 @@ disk_image_type = "vmdk" output_sub_folder = "vmdk" output_name = "disk.vmdk" + no s390-virtio - anaconda-iso: disk_image_type = "anaconda-iso" output_sub_folder = "bootiso" @@ -158,3 +215,15 @@ disk_image_type = "raw" output_sub_folder = "image" output_name = "disk.raw" + - vhd: + disk_image_type = "vhd" + output_sub_folder = "vpc" + output_name = "disk.vhd" + no s390-virtio + only upstream_bib, rhel_9.5_nightly_bib + - gce: + disk_image_type = "gce" + output_sub_folder = "gce" + output_name = "image.tar.gz" + no s390-virtio + only upstream_bib, rhel_9.5_nightly_bib diff --git a/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_install.cfg b/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_install.cfg index 800f6f1fad8..1613de8fbfd 100644 --- a/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_install.cfg +++ b/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_install.cfg @@ -1,6 +1,6 @@ - bootc_image_builder.bib.disk_image_install: type = bootc_disk_image_install - only x86_64, aarch64 + only x86_64, aarch64, s390x, ppc64le start_vm = False take_regular_screendumps = "no" start_vm = "no" @@ -36,9 +36,11 @@ variants centos_bootc_image: - centos9: container_url = "quay.io/centos-bootc/centos-bootc:stream9" + only bios - centos10: container_url = "quay.io/centos-bootc/centos-bootc:stream10" - only upstream_bib, rhel_9.5_nightly_bib, rhel_9.4_nightly_bib + only efi + only upstream_bib, rhel_9.5_nightly_bib, rhel_9.6_nightly_bib, rhel_9.4_nightly_bib roofs = "ext4" rhel_9.4_nightly_bib: roofs = "" @@ -46,20 +48,27 @@ variants fedora_bootc_image: - fedora_40: only upstream_bib + only bios container_url = "quay.io/fedora/fedora-bootc:40" roofs = "ext4" qcow..upstream_bib: roofs = "xfs" anaconda-iso..upstream_bib: kickstart = "yes" + raw..upstream_bib: + filesystem_size_set = "yes" + no s390-virtio - fedora_latest: only upstream_bib + only efi container_url = "quay.io/fedora/fedora-bootc:latest" roofs = "xfs" raw..upstream_bib: roofs = "ext4" + s390-virtio: + container_url = "quay.io/fedora/fedora-bootc:41" - rhel_9.4: - build_container = "registry.redhat.io/rhel9/rhel-bootc:9.4" + build_container = "registry.redhat.io/rhel9-eus/rhel-9.4-bootc:9.4" container_url = "quay.io/wenbaoxin/rhel9test" only rhel_9.4_bib - local_image: @@ -68,24 +77,43 @@ local_container = "yes" build_container = "registry.stage.redhat.io/rhel9/rhel-bootc:rhel-9.4" rhel_9.5_nightly_bib: - build_container = "registry.stage.redhat.io/rhel9/rhel-bootc:rhel-9.5" + build_container = "registry.stage.redhat.io/rhel9/rhel-bootc:9.5" + fips_enable = "yes" + enable_fips_enable_repo = "yes" + rhel_9.6_nightly_bib, upstream_bib: + build_container = "registry.stage.redhat.io/rhel9/rhel-bootc:9.6" fips_enable = "yes" + enable_fips_enable_repo = "yes" + anaconda-iso..upstream_bib, anaconda-iso..rhel_9.5_nightly_bib: + fips_enable = "yes" + use_toml_config = "yes" + kickstart = "yes" + enable_fips_enable_repo = "no" rhel_10.0_bib: - build_container = "registry.stage.redhat.io/rhel10-beta/rhel-bootc:rhel-10.0-beta" + build_container = "registry.stage.redhat.io/rhel10/rhel-bootc:10.0" + - rhel_9.5: + build_container = "registry.redhat.io/rhel9/rhel-bootc:9.5" + container_url = "quay.io/wenbaoxin/rhel9-rhel_bootc" + only rhel_9.5_bib - rhel_9.5_nightly: - container_url = "registry.stage.redhat.io/rhel9/rhel-bootc:rhel-9.5" + container_url = "registry.stage.redhat.io/rhel9/rhel-bootc:9.5" enable_tls_verify = "false" only rhel_9.5_nightly_bib no anaconda-iso + - rhel_9.6_nightly: + container_url = "registry.stage.redhat.io/rhel9/rhel-bootc:9.6" + enable_tls_verify = "false" + only rhel_9.6_nightly_bib + no anaconda-iso - rhel_10.0_nightly: - container_url = "registry.stage.redhat.io/rhel10-beta/rhel-bootc:rhel-10.0-beta" + container_url = "registry.stage.redhat.io/rhel10/rhel-bootc:10.0" enable_tls_verify = "false" only rhel_10.0_bib no anaconda-iso variants bib_ref: - upstream_bib: - registry_key = "example_stage_key" - redhat_registry = "registry.stage.redhat.io" + registry_stage_key = "example_stage_key" + redhat_stage_registry = "registry.stage.redhat.io" bib_image_url = "quay.io/centos-bootc/bootc-image-builder:latest" podman_stage_username = "11009103|stage" podman_stage_password = "example_stage_password" @@ -101,29 +129,50 @@ custom_repo = "rhel-9.4.repo" only rhel_9.4 - rhel_9.4_nightly_bib: - registry_key = "example_stage_key" - redhat_registry = "registry.stage.redhat.io" - bib_image_url = "registry.stage.redhat.io/rhel9/bootc-image-builder:rhel-9.4" + registry_stage_key = "example_stage_key" + redhat_stage_registry = "registry.stage.redhat.io" + bib_image_url = "registry.stage.redhat.io/rhel9/bootc-image-builder:9.4" key_store_mounted = "/etc/pki:/etc/pki" podman_stage_username = "11009103|stage" podman_stage_password = "example_stage_password" anaconda-iso..local_image: custom_repo = "rhel-9.4.repo" compose_url = "example_compose_url" + - rhel_9.5_bib: + podman_redhat_username = "11080659|chwen" + podman_redhat_password = "podman_redhat_password" + redhat_registry = "registry.redhat.io" + container_base_folder = "/var/lib/libvirt/images" + bib_image_url = "registry.redhat.io/rhel9/bootc-image-builder:9.5" + podman_quay_username = "wenbaoxin" + podman_quay_password = "doudou303" + anaconda-iso..rhel_9.5: + custom_repo = "rhel-9.5.repo" + only rhel_9.5 - rhel_9.5_nightly_bib: - registry_key = "example_stage_key" - redhat_registry = "registry.stage.redhat.io" - bib_image_url = "registry.stage.redhat.io/rhel9/bootc-image-builder:rhel-9.5" + registry_stage_key = "example_stage_key" + redhat_stage_registry = "registry.stage.redhat.io" + bib_image_url = "registry.stage.redhat.io/rhel9/bootc-image-builder:9.5" key_store_mounted = "/etc/pki:/etc/pki" podman_stage_username = "11009103|stage" podman_stage_password = "example_stage_password" anaconda-iso..local_image: custom_repo = "rhel-9.5.repo" compose_url = "example_compose_url" + - rhel_9.6_nightly_bib: + registry_stage_key = "example_stage_key" + redhat_stage_registry = "registry.stage.redhat.io" + bib_image_url = "registry.stage.redhat.io/rhel9/bootc-image-builder:9.6" + key_store_mounted = "/etc/pki:/etc/pki" + podman_stage_username = "11009103|stage" + podman_stage_password = "example_stage_password" + anaconda-iso..local_image: + custom_repo = "rhel-9.6.repo" + compose_url = "example_compose_url" - rhel_10.0_bib: - registry_key = "example_stage_key" - redhat_registry = "registry.stage.redhat.io" - bib_image_url = "registry.stage.redhat.io/rhel10-beta/bootc-image-builder:rhel-10.0-beta" + registry_stage_key = "example_stage_key" + redhat_stage_registry = "registry.stage.redhat.io" + bib_image_url = "registry.stage.redhat.io/rhel10/bootc-image-builder:10.0" key_store_mounted = "/etc/pki:/etc/pki" podman_stage_username = "11009103|stage" podman_stage_password = "example_stage_password" @@ -133,6 +182,7 @@ variants: - ami: disk_image_type = "ami" + no s390-virtio output_sub_folder = "image" output_name = "disk.raw" aws_secret_folder = "/var/lib/libvirt/images" @@ -145,7 +195,11 @@ aws_vpc_id = "example_vpc" aws_subnet_id = "example_subnet" aws_config_dict = "{'aws.secrets':'${aws_secret_folder}/aws.secrets','aws_ami_name':'${aws_ami_name}','aws_bucket':'bib-component-test','aws_region':'${aws_region}'}" - rhel_9.5_nightly_bib..centos.centos9, rhel_9.5_nightly_bib..fedora_eln, rhel_9.5_nightly_bib..local_image: + rhel_9.5_nightly_bib..centos.centos9, rhel_9.5_nightly_bib..local_image: + aws_config_dict = {} + rhel_9.6_nightly_bib..centos.centos9, rhel_9.6_nightly_bib..local_image: + aws_config_dict = {} + upstream_bib..centos, upstream_bib..local_image, upstream_bib..fedora.fedora_40: aws_config_dict = {} - qcow: disk_image_type = "qcow2" @@ -155,6 +209,7 @@ disk_image_type = "vmdk" output_sub_folder = "vmdk" output_name = "disk.vmdk" + no s390-virtio local_image: add_vmware_tool = "yes" rhel_9.4: @@ -168,3 +223,15 @@ disk_image_type = "raw" output_sub_folder = "image" output_name = "disk.raw" + - vhd: + disk_image_type = "vhd" + output_sub_folder = "vpc" + output_name = "disk.vhd" + no s390-virtio + only upstream_bib, rhel_9.5_nightly_bib + - gce: + disk_image_type = "gce" + output_sub_folder = "gce" + output_name = "image.tar.gz" + no s390-virtio + only upstream_bib, rhel_9.5_nightly_bib diff --git a/virttools/tests/src/bootc_image_builder/bootc_disk_image_build.py b/virttools/tests/src/bootc_image_builder/bootc_disk_image_build.py index 7fe6ebe5c3e..17a9ad54a6d 100644 --- a/virttools/tests/src/bootc_image_builder/bootc_disk_image_build.py +++ b/virttools/tests/src/bootc_image_builder/bootc_disk_image_build.py @@ -37,6 +37,8 @@ def validate_bib_output(params, test): if formatted_group_user != ownership: test.fail(f"The output folder:{base_folder} has wrong setting in group and user ids: {formatted_group_user}") + # bib_utils.check_bootc_image_version_id(params) + def prepare_env_and_execute_bib(params, test): """ @@ -52,10 +54,12 @@ def prepare_env_and_execute_bib(params, test): container_url = params.get("container_url") local_container = "yes" == params.get("local_container") build_container = params.get("build_container") + signed_container = "yes" == params.get("signed_container") enable_tls_verify = params.get("enable_tls_verify") config_json = params.get("config_json") config_json_file = None + use_toml_config = "yes" == params.get("use_toml_config") ownership = params.get("ownership") key_store_mounted = params.get("key_store_mounted") @@ -70,27 +74,42 @@ def prepare_env_and_execute_bib(params, test): bib_utils.install_bib_packages() if config_json == "use_config_json": - config_json_file = bib_utils.create_config_json_file(params) + if use_toml_config: + config_json_file = bib_utils.create_config_toml_file(params) + else: + config_json_file = bib_utils.create_config_json_file(params) if disk_image_type in ["ami"]: bib_utils.prepare_aws_env(params) - if bib_ref in ["upstream_bib", "rhel_9.4_nightly_bib", "rhel_9.5_nightly_bib", "rhel_10.0_bib"]: + if bib_ref in ["upstream_bib", "rhel_9.4_nightly_bib", "rhel_9.5_nightly_bib", "rhel_9.6_nightly_bib", "rhel_10.0_bib"]: auth_file = bib_utils.create_auth_json_file(params) - bib_utils.podman_login_with_auth(auth_file, params.get("redhat_registry")) - options = auth_file + bib_utils.podman_login_with_auth(auth_file, params.get("redhat_stage_registry")) + options = " -v %s:/run/containers/0/auth.json " % auth_file bib_utils.podman_login(params.get("podman_stage_username"), params.get("podman_stage_password"), - params.get("redhat_registry")) + params.get("redhat_stage_registry")) # pull base image and build local image after change if build_container: - if bib_ref == "rhel_9.4_bib": + if bib_ref in ["rhel_9.4_bib", "rhel_9.5_bib"]: bib_utils.podman_login(params.get("podman_redhat_username"), params.get("podman_redhat_password"), params.get("redhat_registry")) bib_utils.create_and_build_container_file(params) - if bib_ref == "rhel_9.4_bib": + + if bib_ref in ["rhel_9.4_bib", "rhel_9.5_bib"]: bib_utils.podman_push(params.get("podman_quay_username"), params.get("podman_quay_password"), params.get("registry"), container_url) + # sign the container image if needed + if signed_container: + LOG.debug(f"Begin sign container image: {container_url}") + container_url = bib_utils.sign_image(params) + LOG.debug(f"End sign container image: {container_url}") + if options is None: + options = " " + root_dir = params.get("config_file_path") + options += f" -v {root_dir}/policy.json:/etc/containers/policy.json -v {root_dir}/bib_lookaside.yaml:/etc/containers/registries.d/bib_lookaside.yaml " + options += f" -v /var/lib/containers/sigstore:/var/lib/containers/sigstore -v {root_dir}/key.gpg:{root_dir}key.gpg " + result = bib_utils.podman_command_build(bib_image_url, disk_image_type, container_url, config_json_file, local_container, enable_tls_verify, ownership, key_store_mounted, target_arch, roofs, options, **aws_config_dict) diff --git a/virttools/tests/src/bootc_image_builder/bootc_disk_image_install.py b/virttools/tests/src/bootc_image_builder/bootc_disk_image_install.py index 419555403ac..143fba94b36 100644 --- a/virttools/tests/src/bootc_image_builder/bootc_disk_image_install.py +++ b/virttools/tests/src/bootc_image_builder/bootc_disk_image_install.py @@ -9,6 +9,7 @@ import logging import re import os +import platform import shutil from virttest import virsh @@ -35,7 +36,8 @@ def update_bib_env_info(params, test): full_path = os.path.join(base_folder, output_sub_folder, output_name) if not os.path.exists(full_path): test.fail("bootc image build fail to generate outputs for image type: %s" % params.get("disk_image_type")) - converted_disk_image = f"install_{bib_ref}_{firmware}_{bib_utils.convert_disk_image_name(params)}" + special_chars = re.sub(r'[.,-]+', '', platform.release()) + converted_disk_image = f"install_{special_chars}_{bib_ref}_{firmware}_{bib_utils.convert_disk_image_name(params)}" disk_name, _ = os.path.splitext(converted_disk_image) full_path_dest = os.path.join(libvirt_base_folder, converted_disk_image) shutil.move(full_path, full_path_dest) @@ -45,6 +47,15 @@ def update_bib_env_info(params, test): params.update({'vm_disk_image_path': full_path_dest}) params.update({'vm_name_bootc': disk_name}) + if params.get("disk_image_type") == "vhd": + converted_image_from_vhd_qcow2 = bib_utils.convert_vhd_to_qcow2(params) + params.update({'vm_disk_image_path': converted_image_from_vhd_qcow2}) + + if params.get("disk_image_type") == "gce": + untar_raw_image = bib_utils.untar_tgz_to_raw(params) + params.update({'vm_disk_image_path': untar_raw_image}) + cleanup_files.append(untar_raw_image) + iso_install_path = os.path.join(libvirt_base_folder, f"{disk_name}_{firmware}.qcow2") params.update({'iso_install_path': iso_install_path}) cleanup_files.append(iso_install_path) @@ -71,26 +82,31 @@ def prepare_env_and_execute_bib(params, test): roofs = params.get("roofs") aws_config_dict = eval(params.get("aws_config_dict", '{}')) options = None + config_json_file = None + use_toml_config = "yes" == params.get("use_toml_config") bib_utils.install_bib_packages() - config_json_file = bib_utils.create_config_json_file(params) + if use_toml_config: + config_json_file = bib_utils.create_config_toml_file(params) + else: + config_json_file = bib_utils.create_config_json_file(params) if disk_image_type in ["ami"]: bib_utils.prepare_aws_env(params) - if bib_ref in ["upstream_bib", "rhel_9.4_nightly_bib", "rhel_9.5_nightly_bib", "rhel_10.0_bib"]: + if bib_ref in ["upstream_bib", "rhel_9.4_nightly_bib", "rhel_9.5_nightly_bib", "rhel_9.6_nightly_bib", "rhel_10.0_bib"]: auth_file = bib_utils.create_auth_json_file(params) - bib_utils.podman_login_with_auth(auth_file, params.get("redhat_registry")) - options = auth_file + bib_utils.podman_login_with_auth(auth_file, params.get("redhat_stage_registry")) + options = " -v %s:/run/containers/0/auth.json " % auth_file bib_utils.podman_login(params.get("podman_stage_username"), params.get("podman_stage_password"), - params.get("redhat_registry")) + params.get("redhat_stage_registry")) # pull base image and build local image after change if build_container: - if bib_ref == "rhel_9.4_bib": + if bib_ref in ["rhel_9.4_bib", "rhel_9.5_bib"]: bib_utils.podman_login(params.get("podman_redhat_username"), params.get("podman_redhat_password"), params.get("redhat_registry")) bib_utils.create_and_build_container_file(params) - if bib_ref == "rhel_9.4_bib": + if bib_ref in ["rhel_9.4_bib", "rhel_9.5_bib"]: ownership = None bib_utils.podman_push(params.get("podman_quay_username"), params.get("podman_quay_password"), params.get("registry"), container_url) @@ -128,7 +144,11 @@ def run(test, params, env): update_bib_env_info(params, test) if disk_image_type in ["vmdk"]: bib_utils.create_and_start_vmware_vm(params) - elif disk_image_type in ["qcow2", "raw", "anaconda-iso"]: + elif disk_image_type in ["qcow2", "raw", "anaconda-iso", "vhd", "gce"]: + # clean up dirty VM if existed + vm_name = params.get("vm_name_bootc") + if vm_name and vm_name in virsh.dom_list().stdout_text: + virsh.undefine(vm_name, options="--nvram", ignore_status=True) bib_utils.create_qemu_vm(params, env, test) elif disk_image_type in ["ami"]: if len(aws_config_dict) != 0: From 4037fbe7d060dcf584f6cc369537cf03a0851e03 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 16 Dec 2024 09:20:13 -0500 Subject: [PATCH 0744/1055] ethernet_interface: fix color code on RHEL 10.0 ip command might print color codes causing comparison to fail. Use new json option to avoid. Signed-off-by: Sebastian Mitterle --- .../connectivity/connectivity_check_ethernet_interface.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py index 2227eabd9dc..ec7ec55caae 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py @@ -60,7 +60,7 @@ def run(test, params, env): outside_ip = params.get('outside_ip') host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True).split()[0] host_ip = utils_net.get_ip_address_by_interface(host_iface, ip_ver='ipv4') status_error = 'yes' == params.get('status_error', 'no') err_msg = params.get('err_msg') @@ -125,7 +125,7 @@ def run(test, params, env): 'outside_ip': outside_ip, 'host_public_ip': host_ip, } - vm_default_gw = utils_net.get_default_gateway(session=session) + vm_default_gw = utils_net.get_default_gateway(session=session, json=True) if iface_amount == 'two_ifaces': ping_params = { From 8274c124ceb7825dcc68100ea24f81e58ff5309a Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Fri, 13 Dec 2024 02:25:57 -0500 Subject: [PATCH 0745/1055] Update the expectation for libvirt_guests If there is no "on_boot" setting in libvirt_guests.conf, the behavior will be the same with "on_boot=start" for running VM. Refer to libvirt.org: "By default, libvirt-guests will suspend running guests when the host shuts down, and restore them to their pre-shutdown state when the host reboots." Signed-off-by: Yalan Zhang --- .../sysconfig_libvirt_guests/libvirt_guests.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/src/daemon/conf_file/sysconfig_libvirt_guests/libvirt_guests.py b/libvirt/tests/src/daemon/conf_file/sysconfig_libvirt_guests/libvirt_guests.py index 995f592aa10..058d53ffa73 100644 --- a/libvirt/tests/src/daemon/conf_file/sysconfig_libvirt_guests/libvirt_guests.py +++ b/libvirt/tests/src/daemon/conf_file/sysconfig_libvirt_guests/libvirt_guests.py @@ -93,11 +93,11 @@ def chk_on_boot(status_error, on_boot): :param status_error: positive test if status_error is "no", otherwise negative test - :param on_boot: action taking on host booting + :param on_boot: action taking on host booting which set in the conf file """ if status_error == "no": - if on_boot == "start" or transient_vm: - for dom in vms: + if on_boot != "ignore": + for dom in active_persistent_vms: if not dom.is_alive(): test.fail("guest:%s should be running after " "restarting libvirt-guests." % dom.name) @@ -353,6 +353,11 @@ def transfer_to_transient(per_guest_name): process.run("cat /etc/sysconfig/libvirt-guests", shell=True) tail_messages = get_log() + # Before restart libvirt-guests, check the status of all VMs + active_persistent_vms = [] + for dom in vms: + if dom.is_alive and dom.is_persistent: + active_persistent_vms.append(dom) # Even though libvirt-guests was designed to operate guests when # host shutdown. The purpose can also be fulfilled by restart the # libvirt-guests service. From 4a29672fbe9dd30c40f1d77ceae58d90bb0203dd Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Tue, 17 Dec 2024 14:26:16 +0800 Subject: [PATCH 0746/1055] migrate_with_virtual_devices: fix rng check method As there might be other built-in rng devices, we only need to check if attached virtio rng is in rng_available. Signed-off-by: Dan Zheng --- .../src/migration/migrate_with_virtual_devices.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/src/migration/migrate_with_virtual_devices.py b/libvirt/tests/src/migration/migrate_with_virtual_devices.py index e85ba30e062..b7629a542ed 100644 --- a/libvirt/tests/src/migration/migrate_with_virtual_devices.py +++ b/libvirt/tests/src/migration/migrate_with_virtual_devices.py @@ -552,21 +552,21 @@ def check_rng_in_vm(vm, backend_type, rng_present): """ logging.debug("Check rng device in vm") - check_cmd = "dd if=/dev/hwrng of=/dev/null count=2 bs=2" + check_cmd = "cat /sys/devices/virtual/misc/hw_random/rng_available" timeout = 10 try: status, output = vm.session.cmd_status_output(check_cmd, timeout) - logging.debug("cmd exit status: %s, cmd output: %s", + logging.debug("cmd exit status: %s, current rng available: %s", status, output) - - if status == 0: + status = True if output.count("virtio_rng") else False + if status is True: if rng_present: return else: raise DeviceNotRemovedError("rng") else: - if not rng_present and "No such device" in output: + if not rng_present: return elif rng_present: raise DeviceNotFoundError("rng") From b6b80d86f1b4f63063c1c6b9e1ef15df27629fea Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 18 Dec 2024 09:55:53 +0800 Subject: [PATCH 0747/1055] migration: Update error message Signed-off-by: lcheng --- .../network_data_transport/tls_wrong_cert_configurations.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tls_wrong_cert_configurations.cfg b/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tls_wrong_cert_configurations.cfg index dd12dc4c481..ed1591a701d 100644 --- a/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tls_wrong_cert_configurations.cfg +++ b/libvirt/tests/cfg/migration_with_copy_storage/network_data_transport/tls_wrong_cert_configurations.cfg @@ -46,7 +46,7 @@ variants cert_configuration: - no_client_cert_on_src: cert_path = "${custom_pki_path}/client-cert.pem" - err_msg = "Cannot read from TLS channel: Software caused connection abort" + err_msg = "Cannot read from TLS channel:" - no_server_cert_on_target: cert_path = "${custom_pki_path}/server-cert.pem" err_msg = "unable to execute QEMU command 'object-add': Unable to access credentials ${cert_path}: No such file or directory" From 421b4fb8c3407942b05ee7976769fa1b48781aec Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 18 Dec 2024 10:41:02 +0800 Subject: [PATCH 0748/1055] migration: Fix authentication failed issue for ipv6 test Set 'server_info_ip' parameter to fix authentication failed issue. Signed-off-by: lcheng --- libvirt/tests/cfg/migration/migration_uri/migration_desturi.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/cfg/migration/migration_uri/migration_desturi.cfg b/libvirt/tests/cfg/migration/migration_uri/migration_desturi.cfg index 7b9e70d4a1c..ec3c5afd8cb 100644 --- a/libvirt/tests/cfg/migration/migration_uri/migration_desturi.cfg +++ b/libvirt/tests/cfg/migration/migration_uri/migration_desturi.cfg @@ -64,6 +64,7 @@ ipv6_config = "yes" ipv6_addr_des = "ENTER.YOUR.IPv6.DESTINATION" dest_host = "[${ipv6_addr_des}]" + server_info_ip = "${ipv6_addr_des}" - hostname: dest_host = "ENTER.YOUR.EXAMPLE.SERVER_CN" - wrong_hostname: From 3cecbf822aeb3e42bb9f29cd9dc610f5aae9992e Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 18 Dec 2024 10:53:53 +0800 Subject: [PATCH 0749/1055] guest_os_booting: Extend timeout Extend timeout of checking vm boot up to make the script more stable Signed-off-by: Yingshun Cui --- .../boot_order/boot_with_multiple_boot_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py index b3469f6bdd8..8eee55e9e10 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py @@ -92,7 +92,7 @@ def run(test, params, env): vm.wait_for_login(timeout=360).close() test.log.debug("Succeed to boot %s", vm_name) else: - vm.serial_console.read_until_output_matches(check_prompt, timeout=300, + vm.serial_console.read_until_output_matches(check_prompt, timeout=600, internal_timeout=0.5) finally: bkxml.sync() From 38831fba78409b443a47809a184a16d428001273 Mon Sep 17 00:00:00 2001 From: nanli Date: Thu, 12 Dec 2024 09:52:36 +0800 Subject: [PATCH 0750/1055] fix maxvcpu increase makes the case checking maxvcpu failed num changes from 710 to 2096 Signed-off-by: nanli --- libvirt/tests/cfg/cpu/max_vcpus.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/cpu/max_vcpus.cfg b/libvirt/tests/cfg/cpu/max_vcpus.cfg index b8fd70eacb1..fddd0fb64ae 100644 --- a/libvirt/tests/cfg/cpu/max_vcpus.cfg +++ b/libvirt/tests/cfg/cpu/max_vcpus.cfg @@ -50,8 +50,8 @@ - no_iommu: only q35 check = "no_iommu" + status_error = "no" guest_vcpu = "256" - err_msg = "unsupported configuration: more than 255 vCPUs require extended interrupt mode enabled on the iommu device" - with_iommu: only q35 check = "with_iommu" @@ -60,5 +60,5 @@ - ioapic_iommu: only q35 check = "ioapic_iommu_ne" - guest_vcpu = "711" + guest_vcpu = "4097" err_msg = "unsupported configuration: Maximum CPUs greater than specified machine type limit|exceeds the maximum cpus supported|CPU topology doesn't match maximum vcpu count" From 91c50aad85d23fe822cc8e2e5522395683407d54 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 18 Dec 2024 17:57:57 +0800 Subject: [PATCH 0751/1055] guest_os_booting: Fix up login timeout issue On aarch64, the vm will enter uefi if there's no cdrom device. This is as expected so updating the expected result. Signed-off-by: Yingshun Cui --- .../guest_os_booting/boot_order/boot_from_cdrom_device.cfg | 6 ++++-- .../guest_os_booting/boot_order/boot_from_cdrom_device.py | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg index 0b820f8dadb..64edc39d915 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg @@ -6,11 +6,13 @@ variants: - without_cdrom: only os_dev + aarch64: + bootable_patterns = ["Shell>"] - with_cdrom_with_no_src: cdrom1_attrs = {'target': {'dev': 'sda', 'bus': 'sata'}, **${cdrom_attrs}} aarch64: cdrom1_attrs = {'target': {'dev': 'sda', 'bus': 'scsi'}, **${cdrom_attrs}} - bootable_patterns = ["Shell>"] + bootable_patterns = ["Shell>"] - with_cdrom: check_bootable_iso = "yes" cdrom1_attrs = {'source': {'attrs': {'file': boot_img_path}}, 'target': {'dev': 'sda', 'bus': 'scsi'}, **${cdrom_attrs}} @@ -24,7 +26,7 @@ check_bootable_iso = "yes" bootable_patterns = ["begin the installation process|Install Red Hat Enterprise"] os_dev: - status_error = "yes" + status_error = "yes" variants: - os_dev: os_attrs_boots = ['cdrom'] diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py index d9f7572f3bb..417a9f30f8b 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py @@ -102,7 +102,7 @@ def run(test, params, env): vm.start() if bootable_patterns: vm.serial_console.read_until_output_matches( - bootable_patterns, timeout=60, internal_timeout=0.5) + bootable_patterns, timeout=360, internal_timeout=0.5) else: try: vm.wait_for_serial_login().close() From ea5a380950ceab84b51e165d251ee408dc249ee7 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Fri, 25 Oct 2024 05:24:35 -0400 Subject: [PATCH 0752/1055] Add case for migration with numa topology Signed-off-by: liang-cong-red-hat --- .../migration_with_numa_topology.cfg | 44 +++++++++ .../migration_with_numa_topology.py | 94 +++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 libvirt/tests/cfg/numa/guest_numa_topology/migration_with_numa_topology.cfg create mode 100644 libvirt/tests/src/numa/guest_numa_topology/migration_with_numa_topology.py diff --git a/libvirt/tests/cfg/numa/guest_numa_topology/migration_with_numa_topology.cfg b/libvirt/tests/cfg/numa/guest_numa_topology/migration_with_numa_topology.cfg new file mode 100644 index 00000000000..d70ef24410b --- /dev/null +++ b/libvirt/tests/cfg/numa/guest_numa_topology/migration_with_numa_topology.cfg @@ -0,0 +1,44 @@ +- guest_numa_topology.migration_with_numa_topology: + type = migration_with_numa_topology + only aarch64 + start_vm = 'no' + dest_persist_xml = "yes" + dest_xml = "yes" + migration_bandwidth = "1000" + base_migration_options = "--live --p2p --persistent --undefinesource --bandwidth ${migration_bandwidth}" + node_0_cpu = 0-1 + node_1_cpu = 2-3 + node_num = 4 + vcpu_memory_dict = "'vcpu': 8, 'memory_unit':'KiB','memory':8388608,'current_mem':8388608,'current_mem_unit':'KiB'" + variants: + - one_cluster_on_numa: + topology_dict = {'sockets': '2', 'clusters':'2', 'cores': '2', 'threads': '1'} + node_2_cpu = 4-5 + node_3_cpu = 6-7 + numa_list = "[{'id': '0', 'cpus': '${node_0_cpu}', 'memory': '2097152', 'unit': 'KiB'}, {'id': '1', 'cpus': '${node_1_cpu}', 'memory': '2097152', 'unit': 'KiB'}, {'id': '2', 'cpus': '${node_2_cpu}', 'memory': '2097152', 'unit': 'KiB'}, {'id': '3', 'cpus': '${node_3_cpu}', 'memory': '2097152', 'unit': 'KiB'}]" + - multi_cluster_on_numa: + topology_dict = {'sockets': '1', 'clusters':'4', 'cores': '2', 'threads': '1'} + node_2_cpu = 4-7 + numa_list = "[{'id': '0', 'cpus': '${node_0_cpu}', 'memory': '2097152', 'unit': 'KiB'}, {'id': '1', 'cpus': '${node_1_cpu}', 'memory': '2097152', 'unit': 'KiB'}, {'id': '2', 'cpus': '${node_2_cpu}', 'memory': '2097152', 'unit': 'KiB'}, {'id': '3', 'memory': '2097152', 'unit': 'KiB'}]" + variants: + - base_options: + add_options = "" + - addtional_options: + no aarch64 + migration_connections = 3 + add_options = "--auto-converge --parallel --parallel-connections ${migration_connections} --tls" + variants: + - without_postcopy: + copy_type = "" + - postcopy: + no aarch64 + only base_options + copy_type = "--postcopy" + variants: + - with_back_migration: + migrate_vm_back = "yes" + - no_back_migration: + migrate_vm_back = "no" + vm_attrs = {${vcpu_memory_dict}, 'cpu': {'numa_cell': ${numa_list}}} + virsh_migrate_options = "${base_migration_options} ${add_options} ${copy_type}" + diff --git a/libvirt/tests/src/numa/guest_numa_topology/migration_with_numa_topology.py b/libvirt/tests/src/numa/guest_numa_topology/migration_with_numa_topology.py new file mode 100644 index 00000000000..31d36f3a7d8 --- /dev/null +++ b/libvirt/tests/src/numa/guest_numa_topology/migration_with_numa_topology.py @@ -0,0 +1,94 @@ +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: Liang Cong +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from virttest import utils_misc +from virttest import migration_template as mt +from virttest.libvirt_xml import vm_xml + + +class MigrationWithNumaTopology(mt.MigrationTemplate): + + def __init__(self, test, env, params, *args, **dargs): + super().__init__(test, env, params, *args, **dargs) + + @staticmethod + @mt.vm_session_handler + def check_guest_numa_cpu(vm, test, params): + """ + Check cpu id on each guest numa node + + :param vm: guest vm object + :param test: test object + :param params: test parameters + """ + node_num = int(params.get("node_num")) + exp_nodes_cpu_list = [utils_misc.cpu_str_to_list(params.get( + "node_%s_cpu" % i)) if params.get("node_%s_cpu" % i) else [] for i in range(node_num)] + guest_numa_info = utils_misc.NumaInfo(session=vm.session) + act_nodes_cpu_list = [] + for node_index in range(len(guest_numa_info.nodes)): + cpu_list = list(map(int, guest_numa_info.nodes[node_index].cpus)) + act_nodes_cpu_list.append(cpu_list) + test.log.debug("guest node %s has cpus: %s" % + (node_index, cpu_list)) + if exp_nodes_cpu_list != act_nodes_cpu_list: + test.fail("Expect numa nodes cpu list is %s, but get %s" % + (exp_nodes_cpu_list, act_nodes_cpu_list)) + + def _pre_start_vm(self): + """ + Operation before start guest on source host: + Define the guest + """ + vm_attrs = eval(self.params.get("vm_attrs", "{}")) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(self.main_vm.name) + vmxml.setup_attrs(**vm_attrs) + vmxml.cpu.topology = eval(self.params.get("topology_dict", "{}")) + vmxml.sync() + + def _post_start_vm(self): + """ + Operation after start guest on source host: + Check guest numa cpu after guest starts + """ + self.check_guest_numa_cpu(self.main_vm, self.test, self.params) + + def _post_migrate(self): + """ + Operation after migration: + Check guest numa cpu after migration + """ + self.check_guest_numa_cpu(self.main_vm, self.test, self.params) + + def _post_migrate_back(self): + """ + Operation after back migration: + Check guest numa cpu after back migration + """ + self.check_guest_numa_cpu(self.main_vm, self.test, self.params) + + +def run(test, params, env): + """ + 1. Assign cpu topology with numa node + 2. Start guest + 3. Verify the guest cpu assignment for numa nodes on src host + 4. Do migration + 5. Verify the guest cpu assignment for numa nodes on dest host + 6. Do back migration + 7. Verify the guest cpu assignment for numa nodes on src host + """ + + migrationobj = MigrationWithNumaTopology(test, env, params) + try: + migrationobj.runtest() + finally: + migrationobj.cleanup() From ac0d56b9509196b16c20e49ee9310e18b8949455 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Thu, 19 Dec 2024 02:30:45 -0500 Subject: [PATCH 0753/1055] Remove the workaround since qemu bug fixed There was qemu bugs about virtio multiqueue, and now the bugs are fixed. Remove the workaround. Signed-off-by: Yalan Zhang --- libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py index 770d7f64d63..37d9e41c9e9 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py @@ -14,7 +14,6 @@ from virttest.libvirt_xml import vm_xml from virttest.staging.service import Factory from virttest.staging.utils_memory import drop_caches -from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_test import libvirt # Using as lower capital is not the best way to do, but this is just a @@ -363,10 +362,6 @@ def build_vm_xml(vm_name, **dargs): # Destroy vm first for setting configuration file if vm.state() == "running": vm.destroy(gracefully=False) - - # Workaround bug: Remove multi-queue setting - vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) - libvirt_vmxml.modify_vm_device(vmxml, 'interface', {'driver': None}) # Prepare test environment. if libvirtd_state == "off": libvirtd.stop() From 496e846e59c813fb05ec56dea0d7e03bf4964b61 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Thu, 19 Dec 2024 15:06:23 +0800 Subject: [PATCH 0754/1055] v2v: add new case for converting wrong vmx file Signed-off-by: vwu-vera --- v2v/tests/cfg/convert_from_file.cfg | 11 +++++++++-- v2v/tests/src/convert_from_file.py | 6 ++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/v2v/tests/cfg/convert_from_file.cfg b/v2v/tests/cfg/convert_from_file.cfg index 9673cc847ea..e66db849b75 100644 --- a/v2v/tests/cfg/convert_from_file.cfg +++ b/v2v/tests/cfg/convert_from_file.cfg @@ -251,6 +251,13 @@ checkpoint = 'special_character' expect_msg = 'yes' msg_content = 'nbd_connect_uri.*No such file or directory.*' + - wrong_vmx: + only esx_80 + boottype = 3 + version_required = "[virt-v2v-2.4.0-2.el9,)" + main_vm = VM_NAME_RHEL9_V2V_EXAMPLE + checkpoint = 'wrong_vmx' + msg_content_yes = "virt-v2v: error: input file is a VMDK \(disk image\), but we are expecting a VMX \(VMware metadata\)" - no_ssh_agent: only esx_80 version_required = "[virt-v2v-2.4.0-2.el9,)" @@ -321,13 +328,13 @@ variants: - negative_test: status_error = 'yes' - only parse.SHA1,parse.SHA256,special_character + only parse.SHA1,parse.SHA256,special_character,wrong_vmx - positive_test: status_error = 'no' variants: - linux: only ova,vmx,disk - no win2008r2_ostk,aws.win2019,special_character + no win2008r2_ostk,aws.win2019,special_character,wrong_vmx - windows: os_type = 'windows' shutdown_command = 'shutdown /s /f /t 0' diff --git a/v2v/tests/src/convert_from_file.py b/v2v/tests/src/convert_from_file.py index 4a41a29e8de..2338528163a 100644 --- a/v2v/tests/src/convert_from_file.py +++ b/v2v/tests/src/convert_from_file.py @@ -325,6 +325,12 @@ def vm_check(): if checkpoint == 'special_character': v2v_result = utils_v2v.cmd_run(str(utils_v2v.v2v_cmd(v2v_params, cmd_only=True)).replace('.vmx', '.vm*'), params.get('v2v_dirty_resources')) + elif checkpoint == 'wrong_vmx': + esxi_passwd_file = "/tmp/v2v_esxi_passwd" + with open(esxi_passwd_file, 'w') as f: + f.write(esxi_password) + v2v_cmd = str(utils_v2v.v2v_cmd(v2v_params, cmd_only=True) + ' -ip %s' % esxi_passwd_file) + v2v_result = utils_v2v.cmd_run(v2v_cmd.replace('.vmx', '.vmdk'), params.get('v2v_dirty_resources')) elif checkpoint == 'no_ssh_agent': esxi_passwd_file = "/tmp/v2v_esxi_passwd" with open(esxi_passwd_file, 'w') as f: From 16d71c87e1602495a2689fa9b330b470e55481ee Mon Sep 17 00:00:00 2001 From: Yanqiu Zhang Date: Fri, 20 Dec 2024 01:33:32 -0500 Subject: [PATCH 0755/1055] iface_update: change huge average value Bug RHEL-45200(libvirt-10.8.0-1) start to reject huge average values larger than '18014398509481984', so change the test value and error msg. Signed-off-by: Yanqiu Zhang --- libvirt/tests/cfg/virtual_network/iface_update.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/iface_update.cfg b/libvirt/tests/cfg/virtual_network/iface_update.cfg index c6d38c46249..c573ce9926a 100644 --- a/libvirt/tests/cfg/virtual_network/iface_update.cfg +++ b/libvirt/tests/cfg/virtual_network/iface_update.cfg @@ -178,9 +178,9 @@ new_iface_outbound = "{'average':'128','peak':'256','burst':'256'}" expect_err_msg = "could not convert bandwidth average value|Expected non-negative integer value" - huge_val: - new_iface_inbound = "{'average':'10000000000000000','peak':'5000','burst':'1024'}" + new_iface_inbound = "{'average':'100000000000000000','peak':'5000','burst':'1024'}" new_iface_outbound = "{'average':'128','peak':'256','burst':'256'}" - expect_err_msg = 'Illegal "quantum"' + expect_err_msg = "too big for 'average' parameter, maximum is '18014398509481984'" - missing: new_iface_inbound = "{'peak':'5000','burst':'1024'}" new_iface_outbound = "{'peak':'256','burst':'256'}" From 8b89ff7370eaf629bf9d0141a66857ebf73d4aae Mon Sep 17 00:00:00 2001 From: Yanqiu Zhang Date: Fri, 20 Dec 2024 03:47:21 -0500 Subject: [PATCH 0756/1055] mtu: create tap with multi_queue flag If vm iface has 'driver queues' in xml, creating tap also need add multi_queue flag. Signed-off-by: Yanqiu Zhang --- libvirt/tests/cfg/virtual_network/mtu.cfg | 2 +- libvirt/tests/src/virtual_network/mtu.py | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/mtu.cfg b/libvirt/tests/cfg/virtual_network/mtu.cfg index bb6635cca7c..c55f088100d 100644 --- a/libvirt/tests/cfg/virtual_network/mtu.cfg +++ b/libvirt/tests/cfg/virtual_network/mtu.cfg @@ -43,7 +43,7 @@ - tap: create_tap = yes tap_mtu_size = 2000 - tap_cmd = 'ip tuntap add mode tap name {tap_name};ip link set dev {tap_name} mtu ${tap_mtu_size}' + tap_cmd = 'ip tuntap add mode tap name {tap_name} multi_queue;ip link set dev {tap_name} mtu ${tap_mtu_size}' variants: - managed_no: iface_target = {'dev': '%s', 'managed': 'no'} diff --git a/libvirt/tests/src/virtual_network/mtu.py b/libvirt/tests/src/virtual_network/mtu.py index ab3a11659ab..ffa9d020a84 100644 --- a/libvirt/tests/src/virtual_network/mtu.py +++ b/libvirt/tests/src/virtual_network/mtu.py @@ -209,6 +209,10 @@ def check_mtu_in_vm(fn_login, mtu_size, timeout): if tap_cmd is None: test.error('No tap creating command provided.') tap_cmd = tap_cmd.format(tap_name=tap_name) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + iface = vmxml.devices.by_device_tag('interface')[0] + if "driver queues" not in str(iface): + tap_cmd = tap_cmd.replace(' multi_queue', '') logging.debug('Tap creating command: \n %s', tap_cmd) # Create tap device process.run(tap_cmd, verbose=True, shell=True) @@ -231,8 +235,6 @@ def check_mtu_in_vm(fn_login, mtu_size, timeout): test.fail('Host mtu size check FAIL.') # Get iface mac address - vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) - iface = vmxml.devices.by_device_tag('interface')[0] iface_mac = iface.mac_address # Check mtu inside vm @@ -386,4 +388,7 @@ def check_mtu_in_vm(fn_login, mtu_size, timeout): process.run("ovs-vsctl del-br %s" % br, verbose=True) utils_package.package_remove(add_pkg) if create_tap: - process.run('ip tuntap del mode tap {}'.format(tap_name), verbose=True, shell=True) + tap_del_cmd = 'ip tuntap del mode tap {} multi_queue' + if "multi_queue" not in tap_cmd: + tap_del_cmd = tap_del_cmd.replace(' multi_queue', '') + process.run(tap_del_cmd.format(tap_name), verbose=True, shell=True) From 54d1e5ce26fcc3473fdd418ff7128241fa8a432f Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Fri, 20 Dec 2024 05:45:36 -0500 Subject: [PATCH 0757/1055] Fix the malformed default gatway On RHEL 10, the utils_net.get_default_gateway() will get outputs with color, which will be malformed showed in text. Replace it with get_default_gateway_json() can fix the issue. Signed-off-by: Yalan Zhang --- .../tests/src/virtual_network/passt/passt_transfer_file.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py index 3f99e33f938..e1d22ba69f3 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py +++ b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py @@ -79,9 +79,9 @@ def transfer_vm_to_host(session, prot, ip_ver, vm_iface, firewalld, rec_file = params.get('rec_file') cmd_create_file = params.get('cmd_create_file') force_dhcp = True if ip_ver == 'ipv4' else False - vm_default_gw = utils_net.get_default_gateway(session=session, - ip_ver=ip_ver, - force_dhcp=force_dhcp) + vm_default_gw = utils_net.get_default_gateway_json(session=session, + ip_ver=ip_ver, + force_dhcp=force_dhcp) addr = vm_default_gw if ip_ver == 'ipv4' \ else f'[{vm_default_gw}%{vm_iface}]' firewalld.stop() From 45f5f45e0eceba62c6d3864f85e39ba823f841db Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 20 Dec 2024 19:45:32 +0800 Subject: [PATCH 0758/1055] guest_os_booting: Remove unnecessary dhcp-client package Signed-off-by: Yingshun Cui --- .../guest_os_booting/boot_order/boot_from_virtiofs_device.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_virtiofs_device.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_virtiofs_device.py index 9f4c9febbde..5138d51e0ca 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_virtiofs_device.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_virtiofs_device.py @@ -36,7 +36,7 @@ def prepare_virtiofs_bootable_system(): cmd1 = f"mkdir {install_root}" cmd2 = f"dnf --installroot={install_root} --releasever=9 install "\ "system-release vim-minimal systemd passwd dnf rootfiles sudo "\ - "kernel kernel-modules net-tools yum dhcp-client -y >/dev/null" + "kernel kernel-modules net-tools yum -y >/dev/null" # Create the initramfs. cmd3 = f"dracut {initrams_file} --early-microcode "\ "--add virtiofs --filesystem virtiofs" From ae567c8e707342d28cc3ffc8e5ec1ebb50cbed71 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 24 Dec 2024 03:54:36 -0500 Subject: [PATCH 0759/1055] update_device/iface: disable test on s390x On s390x, there's only one model. Trying to unset the type will be ignored. Signed-off-by: Sebastian Mitterle --- .../update_device/unsupported_live_update_delete.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg index faa80241ca6..d4dd90285dd 100644 --- a/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg +++ b/libvirt/tests/cfg/virtual_network/update_device/unsupported_live_update_delete.cfg @@ -28,6 +28,7 @@ del_attr = rom err_msg = cannot modify network device rom enabled setting - model_type: + no s390-virtio del_attr = model err_msg = cannot modify network device model from .* to .* - backend: From 46ba0dffb8abe1b3825d509fdff772ba0f34539f Mon Sep 17 00:00:00 2001 From: Meina Li Date: Tue, 24 Dec 2024 04:35:38 -0500 Subject: [PATCH 0760/1055] SRIOV: fix "Login timeout expired" because of 256 vcpus The numbers of guest vcpu is better little than the host vcpus' number. But we don't have this host to match 256 cpus. So after discussing we decided to use the same host cpus' number to test guest vcpus. Signed-off-by: Meina Li --- .../tests/cfg/sriov/vIOMMU/intel_iommu_with_dma_translation.cfg | 1 - .../tests/src/sriov/vIOMMU/intel_iommu_with_dma_translation.py | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_with_dma_translation.cfg b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_with_dma_translation.cfg index ed796ca7496..15411a02ecf 100644 --- a/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_with_dma_translation.cfg +++ b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_with_dma_translation.cfg @@ -13,5 +13,4 @@ with_more_vcpus = "yes" dma_translation = "off" eim_dict = {'eim': 'on'} - guest_vcpus = 256 iommu_dict = {'model': 'intel', 'driver': {'intremap': 'on', 'caching_mode': 'on', 'iotlb': 'on', 'dma_translation': '${dma_translation}'}} diff --git a/libvirt/tests/src/sriov/vIOMMU/intel_iommu_with_dma_translation.py b/libvirt/tests/src/sriov/vIOMMU/intel_iommu_with_dma_translation.py index 4b057ed4842..cda4e9e539a 100644 --- a/libvirt/tests/src/sriov/vIOMMU/intel_iommu_with_dma_translation.py +++ b/libvirt/tests/src/sriov/vIOMMU/intel_iommu_with_dma_translation.py @@ -1,3 +1,4 @@ +from avocado.utils import cpu from virttest import virsh from virttest.libvirt_xml import vm_xml @@ -23,6 +24,7 @@ def run(test, params, env): test_obj.setup_iommu_test(iommu_dict=iommu_dict) if with_more_vcpus: vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + guest_vcpus = cpu.online_count() vmxml.vcpu = int(guest_vcpus) vmxml.sync() test.log.info("TEST STEP2: Start the guest.") From c1b4841c82e99d69946609f12e6976159bf4a42a Mon Sep 17 00:00:00 2001 From: Meina Li Date: Tue, 24 Dec 2024 21:14:12 -0500 Subject: [PATCH 0761/1055] sriov: fix ipxe rom file issue Relying on ipxe build in tests when cannot obtain VF pxe rom file is an unstable testing method. Because this case is mainly to test the xml but not the pxe function. So we decided to use the fixed virtio rom file to test. The error message: This test needs rom file: /usr/share/ipxe/8086154c.rom. Signed-off-by: Meina Li --- provider/sriov/sriov_base.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/provider/sriov/sriov_base.py b/provider/sriov/sriov_base.py index a908fa75ce3..3558af28fe1 100644 --- a/provider/sriov/sriov_base.py +++ b/provider/sriov/sriov_base.py @@ -258,12 +258,11 @@ def get_rom_file(self): rom_vendor_device = lspci_stdout[1:-1].replace(':', '') + '.rom' rom_file = os.path.join('/usr/share/ipxe', rom_vendor_device) if not os.path.exists(rom_file): - build_cmd = "git clone https://github.com/ipxe/ipxe.git;\ - pushd ipxe/src; make bin/{0}; cp bin/{0} {1}; popd; \ - rm -rf ipxe".format(rom_vendor_device, rom_file) - process.run(build_cmd, shell=True, verbose=True) - if not os.path.exists(rom_file): - self.test.error("This test needs rom file: %s." % rom_file) + virtio_rom_file = "/usr/share/ipxe/1af41000.rom" + if not os.path.exists(virtio_rom_file): + self.test.error(f"This test needs a rom file, but neither {rom_file}" + "nor {virtio_rom_file} exist!") + return virtio_rom_file return rom_file def create_iface_dev(self, dev_type, iface_dict): From a8e7bd8e068193ad228f575f8452835a4715f97f Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 25 Dec 2024 14:13:46 +0800 Subject: [PATCH 0762/1055] sriov: Fix error format issue This is introduced by c1b4841c82e99d69. Signed-off-by: Yingshun Cui --- provider/sriov/sriov_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/provider/sriov/sriov_base.py b/provider/sriov/sriov_base.py index 3558af28fe1..67a4be69171 100644 --- a/provider/sriov/sriov_base.py +++ b/provider/sriov/sriov_base.py @@ -260,8 +260,8 @@ def get_rom_file(self): if not os.path.exists(rom_file): virtio_rom_file = "/usr/share/ipxe/1af41000.rom" if not os.path.exists(virtio_rom_file): - self.test.error(f"This test needs a rom file, but neither {rom_file}" - "nor {virtio_rom_file} exist!") + self.test.error(f"This test needs a rom file, but neither {rom_file} " + f"nor {virtio_rom_file} exist!") return virtio_rom_file return rom_file From 49e531cb72990e2f20602b2d575b3c7f219fbd33 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 27 Dec 2024 01:45:20 -0500 Subject: [PATCH 0763/1055] Move virtiofs managedsave cases to positive cases part Before virtiofs managedsave cases are negative due to migration of virtiofs is not fixed. Now, migration for virtiofs has been supported and RHEL-50542 has been fixed. Move the virtiofs managedsave cases to positive cases part. Signed-off-by: root --- .../cfg/virtual_device/filesystem_device.cfg | 11 +- .../src/virtual_device/filesystem_device.py | 179 +++++++++--------- 2 files changed, 96 insertions(+), 94 deletions(-) diff --git a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg index 76a1352cc9b..f65ab534c79 100644 --- a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg +++ b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg @@ -101,6 +101,11 @@ stdio_handler = "logd" - detach_device: detach_device_alias = "no" + - managedsave: + only xattr_on.cache_mode_auto..one_fs + s390-virtio: + kvm_module_parameters = "hpage=1" + managedsave = "yes" variants: - positive_test: status_error = "no" @@ -130,9 +135,3 @@ - larger_than_1024: queue_size = 2048 error_msg_start = "queue-size property must be 1024 or smaller" - - managedsave: - only nop - s390-virtio: - kvm_module_parameters = "hpage=1" - managedsave = "yes" - error_msg_save = "migration with virtiofs device is not supported" diff --git a/libvirt/tests/src/virtual_device/filesystem_device.py b/libvirt/tests/src/virtual_device/filesystem_device.py index cf4d9361b20..fc289eb4854 100644 --- a/libvirt/tests/src/virtual_device/filesystem_device.py +++ b/libvirt/tests/src/virtual_device/filesystem_device.py @@ -366,95 +366,98 @@ def check_filesystem_hotplug_with_mem_setup(): cmd = 'ps aux | grep /usr/libexec/virtiofsd' utils_test.libvirt.check_cmd_output(cmd, content=expected_results) - if managedsave: - expected_error = error_msg_save - result = virsh.managedsave(vm_names[0], ignore_status=True, debug=True) - utils_test.libvirt.check_exit_status(result, expected_error) - else: - shared_data(vm_names, fs_devs) - if suspend_resume: - virsh.suspend(vm_names[0], debug=True, ignore_status=False) - time.sleep(30) - virsh.resume(vm_names[0], debug=True, ignore_statue=False) - elif destroy_start: - session = vm.wait_for_login(timeout=120) - # Prepare the guest test script - script_path = os.path.join(fs_devs[0].source["dir"], "test.py") - script_content %= (fs_devs[0].source["dir"], fs_devs[0].source["dir"]) - prepare_stress_script(script_path, script_content) - # Run guest stress script - stress_script_thread = threading.Thread(target=run_stress_script, - args=(session, script_path)) - stress_script_thread.setDaemon(True) - stress_script_thread.start() - # Create a lot of unlink files - time.sleep(60) - virsh.destroy(vm_names[0], debug=True, ignore_status=False) - ret = virsh.start(vm_names[0], debug=True) - libvirt.check_exit_status(ret) - elif edit_start: - vmxml_virtio_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_names[0]) - if vm.is_alive(): - virsh.destroy(vm_names[0]) - cmd = "virt-xml %s --edit --qemu-commandline '\-foo'" % vm_names[0] - cmd_result = process.run(cmd, ignore_status=True, shell=True) - logging.debug(virsh.dumpxml(vm_names[0])) - if cmd_result.exit_status: - test.error("virt-xml edit guest failed: %s" % cmd_result) - result = virsh.start(vm_names[0], ignore_status=True, debug=True) - if error_msg_start: - expected_fails_msg.append(error_msg_start) - utils_test.libvirt.check_result(result, expected_fails=expected_fails_msg) - if not libvirt_version.version_compare(6, 10, 0): - # Because of bug #1897105, it was fixed in libvirt-6.10.0, - # before this version, need to recover the env manually. - cmd = "pkill virtiofsd" - process.run(cmd, shell=True) - if not vm.is_alive(): - # Restoring vm and check if vm can start successfully - vmxml_virtio_backup.sync() - virsh.start(vm_names[0], ignore_status=False, shell=True) - elif socket_file_checking: - result = virsh.domid(vm_names[0]) - domid = result.stdout.strip() - domain_dir = "var/lib/libvirt/qemu/domain-" + domid + '-' + vm_names[0] - if result.exit_status: - test.fail("Get domid failed.") - for fs_dev in fs_devs: + shared_data(vm_names, fs_devs) + if suspend_resume: + virsh.suspend(vm_names[0], debug=True, ignore_status=False) + time.sleep(30) + virsh.resume(vm_names[0], debug=True, ignore_statue=False) + elif managedsave: + virsh.managedsave(vm_names[0], ignore_status=True, debug=True) + save_file = "/var/lib/libvirt/qemu/save/%s.save" % vm_names[0] + if not os.path.exists(save_file): + test.fail("guest is not manangedsaved") + virsh.start(vm_names[0], ignore_status=True, debug=True) + if os.path.exists(save_file): + test.fail("guest is not restored from the managedsave file") + elif destroy_start: + session = vm.wait_for_login(timeout=120) + # Prepare the guest test script + script_path = os.path.join(fs_devs[0].source["dir"], "test.py") + script_content %= (fs_devs[0].source["dir"], fs_devs[0].source["dir"]) + prepare_stress_script(script_path, script_content) + # Run guest stress script + stress_script_thread = threading.Thread(target=run_stress_script, + args=(session, script_path)) + stress_script_thread.setDaemon(True) + stress_script_thread.start() + # Create a lot of unlink files + time.sleep(60) + virsh.destroy(vm_names[0], debug=True, ignore_status=False) + ret = virsh.start(vm_names[0], debug=True) + libvirt.check_exit_status(ret) + elif edit_start: + vmxml_virtio_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_names[0]) + if vm.is_alive(): + virsh.destroy(vm_names[0]) + cmd = "virt-xml %s --edit --qemu-commandline '\-foo'" % vm_names[0] + cmd_result = process.run(cmd, ignore_status=True, shell=True) + logging.debug(virsh.dumpxml(vm_names[0])) + if cmd_result.exit_status: + test.error("virt-xml edit guest failed: %s" % cmd_result) + result = virsh.start(vm_names[0], ignore_status=True, debug=True) + if error_msg_start: + expected_fails_msg.append(error_msg_start) + utils_test.libvirt.check_result(result, expected_fails=expected_fails_msg) + if not libvirt_version.version_compare(6, 10, 0): + # Because of bug #1897105, it was fixed in libvirt-6.10.0, + # before this version, need to recover the env manually. + cmd = "pkill virtiofsd" + process.run(cmd, shell=True) + if not vm.is_alive(): + # Restoring vm and check if vm can start successfully + vmxml_virtio_backup.sync() + virsh.start(vm_names[0], ignore_status=False, shell=True) + elif socket_file_checking: + result = virsh.domid(vm_names[0]) + domid = result.stdout.strip() + domain_dir = "var/lib/libvirt/qemu/domain-" + domid + '-' + vm_names[0] + if result.exit_status: + test.fail("Get domid failed.") + for fs_dev in fs_devs: + alias = fs_dev.alias['name'] + expected_pid = domain_dir + alias + '-fs.pid' + expected_sock = alias + '-fs.sock' + status1 = process.run('ls -l %s' % expected_pid, shell=True).exit_status + status2 = process.run('ls -l %s' % expected_sock, shell=True).exit_status + if not (status1 and status2): + test.fail("The socket and pid file is not as expected") + elif hotplug_unplug: + for vm in vms: + umount_fs(vm) + for fs_dev in fs_devs: + if detach_device_alias: + utils_package.package_install("lsof") alias = fs_dev.alias['name'] - expected_pid = domain_dir + alias + '-fs.pid' - expected_sock = alias + '-fs.sock' - status1 = process.run('ls -l %s' % expected_pid, shell=True).exit_status - status2 = process.run('ls -l %s' % expected_sock, shell=True).exit_status - if not (status1 and status2): - test.fail("The socket and pid file is not as expected") - elif hotplug_unplug: - for vm in vms: - umount_fs(vm) - for fs_dev in fs_devs: - if detach_device_alias: - utils_package.package_install("lsof") - alias = fs_dev.alias['name'] - cmd = 'lsof /var/log/libvirt/qemu/%s-%s-virtiofsd.log' % (vm.name, alias) - output = process.run(cmd).stdout_text.splitlines() - for item in output[1:]: - if stdio_handler_file: - if item.split()[0] != "virtiofsd": - test.fail("When setting stdio_handler as file, the command" - "to write log should be virtiofsd!") - else: - if item.split()[0] != "virtlogd": - test.fail("When setting stdio_handler as logd, the command" - "to write log should be virtlogd!") - ret = virsh.detach_device_alias(vm.name, alias, ignore_status=True, - debug=True, wait_for_event=True, - event_timeout=10) - else: - ret = virsh.detach_device(vm.name, fs_dev.xml, ignore_status=True, - debug=True, wait_for_event=True) - libvirt.check_exit_status(ret, status_error) - check_filesystem_in_guest(vm, fs_dev) - check_detached_xml(vm) + cmd = 'lsof /var/log/libvirt/qemu/%s-%s-virtiofsd.log' % (vm.name, alias) + output = process.run(cmd).stdout_text.splitlines() + for item in output[1:]: + if stdio_handler_file: + if item.split()[0] != "virtiofsd": + test.fail("When setting stdio_handler as file, the command" + "to write log should be virtiofsd!") + else: + if item.split()[0] != "virtlogd": + test.fail("When setting stdio_handler as logd, the command" + "to write log should be virtlogd!") + ret = virsh.detach_device_alias(vm.name, alias, ignore_status=True, + debug=True, wait_for_event=True, + event_timeout=10) + else: + ret = virsh.detach_device(vm.name, fs_dev.xml, ignore_status=True, + debug=True, wait_for_event=True) + libvirt.check_exit_status(ret, status_error) + check_filesystem_in_guest(vm, fs_dev) + check_detached_xml(vm) finally: for vm in vms: alias = fs_dev.alias['name'] From 71e0cb1f4c248e15ad7494a3bc98d6b32cf1a1c3 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 27 Dec 2024 17:03:46 +0800 Subject: [PATCH 0764/1055] guest_os_booting: Skip templateFormat when comparing os xml The 'templateFormat' is automatically added in os xml and causes the xml comparison to fail. Signed-off-by: Yingshun Cui --- .../src/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.py b/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.py index 9159e9370aa..22508b31c8d 100644 --- a/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.py +++ b/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.py @@ -30,6 +30,8 @@ def compare_guest_xml(vmxml, os_attrs): current_os_attrs = os_xml.fetch_attrs() for key in os_attrs: if key in current_os_attrs: + if key == "nvram_attrs": + current_os_attrs[key].pop("templateFormat") if os_attrs[key] != current_os_attrs[key]: test.fail("Configured os xml value {} doesn't match the" " entry {} in guest xml".format(os_attrs[key], current_os_attrs[key])) From 9a7ac28e2668a12d93b7f81485a4eacc612e2109 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 27 Dec 2024 17:20:40 +0800 Subject: [PATCH 0765/1055] guest_os_booting: Fix the nonexist_template case error 1. nvram file should be cleared before the testing 2. error message changed Signed-off-by: Yingshun Cui --- .../cfg/guest_os_booting/ovmf_firmware/ovmf_nvram.cfg | 2 +- .../src/guest_os_booting/ovmf_firmware/ovmf_nvram.py | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_nvram.cfg b/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_nvram.cfg index 4a1fd4a15f4..0b041ddc827 100644 --- a/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_nvram.cfg +++ b/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_nvram.cfg @@ -28,4 +28,4 @@ variants: - nonexist_template: template_path = "nonexist" - error_msg = "error: Failed to open file.+: No such file or directory" + error_msg = "error: Failed to open file.+: No such file or directory|conversion of the nvram template to another target format" diff --git a/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_nvram.py b/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_nvram.py index 4139fdae2e9..5d745be9e26 100644 --- a/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_nvram.py +++ b/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_nvram.py @@ -22,16 +22,18 @@ def run(test, params, env): smm_state = params.get("smm_state") error_msg = params.get("error_msg", "") template_path = params.get("template_path", "") - if template_path: - nvram_dict = eval(params.get("nvram_dict", "{}") % template_path) - else: - nvram_dict = eval(params.get("nvram_dict")) vm = env.get_vm(vm_name) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) bkxml = vmxml.copy() try: + if template_path: + nvram_dict = eval(params.get("nvram_dict", "{}") % template_path) + if template_path == "nonexist": + vmxml.sync("--nvram") + else: + nvram_dict = eval(params.get("nvram_dict")) if smm_state: guest_os.prepare_smm_xml(vm_name, smm_state, smm_size=None) guest_os.prepare_os_xml(vm_name, nvram_dict, firmware_type) From 4ed7e4a31a630e90f511add0d07e39f169cf615f Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 30 Dec 2024 04:44:20 -0500 Subject: [PATCH 0766/1055] Change fixed huge page size to default huge page size of host Signed-off-by: liang-cong-red-hat --- .../tests/cfg/numa/numa_numanode_cpu_info.cfg | 5 ++- .../tests/src/numa/numa_numanode_cpu_info.py | 44 +++++++++++-------- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/libvirt/tests/cfg/numa/numa_numanode_cpu_info.cfg b/libvirt/tests/cfg/numa/numa_numanode_cpu_info.cfg index 1f44f494072..4e9de5800f7 100644 --- a/libvirt/tests/cfg/numa/numa_numanode_cpu_info.cfg +++ b/libvirt/tests/cfg/numa/numa_numanode_cpu_info.cfg @@ -6,5 +6,8 @@ variants: - default: err_msg = 'unable to map backing store for guest RAM: Cannot allocate memory' - nodes_pages = ['900', '300'] + current_memory_size = 4194304 + memory_size = 4194304 + nodes_memory = ['1572864', '524288'] memory_mode = "strict" + diff --git a/libvirt/tests/src/numa/numa_numanode_cpu_info.py b/libvirt/tests/src/numa/numa_numanode_cpu_info.py index 76ccdcc746a..124b9557e9b 100644 --- a/libvirt/tests/src/numa/numa_numanode_cpu_info.py +++ b/libvirt/tests/src/numa/numa_numanode_cpu_info.py @@ -7,6 +7,7 @@ from virttest import utils_misc from virttest import utils_test from virttest import virsh +from virttest.staging import utils_memory # Using as lower capital is not the best way to do, but this is just a @@ -23,45 +24,51 @@ def update_xml(vm_name, online_nodes, params): """ vmxml = libvirt_xml.VMXML.new_from_dumpxml(vm_name) memory_mode = params.get("memory_mode") + memory_size = int(params.get("memory_size")) + current_memory_size = int(params.get("current_memory_size")) numa_memory = {'mode': memory_mode, 'nodeset': online_nodes[1]} vmxml.numa_memory = numa_memory mb_xml = libvirt_xml.vm_xml.VMMemBackingXML() mb_xml.hugepages = libvirt_xml.vm_xml.VMHugepagesXML() vmxml.mb = mb_xml + vmxml.memory = memory_size + vmxml.current_mem = current_memory_size logging.debug("vm xml is %s", vmxml) vmxml.sync() -def setup_host(required_node_num, online_nodes, pages_list, ori_page_set): +def setup_host(required_node_num, online_nodes, memory_list, ori_page_set): """ Setup host for test - update number of hugepages and check :param required_node_num: int, numa node number at least on the host required by the test :param online_nodes: List of all online nodes with memory available - :param pages_list: List of required number of pages for particular nodes + :param memory_list: List of required hugepage memory for particular nodes :param ori_page_set: A dict used to save original node page """ index = 0 if len(online_nodes) >= required_node_num: - for pages in pages_list: + hugepage_size = utils_memory.get_huge_page_size() + for memory_size in memory_list: ori_page_set[online_nodes[index]] = process.run( - 'cat /sys/devices/system/node/node{}/hugepages/hugepages-2048kB/nr_hugepages'. - format(online_nodes[index]), shell=True).stdout_text.strip() + 'cat /sys/devices/system/node/node{}/hugepages/hugepages-{}kB/nr_hugepages'. + format(online_nodes[index], hugepage_size), shell=True).stdout_text.strip() logging.debug("ori_page_set is {}".format(ori_page_set)) + pages = int(int(memory_size) / hugepage_size) ret = process.run( - 'echo {} > /sys/devices/system/node/node{}/hugepages/hugepages-2048kB/nr_hugepages'. - format(pages, online_nodes[index]), shell=True) + 'echo {} > /sys/devices/system/node/node{}/hugepages/hugepages-{}kB/nr_hugepages'. + format(pages, online_nodes[index], hugepage_size), shell=True) if ret.exit_status: - raise TestError('Cannot set {} hugepages on node {}'. - format(pages, online_nodes[index])) + raise TestError('Cannot set {} pages for {}kB huge page on node {}'. + format(pages, hugepage_size, online_nodes[index])) ret = process.run( - 'cat /sys/devices/system/node/node{}/hugepages/hugepages-2048kB/nr_hugepages'. - format(online_nodes[index]), shell=True) - if pages not in ret.stdout_text: - raise TestError('Setting {} hugepages on node {} was unsuccessful'. - format(pages, online_nodes[index])) + 'cat /sys/devices/system/node/node{}/hugepages/hugepages-{}kB/nr_hugepages'. + format(online_nodes[index], hugepage_size), shell=True) + if str(pages) not in ret.stdout_text: + raise TestError('Setting {} pages for {}kB huge page on node {} was unsuccessful'. + format(pages, hugepage_size, online_nodes[index])) index += 1 else: raise TestCancel("The test cannot continue since there is no enough " @@ -75,13 +82,13 @@ def run(test, params, env): vm_name = params.get("main_vm") vm = env.get_vm(vm_name) error_message = params.get("err_msg") - pages_list = eval(params.get('nodes_pages')) + node_memory_list = eval(params.get('nodes_memory')) backup_xml = libvirt_xml.VMXML.new_from_dumpxml(vm_name) numa_info = utils_misc.NumaInfo() online_nodes = numa_info.get_online_nodes_withmem() ori_page_set = {} required_numa_node_num = int(params.get("numa_cells_with_memory_required", '2')) - setup_host(required_numa_node_num, online_nodes, pages_list, ori_page_set) + setup_host(required_numa_node_num, online_nodes, node_memory_list, ori_page_set) try: if vm.is_alive(): vm.destroy() @@ -94,8 +101,9 @@ def run(test, params, env): except Exception as e: test.error("Unexpected error: {}".format(e)) finally: + hugepage_size = utils_memory.get_huge_page_size() for node_index, ori_page in ori_page_set.items(): process.run( - 'echo {} > /sys/devices/system/node/node{}/hugepages/hugepages-2048kB/nr_hugepages'. - format(ori_page, node_index), shell=True) + 'echo {} > /sys/devices/system/node/node{}/hugepages/hugepages-{}kB/nr_hugepages'. + format(ori_page, node_index, hugepage_size), shell=True) backup_xml.sync() From b83f4440463c301c48d02ee08e790f2e5b2914a5 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Wed, 1 Jan 2025 21:07:54 -0500 Subject: [PATCH 0767/1055] Add skip logic for cpu frequency checking on aarch64 Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/virsh_cmd/host/virsh_nodeinfo.cfg | 3 +++ libvirt/tests/src/virsh_cmd/host/virsh_nodeinfo.py | 11 ++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/cfg/virsh_cmd/host/virsh_nodeinfo.cfg b/libvirt/tests/cfg/virsh_cmd/host/virsh_nodeinfo.cfg index 025034b28d7..fa07d7c02aa 100644 --- a/libvirt/tests/cfg/virsh_cmd/host/virsh_nodeinfo.cfg +++ b/libvirt/tests/cfg/virsh_cmd/host/virsh_nodeinfo.cfg @@ -4,6 +4,9 @@ start_vm = no virsh_node_options = "" status_error = "no" + check_frequency = yes + aarch64: + check_frequency = no variants test_case: - no_option: libvirtd = "on" diff --git a/libvirt/tests/src/virsh_cmd/host/virsh_nodeinfo.py b/libvirt/tests/src/virsh_cmd/host/virsh_nodeinfo.py index eea3b346885..56a8421a586 100644 --- a/libvirt/tests/src/virsh_cmd/host/virsh_nodeinfo.py +++ b/libvirt/tests/src/virsh_cmd/host/virsh_nodeinfo.py @@ -106,11 +106,12 @@ def output_check(nodeinfo_output): # that it's within 20 percent of each value to give us enough of # a "fudge" factor to declare "close enough". Don't return a failure # just print a debug message and move on. - diffval = abs(int(cpu_frequency_nodeinfo) - int(cpu_frequency_os)) - if (float(diffval) / float(cpu_frequency_nodeinfo) > 0.20 or - float(diffval) / float(cpu_frequency_os) > 0.20): - logging.debug("Virsh nodeinfo output didn't match CPU " - "frequency within 20 percent") + if 'yes' == params.get('check_frequency', 'no'): + diffval = abs(int(cpu_frequency_nodeinfo) - int(cpu_frequency_os)) + if (float(diffval) / float(cpu_frequency_nodeinfo) > 0.20 or + float(diffval) / float(cpu_frequency_os) > 0.20): + logging.debug("Virsh nodeinfo output didn't match CPU " + "frequency within 20 percent") # Get CPU topology from virsh capabilities xml cpu_topology = capability_xml.CapabilityXML()['cpu_topology'] From b231c3958cd3e38316f9f1db259ce6a4d3d3aaf2 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Thu, 2 Jan 2025 14:58:11 +0800 Subject: [PATCH 0768/1055] virtual_network: Add a vdpa test This PR adds: VIRT-302249: Check opened fd on vdpa device is closed when device attaching failed Signed-off-by: Yingshun Cui --- .../rollback_vdpafd_on_hotplug_failure.cfg | 9 +++ .../rollback_vdpafd_on_hotplug_failure.py | 55 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/hotplug/attach_detach_device/rollback_vdpafd_on_hotplug_failure.cfg create mode 100644 libvirt/tests/src/virtual_network/hotplug/attach_detach_device/rollback_vdpafd_on_hotplug_failure.py diff --git a/libvirt/tests/cfg/virtual_network/hotplug/attach_detach_device/rollback_vdpafd_on_hotplug_failure.cfg b/libvirt/tests/cfg/virtual_network/hotplug/attach_detach_device/rollback_vdpafd_on_hotplug_failure.cfg new file mode 100644 index 00000000000..fd5797b058e --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/hotplug/attach_detach_device/rollback_vdpafd_on_hotplug_failure.cfg @@ -0,0 +1,9 @@ +- virtual_network.hotplug.rollback.vdpa_interface: + type = rollback_vdpafd_on_hotplug_failure + start_vm = no + test_target = mellanox + vdpa_dev = "vdpa0" + iface_dict = {'source': {'dev': '/dev/vhost-vdpa-0'}, 'acpi': {'index': '1'}} + iface_dict2 = {'source': {'dev': '/dev/vhost-vdpa-1'}, 'acpi': {'index': '1'}} + func_supported_since_libvirt_ver = (10, 8, 0) + only x86_64 diff --git a/libvirt/tests/src/virtual_network/hotplug/attach_detach_device/rollback_vdpafd_on_hotplug_failure.py b/libvirt/tests/src/virtual_network/hotplug/attach_detach_device/rollback_vdpafd_on_hotplug_failure.py new file mode 100644 index 00000000000..c000eeeaa87 --- /dev/null +++ b/libvirt/tests/src/virtual_network/hotplug/attach_detach_device/rollback_vdpafd_on_hotplug_failure.py @@ -0,0 +1,55 @@ +from provider.interface import interface_base +from provider.interface import vdpa_base + +from avocado.utils import process + +from virttest import libvirt_version +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt + + +def run(test, params, env): + """ + Check opened fd on vdpa device is closed when device attaching failed + """ + + libvirt_version.is_libvirt_feature_supported(params) + + # Variable assignment + test_target = params.get('test_target', '') + dev_type = params.get('dev_type', 'vdpa') + iface_dict2 = eval(params.get("iface_dict2", "{}")) + iface2_dev = iface_dict2["source"]["dev"] + + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + backup_vmxml = vmxml.copy() + + test_obj = None + try: + test_obj, _ = vdpa_base.setup_vdpa(vm, params) + test.log.info("TEST_STEP: Start a vm, attach a vdpa interface with " + "acpi index=1.") + vm.start() + interface_base.attach_iface_device(vm_name, dev_type, params) + + test.log.info("TEST_STEP: Hotplug another vdpa interface with " + "acpi index=1.") + iface2 = interface_base.create_iface("vdpa", iface_dict2) + res = virsh.attach_device(vm.name, iface2.xml, debug=True) + libvirt.check_exit_status(res, True) + res = process.run(f"lsof {iface2_dev}", verbose=True, ignore_status=True) + libvirt.check_exit_status(res, True) + if res.stdout_text: + test.fail(f"{iface2_dev} may be used by qemu - {res.stdout_text}") + + test.log.info("TEST_STEP: Hotplug another vdpa interface with " + "acpi index=2.") + iface2.setup_attrs(**{'acpi': {'index': '2'}}) + virsh.attach_device(vm.name, iface2.xml, debug=True, ignore_status=False) + finally: + backup_vmxml.sync() + vdpa_base.cleanup_vdpa(test_target, test_obj) From 37691887beb92d2cd0ea7de6ba0b6e71a6fb8efd Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 2 Jan 2025 03:22:57 -0500 Subject: [PATCH 0769/1055] connectivity_check_user_interface:Fix error when setting mac_address The value of mac getting from vmxml could be None when there's no interface on vm which could lead to Error when trying to set the value to new interface. Signed-off-by: Haijiao Zhao --- .../connectivity/connectivity_check_user_interface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py index 331abb81731..3a55e488586 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py @@ -95,7 +95,7 @@ def run(test, params, env): vmxml.del_device('interface', by_tag=True) vmxml.sync(virsh_instance=virsh_ins) iface = libvirt_vmxml.create_vm_device_by_type( - 'interface', {**iface_attrs, **{'mac_address': mac}}) + 'interface', {**iface_attrs, **({'mac_address': mac} if mac else {})}) vmxml.add_device(iface) define_result = virsh.define(vmxml.xml, debug=True, uri=virsh_uri) libvirt.check_exit_status(define_result, expect_error) From d86da52fa92f781f142d9c7b1184061239dcb3f9 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Thu, 2 Jan 2025 20:55:53 -0500 Subject: [PATCH 0770/1055] Change request size to fit for 512mb block size on aarch64 64k kernel Signed-off-by: liang-cong-red-hat --- .../virtio_mem_with_memory_allocation_and_numa.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.cfg index b3fd48b4a7b..124f88d0f9a 100644 --- a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.cfg @@ -61,7 +61,7 @@ - virtio_mem_with_exceed_size: only without_numa.with_maxmemory target_size = "10485760" - request_size = "256" + request_size = "512" target_size_unit = "KiB" virtio_mem_dict = {'mem_model': '${mem_model}', 'target': {'requested_unit': '${request_size_unit}', 'size': ${target_size}, 'size_unit': '${target_size_unit}', 'requested_size': ${request_size}, 'block_unit': 'KiB', 'block_size': %s}} coldplug_start_error = "${err_msg2}" From 09bee98902d45d79039c8e4afe21a520d43bbeab Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Fri, 3 Jan 2025 16:55:59 +0800 Subject: [PATCH 0771/1055] memory_misc: fix cleanup error The cleanup step needs to check if the setup is finished successfully. Signed-off-by: Dan Zheng --- libvirt/tests/src/memory/memory_misc.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/memory/memory_misc.py b/libvirt/tests/src/memory/memory_misc.py index c4a0adb5e79..8214a071736 100644 --- a/libvirt/tests/src/memory/memory_misc.py +++ b/libvirt/tests/src/memory/memory_misc.py @@ -243,7 +243,7 @@ def _setup_mbxml(): if cancel: test.cancel('Setting pagenum of numa nodes failed, ' 'please check log') - + params["hp_cfg"] = hp_cfg # Setup vmxml: Add memory device mem_device = Memory() mem_device_attrs = eval(params.get('mem_device_attrs')) @@ -268,6 +268,7 @@ def _setup_mbxml(): hp_cfg = test_setup.HugePageConfig(params) hp_cfg.set_kernel_hugepages(pagesize, vm_mem_size // pagesize, False) hp_cfg.set_kernel_hugepages(mount_pagesize, mem_device_size // mount_pagesize, False) + params["hp_cfg"] = hp_cfg set_vmxml(vmxml, params) _setup_mbxml() vmxml.sync() @@ -448,13 +449,18 @@ def cleanup_test_memorybacking(case): hp_cfg = test_setup.HugePageConfig(params) hp_cfg.set_kernel_hugepages(pagesize, params['page_num_bk']) if case == 'hp_from_2_numa_nodes': + hp_cfg = params.get("hp_cfg") + if hp_cfg is None: + return restore_hugepages() if case == 'mount_hp_running_vm': + hp_cfg = params.get("hp_cfg") + if hp_cfg is None: + return mount_path = params.get('mount_path') utils_disk.umount('hugetlbfs', mount_path, 'hugetlbfs') if os.path.exists(mount_path): os.rmdir(mount_path) - hp_cfg = test_setup.HugePageConfig(params) hp_cfg.set_kernel_hugepages(int(params.get('mount_pagesize')), 0) hp_cfg.cleanup() From fcca6d6bf9cf95b7a2e910625e7996f95cc64bc2 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Mon, 6 Jan 2025 10:53:16 +0800 Subject: [PATCH 0772/1055] guest_os_booting: Fix a case error There is no particular order in which devices with no bootindex property set will be considered for booting. So it is possible to enter the disk system even without cdrom. Signed-off-by: Yingshun Cui --- .../guest_os_booting/boot_order/boot_from_cdrom_device.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg index 64edc39d915..ec07d8d0392 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg @@ -7,12 +7,12 @@ - without_cdrom: only os_dev aarch64: - bootable_patterns = ["Shell>"] + bootable_patterns = ["Shell>", "Booting .* on physical CPU"] - with_cdrom_with_no_src: cdrom1_attrs = {'target': {'dev': 'sda', 'bus': 'sata'}, **${cdrom_attrs}} aarch64: cdrom1_attrs = {'target': {'dev': 'sda', 'bus': 'scsi'}, **${cdrom_attrs}} - bootable_patterns = ["Shell>"] + bootable_patterns = ["Shell>", "Booting .* on physical CPU"] - with_cdrom: check_bootable_iso = "yes" cdrom1_attrs = {'source': {'attrs': {'file': boot_img_path}}, 'target': {'dev': 'sda', 'bus': 'scsi'}, **${cdrom_attrs}} From 92e17edafab55a02d69ad6fbbf915872c2841904 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Mon, 6 Jan 2025 14:45:56 +0800 Subject: [PATCH 0773/1055] guest_os_booting: Fix nvram_attrs xml comparison failure Signed-off-by: Yingshun Cui --- .../src/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.py | 2 ++ .../guest_os_booting/ovmf_firmware/ovmf_seclabel_in_nvram.py | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.py b/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.py index 22508b31c8d..8a67987dd6d 100644 --- a/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.py +++ b/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.py @@ -32,6 +32,8 @@ def compare_guest_xml(vmxml, os_attrs): if key in current_os_attrs: if key == "nvram_attrs": current_os_attrs[key].pop("templateFormat") + if "format" not in os_attrs[key]: + os_attrs[key]["format"] = "raw" if os_attrs[key] != current_os_attrs[key]: test.fail("Configured os xml value {} doesn't match the" " entry {} in guest xml".format(os_attrs[key], current_os_attrs[key])) diff --git a/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_seclabel_in_nvram.py b/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_seclabel_in_nvram.py index 280d3f9f036..56d10bc7b7e 100644 --- a/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_seclabel_in_nvram.py +++ b/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_seclabel_in_nvram.py @@ -31,6 +31,11 @@ def compare_guest_xml(vmxml, os_attrs): current_os_attrs = os_xml.fetch_attrs() for key in os_attrs: if key in current_os_attrs: + if key == "nvram_attrs": + current_os_attrs[key].pop("templateFormat") + if "format" not in os_attrs[key]: + os_attrs[key]["format"] = "raw" + if os_attrs[key] != current_os_attrs[key]: test.fail("Configured os xml value {} doesn't match the" " entry {} in guest xml".format(os_attrs[key], current_os_attrs[key])) From d8e2fc0c4df5b73c63dd94d2519bde36cd7c1dd1 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Thu, 2 Jan 2025 15:07:47 +0800 Subject: [PATCH 0774/1055] vIOMMU: Add tests of intel iommu without ioapic feature Update to cover intremap on and off. Signed-off-by: Yingshun Cui --- .../vIOMMU/intel_iommu_without_ioapic.cfg | 8 ++++- .../vIOMMU/intel_iommu_without_ioapic.py | 30 +++++++++++-------- spell.ignore | 2 ++ 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_without_ioapic.cfg b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_without_ioapic.cfg index f4c9f5168bc..77c03b0822d 100644 --- a/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_without_ioapic.cfg +++ b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_without_ioapic.cfg @@ -3,6 +3,12 @@ start_vm = "yes" enable_guest_iommu = "yes" feature_name = "ioapic" - err_msg = "IOMMU interrupt remapping requires split I/O APIC" iommu_dict = {'model': 'intel', 'driver': {'intremap': 'on'}} only q35 + variants: + - default: + iommu_dict = {'model': 'intel'} + - intremap_on: + func_supported_since_libvirt_ver = (10, 10, 0) + iommu_dict = {'model': 'intel', 'driver': {'intremap': 'on'}} + auto_add_ioapic = "yes" diff --git a/libvirt/tests/src/sriov/vIOMMU/intel_iommu_without_ioapic.py b/libvirt/tests/src/sriov/vIOMMU/intel_iommu_without_ioapic.py index 1c9a321a62d..b7b3cb52524 100644 --- a/libvirt/tests/src/sriov/vIOMMU/intel_iommu_without_ioapic.py +++ b/libvirt/tests/src/sriov/vIOMMU/intel_iommu_without_ioapic.py @@ -1,15 +1,17 @@ +from virttest import libvirt_version +from virttest import virsh from virttest.libvirt_xml import vm_xml -from virttest.libvirt_xml import xcepts from virttest.utils_libvirt import libvirt_vmxml def run(test, params, env): """ - Check for the error message when using an Intel iommu device - but without defined in the VM + libvirt will automatically add "" + if is set for the intel iommu device """ + libvirt_version.is_libvirt_feature_supported(params) iommu_dict = eval(params.get('iommu_dict', '{}')) - err_msg = params.get("err_msg", "I/O APIC") + auto_add_ioapic = params.get("auto_add_ioapic", "no") == "yes" feature_name = params.get("feature_name", "ioapic") vm_name = params.get("main_vm", "avocado-vt-vm1") @@ -27,15 +29,17 @@ def run(test, params, env): iommu_dev = libvirt_vmxml.create_vm_device_by_type('iommu', iommu_dict) vmxml.add_device(iommu_dev) vmxml.xmltreefile.write() - try: - vmxml.sync() - except xcepts.LibvirtXMLError as details: - test.log.debug("Check '%s' in %s.", err_msg, details) - if not str(details).count(err_msg): - test.fail("Incorrect error message, it should be '{}', but " - "got '{}'.".format(err_msg, details)) + vmxml.sync() + + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + features = vmxml.features + tmp_msg = "" if auto_add_ioapic else "not " + msg = (f"{feature_name} should {tmp_msg}be " + f"added automatically! Actual feature list: {features}") + if auto_add_ioapic == features.has_feature(feature_name): + test.log.debug(msg) else: - test.fail("Vm is expected to fail on defining with intel iommu " - "without ioapic feature, while it succeeds.") + test.fail(msg) + virsh.start(vm.name, debug=True, ignore_status=False) finally: backup_vmxml.sync() diff --git a/spell.ignore b/spell.ignore index 819b5d464e9..91c416ce837 100644 --- a/spell.ignore +++ b/spell.ignore @@ -435,6 +435,8 @@ inodes inpect installable installroot +intel +intremap invtsc inx io From f4977f1503453383afb5214a0e864b3cdb8c702c Mon Sep 17 00:00:00 2001 From: hholoubk Date: Fri, 3 Jan 2025 14:12:56 +0100 Subject: [PATCH 0775/1055] configuration udpate and better cfg. issue resolution --- .../migration_network_data_transport_tls.cfg | 2 +- provider/migration/base_steps.py | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls.cfg b/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls.cfg index e085a2bb8f3..a4b4cb46286 100644 --- a/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls.cfg +++ b/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls.cfg @@ -52,7 +52,7 @@ libvirtd_debug_level = "1" libvirtd_debug_filters = "1:*" check_str_local_log = '['"dir":"/etc/pki/qemu","endpoint":"client","verify-peer":true']' - check_str_remote_log = '"dir":"/etc/pki/qemu","endpoint":"server","verify-peer":true' + check_str_remote_log = '['"dir":"/etc/pki/qemu","endpoint":"server","verify-peer":true']' action_during_mig = '[{"func": "libvirt_network.check_established", "after_event": "iteration: \'1\'", "func_param": "params"}, {"func": "set_migrate_speed_to_high", "func_param": "params"}]' - tls_destination: no with_postcopy diff --git a/provider/migration/base_steps.py b/provider/migration/base_steps.py index 19d0085ba55..c5a7c3562db 100644 --- a/provider/migration/base_steps.py +++ b/provider/migration/base_steps.py @@ -368,10 +368,13 @@ def check_local_and_remote_log(self, local_str_in_log=True, remote_str_in_log=Tr :param remote_str_in_log: True if the remote file should include the given string, otherwise, False """ - check_str_local_log = eval(self.params.get("check_str_local_log", "[]")) - check_no_str_local_log = eval(self.params.get("check_no_str_local_log", "[]")) - check_str_remote_log = eval(self.params.get("check_str_remote_log", "[]")) - check_no_str_remote_log = eval(self.params.get("check_no_str_remote_log", "[]")) + try: + check_str_local_log = eval(self.params.get("check_str_local_log", "[]")) + check_no_str_local_log = eval(self.params.get("check_no_str_local_log", "[]")) + check_str_remote_log = eval(self.params.get("check_str_remote_log", "[]")) + check_no_str_remote_log = eval(self.params.get("check_no_str_remote_log", "[]")) + except Exception as e: + self.test.error(f"Wrong test configuration. Unable to eval one or more parameter(s): {str(e)}") log_file = self.params.get("libvirtd_debug_file") runner_on_target = None From 6d431dfebc00dc82b4f8b2622796b4e6040dc9b9 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Thu, 2 Jan 2025 02:44:25 -0500 Subject: [PATCH 0776/1055] Add default value 0 when specific cpu topology file is missing Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/numa/numa_capabilities.cfg | 3 +++ libvirt/tests/src/numa/numa_capabilities.py | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/libvirt/tests/cfg/numa/numa_capabilities.cfg b/libvirt/tests/cfg/numa/numa_capabilities.cfg index c5517496817..34254c60fdf 100644 --- a/libvirt/tests/cfg/numa/numa_capabilities.cfg +++ b/libvirt/tests/cfg/numa/numa_capabilities.cfg @@ -5,3 +5,6 @@ status_error = "no" variants: - default: + aarch64: + missing_cpu_topology_key = 'die_id' + diff --git a/libvirt/tests/src/numa/numa_capabilities.py b/libvirt/tests/src/numa/numa_capabilities.py index fe39e923887..942e3d2e0d4 100644 --- a/libvirt/tests/src/numa/numa_capabilities.py +++ b/libvirt/tests/src/numa/numa_capabilities.py @@ -14,6 +14,7 @@ def run(test, params, env): """ Test capabilities with host numa node topology """ + missing_cpu_topology_key = params.get("missing_cpu_topology_key") libvirtd = utils_libvirtd.Libvirtd() libvirtd.start() try: @@ -49,6 +50,10 @@ def run(test, params, env): cpu_topo_list = [] for cpu_id in cpu_list: cpu_dict = node_.get_cpu_topology(cpu_id) + # if specific cpu topology file from sysfs doesn't exist, default 0 + # would be used in virsh capabilities + if missing_cpu_topology_key and cpu_dict[missing_cpu_topology_key] is None: + cpu_dict[missing_cpu_topology_key] = '0' cpu_topo_list.append(cpu_dict) logging.debug("cpu topology list from capabilities xml is %s", cpu_list_from_xml) From 05b6881a68675f74de226e5cf7c72093c54f2754 Mon Sep 17 00:00:00 2001 From: Kowshik Jois B S Date: Mon, 6 Jan 2025 14:31:29 +0530 Subject: [PATCH 0777/1055] Qemu: snapshot: Don't forbid snapshot if autodestroy is registered! Signed-off-by: Kowshik Jois B S Description: On v5.8.0 and later versions of lobvirt, it is allowed to take the snapshot of guests created with 'autodestroy' since semantically VIR_DOMAIN_START_AUTODESTROY doesn't really clash with snapshot operations as the VM stays on the same host and thus bound to the same connection. Referrece commit: https://gitlab.com/libvirt/libvirt/-/commit/045a8e197c1e14faa1c32bd637033838269094a2 --- .../src/virsh_cmd/snapshot/virsh_snapshot_create_as.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/snapshot/virsh_snapshot_create_as.py b/libvirt/tests/src/virsh_cmd/snapshot/virsh_snapshot_create_as.py index fa629d49187..a1a3494e7a4 100644 --- a/libvirt/tests/src/virsh_cmd/snapshot/virsh_snapshot_create_as.py +++ b/libvirt/tests/src/virsh_cmd/snapshot/virsh_snapshot_create_as.py @@ -594,7 +594,14 @@ def run(test, params, env): # check status_error if status_error == "yes": if status == 0: - test.fail("Run successfully with wrong command!") + # snapshots can be created for the guests created + # with 'autodestroy' option on libvirt v5.8.0 and above! + if libvirt_version.version_compare(5, 8, 0) and \ + create_autodestroy: + logging.info("Run passed as expected in " + "libvirt version >= 5.8.0") + else: + test.fail("Run successfully with wrong command!") else: # Check memspec file should be removed if failed if (options.find("memspec") >= 0 and From c1c49620f1b21ee5e89e98417fda0191d9e00281 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 6 Jan 2025 00:16:33 -0500 Subject: [PATCH 0778/1055] Add adaption for aarch64 huge pages Previously, this case has cpu flag checking for 2M and 1G huge page only for x86_64, so it is not fit for aarch64. So this fix is to add aarch64 supported huge page sizes and remove the cpu flag checking. Signed-off-by: liang-cong-red-hat --- .../cfg/virsh_cmd/host/virsh_freepages.cfg | 42 +++++++++ .../src/virsh_cmd/host/virsh_freepages.py | 91 ++++++++++--------- 2 files changed, 88 insertions(+), 45 deletions(-) diff --git a/libvirt/tests/cfg/virsh_cmd/host/virsh_freepages.cfg b/libvirt/tests/cfg/virsh_cmd/host/virsh_freepages.cfg index 9225f070bec..11539c77ae6 100644 --- a/libvirt/tests/cfg/virsh_cmd/host/virsh_freepages.cfg +++ b/libvirt/tests/cfg/virsh_cmd/host/virsh_freepages.cfg @@ -6,6 +6,7 @@ variants: - positive_test: status_error = "no" + hugepage_allocation_dict = {'64':256, '2048':64, '32768':8, '524288':4, '1048576':2, '16777216':1} variants: - option_all: freepages_option = "--all" @@ -17,20 +18,60 @@ freepages_pagesize = "EACH" - pagesize_2M: freepages_pagesize = "2M" + pagesize_kb = '2048' - pagesize_2048: freepages_pagesize = "2048" + pagesize_kb = '2048' - pagesize_2048K: freepages_pagesize = "2048K" + pagesize_kb = '2048' - pagesize_2048kib: freepages_pagesize = "2048kib" + pagesize_kb = '2048' - pagesize_1G: freepages_pagesize = "1G" + pagesize_kb = '1048576' - pagesize_1048576: freepages_pagesize = "1048576" + pagesize_kb = '1048576' - pagesize_1048576K: freepages_pagesize = "1048576K" + pagesize_kb = '1048576' - pagesize_1048576KIB: freepages_pagesize = "1048576KIB" + pagesize_kb = '1048576' + - pagesize_524288: + only aarch64 + freepages_pagesize = "524288" + pagesize_kb = '524288' + - pagesize_512M: + only aarch64 + freepages_pagesize = "512M" + pagesize_kb = '524288' + - pagesize_64: + only aarch64 + freepages_pagesize = "64" + pagesize_kb = '64' + - pagesize_64K: + only aarch64 + freepages_pagesize = "64K" + pagesize_kb = '64' + - pagesize_32768: + only aarch64 + freepages_pagesize = "32768" + pagesize_kb = '32768' + - pagesize_32M: + only aarch64 + freepages_pagesize = "32M" + pagesize_kb = '32768' + - pagesize_16G: + only aarch64 + freepages_pagesize = "16G" + pagesize_kb = '16777216' + - pagesize_16777216: + only aarch64 + freepages_pagesize = "16777216" + pagesize_kb = '16777216' - negative_test: status_error = "yes" variants: @@ -47,3 +88,4 @@ - invalid_page_size: freepages_cellno = "0" freepages_pagesize = "-1" + diff --git a/libvirt/tests/src/virsh_cmd/host/virsh_freepages.py b/libvirt/tests/src/virsh_cmd/host/virsh_freepages.py index 5ca259087bc..15106debc50 100644 --- a/libvirt/tests/src/virsh_cmd/host/virsh_freepages.py +++ b/libvirt/tests/src/virsh_cmd/host/virsh_freepages.py @@ -1,10 +1,11 @@ import logging as log import time +from avocado.utils import memory as avocado_mem + from virttest import virsh from virttest import test_setup from virttest import utils_misc -from virttest.libvirt_xml import vm_xml from virttest.utils_test import libvirt as utlv @@ -78,14 +79,19 @@ def check_freepages(output, expect_result_list): return False not in check_result -def modify_expect(cell, expect, pagesize='4KiB'): +def modify_expect(cell, expect): """ - For 4KiB freepages checking, if the gap between freepages command return - with system current freememory is less than 4*1024Kib, check would pass. + For default page size freepages checking, if the gap between freepages command return + with system current freememory is less than 'default page size' * 1024Kib, check would pass. + + :params cell: free pages dict of single node + :params expect: expected free page dict """ - if pagesize in expect.keys(): - if abs(int(float(expect[pagesize])) - int(float(cell[pagesize]))) < 1024: - expect[pagesize] = cell[pagesize] + default_pagesize = int(avocado_mem.get_page_size() / 1024) + pagesize_key = f'{default_pagesize}KiB' + if pagesize_key in expect.keys(): + if abs(int(float(expect[pagesize_key])) - int(float(cell[pagesize_key]))) < 1024: + expect[pagesize_key] = cell[pagesize_key] def run(test, params, env): @@ -99,20 +105,19 @@ def get_freepages_number_of_node(node, pagesize): :params node: node No :params pagesize: page size, for example: '4', '2048', '1048576' - For pagesize is '4' which is not hugepage, get free memory from + For pagesize is default page size which is not hugepage, get free memory from `grep MemFree /sys/devices/system/node/node${node}/meminfo` For pagesize '2048' or '1048576', get free page number from /sys/devices/system/node/nodei${node}/hugepages/ hugepages-${pagesize}/free_hugepages :return: integer number of free pagesize """ - if pagesize == '4': + if pagesize == default_pagesize: node_meminfo = host_numa_node.read_from_node_meminfo(node, 'MemFree') - return int(node_meminfo) / 4 - else: - return hp_cl.get_node_num_huge_pages(node, pagesize, type='free') + return int(node_meminfo) / int(default_pagesize) + return hp_cl.get_node_num_huge_pages(node, pagesize, type='free') - def check_hugepages_allocated_status(is_type_check, pagesize, quantity): + def check_hugepages_allocated_status(pagesize, quantity): """ Allocate some specific hugepages and check whether the number of this specific hugepages allocated by kernel totally is equal to the sum that @@ -120,14 +125,11 @@ def check_hugepages_allocated_status(is_type_check, pagesize, quantity): for each node is equal to the number allocated by kernel for each node. If yes, return True, else return False. - :params is_type_check: Flag to determine do this check or not :params pagesize: pagesize type needed to check :params quantity: the number will be allocated :return: True if current system support this pagesize and allocate page successfully, otherwise return False """ - if not is_type_check or pagesize not in supported_hp_size: - return False hp_cl.set_kernel_hugepages(pagesize, quantity) # kernel need some time to prepare hugepages due to maybe there # are some memory fragmentation. @@ -163,10 +165,19 @@ def check_hugepages_allocated_status(is_type_check, pagesize, quantity): "equal to kernel allocated totally." % pagesize) return True + def cleanup(): + """ + Clean up all supported huge page size allocation + """ + for hp_size in hp_cl.get_multi_supported_hugepage_size(): + hp_cl.set_kernel_hugepages(hp_size, 0) + option = params.get("freepages_option", "") status_error = "yes" == params.get("status_error", "no") cellno = params.get("freepages_cellno") pagesize = params.get("freepages_pagesize") + pagesize_kb = params.get("pagesize_kb") + hugepage_allocation_dict = eval(params.get("hugepage_allocation_dict", "{}")) host_numa_node = utils_misc.NumaInfo() node_list = host_numa_node.get_online_nodes_withmem() @@ -175,6 +186,8 @@ def check_hugepages_allocated_status(is_type_check, pagesize, quantity): hp_cl = test_setup.HugePageConfig(params) supported_hp_size = hp_cl.get_multi_supported_hugepage_size() + default_pagesize = str(int(avocado_mem.get_page_size() / 1024)) + cellno_list = [] if cellno == "EACH": cellno_list = node_list @@ -183,35 +196,23 @@ def check_hugepages_allocated_status(is_type_check, pagesize, quantity): else: cellno_list.append(cellno) - # Add 4K pagesize - supported_hp_size.insert(0, '4') - pagesize_list = [] + # Add default pagesize + supported_hp_size.insert(0, str(int(avocado_mem.get_page_size() / 1024))) + pagesize_list, pagesize_kb_list = [], [] if pagesize == "EACH": - pagesize_list = supported_hp_size + pagesize_list = pagesize_kb_list = supported_hp_size else: pagesize_list.append(pagesize) + pagesize_kb_list.append(pagesize_kb) if not status_error: - # Get if CPU support 2M-hugepages - check_2M = vm_xml.VMCPUXML.check_feature_name('pse') - # Get if CPU support 1G-hugepages - check_1G = vm_xml.VMCPUXML.check_feature_name('pdpe1gb') - if not check_2M and not check_1G: - test.cancel("pse and pdpe1gb flags are not supported by CPU.") - - num_1G = str(1024*1024) - num_2M = str(2048) - - # Let kernel allocate 64 of 2M hugepages at runtime - quantity_2M = 64 - # Let kernel allocate 2 of 1G hugepages at runtime - quantity_1G = 2 - check_2M = check_hugepages_allocated_status(check_2M, num_2M, quantity_2M) - check_1G = check_hugepages_allocated_status(check_1G, num_1G, quantity_1G) - - if not check_2M and not check_1G: - test.cancel("Not enough free memory to support huge pages " - "in current system.") + for page_size in pagesize_kb_list: + if page_size is None or page_size == default_pagesize: + continue + if page_size not in supported_hp_size: + test.cancel("Required hugepage size %sKiB is not supported on this host." % page_size) + if not check_hugepages_allocated_status(page_size, hugepage_allocation_dict[page_size]): + test.cancel("Not enough %sKiB hugepage size allocated in current system." % page_size) # Run test for cell in cellno_list: @@ -221,11 +222,8 @@ def check_hugepages_allocated_status(is_type_check, pagesize, quantity): options=option, debug=True) # Unify pagesize unit to KiB - if page is not None: - if page.upper() in ['2M', '2048K', '2048KIB']: - page = num_2M - elif page.upper() in ['1G', '1048576K', '1048576KIB']: - page = num_1G + if page is not None and pagesize_kb is not None: + page = pagesize_kb # the node without memory will fail and it is expected if cell is not None and page is None and not status_error: status_error = True @@ -265,3 +263,6 @@ def check_hugepages_allocated_status(is_type_check, pagesize, quantity): else: test.fail("Huge page freepages check failed, " "expect result is %s" % expect_result_list) + + # clean up the huge page allocation + cleanup() From 8d426a6df0673244ee50a76b17082e86b02c7337 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 7 Jan 2025 14:26:59 +0800 Subject: [PATCH 0779/1055] guest_os_booting: Extend timeout of vm start up Update the timeout to make the case stable. Signed-off-by: Yingshun Cui --- .../guest_os_booting/boot_order/boot_with_multiple_boot_dev.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py index 11f879312cd..cf5c3f96d93 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_dev.py @@ -92,7 +92,7 @@ def run(test, params, env): vm.wait_for_login(timeout=360).close() test.log.debug("Succeed to boot %s", vm_name) else: - vm.serial_console.read_until_output_matches(check_prompt, timeout=300, + vm.serial_console.read_until_output_matches(check_prompt, timeout=600, internal_timeout=0.5) finally: bkxml.sync() From 7f259b9f99918fd20bcc79114b4ca0b4629740bb Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Tue, 7 Jan 2025 01:55:07 -0500 Subject: [PATCH 0780/1055] Add aarch64 adaption for minimal domain disk attach 1. Add aarch64 cpu required xml to minimal domain xml; 2. Add memory and current memory size parameters for aarch64 suggestion; 3. Add aarch64 machine type parameter; Signed-off-by: liang-cong-red-hat --- .../virtual_disks/virtual_disks_multidisks.cfg | 7 +++++++ .../virtual_disks/virtual_disks_multidisks.py | 18 +++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_multidisks.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_multidisks.cfg index c14882c05e7..369987a7628 100644 --- a/libvirt/tests/cfg/virtual_disks/virtual_disks_multidisks.cfg +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_multidisks.cfg @@ -1084,6 +1084,13 @@ - disk_attach_with_minimal_xml: only coldplug test_minimal_xml = "yes" + memory_size = "1048576" + curr_mem_size = "1048576" + aarch64: + cpu_model_xml = "" + aarch64_machine_type = "virt" + memory_size = "4194304" + curr_mem_size = "4194304" disks_attach_option = "--live" virt_disk_device = "disk" virt_disk_device_source = "disk_minimal" diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_multidisks.py b/libvirt/tests/src/virtual_disks/virtual_disks_multidisks.py index 1a1849ef3ee..32f606440d5 100644 --- a/libvirt/tests/src/virtual_disks/virtual_disks_multidisks.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_multidisks.py @@ -1117,19 +1117,25 @@ def check_info_in_libvird_log_file(matchedMsg=None): # For minimal VM xml,it need reconstruct one. if test_minimal_xml: + cpu_model_xml = params.get("cpu_model_xml", "") + aarch64_machine_type = params.get("aarch64_machine_type") + memory_size = params.get("memory_size", "1048576") + curr_mem_size = params.get("curr_mem_size", "1048576") minimal_vm_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + machine_type = aarch64_machine_type if aarch64_machine_type else machine first_disk = vm.get_first_disk_devices() first_disk_source = first_disk['source'] minimal_vm_xml_file = minimal_vm_xml.xml minimal_xml_content = """ %s - 1048576 - 1048576 + %s + %s 1 hvm + %s /usr/libexec/qemu-kvm @@ -1138,7 +1144,13 @@ def check_info_in_libvird_log_file(matchedMsg=None): - """ % (vm_name, arch, machine, first_disk_source) + """ % (vm_name, + memory_size, + curr_mem_size, + arch, + machine_type, + cpu_model_xml, + first_disk_source) with open(minimal_vm_xml_file, 'w') as xml_file: xml_file.seek(0) xml_file.truncate() From 815355733169b366922533da752fdd2dc172e838 Mon Sep 17 00:00:00 2001 From: lcheng Date: Thu, 9 Jan 2025 22:42:05 +0800 Subject: [PATCH 0781/1055] libvirt_hooks: update network hooks According to RHEL-41168, update case. Signed-off-by: lcheng --- libvirt/tests/src/libvirt_hooks.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libvirt/tests/src/libvirt_hooks.py b/libvirt/tests/src/libvirt_hooks.py index 97b1ea5ebc3..169fb2eeb09 100644 --- a/libvirt/tests/src/libvirt_hooks.py +++ b/libvirt/tests/src/libvirt_hooks.py @@ -4,6 +4,7 @@ import platform import time +from avocado.utils import distro from avocado.utils import process from virttest import virt_vm @@ -53,6 +54,9 @@ def prepare_hook_file(hook_op): with open(hook_file, 'w') as hf: hf.write('\n'.join(hook_lines)) os.chmod(hook_file, 0o755) + if distro.detect().name == 'rhel' and int(distro.detect().version) > 9: + process.run("restorecon -Rv /etc/libvirt/hooks", ignore_status=False, shell=True) + process.run("setsebool -P virt_hooks_unconfined on", ignore_status=False, shell=True) # restart libvirtd libvirtd.restart() From ffbe5f6feabd852baea87e8fd2d03cde36a65253 Mon Sep 17 00:00:00 2001 From: lcheng Date: Fri, 10 Jan 2025 09:21:50 +0800 Subject: [PATCH 0782/1055] migration: Update error message Signed-off-by: lcheng --- .../migration_uri/tls_migrate_tls_x509_verify_on_target.cfg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/migration/migration_uri/tls_migrate_tls_x509_verify_on_target.cfg b/libvirt/tests/cfg/migration/migration_uri/tls_migrate_tls_x509_verify_on_target.cfg index 16e6a474895..79c1a502e39 100644 --- a/libvirt/tests/cfg/migration/migration_uri/tls_migrate_tls_x509_verify_on_target.cfg +++ b/libvirt/tests/cfg/migration/migration_uri/tls_migrate_tls_x509_verify_on_target.cfg @@ -45,7 +45,7 @@ - both_to_default: # Use default value for default_tls_x509_verify and migrate_tls_x509_verify default_qemu_conf = ["default_tls_x509_verify", "migrate_tls_x509_verify"] - err_msg = "Cannot read from TLS channel: Software caused connection abort" + err_msg = "Cannot read from TLS channel" migrate_again = "yes" status_error = "yes" migrate_again_status_error = "no" @@ -59,7 +59,7 @@ status_error = "no" - set_default_to_0_and_migrate_to_1: qemu_conf_dest = '{r".*default_tls_x509_verify\s*=.*": "default_tls_x509_verify=0", r".*migrate_tls_x509_verify\s*=.*": "migrate_tls_x509_verify=1"}' - err_msg = "Cannot read from TLS channel: Software caused connection abort" + err_msg = "Cannot read from TLS channel" migrate_again = "yes" status_error = "yes" migrate_again_status_error = "no" @@ -69,7 +69,7 @@ - set_default_to_1: default_qemu_conf = ["migrate_tls_x509_verify"] qemu_conf_dest = '{r".*default_tls_x509_verify\s*=.*": "default_tls_x509_verify=1"}' - err_msg = "Cannot read from TLS channel: Software caused connection abort" + err_msg = "Cannot read from TLS channel" migrate_again = "yes" status_error = "yes" migrate_again_status_error = "no" From 586c8f7ee641c1a95f370b1448a9ef722d27f57e Mon Sep 17 00:00:00 2001 From: lcheng Date: Fri, 10 Jan 2025 10:36:16 +0800 Subject: [PATCH 0783/1055] migration: Update error message Signed-off-by: lcheng --- .../cfg/migration/async_ops/destroy_vm_during_performphase.cfg | 2 +- .../migration_poweroff_vm.cfg | 2 ++ .../migration_uri/tls_migrate_tls_x509_verify_on_src.cfg | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/migration/async_ops/destroy_vm_during_performphase.cfg b/libvirt/tests/cfg/migration/async_ops/destroy_vm_during_performphase.cfg index a31660f2cf8..08c1d9eb303 100644 --- a/libvirt/tests/cfg/migration/async_ops/destroy_vm_during_performphase.cfg +++ b/libvirt/tests/cfg/migration/async_ops/destroy_vm_during_performphase.cfg @@ -62,4 +62,4 @@ expected_dest_state = "nonexist" expected_src_state = "shut off" action_during_mig = [{"func": "virsh.destroy", "after_event": "iteration: '1'", "func_param": {"name": "${main_vm}"}}] - err_msg = "domain is not running" + err_msg = "domain is not running|internal error: QEMU unexpectedly closed the monitor" diff --git a/libvirt/tests/cfg/migration/guest_lifecycle_operations_during_migration/migration_poweroff_vm.cfg b/libvirt/tests/cfg/migration/guest_lifecycle_operations_during_migration/migration_poweroff_vm.cfg index b204b0898c2..074a4e460ac 100644 --- a/libvirt/tests/cfg/migration/guest_lifecycle_operations_during_migration/migration_poweroff_vm.cfg +++ b/libvirt/tests/cfg/migration/guest_lifecycle_operations_during_migration/migration_poweroff_vm.cfg @@ -55,3 +55,5 @@ with_postcopy: poweroff_vm_dest = "yes" virsh_migrate_src_state = "paused" + with_precopy: + err_msg = "domain is not running|internal error: QEMU unexpectedly closed the monitor" diff --git a/libvirt/tests/cfg/migration/migration_uri/tls_migrate_tls_x509_verify_on_src.cfg b/libvirt/tests/cfg/migration/migration_uri/tls_migrate_tls_x509_verify_on_src.cfg index 88111031671..03ff374a0b3 100644 --- a/libvirt/tests/cfg/migration/migration_uri/tls_migrate_tls_x509_verify_on_src.cfg +++ b/libvirt/tests/cfg/migration/migration_uri/tls_migrate_tls_x509_verify_on_src.cfg @@ -33,7 +33,7 @@ qemu_conf_path = '/etc/libvirt/qemu.conf' transport_type = "tls" test_case = "migrate_tls_x509_verify_on_src" - err_msg = "Certificate does not match the hostname" + err_msg = "Certificate does not match the hostname|internal error: QEMU unexpectedly closed the monitor" status_error = "yes" qemu_conf_src = '{"default_tls_x509_verify": "0", "migrate_tls_x509_verify": "0"}' virsh_migrate_extra = "--tls" From 65825c6651864cae086ae305c7ab6cbce24d4dc7 Mon Sep 17 00:00:00 2001 From: lcheng Date: Fri, 10 Jan 2025 11:09:45 +0800 Subject: [PATCH 0784/1055] migration: Update case about io error Currently, we cannot write to disk in the VM of the target host after aborting migration. So update script. Signed-off-by: lcheng --- .../pause_and_io_error_and_recover.cfg | 4 ++-- .../pause_and_io_error_and_recover.py | 2 -- provider/migration/migration_base.py | 7 ++++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_and_io_error_and_recover.cfg b/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_and_io_error_and_recover.cfg index 723f0859c55..c8bd02afcfe 100644 --- a/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_and_io_error_and_recover.cfg +++ b/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_and_io_error_and_recover.cfg @@ -21,7 +21,7 @@ server_ip = "${migrate_dest_host}" server_user = "root" server_pwd = "${migrate_dest_pwd}" - check_network_accessibility_after_mig = "yes" + check_network_accessibility_after_mig = "no" migrate_desturi_port = "16509" migrate_desturi_type = "tcp" virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" @@ -31,7 +31,7 @@ stress_package = "stress" stress_args = "--cpu 8 --io 4 --vm 2 --vm-bytes 128M --timeout 20s" postcopy_options = "--timeout 4 --timeout-postcopy --postcopy" - action_during_mig = '[{"func": "libvirt_network.check_established", "after_event": "iteration: '1'", "func_param": 'params'}, {"func": "get_vm_serial_session_on_dest", "func_param": "params", "need_sleep_time": "10"}, {"func": "virsh.domjobabort", "func_param": "'%s --postcopy' % params.get('migrate_main_vm')"}]' + action_during_mig = '[{"func": "libvirt_network.check_established", "after_event": "iteration: '1'", "func_param": 'params'}, {"func": "write_vm_disk_on_dest", "func_param": "params", "need_sleep_time": "60"}, {"func": "virsh.domjobabort", "func_param": "'%s --postcopy' % params.get('migrate_main_vm')", "need_sleep_time": "5"}]' migrate_again = 'yes' migrate_again_status_error = 'no' action_during_mig_again = '[{"func": "set_migrate_speed_to_high", "before_pause": "yes", "func_param": "params"}]' diff --git a/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/pause_and_io_error_and_recover.py b/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/pause_and_io_error_and_recover.py index b85b2e317f0..148eb33c78b 100644 --- a/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/pause_and_io_error_and_recover.py +++ b/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/pause_and_io_error_and_recover.py @@ -26,8 +26,6 @@ def do_io_error(): test.log.debug("Do I/O Error.") shutil.chown(disk_source, "root", "root") - vm_session.cmd("echo 'do disk I/O error test' > /tmp/disk_io_error_test") - vm_session.close() def verify_test(): """ diff --git a/provider/migration/migration_base.py b/provider/migration/migration_base.py index 5efe665e464..fbafca039c0 100644 --- a/provider/migration/migration_base.py +++ b/provider/migration/migration_base.py @@ -720,9 +720,9 @@ def do_domjobabort(params): libvirt.check_result(ret, expected_fails=domjobabort_err_msg, check_both_on_error=True) -def get_vm_serial_session_on_dest(params): +def write_vm_disk_on_dest(params): """ - Get vm serial session on dest + Write vm's disk on dest :param params: dictionary with the test parameter, get dest uri and migration object """ @@ -733,7 +733,8 @@ def get_vm_serial_session_on_dest(params): migration_obj.vm.cleanup_serial_console() migration_obj.vm.create_serial_console() vm_session = migration_obj.vm.wait_for_serial_login(timeout=120) - params.update({"vm_session": vm_session}) + vm_session.cmd("while true; do echo 'do disk I/O error test' >> /tmp/disk_io_error_test; sleep 1; done &") + vm_session.close() migration_obj.vm.connect_uri = backup_uri From 728f871d4387730b52c1e92a699df01b3cd06e82 Mon Sep 17 00:00:00 2001 From: Julia Graham Date: Fri, 10 Jan 2025 16:32:37 -0500 Subject: [PATCH 0785/1055] virt_xml_validate: remove vm snapshot after use --- libvirt/tests/src/virt_cmd/virt_xml_validate.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/src/virt_cmd/virt_xml_validate.py b/libvirt/tests/src/virt_cmd/virt_xml_validate.py index f05e14eaee1..10424855ff2 100644 --- a/libvirt/tests/src/virt_cmd/virt_xml_validate.py +++ b/libvirt/tests/src/virt_cmd/virt_xml_validate.py @@ -34,6 +34,8 @@ def check_info(s1, s2, errorstr="Values differ"): cmd_result = virsh.snapshot_dumpxml(vm_name, snapshot_name, to_file=file) libvirt.check_exit_status(cmd_result) + cmd_result = virsh.snapshot_delete(vm_name, snapshot_name, to_file=file) + libvirt.check_exit_status(cmd_result) def network_validate(test, net_name, file=None, **virsh_dargs): From aecb32d6279112feb154f18d608a9a6200d8071c Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Mon, 16 Dec 2024 02:48:04 -0500 Subject: [PATCH 0786/1055] Update case of virtual network - qos - VIRT-296327 - [Qos] Check the actual network throughput per bandwidth settings in network/interface Signed-off-by: Haijiao Zhao --- .../qos/check_actual_network_throughput.cfg | 5 ++++- .../virtual_network/qos/check_actual_network_throughput.py | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput.cfg b/libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput.cfg index 5b89e7244e1..0ed26f8cf7e 100644 --- a/libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput.cfg +++ b/libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput.cfg @@ -32,4 +32,7 @@ iface_attrs = {'type_name': 'bridge', 'source': {'bridge': br_name}, 'model': 'virtio', **${iface_bw_attrs}} - ovs_br: iface_attrs = {'type_name': 'bridge', 'source': {'bridge': br_name}, 'model': 'virtio', **${iface_bw_attrs}, 'virtualport': {'type': 'openvswitch'}} - + libvirtd_debug_file = /var/log/libvirt/libvird.log + libvirtd_debug_level = 1 + expect_msg = warning.*Setting different .peak. value than .average. for QoS for OVS interface.*might have unexpected results + throuput_bw = 1024 diff --git a/libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py b/libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py index 59977f1b7fe..bb446730b92 100644 --- a/libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py +++ b/libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py @@ -38,6 +38,8 @@ def run(test, params, env): net_attrs = eval(params.get('net_attrs', '{}')) inbound = eval(params.get('inbound')) outbound = eval(params.get('outbound')) + throuput_bw = params.get('throuput_bw') + expect_msg = params.get('expect_msg') vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) bkxml = vmxml.copy() @@ -65,6 +67,9 @@ def run(test, params, env): vm.start() vm_sess = vm.wait_for_serial_login() + if expect_msg: + libvirt.check_logfile(expect_msg, + params.get("libvirtd_debug_file")) iface = network_base.get_iface_xml_inst(vm_name, 'on vm') mac = iface.mac_address @@ -105,7 +110,7 @@ def run(test, params, env): network_base.check_throughput( vm_sess.cmd, lambda x: process.run(x).stdout_text, - vm_ip, inbound["average"], 'inbound' + vm_ip, throuput_bw if throuput_bw else inbound["average"], 'inbound' ) network_base.check_throughput( From a86ce1e7cf0346566d9d1773da7dba3563ae0d63 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 13 Jan 2025 02:03:04 -0500 Subject: [PATCH 0787/1055] Change parameter check_str_remote_log to support eval to python list check_str_remote_log should be a string which could be parsed to a list by eval() Signed-off-by: liang-cong-red-hat --- .../migration/migration_with_vtpm/migration_with_shared_tpm.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg index 51959644a86..df785078daf 100644 --- a/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg +++ b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg @@ -23,7 +23,7 @@ tpm_cmd = "tpm2_getrandom --hex 16" auth_sec_dict = {"sec_ephemeral": "no", "sec_private": "yes", "sec_desc": "sample vTPM secret", "sec_usage": "vtpm", "sec_name": "VTPM_example"} secret_value = "sec value test" - check_str_remote_log = "migration release-lock-outgoing,incoming" + check_str_remote_log = ["migration release-lock-outgoing,incoming"] set_remote_libvirtd_log = "yes" libvirtd_file_type = "virtqemud" remote_file_type = "virtqemud" From 9b2a2d6b9282ac75608bce8723fc0f7765f6b8c9 Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 24 Jul 2024 13:06:28 +0800 Subject: [PATCH 0788/1055] migration: Update migration with shared tpm case Use the new directory instead of the swtpm directory as the path to store the image. Signed-off-by: lcheng --- .../migration_with_shared_tpm.cfg | 35 +++---- .../migration_with_shared_tpm.py | 93 ++++++++++--------- 2 files changed, 62 insertions(+), 66 deletions(-) diff --git a/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg index df785078daf..05fb3f74e13 100644 --- a/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg +++ b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg @@ -23,7 +23,7 @@ tpm_cmd = "tpm2_getrandom --hex 16" auth_sec_dict = {"sec_ephemeral": "no", "sec_private": "yes", "sec_desc": "sample vTPM secret", "sec_usage": "vtpm", "sec_name": "VTPM_example"} secret_value = "sec value test" - check_str_remote_log = ["migration release-lock-outgoing,incoming"] + check_str_remote_log = '["migration release-lock-outgoing,incoming"]' set_remote_libvirtd_log = "yes" libvirtd_file_type = "virtqemud" remote_file_type = "virtqemud" @@ -34,7 +34,12 @@ tpm_model = "tpm-crb" aarch64: tpm_model = "tpm-tis" - + swtpm_path = "/var/lib/libvirt/swtpm" + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} variants: - persistent_and_p2p: virsh_migrate_options = "--live --p2p --verbose --undefinesource --persistent" @@ -48,31 +53,15 @@ transient_vm = "yes" variants shared_storage_type: - nfs: - image_convert = "no" - storage_type = 'nfs' - setup_local_nfs = 'yes' - disk_type = "file" - disk_source_protocol = "netfs" - nfs_mount_dir = "/var/lib/libvirt/swtpm" - mnt_path_name = ${nfs_mount_dir} + nfs_export_dir = "/var/tmp" + src_mount_path = "${client_ip}:${nfs_export_dir}" tpm_security_contexts = "nfs_t" tpm_security_contexts_restore = "${tpm_security_contexts}" - ceph: - disk_type = "network" - nfs_mount_dir = - mnt_path_name = - setup_local_nfs = 'no' - disk_source_protocol = "rbd" - disk_source_port = "6789" - disk_source_name = "migration-with-vtpm-pool" tpm_security_contexts = "svirt_image_t" tpm_security_contexts_restore = "virt_var_lib_t" disk_dict = {"device": "disk", "type_name": "network", "driver": {"name": "qemu", "type": "raw", "cache": "none"}, "target": {"dev": "vda", "bus": "virtio"}} seclabel_dict = {"type": "static", "model": "selinux", "relabel": "yes", "label": "system_u:system_r:svirt_t:s0:c392,c662"} - cleanup_disks = "yes" - image_convert = "yes" - variants: - - non_auth: - mon_host = "EXAMPLE_MON_HOST" - disk_source_host = "EXAMPLE_HOSTS" - host_dict = {"name": "${disk_source_host}", "port": "${disk_source_port}"} + mon_host = "EXAMPLE_MON_HOST" + ceph_key = "EXAMPLE_CEPH_KEY" + src_mount_path = "${mon_host}:6789:/" diff --git a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py index 5a1d16123e1..b5f0ca31c1b 100644 --- a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py +++ b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py @@ -1,11 +1,10 @@ import os -from avocado.utils import distro from avocado.utils import process -from virttest import ceph from virttest import libvirt_version from virttest import remote +from virttest import utils_disk from virttest import utils_package from virttest import virsh @@ -163,34 +162,6 @@ def setup_vtpm(params, test, vm, migration_obj): vm.wait_for_login().close() -def prepare_ceph_disk(params, test, vm): - """ - Prepare ceph disk - - :param params: dict, test parameters - :param vm: VM object - :param test: test object - """ - mon_host = params.get("mon_host") - disk_source_name = params.get("disk_source_name") - seclabel_dict = eval(params.get("seclabel_dict", "{}")) - vm_name = params.get("migrate_main_vm") - - detected_distro = distro.detect() - rbd_img_prefix = '_'.join(['rbd', detected_distro.name, - detected_distro.version, - detected_distro.release, - detected_distro.arch]) - disk_source_name = os.path.join(disk_source_name, rbd_img_prefix + '.img') - params.update({"disk_source_name": disk_source_name}) - ceph.rbd_image_rm(mon_host, disk_source_name.split("/")[0], - disk_source_name.split("/")[1]) - vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) - vmxml.set_seclabel([seclabel_dict]) - vmxml.sync() - libvirt.set_vm_disk(vm, params) - - def run(test, params, env): """ Test migration with vtpm device with shared TPM state. @@ -206,9 +177,21 @@ def setup_nfs(): """ tpm_security_contexts = params.get("tpm_security_contexts") + swtpm_path = params.get("swtpm_path") + client_ip = params.get("client_ip") + nfs_export_dir = params.get("nfs_export_dir") + server_ip = params.get("server_ip", params.get("remote_ip")) + server_user = params.get("server_user", params.get("remote_user")) + server_pwd = params.get("server_pwd", params.get("remote_pwd")) + src_mount_path = params.get("src_mount_path") test.log.info("Setup for nfs storage type.") libvirt.set_vm_disk(vm, params) + if not os.path.exists(swtpm_path): + os.mkdir(swtpm_path) + libvirt.setup_or_cleanup_nfs(True, mount_dir=swtpm_path, is_mount=True, export_dir=nfs_export_dir) + server_session = remote.wait_for_login("ssh", server_ip, "22", server_user, server_pwd, r"[\#\$]\s*$") + utils_disk.mount(src_mount_path, swtpm_path, session=server_session) setup_vtpm(params, test, vm, migration_obj) check_tpm_security_context(params, vm, test, tpm_security_contexts) check_swtpm_process(params, test) @@ -220,18 +203,31 @@ def setup_ceph(): """ tpm_security_contexts = params.get("tpm_security_contexts") - mon_host = params.get("mon_host") set_remote_libvirtd_log = "yes" == params.get("set_remote_libvirtd_log", "no") + swtpm_path = params.get("swtpm_path") + seclabel_dict = eval(params.get("seclabel_dict", "{}")) + ceph_key = params.get("ceph_key") + src_mount_path = params.get("src_mount_path") + server_ip = params.get("server_ip", params.get("remote_ip")) + server_user = params.get("server_user", params.get("remote_user")) + server_pwd = params.get("server_pwd", params.get("remote_pwd")) test.log.info("Setup for ceph storage type.") if set_remote_libvirtd_log: migration_obj.set_remote_log() - cmd = "mount -t ceph %s:6789:/ /var/lib/libvirt/swtpm -o name=admin" % mon_host - process.run(cmd, ignore_status=False, shell=True) - remote.run_remote_cmd(cmd, params) - - prepare_ceph_disk(params, test, vm) + if not os.path.exists(swtpm_path): + os.mkdir(swtpm_path) + utils_disk.mount(src_mount_path, swtpm_path, fstype="ceph", options="name=admin,secret=%s" % ceph_key) + server_session = remote.wait_for_login("ssh", server_ip, "22", server_user, server_pwd, r"[\#\$]\s*$") + utils_disk.mount(src_mount_path, swtpm_path, fstype="ceph", options="name=admin,secret=%s" % ceph_key, session=server_session) + process.run("restorecon -Rv /var/lib/libvirt/swtpm", ignore_status=False, shell=True) + server_session.close() + + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + vmxml.set_seclabel([seclabel_dict]) + vmxml.sync() + libvirt.set_vm_disk(vm, params) setup_vtpm(params, test, vm, migration_obj) check_tpm_security_context(params, vm, test, tpm_security_contexts) check_swtpm_process(params, test) @@ -260,14 +256,27 @@ def verify_test_again(): vm.wait_for_shutdown() check_tpm_security_context(params, vm, test, tpm_security_contexts_restore) - def cleanup_ceph(): + def cleanup_test(): """ - Cleanup steps for ceph case + Cleanup steps """ - cmd = "umount /var/lib/libvirt/swtpm" - process.run(cmd, ignore_status=False, shell=True) - remote.run_remote_cmd(cmd, params) + src_mount_path = params.get("src_mount_path") + swtpm_path = params.get("swtpm_path") + nfs_export_dir = params.get("nfs_export_dir") + server_ip = params.get("server_ip", params.get("remote_ip")) + server_user = params.get("server_user", params.get("remote_user")) + server_pwd = params.get("server_pwd", params.get("remote_pwd")) + + test.log.info("Cleanup steps.") + server_session = remote.wait_for_login("ssh", server_ip, "22", server_user, server_pwd, r"[\#\$]\s*$") + if shared_storage_type == "ceph": + utils_disk.umount(src_mount_path, swtpm_path, fstype="ceph") + utils_disk.umount(src_mount_path, swtpm_path, fstype="ceph", session=server_session) + else: + utils_disk.umount("127.0.0.1:%s" % nfs_export_dir, swtpm_path) + utils_disk.umount(src_mount_path, swtpm_path, session=server_session) + server_session.close() migration_obj.cleanup_connection() vm_name = params.get("migrate_main_vm") @@ -279,8 +288,6 @@ def cleanup_ceph(): migration_obj = base_steps.MigrationBase(test, vm, params) setup_test = eval("setup_%s" % shared_storage_type) if "setup_%s" % shared_storage_type in \ locals() else migration_obj.setup_connection - cleanup_test = eval("cleanup_%s" % shared_storage_type) if "cleanup_%s" % shared_storage_type in \ - locals() else migration_obj.cleanup_connection try: set_secret(params) From 9104ed5b3c3256cf03115a268d2f325d2e8331ef Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Thu, 28 Nov 2024 22:30:14 -0500 Subject: [PATCH 0789/1055] Check the default backend for user type interface Since libvirt 10.8.0, to unify the xml for user type interface, for user type interface with backend as slirp, add the element, and the default backend is slirp. Signed-off-by: Yalan Zhang --- .../cfg/host_hypervisor/domcapabilities_output.cfg | 2 ++ .../connectivity_check_user_interface.cfg | 4 ++++ .../src/host_hypervisor/domcapabilities_output.py | 13 +++++++++++++ .../connectivity_check_user_interface.py | 6 ++++++ 4 files changed, 25 insertions(+) diff --git a/libvirt/tests/cfg/host_hypervisor/domcapabilities_output.cfg b/libvirt/tests/cfg/host_hypervisor/domcapabilities_output.cfg index b8f073ee88a..98c13f08122 100644 --- a/libvirt/tests/cfg/host_hypervisor/domcapabilities_output.cfg +++ b/libvirt/tests/cfg/host_hypervisor/domcapabilities_output.cfg @@ -3,3 +3,5 @@ start_vm = no variants test_case: - rm_ovmf_path: + - check_iface_backend: + func_supported_since_libvirt_ver = (10, 8, 0) diff --git a/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_user_interface.cfg b/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_user_interface.cfg index 5bc896d4477..c92c492c2f9 100644 --- a/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_user_interface.cfg +++ b/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_user_interface.cfg @@ -41,6 +41,10 @@ ipv4_addr = 100.100.100.15 ipv4_default_gw = 100.100.100.2 nameserver = 100.100.100.3 + - with_backend: + iface_attrs = {'model': 'virtio', 'type_name': 'user'} + backend = {'type': 'default'} + func_supported_since_libvirt_ver = (10, 8, 0) - negative_test: expect_error = yes variants: diff --git a/libvirt/tests/src/host_hypervisor/domcapabilities_output.py b/libvirt/tests/src/host_hypervisor/domcapabilities_output.py index 21f4d4dc44f..163c1ac8f2d 100644 --- a/libvirt/tests/src/host_hypervisor/domcapabilities_output.py +++ b/libvirt/tests/src/host_hypervisor/domcapabilities_output.py @@ -1,6 +1,7 @@ import os from virttest.libvirt_xml import domcapability_xml +from virttest import libvirt_version def get_ovmf_path(): @@ -59,6 +60,17 @@ def test_rm_ovmf_path(test): "is recovered", dir_ovmf_path) +def test_check_iface_backend(test): + domcapa_xml = domcapability_xml.DomCapabilityXML() + get_iface = domcapa_xml.xmltreefile.findall('/devices/interface/enum/value') + get_backend_list = set([i.text for i in get_iface]) + test.log.debug("interface backend supported includes: %s", get_backend_list) + support_list = {'passt', 'default'} + if get_backend_list != support_list: + test.fail("current support interface backend should be %s, " + "but it's %s", support_list, get_backend_list) + + def run(test, params, env): """ This file includes to test scenarios for checking outputs of @@ -69,5 +81,6 @@ def run(test, params, env): """ test_case = params.get("test_case", "") + libvirt_version.is_libvirt_feature_supported(params) run_test = eval("test_%s" % test_case) run_test(test) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py index 3a55e488586..a62d1e09d12 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py @@ -5,6 +5,7 @@ from virttest import remote from virttest import utils_net from virttest import virsh +from virttest import libvirt_version from virttest.libvirt_xml import vm_xml from virttest.utils_libvirt import libvirt_unprivileged from virttest.utils_libvirt import libvirt_vmxml @@ -76,6 +77,7 @@ def run(test, params, env): iface_attrs = eval(params.get('iface_attrs')) outside_ip = params.get('outside_ip') host_iface = params.get('host_iface') + backend = params.get('backend') host_iface = host_iface if host_iface else utils_net.get_default_gateway( iface_name=True, force_dhcp=True, json=True).split()[0] @@ -94,8 +96,12 @@ def run(test, params, env): mac = vm_xml.VMXML.get_first_mac_by_name(vm_name, virsh_ins) vmxml.del_device('interface', by_tag=True) vmxml.sync(virsh_instance=virsh_ins) + if backend: + libvirt_version.is_libvirt_feature_supported(params) + iface_attrs['backend'] = eval(backend) iface = libvirt_vmxml.create_vm_device_by_type( 'interface', {**iface_attrs, **({'mac_address': mac} if mac else {})}) + LOG.debug('iface xml to be tested is: %s', iface) vmxml.add_device(iface) define_result = virsh.define(vmxml.xml, debug=True, uri=virsh_uri) libvirt.check_exit_status(define_result, expect_error) From 9a1ac159672aa884839948f1ee5128e97d234248 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Jan 2025 17:05:54 +0000 Subject: [PATCH 0790/1055] build(deps): bump virtualenv from 1.9.1 to 20.26.6 Bumps [virtualenv](https://github.com/pypa/virtualenv) from 1.9.1 to 20.26.6. - [Release notes](https://github.com/pypa/virtualenv/releases) - [Changelog](https://github.com/pypa/virtualenv/blob/main/docs/changelog.rst) - [Commits](https://github.com/pypa/virtualenv/compare/1.9.1...20.26.6) --- updated-dependencies: - dependency-name: virtualenv dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements-travis.txt | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-travis.txt b/requirements-travis.txt index 1f83bf6df41..baa31f9a5af 100644 --- a/requirements-travis.txt +++ b/requirements-travis.txt @@ -4,7 +4,7 @@ nosexcover==1.0.8 tox==1.5.0; python_version < '3.8' tox==4.16.0; python_version > '3.7' virtualenv==1.9.1; python_version < '3.8' -virtualenv==20.26.3; python_version > '3.7' +virtualenv==20.26.6; python_version > '3.7' simplejson==3.8.1 inspektor==0.5.2; python_version < '3.8' inspektor==0.5.3; python_version > '3.7' diff --git a/requirements.txt b/requirements.txt index 166d4a0dcb9..2c8964b2416 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,4 @@ coverage==3.6 nose==1.3.0 nosexcover==1.0.8 tox==1.5.0 -virtualenv==1.9.1 +virtualenv==20.26.6 From 8fc7dfea3611fe9939638a1e11395449b1d6be92 Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 14 Jan 2025 09:14:32 +0800 Subject: [PATCH 0791/1055] migration: Update error message Signed-off-by: lcheng --- ...tion_network_data_transport_tls_wrong_cert_configuration.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls_wrong_cert_configuration.cfg b/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls_wrong_cert_configuration.cfg index 3d18778bb24..9972a4b71a0 100644 --- a/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls_wrong_cert_configuration.cfg +++ b/libvirt/tests/cfg/migration/migration_uri/migration_network_data_transport_tls_wrong_cert_configuration.cfg @@ -42,7 +42,7 @@ variants cert_configuration: - no_client_cert_on_src: cert_path = "${custom_pki_path}/client-cert.pem" - err_msg = "Cannot write to TLS channel: Input/output error|unable to execute QEMU command 'object-add': Unable to access credentials ${cert_path}|job 'migration out' failed: Cannot read from TLS channel: Software caused connection abort" + err_msg = "Cannot write to TLS channel: Input/output error|unable to execute QEMU command 'object-add': Unable to access credentials ${cert_path}|Cannot read from TLS channel" - no_server_cert_on_target: cert_path = "${custom_pki_path}/server-cert.pem" err_msg = "unable to execute QEMU command 'object-add': Unable to access credentials ${cert_path}" From 61386f3169277defd3120ab75d11257e4cd60139 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Tue, 14 Jan 2025 11:25:02 +0800 Subject: [PATCH 0792/1055] v2v: adjust testing guests according to matrix of 9.6/10.0 Signed-off-by: vwu-vera --- v2v/tests/cfg/convert_vm_to_libvirt.cfg | 45 +++---------------------- 1 file changed, 4 insertions(+), 41 deletions(-) diff --git a/v2v/tests/cfg/convert_vm_to_libvirt.cfg b/v2v/tests/cfg/convert_vm_to_libvirt.cfg index 640c527c768..7e651780dfe 100644 --- a/v2v/tests/cfg/convert_vm_to_libvirt.cfg +++ b/v2v/tests/cfg/convert_vm_to_libvirt.cfg @@ -28,7 +28,7 @@ - it_default: variants: - arch_i386: - only latest6, 5_11, win7, win8, win8_1, win10, debian + only latest6, win10 vm_arch = "i386" - arch_x86_64: vm_arch = "x86_64" @@ -38,7 +38,7 @@ - boot_uefi: vm_boot = "-efi" boottype = 3 - only 8_0.linux.latest10_dev, 8_0.linux.latest9_dev, 8_0.linux.latest9, 8_0.linux.latest8, 8_0.linux.8_8, 8_0.linux.8_6, 8_0.linux.ubuntu22_04, 8_0.linux.ubuntu_lts, 8_0.linux.sles15sp5, 8_0.linux.sles_lts, 8_0.linux.opensuse15_5, 8_0.linux.opensuse_latest, 8_0.windows.win2022, 8_0.windows.win11, 8_0.windows.win2016, 8_0.windows.win2025 + only 8_0.linux.latest10_dev, 8_0.linux.latest9_dev, 8_0.linux.latest9, 8_0.linux.latest8, 8_0.linux.ubuntu_lts, 8_0.linux.sles_lts, 8_0.linux.opensuse_latest, 8_0.windows.win2022, 8_0.windows.win11, 8_0.windows.win10, 8_0.windows.win2016, 8_0.windows.win2019, 8_0.windows.win2025 variants: - linux: os_type = "linux" @@ -57,31 +57,18 @@ - latest8: os_short_id = "RHEL8_SHORT_ID" os_version = "LATEST8" - - 8_8: - os_version = "rhel8.8" - - 8_6: - os_version = "rhel8.6" + - 9_4: + os_version = "rhel9.4" - latest7: os_short_id = "RHEL7_SHORT_ID" os_version = "LATEST7" - latest6: os_version = "LATEST6" enable_legacy_policy = yes - - 5_11: - os_version = "rhel5.11" - enable_legacy_policy = yes - - debian11_7: - only source_esx.esx_80 - #os_short_id = "debian11" - os_version = "debian11.7.0" - debian_lts: only source_esx.esx_80 #os_short_id = "DEBIAN_SHORT_ID" os_version = "DEBIAN_LTS_VERSION" - - ubuntu22_04: - only source_esx.esx_80 - os_short_id = "ubuntu22.04" - os_version = "ubuntu22.04" - ubuntu_lts: only source_esx.esx_80 os_short_id = "UBUNTU_LTS_SHORT_ID" @@ -90,10 +77,6 @@ only source_esx.esx_80 os_short_id = "sles12sp5" os_version = "sles12sp5" - - sles15sp5: - only source_esx.esx_80 - os_short_id = "sles15sp5" - os_version = "sles15sp5" - sles_lts: only source_esx.esx_80 os_version = "SLES_LATEST_VERSION" @@ -101,12 +84,6 @@ only source_esx.esx_80 os_short_id = "OPENSUSE_LATEST_SHORT_ID" os_version = "OPENSUSE_LATEST_VERSION" - - opensuse42_3: - only source_esx.esx_70,source_esx.esx_80 - os_version = "opensuse42.3" - - opensuse15_5: - only source_esx.esx_80 - os_version = "opensuse15.5" - windows: no pv os_type = "windows" @@ -128,20 +105,6 @@ vm_user = "Administrator" vm_pwd = DEFAULT_WIN_VM_PASSWORD variants: - - win2008r2: - os_version = "win2008r2" - - win8: - only esx - os_version = "win8" - - win8_1: - only esx - os_version = "win8.1" - - win2012: - only esx - os_version = "win2012" - - win2012r2: - only esx - os_version = "win2012r2" - win10: only esx os_version = "win10" From 569a1a7e4e8c78825cc0bd502a4aace950f8e167 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Wed, 28 Aug 2024 23:00:11 -0400 Subject: [PATCH 0793/1055] Automate case: Connect to the guest console without serial device xx-300602 - [console][negative] Connect to the guest console without serial device Signed-off-by: chunfuwen --- .../tests/cfg/serial/serial_functional.cfg | 5 +++++ libvirt/tests/src/serial/serial_functional.py | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/libvirt/tests/cfg/serial/serial_functional.cfg b/libvirt/tests/cfg/serial/serial_functional.cfg index 678bc94ffbc..49b04637c6f 100644 --- a/libvirt/tests/cfg/serial/serial_functional.cfg +++ b/libvirt/tests/cfg/serial/serial_functional.cfg @@ -70,6 +70,11 @@ serial_dev_type = pty console_target_type = virtio second_serial_console = yes + - connect_to_console_no_serial_device: + serial_dev_type = pty + error_msg = "cannot find character device" + connect_to_console_without_serial_device = "yes" + func_supported_since_libvirt_ver = (10, 3, 0) - type_tls_server: serial_dev_type = tls serial_sources = mode:bind,host:${local_ip_address},service:5556,tls:yes diff --git a/libvirt/tests/src/serial/serial_functional.py b/libvirt/tests/src/serial/serial_functional.py index d143a64d9b2..f83c8ceae97 100644 --- a/libvirt/tests/src/serial/serial_functional.py +++ b/libvirt/tests/src/serial/serial_functional.py @@ -23,6 +23,7 @@ from virttest import libvirt_version from avocado.utils import astring +from avocado.utils import process # Using as lower capital is not the best way to do, but this is just a @@ -746,6 +747,7 @@ def get_console_type(): target_model = params.get('target_model', '') console_target_port = params.get('console_target_port', '0') second_serial_console = params.get('second_serial_console', 'no') == 'yes' + connect_to_console_without_serial_device = params.get('connect_to_console_without_serial_device', 'no') == 'yes' custom_pki_path = params.get('custom_pki_path', '/etc/pki/libvirt-chardev') auto_recover = params.get('auto_recover', 'no') client_pwd = params.get('client_pwd', None) @@ -821,6 +823,12 @@ def get_console_type(): if console_type == 'server': console = prepare_serial_console() + if connect_to_console_without_serial_device: + libvirt_version.is_libvirt_feature_supported(params) + for device_type in remove_devices: + vm_xml.remove_all_device_by_type(device_type) + vm_xml.sync() + res = virsh.start(vm_name) libvirt.check_result(res, expected_fails, []) if res.exit_status: @@ -835,8 +843,19 @@ def get_console_type(): console_type != 'server'): check_serial_console(console, username, password) + if connect_to_console_without_serial_device: + time.sleep(20) + # use raw virsh console command since we need to output message from virsh console VM + result = process.run("virsh console %s" % vm_name, shell=True, verbose=True, ignore_status=True).stderr_text + error_msg = params.get("error_msg") + if error_msg not in result: + test.fail(f"Fail to get expected error message:{error_msg} from console") + vm.destroy() finally: + # Recover VM. + if vm.is_alive(): + vm.destroy(gracefully=False) cleanup(objs_list) vm_xml_backup.sync() From 2e088325813b3091e7fafc0f27f42645256e59eb Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Wed, 15 Jan 2025 09:30:12 +0800 Subject: [PATCH 0794/1055] v2v: fix the failed tc: specific_kvm..sync_ntp Signed-off-by: vwu-vera --- v2v/tests/src/specific_kvm.py | 1 + 1 file changed, 1 insertion(+) diff --git a/v2v/tests/src/specific_kvm.py b/v2v/tests/src/specific_kvm.py index 4e367b7ad2f..aed2f1bd8a4 100644 --- a/v2v/tests/src/specific_kvm.py +++ b/v2v/tests/src/specific_kvm.py @@ -842,6 +842,7 @@ def check_result(result, status_error): LOG.info('Sync time with %s', ntp_server) cmd = ['yum -y install chrony', 'systemctl start chronyd', + 'systemctl enable chronyd', 'chronyc add server %s' % ntp_server, 'chronyc waitsync'] vm_cmd(cmd) From 8a19dd2935a7cf26556852cb9351313016be4122 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Tue, 14 Jan 2025 20:30:54 -0500 Subject: [PATCH 0795/1055] Inc_backup: add datastore element test scenarios to incremental backup This update is coming from disk datastore new feature(RHEL-69449). Signed-off-by: Meina Li --- .../incremental_backup_pull_mode.cfg | 8 ++++++++ .../incremental_backup_push_mode.cfg | 7 +++++++ .../incremental_backup_pull_mode.py | 16 +++++++++++++++- .../incremental_backup_push_mode.py | 18 +++++++++++++++--- 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/cfg/incremental_backup/incremental_backup_pull_mode.cfg b/libvirt/tests/cfg/incremental_backup/incremental_backup_pull_mode.cfg index 314f04ecb09..40c2f168b78 100644 --- a/libvirt/tests/cfg/incremental_backup/incremental_backup_pull_mode.cfg +++ b/libvirt/tests/cfg/incremental_backup/incremental_backup_pull_mode.cfg @@ -7,6 +7,14 @@ local_ip = "ENTER.YOUR.IPV4ADDR" local_user_name = "ENTER.YOUR.USER.NAME" local_user_password = "ENTER.YOUR.USER.PASSWORD" + only original_disk_local + variants: + - without_datastore: + - with_datastore: + only default_exportbitmap.default_exportname + with_data_file = "yes" + func_supported_since_libvirt_ver = (10, 10, 0) + data_file_option = " -o data_file=%s" variants: - scratch_luks_encrypted: only custom_exportname..custom_exportbitmap..hotplug_disk..original_disk_local diff --git a/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg b/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg index df50fe64402..93c29585d5a 100644 --- a/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg +++ b/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg @@ -3,6 +3,13 @@ start_vm = "no" original_disk_size = "100M" backup_data_size = "1M" + variants: + - without_datastore: + - with_datastore: + only original_disk_local + with_data_file = "yes" + func_supported_since_libvirt_ver = (10, 10, 0) + data_file_option = " -o data_file=%s" variants: - backup_to_file: target_type = "file" diff --git a/libvirt/tests/src/incremental_backup/incremental_backup_pull_mode.py b/libvirt/tests/src/incremental_backup/incremental_backup_pull_mode.py index 888e3dab3e8..a60d75d4090 100644 --- a/libvirt/tests/src/incremental_backup/incremental_backup_pull_mode.py +++ b/libvirt/tests/src/incremental_backup/incremental_backup_pull_mode.py @@ -50,6 +50,8 @@ def run(test, params, env): local_user_name = params.get("local_user_name", "root") local_user_password = params.get("local_user_password", "redhat") tmp_dir = data_dir.get_tmp_dir() + with_data_file = "yes" == params.get("with_data_file", "no") + libvirt_version.is_libvirt_feature_supported(params) # Backup config scratch_type = params.get("scratch_type", "file") reuse_scratch_file = "yes" == params.get("reuse_scratch_file") @@ -150,8 +152,15 @@ def run(test, params, env): if original_disk_type == "local": image_name = "{}_image.qcow2".format(original_disk_target) disk_path = os.path.join(tmp_dir, image_name) + data_file = os.path.join(tmp_dir, "datastore") + for file in [disk_path, data_file]: + if os.path.exists(file): + os.remove(file) + if with_data_file: + data_file_option = params.get("data_file_option", "") % data_file + extra_cmd = "" if not with_data_file else data_file_option libvirt.create_local_disk("file", disk_path, original_disk_size, - "qcow2") + "qcow2", extra=extra_cmd) disk_params = {"device_type": "disk", "type_name": "file", "driver_type": "qcow2", @@ -213,6 +222,11 @@ def run(test, params, env): virsh.attach_device(vm.name, disk_xml, flagstr="--config", debug=True) vm.start() + guest_xml = virsh.dumpxml(vm_name).stdout_text + logging.debug("The current guest xml is:%s" % guest_xml) + if with_data_file: + if data_file not in guest_xml: + test.fail("The datastore file xml can't be generated automatically in guest!") session = vm.wait_for_login() new_disks_in_vm = list(utils_disk.get_linux_disks(session).keys()) session.close() diff --git a/libvirt/tests/src/incremental_backup/incremental_backup_push_mode.py b/libvirt/tests/src/incremental_backup/incremental_backup_push_mode.py index c92d5e3f0cd..9e0c181dcfb 100644 --- a/libvirt/tests/src/incremental_backup/incremental_backup_push_mode.py +++ b/libvirt/tests/src/incremental_backup/incremental_backup_push_mode.py @@ -67,6 +67,8 @@ def backup_job_done(vm_name, vm_disk): backup_error = "yes" == params.get("backup_error") expect_backup_canceled = "yes" == params.get("expect_backup_canceled") tmp_dir = data_dir.get_data_dir() + with_data_file = "yes" == params.get("with_data_file", "no") + libvirt_version.is_libvirt_feature_supported(params) virsh_dargs = {'debug': True, 'ignore_status': True} try: @@ -87,10 +89,15 @@ def backup_job_done(vm_name, vm_disk): if original_disk_type == "local": image_name = "{}_image.qcow2".format(original_disk_target) disk_path = os.path.join(tmp_dir, image_name) - if os.path.exists(disk_path): - os.remove(disk_path) + data_file = os.path.join(tmp_dir, "datastore") + for file in [disk_path, data_file]: + if os.path.exists(file): + os.remove(file) + if with_data_file: + data_file_option = params.get("data_file_option", "") % data_file + extra_cmd = "" if not with_data_file else data_file_option libvirt.create_local_disk("file", disk_path, original_disk_size, - "qcow2") + "qcow2", extra=extra_cmd) disk_params = {"device_type": "disk", "type_name": "file", "driver_type": "qcow2", @@ -167,6 +174,11 @@ def backup_job_done(vm_name, vm_disk): virsh.attach_device(vm.name, disk_xml, flagstr="--config", debug=True) vm.start() + guest_xml = virsh.dumpxml(vm_name).stdout_text + logging.debug("The current guest xml is:%s" % guest_xml) + if with_data_file: + if data_file not in guest_xml: + test.fail("The datastore file xml can't be generated automatically in guest!") session = vm.wait_for_login() new_disks_in_vm = list(utils_disk.get_linux_disks(session).keys()) session.close() From 2739c3eb5fe0a10e0e2f600e2b826eab7e399718 Mon Sep 17 00:00:00 2001 From: Lili Zhu Date: Sun, 29 Dec 2024 07:40:34 -0500 Subject: [PATCH 0796/1055] Add the cases of virtiofs openfiles Signed-off-by: Lili Zhu --- .../cfg/virtual_device/filesystem_device.cfg | 1 + .../src/virtual_device/filesystem_device.py | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg index 76a1352cc9b..0114840e717 100644 --- a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg +++ b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg @@ -40,6 +40,7 @@ variants: - thread_pool_16: thread_pool_size = 16 + openfiles = "yes" only positive_test..nop..xattr_on.cache_mode_auto, positive_test..detach_device..xattr_on.cache_mode_auto - thread_pool_noset: variants: diff --git a/libvirt/tests/src/virtual_device/filesystem_device.py b/libvirt/tests/src/virtual_device/filesystem_device.py index cf4d9361b20..9067d85c3a0 100644 --- a/libvirt/tests/src/virtual_device/filesystem_device.py +++ b/libvirt/tests/src/virtual_device/filesystem_device.py @@ -57,6 +57,8 @@ def generate_expected_process_option(): # virtiofsd man pages. Add another kind of pattern here to avoid # possible change in the future again. expected_results += " --thread-pool-size(\s|=)%s" % thread_pool_size + if openfiles: + expected_results += " --rlimit-nofile(\s|=)%s" % open_files_max logging.debug(expected_results) return expected_results @@ -226,6 +228,7 @@ def check_filesystem_hotplug_with_mem_setup(): xattr = params.get("xattr", "on") path = params.get("virtiofsd_path", "/usr/libexec/virtiofsd") thread_pool_size = params.get("thread_pool_size") + openfiles = params.get("openfiles", "no") == "yes" queue_size = int(params.get("queue_size", "512")) driver_type = params.get("driver_type", "virtiofs") guest_num = int(params.get("guest_num", "1")) @@ -279,6 +282,13 @@ def check_filesystem_hotplug_with_mem_setup(): libvirt_version.is_libvirt_feature_supported(params) check_filesystem_hotplug_with_mem_setup() return + + if openfiles: + with open('/proc/sys/fs/nr_open', 'r') as file: + open_files_max = file.read().strip() + else: + open_files_max = None + # Define filesystem device xml for index in range(fs_num): driver = {'type': driver_type, 'queue': queue_size} @@ -289,8 +299,10 @@ def check_filesystem_hotplug_with_mem_setup(): source = {'socket': source_socket} target = {'dir': target_dir} if launched_mode == "auto": - binary_keys = ['path', 'cache_mode', 'xattr', 'thread_pool_size'] - binary_values = [path, cache_mode, xattr, thread_pool_size] + binary_keys = ['path', 'cache_mode', 'xattr', + 'thread_pool_size', "open_files_max"] + binary_values = [path, cache_mode, xattr, + thread_pool_size, open_files_max] binary_dict = dict(zip(binary_keys, binary_values)) source = {'dir': source_dir} accessmode = "passthrough" From 019cbdabe78b32533a044bee9f04ac25565a5195 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Wed, 15 Jan 2025 15:14:40 +0800 Subject: [PATCH 0797/1055] v2v: fix the failed TCs:specific_kvm.positive_test.linux..chars_telnet/vmx_char to rhev Signed-off-by: vwu-vera --- v2v/tests/cfg/specific_kvm.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v2v/tests/cfg/specific_kvm.cfg b/v2v/tests/cfg/specific_kvm.cfg index 44a1de140b0..dad6b4c9293 100644 --- a/v2v/tests/cfg/specific_kvm.cfg +++ b/v2v/tests/cfg/specific_kvm.cfg @@ -300,6 +300,7 @@ only esx_80 variants: - chars_telnet: + only libvirt boottype = 2 main_vm = VM_NAME_SERVIAL_PORT_CHARACTERS_TELNET_URL_V2V_EXAMPLE - empty_info: @@ -307,6 +308,7 @@ main_vm = VM_NAME_SERVIAL_PORT_EMPTY_V2V_EXAMPLE - vmx_char: only esx_80 + only libvirt boottype = 2 main_vm = VM_NAME_VMX_CONTAINS_CHAR_V2V_EXAMPLE variants: From 3ce3f6049dfb15f47aa1543f1fe497749c70eb0a Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 15 Jan 2025 12:07:57 -0500 Subject: [PATCH 0798/1055] boot_integration: fix test for unexpected control codes aexpect will raise an error if the console contains certain control codes, s. https://github.com/avocado-framework/aexpect/issues/133 This happens in `get_stripped_output`. By using `get_output`, this can't happen and the test passes. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/bios/boot_integration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/bios/boot_integration.py b/libvirt/tests/src/bios/boot_integration.py index 8f8864fc1d0..708341e0a84 100755 --- a/libvirt/tests/src/bios/boot_integration.py +++ b/libvirt/tests/src/bios/boot_integration.py @@ -78,7 +78,7 @@ def console_check(vm, pattern, debug_log=False): :return: function returning true if console output matches pattern """ def _matches(): - output = vm.serial_console.get_stripped_output() + output = vm.serial_console.get_output() matches = re.search(pattern, output, re.S) if debug_log: logging.debug("Checked for '%s' in '%s'", pattern, output) From 36fe18fb5541dca62b503438bfe97f0465976bdd Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Thu, 16 Jan 2025 02:13:20 -0500 Subject: [PATCH 0799/1055] Fix the issue that VM can not be cleared The VM cloned from the test can not be undefined without nvram options. Fix the issue to make the env clean. Signed-off-by: Yalan Zhang --- libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py index 37d9e41c9e9..feb564fafbe 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave.py @@ -538,5 +538,5 @@ def build_vm_xml(vm_name, **dargs): if multi_guests: for i in range(int(multi_guests)): virsh.remove_domain("%s_%s" % (vm_name, i), - "--remove-all-storage", + "--remove-all-storage --nvram", debug=True) From 5cfa5dce8cbb0a059453417cf17e7b8b87d2b135 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Thu, 16 Jan 2025 02:34:17 -0500 Subject: [PATCH 0800/1055] Add boottype for windows uefi guests Signed-off-by: Ming Xie --- v2v/tests/cfg/function_test_esx.cfg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 27c03ee5b4c..2da63f83267 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -889,6 +889,7 @@ msg_content_yes = "server reported: VDDK "Unknown error" can be caused by several problems" - non_admin_user: only esx_80 + boottype = 3 main_vm = VM_NAME_NON_ADMIN_V2V_EXAMPLE vpx_username = VMWARE_NON_ADMIN_USER_EXAMPLE - rocky_linux: @@ -921,6 +922,7 @@ checkpoint = 'invalid_os_storage' - verify_certificate: only esx_80 + boottype = 3 main_vm = VM_NAME_NON_ADMIN_V2V_EXAMPLE checkpoint = 'verify_certificate' certs_src_dir = 'CERTS_DIR_V2V_EXAMPLE' @@ -936,6 +938,7 @@ skip_reason = 'luks encryped, cannot boots up without password' - default_vsphere: only esx_80 + boottype = 3 main_vm = VM_NAME_NON_ADMIN_V2V_EXAMPLE interaction_run = 'yes' vpx_no_username = True From 8dab59db3aa2646ed4b98de9dbc1ab00f6a6db71 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Fri, 17 Jan 2025 11:21:51 +0800 Subject: [PATCH 0801/1055] v2v:fix the failed cases: specific_kvm..no_space.esx/non_exist_network Signed-off-by: vwu-vera --- v2v/tests/cfg/specific_kvm.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v2v/tests/cfg/specific_kvm.cfg b/v2v/tests/cfg/specific_kvm.cfg index dad6b4c9293..e09d4bce6a2 100644 --- a/v2v/tests/cfg/specific_kvm.cfg +++ b/v2v/tests/cfg/specific_kvm.cfg @@ -249,6 +249,7 @@ checkpoint = 'sync_ntp' - no_space: only esx.esx_70 + only rhev checkpoint = 'host_no_space_setcache' main_vm = 'VM_ESX_DEFAULT_NAME_V2V_EXAMPLE' - mem_alloc: @@ -286,6 +287,7 @@ main_vm = 'VM_NAME_80_CHARS_V2V_EXAMPLE' - non_exist_network: only source_esx.esx_80 + only rhev boottype = 2 main_vm = 'VM_NON_EXIST_NETWORK_V2V_EXAMPLE' skip_vm_check = yes From b1b5eb86028f715979c99b9e70fba890ffb589d7 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Fri, 17 Jan 2025 03:21:40 -0500 Subject: [PATCH 0802/1055] Add new case of qos: test bandwidth boundry - VIRT-303876 - [Qos][domiftune] Test bandwidth boundary of an interface via domiftune Signed-off-by: Haijiao Zhao --- .../qos/test_bandwidth_boundry.cfg | 21 +++++++ .../qos/test_bandwidth_boundry.py | 60 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/qos/test_bandwidth_boundry.cfg create mode 100644 libvirt/tests/src/virtual_network/qos/test_bandwidth_boundry.py diff --git a/libvirt/tests/cfg/virtual_network/qos/test_bandwidth_boundry.cfg b/libvirt/tests/cfg/virtual_network/qos/test_bandwidth_boundry.cfg new file mode 100644 index 00000000000..12ff9905211 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/qos/test_bandwidth_boundry.cfg @@ -0,0 +1,21 @@ +- virtual_network.qos.test_bandwidth_boundry: + type = test_bandwidth_boundry + start_vm = yes + variants bw_type: + - inbound: + - outbound: + variants scenario: + - boundry: + bw_args = 4294967295,4294967295,4194303 + - over_boundry_average: + bw_args = 1000000000000000000,4096,4096 + status_error = yes + err_msg = ${bw_type} rate larger than maximum 4294967295 + - over_boundry_peak: + bw_args = 4096,1000000000000000000,4096 + status_error = yes + err_msg = ${bw_type} rate larger than maximum 4294967295 + - over_boundry_burst: + bw_args = 1024000,4096,4194304 + status_error = yes + err_msg = numerical overflow: value '4194304' is too big for 'burst' parameter, maximum is '4194303' diff --git a/libvirt/tests/src/virtual_network/qos/test_bandwidth_boundry.py b/libvirt/tests/src/virtual_network/qos/test_bandwidth_boundry.py new file mode 100644 index 00000000000..ac0fc815d1b --- /dev/null +++ b/libvirt/tests/src/virtual_network/qos/test_bandwidth_boundry.py @@ -0,0 +1,60 @@ +import logging + +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_misc +from virttest.utils_test import libvirt + +from provider.virtual_network import network_base + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test bandwidth boundary of an interface via domiftune + + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + bw_type = params.get('bw_type', '') + bw_args = params.get('bw_args', '') + status_error = 'yes' == params.get("status_error", 'no') + err_msg = params.get('err_msg') + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + iface = network_base.get_iface_xml_inst(vm_name, 'on vm') + mac = iface.mac_address + domiftune_args = {bw_type: bw_args} + virsh_result = virsh.domiftune( + vm_name, mac, **domiftune_args, debug=True) + libvirt.check_exit_status(virsh_result, status_error) + if status_error: + libvirt.check_result(virsh_result, err_msg) + return + + out = virsh.domiftune(vm_name, mac, **VIRSH_ARGS).stdout_text + + bw_out = libvirt_misc.convert_to_dict( + out, '(\S+)\s*:\s*(\d+)') + bw_values = bw_out[f'{bw_type}.average'], \ + bw_out[f'{bw_type}.peak'], bw_out[f'{bw_type}.burst'] + if ','.join(bw_values) != bw_args: + test.fail(f'Bandwidth from domiftune is {",".join(bw_values)}, ' + f'but it should be {bw_args}') + + iface = network_base.get_iface_xml_inst(vm_name, 'after domiftune') + iface_attrs = iface.fetch_attrs() + bw_attrs = iface_attrs['bandwidth'][bw_type] + bw_xml_values = ','.join([bw_attrs['average'], bw_attrs['peak'], + bw_attrs['burst']]) + if bw_xml_values != bw_args: + test.fail(f'Bandwidth from interface xml is {bw_xml_values}, ' + f'but it should be {bw_args}') + finally: + bkxml.sync() From 0f389e360ddd74fe0c2195dbe2ebb75380a727da Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Fri, 17 Jan 2025 04:19:05 -0500 Subject: [PATCH 0803/1055] iface_bridge:Fix colored output if ip command Signed-off-by: Haijiao Zhao --- libvirt/tests/src/virtual_network/iface_bridge.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_network/iface_bridge.py b/libvirt/tests/src/virtual_network/iface_bridge.py index 75281259339..f30f864f73f 100644 --- a/libvirt/tests/src/virtual_network/iface_bridge.py +++ b/libvirt/tests/src/virtual_network/iface_bridge.py @@ -291,7 +291,7 @@ def check_net_functions(guest_ip, ping_count, ping_timeout, guest_session, host_ driver_dict = eval(iface_driver) if session1 is None: session1 = vm1.wait_for_serial_login() - guest_iface_info = session1.cmd_output("ip l").strip() + guest_iface_info = session1.cmd_output("ip --color=never l").strip() guest_iface_name = re.findall(r"^\d+: (\S+?)[@:].*state UP.*$", guest_iface_info, re.MULTILINE)[0] comb_size = driver_dict.get('queues') rx_size = driver_dict.get('rx_queue_size') From 40dbb19412e09aaa5d076ad7facfd38f5a0d319b Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Sun, 19 Jan 2025 21:49:54 -0500 Subject: [PATCH 0804/1055] Exclude unsupported 16M hugepage test for aarch64 and x86_64 Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/numa/guest_numa.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/cfg/numa/guest_numa.cfg b/libvirt/tests/cfg/numa/guest_numa.cfg index 552ec2fcd29..38990953f66 100644 --- a/libvirt/tests/cfg/numa/guest_numa.cfg +++ b/libvirt/tests/cfg/numa/guest_numa.cfg @@ -85,6 +85,7 @@ pseries: page_nodenum_0 = "0" - 16M: + no aarch64, x86_64 max_mem = "2097152" vmpage_size_0 = "16384" hugepage_size_0 = "16384" From cca78d281bbe06462aace28cbe59b120007a5aa3 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 20 Jan 2025 11:21:38 -0500 Subject: [PATCH 0805/1055] virsh_restore: enable tests for VMs with boot order The `xml_option` variant expects the VM to boot from //os/boot with dev="hd" and will skip otherwise. Instead, allow for the test to configure the desired xml update for //os. For s390x, //os/boot is not fully available, so set bootmenu for our xml instead. Signed-off-by: Sebastian Mitterle --- .../tests/cfg/virsh_cmd/domain/virsh_restore.cfg | 3 +++ .../tests/src/virsh_cmd/domain/virsh_restore.py | 16 +++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_restore.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_restore.cfg index 477de656549..9622c2c8be8 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_restore.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_restore.cfg @@ -22,6 +22,9 @@ restore_extra_param = "--running" - xml_option: restore_extra_param = "--xml" + os_update_dict = '{"boots": ["cdrom"]}' + s390-virtio: + os_update_dict = '{"bootmenu_enable": "yes"}' - xml_option_dac: only non_acl restore_extra_param = "--xml" diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_restore.py b/libvirt/tests/src/virsh_cmd/domain/virsh_restore.py index c41a4c1ab8a..55dcc39728b 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_restore.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_restore.py @@ -65,6 +65,7 @@ def check_file_own(file_path, exp_uid, exp_gid): check_log = params.get("check_log") check_str_not_in_log = params.get("check_str_not_in_log") qemu_conf_dict = eval(params.get("qemu_conf_dict", "{}")) + os_update_dict = eval(params.get("os_update_dict")) vm_ref_uid = None vm_ref_gid = None @@ -88,12 +89,7 @@ def check_file_own(file_path, exp_uid, exp_gid): os.chmod(vmxml.xml, stat.S_IRWXU | stat.S_IRGRP | stat.S_IROTH) if not setup_nfs: extra_param = "--xml %s" % vmxml.xml - dict_os_attrs = {} - if "hd" in vmxml.os.boots: - dict_os_attrs.update({"boots": ["cdrom"]}) - vmxml.set_os_attrs(**dict_os_attrs) - else: - test.cancel("Please add 'hd' in boots for --xml testing") + vmxml.set_os_attrs(**os_update_dict) logging.info("vmxml os is %s after update" % vmxml.os.xmltreefile) else: @@ -196,9 +192,11 @@ def check_file_own(file_path, exp_uid, exp_gid): if extra_param.count("xml"): if not setup_nfs: aft_vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) - boots_list = aft_vmxml.os.boots - if "hd" in boots_list or "cdrom" not in boots_list: - test.fail("Update xml with restore failed") + for attr in os_update_dict: + got = getattr(aft_vmxml.os, attr, "") + expected = os_update_dict[attr] + if got != expected: + test.fail("Update xml with restore failed") else: if vm_ref_uid and vm_ref_gid: check_file_own(vm_ref, vm_ref_uid, vm_ref_gid) From 996e15012f2fd95f7e02c2a361c5bfb9017e530c Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 21 Jan 2025 03:32:36 -0500 Subject: [PATCH 0806/1055] virtio_transitional_mem_balloon: fix test on s390x On s390x, memballoon is a ccw device per libvirt default, not pci. Make the command to detect the device configurable and set s390x-specific value. Signed-off-by: Sebastian Mitterle --- .../virtio_transitional/virtio_transitional_mem_balloon.cfg | 3 +++ .../src/virtio_transitional/virtio_transitional_mem_balloon.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_mem_balloon.cfg b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_mem_balloon.cfg index 54a45813e42..1d4fd8f2ad9 100644 --- a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_mem_balloon.cfg +++ b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_mem_balloon.cfg @@ -2,6 +2,9 @@ type = virtio_transitional_mem_balloon start_vm = no vm_memory = 8388608 + detect_cmd = 'lspci |grep balloon' + s390-virtio: + detect_cmd = 'lscss |grep "3832/05"' variants: - virtio: virtio_model = "virtio" diff --git a/libvirt/tests/src/virtio_transitional/virtio_transitional_mem_balloon.py b/libvirt/tests/src/virtio_transitional/virtio_transitional_mem_balloon.py index 3e275dc37eb..1a4c28b836f 100644 --- a/libvirt/tests/src/virtio_transitional/virtio_transitional_mem_balloon.py +++ b/libvirt/tests/src/virtio_transitional/virtio_transitional_mem_balloon.py @@ -95,7 +95,7 @@ def run(test, params, env): if is_windows_guest: return # Check if memory balloon device exists on guest - status = session.cmd_status_output('lspci |grep balloon')[0] + status = session.cmd_status_output(params.get("detect_cmd"))[0] if status != 0: test.fail("Didn't detect memory balloon device on guest.") # Save and restore guest From 4b7205f20ba6226f625441ab132a66cd3801327a Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 21 Jan 2025 09:43:31 -0500 Subject: [PATCH 0807/1055] vol_download_upload: fix disk selection The disk was originally selected by its target name but those names are impersistent and might change in the guest. The test would then sometimes fail as it would read (without I/O errors) from the system disk instead of the new disk when the system was at vdb. Instead, discover the new disk as the one that doesn't have the root filesystem. Signed-off-by: Sebastian Mitterle --- .../src/virsh_cmd/volume/virsh_vol_download_upload.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/volume/virsh_vol_download_upload.py b/libvirt/tests/src/virsh_cmd/volume/virsh_vol_download_upload.py index 344c769721d..4c46cd58a22 100644 --- a/libvirt/tests/src/virsh_cmd/volume/virsh_vol_download_upload.py +++ b/libvirt/tests/src/virsh_cmd/volume/virsh_vol_download_upload.py @@ -18,6 +18,7 @@ from virttest.libvirt_xml import vm_xml from virttest.libvirt_xml.devices.disk import Disk +from virttest.utils_libvirt import libvirt_disk from virttest.utils_test import libvirt from virttest.utils_test import libvirt as utlv @@ -117,22 +118,22 @@ def create_disk(disk_type, disk_path, disk_format, disk_device_type, return custom_disk -def write_disk(test, guest_vm, target_name, size=200): +def write_disk(test, guest_vm, size=200): """ Write data into disk in VM discard value. :param test: test itself. :param guest_vm: Guest VM. - :param target_name: Device target name. :param size: Data size in 1M unit. """ logging.info("Write data into disk in VM...") try: session = guest_vm.wait_for_login() + disk_name, _ = libvirt_disk.get_non_root_disk_name(session) cmd = ("fdisk -l /dev/{0} && mkfs.ext4 -F /dev/{0} && " "mkdir -p test && mount /dev/{0} test && " "dd if=/dev/urandom of=test/file bs=1M count={1} && sync" - .format(target_name, size)) + .format(disk_name, size)) status, output = session.cmd_status_output(cmd) if status != 0: session.close() @@ -376,7 +377,7 @@ def get_pre_post_digest(): # Write 100M data into disk. data_size = 100 - write_disk(test, vm, target, data_size) + write_disk(test, vm, data_size) data_size_in_bytes = data_size * 1024 * 1024 # Refresh directory pool. From 710a2e771d57a965799fbbcc3033342a6f3b4d6e Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 21 Jan 2025 12:12:31 -0500 Subject: [PATCH 0808/1055] transitional_rng: don't attach incompatible controller On s390x, pci bridge is not available. Don't attach this. Also, apply black for uniform formatting and avoid issues in CI. Signed-off-by: Sebastian Mitterle --- .../virtio_transitional_rng.cfg | 3 + .../virtio_transitional_rng.py | 123 +++++++++--------- 2 files changed, 68 insertions(+), 58 deletions(-) diff --git a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_rng.cfg b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_rng.cfg index 9d21214f0ca..489eca77984 100644 --- a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_rng.cfg +++ b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_rng.cfg @@ -2,6 +2,9 @@ type = virtio_transitional_rng start_vm = no check_cmd = 'hexdump /dev/hwrng|head -2' + s390-virtio: + bridge_controller_needed = no + variants: - virtio: virtio_model = "virtio" diff --git a/libvirt/tests/src/virtio_transitional/virtio_transitional_rng.py b/libvirt/tests/src/virtio_transitional/virtio_transitional_rng.py index 8b69b832020..8283862449e 100644 --- a/libvirt/tests/src/virtio_transitional/virtio_transitional_rng.py +++ b/libvirt/tests/src/virtio_transitional/virtio_transitional_rng.py @@ -17,7 +17,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 run(test, params, env): @@ -37,10 +37,9 @@ def get_free_pci_slot(): """ used_slot = [] for dev in pci_devices: - address = dev.find('address') - if (address is not None and - address.get('bus') == pci_bridge_index): - used_slot.append(address.get('slot')) + address = dev.find("address") + if address is not None and address.get("bus") == pci_bridge_index: + used_slot.append(address.get("slot")) for slot_index in range(1, 30): slot = "%0#4x" % slot_index if slot not in used_slot: @@ -58,16 +57,16 @@ def get_free_root_port(): used_slot = set() # Record the bus indexes for all pci controllers for controller in pci_controllers: - if controller.get('model') == 'pcie-root-port': - root_ports.add(controller.get('index')) + if controller.get("model") == "pcie-root-port": + root_ports.add(controller.get("index")) else: - other_ports.add(controller.get('index')) + other_ports.add(controller.get("index")) # Record the addresses being allocated for all pci devices - pci_devices = list(vmxml.xmltreefile.find('devices')) + pci_devices = list(vmxml.xmltreefile.find("devices")) for dev in pci_devices: - address = dev.find('address') + address = dev.find("address") if address is not None: - used_slot.add(address.get('bus')) + used_slot.add(address.get("bus")) # Find the bus address unused for bus_index in root_ports: bus = "%0#4x" % int(bus_index) @@ -76,15 +75,17 @@ def get_free_root_port(): # Add a new pcie-root-port if no free one for index in range(1, 30): if index not in (root_ports | other_ports): - contr_dict = {'controller_type': 'pci', - 'controller_index': index, - 'controller_model': 'pcie-root-port'} + contr_dict = { + "controller_type": "pci", + "controller_index": index, + "controller_model": "pcie-root-port", + } cntl_add = libvirt.create_controller_xml(contr_dict) libvirt.add_controller(vm_name, cntl_add) return "%0#4x" % int(index) return None - def check_plug_to(bus_type='pcie-to-pci-bridge'): + def check_plug_to(bus_type="pcie-to-pci-bridge"): """ Check if the nic is plugged onto pcie-to-pci-bridge @@ -92,12 +93,12 @@ def check_plug_to(bus_type='pcie-to-pci-bridge'): :return True if plugged onto 'bus_type', otherwise False """ vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) - rng = vmxml.xmltreefile.find('devices').find('rng') - bus = int(eval(rng.find('address').get('bus'))) - controllers = vmxml.get_controllers('pci') + rng = vmxml.xmltreefile.find("devices").find("rng") + bus = int(eval(rng.find("address").get("bus"))) + controllers = vmxml.get_controllers("pci") for controller in controllers: - if controller.get('index') == bus: - if controller.get('model') == bus_type: + if controller.get("index") == bus: + if controller.get("model") == bus_type: return True break return False @@ -106,31 +107,33 @@ def check_rng_inside_guest(): """ check rng device inside guest """ - check_cmd = params['check_cmd'] + check_cmd = params["check_cmd"] lspci_output = session.cmd_output(check_cmd) - session.cmd_output('pkill -9 hexdump') - if 'No such file or directory' in lspci_output and device_exists: - test.fail('Can not detect device by %s.' % check_cmd) + session.cmd_output("pkill -9 hexdump") + if "No such file or directory" in lspci_output and device_exists: + test.fail("Can not detect device by %s." % check_cmd) vm_name = params.get("main_vm", "avocado-vt-vm1") vm = env.get_vm(params["main_vm"]) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() guest_src_url = params.get("guest_src_url") - virtio_model = params['virtio_model'] - boot_with_rng = (params.get('boot_with_rng', 'yes') == 'yes') - hotplug = (params.get('hotplug', 'no') == 'yes') - device_exists = (params.get('device_exists', 'yes') == 'yes') - plug_to = params.get('plug_to', '') + virtio_model = params["virtio_model"] + boot_with_rng = params.get("boot_with_rng", "yes") == "yes" + hotplug = params.get("hotplug", "no") == "yes" + device_exists = params.get("device_exists", "yes") == "yes" + plug_to = params.get("plug_to", "") set_crypto_policy = params.get("set_crypto_policy") + bridge_controller_needed = "yes" == params.get("bridge_controller_needed", "yes") if not libvirt_version.version_compare(5, 0, 0): - test.cancel("This libvirt version doesn't support " - "virtio-transitional model.") + test.cancel( + "This libvirt version doesn't support " "virtio-transitional model." + ) # Download and update image if required if guest_src_url: - image_name = params['image_path'] + image_name = params["image_path"] target_path = utils_misc.get_path(data_dir.get_data_dir(), image_name) if not os.path.exists(target_path): download.get_file(guest_src_url, target_path) @@ -139,25 +142,28 @@ def check_rng_inside_guest(): utils_conn.update_crypto_policy(set_crypto_policy) try: - # Add 'pcie-to-pci-bridge' if there is no one - pci_controllers = vmxml.get_controllers('pci') - for controller in pci_controllers: - if controller.get('model') == 'pcie-to-pci-bridge': - pci_bridge = controller - break - else: - contr_dict = {'controller_type': 'pci', - 'controller_model': 'pcie-to-pci-bridge'} - pci_bridge = libvirt.create_controller_xml(contr_dict) - libvirt.add_controller(vm_name, pci_bridge) - pci_bridge = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)\ - .get_controllers('pci', 'pcie-to-pci-bridge')[0] - pci_bridge_index = '%0#4x' % int(pci_bridge.get("index")) + if bridge_controller_needed: + # Add 'pcie-to-pci-bridge' if there is no one + pci_controllers = vmxml.get_controllers("pci") + for controller in pci_controllers: + if controller.get("model") == "pcie-to-pci-bridge": + pci_bridge = controller + break + else: + contr_dict = { + "controller_type": "pci", + "controller_model": "pcie-to-pci-bridge", + } + pci_bridge = libvirt.create_controller_xml(contr_dict) + libvirt.add_controller(vm_name, pci_bridge) + pci_bridge = vm_xml.VMXML.new_from_inactive_dumpxml( + vm_name + ).get_controllers("pci", "pcie-to-pci-bridge")[0] + pci_bridge_index = "%0#4x" % int(pci_bridge.get("index")) # Update nic/nvram and vm disks - if (params["os_variant"] == 'rhel6' or - 'rhel6' in params.get("shortname")): - iface_params = {'model': 'virtio-transitional'} + if params["os_variant"] == "rhel6" or "rhel6" in params.get("shortname"): + iface_params = {"model": "virtio-transitional"} libvirt.modify_vm_iface(vm_name, "update_iface", iface_params) virtio_transitional_base.remove_rhel6_nvram(vm_name) libvirt.set_vm_disk(vm, params) @@ -166,7 +172,7 @@ def check_rng_inside_guest(): vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) # Remove existed rng devices if there are - rng_devs = vmxml.get_devices('rng') + rng_devs = vmxml.get_devices("rng") for rng in rng_devs: vmxml.del_device(rng) vmxml.xmltreefile.write() @@ -174,15 +180,15 @@ def check_rng_inside_guest(): # General new rng xml per configurations rng_xml = libvirt.create_rng_xml({"rng_model": virtio_model}) - if params.get('specify_addr', 'no') == 'yes': - pci_devices = list(vmxml.xmltreefile.find('devices')) + if params.get("specify_addr", "no") == "yes": + pci_devices = list(vmxml.xmltreefile.find("devices")) addr = rng_xml.new_rng_address() - if plug_to == 'pcie-root-port': + if plug_to == "pcie-root-port": bus = get_free_root_port() - addr.set_attrs({'bus': bus}) + addr.set_attrs({"bus": bus}) else: slot = get_free_pci_slot() - addr.set_attrs({'bus': pci_bridge_index, 'slot': slot}) + addr.set_attrs({"bus": pci_bridge_index, "slot": slot}) rng_xml.address = addr if boot_with_rng: # Add to vm if required libvirt.add_vm_device(vmxml, rng_xml) @@ -199,7 +205,7 @@ def check_rng_inside_guest(): check_rng_inside_guest() if hotplug: # Unplug rng if hotplugged previously vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) - rng = vmxml.get_devices('rng')[0] + rng = vmxml.get_devices("rng")[0] file_arg = rng.xml with open(file_arg) as rng_file: logging.debug("Detach rng by XML: %s", rng_file.read()) @@ -208,14 +214,15 @@ def check_rng_inside_guest(): if not hotplug: session.close() save_path = os.path.join( - data_dir.get_tmp_dir(), '%s.save' % params['os_variant']) + data_dir.get_tmp_dir(), "%s.save" % params["os_variant"] + ) ret = virsh.save(vm_name, save_path) libvirt.check_exit_status(ret) ret = virsh.restore(save_path) libvirt.check_exit_status(ret) session = vm.wait_for_login() check_rng_inside_guest() - process.run('rm -f %s' % save_path, ignore_status=True) + process.run("rm -f %s" % save_path, ignore_status=True) finally: vm.destroy() backup_xml.sync() From dfdf06ece669a1be884a85895161745f7b7c0762 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 22 Jan 2025 03:18:20 -0500 Subject: [PATCH 0809/1055] transitional_vsock: disable on s390x The test assumes that vsock is a PCI device with additional device information to be checked. Only one test variant applies to s390x (virtio). We already have test vsock.* that covers this setup and more as it also covers functionality (establish communication). Therefore, skip this test suite for s390x. Signed-off-by: Sebastian Mitterle --- .../cfg/virtio_transitional/virtio_transitional_vsock.cfg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_vsock.cfg b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_vsock.cfg index 4200c1ff4fc..c925cb0672d 100644 --- a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_vsock.cfg +++ b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_vsock.cfg @@ -4,14 +4,13 @@ start_vm = no addr_pattern = '\d\d:\d\d\.\d' device_pattern = 'Communication controller: Red Hat.* Device | Communication controller: Red Hat.* socket' + no s390-virtio variants: - virtio: virtio_model = "virtio" - virtio_transitional: - no s390-virtio virtio_model = "virtio-transitional" - virtio_non_transitional: - no s390-virtio virtio_model = "virtio-non-transitional" variants: - boot_test: From 5d638685100b4a7a26b9a97197b7d8e2d55317eb Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 22 Jan 2025 18:03:47 +0800 Subject: [PATCH 0810/1055] viommu: Fix up incorrect devices' address issue Update to use the correct controller, disk and interface addresses. Signed-off-by: Yingshun Cui --- .../sriov/vIOMMU/iommu_device_settings.cfg | 3 +- provider/viommu/viommu_base.py | 38 ++++++++++++------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg b/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg index 0110f0eef49..6fe7af24ded 100644 --- a/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg +++ b/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg @@ -64,5 +64,6 @@ - pcie_root_port_from_expander_bus: test_devices = ["Eth", "block"] root_port = {'type': 'pci', 'model': 'pcie-root-port', 'pre_controller': 'pcie-expander-bus'} - controller_dicts = [{'type': 'pci', 'model': 'pcie-expander-bus', 'pre_controller': 'pcie-root'}, ${root_port}, ${root_port}] + controller_dicts = [{'type': 'pci', 'model': 'pcie-expander-bus', 'target': {'busNr': '252'}, 'pre_controller': 'pcie-root'}, ${root_port}, ${root_port}] + iface_dict = {'source': {'network': 'default'}} disk_dict = {'target': {'dev': 'vda', 'bus': 'virtio'}, 'device': 'disk', 'driver': ${disk_driver}} diff --git a/provider/viommu/viommu_base.py b/provider/viommu/viommu_base.py index 62d2255f34b..bc19a73137e 100644 --- a/provider/viommu/viommu_base.py +++ b/provider/viommu/viommu_base.py @@ -46,7 +46,6 @@ def __init__(self, vm, test, params, session=None): self.session = session self.remote_virsh_dargs = None self.controller_dicts = eval(self.params.get("controller_dicts", "[]")) - self.dev_slot = 0 libvirt_version.is_libvirt_feature_supported(self.params) new_xml = vm_xml.VMXML.new_from_inactive_dumpxml(self.vm.name) @@ -60,14 +59,16 @@ def parse_iface_dict(self): """ mac_addr = utils_net.generate_mac_address_simple() iface_dict = eval(self.params.get("iface_dict", "{}")) - self.test.log.debug("iface_dict2: %s.", iface_dict) if self.controller_dicts and iface_dict: iface_bus = "%0#4x" % int(self.controller_dicts[-1].get("index")) iface_attrs = {"bus": iface_bus} - if isinstance(self.dev_slot, int): - self.dev_slot += 1 - iface_attrs.update({"slot": self.dev_slot}) + if self.controller_dicts[-1].get("model") == "pcie-to-pci-bridge": + iface_slot = libvirt_pcicontr.get_free_pci_slot( + vm_xml.VMXML.new_from_dumpxml(self.vm.name), + controller_bus=iface_bus) + iface_attrs.update({"slot": iface_slot}) + iface_dict.update({"address": {"attrs": iface_attrs}}) self.test.log.debug("iface_dict: %s.", iface_dict) return iface_dict @@ -80,8 +81,8 @@ def prepare_controller(self): """ if not self.controller_dicts: return - - for contr_dict in self.controller_dicts: + for i in range(len(self.controller_dicts)): + contr_dict = self.controller_dicts[i] pre_controller = contr_dict.get("pre_controller") if pre_controller: pre_contrs = list( @@ -93,10 +94,16 @@ def prepare_controller(self): else: pre_idx = libvirt_pcicontr.get_max_contr_indexes( vm_xml.VMXML.new_from_dumpxml(self.vm.name), - contr_dict["type"], pre_controller) - if not pre_idx: - self.test.error( - f"Unable to get index of {pre_controller} controller!") + contr_dict["type"], pre_controller)[-1] + pre_contr_bus = "%0#4x" % int(pre_idx) + contr_attrs = {"bus": pre_contr_bus} + contr_slot = libvirt_pcicontr.get_free_pci_slot( + vm_xml.VMXML.new_from_dumpxml(self.vm.name), + controller_bus=pre_contr_bus) + if contr_dict.get("model") == "pcie-to-pci-bridge": + contr_slot = "0" + contr_attrs.update({"slot": contr_slot}) + contr_dict.update({"address": {"attrs": contr_attrs}}) contr_dict.pop("pre_controller") libvirt_vmxml.modify_vm_device( vm_xml.VMXML.new_from_dumpxml(self.vm.name), "controller", @@ -104,6 +111,9 @@ def prepare_controller(self): contr_dict["index"] = libvirt_pcicontr.get_max_contr_indexes( vm_xml.VMXML.new_from_dumpxml(self.vm.name), contr_dict["type"], contr_dict["model"])[-1] + self.controller_dicts[i] = contr_dict + + self.test.log.debug(f"Prepared controllers according to {self.controller_dicts}") return self.controller_dicts def update_disk_addr(self, disk_dict): @@ -120,8 +130,10 @@ def update_disk_addr(self, disk_dict): dev_attrs = {"bus": dev_bus} dev_attrs.update({"type": self.controller_dicts[-1].get("type")}) if self.controller_dicts[-1].get("model") == "pcie-to-pci-bridge": - self.dev_slot = 1 - dev_attrs.update({"slot": self.dev_slot}) + dev_slot = libvirt_pcicontr.get_free_pci_slot( + vm_xml.VMXML.new_from_dumpxml(self.vm.name), + controller_bus=dev_bus) + dev_attrs.update({"slot": dev_slot}) disk_dict.update({"address": {"attrs": dev_attrs}}) if disk_dict["target"]["bus"] == "scsi": From 0a7309d6105c3cad5aa5ef97f3a1e2d45e11da29 Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 22 Jan 2025 21:21:37 +0800 Subject: [PATCH 0811/1055] migration: Fix no element found issue For aarch64, only supports migration tests between hosts with the same CPU, so no need to check the CPU. For x86_64, update to use virsh hypervisor-cpu-compare command to compare CPU. Signed-off-by: lcheng --- .../migration_with_external_tpm.py | 2 +- .../migration_with_shared_tpm.py | 2 +- .../migration_with_vtpm_dev.py | 2 +- provider/migration/base_steps.py | 32 ++++++++++++++++--- 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_external_tpm.py b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_external_tpm.py index 462531aa923..3d02e119fb0 100644 --- a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_external_tpm.py +++ b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_external_tpm.py @@ -234,7 +234,7 @@ def cleanup_test(): migration_obj = base_steps.MigrationBase(test, vm, params) try: - if not base_steps.check_cpu_for_mig(desturi): + if not base_steps.check_cpu_for_mig(params): base_steps.sync_cpu_for_mig(params) setup_test() migration_obj.run_migration() diff --git a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py index b5f0ca31c1b..5d50d13ab16 100644 --- a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py +++ b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py @@ -291,7 +291,7 @@ def cleanup_test(): try: set_secret(params) - if not base_steps.check_cpu_for_mig(desturi): + if not base_steps.check_cpu_for_mig(params): base_steps.sync_cpu_for_mig(params) setup_test() migration_obj.run_migration() diff --git a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_dev.py b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_dev.py index dee89010cc5..c83f1f9a528 100644 --- a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_dev.py +++ b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_dev.py @@ -217,7 +217,7 @@ def cleanup_test(): vm = env.get_vm(vm_name) migration_obj = base_steps.MigrationBase(test, vm, params) - if base_steps.check_cpu_for_mig(desturi): + if base_steps.check_cpu_for_mig(params): if test_case != "diff_secret_on_src_and_dst": test.cancel("Need to use machines with different cpu to test this case.") else: diff --git a/provider/migration/base_steps.py b/provider/migration/base_steps.py index c5a7c3562db..2c2db7be67a 100644 --- a/provider/migration/base_steps.py +++ b/provider/migration/base_steps.py @@ -1,4 +1,5 @@ import os +import platform import time from six import itervalues @@ -525,16 +526,39 @@ def sync_cpu_for_mig(params): dom_xml.sync() -def check_cpu_for_mig(dest_uri): +def check_cpu_for_mig(params): """ Check cpu for migration - :param dest_uri: connect uri for destination machine + :param params: Dictionary with the test parameters :return: if the cpu on the source and target hosts are the same, return True """ - cpu_dest_xml = virsh.domcapabilities(uri=dest_uri, debug=True).stdout_text.strip() + dest_uri = params.get("virsh_migrate_desturi") + remote_ip = params.get("server_ip") + remote_user = params.get("server_user") + remote_pwd = params.get("server_pwd") + + # aarch64 only supports migration tests between hosts with the same CPU, so + # no need to check the CPU. + if platform.machine() == "aarch64": + return True + cpu_src_xml = virsh.domcapabilities(debug=True).stdout_text.strip() - if cpu_dest_xml == cpu_src_xml: + mig_src_xml = os.path.join(data_dir.get_tmp_dir(), "mig_src.xml") + with open(mig_src_xml, 'w+') as fd: + fd.write(cpu_src_xml) + + remote_session = remote.remote_login("ssh", remote_ip, "22", + remote_user, remote_pwd, + r'[$#%]') + utils_misc.make_dirs(os.path.dirname(mig_src_xml), remote_session) + remote_session.close() + remote.scp_to_remote(remote_ip, '22', remote_user, remote_pwd, mig_src_xml, + mig_src_xml, limit="", log_filename=None, timeout=60, + interface=None) + + ret = virsh.hypervisor_cpu_compare(xml_file=mig_src_xml, uri=dest_uri, debug=True).stdout_text.strip() + if "identical" in ret or "superset" in ret: return True else: return False From 3b751d93bf4afea19d55cbfe8b729b203ea5c78a Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Thu, 23 Jan 2025 11:37:24 +0800 Subject: [PATCH 0812/1055] vIOMMU: Move viommu_netperf.cfg to vIOMMU dir Signed-off-by: Yingshun Cui --- libvirt/tests/cfg/{ => sriov/vIOMMU}/viommu_netperf.cfg | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename libvirt/tests/cfg/{ => sriov/vIOMMU}/viommu_netperf.cfg (100%) diff --git a/libvirt/tests/cfg/viommu_netperf.cfg b/libvirt/tests/cfg/sriov/vIOMMU/viommu_netperf.cfg similarity index 100% rename from libvirt/tests/cfg/viommu_netperf.cfg rename to libvirt/tests/cfg/sriov/vIOMMU/viommu_netperf.cfg From 83c47f86e2b8463cb6989d13baeb13a3ce64a167 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 12 Dec 2024 22:23:47 -0500 Subject: [PATCH 0813/1055] get_vm_ip:Return None if needed We use get_vm_ip to replace utils_net.get_guest_ip_addr in some test code to avoid potential risks, but it changes the original behavior which is to return None when cannot get valid ip address. Add an argument to choose between returning None or raising error to fix this problem. Signed-off-by: Haijiao Zhao --- libvirt/tests/src/virtual_network/iface_network.py | 2 +- provider/virtual_network/network_base.py | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/src/virtual_network/iface_network.py b/libvirt/tests/src/virtual_network/iface_network.py index 39f01a017dd..4a42a118f3e 100644 --- a/libvirt/tests/src/virtual_network/iface_network.py +++ b/libvirt/tests/src/virtual_network/iface_network.py @@ -1107,7 +1107,7 @@ def _check_lease(loop): vms_mac = vms.get_virsh_mac_address() # restart guest network to get ip addr utils_net.restart_guest_network(sess, vms_mac) - vms_ip = network_base.get_vm_ip(sess, vms_mac) + vms_ip = network_base.get_vm_ip(sess, vms_mac, ignore_error=True) if not vms_ip and dhcp_range: test.fail("Guest has invalid ip address") elif vms_ip and not dhcp_range: diff --git a/provider/virtual_network/network_base.py b/provider/virtual_network/network_base.py index 4360c1b1b52..06e31d33460 100644 --- a/provider/virtual_network/network_base.py +++ b/provider/virtual_network/network_base.py @@ -19,13 +19,15 @@ LOG = logging.getLogger('avocado.' + __name__) -def get_vm_ip(session, mac, ip_ver="ipv4", timeout=5): +def get_vm_ip(session, mac, ip_ver="ipv4", timeout=5, ignore_error=False): """ Get vm ip address :param session: vm session :param mac: mac address of vm :param ip_ver: ip version, defaults to "ipv4" + :param ignore_error: True to return None, False to raise exception, + defaults to False :return: ip address of given mac """ def _get_vm_ip(): @@ -39,16 +41,16 @@ def _get_vm_ip(): and addr.get('mngtmpaddr') is not True] if len(target_addr) == 0: - LOG.warn(f'No ip addr of given mac: {mac}') + LOG.warning(f'No ip addr of given mac: {mac}') return elif len(target_addr) > 1: - LOG.warn(f'Multiple ip addr: {target_addr}') + LOG.warning(f'Multiple ip addr: {target_addr}') return target_addr[0]['local'] vm_ip = utils_misc.wait_for(_get_vm_ip, timeout, ignore_errors=True) - if not vm_ip: + if not vm_ip and not ignore_error: raise exceptions.TestError( f'Cannot find {ip_ver} addr with given mac: {mac}') From 24c084235ead5a839771c82dce4ea5ec135c30c5 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 23 Jan 2025 03:14:26 -0500 Subject: [PATCH 0814/1055] virsh_net_update:Remove negative cases of update dns-txt dns-host Updating dns-txt and dns-host of network is supported now Signed-off-by: Haijiao Zhao --- libvirt/tests/cfg/virsh_cmd/network/virsh_net_update.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/cfg/virsh_cmd/network/virsh_net_update.cfg b/libvirt/tests/cfg/virsh_cmd/network/virsh_net_update.cfg index 63318918b06..236b876f0b1 100644 --- a/libvirt/tests/cfg/virsh_cmd/network/virsh_net_update.cfg +++ b/libvirt/tests/cfg/virsh_cmd/network/virsh_net_update.cfg @@ -322,6 +322,7 @@ network_section = "dns-host" variants: - modify: + no dns_host,dns_txt update_command = "modify" error_type = "modify" - dns_disable: From 7b1252617eea2e48a7661c2810f43e6f6d2720f3 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 23 Jan 2025 03:24:14 -0500 Subject: [PATCH 0815/1055] guest_numa:Code style check fix Signed-off-by: Haijiao Zhao --- libvirt/tests/src/numa/guest_numa.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/numa/guest_numa.py b/libvirt/tests/src/numa/guest_numa.py index e58d4d58cf2..c9a94eabf35 100644 --- a/libvirt/tests/src/numa/guest_numa.py +++ b/libvirt/tests/src/numa/guest_numa.py @@ -66,7 +66,7 @@ def dynamic_node_replacement(params, numa_info, test_obj): if not node_list: test_obj.cancel("No NUMA nodes available on this system to perform the test.") elif int(params['numa_cells_with_memory_required']) > len(node_list): - test_obj.cancel("There is no enough NUMA nodes available on this system to perform the test.") + test_obj.cancel("There is no enough NUMA nodes available on this system to perform the test.") if 'memory_nodeset' in param: params['memory_nodeset'] = ','.join([str(elem) for elem in node_list]) logging.debug('The parameter "memory_nodeset" from config file is going to be replaced by: {} available ' From d320a6e7eb20f927068c242f8f7e1d00f2243907 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 24 Jan 2025 16:10:39 +0800 Subject: [PATCH 0816/1055] Enable a viommu test on aarch64 Signed-off-by: Yingshun Cui --- .../cfg/sriov/vIOMMU/virtio_iommu_with_addtional_attributes.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/sriov/vIOMMU/virtio_iommu_with_addtional_attributes.cfg b/libvirt/tests/cfg/sriov/vIOMMU/virtio_iommu_with_addtional_attributes.cfg index 7811bc087c2..651b609ecbd 100644 --- a/libvirt/tests/cfg/sriov/vIOMMU/virtio_iommu_with_addtional_attributes.cfg +++ b/libvirt/tests/cfg/sriov/vIOMMU/virtio_iommu_with_addtional_attributes.cfg @@ -4,7 +4,7 @@ enable_guest_iommu = "yes" err_msg = "iommu model 'virtio' doesn't support additional attributes" func_supported_since_libvirt_ver = (8, 7, 0) - only x86_64 + only x86_64, aarch64 variants: - caching_mode: iommu_dict = {'driver': {'caching_mode': 'on'}, 'model': 'virtio'} From e5e9bd5645893713b819291ee8bc99aee799a8b7 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Mon, 18 Nov 2024 22:07:27 -0500 Subject: [PATCH 0817/1055] ethernet interface: Update iface xml instead of create new one Signed-off-by: Haijiao Zhao --- .../connectivity_check_ethernet_interface.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py index ec7ec55caae..ebb25644371 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py @@ -28,6 +28,7 @@ def run(test, params, env): vm_name = params.get('main_vm') vm = env.get_vm(vm_name) virsh_ins = virsh + test_user = 'root' else: vm_name = params.get('unpr_vm_name') test_user = params.get('test_user', '') @@ -71,7 +72,9 @@ def run(test, params, env): try: mac_addr = vm_xml.VMXML.get_first_mac_by_name(vm_name, virsh_ins) tap_flag = '' - for attr in (iface_attrs, iface_attrs_2): + iface_ori = network_base.get_iface_xml_inst( + vm_name, 'on vm', virsh_ins=virsh_ins) + for attr in (iface_attrs, iface_attrs_2, iface_ori.fetch_attrs()): if attr.get('driver', {}).get('driver_attr', {}).get('queues'): tap_flag = 'multi_queue' break @@ -99,7 +102,6 @@ def run(test, params, env): iface_attrs['mac_address'] = mac_addr vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=virsh_ins) - vmxml.del_device('interface', by_tag=True) libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs, virsh_instance=virsh_ins) if iface_attrs_2: @@ -109,7 +111,7 @@ def run(test, params, env): libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs_2, 1, virsh_instance=virsh_ins) - LOG.debug(f'VMxml is:\n{virsh_ins.dumpxml(vm_name).stdout_text}') + LOG.debug(f'VMxml is:\n{virsh.dumpxml(vm_name, uri=uri).stdout_text}') start_result = virsh.start(vm_name, debug=True, uri=uri) libvirt.check_exit_status(start_result, status_error) @@ -126,6 +128,9 @@ def run(test, params, env): 'host_public_ip': host_ip, } vm_default_gw = utils_net.get_default_gateway(session=session, json=True) + if isinstance(vm_default_gw, list): + vm_default_gw = [gw for gw in vm_default_gw if gw.startswith('192')][0] + LOG.debug(f'vm_default_gw is {vm_default_gw}') if iface_amount == 'two_ifaces': ping_params = { @@ -188,12 +193,12 @@ def run(test, params, env): session.close() finally: - bkxml.sync(virsh_instance=virsh_ins) - if not root: - del virsh_ins if tap_type: network_base.delete_tap(tap_name) if iface_amount == 'two_ifaces': network_base.delete_tap(tap_name_2) if tap_type == 'tap': utils_net.delete_linux_bridge_tmux(bridge_name, host_iface) + bkxml.sync(virsh_instance=virsh_ins) + if not root: + virsh_ins.close_session() From ccdc124eee173a3d15dbbbec4478a517ebb53d0f Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Sun, 26 Jan 2025 21:21:25 -0500 Subject: [PATCH 0818/1055] Fix two issues 1. Fix undefine error of variable arch 2. Make sure enough huge page memory is allocated for specific host numa node Signed-off-by: liang-cong-red-hat --- libvirt/tests/src/numa/guest_numa.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libvirt/tests/src/numa/guest_numa.py b/libvirt/tests/src/numa/guest_numa.py index c9a94eabf35..27c880b8566 100644 --- a/libvirt/tests/src/numa/guest_numa.py +++ b/libvirt/tests/src/numa/guest_numa.py @@ -62,6 +62,7 @@ def dynamic_node_replacement(params, numa_info, test_obj): key_names = ['memnode_nodeset_', 'page_nodenum_'] for param in params: if 'numa_cells_with_memory_required' in param: + arch = platform.machine() if 'ppc64' in arch: if not node_list: test_obj.cancel("No NUMA nodes available on this system to perform the test.") @@ -291,6 +292,20 @@ def _update_qemu_conf(): deallocate = True hp_cl.target_hugepages = hugepage_num hp_cl.set_hugepages() + # for strict mode, allocate the guest numa cell again to + # make sure it has enough huge page + numa_hugepage_dict = {} + if numa_memnode and numa_memnode[0]['mode'] == 'strict': + if numa_cell: + for cell in numa_cell: + if cell['id'] == numa_memnode[0]['cellid']: + numa_hugepage_dict['node'] = numa_memnode[0]['nodeset'] + numa_hugepage_dict['hp_num'] = int( + cell['memory']) // default_mem_huge_page_size + numa_hugepage_dict['hp_size'] = default_mem_huge_page_size + if numa_hugepage_dict: + hp_cl.set_node_num_huge_pages( + numa_hugepage_dict['hp_num'], numa_hugepage_dict['node'], numa_hugepage_dict['hp_size']) if page_list: hp_size = [h_list[p_size]['size'] for p_size in range(len(h_list))] multi_hp_size = hp_cl.get_multi_supported_hugepage_size() From 5c0cd6c18f32856e8a336c0192a749853f2b2123 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Sun, 26 Jan 2025 17:10:46 +0800 Subject: [PATCH 0819/1055] virsh_detach_device_alias: enhancement for pci Currently the cases are skipped in most time because below error: error: Failed to attach device from pci.xml error: internal error: Non-endpoint PCI devices cannot be assigned to guests This is because the incorrect pci device is used to attach to the vm. This fix is an enhancement to increase possiblities of finding the suitable pci device. Signed-off-by: Dan Zheng --- .../domain/virsh_detach_device_alias.py | 38 +++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py b/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py index 92528d47d09..7251d2fa728 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py @@ -1,6 +1,7 @@ +import logging as log import os +import platform import uuid -import logging as log from virttest import data_dir from virttest import virsh @@ -22,6 +23,34 @@ logging = log.getLogger('avocado.' + __name__) +def get_suitable_pci_device(test): + """ + Get a suitable pci device ID for attaching to the vm. + The host PCI devices will vary on different hardware, so it is hard + to always get an usable pci device. + + :param test: test object + :return: str, the pci device full id or None + """ + pci_ids = utils_sys.get_host_bridge_id() + if not pci_ids: + test.error("Not Found any pci devices") + + if platform.machine() != "aarch64": + good_pci = utils_misc.get_full_pci_id(pci_ids[-1]).split("\n")[0] + return good_pci + else: + suitable_pci_ids = [id for id in pci_ids if id != "0000:00"] + for pci_id in suitable_pci_ids: + full_ids = utils_misc.get_full_pci_id(pci_id) + good_pci = "%s:00.0" % pci_id + if full_ids.count(good_pci): + test.log.debug("PCI ID '%s' is chosen", good_pci) + return good_pci + test.log.warning("No suitable PCI ID is chosen") + return None + + def run(test, params, env): """ Test detach-device-alias command with @@ -159,12 +188,7 @@ def start_usbredirserver(): dev_type='controller', dev_dict=controller_dict, index=int(params.get("index"))) - - pci_ids = utils_sys.get_host_bridge_id() - if not pci_ids: - test.error("Not Found any pci devices") - pci_id = utils_misc.get_full_pci_id(pci_ids[-1]) - + pci_id = get_suitable_pci_device(test) if not vm.is_alive(): vm.start() vm.wait_for_login() From 1a64f5793c63a47c3bd810ecb8e800b5762e2953 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 27 Jan 2025 02:23:13 -0500 Subject: [PATCH 0820/1055] Pass the arch parameter to the function dynamic_node_replacement Signed-off-by: Lili Zhu --- libvirt/tests/src/numa/guest_numa.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/numa/guest_numa.py b/libvirt/tests/src/numa/guest_numa.py index c9a94eabf35..ac574cdd24d 100644 --- a/libvirt/tests/src/numa/guest_numa.py +++ b/libvirt/tests/src/numa/guest_numa.py @@ -50,12 +50,13 @@ def handle_param(param_tuple, params): return param_list -def dynamic_node_replacement(params, numa_info, test_obj): +def dynamic_node_replacement(params, numa_info, arch, test_obj): """ Replace numa node parameters dynamically per current system configuration :param numa_info: available numa node info from avocado-vt/utils_misc :param params: all params passed to test + :param arch: The host architecture :param test_obj: test object - for cancel case """ node_list = numa_info.get_online_nodes_withmem() @@ -104,7 +105,7 @@ def run(test, params, env): host_numa_node = utils_misc.NumaInfo() node_list = host_numa_node.online_nodes arch = platform.machine() - dynamic_node_replacement(params, host_numa_node, test) + dynamic_node_replacement(params, host_numa_node, arch, test) if 'ppc64' in arch: try: ppc_memory_nodeset = "" From 0e8508a738745b05d27e6afbdc1dea2c86fbea05 Mon Sep 17 00:00:00 2001 From: Kowshik Jois B S Date: Tue, 28 Jan 2025 15:15:12 +0530 Subject: [PATCH 0821/1055] There was a bug reported where qemu command line was giving core dump error as below. ** ERROR:../tcg/region.c:782:tcg_region_init: assertion failed: (region_size >= 2 * page_size) Bail out! ERROR:../tcg/region.c:782:tcg_region_init: assertion failed: (region_size >= 2 * page_size) Aborted (core dumped) A fix has been posted upstream and is merged with distros(Fedora and Ubuntu). Adding this test case to catch such a scenario in future. Reference bug: https://bugs.launchpad.net/ubuntu/+source/qemu/+bug/2055003 Signed-off-by: Kowshik Jois B S --- .../cfg/virsh_cmd/virsh_qemu_cmdline_core.cfg | 6 ++++ .../src/virsh_cmd/virsh_qemu_cmdline_core.py | 31 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 libvirt/tests/cfg/virsh_cmd/virsh_qemu_cmdline_core.cfg create mode 100644 libvirt/tests/src/virsh_cmd/virsh_qemu_cmdline_core.py diff --git a/libvirt/tests/cfg/virsh_cmd/virsh_qemu_cmdline_core.cfg b/libvirt/tests/cfg/virsh_cmd/virsh_qemu_cmdline_core.cfg new file mode 100644 index 00000000000..fcd5e3019b1 --- /dev/null +++ b/libvirt/tests/cfg/virsh_cmd/virsh_qemu_cmdline_core.cfg @@ -0,0 +1,6 @@ +- io-github-autotest-libvirt.virsh.qemu_cmdline_core: + virt_test_type = libvirt + provider = io-github-autotest-libvirt + type = virsh_qemu_cmdline_core + variants: + - qemu_cmdline_more_cpus: diff --git a/libvirt/tests/src/virsh_cmd/virsh_qemu_cmdline_core.py b/libvirt/tests/src/virsh_cmd/virsh_qemu_cmdline_core.py new file mode 100644 index 00000000000..ac9f5572e8b --- /dev/null +++ b/libvirt/tests/src/virsh_cmd/virsh_qemu_cmdline_core.py @@ -0,0 +1,31 @@ +import subprocess + + +def run(test, params, env): + + qemu_binary = params.get("qemu_binary") + errors = ["tcg_region_init", "assertion failed", "Aborted", + "core dumped", "Invalid CPU topology"] + + def check_qemu_cmdline(cpus=9999): + + print("checking with %d CPUs" % cpus) + + command = "%s -accel tcg -smp 10,maxcpus=%d" % (qemu_binary, cpus) + global output + output = subprocess.getoutput(command) + + for err in errors: + if err in output: + return True + return False + + cpus = ["9000", "123", "97865", "56789", "123456789"] + + for cpu in cpus: + failed = check_qemu_cmdline(int(cpu)) + if failed: + break + + if failed: + test.fail(output) From 65c9ad958766a4e13e58296b91e89e6c4a810348 Mon Sep 17 00:00:00 2001 From: Kowshik Jois B S Date: Thu, 30 Jan 2025 21:25:42 +0530 Subject: [PATCH 0822/1055] Changing a negative scenario to positive Description: In my recent PR #6114, I had added required changes for autodestroy. As per the comments received, modifying the test to be a positive scenario rather than a negative one. Signed-off-by: Kowshik Jois B S --- .../cfg/virsh_cmd/snapshot/virsh_snapshot_create_as.cfg | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/virsh_cmd/snapshot/virsh_snapshot_create_as.cfg b/libvirt/tests/cfg/virsh_cmd/snapshot/virsh_snapshot_create_as.cfg index aa9597c6215..102c992f879 100644 --- a/libvirt/tests/cfg/virsh_cmd/snapshot/virsh_snapshot_create_as.cfg +++ b/libvirt/tests/cfg/virsh_cmd/snapshot/virsh_snapshot_create_as.cfg @@ -35,9 +35,6 @@ domain_state = "paused" - running_domain: domain_state = "running" - - autodestroy_domain: - create_autodestroy = "yes" - snap_createas_opts = "--disk-only" - quiesce_without_unix_channel: unix_channel = "no" snap_createas_opts = "--quiesce --disk-only" @@ -162,6 +159,10 @@ snap_createas_opts = "--print-xml --name tt --description hello --disk-only" diskspec_opts1 = "vda,snapshot=internal,driver=raw,file=test1.img" diskspec_opts2 = "vdb,snapshot=no" + - autodestroy_domain: + status_error = "yes" + create_autodestroy = "yes" + snap_createas_opts = "--disk-only" variants: - file_disk: variants: From 058e8fc5ee8fba8c68d94087ee23e94db60365a6 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Wed, 5 Feb 2025 03:47:48 -0500 Subject: [PATCH 0823/1055] save_and_restore:Remove workaound Remove workaround added by Commit 5c125c2 Signed-off-by: Haijiao Zhao --- .../tests/cfg/save_and_restore/restore_from_local_file.cfg | 1 - libvirt/tests/cfg/save_and_restore/save_with_options.cfg | 1 - .../tests/src/save_and_restore/restore_from_local_file.py | 5 ----- libvirt/tests/src/save_and_restore/save_to_block.py | 4 ---- libvirt/tests/src/save_and_restore/save_to_nfs.py | 4 ---- libvirt/tests/src/save_and_restore/save_with_formats.py | 4 ---- libvirt/tests/src/save_and_restore/save_with_options.py | 5 ----- 7 files changed, 24 deletions(-) diff --git a/libvirt/tests/cfg/save_and_restore/restore_from_local_file.cfg b/libvirt/tests/cfg/save_and_restore/restore_from_local_file.cfg index 94fbd576d9a..7e070ba44f2 100644 --- a/libvirt/tests/cfg/save_and_restore/restore_from_local_file.cfg +++ b/libvirt/tests/cfg/save_and_restore/restore_from_local_file.cfg @@ -1,7 +1,6 @@ - save_and_restore.restore_from_local_file: type = restore_from_local_file save_opt = - start_vm = no variants scenario: - file_opt: pre_path_options = --file diff --git a/libvirt/tests/cfg/save_and_restore/save_with_options.cfg b/libvirt/tests/cfg/save_and_restore/save_with_options.cfg index d0a97f39af7..606b78223e9 100644 --- a/libvirt/tests/cfg/save_and_restore/save_with_options.cfg +++ b/libvirt/tests/cfg/save_and_restore/save_with_options.cfg @@ -1,6 +1,5 @@ - save_and_restore.save_with_options: type = save_with_options - start_vm = no variants scenario: - no_opt: options = diff --git a/libvirt/tests/src/save_and_restore/restore_from_local_file.py b/libvirt/tests/src/save_and_restore/restore_from_local_file.py index f8234629a93..52398dca326 100644 --- a/libvirt/tests/src/save_and_restore/restore_from_local_file.py +++ b/libvirt/tests/src/save_and_restore/restore_from_local_file.py @@ -7,7 +7,6 @@ from virttest import utils_misc from virttest import virsh from virttest.libvirt_xml import vm_xml -from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_test import libvirt from provider.save import save_base @@ -113,10 +112,6 @@ def run(test, params, env): bkxml = vmxml.copy() try: - # Workaround bug: Remove multi-queue setting - libvirt_vmxml.modify_vm_device(vmxml, 'interface', {'driver': None}) - vm.start() - pid_ping, upsince = save_base.pre_save_setup(vm) virsh.save(vm_name, save_path, options=save_opt, **VIRSH_ARGS) diff --git a/libvirt/tests/src/save_and_restore/save_to_block.py b/libvirt/tests/src/save_and_restore/save_to_block.py index 0886135b0a3..a0a79b4eeec 100644 --- a/libvirt/tests/src/save_and_restore/save_to_block.py +++ b/libvirt/tests/src/save_and_restore/save_to_block.py @@ -7,7 +7,6 @@ from virttest import utils_selinux from virttest import virsh from virttest.libvirt_xml import vm_xml -from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_test import libvirt from provider.save import save_base @@ -34,9 +33,6 @@ def run(test, params, env): libvirtd = utils_libvirtd.Libvirtd() try: - # Workaround bug: Remove multi-queue setting - libvirt_vmxml.modify_vm_device(vmxml, 'interface', {'driver': None}) - selinux_status = passt.ensure_selinux_enforcing() if namespaces: qemu_conf.namespaces = eval(namespaces) diff --git a/libvirt/tests/src/save_and_restore/save_to_nfs.py b/libvirt/tests/src/save_and_restore/save_to_nfs.py index 1df4c9dd056..b457310512a 100644 --- a/libvirt/tests/src/save_and_restore/save_to_nfs.py +++ b/libvirt/tests/src/save_and_restore/save_to_nfs.py @@ -8,7 +8,6 @@ from virttest import utils_misc from virttest import virsh from virttest.libvirt_xml import vm_xml -from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_test import libvirt from provider.save import save_base @@ -40,9 +39,6 @@ def run(test, params, env): libvirtd = utils_libvirtd.Libvirtd() try: - # Workaround bug: Remove multi-queue setting - libvirt_vmxml.modify_vm_device(vmxml, 'interface', {'driver': None}) - qemu_conf.dynamic_ownership = 0 if vmxml.devices.by_device_tag('tpm') is not None: qemu_conf.swtpm_user = 'qemu' diff --git a/libvirt/tests/src/save_and_restore/save_with_formats.py b/libvirt/tests/src/save_and_restore/save_with_formats.py index af9aed13e76..0679390120e 100644 --- a/libvirt/tests/src/save_and_restore/save_with_formats.py +++ b/libvirt/tests/src/save_and_restore/save_with_formats.py @@ -6,7 +6,6 @@ from virttest import utils_misc from virttest import virsh from virttest.libvirt_xml import vm_xml -from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_test import libvirt from provider.save import save_base @@ -34,9 +33,6 @@ def run(test, params, env): bkxml = vmxml.copy() try: - # Workaround bug: Remove multi-queue setting - libvirt_vmxml.modify_vm_device(vmxml, 'interface', {'driver': None}) - qemu_conf = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() qemu_conf.save_image_format = save_format diff --git a/libvirt/tests/src/save_and_restore/save_with_options.py b/libvirt/tests/src/save_and_restore/save_with_options.py index 1e1dfb5c743..e77555539ca 100644 --- a/libvirt/tests/src/save_and_restore/save_with_options.py +++ b/libvirt/tests/src/save_and_restore/save_with_options.py @@ -7,7 +7,6 @@ from virttest import utils_package from virttest import virsh from virttest.libvirt_xml import vm_xml -from virttest.utils_libvirt import libvirt_vmxml from virttest.utils_test import libvirt from provider.save import save_base @@ -52,10 +51,6 @@ def check_output(pattern, output, cmd): bkxml = vmxml.copy() try: - # Workaround bug: Remove multi-queue setting - libvirt_vmxml.modify_vm_device(vmxml, 'interface', {'driver': None}) - vm.start() - pid_ping, upsince = save_base.pre_save_setup(vm) if pre_state == 'paused': virsh.suspend(vm_name, **VIRSH_ARGS) From 40d7b9b2ac6cf7381adf4710ec783043c8a6a1c2 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Tue, 14 Jan 2025 22:17:53 -0500 Subject: [PATCH 0824/1055] Test the "--managed-save" option When the VM have a managedsave file, it can not be undefined without the "--managed-save" option. This option can remove the managedsave file and then undefine the VM. Signed-off-by: Yalan Zhang --- .../domain/virsh_managedsave_undefine.cfg | 3 + .../domain/virsh_managedsave_undefine.py | 56 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave_undefine.cfg create mode 100644 libvirt/tests/src/virsh_cmd/domain/virsh_managedsave_undefine.py diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave_undefine.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave_undefine.cfg new file mode 100644 index 00000000000..872210d7b51 --- /dev/null +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave_undefine.cfg @@ -0,0 +1,3 @@ +- virsh.managedsave_undefine: + type = "virsh_managedsave_undefine" + start_vm = "yes" diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave_undefine.py b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave_undefine.py new file mode 100644 index 00000000000..a83e669b565 --- /dev/null +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave_undefine.py @@ -0,0 +1,56 @@ +import os +import logging +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt + +VIRSH_ARGS = {'debug': True, 'ignore_status': False} +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test option: --managed-save + + Undefine a vm with or without --managed-save option + 1. start a vm, and do managedsave + 2. try to undefine the vm without "--managed-save" option, it should fail + 3. try to undefine the vm with "--managed-save" option, it succeeds + """ + + def vm_undefine_check(vm_name): + """ + Check if vm can be undefined with managed-save option + """ + if not os.path.exists(managed_save_file): + test.fail("Can't find managed save image") + LOG.info("Step2: Undefine the VM without --managed-save option:") + ret = virsh.undefine(vm_name, options='--nvram', ignore_status=True, debug=True) + libvirt.check_exit_status(ret, expect_error=True) + LOG.info("Step3: Undefine the VM with --managed-save option:") + ret1 = virsh.undefine(vm_name, options="--managed-save --nvram", + ignore_status=True) + LOG.debug("%s", ret1) + if ret1.exit_status: + test.fail("Guest can't be undefined with " + "managed-save option!") + + if os.path.exists(managed_save_file): + test.fail("Managed save image exists after undefining vm!") + # restore and start the vm + bk_xml.define() + vm.start() + + vm_name = params.get('main_vm') + managed_save_file = "/var/lib/libvirt/qemu/save/%s.save" % vm_name + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bk_xml = vmxml.copy() + try: + vm = env.get_vm(vm_name) + LOG.info("Step1: start the VM and do managedsave:") + if not vm.is_alive: + vm.start() + virsh.managedsave(vm_name, **VIRSH_ARGS) + vm_undefine_check(vm_name) + finally: + bk_xml.sync() From cc8d8fbbfce64e3dcfc4d7a1b411a40a58c430b8 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Fri, 7 Feb 2025 14:41:54 +0800 Subject: [PATCH 0825/1055] v2v: delete duplicate test case with function_test_esx..external_poweroff Signed-off-by: vwu-vera --- v2v/tests/cfg/specific_kvm.cfg | 9 --------- 1 file changed, 9 deletions(-) diff --git a/v2v/tests/cfg/specific_kvm.cfg b/v2v/tests/cfg/specific_kvm.cfg index e09d4bce6a2..4806b1da0b7 100644 --- a/v2v/tests/cfg/specific_kvm.cfg +++ b/v2v/tests/cfg/specific_kvm.cfg @@ -150,12 +150,6 @@ msg_content = 'kernel [\s\S]* in bootloader, as it does not exist' expect_msg = 'yes' enable_legacy_policy = yes - - unclean_fs: - only source_kvm - checkpoint = 'unclean_fs' - main_vm = 'VM_WIN_8_V2V_EXAMPLE' - msg_content = '.*Windows Hibernation or Fast Restart.*' - expect_msg = 'yes' - network: variants: - multi_netcards: @@ -320,7 +314,6 @@ variants: - linux: no default - no unclean_fs no multi_disks.windows no network.e1000 no fstab.invalid @@ -385,7 +378,5 @@ main_vm = "VM_GUEST_NO_SPACE_V2V_EXAMPLE" checkpoint = 'host_no_space' msg_content = 'virt-v2v: error: insufficient free space in the conversion server' - - unclean_file_system: - only unclean_fs - fstab_invalid: only fstab.invalid From 944c643ca59c788f62381be697e223127274f6ca Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Fri, 7 Feb 2025 03:07:16 -0500 Subject: [PATCH 0826/1055] Fix three issues for more than 2 available host numa node 1. When the host has more than 2 host numa node with memory, the huge page could be allocated on all these nodes, this would impact the verification, so limit only 2 host numa node for huge page allocation. 2. Enable shell when executing cmd with '>'. 3. Add '-r' for remove cmd to delete directory correctly. Signed-off-by: liang-cong-red-hat --- .../memory_devices/virtio_memory_with_numa_node_tuning.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/src/memory/memory_devices/virtio_memory_with_numa_node_tuning.py b/libvirt/tests/src/memory/memory_devices/virtio_memory_with_numa_node_tuning.py index cb35ec81ea7..96be45a0364 100644 --- a/libvirt/tests/src/memory/memory_devices/virtio_memory_with_numa_node_tuning.py +++ b/libvirt/tests/src/memory/memory_devices/virtio_memory_with_numa_node_tuning.py @@ -68,7 +68,7 @@ def _allocate_huge_memory(params, test, allocate_mem, kernel_hp_file = params.get("kernel_hp_tmpl_file") cleanup_file = params.get("cleanup_file", []) - target_nodes = params.get("numa_obj").online_nodes_withmem + target_nodes = params.get("numa_obj").online_nodes_withmem[:2] params.update({"all_nodes": target_nodes}) test.log.debug("Allocate %sKiB on %s pagesize", allocate_mem, hugepage_size) @@ -431,10 +431,10 @@ def teardown_test(): test.log.info("TEST_TEARDOWN: Clean up env.") bkxml.sync() for file in params.get("cleanup_file", []): - process.run("echo 0 > %s" % file, ignore_status=True) + process.run("echo 0 > %s" % file, ignore_status=True, shell=True) hg_path = params.get("hg_path") if hg_path: - process.run("umount %s; rm %s" % (hg_path, hg_path), ignore_status=True) + process.run("umount %s; rm -r %s" % (hg_path, hg_path), ignore_status=True, shell=True) vm_name = params.get("main_vm") vm = env.get_vm(vm_name) From b7ebfaa52482f76dea21b0f0748d62a6f3626180 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Fri, 7 Feb 2025 16:35:27 +0800 Subject: [PATCH 0827/1055] v2v: fix the failed case with deprecated i440fx type img Signed-off-by: vwu-vera --- v2v/tests/cfg/specific_kvm.cfg | 5 +---- v2v/tests/cfg/v2v_options.cfg | 5 +++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/v2v/tests/cfg/specific_kvm.cfg b/v2v/tests/cfg/specific_kvm.cfg index e09d4bce6a2..408802c1897 100644 --- a/v2v/tests/cfg/specific_kvm.cfg +++ b/v2v/tests/cfg/specific_kvm.cfg @@ -252,9 +252,6 @@ only rhev checkpoint = 'host_no_space_setcache' main_vm = 'VM_ESX_DEFAULT_NAME_V2V_EXAMPLE' - - mem_alloc: - only source_kvm - main_vm = VM_MEM_ACCLOC_V2V_EXAMPLE - no_libguestfs_backend: only esx.esx_70 main_vm = 'VM_ESX_DEFAULT_NAME_V2V_EXAMPLE' @@ -352,7 +349,7 @@ - network: only network.e1000,non_exist_network - to_libvirt: - only display.mix,display.listen,mem_alloc,80_chars + only display.mix,display.listen,80_chars only output_mode.libvirt - to_local: only win_rootonlinux diff --git a/v2v/tests/cfg/v2v_options.cfg b/v2v/tests/cfg/v2v_options.cfg index 8927c8eafb9..7fb5cb87a78 100644 --- a/v2v/tests/cfg/v2v_options.cfg +++ b/v2v/tests/cfg/v2v_options.cfg @@ -358,6 +358,11 @@ only output_mode.none input_disk_image = '/DISK_IMAGE_PATH_V2V_EXAMPLE/IMAGE_WITH_IMMUTABLE_BITS_V2V_EXAMPLE' v2v_options = '-i disk ${input_disk_image} -o null' + - mem_alloc: + only input_mode.none + only output_mode.none + input_disk_image = '/DISK_IMAGE_PATH_V2V_EXAMPLE/IMAGE_WITH_MEM_ALLOC_V2V_EXAMPLE' + v2v_options = '-i disk ${input_disk_image} -o null' - negative_test: status_error = "yes" variants: From 99eb999c8e3448533cba103ff42915ed682da7d8 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Fri, 7 Feb 2025 20:50:45 -0500 Subject: [PATCH 0828/1055] Wait 2 seconds after the listen cmd The listen cmd may not be ready if we send the file immediately, wait 2 seconds after the listen cmd. Signed-off-by: Yalan Zhang --- libvirt/tests/src/virtual_network/passt/passt_transfer_file.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py index e1d22ba69f3..1d95b71bbbe 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py +++ b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py @@ -95,6 +95,8 @@ def transfer_vm_to_host(session, prot, ip_ver, vm_iface, firewalld, LOG.debug(f'MD5 of sent file: {md5}') host_session = aexpect.ShellSession('su') host_session.sendline(cmd_listen) + # Wait 2 seconds for the host listen cmd to be prepared + time.sleep(2) session.cmd(cmd_transfer) host_session.close() if not os.path.exists(rec_file): From 47e0557c1ffe8a11e1278d57a0d77622f640f634 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 5 Feb 2025 17:38:19 +0800 Subject: [PATCH 0829/1055] guest_os_booting: Enable serial logs Update to log serial message during the test. Signed-off-by: Yingshun Cui --- .../boot_order/boot_from_virtiofs_device.cfg | 1 - .../boot_order/boot_from_virtiofs_device.py | 11 +++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_virtiofs_device.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_virtiofs_device.cfg index f4a03b87540..6c7c411fdc9 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_virtiofs_device.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_virtiofs_device.cfg @@ -1,7 +1,6 @@ - guest_os_booting.boot_order.virtiofs_device: type = boot_from_virtiofs_device start_vm = no - access_cmd = "virsh console %s" vm_memory = 15728640 no s390-virtio variants: diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_virtiofs_device.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_virtiofs_device.py index 5138d51e0ca..91fe6082638 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_virtiofs_device.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_virtiofs_device.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: GPL-2.0 # Author: Meina Li -import aexpect import os import re import shutil @@ -69,7 +68,6 @@ def change_virtiofs_root_passwd(): initrams_file = os.path.join(BOOT_PATH, "initramfs-virtiofs.img") vmlinuz_file = os.path.join(BOOT_PATH, "vmlinuz-virtiofs.img") boot_img = os.path.join(data_dir.get_data_dir(), "test.img") - access_cmd = params.get("access_cmd") % vm_name guest_cmd = params.get("guest_cmd") target_dir = params.get("target_dir") vm_memory = int(params.get("vm_memory")) @@ -103,13 +101,10 @@ def change_virtiofs_root_passwd(): disk_dict.update({'source': {'attrs': {'file': boot_img}}}) libvirt_vmxml.modify_vm_device(vmxml, 'disk', disk_dict) if not vm.is_alive(): - virsh.start(vm_name, debug=True, ignore_status=False) - + vm.start() test.log.info("STEP3: Login the guest") - access_session = aexpect.ShellSession(access_cmd) - libvirt.virsh_console_login(access_session, username, passwd, - debug=True, timeout=120) - result = access_session.cmd_output(guest_cmd) + vm_session = vm.wait_for_serial_login() + result = vm_session.cmd_output(guest_cmd) test.log.debug("Send cmd: '%s' in console", guest_cmd) if not re.search(target_dir, result): test.fail(f"Expect {target_dir} in {result}, but not found") From da15c2c69857ae6f69e50e398a4c4419fc2294d4 Mon Sep 17 00:00:00 2001 From: Kowshik Jois B S Date: Tue, 11 Feb 2025 17:05:54 +0530 Subject: [PATCH 0830/1055] sosreport: 2 new tests added Description: Adding 2 new test cases for testing the below scenarios. 1. Running sosreport causes the system to crash and produce a dump on Ubuntu 24.04 Referrence Bug: https://bugs.launchpad.net/ubuntu/+source/sosreport/+bug/2068577 2. Kernel OOPS crash while trying to get data from sysfs file: /proc/fs/nfsd/pool_stats Referrence Bug: https://bugs.launchpad.net/ubuntu/+source/sosreport/+bug/2070358 Both above scenarios have got patches merged in the main line kernel. Tests added will catch these scenarios if occurs again anytime in future. Signed-off-by: Kowshik Jois B S --- .../cfg/virsh_cmd/domain/virsh_sosreport.cfg | 10 ++ .../src/virsh_cmd/domain/virsh_sosreport.py | 138 ++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 libvirt/tests/cfg/virsh_cmd/domain/virsh_sosreport.cfg create mode 100644 libvirt/tests/src/virsh_cmd/domain/virsh_sosreport.py diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_sosreport.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_sosreport.cfg new file mode 100644 index 00000000000..5b4bc441f1a --- /dev/null +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_sosreport.cfg @@ -0,0 +1,10 @@ +- io-github-autotest-libvirt.virsh.sosreport: + virt_test_type = libvirt + provider = io-github-autotest-libvirt + type = virsh_sosreport + take_regular_screendumps = "no" + variants: + - generate_sos_report: + generate_sos_report = "yes" + - access_pool_stats: + access_pool_stats = "yes" diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_sosreport.py b/libvirt/tests/src/virsh_cmd/domain/virsh_sosreport.py new file mode 100644 index 00000000000..7bf2e297d97 --- /dev/null +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_sosreport.py @@ -0,0 +1,138 @@ +import logging +import os +import shutil +import subprocess + +from pathlib import Path + + +def run(test, params, env): + + generate_sos_report = params.get("generate_sos_report", "no") == "yes" + access_pool_stats = params.get("access_pool_stats", "no") == "yes" + + # Configuration + LOG_PATTERNS = [ + r"nfsd.*NULL pointer dereference", + r"kernel: BUG:.*nfsd", + r"kernel: WARNING:.*nfsd", + r"pool_stats.*crash", + r"kernel: general protection fault.*nfsd" + ] + proc_file = "/proc/fs/nfsd/pool_stats" + log_sources = ["/var/log/kern.log", "/var/log/syslog", + "journalctl -k --since='1 hour ago'"] + + def check_user_status(): + + # check if user has permissions to run the command + logging.debug("Check for the user privileges") + if os.geteuid() != 0: + test.fail("'sosreport' must be run with root privileges") + + def scan_logs(): + + issues = [] + for source in log_sources: + try: + if source.startswith("journalctl"): + logs = subprocess.check_output(source.split(), universal_newlines=True) + else: + with open(source, 'r') as f: + logs = f.read() + + for pattern in LOG_PATTERNS: + if re.search(pattern, logs, re.IGNORECASE): + issues.append(f"Found in {source}: {pattern}") + + except Exception as e: + continue + return issues + + if generate_sos_report: + # check if the command available + logging.debug("Check if 'sosreport' is installed") + if not shutil.which('sosreport'): + test.fail("sosreport command not found. \ + Is the sos package installed?") + + check_user_status() + + report_path = None + + try: + # Run command in non-interactive mode + logging.debug("Starting sosreport collection...") + result = subprocess.run( + ['sosreport', '--batch'], + capture_output=True, + universal_newlines=True, check=True) + + # Parse output for getting the report path + for line in result.stdout.split('\n'): + if 'tar.xz' in line: + report_path = line.split()[-1] + break + + logging.debug("* * * REPORT GENERATED * * *") + + except Exception as err: + test.fail(err) + + # check for any trace messages after report generation + dmesg = subprocess.run(['dmesg'], + capture_output=True, + universal_newlines=True, check=True) + + log_issues = scan_logs() + if log_issues: + logging.debug("Found potential crash indicators in logs") + for issue in log_issues: + logging.debug(" - %s" % issue) + test.fail("potential crash indicators found in logs") + else: + logging.debug("Your sos report file has been generated" + "and saved in : %s" % report_path) + + if access_pool_stats: + + check_user_status() + + # Check for the file existence + try: + lsmod = subprocess.check_output(["lsmod"], universal_newlines=True) + if "nfsd" not in lsmod: + test.fail("nfsd module not loaded") + + proc_mount = Path(proc_file) + if not proc_mount.exists(): + test.fail("%s file not present" % proc_file) + + logging.debug("NFSD appears healthy") + + except Exception as e: + logging.debug(str(e)) + + # check for crash indicators before accessing the file + log_issues = scan_logs() + if log_issues: + logging.debug("Found potential crash indicators in logs") + for issue in log_issues: + logging.debug(" - %s" % issue) + + # Attempt to safely read the target file + try: + with open(proc_file, 'r') as f: + f.read(500) + logging.debug("File read successfully") + except Exception as e: + test.fail("File access failed: %s" % str(e)) + + # check for crash indicators after accessing the file + log_issues = scan_logs() + if log_issues: + logging.debug("Found potential crash indicators in logs") + for issue in log_issues: + logging.debug(" - %s" % issue) + + test.fail("potential crash indicators found in logs") From dd49492512480efce15d4edc5380a632fe492380 Mon Sep 17 00:00:00 2001 From: Julia Graham Date: Mon, 10 Feb 2025 12:34:54 -0500 Subject: [PATCH 0831/1055] migration_iommu_device: using migrate_vm_back option Use migrate_vm_back option in avocado-vt/share/cfg/base.cfg to determine whether to migrate the vm back to the source host. Signed-off-by: jugraham --- libvirt/tests/src/sriov/vIOMMU/migration_iommu_device.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/src/sriov/vIOMMU/migration_iommu_device.py b/libvirt/tests/src/sriov/vIOMMU/migration_iommu_device.py index d58ad868d88..eacf4c17dc2 100644 --- a/libvirt/tests/src/sriov/vIOMMU/migration_iommu_device.py +++ b/libvirt/tests/src/sriov/vIOMMU/migration_iommu_device.py @@ -80,8 +80,10 @@ def setup_test(): migration_obj.verify_default() check_iommu_xml(vm, params) - test.log.info("TEST_STEP: Migrate back the VM to the source host.") - migration_obj.run_migration_back() - migration_obj.migration_test.ping_vm(vm, params) + migrate_vm_back = "yes" == params.get("migrate_vm_back", "yes") + if migrate_vm_back: + test.log.info("TEST_STEP: Migrate back the VM to the source host.") + migration_obj.run_migration_back() + migration_obj.migration_test.ping_vm(vm, params) finally: test_obj.teardown_iommu_test() From 03bc86c6ba85b6fe1970fd693399e98f070bdf02 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Wed, 12 Feb 2025 03:15:45 -0500 Subject: [PATCH 0832/1055] Fix two v2v failures of function test esx job Signed-off-by: Ming Xie --- v2v/tests/cfg/function_test_esx.cfg | 2 +- v2v/tests/src/function_test_esx.py | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 2da63f83267..71e125fefa1 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -182,6 +182,7 @@ os_version = "win2019" - mac_ip: only libvirt + checkpoint = 'mac_ip' variants: - 3_mac: only esx_80 @@ -205,7 +206,6 @@ v2v_opts = VM_NAME_WIN_0_GW_IP_MAC_CONF_V2V_EXAMPLE - 1_static: only esx_80 - checkpoint = 'mac_ip' variants: - win2019: main_vm = VM_NAME_ESX80_WIN2019_V2V_EXAMPLE diff --git a/v2v/tests/src/function_test_esx.py b/v2v/tests/src/function_test_esx.py index 30a9db45de9..8eada8c31da 100644 --- a/v2v/tests/src/function_test_esx.py +++ b/v2v/tests/src/function_test_esx.py @@ -235,8 +235,10 @@ def check_windows_vmware_tools(vmcheck): """ def _get_vmtools_info(cmd): _, res = vmcheck.run_cmd(cmd) - exit_code = re.search(r'uninstalling VMware Tools\s+.*exit code\s+(\d+)', res).group(1) - return int(exit_code) + vmtools_info = re.search(r'uninstalling VMware Tools\s+.*exit code\s+(\d+)', res) + if vmtools_info: + exit_code = vmtools_info.group(1) + return int(exit_code) cmd = r'type "C:\Program Files\Guestfs\Firstboot\log.txt"' @@ -946,6 +948,7 @@ def vm_check(status_error): params['msg_content_yes'] += '' + res_cpu_topology.get('sockets') + '%' params['msg_content_yes'] += '' + res_cpu_topology.get('cores') + '%' params['msg_content_yes'] += '' + res_cpu_topology.get('threads') + v2v_result = utils_v2v.v2v_cmd(v2v_params) else: if 'exist_uuid' in checkpoint: auto_clean = False From b1573a6b9695d6f90dcbf3328f2dd2d7db595ebf Mon Sep 17 00:00:00 2001 From: Super User Date: Wed, 12 Feb 2025 22:00:07 -0500 Subject: [PATCH 0833/1055] iface_update:Fix error when trying to get net interface Signed-off-by: Haijiao Zhao --- libvirt/tests/src/virtual_network/iface_update.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_network/iface_update.py b/libvirt/tests/src/virtual_network/iface_update.py index bea0475bc88..22123a3356f 100644 --- a/libvirt/tests/src/virtual_network/iface_update.py +++ b/libvirt/tests/src/virtual_network/iface_update.py @@ -314,7 +314,9 @@ def check_mtu(): state_map = "%s.*\n.*%s" % (iface_link_value.upper(), mac_addr) session = vm.wait_for_serial_login() logging.info("ip link output:%s", session.cmd_output("ip link")) - if_name = utils_net.get_net_if(runner=session.cmd_output, state=state_map)[0] + if_name = utils_net.get_net_if( + runner=session.cmd_output, state=state_map, + ip_options='--color=never')[0] if not check_iface_link(session, mac_addr, new_iface_link): test.fail('iface link check inside vm failed.') session.close() From 635c18173b483e5eddd6dc85a6eddb8d18cfa4c6 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Thu, 13 Feb 2025 04:30:13 -0500 Subject: [PATCH 0834/1055] Change audit log cmd to get rid of the time impact Signed-off-by: liang-cong-red-hat --- .../tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg index ac22b4bd5f2..bcbc03fd04e 100644 --- a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg @@ -14,7 +14,7 @@ max_mem = 4194304 max_mem_slots = 16 slot = '0' - audit_cmd = "ausearch --start today -m VIRT_RESOURCE | grep 'mem'" + audit_cmd = "ausearch -m VIRT_RESOURCE | grep 'mem' | tail -n 30" ausearch_check = 'old-mem=%d new-mem=%d' expected_log = "ACPI_DEVICE_OST|device_del" kernel_hp_file = '/sys/devices/system/node/node0/hugepages/hugepages-%skB/nr_hugepages' From 4571c60ddeea8892586cf05db3538fc7e1b78bce Mon Sep 17 00:00:00 2001 From: Julia Graham Date: Thu, 13 Feb 2025 10:43:49 -0500 Subject: [PATCH 0835/1055] direct_kernel_boot: increase wait time for booting. Increase timeout waiting for vm to boot since dracut-initqueue can occasionally take a long time to finish. Signed-off-by: Julia Graham --- .../guest_os_booting/direct_kernel_boot/direct_kernel_boot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/guest_os_booting/direct_kernel_boot/direct_kernel_boot.py b/libvirt/tests/src/guest_os_booting/direct_kernel_boot/direct_kernel_boot.py index 90124677cd2..a3714d185b6 100644 --- a/libvirt/tests/src/guest_os_booting/direct_kernel_boot/direct_kernel_boot.py +++ b/libvirt/tests/src/guest_os_booting/direct_kernel_boot/direct_kernel_boot.py @@ -48,7 +48,7 @@ def run(test, params, env): test.log.debug("The final guest xml is %s", vmxml) if not vm.is_alive(): vm.start() - vm.serial_console.read_until_any_line_matches([check_prompt], timeout=360) + vm.serial_console.read_until_any_line_matches([check_prompt], timeout=600) finally: bkxml.sync() for file_path in [boot_initrd, boot_vmlinuz]: From e65a0b975843112d97cfae9ceac7c98a82c5fb74 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Tue, 18 Feb 2025 02:51:11 -0500 Subject: [PATCH 0836/1055] Replace virsh.VirshPersistent with virsh.Virsh to avoid error The old cold uses virsh.VirshPersistent which requires active aexpect session which is unnecessary for these tests and might cause timeout error of unknown reason occasionally. Replace them with virsh.Virsh could avoid the errors. Signed-off-by: Haijiao Zhao --- .../attach_detach_device/attach_user_type_iface.py | 2 +- .../connectivity/connectivity_check_ethernet_interface.py | 4 +--- .../connectivity/connectivity_check_user_interface.py | 4 +--- .../tests/src/virtual_network/passt/passt_attach_detach.py | 4 +--- .../virtual_network/passt/passt_connectivity_between_2vms.py | 4 +--- libvirt/tests/src/virtual_network/passt/passt_function.py | 4 +--- libvirt/tests/src/virtual_network/passt/passt_lifecycle.py | 4 +--- .../tests/src/virtual_network/passt/passt_negative_setting.py | 4 +--- libvirt/tests/src/virtual_network/passt/passt_reconnect.py | 4 +--- .../tests/src/virtual_network/passt/passt_transfer_file.py | 4 +--- 10 files changed, 10 insertions(+), 28 deletions(-) diff --git a/libvirt/tests/src/virtual_network/attach_detach_device/attach_user_type_iface.py b/libvirt/tests/src/virtual_network/attach_detach_device/attach_user_type_iface.py index 8ad797654af..82199c7f6d5 100644 --- a/libvirt/tests/src/virtual_network/attach_detach_device/attach_user_type_iface.py +++ b/libvirt/tests/src/virtual_network/attach_detach_device/attach_user_type_iface.py @@ -36,7 +36,7 @@ def run(test, params, env): test_passwd, **unpr_vm_args) uri = f'qemu+ssh://{test_user}@localhost/session' - virsh_ins = virsh.VirshPersistent(uri=uri) + virsh_ins = virsh.Virsh(uri=uri) host_session = aexpect.ShellSession('su') remote.VMManager.set_ssh_auth(host_session, 'localhost', test_user, test_passwd) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py index ebb25644371..b0e537dbb08 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py @@ -41,7 +41,7 @@ def run(test, params, env): test_passwd, **unpr_vm_args) uri = f'qemu+ssh://{test_user}@localhost/session' - virsh_ins = virsh.VirshPersistent(uri=uri) + virsh_ins = virsh.Virsh(uri=uri) host_session = aexpect.ShellSession('su') remote.VMManager.set_ssh_auth(host_session, 'localhost', test_user, test_passwd) @@ -200,5 +200,3 @@ def run(test, params, env): if tap_type == 'tap': utils_net.delete_linux_bridge_tmux(bridge_name, host_iface) bkxml.sync(virsh_instance=virsh_ins) - if not root: - virsh_ins.close_session() diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py index a62d1e09d12..c7ef6e62834 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py @@ -65,7 +65,7 @@ def run(test, params, env): vm = libvirt_unprivileged.get_unprivileged_vm(vm_name, test_user, test_passwd, **unpr_vm_args) - virsh_ins = virsh.VirshPersistent(uri=virsh_uri) + virsh_ins = virsh.Virsh(uri=virsh_uri) host_session = aexpect.ShellSession('su') remote.VMManager.set_ssh_auth(host_session, 'localhost', test_user, test_passwd) @@ -144,5 +144,3 @@ def run(test, params, env): vm.destroy() finally: bkxml.sync(virsh_instance=virsh_ins) - if not root: - del virsh_ins diff --git a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py index ba4f5805421..29c104bfc2c 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py +++ b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py @@ -57,7 +57,7 @@ def run(test, params, env): test_passwd, **unpr_vm_args) uri = f'qemu+ssh://{test_user}@localhost/session' - virsh_ins = virsh.VirshPersistent(uri=uri) + virsh_ins = virsh.Virsh(uri=uri) host_session = aexpect.ShellSession('su') remote.VMManager.set_ssh_auth(host_session, 'localhost', test_user, test_passwd) @@ -182,6 +182,4 @@ def run(test, params, env): bkxml.sync(virsh_instance=virsh_ins) if root: shutil.rmtree(log_dir) - else: - del virsh_ins utils_selinux.set_status(selinux_status) diff --git a/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py b/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py index eca15eff4f0..bf21768d866 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py +++ b/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py @@ -52,7 +52,7 @@ def run(test, params, env): test_passwd, **unpr_vm_args) uri = f'qemu+ssh://{test_user}@localhost/session' - virsh_ins = virsh.VirshPersistent(uri=uri) + virsh_ins = virsh.Virsh(uri=uri) host_session = aexpect.ShellSession('su') remote.VMManager.set_ssh_auth(host_session, 'localhost', test_user, test_passwd) @@ -132,6 +132,4 @@ def run(test, params, env): bkxml_c.sync(virsh_instance=virsh_ins) if root: shutil.rmtree(log_dir) - else: - del virsh_ins utils_selinux.set_status(selinux_status) diff --git a/libvirt/tests/src/virtual_network/passt/passt_function.py b/libvirt/tests/src/virtual_network/passt/passt_function.py index b8a201f53e5..835658c0a79 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_function.py +++ b/libvirt/tests/src/virtual_network/passt/passt_function.py @@ -46,7 +46,7 @@ def run(test, params, env): test_passwd, **unpr_vm_args) uri = f'qemu+ssh://{test_user}@localhost/session' - virsh_ins = virsh.VirshPersistent(uri=uri) + virsh_ins = virsh.Virsh(uri=uri) host_session = aexpect.ShellSession('su') remote.VMManager.set_ssh_auth(host_session, 'localhost', test_user, test_passwd) @@ -131,6 +131,4 @@ def run(test, params, env): bkxml.sync(virsh_instance=virsh_ins) if root: shutil.rmtree(log_dir) - else: - del virsh_ins utils_selinux.set_status(selinux_status) diff --git a/libvirt/tests/src/virtual_network/passt/passt_lifecycle.py b/libvirt/tests/src/virtual_network/passt/passt_lifecycle.py index be846bdb412..4a86e356caf 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_lifecycle.py +++ b/libvirt/tests/src/virtual_network/passt/passt_lifecycle.py @@ -48,7 +48,7 @@ def run(test, params, env): test_passwd, **unpr_vm_args) uri = f'qemu+ssh://{test_user}@localhost/session' - virsh_ins = virsh.VirshPersistent(uri=uri) + virsh_ins = virsh.Virsh(uri=uri) host_session = aexpect.ShellSession('su') remote.VMManager.set_ssh_auth(host_session, 'localhost', test_user, test_passwd) @@ -156,8 +156,6 @@ def run(test, params, env): bkxml.sync(virsh_instance=virsh_ins) if root: shutil.rmtree(log_dir) - else: - del virsh_ins utils_selinux.set_status(selinux_status) if os.path.exists(save_path): os.remove(save_path) diff --git a/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py b/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py index cf97ffa54f3..d4b74bf98a4 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py +++ b/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py @@ -43,7 +43,7 @@ def run(test, params, env): remote.VMManager.set_ssh_auth(host_session, 'localhost', test_user, test_passwd) host_session.close() - virsh_ins = virsh.VirshPersistent(uri=virsh_uri) + virsh_ins = virsh.Virsh(uri=virsh_uri) scenario = params.get('scenario') operation = params.get('operation') @@ -143,8 +143,6 @@ def _get_test_ip(): bkxml.sync(virsh_instance=virsh_ins) if root: shutil.rmtree(log_dir) - else: - del virsh_ins utils_selinux.set_status(selinux_status) process.run(f'ip link del {DOWN_IFACE_NAME}', shell=True, ignore_status=True) diff --git a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py index 3f3456b3251..9cd10955f64 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py +++ b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py @@ -50,7 +50,7 @@ def run(test, params, env): test_passwd, **unpr_vm_args) uri = f'qemu+ssh://{test_user}@localhost/session' - virsh_ins = virsh.VirshPersistent(uri=uri) + virsh_ins = virsh.Virsh(uri=uri) host_session = aexpect.ShellSession('su') remote.VMManager.set_ssh_auth(host_session, 'localhost', test_user, test_passwd) @@ -141,6 +141,4 @@ def run(test, params, env): bkxml.sync(virsh_instance=virsh_ins) if root: shutil.rmtree(log_dir) - else: - del virsh_ins utils_selinux.set_status(selinux_status) diff --git a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py index 1d95b71bbbe..7e79883b48e 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py +++ b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py @@ -143,7 +143,7 @@ def run(test, params, env): test_passwd, **unpr_vm_args) uri = f'qemu+ssh://{test_user}@localhost/session' - virsh_ins = virsh.VirshPersistent(uri=uri) + virsh_ins = virsh.Virsh(uri=uri) host_session = aexpect.ShellSession('su') remote.VMManager.set_ssh_auth(host_session, 'localhost', test_user, test_passwd) @@ -193,6 +193,4 @@ def run(test, params, env): bkxml.sync(virsh_instance=virsh_ins) if root: shutil.rmtree(log_dir) - else: - del virsh_ins utils_selinux.set_status(selinux_status) From eefe3332d72d86330683232a84256eac0f2d8285 Mon Sep 17 00:00:00 2001 From: lcheng Date: Tue, 18 Feb 2025 23:46:04 +0800 Subject: [PATCH 0837/1055] migration: Add -color=never option Signed-off-by: lcheng --- libvirt/tests/src/migration/migrate_network.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libvirt/tests/src/migration/migrate_network.py b/libvirt/tests/src/migration/migrate_network.py index 6c8f8aff778..dac8d088b0b 100644 --- a/libvirt/tests/src/migration/migrate_network.py +++ b/libvirt/tests/src/migration/migrate_network.py @@ -15,6 +15,7 @@ from virttest.utils_libvirt import libvirt_network from virttest.libvirt_xml.devices import interface +from provider.virtual_network import network_base # Using as lower capital is not the best way to do, but this is just a # workaround to avoid changing the entire file. @@ -104,7 +105,7 @@ def update_net_dict(net_dict, iface_name, runner=utils_net.local_runner): if net_dict.get("name", "") == "direct-macvtap": logging.info("Updating network iface name") if not iface_name: - iface_name = utils_net.get_net_if(runner=runner, state="UP")[0] + iface_name = utils_net.get_net_if(runner=runner, state="UP", ip_options='-color=never')[0] net_dict.update({'forward_interface': [{'dev': iface_name}]}) else: # TODO: support other types @@ -251,12 +252,12 @@ def create_fake_tap(remote_session): logging.debug("target xml is %s" % target_org_xml) if ovs_bridge_name: - status, stdout = utils_net.create_ovs_bridge(ovs_bridge_name) + status, stdout = utils_net.create_ovs_bridge(ovs_bridge_name, ip_options='-color=never') if status: test.fail("Failed to create ovs bridge on local. Status: %s" "Stdout: %s" % (status, stdout)) status, stdout = utils_net.create_ovs_bridge( - ovs_bridge_name, session=remote_session) + ovs_bridge_name, session=remote_session, ip_options='-color=never') if status: test.fail("Failed to create ovs bridge on remote. Status: %s" "Stdout: %s" % (status, stdout)) @@ -319,7 +320,7 @@ def create_fake_tap(remote_session): if not utils_package.package_install('dhcp-client', session=vm_session): test.error("Failed to install dhcp-client on guest.") utils_net.restart_guest_network(vm_session) - vm_ip = utils_net.get_guest_ip_addr(vm_session, mac) + vm_ip = network_base.get_vm_ip(vm_session, mac) logging.debug("VM IP Addr: %s", vm_ip) if direct_mode: @@ -426,8 +427,8 @@ def create_fake_tap(remote_session): network_dict, is_del=True, remote_args=remote_virsh_dargs) libvirt_network.create_or_del_network(network_dict, is_del=True) if ovs_bridge_name: - utils_net.delete_ovs_bridge(ovs_bridge_name) - utils_net.delete_ovs_bridge(ovs_bridge_name, session=remote_session) + utils_net.delete_ovs_bridge(ovs_bridge_name, ip_options='-color=never') + utils_net.delete_ovs_bridge(ovs_bridge_name, session=remote_session, ip_options='-color=never') remote_session.close() if target_vm_session: From e2e681d2db713618b1e6168c1cb85b6d2b236640 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Tue, 18 Feb 2025 12:35:54 -0500 Subject: [PATCH 0838/1055] Change guests for windows static IP cases Signed-off-by: Ming Xie --- v2v/tests/cfg/function_test_esx.cfg | 49 ++++++++++++++--------------- v2v/tests/cfg/specific_kvm.cfg | 10 ++---- v2v/tests/src/function_test_esx.py | 4 +++ v2v/tests/src/specific_kvm.py | 2 +- 4 files changed, 30 insertions(+), 35 deletions(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 71e125fefa1..e693d2c2429 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -184,37 +184,33 @@ only libvirt checkpoint = 'mac_ip' variants: - - 3_mac: + - 3_static_ip: only esx_80 - boottype = 3 variants: - - win2016: - main_vm = VM_NAME_WIN2016_EFI_V2V_EXAMPLE - v2v_opts = VM_NAME_WIN_3_DHCP_IP_MAC_CONF_V2V_EXAMPLE - - win2022: - main_vm = VM_NAME_WIN2022_EFI_V2V_EXAMPLE - v2v_opts = VM_NAME_WIN_3_DHCP_IP_MAC_CONF_V2V_EXAMPLE - - 0_gw: + - win10: + main_vm = VM_NAME_WIN10_3_STATIC_IP_V2V_EXAMPLE + boottype = 3 + v2v_opts = VM_NAME_WIN10_3_STATIC_IP_MAC_CONF_V2V_EXAMPLE + - empty_gw: only esx_80 - boottype = 3 variants: - - win10: - main_vm = VM_NAME_WIN10_EFI_V2V_EXAMPLE - v2v_opts = VM_NAME_WIN_0_GW_IP_MAC_CONF_V2V_EXAMPLE - - win2025: - main_vm = VM_NAME_WIN2025_EFI_V2V_EXAMPLE - v2v_opts = VM_NAME_WIN_0_GW_IP_MAC_CONF_V2V_EXAMPLE - - 1_static: + - win11: + main_vm = VM_NAME_WIN11_ONLINE_DISKS_V2V_EXAMPLE + v2v_opts = VM_NAME_WIN11_EMPTY_GW_IP_MAC_CONF_V2V_EXAMPLE + - win2022: + main_vm = VM_NAME_WIN2022_ONLINE_DISKS_V2V_EXAMPLE + v2v_opts = VM_NAME_WIN2022_EMPTY_GW_IP_MAC_CONF_V2V_EXAMPLE + - 1_static_ip: only esx_80 variants: - win2019: - main_vm = VM_NAME_ESX80_WIN2019_V2V_EXAMPLE - v2v_opts = VM_NAME_WIN_1_STATIC_IP_MAC_CONF_V2V_EXAMPLE_1 - iface_macs = VM_MAC_ADDR_1_STATIC_IP_MAC_CONF_V2V_EXAMPLE_1 - - win2022: - main_vm = VM_NAME_ESX80_WIN2022_V2V_EXAMPLE - v2v_opts = VM_NAME_WIN_1_STATIC_IP_MAC_CONF_V2V_EXAMPLE_2 - iface_macs = VM_MAC_ADDR_1_STATIC_IP_MAC_CONF_V2V_EXAMPLE_2 + main_vm = VM_NAME_WIN2019_ONLINE_DISKS_V2V_EXAMPLE + boottype = 3 + v2v_opts = VM_NAME_WIN2019_1_STATIC_IP_MAC_CONF_V2V_EXAMPLE + - win2025: + main_vm = VM_NAME_WIN2025_ONLINE_DISKS_V2V_EXAMPLE + boottype = 3 + v2v_opts = VM_NAME_WIN2025_1_STATIC_IP_MAC_CONF_V2V_EXAMPLE - vmware_tools: only esx_80 only dest_libvirt @@ -411,6 +407,7 @@ main_vm = VM_NAME_DEVICE_PASSTHRU_V2V_EXAMPLE - empty_cdrom: only esx_80 + version_required = "[libvirt-10.8.0-1,)" boottype = 3 main_vm = VM_NAME_EMPTY_IDE_SATA_CDROM_V2V_EXAMPLE skip_vm_check = yes @@ -882,10 +879,10 @@ only esx_70 only negative_test only it_vddk - version_required = "[nbdkit-1.30.8-1,)" + version_required = "[virt-v2v-2.5.4-1,)" main_vm = VM_NAME_ESX70_RHEL8_V2V_EXAMPLE vddk_thumbprint = 'AA:2B:AD' - #bug RHEL-55742 was closed as NOTABUG + #bug RHEL-37682 was closed as NOTABUG msg_content_yes = "server reported: VDDK "Unknown error" can be caused by several problems" - non_admin_user: only esx_80 diff --git a/v2v/tests/cfg/specific_kvm.cfg b/v2v/tests/cfg/specific_kvm.cfg index 7a5649d349f..bf7cdfc4c09 100644 --- a/v2v/tests/cfg/specific_kvm.cfg +++ b/v2v/tests/cfg/specific_kvm.cfg @@ -86,14 +86,6 @@ vm_user = 'root' vm_pwd = GENERAL_GUEST_PASSWORD main_vm = "VM_MULTI_DISKS_V2V_EXAMPLE" - - windows: - os_type = 'windows' - checkpoint = 'multi_disks' - os_version = 'OS_VERSION_MULTI_DISK_WIN_V2V_EXAMPLE' - main_vm = 'VM_MULTI_DISK_WIN_V2V_EXAMPLE' - only source_esx.esx_70 - skip_vm_check = yes - skip_reason = "bz#RHEL-17685 on win2016 guest" - multi_kernel: only source_esx.esx_70 # this case requires '-v -x' @@ -285,12 +277,14 @@ skip_reason = "bz#RHEL-1718 on win11 guest" - partial_efi: only source_esx.esx_80 + version_required = "[virt-v2v-2.5.5-1.el9,)" boottype = 2 main_vm = 'VM_NAME_80_UBUNTU_PARTIAL_EFI_V2V_EXAMPLE' skip_vm_check = yes skip_reason = "Special configuration. No console available" - serial_port: only esx_80 + version_required = "[libvirt-10.5.0-4.el9,)" variants: - chars_telnet: only libvirt diff --git a/v2v/tests/src/function_test_esx.py b/v2v/tests/src/function_test_esx.py index 8eada8c31da..7f9ae4f6592 100644 --- a/v2v/tests/src/function_test_esx.py +++ b/v2v/tests/src/function_test_esx.py @@ -430,12 +430,14 @@ def _static_ip_check(): # IP address if i == 0: ip_addr = r'IPv4 Address.*?: %s' % value + LOG.info('static ip addr: %s', re.search(ip_addr, ipconfig, re.S)) if not re.search(ip_addr, ipconfig, re.S): LOG.debug('Found IP addr failed') return False # Default gateway if i == 1: ip_gw = r'Default Gateway.*?: .*?%s' % value + LOG.info('static gateway: %s', re.search(ip_gw, ipconfig, re.S)) if not re.search(ip_gw, ipconfig, re.S): LOG.debug('Found Gateway failed') return False @@ -446,12 +448,14 @@ def _static_ip_check(): cidr = '.'.join( [str(int(bin_mask[i * 8:i * 8 + 8], 2)) for i in range(4)]) sub_mask = r'Subnet Mask.*?: %s' % cidr + LOG.info('static subnet mask: %s', re.search(sub_mask, ipconfig, re.S)) if not re.search(sub_mask, ipconfig, re.S): LOG.debug('Found subnet mask failed') return False # DNS server list if i >= 3: dns_server = r'DNS Servers.*?:.*?%s' % value + LOG.info('static DNS: %s', re.search(dns_server, ipconfig, re.S)) if not re.search(dns_server, ipconfig, re.S): LOG.debug('Found DNS Server failed') return False diff --git a/v2v/tests/src/specific_kvm.py b/v2v/tests/src/specific_kvm.py index aed2f1bd8a4..9de36da468c 100644 --- a/v2v/tests/src/specific_kvm.py +++ b/v2v/tests/src/specific_kvm.py @@ -596,7 +596,7 @@ def check_result(result, status_error): if checkpoint == 'multi_kernel': check_boot_kernel(vmchecker.checker) check_vmlinuz_initramfs(output) - if checkpoint == 'multi_disks' and params.get('skip_vm_check') != 'yes': + if checkpoint == 'multi_disks': check_disks(vmchecker.checker) if checkpoint == 'multi_netcards': check_multi_netcards(params['mac_address'], From eb220ac8909d5b73d467bcb5685c8c6bdbc6942f Mon Sep 17 00:00:00 2001 From: lcheng Date: Sun, 23 Feb 2025 23:34:10 +0800 Subject: [PATCH 0839/1055] migration: Update error message Signed-off-by: lcheng --- .../migrate_vm_disk_on_shared_storage.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration_with_copy_storage/migrate_vm_disk_on_shared_storage.cfg b/libvirt/tests/cfg/migration_with_copy_storage/migrate_vm_disk_on_shared_storage.cfg index e65fc375da4..8487816a142 100644 --- a/libvirt/tests/cfg/migration_with_copy_storage/migrate_vm_disk_on_shared_storage.cfg +++ b/libvirt/tests/cfg/migration_with_copy_storage/migrate_vm_disk_on_shared_storage.cfg @@ -30,7 +30,7 @@ virsh_migrate_options = "--live --verbose" variants: - shared_storage: - err_msg = "unable to execute QEMU command 'block-export-add': Block node is read-only" + err_msg = "unable to execute QEMU command 'block-export-add'" variants: - copy_storage_all: copy_storage_option = "--copy-storage-all" From f273ee6e79f340bdd3b739df0b78178b4def1202 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Mon, 24 Feb 2025 01:58:23 -0500 Subject: [PATCH 0840/1055] Replace virsh.VirshPersistent to avoid timeout error Same as e65a0b9 Signed-off-by: Haijiao Zhao --- .../agent_auto_generated_unix_source_path_session_mode.py | 3 +-- .../src/virtual_device/filesystem_device_unprivileged.py | 4 +--- .../src/virtual_network/link_state/link_state_model_type.py | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/libvirt/tests/src/guest_agent/unix_source_path/agent_auto_generated_unix_source_path_session_mode.py b/libvirt/tests/src/guest_agent/unix_source_path/agent_auto_generated_unix_source_path_session_mode.py index 6296f485158..5f2890f4f01 100644 --- a/libvirt/tests/src/guest_agent/unix_source_path/agent_auto_generated_unix_source_path_session_mode.py +++ b/libvirt/tests/src/guest_agent/unix_source_path/agent_auto_generated_unix_source_path_session_mode.py @@ -60,7 +60,7 @@ def check_src_path(domid, vm_name, dir_name, chn_dir, tgt_name, vm = libvirt_unprivileged.get_unprivileged_vm(vm_name, test_user, test_passwd, **unpr_vm_args) - virsh_ins = virsh.VirshPersistent(uri=vm.connect_uri) + virsh_ins = virsh.Virsh(uri=vm.connect_uri) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=virsh_ins) backup_xml = vmxml.copy() @@ -108,4 +108,3 @@ def check_src_path(domid, vm_name, dir_name, chn_dir, tgt_name, vm_new.destroy() virsh_ins.domrename(vm_new.name, vm.name, debug=True) backup_xml.sync(virsh_instance=virsh_ins) - virsh_ins.close_session() diff --git a/libvirt/tests/src/virtual_device/filesystem_device_unprivileged.py b/libvirt/tests/src/virtual_device/filesystem_device_unprivileged.py index 33ee714ac3a..19044f8d3be 100644 --- a/libvirt/tests/src/virtual_device/filesystem_device_unprivileged.py +++ b/libvirt/tests/src/virtual_device/filesystem_device_unprivileged.py @@ -83,7 +83,7 @@ def _initialize_unpr_virsh(): global unpr_virsh unpr_uri = f"qemu+ssh://{test_user}@localhost/session" - unpr_virsh = virsh.VirshPersistent(uri=unpr_uri, safe=True) + unpr_virsh = virsh.Virsh(uri=unpr_uri, safe=True) host_session = ShellSession("su") remote.VMManager.set_ssh_auth(host_session, "localhost", test_user, test_passwd) @@ -393,8 +393,6 @@ def run(test, params, env): finally: for xml in backupxmls: xml.sync(virsh_instance=unpr_virsh) - if unpr_virsh: - del unpr_virsh for fs_dict in fs_dicts: source_dir = fs_dict["source"]["dir"] if os.path.exists(source_dir): diff --git a/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py b/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py index bcaa797f086..ddf51d1508e 100644 --- a/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py +++ b/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py @@ -50,7 +50,7 @@ def run(test, params, env): vm_name = params.get("unpr_vm_name") vm = libvirt_unprivileged.get_unprivileged_vm( vm_name, test_user, test_passwd, **unpr_vm_args) - virsh_ins = virsh.VirshPersistent(uri=vm.connect_uri) + virsh_ins = virsh.Virsh(uri=vm.connect_uri) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=virsh_ins) From 1491e964f8a59cd927fb56b640c2fa8c7e6b1aea Mon Sep 17 00:00:00 2001 From: Meina Li Date: Mon, 24 Feb 2025 02:02:22 -0500 Subject: [PATCH 0841/1055] Inc_backup: add datastore related test scenarios A new feature data file has been introduced with datastore element. It's important for incremental backup feature. So add this scenario to the scripts. Signed-off-by: Meina Li --- .../incremental_backup_backing_chain.cfg | 7 +++++++ .../incremental_backup_checkpoint_cmd.cfg | 7 +++++++ .../incremental_backup_event_monitor.cfg | 7 +++++++ .../incremental_backup_multidisk.cfg | 6 ++++++ .../incremental_backup_backing_chain.py | 13 ++++++++++++- .../incremental_backup_checkpoint_cmd.py | 13 ++++++++++++- .../incremental_backup_event_monitor.py | 13 ++++++++++++- .../incremental_backup_multidisk.py | 17 ++++++++++++++--- 8 files changed, 77 insertions(+), 6 deletions(-) diff --git a/libvirt/tests/cfg/incremental_backup/incremental_backup_backing_chain.cfg b/libvirt/tests/cfg/incremental_backup/incremental_backup_backing_chain.cfg index e8c5ba6f936..1db8b51b826 100644 --- a/libvirt/tests/cfg/incremental_backup/incremental_backup_backing_chain.cfg +++ b/libvirt/tests/cfg/incremental_backup/incremental_backup_backing_chain.cfg @@ -4,6 +4,13 @@ original_disk_size = "100M" backup_data_size = "1M" backup_rounds = 4 + variants: + - without_datastore: + - with_datastore: + only blockcommit.top_to_base,blockpull.mid_to_top,blockcopy.reuse_external + with_data_file = "yes" + func_supported_since_libvirt_ver = (10, 10, 0) + data_file_option = " -o data_file=%s" variants: - scratch_to_file: scratch_type = "file" diff --git a/libvirt/tests/cfg/incremental_backup/incremental_backup_checkpoint_cmd.cfg b/libvirt/tests/cfg/incremental_backup/incremental_backup_checkpoint_cmd.cfg index 70777d63982..863e5607b66 100644 --- a/libvirt/tests/cfg/incremental_backup/incremental_backup_checkpoint_cmd.cfg +++ b/libvirt/tests/cfg/incremental_backup/incremental_backup_checkpoint_cmd.cfg @@ -3,6 +3,13 @@ start_vm = "no" required_checkpoints = 1 status_error = "no" + variants: + - without_datastore: + - with_datastore: + only checkpoint-create + with_data_file = "yes" + func_supported_since_libvirt_ver = (10, 10, 0) + data_file_option = " -o data_file=%s" variants checkpoint_cmd: - checkpoint-create: variants: diff --git a/libvirt/tests/cfg/incremental_backup/incremental_backup_event_monitor.cfg b/libvirt/tests/cfg/incremental_backup/incremental_backup_event_monitor.cfg index 6409a4cf41a..45052b964d3 100644 --- a/libvirt/tests/cfg/incremental_backup/incremental_backup_event_monitor.cfg +++ b/libvirt/tests/cfg/incremental_backup/incremental_backup_event_monitor.cfg @@ -3,6 +3,13 @@ start_vm = "no" original_disk_size = "100M" backup_data_size = "1M" + variants: + - without_datastore: + - with_datastore: + only scratch_luks_encrypted + with_data_file = "yes" + func_supported_since_libvirt_ver = (10, 10, 0) + data_file_option = " -o data_file=%s" variants: - nbd_unix: nbd_protocol = "unix" diff --git a/libvirt/tests/cfg/incremental_backup/incremental_backup_multidisk.cfg b/libvirt/tests/cfg/incremental_backup/incremental_backup_multidisk.cfg index 7c378d0fda9..621754de92b 100644 --- a/libvirt/tests/cfg/incremental_backup/incremental_backup_multidisk.cfg +++ b/libvirt/tests/cfg/incremental_backup/incremental_backup_multidisk.cfg @@ -4,6 +4,12 @@ test_disk_size = "100M" backup_data_size = "1M" total_test_disk = 3 + variants: + - without_datastore: + - with_datastore: + with_data_file = "yes" + func_supported_since_libvirt_ver = (10, 10, 0) + data_file_option = " -o data_file=%s" variants: - custom_export_name: set_export_name = "yes" diff --git a/libvirt/tests/src/incremental_backup/incremental_backup_backing_chain.py b/libvirt/tests/src/incremental_backup/incremental_backup_backing_chain.py index 9e18cbe5c30..2ebd1f62cd8 100644 --- a/libvirt/tests/src/incremental_backup/incremental_backup_backing_chain.py +++ b/libvirt/tests/src/incremental_backup/incremental_backup_backing_chain.py @@ -192,6 +192,8 @@ def create_shutoff_snapshot(original_img, snapshot_img): blockcopy_reuse = params.get("blockcopy_reuse") backup_error = "yes" == params.get("backup_error") tmp_dir = data_dir.get_tmp_dir() + with_data_file = "yes" == params.get("with_data_file", "no") + libvirt_version.is_libvirt_feature_supported(params) try: vm_name = params.get("main_vm") @@ -217,8 +219,12 @@ def create_shutoff_snapshot(original_img, snapshot_img): if original_disk_type == "local": image_name = "%s_image.qcow2" % original_disk_target disk_path = os.path.join(tmp_dir, image_name) + data_file = os.path.join(tmp_dir, "datastore") + if with_data_file: + data_file_option = params.get("data_file_option", "") % data_file + extra_cmd = "" if not with_data_file else data_file_option libvirt.create_local_disk("file", disk_path, original_disk_size, - "qcow2") + "qcow2", extra=extra_cmd) disk_params = {"device_type": "disk", "type_name": "file", "driver_type": "qcow2", @@ -233,6 +239,11 @@ def create_shutoff_snapshot(original_img, snapshot_img): virsh.attach_device(vm.name, disk_xml, flagstr="--config", debug=True) vm.start() + guest_xml = virsh.dumpxml(vm_name).stdout_text + logging.debug("The current guest xml is:%s" % guest_xml) + if with_data_file: + if data_file not in guest_xml: + test.fail("The datastore file xml can't be generated automatically in guest!") session = vm.wait_for_login() new_disks_in_vm = list(utils_disk.get_linux_disks(session).keys()) session.close() diff --git a/libvirt/tests/src/incremental_backup/incremental_backup_checkpoint_cmd.py b/libvirt/tests/src/incremental_backup/incremental_backup_checkpoint_cmd.py index 837345c7aa8..e4f06517e35 100644 --- a/libvirt/tests/src/incremental_backup/incremental_backup_checkpoint_cmd.py +++ b/libvirt/tests/src/incremental_backup/incremental_backup_checkpoint_cmd.py @@ -55,6 +55,8 @@ def prepare_checkpoints(disk="vdb", num=1, cp_prefix="test_checkpoint_"): tmp_dir = data_dir.get_tmp_dir() current_checkpoints = [] virsh_dargs = {'debug': True, 'ignore_status': False} + with_data_file = "yes" == params.get("with_data_file", "no") + libvirt_version.is_libvirt_feature_supported(params) try: vm_name = params.get("main_vm") @@ -75,8 +77,12 @@ def prepare_checkpoints(disk="vdb", num=1, cp_prefix="test_checkpoint_"): disk_path = "" image_name = "{}_image.qcow2".format(test_disk_target) disk_path = os.path.join(tmp_dir, image_name) + data_file = os.path.join(tmp_dir, "datastore") + if with_data_file: + data_file_option = params.get("data_file_option", "") % data_file + extra_cmd = "" if not with_data_file else data_file_option libvirt.create_local_disk("file", disk_path, test_disk_size, - "qcow2") + "qcow2", extra=extra_cmd) disk_params = {"device_type": "disk", "type_name": "file", "driver_type": "qcow2", @@ -86,6 +92,11 @@ def prepare_checkpoints(disk="vdb", num=1, cp_prefix="test_checkpoint_"): virsh.attach_device(vm.name, disk_xml, flagstr="--config", **virsh_dargs) vm.start() + guest_xml = virsh.dumpxml(vm_name).stdout_text + logging.debug("The current guest xml is:%s" % guest_xml) + if with_data_file: + if data_file not in guest_xml: + test.fail("The datastore file xml can't be generated automatically in guest!") session = vm.wait_for_login() new_disks_in_vm = list(utils_disk.get_linux_disks(session).keys()) session.close() diff --git a/libvirt/tests/src/incremental_backup/incremental_backup_event_monitor.py b/libvirt/tests/src/incremental_backup/incremental_backup_event_monitor.py index 95aa815e82e..28fc4a7a235 100644 --- a/libvirt/tests/src/incremental_backup/incremental_backup_event_monitor.py +++ b/libvirt/tests/src/incremental_backup/incremental_backup_event_monitor.py @@ -42,6 +42,8 @@ def run(test, params, env): usage_threshold = params.get("usage_threshold", "100") tmp_dir = data_dir.get_tmp_dir() local_hostname = params.get("loal_hostname", "localhost") + with_data_file = "yes" == params.get("with_data_file", "no") + libvirt_version.is_libvirt_feature_supported(params) # Backup config scratch_type = params.get("scratch_type", "file") reuse_scratch_file = "yes" == params.get("reuse_scratch_file") @@ -115,8 +117,12 @@ def is_event_captured(virsh_session, re_pattern): disk_path = "" image_name = "{}_image.qcow2".format(original_disk_target) disk_path = os.path.join(tmp_dir, image_name) + data_file = os.path.join(tmp_dir, "datastore") + if with_data_file: + data_file_option = params.get("data_file_option", "") % data_file + extra_cmd = "" if not with_data_file else data_file_option libvirt.create_local_disk("file", disk_path, original_disk_size, - "qcow2") + "qcow2", extra=extra_cmd) disk_params = {"device_type": "disk", "type_name": "file", "driver_type": "qcow2", @@ -127,6 +133,11 @@ def is_event_captured(virsh_session, re_pattern): virsh.attach_device(vm.name, disk_xml, flagstr="--config", debug=True) vm.start() + guest_xml = virsh.dumpxml(vm_name).stdout_text + logging.debug("The current guest xml is:%s" % guest_xml) + if with_data_file: + if data_file not in guest_xml: + test.fail("The datastore file xml can't be generated automatically in guest!") session = vm.wait_for_login() new_disks_in_vm = list(utils_disk.get_linux_disks(session).keys()) session.close() diff --git a/libvirt/tests/src/incremental_backup/incremental_backup_multidisk.py b/libvirt/tests/src/incremental_backup/incremental_backup_multidisk.py index 94c8642f1af..daf3bf3bbd6 100644 --- a/libvirt/tests/src/incremental_backup/incremental_backup_multidisk.py +++ b/libvirt/tests/src/incremental_backup/incremental_backup_multidisk.py @@ -49,6 +49,8 @@ def get_disks_need_backup(disk_dict): total_test_disk = int(params.get("total_test_disk", 3)) tmp_dir = data_dir.get_tmp_dir() backup_error = "yes" == params.get("backup_error") + with_data_file = "yes" == params.get("with_data_file", "no") + libvirt_version.is_libvirt_feature_supported(params) # Backup setting scratch_type = params.get("scratch_type", "file") @@ -108,9 +110,13 @@ def prepare_disk_img(test_disk): """ image_name = "{}_image.qcow2".format(test_disk) image_path = os.path.join(tmp_dir, image_name) + data_file = os.path.join(tmp_dir, test_disk) + if with_data_file: + data_file_option = params.get("data_file_option", "") % data_file + extra_cmd = "" if not with_data_file else data_file_option libvirt.create_local_disk("file", image_path, test_disk_size, - "qcow2") - return image_path + "qcow2", extra=extra_cmd) + return image_path, data_file def prepare_disk_xml(test_disk, image_path): """ @@ -209,7 +215,7 @@ def prepare_checkpoint_xml(backup_disks, all_vm_disks): enable_incremental_backup = True backup_params["backup_incremental"] = checkpoint_list[-1] # Prepare disk image - image_path = prepare_disk_img(test_disk) + image_path, data_file = prepare_disk_img(test_disk) # Prepare disk xml to be hotplugged test_disk_xml = prepare_disk_xml(test_disk, image_path) # Hotplug disk @@ -217,6 +223,11 @@ def prepare_checkpoint_xml(backup_disks, all_vm_disks): ignore_status=False) test_disk_dict[test_disk]['path'] = image_path test_disk_dict[test_disk]['is_attached'] = True + guest_xml = virsh.dumpxml(vm_name).stdout_text + logging.debug("The current guest xml is:%s" % guest_xml) + if with_data_file: + if data_file not in guest_xml: + test.fail("The datastore file xml can't be generated automatically in guest!") # Now we use attached disk as backup disks backup_disks = get_disks_need_backup(test_disk_dict) vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) From e27ec28efa0d8b51ae955fba35978f89492dadc1 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 19 Feb 2025 14:06:04 +0800 Subject: [PATCH 0842/1055] vIOMMU: Add tests for downstream ports This pr adds tests for pcie-downstream-port in below cases: VIRT-294579 - [vIOMMU] Start vm with iommu device VIRT-296710 - [vIOMMU] hotplug/unplug devices with iommu enabled Signed-off-by: Yingshun Cui --- .../hotplug_device_with_iommu_enabled.cfg | 15 +++ .../sriov/vIOMMU/iommu_device_settings.cfg | 16 +++ .../hotplug_device_with_iommu_enabled.py | 21 ++-- .../src/sriov/vIOMMU/iommu_device_settings.py | 18 +++- provider/viommu/viommu_base.py | 101 +++++++++++++++--- 5 files changed, 145 insertions(+), 26 deletions(-) diff --git a/libvirt/tests/cfg/sriov/vIOMMU/hotplug_device_with_iommu_enabled.cfg b/libvirt/tests/cfg/sriov/vIOMMU/hotplug_device_with_iommu_enabled.cfg index de76500888f..5705f62b3b0 100644 --- a/libvirt/tests/cfg/sriov/vIOMMU/hotplug_device_with_iommu_enabled.cfg +++ b/libvirt/tests/cfg/sriov/vIOMMU/hotplug_device_with_iommu_enabled.cfg @@ -57,3 +57,18 @@ disk_dict = {'target': {'dev': 'vdb', 'bus': 'virtio'}, 'device': 'disk', 'driver': ${disk_driver}} interface_driver = {'driver_attr': {'name': 'vhost', 'iommu': 'on', 'ats': 'on'}} iface_dict = {'type_name': 'network', 'model': 'virtio', 'driver': ${interface_driver}, 'source': {'network': 'default'}} + - pcie_downstream_port: + test_devices = ["Eth", "block"] + upstream_port = {'type': 'pci', 'model': 'pcie-switch-upstream-port', 'pre_controller': 'pcie-root-port'} + downstream_port1 = {'type': 'pci', 'model': 'pcie-switch-downstream-port', 'target': {'chassis': '20', 'port': 0x0}, 'pre_controller': 'pcie-switch-upstream-port'} + downstream_port2 = {'type': 'pci', 'model': 'pcie-switch-downstream-port', 'target': {'chassis': '21', 'port': 0x0}, 'pre_controller': 'pcie-switch-upstream-port'} + iface_dict = {'type_name': 'network', 'model': 'virtio', 'driver': {'driver_attr': {'name': 'vhost', 'iommu': 'on'}}, 'source': {'network': 'default'}} + disk_dict = {'target': {'dev': 'vdb', 'bus': 'virtio'}, 'device': 'disk', 'driver': ${disk_driver}} + variants: + - from_pcie_root_port: + root_port = {'type': 'pci', 'model': 'pcie-root-port', 'pre_controller': 'pcie-root'} + controller_dicts = [${root_port}, ${upstream_port}, ${upstream_port}, ${downstream_port1}, ${downstream_port2}] + - from_expander_bus: + downstream_port = {'type': 'pci', 'model': 'pcie-switch-downstream-port', 'pre_controller': 'pcie-switch-upstream-port'} + root_port = {'type': 'pci', 'model': 'pcie-root-port', 'pre_controller': 'pcie-expander-bus'} + controller_dicts = [{'type': 'pci', 'model': 'pcie-expander-bus', 'target': {'busNr': '250'}, 'pre_controller': 'pcie-root'}, ${root_port}, ${upstream_port}, ${upstream_port}, ${downstream_port}, ${downstream_port}] diff --git a/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg b/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg index 6fe7af24ded..6da40ca9f46 100644 --- a/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg +++ b/libvirt/tests/cfg/sriov/vIOMMU/iommu_device_settings.cfg @@ -67,3 +67,19 @@ controller_dicts = [{'type': 'pci', 'model': 'pcie-expander-bus', 'target': {'busNr': '252'}, 'pre_controller': 'pcie-root'}, ${root_port}, ${root_port}] iface_dict = {'source': {'network': 'default'}} disk_dict = {'target': {'dev': 'vda', 'bus': 'virtio'}, 'device': 'disk', 'driver': ${disk_driver}} + - pcie_downstream_port: + test_devices = ["Eth", "block"] + dev_in_same_iommu_group = ["XIO3130", *${test_devices}] + upstream_port = {'type': 'pci', 'model': 'pcie-switch-upstream-port', 'pre_controller': 'pcie-root-port'} + downstream_port1 = {'type': 'pci', 'model': 'pcie-switch-downstream-port', 'target': {'chassis': '20', 'port': 0x0}, 'pre_controller': 'pcie-switch-upstream-port'} + downstream_port2 = {'type': 'pci', 'model': 'pcie-switch-downstream-port', 'target': {'chassis': '21', 'port': 0x0}, 'pre_controller': 'pcie-switch-upstream-port'} + iface_dict = {'type_name': 'network', 'model': 'virtio', 'driver': {'driver_attr': {'name': 'vhost', 'iommu': 'on'}}, 'source': {'network': 'default'}} + disk_dict = {'target': {'dev': 'vdb', 'bus': 'virtio'}, 'device': 'disk', 'driver': ${disk_driver}} + variants: + - from_pcie_root_port: + root_port = {'type': 'pci', 'model': 'pcie-root-port', 'pre_controller': 'pcie-root'} + controller_dicts = [${root_port}, ${upstream_port}, ${upstream_port}, ${downstream_port1}, ${downstream_port2}] + - from_expander_bus: + downstream_port = {'type': 'pci', 'model': 'pcie-switch-downstream-port', 'pre_controller': 'pcie-switch-upstream-port'} + root_port = {'type': 'pci', 'model': 'pcie-root-port', 'pre_controller': 'pcie-expander-bus'} + controller_dicts = [{'type': 'pci', 'model': 'pcie-expander-bus', 'target': {'busNr': '250'}, 'pre_controller': 'pcie-root'}, ${root_port}, ${upstream_port}, ${upstream_port}, ${downstream_port}, ${downstream_port}] diff --git a/libvirt/tests/src/sriov/vIOMMU/hotplug_device_with_iommu_enabled.py b/libvirt/tests/src/sriov/vIOMMU/hotplug_device_with_iommu_enabled.py index 73491fbe171..12e821a688e 100644 --- a/libvirt/tests/src/sriov/vIOMMU/hotplug_device_with_iommu_enabled.py +++ b/libvirt/tests/src/sriov/vIOMMU/hotplug_device_with_iommu_enabled.py @@ -30,13 +30,16 @@ def detach_dev(device_type, dev_iommu_info, vm_session): dev_obj = vm_xml.VMXML.new_from_dumpxml(vm_name).get_devices(device_type)[-1] virsh.detach_device(vm_name, dev_obj.xml, wait_for_event=True, debug=True, ignore_status=False) - if dev_iommu_info: - res = vm_session.cmd_status_output('ifconfig') - test.log.debug(res) - s, o = vm_session.cmd_status_output("ls %s" % dev_iommu_info) - test.log.debug(f"{device_type} iommu check: {o}") - if not s: - test.fail("The %s should be removed from the iommu group" % device_type) + if not dev_iommu_info: + return + for dev_info in dev_iommu_info: + if dev_info: + res = vm_session.cmd_status_output('ifconfig') + test.log.debug(res) + s, o = vm_session.cmd_status_output("ls %s" % dev_info) + test.log.debug(f"{device_type} iommu check: {o}") + if not s: + test.fail("The %s should be removed from the iommu group" % device_type) cleanup_ifaces = params.get("cleanup_ifaces", "yes") disk_dict = eval(params.get('disk_dict', '{}')) @@ -65,7 +68,7 @@ def detach_dev(device_type, dev_iommu_info, vm_session): vm.create_serial_console() vm_session = vm.wait_for_serial_login( timeout=int(params.get('login_timeout'))) - + pre_devices = viommu_base.get_devices_pci(vm_session, test_devices) if disk_dict: test.log.info("TEST_STEP: Attach a disk device to VM.") disk_dict = test_obj.update_disk_addr(disk_dict) @@ -88,7 +91,7 @@ def detach_dev(device_type, dev_iommu_info, vm_session): test.log.info("TEST_STEP: Check dmesg message about iommu inside the vm.") vm_session.cmd("dmesg | grep -i 'Adding to iommu group'", timeout=300) - dev_iommu_groups = viommu_base.check_vm_iommu_group(vm_session, test_devices) + dev_iommu_groups = viommu_base.check_vm_iommu_group(vm_session, test_devices, pre_devices) test.log.debug(f"Device iommu groups info: {dev_iommu_groups}") if "block" in test_devices: diff --git a/libvirt/tests/src/sriov/vIOMMU/iommu_device_settings.py b/libvirt/tests/src/sriov/vIOMMU/iommu_device_settings.py index 207e5e00784..40a6fd30139 100644 --- a/libvirt/tests/src/sriov/vIOMMU/iommu_device_settings.py +++ b/libvirt/tests/src/sriov/vIOMMU/iommu_device_settings.py @@ -19,6 +19,7 @@ def run(test, params, env): ping_dest = params.get('ping_dest') iommu_dict = eval(params.get('iommu_dict', '{}')) test_devices = eval(params.get("test_devices", "[]")) + dev_in_same_iommu_group = eval(params.get("dev_in_same_iommu_group", "[]")) need_sriov = "yes" == params.get("need_sriov", "no") vm_name = params.get("main_vm", "avocado-vt-vm1") @@ -32,6 +33,13 @@ def run(test, params, env): try: test_obj.setup_iommu_test(iommu_dict=iommu_dict, cleanup_ifaces=cleanup_ifaces) test_obj.prepare_controller() + vm.start() + vm.cleanup_serial_console() + vm.create_serial_console() + vm_session = vm.wait_for_serial_login( + timeout=int(params.get('login_timeout'))) + pre_devices = viommu_base.get_devices_pci(vm_session, test_devices) + vm.destroy() for dev in ["disk", "video"]: dev_dict = eval(params.get('%s_dict' % dev, '{}')) @@ -56,15 +64,19 @@ def run(test, params, env): test.log.info("TEST_STEP: Start the VM.") vm.start() - vm.cleanup_serial_console() - vm.create_serial_console() vm_session = vm.wait_for_serial_login( timeout=int(params.get('login_timeout'))) test.log.debug(vm_xml.VMXML.new_from_dumpxml(vm.name)) test.log.info("TEST_STEP: Check dmesg message about iommu inside the vm.") vm_session.cmd("dmesg | grep -i 'Adding to iommu group'") - viommu_base.check_vm_iommu_group(vm_session, test_devices) + viommu_base.check_vm_iommu_group(vm_session, test_devices, pre_devices) + if dev_in_same_iommu_group: + devices_pci_info = viommu_base.get_devices_pci(vm_session, dev_in_same_iommu_group) + devices_pci = [x for y in devices_pci_info.values() for x in y] + dev_dir = str(viommu_base.get_iommu_dev_dir(vm_session, devices_pci[0])) + for dev in devices_pci: + vm_session.cmd(f"ls {dev_dir} |grep {dev}") test.log.info("TEST_STEP: Check if the VM disk and network are woring well.") utils_disk.dd_data_to_vm_disk(vm_session, "/mnt/test") diff --git a/provider/viommu/viommu_base.py b/provider/viommu/viommu_base.py index bc19a73137e..ccaafcedce8 100644 --- a/provider/viommu/viommu_base.py +++ b/provider/viommu/viommu_base.py @@ -1,4 +1,5 @@ import os +import logging from avocado.core import exceptions @@ -10,31 +11,88 @@ from virttest.utils_libvirt import libvirt_virtio from virttest.utils_libvirt import libvirt_pcicontr +LOG = logging.getLogger('avocado.' + __name__) -def check_vm_iommu_group(vm_session, test_devices): + +def get_devices_pci(vm_session, test_devices): """ - Check the devices with iommu enabled are located in a separate iommu group + Get the devices pci :param vm_session: VM session :param test_devices: test devices to check + :return: The test devices' pci """ result = {} for dev in test_devices: s, o = vm_session.cmd_status_output( "lspci | awk 'BEGIN{IGNORECASE=1} /%s/ {print $1}'" % dev) + LOG.debug(o) if s: exceptions.TestFail("Failed to get pci address!") + result.update({dev: o.strip().splitlines()}) + return result - cmd = ("find /sys/kernel/iommu_groups/ -type l | xargs ls -l | awk -F " - "'/' '/%s / {print(\"\",$2,$3,$4,$5,$6)}' OFS='/' " % o.splitlines()[0]) - s, o = vm_session.cmd_status_output(cmd) - if s: - exceptions.TestFail("Failed to find iommu group!") - device_dir = o.strip().splitlines()[-1] - s, dev_pci = vm_session.cmd_status_output("ls %s" % device_dir) - if s: - exceptions.TestFail("Failed to get the device in the iommu group!") - result.update({dev: os.path.join(device_dir, dev_pci.strip())}) + +def get_added_devices_pci(vm_session, test_devices, orig_devices=None): + """ + Get the newly added devices pci + + :param vm_session: VM session + :param test_devices: test devices to check + :param orig_devices: The original devices + :return: The pci of the added device + """ + result = {} + act_devices = get_devices_pci(vm_session, test_devices) + if not orig_devices: + return act_devices + for k, v in act_devices.items(): + added_dev = list(filter(lambda x: x not in orig_devices.get(k), v)) + LOG.debug(f"added dev: {added_dev}") + if not added_dev: + exceptions.TestFail("Failed to get the added devices' pci address!") + result[k] = added_dev + return result + + +def get_iommu_dev_dir(vm_session, pci_addr): + """ + Get iommu group's devices + + :param vm_session: VM session + :param pci_addr: Device pci address + :return: The directory of iommu group devices + """ + cmd = ("find /sys/kernel/iommu_groups/ -type l | xargs ls -l | awk -F " + "'/' '/%s / {print(\"\",$2,$3,$4,$5,$6)}' OFS='/' " % pci_addr) + s, o = vm_session.cmd_status_output(cmd) + LOG.debug(o) + if s: + exceptions.TestFail("Failed to find iommu group!") + return o.strip().splitlines()[-1] + + +def check_vm_iommu_group(vm_session, test_devices, orig_devices=None): + """ + Check the devices with iommu enabled are located in a separate iommu group + + :param vm_session: VM session + :param test_devices: test devices to check + :param orig_devices: The original devices + :return: The test devices' iommu group info + """ + act_devices = get_added_devices_pci(vm_session, test_devices, orig_devices) + result = {} + for dev in test_devices: + tmp_path = [] + for pci_addr in act_devices[dev]: + device_dir = get_iommu_dev_dir(vm_session, pci_addr) + s, dev_pci = vm_session.cmd_status_output("ls %s" % device_dir) + LOG.debug(f"dev pci: {dev_pci}") + if s: + exceptions.TestFail("Failed to get the device in the iommu group!") + tmp_path.append(os.path.join(device_dir, pci_addr)) + result.update({dev: tmp_path}) return result @@ -100,9 +158,24 @@ def prepare_controller(self): contr_slot = libvirt_pcicontr.get_free_pci_slot( vm_xml.VMXML.new_from_dumpxml(self.vm.name), controller_bus=pre_contr_bus) - if contr_dict.get("model") == "pcie-to-pci-bridge": + if contr_dict.get("model") in ["pcie-to-pci-bridge", "pcie-switch-upstream-port", "pcie-switch-downstream-port'"]: contr_slot = "0" contr_attrs.update({"slot": contr_slot}) + self.test.log.debug(contr_slot) + if contr_dict.get("model") in ["pcie-switch-upstream-port"]: + pci_devices = list(vm_xml.VMXML.new_from_dumpxml(self.vm.name).xmltreefile.find("devices")) + used_function = [] + for dev in pci_devices: + address = dev.find("address") + if address is not None and address.get("bus") == pre_contr_bus: + used_function.append(address.get("function")) + self.test.log.debug(contr_dict) + self.test.log.debug(f"Used function: {used_function}") + available_function = sorted(list(filter(lambda x: x not in used_function, ["%0#x" % d for d in range(8)]))) + self.test.log.debug(f"available_function: {available_function}") + contr_function = available_function[0] + contr_attrs.update({"function": contr_function}) + contr_dict.update({"address": {"attrs": contr_attrs}}) contr_dict.pop("pre_controller") libvirt_vmxml.modify_vm_device( @@ -139,7 +212,7 @@ def update_disk_addr(self, disk_dict): if disk_dict["target"]["bus"] == "scsi": disk_dict["address"]["attrs"].update({"type": "drive", "controller": dev_bus}) - if self.controller_dicts[-1]["model"] == "pcie-root-port": + if self.controller_dicts[-1]["model"] in ["pcie-root-port", "pcie-switch-downstream-port"]: self.controller_dicts.pop() return disk_dict From 4d6113d122ad8ca3d7315300ff50ddb8fa1431c0 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Mon, 24 Feb 2025 19:22:09 +0800 Subject: [PATCH 0843/1055] v2v: fix failed case for vmx+ssh connection of esx7.0 Signed-off-by: vwu-vera --- v2v/tests/cfg/v2v_options.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/v2v/tests/cfg/v2v_options.cfg b/v2v/tests/cfg/v2v_options.cfg index 7fb5cb87a78..e9c334e76b5 100644 --- a/v2v/tests/cfg/v2v_options.cfg +++ b/v2v/tests/cfg/v2v_options.cfg @@ -239,13 +239,13 @@ - vmx_ssh: only input_mode.none only output_mode.libvirt - esx_ip = ESX_70_HOSTNAME_V2V_EXAMPLE + esx_ip = ESX_80_HOSTNAME_V2V_EXAMPLE esx_host_user = "root" esx_host_passwd = RHV_NODE_PASSWORD checkpoint = vmx_ssh main_vm = VM_NAME_VMX_SSH_V2V_EXAMPLE output_format = qcow2 - vmx = ssh://root@${esx_ip}/vmfs/volumes/esx6.5-function/${main_vm}/${main_vm}.vmx + vmx = ssh://root@${esx_ip}/vmfs/volumes/esx8.0-matrix/${main_vm}/${main_vm}.vmx - qemu_session: only input_mode.libvirt.kvm.default only output_mode.libvirt From b2902aa127aeb870d01e658a387e682cf32f25eb Mon Sep 17 00:00:00 2001 From: lcheng Date: Sun, 3 Nov 2024 19:29:22 +0800 Subject: [PATCH 0844/1055] migration: Add case about destroying vm XXX-298200 - [VM migration][async ops][postcopy] destroy vm during FinishPhase of postcopy migration Signed-off-by: lcheng --- .../destroy_vm_during_finishphase.cfg | 55 ++++++++++++++++ .../destroy_vm_during_finishphase.py | 63 +++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 libvirt/tests/cfg/migration/async_ops/destroy_vm_during_finishphase.cfg create mode 100644 libvirt/tests/src/migration/async_ops/destroy_vm_during_finishphase.py diff --git a/libvirt/tests/cfg/migration/async_ops/destroy_vm_during_finishphase.cfg b/libvirt/tests/cfg/migration/async_ops/destroy_vm_during_finishphase.cfg new file mode 100644 index 00000000000..08c0d9474ff --- /dev/null +++ b/libvirt/tests/cfg/migration/async_ops/destroy_vm_during_finishphase.cfg @@ -0,0 +1,55 @@ +- migration.async_ops.destroy_vm_during_finishphase: + type = destroy_vm_during_finishphase + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + start_vm = "yes" + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + check_network_accessibility_after_mig = "yes" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + status_error = "yes" + migrate_again_status_error = "no" + virsh_migrate_extra = "--bandwidth 10 --postcopy-bandwidth 10" + virsh_migrate_extra_mig_again = " " + variants: + - p2p: + virsh_migrate_options = '--live --p2p --verbose' + - non_p2p: + virsh_migrate_options = '--live --verbose' + variants: + - with_postcopy: + postcopy_options = '--postcopy' + variants: + - destroy_dst_vm: + expected_event_src = ["Suspended Post-copy", "Suspended Post-copy Error"] + expected_event_target = ["lifecycle.*Stopped Destroyed"] + expected_dest_state = "nonexist" + expected_src_state = "paused" + err_msg = "domain is not running" + action_during_mig = '[{"func": "virsh.migrate_postcopy", "func_param": "'%s' % params.get('migrate_main_vm')", "need_sleep_time": "10"}, {"func": "check_vm_status_during_mig", "func_param": {"vm_name": "${main_vm}", "src_state":"paused", "src_reason": "post-copy"}, "need_sleep_time": "5"}, {"func": "virsh.destroy", "func_param": {"name": "${main_vm}", "uri": "${virsh_migrate_desturi}"}}]' + - destroy_src_vm: + expected_event_src = ["Suspended Post-copy Error", "Stopped Destroyed"] + expected_event_target = ["Resumed Post-copy Error"] + expected_dest_state = "running" + expected_src_state = "shut off" + err_msg = "job 'migration in' failed in post-copy phase" + action_during_mig = '[{"func": "virsh.migrate_postcopy", "func_param": "'%s' % params.get('migrate_main_vm')", "need_sleep_time": "10"}, {"func": "check_vm_status_during_mig", "func_param": {"vm_name": "${main_vm}", "src_state":"paused", "src_reason": "post-copy"}, "need_sleep_time": "5"}, {"func": "virsh.destroy", "func_param": {"name": "${main_vm}"}}]' diff --git a/libvirt/tests/src/migration/async_ops/destroy_vm_during_finishphase.py b/libvirt/tests/src/migration/async_ops/destroy_vm_during_finishphase.py new file mode 100644 index 00000000000..661ce0f0925 --- /dev/null +++ b/libvirt/tests/src/migration/async_ops/destroy_vm_during_finishphase.py @@ -0,0 +1,63 @@ +from virttest import utils_misc +from virttest import virsh + +from virttest.utils_test import libvirt + +from provider.migration import base_steps +from provider.migration import migration_base + + +def run(test, params, env): + """ + This case is to verify that if destroying vm during FinishPhase of postcopy + migration, migration will fail. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def verify_test(): + """ + Verify steps + """ + expected_dest_state = params.get("expected_dest_state") + expected_src_state = params.get("expected_src_state") + dest_uri = params.get("virsh_migrate_desturi") + + test.log.info("Verify steps.") + if expected_src_state: + if not libvirt.check_vm_state(vm.name, expected_src_state, uri=migration_obj.src_uri): + test.fail("Check vm state on source host fail.") + if expected_dest_state: + if expected_dest_state == "nonexist": + dest_vm_list = virsh.dom_list(options="--all --persistent", debug=True, uri=dest_uri) + if vm_name in dest_vm_list.stdout.strip(): + test.fail("%s should not exist." % vm_name) + else: + if not libvirt.check_vm_state(vm.name, expected_dest_state, uri=dest_uri): + test.fail("Check vm state on target host fail.") + if expected_dest_state == "running": + virsh.destroy(vm_name, uri=dest_uri) + utils_misc.wait_for(lambda: virsh.domain_exists(vm_name, uri=dest_uri), 10) + vm.destroy() + vm.start() + vm.wait_for_login().close() + + vm_name = params.get("migrate_main_vm") + + virsh_session = None + remote_virsh_session = None + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + migration_obj.setup_connection() + virsh_session, remote_virsh_session = migration_base.monitor_event(params) + migration_obj.run_migration() + verify_test() + migration_obj.run_migration_again() + migration_obj.verify_default() + migration_base.check_event_output(params, test, virsh_session, remote_virsh_session) + finally: + migration_obj.cleanup_connection() From ee2ad267a4734b4080c88b8016e7d01d552bed0e Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 25 Feb 2025 17:03:38 +0800 Subject: [PATCH 0845/1055] vIOMMU: Fix up login timeout issue To avoid vm login timeout issue, the busNr of the pcie-expander-bus controller should be set to less than 254. Signed-off-by: Yingshun Cui --- .../cfg/sriov/vIOMMU/intel_iommu_virtio_device_with_ats.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_virtio_device_with_ats.cfg b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_virtio_device_with_ats.cfg index 043be96aa73..6b68368af0d 100644 --- a/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_virtio_device_with_ats.cfg +++ b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_virtio_device_with_ats.cfg @@ -28,5 +28,5 @@ - pcie_root_port_from_expander_bus: test_devices = ["Eth", "block"] root_port = {'type': 'pci', 'model': 'pcie-root-port', 'pre_controller': 'pcie-expander-bus'} - controller_dicts = [{'type': 'pci', 'model': 'pcie-expander-bus', 'pre_controller': 'pcie-root'}, ${root_port}, ${root_port}] + controller_dicts = [{'type': 'pci', 'model': 'pcie-expander-bus', 'target': {'busNr': '252'}, 'pre_controller': 'pcie-root'}, ${root_port}, ${root_port}] disk_dict = {'target': {'dev': 'vda', 'bus': 'virtio'}, 'device': 'disk', 'driver': ${disk_driver}} From ef9e7f820a4d86b9463f7b05e2468fd08f27282a Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 9 Dec 2024 21:44:51 +0800 Subject: [PATCH 0846/1055] migration: Add test about query info during migration XXX-298247 - [VM migration][async ops] Query domain information during migration Signed-off-by: lcheng --- .../async_ops/query_info_during_migration.cfg | 43 ++++++++++ .../async_ops/query_info_during_migration.py | 86 +++++++++++++++++++ provider/migration/migration_base.py | 26 +++--- 3 files changed, 143 insertions(+), 12 deletions(-) create mode 100644 libvirt/tests/cfg/migration/async_ops/query_info_during_migration.cfg create mode 100644 libvirt/tests/src/migration/async_ops/query_info_during_migration.py diff --git a/libvirt/tests/cfg/migration/async_ops/query_info_during_migration.cfg b/libvirt/tests/cfg/migration/async_ops/query_info_during_migration.cfg new file mode 100644 index 00000000000..69ca4213e8f --- /dev/null +++ b/libvirt/tests/cfg/migration/async_ops/query_info_during_migration.cfg @@ -0,0 +1,43 @@ +- migration.async_ops.query_info_during_migration: + type = query_info_during_migration + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + check_network_accessibility_after_mig = "yes" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + status_error = "no" + action_during_mig = '[{"func": "execute_statistics_command", "after_event": "iteration: '1'", "func_param": "params"}]' + target_dev = "vdb" + loop_disk_type = "block" + block_device = "${nfs_mount_dir}/query_info_test.img" + migrate_speed = "15" + loop_time = "20" + variants: + - p2p: + virsh_migrate_options = '--live --p2p --verbose' + - non_p2p: + virsh_migrate_options = '--live --verbose' + variants: + - with_precopy: + - with_postcopy: + postcopy_options = '--postcopy --timeout 10 --timeout-postcopy' diff --git a/libvirt/tests/src/migration/async_ops/query_info_during_migration.py b/libvirt/tests/src/migration/async_ops/query_info_during_migration.py new file mode 100644 index 00000000000..cd99b0171c3 --- /dev/null +++ b/libvirt/tests/src/migration/async_ops/query_info_during_migration.py @@ -0,0 +1,86 @@ +from avocado.utils import process + +from virttest import remote +from virttest import virsh + +from virttest.utils_test import libvirt + +from provider.migration import base_steps + +source_loop_dev = None +target_loop_dev = None + + +def run(test, params, env): + """ + This case is to verify that readonly commands domblkinfo/domblklist/domstats/dommemstat + can be executed during migration. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def setup_test(): + """ + Setup steps + + """ + def _setup_loop_dev(remote_host=False): + """ + Setup a loop device for test + + :param remote_host: If True, set loop device on remote host + """ + loop_dev = None + cmd = "losetup --find" + if remote_host: + loop_dev = remote.run_remote_cmd(cmd, params, ignore_status=False).stdout_text.strip() + else: + loop_dev = process.run(cmd, shell=True).stdout_text.strip() + test.log.debug(f"loop dev: {loop_dev}") + + cmd = f"losetup {loop_dev} {block_device}" + if remote_host: + remote.run_remote_cmd(cmd, params, ignore_status=False) + else: + process.run(cmd, shell=True) + return loop_dev + + target_dev = params.get("target_dev") + block_device = params.get("block_device") + + migration_obj.setup_connection() + libvirt.create_local_disk("file", block_device, '1', "qcow2") + + global source_loop_dev + source_loop_dev = _setup_loop_dev() + global target_loop_dev + target_loop_dev = _setup_loop_dev(remote_host=True) + + ret = virsh.attach_disk(vm_name, source_loop_dev, target_dev, debug=True) + libvirt.check_exit_status(ret) + + def cleanup_test(): + """ + Cleanup steps + + """ + migration_obj.cleanup_connection() + global source_loop_dev + if source_loop_dev: + process.run(f"losetup -d {source_loop_dev}", shell=True) + global target_loop_dev + if target_loop_dev: + remote.run_remote_cmd(f"losetup -d {target_loop_dev}", params) + + vm_name = params.get("migrate_main_vm") + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + setup_test() + migration_obj.run_migration() + migration_obj.verify_default() + finally: + cleanup_test() diff --git a/provider/migration/migration_base.py b/provider/migration/migration_base.py index 5efe665e464..d192d44d162 100644 --- a/provider/migration/migration_base.py +++ b/provider/migration/migration_base.py @@ -293,6 +293,7 @@ def execute_statistics_command(params): """ vm_name = params.get("migrate_main_vm") disk_type = params.get("loop_disk_type") + loop_time = params.get("loop_time", "20") vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) if disk_type: @@ -301,18 +302,19 @@ def execute_statistics_command(params): disks = vmxml.get_disk_all_by_expr('device==disk') logging.debug("disks: %s", disks) debug_kargs = {'ignore_status': False, 'debug': True} - for disk in list(disks.values()): - if disk_type: - disk_source = disk.find('source').get('dev') - else: - disk_source = disk.find('source').get('file') - disk_target = disk.find('target').get('dev') - logging.debug("disk_source: %s", disk_source) - logging.debug("disk_target: %s", disk_target) - virsh.domblkstat(vm_name, disk_target, "", **debug_kargs) - virsh.domblkinfo(vm_name, disk_source, **debug_kargs) - virsh.domstats(vm_name, **debug_kargs) - virsh.dommemstat(vm_name, **debug_kargs) + for i in range(int(loop_time)): + for disk in list(disks.values()): + if disk_type: + disk_source = disk.find('source').get('dev') + else: + disk_source = disk.find('source').get('file') + disk_target = disk.find('target').get('dev') + logging.debug("disk_source: %s", disk_source) + logging.debug("disk_target: %s", disk_target) + virsh.domblkstat(vm_name, disk_target, "", **debug_kargs) + virsh.domblkinfo(vm_name, disk_source, **debug_kargs) + virsh.domstats(vm_name, **debug_kargs) + virsh.dommemstat(vm_name, **debug_kargs) def check_qemu_mem_lock_hard_limit(params): From b28326697715befb3af01ff1b2a6aca6bbff6d1c Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Fri, 6 Dec 2024 06:56:48 -0500 Subject: [PATCH 0847/1055] ethernet_interface: remove unsupported rom for s390x On s390x ROM tuning is not supported. Signed-off-by: Sebastian Mitterle --- .../connectivity/connectivity_check_ethernet_interface.cfg | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_ethernet_interface.cfg b/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_ethernet_interface.cfg index c24780f0042..ad09767cfe3 100644 --- a/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_ethernet_interface.cfg +++ b/libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_ethernet_interface.cfg @@ -40,10 +40,15 @@ only smaller_mtu_multi_ifaces extra_attrs = {'rom': {'enabled': 'no'}} iface_attrs_2 = {'type_name': 'ethernet', 'target': {'dev': tap_name_2, 'managed': 'no'}, 'model': 'virtio', 'mtu': {'size': '${iface_mtu_2}'}, 'driver': {'driver_attr': {'name': 'vhost'}}, 'rom': {'enabled': 'no'}} + s390-virtio, aarch64: + extra_attrs = + iface_attrs_2 = {'type_name': 'ethernet', 'target': {'dev': tap_name_2, 'managed': 'no'}, 'model': 'virtio', 'mtu': {'size': '${iface_mtu_2}'}, 'driver': {'driver_attr': {'name': 'vhost'}}} - macvtap: vm_ping_outside = pass vm_ping_host_public = fail iface_attrs = {'target': {'dev': tap_name, 'managed': 'no'}, 'model': 'virtio', 'type_name': 'ethernet', **${mtu_attrs}, **${extra_attrs}} + s390-virtio, aarch64: + iface_attrs = {'target': {'dev': tap_name, 'managed': 'no'}, 'model': 'virtio', 'type_name': 'ethernet', **${mtu_attrs}} - negative_test: status_error = yes variants: From 50cbce62f25fc06019943a66cd0e5ccb40f0be5d Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 26 Feb 2025 11:00:51 +0800 Subject: [PATCH 0848/1055] virsh_shutdown: Extend timeout of vm shutdown Update timeout to make the case stable. Signed-off-by: lcheng --- libvirt/tests/src/virsh_cmd/domain/virsh_shutdown.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_shutdown.py b/libvirt/tests/src/virsh_cmd/domain/virsh_shutdown.py index ed22ad5fe96..2af22c12f38 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_shutdown.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_shutdown.py @@ -111,7 +111,7 @@ def run(test, params, env): session.cmd_output('LANG=C') command = ("virsh -c %s shutdown %s %s" % (remote_uri, vm_name, mode)) - status = session.cmd_status(command, internal_timeout=5) + status = session.cmd_status(command, internal_timeout=10) session.close() except process.CmdError: status = 1 From 11dcb7c9839f9a4a329c48a192fd4d80ca85da79 Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 26 Feb 2025 11:24:59 +0800 Subject: [PATCH 0849/1055] migration: Update error message Signed-off-by: lcheng --- libvirt/tests/cfg/migration/migrate_vm.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration/migrate_vm.cfg b/libvirt/tests/cfg/migration/migrate_vm.cfg index da305753fd2..e0e31c151ed 100644 --- a/libvirt/tests/cfg/migration/migrate_vm.cfg +++ b/libvirt/tests/cfg/migration/migrate_vm.cfg @@ -716,7 +716,7 @@ config_libvirtd = "yes" variants: - no_migrate_disks: - err_msg = "error: internal error: unable to execute QEMU command '(nbd-server-add|block-export-add)': Block node is read-only" + err_msg = "error: internal error: unable to execute QEMU command '(nbd-server-add|block-export-add)'" virsh_options = "--live --verbose --copy-storage-all" - create_neither_target_pool_nor_image: create_target_image = "no" From bc63b39a80e1cc2dba5456927fecfddb94d22cd7 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Wed, 26 Feb 2025 02:11:02 -0500 Subject: [PATCH 0850/1055] Rewrite v2v cases about checking linux ogac Signed-off-by: Ming Xie --- v2v/tests/cfg/function_test_esx.cfg | 68 ++++++++++------------------- v2v/tests/src/function_test_esx.py | 24 ++-------- 2 files changed, 28 insertions(+), 64 deletions(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index e693d2c2429..5040f8b2694 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -122,12 +122,6 @@ checkpoint = 'fstrim_warning' msg_content = 'virt-v2v: warning: fstrim on guest filesystem /dev/.*? failed. Usually' expect_msg = yes - - schtask: - only esx_70 - checkpoint = "ogac" - virtio_win_path = "/usr/share/virtio-win/" - os_version = VM_VERSION_WIN_SCHTASKS_V2V_EXAMPLE - main_vm = VM_NAME_WIN_SCHTASKS_V2V_EXAMPLE - OGAC_balloon: only esx_80 only dest_libvirt @@ -561,53 +555,39 @@ # ovirt-guest-agent-common - OGAC: checkpoint = "ogac" - virtio_win_path = EXPORT_VIRTIO_WIN_PATH_V2V_EXAMPLE - implementation_change_ver = "[virt-v2v-2.0.6-3,)" variants: - rhel6: - only esx_70 - enable_legacy_policy = yes - qa_path = 'linux/el6' - qa_url = QEMU_GUEST_AGENT_EL6_DOWNLOAD_URL_V2V_EXAMPLE - main_vm = VM_NAME_RHEL6_V2V_EXAMPLE + only esx_70 + enable_legacy_policy = yes + main_vm = VM_NAME_ESX_BUGGY_SELINUX_CONTEXT_V2V_EXAMPLE - rhel7: - only esx_70 - qa_path = 'linux/el7' - qa_url = QEMU_GUEST_AGENT_EL7_DOWNLOAD_URL_V2V_EXAMPLE - main_vm = VM_NAME_RHEL7_V2V_EXAMPLE + only esx_80 + main_vm = VM_NAME_RHEL7_REPO_V2V_EXAMPLE - rhel8: - only esx_70 - qa_path = 'linux/el8' - qa_url = QEMU_GUEST_AGENT_EL8_DOWNLOAD_URL_V2V_EXAMPLE - main_vm = VM_NAME_RHEL8_V2V_EXAMPLE + only esx_80 + main_vm = VM_NAME_RHEL8_REPO_V2V_EXAMPLE + boottype = 3 - rhel9: - only esx_70 - version_required = "[libguestfs-1.45.6-2,)" - qa_path = 'linux/el9' - qa_url = QEMU_GUEST_AGENT_EL9_DOWNLOAD_URL_V2V_EXAMPLE - main_vm = VM_NAME_ESX70_RHEL9_V2V_EXAMPLE + only esx_80 + main_vm = VM_NAME_RHEL9_REPO_V2V_EXAMPLE + boottype = 3 + - rhel10: + only esx_80 + main_vm = VM_NAME_RHEL10_REPO_V2V_EXAMPLE - ubuntu: - only esx_70 - version_required = "[virt-v2v-2.0.6-3,)" - qa_path = 'linux/debian' - qa_url = QEMU_GUEST_AGENT_DEBIAN_DOWNLOAD_URL_V2V_EXAMPLE - main_vm = VM_NAME_UBUNTU_V2V_EXAMPLE + only esx_70 + main_vm = VM_NAME_UBUNTU_REPO_V2V_EXAMPLE - debian: - only esx_80 - version_required = "[virt-v2v-2.0.6-3,)" - qa_path = 'linux/debian' - qa_url = QEMU_GUEST_AGENT_DEBIAN_DOWNLOAD_URL_V2V_EXAMPLE - main_vm = VM_NAME_DEBIAN_V2V_EXAMPLE + only esx_80 + main_vm = VM_NAME_DEBIAN_REPO_V2V_EXAMPLE - sles: - only esx_70 - qa_path = 'linux/lp151' - qa_url = QEMU_GUEST_AGENT_SUSE_DOWNLOAD_URL_V2V_EXAMPLE - main_vm = VM_NAME_SLES_V2V_EXAMPLE + only esx_80 + main_vm = VM_NAME_SLES_REPO_V2V_EXAMPLE + boottype = 3 + os_version = "sles" - opensuse: - only esx_80 - qa_path = 'linux/lp151' - qa_url = QEMU_GUEST_AGENT_SUSE_DOWNLOAD_URL_V2V_EXAMPLE - main_vm = VM_NAME_OPENSUSE_V2V_EXAMPLE + only esx_80 + main_vm = VM_NAME_OPENSUSE_REPO_V2V_EXAMPLE - ubuntu-openvm-tools: only esx_70 main_vm = VM_NAME_UBUNTUTOOS_V2V_EXAMPLE diff --git a/v2v/tests/src/function_test_esx.py b/v2v/tests/src/function_test_esx.py index 7f9ae4f6592..a517c49c909 100644 --- a/v2v/tests/src/function_test_esx.py +++ b/v2v/tests/src/function_test_esx.py @@ -18,7 +18,6 @@ from virttest.utils_test import libvirt from virttest.utils_v2v import params_get from avocado.utils import process -from avocado.utils import download from aexpect.exceptions import ShellProcessTerminatedError, ShellTimeoutError, ShellStatusError from provider.v2v_vmcheck_helper import VMChecker @@ -308,7 +307,10 @@ def get_service_info(): Get qemu-guest-agent service info """ status_ptn = r'Active: active \((running|exited)\)|qemu-ga \(pid +[0-9]+\) is running' - cmd = 'service qemu-ga status;systemctl status qemu-guest-agent;systemctl status qemu-ga*' + if os_version == 'sles': + cmd = 'systemctl status qemu-guest-agent' + else: + cmd = 'service qemu-ga status;systemctl status qemu-guest-agent;systemctl status qemu-ga*' _, output = vmcheck.run_cmd(cmd) if not re.search(status_ptn, output): return False @@ -807,24 +809,6 @@ def vm_check(status_error): ovirt4_path = os.path.dirname(ovirtsdk4.__file__) dst_ovirt4_path = ovirt4_path + '.bak' os.rename(ovirt4_path, dst_ovirt4_path) - if checkpoint[0].startswith('ogac') and 'ogac_balloon' not in checkpoint: - os.environ['VIRTIO_WIN'] = virtio_win_path - if os_type == 'linux' and not utils_v2v.multiple_versions_compare(implementation_change_ver) and \ - os.path.isdir(os.getenv('VIRTIO_WIN')): - export_path = os.getenv('VIRTIO_WIN') - qemu_guest_agent_dir = os.path.join(export_path, qa_path) - if not os.path.exists(qemu_guest_agent_dir) and os.access( - export_path, os.W_OK) and qa_url: - LOG.debug( - 'Not found qemu-guest-agent in virtio-win or rhv-guest-tools-iso,' - ' Try to prepare it manually. This is not a permanent step, once' - ' the official build includes it, this step should be removed.') - os.makedirs(qemu_guest_agent_dir) - rpm_name = os.path.basename(qa_url) - download.get_file( - qa_url, os.path.join( - qemu_guest_agent_dir, rpm_name)) - if 'vddk_error' in checkpoint: fqdn_record = params_get(params, 'fqdn_record') with open('/etc/hosts', 'r+') as fd: From 95b52b3df881eb0d6d01c3bc028f52836c268a6c Mon Sep 17 00:00:00 2001 From: hholoubk Date: Wed, 26 Feb 2025 15:00:55 +0100 Subject: [PATCH 0851/1055] tests failing due missing default value in case, that the value is not set for given variant --- libvirt/tests/src/virsh_cmd/domain/virsh_restore.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_restore.py b/libvirt/tests/src/virsh_cmd/domain/virsh_restore.py index 55dcc39728b..8bcb224079c 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_restore.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_restore.py @@ -65,7 +65,7 @@ def check_file_own(file_path, exp_uid, exp_gid): check_log = params.get("check_log") check_str_not_in_log = params.get("check_str_not_in_log") qemu_conf_dict = eval(params.get("qemu_conf_dict", "{}")) - os_update_dict = eval(params.get("os_update_dict")) + os_update_dict = eval(params.get("os_update_dict", "{}")) vm_ref_uid = None vm_ref_gid = None From 48f896a8927f9a99de4b8916af20d92de5442d55 Mon Sep 17 00:00:00 2001 From: nanli Date: Thu, 19 Dec 2024 16:08:56 +0800 Subject: [PATCH 0852/1055] add case for virt-xml-validate for virsh domcap xxxx-17141:validate libvirt XML files against a virsh domcap schema Signed-off-by: nanli --- .../tests/cfg/virt_cmd/virt_xml_validate.cfg | 3 +++ libvirt/tests/src/virt_cmd/virt_xml_validate.py | 17 ++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virt_cmd/virt_xml_validate.cfg b/libvirt/tests/cfg/virt_cmd/virt_xml_validate.cfg index 45a5228c81b..491960ddc99 100644 --- a/libvirt/tests/cfg/virt_cmd/virt_xml_validate.cfg +++ b/libvirt/tests/cfg/virt_cmd/virt_xml_validate.cfg @@ -28,3 +28,6 @@ secret_volume = "/var/lib/libvirt/images/virt_xml_validate.secret" - interface: schema = "interface" + - domcapabilities: + func_supported_since_libvirt_ver = (10, 10, 0) + schema = "domcapabilities" diff --git a/libvirt/tests/src/virt_cmd/virt_xml_validate.py b/libvirt/tests/src/virt_cmd/virt_xml_validate.py index f05e14eaee1..9e3a81937da 100644 --- a/libvirt/tests/src/virt_cmd/virt_xml_validate.py +++ b/libvirt/tests/src/virt_cmd/virt_xml_validate.py @@ -8,6 +8,7 @@ from virttest import virsh from virttest import data_dir +from virttest import libvirt_version from virttest.utils_libvirt import libvirt_secret from virttest.utils_test import libvirt @@ -183,10 +184,21 @@ def interface_validate(test, file=None, **virsh_dargs): test.error(str(e)) +def domcap_validate(file=None, **virsh_dargs): + """ + Prepare schema domcapabilities. + :param file: domcapabilities output file + :param virsh_dargs: virsh debug args. + """ + cmd_result = virsh.domcapabilities(options="> %s" % file, **virsh_dargs) + libvirt.check_exit_status(cmd_result) + + def run(test, params, env): """ Test for virt-xml-validate """ + libvirt_version.is_libvirt_feature_supported(params) # Get the full path of virt-xml-validate command. try: VIRT_XML_VALIDATE = astring.to_text(process.system_output("which virt-xml-validate", shell=True)) @@ -203,7 +215,7 @@ def run(test, params, env): valid_schemas = ['domain', 'domainsnapshot', 'network', 'storagepool', 'storagevol', 'nodedev', 'capability', - 'nwfilter', 'secret', 'interface'] + 'nwfilter', 'secret', 'interface', 'domcapabilities'] if schema not in valid_schemas: test.fail("invalid %s specified" % schema) @@ -230,6 +242,9 @@ def run(test, params, env): secret_validate(test, secret_volume, file=output_path, **virsh_dargs) elif schema == "interface": interface_validate(test, file=output_path, **virsh_dargs) + elif schema == "domcapabilities": + domcap_validate(file=output_path, **virsh_dargs) + schema = "" else: # domain virsh.dumpxml(vm_name, to_file=output_path) From f8e06b94a27c760046b4ca0032824dbb8be9cff7 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Wed, 26 Feb 2025 22:35:16 -0500 Subject: [PATCH 0853/1055] scsi_device: add new case of hostdev device for scsi commands testing Automate case: VIRT-302167 - [Host device assignment][SCSI] SCSI command passthrough test for hostdev scsi device Signed-off-by: Meina Li --- .../cfg/scsi/scsi_command_test_hostdev.cfg | 10 ++ .../src/scsi/scsi_command_test_hostdev.py | 146 ++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 libvirt/tests/cfg/scsi/scsi_command_test_hostdev.cfg create mode 100644 libvirt/tests/src/scsi/scsi_command_test_hostdev.py diff --git a/libvirt/tests/cfg/scsi/scsi_command_test_hostdev.cfg b/libvirt/tests/cfg/scsi/scsi_command_test_hostdev.cfg new file mode 100644 index 00000000000..0574c474ed6 --- /dev/null +++ b/libvirt/tests/cfg/scsi/scsi_command_test_hostdev.cfg @@ -0,0 +1,10 @@ +- scsi_device.scsi_command_test.with_hostdev: + type = scsi_command_test_hostdev + start_vm = no + variants: + - guest_multipath: + emulated_image = "emulated-iscsi" + second_target = "iqn.2024-11.com.virttest:emulated-iscsi.target-2" + mpath_conf_path = "/etc/multipath.conf" + pkg_list = "['device-mapper-multipath', 'python3-rtslib']" + hostdev_dict = {'type': 'scsi', 'source': {'untyped_address': {'target': '0', 'unit': '0', 'bus': '0'}, 'adapter_name': 'scsi_host%s'}, 'mode': 'subsystem', 'type_name': 'scsi', 'rawio': 'yes', 'sgio': 'filtered', 'managed': 'no'} diff --git a/libvirt/tests/src/scsi/scsi_command_test_hostdev.py b/libvirt/tests/src/scsi/scsi_command_test_hostdev.py new file mode 100644 index 00000000000..3d5ebe6f298 --- /dev/null +++ b/libvirt/tests/src/scsi/scsi_command_test_hostdev.py @@ -0,0 +1,146 @@ +import ast +import re + +from avocado.utils import process + +from virttest import iscsi +from virttest import utils_package +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.devices import hostdev +from virttest.utils_test import libvirt + + +def run(test, params, env): + """ + SCSI command passthrough test for hostdev scsi device + """ + + def get_scsi_count(guest_cmd=False): + """ + Get the counts pf scsi devices. + + :params guest_cmd: if the command is ran in guest. + :params return: return the count of scsi device. + """ + if guest_cmd: + _, output = vm_session.cmd_status_output("lsscsi") + else: + output = process.run("lsscsi").stdout_text + scsi_device_count = len(re.findall("LIO", output)) + return scsi_device_count + + def create_second_target_by_iscsi(emulated_image, second_target): + """ + This test needs to have two LUNs with same image but not same target name. + The current libvirt.setup_or_cleanup_iscsi() can't cover it. + + :params emulated_image: an image used for iscsi target LUN + :params second_target: the second target name + """ + scsi_device_count = get_scsi_count() + sec_target_params = {'emulated_image': emulated_image, + 'target': second_target, + 'image_size': '1G', + 'enable_authentication': False, + 'iscsi_allow_multipath': 'yes'} + iscsi_dev = iscsi.Iscsi.create_iSCSI(sec_target_params) + iscsi_dev.login() + iscsi_status = get_scsi_count() + if int(iscsi_status) != (int(scsi_device_count) + 1): + test.fail("Prepare the second target fail!") + + def prepare_guest_with_hostdev_devices(vmxml, emulated_image): + """ + Prepare 2 scsi disks and hostdev devices xml. + + :params vmxml: the guest xml + :params emulated_image: an image used for iscsi target LUN + """ + for i in range(2): + if i == 0: + libvirt.setup_or_cleanup_iscsi(is_setup=True, is_login=True, + emulated_image=emulated_image) + else: + create_second_target_by_iscsi(emulated_image, second_target) + cmd = "lsscsi | grep LIO | awk '{print $1}' | awk -F '[:[]' '{print $2}' | tail -n 1" + scsi_host_num = process.run(cmd, shell=True, ignore_status=False).stdout_text.split()[0] + hostdev_dict = eval(params.get("hostdev_dict", "{}") % scsi_host_num) + hostdev_xml = hostdev.Hostdev() + hostdev_xml.setup_attrs(**hostdev_dict) + libvirt.add_vm_device(vmxml, hostdev_xml) + vmxml.sync() + test.log.debug("The current guest xml is: %s", vmxml) + + def setup_multipath_service(vm_session): + """ + Setup multipath service in guest. + + :params vm_session: the vm session + :params return: return the mpath disk name in guest + """ + mpath_conf_path = params.get("mpath_conf_path", "/etc/multipath.conf ") + pkg_list = ast.literal_eval(params.get("pkg_list")) + if not utils_package.package_install(pkg_list, vm_session): + test.fail("Failed to install %s package on guest!" % pkg_list) + vm_session.cmd("touch %s" % mpath_conf_path) + conf_in_guest = ( + "cat < %s\n" + "defaults {\n" + " user_friendly_names yes\n" + " find_multipaths yes\n" + " no_path_retry fail\n" + " enable_foreign '^$'\n" + " reservation_key file\n" + "}\n" + "EOF" + ) % mpath_conf_path + vm_session.cmd(conf_in_guest) + vm_session.cmd("systemctl restart multipathd") + status, output = vm_session.cmd_status_output("multipath -ll") + if status or ("active" not in output): + test.fail("Setup multipath service failed!") + mpath_dev = re.search(r"mpath[a-z]", output).group(0) + test.log.debug("The multipath disk in guest is %s.", mpath_dev) + return mpath_dev + + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + emulated_image = params.get("emulated_image") + second_target = params.get("second_target") + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + backup_xml = vmxml.copy() + + try: + test.log.info("TEST_STEP1: start the guest with two hostdev devices.") + prepare_guest_with_hostdev_devices(vmxml, emulated_image) + vm.start() + test.log.info("TEST_STEP2: check the scsi disks in guest.") + vm_session = vm.wait_for_serial_login() + scsi_device_count = get_scsi_count(guest_cmd=True) + if int(scsi_device_count) != 2: + test.fail("Can't get the expected scsi disks in guest!") + test.log.info("TEST_STEP3: setup multipath service in guest.") + mpath_dev = setup_multipath_service(vm_session) + + test.log.info("TEST_STEP4: send the scsi commands to scsi disk.") + for cmd in [ + "mpathpersist --out --register-ignore --param-sark 123aaa /dev/mapper/%s" % mpath_dev, + "mpathpersist --out --reserve --param-rk 123aaa --prout-type 5 /dev/mapper/%s" % mpath_dev, + "mpathpersist --in -k /dev/mapper/%s" % mpath_dev, + "mpathpersist --in -r /dev/mapper/%s" % mpath_dev, + "mpathpersist --out --release --param-rk 123aaa --prout-type 5 /dev/mapper/%s" % mpath_dev, + "mpathpersist --out --register --param-rk 123aaa --prout-type 5 /dev/mapper/%s" % mpath_dev + ]: + status, output = vm_session.cmd_status_output(cmd) + if status: + test.fail("Send scsi commands to scsi disk failed with message %s!" % output) + test.log.debug("Send scsi commands successfully!") + vm_session.close() + finally: + if vm.is_alive(): + vm.destroy() + backup_xml.sync() + libvirt.setup_or_cleanup_iscsi(is_setup=False) + if second_target in process.run("targetcli ls").stdout_text: + iscsi.iscsi_logout(second_target) + process.run("targetcli /iscsi/ delete %s" % second_target, shell=True) From cf8a7b6f7efc73499199f581cb19d44b11ecefd2 Mon Sep 17 00:00:00 2001 From: nanli Date: Fri, 7 Feb 2025 11:44:49 +0800 Subject: [PATCH 0854/1055] fix iommu was added automatically when cpus are bigger than 255 LIBVIRT-1414 says case update Signed-off-by: nanli --- libvirt/tests/src/cpu/max_vcpus.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/cpu/max_vcpus.py b/libvirt/tests/src/cpu/max_vcpus.py index 6debbdb6cd6..1ed245a6291 100644 --- a/libvirt/tests/src/cpu/max_vcpus.py +++ b/libvirt/tests/src/cpu/max_vcpus.py @@ -166,7 +166,8 @@ def set_iommu(vmxml, **dargs): vmxml.vcpu = int(guest_vcpu) set_iommu(vmxml) result_need_check = virsh.define(vmxml.xml, debug=True) - + if libvirt_version.version_compare(10, 10, 0): + err_msg = "" # Add ioapic and iommu device in xml for q35 VM if check.startswith('ioapic_iommu'): logging.info('Modify features') From 9a71f16a2c417ab9baa92b049f72715bfb40772f Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 27 Feb 2025 02:25:09 -0500 Subject: [PATCH 0855/1055] iface_unprivileged:update case to use existing vm Signed-off-by: Haijiao Zhao --- .../virtual_network/iface_unprivileged.cfg | 14 +- .../src/virtual_network/iface_unprivileged.py | 229 +++++------------- 2 files changed, 61 insertions(+), 182 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/iface_unprivileged.cfg b/libvirt/tests/cfg/virtual_network/iface_unprivileged.cfg index 0905a4cf7be..c8b93a8a87e 100644 --- a/libvirt/tests/cfg/virtual_network/iface_unprivileged.cfg +++ b/libvirt/tests/cfg/virtual_network/iface_unprivileged.cfg @@ -1,14 +1,12 @@ - virtual_network.iface_unprivileged: type = iface_unprivileged start_vm = no - up_user = 'test_upu' - user_vm_name = 'non_root_vm' - bridge_name = "test_br0" - # Replace remote_ip by a actual IP address - remote_ip = "www.google.com" - ping_count = 3 - ping_timeout = 10 - iface_name = + outside_ip = "www.redhat.com" + vm_ping_outside = pass + host_iface = + test_user = test + test_passwd = test + unpr_vm_name = unpr-vm variants: - precreated: case = 'precreated' diff --git a/libvirt/tests/src/virtual_network/iface_unprivileged.py b/libvirt/tests/src/virtual_network/iface_unprivileged.py index a5d1d41d4c4..98f918ac10f 100644 --- a/libvirt/tests/src/virtual_network/iface_unprivileged.py +++ b/libvirt/tests/src/virtual_network/iface_unprivileged.py @@ -1,22 +1,17 @@ -import logging as log -import shutil -import aexpect - -from avocado.utils import process +import logging +import aexpect from virttest import libvirt_version from virttest import remote from virttest import utils_misc from virttest import utils_net -from virttest import utils_package from virttest import virsh from virttest.libvirt_xml import vm_xml -from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_unprivileged +from provider.virtual_network import network_base -# 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__) +LOG = logging.getLogger('avocado.' + __name__) def run(test, params, env): @@ -24,156 +19,64 @@ def run(test, params, env): Test interface with unprivileged user """ - def create_bridge(br_name, iface_name): - """ - Create bridge attached to physical interface - """ - # Make sure the bridge not exist - if libvirt.check_iface(br_name, "exists", "--all"): - test.cancel("The bridge %s already exist" % br_name) - - # Create bridge - utils_package.package_install('tmux') - cmd = 'tmux -c "ip link add name {0} type bridge; ip link set {1} up;' \ - ' ip link set {1} master {0}; ip link set {0} up; pkill dhclient; ' \ - 'sleep 6; dhclient {0}; ifconfig {1} 0"'.format(br_name, iface_name) - process.run(cmd, shell=True, verbose=True) - - def check_ping(dest_ip, ping_count, timeout, src_ip=None, session=None, - expect_success=True): - """ - Check if ping result meets expectation - """ - status, output = utils_net.ping(dest=dest_ip, count=ping_count, - interface=src_ip, timeout=timeout, - session=session, force_ipv4=True) - success = True if status == 0 else False - - if success != expect_success: - test.fail('Ping result not met expectation, ' - 'actual result is {}'.format(success)) - if not libvirt_version.version_compare(5, 6, 0): test.cancel('Libvirt version is too low for this test.') - vm_name = params.get('main_vm') - rand_id = '_' + utils_misc.generate_random_string(3) + vm_name = params.get('unpr_vm_name') + test_user = params.get('test_user', '') + test_passwd = params.get('test_passwd', '') + unpr_vm_args = { + 'username': params.get('username'), + 'password': params.get('password'), + } + vm = libvirt_unprivileged.get_unprivileged_vm(vm_name, test_user, + test_passwd, + **unpr_vm_args) + uri = f'qemu+ssh://{test_user}@localhost/session' + virsh_ins = virsh.Virsh(uri=uri) + host_session = aexpect.ShellSession('su') + remote.VMManager.set_ssh_auth(host_session, 'localhost', test_user, + test_passwd) + host_session.close() - upu_vm_name = 'upu_vm' + rand_id - user_vm_name = params.get('user_vm_name', 'non_root_vm') + rand_id = '_' + utils_misc.generate_random_string(3) bridge_name = params.get('bridge_name', 'test_br0') + rand_id device_type = params.get('device_type', '') - iface_name = params.get("iface_name") - if not iface_name: - iface_name = utils_net.get_net_if(state="UP")[0] + host_iface = params.get('host_iface') + if not host_iface: + host_iface = utils_net.get_default_gateway( + iface_name=True, force_dhcp=True).split()[0] tap_name = params.get('tap_name', 'mytap0') + rand_id macvtap_name = params.get('macvtap_name', 'mymacvtap0') + rand_id - remote_ip = params.get('remote_ip') - up_user = params.get('up_user', 'test_upu') + rand_id case = params.get('case', '') - # Create unprivileged user - logging.info('Create unprivileged user %s', up_user) - process.run('useradd %s' % up_user, shell=True, verbose=True) - root_vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) - - upu_args = { - 'unprivileged_user': up_user, - 'ignore_status': False, - 'debug': True, - } + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name, + virsh_instance=virsh_ins) + bkxml = vmxml.copy() try: - # Create vm as unprivileged user - logging.info('Create vm as unprivileged user') - upu_vmxml = root_vmxml.copy() - - # Prepare vm for unprivileged user - xml_devices = upu_vmxml.devices - disks = xml_devices.by_device_tag("disk") - for disk in disks: - ori_path = disk.source['attrs'].get('file') - if not ori_path: - continue - - file_name = ori_path.split('/')[-1] - new_disk_path = '/home/{}/{}'.format(up_user, file_name) - logging.debug('New disk path:{}'.format(new_disk_path)) - - # Copy disk image file and chown to make sure that - # unprivileged user has access - shutil.copyfile(ori_path, new_disk_path) - shutil.chown(new_disk_path, up_user, up_user) - - # Modify xml to set new path of disk - disk_index = xml_devices.index(disk) - source = xml_devices[disk_index].source - new_attrs = source.attrs - new_attrs['file'] = new_disk_path - source.attrs = new_attrs - xml_devices[disk_index].source = source - logging.debug(xml_devices[disk_index].source) - - upu_vmxml.devices = xml_devices - - new_xml_path = '/home/{}/upu.xml'.format(up_user) - shutil.copyfile(upu_vmxml.xml, new_xml_path) - - # Define vm for unprivileged user - virsh.define(new_xml_path, **upu_args) - virsh.domrename(vm_name, upu_vm_name, **upu_args) - logging.debug(virsh.dumpxml(upu_vm_name, **upu_args)) - upu_vmxml = vm_xml.VMXML() - upu_vmxml.xml = virsh.dumpxml(upu_vm_name, **upu_args).stdout_text - - # Remove nvram tag of os to avoid permission issue - os_xml = upu_vmxml.os - os_xml.del_nvram() - upu_vmxml.os = os_xml if case == 'precreated': if device_type == 'tap': # Create bridge - create_bridge(bridge_name, iface_name) + iface_attrs = network_base.get_iface_xml_inst( + vm_name, 'on vm', virsh_ins=virsh_ins).fetch_attrs() + if iface_attrs.get('driver', {}).get('driver_attr', {}).get('queues'): + tap_flag = 'multi_queue' + else: + tap_flag = '' + utils_net.create_linux_bridge_tmux(bridge_name, host_iface) - # Create tap device - tap_cmd = 'ip tuntap add mode tap user {user} group {user} ' \ - 'name {tap};ip link set {tap} up;ip link set {tap} ' \ - 'master {br}'.format(tap=tap_name, user=up_user, - br=bridge_name) - - # Execute command as root - process.run(tap_cmd, shell=True, verbose=True) + network_base.create_tap( + tap_name, bridge_name, test_user, tap_flag) if device_type == 'macvtap': # Create macvtap device - mac_addr = utils_net.generate_mac_address_simple() - macvtap_cmd = 'ip link add link {iface} name {macvtap} address' \ - ' {mac} type macvtap mode bridge;' \ - 'ip link set {macvtap} up'.format( - iface=iface_name, - macvtap=macvtap_name, - mac=mac_addr) - process.run(macvtap_cmd, shell=True, verbose=True) - cmd_get_tap = 'ip link show {} | head -1 | cut -d: -f1'.format(macvtap_name) - tap_index = process.run(cmd_get_tap, shell=True, verbose=True).stdout_text.strip() - device_path = '/dev/tap{}'.format(tap_index) - logging.debug('device_path: {}'.format(device_path)) - # Change owner and group for device and ensure it is changed successfully - - def ensure_permission_ready(): - """ - check if the permission set ready - """ - process.run('chown {user} {path};chgrp {user} {path}'.format( - user=up_user, path=device_path), shell=True, verbose=True) - res = process.run('ls -l %s' % device_path, shell=True, verbose=True) - return "%s %s" % (up_user, up_user) in str(res) - - utils_misc.wait_for(ensure_permission_ready, timeout=10) + mac_addr = network_base.create_macvtap( + macvtap_name, host_iface, test_user) # Modify interface - all_devices = upu_vmxml.devices + all_devices = vmxml.devices iface_list = all_devices.by_device_tag('interface') if not iface_list: test.error('No iface to modify') @@ -200,47 +103,25 @@ def ensure_permission_ready(): if device_type == 'macvtap': iface.mac_address = mac_addr - logging.debug(iface) - - upu_vmxml.devices = all_devices - logging.debug(upu_vmxml) - - # Remove seclabel model="dac" since unprivileged user doesn't support this feature - upu_vmxml.del_seclabel([('model', 'dac'), ('relabel', 'yes')]) - # Define updated xml - shutil.copyfile(upu_vmxml.xml, new_xml_path) - upu_vmxml.xml = new_xml_path - virsh.define(new_xml_path, **upu_args) - logging.debug(virsh.dumpxml(upu_vm_name, **upu_args).stdout_text) - - # Switch to unprivileged user and modify vm's interface - # Start vm as unprivileged user and test network - virsh.start(upu_vm_name, debug=True, ignore_status=False, - unprivileged_user=up_user) - cmd = ("su - %s -c 'virsh console %s'" - % (up_user, upu_vm_name)) - session = aexpect.ShellSession(cmd) - session.sendline() - remote.handle_prompts(session, params.get("username"), - params.get("password"), r"[\#\$]\s*$", 60) - logging.debug(session.cmd_output('ifconfig')) - check_ping(remote_ip, 5, 10, session=session) + LOG.debug(iface) + + vmxml.devices = all_devices + LOG.debug(vmxml) + + vm.start() + session = vm.wait_for_serial_login(60) + LOG.debug(session.cmd_output('ifconfig')) + ips = {'outside_ip': params.get('outside_ip')} + network_base.ping_check(params, ips, session) session.close() finally: - if 'upu_virsh' in locals(): - virsh.destroy(upu_vm_name, unprivileged_user=up_user) - virsh.undefine(upu_vm_name, options='--nvram', unprivileged_user=up_user) + bkxml.sync(virsh_instance=virsh_ins) if case == 'precreated': try: - if device_type == 'tap': - process.run('ip tuntap del mode tap {}'.format(tap_name), shell=True, verbose=True) - elif device_type == 'macvtap': - process.run('ip l del {}'.format(macvtap_name), shell=True, verbose=True) + if device_type in ('tap', 'macvtap'): + network_base.delete_tap(tap_name) except Exception: pass finally: - cmd = 'tmux -c "ip link set {1} nomaster; ip link delete {0};' \ - 'pkill dhclient; sleep 6; dhclient {1}"'.format(bridge_name, iface_name) - process.run(cmd, shell=True, verbose=True, ignore_status=True) - process.run('pkill -u {0};userdel -f -r {0}'.format(up_user), shell=True, verbose=True, ignore_status=True) + utils_net.delete_linux_bridge_tmux(bridge_name, host_iface) From c7b0769b468b5793acf39675de1cdfd7a470c387 Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Mon, 20 Jan 2025 09:36:35 -0500 Subject: [PATCH 0856/1055] Filter this suite on s390x since it doesn't make sense to test it on s390x In s390x avocado-vt-vm1 guest, there is already one virto-scsi controller, but the code to libvirt.set_vm_disk(vm, params) to update it, but it throw error: XML error: Multiple 'scsi' controllers with index '0' Signed-off-by: chunfuwen --- .../tests/cfg/virtio_transitional/virtio_transitional_blk.cfg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_blk.cfg b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_blk.cfg index 9acf8a2f686..962d46dc4ce 100644 --- a/libvirt/tests/cfg/virtio_transitional/virtio_transitional_blk.cfg +++ b/libvirt/tests/cfg/virtio_transitional/virtio_transitional_blk.cfg @@ -1,6 +1,7 @@ - virtio_transitional_blk: type = virtio_transitional_blk start_vm = no + no s390-virtio Windows: get_device_cmd = "wmic diskdrive get index, size" get_device_pattern = "^\d+" @@ -10,11 +11,9 @@ virtio_model = "virtio" controller_model = "virtio-scsi" - virtio_transitional: - no s390-virtio virtio_model = "virtio-transitional" controller_model = ${virtio_model} - virtio_non_transitional: - no s390-virtio virtio_model = "virtio-non-transitional" variants: - boot_test: From 1315809db93d00c6d7a5030ec401a8b430f478fc Mon Sep 17 00:00:00 2001 From: Meina Li Date: Thu, 27 Feb 2025 21:01:09 -0500 Subject: [PATCH 0857/1055] SRIOV: add new case to test memory lock limit when hotplug memory with hostdev Automate: VIRT-299986 - hotplug memory to vm with hostdev type interface and check the memlock limit Signed-off-by: Meina Li --- .../sriov_with_hotplug_memory.cfg | 24 +++ .../sriov_with_hotplug_memory.py | 139 ++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 libvirt/tests/cfg/sriov/locked_memory_check/sriov_with_hotplug_memory.cfg create mode 100644 libvirt/tests/src/sriov/locked_memory_check/sriov_with_hotplug_memory.py diff --git a/libvirt/tests/cfg/sriov/locked_memory_check/sriov_with_hotplug_memory.cfg b/libvirt/tests/cfg/sriov/locked_memory_check/sriov_with_hotplug_memory.cfg new file mode 100644 index 00000000000..caf7bbd9f5d --- /dev/null +++ b/libvirt/tests/cfg/sriov/locked_memory_check/sriov_with_hotplug_memory.cfg @@ -0,0 +1,24 @@ +- sriov.locked_memory_check.hotplug_memory: + type = sriov_with_hotplug_memory + start_vm = "no" + mem_dict1 = {'mem_model': 'dimm', 'target': {'size': 1, 'size_unit': 'G', 'node': 0}, 'alias': {'name': 'ua-d9cbe3cc-40fe-4aed-b245-874c534e8362'}} + mem_dict2 = {'mem_model': 'dimm', 'target': {'size': 1, 'size_unit': 'G', 'node': 0}} + vm_attrs = {'max_mem_rt': 6291456, 'max_mem_rt_slots': 32, 'max_mem_rt_unit': 'K', 'vcpu': 8, 'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-3', 'memory': '%s', 'unit': 'K'}, {'id': '1', 'cpus': '4-7', 'memory': '%s', 'unit': 'K'}]}} + only x86_64, aarch64 + variants dev_type: + - hostdev_interface: + iface_dict = {'managed': 'yes', 'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}, 'alias': {'name': 'ua-89cbe690-6c6c-4f2f-adac-5826fe52ea74'}} + - hostdev_device: + variants dev_source: + - vf_address: + hostdev_dict = {'alias': {'name': 'ua-1bcbabff-f022-4d4f-ae8c-13f2d3a07906'}, 'mode': 'subsystem', 'type': 'pci', 'source': {'untyped_address': vf_pci_addr}, 'managed': 'yes'} + - pf_address: + hostdev_dict = {'alias': {'name': 'ua-1bcbabff-f022-4d4f-ae8c-13f2d3a07906'}, 'mode': 'subsystem', 'type': 'pci', 'source': {'untyped_address': pf_pci_addr}, 'managed': 'yes'} + variants: + - start_vm_with_hostdev: + - start_vm_without_hostdev: + without_hostdev = "yes" + variants mem_set: + - without_hardlimit: + - with_hardlimit: + vm_attrs = {**${vm_attrs}, 'memtune': {'hard_limit': 10485760, 'hard_limit_unit': 'K'}} diff --git a/libvirt/tests/src/sriov/locked_memory_check/sriov_with_hotplug_memory.py b/libvirt/tests/src/sriov/locked_memory_check/sriov_with_hotplug_memory.py new file mode 100644 index 00000000000..8bf2263d446 --- /dev/null +++ b/libvirt/tests/src/sriov/locked_memory_check/sriov_with_hotplug_memory.py @@ -0,0 +1,139 @@ +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_memory, libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.sriov import sriov_base + + +def run(test, params, env): + """ + Hotplug memory to vm with hostdev type device and check the memory lock limit. + """ + def setup_test(vm_name, dev_type, iface_dict): + """ + Prepare vm xml with device and memory setting then start guest. + + :params vm_name: the vm name + :params dev_type: the device type, includes hostdev device and interface + :params iface_dict: the dict of hostdev interface/device + :params return: the tuple of vmxml and with_hostdev_device value + """ + test.log.info("SETUP_STEP1: prepare vm xml with memory setting.") + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + vmxml.setup_attrs(**vm_attrs) + vmxml.sync() + with_hostdev_device = False + if not without_hostdev: + test.log.info("SETUP_STEP2: prepare vm xml with device.") + sriov_test_obj.setup_default(dev_name=dev_name) + iface_dev = sriov_test_obj.create_iface_dev(dev_type, iface_dict) + libvirt.add_vm_device(vmxml, iface_dev) + with_hostdev_device = True + return vmxml, with_hostdev_device + + def check_memory_limit(vmxml, current_mem, with_hostdev_device=True, mem_changed=True): + """ + Check the locked memory limit. + + :params vmxml: the vm xml + :params current_mem: the expected current memory + :params with_hostdev_device: boolean to use check if the vm has hostdev device + :params mem_changed: boolean to use check if the MEMLOCK is changed + """ + if int(current_mem) != int(vmxml.get_current_mem() * 1024): + test.fail("The current memory is incorrect after hot-unplugged.") + + # With_hardlimit: MEMLOCK value is equal to the hard_limit value + if mem_set == "with_hardlimit": + expr_memlock = libvirt_memory.normalize_mem_size( + vmxml.memtune.hard_limit, + vmxml.memtune.hard_limit_unit) + + # Without_hardlimit: MEMLOCK value is current memory + 1G + if mem_set == "without_hardlimit": + if without_hostdev and not with_hostdev_device: + expr_memlock = one_G_bytes // 16 + if with_hostdev_device: + if not mem_changed: + expr_memlock = current_mem + one_G_bytes * 2 + else: + expr_memlock = current_mem + one_G_bytes + + if not libvirt_memory.comp_memlock(expr_memlock): + test.fail("Unable to get correct MEMLOCK!") + + def hotplug_mem_device(vm_name, mem_dict, current_mem): + """ + Hotplug the memory device and check locked memory limit. + + :params vm_name: the vm name + :params mem_dict: the dict of memory device + :params current_mem: the expected current memory + """ + mem_xml = libvirt_vmxml.create_vm_device_by_type("memory", mem_dict) + virsh.attach_device(vm_name, mem_xml.xml, debug=True, ignore_status=False) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + check_memory_limit(vmxml, current_mem) + + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + dev_type = params.get("dev_type", "") + dev_source = params.get("dev_source", "") + mem_set = params.get("mem_set", "") + mem_dict1 = eval(params.get("mem_dict1", "{}")) + mem_dict2 = eval(params.get("mem_dict2", "{}")) + without_hostdev = "yes" == params.get("without_hostdev", "no") + + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + backup_vmxml = vmxml.copy() + num_memory = int(vmxml.get_current_mem() / 2) + vm_attrs = eval(params.get("vm_attrs", "{}") % (num_memory, num_memory)) + + sriov_test_obj = sriov_base.SRIOVTest(vm, test, params) + if dev_type == "hostdev_device" and dev_source.startswith("pf"): + dev_name = sriov_test_obj.pf_dev_name + else: + dev_name = sriov_test_obj.vf_dev_name + iface_dict = sriov_test_obj.parse_iface_dict() + + one_G_bytes = 1073741824 + + try: + vmxml, with_hostdev_device = setup_test(vm_name, dev_type, iface_dict) + test.log.info("TEST_STEP: Start the vm and check locked memory limit.") + vm.start() + test.log.debug("The current guest xml is:%s", virsh.dumpxml(vm_name).stdout_text) + vm_session = vm.wait_for_serial_login(timeout=240).close + default_mem = libvirt_memory.normalize_mem_size( + vmxml.get_current_mem(), + vmxml.get_current_mem_unit()) + check_memory_limit(vmxml, default_mem, with_hostdev_device) + if without_hostdev: + test.log.info("TEST_STEP: Hotplug iface device and check locked memory limit.") + iface_dev = sriov_test_obj.create_iface_dev(dev_type, iface_dict) + virsh.attach_device(vm_name, iface_dev.xml, debug=True, ignore_status=False) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + check_memory_limit(vmxml, default_mem, with_hostdev_device=True) + test.log.info("TEST_STEP: Hotplug 1st memory device and check locked memory limit.") + first_mem = default_mem + one_G_bytes + hotplug_mem_device(vm_name, mem_dict1, first_mem) + test.log.info("TEST_STEP: Hotplug 2nd memory device and check locked memory limit.") + second_mem = first_mem + one_G_bytes + hotplug_mem_device(vm_name, mem_dict2, second_mem) + test.log.info("TEST_STEP: Hot-unplug 2nd memory device and check locked memory limit.") + memxml = vm_xml.VMXML.new_from_dumpxml(vm_name).get_devices('memory')[-1] + virsh.detach_device(vm_name, memxml.xml, ignore_status=False, debug=True, + wait_for_event=True) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + check_memory_limit(vmxml, first_mem, mem_changed=False) + if without_hostdev: + test.log.info("TEST_STEP: Hot-unplug iface device and check locked memory limit.") + virsh.detach_device(vm_name, iface_dev.xml, debug=True, ignore_status=False, + wait_for_event=True) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + check_memory_limit(vmxml, first_mem, with_hostdev_device=False) + finally: + sriov_test_obj.teardown_default(dev_name=dev_name) + backup_vmxml.sync() From cdfb04dbcb649a3ff36acbf5c245d2fa9cbbd8f8 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Fri, 7 Feb 2025 04:53:43 -0500 Subject: [PATCH 0858/1055] Update the passt test as behavior changes With passt rebase, the behavior changes when passt interface with source dev as an inactive host interface. The vm can start successfully now. Signed-off-by: Yalan Zhang --- .../cfg/virtual_network/passt/passt_negative_setting.cfg | 1 + .../src/virtual_network/passt/passt_negative_setting.py | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_negative_setting.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_negative_setting.cfg index 5dbe4ecdc17..400a56c7aa3 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_negative_setting.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_negative_setting.cfg @@ -33,6 +33,7 @@ error_msg = Invalid interface name .*: No such device - inactive_host_iface: error_msg = External interface not usable + passt_version = 0^20250121.g4f2c8e7 - non_exist_bind_ip: portForwards = {'portForwards': [{'ranges': [{'start': '9000'}], 'attrs': {'proto': 'tcp', 'address': 'IP_EXAMPLE'}}]} error_msg = Failed to bind port diff --git a/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py b/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py index cf97ffa54f3..de9d021b6f1 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py +++ b/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py @@ -130,7 +130,14 @@ def _get_test_ip(): virsh.start(vm_name, uri=virsh_uri, **VIRSH_ARGS) result = virsh.attach_device(vm_name, iface_device.xml, uri=virsh_uri, debug=True) - + if scenario == 'inactive_host_iface': + passt_ver_cmp = params.get("passt_version") + passt_ver = process.run("rpm -q passt", shell=True, + ignore_status=True).stdout_text.strip().split('-')[1] + # With newer passt version, vm can start successfully + # with inactive interface + if passt_ver >= passt_ver_cmp: + status_error, error_msg = False, '' libvirt.check_exit_status(result, status_error) if error_msg: libvirt.check_result(result, error_msg) From e197976cc05f2709f506e14d61042c29512e8df3 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Thu, 27 Feb 2025 23:04:42 -0500 Subject: [PATCH 0859/1055] Add three v2v cases for customer bugs Signed-off-by: Ming Xie --- v2v/tests/cfg/specific_kvm.cfg | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/v2v/tests/cfg/specific_kvm.cfg b/v2v/tests/cfg/specific_kvm.cfg index bf7cdfc4c09..83834869c84 100644 --- a/v2v/tests/cfg/specific_kvm.cfg +++ b/v2v/tests/cfg/specific_kvm.cfg @@ -298,6 +298,18 @@ only libvirt boottype = 2 main_vm = VM_NAME_VMX_CONTAINS_CHAR_V2V_EXAMPLE + - efi_devicemap: + only esx_80 + boottype = 2 + main_vm = VM_NAME_EFI_GUEST_DEVICE_MAP_FILE_V2V_EXAMPLE + - cmd_output_4M: + only esx_80 + only libvirt + boottype = 2 + main_vm = VM_NAME_SLES_INSTALL_KERNEL_SOURCE_PKG_V2V_EXAMPLE + - vmtools_spausedd: + only esx_70 + main_vm = VM_NAME_OPEM_VM_TOOLS_DEPEND_SPAUSEDD_V2V_EXAMPLE variants: - positive_test: status_error = 'no' From 7e5e83e89c3ce76af6059cbfafaaf749a1db3c25 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Thu, 14 Nov 2024 08:17:37 -0500 Subject: [PATCH 0860/1055] Handle the driver element for non-virtio interface This is to cover the patch https://patchew.org/Libvirt/20240704154454.3999218-1-mirlos@cisco.com/. Signed-off-by: Yalan Zhang --- .../update_driver_non_virtio.cfg | 20 +++++ .../update_device/update_driver_non_virtio.py | 88 +++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/update_device/update_driver_non_virtio.cfg create mode 100644 libvirt/tests/src/virtual_network/update_device/update_driver_non_virtio.py diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_driver_non_virtio.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_driver_non_virtio.cfg new file mode 100644 index 00000000000..4f9b10bdbcd --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/update_device/update_driver_non_virtio.cfg @@ -0,0 +1,20 @@ +- virtual_network.update_device.driver_non_virtio: + type = update_driver_non_virtio + start_vm = no + timeout = 240 + outside_ip = "www.redhat.com" + vm_ping_outside = pass + func_supported_since_libvirt_ver = (10, 6, 0) + variants test_scenario: + - define_with_invaid_driver: + exist_attrs = {'driver': {'driver_host': {'csum':'off'}}} + update_setting = {"link_state": "down"} + - update_with_invalid_driver: + update_setting = {"link_state": "down", 'driver': {'driver_host': {'csum':'off'}}} + variants model_type: + - e1000e: + only x86_64 + - rtl8139: + only x86_64 + iface_attrs = {"model": "${model_type}", "type_name": "network", "source": {"network": "default"}} + diff --git a/libvirt/tests/src/virtual_network/update_device/update_driver_non_virtio.py b/libvirt/tests/src/virtual_network/update_device/update_driver_non_virtio.py new file mode 100644 index 00000000000..805cff2dd16 --- /dev/null +++ b/libvirt/tests/src/virtual_network/update_device/update_driver_non_virtio.py @@ -0,0 +1,88 @@ +import re + +from virttest import libvirt_version +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.interface import interface_base +from provider.virtual_network import network_base + +VIRSH_ARGS = {"ignore_status": False, "debug": True} + + +def run(test, params, env): + """ + Test update-device for interface link state, live update the link state from up to down + There are invalid driver attribute defined in the original xml or the update xml. + The test is to ensure the update can succeed and get expected result. + """ + libvirt_version.is_libvirt_feature_supported(params) + + outside_ip = params.get("outside_ip") + exist_attrs = eval(params.get('exist_attrs', '{}')) + iface_attrs_ = eval(params.get("iface_attrs", "{}")) + iface_attrs = {**iface_attrs_, **exist_attrs} + update_setting = eval(params.get("update_setting", "{}")) + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + def check_link_state(exp_link_state, exp_domiflik_state): + """ + check the link state on vm and in xml should be consistent and expected + """ + # get the link state in the live xml + link_info = virsh.domif_getlink(vm_name, iface_mac, **VIRSH_ARGS).stdout_text + test.log.debug("Get the interface info by domif-getlink: %s", link_info) + # get "Link detected" value from ethtool outputs on vm + output = session.cmd_output("ethtool %s" % vm_iface) + test.log.debug(output) + match = re.search(r"Link detected:\s*(\w+)", output) + if match: + link_status = match.group(1) + else: + test.cancel("Can not get expected Link status on vm!") + # make sure the result is expected + if exp_link_state == 'yes': + ips = {'outside_ip': outside_ip} + network_base.ping_check(params, ips, session, force_ipv4=True) + test.log.debug("link_info is %s, link-status is %s" % (link_info, link_status)) + if link_info.split()[-1] != exp_domiflik_state: + test.fail("The link states in vm xml is not expected") + if link_status != exp_link_state: + test.fail("The link status on vm is not expected") + + try: + vmxml.del_device('interface', by_tag=True) + libvirt_vmxml.modify_vm_device( + vmxml, 'interface', {**iface_attrs}) + test.log.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + vm.start() + session = vm.wait_for_serial_login() + vm_iface = interface_base.get_vm_iface(session) + + test.log.info("TEST_STEP1: Check the original link state in vm should be up") + ifaces = libvirt.get_interface_details(vm_name) + test.log.debug(f'ifaces of vm: {ifaces}') + iface_info = ifaces[0] + iface_mac = iface_info['mac'] + check_link_state("yes", "up") + + test.log.info("TEST_STEP2: Update the link state to be down") + iface = network_base.get_iface_xml_inst(vm_name, f'on VM:{vm_name}') + iface.setup_attrs(**update_setting) + test.log.debug(f"iface xml to be updated: {iface}") + ret = virsh.update_device(vm_name, iface.xml, **VIRSH_ARGS) + libvirt.check_result(ret) + + test.log.info("TEST_STEP3: Check the interface status in xml and on vm") + check_link_state("no", "down") + session.close() + finally: + bkxml.sync() From 98ca881d8510caaa4922cd31e8e5702ef20954bb Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 28 Feb 2025 16:56:27 +0800 Subject: [PATCH 0861/1055] vIOMMU: Add a ping check before and after migration Check that the ping command can be executed continuously before and after the migration. Signed-off-by: Yingshun Cui --- .../sriov/vIOMMU/migration_iommu_device.cfg | 1 + .../sriov/vIOMMU/migration_iommu_device.py | 1 + provider/migration/base_steps.py | 30 +++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/libvirt/tests/cfg/sriov/vIOMMU/migration_iommu_device.cfg b/libvirt/tests/cfg/sriov/vIOMMU/migration_iommu_device.cfg index d0994e5931b..97ac59f6189 100644 --- a/libvirt/tests/cfg/sriov/vIOMMU/migration_iommu_device.cfg +++ b/libvirt/tests/cfg/sriov/vIOMMU/migration_iommu_device.cfg @@ -24,6 +24,7 @@ virsh_migrate_desturi = "qemu+ssh://${migrate_dest_host}/system" virsh_migrate_connect_uri = "qemu:///system" check_network_accessibility_after_mig = "yes" + check_cont_ping = "yes" disk_driver = {'name': 'qemu', 'type': 'qcow2', 'iommu': 'on'} variants: - virtio: diff --git a/libvirt/tests/src/sriov/vIOMMU/migration_iommu_device.py b/libvirt/tests/src/sriov/vIOMMU/migration_iommu_device.py index eacf4c17dc2..a246bbc9dc0 100644 --- a/libvirt/tests/src/sriov/vIOMMU/migration_iommu_device.py +++ b/libvirt/tests/src/sriov/vIOMMU/migration_iommu_device.py @@ -85,5 +85,6 @@ def setup_test(): test.log.info("TEST_STEP: Migrate back the VM to the source host.") migration_obj.run_migration_back() migration_obj.migration_test.ping_vm(vm, params) + migration_obj.check_vm_cont_ping(False) finally: test_obj.teardown_iommu_test() diff --git a/provider/migration/base_steps.py b/provider/migration/base_steps.py index 2c2db7be67a..f2219c7aaa1 100644 --- a/provider/migration/base_steps.py +++ b/provider/migration/base_steps.py @@ -49,6 +49,8 @@ def __init__(self, test, vm, params): self.src_full_uri = libvirt_vm.complete_uri( self.params.get("migrate_source_host")) self.conn_list = [] + self.check_cont_ping = "yes" == self.params.get("check_cont_ping", "no") + self.check_cont_ping_log = self.params.get("check_cont_ping_log", "/tmp/log_file") self.remote_libvirtd_log = None migration_test = migration.MigrationTest() @@ -91,6 +93,11 @@ def setup_default(self): if start_vm == "yes" and not self.vm.is_alive(): self.vm.start() self.vm.wait_for_login().close() + if self.check_cont_ping: + self.test.log.debug("Starting ping command to check network during migration...") + vm_session = self.vm.wait_for_login() + ping_cmd = "ping 8.8.8.8 > %s 2>&1 &" % self.check_cont_ping_log + vm_session.sendline(ping_cmd) def run_migration(self): """ @@ -272,6 +279,28 @@ def run_migration_back(self): % (cmd, cmd_result)) self.vm.connect_uri = self.src_uri + def check_vm_cont_ping(self, check_on_dest=True): + """ + Check continuous ping command in VM + + :param check_on_dest: Check whether on the destination machine + """ + dest_uri = self.params.get("virsh_migrate_desturi") + if self.check_cont_ping: + self.test.log.debug("Checking the output of %s", self.check_cont_ping_log) + if check_on_dest: + backup_uri, self.vm.connect_uri = self.vm.connect_uri, dest_uri + self.vm.cleanup_serial_console() + self.vm.create_serial_console() + vm_session = self.vm.wait_for_serial_login(timeout=360) + vm_session.cmd( + "> {0}; sleep 5; grep time= {0}".format(self.check_cont_ping_log)) + o = vm_session.cmd_output(f"cat {self.check_cont_ping_log}") + self.test.log.debug(f"ping command output: {o}") + vm_session.close() + if check_on_dest: + self.vm.connect_uri = backup_uri + def verify_default(self): """ Verify steps by default @@ -286,6 +315,7 @@ def verify_default(self): if int(self.migration_test.ret.exit_status) == 0: self.migration_test.post_migration_check([self.vm], self.params, dest_uri=dest_uri, src_uri=self.src_uri) + self.check_vm_cont_ping(check_on_dest=True) self.check_local_and_remote_log() def cleanup_default(self): From 7212eb0f01adeadc0574ba5aba51c32963c1035b Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Fri, 28 Feb 2025 09:38:16 -0500 Subject: [PATCH 0862/1055] virsh_restore: fix script by adding default value cca78d281bbe06462aace28cbe59b120007a5aa3 introduced a new test parameter but didn't provide a default value, leading to problems when reading the value. Add default value empty dictionary like the local parameter it replaced at some places. This way the added code is just skipped if not necessary. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/virsh_cmd/domain/virsh_restore.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_restore.py b/libvirt/tests/src/virsh_cmd/domain/virsh_restore.py index 55dcc39728b..8bcb224079c 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_restore.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_restore.py @@ -65,7 +65,7 @@ def check_file_own(file_path, exp_uid, exp_gid): check_log = params.get("check_log") check_str_not_in_log = params.get("check_str_not_in_log") qemu_conf_dict = eval(params.get("qemu_conf_dict", "{}")) - os_update_dict = eval(params.get("os_update_dict")) + os_update_dict = eval(params.get("os_update_dict", "{}")) vm_ref_uid = None vm_ref_gid = None From 30673e39975bc7b258d86fd5d2d659647360a821 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 14 Jan 2025 11:36:35 -0500 Subject: [PATCH 0863/1055] guest_os_booting: update tests for s390x The following features are not available on s390x: * SMBIOS * ACPI * fw_cfg * USB * * firmware settings * SATA For direct kernel boot, don't use hard coded kernel filename. In our setup we'll use kernel.img, so just use the filename from the download url. Don't use ttyS0, it's the line mode console which is not useful. Using ttysclp0 is the standard on s390x. Cover also s390x-specific parameter @loadparm by allowing generically to run a test command in the booted VM whose output should match an expected regular expression. On s390x, the VM will stop if no bootable medium - such as missing cdrom file - is found. Some tests were written assuming the VM would use the //os/boot element instead of the per-device element by trying to remove only that element. Instead just remove all present boot elements in these cases, no matter where, the test will define the new one that's relevant for the test case. In some boot tests also enable boot for VMs without Secure Boot, where there's no firmware. Add test case that attaches two bootable disks. They must not both have the same VG name; this would be an invalid setup leading to issues during boot. Therefore, instead assume there's a bootable disk with standard partition available under new parameter as this issue can't happen with standard partitions. s390x currently doesn't have secure boot. Use the first VM and don't set os attributes that relate to secure boot on other archs. Implement logic to actually load into the installer via PXE. Move s390x PXE setup to provider for reuse in boot order tests. Allow for pxelinux.cfg without kickstart, for the boot check we don't need it. Also, a network boot requires more RAM, so update if configured. Signed-off-by: Sebastian Mitterle --- .../boot_order/boot_from_cdrom_device.cfg | 10 +- .../boot_order/boot_from_disk_device.cfg | 9 ++ .../boot_with_multiple_boot_dev.cfg | 1 + .../boot_with_multiple_boot_order.cfg | 50 +++++++- .../hotplug_device_with_boot_order.cfg | 2 + .../direct_kernel_boot/direct_kernel_boot.cfg | 2 + .../firmware_configuration/os_acpi.cfg | 2 +- .../firmware_configuration/smbios_mode.cfg | 1 + .../firmware_configuration/sysinfo_fwcfg.cfg | 1 + .../migration/migration_boot.cfg | 1 + .../boot_order/boot_from_cdrom_device.py | 4 +- .../boot_order/boot_from_disk_device.py | 42 ++++--- .../boot_with_multiple_boot_order.py | 29 ++++- .../direct_kernel_boot/direct_kernel_boot.py | 4 +- .../guest_os_booting/guest_os_booting_base.py | 4 + provider/virtual_network/tftpboot.py | 109 ++++++++++++++++++ .../src/virt_install/pxe_installation.py | 78 +------------ 17 files changed, 247 insertions(+), 102 deletions(-) create mode 100644 provider/virtual_network/tftpboot.py diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg index 0b820f8dadb..6fb06cbe2cf 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg @@ -7,6 +7,7 @@ - without_cdrom: only os_dev - with_cdrom_with_no_src: + no s390-virtio cdrom1_attrs = {'target': {'dev': 'sda', 'bus': 'sata'}, **${cdrom_attrs}} aarch64: cdrom1_attrs = {'target': {'dev': 'sda', 'bus': 'scsi'}, **${cdrom_attrs}} @@ -14,19 +15,20 @@ - with_cdrom: check_bootable_iso = "yes" cdrom1_attrs = {'source': {'attrs': {'file': boot_img_path}}, 'target': {'dev': 'sda', 'bus': 'scsi'}, **${cdrom_attrs}} - bootable_patterns = ["begin the installation process|Install Red Hat Enterprise"] + bootable_patterns = ["begin the installation process|Install Red Hat Enterprise|Starting installer"] - multi_cdroms: cdrom1_attrs = {'target': {'dev': 'sda', 'bus': 'scsi'}, **${cdrom_attrs}} cdrom2_attrs = {'source': {'attrs': {'file': boot_img_path}}, 'target': {'dev': 'sdb', 'bus': 'sata'}, **${cdrom_attrs}} - aarch64: + aarch64, s390-virtio: cdrom2_attrs = {'source': {'attrs': {'file': boot_img_path}}, 'target': {'dev': 'sdb', 'bus': 'scsi'}, **${cdrom_attrs}} cdrom_boot_order: check_bootable_iso = "yes" - bootable_patterns = ["begin the installation process|Install Red Hat Enterprise"] + bootable_patterns = ["begin the installation process|Install Red Hat Enterprise|Starting installer"] os_dev: status_error = "yes" variants: - os_dev: + no s390-virtio os_attrs_boots = ['cdrom'] - cdrom_boot_order: variants firmware_type: @@ -36,3 +38,5 @@ status_error = "yes" - ovmf: only q35, aarch64 + - no_firmware: + only s390-virtio diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_disk_device.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_disk_device.cfg index 0f913912b45..1b2e23d087d 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_disk_device.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_disk_device.cfg @@ -4,6 +4,7 @@ disk1_attrs_target = {'dev': 'vda', 'bus': 'virtio'} variants: - os_dev: + no s390-virtio os_attrs_boots = ['hd'] disk1_attrs = {'target': ${disk1_attrs_target}} variants: @@ -24,8 +25,16 @@ disk2_attrs = {'target': {'dev': 'sda', 'bus': 'scsi'}} seabios: status_error = "yes" + - multi_disks_bootable: + download_disk1_img = yes + disk1_img_url = + disk1_img = "bootable_standard_partitions.qcow2" + disk1_attrs = {'target': ${disk1_attrs_target}} + disk2_attrs = {'target': {'dev': 'sda', 'bus': 'scsi'}} variants firmware_type: - seabios: only x86_64 - ovmf: only q35, aarch64 + - no_firmware: + only s390-virtio diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_dev.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_dev.cfg index ad60e5d8c9f..32a76da3701 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_dev.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_dev.cfg @@ -8,6 +8,7 @@ os_dict = {'boots': ['%s', '%s'], 'bootmenu_enable': 'yes'} cdrom_dict = {'source': {'attrs': {'file': '%s'}}, 'type_name': 'file', 'device': 'cdrom', 'driver': {'name': 'qemu', 'type': 'raw'}, 'target': {'dev': 'sda', 'bus': '${target_bus}'}} check_prompt = ["begin the installation process|Install Red Hat Enterprise"] + no s390-virtio variants first_dev: - hd: variants second_dev: diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_order.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_order.cfg index 8821b5f6f64..18c7d71dc1d 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_order.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_with_multiple_boot_order.cfg @@ -6,8 +6,11 @@ aarch64: os_dict = {'bootmenu_enable': 'yes'} target_bus = 'scsi' + s390-virtio: + os_dict = {'bootmenu_enable': 'no'} + target_bus = 'scsi' cdrom_dict = {'source': {'attrs': {'file': '%s'}}, 'type_name': 'file', 'device': 'cdrom', 'driver': {'name': 'qemu', 'type': 'raw'}, 'target': {'dev': 'sda', 'bus': '${target_bus}'}} - check_prompt = ["begin the installation process|Install Red Hat Enterprise"] + check_prompt = ["begin the installation process|Install Red Hat Enterprise|Starting installer"] variants first_dev: - hd: disk_order = {'boot': '1'} @@ -16,6 +19,13 @@ cdrom_order = {'boot': '2'} variants bootable_device: - hd_bootable: + variants: + - @default: + - with_loadparm: + only s390-virtio + disk_order = {'boot': '1', 'loadparm': '1'} + test_cmd = "lsreipl" + expected_output = Loadparm:\s+"1" - cdrom_bootable: - network: network_order = {'boot': '2'} @@ -23,6 +33,12 @@ - hd_bootable: - network_bootable: check_prompt = ["iPXE initialising devices|Start PXE over IPv4"] + s390-virtio: + set_up_tftp = yes + check_prompt = ["Starting installer"] + install_tree_url = INSTALL_TREE_URL + network_order = {'boot': '2', 'source': {'network': 'tftpnet'}} + vm_memory = 1953125 - cdrom: cdrom_order = {'boot': '1'} variants second_dev: @@ -30,6 +46,13 @@ disk_order = {'boot': '2'} variants bootable_device: - hd_bootable: + variants: + - @default: + - with_loadparm: + only s390-virtio + disk_order = {'boot': '2', 'loadparm': '2'} + test_cmd = "lsreipl" + expected_output = Loadparm:\s+"2" - cdrom_bootable: - network: network_order = {'boot': '2'} @@ -37,6 +60,12 @@ - cdrom_bootable: - network_bootable: check_prompt = ["iPXE initialising devices|Start PXE over IPv4"] + s390-virtio: + set_up_tftp = yes + check_prompt = ["Starting installer"] + install_tree_url = INSTALL_TREE_URL + network_order = {'boot': '2', 'source': {'network': 'tftpnet'}} + vm_memory = 1953125 - network: network_order = {'boot': '1'} variants second_dev: @@ -44,11 +73,30 @@ disk_order = {'boot': '2'} variants bootable_device: - hd_bootable: + variants: + - @default: + - with_loadparm: + only s390-virtio + disk_order = {'boot': '2', 'loadparm': '2'} + test_cmd = "lsreipl" + expected_output = Loadparm:\s+"2" - network_bootable: check_prompt = ["iPXE initialising devices|Start PXE over IPv4"] + s390-virtio: + set_up_tftp = yes + check_prompt = ["Starting installer"] + install_tree_url = INSTALL_TREE_URL + network_order = {'boot': '1', 'source': {'network': 'tftpnet'}} + vm_memory = 1953125 - cdrom: cdrom_order = {'boot': '2'} variants bootable_device: - cdrom_bootable: - network_bootable: check_prompt = ["iPXE initialising devices|Start PXE over IPv4"] + s390-virtio: + set_up_tftp = yes + check_prompt = ["Starting installer"] + install_tree_url = INSTALL_TREE_URL + network_order = {'boot': '1', 'source': {'network': 'tftpnet'}} + vm_memory = 1953125 diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/hotplug_device_with_boot_order.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/hotplug_device_with_boot_order.cfg index 2722ca402f8..9dfa2607510 100644 --- a/libvirt/tests/cfg/guest_os_booting/boot_order/hotplug_device_with_boot_order.cfg +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/hotplug_device_with_boot_order.cfg @@ -13,6 +13,8 @@ bus_type = "usb" target_disk = "sda" device_dict = {"type_name":"file", "target":{"dev": "${target_disk}", "bus": "${bus_type}"}, 'boot': '2'} + s390-virtio: + expected_error = unsupported configuration: This QEMU doesn't support - filesystem_device: target_dir = "mount_tag" source_dir = "/tmp" diff --git a/libvirt/tests/cfg/guest_os_booting/direct_kernel_boot/direct_kernel_boot.cfg b/libvirt/tests/cfg/guest_os_booting/direct_kernel_boot/direct_kernel_boot.cfg index 563c2522445..4d4a51340cf 100644 --- a/libvirt/tests/cfg/guest_os_booting/direct_kernel_boot/direct_kernel_boot.cfg +++ b/libvirt/tests/cfg/guest_os_booting/direct_kernel_boot/direct_kernel_boot.cfg @@ -6,6 +6,8 @@ initrd_url = "${repo_url}/images/pxeboot/initrd.img" vmlinuz_url = "${repo_url}/images/pxeboot/vmlinuz" direct_kernel_dict = {'cmdline': 'console=ttyS0 inst.repo=${repo_url}', 'initrd': '%s', 'kernel': '%s'} + s390-virtio: + direct_kernel_dict = {'cmdline': 'console=ttysclp0 inst.repo=${repo_url}', 'initrd': '%s', 'kernel': '%s'} variants: - start_guest: check_prompt = "Starting installer" diff --git a/libvirt/tests/cfg/guest_os_booting/firmware_configuration/os_acpi.cfg b/libvirt/tests/cfg/guest_os_booting/firmware_configuration/os_acpi.cfg index 20d6384228b..8cf656f467c 100644 --- a/libvirt/tests/cfg/guest_os_booting/firmware_configuration/os_acpi.cfg +++ b/libvirt/tests/cfg/guest_os_booting/firmware_configuration/os_acpi.cfg @@ -4,7 +4,7 @@ acpi_url = "EXAMPLE_ACPI_URL" acpi_file = "slic.dat" acpi_dict = {'acpi': {'table_type': 'slic', 'table': '%s'}} - no aarch64 + no aarch64, s390-virtio variants: - start_guest: cmd_in_guest = "acpidump" diff --git a/libvirt/tests/cfg/guest_os_booting/firmware_configuration/smbios_mode.cfg b/libvirt/tests/cfg/guest_os_booting/firmware_configuration/smbios_mode.cfg index 88eda2e886f..e0a034ed820 100644 --- a/libvirt/tests/cfg/guest_os_booting/firmware_configuration/smbios_mode.cfg +++ b/libvirt/tests/cfg/guest_os_booting/firmware_configuration/smbios_mode.cfg @@ -1,6 +1,7 @@ - guest_os_booting.smbios_mode: type = smbios_mode start_vm = no + no s390-virtio variants: - positive_test: variants smbios_mode: diff --git a/libvirt/tests/cfg/guest_os_booting/firmware_configuration/sysinfo_fwcfg.cfg b/libvirt/tests/cfg/guest_os_booting/firmware_configuration/sysinfo_fwcfg.cfg index a9d57e5fe1c..32970c35e22 100644 --- a/libvirt/tests/cfg/guest_os_booting/firmware_configuration/sysinfo_fwcfg.cfg +++ b/libvirt/tests/cfg/guest_os_booting/firmware_configuration/sysinfo_fwcfg.cfg @@ -2,6 +2,7 @@ type = sysinfo_fwcfg start_vm = no entry_value = "example value" + no s390-virtio variants: - positive_test: variants: diff --git a/libvirt/tests/cfg/guest_os_booting/migration/migration_boot.cfg b/libvirt/tests/cfg/guest_os_booting/migration/migration_boot.cfg index 58e0e2895fa..7fd79d42f76 100644 --- a/libvirt/tests/cfg/guest_os_booting/migration/migration_boot.cfg +++ b/libvirt/tests/cfg/guest_os_booting/migration/migration_boot.cfg @@ -25,6 +25,7 @@ virsh_migrate_connect_uri = "qemu:///system" variants: - os_dev: + no s390-virtio os_attrs_boots = ['hd', 'cdrom', 'network'] - boot_order: disk_boot_idx = 1 diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py index d9f7572f3bb..4473f5ac1c4 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py @@ -56,9 +56,7 @@ def update_vm_xml(vm, params, cdrom_attrs_list): os_attrs = {'boots': os_attrs_boots} vmxml.setup_attrs(os=os_attrs) else: - vm_os = vmxml.os - vm_os.del_boots() - vmxml.os = vm_os + vmxml.remove_all_boots() if "yes" == params.get("check_bootable_iso", "no"): os_attrs.update({'bootmenu_enable': 'yes', 'bootmenu_timeout': '3000'}) diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_disk_device.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_disk_device.py index d6fecf2f7ac..66cf7a99d91 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_disk_device.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_disk_device.py @@ -3,34 +3,43 @@ from virttest import data_dir from virttest import remote +from virttest import utils_misc from virttest.libvirt_xml import vm_xml from virttest.libvirt_xml.devices import disk from virttest.utils_libvirt import libvirt_disk from virttest.utils_libvirt import libvirt_vmxml -from provider.guest_os_booting import guest_os_booting_base +from provider.guest_os_booting import guest_os_booting_base as guest_os -def parse_disks_attrs(vmxml, params): +def parse_disks_attrs(vmxml, test, params): """ Parse disk devices' attrs :param vmxml: The vmxml object :param params: Dictionary with the test parameters + :param test: test instance for error reporting :return: (Newly created disk image path, list of disk devices' attrs) """ - disk1_img = params.get('disk1_img') + disk1_img = params.get("disk1_img") disk_attrs_list = [] disk1_img_path = "" - disk_org_attrs = vmxml.devices.by_device_tag('disk')[0].fetch_attrs() - del disk_org_attrs['address'] + disk_org_attrs = vmxml.devices.by_device_tag("disk")[0].fetch_attrs() + del disk_org_attrs["address"] + disk1_img_url = params.get("disk1_img_url", "") + download_disk1_img = "yes" == params.get("download_disk1_img", "no") if disk1_img: - disk1_img_path = os.path.join(data_dir.get_data_dir(), 'images', - disk1_img) - libvirt_disk.create_disk('file', disk1_img_path, disk_format='qcow2') + disk1_img_path = os.path.join(data_dir.get_data_dir(), "images", disk1_img) + if download_disk1_img: + if not disk1_img_url or not utils_misc.wait_for( + lambda: guest_os.test_file_download(disk1_img_url, disk1_img_path), 60 + ): + test.fail("Unable to download boot image") + else: + libvirt_disk.create_disk("file", disk1_img_path, disk_format="qcow2") disk1_attrs = copy.deepcopy(disk_org_attrs) - disk1_attrs['source'] = {'attrs': {'file': disk1_img_path}} + disk1_attrs["source"] = {"attrs": {"file": disk1_img_path}} disk_attrs_list.append(disk1_attrs) disk_org_attrs.update(eval(params.get("disk2_attrs", "{}"))) @@ -48,11 +57,11 @@ def update_vm_xml(vm, params, disk_attrs_list): :param params: Dictionary with the test parameters :param disk_attrs_list: List of disk devices' attrs """ - os_attrs_boots = eval(params.get('os_attrs_boots', '[]')) - libvirt_vmxml.remove_vm_devices_by_type(vm, 'disk') + os_attrs_boots = eval(params.get("os_attrs_boots", "[]")) + libvirt_vmxml.remove_vm_devices_by_type(vm, "disk") vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) if os_attrs_boots: - os_attrs = {'boots': os_attrs_boots} + os_attrs = {"boots": os_attrs_boots} vmxml.setup_attrs(os=os_attrs) else: vm_os = vmxml.os @@ -65,9 +74,8 @@ def update_vm_xml(vm, params, disk_attrs_list): disk_obj.setup_attrs(**disk_attrs) vmxml.add_device(disk_obj) index += 1 - if 'disk_boot_order' in params.get("shortname"): - vmxml.set_boot_order_by_target_dev( - disk_attrs['target']['dev'], index) + if "disk_boot_order" in params.get("shortname"): + vmxml.set_boot_order_by_target_dev(disk_attrs["target"]["dev"], index) vmxml.xmltreefile.write() vmxml.sync() @@ -77,7 +85,7 @@ def run(test, params, env): Boot VM from disk devices This case covers per-device(disk) boot elements and os/boot elements. """ - vm_name = guest_os_booting_base.get_vm(params) + vm_name = guest_os.get_vm(params) status_error = "yes" == params.get("status_error", "no") disk1_img_path = "" @@ -86,7 +94,7 @@ def run(test, params, env): bkxml = vmxml.copy() try: - disk1_img_path, disk_attrs_list = parse_disks_attrs(vmxml, params) + disk1_img_path, disk_attrs_list = parse_disks_attrs(vmxml, test, params) update_vm_xml(vm, params, disk_attrs_list) test.log.debug(vm_xml.VMXML.new_from_dumpxml(vm.name)) diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py index b3469f6bdd8..486360137c6 100644 --- a/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_with_multiple_boot_order.py @@ -1,8 +1,9 @@ # Copyright Red Hat # SPDX-License-Identifier: GPL-2.0 # Author: Meina Li - +import platform import os +import re from avocado.utils import process @@ -13,6 +14,7 @@ from virttest.utils_test import libvirt from provider.guest_os_booting import guest_os_booting_base as guest_os +from provider.virtual_network import tftpboot # Prepare a list to record the file path which need to be removed file_list = [] @@ -33,6 +35,8 @@ def prepare_device_attrs(test, params, vm_name, bootable_device): disk_order = eval(params.get("disk_order", "{}")) cdrom_order = eval(params.get("cdrom_order", "{}")) network_order = eval(params.get("network_order", "{}")) + set_up_tftp = "yes" == params.get("set_up_tftp", "no") + memory = params.get("vm_memory", "") disk_image = os.path.join(data_dir.get_data_dir(), 'images', 'test.img') vmxml = guest_os.prepare_os_xml(vm_name, os_dict) vmxml.remove_all_boots() @@ -51,11 +55,20 @@ def prepare_device_attrs(test, params, vm_name, bootable_device): else: cdrom_path = os.path.join(data_dir.get_data_dir(), 'images', 'test.iso') libvirt.create_local_disk("file", path=cdrom_path, size="500M", disk_format="raw") + if bootable_device == "network_bootable" and set_up_tftp: + install_tree_url = params.get("install_tree_url") + tftpboot.create_tftp_content(install_tree_url, + None, + arch=platform.machine()) + tftpboot.create_tftp_network() file_list.append(cdrom_path) cdrom_dict = eval(params.get("cdrom_dict") % cdrom_path) cdrom_dict.update(cdrom_order) cdrom_xml = libvirt_vmxml.create_vm_device_by_type("disk", cdrom_dict) vmxml.add_device(cdrom_xml) + if memory: + vmxml.memory = int(memory) + vmxml.current_mem = int(memory) vmxml.sync() # Update boot order attributes if "hd" in (first_dev, second_dev): @@ -74,10 +87,13 @@ def run(test, params, env): check_prompt = eval(params.get("check_prompt", "[]")) bootable_device = params.get("bootable_device") os_dict = eval(params.get("os_dict")) + test_cmd = params.get("test_cmd", None) + expected_output = params.get("expected_output", None) vm = env.get_vm(vm_name) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) bkxml = vmxml.copy() + session = None try: test.log.info("TEST_SETUP: prepare a guest with necessary attributes.") @@ -89,13 +105,22 @@ def run(test, params, env): test.log.debug(f"The current guest xml is: {vmxml}") test.log.info("TEST_STEP2: check the guest boot from expected device.") if bootable_device == "hd_bootable": - vm.wait_for_login(timeout=360).close() + session = vm.wait_for_login(timeout=360) test.log.debug("Succeed to boot %s", vm_name) + if test_cmd is not None: + output = session.cmd(test_cmd) + if not re.search(expected_output, output): + test.fail(f"Couldn't get {expected_output}, got instead {output}") + test.log.debug("Succeed to set %s", expected_output) + session.close() else: vm.serial_console.read_until_output_matches(check_prompt, timeout=300, internal_timeout=0.5) finally: + if session: + session.close() bkxml.sync() + tftpboot.cleanup() for file in file_list: if os.path.exists(file): os.remove(file) diff --git a/libvirt/tests/src/guest_os_booting/direct_kernel_boot/direct_kernel_boot.py b/libvirt/tests/src/guest_os_booting/direct_kernel_boot/direct_kernel_boot.py index 90124677cd2..77a70401e6e 100644 --- a/libvirt/tests/src/guest_os_booting/direct_kernel_boot/direct_kernel_boot.py +++ b/libvirt/tests/src/guest_os_booting/direct_kernel_boot/direct_kernel_boot.py @@ -35,8 +35,8 @@ def run(test, params, env): bkxml = vmxml.copy() try: - boot_initrd = os.path.join(data_dir.get_data_dir(), "initrd.img") - boot_vmlinuz = os.path.join(data_dir.get_data_dir(), "vmlinuz") + boot_initrd = os.path.join(data_dir.get_data_dir(), initrd_url.split("/")[-1]) + boot_vmlinuz = os.path.join(data_dir.get_data_dir(), vmlinuz_url.split("/")[-1]) url_download(initrd_url, boot_initrd) url_download(vmlinuz_url, boot_vmlinuz) direct_kernel_dict = eval(params.get("direct_kernel_dict") diff --git a/provider/guest_os_booting/guest_os_booting_base.py b/provider/guest_os_booting/guest_os_booting_base.py index 90c64d62172..9e637c2727d 100644 --- a/provider/guest_os_booting/guest_os_booting_base.py +++ b/provider/guest_os_booting/guest_os_booting_base.py @@ -1,4 +1,5 @@ import logging +import platform from avocado.core import exceptions from avocado.utils import distro @@ -25,6 +26,9 @@ def get_vm(params): firmware_type = params.get('firmware_type') detected_distro = distro.detect() os_type_dict = {} + if platform.machine() == "s390x": + return vms[0] + for _vm in vms: if os_type_dict.get("seabios") and os_type_dict.get("ovmf"): break diff --git a/provider/virtual_network/tftpboot.py b/provider/virtual_network/tftpboot.py new file mode 100644 index 00000000000..6b3d14dfabe --- /dev/null +++ b/provider/virtual_network/tftpboot.py @@ -0,0 +1,109 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# See LICENSE for more details. +# +# Copyright: Red Hat Inc. 2024 +# Author: Sebastian Mitterle +import logging as log +import os + +from avocado.utils import process +from virttest import virsh +from virttest.utils_test import libvirt + +logging = log.getLogger("avocado." + __name__) + +tftp_dir = "/var/lib/tftpboot" +boot_file = "pxelinux.cfg" +net_name = "tftpnet" + +cleanup_actions = [] + + +def create_tftp_content(install_tree_url, kickstart_url, arch): + """ + Creates the folder for the tftp server, + downloads images assuming they are below /images, + and creates the pxe configuration file + + :param install_tree_url: url of the installation tree + :param kickstart_url: url of the kickstart file + :param arch: the architecture + """ + + if arch != "s390x": + raise NotImplementedError(f"No implementation available for '{arch}'.") + + process.run("mkdir " + tftp_dir, ignore_status=False, shell=True, verbose=True) + cleanup_actions.insert(0, lambda: process.run("rm -rf " + tftp_dir, ignore_status=False, shell=True, verbose=True)) + + pxeconfig_content = """# pxelinux +default linux +label linux +kernel kernel.img +initrd initrd.img +""" + kernel_cmdline = ("append ip=dhcp inst.repo=%s inst.noverifyssl" + % install_tree_url) + if kickstart_url: + kernel_cmdline += " inst.ks=%s" % kickstart_url + else: + logging.debug("Create pxelinux.cfg without kickstart.") + pxeconfig_content += kernel_cmdline + + with open(os.path.join(tftp_dir, boot_file), "w") as f: + f.write(pxeconfig_content) + + cmds = [] + + initrd_img_url = install_tree_url + "/images/initrd.img" + kernel_img_url = install_tree_url + "/images/kernel.img" + + cmds.append("curl %s -o %s/initrd.img" % (initrd_img_url, tftp_dir)) + cmds.append("curl %s -o %s/kernel.img" % (kernel_img_url, tftp_dir)) + + cmds.append("chmod -R a+r " + tftp_dir) + cmds.append("chown -R nobody: " + tftp_dir) + cmds.append("chcon -R --reference /usr/sbin/dnsmasq " + tftp_dir) + cmds.append("chcon -R --reference /usr/libexec/libvirt_leaseshelper " + tftp_dir) + + for cmd in cmds: + process.run(cmd, ignore_status=False, shell=True, verbose=True) + + +def create_tftp_network(): + """ + Creates a libvirt network that will serve + the tftp content + """ + + net_params = { + "net_forward": "{'mode':'nat'}", + "net_ip_address": "192.168.150.1", + "dhcp_start_ipv4": "192.168.150.2", + "dhcp_end_ipv4": "192.168.150.254", + "tftp_root": tftp_dir, + "bootp_file": boot_file + } + + net_xml = libvirt.create_net_xml(net_name, net_params) + virsh.net_create(net_xml.xml, debug=True, ignore_status=False) + cleanup_actions.insert(0, lambda: virsh.net_destroy(net_name)) + + +def cleanup(): + """ + Runs registered clean up actions + """ + for action in cleanup_actions: + try: + action() + except: + logging.debug("There were errors during cleanup. Please check the log.") diff --git a/virttools/tests/src/virt_install/pxe_installation.py b/virttools/tests/src/virt_install/pxe_installation.py index 64f961ddb8a..4e1260f616c 100644 --- a/virttools/tests/src/virt_install/pxe_installation.py +++ b/virttools/tests/src/virt_install/pxe_installation.py @@ -1,82 +1,13 @@ import logging as log -import os -from avocado.utils import process - -from virttest import virsh from virttest.utils_misc import cmd_status_output -from virttest.utils_test import libvirt +from provider.virtual_network import tftpboot logging = log.getLogger("avocado." + __name__) cleanup_actions = [] -tftp_dir = "/var/lib/tftpboot" -boot_file = "pxelinux.cfg" -net_name = "tftpnet" - - -def create_tftp_content(install_tree_url, kickstart_url): - """ - Creates the folder for the tftp server, - downloads images assuming they are below /images, - and creates the pxe configuration file - - :param install_tree_url: url of the installation tree - :param kickstart_url: url of the kickstart file - """ - - process.run("mkdir " + tftp_dir, ignore_status=False, shell=True, verbose=True) - cleanup_actions.insert(0, lambda: process.run("rm -rf " + tftp_dir, ignore_status=False, shell=True, verbose=True)) - - pxeconfig_content = """# pxelinux -default linux -label linux -kernel kernel.img -initrd initrd.img -append ip=dhcp inst.repo=%s inst.ks=%s inst.noverifyssl -""" % (install_tree_url, kickstart_url) - - with open(os.path.join(tftp_dir, boot_file), "w") as f: - f.write(pxeconfig_content) - - cmds = [] - - initrd_img_url = install_tree_url + "/images/initrd.img" - kernel_img_url = install_tree_url + "/images/kernel.img" - - cmds.append("curl %s -o %s/initrd.img" % (initrd_img_url, tftp_dir)) - cmds.append("curl %s -o %s/kernel.img" % (kernel_img_url, tftp_dir)) - - cmds.append("chmod -R a+r " + tftp_dir) - cmds.append("chown -R nobody: " + tftp_dir) - cmds.append("chcon -R --reference /usr/sbin/dnsmasq " + tftp_dir) - cmds.append("chcon -R --reference /usr/libexec/libvirt_leaseshelper " + tftp_dir) - - for cmd in cmds: - process.run(cmd, ignore_status=False, shell=True, verbose=True) - - -def create_tftp_network(): - """ - Creates a libvirt network that will serve - the tftp content - """ - - net_params = { - "net_forward": "{'mode':'nat'}", - "net_ip_address": "192.168.150.1", - "dhcp_start_ipv4": "192.168.150.2", - "dhcp_end_ipv4": "192.168.150.254", - "tftp_root": tftp_dir, - "bootp_file": boot_file - } - - net_xml = libvirt.create_net_xml(net_name, net_params) - virsh.net_create(net_xml.xml, debug=True, ignore_status=False) - cleanup_actions.insert(0, lambda: virsh.net_destroy(net_name)) - def run(test, params, env): """ @@ -89,8 +20,8 @@ def run(test, params, env): try: install_tree_url = params.get("install_tree_url") kickstart_url = params.get("kickstart_url") - create_tftp_content(install_tree_url, kickstart_url) - create_tftp_network() + tftpboot.create_tftp_content(install_tree_url, kickstart_url, arch="s390x") + tftpboot.create_tftp_network() cmd = ("virt-install --pxe --name %s" " --disk size=10" @@ -100,7 +31,7 @@ def run(test, params, env): " --wait 10" " --noreboot" " --network network=%s" % - (vm_name, net_name)) + (vm_name, tftpboot.net_name)) cmd_status_output(cmd, shell=True, timeout=600) logging.debug("Installation finished") @@ -117,6 +48,7 @@ def run(test, params, env): finally: if vm and vm.is_alive(): vm.destroy() + tftpboot.cleanup() for action in cleanup_actions: try: action() From 586be177e06559da0012007133383993d5582fd3 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Sat, 1 Mar 2025 15:47:00 +0800 Subject: [PATCH 0864/1055] virsh_restore: fix eval error Signed-off-by: Dan Zheng --- libvirt/tests/src/virsh_cmd/domain/virsh_restore.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_restore.py b/libvirt/tests/src/virsh_cmd/domain/virsh_restore.py index 55dcc39728b..8bcb224079c 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_restore.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_restore.py @@ -65,7 +65,7 @@ def check_file_own(file_path, exp_uid, exp_gid): check_log = params.get("check_log") check_str_not_in_log = params.get("check_str_not_in_log") qemu_conf_dict = eval(params.get("qemu_conf_dict", "{}")) - os_update_dict = eval(params.get("os_update_dict")) + os_update_dict = eval(params.get("os_update_dict", "{}")) vm_ref_uid = None vm_ref_gid = None From fe90e1865c6235098b7539cd3c0cf93b0b6bc325 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Thu, 27 Feb 2025 04:26:39 -0500 Subject: [PATCH 0865/1055] Change audit log search cmd ausearch cmd may not get result during automation, so change cmd to search audit log directly. Signed-off-by: liang-cong-red-hat --- .../tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg | 2 +- libvirt/tests/cfg/memory/memory_devices/dimm_memory_hotplug.cfg | 2 +- .../tests/cfg/memory/memory_devices/virtio_mem_hot_unplug.cfg | 2 +- libvirt/tests/cfg/memory/memory_devices/virtio_mem_hotplug.cfg | 2 +- libvirt/tests/cfg/memory/memory_misc.cfg | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg index bcbc03fd04e..cb5cfb7bc1b 100644 --- a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hot_unplug.cfg @@ -14,7 +14,7 @@ max_mem = 4194304 max_mem_slots = 16 slot = '0' - audit_cmd = "ausearch -m VIRT_RESOURCE | grep 'mem' | tail -n 30" + audit_cmd = "grep VIRT_RESOURCE /var/log/audit/audit.log | grep 'mem' | tail -n 20" ausearch_check = 'old-mem=%d new-mem=%d' expected_log = "ACPI_DEVICE_OST|device_del" kernel_hp_file = '/sys/devices/system/node/node0/hugepages/hugepages-%skB/nr_hugepages' diff --git a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hotplug.cfg b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hotplug.cfg index e6691180e6e..a9ea437e7e2 100644 --- a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hotplug.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_hotplug.cfg @@ -17,7 +17,7 @@ max_mem = 4194304 max_mem_slots = 16 plug_event = "device-added" - audit_cmd = "ausearch --start today -m VIRT_RESOURCE | grep 'mem'" + audit_cmd = "grep VIRT_RESOURCE /var/log/audit/audit.log | grep 'mem' | tail -n 20" ausearch_check = 'old-mem=%d new-mem=%d' expected_log = "ACPI_DEVICE_OST|device_add" kernel_hp_file = '/sys/devices/system/node/node0/hugepages/hugepages-%skB/nr_hugepages' diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hot_unplug.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hot_unplug.cfg index 0e042b46b47..9588a04f610 100644 --- a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hot_unplug.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hot_unplug.cfg @@ -27,7 +27,7 @@ addr_dict = "'address':{'attrs': {'base': '${base}'}}" kernel_extra_params_add = "memhp_default_state=online_movable" unplug_event = "device-removed" - audit_cmd = "ausearch --start today -m VIRT_RESOURCE | grep 'mem'" + audit_cmd = "grep VIRT_RESOURCE /var/log/audit/audit.log | grep 'mem' | tail -n 20" ausearch_check = 'old-mem=%d new-mem=%d' expected_log = "device_del" kernel_hp_file = '/sys/devices/system/node/node0/hugepages/hugepages-%skB/nr_hugepages' diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hotplug.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hotplug.cfg index adbde97b91f..c12e23461be 100644 --- a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hotplug.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hotplug.cfg @@ -23,7 +23,7 @@ max_mem = 4194304 max_mem_slots = 16 plug_event = "device-added" - audit_cmd = "ausearch --start today -m VIRT_RESOURCE | grep 'mem'" + audit_cmd = "grep VIRT_RESOURCE /var/log/audit/audit.log | grep 'mem' | tail -n 20" ausearch_check = 'old-mem=%d new-mem=%d' expected_log = "device_add" kernel_hp_file = '/sys/devices/system/node/node0/hugepages/hugepages-%skB/nr_hugepages' diff --git a/libvirt/tests/cfg/memory/memory_misc.cfg b/libvirt/tests/cfg/memory/memory_misc.cfg index fe8da3b220a..3ac1c9f2478 100644 --- a/libvirt/tests/cfg/memory/memory_misc.cfg +++ b/libvirt/tests/cfg/memory/memory_misc.cfg @@ -203,7 +203,7 @@ cpu_attrs = {'mode': 'host-passthrough', 'numa_cell': [{'id': '0', 'cpus': '0,2', 'memory': '${numa_node_size}', 'unit': 'KiB'}, {'id': '1', 'cpus': '1,3', 'memory': '${numa_node_size}', 'unit': 'KiB'}]} dimm_device_1_attrs = {'mem_model': 'dimm', 'target': {'size': ${at_size}, 'size_unit': 'KiB', 'node': 1}} dimm_device_0_attrs = {'mem_model': 'dimm', 'target': {'size': 0, 'size_unit': 'KiB', 'node': 0}} - audit_cmd = ausearch -ts recent -m VIRT_RESOURCE| grep 'mem' + audit_cmd = grep VIRT_RESOURCE /var/log/audit/audit.log | grep 'mem' | tail -n 20 error_msg = "unable to execute QEMU command 'object-add':.*memory-backend-ram.* doesn't take value '0'" dominfo_check_0 = 'Max memory:\s+%d KiB\nUsed memory:\s+%d KiB' dominfo_check_1 = 'Max memory:\s+%d KiB\nUsed memory:\s+%d KiB' From 596cfde574dffc6135591c654e33e1e859833ab1 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Mon, 3 Mar 2025 03:57:53 -0500 Subject: [PATCH 0866/1055] passt:Update code of checking nameserver to fix error Remove irrelevant info such as "search" from output of resolv.conf to avoid inconsistency of nameserver between host and vm. Signed-off-by: Haijiao Zhao --- provider/virtual_network/passt.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/provider/virtual_network/passt.py b/provider/virtual_network/passt.py index 5ece902d511..5985dc0177d 100644 --- a/provider/virtual_network/passt.py +++ b/provider/virtual_network/passt.py @@ -276,11 +276,18 @@ def check_nameserver(session): :param session: vm shell session instance """ get_cmd = 'cat /etc/resolv.conf|grep -vE "#|;"' - on_host = process.run(get_cmd, shell=True).stdout_text.strip().split() - on_vm = session.cmd_output(get_cmd).strip().split() + on_host = process.run(get_cmd, shell=True).stdout_text.strip() + on_vm = session.cmd_output(get_cmd).strip() + LOG.debug(f'Output on host:\n{on_host}\nOutput on vm:\n{on_vm}') # remove zone index - on_host = [re.sub(r'%.*', '', x) for x in on_host] - on_vm = [re.sub(r'%.*', '', x) for x in on_vm] + on_host = [re.sub(r'%.*', '', x) for x in on_host.split()] + on_vm = [re.sub(r'%.*', '', x) for x in on_vm.split()] + # Remove irrelevant items such as "search" + on_host = set([(on_host[i], on_host[i + 1]) for i in range(len(on_host)) + if on_host[i].lower() == 'nameserver']) + on_vm = set([(on_vm[i], on_vm[i + 1]) for i in range(len(on_vm)) + if on_vm[i].lower() == 'nameserver']) + LOG.debug(f'On host:\n{on_host}\nOn vm:\n{on_vm}') if on_host == on_vm: LOG.debug(f'Nameserver on vm is consistent with host:\n{on_host}') else: From eb0f0d2a3b605382de5d6f429815ed2558e8c874 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 4 Mar 2025 13:31:41 +0800 Subject: [PATCH 0867/1055] serial: Add a hotplug/unplug case This PR adds: VIRT-304021: [aarch64 only][hotplug]hotplug/hotunplug system-serial serial device Signed-off-by: Yingshun Cui --- libvirt/tests/cfg/serial/serial_functional.cfg | 9 +++++++++ libvirt/tests/src/serial/serial_functional.py | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/libvirt/tests/cfg/serial/serial_functional.cfg b/libvirt/tests/cfg/serial/serial_functional.cfg index 49b04637c6f..a01240df9dd 100644 --- a/libvirt/tests/cfg/serial/serial_functional.cfg +++ b/libvirt/tests/cfg/serial/serial_functional.cfg @@ -52,6 +52,15 @@ only aarch64 serial_dev_type = pty target_type = system-serial + - type_file_system_serial: + only aarch64 + func_supported_since_libvirt_ver = (10, 10, 0) + serial_dev_type = file + target_model = pl011 + serial_sources = path:/var/lib/libvirt/virt-test + hotplug_serial = "yes" + hotunplug_serial = "yes" + error_msg = "unsupported configuration: Cannot {} platform device" - type_spicevmc: serial_dev_type = spicevmc - type_spiceport: diff --git a/libvirt/tests/src/serial/serial_functional.py b/libvirt/tests/src/serial/serial_functional.py index f83c8ceae97..f476d4beb17 100644 --- a/libvirt/tests/src/serial/serial_functional.py +++ b/libvirt/tests/src/serial/serial_functional.py @@ -738,6 +738,7 @@ def get_console_type(): elif serial_type in ['pipe']: return 'server' + libvirt_version.is_libvirt_feature_supported(params) serial_type = params.get('serial_dev_type', 'pty') sources_str = params.get('serial_sources', '') username = params.get('username') @@ -851,6 +852,16 @@ def get_console_type(): if error_msg not in result: test.fail(f"Fail to get expected error message:{error_msg} from console") + if params.get("hotunplug_serial", "no") == "yes": + error_msg = params.get("error_msg", "").format("detach") + res = virsh.detach_device(vm_name, serial_dev.xml, debug=True) + libvirt.check_result(res, error_msg) + + if params.get("hotplug_serial", "no") == "yes": + error_msg = params.get("error_msg", "").format("hotplug") + res = virsh.attach_device(vm_name, serial_dev.xml, debug=True) + libvirt.check_result(res, error_msg) + vm.destroy() finally: From 12414d8b27676775e47ffaa35607d166421f99d2 Mon Sep 17 00:00:00 2001 From: Meina Li Date: Tue, 4 Mar 2025 04:39:15 -0500 Subject: [PATCH 0868/1055] Snapshot: add datastore test scenarios to snapshot Automate case: VIRT-303301 - [Disk snapshot][External] Create/revert/delete external snapshots for guest whose disk has data file Signed-off-by: Meina Li --- .../snapshot/revert_disk_external_snap.cfg | 9 +++++++++ .../src/snapshot/revert_disk_external_snap.py | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/libvirt/tests/cfg/snapshot/revert_disk_external_snap.cfg b/libvirt/tests/cfg/snapshot/revert_disk_external_snap.cfg index 7bc00edbf1f..ee065f7ee23 100644 --- a/libvirt/tests/cfg/snapshot/revert_disk_external_snap.cfg +++ b/libvirt/tests/cfg/snapshot/revert_disk_external_snap.cfg @@ -4,6 +4,15 @@ snap_names = ['s1', 's2', 's3'] file_list = ["/mnt/s1", "/mnt/s2", "/mnt/s3"] func_supported_since_libvirt_ver = (9, 10, 0) + variants: + - with_datastore: + with_data_file = "yes" + disk_target = "vdb" + disk_type = "file" + disk_dict = {"type_name":"${disk_type}", "target":{"dev":"${disk_target}", "bus":"virtio"}, "driver": {"name":"qemu", "type":"qcow2"}} + func_supported_since_libvirt_ver = (10, 10, 0) + data_file_option = " -o data_file=%s" + - without_datastore: variants snap_type: - disk_only: snap_options = " %s --disk-only %s" diff --git a/libvirt/tests/src/snapshot/revert_disk_external_snap.py b/libvirt/tests/src/snapshot/revert_disk_external_snap.py index 12226500645..b530f43c647 100644 --- a/libvirt/tests/src/snapshot/revert_disk_external_snap.py +++ b/libvirt/tests/src/snapshot/revert_disk_external_snap.py @@ -7,12 +7,15 @@ # Author: Nannan Li # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import os +from virttest import data_dir from virttest import libvirt_version from virttest import virsh from virttest.libvirt_xml import vm_xml from provider.snapshot import snapshot_base +from provider.virtual_disk import disk_base virsh_dargs = {"debug": True, "ignore_status": False} @@ -51,7 +54,14 @@ def setup_test(): Prepare file and snapshot. """ test.log.info("TEST_SETUP: Create files and snaps in running guest.") + if with_data_file: + data_file = data_dir.get_data_dir() + "/datastore.img" + data_file_option = params.get("data_file_option", "") % data_file + image_path = disk_obj.add_vm_disk(disk_type, disk_dict, new_image_path="", + extra=data_file_option) + new_file.extend([data_file, image_path]) vm.start() + test.log.debug("The current guest xml is: %s", virsh.dumpxml(vm_name).stdout_text) session = vm.wait_for_serial_login() mem_file = " " for index, sname in enumerate(snap_names): @@ -85,6 +95,9 @@ def teardown_test(): Clean data. """ test.log.info("TEST_TEARDOWN: Clean up env.") + for file in new_file: + if os.path.exists(file): + os.remove(file) snap_names.reverse() test_obj.teardown_test() @@ -97,10 +110,16 @@ def teardown_test(): snap_type = params.get("snap_type") snap_options = params.get("snap_options") file_list = eval(params.get("file_list")) + disk_target = params.get("disk_target", "vdb") + disk_type = params.get("disk_type", "file") + disk_dict = eval(params.get("disk_dict", "{}")) + with_data_file = "yes" == params.get("with_data_file", "no") test_obj = snapshot_base.SnapshotTest(vm, test, params) + disk_obj = disk_base.DiskBase(test, vm, params) params.update({"test_obj": test_obj}) libvirt_version.is_libvirt_feature_supported(params) + new_file = [] try: setup_test() From 0f83077fbdbaf364a22792d47a267379158ed5ad Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 26 Aug 2024 19:18:56 +0800 Subject: [PATCH 0869/1055] migration: Add case to test migrate vm between 2 hosts with special CPU XXX-301817 - [VM migration] migrate vm between 2 hosts with special CPU Signed-off-by: lcheng --- .../migration_with_special_cpu.cfg | 46 +++ .../migration_with_special_cpu.py | 342 ++++++++++++++++++ 2 files changed, 388 insertions(+) create mode 100644 libvirt/tests/cfg/migration/migration_misc/migration_with_special_cpu.cfg create mode 100644 libvirt/tests/src/migration/migration_misc/migration_with_special_cpu.py diff --git a/libvirt/tests/cfg/migration/migration_misc/migration_with_special_cpu.cfg b/libvirt/tests/cfg/migration/migration_misc/migration_with_special_cpu.cfg new file mode 100644 index 00000000000..09c0f1f4cea --- /dev/null +++ b/libvirt/tests/cfg/migration/migration_misc/migration_with_special_cpu.cfg @@ -0,0 +1,46 @@ +- migration.migration_misc.migration_with_special_cpu: + type = migration_with_special_cpu + migration_setup = 'yes' + vms = avocado-vt-vm1 vm2 + start_vm = no + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + status_error = "no" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + cpu_mode = "host-model" + vm1_hostname = "test-mig-1" + vm2_hostname = "test-mig-2" + l2vm_name = "l2vm" + only x86_64 + variants: + - cpu_disable_vmx_apicv_register: + l1vm_feature_list = {"vmx": "require", "vmx-apicv-register": "disable"} + - cpu: + l1vm_feature_list = {"vmx": "require"} + variants: + - p2p: + virsh_migrate_options = '--live --p2p --verbose' + - non_p2p: + virsh_migrate_options = '--live --verbose' + variants: + - with_precopy: + - with_postcopy: + postcopy_options = '--postcopy --timeout 10 --timeout-postcopy' diff --git a/libvirt/tests/src/migration/migration_misc/migration_with_special_cpu.py b/libvirt/tests/src/migration/migration_misc/migration_with_special_cpu.py new file mode 100644 index 00000000000..abcc7923298 --- /dev/null +++ b/libvirt/tests/src/migration/migration_misc/migration_with_special_cpu.py @@ -0,0 +1,342 @@ +import os +import shutil + +from aexpect import remote + +from avocado.utils import process + +from virttest import data_dir +from virttest import migration +from virttest import nfs +from virttest import ssh_key +from virttest import utils_conn +from virttest import utils_disk +from virttest import utils_libvirtd +from virttest import utils_iptables +from virttest import utils_misc +from virttest import utils_net +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_nested +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +tcp_obj = None + + +def prepare_package_in_vm(vm): + """ + Prepare libvirt/qemu package in vm + + :param vm: VM object + """ + if not vm.is_alive(): + vm.start() + vm_session = vm.wait_for_login() + libvirt_nested.install_virt_pkgs(vm_session) + utils_libvirtd.Libvirtd(all_daemons=True, session=vm_session).restart() + vm_session.close() + + +def update_cpu_xml(vm_xml, cpu_mode, test, feature_list=None): + """ + Update cpu xml + + :param vm_xml: VM xml + :param cpu_mode: CPU mode + :param test: Test object + :param feature_list: Feature list + :return: New VM xml + """ + cpu_xml = vm_xml.cpu + cpu_xml.mode = cpu_mode + if feature_list: + for key, value in feature_list.items(): + try: + vmx_index = cpu_xml.get_feature_index(key) + except Exception as detail: + test.log.debug("Got a exception: %s", detail) + cpu_xml.add_feature(name=key, policy=value) + else: + cpu_xml.set_feature(vmx_index, name=key, policy=value) + vm_xml.cpu = cpu_xml + test.log.debug("cpu xml: %s", vm_xml.cpu) + vm_xml.sync() + return vm_xml + + +def prepare_env_in_vm(vm, vm_hostname, mount_src, mount_dir, desturi_port): + """ + Prepare env in vm + + :param vm: VM object + :param vm_hostname: VM hostname + :param mount_src: Mount source + :param mount_dir: Mount dir + :param desturi_port: Desturi port + """ + vm_session = vm.wait_for_login() + cmd = "mkdir -p %s" % mount_src + vm_session.cmd_status_output(cmd) + + cmd = "mkdir -p %s" % mount_dir + vm_session.cmd_status_output(cmd) + + cmd = "hostnamectl set-hostname %s" % vm_hostname + vm_session.cmd_status_output(cmd) + + cmd = "setsebool virt_use_nfs 1 -P" + vm_session.cmd_status_output(cmd) + + firewall_cmd = utils_iptables.Firewall_cmd(vm_session) + firewall_cmd.add_service('nfs', permanent=True) + firewall_cmd.add_port(desturi_port, 'tcp', permanent=True) + + vm_session.close() + + +def prepare_nfs_server_in_vm(vm_ip, params): + """ + Prepare nfs server in vm + + :param vm_ip: VM ip + :param params: Dictionary with the test parameters + """ + server_user = params.get("server_user", "root") + server_pwd = params.get("server_pwd") + mount_src = params.get("nfs_mount_src") + mount_dir = params.get("nfs_mount_dir") + + # prepare nfs server in vm + nfs_server_params = { + "nfs_setup": True, + "nfs_mount_dir": mount_dir, + "nfs_mount_src": mount_src, + "nfs_mount_options": params.get("nfs_mount_options"), + "nfs_server_ip": vm_ip, + "nfs_server_pwd": server_pwd, + "nfs_server_user": server_user, + "run_mount": False, + "setup_remote_nfs": "yes", + "export_options": params.get("export_options") + } + + nfs_server = nfs.Nfs(nfs_server_params) + nfs_server.setup() + + +def prepare_both_vms(params, vm1, vm2, vm1_xml, vm2_xml, test): + """ + Prepare vms + + :param params: Dictionary with the test parameters + :param vm1: VM1 object + :param vm2: VM2 object + :param vm1_xml: VM1 xml + :param vm2_xml: VM2 xml + :param test: Test object + """ + server_user = params.get("server_user", "root") + server_pwd = params.get("server_pwd") + client_user = params.get("client_user", "root") + client_pwd = params.get("client_pwd") + mount_src = params.get("nfs_mount_src") + mount_dir = params.get("nfs_mount_dir") + vm1_hostname = params.get("vm1_hostname") + vm2_hostname = params.get("vm2_hostname") + desturi_port = params.get("migrate_desturi_port") + cpu_mode = params.get("cpu_mode") + l1vm_feature_list = eval(params.get("l1vm_feature_list")) + + def prepare_single_vm(vm, vm_xml, vm_hostname, test): + vm_xml = update_cpu_xml(vm_xml, cpu_mode, test, l1vm_feature_list) + prepare_package_in_vm(vm) + prepare_env_in_vm(vm, vm_hostname, mount_src, mount_dir, desturi_port) + return vm.get_address() + + vm1_ip = prepare_single_vm(vm1, vm1_xml, vm1_hostname, test) + vm2_ip = prepare_single_vm(vm2, vm2_xml, vm2_hostname, test) + + ssh_key.setup_ssh_key(vm1_ip, server_user, server_pwd, 22) + ssh_key.setup_ssh_key(vm2_ip, client_user, client_pwd, 22) + ssh_key.setup_remote_ssh_key(vm1_ip, server_user, server_pwd, vm2_ip, client_user, client_pwd, port=22) + ssh_key.setup_remote_ssh_key(vm2_ip, client_user, client_pwd, vm1_ip, server_user, server_pwd, port=22) + + test.log.debug("Prepare nfs server in %s.", vm1_ip) + prepare_nfs_server_in_vm(vm1_ip, params) + + hosts_dict = {"%s" % vm1_hostname: "%s" % vm1_ip, "%s" % vm2_hostname: "%s" % vm2_ip} + mount_src = vm1_ip + ":" + mount_src + for vm in (vm1, vm2): + vm_session = vm.wait_for_login() + utils_disk.mount(mount_src, mount_dir, fstype="nfs", session=vm_session) + utils_net.map_hostname_ipaddress(hosts_dict, vm_session) + vm_session.close() + + return vm1_ip, vm2_ip + + +def run(test, params, env): + """ + This case is to verify that migration can succeed in a nested environment + which both source and target host have special CPU. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def setup_test(): + """ + Setup steps for cases + + """ + test.log.info("Setup steps for cases.") + + server_user = params.get("server_user", "root") + server_pwd = params.get("server_pwd") + mount_dir = params.get("nfs_mount_dir") + + nonlocal vm1_ip, vm2_ip + vm1_ip, vm2_ip = prepare_both_vms(params, vm1, vm2, vm1_xml, vm2_xml, test) + + # Prepare TCP connection in vm + params.update({"server_ip": vm2_ip}) + params.update({"client_ip": vm1_ip}) + global tcp_obj + tcp_obj = utils_conn.TCPConnection(params) + tcp_obj.conn_setup() + + test.log.debug("Prepare %s image.", l2vm_name) + disk_dict = {'source': {'attrs': {'file': (os.path.join(mount_dir, l2vm_name) + ".qcow2")}}} + l2vm_xml.vm_name = l2vm_name + libvirt_vmxml.modify_vm_device(l2vm_xml, 'disk', disk_dict, sync_vm=False) + remote.scp_to_remote(vm1_ip, '22', server_user, server_pwd, l2vm_img, mount_dir) + remote.scp_to_remote(vm1_ip, '22', server_user, server_pwd, l2vm_xml.xml, l2vm_xml.xml) + + dest_uri = "qemu+tcp://%s/system" % vm2_ip + migration_test.migrate_pre_setup(dest_uri, params) + + desturi = "qemu+ssh://%s/system" % vm1_ip + virsh.define(l2vm_xml.xml, uri=desturi, debug=True) + virsh.start(l2vm_name, uri=desturi, debug=True) + + def run_migration(): + """ + Run migration + + """ + postcopy_options = params.get("postcopy_options") + options = params.get("virsh_migrate_options") + + test.log.debug("Run migration.") + desturi = "qemu+ssh://%s/system" % vm1_ip + dest_uri = "qemu+tcp://%s/system" % vm2_ip + ret = virsh.migrate(l2vm_name, dest_uri=dest_uri, uri=desturi, option=options, extra=postcopy_options, debug=True) + libvirt.check_exit_status(ret) + + def verify_test(): + """ + Verify steps + + """ + def _check_l2vm_ip(): + ret = virsh.domifaddr(l2vm_name, uri=dest_uri, debug=True) + if "ipv4" in ret.stdout_text.strip(): + return True + else: + return False + + server_user = params.get("server_user", "root") + server_pwd = params.get("server_pwd") + + test.log.debug("Verify steps.") + dest_uri = "qemu+ssh://%s/system" % vm2_ip + utils_misc.wait_for(_check_l2vm_ip, timeout=120, step=5) + ret = virsh.domifaddr(l2vm_name, uri=dest_uri, debug=True) + l2vm_ip = ret.stdout_text.strip().split(" ")[-1].split("/")[0] + test.log.debug("l2vm_ip: %s", l2vm_ip) + + vm2_session = vm2.wait_for_login() + vm2_session.cmd_status_output("yum install sshpass -y") + status, out = vm2_session.cmd_status_output("sshpass -p %s ssh -o StrictHostKeyChecking=no %s@%s 'echo simple_disk_check >> /tmp/simple_disk_check'" % (server_pwd, server_user, l2vm_ip)) + vm2_session.close() + if status != 0: + test.fail("Failed to write l2vm: %s" % out) + + def cleanup_test(): + """ + Cleanup steps + + """ + test.log.debug("Cleanup test.") + global tcp_obj + if tcp_obj: + tcp_obj.auto_recover = True + del tcp_obj + + def revert_vm_setup(vm, vm_img, vm_img_bak): + if vm.is_alive(): + vm.destroy(gracefully=False) + shutil.copyfile(vm_img_bak, vm_img) + os.remove(vm_img_bak) + + bak_vm2_xml.sync() + if os.path.exists(l2vm_img): + os.remove(l2vm_img) + revert_vm_setup(vm2, vm2_img, vm2_img_bak) + revert_vm_setup(vm1, vm1_img, vm1_img_bak) + + #set server/client IP back to configured values + params.update({"server_ip": params.get("migrate_dest_host")}) + params.update({"client_ip": params.get("migrate_source_host")}) + + vms = params.get("vms").split() + if len(vms) >= 2: + vm1_name = vms[0] + vm2_name = vms[1] + else: + test.error("Wrong test configuration, there should be defined two VM names.") + + cpu_mode = params.get("cpu_mode") + l2vm_name = params.get("l2vm_name") + migration_test = migration.MigrationTest() + vm1_ip = vm2_ip = None + + cmd = "virsh domcapabilities |grep vmx- |wc -l" + ret = process.run(cmd, shell=True, verbose=True).stdout_text.strip() + if int(ret) < 76: + test.error(f"Tested CPU capability {eval(params.get('l1vm_feature_list'))} not available on host.") + + vm1 = env.get_vm(vm1_name) + vm2 = env.get_vm(vm2_name) + + vm1_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm1_name) + vm2_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm2_name) + bak_vm2_xml = vm2_xml.copy() + + l2vm_xml = vm1_xml.copy() + l2vm_xml = update_cpu_xml(l2vm_xml, cpu_mode, test) + + vm1_img = vm1.get_first_disk_devices()['source'] + vm2_img = vm2.get_first_disk_devices()['source'] + test.log.debug("vm1 img: %s", vm1_img) + test.log.debug("vm2 img: %s", vm2_img) + + # Backup l2vm image + l2vm_img = os.path.join(os.path.join(data_dir.get_data_dir(), 'images'), l2vm_name) + '.qcow2' + test.log.debug("l2vm img: %s", l2vm_img) + shutil.copyfile(vm1_img, l2vm_img) + # Backup vm1 image + vm1_img_bak = vm1_img + ".bak" + shutil.copyfile(vm1_img, vm1_img_bak) + # Backup vm2 image + vm2_img_bak = vm2_img + ".bak" + shutil.copyfile(vm2_img, vm2_img_bak) + + try: + setup_test() + run_migration() + verify_test() + finally: + cleanup_test() From cd19dab2bdca80b7a67c0d4b02afacc7f037d8f3 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 5 Mar 2025 18:28:36 +0800 Subject: [PATCH 0870/1055] scalability: Add a case about iommu and ioapic setting This PR adds: VIRT-303993: Define/Create guest with more than 255 vcpus Signed-off-by: Yingshun Cui --- .../define_create_vm_with_more_vcpus.cfg | 28 +++++++ .../define_create_vm_with_more_vcpus.py | 78 +++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 libvirt/tests/cfg/scalability/define_create_vm_with_more_vcpus.cfg create mode 100644 libvirt/tests/src/scalability/define_create_vm_with_more_vcpus.py diff --git a/libvirt/tests/cfg/scalability/define_create_vm_with_more_vcpus.cfg b/libvirt/tests/cfg/scalability/define_create_vm_with_more_vcpus.cfg new file mode 100644 index 00000000000..25f5de09d82 --- /dev/null +++ b/libvirt/tests/cfg/scalability/define_create_vm_with_more_vcpus.cfg @@ -0,0 +1,28 @@ +- scalability.intel_iommu.define_create_vm_with_more_vcpus: + type = define_create_vm_with_more_vcpus + start_vm = "yes" + enable_guest_iommu = "yes" + feature_name = "ioapic" + func_supported_since_libvirt_ver = (10, 10, 0) + vm_attrs = {"vcpu": 384} + exp_iommu_dict = {"model": "intel", "driver": {"intremap": "on", "eim": "on"}} + + only q35 + variants: + - with_ioapic: + with_ioapic = "yes" + feature_attr = ["driver", "qemu"] + - without_ioapic: + variants: + - with_iommu: + variants: + - default: + only without_ioapic + iommu_dict = {"model": "intel"} + - with_intremap_on: + iommu_dict = {"model": "intel", "driver": {"intremap": "on"}} + - without_iommu: + variants: + - define_vm: + define_vm = "yes" + - create_vm: diff --git a/libvirt/tests/src/scalability/define_create_vm_with_more_vcpus.py b/libvirt/tests/src/scalability/define_create_vm_with_more_vcpus.py new file mode 100644 index 00000000000..b237fe482da --- /dev/null +++ b/libvirt/tests/src/scalability/define_create_vm_with_more_vcpus.py @@ -0,0 +1,78 @@ +from virttest import libvirt_version +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml + + +def run(test, params, env): + """ + libvirt should automatically add iommu and ioapic setting + when define/create guest with more than 255 vcpus + """ + libvirt_version.is_libvirt_feature_supported(params) + iommu_dict = eval(params.get("iommu_dict", "{}")) + exp_iommu_dict = eval(params.get("exp_iommu_dict", "{}")) + define_vm = params.get("define_vm", "no") == "yes" + with_ioapic = params.get("with_ioapic", "no") == "yes" + feature_name = params.get("feature_name", "ioapic") + feature_attr = eval(params.get("feature_attr", "[]")) + + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + backup_vmxml = vmxml.copy() + try: + libvirt_vmxml.remove_vm_devices_by_type(vm, "iommu") + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + vm_attrs = eval(params.get("vm_attrs", "{}")) + vmxml.setup_attrs(**vm_attrs) + + test.log.info(f"TEST_STEP: Update {feature_name} feature.") + features = vmxml.features + test.log.debug(f"orignal features: {features}") + if features.has_feature(feature_name): + if not with_ioapic: + test.log.debug(f"removing {feature_name}...") + features.remove_feature(feature_name) + else: + if with_ioapic: + test.log.debug(f"Adding {feature_name}...") + features.add_feature(feature_name, *feature_attr) + vmxml.features = features + + if iommu_dict: + test.log.info("TEST_STEP: Define VM with intel iommu device.") + iommu_dev = libvirt_vmxml.create_vm_device_by_type( + "iommu", iommu_dict) + vmxml.add_device(iommu_dev) + vmxml.xmltreefile.write() + test.log.debug(f"vm xml will be updated as below: \n{vmxml}") + if define_vm: + vmxml.sync() + else: + virsh.destroy(vm_name, debug=True) + virsh.undefine(vm_name, options='--nvram', debug=True, ignore_status=False) + virsh.create(vmxml.xml, debug=True, ignore_status=False) + + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + features = vmxml.features + test.log.debug(f"features after updating: {features}") + if not features.has_feature(feature_name): + test.fail("Failed to get feature - %s." % feature_name) + + if exp_iommu_dict: + actual_iommu = vm_xml.VMXML.new_from_dumpxml(vm.name)\ + .devices.by_device_tag("iommu")[0].fetch_attrs() + + test.log.debug(f"actual iommu device: {actual_iommu}\n" + f"expected iommu device: {exp_iommu_dict}") + if exp_iommu_dict != actual_iommu: + test.log.warning("iommu device xml comparison failed. " + "Adding alias and try again...") + exp_iommu_dict.update({"alias": {"name": "iommu0"}}) + if exp_iommu_dict != actual_iommu: + test.fail("Incorrect iommu device!") + finally: + if not define_vm: + vm.define(vmxml.xml) + backup_vmxml.sync() From 0eb83844f510aae4b6db984ced2728ba3256a00d Mon Sep 17 00:00:00 2001 From: Tasmiya Nalatwad Date: Thu, 12 Dec 2024 13:53:43 +0530 Subject: [PATCH 0871/1055] Tests perform PCI_PT of NIC devices and checks ping And Tests pci device persistent across Multiple Reboot of VM 1. Changes made to support ppc64 arch and perform pci PT of network devices 2. Perform ping to other server ip and check the device network connectivity 3. Added test to check the device availability after multiple reboots of guest is done Signed-off-by: Tasmiya Nalatwad --- .../pci/libvirt_pci_passthrough.cfg | 4 + .../pci/libvirt_pci_passthrough.py | 114 +++++++++++------- 2 files changed, 72 insertions(+), 46 deletions(-) diff --git a/libvirt/tests/cfg/passthrough/pci/libvirt_pci_passthrough.cfg b/libvirt/tests/cfg/passthrough/pci/libvirt_pci_passthrough.cfg index f0354e0c17a..cba3a9a29cb 100644 --- a/libvirt/tests/cfg/passthrough/pci/libvirt_pci_passthrough.cfg +++ b/libvirt/tests/cfg/passthrough/pci/libvirt_pci_passthrough.cfg @@ -45,3 +45,7 @@ operation = "suspend" - passthrough_shutdown_start: operation = "shutdown" + - passthrough_multiple_reboots: + number_of_reboots = 15 + operation = "reboot" + supported_err = "not supported by the connection driver: virDomainReboot" diff --git a/libvirt/tests/src/passthrough/pci/libvirt_pci_passthrough.py b/libvirt/tests/src/passthrough/pci/libvirt_pci_passthrough.py index 3fc9d9e9e55..82e776ba2cf 100644 --- a/libvirt/tests/src/passthrough/pci/libvirt_pci_passthrough.py +++ b/libvirt/tests/src/passthrough/pci/libvirt_pci_passthrough.py @@ -1,5 +1,6 @@ import logging as log import ipaddress +import platform import time from virttest import virsh, virt_vm @@ -39,6 +40,8 @@ def run(test, params, env): i) Reboot. ii) Suspend/Resume. iii) Start/Shutdown. + d). Multiple Reboots: + 1. Checking PCI Device remains persistent across multiple reboots """ def guest_lifecycle(): @@ -93,6 +96,8 @@ def guest_lifecycle(): sriov = ('yes' == params.get("libvirt_pci_SRIOV", 'no')) device_type = params.get("libvirt_pci_device_type", "NIC") vm_vfs = int(params.get("number_vfs", 2)) + number_of_reboots = int(params.get("number_of_reboots", "1")) + arch = platform.machine() pci_dev = None pci_address = None bus_info = [] @@ -174,59 +179,76 @@ def guest_lifecycle(): pci_address = pci_xml.cap.get_address_dict() vmxml.add_hostdev(pci_address) - try: - for itr in range(iteration): - logging.info("Currently executing iteration number: '%s'", itr) - vmxml.sync() - vm.start() - session = vm.wait_for_login() - # The Network configuration is generic irrespective of PF or SRIOV VF - if device_type == "NIC": - if sorted(vm.get_pci_devices()) != sorted(nic_list_before): - logging.debug("Adapter passthroughed to guest successfully") - else: - test.fail("Passthrough adapter not found in guest.") - net_ip = ipaddress.ip_address(net_ip) - nic_list_after = vm.get_pci_devices() - nic_list = list(set(nic_list_after).difference(set(nic_list_before))) - for val in range(len(nic_list)): - bus_info.append(str(nic_list[val]).split(' ', 1)[0]) - nic_list[val] = str(nic_list[val]).split(' ', 1)[0][:-2] - bus_info.sort() - if not sriov: - # check all functions get same iommu group + def check_device_status(net_ip, server_ip, netmask): + logging.info("Currently executing iteration number: '%s'", itr) + vmxml.sync() + vm.start() + session = vm.wait_for_login() + # The Network configuration is generic irrespective of PF or SRIOV VF + if device_type == "NIC": + if sorted(vm.get_pci_devices()) != sorted(nic_list_before): + logging.debug("Adapter passthroughed to guest successfully") + else: + test.fail("Passthrough adapter not found in guest.") + net_ip = ipaddress.ip_address(net_ip) + nic_list_after = vm.get_pci_devices() + nic_list = list(set(nic_list_after).difference(set(nic_list_before))) + for val in range(len(nic_list)): + bus_info.append(str(nic_list[val]).split(' ', 1)[0]) + nic_list[val] = str(nic_list[val]).split(' ', 1)[0][:-2] + bus_info.sort() + if not sriov: + # check all functions get same iommu group + # arch ppc64 gets different iommu group when attached to VM + if arch != "ppc64le": if len(set(nic_list)) != 1: test.fail("Multifunction Device passthroughed but " "functions are in different iommu group") - # ping to server from each function - for val in bus_info: - nic_name = str(utils_misc.get_interface_from_pci_id(val, session)) - session.cmd("ip addr flush dev %s" % nic_name) - session.cmd("ip addr add %s/%s dev %s" - % (net_ip, netmask, nic_name)) - session.cmd("ip link set %s up" % nic_name) - # Pinging using nic_name is having issue, - # hence replaced with IPAddress - s_ping, o_ping = utils_test.ping(server_ip, count=5, - interface=net_ip, timeout=30, - session=session) - logging.info(o_ping) - if s_ping != 0: - err_msg = "Ping test fails, error info: '%s'" - test.fail(err_msg % o_ping) - # Each interface should have unique IP + # ping to server from each function + for val in bus_info: + nic_name = str(utils_misc.get_interface_from_pci_id(val, session)) + session.cmd("ip addr flush dev %s" % nic_name) + session.cmd("ip addr add %s/%s dev %s" + % (net_ip, netmask, nic_name)) + session.cmd("ip link set %s up" % nic_name) + # Pinging using nic_name is having issue, + # hence replaced with IPAddress + s_ping, o_ping = utils_test.ping(server_ip, count=5, + interface=net_ip, timeout=30, + session=session) + logging.info(o_ping) + if s_ping != 0: + err_msg = "Ping test fails, error info: '%s'" + test.fail(err_msg % o_ping) + # Each interface should have unique IP + # For ppc64 arch let's test using one ip only + if arch != "ppc64le": net_ip = net_ip + 1 - elif device_type == "STORAGE": - # Get the result of "fdisk -l" in guest, and - # compare the result with fdisk_list_before. - output = session.cmd_output("fdisk -l|grep \"Disk identifier:\"") - fdisk_list_after = output.splitlines() - if fdisk_list_after == fdisk_list_before: - test.fail("Didn't find the disk attached to guest.") + elif device_type == "STORAGE": + # Get the result of "fdisk -l" in guest, and + # compare the result with fdisk_list_before. + output = session.cmd_output("fdisk -l|grep \"Disk identifier:\"") + fdisk_list_after = output.splitlines() + if fdisk_list_after == fdisk_list_before: + test.fail("Didn't find the disk attached to guest.") - # Execute VM Life-cycle Operation with device pass-through + def multiple_reboot(number_of_reboots): + for reboot_count in range(number_of_reboots): + logging.info("Performing VM Reboot with device pass-through for reboot count : %s", reboot_count) guest_lifecycle() + logging.info("Check device avialablity after VM Reboot for reboot count : %s", reboot_count) + check_device_status(net_ip, server_ip, netmask) + + try: + for itr in range(iteration): + check_device_status(net_ip, server_ip, netmask) + + # Execute VM Life-cycle Operation with device pass-through + guest_lifecycle() + + # Execute Multiple reboots on VM and check the device persistency + multiple_reboot(number_of_reboots) finally: backup_xml.sync() From 6d5ad1d4001c1565035cef1cce8e4352f0c27b12 Mon Sep 17 00:00:00 2001 From: nanli Date: Sun, 2 Mar 2025 11:25:49 +0800 Subject: [PATCH 0872/1055] add case for nvdimm turned to dram xxxx-302271:Turned nvdimm to the regular DRAM Signed-off-by: nanli --- .../nvdimm_memory_turn_to_dram.cfg | 22 +++ .../nvdimm_memory_turn_to_dram.py | 127 ++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_devices/nvdimm_memory_turn_to_dram.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/nvdimm_memory_turn_to_dram.py diff --git a/libvirt/tests/cfg/memory/memory_devices/nvdimm_memory_turn_to_dram.cfg b/libvirt/tests/cfg/memory/memory_devices/nvdimm_memory_turn_to_dram.cfg new file mode 100644 index 00000000000..db313f24f98 --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/nvdimm_memory_turn_to_dram.cfg @@ -0,0 +1,22 @@ +- memory.devices.nvdimm.turn_to_dram: + type = nvdimm_memory_turn_to_dram + start_vm = no + mem_model = 'nvdimm' + numa_dict = "'vcpu': 2,'cpu':{'check': 'partial', 'fallback': 'allow','numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '524288'}],'topology':{'sockets': '2', 'cores': '1', 'threads': '1'}}" + vm_attrs = {${numa_dict},"max_mem_rt": 15242880, "max_mem_rt_slots": 16,'memory':4194304,'current_mem':4194304,} + nvdimm_path = "/tmp/nvdimm" + nvdimm_dict = {'mem_model':'${mem_model}',"mem_access":"shared",'target': {'size':1048576, 'size_unit':'KiB', 'node':0}, 'source':{'path': "${nvdimm_path}"},'address':{'attrs': {'type':'dimm','slot':'1'}}} + truncate_cmd = "truncate -s 1024M ${nvdimm_path}" + expected_qemu_cmdline = ["nvdimm=on",'"mem-path":"/tmp/nvdimm"','"share":true'] + repeat_times = 20 + devdax_mode = "devdax" + dram_mode = "system-ram" + create_namespace = "ndctl create-namespace --mode devdax -f -e namespace0.0" + check_dev = "ls -al /dev/dax0.0" + list_nvdimm_namespace = 'ndctl list -N' + persistence_config = 'daxctl migrate-device-model' + add_kmem = "modprobe kmem" + update_to_dram = 'daxctl reconfigure-device --mode=system-ram --region=0 all' + check_list = ['CONFIG_LIBNVDIMM=m', 'CONFIG_BLK_DEV_PMEM=m', 'CONFIG_ACPI_NFIT=m'] + + diff --git a/libvirt/tests/src/memory/memory_devices/nvdimm_memory_turn_to_dram.py b/libvirt/tests/src/memory/memory_devices/nvdimm_memory_turn_to_dram.py new file mode 100644 index 00000000000..1523da35bd0 --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/nvdimm_memory_turn_to_dram.py @@ -0,0 +1,127 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import re + +from avocado.utils import distro +from avocado.utils import process + +from virttest import virsh +from virttest import utils_misc +from virttest import utils_package +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_bios + +from provider.memory import memory_base + + +def run(test, params, env): + """ + Turned nvdimm to the regular DRAM. + """ + def setup_test(): + """ + Create nvdimm file on the host. + """ + process.run(truncate_cmd) + + def run_test(): + """ + Turned nvdimm to the regular DRAM would increase total memory + """ + test.log.info("TEST_STEP1: Define vm with nvdimm memory") + memory_base.define_guest_with_memory_device(params, nvdimm_dict, vm_attrs) + + test.log.info("TEST_STEP2: Start guest and Check nvdimm passed in the qemu command line") + vm.start() + session = vm.wait_for_login() + libvirt.check_qemu_cmd_line(eval(expected_qemu_cmdline)) + + test.log.info("TEST_STEP3:Check the guest support NVDIMM") + libvirt_bios.check_boot_config(session, test, check_list) + + test.log.info("TEST_STEP4:Login to the guest, check mem size and nvdimm mode") + vm_mem_before = utils_misc.get_mem_info(session) + + test.log.debug("VM's memory before updating nvdimm to dram: %s", vm_mem_before) + + if not utils_package.package_install('ndctl', session=session): + test.fail('Cannot install ndctl to vm') + utils_misc.cmd_status_output(create_namespace, session=session) + utils_misc.cmd_status_output(check_dev, session=session) + + ndctl_list = eval(utils_misc.cmd_status_output(list_nvdimm_namespace, session=session)[1]) + if ndctl_list[0]['mode'] != devdax_mode: + test.fail("Expected mode devdax, but %s" % ndctl_list["mode"]) + test.log.debug("Check mode: %s PASS", devdax_mode) + + test.log.info("TEST_STEP5:Turned nvdimm to the regular DRAM, and hot-added memory matches the expectation") + if not utils_package.package_install('daxctl', session=session): + test.fail('Cannot install daxctl to vm') + if distro.detect().name == 'rhel' and int(distro.detect().version) >= 9: + utils_misc.cmd_status_output(persistence_config, session=session) + utils_misc.cmd_status_output(add_kmem, session=session) + + utils_misc.cmd_status_output(create_namespace, session=session) + output = utils_misc.cmd_status_output(update_to_dram, session=session)[1] + if not re.findall(r'"mode":"%s"' % dram_mode, output): + test.fail("Expected mode is dram") + test.log.debug("Check new mode: %s PASS") + + vm_mem_after = utils_misc.get_mem_info(session) + test.log.debug("New memory total value is:%s", vm_mem_after) + if int(vm_mem_after) <= int(vm_mem_before): + test.fail("Memory should increase after updating nvdimm to dram") + test.log.debug("Check guest memory increase successfully") + + test.log.info("TEST_STEP6:Used memhog for memory operation") + utils_misc.cmd_status_output("memhog -r%s 500M" % repeat_times, session=session) + session.close() + + test.log.info("TEST_STEP7:Reboot and check guest status") + virsh.reboot(vm_name, debug=True) + if vm.state() != "running": + test.fail("VM %s should be running, not %s" % (vm.name, vm.state())) + test.log.debug("Check guest status is running") + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bkxml.sync() + process.run("rm -rf %s" % nvdimm_path) + + vm_name = params.get("main_vm") + original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = original_xml.copy() + vm = env.get_vm(vm_name) + nvdimm_path = params.get("nvdimm_path") + truncate_cmd = params.get("truncate_cmd") + expected_qemu_cmdline = params.get("expected_qemu_cmdline") + nvdimm_dict = eval(params.get("nvdimm_dict")) + vm_attrs = eval(params.get("vm_attrs", "{}")) + repeat_times = params.get("repeat_times") + + devdax_mode = params.get("devdax_mode") + dram_mode = params.get("dram_mode") + create_namespace = params.get("create_namespace") + check_dev = params.get("check_dev") + list_nvdimm_namespace = params.get("list_nvdimm_namespace") + add_kmem = params.get("add_kmem") + update_to_dram = params.get("update_to_dram") + persistence_config = params.get("persistence_config") + check_list = eval(params.get("check_list", "{}")) + + try: + setup_test() + run_test() + + finally: + teardown_test() From d61c39a1b8b49ac773670ccbc43b1fc66174095e Mon Sep 17 00:00:00 2001 From: nanli Date: Thu, 6 Mar 2025 17:33:49 +0800 Subject: [PATCH 0873/1055] add case for blockcopy with datafile property xxxx-294532:Check qcow2 properties after blockcopy Signed-off-by: nanli --- ...ckcopy_with_different_qcow2_properties.cfg | 9 +++++ ...ockcopy_with_different_qcow2_properties.py | 35 +++++++++++++++---- provider/virtual_disk/disk_base.py | 17 +++++---- 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/libvirt/tests/cfg/backingchain/blockcopy/blockcopy_with_different_qcow2_properties.cfg b/libvirt/tests/cfg/backingchain/blockcopy/blockcopy_with_different_qcow2_properties.cfg index 6060253faf7..cfeb929e147 100644 --- a/libvirt/tests/cfg/backingchain/blockcopy/blockcopy_with_different_qcow2_properties.cfg +++ b/libvirt/tests/cfg/backingchain/blockcopy/blockcopy_with_different_qcow2_properties.cfg @@ -7,6 +7,7 @@ snap_extra = " --no-metadata --diskspec vda,snapshot=no" copy_image = "/tmp/copy.qcow2" image_path = "/var/lib/libvirt/images/test.qcow2" + snap_path = "/var/lib/libvirt/images/snap1" image_format = "qcow2" image_size = "500M" variants property: @@ -16,6 +17,14 @@ expected_extended_l2 = "true" property_command = "cluster_size=${cluster_size},extended_l2=${extended_l2_value}" image_extras = "-o ${property_command}" + expected_chain_after_snap = ['${snap_path}','${image_path}'] + - with_datastore: + func_supported_since_libvirt_ver = (10, 10, 0) + datastore_path = "/var/lib/libvirt/images/datastore" + data_file_option = " -o data_file=%s" + property_command = "data_file=${datastore_path}" + image_extras = "-o ${property_command}" + expected_chain_after_snap = ['${snap_path}','${image_path}', '${datastore_path}'] variants: - not_encrypt_disk: enable_encrypt_disk = "no" diff --git a/libvirt/tests/src/backingchain/blockcopy/blockcopy_with_different_qcow2_properties.py b/libvirt/tests/src/backingchain/blockcopy/blockcopy_with_different_qcow2_properties.py index 39e828860de..4212abf18ed 100644 --- a/libvirt/tests/src/backingchain/blockcopy/blockcopy_with_different_qcow2_properties.py +++ b/libvirt/tests/src/backingchain/blockcopy/blockcopy_with_different_qcow2_properties.py @@ -1,9 +1,10 @@ import re +from virttest import libvirt_version from virttest import virsh - from virttest.libvirt_xml import vm_xml from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_disk from provider.backingchain import blockcommand_base from provider.backingchain import check_functions @@ -24,14 +25,20 @@ def setup_test(): Prepare image with properties and snap chain """ test.log.info("SETUP:Prepare image with properties and snap chain") + if property_item == "with_datastore": + libvirt.create_local_disk("file", path=datastore_path, size=image_size, + disk_format=image_format) libvirt.create_local_disk("file", path=image_path, size=image_size, disk_format=image_format, extra=image_extras) check_property(image_path, property_item) prepare_disk() - test_obj.backingchain_common_setup(create_snap=True, - snap_num=1, extra=snap_extra) - check_property(test_obj.snap_path_list[0], property_item) + test_obj.backingchain_common_setup( + create_snap=True, snap_num=1, snap_path=snap_path, extra=snap_extra) + + if property_item == "extended_l2_and_cluster_size": + check_property(test_obj.snap_path_list[0], property_item) + check_obj.check_backingchain_from_vmxml(disk_type, target_disk, expected_chain_after_snap) def run_test(): """ @@ -43,8 +50,16 @@ def run_test(): ignore_status=False, debug=True) - test.log.info("TEST_STEP2:Check properties after blockcopy.") - check_property(copy_image, property_item) + test.log.info("TEST_STEP2:Check guest xml and image properties " + "after blockcopy.") + check_obj.check_backingchain_from_vmxml(disk_type, target_disk, + [copy_image]) + + if property_item == "extended_l2_and_cluster_size": + check_property(copy_image, property_item) + + test.log.info("TEST_STEP3: Write file in guest") + libvirt_disk.check_virtual_disk_io(vm, target_disk) def teardown_test(): """ @@ -54,6 +69,8 @@ def teardown_test(): test_obj.backingchain_common_teardown() test_obj.clean_file(copy_image) test_obj.clean_file(image_path) + if datastore_path: + test_obj.clean_file(datastore_path) bkxml.sync() @@ -71,6 +88,8 @@ def check_property(path, property_item): cluster_size_value = int(re.findall(r"\d+", cluster_size)[0])*1024*1024 check_obj.check_image_info(path, 'csize', cluster_size_value) + elif property_item == "with_datastore": + check_obj.check_image_info(path, 'data file', datastore_path) def prepare_disk(): """ @@ -82,6 +101,7 @@ def prepare_disk(): test_obj.new_image_path = disk_obj.add_vm_disk( disk_type, disk_dict, new_image_path=image_path) + libvirt_version.is_libvirt_feature_supported(params) # Process cartesian parameters vm_name = params.get("main_vm") target_disk = params.get('target_disk') @@ -98,6 +118,9 @@ def prepare_disk(): property_item = params.get('property') cluster_size = params.get('cluster_size') expected_extended_l2 = params.get('expected_extended_l2') + datastore_path = params.get("datastore_path") + snap_path = params.get("snap_path") + expected_chain_after_snap = eval(params.get("expected_chain_after_snap", '{}')) encryption_disk = params.get('enable_encrypt_disk', 'no') == "yes" vm = env.get_vm(vm_name) diff --git a/provider/virtual_disk/disk_base.py b/provider/virtual_disk/disk_base.py index 1c87e56f145..bd79fa8e0e1 100644 --- a/provider/virtual_disk/disk_base.py +++ b/provider/virtual_disk/disk_base.py @@ -76,12 +76,17 @@ def get_source_list(vmxml, disk_type, target_dev): backing_list = disk.get_backingstore_list() if disk_type != 'rbd_with_auth' and backing_list != []: backing_list.pop() - source_list = [elem.find('source').get('file') or - elem.find('source').get('name') or - elem.find('source').get('dev') or - elem.find('source').get('volume') - for elem in backing_list - if elem.find("source") is not None] + for elem in backing_list: + source_ele = elem.find("source") + if source_ele is not None: + source_list = [source_ele.get('file') or + source_ele.get('name') or + source_ele.get('dev') or + source_ele.get('volume')] + if source_ele.find("dataStore"): + source_list.append( + source_ele.find("dataStore").find('source').get('file')) + source_list.insert(0, active_level_path) break From 315beebb7f755c0c934a320447849c8fa528aa3f Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Fri, 29 Nov 2024 04:28:26 -0500 Subject: [PATCH 0874/1055] Restart virtnetworkd to make the states clear When the network states become inconsistent since some abnormal situations, ensure the operation to restart virtnetworkd will fix it. Signed-off-by: Yalan Zhang --- .../lifecycle/restart_service.cfg | 5 + .../lifecycle/restart_service.py | 96 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/lifecycle/restart_service.cfg create mode 100644 libvirt/tests/src/virtual_network/lifecycle/restart_service.py diff --git a/libvirt/tests/cfg/virtual_network/lifecycle/restart_service.cfg b/libvirt/tests/cfg/virtual_network/lifecycle/restart_service.cfg new file mode 100644 index 00000000000..ff90b7fdff3 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/lifecycle/restart_service.cfg @@ -0,0 +1,5 @@ +- virtual_network.lifecycle.restart_service: + type = restart_service + start_vm = no + net_attrs = {'name': net_name, 'forward': {'mode': 'nat'}, 'ips': [{'dhcp_ranges': {'attrs': {'start': '192.168.23.2', 'end': '192.168.23.254'}}, 'netmask': '255.255.255.0', 'address': '192.168.23.1'}]} + diff --git a/libvirt/tests/src/virtual_network/lifecycle/restart_service.py b/libvirt/tests/src/virtual_network/lifecycle/restart_service.py new file mode 100644 index 00000000000..4048758baa0 --- /dev/null +++ b/libvirt/tests/src/virtual_network/lifecycle/restart_service.py @@ -0,0 +1,96 @@ +import re +import logging as log + +from avocado.utils import process +from virttest import virsh +from virttest import utils_misc +from virttest.staging import service +from virttest.libvirt_xml import network_xml +from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_network + +logging = log.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + 1) make sure the network is active in healthy state; + 2) delete the bridge of the network, which cause an abnormal status; + 3) restart the network daemon, check the network status is inactive and clean; + 4) start the network and check it's healthy again; + """ + + def delete_bridge(net_name): + """ + Delete the bridge associated with the network created by libvirt to + prepare an abnormal scenario + + :params net_name: the name of the network + :return: None + """ + xml = network_xml.NetworkXML.new_from_net_dumpxml(net_name) + br_name = xml.bridge['name'] + logging.debug("Delete the bridge %s for network %s:", br_name, net_name) + cmd = "ip l delete %s" % br_name + process.run(cmd, shell=True) + cmd1 = "ip l show %s" % br_name + if not process.run(cmd1, shell=True, ignore_status=True).exit_status: + test.cancel("The bridge can not be deleted: %s" % br_name) + + def check_net_states(net_name, active): + """ + Check the network related status are expected, + when it is running, there should be 2 dnsmasq process, + and listening on specific ports. While inactive network + should be clean without these. + + :params net_name: string, name of the network + :params active: bool, True or False + """ + s_active = virsh.net_state_dict()[net_name]["active"] + xml = network_xml.NetworkXML.new_from_net_dumpxml(net_name) + br_ip = xml.ips[0]['address'] + logging.debug("br_ip is %s for network %s", br_ip, net_name) + + cmd = "ps aux|grep dnsmasq|grep -v grep | grep %s" % net_name + dnsmasq_process = process.run(cmd, shell=True, ignore_status=True).stdout_text.strip() + cmd1 = """ps aux|grep dnsmasq|grep -v grep | grep %s | awk '$1=="dnsmasq" {print $2}'""" % net_name + dnsmasq_pid = process.run(cmd1, shell=True, ignore_status=True).stdout_text.strip() + cmd2 = "lsof -i -P -n | grep %s" % dnsmasq_pid + listen_port = process.run(cmd2, shell=True, ignore_status=True).stdout_text.strip() + logging.debug("Check the dnsmasq process of the network: %s", dnsmasq_process) + logging.debug("Check the listen_port associated with the dnsmasq process: %s", listen_port) + if active: + pid_num = len(dnsmasq_process.splitlines()) + pattern_list = [rf'UDP\s+{br_ip}:53', + rf'TCP\s+{br_ip}:53', + r'UDP\s+\*:67'] + for pattern in pattern_list: + if not re.search(pattern, listen_port): + test.fail("Can not find the listen port %s" % pattern) + if (pid_num != 2) or not s_active: + test.fail("The network should be active with 2 dnsmasq process!") + if not active: + if s_active: + test.fail("The network %s should be inactive!" % net_name) + if dnsmasq_process or listen_port: + test.fail("There should not be any dnsmasq process nor listening port!") + + try: + net_name = utils_misc.generate_random_string(8) + net_attrs = eval(params.get('net_attrs', '{}')) + logging.debug("TEST_STEP1: Define and start a network") + libvirt_network.create_or_del_network(net_attrs) + virsh.net_start(net_name, ignore_status=True) + check_net_states(net_name, True) + logging.debug("TEST_STEP2: Delete the bridge to prepare an abnormal status") + delete_bridge(net_name) + logging.debug("TEST_STEP3: Restart virtnetworkd, check the network become inactive") + service.Factory.create_service("virtnetworkd").restart() + check_net_states(net_name, False) + logging.debug("TEST_STEP4: Start the network again and ensure it works well") + ret = virsh.net_start(net_name, ignore_status=False) + libvirt.check_result(ret) + finally: + virsh.net_destroy(net_name, ignore_status=True) + virsh.net_undefine(net_name, ignore_status=True) From a5c490930206d2f37d15d8be07708a561bbb2376 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Fri, 17 Jan 2025 08:05:24 -0500 Subject: [PATCH 0875/1055] Restore VM with various invalid saved file status This case test starting vm when the saved state file is invalid, deleted or corrupted. The VM should be fresh started. Signed-off-by: Yalan Zhang --- .../domain/virsh_managedsave_restore.cfg | 19 +++ .../domain/virsh_managedsave_restore.py | 133 ++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave_restore.cfg create mode 100644 libvirt/tests/src/virsh_cmd/domain/virsh_managedsave_restore.py diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave_restore.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave_restore.cfg new file mode 100644 index 00000000000..817249794b6 --- /dev/null +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave_restore.cfg @@ -0,0 +1,19 @@ +- virsh.managedsave_restore: + type = virsh_managedsave_restore + start_vm = yes + variants: + - managedsaved: + vm_managedsaved = yes + - not_managedsaved: + only no_file + vm_managedsaved = no + variants: + - no_file: + file_state = nonexist + - corrupt_file: + file_state = corrupt + expected_log = "Ignoring incomplete managed state" + - occupied_file: + file_state = occupied + need_vm2 = yes + expected_cmd_err = "Requested operation is not valid" diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave_restore.py b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave_restore.py new file mode 100644 index 00000000000..a4938236f8d --- /dev/null +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave_restore.py @@ -0,0 +1,133 @@ +import logging +import os + +from virttest import virsh +from virttest import data_dir +from virttest import utils_misc +from virttest import utils_libguestfs +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt +from avocado.utils import process + +from provider.save import save_base + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test vm restore after managedsave with various conditions + """ + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + managed_save_file = "/var/lib/libvirt/qemu/save/%s.save" % vm_name + + def check_libvirtd_log(): + """ + Check the libvirtd log for expected messages + """ + result = utils_misc.wait_for( + lambda: libvirt.check_logfile(expected_log, libvirtd_log_file), timeout=20) + if not result: + test.fail("Can't get expected log %s in %s" % (expected_log, libvirtd_log_file)) + + def start_shutdown_cycle(): + """ + Do a managedsave -> start -> shutdown cycle + """ + LOG.info("Do a start shutdown cycle to clear the saved state:") + vm.start() + if os.path.exists(managed_save_file): + test.fail("The saved file exists after restore: %s", managed_save_file) + virsh.shutdown(vm_name, debug=True) + if not vm.wait_for_shutdown(): + test.error('VM failed to shutdown in 60s') + + def setup_saved_file(): + """" + Prepare the pre-conditions about saved file + + 1. Prepare an invalid saved file if needed + 2. Update the saved file to use an occupied one if needed + 3. Remove the saved file if needed + """ + if file_state == "corrupt": + LOG.info("Corrupt the saved file by 'echo >' cmd:") + process.run("echo > %s" % managed_save_file, shell=True, ignore_status=True) + elif file_state == "occupied": + LOG.info("Update the saved file to use an occupied image:") + # Edit the current vm's saved state file to use another running VM's disk path + LOG.info("Clone a VM with name as %s:", add_vm_name) + utils_libguestfs.virt_clone_cmd(vm_name, add_vm_name, + True, timeout=360) + add_vm = vm.clone(add_vm_name) + add_vm.start() + # Get the add_vm disk path, and vm disk path, then replace the + # vm disk path to be add_vm disk path + add_vm_xml = vm_xml.VMXML.new_from_inactive_dumpxml(add_vm_name) + add_disk_xml = add_vm_xml.get_devices(device_type="disk")[0] + add_disk_path = add_disk_xml.source.attrs['file'] + + disk_xml = vmxml.get_devices(device_type="disk")[0] + vm_disk_path = disk_xml.source.attrs['file'] + xmlfile = os.path.join(data_dir.get_tmp_dir(), 'managedsave.xml') + virsh.managedsave_dumpxml(vm_name, to_file=xmlfile, ignore_status=False, debug=False) + + LOG.info("Update the disk path from %s to %s:", vm_disk_path, add_disk_path) + cmd = "sed -i 's|%s|%s|' %s" % (vm_disk_path, add_disk_path, xmlfile) + process.run(cmd, shell=True) + virsh.managedsave_define(vm_name, xmlfile, debug=True) + ret = virsh.managedsave_dumpxml(vm_name, '--xpath //disk', debug=True).stdout_text + LOG.info("After update, the disk in mangedsave state file is: %s", ret) + elif file_state == "nonexist": + LOG.info("Delete the saved file:") + process.run("rm -f %s" % managed_save_file, shell=True, ignore_status=True) + + file_state = params.get("file_state") + vm_managedsaved = "yes" == params.get("vm_managedsaved") + need_vm2 = "yes" == params.get("need_vm2", "no") + expected_log = params.get("expected_log", None) + expected_cmd_err = params.get("expected_cmd_err", None) + libvirtd_log_file = os.path.join(test.debugdir, "libvirtd.log") + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bk_xml = vmxml.copy() + appendix = utils_misc.generate_random_string(4) + add_vm_name = ("%s" % vm_name[:-1]) + ("%s" % appendix) + + try: + LOG.info("TEST_STEP1: Setup before restore the vm:") + if not vm.is_alive(): + vm.start() + pre_pid_ping, pre_upsince = save_base.pre_save_setup(vm) + virsh.managedsave(vm_name, debug=True) + if not vm_managedsaved: + start_shutdown_cycle() + else: + setup_saved_file() + + LOG.info("TEST_STEP2: Restore the vm by 'virsh start':") + ret = virsh.start(vm_name, debug=True) + libvirt.check_result(ret, expected_fails=expected_cmd_err) + virsh.destroy(add_vm_name, debug=True) + # if not expect error, vm should freshly start + if not expected_cmd_err: + LOG.info("TEST_STEP3: Check the vm should be freshly start:") + post_pid_ping, post_upsince = save_base.pre_save_setup(vm) + if pre_upsince == post_upsince: + test.fail("VM is not freshly start!") + else: + LOG.info("The uptime changed: %s vs %s", pre_upsince, post_upsince) + if file_state == 'corrupt': + LOG.info("TEST_STEP4: Check libvirtd log:") + check_libvirtd_log() + finally: + virsh.destroy(vm_name, debug=True) + virsh.undefine(vm_name, "--managed-save --keep-nvram", debug=True) + if os.path.exists(managed_save_file): + process.run("rm -f %s" % managed_save_file, shell=True, ignore_status=True) + bk_xml.sync() + if need_vm2: + LOG.info("Remove the additional VM: %s", add_vm_name) + virsh.remove_domain(add_vm_name, "--remove-all-storage --nvram") From 6dff01e61fc853220142b67b13a07f441aea5bfa Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Mon, 10 Mar 2025 05:59:40 -0400 Subject: [PATCH 0876/1055] Delete target limition for some v2v cases Signed-off-by: Ming Xie --- v2v/tests/cfg/convert_from_file.cfg | 1 - v2v/tests/cfg/function_test_esx.cfg | 1 - v2v/tests/cfg/specific_kvm.cfg | 4 ---- 3 files changed, 6 deletions(-) diff --git a/v2v/tests/cfg/convert_from_file.cfg b/v2v/tests/cfg/convert_from_file.cfg index e66db849b75..555013784cf 100644 --- a/v2v/tests/cfg/convert_from_file.cfg +++ b/v2v/tests/cfg/convert_from_file.cfg @@ -169,7 +169,6 @@ expect_msg = yes input_file = ${ova_dir}/${ova_file} - aws: - only output_mode.rhev ova_dir = OVA_DIR_AWS_V2V_EXAMPLE variants: - rhel7_2: diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 5040f8b2694..6e00af407f8 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -883,7 +883,6 @@ main_vm = VM_NAME_ESX80_MULTI_SPEC_V2V_EXAMPLE - no_vpx_username: only esx_80 - only it_default only negative_test version_required = "[libvirt-9.3.0-1.el9,)" main_vm = VM_NAME_NON_ADMIN_V2V_EXAMPLE diff --git a/v2v/tests/cfg/specific_kvm.cfg b/v2v/tests/cfg/specific_kvm.cfg index 83834869c84..157ade2a5a5 100644 --- a/v2v/tests/cfg/specific_kvm.cfg +++ b/v2v/tests/cfg/specific_kvm.cfg @@ -235,7 +235,6 @@ checkpoint = 'sync_ntp' - no_space: only esx.esx_70 - only rhev checkpoint = 'host_no_space_setcache' main_vm = 'VM_ESX_DEFAULT_NAME_V2V_EXAMPLE' - no_libguestfs_backend: @@ -270,11 +269,8 @@ main_vm = 'VM_NAME_80_CHARS_V2V_EXAMPLE' - non_exist_network: only source_esx.esx_80 - only rhev boottype = 2 main_vm = 'VM_NON_EXIST_NETWORK_V2V_EXAMPLE' - skip_vm_check = yes - skip_reason = "bz#RHEL-1718 on win11 guest" - partial_efi: only source_esx.esx_80 version_required = "[virt-v2v-2.5.5-1.el9,)" From 62204a373e9718b757256fd71925b57bd310dec9 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 10 Mar 2025 06:28:06 -0400 Subject: [PATCH 0877/1055] vcpu: override helper functions on s390x On s390x, override the avocado utility functions because on an LPAR they would return the number of CPUs available on the CEC but not on the LPAR. Instead, use only the CPUs that are currently online on the LPAR before starting the test which will manipulate their state in some cases. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/cpu/vcpu_affinity.py | 3 ++ libvirt/tests/src/libvirt_vcpu_plug_unplug.py | 4 +++ provider/cpu.py | 28 +++++++++++++++++++ spell.ignore | 1 + 4 files changed, 36 insertions(+) create mode 100644 provider/cpu.py diff --git a/libvirt/tests/src/cpu/vcpu_affinity.py b/libvirt/tests/src/cpu/vcpu_affinity.py index ce421beff11..25116fb4839 100644 --- a/libvirt/tests/src/cpu/vcpu_affinity.py +++ b/libvirt/tests/src/cpu/vcpu_affinity.py @@ -10,10 +10,13 @@ from virttest import utils_libvirtd from virttest import libvirt_cgroup +from provider.cpu import patch_total_cpu_count_s390x + # 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__) +patch_total_cpu_count_s390x(cpuutil) def check_vcpu_placement(test, params): diff --git a/libvirt/tests/src/libvirt_vcpu_plug_unplug.py b/libvirt/tests/src/libvirt_vcpu_plug_unplug.py index d59c78bc969..470495062aa 100644 --- a/libvirt/tests/src/libvirt_vcpu_plug_unplug.py +++ b/libvirt/tests/src/libvirt_vcpu_plug_unplug.py @@ -14,12 +14,16 @@ from virttest.utils_test import libvirt from virttest.libvirt_xml.vm_xml import VMXML +from provider.cpu import patch_total_cpu_count_s390x + + vm_uptime_init = 0 # 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__) +patch_total_cpu_count_s390x(cpu_util) def run(test, params, env): diff --git a/provider/cpu.py b/provider/cpu.py new file mode 100644 index 00000000000..847b3a034fa --- /dev/null +++ b/provider/cpu.py @@ -0,0 +1,28 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: smitterl@redhat.com +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import platform + + +def patch_total_cpu_count_s390x(cpu_module): + """ + On s390x, override the avocado utility functions because on an + LPAR they would return the number of CPUs available on the CEC + but not on the LPAR. + + :param cpu_module: the module after import in calling script + """ + + if platform.machine() == "s390x": + online_before_test = cpu_module.online_count() + + def _online_before_test(): + return online_before_test + cpu_module.total_cpus_count = _online_before_test + cpu_module.total_count = _online_before_test diff --git a/spell.ignore b/spell.ignore index 40848d87a7d..8a3dcb4d7b2 100644 --- a/spell.ignore +++ b/spell.ignore @@ -95,6 +95,7 @@ capabilities cartesian ccw CCW +CEC cd cdrom cellno From 06d74081e8e737af067a1648883eff6ace2f718d Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 10 Mar 2025 10:16:39 -0400 Subject: [PATCH 0878/1055] virsh_save_image: enable different domain xml The test cases assume the guest uses . However, those are not supported on s390x. Instead make the XML snippet that's updated configurable. On s390x, use which is supported. Signed-off-by: Sebastian Mitterle --- .../domain/virsh_save_image_define.cfg | 5 +++++ .../virsh_cmd/domain/virsh_save_image_edit.cfg | 5 +++++ .../domain/virsh_save_image_define.py | 18 ++++++++++++------ .../virsh_cmd/domain/virsh_save_image_edit.py | 15 +++++++++------ 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_save_image_define.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_save_image_define.cfg index 305d5fc6bdf..b37ede77b15 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_save_image_define.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_save_image_define.cfg @@ -2,6 +2,11 @@ type = virsh_save_image_define vm_save = "vm.save" kill_vm_on_error = "no" + xml_before = "" + xml_after = "" + s390-virtio: + xml_before = "" + xml_after = "" variants: - running: restore_state = "running" diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_save_image_edit.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_save_image_edit.cfg index 90ed44f1ad9..984b512d85c 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_save_image_edit.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_save_image_edit.cfg @@ -3,6 +3,11 @@ vm_save = "vm.save" kill_vm_on_error = "no" take_regular_screendumps = "no" + xml_before = "" + xml_after = "" + s390-virtio: + xml_before = "" + xml_after = "" variants: - no_option: restore_state = "running" diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_save_image_define.py b/libvirt/tests/src/virsh_cmd/domain/virsh_save_image_define.py index 3148cdbe842..d6aa6d36e59 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_save_image_define.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_save_image_define.py @@ -52,14 +52,18 @@ def redefine_new_xml(): debug=True) libvirt.check_exit_status(cmd_result) - def vm_state_check(): + def vm_state_check(xml_after): + """ + Checks the VM state + + :param xml_after: expected xml substring + """ cmd_result = virsh.dumpxml(vm_name, debug=True) libvirt.check_exit_status(cmd_result) # The xml should contain the match_string xml = cmd_result.stdout.strip() - match_string = "" - if not re.search(match_string, xml): + if not re.search(xml_after, xml): raise exceptions.TestFail("After domain restore, " "the xml is not expected") @@ -74,6 +78,9 @@ def vm_state_check(): restore_state = params.get("restore_state", "running") vm_save = params.get("vm_save", "vm.save") + xml_before = params.get("xml_before") + xml_after = params.get("xml_after") + try: # Get a tmp_dir. tmp_dir = data_dir.get_tmp_dir() @@ -87,8 +94,7 @@ def vm_state_check(): xml = get_image_xml() - # Replace to - newxml = xml.replace("", "") + newxml = xml.replace(xml_before, xml_after) logging.debug("After string replacement, the new xml is %s", newxml) # Write new xml into a tempfile @@ -108,7 +114,7 @@ def vm_state_check(): libvirt.check_exit_status(cmd_result) os.remove(vm_save) - vm_state_check() + vm_state_check(xml_after) finally: # cleanup diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_save_image_edit.py b/libvirt/tests/src/virsh_cmd/domain/virsh_save_image_edit.py index becdb2911bc..2c835fda187 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_save_image_edit.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_save_image_edit.py @@ -25,8 +25,9 @@ def run(test, params, env): 5) Check the new xml of the VM and its state """ - def edit_image_xml(): - edit_cmd = r":%s //" + def edit_image_xml(xml_before, xml_after): + edit_cmd = r":%s /" + xml_before.replace("/", "\/") + edit_cmd += "/" + xml_after.replace("/", "\/") if restore_state == "running": option = "--running" @@ -44,7 +45,7 @@ def edit_image_xml(): session.sendline("virsh save-image-edit %s %s " % (vm_save, option)) - logging.info("Replace '' to ''") + logging.info(f"Replace {xml_before} to {xml_after}") session.sendline(edit_cmd) session.send('\x1b') session.send('ZZ') @@ -64,8 +65,7 @@ def vm_state_check(): # The xml should contain the match_string xml = cmd_result.stdout.strip() - match_string = "" - if not re.search(match_string, xml): + if not re.search(xml_after, xml): test.fail("After domain restore the xml is not expected") domstate = virsh.domstate(vm_name, debug=True).stdout.strip() @@ -83,6 +83,9 @@ def vm_state_check(): vm_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + xml_before = params.get("xml_before") + xml_after = params.get("xml_after") + try: # Get a tmp_dir. tmp_dir = data_dir.get_tmp_dir() @@ -95,7 +98,7 @@ def vm_state_check(): test.fail("Failed to save running domain %s" % vm_name) # Edit the xml in the saved state file - edit_image_xml() + edit_image_xml(xml_before, xml_after) # Restore domain cmd_result = virsh.restore(vm_save, debug=True) From fddc8f4db02f1c958cc07d2b590928aea11dd30d Mon Sep 17 00:00:00 2001 From: Meina Li Date: Mon, 10 Mar 2025 23:10:34 -0400 Subject: [PATCH 0879/1055] Virtual disk: add 2 new datastore cases Automate two cases: VIRT-303298 [virtual disks][dataStore] Hotplug/unplug disks with data files VIRT-303297 [virtual_disks][dataStore] Start guest with disks that have data files Signed-off-by: Meina Li --- .../virtual_disks/virtual_disks_datastore.cfg | 16 +++ .../virtual_disks/virtual_disks_datastore.py | 97 +++++++++++++++++++ spell.ignore | 1 + 3 files changed, 114 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_disks/virtual_disks_datastore.cfg create mode 100644 libvirt/tests/src/virtual_disks/virtual_disks_datastore.py diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_datastore.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_datastore.cfg new file mode 100644 index 00000000000..a756bd9d013 --- /dev/null +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_datastore.cfg @@ -0,0 +1,16 @@ +- virtual_disks.datastore: + type = virtual_disks_datastore + start_vm = no + target_disk = "vdb" + disk_type = "file" + func_supported_since_libvirt_ver = (10, 10, 0) + data_file_option = " -o data_file=%s" + disk_dict = {"type_name":"${disk_type}", "target":{"dev": "${target_disk}", "bus": "virtio"}, "driver": {"name": "qemu", "type":"qcow2"}} + variants: + - start_vm: + - hotplug_disk: + with_hotplug = "yes" + variants datastore_type: + - with_file: + - with_block: + with_block = "yes" diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_datastore.py b/libvirt/tests/src/virtual_disks/virtual_disks_datastore.py new file mode 100644 index 00000000000..7ed35d17dc7 --- /dev/null +++ b/libvirt/tests/src/virtual_disks/virtual_disks_datastore.py @@ -0,0 +1,97 @@ +import os + +from virttest import data_dir +from virttest import libvirt_version +from virttest import utils_disk +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_disk +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.virtual_disk import disk_base + + +def run(test, params, env): + """ + Start guest with datastore and hotplug disk with datastore. + """ + def prepare_disk(): + """ + Prepare the disk. + + :params return: return the data file of new image. + """ + if with_block: + data_file = libvirt.setup_or_cleanup_iscsi(is_setup=True, is_login=True) + else: + data_file = data_dir.get_data_dir() + '/datastore.img' + libvirt.create_local_disk("file", data_file, "50M", "raw") + return data_file + + def hotplug_disk(data_file_option): + """ + Hotplug disk device. + + :params data_file_option: the option to create image with data file + :params return: return the new image path + """ + if not vm.is_alive(): + vm.start() + _, new_image_path = disk_obj.prepare_disk_obj(disk_type, disk_dict, new_image_path="", + extra=data_file_option) + disk_dict.update({'source': {'attrs': {'file': new_image_path}}}) + disk_dev = libvirt_vmxml.create_vm_device_by_type("disk", disk_dict) + virsh.attach_device(vm_name, disk_dev.xml, debug=True, ignore_status=False, wait_for_event=True) + return new_image_path, disk_dev + + def check_result(): + """ + Check the test result. + """ + if not vm.is_alive(): + vm.start() + vm_session = vm.wait_for_login() + disk_xml = virsh.dumpxml(vm_name, "--xpath //disk", debug=True).stdout_text + if "dataStore" not in disk_xml: + test.fail("Can't get the datastore element automatically!") + test.log.info("TEST_STEP: Do read/write for disk.") + new_disk = libvirt_disk.get_non_root_disk_name(vm_session)[0] + utils_disk.dd_data_to_vm_disk(vm_session, new_disk) + vm_session.close() + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + disk_dict = eval(params.get('disk_dict', '{}')) + disk_type = params.get("disk_type") + with_hotplug = "yes" == params.get("with_hotplug", "no") + with_block = "yes" == params.get("with_block", "no") + libvirt_version.is_libvirt_feature_supported(params) + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vmxml_backup = vmxml.copy() + disk_obj = disk_base.DiskBase(test, vm, params) + + try: + test.log.info("TEST_STEP: Prepare the guest.") + data_file = prepare_disk() + data_file_option = params.get("data_file_option") % data_file + if with_hotplug: + test.log.info("TEST_STEP: Hotplug disk with datastore.") + new_image_path, disk_dev = hotplug_disk(data_file_option) + else: + new_image_path = disk_obj.add_vm_disk(disk_type, disk_dict, new_image_path="", + extra=data_file_option) + test.log.info("TEST_STEP: Check the disk dumpxml.") + check_result() + if with_hotplug: + test.log.info("TEST_STEP: Hot-unplug disk.") + virsh.detach_device(vm_name, disk_dev.xml, debug=True, ignore_status=False, + wait_for_event=True) + finally: + vmxml_backup.sync() + if with_block: + libvirt.setup_or_cleanup_iscsi(is_setup=False) + for file in [new_image_path, data_file]: + if os.path.exists(file): + os.remove(file) diff --git a/spell.ignore b/spell.ignore index 40848d87a7d..a4a849da56d 100644 --- a/spell.ignore +++ b/spell.ignore @@ -1259,3 +1259,4 @@ Meina meili ntp userfaultfd +datastore From e2a2cbdd92706417d4b6630e26e7a470015fd1bd Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Thu, 6 Feb 2025 06:13:28 -0500 Subject: [PATCH 0880/1055] Skip if host ipv6 is not available For cases "virtual_network.passt.attach_detach.ip_portfw.attach_detach" and "virtual_network.passt.interface_function.minimal", if the host ipv6 is not available, skip these test. Signed-off-by: Yalan Zhang --- provider/virtual_network/passt.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/provider/virtual_network/passt.py b/provider/virtual_network/passt.py index 5ece902d511..54a11300342 100644 --- a/provider/virtual_network/passt.py +++ b/provider/virtual_network/passt.py @@ -201,7 +201,13 @@ def check_vm_ip(iface_attrs, session, host_iface, vm_iface=None): raise exceptions.TestFail('vm ip and prefix should be ' 'the same as host') - set_ipv6_info = get_iface_ip_and_prefix(host_iface, ip_ver='ipv6')[0] + host_ipv6_info = get_iface_ip_and_prefix(host_iface, ip_ver='ipv6') + # If the host does not support IPv6, the guest will not support it either, cancel the test + if host_ipv6_info: + set_ipv6_info = host_ipv6_info[0] + else: + raise exceptions.TestCancel(f'Host ipv6 is not available, skip the test!') + # The settings in attrs should take precedence if there is if 'ips' in iface_attrs: iface_ipv6_info = [ip for ip in iface_attrs['ips'] if ip['family'] == 'ipv6'][0] From d93b036c56ee4ec24cc2c647295c1c739cacdde5 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Tue, 11 Mar 2025 05:19:37 -0400 Subject: [PATCH 0881/1055] Change migration related case to migration folder Signed-off-by: liang-cong-red-hat --- .../migration_with_numa_topology.cfg | 2 +- .../migration_with_numa_topology.py | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename libvirt/tests/cfg/{numa/guest_numa_topology => migration}/migration_with_numa_topology.cfg (97%) rename libvirt/tests/src/{numa/guest_numa_topology => migration}/migration_with_numa_topology.py (100%) diff --git a/libvirt/tests/cfg/numa/guest_numa_topology/migration_with_numa_topology.cfg b/libvirt/tests/cfg/migration/migration_with_numa_topology.cfg similarity index 97% rename from libvirt/tests/cfg/numa/guest_numa_topology/migration_with_numa_topology.cfg rename to libvirt/tests/cfg/migration/migration_with_numa_topology.cfg index d70ef24410b..a189dbaa6d2 100644 --- a/libvirt/tests/cfg/numa/guest_numa_topology/migration_with_numa_topology.cfg +++ b/libvirt/tests/cfg/migration/migration_with_numa_topology.cfg @@ -1,4 +1,4 @@ -- guest_numa_topology.migration_with_numa_topology: +- migrate.migration_with_numa_topology: type = migration_with_numa_topology only aarch64 start_vm = 'no' diff --git a/libvirt/tests/src/numa/guest_numa_topology/migration_with_numa_topology.py b/libvirt/tests/src/migration/migration_with_numa_topology.py similarity index 100% rename from libvirt/tests/src/numa/guest_numa_topology/migration_with_numa_topology.py rename to libvirt/tests/src/migration/migration_with_numa_topology.py From 95fe99479753621d691de453c910f13b1cc2160b Mon Sep 17 00:00:00 2001 From: lcheng Date: Sun, 8 Dec 2024 23:26:07 +0800 Subject: [PATCH 0882/1055] migration: Add case to test retain sparsity XXX-302256 - VM live migration with copy storage - retain sparsity Signed-off-by: lcheng --- .../migration_retain_sparsity.cfg | 97 ++++++ .../migration_retain_sparsity.py | 316 ++++++++++++++++++ 2 files changed, 413 insertions(+) create mode 100644 libvirt/tests/cfg/migration_with_copy_storage/migration_retain_sparsity.cfg create mode 100644 libvirt/tests/src/migration_with_copy_storage/migration_retain_sparsity.py diff --git a/libvirt/tests/cfg/migration_with_copy_storage/migration_retain_sparsity.cfg b/libvirt/tests/cfg/migration_with_copy_storage/migration_retain_sparsity.cfg new file mode 100644 index 00000000000..16b1b3a70d0 --- /dev/null +++ b/libvirt/tests/cfg/migration_with_copy_storage/migration_retain_sparsity.cfg @@ -0,0 +1,97 @@ +- migration_with_copy_storage.migration_retain_sparsity: + type = migration_retain_sparsity + migration_setup = 'yes' + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = "" + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = "qemu:///system" + image_convert = "no" + status_error = "no" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + start_vm = "no" + setup_nfs = "no" + nfs_mount_dir = + setup_local_nfs = "no" + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + disk_type = "file" + disk_size = "1G" + dd_count = "100" + disk_path = "/var/lib/avocado/data/avocado-vt/images" + target_dev_1 = "sda" + virsh_migrate_options = "--live --p2p --verbose --migrate-disks-detect-zeroes ${target_dev_1}" + ceph_pool_name = "migration-pool" + check_disk_after_mig = "yes" + check_disk_kname_after_mig = "${target_dev_1}" + libvirtd_file_type = "virtqemud" + libvirtd_debug_level = "1" + libvirtd_debug_filters = "1:*" + libvirtd_debug_file = "/var/log/libvirt/virtqemud.log" + check_str_local_log = '['"discard":"unmap","detect-zeroes":"unmap"']' + variants: + - copy_storage_all: + copy_storage_option = "--copy-storage-all" + - copy_storage_inc: + copy_storage_option = "--copy-storage-inc" + variants: + - src1_rbd: + src_driver_type_1 = "rbd" + disk_size = "100M" + dd_count = "10" + src_disk1_name = "retain_sparsity_test_disk1" + src_disk1_dict = {"device": "disk", "type_name": "block", "driver": {"name": "qemu", "type": "raw"}, "target": {"dev": "${target_dev_1}", "bus": "scsi"}} + - src1_raw: + src_driver_type_1 = "raw" + src_disk1_name = "retain_sparsity_test_disk1.img" + src_disk1_dict = {"device": "disk", "type_name": "file", "driver": {"name": "qemu", "type": "raw"}, "target": {"dev": "${target_dev_1}", "bus": "scsi"}, "source": {"attrs": {"file": "${disk_path}/${src_disk1_name}"}}} + - src1_qcow2: + src_driver_type_1 = "qcow2" + src_disk1_name = "retain_sparsity_test_disk1.img" + src_disk1_dict = {"device": "disk", "type_name": "file", "driver": {"name": "qemu", "type": "qcow2"}, "target": {"dev": "${target_dev_1}", "bus": "scsi"}, "source": {"attrs": {"file": "${disk_path}/${src_disk1_name}"}}} + variants: + - dest1_rbd: + disk_size = "100M" + dd_count = "10" + dest_device_type_1 = "block" + dest_driver_type_1 = "rbd" + dest_disk1_name = "retain_sparsity_test_disk2" + dest_disk1_dict = {"device": "disk", "type_name": "${dest_device_type_1}", "driver": {"name": "qemu", "type": "raw"}, "target": {"dev": "${target_dev_1}", "bus": "scsi"}} + - dest1_raw: + dest_device_type_1 = "file" + dest_driver_type_1 = "raw" + dest_disk1_name = "${src_disk1_name}" + dest_disk1_dict = {"device": "disk", "type_name": "${dest_device_type_1}", "driver": {"name": "qemu", "type": "raw"}, "target": {"dev": "${target_dev_1}", "bus": "scsi"}, "source": {"attrs": {"file": "${disk_path}/${dest_disk1_name}"}}} + - dest1_qcow2: + dest_device_type_1 = "file" + dest_driver_type_1 = "qcow2" + dest_disk1_name = "${src_disk1_name}" + dest_disk1_dict = {"device": "disk", "type_name": "${dest_device_type_1}", "driver": {"name": "qemu", "type": "qcow2"}, "target": {"dev": "${target_dev_1}", "bus": "scsi"}, "source": {"attrs": {"file": "${disk_path}/${dest_disk1_name}"}}} + variants: + - disk_num_1: + - disk_num_2: + disk2_name = "retain_sparsity_test_disk2.img" + target_dev_2 = "sdb" + virsh_migrate_options = "--live --p2p --verbose --migrate-disks-detect-zeroes ${target_dev_1},${target_dev_2}" + variants: + - src2_raw: + src_driver_type_2 = "raw" + - src2_qcow2: + src_driver_type_2 = "qcow2" + variants: + - dest2_raw: + dest_driver_type_2 = "raw" + - dest2_qcow2: + dest_driver_type_2 = "qcow2" + src_disk2_dict = {"device": "disk", "type_name": "file", "driver": {"name": "qemu", "type": "${src_driver_type_2}"}, "target": {"dev": "${target_dev_2}", "bus": "scsi"}, "source": {"attrs": {"file": "${disk_path}/${disk2_name}"}}} + dest_disk2_dict = {"device": "disk", "type_name": "file", "driver": {"name": "qemu", "type": "${dest_driver_type_2}"}, "target": {"dev": "${target_dev_2}", "bus": "scsi"}, "source": {"attrs": {"file": "${disk_path}/${disk2_name}"}}} diff --git a/libvirt/tests/src/migration_with_copy_storage/migration_retain_sparsity.py b/libvirt/tests/src/migration_with_copy_storage/migration_retain_sparsity.py new file mode 100644 index 00000000000..484723cd8ed --- /dev/null +++ b/libvirt/tests/src/migration_with_copy_storage/migration_retain_sparsity.py @@ -0,0 +1,316 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: Liping Cheng +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +import os +import shutil + +from avocado.utils import process + +from virttest import data_dir +from virttest import remote +from virttest import utils_misc + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_disk +from virttest.utils_libvirt import libvirt_vmxml +from virttest.libvirt_xml.devices import disk + +from provider.migration import base_steps + + +def prepare_disks_local(params, vm_name): + """ + Prepare disks on local host + + :param params: dictionary with the test parameter + :param vm_name: vm name + :return: rbd device name on source host + """ + src_disk1_dict = eval(params.get("src_disk1_dict")) + src_driver_type_1 = params.get("src_driver_type_1") + src_disk1_name = params.get("src_disk1_name") + disk_size = params.get("disk_size") + disk_path = params.get("disk_path") + disk2_name = params.get("disk2_name") + src_rbd_dev = None + + def _prepare_disk_xml(disk_name, disk_format, disk_dict): + """ + Prepare disk xml + + :param disk_name: disk name + :param disk_format: disk format + :param disk_dict: disk dict + """ + disk_file = os.path.join(disk_path, disk_name) + if os.path.exists(disk_file): + os.remove(disk_file) + libvirt_disk.create_disk("file", size=disk_size, disk_format=disk_format, path=disk_file) + vmxml.add_device(libvirt_vmxml.create_vm_device_by_type("disk", disk_dict)) + vmxml.sync() + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + if src_driver_type_1 == "rbd": + ceph_pool_name = params.get("ceph_pool_name") + cmd1 = f"rbd create {ceph_pool_name}/{src_disk1_name} --size={disk_size}" + process.run(cmd1, shell=True, verbose=True) + cmd2 = f"rbd device map --pool {ceph_pool_name} {src_disk1_name}" + src_rbd_dev = process.run(cmd2, shell=True, verbose=True).stdout_text.strip() + src_disk1_dict.update({'source': {'attrs': {'dev': src_rbd_dev}}}) + vmxml.add_device(libvirt_vmxml.create_vm_device_by_type("disk", src_disk1_dict)) + vmxml.sync() + else: + _prepare_disk_xml(src_disk1_name, src_driver_type_1, src_disk1_dict) + + if disk2_name: + _prepare_disk_xml(disk2_name, params.get("src_driver_type_2"), eval(params.get("src_disk2_dict"))) + return src_rbd_dev + + +def prepare_disks_remote(params): + """ + Prepare disks on remote host + + :param params: dictionary with the test parameter + :return: rbd device name on target host and updated disk dict + """ + dest_disk1_dict = eval(params.get("dest_disk1_dict")) + dest_driver_type_1 = params.get("dest_driver_type_1") + dest_disk1_name = params.get("dest_disk1_name") + disk_size = params.get("disk_size") + disk_path = params.get("disk_path") + disk2_name = params.get("disk2_name") + server_ip = params.get("server_ip") + server_user = params.get("server_user") + server_pwd = params.get("server_pwd") + dest_rbd_dev = None + + remote_session = remote.remote_login("ssh", server_ip, "22", + server_user, server_pwd, + r'[$#%]') + if dest_driver_type_1 == "rbd": + ceph_pool_name = params.get("ceph_pool_name") + cmd1 = f"rbd create {ceph_pool_name}/{dest_disk1_name} --size={disk_size}" + remote.run_remote_cmd(cmd1, params) + cmd2 = f"rbd device map --pool {ceph_pool_name} {dest_disk1_name}" + dest_rbd_dev = remote.run_remote_cmd(cmd2, params).stdout_text.strip() + dest_disk1_dict.update({'source': {'attrs': {'dev': dest_rbd_dev}}}) + else: + disk_file = os.path.join(disk_path, dest_disk1_name) + utils_misc.make_dirs(disk_path, remote_session) + libvirt_disk.create_disk("file", path=disk_file, + size=disk_size, disk_format=dest_driver_type_1, + session=remote_session) + + if disk2_name: + disk2_file = os.path.join(disk_path, disk2_name) + libvirt_disk.create_disk("file", path=disk2_file, + size=disk_size, disk_format=params.get("dest_driver_type_2"), + session=remote_session) + remote_session.close() + return dest_rbd_dev, dest_disk1_dict + + +def prepare_migratable_xml(vm_name, device_type, disk1_dict, test, disk2_dict=None): + """ + Prepare migratable xml + + :param vm_name: vm name + :param device_type: device type + :param disk1_dict: disk1 dict + :param test: test object + :param disk2_dict: disk2 dict + """ + test.log.debug("Prepare migratable xml.") + mig_disk1 = disk.Disk(type_name=device_type) + mig_disk1.setup_attrs(**disk1_dict) + if disk2_dict: + mig_disk2 = disk.Disk(type_name="file") + mig_disk2.setup_attrs(**eval(disk2_dict)) + + guest_xml = vm_xml.VMXML.new_from_dumpxml(vm_name, options="--migratable") + guest_xml.add_device(mig_disk1) + if disk2_dict: + guest_xml.add_device(mig_disk2) + guest_xml.xmltreefile.write() + tmp_dir = data_dir.get_tmp_dir() + xmlfile = os.path.join(tmp_dir, "xml_file") + shutil.copyfile(guest_xml.xml, xmlfile) + test.log.debug(f"migratable xml: {xmlfile}") + return xmlfile + + +def get_disk_size(disk_file, remote_host=False, params=False): + """ + Get disk size + + :param disk_file: disk file + :param remote_host: if true, get disk size on target host + :param params: dictionary with the test parameters + :return: disk size + """ + cmd = f"qemu-img info {disk_file} -U" + if remote_host: + ret = remote.run_remote_cmd(cmd, params).stdout_text.strip() + else: + ret = process.run(cmd, shell=True).stdout_text.strip() + return ret.split('\n')[3].split(':')[1].strip() + + +def run(test, params, env): + """ + To verify that live migration with copying storage can retain sparsity with + option --migrate-disks-detect-zeroes. + + :param test: test object + :param params: dictionary with the test parameters + :param env: dictionary with test environment. + """ + def setup_test(): + """ + Setup steps + + """ + src_disk1_name = params.get("src_disk1_name") + dest_disk1_dict = eval(params.get("dest_disk1_dict")) + ceph_pool_name = params.get("ceph_pool_name") + target_dev_1 = params.get("target_dev_1") + target_dev_2 = params.get("target_dev_2") + disk2_name = params.get("disk2_name") + + test.log.info("Setup steps.") + migration_obj.setup_connection() + base_steps.prepare_disks_remote(params, vm) + + nonlocal dest_rbd_dev + dest_rbd_dev, dest_disk1_dict = prepare_disks_remote(params) + test.log.debug(f"dest_disk1_dict: {dest_disk1_dict}") + test.log.debug(f"dest_rbd_dev: {dest_rbd_dev}") + xmlfile = prepare_migratable_xml(vm_name, params.get("dest_device_type_1"), + dest_disk1_dict, test, + disk2_dict=params.get("dest_disk2_dict")) + params.update({"virsh_migrate_extra": "--xml %s" % xmlfile}) + + nonlocal src_rbd_dev + src_rbd_dev = prepare_disks_local(params, vm_name) + test.log.debug(f"src_rbd_dev: {src_rbd_dev}") + + vm.start() + vm_session = vm.wait_for_serial_login(timeout=120) + vm_session.cmd(f"mkfs.xfs /dev/{target_dev_1}", timeout=600) + vm_session.cmd(f"dd if=/dev/random of=/dev/{target_dev_1} bs=1048576 count={params.get('dd_count')}") + if disk2_name: + vm_session.cmd(f"mkfs.xfs /dev/{target_dev_2}", timeout=100) + vm_session.cmd(f"dd if=/dev/random of=/dev/{target_dev_2} bs=1048576 count={params.get('dd_count')}") + vm_session.close() + + nonlocal old_disk_size + if params.get("src_driver_type_1") == "rbd": + cmd = f"rbd du --pool={ceph_pool_name} | grep {src_disk1_name}" + old_disk_size.append(process.run(cmd, shell=True).stdout_text.strip().split(" ")[-1]) + else: + old_disk_size.append(get_disk_size(os.path.join(disk_path, src_disk1_name))) + if disk2_name: + old_disk_size.append(get_disk_size(os.path.join(disk_path, disk2_name))) + test.log.debug(f"old disk size: {old_disk_size}") + + def verify_test(): + """ + Verify steps + + """ + dest_disk1_name = params.get("dest_disk1_name") + disk2_name = params.get("disk2_name") + ceph_pool_name = params.get("ceph_pool_name") + disk_size = params.get("disk_size") + + test.log.info("Verify steps.") + if params.get("dest_driver_type_1") == "rbd": + cmd = f"rbd du --pool={ceph_pool_name} | grep {dest_disk1_name}" + new_disk_size = remote.run_remote_cmd(cmd, params).stdout_text.strip().split(' ')[-1].split(' ') + else: + new_disk_size = get_disk_size(os.path.join(disk_path, dest_disk1_name), remote_host=True, params=params).split(' ') + if new_disk_size[1][0] == disk_size[-1]: + if float(new_disk_size[0]) == float(disk_size[:-1]): + test.fail(f"Disk1 usage should not be {disk_size}: before migrate: {old_disk_size[0]}, after migrate: {new_disk_size}") + if disk2_name: + disk2_size = get_disk_size(os.path.join(disk_path, disk2_name), remote_host=True, params=params).split(' ') + if disk2_size[1][0] == disk_size[-1]: + if float(disk2_size[0]) == float(disk_size[:-1]): + test.fail(f"Disk2 usage should not be {disk_size}: before migrate: {old_disk_size[1]}, after migrate: {disk2_size}") + migration_obj.verify_default() + + def cleanup_test(): + """ + Cleanup steps + + """ + src_disk1_name = params.get("src_disk1_name") + dest_disk1_name = params.get("dest_disk1_name") + disk2_name = params.get("disk2_name") + ceph_pool_name = params.get("ceph_pool_name") + + def _remove_disk_local(disk_name): + """ + Remove disk on local + + :param disk_name: disk name + """ + disk_file = os.path.join(disk_path, disk_name) + if os.path.exists(disk_file): + os.remove(disk_file) + + def _remove_disk_remote(disk_name): + """ + Remove disk on remote + + :param disk_name: disk name + """ + disk_file = os.path.join(disk_path, disk_name) + remote.run_remote_cmd(f"rm -f {disk_file}", params, ignore_status=False) + + test.log.info("Cleanup steps.") + migration_obj.cleanup_connection() + if params.get("dest_driver_type_1") == "rbd": + cmd = f"rbd unmap {dest_rbd_dev}" + remote.run_remote_cmd(cmd, params) + cmd2 = f"rbd remove --pool {ceph_pool_name} {dest_disk1_name}" + remote.run_remote_cmd(cmd2, params) + else: + _remove_disk_remote(dest_disk1_name) + if disk2_name: + _remove_disk_remote(disk2_name) + + if params.get("src_driver_type_1") == "rbd": + cmd = f"rbd unmap {src_rbd_dev}" + process.run(cmd, shell=True, verbose=True) + cmd2 = f"rbd remove --pool {ceph_pool_name} {src_disk1_name}" + process.run(cmd2, shell=True, verbose=True) + else: + _remove_disk_local(src_disk1_name) + if disk2_name: + _remove_disk_local(disk2_name) + base_steps.cleanup_disks_remote(params, vm) + + vm_name = params.get("migrate_main_vm") + disk_path = params.get("disk_path") + old_disk_size = [] + src_rbd_dev = None + dest_rbd_dev = None + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + setup_test() + migration_obj.run_migration() + verify_test() + finally: + cleanup_test() From 7682eb1b0ab0a2b1e0a5440b1b9172f247fc5609 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Wed, 12 Mar 2025 03:27:37 -0400 Subject: [PATCH 0883/1055] Fix path problem for nbdkit cve-starttls case Signed-off-by: Ming Xie --- v2v/tests/src/nbdkit/nbdkit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2v/tests/src/nbdkit/nbdkit.py b/v2v/tests/src/nbdkit/nbdkit.py index fa95c94e925..e92df31989b 100644 --- a/v2v/tests/src/nbdkit/nbdkit.py +++ b/v2v/tests/src/nbdkit/nbdkit.py @@ -570,7 +570,7 @@ def cve_starttls(): ignore_status=True) process.run('cd %s ; rpmbuild -rp %s' % (tmp_path, (process.run('ls %s/nbdkit*.src.rpm' % tmp_path, shell=True). stdout_text.split('/'))[-1].strip('\n')), shell=True) - check_file = process.run('ls /root/rpmbuild/BUILD/nbdkit-*/server/protocol-handshake-newstyle.c', + check_file = process.run('ls /rpmbuild/BUILD/nbdkit-*/server/protocol-handshake-newstyle.c', shell=True).stdout_text.strip('\n') count = 0 with open(check_file, "r") as ff: From 7c82ea556f9b7446cc3178684f15bf361496d76a Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Thu, 13 Mar 2025 12:49:16 +0800 Subject: [PATCH 0884/1055] v2v:add new case on non-int-disk guest Signed-off-by: vwu-vera --- v2v/tests/cfg/function_test_esx.cfg | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 6e00af407f8..f3ed54b180f 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -946,6 +946,10 @@ main_vm = VM_NAME_DVS_NET_NO_PORTID_CONNECTIONID_V2V_EXAMPLE skip_vm_check = yes skip_reason = 'Bug RHEL-732 is not fixed' + - non_int_disk: + only esx_80 + main_vm = VM_NAME_NON_INT_DISK_V2V_EXAMPLE + version_required = "[nbdkit-1.36.2-2,)" variants: - positive_test: status_error = 'no' From 0d3180c8d598da3dcea35b2d2123862654af66d3 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Wed, 15 Jan 2025 08:50:06 -0500 Subject: [PATCH 0885/1055] Remove saved file by managedsave-remove cmd Remove saved file by managedsave-remove cmd with various situations. Signed-off-by: Yalan Zhang --- .../save_and_restore/managedsave_remove.cfg | 17 +++ .../save_and_restore/managedsave_remove.py | 108 ++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 libvirt/tests/cfg/save_and_restore/managedsave_remove.cfg create mode 100644 libvirt/tests/src/save_and_restore/managedsave_remove.py diff --git a/libvirt/tests/cfg/save_and_restore/managedsave_remove.cfg b/libvirt/tests/cfg/save_and_restore/managedsave_remove.cfg new file mode 100644 index 00000000000..6e68079bb2d --- /dev/null +++ b/libvirt/tests/cfg/save_and_restore/managedsave_remove.cfg @@ -0,0 +1,17 @@ +- save_and_restore.managedsave_remove: + type = managedsave_remove + start_vm = yes + status_error = no + variants: + - normal: + file_state = normal + only managedsaved + - corrupt: + file_state = corrupt + - nonexist: + file_state = nonexist + variants: + - managedsaved: + vm_managedsaved = yes + - not_managedsaved: + vm_managedsaved = no diff --git a/libvirt/tests/src/save_and_restore/managedsave_remove.py b/libvirt/tests/src/save_and_restore/managedsave_remove.py new file mode 100644 index 00000000000..30fdfd36507 --- /dev/null +++ b/libvirt/tests/src/save_and_restore/managedsave_remove.py @@ -0,0 +1,108 @@ +import os +import logging +from virttest import virsh +from avocado.utils import process +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test command: virsh managedsave-remove + + Remove the managedsave state file for a domain, if it exists. + This ensures the domain will do a full boot the next time it + is started. + """ + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + managed_save_file = "/var/lib/libvirt/qemu/save/%s.save" % vm_name + + def setup(): + """" + Prepare the pre-conditions + 1. Managedsave vm if needed + 2. Prepare an invalid saved file if needed + 3. Remove the saved file if needed + """ + if not vm.is_alive(): + vm.start() + if vm_managedsaved: + virsh.managedsave(vm_name, debug=True) + if file_state == "corrupt": + process.run("echo > %s" % managed_save_file, shell=True, ignore_status=True) + elif file_state == "nonexist" and vm_managedsaved: + process.run("rm -f %s" % managed_save_file, shell=True, ignore_status=True) + + file_state = params.get("file_state") + vm_managedsaved = "yes" == params.get("vm_managedsaved") + expected_fails = None + expected_match = None + if vm_managedsaved and file_state == 'nonexist': + expected_fails = 'No such file or directory' + if vm_managedsaved and file_state != 'nonexist': + expected_match = 'Removed managedsave image' + if not vm_managedsaved: + expected_match = 'removal skipped' + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bk_xml = vmxml.copy() + + try: + LOG.info("Step1: Setup before the managedsave-remove and " + "check vm state:") + setup() + # check VM's status after setup, managedsave vm should + # be inactive with "saved" states. + dom_state = virsh.dom_list("--all --managed-save", + debug=True).stdout.strip().splitlines() + vm_state = str([item for item in dom_state if vm_name in item]) + LOG.info("vm %s state is %s", vm_name, vm_state) + if vm_managedsaved: + if "saved" not in vm_state: + test.fail("The domain state should includes 'saved'!") + else: + LOG.info("Found expected state 'saved' in %s state", vm_name) + else: + if "running" not in vm_state: + test.fail("vm should be running!") + else: + LOG.info("Found expected state 'running' in %s state", vm_name) + LOG.info("Step2: Do managedsave-remove:") + ret = virsh.managedsave_remove(vm_name, debug=True) + LOG.debug("%s", ret) + libvirt.check_result(ret, expected_fails=expected_fails, + expected_match=expected_match) + LOG.info("Step3: Check the vm state:") + dom_state1 = virsh.dom_list("--all --managed-save", + debug=True).stdout.strip().splitlines() + vm_state1 = str([item for item in dom_state1 if vm_name in item]) + LOG.info("vm %s state is %s", vm_name, vm_state1) + # Normally, when vm in 'saved' state, it should be 'shut off' after removal + if vm_managedsaved: + if file_state == 'nonexist' and "saved" not in vm_state1: + test.fail("The domain state should not change!") + if file_state != 'nonexist' and "shut off" not in vm_state1: + test.fail("The domain state should change to 'shut off'!") + else: + if "running" not in vm_state: + test.fail("vm should be running!") + else: + LOG.info("Found expected state 'running' in %s state", vm_name) + LOG.info("step4: Check the saved file") + if os.path.exists(managed_save_file): + LOG.info("The saved file exists: %s", managed_save_file) + if vm_managedsaved or file_state != 'corrupt': + test.fail("There should not be saved file after removal") + else: + LOG.info("Saved file does not exists!") + if vm_managedsaved and file_state == 'nonexist': + virsh.undefine(vm_name, '--managed-save --keep-nvram', debug=True) + finally: + virsh.managedsave_remove(vm_name, debug=True) + if os.path.exists(managed_save_file): + process.run("rm -f %s" % managed_save_file, shell=True, ignore_status=True) + bk_xml.sync() From f90149de9f57607b3ade6f0544475f86ed6b169a Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Sun, 16 Mar 2025 19:16:54 -0400 Subject: [PATCH 0886/1055] Update case update_iface_qos_invalid Add more boundry test Signed-off-by: Haijiao Zhao --- .../update_device/update_iface_qos_invalid.cfg | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_iface_qos_invalid.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_iface_qos_invalid.cfg index 4890a3608b4..e7745b141b9 100644 --- a/libvirt/tests/cfg/virtual_network/update_device/update_iface_qos_invalid.cfg +++ b/libvirt/tests/cfg/virtual_network/update_device/update_iface_qos_invalid.cfg @@ -10,11 +10,19 @@ err_msg = could not convert bandwidth average value|Expected non-negative integer value - big_value: func_supported_since_libvirt_ver = (10,8,0) - update_attrs = {'bandwidth': {'inbound': {'average': '100000000000000000', 'peak': '5000', 'burst': '1024'}}} - err_msg = numerical overflow: value .* is too big for 'average' parameter, maximum is + variants: + - average: + update_attrs = {'bandwidth': {'inbound': {'average': '100000000000000000', 'peak': '5000', 'burst': '1024'}}} + err_msg = numerical overflow: value .* is too big for 'average' parameter, maximum is + - peak: + update_attrs = {'bandwidth': {'inbound': {'average': '5000', 'peak': '100000000000000000', 'burst': '1024'}}} + err_msg = numerical overflow: value .* is too big for 'peak' parameter, maximum is + - burst: + update_attrs = {'bandwidth': {'inbound': {'average': '1024000', 'peak': '4096', 'burst': '4194304'}}} + err_msg = numerical overflow: value .* is too big for 'burst' parameter, maximum is - max_value: func_supported_since_libvirt_ver = (10,8,0) - update_attrs = {'bandwidth': {'inbound': {'average': '18014398509481984', 'peak': '5000', 'burst': '1024'}}} + update_attrs = {'bandwidth': {'inbound': {'average': '18014398509481984', 'peak': '5000', 'burst': '4194303'}}} status_error = no - no_mandatory_average: update_attrs = {'bandwidth': {'outbound': {'peak': '5000', 'burst': '1024'}}} From fd424909377fb5e1e490d16fdedaf123d077441b Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Tue, 18 Mar 2025 03:04:18 -0400 Subject: [PATCH 0887/1055] Update the option for test cmd Replace the test command option '-a' with '-e', since '-e' is to check if the file exists. Signed-off-by: Yalan Zhang --- libvirt/tests/src/virtual_network/passt/passt_transfer_file.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py index 7e79883b48e..4f26249a25e 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py +++ b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py @@ -48,7 +48,7 @@ def transfer_host_to_vm(session, prot, ip_ver, params, test): cmd_transfer = eval(params.get('cmd_transfer')) process.run(cmd_transfer, shell=True) - if session.cmd_status(f'test -a {rec_file}') != 0: + if session.cmd_status(f'test -e {rec_file}') != 0: test.fail(f'VM did not recieve {rec_file}') vm_file_md5 = session.cmd_output(f'md5sum {rec_file}') vm_file_md5 = vm_file_md5.split()[0] From 430c2f40df86c38669e67cb50a2c564bdcc057c0 Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 24 Feb 2025 23:35:18 +0800 Subject: [PATCH 0888/1055] migration: Add case about vtpm state on block device XXX-303897 - Migrate vm with vtpm state on block device Signed-off-by: lcheng --- ...migration_with_vtpm_state_on_block_dev.cfg | 69 ++++ .../migration_with_vtpm_state_on_block_dev.py | 345 ++++++++++++++++++ provider/migration/migration_vtpm.py | 153 ++++++++ 3 files changed, 567 insertions(+) create mode 100644 libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.cfg create mode 100644 libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.py create mode 100644 provider/migration/migration_vtpm.py diff --git a/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.cfg b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.cfg new file mode 100644 index 00000000000..2a732ce4721 --- /dev/null +++ b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.cfg @@ -0,0 +1,69 @@ +- migration_with_vtpm.migration_with_vtpm_state_on_block_dev: + type = migration_with_vtpm_state_on_block_dev + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = "" + # SSH connection time out + ssh_timeout = 60 + start_vm = "no" + # Local URI + virsh_migrate_connect_uri = "qemu:///system" + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + transport_type = "ssh" + migrate_desturi_type = "ssh" + virsh_migrate_desturi = "qemu+ssh://${migrate_dest_host}/system" + tpm_cmd = "tpm2_getrandom --hex 16" + auth_sec_dict = {"sec_ephemeral": "no", "sec_private": "yes", "sec_desc": "sample vTPM secret", "sec_usage": "vtpm", "sec_name": "VTPM_example"} + src_secret_value = "sec value test" + src_secret_value_path = "/var/tmp/src_secretinfile" + dst_secret_value = ${src_secret_value} + dst_secret_value_path = "/var/tmp/dst_secretinfile" + status_error = "no" + func_supported_since_libvirt_ver = (10, 10, 0) + block_path = "/iscsiswtpm" + libvirtd_debug_file = '/var/log/libvirt/virtqemud.log' + libvirtd_debug_filters = "1:*" + libvirtd_debug_level = "1" + libvirtd_file_type = "virtqemud" + unexpected_in_list_1 = "['support explicit locking']" + expected_in_list_1 = "['swtpm socket.*--tpmstate.*,lock']" + expected_in_list_2 = "['qemuTPMVirCommandSwtpmAddTPMState.*This swtpm version doesn\'t support explicit locking', '--tpmstate dir=/test/myDir,mode=0600']" + unexpected_in_list_3 = "['swtpm socket.*--tpmstate.*,lock']" + expected_in_list_3 = "['qemuTPMGetSwtpmSetupStateArg.*This swtpm version doesn\'t support explicit locking', '--tpmstate dir=/test/myDir,mode=0600']" + tpm_model = "tpm-crb" + aarch64: + tpm_model = "tpm-tis" + variants test_case: + - auto_create_dir: + block_dir = "${block_path}/mig_vtpm_auto_dir_test" + tpm_dict = {'tpm_model': '${tpm_model}', 'backend': {'backend_type': 'emulator', 'backend_version': '2.0', 'encryption_secret': '0051c505-1ad0-4d77-9b3e-360c8f5e3b86', 'source': {'type': 'dir', 'path': '${block_dir}'}}} + check_lables_1 = '[r"tss tss system_u:object_r:virt_var_lib_t:s0.*.lock", r"tss tss system_u:object_r:virt_var_lib_t:s0.*tpm2-00.permall"]' + check_lables_2 = '[r"tss tss system_u:object_r:svirt_image_t:s0:c.*.lock", r"tss tss system_u:object_r:svirt_image_t:s0:c.*tpm2-00.permall"]' + check_lables_3 = '[r"tss tss system_u:object_r:virt_var_lib_t:s0.*.lock", r"tss tss system_u:object_r:virt_var_lib_t:s0.*tpm2-00.permall"]' + - manual_create_dir: + block_dir = "${block_path}/mig_vtpm_manual_dir_test" + tpm_dict = {'tpm_model': '${tpm_model}', 'backend': {'backend_type': 'emulator', 'backend_version': '2.0', 'encryption_secret': '0051c505-1ad0-4d77-9b3e-360c8f5e3b86', 'source': {'type': 'dir', 'path': '${block_dir}'}}} + check_lables_1 = '[r"root root system_u:object_r:virt_var_lib_t:s0.*.", r"root root unconfined_u:object_r:virt_var_lib_t:s0.*.."]' + check_lables_2 = '[r"tss tss system_u:object_r:svirt_image_t:s0:c.*.lock", r"tss tss system_u:object_r:svirt_image_t:s0:c.*tpm2-00.permall"]' + check_lables_3 = '[r"tss tss system_u:object_r:virt_var_lib_t:s0.*.lock", r"tss tss system_u:object_r:virt_var_lib_t:s0.*tpm2-00.permall"]' + - auto_create_file: + dir_name = "mig_vtpm_auto_file_test" + file_name = "${dir_name}2-00.permall" + block_dir = "${block_path}/{dir_name}" + tpm_dict = {'tpm_model': '${tpm_model}', 'backend': {'backend_type': 'emulator', 'backend_version': '2.0', 'encryption_secret': '0051c505-1ad0-4d77-9b3e-360c8f5e3b86', 'source': {'type': 'file', 'path': '${block_dir}/${file_name}'}}} + check_lables_1 = '[r"tss tss system_u:object_r:virt_var_lib_t:s0.*.", r"root root unconfined_u:object_r:default_t:s0.*.."]' + check_lables_2 = '[r"tss tss system_u:object_r:svirt_image_t:s0:c.*${file_name}"]' + check_lables_3 = '[r"tss tss system_u:object_r:virt_var_lib_t:s0.*${file_name}"]' diff --git a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.py b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.py new file mode 100644 index 00000000000..f8fce8fc5a5 --- /dev/null +++ b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.py @@ -0,0 +1,345 @@ +import os +import re + +from avocado.utils import process + +from virttest import libvirt_version +from virttest import remote +from virttest import utils_disk +from virttest import utils_test +from virttest import virsh + +from virttest.utils_test import libvirt + +from provider.migration import base_steps +from provider.migration import migration_vtpm + + +def check_labels(params, dir_name, expected_labels, test, remote_host=False): + """ + Check tpm state files' labels + + :param params: Dictionary with the test parameters + :param dir_name: dir name + :param expected_labels: Expected labels + :param test: test object + :param remote_host: if True, will check dir on target host + """ + test.log.debug(f"expected labels: {expected_labels}") + cmd = "ls -alZ %s" % dir_name + if remote_host: + ret = remote.run_remote_cmd(cmd, params, ignore_status=False).stdout_text.strip() + else: + ret = process.run(cmd, shell=True, verbose=True).stdout_text.strip() + for item in expected_labels: + if not re.findall(item, ret): + test.fail(f"Unable to find {item} in {ret}") + + +def check_dir(params, dir_name, test, remote_host=False): + """ + Check dir + + :param params: Dictionary with the test parameters + :param dir_name: dir name + :param test: test object + :param remote_host: if True, will check dir on target host + """ + if remote_host: + cmd = f"ls -A {dir_name}" + ret = remote.run_remote_cmd(cmd, params, ignore_status=True).stdout_text.strip() + else: + ret = os.listdir(dir_name) + if len(ret) != 0: + test.fail(f"{dir_name} is not empty: {ret}") + + +def check_items(expected_list, log_file, test, str_in_log=True): + """ + Check log in file + + :param expected_list: Expected list + :param log_file: log file name + :param test: test object + :param str_in_log: if true, check string in log + """ + if str_in_log: + for item in expected_list: + if not re.findall(item, log_file): + test.fail(f"Not found '{item}' in log.") + else: + for item in expected_list: + if re.findall(item, log_file): + test.fail(f"Found '{item}' in log.") + + +def check_capability(params, test): + """ + Check capability + + :param params: Dictionary with the test parameters + :param test: test object + """ + with open(params.get("libvirtd_debug_file"), 'r') as f: + log_file = f.read() + if migration_vtpm.compare_swtpm_version(0, 10): + cmd = "swtpm socket --print-capabilities" + ret = process.run(cmd, shell=True, verbose=True).stdout_text.strip() + if "tpmstate-opt-lock" not in ret: + test.fail(f"Not found 'tpmstate-opt-lock' in {ret}") + + check_items(eval(params.get("unexpected_list_1", "[]")), log_file, test, str_in_log=False) + check_items(eval(params.get("expected_list_1"), "[]"), log_file, test) + else: + if libvirt_version.version_compare(11, 0, 0): + check_items(eval(params.get("expected_list_2"), "[]"), log_file, test) + else: + check_items(eval(params.get("unexpected_list_3", "[]")), log_file, test, str_in_log=False) + check_items(eval(params.get("expected_list_3", "[]")), log_file, test) + + +def prepare_iscsi_disk(params, test, block_dev): + """ + Prepare iscsi disk for test + + :param params: Dictionary with the test parameters + :param test: test object + :param block_dev: block device + """ + client_ip = params.get("client_ip") + block_path = params.get("block_path") + dev_src = None + dev_target = None + target_luns = None + + test.log.info("prepare iscsi disk") + dev_src = libvirt.setup_or_cleanup_iscsi(is_setup=True, + is_login=True, + image_size="1G", + emulated_image="emulated-iscsi-1", + portal_ip=client_ip) + + target_luns, _ = libvirt.setup_or_cleanup_iscsi(is_setup=True, + is_login=False, + image_size="1G", + emulated_image="emulated-iscsi-2", + portal_ip=client_ip) + test.log.debug(f"target_luns: {target_luns}") + dev_target = block_dev.iscsi_login_setup(client_ip, target_luns) + test.log.debug(f"dev_src: {dev_src}") + test.log.debug(f"dev_target: {dev_target}") + + cmd = f"mkfs.xfs -f {dev_src}" + process.run(cmd, shell=True, verbose=True) + + cmd = f"mkdir -p {block_path}" + process.run(cmd, shell=True, verbose=True) + + cmd = f'semanage fcontext -a -t virt_var_lib_t "{block_path}(/.*)?"' + process.run(cmd, shell=True, verbose=True) + remote.run_remote_cmd(cmd, params, ignore_status=False) + + cmd = f"mkfs.xfs -f {dev_target}" + remote.run_remote_cmd(cmd, params, ignore_status=False) + + cmd = f"mkdir -p {block_path}" + remote.run_remote_cmd(cmd, params, ignore_status=False) + return (dev_src, dev_target, target_luns) + + +def run(test, params, env): + """ + Test migration for vm with vtpm state on block dev. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def setup_auto_create_dir(): + """ + Setup steps for auto_create_dir case + + """ + server_ip = params.get("server_ip") + server_user = params.get("server_user", "root") + server_pwd = params.get("server_pwd") + + test.log.info("Setup steps for auto_create_dir.") + utils_disk.mount(dev_src, block_path) + process.run(f"restorecon -Rv {block_path}", shell=True, verbose=True) + + server_session = remote.wait_for_login("ssh", server_ip, "22", server_user, server_pwd, r"[\#\$]\s*$") + utils_disk.mount(dev_target, block_path, session=server_session) + remote.run_remote_cmd(f"restorecon -Rv {block_path}", params, ignore_status=False) + server_session.close() + + def setup_manual_create_dir(): + """ + Setup steps for manual_create_dir case + + """ + server_ip = params.get("server_ip") + server_user = params.get("server_user", "root") + server_pwd = params.get("server_pwd") + + test.log.info("Setup steps for manual_create_dir.") + process.run(f"mkdir {block_dir}", shell=True, verbose=True) + utils_disk.mount(dev_src, block_dir) + process.run(f"restorecon -Rv {block_path}", shell=True, verbose=True) + + server_session = remote.wait_for_login("ssh", server_ip, "22", server_user, server_pwd, r"[\#\$]\s*$") + remote.run_remote_cmd(f"mkdir {block_dir}", params, ignore_status=False) + utils_disk.mount(dev_target, block_dir, session=server_session) + remote.run_remote_cmd(f"restorecon -Rv {block_path}", params, ignore_status=False) + server_session.close() + + check_labels(params, block_dir, eval(params.get("check_lables_1")), test) + + def setup_auto_create_file(): + """ + Setup steps for auto_create_file + + """ + server_ip = params.get("server_ip") + server_user = params.get("server_user", "root") + server_pwd = params.get("server_pwd") + + test.log.info("Setup steps for auto_create_file.") + process.run(f"mkdir {block_dir}", shell=True, verbose=True) + utils_disk.mount(dev_src, block_dir) + process.run(f"restorecon -Rv {block_dir}", shell=True, verbose=True) + process.run(f"chown tss:tss {block_dir}", shell=True, verbose=True) + + server_session = remote.wait_for_login("ssh", server_ip, "22", server_user, server_pwd, r"[\#\$]\s*$") + remote.run_remote_cmd(f"mkdir {block_dir}", params, ignore_status=False) + utils_disk.mount(dev_target, block_dir, session=server_session) + remote.run_remote_cmd(f"restorecon -Rv {block_dir}", params, ignore_status=False) + remote.run_remote_cmd(f"chown tss:tss {block_dir}", params, ignore_status=False) + server_session.close() + + check_labels(params, block_dir, eval(params.get("check_lables_1")), test) + + def setup_test(): + """ + Setup steps + + """ + test.log.info("Setup steps.") + nonlocal dev_src, dev_target, target_luns + dev_src, dev_target, target_luns = prepare_iscsi_disk(params, test, block_dev) + migration_obj.setup_connection() + + if test_case == "auto_create_dir": + setup_auto_create_dir() + elif test_case == "manual_create_dir": + setup_manual_create_dir() + elif test_case == "auto_create_file": + setup_auto_create_file() + + migration_vtpm.setup_vtpm(params, test, vm) + check_labels(params, block_dir, eval(params.get("check_lables_2")), test) + migration_vtpm.check_vtpm_func(params, vm, test) + check_capability(params, test) + + def verify_test(): + """ + Verify steps + + """ + test.log.info("Verify steps.") + check_labels(params, block_dir, eval(params.get("check_lables_2")), test, remote_host=True) + migration_vtpm.check_vtpm_func(params, vm, test, remote_host=True) + + def verify_test_again(): + """ + Verify again + + """ + test.log.info("Verify again.") + if test_case == "auto_create_dir": + check_dir(params, block_path, test, remote_host=True) + + migration_vtpm.check_vtpm_func(params, vm, test) + check_labels(params, block_dir, eval(params.get("check_lables_2")), test) + + virsh.destroy(vm_name, debug=True) + if not vm.wait_for_shutdown(): + test.error('VM failed to shutdown in 60s') + check_labels(params, block_dir, eval(params.get("check_lables_3")), test) + virsh.undefine(vm_name, options='--nvram', debug=True) + if test_case == "auto_create_dir": + check_dir(params, block_path, test) + + def cleanup_test(): + """ + Cleanup steps + + """ + desturi = params.get("virsh_migrate_desturi") + dst_secret_value_path = params.get("dst_secret_value_path") + src_secret_value_path = params.get("src_secret_value_path") + server_ip = params.get("server_ip") + server_user = params.get("server_user", "root") + server_pwd = params.get("server_pwd") + client_ip = params.get("client_ip") + + test.log.info("Cleanup steps.") + + def _umount_dir(dir_path): + utils_disk.umount(dev_src, dir_path) + server_session = remote.wait_for_login("ssh", server_ip, "22", server_user, server_pwd, r"[\#\$]\s*$") + utils_disk.umount(dev_target, dir_path, session=server_session) + server_session.close() + + if test_case == "auto_create_dir": + _umount_dir(block_path) + else: + _umount_dir(block_dir) + + block_dev.iscsi_login_setup(client_ip, target_luns, is_login=False) + libvirt.setup_or_cleanup_iscsi(is_setup=False, emulated_image="emulated-iscsi-2", portal_ip=client_ip) + libvirt.setup_or_cleanup_iscsi(is_setup=False, emulated_image="emulated-iscsi-1", portal_ip=client_ip) + + if src_sec_uuid: + virsh.secret_undefine(src_sec_uuid, debug=True, ignore_status=True) + if dst_sec_uuid: + virsh.secret_undefine(dst_sec_uuid, debug=True, ignore_status=True, uri=desturi) + + migration_obj.cleanup_connection() + cmd = f"rm -rf {dst_secret_value_path}" + remote.run_remote_cmd(cmd, params) + process.run(cmd, shell=True, ignore_status=True) + cmd = f"rm -rf {src_secret_value_path}" + process.run(cmd, shell=True, ignore_status=True) + cmd = f"rm -rf {block_path}" + remote.run_remote_cmd(cmd, params) + process.run(cmd, shell=True, ignore_status=True) + + vm_name = params.get("migrate_main_vm") + test_case = params.get("test_case") + block_dir = params.get("block_dir") + block_path = params.get("block_path") + new_ownership = params.get("new_ownership") + src_sec_uuid = None + dst_sec_uuid = None + dev_src = None + dev_target = None + target_luns = None + + libvirt_version.is_libvirt_feature_supported(params) + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + block_dev = utils_test.RemoteDiskManager(params) + + try: + src_sec_uuid, dst_sec_uuid = migration_vtpm.set_secret(params) + if not base_steps.check_cpu_for_mig(params): + base_steps.sync_cpu_for_mig(params) + setup_test() + migration_obj.run_migration() + verify_test() + migration_obj.run_migration_back() + verify_test_again() + finally: + cleanup_test() diff --git a/provider/migration/migration_vtpm.py b/provider/migration/migration_vtpm.py new file mode 100644 index 00000000000..1d0dc517e35 --- /dev/null +++ b/provider/migration/migration_vtpm.py @@ -0,0 +1,153 @@ +import logging as log +import os + +from avocado.utils import process + +from virttest import remote +from virttest import utils_package +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_secret +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.migration import base_steps # pylint: disable=W0611 + +# 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__) + + +def check_vtpm_func(params, vm, test, remote_host=False): + """ + Check vtpm function + + :param params: dict, test parameters + :param vm: VM object + :param test: test object + :param remote_host: True to check context on remote + """ + tpm_cmd = params.get("tpm_cmd") + dest_uri = params.get("virsh_migrate_desturi") + src_uri = params.get("virsh_migrate_connect_uri") + test.log.debug("Check vtpm func: %s (remote).", remote) + if remote_host: + if vm.serial_console is not None: + vm.cleanup_serial_console() + vm.connect_uri = dest_uri + if vm.serial_console is None: + vm.create_serial_console() + vm_session = vm.wait_for_serial_login(timeout=240) + if not utils_package.package_install("tpm2-tools", vm_session): + test.error("Failed to install tpm2-tools in vm") + cmd_result = vm_session.cmd_status(tpm_cmd) + vm_session.close() + if remote_host: + if vm.serial_console is not None: + vm.cleanup_serial_console() + vm.connect_uri = src_uri + if cmd_result: + test.fail("Fail to run '%s': %s." % (tpm_cmd, cmd_result)) + + +def setup_vtpm(params, test, vm): + """ + Setup vTPM device in guest xml + + :param params: dict, test parameters + :param vm: VM object + :param test: test object + """ + vm_name = params.get("migrate_main_vm") + tpm_dict = eval(params.get('tpm_dict', '{}')) + auth_sec_dict = params.get("auth_sec_dict") + + test.log.info("Setup vTPM device in guest xml.") + if vm.is_alive(): + vm.destroy(gracefully=False) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + # Remove all existing tpm devices + vmxml.remove_all_device_by_type('tpm') + + tpm_dict['backend']['encryption_secret'] = auth_sec_dict['sec_uuid'] + libvirt_vmxml.modify_vm_device(vmxml, 'tpm', tpm_dict) + + vm.start() + vm.wait_for_login().close() + + +def set_secret(params): + """ + Set secret + + :param params: dict, test parameters + """ + auth_sec_dict = eval(params.get("auth_sec_dict")) + src_secret_value = params.get("src_secret_value") + src_secret_value_path = params.get("src_secret_value_path") + dst_secret_value = params.get("dst_secret_value") + dst_secret_value_path = params.get("dst_secret_value_path") + remote_pwd = params.get("migrate_dest_pwd") + remote_ip = params.get("migrate_dest_host") + remote_user = params.get("remote_user", "root") + + def _create_secret(session=None, remote_args=None, secret_value_path=None): + """ + create secret + + :param session: a session object of remote host + :param remote_args: remote host parameters + :param secret_value_path: the path of secret value + """ + src_sec_uuid = None + dst_sec_uuid = None + libvirt_secret.clean_up_secrets(session) + if remote_args: + dst_sec_uuid = libvirt.create_secret(auth_sec_dict, remote_args=remote_args) + else: + src_sec_uuid = libvirt.create_secret(auth_sec_dict) + auth_sec_dict.update({"sec_uuid": src_sec_uuid}) + if os.path.exists(secret_value_path): + os.remove(secret_value_path) + if session: + cmd = "echo '%s' > %s" % (dst_secret_value, secret_value_path) + process.run(cmd, shell=True) + remote.scp_to_remote(remote_ip, '22', remote_user, remote_pwd, + secret_value_path, secret_value_path, + limit="", log_filename=None, timeout=60, + interface=None) + cmd = f"virsh secret-set-value {dst_sec_uuid} --file {secret_value_path} --plain" + remote.run_remote_cmd(cmd, params) + else: + cmd = "echo '%s' > %s" % (src_secret_value, secret_value_path) + process.run(cmd, shell=True) + cmd = f"virsh secret-set-value {src_sec_uuid} --file {secret_value_path} --plain" + process.run(cmd, shell=True) + return src_sec_uuid, dst_sec_uuid + + src_sec_uuid, _ = _create_secret(secret_value_path=src_secret_value_path) + params.update({"auth_sec_dict": auth_sec_dict}) + virsh_dargs = {'remote_ip': remote_ip, 'remote_user': remote_user, + 'remote_pwd': remote_pwd, 'unprivileged_user': None, + 'ssh_remote_auth': True} + remote_virsh_session = None + remote_virsh_session = virsh.VirshPersistent(**virsh_dargs) + _, dst_sec_uuid = _create_secret(session=remote_virsh_session, remote_args=virsh_dargs, + secret_value_path=dst_secret_value_path) + return src_sec_uuid, dst_sec_uuid + + +def compare_swtpm_version(major, minor): + """ + Get swtpm pkg version and check whether > major.minor + + :param major: swtpm major version number + :param minor: swtpm minor version number + :return: boolean value compared to major.minor + """ + cmd = 'rpm -q swtpm' + v_swtpm = process.run(cmd).stdout_text.strip().split('-') + v_major = int(v_swtpm[1].split('.')[0]) + v_minor = int(v_swtpm[1].split('.')[1]) + return False if (v_major == major and v_minor < minor) else True From ab754f1f016e3ef03966e710b609f24ecf025ac5 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Mon, 17 Mar 2025 04:51:26 -0400 Subject: [PATCH 0889/1055] Update code to get host_iface with function get_default_gateway Signed-off-by: Haijiao Zhao --- .../attach_detach_device/attach_mtu_malformed.py | 2 +- .../connectivity_check_bridge_interface.py | 2 +- ...onnectivity_check_bridge_interface_unprivileged.py | 2 +- .../connectivity_check_direct_interface.py | 2 +- .../connectivity_check_ethernet_interface.py | 2 +- .../connectivity/connectivity_check_user_interface.py | 2 +- .../attribute_port_isolated.py | 2 +- .../elements_and_attributes/element_coalesce.py | 2 +- libvirt/tests/src/virtual_network/iface_bridge.py | 2 +- libvirt/tests/src/virtual_network/iface_stat.py | 2 +- .../link_state/link_state_model_type.py | 2 +- .../src/virtual_network/network/net_update_dns.py | 2 +- .../src/virtual_network/passt/passt_attach_detach.py | 2 +- .../passt/passt_connectivity_between_2vms.py | 2 +- .../tests/src/virtual_network/passt/passt_function.py | 2 +- .../virtual_network/passt/passt_negative_setting.py | 2 +- .../src/virtual_network/passt/passt_reconnect.py | 2 +- .../src/virtual_network/passt/passt_transfer_file.py | 2 +- .../qos/check_actual_network_throughput_direct.py | 2 +- .../qos/check_bandwidth_by_domiftune.py | 2 +- .../update_device/update_device_coalesce.py | 2 +- .../update_device/update_iface_link_state.py | 2 +- .../virtual_network/update_device/update_iface_qos.py | 2 +- .../update_device/update_iface_source.py | 2 +- .../update_device/update_iface_trustGuestRxFilters.py | 2 +- .../update_device/update_iface_type_live.py | 2 +- .../update_device/update_port_isolated.py | 2 +- provider/virtual_network/passt.py | 11 ++++++----- 28 files changed, 33 insertions(+), 32 deletions(-) diff --git a/libvirt/tests/src/virtual_network/attach_detach_device/attach_mtu_malformed.py b/libvirt/tests/src/virtual_network/attach_detach_device/attach_mtu_malformed.py index b2ca4f92eb9..95f8e93e93a 100644 --- a/libvirt/tests/src/virtual_network/attach_detach_device/attach_mtu_malformed.py +++ b/libvirt/tests/src/virtual_network/attach_detach_device/attach_mtu_malformed.py @@ -26,7 +26,7 @@ def run(test, params, env): source_net = params.get('source_net', net_name) host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) iface_attrs = eval(params.get('iface_attrs', '{}')) net_attrs = eval(params.get('net_attrs', '{}')) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py index e63aa91d7ec..4573f40f70f 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py @@ -54,7 +54,7 @@ def run(test, params, env): host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) bkxmls = list(map(vm_xml.VMXML.new_from_inactive_dumpxml, vms)) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface_unprivileged.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface_unprivileged.py index d11b55a4c0f..8098e013dbc 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface_unprivileged.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface_unprivileged.py @@ -30,7 +30,7 @@ def run(test, params, env): br_conf_file = '/etc/qemu-kvm/bridge.conf' host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) unpr_user = params.get('unpr_user', 'test_unpr') + rand_id diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_direct_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_direct_interface.py index ddf68c4631a..79e896aeb4a 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_direct_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_direct_interface.py @@ -23,7 +23,7 @@ def run(test, params, env): outside_ip = params.get('outside_ip') host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) iface_attrs = eval(params.get('iface_attrs', '{}')) bkxmls = list(map(vm_xml.VMXML.new_from_inactive_dumpxml, vms)) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py index b0e537dbb08..3562c4b7740 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py @@ -61,7 +61,7 @@ def run(test, params, env): outside_ip = params.get('outside_ip') host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True, json=True).split()[0] + iface_name=True, force_dhcp=True, json=True) host_ip = utils_net.get_ip_address_by_interface(host_iface, ip_ver='ipv4') status_error = 'yes' == params.get('status_error', 'no') err_msg = params.get('err_msg') diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py index c7ef6e62834..394b0489934 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_user_interface.py @@ -79,7 +79,7 @@ def run(test, params, env): host_iface = params.get('host_iface') backend = params.get('backend') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True, json=True).split()[0] + iface_name=True, force_dhcp=True, json=True) ipv4_addr = params.get('ipv4_addr') ipv4_prefix = params.get('ipv4_prefix') diff --git a/libvirt/tests/src/virtual_network/elements_and_attributes/attribute_port_isolated.py b/libvirt/tests/src/virtual_network/elements_and_attributes/attribute_port_isolated.py index 4edbbb6aefc..44907ff4879 100644 --- a/libvirt/tests/src/virtual_network/elements_and_attributes/attribute_port_isolated.py +++ b/libvirt/tests/src/virtual_network/elements_and_attributes/attribute_port_isolated.py @@ -36,7 +36,7 @@ def run(test, params, env): port_attrs = eval(params.get('port_attrs', '{}')) host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) bkxmls = list(map(vm_xml.VMXML.new_from_inactive_dumpxml, vms)) diff --git a/libvirt/tests/src/virtual_network/elements_and_attributes/element_coalesce.py b/libvirt/tests/src/virtual_network/elements_and_attributes/element_coalesce.py index e3cd6dbcd14..7f449a8f817 100644 --- a/libvirt/tests/src/virtual_network/elements_and_attributes/element_coalesce.py +++ b/libvirt/tests/src/virtual_network/elements_and_attributes/element_coalesce.py @@ -32,7 +32,7 @@ def run(test, params, env): host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) iface_attrs = eval(params.get('iface_attrs', '{}')) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) diff --git a/libvirt/tests/src/virtual_network/iface_bridge.py b/libvirt/tests/src/virtual_network/iface_bridge.py index f30f864f73f..4b7ec6351d9 100644 --- a/libvirt/tests/src/virtual_network/iface_bridge.py +++ b/libvirt/tests/src/virtual_network/iface_bridge.py @@ -117,7 +117,7 @@ def check_net_functions(guest_ip, ping_count, ping_timeout, guest_session, host_ ping_timeout = float(params.get("ping_timeout", "10")) host_iface = params.get("host_iface") iface_name = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) bridge_script = NETWORK_SCRIPT + bridge_name iface_script = NETWORK_SCRIPT + iface_name iface_script_bk = os.path.join(data_dir.get_tmp_dir(), "iface-%s.bk" % iface_name) diff --git a/libvirt/tests/src/virtual_network/iface_stat.py b/libvirt/tests/src/virtual_network/iface_stat.py index 92ec87e8bb4..af7340f7030 100644 --- a/libvirt/tests/src/virtual_network/iface_stat.py +++ b/libvirt/tests/src/virtual_network/iface_stat.py @@ -153,7 +153,7 @@ def _collect_and_compare_stat(vm_name, session, **virsh_args): host_iface = params.get("host_iface") if not host_iface: host_iface = utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) if iface_type == 'direct': iface_dict = {k.replace('new_iface_', ''): v for k, v in params.items() diff --git a/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py b/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py index ddf51d1508e..9ec8661f242 100644 --- a/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py +++ b/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py @@ -26,7 +26,7 @@ def run(test, params, env): outside_ip = params.get("outside_ip") host_iface = params.get("host_iface") host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) rand_id = utils_misc.generate_random_string(3) bridge_name = "br_" + rand_id tap_name = "tap_" + rand_id diff --git a/libvirt/tests/src/virtual_network/network/net_update_dns.py b/libvirt/tests/src/virtual_network/network/net_update_dns.py index 10deb8a97e9..96e96333942 100644 --- a/libvirt/tests/src/virtual_network/network/net_update_dns.py +++ b/libvirt/tests/src/virtual_network/network/net_update_dns.py @@ -32,7 +32,7 @@ def run(test, params, env): net_name = 'default' host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) operation = params.get('operation') dns_ele = params.get('dns_ele') update_xml = params.get('update_xml') diff --git a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py index 29c104bfc2c..396db491555 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py +++ b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py @@ -68,7 +68,7 @@ def run(test, params, env): add_iface = 'yes' == params.get('add_iface', 'no') host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) host_ip = utils_net.get_ip_address_by_interface(host_iface, ip_ver='ipv4') host_ip_v6 = utils_net.get_ip_address_by_interface(host_iface, ip_ver='ipv6') iface_attrs = eval(params.get('iface_attrs')) diff --git a/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py b/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py index bf21768d866..e88cebdc5aa 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py +++ b/libvirt/tests/src/virtual_network/passt/passt_connectivity_between_2vms.py @@ -67,7 +67,7 @@ def run(test, params, env): params['proc_checks'] = proc_checks = eval(params.get('proc_checks', '{}')) host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) iface_attrs['backend']['logFile'] = log_file iface_c_attrs['backend']['logFile'] = log_file_c iface_attrs['source']['dev'] = host_iface diff --git a/libvirt/tests/src/virtual_network/passt/passt_function.py b/libvirt/tests/src/virtual_network/passt/passt_function.py index 835658c0a79..0f630b93f72 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_function.py +++ b/libvirt/tests/src/virtual_network/passt/passt_function.py @@ -54,7 +54,7 @@ def run(test, params, env): host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) host_ip = utils_net.get_ip_address_by_interface(host_iface, ip_ver='ipv4') host_ip_v6 = utils_net.get_ip_address_by_interface(host_iface, ip_ver='ipv6') params['host_ip_v6'] = host_ip_v6 diff --git a/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py b/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py index f355be53500..a97aa0d082c 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py +++ b/libvirt/tests/src/virtual_network/passt/passt_negative_setting.py @@ -52,7 +52,7 @@ def run(test, params, env): iface_attrs = eval(params.get('iface_attrs')) host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) log_file = f'/run/user/{user_id}/passt.log' \ if not params.get('log_file') else params['log_file'] iface_attrs['backend']['logFile'] = log_file diff --git a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py index 9cd10955f64..408f106cd65 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py +++ b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py @@ -65,7 +65,7 @@ def run(test, params, env): outside_ip = params.get('outside_ip') host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) log_file = f'/run/user/{user_id}/passt.log' iface_attrs['backend']['logFile'] = log_file iface_attrs['source']['dev'] = host_iface diff --git a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py index 7e79883b48e..c97f04962f6 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py +++ b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py @@ -154,7 +154,7 @@ def run(test, params, env): params['proc_checks'] = proc_checks = eval(params.get('proc_checks', '{}')) host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) log_file = f'/run/user/{user_id}/passt.log' iface_attrs['backend']['logFile'] = log_file iface_attrs['source']['dev'] = host_iface diff --git a/libvirt/tests/src/virtual_network/qos/check_actual_network_throughput_direct.py b/libvirt/tests/src/virtual_network/qos/check_actual_network_throughput_direct.py index 649013f6968..fc4d9af6a6e 100644 --- a/libvirt/tests/src/virtual_network/qos/check_actual_network_throughput_direct.py +++ b/libvirt/tests/src/virtual_network/qos/check_actual_network_throughput_direct.py @@ -30,7 +30,7 @@ def run(test, params, env): net_name = 'net_' + rand_id host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) iface_attrs = eval(params.get('iface_attrs', '{}')) iface_attrs_2 = eval(params.get('iface_attrs_2', '{}')) net_attrs = eval(params.get('net_attrs', '{}')) diff --git a/libvirt/tests/src/virtual_network/qos/check_bandwidth_by_domiftune.py b/libvirt/tests/src/virtual_network/qos/check_bandwidth_by_domiftune.py index 39a0e150126..4b446091858 100644 --- a/libvirt/tests/src/virtual_network/qos/check_bandwidth_by_domiftune.py +++ b/libvirt/tests/src/virtual_network/qos/check_bandwidth_by_domiftune.py @@ -29,7 +29,7 @@ def run(test, params, env): br_name = br_type + '_' + rand_id host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) iface_attrs = eval(params.get('iface_attrs', '{}')) net_attrs = eval(params.get('net_attrs', '{}')) update_bw = eval(params.get('update_bw', '{}')) diff --git a/libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py b/libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py index 7a11cce7a0a..e89f35e7bbe 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py +++ b/libvirt/tests/src/virtual_network/update_device/update_device_coalesce.py @@ -48,7 +48,7 @@ def run(test, params, env): iface_attrs = eval(params.get('iface_attrs', '{}')) host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) rx_frames = params.get('rx_frames', '0') updated_rx_frames = params.get('updated_rx_frames', '0') updated_coalesce = eval(params.get('updated_coalesce', '{}')) diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_link_state.py b/libvirt/tests/src/virtual_network/update_device/update_iface_link_state.py index e1036d84ec3..478cb1742f4 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_link_state.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_link_state.py @@ -22,7 +22,7 @@ def run(test, params, env): outside_ip = params.get("outside_ip") host_iface = params.get("host_iface") host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) rand_id = utils_misc.generate_random_string(3) bridge_name = "br_" + rand_id tap_name = "tap_" + rand_id diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_qos.py b/libvirt/tests/src/virtual_network/update_device/update_iface_qos.py index 522dcb282d8..dbe9c2a3109 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_qos.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_qos.py @@ -43,7 +43,7 @@ def run(test, params, env): br_name = br_type + '_' + rand_id host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) iface_attrs = eval(params.get('iface_attrs', '{}')) extra_attrs = eval(params.get('extra_attrs', '{}')) net_attrs = eval(params.get('net_attrs', '{}')) diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_source.py b/libvirt/tests/src/virtual_network/update_device/update_iface_source.py index 1eb3e8fae7d..2705e4ac9e4 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_source.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_source.py @@ -26,7 +26,7 @@ def run(test, params, env): net_name = 'net_' + rand_id host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) iface_attrs = eval(params.get('iface_attrs', '{}')) net_attrs = eval(params.get('net_attrs', '{}')) status_error = 'yes' == params.get('status_error', 'no') diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py b/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py index 29cb9a940b8..8f3b085bc91 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_trustGuestRxFilters.py @@ -24,7 +24,7 @@ def run(test, params, env): vm = env.get_vm(vm_name) host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) iface_attrs = eval(params.get('iface_attrs', '{}')) ips = {'outside_ip': params.get('outside_ip')} diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_type_live.py b/libvirt/tests/src/virtual_network/update_device/update_iface_type_live.py index 3e26ab6e625..ae2921c53a0 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_type_live.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_type_live.py @@ -28,7 +28,7 @@ def run(test, params, env): iface_type = params.get('iface_type') host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) net_attrs = eval(params.get('net_attrs', '{}')) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) diff --git a/libvirt/tests/src/virtual_network/update_device/update_port_isolated.py b/libvirt/tests/src/virtual_network/update_device/update_port_isolated.py index 12680cffdbc..a0f387d490b 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_port_isolated.py +++ b/libvirt/tests/src/virtual_network/update_device/update_port_isolated.py @@ -116,7 +116,7 @@ def test_update_iface(): update_port_attrs = eval(params.get('update_port_attrs', '{}')) host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) bkxmls = list(map(vm_xml.VMXML.new_from_inactive_dumpxml, vms)) diff --git a/provider/virtual_network/passt.py b/provider/virtual_network/passt.py index 854eb0356ef..4e897506b8b 100644 --- a/provider/virtual_network/passt.py +++ b/provider/virtual_network/passt.py @@ -139,7 +139,7 @@ def check_proc_info(params, log_file, mac): host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( - iface_name=True, force_dhcp=True).split()[0] + iface_name=True, force_dhcp=True, json=True) proc_info = get_proc_info('passt') LOG.debug(proc_info) @@ -250,9 +250,9 @@ def check_default_gw(session, host_iface=None): host interface """ host_gw = utils_net.get_default_gateway( - force_dhcp=True, target_iface=host_iface, json=True).split() + force_dhcp=True, target_iface=host_iface, json=True) vm_gw = utils_net.get_default_gateway( - session=session, force_dhcp=True, json=True).split() + session=session, force_dhcp=True, json=True) LOG.debug(f'Host and vm default ipv4 gateway: {host_gw}, {vm_gw}') if [x for x in vm_gw if x not in host_gw]: raise exceptions.TestFail( @@ -365,8 +365,9 @@ def check_connection(vm, vm_iface, protocols, host_iface=None): :param host_iface: host interface to get default gw for if ommitted all default routes are returned """ - default_gw = utils_net.get_default_gateway(force_dhcp=True, - target_iface=host_iface) + default_gw = utils_net.get_default_gateway( + force_dhcp=True, target_iface=host_iface, json=True + ) vm_session = vm.wait_for_serial_login() default_gw_v6_vm = utils_net.get_default_gateway( session=vm_session, ip_ver='ipv6', json=True) From 4752f7b8bfbf4618d92c2c39cc0631cf522457dd Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Mon, 17 Feb 2025 21:43:30 -0500 Subject: [PATCH 0890/1055] Add new case of virsh domifaddr - VIRT-299270 - [domifaddr] domifaddr for bridge and network type interface Signed-off-by: Haijiao Zhao --- .../tests/cfg/virtual_network/domifaddr.cfg | 13 ++ .../tests/src/virtual_network/domifaddr.py | 152 ++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/domifaddr.cfg create mode 100644 libvirt/tests/src/virtual_network/domifaddr.py diff --git a/libvirt/tests/cfg/virtual_network/domifaddr.cfg b/libvirt/tests/cfg/virtual_network/domifaddr.cfg new file mode 100644 index 00000000000..74df3dd1ac1 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/domifaddr.cfg @@ -0,0 +1,13 @@ +- virtual_network.domifaddr: + type = domifaddr + start_vm = no + libvirtd_debug_file = /var/log/libvirt/libvird.log + libvirtd_debug_level = 1 + libvirtd_debug_filters = 1:qemu 1:libvirt 4:object 4:json 4:event 1:util + variants: + - default: + net_name = default + net_ipv6_attrs = {'address': '2001:db8:ca2:2::1', 'family': 'ipv6', 'prefix': '64', 'dhcp_ranges': {'attrs': {'start': '2001:db8:ca2:2:1::10', 'end': '2001:db8:ca2:2:1::ff'}}} + iface_a_attrs = {'type_name': 'bridge', 'source': {'bridge': br_name}, 'model': 'virtio'} + iface_b_attrs = {'type_name': 'network', 'source': {'network': net_name}, 'model': 'virtio'} + err_msg = Failed to open file '/var/lib/libvirt/dnsmasq/.*status': No such file or directory diff --git a/libvirt/tests/src/virtual_network/domifaddr.py b/libvirt/tests/src/virtual_network/domifaddr.py new file mode 100644 index 00000000000..a1160e1f839 --- /dev/null +++ b/libvirt/tests/src/virtual_network/domifaddr.py @@ -0,0 +1,152 @@ +import logging +import random + +from virttest import utils_misc +from virttest import utils_net +from virttest import virsh +from virttest.libvirt_xml import network_xml +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.virtual_network import network_base + +VIRSH_ARGS = {"ignore_status": False, "debug": True} + +LOG = logging.getLogger("avocado." + __name__) + + +def run(test, params, env): + """ + Test domifaddr for bridge and network type interface + """ + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + net_name = params.get("net_name", "default") + net_ipv6_attrs = eval(params.get("net_ipv6_attrs", "{}")) + + rand_id = utils_misc.generate_random_string(3) + br_name = "linux_br_" + rand_id + host_iface = params.get("host_iface") + host_iface = ( + host_iface + if host_iface + else utils_net.get_default_gateway(iface_name=True, force_dhcp=True).split()[0] + ) + iface_a_attrs = eval(params.get("iface_a_attrs", "{}")) + iface_b_attrs = eval(params.get("iface_b_attrs", "{}")) + err_msg = params.get("err_msg") + + net_xml = network_xml.NetworkXML.new_from_net_dumpxml(net_name) + bk_net = net_xml.copy() + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bk_xml = vmxml.copy() + + try: + utils_net.create_linux_bridge_tmux(br_name, host_iface) + net_ipv6 = network_xml.IPXML(ipv6=True) + net_ipv6.setup_attrs(**net_ipv6_attrs) + net_xml.add_ip(net_ipv6) + LOG.debug(f"Define network {net_name} with xml:\n{net_xml}") + net_xml.sync() + + vmxml.del_device("interface", by_tag=True) + libvirt_vmxml.modify_vm_device(vmxml, "interface", iface_a_attrs, 0) + libvirt_vmxml.modify_vm_device(vmxml, "interface", iface_b_attrs, 1) + LOG.debug(virsh.dumpxml(vm_name).stdout_text) + + iface_a = network_base.get_iface_xml_inst(vm_name, "interface A", 0) + iface_b = network_base.get_iface_xml_inst(vm_name, "interface B", 1) + # Make sure iface_b is network type, switch if not + if iface_b.type_name != "network": + iface_a, iface_b = iface_b, iface_a + mac_a, mac_b = iface_a.mac_address, iface_b.mac_address + + vm.start() + vm.set_state_guest_agent(True, serial=True) + session = vm.wait_for_serial_login() + ip_output = session.cmd_output("ip addr") + LOG.debug(ip_output) + ip_a = network_base.get_vm_ip(session, mac_a, ignore_error=True) + ip_b = network_base.get_vm_ip(session, mac_b, ignore_error=True) + + ipv6_a = network_base.get_vm_ip(session, mac_a, "ipv6", ignore_error=True) + ipv6_b = network_base.get_vm_ip(session, mac_b, "ipv6", ignore_error=True) + LOG.debug(ip_a) + LOG.debug(ip_b) + + vm_iface_a = utils_net.get_linux_iface_info(mac=mac_a, session=session)[ + "ifname" + ] + vm_iface_b = utils_net.get_linux_iface_info(mac=mac_b, session=session)[ + "ifname" + ] + + ip_gen = utils_net.gen_ipv4_addr("173.173.173.0") + ip_alias_a, ip_alias_b = random.choices(list(ip_gen), k=2) + + cmd_set_alias_a = f"ip addr add {ip_alias_a}/24 dev {vm_iface_a}" + cmd_set_alias_b = f"ip addr add {ip_alias_b}/24 dev {vm_iface_b}" + + session.cmd(cmd_set_alias_a) + session.cmd(cmd_set_alias_b) + + virsh.domiflist(vm_name, **VIRSH_ARGS) + virsh.domifaddr(vm_name, **VIRSH_ARGS) + libvirt.check_logfile(err_msg, params.get("libvirtd_debug_file"), False) + + domid = virsh.domid(vm_name).stdout_text.strip() + out_default = virsh.domifaddr(domid, **VIRSH_ARGS) + expect_info = ["vnet*", mac_b, "ipv4", ip_b, "ipv6", ipv6_b] + for s in expect_info: + libvirt.check_result(out_default, expected_match=s) + + domuuid = virsh.domuuid(vm_name).stdout_text.strip() + out_uuid = virsh.domifaddr(domuuid, **VIRSH_ARGS) + out_lease = virsh.domifaddr(domuuid, "--source lease", **VIRSH_ARGS) + for output in (out_uuid, out_lease): + if output.stdout_text.strip() == out_default.stdout_text.strip(): + LOG.info("Output match") + else: + test.fail("Output of domifaddr does not match, please check log") + + iface_info_a = utils_net.get_linux_iface_info(vm_iface_a, session=session) + ips_a = [addr.get("local") for addr in iface_info_a.get("addr_info", {})] + + iface_info_b = utils_net.get_linux_iface_info(vm_iface_b, session=session) + ips_b = [addr.get("local") for addr in iface_info_b.get("addr_info", {})] + + check_list_a = [mac_a] + ips_a + LOG.debug(check_list_a) + check_list_b = [mac_b] + ips_b + LOG.debug(check_list_b) + + out_agent = virsh.domifaddr(domuuid, "--source agent", **VIRSH_ARGS) + for str in check_list_a + check_list_b: + libvirt.check_result(out_agent, expected_match=str) + + out_agent_a = virsh.domifaddr( + vm_name, f"--source agent {vm_iface_a}", **VIRSH_ARGS + ) + for str in check_list_a: + libvirt.check_result(out_agent_a, expected_match=str) + if any([str in out_agent_a.stdout_text for str in check_list_b]): + test.fail( + f"Output with --source agent {vm_iface_a} should not " + f"contain info of other interface, please check log" + ) + + out_agent_a_full = virsh.domifaddr( + vm_name, f"--source agent {vm_iface_a} --full", **VIRSH_ARGS + ) + for str in check_list_a: + libvirt.check_result(out_agent_a_full, expected_match=str) + + out_arp = virsh.domifaddr(domuuid, "--source arp", **VIRSH_ARGS) + for str in (mac_b, ip_b): + libvirt.check_result(out_arp, expected_match=str) + + finally: + bk_xml.sync() + bk_net.sync() + utils_net.delete_linux_bridge_tmux(br_name, host_iface) From 700219495e5f6f1964e2113fd4bc8dd68c6e2e81 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Fri, 21 Mar 2025 21:30:01 +0800 Subject: [PATCH 0891/1055] video_devices: add case for resolution Signed-off-by: Dan Zheng --- .../tests/cfg/virtual_device/video_devices.cfg | 16 ++++++++++++---- .../tests/src/virtual_device/video_devices.py | 12 +++++++++++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/cfg/virtual_device/video_devices.cfg b/libvirt/tests/cfg/virtual_device/video_devices.cfg index 077d0bc24a4..7a1138a2fb1 100644 --- a/libvirt/tests/cfg/virtual_device/video_devices.cfg +++ b/libvirt/tests/cfg/virtual_device/video_devices.cfg @@ -5,6 +5,12 @@ - positive_test: status_error = "no" variants: + - resolution_test: + no qxl + resolution_test = "yes" + resolution_x = 507 + resolution_y = 510 + qemu_line = "xres.*:${resolution_x}.*yres.*:${resolution_y}" - model_test: model_test = "yes" variants: @@ -98,6 +104,7 @@ no mem_test variants: - qxl: + no aarch64 secondary_video_model = qxl - virtio: secondary_video_model = virtio @@ -105,20 +112,21 @@ - primary_video: variants: - qxl: - no s390-virtio + no s390-virtio, aarch64 primary_video_model = qxl - vga: - no s390-virtio + no s390-virtio, aarch64 primary_video_model = vga - cirrus: - no s390-virtio + no s390-virtio, aarch64 + no resolution_test primary_video_model = cirrus no mem_test - virtio: primary_video_model = virtio no mem_test - bochs: - no s390-virtio + no s390-virtio, aarch64 primary_video_model = bochs only no_secondary_video..model_test.default no_secondary_video..vram..bochs_default_size - negative_test: diff --git a/libvirt/tests/src/virtual_device/video_devices.py b/libvirt/tests/src/virtual_device/video_devices.py index d258ca96790..03876f141e3 100644 --- a/libvirt/tests/src/virtual_device/video_devices.py +++ b/libvirt/tests/src/virtual_device/video_devices.py @@ -223,6 +223,9 @@ def up_round_to_power_of_two(num): guest_arch = params.get("vm_arch_name") with_packed = params.get("with_packed", "no") == "yes" driver_packed = params.get("driver_packed", "on") + resolution_test = params.get("resolution_test", "no") == "yes" + resolution_x = params.get("resolution_x") + resolution_y = params.get("resolution_y") vm_xml = VMXML.new_from_dumpxml(vm_name) vm_xml_backup = vm_xml.copy() @@ -243,9 +246,11 @@ def up_round_to_power_of_two(num): if heads_test and not default_primary_heads: kwargs["model_heads"] = primary_heads if mem_test and not default_mem_size: - kwargs["model_"+mem_type] = mem_size + kwargs["model_" + mem_type] = mem_size if model_type == "virtio" and with_packed: kwargs["driver"] = {"packed": driver_packed} + if resolution_test: + kwargs["resolution"] = {"x": resolution_x, "y": resolution_y} add_video_device(model_type, vm_xml, is_primary, status_error, **kwargs) if secondary_video_model: @@ -266,6 +271,9 @@ def up_round_to_power_of_two(num): "device xml. details: %s " % res) logging.debug("vm started successfully in positive cases.") + if resolution_test: + libvirt.check_qemu_cmd_line(params.get("qemu_line")) + if model_test: check_model_test_cmd_line(model_type, is_primary) @@ -283,6 +291,8 @@ def up_round_to_power_of_two(num): check_mem_test_xml(model_type, mem_type, mem_size) check_mem_test_cmd_line(model_type, mem_type, mem_size) + + vm.wait_for_login().close() finally: if vm.is_alive(): vm.destroy(vm_name) From cf87a5adb09af5f08fb3c59970353067d644ae07 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Mon, 24 Mar 2025 04:52:30 -0400 Subject: [PATCH 0892/1055] link_state_model_type:Restore vmxml for non root vm Signed-off-by: Haijiao Zhao --- .../src/virtual_network/link_state/link_state_model_type.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py b/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py index ddf51d1508e..aaf3584e331 100644 --- a/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py +++ b/libvirt/tests/src/virtual_network/link_state/link_state_model_type.py @@ -110,7 +110,7 @@ def run(test, params, env): session.close() finally: - bkxml.sync() + bkxml.sync(virsh_instance=virsh_ins) if interface_type == "ethernet": network_base.delete_tap(tap_name) utils_net.delete_linux_bridge_tmux(bridge_name, host_iface) From 93937df5b9998d9dfc4e46007fc2601649a48857 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Tue, 31 Dec 2024 03:32:33 -0500 Subject: [PATCH 0893/1055] Test the scenario when abort the save process When the save process is aborted, the vm should keep running. Signed-off-by: Yalan Zhang --- .../tests/cfg/save_and_restore/abort_save.cfg | 6 ++ .../tests/src/save_and_restore/abort_save.py | 66 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 libvirt/tests/cfg/save_and_restore/abort_save.cfg create mode 100644 libvirt/tests/src/save_and_restore/abort_save.py diff --git a/libvirt/tests/cfg/save_and_restore/abort_save.cfg b/libvirt/tests/cfg/save_and_restore/abort_save.cfg new file mode 100644 index 00000000000..02ea2f052f9 --- /dev/null +++ b/libvirt/tests/cfg/save_and_restore/abort_save.cfg @@ -0,0 +1,6 @@ +- save_and_restore.abort_save: + type = abort_save + start_vm = no + stress_type = "stress" + stress_cmds = "stress --cpu 8 --io 4 --vm 2 --vm-bytes 128M --vm-keep" + diff --git a/libvirt/tests/src/save_and_restore/abort_save.py b/libvirt/tests/src/save_and_restore/abort_save.py new file mode 100644 index 00000000000..81d0639bbf1 --- /dev/null +++ b/libvirt/tests/src/save_and_restore/abort_save.py @@ -0,0 +1,66 @@ +import logging +import re +import os + +from virttest import data_dir +from virttest import utils_test +from virttest import utils_misc +from virttest import virsh +from virttest.libvirt_xml import vm_xml + +from provider.save import save_base + +LOG = logging.getLogger('avocado.test.' + __name__) + + +def run(test, params, env): + """ + Test the scenario to abort the vm save process + Steps: + 1. Start the vm, run stress in the vm to slow down the save process; + 2. Run "virsh save" to save the vm; + 3. During the save process, run domjobabort; + 4. Check the VM's states after the abort operation; + """ + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + stress_package = params.get("stress_package", "stress") + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + try: + vm.start() + pid_ping, upsince = save_base.pre_save_setup(vm) + LOG.debug('TEST_STEP1: run stress on the vm:') + vm_stress = utils_test.VMStress(vm, stress_package, params) + vm_stress.load_stress_tool() + save_path = os.path.join(data_dir.get_tmp_dir(), 'rhel.save') + LOG.debug('TEST_STEP2: Save the VM:') + cmd = "save %s %s" % (vm_name, save_path) + virsh_session = virsh.VirshSession(virsh_exec=virsh.VIRSH_EXEC, + auto_close=True) + virsh_session.sendline(cmd) + LOG.debug('TEST_STEP3: Abort the save process') + # check if the save process is succeed, if save succeed, cancel the test + st = virsh.domjobinfo(vm_name, ignore_status=True).stdout_text.strip() + LOG.debug("domjobinfo: %s", st) + if not re.search("Unbounded", st): + test.cancel("Test cancel since save process completed before abort.") + virsh.domjobabort(vm_name) + utils_misc.wait_for(lambda: vm.state() == 'running', 10) + LOG.debug("vm state is %s after abort the save process", vm.state()) + if vm.state() != 'running': + test.fail(f'VM should be running after abort restore, not {vm.state()}') + save_base.post_save_check(vm, pid_ping, upsince) + LOG.debug("TEST_STEP4: Check the VM's state details after save abort") + outputs = virsh.domstate(vm_name, "--reason").stdout_text.strip() + LOG.debug("vm state detail is %s", outputs) + if not re.search("save canceled", outputs): + test.fail("There is no 'save canceled' words in the domstate outputs!") + virsh.shutdown(vm_name, debug=True, ignore_status=False) + finally: + virsh_session.close() + bkxml.sync() + if os.path.exists(save_path): + os.remove(save_path) From cc7636b8294b6a932d2e96b36db7ee0a2f948cda Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Thu, 2 Jan 2025 03:34:47 -0500 Subject: [PATCH 0894/1055] Abort the managedsave process and check the events Check after aborting the managesave process, the vm should keep running and there is related events. Signed-off-by: Yalan Zhang --- .../save_and_restore/abort_managedsave.cfg | 9 +++ .../src/save_and_restore/abort_managedsave.py | 74 +++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 libvirt/tests/cfg/save_and_restore/abort_managedsave.cfg create mode 100644 libvirt/tests/src/save_and_restore/abort_managedsave.py diff --git a/libvirt/tests/cfg/save_and_restore/abort_managedsave.cfg b/libvirt/tests/cfg/save_and_restore/abort_managedsave.cfg new file mode 100644 index 00000000000..7c35152c459 --- /dev/null +++ b/libvirt/tests/cfg/save_and_restore/abort_managedsave.cfg @@ -0,0 +1,9 @@ +- save_and_restore.abort_managedsave: + type = abort_managedsave + save_opt = + start_vm = no + default_path = "/var/lib/libvirt/qemu/save" + event_cmd = "event --loop --all" + expected_event = ["Suspended Paused", "Resumed Unpaused"] + stress_type = "stress" + stress_cmds = "stress --cpu 8 --io 4 --vm 2 --vm-bytes 128M --vm-keep" diff --git a/libvirt/tests/src/save_and_restore/abort_managedsave.py b/libvirt/tests/src/save_and_restore/abort_managedsave.py new file mode 100644 index 00000000000..3f386a398dc --- /dev/null +++ b/libvirt/tests/src/save_and_restore/abort_managedsave.py @@ -0,0 +1,74 @@ +import logging +import os +import re + +from virttest import virsh +from virttest import utils_test +from virttest.libvirt_xml import vm_xml + +from provider.save import save_base + +LOG = logging.getLogger('avocado.test.' + __name__) +VIRSH_ARGS = {'debug': True, 'ignore_status': False} + + +def run(test, params, env): + """ + Test the scenario to abort the vm ManagedSave process + Steps: + 1. Start the vm, run stress in the vm to slow down the ManagedSave process; + 2. Run "virsh managedsave" to save the vm; + 3. During the managedsave process, run domjobabort; + 4. Check the VM's states after the abort operation and check the events; + """ + + vm_name = params.get('main_vm') + vm = env.get_vm(vm_name) + default_path = params.get('default_path') + file_path = default_path + vm_name + '.save' + stress_package = params.get("stress_package", "stress") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + event_cmd = params.get("event_cmd") + expected_event = eval(params.get('expected_event')) + try: + vm.start() + pid_ping, upsince = save_base.pre_save_setup(vm) + LOG.debug('TEST_STEP1: run stress on the vm:') + vm_stress = utils_test.VMStress(vm, stress_package, params) + vm_stress.load_stress_tool() + LOG.debug('TEST_STEP2: ManagedSave the VM:') + # Start event session to catch the events + event_session = virsh.EventTracker.start_get_event(vm_name, event_cmd=event_cmd) + cmd = "managedsave %s" % vm_name + virsh_session = virsh.VirshSession(virsh_exec=virsh.VIRSH_EXEC, + auto_close=False) + virsh_session.sendline(cmd) + LOG.debug('TEST_STEP3: Abort the ManagedSave process') + # check if the save process is succeed, cancel the test if save succeed + st = virsh.domjobinfo(vm_name, ignore_status=True).stdout_text.strip() + LOG.debug("domjobinfo: %s", st) + if not re.search("Unbounded", st): + test.cancel("Test cancel since managedsave process completed before abort.") + virsh.domjobabort(vm_name).stdout_text.strip() + LOG.debug("Check the VM's state details after save abort") + save_base.post_save_check(vm, pid_ping, upsince) + # check the events for abort + LOG.debug("TEST_STEP4: Check the event:") + event_output = virsh.EventTracker.finish_get_event(event_session) + for event in expected_event: + if not re.search(event, event_output): + test.fail('Not find: %s from event output:%s' % (event, event_output)) + # check VM states details + outputs_ = virsh.domstate(vm_name, "--reason").stdout_text.strip() + LOG.debug("TEST_STEP5: check the domstate: %s and ensure no saved file", outputs_) + if not re.search("save canceled", outputs_): + test.fail("There is no 'save canceled' words in the domstate outputs!") + if os.path.exists(file_path): + test.fail("There should not be the save file since managedsave aborted") + virsh_session.close() + virsh.shutdown(vm_name, **VIRSH_ARGS) + finally: + bkxml.sync() + if os.path.exists(file_path): + os.remove(file_path) From b3d267168f2ec50471d5ba41a17f7538662be1d7 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Thu, 16 Jan 2025 00:33:29 -0500 Subject: [PATCH 0895/1055] Managedsave for VM with specific name Check managedsave can work properly for VM with long name with 242 characters or non-ACSII name. Signed-off-by: Yalan Zhang --- .../domain/virsh_managedsave_special_name.cfg | 11 ++++ .../domain/virsh_managedsave_special_name.py | 65 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave_special_name.cfg create mode 100644 libvirt/tests/src/virsh_cmd/domain/virsh_managedsave_special_name.py diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave_special_name.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave_special_name.cfg new file mode 100644 index 00000000000..19aae3ca0e8 --- /dev/null +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_managedsave_special_name.cfg @@ -0,0 +1,11 @@ +- virsh.managedsave_special_name: + type = "virsh_managedsave_special_name" + start_vm = "no" + variants: + - non_acsii: + vmname = kīмсhīkīмсhīkīмсhī-∨м + name_display = 'k\xff\xff\xff\xff\xff\xffh\xff\xffk\xff\xff\xff\xff\xff\xffh\xff\xffk\xff\xff\xff\xff\xff\xffh\xff\xff-\xff\xff\xff\xff\xff' + - long: + vmname = 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 + name_display = ${vmname} + diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave_special_name.py b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave_special_name.py new file mode 100644 index 00000000000..c851d00e363 --- /dev/null +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_managedsave_special_name.py @@ -0,0 +1,65 @@ +import os +import logging +from virttest import virsh +from virttest import libvirt_vm +from virttest.libvirt_xml import vm_xml +from avocado.utils import process + +from provider.save import save_base + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Try managedsave on VMs with special name + + 1. start a vm, and do managedsave + 2. check the saved file exists + 3. start the vm, check the vm status and saved file status + """ + special_name = params.get('vmname') + special_name_display = params.get('name_display') + managed_save_file = "/var/lib/libvirt/qemu/save/%s.save" % special_name + vm_name = params.get('main_vm') + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bk_xml = vmxml.copy() + vm = env.get_vm(vm_name) + new_vm = libvirt_vm.VM(special_name, vm.params, vm.root_dir, vm.address_cache) + try: + LOG.info("TEST_STEP1: Rename the VM to be with special name:") + LOG.info("The special name is %s with %s characters.", + special_name, len(special_name)) + if vm.is_alive: + vm.destroy() + virsh.domrename(vm_name, special_name, debug=True) + vmlist = virsh.dom_list("--name --all", + debug=True).stdout_text + if special_name not in vmlist: + test.fail("Rename the VM fail!") + + LOG.info("TEST_STEP2: Start the VM and do managedsave:") + virsh.start(special_name, debug=True) + pid_ping, upsince = save_base.pre_save_setup(new_vm) + if virsh.managedsave(special_name, debug=True).exit_status: + test.fail("VM managedsave fail!") + + LOG.info("TEST_STEP3: Ensure vm state include 'saved', and the saved file exists:") + vm_state = virsh.domstate(special_name, extra="--reason", debug=True).stdout + LOG.info("vm %s state is %s", special_name, vm_state) + if "saved" not in vm_state: + test.fail("The domain state should include 'saved'!") + if not os.path.exists(managed_save_file): + test.fail("The saved file does not exist: %s" % managed_save_file) + + LOG.info("TEST_STEP4: Start the VM to restore:") + virsh.start(special_name, debug=True) + save_base.post_save_check(new_vm, pid_ping, upsince) + if os.path.exists(managed_save_file): + test.fail("The saved file should be removed!") + finally: + virsh.destroy(special_name, debug=True) + virsh.undefine(special_name, "--nvram --managed-save", debug=True) + if os.path.exists(managed_save_file): + process.run("rm -f %s" % managed_save_file, shell=True, ignore_status=True) + bk_xml.sync() From aa3a071a4546148c2ff37b94d91aad72acacdeaf Mon Sep 17 00:00:00 2001 From: nanli Date: Wed, 26 Mar 2025 16:01:35 +0800 Subject: [PATCH 0896/1055] fix get_source_list function missing some disk source paths replace "=" with "append" Signed-off-by: nanli --- provider/virtual_disk/disk_base.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/provider/virtual_disk/disk_base.py b/provider/virtual_disk/disk_base.py index bd79fa8e0e1..456191494ce 100644 --- a/provider/virtual_disk/disk_base.py +++ b/provider/virtual_disk/disk_base.py @@ -79,10 +79,10 @@ def get_source_list(vmxml, disk_type, target_dev): for elem in backing_list: source_ele = elem.find("source") if source_ele is not None: - source_list = [source_ele.get('file') or - source_ele.get('name') or - source_ele.get('dev') or - source_ele.get('volume')] + source_list.append(source_ele.get('file') or + source_ele.get('name') or + source_ele.get('dev') or + source_ele.get('volume')) if source_ele.find("dataStore"): source_list.append( source_ele.find("dataStore").find('source').get('file')) From 3f205b7055fb6c32e02d8a33822a3fedb95606e3 Mon Sep 17 00:00:00 2001 From: Julia Graham Date: Fri, 28 Mar 2025 17:11:24 -0400 Subject: [PATCH 0897/1055] pause_by_domjobabort_and_recover: increase migrate_speed to ensure test does not timeout Signed-of-by: Julia Graham --- .../pause_by_domjobabort_and_recover.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_by_domjobabort_and_recover.cfg b/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_by_domjobabort_and_recover.cfg index 83bed87b680..649a8e62d96 100644 --- a/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_by_domjobabort_and_recover.cfg +++ b/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_by_domjobabort_and_recover.cfg @@ -26,7 +26,7 @@ migrate_desturi_type = "tcp" virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" status_error = "yes" - migrate_speed = "5" + migrate_speed = "15" stress_package = "stress" stress_args = "--cpu 8 --io 4 --vm 2 --vm-bytes 128M --timeout 20s" postcopy_options = "--timeout 4 --timeout-postcopy --postcopy" From 65596203761db46dc32ea0fa314cbd86502c3c0a Mon Sep 17 00:00:00 2001 From: Julia Graham Date: Wed, 19 Feb 2025 17:48:47 -0500 Subject: [PATCH 0898/1055] in_place_upgrade_guest: automates the case that verifies in place upgrade on a guest Signed-off-by: Julia Graham --- libvirt/tests/cfg/in_place_upgrade_guest.cfg | 11 + libvirt/tests/src/in_place_upgrade_guest.py | 210 +++++++++++++++++++ 2 files changed, 221 insertions(+) create mode 100644 libvirt/tests/cfg/in_place_upgrade_guest.cfg create mode 100644 libvirt/tests/src/in_place_upgrade_guest.py diff --git a/libvirt/tests/cfg/in_place_upgrade_guest.cfg b/libvirt/tests/cfg/in_place_upgrade_guest.cfg new file mode 100644 index 00000000000..1530ff81b1a --- /dev/null +++ b/libvirt/tests/cfg/in_place_upgrade_guest.cfg @@ -0,0 +1,11 @@ +- in_place_upgrade_guest: + type = in_place_upgrade_guest + backup_image_before_testing = "yes" + restore_image_after_testing = "yes" + release_check_cmd = "cat /etc/redhat-release" + kernel_check_cmd = "uname -r" + pagesize_check_cmd = "getconf PAGESIZE" + compose_url = "EXAMPLE.COMPOSE.URL" + upgrade_repos_path = "/etc/leapp/files/leapp_upgrade_repositories.repo" + leapp_preupgrade_cmd = "leapp preupgrade --debug --no-rhsm" + leapp_upgrade_cmd = "leapp upgrade --debug --no-rhsm" diff --git a/libvirt/tests/src/in_place_upgrade_guest.py b/libvirt/tests/src/in_place_upgrade_guest.py new file mode 100644 index 00000000000..75a6ec9d741 --- /dev/null +++ b/libvirt/tests/src/in_place_upgrade_guest.py @@ -0,0 +1,210 @@ +# pylint: disable=spelling +# disable pylint spell checker to allow for leapp and preupgrade +import re +import os +import textwrap + +from avocado.utils import process + +from virttest import utils_package +from virttest import utils_test + + +def run(test, params, env): + """ + This case verifies that an in place upgrade on a guest succeeds. + This test only supports upgrading a RHEL X-1 guest to RHEL X on a RHEL X host. + This test ensures that, when relevant, the page size does not change after upgrade. + + :params test: test object + :params params: wrapped dict with all parameters + :params env: environment object + """ + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + + try: + if not vm.is_alive(): + vm.start() + session = vm.wait_for_login() + + source_release, target_release = get_release_info(test, params, session) + check_support(test, source_release, target_release) + + pagesize_check_cmd = params.get("pagesize_check_cmd") + target_page_size = session.cmd_output(pagesize_check_cmd).strip() + + utils_package.package_install(["leapp-upgrade*"], session=session, timeout=360) + + prepare_repos_in_guest(test, params, vm, target_release) + + run_leapp_cmd(test, params, session, step="preupgrade") + run_leapp_cmd(test, params, session, step="upgrade") + session = vm.reboot(session=session, timeout=900) + + verify_upgrade_succeeded(test, params, vm, session, target_release, target_page_size) + + session.close() + + finally: + if vm.is_alive(): + vm.destroy(gracefully=False) + + +def get_release_info(test, params, session): + """ + Get the source release and target release versions + + :params test: test object + :params params: wrapped dict with all parameters + :params session: the vm session + :return: tuple, (source version, target version) + """ + release_check_cmd = params.get("release_check_cmd") + test.log.debug("Getting source release (same as release on vm)") + source_release = extract_release_version(test, session.cmd_output(release_check_cmd)) + test.log.debug("Getting target release (same as release on host)") + target_release = extract_release_version(test, process.run(release_check_cmd, shell=True).stdout_text) + return (source_release, target_release) + + +def extract_release_version(test, release_output): + """ + Extract the release version from the full release output + + :params test: test object + :params release_output: output from running release_check_cmd + """ + test.log.debug("Full release output: %s" % release_output) + return re.findall("\d+\.\d+", release_output)[0] + + +def check_support(test, source_release, target_release): + """ + Check whether the test supports upgrading from source release to target release + + :params test: test object + :params source_release: source release version (upgrading from version) + :params target_release: target release version (upgrading to version) + """ + source_major_release = int(source_release.split(".")[0]) + target_major_release = int(target_release.split(".")[0]) + + if (source_major_release + 1 != target_major_release): + test.cancel("Can not upgrade guest from rhel %s to rhel %s - " + "This test only supports upgrading a RHEL X-1 guest to RHEL X on a RHEL X host" % + (source_release, target_release)) + else: + test.log.info("Upgrading guest from rhel %s to rhel %s on a rhel %s host" % + (source_release, target_release, target_release)) + + +def prepare_repos_in_guest(test, params, vm, target_release): + """ + Prepare repos in the guest by including the upgrade repos paths + + :params test: test object + :params params: wrapped dict with all parameters + :params session: the vm + :params target_release: target release version + """ + compose_url = params.get("compose_url") + upgrade_repos_path = params.get("upgrade_repos_path") + vm_arch_name = params.get("vm_arch_name") + + target_major_release = target_release.split(".")[0] + + upgrade_repos_content = textwrap.dedent(f""" + [APPSTREAM] + name=APPSTREAM + baseurl={compose_url}/rhel-{target_major_release}/nightly/RHEL-{target_major_release}/latest-RHEL-{target_release}/compose/AppStream/{vm_arch_name}/os/ + enabled=1 + gpgcheck=0 + [BASEOS] + name=BASEOS + baseurl={compose_url}/rhel-{target_major_release}/nightly/RHEL-{target_major_release}/latest-RHEL-{target_release}/compose/BaseOS/{vm_arch_name}/os/ + enabled=1 + gpgcheck=0 + """) + + test.log.debug("Temporarily creating leapp_upgrade_repositories file on the host: %s" % upgrade_repos_content) + tmp_upgrade_repos_path = os.path.join(test.debugdir, "tmp_leapp_upgrade_repositories.repo") + with open(tmp_upgrade_repos_path, 'w+') as f: + f.write(upgrade_repos_content) + + test.log.info("Copying leapp_upgrade_repositories file onto the guest") + vm.copy_files_to(host_path=tmp_upgrade_repos_path, guest_path=upgrade_repos_path) + + +def run_leapp_cmd(test, params, session, step): + """ + Run the leapp (pre)upgrade cmd + + :params test: test object + :params params: wrapped dict with all parameters + :params session: the vm session + :params step: "preupgrade" or "upgrade" + """ + leapp_cmd = params.get("leapp_preupgrade_cmd") + if step == "upgrade": + leapp_cmd = params.get("leapp_upgrade_cmd") + + status = session.cmd_status(leapp_cmd, timeout=900) + if status == 0: + test.log.info("Leapp %s executed successfully" % step) + else: + test.fail("Leapp %s failed, see logs for more info" % step) + + +def verify_upgrade_succeeded(test, params, vm, session, target_release, target_page_size): + """ + Verify whether the upgrade succeeded by checking + the release version, the kernel version, and the page size + + :params test: test object + :params params: wrapped dict with all parameters + :params vm: the vm + :params session: the vm session + :params target_release: target release version (guest version after upgrade) + :params target_page_size: target page size (result of pagesize_check_cmd) + """ + vm_arch_name = params.get("vm_arch_name") + release_check_cmd = params.get("release_check_cmd") + kernel_check_cmd = params.get("kernel_check_cmd") + pagesize_check_cmd = params.get("pagesize_check_cmd") + + test.log.debug("Getting guest release after upgrade") + post_release_output = extract_release_version(test, session.cmd_output(release_check_cmd)) + if target_release not in post_release_output: + test.fail("The guest after upgrade should be at rhel %s, but is at %s" % + (target_release, post_release_output)) + else: + test.log.info("The guest after upgrade is at rhel %s, as expected" % post_release_output) + + target_major_release = target_release.split(".")[0] + test.log.debug("Getting guest kernel version after upgrade") + post_kernel_output = session.cmd_output(kernel_check_cmd).strip() + if (".el%s" % target_major_release) not in post_kernel_output: + test.fail("The guest after upgrade should be at kernel version .el%s, but is at %s" % + (target_major_release, post_kernel_output)) + else: + test.log.info("The guest after upgrade is at kernel version .el%s (%s), as expected" % + (target_major_release, post_kernel_output)) + + post_page_size = session.cmd_output(pagesize_check_cmd).strip() + if vm_arch_name == "aarch64" and target_page_size != post_page_size: + # Note: the following is a workaround that should be removed after the leapp tool provides 64k support on aarch64 + test.log.info("Guest page size before upgrade (%s) does not match page size after upgrade (%s)" % + (target_page_size, post_page_size)) + test.log.info("Attempting temporary workaround to update the guest default kernel") + kernel_pattern = ".*el%s.*%sk" % (target_release.replace(".", "_"), int(target_page_size) // 1024) + kernel_version = utils_test.get_available_kernel_paths(session, kernel_pattern)[0] + utils_test.update_vm_default_kernel(vm, kernel_version, reboot=True, guest_arch_name=vm_arch_name, timeout=900) + + session = vm.wait_for_login() + post_page_size = session.cmd_output(pagesize_check_cmd).strip() + if target_page_size != post_page_size: + test.fail("Guest page size before upgrade (%s) does not match page size after upgrade and workaround (%s)" % + (target_page_size, post_page_size)) + else: + test.log.info("Guest page size after upgrade and workaround is %s, as expected" % post_page_size) From e9a0ea0e795151fccb0e7a66de286bf11cbbd04a Mon Sep 17 00:00:00 2001 From: nanli Date: Sat, 29 Mar 2025 18:47:29 +0800 Subject: [PATCH 0899/1055] fix start disk with usb partition issue To avoid other case do partition but influence this case. Signed-off-by: nanli --- .../src/virtual_disks/virtual_disks_usb_startuppolicy.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_usb_startuppolicy.py b/libvirt/tests/src/virtual_disks/virtual_disks_usb_startuppolicy.py index 73e522d8f55..3bbcce4dea2 100644 --- a/libvirt/tests/src/virtual_disks/virtual_disks_usb_startuppolicy.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_usb_startuppolicy.py @@ -1,5 +1,6 @@ import logging import platform +import re import shutil import time @@ -132,6 +133,12 @@ def create_customized_disk(params): vm.start() session = vm.wait_for_login() old_partitions = utils_disk.get_parts_list(session) + # Clean usb partition if existed. + for partitions in old_partitions: + _, output = session.cmd_status_output( + "udevadm info --query=property --name=%s | grep ID_BUS" % (re.sub(r"[\d-]", "", partitions))) + if "ID_BUS=usb" in output and re.findall(r"\d+", partitions): + utils_disk.delete_partition_linux(session, partitions) session.close() vm.destroy(gracefully=False) From 2a6ac58369b0d5cb756ce2fd97ec3bd2ab6cb081 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Wed, 2 Apr 2025 04:27:53 -0400 Subject: [PATCH 0900/1055] ping_check:Update code to report failures after all checks finish Signed-off-by: Haijiao Zhao --- provider/virtual_network/network_base.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/provider/virtual_network/network_base.py b/provider/virtual_network/network_base.py index 06e31d33460..97cc290bbbc 100644 --- a/provider/virtual_network/network_base.py +++ b/provider/virtual_network/network_base.py @@ -103,6 +103,7 @@ def ping_check(params, ips, session=None, force_ipv4=True, **args): :param args: other kwargs """ ping_patterns = {k: v for k, v in params.items() if '_ping_' in k} + failures = [] for pattern, expect_result in ping_patterns.items(): source, destination = pattern.split('_ping_') @@ -138,7 +139,10 @@ def _ping(): if ping_result: LOG.debug(msg) else: - raise exceptions.TestFail(msg) + LOG.error(msg) + failures.append(msg) + if failures: + raise exceptions.TestFail('.'.join(failures)) def create_tap(tap_name, bridge_name, user, flag=''): From 969ec9b13d2be9d88381d686601288c695a1cb94 Mon Sep 17 00:00:00 2001 From: nanli Date: Wed, 2 Apr 2025 10:35:36 +0800 Subject: [PATCH 0901/1055] cpu: add case for virsh cpu models compare with qemu xxxx-303288 Compare x86 cpu models with qemu-kvm Signed-off-by: nanli --- .../cfg/virsh_cmd/host/virsh_cpu_models.cfg | 13 ++++++++- .../src/virsh_cmd/host/virsh_cpu_models.py | 29 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virsh_cmd/host/virsh_cpu_models.cfg b/libvirt/tests/cfg/virsh_cmd/host/virsh_cpu_models.cfg index db5ad3843d5..cc01d7c6f28 100644 --- a/libvirt/tests/cfg/virsh_cmd/host/virsh_cpu_models.cfg +++ b/libvirt/tests/cfg/virsh_cmd/host/virsh_cpu_models.cfg @@ -10,7 +10,18 @@ variants: - auto_get_arch: - specific_arch: - cpu_arch = "x86_64" + only local_host + check_qemu_cpu_supported_cmd = "/usr/libexec/qemu-kvm -cpu help | awk '/Available CPUs/,/Recognized CPUID flags/' | grep '^ ' | awk '{print $1}'" + skip_list = ['base', 'host', 'max'] + variants arch_option: + - arch_x86: + cpu_arch = "x86_64" + - arch_s390: + cpu_arch = "s390" + msg = "all CPU models are accepted" + - arch_aarch64: + cpu_arch = "aarch64" + msg = "all CPU models are accepted" variants: - local_host: - remote_host: diff --git a/libvirt/tests/src/virsh_cmd/host/virsh_cpu_models.py b/libvirt/tests/src/virsh_cmd/host/virsh_cpu_models.py index f76cea0c86c..d89244433bc 100644 --- a/libvirt/tests/src/virsh_cmd/host/virsh_cpu_models.py +++ b/libvirt/tests/src/virsh_cmd/host/virsh_cpu_models.py @@ -1,6 +1,8 @@ import logging as log from six import itervalues +from avocado.utils import process + from virttest import ssh_key from virttest import virsh from virttest import libvirt_vm @@ -13,6 +15,31 @@ logging = log.getLogger('avocado.' + __name__) +def compare_cpu_model_with_qemu(test, params, virsh_cpu_model_result, qemu_cmd): + """ + Compare the libvirt cpu model same with the model in qemu-kvm. + + :params: test: test object + :params: params, cfg parameter dict. + :params: virsh_cpu_model_result:virsh cpu-model result + :params: qemu_cmd: qemu cmd to get cpu model name. + """ + arch_option = params.get("arch_option") + if arch_option == "arch_x86": + skip_list = eval(params.get("skip_list", [])) + qemu_models = process.run(qemu_cmd, ignore_status=False, shell=True).stdout_text.strip().split("\n") + virsh_cpu_model_result = virsh_cpu_model_result.stdout_text.strip().split("\n") + + for qemu_model in qemu_models: + if qemu_model not in {*virsh_cpu_model_result, *skip_list}: + test.fail("Expected the model of qemu-kvm:%s in virsh cpu-model result" % qemu_model) + test.log.debug("All the cpu models of qemu-kvm are contained in virsh cpu-models.") + else: + msg = params.get("msg", "") + if msg not in virsh_cpu_model_result.stdout_text: + test.fail("Expected '%s' in virsh cpu-models result" % msg) + + def run(test, params, env): """ Test command virsh cpu-models @@ -23,6 +50,7 @@ def run(test, params, env): remote_ref = params.get("remote_ref", "") connect_uri = libvirt_vm.normalize_connect_uri(params.get("connect_uri", "default")) + qemu_cmd = params.get("check_qemu_cpu_supported_cmd", "") if remote_ref == "remote": remote_ip = params.get("remote_ip", "REMOTE.EXAMPLE.COM") @@ -54,3 +82,4 @@ def run(test, params, env): result = virsh.cpu_models(arch, options=option, uri=connect_uri, ignore_status=True, debug=True) utlv.check_exit_status(result, expect_error=status_error) + compare_cpu_model_with_qemu(test, params, result, qemu_cmd) From 6be90dc95ddcb20721c6402bbeeb27a778a44c39 Mon Sep 17 00:00:00 2001 From: meinaLi Date: Wed, 2 Apr 2025 21:31:03 -0400 Subject: [PATCH 0902/1055] Backingchain: add 1 new case about datastore element Automate case: VIRT-303303 - Do blockcommit/blockpull with different attributes of source elements Signed-off-by: meinaLi --- ...ommit_pull_with_disk_source_attributes.cfg | 18 +++++ ...commit_pull_with_disk_source_attributes.py | 79 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 libvirt/tests/cfg/backingchain/with_disk_attributes_test/commit_pull_with_disk_source_attributes.cfg create mode 100644 libvirt/tests/src/backingchain/with_disk_attributes_test/commit_pull_with_disk_source_attributes.py diff --git a/libvirt/tests/cfg/backingchain/with_disk_attributes_test/commit_pull_with_disk_source_attributes.cfg b/libvirt/tests/cfg/backingchain/with_disk_attributes_test/commit_pull_with_disk_source_attributes.cfg new file mode 100644 index 00000000000..ac7133ea0b1 --- /dev/null +++ b/libvirt/tests/cfg/backingchain/with_disk_attributes_test/commit_pull_with_disk_source_attributes.cfg @@ -0,0 +1,18 @@ +- backingchain.with_disk_attributes_test.with_source_attributes: + type = commit_pull_with_disk_source_attributes + start_vm = no + common_options = " --wait --verbose" + target_disk = "vdb" + disk_type = "file" + snap_num = 3 + disk_dict = {"type_name":"${disk_type}", "target":{"dev": "${target_disk}", "bus": "virtio"}, "driver": {"name": "qemu", "type":"qcow2"}} + variants: + - with_datastore: + func_supported_since_libvirt_ver = (10, 10, 0) + data_file_option = " -o data_file=%s" + variants block_cmd: + - blockcommit: + blockcommit_options = " --active --pivot" + expected_chain_index = "base" + - blockpull: + expected_chain_index = "3" diff --git a/libvirt/tests/src/backingchain/with_disk_attributes_test/commit_pull_with_disk_source_attributes.py b/libvirt/tests/src/backingchain/with_disk_attributes_test/commit_pull_with_disk_source_attributes.py new file mode 100644 index 00000000000..7f85a320db1 --- /dev/null +++ b/libvirt/tests/src/backingchain/with_disk_attributes_test/commit_pull_with_disk_source_attributes.py @@ -0,0 +1,79 @@ +import os + +from virttest import data_dir +from virttest import virsh +from virttest import libvirt_version +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt + +from provider.backingchain import blockcommand_base +from provider.backingchain import check_functions +from provider.virtual_disk import disk_base + + +def run(test, params, env): + """ + Do blockcommit/blockpull with different attributes of source elements. + 1) Prepare a running guest with the following source elements and create snapshots: + - datastore + 2) Do blockcommit/blockpull and check dumpxml. + """ + + def setup_test(): + """ + Prepare a running guest with different source elements and create snapshots. + """ + test.log.info("Setup env: prepare a running guest and snap chain.") + data_file = data_dir.get_data_dir() + '/datastore.img' + data_file_option = params.get("data_file_option") % data_file + back_obj.new_image_path = disk_obj.add_vm_disk(disk_type, disk_dict, new_image_path="", + extra=data_file_option) + back_obj.backingchain_common_setup(create_snap=True, snap_num=snap_num) + disk_xml = virsh.dumpxml(vm_name, "--xpath //disk", debug=True).stdout_text + if data_file not in disk_xml: + test.fail("Can't get the datastore element automatically!") + return data_file, back_obj.new_image_path + + def run_test(): + """ + Do blockcommit/blockpull for the guest with different source attributes. + """ + test.log.info("TEST_STEP1: Do blockcommit/blockpull.") + if block_cmd == "blockcommit": + virsh.blockcommit(vm_name, target_disk, common_options+blockcommit_options, + ignore_status=False, debug=True) + if block_cmd == "blockpull": + virsh.blockpull(vm_name, target_disk, common_options, + ignore_status=False, debug=True) + test.log.info("TEST_STEP2: Check expected disk image.") + expected_chain = back_obj.convert_expected_chain(expected_chain_index) + check_obj.check_backingchain_from_vmxml(disk_type, target_disk, expected_chain) + + libvirt_version.is_libvirt_feature_supported(params) + vm_name = params.get("main_vm") + target_disk = params.get("target_disk") + disk_type = params.get("disk_type") + disk_dict = eval(params.get("disk_dict", "{}")) + common_options = params.get("common_options") + snap_num = int(params.get("snap_num")) + block_cmd = params.get("block_cmd") + blockcommit_options = params.get("blockcommit_options", "") + expected_chain_index = params.get("expected_chain_index") + + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + back_obj = blockcommand_base.BlockCommand(test, vm, params) + check_obj = check_functions.Checkfunction(test, vm, params) + disk_obj = disk_base.DiskBase(test, vm, params) + + try: + data_file, new_image_path = setup_test() + run_test() + finally: + libvirt.clean_up_snapshots(vm_name) + bkxml.sync() + for file in [data_file, new_image_path]: + if os.path.exists(file): + os.remove(file) From efb81de3d7a78b83a00b219b3400980dd96bf93b Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Thu, 3 Apr 2025 16:20:27 +0800 Subject: [PATCH 0903/1055] virtio_page_per_vq: fix var reference Signed-off-by: Dan Zheng --- libvirt/tests/src/virtio/virtio_page_per_vq.py | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/src/virtio/virtio_page_per_vq.py b/libvirt/tests/src/virtio/virtio_page_per_vq.py index ac0f8d407f6..de4e9920345 100644 --- a/libvirt/tests/src/virtio/virtio_page_per_vq.py +++ b/libvirt/tests/src/virtio/virtio_page_per_vq.py @@ -182,6 +182,7 @@ def start_guest(): vm = env.get_vm(vm_name) vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) bkxml = vmxml.copy() + disk_image_path = None try: device_xml, vmxml, disk_image_path = prepare_test(vmxml) From 195ddb7308a3df24ae1f7ad739032458805fb42d Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 26 Feb 2025 13:16:49 -0500 Subject: [PATCH 0904/1055] filesystem_device: test fix of missing directory Add test case: Given 2 filesystems but one set up incorrectly And I can't start the VM When I fix the setup Then I can start the VM Signed-off-by: Sebastian Mitterle --- .../tests/cfg/virtual_device/filesystem_device.cfg | 4 ++++ .../tests/src/virtual_device/filesystem_device.py | 13 ++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg index acf25668989..3acde3c1c59 100644 --- a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg +++ b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg @@ -37,6 +37,10 @@ - multiple_fs: fs_num = 2 only xattr_on.cache_mode_auto + - retry_multiple_fs: + fs_num = 2 + omit_dir_at_first = yes + only nop..xattr_on.cache_mode_auto.thread_pool_noset variants: - thread_pool_16: thread_pool_size = 16 diff --git a/libvirt/tests/src/virtual_device/filesystem_device.py b/libvirt/tests/src/virtual_device/filesystem_device.py index cd55c6dbcba..07546f9242b 100644 --- a/libvirt/tests/src/virtual_device/filesystem_device.py +++ b/libvirt/tests/src/virtual_device/filesystem_device.py @@ -256,6 +256,7 @@ def check_filesystem_hotplug_with_mem_setup(): script_content = params.get("stress_script", "") stdio_handler_file = "file" == params.get("stdio_handler") setup_mem = params.get("setup_mem", False) + omit_dir_at_first = "yes" == params.get("omit_dir_at_first", "no") fs_devs = [] vms = [] @@ -294,7 +295,9 @@ def check_filesystem_hotplug_with_mem_setup(): driver = {'type': driver_type, 'queue': queue_size} source_dir = os.path.join('/var/tmp/', str(dir_prefix) + str(index)) logging.debug(source_dir) - not os.path.isdir(source_dir) and os.mkdir(source_dir) + if not os.path.isdir(source_dir): + if not (omit_dir_at_first and fs_index == 0): + os.mkdir(source_dir) target_dir = dir_prefix + str(index) source = {'socket': source_socket} target = {'dir': target_dir} @@ -355,6 +358,14 @@ def check_filesystem_hotplug_with_mem_setup(): logging.debug(vmxml) libvirt_pcicontr.reset_pci_num(vm_names[index]) result = virsh.start(vm_names[index], debug=True) + if omit_dir_at_first: + expect_error = True + libvirt.check_exit_status(result, expect_error) + source_dir = os.path.join('/var/tmp/', str(dir_prefix) + str(0)) + os.mkdir(source_dir) + result = virsh.start(vm_names[index], debug=True) + libvirt.check_exit_status(result, not expect_error) + return if hotplug_unplug: if stdio_handler_file: qemu_config = LibvirtQemuConfig() From cfda32730f38ffd10e666d18cafbadcfa18dfbd3 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 5 Mar 2025 06:39:09 -0500 Subject: [PATCH 0905/1055] filesystem_device: improve parameter coverage Cover more test values for parameters according to our test plan. 1.) thread_pool_size = 0 2.) sandbox mode Furthermore, the test constructed a long regular expression assuming a certain order of the parameters to be present in the virtiofsd command line. However, the order is not relevant, so instead of constructing one long regular expression add one for each parameter instead. This way the test won't fail if the order was different and it's easier to add new expectations. Signed-off-by: Sebastian Mitterle --- .../cfg/virtual_device/filesystem_device.cfg | 11 ++++++++ .../src/virtual_device/filesystem_device.py | 28 ++++++++++--------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg index 3acde3c1c59..05adaa22565 100644 --- a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg +++ b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg @@ -42,6 +42,17 @@ omit_dir_at_first = yes only nop..xattr_on.cache_mode_auto.thread_pool_noset variants: + - sandbox_mode_none: + sandbox_mode = "none" + - sandbox_mode_chroot: + sandbox_mode = "chroot" + - sandbox_mode_namespace: + sandbox_mode = "namespace" + variants: + - thread_pool_0: + thread_pool_size = 0 + openfiles = "no" + only positive_test..nop..xattr_on.cache_mode_auto, positive_test..detach_device..xattr_on.cache_mode_auto - thread_pool_16: thread_pool_size = 16 openfiles = "yes" diff --git a/libvirt/tests/src/virtual_device/filesystem_device.py b/libvirt/tests/src/virtual_device/filesystem_device.py index 07546f9242b..84365d1bfb7 100644 --- a/libvirt/tests/src/virtual_device/filesystem_device.py +++ b/libvirt/tests/src/virtual_device/filesystem_device.py @@ -37,29 +37,31 @@ def run(test, params, env): 5.Lifecycle for guest with virtiofs filesystem device. """ - def generate_expected_process_option(): + def generate_expected_process_options(): """ Generate expected virtiofsd process option """ - expected_results = "" + expected_results = [] if cache_mode != "auto": if cache_mode == "none": - expected_results += "cache(\s|=)(none|never)" + expected_results.append("cache(\s|=)(none|never)") else: - expected_results += "cache(\s|=)%s" % cache_mode + expected_results.append("cache(\s|=)%s" % cache_mode) if xattr == "on": - expected_results += "(\s--|,)xattr" + expected_results.append("(\s--|,)xattr") elif xattr == "off" and not libvirt_version.version_compare(10, 5, 0): - expected_results += ",no_xattr" + expected_results.append(",no_xattr") if thread_pool_size: # Even through there is a equal mark between --thread-pool-size and # its value for libvirt format. But there is no equal mark in # virtiofsd man pages. Add another kind of pattern here to avoid # possible change in the future again. - expected_results += " --thread-pool-size(\s|=)%s" % thread_pool_size + expected_results.append("--thread-pool-size(\s|=)%s" % thread_pool_size) if openfiles: - expected_results += " --rlimit-nofile(\s|=)%s" % open_files_max - logging.debug(expected_results) + expected_results.append(" --rlimit-nofile(\s|=)%s" % open_files_max) + if sandbox_mode and sandbox_mode == "namespace": + expected_results.append(" --sandbox(\s|=)%s" % sandbox_mode) + logging.debug(f"Expected qemu cmdline pattern {expected_results}") return expected_results def shared_data(vm_names, fs_devs): @@ -224,7 +226,7 @@ def check_filesystem_hotplug_with_mem_setup(): start_vm = params.get("start_vm", "no") vm_names = params.get("vms", "avocado-vt-vm1").split() cache_mode = params.get("cache_mode", "none") - xattr = params.get("xattr", "on") + sandbox_mode = params.get("sandbox_mode", "none") xattr = params.get("xattr", "on") path = params.get("virtiofsd_path", "/usr/libexec/virtiofsd") thread_pool_size = params.get("thread_pool_size") @@ -303,9 +305,9 @@ def check_filesystem_hotplug_with_mem_setup(): target = {'dir': target_dir} if launched_mode == "auto": binary_keys = ['path', 'cache_mode', 'xattr', - 'thread_pool_size', "open_files_max"] + 'thread_pool_size', "open_files_max", "sandbox_mode"] binary_values = [path, cache_mode, xattr, - thread_pool_size, open_files_max] + thread_pool_size, open_files_max, sandbox_mode] binary_dict = dict(zip(binary_keys, binary_values)) source = {'dir': source_dir} accessmode = "passthrough" @@ -384,8 +386,8 @@ def check_filesystem_hotplug_with_mem_setup(): return else: utils_test.libvirt.check_exit_status(result, expect_error=False) - expected_results = generate_expected_process_option() if launched_mode == "auto": + expected_results = generate_expected_process_options() cmd = 'ps aux | grep /usr/libexec/virtiofsd' utils_test.libvirt.check_cmd_output(cmd, content=expected_results) From f313de4948c2f443e323570f08096f1562e9d777 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 5 Mar 2025 07:49:43 -0500 Subject: [PATCH 0906/1055] filesystem_device: restrict socket file check Avoid too many variants for checking socket and pid file naming. Restrict to one per backing and externally/internally. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/virtual_device/filesystem_device.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg index 05adaa22565..a35c8fb205e 100644 --- a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg +++ b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg @@ -76,7 +76,7 @@ - nop: - socket_file_checking: socket_file_checking = "yes" - only xattr_on.cache_mode_auto, externally_launched_fs_test + only xattr_on.cache_mode_auto.thread_pool_noset.sandbox_mode_none..one_fs.one_guest, externally_launched_fs_test - lifecycle: only xattr_on.cache_mode_auto..one_fs variants: From b648da36fba93087009a234695d86b60dd0e968e Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Thu, 6 Mar 2025 04:41:23 -0500 Subject: [PATCH 0907/1055] filesystem_device: externally launch several filesystems 1. For externally launched filesystem instances, there must be a socket for each filesystem and VM, therefore, the filesystem device XML definitions `fs_dev` cannot be reused. a. move the logic to create the filesystem device XML into its own function that will also return the source directory because that is not part of the XML for externally launched instances; the function creates the same XML definitions for internally launched like before, distinguished by the mount directory and tag index: ``` ... ``` but it will create different XMLs when externally launched ``` ... ... ``` b. this means, in the case of externally launched filesystem devices there will be more `fs_dev` instances than there are actual shared directories `fs_num`; update the `shared_data` function accordingly to expect as many different md5 sums as there are shared directories, not filesytem device definitions c. create an internal function `_fs_dev_indexes` to map between the list indexes of all created filesystem device XMLs and the guest indexes for both, internally and externally launched filesytems; this way the code structure can be maintained that first creates all definitions that will occur in the test case and only then used them in the test d. create function to handle the filesystem provision (cold, hot, or re-defining the domain XML); it also starts the external virtiofsd process if necessary 2. Update the test cleanup to remove all files and folders (socket, pid, source directory) according to their name pattern to stabilize the cleanup and reduce complexity Signed-off-by: Sebastian Mitterle --- .../cfg/virtual_device/filesystem_device.cfg | 15 +- .../src/virtual_device/filesystem_device.py | 264 ++++++++++++------ 2 files changed, 189 insertions(+), 90 deletions(-) diff --git a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg index a35c8fb205e..7cc1586765b 100644 --- a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg +++ b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg @@ -19,17 +19,22 @@ with_numa = no variants: - externally_launched_fs_test: + launch_mode = "externally" variants: - - launched_mode: - launched_mode = "externally" - source_socket = "/var/tmp/vm001.socket" + - one_guest: + - two_guests: + only nop..one_fs + vms = "avocado-vt-vm1 avocado-vt-vm2" + variants: + - one_fs: + fs_num = 1 + - multiple_fs: + fs_num = 2 - fs_test: variants: - one_guest: - guest_num = 1 - two_guests: vms = "avocado-vt-vm1 avocado-vt-vm2" - guest_num = 2 only nop.fs_test.xattr_on.cache_mode_auto..one_fs, hotplug_unplug..fs_test.xattr_on.cache_mode_auto..one_fs variants: - one_fs: diff --git a/libvirt/tests/src/virtual_device/filesystem_device.py b/libvirt/tests/src/virtual_device/filesystem_device.py index 84365d1bfb7..6f3f1234ddd 100644 --- a/libvirt/tests/src/virtual_device/filesystem_device.py +++ b/libvirt/tests/src/virtual_device/filesystem_device.py @@ -1,8 +1,11 @@ -import os import logging as log +import os +import shutil import time import threading +from glob import glob + from avocado.utils import process from avocado.utils import path as utils_path @@ -73,8 +76,11 @@ def shared_data(vm_names, fs_devs): """ md5s = [] for vm in vms: + guest_index = vms.index(vm) session = vm.wait_for_login() - for fs_dev in fs_devs: + fs_indexes = _fs_dev_indexes(guest_index) + for fs_index in fs_indexes: + fs_dev = fs_devs[fs_index] logging.debug(fs_dev) mount_dir = '/var/tmp/' + fs_dev.target['dir'] session.cmd('rm -rf %s' % mount_dir, ignore_all_errors=False) @@ -100,7 +106,7 @@ def shared_data(vm_names, fs_devs): logging.debug(md5_value) md5s.append(md5_value) session.close() - if len(set(md5s)) != len(fs_devs): + if len(set(md5s)) != fs_num: test.fail("The md5sum value are not the same in guests and host") def launch_externally_virtiofs(source_dir, source_socket): @@ -149,16 +155,18 @@ def run_stress_script(session, script_path): # Set ULIMIT_NOFILE to increase the number of unlinked files session.cmd("ulimit -n 500000 && /usr/bin/python3 %s" % script_path, timeout=120) - def umount_fs(vm): + def umount_fs(guest_index): """ Unmount the filesystem in guest - :param vm: filesystem in this vm that should be unmounted + :param guest_index: the guest's index in vms """ + fs_indexes = _fs_dev_indexes(guest_index) + vm = vms[guest_index] if vm.is_alive(): session = vm.wait_for_login() - for fs_dev in fs_devs: - mount_dir = '/var/tmp/' + fs_dev.target['dir'] + for index in fs_indexes: + mount_dir = '/var/tmp/' + fs_devs[index].target['dir'] session.cmd('umount -f %s' % mount_dir, ignore_all_errors=True) session.cmd('rm -rf %s' % mount_dir, ignore_all_errors=True) session.close() @@ -202,29 +210,31 @@ def check_filesystem_hotplug_with_mem_setup(): fs_dict = eval(params.get('fs_dict', '{}')) source_dir = params.get('source_dir') dev_type = params.get('dev_type') + vm_name = vm_names[-1] vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( - vm_names[int(guest_num) - 1]) + vm_name) vmxml.setup_attrs(**vm_attrs) virsh.define(vmxml.xml, debug=True, ignore_status=False) libvirtd = utils_libvirtd.Libvirtd() libvirtd.restart() - vmxml = vm_xml.VMXML.new_from_dumpxml(vm_names[int(guest_num) - 1]) + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) vmxml.remove_all_device_by_type(dev_type) vmxml.sync() - vm = env.get_vm(vm_names[int(guest_num) - 1]) + vm = env.get_vm(vm_name) vm.start() vm.wait_for_login(timeout=120) os.mkdir(source_dir) fs = libvirt_vmxml.create_vm_device_by_type(dev_type, fs_dict) - virsh.attach_device(vm_names[int(guest_num) - 1], fs.xml, + virsh.attach_device(vm_name, fs.xml, debug=True, ignore_status=False) start_vm = params.get("start_vm", "no") vm_names = params.get("vms", "avocado-vt-vm1").split() + guest_num = len(vm_names) cache_mode = params.get("cache_mode", "none") sandbox_mode = params.get("sandbox_mode", "none") xattr = params.get("xattr", "on") @@ -233,7 +243,6 @@ def check_filesystem_hotplug_with_mem_setup(): openfiles = params.get("openfiles", "no") == "yes" queue_size = int(params.get("queue_size", "512")) driver_type = params.get("driver_type", "virtiofs") - guest_num = int(params.get("guest_num", "1")) fs_num = int(params.get("fs_num", "1")) vcpus_per_cell = int(params.get("vcpus_per_cell", 2)) dir_prefix = params.get("dir_prefix", "mount_tag") @@ -252,7 +261,7 @@ def check_filesystem_hotplug_with_mem_setup(): with_numa = params.get("with_numa", "yes") == "yes" with_memfd = params.get("with_memfd", "no") == "yes" source_socket = params.get("source_socket", "/var/tmp/vm001.socket") - launched_mode = params.get("launched_mode", "auto") + launch_mode = params.get("launch_mode", "auto") destroy_start = params.get("destroy_start", "no") == "yes" bug_url = params.get("bug_url", "") script_content = params.get("stress_script", "") @@ -271,9 +280,6 @@ def check_filesystem_hotplug_with_mem_setup(): if hotplug_unplug and not utils_path.find_command("lsof", default=False): test.error("Lsof command is required to run test, but not installed") - if len(vm_names) != guest_num: - test.error("This test needs exactly %d vms." % guest_num) - if not libvirt_version.version_compare(7, 0, 0) and not with_numa: test.cancel("Not supported without NUMA before 7.0.0") @@ -292,18 +298,29 @@ def check_filesystem_hotplug_with_mem_setup(): else: open_files_max = None - # Define filesystem device xml - for index in range(fs_num): + def _get_fs_dev_and_source_dir(fs_index, socket_index): + """ + Returns the device XML for both internally or externally launched + virtiofsd. + + :param fs_index: the index of the filesystem + :param socket_index: the index of the socket for externally launched + virtiofsd; this parameter is ignored for internally + launched virtifosd and must be different for each + VM accessing the filesystem + :return tuple: (fs_dev, source_dir) - the device xml but also the source + directory which is not part of the XML so the test can + launch the instance for it + """ driver = {'type': driver_type, 'queue': queue_size} - source_dir = os.path.join('/var/tmp/', str(dir_prefix) + str(index)) + source_dir = os.path.join('/var/tmp/', str(dir_prefix) + str(fs_index)) logging.debug(source_dir) if not os.path.isdir(source_dir): if not (omit_dir_at_first and fs_index == 0): os.mkdir(source_dir) - target_dir = dir_prefix + str(index) - source = {'socket': source_socket} + target_dir = dir_prefix + str(fs_index) target = {'dir': target_dir} - if launched_mode == "auto": + if launch_mode == "auto": binary_keys = ['path', 'cache_mode', 'xattr', 'thread_pool_size', "open_files_max", "sandbox_mode"] binary_values = [path, cache_mode, xattr, @@ -314,23 +331,126 @@ def check_filesystem_hotplug_with_mem_setup(): fsdev_keys = ['accessmode', 'driver', 'source', 'target', 'binary'] fsdev_values = [accessmode, driver, source, target, binary_dict] else: + source_socket = f"/var/tmp/vm_test{socket_index}.socket" + source = {'socket': source_socket} fsdev_keys = ['driver', 'source', 'target'] fsdev_values = [driver, source, target] fsdev_dict = dict(zip(fsdev_keys, fsdev_values)) logging.debug(fsdev_dict) - fs_dev = libvirt_device_utils.create_fs_xml(fsdev_dict, launched_mode) + fs_dev = libvirt_device_utils.create_fs_xml(fsdev_dict, launch_mode) logging.debug(fs_dev) - fs_devs.append(fs_dev) + return fs_dev, source_dir + + def create_fs_devs(): + """ + Creates all fs devs necessary for the test setup and adds them + to the list fs_devs. + """ + with_sockets = launch_mode == "externally" + def __indexes(): + """ + Helper function that creates input parameters for + _get_fs_dev_and_source_dir. They are different for internally + and externally launched virtiofsd, e.g. for 2 times 2: + (fs_index, socket_index) + internally: the same xml can be used for all guests: + (0, None), (1, None) + externally: there must be 1 socket for each instance and guest: + (0, 0), (0, 1), (1, 2), (1, 3) + """ + socket_number = -1 + for i in range(fs_num): + if not with_sockets: + yield (i, None) + else: + for j in range(guest_num): + socket_number += 1 + yield (i, socket_number) + + for index in __indexes(): + fs_dev, source_dir = _get_fs_dev_and_source_dir(index[0], index[1]) + if with_sockets: + launch_externally_virtiofs(source_dir, fs_dev.source['socket']) + fs_devs.append(fs_dev) + + def _fs_dev_indexes(guest_index): + """ + Returns the list of indexes of all filesystem devices in fs_devs + that correspond to guest_index, e.g. for 2 times 2: + (fs_dev_index, guest_index) + internally launched: no socket necessary, reuse file + fs_dev with index 0, 1 can both be attached to guest 0, 1 + externally launched: can't reuse file + fs_dev with index 0, 2 (with sockets 0, 2) are attached to guest 0 + fs_dev with index 1, 3 (with sockets 1, 3) are attached to guest 1 + + :param guest_index: the index of the VM in vms list + """ + if launch_mode == "externally": + return range(guest_index, fs_num*guest_num, guest_num) + else: + return range(fs_num) + + def update_vm_with_fs_devs(guest_index, attach): + """ + Either updates the VM XML or attaches the device XML + + :param guest_index: the index of the guest in vms + :param attach: if True uses `virsh attach` else it redefines the VM + """ + fs_indexes = _fs_dev_indexes(guest_index) + if attach: + for fs_index in fs_indexes: + ret = virsh.attach_device(vms[guest_index].name, fs_devs[fs_index].xml, + flagstr='--current', debug=True) + utils_test.libvirt.check_exit_status(ret, expect_error=False) + else: + for fs_index in fs_indexes: + vmxml.add_device(fs_devs[fs_index]) + vmxml.sync() + + def detach_fs_dev(guest_index): + """ + The function uses the virsh detach command to detach + all file systems from the guest determined by its index. + + :param guest_index: the index of the VM as given by the vms list + """ + vm = vms[guest_index] + fs_indexes = _fs_dev_indexes(guest_index) + for fs_index in fs_indexes: + fs_dev = fs_devs[fs_index] + if detach_device_alias: + utils_package.package_install("lsof") + alias = fs_dev.alias['name'] + cmd = 'lsof /var/log/libvirt/qemu/%s-%s-virtiofsd.log' % (vm.name, alias) + output = process.run(cmd).stdout_text.splitlines() + for item in output[1:]: + if stdio_handler_file: + if item.split()[0] != "virtiofsd": + test.fail("When setting stdio_handler as file, the command" + "to write log should be virtiofsd!") + else: + if item.split()[0] != "virtlogd": + test.fail("When setting stdio_handler as logd, the command" + "to write log should be virtlogd!") + ret = virsh.detach_device_alias(vm.name, alias, ignore_status=True, + debug=True, wait_for_event=True, + event_timeout=10) + else: + ret = virsh.detach_device(vm.name, fs_dev.xml, ignore_status=True, + debug=True, wait_for_event=True) + libvirt.check_exit_status(ret, status_error) + check_filesystem_in_guest(vm, fs_dev) + + create_fs_devs() - #Start guest with virtiofs filesystem device for index in range(guest_num): - logging.debug("prepare vm %s", vm_names[index]) vm = env.get_vm(vm_names[index]) + logging.debug("prepare vm %s", vm.name) vms.append(vm) - vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_names[index]) - vmxml_backup = vmxml.copy() - vmxml_backups.append(vmxml_backup) - logging.debug(fs_dev) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) + vmxml_backups.append(vmxml.copy()) if vmxml.max_mem < 1024000: vmxml.max_mem = 1024000 if with_hugepages: @@ -344,28 +464,22 @@ def check_filesystem_hotplug_with_mem_setup(): vm_xml.VMXML.set_vm_vcpus(vmxml.vm_name, vmxml.vcpu, numa_number=numa_no) vm_xml.VMXML.set_memoryBacking_tag(vmxml.vm_name, access_mode="shared", hpgs=with_hugepages, memfd=with_memfd) - vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_names[index]) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) logging.debug(vmxml) - if launched_mode == "externally": - launch_externally_virtiofs(source_dir, source_socket) if coldplug: - ret = virsh.attach_device(vm_names[index], fs_devs[0].xml, - flagstr='--config', debug=True) - utils_test.libvirt.check_exit_status(ret, expect_error=False) + update_vm_with_fs_devs(index, attach=True) else: if not hotplug_unplug: - for fs in fs_devs: - vmxml.add_device(fs) - vmxml.sync() + update_vm_with_fs_devs(index, attach=False) logging.debug(vmxml) - libvirt_pcicontr.reset_pci_num(vm_names[index]) - result = virsh.start(vm_names[index], debug=True) + libvirt_pcicontr.reset_pci_num(vm.name) + result = virsh.start(vm.name, debug=True) if omit_dir_at_first: expect_error = True libvirt.check_exit_status(result, expect_error) source_dir = os.path.join('/var/tmp/', str(dir_prefix) + str(0)) os.mkdir(source_dir) - result = virsh.start(vm_names[index], debug=True) + result = virsh.start(vm.name, debug=True) libvirt.check_exit_status(result, not expect_error) return if hotplug_unplug: @@ -373,24 +487,22 @@ def check_filesystem_hotplug_with_mem_setup(): qemu_config = LibvirtQemuConfig() qemu_config.stdio_handler = "file" utils_libvirtd.Libvirtd().restart() - for fs_dev in fs_devs: - ret = virsh.attach_device(vm_names[index], fs_dev.xml, - ignore_status=True, debug=True) - libvirt.check_exit_status(ret, status_error) - + update_vm_with_fs_devs(index, attach=True) if status_error: return - if status_error and not managedsave: + + if status_error and not lifecycle_scenario == "managedsave": expected_error = error_msg_start utils_test.libvirt.check_exit_status(result, expected_error) return else: utils_test.libvirt.check_exit_status(result, expect_error=False) - if launched_mode == "auto": + if launch_mode == "auto": expected_results = generate_expected_process_options() cmd = 'ps aux | grep /usr/libexec/virtiofsd' utils_test.libvirt.check_cmd_output(cmd, content=expected_results) + shared_data(vm_names, fs_devs) if suspend_resume: virsh.suspend(vm_names[0], debug=True, ignore_status=False) @@ -457,47 +569,29 @@ def check_filesystem_hotplug_with_mem_setup(): if not (status1 and status2): test.fail("The socket and pid file is not as expected") elif hotplug_unplug: - for vm in vms: - umount_fs(vm) - for fs_dev in fs_devs: - if detach_device_alias: - utils_package.package_install("lsof") - alias = fs_dev.alias['name'] - cmd = 'lsof /var/log/libvirt/qemu/%s-%s-virtiofsd.log' % (vm.name, alias) - output = process.run(cmd).stdout_text.splitlines() - for item in output[1:]: - if stdio_handler_file: - if item.split()[0] != "virtiofsd": - test.fail("When setting stdio_handler as file, the command" - "to write log should be virtiofsd!") - else: - if item.split()[0] != "virtlogd": - test.fail("When setting stdio_handler as logd, the command" - "to write log should be virtlogd!") - ret = virsh.detach_device_alias(vm.name, alias, ignore_status=True, - debug=True, wait_for_event=True, - event_timeout=10) - else: - ret = virsh.detach_device(vm.name, fs_dev.xml, ignore_status=True, - debug=True, wait_for_event=True) - libvirt.check_exit_status(ret, status_error) - check_filesystem_in_guest(vm, fs_dev) - check_detached_xml(vm) + for guest_index in range(guest_num): + umount_fs(guest_index) + vm = vms[guest_index] + detach_fs_dev(guest_index) + check_detached_xml(vms[guest_index]) finally: for vm in vms: - alias = fs_dev.alias['name'] - process.run('rm -f /var/log/libvirt/qemu/%s-%s-virtiofsd.log' % (vm.name, alias)) + index = vms.index(vm) if vm.is_alive(): - umount_fs(vm) + umount_fs(index) vm.destroy(gracefully=False) - for vmxml_backup in vmxml_backups: - vmxml_backup.sync() - for index in range(fs_num): - process.run('rm -rf %s' % '/var/tmp/' + str(dir_prefix) + str(index), ignore_status=False) - process.run('rm -rf %s' % source_socket, ignore_status=False, shell=True) - if launched_mode == "externally": - process.run('restorecon %s' % path, ignore_status=False, shell=True) + vmxml_backups[index].sync() utils_memory.set_num_huge_pages(backup_huge_pages_num) if stdio_handler_file: qemu_config.restore() utils_libvirtd.Libvirtd().restart() + for path_pattern in [ + "/var/log/libvirt/qemu/*-virtiofsd.log'", + "/var/tmp/vm_test*socket*", + ]: + for file in glob(path_pattern): + os.remove(file) + for folder in glob("/var/tmp/%s*" % str(dir_prefix)): + shutil.rmtree(folder) + if launch_mode == "externally": + process.run('restorecon %s' % path, ignore_status=False, shell=True) From 5e73a239dc1582a86417559d9d00474916eb8fa7 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Fri, 14 Mar 2025 07:48:58 -0400 Subject: [PATCH 0908/1055] filesystem_device: enable lifecycle tests for externally launched 1. move managedsave below lifecycle variant for consistency after confirming this will not increase the test matrix 2. update only filter for lifecycle coverage and externally launched virtiofsd 3. enable destroy-start for externally launched which needs the source directory 4. remove managedsave file in case test fails to restore 5. add test scenarios shutdown, reboot: use single parameter to distinguish the cases, add function to mount on next boot and confirm written file is present Signed-off-by: Sebastian Mitterle --- .../cfg/virtual_device/filesystem_device.cfg | 23 +-- .../src/virtual_device/filesystem_device.py | 136 +++++++++++++----- 2 files changed, 113 insertions(+), 46 deletions(-) diff --git a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg index 7cc1586765b..fb871dc9039 100644 --- a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg +++ b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg @@ -83,26 +83,36 @@ socket_file_checking = "yes" only xattr_on.cache_mode_auto.thread_pool_noset.sandbox_mode_none..one_fs.one_guest, externally_launched_fs_test - lifecycle: - only xattr_on.cache_mode_auto..one_fs + only xattr_on.cache_mode_auto.thread_pool_noset.sandbox_mode_none..one_fs.one_guest, externally_launched_fs_test..one_fs.one_guest variants: - suspend_resume: - suspend_resume = "yes" + lifecycle_scenario = "suspend_resume" - edit_start: - edit_start = "yes" + only fs_test + lifecycle_scenario = "edit_start" error_msg_start = "qemu-kvm: -foo: invalid option" - destroy_start: only file_backed bug_url = "https://bugzilla.redhat.com/show_bug.cgi?id=1940276" - destroy_start = "yes" + lifecycle_scenario = "destroy_start" stress_script = "#!/usr/bin/python3;import os;while True:; os.open("%s/moo", os.O_CREAT | os.O_RDWR); os.unlink("%s/moo");" + - shutdown_start: + only file_backed + lifecycle_scenario = "shutdown_start" + - reboot: + only file_backed + lifecycle_scenario = "reboot" - restart_service: only file_backed func_supported_since_libvirt_ver = (9, 2, 0) + lifecycle_scenario = "restart_service" setup_mem = True source_dir = "/var/tmp/mount_tag0" dev_type = "filesystem" vm_attrs = {'mb': {"source_type":"file", 'access_mode': 'shared'}} fs_dict = {'accessmode':'passthrough', 'driver': {'type': 'virtiofs', 'queue':'512'}, 'source':{'dir': '${source_dir}'}, "target": {'dir': 'mount_tag0'}, 'binary': {'path': '/usr/libexec/virtiofsd', 'xattr': 'on','cache_mode':'always'}} + - managedsave: + lifecycle_scenario = "managedsave" - coldplug_coldunplug: only xattr_on.cache_mode_auto..one_fs coldplug = "yes" @@ -122,11 +132,6 @@ stdio_handler = "logd" - detach_device: detach_device_alias = "no" - - managedsave: - only xattr_on.cache_mode_auto..one_fs - s390-virtio: - kvm_module_parameters = "hpage=1" - managedsave = "yes" variants: - positive_test: status_error = "no" diff --git a/libvirt/tests/src/virtual_device/filesystem_device.py b/libvirt/tests/src/virtual_device/filesystem_device.py index 6f3f1234ddd..26555bc569b 100644 --- a/libvirt/tests/src/virtual_device/filesystem_device.py +++ b/libvirt/tests/src/virtual_device/filesystem_device.py @@ -165,6 +165,8 @@ def umount_fs(guest_index): vm = vms[guest_index] if vm.is_alive(): session = vm.wait_for_login() + if lifecycle_scenario == "reboot": + session.cmd("sed -i '$d' /etc/fstab", ignore_all_errors=True) for index in fs_indexes: mount_dir = '/var/tmp/' + fs_devs[index].target['dir'] session.cmd('umount -f %s' % mount_dir, ignore_all_errors=True) @@ -250,19 +252,16 @@ def check_filesystem_hotplug_with_mem_setup(): error_msg_save = params.get("error_msg_save", "") status_error = params.get("status_error", "no") == "yes" socket_file_checking = params.get("socket_file_checking", "no") == "yes" - suspend_resume = params.get("suspend_resume", "no") == "yes" - managedsave = params.get("managedsave", "no") == "yes" coldplug = params.get("coldplug", "no") == "yes" hotplug_unplug = params.get("hotplug_unplug", "no") == "yes" detach_device_alias = params.get("detach_device_alias", "no") == "yes" extra_hugepages = params.get_numeric("extra_hugepages") - edit_start = params.get("edit_start", "no") == "yes" + lifecycle_scenario = params.get("lifecycle_scenario", "") with_hugepages = params.get("with_hugepages", "yes") == "yes" with_numa = params.get("with_numa", "yes") == "yes" with_memfd = params.get("with_memfd", "no") == "yes" source_socket = params.get("source_socket", "/var/tmp/vm001.socket") launch_mode = params.get("launch_mode", "auto") - destroy_start = params.get("destroy_start", "no") == "yes" bug_url = params.get("bug_url", "") script_content = params.get("stress_script", "") stdio_handler_file = "file" == params.get("stdio_handler") @@ -273,8 +272,8 @@ def check_filesystem_hotplug_with_mem_setup(): vms = [] vmxml_backups = [] expected_fails_msg = [] - host_hp_size = utils_memory.get_huge_page_size() backup_huge_pages_num = utils_memory.get_num_huge_pages() + host_hp_size = utils_memory.get_huge_page_size() huge_pages_num = 0 if hotplug_unplug and not utils_path.find_command("lsof", default=False): @@ -283,7 +282,7 @@ def check_filesystem_hotplug_with_mem_setup(): if not libvirt_version.version_compare(7, 0, 0) and not with_numa: test.cancel("Not supported without NUMA before 7.0.0") - if not libvirt_version.version_compare(7, 6, 0) and destroy_start: + if not libvirt_version.version_compare(7, 6, 0) and lifecycle_scenario == "destroy_start": test.cancel("Bug %s is not fixed on current build" % bug_url) try: @@ -314,7 +313,7 @@ def _get_fs_dev_and_source_dir(fs_index, socket_index): """ driver = {'type': driver_type, 'queue': queue_size} source_dir = os.path.join('/var/tmp/', str(dir_prefix) + str(fs_index)) - logging.debug(source_dir) + logging.debug(f"This filesystem has source dir: {source_dir}") if not os.path.isdir(source_dir): if not (omit_dir_at_first and fs_index == 0): os.mkdir(source_dir) @@ -391,11 +390,12 @@ def _fs_dev_indexes(guest_index): else: return range(fs_num) - def update_vm_with_fs_devs(guest_index, attach): + def update_vm_with_fs_devs(guest_index, vmxml, attach): """ Either updates the VM XML or attaches the device XML :param guest_index: the index of the guest in vms + :param vmxml: VMXML instance for guest_index :param attach: if True uses `virsh attach` else it redefines the VM """ fs_indexes = _fs_dev_indexes(guest_index) @@ -408,6 +408,7 @@ def update_vm_with_fs_devs(guest_index, attach): for fs_index in fs_indexes: vmxml.add_device(fs_devs[fs_index]) vmxml.sync() + logging.debug(f"VMXML after adding device: {vmxml}") def detach_fs_dev(guest_index): """ @@ -443,10 +444,16 @@ def detach_fs_dev(guest_index): libvirt.check_exit_status(ret, status_error) check_filesystem_in_guest(vm, fs_dev) - create_fs_devs() + def set_up_and_start_vm(guest_index): + """ + Updates the domain xml according to test scenario + and starts it - for index in range(guest_num): - vm = env.get_vm(vm_names[index]) + :param guest_index: the index of the guest to be handled + :return end_of_test: True if test should terminate after VM + can be started + """ + vm = env.get_vm(vm_names[guest_index]) logging.debug("prepare vm %s", vm.name) vms.append(vm) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) @@ -454,6 +461,7 @@ def detach_fs_dev(guest_index): if vmxml.max_mem < 1024000: vmxml.max_mem = 1024000 if with_hugepages: + nonlocal huge_pages_num huge_pages_num += vmxml.max_mem // host_hp_size + extra_hugepages utils_memory.set_num_huge_pages(huge_pages_num) vmxml.remove_all_device_by_type('filesystem') @@ -465,13 +473,12 @@ def detach_fs_dev(guest_index): vm_xml.VMXML.set_memoryBacking_tag(vmxml.vm_name, access_mode="shared", hpgs=with_hugepages, memfd=with_memfd) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) - logging.debug(vmxml) + logging.debug(f"VMXML before adding device: {vmxml}") if coldplug: - update_vm_with_fs_devs(index, attach=True) + update_vm_with_fs_devs(guest_index, vmxml, attach=True) else: if not hotplug_unplug: - update_vm_with_fs_devs(index, attach=False) - logging.debug(vmxml) + update_vm_with_fs_devs(guest_index, vmxml, attach=False) libvirt_pcicontr.reset_pci_num(vm.name) result = virsh.start(vm.name, debug=True) if omit_dir_at_first: @@ -481,20 +488,20 @@ def detach_fs_dev(guest_index): os.mkdir(source_dir) result = virsh.start(vm.name, debug=True) libvirt.check_exit_status(result, not expect_error) - return + return True if hotplug_unplug: if stdio_handler_file: qemu_config = LibvirtQemuConfig() qemu_config.stdio_handler = "file" utils_libvirtd.Libvirtd().restart() - update_vm_with_fs_devs(index, attach=True) + update_vm_with_fs_devs(guest_index, vmxml, attach=True) if status_error: - return + return True if status_error and not lifecycle_scenario == "managedsave": expected_error = error_msg_start utils_test.libvirt.check_exit_status(result, expected_error) - return + return True else: utils_test.libvirt.check_exit_status(result, expect_error=False) if launch_mode == "auto": @@ -502,13 +509,36 @@ def detach_fs_dev(guest_index): cmd = 'ps aux | grep /usr/libexec/virtiofsd' utils_test.libvirt.check_cmd_output(cmd, content=expected_results) + def check_file_exists(vm, filepath): + """ + Confirm that the given file path exists. + It should have been created earlier in the `shared_data` + function + + :param vm: VM instance + :param filepath: the filepath created in the shared directory + :raise TestFail: file not found + """ + session = vm.wait_for_login() + status, output = session.cmd_status_output(f"ls {filepath}") + if status: + test.fail(f"{filepath} not found in the mount: {output}") + + + create_fs_devs() + + for index in range(guest_num): + end_test = set_up_and_start_vm(index) + if end_test: + return shared_data(vm_names, fs_devs) - if suspend_resume: + + if lifecycle_scenario == "suspend_resume": virsh.suspend(vm_names[0], debug=True, ignore_status=False) time.sleep(30) virsh.resume(vm_names[0], debug=True, ignore_statue=False) - elif managedsave: + elif lifecycle_scenario == "managedsave": virsh.managedsave(vm_names[0], ignore_status=True, debug=True) save_file = "/var/lib/libvirt/qemu/save/%s.save" % vm_names[0] if not os.path.exists(save_file): @@ -516,23 +546,54 @@ def detach_fs_dev(guest_index): virsh.start(vm_names[0], ignore_status=True, debug=True) if os.path.exists(save_file): test.fail("guest is not restored from the managedsave file") - elif destroy_start: - session = vm.wait_for_login(timeout=120) - # Prepare the guest test script - script_path = os.path.join(fs_devs[0].source["dir"], "test.py") - script_content %= (fs_devs[0].source["dir"], fs_devs[0].source["dir"]) - prepare_stress_script(script_path, script_content) - # Run guest stress script - stress_script_thread = threading.Thread(target=run_stress_script, + elif lifecycle_scenario in [ + "destroy_start", + "shutdown_start", + "reboot" + ]: + if fs_num > 1 or guest_num > 1: + raise test.error( + "some lifecycle tests are implemented for only 1 guest and" + " filesystem" + ) + session = vms[0].wait_for_login(timeout=120) + session.cmd_status_output( + "echo 'mount_tag0 /var/tmp/mount_tag0 " + "virtiofs defaults 0 0' >> /etc/fstab" + ) + if lifecycle_scenario == "destroy_start": + # Prepare the guest test script + _, source_dir = _get_fs_dev_and_source_dir(0, 0) + script_path = os.path.join(source_dir, "test.py") + script_content %= (source_dir, source_dir) + prepare_stress_script(script_path, script_content) + # Run guest stress script + stress_script_thread = threading.Thread(target=run_stress_script, args=(session, script_path)) - stress_script_thread.setDaemon(True) - stress_script_thread.start() - # Create a lot of unlink files - time.sleep(60) - virsh.destroy(vm_names[0], debug=True, ignore_status=False) - ret = virsh.start(vm_names[0], debug=True) - libvirt.check_exit_status(ret) - elif edit_start: + stress_script_thread.setDaemon(True) + stress_script_thread.start() + # Creates a lot of unlink files + time.sleep(60) + virsh.destroy(vm_names[0], debug=True, ignore_status=False) + ret = virsh.start(vm_names[0], debug=True) + libvirt.check_exit_status(ret) + elif lifecycle_scenario == "shutdown_start": + virsh.shutdown( + vm_names[0], + debug=True, + ignore_status=False + ) + utils_misc.wait_for(vms[0].is_dead, timeout=60) + ret = virsh.start(vm_names[0], debug=True) + libvirt.check_exit_status(ret) + elif lifecycle_scenario == "reboot": + ret = virsh.reboot(vm_names[0], debug=True, ignore_status=False) + libvirt.check_exit_status(ret) + else: + test.fail("Test case not implemented.") + if lifecycle_scenario: + check_file_exists(vms[0], "/var/tmp/mount_tag0/" + vm_names[0]) + elif lifecycle_scenario == "edit_start": vmxml_virtio_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_names[0]) if vm.is_alive(): virsh.destroy(vm_names[0]) @@ -580,6 +641,7 @@ def detach_fs_dev(guest_index): if vm.is_alive(): umount_fs(index) vm.destroy(gracefully=False) + virsh.managedsave_remove(vm.name, debug=True, ignore_status=True) vmxml_backups[index].sync() utils_memory.set_num_huge_pages(backup_huge_pages_num) if stdio_handler_file: From 756b2be1a4c8c9b8d9774572af010dde070de2de Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Sun, 6 Apr 2025 12:46:05 +0800 Subject: [PATCH 0909/1055] numa_config_with_auto_placement: fix iothreadinfo check Existing cpu affinity checking for iothreadinfo command is using host numa node id instead of iothreadid. This is incorrect. Like below, we should use iothread id instead numa node id. virsh iothreadinfo yal --config IOThread ID CPU Affinity --------------------------------------------------- 1 0-23 2 0-23 Signed-off-by: Dan Zheng --- .../numa/numa_config_with_auto_placement.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/src/numa/numa_config_with_auto_placement.py b/libvirt/tests/src/numa/numa_config_with_auto_placement.py index 2e1363e8571..9da82f6f66d 100644 --- a/libvirt/tests/src/numa/numa_config_with_auto_placement.py +++ b/libvirt/tests/src/numa/numa_config_with_auto_placement.py @@ -159,21 +159,25 @@ def check_iothreadinfo(vm_name, cpu_range, config=''): :param cpu_range: range of CPUs available as a string :param config: config parameter as a string, empty by default """ - numa_info = utils_misc.NumaInfo() result = virsh.iothreadinfo(vm_name, options=config, debug=True, ignore_status=False) range_found = False - for node in numa_info.get_online_nodes_withcpu(): - if re.search('{}\s*{}'.format(node, cpu_range), + live_vmxml = libvirt_xml.VMXML.new_from_dumpxml(vm_name) + iothreadid_list = live_vmxml.iothreadids.iothread + for one_iothread in iothreadid_list: + iothread_attrs = one_iothread.fetch_attrs() + iothread_id = iothread_attrs['id'] + if re.search('{}\s*{}'.format(iothread_id, cpu_range), result.stdout_text): logging.debug( - 'Expected cpu range: {} found in stdout for ' - 'node: {}.'.format(cpu_range, node)) + 'Expected cpu affinity: {} found in stdout for ' + 'iothread: {}.'.format(cpu_range, iothread_id)) range_found = True else: - logging.debug('Node {} has no cpu range'.format(node)) + logging.debug('Iothread {} has no cpu affinity'.format(iothread_id)) + if not range_found: - raise TestFail('Expected cpu range: {} not found in stdout of ' + raise TestFail('Expected cpu affinity: {} not found in stdout of ' 'iothreadinfo command.'.format(cpu_range)) From 694928099b42371a1854b71997a81861cdfb620e Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Sun, 6 Apr 2025 16:08:34 +0800 Subject: [PATCH 0910/1055] aarch64_cpu_sve: extend timeout The make check tests need more time, so this case needs bigger timeout Signed-off-by: Dan Zheng --- libvirt/tests/src/cpu/aarch64_cpu_sve.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/cpu/aarch64_cpu_sve.py b/libvirt/tests/src/cpu/aarch64_cpu_sve.py index 51fcb68ef72..d2ffc4f9feb 100644 --- a/libvirt/tests/src/cpu/aarch64_cpu_sve.py +++ b/libvirt/tests/src/cpu/aarch64_cpu_sve.py @@ -249,7 +249,7 @@ def update_cpu_xml(cpu_xml, params, test, supported_list, unsupported_list): logging.debug("cpu_xml is %s" % cpu_xml) -def execute_cmds(cmd, session, test, timeout=360, ignore_status=False): +def execute_cmds(cmd, session, test, timeout=720, ignore_status=False): """ Execute a command with vm session From 5726e7a433cdf17e4ca7155661865c9c319ce4de Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Sun, 6 Apr 2025 10:09:06 +0800 Subject: [PATCH 0911/1055] various_numa_topology_settings:add necessary check Signed-off-by: Dan Zheng --- .../numa_mem_binding_with_offline_cpu.py | 4 ++++ .../guest_numa_topology/change_vcpu_pin.py | 7 +++--- .../various_numa_topology_settings.py | 3 ++- .../src/numa/host_numa/host_numa_info.py | 23 ++++++++++--------- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/numa_mem_binding_with_offline_cpu.py b/libvirt/tests/src/numa/guest_numa_node_tuning/numa_mem_binding_with_offline_cpu.py index 6d3c067422a..a8989b4ca63 100644 --- a/libvirt/tests/src/numa/guest_numa_node_tuning/numa_mem_binding_with_offline_cpu.py +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/numa_mem_binding_with_offline_cpu.py @@ -44,6 +44,10 @@ def setup_test(): online_nodes = numa_info.get_online_nodes_withmem() test.log.debug("Get online node with memory:%s", online_nodes) + if online_nodes < 2: + test.cancel("Expect %d numa nodes at " + "least, but found %d" % (2, + online_nodes)) node_cpus = numa_info.get_all_node_cpus()[ online_nodes[offline_node_index]].strip().split(' ') diff --git a/libvirt/tests/src/numa/guest_numa_topology/change_vcpu_pin.py b/libvirt/tests/src/numa/guest_numa_topology/change_vcpu_pin.py index a6f66cdcf31..46f674cce9e 100644 --- a/libvirt/tests/src/numa/guest_numa_topology/change_vcpu_pin.py +++ b/libvirt/tests/src/numa/guest_numa_topology/change_vcpu_pin.py @@ -174,9 +174,10 @@ def teardown_default(test_obj): :param test_obj: NumaTest object """ test_obj.teardown() - backup_numad_status = test_obj.params['backup_numad_status'] - libvirt_service.ensure_service_status('numad', - expect_active=backup_numad_status) + backup_numad_status = test_obj.params.get("backup_numad_status") + if backup_numad_status: + libvirt_service.ensure_service_status('numad', + expect_active=backup_numad_status) test_obj.test.log.info("Step: teardown is done") diff --git a/libvirt/tests/src/numa/guest_numa_topology/various_numa_topology_settings.py b/libvirt/tests/src/numa/guest_numa_topology/various_numa_topology_settings.py index c4668527644..b6510c17225 100644 --- a/libvirt/tests/src/numa/guest_numa_topology/various_numa_topology_settings.py +++ b/libvirt/tests/src/numa/guest_numa_topology/various_numa_topology_settings.py @@ -172,7 +172,8 @@ def teardown_default(test_obj): """ test_obj.teardown() hpc = test_obj.params.get('hp_config_obj') - hpc.cleanup() + if hpc: + hpc.cleanup() test_obj.test.log.debug("Step: teardown is done") diff --git a/libvirt/tests/src/numa/host_numa/host_numa_info.py b/libvirt/tests/src/numa/host_numa/host_numa_info.py index 44694e17cd8..c1ee2c0e9ad 100644 --- a/libvirt/tests/src/numa/host_numa/host_numa_info.py +++ b/libvirt/tests/src/numa/host_numa/host_numa_info.py @@ -197,17 +197,18 @@ def verify_node_mem_by_freepages_all(test_obj): page_info = all_freepages[node] for pgsize, pgnum in page_info.items(): test_obj.test.log.debug("node %d, pgsize %d, pgnum %d", node, pgsize, pgnum) - if allocate_result[node].get(pgsize) is not None and pgnum != allocate_result[node][pgsize]: - test_obj.test.fail("Expect freepages " - "result has '%d' pages " - "for size '%d' on node %d, but " - "found '%d'" % (allocate_result[node][pgsize], - pgsize, node, pgnum)) - elif allocate_result[node].get(pgsize) is None and pgnum != 0: - test_obj.test.fail("Expect freepages " - "result has 0 page " - "for size '%d' on node %d, but " - "found '%d'" % (pgsize, node, pgnum)) + if allocate_result.get(node): + if allocate_result[node].get(pgsize) is not None and pgnum != allocate_result[node][pgsize]: + test_obj.test.fail("Expect freepages " + "result has '%d' pages " + "for size '%d' on node %d, but " + "found '%d'" % (allocate_result[node][pgsize], + pgsize, node, pgnum)) + elif allocate_result[node].get(pgsize) is None and pgnum != 0: + test_obj.test.fail("Expect freepages " + "result has 0 page " + "for size '%d' on node %d, but " + "found '%d'" % (pgsize, node, pgnum)) test_obj.test.log.debug("Verify node memory by freepages with --all - PASS") From 74af985384e78aaa59312c5c30f065581a42428e Mon Sep 17 00:00:00 2001 From: lcheng Date: Mon, 24 Mar 2025 11:39:21 +0800 Subject: [PATCH 0912/1055] migration: Add case about shared_filesystems XXX-304029 - Migrate the guests with various tpm and firmware on canonical paths in shared_filesystems Signed-off-by: lcheng --- .../canonical_paths_in_shared_filesystems.cfg | 67 ++++++ .../canonical_paths_in_shared_filesystems.py | 206 ++++++++++++++++++ 2 files changed, 273 insertions(+) create mode 100644 libvirt/tests/cfg/migration/migration_misc/canonical_paths_in_shared_filesystems.cfg create mode 100644 libvirt/tests/src/migration/migration_misc/canonical_paths_in_shared_filesystems.py diff --git a/libvirt/tests/cfg/migration/migration_misc/canonical_paths_in_shared_filesystems.cfg b/libvirt/tests/cfg/migration/migration_misc/canonical_paths_in_shared_filesystems.cfg new file mode 100644 index 00000000000..e5a7458e34a --- /dev/null +++ b/libvirt/tests/cfg/migration/migration_misc/canonical_paths_in_shared_filesystems.cfg @@ -0,0 +1,67 @@ +- migration.migration_misc.canonical_paths_in_shared_filesystems: + type = canonical_paths_in_shared_filesystems + migration_setup = 'yes' + storage_type = '' + setup_nfs = 'no' + setup_local_nfs = 'no' + disk_type = "file" + disk_source_protocol = "netfs" + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + vms = avocado-vt-vm1 vm2 + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + status_error = "no" + migrate_desturi_port = "22" + migrate_desturi_type = "ssh" + virsh_migrate_desturi = "qemu+ssh://${migrate_dest_host}/system" + start_vm = "no" + nfs_mount_options = "bind" + export_dir = "/nfs" + nfs_server_ip = "${migrate_source_host}" + images_path = "/var/lib/libvirt/images" + nvram_path = "/var/lib/libvirt/qemu/nvram" + swtpm_path = "/var/lib/libvirt/swtpm" + nfs_mount_dir = "${images_path}" + mnt_path_name = "${images_path}" + nfs_images_path = "${export_dir}/libvirt/images" + nfs_nvram_path = "${export_dir}/libvirt/nvram" + nfs_swtpm_path = "${export_dir}/libvirt/swtpm" + mount_images_path = "${nfs_server_ip}:${export_dir}/libvirt/images" + mount_nvram_path = "${nfs_server_ip}:${export_dir}/libvirt/nvram" + mount_swtpm_path = "${nfs_server_ip}:${export_dir}/libvirt/swtpm" + qemu_conf_dest = '{r".*shared_filesystems\s*=.*": "shared_filesystems = [\"${images_path}\", \"${nvram_path}\", \"${swtpm_path}\"]"}' + qemu_conf_src = '{"shared_filesystems": "[\"${images_path}\", \"${nvram_path}\", \"${swtpm_path}\"]"}' + migrate_vm_back = "yes" + variants: + - with_tpm: + tpm_args = "{"tpm_model": "tpm-crb", "backend_type": "emulator", "backend_version": "2.0"}" + - without_tpm: + variants boot_type: + - bios: + firmware_type = "seabios" + os_dict = {'type': 'hvm', 'boots': ['hd'], 'machine': 'q35'} + - statless_uefi: + firmware_type = "ovmf" + loader_path = "/usr/share/edk2/ovmf/OVMF.amdsev.fd" + loader_dict = {'os_firmware': 'efi', 'loader_stateless': 'yes', 'loader': '${loader_path}', 'loader_type': 'rom'} + - uefi_with_nvram: + firmware_type = "ovmf" + loader_path = "/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd" + nvram_fd_path = "/var/lib/libvirt/qemu/nvram/avocado-vt-vm1_VARS.fd" + nvram_template = "/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd" + loader_dict = {'loader': '${loader_path}', 'nvram': '${nvram_fd_path}', 'nvram_attrs': {'template': '${nvram_template}'}, 'secure': 'yes', 'loader_readonly': 'yes', 'loader_type': 'pflash'} diff --git a/libvirt/tests/src/migration/migration_misc/canonical_paths_in_shared_filesystems.py b/libvirt/tests/src/migration/migration_misc/canonical_paths_in_shared_filesystems.py new file mode 100644 index 00000000000..e556abaa2d7 --- /dev/null +++ b/libvirt/tests/src/migration/migration_misc/canonical_paths_in_shared_filesystems.py @@ -0,0 +1,206 @@ +import os + +from avocado.utils import process + +from virttest import libvirt_remote +from virttest import remote +from virttest import utils_config +from virttest import utils_disk +from virttest import utils_misc +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_bios +from virttest.utils_test import libvirt + +from provider.guest_os_booting import guest_os_booting_base as guest_os +from provider.migration import base_steps + + +def setup_for_shared_filesystems(params, test): + """ + Setup for shared filesystems + + :param params: dict, test parameters + :param test: test object + """ + export_dir = params.get("export_dir") + nfs_server_ip = params.get("nfs_server_ip") + nfs_images_path = params.get("nfs_images_path") + nfs_nvram_path = params.get("nfs_nvram_path") + nfs_swtpm_path = params.get("nfs_swtpm_path") + images_path = params.get("images_path") + nvram_path = params.get("nvram_path") + swtpm_path = params.get("swtpm_path") + nfs_mount_options = params.get("nfs_mount_options") + server_ip = params.get("server_ip") + server_user = params.get("server_user", "root") + server_pwd = params.get("server_pwd") + mount_images_path = params.get("mount_images_path") + mount_nvram_path = params.get("mount_nvram_path") + mount_swtpm_path = params.get("mount_swtpm_path") + + if not os.path.exists(export_dir): + os.mkdir(export_dir) + + mount_opt = "rw,no_root_squash,sync" + res = libvirt.setup_or_cleanup_nfs(is_setup=True, + is_mount=False, + export_options=mount_opt, + export_dir=export_dir) + + for path in [nfs_images_path, nfs_nvram_path, nfs_swtpm_path]: + if not utils_misc.check_exists(path): + process.run(f"mkdir -p {path}", shell=True, verbose=True) + + utils_disk.mount(nfs_images_path, images_path, options=nfs_mount_options) + utils_disk.mount(nfs_nvram_path, nvram_path, options=nfs_mount_options) + utils_disk.mount(nfs_swtpm_path, swtpm_path, options=nfs_mount_options) + + remote_session = remote.wait_for_login("ssh", server_ip, "22", server_user, server_pwd, r"[\#\$]\s*$") + utils_disk.mount(mount_images_path, images_path, session=remote_session) + utils_disk.mount(mount_nvram_path, nvram_path, session=remote_session) + utils_disk.mount(mount_swtpm_path, swtpm_path, session=remote_session) + remote_session.close() + + remote_obj = None + local_obj = None + qemu_conf_src = eval(params.get("qemu_conf_src", "{}")) + qemu_conf_dest = params.get("qemu_conf_dest", "{}") + qemu_conf_path = utils_config.LibvirtQemuConfig().conf_path + remote_obj = libvirt_remote.update_remote_file(params, qemu_conf_dest, qemu_conf_path) + local_obj = libvirt.customize_libvirt_config(qemu_conf_src, "qemu", remote_host=False, + extra_params=params) + return (local_obj, remote_obj) + + +def cleanup_for_shared_filesystems(params, test): + """ + Cleanup for shared filesystems + + :param params: dict, test parameters + :param test: test object + """ + images_path = params.get("images_path") + nvram_path = params.get("nvram_path") + swtpm_path = params.get("swtpm_path") + server_ip = params.get("server_ip") + server_user = params.get("server_user", "root") + server_pwd = params.get("server_pwd") + export_dir = params.get("export_dir") + mount_images_path = params.get("mount_images_path") + mount_nvram_path = params.get("mount_nvram_path") + mount_swtpm_path = params.get("mount_swtpm_path") + + test.log.info("Cleanup for shared_filesystems.") + remote_session = remote.wait_for_login("ssh", server_ip, "22", server_user, server_pwd, r"[\#\$]\s*$") + utils_disk.umount(mount_images_path, images_path, session=remote_session) + utils_disk.umount(mount_nvram_path, nvram_path, session=remote_session) + utils_disk.umount(mount_swtpm_path, swtpm_path, session=remote_session) + remote_session.close() + + for path in [images_path, nvram_path, swtpm_path]: + process.run(f"umount {path}", shell=True, verbose=True) + + libvirt.setup_or_cleanup_nfs(is_setup=False) + process.run(f"rm -rf {export_dir}", shell=True, ignore_status=True) + + +def run(test, params, env): + """ + Migrate the guests with various tpm and firmware on canonical paths in shared_filesystems. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def setup_test(): + """ + Setup steps for cases + + """ + images_path = params.get("images_path") + tpm_args = eval(params.get("tpm_args", '{}')) + loader_dict = eval(params.get("loader_dict", "{}")) + + test.log.info("Setup steps for cases.") + + nonlocal local_qemu_obj + nonlocal remote_qemu_obj + local_qemu_obj, remote_qemu_obj = setup_for_shared_filesystems(params, test) + + blk_source = vm.get_first_disk_devices()['source'] + process.run(f"cp {blk_source} {images_path}", shell=True, verbose=True) + process.run("setsebool virt_use_nfs 1", shell=True, verbose=True) + remote.run_remote_cmd("setsebool virt_use_nfs 1", params) + + vmxml.remove_all_device_by_type('tpm') + if tpm_args: + tpm_dev = libvirt.create_tpm_dev(tpm_args) + vmxml.add_device(tpm_dev) + vmxml.sync() + + if boot_type == "bios": + os_dict = eval(params.get("os_dict")) + vmxml.del_os() + vmxml.setup_attrs(os=os_dict) + elif boot_type == "statless_uefi": + vmxml.os = libvirt_bios.remove_bootconfig_items_from_vmos(vmxml.os) + vmxml.setup_attrs(os=loader_dict) + else: + vmxml.setup_attrs(os=loader_dict) + vmxml.sync() + virsh.dumpxml(vm_name, debug=True) + migration_obj.setup_connection() + vm.start() + vm.wait_for_login().close() + + def verify_test_again(): + """ + Verify test again + + """ + test.log.info("Verify test again.") + dargs = {"check_disk_on_dest": "no"} + migration_obj.migration_test.post_migration_check([vm], dargs) + + def cleanup_test(): + """ + Cleanup steps for cases + """ + test.log.info("Cleanup steps for cases.") + migration_obj.cleanup_connection() + cleanup_for_shared_filesystems(params, test) + process.run("rm -rf /var/lib/libvirt/swtpm/*", shell=True, ignore_status=True) + process.run("rm -rf /var/lib/libvirt/qemu/nvram/*", shell=True, ignore_status=True) + nonlocal local_qemu_obj + if local_qemu_obj: + libvirt.customize_libvirt_config(None, config_type="qemu", remote_host=False, + is_recover=True, extra_params=params, + config_object=local_qemu_obj) + nonlocal remote_qemu_obj + if remote_qemu_obj: + del remote_qemu_obj + + vm_name = guest_os.get_vm(params) + boot_type = params.get("boot_type") + params.update({"main_vm": vm_name}) + local_qemu_obj = None + remote_qemu_obj = None + + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + if boot_type == "bios": + bkxml = vmxml.copy() + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + setup_test() + migration_obj.run_migration() + migration_obj.verify_default() + migration_obj.run_migration_back() + verify_test_again() + finally: + cleanup_test() + if boot_type == "bios": + bkxml.sync() From a54beecb216c6b2ce3bd22a6ce500a9575b3c8cf Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Sun, 6 Oct 2024 08:49:03 -0400 Subject: [PATCH 0913/1055] Automate Check the disk-change events for cdrom and disk when startuppolicy is set to optional, and no cdrom:pass-through log when using block type cdrom xx-38693 - [disk-change]Check the disk-change events when startuppolicy is optional xx-112414 - start a guest with block type cdrom --bz1471225 xx-32763 - [audit log] Audit log related to guest CDROM Signed-off-by: chunfuwen --- .../virtual_disks_cdrom_device.cfg | 23 +++ .../virtual_disks_cdrom_device.py | 140 +++++++++++++++++- 2 files changed, 162 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_cdrom_device.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_cdrom_device.cfg index 9a449da44f6..0b8ff6d41a5 100755 --- a/libvirt/tests/cfg/virtual_disks/virtual_disks_cdrom_device.cfg +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_cdrom_device.cfg @@ -129,6 +129,29 @@ target_dev = "sdd" backend_device = "empty_source_cdrom_backend" only hotplug..positive_test + - dropped_changed_events_startuppolicy: + type_name = "file" + target_format = "raw" + virt_disk_device_source_second = "/var/lib/libvirt/images/none.qcow2" + virt_disk_device_source = "/var/lib/libvirt/images/none" + target_dev = "sdc" + startupPolicy="optional" + backend_device = "dropped_changed_events_startuppolicy" + only coldplug..positive_test + - block_cdrom_tainted: + only coldplug..positive_test + target_format = "raw" + type_name = "block" + target_dev = "sdb" + virt_disk_device_source = "/dev/sdb" + backend_device = "block_cdrom_tainted" + - disconnect_audit_cdrom_backend: + type_name = "file" + target_format = "raw" + virt_disk_device_source = "/var/lib/libvirt/images/disconnect.iso" + target_dev = "sdb" + backend_device = "disconnect_audit_cdrom_backend" + only coldplug..positive_test variants: - hotplug: virt_device_hotplug = "yes" diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_cdrom_device.py b/libvirt/tests/src/virtual_disks/virtual_disks_cdrom_device.py index 87d5b77ef0b..862a9251b49 100755 --- a/libvirt/tests/src/virtual_disks/virtual_disks_cdrom_device.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_cdrom_device.py @@ -8,17 +8,23 @@ from avocado.utils import linux_modules from avocado.utils import process +from avocado.utils import service from virttest import libvirt_version from virttest import virt_vm, utils_misc from virttest import virsh from virttest import utils_split_daemons +from virttest import utils_libvirtd from virttest.libvirt_xml import vm_xml, xcepts from virttest.utils_test import libvirt from virttest.utils_libvirt import libvirt_disk +from virttest.utils_config import LibvirtdConfig +from virttest.utils_config import VirtQemudConfig + + LOG = logging.getLogger('avocado.' + __name__) CLEANUP_FILES = [] @@ -512,6 +518,113 @@ def check_empty_source_cdrom(vm, params, test): check_source_in_cdrom_device(vm, None, test) +def check_dropped_changed_events_startuppolicy_backend(vm, params, virsh_session, test): + """ + Check changed event for cdrom, and dropped event for disk + + :param vm: one object representing VM + :param params: wrapped parameters in dictionary format + :param virsh_session: virsh session + :param test: test assert object + """ + # check tray-change event + virsh_session.send_ctrl("^C") + ret_output = virsh_session.get_stripped_output().replace("\n", "").strip() + LOG.debug("dropped and changed events:\n%s", ret_output) + event_keywords = ["changed", "dropped"] + + for keyword in event_keywords: + event_pattern = r"event 'disk-change' for domain '%s' disk .*%s" % (vm.name, keyword) + if not re.search(event_pattern, ret_output): + test.fail("Can not find matched event: %s from event output: %s" % (event_pattern, ret_output)) + + +def create_block_cdrom_disk(params): + """ + + Create one block cdrom device + :param params: dict wrapped with parameter + """ + source_disk = libvirt.create_scsi_disk(scsi_option="", + scsi_size="100") + params.update({'virt_disk_device_source': source_disk}) + + block_cdrom_disk = create_customized_disk(params) + return block_cdrom_disk + + +def check_block_cdrom_log(vm, params, test): + """ + Check matched information in vm.log + + :param vm: one object representing VM + :param params: wrapped parameters in dictionary format + :param test: test assert object + """ + qemu_log = "/var/log/libvirt/qemu/%s.log" % vm.name + libvirt.check_logfile(" tainted: cdrom-passthrough", qemu_log, str_in_log=False) + + +def create_disconnect_audit_cdrom(params): + """ + + Create one file cdrom device + :param params: dict wrapped with parameter + """ + libvirtd_config = VirtQemudConfig() if utils_split_daemons.is_modular_daemon() else LibvirtdConfig() + libvirtd_config.audit_level = 1 + libvirtd_config.audit_logging = 1 + utils_libvirtd.Libvirtd('virtqemud').restart() + + # Clean up audit message in log file + cmd = "truncate -s 0 /var/log/audit/audit.log*" + process.run(cmd, shell=True) + + # ensure audit service is started + service_name = 'auditd' + service_mgr = service.ServiceManager() + status = service_mgr.status(service_name) + LOG.debug('Service status is %s', status) + + if not status: + service_mgr.start(service_name) + + block_cdrom_disk = create_iso_cdrom_disk(params) + return block_cdrom_disk + + +def check_disconnect_audit_cdrom(params, test): + """ + + check audit log when cdrom is disconnected + :param params: dict wrapped with parameter + :param test: test assert object + """ + source_file_path = params.get("virt_disk_device_source") + if os.path.exists(source_file_path): + os.remove(source_file_path) + + def _check_disk_message_from_audit_log(): + """ + Check whether disk related message in /var/log/audit/audit.log + """ + cmd = 'ausearch --start today -m VIRT_RESOURCE -i | grep update' + return process.system(cmd, ignore_status=True, shell=True) + + result = utils_misc.wait_for(lambda: _check_disk_message_from_audit_log(), timeout=30) + if not result: + test.fail("Failed to get expected messages: virt resource update from log file: /var/log/audit/audit.log.") + + +def restore_libvirtd_config(): + """ + restore to previous libvirtd config + """ + libvirtd_config = VirtQemudConfig() if utils_split_daemons.is_modular_daemon() else LibvirtdConfig() + libvirtd_config.restore() + utils_libvirtd.Libvirtd('virtqemud').restart() + + def run(test, params, env): """ Test attach cdrom device with option. @@ -579,6 +692,23 @@ def run(test, params, env): if backend_device == "empty_source_cdrom_backend": device_obj = create_customized_disk(params) params.update({'cdrom_xml': device_obj}) + if backend_device == "dropped_changed_events_startuppolicy": + # First create cdrom disk, then create one more file disk + device_obj1 = create_customized_disk(params) + vmxml.add_device(device_obj1) + vmxml.sync() + params.update({'virt_disk_device_source': params.get("virt_disk_device_source_second")}) + params.update({'target_dev': "sdd"}) + params.update({'device_type': 'disk'}) + device_obj = create_customized_disk(params) + # start loop to wait for disk change event + virsh_session = aexpect.ShellSession(virsh.VIRSH_EXEC, auto_close=True) + event_cmd = "event --domain %s --event disk-change --loop" % vm.name + virsh_session.sendline(event_cmd) + if backend_device == "block_cdrom_tainted": + device_obj = create_block_cdrom_disk(params) + if backend_device == "disconnect_audit_cdrom_backend": + device_obj = create_disconnect_audit_cdrom(params) if not hotplug: # Sync VM xml. vmxml.add_device(device_obj) @@ -638,6 +768,12 @@ def run(test, params, env): check_scsi_cdrom_hot_eject(vm, params, test) elif backend_device == "empty_source_cdrom_backend": check_empty_source_cdrom(vm, params, test) + elif backend_device == "dropped_changed_events_startuppolicy": + check_dropped_changed_events_startuppolicy_backend(vm, params, virsh_session, test) + elif backend_device == "block_cdrom_tainted": + check_block_cdrom_log(vm, params, test) + elif backend_device == "disconnect_audit_cdrom_backend": + check_disconnect_audit_cdrom(params, test) finally: # Recover VM. if vm.is_alive(): @@ -648,11 +784,13 @@ def run(test, params, env): for file_path in CLEANUP_FILES: if os.path.exists(file_path): os.remove(file_path) - if backend_device == "change_startuppolicy_cdrom_backend": + if backend_device in ["change_startuppolicy_cdrom_backend", "block_cdrom_tainted"]: # unload scsi_debug module if loaded def _unload(): linux_modules.unload_module("scsi_debug") return True utils_misc.wait_for(_unload, timeout=20, ignore_errors=True) + if backend_device in ["disconnect_audit_cdrom_backend"]: + restore_libvirtd_config() if backend_device == "block_lun_source": process.run("losetup -D", shell=True) From 16adcb67ede19a69c20796ec6072fb22a50c668b Mon Sep 17 00:00:00 2001 From: chunfuwen Date: Sun, 6 Oct 2024 08:15:37 -0400 Subject: [PATCH 0914/1055] Automate Resize a block size to a value that's not a multiple of 1024 xxx-62472 - Resize a block size to a value that's not a multiple of 1024,it need align with multiple of 1024 Signed-off-by: chunfuwen --- .../virtual_disks_blockresize.cfg | 6 ++++++ .../virtual_disks_blockresize.py | 21 ++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_blockresize.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_blockresize.cfg index ea6d3974279..03e7b99055a 100755 --- a/libvirt/tests/cfg/virtual_disks/virtual_disks_blockresize.cfg +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_blockresize.cfg @@ -42,6 +42,12 @@ status_error = "yes" resize_value = "--capacity" status_error_msg = "Operation not supported: block resize to full capacity supported only with.*raw.*local block-based disks" + - not_align_with_multiple_1024: + only coldplug..virtio + resize_value = "1025000B" + source_raw_file_path = "/var/lib/libvirt/images/align_large.raw" + type_name = "file" + actual_resize_value = "1025024" variants target_bus: - virtio: - sata: diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_blockresize.py b/libvirt/tests/src/virtual_disks/virtual_disks_blockresize.py index e7380dd73b9..e912954266b 100644 --- a/libvirt/tests/src/virtual_disks/virtual_disks_blockresize.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_blockresize.py @@ -65,7 +65,14 @@ def create_customized_disk(params, test): device_target = params.get("target_dev") device_bus = params.get("target_bus") device_format = params.get("target_format") - source_file_path = setup_scsi_debug_block_device() + source_file_path = None + source_raw_file_path = params.get("source_raw_file_path") + if source_raw_file_path: + libvirt.create_local_disk("file", source_raw_file_path, "1M", device_format) + cleanup_files.append(source_raw_file_path) + source_file_path = source_raw_file_path + else: + source_file_path = setup_scsi_debug_block_device() overlay_source_file_path = params.get("overlay_source_file_path") expected_size = params.get("block_size_in_bytes") source_dict = {} @@ -73,7 +80,9 @@ def create_customized_disk(params, test): # check block size check_image_virtual_size(source_file_path, expected_size, test) - if source_file_path: + if source_raw_file_path: + source_dict.update({"file": source_file_path}) + else: source_dict.update({"dev": source_file_path}) if overlay_source_file_path: @@ -180,6 +189,8 @@ def run(test, params, env): target_bus = params.get("target_bus") target_dev = params.get('target_dev') status_error = "yes" == params.get("status_error") + type_name = params.get("type_name") + source_raw_file_path = params.get("source_raw_file_path") try: device_obj = create_customized_disk(params, test) if not hotplug: @@ -216,6 +227,9 @@ def run(test, params, env): result = virsh.blockresize(vm_name, target_dev, resize_value, **virsh_dargs) libvirt.check_exit_status(result, status_error) + if test_scenario in ["not_align_with_multiple_1024"]: + actual_expectd_size = params.get("actual_resize_value") + check_image_virtual_size(source_raw_file_path, actual_expectd_size, test) if not status_error: check_vm_dumpxml(params, test, False) @@ -228,7 +242,8 @@ def run(test, params, env): if vm.is_alive(): vm.destroy(gracefully=False) vmxml_backup.sync() - libvirt.delete_scsi_disk() + if type_name in ["block"]: + libvirt.delete_scsi_disk() for file_path in cleanup_files: if os.path.exists(file_path): os.remove(file_path) From 6ca5c330dfab2049b86b2ccedd76e19b12408e09 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 7 Apr 2025 03:14:45 -0400 Subject: [PATCH 0915/1055] Enable kvm-no-adjvtime on aarch64 to avoid time adjustment after migration --- libvirt/tests/cfg/migration/migrate_options_shared.cfg | 2 ++ libvirt/tests/src/migration/migrate_options_shared.py | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/libvirt/tests/cfg/migration/migrate_options_shared.cfg b/libvirt/tests/cfg/migration/migrate_options_shared.cfg index 156a62e3f0e..44ce5234de8 100644 --- a/libvirt/tests/cfg/migration/migrate_options_shared.cfg +++ b/libvirt/tests/cfg/migration/migrate_options_shared.cfg @@ -494,6 +494,8 @@ cmd_in_vm_after_migration = "tpm2_getrandom 10" - timer: no s390-virtio + aarch64: + armvtimer = {"clock": {"offset": "utc", "timers": [{"name": "armvtimer", "tickpolicy": "discard"}]}} timer_migration = "yes" asynch_migrate = "yes" actions_during_migration = "setmaxdowntime" diff --git a/libvirt/tests/src/migration/migrate_options_shared.py b/libvirt/tests/src/migration/migrate_options_shared.py index 02202456c12..6a0bc83b85c 100644 --- a/libvirt/tests/src/migration/migrate_options_shared.py +++ b/libvirt/tests/src/migration/migrate_options_shared.py @@ -1057,6 +1057,7 @@ def cancel_bg_migration(): low_speed = params.get("low_speed", None) migrate_vm_back = "yes" == params.get("migrate_vm_back", "no") timer_migration = "yes" == params.get("timer_migration", "no") + armvtimer = eval(params.get("armvtimer", "{}")) concurrent_migration = "yes" == params.get("concurrent_migration", "no") remote_virsh_dargs = {'remote_ip': server_ip, 'remote_user': server_user, @@ -1277,6 +1278,10 @@ def cancel_bg_migration(): .format(loc)) remote_session.close() + if timer_migration and armvtimer: + new_xml.setup_attrs(**armvtimer) + new_xml.sync() + # Change the disk of the vm to shared disk and then start VM libvirt.set_vm_disk(vm, params) From a31e2c2cd3d7a1ad41c3a7164566ab1db2e3b1f3 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 7 Apr 2025 05:55:49 -0400 Subject: [PATCH 0916/1055] Increase memory balloon size to avoid guest crash for short of memory Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/migration/migrate_mem.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration/migrate_mem.cfg b/libvirt/tests/cfg/migration/migrate_mem.cfg index 866553f38c8..5668ce06c19 100644 --- a/libvirt/tests/cfg/migration/migrate_mem.cfg +++ b/libvirt/tests/cfg/migration/migrate_mem.cfg @@ -53,7 +53,7 @@ check_str_local_log = 'Unsupported migration cookie feature memory-hotplug' str_in_log = False - mem_balloon: - ballooned_mem = "716800" + ballooned_mem = "1572864" - mem_nvdimm: no s390-virtio nvdimm_file_path = '${nfs_mount_dir}/nvdimm' From f5683b26e988a18ee219e50020587dcf0f854afb Mon Sep 17 00:00:00 2001 From: nanli Date: Tue, 8 Apr 2025 09:58:01 +0800 Subject: [PATCH 0917/1055] cpu: add case for starting guest with new hyperv enlightments xxxx-304144:Start a guest with emsr_bitmap, xmm_input, tlbflush-direct and tlbflush-ext Signed-off-by: nanli --- libvirt/tests/cfg/cpu/vm_features.cfg | 18 ++++++++++++++++++ libvirt/tests/src/cpu/vm_features.py | 5 +++++ 2 files changed, 23 insertions(+) diff --git a/libvirt/tests/cfg/cpu/vm_features.cfg b/libvirt/tests/cfg/cpu/vm_features.cfg index b33c14e7bcb..17009e09cfe 100644 --- a/libvirt/tests/cfg/cpu/vm_features.cfg +++ b/libvirt/tests/cfg/cpu/vm_features.cfg @@ -14,6 +14,24 @@ - tlbflush: func_supported_since_libvirt_ver = (5, 0, 0) hyperv_attr = {'relaxed': {'state': 'on'}, 'vapic': {'state': 'on'}, 'vpindex': {'state': 'on'}, 'tlbflush': {'state': 'on'}} + - tlbflush_direct_extended: + func_supported_since_libvirt_ver = (10, 10, 0) + hyperv_attr = {'tlbflush': {'state': 'on', 'direct':{'state': 'on'}, 'extended':{'state': 'on'}}, 'vapic': {'state': 'on'}, 'vpindex': {'state': 'on'},'relaxed': {'state': 'on'}} + qemu_include = 'hv-tlbflush=on,hv-tlbflush-direct=on,hv-tlbflush-ext=on' + expected_xpaths = [{'element_attrs':['.//tlbflush[@state="on"]']},{'element_attrs':['.//tlbflush/direct[@state="on"]']},{'element_attrs':['.//tlbflush/extended[@state="on"]']}] + check_xml = "yes" + - emsr_bitmap: + func_supported_since_libvirt_ver = (10, 10, 0) + hyperv_attr = {'emsr_bitmap': {'state': 'on'}} + qemu_include = 'hv-emsr-bitmap=on' + check_xml = "yes" + expected_xpaths = [{'element_attrs':['.//emsr_bitmap[@state="on"]']}] + - xmm_input: + func_supported_since_libvirt_ver = (10, 10, 0) + hyperv_attr = {'xmm_input': {'state': 'on'}} + qemu_include = 'hv-xmm-input=on' + check_xml = "yes" + expected_xpaths = [{'element_attrs':['.//xmm_input[@state="on"]']}] - frequencies: func_supported_since_libvirt_ver = (5, 0, 0) hyperv_attr = {'relaxed': {'state': 'on'}, 'vapic': {'state': 'on'}, 'vpindex': {'state': 'on'}, 'frequencies': {'state': 'on'}} diff --git a/libvirt/tests/src/cpu/vm_features.py b/libvirt/tests/src/cpu/vm_features.py index e4998c65dd6..0821847aafc 100644 --- a/libvirt/tests/src/cpu/vm_features.py +++ b/libvirt/tests/src/cpu/vm_features.py @@ -11,6 +11,7 @@ from virttest.libvirt_xml import domcapability_xml from virttest.libvirt_xml import vm_xml from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_vmxml from virttest.libvirt_xml import xcepts # Using as lower capital is not the best way to do, but this is just a @@ -180,6 +181,7 @@ def run(test, params, env): pkgs = params.get('pkgs') features_from_domcap = params.get('features_from_domcap') status_error = params.get('status_error') == 'yes' + check_xml = params.get('check_xml') == 'yes' vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) bkxml = vmxml.copy() @@ -206,6 +208,9 @@ def run(test, params, env): try: ret = virsh.start(vm_name, debug=True) libvirt.check_exit_status(ret, status_error) + if check_xml: + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + libvirt_vmxml.check_guest_xml_by_xpaths(vmxml, eval(params.get("expected_xpaths"))) except exceptions.TestFail as details: if re.search(r"host doesn\'t support paravirtual spinlocks", str(details)): From 5842e162e3184816de5cc1dbfa356e1ad8042d01 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 7 Apr 2025 23:12:41 -0400 Subject: [PATCH 0918/1055] Release postcopy and additional parameter for aarch64 Signed-off-by: liang-cong-red-hat --- libvirt/tests/cfg/migration/migration_with_numa_topology.cfg | 2 -- 1 file changed, 2 deletions(-) diff --git a/libvirt/tests/cfg/migration/migration_with_numa_topology.cfg b/libvirt/tests/cfg/migration/migration_with_numa_topology.cfg index a189dbaa6d2..514ae02f0cd 100644 --- a/libvirt/tests/cfg/migration/migration_with_numa_topology.cfg +++ b/libvirt/tests/cfg/migration/migration_with_numa_topology.cfg @@ -24,14 +24,12 @@ - base_options: add_options = "" - addtional_options: - no aarch64 migration_connections = 3 add_options = "--auto-converge --parallel --parallel-connections ${migration_connections} --tls" variants: - without_postcopy: copy_type = "" - postcopy: - no aarch64 only base_options copy_type = "--postcopy" variants: From f5b1649e864b5d5c116a06fe381f054aa18ba910 Mon Sep 17 00:00:00 2001 From: meinaLi Date: Mon, 7 Apr 2025 23:28:43 -0400 Subject: [PATCH 0919/1055] Sriov: fix "unplug of device was rejected by the guest" failure Fix the unplug failure of dimm memory device by adding memhp_default_state=online_movable to guest kernel which is a common workaround. Signed-off-by: meinaLi --- .../sriov/locked_memory_check/sriov_with_hotplug_memory.cfg | 3 ++- .../src/sriov/locked_memory_check/sriov_with_hotplug_memory.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/sriov/locked_memory_check/sriov_with_hotplug_memory.cfg b/libvirt/tests/cfg/sriov/locked_memory_check/sriov_with_hotplug_memory.cfg index caf7bbd9f5d..053ff627211 100644 --- a/libvirt/tests/cfg/sriov/locked_memory_check/sriov_with_hotplug_memory.cfg +++ b/libvirt/tests/cfg/sriov/locked_memory_check/sriov_with_hotplug_memory.cfg @@ -1,9 +1,10 @@ - sriov.locked_memory_check.hotplug_memory: type = sriov_with_hotplug_memory - start_vm = "no" + start_vm = "yes" mem_dict1 = {'mem_model': 'dimm', 'target': {'size': 1, 'size_unit': 'G', 'node': 0}, 'alias': {'name': 'ua-d9cbe3cc-40fe-4aed-b245-874c534e8362'}} mem_dict2 = {'mem_model': 'dimm', 'target': {'size': 1, 'size_unit': 'G', 'node': 0}} vm_attrs = {'max_mem_rt': 6291456, 'max_mem_rt_slots': 32, 'max_mem_rt_unit': 'K', 'vcpu': 8, 'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-3', 'memory': '%s', 'unit': 'K'}, {'id': '1', 'cpus': '4-7', 'memory': '%s', 'unit': 'K'}]}} + kernel_extra_params_add = "memhp_default_state=online_movable" only x86_64, aarch64 variants dev_type: - hostdev_interface: diff --git a/libvirt/tests/src/sriov/locked_memory_check/sriov_with_hotplug_memory.py b/libvirt/tests/src/sriov/locked_memory_check/sriov_with_hotplug_memory.py index 8bf2263d446..1f83d4b7564 100644 --- a/libvirt/tests/src/sriov/locked_memory_check/sriov_with_hotplug_memory.py +++ b/libvirt/tests/src/sriov/locked_memory_check/sriov_with_hotplug_memory.py @@ -105,7 +105,7 @@ def hotplug_mem_device(vm_name, mem_dict, current_mem): test.log.info("TEST_STEP: Start the vm and check locked memory limit.") vm.start() test.log.debug("The current guest xml is:%s", virsh.dumpxml(vm_name).stdout_text) - vm_session = vm.wait_for_serial_login(timeout=240).close + vm.wait_for_login(timeout=240).close() default_mem = libvirt_memory.normalize_mem_size( vmxml.get_current_mem(), vmxml.get_current_mem_unit()) From a5d87a6d301d486088592d7699a77b7a615b062e Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Thu, 13 Mar 2025 21:52:28 -0400 Subject: [PATCH 0920/1055] Add new case for deleting external snapshot after reverting to an internal snapshot Signed-off-by: liang-cong-red-hat --- ...lete_external_after_reverting_internal.cfg | 19 +++ ...elete_external_after_reverting_internal.py | 152 ++++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 libvirt/tests/cfg/snapshot/delete_external_after_reverting_internal.cfg create mode 100644 libvirt/tests/src/snapshot/delete_external_after_reverting_internal.py diff --git a/libvirt/tests/cfg/snapshot/delete_external_after_reverting_internal.cfg b/libvirt/tests/cfg/snapshot/delete_external_after_reverting_internal.cfg new file mode 100644 index 00000000000..ea0f1fce2c2 --- /dev/null +++ b/libvirt/tests/cfg/snapshot/delete_external_after_reverting_internal.cfg @@ -0,0 +1,19 @@ +- snapshot_delete.after_reverting_internal: + type = delete_external_after_reverting_internal + start_vm = no + internal_snap_name = s1 + internal_snap_option = "${internal_snap_name}" + external_snap_name = s2 + external_snap_option = "${external_snap_name} --memspec file=%s,snapshot=external" + disk_xpath = [{'element_attrs':[".//devices/disk/source[@file='%s']"]}, {'element_attrs':[".//devices/disk/backingStore[@type='file']"]}, {'element_attrs':[".//devices/disk/backingStore/source[@file='%s']"]}] + variants: + - seabios: + only x86_64 + firmware_type = "seabios" + - ovmf: + only aarch64 + func_supported_since_libvirt_ver = (10, 10, 0) + firmware_type = "ovmf" + - no_firmware: + only s390-virtio + diff --git a/libvirt/tests/src/snapshot/delete_external_after_reverting_internal.py b/libvirt/tests/src/snapshot/delete_external_after_reverting_internal.py new file mode 100644 index 00000000000..d52089a35c3 --- /dev/null +++ b/libvirt/tests/src/snapshot/delete_external_after_reverting_internal.py @@ -0,0 +1,152 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Liang Cong +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import os + +from virttest import data_dir +from virttest import libvirt_version +from virttest import utils_misc +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.guest_os_booting import guest_os_booting_base + + +def run(test, params, env): + """ + Delete external snapshot after reverting to internal snapshot. + """ + def check_dom_disks(): + """ + Check domain disk type and file type disk number. + """ + domxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + disks = domxml.get_disk_all_by_expr("type!=file", "device==disk") + if disks: + test.error("Unsupported non-file type disk found in domain.") + disks = domxml.get_disk_all_by_expr("type==file", "device==disk") + if len(disks) != 1: + test.error("Expected only 1 file type disk but found %s." % len(disks)) + + def check_internal_snap(): + """ + Check internal snapshot info. + """ + snap_info = virsh.snapshot_info(vm_name, internal_snap_name, **virsh_dargs) + if snap_info["Name"] != internal_snap_name or snap_info["Location"] != "internal": + test.fail("Expected internal snapshot named after '%s', but found %s snapshot named after '%s'." % ( + internal_snap_name, snap_info["Location"], snap_info["Name"])) + internal_snap_list = utils_misc.get_image_snapshot(disk_source) + if len(internal_snap_list) != 1: + test.fail("Expected only 1 internal snapshot in image, but found %s." % len( + internal_snap_list)) + + def check_disk_xml(xpath_list): + """ + Check domain disk xml according to xpath. + + :param xpath_list: expected xpath list. + """ + dom_xml = vm_xml.VMXML.new_from_dumpxml(vm_name) + test.log.debug("domain xml is: %s", dom_xml) + libvirt_vmxml.check_guest_xml_by_xpaths(dom_xml, xpath_list) + + def check_file_after_snapshot_delete(file, exist): + """ + Check snapshot related file after snapshot delete. + + :param file: str, snapshot related file path. + :param exist: bool, file should exist or not. + """ + if os.path.exists(file) != exist: + judgement_string = "" if exist else "not " + test.fail("file '%s' should %sexist after snapshot delete." % (file, judgement_string)) + + def run_test(): + """ + 1. Define a guest. + 2. Create an internal snapshot. + 3. Start the guest. + 4. Create an external snapshot. + 5. Revert snapshot to the internal snapshot. + 6. Delete the external snapshot. + 7. Check the snapshot related images. + """ + #since default guest is used, so step 1 virsh define is skipped. + test.log.info("TEST_STEP2:Create an internal snapshot.") + virsh.snapshot_create_as(vm_name, internal_snap_option, **virsh_dargs) + check_internal_snap() + + test.log.info("TEST_STEP3:Start the guest.") + vm.start() + vm.wait_for_login().close() + + test.log.info("TEST_STEP4:Create an external snapshot.") + virsh.snapshot_create_as(vm_name, external_snap_option, **virsh_dargs) + check_disk_xml(disk_xpath) + + test.log.info("TEST_STEP5:Revert snapshot to the internal snapshot.") + virsh.snapshot_revert(vm_name, internal_snap_name, **virsh_dargs) + dom_xml = vm_xml.VMXML.new_from_dumpxml(vm_name) + current_disk_dict = dom_xml.devices.by_device_tag('disk')[0].fetch_attrs() + original_disk_dict = original_disk.fetch_attrs() + if original_disk_dict != current_disk_dict: + test.fail("Expected domain disk is %s, but found %s." % + (original_disk_dict, current_disk_dict)) + + test.log.info("TEST_STEP6:Delete the external snapshot.") + virsh.snapshot_delete(vm_name, external_snap_name, **virsh_dargs) + + test.log.info("TEST_STEP7:Check the snapshot related images.") + for snap_file in external_snap_file_list: + check_file_after_snapshot_delete(snap_file, exist=False) + check_file_after_snapshot_delete(disk_source, exist=True) + + def teardown_test(): + """ + Clean test environment. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + if vm.is_alive(): + vm.destroy() + libvirt.clean_up_snapshots(vm_name) + for snap_file in external_snap_file_list: + if os.path.exists(snap_file): + os.remove(snap_file) + undefine_option = "--nvram" if firmware_type == "ovmf" else None + bkxml.sync(undefine_option) + + libvirt_version.is_libvirt_feature_supported(params) + vm_name = guest_os_booting_base.get_vm(params) + firmware_type = params.get("firmware_type") + internal_snap_name = params.get("internal_snap_name") + external_snap_name = params.get("external_snap_name") + external_mem_file = "%s/%s.%s" % (data_dir.get_tmp_dir(), vm_name, external_snap_name) + internal_snap_option = params.get("internal_snap_option") + external_snap_option = params.get("external_snap_option") % external_mem_file + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + original_disk = vmxml.devices.by_device_tag('disk')[0] + vm = env.get_vm(vm_name) + disk_source = vm.get_first_disk_devices()["source"] + ori_image_file, _ = os.path.splitext(disk_source) + external_snapshot_file = "%s.%s" % (ori_image_file, external_snap_name) + external_snap_file_list = [external_mem_file, external_snapshot_file] + disk_xpath = eval(params.get("disk_xpath") % (external_snapshot_file, disk_source)) + virsh_dargs = {"debug": True, "ignore_status": False} + + try: + check_dom_disks() + run_test() + + finally: + teardown_test() From 79d4e1a31c988600fb334d6f8c551e0fcdca44a8 Mon Sep 17 00:00:00 2001 From: nanli Date: Tue, 8 Apr 2025 15:07:27 +0800 Subject: [PATCH 0921/1055] fix cpu max value increases cpu max value increase in rhel10 Signed-off-by: nanli --- libvirt/tests/src/cpu/max_vcpus.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/cpu/max_vcpus.py b/libvirt/tests/src/cpu/max_vcpus.py index 1ed245a6291..e5aa323472b 100644 --- a/libvirt/tests/src/cpu/max_vcpus.py +++ b/libvirt/tests/src/cpu/max_vcpus.py @@ -112,7 +112,7 @@ def set_iommu(vmxml, **dargs): exp_val = report_num_q35_7_8 if key == "pc-q35-rhel7.3.0": exp_val = report_num_q35_73 - elif key == "pc-q35-rhel9.6.0" or key == 'q35': + elif key == "pc-q35-rhel9.6.0" or key == "pc-q35-rhel10.0.0" or key == 'q35': exp_val = report_num_q35_9_6 else: if libvirt_version.version_compare(7, 0, 0): From 1d76c68770441b2a1910e26d61c82b2c4efb5b0a Mon Sep 17 00:00:00 2001 From: lcheng Date: Sun, 6 Apr 2025 20:49:31 +0800 Subject: [PATCH 0922/1055] migration: Add case about non-canonical paths in shared_filesystems XXX-304031 - Migrate a guest on non-canonical paths in shared_filesystems Signed-off-by: lcheng --- ..._canonical_paths_in_shared_filesystems.cfg | 49 +++++ ...n_canonical_paths_in_shared_filesystems.py | 175 ++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100644 libvirt/tests/cfg/migration/migration_misc/non_canonical_paths_in_shared_filesystems.cfg create mode 100644 libvirt/tests/src/migration/migration_misc/non_canonical_paths_in_shared_filesystems.py diff --git a/libvirt/tests/cfg/migration/migration_misc/non_canonical_paths_in_shared_filesystems.cfg b/libvirt/tests/cfg/migration/migration_misc/non_canonical_paths_in_shared_filesystems.cfg new file mode 100644 index 00000000000..8f11f00428a --- /dev/null +++ b/libvirt/tests/cfg/migration/migration_misc/non_canonical_paths_in_shared_filesystems.cfg @@ -0,0 +1,49 @@ +- migration.migration_misc.non_canonical_paths_in_shared_filesystems: + type = non_canonical_paths_in_shared_filesystems + migration_setup = 'yes' + storage_type = '' + setup_nfs = 'no' + setup_local_nfs = 'no' + disk_type = "file" + disk_source_protocol = "netfs" + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + client_ip = "${migrate_source_host}" + client_user = "root" + client_pwd = "${migrate_source_pwd}" + status_error = "no" + migrate_desturi_port = "22" + migrate_desturi_type = "ssh" + virsh_migrate_desturi = "qemu+ssh://${migrate_dest_host}/system" + start_vm = "yes" + nfs_mount_options = "bind" + export_dir = "/nfs" + nfs_server_ip = "${migrate_source_host}" + images_path = "/var/lib/libvirt/images" + nvram_path = "/var/lib/libvirt/qemu/nvram" + swtpm_path = "/var/lib/libvirt/swtpm" + soft_link = "/var/lib/libvirt/images/nfs-link" + nfs_mount_dir = "${soft_link}" + mnt_path_name = "${soft_link}" + nfs_images_path = "${export_dir}/libvirt/images" + nfs_nvram_path = "${export_dir}/libvirt/nvram" + nfs_swtpm_path = "${export_dir}/libvirt/swtpm" + mount_images_path = "${nfs_server_ip}:${export_dir}/libvirt/images" + mount_nvram_path = "${nfs_server_ip}:${export_dir}/libvirt/nvram" + mount_swtpm_path = "${nfs_server_ip}:${export_dir}/libvirt/swtpm" + qemu_conf_dest = '{r".*shared_filesystems\s*=.*": "shared_filesystems = [\"${soft_link}\", \"${nvram_path}\", \"${swtpm_path}\"]"}' + qemu_conf_src = '{"shared_filesystems": "[\"${soft_link}/\", \"${nvram_path}\", \"${swtpm_path}\"]"}' + migrate_vm_back = "yes" diff --git a/libvirt/tests/src/migration/migration_misc/non_canonical_paths_in_shared_filesystems.py b/libvirt/tests/src/migration/migration_misc/non_canonical_paths_in_shared_filesystems.py new file mode 100644 index 00000000000..78c96381c1d --- /dev/null +++ b/libvirt/tests/src/migration/migration_misc/non_canonical_paths_in_shared_filesystems.py @@ -0,0 +1,175 @@ +import os + +from avocado.utils import process + +from virttest import libvirt_remote +from virttest import remote +from virttest import utils_config +from virttest import utils_disk +from virttest import utils_misc +from virttest.utils_test import libvirt + +from provider.migration import base_steps + + +def setup_for_shared_filesystems(params, test): + """ + Setup for shared filesystems + + :param params: dict, test parameters + :param test: test object + """ + export_dir = params.get("export_dir") + nfs_images_path = params.get("nfs_images_path") + nfs_nvram_path = params.get("nfs_nvram_path") + nfs_swtpm_path = params.get("nfs_swtpm_path") + images_path = params.get("images_path") + nvram_path = params.get("nvram_path") + swtpm_path = params.get("swtpm_path") + nfs_mount_options = params.get("nfs_mount_options") + server_ip = params.get("server_ip") + server_user = params.get("server_user", "root") + server_pwd = params.get("server_pwd") + mount_images_path = params.get("mount_images_path") + mount_nvram_path = params.get("mount_nvram_path") + mount_swtpm_path = params.get("mount_swtpm_path") + + if not os.path.exists(export_dir): + os.mkdir(export_dir) + + mount_opt = "rw,no_root_squash,sync" + res = libvirt.setup_or_cleanup_nfs(is_setup=True, + is_mount=False, + export_options=mount_opt, + export_dir=export_dir) + + for path in [nfs_images_path, nfs_nvram_path, nfs_swtpm_path]: + if not utils_misc.check_exists(path): + process.run(f"mkdir -p {path}", shell=True, verbose=True) + + remote_session = remote.wait_for_login("ssh", server_ip, "22", server_user, server_pwd, r"[\#\$]\s*$") + utils_disk.mount(mount_images_path, images_path, session=remote_session) + utils_disk.mount(mount_nvram_path, nvram_path, session=remote_session) + utils_disk.mount(mount_swtpm_path, swtpm_path, session=remote_session) + remote_session.close() + + process.run(f"cd {nfs_images_path}; mkdir nfs; ln -s nfs nfs-link", shell=True, verbose=True) + + utils_disk.mount(nfs_images_path, images_path, options=nfs_mount_options) + utils_disk.mount(nfs_nvram_path, nvram_path, options=nfs_mount_options) + utils_disk.mount(nfs_swtpm_path, swtpm_path, options=nfs_mount_options) + + remote_obj = None + local_obj = None + qemu_conf_src = eval(params.get("qemu_conf_src", "{}")) + qemu_conf_dest = params.get("qemu_conf_dest", "{}") + qemu_conf_path = utils_config.LibvirtQemuConfig().conf_path + remote_obj = libvirt_remote.update_remote_file(params, qemu_conf_dest, qemu_conf_path) + local_obj = libvirt.customize_libvirt_config(qemu_conf_src, "qemu", remote_host=False, + extra_params=params) + return (local_obj, remote_obj) + + +def cleanup_for_shared_filesystems(params, test): + """ + Cleanup for shared filesystems + + :param params: dict, test parameters + :param test: test object + """ + images_path = params.get("images_path") + nvram_path = params.get("nvram_path") + swtpm_path = params.get("swtpm_path") + server_ip = params.get("server_ip") + server_user = params.get("server_user", "root") + server_pwd = params.get("server_pwd") + export_dir = params.get("export_dir") + mount_images_path = params.get("mount_images_path") + mount_nvram_path = params.get("mount_nvram_path") + mount_swtpm_path = params.get("mount_swtpm_path") + + test.log.info("Cleanup for shared_filesystems.") + for path in [images_path, nvram_path, swtpm_path]: + process.run(f"umount {path}", shell=True, verbose=True) + + remote_session = remote.wait_for_login("ssh", server_ip, "22", server_user, server_pwd, r"[\#\$]\s*$") + utils_disk.umount(mount_nvram_path, nvram_path, session=remote_session) + utils_disk.umount(mount_swtpm_path, swtpm_path, session=remote_session) + utils_disk.umount(mount_images_path, images_path, session=remote_session) + remote_session.close() + + libvirt.setup_or_cleanup_nfs(is_setup=False) + process.run(f"rm -rf {export_dir}", shell=True, ignore_status=True) + + +def run(test, params, env): + """ + Use non-canonical paths in shared_filesystems. Then migrate the domain + based on the non-canonical paths. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def setup_test(): + """ + Setup steps for cases + + """ + soft_link = params.get("soft_link") + + test.log.info("Setup steps for cases.") + + nonlocal local_qemu_obj + nonlocal remote_qemu_obj + local_qemu_obj, remote_qemu_obj = setup_for_shared_filesystems(params, test) + + blk_source = vm.get_first_disk_devices()['source'] + process.run(f"cp {blk_source} {soft_link}", shell=True, verbose=True) + process.run("setsebool virt_use_nfs on", shell=True, verbose=True) + remote.run_remote_cmd("setsebool virt_use_nfs on", params) + + migration_obj.setup_connection() + + def verify_test_again(): + """ + Verify test again + + """ + test.log.info("Verify test again.") + dargs = {"check_disk_on_dest": "no"} + migration_obj.migration_test.post_migration_check([vm], dargs) + + def cleanup_test(): + """ + Cleanup steps for cases + """ + test.log.info("Cleanup steps for cases.") + migration_obj.cleanup_connection() + cleanup_for_shared_filesystems(params, test) + process.run("rm -rf /var/lib/libvirt/swtpm/*", shell=True, ignore_status=True) + process.run("rm -rf /var/lib/libvirt/qemu/nvram/*", shell=True, ignore_status=True) + nonlocal local_qemu_obj + if local_qemu_obj: + libvirt.customize_libvirt_config(None, config_type="qemu", remote_host=False, + is_recover=True, extra_params=params, + config_object=local_qemu_obj) + nonlocal remote_qemu_obj + if remote_qemu_obj: + del remote_qemu_obj + + vm_name = params.get("migrate_main_vm") + local_qemu_obj = None + remote_qemu_obj = None + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + setup_test() + migration_obj.run_migration() + migration_obj.verify_default() + migration_obj.run_migration_back() + verify_test_again() + finally: + cleanup_test() From 0e37a9a061df0a00c0091771946eaffe1da4e56a Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 19 Mar 2025 07:48:44 -0400 Subject: [PATCH 0923/1055] filesystem_device: add test for virt queue size and debug log There were already tests for negative test cases but we also want to confirm the valid values are passed to qemu correctly. Instead of creating another paramter variant similar to xattr, sandbox_mode create a variant on a higher level. Firstly, this allows more easily to define these tests for both externally and internally launched virtiofsd instances and secondly, in future commits the parameter coverage should be reorganized to allow for controlling the test matrix more easily and thus avoid matrix explosion. Furthermore, add a test case to check that virtiofsd's debug log level can be set correclty. Signed-off-by: Sebastian Mitterle --- .../cfg/virtual_device/filesystem_device.cfg | 17 +++++- .../src/virtual_device/filesystem_device.py | 59 ++++++++++++++++--- 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg index fb871dc9039..12c408d8d17 100644 --- a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg +++ b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg @@ -81,7 +81,22 @@ - nop: - socket_file_checking: socket_file_checking = "yes" - only xattr_on.cache_mode_auto.thread_pool_noset.sandbox_mode_none..one_fs.one_guest, externally_launched_fs_test + only file_backed..xattr_on.cache_mode_auto.thread_pool_noset.sandbox_mode_none..one_fs.one_guest, externally_launched_fs_test + - queue_size: + only file_backed..xattr_on.cache_mode_auto.thread_pool_noset.sandbox_mode_none..one_fs.one_guest, file_backed..externally_launched_fs_test..one_fs.one_guest + variants: + - queue_size_none: + queue_size = "" + - queue_size_0: + queue_size = "0" + - queue_size_1024: + queue_size = "1024" + - qemu_config: + only file_backed..xattr_on.cache_mode_auto.thread_pool_noset.sandbox_mode_none..one_fs.one_guest + no externally_launched_fs_test + variants: + - debug_log: + check_debug_log = "yes" - lifecycle: only xattr_on.cache_mode_auto.thread_pool_noset.sandbox_mode_none..one_fs.one_guest, externally_launched_fs_test..one_fs.one_guest variants: diff --git a/libvirt/tests/src/virtual_device/filesystem_device.py b/libvirt/tests/src/virtual_device/filesystem_device.py index 26555bc569b..b5642909c0b 100644 --- a/libvirt/tests/src/virtual_device/filesystem_device.py +++ b/libvirt/tests/src/virtual_device/filesystem_device.py @@ -243,7 +243,7 @@ def check_filesystem_hotplug_with_mem_setup(): path = params.get("virtiofsd_path", "/usr/libexec/virtiofsd") thread_pool_size = params.get("thread_pool_size") openfiles = params.get("openfiles", "no") == "yes" - queue_size = int(params.get("queue_size", "512")) + queue_size = params.get("queue_size", "512") driver_type = params.get("driver_type", "virtiofs") fs_num = int(params.get("fs_num", "1")) vcpus_per_cell = int(params.get("vcpus_per_cell", 2)) @@ -267,7 +267,9 @@ def check_filesystem_hotplug_with_mem_setup(): stdio_handler_file = "file" == params.get("stdio_handler") setup_mem = params.get("setup_mem", False) omit_dir_at_first = "yes" == params.get("omit_dir_at_first", "no") + check_debug_log = "yes" == params.get("check_debug_log", "no") + qemu_config = None fs_devs = [] vms = [] vmxml_backups = [] @@ -311,7 +313,9 @@ def _get_fs_dev_and_source_dir(fs_index, socket_index): directory which is not part of the XML so the test can launch the instance for it """ - driver = {'type': driver_type, 'queue': queue_size} + driver = {'type': driver_type } + if queue_size != "": + driver['queue'] = queue_size source_dir = os.path.join('/var/tmp/', str(dir_prefix) + str(fs_index)) logging.debug(f"This filesystem has source dir: {source_dir}") if not os.path.isdir(source_dir): @@ -490,10 +494,6 @@ def set_up_and_start_vm(guest_index): libvirt.check_exit_status(result, not expect_error) return True if hotplug_unplug: - if stdio_handler_file: - qemu_config = LibvirtQemuConfig() - qemu_config.stdio_handler = "file" - utils_libvirtd.Libvirtd().restart() update_vm_with_fs_devs(guest_index, vmxml, attach=True) if status_error: return True @@ -509,6 +509,24 @@ def set_up_and_start_vm(guest_index): cmd = 'ps aux | grep /usr/libexec/virtiofsd' utils_test.libvirt.check_cmd_output(cmd, content=expected_results) + def check_qemu_cmdline(): + """ + Checks the qemu command line output + At this point only queue size is checked. + """ + if ( + queue_size + and int(queue_size) > 0 + and not hotplug_unplug + ): + cmd = 'ps aux | grep qemu-kvm' + content = [f"queue-size.{{1,3}}{queue_size}"] + utils_test.libvirt.check_cmd_output( + cmd, + content=content + ) + + def check_file_exists(vm, filepath): """ Confirm that the given file path exists. @@ -524,16 +542,43 @@ def check_file_exists(vm, filepath): if status: test.fail(f"{filepath} not found in the mount: {output}") + def update_qemu_config(): + """ + Updates Libvirt's QEMU configuration if needed + """ + if not any([stdio_handler_file, check_debug_log]): + return + qemu_config = LibvirtQemuConfig() + if stdio_handler_file: + qemu_config.stdio_handler = "file" + if check_debug_log: + qemu_config.virtiofsd_debug = 1 + utils_libvirtd.Libvirtd().restart() + update_qemu_config() create_fs_devs() for index in range(guest_num): end_test = set_up_and_start_vm(index) + check_qemu_cmdline() if end_test: return shared_data(vm_names, fs_devs) + if check_debug_log: + alias = fs_devs[0].alias['name'] + file_name = '/var/log/libvirt/qemu/%s-%s-virtiofsd.log' % (vm_names[0], alias) + try: + with open(file_name, 'r') as f: + output = f.read() + if "DEBUG" not in output: + shutil.copy(file_name, test.debugdir) + test.fail("Failed to find string in virtiofsd log.") + except FileNotFoundError: + test.fail("virtiofsd log not found") + + if lifecycle_scenario == "suspend_resume": virsh.suspend(vm_names[0], debug=True, ignore_status=False) time.sleep(30) @@ -644,7 +689,7 @@ def check_file_exists(vm, filepath): virsh.managedsave_remove(vm.name, debug=True, ignore_status=True) vmxml_backups[index].sync() utils_memory.set_num_huge_pages(backup_huge_pages_num) - if stdio_handler_file: + if qemu_config: qemu_config.restore() utils_libvirtd.Libvirtd().restart() for path_pattern in [ From cd9a56b92ca274ba8961f7e357d17a2e9cc65d92 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Thu, 20 Mar 2025 10:08:48 -0400 Subject: [PATCH 0924/1055] filesystem_device: restructure test matrix In time the matrix has grown considerably. Restructure it to reduce number of variants and make it easier to select tests. 1. Use external/internal to distinguish between tests where a running virtiofsd instance is used or when libvirt starts it. 2. Where test scope seems independent or low risk, select certain test cases only for - 1 device - 1 guest - default settings (memoryBacking, parameter values) namely: a. lifecycle tests b. libvirt qemu.conf tests c. socket file check d. command line checks for all parameters values 3. Tests that check the file system functionally use a combination of settings, at this point we define 3: i. to cover the case where no additional paramter is set ii. to cover a reasonable setup for sharing a directory between two guests with some security measures in place iii. to cover values that weren't covered previously Currently, all but the queue size parameter apply only to the launch by libvirt. queue size itself is not a virtiofsd parameter, so cover it only for in the single device for external set ref. 2. above. 4. Test matrix can be further reduced with low risk to: - only 1 coldplug_unplug case per memory backing and launch mode becaues nop and hotplug cover the other scenarios more exhaustively - retry_two_devices should be independent from chosen memory backing and doesn't apply to hotplug - parameter sets are only really relevant for internally launched instances because only queue size applies to both modes - not all unplug scenarios have to use the alias for unplugging, most don't have to 5. Some other changes were necessary to match the new matrix. - Enable with_alias detach test case for externally launched instance: checking for the log file is only valid for internally launched instances. - Don't run lifecycle tests with extenrally launched instance if it means the VM is stopped as in this case the virtiofsd exits. 6. Finally, fix also some script issues that surfaced during test run of the new matrix. Signed-off-by: Sebastian Mitterle --- .../cfg/virtual_device/filesystem_device.cfg | 311 ++++++++++-------- .../src/virtual_device/filesystem_device.py | 42 ++- 2 files changed, 191 insertions(+), 162 deletions(-) diff --git a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg index 12c408d8d17..4eceb368a15 100644 --- a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg +++ b/libvirt/tests/cfg/virtual_device/filesystem_device.cfg @@ -18,154 +18,185 @@ s390-virtio: with_numa = no variants: - - externally_launched_fs_test: - launch_mode = "externally" - variants: - - one_guest: - - two_guests: - only nop..one_fs - vms = "avocado-vt-vm1 avocado-vt-vm2" - variants: - - one_fs: - fs_num = 1 - - multiple_fs: - fs_num = 2 - - fs_test: - variants: - - one_guest: - - two_guests: - vms = "avocado-vt-vm1 avocado-vt-vm2" - only nop.fs_test.xattr_on.cache_mode_auto..one_fs, hotplug_unplug..fs_test.xattr_on.cache_mode_auto..one_fs + - positive_test: variants: - - one_fs: + - multiple_devices: + variants @launched: + - internal: + - external: + launch_mode = "externally" + variants @devices: + - one_device: + fs_num = 1 + - two_devices: + only one_guest + fs_num = 2 + - retry_two_devices: + only one_guest + only nop.file_backed..internal + omit_dir_at_first = "yes" + variants @guests: + - one_guest: + - two_guests: + vms = "avocado-vt-vm1 avocado-vt-vm2" + variants @memory_backing: + - file_backed: + with_hugepages = no + - memfd_backed: + with_hugepages = no + with_memfd = "yes" + - hugepages_backed: + with_hugepages = "yes" + s390-virtio: + kvm_module_parameters = "hpage=1" + variants @attachment: + - nop: + - coldplug_unplug: + only file_backed + only one_guest.one_device + coldplug = "yes" + - hotplug_unplug: + hotplug_unplug = "yes" + variants @reference: + - with_alias: + only default_parameters + only file_backed.one_guest.one_device + detach_device_alias = "yes" + - no_alias: + detach_device_alias = "no" + variants @parameter_set: + - default_parameters: + xattr = "" + cache_mode = "none" + thread_pool_size = + queue_size = + sandbox_mode = "none" + - non_default_parameters_1: + only hotplug_unplug + xattr = "on" + cache_mode = "auto" + thread_pool_size = + queue_size = + sandbox_mode = "namespace" + - non_default_parameters_2: + only hotplug_unplug + xattr = "on" + cache_mode = "always" + thread_pool_size = 16 + openfiles = "yes" + queue_size = 512 + sandbox_mode = "chroot" + - single_device: fs_num = 1 - - multiple_fs: - fs_num = 2 - only xattr_on.cache_mode_auto - - retry_multiple_fs: - fs_num = 2 - omit_dir_at_first = yes - only nop..xattr_on.cache_mode_auto.thread_pool_noset - variants: - - sandbox_mode_none: - sandbox_mode = "none" - - sandbox_mode_chroot: - sandbox_mode = "chroot" - - sandbox_mode_namespace: - sandbox_mode = "namespace" - variants: - - thread_pool_0: - thread_pool_size = 0 - openfiles = "no" - only positive_test..nop..xattr_on.cache_mode_auto, positive_test..detach_device..xattr_on.cache_mode_auto - - thread_pool_16: - thread_pool_size = 16 - openfiles = "yes" - only positive_test..nop..xattr_on.cache_mode_auto, positive_test..detach_device..xattr_on.cache_mode_auto - - thread_pool_noset: - variants: - - cache_mode_none: - cache_mode = "none" - - cache_mode_always: - cache_mode = "always" - - cache_mode_auto: - cache_mode = "auto" - variants: - - xattr_on: - xattr = "on" - - xattr_off: - xattr = "off" - - xattr_noset: - xattr = "" - variants: - - nop: - - socket_file_checking: - socket_file_checking = "yes" - only file_backed..xattr_on.cache_mode_auto.thread_pool_noset.sandbox_mode_none..one_fs.one_guest, externally_launched_fs_test - - queue_size: - only file_backed..xattr_on.cache_mode_auto.thread_pool_noset.sandbox_mode_none..one_fs.one_guest, file_backed..externally_launched_fs_test..one_fs.one_guest - variants: - - queue_size_none: - queue_size = "" - - queue_size_0: - queue_size = "0" - - queue_size_1024: - queue_size = "1024" - - qemu_config: - only file_backed..xattr_on.cache_mode_auto.thread_pool_noset.sandbox_mode_none..one_fs.one_guest - no externally_launched_fs_test - variants: - - debug_log: - check_debug_log = "yes" - - lifecycle: - only xattr_on.cache_mode_auto.thread_pool_noset.sandbox_mode_none..one_fs.one_guest, externally_launched_fs_test..one_fs.one_guest - variants: - - suspend_resume: - lifecycle_scenario = "suspend_resume" - - edit_start: - only fs_test - lifecycle_scenario = "edit_start" - error_msg_start = "qemu-kvm: -foo: invalid option" - - destroy_start: - only file_backed - bug_url = "https://bugzilla.redhat.com/show_bug.cgi?id=1940276" - lifecycle_scenario = "destroy_start" - stress_script = "#!/usr/bin/python3;import os;while True:; os.open("%s/moo", os.O_CREAT | os.O_RDWR); os.unlink("%s/moo");" - - shutdown_start: - only file_backed - lifecycle_scenario = "shutdown_start" - - reboot: - only file_backed - lifecycle_scenario = "reboot" - - restart_service: - only file_backed - func_supported_since_libvirt_ver = (9, 2, 0) - lifecycle_scenario = "restart_service" - setup_mem = True - source_dir = "/var/tmp/mount_tag0" - dev_type = "filesystem" - vm_attrs = {'mb': {"source_type":"file", 'access_mode': 'shared'}} - fs_dict = {'accessmode':'passthrough', 'driver': {'type': 'virtiofs', 'queue':'512'}, 'source':{'dir': '${source_dir}'}, "target": {'dir': 'mount_tag0'}, 'binary': {'path': '/usr/libexec/virtiofsd', 'xattr': 'on','cache_mode':'always'}} - - managedsave: - lifecycle_scenario = "managedsave" - - coldplug_coldunplug: - only xattr_on.cache_mode_auto..one_fs - coldplug = "yes" - - hotplug_unplug: - hotplug_unplug = "yes" - variants: - - detach_device_alias: - detach_device_alias = "yes" - only xattr_on.cache_mode_auto + with_hugepages = no + variants @launched: + - internal: + xattr = "" + cache_mode = "none" + thread_pool_size = + queue_size = + sandbox_mode = "none" + - external: + launch_mode = "externally" + queue_size = variants: - - stdio_handler: + - lifecycle: variants: - - file: - stdio_handler = "file" - only one_fs.one_guest - - logd: - stdio_handler = "logd" - - detach_device: - detach_device_alias = "no" - variants: - - positive_test: - status_error = "no" - variants: - - hugepages_backed: - with_hugepages = yes - s390-virtio: - kvm_module_parameters = "hpage=1" - - file_backed: - with_hugepages = no - - memfd_backed: - with_hugepages = no - with_memfd = yes + - managedsave: + no external + lifecycle_scenario = "managedsave" + - restart_service: + func_supported_since_libvirt_ver = (9, 2, 0) + lifecycle_scenario = "restart_service" + setup_mem = True + source_dir = "/var/tmp/mount_tag0" + dev_type = "filesystem" + vm_attrs = {'mb': {"source_type":"file", 'access_mode': 'shared'}} + fs_dict = {'accessmode':'passthrough', 'driver': {'type': 'virtiofs', 'queue':'512'}, 'source':{'dir': '${source_dir}'}, "target": {'dir': 'mount_tag0'}, 'binary': {'path': '/usr/libexec/virtiofsd', 'xattr': 'on','cache_mode':'always'}} + - reboot: + lifecycle_scenario = "reboot" + - shutdown_start: + no external + lifecycle_scenario = "shutdown_start" + - edit_start: + no external + lifecycle_scenario = "edit_start" + - destroy_start: + no external + lifecycle_scenario = "destroy_start" + stress_script = "#!/usr/bin/python3;import os;while True:; os.open("%s/moo", os.O_CREAT | os.O_RDWR); os.unlink("%s/moo");" + bug_url = "https://bugzilla.redhat.com/show_bug.cgi?id=1940276" + - suspend_resume: + lifecycle_scenario = "suspend_resume" + - qemu_config: + only internal + variants: + - virtiofsd_debug_log: + - stdio_handler: + variants: + - file: + stdio_handler = "file" + - logd: + stdio_handler = "logd" + - socket_file_check: + socket_file_checking = "yes" + - parameters: + variants: + - xattr: + only internal + variants: + - xattr_not_set: + xattr = "" + - xattr_on: + xattr = "on" + - xattr_off: + xattr = "off" + - cache_mode: + only internal + variants: + - cache_mode_none: + cache_mode = "none" + - cache_mode_always: + cache_mode = "always" + - cache_mode_auto: + cache_mode = "auto" + - thread_pool: + only internal + variants: + - thread_pool_notset: + - thread_pool_0: + thread_pool_size = 0 + openfiles = "no" + - thread_pool_16: + thread_pool_size = 0 + openfiles = "yes" + - sandbox_mode: + only internal + variants: + - sandox_mode_none: + sandbox_mode = "none" + - sandox_mode_chroot: + sandbox_mode = "chroot" + - sandox_mode_namespace: + sandbox_mode = "namespace" + - queue_size: + variants: + - queue_size_none: + queue_size = "" + - queue_size_0: + queue_size = "0" + - queue_size_1024: + queue_size = "1024" - negative_test: - only fs_test.xattr_on.cache_mode_auto..one_fs.one_guest status_error = "yes" + xattr = "" + cache_mode = "none" + thread_pool_size = + queue_size = + sandbox_mode = "none" + fs_num = 1 variants: - invalid_queue_size: - only nop, hotplug_unplug.detach_device variants: - larger_than_uint16: queue_size = 1048576 diff --git a/libvirt/tests/src/virtual_device/filesystem_device.py b/libvirt/tests/src/virtual_device/filesystem_device.py index b5642909c0b..d388964c49d 100644 --- a/libvirt/tests/src/virtual_device/filesystem_device.py +++ b/libvirt/tests/src/virtual_device/filesystem_device.py @@ -264,7 +264,7 @@ def check_filesystem_hotplug_with_mem_setup(): launch_mode = params.get("launch_mode", "auto") bug_url = params.get("bug_url", "") script_content = params.get("stress_script", "") - stdio_handler_file = "file" == params.get("stdio_handler") + stdio_handler = params.get("stdio_handler", "") setup_mem = params.get("setup_mem", False) omit_dir_at_first = "yes" == params.get("omit_dir_at_first", "no") check_debug_log = "yes" == params.get("check_debug_log", "no") @@ -307,13 +307,13 @@ def _get_fs_dev_and_source_dir(fs_index, socket_index): :param fs_index: the index of the filesystem :param socket_index: the index of the socket for externally launched virtiofsd; this parameter is ignored for internally - launched virtifosd and must be different for each + launched virtiofsd and must be different for each VM accessing the filesystem :return tuple: (fs_dev, source_dir) - the device xml but also the source directory which is not part of the XML so the test can launch the instance for it """ - driver = {'type': driver_type } + driver = {'type': driver_type} if queue_size != "": driver['queue'] = queue_size source_dir = os.path.join('/var/tmp/', str(dir_prefix) + str(fs_index)) @@ -350,9 +350,10 @@ def create_fs_devs(): to the list fs_devs. """ with_sockets = launch_mode == "externally" + def __indexes(): """ - Helper function that creates input parameters for + Helper function that creates input parameters for _get_fs_dev_and_source_dir. They are different for internally and externally launched virtiofsd, e.g. for 2 times 2: (fs_index, socket_index) @@ -397,7 +398,7 @@ def _fs_dev_indexes(guest_index): def update_vm_with_fs_devs(guest_index, vmxml, attach): """ Either updates the VM XML or attaches the device XML - + :param guest_index: the index of the guest in vms :param vmxml: VMXML instance for guest_index :param attach: if True uses `virsh attach` else it redefines the VM @@ -425,19 +426,19 @@ def detach_fs_dev(guest_index): fs_indexes = _fs_dev_indexes(guest_index) for fs_index in fs_indexes: fs_dev = fs_devs[fs_index] - if detach_device_alias: + if detach_device_alias and launch_mode == "auto": utils_package.package_install("lsof") alias = fs_dev.alias['name'] cmd = 'lsof /var/log/libvirt/qemu/%s-%s-virtiofsd.log' % (vm.name, alias) output = process.run(cmd).stdout_text.splitlines() for item in output[1:]: - if stdio_handler_file: + if stdio_handler == "file": if item.split()[0] != "virtiofsd": test.fail("When setting stdio_handler as file, the command" - "to write log should be virtiofsd!") - else: + " to write log should be virtiofsd!") + elif stdio_handler == "logd": if item.split()[0] != "virtlogd": - test.fail("When setting stdio_handler as logd, the command" + test.fail(" When setting stdio_handler as logd, the command" "to write log should be virtlogd!") ret = virsh.detach_device_alias(vm.name, alias, ignore_status=True, debug=True, wait_for_event=True, @@ -526,7 +527,6 @@ def check_qemu_cmdline(): content=content ) - def check_file_exists(vm, filepath): """ Confirm that the given file path exists. @@ -546,11 +546,12 @@ def update_qemu_config(): """ Updates Libvirt's QEMU configuration if needed """ - if not any([stdio_handler_file, check_debug_log]): + if not any([stdio_handler, check_debug_log]): return + nonlocal qemu_config qemu_config = LibvirtQemuConfig() - if stdio_handler_file: - qemu_config.stdio_handler = "file" + if stdio_handler: + qemu_config.stdio_handler = stdio_handler if check_debug_log: qemu_config.virtiofsd_debug = 1 utils_libvirtd.Libvirtd().restart() @@ -576,8 +577,7 @@ def update_qemu_config(): shutil.copy(file_name, test.debugdir) test.fail("Failed to find string in virtiofsd log.") except FileNotFoundError: - test.fail("virtiofsd log not found") - + test.fail("virtiofsd log not found") if lifecycle_scenario == "suspend_resume": virsh.suspend(vm_names[0], debug=True, ignore_status=False) @@ -595,12 +595,10 @@ def update_qemu_config(): "destroy_start", "shutdown_start", "reboot" - ]: + ]: if fs_num > 1 or guest_num > 1: - raise test.error( - "some lifecycle tests are implemented for only 1 guest and" - " filesystem" - ) + test.error("some lifecycle tests are implemented for only" + " 1 guest and filesystem") session = vms[0].wait_for_login(timeout=120) session.cmd_status_output( "echo 'mount_tag0 /var/tmp/mount_tag0 " @@ -614,7 +612,7 @@ def update_qemu_config(): prepare_stress_script(script_path, script_content) # Run guest stress script stress_script_thread = threading.Thread(target=run_stress_script, - args=(session, script_path)) + args=(session, script_path)) stress_script_thread.setDaemon(True) stress_script_thread.start() # Creates a lot of unlink files From 22de8fd716df28a8df2755baa65eddc112f9f177 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Sun, 23 Mar 2025 11:17:06 -0400 Subject: [PATCH 0925/1055] filesystem_device: sync shared folder to avoid caching problems Sometimes md5sum gets stuck. This might happen because there's a problem with the file. In each guest sync the mounted folder before creating the md5sum to make sure the cache and storage are synchronized. Also, move the filename definition out because it was only defined once in the first loop giving the wrong impression that it would vary. However, we always write only one file so it's reasonable to have a single file name. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/virtual_device/filesystem_device.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_device/filesystem_device.py b/libvirt/tests/src/virtual_device/filesystem_device.py index d388964c49d..15217d87a58 100644 --- a/libvirt/tests/src/virtual_device/filesystem_device.py +++ b/libvirt/tests/src/virtual_device/filesystem_device.py @@ -91,13 +91,14 @@ def shared_data(vm_names, fs_devs): if status != 0: session.close() test.fail("mount virtiofs dir failed: %s" % output) + filename_guest = mount_dir + '/' + vms[0].name if vm == vms[0]: - filename_guest = mount_dir + '/' + vm.name cmd = "dd if=/dev/urandom of=%s bs=1M count=512 oflag=direct" % filename_guest status, output = session.cmd_status_output(cmd, timeout=300) if status != 0: session.close() test.fail("Write data failed: %s" % output) + session.cmd_status_output(f"sync -d {mount_dir}") md5_value = session.cmd_status_output("md5sum %s" % filename_guest, timeout=300)[1].strip().split()[0] md5s.append(md5_value) From c6df0ce1a706701470c13e496a7f1d7b8020e34f Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Thu, 3 Apr 2025 14:07:14 +0200 Subject: [PATCH 0926/1055] filesystem_device: move and rename test suites Agreed to rename tests and move into their own folder because: 1. virtiofs is one example of , historically there were others, too. 2. virtiofs for us has now its own high level test plan, so according to our internal strategy it should be easier to find. Additionally, make the `unprivileged` test variants a subvariant of `virtiofs`. This way with `virtiofs` all test cases are selected. Signed-off-by: Sebastian Mitterle --- .../filesystem_device.cfg => virtiofs/virtiofs.cfg} | 4 ++-- .../virtiofs_unprivileged.cfg} | 4 ++-- .../filesystem_device.py => virtiofs/virtiofs.py} | 0 .../virtiofs_unprivileged.py} | 0 4 files changed, 4 insertions(+), 4 deletions(-) rename libvirt/tests/cfg/{virtual_device/filesystem_device.cfg => virtiofs/virtiofs.cfg} (99%) rename libvirt/tests/cfg/{virtual_device/filesystem_device_unprivileged.cfg => virtiofs/virtiofs_unprivileged.cfg} (93%) rename libvirt/tests/src/{virtual_device/filesystem_device.py => virtiofs/virtiofs.py} (100%) rename libvirt/tests/src/{virtual_device/filesystem_device_unprivileged.py => virtiofs/virtiofs_unprivileged.py} (100%) diff --git a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg b/libvirt/tests/cfg/virtiofs/virtiofs.cfg similarity index 99% rename from libvirt/tests/cfg/virtual_device/filesystem_device.cfg rename to libvirt/tests/cfg/virtiofs/virtiofs.cfg index 4eceb368a15..a5ab31c37cb 100644 --- a/libvirt/tests/cfg/virtual_device/filesystem_device.cfg +++ b/libvirt/tests/cfg/virtiofs/virtiofs.cfg @@ -1,5 +1,5 @@ -- virtual_devices.filesystem_device: - type = filesystem_device +- virtiofs: + type = virtiofs take_regular_screendumps = "no" vms = "avocado-vt-vm1" start_vm = no diff --git a/libvirt/tests/cfg/virtual_device/filesystem_device_unprivileged.cfg b/libvirt/tests/cfg/virtiofs/virtiofs_unprivileged.cfg similarity index 93% rename from libvirt/tests/cfg/virtual_device/filesystem_device_unprivileged.cfg rename to libvirt/tests/cfg/virtiofs/virtiofs_unprivileged.cfg index c90f7a48d03..aaf21aee7e4 100644 --- a/libvirt/tests/cfg/virtual_device/filesystem_device_unprivileged.cfg +++ b/libvirt/tests/cfg/virtiofs/virtiofs_unprivileged.cfg @@ -1,5 +1,5 @@ -- virtual_devices.filesystem_device_unprivileged: - type = filesystem_device_unprivileged +- virtiofs.unprivileged: + type = virtiofs_unprivileged # 10.0.0-6 func_supported_since_libvirt_ver = (10, 0, 0) take_regular_screendumps = "no" diff --git a/libvirt/tests/src/virtual_device/filesystem_device.py b/libvirt/tests/src/virtiofs/virtiofs.py similarity index 100% rename from libvirt/tests/src/virtual_device/filesystem_device.py rename to libvirt/tests/src/virtiofs/virtiofs.py diff --git a/libvirt/tests/src/virtual_device/filesystem_device_unprivileged.py b/libvirt/tests/src/virtiofs/virtiofs_unprivileged.py similarity index 100% rename from libvirt/tests/src/virtual_device/filesystem_device_unprivileged.py rename to libvirt/tests/src/virtiofs/virtiofs_unprivileged.py From 4a8325c0e912a7c6150ba163af0264e2bfdd6564 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 9 Apr 2025 08:51:28 +0200 Subject: [PATCH 0927/1055] filesystem_device: skip test on known issue Managedsave for internally launched had an issue before 10.0.0 Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/virtiofs/virtiofs.cfg | 1 + libvirt/tests/src/virtiofs/virtiofs.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/libvirt/tests/cfg/virtiofs/virtiofs.cfg b/libvirt/tests/cfg/virtiofs/virtiofs.cfg index a5ab31c37cb..1668004baff 100644 --- a/libvirt/tests/cfg/virtiofs/virtiofs.cfg +++ b/libvirt/tests/cfg/virtiofs/virtiofs.cfg @@ -105,6 +105,7 @@ - managedsave: no external lifecycle_scenario = "managedsave" + bug_url = https://issues.redhat.com/browse/RHEL-50542 - restart_service: func_supported_since_libvirt_ver = (9, 2, 0) lifecycle_scenario = "restart_service" diff --git a/libvirt/tests/src/virtiofs/virtiofs.py b/libvirt/tests/src/virtiofs/virtiofs.py index 15217d87a58..a4c6ac31e61 100644 --- a/libvirt/tests/src/virtiofs/virtiofs.py +++ b/libvirt/tests/src/virtiofs/virtiofs.py @@ -288,6 +288,9 @@ def check_filesystem_hotplug_with_mem_setup(): if not libvirt_version.version_compare(7, 6, 0) and lifecycle_scenario == "destroy_start": test.cancel("Bug %s is not fixed on current build" % bug_url) + if not libvirt_version.version_compare(10, 0, 0) and lifecycle_scenario == "managed_save": + test.cancel("Bug %s is not fixed on current build" % bug_url) + try: if setup_mem: libvirt_version.is_libvirt_feature_supported(params) From 9a50d9e6b9ddc2730ae3c56d89056fd8826f3c2c Mon Sep 17 00:00:00 2001 From: hholoubk Date: Fri, 3 Jan 2025 14:12:56 +0100 Subject: [PATCH 0928/1055] Implement Xxx 304022 disable pauth cpu feature --- libvirt/tests/cfg/cpu/vcpu_feature.cfg | 16 ++++++++++++++-- libvirt/tests/src/cpu/vcpu_feature.py | 16 +++++++++++----- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/cfg/cpu/vcpu_feature.cfg b/libvirt/tests/cfg/cpu/vcpu_feature.cfg index bb91a5c82d5..2af78e5267b 100644 --- a/libvirt/tests/cfg/cpu/vcpu_feature.cfg +++ b/libvirt/tests/cfg/cpu/vcpu_feature.cfg @@ -3,7 +3,7 @@ start_vm = "no" cpu_check = "full" variants: - - policy_diable: + - policy_disable: feature_policy = "disable" - policy_require: feature_policy = "require" @@ -13,8 +13,19 @@ variants: - positive_test: variants: + - host_with_pauth: + only aarch64 + only policy_disable + func_supported_since_libvirt_ver = (10, 7, 0) + host_supported_feature = "yes" + feature_name = "pauth" + feature_check_name = "paca" + check_vm_feature = "yes" + check_qemu_pattern = "-cpu host,pauth=off" + cpu_check = "none" + start_vm = "yes" - host_with_vmx: - only policy_diable + only policy_disable host_supported_feature = "yes" feature_name = "vmx" check_vm_feature = "yes" @@ -27,3 +38,4 @@ host_supported_feature = "no" feature_name = "cr8legacy" err_msg = "guest CPU doesn't match specification: missing features: .*${feature_name}" + diff --git a/libvirt/tests/src/cpu/vcpu_feature.py b/libvirt/tests/src/cpu/vcpu_feature.py index 709f939f643..2577e31f8d6 100644 --- a/libvirt/tests/src/cpu/vcpu_feature.py +++ b/libvirt/tests/src/cpu/vcpu_feature.py @@ -49,6 +49,7 @@ def update_cpu_xml(): cpu_mode = params.get('cpu_mode', "host-passthrough") cpu_check = params.get('cpu_check', "full") feature_name = params.get('feature_name', "vmx") + feature_check_name = params.get('feature_check_name', feature_name) feature_policy = params.get('feature_policy', "require") host_supported_feature = "yes" == params.get("host_supported_feature", "no") check_vm_feature = "yes" == params.get("check_vm_feature", "no") @@ -58,10 +59,9 @@ def update_cpu_xml(): bkxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) try: - if not libvirt_version.version_compare(6, 0, 0): - test.cancel("Libvirt version is too low for this test.") + libvirt_version.is_libvirt_feature_supported(params) - flags_cmd = "grep -q %s /proc/cpuinfo" % feature_name + flags_cmd = "grep -qw %s /proc/cpuinfo" % feature_check_name res = process.run(flags_cmd, shell=True, ignore_status=True).exit_status if host_supported_feature == bool(res): test.cancel('The host does not support current test!') @@ -75,14 +75,20 @@ def update_cpu_xml(): if err_msg: libvirt.check_result(result, err_msg) + vm_session = None if not status_error and check_vm_feature: vm_session = vm.wait_for_login() res = vm_session.cmd_status(flags_cmd) # TODO: Add checks for other feature policies if feature_policy == "disable": if not res: - test.fail("The vm unexpectedly contains %s flag" - % feature_name) + test.fail("The vm unexpectedly contains %s flag" % feature_name) + + check_qemu_pattern = params.get('check_qemu_pattern', "") + # we don't expect for now negative cases for the check_qemu_pattern + if check_qemu_pattern: + logging.debug(f"TEST_STEP: checking pattern in qemu-kvm command line:{check_qemu_pattern}.") + libvirt.check_qemu_cmd_line(check_qemu_pattern) finally: if vm.is_alive(): From a21ef4d78ca0a237942c1483645ae2820c21d8d2 Mon Sep 17 00:00:00 2001 From: Misbah Anjum N Date: Tue, 11 Feb 2025 02:46:35 -0600 Subject: [PATCH 0929/1055] Add new test case: guest_kdump test The patch introduces guest kernel debugging via kdump mechanism. The script is used to test the kdump functionality of the guest(s). 1. Check if kdump.service is operational 2. Get the vmcores present in the guest 3. Load the stress app if specified 4. Trigger crash simultaneously in all guests 5. Debug vmcore using crash utility if specified Using this patch the followng scenarios can be verified 1. single-guest: a. kdump with no stress b. kdump with stress c. kdump with stress with crash utility 2. multi-guests: a. kdump with no stress b. kdump with stress c. kdump with stress with crash utility Signed-off-by: Misbah Anjum N --- .../guest_kernel_debugging/guest_kdump.cfg | 47 +++ .../src/guest_kernel_debugging/guest_kdump.py | 306 ++++++++++++++++++ 2 files changed, 353 insertions(+) create mode 100644 libvirt/tests/cfg/guest_kernel_debugging/guest_kdump.cfg create mode 100644 libvirt/tests/src/guest_kernel_debugging/guest_kdump.py diff --git a/libvirt/tests/cfg/guest_kernel_debugging/guest_kdump.cfg b/libvirt/tests/cfg/guest_kernel_debugging/guest_kdump.cfg new file mode 100644 index 00000000000..ecd35787550 --- /dev/null +++ b/libvirt/tests/cfg/guest_kernel_debugging/guest_kdump.cfg @@ -0,0 +1,47 @@ +- guest_kernel_debugging.guest_kdump: + type = guest_kdump + main_vm = "avocado-vm" + vms = "vm" + mem = "32768" + take_regular_screendumps = "no" + login_timeout = 240 + guest_stress = "no" + stress_time = "300" + guest_upstream_kernel = "no" + crash_utility = "no" + crash_dir = "/var/crash/" + debug_dir = "/home/" + dump_options = "--memory-only --bypass-cache" + start_vm = "yes" + kill_vm = "yes" + variants: + - kdump_no_stress: + - kdump_with_stress: + guest_stress = "yes" + - kdump_with_stress_crash_utility: + crash_utility = "yes" + guest_stress = "yes" + - two_guests_kdump_no_stress: + vms = "vm1 vm2" + mem = "10000" + - two_guests_kdump_with_stress: + vms = "vm1 vm2" + mem = "10000" + guest_stress = "yes" + - two_guests_kdump_with_stress_crash_utility: + vms = "vm1 vm2" + mem = "10000" + crash_utility = "yes" + guest_stress = "yes" + - four_guests_kdump_no_stress: + vms = "vm1 vm2 vm3 vm4" + mem = "5000" + - four_guests_kdump_with_stress: + vms = "vm1 vm2 vm3 vm4" + mem = "5000" + guest_stress = "yes" + - four_guests_kdump_with_stress_crash_utility: + vms = "vm1 vm2 vm3 vm4" + mem = "5000" + crash_utility = "yes" + guest_stress = "yes" diff --git a/libvirt/tests/src/guest_kernel_debugging/guest_kdump.py b/libvirt/tests/src/guest_kernel_debugging/guest_kdump.py new file mode 100644 index 00000000000..c64e5a8e9b6 --- /dev/null +++ b/libvirt/tests/src/guest_kernel_debugging/guest_kdump.py @@ -0,0 +1,306 @@ +import time +import threading +import logging as log + +from virttest import utils_test +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from aexpect.exceptions import ShellProcessTerminatedError +from aexpect.exceptions import ShellTimeoutError + + +# 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__) + + +def run(test, params, env): + """ + Test: Kdump of guest + + param test: kvm test object + param params: Dictionary with the test parameters + param env: Dictionary with test environment. + + This script is used to test the kdump functionality of the guest(s). + 1. Check if kdump.service is operational + 2. Get the vm-cores present in the guest + 3. Load the stress app if specified + 4. Trigger crash simultaneously in all guests + 5. Debug vm-core using crash utility if specified + """ + vms = env.get_all_vms() + guest_stress = params.get("guest_stress", "no") == "yes" + guest_upstream_kernel = params.get("guest_upstream_kernel", "no") == "yes" + crash_utility = params.get("crash_utility", "no") == "yes" + stress_time = params.get("stress_time", "30") + crash_dir = params.get("crash_dir", "/var/crash/") + debug_dir = params.get("debug_dir", "/home/") + dump_options = params.get("dump_options", "--memory-only --bypass-cache") + trigger_crash_cmd = "echo c > /proc/sysrq-trigger" + + def check_kdump_service(vm): + """ + Check if kdump.service is running + Current supported Distros: rhel, fedora, ubuntu + + param vm: vm object + returns: None + """ + # Set command based on different distros + logging.info("Checking for kdump.service in guest %s" % vm.name) + session = vm.wait_for_login(timeout=240) + distro_details = session.cmd("cat /etc/os-release").lower() + check_kdump_cmd = "" + if "fedora" in distro_details or "rhel" in distro_details: + check_kdump_cmd = "kdumpctl status" + elif "ubuntu" in distro_details: + check_kdump_cmd = "kdump-config status" + else: + test.cancel("Guest distro not supported") + + # Check the kdump.service status + check_kdump_status, check_kdump = session.cmd_status_output(check_kdump_cmd) + if check_kdump_status: + logging.debug("Kdump service status: %s" % check_kdump) + test.error("Kdump service is not running in guest %s" % vm.name) + logging.info("Kdump service is up and running:\n%s" % check_kdump) + session.close() + + def get_vmcores(vm): + """ + Get vm-cores present in the crash directory + + param vm: vm object + returns: list of vm-cores + """ + logging.info("Getting vmcores in the guest %s" % vm.name) + session = vm.wait_for_login(timeout=100) + get_vmcores_cmd = "ls " + crash_dir + vmcores = session.cmd(get_vmcores_cmd).split() + session.close() + return vmcores + + def check_guest_status(vm): + """ + Check guest domstate. Guest should be running at all times. + + param vm: vm object + returns: + 1. 0 if guest is running + 2. 1 if guest is not running + """ + logging.info("Checking domstate of guest %s" % vm.name) + if vm.state() != "running": + logging.debug("Domain is not running: %s" % vm.state()) + return 1 + return 0 + + def trigger_crash(vm, session): + """ + Trigger sysrq triggered crash in guest + + param vm: vm object + param session: session object + returns: None + """ + logging.info("Triggering sysrq crash in guest %s" % vm.name) + try: + session.cmd(trigger_crash_cmd) + except ShellProcessTerminatedError: + time.sleep(120) + session.close() + + def load_guest_stress(vms): + """ + Load stress app in all the vms + + param vms: all vm objects + returns: None + """ + logging.info("Starting stress app in guest(s)") + try: + utils_test.load_stress("stress_in_vms", params=params, vms=vms) + except Exception as err: + test.fail("Error running stress in vms: %s" % str(err)) + + def unload_guest_stress(vms): + """ + Unload stress app in all the vms + + param vms: all vm objects + returns: None + """ + logging.info("Stopping stress app in guest(s)") + utils_test.unload_stress("stress_in_vms", params=params, vms=vms) + + def virsh_dump(failed_vms): + """ + Take virsh dump of guest in case of guest failure + + param failed_vms: vm objects which are failed/broken + returns: None + """ + logging.info("Dumping failed vms to directory %s" % debug_dir) + for vm in failed_vms: + if vm.state() != "shut off": + logging.debug("Dumping %s to debug_dir %s" % (vm.name, debug_dir)) + virsh.dump(vm.name, debug_dir+vm.name+"-core", + dump_options, ignore_status=False, + debug=True) + logging.debug("Successfully dumped %s as %s-core" % (vm.name, vm.name)) + else: + logging.debug("Cannot dump %s as it is in shut off state" % vm.name) + + def crash_utility_tool(vm, vmcore): + """ + Check the working of crash utility tool to analyse the guest dump + Current supported Distros: rhel, fedora, ubuntu + + param vm: vm object + param vm-core: guest vm-core file + returns: None + """ + logging.info("Debugging %s vmcore using crash utility" % vm.name) + session = vm.wait_for_login(timeout=100) + debug_libraries = [] + vmcore_file = crash_dir + vmcore + "/vmcore" + distro_details = session.cmd("cat /etc/os-release").lower() + guest_kernel = session.cmd("uname -r").strip() + + # Get required debug libraries based on distros + if "fedora" in distro_details or "rhel" in distro_details: + debug_libraries = ["*kexec-tools*", "*elfutils*", "*crash*", "*kdump-utils*"] + if not guest_upstream_kernel: + debug_libraries.append("*kernel-debuginfo*") + elif "ubuntu" in distro_details: + debug_libraries = ["*linux-crashdump*", "*kdump-tools*", "*crash*", "*elfutils*"] + else: + test.cancel("Guest distro not supported") + + # Check if required debug libraries are installed + not_installed_libs = set() + for library in debug_libraries: + get_library_cmd = "rpm -qa " + library + output = session.cmd(get_library_cmd).split() + if not output: + not_installed_libs.add(library) + if not_installed_libs: + test.error("Debug libraries not installed in %s: %s" % (vm.name, not_installed_libs)) + session.close() + + # Get debug kernel location based on distros + if "fedora" in distro_details or "rhel" in distro_details: + vmlinux = "/usr/lib/debug/lib/modules/" + guest_kernel + "/vmlinux" + elif "ubuntu" in distro_details: + vmlinux = "/usr/lib/debug/boot/vmlinux-" + guest_kernel + else: + test.cancel("Guest distro not supported") + if guest_upstream_kernel: + vmlinux = params.get("upstream_kernel_vmlinux", vmlinux) + + # Run the crash utility tool + session = vm.wait_for_login(timeout=100) + crash_cmd = f"crash {vmlinux} {vmcore_file}" + crash_log = "" + logging.debug("Crash command: %s", crash_cmd) + try: + session.cmd(crash_cmd) + except ShellTimeoutError: + crash_log = session.get_output() + session.close() + + logging.debug("Crash utility output: %s" % crash_log) + if "PID" not in crash_log or "crash>" not in crash_log: + test.fail("Failed to debug %s vmcore using crash utiility" % vm.name) + + # Declaring variables before starting test + failed_vms = set() + virsh_dump_vms = set() + + # Set on_crash value to preserve in guests + for vm in vms: + logging.info("Setting on_crash to preserve in %s" % vm.name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) + if vm.is_alive(): + vm.destroy(gracefully=False) + vmxml.on_crash = "restart" + vmxml.sync() + vm.start() + + # Check for kdump service if it is operational + for vm in vms: + check_kdump_service(vm) + + # Check for the present vm-cores in guests + pre_vmcores = {} + for vm in vms: + pre_vmcores[vm.name] = get_vmcores(vm) + logging.info("%s vmcores before crash: %s" % (vm.name, pre_vmcores[vm.name])) + + # Load the stress app + if guest_stress: + load_guest_stress(vms) + logging.info("Started running stress app") + logging.info("Sleeping for %s seconds" % stress_time) + time.sleep(int(stress_time)) + + for vm in vms: + if check_guest_status(vm): + failed_vms.add(vm.name) + virsh_dump_vms.add(vm) + if failed_vms: + virsh_dump(virsh_dump_vms) + test.fail("Guest %s not running after running stress" % failed_vms) + + # Trigger crash in guests in parallel + kdump_threads = [] + for vm in vms: + kdump_threads.append( + threading.Thread(target=trigger_crash, args=(vm, vm.wait_for_login(timeout=100))) + ) + time.sleep(20) + for kdump_thread in kdump_threads: + kdump_thread.start() + for kdump_thread in kdump_threads: + kdump_thread.join() + + # Check guest status after crash + for vm in vms: + try: + if check_guest_status(vm): + raise Exception("Guest %s not running after triggering crash" % vm.name) + session = vm.wait_for_login(timeout=240) + logging.info("Able to login into %s" % vm.name) + session.close() + except Exception as err: + logging.debug("Error occured %s" % str(err)) + failed_vms.add(vm.name) + virsh_dump_vms.add(vm) + if failed_vms: + virsh_dump(virsh_dump_vms) + test.fail("Unable to login into %s after triggering crash" % failed_vms) + + # Check for the vm-cores in guests after crash + post_vmcores = {} + for vm in vms: + post_vmcores[vm.name] = get_vmcores(vm) + logging.info("%s vmcores after crash: %s" % (vm.name, post_vmcores[vm.name])) + + # Check if vm-core got generated after crash in guests + for vm in vms: + if len(post_vmcores[vm.name]) <= len(pre_vmcores[vm.name]): + failed_vms.add(vm.name) + if failed_vms: + test.fail("vmcore not generated in %s" % failed_vms) + + # Debug vm-core using crash utility tool + if crash_utility: + for vm in vms: + for vmcore_file in pre_vmcores[vm.name]: + post_vmcores[vm.name].remove(vmcore_file) + crash_utility_tool(vm, post_vmcores[vm.name][-1]) + + # Unload the stress app in guests + if guest_stress: + unload_guest_stress(vms) From a437c62de67f8e726d1860b3e3044b988891e19a Mon Sep 17 00:00:00 2001 From: Misbah Anjum N Date: Tue, 21 Jan 2025 03:02:02 -0600 Subject: [PATCH 0930/1055] virsh-dump: Add Crash Utility Tests for vmcore This Patch adds support for testing Crash Utility for vmcore generated by "virsh dump" command. Crash Utility is a tool that allows us to interactively analyze a running Linux system as well as a core dump created. This crash_utility function works as following: Returns: 0: Success 1: Crash command failed 2: Dependency installation failed or vmlinux not found 3: Kernel mismatch between host and guest 4: Guest kernel retrieval failed 5: Unsupported distribution 6: virsh dump unsuccessful Signed-off-by: Misbah Anjum N --- .../cfg/guest_kernel_debugging/virsh_dump.cfg | 18 ++ .../src/guest_kernel_debugging/virsh_dump.py | 204 +++++++++++++++--- 2 files changed, 196 insertions(+), 26 deletions(-) diff --git a/libvirt/tests/cfg/guest_kernel_debugging/virsh_dump.cfg b/libvirt/tests/cfg/guest_kernel_debugging/virsh_dump.cfg index 3131aa58995..117e3c5c5c0 100644 --- a/libvirt/tests/cfg/guest_kernel_debugging/virsh_dump.cfg +++ b/libvirt/tests/cfg/guest_kernel_debugging/virsh_dump.cfg @@ -98,3 +98,21 @@ - no_space_left: dump_options = "--memory-only" dump_dir = "/var/tmp/too_small" + - crash_utility_tests: + crash_utility = "yes" + variants: + - memory_dump: + dump_options = "--memory-only" + variants: + - elf_format: + memory_dump_format = 'elf' + - kdump-zlib_format: + memory_dump_format = 'kdump-zlib' + - kdump-lzo_format: + memory_dump_format = 'kdump-lzo' + - kdump-snappy_format: + memory_dump_format = 'kdump-snappy' + - memory_crash_dump: + dump_options = "--crash --memory-only" + - memory_bypass_cache_dump: + dump_options = "--memory-only --bypass-cache --verbose" diff --git a/libvirt/tests/src/guest_kernel_debugging/virsh_dump.py b/libvirt/tests/src/guest_kernel_debugging/virsh_dump.py index 2870d8aeee3..a381735f56c 100644 --- a/libvirt/tests/src/guest_kernel_debugging/virsh_dump.py +++ b/libvirt/tests/src/guest_kernel_debugging/virsh_dump.py @@ -4,7 +4,11 @@ import time import platform import re +import pexpect + from avocado.utils import process +from avocado.utils.software_manager.manager import SoftwareManager +from avocado.utils import distro from virttest import virsh from virttest import utils_libvirtd @@ -195,6 +199,131 @@ def check_dump_format(dump_image_format, dump_file): else: return True + def crash_utility(dump_file, vm): + """ + Check the working of crash utility tool to analyse the guest dump + + In order for the function to work, both the guest and the host must + have the same kernel + If crash tool or kernel debug libraries are not installed, the function + returns error + If crash tool cannot read into the vm-core, the function returns fail + If crash tool can read the vm-core, the function returns true + + Returns: + 0: Success + 1: Crash command failed + 2: Dependency installation failed or debug kernel not found + 3: Kernel mismatch between host and guest + 4: Guest kernel retrieval failed + 5: Unsupported distribution + 6: virsh dump unsuccessful + """ + def get_guest_kernel(vm): + """ + Login into the guest and get guest kernel + """ + try: + session = vm.wait_for_login(timeout=240) + except: + logging.error("Error Logging into the guest") + return "" + guest_kernel = session.cmd("uname -r") + session.close() + return guest_kernel + + logging.debug("Crash Utility to Analyse Dump") + + # Get guest and host kernel to verify if it is same + guest_kernel = get_guest_kernel(vm).strip() + host_kernel = platform.release().strip() + if not guest_kernel: + return 4 + if guest_kernel != host_kernel: + logging.error("Kernel mismatch") + logging.error("Host Kernel: %s", host_kernel) + logging.error("Guest Kernel: %s", guest_kernel) + return 3 + + # Get distro version to check for respective libraries + smm = SoftwareManager() + detected_distro = distro.detect() + distro_name = detected_distro.name.lower() + upstream_kernel = params.get("upstream_kernel", "no") == "yes" + + # Check for required debug tools and libraries + if distro_name in ("fedora", "rhel"): + deps = ["kexec-tools", "elfutils", "crash"] + if not upstream_kernel: + deps.append("kernel-debuginfo") + elif distro_name in ("ubuntu"): + deps = ["linux-crashdump", "kdump-tools", "crash", "elfutils"] + if not upstream_kernel: + deps.append("linux-image-debug") + elif distro_name in ("suse", "sles"): + deps = ["elfutils", "crash"] + if not upstream_kernel: + deps.append("linux-image-debug") + else: + return 5 + for package in deps: + if not smm.check_installed(package) and not smm.install(package): + logging.error("Failed to install dependency: %s", package) + return 2 + + # Check if debug kernel is present + if distro_name in ("fedora", "rhel"): + vmlinux = "/usr/lib/debug/lib/modules/" + host_kernel + "/vmlinux" + elif distro_name in ("ubuntu", "suse", "sles"): + vmlinux = "/usr/lib/debug/boot/vmlinux-" + host_kernel + else: + return 5 + if upstream_kernel: + vmlinux = params.get("upstream_kernel_vmlinux", vmlinux) + if not os.path.isfile(vmlinux): + logging.error("vmlinux not found") + return 2 + + # Collect guest vm-core + try: + virsh.dump(vm_name, dump_file, options, + ignore_status=True, debug=True) + except: + return 6 + + # Run Crash Utility + crash_cmd = f"crash {vmlinux} {dump_file}" + logging.debug("Crash command: %s", crash_cmd) + try: + # Spawn the crash command + child = pexpect.spawn(crash_cmd, timeout=100) + child.expect("crash> ") + stdout = child.before.decode('utf-8') + logging.debug("Crash tool output: %s", stdout.strip()) + + # Send the back-trace command and capture output + child.sendline("bt | head") + child.expect("crash> ") + stdout = child.before.decode('utf-8') + + # Check if the back-trace produced output + if "PID" in stdout or "TASK" in stdout: + logging.info("Crash tool is working correctly.") + logging.debug("Crash tool bt output: %s", stdout.strip()) + return 0 + else: + logging.error("Crash tool did not produce expected output.") + logging.debug("Crash tool output: %s", stdout.strip()) + return 1 + + except pexpect.TIMEOUT: + logging.error("Crash command timed out.") + return 1 + + except Exception as e: + logging.error("An error occurred while running the crash command: %s", e) + return 1 + # Configure dump_image_format in /etc/libvirt/qemu.conf. qemu_config = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() @@ -282,34 +411,57 @@ def check_dump_format(dump_image_format, dump_file): libvirt.mkfs(small_img, "ext3") os.mkdir(dump_dir) utils_misc.mount(small_img, dump_dir, None) - # Run virsh command - cmd_result = virsh.dump(vm_name, dump_file, options, - unprivileged_user=unprivileged_user, - uri=uri, - ignore_status=True, debug=True) - status = cmd_result.exit_status - if 'child_process' in locals(): - child_process.join(timeout=check_bypass_timeout) - params['bypass'] = result_dict['bypass'] - - logging.info("Start check result") - time.sleep(5) - if not check_domstate(vm.state(), options): - test.fail("Domain status check fail.") - if status_error: - if not status: - test.fail("Expect fail, but run successfully") + + # Check for Crash Utility test + crash_utility_test = params.get("crash_utility", "no") == "yes" + + if not crash_utility_test: + # Run virsh command + cmd_result = virsh.dump(vm_name, dump_file, options, + unprivileged_user=unprivileged_user, + uri=uri, + ignore_status=True, debug=True) + status = cmd_result.exit_status + if 'child_process' in locals(): + child_process.join(timeout=check_bypass_timeout) + params['bypass'] = result_dict['bypass'] + + logging.info("Start check result") + time.sleep(5) + if not check_domstate(vm.state(), options): + test.fail("Domain status check fail.") + if status_error: + if not status: + test.fail("Expect fail, but run successfully") + else: + if status: + test.fail("Expect succeed, but run fail") + if not os.path.exists(dump_file): + test.fail("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: + test.fail("The format of dumped file is wrong.") + if params.get('bypass'): + test.fail(params['bypass']) + else: - if status: - test.fail("Expect succeed, but run fail") - if not os.path.exists(dump_file): - test.fail("Fail to find domain dumped file.") - if check_dump_format(dump_image_format, dump_file): - logging.info("Successfully dump domain to %s", dump_file) + crash_tool = crash_utility(dump_file, vm) + if crash_tool == 6: + test.fail("Unable to collect guest vmcore") + if crash_tool == 5: + test.cancel("Test unsupported for distro") + if crash_tool == 4: + test.error("Guest login issue. Unable to get guest kernel version") + if crash_tool == 3: + test.cancel("Guest and Host kernel are different") + elif crash_tool == 2: + test.error("Required debug libraries/tools not installed") + elif crash_tool == 1: + test.fail("Unable to analyse guest vmcore using crash") else: - test.fail("The format of dumped file is wrong.") - if params.get('bypass'): - test.fail(params['bypass']) + logging.info("Able to analyse guest vmcore using crash") + finally: backup_xml.sync() qemu_config.restore() From 6ed819e018831d94b7bbd91f8cd66af697f31ac8 Mon Sep 17 00:00:00 2001 From: meinaLi Date: Wed, 9 Apr 2025 23:20:04 -0400 Subject: [PATCH 0931/1055] Scsi_device: automate 1 new case for rawio attribute Automate case: VIRT-302169 - [virtual disks] [SCSI]Start vm with block lun disk(scsi-block) and rawio attribute Signed-off-by: meinaLi --- .../tests/cfg/scsi/scsi_disk_attributes.cfg | 13 +++++ .../tests/src/scsi/scsi_disk_attributes.py | 56 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 libvirt/tests/cfg/scsi/scsi_disk_attributes.cfg create mode 100644 libvirt/tests/src/scsi/scsi_disk_attributes.py diff --git a/libvirt/tests/cfg/scsi/scsi_disk_attributes.cfg b/libvirt/tests/cfg/scsi/scsi_disk_attributes.cfg new file mode 100644 index 00000000000..b5e66db8000 --- /dev/null +++ b/libvirt/tests/cfg/scsi/scsi_disk_attributes.cfg @@ -0,0 +1,13 @@ +- scsi_device.scsi_disk_attributes.rawio: + type = scsi_disk_attributes + start_vm = no + target_disk = "sdb" + disk_type = "block" + variants: + - rawio_yes: + rawio_value = "yes" + expected_xpaths = [{'element_attrs': [".//disk[@rawio='yes']"]}] + - rawio_no: + rawio_value = "no" + expected_xpaths = [{'element_attrs': [".//disk[@rawio='no']"]}] + disk_dict = {'target': {'dev': '${target_disk}', 'bus': 'scsi'}, 'driver': {'name': 'qemu', 'type': 'raw'}, 'device': 'lun', 'sgio': 'filtered', 'rawio': '${rawio_value}', 'type_name': 'block', 'source': {'attrs': {'dev': '%s'}}} diff --git a/libvirt/tests/src/scsi/scsi_disk_attributes.py b/libvirt/tests/src/scsi/scsi_disk_attributes.py new file mode 100644 index 00000000000..24dd7bdb6cd --- /dev/null +++ b/libvirt/tests/src/scsi/scsi_disk_attributes.py @@ -0,0 +1,56 @@ +from avocado.utils import process + +from virttest import virsh +from virttest import utils_disk +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml, libvirt_disk +from virttest.utils_test import libvirt + + +def run(test, params, env): + """ + This case is to verify starting the guest with scsi disk with different attributes. + """ + def check_result(): + """ + Check the result in host and guest. + """ + test.log.debug("The current guest xml is %s", virsh.dumpxml(vm_name).stdout_text) + test.log.info("TEST_STEP2: check the guest xml.") + xml_after_adding_device = vm_xml.VMXML.new_from_dumpxml(vm_name) + libvirt_vmxml.check_guest_xml_by_xpaths(xml_after_adding_device, expected_xpaths) + test.log.info("TEST_STEP3: check the result in host and guest.") + vm_session = vm.wait_for_login() + cap_result = process.run("getpcaps `pidof qemu-kvm`", shell=True).stdout_text.strip() + new_disk = libvirt_disk.get_non_root_disk_name(vm_session)[0] + utils_disk.dd_data_to_vm_disk(vm_session, new_disk) + _, sg_result = vm_session.cmd_status_output("sg_persist -v /dev/%s" % new_disk) + vm_session.close() + if rawio_value == "yes": + if "cap_sys_rawio" not in cap_result or "registered reservation keys" not in sg_result: + test.fail("The rawio capability doesn't work as expected.") + if rawio_value == "no": + if "cap_sys_rawio" in cap_result or "aborted command" not in sg_result.lower(): + test.fail("Shouldn't get the rawio capability.") + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + disk_type = params.get("disk_type") + rawio_value = params.get("rawio_value") + expected_xpaths = eval(params.get("expected_xpaths")) + + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + backup_xml = vmxml.copy() + + try: + test.log.info("TEST_STEP1: start the guest with scsi disk.") + device_name = libvirt.setup_or_cleanup_iscsi(is_setup=True) + disk_dict = eval(params.get("disk_dict", "{}") % device_name) + disk_obj = libvirt_vmxml.create_vm_device_by_type("disk", disk_dict) + libvirt.add_vm_device(vmxml, disk_obj) + if not vm.is_alive(): + vm.start() + check_result() + finally: + backup_xml.sync() + libvirt.setup_or_cleanup_iscsi(is_setup=False) From 8c9867949f95eeb85a413fc3396c7f6a1e35a1cb Mon Sep 17 00:00:00 2001 From: Tasmiya Nalatwad Date: Wed, 18 Sep 2024 14:56:49 +0530 Subject: [PATCH 0932/1055] Replacing Dmidecode with lshw package As dmidecode is not available in ppc64 , removing it and replacing it with lshw as lshw is a standard way to get the resources details on ppc64 arch Keeping dmidecide for other arch Signed-off-by: Tasmiya Nalatwad --- libvirt/tests/src/memory/virsh_setmem.py | 55 ++++++++++++++++++++---- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/libvirt/tests/src/memory/virsh_setmem.py b/libvirt/tests/src/memory/virsh_setmem.py index 19864e03b99..74d1f04a741 100644 --- a/libvirt/tests/src/memory/virsh_setmem.py +++ b/libvirt/tests/src/memory/virsh_setmem.py @@ -1,6 +1,7 @@ import re import os import logging as log +import platform import time from virttest import virsh @@ -119,6 +120,30 @@ def vm_unusable_mem(session): total_physical_mem += mem_size * 1048576 return total_physical_mem - get_vm_usable_mem(session) + def vm_unusable_mem_ppc64(session): + """ + Get the unusable RAM of the VM for Arch PPC64. + """ + # Get total physical memory from lshw + cmd = "lshw -C memory" + lshw_mem = session.cmd_output(cmd) + lshw_mem_size = re.findall(r'\*-\s*memory\s*[\s\S]*?size:\s*(\d+[K|M|G]iB)', lshw_mem) + if not lshw_mem_size: + test.fail("Cannot get memory size info inside VM.") + total_physical_mem = 0 + for mem in lshw_mem_size: + size_value = re.match(r'(\d+)\s*([K|M|G]iB)', mem) + if size_value: + mem_size = int(size_value.group(1)) # Convert the numeric part to an integer + mem_unit = size_value.group(2) + if mem_unit.lower() == "kib": + total_physical_mem += mem_size + elif mem_unit.lower() == "mib": + total_physical_mem += mem_size * 1024 + elif mem_unit.lower() == "gib": + total_physical_mem += mem_size * 1048576 + return total_physical_mem - get_vm_usable_mem(session) + def make_domref(domarg, vm_ref, domid, vm_name, domuuid): """ Create domain options of command @@ -266,7 +291,8 @@ def print_debug_stats( 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") + use_pkg = "yes" == params.get("use_dmidecode", "yes") + arch = platform.machine() vm = env.get_vm(vm_name) # Back up domain XML @@ -357,15 +383,26 @@ def print_debug_stats( if not vm.is_alive(): vm.start() session = vm.wait_for_login() - 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) + if arch != "ppc64le": + if use_pkg: + # try make dmidecode or lshw available if not present + use_pkg &= 0 == session.cmd_status( + "dmidecode" + ) or utils_package.package_install("dmidecode", session) + if use_pkg: + unusable_mem = vm_unusable_mem(session) + else: + unusable_mem = int(vmxml.memory) - get_vm_usable_mem(session) else: - unusable_mem = int(vmxml.memory) - get_vm_usable_mem(session) + if use_pkg: + # try make dmidecode or lshw available if not present + use_pkg &= 0 == session.cmd_status( + "lshw" + ) or utils_package.package_install("lshw", session) + if use_pkg: + unusable_mem = vm_unusable_mem_ppc64(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() From ae62b9bd0529c5d3295c6e3970ed128791147df9 Mon Sep 17 00:00:00 2001 From: Fangge Jin Date: Thu, 20 Feb 2025 18:22:57 +0800 Subject: [PATCH 0933/1055] Add test cases for live updating iothread_vq_mapping Signed-off-by: Fangge Jin --- .../virtual_disks_iothreads_queue.cfg | 38 +++++++++++ .../virtual_disks_iothreads_queue.py | 64 +++++++++++++------ 2 files changed, 84 insertions(+), 18 deletions(-) diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg index 8d0518e1cd1..cd6c4ffa11c 100755 --- a/libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg @@ -78,6 +78,44 @@ del_iothread_id = 2 check_qemu_pattern = err_msg = "cannot remove IOThread ${del_iothread_id} since it is being used by disk" + - live_update_disk: + func_supported_since_libvirt_ver = (10, 10, 0) + check_qemu_pattern = + status_error = yes + err_msg = "error: Operation not supported: cannot modify field '' \(or it's parts\) of the disk*" + variants: + - change_none_to_roundrobin: + only coldplug..round_robin + driver = {'name': 'qemu', 'type': 'qcow2'} + driver_iothreads = {} + new_driver_iothreads = {'iothread': [{'id': '1'}, {'id': '2'}]} + - add_iothreadid_to_mapping: + only coldplug..round_robin + driver = {'name': 'qemu', 'type': 'qcow2'} + driver_iothreads = {'iothread': [{'id': '1'}, {'id': '2'}]} + new_driver_iothreads = {'iothread': [{'id': '1'}, {'id': '2'}, {'id': '3'}]} + - del_iothreadid_from_mapping: + only coldplug..round_robin + driver = {'name': 'qemu', 'type': 'qcow2'} + driver_iothreads = {'iothread': [{'id': '1'}, {'id': '2'}, {'id': '3'}]} + new_driver_iothreads = {'iothread': [{'id': '1'}, {'id': '2'}]} + - change_roundrobin_to_userdefined: + only coldplug..round_robin + driver = {'name': 'qemu', 'type': 'qcow2', 'queues': '3'} + driver_iothreads = {'iothread': [{'id': '1'}, {'id': '2'}, {'id': '3'}]} + new_driver_iothreads = {'iothread': [{'queue': [{'id': '0'}], 'id': '1'}, {'queue': [{'id': '1'}], 'id': '2'}, {'queue': [{'id': '2'}], 'id': '3'}]} + - change_iothreadid_vqid_mapping: + only coldplug..user_defined + driver = {'name': 'qemu', 'type': 'qcow2', 'queues': '3'} + driver_iothreads = {'iothread': [{'queue': [{'id': '0'}], 'id': '1'}, {'queue': [{'id': '1'}], 'id': '2'}, {'queue': [{'id': '2'}], 'id': '3'}]} + new_driver_iothreads = {'iothread': [{'queue': [{'id': '0'}], 'id': '1'}, {'queue': [{'id': '2'}], 'id': '2'}, {'queue': [{'id': '1'}], 'id': '3'}]} + - change_nothing: + only coldplug..user_defined + status_error = no + driver = {'name': 'qemu', 'type': 'qcow2', 'queues': '3'} + driver_iothreads = {'iothread': [{'queue': [{'id': '0'}], 'id': '1'}, {'queue': [{'id': '1'}], 'id': '2'}, {'queue': [{'id': '2'}], 'id': '3'}]} + new_driver_iothreads = {'iothread': [{'queue': [{'id': '0'}], 'id': '1'}, {'queue': [{'id': '1'}], 'id': '2'}, {'queue': [{'id': '2'}], 'id': '3'}]} + err_msg = "" variants plug_type: - coldplug: - hotplug: diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_iothreads_queue.py b/libvirt/tests/src/virtual_disks/virtual_disks_iothreads_queue.py index d1882905a87..5d6f7414b20 100755 --- a/libvirt/tests/src/virtual_disks/virtual_disks_iothreads_queue.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_iothreads_queue.py @@ -254,14 +254,34 @@ def run_test_define_start(vm, params, vmxml, test): def run_test_update_delete_iothread(vm, params, vmxml, test): """ - Test to delete an iothread being used by a disk and - update the disk with new driver iothreads information + Test to delete an iothread being used by a disk :param vm: vm instance :param params: dict, test parameters :param vmxml: VMXML instance :param test: test object """ + vm_name = params.get("main_vm") + err_msg = params.get("err_msg") + del_iothread_id = params.get("del_iothread_id") + virsh_dargs = {"debug": True, "ignore_status": True} + + run_common(params, vmxml, test) + test.log.debug("Step: delete an iothread") + ret = virsh.iothreaddel(vm_name, del_iothread_id, **virsh_dargs) + libvirt.check_result(ret, expected_fails=err_msg) + + +def run_test_live_update_disk(vm, params, vmxml, test): + """ + Test to live update iothread_vq_mapping of a disk. + + :param vm: vm instance + :param params: dict, test parameters + :param vmxml: VMXML instance + :param test: test object + """ + def _get_driver_iothreads(vmxml): """ Utility function for getting the device object and driver iothreads @@ -269,39 +289,47 @@ def _get_driver_iothreads(vmxml): :param vmxml: VMXML instance :return tuple: device xml object, dict of driver_iothreads """ - dev_obj, _ = libvirt.get_vm_device(vmxml, 'disk') - iothreads = dev_obj.driver_iothreads + dev_obj, _ = libvirt.get_vm_device(vmxml, "disk") + iothreads = None + if dev_obj.fetch_attrs().get("driver_iothreads") is not None: + iothreads = dev_obj.driver_iothreads return dev_obj, iothreads vm_name = params.get("main_vm") + status_error = "yes" == params.get("status_error", "no") err_msg = params.get("err_msg") - del_iothread_id = params.get("del_iothread_id") old_driver_iothreads = eval(params.get("driver_iothreads")) new_driver_iothreads = eval(params.get("new_driver_iothreads")) virsh_dargs = {"debug": True, "ignore_status": True} run_common(params, vmxml, test) - test.log.debug("Step: delete an iothread") - ret = virsh.iothreaddel(vm_name, del_iothread_id, **virsh_dargs) - libvirt.check_result(ret, expected_fails=err_msg) - test.log.debug("Step: update the disk with new driver iothreads") dev_obj, iothreads = _get_driver_iothreads(vmxml) iothreads.update(**new_driver_iothreads) dev_obj.driver_iothreads = iothreads - test.log.debug("After updated with driver iothreads, " - "the disk is:\n%s", dev_obj) + test.log.debug("The new disk xml is:\n%s", dev_obj) ret = virsh.update_device(vm_name, dev_obj.xml, **virsh_dargs) updated_vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) _, new_iothreads = _get_driver_iothreads(updated_vmxml) - if new_iothreads.fetch_attrs() != old_driver_iothreads: - test.fail("Expect driver iothreads in the disk " - "to be '%s', but found '%s'" % (old_driver_iothreads, - new_iothreads.fetch_attrs())) + if new_iothreads is None and old_driver_iothreads != {}: + test.fail( + "Expect driver iothreads in the disk " + "to be '%s', but found None" % (old_driver_iothreads) + ) + elif ( + new_iothreads is not None + and new_iothreads.fetch_attrs() != old_driver_iothreads + ): + test.fail( + "Expect driver iothreads in the disk " + "to be '%s', but found '%s'" + % (old_driver_iothreads, new_iothreads.fetch_attrs()) + ) else: - test.log.debug("Verify: the disk's driver iothreads " - "is not changed - PASS") - libvirt.check_exit_status(ret, True) + test.log.debug("Verify: the disk's driver iothreads is not changed - PASS") + libvirt.check_exit_status(ret, status_error) + if err_msg: + libvirt.check_result(ret, expected_fails=err_msg) def run(test, params, env): From 592fafb9bb38d97fcf47b986dbeff7318b6bc7f7 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Fri, 11 Apr 2025 08:12:59 -0400 Subject: [PATCH 0934/1055] libvirt_ccw_passthrough: relax test condition There have been changes in the kernel so that now, sometimes a device would show up, other times it wouldn't. The test case was motivated by a critical issue where removing all channel paths led to an unusable system. Let's reduce our test condition to that. Signed-off-by: Sebastian Mitterle --- .../ccw/libvirt_ccw_passthrough.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py b/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py index 581401da42b..d9f14bfa9f1 100644 --- a/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py +++ b/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py @@ -27,6 +27,21 @@ def _mdev_listed(): return _mdev_listed +def guest_is_responsive(session): + """ + Executes a simple command on the guest and handles errors. + + :param session: logged in guest console session + :return True: if all works well, False if not + """ + try: + cmd_status_output("ls", session=session, ignore_status=False) + return True + except Exception as e: + logging.debug(f"failed to execute command: {e}") + return False + + def run(test, params, env): """ Test for CCW, esp. DASD disk passthrough on s390x. @@ -68,8 +83,8 @@ def run(test, params, env): if device_removal_case: ChannelPaths.set_standby(chpids) - if ccw.device_is_listed(session, chpids): - test.fail("Device must not be visible inside guest") + if not guest_is_responsive(session): + test.fail("Guest and host must be responsive if device removed.") vm.destroy() ChannelPaths.set_online(chpids) From e164e20ea85d83b15b1403599d8fab1e54f267d4 Mon Sep 17 00:00:00 2001 From: zhentang-tz Date: Mon, 31 Mar 2025 23:56:16 -0400 Subject: [PATCH 0935/1055] domstats: fix failure by adding sched_schedstats fix domstats failures by adding "echo 1 > /proc/sys/kernel/sched_schedstats" before domststs command Signed-off-by: zhentang-tz --- libvirt/tests/src/virsh_cmd/monitor/virsh_domstats.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/monitor/virsh_domstats.py b/libvirt/tests/src/virsh_cmd/monitor/virsh_domstats.py index c5f0780c94a..7b00d904c78 100644 --- a/libvirt/tests/src/virsh_cmd/monitor/virsh_domstats.py +++ b/libvirt/tests/src/virsh_cmd/monitor/virsh_domstats.py @@ -13,7 +13,7 @@ from virttest.libvirt_xml.devices.panic import Panic from virttest import libvirt_version - +from avocado.utils import process # Using as lower capital is not the best way to do, but this is just a # workaround to avoid changing the entire file. @@ -355,6 +355,8 @@ def run(test, params, env): if "--iothread" in domstats_option: add_iothread(vm_list, iothread_add_ids) # Run virsh command + process.run("echo 1 > /proc/sys/kernel/sched_schedstats", shell=True) + logging.debug("enable sched_schedstats success") result = virsh.domstats(vm_list, domstats_option, ignore_status=True, debug=True) status = result.exit_status From 9716ccb808e5d11d96ecb5822e54fa3172b67b89 Mon Sep 17 00:00:00 2001 From: hholoubk Date: Mon, 14 Apr 2025 10:13:58 +0200 Subject: [PATCH 0936/1055] resolving skipped cases: 56145 --- .../sysconfig_libvirt_guests/libvirt_guests.cfg | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/libvirt/tests/cfg/daemon/conf_file/sysconfig_libvirt_guests/libvirt_guests.cfg b/libvirt/tests/cfg/daemon/conf_file/sysconfig_libvirt_guests/libvirt_guests.cfg index 376c61326bd..8ec3059b212 100644 --- a/libvirt/tests/cfg/daemon/conf_file/sysconfig_libvirt_guests/libvirt_guests.cfg +++ b/libvirt/tests/cfg/daemon/conf_file/sysconfig_libvirt_guests/libvirt_guests.cfg @@ -18,23 +18,16 @@ parallel_shutdown = "" variants: - persistent_only_none: + only suspend_on_shutdown persistent_only = "" - shutdown_on_shutdown: - transient_vm_operation = "shutdown" - suspend_on_shutdown: - transient_vm_operation = "nothing" + transient_vm_operation = "nothing" - persistent_only_true: persistent_only = "true" transient_vm_operation = "nothing" - - persistent_only_false: - persistent_only = "false" - transient_vm_operation = ${on_shutdown} - persistent_only_default: + only suspend_on_shutdown persistent_only = "default" - shutdown_on_shutdown: - transient_vm_operation = "shutdown" - suspend_on_shutdown: - transient_vm_operation = "nothing" + transient_vm_operation = "nothing" variants: - start_on_boot: on_boot = "start" From 7adc2fb1d622cb9d0ec11c2abb97fa5b89af2823 Mon Sep 17 00:00:00 2001 From: zhentang-tz Date: Tue, 18 Mar 2025 04:59:53 -0400 Subject: [PATCH 0937/1055] hot-plug/unplug: update usbredirct commands to resolve issues Resolved script failures caused by recent changes in usbredirection command syntax. Rewritted method "start_usbredirserver" to maintain compatibility with both new and old usbredir command formats. Signed-off-by: zhentang-tz --- .../domain/virsh_detach_device_alias.cfg | 4 ++-- .../domain/virsh_detach_device_alias.py | 19 +++++++++++++++---- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_detach_device_alias.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_detach_device_alias.cfg index a937e79af2f..bf3b6f1f813 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_detach_device_alias.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_detach_device_alias.cfg @@ -29,8 +29,8 @@ detach_redirdev_type = "spicevmc" - tcp: detach_redirdev_type = "tcp" - port = '4000' - redir_params = "{'source':'{"mode":"connect","host":"localhost","service":"${port}", "tls":"no"}'}" + port_num = '4000' + redir_params = "{'source':'{"mode":"connect","host":"localhost","service":"${port_num}", "tls":"no"}'}" - channel: variants: - spicevmc: diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py b/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py index 7251d2fa728..4c2ccb716b8 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_detach_device_alias.py @@ -2,6 +2,8 @@ import os import platform import uuid +import re +import time from virttest import data_dir from virttest import virsh @@ -16,6 +18,7 @@ from virttest.utils_libvirt import libvirt_vmxml from avocado.utils import process +from provider.usb import usb_base # Using as lower capital is not the best way to do, but this is just a @@ -76,7 +79,7 @@ def run(test, params, env): redir_type = params.get("detach_redirdev_type") redir_bus = params.get("detach_redirdev_bus") redir_params = eval(params.get("redir_params", "{}")) - port = params.get("port") + port_num = params.get("port_num") # channel params channel_type = params.get("detach_channel_type") channel_dict = eval(params.get("channel_dict", "{}")) @@ -97,6 +100,8 @@ def run(test, params, env): input_dict = eval(params.get('input_dict', '{}')) device_alias = "ua-" + str(uuid.uuid4()) + if redir_type: + usb_cmd = usb_base.get_host_pkg_and_cmd()[1] def check_device_by_alias(dev_type, dev_alias, expect_exist=True): """ @@ -154,9 +159,15 @@ def start_usbredirserver(): """ lsusb_list = process.run('lsusb').stdout_text.splitlines() - ps = process.SubProcess("usbredirserver -p {} {}".format - (port, lsusb_list[0].split()[5]), shell=True) - server_id = ps.start() + for usb_info in lsusb_list: + if re.search("hub", usb_info, re.IGNORECASE): + continue + if len(usb_info.split()[5].split(':')) == 2: + vendor_id, product_id = usb_info.split()[5].split(':') + if not (vendor_id and product_id): + test.fail("vendor/product id is not available") + server_id = usb_base.start_redirect_server(params, usb_cmd, vendor_id, product_id) + time.sleep(2) return server_id # backup xml From 2464ddda6fa9b533d36869d7fd0b77e396eb7ec9 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Fri, 21 Mar 2025 03:40:58 -0400 Subject: [PATCH 0938/1055] Add new case for dimm memory lifecycle test Add new case VIRT-299042 Life cycle for various config of dimm memory device Signed-off-by: liang-cong-red-hat --- .../memory_devices/dimm_memory_lifecycle.cfg | 81 ++++++ .../memory_devices/dimm_memory_lifecycle.py | 261 ++++++++++++++++++ 2 files changed, 342 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_devices/dimm_memory_lifecycle.cfg create mode 100644 libvirt/tests/src/memory/memory_devices/dimm_memory_lifecycle.py diff --git a/libvirt/tests/cfg/memory/memory_devices/dimm_memory_lifecycle.cfg b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_lifecycle.cfg new file mode 100644 index 00000000000..3835ac721b5 --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_devices/dimm_memory_lifecycle.cfg @@ -0,0 +1,81 @@ +- memory.devices.dimm.lifecycle: + type = dimm_memory_lifecycle + no s390-virtio + start_vm = no + check_path_secure_cmd = "ls /dev/hugepages/libvirt/qemu/ -dlZ" + path_secure_context = " root root system_u:object_r:hugetlbfs_t:s0" + check_guest_secure_cmd = "ls /dev/hugepages/libvirt/qemu/%s-%s -dlZ" + guest_secure_context = " qemu qemu system_u:object_r:svirt_image_t:s0" + numa_mem_val = 1048576 + memory_val = 2228224 + current_mem_val = 2228224 + init_size = 131072 + plug_size = 262144 + aarch64: + numa_mem_val = 4194304 + memory_val = 8912896 + current_mem_val = 8912896 + init_size = 524288 + plug_size = 1572864 + vm_attrs = {'max_mem_rt': 15428800, 'max_mem_rt_slots': 16,'max_mem_rt_unit': 'KiB','memory_unit':"KiB", 'memory':${memory_val}, 'current_mem':${current_mem_val}, 'current_mem_unit':'KiB', 'vcpu': 4,'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem_val}', 'unit': 'KiB'},{'id':'1','cpus': '2-3','memory':'${numa_mem_val}','unit':'KiB'}]}} + init_target_dict = {'size':${init_size}, 'size_unit':'KiB', 'node':0} + init_target_xpath = [{'element_attrs':[".//target/size[@unit='KiB']"],'text':'${init_size}'}, {'element_attrs':[".//target/node"],'text':'0'}] + plug_target_dict = {'size':${plug_size}, 'size_unit':'KiB', 'node':1} + plug_target_xpath = [{'element_attrs':[".//target/size[@unit='KiB']"],'text':'${plug_size}'}, {'element_attrs':[".//target/node"],'text':'1'}] + x86_64: + bios_check = 'yes' + sysinfo_attrs = {'type': 'smbios', 'bios_entry': [{'entry': 'LENOVO', 'entry_name': 'vendor'}]} + idmap_attrs = {'uid': {'start': '0', 'target': '1000', 'count': '10'}, 'gid': {'start': '0', 'target': '1000', 'count': '10'}} + os_attrs = {'smbios_mode': 'sysinfo'} + bios_check_xpath = [{'element_attrs':[".//os/smbios[@mode='sysinfo']"]}, {'element_attrs':[".//sysinfo[@type='smbios']"]}, {'element_attrs':[".//sysinfo/bios/entry[@name='vendor']"],'text':'LENOVO'}, {'element_attrs':[".//idmap/uid[@start='0']", ".//idmap/uid[@target='1000']", ".//idmap/uid[@count='10']"]}, {'element_attrs':[".//idmap/gid[@start='0']", ".//idmap/gid[@target='1000']", ".//idmap/gid[@count='10']"]}] + variants kernel_pagesize: + - 4k: + only x86_64, aarch64 + page_size = 4 + default_hp_size = 2048 + - 64k: + only aarch64 + page_size = 64 + default_hp_size = 524288 + variants memory_source: + - no_source: + source_dict = {} + source_xpath = [] + - nodemask: + nodeset_num = 1 + source_dict = {'nodemask':'%s'} + source_xpath = [{'element_attrs':[".//source/nodemask"],'text':'%s'}] + - pagesize: + source_dict = {'pagesize':${page_size}, 'pagesize_unit':'KiB'} + source_xpath = [{'element_attrs':[".//source/pagesize[@unit='KiB']"],'text':'${page_size}'}] + - nodemask_pagesize: + nodeset_num = 2 + use_huge_page = "yes" + source_dict = {'nodemask':'%s', 'pagesize':${default_hp_size}, 'pagesize_unit':'KiB'} + source_xpath = [{'element_attrs':[".//source/nodemask"],'text':'%s'}, {'element_attrs':[".//source/pagesize[@unit='KiB']"],'text':'${default_hp_size}'}] + variants address_config: + - no_address: + init_alias_name = "dimm0" + plug_alias_name = "dimm1" + init_address_dict = {} + plug_address_dict = {} + init_address_xpath= [{'element_attrs':[".//address[@slot='0']", ".//address[@base]"]}] + plug_address_xpath= [{'element_attrs':[".//address[@slot='1']", ".//address[@base]"]}] + - slot_base: + init_address = '0x200000000' + plug_address = '0x400000000' + aarch64: + init_address = '0x300000000' + init_slot = '1' + plug_slot = '2' + init_alias_name = "dimm${init_slot}" + plug_alias_name = "dimm${plug_slot}" + init_address_dict = {'attrs':{'base':'${init_address}', 'type':'dimm', 'slot':'${init_slot}'}} + init_address_xpath= [{'element_attrs':[".//address[@slot='${init_slot}']", ".//address[@base='${init_address}']"]}] + plug_address_dict = {'attrs':{'base':'${plug_address}', 'type':'dimm', 'slot':'${plug_slot}'}} + plug_address_xpath= [{'element_attrs':[".//address[@slot='${plug_slot}']", ".//address[@base='${plug_address}']"]}] + init_mem_device_dict = {'mem_model':'dimm', 'source':${source_dict}, 'target':${init_target_dict}, 'address':${init_address_dict}} + init_xpath_list = [${source_xpath}, ${init_target_xpath}, ${init_address_xpath}] + plug_mem_device_dict = {'mem_model':'dimm', 'source':${source_dict}, 'target':${plug_target_dict}, 'address':${plug_address_dict}} + plug_xpath_list = [${source_xpath}, ${plug_target_xpath}, ${plug_address_xpath}] + diff --git a/libvirt/tests/src/memory/memory_devices/dimm_memory_lifecycle.py b/libvirt/tests/src/memory/memory_devices/dimm_memory_lifecycle.py new file mode 100644 index 00000000000..f3ea9dcdbb7 --- /dev/null +++ b/libvirt/tests/src/memory/memory_devices/dimm_memory_lifecycle.py @@ -0,0 +1,261 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: Liang Cong +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import os +import re + +from avocado.utils import process + +from virttest import data_dir +from virttest import test_setup +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.devices import memory +from virttest.utils_libvirt import libvirt_memory +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_libvirtd import Libvirtd +from virttest.utils_test import libvirt + +from provider.memory import memory_base +from provider.numa import numa_base + + +def run(test, params, env): + """ + Verify various config of dimm memory device settings take effect + during the life cycle of guest vm. + """ + + def clean_empty_memory_device_config(mem_device_dict): + """ + Clean empty config of the memory device + + :param mem_device_dict (dict): memory device config dictionary + """ + for key in list(mem_device_dict.keys()): + if not mem_device_dict[key]: + del mem_device_dict[key] + + def check_dimm_mem_device_xml(xpath_dict): + """ + Check the dimm memory device config by xpath + + :param xpath_dict (dict): xpath dict to check if the memory config is correct, + like {"alias_name":[xpath1, xpath2]},...} + """ + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + test.log.debug(f"Current guest config xml is:\n{vmxml}") + memory_devices = vmxml.devices.by_device_tag('memory') + target_memory_num = 0 + for alias_name, xpath_list in xpath_dict.items(): + for memory_device in memory_devices: + if alias_name == memory_device.alias.get('name'): + target_memory_num = target_memory_num + 1 + for xpath in xpath_list: + libvirt_vmxml.check_guest_xml_by_xpaths(memory_device, xpath) + if target_memory_num != len(xpath_dict): + test.fail( + f"Expected {len(xpath_dict)} dimm mem devices with required alias name, but found {target_memory_num}") + + def check_numa_node_memory_allocation(mem_size, numa_list, page_size): + """ + Check memory is allocated on target numa list with correct page size + + :param mem_size (int): memory size + :param numa_list (list): target numa list + :param page_size (str): page size of the memory + """ + cmd_output = numa_base.get_host_numa_memory_alloc_info(mem_size) + actual_numa_list = re.findall(r'N(\d+)=', cmd_output) + if not set(actual_numa_list).issubset(set(numa_list)): + test.fail( + f"Expected numa list {numa_list} doesn't contain actual numa in numa_maps output {cmd_output}") + if not re.search(fr'kernelpagesize_kB={page_size}', cmd_output): + test.fail( + f"Failed to find {page_size}kb memory page size in numa_maps output {cmd_output}") + + def check_case_availability(): + """ + Check whether the case is available + """ + memory_base.check_mem_page_sizes(test, page_size, default_hp_size) + memory_base.check_supported_version(params, test, vm) + + def setup_test(): + """ + Setup for the case: + 1. Get host available numa nodes + 2. Change parameters according to available numa nodes + 3. Allocate huge page memory for target host node if needs + """ + if nodeset_num: + numatest_obj = numa_base.NumaTest(vm, params, test) + if 1 == nodeset_num: + min_memory_size = init_size + plug_size + elif 2 == nodeset_num: + min_memory_size = init_size if init_size >= plug_size else plug_size + numatest_obj.check_numa_nodes_availability(nodeset_num, min_memory_size) + numa_list = numatest_obj.get_available_numa_nodes(min_memory_size)[:nodeset_num] + nodeset_str = numa_base.convert_to_string_with_dash( + ','.join([str(node) for node in numa_list])) + params["numa_node_list"] = numa_list + source_dict = params.get("source_dict") + source_xpath = params.get("source_xpath") + source_dict = eval(source_dict % nodeset_str) + source_xpath = eval(source_xpath % nodeset_str) + init_mem_device_dict["source"] = source_dict + plug_mem_device_dict["source"] = source_dict + init_xpath_list[0] = source_xpath + plug_xpath_list[0] = source_xpath + test.log.debug(f"Selected numa nodeset is:{nodeset_str}") + + if use_huge_page: + params["target_nodes"] = " ".join([str(node) for node in numa_list]) + params["target_hugepages"] = (init_size + plug_size) / default_hp_size + hpc = test_setup.HugePageConfig(params) + hpc.setup() + + if vm.is_alive(): + vm.destroy() + + def run_test(): + """ + Test steps + """ + test.log.info("TEST_STEP1: Define the guest") + clean_empty_memory_device_config(init_mem_device_dict) + memory_base.define_guest_with_memory_device(params, init_mem_device_dict, vm_attrs) + + if use_huge_page: + test.log.info("TEST_STEP2: Check secure context for default huge page mount path") + cmd_result = process.run(check_path_secure_cmd, ignore_status=True, shell=True) + libvirt.check_result(cmd_result, expected_match=path_secure_context) + + test.log.info("TEST_STEP3: Start the guest") + vm.start() + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + test.log.debug(f"Guest config xml after start is:\n{vmxml}") + + if use_huge_page: + test.log.info("TEST_STEP4: Check secure context for default huge page mount path") + check_cmd = check_guest_secure_cmd % (vm.get_id(), vm_name) + cmd_result = process.run(check_cmd, ignore_status=True, shell=True) + libvirt.check_result(cmd_result, expected_match=guest_secure_context) + + test.log.info("TEST_STEP5: Check dimm memory device config by virsh dumpxml") + check_dimm_mem_device_xml({init_alias_name: init_xpath_list}) + + if bios_check: + test.log.info("TEST_STEP6: Check smbios, sysinfo and idmap info by virsh dumpxml") + libvirt_vmxml.check_guest_xml_by_xpaths(vmxml, bios_check_xpath) + + test.log.info("TEST_STEP7: Hotplug a dimm memory device") + clean_empty_memory_device_config(plug_mem_device_dict) + mem_device = memory.Memory() + mem_device.setup_attrs(**plug_mem_device_dict) + virsh.attach_device(vm_name, mem_device.xml, **virsh_dargs) + + test.log.info( + "TEST_STEP8: Check dimm memory device config by virsh dumpxml") + check_dimm_mem_device_xml( + {init_alias_name: init_xpath_list, plug_alias_name: plug_xpath_list}) + + test.log.info("TEST_STEP9: Consume the guest memory") + with vm.wait_for_login() as session: + libvirt_memory.consume_vm_freememory(session) + + if nodeset_num: + test.log.info("TEST_STEP10: Check dimm memory device source node") + numa_list = [str(node) for node in params['numa_node_list']] + expected_page_size = default_hp_size if use_huge_page else page_size + check_numa_node_memory_allocation(init_size, numa_list, expected_page_size) + check_numa_node_memory_allocation(plug_size, numa_list, expected_page_size) + + test.log.info("TEST_STEP11: Life cycle test") + virsh.suspend(vm_name, **virsh_dargs) + virsh.resume(vm_name, **virsh_dargs) + check_dimm_mem_device_xml( + {init_alias_name: init_xpath_list, plug_alias_name: plug_xpath_list}) + + virsh.save(vm_name, state_file, **virsh_dargs) + virsh.restore(state_file, **virsh_dargs) + check_dimm_mem_device_xml( + {init_alias_name: init_xpath_list, plug_alias_name: plug_xpath_list}) + + virsh.managedsave(vm_name, **virsh_dargs) + vm.start() + check_dimm_mem_device_xml( + {init_alias_name: init_xpath_list, plug_alias_name: plug_xpath_list}) + + vm.reboot() + vm.wait_for_login().close() + check_dimm_mem_device_xml( + {init_alias_name: init_xpath_list, plug_alias_name: plug_xpath_list}) + + libvirt_daemon = Libvirtd() + if not libvirt_daemon.restart(reset_failed=False): + test.error("libvirt deamon restarts failed or is not working properly") + check_dimm_mem_device_xml( + {init_alias_name: init_xpath_list, plug_alias_name: plug_xpath_list}) + + def teardown_test(): + """ + 1. Restore guest config xml + 2. Clean huge page memory + 3. Remove state file + """ + bkxml.sync() + if use_huge_page: + hpc = test_setup.HugePageConfig(params) + hpc.cleanup() + if os.path.exists(state_file): + os.remove(state_file) + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + + vm_attrs = eval(params.get("vm_attrs", "{}")) + bios_check = params.get("bios_check", "no") == "yes" + if bios_check: + sysinfo_attrs = eval(params.get("sysinfo_attrs", "{}")) + idmap_attrs = eval(params.get("idmap_attrs", "{}")) + os_attrs = eval(params.get("os_attrs", "{}")) + vm_attrs.update({'sysinfo': sysinfo_attrs, + 'os': os_attrs, 'idmap': idmap_attrs}) + bios_check_xpath = eval(params.get("bios_check_xpath")) + init_mem_device_dict = eval( + params.get("init_mem_device_dict", "{}")) + plug_mem_device_dict = eval( + params.get("plug_mem_device_dict", "{}")) + init_xpath_list = eval(params.get("init_xpath_list")) + plug_xpath_list = eval(params.get("plug_xpath_list")) + check_path_secure_cmd = params.get("check_path_secure_cmd") + path_secure_context = params.get("path_secure_context") + check_guest_secure_cmd = params.get("check_guest_secure_cmd") + guest_secure_context = params.get("guest_secure_context") + init_alias_name = params.get("init_alias_name") + plug_alias_name = params.get("plug_alias_name") + page_size = int(params.get("page_size")) + default_hp_size = int(params.get("default_hp_size")) + init_size = int(params.get("init_size")) + plug_size = int(params.get("plug_size")) + nodeset_num = int(params.get("nodeset_num", "0")) + use_huge_page = "yes" == params.get("use_huge_page") + state_file = f"{data_dir.get_tmp_dir()}/{vm_name}.save" + virsh_dargs = {"debug": True, "ignore_status": False} + + try: + check_case_availability() + setup_test() + run_test() + + finally: + teardown_test() From 4df2e77af619d833afe002764e7c0d6c2da86fcf Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Thu, 20 Feb 2025 10:48:13 -0500 Subject: [PATCH 0939/1055] Add vhostuser support for passt Add vhostuser support for passt in sevaral scenarios. Signed-off-by: Yalan Zhang --- .../virtual_network/passt/passt_attach_detach.cfg | 5 +++++ .../cfg/virtual_network/passt/passt_function.cfg | 5 +++++ .../cfg/virtual_network/passt/passt_lifecycle.cfg | 10 ++++++++++ .../cfg/virtual_network/passt/passt_reconnect.cfg | 6 ++++++ .../virtual_network/passt/passt_transfer_file.cfg | 5 +++++ .../virtual_network/passt/passt_attach_detach.py | 12 +++++++++++- .../src/virtual_network/passt/passt_function.py | 13 ++++++++++++- .../src/virtual_network/passt/passt_lifecycle.py | 15 +++++++++++++-- .../src/virtual_network/passt/passt_reconnect.py | 8 ++++++++ 9 files changed, 75 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg index eafee0b3439..278518d87b9 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg @@ -24,6 +24,11 @@ - detach: add_iface = yes - attach_detach: + variants: + - default: + - vhostuser: + vhostuser = yes + func_supported_since_libvirt_ver = (10, 10, 0) variants: - ip_portfw: alias = {'name': 'ua-c87b89ff-b769-4abc-921f-30d42d7aec5b'} diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg index a2803e50729..48f893f6bd1 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg @@ -78,3 +78,8 @@ iface_attrs = {'model': 'virtio', 'acpi': {'index': '1'}, 'ips': ${ips}, 'backend': ${backend}, 'source': {'dev': host_iface}, 'alias': ${alias}, 'type_name': 'user', 'portForwards': ${portForwards}} s390-virtio: iface_attrs = {'model': 'virtio', 'ips': ${ips}, 'backend': ${backend}, 'source': {'dev': host_iface}, 'alias': ${alias}, 'type_name': 'user', 'portForwards': ${portForwards}} + variants: + - default: + - vhostuser: + vhostuser = yes + func_supported_since_libvirt_ver = (10, 10, 0) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_lifecycle.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_lifecycle.cfg index edac5f3569c..eee50205c2e 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_lifecycle.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_lifecycle.cfg @@ -20,6 +20,11 @@ operation_a = suspend operation_b = resume passt_running = yes + variants: + - default: + - vhostuser: + vhostuser = yes + func_supported_since_libvirt_ver = (10, 10, 0) variants user_type: - non_root_user: test_user = USER.EXAMPLE @@ -27,6 +32,11 @@ user_id = unpr_vm_name = UNPRIVILEGED_VM.EXAMPLE socket_dir = f'/run/user/{user_id}/libvirt/qemu/run/passt/' + - root_user: + test_user = root + user_id = 107 + log_dir = /run/user/${user_id} + socket_dir = f'/run/libvirt/qemu/passt/' variants scenario: - ip_portfw: ipv6_prefix = 128 diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg index 20444a0b981..09d4af072d3 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg @@ -20,6 +20,12 @@ unpr_vm_name = UNPRIVILEGED_VM.EXAMPLE virsh_uri = 'qemu+ssh://${test_user}@localhost/session' socket_dir = f'/run/user/{user_id}/libvirt/qemu/run/passt/' + variants: + - default: + - vhostuser: + vhostuser = 'yes' + qemu_cmd_check = "reconnect=5" + func_supported_since_libvirt_ver = (10, 10, 0) variants: - ip_portfw: alias = {'alias': {'name': 'ua-c87b89ff-b769-4abc-921f-30d42d7aec5b'}} diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg index 81ff28300de..76b45bf0b1b 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg @@ -18,6 +18,11 @@ unpr_vm_name = UNPRIVILEGED_VM.EXAMPLE virsh_uri = 'qemu+ssh://${test_user}@localhost/session' socket_dir = f'/run/user/{user_id}/libvirt/qemu/run/passt/' + variants: + - default: + - vhostuser: + vhostuser = 'yes' + func_supported_since_libvirt_ver = (10, 10, 0) variants: - ip_portfw: alias = {'alias': {'name': 'ua-c87b89ff-b769-4abc-921f-30d42d7aec5b'}} diff --git a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py index ba4f5805421..b723fbd0022 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py +++ b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py @@ -11,6 +11,7 @@ from virttest import virsh from virttest.libvirt_xml import vm_xml from virttest.staging import service +from virttest.staging import utils_memory from virttest.utils_libvirt import libvirt_unprivileged from virttest.utils_libvirt import libvirt_vmxml @@ -79,10 +80,12 @@ def run(test, params, env): log_file = f'/run/user/{user_id}/passt.log' iface_attrs['backend']['logFile'] = log_file iface_attrs['source']['dev'] = host_iface + vhostuser = 'yes' == params.get('vhostuser', 'no') vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name, virsh_instance=virsh_ins) bkxml = vmxml.copy() + shp_orig_num = utils_memory.get_num_huge_pages() selinux_status = passt.ensure_selinux_enforcing() passt.check_socat_installed() @@ -93,6 +96,12 @@ def run(test, params, env): passt.make_log_dir(user_id, log_dir) vmxml.del_device('interface', by_tag=True) + if vhostuser: + # set static hugepage + utils_memory.set_num_huge_pages(2048) + vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", hpgs=True, vmxml=vmxml) + # update vm xml with shared memory and vhostuser interface + iface_attrs['type_name'] = 'vhostuser' iface_device = libvirt_vmxml.create_vm_device_by_type('interface', iface_attrs) LOG.debug(f'iface_device: {iface_device}') @@ -150,7 +159,7 @@ def run(test, params, env): if 'detach' not in scenario: vm.destroy() passt.check_passt_pid_not_exist() - if os.listdir(socket_dir): + if not vhostuser and os.listdir(socket_dir): test.fail(f'Socket dir is not empty: {os.listdir(socket_dir)}') else: vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name, @@ -185,3 +194,4 @@ def run(test, params, env): else: del virsh_ins utils_selinux.set_status(selinux_status) + utils_memory.set_num_huge_pages(shp_orig_num) diff --git a/libvirt/tests/src/virtual_network/passt/passt_function.py b/libvirt/tests/src/virtual_network/passt/passt_function.py index b8a201f53e5..008b143ecee 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_function.py +++ b/libvirt/tests/src/virtual_network/passt/passt_function.py @@ -10,6 +10,7 @@ from virttest import virsh from virttest.libvirt_xml import vm_xml from virttest.staging import service +from virttest.staging import utils_memory from virttest.utils_libvirt import libvirt_unprivileged from virttest.utils_libvirt import libvirt_vmxml @@ -65,10 +66,12 @@ def run(test, params, env): log_file = f'/run/user/{user_id}/passt.log' iface_attrs = eval(params.get('iface_attrs')) iface_attrs['backend']['logFile'] = log_file + vhostuser = 'yes' == params.get('vhostuser', 'no') vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name, virsh_instance=virsh_ins) bkxml = vmxml.copy() + shp_orig_num = utils_memory.get_num_huge_pages() selinux_status = passt.ensure_selinux_enforcing() passt.check_socat_installed() @@ -83,6 +86,12 @@ def run(test, params, env): vmxml.del_device('interface', by_tag=True) vmxml.sync(virsh_instance=virsh_ins) + if vhostuser: + # set static hugepage + utils_memory.set_num_huge_pages(2048) + vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", hpgs=True, vmxml=vmxml) + # update vm xml with shared memory and vhostuser interface + iface_attrs['type_name'] = 'vhostuser' libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs, virsh_instance=virsh_ins) LOG.debug(virsh_ins.dumpxml(vm_name).stdout_text) @@ -92,6 +101,7 @@ def run(test, params, env): passt.check_proc_info(params, log_file, mac) # check the passt log + LOG.debug(virsh.dumpxml(vm_name)) if not os.path.exists(log_file): test.fail(f'Logfile of passt "{log_file}" not created') @@ -123,7 +133,7 @@ def run(test, params, env): vm.destroy() passt.check_passt_pid_not_exist() - if os.listdir(socket_dir): + if not vhostuser and os.listdir(socket_dir): test.fail(f'Socket dir is not empty: {os.listdir(socket_dir)}') finally: @@ -134,3 +144,4 @@ def run(test, params, env): else: del virsh_ins utils_selinux.set_status(selinux_status) + utils_memory.set_num_huge_pages(shp_orig_num) diff --git a/libvirt/tests/src/virtual_network/passt/passt_lifecycle.py b/libvirt/tests/src/virtual_network/passt/passt_lifecycle.py index be846bdb412..004da380071 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_lifecycle.py +++ b/libvirt/tests/src/virtual_network/passt/passt_lifecycle.py @@ -11,6 +11,7 @@ from virttest import virsh from virttest.libvirt_xml import vm_xml from virttest.staging import service +from virttest.staging import utils_memory from virttest.utils_libvirt import libvirt_unprivileged from virttest.utils_libvirt import libvirt_vmxml @@ -29,6 +30,7 @@ def run(test, params, env): """ libvirt_version.is_libvirt_feature_supported(params) root = 'root_user' == params.get('user_type', '') + test_user = params.get('test_user') if root: vm_name = params.get('main_vm') vm = env.get_vm(vm_name) @@ -70,14 +72,16 @@ def run(test, params, env): iface_attrs['backend']['logFile'] = log_file operation_a = params.get('operation_a') operation_b = params.get('operation_b') - save_path = f'/home/{test_user}/save_{utils_misc.generate_random_string(3)}' + save_path = f'/tmp/save_{utils_misc.generate_random_string(3)}' options_a = eval(params.get('options_a', '{}')) options_b = eval(params.get('options_b', '{}')) passt_running = 'yes' == params.get('passt_running', 'no') + vhostuser = 'yes' == params.get('vhostuser', 'no') vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name, virsh_instance=virsh_ins) bkxml = vmxml.copy() + shp_orig_num = utils_memory.get_num_huge_pages() selinux_status = passt.ensure_selinux_enforcing() passt.check_socat_installed() @@ -97,6 +101,12 @@ def run(test, params, env): vmxml.sync(virsh_instance=virsh_ins) libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs, virsh_instance=virsh_ins) + if vhostuser: + # set static hugepage + utils_memory.set_num_huge_pages(2048) + vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", hpgs=True, vmxml=vmxml) + # update vm xml with shared memory and vhostuser interface + iface_attrs['type_name'] = 'vhostuser' LOG.debug(virsh_ins.dumpxml(vm_name).stdout_text) mac = vm.get_virsh_mac_address() @@ -148,7 +158,7 @@ def run(test, params, env): vm.destroy() passt.check_passt_pid_not_exist() - if os.listdir(socket_dir): + if not vhostuser and os.listdir(socket_dir): test.fail(f'Socket dir is not empty: {os.listdir(socket_dir)}') finally: @@ -161,3 +171,4 @@ def run(test, params, env): utils_selinux.set_status(selinux_status) if os.path.exists(save_path): os.remove(save_path) + utils_memory.set_num_huge_pages(shp_orig_num) diff --git a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py index 3f3456b3251..aaddb77ce31 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py +++ b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py @@ -13,6 +13,7 @@ from virttest import virsh from virttest.libvirt_xml import vm_xml from virttest.staging import service +from virttest.staging import utils_memory from virttest.utils_libvirt import libvirt_unprivileged from virttest.utils_test import libvirt @@ -69,10 +70,12 @@ def run(test, params, env): log_file = f'/run/user/{user_id}/passt.log' iface_attrs['backend']['logFile'] = log_file iface_attrs['source']['dev'] = host_iface + vhostuser = 'yes' == params.get('vhostuser', 'no') vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name, virsh_instance=virsh_ins) bkxml = vmxml.copy() + shp_orig_num = utils_memory.get_num_huge_pages() selinux_status = passt.ensure_selinux_enforcing() passt.check_socat_installed() @@ -82,6 +85,10 @@ def run(test, params, env): if root: passt.make_log_dir(user_id, log_dir) + if vhostuser: + iface_attrs['type_name'] = 'vhostuser' + utils_memory.set_num_huge_pages(2048) + vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", hpgs=True, vmxml=vmxml) passt.vm_add_iface(vmxml, iface_attrs, virsh_ins) vm.start() @@ -144,3 +151,4 @@ def run(test, params, env): else: del virsh_ins utils_selinux.set_status(selinux_status) + utils_memory.set_num_huge_pages(shp_orig_num) From ce803920299920ad3c7a92e33ade793029023575 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Wed, 16 Apr 2025 18:35:16 +0800 Subject: [PATCH 0940/1055] ci.yml: fix ubuntu 20.04 deprecated Signed-off-by: Dan Zheng --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7fc25a3f05e..b65375b3c56 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,11 +12,11 @@ jobs: travis-check: name: Python ${{ matrix.python-version }} - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 strategy: matrix: - python-version: [3.6, 3.7, 3.8, 3.9] + python-version: [3.8, 3.9, 3.11, 3.12] fail-fast: false steps: From c7958b32ff64105a0ea5a92c135ebc615b7b397d Mon Sep 17 00:00:00 2001 From: lcheng Date: Thu, 17 Apr 2025 10:57:57 +0800 Subject: [PATCH 0941/1055] migration: Add migrate_vm_back for case Signed-off-by: lcheng --- .../migrate_vm_in_various_status/migrate_paused_vm.cfg | 2 ++ .../migrate_vm_in_various_status/migrate_paused_vm.py | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/libvirt/tests/cfg/migration/migrate_vm_in_various_status/migrate_paused_vm.cfg b/libvirt/tests/cfg/migration/migrate_vm_in_various_status/migrate_paused_vm.cfg index db8ebf03406..6d607cc2f0d 100644 --- a/libvirt/tests/cfg/migration/migrate_vm_in_various_status/migrate_paused_vm.cfg +++ b/libvirt/tests/cfg/migration/migrate_vm_in_various_status/migrate_paused_vm.cfg @@ -33,6 +33,8 @@ - migration_succeeds: status_error = "no" virsh_migrate_dest_state = "paused" + migrate_vm_back = "yes" + src_state = "paused" - cancel_migration: status_error = "yes" migrate_speed = "5" diff --git a/libvirt/tests/src/migration/migrate_vm_in_various_status/migrate_paused_vm.py b/libvirt/tests/src/migration/migrate_vm_in_various_status/migrate_paused_vm.py index 81bba325265..5828f05b889 100644 --- a/libvirt/tests/src/migration/migrate_vm_in_various_status/migrate_paused_vm.py +++ b/libvirt/tests/src/migration/migrate_vm_in_various_status/migrate_paused_vm.py @@ -1,4 +1,5 @@ from virttest import virsh +from virttest.utils_test import libvirt from provider.migration import base_steps @@ -14,6 +15,7 @@ def run(test, params, env): :param env: Dictionary with test environment. """ vm_name = params.get("migrate_main_vm") + migrate_vm_back = "yes" == params.get("migrate_vm_back", "no") vm = env.get_vm(vm_name) migration_obj = base_steps.MigrationBase(test, vm, params) @@ -24,5 +26,10 @@ def run(test, params, env): virsh.suspend(vm.name, debug=True, ignore_status=False) migration_obj.run_migration() migration_obj.verify_default() + if migrate_vm_back: + migration_obj.run_migration_back() + if not libvirt.check_vm_state(vm_name, params.get("src_state"), + uri=migration_obj.src_uri, debug=True): + test.fail("Check vm state failed.") finally: migration_obj.cleanup_connection() From c38fc234d1185f4e9a2bbf61b3d48cf2a60b1a5f Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 21 Apr 2025 04:53:31 -0400 Subject: [PATCH 0942/1055] virsh_cpu_models: add filters 969ec9b13d2be9d88381d686601288c695a1cb94 restructured the tests introducing a named variant for each of the main architectures. However, this requires additional filtering in CI. Instead, use existing avocado-vt configuration parameters to keep having a single variant that applies to all considered archs. Signed-off-by: Sebastian Mitterle --- .../cfg/virsh_cmd/host/virsh_cpu_models.cfg | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/libvirt/tests/cfg/virsh_cmd/host/virsh_cpu_models.cfg b/libvirt/tests/cfg/virsh_cmd/host/virsh_cpu_models.cfg index cc01d7c6f28..c73cb9dd57a 100644 --- a/libvirt/tests/cfg/virsh_cmd/host/virsh_cpu_models.cfg +++ b/libvirt/tests/cfg/virsh_cmd/host/virsh_cpu_models.cfg @@ -13,15 +13,13 @@ only local_host check_qemu_cpu_supported_cmd = "/usr/libexec/qemu-kvm -cpu help | awk '/Available CPUs/,/Recognized CPUID flags/' | grep '^ ' | awk '{print $1}'" skip_list = ['base', 'host', 'max'] - variants arch_option: - - arch_x86: - cpu_arch = "x86_64" - - arch_s390: - cpu_arch = "s390" - msg = "all CPU models are accepted" - - arch_aarch64: - cpu_arch = "aarch64" - msg = "all CPU models are accepted" + cpu_arch = "x86_64" + s390-virtio: + cpu_arch = "s390" + msg = "all CPU models are accepted" + aarch64: + cpu_arch = "aarch64" + msg = "all CPU models are accepted" variants: - local_host: - remote_host: From e1716baa6aef20abbe6c14610777a85f96efca0d Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Mon, 21 Apr 2025 05:14:33 -0400 Subject: [PATCH 0943/1055] Add required parameters for shared disk and tls setup Signed-off-by: liang-cong-red-hat --- .../tests/cfg/migration/migration_with_numa_topology.cfg | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libvirt/tests/cfg/migration/migration_with_numa_topology.cfg b/libvirt/tests/cfg/migration/migration_with_numa_topology.cfg index 514ae02f0cd..49133da53e7 100644 --- a/libvirt/tests/cfg/migration/migration_with_numa_topology.cfg +++ b/libvirt/tests/cfg/migration/migration_with_numa_topology.cfg @@ -1,6 +1,10 @@ - migrate.migration_with_numa_topology: type = migration_with_numa_topology only aarch64 + migration_setup = "yes" + storage_type = "nfs" + setup_local_nfs = "yes" + take_regular_screendumps = no start_vm = 'no' dest_persist_xml = "yes" dest_xml = "yes" @@ -26,6 +30,8 @@ - addtional_options: migration_connections = 3 add_options = "--auto-converge --parallel --parallel-connections ${migration_connections} --tls" + migrate_dest_host_cn = "ENTER.YOUR.EXAMPLE.SERVER_CN" + migrate_source_host_cn = "ENTER.YOUR.EXAMPLE.CLIENT_CN" variants: - without_postcopy: copy_type = "" From c3ab3ae6b5a8295e6e069113f51091b18bc0dd31 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 5 Dec 2024 22:34:00 -0500 Subject: [PATCH 0944/1055] Add new case of zone of network - VIRT-298946 - [Zone] Define network with libvirt managed bridge zone Signed-off-by: Haijiao Zhao --- .../cfg/virtual_network/network_misc.cfg | 14 +++ .../tests/src/virtual_network/network_misc.py | 111 ++++++++++++++---- 2 files changed, 100 insertions(+), 25 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/network_misc.cfg b/libvirt/tests/cfg/virtual_network/network_misc.cfg index 26bd0ed029b..8aef75b2ba7 100644 --- a/libvirt/tests/cfg/virtual_network/network_misc.cfg +++ b/libvirt/tests/cfg/virtual_network/network_misc.cfg @@ -4,7 +4,21 @@ variants test_group: - zone: variants case: + - libvirt_managed: + br_attrs = {'stp': 'on', 'delay': '0'} + variants forward_mode: + - nat: + default_zone = libvirt + - route: + default_zone = libvirt-routed + - isolated: + default_zone = libvirt + - open: + default_zone = no zone + net_attrs = {'forward': {'mode': '${forward_mode}'}, 'name': net_name, 'ips': [{'address': '192.168.152.1', 'netmask': '255.255.255.0', 'dhcp_ranges': {'attrs': {'start': '192.168.152.2', 'end': '192.168.152.254'}}}]} + expect_str = ['${default_zone} (active)', 'target: ACCEPT', 'interfaces: .*%s' % br, 'services: dhcp dhcpv6 dns ssh tftp', 'protocols: icmp ipv6-icmp', 'rule priority="32767" reject'] - public: + net_attrs = {'forward': {'mode': 'nat'}, 'name': net_name, 'bridge': {'zone': 'public'}, 'ips': [{'address': '192.168.152.1', 'netmask': '255.255.255.0', 'dhcp_ranges': {'attrs': {'start': '192.168.152.2', 'end': '192.168.152.254'}}}]} - info: expect_str = ['libvirt (active)', 'target: ACCEPT', 'interfaces: .*%s' % br, 'services: dhcp dhcpv6 dns ssh tftp', 'protocols: icmp ipv6-icmp', 'rule priority="32767" reject'] - iface_acpi: diff --git a/libvirt/tests/src/virtual_network/network_misc.py b/libvirt/tests/src/virtual_network/network_misc.py index 35e14960f80..a21df2a9f00 100644 --- a/libvirt/tests/src/virtual_network/network_misc.py +++ b/libvirt/tests/src/virtual_network/network_misc.py @@ -1,18 +1,17 @@ import logging as log import re -from avocado.utils.software_manager.backends import rpm from avocado.utils import process from avocado.utils import service - +from avocado.utils.software_manager.backends import rpm from virttest import libvirt_version from virttest import utils_misc from virttest import utils_net from virttest import virsh - from virttest.libvirt_xml import vm_xml from virttest.libvirt_xml.devices import interface from virttest.libvirt_xml.network_xml import NetworkXML +from virttest.utils_libvirt import libvirt_network from virttest.utils_test import libvirt DEFAULT_NET = 'default' @@ -44,9 +43,12 @@ def run(test, params, env): vm = env.get_vm(vm_name) machine_type = params.get('machine_type') net = params.get('net', DEFAULT_NET) + ran_id = utils_misc.generate_random_string(3) + net_name = 'net_' + ran_id + net_attrs = eval(params.get('net_attrs', '{}')) status_error = 'yes' == params.get('status_error', 'no') expect_str = params.get('expect_str') - bridge_name = 'br_' + utils_misc.generate_random_string(3) + bridge_name = 'br_' + ran_id test_group = params.get('test_group', 'default') case = params.get('case', '') @@ -86,17 +88,29 @@ def setup_test_zone(case): setup_firewalld() - # Setup zone for bridge - netxml = NetworkXML.new_from_net_dumpxml(net) - if case == 'public': - netxml.bridge = {'name': bridge_name, 'zone': 'public'} - elif case == 'info': - netxml.bridge = {'name': bridge_name} - else: - test.error('Test "%s" is not supported.' % case) - netxml.forward = {'mode': 'nat'} - netxml.sync() - logging.debug('Updated net:\n%s', virsh.net_dumpxml(net).stdout_text) + def setup_test_zone_default(): + # Setup zone for bridge + netxml = NetworkXML.new_from_net_dumpxml(net) + if case == 'info': + netxml.bridge = {'name': bridge_name} + else: + test.error('Test "%s" is not supported.' % case) + netxml.forward = {'mode': 'nat'} + netxml.sync() + logging.debug('Updated net:\n%s', + virsh.net_dumpxml(net).stdout_text) + + def setup_test_zone_libvirt_managed(): + if params.get('forward_mode') == 'isolated': + net_attrs.pop('forward') + libvirt_network.create_or_del_network(net_attrs) + + def setup_test_zone_public(): + libvirt_network.create_or_del_network(net_attrs) + + setup_zone = eval('setup_test_zone_%s' % case) if \ + 'setup_test_zone_%s' % case in locals() else setup_test_zone_default + setup_zone() def run_test_zone(case): """ @@ -104,31 +118,76 @@ def run_test_zone(case): :param case: test case """ - - def run_test_zone_public(): + def check_zone(iface, expect_zone): """ - Check zone of interface with firewalld-cmd + Check whether zone info meets expectation """ - check_cmd = 'firewall-cmd --get-zone-of-interface=%s' % bridge_name - output = process.run(check_cmd, verbose=True).stdout_text.strip() - if output == 'public': + check_cmd = 'firewall-cmd --get-zone-of-interface=%s' % iface + cmd_result = process.run(check_cmd, ignore_status=True) + output = cmd_result.stdout_text.strip() + cmd_result.stderr_text.strip() + if output == expect_zone: logging.info('Zone check of interface PASSED') + return output else: - test.fail('Zone check of interface FAILED, should be public, but got %s' % output) + test.fail( + f'Zone check of interface FAILED, should be {expect_zone}, but got %s' % output) - def run_test_zone_info(): + def check_zone_info(br, zone): """ Check zone info with firewalld-cmd """ - check_cmd = 'firewall-cmd --info-zone=libvirt' + check_cmd = f'firewall-cmd --info-zone={zone}' output = process.run(check_cmd, verbose=True).stdout_text.strip() - br = bridge_name for item in eval(expect_str): if item in output or re.search(item, output): logging.debug('Found "%s" in firewalld-cmd output' % item) else: test.fail('Not found "%s" in firewalld-cmd output' % item) + def run_test_zone_public(): + """ + Check zone of interface with firewalld-cmd + """ + net_attrs = NetworkXML.new_from_net_dumpxml(net_name).fetch_attrs() + net_br_attrs = net_attrs['bridge'] + if net_attrs['bridge']['zone'] != 'public': + test.fail(f"Network {net_name} zone should be 'public'," + f"not {net_attrs['bridge']['zone']}") + + check_zone(net_br_attrs['name'], 'public') + process.run('firewall-cmd --reload') + utils_misc.wait_for( + lambda: check_zone(net_br_attrs['name'], 'public'), + timeout=10, ignore_errors=True) + + def run_test_zone_info(): + """ + Check zone info with firewalld-cmd + """ + check_zone_info(bridge_name, 'libvirt') + + def run_test_zone_libvirt_managed(): + br_attrs = eval(params.get('br_attrs', {})) + default_zone = params.get('default_zone') + + virsh.net_dumpxml(net_name, **VIRSH_ARGS) + net_attrs = NetworkXML.new_from_net_dumpxml(net_name).fetch_attrs() + net_br_attrs = net_attrs['bridge'] + if not set(br_attrs.items()).issubset(set(net_br_attrs.items())): + test.fail( + f'libvirt should create a linux bridge named ' + f'{net_br_attrs["name"]}, with stp=on, delay=0') + + check_zone(net_br_attrs['name'], default_zone) + if default_zone in ('no zone', 'libvirt-routed'): + logging.info(f'Skip checking zone info for "{default_zone}"') + else: + check_zone_info(net_br_attrs['name'], default_zone) + process.run('firewall-cmd --reload') + utils_misc.wait_for( + lambda: check_zone(net_br_attrs['name'], default_zone), + timeout=10, ignore_errors=True) + test_zone = eval('run_test_zone_%s' % case) test_zone() @@ -235,4 +294,6 @@ def run_test_iface_acpi(case): finally: bk_netxml.sync() + if net_attrs: + libvirt_network.create_or_del_network(net_attrs, is_del=True) bk_xml.sync() From 26ff43a5aa29d13df4ef32dcc7b575f3034580a5 Mon Sep 17 00:00:00 2001 From: Fangge Jin Date: Tue, 22 Apr 2025 16:16:56 +0800 Subject: [PATCH 0945/1055] guest_agent: Fix image mode path permissions Signed-off-by: Fangge Jin --- libvirt/tests/cfg/guest_agent/guest_agent.cfg | 4 ++-- libvirt/tests/cfg/virsh_cmd/domain/virsh_domfsinfo.cfg | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/guest_agent/guest_agent.cfg b/libvirt/tests/cfg/guest_agent/guest_agent.cfg index 8628dddb338..bce252849b8 100644 --- a/libvirt/tests/cfg/guest_agent/guest_agent.cfg +++ b/libvirt/tests/cfg/guest_agent/guest_agent.cfg @@ -13,9 +13,9 @@ con_label = "system_u:object_r:qemu_var_run_t:s0" variants: - auto_gen_path: - src_path = "/40-a/org.qemu.guest_agent.0" + src_path = "/var/org.qemu.guest_agent.0" - random: - src_path = "/test/agent" + src_path = "/var/agent" - hotplug_ga_without_tgt_type: only ga_started hotplug_ga_without_tgt_type = "yes" diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_domfsinfo.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_domfsinfo.cfg index 24ecdfc56a5..c469f5ae3a0 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_domfsinfo.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_domfsinfo.cfg @@ -11,7 +11,7 @@ - no_freezed_fs: - nfs: nfs_mount = "yes" - mount_dir = "/test" + mount_dir = "/var/test" - quiet_mode: quiet_mode = "yes" - hotplug_unplug: From 493553d060d8768ce785987570112a1d5f8272d6 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Fri, 18 Apr 2025 11:03:51 +0800 Subject: [PATCH 0946/1055] virtual_disks_iothreads_queue: update err message According to the libvirt code changes, let's update the error messages. Signed-off-by: Dan Zheng --- .../virtual_disks_iothreads_queue.cfg | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg index cd6c4ffa11c..d69fc0ae61b 100755 --- a/libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg @@ -32,43 +32,43 @@ queue_num = "3" driver = {'name': 'qemu', 'queues': '${queue_num}'} driver_iothreads = {'iothread': [{'queue': [{'id': '0'}, {'id': '1'}], 'id': '1'}, {'id': '2'}]} - err_msg = "unsupported configuration: iothread to queue mapping must be provided for all iothreads or for none" + err_msg = "iothread to queue mapping must be provided for all iothreads or for none" - no_iothreads_define: only coldplug..round_robin vm_attrs = {'iothreads': 0} queue_num = "2" driver = {'name': 'qemu', 'queues': '${queue_num}'} driver_iothreads = {'iothread': [{'id': '1'}, {'id': '2'}]} - err_msg = "unsupported configuration: Disk iothread '1' not defined in iothreadid" + err_msg = "iothread '1' not defined in iothreadid" - dup_mapping_same_iothread: only coldplug..round_robin queue_num = "3" driver = {'name': 'qemu', 'queues': '${queue_num}'} driver_iothreads = {'iothread': [{'id': '1'}, {'id': '1'}]} - err_msg = "unsupported configuration: Duplicate mapping for iothread '1'" + err_msg = "d|Duplicate mapping for iothread '1'" - dup_queue_assigned: only coldplug..user_defined queue_num = "2" driver = {'name': 'qemu', 'queues': '${queue_num}'} driver_iothreads = {'iothread': [{'queue': [{'id': '0'}], 'id': '1'}, {'queue': [{'id': '1'}], 'id': '2'}, {'queue': [{'id': '1'}], 'id': '3'}]} - err_msg = "unsupported configuration: disk iothread queue '1' is already assigned" + err_msg = "iothread queue '1' is already assigned" - no_queue_number: only coldplug..user_defined driver = {'name': 'qemu', 'type': 'qcow2'} driver_iothreads = {'iothread': [{'queue': [{'id': '0'}], 'id': '1'}, {'queue': [{'id': '2'}], 'id': '2'}]} - err_msg = "unsupported configuration: disk 'queue' count must be configured for explicit iothread to queue mapping" + err_msg = "'queue' count must be configured for explicit iothread to queue mapping" - missing_iothread_mapping: only coldplug..user_defined queue_num = "3" driver = {'name': 'qemu', 'queues': '${queue_num}'} driver_iothreads = {'iothread': [{'queue': [{'id': '2'}], 'id': '1'}, {'queue': [{'id': '1'}], 'id': '2'}]} - err_msg = "unsupported configuration: missing iothread mapping for queue '0'" + err_msg = "missing iothread mapping for queue '0'" - queue_id_out_of_range: only coldplug..user_defined queue_num = "2" driver = {'name': 'qemu', 'queues': '${queue_num}'} driver_iothreads = {'iothread': [{'queue': [{'id': '0'}], 'id': '1'}, {'queue': [{'id': '1'}], 'id': '2'}, {'queue': [{'id': '2'}], 'id': '3'}]} - err_msg = "unsupported configuration: disk iothread queue '${queue_num}'.*out of range" + err_msg = "iothread queue '${queue_num}'.*out of range" - update_delete_iothread: only coldplug..round_robin status_error = yes From ec295cb4fb18aa4eed0caea366a25a47c392f953 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Sat, 7 Oct 2023 16:58:57 +0800 Subject: [PATCH 0947/1055] hmat_info: add case to set HMAT in vm Signed-off-by: Dan Zheng --- .../cfg/numa/guest_numa_hmat/hmat_info.cfg | 50 ++++ .../src/numa/guest_numa_hmat/hmat_info.py | 221 ++++++++++++++++++ 2 files changed, 271 insertions(+) create mode 100644 libvirt/tests/cfg/numa/guest_numa_hmat/hmat_info.cfg create mode 100644 libvirt/tests/src/numa/guest_numa_hmat/hmat_info.py diff --git a/libvirt/tests/cfg/numa/guest_numa_hmat/hmat_info.cfg b/libvirt/tests/cfg/numa/guest_numa_hmat/hmat_info.cfg new file mode 100644 index 00000000000..d10c65aee5f --- /dev/null +++ b/libvirt/tests/cfg/numa/guest_numa_hmat/hmat_info.cfg @@ -0,0 +1,50 @@ +- guest_numa_hmat.hmat_info: + type = hmat_info + take_regular_screendumps = no + start_vm = "no" + single_host_node = yes + cpu_mode = 'host-model' + no s390-virtio + aarch64: + cpu_mode = 'host-passthrough' + dmesg_pattern_0 = "Flags:00 Type:Access Latency Initiator, Initiator-Target[0-1]:10 nsec, Flags:00 Type:Read Latency Initiator, Initiator-Target[0-0]:6 nsec," + dmesg_pattern_1 = "Initiator-Target[1-1]:11 nsec, Flags:00 Type:Write Latency Initiator,Initiator-Target[0-0]:7 nsec, Initiator-Target[1-1]:12 nsec," + dmesg_pattern_2 = "Flags:00 Type:Access Bandwidth Initiator, Initiator-Target[0-1]:100 MB/s, Flags:00 Type:Read Bandwidth Initiator, Initiator-Target[0-0]:201 MB/s," + dmesg_pattern_3 = "Initiator-Target[1-1]:101 MB/s, Flags:00 Type:Write Bandwidth Initiator, Initiator-Target[0-0]:202 MB/s, Initiator-Target[1-1]:102 MB/s," + dmesg_pattern_4 = "Flags:01 Type:Read Latency Initiator, Initiator-Target[0-0]:5 nsec, Flags:01 Type:Access Bandwidth Initiator, Initiator-Target[0-0]:200 MB/s" + dmesg_pattern = "${dmesg_pattern_0}${dmesg_pattern_1}${dmesg_pattern_2}${dmesg_pattern_3}${dmesg_pattern_4}" + numa_cell0_cache0 = "{'size_unit': 'KiB', 'line_unit': 'B', 'policy': 'writeback', 'associativity': 'direct', 'line_value': '8', 'level': '1', 'size_value': '10'}" + numa_cell0_cache1 = "{'size_unit': 'KiB', 'line_unit': 'B', 'policy': 'writethrough', 'associativity': 'full', 'line_value': '16', 'level': '2', 'size_value': '128'}" + numa_cell0 = "{'caches': [${numa_cell0_cache0}, ${numa_cell0_cache1}], 'memory': '1048576', 'cpus': '0-1', 'unit': 'KiB', 'id': '0'}" + numa_cell1_cache0 = "{'size_unit': 'KiB', 'line_unit': 'B', 'policy': 'none', 'associativity': 'none','line_value': '8', 'level': '1', 'size_value': '10'}" + numa_cell1 = "{'caches': [${numa_cell1_cache0}], 'memory': '1048576', 'cpus': '2-3', 'unit': 'KiB', 'id': '1'}" + bandwidth0 = "{'cache': '1', 'initiator': '0', 'target': '0', 'type': 'access', 'unit': 'KiB', 'value': '204800'}" + bandwidth1 = "{'initiator': '0', 'target': '0', 'type': 'read', 'unit': 'KiB', 'value': '205824'}" + bandwidth2 = "{'initiator': '0', 'target': '0', 'type': 'write', 'unit': 'KiB', 'value': '206848'}" + bandwidth3 = "{'initiator': '0', 'target': '1', 'type': 'access', 'unit': 'KiB', 'value': '102400'}" + bandwidth4 = "{'initiator': '1', 'target': '1', 'type': 'read', 'unit': 'KiB', 'value': '103424'}" + bandwidth5 = "{'initiator': '1', 'target': '1', 'type': 'write', 'unit': 'KiB', 'value': '104448'}" + latency0 = "{'cache': '1', 'initiator': '0', 'target': '0', 'type': 'read', 'value': '5'}" + latency1 = "{'initiator': '0', 'target': '0', 'type': 'read', 'value': '6'}" + latency2 = "{'initiator': '0', 'target': '0', 'type': 'write', 'value': '7'}" + latency3 = "{'initiator': '0', 'target': '1', 'type': 'access', 'value': '10'}" + latency4 = "{'initiator': '1', 'target': '1', 'type': 'read', 'value': '11'}" + latency5 = "{'initiator': '1', 'target': '1', 'type': 'write', 'value': '12'}" + bandwidth = "[${bandwidth0}, ${bandwidth1}, ${bandwidth2}, ${bandwidth3}, ${bandwidth4}, ${bandwidth5}]" + latency = "[${latency0}, ${latency1}, ${latency2}, ${latency3}, ${latency4}, ${latency5}]" + interconnects = "'interconnects': {'bandwidth':${bandwidth}, 'latency': ${latency}}" + numa_cell = "'numa_cell': [${numa_cell0}, ${numa_cell1}]" + vm_attrs = "{'vcpu': 4, 'cpu': {'mode': '${cpu_mode}', ${numa_cell}, ${interconnects}}}" + qemu_check_initiator = "-numa node,nodeid=0,cpus=0-1,initiator=0,memdev=ram-node0 .*-numa node,nodeid=1,cpus=2-3,initiator=1,memdev=ram-node1" + qemu_check_lb_0 = "-numa hmat-lb,initiator=0,target=0,hierarchy=first-level,data-type=read-latency,latency=5 -numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=read-latency,latency=6" + qemu_check_lb_1 = "-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=write-latency,latency=7 -numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,latency=10" + qemu_check_lb_2 = "-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=read-latency,latency=11 -numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=write-latency,latency=12" + qemu_check_lb_3 = "-numa hmat-lb,initiator=0,target=0,hierarchy=first-level,data-type=access-bandwidth,bandwidth=204800K -numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=read-bandwidth,bandwidth=205824K" + qemu_check_lb_4 = "-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=write-bandwidth,bandwidth=206848K -numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,bandwidth=102400K" + qemu_check_lb_5 = "-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=read-bandwidth,bandwidth=103424K -numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=write-bandwidth,bandwidth=104448K" + qemu_check_cache_0 = "-numa hmat-cache,node-id=0,size=10K,level=1,associativity=direct,policy=write-back,line=8" + qemu_check_cache_1 = "-numa hmat-cache,node-id=0,size=128K,level=2,associativity=complex,policy=write-through,line=16" + qemu_check_cache_2 = "-numa hmat-cache,node-id=1,size=10K,level=1,associativity=none,policy=none,line=8" + variants: + - default: + func_supported_since_libvirt_ver = (7, 5, 0) \ No newline at end of file diff --git a/libvirt/tests/src/numa/guest_numa_hmat/hmat_info.py b/libvirt/tests/src/numa/guest_numa_hmat/hmat_info.py new file mode 100644 index 00000000000..9286e1dd83b --- /dev/null +++ b/libvirt/tests/src/numa/guest_numa_hmat/hmat_info.py @@ -0,0 +1,221 @@ +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 +# Author: Dan Zheng +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from virttest import libvirt_version +from virttest import utils_libvirtd +from virttest import utils_package +from virttest import virsh +from virttest import ssh_key + +from virttest.libvirt_xml import capability_xml +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt + +from provider.numa import numa_base +from provider.virtual_network import network_base + + +def setup_default(test_obj): + """ + Default setup function for the test + + :param test_obj: NumaTest object + """ + test_obj.setup() + test_obj.test.log.debug("Step: setup is done") + + +def prepare_vm_xml(test_obj): + """ + Customize the vm xml + + :param test_obj: NumaTest object + :return: VMXML object updated + """ + vmxml = test_obj.prepare_vm_xml() + test_obj.test.log.debug("Step: vm xml before defining:\n%s", vmxml) + return vmxml + + +def verify_guest_dmesg(test_obj, vm_session): + """ + Verify messages in guest dmesg output + + :param test_obj: NumaTest object + :param vm_session: vm session + """ + dmesg_pattern = test_obj.params.get("dmesg_pattern") + search_list = dmesg_pattern.split(",") + cmd_dmesg = 'dmesg | grep hmat' + status, output = vm_session.cmd_status_output(cmd_dmesg) + if status: + test_obj.test.error("Can not find any message with command '%s'" % cmd_dmesg) + + for search_item in search_list: + if not output.count(search_item): + test_obj.test.fail("Expect '%s' in guest dmesg, but not found" % search_item) + else: + test_obj.test.log.debug("Verify '%s' in guest dmesg - PASS", search_item) + test_obj.test.log.debug("Verify guest dmesg - PASS") + + +def verify_qemu_command_line(test_obj): + """ + Verify qemu command line + + :param test_obj: NumaTest object + """ + all_search_keys = [key for key in list(test_obj.params.keys()) if "qemu_check" in key] + + all_search_values = [test_obj.params.get(key) for key in all_search_keys] + test_obj.test.log.debug("search string:%s", all_search_values) + libvirt.check_qemu_cmd_line(all_search_values, expect_exist=True) + test_obj.test.log.debug("Verify qemu command line - PASS") + + +def verify_hmat_info(test_obj, vm_session): + """ + Verify HMAT info + + :param test_obj: NumaTest object + :param vm_session: vm session + """ + if not utils_package.package_install("libvirt", vm_session): + test_obj.test.fail("Failed to install libvirt on guest") + if libvirt_version.version_compare(9, 0, 0): + for daemon_name in ["virtproxyd.socket", "virtqemud.socket"]: + daemon = utils_libvirtd.Libvirtd(daemon_name, session=vm_session) + daemon.start() + test_obj.test.log.debug("%s is started", daemon_name) + + iface_mac = vm_xml.VMXML.get_first_mac_by_name(test_obj.vm.name) + vm_ip = network_base.get_vm_ip(vm_session, iface_mac) + if not vm_ip: + test_obj.test.error("Can not get vm IP") + connect_uri = "qemu+ssh://%s/system" % vm_ip + vm_user = test_obj.params.get("username", "root") + vm_user_passwd = test_obj.params.get("password") + ssh_key.setup_ssh_key(vm_ip, vm_user, vm_user_passwd) + output = virsh.capabilities("", uri=connect_uri, + ignore_status=False, debug=True) + cap_xml = capability_xml.CapabilityXML() + cap_xml.xml = output + + verify_hmat_cache_by_virsh_capabilities(test_obj, cap_xml) + verify_hmat_interconnects_by_virsh_capabilities(test_obj, cap_xml) + + +def verify_hmat_cache_by_virsh_capabilities(test_obj, cap_xml): + """ + Verify HMAT cache info + + :param test_obj: NumaTest object + :param cap_xml: CapabilityXML instance + """ + def _compare(cell_id, cache_id, expect_cache, actual_cache): + if actual_cache != expect_cache: + test_obj.test.fail("Expect cache %d in cell %d to be '%s', " + "but found '%s'" % (cache_id, cell_id, + expect_cache, + actual_cache)) + + numa_cell0_cache0 = eval(test_obj.params.get("numa_cell0_cache0")) + numa_cell0_cache1 = eval(test_obj.params.get("numa_cell0_cache1")) + numa_cell1_cache0 = eval(test_obj.params.get("numa_cell1_cache0")) + cells = cap_xml.cells_topology.get_cell() + + actual_cell0_cache0 = cells[0].cache[0].fetch_attrs() + actual_cell0_cache1 = cells[0].cache[1].fetch_attrs() + actual_cell1_cache0 = cells[1].cache[0].fetch_attrs() + _compare(0, 0, numa_cell0_cache0, actual_cell0_cache0) + _compare(0, 1, numa_cell0_cache1, actual_cell0_cache1) + _compare(1, 0, numa_cell1_cache0, actual_cell1_cache0) + test_obj.test.log.debug("Verify HMAT cache information in virsh capability - PASS") + + +def verify_hmat_interconnects_by_virsh_capabilities(test_obj, cap_xml): + """ + Verify HMAT interconnects info + + :param test_obj: NumaTest object + :param cap_xml: CapabilityXML instance + """ + def _compare(conf_items, actual_items, item_name): + conf_sublist = [] + for item in conf_items: + # Ignore checking "access" because kernel does not expose it yet + if item["type"] == "access" or item.get("cache"): + continue + conf_sublist.append(item) + if len(conf_sublist) != len(actual_items): + test_obj.test.fail("Expect %s to be '%s', " + "but found '%s'" % (item_name, + conf_sublist, + actual_items)) + for conf_item in conf_sublist: + if conf_item not in actual_items: + test_obj.test.fail("Expect %s to include '%s', " + "but not found in '%s'" % (item_name, + conf_item, + actual_items)) + else: + test_obj.test.log.debug("Verify '%s' in HMAT interconnects of " + "virsh capability in guest - PASS", item_name) + interconnects = cap_xml.cells_topology.interconnects.fetch_attrs() + conf_bandwidth = eval(test_obj.params.get("bandwidth")) + conf_latency = eval(test_obj.params.get("latency")) + _compare(conf_bandwidth, interconnects["bandwidth"], "bandwidth") + _compare(conf_latency, interconnects["latency"], "latency") + test_obj.test.log.debug("Verify HMAT interconnects information of " + "virsh capability in guest - PASS") + + +def run_default(test_obj): + """ + Default run function for the test + + :param test_obj: NumaTest object + """ + test_obj.test.log.debug("Step: prepare vm xml") + vmxml = prepare_vm_xml(test_obj) + test_obj.test.log.debug("Step: define vm") + virsh.define(vmxml.xml, **test_obj.virsh_dargs) + test_obj.test.log.debug("Step: start vm") + ret = virsh.start(test_obj.vm.name, **test_obj.virsh_dargs) + test_obj.test.log.debug("After vm is started, vm xml:\n" + "%s", vm_xml.VMXML.new_from_dumpxml(test_obj.vm.name)) + vm_session = test_obj.vm.wait_for_login() + verify_qemu_command_line(test_obj) + verify_guest_dmesg(test_obj, vm_session) + verify_hmat_info(test_obj, vm_session) + + +def teardown_default(test_obj): + """ + Default teardown function for the test + + :param test_obj: NumaTest object + """ + test_obj.teardown() + test_obj.test.log.debug("Step: teardown is done") + + +def run(test, params, env): + """ + Test for numa memory binding with emulator thread pin + """ + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + numatest_obj = numa_base.NumaTest(vm, params, test) + try: + setup_default(numatest_obj) + run_default(numatest_obj) + finally: + teardown_default(numatest_obj) From 6dc502bf4d1b1713e998d3d89b822a349b9ae1e2 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Wed, 23 Apr 2025 10:25:00 +0800 Subject: [PATCH 0948/1055] memory_binding_setting: fix daemon restart Libvirt daemon needs to be restarted after hugepage filesystem is mounted. Signed-off-by: Dan Zheng --- .../numa/guest_numa_node_tuning/memory_binding_setting.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py b/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py index e2f663ce3a4..9eccdfe006a 100644 --- a/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/memory_binding_setting.py @@ -7,6 +7,7 @@ # # Author: Dan Zheng # +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ import os @@ -17,8 +18,9 @@ from virttest import libvirt_cgroup from virttest import libvirt_version -from virttest import virsh from virttest import test_setup +from virttest import utils_libvirtd +from virttest import virsh from virttest.libvirt_xml import vm_xml from virttest.utils_test import libvirt from virttest.utils_libvirt import libvirt_numa @@ -42,6 +44,8 @@ def setup_default(test_obj): target_hugepages = test_obj.params.get('target_hugepages') hpc.set_node_num_huge_pages(target_hugepages, all_nodes[0], expected_hugepage_size) hpc.set_node_num_huge_pages(target_hugepages, all_nodes[1], expected_hugepage_size) + hpc.mount_hugepage_fs() + utils_libvirtd.Libvirtd().restart() test_obj.test.log.debug("Get first node hugepage is " "%d", hpc.get_node_num_huge_pages(all_nodes[0], expected_hugepage_size)) From c0be265f0f7536c3e323bfd0e441dc7033fa1784 Mon Sep 17 00:00:00 2001 From: Fangge Jin Date: Tue, 22 Apr 2025 14:19:59 +0800 Subject: [PATCH 0949/1055] guestinfo: Check guest_bus in the output "guest_bus" is added to the output of "virsh guestinfo --disk". Supported since libvirt-11.2.0 Signed-off-by: Fangge Jin --- .../cfg/virsh_cmd/domain/virsh_guestinfo.cfg | 1 + .../src/virsh_cmd/domain/virsh_guestinfo.py | 37 +++++++++++++++---- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_guestinfo.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_guestinfo.cfg index 123d89e3f2d..c9517ca176d 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_guestinfo.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_guestinfo.cfg @@ -22,6 +22,7 @@ option = "--disk" disk_target_name = "vdb" disk_name = "vdb.img" + disk_target_bus = "virtio" serial_num = "12345678" - interface_info: option = "--interface" diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_guestinfo.py b/libvirt/tests/src/virsh_cmd/domain/virsh_guestinfo.py index 255bba0c9d5..bea2acf3983 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_guestinfo.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_guestinfo.py @@ -45,20 +45,40 @@ def check_attached_disk_info(disk_info, target_name): :param target_name: the target name for the attached disk :return: the attached disk info returned from virsh guestinfo --disk """ - attached_disk_info_reported = False + serial_num_reported = False + bus_type_reported = False disk_logical_name = '/dev/%s' % target_name for i in range(int(disk_info['disk.count'])): prefix = 'disk.' + str(i) + '.' try: - if disk_info[prefix + 'alias'] == target_name: - if (disk_info[prefix + 'name'] == disk_logical_name and - disk_info[prefix + 'partition'] == 'no' and - disk_info[prefix + 'serial'] == serial_num): - attached_disk_info_reported = True - break + if (disk_info[prefix + 'alias'] == target_name and + disk_info[prefix + 'name'] == disk_logical_name and + disk_info[prefix + 'partition'] == 'no'): + support_dict = {} + support_dict["func_supported_since_libvirt_ver"] = "(7, 3, 0)" + if libvirt_version.is_libvirt_feature_supported(support_dict, ignore_error=True): + if disk_info[prefix + 'serial'] == serial_num: + serial_num_reported = True + logging.debug("Disk serial num is returned in guestinfo") + else: + return False + else: + # If serial is unsupported, treat it as already reported + serial_num_reported = True + support_dict["func_supported_since_libvirt_ver"] = "(11, 2, 0)" + if libvirt_version.is_libvirt_feature_supported(support_dict, ignore_error=True): + if disk_info[prefix + 'guest_bus'] == disk_target_bus: + bus_type_reported = True + logging.debug("Disk bus type is returned in guestinfo") + else: + return False + else: + # If bus_type is unsupported, treat it as already reported + bus_type_reported = True + break except KeyError: logging.error("Num %i is not the attached disk", i) - return attached_disk_info_reported + return serial_num_reported and bus_type_reported def check_guest_os_info(): """ @@ -322,6 +342,7 @@ def check_guest_interface_info(): disk_target_name = params.get("disk_target_name") disk_name = params.get("disk_name") serial_num = params.get("serial_num") + disk_target_bus = params.get("disk_target_bus") readonly_mode = ("yes" == params.get("readonly_mode")) if not libvirt_version.version_compare(6, 0, 0): From b1897cfe862809d5117db7699531bbe8a193e8e7 Mon Sep 17 00:00:00 2001 From: Fangge Jin Date: Wed, 23 Apr 2025 12:19:24 +0800 Subject: [PATCH 0950/1055] guest_agent: Fix the error message change Signed-off-by: Fangge Jin --- libvirt/tests/cfg/virsh_cmd/domain/virsh_set_user_password.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_set_user_password.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_set_user_password.cfg index 7aa4ff3d5c4..5c89f76669b 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_set_user_password.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_set_user_password.cfg @@ -36,4 +36,4 @@ err_msg = "error: failed to get domain 'not_existed_domain'" - not_existed_user: set_user_name = "not_existed_user" - err_msg = "error: internal error: unable to execute QEMU agent command 'guest-set-user-password': child process has failed to set user password" + err_msg = "error: (internal error|guest agent command failed): unable to execute QEMU agent command 'guest-set-user-password': child process has failed to set user password" From 9461a8b5276222d0d1de6a2d88486fccdeebbd6f Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 24 Apr 2025 02:19:43 -0400 Subject: [PATCH 0951/1055] Add new cpu case of hv-passthrough - RHEL-288471 - Start VM with hyperv passthrough mode Signed-off-by: Haijiao Zhao --- libvirt/tests/cfg/cpu/vm_features.cfg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libvirt/tests/cfg/cpu/vm_features.cfg b/libvirt/tests/cfg/cpu/vm_features.cfg index 17009e09cfe..66220594efe 100644 --- a/libvirt/tests/cfg/cpu/vm_features.cfg +++ b/libvirt/tests/cfg/cpu/vm_features.cfg @@ -44,6 +44,9 @@ hyperv_attr={'relaxed': {'state': 'on'}} - disable: hyperv_attr={'relaxed': {'state': 'on'}} + - passthrough: + hyperv_attr = {'mode': 'passthrough'} + qemu_include = 'hv-passthrough=on' - pmu: no pseries, s390-virtio variants: From bdaabe218cd0605cfff09c534ea21409a9162c46 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 8 Apr 2025 17:12:01 +0800 Subject: [PATCH 0952/1055] GPU: Add cases for aarch64 This PR adds: VIRT-304166 Cuda sanity test VIRT-304168 GPU driver installation/uninstallation/re-installation VIRT-304169 Hotplug/hotunplug GPU to/from VM VIRT-304167 MIG sanity test for capable GPU VIRT-304164 Start vm with a gpu hostdev type, and check the gpu device in guest. VIRT-304170 Start vm with GPU hostdev with managed=no or ignored VIRT-304171 VM lifecycle for gpu passthrough hostdev device Signed-off-by: Yingshun Cui --- libvirt/tests/cfg/gpu/hotplug_gpu.cfg | 8 + .../tests/cfg/gpu/lifecycle_vm_with_gpu.cfg | 9 + libvirt/tests/cfg/gpu/start_vm_with_gpu.cfg | 14 ++ .../start_vm_with_gpu_managed_disabled.cfg | 16 ++ libvirt/tests/cfg/gpu/vm_cuda_sanity.cfg | 10 + libvirt/tests/cfg/gpu/vm_mig_sanity.cfg | 10 + .../tests/cfg/gpu/vm_nvidia_gpu_driver.cfg | 8 + libvirt/tests/src/gpu/hotplug_gpu.py | 56 +++++ .../tests/src/gpu/lifecycle_vm_with_gpu.py | 76 ++++++ libvirt/tests/src/gpu/start_vm_with_gpu.py | 49 ++++ .../gpu/start_vm_with_gpu_managed_disabled.py | 38 +++ libvirt/tests/src/gpu/vm_cuda_sanity.py | 52 ++++ libvirt/tests/src/gpu/vm_mig_sanity.py | 79 ++++++ libvirt/tests/src/gpu/vm_nvidia_gpu_driver.py | 40 +++ provider/gpu/__init__.py | 0 provider/gpu/gpu_base.py | 235 ++++++++++++++++++ 16 files changed, 700 insertions(+) create mode 100644 libvirt/tests/cfg/gpu/hotplug_gpu.cfg create mode 100644 libvirt/tests/cfg/gpu/lifecycle_vm_with_gpu.cfg create mode 100644 libvirt/tests/cfg/gpu/start_vm_with_gpu.cfg create mode 100644 libvirt/tests/cfg/gpu/start_vm_with_gpu_managed_disabled.cfg create mode 100644 libvirt/tests/cfg/gpu/vm_cuda_sanity.cfg create mode 100644 libvirt/tests/cfg/gpu/vm_mig_sanity.cfg create mode 100644 libvirt/tests/cfg/gpu/vm_nvidia_gpu_driver.cfg create mode 100644 libvirt/tests/src/gpu/hotplug_gpu.py create mode 100644 libvirt/tests/src/gpu/lifecycle_vm_with_gpu.py create mode 100644 libvirt/tests/src/gpu/start_vm_with_gpu.py create mode 100644 libvirt/tests/src/gpu/start_vm_with_gpu_managed_disabled.py create mode 100644 libvirt/tests/src/gpu/vm_cuda_sanity.py create mode 100644 libvirt/tests/src/gpu/vm_mig_sanity.py create mode 100644 libvirt/tests/src/gpu/vm_nvidia_gpu_driver.py create mode 100644 provider/gpu/__init__.py create mode 100644 provider/gpu/gpu_base.py diff --git a/libvirt/tests/cfg/gpu/hotplug_gpu.cfg b/libvirt/tests/cfg/gpu/hotplug_gpu.cfg new file mode 100644 index 00000000000..fc55c007e42 --- /dev/null +++ b/libvirt/tests/cfg/gpu/hotplug_gpu.cfg @@ -0,0 +1,8 @@ +- gpu.lifecycle_vm_with_gpu: + type = lifecycle_vm_with_gpu + start_vm = "no" + + only aarch64 + variants: + - gpu_address: + hostdev_dict = {'mode': 'subsystem', 'type': 'pci', 'source': {'untyped_address': gpu_pci_addr}, 'managed': 'yes'} diff --git a/libvirt/tests/cfg/gpu/lifecycle_vm_with_gpu.cfg b/libvirt/tests/cfg/gpu/lifecycle_vm_with_gpu.cfg new file mode 100644 index 00000000000..dbeb02931b3 --- /dev/null +++ b/libvirt/tests/cfg/gpu/lifecycle_vm_with_gpu.cfg @@ -0,0 +1,9 @@ +- gpu.lifecycle_vm_with_gpu: + type = lifecycle_vm_with_gpu + start_vm = "no" + unsupported_error = "VFIO migration is not supported in kernel" + + only aarch64 + variants: + - gpu_address: + hostdev_dict = {'mode': 'subsystem', 'type': 'pci', 'source': {'untyped_address': gpu_pci_addr}, 'managed': 'yes'} diff --git a/libvirt/tests/cfg/gpu/start_vm_with_gpu.cfg b/libvirt/tests/cfg/gpu/start_vm_with_gpu.cfg new file mode 100644 index 00000000000..a6c0e4e9ca4 --- /dev/null +++ b/libvirt/tests/cfg/gpu/start_vm_with_gpu.cfg @@ -0,0 +1,14 @@ +- gpu.start_vm_with_gpu: + type = start_vm_with_gpu + start_vm = "no" + + only aarch64 + variants: + - gpu_address: + variants: + - managed_yes: + hostdev_dict = {'mode': 'subsystem', 'type': 'pci', 'source': {'untyped_address': gpu_pci_addr}, 'managed': 'yes'} + - managed_no: + hostdev_dict = {'mode': 'subsystem', 'type': 'pci', 'source': {'untyped_address': gpu_pci_addr}, 'managed': 'no'} + - managed_ignore: + hostdev_dict = {'mode': 'subsystem', 'type': 'pci', 'source': {'untyped_address': gpu_pci_addr}} diff --git a/libvirt/tests/cfg/gpu/start_vm_with_gpu_managed_disabled.cfg b/libvirt/tests/cfg/gpu/start_vm_with_gpu_managed_disabled.cfg new file mode 100644 index 00000000000..4e74751e75e --- /dev/null +++ b/libvirt/tests/cfg/gpu/start_vm_with_gpu_managed_disabled.cfg @@ -0,0 +1,16 @@ +- gpu.managed_disabled_gpu: + type = start_vm_with_gpu_managed_disabled + start_vm = "no" + error_msg = "Unmanaged PCI device" + + only aarch64 + variants: + - gpu_address: + variants: + - managed_no: + hostdev_dict = {'mode': 'subsystem', 'type': 'pci', 'source': {'untyped_address': gpu_pci_addr}, 'managed': 'no'} + - managed_ignore: + hostdev_dict = {'mode': 'subsystem', 'type': 'pci', 'source': {'untyped_address': gpu_pci_addr}} + variants test_scenario: + - define_start: + - hotplug: diff --git a/libvirt/tests/cfg/gpu/vm_cuda_sanity.cfg b/libvirt/tests/cfg/gpu/vm_cuda_sanity.cfg new file mode 100644 index 00000000000..eadec96aca4 --- /dev/null +++ b/libvirt/tests/cfg/gpu/vm_cuda_sanity.cfg @@ -0,0 +1,10 @@ +- gpu.vm_cuda_sanity: + type = vm_cuda_sanity + start_vm = "no" + cuda_samples_path = "../../deps/gpu/cuda-samples.tar.gz" + cuda_tests = ["./cuda-samples/build/Samples/1_Utilities/deviceQuery/deviceQuery", "./cuda-samples/build/Samples/1_Utilities/bandwidthTest/bandwidthTest", "./cuda-samples/build/Samples//0_Introduction/simpleMultiCopy/simpleMultiCopy"] + + only aarch64 + variants: + - gpu_address: + hostdev_dict = {'mode': 'subsystem', 'type': 'pci', 'source': {'untyped_address': gpu_pci_addr}, 'managed': 'yes'} diff --git a/libvirt/tests/cfg/gpu/vm_mig_sanity.cfg b/libvirt/tests/cfg/gpu/vm_mig_sanity.cfg new file mode 100644 index 00000000000..4d78348bbbd --- /dev/null +++ b/libvirt/tests/cfg/gpu/vm_mig_sanity.cfg @@ -0,0 +1,10 @@ +- gpu.mig_sanity: + type = vm_mig_sanity + start_vm = "no" + cuda_samples_path = "../../deps/gpu/cuda-samples.tar.gz" + cuda_test = "./cuda-samples/build/Samples/5_Domain_Specific/BlackScholes/BlackScholes" + + only aarch64 + variants: + - gpu_address: + hostdev_dict = {'mode': 'subsystem', 'type': 'pci', 'source': {'untyped_address': gpu_pci_addr}, 'managed': 'yes'} diff --git a/libvirt/tests/cfg/gpu/vm_nvidia_gpu_driver.cfg b/libvirt/tests/cfg/gpu/vm_nvidia_gpu_driver.cfg new file mode 100644 index 00000000000..a7f9ef175b8 --- /dev/null +++ b/libvirt/tests/cfg/gpu/vm_nvidia_gpu_driver.cfg @@ -0,0 +1,8 @@ +- gpu.nvidia_driver: + type = vm_nvidia_gpu_driver + start_vm = "no" + + only aarch64 + variants: + - gpu_address: + hostdev_dict = {'mode': 'subsystem', 'type': 'pci', 'source': {'untyped_address': gpu_pci_addr}, 'managed': 'yes'} diff --git a/libvirt/tests/src/gpu/hotplug_gpu.py b/libvirt/tests/src/gpu/hotplug_gpu.py new file mode 100644 index 00000000000..399ce693cde --- /dev/null +++ b/libvirt/tests/src/gpu/hotplug_gpu.py @@ -0,0 +1,56 @@ +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.gpu import gpu_base + + +def run(test, params, env): + """ + Hotplug/unplug GPU device + """ + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + virsh_args = {'ignore_status': False, 'debug': True} + + gpu_test = gpu_base.GPUTest(vm, test, params) + hostdev_dict = gpu_test.parse_hostdev_dict() + + try: + gpu_test.setup_default() + test.log.info("TEST_STEP: Start the VM") + vm.start() + vm_session = vm.wait_for_login() + + test.log.info("TEST_STEP: Hotplug a gpu device to vm") + gpu_dev = libvirt_vmxml.create_vm_device_by_type("hostdev", hostdev_dict) + virsh.attach_device(vm.name, gpu_dev.xml, **virsh_args) + gpu_test.check_gpu_dev(vm) + test.log.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + gpu_test.install_latest_driver(vm_session) + gpu_test.nvidia_smi_check(vm_session) + + test.log.info("TEST_STEP: Unplug a gpu device from vm") + vm_hostdev = vm_xml.VMXML.new_from_dumpxml(vm.name)\ + .devices.by_device_tag("hostdev")[0] + virsh.detach_device(vm.name, vm_hostdev.xml, + wait_for_event=True, event_timeout=30, + **virsh_args) + gpu_test.check_gpu_dev(vm, True) + + test.log.info("TEST_STEP: Hotplug back the gpu device") + virsh.attach_device(vm.name, gpu_dev.xml, **virsh_args) + gpu_test.check_gpu_dev(vm) + gpu_test.nvidia_smi_check(vm_session) + + test.log.info("TEST_STEP: Check gpu device exclusivity") + res = virsh.attach_device(vm.name, gpu_dev.xml, debug=True) + libvirt.check_result(res, "in use") + gpu_test.check_gpu_dev(vm) + gpu_test.nvidia_smi_check(vm_session) + vm_session.close() + finally: + gpu_test.teardown_default() diff --git a/libvirt/tests/src/gpu/lifecycle_vm_with_gpu.py b/libvirt/tests/src/gpu/lifecycle_vm_with_gpu.py new file mode 100644 index 00000000000..5da774c641d --- /dev/null +++ b/libvirt/tests/src/gpu/lifecycle_vm_with_gpu.py @@ -0,0 +1,76 @@ +import os + +from virttest import data_dir +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.gpu import gpu_base + + +def run(test, params, env): + """ + Lifecycle test on vm with GPU device + """ + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + virsh_args = {'ignore_status': False, 'debug': True} + unsupported_error = params.get("unsupported_error") + gpu_test = gpu_base.GPUTest(vm, test, params) + hostdev_dict = gpu_test.parse_hostdev_dict() + + try: + gpu_test.setup_default() + libvirt_vmxml.modify_vm_device( + vm_xml.VMXML.new_from_dumpxml(vm.name), "hostdev", + hostdev_dict) + test.log.info("TEST_STEP: Start the VM") + vm.start() + test.log.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + gpu_test.check_gpu_dev(vm) + vm_session = vm.wait_for_login() + gpu_test.install_latest_driver(vm_session) + gpu_test.nvidia_smi_check(vm_session) + vm_session.close() + + test.log.info("TEST_STEP: Shudown and start VM") + virsh.shutdown(vm.name, **virsh_args, wait_for_event=True) + if not vm.wait_for_shutdown(): + test.error('VM failed to shutdown in 60s') + virsh.start(vm.name, **virsh_args) + gpu_test.check_gpu_dev(vm) + + test.log.info("TEST_STEP: Reboot VM") + virsh.reboot(vm.name, **virsh_args) + gpu_test.check_gpu_dev(vm) + + test.log.info("TEST_STEP: Reset VM") + virsh.reset(vm.name, **virsh_args) + gpu_test.check_gpu_dev(vm) + vm_session = vm.wait_for_login() + gpu_test.nvidia_smi_check(vm_session) + vm_session.close() + + test.log.info("TEST_STEP: Save the VM.") + save_path = os.path.join(data_dir.get_tmp_dir(), vm.name + '.save') + res = virsh.save(vm.name, save_path, debug=True) + libvirt.check_result(res, unsupported_error) + res = virsh.managedsave(vm.name, debug=True) + libvirt.check_result(res, unsupported_error) + res = virsh.snapshot_create(vm.name, debug=True) + libvirt.check_result(res, unsupported_error) + gpu_test.check_gpu_dev(vm) + + test.log.info("TEST_STEP: Suspend and resume the vm.") + virsh.suspend(vm.name, **virsh_args) + if not libvirt.check_vm_state(vm_name, "paused"): + test.fail("VM should be paused!") + virsh.resume(vm.name, **virsh_args) + if not libvirt.check_vm_state(vm_name, "running"): + test.fail("VM should be running!") + gpu_test.check_gpu_dev(vm) + + finally: + gpu_test.teardown_default() diff --git a/libvirt/tests/src/gpu/start_vm_with_gpu.py b/libvirt/tests/src/gpu/start_vm_with_gpu.py new file mode 100644 index 00000000000..4484615dc82 --- /dev/null +++ b/libvirt/tests/src/gpu/start_vm_with_gpu.py @@ -0,0 +1,49 @@ +from virttest import utils_misc +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_libvirt import libvirt_vfio + +from provider.gpu import gpu_base + + +def run(test, params, env): + """ + Start vm with GPU device + """ + + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + gpu_test = gpu_base.GPUTest(vm, test, params) + dev_name = gpu_test.gpu_dev_name + dev_pci = gpu_test.gpu_pci + hostdev_dict = gpu_test.parse_hostdev_dict() + managed_disabled = hostdev_dict.get('managed') != "yes" + + try: + gpu_test.setup_default(dev_name=dev_name, + managed_disabled=managed_disabled) + libvirt_vmxml.modify_vm_device( + vm_xml.VMXML.new_from_dumpxml(vm.name), "hostdev", + hostdev_dict) + test.log.info("TEST_STEP: Start the VM") + vm.start() + test.log.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + gpu_test.check_gpu_dev(vm) + libvirt_vfio.check_vfio_pci(dev_pci) + + test.log.info("TEST_STEP: Destroy VM") + vm.destroy(gracefully=False) + + if not utils_misc.wait_for( + lambda: libvirt_vfio.check_vfio_pci( + dev_pci, not managed_disabled, True), 10, 5): + test.fail("Got incorrect driver!") + if managed_disabled: + virsh.nodedev_reattach(dev_name, debug=True, ignore_status=False) + libvirt_vfio.check_vfio_pci(dev_pci, True) + finally: + gpu_test.teardown_default( + managed_disabled=managed_disabled, + dev_name=dev_name) diff --git a/libvirt/tests/src/gpu/start_vm_with_gpu_managed_disabled.py b/libvirt/tests/src/gpu/start_vm_with_gpu_managed_disabled.py new file mode 100644 index 00000000000..ff222b27a5b --- /dev/null +++ b/libvirt/tests/src/gpu/start_vm_with_gpu_managed_disabled.py @@ -0,0 +1,38 @@ +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.gpu import gpu_base + + +def run(test, params, env): + """ + Start vm with GPU device with managed=no or ignored + """ + error_msg = params.get("error_msg", "Unmanaged") + test_scenario = params.get("test_scenario") + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + gpu_test = gpu_base.GPUTest(vm, test, params) + hostdev_dict = gpu_test.parse_hostdev_dict() + + try: + gpu_test.setup_default() + if test_scenario == "define_start": + test.log.info("TEST_STEP: Start the VM") + libvirt_vmxml.modify_vm_device( + vm_xml.VMXML.new_from_dumpxml(vm.name), "hostdev", + hostdev_dict) + res = virsh.start(vm.name, debug=True) + else: + test.log.info("TEST_STEP: Hotplug a gpu device") + vm.start() + vm.wait_for_login().close() + gpu_dev = libvirt_vmxml.create_vm_device_by_type("hostdev", hostdev_dict) + res = virsh.attach_device(vm.name, gpu_dev.xml, debug=True) + libvirt.check_result(res, error_msg) + + finally: + gpu_test.teardown_default() diff --git a/libvirt/tests/src/gpu/vm_cuda_sanity.py b/libvirt/tests/src/gpu/vm_cuda_sanity.py new file mode 100644 index 00000000000..6b758b46a3e --- /dev/null +++ b/libvirt/tests/src/gpu/vm_cuda_sanity.py @@ -0,0 +1,52 @@ +import os + +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml + +from provider.gpu import gpu_base + + +def run(test, params, env): + """ + cuda sanity tests in guest + """ + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + cuda_tests = eval(params.get("cuda_tests", "[]")) + gpu_test = gpu_base.GPUTest(vm, test, params) + hostdev_dict = gpu_test.parse_hostdev_dict() + + try: + gpu_test.setup_default() + libvirt_vmxml.modify_vm_device( + vm_xml.VMXML.new_from_dumpxml(vm.name), "hostdev", + hostdev_dict) + test.log.info("TEST_STEP: Start the VM") + vm.start() + vm_session = vm.wait_for_login() + test.log.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + cuda_samples_path = os.path.join(os.path.dirname(__file__), params.get("cuda_samples_path")) + cuda_sample_guest_path = os.path.join("/tmp", os.path.basename(cuda_samples_path)) + vm.copy_files_to( + cuda_samples_path, os.path.dirname(cuda_sample_guest_path), + timeout=240) + vm_session.cmd(f"tar -xf {cuda_sample_guest_path} -C /root") + vm_session.cmd(f"rm -rf {cuda_sample_guest_path}") + + test.log.info("TEST_STEP: Install the driver") + gpu_test.install_latest_driver(vm_session) + gpu_test.install_cuda_toolkit(vm_session) + gpu_test.nvidia_smi_check(vm_session) + + test.log.info("TEST_STEP: Run cuda sanity tests") + for s_test in cuda_tests: + test.log.debug(f"TEST_STEP: Run {s_test}") + s, o = vm_session.cmd_status_output(s_test, timeout=600) + test.log.debug(f"output: {o}") + if s: + test.fail("Failed to run cuda sanity - %s" % s_test) + + finally: + gpu_test.teardown_default() diff --git a/libvirt/tests/src/gpu/vm_mig_sanity.py b/libvirt/tests/src/gpu/vm_mig_sanity.py new file mode 100644 index 00000000000..2badf3e63b1 --- /dev/null +++ b/libvirt/tests/src/gpu/vm_mig_sanity.py @@ -0,0 +1,79 @@ +import os +import re + +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml + +from provider.gpu import gpu_base + + +def run(test, params, env): + """ + MIG sanity test in vm with GPU device + """ + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + cuda_test = params.get("cuda_test") + + gpu_test = gpu_base.GPUTest(vm, test, params) + hostdev_dict = gpu_test.parse_hostdev_dict() + + try: + gpu_test.setup_default() + libvirt_vmxml.modify_vm_device( + vm_xml.VMXML.new_from_dumpxml(vm.name), "hostdev", + hostdev_dict) + test.log.info("TEST_STEP: Start the VM") + vm.start() + vm_session = vm.wait_for_login() + test.log.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + test.log.info("TEST_STEP: Copy the sample") + guest_gpu_pci = gpu_base.get_gpu_pci(vm_session) + cuda_samples_path = os.path.join(os.path.dirname(__file__), params.get("cuda_samples_path")) + cuda_sample_guest_path = os.path.join("/tmp", os.path.basename(cuda_samples_path)) + vm.copy_files_to( + cuda_samples_path, os.path.dirname(cuda_sample_guest_path), + timeout=240) + vm_session.cmd(f"tar -xf {cuda_sample_guest_path} -C /root") + vm_session.cmd(f"rm -rf {cuda_sample_guest_path}") + + test.log.info("TEST_STEP: Install the driver") + gpu_test.install_latest_driver(vm_session, True) + gpu_test.install_cuda_toolkit(vm_session, True) + + test.log.info("TEST_STEP: Enable MIG mode") + vm_session.cmd(f"nvidia-smi -i {guest_gpu_pci} -mig 1") + output = vm_session.cmd_output(f"nvidia-smi -i {guest_gpu_pci} --query-gpu=pci.bus_id,mig.mode.current --format=csv,noheader") + if "Enabled" not in output: + test.fail("Failed to enable MIG mode!") + + test.log.info("TEST_STEP: Create GPU instances ") + vm_session.cmd(f"nvidia-smi mig -cgi 4g.20gb,2g.10gb,1g.5gb -C") + res = vm_session.cmd_output_safe("nvidia-smi -L") + compute_instances = re.findall(r"Device .(\d).*UUID: (.*)\)", res) + if not compute_instances: + test.fail("Failed to get compute instances!") + for dev in compute_instances: + s, o = vm_session.cmd_status_output(f"CUDA_VISIBLE_DEVICES={dev[1]} {cuda_test}") + test.log.debug(f"dev: {dev[1]}, output of BlackScholes: {o}") + if s: + test.fail("Failed to run BlackScholes test!") + + test.log.info("TEST_STEP: Destroy the GPU instances") + res = vm_session.cmd_output_safe("nvidia-smi mig -lci | awk '/MIG/ {print $2, $3}'") + for line in res.splitlines(): + if line: + ids = line.split() + test.log.debug(f"Destroy instance - {ids}") + vm_session.cmd(f"nvidia-smi mig -dci -ci {ids[0]} -gi {ids[1]}") + + test.log.info("TEST_STEP: Disable MIG mode") + vm_session.cmd(f"nvidia-smi -i {guest_gpu_pci} -mig 0") + output = vm_session.cmd_output(f"nvidia-smi -i {guest_gpu_pci} --query-gpu=pci.bus_id,mig.mode.current --format=csv,noheader") + if "Disabled" not in output: + test.fail("Failed to disable MIG mode!") + finally: + gpu_test.teardown_default() diff --git a/libvirt/tests/src/gpu/vm_nvidia_gpu_driver.py b/libvirt/tests/src/gpu/vm_nvidia_gpu_driver.py new file mode 100644 index 00000000000..f1f7dd78e12 --- /dev/null +++ b/libvirt/tests/src/gpu/vm_nvidia_gpu_driver.py @@ -0,0 +1,40 @@ +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml + +from provider.gpu import gpu_base + + +def run(test, params, env): + """ + GPU driver installation/uninstallation/re-installation on vm with GPU device + """ + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + gpu_test = gpu_base.GPUTest(vm, test, params) + + hostdev_dict = gpu_test.parse_hostdev_dict() + + try: + gpu_test.setup_default() + libvirt_vmxml.modify_vm_device( + vm_xml.VMXML.new_from_dumpxml(vm.name), "hostdev", + hostdev_dict) + test.log.info("TEST_STEP: Start the VM") + vm.start() + vm_session = vm.wait_for_login() + test.log.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') + + test.log.info("TEST_STEP: Install the driver") + gpu_test.install_latest_driver(vm_session) + gpu_test.nvidia_smi_check(vm_session) + + test.log.info("TEST_STEP: Uninstall the driver") + vm_session.cmd("dnf module -y remove --all nvidia-driver", timeout=600) + + test.log.info("TEST_STEP: Re-install the driver") + gpu_test.install_latest_driver(vm_session) + gpu_test.nvidia_smi_check(vm_session) + finally: + gpu_test.teardown_default() diff --git a/provider/gpu/__init__.py b/provider/gpu/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/provider/gpu/gpu_base.py b/provider/gpu/gpu_base.py new file mode 100644 index 00000000000..2cbfbe66045 --- /dev/null +++ b/provider/gpu/gpu_base.py @@ -0,0 +1,235 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: yicui@redhat.com +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import logging +import re +import os +import platform +import requests + +from avocado.core import exceptions +from avocado.utils import process + +from virttest import libvirt_version +from virttest import utils_misc +from virttest import utils_package +from virttest import utils_sriov +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +LOG = logging.getLogger("avocado." + __name__) + + +def get_gpus_info(session=None): + """ + Get GPUs information + + :param session: The session object to the host + :raise: exceptions.TestError when command fails + :return: dict, GPUs' info. + eg. {'3b:00.0': {'driver': 'ixgbe', 'pci_id': '0000:3b:00.0', + 'iface': 'ens1f0', 'status': 'up'}, + '3b:00.1': {'driver': 'ixgbe', 'pci_id': '0000:3b:00.1', + 'iface': 'ens1f1', 'status': 'down'}} + + """ + dev_info = {} + status, output = utils_misc.cmd_status_output( + "lspci -D -nn|awk '/3D controller/'", + shell=True, session=session + ) + if status or not output: + raise exceptions.TestError( + "Unable to get 3D controllers. status: %s," + "stdout: %s." % (status, output) + ) + pattern = r'(\S+:\S+:\S+.\d+)\s.*\s\[(\w+:\w+)\]' + matches = re.findall(pattern, output) + for match in matches: + dev_info[match[0]] = {"pci_id": match[0], "ID": re.sub(":", " ", match[1])} + + for pci in dev_info.keys(): + _, output = utils_misc.cmd_status_output( + "lspci -v -s %s" % pci, shell=True, session=session + ) + driver_in_use = re.search("driver in use: (.*)", output) + if driver_in_use: + dev_info[pci].update({"driver": driver_in_use[1]}) + + LOG.debug(f"GPU info: {dev_info}.") + return dev_info + + +def get_gpu_pci(session=None): + """ + Get the pci id of the first available GPU. + + :param session: The session object to the host + :return: pci id of GPU, eg. 0000:01:00.0 + """ + return list(get_gpus_info(session=session).values())[0].get("pci_id") + + +def pci_to_addr(pci_id): + """ + Get address dict according to pci_id + + :param pci_id: PCI ID of a device(eg. 0000:05:10.1) + :return: address dict + """ + pci_list = ["0x%s" % x for x in re.split("[.:]", pci_id)] + return dict(zip(["domain", "bus", "slot", "function"], pci_list + ["pci"])) + + +class GPUTest(object): + """ + Wrapper class for GPU testing + """ + def __init__(self, vm, test, params, session=None): + self.vm = vm + self.test = test + self.params = params + self.session = session + self.remote_virsh_dargs = None + + libvirt_version.is_libvirt_feature_supported(self.params) + self.gpu_pci = get_gpu_pci(session=self.session) + if not self.gpu_pci: + test.cancel("NO available gpu found.") + self.gpu_pci_addr = pci_to_addr(self.gpu_pci) + self.gpu_dev_name = utils_sriov.get_device_name(self.gpu_pci) + + new_xml = vm_xml.VMXML.new_from_inactive_dumpxml(self.vm.name) + self.orig_config_xml = new_xml.copy() + + def parse_hostdev_dict(self): + """ + Parse hostdev_dict from params + + :return: The updated iface_dict + """ + gpu_pci_addr = self.gpu_pci_addr + hostdev_dict = eval(self.params.get('hostdev_dict', '{}')) + return hostdev_dict + + def check_gpu_dev(self, vm, status_error=False): + """ + Check GPU device in guest + + :param vm: vm object + :param status_error: True if expect not existing, otherwise False + """ + vm_session = vm.wait_for_login(timeout=240) + s, o = vm_session.cmd_status_output("lspci |grep 3D") + vm_session.close() + result = process.CmdResult(stdout=o, exit_status=s) + libvirt.check_exit_status(result, status_error) + + def nvidia_smi_check(self, vm_session): + """ + Run nvidia-smi command and check GPU device's info + + :param vm_session: vm's session + """ + gpu_pci = get_gpu_pci(session=vm_session) + s, o = vm_session.cmd_status_output("nvidia-smi -q") + if s or not re.search(gpu_pci, o): + self.test.fail("Failed to run nvidia-smi command. Status: %s, output: %s." + % (s, o)) + + def install_latest_driver(self, vm_session, local_rpm=False): + """ + Install the latest data centre driver + + :param vm_session: vm session object + :local_rpm: Install the driver using local rpm + """ + pkgs = ["gcc", "kernel*headers*", "kernel*devel*"] + if not utils_package.package_install(pkgs, vm_session): + self.test.error(f"Unable to install {pkgs} in guest!") + arch = platform.machine() + if local_rpm: + url = "https://developer.nvidia.com/datacenter-driver-downloads" + page = requests.Session().get(url) + pkg_download_cmd = re.findall(rf"(wget https://developer.download.nvidia.com/compute/nvidia-driver/\S+/local_installers/nvidia-driver-local-repo-rhel9-\S+{arch}.rpm)", page.text) + if not pkg_download_cmd: + self.test.error("Unable to get download command!") + pkg_name = os.path.basename(pkg_download_cmd[0]) + vm_session.cmd(pkg_download_cmd[0], timeout=240) + vm_session.cmd(f"rpm -i {pkg_name}", timeout=120) + else: + # TODO: Get distro from guest. epel repo should be covered in ci + distro = "rhel9" + pkg_mgr = utils_package.package_manager(vm_session, "epel-release") + if not pkg_mgr.is_installed("epel-release"): + vm_session.cmd_output_safe(f"subscription-manager repos --enable=rhel-9-for-{arch}-appstream-rpms") + vm_session.cmd_output_safe(f"subscription-manager repos --enable=rhel-9-for-{arch}-baseos-rpms") + vm_session.cmd_output_safe(f"subscription-manager repos --enable=codeready-builder-for-rhel-9-{arch}-rpms") + vm_session.cmd_output_safe("dnf -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm", timeout=600) + + if vm_session.cmd_status(f"ls /etc/yum.repos.d/cuda-{distro}.repo"): + repo_url = f"https://developer.download.nvidia.com/compute/cuda/repos/{distro}/sbsa/cuda-{distro}.repo" + vm_session.cmd(f"dnf config-manager --add-repo {repo_url}") + vm_session.cmd(f"sed -i 's/^gpgcheck=1/gpgcheck=0/' /etc/yum.repos.d/cuda-{distro}.repo") + vm_session.cmd("dnf clean all") + vm_session.cmd("dnf -y module install nvidia-driver:open-dkms --skip-broken", timeout=600) + + def install_cuda_toolkit(self, vm_session, runfile=False): + """ + Install cuda toolkit + :param vm_session: vm session object + :runfile: Install the cuda toolkit using runfile + """ + if runfile: + url = "https://developer.nvidia.com/cuda-downloads" + page = requests.Session().get(url) + pkg_download_cmd = re.findall(r"(wget https://developer.download.nvidia.com/compute/cuda/\S+/local_installers/cuda_\S+_linux_sbsa.run)", page.text) + if not pkg_download_cmd: + self.test.error("Unable to get download command!") + pkg_name = os.path.basename(pkg_download_cmd[0]) + vm_session.cmd(pkg_download_cmd[0], timeout=240) + vm_session.cmd(f"sh {pkg_name} --silent", timeout=600) + else: + pkgs = "cuda-toolkit" + if not utils_package.package_install(pkgs, vm_session): + self.test.fail(f"Unable to install {pkgs} in guest!") + + def setup_default(self, **dargs): + """ + Default setup + + :param dargs: test keywords + """ + dev_name = dargs.get('dev_name') + managed_disabled = dargs.get('managed_disabled', False) + + self.test.log.debug("Removing the existing hostdev device...") + libvirt_vmxml.remove_vm_devices_by_type(self.vm, 'hostdev') + + if managed_disabled: + virsh.nodedev_detach(dev_name, debug=True, ignore_status=False) + + def teardown_default(self, **dargs): + """ + Default cleanup + + :param dargs: test keywords + """ + dev_name = dargs.get('dev_name') + managed_disabled = dargs.get('managed_disabled', False) + self.test.log.info("TEST_TEARDOWN: Recover test environment.") + if self.vm.is_alive(): + self.vm.destroy(gracefully=False) + self.orig_config_xml.sync() + + if managed_disabled: + virsh.nodedev_reattach(dev_name, debug=True, ignore_status=False) From 0f135e2eab8131939b40a4b7a564b60695b8ee14 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Fri, 25 Apr 2025 15:37:30 +0800 Subject: [PATCH 0953/1055] Virtual_network: Fixup dhcpcd installation issue It was introduced by 0ad965d679a3801de0e. Signed-off-by: Yingshun Cui --- .../virsh_cmd/network/virsh_net_dhcp_leases.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/network/virsh_net_dhcp_leases.py b/libvirt/tests/src/virsh_cmd/network/virsh_net_dhcp_leases.py index eb2a2699a28..5c57ebe47ef 100644 --- a/libvirt/tests/src/virsh_cmd/network/virsh_net_dhcp_leases.py +++ b/libvirt/tests/src/virsh_cmd/network/virsh_net_dhcp_leases.py @@ -1,21 +1,20 @@ +from datetime import datetime, timedelta import re import logging as log import signal +from avocado.utils import process + +from virttest import libvirt_version from virttest import utils_net from virttest import utils_misc from virttest import virsh -from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml import LibvirtXMLError from virttest.libvirt_xml import network_xml +from virttest.libvirt_xml import vm_xml from virttest.utils_test import libvirt as utlv -from avocado.utils import process -from datetime import datetime, timedelta -from virttest.libvirt_xml import LibvirtXMLError from provider.virtual_network import network_base -from virttest import libvirt_version, utils_package - - # 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__) @@ -155,9 +154,7 @@ def f(): if ip_addr is None: iface_name = utils_net.get_linux_ifname(session, mac_addr) if try_dhclint: - if not utils_package.package_install('dhcpcd', session, 60): - test.fail("Failed to install dhcpcd in guest OS.") - session.cmd("dhcpcd %s" % iface_name) + session.cmd(f"dhcpcd {iface_name} || dhclient {iface_name}") ip_addr = utils_misc.wait_for(f, 10) else: # No IP for the interface, just print the interface name From 8a8d803e4466cf7d9aa8dfae403f3b6e78dc6905 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Sun, 27 Apr 2025 03:37:02 -0400 Subject: [PATCH 0954/1055] Fix error for nonexistent iothreadids The domain xml has no iothreadids config, so use iothreads instead Signed-off-by: liang-cong-red-hat --- .../numa/numa_config_with_auto_placement.py | 24 ++++++------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/libvirt/tests/src/numa/numa_config_with_auto_placement.py b/libvirt/tests/src/numa/numa_config_with_auto_placement.py index 9da82f6f66d..b7d8f795880 100644 --- a/libvirt/tests/src/numa/numa_config_with_auto_placement.py +++ b/libvirt/tests/src/numa/numa_config_with_auto_placement.py @@ -161,24 +161,14 @@ def check_iothreadinfo(vm_name, cpu_range, config=''): """ result = virsh.iothreadinfo(vm_name, options=config, debug=True, ignore_status=False) - range_found = False live_vmxml = libvirt_xml.VMXML.new_from_dumpxml(vm_name) - iothreadid_list = live_vmxml.iothreadids.iothread - for one_iothread in iothreadid_list: - iothread_attrs = one_iothread.fetch_attrs() - iothread_id = iothread_attrs['id'] - if re.search('{}\s*{}'.format(iothread_id, cpu_range), - result.stdout_text): - logging.debug( - 'Expected cpu affinity: {} found in stdout for ' - 'iothread: {}.'.format(cpu_range, iothread_id)) - range_found = True - else: - logging.debug('Iothread {} has no cpu affinity'.format(iothread_id)) - - if not range_found: - raise TestFail('Expected cpu affinity: {} not found in stdout of ' - 'iothreadinfo command.'.format(cpu_range)) + iothread_num = live_vmxml.iothreads + for iothread_id in range(1, iothread_num + 1): + if not re.search('{}\s*{}'.format(iothread_id, cpu_range), + result.stdout_text): + raise TestFail( + 'Iothread {} has no expected cpu affinity {} according to stdout of ' + 'iothreadinfo cmd {}.'.format(iothread_id, cpu_range, result.stdout_text)) def check_cgget_output(test, vm, expected_value): From 8bc9307339207f1dc0be396b0fc5a117f89336a4 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Sun, 27 Apr 2025 16:33:10 +0800 Subject: [PATCH 0955/1055] numa_mem_binding_with_offline_cpu: fix sync error Signed-off-by: Dan Zheng --- .../numa_mem_binding_with_offline_cpu.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/numa/guest_numa_node_tuning/numa_mem_binding_with_offline_cpu.py b/libvirt/tests/src/numa/guest_numa_node_tuning/numa_mem_binding_with_offline_cpu.py index a8989b4ca63..8306c939c72 100644 --- a/libvirt/tests/src/numa/guest_numa_node_tuning/numa_mem_binding_with_offline_cpu.py +++ b/libvirt/tests/src/numa/guest_numa_node_tuning/numa_mem_binding_with_offline_cpu.py @@ -44,10 +44,10 @@ def setup_test(): online_nodes = numa_info.get_online_nodes_withmem() test.log.debug("Get online node with memory:%s", online_nodes) - if online_nodes < 2: + if len(online_nodes) < 2: test.cancel("Expect %d numa nodes at " "least, but found %d" % (2, - online_nodes)) + len(online_nodes))) node_cpus = numa_info.get_all_node_cpus()[ online_nodes[offline_node_index]].strip().split(' ') From ad749258bfaf2e5e697293d75006d6bc4a518441 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Sun, 27 Apr 2025 18:28:17 +0800 Subject: [PATCH 0956/1055] v2v:add 10.0 to latest10 Signed-off-by: vwu-vera --- v2v/tests/cfg/convert_vm_to_libvirt.cfg | 5 ++++- v2v/tests/cfg/convert_vm_to_ovirt.cfg | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/v2v/tests/cfg/convert_vm_to_libvirt.cfg b/v2v/tests/cfg/convert_vm_to_libvirt.cfg index 7e651780dfe..3d528aa0ee8 100644 --- a/v2v/tests/cfg/convert_vm_to_libvirt.cfg +++ b/v2v/tests/cfg/convert_vm_to_libvirt.cfg @@ -38,7 +38,7 @@ - boot_uefi: vm_boot = "-efi" boottype = 3 - only 8_0.linux.latest10_dev, 8_0.linux.latest9_dev, 8_0.linux.latest9, 8_0.linux.latest8, 8_0.linux.ubuntu_lts, 8_0.linux.sles_lts, 8_0.linux.opensuse_latest, 8_0.windows.win2022, 8_0.windows.win11, 8_0.windows.win10, 8_0.windows.win2016, 8_0.windows.win2019, 8_0.windows.win2025 + only 8_0.linux.latest10_dev, 8_0.linux.latest10, 8_0.linux.latest9_dev, 8_0.linux.latest9, 8_0.linux.latest8, 8_0.linux.ubuntu_lts, 8_0.linux.sles_lts, 8_0.linux.opensuse_latest, 8_0.windows.win2022, 8_0.windows.win11, 8_0.windows.win10, 8_0.windows.win2016, 8_0.windows.win2019, 8_0.windows.win2025 variants: - linux: os_type = "linux" @@ -48,6 +48,9 @@ - latest10_dev: os_short_id = "RHEL10_DEV_SHORT_ID" os_version = "LATEST_DEV_10" + - latest10: + os_short_id = "RHEL10_SHORT_ID" + os_version = "LATEST10" - latest9_dev: os_short_id = "RHEL9_DEV_SHORT_ID" os_version = "LATEST_DEV_9" diff --git a/v2v/tests/cfg/convert_vm_to_ovirt.cfg b/v2v/tests/cfg/convert_vm_to_ovirt.cfg index b97ff3d86a1..1e62fa76055 100644 --- a/v2v/tests/cfg/convert_vm_to_ovirt.cfg +++ b/v2v/tests/cfg/convert_vm_to_ovirt.cfg @@ -81,7 +81,7 @@ - boot_uefi: vm_boot = "-efi" boottype = 3 - only 8_0.linux.latest10_dev, 8_0.linux.latest9_dev, 8_0.linux.latest9, 8_0.linux.latest8, 8_0.linux.8_8, 8_0.linux.8_6, 8_0.linux.ubuntu22_04, 8_0.linux.ubuntu_lts, 8_0.linux.sles15sp5, 8_0.linux.sles_lts, 8_0.linux.opensuse15_5, 8_0.linux.opensuse_latest, 8_0.windows.win2022, 8_0.windows.win11, 8_0.windows.win2016, 8_0.windows.win2025 + only 8_0.linux.latest10_dev, 8_0.linux.latest10, 8_0.linux.latest9_dev, 8_0.linux.latest9, 8_0.linux.latest8, 8_0.linux.8_8, 8_0.linux.8_6, 8_0.linux.ubuntu22_04, 8_0.linux.ubuntu_lts, 8_0.linux.sles15sp5, 8_0.linux.sles_lts, 8_0.linux.opensuse15_5, 8_0.linux.opensuse_latest, 8_0.windows.win2022, 8_0.windows.win11, 8_0.windows.win2016, 8_0.windows.win2025 variants: - linux: os_type = "linux" @@ -90,6 +90,8 @@ variants: - latest10_dev: os_version = "LATEST_DEV_10" + - latest10: + os_version = "LATEST10" - latest9_dev: os_version = "LATEST_DEV_9" - latest9: From 550ca68953f52393aff65ed34ed1f9ca42ee3f5f Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 28 Apr 2025 02:41:12 -0400 Subject: [PATCH 0957/1055] virtiofs: fix negative scenarios QEMU cmdline check was always executed, also in negative scenario. Return test immediately when done. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/virtiofs/virtiofs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtiofs/virtiofs.py b/libvirt/tests/src/virtiofs/virtiofs.py index a4c6ac31e61..c82061b3ded 100644 --- a/libvirt/tests/src/virtiofs/virtiofs.py +++ b/libvirt/tests/src/virtiofs/virtiofs.py @@ -565,9 +565,9 @@ def update_qemu_config(): for index in range(guest_num): end_test = set_up_and_start_vm(index) - check_qemu_cmdline() if end_test: return + check_qemu_cmdline() shared_data(vm_names, fs_devs) From 2087f55709703a689177a79a90ded12604db9dc8 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 9 Apr 2025 10:37:31 -0400 Subject: [PATCH 0958/1055] filesystem_device: add data collection on failing virtiofs usage Sometimes the mount command or other commmands would time out. In this case, log some information about the processes and retry. If the retry worked we still raise a test error because we expect it on the first try and want to inspect the logged information. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/virtiofs/virtiofs.py | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/libvirt/tests/src/virtiofs/virtiofs.py b/libvirt/tests/src/virtiofs/virtiofs.py index a4c6ac31e61..eb557ef6b60 100644 --- a/libvirt/tests/src/virtiofs/virtiofs.py +++ b/libvirt/tests/src/virtiofs/virtiofs.py @@ -73,6 +73,34 @@ def shared_data(vm_names, fs_devs): 1.Mount dir in guest; 2.Write a file in guest; 3.Check the md5sum value are the same in guests and host; + + :param vm_names: list of the VM names in the test + :param fs_devs: list of device XML instances + """ + try: + _shared_data(vm_names, fs_devs) + except ShellTimeoutError as e: + logging.error(f"Issue using virtiofs {e}") + logging.error("Collect more information and retry") + for cmd in [ + "ps aux|grep virtiofsd", + "ps aux|grep qemu-kvm", + "ls /var/tmp|grep mount", + "cat /var/log/libvirt/qemu/*virtiofsd.log" + ]: + logging.error(utils_misc.cmd_status_output(cmd)[1]) + logging.error("Retry now") + _shared_data(vm_names, fs_devs) + logging.error("Seems retrying succeeded") + raise e + + def _shared_data(vm_names, fs_devs): + """ + Helper function for `shared_data` so we can retry and collect more + information about the system state. + + :param vm_names: list of the VM names in the test + :param fs_devs: list of device XML instances """ md5s = [] for vm in vms: From dfe5a3b70f4b8284126b414c7ef4df4d7fe5f508 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 30 Apr 2025 11:06:12 +0800 Subject: [PATCH 0959/1055] virsh_domiflist: Update filters Only x86_64 machine supports e1000 and rtl8139 ifaces. Signed-off-by: Yingshun Cui --- libvirt/tests/cfg/virsh_cmd/domain/virsh_domiflist.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_domiflist.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_domiflist.cfg index 37b2cfed6cf..178c12a2ec0 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_domiflist.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_domiflist.cfg @@ -29,8 +29,10 @@ - virtio_iface: iface_model = "virtio" - e1000_iface: + only x86_64 iface_model = "e1000" - rtl8139_iface: + only x86_64 iface_model = "rtl8139" - iface_options: domiflist_domname_options = "name" From 103f59dd5159b998371a081baa0526637d1c9700 Mon Sep 17 00:00:00 2001 From: meinaLi Date: Wed, 30 Apr 2025 02:22:16 -0400 Subject: [PATCH 0960/1055] Virtual disk: add new https network disk case Automate case: RHEL-187504 - Start vm and hotplug/unplug https network disk with different options Signed-off-by: meinaLi --- .../cfg/virtual_disks/virtual_disks_https.cfg | 25 +++++ .../src/virtual_disks/virtual_disks_https.py | 91 +++++++++++++++++++ spell.ignore | 1 + 3 files changed, 117 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_disks/virtual_disks_https.cfg create mode 100644 libvirt/tests/src/virtual_disks/virtual_disks_https.py diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_https.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_https.cfg new file mode 100644 index 00000000000..d33e39e5a46 --- /dev/null +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_https.cfg @@ -0,0 +1,25 @@ +- virtual_disks.https: + type = virtual_disks_https + start_vm = "no" + target_disk = "sdb" + disk_format = "raw" + source_host_name = "insect.mm.fcix.net" + source_iso_name = "/fedora/linux/releases/41/Server/x86_64/iso/Fedora-Server-netinst-x86_64-41-1.4.iso" + cookie_name = "vmware_soap_session" + cookie_value = "314455dbd2eaafd7d76b3b7828f0a3e3956450f9" + expected_xpaths = [{'element_attrs': [".//ssl[@verify='yes']"]}, {'element_attrs': [".//readahead[@size='1024']"]}, {'element_attrs': [".//timeout[@seconds='60']"]}] + cookie_in_dumpxml = "${cookie_name}.*${cookie_value}" + driver_dict = "'driver': {'name': 'qemu', 'type': '${disk_format}'}" + source_extra_dict = "'cookies': {'cookie_name': '${cookie_name}', 'cookie': '${cookie_value}'}, 'readahead': '1024', 'timeout': '60', 'ssl': 'yes'" + source_dict = "'source': {'hosts': [{'name': '${source_host_name}'}], 'attrs': {'protocol': 'https', 'name': '${source_iso_name}'}, ${source_extra_dict}}" + disk_dict = {'type_name': 'network', 'readonly': True, 'device': '%s', ${driver_dict}, ${source_dict}, 'target': {'dev': '${target_disk}', 'bus': 'scsi'}} + func_supported_since_libvirt_ver = (10, 10, 0) + variants: + - start_vm: + - detach_attach_disk: + with_hotplug = "yes" + variants: + - network_disk: + network_device = "disk" + - network_cdrom: + network_device = "cdrom" diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_https.py b/libvirt/tests/src/virtual_disks/virtual_disks_https.py new file mode 100644 index 00000000000..ca8595879bd --- /dev/null +++ b/libvirt/tests/src/virtual_disks/virtual_disks_https.py @@ -0,0 +1,91 @@ +from virttest import virsh +from virttest import libvirt_version + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt +from virttest.utils_libvirtd import Libvirtd +from virttest.utils_config import LibvirtQemuConfig + + +def run(test, params, env): + """ + Start vm and hotplug/unplug https network disk with different options. + + 1. Start vm with/without https network disk. + 2. Hot-unplug https network disk. + 3. Hotplug the https network disk. + """ + def setup_test(): + """ + Prepare a https network disk test environment. + + :param qemu_config: return the qemu config. + """ + qemu_config = LibvirtQemuConfig() + qemu_config.storage_use_nbdkit = 1 + Libvirtd('virtqemud').restart() + return qemu_config + + def prepare_disk(): + """ + Prepare the https network disk. + + :param disk_obj: return the disk object. + """ + network_device = params.get("network_device") + disk_dict = eval(params.get("disk_dict", "{}") % network_device) + disk_obj = libvirt_vmxml.create_vm_device_by_type("disk", disk_dict) + if not with_hotplug: + libvirt.add_vm_device(vmxml, disk_obj) + vmxml.sync() + return disk_obj + + def check_result(disk_in_vm=True): + """ + Check the test result. + + :param disk_in_vm: boolean value to make sure if disk in vm. + """ + if disk_in_vm: + xml_after_adding_device = vm_xml.VMXML.new_from_dumpxml(vm_name) + libvirt_vmxml.check_guest_xml_by_xpaths(xml_after_adding_device, expected_xpaths) + libvirt_vmxml.check_guest_xml(vm_name, cookie_in_dumpxml, + option=" --security-info") + else: + domblklist_result = virsh.domblklist(vm_name, debug=True).stdout_text.strip() + if target_disk in domblklist_result: + test.fail("The target disk %s can't be detached from guest." % target_disk) + + libvirt_version.is_libvirt_feature_supported(params) + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + target_disk = params.get("target_disk") + expected_xpaths = eval(params.get("expected_xpaths")) + cookie_in_dumpxml = params.get("cookie_in_dumpxml") + with_hotplug = "yes" == params.get("with_hotplug", "no") + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + backup_vmxml = vmxml.copy() + + try: + qemu_config = setup_test() + disk_dev = prepare_disk() + test.log.info("TEST_STEP1: Start the guest.") + if not vm.is_alive(): + vm.start() + vm.wait_for_login().close() + test.log.debug("The current guest xml is: %s", virsh.dumpxml(vm_name).stdout_text) + disk_in_vm = not with_hotplug + check_result(disk_in_vm) + if with_hotplug: + test.log.info("TEST_STEP2: Hotplug the disk.") + virsh.attach_device(vm_name, disk_dev.xml, debug=True, ignore_status=False) + check_result() + test.log.info("TEST_STEP3: Hot-unplug the disk.") + virsh.detach_device(vm_name, disk_dev.xml, debug=True, ignore_status=False) + check_result(disk_in_vm=False) + finally: + backup_vmxml.sync() + qemu_config.restore() + Libvirtd('virtqemud').restart() diff --git a/spell.ignore b/spell.ignore index 5a5a95486e8..c597e9cbf05 100644 --- a/spell.ignore +++ b/spell.ignore @@ -1261,3 +1261,4 @@ meili ntp userfaultfd datastore +https From 47c4c94faa9ae0c389e6c2862ee15f5d3c253bfa Mon Sep 17 00:00:00 2001 From: hholoubk Date: Fri, 2 May 2025 10:41:55 +0200 Subject: [PATCH 0961/1055] Adding more information to failure message. --- .../src/virsh_cmd/domain/virsh_migrate.py | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_migrate.py b/libvirt/tests/src/virsh_cmd/domain/virsh_migrate.py index 02514cfaf6b..43f2c7c1b27 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_migrate.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_migrate.py @@ -109,6 +109,7 @@ def check_migration_result(migration_res): test.cancel(migration_res.stderr) def do_migration(delay, vm, dest_uri, options, extra, **virsh_args): + migration_msg = "Migration done." logging.info("Sleeping %d seconds before migration", delay) time.sleep(delay) # Migrate the guest. @@ -119,8 +120,9 @@ def do_migration(delay, vm, dest_uri, options, extra, **virsh_args): logging.info("Migration stderr: %s", migration_res.stderr) check_migration_result(migration_res) if int(migration_res.exit_status) != 0: - logging.error("Migration failed for %s.", vm_name) - return False + migration_msg = f"Migration failed for {vm_name}, with stderr: {migration_res.stderr}" + logging.error(migration_msg) + return (False, migration_msg) if options.count("dname") or extra.count("dname"): vm.name = extra.split()[1].strip() @@ -129,8 +131,9 @@ def do_migration(delay, vm, dest_uri, options, extra, **virsh_args): logging.info("Alive guest found on destination %s.", dest_uri) else: if not options.count("offline"): - logging.error("VM not alive on destination %s", dest_uri) - return False + migration_msg = f"VM not alive on destination {dest_uri}" + logging.error(migration_msg) + return (False, migration_msg) # Throws exception if console shows panic message if not options.count("dname") and not extra.count("dname"): @@ -246,6 +249,7 @@ def enable_hugepage(vmname, no_of_HPs, hp_unit='', hp_node='', pin=False, r"[\#\$]\s*$") cmd_output = server_session.cmd_status_output(command) server_session.close() + dest_HP_free = "" if (cmd_output[0] == 0): dest_HP_free = cmd_output[1].strip('HugePages_Free:').strip() else: @@ -735,12 +739,12 @@ def check_vm_state_dest(): "single node") # To check if Hugepage supported and configure + default_hp_unit = "KiB" if enable_HP or enable_HP_pin: try: hp_obj = test_setup.HugePageConfig(params) host_hp_size = hp_obj.get_hugepage_size() # libvirt xml takes HP sizes in KiB - default_hp_unit = "KiB" hp_pin_nodes = int(params.get("HP_pin_node_count", "2")) vm_max_mem = vmxml.max_mem no_of_HPs = int(vm_max_mem // host_hp_size) + 1 @@ -826,6 +830,7 @@ def check_vm_state_dest(): remote_libvirt_file = None src_libvirt_file = None scsi_disk = None + migration_msg = "No info." try: # Change the disk of the vm to shared disk @@ -1000,6 +1005,7 @@ def check_vm_state_dest(): # Prepare for --xml. xml_option = params.get("xml_option", "no") + new_nic_mac = "" if xml_option == "yes": if not extra.count("--dname") and not extra.count("--xml"): logging.debug("Preparing new xml file for --xml option.") @@ -1128,7 +1134,7 @@ def check_vm_state_dest(): else: ret_migrate = False if not asynch_migration: - ret_migrate = do_migration(delay, vm, dest_uri, options, extra, **virsh_args) + (ret_migrate, migration_msg) = do_migration(delay, vm, dest_uri, options, extra, **virsh_args) dest_state = params.get("virsh_migrate_dest_state", "running") if ret_migrate and dest_state == "running": @@ -1170,8 +1176,8 @@ def check_vm_state_dest(): .remove_key_for_modular_daemon(remove_dict, remote_dargs) if not asynch_migration: - ret_migrate = do_migration(delay, vm, src_uri, options, - extra) + (ret_migrate, migration_msg) = do_migration(delay, vm, src_uri, options, + extra) elif extra.count("--timeout-suspend"): func = check_migration_timeout_suspend try: @@ -1250,7 +1256,7 @@ def check_vm_state_dest(): # Check unsafe result and may do migration again in right mode if ret_migrate is False and unsafe_test: options = params.get("virsh_migrate_options") - ret_migrate = do_migration(delay, vm, dest_uri, options, extra) + (ret_migrate, migration_msg) = do_migration(delay, vm, dest_uri, options, extra) elif ret_migrate and unsafe_test: check_unsafe_result = False if vm_ref != vm_name: @@ -1322,10 +1328,10 @@ def check_vm_state_dest(): # Check test result. if status_error == 'yes': if ret_migrate: - test.fail("Migration finished with unexpected status.") + test.fail(f"Migration finished with unexpected status {migration_msg}.") else: if not ret_migrate: - test.fail("Migration finished with unexpected status.") + test.fail(f"Migration finished with unexpected status {migration_msg}.") if not check_dest_persistent: test.fail("VM is not persistent on destination.") if not check_src_undefine: From 37bd45e5e3fd2deaa9c403de5af57d44720b690e Mon Sep 17 00:00:00 2001 From: meinaLi Date: Tue, 6 May 2025 02:15:14 -0400 Subject: [PATCH 0962/1055] Virtual_disk: add new case about ssh network disk Automate case: VIRT-304003 - Start guest and hotplug/unplug ssh network disk Signed-off-by: meinaLi --- .../cfg/virtual_disks/virtual_disks_ssh.cfg | 22 ++++ .../src/virtual_disks/virtual_disks_ssh.py | 117 ++++++++++++++++++ provider/virtual_disk/disk_base.py | 86 ++++++++++++- 3 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 libvirt/tests/cfg/virtual_disks/virtual_disks_ssh.cfg create mode 100644 libvirt/tests/src/virtual_disks/virtual_disks_ssh.py diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_ssh.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_ssh.cfg new file mode 100644 index 00000000000..f9f1d7d46cb --- /dev/null +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_ssh.cfg @@ -0,0 +1,22 @@ +- virtual_disks.ssh: + type = virtual_disks_ssh + start_vm = "no" + target_disk = "vdb" + disk_dict = {'type_name': 'network', 'device': 'disk', 'driver': {'name': 'qemu', 'type': 'qcow2'}, "target":{"dev": "${target_disk}", "bus": "virtio"}} + func_supported_since_libvirt_ver = (10, 10, 0) + variants: + - start_vm: + - hotplug_disk: + with_hotplug = "yes" + variants: + - with_ssh_key: + disk_type = "ssh_with_key" + expected_xpaths = [{'element_attrs': [".//knownHosts[@path='%s']"]}, {'element_attrs': [".//identity[@keyfile='%s']"]}] + - with_secret_password: + with_secret_passwd = "yes" + disk_type = "ssh_with_passwd" + key_word = "redhat" + iscsi_user = "root" + secret_pwd = "`printf %s ${key_word} | base64`" + sec_dict = {"secret_ephemeral": "no", "secret_private": "no", "description": "secret_desc_for_ssh_disk", "usage": "iscsi", "target": "libvirtiscsi"} + expected_xpaths = [{'element_attrs': [".//knownHosts[@path='%s']"]}, {'element_attrs': [".//secret[@type='iscsi']"]}] diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_ssh.py b/libvirt/tests/src/virtual_disks/virtual_disks_ssh.py new file mode 100644 index 00000000000..d1d425e54df --- /dev/null +++ b/libvirt/tests/src/virtual_disks/virtual_disks_ssh.py @@ -0,0 +1,117 @@ +import re +import os + +from virttest import virsh +from virttest import libvirt_version +from virttest import utils_disk +from virttest import data_dir + +from virttest.libvirt_xml import vm_xml +from avocado.utils import process +from virttest.utils_libvirt import libvirt_vmxml, libvirt_disk +from virttest.utils_config import LibvirtQemuConfig +from virttest.utils_libvirtd import Libvirtd + +from provider.virtual_disk import disk_base + + +def run(test, params, env): + """ + Verify start guest and hotplug/unplug ssh network disk. + + 1. Prepare disk xml with ssh network disk. + 2. Start guest with or without network disk based on scenarios. + 3. Hotplug network disk only for hotplugging test scenario. + 4. Check disk in guest. + 5. Hot-unplug network disk if necessary. + """ + def setup_test(): + """ + Prepare a ssh network disk test environment. + + :params qemu_config: return the qemu config. + """ + qemu_config = LibvirtQemuConfig() + qemu_config.storage_use_nbdkit = 1 + Libvirtd('virtqemud').restart() + return qemu_config + + def check_result(disk_in_vm=True): + """ + Check the dumpxml and the nbdkit process. + + :params disk_in_vm: boolean value to make sure if disk in vm. + """ + test.log.info("TEST_STEP: Check the nbdkit process.") + cmd = "ps aux | grep nbdkit | grep -v grep" + nbdkit_process = process.run(cmd, shell=True, ignore_status=True).stdout_text + match_result = re.findall(r"storage.socket", nbdkit_process) + if disk_in_vm and not match_result: + test.fail("Can't find the nbdkit process!") + if not disk_in_vm: + if match_result: + test.fail("Find the nbdkit process unexpectedly!") + else: + test.log.debug("Can't find nbdkit process after hot-unplugging as expect!") + return + + test.log.info("TEST_STEP: Check the vm xml.") + if with_secret_passwd: + expected_xpaths = eval(params.get("expected_xpaths") % + known_hosts_path) + else: + expected_xpaths = eval(params.get("expected_xpaths") % + (known_hosts_path, keyfile)) + xml_after_adding_device = vm_xml.VMXML.new_from_dumpxml(vm_name) + test.log.debug("The current guest xml is: %s", xml_after_adding_device) + libvirt_vmxml.check_guest_xml_by_xpaths(xml_after_adding_device, expected_xpaths) + + test.log.info("TEST_STEP: Do read/write for disk.") + vm_session = vm.wait_for_login() + new_disk = libvirt_disk.get_non_root_disk_name(vm_session)[0] + utils_disk.dd_data_to_vm_disk(vm_session, new_disk) + vm_session.close() + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + disk_type = params.get("disk_type") + disk_dict = eval(params.get("disk_dict", "{}")) + with_hotplug = "yes" == params.get("with_hotplug", "no") + with_secret_passwd = "yes" == params.get("with_secret_passwd", "no") + libvirt_version.is_libvirt_feature_supported(params) + keyfile = os.path.join(data_dir.get_tmp_dir(), "keyfile") + known_hosts_path = os.path.join(data_dir.get_tmp_dir(), "known_hosts") + kwargs = {"keyfile": keyfile, "known_hosts_path": known_hosts_path} + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) + bkxml = vmxml.copy() + disk_obj = disk_base.DiskBase(test, vm, params) + + try: + qemu_config = setup_test() + if not with_hotplug: + disk_obj.new_image_path = disk_obj.add_vm_disk(disk_type, + disk_dict, + **kwargs) + + test.log.info("TEST_STEP: Start the guest.") + if not vm.is_alive(): + virsh.start(vm_name, debug=True, ignore_status=False) + if with_hotplug: + test.log.info("TEST_STEP: Hotplug the disk to guest.") + disk_dev, disk_obj.new_image_path = \ + disk_obj.prepare_disk_obj(disk_type, disk_dict, **kwargs) + virsh.attach_device(vm_name, disk_dev.xml, debug=True, + ignore_status=False, wait_for_event=True) + check_result() + + if with_hotplug: + test.log.info("TEST_STEP: Hot-unplug the disk from guest.") + virsh.detach_device(vm_name, disk_dev.xml, debug=True, + ignore_status=False, wait_for_event=True) + check_result(disk_in_vm=False) + finally: + qemu_config.restore() + Libvirtd('virtqemud').restart() + bkxml.sync() + disk_obj.cleanup_disk_preparation(disk_type, **kwargs) diff --git a/provider/virtual_disk/disk_base.py b/provider/virtual_disk/disk_base.py index 456191494ce..f84a61720e5 100644 --- a/provider/virtual_disk/disk_base.py +++ b/provider/virtual_disk/disk_base.py @@ -218,6 +218,32 @@ def prepare_disk_obj(self, disk_type, disk_dict, new_image_path='', **kwargs): "port": nbd_server_port}]}, }) + elif disk_type == "ssh_with_key": + new_image_path, known_hosts_path, keyfile = \ + self.create_ssh_disk_path(self.params, **kwargs) + ssh_user = os.environ.get("USER") + disk_dict.update( + {'source': {"attrs": {"protocol": "ssh", + "name": new_image_path}, + "identity": [{"username": "%s" % ssh_user, + "keyfile": keyfile}], + "knownhosts": known_hosts_path, + "hosts": [{"name": "127.0.0.1", + "port": "22"}]}}) + + elif disk_type == "ssh_with_passwd": + new_image_path, known_hosts_path, _ = \ + self.create_ssh_disk_path(self.params, **kwargs) + disk_dict.update( + {'source': {"attrs": {"protocol": "ssh", + "name": new_image_path}, + "knownhosts": known_hosts_path, + "hosts": [{"name": "127.0.0.1", + "port": "22"}], + "auth": {"auth_user": self.params.get("iscsi_user"), + "secret_usage": "libvirtiscsi", + "secret_type": "iscsi"}}}) + disk_obj = libvirt_vmxml.create_vm_device_by_type("disk", disk_dict) self.test.log.debug('Create disk object is :%s', disk_obj) @@ -239,7 +265,7 @@ def add_luks_encryption_to_disk_dict(self, disk_dict, secret_dict): "encryption": "luks", "attrs": {"engine": "librbd"}}}) return disk_dict - def cleanup_disk_preparation(self, disk_type): + def cleanup_disk_preparation(self, disk_type, **kwargs): """ Clean up the preparation of different type disk @@ -271,6 +297,9 @@ def cleanup_disk_preparation(self, disk_type): except Exception as ndbEx: self.test.log.debug("Clean Up nbd failed: %s", str(ndbEx)) + elif disk_type == "ssh_with_key" or disk_type == "ssh_with_passwd": + self.cleanup_ssh_disk_path(self.new_image_path, **kwargs) + @staticmethod def cleanup_block_disk_preparation(vg_name, lv_name, **kwargs): """ @@ -345,6 +374,20 @@ def create_lvm_disk_path(vg_name='vg0', lv_name='lv0', **kwargs): return path + @staticmethod + def cleanup_ssh_disk_path(new_image_path, **kwargs): + """ + Clean up ssh disk image + + :params new_image_path: the new image path. + :param kwargs: optional keyword arguments. + """ + keyfile = kwargs.get("keyfile") + known_hosts_path = kwargs.get("known_hosts_path") + for file in [keyfile, f"{keyfile}.pub", known_hosts_path, new_image_path]: + if os.path.exists(file): + os.remove(file) + @staticmethod def cleanup_rbd_disk_path(params): """ @@ -406,6 +449,47 @@ def create_rbd_disk_path(params, create_img_by_qemu_cmd=False): return mon_host, auth_username, new_image_path, sec_uuid + @staticmethod + def create_ssh_disk_path(params, **kwargs): + """ + Prepare ssh type disk image path + + :params params: Dict with the test parameters. + :param kwargs: optional keyword arguments. + :params return: tuple, include new_image_path, known_hosts_path and keyfile. + """ + authorized_path = "/root/.ssh/authorized_keys" + sec_dict = eval(params.get("sec_dict", "{}")) + secret_pwd = params.get("secret_pwd") + new_image_path = params.get("new_image_path") + with_secret_passwd = "yes" == params.get("with_secret_passwd", "no") + + if not new_image_path: + new_image_path = data_dir.get_data_dir() + '/test.img' + size = kwargs.get("size", "50M") + if kwargs.get("size"): + kwargs.pop("size") + libvirt.create_local_disk( + "file", path=new_image_path, size=size, + disk_format=params.get("disk_image_format", 'qcow2')) + + keyfile = kwargs.get("keyfile") + known_hosts_path = kwargs.get("known_hosts_path") + for file in [keyfile, f"{keyfile}.pub", known_hosts_path]: + if os.path.exists(file): + os.remove(file) + + process.run("ssh-keygen -t rsa -q -N '' -f %s" % keyfile, shell=True) + process.run("ssh-keyscan -p 22 127.0.0.1 >> %s" % known_hosts_path, shell=True) + process.run("cat %s >> %s" % (f"{keyfile}.pub", authorized_path), shell=True) + + if with_secret_passwd: + libvirt_secret.clean_up_secrets() + sec_uuid = libvirt_secret.create_secret(sec_dict=sec_dict) + virsh.secret_set_value(sec_uuid, secret_pwd, + debug=True, ignore_status=False) + return new_image_path, known_hosts_path, keyfile + def prepare_relative_path(self, disk_type, **kwargs): """ Prepare relative path From 14b7644c99d859e28033eaf75362782983c6e0a1 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 6 May 2025 12:58:14 +0200 Subject: [PATCH 0963/1055] provider/vfio/ccw: return full device info on additional parameter Some test needs the full device information. Let's unify the code by adding an additional parameter that if set to True, allows for this. This reduces code duplication and the ccw provider can be used in all cases. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/virtual_disks/virtual_disks_dasd.py | 10 +--------- provider/vfio/ccw.py | 8 ++++++-- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_dasd.py b/libvirt/tests/src/virtual_disks/virtual_disks_dasd.py index ec3acb3f325..5ba1dd56918 100644 --- a/libvirt/tests/src/virtual_disks/virtual_disks_dasd.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_dasd.py @@ -28,15 +28,7 @@ def get_partitioned_dasd_path(devid): :param devid: the ccw device id, e.g. 0.0.5200 :return path: absolute path to block device, e.g. '/dev/dasda' """ - paths = SubchannelPaths() - paths.get_info() - device = None - if devid: - device = paths.get_device(devid) - else: - device = paths.get_first_unused_and_safely_removable() - if not device: - raise TestError("Couldn't find dasd device for test") + device = ccw.get_device_info(devid, True) global TEST_DASD_ID TEST_DASD_ID = device[paths.HEADER["Device"]] enable_disk(TEST_DASD_ID) diff --git a/provider/vfio/ccw.py b/provider/vfio/ccw.py index 2975e94e399..c55127131ee 100644 --- a/provider/vfio/ccw.py +++ b/provider/vfio/ccw.py @@ -336,14 +336,16 @@ def select_first_available_device(device_ids): raise TestError(f"None of the devices is available, {device_ids}") -def get_device_info(devid=None): +def get_device_info(devid=None, full=False): """ Gets the device info for passthrough. It selects a device that's safely removable if devid is not given. :param devid: The ccw device id, e.g. 0.0.5000 - :return: Subchannel and Channel path ids (schid, chpids) + :param full: per default only return schid, chpids; return + full device info if True + :return: The device info """ paths = get_subchannel_info() @@ -352,6 +354,8 @@ def get_device_info(devid=None): device = paths.get_device(devid) else: device = paths.get_first_unused_and_safely_removable() + if full: + return device schid = device[paths.HEADER["Subchan."]] chpids = device[paths.HEADER["CHPIDs"]] return schid, chpids From 9073dd7354ef6ff762361c3160178ae1c32bb387 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 6 May 2025 15:54:17 +0200 Subject: [PATCH 0964/1055] provider/vfio/ccw: add new way to select dasd Handling several device ids over different LPARs has become increasingly difficult. Our test environments generally now install on FCP SCSI disks, not on DASDs. When tests define "dasd", they should select the first available (assumed spare) DASD disk available on the host, that's been set in Use. Signed-off-by: Sebastian Mitterle --- provider/vfio/ccw.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/provider/vfio/ccw.py b/provider/vfio/ccw.py index c55127131ee..86e7fb846cb 100644 --- a/provider/vfio/ccw.py +++ b/provider/vfio/ccw.py @@ -336,13 +336,14 @@ def select_first_available_device(device_ids): raise TestError(f"None of the devices is available, {device_ids}") -def get_device_info(devid=None, full=False): +def get_device_info(devid="", full=False): """ Gets the device info for passthrough. It selects a device that's safely removable if devid is not given. :param devid: The ccw device id, e.g. 0.0.5000 + Also supports value 'dasd' to return the first available DASD :param full: per default only return schid, chpids; return full device info if True :return: The device info @@ -350,10 +351,12 @@ def get_device_info(devid=None, full=False): paths = get_subchannel_info() device = None - if devid: - device = paths.get_device(devid) - else: + if not devid: device = paths.get_first_unused_and_safely_removable() + elif devid == "dasd": + device = paths.get_first_dasd_in_use() + else: + device = paths.get_device(devid) if full: return device schid = device[paths.HEADER["Subchan."]] From c488df2dafe77e441a7bbfc3d5ddde912d56573d Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Wed, 7 May 2025 20:08:31 +0800 Subject: [PATCH 0965/1055] sriov: Extend event wait time Signed-off-by: Yingshun Cui --- .../src/sriov/locked_memory_check/sriov_with_hotplug_memory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/sriov/locked_memory_check/sriov_with_hotplug_memory.py b/libvirt/tests/src/sriov/locked_memory_check/sriov_with_hotplug_memory.py index 1f83d4b7564..92ff6c44609 100644 --- a/libvirt/tests/src/sriov/locked_memory_check/sriov_with_hotplug_memory.py +++ b/libvirt/tests/src/sriov/locked_memory_check/sriov_with_hotplug_memory.py @@ -131,7 +131,7 @@ def hotplug_mem_device(vm_name, mem_dict, current_mem): if without_hostdev: test.log.info("TEST_STEP: Hot-unplug iface device and check locked memory limit.") virsh.detach_device(vm_name, iface_dev.xml, debug=True, ignore_status=False, - wait_for_event=True) + wait_for_event=True, event_timeout=30) vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) check_memory_limit(vmxml, first_mem, with_hostdev_device=False) finally: From 8fecf01c3d290e920e0ea872902b41715b0142b5 Mon Sep 17 00:00:00 2001 From: lcheng Date: Wed, 7 May 2025 22:56:14 +0800 Subject: [PATCH 0966/1055] migration: Update migration_bandwidth_limit case According to bug RHEL-7042, update case. Signed-off-by: lcheng --- .../migration_with_copy_storage/migration_bandwidth_limit.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration_with_copy_storage/migration_bandwidth_limit.cfg b/libvirt/tests/cfg/migration_with_copy_storage/migration_bandwidth_limit.cfg index 097a3ee2072..9a78126c730 100644 --- a/libvirt/tests/cfg/migration_with_copy_storage/migration_bandwidth_limit.cfg +++ b/libvirt/tests/cfg/migration_with_copy_storage/migration_bandwidth_limit.cfg @@ -45,7 +45,7 @@ virsh_migrate_extra = "--bandwidth ${bandwidth}" - setspeed_before_migration: - setspeed_during_migration: - virsh_migrate_extra = "--bandwidth 30" + check_item_value = "9223372036853727232" action_during_mig = '[{"func": "set_bandwidth", "after_event": "block-job", "func_param": "params", "wait_for_after_event_timeout": "600"}, {"func": "libvirt_disk.check_item_by_blockjob", "func_param": "params"}, {"func": "check_domjobinfo_during_mig", "func_param": "params"}]' variants: - copy_storage_all: From e95cd635dc583ef5b7bf75ec45ff0adce97f76d0 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 6 May 2025 17:43:22 +0200 Subject: [PATCH 0967/1055] passthrough/ccw: set dasd selection default Assumptions about the test environment shared. There should be little risk in changing the default configuration because the previous one could also have led to broken systems. The DASD selection would always have to be reviewed before running the tests. We now assume there will be at least 1 DASD device with Use = Yes. Remove the previous assumption from the comments. Signed-off-by: Sebastian Mitterle --- .../ccw/libvirt_ccw_passthrough.cfg | 2 +- .../libvirt_ccw_passthrough_read_write.cfg | 2 +- .../cfg/virtual_disks/virtual_disks_dasd.cfg | 2 +- .../ccw/libvirt_ccw_passthrough.py | 3 --- .../ccw/libvirt_ccw_passthrough_read_write.py | 3 --- .../src/virtual_disks/virtual_disks_dasd.py | 25 ++++++++++--------- 6 files changed, 16 insertions(+), 21 deletions(-) diff --git a/libvirt/tests/cfg/passthrough/ccw/libvirt_ccw_passthrough.cfg b/libvirt/tests/cfg/passthrough/ccw/libvirt_ccw_passthrough.cfg index ae7829012d0..fd1cf6768f5 100644 --- a/libvirt/tests/cfg/passthrough/ccw/libvirt_ccw_passthrough.cfg +++ b/libvirt/tests/cfg/passthrough/ccw/libvirt_ccw_passthrough.cfg @@ -1,7 +1,7 @@ - libvirt_ccw_passthrough: type = libvirt_ccw_passthrough only s390-virtio - devid = + devid = dasd variants: - happy_path: - device_removal: diff --git a/libvirt/tests/cfg/passthrough/ccw/libvirt_ccw_passthrough_read_write.cfg b/libvirt/tests/cfg/passthrough/ccw/libvirt_ccw_passthrough_read_write.cfg index a8ef3345f90..92398f1abad 100644 --- a/libvirt/tests/cfg/passthrough/ccw/libvirt_ccw_passthrough_read_write.cfg +++ b/libvirt/tests/cfg/passthrough/ccw/libvirt_ccw_passthrough_read_write.cfg @@ -1,7 +1,7 @@ - libvirt_ccw_passthrough.read_write: type = libvirt_ccw_passthrough_read_write only s390-virtio - devid = + devid = dasd start_vm = yes variants: - happy_path: diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_dasd.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_dasd.cfg index b9321ecf1f8..39abe318a25 100644 --- a/libvirt/tests/cfg/virtual_disks/virtual_disks_dasd.cfg +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_dasd.cfg @@ -1,6 +1,6 @@ - virtual_disks.dasd: type = virtual_disks_dasd only s390-virtio - devid = + devid = dasd variants: - read_native_partition_table: diff --git a/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py b/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py index d9f14bfa9f1..4cc5b9f79fc 100644 --- a/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py +++ b/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough.py @@ -45,9 +45,6 @@ def guest_is_responsive(session): def run(test, params, env): """ Test for CCW, esp. DASD disk passthrough on s390x. - - The CCW disk/its subchannel for passthrough is expected to - be listed on the host but not enabled for use. """ vm_name = params.get("main_vm") diff --git a/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough_read_write.py b/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough_read_write.py index 21c2b445782..b4d04c45820 100644 --- a/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough_read_write.py +++ b/libvirt/tests/src/passthrough/ccw/libvirt_ccw_passthrough_read_write.py @@ -8,9 +8,6 @@ def run(test, params, env): """ Test for CCW, esp. DASD disk passthrough on s390x. - - The CCW disk/its subchannel for passthrough is expected to - be listed on the host but not enabled for use. """ vm_name = params.get("main_vm") diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_dasd.py b/libvirt/tests/src/virtual_disks/virtual_disks_dasd.py index 5ba1dd56918..e343e05a78b 100644 --- a/libvirt/tests/src/virtual_disks/virtual_disks_dasd.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_dasd.py @@ -6,7 +6,7 @@ from avocado.core.exceptions import TestError from virttest import virsh -from virttest.utils_zchannels import SubchannelPaths +from virttest.utils_zchannels import SubchannelPaths as paths from virttest.utils_misc import cmd_status_output, wait_for from virttest.libvirt_xml.vm_xml import VMXML @@ -14,6 +14,7 @@ TEST_DASD_ID = None TARGET = "vdb" # suppose guest has only one disk 'vda' +cleanup_actions = [] # Using as lower capital is not the best way to do, but this is just a @@ -31,14 +32,14 @@ def get_partitioned_dasd_path(devid): device = ccw.get_device_info(devid, True) global TEST_DASD_ID TEST_DASD_ID = device[paths.HEADER["Device"]] - enable_disk(TEST_DASD_ID) + try_enable_disk(TEST_DASD_ID) disk_path = get_device_path(TEST_DASD_ID) wait_for(lambda: ccw.format_dasd(disk_path, None), 10, first=1.0) wait_for(lambda: ccw.make_dasd_part(disk_path, None), 10, first=1.0) return disk_path -def enable_disk(disk_id): +def try_enable_disk(disk_id): """ Enables the disk so it can be used @@ -48,8 +49,10 @@ def enable_disk(disk_id): cmd = "chzdev -e %s" % disk_id err, out = cmd_status_output(cmd, shell=True) - if err: - raise TestError("Couldn't enable dasd '%s'. %s" % (disk_id, out)) + if 'already configured' not in out: + cleanup_actions.append(lambda: disable_disk(disk_id)) + if err: + raise TestError("Couldn't enable dasd '%s'. %s" % (disk_id, out)) def disable_disk(disk_id): @@ -147,17 +150,15 @@ def run(test, params, env): devid = params.get("devid") try: + cleanup_actions.append(lambda: vm.destroy()) disk_path = get_partitioned_dasd_path(devid) + attach_disk(vm_name, TARGET, disk_path) session = vm.wait_for_login() check_dasd_partition_table(session, TARGET) detach_disk(vm_name, TARGET) finally: - if vm.is_alive(): - vm.destroy(gracefully=False) - # sync will release attached disk, precondition for disablement - backup_xml.sync() - global TEST_DASD_ID - if TEST_DASD_ID: - disable_disk(TEST_DASD_ID) + cleanup_actions.reverse() + for action in cleanup_actions: + action() From cecf3fa441b94743860f7d14b300039469825278 Mon Sep 17 00:00:00 2001 From: Yan Fu Date: Fri, 9 May 2025 17:00:23 +0800 Subject: [PATCH 0968/1055] Check the libvirt/qemu/kvm group/users are created via sysuser.d Signed-off-by: Yan Fu --- libvirt/tests/cfg/daemon/check_users.cfg | 5 ++++ libvirt/tests/src/daemon/check_users.py | 29 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 libvirt/tests/cfg/daemon/check_users.cfg create mode 100644 libvirt/tests/src/daemon/check_users.py diff --git a/libvirt/tests/cfg/daemon/check_users.cfg b/libvirt/tests/cfg/daemon/check_users.cfg new file mode 100644 index 00000000000..26589e9b1ee --- /dev/null +++ b/libvirt/tests/cfg/daemon/check_users.cfg @@ -0,0 +1,5 @@ +- daemon.check_users: + type = check_users + func_supported_since_libvirt_ver = (10, 10, 0) + start_vm = no + users_list = ['g qemu', 'g libvirt', 'g kvm', 'u qemu', 'm qemu kvm'] diff --git a/libvirt/tests/src/daemon/check_users.py b/libvirt/tests/src/daemon/check_users.py new file mode 100644 index 00000000000..010046eed84 --- /dev/null +++ b/libvirt/tests/src/daemon/check_users.py @@ -0,0 +1,29 @@ +import logging +import re +import ast + +from avocado.utils import process + +from virttest import libvirt_version + + +LOGGER = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Check libvirt/qemu/kvm user/group are created via sysuser.d + """ + libvirt_version.is_libvirt_feature_supported(params) + users_list = ast.literal_eval(params.get("users_list", "[]")) + + users_match_list = [] + + sysuser_dir = '/usr/lib/sysusers.d/' + cmd = "grep -hr -E 'kvm|qemu|libvirt' %s" % sysuser_dir + output = process.getoutput(cmd, shell=True) + LOGGER.debug(output) + + for user in users_list: + if not re.search(user, output): + test.fail("%s not created by sysuser.d" % user) From effb2e8fe4e56125f80c42e3149e4750656d9911 Mon Sep 17 00:00:00 2001 From: chwen Date: Wed, 16 Apr 2025 02:13:41 -0400 Subject: [PATCH 0969/1055] Add new features support and enable more utils 1. Remove virt-manager package install since it is never necessary 2. Enable local storage as default since it is default behaviour after bootc image builder feature updates 3. Enable -use-librepo when building out anaconda-iso since this is default feature for anaconda-iso 4. Add util: podman_pull to support podman download image before run bootc image builder 5. Add files and directories customization when creating json files since it is new feature for bootc image builder 6. Enable vhd on rhel_9.6 and rhel_10.0 since this feature are newly supported on those two releases 7. Add check_squashfs when anaconda-iso since it is new feature requirement when building out anaconda-iso Signed-off-by: chwen --- .../bootc_image_build_utils.py | 74 ++++++++++++++++++- .../bootc_disk_image_build.cfg | 9 ++- .../bootc_disk_image_install.cfg | 8 +- .../bootc_disk_image_build.py | 4 + .../bootc_disk_image_install.py | 4 + 5 files changed, 89 insertions(+), 10 deletions(-) diff --git a/provider/bootc_image_builder/bootc_image_build_utils.py b/provider/bootc_image_builder/bootc_image_build_utils.py index 0439842a76e..ad1b3c54923 100644 --- a/provider/bootc_image_builder/bootc_image_build_utils.py +++ b/provider/bootc_image_builder/bootc_image_build_utils.py @@ -34,7 +34,7 @@ def install_bib_packages(): install necessary bootc image builder necessary packages """ - package_list = ["podman", "skopeo", "virt-install", "curl", "virt-manager"] + package_list = ["podman", "skopeo", "virt-install", "curl"] for pkg in package_list: try: path.find_command(pkg) @@ -71,8 +71,7 @@ def podman_command_build(bib_image_url, disk_image_type, image_ref, config=None, else: cmd += " -v %s:/config.json " % config - if local_container: - cmd += " -v /var/lib/containers/storage:/var/lib/containers/storage " + cmd += " -v /var/lib/containers/storage:/var/lib/containers/storage " if options is not None: cmd += " %s " % options @@ -86,6 +85,9 @@ def podman_command_build(bib_image_url, disk_image_type, image_ref, config=None, cmd += " %s " \ " --type %s --tls-verify=%s " % (bib_image_url, disk_image_type, tls_verify) + if type in ['anaconda-iso'] and "9.4" not in bib_image_url and "9.5" not in bib_image_url: + cmd += " --use-librepo " + if config: if "toml" in config: cmd += " --config /config.toml " @@ -169,6 +171,17 @@ def podman_push(podman_username, podman_password, registry, container_url): command, timeout=1200, verbose=True, ignore_status=False, shell=True) +def podman_pull(container_url): + """ + Use podman pull registry image + + :param container_url: image url + :return: CmdResult object + """ + pull_image_cmd = f"sudo podman pull {container_url}" + process.run(pull_image_cmd, timeout=600, verbose=True, ignore_status=False, shell=True) + + def create_config_json_file(params): """ create json configuration file @@ -184,6 +197,7 @@ def create_config_json_file(params): enable_lvm_disk_partitions = "yes" == params.get("enable_lvm_disk_partitions") enable_plain_disk_partitions = "yes" == params.get("enable_plain_disk_partitions") enable_btrf_disk_partitions = "yes" == params.get("enable_btrf_disk_partitions") + file_dir_set = "yes" == params.get("file_dir_set") filesystem_dict = {"filesystem": [ { @@ -197,6 +211,22 @@ def create_config_json_file(params): ] } + files_dict = {"files": [ + { + "path": "/etc/custom_file", + "data": "hello world" + }, + ] + } + + directories_dict = {"directories": [ + { + "path": "/etc/custom_dir", + + }, + ] + } + enable_lvm_disk_partitions_dict = {"disk": { "partitions": [ { @@ -352,6 +382,10 @@ def create_config_json_file(params): if filesystem_size_set: cfg['blueprint']['customizations'].update(filesystem_dict) + if file_dir_set: + cfg['blueprint']['customizations'].update(files_dict) + cfg['blueprint']['customizations'].update(directories_dict) + LOG.debug("what is cfg:%s", cfg) config_json_path = pathlib.Path(folder) / "config.json" config_json_path.write_text(json.dumps(cfg), encoding="utf-8") @@ -372,6 +406,8 @@ def create_config_toml_file(params): filesystem_size_set = "yes" == params.get("filesystem_size_set") filesystem_size_str = "" fips_content = "" + file_dir_set = "yes" == params.get("file_dir_set") + file_dir_str = "" if not os.path.exists(public_key_path): LOG.debug("public key doesn't exist, will help create one") @@ -391,6 +427,16 @@ def create_config_toml_file(params): mountpoint = "/var/data" minsize = "20 GiB" """ + if file_dir_set: + file_dir_str = f""" + [[customizations.files]] + path = "/etc/custom_file" + data = "hello world" + + [[customizations.directories]] + path = "/etc/custom_dir" + """ + if not kickstart: container_file_content = f"""\n [[customizations.user]] @@ -399,6 +445,7 @@ def create_config_toml_file(params): key = "{key_value}" groups = ["wheel"] {filesystem_size_str} + {file_dir_str} [customizations.kernel] append = "mitigations=auto,nosmt" """ @@ -407,7 +454,7 @@ def create_config_toml_file(params): "rootpw --lock --iscrypted locked\n" "sshkey --username %s \"%s\"\ntext --non-interactive\nzerombr\n" "clearpart --all --initlabel --disklabel=gpt\nautopart --noswap --type=lvm\n" - "network --bootproto=dhcp --device=eno1 --activate --onboot=on\n reboot" % (username, password, username, key_value) + "network --bootproto=dhcp --device=link --activate --onboot=on\n reboot" % (username, password, username, key_value) } if params.get("fips_enable") == "yes": fips_content = f""" @@ -427,6 +474,7 @@ def create_config_toml_file(params): "org.fedoraproject.Anaconda.Modules.Timezone" ] {filesystem_size_str} + {file_dir_str} [customizations.installer.kickstart] contents = \"""{kick_start.get("contents")}\""" """ @@ -930,6 +978,9 @@ def virt_install_vm(params): if disk_image_type in ["anaconda-iso"]: if os.path.exists(iso_install_path): os.remove(iso_install_path) + check_squashfs = params.get("check_squashfs") == "yes" + if check_squashfs: + check_image_filesystem(params) cmd = ("virt-install --name %s" " --disk path=%s,bus=virtio,format=qcow2,size=12" " --vcpus 3 --memory 3096" @@ -960,6 +1011,21 @@ def virt_install_vm(params): process.run(cmd, shell=True, verbose=True, ignore_status=True) +def check_image_filesystem(params): + """ + Check image file system + + @param params: one dictionary containing parameters + """ + disk_path = params.get("vm_disk_image_path") + mount_cmd = f"mount {disk_path} /mnt" + process.run(mount_cmd, shell=True, verbose=True, ignore_status=False) + check_squashfs_cmd = "file /mnt/images/install.img" + ret = process.run(check_squashfs_cmd, verbose=True, ignore_status=False, shell=True).stdout_text + if "Squashfs" not in ret: + raise exceptions.TestFail(f"Squashfs is not enabled") + + def verify_in_vm_internal(vm, params): """ Verify something by login Vm diff --git a/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_build.cfg b/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_build.cfg index 3075aae8b08..4adb7423abb 100644 --- a/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_build.cfg +++ b/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_build.cfg @@ -25,6 +25,7 @@ os_password = "bob" qcow..upstream_bib: filesystem_size_set = "yes" + file_dir_set = "yes" anaconda-iso..upstream_bib..fedora_40: kickstart = "yes" use_toml_config = "yes" @@ -44,7 +45,7 @@ local_container = "yes" - centos10: container_url = "quay.io/centos-bootc/centos-bootc:stream10" - only upstream_bib..use_config_json..tls_verify_enable, rhel_9.5_nightly_bib..use_config_json..tls_verify_enable, rhel_9.6_nightly_bib..use_config_json..tls_verify_enable, rhel_9.4_nightly_bib..use_config_json..tls_verify_enable + only upstream_bib..use_config_json..tls_verify_enable, rhel_10.0_bib..use_config_json..tls_verify_enable, rhel_9.6_nightly_bib..use_config_json..tls_verify_enable, rhel_9.4_nightly_bib..use_config_json..tls_verify_enable roofs = "xfs" rhel_9.4_nightly_bib..use_config_json..tls_verify_enable: roofs = "" @@ -91,6 +92,8 @@ - rhel_9.5_nightly: container_url = "registry.stage.redhat.io/rhel9/rhel-bootc:9.5" only rhel_9.5_nightly_bib + qcow..rhel_9.6_nightly_bib: + enable_lvm_disk_partitions = "yes" redhat_version_id = "9.5" no anaconda-iso - rhel_9.6_nightly: @@ -220,10 +223,10 @@ output_sub_folder = "vpc" output_name = "disk.vhd" no s390-virtio - only upstream_bib, rhel_9.5_nightly_bib + only upstream_bib, rhel_9.6_nightly_bib, rhel_10.0_bib - gce: disk_image_type = "gce" output_sub_folder = "gce" output_name = "image.tar.gz" no s390-virtio - only upstream_bib, rhel_9.5_nightly_bib + only upstream_bib, rhel_9.6_nightly_bib, rhel_10.0_bib diff --git a/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_install.cfg b/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_install.cfg index 1613de8fbfd..21aab0d59b6 100644 --- a/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_install.cfg +++ b/virttools/tests/cfg/bootc_image_builder/bootc_disk_image_install.cfg @@ -40,10 +40,12 @@ - centos10: container_url = "quay.io/centos-bootc/centos-bootc:stream10" only efi - only upstream_bib, rhel_9.5_nightly_bib, rhel_9.6_nightly_bib, rhel_9.4_nightly_bib + only upstream_bib, rhel_10.0_bib, rhel_9.6_nightly_bib, rhel_9.4_nightly_bib roofs = "ext4" rhel_9.4_nightly_bib: roofs = "" + anaconda-iso..upstream_bib: + check_squashfs = "yes" - fedora: variants fedora_bootc_image: - fedora_40: @@ -228,10 +230,10 @@ output_sub_folder = "vpc" output_name = "disk.vhd" no s390-virtio - only upstream_bib, rhel_9.5_nightly_bib + only upstream_bib, rhel_9.6_nightly_bib, rhel_10.0_bib - gce: disk_image_type = "gce" output_sub_folder = "gce" output_name = "image.tar.gz" no s390-virtio - only upstream_bib, rhel_9.5_nightly_bib + only upstream_bib, rhel_9.6_nightly_bib, rhel_10.0_bib diff --git a/virttools/tests/src/bootc_image_builder/bootc_disk_image_build.py b/virttools/tests/src/bootc_image_builder/bootc_disk_image_build.py index 17a9ad54a6d..594a5100256 100644 --- a/virttools/tests/src/bootc_image_builder/bootc_disk_image_build.py +++ b/virttools/tests/src/bootc_image_builder/bootc_disk_image_build.py @@ -110,6 +110,10 @@ def prepare_env_and_execute_bib(params, test): options += f" -v {root_dir}/policy.json:/etc/containers/policy.json -v {root_dir}/bib_lookaside.yaml:/etc/containers/registries.d/bib_lookaside.yaml " options += f" -v /var/lib/containers/sigstore:/var/lib/containers/sigstore -v {root_dir}/key.gpg:{root_dir}key.gpg " + # Pull images first + if "local" not in container_url: + bib_utils.podman_pull(container_url) + result = bib_utils.podman_command_build(bib_image_url, disk_image_type, container_url, config_json_file, local_container, enable_tls_verify, ownership, key_store_mounted, target_arch, roofs, options, **aws_config_dict) diff --git a/virttools/tests/src/bootc_image_builder/bootc_disk_image_install.py b/virttools/tests/src/bootc_image_builder/bootc_disk_image_install.py index 143fba94b36..f87b6085f1f 100644 --- a/virttools/tests/src/bootc_image_builder/bootc_disk_image_install.py +++ b/virttools/tests/src/bootc_image_builder/bootc_disk_image_install.py @@ -111,6 +111,10 @@ def prepare_env_and_execute_bib(params, test): bib_utils.podman_push(params.get("podman_quay_username"), params.get("podman_quay_password"), params.get("registry"), container_url) + # Pull images first + if "local" not in container_url: + bib_utils.podman_pull(container_url) + result = bib_utils.podman_command_build(bib_image_url, disk_image_type, container_url, config_json_file, local_container, enable_tls_verify, ownership, key_store_mounted, None, roofs, options, **aws_config_dict) From 7a2e6774d022e3903bb2aabe693cac2e9c150221 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Wed, 14 May 2025 06:16:17 -0400 Subject: [PATCH 0970/1055] virtiofs.unpriviledged: fix hugepages tests for bootc bootc doesn't allow creating the hugepages user directory in the original path. Add it to /var instead. Signed-off-by: Sebastian Mitterle --- libvirt/tests/src/virtiofs/virtiofs_unprivileged.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtiofs/virtiofs_unprivileged.py b/libvirt/tests/src/virtiofs/virtiofs_unprivileged.py index 19044f8d3be..d79e135f452 100644 --- a/libvirt/tests/src/virtiofs/virtiofs_unprivileged.py +++ b/libvirt/tests/src/virtiofs/virtiofs_unprivileged.py @@ -40,7 +40,7 @@ _params = {} backup_huge_pages_num = 0 user_config_path = "" -hugepages_user_path = "/user_hugepages" +hugepages_user_path = "/var/user_hugepages" with_hugepages = False qemu_config = None From dd66dc8e02941e5d1bcebb66281dab1089d7dc83 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 13 May 2025 10:58:43 -0400 Subject: [PATCH 0971/1055] migration/destructive_operations: kill virtiofsd on source Add test for killing virtiofsd during migration perform phase with external virtiofsd. Signed-off-by: Sebastian Mitterle --- .../kill_virtiofsd_during_performphase.cfg | 49 ++++++++ .../kill_virtiofsd_during_performphase.py | 110 ++++++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_virtiofsd_during_performphase.cfg create mode 100644 libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_virtiofsd_during_performphase.py diff --git a/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_virtiofsd_during_performphase.cfg b/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_virtiofsd_during_performphase.cfg new file mode 100644 index 00000000000..5e7e0ce63e0 --- /dev/null +++ b/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_virtiofsd_during_performphase.cfg @@ -0,0 +1,49 @@ +- migration.destructive_operations_around_live_migration.kill_virtiofsd_during_performphase: + type = kill_virtiofsd_during_performphase + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + status_error = "no" + migrate_desturi_port = "22" + migrate_desturi_type = "ssh" + virsh_migrate_desturi = "qemu+ssh://${migrate_dest_host}/system" + func_supported_since_libvirt_ver = (10, 5, 0) + vm_attrs = {'mb': {"source_type":"file", 'access_mode': 'shared'}} + socket_path = "/vm001-vhost-fs.sock" + dev_type = "filesystem" + mount_tag = "mount_tag1" + mount_dir = "/mnt/${mount_tag}" + fs_dict = {'accessmode':'passthrough', 'type_name': 'mount', 'driver': {'type': 'virtiofs', 'queue':'1024'}, 'source':{'socket': '${socket_path}'}, "target": {'dir': '${mount_tag}'}} + expect_str = "${mount_tag}.*${mount_dir}" + variants: + - with_precopy: + status_error = "yes" + service_name = "virtiofsd" + migrate_speed = "1000" + virsh_migrate_options = '--live --verbose' + variants: + - kill_src_virtiofsd: + expected_dest_state = "nonexist" + expected_src_state = "running" + action_during_mig = '[{"func": "libvirt_service.kill_service", "after_event": "migration-iteration", "func_param": "params"}]' + err_msg = "load of migration failed: Input/output error|operation failed" + variants: + - external: diff --git a/libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_virtiofsd_during_performphase.py b/libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_virtiofsd_during_performphase.py new file mode 100644 index 00000000000..6d80ddcded3 --- /dev/null +++ b/libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_virtiofsd_during_performphase.py @@ -0,0 +1,110 @@ +import re + +from avocado.utils import process + +from virttest import libvirt_version +from virttest import remote +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt + +from provider.migration import base_steps + + +def run(test, params, env): + """ + This case is to verify that if killing virtiofsd process during PerformPhase of + migration, migration will fail. If dst virtiofsd is killed, src virtiofsd will keep + running. If src virtiofsd is killed, dst virtiofsd will be closed. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + + def setup_test(): + """ + Setup steps + + """ + test.log.info("Setup steps.") + mnt_path_name = params.get("mnt_path_name") + socket_path = params.get("socket_path") + vm_attrs = eval(params.get("vm_attrs", "{}")) + fs_dict = eval(params.get("fs_dict", "{}")) + dev_type = params.get("dev_type") + mount_tag = params.get("mount_tag") + mount_dir = params.get("mount_dir") + expect_str = params.get("expect_str") + + cmd1 = f"chcon -t virtd_exec_t /usr/libexec/virtiofsd" + cmd2 = f"mkdir -p {mnt_path_name}" + cmd3 = f"systemd-run /usr/libexec/virtiofsd --socket-path={socket_path} -o source={mnt_path_name}" + multi_cmd1 = f"{cmd1}; {cmd2}; {cmd3}" + process.run(multi_cmd1, shell=True, ignore_status=False) + remote.run_remote_cmd(multi_cmd1, params, ignore_status=False) + cmd4 = f"chcon -t svirt_image_t {socket_path}" + cmd5 = f"chown qemu:qemu {socket_path}" + multi_cmd2 = f"{cmd4}; {cmd5}" + process.run(multi_cmd2, shell=True, ignore_status=False) + remote.run_remote_cmd(multi_cmd2, params, ignore_status=False) + + migration_obj.setup_connection() + + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vmxml.setup_attrs(**vm_attrs) + vmxml.remove_all_device_by_type("tpm") + vmxml.sync() + if not vm.is_alive(): + vm.start() + fs = libvirt_vmxml.create_vm_device_by_type(dev_type, fs_dict) + virsh.attach_device(vm_name, fs.xml, debug=True, ignore_status=False) + + vm_session = vm.wait_for_login() + vm_session.cmd_output_safe(f"mkdir {mount_dir}") + vm_session.cmd_output_safe(f"mount -t virtiofs {mount_tag} {mount_dir}") + output = vm_session.cmd_output("df -h") + vm_session.close() + test.log.debug("output: %s", output) + if not re.search(expect_str, output): + test.fail(f'Expect content "{expect_str}" not in output: {output}') + + def verify_test(): + """ + Verify migration result + + """ + dest_uri = params.get("virsh_migrate_desturi") + expected_src_state = params.get("expected_src_state") + expected_dest_state = params.get("expected_dest_state") + + func_returns = dict(migration_obj.migration_test.func_ret) + migration_obj.migration_test.func_ret.clear() + test.log.debug("Migration returns function results: %s", func_returns) + virsh.domstate(vm_name, uri=migration_obj.src_uri, debug=True) + if expected_src_state: + if not libvirt.check_vm_state( + vm.name, expected_src_state, uri=migration_obj.src_uri + ): + test.fail( + "Migrated VM failed to be in %s state at source." + % expected_src_state + ) + if expected_dest_state and expected_dest_state == "nonexist": + virsh.domstate(vm_name, uri=dest_uri, debug=True) + if virsh.domain_exists(vm_name, uri=dest_uri): + test.fail("The domain on target host is found, but expected not") + + libvirt_version.is_libvirt_feature_supported(params) + vm_name = params.get("migrate_main_vm") + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + setup_test() + migration_obj.run_migration() + verify_test() + finally: + migration_obj.cleanup_connection() From e7c7eef9499f04775cee3f287d6b19951c7923c1 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 20 May 2025 09:04:17 +0800 Subject: [PATCH 0972/1055] gpu: Fix errors 1. Fix hotplug case's pattern and type 2. Update to download cuda sample file from storage server Signed-off-by: Yingshun Cui --- libvirt/tests/cfg/gpu/hotplug_gpu.cfg | 4 ++-- libvirt/tests/cfg/gpu/vm_cuda_sanity.cfg | 2 +- libvirt/tests/cfg/gpu/vm_mig_sanity.cfg | 2 +- libvirt/tests/src/gpu/vm_cuda_sanity.py | 6 ++---- libvirt/tests/src/gpu/vm_mig_sanity.py | 6 ++---- 5 files changed, 8 insertions(+), 12 deletions(-) diff --git a/libvirt/tests/cfg/gpu/hotplug_gpu.cfg b/libvirt/tests/cfg/gpu/hotplug_gpu.cfg index fc55c007e42..fbd941b2639 100644 --- a/libvirt/tests/cfg/gpu/hotplug_gpu.cfg +++ b/libvirt/tests/cfg/gpu/hotplug_gpu.cfg @@ -1,5 +1,5 @@ -- gpu.lifecycle_vm_with_gpu: - type = lifecycle_vm_with_gpu +- gpu.hotplug_gpu: + type = hotplug_gpu start_vm = "no" only aarch64 diff --git a/libvirt/tests/cfg/gpu/vm_cuda_sanity.cfg b/libvirt/tests/cfg/gpu/vm_cuda_sanity.cfg index eadec96aca4..ceba493922b 100644 --- a/libvirt/tests/cfg/gpu/vm_cuda_sanity.cfg +++ b/libvirt/tests/cfg/gpu/vm_cuda_sanity.cfg @@ -1,7 +1,7 @@ - gpu.vm_cuda_sanity: type = vm_cuda_sanity start_vm = "no" - cuda_samples_path = "../../deps/gpu/cuda-samples.tar.gz" + cuda_samples_path = "http://download.libvirt.redhat.com/libvirt-CI-resources/gpu/cuda-samples.tar.gz" cuda_tests = ["./cuda-samples/build/Samples/1_Utilities/deviceQuery/deviceQuery", "./cuda-samples/build/Samples/1_Utilities/bandwidthTest/bandwidthTest", "./cuda-samples/build/Samples//0_Introduction/simpleMultiCopy/simpleMultiCopy"] only aarch64 diff --git a/libvirt/tests/cfg/gpu/vm_mig_sanity.cfg b/libvirt/tests/cfg/gpu/vm_mig_sanity.cfg index 4d78348bbbd..39b77f76d8b 100644 --- a/libvirt/tests/cfg/gpu/vm_mig_sanity.cfg +++ b/libvirt/tests/cfg/gpu/vm_mig_sanity.cfg @@ -1,7 +1,7 @@ - gpu.mig_sanity: type = vm_mig_sanity start_vm = "no" - cuda_samples_path = "../../deps/gpu/cuda-samples.tar.gz" + cuda_samples_path = "http://download.libvirt.redhat.com/libvirt-CI-resources/gpu/cuda-samples.tar.gz" cuda_test = "./cuda-samples/build/Samples/5_Domain_Specific/BlackScholes/BlackScholes" only aarch64 diff --git a/libvirt/tests/src/gpu/vm_cuda_sanity.py b/libvirt/tests/src/gpu/vm_cuda_sanity.py index 6b758b46a3e..e1269e84e17 100644 --- a/libvirt/tests/src/gpu/vm_cuda_sanity.py +++ b/libvirt/tests/src/gpu/vm_cuda_sanity.py @@ -27,11 +27,9 @@ def run(test, params, env): vm.start() vm_session = vm.wait_for_login() test.log.debug(f'VMXML of {vm_name}:\n{virsh.dumpxml(vm_name).stdout_text}') - cuda_samples_path = os.path.join(os.path.dirname(__file__), params.get("cuda_samples_path")) + cuda_samples_path = params.get("cuda_samples_path") cuda_sample_guest_path = os.path.join("/tmp", os.path.basename(cuda_samples_path)) - vm.copy_files_to( - cuda_samples_path, os.path.dirname(cuda_sample_guest_path), - timeout=240) + vm_session.cmd(f"wget {cuda_samples_path} -O {cuda_sample_guest_path}") vm_session.cmd(f"tar -xf {cuda_sample_guest_path} -C /root") vm_session.cmd(f"rm -rf {cuda_sample_guest_path}") diff --git a/libvirt/tests/src/gpu/vm_mig_sanity.py b/libvirt/tests/src/gpu/vm_mig_sanity.py index 2badf3e63b1..6d02e4eb25d 100644 --- a/libvirt/tests/src/gpu/vm_mig_sanity.py +++ b/libvirt/tests/src/gpu/vm_mig_sanity.py @@ -32,11 +32,9 @@ def run(test, params, env): test.log.info("TEST_STEP: Copy the sample") guest_gpu_pci = gpu_base.get_gpu_pci(vm_session) - cuda_samples_path = os.path.join(os.path.dirname(__file__), params.get("cuda_samples_path")) + cuda_samples_path = params.get("cuda_samples_path") cuda_sample_guest_path = os.path.join("/tmp", os.path.basename(cuda_samples_path)) - vm.copy_files_to( - cuda_samples_path, os.path.dirname(cuda_sample_guest_path), - timeout=240) + vm_session.cmd(f"wget {cuda_samples_path} -O {cuda_sample_guest_path}") vm_session.cmd(f"tar -xf {cuda_sample_guest_path} -C /root") vm_session.cmd(f"rm -rf {cuda_sample_guest_path}") From 9623b637a03540faadf26e3b82d41c043a9dc9ec Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Wed, 21 May 2025 03:49:12 -0400 Subject: [PATCH 0973/1055] Remove 2 checkpoints for passt Delete 2 checkpoints: 1) Check the socket dir, when vm destroyed, the passt socket dir is not cleared for passt+vhostuser. In CNV, this is not an issue, tracked in RHEL-80285. (We can restore the check after the bug is fixed) 2) When start vm with interface using passt, and the qemu support reconect parameter, there is "reconnect:5" or "reconnect=5" in qemu cmd once qemu support reconnect feature. But since qemu 10.1, the parameter change to "reconnect-ms:5000" or "reconnect-ms=5000". To make is simple, delete this qemu cmd check, and just check the function that if the passt process will reconnect after killed is enough. Signed-off-by: Yalan Zhang --- libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg | 2 -- .../tests/src/virtual_network/passt/passt_attach_detach.py | 2 -- libvirt/tests/src/virtual_network/passt/passt_function.py | 2 -- libvirt/tests/src/virtual_network/passt/passt_reconnect.py | 4 ---- 4 files changed, 10 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg index 09d4af072d3..ab0ec68b591 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg @@ -5,7 +5,6 @@ outside_ip = 'www.redhat.com' start_vm = no mtu = 65520 - qemu_cmd_check = "reconnect":5 variants user_type: - root_user: test_user = root @@ -24,7 +23,6 @@ - default: - vhostuser: vhostuser = 'yes' - qemu_cmd_check = "reconnect=5" func_supported_since_libvirt_ver = (10, 10, 0) variants: - ip_portfw: diff --git a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py index 4975d68af22..eaa701d601b 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py +++ b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py @@ -159,8 +159,6 @@ def run(test, params, env): if 'detach' not in scenario: vm.destroy() passt.check_passt_pid_not_exist() - if not vhostuser and os.listdir(socket_dir): - test.fail(f'Socket dir is not empty: {os.listdir(socket_dir)}') else: vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name, virsh_instance=virsh_ins) diff --git a/libvirt/tests/src/virtual_network/passt/passt_function.py b/libvirt/tests/src/virtual_network/passt/passt_function.py index b8aab4822ad..ed0c4738177 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_function.py +++ b/libvirt/tests/src/virtual_network/passt/passt_function.py @@ -133,8 +133,6 @@ def run(test, params, env): vm.destroy() passt.check_passt_pid_not_exist() - if not vhostuser and os.listdir(socket_dir): - test.fail(f'Socket dir is not empty: {os.listdir(socket_dir)}') finally: firewalld.start() diff --git a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py index d29a6957211..40b57801dbb 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py +++ b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py @@ -15,7 +15,6 @@ from virttest.staging import service from virttest.staging import utils_memory from virttest.utils_libvirt import libvirt_unprivileged -from virttest.utils_test import libvirt from provider.virtual_network import network_base from provider.virtual_network import passt @@ -62,7 +61,6 @@ def run(test, params, env): params['socket_dir'] = socket_dir = eval(params.get('socket_dir')) params['proc_checks'] = proc_checks = eval(params.get('proc_checks', '{}')) mtu = params.get('mtu') - qemu_cmd_check = params.get('qemu_cmd_check') outside_ip = params.get('outside_ip') host_iface = params.get('host_iface') host_iface = host_iface if host_iface else utils_net.get_default_gateway( @@ -92,8 +90,6 @@ def run(test, params, env): passt.vm_add_iface(vmxml, iface_attrs, virsh_ins) vm.start() - libvirt.check_qemu_cmd_line(qemu_cmd_check) - passt_proc = passt.get_proc_info('passt') LOG.debug(f'passt process info: {passt_proc}') From 827d7c4104a4fa4a72db7c5a9bfeecacd9c2f3b7 Mon Sep 17 00:00:00 2001 From: meinaLi Date: Thu, 22 May 2025 03:21:05 -0400 Subject: [PATCH 0974/1055] Inc_backup: automate one case which is related to readonly disk Automate case: RHEL-189084 - [incremental_backup] push mode full backup and incremental backup for a READONLY disk Signed-off-by: meinaLi --- .../incremental_backup_push_mode.cfg | 8 ++++++ .../incremental_backup_push_mode.py | 28 +++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg b/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg index 93c29585d5a..dcf1371caa7 100644 --- a/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg +++ b/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg @@ -26,6 +26,14 @@ prepare_target_file = "no" - positive_test: - not_reuse_target_file: + variants: + - normal_disk: + - readonly_disk: + only original_disk_local.coldplug_disk.backup_to_qcow2 + with_readonly = "yes" + backup_rounds = 2 + original_disk_size = 1024M + dd_count = "100" - backup_to_block: target_type = "block" backup_rounds = 1 diff --git a/libvirt/tests/src/incremental_backup/incremental_backup_push_mode.py b/libvirt/tests/src/incremental_backup/incremental_backup_push_mode.py index 9e0c181dcfb..48db1776188 100644 --- a/libvirt/tests/src/incremental_backup/incremental_backup_push_mode.py +++ b/libvirt/tests/src/incremental_backup/incremental_backup_push_mode.py @@ -68,6 +68,7 @@ def backup_job_done(vm_name, vm_disk): expect_backup_canceled = "yes" == params.get("expect_backup_canceled") tmp_dir = data_dir.get_data_dir() with_data_file = "yes" == params.get("with_data_file", "no") + with_readonly = "yes" == params.get("with_readonly", "no") libvirt_version.is_libvirt_feature_supported(params) virsh_dargs = {'debug': True, 'ignore_status': True} @@ -263,6 +264,10 @@ def backup_job_done(vm_name, vm_disk): # Start backup backup_options = backup_xml.xml + " " + checkpoint_xml.xml + if with_readonly: + backup_options = backup_xml.xml + if backup_index == 0: + virsh.checkpoint_create(vm_name, checkpoint_xml.xml, **virsh_dargs) # Create some data in vdb dd_count = params.get("dd_count", "1") @@ -275,6 +280,18 @@ def backup_job_done(vm_name, vm_disk): if reuse_target_file: backup_options += " --reuse-external" + if with_readonly and backup_index == 0: + virsh.detach_device(vm_name, disk_xml, + flagstr="--config", debug=True) + virsh.destroy(vm_name) + disk_params.update({"readonly": "yes"}) + disk_xml_readonly = libvirt.create_disk_xml(disk_params) + virsh.attach_device(vm.name, disk_xml_readonly, + flagstr="--config", debug=True) + virsh.start(vm_name, debug=True) + vm.wait_for_login().close() + test.log.debug("The current disk xml is: %s" + % virsh.dumpxml(vm_name, "--xpath //disk").stdout_text) backup_result = virsh.backup_begin(vm_name, backup_options, debug=True) if backup_result.exit_status: @@ -296,9 +313,16 @@ def backup_job_done(vm_name, vm_disk): if not utils_misc.wait_for( lambda: backup_job_done(vm_name, original_disk_target), 60): test.fail("Backup job not finished in 60s") + if with_readonly: + img_info = utils_misc.get_image_info(target_file_path) + if img_info['dsize'] >= 100: + test.log.info("The disk size is acceptable.") + else: + test.fail("Can't get the expected disk size!") - for checkpoint_name in checkpoint_list: - virsh.checkpoint_delete(vm_name, checkpoint_name, debug=True) + if not with_readonly: + for checkpoint_name in checkpoint_list: + virsh.checkpoint_delete(vm_name, checkpoint_name, debug=True) if vm.is_alive(): vm.destroy(gracefully=False) From 653bba26d2b35d13d47bca0ccd7e5bec7c65d72e Mon Sep 17 00:00:00 2001 From: Han Han Date: Thu, 22 May 2025 22:06:58 +0800 Subject: [PATCH 0975/1055] update_device: Add the missing source network It will fix the error like following when defining a domain: XML error: interface type='network' requires a 'source' element Signed-off-by: Han Han --- .../update_device/update_iface_with_options_active.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_options_active.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_options_active.cfg index 8bc7942e8d1..bde26fdeafc 100644 --- a/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_options_active.cfg +++ b/libvirt/tests/cfg/virtual_network/update_device/update_iface_with_options_active.cfg @@ -3,8 +3,8 @@ start_vm = no timeout = 240 vm_active = True - iface_attrs = {'link_state': 'up'} - update_attrs = {'link_state': 'down'} + iface_attrs = {'link_state': 'up', 'source': {'network': 'default'}} + update_attrs = {'link_state': 'down', 'source': {'network': 'default'}} variants options: - live: update_expect = {'active': True, 'inactive': False} From e11b44f241bc7184ca6ed5ea9d28ffb40bad6996 Mon Sep 17 00:00:00 2001 From: Yanqiu Zhang Date: Tue, 20 May 2025 09:43:24 -0400 Subject: [PATCH 0976/1055] tpm_device: avoid chcon on bin files Deleting chcon for /usr/bin/swtpm_setup or /usr/bin/swtpm, in case of running failure in Read-only filesystems. Signed-off-by: Yanqiu Zhang --- .../tests/cfg/virtual_device/tpm_device.cfg | 2 -- .../tests/src/virtual_device/tpm_device.py | 26 +++++++++++-------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/libvirt/tests/cfg/virtual_device/tpm_device.cfg b/libvirt/tests/cfg/virtual_device/tpm_device.cfg index 45b618567c7..a5abf51f759 100644 --- a/libvirt/tests/cfg/virtual_device/tpm_device.cfg +++ b/libvirt/tests/cfg/virtual_device/tpm_device.cfg @@ -146,8 +146,6 @@ no default_model source_attrs = {'type': 'unix', 'mode': 'connect', 'path': '/var/tmp/guest-swtpm.sock'} statedir = "/var/tmp/mytpm" - swtpm_setup_path = '/usr/bin/swtpm_setup' - swtpm_path = '/usr/bin/swtpm' variants: - start_vm: audit_cmd = "cat /var/log/audit/audit.log| grep 'tpm-external'" diff --git a/libvirt/tests/src/virtual_device/tpm_device.py b/libvirt/tests/src/virtual_device/tpm_device.py index 687d795bdd9..53b0d6ce8b3 100644 --- a/libvirt/tests/src/virtual_device/tpm_device.py +++ b/libvirt/tests/src/virtual_device/tpm_device.py @@ -6,6 +6,7 @@ import platform import shutil import glob +import subprocess from virttest import data_dir from virttest import libvirt_version @@ -92,8 +93,7 @@ def run(test, params, env): audit_cmd = params.get("audit_cmd") ausearch_check = params.get("ausearch_check") skip_start = ('yes' == params.get("skip_start", "no")) - swtpm_setup_path = params.get("swtpm_setup_path") - swtpm_path = params.get("swtpm_path") + p2 = None source_attrs_str = params.get("source_attrs") if source_attrs_str: source_attrs = ast.literal_eval(source_attrs_str) @@ -305,7 +305,7 @@ def check_dumpxml(vm_name): def launch_external_swtpm(skip_setup): """ - Launch externally swtpm + Launch external swtpm :param skip_setup: whether skip swtpm_setup steps """ @@ -314,16 +314,19 @@ def launch_external_swtpm(skip_setup): shutil.rmtree(statedir) os.mkdir(statedir) process.run("ls -lZd %s" % statedir) - process.run('chcon -t virtd_exec_t %s' % swtpm_setup_path, ignore_status=False, shell=True) - cmd1 = "systemd-run %s --tpm2 --tpmstate %s --create-ek-cert --create-platform-cert --overwrite" % (swtpm_setup_path, statedir) - process.run('chcon -t virtd_exec_t %s' % swtpm_path, ignore_status=False, shell=True) - cmd2 = "systemd-run %s socket --ctrl type=unixio,path=%s,mode=0600 --tpmstate dir=%s,mode=0600 --tpm2 --terminate" % (swtpm_path, source_socket, statedir) + cmd1 = "swtpm_setup --tpm2 --tpmstate %s --create-ek-cert --create-platform-cert --overwrite" % statedir + cmd2 = "swtpm socket --ctrl type=unixio,path=%s,mode=0600 --tpmstate dir=%s,mode=0600 --tpm2 --terminate" % (source_socket, statedir) try: if not skip_setup: process.run(cmd1, ignore_status=False, shell=True) - process.run(cmd2, ignore_status=False, shell=True) + logging.debug("Running '%s'", cmd2) + p2 = subprocess.Popen(cmd2, shell=True, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + process.run("ps aux|grep 'swtpm socket'|grep -v avocado-runner-avocado-vt|grep -v grep", ignore_status=True, shell=True) + if p2.poll() is not None: + test.error('External swtpm socket process does not exist') # Make sure the socket is created - utils_misc.wait_for(lambda: os.path.isdir(source_socket), timeout=3) + utils_misc.wait_for(lambda: os.path.exists(source_socket), timeout=3) process.run('chcon -t svirt_image_t %s' % source_socket, ignore_status=False, shell=True) process.run('chown qemu:qemu %s' % source_socket, ignore_status=False, shell=True) except Exception as err: @@ -1036,10 +1039,11 @@ def test_swtpm_logging(): vm_xml_backup.sync(options="--nvram --managed-save") check_swtpmpidfile(vm_name, "test finished") if backend_type == 'external' and not status_error: - process.run("restorecon %s" % swtpm_setup_path, ignore_status=False, shell=True) - process.run("restorecon %s" % swtpm_path, ignore_status=False, shell=True) if os.path.exists(statedir): shutil.rmtree(statedir) + if p2 and p2.poll() is None: + p2.kill() + process.run("rm -rf /var/lib/swtpm-localca/*", shell=True, ignore_status=True) # Remove swtpm log file in case of impact on later runs if os.path.exists("/var/log/swtpm/libvirt/qemu/%s-swtpm.log" % vm.name): os.remove("/var/log/swtpm/libvirt/qemu/%s-swtpm.log" % vm.name) From 3c618a265447ca449c60dfec12a813ebc6d3b2bd Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Thu, 22 May 2025 03:44:11 -0400 Subject: [PATCH 0977/1055] Update the shared memory configuration The previous code use hugepages as backend of the memory, which is not supported with unpriviledged users. Update it to use memfd backend which is currently used the CNV. And add one step in the cleanup section to kill the legacy passt process if there is. Signed-off-by: Yalan Zhang --- .../tests/src/virtual_network/passt/passt_attach_detach.py | 5 +---- libvirt/tests/src/virtual_network/passt/passt_function.py | 5 +---- libvirt/tests/src/virtual_network/passt/passt_lifecycle.py | 7 +------ libvirt/tests/src/virtual_network/passt/passt_reconnect.py | 5 ++--- provider/virtual_network/passt.py | 1 + 5 files changed, 6 insertions(+), 17 deletions(-) diff --git a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py index eaa701d601b..6c09c65a0f8 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py +++ b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py @@ -97,10 +97,8 @@ def run(test, params, env): vmxml.del_device('interface', by_tag=True) if vhostuser: - # set static hugepage - utils_memory.set_num_huge_pages(2048) - vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", hpgs=True, vmxml=vmxml) # update vm xml with shared memory and vhostuser interface + vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", hpgs=False, memfd=True, vmxml=vmxml) iface_attrs['type_name'] = 'vhostuser' iface_device = libvirt_vmxml.create_vm_device_by_type('interface', iface_attrs) @@ -190,4 +188,3 @@ def run(test, params, env): if root: shutil.rmtree(log_dir) utils_selinux.set_status(selinux_status) - utils_memory.set_num_huge_pages(shp_orig_num) diff --git a/libvirt/tests/src/virtual_network/passt/passt_function.py b/libvirt/tests/src/virtual_network/passt/passt_function.py index ed0c4738177..54860988ae5 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_function.py +++ b/libvirt/tests/src/virtual_network/passt/passt_function.py @@ -87,10 +87,8 @@ def run(test, params, env): vmxml.del_device('interface', by_tag=True) vmxml.sync(virsh_instance=virsh_ins) if vhostuser: - # set static hugepage - utils_memory.set_num_huge_pages(2048) - vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", hpgs=True, vmxml=vmxml) # update vm xml with shared memory and vhostuser interface + vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", hpgs=False, memfd=True, vmxml=vmxml) iface_attrs['type_name'] = 'vhostuser' libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs, virsh_instance=virsh_ins) @@ -140,4 +138,3 @@ def run(test, params, env): if root: shutil.rmtree(log_dir) utils_selinux.set_status(selinux_status) - utils_memory.set_num_huge_pages(shp_orig_num) diff --git a/libvirt/tests/src/virtual_network/passt/passt_lifecycle.py b/libvirt/tests/src/virtual_network/passt/passt_lifecycle.py index 3ee24128e13..b2950dd0ddb 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_lifecycle.py +++ b/libvirt/tests/src/virtual_network/passt/passt_lifecycle.py @@ -102,10 +102,8 @@ def run(test, params, env): libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs, virsh_instance=virsh_ins) if vhostuser: - # set static hugepage - utils_memory.set_num_huge_pages(2048) - vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", hpgs=True, vmxml=vmxml) # update vm xml with shared memory and vhostuser interface + vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", hpgs=False, memfd=True, vmxml=vmxml) iface_attrs['type_name'] = 'vhostuser' LOG.debug(virsh_ins.dumpxml(vm_name).stdout_text) mac = vm.get_virsh_mac_address() @@ -158,8 +156,6 @@ def run(test, params, env): vm.destroy() passt.check_passt_pid_not_exist() - if not vhostuser and os.listdir(socket_dir): - test.fail(f'Socket dir is not empty: {os.listdir(socket_dir)}') finally: firewalld.start() @@ -169,4 +165,3 @@ def run(test, params, env): utils_selinux.set_status(selinux_status) if os.path.exists(save_path): os.remove(save_path) - utils_memory.set_num_huge_pages(shp_orig_num) diff --git a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py index 40b57801dbb..060aa862a7f 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py +++ b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py @@ -85,8 +85,8 @@ def run(test, params, env): if vhostuser: iface_attrs['type_name'] = 'vhostuser' - utils_memory.set_num_huge_pages(2048) - vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", hpgs=True, vmxml=vmxml) + # update vm xml with shared memory and vhostuser interface + vm_xml.VMXML.set_memoryBacking_tag(vm_name, access_mode="shared", hpgs=False, memfd=True, vmxml=vmxml) passt.vm_add_iface(vmxml, iface_attrs, virsh_ins) vm.start() @@ -145,4 +145,3 @@ def run(test, params, env): if root: shutil.rmtree(log_dir) utils_selinux.set_status(selinux_status) - utils_memory.set_num_huge_pages(shp_orig_num) diff --git a/provider/virtual_network/passt.py b/provider/virtual_network/passt.py index 4e897506b8b..1636028a5e4 100644 --- a/provider/virtual_network/passt.py +++ b/provider/virtual_network/passt.py @@ -467,6 +467,7 @@ def check_passt_pid_not_exist(): pid_passt = process.run('pidof passt', ignore_status=True).stdout_text.strip() if pid_passt: + utils_misc.kill_process_tree(pid_passt) raise exceptions.TestFail(f'Process of passt still exists: ' f'{pid_passt}') From e4dd2910379d8ea28a2e9e6e74741136396039f0 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Wed, 21 May 2025 02:37:12 -0400 Subject: [PATCH 0978/1055] Enable virtio-mem on s390x Signed-off-by: liang-cong-red-hat --- .../change_virtio_mem_request_size.cfg | 19 +++++++-- .../invalid_virtio_mem_config.cfg | 39 +++++++++++------- .../virtio_mem_access_and_discard.cfg | 40 ++++++++++--------- .../virtio_mem_coldplug_and_unplug.cfg | 25 +++++++++++- .../virtio_mem_device_lifecycle.cfg | 18 ++++++++- .../virtio_mem_dynamic_slots.cfg | 8 +++- .../memory_devices/virtio_mem_hot_unplug.cfg | 19 ++++++++- .../memory_devices/virtio_mem_hotplug.cfg | 16 +++++++- ...io_mem_with_memory_allocation_and_numa.cfg | 24 ++++++++--- .../virtio_mem_with_memory_backing_type.cfg | 25 +++++++++++- .../change_virtio_mem_request_size.py | 23 ++++++++++- .../invalid_virtio_mem_config.py | 8 ++-- .../virtio_mem_access_and_discard.py | 26 ++++++------ .../memory_devices/virtio_mem_hot_unplug.py | 23 +++++++++-- .../memory_devices/virtio_mem_hotplug.py | 22 +++++++--- ...tio_mem_with_memory_allocation_and_numa.py | 3 +- .../virtio_mem_with_memory_backing_type.py | 27 +++++++++---- 17 files changed, 282 insertions(+), 83 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_devices/change_virtio_mem_request_size.cfg b/libvirt/tests/cfg/memory/memory_devices/change_virtio_mem_request_size.cfg index 3626a1eeaa3..7b3cb917e6e 100644 --- a/libvirt/tests/cfg/memory/memory_devices/change_virtio_mem_request_size.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/change_virtio_mem_request_size.cfg @@ -1,6 +1,5 @@ - memory.devices.virtio_mem.change_memory: type = change_virtio_mem_request_size - no s390-virtio start_vm = yes mem_model = "virtio-mem" allocate_huge_pages = "4194304KiB" @@ -26,19 +25,28 @@ numa_attrs = "'vcpu': 4, 'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'},{'id':'1','cpus': '2-3','memory':'${numa_mem}','unit':'KiB'}]}" max_attrs = "'max_mem_rt': ${max_mem}, 'max_mem_rt_slots': ${max_mem_slots}, 'max_mem_rt_unit': 'KiB'" vm_attrs = {${base_attrs}, ${numa_attrs}, ${max_attrs}} + with_numa = yes + s390-virtio: + with_numa = no + vm_attrs = {${base_attrs}, ${max_attrs}} expect_xpath = [{'element_attrs':[".//memory[@unit='${memory_unit}']"],'text':'%d'},{'element_attrs':[".//currentMemory[@unit='KiB']"],'text':'%d'}] variants guest_state: - shutoff_guest: + no s390-virtio no file hugepages memfd mem_basic = {'mem_model': '${mem_model}', 'target': {'requested_unit': '${requested_unit}', 'size': %s, 'node': ${basic_node}, 'size_unit': 'KiB', 'requested_size': %s, 'block_unit': 'KiB', 'block_size': %s}} - running_guest: - kernel_extra_params_add = "memhp_default_state=online_movable" - kernel_extra_params_remove = "memhp_default_state" + kernel_params_add = "memhp_default_state=online_movable" + kernel_params_remove = "memhp_default_state" attach_node = 1 attached_device = "--node ${attach_node}" basic_device_alias = "--alias virtiomem0" mem_basic = {'mem_model': '${mem_model}', 'target': {'requested_unit': '${requested_unit}', 'size': %s, 'node': ${basic_node}, 'size_unit': 'KiB', 'requested_size': %s, 'block_unit': 'KiB', 'block_size': %s}} mem_attach = {'mem_model': '${mem_model}', 'target': {'requested_unit': '${requested_unit}', 'size': %s, 'node': ${attach_node}, 'size_unit': 'KiB', 'requested_size': %s, 'block_unit': 'KiB', 'block_size': %s}} + s390-virtio: + attached_device = "--alias virtiomem1" + mem_basic = {'mem_model': '${mem_model}', 'target': {'requested_unit': '${requested_unit}', 'size': %s, 'size_unit': 'KiB', 'requested_size': %s, 'block_unit': 'KiB', 'block_size': %s}} + mem_attach = {'mem_model': '${mem_model}', 'target': {'requested_unit': '${requested_unit}', 'size': %s, 'size_unit': 'KiB', 'requested_size': %s, 'block_unit': 'KiB', 'block_size': %s}} variants requested_setting: - normal_requested: update_request_size = '1024MiB' @@ -49,14 +57,19 @@ error_msg = "requested size must be smaller than or equal to" - not_mutiple_of_block_requested: update_request_size = '513MiB' + s390-virtio: + update_request_size = '524800KiB' error_msg = "requested size must be an integer multiple of block size" variants memory_backing: - file: source_type = 'file' source_attr = "'source_type':'${source_type}'" - hugepages: + s390-virtio: + kvm_module_parameters = "hpage=1" hugepages_attr = "'hugepages': {}" - memfd: source_type = 'memfd' source_attr = "'source_type':'${source_type}'" - undefined: + diff --git a/libvirt/tests/cfg/memory/memory_devices/invalid_virtio_mem_config.cfg b/libvirt/tests/cfg/memory/memory_devices/invalid_virtio_mem_config.cfg index 9f3dc29cc74..367ecedc4c2 100644 --- a/libvirt/tests/cfg/memory/memory_devices/invalid_virtio_mem_config.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/invalid_virtio_mem_config.cfg @@ -6,13 +6,31 @@ target_size = 524288 request_size = 262144 block_size = 2048 + with_numa = yes aarch64: request_size = 524288 block_size = 524288 + s390-virtio: + with_numa = no + request_size = 262144 + block_size = 1024 guest_node = 0 addr_base = '0x100000000' pagesize_cmd = "getconf PAGE_SIZE" pagesize_unit = 'b' + mem_value = 2097152 + mem_unit = 'KiB' + current_mem = 2097152 + current_mem_unit = 'KiB' + numa_mem = 1048576 + max_mem_slots = 16 + max_mem = 10485760 + max_mem_unit = 'KiB' + max_dict = '"max_mem_rt": ${max_mem}, "max_mem_rt_slots": ${max_mem_slots}, "max_mem_rt_unit": "${max_mem_unit}"' + numa_attrs = "'vcpu': 4,'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'},{'id':'1','cpus': '2-3','memory':'${numa_mem}','unit':'KiB'}]}" + vm_attrs = {${numa_attrs}, ${max_dict}, 'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':"KiB"} + s390-virtio: + vm_attrs = {${max_dict}, 'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':"KiB"} required_kernel = [5.14.0,) guest_required_kernel = [5.8.0,) func_supported_since_libvirt_ver = (8, 0, 0) @@ -25,9 +43,11 @@ addr_base = '0xffffffffffffffff' define_error = "memory device address must be aligned to blocksize" - unexisted_node: + no s390-virtio guest_node = '6' define_error = "can't add memory backend for guest node '${guest_node}' as the guest has only '2' NUMA nodes configured" - unexisted_nodemask: + no s390-virtio node_mask = '7' start_vm_error = "NUMA node ${node_mask} is unavailable" - invalid_pagesize: @@ -36,6 +56,8 @@ start_vm_error = "Unable to find any usable hugetlbfs mount for 9 KiB" - small_block: block_size = '1024' + s390-virtio: + block_size = '512' define_error = "block size too small, must be at least" - invalid_block: block_size = "3072" @@ -43,18 +65,7 @@ addr_dict = "'address':{'attrs': {'base': '${addr_base}','slot': '0'}}" source_dict = "'source': {'nodemask': '${node_mask}','pagesize': %d, 'pagesize_unit':'${pagesize_unit}'}" mem_dict = {'mem_model':'${mem_model}', ${source_dict}, 'target': {'size':${target_size}, 'size_unit':'KiB', ${addr_dict}, 'node':${guest_node},'requested_size': ${request_size}, 'block_size': ${block_size}}} - variants basic_memory: - - with_numa: - no s390-virtio - mem_value = 2097152 - mem_unit = 'KiB' - current_mem = 2097152 - current_mem_unit = 'KiB' - numa_mem = 1048576 - max_mem_slots = 16 - max_mem = 10485760 - max_mem_unit = 'KiB' - max_dict = '"max_mem_rt": ${max_mem}, "max_mem_rt_slots": ${max_mem_slots}, "max_mem_rt_unit": "${max_mem_unit}"' - numa_attrs = "'vcpu': 4,'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'},{'id':'1','cpus': '2-3','memory':'${numa_mem}','unit':'KiB'}]}" - vm_attrs = {${numa_attrs}, ${max_dict}, 'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':"KiB"} + s390-virtio: + source_dict = "'source': {'pagesize': %d, 'pagesize_unit':'${pagesize_unit}'}" + mem_dict = {'mem_model':'${mem_model}', ${source_dict}, 'target': {'size':${target_size}, 'size_unit':'KiB', ${addr_dict}, 'requested_size': ${request_size}, 'block_size': ${block_size}}} diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_access_and_discard.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_access_and_discard.cfg index a73695f2bf8..e1c05a622e3 100644 --- a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_access_and_discard.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_access_and_discard.cfg @@ -2,23 +2,42 @@ type = virtio_mem_access_and_discard start_vm = no mem_model = "virtio-mem" - virtio_mem_num = 6 share_0 = 'false' discard_0 = 'False' check_path = "ls -l /var/lib/libvirt/qemu/ram/%s" target_size = 131072 requested_size = 131072 block_size = 2048 - no s390-virtio + mem_value = 3145728 + current_mem = 3145728 + max_mem = 10485760 aarch64: + max_mem = 20971520 target_size = 1048576 requested_size = 524288 block_size = 524288 mem_basic = {'mem_model': '${mem_model}', 'target': {'requested_unit': 'KiB', 'size': ${target_size}, 'size_unit': 'KiB', 'requested_size': ${requested_size}, 'block_unit': 'KiB', 'block_size': ${block_size}}} + base_attrs = "'vcpu': 6, 'placement': 'static', 'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'" + max_attrs = "'max_mem_rt': ${max_mem}, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'" required_kernel = [5.14.0,) guest_required_kernel = [5.8.0,) func_supported_since_libvirt_ver = (8, 0, 0) func_supported_since_qemu_kvm_ver = (6, 2, 0) + variants: + - with_numa: + no s390-virtio + numa_mem = 1048576 + mem_access_1 = "shared" + discard_1 = "yes" + mem_access_2 = "private" + discard_2 = "no" + numa_attrs = "'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_mem}', 'unit': 'KiB', 'memAccess':'${mem_access_1}','discard':'${discard_1}'},{'id':'2','cpus': '4-5','memory':'${numa_mem}','unit':'KiB', 'memAccess':'${mem_access_2}','discard':'${discard_2}'}]}" + vm_attrs = {${base_attrs}, ${numa_attrs}, ${max_attrs}} + mem_conf_list = [(None, None, 0), ('shared', 'yes', 0), (None, None, 1), ('private', 'no', 1), (None, None, 2), ('shared', 'yes', 2)] + - without_numa: + only s390-virtio + vm_attrs = {${base_attrs}, ${max_attrs}} + mem_conf_list = [(None, None, None), ('shared', 'yes', None)] variants memory_backing: - file: source_type = 'file' @@ -57,19 +76,4 @@ expected_share = ['${share_0}', 'true', 'true', 'false', 'false', 'true'] check_discard = '{"execute":"qom-get", "arguments":{"path":"/objects/%s", "property":"discard-data"}}' expected_discard = ['${discard_0}', 'True', 'True', 'False', 'False', 'True'] - variants: - - with_numa: - mem_value = 3145728 - current_mem = 3145728 - max_mem = 10485760 - numa_mem = 1048576 - aarch64: - max_mem = 20971520 - mem_access_1 = "shared" - discard_1 = "yes" - mem_access_2 = "private" - discard_2 = "no" - base_attrs = "'vcpu': 6, 'placement': 'static', 'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'" - numa_attrs = "'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_mem}', 'unit': 'KiB', 'memAccess':'${mem_access_1}','discard':'${discard_1}'},{'id':'2','cpus': '4-5','memory':'${numa_mem}','unit':'KiB', 'memAccess':'${mem_access_2}','discard':'${discard_2}'}]}" - max_attrs = "'max_mem_rt': ${max_mem}, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'" - vm_attrs = {${base_attrs}, ${numa_attrs}, ${max_attrs}} + diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_coldplug_and_unplug.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_coldplug_and_unplug.cfg index 9b7b4b416ca..f96558a44c0 100644 --- a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_coldplug_and_unplug.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_coldplug_and_unplug.cfg @@ -1,6 +1,5 @@ - memory.devices.virtio_mem.coldplug_and_unplug: type = virtio_mem_coldplug_and_unplug - no s390-virtio start_vm = "no" mem_model = "virtio-mem" target_size = 524288 @@ -20,6 +19,9 @@ numa_dict = "'vcpu': 4,'cpu':{'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_mem}'}]}" vm_attrs = {${numa_dict},${max_dict},'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'} numa_xpath = [{'element_attrs':[".//cell[@unit='KiB']",".//cell[@id='0']",".//cell[@memory='${numa_mem}']"]}] + s390-virtio: + vm_attrs = {${max_dict},'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'} + numa_xpath = [] base = '0x100000000' plug_option = " --config" required_kernel = [5.14.0,) @@ -37,6 +39,10 @@ virtio_xpath = [{'element_attrs':["./devices/memory/target/size[@unit='${size_unit}']"],'text':'${target_size}'},{'element_attrs':[".//memory/target/block[@unit='${block_unit}']"],'text':'%s'}, {'element_attrs':[".//memory/target/requested[@unit='${request_unit}']"],'text':'${request_size}'},{'element_attrs':[".//memory/target/address[@base='${base}']"]}] unplug_xpath = ${virtio_xpath} plug_xpath = [{'element_attrs':[".//memory/target/size[@unit='${plug_size_unit}']"],'text':'${plug_target_size}'},{'element_attrs':[".//memory/target/block[@unit='${block_unit}']"],'text':'%s'}, {'element_attrs':[".//memory/target/requested[@unit='${plug_request_unit}']"],'text':'${plug_request_size}'},{'element_attrs':[".//memory/target/address[@base='${base}']"]}] + s390-virtio: + virtio_dict = {'mem_model':'${mem_model}','target': {${addr_dict},'size':${target_size}, 'size_unit':'${size_unit}', 'requested_size': ${request_size},'requested_unit':'${request_unit}', 'block_size': %s, 'block_unit':'${block_unit}'}} + unplug_dict = ${virtio_dict} + plug_dict = {'mem_model':'${mem_model}','target': {${addr_dict},'size':${plug_target_size},'requested_size': ${plug_request_size}, 'block_size': %s, 'size_unit':'${plug_size_unit}','requested_unit':'${plug_request_unit}','block_unit':'${plug_block_unit}'}} - source_and_mib: target_size = 512 request_size = 512 @@ -54,12 +60,22 @@ plug_dict = {'mem_model':'${mem_model}',${source_dict},'target': {'size':${plug_target_size},'requested_size': ${plug_request_size}, 'block_size': %s, 'size_unit':'${plug_size_unit}','requested_unit':'${plug_request_unit}','block_unit':'${plug_block_unit}','node':1}} virtio_xpath = [{'element_attrs':[".//memory/target/size[@unit='KiB']"],'text':'%s'},{'element_attrs':[".//memory/target/block[@unit='KiB']"],'text':'%s'}, {'element_attrs':[".//memory/target/requested[@unit='KiB']"],'text':'%s'}, {'element_attrs':[".//memory/source/pagesize"]}, {'element_attrs':[".//memory/source/nodemask"],'text':'${nodemask}'}] unplug_xpath = ${virtio_xpath} + s390-virtio: + source_dict = "'source': {'pagesize': 4, 'pagesize_unit':'KiB'}" + virtio_dict = {'mem_model':'${mem_model}',${source_dict}, 'target': {'size':${target_size}, 'size_unit':'${size_unit}','requested_unit':'${request_unit}','block_unit':'${block_unit}','requested_size': ${request_size}, 'block_size': %s}} + unplug_dict = ${virtio_dict} + plug_dict = {'mem_model':'${mem_model}',${source_dict},'target': {'size':${plug_target_size},'requested_size': ${plug_request_size}, 'block_size': %s, 'size_unit':'${plug_size_unit}','requested_unit':'${plug_request_unit}','block_unit':'${plug_block_unit}'}} + virtio_xpath = [{'element_attrs':[".//memory/target/size[@unit='KiB']"],'text':'%s'},{'element_attrs':[".//memory/target/block[@unit='KiB']"],'text':'%s'}, {'element_attrs':[".//memory/target/requested[@unit='KiB']"],'text':'%s'}, {'element_attrs':[".//memory/source/pagesize"]}] + unplug_xpath = ${virtio_xpath} plug_xpath = [{'element_attrs':[".//memory/target/size[@unit='KiB']"],'text':'%s'},{'element_attrs':[".//memory/target/block[@unit='KiB']"],'text':'%s'}, {'element_attrs':[".//memory/target/requested[@unit='KiB']"],'text':'%s'}] - unplug_none_dev: addr_dict = "'address':{'attrs': {'base': '${base}'}}" virtio_dict = {'mem_model':'${mem_model}', 'target': {'size':${target_size}, 'size_unit':'KiB', ${addr_dict}, 'node':0,'requested_size': ${request_size}, 'block_size': %s}} unplug_request_size = 0 unplug_dict = {'mem_model':'${mem_model}', 'target': {'requested_size': ${unplug_request_size}, 'size':${target_size}, 'size_unit':'KiB', ${addr_dict}, 'node':0,'block_size': %s}} + s390-virtio: + virtio_dict = {'mem_model':'${mem_model}', 'target': {'size':${target_size}, 'size_unit':'KiB', ${addr_dict}, 'requested_size': ${request_size}, 'block_size': %s}} + unplug_dict = {'mem_model':'${mem_model}', 'target': {'requested_size': ${unplug_request_size}, 'size':${target_size}, 'size_unit':'KiB', ${addr_dict}, 'block_size': %s}} unplug_error = "matching memory device was not found" virtio_xpath = [{'element_attrs':[".//memory/target/size[@unit='${size_unit}']"],'text':'${target_size}'},{'element_attrs':[".//memory/target/block[@unit='${block_unit}']"],'text':'%s'}, {'element_attrs':[".//memory/target/requested[@unit='${request_unit}']"],'text':'${request_size}'},{'element_attrs':[".//memory/target/address[@base='${base}']"]}] unplug_xpath = [{'element_attrs':[".//memory/target/size[@unit='${size_unit}']"],'text':'${target_size}'},{'element_attrs':[".//memory/target/block[@unit='${plug_block_unit}']"],'text':'%s'}, {'element_attrs':[".//memory/target/requested[@unit='${plug_request_unit}']"],'text':'${unplug_request_size}'},{'element_attrs':[".//memory/target/address[@base='${base}']"]}] @@ -75,6 +91,9 @@ virtio_xpath = [{'element_attrs':[".//memory/target/size[@unit='${size_unit}']"],'text':'${target_size}'},{'element_attrs':[".//memory/target/block[@unit='${block_unit}']"],'text':'%s'}, {'element_attrs':[".//memory/target/requested[@unit='${request_unit}']"],'text':'${request_size}'}] plug_xpath = [{'element_attrs':[".//memory/target/size[@unit='${size_unit}']"],'text':'%s'},{'element_attrs':[".//memory/target/block[@unit='${block_unit}']"],'text':'%s'}, {'element_attrs':[".//memory/target/requested[@unit='${request_unit}']"],'text':'%s'}] plug_error = "Attaching memory device with size '\S+' would exceed domain's maxMemory config size '${max_mem}'" + s390-virtio: + virtio_dict = {'mem_model':'${mem_model}', 'target': {'size':${target_size}, 'size_unit':'KiB','requested_size': ${request_size}, 'block_size': %s}} + plug_dict = {'mem_model':'${mem_model}','target': {'size':${plug_target_size},'requested_size': ${plug_request_size}, 'block_size': %s, 'size_unit':'${plug_size_unit}','requested_unit':'${plug_request_unit}','block_unit':'${plug_block_unit}'}} - duplicate_addr: addr_dict = "'address':{'attrs': {'base': '0x100000000'}}" virtio_dict = {'mem_model':'${mem_model}', 'target': {${addr_dict},'size':${target_size}, 'size_unit':'KiB', ${addr_dict}, 'node':0,'requested_size': ${request_size}, 'block_size': %s}} @@ -82,3 +101,7 @@ plug_error = "unsupported configuration: memory device address [0x100000000:0x108000000] overlaps with other memory device (0x100000000)" virtio_xpath = [{'element_attrs':[".//memory/target/size[@unit='${size_unit}']"],'text':'${target_size}'},{'element_attrs':[".//memory/target/block[@unit='${block_unit}']"],'text':'%s'}, {'element_attrs':[".//memory/target/requested[@unit='${request_unit}']"],'text':'${request_size}'},{'element_attrs':[".//memory/target/address[@base='${base}']"]}] plug_xpath = ${virtio_xpath} + s390-virtio: + virtio_dict = {'mem_model':'${mem_model}', 'target': {${addr_dict},'size':${target_size}, 'size_unit':'KiB', ${addr_dict}, 'requested_size': ${request_size}, 'block_size': %s}} + plug_dict = ${virtio_dict} + diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_device_lifecycle.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_device_lifecycle.cfg index cd62f1a8744..7332f6d661e 100644 --- a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_device_lifecycle.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_device_lifecycle.cfg @@ -1,6 +1,5 @@ - memory.devices.virtio_mem.lifecycle: type = virtio_mem_device_lifecycle - no s390-virtio start_vm = no state_file = "/tmp/%s.save" numa_mem_val = 1048576 @@ -17,11 +16,14 @@ guest_required_kernel = [5.8.0,) func_supported_since_libvirt_ver = (8, 0, 0) func_supported_since_qemu_kvm_ver = (6, 2, 0) + s390-virtio: + vm_attrs = {'max_mem_rt': 15428800, 'max_mem_rt_unit': 'KiB','memory_unit':"KiB", 'memory':${memory_val}, 'current_mem':${current_mem_val}, 'current_mem_unit':'KiB', 'vcpu': 4} variants kernel_pagesize: - 4k: - only x86_64, aarch64 page_size = 4 default_hp_size = 2048 + s390-virtio: + default_hp_size = 1024 - 64k: only aarch64 page_size = 64 @@ -31,6 +33,7 @@ source_dict = {} source_xpath = [] - nodemask: + no s390-virtio nodeset_num = 1 source_dict = {'nodemask':'%s'} source_xpath = [{'element_attrs':[".//source/nodemask"],'text':'%s'}] @@ -38,6 +41,7 @@ source_dict = {'pagesize':${page_size}, 'pagesize_unit':'KiB'} source_xpath = [{'element_attrs':[".//source/pagesize[@unit='KiB']"],'text':'${page_size}'}] - nodemask_pagesize: + no s390-virtio nodeset_num = 2 use_huge_page = "yes" source_dict = {'nodemask':'%s', 'pagesize':${default_hp_size}, 'pagesize_unit':'KiB'} @@ -54,6 +58,11 @@ init_target_xpath = [{'element_attrs':[".//target/size[@unit='KiB']"],'text':'${init_size}'}, {'element_attrs':[".//target/requested[@unit='KiB']"],'text':'${init_requested}'}, {'element_attrs':[".//target/block[@unit='KiB']"],'text':'${default_hp_size}'}, {'element_attrs':[".//target/current[@unit='KiB']"],'text':'${init_requested}'}, {'element_attrs':[".//target/node"],'text':'0'}, {'element_attrs':[".//target/address[@base='${init_address}']"]}] plug_target_dict = {'size':${plug_size}, 'size_unit':'KiB', 'node':1, 'requested_size':${plug_requested}, 'requested_unit':'KiB', 'block_size':${default_hp_size}, 'address':{'attrs':{'base':'${plug_address}'}}} plug_target_xpath = [{'element_attrs':[".//target/size[@unit='KiB']"],'text':'${plug_size}'}, {'element_attrs':[".//target/requested[@unit='KiB']"],'text':'${plug_requested}'}, {'element_attrs':[".//target/block[@unit='KiB']"],'text':'${default_hp_size}'}, {'element_attrs':[".//target/current[@unit='KiB']"],'text':'${plug_requested}'}, {'element_attrs':[".//target/node"],'text':'1'}, {'element_attrs':[".//target/address[@base='${plug_address}']"]}] + s390-virtio: + init_target_dict = {'size':${init_size}, 'size_unit':'KiB', 'requested_size':${init_requested}, 'requested_unit':'KiB', 'block_size':${default_hp_size}, 'address':{'attrs':{'base':'${init_address}'}}} + init_target_xpath = [{'element_attrs':[".//target/size[@unit='KiB']"],'text':'${init_size}'}, {'element_attrs':[".//target/requested[@unit='KiB']"],'text':'${init_requested}'}, {'element_attrs':[".//target/block[@unit='KiB']"],'text':'${default_hp_size}'}, {'element_attrs':[".//target/current[@unit='KiB']"],'text':'${init_requested}'}, {'element_attrs':[".//target/address[@base='${init_address}']"]}] + plug_target_dict = {'size':${plug_size}, 'size_unit':'KiB', 'requested_size':${plug_requested}, 'requested_unit':'KiB', 'block_size':${default_hp_size}, 'address':{'attrs':{'base':'${plug_address}'}}} + plug_target_xpath = [{'element_attrs':[".//target/size[@unit='KiB']"],'text':'${plug_size}'}, {'element_attrs':[".//target/requested[@unit='KiB']"],'text':'${plug_requested}'}, {'element_attrs':[".//target/block[@unit='KiB']"],'text':'${default_hp_size}'}, {'element_attrs':[".//target/current[@unit='KiB']"],'text':'${plug_requested}'}, {'element_attrs':[".//target/address[@base='${plug_address}']"]}] - part_requested_and_no_address: init_size = 1048576 init_requested = 524288 @@ -63,6 +72,11 @@ init_target_xpath = [{'element_attrs':[".//target/size[@unit='KiB']"],'text':'${init_size}'}, {'element_attrs':[".//target/requested[@unit='KiB']"],'text':'${init_requested}'}, {'element_attrs':[".//target/block[@unit='KiB']"],'text':'${default_hp_size}'}, {'element_attrs':[".//target/current[@unit='KiB']"],'text':'${init_requested}'}, {'element_attrs':[".//target/node"],'text':'0'}, {'element_attrs':[".//target/address"]}] plug_target_dict = {'size':${plug_size}, 'size_unit':'KiB', 'node':1, 'requested_size':${plug_requested}, 'requested_unit':'KiB', 'block_size':${default_hp_size}} plug_target_xpath = [{'element_attrs':[".//target/size[@unit='KiB']"],'text':'${plug_size}'}, {'element_attrs':[".//target/requested[@unit='KiB']"],'text':'${plug_requested}'}, {'element_attrs':[".//target/block[@unit='KiB']"],'text':'${default_hp_size}'}, {'element_attrs':[".//target/current[@unit='KiB']"],'text':'${plug_requested}'}, {'element_attrs':[".//target/node"],'text':'1'}, {'element_attrs':[".//target/address"]}] + s390-virtio: + init_target_dict = {'size':${init_size}, 'size_unit':'KiB', 'requested_size':${init_requested}, 'requested_unit':'KiB', 'block_size':${default_hp_size}} + init_target_xpath = [{'element_attrs':[".//target/size[@unit='KiB']"],'text':'${init_size}'}, {'element_attrs':[".//target/requested[@unit='KiB']"],'text':'${init_requested}'}, {'element_attrs':[".//target/block[@unit='KiB']"],'text':'${default_hp_size}'}, {'element_attrs':[".//target/current[@unit='KiB']"],'text':'${init_requested}'}, {'element_attrs':[".//target/address"]}] + plug_target_dict = {'size':${plug_size}, 'size_unit':'KiB', 'requested_size':${plug_requested}, 'requested_unit':'KiB', 'block_size':${default_hp_size}} + plug_target_xpath = [{'element_attrs':[".//target/size[@unit='KiB']"],'text':'${plug_size}'}, {'element_attrs':[".//target/requested[@unit='KiB']"],'text':'${plug_requested}'}, {'element_attrs':[".//target/block[@unit='KiB']"],'text':'${default_hp_size}'}, {'element_attrs':[".//target/current[@unit='KiB']"],'text':'${plug_requested}'}, {'element_attrs':[".//target/address"]}] init_mem_device_dict = {'mem_model':'virtio-mem', 'source':${source_dict}, 'target':${init_target_dict}} init_xpath_list = [${source_xpath}, ${init_target_xpath}] plug_mem_device_dict = {'mem_model':'virtio-mem', 'source':${source_dict}, 'target':${plug_target_dict}} diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_dynamic_slots.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_dynamic_slots.cfg index a92a2c93067..47787107024 100644 --- a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_dynamic_slots.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_dynamic_slots.cfg @@ -1,6 +1,5 @@ - memory.devices.virtio_mem.dynamic_slots: type = virtio_mem_dynamic_slots - no s390-virtio start_vm = "no" mem_model = "virtio-mem" allocate_size = "3145728" @@ -13,6 +12,8 @@ numa_attrs = "'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'},{'id':'1','cpus': '2-3','memory':'${numa_mem}','unit':'KiB'}]}" max_attrs = "'max_mem_rt': ${max_mem}, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'" vm_attrs = {${base_attrs}, ${numa_attrs}, ${max_attrs}} + s390-virtio: + vm_attrs = {${base_attrs}, ${max_attrs}} required_kernel = [5.14.0,) guest_required_kernel = [5.8.0,) func_supported_since_libvirt_ver = (10, 0, 0) @@ -25,6 +26,8 @@ target_size = 524288 request_size = 524288 virtio_mem_dict = {'mem_model':'${mem_model}','target': {'size':${target_size}, 'requested_size': ${request_size},'block_size': %s, 'node':0}} + s390-virtio: + virtio_mem_dict = {'mem_model':'${mem_model}','target': {'size':${target_size}, 'requested_size': ${request_size},'block_size': %s}} variants dynamic_memory_slots: - undefined_dynamic_memory_slots: slots_pattern = ["alias memslot-0 @memvirtiomem0", "alias memslot-0 @memvirtiomem1"] @@ -40,7 +43,10 @@ source_type = 'file' source_attr = "'source_type':'${source_type}'" - hugepages_mb: + s390-virtio: + kvm_module_parameters = "hpage=1" hugepages_attr = "'hugepages': {}" - memfd_mb: source_type = 'memfd' source_attr = "'source_type':'${source_type}'" + diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hot_unplug.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hot_unplug.cfg index 9588a04f610..4938070000f 100644 --- a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hot_unplug.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hot_unplug.cfg @@ -1,5 +1,4 @@ - memory.devices.virtio_mem.hot_unplug: - no s390-virtio type = virtio_mem_hot_unplug start_vm = yes mem_model = "virtio-mem" @@ -24,8 +23,13 @@ max_mem = 4194304 max_mem_slots = 16 base = "0x100000000" + with_numa = yes + s390-virtio: + with_numa = no + base = "0x40000000" addr_dict = "'address':{'attrs': {'base': '${base}'}}" - kernel_extra_params_add = "memhp_default_state=online_movable" + kernel_params_add = "memhp_default_state=online_movable" + kernel_params_remove = "memhp_default_state" unplug_event = "device-removed" audit_cmd = "grep VIRT_RESOURCE /var/log/audit/audit.log | grep 'mem' | tail -n 20" ausearch_check = 'old-mem=%d new-mem=%d' @@ -34,6 +38,8 @@ max_dict = '"max_mem_rt": ${max_mem}, "max_mem_rt_slots": ${max_mem_slots}, "max_mem_rt_unit": "KiB"' numa_dict = "'vcpu': 4,'cpu':{'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_mem}'}]}" vm_attrs = {${numa_dict},${max_dict},'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'} + s390-virtio: + vm_attrs = {${max_dict},'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'} required_kernel = [5.14.0,) guest_required_kernel = [5.8.0,) func_supported_since_libvirt_ver = (10, 0, 0) @@ -47,6 +53,7 @@ unplug_request_size = '0' updated_request_option = "--requested-size 0" - source_mib_and_hugepages: + no s390-virtio target_size = "1024" request_size = "512" size_unit = 'MiB' @@ -66,11 +73,18 @@ request_size = "524288" unplug_target_size = "1048576" unplug_request_size = "524288" + s390-virtio: + base = "0x80000000" + addr_dict = "'address':{'attrs': {'base': '${base}'}}" - none_zero_current: - none_zero_request: + no s390-virtio source_dict = {'nodemask': '0','pagesize': %d, 'pagesize_unit':'KiB'} virtio_dict = {'mem_model':'${mem_model}','alias': {'name': '%s'},'target': {${addr_dict},'size':${target_size}, 'size_unit':'${size_unit}', 'node':${node},'requested_size': ${request_size},'requested_unit':'${request_unit}', 'block_size': %s, 'block_unit':'${block_unit}'}} unplug_dict = {'mem_model':'${mem_model}','alias': {'name': '%s'},'target': {${addr_dict},'size':${unplug_target_size},'requested_size': ${unplug_request_size}, 'block_size': %s, 'size_unit':'${unplug_size_unit}','requested_unit':'${unplug_request_unit}','block_unit':'${unplug_block_unit}','node':${unplug_node}}} + s390-virtio: + virtio_dict = {'mem_model':'${mem_model}','alias': {'name': '%s'},'target': {${addr_dict},'size':${target_size}, 'size_unit':'${size_unit}', 'requested_size': ${request_size},'requested_unit':'${request_unit}', 'block_size': %s, 'block_unit':'${block_unit}'}} + unplug_dict = {'mem_model':'${mem_model}','alias': {'name': '%s'},'target': {${addr_dict},'size':${unplug_target_size},'requested_size': ${unplug_request_size}, 'block_size': %s, 'size_unit':'${unplug_size_unit}','requested_unit':'${unplug_request_unit}','block_unit':'${unplug_block_unit}'}} variants plug_way: - detach: detach_method = "detach" @@ -87,3 +101,4 @@ unplug_error = "${zero_size_error_msg}|${basic_error_msg}" none_zero_request: unplug_error = "${zero_request_error_msg}|${basic_error_msg}" + diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hotplug.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hotplug.cfg index c12e23461be..20760cc1933 100644 --- a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hotplug.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_hotplug.cfg @@ -1,5 +1,4 @@ - memory.devices.virtio_mem.hotplug: - no s390-virtio type = virtio_mem_hotplug start_vm = no mem_model = "virtio-mem" @@ -30,6 +29,12 @@ max_dict = '"max_mem_rt": ${max_mem}, "max_mem_rt_slots": ${max_mem_slots}, "max_mem_rt_unit": "KiB"' numa_dict = "'vcpu': 4,'cpu':{'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_mem}'}]}" vm_attrs = {${numa_dict},${max_dict},'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'} + s390-virtio: + base = "0x80000000" + mem_value = 3145728 + current_mem = 3145728 + numa_dict = + vm_attrs = {${max_dict},'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'} required_kernel = [5.14.0,) guest_required_kernel = [5.8.0,) func_supported_since_libvirt_ver = (8, 0, 0) @@ -40,8 +45,11 @@ plug_request_size = '524288' addr_dict = {'attrs': {'base':'${base}'}} plug_base = "0x140000000" + s390-virtio: + plug_base = "0xc0000000" plug_addr_dict = {'attrs': {'base':'${plug_base}'}} - source_mib_and_hugepages: + no s390-virtio target_size = "512" request_size = "512" size_unit = 'MiB' @@ -62,6 +70,8 @@ - duplicate_addr: target_size = '524288' request_size = '524288' + s390-virtio: + base = "0xc0000000" addr_dict = {'attrs': {'base':'${base}'}} plug_error = "address range conflicts|overlaps" plug_target_size = ${target_size} @@ -69,3 +79,7 @@ plug_addr_dict = ${addr_dict} virtio_dict = {'mem_model':'${mem_model}','target': {'size':${target_size}, 'size_unit':'${size_unit}', 'node':${node},'requested_size': ${request_size},'requested_unit':'${request_unit}', 'block_size': %s, 'block_unit':'${block_unit}'}} plug_dict = {'mem_model':'${mem_model}','target': {'size':${plug_target_size},'requested_size': ${plug_request_size}, 'block_size': %s, 'size_unit':'${plug_size_unit}','requested_unit':'${plug_request_unit}','block_unit':'${plug_block_unit}','node':${plug_node}}} + s390-virtio: + virtio_dict = {'mem_model':'${mem_model}','target': {'size':${target_size}, 'size_unit':'${size_unit}','requested_size': ${request_size},'requested_unit':'${request_unit}', 'block_size': %s, 'block_unit':'${block_unit}'}} + plug_dict = {'mem_model':'${mem_model}','target': {'size':${plug_target_size},'requested_size': ${plug_request_size}, 'block_size': %s, 'size_unit':'${plug_size_unit}','requested_unit':'${plug_request_unit}','block_unit':'${plug_block_unit}'}} + diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.cfg index 124f88d0f9a..99f1177d7f3 100644 --- a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.cfg @@ -1,6 +1,5 @@ - memory.devices.virtio_mem.memory_allocation_and_numa: type = virtio_mem_with_memory_allocation_and_numa - no s390-virtio start_vm = no mem_model = "virtio-mem" mem_value = 8388608 @@ -29,11 +28,13 @@ - without_numa: numa_attrs = "" - with_numa: + no s390-virtio numa_mem = 8388608 numa_attrs = "'vcpu': 4, 'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-3', 'memory': '${numa_mem}', 'unit': 'KiB'}]}," vm_attrs = {${base_attrs} ${max_attrs} ${numa_attrs}} variants: - virtio_mem_with_node: + no s390-virtio node = 0 virtio_mem_dict = {'mem_model': '${mem_model}', 'target': {'requested_unit': '${request_size_unit}', 'size': ${target_size}, 'node': ${node}, 'size_unit': '${target_size_unit}', 'requested_size': ${request_size}, 'block_unit': 'KiB', 'block_size': %s}} no_maxmemory: @@ -52,22 +53,32 @@ define_error = "${err_msg2}" hot_plug_error = "${err_msg1}" with_maxmemory: - hot_plug_error = "${err_msg2}" - cold_plug_error = "${err_msg2}" + x86_64, aarch64: + hot_plug_error = "${err_msg2}" + cold_plug_error = "${err_msg2}" + s390-virtio: + coldplug_start_error = no_maxmemory: cold_plug_error = "${err_msg1}" without_numa,with_numa: hot_plug_error = "${err_msg1}" - virtio_mem_with_exceed_size: only without_numa.with_maxmemory - target_size = "10485760" + target_size = "524288" + s390-virtio: + target_size = "15728640" request_size = "512" target_size_unit = "KiB" virtio_mem_dict = {'mem_model': '${mem_model}', 'target': {'requested_unit': '${request_size_unit}', 'size': ${target_size}, 'size_unit': '${target_size_unit}', 'requested_size': ${request_size}, 'block_unit': 'KiB', 'block_size': %s}} coldplug_start_error = "${err_msg2}" with_maxmemory: - hot_plug_error = "${err_msg2}" - cold_plug_error = "${err_msg2}" + x86_64, aarch64: + hot_plug_error = "${err_msg2}" + cold_plug_error = "${err_msg2}" + s390-virtio: + coldplug_start_error = + cold_plug_error = "would exceed domain's maxMemory config size" + hot_plug_error = "${cold_plug_error}" without_numa: with_maxmemory: define_error = "Total size of memory devices exceeds the total memory size" @@ -79,3 +90,4 @@ - hot_plug: operation = "attach" plug_option = " " + diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_backing_type.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_backing_type.cfg index 5c4c44ee160..edbcc7a8395 100644 --- a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_backing_type.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_backing_type.cfg @@ -1,6 +1,5 @@ - memory.devices.virtio_mem.memory_backing_type: type = virtio_mem_with_memory_backing_type - no s390-virtio start_vm = no mem_model = "virtio-mem" virtio_mem_num = 2 @@ -11,16 +10,22 @@ max_mem = 4194304 numa_mem = 1048576 aarch_max_mem = 20971520 + virtio_config = [(None, 0), ("huge_page", 1)] base_attrs = "'vcpu': 4, 'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'" numa_attrs = "'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'}, {'id': '1', 'cpus': '2-3', 'memory': '${numa_mem}', 'unit': 'KiB'}]}" max_attrs = "'max_mem_rt': %s, 'max_mem_rt_slots': 16, 'max_mem_rt_unit': 'KiB'" vm_attrs = {${base_attrs}, ${numa_attrs}, ${max_attrs}} + s390-virtio: + virtio_config = [(None,), (None,)] + vm_attrs = {${base_attrs}, ${max_attrs}} target_size = 524288 request_size = 524288 type0 = "memory-backend-ram" type1 = "memory-backend-file" path0 = "" path1 = "/dev/hugepages/libvirt/qemu/" + prealloc0 = "True" + prealloc1 = "True" required_kernel = [5.14.0,) guest_required_kernel = [5.8.0,) func_supported_since_libvirt_ver = (8, 0, 0) @@ -43,10 +48,18 @@ - undefined: variants allocation_mode: - alloc_ondemand: + prealloc0 = "False" + s390-virtio: + prealloc1 = "False" mode = "ondemand" alloc_attr = "'allocation':{'mode':'${mode}'}" file: path0 = "/var/lib/libvirt/qemu/ram/" + s390-virtio: + path1 = "/var/lib/libvirt/qemu/ram/" + anonymous, undefined: + s390-virtio: + type1 = "memory-backend-ram" - alloc_immediate_with_threads: func_supported_since_libvirt_ver = (8, 2, 0) mode = "immediate" @@ -54,7 +67,14 @@ alloc_attr = "'allocation':{'mode':'${mode}', 'threads':${threads}}" file: path0 = "/var/lib/libvirt/qemu/ram/" + s390-virtio: + path1 = "/var/lib/libvirt/qemu/ram/" + anonymous, undefined: + s390-virtio: + type1 = "memory-backend-ram" - set_hugepage: + s390-virtio: + kvm_module_parameters = "hpage=1" hugepages_attr = "'hugepages': {}" undefined: type0 = "memory-backend-file" @@ -65,9 +85,12 @@ path0 = "/dev/hugepages/libvirt/qemu/" check_backing_type = '{"execute":"qom-get", "arguments":{"path":"/objects/%s", "property":"type"}}' check_mem_path = '{"execute":"qom-get", "arguments":{"path":"/objects/%s", "property":"mem-path"}}' + check_prealloc_config = '{"execute":"qom-get", "arguments":{"path":"/machine/peripheral/%s", "property":"prealloc"}}' + expected_prealloc_config = ['${prealloc0}', '${prealloc1}'] expected_allocated = ['false', 'false'] expected_backing_type = ['${type0}', '${type1}'] expected_mem_path = ['${path0}', '${path1}'] variants attach_type: - hot_plug: - cold_plug: + diff --git a/libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py b/libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py index 56bdd209554..feeeda85c77 100644 --- a/libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py +++ b/libvirt/tests/src/memory/memory_devices/change_virtio_mem_request_size.py @@ -12,6 +12,7 @@ from avocado.utils import memory from virttest import utils_misc +from virttest import utils_test from virttest import virsh from virttest.libvirt_xml import vm_xml @@ -189,6 +190,7 @@ def check_guest_xml(test, vm_name, params): target_size = int(params.get("target_size")) mem_value = int(params.get("mem_value")) current_mem = int(params.get("current_mem")) + with_numa = params.get("with_numa", "yes") == "yes" basic_request = int(re.findall(r'\d+', params.get("basic_request"))[0]) update_request_size = int(memory_base.convert_data_size( params.get("update_request_size"), 'KiB')) @@ -199,8 +201,13 @@ def check_guest_xml(test, vm_name, params): virtio_mem_value = current_0 = current_1 = update_request_size elif params.get('bigger_or_not_muti_request'): virtio_mem_value = current_0 = current_1 = basic_request - xpath = expect_xpath % (mem_value + target_size * 2, - current_mem + current_0 + current_1) + + expect_memory = mem_value + target_size * 2 \ + if with_numa else mem_value + target_size + expect_current = current_mem + current_0 + current_1 \ + if with_numa else current_mem - target_size + current_0 + current_1 + xpath = expect_xpath % (expect_memory, + expect_current) test.log.debug("Checking xml pathern is :%s", xpath) vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) @@ -273,6 +280,10 @@ def setup_test(): default_pagesize = memory.get_huge_page_size() params.update({'default_pagesize': default_pagesize}) utils_memory.set_num_huge_pages(int(allocate_huge_pages)/default_pagesize) + if kernel_params_add: + test.log.info("TEST_SETUP: Add kernel parmater") + utils_test.update_boot_option( + vm, args_added=kernel_params_add, guest_arch_name=vm_arch_name) def run_test_shutoff_guest(): """ @@ -344,6 +355,11 @@ def teardown_test(): test.log.info("TEST_TEARDOWN: Clean up env.") utils_memory.set_num_huge_pages(0) bkxml.sync() + if kernel_params_remove: + if not vm.is_alive(): + vm.start() + utils_test.update_boot_option( + vm, args_removed=kernel_params_remove, guest_arch_name=vm_arch_name) vm_name = params.get("main_vm") vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) @@ -351,6 +367,7 @@ def teardown_test(): vm = env.get_vm(vm_name) allocate_huge_pages = re.findall(r'\d+', params.get("allocate_huge_pages"))[0] + vm_arch_name = params.get("vm_arch_name") guest_state = params.get("guest_state") basic_node = params.get("basic_node") target_size = int(params.get("target_size")) @@ -362,6 +379,8 @@ def teardown_test(): update_request_size = params.get("update_request_size") requested_unit = params.get("requested_unit") requested_setting = params.get("requested_setting") + kernel_params_add = params.get("kernel_params_add") + kernel_params_remove = params.get("kernel_params_remove") params.update( {'normal_or_zero_request': requested_setting in [ "normal_requested", "zero_requested"]}) diff --git a/libvirt/tests/src/memory/memory_devices/invalid_virtio_mem_config.py b/libvirt/tests/src/memory/memory_devices/invalid_virtio_mem_config.py index 3367ae476e6..53b3ff076a4 100644 --- a/libvirt/tests/src/memory/memory_devices/invalid_virtio_mem_config.py +++ b/libvirt/tests/src/memory/memory_devices/invalid_virtio_mem_config.py @@ -92,9 +92,10 @@ def setup_test(): """ Check host has at least 2 numa nodes. """ - test.log.info("TEST_SETUP: Check the numa nodes") - numa_obj = numa_base.NumaTest(vm, params, test) - numa_obj.check_numa_nodes_availability() + if with_numa: + test.log.info("TEST_SETUP: Check the numa nodes") + numa_obj = numa_base.NumaTest(vm, params, test) + numa_obj.check_numa_nodes_availability() def run_test(): """ @@ -129,6 +130,7 @@ def teardown_test(): bkxml.sync() vm_name = params.get("main_vm") + with_numa = params.get("with_numa", "yes") == "yes" vm = env.get_vm(vm_name) original_vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) bkxml = original_vmxml.copy() diff --git a/libvirt/tests/src/memory/memory_devices/virtio_mem_access_and_discard.py b/libvirt/tests/src/memory/memory_devices/virtio_mem_access_and_discard.py index c5547708d13..7980c11fe59 100644 --- a/libvirt/tests/src/memory/memory_devices/virtio_mem_access_and_discard.py +++ b/libvirt/tests/src/memory/memory_devices/virtio_mem_access_and_discard.py @@ -48,25 +48,24 @@ def get_vm_attrs(test, params): def get_virtio_mem(test, params): """ - Get 6 basic different virtio-mem memory devices. + Get basic different virtio-mem memory devices. :param test: test object. :param params: dictionary with the test parameters. :return mem_list: virtio-mem attr dict list. """ + mem_conf_list = eval(params.get("mem_conf_list")) + conf_map = {0: 'mem_access', 1: 'mem_discard', 2: 'node'} mem_list = [] - for item in [(None, None, 0), ('shared', 'yes', 0), - (None, None, 1), ('private', 'no', 1), - (None, None, 2), ('shared', 'yes', 2)]: - + for item in mem_conf_list: single_mem = eval(params.get("mem_basic")) target = single_mem['target'] - target.update({'node': item[2]}) - - if item[0] is not None: - single_mem.update({'mem_access': item[0]}) - if item[1] is not None: - single_mem.update({'mem_discard': item[1]}) + for k, v in conf_map.items(): + if item[k] is not None: + if v == "node": + target.update({v: item[k]}) + else: + single_mem.update({v: item[k]}) mem_list.append(single_mem) test.log.debug("Get all virtio-mem list:'%s'", mem_list) @@ -84,7 +83,7 @@ def check_access_and_discard(test, params, vm, :param expected_share: expected access shared value list. :param expected_discard: expected discard value list. """ - virtio_mem_num = int(params.get("virtio_mem_num")) + virtio_mem_num = len(eval(params.get("mem_conf_list"))) check_discard = params.get("check_discard") discard_error_msg = params.get("discard_error_msg") mem_name_list = [] @@ -184,11 +183,12 @@ def teardown_test(): Clean data. """ test.log.info("TEST_TEARDOWN: Clean up env.") - bkxml.sync() + orig_vmxml.sync() vm_name = params.get("main_vm") vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) bkxml = vmxml.copy() + orig_vmxml = vmxml.copy() vm = env.get_vm(vm_name) expected_share = eval(params.get("expected_share")) diff --git a/libvirt/tests/src/memory/memory_devices/virtio_mem_hot_unplug.py b/libvirt/tests/src/memory/memory_devices/virtio_mem_hot_unplug.py index c20cec221fc..5cdab1c14bb 100644 --- a/libvirt/tests/src/memory/memory_devices/virtio_mem_hot_unplug.py +++ b/libvirt/tests/src/memory/memory_devices/virtio_mem_hot_unplug.py @@ -15,6 +15,7 @@ from virttest import virsh from virttest import utils_misc from virttest import utils_sys +from virttest import utils_test from virttest import test_setup from virttest.libvirt_xml import vm_xml from virttest.staging import utils_memory @@ -137,6 +138,7 @@ def check_guest_xml(test, params, hot_unplugged=False): vm_name = params.get("main_vm") mem_value = int(params.get("mem_value")) current_mem = int(params.get("current_mem")) + with_numa = params.get('with_numa', 'yes') == 'yes' target_size, request_size, unplug_target_size, unplug_request_size = \ adjust_virtio_size(params, test) @@ -152,8 +154,12 @@ def check_guest_xml(test, params, hot_unplugged=False): acutal_virtio_block = virtio_mem_xml[0].target.block_size acutal_virtio_requested = virtio_mem_xml[0].target.requested_size acutal_virtio_current = virtio_mem_xml[0].target.current_size - params.update({"expected_mem0": mem_value + target_size}) - params.update({"expected_curr0": current_mem + acutal_virtio_current}) + if with_numa: + params.update({"expected_mem0": mem_value + target_size}) + params.update({"expected_curr0": current_mem + acutal_virtio_current}) + else: + params.update({"expected_mem0": mem_value}) + params.update({"expected_curr0": current_mem - target_size + acutal_virtio_current}) params.update({"curr1": acutal_virtio_current}) check_source_and_addr_xml(test, params, virtio_mem_xml[0]) @@ -256,13 +262,16 @@ def run(test, params, env): """ def setup_test(): """ - Allocate memory on the host. + Allocate memory on the host, add kernel parameter to guest. """ if case == "source_mib_and_hugepages": if not libvirt_vmxml.check_guest_machine_type(vmxml, machine_version): test.fail("Guest config machine should be >= rhel{}".format( machine_version)) hpc.setup() + if kernel_params_add: + utils_test.update_boot_option( + vm, args_added=kernel_params_add, guest_arch_name=vm_arch_name) def run_test(): """ @@ -312,6 +321,11 @@ def teardown_test(): test.log.info("TEST_TEARDOWN: Clean up env.") bkxml.sync() hpc.cleanup() + if kernel_params_remove: + if not vm.is_alive(): + vm.start() + utils_test.update_boot_option( + vm, args_removed=kernel_params_remove, guest_arch_name=vm_arch_name) vm_name = params.get("main_vm") vm = env.get_vm(vm_name) @@ -329,6 +343,9 @@ def teardown_test(): detach_method = params.get("detach_method") unplug_error = params.get("unplug_error") unplug_event = params.get('unplug_event') + kernel_params_add = params.get('kernel_params_add') + kernel_params_remove = params.get('kernel_params_remove') + vm_arch_name = params.get('vm_arch_name') params.update({"kernel_hp_file": kernel_hp_file % default_hugepage_size}) params.update({"target_hugepages": allocate_size / default_hugepage_size}) diff --git a/libvirt/tests/src/memory/memory_devices/virtio_mem_hotplug.py b/libvirt/tests/src/memory/memory_devices/virtio_mem_hotplug.py index 77891771d81..57522f9e2e3 100644 --- a/libvirt/tests/src/memory/memory_devices/virtio_mem_hotplug.py +++ b/libvirt/tests/src/memory/memory_devices/virtio_mem_hotplug.py @@ -166,6 +166,7 @@ def check_guest_xml(test, params, mem_index=0): vm_name = params.get("main_vm") mem_value = int(params.get("mem_value")) current_mem = int(params.get("current_mem")) + numa_dict = params.get("numa_dict") target_size, request_size, plug_target_size, plug_request_size = \ adjust_virtio_size(params) @@ -182,9 +183,12 @@ def check_guest_xml(test, params, mem_index=0): check_source_and_addr_xml(test, params, virtio_mem_xml, mem_index) if mem_index == 0: + expected_mem0 = mem_value + target_size if numa_dict else mem_value + expected_curr0 = current_mem + acutal_virtio_current if numa_dict else current_mem - \ + target_size + acutal_virtio_current params.update({"first_virtio_curr": acutal_virtio_current}) - params.update({"expected_mem0": mem_value + target_size}) - params.update({"expected_curr0": current_mem + acutal_virtio_current}) + params.update({"expected_mem0": expected_mem0}) + params.update({"expected_curr0": expected_curr0}) compare_two_values( test, params.get("expected_mem0"), acutal_mem, 'memory') @@ -213,9 +217,13 @@ def check_guest_xml(test, params, mem_index=0): check_delayed_current(test, params, mem_index, plug_request_size) curr1, curr2 = params.get("first_virtio_curr"), params.get("second_virtio_curr") + expected_mem1 = mem_value + target_size + \ + plug_target_size if numa_dict else mem_value + plug_target_size + expected_curr1 = current_mem + curr1 + \ + curr2 if numa_dict else current_mem - target_size + curr1 + curr2 params.update( - {"expected_mem1": mem_value + target_size + plug_target_size}) - params.update({"expected_curr1": current_mem + curr1 + curr2}) + {"expected_mem1": expected_mem1}) + params.update({"expected_curr1": expected_curr1}) compare_two_values( test, params.get("expected_mem1"), acutal_mem, 'memory') compare_two_values( @@ -259,12 +267,16 @@ def check_after_attach(vm, test, params): mem_value = int(params.get("mem_value")) expected_log = params.get("expected_log") audit_cmd = params.get("audit_cmd") + numa_dict = params.get("numa_dict") target_size, request_size, plug_target_size, plug_request_size = \ adjust_virtio_size(params) + ori_mem = mem_value + target_size if numa_dict else mem_value + pluged_mem = mem_value + target_size + \ + plug_target_size if numa_dict else mem_value + plug_target_size libvirtd_log_file = os.path.join(test.debugdir, "libvirtd.log") ausearch_check = params.get("ausearch_check") % ( - mem_value + target_size, mem_value + target_size + plug_target_size) + ori_mem, pluged_mem) # Check the audit log by ausearch. ausearch_result = process.run(audit_cmd, shell=True) diff --git a/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.py b/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.py index 961c3f8dfbd..7c379155970 100644 --- a/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.py +++ b/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_allocation_and_numa.py @@ -59,7 +59,8 @@ def check_guest_xml(vm, params, test): virtio_mem = vmxml.get_devices("memory")[0] target = virtio_mem.target target_size = int(target.get_size()) - target_node = target.get_node() + if params.get("node"): + target_node = target.get_node() target_block = target.get_block_size() target_request = target.get_requested_size() target_current = int(target.get_current_size()) diff --git a/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_backing_type.py b/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_backing_type.py index 589e0ec0ad8..9d35a6ced70 100644 --- a/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_backing_type.py +++ b/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_backing_type.py @@ -61,15 +61,18 @@ def get_virtio_objs(test, params): :return mem_objs: virtio memory device object list. """ default_pagesize = params.get('default_pagesize') + virtio_config = eval(params.get("virtio_config")) mem_objs = [] - for item in [(None, 0), (default_pagesize, 1)]: + for item in virtio_config: single_mem = {'mem_model': 'virtio-mem'} - if item[0] is not None: - single_mem.update({'source': {'pagesize': item[0]}}) + if item[0] == "huge_page": + single_mem.update({'source': {'pagesize': default_pagesize}}) single_mem.update( - {'target': {'node': item[1], 'size': int(params.get('target_size')), + {'target': {'size': int(params.get('target_size')), 'requested_size': int(params.get('request_size')), 'block_size': int(default_pagesize)}}) + if len(item) == 2: + single_mem['target'].update({'node': item[1]}) test.log.debug("Get the virtio-mem dict: %s", single_mem) mem_obj = libvirt_vmxml.create_vm_device_by_type('memory', single_mem) mem_objs.append(mem_obj) @@ -113,10 +116,12 @@ def check_mb_setting(test, params): :param params: dictionary with the test parameters. """ virtio_mem_num = int(params.get("virtio_mem_num")) - expected_allocated = eval(params.get("expected_allocated", "{}")) - expected_backing_type = eval(params.get("expected_backing_type", "{}")) - expected_mem_path = eval(params.get("expected_mem_path", "{}")) + expected_prealloc_config = eval(params.get("expected_prealloc_config", "[]")) + expected_allocated = eval(params.get("expected_allocated", "[]")) + expected_backing_type = eval(params.get("expected_backing_type", "[]")) + expected_mem_path = eval(params.get("expected_mem_path", "[]")) memory_backing = params.get("memory_backing") + check_prealloc_config = params.get("check_prealloc_config") check_backing_type = params.get("check_backing_type") check_mem_path = params.get("check_mem_path") allocation_mode = params.get("allocation_mode") @@ -126,10 +131,12 @@ def check_mb_setting(test, params): memory_backing == "undefined" and allocation_mode == "set_hugepage" mem_name_list = [] + alias_name_list = [] # Check virtio memory pre-allocated value ret = virsh.qemu_monitor_command(vm_name, "info memdev", "--hmp", debug=True).stdout_text.replace("\r\n", "") for index in range(virtio_mem_num): + alias_name = "virtiomem%d" % index mem_name = "memvirtiomem%d" % index pattern = "memory backend: %s.*prealloc: %s " % ( mem_name, expected_allocated[index]) @@ -139,6 +146,12 @@ def check_mb_setting(test, params): else: test.log.debug("Check access pre-allocated value is '%s': PASS", pattern) mem_name_list.append(mem_name) + alias_name_list.append(alias_name) + + # Check virtio memory device prealloc. + check_qemu_monitor_json(test, params, alias_name_list, + 'memory device prealloc config', check_prealloc_config, + expected_prealloc_config) # Check virtio memory backing type. check_qemu_monitor_json(test, params, mem_name_list, From 646723728d247dfe2d2b55a714682bed709231bf Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Sun, 27 Apr 2025 03:00:23 -0400 Subject: [PATCH 0979/1055] Add cpu case of cpuset limited by cgroup - RHEL-179878 - [vcpupin] Start VM with vcpupin config when machine cpuset is limited in cgroup Signed-off-by: Haijiao Zhao --- libvirt/tests/cfg/cpu/vcpupin.cfg | 6 +++ libvirt/tests/src/cpu/vcpupin.py | 64 ++++++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/cpu/vcpupin.cfg b/libvirt/tests/cfg/cpu/vcpupin.cfg index f351f25c240..0901b0476ea 100644 --- a/libvirt/tests/cfg/cpu/vcpupin.cfg +++ b/libvirt/tests/cfg/cpu/vcpupin.cfg @@ -3,6 +3,7 @@ vcpu_placement = 'static' vcpu_max = 4 vcpu_current = 2 + update_xml = yes variants: - positive: variants test_case: @@ -16,3 +17,8 @@ - vcpupin_current_inactive_vm: vcpupin_conf = "{'0': 'x,y', '1': 'x-y,^z', '2': 'x-y,^z,m', '3': 'r'}" affinity_pattern = 'CPU Affinity:\s*(.*) .*out of' + - cpuset_limilted_in_cgroup: + update_xml = no + vcpu_max = 2 + vcpupin_conf = {'0': '2', '1': '4'} + vm_attrs = {'cputune': {'vcpupins': [{'vcpu': '0', 'cpuset': '2'}, {'vcpu': '1', 'cpuset': '4'}]}} diff --git a/libvirt/tests/src/cpu/vcpupin.py b/libvirt/tests/src/cpu/vcpupin.py index 642c1e3751e..ef6d2aaecad 100644 --- a/libvirt/tests/src/cpu/vcpupin.py +++ b/libvirt/tests/src/cpu/vcpupin.py @@ -3,6 +3,7 @@ import re from avocado.utils import cpu as cpuutils +from avocado.utils import process from virttest import data_dir from virttest import utils_misc @@ -365,6 +366,65 @@ def test_vcpupin_current_inactive_vm(test, vm, cpu_max_id, params): check_vcpuinfo_affinity(test, affinity, vcpupin_new_values) +def test_cpuset_limilted_in_cgroup(test, vm, cpu_max_id, params): + """ + Test Start VM with vcpupin config when machine cpuset is limited in cgroup + + :param test: test object + :param vm: vm object + :param cpu_max_id: maximum id of host cpu id + :param params: test parameters + """ + vm_attrs = eval(params.get('vm_attrs', '{}')) + rand_id = utils_misc.generate_random_string(3) + tmp_vm_name = 'test-vcpupin-' + rand_id + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) + + config_path = '/sys/fs/cgroup/machine.slice/cpuset.cpus' + + bk_cpu_set = process.run( + f'cat {config_path}', shell=True, ignore_status=True).stdout_text + try: + process.run(f'echo "0,2,4,6,8" > {config_path}', shell=True) + process.run(f'cat {config_path}', shell=True) + + vm.destroy() + + # Create a new vm with vcpupin config + tmp_vmxml = vmxml.copy() + tmp_vmxml.setup_attrs(**vm_attrs) + tmp_vmxml.vm_name = tmp_vm_name + tmp_vmxml.del_uuid() + osxml = tmp_vmxml.os + os_attrs = osxml.fetch_attrs() + for k, v in list(os_attrs.items()): + if k.startswith('nvram'): + os_attrs.pop(k) + new_os = vm_xml.VMOSXML() + new_os.setup_attrs(**os_attrs) + tmp_vmxml.os = new_os + + tmp_vmxml.xmltreefile.write() + logging.debug(tmp_vmxml) + + virsh.create(tmp_vmxml.xml, debug=True, ignore_status=False) + logging.debug(virsh.dumpxml(tmp_vm_name).stdout_text) + + out = virsh.vcpupin(tmp_vm_name, debug=True, + ignore_status=False).stdout_text + out_dict = libvirt_misc.convert_to_dict(out) + vcpupin_conf = eval(params.get('vcpupin_conf')) + if out_dict != vcpupin_conf: + test.fail( + f'vcpupin output is not expected, should be {vcpupin_conf}') + + finally: + virsh.destroy(tmp_vm_name, debug=True) + if not vm.is_alive(): + vm.start() + process.run(f'echo {bk_cpu_set} > {config_path}', shell=True) + + def run(test, params, env): """ Run some tests for vcpupin with --live, --config @@ -373,6 +433,7 @@ def run(test, params, env): run_test = eval("test_%s" % test_case) vm_name = params.get("main_vm", "avocado-vt-vm1") vm = env.get_vm(vm_name) + update_xml = 'yes' == params.get("update_xml", "no") # Backup for recovery. vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) @@ -381,7 +442,8 @@ def run(test, params, env): try: if vm.is_alive(): vm.destroy() - update_vm_xml(vmxml, params) + if update_xml: + update_vm_xml(vmxml, params) vm.start() logging.debug(vm_xml.VMXML.new_from_dumpxml(vm_name)) # Get the host cpu max id From 5f3fb67198414068e8a1da8005573c43bb095107 Mon Sep 17 00:00:00 2001 From: Lili Zhu Date: Wed, 28 May 2025 23:04:07 -0400 Subject: [PATCH 0980/1055] Remove systemd-run when run virtiofsd process For now, we do not need to use systemd-run to run virtiofsd process any more, then there is no need to change the selinux context of /usr/libexec/virtiofsd Signed-off-by: Lili Zhu --- libvirt/tests/src/virtiofs/virtiofs.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/src/virtiofs/virtiofs.py b/libvirt/tests/src/virtiofs/virtiofs.py index f7240f59aad..78a7b3e3859 100644 --- a/libvirt/tests/src/virtiofs/virtiofs.py +++ b/libvirt/tests/src/virtiofs/virtiofs.py @@ -145,10 +145,9 @@ def launch_externally_virtiofs(source_dir, source_socket): :param source_dir: the dir shared on host :param source_socket: the socket file listened on """ - process.run('chcon -t virtd_exec_t %s' % path, ignore_status=False, shell=True) - cmd = "systemd-run %s --socket-path=%s -o source=%s" % (path, source_socket, source_dir) + cmd = "%s --socket-path=%s -o source=%s &" % (path, source_socket, source_dir) try: - process.run(cmd, ignore_status=False, shell=True) + process.run(cmd, ignore_status=False, shell=True, ignore_bg_processes=True) # Make sure the socket is created utils_misc.wait_for(lambda: os.path.isdir(source_socket), timeout=3) process.run("chown qemu:qemu %s" % source_socket, ignore_status=False) From 7bea15f49f2538bb934fffa9cc0a7df84f5461be Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Thu, 29 May 2025 12:54:29 +0800 Subject: [PATCH 0981/1055] nbdkit: fix the value which is supported after 1.40 Signed-off-by: vwu-vera --- v2v/tests/src/nbdkit/nbdkit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2v/tests/src/nbdkit/nbdkit.py b/v2v/tests/src/nbdkit/nbdkit.py index e92df31989b..af16c6dee27 100644 --- a/v2v/tests/src/nbdkit/nbdkit.py +++ b/v2v/tests/src/nbdkit/nbdkit.py @@ -459,7 +459,7 @@ def delay_close_delay_open_options(): if not re.search('0m0', cmd_pass.stderr_text): test.fail('fail to test delay-close option when nbdkit clients are not shutdown') #Set invalid number for delay option - values = ['10secs', '40SECS', '10s', '10MS', '1:'] + values = ['10secs', '40SECS', '10MS', '1:'] for value in values: cmd_num = process.run("nbdkit null --filter=delay delay-open=%s --run 'nbdinfo $uri'" % value, shell=True, ignore_status=True) From 6b876a1c5f8f8c07a516cea791b818ebbc3ab246 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Sun, 25 May 2025 17:57:36 +0800 Subject: [PATCH 0982/1055] passt: support multiple nexthops In some environment, there are more than one gateway in nexthops in ip route output, for example on ARM host. This patch is to support this situation instead of only selecting the first default route which is not accurate. For example: "nexthops":[{"gateway":"fe80::4a5a:d00:6631:2920","dev":"eno1","weight":1,"flags":[]}, {"gateway":"fe80::4a5a:d00:6631:b20","dev":"eno1","weight":1,"flags":[]} ] Signed-off-by: Dan Zheng --- .../passt/passt_attach_detach.cfg | 1 + .../virtual_network/passt/passt_function.cfg | 1 + .../virtual_network/passt/passt_lifecycle.cfg | 1 + .../virtual_network/passt/passt_reconnect.cfg | 1 + .../passt/passt_transfer_file.cfg | 1 + .../passt/passt_attach_detach.py | 3 ++- .../virtual_network/passt/passt_function.py | 3 ++- .../virtual_network/passt/passt_lifecycle.py | 3 ++- .../virtual_network/passt/passt_reconnect.py | 3 ++- .../passt/passt_transfer_file.py | 3 ++- provider/virtual_network/passt.py | 23 ++++++++++++------- 11 files changed, 30 insertions(+), 13 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg index 278518d87b9..e417e2ac97b 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg @@ -5,6 +5,7 @@ outside_ip = 'www.redhat.com' start_vm = no mtu = 65520 + multiple_nexthops = no variants user_type: - root_user: test_user = root diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg index 48f893f6bd1..9d7087e04a2 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg @@ -5,6 +5,7 @@ outside_ip = 'www.redhat.com' start_vm = no mtu = 65520 + multiple_nexthops = no variants user_type: - root_user: test_user = root diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_lifecycle.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_lifecycle.cfg index eee50205c2e..64ed3b6c5d4 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_lifecycle.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_lifecycle.cfg @@ -5,6 +5,7 @@ outside_ip = 'www.redhat.com' start_vm = no mtu = 65520 + multiple_nexthops = no variants operation: - save_restore: operation_a = save diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg index ab0ec68b591..f1b42407108 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg @@ -5,6 +5,7 @@ outside_ip = 'www.redhat.com' start_vm = no mtu = 65520 + multiple_nexthops = no variants user_type: - root_user: test_user = root diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg index 76b45bf0b1b..57f8a9e969e 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg @@ -4,6 +4,7 @@ host_iface = outside_ip = 'www.redhat.com' start_vm = no + multiple_nexthops = no variants user_type: - root_user: test_user = root diff --git a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py index eaa701d601b..5951674a21a 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py +++ b/libvirt/tests/src/virtual_network/passt/passt_attach_detach.py @@ -81,6 +81,7 @@ def run(test, params, env): iface_attrs['backend']['logFile'] = log_file iface_attrs['source']['dev'] = host_iface vhostuser = 'yes' == params.get('vhostuser', 'no') + multiple_nexthops = 'yes' == params.get('multiple_nexthops', 'no') vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name, virsh_instance=virsh_ins) @@ -138,7 +139,7 @@ def run(test, params, env): vm_iface = utils_net.get_linux_ifname(session, mac) passt.check_vm_ip(iface_attrs, session, host_iface, vm_iface) passt.check_vm_mtu(session, vm_iface, mtu) - passt.check_default_gw(session, host_iface) + passt.check_default_gw(session, host_iface, multiple_nexthops) passt.check_nameserver(session) ips = { diff --git a/libvirt/tests/src/virtual_network/passt/passt_function.py b/libvirt/tests/src/virtual_network/passt/passt_function.py index ed0c4738177..dcbdc9d7a7c 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_function.py +++ b/libvirt/tests/src/virtual_network/passt/passt_function.py @@ -67,6 +67,7 @@ def run(test, params, env): iface_attrs = eval(params.get('iface_attrs')) iface_attrs['backend']['logFile'] = log_file vhostuser = 'yes' == params.get('vhostuser', 'no') + multiple_nexthops = 'yes' == params.get('multiple_nexthops', 'no') vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name, virsh_instance=virsh_ins) @@ -109,7 +110,7 @@ def run(test, params, env): vm_iface = utils_net.get_linux_ifname(session, mac) passt.check_vm_ip(iface_attrs, session, host_iface, vm_iface) passt.check_vm_mtu(session, vm_iface, mtu) - passt.check_default_gw(session, host_iface) + passt.check_default_gw(session, host_iface, multiple_nexthops) passt.check_nameserver(session) ips = { diff --git a/libvirt/tests/src/virtual_network/passt/passt_lifecycle.py b/libvirt/tests/src/virtual_network/passt/passt_lifecycle.py index 3ee24128e13..2fe27c7e566 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_lifecycle.py +++ b/libvirt/tests/src/virtual_network/passt/passt_lifecycle.py @@ -77,6 +77,7 @@ def run(test, params, env): options_b = eval(params.get('options_b', '{}')) passt_running = 'yes' == params.get('passt_running', 'no') vhostuser = 'yes' == params.get('vhostuser', 'no') + multiple_nexthops = 'yes' == params.get('multiple_nexthops', 'no') vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name, virsh_instance=virsh_ins) @@ -134,7 +135,7 @@ def run(test, params, env): vm_iface = utils_net.get_linux_ifname(session, mac) passt.check_vm_ip(iface_attrs, session, host_iface, vm_iface) passt.check_vm_mtu(session, vm_iface, mtu) - passt.check_default_gw(session, host_iface) + passt.check_default_gw(session, host_iface, multiple_nexthops) passt.check_nameserver(session) ips = { diff --git a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py index 40b57801dbb..70ea112efa1 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_reconnect.py +++ b/libvirt/tests/src/virtual_network/passt/passt_reconnect.py @@ -69,6 +69,7 @@ def run(test, params, env): iface_attrs['backend']['logFile'] = log_file iface_attrs['source']['dev'] = host_iface vhostuser = 'yes' == params.get('vhostuser', 'no') + multiple_nexthops = 'yes' == params.get('multiple_nexthops', 'no') vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name, virsh_instance=virsh_ins) @@ -117,7 +118,7 @@ def run(test, params, env): vm_iface = utils_net.get_linux_ifname(session, mac) passt.check_vm_ip(iface_attrs, session, host_iface, vm_iface) passt.check_vm_mtu(session, vm_iface, mtu) - passt.check_default_gw(session, host_iface) + passt.check_default_gw(session, host_iface, multiple_nexthops) passt.check_nameserver(session) ips = { diff --git a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py index bb0c7751b4d..f8ecb83ad7d 100644 --- a/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py +++ b/libvirt/tests/src/virtual_network/passt/passt_transfer_file.py @@ -159,6 +159,7 @@ def run(test, params, env): iface_attrs['backend']['logFile'] = log_file iface_attrs['source']['dev'] = host_iface direction = params.get('direction') + multiple_nexthops = 'yes' == params.get('multiple_nexthops', 'no') vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name, virsh_instance=virsh_ins) @@ -177,7 +178,7 @@ def run(test, params, env): LOG.debug(virsh_ins.dumpxml(vm_name).stdout_text) session = vm.wait_for_serial_login(timeout=60) - passt.check_default_gw(session, host_iface) + passt.check_default_gw(session, host_iface, multiple_nexthops) prot = 'TCP' if ip_ver == 'ipv4' else 'TCP6' if direction == 'host_to_vm': diff --git a/provider/virtual_network/passt.py b/provider/virtual_network/passt.py index 4e897506b8b..095745c8079 100644 --- a/provider/virtual_network/passt.py +++ b/provider/virtual_network/passt.py @@ -240,7 +240,7 @@ def check_vm_mtu(session, iface, mtu): raise exceptions.TestFail(f'Wrong vm mtu: {vm_mtu}, should be {mtu}') -def check_default_gw(session, host_iface=None): +def check_default_gw(session, host_iface=None, multiple_nexthops=False): """ Check whether default host gateways of host and guest are consistent, i.e. the guest's gateways are available on the host. @@ -249,28 +249,35 @@ def check_default_gw(session, host_iface=None): :param host_iface: if given, only check gateway information on this host interface """ + LOG.debug(f'Get host default ipv4 gateway') host_gw = utils_net.get_default_gateway( - force_dhcp=True, target_iface=host_iface, json=True) + force_dhcp=True, target_iface=host_iface, json=True, multiple_nexthops=multiple_nexthops) + LOG.debug(f'Get guest default ipv4 gateway') vm_gw = utils_net.get_default_gateway( - session=session, force_dhcp=True, json=True) + session=session, force_dhcp=True, json=True, multiple_nexthops=multiple_nexthops) LOG.debug(f'Host and vm default ipv4 gateway: {host_gw}, {vm_gw}') if [x for x in vm_gw if x not in host_gw]: raise exceptions.TestFail( 'Host default ipv4 gateway not consistent with vm.') - + LOG.debug(f'Get host default ipv6 gateway') _host_gw_v6 = utils_net.get_default_gateway(ip_ver='ipv6', target_iface=host_iface, - json=True) + json=True, + multiple_nexthops=multiple_nexthops) if not _host_gw_v6: raise exceptions.TestFail('Guest has no ipv6 gateway!') - vm_gw_v6 = utils_net.get_default_gateway(session=session, ip_ver='ipv6', - json=True) + LOG.debug(f'Get guest default ipv6 gateway') + vm_gw_v6 = utils_net.get_default_gateway(session=session, + ip_ver='ipv6', + json=True, + multiple_nexthops=multiple_nexthops) if not vm_gw_v6: raise exceptions.TestFail('Guest has no ipv6 gateway!') host_gw_v6 = _host_gw_v6 if isinstance(_host_gw_v6, list) else [_host_gw_v6] + vm_gw_v6 = vm_gw_v6 if isinstance(vm_gw_v6, list) else [vm_gw_v6] LOG.debug(f'Host and vm default ipv6 gateway: {host_gw_v6}, {vm_gw_v6}') - if vm_gw_v6 not in host_gw_v6: + if [x for x in vm_gw_v6 if x not in host_gw_v6]: raise exceptions.TestFail( 'Host default ipv6 gateway not consistent with vm.') From 2f96cc317de2f44bf4b7f0748dfe48c0238f2124 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Thu, 29 May 2025 10:18:48 -0400 Subject: [PATCH 0983/1055] nvdimm: disable test on s390x No NVDIMM nor DIMM on s390x, disable. Signed-off-by: Sebastian Mitterle --- .../cfg/memory/memory_devices/nvdimm_memory_turn_to_dram.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/cfg/memory/memory_devices/nvdimm_memory_turn_to_dram.cfg b/libvirt/tests/cfg/memory/memory_devices/nvdimm_memory_turn_to_dram.cfg index db313f24f98..3159bc0dff4 100644 --- a/libvirt/tests/cfg/memory/memory_devices/nvdimm_memory_turn_to_dram.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/nvdimm_memory_turn_to_dram.cfg @@ -1,4 +1,5 @@ - memory.devices.nvdimm.turn_to_dram: + no s390-virtio type = nvdimm_memory_turn_to_dram start_vm = no mem_model = 'nvdimm' From e3f3ac5679a7b65390ad77ba2a0445543da224da Mon Sep 17 00:00:00 2001 From: lcheng Date: Thu, 29 May 2025 23:23:28 +0800 Subject: [PATCH 0984/1055] migration: Update virtiofs case Don't need to use systemd-run to run virtiofsd process. So update case. Signed-off-by: lcheng --- ..._with_externally_launched_virtiofs_dev.cfg | 2 +- ...n_with_externally_launched_virtiofs_dev.py | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/libvirt/tests/cfg/migration/migration_with_virtiofs/migration_with_externally_launched_virtiofs_dev.cfg b/libvirt/tests/cfg/migration/migration_with_virtiofs/migration_with_externally_launched_virtiofs_dev.cfg index a5cb0cb418e..c26d050c665 100644 --- a/libvirt/tests/cfg/migration/migration_with_virtiofs/migration_with_externally_launched_virtiofs_dev.cfg +++ b/libvirt/tests/cfg/migration/migration_with_virtiofs/migration_with_externally_launched_virtiofs_dev.cfg @@ -27,7 +27,7 @@ virsh_migrate_desturi = "qemu+ssh://${migrate_dest_host}/system" func_supported_since_libvirt_ver = (10, 5, 0) vm_attrs = {'mb': {"source_type":"file", 'access_mode': 'shared'}} - socket_path = "/vm001-vhost-fs.sock" + socket_path = "/var/vm001-vhost-fs.sock" dev_type = "filesystem" mount_tag = "mount_tag1" mount_dir = "/mnt/${mount_tag}" diff --git a/libvirt/tests/src/migration/migration_with_virtiofs/migration_with_externally_launched_virtiofs_dev.py b/libvirt/tests/src/migration/migration_with_virtiofs/migration_with_externally_launched_virtiofs_dev.py index 1634bcc3b1e..aa1de36251e 100644 --- a/libvirt/tests/src/migration/migration_with_virtiofs/migration_with_externally_launched_virtiofs_dev.py +++ b/libvirt/tests/src/migration/migration_with_virtiofs/migration_with_externally_launched_virtiofs_dev.py @@ -35,17 +35,18 @@ def setup_test(): mount_dir = params.get("mount_dir") expect_str = params.get("expect_str") - cmd1 = f"chcon -t virtd_exec_t /usr/libexec/virtiofsd" - cmd2 = f"mkdir -p {mnt_path_name}" - cmd3 = f"systemd-run /usr/libexec/virtiofsd --socket-path={socket_path} -o source={mnt_path_name}" - multi_cmd1 = f"{cmd1}; {cmd2}; {cmd3}" - process.run(multi_cmd1, shell=True, ignore_status=False) - remote.run_remote_cmd(multi_cmd1, params, ignore_status=False) + cmd1 = f"mkdir -p {mnt_path_name}" + cmd2 = f"/usr/libexec/virtiofsd --socket-path={socket_path} -o source={mnt_path_name} &" + multi_cmd1 = f"{cmd1}; {cmd2}" + process.run(multi_cmd1, shell=True, ignore_status=False, ignore_bg_processes=True) + cmd3 = f"/usr/libexec/virtiofsd --socket-path={socket_path} -o source={mnt_path_name} > /dev/null 2>&1 &" + multi_cmd2 = f"{cmd1}; {cmd3}" + remote.run_remote_cmd(multi_cmd2, params, ignore_status=False) cmd4 = f"chcon -t svirt_image_t {socket_path}" cmd5 = f"chown qemu:qemu {socket_path}" - multi_cmd2 = f"{cmd4}; {cmd5}" - process.run(multi_cmd2, shell=True, ignore_status=False) - remote.run_remote_cmd(multi_cmd2, params, ignore_status=False) + multi_cmd3 = f"{cmd4}; {cmd5}" + process.run(multi_cmd3, shell=True, ignore_status=False) + remote.run_remote_cmd(multi_cmd3, params, ignore_status=False) migration_obj.setup_connection() From bf53f3c3adca60c2755a295ca1219a9f6995139a Mon Sep 17 00:00:00 2001 From: Fangge Jin Date: Tue, 29 Apr 2025 17:10:06 +0800 Subject: [PATCH 0985/1055] virsh_event: Get the correct loop device name for umounting The current code uses /dev/loop0 for umounting, but sometimes it can be /dev/loop1 or others. So we need to get the correct loop device name from file /proc/mounts. Signed-off-by: Fangge Jin --- libvirt/tests/src/event/virsh_event.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/event/virsh_event.py b/libvirt/tests/src/event/virsh_event.py index b0fb59033ca..eabe5c69a93 100644 --- a/libvirt/tests/src/event/virsh_event.py +++ b/libvirt/tests/src/event/virsh_event.py @@ -87,6 +87,7 @@ def run(test, params, env): mount_point = tmpdir + "/smalldiskmountpoint" os.mkdir(mount_point) small_part = os.path.join(tmpdir, params.get("part_name", "io-error_part")) + mount_device = None def create_iface_xml(): """ @@ -558,6 +559,13 @@ def _check_disk(target): process.run("truncate -s %s %s" % (part_size, small_part), shell=True) utlv.mkfs(small_part, part_format) utils_misc.mount(small_part, mount_point, None) + + def _get_mount_device(): + with open("/proc/mounts") as f: + last_line = f.readlines()[-1] + mount_device = last_line.split()[0] + return mount_device + mount_device = _get_mount_device() new_disk = mount_point + "/%s_new_disk.img" % dom.name add_disk(dom.name, new_disk, 'vdb', '--subdriver qcow2 --config', 'qcow2') dom.start() @@ -716,8 +724,8 @@ def check_output(output, expected_events_list): if os.path.exists(dump_path): shutil.rmtree(dump_path) os.mkdir(dump_path) - if utils_misc.is_mounted("/dev/loop0", mount_point, part_format): - utils_misc.umount("/dev/loop0", mount_point, part_format) + if utils_misc.is_mounted(mount_device, mount_point, part_format): + utils_misc.umount(mount_device, mount_point, part_format) if os.path.exists(small_part): os.unlink(small_part) if os.path.exists(mount_point): From 853f4b731240b3236fc3903af9cd010d3df24909 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Fri, 21 Mar 2025 02:49:35 -0400 Subject: [PATCH 0986/1055] Update connectivity check of bridge type interface Remove nwfilter from test according to RHEL-71411:the nwfilter driver makes exensive use of ebtables in addition to iptables, but both of those have been deprecated, and in RHEL10 they've started removing parts of those packages with the intent of eventually removing them completely. Signed-off-by: Haijiao Zhao --- .../connectivity/connectivity_check_bridge_interface.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py index e63aa91d7ec..40431157722 100644 --- a/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py +++ b/libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py @@ -2,9 +2,9 @@ import re from avocado.utils import process - from virttest import utils_misc from virttest import utils_net +from virttest import libvirt_version from virttest import virsh from virttest.libvirt_xml import nwfilter_xml from virttest.libvirt_xml import vm_xml @@ -65,13 +65,17 @@ def run(test, params, env): elif bridge_type == 'ovs_br': utils_net.create_ovs_bridge(bridge_name) - if nwfilter_attrs: + if nwfilter_attrs and not libvirt_version.version_compare(8, 0, 0): nwf = nwfilter_xml.NwfilterXML() nwf.setup_attrs(**nwfilter_attrs) virsh.nwfilter_define(nwf.xml, **VIRSH_ARGS) LOG.debug('nwfilter xml:\n' + virsh.nwfilter_dumpxml( nwfilter_attrs['filter_name']).stdout_text) + if libvirt_version.version_compare(8, 0, 0): + if 'filterref' in iface_attrs: + iface_attrs.pop('filterref') + vmxml, ep_vmxml = list(map(vm_xml.VMXML.new_from_inactive_dumpxml, vms)) if vm_attrs: From c550fdcad22253a86a8103458f166f070a56ffbc Mon Sep 17 00:00:00 2001 From: lcheng Date: Thu, 29 May 2025 11:46:11 +0800 Subject: [PATCH 0987/1055] migration: Update netperf Replaced compilation of netperf with the netperf rpm for testing. Signed-off-by: lcheng --- libvirt/tests/cfg/migration/migrate_vm.cfg | 9 +- libvirt/tests/src/migration/migrate_vm.py | 177 +++++++-------------- 2 files changed, 57 insertions(+), 129 deletions(-) diff --git a/libvirt/tests/cfg/migration/migrate_vm.cfg b/libvirt/tests/cfg/migration/migrate_vm.cfg index e0e31c151ed..4f6acd163bc 100644 --- a/libvirt/tests/cfg/migration/migrate_vm.cfg +++ b/libvirt/tests/cfg/migration/migrate_vm.cfg @@ -174,12 +174,9 @@ migration_timeout = 600 virsh_options = "--live --verbose" - netperf_network: - netperf_version = "netperf-2.6.0-1" - netperf_source = "shared/deps/netperf/${netperf_version}.tar.bz2" - client_path = "/var/tmp/" - server_path = "/var/tmp/" - netperf_test_duration = 300 - netperf_para_sessions = 1 + netperf_network = "yes" + netperf_cmd_dst = "netperf -H ${client_ip} -l 600 > /dev/null 2>&1 &" + netperf_cmd_src = "netperf -H ${server_ip} -l 600 &" migration_timeout = 600 virsh_options = "--live --verbose" - iothread: diff --git a/libvirt/tests/src/migration/migrate_vm.py b/libvirt/tests/src/migration/migrate_vm.py index 0671b68a49f..0fa30f35d39 100644 --- a/libvirt/tests/src/migration/migrate_vm.py +++ b/libvirt/tests/src/migration/migrate_vm.py @@ -23,7 +23,6 @@ from virttest import utils_config from virttest import utils_libvirtd from virttest import utils_misc -from virttest import utils_netperf from virttest import utils_package from virttest import utils_selinux from virttest import utils_test @@ -777,83 +776,62 @@ def run_remote_cmd(command, server_ip, server_user, server_pwd, return (session, status, output) -def setup_netsever_and_launch_netperf(test, params): +def run_cmd(cmd, params): """ - Setup netserver and run netperf client + Run cmd on source host and target host + + :param cmd: command + :param params: parameters used + """ + process.run(cmd, shell=True, ignore_status=True) + remote.run_remote_cmd(cmd, params, ignore_status=True) + + +def setup_netperf(test, params): + """ + Setup netserver and run netperf cmd :param test: test object :param params: parameters used - :raise: test.error if automake installation fails """ server_ip = params.get("server_ip") - server_user = params.get("server_user") + server_user = params.get("server_user", "root") server_pwd = params.get("server_pwd") - client_ip = params.get("client_ip") - client_user = params.get("client_user") - client_pwd = params.get("client_pwd") - netperf_source = params.get("netperf_source") - netperf_source = os.path.join(data_dir.get_root_dir(), netperf_source) - client_md5sum = params.get("client_md5sum") - client_path = params.get("client_path", "/var/tmp") - server_md5sum = params.get("server_md5sum") - server_path = params.get("server_path", "/var/tmp") - compile_option_client = params.get("compile_option_client", "") - compile_option_server = params.get("compile_option_server", "") - # Run netperf with message size defined in range. - netperf_test_duration = int(params.get("netperf_test_duration", 60)) - netperf_para_sess = params.get("netperf_para_sessions", "1") - test_protocol = params.get("test_protocols", "TCP_STREAM") - netperf_cmd_prefix = params.get("netperf_cmd_prefix", "") - netperf_output_unit = params.get("netperf_output_unit", " ") - netperf_package_sizes = params.get("netperf_package_sizes") - test_option = params.get("test_option", "") - direction = params.get("direction", "remote") - remote_session = remote.remote_login("ssh", server_ip, "22", server_user, - server_pwd, r'[$#%]') - for loc in ['source', 'target']: - session = None - if loc == 'target': - session = remote_session - if not utils_package.package_install("automake", session): - test.error("Failed to install automake on %s host." % loc) + netperf_cmd_src = params.get("netperf_cmd_src") + netperf_cmd_dst = params.get("netperf_cmd_dst") + + if not utils_package.package_install("netperf"): + test.error("Failed to install netperf on source host.") + + remote_session = remote.wait_for_login('ssh', server_ip, '22', server_user, + server_pwd, r"[\#\$]\s*$") + if not utils_package.package_install("netperf", remote_session): + test.error("Failed to install netperf on target host.") remote_session.close() - n_client = utils_netperf.NetperfClient(client_ip, - client_path, - client_md5sum, - netperf_source, - client="ssh", - port="22", - username=client_user, - password=client_pwd, - compile_option=compile_option_client) - - logging.info("Start netserver on %s", server_ip) - n_server = utils_netperf.NetperfServer(server_ip, - server_path, - server_md5sum, - netperf_source, - client="ssh", - port="22", - username=server_user, - password=server_pwd, - compile_option=compile_option_server) - - n_server.start() - - test_option += " -l %s" % netperf_test_duration - start_time = time.time() - stop_time = start_time + netperf_test_duration - t_option = "%s -t %s" % (test_option, test_protocol) - logging.info("Start netperf on %s", client_ip) - n_client.bg_start(server_ip, t_option, - netperf_para_sess, netperf_cmd_prefix, - package_sizes=netperf_package_sizes) - if utils_misc.wait_for(n_client.is_netperf_running, 10, 0, 1, - "Wait netperf test start"): - logging.info("Start netperf on %s successfully.", client_ip) - return (True, n_client, n_server) - else: - return (False, n_client, n_server) + + run_cmd("systemctl stop firewalld", params) + run_cmd("killall netserver", params) + test.log.debug("Start netserver.") + run_cmd("netserver", params) + + test.log.debug("Run netperf on source host.") + process.run(netperf_cmd_src, shell=True, ignore_bg_processes=True) + + test.log.debug("Run netperf on target host.") + remote.run_remote_cmd(netperf_cmd_dst, params, ignore_status=True) + + +def cleanup_netperf(test, params): + """ + Cleanup netserver and netperf cmd + + :param test: test object + :param params: parameters used + """ + test.log.debug("Cleanup netserver and netperf.") + run_cmd("killall netperf", params) + run_cmd("killall netserver", params) + run_cmd("systemctl start firewalld", params) def cleanup(objs_list): @@ -1279,6 +1257,7 @@ def get_target_hugepage_num(params): block_time = test_dict.get("block_time") restart_vm = "yes" == test_dict.get("restart_vm", "no") diff_cpu_vendor = "yes" == test_dict.get("diff_cpu_vendor", "no") + netperf_network = "yes" == test_dict.get("netperf_network", "no") # Get iothread parameters. driver_iothread = test_dict.get("driver_iothread") @@ -1474,10 +1453,6 @@ def get_target_hugepage_num(params): nfs_cli = None se_obj = None libvirtd_conf = None - n_server_c = None - n_client_c = None - n_server_s = None - n_client_s = None need_mkswap = False LOCAL_SELINUX_ENFORCING = True REMOTE_SELINUX_ENFORCING = True @@ -2203,43 +2178,8 @@ def get_target_hugepage_num(params): result = virsh.migrate_compcache(vm_name, size=set_migr_cache_size) logging.debug(result) - netperf_version = test_dict.get("netperf_version") - if netperf_version: - # Install tar on client - # Note: tar is used to untar netperf package later. - if not utils_package.package_install(["tar"]): - test.error("Failed to install tar on client") - - # Install tar on server - # Note: tar is used to untar netperf package later. - remote_session = remote.wait_for_login('ssh', server_ip, '22', server_user, - server_pwd, r"[\#\$]\s*$") - if not utils_package.package_install(["tar"], remote_session): - test.error("Failed to install tar on server") - - ret, n_client_c, n_server_c = setup_netsever_and_launch_netperf( - test, test_dict) - if not ret: - test.error("Can not start netperf on %s" % client_ip) - - new_args_dict = dict(test_dict) - new_args_dict["server_ip"] = client_ip - new_args_dict["server_user"] = client_user - new_args_dict["server_pwd"] = client_pwd - new_args_dict["client_ip"] = server_ip - new_args_dict["client_user"] = server_user - new_args_dict["client_pwd"] = server_pwd - new_args_dict["server_md5sum"] = test_dict.get("client_md5sum") - new_args_dict["server_path"] = test_dict.get("client_path", "/var/tmp") - new_args_dict["compile_option_server"] = test_dict.get("compile_option_client", "") - new_args_dict["client_md5sum"] = test_dict.get("server_md5sum") - new_args_dict["client_path"] = test_dict.get("server_path", "/var/tmp") - new_args_dict["compile_option_client"] = test_dict.get("compile_option_server", "") - - ret, n_client_s, n_server_s = setup_netsever_and_launch_netperf( - test, new_args_dict) - if not ret: - test.error("Can not start netperf on %s" % client_ip) + if netperf_network: + setup_netperf(test, params) speed = test_dict.get("set_migration_speed") if speed: @@ -2987,18 +2927,9 @@ def get_target_hugepage_num(params): test.fail("Failed to run '%s' on the remote: %s" % (cmd, output)) - # Stop netserver service and clean up netperf package - if n_server_c: - n_server_c.stop() - n_server_c.package.env_cleanup(True) - if n_client_c: - n_client_c.package.env_cleanup(True) - - if n_server_s: - n_server_s.stop() - n_server_s.package.env_cleanup(True) - if n_client_s: - n_client_s.package.env_cleanup(True) + # Stop netserver service and clean up netperf cmd + if netperf_network: + cleanup_netperf(test, params) if objs_list and len(objs_list) > 0: logging.debug("Clean up the objects") From 8a3a3958ae2213844d13270bcc0a45e1af84e350 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Fri, 30 May 2025 18:29:18 +0800 Subject: [PATCH 0988/1055] migration_with_vtpm_state_on_block_dev: fix syntax error Signed-off-by: Dan Zheng --- .../migration_with_vtpm_state_on_block_dev.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.py b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.py index f8fce8fc5a5..bc24a59d2a6 100644 --- a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.py +++ b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.py @@ -92,7 +92,7 @@ def check_capability(params, test): check_items(eval(params.get("expected_list_1"), "[]"), log_file, test) else: if libvirt_version.version_compare(11, 0, 0): - check_items(eval(params.get("expected_list_2"), "[]"), log_file, test) + check_items(eval(params.get("expected_list_2", "[]")), log_file, test) else: check_items(eval(params.get("unexpected_list_3", "[]")), log_file, test, str_in_log=False) check_items(eval(params.get("expected_list_3", "[]")), log_file, test) From 799296642b5dce5132388946c49f98699f6b0f98 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Mon, 2 Jun 2025 10:41:04 -0400 Subject: [PATCH 0989/1055] virttools: enable selection of first dasd for test Our test environments now use DASD only for passthrough tests. Therefore it's safe to select the first DASD in Use. Select assume per default environments are set up with at least 1 DASD disk in Use. This means, the virttools test cases don't have to manage the Use state anymore but can fully rely in the `provider.vfio.ccw` to retrieve the device and manage it. Also, the `CcwMdevHandler` must not deactivate the device anymore. It has been used in the following test suites: 1) libvirt/passthrough/passthrough_robustness 2) virttools/virt_install/hostdev_mdev 3) virttools/virt_install/vfio_installation The PR will provide data showing this patch doesn't introduce regression. Signed-off-by: Sebastian Mitterle --- provider/vfio/mdev_handlers.py | 2 -- virttools/tests/cfg/virt_install/blk_installation.cfg | 2 +- virttools/tests/cfg/virt_install/hostdev_mdev.cfg | 2 +- virttools/tests/cfg/virt_install/vfio_installation.cfg | 2 +- virttools/tests/src/virt_install/blk_installation.py | 7 +++++-- virttools/tests/src/virt_install/hostdev_mdev.py | 7 ++++++- virttools/tests/src/virt_install/vfio_installation.py | 5 +++++ 7 files changed, 19 insertions(+), 8 deletions(-) diff --git a/provider/vfio/mdev_handlers.py b/provider/vfio/mdev_handlers.py index 61e33c9d376..74e1b77d820 100644 --- a/provider/vfio/mdev_handlers.py +++ b/provider/vfio/mdev_handlers.py @@ -175,8 +175,6 @@ def clean_up(self): # need to sleep to avoid issue with setting device offline # adding a wait_for would likely be more complicated sleep(1) - if self.device_id: - ccw.set_device_offline(self.device_id) class ApMdevHandler(MdevHandler): diff --git a/virttools/tests/cfg/virt_install/blk_installation.cfg b/virttools/tests/cfg/virt_install/blk_installation.cfg index 8993db76700..93e49f61560 100644 --- a/virttools/tests/cfg/virt_install/blk_installation.cfg +++ b/virttools/tests/cfg/virt_install/blk_installation.cfg @@ -4,4 +4,4 @@ start_vm = False install_tree_url = INSTALL_TREE_URL kickstart_url = KICKSTART_URL - devid = + devid = dasd diff --git a/virttools/tests/cfg/virt_install/hostdev_mdev.cfg b/virttools/tests/cfg/virt_install/hostdev_mdev.cfg index c6b9cf38ccf..a4c8a50cda8 100644 --- a/virttools/tests/cfg/virt_install/hostdev_mdev.cfg +++ b/virttools/tests/cfg/virt_install/hostdev_mdev.cfg @@ -4,4 +4,4 @@ - check_present_inside_guest: only s390-virtio mdev_type = vfio_ccw-io - devid = + devid = dasd diff --git a/virttools/tests/cfg/virt_install/vfio_installation.cfg b/virttools/tests/cfg/virt_install/vfio_installation.cfg index f794d43184b..449721da51f 100644 --- a/virttools/tests/cfg/virt_install/vfio_installation.cfg +++ b/virttools/tests/cfg/virt_install/vfio_installation.cfg @@ -4,4 +4,4 @@ start_vm = False install_tree_url = INSTALL_TREE_URL kickstart_url = KICKSTART_URL - devid = + devid = dasd diff --git a/virttools/tests/src/virt_install/blk_installation.py b/virttools/tests/src/virt_install/blk_installation.py index 1f934b9aff7..5fdfefcac1f 100644 --- a/virttools/tests/src/virt_install/blk_installation.py +++ b/virttools/tests/src/virt_install/blk_installation.py @@ -13,6 +13,9 @@ from avocado.utils import process from virttest.utils_misc import cmd_status_output +from virttest.utils_zchannels import SubchannelPaths as paths + +from provider.vfio import ccw logging = log.getLogger("avocado." + __name__) @@ -34,9 +37,9 @@ def run(test, params, env): kickstart_url = params.get("kickstart_url") process.run("curl -k -o /tmp/ks.cfg %s" % kickstart_url) - process.run("chzdev -e %s" % devid) + device = ccw.get_device_info(devid, True) + devid = device[paths.HEADER["Device"]] disk_path = "/dev/disk/by-path/ccw-%s" % devid - cleanup_actions.insert(0, lambda: process.run("chzdev -d %s" % devid)) cmd = ("virt-install --name %s" " --disk %s" diff --git a/virttools/tests/src/virt_install/hostdev_mdev.py b/virttools/tests/src/virt_install/hostdev_mdev.py index 439ddaa5c36..fb3174f5afc 100644 --- a/virttools/tests/src/virt_install/hostdev_mdev.py +++ b/virttools/tests/src/virt_install/hostdev_mdev.py @@ -2,9 +2,12 @@ from avocado.core.exceptions import TestError from provider.vfio.mdev_handlers import MdevHandler +from virttest import virsh from virttest.libvirt_xml.vm_xml import VMXML from virttest.utils_misc import cmd_status_output -from virttest import virsh +from virttest.utils_zchannels import SubchannelPaths as paths + +from provider.vfio import ccw LOG = logging.getLogger('avocado.' + __name__) @@ -76,6 +79,8 @@ def run(test, params, env): try: + device = ccw.get_device_info(devid, True) + devid = device[paths.HEADER["Device"]] vm.undefine() handler = MdevHandler.from_type(mdev_type) disk = get_disk_for_import(vmxml) diff --git a/virttools/tests/src/virt_install/vfio_installation.py b/virttools/tests/src/virt_install/vfio_installation.py index ae8a890c663..1b18bd66c6e 100644 --- a/virttools/tests/src/virt_install/vfio_installation.py +++ b/virttools/tests/src/virt_install/vfio_installation.py @@ -14,6 +14,9 @@ from provider.vfio.mdev_handlers import MdevHandler from virttest.utils_misc import cmd_status_output +from virttest.utils_zchannels import SubchannelPaths as paths + +from provider.vfio import ccw logging = log.getLogger("avocado." + __name__) @@ -37,6 +40,8 @@ def run(test, params, env): process.run("curl -k -o /tmp/ks.cfg %s" % kickstart_url) + device = ccw.get_device_info(devid, True) + devid = device[paths.HEADER["Device"]] handler = MdevHandler.from_type("vfio_ccw-io") mdev_nodedev = handler.create_nodedev(devid=devid) target_address = handler.get_target_address() From 15798825d3f95dbe020a1a787e52b111dd1d47ba Mon Sep 17 00:00:00 2001 From: lcheng Date: Fri, 17 Jan 2025 11:04:56 +0800 Subject: [PATCH 0990/1055] migration: add case about migrate vm with cpu mode XXX-303279 - [VM migration] migrate vm with cpu mode Signed-off-by: lcheng --- .../migration_with_cpu_mode.cfg | 42 ++++++++++++++ .../migration_misc/migration_with_cpu_mode.py | 55 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 libvirt/tests/cfg/migration/migration_misc/migration_with_cpu_mode.cfg create mode 100644 libvirt/tests/src/migration/migration_misc/migration_with_cpu_mode.py diff --git a/libvirt/tests/cfg/migration/migration_misc/migration_with_cpu_mode.cfg b/libvirt/tests/cfg/migration/migration_misc/migration_with_cpu_mode.cfg new file mode 100644 index 00000000000..74c902aa709 --- /dev/null +++ b/libvirt/tests/cfg/migration/migration_misc/migration_with_cpu_mode.cfg @@ -0,0 +1,42 @@ +- migration.migration_misc.migration_with_cpu_mode: + type = migration_with_cpu_mode + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + take_regular_screendumps = no + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + status_error = "no" + migrate_desturi_port = "16509" + migrate_desturi_type = "tcp" + virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" + start_vm = "no" + variants: + - p2p: + virsh_migrate_options = '--live --p2p --verbose' + - non_p2p: + virsh_migrate_options = '--live --verbose' + variants migration_option: + - with_xml: + - without_xml: + variants cpu_mode: + - host_model: + no s390x + numa_cell = "'numa_cell': [{'cpus': '0-1', 'memory': '2097152', 'unit': 'KiB'}]" + vm_attrs = {'cpu': {'mode': 'host-model', 'check': 'partial', ${numa_cell}}} + - custom: + no aarch64 + cpu_mode = "custom" diff --git a/libvirt/tests/src/migration/migration_misc/migration_with_cpu_mode.py b/libvirt/tests/src/migration/migration_misc/migration_with_cpu_mode.py new file mode 100644 index 00000000000..262c0691dde --- /dev/null +++ b/libvirt/tests/src/migration/migration_misc/migration_with_cpu_mode.py @@ -0,0 +1,55 @@ +import os + +from virttest import data_dir +from virttest import virsh +from virttest.libvirt_xml import vm_xml + +from provider.migration import base_steps + + +def run(test, params, env): + """ + Verify that migration can succeed when cpu mode is configured. + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + def setup_test(): + """ + Setup steps + + """ + cpu_mode = params.get("cpu_mode") + migration_option = params.get("migration_option") + + test.log.info("Setup steps.") + migration_obj.setup_connection() + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + if cpu_mode == "host_model": + vm_attrs = eval(params.get('vm_attrs', '{}')) + vmxml.setup_attrs(**vm_attrs) + vmxml.sync() + else: + base_steps.sync_cpu_for_mig(params) + + if not vm.is_alive(): + vm.start() + vm.wait_for_login().close() + + if migration_option == "with_xml": + xmlfile = os.path.join(data_dir.get_tmp_dir(), '%s.xml' % vm_name) + virsh.dumpxml(vm_name, extra="--migratable", to_file=xmlfile, ignore_status=False) + params.update({"virsh_migrate_extra": f"--xml {xmlfile}"}) + + vm_name = params.get("migrate_main_vm") + + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + + try: + setup_test() + migration_obj.run_migration() + migration_obj.verify_default() + finally: + migration_obj.cleanup_connection() From 3da3e31116f6349550bbf29dda581ca02227420c Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Tue, 3 Jun 2025 13:37:41 +0800 Subject: [PATCH 0991/1055] nbdkit: fix the failed case with the version issue Signed-off-by: vwu-vera --- v2v/tests/cfg/nbdkit/nbdkit.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2v/tests/cfg/nbdkit/nbdkit.cfg b/v2v/tests/cfg/nbdkit/nbdkit.cfg index 1e13f0f0cc1..143d60fd4da 100644 --- a/v2v/tests/cfg/nbdkit/nbdkit.cfg +++ b/v2v/tests/cfg/nbdkit/nbdkit.cfg @@ -228,4 +228,4 @@ - cve_starttls: only source_none..dest_none checkpoint = 'cve_starttls' - version_required = "[nbdkit-server-1.26.5-1,)" + version_required = "[nbdkit-1.26.5-1,nbdkit-1.40)" From 7f8744ecb8ef4613f52111d19b02b2201ea261e6 Mon Sep 17 00:00:00 2001 From: meinaLi Date: Tue, 3 Jun 2025 02:16:36 -0400 Subject: [PATCH 0992/1055] SRIOV: fix an expected error message issue The previous error message is "Supported values for aw-bits are", but in current version it's "supported values for aw-bits are". So update the script to include all of them. Signed-off-by: meinaLi --- libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_aw_bits.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_aw_bits.cfg b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_aw_bits.cfg index f5d73f13e93..8f342d9b74d 100644 --- a/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_aw_bits.cfg +++ b/libvirt/tests/cfg/sriov/vIOMMU/intel_iommu_aw_bits.cfg @@ -9,7 +9,7 @@ - 39: - 36: status_error = yes - err_msg = "Supported values for aw-bits are" + err_msg = "Supported | supported values for aw-bits are" - 3423: status_error = yes err_msg = "Parameter 'aw-bits' expects uint8_t" From 63f34896d25b9978a3c69761903511db4b87ae8a Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Tue, 3 Jun 2025 16:48:58 +0800 Subject: [PATCH 0993/1055] hmat_info: correct the pattern This is to avoid the messed up case pattern Signed-off-by: Dan Zheng --- libvirt/tests/cfg/numa/guest_numa_hmat/hmat_info.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/numa/guest_numa_hmat/hmat_info.cfg b/libvirt/tests/cfg/numa/guest_numa_hmat/hmat_info.cfg index d10c65aee5f..c685b75b6a7 100644 --- a/libvirt/tests/cfg/numa/guest_numa_hmat/hmat_info.cfg +++ b/libvirt/tests/cfg/numa/guest_numa_hmat/hmat_info.cfg @@ -46,5 +46,5 @@ qemu_check_cache_1 = "-numa hmat-cache,node-id=0,size=128K,level=2,associativity=complex,policy=write-through,line=16" qemu_check_cache_2 = "-numa hmat-cache,node-id=1,size=10K,level=1,associativity=none,policy=none,line=8" variants: - - default: + - @default: func_supported_since_libvirt_ver = (7, 5, 0) \ No newline at end of file From 96025d7e0e15da80db00ea50d5ec421ab5931604 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle Date: Tue, 3 Jun 2025 11:24:41 +0200 Subject: [PATCH 0994/1055] migrate_mem: restore configuration for s390x a31e2c2cd3d7a1ad41c3a7164566ab1db2e3b1f3 apparently fixed the configuration value for a specific VM setup. This now leads to test failure for s390x with 1GB RAM. For s390x, restore the previous value. Signed-off-by: Sebastian Mitterle --- libvirt/tests/cfg/migration/migrate_mem.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libvirt/tests/cfg/migration/migrate_mem.cfg b/libvirt/tests/cfg/migration/migrate_mem.cfg index 5668ce06c19..754aaf1b423 100644 --- a/libvirt/tests/cfg/migration/migrate_mem.cfg +++ b/libvirt/tests/cfg/migration/migrate_mem.cfg @@ -54,6 +54,8 @@ str_in_log = False - mem_balloon: ballooned_mem = "1572864" + s390-virtio: + ballooned_mem = "716800" - mem_nvdimm: no s390-virtio nvdimm_file_path = '${nfs_mount_dir}/nvdimm' From da5595d5d02f392448801de9034f539c0cf3b1c5 Mon Sep 17 00:00:00 2001 From: meinaLi Date: Tue, 3 Jun 2025 22:11:13 -0400 Subject: [PATCH 0995/1055] virtual_disks: fix sgio issue with multipath disk The auto case virtual_disks.multipath.rawio_yes.sgio_filtered.hotplug has 20% failure rate. It maybe caused by using udev to scan the multipath device for too long, causing the device to be occupied. So add timeout before test. Also because for multipath SAN, the scaning time between 10s to 30s. So use 15s here. Signed-off-by: meinaLi --- libvirt/tests/src/virtual_disks/virtual_disks_multipath.py | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_multipath.py b/libvirt/tests/src/virtual_disks/virtual_disks_multipath.py index 07001dd32c3..b1ee0696109 100644 --- a/libvirt/tests/src/virtual_disks/virtual_disks_multipath.py +++ b/libvirt/tests/src/virtual_disks/virtual_disks_multipath.py @@ -179,6 +179,7 @@ def _verify_multipathd_alive(): attach_option = "" if not hotplug_disk: attach_option = "--config" + time.sleep(15) result = virsh.attach_device(vm_name, disk_xml, flagstr=attach_option, ignore_status=True, debug=True) libvirt.check_exit_status(result, status_error) From df1a3ad14f6a8f2b1e7b0f1b741f22a43e11bb3f Mon Sep 17 00:00:00 2001 From: Julia Graham Date: Wed, 4 Jun 2025 12:22:26 -0400 Subject: [PATCH 0996/1055] updated do_migration function to always return a tuple Signed-off-by: Julia Graham --- libvirt/tests/src/virsh_cmd/domain/virsh_migrate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_migrate.py b/libvirt/tests/src/virsh_cmd/domain/virsh_migrate.py index 43f2c7c1b27..35bbef79b46 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_migrate.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_migrate.py @@ -139,7 +139,7 @@ def do_migration(delay, vm, dest_uri, options, extra, **virsh_args): if not options.count("dname") and not extra.count("dname"): vm.verify_kernel_crash() - return True + return (True, migration_msg) def numa_pin(memory_mode, memnode_mode, numa_dict_list, host_numa_node): """ From 4045092b1a323edb3dee3062cbf05fd82f17b514 Mon Sep 17 00:00:00 2001 From: hholoubk Date: Fri, 21 Mar 2025 14:15:13 +0100 Subject: [PATCH 0997/1055] automate VIRT-303225 - virsh reset when booting guest for 10+ times --- .../cfg/sriov/vIOMMU/iommu_repeated_reset.cfg | 28 +++++++ .../src/sriov/vIOMMU/iommu_repeated_reset.py | 76 +++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 libvirt/tests/cfg/sriov/vIOMMU/iommu_repeated_reset.cfg create mode 100644 libvirt/tests/src/sriov/vIOMMU/iommu_repeated_reset.py diff --git a/libvirt/tests/cfg/sriov/vIOMMU/iommu_repeated_reset.cfg b/libvirt/tests/cfg/sriov/vIOMMU/iommu_repeated_reset.cfg new file mode 100644 index 00000000000..35af9fd26f2 --- /dev/null +++ b/libvirt/tests/cfg/sriov/vIOMMU/iommu_repeated_reset.cfg @@ -0,0 +1,28 @@ +- vIOMMU.iommu_repeated_reset: + type = iommu_repeated_reset + ping_dest = '8.8.8.8' + max_wait_ms = 3000 + max_repeat = 10 + str_in_log = False + log_messages = "virtio: zero sized buffers are not allowed" + variants: + - virtio: + only q35, aarch64 + func_supported_since_libvirt_ver = (8, 3, 0) + iommu_dict = {'model': 'virtio'} + - intel: + only q35 + start_vm = "yes" + enable_guest_iommu = "yes" + iommu_dict = {'model': 'intel', 'driver': {'intremap': 'on', 'caching_mode': 'on', 'eim': 'on', 'iotlb': 'on', 'aw_bits': '48'}} + - smmuv3: + only aarch64 + func_supported_since_libvirt_ver = (5, 5, 0) + iommu_dict = {'model': 'smmuv3'} + variants: + - scsi_controller: + controller_dicts = [{'type': 'scsi', 'model': 'virtio-scsi','driver': {'iommu': 'on'}}] + disk_driver = {'name': 'qemu', 'type': 'qcow2'} + disk_dict = {'target': {'dev': 'sda', 'bus': 'scsi'}, 'driver': ${disk_driver}} + cleanup_ifaces = no + start_vm = "yes" diff --git a/libvirt/tests/src/sriov/vIOMMU/iommu_repeated_reset.py b/libvirt/tests/src/sriov/vIOMMU/iommu_repeated_reset.py new file mode 100644 index 00000000000..7df626b448e --- /dev/null +++ b/libvirt/tests/src/sriov/vIOMMU/iommu_repeated_reset.py @@ -0,0 +1,76 @@ +import os +from time import sleep +from random import uniform + +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_test import libvirt +from virttest import utils_logfile + +from provider.viommu import viommu_base + + +def run(test, params, env): + """ + Start vm with iommu device and kinds of virtio devices with iommu=on, and + check network and disk function. + """ + + def setup_test(): + utils_logfile.clear_log_file(log_file_name, '/var/log/libvirt/qemu') + test_obj.setup_iommu_test(iommu_dict=iommu_dict, cleanup_ifaces=False) + test_obj.prepare_controller() + test.log.debug("---------------------------------------------------------------------------") + dev_dict = eval(params.get('disk_dict', '{}')) + test.log.debug(f"disk_dict: {dev_dict}") + if dev_dict: + dev_dict = test_obj.update_disk_addr(dev_dict) + if dev_dict["target"].get("bus") != "virtio": + libvirt_vmxml.modify_vm_device( + vm_xml.VMXML.new_from_dumpxml(vm.name), 'disk', {'driver': None}) + + libvirt_vmxml.modify_vm_device( + vm_xml.VMXML.new_from_dumpxml(vm.name), 'disk', dev_dict) + + iommu_dict = eval(params.get('iommu_dict', '{}')) + + vm_name = params.get("main_vm", "avocado-vt-vm1") + log_file_name = f"{vm_name}.log" + log_file = os.path.join("/var/log/libvirt/qemu", log_file_name) + vm = env.get_vm(vm_name) + + test_obj = viommu_base.VIOMMUTest(vm, test, params) + + try: + setup_test() + + test.log.info("TEST_STEP: Start the VM and wait for login.") + vm.start() + vm.wait_for_login().close() + test.log.info("TEST_STEP: Reboot the VM and wait for event 'reboot'") + virsh.reboot(vm_name, wait_for_event=True, debug=True, ignore_status=False) + test.log.debug("TEST_STEP: verify user is able to login also after restarts") + vm.wait_for_login().close() + + max_wait_ms = int(params.get('max_wait_ms', 0)) + max_repeat = int(params.get('max_repeat', 10)) + + for _ in range(max_repeat): + if max_wait_ms > 0: + wait_time = uniform(0, max_wait_ms) / 1000 + test.log.debug(f"waiting before reset {wait_time}s") + sleep(wait_time) + virsh.reset(vm_name) + + test.log.debug(vm_xml.VMXML.new_from_dumpxml(vm.name)) + + test.log.debug("TEST_STEP: verify user is able to login also after restarts") + vm.wait_for_login().close() + log_messages = params.get('log_messages', "") + str_in_log = (params.get('str_in_log', "False") == "True") + test.log.debug("TEST_STEP: check log for error messages") + libvirt.check_logfile(log_messages, log_file, str_in_log) + + finally: + test_obj.teardown_iommu_test() From 7923601855cba30927a2121dfa38f3698f02238a Mon Sep 17 00:00:00 2001 From: lcheng Date: Fri, 6 Jun 2025 09:38:36 +0800 Subject: [PATCH 0998/1055] migration: Update mount path for image mode Signed-off-by: lcheng --- .../migration_with_vtpm/migration_with_shared_tpm.cfg | 4 ++-- .../migration_with_vtpm/migration_with_shared_tpm.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg index 05fb3f74e13..6a160e17ec3 100644 --- a/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg +++ b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_shared_tpm.cfg @@ -19,6 +19,7 @@ client_pwd = "${migrate_source_pwd}" status_error = "no" transport_type = "ssh" + migrate_desturi_type = "ssh" virsh_migrate_desturi = "qemu+ssh://${migrate_dest_host}/system" tpm_cmd = "tpm2_getrandom --hex 16" auth_sec_dict = {"sec_ephemeral": "no", "sec_private": "yes", "sec_desc": "sample vTPM secret", "sec_usage": "vtpm", "sec_name": "VTPM_example"} @@ -38,7 +39,6 @@ storage_type = 'nfs' setup_local_nfs = 'yes' disk_type = "file" - disk_source_protocol = "netfs" mnt_path_name = ${nfs_mount_dir} variants: - persistent_and_p2p: @@ -53,7 +53,7 @@ transient_vm = "yes" variants shared_storage_type: - nfs: - nfs_export_dir = "/var/tmp" + nfs_export_dir = "${export_dir}/swtpm" src_mount_path = "${client_ip}:${nfs_export_dir}" tpm_security_contexts = "nfs_t" tpm_security_contexts_restore = "${tpm_security_contexts}" diff --git a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py index 5d50d13ab16..6c5e30ed56f 100644 --- a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py +++ b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py @@ -186,7 +186,7 @@ def setup_nfs(): src_mount_path = params.get("src_mount_path") test.log.info("Setup for nfs storage type.") - libvirt.set_vm_disk(vm, params) + migration_obj.setup_connection() if not os.path.exists(swtpm_path): os.mkdir(swtpm_path) libvirt.setup_or_cleanup_nfs(True, mount_dir=swtpm_path, is_mount=True, export_dir=nfs_export_dir) @@ -227,7 +227,7 @@ def setup_ceph(): vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) vmxml.set_seclabel([seclabel_dict]) vmxml.sync() - libvirt.set_vm_disk(vm, params) + migration_obj.setup_connection() setup_vtpm(params, test, vm, migration_obj) check_tpm_security_context(params, vm, test, tpm_security_contexts) check_swtpm_process(params, test) From 24f0c59d2cb5e3463b632a2bcbada77aa8b40f0a Mon Sep 17 00:00:00 2001 From: meinaLi Date: Thu, 5 Jun 2025 21:42:09 -0400 Subject: [PATCH 0999/1055] Inc_backup: automate 1 checkpoint-edit backlog case Automate case: RHEL-187684 - test 'checkpoint-edit' Signed-off-by: meinaLi --- .../incremental_backup_checkpoint_cmd.cfg | 1 + .../incremental_backup_checkpoint_cmd.py | 44 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/libvirt/tests/cfg/incremental_backup/incremental_backup_checkpoint_cmd.cfg b/libvirt/tests/cfg/incremental_backup/incremental_backup_checkpoint_cmd.cfg index 863e5607b66..784f0cf2619 100644 --- a/libvirt/tests/cfg/incremental_backup/incremental_backup_checkpoint_cmd.cfg +++ b/libvirt/tests/cfg/incremental_backup/incremental_backup_checkpoint_cmd.cfg @@ -74,3 +74,4 @@ flag = "--with-checkpoint" - without-checkpoint: flag = "--without-checkpoint" + - checkpoint_edit: diff --git a/libvirt/tests/src/incremental_backup/incremental_backup_checkpoint_cmd.py b/libvirt/tests/src/incremental_backup/incremental_backup_checkpoint_cmd.py index e4f06517e35..432f116612d 100644 --- a/libvirt/tests/src/incremental_backup/incremental_backup_checkpoint_cmd.py +++ b/libvirt/tests/src/incremental_backup/incremental_backup_checkpoint_cmd.py @@ -2,12 +2,14 @@ import re import logging as log import operator +import aexpect from virttest import virsh from virttest import data_dir from virttest import libvirt_version from virttest import utils_disk from virttest import utils_backup +from virttest import remote from virttest.libvirt_xml import vm_xml from virttest.libvirt_xml import checkpoint_xml from virttest.libvirt_xml.devices import graphics @@ -41,6 +43,45 @@ def prepare_checkpoints(disk="vdb", num=1, cp_prefix="test_checkpoint_"): virsh.checkpoint_create_as(vm_name, options, **virsh_dargs) current_checkpoints.append(checkpoint_name) + def edit_checkpoint(vm_name, checkpoint_name, restore=False): + """ + Edit the checkpoints. + + :param vm_name: the domain name + :param checkpoint_name: the checkpoint name + :params restore: determine whether to restore the modified checkpoint + """ + checkpoint_dumpxml = virsh.checkpoint_dumpxml(vm_name, checkpoint_name, "--no-domain") + session = aexpect.ShellSession("sudo -s") + try: + session.sendline("virsh checkpoint-edit %s %s" % (vm_name, checkpoint_name)) + if not restore: + test.log.debug("The checkpoint dumpxml before edit: %s", + checkpoint_dumpxml.stdout_text) + edit_cmd = ":%s#checkpoint='no'#checkpoint='bitmap'#" + else: + edit_cmd = ":%s###" + session.sendline(edit_cmd) + session.send('\x1b') + session.send('ZZ') + remote.handle_prompts(session, None, None, r"[\#\$]\s*$") + session.close() + edit_result = virsh.checkpoint_dumpxml( + vm_name, + checkpoint_name, + "--no-domain", + debug=True + ).stdout_text.strip() + if not restore: + if edit_result.count("bitmap") == 4: + test.log.debug("Edit checkpoint succeeded!") + else: + test.fail("Expect 'bitmap' for four times, but not found!") + except (aexpect.ShellError, aexpect.ExpectError) as details: + log = session.get_output() + session.close() + test.fail("Edit checkpoint failed: %s" % details) + # Cancel the test if libvirt version is too low if not libvirt_version.version_compare(6, 0, 0): test.cancel("Current libvirt version doesn't support " @@ -310,6 +351,9 @@ def prepare_checkpoints(disk="vdb", num=1, cp_prefix="test_checkpoint_"): if ((vm_name in stdout and cmd_flag == "--without-checkpoint") or (vm_name not in stdout and cmd_flag == "--with-checkpoint")): test.fail("virsh list with '%s' contains wrong data" % cmd_flag) + elif checkpoint_cmd == "checkpoint_edit": + edit_checkpoint(vm_name, current_checkpoints[0]) + edit_checkpoint(vm_name, current_checkpoints[0], restore=True) # Make sure vm is running and check checkpoints can be normally deleted if not vm.is_alive(): vm.start() From 1a3c4951e1edc3ad52cdd2994d62399d47f504bc Mon Sep 17 00:00:00 2001 From: lcheng Date: Thu, 5 Jun 2025 09:16:35 +0800 Subject: [PATCH 1000/1055] migration: Fix decode failure Fix following issue: 'utf-8' codec can't decode byte 0xff in position 1465040: invalid start byte The ignoring will not impact some key strings matched in the log. Signed-off-by: lcheng --- .../migration_with_vtpm_state_on_block_dev.cfg | 4 ++-- .../migration_with_vtpm_state_on_block_dev.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.cfg b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.cfg index 2a732ce4721..582a7aa9d3b 100644 --- a/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.cfg +++ b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.cfg @@ -33,7 +33,7 @@ dst_secret_value_path = "/var/tmp/dst_secretinfile" status_error = "no" func_supported_since_libvirt_ver = (10, 10, 0) - block_path = "/iscsiswtpm" + block_path = "/var/iscsiswtpm" libvirtd_debug_file = '/var/log/libvirt/virtqemud.log' libvirtd_debug_filters = "1:*" libvirtd_debug_level = "1" @@ -62,7 +62,7 @@ - auto_create_file: dir_name = "mig_vtpm_auto_file_test" file_name = "${dir_name}2-00.permall" - block_dir = "${block_path}/{dir_name}" + block_dir = "${block_path}/${dir_name}" tpm_dict = {'tpm_model': '${tpm_model}', 'backend': {'backend_type': 'emulator', 'backend_version': '2.0', 'encryption_secret': '0051c505-1ad0-4d77-9b3e-360c8f5e3b86', 'source': {'type': 'file', 'path': '${block_dir}/${file_name}'}}} check_lables_1 = '[r"tss tss system_u:object_r:virt_var_lib_t:s0.*.", r"root root unconfined_u:object_r:default_t:s0.*.."]' check_lables_2 = '[r"tss tss system_u:object_r:svirt_image_t:s0:c.*${file_name}"]' diff --git a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.py b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.py index bc24a59d2a6..e146cfb6afa 100644 --- a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.py +++ b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.py @@ -80,7 +80,7 @@ def check_capability(params, test): :param params: Dictionary with the test parameters :param test: test object """ - with open(params.get("libvirtd_debug_file"), 'r') as f: + with open(params.get("libvirtd_debug_file"), 'r', errors='ignore') as f: log_file = f.read() if migration_vtpm.compare_swtpm_version(0, 10): cmd = "swtpm socket --print-capabilities" @@ -89,7 +89,7 @@ def check_capability(params, test): test.fail(f"Not found 'tpmstate-opt-lock' in {ret}") check_items(eval(params.get("unexpected_list_1", "[]")), log_file, test, str_in_log=False) - check_items(eval(params.get("expected_list_1"), "[]"), log_file, test) + check_items(eval(params.get("expected_list_1", "[]")), log_file, test) else: if libvirt_version.version_compare(11, 0, 0): check_items(eval(params.get("expected_list_2", "[]")), log_file, test) From 040f711bf56e8bbbd2226f14b423da59d029683d Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Thu, 20 Mar 2025 03:13:16 -0400 Subject: [PATCH 1001/1055] Remove dhclient from tests dhclient is deprecated on RHEL 10 and will have to be removed from our code base. Use avocado-vt functions instead of invoking it directly so this can be handled from avocado-vt when needed. Signed-off-by: Haijiao Zhao --- .../update_device/update_iface_source.py | 2 +- .../virtual_network_multivms.py | 25 +------------------ 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_source.py b/libvirt/tests/src/virtual_network/update_device/update_iface_source.py index 1eb3e8fae7d..47fa1d8eef8 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_source.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_source.py @@ -76,7 +76,7 @@ def run(test, params, env): vm_iface = utils_net.get_linux_ifname(session, mac) LOG.debug(f'Interface inside vm: {vm_iface}') - LOG.info('Run dhclient to refresh network.') + LOG.info('Run command to refresh network.') utils_net.restart_guest_network(session, mac) vm_iface_info = utils_net.get_linux_iface_info( diff --git a/libvirt/tests/src/virtual_network/virtual_network_multivms.py b/libvirt/tests/src/virtual_network/virtual_network_multivms.py index 6b5f84c1770..6713d2dab83 100644 --- a/libvirt/tests/src/virtual_network/virtual_network_multivms.py +++ b/libvirt/tests/src/virtual_network/virtual_network_multivms.py @@ -23,26 +23,6 @@ logging = log.getLogger('avocado.' + __name__) -def create_bridge(br_name, iface_name): - """ - Create bridge attached to physical interface - - :param br_name: bridge to be created - :param iface_name: physical interface name - :return: - """ - # Make sure the bridge not exist - if libvirt.check_iface(br_name, "exists", "--all"): - return - - # Create bridge using commands - utils_package.package_install('tmux') - cmd = 'tmux -c "ip link add name {0} type bridge; ip link set {1} up;' \ - ' ip link set {1} master {0}; ip link set {0} up; pkill dhclient; ' \ - 'sleep 6; dhclient {0}; ifconfig {1} 0"'.format(br_name, iface_name) - process.run(cmd, shell=True, verbose=True) - - def ping_func(session, **expect): """ Check whether ping result meet expectation @@ -424,7 +404,4 @@ def pause_resume_vm(vm_name): # Remove test bridge if bridge_created: - cmd = 'tmux -c "ip link set {1} nomaster; ip link delete {0};' \ - 'pkill dhclient; sleep 6; dhclient {1}"'.format( - bridge_name, iface_name) - process.run(cmd, shell=True, verbose=True, ignore_status=True) + utils_net.delete_linux_bridge_tmux(bridge_name, iface_name) From bc8af73bf7ccbd96463cb17f47d8076a48154007 Mon Sep 17 00:00:00 2001 From: Haijiao Zhao Date: Tue, 5 Nov 2024 03:34:10 -0500 Subject: [PATCH 1002/1055] Update case:update interface type live - VIRT-298342 - [update-device] live update interface with different interface type - bridge/direct type Furthermore, use get_iface_xml_inst instead because it contains the get_devices function and logging, making code cleaner Signed-off-by: Haijiao Zhao --- .../update_device/update_iface_type_live.cfg | 25 +++++++++- .../update_device/update_iface_type_live.py | 48 ++++++++++++++----- 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/update_device/update_iface_type_live.cfg b/libvirt/tests/cfg/virtual_network/update_device/update_iface_type_live.cfg index df0e02f7a1b..339f0ad7eb9 100644 --- a/libvirt/tests/cfg/virtual_network/update_device/update_iface_type_live.cfg +++ b/libvirt/tests/cfg/virtual_network/update_device/update_iface_type_live.cfg @@ -3,12 +3,35 @@ host_iface = start_vm = no timeout = 240 + extra_attrs = {} + check_link = yes variants: - bridge_type: iface_type = bridge create_linux_br = yes net_attrs = {'name': net_name, 'bridge': {'name': linux_br}, 'forward': {'mode': 'bridge'}} + - ovsbr_type: + iface_type = bridge + create_ovs_br = yes + net_attrs = {'name': net_name, 'bridge': {'name': linux_br}, 'forward': {'mode': 'bridge'}} + extra_attrs = {'virtualport': {'type': 'openvswitch'}} + variants: + - default: + - no_change: + check_link = no + with_iface_xml = yes + variants operation: + - default: + - attach_device: + - attach_interface: + net_attrs = {'name': net_name, 'bridge': {'name': linux_br}, 'forward': {'mode': 'bridge'}, 'virtualport_type': 'openvswitch'} + variants xml_opt: + - active: + xml_opt = + - inactive: + xml_opt = --inactive + - direct_type: iface_type = direct net_attrs = {'name': net_name, 'forward': {'mode': 'bridge'}, 'forward_interface': [{'dev': host_iface}]} - iface_attrs = {'model': 'virtio', 'type_name': 'network', 'source': {'network': net_name}, 'mac_address': mac} + iface_attrs = {'model': 'virtio', 'type_name': 'network', 'source': {'network': net_name}, 'mac_address': mac, **${extra_attrs}} diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_type_live.py b/libvirt/tests/src/virtual_network/update_device/update_iface_type_live.py index 3e26ab6e625..bf3b9cc5c79 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_type_live.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_type_live.py @@ -8,6 +8,8 @@ from virttest.utils_libvirt import libvirt_network from virttest.utils_libvirt import libvirt_vmxml +from provider.virtual_network import network_base + VIRSH_ARGS = {'ignore_status': False, 'debug': True} LOG = logging.getLogger('avocado.' + __name__) @@ -21,7 +23,10 @@ def run(test, params, env): vm = env.get_vm(vm_name) rand_id = utils_misc.generate_random_string(3) create_linux_br = 'yes' == params.get('create_linux_br', 'no') - linux_br = 'linux_br_' + rand_id + create_ovs_br = 'yes' == params.get('create_ovs_br', 'no') + check_link = 'yes' == params.get('check_link', 'yes') + linux_br = 'br_' + rand_id + operation = params.get('operation', 'attach_device') net_name = 'net_' + rand_id mac = utils_net.generate_mac_address_simple() iface_attrs = eval(params.get('iface_attrs', '{}')) @@ -42,35 +47,52 @@ def run(test, params, env): if create_linux_br: LOG.debug(f'Create linux bridge: {linux_br}') utils_net.create_linux_bridge_tmux(linux_br, host_iface) + if create_ovs_br: + LOG.debug(f'Create ovs bridge: {linux_br}') + utils_net.create_ovs_bridge(linux_br) libvirt_network.create_or_del_network(net_attrs) LOG.debug(f'Network xml:\n' f'{virsh.net_dumpxml(net_attrs["name"]).stdout_text}') - vm.start() - session = vm.wait_for_serial_login() - iface = libvirt_vmxml.create_vm_device_by_type( 'interface', iface_attrs) - LOG.debug(f'Interface to attach:\n{iface}') + LOG.debug(f'Interface to attach/add:\n{iface.xmltreefile.str_out()}') - virsh.attach_device(vm_name, iface.xml, **VIRSH_ARGS) + if operation == 'default': + vmxml.add_device(iface) + vmxml.sync() + + vm.start() + session = vm.wait_for_serial_login() + + if operation == 'attach_device': + virsh.attach_device(vm_name, iface.xml, + flagstr='--persistent', **VIRSH_ARGS) + elif operation == 'attach_interface': + virsh.attach_interface( + vm_name, f'--source {net_name} --model virtio --type network --persistent', **VIRSH_ARGS) vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) - iface_at = vmxml.get_devices('interface')[0] - LOG.debug(f'Interface xml after attached to vm:\n{iface_at}') - LOG.debug(f'Interface type after attached to vm:\n' - f'{iface_at.type_name}') + iface_at = network_base.get_iface_xml_inst(vm_name, 'after attach') + LOG.debug(f'Interface type after attached to vm: {iface_at.type_name}') if iface_at.type_name != iface_type: test.fail(f'Interface type should change to {iface_type}') LOG.debug('Update interface link state') link_state = 'down' iface.setup_attrs(**{'link_state': link_state}) - LOG.debug(iface) + if params.get('with_iface_xml') == 'yes': + xml_opt = params.get('xml_opt', '') + iface = network_base.get_iface_xml_inst( + vm_name, f'on vm ({xml_opt})', options=f'{xml_opt}') + LOG.debug(f'Update iface with xml:\n{iface}') virsh.update_device(vm_name, iface.xml, **VIRSH_ARGS) vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) - iface_update = vmxml.get_devices('interface')[0] + iface_update = network_base.get_iface_xml_inst(vm_name, 'after update') + if not check_link: + return + LOG.debug(f'Link state of interface after update: ' f'{iface_update.link_state}') if iface_update.link_state != link_state: @@ -95,3 +117,5 @@ def run(test, params, env): if create_linux_br: LOG.debug(f'Delete linux bridge: {linux_br}') utils_net.delete_linux_bridge_tmux(linux_br, host_iface) + if create_ovs_br: + utils_net.delete_ovs_bridge(linux_br) From abe2901e4d1c334191cb81095bc41219034f8a17 Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle <54858857+smitterl@users.noreply.github.com> Date: Fri, 6 Jun 2025 12:14:13 +0200 Subject: [PATCH 1003/1055] hypervisor_cpu_models: add test for new command (#6324) * hypervisor_cpu_models: add test for new command New command added in libvirt 11.2.0. Signed-off-by: Sebastian Mitterle * hypervisor_cpu_model: enable on x86_64 Add config for x86_64. Signed-off-by: Sebastian Mitterle * hypervisor_cpu_model: enable aarch64 Add config to enable aarch64 coverage. Signed-off-by: Sebastian Mitterle * fix libvirt_version check Config was available but forgot to check version in code with that config. Signed-off-by: Sebastian Mitterle * cfg: remove unused parameters Initially this configuration was reused from a similar test case. However, these parameters are not necessary anymore. Signed-off-by: Sebastian Mitterle --------- Signed-off-by: Sebastian Mitterle --- .../host/virsh_hypervisor_cpu_models.cfg | 30 +++++++++++++ .../host/virsh_hypervisor_cpu_models.py | 45 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 libvirt/tests/cfg/virsh_cmd/host/virsh_hypervisor_cpu_models.cfg create mode 100644 libvirt/tests/src/virsh_cmd/host/virsh_hypervisor_cpu_models.py diff --git a/libvirt/tests/cfg/virsh_cmd/host/virsh_hypervisor_cpu_models.cfg b/libvirt/tests/cfg/virsh_cmd/host/virsh_hypervisor_cpu_models.cfg new file mode 100644 index 00000000000..45a1d711f12 --- /dev/null +++ b/libvirt/tests/cfg/virsh_cmd/host/virsh_hypervisor_cpu_models.cfg @@ -0,0 +1,30 @@ +- virsh.hypervisor_cpu_models: + type = virsh_hypervisor_cpu_models + func_supported_since_libvirt_ver = (11, 2, 0) + options = "" + start_vm = no + variants: + - positive_test: + status_error = "no" + variants: + - default: + - all: + options = "--all" + - valid_parameter_values: + s390-virtio: + options = "--all --arch s390x --machine s390-ccw-virtio --emulator /usr/libexec/qemu-kvm --virttype kvm" + x86_64: + options = "--all --arch x86_64 --machine q35 --emulator /usr/libexec/qemu-kvm --virttype kvm" + aarch64: + options = "--all --arch aarch64 --machine virt --emulator /usr/libexec/qemu-kvm --virttype kvm" + - negative_test: + status_error = "yes" + variants: + - invalid_arch: + options = "--arch invalid" + - invalid_virttype: + options = "--virttype invalid" + - invalid_machine: + options = "--machine invalid" + - invalid_emulator: + options = "--virttype invalid" diff --git a/libvirt/tests/src/virsh_cmd/host/virsh_hypervisor_cpu_models.py b/libvirt/tests/src/virsh_cmd/host/virsh_hypervisor_cpu_models.py new file mode 100644 index 00000000000..03b75e49941 --- /dev/null +++ b/libvirt/tests/src/virsh_cmd/host/virsh_hypervisor_cpu_models.py @@ -0,0 +1,45 @@ +import logging as log + +from virttest import libvirt_version +from virttest import virsh +from virttest.utils_test import libvirt as utlv +from virttest.libvirt_xml.domcapability_xml import DomCapabilityXML + + +logging = log.getLogger("avocado." + __name__) + + +def compare_cpu_model_with_domcapabilities(test, params, result): + """ + Compare the available CPUs with those returned by domcapabilities. + + :param test: the test instance + :param params: the test parameters + :param result: the output from hypervisor-cpu-models + """ + xml = DomCapabilityXML() + hc_models = [x for x in result.stdout_text.split("\n") if x != ""] + if "--all" in params.get("options"): + xpath = "/cpu/mode/model" + else: + xpath = "/cpu/mode/model[@usable='yes']" + dc_models = [str(x.text) for x in xml.xmltreefile.findall(xpath)] + difference = set(dc_models) ^ set(hc_models) + if difference and difference != set(""): + test.fail(f"Model list should be identical. Difference: {difference}") + test.log.debug("All models were found in hypervisor-cpu-models") + + +def run(test, params, env): + """ + Test command virsh hypervisor-cpu-models + """ + options = params.get("options", "") + status_error = "yes" == params.get("status_error", "no") + + libvirt_version.is_libvirt_feature_supported(params) + + result = virsh.hypervisor_cpu_models(options, ignore_status=True, debug=True) + utlv.check_exit_status(result, expect_error=status_error) + if not status_error: + compare_cpu_model_with_domcapabilities(test, params, result) From e002d4d137c157ce7cb0a8e53222e7fbfc6ad965 Mon Sep 17 00:00:00 2001 From: cliping Date: Fri, 6 Jun 2025 18:32:19 +0800 Subject: [PATCH 1004/1055] migration: Update external tpm case (#6351) Running chcon on a read-only system will fail. So update case. Signed-off-by: lcheng --- .../migration_with_external_tpm.cfg | 5 +-- .../migration_with_external_tpm.py | 40 +++++++------------ 2 files changed, 16 insertions(+), 29 deletions(-) diff --git a/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_external_tpm.cfg b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_external_tpm.cfg index 7807974850a..aa8771b8380 100644 --- a/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_external_tpm.cfg +++ b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_external_tpm.cfg @@ -4,7 +4,6 @@ storage_type = 'nfs' setup_local_nfs = 'yes' disk_type = "file" - disk_source_protocol = "netfs" mnt_path_name = ${nfs_mount_dir} # Console output can only be monitored via virsh console output only_pty = True @@ -26,6 +25,7 @@ client_pwd = "${migrate_source_pwd}" status_error = "no" transport_type = "ssh" + migrate_desturi_type = "ssh" virsh_migrate_desturi = "qemu+ssh://${migrate_dest_host}/system" # vtpm setting func_supported_since_libvirt_ver = (9, 0, 0) @@ -35,11 +35,8 @@ aarch64: tpm_dict = {'tpm_model': 'tpm-tis', 'backend': {'backend_type': 'external', 'source': {'type': 'unix', 'mode': 'connect', 'path': '/var/tmp/guest-swtpm.sock'}}} statedir = "/var/tmp/mytpm" - swtpm_setup_path = '/usr/bin/swtpm_setup' - swtpm_path = '/usr/bin/swtpm' tpm_cmd = "tpm2_getrandom --hex 16" tpm_security_contexts= "user_tmp_t" - variants: - persistent_and_p2p: virsh_migrate_options = "--live --p2p --verbose --undefinesource --persistent" diff --git a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_external_tpm.py b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_external_tpm.py index 3d02e119fb0..6ac82ea2a88 100644 --- a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_external_tpm.py +++ b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_external_tpm.py @@ -11,7 +11,6 @@ from virttest.libvirt_xml import vm_xml from virttest.utils_libvirt import libvirt_vmxml -from virttest.utils_test import libvirt from provider.migration import base_steps @@ -84,41 +83,35 @@ def launch_external_swtpm(params, test, skip_setup=False, on_remote=False): tpm_dict = eval(params.get('tpm_dict', '{}')) source_socket = tpm_dict['backend']['source']['path'] statedir = params.get("statedir") - swtpm_setup_path = params.get("swtpm_setup_path") - swtpm_path = params.get("swtpm_path") test.log.info("Launch external swtpm process: (on_remote: %s)", on_remote) if not skip_setup: - cmd1 = 'chcon -t virtd_exec_t %s' % swtpm_setup_path - cmd2 = 'chcon -t virtd_exec_t %s' % swtpm_path if on_remote: remote.run_remote_cmd("rm -rf %s" % statedir, params) remote.run_remote_cmd("mkdir %s" % statedir, params) - remote.run_remote_cmd(cmd1, params) - remote.run_remote_cmd(cmd2, params) else: if os.path.exists(statedir): shutil.rmtree(statedir) os.mkdir(statedir) process.run("ls -lZd %s" % statedir) - process.run(cmd1, ignore_status=False, shell=True) - process.run(cmd2, ignore_status=False, shell=True) - cmd3 = "systemd-run %s --tpm2 --tpmstate %s --create-ek-cert --create-platform-cert --overwrite" % (swtpm_setup_path, statedir) - cmd4 = "systemd-run %s socket --ctrl type=unixio,path=%s,mode=0600 --tpmstate dir=%s,mode=0600 --tpm2 --terminate" % (swtpm_path, source_socket, statedir) + cmd1 = "swtpm_setup --tpm2 --tpmstate %s --create-ek-cert --create-platform-cert --overwrite" % statedir try: if not skip_setup: if on_remote: - remote.run_remote_cmd(cmd3, params) + remote.run_remote_cmd(cmd1, params) else: - process.run(cmd3, ignore_status=False, shell=True) + process.run(cmd1, ignore_status=False, shell=True) if on_remote: - remote.run_remote_cmd(cmd4, params) + cmd2 = "nohup swtpm socket --ctrl type=unixio,path=%s,mode=0600 --tpmstate dir=%s,mode=0600 --tpm2 --terminate > /dev/null 2>&1 &" % (source_socket, statedir) + remote.run_remote_cmd(cmd2, params) remote.run_remote_cmd('chcon -t svirt_image_t %s' % source_socket, params) remote.run_remote_cmd('chown qemu:qemu %s' % source_socket, params) else: - process.run(cmd4, ignore_status=False, shell=True) + cmd2 = "swtpm socket --ctrl type=unixio,path=%s,mode=0600 --tpmstate dir=%s,mode=0600 --tpm2 --terminate &" % (source_socket, statedir) + process.run(cmd2, ignore_status=False, shell=True, ignore_bg_processes=True) + process.run("ps aux|grep 'swtpm socket'|grep -v avocado-runner-avocado-vt|grep -v grep", ignore_status=True, shell=True) # Make sure the socket is created - utils_misc.wait_for(lambda: os.path.isdir(source_socket), timeout=3) + utils_misc.wait_for(lambda: os.path.exists(source_socket), timeout=3) process.run('chcon -t svirt_image_t %s' % source_socket, ignore_status=False, shell=True) process.run('chown qemu:qemu %s' % source_socket, ignore_status=False, shell=True) except Exception as err: @@ -177,7 +170,8 @@ def setup_test(): """ tpm_security_contexts = params.get("tpm_security_contexts") - libvirt.set_vm_disk(vm, params) + test.log.debug("Setup steps.") + migration_obj.setup_connection() launch_external_swtpm(params, test) launch_external_swtpm(params, test, skip_setup=False, on_remote=True) setup_vtpm(params, test, vm) @@ -211,18 +205,14 @@ def cleanup_test(): Cleanup steps """ - swtpm_setup_path = params.get("swtpm_setup_path") - swtpm_path = params.get("swtpm_path") statedir = params.get("statedir") - cmd1 = "restorecon %s" % swtpm_setup_path - cmd2 = "restorecon %s" % swtpm_path - process.run(cmd1, ignore_status=False, shell=True) - process.run(cmd2, ignore_status=False, shell=True) + remote.run_remote_cmd('pkill swtpm', params, ignore_status=True) + remote.run_remote_cmd("rm -rf /var/lib/swtpm-localca/*", params, ignore_status=True) + process.run("pkill swtpm", shell=True, ignore_status=True) + process.run("rm -rf /var/lib/swtpm-localca/*", shell=True, ignore_status=True) if os.path.exists(statedir): shutil.rmtree(statedir) - remote.run_remote_cmd(cmd1, params) - remote.run_remote_cmd(cmd2, params) remote.run_remote_cmd("rm -rf %s" % statedir, params) migration_obj.cleanup_connection() From 9bb914a5840c700592428670740a927145670af7 Mon Sep 17 00:00:00 2001 From: cliping Date: Tue, 10 Jun 2025 07:57:25 +0800 Subject: [PATCH 1005/1055] migration: Update retain sparsity case (#6360) According to RHEL-88435, update script. Signed-off-by: lcheng --- .../migration_retain_sparsity.cfg | 21 ++++++------ .../migration_retain_sparsity.py | 32 +++++++++++++++++++ 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/libvirt/tests/cfg/migration_with_copy_storage/migration_retain_sparsity.cfg b/libvirt/tests/cfg/migration_with_copy_storage/migration_retain_sparsity.cfg index 16b1b3a70d0..39d0e18fc04 100644 --- a/libvirt/tests/cfg/migration_with_copy_storage/migration_retain_sparsity.cfg +++ b/libvirt/tests/cfg/migration_with_copy_storage/migration_retain_sparsity.cfg @@ -31,7 +31,10 @@ disk_path = "/var/lib/avocado/data/avocado-vt/images" target_dev_1 = "sda" virsh_migrate_options = "--live --p2p --verbose --migrate-disks-detect-zeroes ${target_dev_1}" - ceph_pool_name = "migration-pool" + mon_host = "EXAMPLE_MON_HOST" + client_name = "EXAMPLE_CLIENT_NAME" + client_key = "EXAMPLE_CLIENT_KEY" + ceph_pool_name = "migration-retain-sparsity-pool" check_disk_after_mig = "yes" check_disk_kname_after_mig = "${target_dev_1}" libvirtd_file_type = "virtqemud" @@ -47,8 +50,8 @@ variants: - src1_rbd: src_driver_type_1 = "rbd" - disk_size = "100M" - dd_count = "10" + disk_size = "300M" + dd_count = "30" src_disk1_name = "retain_sparsity_test_disk1" src_disk1_dict = {"device": "disk", "type_name": "block", "driver": {"name": "qemu", "type": "raw"}, "target": {"dev": "${target_dev_1}", "bus": "scsi"}} - src1_raw: @@ -61,17 +64,17 @@ src_disk1_dict = {"device": "disk", "type_name": "file", "driver": {"name": "qemu", "type": "qcow2"}, "target": {"dev": "${target_dev_1}", "bus": "scsi"}, "source": {"attrs": {"file": "${disk_path}/${src_disk1_name}"}}} variants: - dest1_rbd: - disk_size = "100M" - dd_count = "10" + disk_size = "300M" + dd_count = "30" dest_device_type_1 = "block" dest_driver_type_1 = "rbd" dest_disk1_name = "retain_sparsity_test_disk2" - dest_disk1_dict = {"device": "disk", "type_name": "${dest_device_type_1}", "driver": {"name": "qemu", "type": "raw"}, "target": {"dev": "${target_dev_1}", "bus": "scsi"}} + dest_disk1_dict = {"device": "disk", "type_name": "${dest_device_type_1}", "driver": {"name": "qemu", "type": "raw", "discard": "unmap"}, "target": {"dev": "${target_dev_1}", "bus": "scsi"}} - dest1_raw: dest_device_type_1 = "file" dest_driver_type_1 = "raw" dest_disk1_name = "${src_disk1_name}" - dest_disk1_dict = {"device": "disk", "type_name": "${dest_device_type_1}", "driver": {"name": "qemu", "type": "raw"}, "target": {"dev": "${target_dev_1}", "bus": "scsi"}, "source": {"attrs": {"file": "${disk_path}/${dest_disk1_name}"}}} + dest_disk1_dict = {"device": "disk", "type_name": "${dest_device_type_1}", "driver": {"name": "qemu", "type": "raw", "discard": "unmap"}, "target": {"dev": "${target_dev_1}", "bus": "scsi"}, "source": {"attrs": {"file": "${disk_path}/${dest_disk1_name}"}}} - dest1_qcow2: dest_device_type_1 = "file" dest_driver_type_1 = "qcow2" @@ -93,5 +96,5 @@ dest_driver_type_2 = "raw" - dest2_qcow2: dest_driver_type_2 = "qcow2" - src_disk2_dict = {"device": "disk", "type_name": "file", "driver": {"name": "qemu", "type": "${src_driver_type_2}"}, "target": {"dev": "${target_dev_2}", "bus": "scsi"}, "source": {"attrs": {"file": "${disk_path}/${disk2_name}"}}} - dest_disk2_dict = {"device": "disk", "type_name": "file", "driver": {"name": "qemu", "type": "${dest_driver_type_2}"}, "target": {"dev": "${target_dev_2}", "bus": "scsi"}, "source": {"attrs": {"file": "${disk_path}/${disk2_name}"}}} + src_disk2_dict = {"device": "disk", "type_name": "file", "driver": {"name": "qemu", "type": "${src_driver_type_2}", "discard": "unmap"}, "target": {"dev": "${target_dev_2}", "bus": "scsi"}, "source": {"attrs": {"file": "${disk_path}/${disk2_name}"}}} + dest_disk2_dict = {"device": "disk", "type_name": "file", "driver": {"name": "qemu", "type": "${dest_driver_type_2}", "discard": "unmap"}, "target": {"dev": "${target_dev_2}", "bus": "scsi"}, "source": {"attrs": {"file": "${disk_path}/${disk2_name}"}}} diff --git a/libvirt/tests/src/migration_with_copy_storage/migration_retain_sparsity.py b/libvirt/tests/src/migration_with_copy_storage/migration_retain_sparsity.py index 484723cd8ed..c475e739d79 100644 --- a/libvirt/tests/src/migration_with_copy_storage/migration_retain_sparsity.py +++ b/libvirt/tests/src/migration_with_copy_storage/migration_retain_sparsity.py @@ -13,6 +13,7 @@ from avocado.utils import process +from virttest import ceph from virttest import data_dir from virttest import remote from virttest import utils_misc @@ -164,6 +165,27 @@ def get_disk_size(disk_file, remote_host=False, params=False): return ret.split('\n')[3].split(':')[1].strip() +def copy_file_to_remote(params, file_list): + """ + Copy files from source host to target host + + :param params: dictionary with the test parameter + :param file_list: list, the list of files + """ + server_ip = params.get("server_ip") + server_user = params.get("server_user") + server_pwd = params.get("server_pwd") + + remote_session = remote.remote_login("ssh", server_ip, "22", + server_user, server_pwd, + r'[$#%]') + for f in file_list: + utils_misc.make_dirs(os.path.dirname(f), remote_session) + remote.copy_files_to(server_ip, 'scp', server_user, server_pwd, + '22', f, f) + remote_session.close() + + def run(test, params, env): """ To verify that live migration with copying storage can retain sparsity with @@ -297,6 +319,10 @@ def _remove_disk_remote(disk_name): _remove_disk_local(src_disk1_name) if disk2_name: _remove_disk_local(disk2_name) + for rm_file in [ceph_cfg, keyring_file]: + if os.path.exists(rm_file): + os.remove(rm_file) + remote.run_remote_cmd(f"rm -f {rm_file}", params, ignore_status=True) base_steps.cleanup_disks_remote(params, vm) vm_name = params.get("migrate_main_vm") @@ -304,9 +330,15 @@ def _remove_disk_remote(disk_name): old_disk_size = [] src_rbd_dev = None dest_rbd_dev = None + ceph_cfg = '' + keyring_file = '' vm = env.get_vm(vm_name) migration_obj = base_steps.MigrationBase(test, vm, params) + # Create config file if it doesn't exist + ceph_cfg = ceph.create_config_file(params.get("mon_host")) + keyring_file = ceph.create_keyring_file(params.get("client_name"), params.get('client_key')) + copy_file_to_remote(params, [ceph_cfg, keyring_file]) try: setup_test() From cf24b1471220231ea75d2c9315426bfef120e5e7 Mon Sep 17 00:00:00 2001 From: cliping Date: Tue, 10 Jun 2025 07:58:49 +0800 Subject: [PATCH 1006/1055] migration: Fix incorrect path issue (#6363) Due to an incorrect restorecon path, the expected matching string could not be found. So update script. Signed-off-by: lcheng --- .../migration_with_vtpm_state_on_block_dev.cfg | 2 +- .../migration_with_vtpm_state_on_block_dev.py | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.cfg b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.cfg index 582a7aa9d3b..652e3b8a2bb 100644 --- a/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.cfg +++ b/libvirt/tests/cfg/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.cfg @@ -64,6 +64,6 @@ file_name = "${dir_name}2-00.permall" block_dir = "${block_path}/${dir_name}" tpm_dict = {'tpm_model': '${tpm_model}', 'backend': {'backend_type': 'emulator', 'backend_version': '2.0', 'encryption_secret': '0051c505-1ad0-4d77-9b3e-360c8f5e3b86', 'source': {'type': 'file', 'path': '${block_dir}/${file_name}'}}} - check_lables_1 = '[r"tss tss system_u:object_r:virt_var_lib_t:s0.*.", r"root root unconfined_u:object_r:default_t:s0.*.."]' + check_lables_1 = '[r"tss tss system_u:object_r:virt_var_lib_t:s0.*.", r"root root unconfined_u:object_r:virt_var_lib_t:s0.*.."]' check_lables_2 = '[r"tss tss system_u:object_r:svirt_image_t:s0:c.*${file_name}"]' check_lables_3 = '[r"tss tss system_u:object_r:virt_var_lib_t:s0.*${file_name}"]' diff --git a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.py b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.py index e146cfb6afa..6c7dabb8130 100644 --- a/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.py +++ b/libvirt/tests/src/migration/migration_with_vtpm/migration_with_vtpm_state_on_block_dev.py @@ -139,6 +139,10 @@ def prepare_iscsi_disk(params, test, block_dev): process.run(cmd, shell=True, verbose=True) remote.run_remote_cmd(cmd, params, ignore_status=False) + cmd = f'cat /etc/selinux/targeted/contexts/files/file_contexts.local|grep iscsiswtpm' + process.run(cmd, shell=True, verbose=True) + remote.run_remote_cmd(cmd, params, ignore_status=False) + cmd = f"mkfs.xfs -f {dev_target}" remote.run_remote_cmd(cmd, params, ignore_status=False) @@ -207,13 +211,13 @@ def setup_auto_create_file(): test.log.info("Setup steps for auto_create_file.") process.run(f"mkdir {block_dir}", shell=True, verbose=True) utils_disk.mount(dev_src, block_dir) - process.run(f"restorecon -Rv {block_dir}", shell=True, verbose=True) + process.run(f"restorecon -Rv {block_path}", shell=True, verbose=True) process.run(f"chown tss:tss {block_dir}", shell=True, verbose=True) server_session = remote.wait_for_login("ssh", server_ip, "22", server_user, server_pwd, r"[\#\$]\s*$") remote.run_remote_cmd(f"mkdir {block_dir}", params, ignore_status=False) utils_disk.mount(dev_target, block_dir, session=server_session) - remote.run_remote_cmd(f"restorecon -Rv {block_dir}", params, ignore_status=False) + remote.run_remote_cmd(f"restorecon -Rv {block_path}", params, ignore_status=False) remote.run_remote_cmd(f"chown tss:tss {block_dir}", params, ignore_status=False) server_session.close() From 7dca9b8295e6f323f2900e31dae733cf53622009 Mon Sep 17 00:00:00 2001 From: cliping Date: Tue, 10 Jun 2025 08:04:54 +0800 Subject: [PATCH 1007/1055] migration: Fix the incorrect path issue (#6362) Signed-off-by: lcheng --- libvirt/tests/src/migration/migrate_mem.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/src/migration/migrate_mem.py b/libvirt/tests/src/migration/migrate_mem.py index b42be712bf3..acc31c58261 100644 --- a/libvirt/tests/src/migration/migrate_mem.py +++ b/libvirt/tests/src/migration/migrate_mem.py @@ -254,6 +254,9 @@ def verify_test_mem_nvdimm(vm, params, test): vm_session.cmd("echo '{}.back' > /mnt/nvdimm_test_back".format(expected_content)) vm_session.cmd('umount /mnt') + # Cleanup nvram file on source host + vm_name = params.get("migrate_main_vm") + process.run(f"rm -rf /var/lib/libvirt/qemu/nvram/{vm_name}_VARS.fd", shell=True, ignore_status=True) def verify_test_back_default(vm, params, test): @@ -333,7 +336,9 @@ def cleanup_test_mem_nvdimm(vm, params, test): """ cleanup_test_default(vm, params, test) test.log.debug("Recover test environment for memory nvdimm device test") - os.remove(params.get('nfs_mount_src') + '/nvdimm') + nvdimm_file_path = params.get("nvdimm_file_path") + if os.path.exists(nvdimm_file_path): + os.remove(nvdimm_file_path) def run_migration_back(params, test): From a42f4eb8cc92f973cd3f93b4d5f6470db492654a Mon Sep 17 00:00:00 2001 From: cliping Date: Tue, 10 Jun 2025 08:06:20 +0800 Subject: [PATCH 1008/1055] migration: Fix the SSH connection issue (#6361) Add the SSH connection steps. Signed-off-by: lcheng --- .../async_job/query_domain_job_info.cfg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libvirt/tests/cfg/migration_with_copy_storage/async_job/query_domain_job_info.cfg b/libvirt/tests/cfg/migration_with_copy_storage/async_job/query_domain_job_info.cfg index d23c26fdd60..3304ded2545 100644 --- a/libvirt/tests/cfg/migration_with_copy_storage/async_job/query_domain_job_info.cfg +++ b/libvirt/tests/cfg/migration_with_copy_storage/async_job/query_domain_job_info.cfg @@ -20,6 +20,9 @@ client_user = "root" client_pwd = "${migrate_source_pwd}" check_network_accessibility_after_mig = "yes" + storage_type = 'file' + start_vm = "yes" + setup_ssh = "yes" migrate_desturi_port = "16509" migrate_desturi_type = "tcp" virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" From 0ae1b9dc4aba2766726ccb64e7c5fc6b5a4a6222 Mon Sep 17 00:00:00 2001 From: meinaLi Date: Tue, 10 Jun 2025 05:23:37 -0400 Subject: [PATCH 1009/1055] Inc_backup: fix "Backup job should be canceled but not" error Sometimes we can't destroy guest after backup because of "resource busy". This mainly happens with backup_to_block case. Because block type backup file may take more time than file type backup file on backup-begin process, which causes the resouce busy. So this PR is changed the destroy_vm test to backup_to_file. Signed-off-by: meinaLi --- .../incremental_backup_push_mode.cfg | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg b/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg index 93c29585d5a..12d1d6486c5 100644 --- a/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg +++ b/libvirt/tests/cfg/incremental_backup/incremental_backup_push_mode.cfg @@ -24,6 +24,12 @@ variants: - target_file_not_exist: prepare_target_file = "no" + - destroy_vm: + only original_disk_local.coldplug_disk.backup_to_raw.backup_to_file + error_operation = "destroy_vm" + expect_backup_canceled = "yes" + original_disk_size = "5000M" + dd_count = "2000" - positive_test: - not_reuse_target_file: - backup_to_block: @@ -37,11 +43,6 @@ backup_error = "yes" prepare_target_blkdev = "no" target_blkdev_path = "/dev/not/exist" - - destroy_vm: - only original_disk_local.coldplug_disk.backup_to_raw.backup_to_block - expect_backup_canceled = "yes" - original_disk_size = "5000M" - dd_count = "2000" - kill_qemu: only original_disk_local.hotplug_disk.backup_to_qcow2.backup_to_block expect_backup_canceled = "yes" From 63b6031aaf151370c76a5d7e4523db95f2a0fcb3 Mon Sep 17 00:00:00 2001 From: cliping Date: Tue, 10 Jun 2025 18:32:53 +0800 Subject: [PATCH 1010/1055] migration: Update error message (#6366) Signed-off-by: lcheng --- .../kill_qemu_during_performphase.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_performphase.cfg b/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_performphase.cfg index 9af9a89cd43..c04e4dc4012 100644 --- a/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_performphase.cfg +++ b/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_performphase.cfg @@ -47,7 +47,7 @@ expected_dest_state = "nonexist" expected_src_state = "running" migrate_speed = "1" - err_msg = "QEMU unexpectedly closed the monitor" + err_msg = "QEMU unexpectedly closed the monitor|Unable to read from socket: Connection reset by peer" check_disk_on_dest = "no" virsh_migrate_extra = "--bandwidth 1000" - kill_dest_qemu_after_vm_paused: @@ -58,7 +58,7 @@ expected_dest_state = "nonexist" expected_src_state = "running" virsh_migrate_extra = "--timeout 2 --timeout-suspend --bandwidth 1000" - err_msg = "QEMU unexpectedly closed the monitor" + err_msg = "QEMU unexpectedly closed the monitor|Unable to read from socket: Connection reset by peer" - kill_src_qemu: expected_dest_state = "nonexist" expected_src_state = "shut off" From 1c6680a4ad37d17a52640445bc83c872567d144e Mon Sep 17 00:00:00 2001 From: Sebastian Mitterle <54858857+smitterl@users.noreply.github.com> Date: Wed, 11 Jun 2025 11:04:30 +0200 Subject: [PATCH 1011/1055] contributor guidelines: fix link (#6365) Links to avocado-vt contributor guidelines. That file was moved. Fix url. Signed-off-by: Sebastian Mitterle --- contributor_reviewer_maintainer_guidelines.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contributor_reviewer_maintainer_guidelines.rst b/contributor_reviewer_maintainer_guidelines.rst index 36c545e847f..b40f33b85f6 100644 --- a/contributor_reviewer_maintainer_guidelines.rst +++ b/contributor_reviewer_maintainer_guidelines.rst @@ -1,2 +1,2 @@ Please follow up the same best practices as avocado-vt: -https://github.com/avocado-framework/avocado-vt/blob/master/PR_Review_And_Contribute_Practices.txt +https://github.com/avocado-framework/avocado-vt/blob/master/docs/source/contributing/Guidelines.rst From a5e34bbf7c03c819e17854e14fb825b7fd4ff2dd Mon Sep 17 00:00:00 2001 From: qiankehan Date: Wed, 11 Jun 2025 17:26:46 +0800 Subject: [PATCH 1012/1055] passt: Replace the test file dir '/' with '/var/tmp' (#6328) For RHEL image mode, the directory '/' is read-only. It will cause the case failures when trying to write a file on it. Fix it with the writable directory '/var/tmp'. Signed-off-by: Han Han --- libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg index 57f8a9e969e..278e118fadd 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_transfer_file.cfg @@ -41,7 +41,7 @@ bs = 1M - 1G: bs = 100M - test_file = /${file_size}_file + test_file = /var/tmp/${file_size}_file rec_file = out_${file_size} cmd_create_file = dd if=/dev/urandom bs=${bs} count=10 > ${test_file} cmd_listen = f'socat -u {prot}-LISTEN:{port},reuseaddr OPEN:${rec_file},create' From e7d500ae6d8131077b3bf6d9addde90eb8f6847c Mon Sep 17 00:00:00 2001 From: Han Han Date: Wed, 11 Jun 2025 20:56:05 +0800 Subject: [PATCH 1013/1055] update_device: Replace str_out() with __str__() That will fix the error: 'XMLTreeFile' object has no attribute 'str_out' Signed-off-by: Han Han --- .../src/virtual_network/update_device/update_iface_type_live.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/src/virtual_network/update_device/update_iface_type_live.py b/libvirt/tests/src/virtual_network/update_device/update_iface_type_live.py index ba2e16c5010..06c82a4668f 100644 --- a/libvirt/tests/src/virtual_network/update_device/update_iface_type_live.py +++ b/libvirt/tests/src/virtual_network/update_device/update_iface_type_live.py @@ -56,7 +56,7 @@ def run(test, params, env): iface = libvirt_vmxml.create_vm_device_by_type( 'interface', iface_attrs) - LOG.debug(f'Interface to attach/add:\n{iface.xmltreefile.str_out()}') + LOG.debug(f'Interface to attach/add:\n{iface.xmltreefile.__str__()}') if operation == 'default': vmxml.add_device(iface) From 3c95a98e8809f4f7c7a7368ae8a4717e10e8900e Mon Sep 17 00:00:00 2001 From: Yingshun <49855663+Yingshun@users.noreply.github.com> Date: Mon, 16 Jun 2025 16:30:43 +0800 Subject: [PATCH 1014/1055] sriov: Add a hotplut case (#6373) This PR adds: VIRT-300491: Attach/detach-device a hostdev interface or device to/from guest Signed-off-by: Yingshun Cui --- ...tach_detach_device_vfio_variant_driver.cfg | 24 +++++ ...ttach_detach_device_vfio_variant_driver.py | 98 +++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_vfio_variant_driver.cfg create mode 100644 libvirt/tests/src/sriov/plug_unplug/sriov_attach_detach_device_vfio_variant_driver.py diff --git a/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_vfio_variant_driver.cfg b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_vfio_variant_driver.cfg new file mode 100644 index 00000000000..e64afe3483e --- /dev/null +++ b/libvirt/tests/cfg/sriov/plug_unplug/sriov_attach_detach_device_vfio_variant_driver.cfg @@ -0,0 +1,24 @@ +- sriov.plug_unplug.vfio_variant_driver: + type = sriov_attach_detach_device_vfio_variant_driver + start_vm = "no" + expr_driver = "mlx5_vfio_pci" + ping_dest = "www.redhat.com" + + only x86_64, aarch64 + variants: + - mlx5_vfio: + driver_dict = {'driver': {'driver_attr': {'name': 'vfio', 'model': 'mlx5_vfio_pci'}}} + - vfio_vfio: + driver_dict = {'driver': {'driver_attr': {'name': 'vfio', 'model': 'vfio_pci'}}} + - @default: + driver_dict = {} + variants dev_type: + - hostdev_interface: + iface_dict = {'type_name': 'hostdev', 'hostdev_address': {'type_name': 'pci', 'attrs': vf_pci_addr}, 'mac_address': mac_addr, 'managed': 'yes'} + - hostdev_device: + hostdev_dict = {'mode': 'subsystem', 'type': 'pci', 'source': {'untyped_address': vf_pci_addr}, 'managed': 'yes'} + variants: + - single_iface: + iface_number = 1 + - multiple_ifaces: + iface_number = 4 diff --git a/libvirt/tests/src/sriov/plug_unplug/sriov_attach_detach_device_vfio_variant_driver.py b/libvirt/tests/src/sriov/plug_unplug/sriov_attach_detach_device_vfio_variant_driver.py new file mode 100644 index 00000000000..f5c93e903ee --- /dev/null +++ b/libvirt/tests/src/sriov/plug_unplug/sriov_attach_detach_device_vfio_variant_driver.py @@ -0,0 +1,98 @@ +import time + +from virttest import utils_net +from virttest import utils_sriov +from virttest import utils_test +from virttest import virsh + +from virttest.libvirt_xml import vm_xml +from virttest.utils_libvirt import libvirt_vfio +from virttest.utils_libvirt import libvirt_vmxml + + +def run(test, params, env): + """ + Attach/detach device of hostdev type with vfio variant driver to/from guest + """ + def parse_iface_dict(pf_pci): + """ + Parse interface dictionary from parameters + """ + mac_addr = utils_net.generate_mac_address_simple() + + vf_pci_addr = utils_sriov.pci_to_addr(vf_pci) + if params.get('iface_dict'): + iface_dict = eval(params.get('iface_dict', '{}')) + else: + if vf_pci_addr.get('type'): + del vf_pci_addr['type'] + iface_dict = eval(params.get('hostdev_dict', '{}')) + driver_dict = eval(params.get("pf_pci", "{}")) + if driver_dict: + iface_dict.update(driver_dict) + managed = params.get("managed") + if managed: + iface_dict.update({"manged": managed}) + test.log.debug(f"Iface dict: {iface_dict}") + + return iface_dict + + dev_type = params.get("dev_type", "hostdev_interface") + device_type = "hostdev" if dev_type == "hostdev_device" else "interface" + expr_driver = params.get("expr_driver", "mlx5_vfio_pci") + test_pf = params.get("test_pf", "ens3f0np0") + pf_pci = utils_sriov.get_pf_pci(test_pf=test_pf) + iface_number = int(params.get("iface_number", "1")) + ping_dest = params.get("ping_dest", "www.redhat.com") + + vm_name = params.get("main_vm", "avocado-vt-vm1") + vm = env.get_vm(vm_name) + new_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) + orig_vm_xml = new_xml.copy() + try: + libvirt_vmxml.remove_vm_devices_by_type(vm, 'interface') + libvirt_vmxml.remove_vm_devices_by_type(vm, 'hostdev') + + test.log.info("TEST_STEP: Start the VM") + vm.start() + vm_session = vm.wait_for_serial_login(timeout=240) + # FIXME: If the "IP" command is executed immediately after the interface + # is attached, it will be hung. + time.sleep(10) + + for idx in range(iface_number): + test.log.info("TEST_STEP: Attach a hostdev interface/device to VM") + vf_pci = utils_sriov.get_vf_pci_id(pf_pci, idx) + iface_dict = parse_iface_dict(vf_pci) + iface_dev = libvirt_vmxml.create_vm_device_by_type(device_type, iface_dict) + virsh.attach_device(vm.name, iface_dev.xml, ignore_status=False, + debug=True) + actual_vm_hostdev = vm_xml.VMXML.new_from_dumpxml(vm.name)\ + .devices.by_device_tag(device_type)[idx] + act_hostdev_dict = actual_vm_hostdev.fetch_attrs() + test.log.debug(f"Actual XML: {actual_vm_hostdev}") + if act_hostdev_dict.get("driver")["driver_attr"].get("name") != "vfio": + test.fail("The hostdev driver is not set to VFIO.") + libvirt_vfio.check_vfio_pci(vf_pci, exp_driver=expr_driver) + if utils_test.ping(ping_dest, count=3, timeout=5, session=vm_session): + test.fail("Failed to ping %s." % ping_dest) + + vm_hostdevs = vm_xml.VMXML.new_from_dumpxml(vm.name)\ + .devices.by_device_tag(device_type) + for vm_dev in vm_hostdevs: + test.log.info("TEST_STEP: Detach a hostdev interface/device from VM") + virsh.detach_device(vm.name, vm_dev.xml, debug=True, + wait_for_event=True, ignore_status=False) + vm_hostdevs = vm_xml.VMXML.new_from_dumpxml(vm.name)\ + .devices.by_device_tag(device_type) + if vm_hostdevs: + test.fail("Got hostdev interface/device(%s) after detaching the " + "device!" % vm_hostdevs) + libvirt_vfio.check_vfio_pci(vf_pci, exp_driver="mlx5_core") + virsh.reboot(vm.name, ignore_status=False, debug=True) + vm.cleanup_serial_console() + vm.create_serial_console() + vm.wait_for_serial_login().close() + + finally: + orig_vm_xml.sync() From e520c21797255f777ed4cb69ebc57c98964bf09d Mon Sep 17 00:00:00 2001 From: nanli Date: Sun, 15 Jun 2025 16:01:59 +0800 Subject: [PATCH 1015/1055] add case for virsh net-metadata cmd xxxx-300498:'virsh net-metadata' with different options to show or modify the XML metadata of a network. Signed-off-by: nanli --- .../network/virsh_cmds/virsh_net_metadata.cfg | 44 +++++ .../network/virsh_cmds/virsh_net_metadata.py | 181 ++++++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/network/virsh_cmds/virsh_net_metadata.cfg create mode 100644 libvirt/tests/src/virtual_network/network/virsh_cmds/virsh_net_metadata.py diff --git a/libvirt/tests/cfg/virtual_network/network/virsh_cmds/virsh_net_metadata.cfg b/libvirt/tests/cfg/virtual_network/network/virsh_cmds/virsh_net_metadata.cfg new file mode 100644 index 00000000000..ff2fea43c80 --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/network/virsh_cmds/virsh_net_metadata.cfg @@ -0,0 +1,44 @@ +- virtual_network.network.net_metadata: + type = virsh_net_metadata + net_name = "default" + metadata_uri = "http://app.org/" + prefix = "test" + ele_name = "head" + metadata_extra = " --key ${prefix} --set '<${ele_name}/>' " + expected_xml = "<${ele_name}/>" + expected_metadata_xml = '\n.*<${prefix}:${ele_name} xmlns:${prefix}="${metadata_uri}"/>\n.*' + prefix_update = "abc" + ele_update = "body" + metadata_extra_update = " --key ${prefix_update} --set '<${ele_update}/>' " + expected_update_xml = "<${ele_update}/>" + expected_update_metadata_xml = '\n.*<${prefix_update}:${ele_update} xmlns:${prefix_update}="${metadata_uri}"/>\n.*' + exist = "yes" + remove_opt = " --remove" + removed_msg = "error: metadata not found: Requested metadata element is not present" + func_supported_since_libvirt_ver = (9, 8, 0) + variants update_method: + - cmdline: + - edit_space: + variants network_states: + - active_net: + - inactive_net: + variants: + - live: + opt = ' --live' + inactive_net: + error_msg = "error: Requested operation is not valid: network is not running" + - config: + opt = ' --config' + - current: + opt = ' --current' + - opt_none: + opt = ' ' + variants: + - active_dumpxml: + dumpxml_opt = " " + config.active_net: + exist = "no" + - inactive_dumpxml: + dumpxml_opt = " --inactive" + live, current.active_net, opt_none.active_net: + exist = "no" diff --git a/libvirt/tests/src/virtual_network/network/virsh_cmds/virsh_net_metadata.py b/libvirt/tests/src/virtual_network/network/virsh_cmds/virsh_net_metadata.py new file mode 100644 index 00000000000..59872fb4e71 --- /dev/null +++ b/libvirt/tests/src/virtual_network/network/virsh_cmds/virsh_net_metadata.py @@ -0,0 +1,181 @@ +import aexpect +import re + +from virttest import libvirt_version +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_network +from virttest.libvirt_xml.network_xml import NetworkXML + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + + +def edit_metadata(test, params, metadata_cmd, **dargs): + """ + Edit metadata with cmdline or edit space according to scenario. + + :params: test: test object. + :params: params: cfg parameter dict. + :params: metadata_cmd: metadata updating cmd. + :param dargs: mutable parameter dict. + """ + update_options = params.get("opt") + update_method = params.get("update_method") + metadata_uri = params.get("metadata_uri") + net_name = params.get("net_name") + error_msg = params.get("error_msg") + + if update_method == "cmdline": + result = virsh.net_metadata(net_name, metadata_uri, + extra=metadata_cmd+update_options, debug=True) + libvirt.check_exit_status(result, error_msg) + + elif update_method == "edit_space": + prefix = re.findall("(--key.* )-", metadata_cmd)[0] + ele_name = re.findall("--set \'(.*)\' ", metadata_cmd)[0] + + send_cmd = r"virsh net-metadata %s --uri %s %s --edit %s" % ( + net_name, metadata_uri, prefix, update_options) + test.log.debug("Send updating metadate cmd: %s", send_cmd) + + session = aexpect.ShellSession("sudo -s") + try: + session.sendline(send_cmd) + if "clean_content" in dargs: + session.send('dG') + session.send('i') + session.sendline(ele_name) + session.send('\x1b') + session.send('ZZ') + session.read_until_any_line_matches( + [r"Metadata modified"], timeout=10, internal_timeout=1) + except Exception as e: + if not error_msg: + test.fail("Error occurred: %s when virsh net-metadata --edit" % str(e)) + session.close() + + +def check_net_metadata_result(test, params, expected_string, existed=True): + """ + Check expected result in virsh net-metadata. + + :params: test, test object. + :params: params, params object. + :params: expected_string, expected result string. + :params: existed, the flag of expected result string exist or not. + """ + update_options = params.get("opt") + metadata_uri = params.get("metadata_uri") + net_name = params.get("net_name") + + result = virsh.net_metadata(net_name, metadata_uri, + extra=update_options, debug=True) + if existed: + if result.stdout.strip() != expected_string: + test.fail('Expect "%s" was existed.' % expected_string) + else: + if result.stderr.strip() != expected_string: + test.fail('Expect "%s" was existed.' % expected_string) + test.log.debug("Check %s PASS in virsh net-metadata", expected_string) + + +def check_net_dumpxml(test, params, expected_xml, exist): + """ + Check if expected xml in virsh net-dumpxml. + + :params: test, test object. + :params: params, params object. + :params: expected_xml, expected xml string. + :params: exist, exist or not. + """ + net_name = params.get("net_name") + dumpxml_opt = params.get("dumpxml_opt") + + result = virsh.net_dumpxml(net_name, dumpxml_opt).stdout.strip() + if exist: + if not re.findall(expected_xml, result): + test.fail('Expect %s was existed but got %s.' % (expected_xml, result)) + else: + if re.findall(expected_xml, result): + test.fail('Expect %s was not existed but got %s.' % (expected_xml, result)) + + test.log.debug("Checked %s PASS" % expected_xml) + + +def run(test, params, env): + """ + Test 'virsh net-metadata' with different options to show or + modify the XML metadata of a network. + """ + def setup_test(): + """ + Prepare network status. + """ + test.log.info("TEST_SETUP: Prepare network status.") + libvirt_network.ensure_default_network() + if network_states == "inactive_net": + virsh.net_destroy(net_name, **VIRSH_ARGS) + + def run_test(): + """ + 1. Update and remove network metadata. + 2. Check metadata xml is existed or removed. + """ + test.log.info("TEST_STEP1:Set a xml metadata for network.") + edit_metadata(test, params, metadata_cmd=metadata_extra) + if error_msg: + return + + test.log.info("TEST_STEP2: Check correct metadata xml in network.") + check_net_metadata_result(test, params, expected_xml) + check_net_dumpxml(test, params, expected_metadata_xml, exist) + + test.log.info("TEST_STEP3-4: Modify and check metadata xml in network.") + edit_metadata(test, params, metadata_cmd=metadata_extra_update, clean_content=True) + check_net_metadata_result(test, params, expected_update_xml) + check_net_dumpxml(test, params, expected_update_metadata_xml, exist) + + test.log.info("TEST_STEP5-6: Remove and check metadata xml in network.") + virsh.net_metadata(net_name, metadata_uri, + extra=update_options+remove_opt, **VIRSH_ARGS) + check_net_metadata_result(test, params, removed_msg, existed=False) + check_net_dumpxml(test, params, expected_update_metadata_xml, exist=False) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bk_net.sync() + bkxml.sync() + libvirt_network.ensure_default_network() + + libvirt_version.is_libvirt_feature_supported(params) + vm_name = params.get('main_vm') + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + default_net = NetworkXML.new_from_net_dumpxml('default') + bk_net = default_net.copy() + + net_name = params.get("net_name") + network_states = params.get("network_states") + metadata_extra = params.get('metadata_extra') + metadata_extra_update = params.get("metadata_extra_update") + metadata_uri = params.get("metadata_uri") + update_options = params.get("opt") + error_msg = params.get("error_msg") + remove_opt = params.get("remove_opt") + expected_xml = params.get("expected_xml") + expected_metadata_xml = params.get("expected_metadata_xml") + expected_update_xml = params.get("expected_update_xml") + expected_update_metadata_xml = params.get("expected_update_metadata_xml") + exist = params.get("exist", "no") == "yes" + removed_msg = params.get("removed_msg") + + try: + setup_test() + run_test() + + finally: + teardown_test() From ccb9c6573121296bbc96d9dba120b10cf14045a2 Mon Sep 17 00:00:00 2001 From: Yanqiu Zhang Date: Fri, 16 May 2025 11:34:48 -0400 Subject: [PATCH 1016/1055] add swtpm cmds tests test swtpm capabilities, starting qemu guest with swtpm_setup and swtpm socket file, massive concurrent swtpm_setup runs. Signed-off-by: Yanqiu Zhang --- .../tests/cfg/virtual_device/swtpm_cmd.cfg | 20 ++++ libvirt/tests/src/virtual_device/swtpm_cmd.py | 109 ++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_device/swtpm_cmd.cfg create mode 100644 libvirt/tests/src/virtual_device/swtpm_cmd.py diff --git a/libvirt/tests/cfg/virtual_device/swtpm_cmd.cfg b/libvirt/tests/cfg/virtual_device/swtpm_cmd.cfg new file mode 100644 index 00000000000..4c209148403 --- /dev/null +++ b/libvirt/tests/cfg/virtual_device/swtpm_cmd.cfg @@ -0,0 +1,20 @@ +- virtual_devices.swtpm_cmd: + type = swtpm_cmd + start_vm = no + no s390-virtio + variants case: + - print_caps: + swtpm_setup_cmd = "swtpm_setup --print-capabilities" + swtpm_socket_cmd = "swtpm socket --print-capabilities" + - start_qemu_guest: + tpm_state_dir = "/tmp/mytpm" + swtpm_setup_cmd = "swtpm_setup --tpm2 --tpmstate /tmp/mytpm --create-ek-cert --create-platform-cert --overwrite" + swtpm_socket_cmd = "swtpm socket --daemon --ctrl type=unixio,path=/tmp/guest-swtpm.sock,mode=0600 --tpmstate dir=/tmp/mytpm,mode=0600 --tpm2" + qemu_cmd = "/usr/libexec/qemu-kvm -tpmdev emulator,id=tpm-tpm0,chardev=chrtpm -chardev socket,id=chrtpm,path=/tmp/guest-swtpm.sock -device tpm-crb,tpmdev=tpm-tpm0,id=tpm0" + variants: + - with_terminate: + extra_option = "--terminate" + - no_terminate: + - cocurrent_setup: + co_cmd = "rm -rf /var/lib/swtpm-localca/* ; for ((i = 0; i<500;i++)); do rm -rf /tmp/vtpm${i}; mkdir -p /tmp/vtpm${i}; swtpm_setup --tpm2 --tpmstate /tmp/vtpm${i} --create-ek-cert --create-platform-cert --pcr-banks sha256 2>&1 | grep -i read & done" + unexpected_error = "Need read rights on issuer certificate" diff --git a/libvirt/tests/src/virtual_device/swtpm_cmd.py b/libvirt/tests/src/virtual_device/swtpm_cmd.py new file mode 100644 index 00000000000..0ec5885bb02 --- /dev/null +++ b/libvirt/tests/src/virtual_device/swtpm_cmd.py @@ -0,0 +1,109 @@ +import os +import time +import psutil +import shutil +import subprocess +import logging as log + +from avocado.utils import process +from glob import glob + +# 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__) + + +def check_process_exist(process_cmd, check_cmd): + """ + Check if a cmd process exists in system processes. + + :param process_cmd: the process to check + :param check_cmd: the cmd for how to check process + :return: boolean value for exist or not + """ + p_list = process.run(check_cmd, shell=True, ignore_status=True).stdout_text + ret = True if process_cmd in p_list else False + return ret + + +def kill_process(name): + """ + Kill a process by name + + :param name: the process name to kill + """ + for proc in psutil.process_iter(): + if proc.name() == name: + logging.debug('Killing process %s', name) + proc.kill() + + +def run(test, params, env): + """ + Test the swtpm_setup or 'swtpm_socket' cmds + """ + swtpm_setup_cmd = params.get("swtpm_setup_cmd") + swtpm_socket_cmd = params.get("swtpm_socket_cmd", "") + qemu_cmd = params.get("qemu_cmd", "") + extra_option = params.get("extra_option", "") + co_cmd = params.get("co_cmd", "") + unexpected_error = params.get("unexpected_error", "") + tpm_state_dir = params.get("tpm_state_dir", "") + p2 = None + + if extra_option: + swtpm_socket_cmd += " " + extra_option + if tpm_state_dir and not os.path.exists(tpm_state_dir): + os.mkdir(tpm_state_dir) + + swtpm_check_cmd = "ps aux|grep 'swtpm socket'\ + |grep -v avocado-runner-avocado-vt|grep -v grep" + + try: + if co_cmd: + logging.debug("Running '%s'", co_cmd) + p_out = subprocess.Popen(co_cmd, shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE).stdout.read() + logging.debug("The cocurrent swtpm_setup output \ + including 'read' is:\n%s", p_out) + if unexpected_error in str(p_out): + test.fail(p_out) + else: + process.run(swtpm_setup_cmd, shell=True, ignore_status=False) + process.run(swtpm_socket_cmd, shell=True, ignore_status=False) + qemu_check_cmd = "ps aux|grep '/usr/libexec/qemu-kvm -tpmdev' \ + |grep -v avocado-runner-avocado-v|grep -v grep" + if qemu_cmd and check_process_exist(swtpm_socket_cmd, + swtpm_check_cmd): + p2 = subprocess.Popen(qemu_cmd, shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + logging.debug("Running '%s'", qemu_cmd) + time.sleep(3) + check_process_exist(qemu_cmd, qemu_check_cmd) + if p2.poll() is None: + logging.debug('Killing qemu cmd...') + p2.kill() + check_process_exist(qemu_cmd, qemu_check_cmd) + swtpm_socket_exists = check_process_exist(swtpm_socket_cmd, + swtpm_check_cmd) + if swtpm_socket_exists and '--terminate' in swtpm_socket_cmd: + test.fail("swtpm process should exit with '--terminate'\ + when qemu is killed.") + elif not swtpm_socket_exists and \ + '--terminate' not in swtpm_socket_cmd: + test.fail("swtpm process should not exit\ + without '--terminate' when qemu is killed.") + + finally: + logging.debug('Cleaning env...') + if check_process_exist(swtpm_socket_cmd, swtpm_check_cmd): + kill_process('swtpm') + if p2 and p2.poll() is None: + p2.kill() + if os.path.exists(tpm_state_dir): + shutil.rmtree(tpm_state_dir) + for folder in glob("/tmp/vtpm*"): + shutil.rmtree(folder) + process.run("rm -rf /var/lib/swtpm-localca/*", shell=True, ignore_status=True) From db0b49d9c86f2cb2fb192f38ff05801794e0dd56 Mon Sep 17 00:00:00 2001 From: nanli Date: Tue, 17 Jun 2025 18:37:08 +0800 Subject: [PATCH 1017/1055] add case for virsh net-desc cmd xxxx-300439: Test virsh net-desc with different options to show or modify network description or title. Signed-off-by: nanli --- .../network/virsh_cmds/virsh_net_desc.cfg | 47 +++++ .../network/virsh_cmd/virsh_net_desc.py | 196 ++++++++++++++++++ 2 files changed, 243 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_network/network/virsh_cmds/virsh_net_desc.cfg create mode 100644 libvirt/tests/src/virtual_network/network/virsh_cmd/virsh_net_desc.py diff --git a/libvirt/tests/cfg/virtual_network/network/virsh_cmds/virsh_net_desc.cfg b/libvirt/tests/cfg/virtual_network/network/virsh_cmds/virsh_net_desc.cfg new file mode 100644 index 00000000000..d55a4c72daf --- /dev/null +++ b/libvirt/tests/cfg/virtual_network/network/virsh_cmds/virsh_net_desc.cfg @@ -0,0 +1,47 @@ +- virtual_network.network.net_desc: + type = virsh_net_desc + net_name = "default" + func_supported_since_libvirt_ver = (9, 8, 0) + variants update_method: + - cmdline: + - edit_space: + variants update_item: + - title: + net_title = "network title" + execute_cmd =" --title '${net_title}'" + expected_xml = '${net_title}' + expected_str = ${net_title} + net_title_update = "network title update" + execute_update_cmd =" --title '${net_title_update}'" + expected_update_xml = '${net_title_update}' + expected_update_str = ${net_title_update} + remove_opt = " --title '' " + removed_msg = "No title for network: default" + get_cmd = ' --title' + - description: + net_desc = "network description" + execute_cmd = "${net_desc}" + expected_xml = '${net_desc}' + expected_str = ${net_desc} + net_desc_update = "network description update" + execute_update_cmd =" ${net_desc_update}" + expected_update_xml = '${net_desc_update}' + expected_update_str = ${net_desc_update} + remove_opt = "''" + removed_msg = "No description for network: default" + get_cmd = ' ' + variants network_states: + - active_net: + - inactive_net: + variants: + - live: + opt = ' --live' + inactive_net: + error_msg = "error: Requested operation is not valid: network is not running" + - config: + opt = ' --config' + - current: + opt = ' --current' + - opt_none: + no inactive_net + opt = ' ' diff --git a/libvirt/tests/src/virtual_network/network/virsh_cmd/virsh_net_desc.py b/libvirt/tests/src/virtual_network/network/virsh_cmd/virsh_net_desc.py new file mode 100644 index 00000000000..6b139e7d417 --- /dev/null +++ b/libvirt/tests/src/virtual_network/network/virsh_cmd/virsh_net_desc.py @@ -0,0 +1,196 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import aexpect +import re + +from virttest import libvirt_version +from virttest import remote +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_network +from virttest.libvirt_xml.network_xml import NetworkXML + +VIRSH_ARGS = {'ignore_status': False, 'debug': True} + + +def virsh_net_desc(test, params, cmd): + """ + Edit description or title with virsh net-desc by cmdline or + edit space according to scenario. + + :params: test: test object. + :params: params: cfg parameter dict. + :params: cmd: virsh desc updating cmd, delete all content if cmd is empty. + """ + update_method = params.get("update_method") + update_options = params.get("opt") + net_name = params.get("net_name") + error_msg = params.get("error_msg") + + if update_method == "cmdline": + result = virsh.net_desc(net_name, extra=cmd+update_options, debug=True) + libvirt.check_exit_status(result, error_msg) + + elif update_method == "edit_space": + send_cmd = r"virsh net-desc %s %s --edit %s" % (net_name, cmd, update_options) + test.log.debug("Send cmd: %s", send_cmd) + session = aexpect.ShellSession("sudo -s") + try: + session.sendline(send_cmd) + session.send('\x1b') + session.send('ZZ') + remote.handle_prompts(session, None, None, r"[\#\$]\s*$") + except Exception as e: + if not error_msg: + test.fail("Error occurred: %s when virsh net-desc --edit" % str(e)) + session.close() + + +def check_net_desc_result(test, params, get_cmd, expected_string, existed=True): + """ + Get and check desc or title by virsh net-desc cmd. + + :params: test, test object. + :params: params, params object. + :params: get_cmd, the get cmd for virsh net-desc. + :params: expected_string, expected result string. + :params: existed, the flag of expected result string exist or not. + """ + net_name = params.get("net_name") + update_options = params.get("opt") + + result = virsh.net_desc(net_name, extra=get_cmd+update_options, debug=True) + if existed: + if result.stdout.strip() != expected_string: + test.fail('Expect "%s" was existed.' % expected_string) + else: + if result.stderr.strip() != expected_string: + test.fail('Expect "%s" was not existed.' % expected_string) + test.log.debug("Check '%s' PASS in virsh net-desc", expected_string) + + +def _confirm_existed(params, dumpxml_opt, check_remove): + """ + Get existed value according to the scenario. + + :params: params, params object. + :params: dumpxml_opt, virsh net-dumpxml option, '--inactive' or '' + :params: check_remove, check net-dumpxml after removing. + :return: expected xml was existed flag. + """ + opt = params.get('opt') + network_states = params.get('network_states') + + existed = True + if ((dumpxml_opt == " " and opt == ' --config' and network_states == 'active_net') + or (dumpxml_opt == " --inactive" and opt == " --live") + or (dumpxml_opt == " --inactive" and network_states == 'active_net' and opt in [' --current', ' ']) + or check_remove): + existed = False + + return existed + + +def check_net_dumpxml(test, params, expected_xml, check_remove=False): + """ + Check if expected xml in virsh net-dumpxml. + + :params: test, test object. + :params: params, params object. + :params: expected_xml, expected xml string. + :params: check_remove, check net-dumpxml after removing, default False + """ + net_name = params.get("net_name") + + dumpxml_opt = [" ", " --inactive"] + for dump in dumpxml_opt: + existed = _confirm_existed(params, dump, check_remove) + result = virsh.net_dumpxml(net_name, dump, debug=True).stdout.strip() + if existed: + if not re.findall(expected_xml, result): + test.fail('Expect %s was existed' % expected_xml) + else: + if re.findall(expected_xml, result): + test.fail('Expect %s was not existed' % expected_xml) + test.log.debug("Checked '%s' PASS in active and inactive xml" % expected_xml) + + +def run(test, params, env): + """ + Test 'virsh net-desc' with different options to show or modify network description + or title. + """ + def setup_test(): + """ + Prepare network status. + """ + test.log.info("TEST_SETUP: Prepare network status.") + libvirt_network.ensure_default_network() + if network_states == "inactive_net": + virsh.net_destroy(net_name, **VIRSH_ARGS) + + def run_test(): + """ + 1. Update and remove network description or title. + 2. Check description xml is existed or removed. + """ + test.log.info("TEST_STEP1:Set a %s xml for network." % update_item) + virsh_net_desc(test, params, execute_cmd) + if error_msg: + return + + test.log.info("TEST_STEP2: Check correct %s xml in network." % update_item) + check_net_desc_result(test, params, get_cmd, expected_str) + check_net_dumpxml(test, params, expected_xml) + + test.log.info("TEST_STEP3-4: Modify and check %s xml in network." % update_item) + virsh_net_desc(test, params, execute_update_cmd) + check_net_desc_result(test, params, get_cmd, expected_update_str) + check_net_dumpxml(test, params, expected_update_xml) + + test.log.info("TEST_STEP5-6: Remove and check %s xml in network." % update_item) + virsh_net_desc(test, params, remove_opt) + check_net_desc_result(test, params, get_cmd, removed_msg) + check_net_dumpxml(test, params, expected_update_xml, check_remove=True) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bk_net.sync() + bkxml.sync() + libvirt_network.ensure_default_network() + + libvirt_version.is_libvirt_feature_supported(params) + vm_name = params.get('main_vm') + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + default_net = NetworkXML.new_from_net_dumpxml('default') + bk_net = default_net.copy() + + net_name = params.get("net_name") + network_states = params.get("network_states") + update_item = params.get("update_item") + error_msg = params.get("error_msg") + remove_opt = params.get("remove_opt") + removed_msg = params.get("removed_msg") + get_cmd = params.get("get_cmd") + execute_cmd, execute_update_cmd = params.get('execute_cmd'), params.get("execute_update_cmd") + expected_str, expected_update_str = params.get("expected_str"), params.get("expected_update_str") + expected_xml, expected_update_xml = params.get("expected_xml"), params.get("expected_update_xml") + + try: + setup_test() + run_test() + + finally: + teardown_test() From c5fbff731fba288cdc76064e135d652afce5eedf Mon Sep 17 00:00:00 2001 From: meinaLi Date: Tue, 17 Jun 2025 23:30:43 -0400 Subject: [PATCH 1018/1055] Virtual_disk: fix error message to match new change Update the error message to also cover "Operation not supported: cannot modify '' configuration of the disk". Signed-off-by: meinaLi --- .../tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg index d69fc0ae61b..36567f89977 100755 --- a/libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_iothreads_queue.cfg @@ -82,7 +82,7 @@ func_supported_since_libvirt_ver = (10, 10, 0) check_qemu_pattern = status_error = yes - err_msg = "error: Operation not supported: cannot modify field '' \(or it's parts\) of the disk*" + err_msg = "error: Operation not supported: cannot modify .*iothreads.* of the disk" variants: - change_none_to_roundrobin: only coldplug..round_robin From d49f61bdb7aec49aa38eafabd1afc7086ccaea10 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Wed, 18 Jun 2025 02:57:15 -0400 Subject: [PATCH 1019/1055] Add v2v cases about btrfs Signed-off-by: Ming Xie --- v2v/tests/cfg/function_test_esx.cfg | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index f3ed54b180f..a7e14886dc5 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -950,6 +950,29 @@ only esx_80 main_vm = VM_NAME_NON_INT_DISK_V2V_EXAMPLE version_required = "[nbdkit-1.36.2-2,)" + - sles_btrfs: + only_esx_80 + version_required = "[libguestfs-fssupport-10.1-2,)" + variants: + - default: + variants: + - sles15sp6: + main_vm = VM_NAME_SLES_BTRFS_DEFAULT_SLES15SP6_V2V_EXAMPLE + boottype = 3 + - sles12sp5: + main_vm = VM_NAME_SLES_BTRFS_DEFAULT_SLES12SP5_V2V_EXAMPLE + - raid: + main_vm = VM_NAME_SLES_BTRFS_RAID_V2V_EXAMPLE + skip_vm_check = yes + skip_reason = 'bug RHEL-97179 is not fixed' + boottype = 3 + - encrypted: + main_vm = VM_NAME_SLES_BTRFS_ENCRYPTED_SLES12SP5_V2V_EXAMPLE + skip_vm_check = yes + skip_reason = 'bug RHEL-93583 is not fixed and cannot boot into OS without password automatically' + checkpoint = 'luks_dev_keys' + luks_keys = LUKS_ALL_KEYS + variants: - positive_test: status_error = 'no' From eb2acfefebfb1fd20e92d8207407f31fe1c3677f Mon Sep 17 00:00:00 2001 From: Han Han Date: Wed, 18 Jun 2025 15:15:44 +0800 Subject: [PATCH 1020/1055] passt: Allow multiple nexthops The cases will failed with error "FAIL: Host default ipv6 gateway not consistent with vm" for the host with multiple nexthops in default route like: default proto ra metric 100 pref medium nexthop via fe80::4a5a:d01:f631:3320 dev eno1 weight 1 nexthop via fe80::4a5a:d01:f631:2420 dev eno1 weight 1 Allow multiple nexthops to fix the failures. Signed-off-by: Han Han --- libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg | 2 +- libvirt/tests/cfg/virtual_network/passt/passt_function.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg index e417e2ac97b..9f659d9ddb6 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_attach_detach.cfg @@ -5,7 +5,7 @@ outside_ip = 'www.redhat.com' start_vm = no mtu = 65520 - multiple_nexthops = no + multiple_nexthops = yes variants user_type: - root_user: test_user = root diff --git a/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg b/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg index 9d7087e04a2..7442b461675 100644 --- a/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg +++ b/libvirt/tests/cfg/virtual_network/passt/passt_function.cfg @@ -5,7 +5,7 @@ outside_ip = 'www.redhat.com' start_vm = no mtu = 65520 - multiple_nexthops = no + multiple_nexthops = yes variants user_type: - root_user: test_user = root From 9dd603065a7e2563401d7f6b40bfe079fb77959c Mon Sep 17 00:00:00 2001 From: Bolatbek Issakh Date: Wed, 18 Jun 2025 13:26:55 +0200 Subject: [PATCH 1021/1055] nvdimm: Add libvirt version check for snapshot revert Snapshot revert is already supported since libvirt-9.9.0 , so this patch is to support this operation and retained the functionality to test older versions Signed-off-by: Bolatbek Issakh --- libvirt/tests/src/memory/nvdimm.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/src/memory/nvdimm.py b/libvirt/tests/src/memory/nvdimm.py index 0fa0d8aba6e..e6ca6a6d66f 100644 --- a/libvirt/tests/src/memory/nvdimm.py +++ b/libvirt/tests/src/memory/nvdimm.py @@ -359,12 +359,24 @@ def test_with_label(vm, params, test): virsh.snapshot_create_as(vm_name, "%s --disk-only" % vm_s1, ignore_status=False, debug=True) revert_result = virsh.snapshot_revert(vm_name, vm_s1, debug=True) - libvirt.check_result(revert_result, expected_fails=([params.get('error_msg_1'), - params.get('error_msg_2')])) - if libvirt_version.version_compare(9, 10, 0): - virsh.snapshot_delete(vm_name, vm_s1, ignore_status=False, debug=True) + if libvirt_version.version_compare(9, 9, 0): + libvirt.check_exit_status(revert_result) else: - virsh.snapshot_delete(vm_name, "%s --metadata" % vm_s1, ignore_status=False, debug=True) + libvirt.check_result( + revert_result, + expected_fails=[ + params.get('error_msg_1'), + params.get('error_msg_2') + ] + ) + + if libvirt_version.version_compare(9, 9, 0): + virsh.snapshot_delete(vm_name, vm_s1, + ignore_status=False, debug=True) + else: + virsh.snapshot_delete(vm_name, + "%s --metadata" % vm_s1, + ignore_status=False, debug=True) snap_file_path = libvirt_disk.get_first_disk_source(vm) if os.path.exists(snap_file_path): os.remove(snap_file_path) From 75c89f8f0bcf6f69b5cec645be3ceb20064a8ec1 Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Wed, 18 Jun 2025 11:36:24 -0400 Subject: [PATCH 1022/1055] Fix a minor mistake Signed-off-by: Ming Xie --- v2v/tests/cfg/function_test_esx.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index a7e14886dc5..1536b0a29d6 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -951,7 +951,7 @@ main_vm = VM_NAME_NON_INT_DISK_V2V_EXAMPLE version_required = "[nbdkit-1.36.2-2,)" - sles_btrfs: - only_esx_80 + only esx_80 version_required = "[libguestfs-fssupport-10.1-2,)" variants: - default: From df5ffcaf53956158bd252fc9c655cdd272339892 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Wed, 18 Jun 2025 21:21:40 -0400 Subject: [PATCH 1023/1055] Delete a negative test with invalid setting There was a negative test to save with formats as "abc". The behavior changes to handel such kind of settings in qemu.conf. Before, the setting can be saved and the daemon can start, but virsh save failed; Now, the daemon can not start with such invalid setting. Delete this negative test as it can not cause any problem if daemon can not start with it. Signed-off-by: Yalan Zhang --- libvirt/tests/cfg/save_and_restore/save_with_formats.cfg | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libvirt/tests/cfg/save_and_restore/save_with_formats.cfg b/libvirt/tests/cfg/save_and_restore/save_with_formats.cfg index 702bbbda463..b08d15a27ff 100644 --- a/libvirt/tests/cfg/save_and_restore/save_with_formats.cfg +++ b/libvirt/tests/cfg/save_and_restore/save_with_formats.cfg @@ -12,8 +12,3 @@ - gzip: - bzip2: - xz: - - negative_test: - status_error = yes - variants save_format: - - abc: - error_msg = Invalid save image format specified in configuration file From afca49fb4aa0790691db9bf25dc2e9b4c6922114 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Fri, 16 May 2025 05:41:18 -0400 Subject: [PATCH 1024/1055] Add new case VIRT-299024 for memory balloon freepagereporting Signed-off-by: liang-cong-red-hat --- .../memory_balloon_freepagereporting.cfg | 29 ++++ .../memory_balloon_freepagereporting.py | 142 ++++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 libvirt/tests/cfg/memory/memory_balloon/memory_balloon_freepagereporting.cfg create mode 100644 libvirt/tests/src/memory/memory_balloon/memory_balloon_freepagereporting.py diff --git a/libvirt/tests/cfg/memory/memory_balloon/memory_balloon_freepagereporting.cfg b/libvirt/tests/cfg/memory/memory_balloon/memory_balloon_freepagereporting.cfg new file mode 100644 index 00000000000..7260b1d3a18 --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_balloon/memory_balloon_freepagereporting.cfg @@ -0,0 +1,29 @@ +- memory.balloon.freepagereporting: + type = memory_balloon_freepagereporting + start_vm = no + current_mem = 4194304 + mem_value = 4194304 + set_memroy = 3145728 + mem_consume_cmd = "timeout 20s memhog -r80 %sk" + unconsumed_mem = 204800 + variants: + - virtio: + model = "virtio" + - virtio-non-transitional: + no s390-virtio + model = "virtio-non-transitional" + variants: + - undefined: + freepage_reporting_config = "" + max_memory_difference = 51200 + - off: + freepagereporting = off + freepage_reporting_config = ", 'freepage_reporting':'${freepagereporting}'" + max_memory_difference = 51200 + - on: + freepagereporting = on + freepage_reporting_config = ", 'freepage_reporting':'${freepagereporting}'" + min_memory_difference = 819200 + memballoon_dict ={'model':'${model}' ${freepage_reporting_config}} + mem_attrs = {'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':'KiB'} + diff --git a/libvirt/tests/src/memory/memory_balloon/memory_balloon_freepagereporting.py b/libvirt/tests/src/memory/memory_balloon/memory_balloon_freepagereporting.py new file mode 100644 index 00000000000..ebb691138e4 --- /dev/null +++ b/libvirt/tests/src/memory/memory_balloon/memory_balloon_freepagereporting.py @@ -0,0 +1,142 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Red Hat +# +# SPDX-License-Identifier: GPL-2.0 +# +# Author: Liang Cong +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import re +import time + +from virttest import utils_misc +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.devices import memballoon +from virttest.staging import utils_memory +from virttest.utils_test import libvirt + + +def run(test, params, env): + """ + Verify the freepagereporting takes effect with various memory balloon models + """ + def get_rss_mem_list(timeout=30): + """" + Get rss memory list from virsh dommemstat cmd per second + + :param timeout: timeout of getting rss memory list from virsh dommemstat cmd + :return: rss memory list + """ + current = 0 + rss_mem_list = [] + while current < timeout: + time.sleep(1) + rss_mem_list.append(get_rss_mem()) + current += 1 + return rss_mem_list + + def get_rss_mem(): + """" + Get rss memory from virsh dommemstat cmd + """ + output = virsh.dommemstat(vm_name, **virsh_dargs).stdout_text + match = re.search(r"rss\s+(\d+)", output) + return int(match.group(1)) + + def run_test(): + """ + Test steps + 1. Define guest + 2. Start the domain + 3. Check the memory usage of the guest on host + 4. Login the guest and consume the guest memory + 5. Verify the memory usage is increased after consuming more memory on host + 6. Check the memory after memory consumption + """ + test.log.info("TEST_STEP1: Define guest") + vmxml.del_device('memballoon', by_tag=True) + mem_balloon = memballoon.Memballoon() + mem_balloon.setup_attrs(**memballoon_dict) + vmxml.devices = vmxml.devices.append(mem_balloon) + vmxml.setup_attrs(**mem_attrs) + vmxml.sync() + + test.log.info("TEST_STEP2: Start the domain") + vm.start() + + test.log.info("TEST_STEP3: Check the memory usage of the guest on host") + session = vm.wait_for_login() + init_rss = get_rss_mem() + + test.log.info( + "TEST_STEP4: Login the guest and consume the guest memory") + rss_mem_thread = utils_misc.InterruptedThread(get_rss_mem_list) + rss_mem_thread.start() + free_mem = utils_memory.freememtotal(session) + session.cmd_status("swapoff -a") + session.cmd_status(mem_consume_cmd % (free_mem - unconsumed_mem)) + session.close() + rss_mem_list = rss_mem_thread.join() + test.log.debug( + "The rss memory list is %s during guest consumption." % rss_mem_list) + + test.log.info( + "TEST_STEP5: Verify the memory usage is increased after consuming more memory on host") + second_rss_mem = max(rss_mem_list) + if second_rss_mem < init_rss: + test.fail("Expected rss memory after consuming %s is larger than %s" % ( + second_rss_mem, init_rss)) + + test.log.info("TEST_STEP6: Check the memory after memory consumption") + third_rss_mem = rss_mem_list[-1] + rss_mem_changed = second_rss_mem - third_rss_mem + if max_memory_difference and abs(rss_mem_changed) > max_memory_difference: + test.fail("Expected rss memory changed lower than %s, but got %s" % ( + max_memory_difference, abs(rss_mem_changed))) + if min_memory_difference and rss_mem_changed < min_memory_difference: + test.fail("Expected rss memory changed larger than %s, but got %s" % ( + min_memory_difference, rss_mem_changed)) + + test.log.info( + "TEST_STEP7: Change the current memory allocation of the guest.") + result = virsh.setmem(domain=vm_name, size=set_memory, **virsh_dargs) + libvirt.check_exit_status(result) + + test.log.info( + "TEST_STEP8: Check the memory allocation config by virsh dominfo.") + if not utils_misc.wait_for(lambda: vm.get_used_mem() == int(set_memory), timeout=10): + test.fail("Expect used memory of dominfo is %s, but got %s" % ( + set_memory, vm.get_used_mem())) + max_mem = vm.get_max_mem() + if max_mem != int(mem_value): + test.fail("Expected max memory of dominfo is %s, but got %s" % + (mem_value, max_mem)) + + def teardown_test(): + """ + Clean test environment. + """ + test.log.info("TEST_TEARDOWN: Clean up environment.") + bkxml.sync() + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + memballoon_dict = eval(params.get('memballoon_dict', '{}')) + mem_attrs = eval(params.get('mem_attrs', '{}')) + virsh_dargs = {"debug": True, "ignore_status": True} + max_memory_difference = int(params.get('max_memory_difference', '0')) + min_memory_difference = int(params.get('min_memory_difference', '0')) + set_memory = params.get('set_memroy') + mem_value = params.get('mem_value') + mem_consume_cmd = params.get('mem_consume_cmd') + unconsumed_mem = int(params.get('unconsumed_mem')) + + try: + run_test() + + finally: + teardown_test() From 139a297b0bdb44025641161acfaa2041d150a012 Mon Sep 17 00:00:00 2001 From: liang-cong-red-hat Date: Thu, 19 Jun 2025 23:00:52 -0400 Subject: [PATCH 1025/1055] Optimize to accommodate multiple error msg Signed-off-by: liang-cong-red-hat --- .../invalid_nvdimm_memory_device_config.cfg | 29 ++++++++++--------- .../invalid_nvdimm_memory_device_config.py | 22 +++++++------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_devices/invalid_nvdimm_memory_device_config.cfg b/libvirt/tests/cfg/memory/memory_devices/invalid_nvdimm_memory_device_config.cfg index 0a6fb1b468b..f8fe0e34cf3 100644 --- a/libvirt/tests/cfg/memory/memory_devices/invalid_nvdimm_memory_device_config.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/invalid_nvdimm_memory_device_config.cfg @@ -17,43 +17,43 @@ variants invalid_setting: - exceed_slot: slot = '4294967295' - define_error = "memory device slot '${slot}' exceeds slots count" + define_error = ["memory device slot '${slot}' exceeds slots count"] - max_addr: addr_base = '0xffffffffffffffff' - start_vm_error = "address must be aligned to" - attach_error = "nvdimm is not enabled: missing 'nvdimm' in '-M'" + start_vm_error = ["address must be aligned to"] + attach_error = ["nvdimm is not enabled: missing 'nvdimm' in '-M'"] aarch64: - attach_error = "nvdimm is not enabled: add 'nvdimm=on' to '-M'" + attach_error = ["nvdimm is not enabled: add 'nvdimm=on' to '-M'"] - unexisted_node: guest_node = '6' - start_vm_error = "can't add memory backend for guest node '${guest_node}' as the guest has only '2' NUMA nodes configured" + start_vm_error = ["can't add memory backend for guest node '${guest_node}' as the guest has only '2' NUMA nodes configured"] - unexisted_path: nvdimm_path = "/tmp/nonexist.file" - start_vm_error = "No such file or directory" + start_vm_error = ["No such file or directory"] - invalid_alignsize: alignsize = '2' align_attrs = "'alignsize':${alignsize},'alignsize_unit': 'KiB'" - start_vm_error = "must be multiples of page size 0x1000" + start_vm_error = ["must be multiples of page size 0x1000"] - invalid_addr_type: addr_type = 'fakedimm' - define_error = "Invalid value for attribute 'type' in element 'address': '${addr_type}'" - define_error_8 = "unknown address type '${addr_type}'" - attach_error_8 = "unknown address type '${addr_type}'" + define_error = ["Invalid value for attribute 'type' in element 'address': '${addr_type}'"] + define_error_8 = ["unknown address type '${addr_type}'"] + attach_error_8 = ["unknown address type '${addr_type}'"] - small_label: label_size = 100 label_attrs = "'label':{'size_unit':'KiB','size':${label_size}}" - define_error ="nvdimm label must be at least 128KiB" + define_error = ["nvdimm label must be at least 128KiB"] - bigger_label: label_size = 524289 label_attrs = "'label':{'size_unit':'KiB','size':${label_size}}" - define_error ="label size must be smaller than NVDIMM size" + define_error = ["label size must be smaller than NVDIMM size"] - bigger_target_memory: target_size = 1048576 - start_vm_error = "backing store size 0x20000000 does not match 'size' option 0x40000000" + start_vm_error = ["backing store size 0x20000000 does not match 'size' option 0x40000000", "backing store size 0x20000000 is too small for 'size' option 0x40000000"] - with_discard: mem_discard = "yes" discard_attr = " 'mem_discard':'${mem_discard}'," - define_error = "discard is not supported for nvdimms" + define_error = ["discard is not supported for nvdimms"] addr_attrs = "'address':{'attrs': {'type': '${addr_type}', 'base': '${addr_base}', 'slot': '${slot}'}}" source_attrs = "'source': {${align_attrs},'path': '${nvdimm_path}'}" target_attrs = "'target': {'size': ${target_size},'size_unit': 'KiB','node':${guest_node}, ${label_attrs}}" @@ -67,3 +67,4 @@ max_dict = '"max_mem_rt": 10485760, "max_mem_rt_slots":16, "max_mem_rt_unit": "KiB"' numa_attrs = "'vcpu': 4,'cpu': {'numa_cell': [{'id': '0', 'cpus': '0-1', 'memory': '${numa_mem}', 'unit': 'KiB'},{'id':'1','cpus': '2-3','memory':'${numa_mem}','unit':'KiB'}]}" vm_attrs = {${numa_attrs}, ${max_dict}, 'memory_unit':'KiB','memory':${mem_value},'current_mem':${current_mem},'current_mem_unit':"KiB"} + diff --git a/libvirt/tests/src/memory/memory_devices/invalid_nvdimm_memory_device_config.py b/libvirt/tests/src/memory/memory_devices/invalid_nvdimm_memory_device_config.py index dda407db1e5..69aa3f10aac 100644 --- a/libvirt/tests/src/memory/memory_devices/invalid_nvdimm_memory_device_config.py +++ b/libvirt/tests/src/memory/memory_devices/invalid_nvdimm_memory_device_config.py @@ -40,12 +40,12 @@ def define_guest(test, params): # Check libvirt version if libvirt_version.version_compare(9, 0, 0) and \ invalid_setting == "unexisted_node": - define_error = params.get("start_vm_error") + define_error = eval(params.get("start_vm_error", "[]")) elif not libvirt_version.version_compare(9, 9, 0) and \ invalid_setting == "invalid_addr_type": - define_error = params.get("define_error_8") + define_error = eval(params.get("define_error_8", "[]")) else: - define_error = params.get("define_error") + define_error = eval(params.get("define_error", "[]")) # Redefine define_error for checking start_vm_error params.update({"define_error": define_error}) @@ -54,7 +54,7 @@ def define_guest(test, params): vmxml.sync() except Exception as e: if define_error: - if define_error not in str(e): + if not any(s in str(e) for s in define_error): test.fail("Expect to get '%s' error, but got '%s'" % (define_error, e)) else: test.fail("Expect define successfully, but failed with '%s'" % e) @@ -106,8 +106,8 @@ def run_test(): test.log.info("TEST_STEP4: Hotplug nvdimm memory device") mem_obj = memory_base.prepare_mem_obj(nvdimm_dict) result = virsh.attach_device(vm_name, mem_obj.xml, debug=True).stderr_text - if attach_error not in result: - test.fail("Expected get error '%s', but got '%s'" % (attach_error, result)) + if not any(s in result for s in attach_error): + test.fail("Expected get error in '%s', but got '%s'" % (attach_error, result)) def teardown_test(): """ @@ -130,18 +130,18 @@ def teardown_test(): # Get start vm error if libvirt_version.version_compare(9, 0, 0) and \ invalid_setting == "unexisted_node": - start_vm_error = "" + start_vm_error = [] else: - start_vm_error = params.get("start_vm_error") + start_vm_error = eval(params.get("start_vm_error", "[]")) # Get attach error if invalid_setting == "max_addr": - attach_error = params.get('attach_error') + attach_error = eval(params.get("attach_error", "[]")) elif not libvirt_version.version_compare(9, 9, 0) and \ invalid_setting == "invalid_addr_type": - attach_error = params.get('attach_error_8') + attach_error = eval(params.get("attach_error_8", "[]")) else: - attach_error = params.get("start_vm_error", params.get("define_error")) + attach_error = eval(params.get("start_vm_error", params.get("define_error", "[]"))) try: setup_test() From f597c4f691df2cfac4bde3f85959d0c04250ddd6 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Mon, 23 Jun 2025 04:40:23 -0500 Subject: [PATCH 1026/1055] v2v:fix the failed no-shutdown case Signed-off-by: vwu-vera --- v2v/tests/cfg/specific_kvm.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2v/tests/cfg/specific_kvm.cfg b/v2v/tests/cfg/specific_kvm.cfg index 157ade2a5a5..50c37de2f09 100644 --- a/v2v/tests/cfg/specific_kvm.cfg +++ b/v2v/tests/cfg/specific_kvm.cfg @@ -355,7 +355,7 @@ - not_shutdown: only default.kvm only output_mode.local - msg_content = 'virt-v2v: error:.*is running or paused.*must be shut down' + msg_content = 'virt-v2v.*is running or paused' expect_msg = 'yes' variants: - running: From 5359464640c9fe75e76931fb327f2892709baa12 Mon Sep 17 00:00:00 2001 From: zhentang-tz <87700433+zhentang-tz@users.noreply.github.com> Date: Mon, 23 Jun 2025 18:03:35 +0800 Subject: [PATCH 1027/1055] guest os booting: add block device support for NVRAM (#6310) * guest os booting: add block device support for NVRAM add a new scenario for case VIRT-297065 - [OVMF] Boot ovmf vm with different types backed nvram * Switch to using the existing method for generating random strings in utils_misc. Signed-off-by: zhentang-tz --- .../ovmf_firmware/ovmf_backed_nvram.cfg | 5 +++- .../ovmf_firmware/ovmf_backed_nvram.py | 30 ++++++++++++++++--- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.cfg b/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.cfg index 92ed6752f7d..68477f27858 100644 --- a/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.cfg +++ b/libvirt/tests/cfg/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.cfg @@ -5,7 +5,6 @@ template_path = "/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd" os_secure = "yes" firmware_type = "ovmf" - nvram_attrs = {'nvram_attrs': {'template': '${template_path}', 'type': '%s'}} func_supported_since_libvirt_ver = (8, 5, 0) only q35, aarch64 aarch64: @@ -18,3 +17,7 @@ variants source_type: - file: nvram_source = {'nvram_source': {'attrs': {'file': '%s'}}} + nvram_attrs = {'nvram_attrs': {'template': '${template_path}', 'type': 'file'}} + - block: + nvram_source = {'nvram_source': {'attrs': {'dev': '%s'}}} + nvram_attrs = {'nvram_attrs': {'template': '${template_path}', 'type': 'block', 'format': 'qcow2'}} diff --git a/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.py b/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.py index 8a67987dd6d..d5431475966 100644 --- a/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.py +++ b/libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_backed_nvram.py @@ -9,7 +9,9 @@ from virttest import virsh from virttest.data_dir import get_data_dir from virttest.libvirt_xml import vm_xml +from virttest import utils_misc from provider.guest_os_booting import guest_os_booting_base as guest_os +from provider.virtual_disk import disk_base def run(test, params, env): @@ -41,16 +43,34 @@ def compare_guest_xml(vmxml, os_attrs): test.fail("Configured os attributes {} don't existed in guest.".format(key)) test.log.debug("Get expected os xml of guest.") + def create_block_device(): + """ + Setup one scsi_debug block device + + :return: device name + """ + name_term = utils_misc.generate_random_string(4) + disk_obj.lv_name = 'lv_' + name_term + disk_obj.vg_name = 'vg_' + name_term + _, new_image_path = disk_obj.prepare_disk_obj(disk_type='block', disk_dict={}, size='8M', convert_format='qcow2') + return new_image_path + vm_name = guest_os.get_vm(params) firmware_type = params.get("firmware_type") source_type = params.get("source_type") nvram_file = os.path.join(get_data_dir(), "test.fd") - nvram_attrs = eval(params.get("nvram_attrs") % source_type) + nvram_attrs = eval(params.get("nvram_attrs")) os_dict = eval(params.get("os_dict")) - nvram_source = eval(params.get("nvram_source") % nvram_file) - libvirt_version.is_libvirt_feature_supported(params) - vm = env.get_vm(vm_name) + if source_type == 'file': + nvram_source = eval(params.get("nvram_source") % nvram_file) + elif source_type == 'block': + disk_obj = disk_base.DiskBase(test, vm, params) + disk_obj.disk_size = '8M' + image_path = create_block_device() + nvram_source = eval(params.get("nvram_source") % image_path) + test.log.info('the path of nvram:' + image_path) + libvirt_version.is_libvirt_feature_supported(params) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) bkxml = vmxml.copy() @@ -67,4 +87,6 @@ def compare_guest_xml(vmxml, os_attrs): virsh.destroy(vm_name) if os.path.exists(nvram_file): os.remove(nvram_file) + if source_type == 'block': + disk_obj.cleanup_disk_preparation(disk_type='block') bkxml.sync() From 37786f70b8cee6ce0cd2b9392534ddbdf7c763d9 Mon Sep 17 00:00:00 2001 From: zhentang-tz <87700433+zhentang-tz@users.noreply.github.com> Date: Mon, 23 Jun 2025 18:04:25 +0800 Subject: [PATCH 1028/1055] chardev:Add error message handling for serial case (#6258) 1. Added a second version of the error message to the script's expected results to accommodate variations across different environments. 2. switch to libvirt.check_result Signed-off-by: zhentang-tz --- libvirt/tests/cfg/serial/serial_functional.cfg | 2 +- libvirt/tests/src/serial/serial_functional.py | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libvirt/tests/cfg/serial/serial_functional.cfg b/libvirt/tests/cfg/serial/serial_functional.cfg index a01240df9dd..c2845dabcc4 100644 --- a/libvirt/tests/cfg/serial/serial_functional.cfg +++ b/libvirt/tests/cfg/serial/serial_functional.cfg @@ -81,7 +81,7 @@ second_serial_console = yes - connect_to_console_no_serial_device: serial_dev_type = pty - error_msg = "cannot find character device" + error_msg = ["cannot find character device","error: Cannot run interactive console without a controlling TTY"] connect_to_console_without_serial_device = "yes" func_supported_since_libvirt_ver = (10, 3, 0) - type_tls_server: diff --git a/libvirt/tests/src/serial/serial_functional.py b/libvirt/tests/src/serial/serial_functional.py index f476d4beb17..2fbcb748434 100644 --- a/libvirt/tests/src/serial/serial_functional.py +++ b/libvirt/tests/src/serial/serial_functional.py @@ -847,10 +847,9 @@ def get_console_type(): if connect_to_console_without_serial_device: time.sleep(20) # use raw virsh console command since we need to output message from virsh console VM - result = process.run("virsh console %s" % vm_name, shell=True, verbose=True, ignore_status=True).stderr_text - error_msg = params.get("error_msg") - if error_msg not in result: - test.fail(f"Fail to get expected error message:{error_msg} from console") + res = process.run("virsh console %s" % vm_name, shell=True, verbose=True, ignore_status=True) + error_msgs = params.get("error_msg") + libvirt.check_result(res, error_msgs) if params.get("hotunplug_serial", "no") == "yes": error_msg = params.get("error_msg", "").format("detach") From 24d894104e8c1e23df885bd46f23c9e110d3df4d Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Tue, 24 Jun 2025 04:20:19 -0400 Subject: [PATCH 1029/1055] Fix some failures of v2v auto jobs on rhel10 1. Update guest for OGAC SLES case 2. Not check serril driver when virtio-win is not installed 3. Delete vmx_ssh case of v2v_option as it's duplicated with the one of convert_from_file Signed-off-by: Ming Xie --- v2v/tests/cfg/function_test_esx.cfg | 4 ++-- v2v/tests/cfg/v2v_options.cfg | 12 +----------- v2v/tests/src/v2v_options.py | 17 +---------------- 3 files changed, 4 insertions(+), 29 deletions(-) diff --git a/v2v/tests/cfg/function_test_esx.cfg b/v2v/tests/cfg/function_test_esx.cfg index 1536b0a29d6..ebbdf579ba7 100644 --- a/v2v/tests/cfg/function_test_esx.cfg +++ b/v2v/tests/cfg/function_test_esx.cfg @@ -160,7 +160,7 @@ variants: - unset: checkpoint += 'unset' - missing = 'Red Hat VirtIO SCSI,Red Hat VirtIO Ethernet Adapte,VirtIO RNG,VirtIO Serial,VirtIO Balloon' + missing = 'Red Hat VirtIO SCSI,Red Hat VirtIO Ethernet Adapte,VirtIO RNG,VirtIO Balloon' only dest_libvirt - custom: checkpoint += 'custom' @@ -582,7 +582,7 @@ main_vm = VM_NAME_DEBIAN_REPO_V2V_EXAMPLE - sles: only esx_80 - main_vm = VM_NAME_SLES_REPO_V2V_EXAMPLE + main_vm = VM_NAME_SLES_INSTALL_KERNEL_SOURCE_PKG_V2V_EXAMPLE boottype = 3 os_version = "sles" - opensuse: diff --git a/v2v/tests/cfg/v2v_options.cfg b/v2v/tests/cfg/v2v_options.cfg index e9c334e76b5..d919a164167 100644 --- a/v2v/tests/cfg/v2v_options.cfg +++ b/v2v/tests/cfg/v2v_options.cfg @@ -236,16 +236,6 @@ mount_point = /vmx_mnt nfs_vmx = NFS_VMX_V2V_EXAMPLE vmx = ${mount_point}/${main_vm}/${main_vm}.vmx - - vmx_ssh: - only input_mode.none - only output_mode.libvirt - esx_ip = ESX_80_HOSTNAME_V2V_EXAMPLE - esx_host_user = "root" - esx_host_passwd = RHV_NODE_PASSWORD - checkpoint = vmx_ssh - main_vm = VM_NAME_VMX_SSH_V2V_EXAMPLE - output_format = qcow2 - vmx = ssh://root@${esx_ip}/vmfs/volumes/esx8.0-matrix/${main_vm}/${main_vm}.vmx - qemu_session: only input_mode.libvirt.kvm.default only output_mode.libvirt @@ -333,7 +323,7 @@ expect_msg = yes msg_content = "Remove 1 Package" - required_patch: - version_required = "(,virt-v2v-2.4.0-1)" + version_required = "[virt-v2v-2.4.0-1,)" check_command = "rpm -q --changelog %s" checkpoint = check_patch - print_estimate: diff --git a/v2v/tests/src/v2v_options.py b/v2v/tests/src/v2v_options.py index acaaec9834d..f0bc2990c85 100644 --- a/v2v/tests/src/v2v_options.py +++ b/v2v/tests/src/v2v_options.py @@ -477,7 +477,7 @@ def check_alloc(): if output_mode == "libvirt": if "qemu:///session" not in v2v_options and not no_root: virsh.start(vm_name, debug=True, ignore_status=False) - if checkpoint in ['vmx', 'vmx_ssh']: + if checkpoint == 'vmx': vmchecker = VMChecker(test, params, env) params['vmchecker'] = vmchecker params['vmcheck_flag'] = True @@ -821,18 +821,6 @@ def check_alloc(): input_option = '-i vmx %s' % vmx v2v_options += " -b %s -n %s" % (params.get("output_bridge"), params.get("output_network")) - - if checkpoint == 'vmx_ssh': - esx_user = params.get("esx_host_user", "root") - esx_pwd = params.get("esx_host_passwd") - vmx = params.get('vmx') - esx_pubkey, esx_session = utils_v2v.v2v_setup_ssh_key( - esx_ip, esx_user, esx_pwd, server_type='esx', auto_close=False) - utils_misc.add_identities_into_ssh_agent() - input_option = '-i vmx -it ssh %s' % vmx - v2v_options += " -b %s -n %s" % (params.get("output_bridge"), - params.get("output_network")) - if checkpoint == 'simulate_nfs': simulate_images = params.get("simu_images_path") simulate_vms = params.get("simu_vms_path") @@ -941,9 +929,6 @@ def check_alloc(): if checkpoint == 'vmx': utils_misc.umount(params['nfs_vmx'], params['mount_point'], 'nfs') os.rmdir(params['mount_point']) - if checkpoint == 'vmx_ssh': - utils_v2v.v2v_setup_ssh_key_cleanup(esx_session, esx_pubkey, 'esx') - process.run("ssh-agent -k") if checkpoint == 'simulate_nfs': process.run('rm -rf /tmp/rhv/') if os.path.exists(estimate_file): From 0aa603c406607eeadb034dbe7eb1d1cd210f7887 Mon Sep 17 00:00:00 2001 From: cliping Date: Wed, 25 Jun 2025 11:54:45 +0800 Subject: [PATCH 1030/1055] migration: Sleep to wait bandwidth change (#6356) Wait 3 seconds before verifying the bandwidth to make sure it takes effect. Signed-off-by: lcheng --- .../migration_with_copy_storage/migration_bandwidth_limit.cfg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/migration_with_copy_storage/migration_bandwidth_limit.cfg b/libvirt/tests/cfg/migration_with_copy_storage/migration_bandwidth_limit.cfg index 9a78126c730..a27bd06cd2e 100644 --- a/libvirt/tests/cfg/migration_with_copy_storage/migration_bandwidth_limit.cfg +++ b/libvirt/tests/cfg/migration_with_copy_storage/migration_bandwidth_limit.cfg @@ -27,6 +27,7 @@ virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" setup_nfs = "no" nfs_mount_dir = + storage_type = "file" bandwidth = "20" jobinfo_item = "Memory bandwidth:" precopy_bandwidth = "${bandwidth}" @@ -46,7 +47,7 @@ - setspeed_before_migration: - setspeed_during_migration: check_item_value = "9223372036853727232" - action_during_mig = '[{"func": "set_bandwidth", "after_event": "block-job", "func_param": "params", "wait_for_after_event_timeout": "600"}, {"func": "libvirt_disk.check_item_by_blockjob", "func_param": "params"}, {"func": "check_domjobinfo_during_mig", "func_param": "params"}]' + action_during_mig = '[{"func": "set_bandwidth", "after_event": "block-job", "func_param": "params", "wait_for_after_event_timeout": "600"}, {"func": "libvirt_disk.check_item_by_blockjob", "func_param": "params", "need_sleep_time": "3"}, {"func": "check_domjobinfo_during_mig", "func_param": "params"}]' variants: - copy_storage_all: copy_storage_option = "--copy-storage-all" From 437606c3173bc97cb0b50bea1daecd622096e48c Mon Sep 17 00:00:00 2001 From: cliping Date: Wed, 25 Jun 2025 12:02:46 +0800 Subject: [PATCH 1031/1055] migration: Fix nfs service issue (#6383) Update case to make sure the NFS service is started. Signed-off-by: lcheng --- .../migration_misc/migration_with_special_cpu.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/src/migration/migration_misc/migration_with_special_cpu.py b/libvirt/tests/src/migration/migration_misc/migration_with_special_cpu.py index abcc7923298..d1a9a319f9d 100644 --- a/libvirt/tests/src/migration/migration_misc/migration_with_special_cpu.py +++ b/libvirt/tests/src/migration/migration_misc/migration_with_special_cpu.py @@ -96,11 +96,12 @@ def prepare_env_in_vm(vm, vm_hostname, mount_src, mount_dir, desturi_port): vm_session.close() -def prepare_nfs_server_in_vm(vm_ip, params): +def prepare_nfs_server_in_vm(vm_ip, vm, params): """ Prepare nfs server in vm :param vm_ip: VM ip + :param vm: VM object :param params: Dictionary with the test parameters """ server_user = params.get("server_user", "root") @@ -108,6 +109,10 @@ def prepare_nfs_server_in_vm(vm_ip, params): mount_src = params.get("nfs_mount_src") mount_dir = params.get("nfs_mount_dir") + vm_session = vm.wait_for_login() + vm_session.cmd("systemctl restart nfs-server; systemctl restart rpcbind") + vm_session.close() + # prepare nfs server in vm nfs_server_params = { "nfs_setup": True, @@ -164,7 +169,7 @@ def prepare_single_vm(vm, vm_xml, vm_hostname, test): ssh_key.setup_remote_ssh_key(vm2_ip, client_user, client_pwd, vm1_ip, server_user, server_pwd, port=22) test.log.debug("Prepare nfs server in %s.", vm1_ip) - prepare_nfs_server_in_vm(vm1_ip, params) + prepare_nfs_server_in_vm(vm1_ip, vm1, params) hosts_dict = {"%s" % vm1_hostname: "%s" % vm1_ip, "%s" % vm2_hostname: "%s" % vm2_ip} mount_src = vm1_ip + ":" + mount_src From ba273ae91f5f9c0e3fa5cf7f3d8915c41a7e25ef Mon Sep 17 00:00:00 2001 From: cliping Date: Wed, 25 Jun 2025 12:05:19 +0800 Subject: [PATCH 1032/1055] migration: Update loop time (#6394) Update loop time to ensure the VM is in running state when executing the command. Signed-off-by: lcheng --- .../cfg/migration/async_ops/query_info_during_migration.cfg | 2 +- provider/migration/migration_base.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/migration/async_ops/query_info_during_migration.cfg b/libvirt/tests/cfg/migration/async_ops/query_info_during_migration.cfg index 69ca4213e8f..bc8d99f0eb1 100644 --- a/libvirt/tests/cfg/migration/async_ops/query_info_during_migration.cfg +++ b/libvirt/tests/cfg/migration/async_ops/query_info_during_migration.cfg @@ -31,7 +31,7 @@ loop_disk_type = "block" block_device = "${nfs_mount_dir}/query_info_test.img" migrate_speed = "15" - loop_time = "20" + loop_time = "10" variants: - p2p: virsh_migrate_options = '--live --p2p --verbose' diff --git a/provider/migration/migration_base.py b/provider/migration/migration_base.py index 7e7cf6fb900..4e60a4645c6 100644 --- a/provider/migration/migration_base.py +++ b/provider/migration/migration_base.py @@ -293,7 +293,7 @@ def execute_statistics_command(params): """ vm_name = params.get("migrate_main_vm") disk_type = params.get("loop_disk_type") - loop_time = params.get("loop_time", "20") + loop_time = params.get("loop_time", "1") vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) if disk_type: From 0389064f7f357819601c48927df1ba29a138e91e Mon Sep 17 00:00:00 2001 From: cliping Date: Wed, 25 Jun 2025 12:17:35 +0800 Subject: [PATCH 1033/1055] migration: Update error message (#6398) Signed-off-by: lcheng --- .../kill_qemu_during_performphase.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_performphase.cfg b/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_performphase.cfg index c04e4dc4012..cdcbc4a2b73 100644 --- a/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_performphase.cfg +++ b/libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_qemu_during_performphase.cfg @@ -47,7 +47,7 @@ expected_dest_state = "nonexist" expected_src_state = "running" migrate_speed = "1" - err_msg = "QEMU unexpectedly closed the monitor|Unable to read from socket: Connection reset by peer" + err_msg = "QEMU unexpectedly closed the monitor|Unable to read from socket: Connection reset by peer|Channel error: Input/output error" check_disk_on_dest = "no" virsh_migrate_extra = "--bandwidth 1000" - kill_dest_qemu_after_vm_paused: @@ -58,7 +58,7 @@ expected_dest_state = "nonexist" expected_src_state = "running" virsh_migrate_extra = "--timeout 2 --timeout-suspend --bandwidth 1000" - err_msg = "QEMU unexpectedly closed the monitor|Unable to read from socket: Connection reset by peer" + err_msg = "QEMU unexpectedly closed the monitor|Unable to read from socket: Connection reset by peer|Channel error: Input/output error" - kill_src_qemu: expected_dest_state = "nonexist" expected_src_state = "shut off" From 62ddea0d465615405856fb1eb58d18041c2076af Mon Sep 17 00:00:00 2001 From: Ming Xie Date: Wed, 25 Jun 2025 04:59:06 -0400 Subject: [PATCH 1034/1055] Fix some failures of v2v specific_kvm job 1. Adjust cases about no space scenarios 2. Change the error info for cases about running guest 3. Improve the checkpoint of cases about time sync Signed-off-by: Ming Xie --- v2v/tests/cfg/specific_kvm.cfg | 10 +++++++--- v2v/tests/src/specific_kvm.py | 21 ++++++++++++++++----- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/v2v/tests/cfg/specific_kvm.cfg b/v2v/tests/cfg/specific_kvm.cfg index 50c37de2f09..b3d5763157f 100644 --- a/v2v/tests/cfg/specific_kvm.cfg +++ b/v2v/tests/cfg/specific_kvm.cfg @@ -233,9 +233,9 @@ checkpoint = 'ntpd_on' - sync_ntp: checkpoint = 'sync_ntp' - - no_space: + - set_cache_dir: only esx.esx_70 - checkpoint = 'host_no_space_setcache' + checkpoint = 'set_cache_dir' main_vm = 'VM_ESX_DEFAULT_NAME_V2V_EXAMPLE' - no_libguestfs_backend: only esx.esx_70 @@ -355,7 +355,7 @@ - not_shutdown: only default.kvm only output_mode.local - msg_content = 'virt-v2v.*is running or paused' + msg_content = 'virt-v2v: warning:.*Converting a live guest will result in corrupted output.' expect_msg = 'yes' variants: - running: @@ -377,5 +377,9 @@ main_vm = "VM_GUEST_NO_SPACE_V2V_EXAMPLE" checkpoint = 'host_no_space' msg_content = 'virt-v2v: error: insufficient free space in the conversion server' + - guest: + only default.esx.esx_70 + main_vm = "VM_GUEST_NO_SPACE_V2V_EXAMPLE" + msg_content = 'virt-v2v: error: not enough free space for conversion on filesystem' - fstab_invalid: only fstab.invalid diff --git a/v2v/tests/src/specific_kvm.py b/v2v/tests/src/specific_kvm.py index 9de36da468c..db126ccd15c 100644 --- a/v2v/tests/src/specific_kvm.py +++ b/v2v/tests/src/specific_kvm.py @@ -2,6 +2,7 @@ import re import logging import string +import time import aexpect import xml.etree.ElementTree as ET @@ -520,8 +521,18 @@ def check_time_keep(vmcheck): Check time drift after conversion. """ LOG.info('Check time drift') - output = vmcheck.session.cmd('chronyc tracking') - LOG.debug(output) + + def chronyc_output(): + for i in range(3): + output = vmcheck.session.cmd('chronyc tracking') + LOG.debug(output) + if 'Not synchronised' in output: + time.sleep(20) + else: + return output + return output + + output = chronyc_output() if 'Not synchronised' in output: log_fail('Time not synchronised') lst_offset = re.search('Last offset *?: *(.*) ', output).group(1) @@ -765,9 +776,9 @@ def check_result(result, status_error): if checkpoint.startswith('host_no_space'): session = aexpect.ShellSession('sh') large_file = create_large_file(session, 800) - if checkpoint == 'host_no_space_setcache': - LOG.info('Set LIBGUESTFS_CACHEDIR=/home') - os.environ['LIBGUESTFS_CACHEDIR'] = '/home' + if checkpoint == 'set_cache_dir': + LOG.info('Set LIBGUESTFS_CACHEDIR=/home') + os.environ['LIBGUESTFS_CACHEDIR'] = '/home' if checkpoint.startswith('network'): change_network_model(checkpoint[8:]) if checkpoint == 'multi_netcards': From f6360c8263ad562d242547cc9752e8430e94bdd8 Mon Sep 17 00:00:00 2001 From: cliping Date: Thu, 26 Jun 2025 16:49:27 +0800 Subject: [PATCH 1035/1055] migration: Update pause by network test case (#6403) For libvirt layer network broken, recover postcopy migration step will fail because qemu migration still running. So updated auto script. Signed-off-by: lcheng --- .../pause_by_network_and_recover.cfg | 18 +++++++++++------- .../pause_by_network_and_recover.py | 13 +++++++++---- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_by_network_and_recover.cfg b/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_by_network_and_recover.cfg index 2839312e20a..b3dc700e847 100644 --- a/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_by_network_and_recover.cfg +++ b/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_by_network_and_recover.cfg @@ -27,10 +27,8 @@ stress_package = "stress" stress_args = "--cpu 8 --io 4 --vm 2 --vm-bytes 128M --timeout 20s" postcopy_options = "--timeout 4 --timeout-postcopy --postcopy --postcopy-bandwidth 5" - action_during_mig = '[{"func": "libvirt_network.check_established", "after_event": "iteration: '1'", "func_param": 'params'}, {"func": "libvirt_network.setup_firewall_rule", "func_param": "params", "need_sleep_time": "5"}, {"func": "do_common_check", "func_param": "params", "need_sleep_time": "90"}, {"func": "libvirt_network.cleanup_firewall_rule", "func_param": "params"}]' + action_during_mig = '[{"func": "libvirt_network.check_established", "after_event": "iteration: '1'", "func_param": 'params'}, {"func": "libvirt_network.setup_firewall_rule", "func_param": "params", "need_sleep_time": "5"}]' migrate_again = 'yes' - migrate_again_status_error = 'no' - action_during_mig_again = '[{"func": "do_common_check", "before_pause": "yes", "func_param": "params"}, {"func": "set_migrate_speed_to_high", "before_pause": "yes", "func_param": "params"}]' virsh_migrate_extra_mig_again = "--timeout 4 --timeout-postcopy --postcopy --postcopy-resume" postcopy_resume_migration = "yes" migrate_speed_high = "1048576" @@ -38,12 +36,10 @@ expected_dest_state = "running" expected_src_state = "paused" dominfo_check = "Persistent: no" - expected_event_src = ["event 'lifecycle' for domain.*: Suspended Post-copy Error", "event 'lifecycle' for domain .*: Suspended Post-copy", "event 'lifecycle' for domain .*: Stopped Migrated", "event 'job-completed' for domain"] - expected_event_target = ["event 'lifecycle' for domain.*: Resumed Post-copy Error", "event 'lifecycle' for domain.*: Resumed Post-copy", "event 'lifecycle' for domain.*: Resumed Migrated"] migrate_desturi_port = "16509" migrate_desturi_type = "tcp" virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" - tcp_config_list = '{"tcp_keepalive_probes": "9", "tcp_keepalive_intvl": "60", "tcp_retries1": "4", "tcp_retries2": "8", "tcp_fin_timeout": "2"}' + tcp_config_list = '{"tcp_keepalive_probes": "3", "tcp_keepalive_intvl": "3", "tcp_retries1": "1", "tcp_retries2": "1", "tcp_fin_timeout": "2"}' recover_tcp_config_list = '{"tcp_keepalive_probes": "9", "tcp_keepalive_intvl": "75", "tcp_retries1": "3", "tcp_retries2": "15", "tcp_fin_timeout": "60"}' func_supported_since_libvirt_ver = (8, 5, 0) @@ -68,7 +64,15 @@ firewall_rule_on_dest = "ipv4 filter INPUT 0 -p tcp --dport ${port_to_check} -j DROP" firewall_rule_on_src = "ipv4 filter INPUT 0 -p tcp --sport ${port_to_check} -j DROP" err_msg = "job 'migration in' failed in post-copy phase" + migrate_again_status_error = 'no' + action_during_mig_again = '[{"func": "do_common_check", "before_pause": "yes", "func_param": "params"}, {"func": "set_migrate_speed_to_high", "before_pause": "yes", "func_param": "params"}]' + expected_event_src = ["event 'lifecycle' for domain.*: Suspended Post-copy Error", "event 'lifecycle' for domain .*: Suspended Post-copy", "event 'lifecycle' for domain .*: Stopped Migrated", "event 'job-completed' for domain"] + expected_event_target = ["event 'lifecycle' for domain.*: Resumed Post-copy Error", "event 'lifecycle' for domain.*: Resumed Post-copy", "event 'lifecycle' for domain.*: Resumed Migrated"] - libvirt_layer: firewall_rule_on_dest = "ipv4 filter INPUT 0 -p tcp --dport ${migrate_desturi_port} -j DROP" firewall_rule_on_src = "ipv4 filter INPUT 0 -p tcp --sport ${migrate_desturi_port} -j DROP" - err_msg = "internal error: client socket is closed|connection closed due to keepalive timeout" + err_msg = "internal error: client socket is closed|connection closed due to keepalive timeout|Cannot recv data: Connection timed out" + migrate_again_status_error = 'yes' + err_msg_again = "QEMU reports migration is still running" + expected_event_src = ["event 'lifecycle' for domain.*: Suspended Post-copy Error", "event 'lifecycle' for domain .*: Suspended Post-copy"] + expected_event_target = ["event 'lifecycle' for domain.*: Resumed Post-copy"] diff --git a/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/pause_by_network_and_recover.py b/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/pause_by_network_and_recover.py index a0bb401dd43..13e7834c528 100644 --- a/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/pause_by_network_and_recover.py +++ b/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/pause_by_network_and_recover.py @@ -30,12 +30,11 @@ def verify_test(): dominfo = virsh.dominfo(vm_name, ignore_status=True, debug=True, uri=dest_uri) libvirt.check_result(dominfo, expected_match=dominfo_check) + migration_obj.verify_default() # check qemu-guest-agent command result = virsh.domtime(vm_name, ignore_status=True, debug=True, uri=dest_uri) libvirt.check_exit_status(result) - migration_obj.verify_default() - # Check event output migration_base.check_event_output(params, test, virsh_session, remote_virsh_session) @@ -45,6 +44,7 @@ def verify_test(): migrate_again = "yes" == params.get("migrate_again", "no") tcp_config_list = eval(params.get("tcp_config_list")) recover_tcp_config_list = eval(params.get("recover_tcp_config_list")) + remove_firewall_rule = False virsh_session = None remote_virsh_session = None @@ -55,14 +55,19 @@ def verify_test(): try: base_steps.setup_network_data_transport(params) - libvirt_network.change_tcp_config(tcp_config_list) + libvirt_network.change_tcp_config(tcp_config_list, params) migration_obj.setup_connection() # Monitor event on source/target host virsh_session, remote_virsh_session = migration_base.monitor_event(params) migration_obj.run_migration() + migration_base.do_common_check(params) + libvirt_network.cleanup_firewall_rule(params) + remove_firewall_rule = True if migrate_again: migration_obj.run_migration_again() verify_test() finally: - libvirt_network.change_tcp_config(recover_tcp_config_list) + if not remove_firewall_rule: + libvirt_network.cleanup_firewall_rule(params) + libvirt_network.change_tcp_config(recover_tcp_config_list, params) migration_obj.cleanup_connection() From d93bbedc99a8ed1f739bdf5eaf915f75b7c7089b Mon Sep 17 00:00:00 2001 From: lcheng Date: Thu, 26 Jun 2025 09:55:57 +0800 Subject: [PATCH 1036/1055] migration: Update cases about tcp connections Update tcp configurations parameters to make tcp connections timeout more quickly. Signed-off-by: lcheng --- .../pause_and_recover_and_disruptive.cfg | 4 ++-- .../pause_and_recover_twice.cfg | 4 ++-- .../unattended_migration.cfg | 3 ++- .../unattended_migration_and_disruptive.cfg | 4 ++-- .../pause_and_recover_and_disruptive.py | 4 ++-- .../pause_and_recover_twice.py | 4 ++-- .../unattended_migration.py | 13 ++++++++++--- .../unattended_migration_and_disruptive.py | 4 ++-- 8 files changed, 24 insertions(+), 16 deletions(-) diff --git a/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_and_recover_and_disruptive.cfg b/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_and_recover_and_disruptive.cfg index 369cdd13b42..98900a1086d 100644 --- a/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_and_recover_and_disruptive.cfg +++ b/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_and_recover_and_disruptive.cfg @@ -77,9 +77,9 @@ virsh_migrate_extra = "--migrateuri tcp://${migrate_dest_host}:${port_to_check} --listen-address ${migrate_dest_host}" firewall_rule_on_dest = "ipv4 filter INPUT 0 -p tcp --dport ${port_to_check} -j DROP" firewall_rule_on_src = "ipv4 filter INPUT 0 -p tcp --sport ${port_to_check} -j DROP" - action_during_do_mig = '[{"func": "libvirt_network.setup_firewall_rule", "func_param": "params", "need_sleep_time": "10"}, {"func": "libvirt_network.cleanup_firewall_rule", "func_param": "params", "need_sleep_time": "90"}]' + action_during_do_mig = '[{"func": "libvirt_network.setup_firewall_rule", "func_param": "params", "need_sleep_time": "10"}, {"func": "libvirt_network.cleanup_firewall_rule", "func_param": "params", "need_sleep_time": "10"}]' status_error_during_mig = "no" - tcp_config_list = '{"tcp_keepalive_probes": "9", "tcp_keepalive_intvl": "60", "tcp_retries1": "4", "tcp_retries2": "8", "tcp_fin_timeout": "2"}' + tcp_config_list = '{"tcp_keepalive_probes": "3", "tcp_keepalive_intvl": "3", "tcp_retries1": "1", "tcp_retries2": "1", "tcp_fin_timeout": "2"}' recover_tcp_config_list = '{"tcp_keepalive_probes": "9", "tcp_keepalive_intvl": "75", "tcp_retries1": "3", "tcp_retries2": "15", "tcp_fin_timeout": "60"}' - pause_by_proxy_issue: action_during_do_mig = '[{"func": "clear_pmsocat", "func_param": "params", "need_sleep_time": "5"}, {"func": "base_steps.recreate_conn_objs", "func_param": "params", "need_sleep_time": "10"}]' diff --git a/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_and_recover_twice.cfg b/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_and_recover_twice.cfg index c7ece41cce3..8c78bdd7dc0 100644 --- a/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_and_recover_twice.cfg +++ b/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/pause_and_recover_twice.cfg @@ -46,12 +46,12 @@ virsh_migrate_extra = "--migrateuri tcp://${migrate_dest_host}:${port_to_check} --listen-address ${migrate_dest_host}" firewall_rule_on_dest = "ipv4 filter INPUT 0 -p tcp --dport ${port_to_check} -j DROP" firewall_rule_on_src = "ipv4 filter INPUT 0 -p tcp --sport ${port_to_check} -j DROP" - action_during_mig = '[{"func": "libvirt_network.check_established", "after_event": "iteration: '1'", "func_param": 'params'}, {"func": "virsh.domjobabort", "func_param": "'%s --postcopy' % params.get('migrate_main_vm')", "need_sleep_time": "5"}, {"func": "libvirt_network.setup_firewall_rule", "func_param": "params"}, {"func": "do_migration", "func_param": "params", "need_sleep_time": "90"}, {"func": "libvirt_network.cleanup_firewall_rule", "func_param": "params", "need_sleep_time": "5"}, {"func": "resume_migration_again", "func_param": "params", "need_sleep_time": "5"}]' + action_during_mig = '[{"func": "libvirt_network.check_established", "after_event": "iteration: '1'", "func_param": 'params'}, {"func": "virsh.domjobabort", "func_param": "'%s --postcopy' % params.get('migrate_main_vm')", "need_sleep_time": "5"}, {"func": "libvirt_network.setup_firewall_rule", "func_param": "params"}, {"func": "do_migration", "func_param": "params", "need_sleep_time": "15"}, {"func": "libvirt_network.cleanup_firewall_rule", "func_param": "params", "need_sleep_time": "5"}, {"func": "resume_migration_again", "func_param": "params", "need_sleep_time": "5"}]' migrate_desturi_port = "16509" migrate_desturi_type = "tcp" virsh_migrate_desturi = "qemu+tcp://${migrate_dest_host}/system" err_msg_during_mig = "unable to connect to server at.*: Connection timed out" - tcp_config_list = '{"tcp_keepalive_probes": "9", "tcp_keepalive_intvl": "60", "tcp_retries1": "4", "tcp_retries2": "8", "tcp_fin_timeout": "2"}' + tcp_config_list = '{"tcp_keepalive_probes": "3", "tcp_keepalive_intvl": "3", "tcp_retries1": "1", "tcp_retries2": "1", "tcp_fin_timeout": "2"}' recover_tcp_config_list = '{"tcp_keepalive_probes": "9", "tcp_keepalive_intvl": "75", "tcp_retries1": "3", "tcp_retries2": "15", "tcp_fin_timeout": "60"}' - proxy_issue: transport_type = "unix_proxy" diff --git a/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/unattended_migration.cfg b/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/unattended_migration.cfg index 924b88f0fba..6e2c46501a0 100644 --- a/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/unattended_migration.cfg +++ b/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/unattended_migration.cfg @@ -67,9 +67,10 @@ expected_event_src = ["event 'lifecycle' for domain .*: Suspended Post-copy"] expected_event_src_2 = ["event 'lifecycle' for domain .*: Stopped Migrated", "event 'job-completed' for domain"] expected_event_target = ["event 'lifecycle' for domain.*: Resumed Post-copy", "event 'lifecycle' for domain.*: Resumed Migrated"] - tcp_config_list = '{"tcp_keepalive_probes": "9", "tcp_keepalive_intvl": "60", "tcp_retries1": "4", "tcp_retries2": "8", "tcp_fin_timeout": "2"}' + tcp_config_list = '{"tcp_keepalive_probes": "3", "tcp_keepalive_intvl": "3", "tcp_retries1": "1", "tcp_retries2": "1", "tcp_fin_timeout": "2"}' recover_tcp_config_list = '{"tcp_keepalive_probes": "9", "tcp_keepalive_intvl": "75", "tcp_retries1": "3", "tcp_retries2": "15", "tcp_fin_timeout": "60"}' action_during_mig = '[{"func": "libvirt_network.check_established", "after_event": "iteration: '1'", "func_param": 'params'}, {"func": "check_event_before_unattended", "func_param": "params"}, {"func": "libvirt_network.setup_firewall_rule", "func_param": "params"}, {"func": "do_common_check", "func_param": "params", "need_sleep_time": "90"}, {"func": "wait_for_unattended_mig", "func_param": "params"}, {"func": "libvirt_network.cleanup_firewall_rule", "func_param": "params"}]' + action_during_mig = '[{"func": "libvirt_network.check_established", "after_event": "iteration: '1'", "func_param": 'params'}, {"func": "check_event_before_unattended", "func_param": "params"}, {"func": "libvirt_network.setup_firewall_rule", "func_param": "params"}, {"func": "do_common_check", "func_param": "params", "need_sleep_time": "15"}, {"func": "wait_for_unattended_mig", "func_param": "params"}]' variants migration_options: - with_undefinesource_persistent: virsh_migrate_extra = "--undefinesource --persistent" diff --git a/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/unattended_migration_and_disruptive.cfg b/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/unattended_migration_and_disruptive.cfg index 09ee9aa2914..0518e945144 100644 --- a/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/unattended_migration_and_disruptive.cfg +++ b/libvirt/tests/cfg/migration/pause_postcopy_migration_and_recover/unattended_migration_and_disruptive.cfg @@ -64,10 +64,10 @@ virsh_migrate_extra = "--migrateuri tcp://${migrate_dest_host}:${port_to_check} --listen-address ${migrate_dest_host}" firewall_rule_on_dest = "ipv4 filter INPUT 0 -p tcp --dport ${port_to_check} -j DROP" firewall_rule_on_src = "ipv4 filter INPUT 0 -p tcp --sport ${port_to_check} -j DROP" - action_during_mig = '[{"func": "libvirt_network.check_established", "after_event": "iteration: '1'", "func_param": 'params'}, {"func": "libvirt_service.kill_service", "func_param": "params"}, {"func": "libvirt_network.setup_firewall_rule", "func_param": "params", "need_sleep_time": "5"}, {"func": "libvirt_network.cleanup_firewall_rule", "func_param": "params", "need_sleep_time": "90"}, {"func": "do_migration", "func_param": "params", "need_sleep_time": "10"}]' + action_during_mig = '[{"func": "libvirt_network.check_established", "after_event": "iteration: '1'", "func_param": 'params'}, {"func": "libvirt_service.kill_service", "func_param": "params"}, {"func": "libvirt_network.setup_firewall_rule", "func_param": "params", "need_sleep_time": "5"}, {"func": "libvirt_network.cleanup_firewall_rule", "func_param": "params", "need_sleep_time": "10"}, {"func": "do_migration", "func_param": "params", "need_sleep_time": "10"}]' status_error = "no" status_error_during_mig = "no" - tcp_config_list = '{"tcp_keepalive_probes": "9", "tcp_keepalive_intvl": "60", "tcp_retries1": "4", "tcp_retries2": "8", "tcp_fin_timeout": "2"}' + tcp_config_list = '{"tcp_keepalive_probes": "3", "tcp_keepalive_intvl": "3", "tcp_retries1": "1", "tcp_retries2": "1", "tcp_fin_timeout": "2"}' recover_tcp_config_list = '{"tcp_keepalive_probes": "9", "tcp_keepalive_intvl": "75", "tcp_retries1": "3", "tcp_retries2": "15", "tcp_fin_timeout": "60"}' action_during_do_mig = '[{"func": "set_migrate_speed_to_high", "before_pause": "yes", "func_param": "params"}]' - pause_by_proxy: diff --git a/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/pause_and_recover_and_disruptive.py b/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/pause_and_recover_and_disruptive.py index 0494973f2b2..436b0e646cf 100644 --- a/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/pause_and_recover_and_disruptive.py +++ b/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/pause_and_recover_and_disruptive.py @@ -21,7 +21,7 @@ def setup_pause_by_network(): """ test.log.info("Setup for pause_by_network") tcp_config_list = eval(params.get("tcp_config_list")) - libvirt_network.change_tcp_config(tcp_config_list) + libvirt_network.change_tcp_config(tcp_config_list, params) migration_obj.setup_connection() def cleanup_pause_by_network(): @@ -31,7 +31,7 @@ def cleanup_pause_by_network(): """ test.log.info("Cleanup for pause_by_network") recover_tcp_config_list = eval(params.get("recover_tcp_config_list")) - libvirt_network.change_tcp_config(recover_tcp_config_list) + libvirt_network.change_tcp_config(recover_tcp_config_list, params) migration_obj.cleanup_connection() libvirt_version.is_libvirt_feature_supported(params) diff --git a/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/pause_and_recover_twice.py b/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/pause_and_recover_twice.py index 9880d25eb3f..b52dcd2ce16 100644 --- a/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/pause_and_recover_twice.py +++ b/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/pause_and_recover_twice.py @@ -21,7 +21,7 @@ def setup_network_issue(): """ test.log.info("Setup for network issue") tcp_config_list = eval(params.get("tcp_config_list")) - libvirt_network.change_tcp_config(tcp_config_list) + libvirt_network.change_tcp_config(tcp_config_list, params) migration_obj.setup_connection() def cleanup_network_issue(): @@ -31,7 +31,7 @@ def cleanup_network_issue(): """ test.log.info("Cleanup for network issue") recover_tcp_config_list = eval(params.get("recover_tcp_config_list")) - libvirt_network.change_tcp_config(recover_tcp_config_list) + libvirt_network.change_tcp_config(recover_tcp_config_list, params) migration_obj.cleanup_connection() libvirt_version.is_libvirt_feature_supported(params) diff --git a/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/unattended_migration.py b/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/unattended_migration.py index 39642226150..44eaa2d56a7 100644 --- a/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/unattended_migration.py +++ b/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/unattended_migration.py @@ -39,7 +39,7 @@ def setup_network_issue_libvirt_layer(): """ test.log.info("Setup for network_issue_libvirt_layer.") tcp_config_list = eval(params.get("tcp_config_list")) - libvirt_network.change_tcp_config(tcp_config_list) + libvirt_network.change_tcp_config(tcp_config_list, params) migration_obj.setup_connection() def verify_test(): @@ -51,6 +51,9 @@ def verify_test(): dominfo_check = params.get("dominfo_check") migration_options = params.get("migration_options") + if make_unattended == "network_issue_libvirt_layer": + libvirt_network.cleanup_firewall_rule(params) + remote_firewall_rule = True # check domain persistence if dominfo_check: dominfo = virsh.dominfo(vm_name, ignore_status=True, debug=True, uri=dest_uri) @@ -61,7 +64,8 @@ def verify_test(): func_returns = dict(migration_obj.migration_test.func_ret) migration_obj.migration_test.func_ret.clear() test.log.debug("Migration returns function results:%s", func_returns) - if not libvirt.check_vm_state(vm_name, virsh_migrate_src_state, uri=migration_obj.src_uri): + if not libvirt.check_vm_state(vm_name, virsh_migrate_src_state, + uri=migration_obj.src_uri, debug=True): test.fail("Migrated VMs failed to be in %s state at source" % virsh_migrate_src_state) if int(migration_obj.migration_test.ret.exit_status) == 0: migration_obj.migration_test.post_migration_check([vm], params, @@ -76,13 +80,16 @@ def cleanup_network_issue_libvirt_layer(): """ test.log.info("Cleanup for network_issue_libvirt_layer") recover_tcp_config_list = eval(params.get("recover_tcp_config_list")) - libvirt_network.change_tcp_config(recover_tcp_config_list) + if not remote_firewall_rule: + libvirt_network.cleanup_firewall_rule(params) + libvirt_network.change_tcp_config(recover_tcp_config_list, params) migration_obj.cleanup_connection() libvirt_version.is_libvirt_feature_supported(params) vm_name = params.get("migrate_main_vm") make_unattended = params.get("make_unattended") + remote_firewall_rule = False virsh_session = None remote_virsh_session = None diff --git a/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/unattended_migration_and_disruptive.py b/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/unattended_migration_and_disruptive.py index 3074ff219b6..1bdb01ed647 100644 --- a/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/unattended_migration_and_disruptive.py +++ b/libvirt/tests/src/migration/pause_postcopy_migration_and_recover/unattended_migration_and_disruptive.py @@ -22,7 +22,7 @@ def setup_pause_by_network(): """ test.log.info("Setup for pause_by_network.") tcp_config_list = eval(params.get("tcp_config_list")) - libvirt_network.change_tcp_config(tcp_config_list) + libvirt_network.change_tcp_config(tcp_config_list, params) migration_obj.setup_connection() def cleanup_pause_by_network(): @@ -32,7 +32,7 @@ def cleanup_pause_by_network(): """ test.log.info("Cleanup for pause_by_network") recover_tcp_config_list = eval(params.get("recover_tcp_config_list")) - libvirt_network.change_tcp_config(recover_tcp_config_list) + libvirt_network.change_tcp_config(recover_tcp_config_list, params) migration_obj.cleanup_connection() libvirt_version.is_libvirt_feature_supported(params) From 33da02d4800a089d112a1102d45cd8036d6b6307 Mon Sep 17 00:00:00 2001 From: Lily Zhu Date: Fri, 27 Jun 2025 09:56:35 +0800 Subject: [PATCH 1037/1055] Add the case of ssh proxy for vsock (#6224) Signed-off-by: Lili Zhu Co-authored-by: root --- libvirt/tests/cfg/virtual_device/vsock.cfg | 6 ++ libvirt/tests/src/virtual_device/vsock.py | 67 +++++++++++++++++++++- 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/libvirt/tests/cfg/virtual_device/vsock.cfg b/libvirt/tests/cfg/virtual_device/vsock.cfg index a2f01b4ba90..25acdac1b90 100644 --- a/libvirt/tests/cfg/virtual_device/vsock.cfg +++ b/libvirt/tests/cfg/virtual_device/vsock.cfg @@ -31,6 +31,12 @@ - edit_start: start_vm = "no" edit_xml = "yes" + - ssh_proxy: + func_supported_since_libvirt_ver = (10, 4, 0) + start_vm = "no" + guest_user = "guest_user" + guest_user_passwd = "123456" + systemd_version_cmd = "rpm -q systemd | awk -F'-' '{print $2}'" - negative_test: status_error = no variants: diff --git a/libvirt/tests/src/virtual_device/vsock.py b/libvirt/tests/src/virtual_device/vsock.py index e8df713ac8c..61498bd6d17 100644 --- a/libvirt/tests/src/virtual_device/vsock.py +++ b/libvirt/tests/src/virtual_device/vsock.py @@ -9,9 +9,12 @@ from avocado.utils import process +from virttest import libvirt_version +from virttest import ssh_key from virttest import virsh from virttest import utils_test from virttest import utils_misc +from virttest import utils_package from virttest.utils_test import libvirt from virttest.libvirt_xml import vm_xml from virttest.libvirt_xml.devices.vsock import Vsock @@ -183,6 +186,43 @@ def managedsave_restore(): result = virsh.start(vm_name) utils_test.libvirt.check_exit_status(result, expect_error=False) + def add_guest_user(name, passwd): + """ + Added a user account in guest + + :param name: user name + :param passwd: password of user account + """ + try: + session = vm.wait_for_login() + session.cmd_output('useradd %s' % name) + finally: + session.close() + virsh.set_user_password(vm_name, name, passwd, debug=True) + + def forward_vsock_to_sshd(): + """ + Run a service that forwards VSOCK <=> SSHD communication + """ + + session = vm.wait_for_login() + try: + session.cmd("socat VSOCK-LISTEN:22,reuseaddr,fork TCP:localhost:22 &") + except Exception as e: + test.fail("Forwarding vsock to sshd communication failed: %s" % e) + + def check_systemd_version(): + """ + Check the version of systemd inside the guest + """ + try: + session = vm.wait_for_login() + systemd_version = session.cmd_output(systemd_version_cmd) + logging.debug("systemd version of guest is %s" % systemd_version) + finally: + session.close() + return systemd_version + start_vm = params.get("start_vm", "no") vm_name = params.get("main_vm", "avocado-vt-vm1") vm = env.get_vm(params["main_vm"]) @@ -197,6 +237,9 @@ def managedsave_restore(): vsock_num = params.get("num") communication = params.get("communication", "no") == "yes" detach_device_alias = params.get("detach_device_alias", "no") == "yes" + guest_user = params.get("guest_user") + guest_user_passwd = params.get("guest_user_passwd") + systemd_version_cmd = params.get("systemd_version_cmd") # Backup xml file vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() @@ -217,7 +260,7 @@ def managedsave_restore(): logging.debug(vsock_dev) if start_vm == "no" and vm.is_alive(): - virsh.destroy() + vm.destroy() try: if edit_xml: @@ -244,6 +287,28 @@ def managedsave_restore(): else: result = virsh.start(vm_name, debug=True) utils_test.libvirt.check_exit_status(result, expect_error=False) + elif guest_user: + libvirt_version.is_libvirt_feature_supported(params) + if not utils_package.package_install(["libvirt-ssh-proxy"]): + test.cancel("Failed to install libvirt-ssh-proxy on host") + + vmxml.add_device(vsock_dev) + vmxml.sync() + logging.debug(vmxml) + vm.start() + vm_ip = vm.wait_for_get_address(0, timeout=60) + vm.prepare_guest_agent() + add_guest_user(guest_user, guest_user_passwd) + ssh_key.setup_ssh_key(vm_ip, guest_user, guest_user_passwd) + + if int(check_systemd_version()) < 256: + forward_vsock_to_sshd() + + # For convenienence in automation, Fully disable host key checking. + ssh_proxy_cmd = ("ssh -o StrictHostKeyChecking=no %s@qemu/%s hostname" + % (guest_user, vm_name)) + if process.run(ssh_proxy_cmd, shell=True, ignore_status=True).exit_status != 0: + test.fail("ssh proxy for vsock is not working.") else: session = vm.wait_for_login() session.close() From 5783b8ae059a8149187a865e7220041818106249 Mon Sep 17 00:00:00 2001 From: Yalan Zhang Date: Fri, 27 Jun 2025 19:00:58 +0800 Subject: [PATCH 1038/1055] Dumpxml by managedsave-dumpxml (#6298) Dumpxml from managedsaved vm by managedsave-dumpxml cmd with different options. Automate case VIRT-297773. Signed-off-by: Yalan Zhang --- .../save_and_restore/managedsave_dumpxml.cfg | 21 ++++ .../save_and_restore/managedsave_dumpxml.py | 101 ++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 libvirt/tests/cfg/save_and_restore/managedsave_dumpxml.cfg create mode 100644 libvirt/tests/src/save_and_restore/managedsave_dumpxml.py diff --git a/libvirt/tests/cfg/save_and_restore/managedsave_dumpxml.cfg b/libvirt/tests/cfg/save_and_restore/managedsave_dumpxml.cfg new file mode 100644 index 00000000000..f839742e367 --- /dev/null +++ b/libvirt/tests/cfg/save_and_restore/managedsave_dumpxml.cfg @@ -0,0 +1,21 @@ +- save_and_restore.managedsave_dumpxml: + type = managedsave_dumpxml + graphic_attrs = {'listen_attrs': {'type': 'address'}, 'type_name': 'vnc', 'autoport': 'yes', 'passwd': '12345'} + variants: + - no_option: + option = "" + - security_info: + option = "--security-info" + - xpath: + option = "--xpath //os" + - wrap: + option = "--xpath //os --wrap" + variants: + - not_readonly: + - readonly: + only no_option, security_info + readonly = "yes" + security_info: + err_msg = "operation forbidden: virDomainManagedSaveGetXMLDesc with secure flag" + + diff --git a/libvirt/tests/src/save_and_restore/managedsave_dumpxml.py b/libvirt/tests/src/save_and_restore/managedsave_dumpxml.py new file mode 100644 index 00000000000..0fa868bdb54 --- /dev/null +++ b/libvirt/tests/src/save_and_restore/managedsave_dumpxml.py @@ -0,0 +1,101 @@ +import os +import logging +import xml.etree.ElementTree as ET + +from avocado.utils import process + +from virttest import virsh +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_vmxml + +LOG = logging.getLogger('avocado.' + __name__) + + +def run(test, params, env): + """ + Test command: virsh managedsave-dumpxml + Extract the domain XML that was in effect at the time the saved state file was created + with the managedsave command. Using --security-info will also include security sensitive information. + """ + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + managed_save_file = "/var/lib/libvirt/qemu/save/%s.save" % vm_name + graphic_attrs = eval(params.get('graphic_attrs', '{}')) + + def setup(): + """" + Prepare the pre-conditions: + 1) Prepare the vm with security info; + 2) Managedsave the vm; + """ + vmxml_ = vm_xml.VMXML.new_from_dumpxml(vm_name) + libvirt_vmxml.modify_vm_device(vmxml_, 'graphics', graphic_attrs) + vmxml_.sync() + if not vm.is_alive(): + vm.start() + LOG.info("vm %s state is %s", vm_name, virsh.domstate(vm_name).stdout) + virsh.dumpxml(vm_name, "--xpath //graphics") + virsh.managedsave(vm_name, ignore_status=False, debug=True) + + def check_outputxml(xml_text, graphic_setting): + """ + Check the XML snippet: + 1) If no --xpath option, the root element should be ; + 2) If --xpath is given, validate the root structure accordingly; + 3) If --security-info is set, ensure password info is included/excluded correctly. + """ + try: + # If xml_text is actual content, parse from string + root = ET.fromstring(xml_text) + + # Step 1: Validate root + if option == "--xpath //os": + if root.tag != "os": + test.fail("Expected root tag but got <%s>" % root.tag) + + elif option == "--xpath //os --wrap": + if root.tag != "nodes": + test.fail("Expected root tag for wrapped content.") + children = list(root) + if not children or children[0].tag != "os": + test.fail("Expected first child under to be .") + + else: # Default: should be + if root.tag != "domain": + test.fail("Expected root tag but got <%s>" % root.tag) + + # Step 2: Validate security info + if option == "--security-info": + expected = f"passwd='{graphic_setting.get('passwd', '')}'" + LOG.info("Checking for presence of: %s", expected) + if expected not in xml_text: + test.fail("Missing security info (passwd) in the XML.") + else: + if "passwd" in xml_text: + test.fail("Unexpected security info (passwd) found in the XML.") + + except ET.ParseError as e: + test.fail(f"XML parsing failed: {e}") + + option = params.get("option", "") + err_msg = params.get("err_msg", None) + opt_r = "yes" == params.get("readonly", "no") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bk_xml = vmxml.copy() + + try: + LOG.info("TEST_STEP1: Managedsave the VM:") + setup() + LOG.info("TEST_STEP2: Dump the VM's xml by managedave-dumpxml with %s:", option) + res = virsh.managedsave_dumpxml(vm_name, option, readonly=opt_r) + libvirt.check_result(res, expected_fails=err_msg) + if not err_msg: + LOG.info("TEST_STEP3: Check the format of the xml dumped:") + check_outputxml(res.stdout.strip(), graphic_attrs) + virsh.destroy(vm_name) + finally: + virsh.managedsave_remove(vm_name, debug=True) + if os.path.exists(managed_save_file): + process.run("rm -f %s" % managed_save_file, shell=True, ignore_status=True) + bk_xml.sync() From 9a77dd6b5f0d173d08b09c354ca6669922cc441a Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Fri, 30 May 2025 11:26:38 +0800 Subject: [PATCH 1039/1055] virsh_guestinfo: add case for cpu load This is to support the scenario like below $ virsh guestinfo rhel1 --load load.1m : 0.917969 load.5m : 1.265625 load.15m : 0.906738 Signed-off-by: Dan Zheng --- .../cfg/virsh_cmd/domain/virsh_guestinfo.cfg | 8 +++++ .../src/virsh_cmd/domain/virsh_guestinfo.py | 35 +++++++++++++++++-- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/libvirt/tests/cfg/virsh_cmd/domain/virsh_guestinfo.cfg b/libvirt/tests/cfg/virsh_cmd/domain/virsh_guestinfo.cfg index c9517ca176d..89d35ec66bf 100644 --- a/libvirt/tests/cfg/virsh_cmd/domain/virsh_guestinfo.cfg +++ b/libvirt/tests/cfg/virsh_cmd/domain/virsh_guestinfo.cfg @@ -1,8 +1,10 @@ - virsh.guestinfo: type = virsh_guestinfo start_vm = yes + func_supported_since_libvirt_ver = (6, 0, 0) variants: - positive: + start_vm = no start_ga = "yes" prepare_channel = "yes" variants: @@ -26,6 +28,12 @@ serial_num = "12345678" - interface_info: option = "--interface" + - load_info: + func_supported_since_libvirt_ver = (10, 10, 0) + option = "--load" + stress_in_vm = "yes" + remove_exist_qa = "yes" + load_info_field = ["load.1m", "load.5m", "load.15m"] - negative: status_error = "yes" variants: diff --git a/libvirt/tests/src/virsh_cmd/domain/virsh_guestinfo.py b/libvirt/tests/src/virsh_cmd/domain/virsh_guestinfo.py index bea2acf3983..601d080a90f 100644 --- a/libvirt/tests/src/virsh_cmd/domain/virsh_guestinfo.py +++ b/libvirt/tests/src/virsh_cmd/domain/virsh_guestinfo.py @@ -8,6 +8,7 @@ from virttest import data_dir from virttest import libvirt_version from virttest import utils_misc +from virttest.utils_test import VMStress from virttest.utils_test import libvirt @@ -332,6 +333,26 @@ def check_guest_interface_info(): logging.debug("if_info is %s", if_info) return if_info + def check_load_info_by_agent(load_info): + """ + Check the cpu load information reported by guest agent + + :param load_info: dict, load information from guestinfo command with --load + like {"load.1m":"0.917969","load.5m":"1.265625","load.15m":"0.906738"} + """ + load_info_field = eval(params.get("load_info_field")) + for item, value in load_info.items(): + if item not in load_info_field: + test.fail("Expect load info fields:%s, but found %s" % (load_info_field, item)) + try: + if float(value) <= 0: + test.fail("Incorrect load info value %s for field %s" % (value, item)) + except ValueError as err: + test.fail("Invalid load info value %s for field %s" % (value, item)) + test.log.debug("Verify load info from guest agent - PASS") + + libvirt_version.is_libvirt_feature_supported(params) + vm_name = params.get("main_vm") option = params.get("option", " ") added_user_name = params.get("added_user_name") @@ -344,9 +365,9 @@ def check_guest_interface_info(): serial_num = params.get("serial_num") disk_target_bus = params.get("disk_target_bus") readonly_mode = ("yes" == params.get("readonly_mode")) + stress_in_vm = ("yes" == params.get("stress_in_vm")) + remove_exist = ("yes" == params.get("remove_exist_qa")) - if not libvirt_version.version_compare(6, 0, 0): - test.cancel("Guestinfo command is not supported before version libvirt-6.0.0 ") import dateutil.parser added_user_session = None @@ -359,7 +380,12 @@ def check_guest_interface_info(): virsh_dargs["readonly"] = True if start_ga and prepare_channel: - vm.prepare_guest_agent(start=True, channel=True) + vm.prepare_guest_agent(start=True, channel=True, remove_existing=remove_exist) + + if stress_in_vm: + params.update({"stress_dependency_packages_list": "['gcc', 'make']"}) + vm_stress = VMStress(vm, "stress", params) + vm_stress.load_stress_tool() if "user" in option: add_user(added_user_name, added_user_passwd) @@ -393,6 +419,9 @@ def check_guest_interface_info(): test.fail("The disk info reported by agent cmd is not correct. " "result: %s" % info_from_agent_cmd) return + elif "load" in option: + check_load_info_by_agent(info_from_agent_cmd) + return else: if "filesystem" in option: info_from_guest = check_guest_filesystem_info(info_from_agent_cmd) From 75a690377c792a4b8f0e8daf0eb61349f79158b0 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Tue, 22 Apr 2025 08:42:28 +0800 Subject: [PATCH 1040/1055] migration_numa: add case The case is to test guest migration when numatune is configured w/o hugepage setting. Signed-off-by: Dan Zheng --- .../migration_numa/migration_numatune.cfg | 62 +++++++ .../migration_numa/migration_numatune.py | 170 ++++++++++++++++++ provider/numa/numa_base.py | 36 ++-- 3 files changed, 255 insertions(+), 13 deletions(-) create mode 100644 libvirt/tests/cfg/migration/migration_numa/migration_numatune.cfg create mode 100644 libvirt/tests/src/migration/migration_numa/migration_numatune.py diff --git a/libvirt/tests/cfg/migration/migration_numa/migration_numatune.cfg b/libvirt/tests/cfg/migration/migration_numa/migration_numatune.cfg new file mode 100644 index 00000000000..2b7854aa897 --- /dev/null +++ b/libvirt/tests/cfg/migration/migration_numa/migration_numatune.cfg @@ -0,0 +1,62 @@ +- migration.numa.numatune: + type = migration_numatune + take_regular_screendumps = no + migration_setup = 'yes' + storage_type = 'nfs' + setup_local_nfs = 'yes' + disk_type = "file" + disk_source_protocol = "netfs" + mnt_path_name = ${nfs_mount_dir} + # Console output can only be monitored via virsh console output + only_pty = True + # Extra options to pass after + virsh_migrate_extra = '' + # SSH connection time out + ssh_timeout = 60 + # Local URI + virsh_migrate_connect_uri = 'qemu:///system' + virsh_migrate_dest_state = "running" + virsh_migrate_src_state = "shut off" + image_convert = 'no' + server_ip = "${migrate_dest_host}" + server_user = "root" + server_pwd = "${migrate_dest_pwd}" + status_error = "no" + migrate_desturi_port = "22" + migrate_desturi_type = "ssh" + virsh_migrate_desturi = "qemu+ssh://${migrate_dest_host}/system" + migration_connections = 3 + virsh_migrate_options = "--p2p --live --persistent --parallel --parallel-connections ${migration_connections} --migrateuri tcp://${migrate_dest_host}" + single_host_node = "no" + mem_value = "'memory': 4194304, 'memory_unit': 'KiB'" + vm_node_mem = 1048576 + hugepage_mem = 4194304 + numa_node0 = {'id': '0', 'cpus': '0', 'memory': '${vm_node_mem}', 'unit': 'KiB'} + numa_node1 = {'id': '1', 'cpus': '1', 'memory': '${vm_node_mem}', 'unit': 'KiB'} + numa_node2 = {'id': '2', 'cpus': '2', 'memory': '${vm_node_mem}', 'unit': 'KiB'} + numa_node3 = {'id': '3', 'cpus': '3', 'memory': '${vm_node_mem}', 'unit': 'KiB'} + numa_cell = "'numa_cell': [${numa_node0}, ${numa_node1}, ${numa_node2}, ${numa_node3}]" + cpu_mode = 'host-model' + no s390-virtio + aarch64: + cpu_mode = 'host-passthrough' + variants mem_pagesize: + - default: + - hugepage: + memory_backing = {'hugepages': {}} + variants memory_mode: + - mem_mode_strict: + mem_mode = 'strict' + numa_memnode = [{'cellid': '0', 'mode': 'preferred', 'nodeset': '%s'}, {'cellid': '1', 'mode': 'interleave', 'nodeset': '%s'}] + - mem_mode_interleave: + mem_mode = 'interleave' + numa_memnode = [{'cellid': '0', 'mode': 'preferred', 'nodeset': '%s'}, {'cellid': '1', 'mode': 'strict', 'nodeset': '%s'}] + - mem_mode_preferred: + mem_mode = 'preferred' + numa_memnode = [{'cellid': '0', 'mode': 'strict', 'nodeset': '%s'}, {'cellid': '1', 'mode': 'interleave', 'nodeset': '%s'}] + - mem_mode_restrictive: + func_supported_since_libvirt_ver = (9, 4, 0) + mem_mode = 'restrictive' + numa_memnode = [{'cellid': '0', 'mode': 'restrictive', 'nodeset': '%s'}, {'cellid': '1', 'mode': 'restrictive', 'nodeset': '%s'}] + numa_memory = {'mode': '${mem_mode}', 'nodeset': '%s'} + vm_attrs = {${mem_value}, 'vcpu': 4, 'cpu': {'mode': '${cpu_mode}', ${numa_cell}}} diff --git a/libvirt/tests/src/migration/migration_numa/migration_numatune.py b/libvirt/tests/src/migration/migration_numa/migration_numatune.py new file mode 100644 index 00000000000..ed05ec02d88 --- /dev/null +++ b/libvirt/tests/src/migration/migration_numa/migration_numatune.py @@ -0,0 +1,170 @@ +from aexpect import remote + +from virttest import libvirt_version +from virttest import test_setup +from virttest import utils_libvirtd +from virttest import virsh + +from virttest.libvirt_xml import vm_xml + +from provider.migration import base_steps +from provider.numa import numa_base + + +def update_numa_memnode(numatest, node0, node1): + """ + Update numa_memnode values using available numa nodes + + :param numatest: NumaTest object + :param node0: str, available numa node + :param node1: str, available numa node + """ + mem_mode = numatest.params.get("mem_mode") + numa_memnode = numatest.params.get("numa_memnode") + two_nodes = "%d,%d" % (node0, node1) + two_nodes = numa_base.convert_to_string_with_dash(two_nodes) + if mem_mode == "strict": + numa_memnode = numa_memnode % (node0, two_nodes) + elif mem_mode == "interleave": + numa_memnode = numa_memnode % (two_nodes, node1) + elif mem_mode == "preferred": + numa_memnode = numa_memnode % (two_nodes, node0) + elif mem_mode == "restrictive": + numa_memnode = numa_memnode % (node0, node1) + + numatest.params["numa_memnode"] = eval(numa_memnode) + + +def setup_test(numatest_src, numatest_dst, migration_obj): + """ + Setup steps + + :param numatest_src: NumaTest object for source host + :param numatest_dst: NumaTest object for target host + :param migration_obj: MigrationBase object + """ + numatest_src.test.log.info("Setup steps.") + numatest_src.setup(expect_node_free_mem_min=2097152) + src_numanodes = numatest_src.get_available_numa_nodes(expect_node_free_mem_min=2097152) + dst_numanodes = numatest_dst.get_available_numa_nodes(expect_node_free_mem_min=2097152) + same_node_ids = set(src_numanodes).intersection(set(dst_numanodes)) + if len(same_node_ids) < 2: + numatest_src.test.cancel("The two hosts do not have at least 2 numa nodes with same ID") + same_node_ids = list(same_node_ids) + node0 = same_node_ids[0] + node1 = same_node_ids[1] + update_numa_memnode(numatest_src, node0, node1) + vmxml = numatest_src.prepare_vm_xml(required_nodes=same_node_ids) + virsh.define(vmxml.xml, **numatest_src.virsh_dargs) + + if numatest_src.params.get('memory_backing'): + for numa_obj in [numatest_src, numatest_dst]: + session = numatest_dst.session if numa_obj == numatest_dst else None + numa_base.adjust_parameters(numa_obj.params, + hugepage_mem=int(numa_obj.params.get("hugepage_mem")), + target_nodes=f"{node0} {node1}") + hpc = test_setup.HugePageConfig(numa_obj.params, session=session) + hpc.setup() + numa_obj.params['hpc_list'] = [hpc] + utils_libvirtd.Libvirtd(session=session).restart() + numatest_src.test.log.info("Restart libvirt daemon to make hugepage " + "configration take effect.") + migration_obj.setup_connection() + + +def verify_test(numatest, migration_obj): + """ + Verify steps for cases + + :param numatest: NumaTest object for source host + :param migration_obj: MigrationBase object + + """ + numatest.test.log.info("Verify steps.") + desturi = migration_obj.params.get("virsh_migrate_desturi") + backup_uri, migration_obj.vm.connect_uri = migration_obj.vm.connect_uri, desturi + virsh_remote = virsh.VirshPersistent(uri=migration_obj.vm.connect_uri) + vmxml_remote = vm_xml.VMXML.new_from_dumpxml( + migration_obj.vm.name, virsh_instance=virsh_remote + ) + memory_backing = eval(numatest.params.get("memory_backing", "{}")) + if memory_backing: + mb_remote = vmxml_remote.mb + mb_remote_attr = mb_remote.fetch_attrs() + numatest.test.log.info("Memorybacking on remote vm: %s", mb_remote) + if memory_backing != mb_remote_attr: + numatest.test.fail("Expect memory backing to be '%s', " + "but found '%s'" % (memory_backing, mb_remote_attr)) + else: + numatest.test.log.debug("Verify memory backing on remote vm - PASS") + + actual_numa_memnodes = vmxml_remote.numa_memnode + actual_numa_memory = vmxml_remote.numa_memory + conf_numa_memory = numatest.params.get("numa_memory") + conf_numa_memnode = numatest.params.get("numa_memnode") + if actual_numa_memnodes != conf_numa_memnode: + numatest.test.fail("Expect numa memnode to be '%s' on remote vm, " + "but found '%s'" % (conf_numa_memnode, actual_numa_memnodes)) + else: + numatest.test.log.debug("Verify numa memnode on remote vm - PASS") + if actual_numa_memory != conf_numa_memory: + numatest.test.fail("Expect numa memory to be '%s' on remote vm, " + "but found '%s'" % (conf_numa_memory, actual_numa_memory)) + else: + numatest.test.log.debug("Verify numa memory on remote vm - PASS") + migration_obj.vm.connect_uri = backup_uri + migration_obj.verify_default() + + +def teardown_default(numatest_src, numatest_dst, migration_obj): + """ + Default teardown function for the test + + :param numatest_src: NumaTest object for source host + :param numatest_dst: NumaTest object for target host + :param migration_obj: MigrationBase object + """ + migration_obj.cleanup_connection() + for numatest_obj in [numatest_src, numatest_dst]: + numatest_obj.teardown() + numatest_obj.test.log.debug("Step: teardown is done") + + +def run(test, params, env): + """ + Verify that guest with externally launched virtiofs device can be migrated. + + Check numa nodes on both hosts are available and qualified which must + have at least same two IDs of numa nodes with memory. + Check numa memory is enough on both hosts + Setup hugepage if needed on both hosts + Do migration + Check hugepage setting in remote host after migration + + :param test: test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environment. + """ + libvirt_version.is_libvirt_feature_supported(params) + vm_name = params.get("migrate_main_vm") + server_ip = params.get("server_ip") + server_pwd = params.get("server_pwd") + vm = env.get_vm(vm_name) + migration_obj = base_steps.MigrationBase(test, vm, params) + remote_session = remote.remote_login( + client="ssh", + host=server_ip, + port=22, + username="root", + password=server_pwd, + prompt=r"[$#%]", + ) + numatest_dst = numa_base.NumaTest(None, params.copy(), test, session=remote_session) + numatest_src = numa_base.NumaTest(vm, params, test) + try: + setup_test(numatest_src, numatest_dst, migration_obj) + migration_obj.run_migration() + verify_test(numatest_src, migration_obj) + + finally: + teardown_default(numatest_src, numatest_dst, migration_obj) diff --git a/provider/numa/numa_base.py b/provider/numa/numa_base.py index 0d009697ed3..ea20deee961 100644 --- a/provider/numa/numa_base.py +++ b/provider/numa/numa_base.py @@ -27,15 +27,16 @@ class NumaTest(object): :param params: dict with the test parameters :param test: test object """ - def __init__(self, vm, params, test): + def __init__(self, vm, params, test, session=None): self.params = params self.test = test self.vm = vm + self.session = session cmd = "numactl --hardware" - status, self.host_numactl_info = utils_misc.cmd_status_output(cmd, shell=True) + status, self.host_numactl_info = utils_misc.cmd_status_output(cmd, shell=True, session=self.session) if status != 0: test.error("Failed to get information from %s", cmd) - self.host_numa_info = utils_misc.NumaInfo() + self.host_numa_info = utils_misc.NumaInfo(session=self.session) self.online_nodes = self.host_numa_info.get_online_nodes().copy() self.online_nodes_withmem = self.host_numa_info.get_online_nodes_withmem().copy() self.virsh_dargs = {'ignore_status': False, 'debug': True} @@ -78,11 +79,12 @@ def check_numa_nodes_availability(self, expect_nodes_num=2, expect_node_free_mem def setup(self, expect_nodes_num=2, expect_node_free_mem_min=None): self.check_numa_nodes_availability(expect_nodes_num, expect_node_free_mem_min) - vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(self.vm.name) - self.params['backup_vmxml'] = vmxml.copy() + if self.vm: + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(self.vm.name) + self.params['backup_vmxml'] = vmxml.copy() def teardown(self): - if self.vm.is_alive(): + if self.vm and self.vm.is_alive(): self.vm.destroy() backup_vmxml = self.params.get("backup_vmxml") if backup_vmxml: @@ -97,10 +99,11 @@ def teardown(self): self.test.log.debug("Teardown: clean up hugepage setting for %d", hpc.hugepage_size) hpc.cleanup() - def prepare_vm_xml(self): + def prepare_vm_xml(self, required_nodes=None): """ Prepare vm xml + :param required_nodes: list, the specified numa node ids, like [0, 1, 2] :return: VMXML object """ single_host_node = self.params.get('single_host_node') @@ -117,15 +120,16 @@ def prepare_vm_xml(self): # Setup numa tune attributes nodeset = None if single_host_node: - all_nodes = self.online_nodes_withmem + nodes_used = required_nodes if required_nodes else self.online_nodes_withmem if single_host_node == 'no': # When memory bind to multiple numa nodes, # the test only selects the first two numa nodes with memory on the host - nodeset = ','.join(['%d' % all_nodes[0], '%d' % all_nodes[1]]) + nodeset = ','.join(['%d' % nodes_used[0], '%d' % nodes_used[1]]) + nodeset = convert_to_string_with_dash(nodeset) elif single_host_node == 'yes': # When memory bind to single numa node, the test only selects # the first host numa node. - nodeset = '%d' % all_nodes[0] + nodeset = '%d' % nodes_used[0] self.params['nodeset'] = nodeset numa_tune_dict = {} @@ -138,10 +142,13 @@ def prepare_vm_xml(self): if nodeset: numa_memory.update({'nodeset': nodeset}) numa_tune_dict.update({'numa_memory': numa_memory}) + self.params["numa_memory"] = numa_memory if numa_memnode: if numa_memnode.count('%s'): - numa_memnode = numa_memnode % nodeset - numa_tune_dict.update({'numa_memnode': eval(numa_memnode)}) + numa_memnode = eval(numa_memnode % nodeset) + self.params["numa_memnode"] = numa_memnode + numa_tune_dict.update({'numa_memnode': numa_memnode}) + self.test.log.debug(numa_tune_dict) if numa_tune_dict: vmxml.setup_attrs(**numa_tune_dict) @@ -251,7 +258,7 @@ def check_hugepage_availability(pages_list): supported_hugepages)) -def adjust_parameters(params, hugepage_size=None, node_index='0', hugepage_mem=1048576): +def adjust_parameters(params, hugepage_size=None, node_index="0", hugepage_mem=1048576, target_nodes=""): """ This function will adjust parameters according to current architecture and given hugepage size and parameters. @@ -274,6 +281,7 @@ def adjust_parameters(params, hugepage_size=None, node_index='0', hugepage_mem=1 :param hugepage_size: int, huge page size in KiB :param node_index: str, the numa node index :param hugepage_mem: int, the hugepage memory in KiB to be allocated + :param target_nodes: str, numa nodes to set, for example "0 1" """ default_hugepage_size = memory.get_huge_page_size() page_size = default_hugepage_size if hugepage_size is None else hugepage_size @@ -293,4 +301,6 @@ def adjust_parameters(params, hugepage_size=None, node_index='0', hugepage_mem=1 hugepage_path = "/dev/hugepages" else: hugepage_path = "/dev/hugepages%d" % page_size + if target_nodes: + params['target_nodes'] = target_nodes params['vm_hugepage_mountpoint'] = hugepage_path From fff4249009ed2e593a1e8b0f2578c1a6210e4c57 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Mon, 30 Jun 2025 14:18:57 +0800 Subject: [PATCH 1041/1055] Update parameter name in batch Update according to https://github.com/avocado-framework/avocado-vt/pull/4153 Signed-off-by: Dan Zheng --- .../tests/cfg/memory/memory_backing/hugepage_mount_path.cfg | 2 +- .../memory_devices/virtio_mem_with_memory_backing_type.cfg | 2 +- .../tests/src/memory/memory_backing/hugepage_mount_path.py | 4 ++-- .../memory_devices/virtio_mem_with_memory_backing_type.py | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libvirt/tests/cfg/memory/memory_backing/hugepage_mount_path.cfg b/libvirt/tests/cfg/memory/memory_backing/hugepage_mount_path.cfg index 9c3ac8eb91e..2ac746b0a63 100644 --- a/libvirt/tests/cfg/memory/memory_backing/hugepage_mount_path.cfg +++ b/libvirt/tests/cfg/memory/memory_backing/hugepage_mount_path.cfg @@ -13,7 +13,7 @@ current_mem = 2097152 max_mem = 15242880 start_vm = "no" - consume_value = 204800 + remain_mem = 204800 variants kernel_pagesize: - 4k: default_page_size = 4 diff --git a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_backing_type.cfg b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_backing_type.cfg index edbcc7a8395..52f371ec3b7 100644 --- a/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_backing_type.cfg +++ b/libvirt/tests/cfg/memory/memory_devices/virtio_mem_with_memory_backing_type.cfg @@ -4,7 +4,7 @@ mem_model = "virtio-mem" virtio_mem_num = 2 allocate_huge_pages = "3145728KiB" - consume_value = 102400 + remain_mem = 102400 mem_value = 2097152 current_mem = 2097152 max_mem = 4194304 diff --git a/libvirt/tests/src/memory/memory_backing/hugepage_mount_path.py b/libvirt/tests/src/memory/memory_backing/hugepage_mount_path.py index e79015ba2de..b4a5024e0d0 100644 --- a/libvirt/tests/src/memory/memory_backing/hugepage_mount_path.py +++ b/libvirt/tests/src/memory/memory_backing/hugepage_mount_path.py @@ -120,7 +120,7 @@ def _compare_state(): test.log.info("TEST_STEP11: Check mem") session = vm.wait_for_login() - libvirt_memory.consume_vm_freememory(session, consume_value) + libvirt_memory.consume_vm_freememory(session, remain_mem) session.close() test.log.info("TEST_STEP12: Destroy the guest") @@ -163,7 +163,7 @@ def teardown_test(): err_2 = params.get("guest_log_error2") hugetlbfs_mount = params.get("hugetlbfs_mount") default_path = params.get("default_path") - consume_value = int(params.get("consume_value")) + remain_mem = int(params.get("remain_mem")) default_page_size = int(params.get('default_page_size')) mount_pagesize = params.get("mount_pagesize", '{}') diff --git a/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_backing_type.py b/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_backing_type.py index 9d35a6ced70..723af71599e 100644 --- a/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_backing_type.py +++ b/libvirt/tests/src/memory/memory_devices/virtio_mem_with_memory_backing_type.py @@ -215,7 +215,7 @@ def run_test(): test.log.info("TEST_STEP10: Consume guest memory successfully") session = vm.wait_for_login() status, output = libvirt_memory.consume_vm_freememory( - session, consume_value=consume_value) + session, remain_mem=remain_mem) if status: test.fail("Fail to consume guest memory. Error:%s" % output) session.close() @@ -236,7 +236,7 @@ def teardown_test(): allocate_huge_pages = re.findall(r'\d+', params.get("allocate_huge_pages"))[0] attach_type = params.get("attach_type") - consume_value = int(params.get("consume_value")) + remain_mem = int(params.get("remain_mem")) try: memory_base.check_supported_version(params, test, vm) From 04ff66fa5e5e8b08379e7e3c731b9c3c7743b51e Mon Sep 17 00:00:00 2001 From: nanli1 <94951421+nanli1@users.noreply.github.com> Date: Mon, 30 Jun 2025 16:32:08 +0800 Subject: [PATCH 1042/1055] add case for making disk produce io error msg (#6274) xxxx-303986 Make disk produce I/O error due to "message" Signed-off-by: nanli --- .../virtual_disks/virtual_disks_io_error.cfg | 18 +++ .../virtual_disks/virtual_disks_io_error.py | 129 ++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 libvirt/tests/cfg/virtual_disks/virtual_disks_io_error.cfg create mode 100644 libvirt/tests/src/virtual_disks/virtual_disks_io_error.py diff --git a/libvirt/tests/cfg/virtual_disks/virtual_disks_io_error.cfg b/libvirt/tests/cfg/virtual_disks/virtual_disks_io_error.cfg new file mode 100644 index 00000000000..c4972bcbb6b --- /dev/null +++ b/libvirt/tests/cfg/virtual_disks/virtual_disks_io_error.cfg @@ -0,0 +1,18 @@ +- virtual_disks.io_error: + type = virtual_disks_io_error + start_vm = "no" + virt_disk_device = "disk" + take_regular_screendumps=no + func_supported_since_libvirt_ver = (10, 10, 0) + variants: + - hypervisor_message: + device_manager_path = "/tmp/img" + prepare_file = "dd if=/dev/zero of=${device_manager_path} count=512 bs=1048576" + device_manager = "errdev1" + disk_dict = {"type_name": "block",'source': {'attrs': {'dev': '/dev/mapper/${device_manager}'}}, "target": {"dev": "vdb", "bus": "virtio"}, "driver": {"name": "qemu", "type": "raw"}} + dd_in_guest = "dd if=/dev/vdb of=/tmp/img bs=1024 count=524288" + dd_msg = "Input/output error" + event_msg = "/dev/mapper/${device_manager}.*report due to message" + guest_log_msg = "IO error device=.*Input/output error" + dominfo_msg = "I/O error:.*path='/dev/mapper/${device_manager}'.*message='Input/output error'" + diff --git a/libvirt/tests/src/virtual_disks/virtual_disks_io_error.py b/libvirt/tests/src/virtual_disks/virtual_disks_io_error.py new file mode 100644 index 00000000000..75860eed667 --- /dev/null +++ b/libvirt/tests/src/virtual_disks/virtual_disks_io_error.py @@ -0,0 +1,129 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nannan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +import os +import re +import subprocess + +from avocado.utils import process + +from virttest import virsh +from virttest import libvirt_version + +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.devices import disk +from virttest.utils_test import libvirt + +virsh_dargs = {"ignore_status": False, "shell": True} + + +def run(test, params, env): + """ + Make disk produce I/O error due to "message", then check the error + in "virsh event", vm log and "virsh dominfo" + + Note: "message" is a kind of I/O error reason. It means that the hypervisor + reported a string description of the I/O error. The errors are usually logged + into the domain log file or the last instance of the error string can be + queried via virDomainGetMessages(). + """ + + def setup_test(): + """ + Prepare one error device mapper。 + """ + test.log.info("Setup env.") + process.run(prepare_file, **virsh_dargs) + # Find a free loop device + global free_loop_dev + free_loop_dev = process.run("losetup --find", **virsh_dargs).stdout_text.strip() + # Setup a loop device and create error device mapper + process.run('losetup %s %s' % (free_loop_dev, device_manager_path), **virsh_dargs) + dm_table = """0 261144 linear %s 0 + 261144 5 error + 261149 787427 linear %s 261139""" % (free_loop_dev, free_loop_dev) + try: + subprocess.run(["sudo", "dmsetup", "create", device_manager], + input=dm_table.encode('utf-8'), stderr=subprocess.PIPE, check=True) + except subprocess.CalledProcessError as e: + test.log.debug("create device manager failed :%s", e.stderr.decode('utf-8')) + + def run_test(): + """ + Attach disk and check error message. + """ + test.log.info("TEST_STEP1: Attach a new disk") + vm.start() + session = vm.wait_for_login() + new_disk = disk.Disk() + new_disk.setup_attrs(**disk_dict) + virsh.attach_device(vm_name, new_disk.xml, flagstr="--current", + wait_for_event=True, event_timeout=100, **virsh_dargs) + + test.log.info("TEST_STEP2: Write file in guest and check I/O error message.") + virsh_session = virsh.EventTracker.start_get_event(vm_name) + try: + output = session.cmd(dd_in_guest) + except Exception as e: + if dd_msg not in str(e): + test.fail("Write data in guest should produce error: %s in %s" % (dd_msg, output)) + else: + test.fail("Except error: in %s" % output) + + test.log.info("TEST_STEP3: Check event output.") + event_output = virsh.EventTracker.finish_get_event(virsh_session) + if not re.search(event_msg, event_output): + test.fail('Not find: %s from event output:%s' % (event_msg, event_output)) + + test.log.info("TEST_STEP4: Check about I/O error in vm log.") + qemu_log = os.path.join('/var/log/libvirt/qemu/', "%s.log" % vm_name) + if not libvirt.check_logfile(guest_log_msg, qemu_log, str_in_log=True): + test.fail('Find unexpected error:%s in log file:%s' % (guest_log_msg, qemu_log)) + + test.log.info("TEST_STEP5: Check about I/O error in virsh domain info.") + dominfo = virsh.dominfo(vm_name, debug=True) + libvirt.check_result(dominfo, expected_match=dominfo_msg) + + def teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + if session: + session.close() + bkxml.sync() + process.run('sudo losetup -d %s' % free_loop_dev, **virsh_dargs) + process.run('sudo dmsetup remove %s' % device_manager, **virsh_dargs) + if os.path.exists(device_manager_path): + os.remove(device_manager_path) + + libvirt_version.is_libvirt_feature_supported(params) + + vm_name = params.get("main_vm") + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + bkxml = vmxml.copy() + prepare_file = params.get("prepare_file") + device_manager = params.get("device_manager") + device_manager_path = params.get("device_manager_path") + disk_dict = eval(params.get("disk_dict", "{}")) + dd_in_guest = params.get("dd_in_guest") + dd_msg = params.get("dd_msg") + event_msg = params.get("event_msg") + guest_log_msg = params.get("guest_log_msg") + dominfo_msg = params.get("dominfo_msg") + session = None + + try: + setup_test() + run_test() + + finally: + teardown_test() From 4df06375ad1a12a151a37e89f3b6ea4753d731f8 Mon Sep 17 00:00:00 2001 From: vwu-vera Date: Mon, 30 Jun 2025 03:43:12 -0500 Subject: [PATCH 1043/1055] v2v:nbdkit:fix the failed case on matching time Signed-off-by: vwu-vera --- v2v/tests/src/nbdkit/nbdkit.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/v2v/tests/src/nbdkit/nbdkit.py b/v2v/tests/src/nbdkit/nbdkit.py index af16c6dee27..5a0f7dddcaf 100644 --- a/v2v/tests/src/nbdkit/nbdkit.py +++ b/v2v/tests/src/nbdkit/nbdkit.py @@ -502,8 +502,9 @@ def cow_on_read_path(): shell=True, ignore_status=True) time_2 = process.run("nbdkit file %s --filter=cow --filter=delay rdelay=200ms --run '%s' > %s/time2.log" % (image_path, cmd_inspect, tmp_path), shell=True, ignore_status=True) - if not (int(''.join(filter(str.isdigit, re.search(r'real.*m', time_1.stderr_text).group(0)))) < - int(''.join(filter(str.isdigit, re.search(r'real.*m', time_2.stderr_text).group(0))))): + match_1 = re.search(r'real\s+(\d+)m([\d.]+)s', time_1.stderr_text) + match_2 = re.search(r'real\s+(\d+)m([\d.]+)s', time_2.stderr_text) + if not (int(match_1.group(1))*60+float(match_1.group(2))) < (int(match_2.group(1))*60+float(match_2.group(2))): test.fail('fail to test cow-on-read=/path option') def cow_block_size(): From bda99f60f8813875f56e4543beaa4880b837fc45 Mon Sep 17 00:00:00 2001 From: Yingshun <49855663+Yingshun@users.noreply.github.com> Date: Tue, 1 Jul 2025 17:03:59 +0800 Subject: [PATCH 1044/1055] svirt: Update to check error message for relabel without label device (#6418) Device's with no