#!/usr/bin/env bash # ============================================================================== # NexusPBX HA - Script Helper Root pour l'orchestration Keepalived # ============================================================================== set -euo pipefail export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH" CMD="${1:-status}" case "$CMD" in apply) # 1. Activation kernel sysctl pour liaison IP non-locale (indispensable HA) sysctl -w net.ipv4.ip_nonlocal_bind=1 >/dev/null 2>&1 || true if [ ! -f /etc/sysctl.d/99-nexus-ha.conf ]; then echo "net.ipv4.ip_nonlocal_bind=1" > /etc/sysctl.d/99-nexus-ha.conf 2>/dev/null || true fi # 2. Vérification et installation éventuelle de Keepalived et arping if ! command -v keepalived >/dev/null 2>&1 || ! command -v arping >/dev/null 2>&1; then apt-get update -qq && apt-get install -y -qq keepalived iputils-arping >/dev/null 2>&1 || true fi # 3. Création et sécurisation stricte du dossier des scripts Keepalived (exigences strictes Keepalived 2.x) mkdir -p /etc/keepalived/scripts if [ -d "/var/www/nexus-pbx/scripts/cluster" ]; then cp -f /var/www/nexus-pbx/scripts/cluster/*.sh /etc/keepalived/scripts/ 2>/dev/null || true fi chown -R root:root /etc/keepalived chmod 755 /etc/keepalived chmod 755 /etc/keepalived/scripts chmod 755 /etc/keepalived/scripts/*.sh 2>/dev/null || true # 4. Déploiement de la configuration générée depuis /tmp if [ -f "/tmp/keepalived.conf.tmp" ]; then cp -f /tmp/keepalived.conf.tmp /etc/keepalived/keepalived.conf chown root:root /etc/keepalived/keepalived.conf chmod 644 /etc/keepalived/keepalived.conf rm -f /tmp/keepalived.conf.tmp fi # Fichier journal du cluster accessible en écriture touch /var/log/nexus_cluster.log chmod 666 /var/log/nexus_cluster.log # 5. Activation et démarrage du service systemctl daemon-reload systemctl unmask keepalived >/dev/null 2>&1 || true systemctl enable keepalived >/dev/null 2>&1 || true systemctl restart keepalived echo "KEEPALIVED_APPLIED_OK" ;; stop) systemctl stop keepalived >/dev/null 2>&1 || true systemctl disable keepalived >/dev/null 2>&1 || true echo "KEEPALIVED_STOPPED_OK" ;; status) if systemctl is-active --quiet keepalived 2>/dev/null; then echo "RUNNING" else echo "STOPPED" fi ;; restore-astdb) SRC="${2:-/tmp/astdb_cluster_sync.sqlite3}" DEST="/var/lib/asterisk/astdb.sqlite3" if [ ! -f "$SRC" ] || [ ! -s "$SRC" ]; then echo "ASTDB_RESTORE_NO_FILE" exit 0 fi # 1. Vérification intégrité du fichier source temporaire SRC_INTEGRITY=$(sqlite3 "$SRC" "PRAGMA integrity_check;" 2>/dev/null || echo "corrupt") if [ "$SRC_INTEGRITY" != "ok" ]; then echo "ASTDB_SOURCE_CORRUPT: $SRC_INTEGRITY" rm -f "$SRC" exit 1 fi chmod 644 "$SRC" 2>/dev/null || true # 2. Si Asterisk tourne, injection via son moteur interne database query # Cela garantit l'absence totale de verrou SQLite (database is locked) et préserve les descripteurs ouverts if pidof asterisk >/dev/null 2>&1; then /usr/sbin/asterisk -rx "database query \"ATTACH '$SRC' AS src;\"" >/dev/null 2>&1 || true /usr/sbin/asterisk -rx "database query \"DELETE FROM astdb WHERE key LIKE '/registrar/%';\"" >/dev/null 2>&1 || true /usr/sbin/asterisk -rx "database query \"INSERT INTO astdb SELECT * FROM src.astdb WHERE key LIKE '/registrar/%';\"" >/dev/null 2>&1 || true /usr/sbin/asterisk -rx "database query \"INSERT OR REPLACE INTO astdb SELECT * FROM src.astdb WHERE key NOT LIKE '/registrar/%';\"" >/dev/null 2>&1 || true /usr/sbin/asterisk -rx "database query \"DETACH src;\"" >/dev/null 2>&1 || true else # Asterisk arrêté : copie directe intègre cp -f "$SRC" "$DEST" chown asterisk:asterisk "$DEST" 2>/dev/null || true chmod 664 "$DEST" 2>/dev/null || true fi rm -f "$SRC" echo "ASTDB_RESTORED_OK" ;; fix-astdb) DEST="/var/lib/asterisk/astdb.sqlite3" if [ -f "$DEST" ]; then INTEGRITY=$(sqlite3 "$DEST" "PRAGMA integrity_check;" 2>/dev/null || echo "corrupt") if [ "$INTEGRITY" != "ok" ]; then mv -f "$DEST" "${DEST}.corrupt.$(date +%s)" 2>/dev/null || true sqlite3 "$DEST" "CREATE TABLE astdb(key TEXT, value TEXT, PRIMARY KEY(key));" 2>/dev/null || true chown asterisk:asterisk "$DEST" 2>/dev/null || true chmod 664 "$DEST" 2>/dev/null || true if pidof asterisk >/dev/null 2>&1; then /usr/sbin/asterisk -rx "pjsip reload" 2>/dev/null || true fi echo "ASTDB_FIXED" exit 0 fi fi echo "ASTDB_OK" ;; check) if pidof asterisk >/dev/null 2>&1 && /usr/sbin/asterisk -rx "core show uptime" 2>/dev/null | grep -qi "uptime"; then echo "HEALTHY" else echo "DEGRADED" fi ;; *) echo "Usage: $0 {apply|stop|status|check}" exit 1 ;; esac