diff --git a/libvirt/tests/cfg/memory/memory_backing/memory_access_mode.cfg b/libvirt/tests/cfg/memory/memory_backing/memory_access_mode.cfg new file mode 100644 index 00000000000..70a7d9e180e --- /dev/null +++ b/libvirt/tests/cfg/memory/memory_backing/memory_access_mode.cfg @@ -0,0 +1,60 @@ +- memory.backing.access_mode: + type = memory_access_mode + set_pagesize = 2048 + set_pagenum = 1024 + numa_mem = 2097152 + start_vm = no + qemu_monitor_option = '--hmp' + qemu_monitor_cmd = 'info memdev' + pattern_share = "share:\s*{}" + mem_backend = "memory backend: ram-node0" + variants source: + - file: + source_type = 'file' + source_attr = "'source_type':'${source_type}'" + source_path = {'element_attrs': ['./memoryBacking/source/[@type="${source_type}"]']} + - anonymous: + source_type = 'anonymous' + source_attr = "'source_type':'${source_type}'" + source_path = {'element_attrs': ['./memoryBacking/source/[@type="${source_type}"]']} + - memfd: + source_type = 'memfd' + source_attr = "'source_type':'${source_type}'" + source_path = {'element_attrs': ['./memoryBacking/source/[@type="${source_type}"]']} + - no_source: + variants mem_access: + - mem_access_private: + mem_access_mode = 'private' + mem_acccess_attr = "'access_mode':'${mem_access_mode}'" + mem_access_path = {'element_attrs': ['./memoryBacking/access/[@mode="${mem_access_mode}"]']} + - mem_access_shared: + mem_access_mode = 'shared' + mem_acccess_attr = "'access_mode':'${mem_access_mode}'" + mem_access_path = {'element_attrs': ['./memoryBacking/access/[@mode="${mem_access_mode}"]']} + - mem_access_default: + variants numa_access: + - numa_access_private: + 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: + 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: + 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" + variants mem_pagesize: + - without_hugepage: + - with_hugepage: + no anonymous + hugepages_attr = "'hugepages': {}" + hugepages_path = {'element_attrs': ['./memoryBacking/hugepages']} + variants: + - memory_allocation: + mem_unit = "KiB" + current_mem_unit = "KiB" + 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/src/memory/memory_backing/memory_access_mode.py b/libvirt/tests/src/memory/memory_backing/memory_access_mode.py new file mode 100644 index 00000000000..e6aac800a57 --- /dev/null +++ b/libvirt/tests/src/memory/memory_backing/memory_access_mode.py @@ -0,0 +1,214 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright Redhat +# +# SPDX-License-Identifier: GPL-2.0 + +# Author: Nan Li +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import re + +from virttest import virsh +from virttest import test_setup + +from virttest.libvirt_xml import vm_xml +from virttest.utils_test import libvirt +from virttest.utils_libvirt import libvirt_vmxml +from virttest.utils_libvirt import libvirt_memory + + +def run(test, params, env): + """ + 1. Verify memory access setting takes effect + 2. Verify the numa topology access setting takes effect + against memory backing setting + """ + + def get_vm_attrs(): + """ + Get vm attrs. + :return vm_attrs: expected vm attrs dict. + """ + mb_value = "" + for item in [source_attr, mem_acccess_attr, hugepages_attr]: + if item != "": + mb_value = mb_value + item + "," + vm_attrs = eval("{'mb':{%s}}" % mb_value[:-1]) + if numa_attrs: + vm_attrs.update(numa_attrs) + vm_attrs.update(mem_attrs) + test.log.debug("Get current vm attrs is :%s" % vm_attrs) + + return vm_attrs + + def get_expected_xpath(): + """ + Get expected xpath. + :return expect_xpath: Get xpath according to the cfg file. + """ + expect_xpath = [] + for xpath in [source_path, hugepages_path, mem_access_path, + numa_access_path]: + if xpath != "": + expect_xpath.append(eval(xpath)) + test.log.debug("Get expected xpath: %s", expect_xpath) + return expect_xpath + + def get_qemu_cmd_line(): + """ + Get expected qemu cmd line. + :return qemu_cmd: Get expected qemu cmd according to the scenarios. + """ + existed_line, not_existed_line = [], [] + + if mem_access == "mem_access_default" and \ + numa_access in ["numa_access_default", "no_numa"] and \ + mem_pagesize == "without_hugepage": + existed_line += ['"qom-type":"memory-backend-ram"'] + not_existed_line += ['"mem-path":"/var/lib/libvirt/qemu/ram/'] + + elif mem_pagesize == "with_hugepage": + existed_line += ['"qom-type":"memory-backend-file"', + '"mem-path":"/dev/hugepages/libvirt/qemu/'] + + elif (mem_access in ["mem_access_private", "mem_access_shared", + "mem_access_default"] and + numa_access in ["numa_access_private", "numa_access_shared"] + and mem_pagesize == "without_hugepage"): + + existed_line += ['"qom-type":"memory-backend-file"', + '"mem-path":"/var/lib/libvirt/qemu/ram/'] + elif (mem_access in ["mem_access_private", "mem_access_shared"] + and numa_access == "numa_access_default" and + mem_pagesize == "without_hugepage"): + + existed_line += ['"qom-type":"memory-backend-file"', + '"mem-path":"/var/lib/libvirt/qemu/ram/'] + + elif (mem_access in ["mem_access_private", "mem_access_shared"] and + numa_access == "no_numa" and mem_pagesize == "without_hugepage"): + + existed_line += ['"qom-type":"memory-backend-file"', + '"mem-path":"/var/lib/libvirt/qemu/ram/'] + + qemu_cmd = {True: existed_line, False: not_existed_line} + + return qemu_cmd + + def get_access_mode(): + """ + Get expected access mode according to the scenarios. + :return: share value. + """ + share = "false" + if numa_access == "numa_access_shared": + share = "true" + + elif mem_access == "mem_access_shared" and \ + numa_access in ["numa_access_default", "no_numa"]: + share = "true" + + elif source == "memfd" and mem_access == "mem_access_default" and \ + numa_access in ["numa_access_default", "no_numa"]: + share = "true" + + return share + + def setup_test(): + """ + Setup pagesize + """ + hp_cfg.set_kernel_hugepages(set_pagesize, set_pagenum) + + def run_test(): + """ + Define vm and check msg + Start vm and check config + Check the qemu cmd line + Check the access mode + Login the guest and consume the guest memory + """ + test.log.info("TEST_STEP1: Define vm and check result") + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) + vm_attrs = get_vm_attrs() + vmxml.setup_attrs(**vm_attrs) + test.log.debug("Define vm with %s." % vmxml) + virsh.undefine(vm.name, debug=True) + virsh.define(vmxml.xml, debug=True, ignore_status=False) + + test.log.info("TEST_STEP2: Start vm") + vm.start() + + test.log.info("TEST_STEP3: Check xml config") + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) + libvirt_vmxml.check_guest_xml_by_xpaths(vmxml, get_expected_xpath()) + + if source == "no_source": + test.log.info("TEST_STEP4: Check the qemu cmd line") + for existed, item_list in get_qemu_cmd_line().items(): + for item in item_list: + libvirt.check_qemu_cmd_line(item, expect_exist=existed) + test.log.debug("Check %s exist", item) + + test.log.info("TEST_STEP5: Check the memory allocated") + share_value = get_access_mode() + pattern = pattern_share.format(share_value) + + ret = virsh.qemu_monitor_command(vm_name, + qemu_monitor_cmd, + qemu_monitor_option).stdout_text.strip() + test.log.debug("Get qemu-monitor-command cmd result:\n%s", ret) + if not re.search(pattern, ret[ret.index(mem_backend):]): + test.fail("Expect '%s' exist, but not found." % pattern) + else: + test.log.debug("Check '%s' PASS.", pattern) + + test.log.info("TEST_STEP6: Consume the guest memory") + 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 teardown_test(): + """ + Clean data. + """ + test.log.info("TEST_TEARDOWN: Clean up env.") + bkxml.sync() + hp_cfg.cleanup() + + 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() + numa_access = params.get("numa_access") + mem_access = params.get("mem_access") + mem_pagesize = params.get("mem_pagesize") + pattern_share = params.get('pattern_share') + source = params.get("source") + mem_backend = params.get("mem_backend") + qemu_monitor_cmd = params.get('qemu_monitor_cmd') + qemu_monitor_option = params.get('qemu_monitor_option') + numa_attrs = eval(params.get("numa_attrs", '{}')) + mem_attrs = eval(params.get("mem_attrs", "{}")) + set_pagesize = params.get("set_pagesize") + set_pagenum = params.get("set_pagenum") + source_attr = params.get("source_attr", "") + hugepages_attr = params.get("hugepages_attr", "") + mem_acccess_attr = params.get("mem_acccess_attr", "") + + source_path = params.get("source_path", '') + hugepages_path = params.get("hugepages_path", '') + mem_access_path = params.get("mem_access_path", '') + numa_access_path = params.get("numa_access_path", '') + + hp_cfg = test_setup.HugePageConfig(params) + + try: + setup_test() + run_test() + + finally: + teardown_test()