Colleague-safety batch #1+#2 (script-only). Adds a guarded, dry-run-aware --uninstall local host teardown (guest -> agent -> pveum(ACL,token,user,role) -> golden(opt-in) -> state file), with ours-check on the /etc/felhom-bootstrap mount, typed vmid confirm, other-Felhom-guests safe-skip, and idempotent tolerate-absent. Records customer_id + provisioned_vmid into the install state (_state_put/_state_get) so uninstall resolves its target automatically. Adds three provision pre-flight guards: multi-node (--node required), archive-storage exists, and a RAM-floor WARN. Validated dry-run-only on felhom-pve. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
6.9 KiB
felhom.eu — task reports
Overwrite this file with a summary of the most recent task only (uniform with the other repos; not cumulative). The cumulative hub history lives in hub/CHANGELOG.md; the scripts history lives in scripts/CHANGELOG.md.
REPORT — felhom-host-install.sh --uninstall (clean revert) + pre-flight guards (host-install v1.3.0)
Date: 2026-07-01 · Repo: felhom.eu (scripts/ only)
Colleague-safety batch #1 (--uninstall) + #2 (pre-flight guards). Script-only. A first-class,
guarded local host-teardown mode so an operator can cleanly back out of a trial install, plus three
provision pre-flight guards. Specced, built, and validated dry-run-only (the live --uninstall is a
supervised step and was deliberately NOT run — see the STOP list).
1. Confirmed baseline
| Repo | main @ commit |
Current | → Target |
|---|---|---|---|
felhom.eu (scripts/felhom-host-install.sh) |
83c4f7f7 |
script v1.2.0 | v1.3.0 |
No agent/controller/hub change in this task.
2. Files changed
scripts/felhom-host-install.sh(v1.2.0 → v1.3.0) — the only code file.scripts/CHANGELOG.md— v1.3.0 entry (newest on top; this is where the v1.2.0 entry lives).REPORT.md— this file (overwritten).
3. Commit hash(es)
<COMMIT_HASH>onmain(filled in after push; see §Served-copy check).
4. What was implemented
Part 1 — install state records vmid + customer. New _state_put KEY VALUE / _state_get KEY
helpers (python3, dry-run-guarded like _state_mark, completed[] shape untouched). step_preflight
now records customer_id; step_provision records provisioned_vmid on success (dry-run logs only).
Part 2 — --uninstall mode (early top-level dispatch, root-required, no --customer-id, no hub
contact, no passphrase). run_uninstall reverses install order: guest → agent(unit+.bak / sudoers /
binary+.bak / state dir / user) → pveum(ACL user, ACL token, token, user, role) → golden(opt-in) →
state file. Every mutation via run() (dry-run prints, executes nothing). Guards: ours-check on the
/etc/felhom-bootstrap bind mount (matched by the constant guest path, not a slot), typed vmid
confirmation (/dev/tty, skipped only in dry-run), other-Felhom-guests safe-skip (keeps host-level in
place unless --force), state-mismatch --force gate, and idempotent tolerate-absent on every object.
--remove-golden opt-in deletes the golden vzdump (pvesm free). Never removes the sudo package;
never contacts the hub. New helper felhom_guests() enumerates Felhom guests by the bootstrap mount.
Part 3 — pre-flight guards (all inside step_preflight, before any mutation → fire under dry-run):
multi-node guard (die unless --node explicit via new NODE_EXPLICIT; no-op single-node / under
--skip-provision), archive-storage-exists guard (pvesm status --storage; no-op under
--skip-provision), RAM floor WARN (MemAvailable < 2048 MiB, never fatal).
Confirmed the PVE 9 ACL-delete syntax live before wiring it:
pveum acl delete <path> --users|--tokens <x> --roles <role>.
5. Green gate — bash -n + shellcheck
bash -n scripts/felhom-host-install.sh→ OK (locally + on felhom-pve).shellcheck v0.10.0(fetched static binary on the build server; shellcheck isn't installed on any box): HEAD v1.2.0 baseline = 2× SC2015 (info); v1.3.0 = 2× SC2015 (info) at lines 1128 & 1138 — both in the pre-existingstep_verify(A && B || C), untouched by this task. 0 new warnings.
6. Tests → §7 mapping (dry-run transcripts / read-only live checks on felhom-pve, single-node, live guest 9201)
| # | Scenario | Result |
|---|---|---|
| T-A | full clean-uninstall plan (--uninstall --vmid 9201 --dry-run) |
PASS — ours-check passes, prints pct config 9201, would-prompt for typed confirm, then the full plan: pct stop/destroy 9201 → agent removal (unit + all .bak-*, sudoers, binary + all .bak-*, rm -rf /var/lib/felhom-agent, userdel) → pveum acl delete (user, then token) → token remove → user delete → role delete last → golden skipped → state file rm. All [DRY-RUN]. sudo package NOT touched; hub note printed. |
| T-B | other-guests detector | PASS — felhom_guests() enumeration prints only 9201 (only Felhom guest on the host). Skip-branch code-reviewed (2nd Felhom guest not available live). |
| T-C | not-ours refusal (red-proof) | PASS — --uninstall --vmid 9001 --dry-run (9001 exists, no bootstrap mount) → die "vmid 9001 does not look like a Felhom-provisioned guest … Refusing to destroy. Pass --force to override.", exit 1, dies before any run(). Nonexistent id 987654 → safe refusal ("absent and is not the recorded provisioned_vmid … --force"). |
| T-D | multi-node guard | PASS (single-node) — node: demo-felhom (auto), guard is a no-op on the 1-node host; multi-node die code-reviewed. Live multi-node validation deferred (see STOP). |
| T-E | storage / RAM guards | PASS — --dry-run --archive-storage nonesuch → die "archive storage 'nonesuch' not found (pvesm status)…" before the passphrase prompt; normal dry-run prints the RAM line (free RAM: ~12251 MiB; the <2048 WARN branch is code-reviewed — the box has 12 GiB free). |
| T-F | dry-run executes nothing | PASS — after all dry-runs: pct status 9201 = running, felhom-agent active, binary present, pveum user + role present, state.json unchanged (no provisioned_vmid added — dry-run writes nothing). |
| Part 1 | _state_put/_state_get round-trip |
PASS — isolated temp-file test: writes top-level customer_id/provisioned_vmid, preserves completed[], reads both back. |
7. Served-copy version check (after push)
curl -fsSL https://felhom.eu/scripts/felhom-host-install.sh | grep SCRIPT_VERSION
# expect: SCRIPT_VERSION="1.3.0"
→ <RESULT after push>
8. NOT yet live-validated — awaiting a supervised run
- A real live
--uninstall(actual guest destroy +pveumrole/user/token/ACL removal +userdel- state wipe). Deliberately not run per the TASK STOP — do it on the colleague's box or a throwaway scratch guest, never the demo guest 9201.
- The multi-node guard on an actual 2+-node cluster (felhom-pve is single-node).
- The other-Felhom-guests safe-skip branch with a second live Felhom guest present.
9. Observations (noticed, NOT acted on)
- In
--dry-run,run_uninstallprints[OK] guest <vmid> destroyedafter the[DRY-RUN] pct destroylines; the trailing[DRY-RUN]: nothing above was actually executed.clarifies it, and this mirrors the existing dry-run success-logging pattern — left as-is (minimal change). - Colleague-safety batch items #3 (CPU/mem cap, agent-side) and #4 (pool-scoped ACL) are separate specs; not touched here.