From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id CC6B71FF0EA for ; Thu, 13 Aug 2026 13:27:51 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id A16F9215F6; Thu, 13 Aug 2026 13:27:31 +0200 (CEST) From: Jakob Klocker To: pve-devel@lists.proxmox.com Subject: [PATCH qemu-server 2/6] fix #7213: config: add `powercycle` sub-property to `reboot` Date: Thu, 13 Aug 2026 13:27:13 +0200 Message-ID: <20260813112717.272254-3-j.klocker@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260813112717.272254-1-j.klocker@proxmox.com> References: <20260813112717.272254-1-j.klocker@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 1 AWL -0.538 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) KAM_LAZY_DOMAIN_SECURITY 1 Sending domain does not have any anti-forgery methods RDNS_NONE 1.274 Delivered to internal network by a host with no rDNS SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_NONE 0.001 SPF: sender does not publish an SPF Record Message-ID-Hash: 5FE5U2NXRF4ZJ7AIQNYCE2KLEOYTCXSZ X-Message-ID-Hash: 5FE5U2NXRF4ZJ7AIQNYCE2KLEOYTCXSZ X-MailFrom: jklocker@iris.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 CC: Jakob Klocker X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: A guest-initiated reboot is handled by QEMU itself, so the process keeps running and the VM stays on the configuration and QEMU binary it was started with. Pending changes therefore remain pending. With `powercycle` set, start the VM with `-no-reboot` so that QEMU exits on a reset instead. `qm cleanup` then starts the VM again, which makes it a full start and applies pending changes. Note that `-no-reboot` covers resets requested through the API as well, so those also become a full stop and start. Convert `reboot` to a property string to carry the new sub-property. Existing configurations stay valid, as the previous boolean value is the default key. Link: https://bugzilla.proxmox.com/show_bug.cgi?id=7213 Signed-off-by: Jakob Klocker --- src/PVE/QemuServer.pm | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm index 2f43faa7..1727f143 100644 --- a/src/PVE/QemuServer.pm +++ b/src/PVE/QemuServer.pm @@ -237,6 +237,27 @@ my $spice_enhancements_fmt = { }, }; +my $reboot_fmt = { + enabled => { + default_key => 1, + type => 'boolean', + default => 1, + optional => 1, + description => "Allow reboot. If set to '0' the VM is shut down instead of rebooted" + . " and stays off, no matter whether the reboot was initiated by the guest or" + . " through the API.", + }, + powercycle => { + type => 'boolean', + optional => 1, + default => 0, + description => "Stop and start the VM on a reset instead of resetting it in place, so" + . " pending changes are applied and the currently installed QEMU version is used." + . " Applies to resets initiated by the guest as well as through the API. Has no" + . " effect when reboot is disabled.", + }, +}; + my $confdesc = { onboot => { optional => 1, @@ -263,9 +284,9 @@ my $confdesc = { }, reboot => { optional => 1, - type => 'boolean', - description => "Allow reboot. If set to '0' the VM exit on reboot.", - default => 1, + type => 'string', + format => $reboot_fmt, + description => "Reboot behavior and its properties.", }, lock => { optional => 1, @@ -1694,6 +1715,16 @@ sub parse_vga { return $res; } +sub parse_reboot { + my ($value) = @_; + + return { enabled => 1 } if !defined($value) || $value eq ''; + + my $res = eval { parse_property_string($reboot_fmt, $value) }; + warn $@ if $@; + return $res // {}; +} + sub qemu_created_version_fixups { my ($conf, $forcemachine, $kvmver) = @_; @@ -3216,6 +3247,8 @@ sub config_to_command { push @$cmd, '-name', "$vmname,debug-threads=on"; } + my $reboot = parse_reboot($conf->{reboot}); + push @$cmd, '-no-reboot' if !($reboot->{enabled} // 1) || $reboot->{powercycle}; push @$cmd, '-no-shutdown'; my $use_virtio = 0; @@ -3400,8 +3433,6 @@ sub config_to_command { push $machineFlags->@*, 'acpi=off' if defined($conf->{acpi}) && $conf->{acpi} == 0; - push @$cmd, '-no-reboot' if defined($conf->{reboot}) && $conf->{reboot} == 0; - if ($vga->{type} && $vga->{type} !~ m/^serial\d+$/ && $vga->{type} ne 'none') { push @$devices, '-device', print_vga_device($conf, $vga, $arch, $machine_version, undef, $qxlnum, $bridges); -- 2.47.3