#!/bin/bash # Revenire VM 201 pe pvemini după failover manual # Deployed la /opt/scripts/recover-vm201-to-pvemini.sh pe pveelite # Rulează DUPĂ ce pvemini e stabil din nou set -euo pipefail VMID=201 PRIMARY=pvemini PRIMARY_IP=10.0.20.201 SECONDARY=$(hostname) LOG=/var/log/recover-vm201.log MAIL_TO=mmarius28@gmail.com MIN_UPTIME_MIN=30 # pvemini trebuie să fie UP min. 30 min log() { echo "[$(date '+%F %T')] $*" | tee -a "$LOG"; } die() { log "ABORT: $*"; exit 1; } confirm() { local msg="$1" if [[ "${FORCE:-}" == "--yes" ]]; then log "$msg → auto-confirmat (--yes)" return 0 fi echo read -p "$msg (tastează 'DA'): " ANS [[ "$ANS" == "DA" ]] || die "Anulat la pasul: $msg" } [[ "$SECONDARY" == "pveelite" ]] || die "Rulează pe pveelite, nu pe $SECONDARY" [[ $EUID -eq 0 ]] || die "Trebuie root" FORCE=${1:-} log "=== Recovery VM $VMID → $PRIMARY pornit ===" # === CHECK-URI PRE-RECOVERY === # Check 1: VM rulează pe pveelite if ! qm status "$VMID" 2>/dev/null | grep -q running; then die "VM $VMID NU rulează pe $SECONDARY. Nu e nimic de recuperat." fi log "VM $VMID running pe $SECONDARY ✓" # Check 2: pvemini reachable + ssh OK if ! ping -c 3 -W 2 "$PRIMARY_IP" &>/dev/null; then die "$PRIMARY nu răspunde la ping. Abort." fi if ! ssh -o ConnectTimeout=5 -o BatchMode=yes "root@$PRIMARY_IP" 'pvecm status' &>/dev/null; then die "$PRIMARY nu răspunde la ssh sau nu e în cluster. Abort." fi log "$PRIMARY reachable ✓" # Check 3: uptime pvemini > threshold UPTIME_SEC=$(ssh "root@$PRIMARY_IP" "cat /proc/uptime | awk '{print int(\$1)}'") UPTIME_MIN=$((UPTIME_SEC / 60)) log "$PRIMARY uptime: ${UPTIME_MIN} min" if [[ "$UPTIME_MIN" -lt "$MIN_UPTIME_MIN" ]]; then die "$PRIMARY uptime doar ${UPTIME_MIN} min (< ${MIN_UPTIME_MIN} min). Așteaptă stabilizare." fi # Check 4: errors recente pe pvemini ERR_COUNT=$(ssh "root@$PRIMARY_IP" "journalctl -p err -b --since '30 min ago' 2>/dev/null | grep -v '^-- ' | wc -l" || echo 0) log "$PRIMARY erori în ultimele 30 min: $ERR_COUNT" if [[ "$ERR_COUNT" -gt 50 ]]; then log "ATENȚIE: $ERR_COUNT erori pe $PRIMARY" confirm "Continui oricum?" fi # Check 5: VM 201 NU există ca running pe pvemini if ssh "root@$PRIMARY_IP" "qm status $VMID 2>/dev/null | grep -q running"; then die "VM $VMID rulează deja pe $PRIMARY (split brain!). Oprește manual întâi." fi # === EXECUȚIE === echo echo "========================================" echo "Plan recovery VM $VMID către $PRIMARY:" echo " 1. Shutdown VM $VMID pe $SECONDARY" echo " 2. Replicare inversă $SECONDARY → $PRIMARY" echo " 3. Migrare offline $VMID către $PRIMARY" echo " 4. Restore replicări normale" echo " 5. Start VM $VMID pe $PRIMARY" echo "========================================" confirm "Pornesc recovery?" # Pas 1: Shutdown VM 201 pe pveelite log "Pas 1/5: Shutdown VM $VMID pe $SECONDARY..." qm shutdown "$VMID" --timeout 120 || die "Shutdown VM eșuat" sleep 5 qm status "$VMID" | grep -q stopped || die "VM $VMID nu s-a oprit" log "VM $VMID stopped ✓" # Pas 2: Job replicare inversă pveelite → pvemini log "Pas 2/5: Creez replicare inversă $SECONDARY → $PRIMARY..." if pvesr status | grep -q "^${VMID}-2 "; then log "Job ${VMID}-2 deja există, îl șterg" pvesr delete "${VMID}-2" --force 1 || true sleep 2 fi pvesr create-local-job "${VMID}-2" "$PRIMARY" --schedule '*/5' --source "$SECONDARY" \ --comment "recovery reverse" log "Rulez replicare inversă acum (poate dura, depinde de delta)..." pvesr run --id "${VMID}-2" || die "Replicare inversă eșuată" log "Replicare inversă OK ✓" # Pas 3: Migrare offline VM către pvemini log "Pas 3/5: Migrare offline VM $VMID → $PRIMARY..." qm migrate "$VMID" "$PRIMARY" || die "Migrare eșuată" log "Migrare completă ✓" # Pas 4: Șterge job reverse + verifică replicările normale log "Pas 4/5: Curăț jobul de replicare inversă..." pvesr delete "${VMID}-2" --force 1 || true sleep 2 log "Replicări active:" pvesr status | grep "^${VMID}-" | tee -a "$LOG" # Pas 5: Start VM pe pvemini log "Pas 5/5: Start VM $VMID pe $PRIMARY..." ssh "root@$PRIMARY_IP" "qm start $VMID" || die "Start pe $PRIMARY eșuat" sleep 10 PRIMARY_STATUS=$(ssh "root@$PRIMARY_IP" "qm status $VMID" | awk '{print $2}') log "VM $VMID pe $PRIMARY: $PRIMARY_STATUS" # Mail confirmare { echo "Recovery VM $VMID complet la $(date)" echo echo "$SECONDARY → $PRIMARY migrare reușită." echo "Status VM pe $PRIMARY: $PRIMARY_STATUS" echo echo "Replicări active:" pvesr status | grep "^${VMID}-" echo echo "Verifică aplicația Windows pe 10.0.20.201 (IIS etc)." } | mail -r 'ups@romfast.ro' -s "[OK] Recovery VM $VMID pe $PRIMARY" "$MAIL_TO" log "=== Recovery complet ==="