all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Dominik Csapak <d.csapak@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH qemu-server v2 1/2] tests: improve multiarch build support
Date: Wed,  4 Feb 2026 11:01:01 +0100	[thread overview]
Message-ID: <20260204100425.1303295-1-d.csapak@proxmox.com> (raw)

instead of simply saving 'host_arch' in the global package namespace,
use the PVE::Tools::get_host_arch helper, which caches the result
anyway.

For easier testing:
* introduce our own helper for getting the host arch, which uses
  the PVE::Tools one. So we only have to mock the Tools one to get
  correct behavior in the tests. Use this everywhere here where we need
  it.
* move the cpu_models_by_arch initialization into a sub that can be
  called by the tests to re-initialize.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
changes from v1:
* add helpers to be more easily used and mocked by the tests instead
  of modifying the module level variable

 src/PVE/QemuServer.pm                |   5 +-
 src/PVE/QemuServer/CPUConfig.pm      | 258 ++++++++++++++-------------
 src/PVE/QemuServer/Helpers.pm        |   8 +-
 src/test/run_config2command_tests.pl |   8 +-
 4 files changed, 146 insertions(+), 133 deletions(-)

diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
index 5d2dbe03..8bf23945 100644
--- a/src/PVE/QemuServer.pm
+++ b/src/PVE/QemuServer.pm
@@ -46,8 +46,7 @@ use PVE::SafeSyslog;
 use PVE::Storage;
 use PVE::SysFSTools;
 use PVE::Systemd;
-use PVE::Tools
-    qw(run_command file_read_firstline file_get_contents dir_glob_foreach get_host_arch $IPV6RE);
+use PVE::Tools qw(run_command file_read_firstline file_get_contents dir_glob_foreach $IPV6RE);
 
 use PVE::QMPClient;
 use PVE::QemuConfig;
@@ -58,7 +57,7 @@ use PVE::QemuServer::Blockdev;
 use PVE::QemuServer::BlockJob;
 use PVE::QemuServer::Cfg2Cmd;
 use PVE::QemuServer::Helpers
