Skip to content

feat: guest-agent over vsock acceptance test - #16

Merged
richardcase merged 1 commit into
mainfrom
feat/guest-agent-vsock
Jul 26, 2026
Merged

richardcase merged 1 commit into
mainfrom
feat/guest-agent-vsock

Conversation

@richardcase

Copy link
Copy Markdown
Member

What

Installs the LiquidMetal guest-agent into the microVM guest via apt during cloud-init, and adds an e2e test that connects to it over AF_VSOCK and runs commands.

Why

flintlock v0.11.0 (PR liquidmetal-dev/flintlock#1151) adds a vsock guest-agent channel: allow_guest_agent on the spec attaches a vsock device (host CID 2 ↔ guest CID 3) and reports the host-side UDS in MicroVMStatus.vsock_path. brigade v0.2.0 (PR liquidmetal-dev/brigade#21) bumps to that flintlock API, so the fields cross brigade natively. This gives the suite a host-controlled guest channel that needs no guest network — a different, complementary path to the existing SSH-reachability test.

How

  • spec.py — opt-in guest_agent flag: sets allow_guest_agent, adds NIC nameservers (apt needs guest DNS), and swaps in cloud-init that installs + enables guest-agent from the LiquidMetal apt repo. The default path (SSH test) is untouched.
  • provision_host.sh.j2 — installs the vsock-connect host client on each droplet (non-fatal on download miss).
  • config.py / .env.exampleGUEST_AGENT_VERSION knob (0.1.0); pins FLINTLOCK_REF=v0.11.0 + BRIGADE_REF=v0.2.0.
  • protos — re-vendored from flintlock v0.11.0 (allow_guest_agent, vsock_path); stubs regenerated.
  • tests/test_guest_agent_vsock.py (new) — creates a VM with guest_agent, reads vsock_path via brigade, finds the hosting droplet (UDS lives on exactly one host), and runs vsock-connect exec/ping/info over SSH — asserting hostname == vm-id, an arbitrary command, and exit-code propagation.

vsock is host-local (and host flintlockd :9090 is firewalled to peers), so the test runs vsock-connect on the droplet holding the UDS rather than from the runner.

Testing

  • make lint ✅ and pytest tests/test_cleanup.py ✅ (13 offline tests, incl. 3 new: guest-agent spec, default-off, provision installs vsock-connect).
  • Not yet run: make test (full e2e, real DO infra, ~20-40 min, costs money) with FLINTLOCK_REF=v0.11.0 + BRIGADE_REF=v0.2.0.

Residual runtime risks (flagged, fail loudly + guest serial console captured)

  • Guest kernel virtio-vsock support (assumed present in standard kernel images).
  • Guest DNS for apt (mitigated: NIC nameservers + resolv.conf append).

Install the LiquidMetal guest-agent into the microVM guest via apt during
cloud-init and add an e2e test that drives it over AF_VSOCK.

flintlock v0.11.0 attaches a vsock device when the spec sets allow_guest_agent
(host CID 2 <-> guest CID 3) and reports the host-side UDS in
MicroVMStatus.vsock_path; brigade v0.2.0 carries those fields natively. The
guest-agent (v0.1.0) listens on vsock control port 1024 and the host drives it
with the vsock-connect CLI.

- spec.py: opt-in guest_agent flag adds allow_guest_agent, NIC nameservers, and
  cloud-init that installs + enables guest-agent from the apt repo. Default path
  (SSH-reachability test) is untouched.
- provision_host.sh.j2: install the vsock-connect host client on each droplet.
- config.py/.env.example: GUEST_AGENT_VERSION knob; pin FLINTLOCK_REF=v0.11.0 and
  BRIGADE_REF=v0.2.0 (matched flintlock API).
- re-vendor protos from flintlock v0.11.0 (allow_guest_agent, vsock_path).
- new tests/test_guest_agent_vsock.py: create a VM with guest_agent, read
  vsock_path via brigade, find the hosting droplet, and run vsock-connect
  exec/ping/info asserting output + exit-code propagation.
Copilot AI review requested due to automatic review settings July 24, 2026 14:13

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an end-to-end acceptance path for LiquidMetal’s in-guest guest-agent reachable via AF_VSOCK, complementing the existing SSH reachability checks by validating a host-local control channel that doesn’t depend on guest networking.

Changes:

  • Add a new e2e test that locates the flintlock host-side vsock_path and runs vsock-connect commands via SSH on the hosting droplet.
  • Extend flintlock spec building to optionally enable allow_guest_agent, add NIC nameservers, and use cloud-init that installs/enables guest-agent.
  • Add config/env and host provisioning support for pinning and installing the matching vsock-connect client version, plus proto updates for allow_guest_agent / vsock_path.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/test_guest_agent_vsock.py New e2e test exercising guest-agent over vsock via host-local vsock_path.
tests/test_cleanup.py Offline/unit checks for guest-agent spec behavior and host provisioning template output.
proto/fltypes/microvm.proto Vendored proto updates adding allow_guest_agent and vsock_path.
proto/flapi/microvms.proto Minor vendored proto formatting/closure alignment.
liquidmetal_at/flintlock/spec.py Add guest_agent opt-in to spec/request builders and guest-agent cloud-init.
liquidmetal_at/config.py Add guest_agent_version config knob with env defaulting/pinning commentary.
liquidmetal_at/bootstrap/templates/provision_host.sh.j2 Install vsock-connect on hosts (intended non-fatal).
liquidmetal_at/bootstrap/host.py Thread guest_agent_version into host provisioning template rendering.
.env.example Pin refs for brigade/flintlock versions supporting vsock guest-agent and add GUEST_AGENT_VERSION.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +64 to +80
for droplet in cluster.droplets:
ssh = SSH(host=droplet.public_ip, user="root", key_path=config.ssh_private_key_path)
ssh.connect(timeout=config.timeout_ssh)
try:
rc, _, _ = ssh.run(f"test -S {quoted}", check=False, timeout=15)
if rc == 0:
rc, out, err = ssh.run(
f"vsock-connect ping --uds {quoted} --port 1024",
check=False,
timeout=30,
)
if rc == 0:
return ssh
last = f"ping rc={rc}: {(err or out).strip()}"
except Exception as exc: # noqa: BLE001 - agent lives behind one host
last = str(exc)
ssh.close()
Comment on lines +91 to +95
if curl -fsSL "$GA_URL" -o "$GA_TMP/vc.tgz"; then
tar -xzf "$GA_TMP/vc.tgz" -C "$GA_TMP"
GA_BIN=$(find "$GA_TMP" -type f -name vsock-connect | head -1)
[ -n "$GA_BIN" ] && install -m0755 "$GA_BIN" /usr/local/bin/vsock-connect
fi
// not supplied a autogenerated MAC address will be used.
optional string guest_mac = 4;
// Address is an optional static IP address to manually assign to this interface.
// Address is an optional static IP address to manually assign to this interface.
@richardcase
richardcase merged commit a990bbe into main Jul 26, 2026
1 check passed
@richardcase
richardcase deleted the feat/guest-agent-vsock branch July 26, 2026 07:24
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.

2 participants