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 0000000000..7fdfe3c64a --- /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 0000000000..c5547708d1 --- /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()