From b5446b2fb7ecd248097b6ab2bc57939f165453ef Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Mon, 26 Feb 2024 15:59:29 +0100 Subject: [PATCH 1/2] vm_data.py-dist: Add documentation about VMS dictionary content Also adds the sample code that prepends the VMS dictionary entries with XVA_LOCATION (This code was present in the file from the pxe server but not committed elsewhere). Signed-off-by: Thierry Escande --- vm_data.py-dist | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/vm_data.py-dist b/vm_data.py-dist index 671ac577d..565881ae6 100644 --- a/vm_data.py-dist +++ b/vm_data.py-dist @@ -3,6 +3,15 @@ # Consult README.md for accepted values. # Example value: "http://somewhere/images/small_vm.xva" +# The "single" element contains 1 entry per VM filename: +# "small_vm": "alpine-minimal-3.12.0.xva", +# "small_vm_unix_tools": "centos7-64-created_8.0-zstd.xva", + +# The "multi" element contains a list of VMs per entry +# "all": ["alpine-minimal-3.12.0.xva", +# "alpine-uefi-minimal-efitools-3.12.0.xva", +# ...], + VMS = { "single": { # basic small VM @@ -27,3 +36,13 @@ VMS = { "uefi_windows": [], } } + +# Example of use for a common XVA_LOCATION +# +# XVA_LOCATION="http://somewhere/" +# +# for key, vm in dict(VMS["single"]).items(): +# VMS["single"][key] = XVA_LOCATION + vm +# +# for key, vms in dict(VMS["multi"]).items(): +# VMS["multi"][key] = [XVA_LOCATION + vm for vm in vms] From 1b7ee2029ab7e2fcf6bd11ed3c6e32c1e723f234 Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Fri, 16 Feb 2024 08:54:47 +0100 Subject: [PATCH 2/2] jobs.py: Add support to filter VMs based on host version VMs listed in vm_data.py can now be specified with the version of the XCP-ng host they support. i.e. PV VMs should be run only on 8.2 hosts. The VMS dictionary structure remains the same. If you want to specify the host version for a particular VM, use a dictionary entry instead of the VM filename plain string as: {"vm_filename.xva": "8.2.*"} The host version matched using re.mtach(), so valid patterns can be "8\.2\.", "8\.[23]\.", or "(9\.0|8\.2)". See vm_data.py-dist for more details. Signed-off-by: Thierry Escande --- jobs.py | 56 +++++++++++++++++++++++++++++++++++++++++++++---- vm_data.py-dist | 24 +++++++++++++++++++-- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/jobs.py b/jobs.py index 871bcce8e..ac36588d3 100755 --- a/jobs.py +++ b/jobs.py @@ -332,7 +332,24 @@ "tests/migration/test_host_evacuate.py::TestHostEvacuateWithNetwork", ] -def get_vm_or_vms_refs(handle): +# Returns the vm filename or None if a host_version is passed and matches the one specified +# with the vm filename in vm_data.py. ex: ("centos6-32-hvm-created_8.2-zstd.xva", "8\.2\..*") +def filter_vm(vm, host_version): + import re + + if type(vm) is tuple: + if len(vm) < 2: + return None + + if host_version is not None and not re.match(vm[1], host_version): + print(f"Host version pattern '{vm[1]}' for '{vm[0]}' doesn't match version '{host_version}'. Filtered out") + return None + + return vm[0] + + return vm + +def get_vm_or_vms_refs(handle, host_version=None): try: from vm_data import VMS except ImportError: @@ -347,7 +364,27 @@ def get_vm_or_vms_refs(handle): print("You need to update your local vm_data.py.") print("You may also bypass this error by providing your own --vm parameter(s).") sys.exit(1) - return VMS[category][key] + + if type(VMS[category][key]) is list: + # Multi VMs + vms = list() + for vm in VMS[category][key]: + xva = filter_vm(vm, host_version) + if xva is not None: + vms.append(xva) + if len(vms) == 0: + vms = None + else: + # Single VMs + vms = filter_vm(VMS[category][key], host_version) + + if vms is None: + print(f"ERROR: Could not find VMS['{category}']['{key}'] for host version {host_version}.") + print("You need to update your local vm_data.py.") + print("You may also bypass this error by providing your own --vm parameter(s).") + sys.exit(1) + + return vms def build_pytest_cmd(job_data, hosts=None, pytest_args=[]): markers = job_data.get("markers", None) @@ -355,6 +392,17 @@ def build_pytest_cmd(job_data, hosts=None, pytest_args=[]): job_params = dict(job_data["params"]) + host_version = None + if hosts is not None: + try: + host = hosts.split(',')[0] + cmd = ["ssh", host, "lsb_release", "-sr"] + res = subprocess.run(cmd, capture_output=True, text=True) + if res.returncode == 0: + host_version = res.stdout.strip() + except Exception as e: + print(e, file=sys.stderr) + def _join_pytest_args(arg, option): cli_args = [] try: @@ -397,11 +445,11 @@ def _join_pytest_args(arg, option): cmd.append(f"--hosts={hosts}") for key, value in job_params.items(): if key == "--vm[]": - vms = get_vm_or_vms_refs(value) + vms = get_vm_or_vms_refs(value, host_version) for vm_ref in vms: cmd.append(f"--vm={vm_ref}") elif key == "--vm": - cmd.append(f"--vm={get_vm_or_vms_refs(value)}") + cmd.append(f"--vm={get_vm_or_vms_refs(value, host_version)}") else: cmd.append(f"{key}={value}") cmd += pytest_args diff --git a/vm_data.py-dist b/vm_data.py-dist index 565881ae6..075c90fc3 100644 --- a/vm_data.py-dist +++ b/vm_data.py-dist @@ -7,11 +7,25 @@ # "small_vm": "alpine-minimal-3.12.0.xva", # "small_vm_unix_tools": "centos7-64-created_8.0-zstd.xva", +# If a vm is meant to be used only on a given host version, the version can be specified +# through a tuple entry with (vm_filename, host_version) as: +# "small_vm": ("alpine-minimal-3.12.0.xva", "8\.3\.") + +# The host version specified for a vm is matched using re.match(), so valid patterns +# can be "8\.2\.1", "8\.[23]\.", or "(9\.0|8\.2)". + +# If host version is not specified, the vm filename will be used whatever the host version + # The "multi" element contains a list of VMs per entry # "all": ["alpine-minimal-3.12.0.xva", # "alpine-uefi-minimal-efitools-3.12.0.xva", # ...], +# Same as "single", a vm can be bound to a given host version: +# "all": ["alpine-minimal-3.12.0.xva", +# ("alpine-uefi-minimal-efitools-3.12.0.xva", "8\.2\."), +# ...], + VMS = { "single": { # basic small VM @@ -41,8 +55,14 @@ VMS = { # # XVA_LOCATION="http://somewhere/" # +# def prepend_xva_location(vm): +# if type(vm) is tuple: +# return (XVA_LOCATION + vm[0], vm[1]) +# +# return XVA_LOCATION + vm +# # for key, vm in dict(VMS["single"]).items(): -# VMS["single"][key] = XVA_LOCATION + vm +# VMS["single"][key] = prepend_xva_location(vm) # # for key, vms in dict(VMS["multi"]).items(): -# VMS["multi"][key] = [XVA_LOCATION + vm for vm in vms] +# VMS["multi"][key] = [prepend_xva_location(vm) for vm in vms]