Files
ROMFASTSQL/proxmox/cluster/ups/scripts/ups-battery-trend-backfill.sh
Marius 0b8e8f6892 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
2026-08-27 14:46:35 +03:00

103 lines
3.1 KiB
Bash

#!/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"