From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 90D4B1FF137 for ; Tue, 03 Feb 2026 11:28:09 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id D80271A3E3; Tue, 3 Feb 2026 11:28:38 +0100 (CET) From: Dominik Csapak To: pve-devel@lists.proxmox.com Subject: [PATCH manager v2 10/17] ui: qemu: make machine panels/fields architecture aware Date: Tue, 3 Feb 2026 11:00:15 +0100 Message-ID: <20260203102118.1430545-11-d.csapak@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260203102118.1430545-1-d.csapak@proxmox.com> References: <20260203102118.1430545-1-d.csapak@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.032 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: 5SYWZD5CC3UJBB4RUP7BQSVLWF6TEP5T X-Message-ID-Hash: 5SYWZD5CC3UJBB4RUP7BQSVLWF6TEP5T X-MailFrom: d.csapak@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: 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 --- 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