R-85 Phase 4: docs — the UNATTENDED path is documented as unproven
- ROADMAP: R-85 row. Code SHIPPED; rotation NOT YET OBSERVED LIVE, stated as such rather than written as done. - Capability map: a new row for UNATTENDED restore-proof, IMPLEMENTED not PROVEN-LIVE, kept distinct from the R-82 row that a MANUAL selftest earned. That distinction is the same one the activation-vs-arrival split made. - 03-host-agent §8: the scheduler covers every tier, oldest-proven first; the spec is per-run; a restore-test joins the one-heavy-op gate. The safety properties that must not be re-derived are listed. - 07: restore-proof recorded as a per-tier property. Doc still NOT ratified. - 06: corrects S4.1's 'the offsite restore-test now runs unattended' — it silently stopped being true when local_backup_target was retargeted to 'local', the SECOND time in that doc that a correct mechanism was broken by its input changing underneath it. - CONTEXT + REUSE. Hub gate green (17 packages, rc=0).
This commit is contained in:
@@ -228,6 +228,33 @@ Tiers double as backup *and* restore-source priority (fastest surviving source f
|
||||
per Part 1: **snapshot** (LVM-thin, transient, whole-guest rollback — not a backup) →
|
||||
**local second storage** (vzdump to dir/NFS/CIFS) → **PBS offsite** (the DR substrate).
|
||||
|
||||
> **Self-restore-test: the scheduler covers EVERY tier, oldest-proven first (R-85, agent v0.104.0).**
|
||||
> It used to build ONE runner on `cfg.Backup.BackupTarget()`, so **the offsite tier's archives were
|
||||
> never candidates** — the DR tier could not be restore-tested unattended at all, which is how
|
||||
> demo-hp's tier sat `applied` with zero snapshots for five days unnoticed. Three things changed:
|
||||
>
|
||||
> - **The spec is built PER RUN** (`backup.SpecBuilder`), not frozen at daemon start. It previously
|
||||
> came from an immediately-invoked function, so `storageTier()`/`restoreTaskTimeout()` were
|
||||
> evaluated once and reused forever — nothing tier-varying was expressible, and any storage-type or
|
||||
> config change stayed stale until the daemon restarted. `SourceTier` comes from **the archive**
|
||||
> (`restoreTierForArchive`), never the configured target: config-derived is what classified a PBS
|
||||
> archive as `local` and killed a 14.46 GB WAN restore at the 10-minute local bound.
|
||||
> - **Rotation is oldest-first** (operator ruling 2026-07-26), persisted at
|
||||
> `<state_dir>/restore-test-state.json` so it survives a restart — an in-memory map would reset
|
||||
> every tier to "never proven" on each deploy and could starve one indefinitely. **Credit only on
|
||||
> SUCCESS**, or a permanently failing tier would look freshly proven and stop being retried. A tier
|
||||
> with no archive **no-ops and the next tier is tried** — a brand-new offsite tier legitimately has
|
||||
> nothing to restore, and that is not an error.
|
||||
> - **A restore-test joins the host-wide one-heavy-operation gate** (`backup.InFlight`), shared with
|
||||
> the local-API backup path. Not a lock concern — the scratch VMID never touches the live guest's
|
||||
> vzdump lock — but a **LINK** one: an offsite restore PULLS multi-GB over the same tunnel an
|
||||
> offsite backup PUSHES one, and at the measured ~33 MB/min upstream running both drives each
|
||||
> toward its timeout, which is how a healthy tier ends up recorded as failed. Callers **defer**;
|
||||
> they never cancel what is already running.
|
||||
>
|
||||
> Unchanged and load-bearing: `onboot=0` on the scratch at restore time, **every NIC link-down before
|
||||
> boot**, journal-before-mutate, guaranteed teardown, and the per-tier restore-task timeout.
|
||||
|
||||
- **Quiescing (controller-driven for app-consistency) — implemented (slice 8B):** an LXC has no
|
||||
fsfreeze (`proxmox-platform.md` §4.2), so app-consistency is the controller's job: it learns a
|
||||
backup is due (`GET /backup/due`, §6) → **quiesces** (stops its app stacks) → `POST /backup` →
|
||||
|
||||
Reference in New Issue
Block a user