1. KVM Migration From Intel to AMD Fails With Missing Cmp_legacy Feature (+ Solution)

    Tue 06 January 2026

    Context

    I'm running a virtualisation lab environment, with four Intel-based CPUs (i5-6500) and one AMD Ryzen 3 PRO 2200GE.

    When migrating virtual machines from one of the Intel hosts to the AMD host, the migration would fail with the following error:

    error: operation failed: guest CPU doesn't match specification: extra features: cmp_legacy"
    

    The really strange thing is that some virtual machines did migrate successfully from an Intel system to the AMD system without any issues.

    So I dumped the XML of the virtual machines and compared them. It turns out that the virtual machines that migrated successfully were all single-core and all failing virtual machines were multi-core.

    As the cmp_legacy CPU feature seems to be related to (lack of) support for hyper-threading, the configured CPU topology of the virtual machines was suspected to be the culprit.

    I've configured a custom CPU topology on the virtual machines with 1 socket, 1 die and one or more CPU cores. This caused the migration failure.

    Solution

    If you configure multi-core virtual machines with multiple sockets instead of cores migration between Intel and AMD hosts will succeed.

    In the past, migrations between an Intel and AMD host always succeeded, assuming that the appropriate CPU features were disabled. Why this suddenly stopped working is not clear to me, as this configuration never changed. Maybe it's related to a Libvirt update, but I have no proof for this.

    Tagged as : KVM
    If you have any comments email me, see the About page for contact details.
  2. Sharing Group_var Variables Across Ansible Inventories

    Sat 20 December 2025

    The problem

    Some time ago I worked with a customer that used Ansible to deploy a multitude of applications across their individual TAP1 environments.

    Unfortunately the Ansible inventory was setup in such a way that group_vars variables for a specific application were manually duplicated across each TAP environment.

    Ansible Inventory Hierarchy Example of inventory folder hierarchy

    Changing or adding a group_vars variable meant updating the group_vars file for each TAP environment. Making changes to group_vars in this environment is a cognitive burden: there is a high risk that one of the environments is missed by mistake.

    The different TAP environments share the vast majority of all group_var variables, except for just a few variables that are environment-specific. There should be no reason to duplicate group_vars variables for each environment.

    The solution

    A shared folder symlinked into group_vars

    Within the application inventory folder, We first create a folder called 000_shared that will contain all group_vars YAML files with variables that are shared across all TAP environments.

    Next, we symlink this folder within each group_vars folder of each environment. Each environment also contains environment-specific configuration in one or more separate files.

    Ansible Inventory Hierarchy

    With this example, any change within webserver.yaml will be applied to all TAP environments of the 'Alpha' application.

    Sharing group_vars variables across applications

    We can apply this trick one level higher: we can create a shared folder called 000_shared_global containing settings that are shared across all application environments.

    Ansible Inventory Hierarchy

    In this example, we could change the DNS configuration for all environments by changing the settings in one, single file. But the global shared group_vars can be used to assure a (security) baseline between unrelated applications that do share similar technology (All Python or PHP applications).

    Evaluation

    Implementing this solution in an existing Ansible 'code base' can be a significant undertaking, but the long-term benefits seem worth it.

    • It reduces the amount of work required for changes
    • It reduces the risk of human error
    • It reduces the cognitive load

    The good news is that you can migrate to this new style of inventory at your own pace, there is no need for a big-bang deployment. Changes can be made to one environment at a time.

    Q & A

    Why the leading 000 zeros in shared folder names?

    Ansible parses group_vars YAML files according to their order within a directory. This means that the shared folders should be named with leading zeros, to assure that they are always parsed first.

    This allows you to override shared group_vars settings for a particular environment, because these environment-specific files will be parsed later and their variable settings will be applied.

    Just use one inventory for DTAP!

    You can create a single inventory for test, acceptance and production, and separate the environments with groups. A shared group contains shared settings and environment-specific settings are put in the group_vars of the specific group. Unfortunately there is a risk:

    Ansible documentation:

    If you need to manage multiple environments, consider defining only the hosts of a single environment in each inventory. This way, it is harder to, for example, accidentally change the state of nodes inside the “test” environment when you wanted to update some “staging” servers.

    Therefore, I would recommend against this approach.

    Changes impact production?

    Changing shared group_vars variables means that all environments are changed, including production. This requires proper code review and deployment processes that assures that said changes are only deployed to production when test and acceptance environments have been changed first.


    1. Development, Test, Acceptance and Production 

    2. When an inventory contains test, acceptance and prod environments it's easy to target all three environments by mistake. 

    Tagged as : Ansible
    If you have any comments email me, see the About page for contact details.

Page 1 / 111