Files
felhom-controller/REPORT.md
T
2026-06-14 20:17:47 +02:00

70 lines
5.3 KiB
Markdown

# REPORT — TASK B1+B2 data migration + self-serve decommission → controller v0.65.0 (2026-06-14)
Customer-self-serve storage **migration** (move app data between drives) and **decommission** (retire a
drive), implemented trunk-based on `main` against the locked spike design
(`felhom.eu/documentation/audits/SPIKE-decommission-migration-2026-06-14.md`). Pairs with **agent
v0.32.0**. Each change carries non-hollow tests; the load-bearing companions were mutation-proven to
fail on the pre-fix code. Built + deployed both images to demo guest 9201 / felhom-pve.
> Validate against pushed source, not this report. **Live decommission/migration of real data is NOT
> yet validated — that is the supervised B3 session (see the end).**
## Confirmed baselines
- Controller `main` was `c37ee6d` = **v0.64.0** → shipped **v0.65.0**.
- Agent `main` was `8e6d00a` = **v0.31.0** → shipped **v0.32.0**.
## Commits (controller repo unless noted)
| # | Commit | Scope |
|---|---|---|
| 1 | `b57150e` | B1 migration engine (`internal/stacks/migrate.go`, MigrateAll+MigrateApp) + tests + main wiring + backup mutual-exclusion (Change 3) |
| 2 | `16a4c3e` | B1 UI — `/api/storage/migrate{,-app,/status}` + settings.html & app_info.html + progress panel |
| 3 | `f43697c` (felhom-agent) | v0.32.0 — `POST /disks/decommission` + intent-aware `ReassertGuestBinds` + `GuestBindStore.Remove` + tests |
| 4 | `f2596ea` | B2b decommission orchestration + "Hiányzó tárhely" indicator + Change 4 re-enroll fix + tests |
## What shipped
- **B1 engine** — crash-safe, resumable, journaled (`<dataDir>/migration.json`). Pipeline validate → stop
→ copy (`rsync -a --checksum`, additive, **no `--delete`**; conflict-merge walk for non-app content) →
verify (`rsync -ani --checksum`, zero pending) → flip+redeploy (`RedeployFromEnv`) → **cleanup gated on
all-verified AND all-redeployed**. Two entry points (whole-namespace + per-app incl. SSD→drive) over one
pipeline. Single-flight; mutually exclusive with the backup orchestrator (migration refuses while a
backup runs; scheduled DB-dump/Tier-2 skip while a migration runs).
- **B1 UI** — migrate-all (settings page) + per-app "Áthelyezés másik tárhelyre" (app-info page) + shared
status poll/progress panel.
- **B2a (agent)** — self-serve `POST /disks/decommission` mirroring eject (user-data role gate, no
signature, never formats): intent=decommissioned + bind-prune + unmount. **`ReassertGuestBinds` is now
intent-aware** (skips non-enrolled) — the F9-reconnect correctness fix. Operator-signed path untouched.
- **B2b** — `handleStorageDecommission` (migrate-all-or-none): migrate-then-decommission via the migration
done-hook, or decommission-anyway (stop apps, keep HDD_PATH). `agentapi.Decommission` added. Soft-marker
retained. **Change 4:** re-enroll clears the marker (`ClearDecommissioned` had zero callers before).
**"Hiányzó tárhely"** badge for apps on a missing drive.
## Tests (per-commit green: `go build && go vet && go test ./...`)
- `internal/stacks/migrate_test.go` — siblingName, conflict-merge (differ→`(1)`, identical→dedup, re-run
idempotent no `(1)(1)`, 3rd→`(2)`), assert-only verify, skip-dirs, cleanup-only-after-redeploy
(+companion: redeploy-fail → source intact), verify-catches-corruption, resume (no re-copy),
collision-refused, backup-exclusion, single-flight, SSD→drive resolution, cleanup gate.
- `internal/backup/migration_exclusion_test.go` — scheduled DB-dump **skipped** while migrating.
- `internal/web/decommission_test.go` — finalize soft-marks + calls agent (entry retained), re-enroll
clears marker (Change 4), missing-storage label, unflagged-migration no-op.
- **Mutation-proven companions** (fail on pre-fix, pass after revert): migration collision guard, cleanup
gate, Change-4 re-enroll clearing, and (agent) the intent-aware reassert (`disks.go` guard removed →
decommissioned drive re-bound → test FAILS).
## Build / deploy / verify
- Built+pushed `gitea.dooplex.hu/admin/felhom-controller:0.65.0` (192.168.0.180); deployed to guest 9201
via golden/bootstrap → `docker ps`: `:0.65.0 Up (healthy)`, clean startup (`controller_started (0.65.0)`,
no errors), `GET /api/storage/migrate/status``{"job":null}` (idle, wired).
- Built agent v0.32.0 on 180; installed on felhom-pve (`/usr/local/bin/felhom-agent`, backup
`.bak-0.31.0`), `systemctl restart felhom-agent` → active, `--version` 0.32.0.
- **Live-proven (incidental, safe):** on agent restart the new intent-aware re-assert logged
`F9 re-assert: skipping non-enrolled drive (intent-gated) vmid=9201 durable_id=uuid:ce9d… intent=ejected`
— the exact drive that lingered in `guest-binds.json` (B0 spike finding) is now correctly NOT re-bound.
## NOT yet live-validated — awaiting supervised B3
The real end-to-end UI flow with actual data was deliberately NOT run (per the task STOP):
- put data on a drive → decommission (migrate-to-another OR decommission-anyway) → verify data integrity
end-to-end → drive un-enrolled and does NOT auto-mount/re-bind on reconnect → orphaned apps show
"Hiányzó tárhely" → re-enroll clears it. Operator-present, real UI (no agent/CLI shortcuts, per the A4
rule). The engine/endpoint logic is unit-proven and the intent-aware reassert is already proven live by
the restart log above; the data-bearing round-trip is what B3 covers.