Repository navigation
openvmm: pin the refusal of earlier snapshot formats by their version - #1417
Merged
Pedro Henrique Penna (ppenna) merged 3 commits intoNov 9, 2026
Merged
Conversation
Restoring a snapshot of an earlier OpenVMM directly, with
`openvmm --restore-snapshot` or the management RPC, fails with a
decoding error rather than with E_SNAPSHOT_VERSION, which run.md
promises. Manifest version 6, which OpenVMM wrote until its v4 microVM
chain restarted the manifest at version 2, gives fields 11 and 13 other
types than version 2 does, and the first manifests of version 2 give
fields 9 and 10 other types, but restore decoded the whole manifest
before it checked the version and magic:
failed to decode snapshot manifest: decoding failed: expected a
varint
nvx-rs, which reads a template's manifest itself, already checks the
version and magic first, so only a direct restore was affected.
Pin microsoft/openvmm#4994, 98e5b3ca504ea18ffdcc7181e27516f7d7e5a6d7,
two commits on feature/microvm/dev ed8fc0713:
- openvmm_helpers: refuse earlier snapshot formats before decoding
them. Restore decodes the version alone, then the magic alone, and
refuses any other with E_SNAPSHOT_VERSION before it decodes the rest.
- openvmm_helpers: reserve the manifest fields that upstream assigns.
Upstream's SaveVM and RestoreVM (microsoft/openvmm#4553) moved their
snapshot ID from field 8, which this manifest gives to the length of
state.bin, to field 18, and reserve fields 19 and 20, which no field
of this manifest takes.
No field moves, so the format stays manifest version 2, and every
existing snapshot stays restorable. The protocol vectors and CPU
profiles that nvx-rs copies are unchanged.
On KVM and MSHV, on Azure Linux 3 virtual machines, and on WHP, on a
Windows virtual machine, a microVM snapshot that the OpenVMM of NVX
release v0.1.0-dev.304f8e1686b4 captured, of manifest version 6, which
that OpenVMM restores, fails to restore with the error above at the
previous pin, and with
[E_SNAPSHOT_VERSION] snapshot manifest version 6 is not supported
(expected 2); recapture the snapshot
at this one. With this pin, the snapshot-core, run-console-restore,
snapshot-tiers, scratch-snapshot, console-snapshot, filesystem-snapshot,
network-snapshot, smp-snapshot, restore-processors, restore-memory,
snapshot-rollback, restore-downtime, platform-restore-processors,
platform-zero-fill, platform-network-policy, untiered-network-policy,
and sandbox-blocks microVM scenarios pass on all three backends.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Snapshots of an earlier OpenVMM in run.md said that OpenVMM refuses their manifest by its version with E_SNAPSHOT_VERSION. Until the previous commit's pin, it did so only once it had decoded the whole manifest, which fails first for manifest version 6 and the first manifests of version 2, whose fields have other types than version 2 gives them. With the pin, OpenVMM decodes the version and then the format magic before the rest, so it refuses every earlier manifest with E_SNAPSHOT_VERSION: by its version, or, for the earliest manifests of version 2, which have no magic, by the magic that they lack. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Map positions 230 and 231, the two commits of microsoft/openvmm#4994, which NVX now pins at 98e5b3ca5, 100 commits past the mapped tip: - 230, openvmm_helpers: refuse earlier snapshot formats before decoding them. Restore decodes the manifest's version and then its magic, each alone, and refuses any other with E_SNAPSHOT_VERSION before it decodes the rest, since positions 195 and 205 restarted the manifest at version 2 and numbered its fields without gaps. - 231, openvmm_helpers: reserve the manifest fields that upstream assigns. A comment and the snapshot format guide keep fields 18-20 for upstream's SaveVM and RestoreVM. Both are unassigned, and neither is a fixup of a mapped PR: they change the manifest decoding and header check of PR11's position 031, which PR12's position 035 moves to the opened snapshot directory, and their tests use the machine contract of PR17's position 074. They conflict with upstream main in all four of their files, so they follow PR11, PR12, and PR17 upstream. Under the open upstream pull requests, note microsoft/openvmm#4553, which proposes no chain commit: it records its snapshot ID in field 18, moved from field 8 after #1210, and reserves fields 19 and 20, so a rebase onto it adds the field to the chain's manifest, and nvx-rs's template-manifest reader must accept it. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This was referenced Nov 9, 2026
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues were identified for the documentation updates covering snapshot-format rejection and the OpenVMM pin.
No open issues 🎉
What changed in this PR
Documents the OpenVMM pin update addressing earlier snapshot-format rejection from #1210, without changing the current manifest layout or invalidating current snapshots.
Changes:
- Clarifies that earlier manifests are rejected by version or missing format magic before full decoding.
- Maps the two new OpenVMM commits and their upstream dependencies.
- Records upstream’s reserved manifest fields and the future
snapshot_idintegration requirements.
| File | Description |
|---|---|
doc/run.md |
Clarifies early rejection and diagnostics for older snapshot formats. |
doc/openvmm-upstream-roadmap.md |
Updates the pin, commit mapping, and upstream manifest integration notes. |
Review effort: Balanced
Pedro Henrique Penna (ppenna)
deleted the
agents/issue-1210-manifest-alignment
branch
November 9, 2026 14:49
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #1210
What and why
#1210 asked to move the snapshot manifest's
state_size_bytesoff field 8,which upstream's SaveVM and RestoreVM (microsoft/openvmm#4553) had taken for
their snapshot ID, to bump the manifest's version, and to refuse NVX's version
6 manifests with an
E_SNAPSHOT_VERSIONrecapture diagnostic before decodingtheir integer field 8 as a GUID. Two things changed after it was filed:
snapshot_idto field 18 instead(reply),
and ttrpc: add SaveVM and RestoreVM APIs openvmm#4553's head reserves field 19 for
compatibility_bundle_digestand field 20 formemory_artifacts. That isthe case for which snapshot: align NVX manifest with upstream SaveVM/RestoreVM #1210 asked to reconcile the mapping first: rather than
give 18 to
state_size_bytes,state_size_byteskeeps field 8, and no fieldmoves.
the magic
OPENVMM_SNAPSHOT_V2\0, and numbered its fields 8-15 without gaps,so version 6 is an earlier format now.
So the manifest keeps version 2 and every field. The diagnostic that #1210
asked for was still missing, though, for a reason that the renumbering
created. Restore decoded the whole manifest (
decode_snapshot_manifestinopenvmm_helpers/src/snapshot/restore.rs) before it checked the version andmagic, and earlier formats give some field numbers other types, which
meshrefuses before any check runs: version 6 keeps its machine contract, a
message, in field 11, where version 2 keeps the saved-state schema version, a
varint, and the first manifests of version 2 keep artifact digests in fields 9
and 10, where version 2 now keeps its machine contract and magic. A version 6
snapshot that NVX release v0.1.0-dev.304f8e1686b4 captured therefore failed to
restore with
failed to decode snapshot manifest: decoding failed: expected a varint, rather than with theE_SNAPSHOT_VERSIONthatdoc/run.mdandOpenVMM's snapshot format guide promise.
nvx-rs, which reads a template'smanifest itself (
check_formatinnvx-rs/src/host/template/manifest.rs),already checks the version and magic first, so only direct restores were
affected:
openvmm --restore-snapshotand the management RPC's restore.microsoft/openvmm#4994, two commits on
ed8fc0713, the head offeature/microvm/dev:openvmm_helpers: refuse earlier snapshot formats before decoding themdecodes the version alone, field 1 in every format, upstream's included,
then the magic alone, field 10, whose type only the formats of version 2
agree on, and refuses any other with
[E_SNAPSHOT_VERSION] ... recapture the snapshotbefore it decodes the rest. This is the version-first decode thatsnapshot: align NVX manifest with upstream SaveVM/RestoreVM #1210 asked for, and it mirrors what
nvx-rs'scheck_formatdoes.openvmm_helpers: reserve the manifest fields that upstream assignskeepsfields 18, 19, and 20 free, in a comment where
SnapshotManifestdeclaresits fields and in the Guide's rule for extending the format.
Decisions:
of version 2 stay restorable, and snapshots of earlier releases need
recapture as before;
doc/run.mddocuments that, and no conversion orbackward-compatible restore is added.
reorganization gave them to the machine contract and the magic when it
restarted the manifest. Renumbering again would invalidate every current
snapshot for nothing: the version-then-magic check refuses the first
manifests of version 2, which used them for digests, by their missing magic
before it decodes those fields.
snapshot_idyet. ttrpc: add SaveVM and RestoreVM APIs openvmm#4553 is still open, so the chaindoes not take its field ahead of upstream; the roadmap now notes what a
rebase onto it needs.
Snapshot invalidation: this change invalidates no snapshot, so #1180's note
that #1210 changes the manifest's layout and version, and that other changes
that invalidate snapshots should land with it, no longer applies. Of the open
issues queued after it, #995 admits more tokens on a platform snapshot's
command line, which leaves existing snapshots valid (its new
CaptureClassencoding only retires
nvx-rs's existing templates, whichnvx-rscapturesagain), and #1361, #1364, #1373, #1154, #1157, and #565 only add checks or
reorder restore steps. The saved-state changes of #1182 (#1141, #1160, #1368,
#1158, #1161, #1169, #1369, #1171, #1359, and #1367, depending on its fix)
and #1184's #1163 can invalidate snapshots: they should share one compatibility
policy and one saved-state schema bump, as #1182's notes ask, so that
snapshots are recaptured once, and that batch should make a schema mismatch,
which
validate_manifest_headerreports today without a code, reportE_SNAPSHOT_VERSIONand ask for a recapture.Left open in #1210, once microsoft/openvmm#4553 merges and the chain rebases
onto it:
snapshot_id(field 18) in the chain'sSnapshotManifest,with upstream's policy for a missing ID (a zero GUID means none), and tests
of a manifest without an ID and with a malformed one;
nvx-rs's reader of a template's manifest,which refuses fields that it does not know, accept field 18.
Commits:
openvmm: pin the refusal of earlier snapshot formats by their versionmoves the gitlink from
ed8fc0713to98e5b3ca504ea18ffdcc7181e27516f7d7e5a6d7, the head of[DO NOT REVIEW] openvmm_helpers: refuse earlier snapshot formats before decoding them openvmm#4994. The protocol vectors and CPU profiles that
nvx-rscopies are unchanged.
doc: say that OpenVMM refuses earlier manifests before decoding themsaysin
doc/run.md's "Snapshots of an earlier OpenVMM" that OpenVMM refuses theearliest manifests of version 2 by their missing magic, and every earlier
manifest before it decodes the rest.
doc: map the refusal of earlier snapshot formats in the OpenVMM roadmapmaps positions 230 and 231, unassigned, 100 commits past the mapped tip,
with the mapped work that they change: the manifest decoding and header
check of PR11's position 031, which PR12's position 035 moves to the opened
snapshot directory, and their tests use the machine contract of PR17's
position 074. They conflict with upstream main in all four of their files,
so they follow PR11, PR12, and PR17 upstream. It also notes
ttrpc: add SaveVM and RestoreVM APIs openvmm#4553 under the open upstream pull requests.
98e5b3ca5is patch-equivalent toa851d870b, the same two commits on99aac19b3, which the first validation round below tested (identicalrange-diff).
OpenVMM's tests: two new tests in
openvmm_helpers::snapshot::restore, and nochange to an existing test. This pull request changes no NVX test.
Landing order: land microsoft/openvmm#4994 first, by fast-forwarding
feature/microvm/devto98e5b3ca504ea18ffdcc7181e27516f7d7e5a6d7(OpenVMM's merge button squashes, which would leave the pin off the branch);
then merge this pull request.
Validation
Reproduction, before and after:
read_snapshot_refuses_a_version_6_manifest_by_its_version99aac19b3: fails,expected a varint98e5b3ca5: passesread_snapshot_refuses_an_early_version_2_manifest_by_its_magic99aac19b3: fails,unknown wire type 398e5b3ca5: passesed8fc0713and99aac19b3:failed to decode snapshot manifest(expected a varint)98e5b3ca5anda851d870b:[E_SNAPSHOT_VERSION] snapshot manifest version 6 is not supported (expected 2); recapture the snapshotSnapshot scenarios, with OpenVMM built at the pin on each host
(
python3 scripts/nvx.py test-microvm --backend BACKEND --scenario ... --processors 1): snapshot-core, run-console-restore, snapshot-tiers,scratch-snapshot, console-snapshot, filesystem-snapshot, network-snapshot,
smp-snapshot, restore-processors, restore-memory, snapshot-rollback,
restore-downtime, platform-restore-processors, platform-zero-fill,
platform-network-policy, untiered-network-policy, and sandbox-blocks.
a851d870bThe guest artifacts were those of release v0.1.0-dev.da327b5bf6d1 on KVM and
MSHV, and of v0.1.0-dev.7714de16388c on WHP, whose guest inputs match this
head's.
OpenVMM package checks for
openvmm_helpersat98e5b3ca5: on Windows,cargo clippy --all-targets,cargo doc --no-deps, andcargo nextest run --profile agentpass (122 tests), andcargo xtask fmt --fixis clean; onLinux (Azure Linux 3.0, nvx-kvm-test), the same pass (128 tests).
NVX gates (
python3 scripts/local_gates.py --base origin/dev --run):test-changes,markdown-links,test-layout,openvmm-vectors, andopenvmm-cpu-profilespass on Windows; the Linuxnvx-cligate's tests passon nvx-kvm-test (2188 unit tests, 43 skipped, and 84 adversarial tests),
without its
pip installstep;openvmm-ciwaits for microsoft/openvmm#4994'sCI.
python3 scripts/openvmm_pin.py check-branch --topic,check-roadmap --worktree, andpython3 scripts/rebase_check.py verifypass.Left to CI: the full NVX matrix, including the hypervisor suites on the CI
runners, and OpenVMM's CI of the pin.