clear_hold (D64 = B) + the box command through the running controller (R-1343), R-1340, R-1341 — tests red first; commit only
gates / gates (push) Successful in 31s

- clear_hold: a fifth verb in the closed operator-action list; lifts a hold of any reason in the RUNNING
  controller (memory + settings.json together), forgets the update's held flag, drops a waiting put-back
  from the app-stop marker (copy kept). Refused on a bad name or no hold. No new event type.
- --clear-restore-hold asks the running controller over <data dir>/ctl/hold.sock (unix, 0600, peer uid
  checked, no TCP); edits settings.json only when no controller answers, and says so (in-guest restart).
- R-1340: the operator's HELD STOPPED mail is built from the hold record (restore kind, mixed cause,
  failed put-back step, database replay or not, kept copy) — never the option-C database story by default.
- R-1341: the OOM WARN line once per new kill (container, start time, kill count); event unchanged.
This commit is contained in:
admin committed 2026-10-29 12:49:46 +01:00
1 parent c7bb776e00
commit 5b3b541602
25 files changed
+1809 -83

No files matched your search

+46
View File
@@ -1,3 +1,49 @@
## Unreleased (2026-10-29, afternoon) — clear_hold (D64 = B), the box command through the running controller (R-1343), R-1340, R-1341; commit only, rides the next release
**MinAgent: 0.158.1** (unchanged). The next release also carries R-1342 (`652a690`, already on main, the entry below).
**No new event type** — the hub records the operator action's result as its own `operator_action` event.
- **`clear_hold` — a fifth verb in the CLOSED operator-action list (operator ruling D64 = B, 2026-10-29 12:10)**
(`internal/report/opactions.go`, wired in `cmd/controller/opactions_wiring.go`; arg = the app's stack name, letters,
digits, `-`, `_`, ≤64 — checked before any handler). It lifts the app's hold of ANY reason in the RUNNING controller
(`backup.AppStopGuard.ClearHoldByOperator` → `settings.ClearRestoreHold`: memory and `settings.json` together), so no
later save can write it back. It starts nothing. Refused, nothing changed: a bad name, an app with no hold. One log
line names who: „hold CLEARED by the operator via the hub, action #<id>". Every reader of the hold (page, start gate,
API, `RestoreHoldFor`, hold reporter) reads the same settings record; the ONE held flag cached elsewhere —
`stacks.Manager`'s „the last update ended held" (it made the crash-loop observer and the nightly update leg skip the
app) — is forgotten too (`ForgetUpdateHeld`). A `putback_pending` hold is also dropped from the app-stop marker, or the
next start with the drive bound would pour the old copy over what the app wrote after the clear; the copy stays on
disk. The hold reporter needs no change: its next tick (≤1 min) sends `app_hold_cleared`.
Tests: `TestOpActions_ClosedList` (updated deliberately), `TestOpActions_ClearHoldBadArgumentIsRefusedAndCallsNothing`,
`TestOpActions_ClearHoldDoneRefusedFailed`, `TestD64_ClearHoldViaTheHub`, `TestD64_ClearHoldRefusals`,
`TestD64_ClearHoldStaysGoneAfterALaterSave`, `TestD64_ClearPutBackPendingDropsTheMarkerEntry`,
`TestD64_TheHoldReporterTellsTheHubAfterTheClear`, `TestD64_ForgetUpdateHeld`, `TestD64_MainWiresTheNewPieces`.
- **R-1343 — the box command `--clear-restore-hold <app>` goes through the running controller** (`cmd/controller/holdclear.go`):
a unix socket `<data dir>/ctl/hold.sock`, 0600 in a 0700 dir, peer uid checked (SO_PEERCRED), nothing on TCP — not
reachable through traefik, the LAN or an app container. Output: „Cleared by the RUNNING controller … no restart is
needed". Only when no controller answers (no socket, or a stale one) does it edit `settings.json`, and it says so,
naming the restart INSIDE the guest (`pct exec <vmid> -- systemctl restart felhom-controller-bootstrap.service`). The
flag's help names the exact guest command. `--restore-holds` (the list) is unchanged.
Tests: `TestR1343_TheBoxCommandClearsThroughTheRunningController` (red with the socket skipped: „the hold came back
after a later save of the running controller" — R-1343 reproduced), `TestR1343_TheBoxCommandFallsBackWhenNoControllerRuns`,
`TestHoldCtl_NotReachableFromOutside`, `TestHoldCtl_UnknownRequestIsRefused`, `TestHoldCtl_ANonSocketFileIsNotReplaced`.
- **R-1340 — the operator's „HELD STOPPED" mail names the real cause** (`cmd/controller/holdmail.go`
`heldStoppedOperatorText`, built from the hold record). Hold writers now record `RestoreKind` (off-site / local),
`MixedCause` (`definition_write` / `put_back` / `interrupted_put_back`), `FailedStep` (the put-back step that failed,
with its error), `DBReplay`, and the kept copy's folder (`settings.RestoreHold`, all `omitempty`). The mail never says
„database" unless the failure was a database replay, never „off-site" for a local restore; a pre-R-1340 mixed hold
names only what its record says. Legs unchanged (`restore-hold`, `restore-hold-mixed`); a local restore's RunKind is
`restore`. Tests (red with the old sentence/record): `TestR1340_UnhealthyStop`, `_UpdateFailed`,
`_RestoreFailedWithADatabase`, `_PutBackWithoutADatabase` (the measured Radicale case), `_PutBackAfterADatabaseReplay`,
`_DefinitionWrite`, `_LocalRestore`, `_PutBackPending`, `_InterruptedPutBack`, `_LegacyMixedHoldAssumesNothing`,
`_NotifyReadsTheHoldRecord`; writer side `TestR1340_AVolumeFailureWhosePutBackStopFailsRecordsTheStepAndNoDatabase`,
`_ADatabaseReplayFailureRecordsTheDatabase`, `_ADefinitionWriteFailureRecordsItsCause`, `_ALocalRestoreRecordsItsKind`,
`_AnInterruptedPutBackRecordsItsCause`. `TestEventMessageWireTextIsFrozen` is untouched (this text is passed through).
- **R-1341 — the OOM line once per NEW kill** (`cmd/controller/oomlog.go` `oomLogGate`, key = container + start time +
kill count): a second scan of the same kill logs nothing; a new kill or a restarted container logs again. The
`app_oom` event call is unchanged. Tests: `TestR1341_ASecondScanOfTheSameKillLogsNothing`, `_ANewKillLogsAgain`,
`_ARestartedContainerLogsAgain`, `_ContainersAreJudgedApart`.
## Unreleased (2026-10-29, after v0.347.0) — R-1342: the restore copy is safe during the stable-start watch; a removed app does not alarm; commit only, rides the next release
**MinAgent: 0.158.1** (unchanged). Found live on Tester 1 at 10:39 CET: a false `backup_run_failures` mail („Gokapi did