Repository navigation
feat(node): a Firecracker backend, behind --backend firecracker - #370
Merged
Merged
Conversation
WaylandYang
force-pushed
the
feat/firecracker-backend
branch
from
October 29, 2026 10:36
0024ccc to
7196c54
Compare
NOT YET RUN ON KVM: none of bm, bj or hk has /dev/kvm. Compiled and unit-tested on macOS only; DESIGN-v0.6-FIRECRACKER.md lists what to verify first. Upstream Firecracker, no fork. From v0.5 it keeps the three things v0.6 kept: forks of one tag share a page cache (File backend, MAP_PRIVATE on one memory file); a restored sandbox snapshots next time as a diff of the pages it dirtied, chained onto its image; and every sandbox has its own reflinked disk. Live fork stays out -- it needs the vendored fork and upstream #6270 is not merged. - The Backend trait now prepares the sandbox too (template_root, prepare, layer, unmount, teardown): a VM needs a disk image, not an overlay. runsc's implementations call bundle.rs exactly as before. - Every image carries the disk as it was while the VM was paused, since the guest's page cache refers to disk blocks. The disk's path in the VM is the relative rootfs.ext4 and Firecracker runs in the sandbox's own disk directory, so a vmstate opens the loading sandbox's copy, never the parent's; then load with resume_vm:false, PATCH /drives/rootfs, resume, as in #321. Any failure kills it unresumed. - Diff chains are hard-linked into each image, so dropping a tag never breaks one derived from it; assembled once into a dot file that tag transfer leaves out. - Every guest is 10.42.0.2 behind a tap in its netns, DNATed from the netns address, so a snapshot restores into any namespace. - Firecracker joins the sandbox's cgroup before exec and runs in its own session: freeze, accounting, cgroup.kill and restart adoption are the runsc code unchanged. - Refuses to start without /dev/kvm, the kernel, or a work dir that can reflink. - The agent starts the template's program from sandstorm.app= on the kernel command line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: WaylandYang <145302500+WaylandYang@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: WaylandYang <145302500+WaylandYang@users.noreply.github.com>
WaylandYang
force-pushed
the
feat/firecracker-backend
branch
from
October 29, 2026 11:13
7196c54 to
bc030dd
Compare
WaylandYang
added a commit
to Floating-Y/sandstorm
that referenced
this pull request
Oct 29, 2026
dev now runs the archive through the Backend trait (deeplethe#368, deeplethe#370). Resolving the conflict in detach_with_commands keeps this PR's two-process pipeline and adds what dev needed: - tar gets -S again. A Firecracker layer is a sparse rootfs.ext4; without it tar reads every hole and the restore writes them all out. - The archive directory is fsynced after the rename. The local layer and snapshot are deleted right after, so the rename must be durable first. - Stdio is imported, and the test fixture builds its Runtime with Runtime::new now that Runtime has an engine and a fingerprint. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: WaylandYang <145302500+WaylandYang@users.noreply.github.com>
WaylandYang
added a commit
to Floating-Y/sandstorm
that referenced
this pull request
Oct 29, 2026
dev now drives checkpoints through the Backend trait (deeplethe#368) and has a Firecracker backend (deeplethe#370), so this PR's fix is redone on top of them. The idea is unchanged: an attempt writes into a directory of its own and is renamed into place, without replacing anything, only once it checks out. What changed in the reworking: - Validation is `Backend::validate`. The runsc check keeps this PR's statefile-header and pages-file rules; Firecracker checks vmstate, rootfs.ext4 and an unbroken mem chain. Before, every Firecracker image would have failed to publish. - `observe` runs no subprocess: `runsc statefile` and the validation cache are gone. A published image carries a seal listing its files' lengths (dot names excluded, so tag listings skip it and backend caches such as .mem.assembled do not break it); an image from before sealing is judged by `validate`. The cgroup is read first, so a running sandbox is never reported as Snapshot. - Failed attempts are removed at once, or by the next attempt or a destroy if a writer is still holding one, rather than kept until someone destroys the sandbox by hand. `create` no longer refuses. - renameat2 falls back to check-then-rename on EINVAL; one sandbox's transitions never run concurrently, so that holds. - `branch` publishes its tag the same way, so a failed branch no longer leaves a tag that blocks the name forever. - Nothing is fsynced, as before: this guards against a failed checkpoint, not a power cut, and syncing whole images would sit on the snapshot tier's critical path. Tests use the in-memory Recorder backend, so they run on any OS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: WaylandYang <145302500+WaylandYang@users.noreply.github.com>
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.
The optional backend from DESIGN-v0.6 §2, on upstream Firecracker (no fork), built on the
Backendtrait from #368.What it keeps from v0.5
MAP_PRIVATE)date -sthrough the agentNot included: live fork (needs the vendored fork; upstream #6270 is not merged), hugepages (file-backed hugetlbfs restore is upstream #6099), user volumes (refused with an error for now).
How
template_root,prepare,layer,unmount,teardown), because a VM needs a disk image, not an overlay. runsc's implementations callbundle.rsexactly as before.rootfs.ext4, and Firecracker runs in the sandbox's own disk directory, so a vmstate opens the loading sandbox's copy, never the parent's. Thenresume_vm:false→PATCH /drives/rootfs→ resume, as in feat(vmm): give every restored child its own rootfs backing #321; any failure kills it unresumed.cgroup.killand restart adoption are unchanged code.sandstorm.app=on the kernel command line. Port 8888 belongs to the agent.Testing
cargo test -p sandstorm-core(173 lib + integration) andcargo clippy --all-targets -D warningspass. New tests: the API client against a fake socket, load ordering (no resume before the re-point, none after a failed one), chain reading/assembly, sparse diff application, boot args and the 2048-byte limit,prepare. Agent:rootfs-init/tests/test_agent_app.py.FICLONE,SEEK_DATA) is compiled for the first time by this PR's CI. CI's ext4 cannot reflink, so the two reflink tests skip there;apply_diffhas its own test that runs.dev:wake::tests::a_wake_behind_a_full_queue_is_refused_at_oncefails whenever it runs alone, and passes in the full suite.First things to check on a KVM host
snapshot/loadwith dirty tracking holds exactly the pages dirtied since the load. If not, chains lose pages.sandstormdrestart with VMs running.🤖 Generated with Claude Code