Flip fallback coverage model: each host defines its own recovery profile

Previously HOST1 defined what it would run for HOST2 (FALLBACK_HOST1_COVERS_HOST2_TIER*).
Now each host defines what it wants run when IT goes down (FALLBACK_HOST1_TIER*), and the
covering server reads the down host's conf via the RAM/persistent cache.

get_tier_containers() reads FALLBACK_${REMOTE_ID}_TIER* instead of
FALLBACK_${MY_ID}_COVERS_${REMOTE_ID}_TIER*. Tier data migrated to the correct host confs.
Writeback paths and delays were already REMOTE_ID-based — no change needed there.
This commit is contained in:
Gmer4Lfe
2026-06-19 17:44:53 -04:00
parent 7332eb81e0
commit b27b2d62f5
3 changed files with 23 additions and 24 deletions
+12 -12
View File
@@ -40,8 +40,8 @@
# ── FALLBACK ─────────────────────────────────────────────────────────────────────────────── # ── FALLBACK ───────────────────────────────────────────────────────────────────────────────
# DDNS DDNS containers managed by this host # DDNS DDNS containers managed by this host
# INTERNET LOSS containers stopped when internet is lost # INTERNET LOSS containers stopped when internet is lost
# FALLBACK TIERS what this host runs for the remote per tier # FALLBACK TIERS what this host wants the partner to run when this host is down
# TIER DELAYS delays before each tier activates # TIER DELAYS how long this host must be down before each tier activates
# RSYNC WRITEBACK appdata synced back on handback # RSYNC WRITEBACK appdata synced back on handback
# #
# ── DOCKER ───────────────────────────────────────────────────────────────────────────────── # ── DOCKER ─────────────────────────────────────────────────────────────────────────────────
@@ -255,27 +255,27 @@
# "MyServer.com" # "MyServer.com"
) )
# ━━━ Fallback Tiers — HOSTN Runs for Partner ━━━ # ━━━ Fallback Tiers — What HOSTN Wants Covered When Down ━━━
# Containers this host starts when the partner goes down. # Containers the partner starts for HOSTN when HOSTN goes down.
# Replace REMOTE_ID below with the actual remote host ID (HOST1, HOST2, etc.) # Tier 1 is always immediate. Higher tiers activate after HOSTN_TIER*_DELAY minutes.
FALLBACK_HOSTN_COVERS_REMOTE_ID_TIER1=( FALLBACK_HOSTN_TIER1=(
# "Partner-DDNS-Container" # "MyServer-DDNS-Container"
) )
FALLBACK_HOSTN_COVERS_REMOTE_ID_TIER2=( FALLBACK_HOSTN_TIER2=(
# "container-placeholder" # "container-placeholder"
) )
FALLBACK_HOSTN_COVERS_REMOTE_ID_TIER3=( FALLBACK_HOSTN_TIER3=(
# "container-placeholder" # "container-placeholder"
) )
FALLBACK_HOSTN_COVERS_REMOTE_ID_TIER4=( FALLBACK_HOSTN_TIER4=(
# "container-placeholder" # "container-placeholder"
) )
# ━━━ Tier Delays — This Host's Outage Timers ━━━ # ━━━ Tier Delays — HOSTN Outage Timers ━━━
# How long THIS host must be down before each tier activates on the partner. # How long HOSTN must be down before each tier activates on the partner.
HOSTN_TIER2_DELAY=240 # 4 hours HOSTN_TIER2_DELAY=240 # 4 hours
HOSTN_TIER3_DELAY=720 # 12 hours HOSTN_TIER3_DELAY=720 # 12 hours
HOSTN_TIER4_DELAY=1440 # 24 hours HOSTN_TIER4_DELAY=1440 # 24 hours
+9 -9
View File
@@ -75,10 +75,10 @@
# failed handback: containers stop on the covering server, remote goes down # failed handback: containers stop on the covering server, remote goes down
# again mid-rsync. Strikes prevent this. # again mid-rsync. Strikes prevent this.
# #
# MY_ID-Based Routing # REMOTE_ID-Based Coverage Config
# All tier arrays, DDNS lists, and writeback paths are selected via MY_ID # Tier arrays, writeback paths, and delays are all defined in the covered
# set by detect_hosts() — not hostname string comparison. The same script # host's own conf and read via REMOTE_ID — not MY_ID. Each host owns its
# and same config file handle both directions symmetrically. # complete recovery profile. The same script handles both directions.
# #
# ============================================================================================== # ==============================================================================================
# OPERATIONAL SAFEGUARDS # OPERATIONAL SAFEGUARDS
@@ -150,9 +150,10 @@
# FALLBACK_HOST*_STOP_ON_NO_NET # FALLBACK_HOST*_STOP_ON_NO_NET
# Containers stopped when this host loses internet # Containers stopped when this host loses internet
# #
# FALLBACK_HOST*_COVERS_HOST*_TIER14 # FALLBACK_HOST*_TIER14
# Containers this host starts for the remote when remote is down, by tier. # Containers started on this host when the partner is down — defined in the
# Variable pattern: FALLBACK_${MY_ID}_COVERS_${REMOTE_ID}_TIER${N} # partner's own conf (what the partner wants covered). Read via REMOTE_ID.
# Variable pattern: FALLBACK_${REMOTE_ID}_TIER${N}
# #
# HOST*_TIER2_DELAY / TIER3_DELAY / TIER4_DELAY # HOST*_TIER2_DELAY / TIER3_DELAY / TIER4_DELAY
# Minutes after FALLBACK entry before activating each tier. # Minutes after FALLBACK entry before activating each tier.
@@ -537,8 +538,7 @@ remote_ddns_stop() {
get_tier_containers() { get_tier_containers() {
local tier="$1" local tier="$1"
local remote_id="${REMOTE_ID}" local var_name="FALLBACK_${REMOTE_ID}_TIER${tier}"
local var_name="FALLBACK_${MY_ID}_COVERS_${remote_id}_TIER${tier}"
eval "echo \"\${${var_name}[@]:-}\"" eval "echo \"\${${var_name}[@]:-}\""
} }
+2 -3
View File
@@ -67,11 +67,10 @@ function vv_fb_remote_running(string $ip, string $sshKey): array {
// ── Covers — what a node runs for the other when it's down ─────────────────── // ── Covers — what a node runs for the other when it's down ───────────────────
function vv_fb_covers(string $covering, string $remote, string $coveringRaw, string $remoteRaw): array { function vv_fb_covers(string $covering, string $remote, string $coveringRaw, string $remoteRaw): array {
$cu = strtoupper($covering); // HOST1 $ru = strtoupper($remote); // HOST2 — covered host owns its own tier lists
$ru = strtoupper($remote); // HOST2
$tiers = []; $tiers = [];
for ($t = 1; $t <= 4; $t++) { for ($t = 1; $t <= 4; $t++) {
$tiers["tier$t"] = vv_fb_bash_array($coveringRaw, "FALLBACK_{$cu}_COVERS_{$ru}_TIER{$t}"); $tiers["tier$t"] = vv_fb_bash_array($remoteRaw, "FALLBACK_{$ru}_TIER{$t}");
} }
// Delays: how long the remote (covered) host must be down before each tier fires. // Delays: how long the remote (covered) host must be down before each tier fires.
// Stored in the *remote* host's conf as REMOTE_TIER*_DELAY. // Stored in the *remote* host's conf as REMOTE_TIER*_DELAY.