-    qw(config_aware_timeout get_iscsi_initiator_name min_version kvm_user_version windows_version);
+    qw(config_aware_timeout get_iscsi_initiator_name get_host_arch min_version kvm_user_version windows_version);
 use PVE::QemuServer::Cloudinit;
 use PVE::QemuServer::CGroup;
 use PVE::QemuServer::CPUConfig qw(
diff --git a/src/PVE/QemuServer/CPUConfig.pm b/src/PVE/QemuServer/CPUConfig.pm
index 32ec4954..7d5559b0 100644
--- a/src/PVE/QemuServer/CPUConfig.pm
+++ b/src/PVE/QemuServer/CPUConfig.pm
@@ -11,7 +11,7 @@ use PVE::ProcFSTools;
 use PVE::RESTEnvironment qw(log_warn);
 use PVE::Tools qw(run_command);
 
-use PVE::QemuServer::Helpers qw(min_version);
+use PVE::QemuServer::Helpers qw(min_version get_host_arch);
 
 use base qw(PVE::SectionConfig Exporter);
 
@@ -25,8 +25,6 @@ our @EXPORT_OK = qw(
     get_cvm_type
 );
 
-my $host_arch = PVE::Tools::get_host_arch();
-
 my $arch_desc = {
     description => "Virtual processor architecture. Defaults to the host architecture.",
     type => 'string',
@@ -100,130 +98,138 @@ my $cputypes_32bit = {
     'qemu32' => 1,
 };
 
-my $cpu_models_by_arch = {
-    x86_64 => {
-        # Intel CPUs
-        486 => 'GenuineIntel',
-        pentium => 'GenuineIntel',
-        pentium2 => 'GenuineIntel',
-        pentium3 => 'GenuineIntel',
-        coreduo => 'GenuineIntel',
-        core2duo => 'GenuineIntel',
-        Conroe => 'GenuineIntel',
-        Penryn => 'GenuineIntel',
-        Nehalem => 'GenuineIntel',
-        'Nehalem-IBRS' => 'GenuineIntel',
-        Westmere => 'GenuineIntel',
-        'Westmere-IBRS' => 'GenuineIntel',
-        SandyBridge => 'GenuineIntel',
-        'SandyBridge-IBRS' => 'GenuineIntel',
-        IvyBridge => 'GenuineIntel',
-        'IvyBridge-IBRS' => 'GenuineIntel',
-        Haswell => 'GenuineIntel',
-        'Haswell-IBRS' => 'GenuineIntel',
-        'Haswell-noTSX' => 'GenuineIntel',
-        'Haswell-noTSX-IBRS' => 'GenuineIntel',
-        Broadwell => 'GenuineIntel',
-        'Broadwell-IBRS' => 'GenuineIntel',
-        'Broadwell-noTSX' => 'GenuineIntel',
-        'Broadwell-noTSX-IBRS' => 'GenuineIntel',
-        'Skylake-Client' => 'GenuineIntel',
-        'Skylake-Client-IBRS' => 'GenuineIntel',
-        'Skylake-Client-noTSX-IBRS' => 'GenuineIntel',
-        'Skylake-Client-v4' => 'GenuineIntel',
-        'Skylake-Server' => 'GenuineIntel',
-        'Skylake-Server-IBRS' => 'GenuineIntel',
-        'Skylake-Server-noTSX-IBRS' => 'GenuineIntel',
-        'Skylake-Server-v4' => 'GenuineIntel',
-        'Skylake-Server-v5' => 'GenuineIntel',
-        'Cascadelake-Server' => 'GenuineIntel',
-        'Cascadelake-Server-v2' => 'GenuineIntel',
-        'Cascadelake-Server-noTSX' => 'GenuineIntel',
-        'Cascadelake-Server-v4' => 'GenuineIntel',
-        'Cascadelake-Server-v5' => 'GenuineIntel',
-        'Cooperlake' => 'GenuineIntel',
-        'Cooperlake-v2' => 'GenuineIntel',
-        KnightsMill => 'GenuineIntel',
-        'Icelake-Client' => 'GenuineIntel', # depreacated, removed with QEMU 7.1
-        'Icelake-Client-noTSX' => 'GenuineIntel', # depreacated, removed with QEMU 7.1
-        'Icelake-Server' => 'GenuineIntel',
-        'Icelake-Server-noTSX' => 'GenuineIntel',
-        'Icelake-Server-v3' => 'GenuineIntel',
-        'Icelake-Server-v4' => 'GenuineIntel',
-        'Icelake-Server-v5' => 'GenuineIntel',
-        'Icelake-Server-v6' => 'GenuineIntel',
-        'Icelake-Server-v7' => 'GenuineIntel',
-        'SapphireRapids' => 'GenuineIntel',
-        'SapphireRapids-v2' => 'GenuineIntel',
-        'SapphireRapids-v3' => 'GenuineIntel',
-        'SapphireRapids-v4' => 'GenuineIntel',
-        'GraniteRapids' => 'GenuineIntel',
-        'GraniteRapids-v2' => 'GenuineIntel',
-        'GraniteRapids-v3' => 'GenuineIntel',
-        'SierraForest' => 'GenuineIntel',
-        'SierraForest-v2' => 'GenuineIntel',
-        'SierraForest-v3' => 'GenuineIntel',
-        'ClearwaterForest' => 'GenuineIntel',
-
-        # AMD CPUs
-        athlon => 'AuthenticAMD',
-        phenom => 'AuthenticAMD',
-        Opteron_G1 => 'AuthenticAMD',
-        Opteron_G2 => 'AuthenticAMD',
-        Opteron_G3 => 'AuthenticAMD',
-        Opteron_G4 => 'AuthenticAMD',
-        Opteron_G5 => 'AuthenticAMD',
-        EPYC => 'AuthenticAMD',
-        'EPYC-IBPB' => 'AuthenticAMD',
-        'EPYC-v3' => 'AuthenticAMD',
-        'EPYC-v4' => 'AuthenticAMD',
-        'EPYC-v5' => 'AuthenticAMD',
-        'EPYC-Rome' => 'AuthenticAMD',
-        'EPYC-Rome-v2' => 'AuthenticAMD',
-        'EPYC-Rome-v3' => 'AuthenticAMD',
-        'EPYC-Rome-v4' => 'AuthenticAMD',
-        'EPYC-Rome-v5' => 'AuthenticAMD',
-        'EPYC-Milan' => 'AuthenticAMD',
-        'EPYC-Milan-v2' => 'AuthenticAMD',
-        'EPYC-Milan-v3' => 'AuthenticAMD',
-        'EPYC-Genoa' => 'AuthenticAMD',
-        'EPYC-Genoa-v2' => 'AuthenticAMD',
-        'EPYC-Turin' => 'AuthenticAMD',
-
-        # generic types, use vendor from host node
-        kvm32 => 'default',
-        kvm64 => 'default',
-        qemu32 => 'default',
-        qemu64 => 'default',
-        max => 'default',
-    },
-    aarch64 => {
-        'a64fx' => 'ARM',
-        'cortex-a35' => 'ARM',
-        'cortex-a53' => 'ARM',
-        'cortex-a55' => 'ARM',
-        'cortex-a57' => 'ARM',
-        'cortex-a710' => 'ARM',
-        'cortex-a72' => 'ARM',
-        'cortex-a76' => 'ARM',
-        'neoverse-n1' => 'ARM',
-        'neoverse-n2' => 'ARM',
-        'neoverse-v1' => 'ARM',
-        # 32 bit and deprecated models were not added
-        max => 'default',
-    },
-};
+my $cpu_models_by_arch;
+my $all_cpu_models;
 
-# The host CPU model only exists if the arch matches
-$cpu_models_by_arch->{$host_arch}->{host} = 'default';
+# helper to make it easier for testing
+sub initialize_cpu_models {
+    $cpu_models_by_arch = {
+        x86_64 => {
+            # Intel CPUs
+            486 => 'GenuineIntel',
+            pentium => 'GenuineIntel',
+            pentium2 => 'GenuineIntel',
+            pentium3 => 'GenuineIntel',
+            coreduo => 'GenuineIntel',
+            core2duo => 'GenuineIntel',
+            Conroe => 'GenuineIntel',
+            Penryn => 'GenuineIntel',
+            Nehalem => 'GenuineIntel',
+            'Nehalem-IBRS' => 'GenuineIntel',
+            Westmere => 'GenuineIntel',
+            'Westmere-IBRS' => 'GenuineIntel',
+            SandyBridge => 'GenuineIntel',
+            'SandyBridge-IBRS' => 'GenuineIntel',
+            IvyBridge => 'GenuineIntel',
+            'IvyBridge-IBRS' => 'GenuineIntel',
+            Haswell => 'GenuineIntel',
+            'Haswell-IBRS' => 'GenuineIntel',
+            'Haswell-noTSX' => 'GenuineIntel',
+            'Haswell-noTSX-IBRS' => 'GenuineIntel',
+            Broadwell => 'GenuineIntel',
+            'Broadwell-IBRS' => 'GenuineIntel',
+            'Broadwell-noTSX' => 'GenuineIntel',
+            'Broadwell-noTSX-IBRS' => 'GenuineIntel',
+            'Skylake-Client' => 'GenuineIntel',
+            'Skylake-Client-IBRS' => 'GenuineIntel',
+            'Skylake-Client-noTSX-IBRS' => 'GenuineIntel',
+            'Skylake-Client-v4' => 'GenuineIntel',
+            'Skylake-Server' => 'GenuineIntel',
+            'Skylake-Server-IBRS' => 'GenuineIntel',
+            'Skylake-Server-noTSX-IBRS' => 'GenuineIntel',
+            'Skylake-Server-v4' => 'GenuineIntel',
+            'Skylake-Server-v5' => 'GenuineIntel',
+            'Cascadelake-Server' => 'GenuineIntel',
+            'Cascadelake-Server-v2' => 'GenuineIntel',
+            'Cascadelake-Server-noTSX' => 'GenuineIntel',
+            'Cascadelake-Server-v4' => 'GenuineIntel',
+            'Cascadelake-Server-v5' => 'GenuineIntel',
+            'Cooperlake' => 'GenuineIntel',
+            'Cooperlake-v2' => 'GenuineIntel',
+            KnightsMill => 'GenuineIntel',
+            'Icelake-Client' => 'GenuineIntel', # depreacated, removed with QEMU 7.1
+            'Icelake-Client-noTSX' => 'GenuineIntel', # depreacated, removed with QEMU 7.1
+            'Icelake-Server' => 'GenuineIntel',
+            'Icelake-Server-noTSX' => 'GenuineIntel',
+            'Icelake-Server-v3' => 'GenuineIntel',
+            'Icelake-Server-v4' => 'GenuineIntel',
+            'Icelake-Server-v5' => 'GenuineIntel',
+            'Icelake-Server-v6' => 'GenuineIntel',
+            'Icelake-Server-v7' => 'GenuineIntel',
+            'SapphireRapids' => 'GenuineIntel',
+            'SapphireRapids-v2' => 'GenuineIntel',
+            'SapphireRapids-v3' => 'GenuineIntel',
+            'SapphireRapids-v4' => 'GenuineIntel',
+            'GraniteRapids' => 'GenuineIntel',
+            'GraniteRapids-v2' => 'GenuineIntel',
+            'GraniteRapids-v3' => 'GenuineIntel',
+            'SierraForest' => 'GenuineIntel',
+            'SierraForest-v2' => 'GenuineIntel',
+            'SierraForest-v3' => 'GenuineIntel',
+            'ClearwaterForest' => 'GenuineIntel',
+
+            # AMD CPUs
+            athlon => 'AuthenticAMD',
+            phenom => 'AuthenticAMD',
+            Opteron_G1 => 'AuthenticAMD',
+            Opteron_G2 => 'AuthenticAMD',
+            Opteron_G3 => 'AuthenticAMD',
+            Opteron_G4 => 'AuthenticAMD',
+            Opteron_G5 => 'AuthenticAMD',
+            EPYC => 'AuthenticAMD',
+            'EPYC-IBPB' => 'AuthenticAMD',
+            'EPYC-v3' => 'AuthenticAMD',
+            'EPYC-v4' => 'AuthenticAMD',
+            'EPYC-v5' => 'AuthenticAMD',
+            'EPYC-Rome' => 'AuthenticAMD',
+            'EPYC-Rome-v2' => 'AuthenticAMD',
+            'EPYC-Rome-v3' => 'AuthenticAMD',
+            'EPYC-Rome-v4' => 'AuthenticAMD',
+            'EPYC-Rome-v5' => 'AuthenticAMD',
+            'EPYC-Milan' => 'AuthenticAMD',
+            'EPYC-Milan-v2' => 'AuthenticAMD',
+            'EPYC-Milan-v3' => 'AuthenticAMD',
+            'EPYC-Genoa' => 'AuthenticAMD',
+            'EPYC-Genoa-v2' => 'AuthenticAMD',
+            'EPYC-Turin' => 'AuthenticAMD',
+
+            # generic types, use vendor from host node
+            kvm32 => 'default',
+            kvm64 => 'default',
+            qemu32 => 'default',
+            qemu64 => 'default',
+            max => 'default',
+        },
+        aarch64 => {
+            'a64fx' => 'ARM',
+            'cortex-a35' => 'ARM',
+            'cortex-a53' => 'ARM',
+            'cortex-a55' => 'ARM',
+            'cortex-a57' => 'ARM',
+            'cortex-a710' => 'ARM',
+            'cortex-a72' => 'ARM',
+            'cortex-a76' => 'ARM',
+            'neoverse-n1' => 'ARM',
+            'neoverse-n2' => 'ARM',
+            'neoverse-v1' => 'ARM',
+            # 32 bit and deprecated models were not added
+            max => 'default',
+        },
+    };
 
-my $all_cpu_models;
-for my $arch (keys $cpu_models_by_arch->%*) {
-    for my $model (keys $cpu_models_by_arch->{$arch}->%*) {
-        $all_cpu_models->{$model} = $cpu_models_by_arch->{$arch}->{$model};
+    my $host_arch = get_host_arch();
+    # The host CPU model only exists if the arch matches
+    $cpu_models_by_arch->{$host_arch}->{host} = 'default';
+
+    for my $arch (keys $cpu_models_by_arch->%*) {
+        for my $model (keys $cpu_models_by_arch->{$arch}->%*) {
+            $all_cpu_models->{$model} = $cpu_models_by_arch->{$arch}->{$model};
+        }
     }
 }
 
+initialize_cpu_models();
+
 my $supported_cpu_flags_by_arch = {
     x86_64 => [
         {
@@ -294,7 +300,7 @@ my $supported_cpu_flags_by_arch = {
 
 sub get_supported_cpu_flags {
     my ($arch) = @_;
-    $arch = $host_arch if !defined($arch);
+    $arch = get_host_arch() if !defined($arch);
     return $supported_cpu_flags_by_arch->{$arch};
 }
 
@@ -582,7 +588,7 @@ sub add_cpu_json_properties {
 sub get_cpu_models {
     my ($include_custom, $arch) = @_;
 
-    $arch = $host_arch if !defined($arch);
+    $arch = get_host_arch() if !defined($arch);
     my $cpu_vendor_list = $cpu_models_by_arch->{$arch};
 
     my $models = [];
@@ -1077,13 +1083,13 @@ sub get_default_cpu_type {
 
 sub is_native_arch($) {
     my ($arch) = @_;
-    return $host_arch eq $arch;
+    return get_host_arch() eq $arch;
 }
 
 sub get_cpu_bitness {
     my ($cpu_prop_str, $arch) = @_;
 
-    $arch //= $host_arch;
+    $arch //= get_host_arch();
 
     my $cputype = get_default_cpu_type($arch, 0);
 
diff --git a/src/PVE/QemuServer/Helpers.pm b/src/PVE/QemuServer/Helpers.pm
index 35c00754..e898440c 100644
--- a/src/PVE/QemuServer/Helpers.pm
+++ b/src/PVE/QemuServer/Helpers.pm
@@ -10,7 +10,7 @@ use JSON;
 use PVE::Cluster;
 use PVE::INotify;
 use PVE::ProcFSTools;
-use PVE::Tools qw(get_host_arch);
+use PVE::Tools;
 
 use base 'Exporter';
 our @EXPORT_OK = qw(
@@ -20,6 +20,7 @@ our @EXPORT_OK = qw(
     kvm_user_version
     parse_number_sets
     windows_version
+    get_host_arch
 );
 
 my $nodename = PVE::INotify::nodename();
@@ -29,6 +30,11 @@ my $arch_to_qemu_binary = {
     x86_64 => '/usr/bin/qemu-system-x86_64',
 };
 
+# wrapper around the Tools helper, having it here makes it easier for testing
+sub get_host_arch {
+    return PVE::Tools::get_host_arch();
+}
+
 sub get_command_for_arch($) {
     my ($arch) = @_;
     return '/usr/bin/kvm' if get_host_arch() eq $arch; # i.e. native arch
diff --git a/src/test/run_config2command_tests.pl b/src/test/run_config2command_tests.pl
index 4c872d1c..7ca2014e 100755
--- a/src/test/run_config2command_tests.pl
+++ b/src/test/run_config2command_tests.pl
@@ -235,6 +235,8 @@ sub parse_test($config_fn) {
         $testname = "'$testname' - $desc";
     }
     $current_test->{testname} = $testname;
+
+    PVE::QemuServer::CPUConfig::initialize_cpu_models();
 }
 
 sub get_test_qemu_version {
@@ -253,9 +255,6 @@ $qemu_server_module->mock(
     kernel_has_vhost_net => sub {
         return 1; # TODO: make this per-test configurable?
     },
-    get_host_arch => sub() {
-        return $current_test->{host_arch} // 'x86_64';
-    },
     get_iscsi_initiator_name => sub {
         return 'iqn.1993-08.org.debian:01:aabbccddeeff';
     },
@@ -388,6 +387,9 @@ $pve_common_tools->mock(
             },
         );
     },
+    get_host_arch => sub() {
+        return $current_test->{host_arch} // 'x86_64';
+    },
 );
 
 my $pve_cpuconfig;
-- 
2.47.3





             reply	other threads:[~2026-02-04 10:04 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-04 10:01 Dominik Csapak [this message]
2026-02-04 10:01 ` [PATCH qemu-server v2 2/2] tests: cfg2cmd: add some architecture tests Dominik Csapak
2026-02-04 15:46 ` [PATCH qemu-server v2 1/2] tests: improve multiarch build support Thomas Lamprecht

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260204100425.1303295-1-d.csapak@proxmox.com \
    --to=d.csapak@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal