716cbcd705
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.2 KiB
4.2 KiB
REPORT — felhom-agent v0.28.0
Backup re-target → offsite PBS (real DR) + operator-signed decommission + restore-test bind-mount fix. Implemented from the "whole-guest backup → felhom-pbs" CC SPEC (PHASE 0 gate → PHASE 1/3 + a validation-discovered fix). Live-validated on demo-felhom (PVE 9.2.2, guest 9201). Secrets (PBS token/fingerprint, encryption key) redacted / stored out-of-band.
PHASE 0 — GATE (proven live before any re-target code)
- Backup → PBS, snapshot mode fires the
create storage snapshot 'vzdump'marker → 8B.2 early-resume/quiesce survives a PBS target (marker is mode-driven, not target-driven). - Restore-test enumerates PBS through the SAME generic
StorageContent(/nodes/<node>/storage/felhom-pbs/contentreturnscontent:"backup"+ ctime/vmid/volid) —PickRestoreCandidate/latestArchiveneed NO PBS-client change. - pct restore from a PBS volid round-trips (storage.cfg encryption key applied transparently). PBS gotchas (
ignore-verified, node-from-UPID, privsep) touch only the verify-API path.
PHASE 1 — backup re-target → felhom-pbs
config.BackupConfig.BackupTarget()returnsbackup.local_backup_targetor, when empty, the new defaultfelhom-pbs(separate hardware = real DR). Configurable; no call site hardcodes it. AllNewBackupRunnersites + restore-testSourceTierroute through it.- Live: demo
agent.jsonlocal_backup_target"local" → felhom-pbs;--selftest=backup -vmid 9201→target=felhom-pbs, snapshot, crash-consistent ✓. Daemon/backup/statusnow reportstarget_id=felhom-pbs. - PBS prune default set on the storage:
prune-backups keep-daily=7,keep-weekly=4,keep-monthly=3(was keep-all at 73% full).
Restore-test bind-mount fix (validation-discovered; scope-approved)
- A slice-10 enrolled guest's data drive is a host bind-mount
mp0; vzrestore refuses it under the privsep token ("restoring 'mpN' to bind mount is only possible for root") — so the restore-test failed for EVERY enrolled guest, independent of backup tier. - Fix: the restore-test reads the SOURCE guest config (vmid parsed from the archive volid) and passes
RestoreLXCOptions.MountOverridesconverting each bind-mountmpN→ a throwaway 1G volume on the restore storage, plus arootfsoverride sized from the source (PVE requires rootfs when mp params are present). Boot-verify doesn't need the data. Storage-backed mounts restore normally; best-effort if the source config is unreadable. - Live: daemon scheduled restore-test from felhom-pbs →
pass:true, verified:"boot+running", source_tier:"pbs"(44s, scratch torn down clean).
PHASE 3 — operator-signed decommission (reachable now)
- The previously-unreachable
IntentDecommissionedis now reached ONLY via a gate-VERIFIED operator signature (classified destructive). Newsignedjobs.DecommissionExecutor(opdecommission) →IntentStore.SetDecommissioned, keyed by the drive's storage durable-id (the watchdog's key, e.g.uuid:<fs-uuid>— NOT the device-levelbyid:/byuuid:ofstorage_wipe), so the intent actually gates remounts. NewExecutorChainserves both wipe + decommission; runner wiring moved below the intent-store open.felhom-opsignbuilds decommission params from-durable-id. No customer/controller UI — operator path is hub jobs-queue → signed-jobs runner. Distinct from a customer-confirmable safe eject.
Tests
internal/signedjobs: decommission happy-path / foreign-op / unbound-refusal / no-store; ExecutorChain dispatch.internal/reconcile:archiveVMID(PBS ct/vm + vzdump forms),bindMountOverrides,rootfsSizeGB/sizeToGB.- Full
go build ./...+ package tests green.
Live deploy
felhom-agent 0.28.0active on demo-felhom (prior binary kept asfelhom-agent.bak-0.27.0); configlocal_backup_target=felhom-pbs, restore-test cadence restored to 86400s.- Golden prune (housekeeping): kept the newest 2 golden (VMID 9100) archives on
local, freed the older 11. - Note (not actioned): the drive's legacy bare-metal
felhom_data(underscore) dir is orphaned under the newfelhom-data(hyphen) namespace on/mnt/felhom-usb; flagged for a real-customer migration path (out of scope here).