Repository navigation
nvx-rs, runtime-adapter: #845's VM scenarios (GPT clones, a used upper, generated machine IDs) - #961
Closed
Enrique Saurez (esaurez) wants to merge 3 commits into
Conversation
A clone's plan refused a GPT disk as its image before any VMM started: the kernel of a clone's guest had created the block devices of the partitions of the template's placeholder, and no clone rebuilt them. The guest of a GPT clone now asks the kernel to reread the disk's partition table before it assembles the root, so the plan takes a GPT disk as it takes an EROFS layer. The record of a GPT clone names the disk: the identity of its binding, the GUID that the adapter's plan expects of it, and the bound of its first partition, which CloneRequest gains, as first_partition_bound, beside the journal policy. An EROFS layer has no partitions, so the record of a clone of one leaves the bound out. A bound of 0 is a setting that no record holds, and the plan refuses it before it opens anything, as it refuses the request's other Activate settings, with the evidence InvalidActivate. InvalidFormat now names only an image that is not of the format and identity that its binding names. The plan checks a GPT disk as it checks an EROFS layer, from its metadata alone: the check of its binding, and the geometry of the template's placeholder, whatever the placeholder's format. As at a cold launch, the guest reads and checks the partition table with nvx::gpt before it assembles the root, so the host reads none of the disk, and hashes nothing. The test adapter's clone requests bound a GPT disk's first partition by 64 KiB, the default of a launch's guest. Part of #845 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 80932e09-af82-4b79-b417-70a241303cda
A clone's guest rereads a GPT disk's partition table before it assembles the root, and refuses an upper that is not fresh, and the host now plans GPT clones. These VM tests start such clones through runtime-adapter-host start, on the hypervisor. start takes --first-partition-bound BYTES for a GPT disk, as launch does, and clone::Request takes the bound, 64 KiB unless given. In vm_clone, one template, whose placeholder is a GPT disk of two layers, serves four clones at once: the EROFS image over a scratch image and in RAM, a GPT disk of one layer in RAM, and one of three layers over a scratch image, with a bound that its first partition meets exactly. The disks' layer partitions start where none of the placeholder's do, nor each other's, so a clone whose kernel kept the placeholder's partitions would fail its assembly. Each GPT clone's root stacks the layers of its own disk's table, read-only, and returns its own first partition. A disk whose first partition is one byte larger than the bound ends the clone with status 54, as does a scratch image that an earlier clone used, whose upper is not fresh. The GPT writer moves from vm_layered into tests/common/gpt.rs, with the small ext2 layers and the CRC, and writes disks of any layout and length. vm_layered writes the same disks as before through it. Part of #845 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 80932e09-af82-4b79-b417-70a241303cda
A clone's guest sets the hostname and the machine ID of the record's workload view for every execution: the image's own machine ID, or one that it generates once for the clone, which a read-only bind holds at /etc/machine-id. These VM tests check that view in clones that run at once. start takes --machine-id image|generated, the image's own by default, and clone::Request passes the mode to the clone's activation record. In vm_clone, one template serves three clones at once: over a scratch image and in RAM, each with a generated machine ID, and in RAM with the image's own. Two executions in each, as user ID 0, see the hostname, none of the markers that the other clones' executions wrote in their roots, and the clone's machine ID: a generated one, distinct between the clones, the same in both executions, held by one bind that is read-only, nosuid and nodev, which a write cannot change; or, with the image's own, none, since the image has none, and then the one that the first execution wrote. Each stop then tears its root down, binds included. A clone of a GPT disk whose layer holds a regular file etc starts with the image's own machine ID, which needs no bind, and ends with status 55 before it is ready with a generated one, which no bind can hold below a file. The template of that scenario is of the EROFS image, so it also restores a GPT clone of an EROFS placeholder. The scenarios' GPT disks may hold regular files in their top layer. Part of #845 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 80932e09-af82-4b79-b417-70a241303cda
This was referenced Oct 28, 2026
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues remain for the GPT clone support and runtime-adapter changes.
No open issues 🎉
What changed in this PR
This PR adds host-side GPT clone support and VM scenarios for #845’s root activation and workload-view changes. Its commits are intended to fold into #957 and #959 during the final restack rather than merge independently.
Changes:
- Allow GPT clone plans and activation records to carry disk identity and a first-partition size bound, while retaining metadata-only host checks.
- Expose first-partition bounds and machine-ID modes through the runtime adapter’s
startcommand. - Add VM coverage for differing GPT layouts, used-upper rejection, and machine-ID isolation, with shared GPT test helpers.
| File | Description |
|---|---|
| tests/runtime-adapter/tests/vm_layered.rs | Reuses the shared GPT and ext2 fixture helpers. |
| tests/runtime-adapter/tests/vm_clone.rs | Adds GPT, used-upper, and machine-ID VM scenarios. |
| tests/runtime-adapter/tests/common/mod.rs | Exposes the shared GPT helper module. |
| tests/runtime-adapter/tests/common/gpt.rs | Provides configurable GPT disks and small ext2 layers. |
| tests/runtime-adapter/tests/clone_start.rs | Tests new option validation and request defaults. |
| tests/runtime-adapter/src/clone.rs | Passes partition bounds and machine-ID modes into clone requests. |
| tests/runtime-adapter/src/bin/runtime-adapter-host.rs | Parses and documents the new start options. |
| tests/runtime-adapter/README.md | Documents clone options and added VM coverage. |
| nvx-rs/src/host/template/clone/tests.rs | Tests GPT planning, activation records, and invalid bounds. |
| nvx-rs/src/host/template/clone/record.rs | Builds GPT activation records with disk GUIDs and bounds. |
| nvx-rs/src/host/template/clone/failure.rs | Updates InvalidFormat documentation for GPT support. |
| nvx-rs/src/host/template/clone.rs | Removes GPT rejection and adds the request’s partition bound. |
| nvx-rs/README.md | Documents GPT support in the host template API. |
Review effort: Balanced
This was referenced Oct 28, 2026
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 #845: the VM scenarios of PR 1 (#957) and PR 2 (#959).
Review base: this PR temporarily targets
esaurez/845-vm-tests-base-snapshot-20261028, a frozen copy of the work it builds on, so that its diff shows only its own commits while the pull requests below it are in review. The snapshot is e00f02c: #844's PR 5 (clones in VMs through the test adapter) merged with this issue's PRs 1 to 3 (#957, #959, #960).This PR does not merge on its own. At the final restack, its commits fold into the PRs whose work they test: 7f4de94 and 844e960 into PR 1 (#957), and 62b88de into PR 2 (#959). This PR then closes.
What and why
nvx-rs: restore clones of GPT disks (7f4de94, for PR 1)
A clone's plan refused a GPT disk as its image before any VMM started, since no clone's guest rebuilt the partitions that its kernel created for the template's placeholder. With PR 1's reread, the plan takes a GPT disk as it takes an EROFS layer:
CloneRequestgains, asfirst_partition_bound, beside the journal policy. An EROFS layer has no partitions, so the record of a clone of one leaves the bound out.InvalidActivate.InvalidFormatnow names only an image that is not of the format and identity that its binding names.nvx::gptbefore it assembles the root, so the host reads none of the disk, and hashes nothing.runtime-adapter: start GPT clones, and refuse a used upper, in VMs (844e960, for PR 1)
runtime-adapter-host starttakes--first-partition-bound BYTESfor a GPT disk, aslaunchdoes, andclone::Requesttakes the bound, 64 KiB unless given.In
vm_clone, one template, whose placeholder is a GPT disk of two layers, serves four clones at once: the EROFS image over a scratch image and in RAM, a GPT disk of one layer in RAM, and one of three layers over a scratch image, with a bound that its first partition meets exactly. The disks' layer partitions start where none of the placeholder's do, nor each other's, so a clone whose kernel kept the placeholder's partitions would fail its assembly. Each GPT clone's root stacks the layers of its own disk's table, read-only, and returns its own first partition. A disk whose first partition is one byte larger than the bound ends the clone before it is ready, as does a scratch image that an earlier clone used, whose upper is not fresh: status 8, with the record of a failure of the request, by the evidence of an unusable root, with the guest's status 54.The GPT writer moves from
vm_layeredintotests/common/gpt.rs, with the small ext2 layers and the CRC, and writes disks of any layout and length.vm_layeredwrites the same disks as before through it.runtime-adapter: start clones with generated machine IDs, in VMs (62b88de, for PR 2)
starttakes--machine-id (image | generated), the image's own by default, andclone::Requestpasses the mode to the clone's activation record.In
vm_clone, one template serves three clones at once: over a scratch image and in RAM, each with a generated machine ID, and in RAM with the image's own. Two executions in each, as user ID 0, see the hostname, none of the markers that the other clones' executions wrote in their roots, and the clone's machine ID: a generated one, distinct between the clones, the same in both executions, held by one bind that is read-only,nosuidandnodev, which a write cannot change; or, with the image's own, none, since the image has none, and then the one that the first execution wrote. Each stop then tears its root down, binds included.A clone of a GPT disk whose layer holds a regular file
etcstarts with the image's own machine ID, which needs no bind, and ends before it is ready with a generated one, which no bind can hold below a file: status 8, by the evidence of invalid settings, with the guest's status 55. The template of that scenario is of the EROFS image, so it also restores a GPT clone of an EROFS placeholder.Validation
At this head, with OpenVMM at 79a501b6, the pin of its base:
-D warningswith all features and on the library without default features; the tests with all features and with the default ones; the library without default features; the documentation with-D warnings; and the MSRV check, with the aarch64-apple-darwin check on Linux.guest::clone::activation::applyand of the partition-table reread with a loop device, three times each, and the privileged tests ofguest::entryandguest::mappings.vm_clone, 15 scenarios, with the four of this PR;vm_layered, 43;vm_restart, 3;vm_steps, 3; andvm_template, 9.