Wire the folder-layout mirroring into onboard Step 12

A fresh install reproduced the single lump folder because Step 12 only ever called fallback_folder.php; it now mirrors the owner's layout first and hands the fallback folder just what is left.
This commit is contained in:
Gmer4Lfe
2026-08-17 14:13:17 -04:00
parent e3ed5a53f2
commit 49372996ac
3 changed files with 56 additions and 5 deletions
+7
View File
@@ -165,6 +165,13 @@
"/mnt/user/appdata-Fallback/Critical-Data" # critical-data profile — the auth stack
)
# Containers that belong in "<PartnerShort>-Fallback" on the mirror rather than in a mirrored
# copy of this host's folder layout — the ones that exist there only to cover this host going
# dark. Everything else the onboard deploys is filed onto the same shelf it occupies here
# (Arrs Stack, Networking, Databases…), because it runs on the mirror continuously.
# Empty is the normal state: leave it empty unless a container is genuinely failover-only.
HOSTN_PARTNERSHIP_FALLBACK_ONLY=()
# XML templates pushed to mirror during onboard — auth stack.
# Dependencies (databases) must come before apps that depend on them.
HOSTN_PARTNERSHIP_AUTH_STACK=(
+48 -5
View File
@@ -42,8 +42,11 @@
# Step 10: Conf push — push master.conf + setup state to all listed hosts
# Step 11: Service discovery — conf_populate.sh on the mirror, last, once the stacks it
# would discover are actually deployed there
# Step 12: Container grouping — file our containers on the mirror under "<OwnerShort>-Fallback",
# icon resolved here and passed over: the mirror has no Emby key
# Step 12: Container grouping — reproduce this host's folder layout on the mirror (Arrs
# Stack, Networking, Databases…) for the containers deployed
# there; only unfiled or PARTNERSHIP_FALLBACK_ONLY entries go
# to "<OwnerShort>-Fallback". Icon resolved here and passed
# over: the mirror has no Emby key
#
# Phase 3 (media seed) is NOT part of the above. Onboard ends at Phase 2 — connected, running,
# and saying so. Seeding is a separate operator-triggered phase; see --phase3-only. With
@@ -1268,23 +1271,63 @@ else
FOLDER_OK=true
else
_ff_local="$SCRIPTS_ROOT/Plugin/$PLATFORM/Tools/fallback_folder.php"
_mf_local="$SCRIPTS_ROOT/Plugin/$PLATFORM/Tools/mirror_folders.php"
_icon=$(php "$_ff_local" --host="$MY_ID" --icon-only 2>/dev/null || true)
[[ -z "$_icon" ]] && log "No icon resolved for $MY_ID — folder will be created without one"
_mirror_sd=$(resolve_remote_scripts_dir "$MIRROR_IP" "$MIRROR_SSH_KEY" "no")
_ff_remote="${_mirror_sd}/Plugin/${PLATFORM}/Tools/fallback_folder.php"
if timeout 60 ssh -i "$MIRROR_SSH_KEY" \
_mf_remote="${_mirror_sd}/Plugin/${PLATFORM}/Tools/mirror_folders.php"
# ── 12a: reproduce our own folder layout on the mirror ────────────────────────────────
# The deployed stacks run on the mirror continuously — they are not failover coverage —
# so they belong on the same shelves they occupy here: Sonarr in "Arrs Stack", NPM and
# Lldap in "Networking", the databases in "Databases". Filing all of them under
# "<Owner>-Fallback", which is what this step used to do, records whose they are and
# nothing about what they do.
#
# The plan is computed here, where the owner's folder.view3 layout lives, and applied
# there. Whatever the layout does not account for comes back as "unfiled" and is what
# the fallback folder is actually for.
_unfiled="$_deployed_csv"
if [[ -f "$_mf_local" ]]; then
# Comma-joined: the flag takes a CSV, and "${arr[*]}" would join on spaces — which
# also happen to appear inside folder names, so the plan must never be reflowed.
_fbonly=$(IFS=,; printf '%s' "${PARTNERSHIP_FALLBACK_ONLY[*]:-}")
_plan=$(php "$_mf_local" --export --containers="$_deployed_csv" \
--fallback-only="$_fbonly" 2>/dev/null)
if [[ -n "$_plan" ]]; then
if printf '%s' "$_plan" | timeout 60 ssh -i "$MIRROR_SSH_KEY" \
-o ConnectTimeout="$SSH_TIMEOUT" -o BatchMode=yes -o StrictHostKeyChecking=no \
root@"$MIRROR_IP" \
"[ -f '$_mf_remote' ] || exit 127; php '$_mf_remote' --import" 2>/dev/null; then
_unfiled=$(printf '%s' "$_plan" | php -r \
'echo implode(",", json_decode(stream_get_contents(STDIN),true)["unfiled"] ?? []);' 2>/dev/null)
else
warn "Could not mirror the folder layout to $MIRROR — falling back to one folder"
fi
fi
unset _plan _fbonly
fi
# ── 12b: the fallback folder gets only what is genuinely fallback ─────────────────────
# Unfiled containers plus anything named in PARTNERSHIP_FALLBACK_ONLY. Empty is the
# normal, correct outcome when every deployed container has a home in the layout.
if [[ -z "$_unfiled" ]]; then
echo " Folder layout mirrored — nothing left for ${MY_ID}-Fallback ✅"
FOLDER_OK=true
elif timeout 60 ssh -i "$MIRROR_SSH_KEY" \
-o ConnectTimeout="$SSH_TIMEOUT" -o BatchMode=yes -o StrictHostKeyChecking=no \
root@"$MIRROR_IP" \
"[ -f '$_ff_remote' ] || { echo missing; exit 127; }
php '$_ff_remote' --host=$(printf '%q' "$MY_ID") \
--containers=$(printf '%q' "$_deployed_csv") \
--containers=$(printf '%q' "$_unfiled") \
--icon=$(printf '%q' "$_icon")" 2>/dev/null; then
FOLDER_OK=true
else
warn "Could not group containers on $MIRROR — run $_ff_remote there by hand"
fi
unset _ff_local _ff_remote _mirror_sd _icon
unset _ff_local _ff_remote _mf_local _mf_remote _mirror_sd _icon _unfiled
fi
unset _deployed _deployed_csv
fi
+1
View File
@@ -731,6 +731,7 @@ detect_hosts() {
_alias_array "WEEKLY_SYNC_SHARES"
_alias_array "CRITICAL_SYNC_SHARES"
_alias_array "PARTNERSHIP_PROVISION_SHARES"
_alias_array "PARTNERSHIP_FALLBACK_ONLY"
_alias_array "BACKUP_VERIFY_SHARES"
_alias_array "DAILY_RESTART_CONTAINERS"
_alias_array "WEEKLY_RESTART_CONTAINERS"