Skip to content

fix(snapshots): snapshot running VMs disk-only over QMP - #159

Merged
NovusEdge merged 2 commits into
mainfrom
qol/snapshots
Sep 29, 2026
Merged

NovusEdge merged 2 commits into
mainfrom
qol/snapshots

Conversation

@NovusEdge

Copy link
Copy Markdown
Owner

Snapshots of a running local VM failed because QEMU refuses savevm while the always-on work virtfs share is mounted. The share stays, since copy_to and copy_from depend on it.

  • A running VM now takes a disk-only internal snapshot with blockdev-snapshot-internal-sync on the qcow2 device found through query-block. It records no RAM and is crash-consistent; stoat has no guest agent to freeze filesystems. Delete uses blockdev-snapshot-delete-internal-sync. Command names and arguments checked against the QEMU 11.1 QMP reference.
  • Restore refuses a running VM (already_running, "stop the VM first (stoat down )"), because QEMU cannot revert a live disk.
  • Listing reads ImageInfo (qemu-img info --output=json when stopped, query-block when running). SIZE is the saved RAM state, so it shows "-" for disk-only snapshots. QEMU records no size for the disk part.
  • Wire: Snapshot has created (RFC 3339 UTC) and size_bytes; the display strings are removed. VM has shared_dir and shared_mount.
  • MCP: list_snapshots (read) and delete_snapshot (destructive, like restore). copy_to, copy_from and destroy descriptions name the shared directory; copy errors name the host path.
  • docs/reference/cli.md no longer shows a RAM=yes snapshot of a running VM.

Tests use a fake QMP socket and the real qemu-img on a scratch qcow2; no VM is booted. Live verification is still needed on a running VM.

savevm is refused while the always-on work virtfs share is mounted, so
stoat snapshot failed on every running local VM. A running VM now gets
an internal qcow2 snapshot via blockdev-snapshot-internal-sync, with no
RAM, and it is crash-consistent. Delete uses the matching QMP command.
Restore refuses a running VM with already_running and "stop the VM
first". Listing reads structured ImageInfo (qemu-img info JSON or QMP
query-block) instead of scraping the text table.

Wire: Snapshot gets created (RFC 3339 UTC) and size_bytes in place of
the display strings. VM gets shared_dir and shared_mount. MCP gets
list_snapshots and delete_snapshot; copy_to, copy_from and destroy name
the shared directory.

Signed-off-by: NovusEdge <novusedge0@gmail.com>
@coderabbitai

coderabbitai Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 28 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: d6b3a53b-1c10-4fe4-88c4-9fdb9fa58118

📥 Commits

Reviewing files that changed from the base of the PR and between ba413a3 and 5f56d03.

📒 Files selected for processing (18)
  • docs/reference/cli.md
  • docs/reference/json.md
  • docs/reference/mcp.md
  • internal/cli/display_test.go
  • internal/cli/run_state.go
  • internal/cli/wire/dto.go
  • internal/cli/wire/dto_test.go
  • internal/core/snapshot.go
  • internal/core/snapshot_test.go
  • internal/core/vm.go
  • internal/mcpsrv/redact_test.go
  • internal/mcpsrv/table_test.go
  • internal/mcpsrv/tools_guest.go
  • internal/mcpsrv/tools_vm.go
  • internal/qemu/qmp.go
  • internal/qemu/qmp_test.go
  • internal/tui/snapshots.go
  • internal/tui/snapshots_test.go

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Removing size_display and created_display breaks contract 3. They stay next to size_bytes and created, and the docs mark them deprecated.

Signed-off-by: NovusEdge <novusedge0@gmail.com>
@NovusEdge
NovusEdge merged commit 71c5eef into main Sep 29, 2026
8 of 9 checks passed
@NovusEdge
NovusEdge deleted the qol/snapshots branch September 29, 2026 18:28
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