Skip to content

Sync guest realtime clock after standby restore#301

Closed
yummybomb wants to merge 4 commits into
mainfrom
hypeship/sync-guest-clock-after-restore
Closed

Sync guest realtime clock after standby restore#301
yummybomb wants to merge 4 commits into
mainfrom
hypeship/sync-guest-clock-after-restore

Conversation

@yummybomb

Copy link
Copy Markdown
Contributor

Summary

After a snapshot restore, the guest wall clock resumes from the moment the snapshot was saved — Firecracker does not advance CLOCK_REALTIME on restore, and nothing in the guest resyncs it. Every in-guest timestamp (telemetry events, logs, recordings) therefore lags real time by however long the instance sat in standby.

This adds a clock resync to the restore path:

  • SyncClock guest-agent RPC (lib/guest/guest.proto, lib/system/guest_agent/clock.go): sets CLOCK_REALTIME to a host-provided wall-clock time via clock_settime(2).
  • Host client (lib/guest/clock.go): SyncClockInInstance with the same wait-for-agent retry behavior as ReconfigureNetworkInInstance. The host timestamp is captured per attempt so a long agent wait isn't baked into the guest clock.
  • Restore wiring (lib/instances/restore.go): after resume, sync the clock (gated on SkipGuestAgent). Non-fatal — a skewed clock degrades timestamps, not the VM, so failure logs a warning instead of failing the restore.
  • Exec fallback: instances already in standby when this ships still run the old agent binary from their snapshot and return Unimplemented; those get date -u -s @<epoch> via the existing exec path, mirroring the network-reconfigure fallback.

A discontinuous step (rather than slewing) is intentional: the skew accrues while the VM is paused pre-claim, so nothing in the guest observes the jump, and slewing would take hours to absorb multi-minute offsets.

Generated files (guest.pb.go, guest_grpc.pb.go) were regenerated with make generate-grpc (protoc 33.4, plugin versions from go.mod).

Testing

  • go build / go vet on lib/guest, lib/instances, lib/system/guest_agent — clean
  • go test ./lib/system/guest_agent ./lib/guest — pass (includes new SyncClock input-validation test)
  • guest-agent cross-compiles for linux via the Makefile target
  • make test TEST=TestStandbyAndRestore could not complete in my environment: the test fails in setup (test image never reaches "ready" within its 60s window), before any restore code runs. The end-to-end behavior (clock actually stepped after restore, plus the exec fallback against an old-agent snapshot) still needs verification on real infrastructure.

Follow-ups (not in this PR)

  • Ongoing drift on long-lived sessions would need kvm-ptp + chrony in guest images; this PR only corrects the restore-time step.
  • Worth checking whether other VM wake paths need the same treatment.

🤖 Generated with Claude Code

yummybomb and others added 4 commits July 8, 2026 14:14
The guest wall clock resumes from the snapshot's saved time after a
restore, so every in-guest timestamp lags by the time spent in standby
until corrected. Add a SyncClock guest-agent RPC that sets
CLOCK_REALTIME to the host's current time, and call it from the restore
path once the VM resumes. Instances whose snapshots predate the new
agent binary fall back to setting the clock via exec.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
unix.ClockSettime does not exist on darwin, which broke test-darwin
compiling the guest_agent package. The shipped agent binary is
linux-only; non-linux builds get an error stub.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Clock sync is non-fatal and runs on every restore, so an unresponsive
agent should cost seconds of restore latency, not the 120s the fatal
fork-only network reconfigure path tolerates. The agent was running at
snapshot time and is reachable almost immediately after resume, so the
short wait covers the happy path. This also bounds how stale the
timestamp baked into the exec fallback command can get.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
TestStandbyAndRestore now sleeps 10s in standby and asserts the guest
clock does not lag after restore, and exercises the exec fallback by
skewing the guest clock back an hour and syncing it via
syncGuestClockWithExec. Without the restore-time SyncClock the guest
lags by the full standby duration and the assertion fails.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@yummybomb yummybomb closed this Jul 8, 2026
@yummybomb yummybomb reopened this Jul 8, 2026
@yummybomb yummybomb closed this Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant