fix(ups): testul lunar de baterie nu putea da alarma niciodata
Verdictul se calcula din CHARGE_DROP, dar la acest UPS battery.charge nu e o masuratoare independenta: driverul nutdrv_qx / Voltronic-QS-Hex o deduce liniar din tensiune intre battery.voltage.low (20.8V) si .high (26.0V). Verificat pe toate probele din 11 luni: 25.76V -> 95.4% -> raportat 95%. Traduse in tensiune, pragurile vechi cereau o cadere de 3.70V pentru FAIR (primul prag care trimite severity warning) si 4.74V pentru POOR, intr-un test de 40 de secunde. Maximul observat in 11 luni a fost 2.59V. De asta raportul a iesit EXCELLENT 11 luni la rand si ar fi facut-o si cu bateria pe moarte. Evaluarea se face acum pe tendinta: mediana ultimelor 3 rulari fata de mediana primelor 6, plus o plasa de siguranta pe tensiune absoluta (<25.0V forteaza FAIR, <24.0V forteaza POOR). Fereastra de 3 impiedica o luna atipica sa declanseze singura alarma - verificat pe feb 2026 (2.59V), care nu bascuelaza verdictul. Istoricul se tine in /var/log/ups-battery-trend.csv, populat cu cele 14 rulari extrase din jurnal (2025-10-06 -> 2026-08-01), ca linia de baza sa fie valida imediat si nu peste 9 luni. Starea la zi: baza 1.82V, recent 2.12V, raport 1.16x -> EXCELLENT. Cresterea de ~16% in 10 luni e reala dar sub banda de avertizare; FAIR s-ar da la 2.73V. Instalat pe pvemini in /opt/scripts/, verificat cap-coada cu testul de baterie anulat, ca sa nu descarce bateria: tendinta calculata corect, template-urile regenerate cu campurile noi, notificarea PVE::Notify trimisa cu succes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RRyaDj39hPQ89SZS6URRpS
This commit is contained in:
102
proxmox/cluster/ups/scripts/ups-battery-trend-backfill.sh
Normal file
102
proxmox/cluster/ups/scripts/ups-battery-trend-backfill.sh
Normal file
@@ -0,0 +1,102 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Reconstruiește /var/log/ups-battery-trend.csv din jurnalul testelor lunare.
|
||||
#
|
||||
# De ce există: ups-monthly-test.sh evaluează sănătatea bateriei comparând
|
||||
# căderea de tensiune cu linia de bază a acestei baterii. Fără istoric, linia de
|
||||
# bază s-ar forma abia după 9 rulări, adică 9 luni. Jurnalul conține însă deja
|
||||
# măsurătorile, din 2025-10-06 încoace — se extrag de acolo.
|
||||
#
|
||||
# Rulare unică. Refuză să suprascrie un CSV existent fără --force, ca să nu
|
||||
# reseteze din greșeală linia de bază acumulată.
|
||||
#
|
||||
# Creat: 2026-08-27
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
LOGFILE="${LOGFILE:-/var/log/ups-monthly-test.log}"
|
||||
TRENDFILE="${TRENDFILE:-/var/log/ups-battery-trend.csv}"
|
||||
FORCE=0
|
||||
DRY_RUN=0
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--force) FORCE=1 ;;
|
||||
--dry-run) DRY_RUN=1 ;;
|
||||
*) echo "Argument necunoscut: $arg" >&2; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ ! -f "$LOGFILE" ]; then
|
||||
echo "EROARE: nu găsesc jurnalul $LOGFILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -f "$TRENDFILE" ] && [ "$FORCE" -eq 0 ] && [ "$DRY_RUN" -eq 0 ]; then
|
||||
echo "EROARE: $TRENDFILE există deja. Folosește --force ca să-l reconstruiești." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Parserul lucrează doar cu tipare ASCII — etichetele cu diacritice din jurnal
|
||||
# ("Scădere tensiune") nu se pot potrivi portabil în awk pe toate locale-urile,
|
||||
# așa că valorile se recalculează din before/min, care apar fără diacritice.
|
||||
parse_log() {
|
||||
awk '
|
||||
function num(s) { gsub(/[^0-9.]/, "", s); return s }
|
||||
|
||||
/UPS MONTHLY BATTERY TEST - START/ {
|
||||
active = 1; phase = 0
|
||||
bch = ""; bv = ""; bl = ""; mc = ""; mv = ""; al = ""; dur = ""; d = ""
|
||||
next
|
||||
}
|
||||
!active { next }
|
||||
|
||||
/Step 1:/ { phase = 1; next }
|
||||
/Step 3:/ { phase = 3; d = substr($1, 2); next }
|
||||
/Step 4:/ { phase = 4; next }
|
||||
|
||||
phase == 1 && /Battery Charge:/ { bch = num($NF); next }
|
||||
phase == 1 && /Battery Voltage:/ { bv = num($(NF-1)); next }
|
||||
phase == 1 && /Load:/ { bl = num($NF); next }
|
||||
|
||||
/Minimum Charge:/ { mc = num($NF); next }
|
||||
/Minimum Voltage:/ { mv = num($(NF-1)); next }
|
||||
|
||||
phase == 4 && /Load:/ { al = num($NF); next }
|
||||
|
||||
/ test: [0-9]+ secunde/ { dur = num($(NF-1)); next }
|
||||
|
||||
/UPS MONTHLY BATTERY TEST - COMPLETE/ {
|
||||
active = 0
|
||||
# Blocurile din versiunile vechi de script nu au minimele — se sar.
|
||||
if (d != "" && mv != "" && bv != "") {
|
||||
vd = bv - mv
|
||||
cd = (bch != "" && mc != "") ? bch - mc : ""
|
||||
printf "%s,%.2f,%s,%s,%s,%s,%s\n", d, vd, mv, cd, bl, al, dur
|
||||
}
|
||||
next
|
||||
}
|
||||
' "$LOGFILE"
|
||||
}
|
||||
|
||||
ROWS=$(parse_log)
|
||||
COUNT=$(printf '%s\n' "$ROWS" | grep -c ',' || true)
|
||||
|
||||
if [ "$COUNT" -eq 0 ]; then
|
||||
echo "EROARE: nu s-a extras nicio rulare din $LOGFILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$DRY_RUN" -eq 1 ]; then
|
||||
echo "date,voltage_drop,min_voltage,charge_drop,before_load,after_load,duration"
|
||||
printf '%s\n' "$ROWS"
|
||||
echo "--- $COUNT rulari extrase (dry-run, nimic scris) ---" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
{
|
||||
echo "date,voltage_drop,min_voltage,charge_drop,before_load,after_load,duration"
|
||||
printf '%s\n' "$ROWS"
|
||||
} > "$TRENDFILE"
|
||||
|
||||
echo "Scris $COUNT rulari in $TRENDFILE"
|
||||
Reference in New Issue
Block a user