SPB Git forge
3commits 1branches 0releases
2.9 MBsize
maindefault branch
1 h agolast push
HTML 57.2% Shell 19.1% Python 11.2% CSS 7.4% JavaScript 5.1%
5.3 KB · 148 lines shellscript
Raw Blame History
1#!/bin/bash2# cluster-gateway.sh — M3U96a comme porte d'entrée (staging) du cluster MacLustr.3#4# Principe : on pousse un projet UNE fois laptop -> M3U96a (~/cluster-projects/<nom>/),5# puis M3U96a le diffuse aux autres noeuds en parallele via le reseau local (Tailscale/LAN).6# Le meme chemin ~/cluster-projects/<nom>/ existe ainsi sur tous les noeuds cibles.7#8# Usage :9#   cluster-gateway.sh stage  <dir-local> [nom]             # laptop -> M3U96a10#   cluster-gateway.sh fanout <nom> [noeud ...]             # M3U96a -> noeuds (defaut: tous sauf M3U96a & M2U64)11#   cluster-gateway.sh push   <dir-local> [nom]             # stage + fanout (defaut)12#   cluster-gateway.sh list                                 # projets stages sur M3U96a13#   cluster-gateway.sh where  <nom>                         # sur quels noeuds le projet est present14#   cluster-gateway.sh clean  <nom> [--everywhere]          # efface de M3U96a (et de tous les noeuds)15#16# Options : --include-m2u64 (fanout/push : inclure le noeud prod M2U64)17# Doc complete : ~/Desktop/cluster-skill/GATEWAY.md18set -euo pipefail1920GATEWAY="M3U96a"21DOMAIN="maclustr.io"22STAGE_DIR="cluster-projects"23LAN_PREFIX_RE='192\.168\.2\.'   # sous-reseau LAN du cluster24ALL_NODES="M3U96b M2U64 M4M64a M4M64b M4BP48 M4BP36 M4M36 M2M32 M2M32b M2M32c m4mc M1M32 m4ma m4mb m2m16 M3BA24 M3BA16 m2m8a m2m8b"2526usage() { sed -n '2,18p' "$0" | sed 's/^# \{0,1\}//'; exit 1; }2728CMD="${1:-}"; shift || true2930INCLUDE_M2U64=031ARGS=()32for a in "$@"; do33  case "$a" in34    --include-m2u64) INCLUDE_M2U64=1 ;;35    *) ARGS+=("$a") ;;36  esac37done38set -- "${ARGS[@]:-}"3940default_targets() {41  local out=""42  for n in $ALL_NODES; do43    [ "$n" = "M2U64" ] && [ "$INCLUDE_M2U64" -eq 0 ] && continue44    out="$out $n"45  done46  echo "$out"47}4849do_stage() {50  local src="${1:?usage: stage <dir-local> [nom]}"51  src="${src%/}"52  [ -d "$src" ] || { echo "ERREUR: $src n'est pas un dossier" >&2; exit 2; }53  local name="${2:-$(basename "$src")}"54  echo ">> stage: $src -> $GATEWAY:~/$STAGE_DIR/$name/"55  rsync -az --delete --rsync-path="mkdir -p $STAGE_DIR && rsync" \56    "$src/" "$GATEWAY:$STAGE_DIR/$name/"57  echo "OK  stage $name ($(du -sh "$src" | cut -f1))"58}5960do_fanout() {61  local name="${1:?usage: fanout <nom> [noeud ...]}"; shift || true62  local nodes="${*:-$(default_targets)}"63  # Le SSH inter-noeuds via Tailscale est filtre (ACL) : le fanout passe par le LAN64  # 192.168.2.x. Les IP LAN sont en DHCP -> on les resout en live depuis le laptop.65  echo ">> resolution des IP LAN des cibles ($(echo $nodes | wc -w | tr -d ' ') noeuds)..."66  local tmp; tmp=$(mktemp -d)67  local n68  for n in $nodes; do69    ( ip=$(ssh -n -o ConnectTimeout=8 "$n" \70        "ifconfig | awk '/inet $LAN_PREFIX_RE/{print \$2; exit}'" 2>/dev/null || true)71      echo "${ip:-NONE}" >"$tmp/$n" ) &72  done73  wait74  local pairs=""75  for n in $nodes; do pairs="$pairs $n=$(cat "$tmp/$n" 2>/dev/null || echo NONE)"; done76  rm -rf "$tmp"77  echo ">> fanout depuis $GATEWAY via LAN: $name ->$(echo "$pairs" | tr ' ' '\n' | grep -c '=' | xargs echo) noeuds"78  # shellcheck disable=SC208779  ssh -A "$GATEWAY" "NAME='$name' PAIRS='$pairs' bash -s" <<'REMOTE'80set -u81SRC="$HOME/cluster-projects/$NAME/"82[ -d "$SRC" ] || { echo "ERREUR: $SRC absent sur la passerelle — faire stage d abord" >&2; exit 2; }83TMP=$(mktemp -d)84for pair in $PAIRS; do85  n="${pair%%=*}"; ip="${pair##*=}"86  if [ "$ip" = "NONE" ]; then echo "FAIL (hors LAN cluster ou injoignable)" >"$TMP/$n"; continue; fi87  ( rsync -az --delete \88      -e "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=8" \89      --rsync-path="mkdir -p cluster-projects && rsync" \90      "$SRC" "$ip:cluster-projects/$NAME/" \91      >/dev/null 2>"$TMP/$n.err" && echo "OK ($ip)" >"$TMP/$n" || echo "FAIL ($ip)" >"$TMP/$n" ) &92done93wait94FAILED=095for pair in $PAIRS; do96  n="${pair%%=*}"97  st=$(cat "$TMP/$n" 2>/dev/null || echo FAIL)98  printf "  %-8s %s\n" "$n" "$st"99  case "$st" in FAIL*) FAILED=1; [ -f "$TMP/$n.err" ] && sed 's/^/           /' "$TMP/$n.err" | grep -v "known hosts" | head -2 ;; esac100done101rm -rf "$TMP"102exit $FAILED103REMOTE104  echo "OK  fanout $name termine"105}106107do_list() {108  echo ">> projets stages sur $GATEWAY:~/$STAGE_DIR/"109  ssh "$GATEWAY" "du -sh $STAGE_DIR/*/ 2>/dev/null || echo '  (aucun projet stage)'"110}111112do_where() {113  local name="${1:?usage: where <nom>}"114  echo ">> presence de '$name' sur le cluster :"115  for n in $GATEWAY $ALL_NODES; do116    ( sz=$(ssh -o ConnectTimeout=6 "$n.$DOMAIN" "du -sh $STAGE_DIR/$name 2>/dev/null | cut -f1" 2>/dev/null)117      printf "  %-8s %s\n" "$n" "${sz:-—}" ) &118  done119  wait120}121122do_clean() {123  local name="${1:?usage: clean <nom> [--everywhere]}"124  local everywhere=0125  [ "${2:-}" = "--everywhere" ] && everywhere=1126  if [ "$everywhere" -eq 1 ]; then127    echo ">> clean '$name' sur TOUS les noeuds"128    for n in $GATEWAY $ALL_NODES; do129      ( ssh -o ConnectTimeout=6 "$n.$DOMAIN" "rm -rf $STAGE_DIR/$name" 2>/dev/null \130          && printf "  %-8s OK\n" "$n" || printf "  %-8s (injoignable)\n" "$n" ) &131    done132    wait133  else134    echo ">> clean '$name' sur $GATEWAY uniquement"135    ssh "$GATEWAY" "rm -rf $STAGE_DIR/$name" && echo "  $GATEWAY OK"136  fi137}138139case "$CMD" in140  stage)  do_stage "$@" ;;141  fanout) do_fanout "$@" ;;142  push)   do_stage "$1" "${2:-}"; do_fanout "${2:-$(basename "${1%/}")}" ;;143  list)   do_list ;;144  where)  do_where "$@" ;;145  clean)  do_clean "$@" ;;146  *)      usage ;;147esac148