Fix dead/incorrect vars and consolidate duplicated logic into common.sh
Codebase-wide audit pass: fixed real bugs (SSH hangs missing BatchMode, local-outside-function no-ops, variable name collisions, a truncated ratio calc, wrong state-dir path, DARK vs NO_INTERNET drift, and more), then pulled logic that was duplicated across multiple scripts — arr cleanup safety gates, docker restart ordering, container maintenance stop/restart, watchdog state-file helpers, partnership role resolution, cert expiry checks, remote node discovery, and TMDB discovery scoring — into common.sh so each now has a single implementation.
This commit is contained in:
@@ -249,22 +249,7 @@ fi
|
||||
detect_hosts
|
||||
|
||||
# ── Derive owner and mirror from PARTNERSHIP_OWNER_HOST ───────────────────────────────────────
|
||||
OWNER_ID="${PARTNERSHIP_OWNER_HOST:-HOST1}" # e.g. "HOST1"
|
||||
MIRROR_ID=$( [[ "$OWNER_ID" == "HOST1" ]] && echo "HOST2" || echo "HOST1" )
|
||||
|
||||
OWNER="${!OWNER_ID}" # hostname string
|
||||
MIRROR="${!MIRROR_ID}"
|
||||
# SSH_KEY (set by detect_hosts) is this server's own private key.
|
||||
# The remote accepts it because this server's PUBLIC key was installed there via ssh_setup.sh.
|
||||
# With sparse checkout, each server only has its own host{N}.conf — the other server's
|
||||
# key path is never available here. Use SSH_KEY for all outbound SSH regardless of mode.
|
||||
MIRROR_SSH_KEY="$SSH_KEY"
|
||||
OWNER_SSH_KEY="$SSH_KEY"
|
||||
|
||||
AM_OWNER=false
|
||||
AM_MIRROR=false
|
||||
[[ "$MY_ID" == "$OWNER_ID" ]] && AM_OWNER=true
|
||||
[[ "$MY_ID" == "$MIRROR_ID" ]] && AM_MIRROR=true
|
||||
partnership_resolve_roles
|
||||
|
||||
# State files
|
||||
LOCAL_STATE_FILE="${STATE_DIR}/partnership_${LOCAL_SERVER_NAME}.db"
|
||||
@@ -355,7 +340,7 @@ push_state_to_remote() {
|
||||
warn "DRY RUN — would push state file to remote"
|
||||
return 0
|
||||
fi
|
||||
timeout "$SSH_TIMEOUT" scp -i "$ssh_key" -o ConnectTimeout="$SSH_TIMEOUT" \
|
||||
timeout "$SSH_TIMEOUT" scp -i "$ssh_key" -o ConnectTimeout="$SSH_TIMEOUT" -o BatchMode=yes \
|
||||
"$local_file" "root@${remote_ip}:${local_file}" 2>/dev/null && \
|
||||
echo "State file pushed to remote ✅" || \
|
||||
warn "Could not push state file to remote — will propagate on next sync"
|
||||
@@ -364,7 +349,7 @@ push_state_to_remote() {
|
||||
read_remote_state() {
|
||||
local remote_ip="$1" ssh_key="$2" remote_file="$3"
|
||||
timeout "$SSH_TIMEOUT" ssh -i "$ssh_key" \
|
||||
-o ConnectTimeout="$SSH_TIMEOUT" root@"$remote_ip" \
|
||||
-o ConnectTimeout="$SSH_TIMEOUT" -o BatchMode=yes root@"$remote_ip" \
|
||||
"cat '$remote_file' 2>/dev/null" 2>/dev/null
|
||||
}
|
||||
|
||||
@@ -524,34 +509,9 @@ gather_partner_fallback_containers() {
|
||||
done
|
||||
}
|
||||
|
||||
# Read a scalar var from the mirror's own config via SSH.
|
||||
# Sources load_config.sh + detect_hosts() on the remote so HOST* aliasing works.
|
||||
read_remote_conf_var() {
|
||||
local mirror_ip="$1" var_name="$2"
|
||||
timeout "$SSH_TIMEOUT" ssh -i "$SSH_KEY" \
|
||||
-o ConnectTimeout="$SSH_TIMEOUT" -o BatchMode=yes root@"$mirror_ip" \
|
||||
"source '$SCRIPT_DIR/../load_config.sh' 2>/dev/null
|
||||
detect_hosts 2>/dev/null
|
||||
printf '%s' \"\${${var_name}:-}\"" 2>/dev/null
|
||||
}
|
||||
# read_remote_conf_var() / read_remote_conf_array() — provided by common.sh
|
||||
|
||||
# Read an array var from the mirror's own config via SSH — one element per line.
|
||||
read_remote_conf_array() {
|
||||
local mirror_ip="$1" var_name="$2"
|
||||
timeout "$SSH_TIMEOUT" ssh -i "$SSH_KEY" \
|
||||
-o ConnectTimeout="$SSH_TIMEOUT" -o BatchMode=yes root@"$mirror_ip" \
|
||||
"source '$SCRIPT_DIR/../load_config.sh' 2>/dev/null
|
||||
detect_hosts 2>/dev/null
|
||||
printf '%s\n' \"\${${var_name}[@]:-}\"" 2>/dev/null
|
||||
}
|
||||
|
||||
# Returns just the short name portion: "unRAID-Gmer4Lfe" → "Gmer4Lfe"
|
||||
derive_short_name() {
|
||||
local hostname="$1"
|
||||
local short="${hostname,,}"
|
||||
[[ "$short" == unraid-* ]] && short="${short:7}"
|
||||
echo "${short^}"
|
||||
}
|
||||
# derive_short_name() — provided by common.sh
|
||||
|
||||
# Start this server's own parked containers after partnership ends.
|
||||
start_own_stack() {
|
||||
@@ -644,7 +604,7 @@ cleanup_owner_containers_on_mirror() {
|
||||
|
||||
local container_list
|
||||
container_list=$(timeout "$SSH_TIMEOUT" ssh -i "$SSH_KEY" \
|
||||
-o ConnectTimeout="$SSH_TIMEOUT" root@"$mirror_ip" \
|
||||
-o ConnectTimeout="$SSH_TIMEOUT" -o BatchMode=yes root@"$mirror_ip" \
|
||||
"docker ps -a --format '{{.Names}}' 2>/dev/null | grep -i -- '-${owner_short}$'" 2>/dev/null)
|
||||
|
||||
if [[ -z "$container_list" ]]; then
|
||||
@@ -658,12 +618,12 @@ cleanup_owner_containers_on_mirror() {
|
||||
# Collect appdata paths before removal
|
||||
local appdata_paths
|
||||
appdata_paths=$(timeout "$SSH_TIMEOUT" ssh -i "$SSH_KEY" \
|
||||
-o ConnectTimeout="$SSH_TIMEOUT" root@"$mirror_ip" \
|
||||
-o ConnectTimeout="$SSH_TIMEOUT" -o BatchMode=yes root@"$mirror_ip" \
|
||||
"docker inspect --format '{{range .HostConfig.Binds}}{{println .}}{{end}}' '$container' 2>/dev/null \
|
||||
| awk -F: '{print \$1}' | grep '^/mnt/.*/appdata'" 2>/dev/null)
|
||||
|
||||
timeout "$SSH_TIMEOUT" ssh -i "$SSH_KEY" \
|
||||
-o ConnectTimeout="$SSH_TIMEOUT" root@"$mirror_ip" \
|
||||
-o ConnectTimeout="$SSH_TIMEOUT" -o BatchMode=yes root@"$mirror_ip" \
|
||||
"docker stop '$container' >/dev/null 2>&1
|
||||
docker rm '$container' >/dev/null 2>&1 && echo removed" 2>/dev/null | \
|
||||
grep -q removed && \
|
||||
@@ -674,7 +634,7 @@ cleanup_owner_containers_on_mirror() {
|
||||
while IFS= read -r path; do
|
||||
[[ -z "$path" ]] && continue
|
||||
timeout "$SSH_TIMEOUT" ssh -i "$SSH_KEY" \
|
||||
-o ConnectTimeout="$SSH_TIMEOUT" root@"$mirror_ip" \
|
||||
-o ConnectTimeout="$SSH_TIMEOUT" -o BatchMode=yes root@"$mirror_ip" \
|
||||
"rm -rf '$path' && echo removed" 2>/dev/null | grep -q removed && \
|
||||
echo " Appdata removed on $MIRROR: $path ✅" || \
|
||||
warn " Failed to remove appdata on $MIRROR: $path"
|
||||
@@ -707,7 +667,7 @@ start_mirror_own_stack() {
|
||||
continue
|
||||
fi
|
||||
timeout "$SSH_TIMEOUT" ssh -i "$SSH_KEY" \
|
||||
-o ConnectTimeout="$SSH_TIMEOUT" root@"$mirror_ip" \
|
||||
-o ConnectTimeout="$SSH_TIMEOUT" -o BatchMode=yes root@"$mirror_ip" \
|
||||
"docker start '$container' >/dev/null 2>&1 && echo started" 2>/dev/null | \
|
||||
grep -q started && \
|
||||
echo "$container started on $MIRROR ✅" || \
|
||||
@@ -881,7 +841,7 @@ check_both_healthy() {
|
||||
[[ -z "$mirror_ip" ]] && { error "Cannot resolve $MIRROR Tailscale IP"; return 1; }
|
||||
|
||||
timeout "$SSH_TIMEOUT" ssh -i "$MIRROR_SSH_KEY" \
|
||||
-o ConnectTimeout="$SSH_TIMEOUT" root@"$mirror_ip" \
|
||||
-o ConnectTimeout="$SSH_TIMEOUT" -o BatchMode=yes root@"$mirror_ip" \
|
||||
"mountpoint -q '$REMOTE_STORAGE_PATH' && timeout 10 docker ps" >/dev/null 2>&1 || {
|
||||
error "Mirror $MIRROR not healthy"
|
||||
return 1
|
||||
@@ -913,7 +873,8 @@ do_final_sync() {
|
||||
warn "Final sync complete — mirror has current state ✅"
|
||||
}
|
||||
|
||||
# Safe master.conf modification with error handling
|
||||
# Safe master.conf modification with error handling — appends the key if not already present,
|
||||
# since sed -i returns 0 whether or not it matched anything.
|
||||
update_master_conf() {
|
||||
local key="$1" value="$2"
|
||||
local conf="$CONF_DIR/master.conf"
|
||||
@@ -921,12 +882,22 @@ update_master_conf() {
|
||||
error "master.conf not found at $conf"
|
||||
return 1
|
||||
fi
|
||||
if sed -i "s|^[[:space:]]*${key}=.*| ${key}=${value}|" "$conf" 2>/dev/null; then
|
||||
echo "master.conf updated: ${key}=${value}"
|
||||
return 0
|
||||
if grep -q "^[[:space:]]*${key}=" "$conf" 2>/dev/null; then
|
||||
if sed -i "s|^[[:space:]]*${key}=.*| ${key}=${value}|" "$conf" 2>/dev/null; then
|
||||
echo "master.conf updated: ${key}=${value}"
|
||||
return 0
|
||||
else
|
||||
error "Failed to update master.conf: ${key}=${value}"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
error "Failed to update master.conf: ${key}=${value}"
|
||||
return 1
|
||||
if echo " ${key}=${value}" >> "$conf" 2>/dev/null; then
|
||||
echo "master.conf updated: ${key}=${value} (appended)"
|
||||
return 0
|
||||
else
|
||||
error "Failed to append to master.conf: ${key}=${value}"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -1162,13 +1133,7 @@ if [[ "$MODE" == "onboard" ]]; then
|
||||
echo ""
|
||||
echo "Enabling partnership in master.conf..."
|
||||
if [[ "$DRY_RUN" == false ]]; then
|
||||
_master_conf="$CONF_DIR/master.conf"
|
||||
if grep -q "^[[:space:]]*PARTNERSHIP_ENABLED=" "$_master_conf" 2>/dev/null; then
|
||||
sed -i "s|^[[:space:]]*PARTNERSHIP_ENABLED=.*|PARTNERSHIP_ENABLED=true|" "$_master_conf"
|
||||
else
|
||||
echo "PARTNERSHIP_ENABLED=true" >> "$_master_conf"
|
||||
fi
|
||||
echo "PARTNERSHIP_ENABLED=true in master.conf ✅"
|
||||
update_master_conf "PARTNERSHIP_ENABLED" "true"
|
||||
platform_push_conf | while IFS= read -r line; do log "$line"; done
|
||||
else
|
||||
warn "DRY RUN — would set PARTNERSHIP_ENABLED=true in master.conf and push"
|
||||
@@ -1435,9 +1400,9 @@ if false; then
|
||||
|
||||
# Update remote master.conf
|
||||
timeout "$SSH_TIMEOUT" ssh -i "$NEW_MIRROR_SSH_KEY" \
|
||||
-o ConnectTimeout="$SSH_TIMEOUT" root@"$NEW_MIRROR_IP" \
|
||||
-o ConnectTimeout="$SSH_TIMEOUT" -o BatchMode=yes root@"$NEW_MIRROR_IP" \
|
||||
"sed -i 's|^[[:space:]]*PARTNERSHIP_OWNER_HOST=.*| PARTNERSHIP_OWNER_HOST=\"$NEW_OWNER_ID\"|' \
|
||||
'$SCRIPT_DIR/../master.conf'" 2>/dev/null && \
|
||||
'$SCRIPT_DIR/../Configurations/master.conf'" 2>/dev/null && \
|
||||
echo "Remote master.conf updated ✅" || \
|
||||
error "Failed to update remote master.conf — update manually"
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user