labsim: PPPoE HA passes the matrix, and the health check had a real flap bug
Some checks failed
CI/CD / typecheck (push) Failing after 9s
CI/CD / test (push) Failing after 9s
CI/CD / lint (push) Failing after 23s
CI/CD / build (push) Has been skipped
CI/CD / publish-rpm (push) Has been skipped
CI/CD / publish-deb (push) Has been skipped

Full run green: baseline (one AC session, held by the VIP holder), clean
failover (pppoe0 moves in 26s, old master releases), 10 gig down (route falls to
pppoe0 and the LAN is back online in 5s), lease expiry (the guard hangs up), and
a missing peers file (NRestarts=0, no loop). Evidence in
labsim/wan-failover-evidence/.

The 10 gig test found a genuine bug in vrrp-wan-health, not in the sim. GRACE
was measured from PROMOTION, so an established master had no grace at all --
after hours of uptime `now - since` far exceeds any window. The first moment
bond0.53 went down while pppoe0 was mid-redial, the master failed its own check,
shed every VIP, and the peer inherited the same WAN outage and did the same. A
brief WAN blip would have flapped the production pair. The stamp is now
refreshed on every healthy tick, so grace measures time since the box last
demonstrably HAD a WAN -- survivable wherever the gap happens, not only just
after a promotion.

Three harness bugs, all the same shape, all of which produced a confident wrong
answer before being caught:

  - waiting for "exactly one pppoe0 holder" returns INSTANTLY during a handover,
    because it was already true. The useful question is who holds it.
  - judging connectivity on a single ping 20s after a link drop reported an
    outage that had already healed. Poll, do not sample.
  - `-o PreferredAuthentications=password` suits the routers but not the Alpine
    LAN VMs, whose sshd offers keyboard-interactive: ssh exited 255 before
    running anything and the test read that as "the LAN lost the internet". A
    tcpdump on the router showed the pings leaving pppoe0 NATed to
    198.51.100.117 and the replies coming back the whole time. An exit code that
    can mean "the network is broken" or "I could not log in" is not a
    connectivity test, so the check now asserts on what the guest reported.

That last one is why the harness asks the routers and the access concentrator
rather than a client, and why it refuses to run at all while either router still
has a default route via eth2 -- the libvirt-NAT scaffold answers connectivity
checks the WAN under test would have failed.

Still to run: hard failover (destroy the master), and the session-control
replace/deny/disable axis that brackets Vodafone's unknown behaviour and sets
the final GRACE. Nothing applied to production.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DMVzWZgiKW2wquf5z8S1yH
This commit is contained in:
Michal
2026-09-05 19:11:07 +01:00
parent 4efd70c987
commit 93fed7826b
8 changed files with 437 additions and 4 deletions

View File

@@ -115,15 +115,25 @@ mkdir -p "$STATE" 2>/dev/null
for ifc in bond0.53 pppoe0; do
if ip -4 addr show dev "$ifc" 2>/dev/null | grep -q 'inet '; then
echo "$ifc" > "$STATE/wan" 2>/dev/null
# Re-stamp on every healthy tick, so the grace window below measures
# time since this box last DEMONSTRABLY had a WAN.
date +%s > "$STATE/since" 2>/dev/null
exit 0
fi
done
rm -f "$STATE/wan" 2>/dev/null
# Master, no WAN yet, still within the grace window: DHCP negotiation and PPPoE
# dial-up take real time, and the ISP has to accept the cloned MAC arriving on a
# different port. Failing here would demote the new master before it ever had a
# chance, and hand the VIPs straight back -- a flap, not a failover.
# No WAN right now, but there was one within GRACE: ride it out.
#
# `since` is re-stamped on every healthy tick, so this measures time since the
# box last HAD a WAN -- not time since it was promoted. Measuring from promotion
# was wrong in a way that only shows up on an established master: after hours of
# uptime `now - since` far exceeds any grace, so the first moment bond0.53 went
# down and pppoe0 was mid-redial, the master failed its own check, shed every
# VIP, and the peer -- inheriting the same WAN outage -- did the same. Observed
# in labsim: taking the 10 gig down flapped the pair instead of falling back to
# PPPoE. A WAN gap must be survivable wherever it happens, not only just after a
# promotion.
since=$(cat "$STATE/since" 2>/dev/null || echo 0)
[ $(( $(date +%s) - since )) -lt "$GRACE" ] && exit 0