* [pve-devel] [PATCH manager 01/10] api/pvestatd: broadcast and expose non-x86 host architecture
2026-01-28 12:18 [pve-devel] [PATCH manager 00/10] enable qemu vm architecture selection Dominik Csapak
@ 2026-01-28 12:18 ` Dominik Csapak
2026-01-28 16:05 ` Fiona Ebner
2026-01-28 12:18 ` [pve-devel] [PATCH manager 02/10] ui: resource store: add architecture field Dominik Csapak
` (9 subsequent siblings)
10 siblings, 1 reply; 25+ messages in thread
From: Dominik Csapak @ 2026-01-28 12:18 UTC (permalink / raw)
To: pve-devel
in case a nodes runs a non-x86 kernel, broadcast that info into the
'static-info' hash to pmxcfs (once). Use that info to add an
'architecture' property to /cluster/resources.
x86 nodes won't return a value here.
Use 'POSIX::uname' for determining the architecture (from the running
kernel). POSIX is used in this module anyway but was missing in the
imports.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
PVE/API2/Cluster.pm | 9 +++++++++
PVE/API2/Nodes.pm | 3 ++-
PVE/Service/pvestatd.pm | 10 ++++++++++
3 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/PVE/API2/Cluster.pm b/PVE/API2/Cluster.pm
index d6003a7d..73b948b5 100644
--- a/PVE/API2/Cluster.pm
+++ b/PVE/API2/Cluster.pm
@@ -484,6 +484,12 @@ __PACKAGE__->register_method({
type => "string",
optional => 1,
},
+ architecture => {
+ description => "The nodes CPU architecture. (for type 'node').",
+ type => 'string',
+ default => 'x86_64',
+ optional => 1,
+ },
},
},
},
@@ -608,6 +614,9 @@ __PACKAGE__->register_method({
if (defined(my $mode = $info->{'cgroup-mode'})) {
$entry->{'cgroup-mode'} = int($mode);
}
+ if (defined(my $architecture = $info->{architecture})) {
+ $entry->{architecture} = $architecture;
+ }
if (defined(my $status = $hastatus->{node_status}->{$node})) {
$entry->{'hastate'} = $status;
}
diff --git a/PVE/API2/Nodes.pm b/PVE/API2/Nodes.pm
index 5bd6fe49..9fddea9f 100644
--- a/PVE/API2/Nodes.pm
+++ b/PVE/API2/Nodes.pm
@@ -502,7 +502,8 @@ __PACKAGE__->register_method({
my ($avg1, $avg5, $avg15) = PVE::ProcFSTools::read_loadavg();
$res->{loadavg} = [$avg1, $avg5, $avg15];
- my ($current_kernel_info, $kversion_string) = get_current_kernel_info();
+ my ($current_kernel_info, $kversion_string) =
+ PVE::NodeConfig::get_current_kernel_info();
$res->{kversion} = $kversion_string;
$res->{'current-kernel'} = $current_kernel_info;
diff --git a/PVE/Service/pvestatd.pm b/PVE/Service/pvestatd.pm
index 98d421f4..05f4061e 100755
--- a/PVE/Service/pvestatd.pm
+++ b/PVE/Service/pvestatd.pm
@@ -7,6 +7,7 @@ use PVE::SafeSyslog;
use PVE::Daemon;
use JSON;
+use POSIX qw();
use Time::HiRes qw (gettimeofday);
use PVE::Tools qw(dir_glob_foreach file_read_firstline);
@@ -138,6 +139,8 @@ my sub broadcast_static_node_info {
my $cgroup_mode = eval { PVE::CGroup::cgroup_mode(); };
syslog('err', "cgroup mode error: $@") if $@;
+ my (undef, undef, undef, undef, $architecture) = POSIX::uname();
+
my $old = PVE::Cluster::get_node_kv('static-info', $nodename);
$old = eval { decode_json($old->{$nodename}) } if defined($old->{$nodename});
@@ -147,11 +150,18 @@ my sub broadcast_static_node_info {
|| !defined($old->{memory})
|| $old->{memory} != $memory
|| ($old->{'cgroup-mode'} // -1) != ($cgroup_mode // -1)
+ || (defined($architecture)
+ && $architecture ne 'x86_64'
+ && (!defined($old->{architecture}) || $old->{architecture} ne $architecture))
) {
my $info = {
cpus => $cpus,
memory => $memory,
};
+
+ # only save architecture info for non-x86 ones
+ $info->{architecture} = $architecture;
+
$info->{'cgroup-mode'} = $cgroup_mode if defined($cgroup_mode);
PVE::Cluster::broadcast_node_kv('static-info', encode_json($info));
}
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [pve-devel] [PATCH manager 01/10] api/pvestatd: broadcast and expose non-x86 host architecture
2026-01-28 12:18 ` [pve-devel] [PATCH manager 01/10] api/pvestatd: broadcast and expose non-x86 host architecture Dominik Csapak
@ 2026-01-28 16:05 ` Fiona Ebner
2026-01-29 9:20 ` Dominik Csapak
0 siblings, 1 reply; 25+ messages in thread
From: Fiona Ebner @ 2026-01-28 16:05 UTC (permalink / raw)
To: Proxmox VE development discussion, Dominik Csapak
Am 28.01.26 um 1:29 PM schrieb Dominik Csapak:
> in case a nodes runs a non-x86 kernel, broadcast that info into the
typo: nodes -> node
> 'static-info' hash to pmxcfs (once). Use that info to add an
> 'architecture' property to /cluster/resources.
>
> x86 nodes won't return a value here.
>
> Use 'POSIX::uname' for determining the architecture (from the running
> kernel). POSIX is used in this module anyway but was missing in the
> imports.
>
> Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
> ---
> PVE/API2/Cluster.pm | 9 +++++++++
> PVE/API2/Nodes.pm | 3 ++-
> PVE/Service/pvestatd.pm | 10 ++++++++++
> 3 files changed, 21 insertions(+), 1 deletion(-)
>
> diff --git a/PVE/API2/Cluster.pm b/PVE/API2/Cluster.pm
> index d6003a7d..73b948b5 100644
> --- a/PVE/API2/Cluster.pm
> +++ b/PVE/API2/Cluster.pm
> @@ -484,6 +484,12 @@ __PACKAGE__->register_method({
> type => "string",
> optional => 1,
> },
> + architecture => {
> + description => "The nodes CPU architecture. (for type 'node').",
typo: nodes -> node's
> + type => 'string',
could also be an enum
> + default => 'x86_64',
> + optional => 1,
> + },
> },
> },
> },
> @@ -608,6 +614,9 @@ __PACKAGE__->register_method({
> if (defined(my $mode = $info->{'cgroup-mode'})) {
> $entry->{'cgroup-mode'} = int($mode);
> }
> + if (defined(my $architecture = $info->{architecture})) {
> + $entry->{architecture} = $architecture;
> + }
> if (defined(my $status = $hastatus->{node_status}->{$node})) {
> $entry->{'hastate'} = $status;
> }
> diff --git a/PVE/API2/Nodes.pm b/PVE/API2/Nodes.pm
> index 5bd6fe49..9fddea9f 100644
> --- a/PVE/API2/Nodes.pm
> +++ b/PVE/API2/Nodes.pm
> @@ -502,7 +502,8 @@ __PACKAGE__->register_method({
> my ($avg1, $avg5, $avg15) = PVE::ProcFSTools::read_loadavg();
> $res->{loadavg} = [$avg1, $avg5, $avg15];
>
> - my ($current_kernel_info, $kversion_string) = get_current_kernel_info();
> + my ($current_kernel_info, $kversion_string) =
> + PVE::NodeConfig::get_current_kernel_info();
Seems like an unrelated hunk from an older iteration of the patch?
> $res->{kversion} = $kversion_string;
> $res->{'current-kernel'} = $current_kernel_info;
>
> diff --git a/PVE/Service/pvestatd.pm b/PVE/Service/pvestatd.pm
> index 98d421f4..05f4061e 100755
> --- a/PVE/Service/pvestatd.pm
> +++ b/PVE/Service/pvestatd.pm
> @@ -7,6 +7,7 @@ use PVE::SafeSyslog;
> use PVE::Daemon;
>
> use JSON;
> +use POSIX qw();
>
> use Time::HiRes qw (gettimeofday);
> use PVE::Tools qw(dir_glob_foreach file_read_firstline);
> @@ -138,6 +139,8 @@ my sub broadcast_static_node_info {
> my $cgroup_mode = eval { PVE::CGroup::cgroup_mode(); };
> syslog('err', "cgroup mode error: $@") if $@;
>
> + my (undef, undef, undef, undef, $architecture) = POSIX::uname();
> +
> my $old = PVE::Cluster::get_node_kv('static-info', $nodename);
> $old = eval { decode_json($old->{$nodename}) } if defined($old->{$nodename});
>
> @@ -147,11 +150,18 @@ my sub broadcast_static_node_info {
> || !defined($old->{memory})
> || $old->{memory} != $memory
> || ($old->{'cgroup-mode'} // -1) != ($cgroup_mode // -1)
> + || (defined($architecture)
> + && $architecture ne 'x86_64'
> + && (!defined($old->{architecture}) || $old->{architecture} ne $architecture))
> ) {
> my $info = {
> cpus => $cpus,
> memory => $memory,
> };
> +
> + # only save architecture info for non-x86 ones
> + $info->{architecture} = $architecture;
> +
> $info->{'cgroup-mode'} = $cgroup_mode if defined($cgroup_mode);
> PVE::Cluster::broadcast_node_kv('static-info', encode_json($info));
> }
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [pve-devel] [PATCH manager 01/10] api/pvestatd: broadcast and expose non-x86 host architecture
2026-01-28 16:05 ` Fiona Ebner
@ 2026-01-29 9:20 ` Dominik Csapak
0 siblings, 0 replies; 25+ messages in thread
From: Dominik Csapak @ 2026-01-29 9:20 UTC (permalink / raw)
To: Fiona Ebner, Proxmox VE development discussion
On 1/28/26 5:04 PM, Fiona Ebner wrote:
> Am 28.01.26 um 1:29 PM schrieb Dominik Csapak:
>> in case a nodes runs a non-x86 kernel, broadcast that info into the
>
> typo: nodes -> node
>
>> 'static-info' hash to pmxcfs (once). Use that info to add an
>> 'architecture' property to /cluster/resources.
>>
>> x86 nodes won't return a value here.
>>
>> Use 'POSIX::uname' for determining the architecture (from the running
>> kernel). POSIX is used in this module anyway but was missing in the
>> imports.
>>
>> Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
>> ---
>> PVE/API2/Cluster.pm | 9 +++++++++
>> PVE/API2/Nodes.pm | 3 ++-
>> PVE/Service/pvestatd.pm | 10 ++++++++++
>> 3 files changed, 21 insertions(+), 1 deletion(-)
>>
>> diff --git a/PVE/API2/Cluster.pm b/PVE/API2/Cluster.pm
>> index d6003a7d..73b948b5 100644
>> --- a/PVE/API2/Cluster.pm
>> +++ b/PVE/API2/Cluster.pm
>> @@ -484,6 +484,12 @@ __PACKAGE__->register_method({
>> type => "string",
>> optional => 1,
>> },
>> + architecture => {
>> + description => "The nodes CPU architecture. (for type 'node').",
>
> typo: nodes -> node's
>
>> + type => 'string',
>
> could also be an enum
i also thought about that but was not sure if we should limit ourselves
in the response here.
can do of course, and would add
'x86_64' and 'aarch64'
>
>> + default => 'x86_64',
>> + optional => 1,
>> + },
>> },
>> },
>> },
>> @@ -608,6 +614,9 @@ __PACKAGE__->register_method({
>> if (defined(my $mode = $info->{'cgroup-mode'})) {
>> $entry->{'cgroup-mode'} = int($mode);
>> }
>> + if (defined(my $architecture = $info->{architecture})) {
>> + $entry->{architecture} = $architecture;
>> + }
>> if (defined(my $status = $hastatus->{node_status}->{$node})) {
>> $entry->{'hastate'} = $status;
>> }
>> diff --git a/PVE/API2/Nodes.pm b/PVE/API2/Nodes.pm
>> index 5bd6fe49..9fddea9f 100644
>> --- a/PVE/API2/Nodes.pm
>> +++ b/PVE/API2/Nodes.pm
>> @@ -502,7 +502,8 @@ __PACKAGE__->register_method({
>> my ($avg1, $avg5, $avg15) = PVE::ProcFSTools::read_loadavg();
>> $res->{loadavg} = [$avg1, $avg5, $avg15];
>>
>> - my ($current_kernel_info, $kversion_string) = get_current_kernel_info();
>> + my ($current_kernel_info, $kversion_string) =
>> + PVE::NodeConfig::get_current_kernel_info();
>
> Seems like an unrelated hunk from an older iteration of the patch?
yep, in my first version i moved that function to reuse it, but
ultimately decided against that since i only need one field
from the uname call and we use the POSIX module here anyway..
>
>> $res->{kversion} = $kversion_string;
>> $res->{'current-kernel'} = $current_kernel_info;
>>
>> diff --git a/PVE/Service/pvestatd.pm b/PVE/Service/pvestatd.pm
>> index 98d421f4..05f4061e 100755
>> --- a/PVE/Service/pvestatd.pm
>> +++ b/PVE/Service/pvestatd.pm
>> @@ -7,6 +7,7 @@ use PVE::SafeSyslog;
>> use PVE::Daemon;
>>
>> use JSON;
>> +use POSIX qw();
>>
>> use Time::HiRes qw (gettimeofday);
>> use PVE::Tools qw(dir_glob_foreach file_read_firstline);
>> @@ -138,6 +139,8 @@ my sub broadcast_static_node_info {
>> my $cgroup_mode = eval { PVE::CGroup::cgroup_mode(); };
>> syslog('err', "cgroup mode error: $@") if $@;
>>
>> + my (undef, undef, undef, undef, $architecture) = POSIX::uname();
>> +
>> my $old = PVE::Cluster::get_node_kv('static-info', $nodename);
>> $old = eval { decode_json($old->{$nodename}) } if defined($old->{$nodename});
>>
>> @@ -147,11 +150,18 @@ my sub broadcast_static_node_info {
>> || !defined($old->{memory})
>> || $old->{memory} != $memory
>> || ($old->{'cgroup-mode'} // -1) != ($cgroup_mode // -1)
>> + || (defined($architecture)
>> + && $architecture ne 'x86_64'
>> + && (!defined($old->{architecture}) || $old->{architecture} ne $architecture))
>> ) {
>> my $info = {
>> cpus => $cpus,
>> memory => $memory,
>> };
>> +
>> + # only save architecture info for non-x86 ones
>> + $info->{architecture} = $architecture;
>> +
>> $info->{'cgroup-mode'} = $cgroup_mode if defined($cgroup_mode);
>> PVE::Cluster::broadcast_node_kv('static-info', encode_json($info));
>> }
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [pve-devel] [PATCH manager 02/10] ui: resource store: add architecture field
2026-01-28 12:18 [pve-devel] [PATCH manager 00/10] enable qemu vm architecture selection Dominik Csapak
2026-01-28 12:18 ` [pve-devel] [PATCH manager 01/10] api/pvestatd: broadcast and expose non-x86 host architecture Dominik Csapak
@ 2026-01-28 12:18 ` Dominik Csapak
2026-01-28 12:18 ` [pve-devel] [PATCH manager 03/10] ui: qemu: add architecture field in wizard and hardware view Dominik Csapak
` (8 subsequent siblings)
10 siblings, 0 replies; 25+ messages in thread
From: Dominik Csapak @ 2026-01-28 12:18 UTC (permalink / raw)
To: pve-devel
so we can use it from a node record.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/manager6/data/ResourceStore.js | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/www/manager6/data/ResourceStore.js b/www/manager6/data/ResourceStore.js
index bf740129..cca52914 100644
--- a/www/manager6/data/ResourceStore.js
+++ b/www/manager6/data/ResourceStore.js
@@ -210,6 +210,12 @@ Ext.define('PVE.data.ResourceStore', {
sortable: true,
width: 100,
},
+ architecture: {
+ header: gettext('Architecture'),
+ defaultValue: 'x86_64',
+ type: 'string',
+ hidden: true,
+ },
cpu: {
header: gettext('CPU usage'),
type: 'float',
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 25+ messages in thread* [pve-devel] [PATCH manager 03/10] ui: qemu: add architecture field in wizard and hardware view
2026-01-28 12:18 [pve-devel] [PATCH manager 00/10] enable qemu vm architecture selection Dominik Csapak
2026-01-28 12:18 ` [pve-devel] [PATCH manager 01/10] api/pvestatd: broadcast and expose non-x86 host architecture Dominik Csapak
2026-01-28 12:18 ` [pve-devel] [PATCH manager 02/10] ui: resource store: add architecture field Dominik Csapak
@ 2026-01-28 12:18 ` Dominik Csapak
2026-01-28 16:32 ` Fiona Ebner
2026-01-28 12:18 ` [pve-devel] [PATCH manager 04/10] ui: qemu: make scsi hw selector architecture aware Dominik Csapak
` (7 subsequent siblings)
10 siblings, 1 reply; 25+ messages in thread
From: Dominik Csapak @ 2026-01-28 12:18 UTC (permalink / raw)
To: pve-devel
adds a new architecture field to the wizard to select the target
architecture for the virtual machine. When the selected architecture
does not match the host architecture of the selected node, disable kvm.
Also show the architecture in the hardware view when it does not match
the host architecture (and add it automatically to the editors so we can
access it there).
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/manager6/Utils.js | 11 +++++++++++
www/manager6/qemu/CreateWizard.js | 26 ++++++++++++++++++++++++++
www/manager6/qemu/HardwareView.js | 16 ++++++++++++++++
3 files changed, 53 insertions(+)
diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index 2992f655..d8b212bc 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -2067,6 +2067,17 @@ Ext.define('PVE.Utils', {
);
return Ext.htmlEncode(description);
},
+
+ // returns if the given architecture is the native host architecture of the given nodename
+ isHostArchitecture: function (architecture, nodename) {
+ if (architecture === '__default__') {
+ architecture = undefined;
+ }
+
+ let hostArchitecture = PVE.data.ResourceStore.getNodeById(nodename)?.data.architecture;
+
+ return (architecture ?? 'x86_64') === (hostArchitecture ?? 'x86_64');
+ },
},
singleton: true,
diff --git a/www/manager6/qemu/CreateWizard.js b/www/manager6/qemu/CreateWizard.js
index 341324c8..d01c77e9 100644
--- a/www/manager6/qemu/CreateWizard.js
+++ b/www/manager6/qemu/CreateWizard.js
@@ -8,6 +8,7 @@ Ext.define('PVE.qemu.CreateWizard', {
nodename: '',
current: {
scsihw: '',
+ architecture: '__default__',
},
},
formulas: {
@@ -122,6 +123,23 @@ Ext.define('PVE.qemu.CreateWizard', {
deleteDefaultValue: true,
fieldLabel: gettext('Start at boot'),
},
+ {
+ xtype: 'proxmoxKVComboBox',
+ name: 'arch',
+ value: '__default__',
+ fieldLabel: gettext('Architecture'),
+ bind: {
+ value: '{current.architecture}',
+ },
+ comboItems: [
+ [
+ '__default__',
+ `${Proxmox.Utils.defaultText} (${gettext('Host Architecture')})`,
+ ],
+ ['x86_64', gettext('x86 (64-bit)')],
+ ['aarch64', gettext('ARM (64-bit)')],
+ ],
+ },
],
advancedColumn2: [
{
@@ -280,6 +298,10 @@ Ext.define('PVE.qemu.CreateWizard', {
kv.boot = boot;
}
+ if (kv.arch && !PVE.Utils.isHostArchitecture(kv.arch, kv.nodename)) {
+ kv.kvm = 0;
+ }
+
Ext.Object.each(kv, function (key, value) {
if (key === 'delete') {
// ignore
@@ -310,6 +332,10 @@ Ext.define('PVE.qemu.CreateWizard', {
kv.boot = boot;
}
+ if (kv.arch && !PVE.Utils.isHostArchitecture(kv.arch, nodename)) {
+ kv.kvm = 0;
+ }
+
Proxmox.Utils.API2Request({
url: '/nodes/' + nodename + '/qemu',
waitMsgTarget: wizard,
diff --git a/www/manager6/qemu/HardwareView.js b/www/manager6/qemu/HardwareView.js
index cf5e2a0f..b7cc7856 100644
--- a/www/manager6/qemu/HardwareView.js
+++ b/www/manager6/qemu/HardwareView.js
@@ -66,6 +66,21 @@ Ext.define('PVE.qemu.HardwareView', {
};
let rows = {
+ arch: {
+ header: gettext('Architecture'),
+ iconCls: 'university', // TODO: find/design better icon
+ renderer: function (value) {
+ switch (value ?? '') {
+ case '':
+ case 'x86_64':
+ return gettext('x86 (64-bit)');
+ case 'aarch64':
+ return gettext('ARM (64-bit)');
+ default:
+ return Proxmox.Utils.unknownText;
+ }
+ },
+ },
memory: {
header: gettext('Memory'),
editor: caps.vms['VM.Config.Memory'] ? 'PVE.qemu.MemoryEdit' : undefined,
@@ -419,6 +434,7 @@ Ext.define('PVE.qemu.HardwareView', {
pveSelNode: me.pveSelNode,
confid: rec.data.key,
url: `/api2/extjs/${baseurl}`,
+ arch: me.getObjectValue('arch'),
listeners: {
destroy: () => me.reload(),
},
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [pve-devel] [PATCH manager 03/10] ui: qemu: add architecture field in wizard and hardware view
2026-01-28 12:18 ` [pve-devel] [PATCH manager 03/10] ui: qemu: add architecture field in wizard and hardware view Dominik Csapak
@ 2026-01-28 16:32 ` Fiona Ebner
0 siblings, 0 replies; 25+ messages in thread
From: Fiona Ebner @ 2026-01-28 16:32 UTC (permalink / raw)
To: Proxmox VE development discussion, Dominik Csapak
Am 28.01.26 um 1:30 PM schrieb Dominik Csapak:
> adds a new architecture field to the wizard to select the target
> architecture for the virtual machine. When the selected architecture
> does not match the host architecture of the selected node, disable kvm.
>
> Also show the architecture in the hardware view when it does not match
> the host architecture (and add it automatically to the editors so we can
> access it there).
>
> Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
> ---
> www/manager6/Utils.js | 11 +++++++++++
> www/manager6/qemu/CreateWizard.js | 26 ++++++++++++++++++++++++++
> www/manager6/qemu/HardwareView.js | 16 ++++++++++++++++
> 3 files changed, 53 insertions(+)
>
> diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
> index 2992f655..d8b212bc 100644
> --- a/www/manager6/Utils.js
> +++ b/www/manager6/Utils.js
> @@ -2067,6 +2067,17 @@ Ext.define('PVE.Utils', {
> );
> return Ext.htmlEncode(description);
> },
> +
> + // returns if the given architecture is the native host architecture of the given nodename
> + isHostArchitecture: function (architecture, nodename) {
> + if (architecture === '__default__') {
> + architecture = undefined;
> + }
> +
> + let hostArchitecture = PVE.data.ResourceStore.getNodeById(nodename)?.data.architecture;
> +
> + return (architecture ?? 'x86_64') === (hostArchitecture ?? 'x86_64');
> + },
> },
>
> singleton: true,
> diff --git a/www/manager6/qemu/CreateWizard.js b/www/manager6/qemu/CreateWizard.js
> index 341324c8..d01c77e9 100644
> --- a/www/manager6/qemu/CreateWizard.js
> +++ b/www/manager6/qemu/CreateWizard.js
> @@ -8,6 +8,7 @@ Ext.define('PVE.qemu.CreateWizard', {
> nodename: '',
> current: {
> scsihw: '',
> + architecture: '__default__',
> },
> },
> formulas: {
> @@ -122,6 +123,23 @@ Ext.define('PVE.qemu.CreateWizard', {
> deleteDefaultValue: true,
> fieldLabel: gettext('Start at boot'),
> },
> + {
> + xtype: 'proxmoxKVComboBox',
> + name: 'arch',
> + value: '__default__',
> + fieldLabel: gettext('Architecture'),
Maybe 'vCPU Architecture' to be explicit?
> + bind: {
> + value: '{current.architecture}',
> + },
> + comboItems: [
> + [
> + '__default__',
> + `${Proxmox.Utils.defaultText} (${gettext('Host Architecture')})`,
> + ],
> + ['x86_64', gettext('x86 (64-bit)')],
> + ['aarch64', gettext('ARM (64-bit)')],
> + ],
> + },
> ],
> advancedColumn2: [
> {
Everything around it is related to startup (order), so it seems a bit
off IMHO. Should we put it further below by itself?
> @@ -280,6 +298,10 @@ Ext.define('PVE.qemu.CreateWizard', {
> kv.boot = boot;
> }
>
> + if (kv.arch && !PVE.Utils.isHostArchitecture(kv.arch, kv.nodename)) {
> + kv.kvm = 0;
> + }
> +
> Ext.Object.each(kv, function (key, value) {
> if (key === 'delete') {
> // ignore
> @@ -310,6 +332,10 @@ Ext.define('PVE.qemu.CreateWizard', {
> kv.boot = boot;
> }
>
> + if (kv.arch && !PVE.Utils.isHostArchitecture(kv.arch, nodename)) {
> + kv.kvm = 0;
> + }
> +
> Proxmox.Utils.API2Request({
> url: '/nodes/' + nodename + '/qemu',
> waitMsgTarget: wizard,
> diff --git a/www/manager6/qemu/HardwareView.js b/www/manager6/qemu/HardwareView.js
> index cf5e2a0f..b7cc7856 100644
> --- a/www/manager6/qemu/HardwareView.js
> +++ b/www/manager6/qemu/HardwareView.js
> @@ -66,6 +66,21 @@ Ext.define('PVE.qemu.HardwareView', {
> };
>
> let rows = {
> + arch: {
> + header: gettext('Architecture'),
> + iconCls: 'university', // TODO: find/design better icon
Maybe just reuse the CPU one?
I noticed that the Arch can be removed via the UI button. I guess it's
better to disable the button, to avoid any accidents (since it can't be
added back and is a very unusual change to begin with).
> + renderer: function (value) {
> + switch (value ?? '') {
> + case '':
> + case 'x86_64':
> + return gettext('x86 (64-bit)');
> + case 'aarch64':
> + return gettext('ARM (64-bit)');
> + default:
> + return Proxmox.Utils.unknownText;
> + }
> + },
> + },
> memory: {
> header: gettext('Memory'),
> editor: caps.vms['VM.Config.Memory'] ? 'PVE.qemu.MemoryEdit' : undefined,
> @@ -419,6 +434,7 @@ Ext.define('PVE.qemu.HardwareView', {
> pveSelNode: me.pveSelNode,
> confid: rec.data.key,
> url: `/api2/extjs/${baseurl}`,
> + arch: me.getObjectValue('arch'),
> listeners: {
> destroy: () => me.reload(),
> },
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 25+ messages in thread
* [pve-devel] [PATCH manager 04/10] ui: qemu: make scsi hw selector architecture aware
2026-01-28 12:18 [pve-devel] [PATCH manager 00/10] enable qemu vm architecture selection Dominik Csapak
` (2 preceding siblings ...)
2026-01-28 12:18 ` [pve-devel] [PATCH manager 03/10] ui: qemu: add architecture field in wizard and hardware view Dominik Csapak
@ 2026-01-28 12:18 ` Dominik Csapak
2026-01-28 12:18 ` [pve-devel] [PATCH manager 05/10] ui: qemu: make osdefaults " Dominik Csapak
` (6 subsequent siblings)
10 siblings, 0 replies; 25+ messages in thread
From: Dominik Csapak @ 2026-01-28 12:18 UTC (permalink / raw)
To: pve-devel
e.g. on aarch64 it makes only sense to use virtio-scsi or
virtio-scsi-single, so hide all other values, by adding a filter on the
internal store that allows only certain values.
Default to 'x86_64' for the architecture.
By using a setter for 'nodename' and 'arch' this also works in a
context where we can bind the values to these fields, e.g. in the wizard.
To properly trigger validation, we have to check the state before and
after setting the filter, since just a filter change, does not trigger
a validity change in the form field it seems.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/manager6/form/ScsiHwSelector.js | 63 +++++++++++++++++++++++++++++
www/manager6/qemu/ScsiHwEdit.js | 1 +
www/manager6/qemu/SystemEdit.js | 2 +
3 files changed, 66 insertions(+)
diff --git a/www/manager6/form/ScsiHwSelector.js b/www/manager6/form/ScsiHwSelector.js
index d35a5b3a..10d9f4db 100644
--- a/www/manager6/form/ScsiHwSelector.js
+++ b/www/manager6/form/ScsiHwSelector.js
@@ -10,4 +10,67 @@ Ext.define('PVE.form.ScsiHwSelector', {
['virtio-scsi-single', PVE.Utils.render_scsihw('virtio-scsi-single')],
['pvscsi', PVE.Utils.render_scsihw('pvscsi')],
],
+
+ controllersPerArchitecture: {
+ x86_64: [
+ '__default__',
+ 'lsi',
+ 'lsi53c810',
+ 'megasas',
+ 'virtio-scsi-pci',
+ 'virtio-scsi-single',
+ 'pvscsi',
+ ],
+ aarch64: ['virtio-scsi-pci', 'virtio-scsi-single'],
+ },
+
+ // defaults to hostArch
+ arch: undefined,
+
+ // depends on the node
+ hostArch: 'x86_64',
+
+ nodename: undefined,
+
+ setNodename: function (nodename) {
+ let me = this;
+ let node = PVE.data.ResourceStore.getNodeById(nodename);
+ if (node) {
+ me.hostArch = node.data.architecture;
+ me.setArch(me.arch); // recalculate the filter
+ }
+ },
+
+ setArch: function (arch) {
+ let me = this;
+ if (arch === '__default__') {
+ arch = undefined;
+ }
+ me.arch = arch;
+ arch ??= me.hostArch;
+ let wasValid = me.isValid();
+ me.store.clearFilter();
+ let allowedControllers = me.controllersPerArchitecture[arch];
+ me.store.addFilter((rec) => allowedControllers.indexOf(rec.data.key) !== -1);
+ // update default value with new arch
+ let record = me.store.findRecord('key', '__default__');
+ if (record) {
+ record.set('value', PVE.Utils.render_scsihw('', arch));
+ record.commit();
+ }
+ let isValid = me.isValid();
+
+ // for some reason, adding/changing filters does not trigger this, even though
+ // it show the field as invalid, so simply track and fire the event manually.
+ if (wasValid !== isValid) {
+ me.fireEvent('validitychange', isValid);
+ }
+ },
+
+ initComponent: function () {
+ let me = this;
+
+ me.callParent();
+ me.setArch(me.arch);
+ },
});
diff --git a/www/manager6/qemu/ScsiHwEdit.js b/www/manager6/qemu/ScsiHwEdit.js
index 48dcb228..212343c0 100644
--- a/www/manager6/qemu/ScsiHwEdit.js
+++ b/www/manager6/qemu/ScsiHwEdit.js
@@ -11,6 +11,7 @@ Ext.define('PVE.qemu.ScsiHwEdit', {
name: 'scsihw',
value: '__default__',
fieldLabel: gettext('Type'),
+ arch: me.arch,
},
});
diff --git a/www/manager6/qemu/SystemEdit.js b/www/manager6/qemu/SystemEdit.js
index 2cf17e8e..a2ad8494 100644
--- a/www/manager6/qemu/SystemEdit.js
+++ b/www/manager6/qemu/SystemEdit.js
@@ -140,6 +140,8 @@ Ext.define('PVE.qemu.SystemInputPanel', {
value: '__default__',
bind: {
value: '{current.scsihw}',
+ arch: '{current.architecture}',
+ nodename: '{nodename}',
},
fieldLabel: gettext('SCSI Controller'),
},
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 25+ messages in thread* [pve-devel] [PATCH manager 05/10] ui: qemu: make osdefaults architecture aware
2026-01-28 12:18 [pve-devel] [PATCH manager 00/10] enable qemu vm architecture selection Dominik Csapak
` (3 preceding siblings ...)
2026-01-28 12:18 ` [pve-devel] [PATCH manager 04/10] ui: qemu: make scsi hw selector architecture aware Dominik Csapak
@ 2026-01-28 12:18 ` Dominik Csapak
2026-01-29 9:25 ` Fiona Ebner
2026-01-28 12:18 ` [pve-devel] [PATCH manager 06/10] ui: qemu: make os type selector " Dominik Csapak
` (5 subsequent siblings)
10 siblings, 1 reply; 25+ messages in thread
From: Dominik Csapak @ 2026-01-28 12:18 UTC (permalink / raw)
To: pve-devel
This enables us to have different default for different architectures,
e.g. using 'ovmf' for 'aarch64' for everything.
The external interface should be compatible, so there is nothing
to do for current callers.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/manager6/qemu/OSDefaults.js | 74 ++++++++++++++++++++++++++-------
1 file changed, 58 insertions(+), 16 deletions(-)
diff --git a/www/manager6/qemu/OSDefaults.js b/www/manager6/qemu/OSDefaults.js
index bcebd0b3..3a707d60 100644
--- a/www/manager6/qemu/OSDefaults.js
+++ b/www/manager6/qemu/OSDefaults.js
@@ -24,8 +24,17 @@ Ext.define('PVE.qemu.OSDefaults', {
let addOS = function (settings) {
if (Object.hasOwn(settings, 'parent')) {
- let child = Ext.clone(me[settings.parent]);
- me[settings.pveOS] = Ext.apply(child, settings);
+ let architectures = settings.architectures;
+ delete settings.architectures;
+
+ let child = {
+ x86_64: Ext.apply({}, settings, me[settings.parent].x86_64),
+ };
+
+ for (const arch of Object.keys(architectures ?? {})) {
+ child[arch] = Ext.apply({}, architectures[arch], me[settings.parent][arch]);
+ }
+ me[settings.pveOS] = child;
} else {
throw 'Could not find your genitor';
}
@@ -33,16 +42,32 @@ Ext.define('PVE.qemu.OSDefaults', {
// default values
me.generic = {
- busType: 'ide',
- networkCard: 'e1000',
- busPriority: {
- ide: 4,
- sata: 3,
- scsi: 2,
- virtio: 1,
+ x86_64: {
+ busType: 'ide',
+ networkCard: 'e1000',
+ busPriority: {
+ ide: 4,
+ sata: 3,
+ scsi: 2,
+ virtio: 1,
+ },
+ scsihw: 'virtio-scsi-single',
+ cputype: 'x86-64-v2-AES',
+ },
+
+ aarch64: {
+ // aarch64 has no ide, and ovmf can't boot from sata
+ busType: 'scsi',
+ networkCard: 'e1000',
+ busPriority: {
+ scsi: 3,
+ sata: 2,
+ virtio: 1,
+ },
+ scsihw: 'virtio-scsi-single',
+ cputype: 'x86-64-v2-AES',
+ bios: 'ovmf',
},
- scsihw: 'virtio-scsi-single',
- cputype: 'x86-64-v2-AES',
};
// virtio-net is in kernel since 2.6.25
@@ -58,6 +83,17 @@ Ext.define('PVE.qemu.OSDefaults', {
ide: 1,
},
networkCard: 'virtio',
+
+ architectures: {
+ aarch64: {
+ busPriority: {
+ scsi: 3,
+ virtio: 2,
+ sata: 1,
+ },
+ networkCard: 'virtio',
+ },
+ },
});
// recommendation from http://wiki.qemu.org/Windows2000
@@ -73,12 +109,18 @@ Ext.define('PVE.qemu.OSDefaults', {
parent: 'w2k',
});
- me.getDefaults = function (ostype) {
- if (PVE.qemu.OSDefaults[ostype]) {
- return PVE.qemu.OSDefaults[ostype];
- } else {
- return PVE.qemu.OSDefaults.generic;
+ me.getDefaults = function (ostype, arch = 'x86_64') {
+ if (!PVE.qemu.OSDefaults[ostype]) {
+ ostype = 'generic';
}
+
+ let os = PVE.qemu.OSDefaults[ostype];
+ if (os[arch]) {
+ return os[arch];
+ }
+
+ // default
+ return os.x86_64;
};
},
});
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [pve-devel] [PATCH manager 05/10] ui: qemu: make osdefaults architecture aware
2026-01-28 12:18 ` [pve-devel] [PATCH manager 05/10] ui: qemu: make osdefaults " Dominik Csapak
@ 2026-01-29 9:25 ` Fiona Ebner
0 siblings, 0 replies; 25+ messages in thread
From: Fiona Ebner @ 2026-01-29 9:25 UTC (permalink / raw)
To: Proxmox VE development discussion, Dominik Csapak
Am 28.01.26 um 1:29 PM schrieb Dominik Csapak:
> This enables us to have different default for different architectures,
> e.g. using 'ovmf' for 'aarch64' for everything.
>
> The external interface should be compatible, so there is nothing
> to do for current callers.
>
> Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
> ---
> www/manager6/qemu/OSDefaults.js | 74 ++++++++++++++++++++++++++-------
> 1 file changed, 58 insertions(+), 16 deletions(-)
>
> diff --git a/www/manager6/qemu/OSDefaults.js b/www/manager6/qemu/OSDefaults.js
> index bcebd0b3..3a707d60 100644
> --- a/www/manager6/qemu/OSDefaults.js
> +++ b/www/manager6/qemu/OSDefaults.js
> @@ -24,8 +24,17 @@ Ext.define('PVE.qemu.OSDefaults', {
>
> let addOS = function (settings) {
> if (Object.hasOwn(settings, 'parent')) {
> - let child = Ext.clone(me[settings.parent]);
> - me[settings.pveOS] = Ext.apply(child, settings);
> + let architectures = settings.architectures;
> + delete settings.architectures;
> +
> + let child = {
> + x86_64: Ext.apply({}, settings, me[settings.parent].x86_64),
> + };
> +
> + for (const arch of Object.keys(architectures ?? {})) {
> + child[arch] = Ext.apply({}, architectures[arch], me[settings.parent][arch]);
> + }
> + me[settings.pveOS] = child;
> } else {
> throw 'Could not find your genitor';
> }
---snip 8<---
> @@ -58,6 +83,17 @@ Ext.define('PVE.qemu.OSDefaults', {
> ide: 1,
> },
> networkCard: 'virtio',
> +
> + architectures: {
Nit: I'd prefer something like architectureSpecific, what do you think?
> + aarch64: {
> + busPriority: {
> + scsi: 3,
> + virtio: 2,
> + sata: 1,
> + },
> + networkCard: 'virtio',
> + },
> + },
> });
>
> // recommendation from http://wiki.qemu.org/Windows2000
> @@ -73,12 +109,18 @@ Ext.define('PVE.qemu.OSDefaults', {
> parent: 'w2k',
> });
>
> - me.getDefaults = function (ostype) {
> - if (PVE.qemu.OSDefaults[ostype]) {
> - return PVE.qemu.OSDefaults[ostype];
> - } else {
> - return PVE.qemu.OSDefaults.generic;
> + me.getDefaults = function (ostype, arch = 'x86_64') {
> + if (!PVE.qemu.OSDefaults[ostype]) {
> + ostype = 'generic';
> }
> +
> + let os = PVE.qemu.OSDefaults[ostype];
> + if (os[arch]) {
> + return os[arch];
> + }
> +
> + // default
> + return os.x86_64;
> };
> },
> });
^ permalink raw reply [flat|nested] 25+ messages in thread
* [pve-devel] [PATCH manager 06/10] ui: qemu: make os type selector architecture aware
2026-01-28 12:18 [pve-devel] [PATCH manager 00/10] enable qemu vm architecture selection Dominik Csapak
` (4 preceding siblings ...)
2026-01-28 12:18 ` [pve-devel] [PATCH manager 05/10] ui: qemu: make osdefaults " Dominik Csapak
@ 2026-01-28 12:18 ` Dominik Csapak
2026-01-29 9:41 ` Fiona Ebner
2026-01-28 12:18 ` [pve-devel] [PATCH manager 07/10] ui: qemu: make machine panels/fields " Dominik Csapak
` (4 subsequent siblings)
10 siblings, 1 reply; 25+ messages in thread
From: Dominik Csapak @ 2026-01-28 12:18 UTC (permalink / raw)
To: pve-devel
A list of valid ostypes for each architecture is defined in PVE.Utils,
and this is used for the os type selector to only show relevant os
types.
Use a setter for 'arch' so we can bind the values again in the wizard,
similar to how the scsi selector is done.
Also update 'me.nodename' in 'setNodename'. This was never necessary
until now, but it is with the 'setArch' logic.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/manager6/Utils.js | 23 ++++++++++++++++++
www/manager6/qemu/CreateWizard.js | 1 +
www/manager6/qemu/OSTypeEdit.js | 39 ++++++++++++++++++++++++++++---
3 files changed, 60 insertions(+), 3 deletions(-)
diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index d8b212bc..de1ee0ba 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -63,6 +63,17 @@ Ext.define('PVE.Utils', {
Other: [{ desc: '-', val: 'other' }],
},
+ kvmOSTypesPerArchitecture: {
+ x86_64: {
+ bases: undefined, // include all
+ ostypes: undefined, // include all
+ },
+ aarch64: {
+ bases: ['Linux', 'Other'],
+ ostypes: ['l26', 'other'],
+ },
+ },
+
is_windows: function (ostype) {
for (let entry of PVE.Utils.kvm_ostypes['Microsoft Windows']) {
if (entry.val === ostype) {
@@ -2068,6 +2079,18 @@ Ext.define('PVE.Utils', {
return Ext.htmlEncode(description);
},
+ // returns the resulting architecture from a given arch and
+ // the nodename, in case the architecture is set to default
+ getArchitecture: function (architecture, nodename) {
+ if (architecture === '__default__') {
+ architecture = undefined;
+ }
+
+ let hostArchitecture = PVE.data.ResourceStore.getNodeById(nodename)?.data.architecture;
+
+ return architecture ?? hostArchitecture ?? 'x86_64';
+ },
+
// returns if the given architecture is the native host architecture of the given nodename
isHostArchitecture: function (architecture, nodename) {
if (architecture === '__default__') {
diff --git a/www/manager6/qemu/CreateWizard.js b/www/manager6/qemu/CreateWizard.js
index d01c77e9..16bf6d9b 100644
--- a/www/manager6/qemu/CreateWizard.js
+++ b/www/manager6/qemu/CreateWizard.js
@@ -222,6 +222,7 @@ Ext.define('PVE.qemu.CreateWizard', {
insideWizard: true,
bind: {
nodename: '{nodename}',
+ arch: '{current.architecture}',
},
},
],
diff --git a/www/manager6/qemu/OSTypeEdit.js b/www/manager6/qemu/OSTypeEdit.js
index f8f8c0b6..8c71f832 100644
--- a/www/manager6/qemu/OSTypeEdit.js
+++ b/www/manager6/qemu/OSTypeEdit.js
@@ -36,7 +36,11 @@ Ext.define('PVE.qemu.OSTypeInputPanel', {
if (!me.getView().insideWizard) {
return;
}
- var targetValues = PVE.qemu.OSDefaults.getDefaults(ostype);
+ let arch = PVE.Utils.getArchitecture(
+ me.getViewModel().get('current.architecture'),
+ me.nodename,
+ );
+ var targetValues = PVE.qemu.OSDefaults.getDefaults(ostype, arch);
me.setWidget('pveBusSelector', targetValues.busType);
me.setWidget('pveNetworkCardSelector', targetValues.networkCard);
@@ -77,17 +81,43 @@ Ext.define('PVE.qemu.OSTypeInputPanel', {
updateVMConfig();
me.setWidget('pveBusSelector', 'scsi');
let ostype = me.lookup('ostype').getValue();
- let targetValues = PVE.qemu.OSDefaults.getDefaults(ostype);
+ let arch = PVE.Utils.getArchitecture(
+ me.getViewModel().get('current.architecture'),
+ me.nodename,
+ );
+ let targetValues = PVE.qemu.OSDefaults.getDefaults(ostype, arch);
me.setWidget('pveBusSelector', targetValues.busType);
}
},
},
setNodename: function (nodename) {
- var me = this;
+ let me = this;
+ me.nodename = nodename;
me.lookup('isoSelector').setNodename(nodename);
},
+ setArch: function (arch) {
+ let me = this;
+
+ arch = PVE.Utils.getArchitecture(arch, me.nodename);
+ me.arch = arch;
+
+ let osbaseStore = me.lookup('osbase').getStore();
+ osbaseStore.clearFilter();
+ let list = PVE.Utils.kvmOSTypesPerArchitecture[arch]?.bases;
+ if (list) {
+ osbaseStore.addFilter((rec) => list.indexOf(rec.data.field1) !== -1);
+ }
+
+ let ostypeStore = me.lookup('ostype').getStore();
+ ostypeStore.clearFilter();
+ list = PVE.Utils.kvmOSTypesPerArchitecture[arch]?.ostypes;
+ if (list) {
+ ostypeStore.addFilter((rec) => list.indexOf(rec.data.val) !== -1);
+ }
+ },
+
onGetValues: function (values) {
if (values.ide0) {
let drive = {
@@ -112,6 +142,7 @@ Ext.define('PVE.qemu.OSTypeInputPanel', {
xtype: 'combobox',
submitValue: false,
name: 'osbase',
+ reference: 'osbase',
fieldLabel: gettext('Type'),
editable: false,
queryMode: 'local',
@@ -196,6 +227,8 @@ Ext.define('PVE.qemu.OSTypeEdit', {
var value = response.result.data.ostype || 'other';
var osinfo = PVE.Utils.get_kvm_osinfo(value);
me.setValues({ ostype: value, osbase: osinfo.base });
+ let arch = response.result.data.arch;
+ me.down('pveQemuOSTypePanel').setArch(arch);
},
});
},
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [pve-devel] [PATCH manager 06/10] ui: qemu: make os type selector architecture aware
2026-01-28 12:18 ` [pve-devel] [PATCH manager 06/10] ui: qemu: make os type selector " Dominik Csapak
@ 2026-01-29 9:41 ` Fiona Ebner
2026-01-29 9:47 ` Dominik Csapak
2026-01-29 10:18 ` Dominik Csapak
0 siblings, 2 replies; 25+ messages in thread
From: Fiona Ebner @ 2026-01-29 9:41 UTC (permalink / raw)
To: Proxmox VE development discussion, Dominik Csapak
Am 28.01.26 um 1:30 PM schrieb Dominik Csapak:
> diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
> index d8b212bc..de1ee0ba 100644
> --- a/www/manager6/Utils.js
> +++ b/www/manager6/Utils.js
> @@ -63,6 +63,17 @@ Ext.define('PVE.Utils', {
> Other: [{ desc: '-', val: 'other' }],
> },
>
> + kvmOSTypesPerArchitecture: {
> + x86_64: {
> + bases: undefined, // include all
> + ostypes: undefined, // include all
> + },
> + aarch64: {
> + bases: ['Linux', 'Other'],
> + ostypes: ['l26', 'other'],
What about Windows? Do we really want to hide that compeletely in the
UI? Unfortunately [;P], I expect that to be a non-negligible use case
and many requests to come in (which will miss that it's available on the
CLI). Or is it not properly supported in the backend? If yes, that
should be fixed, note that I have sent a patch at least for the
unavailable hyperv flags [0]. I mean, we can also wait and see if I'm
right. Maybe people don't care about it as much on ARM, I'd be glad ;)
[0]:
https://lore.proxmox.com/pve-devel/20260127134626.127432-3-f.ebner@proxmox.com/
> + },
> + },
> +
> is_windows: function (ostype) {
> for (let entry of PVE.Utils.kvm_ostypes['Microsoft Windows']) {
> if (entry.val === ostype) {
> @@ -2068,6 +2079,18 @@ Ext.define('PVE.Utils', {
> return Ext.htmlEncode(description);
> },
>
> + // returns the resulting architecture from a given arch and
> + // the nodename, in case the architecture is set to default
> + getArchitecture: function (architecture, nodename) {
getNodeArchitecture would be a bit more telling
> + if (architecture === '__default__') {
> + architecture = undefined;
> + }
> +
> + let hostArchitecture = PVE.data.ResourceStore.getNodeById(nodename)?.data.architecture;
> +
> + return architecture ?? hostArchitecture ?? 'x86_64';
> + },
> +
> // returns if the given architecture is the native host architecture of the given nodename
> isHostArchitecture: function (architecture, nodename) {
> if (architecture === '__default__') {
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [pve-devel] [PATCH manager 06/10] ui: qemu: make os type selector architecture aware
2026-01-29 9:41 ` Fiona Ebner
@ 2026-01-29 9:47 ` Dominik Csapak
2026-01-29 12:09 ` Fiona Ebner
2026-01-29 10:18 ` Dominik Csapak
1 sibling, 1 reply; 25+ messages in thread
From: Dominik Csapak @ 2026-01-29 9:47 UTC (permalink / raw)
To: Fiona Ebner, Proxmox VE development discussion
On 1/29/26 10:40 AM, Fiona Ebner wrote:
> Am 28.01.26 um 1:30 PM schrieb Dominik Csapak:
>> diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
>> index d8b212bc..de1ee0ba 100644
>> --- a/www/manager6/Utils.js
>> +++ b/www/manager6/Utils.js
>> @@ -63,6 +63,17 @@ Ext.define('PVE.Utils', {
>> Other: [{ desc: '-', val: 'other' }],
>> },
>>
>> + kvmOSTypesPerArchitecture: {
>> + x86_64: {
>> + bases: undefined, // include all
>> + ostypes: undefined, // include all
>> + },
>> + aarch64: {
>> + bases: ['Linux', 'Other'],
>> + ostypes: ['l26', 'other'],
>
> What about Windows? Do we really want to hide that compeletely in the
> UI? Unfortunately [;P], I expect that to be a non-negligible use case
> and many requests to come in (which will miss that it's available on the
> CLI). Or is it not properly supported in the backend? If yes, that
> should be fixed, note that I have sent a patch at least for the
> unavailable hyperv flags [0]. I mean, we can also wait and see if I'm
> right. Maybe people don't care about it as much on ARM, I'd be glad ;)
>
> [0]:
> https://lore.proxmox.com/pve-devel/20260127134626.127432-3-f.ebner@proxmox.com/
>
yeah, sorry should have expanded on the why here a bit:
yes, there are a few things in the backend still missing for windows arm
support, namely:
* display: the only device i could get windows to show anything was 'ramfb'
* iso/storage: since aarch64 does not support ide (at least in my tests
i couldn't get it to work, maybe there is a way), we have to use a
different bus for the iso/cdrom drives. virtio-scsi works theoretically,
but the windows installer stops at some point because the drivers are
missing. OVMF can't boot from other scsi controllers or sata.
so the only other way would be to implement usb-storage support, but
that's not here yet
so all in all i opted to hide windows for the moment because one cannot
make it work with the current options anyway
>> + },
>> + },
>> +
>> is_windows: function (ostype) {
>> for (let entry of PVE.Utils.kvm_ostypes['Microsoft Windows']) {
>> if (entry.val === ostype) {
>> @@ -2068,6 +2079,18 @@ Ext.define('PVE.Utils', {
>> return Ext.htmlEncode(description);
>> },
>>
>> + // returns the resulting architecture from a given arch and
>> + // the nodename, in case the architecture is set to default
>> + getArchitecture: function (architecture, nodename) {
>
> getNodeArchitecture would be a bit more telling
>
>> + if (architecture === '__default__') {
>> + architecture = undefined;
>> + }
>> +
>> + let hostArchitecture = PVE.data.ResourceStore.getNodeById(nodename)?.data.architecture;
>> +
>> + return architecture ?? hostArchitecture ?? 'x86_64';
>> + },
>> +
>> // returns if the given architecture is the native host architecture of the given nodename
>> isHostArchitecture: function (architecture, nodename) {
>> if (architecture === '__default__') {
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [pve-devel] [PATCH manager 06/10] ui: qemu: make os type selector architecture aware
2026-01-29 9:47 ` Dominik Csapak
@ 2026-01-29 12:09 ` Fiona Ebner
0 siblings, 0 replies; 25+ messages in thread
From: Fiona Ebner @ 2026-01-29 12:09 UTC (permalink / raw)
To: Dominik Csapak, Proxmox VE development discussion
Am 29.01.26 um 10:46 AM schrieb Dominik Csapak:
> On 1/29/26 10:40 AM, Fiona Ebner wrote:
>> Am 28.01.26 um 1:30 PM schrieb Dominik Csapak:
>>> diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
>>> index d8b212bc..de1ee0ba 100644
>>> --- a/www/manager6/Utils.js
>>> +++ b/www/manager6/Utils.js
>>> @@ -63,6 +63,17 @@ Ext.define('PVE.Utils', {
>>> Other: [{ desc: '-', val: 'other' }],
>>> },
>>> + kvmOSTypesPerArchitecture: {
>>> + x86_64: {
>>> + bases: undefined, // include all
>>> + ostypes: undefined, // include all
>>> + },
>>> + aarch64: {
>>> + bases: ['Linux', 'Other'],
>>> + ostypes: ['l26', 'other'],
>>
>> What about Windows? Do we really want to hide that compeletely in the
>> UI? Unfortunately [;P], I expect that to be a non-negligible use case
>> and many requests to come in (which will miss that it's available on the
>> CLI). Or is it not properly supported in the backend? If yes, that
>> should be fixed, note that I have sent a patch at least for the
>> unavailable hyperv flags [0]. I mean, we can also wait and see if I'm
>> right. Maybe people don't care about it as much on ARM, I'd be glad ;)
>>
>> [0]:
>> https://lore.proxmox.com/pve-devel/20260127134626.127432-3-
>> f.ebner@proxmox.com/
>>
>
> yeah, sorry should have expanded on the why here a bit:
>
> yes, there are a few things in the backend still missing for windows arm
> support, namely:
> * display: the only device i could get windows to show anything was 'ramfb'
> * iso/storage: since aarch64 does not support ide (at least in my tests
> i couldn't get it to work, maybe there is a way), we have to use a
> different bus for the iso/cdrom drives. virtio-scsi works theoretically,
> but the windows installer stops at some point because the drivers are
> missing. OVMF can't boot from other scsi controllers or sata.
>
> so the only other way would be to implement usb-storage support, but
> that's not here yet
>
> so all in all i opted to hide windows for the moment because one cannot
> make it work with the current options anyway
Seems like there are virtio-win drivers for win11:
https://virtio-win.github.io/Knowledge-Base/Windows-arm64-vm-using-qemu.html
But also requires going into regedit during installation to disable TPM ;P
Yeah, let's just not expose it in the UI for now if there is no
first-class support for it yet.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [pve-devel] [PATCH manager 06/10] ui: qemu: make os type selector architecture aware
2026-01-29 9:41 ` Fiona Ebner
2026-01-29 9:47 ` Dominik Csapak
@ 2026-01-29 10:18 ` Dominik Csapak
2026-01-29 12:10 ` Fiona Ebner
1 sibling, 1 reply; 25+ messages in thread
From: Dominik Csapak @ 2026-01-29 10:18 UTC (permalink / raw)
To: Fiona Ebner, Proxmox VE development discussion
btw. i found some bugs with the current ostype implementation
(there is some bad behavior with different host arch + wizard vs non-wizard)
i'm currently contemplating rewriting this + the iso edit component into
pure 'non-wizard' components and make a separate 'iso+ostype' panel
that's specific for the wizard.
that would clean up a fair bit of code and make the different flows
a bit cleaner
also, i'd like to change the way we generate the architecture in the wizard.
imho it's better to let the wizard calculate the 'correct' arch
(including considering the hostarch) than each component itself
On 1/29/26 10:40 AM, Fiona Ebner wrote:
> Am 28.01.26 um 1:30 PM schrieb Dominik Csapak:
>> diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
>> index d8b212bc..de1ee0ba 100644
>> --- a/www/manager6/Utils.js
>> +++ b/www/manager6/Utils.js
>> @@ -63,6 +63,17 @@ Ext.define('PVE.Utils', {
>> Other: [{ desc: '-', val: 'other' }],
>> },
>>
>> + kvmOSTypesPerArchitecture: {
>> + x86_64: {
>> + bases: undefined, // include all
>> + ostypes: undefined, // include all
>> + },
>> + aarch64: {
>> + bases: ['Linux', 'Other'],
>> + ostypes: ['l26', 'other'],
>
> What about Windows? Do we really want to hide that compeletely in the
> UI? Unfortunately [;P], I expect that to be a non-negligible use case
> and many requests to come in (which will miss that it's available on the
> CLI). Or is it not properly supported in the backend? If yes, that
> should be fixed, note that I have sent a patch at least for the
> unavailable hyperv flags [0]. I mean, we can also wait and see if I'm
> right. Maybe people don't care about it as much on ARM, I'd be glad ;)
>
> [0]:
> https://lore.proxmox.com/pve-devel/20260127134626.127432-3-f.ebner@proxmox.com/
>
>> + },
>> + },
>> +
>> is_windows: function (ostype) {
>> for (let entry of PVE.Utils.kvm_ostypes['Microsoft Windows']) {
>> if (entry.val === ostype) {
>> @@ -2068,6 +2079,18 @@ Ext.define('PVE.Utils', {
>> return Ext.htmlEncode(description);
>> },
>>
>> + // returns the resulting architecture from a given arch and
>> + // the nodename, in case the architecture is set to default
>> + getArchitecture: function (architecture, nodename) {
>
> getNodeArchitecture would be a bit more telling
>
>> + if (architecture === '__default__') {
>> + architecture = undefined;
>> + }
>> +
>> + let hostArchitecture = PVE.data.ResourceStore.getNodeById(nodename)?.data.architecture;
>> +
>> + return architecture ?? hostArchitecture ?? 'x86_64';
>> + },
>> +
>> // returns if the given architecture is the native host architecture of the given nodename
>> isHostArchitecture: function (architecture, nodename) {
>> if (architecture === '__default__') {
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [pve-devel] [PATCH manager 06/10] ui: qemu: make os type selector architecture aware
2026-01-29 10:18 ` Dominik Csapak
@ 2026-01-29 12:10 ` Fiona Ebner
0 siblings, 0 replies; 25+ messages in thread
From: Fiona Ebner @ 2026-01-29 12:10 UTC (permalink / raw)
To: Dominik Csapak, Proxmox VE development discussion
Am 29.01.26 um 11:17 AM schrieb Dominik Csapak:
> btw. i found some bugs with the current ostype implementation
> (there is some bad behavior with different host arch + wizard vs non-
> wizard)
>
> i'm currently contemplating rewriting this + the iso edit component into
> pure 'non-wizard' components and make a separate 'iso+ostype' panel
> that's specific for the wizard.
>
> that would clean up a fair bit of code and make the different flows
> a bit cleaner
>
> also, i'd like to change the way we generate the architecture in the
> wizard.
>
> imho it's better to let the wizard calculate the 'correct' arch
> (including considering the hostarch) than each component itself
Sounds good!
^ permalink raw reply [flat|nested] 25+ messages in thread
* [pve-devel] [PATCH manager 07/10] ui: qemu: make machine panels/fields architecture aware
2026-01-28 12:18 [pve-devel] [PATCH manager 00/10] enable qemu vm architecture selection Dominik Csapak
` (5 preceding siblings ...)
2026-01-28 12:18 ` [pve-devel] [PATCH manager 06/10] ui: qemu: make os type selector " Dominik Csapak
@ 2026-01-28 12:18 ` Dominik Csapak
2026-01-29 11:12 ` Fiona Ebner
2026-01-28 12:18 ` [pve-devel] [PATCH manager 08/10] ui: qemu: make bios selector " Dominik Csapak
` (3 subsequent siblings)
10 siblings, 1 reply; 25+ messages in thread
From: Dominik Csapak @ 2026-01-28 12:18 UTC (permalink / raw)
To: pve-devel
For this, introduce a new 'QemuMachineSelector', which does the same
thing as the scsihw selector by filtering the kv store with a predefined
list for each architecture.
Since the backend default of the machine is actually different for
x86_64 vs aarch64, there is some logic to handle the 'default' value
for the machine (iow. replace 'pc' with the default machine for each
architecture)
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/manager6/Makefile | 1 +
www/manager6/Utils.js | 18 ++++++-
www/manager6/form/QemuMachineSelector.js | 64 ++++++++++++++++++++++++
www/manager6/qemu/HardwareView.js | 3 +-
www/manager6/qemu/MachineEdit.js | 63 +++++++++++++++++------
www/manager6/qemu/SystemEdit.js | 10 ++--
6 files changed, 136 insertions(+), 23 deletions(-)
create mode 100644 www/manager6/form/QemuMachineSelector.js
diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 4558d53e..7670b95d 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -62,6 +62,7 @@ JSSRC= \
form/PreallocationSelector.js \
form/PrivilegesSelector.js \
form/QemuBiosSelector.js \
+ form/QemuMachineSelector.js \
form/SDNControllerSelector.js \
form/SDNZoneSelector.js \
form/SDNVnetSelector.js \
diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index de1ee0ba..613a7113 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -509,8 +509,22 @@ Ext.define('PVE.Utils', {
return agentstring;
},
- render_qemu_machine: function (value) {
- return value || Proxmox.Utils.defaultText + ' (i440fx)';
+ defaultMachines: {
+ x86_64: 'pc',
+ aarch64: 'virt',
+ },
+
+ machineText: {
+ pc: 'i440fx',
+ },
+
+ render_qemu_machine: function (value, arch = 'x86_64') {
+ if (!value) {
+ let machine = PVE.Utils.defaultMachines[arch];
+ let machineText = PVE.Utils.machineText[machine] ?? machine;
+ return `${Proxmox.Utils.defaultText} (${machineText})`;
+ }
+ return value;
},
render_qemu_bios: function (value) {
diff --git a/www/manager6/form/QemuMachineSelector.js b/www/manager6/form/QemuMachineSelector.js
new file mode 100644
index 00000000..2852b585
--- /dev/null
+++ b/www/manager6/form/QemuMachineSelector.js
@@ -0,0 +1,64 @@
+Ext.define('PVE.form.QemuMachineSelector', {
+ extend: 'Proxmox.form.KVComboBox',
+ alias: 'widget.pveQemuMachineSelector',
+
+ comboItems: [
+ ['__default__', PVE.Utils.render_qemu_machine('')],
+ ['q35', 'q35'],
+ ],
+
+ machinesPerArchitecture: {
+ x86_64: ['__default__', 'q35'], // __default__ is i440fx
+ aarch64: ['__default__'], // __default__ is virt
+ },
+
+ // defaults to hostArch
+ arch: undefined,
+
+ // depends on the node
+ hostArch: 'x86_64',
+
+ nodename: undefined,
+
+ setNodename: function (nodename) {
+ let me = this;
+ let node = PVE.data.ResourceStore.getNodeById(nodename);
+ if (node) {
+ me.hostArch = node.data.architecture;
+ me.setArch(me.arch); // recalculate the filter
+ }
+ },
+
+ setArch: function (arch) {
+ let me = this;
+ if (arch === '__default__') {
+ arch = undefined;
+ }
+ me.arch = arch;
+ arch ??= me.hostArch;
+ let wasValid = me.isValid();
+ me.store.clearFilter();
+ let allowedMachines = me.machinesPerArchitecture[arch];
+ me.store.addFilter((rec) => allowedMachines.indexOf(rec.data.key) !== -1);
+ // update default value with new arch
+ let record = me.store.findRecord('key', '__default__');
+ if (record) {
+ record.set('value', PVE.Utils.render_qemu_machine('', arch));
+ record.commit();
+ }
+ let isValid = me.isValid();
+
+ // for some reason, adding/changing filters does not trigger this, even though
+ // it show the field as invalid, so simply track and fire the event manually.
+ if (wasValid !== isValid) {
+ me.fireEvent('validitychange', isValid);
+ }
+ },
+
+ initComponent: function () {
+ var me = this;
+
+ me.callParent();
+ me.setArch(me.arch);
+ },
+});
diff --git a/www/manager6/qemu/HardwareView.js b/www/manager6/qemu/HardwareView.js
index b7cc7856..1e2cd026 100644
--- a/www/manager6/qemu/HardwareView.js
+++ b/www/manager6/qemu/HardwareView.js
@@ -202,13 +202,14 @@ Ext.define('PVE.qemu.HardwareView', {
defaultValue: '',
renderer: function (value, metaData, record, rowIndex, colIndex, store, pending) {
let ostype = me.getObjectValue('ostype', undefined, pending);
+ let arch = PVE.Utils.getArchitecture(me.getObjectValue('arch'), nodename);
if (
PVE.Utils.is_windows(ostype) &&
(!value || value === 'pc' || value === 'q35')
) {
return value === 'q35' ? 'pc-q35-5.1' : 'pc-i440fx-5.1';
}
- return PVE.Utils.render_qemu_machine(value);
+ return PVE.Utils.render_qemu_machine(value, arch);
},
},
scsihw: {
diff --git a/www/manager6/qemu/MachineEdit.js b/www/manager6/qemu/MachineEdit.js
index 1b1989e8..89d13886 100644
--- a/www/manager6/qemu/MachineEdit.js
+++ b/www/manager6/qemu/MachineEdit.js
@@ -23,8 +23,16 @@ Ext.define('PVE.qemu.MachineInputPanel', {
let me = this;
let version = me.lookup('version');
let store = version.getStore();
+
let oldRec = store.findRecord('id', version.getValue(), 0, false, false, true);
- let type = value === 'q35' ? 'q35' : 'i440fx';
+
+ let vm = me.getViewModel();
+ let arch = PVE.Utils.getArchitecture(vm.get('arch'), vm.get('nodename'));
+ let defaultMachine = PVE.Utils.defaultMachines[arch];
+ if (defaultMachine === 'pc') {
+ defaultMachine = 'i440fx'; // the default in the backend is 'pc' which means 'i440fx' for the qemu machinetype'
+ }
+ let type = value === 'q35' ? 'q35' : defaultMachine;
store.clearFilter();
store.addFilter((val) => val.data.id === 'latest' || val.data.type === type);
if (!me.getView().isWindows) {
@@ -45,9 +53,12 @@ Ext.define('PVE.qemu.MachineInputPanel', {
},
onGetValues: function (values) {
+ let me = this;
+ let arch = PVE.Utils.getArchitecture(values.arch, me.nodename);
+ delete values.arch;
if (values.delete === 'machine' && values.viommu) {
delete values.delete;
- values.machine = 'pc';
+ values.machine = PVE.Utils.defaultMachines[arch];
}
if (values.version && values.version !== 'latest') {
values.machine = values.version;
@@ -68,8 +79,10 @@ Ext.define('PVE.qemu.MachineInputPanel', {
let machineConf = PVE.Parser.parsePropertyString(values.machine, 'type');
values.machine = machineConf.type;
+ let arch = PVE.Utils.getArchitecture(values.arch, me.nodename);
+ let defaultMachine = PVE.Utils.defaultMachines[arch];
me.isWindows = values.isWindows;
- if (values.machine === 'pc') {
+ if (values.machine === defaultMachine) {
values.machine = '__default__';
}
@@ -94,19 +107,31 @@ Ext.define('PVE.qemu.MachineInputPanel', {
this.callParent(arguments);
},
- items: {
- xtype: 'proxmoxKVComboBox',
- name: 'machine',
- reference: 'machine',
- fieldLabel: gettext('Machine'),
- comboItems: [
- ['__default__', PVE.Utils.render_qemu_machine('')],
- ['q35', 'q35'],
- ],
- bind: {
- value: '{type}',
+ items: [
+ {
+ xtype: 'pveQemuMachineSelector',
+ name: 'machine',
+ reference: 'machine',
+ fieldLabel: gettext('Machine'),
+ bind: {
+ value: '{type}',
+ arch: '{arch}',
+ nodename: '{nodename}',
+ },
},
- },
+ {
+ xtype: 'hidden',
+ name: 'arch',
+ reference: 'arch',
+ bind: '{arch}',
+ },
+ {
+ xtype: 'hidden',
+ name: 'nodename',
+ submitValue: false,
+ bind: '{nodename}',
+ },
+ ],
advancedItems: [
{
@@ -197,6 +222,12 @@ Ext.define('PVE.qemu.MachineEdit', {
initComponent: function () {
let me = this;
+ me.nodename = me.pveSelNode?.data.node;
+
+ if (!me.nodename) {
+ throw 'no nodename given';
+ }
+
me.callParent();
me.load({
@@ -206,6 +237,8 @@ Ext.define('PVE.qemu.MachineEdit', {
machine: conf.machine || '__default__',
};
values.isWindows = PVE.Utils.is_windows(conf.ostype);
+ values.arch = PVE.Utils.getArchitecture(conf.arch, me.nodename);
+ values.nodename = me.nodename;
me.setValues(values);
},
});
diff --git a/www/manager6/qemu/SystemEdit.js b/www/manager6/qemu/SystemEdit.js
index a2ad8494..71fd1125 100644
--- a/www/manager6/qemu/SystemEdit.js
+++ b/www/manager6/qemu/SystemEdit.js
@@ -83,15 +83,15 @@ Ext.define('PVE.qemu.SystemInputPanel', {
comboItems: Object.entries(PVE.Utils.kvm_vga_drivers),
},
{
- xtype: 'proxmoxKVComboBox',
+ xtype: 'pveQemuMachineSelector',
name: 'machine',
reference: 'machine',
value: '__default__',
fieldLabel: gettext('Machine'),
- comboItems: [
- ['__default__', PVE.Utils.render_qemu_machine('')],
- ['q35', 'q35'],
- ],
+ bind: {
+ arch: '{current.architecture}',
+ nodename: '{nodename}',
+ },
},
{
xtype: 'displayfield',
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [pve-devel] [PATCH manager 07/10] ui: qemu: make machine panels/fields architecture aware
2026-01-28 12:18 ` [pve-devel] [PATCH manager 07/10] ui: qemu: make machine panels/fields " Dominik Csapak
@ 2026-01-29 11:12 ` Fiona Ebner
2026-01-29 12:16 ` Dominik Csapak
0 siblings, 1 reply; 25+ messages in thread
From: Fiona Ebner @ 2026-01-29 11:12 UTC (permalink / raw)
To: Proxmox VE development discussion, Dominik Csapak
Am 28.01.26 um 1:30 PM schrieb Dominik Csapak:
> For this, introduce a new 'QemuMachineSelector', which does the same
> thing as the scsihw selector by filtering the kv store with a predefined
> list for each architecture.
>
> Since the backend default of the machine is actually different for
> x86_64 vs aarch64, there is some logic to handle the 'default' value
> for the machine (iow. replace 'pc' with the default machine for each
> architecture)
>
Setting a machine version for an existing aarch64 VM is broken, e.g. the
result will be "pc-i440fx-10.1" instead.
> Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
> ---
> www/manager6/Makefile | 1 +
> www/manager6/Utils.js | 18 ++++++-
> www/manager6/form/QemuMachineSelector.js | 64 ++++++++++++++++++++++++
> www/manager6/qemu/HardwareView.js | 3 +-
> www/manager6/qemu/MachineEdit.js | 63 +++++++++++++++++------
> www/manager6/qemu/SystemEdit.js | 10 ++--
> 6 files changed, 136 insertions(+), 23 deletions(-)
> create mode 100644 www/manager6/form/QemuMachineSelector.js
>
> diff --git a/www/manager6/Makefile b/www/manager6/Makefile
> index 4558d53e..7670b95d 100644
> --- a/www/manager6/Makefile
> +++ b/www/manager6/Makefile
> @@ -62,6 +62,7 @@ JSSRC= \
> form/PreallocationSelector.js \
> form/PrivilegesSelector.js \
> form/QemuBiosSelector.js \
> + form/QemuMachineSelector.js \
> form/SDNControllerSelector.js \
> form/SDNZoneSelector.js \
> form/SDNVnetSelector.js \
> diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
> index de1ee0ba..613a7113 100644
> --- a/www/manager6/Utils.js
> +++ b/www/manager6/Utils.js
> @@ -509,8 +509,22 @@ Ext.define('PVE.Utils', {
> return agentstring;
> },
>
> - render_qemu_machine: function (value) {
> - return value || Proxmox.Utils.defaultText + ' (i440fx)';
> + defaultMachines: {
> + x86_64: 'pc',
> + aarch64: 'virt',
> + },
> +
> + machineText: {
> + pc: 'i440fx',
> + },
These new entries should mention QEMU somewhere in their name, because
it's in the very general/stuffed Utils class.
> +
> + render_qemu_machine: function (value, arch = 'x86_64') {
> + if (!value) {
> + let machine = PVE.Utils.defaultMachines[arch];
> + let machineText = PVE.Utils.machineText[machine] ?? machine;
> + return `${Proxmox.Utils.defaultText} (${machineText})`;
> + }
> + return value;
> },
>
> render_qemu_bios: function (value) {
> diff --git a/www/manager6/form/QemuMachineSelector.js b/www/manager6/form/QemuMachineSelector.js
> new file mode 100644
> index 00000000..2852b585
> --- /dev/null
> +++ b/www/manager6/form/QemuMachineSelector.js
> @@ -0,0 +1,64 @@
> +Ext.define('PVE.form.QemuMachineSelector', {
> + extend: 'Proxmox.form.KVComboBox',
> + alias: 'widget.pveQemuMachineSelector',
> +
> + comboItems: [
> + ['__default__', PVE.Utils.render_qemu_machine('')],
> + ['q35', 'q35'],
> + ],
> +
> + machinesPerArchitecture: {
> + x86_64: ['__default__', 'q35'], // __default__ is i440fx
> + aarch64: ['__default__'], // __default__ is virt
> + },
> +
> + // defaults to hostArch
> + arch: undefined,
> +
> + // depends on the node
> + hostArch: 'x86_64',
Sounds like it should start as undefined and we should require a
nodename to be present at init time then and set hostArch accordingly?
Otherwise, it seems a bit brittle and might be wrong if setNodename() is
forgotten to be called by a use site.
> +
> + nodename: undefined,
> +
> + setNodename: function (nodename) {
> + let me = this;
> + let node = PVE.data.ResourceStore.getNodeById(nodename);
> + if (node) {
> + me.hostArch = node.data.architecture;
> + me.setArch(me.arch); // recalculate the filter
> + }
> + },
> +
> + setArch: function (arch) {
> + let me = this;
> + if (arch === '__default__') {
> + arch = undefined;
> + }
> + me.arch = arch;
> + arch ??= me.hostArch;
> + let wasValid = me.isValid();
> + me.store.clearFilter();
> + let allowedMachines = me.machinesPerArchitecture[arch];
> + me.store.addFilter((rec) => allowedMachines.indexOf(rec.data.key) !== -1);
> + // update default value with new arch
> + let record = me.store.findRecord('key', '__default__');
> + if (record) {
> + record.set('value', PVE.Utils.render_qemu_machine('', arch));
> + record.commit();
> + }
> + let isValid = me.isValid();
> +
> + // for some reason, adding/changing filters does not trigger this, even though
> + // it show the field as invalid, so simply track and fire the event manually.
> + if (wasValid !== isValid) {
> + me.fireEvent('validitychange', isValid);
> + }
> + },
> +
> + initComponent: function () {
> + var me = this;
> +
> + me.callParent();
> + me.setArch(me.arch);
> + },
> +});
> diff --git a/www/manager6/qemu/HardwareView.js b/www/manager6/qemu/HardwareView.js
> index b7cc7856..1e2cd026 100644
> --- a/www/manager6/qemu/HardwareView.js
> +++ b/www/manager6/qemu/HardwareView.js
> @@ -202,13 +202,14 @@ Ext.define('PVE.qemu.HardwareView', {
> defaultValue: '',
> renderer: function (value, metaData, record, rowIndex, colIndex, store, pending) {
> let ostype = me.getObjectValue('ostype', undefined, pending);
> + let arch = PVE.Utils.getArchitecture(me.getObjectValue('arch'), nodename);
> if (
> PVE.Utils.is_windows(ostype) &&
> (!value || value === 'pc' || value === 'q35')
> ) {
> return value === 'q35' ? 'pc-q35-5.1' : 'pc-i440fx-5.1';
Unrelated to the patch, but I noticed now that this is actually wrong.
Since QEMU 9.1+ the backend defaults to the creation version if present.
But related to the series, it should default to virt for ARM of course,
which it doesn't yet, but I sent a patch:
https://lore.proxmox.com/pve-devel/20260129110607.65416-1-f.ebner@proxmox.com/T/
> }
> - return PVE.Utils.render_qemu_machine(value);
> + return PVE.Utils.render_qemu_machine(value, arch);
> },
> },
> scsihw: {
> diff --git a/www/manager6/qemu/MachineEdit.js b/www/manager6/qemu/MachineEdit.js
> index 1b1989e8..89d13886 100644
> --- a/www/manager6/qemu/MachineEdit.js
> +++ b/www/manager6/qemu/MachineEdit.js
> @@ -23,8 +23,16 @@ Ext.define('PVE.qemu.MachineInputPanel', {
> let me = this;
> let version = me.lookup('version');
> let store = version.getStore();
> +
> let oldRec = store.findRecord('id', version.getValue(), 0, false, false, true);
> - let type = value === 'q35' ? 'q35' : 'i440fx';
> +
> + let vm = me.getViewModel();
> + let arch = PVE.Utils.getArchitecture(vm.get('arch'), vm.get('nodename'));
> + let defaultMachine = PVE.Utils.defaultMachines[arch];
> + if (defaultMachine === 'pc') {
> + defaultMachine = 'i440fx'; // the default in the backend is 'pc' which means 'i440fx' for the qemu machinetype'
Style nit: please move the comment to its own line. Comment has a
trailing excessive single quote
> + }
> + let type = value === 'q35' ? 'q35' : defaultMachine;
> store.clearFilter();
> store.addFilter((val) => val.data.id === 'latest' || val.data.type === type);
> if (!me.getView().isWindows) {
> @@ -45,9 +53,12 @@ Ext.define('PVE.qemu.MachineInputPanel', {
> },
>
> onGetValues: function (values) {
> + let me = this;
> + let arch = PVE.Utils.getArchitecture(values.arch, me.nodename);
> + delete values.arch;
> if (values.delete === 'machine' && values.viommu) {
> delete values.delete;
> - values.machine = 'pc';
> + values.machine = PVE.Utils.defaultMachines[arch];
> }
> if (values.version && values.version !== 'latest') {
> values.machine = values.version;
> @@ -68,8 +79,10 @@ Ext.define('PVE.qemu.MachineInputPanel', {
> let machineConf = PVE.Parser.parsePropertyString(values.machine, 'type');
> values.machine = machineConf.type;
>
> + let arch = PVE.Utils.getArchitecture(values.arch, me.nodename);
> + let defaultMachine = PVE.Utils.defaultMachines[arch];
> me.isWindows = values.isWindows;
> - if (values.machine === 'pc') {
> + if (values.machine === defaultMachine) {
> values.machine = '__default__';
> }
>
Similar to above, unrelated but the pinning does not match the backend,
but will also need to be adapted once the default for virt is fixed in
the backend.
if (me.isWindows) {
if (values.machine === '__default__') {
values.version = 'pc-i440fx-5.1';
} else if (values.machine === 'q35') {
values.version = 'pc-q35-5.1';
}
}
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [pve-devel] [PATCH manager 07/10] ui: qemu: make machine panels/fields architecture aware
2026-01-29 11:12 ` Fiona Ebner
@ 2026-01-29 12:16 ` Dominik Csapak
2026-01-29 12:25 ` Fiona Ebner
0 siblings, 1 reply; 25+ messages in thread
From: Dominik Csapak @ 2026-01-29 12:16 UTC (permalink / raw)
To: Fiona Ebner, Proxmox VE development discussion
On 1/29/26 12:11 PM, Fiona Ebner wrote:
> Am 28.01.26 um 1:30 PM schrieb Dominik Csapak:
>> For this, introduce a new 'QemuMachineSelector', which does the same
>> thing as the scsihw selector by filtering the kv store with a predefined
>> list for each architecture.
>>
>> Since the backend default of the machine is actually different for
>> x86_64 vs aarch64, there is some logic to handle the 'default' value
>> for the machine (iow. replace 'pc' with the default machine for each
>> architecture)
>>
>
> Setting a machine version for an existing aarch64 VM is broken, e.g. the
> result will be "pc-i440fx-10.1" instead.
yep noticed it too now, the reason is that the arch and nodename are not
set via 'binds' yet when the 'onMachineChange' is triggering
(at least not everytime, maybe a race condition? i swear it
worked at least once on my machine ;) )
I'll have to change how we get/save the arch/nodename there.
When that works, it'll not show any versions currently because
the backend does not return any 'virt' models.
i think we should fix that in the backend. I'd also add an 'arch'
parameter for the machines like you sent for the cputype
>
>> Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
>> ---
>> www/manager6/Makefile | 1 +
>> www/manager6/Utils.js | 18 ++++++-
>> www/manager6/form/QemuMachineSelector.js | 64 ++++++++++++++++++++++++
>> www/manager6/qemu/HardwareView.js | 3 +-
>> www/manager6/qemu/MachineEdit.js | 63 +++++++++++++++++------
>> www/manager6/qemu/SystemEdit.js | 10 ++--
>> 6 files changed, 136 insertions(+), 23 deletions(-)
>> create mode 100644 www/manager6/form/QemuMachineSelector.js
>>
>> diff --git a/www/manager6/Makefile b/www/manager6/Makefile
>> index 4558d53e..7670b95d 100644
>> --- a/www/manager6/Makefile
>> +++ b/www/manager6/Makefile
>> @@ -62,6 +62,7 @@ JSSRC= \
>> form/PreallocationSelector.js \
>> form/PrivilegesSelector.js \
>> form/QemuBiosSelector.js \
>> + form/QemuMachineSelector.js \
>> form/SDNControllerSelector.js \
>> form/SDNZoneSelector.js \
>> form/SDNVnetSelector.js \
>> diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
>> index de1ee0ba..613a7113 100644
>> --- a/www/manager6/Utils.js
>> +++ b/www/manager6/Utils.js
>> @@ -509,8 +509,22 @@ Ext.define('PVE.Utils', {
>> return agentstring;
>> },
>>
>> - render_qemu_machine: function (value) {
>> - return value || Proxmox.Utils.defaultText + ' (i440fx)';
>> + defaultMachines: {
>> + x86_64: 'pc',
>> + aarch64: 'virt',
>> + },
>> +
>> + machineText: {
>> + pc: 'i440fx',
>> + },
>
> These new entries should mention QEMU somewhere in their name, because
> it's in the very general/stuffed Utils class.
make sense
>
>> +
>> + render_qemu_machine: function (value, arch = 'x86_64') {
>> + if (!value) {
>> + let machine = PVE.Utils.defaultMachines[arch];
>> + let machineText = PVE.Utils.machineText[machine] ?? machine;
>> + return `${Proxmox.Utils.defaultText} (${machineText})`;
>> + }
>> + return value;
>> },
>>
>> render_qemu_bios: function (value) {
>> diff --git a/www/manager6/form/QemuMachineSelector.js b/www/manager6/form/QemuMachineSelector.js
>> new file mode 100644
>> index 00000000..2852b585
>> --- /dev/null
>> +++ b/www/manager6/form/QemuMachineSelector.js
>> @@ -0,0 +1,64 @@
>> +Ext.define('PVE.form.QemuMachineSelector', {
>> + extend: 'Proxmox.form.KVComboBox',
>> + alias: 'widget.pveQemuMachineSelector',
>> +
>> + comboItems: [
>> + ['__default__', PVE.Utils.render_qemu_machine('')],
>> + ['q35', 'q35'],
>> + ],
>> +
>> + machinesPerArchitecture: {
>> + x86_64: ['__default__', 'q35'], // __default__ is i440fx
>> + aarch64: ['__default__'], // __default__ is virt
>> + },
>> +
>> + // defaults to hostArch
>> + arch: undefined,
>> +
>> + // depends on the node
>> + hostArch: 'x86_64',
>
> Sounds like it should start as undefined and we should require a
> nodename to be present at init time then and set hostArch accordingly?
> Otherwise, it seems a bit brittle and might be wrong if setNodename() is
> forgotten to be called by a use site.
as i wrote in the other mail, i think i'll change this completely
namely don't let each component calculate this seperately
>
>> +
>> + nodename: undefined,
>> +
>> + setNodename: function (nodename) {
>> + let me = this;
>> + let node = PVE.data.ResourceStore.getNodeById(nodename);
>> + if (node) {
>> + me.hostArch = node.data.architecture;
>> + me.setArch(me.arch); // recalculate the filter
>> + }
>> + },
>> +
>> + setArch: function (arch) {
>> + let me = this;
>> + if (arch === '__default__') {
>> + arch = undefined;
>> + }
>> + me.arch = arch;
>> + arch ??= me.hostArch;
>> + let wasValid = me.isValid();
>> + me.store.clearFilter();
>> + let allowedMachines = me.machinesPerArchitecture[arch];
>> + me.store.addFilter((rec) => allowedMachines.indexOf(rec.data.key) !== -1);
>> + // update default value with new arch
>> + let record = me.store.findRecord('key', '__default__');
>> + if (record) {
>> + record.set('value', PVE.Utils.render_qemu_machine('', arch));
>> + record.commit();
>> + }
>> + let isValid = me.isValid();
>> +
>> + // for some reason, adding/changing filters does not trigger this, even though
>> + // it show the field as invalid, so simply track and fire the event manually.
>> + if (wasValid !== isValid) {
>> + me.fireEvent('validitychange', isValid);
>> + }
>> + },
>> +
>> + initComponent: function () {
>> + var me = this;
>> +
>> + me.callParent();
>> + me.setArch(me.arch);
>> + },
>> +});
>> diff --git a/www/manager6/qemu/HardwareView.js b/www/manager6/qemu/HardwareView.js
>> index b7cc7856..1e2cd026 100644
>> --- a/www/manager6/qemu/HardwareView.js
>> +++ b/www/manager6/qemu/HardwareView.js
>> @@ -202,13 +202,14 @@ Ext.define('PVE.qemu.HardwareView', {
>> defaultValue: '',
>> renderer: function (value, metaData, record, rowIndex, colIndex, store, pending) {
>> let ostype = me.getObjectValue('ostype', undefined, pending);
>> + let arch = PVE.Utils.getArchitecture(me.getObjectValue('arch'), nodename);
>> if (
>> PVE.Utils.is_windows(ostype) &&
>> (!value || value === 'pc' || value === 'q35')
>> ) {
>> return value === 'q35' ? 'pc-q35-5.1' : 'pc-i440fx-5.1';
>
> Unrelated to the patch, but I noticed now that this is actually wrong.
> Since QEMU 9.1+ the backend defaults to the creation version if present.
i think this was just done as a heuristic without trying to replicate
the backend logic too tightly, but i might be misremembering
>
> But related to the series, it should default to virt for ARM of course,
> which it doesn't yet, but I sent a patch:
> https://lore.proxmox.com/pve-devel/20260129110607.65416-1-f.ebner@proxmox.com/T/
i'll check it out
>
>> }
>> - return PVE.Utils.render_qemu_machine(value);
>> + return PVE.Utils.render_qemu_machine(value, arch);
>> },
>> },
>> scsihw: {
>> diff --git a/www/manager6/qemu/MachineEdit.js b/www/manager6/qemu/MachineEdit.js
>> index 1b1989e8..89d13886 100644
>> --- a/www/manager6/qemu/MachineEdit.js
>> +++ b/www/manager6/qemu/MachineEdit.js
>> @@ -23,8 +23,16 @@ Ext.define('PVE.qemu.MachineInputPanel', {
>> let me = this;
>> let version = me.lookup('version');
>> let store = version.getStore();
>> +
>> let oldRec = store.findRecord('id', version.getValue(), 0, false, false, true);
>> - let type = value === 'q35' ? 'q35' : 'i440fx';
>> +
>> + let vm = me.getViewModel();
>> + let arch = PVE.Utils.getArchitecture(vm.get('arch'), vm.get('nodename'));
>> + let defaultMachine = PVE.Utils.defaultMachines[arch];
>> + if (defaultMachine === 'pc') {
>> + defaultMachine = 'i440fx'; // the default in the backend is 'pc' which means 'i440fx' for the qemu machinetype'
>
> Style nit: please move the comment to its own line. Comment has a
> trailing excessive single quote
>
>> + }
>> + let type = value === 'q35' ? 'q35' : defaultMachine;
>> store.clearFilter();
>> store.addFilter((val) => val.data.id === 'latest' || val.data.type === type);
>> if (!me.getView().isWindows) {
>> @@ -45,9 +53,12 @@ Ext.define('PVE.qemu.MachineInputPanel', {
>> },
>>
>> onGetValues: function (values) {
>> + let me = this;
>> + let arch = PVE.Utils.getArchitecture(values.arch, me.nodename);
>> + delete values.arch;
>> if (values.delete === 'machine' && values.viommu) {
>> delete values.delete;
>> - values.machine = 'pc';
>> + values.machine = PVE.Utils.defaultMachines[arch];
>> }
>> if (values.version && values.version !== 'latest') {
>> values.machine = values.version;
>> @@ -68,8 +79,10 @@ Ext.define('PVE.qemu.MachineInputPanel', {
>> let machineConf = PVE.Parser.parsePropertyString(values.machine, 'type');
>> values.machine = machineConf.type;
>>
>> + let arch = PVE.Utils.getArchitecture(values.arch, me.nodename);
>> + let defaultMachine = PVE.Utils.defaultMachines[arch];
>> me.isWindows = values.isWindows;
>> - if (values.machine === 'pc') {
>> + if (values.machine === defaultMachine) {
>> values.machine = '__default__';
>> }
>>
>
> Similar to above, unrelated but the pinning does not match the backend,
> but will also need to be adapted once the default for virt is fixed in
> the backend.
>
> if (me.isWindows) {
> if (values.machine === '__default__') {
> values.version = 'pc-i440fx-5.1';
> } else if (values.machine === 'q35') {
> values.version = 'pc-q35-5.1';
> }
> }
>
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [pve-devel] [PATCH manager 07/10] ui: qemu: make machine panels/fields architecture aware
2026-01-29 12:16 ` Dominik Csapak
@ 2026-01-29 12:25 ` Fiona Ebner
0 siblings, 0 replies; 25+ messages in thread
From: Fiona Ebner @ 2026-01-29 12:25 UTC (permalink / raw)
To: Dominik Csapak, Proxmox VE development discussion
Am 29.01.26 um 1:15 PM schrieb Dominik Csapak:
> On 1/29/26 12:11 PM, Fiona Ebner wrote:
>> Am 28.01.26 um 1:30 PM schrieb Dominik Csapak:
>>> For this, introduce a new 'QemuMachineSelector', which does the same
>>> thing as the scsihw selector by filtering the kv store with a predefined
>>> list for each architecture.
>>>
>>> Since the backend default of the machine is actually different for
>>> x86_64 vs aarch64, there is some logic to handle the 'default' value
>>> for the machine (iow. replace 'pc' with the default machine for each
>>> architecture)
>>>
>>
>> Setting a machine version for an existing aarch64 VM is broken, e.g. the
>> result will be "pc-i440fx-10.1" instead.
>
> yep noticed it too now, the reason is that the arch and nodename are not
> set via 'binds' yet when the 'onMachineChange' is triggering
> (at least not everytime, maybe a race condition? i swear it
> worked at least once on my machine ;) )
>
> I'll have to change how we get/save the arch/nodename there.
> When that works, it'll not show any versions currently because
> the backend does not return any 'virt' models.
>
> i think we should fix that in the backend. I'd also add an 'arch'
> parameter for the machines like you sent for the cputype
Ah, I'll look into adding that!
>>> diff --git a/www/manager6/qemu/HardwareView.js b/www/manager6/qemu/
>>> HardwareView.js
>>> index b7cc7856..1e2cd026 100644
>>> --- a/www/manager6/qemu/HardwareView.js
>>> +++ b/www/manager6/qemu/HardwareView.js
>>> @@ -202,13 +202,14 @@ Ext.define('PVE.qemu.HardwareView', {
>>> defaultValue: '',
>>> renderer: function (value, metaData, record,
>>> rowIndex, colIndex, store, pending) {
>>> let ostype = me.getObjectValue('ostype',
>>> undefined, pending);
>>> + let arch =
>>> PVE.Utils.getArchitecture(me.getObjectValue('arch'), nodename);
>>> if (
>>> PVE.Utils.is_windows(ostype) &&
>>> (!value || value === 'pc' || value === 'q35')
>>> ) {
>>> return value === 'q35' ? 'pc-q35-5.1' :
>>> 'pc-i440fx-5.1';
>>
>> Unrelated to the patch, but I noticed now that this is actually wrong.
>> Since QEMU 9.1+ the backend defaults to the creation version if present.
>
> i think this was just done as a heuristic without trying to replicate
> the backend logic too tightly, but i might be misremembering
I think I just wasn't aware/didn't adapt it to the backend change (that
came much later).
^ permalink raw reply [flat|nested] 25+ messages in thread
* [pve-devel] [PATCH manager 08/10] ui: qemu: make bios selector architecture aware
2026-01-28 12:18 [pve-devel] [PATCH manager 00/10] enable qemu vm architecture selection Dominik Csapak
` (6 preceding siblings ...)
2026-01-28 12:18 ` [pve-devel] [PATCH manager 07/10] ui: qemu: make machine panels/fields " Dominik Csapak
@ 2026-01-28 12:18 ` Dominik Csapak
2026-01-28 12:18 ` [pve-devel] [PATCH manager 09/10] ui: qemu: make sortByPreviousUsage " Dominik Csapak
` (2 subsequent siblings)
10 siblings, 0 replies; 25+ messages in thread
From: Dominik Csapak @ 2026-01-28 12:18 UTC (permalink / raw)
To: pve-devel
since not all firmware variants are available/supported on every
architecture, limit the selector to variants that make sense (e.g. to
'ovmf' on aarch64).
Same mechanism like the scsi hw selector.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/manager6/form/QemuBiosSelector.js | 61 ++++++++++++++++++++++++---
www/manager6/qemu/QemuBiosEdit.js | 35 ++++++++++++++-
www/manager6/qemu/SystemEdit.js | 5 +++
3 files changed, 93 insertions(+), 8 deletions(-)
diff --git a/www/manager6/form/QemuBiosSelector.js b/www/manager6/form/QemuBiosSelector.js
index 5fa443f1..2b8231dc 100644
--- a/www/manager6/form/QemuBiosSelector.js
+++ b/www/manager6/form/QemuBiosSelector.js
@@ -2,15 +2,64 @@ Ext.define('PVE.form.QemuBiosSelector', {
extend: 'Proxmox.form.KVComboBox',
alias: ['widget.pveQemuBiosSelector'],
+ comboItems: [
+ ['__default__', PVE.Utils.render_qemu_bios('')],
+ ['seabios', PVE.Utils.render_qemu_bios('seabios')],
+ ['ovmf', PVE.Utils.render_qemu_bios('ovmf')],
+ ],
+
+ firmwarePerArchitecture: {
+ x86_64: ['__default__', 'seabios', 'ovmf'], // default is seabios
+ aarch64: ['ovmf'],
+ },
+
+ // defaults to hostArch
+ arch: undefined,
+
+ // depends on the node
+ hostArch: 'x86_64',
+
+ nodename: undefined,
+
+ setNodename: function (nodename) {
+ let me = this;
+ let node = PVE.data.ResourceStore.getNodeById(nodename);
+ if (node) {
+ me.hostArch = node.data.architecture;
+ me.setArch(me.arch); // recalculate the filter
+ }
+ },
+
+ setArch: function (arch) {
+ let me = this;
+ if (arch === '__default__') {
+ arch = undefined;
+ }
+ me.arch = arch;
+ arch ??= me.hostArch;
+ let wasValid = me.isValid();
+ me.store.clearFilter();
+ let allowedFirmware = me.firmwarePerArchitecture[arch];
+ me.store.addFilter((rec) => allowedFirmware.indexOf(rec.data.key) !== -1);
+ let isValid = me.isValid();
+ // update default value with new arch
+ let record = me.store.findRecord('key', '__default__');
+ if (record) {
+ record.set('value', PVE.Utils.render_qemu_bios('', arch));
+ record.commit();
+ }
+
+ // for some reason, adding/changing filters does not trigger this, even though
+ // it show the field as invalid, so simply track and fire the event manually.
+ if (wasValid !== isValid) {
+ me.fireEvent('validitychange', isValid);
+ }
+ },
+
initComponent: function () {
var me = this;
- me.comboItems = [
- ['__default__', PVE.Utils.render_qemu_bios('')],
- ['seabios', PVE.Utils.render_qemu_bios('seabios')],
- ['ovmf', PVE.Utils.render_qemu_bios('ovmf')],
- ];
-
me.callParent();
+ me.setArch(me.arch);
},
});
diff --git a/www/manager6/qemu/QemuBiosEdit.js b/www/manager6/qemu/QemuBiosEdit.js
index ef8f1844..9fd98ab8 100644
--- a/www/manager6/qemu/QemuBiosEdit.js
+++ b/www/manager6/qemu/QemuBiosEdit.js
@@ -4,7 +4,6 @@ Ext.define('PVE.qemu.BiosEdit', {
onlineHelp: 'qm_bios_and_uefi',
subject: 'BIOS',
- autoLoad: true,
viewModel: {
data: {
@@ -22,7 +21,10 @@ Ext.define('PVE.qemu.BiosEdit', {
onlineHelp: 'qm_bios_and_uefi',
name: 'bios',
value: '__default__',
- bind: '{bios}',
+ bind: {
+ value: '{bios}',
+ arch: '{arch}',
+ },
fieldLabel: 'BIOS',
},
{
@@ -31,6 +33,13 @@ Ext.define('PVE.qemu.BiosEdit', {
bind: '{efidisk0}',
hidden: true,
},
+ {
+ xtype: 'hiddenfield',
+ name: 'arch',
+ hidden: true,
+ bind: '{arch}',
+ submitValue: false,
+ },
{
xtype: 'displayfield',
userCls: 'pmx-hint',
@@ -42,4 +51,26 @@ Ext.define('PVE.qemu.BiosEdit', {
},
},
],
+
+ initComponent: function () {
+ let me = this;
+
+ me.nodename = me.pveSelNode?.data.node;
+
+ if (!me.nodename) {
+ throw 'no nodename given';
+ }
+
+ me.callParent();
+
+ if (!me.isCreate) {
+ me.load({
+ success: function ({ result }) {
+ let values = result.data;
+ values.arch = PVE.Utils.getArchitecture(values.arch, me.nodename);
+ me.setValues(values);
+ },
+ });
+ }
+ },
});
diff --git a/www/manager6/qemu/SystemEdit.js b/www/manager6/qemu/SystemEdit.js
index 71fd1125..4b72b274 100644
--- a/www/manager6/qemu/SystemEdit.js
+++ b/www/manager6/qemu/SystemEdit.js
@@ -103,6 +103,11 @@ Ext.define('PVE.qemu.SystemInputPanel', {
reference: 'bios',
value: '__default__',
fieldLabel: 'BIOS',
+ bind: {
+ arch: '{current.architecture}',
+ nodename: '{nodename}',
+ value: '{selectedBios}',
+ },
},
{
xtype: 'proxmoxcheckbox',
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 25+ messages in thread* [pve-devel] [PATCH manager 09/10] ui: qemu: make sortByPreviousUsage architecture aware
2026-01-28 12:18 [pve-devel] [PATCH manager 00/10] enable qemu vm architecture selection Dominik Csapak
` (7 preceding siblings ...)
2026-01-28 12:18 ` [pve-devel] [PATCH manager 08/10] ui: qemu: make bios selector " Dominik Csapak
@ 2026-01-28 12:18 ` Dominik Csapak
2026-01-28 12:18 ` [pve-devel] [PATCH manager 10/10] ui: qemu: wizard: use defaults to populate machine and bios Dominik Csapak
2026-01-29 13:13 ` [pve-devel] [PATCH manager 00/10] enable qemu vm architecture selection Fiona Ebner
10 siblings, 0 replies; 25+ messages in thread
From: Dominik Csapak @ 2026-01-28 12:18 UTC (permalink / raw)
To: pve-devel
Different architectures may have different controller priorities,
so this has to use the architecture specific defaults.
For this, we have to pass through the nodename sometimes (to get the
host architecture).
The other notable change is that in the multi hd edit panel, we now only
add the first disk in the 'afterrender' event. This is done so that we
guaranteed have a nodename, which is not the case when called in 'init'.
(The 'bind' mechanism we use in the wizard changes that only after the
'init' functions are called.)
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/manager6/Utils.js | 9 ++++-----
www/manager6/form/ControllerSelector.js | 9 ++++++++-
www/manager6/panel/MultiDiskEdit.js | 14 ++++++++------
www/manager6/qemu/CIDriveEdit.js | 2 ++
www/manager6/qemu/MultiHDEdit.js | 3 ++-
www/manager6/qemu/NetworkEdit.js | 3 ++-
www/manager6/window/GuestDiskReassign.js | 1 +
7 files changed, 27 insertions(+), 14 deletions(-)
diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index 613a7113..975a0aec 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -1951,10 +1951,8 @@ Ext.define('PVE.Utils', {
return true;
},
- sortByPreviousUsage: function (vmconfig, controllerList) {
- if (!controllerList) {
- controllerList = ['ide', 'virtio', 'scsi', 'sata'];
- }
+ sortByPreviousUsage: function (vmconfig, nodename) {
+ let controllerList = ['ide', 'virtio', 'scsi', 'sata'];
let usedControllers = {};
for (const type of Object.keys(PVE.Utils.diskControllerMaxIDs)) {
usedControllers[type] = 0;
@@ -1970,7 +1968,8 @@ Ext.define('PVE.Utils', {
}
}
- let sortPriority = PVE.qemu.OSDefaults.getDefaults(vmconfig.ostype).busPriority;
+ let arch = PVE.Utils.getArchitecture(vmconfig.arch, nodename);
+ let sortPriority = PVE.qemu.OSDefaults.getDefaults(vmconfig.ostype, arch).busPriority;
let sortedList = Ext.clone(controllerList);
sortedList.sort(function (a, b) {
diff --git a/www/manager6/form/ControllerSelector.js b/www/manager6/form/ControllerSelector.js
index bcc8334d..fee2b398 100644
--- a/www/manager6/form/ControllerSelector.js
+++ b/www/manager6/form/ControllerSelector.js
@@ -7,6 +7,13 @@ Ext.define('PVE.form.ControllerSelector', {
vmconfig: {}, // used to check for existing devices
+ nodename: undefined,
+
+ setNodename: function (nodename) {
+ let me = this;
+ me.nodename = nodename;
+ },
+
setToFree: function (controllers, busField, deviceIDField) {
let me = this;
let freeId = PVE.Utils.nextFreeDisk(controllers, me.vmconfig);
@@ -42,7 +49,7 @@ Ext.define('PVE.form.ControllerSelector', {
clist = ['ide', 'scsi', 'sata'];
} else {
// in most cases we want to add a disk to the same controller we previously used
- clist = PVE.Utils.sortByPreviousUsage(me.vmconfig);
+ clist = PVE.Utils.sortByPreviousUsage(me.vmconfig, me.nodename);
}
me.setToFree(clist, bussel, deviceid);
diff --git a/www/manager6/panel/MultiDiskEdit.js b/www/manager6/panel/MultiDiskEdit.js
index 32fad5dc..e96a5f96 100644
--- a/www/manager6/panel/MultiDiskEdit.js
+++ b/www/manager6/panel/MultiDiskEdit.js
@@ -5,6 +5,7 @@ Ext.define('PVE.panel.MultiDiskPanel', {
setNodename: function (nodename) {
this.items.each((panel) => panel.setNodename(nodename));
+ this.nodename = nodename;
},
border: false,
@@ -210,12 +211,13 @@ Ext.define('PVE.panel.MultiDiskPanel', {
'grid[reference=grid]': {
selectionchange: 'onSelectionChange',
},
- },
-
- init: function (view) {
- let me = this;
- me.onAdd();
- me.lookup('grid').getSelectionModel().select(0, false);
+ '#': {
+ afterrender: function (view) {
+ let me = this;
+ me.onAdd();
+ me.lookup('grid').getSelectionModel().select(0, false);
+ },
+ },
},
},
diff --git a/www/manager6/qemu/CIDriveEdit.js b/www/manager6/qemu/CIDriveEdit.js
index 14e6d368..aefbbfab 100644
--- a/www/manager6/qemu/CIDriveEdit.js
+++ b/www/manager6/qemu/CIDriveEdit.js
@@ -20,6 +20,7 @@ Ext.define('PVE.qemu.CIDriveInputPanel', {
setNodename: function (nodename) {
var me = this;
me.down('#hdstorage').setNodename(nodename);
+ me.down('#drive').setNodename(nodename);
me.down('#hdimage').setStorage(undefined, nodename);
},
@@ -39,6 +40,7 @@ Ext.define('PVE.qemu.CIDriveInputPanel', {
withVirtIO: false,
itemId: 'drive',
fieldLabel: gettext('CloudInit Drive'),
+ nodename: me.nodename,
name: 'drive',
},
{
diff --git a/www/manager6/qemu/MultiHDEdit.js b/www/manager6/qemu/MultiHDEdit.js
index 0b048709..220167de 100644
--- a/www/manager6/qemu/MultiHDEdit.js
+++ b/www/manager6/qemu/MultiHDEdit.js
@@ -17,7 +17,8 @@ Ext.define('PVE.qemu.MultiHDPanel', {
) - 1,
getNextFreeDisk: function (vmconfig) {
- let clist = PVE.Utils.sortByPreviousUsage(vmconfig);
+ let nodename = this.getView().nodename;
+ let clist = PVE.Utils.sortByPreviousUsage(vmconfig, nodename);
return PVE.Utils.nextFreeDisk(clist, vmconfig);
},
diff --git a/www/manager6/qemu/NetworkEdit.js b/www/manager6/qemu/NetworkEdit.js
index 2ba13c40..7655864c 100644
--- a/www/manager6/qemu/NetworkEdit.js
+++ b/www/manager6/qemu/NetworkEdit.js
@@ -264,7 +264,8 @@ Ext.define('PVE.qemu.NetworkEdit', {
}
let ostype = me.vmconfig.ostype;
- let defaults = PVE.qemu.OSDefaults.getDefaults(ostype);
+ let arch = PVE.Utils.getArchitecture(me.vmconfig.arch, me.nodename);
+ let defaults = PVE.qemu.OSDefaults.getDefaults(ostype, arch);
let data = {
model: defaults.networkCard,
};
diff --git a/www/manager6/window/GuestDiskReassign.js b/www/manager6/window/GuestDiskReassign.js
index 596808f8..af149010 100644
--- a/www/manager6/window/GuestDiskReassign.js
+++ b/www/manager6/window/GuestDiskReassign.js
@@ -171,6 +171,7 @@ Ext.define('PVE.window.GuestDiskReassign', {
disabled: true,
cbind: {
hidden: '{!isQemu}',
+ nodename: '{nodename}',
},
},
{
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 25+ messages in thread* [pve-devel] [PATCH manager 10/10] ui: qemu: wizard: use defaults to populate machine and bios
2026-01-28 12:18 [pve-devel] [PATCH manager 00/10] enable qemu vm architecture selection Dominik Csapak
` (8 preceding siblings ...)
2026-01-28 12:18 ` [pve-devel] [PATCH manager 09/10] ui: qemu: make sortByPreviousUsage " Dominik Csapak
@ 2026-01-28 12:18 ` Dominik Csapak
2026-01-29 13:13 ` [pve-devel] [PATCH manager 00/10] enable qemu vm architecture selection Fiona Ebner
10 siblings, 0 replies; 25+ messages in thread
From: Dominik Csapak @ 2026-01-28 12:18 UTC (permalink / raw)
To: pve-devel
instead of hardcoding some values here for win11, use the OSDefaults
mechanism to load it for all. This makes it also architecture aware.
rename the function to 'setDefaults' as it's a more fitting name now.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/manager6/qemu/OSDefaults.js | 7 +++++++
www/manager6/qemu/SystemEdit.js | 16 ++++++++++++----
2 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/www/manager6/qemu/OSDefaults.js b/www/manager6/qemu/OSDefaults.js
index 3a707d60..b679f58d 100644
--- a/www/manager6/qemu/OSDefaults.js
+++ b/www/manager6/qemu/OSDefaults.js
@@ -109,6 +109,13 @@ Ext.define('PVE.qemu.OSDefaults', {
parent: 'w2k',
});
+ addOS({
+ pveOS: 'win11',
+ parent: 'generic',
+ machine: 'q35',
+ bios: 'ovmf',
+ });
+
me.getDefaults = function (ostype, arch = 'x86_64') {
if (!PVE.qemu.OSDefaults[ostype]) {
ostype = 'generic';
diff --git a/www/manager6/qemu/SystemEdit.js b/www/manager6/qemu/SystemEdit.js
index 4b72b274..7422d3e7 100644
--- a/www/manager6/qemu/SystemEdit.js
+++ b/www/manager6/qemu/SystemEdit.js
@@ -57,19 +57,27 @@ Ext.define('PVE.qemu.SystemInputPanel', {
change: 'biosChange',
},
'#': {
- afterrender: 'setMachine',
+ afterrender: 'setDefaults',
},
},
- setMachine: function () {
+ setDefaults: function () {
let me = this;
let vm = this.getViewModel();
+
let ostype = vm.get('current.ostype');
+ let architecture = PVE.Utils.getArchitecture(
+ vm.get('current.architecture'),
+ vm.get('nodename'),
+ );
+
+ let defaults = PVE.qemu.OSDefaults.getDefaults(ostype, architecture);
if (ostype === 'win11') {
- me.lookup('machine').setValue('q35');
- me.lookup('bios').setValue('ovmf');
me.lookup('addtpmbox').setValue(true);
}
+
+ me.lookup('machine').setValue(defaults.machine ?? '__default__');
+ me.lookup('bios').setValue(defaults.bios ?? '__default__');
},
},
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [pve-devel] [PATCH manager 00/10] enable qemu vm architecture selection
2026-01-28 12:18 [pve-devel] [PATCH manager 00/10] enable qemu vm architecture selection Dominik Csapak
` (9 preceding siblings ...)
2026-01-28 12:18 ` [pve-devel] [PATCH manager 10/10] ui: qemu: wizard: use defaults to populate machine and bios Dominik Csapak
@ 2026-01-29 13:13 ` Fiona Ebner
2026-01-29 13:15 ` Fiona Ebner
10 siblings, 1 reply; 25+ messages in thread
From: Fiona Ebner @ 2026-01-29 13:13 UTC (permalink / raw)
To: Proxmox VE development discussion, Dominik Csapak
Am 28.01.26 um 1:29 PM schrieb Dominik Csapak:
> This series brings the emulated aarch64 vms to the gui. This could
> be configured on the api only previously.
>
> The code also handles if the host has a non-x86 architecture, and is
> generally structured in a way that should make it (relatively) easy
> to add other architectures in the future.
>
> Some fields/panels needed adaptions to hide some values or change some
> defaults, since not every combination that can be configured makes
> sense. (e.g. seabios on aarch64 cannot work currently)
>
> Generally the backend allows many combinations that don't make sense on
> all architectures, so i tried to limit the users here to the 'correct'
> ones, but we should think about limiting them in the backend too.
>
> Also, the backend made some inconsistent choices with different
> architectures, such as the default controller changes with the
> architecture, but things like 'bios' or 'scsihw' do not. So I worked
> around these things a bit differently.
>
> What is still missing:
> * make the disk controllers selective per architecture
> (e.g. aarch64 has no ide controller, ovmf+aarch64 cannot boot from sata)
Related, but maybe independent patch-wise:
* do not add the ISO(s) from the wizard as IDE.
> * cpumodel + cpuflags need to be architecture aware
For reference:
https://lore.proxmox.com/pve-devel/20260129131021.118199-1-f.ebner@proxmox.com/
(v2 because I had forgotten to adapt the endpoint for flags)
>
> other nice to haves not yet done, that also invovle changing the backend:
> * 'virt' machine support in our api, so one can choose older versions
AFAICT, this is already supported by the API?
> * allow 'pcie' passthrough on 'virt'
Nice work so far! :)
^ permalink raw reply [flat|nested] 25+ messages in thread