v0.5.0-rc1: slice 5 Phase A — storage observe/report + watchdog (read-only, live)
Fill the slice-3 storage_targets stub and add the fast-poll storage watchdog. Read-only this phase; the host-root surface (mounts/SMART/grow/destructive gate) is Phase B. Hub-owned desired manifest is slice 10, so reconcile against it is built-but-unfed. - internal/storage: StorageTarget wire contract, durable_id derivation per type, HostReader seam (procfs/sysfs, root-free), Observer (storage_targets from ListStorage/NodeStorage + host reads, lvmthin thin-pool fill), and the watchdog (third daemon goroutine; debounced out-of-band report on a known target's attach/disconnect transition). - proxmox.Storage: additive parse-only config fields (durable_id sources). - collector StorageObserver seam; Loop.SetTrigger out-of-band report; daemon runs the watchdog as a third goroutine; StorageConfig knobs. - cross-repo golden kept byte-identical with felhom.eu/hub; bidirectional key-set test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,13 +15,38 @@ Module: `gitea.dooplex.hu/admin/felhom-agent` · binary: `felhom-agent` · Go 1.
|
||||
## Layout
|
||||
|
||||
```
|
||||
cmd/felhom-agent/ # entry point + --selftest (wiring only; no daemon loop yet)
|
||||
cmd/felhom-agent/ # entry point + --selftest modes + the daemon (poll loop + reconcile + watchdog)
|
||||
internal/proxmox/ # the Proxmox interaction layer (API-first + fenced root-CLI)
|
||||
internal/config/ # JSON config + env overrides (secrets never logged)
|
||||
internal/log/ # slog setup
|
||||
internal/authz/ # operator signed-op verifier (SSHSIG); durable nonce store
|
||||
internal/hub/ # daemon: host-report collector + Bearer client + resilient poll loop
|
||||
internal/reconcile/ # reconcile engine + reversibility gate + op journal + crash recovery
|
||||
internal/storage/ # storage-target observer + durable_id + fast-poll watchdog (slice 5)
|
||||
configs/agent.example.json
|
||||
```
|
||||
|
||||
## The `storage` package — observe + watchdog (slice 5)
|
||||
|
||||
Read-only this slice (no hub desired-state until slice 10):
|
||||
|
||||
- **Observer** builds the host-report's `storage_targets` from `ListStorage`/`NodeStorage`
|
||||
joined with non-privileged host reads (`/proc/mounts`, `/dev/disk/by-uuid`,
|
||||
`/sys/.../rotational`). It reports each target's `durable_id` (the DR-load-bearing
|
||||
re-attach key: fs-UUID for usb/local-dir, `server:export` for nfs/cifs,
|
||||
`repo+fingerprint` for pbs, `vg/pool` for lvmthin), state, usage, a rotational
|
||||
**class hint** (never authoritative — class is hub-owned), and the lvmthin **thin-pool
|
||||
data fill** (a full pool corrupts every guest on it). SMART is a Phase-B privileged read.
|
||||
- **Watchdog** is the third daemon goroutine: a fast poll (seconds) over the *known*
|
||||
target set that detects an `attached↔disconnected` transition and fires a **debounced,
|
||||
out-of-band** host-report so the hub learns of a USB drop in seconds rather than at the
|
||||
~15-minute cycle. It mutates nothing (the benign re-mount-by-UUID response lands in
|
||||
Phase B). The `HostReader` seam keeps it root-free and unit-testable with no real devices.
|
||||
|
||||
The reported `StorageTarget` shape is a cross-repo contract duplicated in `felhom.eu/hub`;
|
||||
`internal/hub/testdata/host-report.golden.json` is byte-identical with the hub's copy and a
|
||||
bidirectional key-set test guards drift.
|
||||
|
||||
## The `proxmox` package — model
|
||||
|
||||
Two backends, one fixed routing policy (the fence is structural — `Client` never shells out,
|
||||
|
||||
Reference in New Issue
Block a user