fix(vm): speak donate-clanker's version-2 bootstrap protocol in the guest - #40
Merged
Conversation
…uest
The published podman-vm guest boots, systemd activates
donate-clanker-bootstrap.service, and the service then dies immediately:
systemd[1]: Starting donate-clanker-bootstrap.service ...
donate-clanker-bootstrap[438]: donate-clanker bootstrap failed:
Expecting value: line 1 column 1 (char 0)
systemd[1]: donate-clanker-bootstrap.service: Main process exited,
code=exited, status=1/FAILURE
The user-visible symptom is that the VM boots and the worker never runs.
The guest consumer spoke protocol version 1: it required an exact key set,
rejected anything whose version was not 1, acked version 1, treated an
empty first read as fatal, and exported DONATE_CLANKER_* environment
names. donate-clanker sends a version-2 envelope with optional keys,
requires a version-2 ack, and its worker reads HIVE_WS_URL, HIVE_HUB,
HIVE_REGISTRATION_TOKEN, AGENT_BACKEND, GOOSE_PROVIDER, GOOSE_MODEL and
GITHUB_COPILOT_TOKEN. Every real envelope was rejected twice over, and
even a hypothetically accepted one would have started a worker with no
credentials in its environment.
Rewrite the consumer to speak version 2, validate only the four required
fields while tolerating optional ones, retry the port open and empty
reads under a bounded deadline, ack version 2, and export the names the
worker actually reads. Give the unit a start timeout long enough to
outlast the host's accept timeout.
Progress lines are mirrored to /dev/kmsg. Measured on the real disk, a
unit's StandardOutput=journal+console no longer reaches the serial
console once serial-getty has run its TTYVHangup, while /dev/kmsg writes
still land, so kmsg is the only reliable channel for a boot-time
assertion here.
tests/vm-boot.sh gains marker 5, asserting that the bootstrap banner
reaches the serial console. That proves the unit shipped, the preset
enabled it, systemd activated it and ExecStart ran, without requiring a
handshake that CI cannot complete. Run against the unfixed published
v25.08.15 disk the new assertion fails as intended: the login prompt
appears, the banner never does.
The brief's suspected cause -- an unapplied systemd preset -- is not the
defect. FSDK's files/vm/prepare-image.sh runs systemctl --root preset-all
at image assembly time, the published disk does contain
/etc/systemd/system/multi-user.target.wants/donate-clanker-bootstrap.service,
and systemd-networkd is enabled and takes a DHCP lease. The docs that
claimed otherwise are corrected here.
Unblocks projectbluefin/donate-clanker#13.
Co-authored-by: Copilot <223556219+Copilot@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 defect
The published
podman-vmguest boots and the worker never runs.The suspected cause going in was an unapplied systemd preset. That is not the defect. Evidence from the real published
v25.08.15aarch64 disk:debugfson the root partition shows/etc/systemd/system/multi-user.target.wants/donate-clanker-bootstrap.servicealready present, pointing at/usr/lib/systemd/system/donate-clanker-bootstrap.service. FSDK'sfiles/vm/prepare-image.sh, whichpodman-vm-efi.bstinvokes, runssystemctl --root "${sysroot}" preset-allat image assembly time. The preset mechanism works.donate-clanker-bootstrap.serviceisUnitFileState=enabled,LoadState=loaded,ActiveState=failed,Result=exit-code.systemd-networkd.serviceisenabled/active/running;networkctlshows the NIC routable with a DHCP lease of10.0.2.15/24, andsystemd-networkd-wait-online.servicefinished. Networking was never broken and is left alone.The journal has the actual cause:
The guest consumer speaks protocol version 1. donate-clanker speaks version 2. Concretely, the shipped consumer:
{version, hive_endpoint, registration_token, backend, run_id}, so a version-2 envelope carryinggoose_provider,goose_modelorprovider_secretwas rejected;versionthat was not1;{"version": 1, ...}, which the host rejects because it requires{"version": 2, "type": "control_ack"};DONATE_CLANKER_*environment names, while the pinned worker readsHIVE_WS_URL,HIVE_HUB,HIVE_REGISTRATION_TOKEN,AGENT_BACKEND,GOOSE_PROVIDER,GOOSE_MODELandGITHUB_COPILOT_TOKEN.Any one of those alone makes the VM path inert.
The fix
elements/podman-vm/files/donate-clanker-bootstrap.pynow:{"version": 2, "type": "control_ack"};GOOSE_PROVIDERtogithub_copilotand mappingprovider_secrettoGITHUB_COPILOT_TOKEN;/dev/kmsgas well as stderr.The unit gains
TimeoutStartSec=300so systemd's 90s default cannot kill a wait that must outlast the host's 180s accept timeout.The
/dev/kmsgmirroring is not decoration. Measured on the real disk: a unit'sStandardOutput=journal+consolestops reaching the serial console onceserial-getty@ttyAMA0.servicehas run itsTTYVHangup=yes, while a/dev/kmsgwrite from the same boot lands and is timestamped like a kernel message. kmsg is the only reliable channel for a boot-time assertion on this guest. Kernel audit lines are no better, since they route toauditdonce it starts, before the bootstrap unit runs.No new enablement mechanism was added, because none is missing.
The test
tests/vm-boot.shgains marker 5: the serial log must contain the bootstrap's first banner line. That proves the unit shipped, the preset enabled it, systemd activated it andExecStartran, without requiring a handshake CI cannot complete (nothing in CI writes an envelope, and the envelope schema belongs to donate-clanker, so asserting on it here would make their bump redden our builds). The unit still goes on to fail its wait in CI; that is expected and documented.The assertion is not vacuous. Run against the unfixed published
v25.08.15disk:with
login:present once in the captured serial log anddonate-clanker-bootstrappresent zero times.Proof
The fixed script was injected into the real booted
v25.08.15guest, the shipped v1 unit stopped, and a version-2 envelope served over the virtio-serial port. The host observed exactly one ack line:and the serial console showed both kmsg banners:
with the worker exec'd carrying
HIVE_WS_URL,HIVE_HUB,HIVE_REGISTRATION_TOKEN,AGENT_BACKEND=goose,GOOSE_PROVIDER=github_copilot,GOOSE_MODELandGITHUB_COPILOT_TOKEN.No new disk was built.
just export-podman-vmis a multi-GB BuildStream export that was not feasible here, so the runtime proof above comes from injecting the fixed script into the real guest rather than from booting a rebuilt image. Only a real CI build can confirm that the rebuilt image ships the fixed script and that marker 5 passes green.Validation
just validateexits 0 and resolves throughpodman-vm/podman-vm-efi.bstshellcheck tests/vm-boot.sh,bash -n,git diff --checkcleanpython3 -m py_compileandruff checkcleanrun_idrejected with clear messagesScope
One logical change. No Lima, cloud-init, SSH or guest agent reintroduced. PR #38's publish guarantees and PR #39's boot assertions are untouched; marker 5 is additive. Docs in
docs/skills/are corrected in the same PR, since they previously carried the false "the preset is not applied, do not assert on the unit" claim.Unblocks projectbluefin/donate-clanker#13.