test(os): #1945 the restore leg waits for the provisioning units before it backs up - #1947
test(os): #1945 the restore leg waits for the provisioning units before it backs up#1947VijitSingh97 wants to merge 1 commit into
Conversation
…re it backs up The leg read "provisioned" off two identical `podman ps` readings, which cannot see the wizard's `up` still inside its tor-health wait, holding the mutation lock. The backup then waited that `up` out and, when it died, archived and restarted the wreck, and the red said "could not take the source backup" instead of naming the failed setup. tests/os/provisioning-settled.sh: settled when neither pithead-firstboot nor pithead-boot is `activating` (word-anchored: `deactivating` is on its way out), bounded, with a verdict line that carries the units and the wizard's spooled error. run.sh swaps the settle loop for it, line-neutral at its ceiling. Ten fixture rows in test-appliance-boot-remint.sh drive the helper with a stubbed _ssh; five mutants each red their own rows. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NeSaJPWy7AkhYcYpGVkxBJ
Non-author review — PASS at
|
… state route too The fourth /api/state read in tests/os — the fixture-works control at the top of the reinstall pre-fill submit leg — used the wizard's session jar against a route only the provisioned dashboard registers. The wizard serves /api/wizard-state (wizard.py:526), and its `config` carries `monero.wallet_address`, the field the control compares. Without this the first install run to get past the restore leg (PR #1947) would have redded with "pre-fill NOT armed (served wallet: none)" — loud, but naming the wrong cause. Found by the fixes lane at source (git grep at d973163: zero "/api/state" in wizard.py, two "/api/wizard-state"); re-derived here before the edit. The three /api/state reads left in run.sh are basic-auth reads against the provisioned dashboard and stay. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NeSaJPWy7AkhYcYpGVkxBJ
|
KVM install leg, RUN 1 — tree This PR's claim PASSED. The two new rows both went green in that order: so the harness's backup no longer starts while the firstboot's The one ✗ is downstream of this PR and is the #1939 negative control, not a #1945 regression: Run 2 launches next on What this run does NOT prove: nothing after the backup step ran (restore, pre-fill legs), so #1934's third commit (the install-phase pre-fill control) was not exercised here — run 2 covers it. |
|
Run 2 (tree |
Harness half of #1945 (the issue stays open for the KVM leg named below; hand-close after it). Lane paths only (
tests/os/, this lane'stest-appliance-boot-remint.sh) plus one doc row indocs/dev/appliance-wizard.md.What changes
tests/os/provisioning-settled.sh(new, sourced byrun.sh):provisioning_settled <seconds>returns 0 once neitherpithead-firstbootnorpithead-bootreadsactivatingfromsystemctl is-active, 1 at the deadline; the match is word-anchored, sincedeactivatingcontainsactivatingand is a unit on its way out. An unanswered probe keeps waiting rather than reading as settled.provisioning_stateis the verdict line: both unit states and, when the wizard spooled one, itserror.txt.tests/os/run.shrestore leg: thepodman pssettle loop (two identical readings 10 s apart) goes; in its place the leg waits up to 900 s for the units, reds withprovisioning never finished on the machine (units: … — setup error: …)plus the existing guest evidence block on the deadline, and otherwise logs that provisioning finished before it runspithead backup. Line-neutral at the file's 3423 ceiling (13 lines out, 13 in).tests/stack/test-appliance-boot-remint.sh: a fifth unit section, ten rows, driving the helper with a stubbed_sshthat answers the two probes;PROVISIONING_POLL_S=0and a flip file exercise the poll itself.docs/dev/appliance-wizard.md: the restore-leg row says the backup is taken after the provisioning units have finished, and why.Why
The w141 install leg (BUILD_COMMIT
87aea589) reddenedrestore leg: could not take the source backup. Re-derived at source on #1945: the wizard's(setup)subshell releasessetup's hold and re-acquires asupin the same process, then sits insidedocker compose up | teewaiting on tor's healthcheck for minutes after dashboard and caddy show inpodman ps. The harness read that as "provisioned", ran the backup, the backup waited theupout (correctly), and when thatupdied on tor unhealthy the backup was let through and archived the wreck. The lock held; the harness acted on a wrong reading and its red named the wrong thing. This PR makes the leg wait on the product's own boundary (the unit leavesactivatingonly when the wizard'ssetuphas returned) and say what it saw.What was RUN
STACK_SUITE=1,lib.shthentest-appliance-boot-remint.sh): 40/40 green (30 existing rows + the 10 new).git diff --numstatapplied-readback printed blank; the applied-proof is that each mutant reddened a DIFFERENT row set, and none left the file green): word-anchoring removed → only thedeactivatingrow red; empty probe treated as settled → only the unanswered-probe row; deadline returns 0 → exactly the three deadline rows; activating returned at once instead of polled → only the flip row; the spool-error condition inverted → both verdict rows.bash -n,shfmt -i 4 -d,shellcheck -x -S warningon all three shell files: clean.scripts/lint-file-budget.sh: OK,run.shat 3423.tests/inventory.shlists the fragment with 5 sections.make lint-docs-voice: OK.What was NOT done
--phase install, ~35 min plus the build): the bench is under the fix(os): #1896 the dashboard quadlet carries the three dashboard-onion values #1942 re-proof as this opens. Queued next on the bench; rc, BUILD_COMMIT and the leg's line are posted here when it lands, and the reviewer ask goes out after that so the PASS can name it. If tor goes unhealthy on the re-provisioned guest again (the layer-1 cause on KVM restore leg: the harness's backup is granted the mutation lock while the firstboot'spithead upis still in its health wait; two compose ups overlap and tor ends unhealthy #1945, still open), the leg is expected to red with the new line naming the failed setup rather than the backup.lib/pithead/— the evidence does not support a product guard; the lock serialised the two verbs as designed.Over-engineering pass (by hand; the PR-gate hook keys off the wrong branch from this lane's cwd)
systemctl is-activeis the product's own boundary and needs no knowledge of the lock path or record format, and it also covers a holder that wrote no record (the fail-open branch).run.shis at its ceiling, the three functions are 30 lines, and the fixture rows need them sourceable in isolation — the shapejournal-boot-verdict.shset.podman psloop deleted, not kept beside the new wait: its property ("startup is over") is implied bycompose up -dhaving returned, which is what the unit wait establishes.PROVISIONING_POLL_Sexists only for the fixture; the 15 s default matches the leg's other polls. Not taken: a general knob or a config key.unhealthyat 240 s worst case per attempt (start_period90 + 5 × 30) and monerod/tari start after it; the leg's own "stack came up" wait is 1500 s. Rejected: reusing 1500 s, which would put the deadline past the point where a failed setup is already sitting in its reopened window.tests/stack/*-lock.shfragments), not this leg's.🤖 Generated with Claude Code
https://claude.ai/code/session_01NeSaJPWy7AkhYcYpGVkxBJ