public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [PATCH manager/qemu-server 0/2] fix #5032: sync guest time after restore from saved state
@ 2026-06-12 12:29 Jakob Klocker
  2026-06-12 12:29 ` [PATCH qemu-server 1/2] fix #5032: qemu: sync guest time on resume and snapshot of " Jakob Klocker
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Jakob Klocker @ 2026-06-12 12:29 UTC (permalink / raw)
  To: pve-devel; +Cc: Jakob Klocker

This series adds a new agent option set-time-on-resume to 
automatically synchronize the guest clock via the QEMU Guest Agent 
after operations that can leave the guest time stale. The option is 
enabled by default when the QEMU Guest Agent is configured.

When a VM is restored from a saved state (hibernation or snapshot with
RAM), the guest clock continues from the point the state was saved and
no longer matches wall-clock time. The same skew can appear after
creating a snapshot of a running VM. For guests whose OS does not
correct this on its own, the drift persists until the next NTP sync (if
any), which can cause problems for time-sensitive workloads.

This series introduces the set-time-on-resume agent option and triggers
a guest-set-time call:
 * after restoring a VM from a saved state or snapshot with RAM
 * after taking a snapshot

The option is exposed in the VM configuration GUI so it can be toggled
per guest.

This series depends on [0] being applied first.

[0] https://lore.proxmox.com/pve-devel/20260612100758.116697-1-j.klocker@proxmox.com/T/#u

Link: https://bugzilla.proxmox.com/show_bug.cgi?id=5032


qemu-server:

Jakob Klocker (1):
  fix #5032: qemu: sync guest time on resume and snapshot of saved state

 src/PVE/QemuConfig.pm       |  7 ++++++
 src/PVE/QemuServer.pm       | 10 ++++++++
 src/PVE/QemuServer/Agent.pm | 47 +++++++++++++++++++++++++++++++++++++
 3 files changed, 64 insertions(+)


pve-manager:

Jakob Klocker (1):
  fix #5032: ui: qemu agent: add set-time-on-resume option

 www/manager6/Utils.js                     |  2 ++
 www/manager6/form/AgentFeatureSelector.js | 18 ++++++++++++++++++
 2 files changed, 20 insertions(+)


Summary over all repositories:
  5 files changed, 84 insertions(+), 0 deletions(-)

-- 
Generated by murpp 0.12.0



^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH qemu-server 1/2] fix #5032: qemu: sync guest time on resume and snapshot of saved state
  2026-06-12 12:29 [PATCH manager/qemu-server 0/2] fix #5032: sync guest time after restore from saved state Jakob Klocker
@ 2026-06-12 12:29 ` Jakob Klocker
  2026-06-18 12:36   ` Arthur Bied-Charreton
  2026-06-12 12:29 ` [PATCH pve-manager 2/2] fix #5032: ui: qemu agent: add set-time-on-resume option Jakob Klocker
  2026-06-18 12:35 ` [PATCH manager/qemu-server 0/2] fix #5032: sync guest time after restore from saved state Arthur Bied-Charreton
  2 siblings, 1 reply; 6+ messages in thread
From: Jakob Klocker @ 2026-06-12 12:29 UTC (permalink / raw)
  To: pve-devel; +Cc: Jakob Klocker

When a VM is resumed from a saved state (hibernation or snapshot with
RAM), the guest clock may be stale. A time skew can occur when
creating a snapshot of a running VM.

Add a new agent option `set-time-on-resume` to automatically
synchronize the guest time with the host using the QEMU Guest Agent.

Trigger time synchronization:
- after restoring a VM from a saved state or snapshot with RAM
- after taking a snapshot

This ensures consistent guest time after rollback, restore, or
snapshot operations when the guest OS clock does not automatically
correct itself.

Link: https://bugzilla.proxmox.com/show_bug.cgi?id=5032

Signed-off-by: Jakob Klocker <j.klocker@proxmox.com>
---
 src/PVE/QemuConfig.pm       |  7 ++++++
 src/PVE/QemuServer.pm       | 10 ++++++++
 src/PVE/QemuServer/Agent.pm | 47 +++++++++++++++++++++++++++++++++++++
 3 files changed, 64 insertions(+)

diff --git a/src/PVE/QemuConfig.pm b/src/PVE/QemuConfig.pm
index 80a3999e..1950c328 100644
--- a/src/PVE/QemuConfig.pm
+++ b/src/PVE/QemuConfig.pm
@@ -383,6 +383,13 @@ sub __snapshot_create_vol_snapshots_hook {
                     next;
                 }
             }
+            if ($snap->{vmstate}) {
+                my $conf = $class->load_config($vmid);
+                if (PVE::QemuServer::Agent::should_set_time_on_resume($conf->{agent})) {
+                    eval { PVE::QemuServer::Agent::guest_set_time($vmid); 1 }
+                        or warn "could not sync guest time after snapshot - $@";
+                }
+            }
         }
     }
 }
diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
index 239b0cab..99bdd9f5 100644
--- a/src/PVE/QemuServer.pm
+++ b/src/PVE/QemuServer.pm
@@ -5983,6 +5983,16 @@ sub vm_start_nolock {
         );
     }
 
+    my $from_saved_state = $resume || ($statefile && !$migratedfrom);
+
+    if (
+        $from_saved_state
+        && PVE::QemuServer::Agent::should_set_time_on_resume($conf->{agent})
+    ) {
+        eval { PVE::QemuServer::Agent::guest_set_time($vmid); 1 }
+            or warn "could not sync guest time after snapshot - $@";
+    }
+
     return $res;
 }
 
diff --git a/src/PVE/QemuServer/Agent.pm b/src/PVE/QemuServer/Agent.pm
index be6df443..be8bbae6 100644
--- a/src/PVE/QemuServer/Agent.pm
+++ b/src/PVE/QemuServer/Agent.pm
@@ -4,6 +4,7 @@ use v5.36;
 
 use JSON;
 use MIME::Base64 qw(decode_base64 encode_base64);
+use Time::HiRes ();
 
 use PVE::JSONSchema;
 
@@ -18,6 +19,8 @@ our @EXPORT_OK = qw(
     get_qga_key
     parse_guest_agent
     qga_check_running
+    should_set_time_on_resume
+    guest_set_time
 );
 
 our $agent_fmt = {
@@ -52,6 +55,21 @@ our $agent_fmt = {
         optional => 1,
         default => 1,
     },
+    'set-time-on-resume' => {
+        description => "Update the guest clock through QGA after resuming from"
+            . " hibernation or rolling back to a snapshot with RAM.",
+        verbose_description =>
+            "Whether to issue the guest-set-time QEMU guest agent command after the VM"
+            . " resumes with a restored RAM state, that is, when waking from hibernation"
+            . " or after rolling back to a snapshot that includes RAM. In these cases the"
+            . " guest's clock still reflects the time the state was saved. With this"
+            . " option enabled, the clock is synchronized to the host's current time,"
+            . " provided the QEMU Guest Agent option is enabled in the guest's"
+            . " configuration and the agent is running inside of the guest.",
+        type => 'boolean',
+        optional => 1,
+        default => 1,
+    },
     type => {
         description => "Select the agent type",
         type => 'string',
@@ -332,4 +350,33 @@ sub guest_fs_freeze_applicable($agent_str, $vmid, $logfunc = undef) {
     return 1;
 }
 
+=head3 should_set_time_on_resume
+
+Returns whether the guest's clock should be synchronized to the host's via the QEMU Guest Agent
+when the VM is resumed from saved state. Does B<not> check whether the agent is actually running.
+
+=cut
+
+sub should_set_time_on_resume($agent_str) {
+    my $agent = parse_guest_agent($agent_str);
+    return 0 if !$agent->{enabled};
+    return $agent->{'set-time-on-resume'} // 1;
+}
+
+=head3 guest_set_time
+
+Sets the guest's clock via the QEMU Guest Agent's C<guest-set-time> command. If C<$time_ns>
+(nanoseconds since the UNIX epoch, UTC) is not given, the current host time is used. Passing
+an explicit time is required because the agent's argument-less form reads the guest's RTC,
+which may itself be stale after a vmstate snapshot or resume.
+
+=cut
+
+sub guest_set_time($vmid, $time_ns = undef) {
+    $time_ns //= int(Time::HiRes::time() * 1_000_000_000);
+    my $res = PVE::QemuServer::Monitor::mon_cmd($vmid, 'guest-set-time', time => $time_ns);
+    check_agent_error($res, "unable to set guest time");
+    return;
+}
+
 1;
-- 
2.47.3




^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH pve-manager 2/2] fix #5032: ui: qemu agent: add set-time-on-resume option
  2026-06-12 12:29 [PATCH manager/qemu-server 0/2] fix #5032: sync guest time after restore from saved state Jakob Klocker
  2026-06-12 12:29 ` [PATCH qemu-server 1/2] fix #5032: qemu: sync guest time on resume and snapshot of " Jakob Klocker
