* [PATCH manager v2 01/17] api/pvestatd: broadcast and expose non-x86 host architecture
2026-02-03 10:00 [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
@ 2026-02-03 10:00 ` Dominik Csapak
2026-02-03 13:56 ` Thomas Lamprecht
2026-02-03 15:07 ` Thomas Lamprecht
2026-02-03 10:00 ` [PATCH manager v2 02/17] ui: qemu: wizard: refactor ostype and cd selector into an OSPanel Dominik Csapak
` (17 subsequent siblings)
18 siblings, 2 replies; 22+ messages in thread
From: Dominik Csapak @ 2026-02-03 10:00 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/Service/pvestatd.pm | 10 ++++++++++
2 files changed, 19 insertions(+)
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/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
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH manager v2 01/17] api/pvestatd: broadcast and expose non-x86 host architecture
2026-02-03 10:00 ` [PATCH manager v2 01/17] api/pvestatd: broadcast and expose non-x86 host architecture Dominik Csapak
@ 2026-02-03 13:56 ` Thomas Lamprecht
2026-02-03 15:07 ` Thomas Lamprecht
1 sibling, 0 replies; 22+ messages in thread
From: Thomas Lamprecht @ 2026-02-03 13:56 UTC (permalink / raw)
To: Dominik Csapak, pve-devel
Am 03.02.26 um 11:20 schrieb Dominik Csapak:
> +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();
You can just use the PVE::Tools::get_host_arch here, does the same under
the hood but it's also cached. Could be fixed up if nothing else comes up.
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH manager v2 01/17] api/pvestatd: broadcast and expose non-x86 host architecture
2026-02-03 10:00 ` [PATCH manager v2 01/17] api/pvestatd: broadcast and expose non-x86 host architecture Dominik Csapak
2026-02-03 13:56 ` Thomas Lamprecht
@ 2026-02-03 15:07 ` Thomas Lamprecht
1 sibling, 0 replies; 22+ messages in thread
From: Thomas Lamprecht @ 2026-02-03 15:07 UTC (permalink / raw)
To: Dominik Csapak, pve-devel
Am 03.02.26 um 11:20 schrieb Dominik Csapak:
> 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();
Besides reusing the helper from PVE::Tools I'd also prefer naming the variable
then `$host_arch`, as arch is a pretty standard abbreviation already and denoting
that this holds the host architecture itself is slightly nicer for a system where
there are also guest archs.
> +
> 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;
that isn't only saved for non-x86 though? If any other of the OR'd sub-expression
of the if here evaluates true, which will always happen sooner or later, we will
always set this. I.e., parts of the check above can move down here to make this
something like:
$info->{'host-arch'} = $host_arch if defined($host_arch) && $host_arch ne 'x86_64';
> +
> $info->{'cgroup-mode'} = $cgroup_mode if defined($cgroup_mode);
> PVE::Cluster::broadcast_node_kv('static-info', encode_json($info));
> }
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH manager v2 02/17] ui: qemu: wizard: refactor ostype and cd selector into an OSPanel
2026-02-03 10:00 [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
2026-02-03 10:00 ` [PATCH manager v2 01/17] api/pvestatd: broadcast and expose non-x86 host architecture Dominik Csapak
@ 2026-02-03 10:00 ` Dominik Csapak
2026-02-03 10:00 ` [PATCH manager v2 03/17] ui: form: add filtered KVComboBox Dominik Csapak
` (16 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Dominik Csapak @ 2026-02-03 10:00 UTC (permalink / raw)
To: pve-devel
which is specific for the wizard (like the SystemPanel). The wizard
specific code is now moved to this panel, and the original selectors are
(mostly) free of wizard specific code.
This makes the set/bind flows easier to follow.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/manager6/Makefile | 1 +
www/manager6/qemu/CreateWizard.js | 24 +----
www/manager6/qemu/OSPanel.js | 148 ++++++++++++++++++++++++++++++
www/manager6/qemu/OSTypeEdit.js | 104 ---------------------
4 files changed, 150 insertions(+), 127 deletions(-)
create mode 100644 www/manager6/qemu/OSPanel.js
diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 4558d53e..944dd873 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -267,6 +267,7 @@ JSSRC= \
qemu/NetworkEdit.js \
qemu/OSDefaults.js \
qemu/OSTypeEdit.js \
+ qemu/OSPanel.js \
qemu/Options.js \
qemu/PCIEdit.js \
qemu/ProcessorEdit.js \
diff --git a/www/manager6/qemu/CreateWizard.js b/www/manager6/qemu/CreateWizard.js
index 341324c8..3928d7ff 100644
--- a/www/manager6/qemu/CreateWizard.js
+++ b/www/manager6/qemu/CreateWizard.js
@@ -183,30 +183,8 @@ Ext.define('PVE.qemu.CreateWizard', {
},
},
{
- xtype: 'container',
- layout: 'hbox',
- defaults: {
- flex: 1,
- padding: '0 10',
- },
+ xtype: 'pveQemuOSPanel',
title: gettext('OS'),
- items: [
- {
- xtype: 'pveQemuCDInputPanel',
- bind: {
- nodename: '{nodename}',
- },
- confid: 'ide2',
- insideWizard: true,
- },
- {
- xtype: 'pveQemuOSTypePanel',
- insideWizard: true,
- bind: {
- nodename: '{nodename}',
- },
- },
- ],
},
{
xtype: 'pveQemuSystemPanel',
diff --git a/www/manager6/qemu/OSPanel.js b/www/manager6/qemu/OSPanel.js
new file mode 100644
index 00000000..dd44c865
--- /dev/null
+++ b/www/manager6/qemu/OSPanel.js
@@ -0,0 +1,148 @@
+/// Used only for the wizard to combine the cd input panel and the ostype panel
+
+Ext.define('PVE.qemu.OSPanel', {
+ extend: 'Ext.panel.Panel',
+ xtype: 'pveQemuOSPanel',
+
+ layout: 'hbox',
+ defaults: {
+ flex: 1,
+ padding: '0 10',
+ },
+
+ controller: {
+ xclass: 'Ext.app.ViewController',
+ control: {
+ 'combobox[name=osbase]': {
+ change: 'onOSBaseChange',
+ },
+ 'combobox[name=ostype]': {
+ afterrender: 'onOSTypeChange',
+ change: 'onOSTypeChange',
+ },
+ 'checkbox[reference=enableSecondCD]': {
+ change: 'onSecondCDChange',
+ },
+ },
+ onOSBaseChange: function (field, value) {
+ let me = this;
+ let isWindows = value === 'Microsoft Windows';
+ let enableSecondCD = me.lookup('enableSecondCD');
+ enableSecondCD.setVisible(isWindows);
+ if (!isWindows) {
+ enableSecondCD.setValue(false);
+ }
+ },
+ onOSTypeChange: function (field) {
+ var me = this,
+ ostype = field.getValue();
+ var targetValues = PVE.qemu.OSDefaults.getDefaults(ostype);
+
+ me.setWidget('pveBusSelector', targetValues.busType);
+ me.setWidget('pveNetworkCardSelector', targetValues.networkCard);
+ me.setWidget('CPUModelSelector', targetValues.cputype);
+ var scsihw = targetValues.scsihw || '__default__';
+ this.getViewModel().set('current.scsihw', scsihw);
+ this.getViewModel().set('current.ostype', ostype);
+ },
+ setWidget: function (widget, newValue) {
+ // changing a widget is safe only if ComponentQuery.query returns us
+ // a single value array
+ var widgets = Ext.ComponentQuery.query('pveQemuCreateWizard ' + widget);
+ if (widgets.length === 1) {
+ widgets[0].setValue(newValue);
+ } else {
+ // ignore multiple disks, we only want to set the type if there is a single disk
+ }
+ },
+ onSecondCDChange: function (widget, value, lastValue) {
+ let me = this;
+ let vm = me.getViewModel();
+ let updateVMConfig = function () {
+ let widgets = Ext.ComponentQuery.query('pveMultiHDPanel');
+ if (widgets.length === 1) {
+ widgets[0].getController().updateVMConfig();
+ }
+ };
+ if (value) {
+ // only for windows
+ vm.set('current.ide0', 'some');
+ vm.notify();
+ updateVMConfig();
+ me.setWidget('pveBusSelector', 'scsi');
+ me.setWidget('pveNetworkCardSelector', 'virtio');
+ } else {
+ vm.set('current.ide0', '');
+ vm.notify();
+ updateVMConfig();
+ me.setWidget('pveBusSelector', 'scsi');
+ let ostype = me.getView().down('[name=ostype]').getValue();
+ let targetValues = PVE.qemu.OSDefaults.getDefaults(ostype);
+ me.setWidget('pveBusSelector', targetValues.busType);
+ }
+ },
+ },
+
+ items: [
+ {
+ xtype: 'pveQemuCDInputPanel',
+ reference: 'cdSelector',
+ bind: {
+ nodename: '{nodename}',
+ },
+ confid: 'ide2',
+ insideWizard: true,
+ },
+ {
+ xtype: 'container',
+ layout: {
+ type: 'vbox',
+ align: 'stretch',
+ },
+ defaults: {
+ flex: 1,
+ },
+ items: [
+ {
+ xtype: 'displayfield',
+ value: gettext('Guest OS') + ':',
+ },
+ {
+ xtype: 'pveQemuOSTypePanel',
+ insideWizard: true,
+ },
+ {
+ xtype: 'inputpanel',
+ items: [
+ {
+ xtype: 'proxmoxcheckbox',
+ reference: 'enableSecondCD',
+ isFormField: false,
+ hidden: true,
+ checked: false,
+ boxLabel: gettext('Add additional drive for VirtIO drivers'),
+ listeners: {
+ change: function (cb, value) {
+ let me = this.up('pveQemuOSPanel');
+ me.lookup('isoSelector').setDisabled(!value);
+ me.lookup('isoSelector').setHidden(!value);
+ },
+ },
+ },
+ {
+ xtype: 'pveIsoSelector',
+ reference: 'isoSelector',
+ name: 'ide0',
+ insideWizard: true,
+ hidden: true,
+ disabled: true,
+ bind: {
+ nodename: '{nodename}',
+ },
+ },
+ ],
+ },
+ ],
+ },
+ ],
+});
diff --git a/www/manager6/qemu/OSTypeEdit.js b/www/manager6/qemu/OSTypeEdit.js
index f8f8c0b6..a9508539 100644
--- a/www/manager6/qemu/OSTypeEdit.js
+++ b/www/manager6/qemu/OSTypeEdit.js
@@ -10,82 +10,11 @@ Ext.define('PVE.qemu.OSTypeInputPanel', {
'combobox[name=osbase]': {
change: 'onOSBaseChange',
},
- 'combobox[name=ostype]': {
- afterrender: 'onOSTypeChange',
- change: 'onOSTypeChange',
- },
- 'checkbox[reference=enableSecondCD]': {
- change: 'onSecondCDChange',
- },
},
onOSBaseChange: function (field, value) {
let me = this;
me.lookup('ostype').getStore().setData(PVE.Utils.kvm_ostypes[value]);
- if (me.getView().insideWizard) {
- let isWindows = value === 'Microsoft Windows';
- let enableSecondCD = me.lookup('enableSecondCD');
- enableSecondCD.setVisible(isWindows);
- if (!isWindows) {
- enableSecondCD.setValue(false);
- }
- }
- },
- onOSTypeChange: function (field) {
- var me = this,
- ostype = field.getValue();
- if (!me.getView().insideWizard) {
- return;
- }
- var targetValues = PVE.qemu.OSDefaults.getDefaults(ostype);
-
- me.setWidget('pveBusSelector', targetValues.busType);
- me.setWidget('pveNetworkCardSelector', targetValues.networkCard);
- me.setWidget('CPUModelSelector', targetValues.cputype);
- var scsihw = targetValues.scsihw || '__default__';
- this.getViewModel().set('current.scsihw', scsihw);
- this.getViewModel().set('current.ostype', ostype);
- },
- setWidget: function (widget, newValue) {
- // changing a widget is safe only if ComponentQuery.query returns us
- // a single value array
- var widgets = Ext.ComponentQuery.query('pveQemuCreateWizard ' + widget);
- if (widgets.length === 1) {
- widgets[0].setValue(newValue);
- } else {
- // ignore multiple disks, we only want to set the type if there is a single disk
- }
},
- onSecondCDChange: function (widget, value, lastValue) {
- let me = this;
- let vm = me.getViewModel();
- let updateVMConfig = function () {
- let widgets = Ext.ComponentQuery.query('pveMultiHDPanel');
- if (widgets.length === 1) {
- widgets[0].getController().updateVMConfig();
- }
- };
- if (value) {
- // only for windows
- vm.set('current.ide0', 'some');
- vm.notify();
- updateVMConfig();
- me.setWidget('pveBusSelector', 'scsi');
- me.setWidget('pveNetworkCardSelector', 'virtio');
- } else {
- vm.set('current.ide0', '');
- vm.notify();
- updateVMConfig();
- me.setWidget('pveBusSelector', 'scsi');
- let ostype = me.lookup('ostype').getValue();
- let targetValues = PVE.qemu.OSDefaults.getDefaults(ostype);
- me.setWidget('pveBusSelector', targetValues.busType);
- }
- },
- },
-
- setNodename: function (nodename) {
- var me = this;
- me.lookup('isoSelector').setNodename(nodename);
},
onGetValues: function (values) {
@@ -103,11 +32,6 @@ Ext.define('PVE.qemu.OSTypeInputPanel', {
var me = this;
me.items = [
- {
- xtype: 'displayfield',
- value: gettext('Guest OS') + ':',
- hidden: !me.insideWizard,
- },
{
xtype: 'combobox',
submitValue: false,
@@ -147,34 +71,6 @@ Ext.define('PVE.qemu.OSTypeInputPanel', {
},
];
- if (me.insideWizard) {
- me.items.push(
- {
- xtype: 'proxmoxcheckbox',
- reference: 'enableSecondCD',
- isFormField: false,
- hidden: true,
- checked: false,
- boxLabel: gettext('Add additional drive for VirtIO drivers'),
- listeners: {
- change: function (cb, value) {
- me.lookup('isoSelector').setDisabled(!value);
- me.lookup('isoSelector').setHidden(!value);
- },
- },
- },
- {
- xtype: 'pveIsoSelector',
- reference: 'isoSelector',
- name: 'ide0',
- nodename: me.nodename,
- insideWizard: true,
- hidden: true,
- disabled: true,
- },
- );
- }
-
me.callParent();
},
});
--
2.47.3
^ permalink raw reply [flat|nested] 22+ messages in thread* [PATCH manager v2 03/17] ui: form: add filtered KVComboBox
2026-02-03 10:00 [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
2026-02-03 10:00 ` [PATCH manager v2 01/17] api/pvestatd: broadcast and expose non-x86 host architecture Dominik Csapak
2026-02-03 10:00 ` [PATCH manager v2 02/17] ui: qemu: wizard: refactor ostype and cd selector into an OSPanel Dominik Csapak
@ 2026-02-03 10:00 ` Dominik Csapak
2026-02-03 10:00 ` [PATCH manager v2 04/17] ui: resource store: add architecture field Dominik Csapak
` (15 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Dominik Csapak @ 2026-02-03 10:00 UTC (permalink / raw)
To: pve-devel
this makes it easier to have the same KVComboBox, but for different
configurations, depending on a single 'category' value. This is useful
for having the same KVComboBox in different categories, such as the cpu
architecture, for e.g. the scsi hw or bios selector, which need different
values for different architectures.
Instead of implementing the logic for each KVComboBox, abstract it away,
so we can reuse the code and have consistent behavior here.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/manager6/Makefile | 1 +
www/manager6/form/FilteredKVComboBox.js | 67 +++++++++++++++++++++++++
2 files changed, 68 insertions(+)
create mode 100644 www/manager6/form/FilteredKVComboBox.js
diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 944dd873..8857045c 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -17,6 +17,7 @@ JSSRC= \
data/ResourceStore.js \
data/model/RRDModels.js \
container/TwoColumnContainer.js \
+ form/FilteredKVComboBox.js \
form/ACMEAPISelector.js \
form/ACMEAccountSelector.js \
form/ACMEPluginSelector.js \
diff --git a/www/manager6/form/FilteredKVComboBox.js b/www/manager6/form/FilteredKVComboBox.js
new file mode 100644
index 00000000..0e24a79f
--- /dev/null
+++ b/www/manager6/form/FilteredKVComboBox.js
@@ -0,0 +1,67 @@
+Ext.define('PVE.form.FilteredKVComboBox', {
+ extend: 'Proxmox.form.KVComboBox',
+ alias: ['widget.pveFilteredKVComboBox'],
+
+ // sam as in the KVComboBox
+ comboItems: undefined,
+
+ // contains the allowed keys per category, e.g.
+ // {
+ // category1: ['foo', 'bar'],
+ // cateogry2: ['foo'],'
+ // }
+ //
+ // to have an effect, the listed values must exist in the comboItems list
+ allowedValuesPerCategory: {},
+
+ // the current category. If not set, the store is not filtered.
+ category: undefined,
+
+ // If set, will be used to update the display value of the '__default__' value
+ // that is usually set in a KVComboBox.
+ //
+ // gets the current category (if any) as parameter)
+ setDefaultDisplay: undefined,
+
+ setCategory: function (category) {
+ let me = this;
+ me.category = category;
+ me.filterByCategory(category);
+ },
+
+ filterByCategory: function (category) {
+ let me = this;
+ let wasValid = me.isValid();
+ me.store.clearFilter();
+
+ let allowedKeys = me.allowedValuesPerCategory[category];
+ if (allowedKeys) {
+ me.store.addFilter((rec) => allowedKeys.indexOf(rec.data.key) !== -1);
+ }
+
+ let isValid = me.isValid();
+ // update default value with new arch
+ if (Ext.isFunction(me.setDefaultDisplay)) {
+ let record = me.store.findRecord('key', '__default__');
+ if (record) {
+ record.set('value', me.setDefaultDisplay(category));
+ 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.callParent();
+
+ // initial filtering
+ me.setCategory(me.category);
+ },
+});
--
2.47.3
^ permalink raw reply [flat|nested] 22+ messages in thread* [PATCH manager v2 04/17] ui: resource store: add architecture field
2026-02-03 10:00 [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
` (2 preceding siblings ...)
2026-02-03 10:00 ` [PATCH manager v2 03/17] ui: form: add filtered KVComboBox Dominik Csapak
@ 2026-02-03 10:00 ` Dominik Csapak
2026-02-03 10:00 ` [PATCH manager v2 05/17] ui: qemu: add architecture specific defaults and helpers Dominik Csapak
` (14 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Dominik Csapak @ 2026-02-03 10:00 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
^ permalink raw reply [flat|nested] 22+ messages in thread* [PATCH manager v2 05/17] ui: qemu: add architecture specific defaults and helpers
2026-02-03 10:00 [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
` (3 preceding siblings ...)
2026-02-03 10:00 ` [PATCH manager v2 04/17] ui: resource store: add architecture field Dominik Csapak
@ 2026-02-03 10:00 ` Dominik Csapak
2026-02-03 10:00 ` [PATCH manager v2 06/17] ui: qemu: add architecture field in wizard and hardware view Dominik Csapak
` (13 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Dominik Csapak @ 2026-02-03 10:00 UTC (permalink / raw)
To: pve-devel
Introduce a new singleton 'PVE.qemu.Architecture', that contains nearly all
architecture specific settings such as renderers, defaults and filters.
This provides a single place to modify architecture specific behavior,
or add new architectures the gui should handle.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/manager6/Makefile | 1 +
www/manager6/qemu/Architecture.js | 104 ++++++++++++++++++++++++++++++
2 files changed, 105 insertions(+)
create mode 100644 www/manager6/qemu/Architecture.js
diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 8857045c..8f9c53c4 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -5,6 +5,7 @@ BIOME ?= proxmox-biome
JSSRC= \
Parser.js \
StateProvider.js \
+ qemu/Architecture.js \
Utils.js \
UIOptions.js \
Toolkit.js \
diff --git a/www/manager6/qemu/Architecture.js b/www/manager6/qemu/Architecture.js
new file mode 100644
index 00000000..21aabd26
--- /dev/null
+++ b/www/manager6/qemu/Architecture.js
@@ -0,0 +1,104 @@
+/* This file defines the helpers, defaults and limtis for various vCPU architectures, such
+ * as x86_64, and aarch64.
+ *
+ * To add a new architecture, add the respective entry in the defaults/renderers and selection.
+ */
+Ext.define('PVE.qemu.Architecture', {
+ singleton: true,
+
+ selection: [
+ ['__default__', `${Proxmox.Utils.defaultText} (${gettext('Host Architecture')})`],
+ ['x86_64', gettext('x86 (64-bit)')],
+ ['aarch64', gettext('ARM (64-bit)')],
+ ],
+
+ // filter for PVE.Utils.kvm_ostypes
+ kvmOSTypes: {
+ x86_64: {
+ bases: undefined, // include all
+ ostypes: undefined, // include all
+ },
+ aarch64: {
+ bases: ['Linux', 'Other'],
+ ostypes: ['l26', 'other'],
+ },
+ },
+
+ defaultProcessorModel: {
+ x86_64: 'x86-64-v2-AES',
+ aarch64: 'cortex-a57',
+ },
+
+ defaultMachines: {
+ x86_64: 'pc',
+ aarch64: 'virt',
+ },
+
+ defaultCDDrive: {
+ x86_64: ['ide', 2],
+ aarch64: ['scsi', 2],
+ },
+
+ allowedScsiHw: {
+ x86_64: [
+ '__default__',
+ 'lsi',
+ 'lsi53c810',
+ 'megasas',
+ 'virtio-scsi-pci',
+ 'virtio-scsi-single',
+ 'pvscsi',
+ ],
+ aarch64: ['virtio-scsi-pci', 'virtio-scsi-single'],
+ },
+
+ allowedMachines: {
+ x86_64: ['__default__', 'q35'], // __default__ is i440fx
+ aarch64: ['__default__'], // __default__ is virt
+ },
+
+ allowedBusses: {
+ x86_64: ['ide', 'sata', 'virtio', 'scsi', 'unused'],
+ aarch64: ['sata', 'virtio', 'scsi', 'unused'],
+ },
+
+ allowedFirmware: {
+ x86_64: ['__default__', 'seabios', 'ovmf'], // default is seabios
+ aarch64: ['ovmf'],
+ },
+
+ render_vcpu_architecture: 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;
+ }
+ },
+
+ // returns the resulting architecture from a given arch and
+ // the nodename, in case the architecture is set to default or empty
+ getNodeArchitecture: 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__') {
+ architecture = undefined;
+ }
+
+ let hostArchitecture = PVE.data.ResourceStore.getNodeById(nodename)?.data.architecture;
+
+ return (architecture ?? 'x86_64') === (hostArchitecture ?? 'x86_64');
+ },
+});
--
2.47.3
^ permalink raw reply [flat|nested] 22+ messages in thread* [PATCH manager v2 06/17] ui: qemu: add architecture field in wizard and hardware view
2026-02-03 10:00 [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
` (4 preceding siblings ...)
2026-02-03 10:00 ` [PATCH manager v2 05/17] ui: qemu: add architecture specific defaults and helpers Dominik Csapak
@ 2026-02-03 10:00 ` Dominik Csapak
2026-02-03 10:00 ` [PATCH manager v2 07/17] ui: qemu: make scsi hw selector architecture aware Dominik Csapak
` (12 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Dominik Csapak @ 2026-02-03 10:00 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/qemu/CreateWizard.js | 51 +++++++++++++++++++++++++++++++
www/manager6/qemu/HardwareView.js | 10 ++++++
2 files changed, 61 insertions(+)
diff --git a/www/manager6/qemu/CreateWizard.js b/www/manager6/qemu/CreateWizard.js
index 3928d7ff..14cb2c43 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: '',
},
},
formulas: {
@@ -60,6 +61,25 @@ Ext.define('PVE.qemu.CreateWizard', {
return undefined;
},
+ setArchitecture: function () {
+ let me = this;
+ let vm = me.getViewModel();
+
+ let nodename = me.lookup('nodenameSelector').getValue();
+ if (!nodename) {
+ // we can't set an architecture if we don't have a nodename
+ return;
+ }
+ let arch = me.lookup('archSelector').getValue();
+ if (arch === '__default__') {
+ arch = undefined;
+ }
+ arch = PVE.qemu.Architecture.getNodeArchitecture(arch, nodename);
+ vm.set('current.architecture', arch);
+ },
+
+ referenceHolder: true,
+
items: [
{
xtype: 'inputpanel',
@@ -69,6 +89,7 @@ Ext.define('PVE.qemu.CreateWizard', {
{
xtype: 'pveNodeSelector',
name: 'nodename',
+ reference: 'nodenameSelector',
cbind: {
selectCurNode: '{!nodename}',
preferredValue: '{nodename}',
@@ -79,6 +100,11 @@ Ext.define('PVE.qemu.CreateWizard', {
fieldLabel: gettext('Node'),
allowBlank: false,
onlineValidator: true,
+ listeners: {
+ change: function () {
+ this.up('window').setArchitecture();
+ },
+ },
},
{
xtype: 'pveGuestIDSelector',
@@ -151,6 +177,20 @@ Ext.define('PVE.qemu.CreateWizard', {
],
advancedColumnB: [
+ {
+ xtype: 'proxmoxKVComboBox',
+ name: 'arch',
+ value: '__default__',
+ reference: 'archSelector',
+ fieldLabel: gettext('vCPU Architecture'),
+ labelWidth: 120,
+ comboItems: PVE.qemu.Architecture.selection,
+ listeners: {
+ change: function () {
+ this.up('window').setArchitecture();
+ },
+ },
+ },
{
xtype: 'pveTagFieldSet',
name: 'tags',
@@ -258,6 +298,13 @@ Ext.define('PVE.qemu.CreateWizard', {
kv.boot = boot;
}
+ if (
+ kv.arch &&
+ !PVE.qemu.Architecture.isHostArchitecture(kv.arch, kv.nodename)
+ ) {
+ kv.kvm = 0;
+ }
+
Ext.Object.each(kv, function (key, value) {
if (key === 'delete') {
// ignore
@@ -288,6 +335,10 @@ Ext.define('PVE.qemu.CreateWizard', {
kv.boot = boot;
}
+ if (kv.arch && !PVE.qemu.Architecture.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..541a41cb 100644
--- a/www/manager6/qemu/HardwareView.js
+++ b/www/manager6/qemu/HardwareView.js
@@ -66,6 +66,12 @@ Ext.define('PVE.qemu.HardwareView', {
};
let rows = {
+ arch: {
+ header: gettext('vCPU Architecture'),
+ tdCls: 'pve-itype-icon-cpu',
+ never_delete: true,
+ renderer: PVE.qemu.Architecture.render_vcpu_architecture,
+ },
memory: {
header: gettext('Memory'),
editor: caps.vms['VM.Config.Memory'] ? 'PVE.qemu.MemoryEdit' : undefined,
@@ -419,6 +425,10 @@ Ext.define('PVE.qemu.HardwareView', {
pveSelNode: me.pveSelNode,
confid: rec.data.key,
url: `/api2/extjs/${baseurl}`,
+ arch: PVE.qemu.Architecture.getNodeArchitecture(
+ me.getObjectValue('arch'),
+ nodename,
+ ),
listeners: {
destroy: () => me.reload(),
},
--
2.47.3
^ permalink raw reply [flat|nested] 22+ messages in thread* [PATCH manager v2 07/17] ui: qemu: make scsi hw selector architecture aware
2026-02-03 10:00 [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
` (5 preceding siblings ...)
2026-02-03 10:00 ` [PATCH manager v2 06/17] ui: qemu: add architecture field in wizard and hardware view Dominik Csapak
@ 2026-02-03 10:00 ` Dominik Csapak
2026-02-03 10:00 ` [PATCH manager v2 08/17] ui: qemu: make osdefaults " Dominik Csapak
` (11 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Dominik Csapak @ 2026-02-03 10:00 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 | 6 +++++-
www/manager6/qemu/ScsiHwEdit.js | 1 +
www/manager6/qemu/SystemEdit.js | 1 +
3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/www/manager6/form/ScsiHwSelector.js b/www/manager6/form/ScsiHwSelector.js
index d35a5b3a..af751b80 100644
--- a/www/manager6/form/ScsiHwSelector.js
+++ b/www/manager6/form/ScsiHwSelector.js
@@ -1,5 +1,5 @@
Ext.define('PVE.form.ScsiHwSelector', {
- extend: 'Proxmox.form.KVComboBox',
+ extend: 'PVE.form.FilteredKVComboBox',
alias: ['widget.pveScsiHwSelector'],
comboItems: [
['__default__', PVE.Utils.render_scsihw('')],
@@ -10,4 +10,8 @@ Ext.define('PVE.form.ScsiHwSelector', {
['virtio-scsi-single', PVE.Utils.render_scsihw('virtio-scsi-single')],
['pvscsi', PVE.Utils.render_scsihw('pvscsi')],
],
+
+ allowedValuesPerCategory: PVE.qemu.Architecture.allowedScsiHw,
+
+ setDefaultDisplay: (arch) => PVE.Utils.render_scsihw('', arch),
});
diff --git a/www/manager6/qemu/ScsiHwEdit.js b/www/manager6/qemu/ScsiHwEdit.js
index 48dcb228..a3264212 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'),
+ category: me.arch,
},
});
diff --git a/www/manager6/qemu/SystemEdit.js b/www/manager6/qemu/SystemEdit.js
index 2cf17e8e..bec9fef1 100644
--- a/www/manager6/qemu/SystemEdit.js
+++ b/www/manager6/qemu/SystemEdit.js
@@ -139,6 +139,7 @@ Ext.define('PVE.qemu.SystemInputPanel', {
name: 'scsihw',
value: '__default__',
bind: {
+ category: '{current.architecture}',
value: '{current.scsihw}',
},
fieldLabel: gettext('SCSI Controller'),
--
2.47.3
^ permalink raw reply [flat|nested] 22+ messages in thread* [PATCH manager v2 08/17] ui: qemu: make osdefaults architecture aware
2026-02-03 10:00 [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
` (6 preceding siblings ...)
2026-02-03 10:00 ` [PATCH manager v2 07/17] ui: qemu: make scsi hw selector architecture aware Dominik Csapak
@ 2026-02-03 10:00 ` Dominik Csapak
2026-02-03 10:00 ` [PATCH manager v2 09/17] ui: qemu: make os type selector " Dominik Csapak
` (10 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Dominik Csapak @ 2026-02-03 10:00 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 | 76 ++++++++++++++++++++++++++-------
1 file changed, 60 insertions(+), 16 deletions(-)
diff --git a/www/manager6/qemu/OSDefaults.js b/www/manager6/qemu/OSDefaults.js
index bcebd0b3..d921ab53 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,33 @@ 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: 4,
+ sata: 3,
+ virtio: 2,
+ ide: 1,
+ },
+ scsihw: 'virtio-scsi-single',
+ cputype: 'neoverse-n2',
+ bios: 'ovmf',
},
- scsihw: 'virtio-scsi-single',
- cputype: 'x86-64-v2-AES',
};
// virtio-net is in kernel since 2.6.25
@@ -58,6 +84,18 @@ Ext.define('PVE.qemu.OSDefaults', {
ide: 1,
},
networkCard: 'virtio',
+
+ architectures: {
+ aarch64: {
+ busPriority: {
+ scsi: 4,
+ virtio: 2,
+ sata: 2,
+ ide: 1,
+ },
+ networkCard: 'virtio',
+ },
+ },
});
// recommendation from http://wiki.qemu.org/Windows2000
@@ -73,12 +111,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
^ permalink raw reply [flat|nested] 22+ messages in thread* [PATCH manager v2 09/17] ui: qemu: make os type selector architecture aware
2026-02-03 10:00 [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
` (7 preceding siblings ...)
2026-02-03 10:00 ` [PATCH manager v2 08/17] ui: qemu: make osdefaults " Dominik Csapak
@ 2026-02-03 10:00 ` Dominik Csapak
2026-02-03 10:00 ` [PATCH manager v2 10/17] ui: qemu: make machine panels/fields " Dominik Csapak
` (9 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Dominik Csapak @ 2026-02-03 10:00 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/qemu/OSPanel.js | 10 ++++++++--
www/manager6/qemu/OSTypeEdit.js | 26 ++++++++++++++++++++++++++
www/manager6/qemu/Options.js | 4 +++-
3 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/www/manager6/qemu/OSPanel.js b/www/manager6/qemu/OSPanel.js
index dd44c865..136c0316 100644
--- a/www/manager6/qemu/OSPanel.js
+++ b/www/manager6/qemu/OSPanel.js
@@ -36,7 +36,9 @@ Ext.define('PVE.qemu.OSPanel', {
onOSTypeChange: function (field) {
var me = this,
ostype = field.getValue();
- var targetValues = PVE.qemu.OSDefaults.getDefaults(ostype);
+
+ let arch = me.getViewModel().get('current.architecture');
+ var targetValues = PVE.qemu.OSDefaults.getDefaults(ostype, arch);
me.setWidget('pveBusSelector', targetValues.busType);
me.setWidget('pveNetworkCardSelector', targetValues.networkCard);
@@ -77,7 +79,8 @@ Ext.define('PVE.qemu.OSPanel', {
updateVMConfig();
me.setWidget('pveBusSelector', 'scsi');
let ostype = me.getView().down('[name=ostype]').getValue();
- let targetValues = PVE.qemu.OSDefaults.getDefaults(ostype);
+ let arch = vm.get('current.architecture');
+ let targetValues = PVE.qemu.OSDefaults.getDefaults(ostype, arch);
me.setWidget('pveBusSelector', targetValues.busType);
}
},
@@ -110,6 +113,9 @@ Ext.define('PVE.qemu.OSPanel', {
{
xtype: 'pveQemuOSTypePanel',
insideWizard: true,
+ bind: {
+ arch: '{current.architecture}',
+ },
},
{
xtype: 'inputpanel',
diff --git a/www/manager6/qemu/OSTypeEdit.js b/www/manager6/qemu/OSTypeEdit.js
index a9508539..dd84d40e 100644
--- a/www/manager6/qemu/OSTypeEdit.js
+++ b/www/manager6/qemu/OSTypeEdit.js
@@ -17,6 +17,25 @@ Ext.define('PVE.qemu.OSTypeInputPanel', {
},
},
+ setArch: function (arch) {
+ let me = this;
+ me.arch = arch;
+
+ let osbaseStore = me.lookup('osbase').getStore();
+ osbaseStore.clearFilter();
+ let list = PVE.qemu.Architecture.kvmOSTypes[arch]?.bases;
+ if (list) {
+ osbaseStore.addFilter((rec) => list.indexOf(rec.data.field1) !== -1);
+ }
+
+ let ostypeStore = me.lookup('ostype').getStore();
+ ostypeStore.clearFilter();
+ list = PVE.qemu.Architecture.kvmOSTypes[arch]?.ostypes;
+ if (list) {
+ ostypeStore.addFilter((rec) => list.indexOf(rec.data.val) !== -1);
+ }
+ },
+
onGetValues: function (values) {
if (values.ide0) {
let drive = {
@@ -36,6 +55,7 @@ Ext.define('PVE.qemu.OSTypeInputPanel', {
xtype: 'combobox',
submitValue: false,
name: 'osbase',
+ reference: 'osbase',
fieldLabel: gettext('Type'),
editable: false,
queryMode: 'local',
@@ -77,6 +97,7 @@ Ext.define('PVE.qemu.OSTypeInputPanel', {
Ext.define('PVE.qemu.OSTypeEdit', {
extend: 'Proxmox.window.Edit',
+ alias: 'widget.pveQemuOSTypeEdit',
subject: 'OS Type',
@@ -92,6 +113,11 @@ 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 = PVE.qemu.Architecture.getNodeArchitecture(
+ response.result.data.arch,
+ me.nodename,
+ );
+ me.down('pveQemuOSTypePanel').setArch(arch);
},
});
},
diff --git a/www/manager6/qemu/Options.js b/www/manager6/qemu/Options.js
index 0c0de699..8a4721a0 100644
--- a/www/manager6/qemu/Options.js
+++ b/www/manager6/qemu/Options.js
@@ -86,7 +86,9 @@ Ext.define('PVE.qemu.Options', {
},
ostype: {
header: gettext('OS Type'),
- editor: caps.vms['VM.Config.Options'] ? 'PVE.qemu.OSTypeEdit' : undefined,
+ editor: caps.vms['VM.Config.Options']
+ ? { xtype: 'pveQemuOSTypeEdit', nodename }
+ : undefined,
renderer: PVE.Utils.render_kvm_ostype,
defaultValue: 'other',
},
--
2.47.3
^ permalink raw reply [flat|nested] 22+ messages in thread* [PATCH manager v2 10/17] ui: qemu: make machine panels/fields architecture aware
2026-02-03 10:00 [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
` (8 preceding siblings ...)
2026-02-03 10:00 ` [PATCH manager v2 09/17] ui: qemu: make os type selector " Dominik Csapak
@ 2026-02-03 10:00 ` Dominik Csapak
2026-02-03 10:00 ` [PATCH manager v2 11/17] ui: qemu: make bios selector " Dominik Csapak
` (8 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Dominik Csapak @ 2026-02-03 10:00 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 | 12 ++++-
www/manager6/form/QemuMachineSelector.js | 13 +++++
www/manager6/qemu/HardwareView.js | 6 ++-
www/manager6/qemu/MachineEdit.js | 68 +++++++++++++++++-------
www/manager6/qemu/SystemEdit.js | 9 ++--
6 files changed, 83 insertions(+), 26 deletions(-)
create mode 100644 www/manager6/form/QemuMachineSelector.js
diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 8f9c53c4..0eb5d3d0 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -64,6 +64,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 2992f655..6fdfda6f 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -498,8 +498,16 @@ Ext.define('PVE.Utils', {
return agentstring;
},
- render_qemu_machine: function (value) {
- return value || Proxmox.Utils.defaultText + ' (i440fx)';
+ render_qemu_machine: function (value, arch = 'x86_64') {
+ let machineTextMap = {
+ pc: 'i440fx',
+ };
+ if (!value) {
+ let machine = PVE.qemu.Architecture.defaultMachines[arch];
+ let machineText = machineTextMap[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..faeb530a
--- /dev/null
+++ b/www/manager6/form/QemuMachineSelector.js
@@ -0,0 +1,13 @@
+Ext.define('PVE.form.QemuMachineSelector', {
+ extend: 'PVE.form.FilteredKVComboBox',
+ alias: 'widget.pveQemuMachineSelector',
+
+ comboItems: [
+ ['__default__', PVE.Utils.render_qemu_machine('')],
+ ['q35', 'q35'],
+ ],
+
+ allowedValuesPerCategory: PVE.qemu.Architecture.allowedMachines,
+
+ setDefaultDisplay: (arch) => PVE.Utils.render_qemu_machine('', arch),
+});
diff --git a/www/manager6/qemu/HardwareView.js b/www/manager6/qemu/HardwareView.js
index 541a41cb..c37e6b17 100644
--- a/www/manager6/qemu/HardwareView.js
+++ b/www/manager6/qemu/HardwareView.js
@@ -193,13 +193,17 @@ 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.qemu.Architecture.getNodeArchitecture(
+ 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..c3fea1d0 100644
--- a/www/manager6/qemu/MachineEdit.js
+++ b/www/manager6/qemu/MachineEdit.js
@@ -23,14 +23,14 @@ 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';
- store.clearFilter();
- store.addFilter((val) => val.data.id === 'latest' || val.data.type === type);
+
+ me.setVersionFilter(value);
+
if (!me.getView().isWindows) {
version.setValue('latest');
} else {
- store.isWindows = true;
if (!oldRec) {
return;
}
@@ -42,12 +42,29 @@ Ext.define('PVE.qemu.MachineInputPanel', {
}
}
},
+
+ setVersionFilter: function (machineType) {
+ let me = this;
+ let vm = me.getViewModel();
+ let arch = vm.get('arch');
+ let defaultMachine = PVE.qemu.Architecture.defaultMachines[arch];
+ if (defaultMachine === 'pc') {
+ defaultMachine = 'i440fx'; // the default in the backend is 'pc' which means 'i440fx' for the qemu machinetype'
+ }
+ let type = machineType === 'q35' ? 'q35' : defaultMachine;
+ let store = me.lookup('version').getStore();
+ store.clearFilter();
+ store.addFilter((val) => val.data.id === 'latest' || val.data.type === type);
+ store.isWindows = me.getView().isWindows;
+ },
},
onGetValues: function (values) {
+ let arch = values.arch;
+ delete values.arch;
if (values.delete === 'machine' && values.viommu) {
delete values.delete;
- values.machine = 'pc';
+ values.machine = PVE.qemu.Architecture.defaultMachines[arch];
}
if (values.version && values.version !== 'latest') {
values.machine = values.version;
@@ -68,8 +85,9 @@ Ext.define('PVE.qemu.MachineInputPanel', {
let machineConf = PVE.Parser.parsePropertyString(values.machine, 'type');
values.machine = machineConf.type;
+ let defaultMachine = PVE.qemu.Architecture.defaultMachines[values.arch];
me.isWindows = values.isWindows;
- if (values.machine === 'pc') {
+ if (values.machine === defaultMachine) {
values.machine = '__default__';
}
@@ -92,21 +110,28 @@ Ext.define('PVE.qemu.MachineInputPanel', {
}
this.callParent(arguments);
+ this.getController().setVersionFilter(values.machine);
},
- 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'),
+ value: '__default__',
+ bind: {
+ value: '{type}',
+ category: '{arch}',
+ },
},
- },
+ {
+ xtype: 'hidden',
+ name: 'arch',
+ reference: 'arch',
+ bind: '{arch}',
+ },
+ ],
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,7 @@ Ext.define('PVE.qemu.MachineEdit', {
machine: conf.machine || '__default__',
};
values.isWindows = PVE.Utils.is_windows(conf.ostype);
+ values.arch = PVE.qemu.Architecture.getNodeArchitecture(conf.arch, me.nodename);
me.setValues(values);
},
});
diff --git a/www/manager6/qemu/SystemEdit.js b/www/manager6/qemu/SystemEdit.js
index bec9fef1..8bc92bd9 100644
--- a/www/manager6/qemu/SystemEdit.js
+++ b/www/manager6/qemu/SystemEdit.js
@@ -83,15 +83,14 @@ 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: {
+ category: '{current.architecture}',
+ },
},
{
xtype: 'displayfield',
--
2.47.3
^ permalink raw reply [flat|nested] 22+ messages in thread* [PATCH manager v2 11/17] ui: qemu: make bios selector architecture aware
2026-02-03 10:00 [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
` (9 preceding siblings ...)
2026-02-03 10:00 ` [PATCH manager v2 10/17] ui: qemu: make machine panels/fields " Dominik Csapak
@ 2026-02-03 10:00 ` Dominik Csapak
2026-02-03 10:00 ` [PATCH manager v2 12/17] ui: qemu: make sortByPreviousUsage " Dominik Csapak
` (7 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Dominik Csapak @ 2026-02-03 10:00 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 | 18 ++++++++---------
www/manager6/qemu/QemuBiosEdit.js | 29 +++++++++++++++++++++++++--
www/manager6/qemu/SystemEdit.js | 3 +++
3 files changed, 38 insertions(+), 12 deletions(-)
diff --git a/www/manager6/form/QemuBiosSelector.js b/www/manager6/form/QemuBiosSelector.js
index 5fa443f1..40abb589 100644
--- a/www/manager6/form/QemuBiosSelector.js
+++ b/www/manager6/form/QemuBiosSelector.js
@@ -1,16 +1,14 @@
Ext.define('PVE.form.QemuBiosSelector', {
- extend: 'Proxmox.form.KVComboBox',
+ extend: 'PVE.form.FilteredKVComboBox',
alias: ['widget.pveQemuBiosSelector'],
- initComponent: function () {
- var me = this;
+ comboItems: [
+ ['__default__', PVE.Utils.render_qemu_bios('')],
+ ['seabios', PVE.Utils.render_qemu_bios('seabios')],
+ ['ovmf', PVE.Utils.render_qemu_bios('ovmf')],
+ ],
- me.comboItems = [
- ['__default__', PVE.Utils.render_qemu_bios('')],
- ['seabios', PVE.Utils.render_qemu_bios('seabios')],
- ['ovmf', PVE.Utils.render_qemu_bios('ovmf')],
- ];
+ allowedValuesPerCategory: PVE.qemu.Architecture.allowedFirmware,
- me.callParent();
- },
+ setDefaultDisplay: (arch) => PVE.Utils.render_qemu_bios('', arch),
});
diff --git a/www/manager6/qemu/QemuBiosEdit.js b/www/manager6/qemu/QemuBiosEdit.js
index ef8f1844..76e5cfb1 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}',
+ category: '{arch}',
+ },
fieldLabel: 'BIOS',
},
{
@@ -42,4 +44,27 @@ 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;
+ let arch = PVE.qemu.Architecture.getNodeArchitecture(values.arch, me.nodename);
+ me.setValues(values);
+ me.down('pveQemuBiosSelector').setCategory(arch);
+ },
+ });
+ }
+ },
});
diff --git a/www/manager6/qemu/SystemEdit.js b/www/manager6/qemu/SystemEdit.js
index 8bc92bd9..0c1e03ca 100644
--- a/www/manager6/qemu/SystemEdit.js
+++ b/www/manager6/qemu/SystemEdit.js
@@ -102,6 +102,9 @@ Ext.define('PVE.qemu.SystemInputPanel', {
reference: 'bios',
value: '__default__',
fieldLabel: 'BIOS',
+ bind: {
+ category: '{current.architecture}',
+ },
},
{
xtype: 'proxmoxcheckbox',
--
2.47.3
^ permalink raw reply [flat|nested] 22+ messages in thread* [PATCH manager v2 12/17] ui: qemu: make sortByPreviousUsage architecture aware
2026-02-03 10:00 [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
` (10 preceding siblings ...)
2026-02-03 10:00 ` [PATCH manager v2 11/17] ui: qemu: make bios selector " Dominik Csapak
@ 2026-02-03 10:00 ` Dominik Csapak
2026-02-03 10:00 ` [PATCH manager v2 13/17] ui: qemu: wizard: use defaults to populate machine and bios Dominik Csapak
` (6 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Dominik Csapak @ 2026-02-03 10:00 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 | 6 +++++-
www/manager6/window/GuestDiskReassign.js | 1 +
7 files changed, 30 insertions(+), 14 deletions(-)
diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index 6fdfda6f..8c04f23b 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -1934,10 +1934,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;
@@ -1953,7 +1951,8 @@ Ext.define('PVE.Utils', {
}
}
- let sortPriority = PVE.qemu.OSDefaults.getDefaults(vmconfig.ostype).busPriority;
+ let arch = PVE.qemu.Architecture.getNodeArchitecture(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..18f11a42 100644
--- a/www/manager6/qemu/NetworkEdit.js
+++ b/www/manager6/qemu/NetworkEdit.js
@@ -264,7 +264,11 @@ Ext.define('PVE.qemu.NetworkEdit', {
}
let ostype = me.vmconfig.ostype;
- let defaults = PVE.qemu.OSDefaults.getDefaults(ostype);
+ let arch = PVE.qemu.Architecture.getNodeArchitecture(
+ 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
^ permalink raw reply [flat|nested] 22+ messages in thread* [PATCH manager v2 13/17] ui: qemu: wizard: use defaults to populate machine and bios
2026-02-03 10:00 [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
` (11 preceding siblings ...)
2026-02-03 10:00 ` [PATCH manager v2 12/17] ui: qemu: make sortByPreviousUsage " Dominik Csapak
@ 2026-02-03 10:00 ` Dominik Csapak
2026-02-03 10:00 ` [PATCH manager v2 14/17] ui: qemu: wizard: make iso confid architecture specific Dominik Csapak
` (5 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Dominik Csapak @ 2026-02-03 10:00 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 | 13 +++++++++----
2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/www/manager6/qemu/OSDefaults.js b/www/manager6/qemu/OSDefaults.js
index d921ab53..a2c218df 100644
--- a/www/manager6/qemu/OSDefaults.js
+++ b/www/manager6/qemu/OSDefaults.js
@@ -111,6 +111,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 0c1e03ca..299be5f8 100644
--- a/www/manager6/qemu/SystemEdit.js
+++ b/www/manager6/qemu/SystemEdit.js
@@ -57,19 +57,24 @@ 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 = vm.get('current.architecture');
+
+ 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
^ permalink raw reply [flat|nested] 22+ messages in thread* [PATCH manager v2 14/17] ui: qemu: wizard: make iso confid architecture specific
2026-02-03 10:00 [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
` (12 preceding siblings ...)
2026-02-03 10:00 ` [PATCH manager v2 13/17] ui: qemu: wizard: use defaults to populate machine and bios Dominik Csapak
@ 2026-02-03 10:00 ` Dominik Csapak
2026-02-03 10:00 ` [PATCH manager v2 15/17] ui: qemu: make bus selector architecture aware Dominik Csapak
` (4 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Dominik Csapak @ 2026-02-03 10:00 UTC (permalink / raw)
To: pve-devel
e.g. on aarch64, there is no ide bus, so we can't use ide2. Instead use
'scsi2' there. We have to slightly adapt the MultiHDEdit panel to
account for a possibly different confid here.
Since windows is currently not available for aarch64, the confid for the
second cd stays the same for now, but has to be adapted if we allow
windows on aarch64 in the future.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/manager6/qemu/CreateWizard.js | 3 +++
www/manager6/qemu/MultiHDEdit.js | 4 +++-
www/manager6/qemu/OSPanel.js | 10 ++++++++++
3 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/www/manager6/qemu/CreateWizard.js b/www/manager6/qemu/CreateWizard.js
index 14cb2c43..1302d9dc 100644
--- a/www/manager6/qemu/CreateWizard.js
+++ b/www/manager6/qemu/CreateWizard.js
@@ -225,6 +225,9 @@ Ext.define('PVE.qemu.CreateWizard', {
{
xtype: 'pveQemuOSPanel',
title: gettext('OS'),
+ bind: {
+ arch: '{current.architecture}',
+ },
},
{
xtype: 'pveQemuSystemPanel',
diff --git a/www/manager6/qemu/MultiHDEdit.js b/www/manager6/qemu/MultiHDEdit.js
index 220167de..e69f3885 100644
--- a/www/manager6/qemu/MultiHDEdit.js
+++ b/www/manager6/qemu/MultiHDEdit.js
@@ -45,11 +45,13 @@ Ext.define('PVE.qemu.MultiHDPanel', {
let vm = me.getViewModel();
let res = {
- ide2: 'media=cdrom',
scsihw: vm.get('current.scsihw'),
ostype: vm.get('current.ostype'),
};
+ let isoConfig = vm.get('current.isoConfig') ?? 'ide2';
+ res[isoConfig] = 'media=cdrom';
+
if (vm.get('current.ide0') === 'some') {
res.ide0 = 'media=cdrom';
}
diff --git a/www/manager6/qemu/OSPanel.js b/www/manager6/qemu/OSPanel.js
index 136c0316..3d2b5a3e 100644
--- a/www/manager6/qemu/OSPanel.js
+++ b/www/manager6/qemu/OSPanel.js
@@ -10,6 +10,16 @@ Ext.define('PVE.qemu.OSPanel', {
padding: '0 10',
},
+ setArch: function (arch) {
+ let me = this;
+ let [controller, id] = PVE.qemu.Architecture.defaultCDDrive[arch] ?? ['ide', 2];
+ let vm = me.getController().getViewModel();
+ let conf = `${controller}${id}`;
+ vm.set('current.isoConfig', conf);
+ me.lookup('cdSelector').confid = conf;
+ // TODO change confid for second cd if windows is allowed for other architectures
+ },
+
controller: {
xclass: 'Ext.app.ViewController',
control: {
--
2.47.3
^ permalink raw reply [flat|nested] 22+ messages in thread* [PATCH manager v2 15/17] ui: qemu: make bus selector architecture aware
2026-02-03 10:00 [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
` (13 preceding siblings ...)
2026-02-03 10:00 ` [PATCH manager v2 14/17] ui: qemu: wizard: make iso confid architecture specific Dominik Csapak
@ 2026-02-03 10:00 ` Dominik Csapak
2026-02-03 10:00 ` [PATCH manager v2 16/17] ui: qemu: make processor edit " Dominik Csapak
` (3 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Dominik Csapak @ 2026-02-03 10:00 UTC (permalink / raw)
To: pve-devel
by turning it into a FilteredKVComboBox. Filter out 'ide' for aarch64.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/manager6/form/BusTypeSelector.js | 4 +++-
www/manager6/form/ControllerSelector.js | 17 +++++++++++++++--
www/manager6/qemu/CDEdit.js | 4 ++++
www/manager6/qemu/HDEdit.js | 3 +++
www/manager6/qemu/MultiHDEdit.js | 1 +
5 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/www/manager6/form/BusTypeSelector.js b/www/manager6/form/BusTypeSelector.js
index 019b2c88..6641ec3a 100644
--- a/www/manager6/form/BusTypeSelector.js
+++ b/www/manager6/form/BusTypeSelector.js
@@ -1,10 +1,12 @@
Ext.define('PVE.form.BusTypeSelector', {
- extend: 'Proxmox.form.KVComboBox',
+ extend: 'PVE.form.FilteredKVComboBox',
alias: 'widget.pveBusSelector',
withVirtIO: true,
withUnused: false,
+ allowedValuesPerCategory: PVE.qemu.Architecture.allowedBusses,
+
initComponent: function () {
var me = this;
diff --git a/www/manager6/form/ControllerSelector.js b/www/manager6/form/ControllerSelector.js
index fee2b398..365c4970 100644
--- a/www/manager6/form/ControllerSelector.js
+++ b/www/manager6/form/ControllerSelector.js
@@ -24,6 +24,14 @@ Ext.define('PVE.form.ControllerSelector', {
}
},
+ filterListByArchitecture: function (clist, arch) {
+ let allowedList = PVE.form.BusTypeSelector.prototype.allowedValuesPerCategory[arch];
+ if (!allowedList) {
+ return clist;
+ }
+ return clist.filter((controller) => allowedList.indexOf(controller) !== -1);
+ },
+
updateVMConfig: function (vmconfig) {
let me = this;
me.vmconfig = Ext.apply({}, vmconfig);
@@ -40,10 +48,13 @@ Ext.define('PVE.form.ControllerSelector', {
let deviceid = me.down('field[name=deviceid]');
let clist;
+ let arch = PVE.qemu.Architecture.getNodeArchitecture(vmconfig.arch, me.nodename);
+ bussel.setCategory(arch);
if (autoSelect === 'cdrom') {
if (!Ext.isDefined(me.vmconfig.ide2)) {
- bussel.setValue('ide');
- deviceid.setValue(2);
+ let [controller, id] = PVE.qemu.Architecture.defaultCDDrive[arch];
+ bussel.setValue(controller);
+ deviceid.setValue(id);
return;
}
clist = ['ide', 'scsi', 'sata'];
@@ -52,6 +63,8 @@ Ext.define('PVE.form.ControllerSelector', {
clist = PVE.Utils.sortByPreviousUsage(me.vmconfig, me.nodename);
}
+ clist = me.filterListByArchitecture(clist, arch);
+
me.setToFree(clist, bussel, deviceid);
deviceid.validate();
diff --git a/www/manager6/qemu/CDEdit.js b/www/manager6/qemu/CDEdit.js
index 80443b35..c185de53 100644
--- a/www/manager6/qemu/CDEdit.js
+++ b/www/manager6/qemu/CDEdit.js
@@ -55,6 +55,9 @@ Ext.define('PVE.qemu.CDInputPanel', {
var me = this;
me.isosel.setNodename(nodename);
+ if (me.bussel) {
+ me.bussel.setNodename(nodename);
+ }
},
initComponent: function () {
@@ -67,6 +70,7 @@ Ext.define('PVE.qemu.CDInputPanel', {
if (!me.confid) {
me.bussel = Ext.create('PVE.form.ControllerSelector', {
withVirtIO: false,
+ nodename: me.nodename,
});
items.push(me.bussel);
}
diff --git a/www/manager6/qemu/HDEdit.js b/www/manager6/qemu/HDEdit.js
index d5ebfdb9..1bb2bfda 100644
--- a/www/manager6/qemu/HDEdit.js
+++ b/www/manager6/qemu/HDEdit.js
@@ -178,6 +178,7 @@ Ext.define('PVE.qemu.HDInputPanel', {
me.lookup('import-source')?.setNodename(nodename);
me.lookup('import-source-file')?.setNodename(nodename);
me.lookup('import-target')?.setNodename(nodename);
+ me.lookup('controllerSelector')?.setNodename(nodename);
},
hasAdvanced: true,
@@ -195,7 +196,9 @@ Ext.define('PVE.qemu.HDInputPanel', {
if (!me.confid || me.unused) {
me.bussel = Ext.create('PVE.form.ControllerSelector', {
+ reference: 'controllerSelector',
vmconfig: me.vmconfig,
+ nodename: me.nodename,
selectFree: true,
});
column1.push(me.bussel);
diff --git a/www/manager6/qemu/MultiHDEdit.js b/www/manager6/qemu/MultiHDEdit.js
index e69f3885..f6b35121 100644
--- a/www/manager6/qemu/MultiHDEdit.js
+++ b/www/manager6/qemu/MultiHDEdit.js
@@ -45,6 +45,7 @@ Ext.define('PVE.qemu.MultiHDPanel', {
let vm = me.getViewModel();
let res = {
+ arch: vm.get('current.architecture'),
scsihw: vm.get('current.scsihw'),
ostype: vm.get('current.ostype'),
};
--
2.47.3
^ permalink raw reply [flat|nested] 22+ messages in thread* [PATCH manager v2 16/17] ui: qemu: make processor edit architecture aware
2026-02-03 10:00 [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
` (14 preceding siblings ...)
2026-02-03 10:00 ` [PATCH manager v2 15/17] ui: qemu: make bus selector architecture aware Dominik Csapak
@ 2026-02-03 10:00 ` Dominik Csapak
2026-02-03 10:00 ` [PATCH manager v2 17/17] ui: qemu: change ui default for cpu model Dominik Csapak
` (2 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Dominik Csapak @ 2026-02-03 10:00 UTC (permalink / raw)
To: pve-devel
The cpu and flags list we get from the backend got an architecture
parameter that we now use to filter the correct cpu models.
For the flags grid, we add an emptyText to show when there are no flags
available (e.g. currently this is the case for aarch64).
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/manager6/form/CPUModelSelector.js | 13 +++++++++++++
www/manager6/form/VMCPUFlagSelector.js | 13 +++++++++++++
www/manager6/qemu/CreateWizard.js | 3 +++
www/manager6/qemu/ProcessorEdit.js | 19 +++++++++++++++++++
4 files changed, 48 insertions(+)
diff --git a/www/manager6/form/CPUModelSelector.js b/www/manager6/form/CPUModelSelector.js
index 2ebd08eb..602706e7 100644
--- a/www/manager6/form/CPUModelSelector.js
+++ b/www/manager6/form/CPUModelSelector.js
@@ -40,6 +40,19 @@ Ext.define('PVE.form.CPUModelSelector', {
width: 360,
},
+ arch: undefined,
+
+ setArch: function (arch) {
+ let me = this;
+ me.arch = arch;
+ let params = {};
+ if (arch) {
+ params.arch = arch;
+ }
+ me.store.getProxy().setExtraParams(params);
+ me.store.reload();
+ },
+
store: {
autoLoad: true,
model: 'PVE.data.CPUModel',
diff --git a/www/manager6/form/VMCPUFlagSelector.js b/www/manager6/form/VMCPUFlagSelector.js
index 922fcfa6..6e49ea45 100644
--- a/www/manager6/form/VMCPUFlagSelector.js
+++ b/www/manager6/form/VMCPUFlagSelector.js
@@ -16,6 +16,8 @@ Ext.define('PVE.form.VMCPUFlagSelector', {
unkownFlags: [],
+ emptyText: gettext('No CPU flags available'),
+
store: {
type: 'store',
fields: ['name', { name: 'state', defaultValue: '=' }, 'description'],
@@ -67,6 +69,17 @@ Ext.define('PVE.form.VMCPUFlagSelector', {
return flags;
},
+ setArch: function (arch) {
+ let me = this;
+ me.arch = arch;
+ let params = {};
+ if (arch) {
+ params.arch = arch;
+ }
+ me.store.getProxy().setExtraParams(params);
+ me.store.reload();
+ },
+
// Adjusts the store for the current value and determines the unkown flags based on what the
// store does not know.
adjustStoreForValue: function () {
diff --git a/www/manager6/qemu/CreateWizard.js b/www/manager6/qemu/CreateWizard.js
index 1302d9dc..4bf9e00f 100644
--- a/www/manager6/qemu/CreateWizard.js
+++ b/www/manager6/qemu/CreateWizard.js
@@ -246,6 +246,9 @@ Ext.define('PVE.qemu.CreateWizard', {
xtype: 'pveQemuProcessorPanel',
insideWizard: true,
title: gettext('CPU'),
+ bind: {
+ arch: '{current.architecture}',
+ },
},
{
xtype: 'pveQemuMemoryPanel',
diff --git a/www/manager6/qemu/ProcessorEdit.js b/www/manager6/qemu/ProcessorEdit.js
index ffaf014e..e1383c3f 100644
--- a/www/manager6/qemu/ProcessorEdit.js
+++ b/www/manager6/qemu/ProcessorEdit.js
@@ -108,6 +108,15 @@ Ext.define('PVE.qemu.ProcessorInputPanel', {
cpu: {},
+ arch: undefined,
+
+ setArch: function (arch) {
+ let me = this;
+ me.arch = arch;
+ me.lookup('cputype').setArch(arch);
+ me.lookup('cpuFlags').setArch(arch);
+ },
+
column1: [
{
xtype: 'proxmoxintegerfield',
@@ -236,10 +245,12 @@ Ext.define('PVE.qemu.ProcessorInputPanel', {
advancedColumnB: [
{
xtype: 'label',
+ reference: 'cpuFlagsLabel',
text: 'Extra CPU Flags:',
},
{
xtype: 'vmcpuflagselector',
+ reference: 'cpuFlags',
name: 'flags',
},
],
@@ -259,6 +270,12 @@ Ext.define('PVE.qemu.ProcessorEdit', {
initComponent: function () {
let me = this;
+
+ me.nodename = me.pveSelNode?.data.node;
+ if (!me.nodename) {
+ throw 'no nodename given';
+ }
+
me.getViewModel().set('cgroupMode', me.cgroupMode);
var ipanel = Ext.create('PVE.qemu.ProcessorInputPanel');
@@ -289,6 +306,8 @@ Ext.define('PVE.qemu.ProcessorEdit', {
}
}
me.setValues(data);
+ let arch = PVE.qemu.Architecture.getNodeArchitecture(data.arch, me.nodename);
+ ipanel.setArch(arch);
},
});
},
--
2.47.3
^ permalink raw reply [flat|nested] 22+ messages in thread* [PATCH manager v2 17/17] ui: qemu: change ui default for cpu model
2026-02-03 10:00 [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
` (15 preceding siblings ...)
2026-02-03 10:00 ` [PATCH manager v2 16/17] ui: qemu: make processor edit " Dominik Csapak
@ 2026-02-03 10:00 ` Dominik Csapak
2026-02-03 10:56 ` [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
2026-02-03 13:34 ` Thomas Lamprecht
18 siblings, 0 replies; 22+ messages in thread
From: Dominik Csapak @ 2026-02-03 10:00 UTC (permalink / raw)
To: pve-devel
in the wizard, we already choose 'x86-64-v2-AES' by default for new vms,
but the backend default (kvm64) is very easy to select by emptying the
field.
Since that default is actually discouraged (but can't be changed as
backend default easily), use the wizard default as default for all
occurrences of the cpu model selector (making it much harder to
accidentally select 'kvm64').
While at it, document the 'default' cpu types in Utils, and use it to
set the correct emptyText for earch architecture.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/manager6/form/CPUModelSelector.js | 26 ++++++++++++++++++++++++++
www/manager6/qemu/OSDefaults.js | 1 -
www/manager6/qemu/ProcessorEdit.js | 13 ++++++++++++-
3 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/www/manager6/form/CPUModelSelector.js b/www/manager6/form/CPUModelSelector.js
index 602706e7..a55d473e 100644
--- a/www/manager6/form/CPUModelSelector.js
+++ b/www/manager6/form/CPUModelSelector.js
@@ -20,6 +20,28 @@ Ext.define('PVE.form.CPUModelSelector', {
deleteEmpty: true,
+ getSubmitData: function () {
+ let me = this,
+ data = null,
+ val;
+ if (!me.disabled && me.submitValue) {
+ val = me.getSubmitValue();
+ if (val !== null && val !== '' && val !== undefined) {
+ data = {};
+ data[me.getName()] = val;
+ } else if (me.getDeleteEmpty()) {
+ data = {};
+ // special case to change gui default for x86
+ if (me.arch === 'x86_64') {
+ data[me.getName()] = PVE.qemu.Architecture.defaultProcessorModel.x86_64;
+ } else {
+ data.delete = me.getName();
+ }
+ }
+ }
+ return data;
+ },
+
listConfig: {
columns: [
{
@@ -51,6 +73,10 @@ Ext.define('PVE.form.CPUModelSelector', {
}
me.store.getProxy().setExtraParams(params);
me.store.reload();
+
+ let defaultCPU = PVE.qemu.Architecture.defaultProcessorModel[arch] ?? 'kvm64';
+
+ me.setEmptyText(`${Proxmox.Utils.defaultText} (${defaultCPU})`);
},
store: {
diff --git a/www/manager6/qemu/OSDefaults.js b/www/manager6/qemu/OSDefaults.js
index a2c218df..bd652e2f 100644
--- a/www/manager6/qemu/OSDefaults.js
+++ b/www/manager6/qemu/OSDefaults.js
@@ -52,7 +52,6 @@ Ext.define('PVE.qemu.OSDefaults', {
virtio: 1,
},
scsihw: 'virtio-scsi-single',
- cputype: 'x86-64-v2-AES',
},
aarch64: {
diff --git a/www/manager6/qemu/ProcessorEdit.js b/www/manager6/qemu/ProcessorEdit.js
index e1383c3f..52b8074c 100644
--- a/www/manager6/qemu/ProcessorEdit.js
+++ b/www/manager6/qemu/ProcessorEdit.js
@@ -305,8 +305,19 @@ Ext.define('PVE.qemu.ProcessorEdit', {
vm.set('showCustomModelPermWarning', true);
}
}
- me.setValues(data);
let arch = PVE.qemu.Architecture.getNodeArchitecture(data.arch, me.nodename);
+ // change default cputype for x86 in gui only
+ if (arch === 'x86_64') {
+ if (!data.cputype) {
+ // use our backend default as explicit value
+ data.cputype = 'kvm64';
+ } else if (
+ data.cputype === PVE.qemu.Architecture.defaultProcessorModel.x86_64
+ ) {
+ delete data.cputype;
+ }
+ }
+ me.setValues(data);
ipanel.setArch(arch);
},
});
--
2.47.3
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH manager v2 00/17] enable qemu vm architecture selection
2026-02-03 10:00 [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
` (16 preceding siblings ...)
2026-02-03 10:00 ` [PATCH manager v2 17/17] ui: qemu: change ui default for cpu model Dominik Csapak
@ 2026-02-03 10:56 ` Dominik Csapak
2026-02-03 13:34 ` Thomas Lamprecht
18 siblings, 0 replies; 22+ messages in thread
From: Dominik Csapak @ 2026-02-03 10:56 UTC (permalink / raw)
To: pve-devel
forgot of course to add the [0] reference for fionas series
so here it is now:
0: https://lore.proxmox.com/all/20260129131021.118199-1-f.ebner@proxmox.com/
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH manager v2 00/17] enable qemu vm architecture selection
2026-02-03 10:00 [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
` (17 preceding siblings ...)
2026-02-03 10:56 ` [PATCH manager v2 00/17] enable qemu vm architecture selection Dominik Csapak
@ 2026-02-03 13:34 ` Thomas Lamprecht
18 siblings, 0 replies; 22+ messages in thread
From: Thomas Lamprecht @ 2026-02-03 13:34 UTC (permalink / raw)
To: Dominik Csapak, pve-devel
Am 03.02.26 um 11:20 schrieb Dominik Csapak:
> NOTE: requires fionas series for qemu-server[0] to work properly
> for the cpu models + flags
Which means that you basically tested Fiona's series already?
Might I ask for a T-b reply to her series in that case, to have
that on record?
^ permalink raw reply [flat|nested] 22+ messages in thread