rename: appdata/varaverk → appdata/Varaverk (capital V throughout)
This commit is contained in:
+128
-8
@@ -115,6 +115,14 @@
|
||||
# detect_hosts() resolves MY_ID / REMOTE_ID from master.conf at startup.
|
||||
# Exits if the host cannot be identified — prevents running on an unknown machine.
|
||||
#
|
||||
# Partnership Gate
|
||||
# When FALLBACK_PARTNERSHIP_REQUIRED=true, fallback is only permitted when the
|
||||
# local partnership DB reports an active partnership. If partnership goes inactive,
|
||||
# a grace timer starts. After FALLBACK_PARTNERSHIP_SUSPEND_AFTER minutes the loop
|
||||
# suspends: no new FALLBACK is entered, and any live fallback containers are
|
||||
# stopped cleanly. Resumes automatically when partnership becomes active again.
|
||||
# Set FALLBACK_PARTNERSHIP_REQUIRED=false to run fallback without a partnership.
|
||||
#
|
||||
# Silent by Default
|
||||
# State transitions: warn() — always visible. Healthy routine cycles: log()
|
||||
# — suppressed unless --log. Produces no output on clean cycles.
|
||||
@@ -125,8 +133,9 @@
|
||||
#
|
||||
# FALLBACK_STATE_FILE — /boot/config/fallback_state.db (survives reboots)
|
||||
# Keys: state, fallback_start, handback_strikes, tier2_started,
|
||||
# tier3_started, tier4_started. Lives on /boot/ intentionally — if the
|
||||
# server was in FALLBACK when it rebooted, it resumes FALLBACK on restart.
|
||||
# tier3_started, tier4_started, partnership_suspended, partner_lost_at.
|
||||
# Lives on /boot/ intentionally — if the server was in FALLBACK when it
|
||||
# rebooted, it resumes FALLBACK on restart.
|
||||
#
|
||||
# ==============================================================================================
|
||||
# CONFIGURATION
|
||||
@@ -164,6 +173,16 @@
|
||||
# FALLBACK_ENABLED
|
||||
# false = exit cleanly (e.g. remote server being rebuilt). (default: false)
|
||||
#
|
||||
# FALLBACK_PARTNERSHIP_REQUIRED
|
||||
# true = fallback is gated on an active partnership — suspends when no active
|
||||
# partner is found after FALLBACK_PARTNERSHIP_SUSPEND_AFTER minutes.
|
||||
# false = fallback runs standalone regardless of partnership state. (default: true)
|
||||
#
|
||||
# FALLBACK_PARTNERSHIP_SUSPEND_AFTER
|
||||
# Minutes without an active partnership before fallback suspends itself.
|
||||
# Grace period: fallback continues normally during this window.
|
||||
# 0 = suspend immediately when partnership goes inactive. (default: 120)
|
||||
#
|
||||
# FALLBACK_CHECK_INTERVAL
|
||||
# Seconds between connectivity checks. (default: 30)
|
||||
#
|
||||
@@ -309,12 +328,42 @@ state_set() {
|
||||
state_init() {
|
||||
mkdir -p "$(dirname "$FALLBACK_STATE_FILE")"
|
||||
[[ ! -f "$FALLBACK_STATE_FILE" ]] && touch "$FALLBACK_STATE_FILE"
|
||||
[[ -z "$(state_get state)" ]] && state_set state "NORMAL"
|
||||
[[ -z "$(state_get fallback_start)" ]] && state_set fallback_start "0"
|
||||
[[ -z "$(state_get handback_strikes)" ]] && state_set handback_strikes "0"
|
||||
[[ -z "$(state_get tier2_started)" ]] && state_set tier2_started "false"
|
||||
[[ -z "$(state_get tier3_started)" ]] && state_set tier3_started "false"
|
||||
[[ -z "$(state_get tier4_started)" ]] && state_set tier4_started "false"
|
||||
[[ -z "$(state_get state)" ]] && state_set state "NORMAL"
|
||||
[[ -z "$(state_get fallback_start)" ]] && state_set fallback_start "0"
|
||||
[[ -z "$(state_get handback_strikes)" ]] && state_set handback_strikes "0"
|
||||
[[ -z "$(state_get tier2_started)" ]] && state_set tier2_started "false"
|
||||
[[ -z "$(state_get tier3_started)" ]] && state_set tier3_started "false"
|
||||
[[ -z "$(state_get tier4_started)" ]] && state_set tier4_started "false"
|
||||
[[ -z "$(state_get partnership_suspended)" ]] && state_set partnership_suspended "false"
|
||||
[[ -z "$(state_get partner_lost_at)" ]] && state_set partner_lost_at "0"
|
||||
}
|
||||
|
||||
# ==============================================================================================
|
||||
# ── PARTNERSHIP GATE HELPERS ──────────────────────────────────────────────────────────────────
|
||||
# ==============================================================================================
|
||||
|
||||
# Returns 0 (true) if the local partnership DB reports an ACTIVE partnership.
|
||||
# Reads /boot/config/partnership_<hostname>.db — no subprocess, no SSH.
|
||||
check_partnership_active() {
|
||||
local state_file="/boot/config/partnership_${LOCAL_SERVER_NAME}.db"
|
||||
local state
|
||||
state=$(grep "^state=" "$state_file" 2>/dev/null | cut -d= -f2)
|
||||
[[ "$state" == "ACTIVE" ]]
|
||||
}
|
||||
|
||||
# Stop all tiers that were started during a fallback and clear their state flags.
|
||||
# Called when the partnership gate suspends an in-progress fallback.
|
||||
_abort_fallback_containers() {
|
||||
for tier in 4 3 2 1; do
|
||||
[[ "$(state_get "tier${tier}_started")" != "true" ]] && continue
|
||||
warn "Aborting Tier $tier containers — partnership suspended"
|
||||
local containers
|
||||
read -r -a containers <<< "$(get_tier_containers "$tier")"
|
||||
for container in "${containers[@]}"; do
|
||||
[[ -n "$container" ]] && local_stop "$container"
|
||||
done
|
||||
state_set "tier${tier}_started" "false"
|
||||
done
|
||||
}
|
||||
|
||||
# ==============================================================================================
|
||||
@@ -577,6 +626,22 @@ if [[ "$SHOW_STATUS" == true ]]; then
|
||||
|
||||
echo "$ICON_GEAR Enabled: $FALLBACK_ENABLED"
|
||||
echo "$ICON_GEAR Dry Run: $DRY_RUN"
|
||||
|
||||
if [[ "${FALLBACK_PARTNERSHIP_REQUIRED:-true}" == "true" ]]; then
|
||||
SUSPENDED=$(state_get partnership_suspended)
|
||||
PLOST=$(state_get partner_lost_at)
|
||||
if [[ "$SUSPENDED" == "true" ]]; then
|
||||
echo "$ICON_GEAR Partnership: SUSPENDED (no active partnership)"
|
||||
elif [[ -n "$PLOST" && "$PLOST" != "0" ]]; then
|
||||
PLOST_MIN=$(( ($(date +%s) - PLOST) / 60 ))
|
||||
echo "$ICON_GEAR Partnership: GRACE (${PLOST_MIN}min / ${FALLBACK_PARTNERSHIP_SUSPEND_AFTER:-120}min until suspend)"
|
||||
else
|
||||
echo "$ICON_GEAR Partnership: ACTIVE"
|
||||
fi
|
||||
else
|
||||
echo "$ICON_GEAR Partnership: REQUIRED=false (standalone mode)"
|
||||
fi
|
||||
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
exit 0
|
||||
fi
|
||||
@@ -796,6 +861,61 @@ while [[ "$FALLBACK_RUNNING" == true ]]; do
|
||||
|
||||
log "Remote: $REMOTE_UP | Internet: $INTERNET_UP | State: $CURRENT_STATE"
|
||||
|
||||
# ── Partnership gate ──────────────────────────────────────────────────────────────────────
|
||||
# When FALLBACK_PARTNERSHIP_REQUIRED=true, a fallback without an active partner is
|
||||
# meaningless — who are we covering for? The gate suspends the loop after a grace
|
||||
# period and aborts any live fallback containers. Clears automatically when partnership
|
||||
# is restored.
|
||||
if [[ "${FALLBACK_PARTNERSHIP_REQUIRED:-true}" == "true" ]]; then
|
||||
if check_partnership_active; then
|
||||
# Partnership healthy — clear any accumulated grace state
|
||||
if [[ "$(state_get partnership_suspended)" == "true" ]]; then
|
||||
warn "Active partnership restored — re-enabling fallback monitoring"
|
||||
state_set partnership_suspended "false"
|
||||
state_set partner_lost_at "0"
|
||||
notify "Fallback re-enabled on $(hostname) — active partnership restored" \
|
||||
"Fallback" "normal"
|
||||
elif [[ "$(state_get partner_lost_at)" != "0" ]]; then
|
||||
log "Partnership recovered within grace window — resetting timer"
|
||||
state_set partner_lost_at "0"
|
||||
fi
|
||||
else
|
||||
PARTNER_LOST_AT=$(state_get partner_lost_at)
|
||||
if [[ -z "$PARTNER_LOST_AT" || "$PARTNER_LOST_AT" == "0" ]]; then
|
||||
warn "No active partnership detected — grace timer started (${FALLBACK_PARTNERSHIP_SUSPEND_AFTER:-120}min before suspend)"
|
||||
state_set partner_lost_at "$NOW"
|
||||
PARTNER_LOST_AT=$NOW
|
||||
fi
|
||||
|
||||
PARTNER_LOST_MIN=$(( (NOW - PARTNER_LOST_AT) / 60 ))
|
||||
SUSPEND_AFTER=${FALLBACK_PARTNERSHIP_SUSPEND_AFTER:-120}
|
||||
|
||||
if [[ "$(state_get partnership_suspended)" == "true" || "$PARTNER_LOST_MIN" -ge "$SUSPEND_AFTER" ]]; then
|
||||
# Suspend — abort any live fallback containers, then skip this cycle entirely
|
||||
if [[ "$(state_get partnership_suspended)" != "true" ]]; then
|
||||
warn "No active partnership for ${PARTNER_LOST_MIN}min — suspending fallback"
|
||||
state_set partnership_suspended "true"
|
||||
notify "Fallback suspended on $(hostname) — no active partnership for ${PARTNER_LOST_MIN}min" \
|
||||
"Fallback" "warning"
|
||||
fi
|
||||
if [[ "$CURRENT_STATE" == "FALLBACK" ]]; then
|
||||
warn "Aborting in-progress fallback — partnership suspended"
|
||||
_abort_fallback_containers
|
||||
state_set state "NORMAL"
|
||||
state_set fallback_start "0"
|
||||
state_set handback_strikes "0"
|
||||
notify "Fallback aborted on $(hostname) — no active partnership, containers stopped" \
|
||||
"Fallback" "warning"
|
||||
fi
|
||||
log "Partnership suspended — skipping fallback cycle"
|
||||
sleep "$FALLBACK_CHECK_INTERVAL" & wait $!
|
||||
continue
|
||||
else
|
||||
log "No active partnership — ${PARTNER_LOST_MIN}min elapsed / ${SUSPEND_AFTER}min until suspend"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# ════════════════════════════════════════════════════════════════
|
||||
# NORMAL STATE
|
||||
# ════════════════════════════════════════════════════════════════
|
||||
|
||||
Reference in New Issue
Block a user