@ 2026-06-12 12:29 ` Jakob Klocker
  2026-06-18 12:36   ` Arthur Bied-Charreton
  2026-06-18 12:35 ` [PATCH manager/qemu-server 0/2] fix #5032: sync guest time after restore from saved state Arthur Bied-Charreton
  2 siblings, 1 reply; 6+ messages in thread
From: Jakob Klocker @ 2026-06-12 12:29 UTC (permalink / raw)
  To: pve-devel; +Cc: Jakob Klocker

Expose the new agent configuration option `set-time-on-resume`
in the VM configuration GUI.

This allows enabling/disabling automatic guest clock
synchronization after resume from saved state or snapshot
restore with RAM.

Link: https://bugzilla.proxmox.com/show_bug.cgi?id=5032
Signed-off-by: Jakob Klocker <j.klocker@proxmox.com>
---
 www/manager6/Utils.js                     |  2 ++
 www/manager6/form/AgentFeatureSelector.js | 18 ++++++++++++++++++
 2 files changed, 20 insertions(+)

diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index 2ed4e65d..ee55a6ac 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -523,6 +523,8 @@ Ext.define('PVE.Utils', {
                     continue;
                 } else if (key === 'freeze-fs' && PVE.Parser.parseBoolean(value)) {
                     continue;
+                } else if (key === 'set-time-on-resume' && PVE.Parser.parseBoolean(value)) {
+                    continue;
                 } else if (PVE.Parser.parseBoolean(value)) {
                     displayText = Proxmox.Utils.enabledText;
                 }
diff --git a/www/manager6/form/AgentFeatureSelector.js b/www/manager6/form/AgentFeatureSelector.js
index 3cae4194..ba21a383 100644
--- a/www/manager6/form/AgentFeatureSelector.js
+++ b/www/manager6/form/AgentFeatureSelector.js
@@ -45,6 +45,18 @@ Ext.define('PVE.form.AgentFeatureSelector', {
                 hidden: '{freeze_fs.checked}',
             },
         },
+        {
+            xtype: 'proxmoxcheckbox',
+            boxLabel: gettext('Set guest clock to host after resume from saved state'),
+            name: 'set-time-on-resume',
+            reference: 'set_time_on_resume',
+            bind: {
+                disabled: '{!enabled.checked}',
+            },
+            disabled: true,
+            uncheckedValue: '0',
+            defaultValue: '1',
+        },
         {
             xtype: 'displayfield',
             userCls: 'pmx-hint',
@@ -74,6 +86,9 @@ Ext.define('PVE.form.AgentFeatureSelector', {
         if (PVE.Parser.parseBoolean(values['freeze-fs'])) {
             delete values['freeze-fs'];
         }
+        if (PVE.Parser.parseBoolean(values['set-time-on-resume'])) {
+            delete values['set-time-on-resume'];
+        }
 
         const agentstr = PVE.Parser.printPropertyString(values, 'enabled');
         return { agent: agentstr };
@@ -90,6 +105,9 @@ Ext.define('PVE.form.AgentFeatureSelector', {
         if (!Ext.isDefined(res['freeze-fs'])) {
             res['freeze-fs'] = 1;
         }
+        if (!Ext.isDefined(res['set-time-on-resume'])) {
+            res['set-time-on-resume'] = 1;
+        }
 
         this.callParent([res]);
     },
-- 
2.47.3




^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH manager/qemu-server 0/2] fix #5032: sync guest time after restore from saved state
  2026-06-12 12:29 [PATCH manager/qemu-server 0/2] fix #5032: sync guest time after restore from saved state Jakob Klocker
  2026-06-12 12:29 ` [PATCH qemu-server 1/2] fix #5032: qemu: sync guest time on resume and snapshot of " Jakob Klocker
  2026-06-12 12:29 ` [PATCH pve-manager 2/2] fix #5032: ui: qemu agent: add set-time-on-resume option Jakob Klocker
@ 2026-06-18 12:35 ` Arthur Bied-Charreton
  2 siblings, 0 replies; 6+ messages in thread
From: Arthur Bied-Charreton @ 2026-06-18 12:35 UTC (permalink / raw)
  To: Jakob Klocker; +Cc: pve-devel

On Fri, Jun 12, 2026 at 02:29:40PM +0200, Jakob Klocker wrote:
> This series adds a new agent option set-time-on-resume to 
> automatically synchronize the guest clock via the QEMU Guest Agent 
> after operations that can leave the guest time stale. The option is 
> enabled by default when the QEMU Guest Agent is configured.
> 
> When a VM is restored from a saved state (hibernation or snapshot with
> RAM), the guest clock continues from the point the state was saved and
> no longer matches wall-clock time. The same skew can appear after
> creating a snapshot of a running VM. For guests whose OS does not
> correct this on its own, the drift persists until the next NTP sync (if
> any), which can cause problems for time-sensitive workloads.
> 
> This series introduces the set-time-on-resume agent option and triggers
> a guest-set-time call:
>  * after restoring a VM from a saved state or snapshot with RAM
>  * after taking a snapshot
> 
> The option is exposed in the VM configuration GUI so it can be toggled
> per guest.
> 
> This series depends on [0] being applied first.
> 
> [0] https://lore.proxmox.com/pve-devel/20260612100758.116697-1-j.klocker@proxmox.com/T/#u
> 
> Link: https://bugzilla.proxmox.com/show_bug.cgi?id=5032
> 
> 
> qemu-server:
> 
> Jakob Klocker (1):
>   fix #5032: qemu: sync guest time on resume and snapshot of saved state
> 
>  src/PVE/QemuConfig.pm       |  7 ++++++
>  src/PVE/QemuServer.pm       | 10 ++++++++
>  src/PVE/QemuServer/Agent.pm | 47 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 64 insertions(+)
> 
> 
> pve-manager:
> 
> Jakob Klocker (1):
>   fix #5032: ui: qemu agent: add set-time-on-resume option
> 
>  www/manager6/Utils.js                     |  2 ++
>  www/manager6/form/AgentFeatureSelector.js | 18 ++++++++++++++++++
>  2 files changed, 20 insertions(+)
> 
> 
> Summary over all repositories:
>   5 files changed, 84 insertions(+), 0 deletions(-)
> 
> -- 
> Generated by murpp 0.12.0
> 
I tested the two paths calling guest-set-time.

Skew after restore:

I set up a guest with kvm-clock & NTP enabled. I took a snapshot of it 
with RAM, waited a minute and rolled the VM back to the snapshot.

Before applying this series, I observed a transient clock skew on the VM
which was corrected shortly after. 

After applying, there was no observable clock skew. 

Skew after snapshot:

This was a bit trickier to test. I edited 
/sys/devices/system/clocksource/clocksource0/current_clocksource from
kvm-clock to tsc, however I was not able to observe any skew in the
guest after taking snapshots. I then added a sleep to pve-qemu to force
longer freezes during snapshots, still could not reproduce the skew.

I ended up just disabling NTP (`timedatectl set-ntp false`) in the 
guest and setting a wrong date with `date -s`. I then saw that, before
the patch, the time stayed wrong in the guest after a snapshot, whereas
after the patch, it was corrected by the guest-set-time command. 

Not very familiar with that part of the code, but FWIW the code looks 
good to me as well. Left two minor comments on the patches (not blockers)

Consider this series:

Reviewed-by: Arthur Bied-Charreton <a.bied-charreton@proxmox.com>
Tested-by: Arthur Bied-Charreton <a.bied-charreton@proxmox.com>





^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH qemu-server 1/2] fix #5032: qemu: sync guest time on resume and snapshot of saved state
  2026-06-12 12:29 ` [PATCH qemu-server 1/2] fix #5032: qemu: sync guest time on resume and snapshot of " Jakob Klocker
@ 2026-06-18 12:36   ` Arthur Bied-Charreton
  0 siblings, 0 replies; 6+ messages in thread
From: Arthur Bied-Charreton @ 2026-06-18 12:36 UTC (permalink / raw)
  To: Jakob Klocker; +Cc: pve-devel

On Fri, Jun 12, 2026 at 02:29:41PM +0200, Jakob Klocker wrote:

One comment inline, with that addressed consider this:

Reviewed-by: Arthur Bied-Charreton <a.bied-charreton@proxmox.com>
Tested-by: Arthur Bied-Charreton <a.bied-charreton@proxmox.com>

> When a VM is resumed from a saved state (hibernation or snapshot with
> RAM), the guest clock may be stale. A time skew can occur when
> creating a snapshot of a running VM.
> 
> Add a new agent option `set-time-on-resume` to automatically
> synchronize the guest time with the host using the QEMU Guest Agent.
> 
> Trigger time synchronization:
> - after restoring a VM from a saved state or snapshot with RAM
> - after taking a snapshot
> 
> This ensures consistent guest time after rollback, restore, or
> snapshot operations when the guest OS clock does not automatically
> correct itself.
> 
> Link: https://bugzilla.proxmox.com/show_bug.cgi?id=5032
> 
> Signed-off-by: Jakob Klocker <j.klocker@proxmox.com>
> ---
[...]
> diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
> index 239b0cab..99bdd9f5 100644
> --- a/src/PVE/QemuServer.pm
> +++ b/src/PVE/QemuServer.pm
> @@ -5983,6 +5983,16 @@ sub vm_start_nolock {
>          );
>      }
>  
> +    my $from_saved_state = $resume || ($statefile && !$migratedfrom);
> +
> +    if (
> +        $from_saved_state
> +        && PVE::QemuServer::Agent::should_set_time_on_resume($conf->{agent})
> +    ) {
> +        eval { PVE::QemuServer::Agent::guest_set_time($vmid); 1 }
> +            or warn "could not sync guest time after snapshot - $@";
> +    }
Since this is the resume path, it would make sense to adapt this 
warning message accordingly, would be less confusing and make it easier
to grep for the relevant code when seeing the line in the journal. 
> +
>      return $res;
>  }
[...]




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH pve-manager 2/2] fix #5032: ui: qemu agent: add set-time-on-resume option
  2026-06-12 12:29 ` [PATCH pve-manager 2/2] fix #5032: ui: qemu agent: add set-time-on-resume option Jakob Klocker
@ 2026-06-18 12:36   ` Arthur Bied-Charreton
  0 siblings, 0 replies; 6+ messages in thread
From: Arthur Bied-Charreton @ 2026-06-18 12:36 UTC (permalink / raw)
  To: Jakob Klocker; +Cc: pve-devel

On Fri, Jun 12, 2026 at 02:29:42PM +0200, Jakob Klocker wrote:

One nit inline

Reviewed-by: Arthur Bied-Charreton <a.bied-charreton@proxmox.com>
Tested-by: Arthur Bied-Charreton <a.bied-charreton@proxmox.com>

