How to Handle Guest OS Variants and Version Compatibility in Avocado-VT Test Scenarios
Avocado-VT manages guest OS variants through Cartesian configuration expansion and enforces libvirt version compatibility via runtime checks and decorators, ensuring tests adapt to both the target operating system and host hypervisor capabilities.
Avocado-VT (avocado-framework/avocado-vt) provides a comprehensive framework for virtualization testing that must accommodate diverse guest operating systems and evolving libvirt capabilities. Handling guest OS variants and version compatibility across test scenarios requires understanding how the framework parses configuration variants, validates OS definitions against host tools, and gates feature-specific code behind version checks.
Configuring Guest OS Variants with Cartesian Config
The foundation of guest OS variant handling lies in the Cartesian configuration parser, which expands test matrices based on defined variants.
Defining Variants in Test Configuration Files
In virttest/cartesian_config.py, the LVariant token and related operators parse variants: blocks within .cfg files. This allows test authors to declare multiple guest OS scenarios that the framework automatically expands into separate sub-tests.
# examples/tests/guest_os.cfg
variants:
- JeOS.27:
os_variant = JeOS.27
use_os_variant = yes
- fedora28:
os_variant = fedora28
use_os_variant = yes
When executed, Avocado-VT generates distinct sub-tests for each variant, attaching the specific os_variant value to the params dictionary of each test instance.
Setting Default Guest OS Values
For environments where no specific variant is declared, virttest/defaults.py supplies sensible defaults through DEFAULT_GUEST_OS. This module computes the default asset and variant based on the host architecture, ensuring that JeOS.27 or equivalent is available as a fallback when test configurations do not explicitly specify an operating system.
Runtime Variant Handling and Validation
Once configurations are parsed, the framework must retrieve variant names and validate them against the host's virtualization capabilities before VM creation.
Retrieving Variant Parameters with params_get()
Located in virttest/utils_v2v.py, the params_get() function provides a transparent helper for accessing variant values. This utility retrieves the OS variant whether it is passed directly as a parameter or nested within complex params structures, standardizing access across different test layouts.
from virttest import utils_v2v
def test_install(params):
# Grab the variant (works whether it is top-level or nested)
variant = utils_v2v.params_get(params, "os_variant", "JeOS.27")
# Use the variant to build the virt-install command
cmd = "virt-install --name testvm --memory 1024"
cmd += " --os-variant %s" % variant
Validating and Injecting OS Variants
The virttest/libvirt_vm.py module contains add_os_variant() and has_os_variant() functions that bridge configuration and execution. When use_os_variant=yes is set in the test parameters, add_os_variant() checks the requested variant against the list of supported OS variants exposed by virt-install --os-variant list. If validation succeeds via has_os_variant(), the framework injects the correct --os-variant <variant> argument into the virt-install command.
This ensures that tests fail early with clear errors when an unsupported guest OS is requested, rather than failing during VM boot.
Managing Libvirt Version Compatibility
Beyond guest OS selection, tests must adapt to the libvirt version installed on the host, as capabilities vary significantly between releases.
Runtime Version Comparison
The virttest/utils_libvirtd.py module centralizes version gating through libvirt_version.version_compare(). This utility wraps feature-specific code with version guards, allowing tests to exercise newer libvirt capabilities only when the underlying daemon supports them.
from virttest import libvirt_version, virsh
def test_numa_support(params, session):
# NUMA support was added in libvirt 5.6.0
if not libvirt_version.version_compare(5, 6, 0):
raise Exception("NUMA not supported by this libvirt version")
# Continue with NUMA-related test steps
virsh.numa_cpu_map(params, session)
Automated Mode Switching with Decorators
For tests requiring specific libvirtd operational modes, virttest/libvirtd_decorator.py provides version-aware decorators. The @libvirt_version_context_aware_libvirtd_split and @libvirt_version_context_aware_libvirtd_legacy decorators automatically switch the libvirtd mode according to the detected version, abstracting version-specific setup from test logic.
from virttest import libvirtd_decorator
@libvirtd_decorator.libvirt_version_context_aware_libvirtd_split
def test_split_libvirtd(params, session):
# The decorator ensures that libvirtd is started in "split" mode
# only when the host libvirt version >= 5.6.0.
# Test code can assume the split mode is active.
pass
Integration Workflow
Understanding how these components interact clarifies the complete lifecycle of guest OS variant and version handling:
-
Configuration Phase: Test authors define variants in
.cfgfiles using thevariants:syntax, specifyingos_variantanduse_os_variantparameters. -
Expansion Phase: The Cartesian Config parser in
virttest/cartesian_config.pyprocessesLVarianttokens, expanding each variant block into separate test parameter sets. -
Validation Phase: During VM creation,
virttest/libvirt_vm.add_os_variant()validates the requested variant against the host'svirt-installcapabilities and injects the appropriate command-line switch. -
Execution Phase: Throughout the test,
virttest/utils_libvirtd.libvirt_version.version_compare()guards feature-specific code paths, while decorators invirttest/libvirtd_decorator.pyadjust the libvirtd mode transparently.
This architecture isolates variant handling (configuration-level concerns) from version gating (runtime-level concerns), while virttest/utils_v2v.params_get() provides a unified interface for parameter retrieval across both domains.
Summary
-
Default guest OS variants are defined in
virttest/defaults.pybased on host architecture, providing sensible fallbacks when tests do not specify an operating system. -
Cartesian configuration in
virttest/cartesian_config.pyexpandsvariants:blocks into separate test instances, allowing a single test file to cover multiple guest OS scenarios. -
Parameter retrieval via
virttest/utils_v2v.params_get()abstracts access to variant names from complex nested parameter structures. -
OS variant validation occurs in
virttest/libvirt_vm.pythroughhas_os_variant()andadd_os_variant(), ensuring only supported guest types are passed tovirt-install. -
Version compatibility is enforced through
virttest/utils_libvirtd.libvirt_version.version_compare()for runtime checks andvirttest/libvirtd_decorator.pydecorators for automatic mode switching.
Frequently Asked Questions
How do I add a new guest OS variant to my test suite?
Define the variant in your .cfg file using the Cartesian variants: syntax, specifying the os_variant parameter and setting use_os_variant = yes. Ensure the variant name matches a valid entry from virt-install --os-variant list on your host, as validated by virttest/libvirt_vm.has_os_variant().
What happens if the specified OS variant is not supported by virt-install?
The add_os_variant() function in virttest/libvirt_vm.py checks variant validity against the host's supported list before VM creation. If the variant is unsupported, the validation fails and the test aborts before attempting installation, preventing opaque boot failures.
How can I skip tests for features unsupported by the host libvirt version?
Use virttest/utils_libvirtd.libvirt_version.version_compare() to check the host libvirt version at runtime. Wrap feature-specific test code in conditional blocks that raise exceptions or return early when the version requirement is not met, ensuring tests only execute when the capability is present.
What is the difference between libvirt_version.version_compare() and the version decorators?
libvirt_version.version_compare() in virttest/utils_libvirtd.py provides explicit runtime version checking for conditional logic within test functions. The decorators in virttest/libvirtd_decorator.py (such as @libvirt_version_context_aware_libvirtd_split) automatically configure the test environment—such as starting libvirtd in split mode—based on version detection without requiring manual conditional logic in every test.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →