feat(cluster): corosync ring1 pe insula, test de repornire cu WoL, fixuri in scripturi
Ring1 aplicat si verificat pe cluster live: config_version 17, ring1_addr pe
10.10.10.20x la fiecare nod, interface{linknumber:1}. Validat cu `corosync -t`
inainte de instalare. Testat prin oprirea reala a lui ring0 pe pveelite: link0
disconnected, link1 connected, cvorum 3/3 neatins - exact scenariul care pe
27 august a lasat nodul mort 16 ore.
Test de repornire completa a clusterului, cu Wake-on-LAN (trezire in ~15s).
Insula a urcat singura pe toate trei nodurile; ipoteza enumerarii tarzii a
USB-ului nu s-a materializat. Unealta noua: wake-cluster.ps1.
Testul a scos la iveala o linie ramasa in /etc/fstab pe pve1 si pveelite, care
monta storage-ul NFS de pe IP-ul de productie inaintea lui pvestatd. Backup-ul
trecea tacut pe reteaua gresita, cu storage.cfg corect. cluster-startup verifica
acum asta automat, impreuna cu IP-urile de insula si conectivitatea reala.
Patru bug-uri gasite prin rulare pe cluster live:
- sonda Oracle nu avea timeout: un sqlplus agatat pe o instanta in pornire a
blocat cluster-startup 14 minute, fara mesaj, cu propriul prag de 600s
nefolosit, fiindca bucla n-a apucat o iteratie;
- `bash -c` in loc de `bash -lc`: sqlplus lipsea din PATH, deci baza nu se
oprea si containerul s-ar fi inchis peste ea;
- PowerShell 5.1 pierde ghilimelele duble catre exe-uri native, deci comanda
ajungea rupta pe nod - trecut pe trimitere codificata base64;
- backup-ul de crontab si fisierul de stare se rescriau la o a doua rulare,
lasand monitorizarea oprita permanent si lista de repornit goala.
Documentatia de oprire planificata pornea de la o afirmatie devenita falsa
("nu exista datacenter.cfg") si de la o comanda care ar fi adaugat o a doua
linie `ha:`. Actualizata, impreuna cu inventarul de guest-uri (VM 304 lipsea
din toate listele de ordine si cadea in maturarea de dupa Oracle).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RJFQZcA7uerXRaL1NrsXpS
This commit is contained in:
@@ -34,6 +34,7 @@ NODE_SHUTDOWN_ORDER=(pveelite pve1 pvemini)
|
||||
# Orice guest pornit care nu apare aici e oprit la final, într-o măturare.
|
||||
GUEST_SHUTDOWN_ORDER=(
|
||||
303 # Win11-Adina — desktop, fără dependențe
|
||||
304 # Win11-Marius — desktop, fără dependențe
|
||||
302 # oracle-test-302 — VM de test
|
||||
310 # Win11-Template — template
|
||||
201 # roacentral — IIS reverse proxy, consumator Oracle
|
||||
@@ -202,9 +203,19 @@ fi
|
||||
# Salvează starea LOCAL — cluster-startup.sh pornește exact ce era pornit,
|
||||
# ca să nu repornească VM-uri oprite intenționat (302, 310, 301...).
|
||||
if (( ! DRY_RUN )); then
|
||||
{ echo "# stare cluster salvată la $(date '+%Y-%m-%d %H:%M:%S')"
|
||||
printf '%s\n' "${RUNNING:-}"; } > "$STATE_FILE"
|
||||
ok "stare salvată în $STATE_FILE"
|
||||
# Nu rescrie peste o stare existentă cu un inventar gol. Cazul real: scriptul
|
||||
# e rulat a doua oară (după --no-nodes, sau după o eroare), când guest-urile
|
||||
# sunt deja oprite — inventarul e gol și am pierde exact lista de repornit.
|
||||
EXISTING=0
|
||||
[[ -f "$STATE_FILE" ]] && EXISTING=$(grep -cv -e '^[[:space:]]*#' -e '^[[:space:]]*$' "$STATE_FILE" || true)
|
||||
if [[ -z "$RUNNING" ]] && (( EXISTING > 0 )); then
|
||||
warn "Niciun guest pornit, dar $STATE_FILE conține deja $EXISTING intrări — îl PĂSTREZ."
|
||||
warn "Altfel cluster-startup.sh n-ar mai ști ce să pornească."
|
||||
else
|
||||
{ echo "# stare cluster salvată la $(date '+%Y-%m-%d %H:%M:%S')"
|
||||
printf '%s\n' "${RUNNING:-}"; } > "$STATE_FILE"
|
||||
ok "stare salvată în $STATE_FILE"
|
||||
fi
|
||||
fi
|
||||
|
||||
confirm "Se opresc $RUNNING_COUNT guest-uri, apoi nodurile: ${NODE_SHUTDOWN_ORDER[*]}."
|
||||
@@ -218,6 +229,9 @@ if [[ "$CURRENT_POLICY" == "freeze" ]]; then
|
||||
ok "deja pe freeze"
|
||||
else
|
||||
if nssh pvemini "test -f /etc/pve/datacenter.cfg"; then
|
||||
# sed șterge DOAR linia 'ha:', nu rescrie fișierul: din 2026-08-29 acolo
|
||||
# stă și 'migration: network=10.10.10.0/24,type=insecure', fără de care
|
||||
# replicarea se întoarce tăcut pe rețeaua de producție.
|
||||
run pvemini "cp /etc/pve/datacenter.cfg /root/datacenter.cfg.backup-mentenanta"
|
||||
run pvemini "sed -i '/^ha:/d' /etc/pve/datacenter.cfg; printf 'ha: shutdown_policy=freeze\n' >> /etc/pve/datacenter.cfg"
|
||||
else
|
||||
@@ -231,7 +245,10 @@ fi
|
||||
step "Dezactivare cron-uri de alertă"
|
||||
|
||||
for node in "${!NODE_IP[@]}"; do
|
||||
run "$node" "crontab -l > $CRON_BACKUP 2>/dev/null || true"
|
||||
# Backup DOAR dacă crontab-ul curent nu e deja comentat. Altfel o a doua rulare
|
||||
# a scriptului (după o eroare, de exemplu) ar salva peste backup versiunea deja
|
||||
# comentată, iar cluster-startup.sh ar „restaura" monitorizarea oprită — tăcut.
|
||||
run "$node" "if crontab -l 2>/dev/null | grep -q '^#MENTENANTA'; then echo 'backup păstrat'; else crontab -l > $CRON_BACKUP 2>/dev/null || true; fi"
|
||||
run "$node" "crontab -l | sed -E '/^[^#]/ s%^(.*($CRON_PATTERN)\.sh.*)\$%#MENTENANTA \1%' | crontab -"
|
||||
if (( ! DRY_RUN )); then
|
||||
n=$(nssh "$node" "crontab -l | grep -c '^#MENTENANTA' || true")
|
||||
@@ -253,9 +270,23 @@ else
|
||||
if (( DRY_RUN )); then
|
||||
printf '%s [dry-run] shutdown immediate în %s%s\n' "$c_dim" "$ORACLE_DOCKER" "$c_off"
|
||||
else
|
||||
nssh "$ORACLE_NODE" "pct exec $ORACLE_CT -- docker exec $ORACLE_DOCKER bash -c \"printf 'shutdown immediate\nexit\n' | sqlplus -s / as sysdba\"" \
|
||||
|| warn "Shutdown-ul bazei a raportat eroare. Verifică manual înainte de a continua!"
|
||||
ok "instanța Oracle oprită"
|
||||
# `bash -lc`, NU `bash -c`: fără shell de login, PATH-ul Oracle nu e încărcat
|
||||
# și comanda eșuează cu „sqlplus: command not found" — adică baza rămâne
|
||||
# DESCHISĂ, iar containerul ar fi oprit peste ea.
|
||||
# `timeout 180`: un „shutdown immediate" poate dura, dar nu la infinit. Fără
|
||||
# el, un sqlplus blocat ar ține scriptul agățat fără niciun mesaj (pățit pe
|
||||
# 2026-08-29, la sonda echivalentă din cluster-startup.sh).
|
||||
SQL_OUT=$(nssh "$ORACLE_NODE" "timeout 180 pct exec $ORACLE_CT -- docker exec $ORACLE_DOCKER bash -lc \"printf 'shutdown immediate\nexit\n' | sqlplus -s / as sysdba\" 2>&1" || true)
|
||||
|
||||
# Codul de ieșire nu e o dovadă: sqlplus întoarce 0 și când n-a închis nimic.
|
||||
# Singura confirmare reală e mesajul instanței.
|
||||
if grep -q 'ORACLE instance shut down' <<<"$SQL_OUT"; then
|
||||
ok "instanța Oracle oprită curat"
|
||||
else
|
||||
warn "Baza NU a confirmat „ORACLE instance shut down\". Ultimele linii:"
|
||||
tail -8 <<<"$SQL_OUT"
|
||||
confirm "Oprirea CT $ORACLE_CT peste o bază posibil deschisă. Continui?"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user