docs(report): STOP-2 evidence — the incident replayed and PREVENTED (tunnel never dropped)
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
# REPORT — TASK-D Part 3: the guest-network watchdog (R-54) · felhom-agent v0.91.2 → **v0.92.1**
|
||||
|
||||
**Date:** 2026-07-21 · Trunk, pushed to `main`. **Baseline:** `08b55a1` (clean, == `origin/main`).
|
||||
**Deployed and running on felhom-pve.** The healthy-cycle leg is **PROVEN LIVE**; the heal leg
|
||||
(STOP-2, a deliberate replay of the 2026-07-20 incident) is operator-present and has **not** run.
|
||||
**Deployed, running on felhom-pve, and STOP-2 RAN — the incident was replayed and the watchdog
|
||||
prevented it (§6b).** Every claim below was observed.
|
||||
|
||||
---
|
||||
|
||||
@@ -174,6 +174,69 @@ so STOP-2's heal chain is visible in journald. **Revert it to `info` after STOP-
|
||||
|
||||
---
|
||||
|
||||
## 6b. STOP-2 — the incident replay (operator-present, 2026-07-21)
|
||||
|
||||
The 2026-07-20 kill, repeated deliberately. **The `/proc/<pid>/cgroup` check the incident produced
|
||||
was applied before the kill** — the script refuses unless the pid's cgroup is guest 9201's, which is
|
||||
the rule that would have prevented the original outage:
|
||||
|
||||
```
|
||||
GATE OK — pid 336708 belongs to guest 9201 (0::/lxc/9201/ns/.lxc)
|
||||
KILL at 2026-07-21T10:43:18Z / 12:43:18 CEST
|
||||
after kill: no dhclient running; address 192.168.0.104/24 STILL PRESENT (valid_lft 4998s); default route STILL PRESENT
|
||||
```
|
||||
|
||||
That second line is the whole point: the box looked perfectly healthy, with ~83 minutes of lease
|
||||
left before any symptom would appear.
|
||||
|
||||
| Time (CEST) | Event |
|
||||
|---|---|
|
||||
| 12:43:15 | `DEBUG guest network healthy … dhclient_alive=true` — last good cycle |
|
||||
| 12:43:18 | **kill -9** |
|
||||
| **12:44:15** | **detected in 57 s, on process liveness alone** — `unhealthy (first bad probe — not acting yet) bad_probes=1 required=2`, detail *"dhclient is not running — the lease will not be renewed (the 2026-07-20 failure mode; address still present, renewal already dead)"* |
|
||||
| 12:45:15 | second consecutive bad probe → `healing`, then `running heal command … cmd="pct exec 9201 -- dhclient -pf /run/dhclient.eth0.pid -lf /var/lib/dhcp/dhclient.eth0.leases eth0"` |
|
||||
| **12:45:18** | **`guest network healed` ip=192.168.0.104 has_route=true dhclient_alive=true heals_last_hour=1** |
|
||||
|
||||
**Healed 120 seconds after the kill — roughly 80 minutes before the outage would have begun.** The
|
||||
strongest evidence is therefore what did *not* happen, verified from inside the guest:
|
||||
|
||||
| Check | Result |
|
||||
|---|---|
|
||||
| `cloudflared` | **`Up 29 hours`** — the tunnel never dropped, never reconnected |
|
||||
| DNS `gitea.dooplex.hu` | OK |
|
||||
| hub | **302 in 0.16 s** |
|
||||
| `https://felhom.demo-felhom.eu/` | **302 in 0.25 s** |
|
||||
| new dhclient | pid 2043719, `cgroup=0::/lxc/9201/ns/.lxc`, argv byte-identical to the original |
|
||||
|
||||
On 2026-07-20 every one of those was dead for 1h15m. This time the outage was **prevented**, not
|
||||
detected.
|
||||
|
||||
**The negative legs, both clean.** Exactly ONE heal (`grep -c` = 1), zero re-heals, zero
|
||||
guestnet WARN/ERROR in the quiet window that followed, and the healthy Debug line kept appearing
|
||||
each cycle — so "no alarms" stayed distinguishable from "not probing".
|
||||
|
||||
**An unplanned damper proof, against a REAL transient.** STOP-1's guest reboot at 12:53 caught the
|
||||
guest mid-boot:
|
||||
|
||||
```
|
||||
12:53:16 INFO guest network unhealthy (first bad probe — not acting yet) detail="no IPv4 address on eth0" bad_probes=1
|
||||
12:54:15 DEBUG guest network healthy …
|
||||
12:54:15 INFO guest network recovered previous_state=unhealthy
|
||||
```
|
||||
|
||||
One bad probe, **no action**, then recovery. The two-consecutive-probes rule and the boot-race guard
|
||||
did exactly what they exist for — a booting guest was not injected with a dhclient — and this was a
|
||||
genuine transient, not a scripted one.
|
||||
|
||||
## 6c. What could NOT be verified here
|
||||
|
||||
The `guest_net` stanza **on the wire**. `--selftest=hub` builds its own one-shot collector and never
|
||||
wires the guestnet reporter, so it would print a misleading absence — using it as evidence would be
|
||||
worse than having none. (That divergence between the selftest collector and the daemon's is itself
|
||||
worth a small fix; the same comment already exists in the code for the pbs reporter.) The stanza is
|
||||
proven through the production `Collect` path by test, and `SetGuestNetReporter` is proven called by
|
||||
the AST wiring test, but seeing it in a real hub report needs the operator UI.
|
||||
|
||||
## 7. Deliverables
|
||||
|
||||
- `c0966d7` — v0.92.0: the watchdog, the report block, config, tests.
|
||||
@@ -184,8 +247,7 @@ so STOP-2's heal chain is visible in journald. **Revert it to `info` after STOP-
|
||||
|
||||
## 8. Operator actions outstanding
|
||||
|
||||
1. **STOP-2** — the incident replay (kill 9201's dhclient, watch it heal within ≤2 cycles). It is
|
||||
the deliberate reproduction of a real outage, so it is operator-present by construction.
|
||||
1. ~~STOP-2~~ — **DONE 2026-07-21, passed** (§6b).
|
||||
2. **STOP-3** — Day-0 manifest Agent → **0.92.1** / `7424bc1c3c533eff9157e15a18d4635c624931f5a479a48126de77a94e6a3d4d`
|
||||
(wrapper sha unchanged — `configs/felhom-pbs-apply` was not touched). MinAgent is the operator's
|
||||
call; 0.92.1 is safe once felhom-pve has converged, which it has.
|
||||
|
||||
Reference in New Issue
Block a user