* [PATCH manager v2] fix #7896: ui: qemu: show effective machine version for Windows guests
@ 2026-08-24 13:01 Jakob Klocker
2026-08-26 8:36 ` Dominik Csapak
2026-08-31 9:48 ` superseded: " Jakob Klocker
0 siblings, 2 replies; 6+ messages in thread
From: Jakob Klocker @ 2026-08-24 13:01 UTC (permalink / raw)
To: pve-devel
Windows guests without an explicitly pinned machine version still run
with a fixed one: guests created with QEMU 9.1 or newer keep the
version they were created with, older ones fall back to 5.1.
The GUI assumed the 5.1 fallback unconditionally, so guests created
with a newer QEMU were shown a version they are not running. Derive
the version from the QEMU version recorded at creation time instead,
in both the hardware view and the machine edit dialog, and mark it as
implicit so it stays distinguishable from an explicit pin.
The edit dialog also pre-filled the version field with the fallback,
which both suggested a version the guest might not be running and
caused any other change in the dialog to submit that stale value.
Leave the selector at 'latest' instead, so a version can be picked
deliberately, and show the effective version as a read-only field
together with a hint recommending an explicit pin. The advanced
section is expanded so the hint is visible without further
interaction.
Link: https://bugzilla.proxmox.com/show_bug.cgi?id=7896
Signed-off-by: Jakob Klocker <j.klocker@proxmox.com>
---
changes from v1 to v2 (thanks @Dominik):
* consider viommu during machine-version parsing
* display viommu when the version is implicit
* preserve the current version & note displayed on reset
www/manager6/Utils.js | 22 ++++++++++++++++
www/manager6/qemu/HardwareView.js | 27 +++++++++++++++++--
www/manager6/qemu/MachineEdit.js | 44 ++++++++++++++++++++++++++++---
3 files changed, 87 insertions(+), 6 deletions(-)
diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index c86a00c5..8b99371d 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -1822,6 +1822,28 @@ Ext.define('PVE.Utils', {
return true;
},
+ qemu_implicit_machine_version: function (machineType, creationQemu, arch) {
+ let baseVersion = '5.1';
+ let m = creationQemu?.match(/^(\d+)\.(\d+)/);
+ if (m) {
+ let major = parseInt(m[1], 10);
+ let minor = parseInt(m[2], 10);
+ if (major > 9 || (major === 9 && minor >= 1)) {
+ baseVersion = `${major}.${minor}`;
+ }
+ }
+
+ let base;
+ if (machineType === 'q35') {
+ base = 'pc-q35';
+ } else {
+ let defaultMachine = PVE.qemu.Architecture.defaultMachines[arch];
+ base = defaultMachine === 'virt' ? 'virt' : 'pc-i440fx';
+ }
+
+ return `${base}-${baseVersion}`;
+ },
+
cleanEmptyObjectKeys: function (obj) {
for (const propName of Object.keys(obj)) {
if (obj[propName] === null || obj[propName] === undefined) {
diff --git a/www/manager6/qemu/HardwareView.js b/www/manager6/qemu/HardwareView.js
index e6c02299..f7f4b46f 100644
--- a/www/manager6/qemu/HardwareView.js
+++ b/www/manager6/qemu/HardwareView.js
@@ -197,11 +197,31 @@ Ext.define('PVE.qemu.HardwareView', {
me.getObjectValue('arch'),
nodename,
);
+ let machineConf = PVE.Parser.parsePropertyString(value, 'type');
+ let machineType = machineConf.type;
if (
PVE.Utils.is_windows(ostype) &&
- (!value || value === 'pc' || value === 'q35')
+ (!machineType || machineType === 'pc' || machineType === 'q35')
) {
- return value === 'q35' ? 'pc-q35-5.1' : 'pc-i440fx-5.1';
+ let meta = me.getObjectValue('meta', undefined, pending);
+ let creationQemu;
+ if (meta) {
+ creationQemu = PVE.Parser.parsePropertyString(meta)['creation-qemu'];
+ }
+
+ machineType = machineType === 'q35' ? 'q35' : '__default__';
+ let displayMachine = PVE.Utils.qemu_implicit_machine_version(
+ machineType,
+ creationQemu,
+ arch,
+ );
+
+ let displayValue = displayMachine + ' ' + gettext('(implicit)');
+ if (machineConf.viommu) {
+ displayValue += ', viommu=' + machineConf.viommu;
+ }
+
+ return displayValue;
}
return PVE.Utils.render_qemu_machine(value, arch);
},
@@ -254,6 +274,9 @@ Ext.define('PVE.qemu.HardwareView', {
ostype: {
visible: false,
},
+ meta: {
+ visible: false,
+ },
affinity: {
visible: false,
},
diff --git a/www/manager6/qemu/MachineEdit.js b/www/manager6/qemu/MachineEdit.js
index 4b1a9e83..6cf70705 100644
--- a/www/manager6/qemu/MachineEdit.js
+++ b/www/manager6/qemu/MachineEdit.js
@@ -6,6 +6,8 @@ Ext.define('PVE.qemu.MachineInputPanel', {
viewModel: {
data: {
type: '__default__',
+ effectiveVersionLabel: '',
+ implicitVersion: false,
},
formulas: {
q35: (get) => get('type') === 'q35',
@@ -102,10 +104,21 @@ Ext.define('PVE.qemu.MachineInputPanel', {
}
if (me.isWindows) {
- if (values.machine === '__default__') {
- values.version = 'pc-i440fx-5.1';
- } else if (values.machine === 'q35') {
- values.version = 'pc-q35-5.1';
+ if (values.machine === '__default__' || values.machine === 'q35') {
+ let effective = PVE.Utils.qemu_implicit_machine_version(
+ values.machine,
+ values.creationQemu,
+ values.arch,
+ );
+ me.getViewModel().set({
+ effectiveVersionLabel: effective + ' ' + gettext('(implicit)'),
+ implicitVersion: true,
+ });
+ me.setAdvancedVisible(true);
+ // flush the binding, then re-baseline the reset value to it
+ // otherwise the Reset button reverts to the field's empty initial value
+ me.getViewModel().notify();
+ me.lookup('effectiveVersion').resetOriginalValue();
}
}
@@ -176,6 +189,24 @@ Ext.define('PVE.qemu.MachineInputPanel', {
},
},
},
+ {
+ xtype: 'displayfield',
+ fieldLabel: gettext('Current Version'),
+ reference: 'effectiveVersion',
+ bind: {
+ value: '{effectiveVersionLabel}',
+ hidden: '{!implicitVersion}',
+ },
+ },
+ {
+ xtype: 'displayfield',
+ userCls: 'pmx-hint',
+ value: gettext(
+ 'No fixed version is set; the version is chosen automatically based on when the VM' +
+ ' was created. Pinning a specific version is recommended.',
+ ),
+ bind: { hidden: '{!implicitVersion}' },
+ },
{
xtype: 'displayfield',
fieldLabel: gettext('Note'),
@@ -249,6 +280,11 @@ Ext.define('PVE.qemu.MachineEdit', {
};
values.isWindows = PVE.Utils.is_windows(conf.ostype);
values.arch = PVE.qemu.Architecture.getGuestArchitecture(conf.arch, me.nodename);
+ if (conf.meta) {
+ let meta = PVE.Parser.parsePropertyString(conf.meta);
+ values.creationQemu = meta['creation-qemu'];
+ }
+
me.setValues(values);
},
});
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH manager v2] fix #7896: ui: qemu: show effective machine version for Windows guests
2026-08-24 13:01 [PATCH manager v2] fix #7896: ui: qemu: show effective machine version for Windows guests Jakob Klocker
@ 2026-08-26 8:36 ` Dominik Csapak
2026-08-31 7:11 ` Jakob Klocker
2026-08-31 9:48 ` superseded: " Jakob Klocker
1 sibling, 1 reply; 6+ messages in thread
From: Dominik Csapak @ 2026-08-26 8:36 UTC (permalink / raw)
To: Jakob Klocker, pve-devel
one comment inline
On 8/24/26 3:01 PM, Jakob Klocker wrote:
[snip]
> q35: (get) => get('type') === 'q35',
> @@ -102,10 +104,21 @@ Ext.define('PVE.qemu.MachineInputPanel', {
> }
>
> if (me.isWindows) {
> - if (values.machine === '__default__') {
> - values.version = 'pc-i440fx-5.1';
> - } else if (values.machine === 'q35') {
> - values.version = 'pc-q35-5.1';
> + if (values.machine === '__default__' || values.machine === 'q35') {
> + let effective = PVE.Utils.qemu_implicit_machine_version(
> + values.machine,
> + values.creationQemu,
> + values.arch,
> + );
> + me.getViewModel().set({
> + effectiveVersionLabel: effective + ' ' + gettext('(implicit)'),
> + implicitVersion: true,
> + });
> + me.setAdvancedVisible(true);
> + // flush the binding, then re-baseline the reset value to it
> + // otherwise the Reset button reverts to the field's empty initial value
> + me.getViewModel().notify();
> + me.lookup('effectiveVersion').resetOriginalValue();
under which circumstances is this necessary?
even with those two statements deleted, i can't trigger it to have
the reset button enabled?
in general, we probably shouldn't mess with the 'resetOriginalValue' too
much, but if we do, having the steps where this is necessary
would be good (does not have to be a comment, in the commit message is
fine for me)
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH manager v2] fix #7896: ui: qemu: show effective machine version for Windows guests
2026-08-26 8:36 ` Dominik Csapak
@ 2026-08-31 7:11 ` Jakob Klocker
2026-08-31 8:03 ` Dominik Csapak
0 siblings, 1 reply; 6+ messages in thread
From: Jakob Klocker @ 2026-08-31 7:11 UTC (permalink / raw)
To: Dominik Csapak, pve-devel
On Wed Aug 26, 2026 at 10:36 AM CEST, Dominik Csapak wrote:
> one comment inline
>
> On 8/24/26 3:01 PM, Jakob Klocker wrote:
> [snip]
>> q35: (get) => get('type') === 'q35',
>> @@ -102,10 +104,21 @@ Ext.define('PVE.qemu.MachineInputPanel', {
>> }
>>
>> if (me.isWindows) {
>> - if (values.machine === '__default__') {
>> - values.version = 'pc-i440fx-5.1';
>> - } else if (values.machine === 'q35') {
>> - values.version = 'pc-q35-5.1';
>> + if (values.machine === '__default__' || values.machine === 'q35') {
>> + let effective = PVE.Utils.qemu_implicit_machine_version(
>> + values.machine,
>> + values.creationQemu,
>> + values.arch,
>> + );
>> + me.getViewModel().set({
>> + effectiveVersionLabel: effective + ' ' + gettext('(implicit)'),
>> + implicitVersion: true,
>> + });
>> + me.setAdvancedVisible(true);
>
>
>> + // flush the binding, then re-baseline the reset value to it
>> + // otherwise the Reset button reverts to the field's empty initial value
>> + me.getViewModel().notify();
>> + me.lookup('effectiveVersion').resetOriginalValue();
>
> under which circumstances is this necessary?
>
> even with those two statements deleted, i can't trigger it to have
> the reset button enabled?
>
> in general, we probably shouldn't mess with the 'resetOriginalValue' too
> much, but if we do, having the steps where this is necessary
> would be good (does not have to be a comment, in the commit message is
> fine for me)
Than for taking a look at the patch.
I'm not quite sure what you mean with 'reset button enabled'. The reset
button enables just like in other UI forms; in the Machine case that's
when you select a different value in the dropdowns (e.g. change
`Machine`, `Version` or `vIOMMU`). I'm talking about the
`Reset from Data` button on the top right.
The `resetOriginalValue` is necessary because the
`effectiveVersionLabel` value is empty on page load, and only gets set
when `setValues` is called. Since `setValues` is not called on a reset,
this would display an empty current version on a reset. Therefore I
replace the field's empty initial value with the actual current version
on page load, so a reset reverts to the correct value instead of an
empty one.
I thought adding the comment above the code, saying that on reset the
value is empty made this clear -- if not, I can mention why exactly I
used this in the commit message as well.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH manager v2] fix #7896: ui: qemu: show effective machine version for Windows guests
2026-08-31 7:11 ` Jakob Klocker
@ 2026-08-31 8:03 ` Dominik Csapak
2026-08-31 8:42 ` Jakob Klocker
0 siblings, 1 reply; 6+ messages in thread
From: Dominik Csapak @ 2026-08-31 8:03 UTC (permalink / raw)
To: Jakob Klocker, pve-devel
On 8/31/26 9:11 AM, Jakob Klocker wrote:
> On Wed Aug 26, 2026 at 10:36 AM CEST, Dominik Csapak wrote:
>> one comment inline
>>
>> On 8/24/26 3:01 PM, Jakob Klocker wrote:
>> [snip]
>>> q35: (get) => get('type') === 'q35',
>>> @@ -102,10 +104,21 @@ Ext.define('PVE.qemu.MachineInputPanel', {
>>> }
>>>
>>> if (me.isWindows) {
>>> - if (values.machine === '__default__') {
>>> - values.version = 'pc-i440fx-5.1';
>>> - } else if (values.machine === 'q35') {
>>> - values.version = 'pc-q35-5.1';
>>> + if (values.machine === '__default__' || values.machine === 'q35') {
>>> + let effective = PVE.Utils.qemu_implicit_machine_version(
>>> + values.machine,
>>> + values.creationQemu,
>>> + values.arch,
>>> + );
>>> + me.getViewModel().set({
>>> + effectiveVersionLabel: effective + ' ' + gettext('(implicit)'),
>>> + implicitVersion: true,
>>> + });
>>> + me.setAdvancedVisible(true);
>>
>>
>>> + // flush the binding, then re-baseline the reset value to it
>>> + // otherwise the Reset button reverts to the field's empty initial value
>>> + me.getViewModel().notify();
>>> + me.lookup('effectiveVersion').resetOriginalValue();
>>
>> under which circumstances is this necessary?
>>
>> even with those two statements deleted, i can't trigger it to have
>> the reset button enabled?
>>
>> in general, we probably shouldn't mess with the 'resetOriginalValue' too
>> much, but if we do, having the steps where this is necessary
>> would be good (does not have to be a comment, in the commit message is
>> fine for me)
> Than for taking a look at the patch.
>
> I'm not quite sure what you mean with 'reset button enabled'. The reset
> button enables just like in other UI forms; in the Machine case that's
> when you select a different value in the dropdowns (e.g. change
> `Machine`, `Version` or `vIOMMU`). I'm talking about the
> `Reset from Data` button on the top right.
>
> The `resetOriginalValue` is necessary because the
> `effectiveVersionLabel` value is empty on page load, and only gets set
> when `setValues` is called. Since `setValues` is not called on a reset,
> this would display an empty current version on a reset. Therefore I
> replace the field's empty initial value with the actual current version
> on page load, so a reset reverts to the correct value instead of an
> empty one.
>
> I thought adding the comment above the code, saying that on reset the
> value is empty made this clear -- if not, I can mention why exactly I
> used this in the commit message as well.
ok i misunderstood what you meant from the comment, i get it now and
could reproduce the misbehavior with the lines deleted.
(i simply looked for a different thing)
there is a much easier method instead of manipulating the value itself
and notifying the viewmodel:
since both the effectiveVersion field and the hint are only modified
once, we don't need to use the viewmodel here at all?
just have the field value set via the normal 'value' object
but set 'submitValue: false' so it does not get submitted on
clicking ok. (the setValue parent handler then calls resetOriginal value
anyway)
same for the hint, we can show/hide it in the setValue method, but
don't have to use the viewmodel for it.
In general the viewmodel is only really helpful if we change their
values dynamically while the user has the editor open
which isn't the case for the 'setValue' method (this is only
called once on opening)
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH manager v2] fix #7896: ui: qemu: show effective machine version for Windows guests
2026-08-31 8:03 ` Dominik Csapak
@ 2026-08-31 8:42 ` Jakob Klocker
0 siblings, 0 replies; 6+ messages in thread
From: Jakob Klocker @ 2026-08-31 8:42 UTC (permalink / raw)
To: Dominik Csapak, pve-devel
On Mon Aug 31, 2026 at 10:03 AM CEST, Dominik Csapak wrote:
> ok i misunderstood what you meant from the comment, i get it now and
> could reproduce the misbehavior with the lines deleted.
> (i simply looked for a different thing)
>
> there is a much easier method instead of manipulating the value itself
> and notifying the viewmodel:
>
> since both the effectiveVersion field and the hint are only modified
> once, we don't need to use the viewmodel here at all?
>
> just have the field value set via the normal 'value' object
> but set 'submitValue: false' so it does not get submitted on
> clicking ok. (the setValue parent handler then calls resetOriginal value
> anyway)
>
> same for the hint, we can show/hide it in the setValue method, but
> don't have to use the viewmodel for it.
>
> In general the viewmodel is only really helpful if we change their
> values dynamically while the user has the editor open
> which isn't the case for the 'setValue' method (this is only
> called once on opening)
Thanks for the detailed explanation, makes a lot more sense
implementing it that way! As you mentioned, viewmodel isn't necessary
here -- not sure why I opted for it. I'll send a revision using the
'value' approach.
^ permalink raw reply [flat|nested] 6+ messages in thread
* superseded: [PATCH manager v2] fix #7896: ui: qemu: show effective machine version for Windows guests
2026-08-24 13:01 [PATCH manager v2] fix #7896: ui: qemu: show effective machine version for Windows guests Jakob Klocker
2026-08-26 8:36 ` Dominik Csapak
@ 2026-08-31 9:48 ` Jakob Klocker
1 sibling, 0 replies; 6+ messages in thread
From: Jakob Klocker @ 2026-08-31 9:48 UTC (permalink / raw)
To: Jakob Klocker, pve-devel
Superseded-by: https://lore.proxmox.com/all/20260831094644.137848-1-j.klocker@proxmox.com/T/#u
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-08-31 9:48 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-24 13:01 [PATCH manager v2] fix #7896: ui: qemu: show effective machine version for Windows guests Jakob Klocker
2026-08-26 8:36 ` Dominik Csapak
2026-08-31 7:11 ` Jakob Klocker
2026-08-31 8:03 ` Dominik Csapak
2026-08-31 8:42 ` Jakob Klocker
2026-08-31 9:48 ` superseded: " Jakob Klocker
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.