public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [PATCH qemu-server v2 1/2] tests: improve multiarch build support
@ 2026-02-04 10:01 Dominik Csapak
  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
  0 siblings, 2 replies; 3+ messages in thread
From: Dominik Csapak @ 2026-02-04 10:01 UTC (permalink / raw)
  To: pve-devel

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





^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-02-04 15:46 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-02-04 10:01 [PATCH qemu-server v2 1/2] tests: improve multiarch build support Dominik Csapak
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal