Skip to content

feat(console): choose a node's backend, and switch an empty one - #386

Merged
WaylandYang merged 4 commits into
devfrom
claude/gallant-blackburn-eaf40d
Oct 30, 2026
Merged

WaylandYang merged 4 commits into
devfrom
claude/gallant-blackburn-eaf40d

Conversation

@WaylandYang

@WaylandYang WaylandYang commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Lets an operator pick a node's backend from the console instead of editing its systemd unit.

Design

Add node. Auto, gVisor or Firecracker, plus optional kernel path and work dir, carried into the install command. The master validates paths before they reach a root shell.

Installer. SANDSTORM_BACKEND is auto, gvisor or firecracker; unset stays gVisor, so existing scripts keep working. It checks /dev/kvm, the guest kernel and a real reflink probe, then runs the new sandstormd preflight, which makes the same checks a node makes at startup. A refusal says what is missing and installs nothing. Auto prints what it picked and why. Firecracker comes from SANDSTORM_FIRECRACKER, the PATH, or the release and sha256 pinned in setup-host.sh.

Switching. The choice lives in a file (--backend-file), not the unit's command line, because ProtectSystem=strict keeps the node out of /etc. POST /v1/nodes/:id/backend sends a SetBackend command; the node preflights, rewrites the file and exits 75 for Restart=on-failure. Refused while the master records any sandbox or snapshot on the node, and again by the node if anything is in bundles/, warm seeds included. Snapshots count too: a tag on a dial-in node is forked on that node, so it would be restored on the wrong engine. The node is out of placement from acceptance until it reports the new engine, or 120 s. The dialog says it will change host group.

Templates. Nodes report which templates they can start on their backend. The master places a template only on those; if none can, the create is a 409 naming both forms. Nodes that have not reported are placed on as before.

Create dialogs. "Where" lists each backend with its pools, and each node with its backend. This needed a new optional backend on POST /v1/sandboxes: a pool name also matches its #fingerprint groups, so it cannot pin a backend.

Behaviour changes

  • gVisor install now refuses when runsc is missing; it used to warn.
  • Nodes installed before this have no backend file, and must be reinstalled to switch. The console says so.

Also fixes an existing installer bug: backticked words in the unit's comments ran as root during install (ip netns add, runsc start) and were lost from the unit.

Verified

On the bare-metal KVM host, with a real master, install.sh, systemd unit, runsc and Firecracker v1.17.0, on an XFS loop mount:

  • Auto on an ext4 work dir: picked Firecracker, refused, nothing installed.
  • gVisor install, then a sandbox ran; the switch got a 409 and the file was unchanged.
  • Empty node: switched to Firecracker, NRestarts 0 to 1, fingerprint changed, and a real microVM answered exec (guest kernel 6.1.141) under the hardened unit.
  • Template with no ext4 form: 409 naming both forms.
  • Switched back to gVisor; a sandbox ran.

Tests: cargo test --all on Linux, 316 passed. cargo clippy -D warnings clean. Console 12 passed, plus packaging/tests/install_backend.sh; both are added to CI.

Not verified

  • The Firecracker download path in the installer: the test host already had a binary on its PATH.
  • A switch on a node in a mixed pool on real machines: the node was alone, so its pool name stayed default. Moving groups is covered by the existing refingerprint_node test.
  • Listen-mode nodes on real machines.
  • The new dialogs in a browser: only type-checked, built and unit-tested.

🤖 Generated with Claude Code

WaylandYang and others added 4 commits October 30, 2026 15:33
Add node offers Auto, gVisor or Firecracker and carries it into the install
command. The installer checks the machine first, then runs the node's own
checks (`sandstormd preflight`), and refuses before installing anything.

An empty node can move backend: POST /v1/nodes/:id/backend has it rewrite its
--backend-file and restart. Refused while it holds a sandbox or snapshot.

Nodes report the templates their backend can start, the master places a
template only on those, and a create can name a backend. The create dialogs
show each place's backend.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The unit is an unquoted heredoc, so each backticked word in its comments ran
as root during install (`ip netns add`, `runsc start`) and vanished from the
unit. Found installing on bare metal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@WaylandYang
WaylandYang merged commit 85ef162 into dev Oct 30, 2026
10 checks passed
@WaylandYang
WaylandYang deleted the claude/gallant-blackburn-eaf40d branch October 30, 2026 09:31
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