spb/maclustr-dispatch
Public
1"""maclustr-dispatch — configuration centrale.23Tout tourne SUR la passerelle (M1M32). Python 3.9 (système macOS) : pas de syntaxe > 3.9.4"""5import os67USER = "simon-pierreboucher"8HOME = os.path.expanduser("~")9GATEWAY = "M1M32"10DOMAIN = "maclustr.io"11LAN_PREFIX = "192.168.2."12SSH_KEY = os.path.join(HOME, ".ssh", "id_ed25519") # clé « maclustr-m1m32 », autorisée sur tous les nœuds13STATE = os.path.join(HOME, "dispatch") # état : apps/, stage/, registry.json, lan.json, logs/14APPS_DIR = os.path.join(STATE, "apps")15STAGE_DIR = os.path.join(STATE, "stage")16LOG_DIR = os.path.join(STATE, "logs")17REGISTRY = os.path.join(STATE, "registry.json")18LAN_CACHE = os.path.join(STATE, "lan.json")19SCAN_CACHE = os.path.join(STATE, "scan.json")20NGROK_CFG = os.path.join(HOME, "Library", "Application Support", "ngrok", "ngrok.yml")21RUN_DIR = "~/dispatch-run" # sur les nœuds : ecosystem PM2 générés22SUDO_PW_FILE = os.path.join(STATE, ".sudo") # mot de passe sudo des nœuds (0600), pour `prepare`2324# Inventaire statique (alias -> cœurs, RAM Go, modèle). Les IP LAN sont découvertes en live.25NODES = {26 "M3U96a": {"cores": 32, "ram_gb": 96, "model": "Mac Studio"},27 "M3U96b": {"cores": 32, "ram_gb": 96, "model": "Mac Studio"},28 "M2U64": {"cores": 24, "ram_gb": 64, "model": "Mac Studio"},29 "M4M64a": {"cores": 16, "ram_gb": 64, "model": "Mac Studio"},30 "M4M64b": {"cores": 16, "ram_gb": 64, "model": "Mac Studio"},31 "M4BP48": {"cores": 16, "ram_gb": 48, "model": "MacBook Pro"},32 "M4BP36": {"cores": 14, "ram_gb": 36, "model": "MacBook Pro"},33 "M4M36": {"cores": 14, "ram_gb": 36, "model": "Mac Studio"},34 "M2M32": {"cores": 12, "ram_gb": 32, "model": "Mac Studio"},35 "M2M32b": {"cores": 12, "ram_gb": 32, "model": "Mac Studio"},36 "M2M32c": {"cores": 12, "ram_gb": 32, "model": "Mac Studio"},37 "m4mc": {"cores": 12, "ram_gb": 24, "model": "Mac mini"},38 "M1M32": {"cores": 10, "ram_gb": 32, "model": "Mac Studio"},39 "m4ma": {"cores": 10, "ram_gb": 24, "model": "Mac mini"},40 "m4mb": {"cores": 10, "ram_gb": 16, "model": "Mac mini"},41 "m2m16": {"cores": 10, "ram_gb": 16, "model": "Mac mini"},42 "M3BA24": {"cores": 8, "ram_gb": 24, "model": "MacBook Air"},43 "M3BA16": {"cores": 8, "ram_gb": 16, "model": "MacBook Air"},44 "m2m8a": {"cores": 8, "ram_gb": 8, "model": "Mac mini"},45 "m2m8b": {"cores": 8, "ram_gb": 8, "model": "Mac mini"},46 "m4md": {"cores": 10, "ram_gb": 16, "model": "Mac mini"}, # ajouté 2026-09-04 (Mac16,10, M4, 100.78.227.79)47}4849# Nœuds réservés : inéligibles au placement automatique (sauf app épinglée dessus).50RESERVED = {"M3U96b": "réservé à hfmarketdata (lac FirstRate Data) depuis le 2026-09-04"}5152# Rôles : gateway = jamais d'app ; worker = éligible. Un nœud absent du scan est « offline ».53ROLES = {alias: ("gateway" if alias == GATEWAY else "worker") for alias in NODES}5455# Runtimes que `prepare` sait installer via Homebrew, et comment les détecter sur un nœud.56RUNTIME_CHECKS = {57 "node": "test -x /opt/homebrew/bin/node",58 "pnpm": "test -x /opt/homebrew/bin/pnpm",59 "pm2": "test -x /opt/homebrew/bin/pm2",60 "ngrok": "(test -x /opt/homebrew/bin/ngrok || test -x $HOME/bin/ngrok) && test -f \"$HOME/Library/Application Support/ngrok/ngrok.yml\"",61 "python@3.14": "test -x /opt/homebrew/opt/python@3.14/bin/python3.14",62 "python@3.13": "test -x /opt/homebrew/opt/python@3.13/bin/python3.13",63 "python@3.12": "test -x /opt/homebrew/opt/python@3.12/bin/python3.12",64 "uv": "test -x /opt/homebrew/bin/uv || test -x $HOME/.local/bin/uv",65 "uv-python@3.12": "ls -d $HOME/.local/share/uv/python/cpython-3.12* >/dev/null 2>&1",66 "docker": "test -x /opt/homebrew/bin/docker",67 "postgresql@17": "test -x /opt/homebrew/opt/postgresql@17/bin/postgres",68 "brew": "test -x /opt/homebrew/bin/brew",69 "git": "test -x /opt/homebrew/bin/git || test -x /usr/bin/git",70}71BREW_FORMULAE = {72 "node": "node", "pnpm": "pnpm", "pm2": "pm2", "python@3.14": "python@3.14", "python@3.13": "python@3.13",73 "python@3.12": "python@3.12", "uv": "uv", "docker": "docker", "postgresql@17": "postgresql@17", "git": "git",74}75BREW_CASKS = {"ngrok": "ngrok"}7677os.makedirs(APPS_DIR, exist_ok=True)78os.makedirs(STAGE_DIR, exist_ok=True)79os.makedirs(LOG_DIR, exist_ok=True)80