public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Dominik Csapak <d.csapak@proxmox.com>
To: Fiona Ebner <f.ebner@proxmox.com>,
	Proxmox VE development discussion <pve-devel@lists.proxmox.com>
Subject: Re: [pve-devel] [PATCH manager 07/10] ui: qemu: make machine panels/fields architecture aware
Date: Thu, 29 Jan 2026 13:16:35 +0100	[thread overview]
Message-ID: <3f6ae5e9-7871-4220-b759-15b71720a4b6@proxmox.com> (raw)
In-Reply-To: <60129254-d70c-48d5-8f3c-10d3e320da28@proxmox.com>



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';
>              }
>          }
> 





  reply	other threads:[~2026-01-29 12:16 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 16:05   ` Fiona Ebner
2026-01-29  9:20     ` 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 ` [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
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 ` [pve-devel] [PATCH manager 05/10] ui: qemu: make osdefaults " 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
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
2026-01-29 12:10       ` Fiona Ebner
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 [this message]
2026-01-29 12:25       ` Fiona Ebner
2026-01-28 12:18 ` [pve-devel] [PATCH manager 08/10] ui: qemu: make bios selector " Dominik Csapak
2026-01-28 12:18 ` [pve-devel] [PATCH manager 09/10] ui: qemu: make sortByPreviousUsage " 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
2026-01-29 13:15   ` Fiona Ebner

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=3f6ae5e9-7871-4220-b759-15b71720a4b6@proxmox.com \
    --to=d.csapak@proxmox.com \
    --cc=f.ebner@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

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

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