> Expose the new agent configuration option `set-time-on-resume`
> in the VM configuration GUI.
> 
> This allows enabling/disabling automatic guest clock
> synchronization after resume from saved state or snapshot
> restore with RAM.
> 
> Link: https://bugzilla.proxmox.com/show_bug.cgi?id=5032
> Signed-off-by: Jakob Klocker <j.klocker@proxmox.com>
> ---
>  www/manager6/Utils.js                     |  2 ++
>  www/manager6/form/AgentFeatureSelector.js | 18 ++++++++++++++++++
>  2 files changed, 20 insertions(+)
> 
> diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
> index 2ed4e65d..ee55a6ac 100644
> --- a/www/manager6/Utils.js
> +++ b/www/manager6/Utils.js
> @@ -523,6 +523,8 @@ Ext.define('PVE.Utils', {
>                      continue;
>                  } else if (key === 'freeze-fs' && PVE.Parser.parseBoolean(value)) {
>                      continue;
> +                } else if (key === 'set-time-on-resume' && PVE.Parser.parseBoolean(value)) {
> +                    continue;
>                  } else if (PVE.Parser.parseBoolean(value)) {
>                      displayText = Proxmox.Utils.enabledText;
>                  }
> diff --git a/www/manager6/form/AgentFeatureSelector.js b/www/manager6/form/AgentFeatureSelector.js
> index 3cae4194..ba21a383 100644
> --- a/www/manager6/form/AgentFeatureSelector.js
> +++ b/www/manager6/form/AgentFeatureSelector.js
> @@ -45,6 +45,18 @@ Ext.define('PVE.form.AgentFeatureSelector', {
>                  hidden: '{freeze_fs.checked}',
>              },
>          },
> +        {
> +            xtype: 'proxmoxcheckbox',
> +            boxLabel: gettext('Set guest clock to host after resume from saved state'),
nit: maybe "synchronize guest clock with the host's ..." would be
clearer here
> +            name: 'set-time-on-resume',
> +            reference: 'set_time_on_resume',
> +            bind: {
> +                disabled: '{!enabled.checked}',
> +            },
> +            disabled: true,
> +            uncheckedValue: '0',
> +            defaultValue: '1',
> +        },
>          {
>              xtype: 'displayfield',
>              userCls: 'pmx-hint',
> @@ -74,6 +86,9 @@ Ext.define('PVE.form.AgentFeatureSelector', {
>          if (PVE.Parser.parseBoolean(values['freeze-fs'])) {
>              delete values['freeze-fs'];
>          }
> +        if (PVE.Parser.parseBoolean(values['set-time-on-resume'])) {
> +            delete values['set-time-on-resume'];
> +        }
>  
>          const agentstr = PVE.Parser.printPropertyString(values, 'enabled');
>          return { agent: agentstr };
> @@ -90,6 +105,9 @@ Ext.define('PVE.form.AgentFeatureSelector', {
>          if (!Ext.isDefined(res['freeze-fs'])) {
>              res['freeze-fs'] = 1;
>          }
> +        if (!Ext.isDefined(res['set-time-on-resume'])) {
> +            res['set-time-on-resume'] = 1;
> +        }
>  
>          this.callParent([res]);
>      },
> -- 
> 2.47.3
> 
> 
> 
> 




^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-06-18 12:36 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-12 12:29 [PATCH manager/qemu-server 0/2] fix #5032: sync guest time after restore from saved state Jakob Klocker
2026-06-12 12:29 ` [PATCH qemu-server 1/2] fix #5032: qemu: sync guest time on resume and snapshot of " Jakob Klocker
2026-06-18 12:36   ` Arthur Bied-Charreton
2026-06-12 12:29 ` [PATCH pve-manager 2/2] fix #5032: ui: qemu agent: add set-time-on-resume option Jakob Klocker
2026-06-18 12:36   ` Arthur Bied-Charreton
2026-06-18 12:35 ` [PATCH manager/qemu-server 0/2] fix #5032: sync guest time after restore from saved state Arthur Bied-Charreton

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