Files
ROMFASTSQL/proxmox/cluster/ups/docs/UPS-MONTHLY-TEST.md
Marius 83bb8b8d8c feat(ups): varsta acumulatorilor devine criteriu in testul lunar
Utilizatorul a confirmat ca acumulatorii au fost schimbati pe 2024-01-09 (data
aproximativa). Asta scoate la iveala o limita a evaluarii pe tendinta: NUT a fost
instalat pe 2025-10-06, cand acumulatorii aveau deja ~21 luni, deci linia de baza
NU e o baterie noua. Raportul de 1.16x masoara degradarea peste o baterie care
isi pierduse deja o parte din capacitate. Verdictul EXCELLENT e corect ca
tendinta, dar nu inseamna "ca noua".

Varsta devine criteriu separat, citit din /etc/nut/battery-install-date:
sub 3 ani niciun efect, 3-4 ani nota vizibila in raport, peste 4 ani forteaza cel
putin FAIR indiferent de tendinta. Fara fisier, scriptul merge normal si cere
completarea lui.

Verificat pe pvemini cu testul de baterie anulat, pe trei date: 32 luni (reala)
-> EXCELLENT, 39 luni -> EXCELLENT cu nota, 56 luni -> FAIR fortat. Fallback-ul
fara fisier intoarce varsta goala, nu eroare.

Un bug prins la verificare: extragerea datei lua prima potrivire din fisier, care
era un an dintr-un comentariu, si dadea varsta 0. Ambele extrageri sar acum peste
liniile care incep cu #.

Prag de 3 ani: 2027-01-09. Prag de 4 ani, cand testul incepe sa avertizeze
singur: 2028-01-09.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RRyaDj39hPQ89SZS6URRpS
2026-08-27 15:00:16 +03:00

571 lines
17 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Test Lunar Automat Baterie UPS
## Despre
Script automat pentru testarea lunară a bateriei UPS care rulează pe data de 1 a fiecărei luni la ora 00:00. Testul verifică capacitatea reală a bateriei prin comutare pe baterie și monitorizare descărcare/recuperare.
## Funcționalitate
### Ce face scriptul:
1. **Verificare status UPS** înainte de test
- Battery charge, voltage
- Input/output voltage
- Load %
- Verifică că UPS este Online
2. **Rulare test baterie automat**
- Comandă: `upscmd nutdev1 test.battery.start.quick`
- UPS comută pe baterie pentru ~10 secunde
- Descarcă efectiv bateria pentru testare reală
3. **Monitorizare în timp real** (30 secunde)
- Status UPS
- Battery charge %
- Battery voltage
- Detectare anomalii
4. **Analiză rezultate**
- Calculează scăderea încărcării (%)
- Calculează scăderea tensiunii (V)
- Evaluează sănătatea bateriei
5. **Monitorizare recuperare** (5 minute)
- Urmărește reîncărcarea bateriei
- Calculează rata de recuperare
- Oprește când bateria > 95%
6. **Generare rapoarte**
- Raport HTML detaliat cu grafice
- Raport text pentru email
- Log detaliat în `/var/log/ups-monthly-test.log`
7. **Notificare email**
- Trimite raport prin sistemul de notificări Proxmox
- Include sănătatea bateriei în subject
- Rapoarte salvate în `/tmp/ups-test-YYYYMM/`
## Evaluare Sănătate Baterie
**Evaluarea se face pe tendință, nu pe praguri absolute.** Din 2026-08-27; înainte
se folosea scăderea încărcării față de praguri fixe, care nu funcționa — vezi
[De ce s-a schimbat metoda](#de-ce-sa-schimbat-metoda) mai jos.
### Metoda
Se măsoară **căderea de tensiune sub sarcină** în cele ~40 de secunde de test și se
compară cu linia de bază a acestei baterii:
- **linia de bază** = mediana primelor 6 rulări înregistrate, adică bateria în cea
mai bună stare pe care o avem măsurată;
- **valoarea recentă** = mediana ultimelor 3 rulări, ca o lună atipică (frig,
sarcină mare) să nu declanșeze singură o alarmă;
- **raportul** dintre ele urcă pe măsură ce crește rezistența internă a bateriei,
ceea ce dă avertisment cu luni înainte de cedare.
| Raport față de bază | Sănătate | Severitate email | Acțiune |
|---------------------|----------|------------------|---------|
| < 1.25x | **EXCELLENT** | info | Nicio acțiune |
| 1.25 – 1.50x | **GOOD** | info | Uzură normală, urmărește lunar |
| 1.50 – 2.00x | **FAIR** | ⚠️ warning | Planifică înlocuirea în 3-6 luni |
| ≥ 2.00x | **POOR** | 🔴 error | **URGENT: înlocuiește bateria** |
Peste asta există o **plasă de siguranță pe tensiune absolută**, pentru cazul în
care bateria cedează brusc, înainte să apuce mediana să urce:
| Minim atins în test | Efect |
|---------------------|-------|
| < 25.0 V | forțează cel puțin **FAIR** |
| < 24.0 V | forțează **POOR** direct |
Până se strâng 9 rulări (6 pentru bază + 3 pentru fereastra recentă), verdictul
este **BASELINE** — se colectează date, severitate `info`.
### Fișierul de tendință
`/var/log/ups-battery-trend.csv`, câte o linie per rulare:
```
date,voltage_drop,min_voltage,charge_drop,before_load,after_load,duration
2026-08-01,2.12,25.76,5,10,12,40
```
Se poate reconstrui oricând din jurnal cu
`/opt/scripts/ups-battery-trend-backfill.sh --force`. A fost populat inițial cu
14 rulări extrase din `/var/log/ups-monthly-test.log` (2025-10-06 → 2026-08-01),
ca linia de bază să fie validă imediat și nu peste 9 luni.
### Vârsta acumulatorilor
Vârsta e al doilea criteriu, independent de tendință, pentru că **linia de bază nu
a fost măsurată pe o baterie nouă** — vezi avertismentul de mai jos.
Data instalării se ține în `/etc/nut/battery-install-date` (o linie, `YYYY-MM-DD`,
comentariile cu `#` se ignoră). Versionată în
`proxmox/cluster/ups/config/battery-install-date`.
| Vârstă | Efect asupra verdictului |
|--------|--------------------------|
| < 3 ani | niciunul |
| 3 – 4 ani | notă vizibilă în raport, verdictul rămâne pe tendință |
| > 4 ani | forțează cel puțin **FAIR**, indiferent de tendință |
| necunoscută | notă care cere completarea fișierului |
Dacă fișierul lipsește sau nu conține o dată validă, scriptul funcționează normal
și raportează vârsta ca necunoscută.
### Starea la 2026-08-27
| Perioadă | Cădere de tensiune |
|----------|--------------------|
| oct–dec 2025 (linia de bază) | 1.41 – 2.00 V, mediană **1.82 V** |
| iun–aug 2026 (recent) | 2.12 – 2.23 V, mediană **2.12 V** |
Raport **1.16x** → **EXCELLENT**. Creșterea de ~16% în 10 luni e reală, dar sub
banda de avertizare. Alarma (FAIR) s-ar da la o cădere de ~2.73 V.
Acumulatori instalați **2024-01-09** (dată aproximativă, confirmată de utilizator),
deci **32 de luni** la 2026-08-27. Pragul de 3 ani vine pe 2027-01-09.
> ⚠️ **Linia de bază nu e o baterie nouă.** NUT a fost instalat pe 2025-10-06, când
> acumulatorii aveau deja ~21 de luni. Raportul de 1.16x măsoară deci degradarea
> *peste* o baterie care își pierduse deja o parte din capacitate — nu față de
> starea din fabrică. Verdictul EXCELLENT e corect ca tendință, dar nu înseamnă
> „baterie ca nouă". De aceea vârsta e criteriu separat.
>
> **La următoarea înlocuire linia de bază se resetează**, și abia atunci raportul
> va porni de la o baterie chiar nouă.
### De ce s-a schimbat metoda
`battery.charge` **nu e o măsurătoare independentă** la acest UPS. Driverul
`nutdrv_qx` / `Voltronic-QS-Hex` nu are contor de coulombi; deduce încărcarea
liniar din tensiune, între `battery.voltage.low` (20.8 V) și `battery.voltage.high`
(26.0 V):
```
charge = (V - 20.8) / (26.0 - 20.8) * 100
```
Verificat pe toate probele din 11 luni: 25.76 V → 95.4% → raportat 95%;
25.29 V → 86.3% → raportat 86%. Se potrivește exact de fiecare dată.
Pragurile vechi, traduse înapoi în tensiune, cereau:
| Prag vechi | Însemna cădere de | Observat în 11 luni |
|------------|-------------------|---------------------|
| GOOD (drop 15%) | 2.66 V | maxim 2.59 V |
| FAIR (drop 35%) | **3.70 V** | niciodată |
| POOR (drop 55%) | **4.74 V** | niciodată |
EXCELLENT și GOOD sunt amândouă severitate `info`, deci primul prag care chiar
trimite un avertisment era FAIR, la o cădere de 3.70 V într-un test de 40 de
secunde. O baterie ajunsă acolo e practic un rezistor. De asta testul a raportat
**EXCELLENT 11 luni la rând** și ar fi făcut-o și cu bateria pe moarte.
## Instalare
### 1. Copiere script pe server
```bash
scp scripts/ups-monthly-test.sh root@10.0.20.201:/opt/scripts/
ssh root@10.0.20.201 "chmod +x /opt/scripts/ups-monthly-test.sh"
```
### 2. Configurare cron
Script-ul se adaugă automat în cron la instalare, dar poți verifica:
```bash
ssh root@10.0.20.201 "crontab -l | grep ups-monthly-test"
```
Ar trebui să vezi:
```
# UPS Monthly Battery Test - Rulează pe 1 ale lunii la 00:00
0 0 1 * * /opt/scripts/ups-monthly-test.sh
```
### 3. Test manual (recomandat înainte de prima rulare lunară)
```bash
ssh root@10.0.20.201 "/opt/scripts/ups-monthly-test.sh"
```
**ATENȚIE:** Testul va comuta UPS-ul pe baterie pentru ~10 secunde!
## Configurare
### Parametri editabili în script:
```bash
UPS_NAME="nutdev1" # Numele UPS-ului din NUT
UPS_USER="admin" # Username pentru comenzi NUT
UPS_PASS="parola99" # Parola pentru comenzi NUT
MAIL_TO="root@pam" # Destinatar email rapoarte
```
### Personalizare cron:
Pentru a schimba data/ora de rulare, editează cron:
```bash
ssh root@10.0.20.201
crontab -e
```
Exemple:
```bash
# Rulează pe 1 ale lunii la 02:00 (noapte)
0 2 1 * * /opt/scripts/ups-monthly-test.sh
# Rulează în fiecare Duminică la 00:00 (săptămânal)
0 0 * * 0 /opt/scripts/ups-monthly-test.sh
# Rulează pe 15 ale lunii la 00:00 (mijloc de lună)
0 0 15 * * /opt/scripts/ups-monthly-test.sh
```
## Rapoarte Generate
### 1. Raport HTML
**Locație:** `/tmp/ups-test-YYYYMM/ups-test-report.html`
Conține:
- Header cu data, UPS, nod
- Status sănătate baterie (color-coded)
- Metrici în grid layout:
- Încărcare înainte/după
- Tensiune înainte/după
- Scădere încărcare
- Recuperare în 5 min
- Tabel detalii tehnice
- Recomandări bazate pe sănătate
- Footer cu timestamp și paths
### 2. Raport Text
**Locație:** `/tmp/ups-test-YYYYMM/ups-test-report.txt`
Versiune text simplă pentru email.
### 3. Log Detaliat
**Locație:** `/var/log/ups-monthly-test.log`
Log complet cu toate măsurătorile:
- Timestamp pentru fiecare pas
- Status UPS în timp real
- Toate valorile măsurate
- Erori sau warnings
**Păstrare:** Log-ul este append-only, conține istoric complet al tuturor testelor.
## Logs și Monitorizare
### Vizualizare log în timp real:
```bash
ssh root@10.0.20.201 "tail -f /var/log/ups-monthly-test.log"
```
### Verificare ultimul test:
```bash
ssh root@10.0.20.201 "tail -50 /var/log/ups-monthly-test.log"
```
### Căutare teste anterioare:
```bash
# Caută toate testele din 2025
ssh root@10.0.20.201 "grep 'UPS MONTHLY BATTERY TEST - START' /var/log/ups-monthly-test.log | grep 2025"
# Vezi rezultatul ultimului test
ssh root@10.0.20.201 "grep 'Sănătate baterie:' /var/log/ups-monthly-test.log | tail -1"
```
### Verificare cron execution:
```bash
# Verifică că cron a rulat scriptul
ssh root@10.0.20.201 "grep ups-monthly-test /var/log/syslog"
```
## Email Notifications
### Configurare sistem de mail
Scriptul încearcă să trimită email prin:
1. **mail command** (recomandat)
2. **logger** (fallback - doar în syslog)
#### Instalare mail command (dacă nu există):
```bash
ssh root@10.0.20.201 "apt update && apt install -y mailutils"
```
#### Configurare SMTP pentru Proxmox:
Editează `/etc/postfix/main.cf`:
```bash
relayhost = smtp.gmail.com:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = encrypt
```
Creează `/etc/postfix/sasl_passwd`:
```
smtp.gmail.com:587 your-email@gmail.com:your-app-password
```
Apoi:
```bash
postmap /etc/postfix/sasl_passwd
chmod 600 /etc/postfix/sasl_passwd*
systemctl restart postfix
```
#### Test email:
```bash
echo "Test email from UPS monitoring" | mail -s "Test" root@pam
```
### Verificare email trimis:
```bash
# Verifică mail queue
ssh root@10.0.20.201 "mailq"
# Verifică mail logs
ssh root@10.0.20.201 "grep 'UPS' /var/log/mail.log"
```
## Troubleshooting
### Testul nu pornește
**Verificare:**
```bash
# UPS online?
upsc nutdev1 ups.status
# Comenzi disponibile?
upscmd -l nutdev1 | grep battery
# Autentificare corectă?
upscmd -u admin -p parola99 nutdev1 test.battery.start.quick
```
### Bateria nu se descarcă în test
**Cauze posibile:**
- UPS-ul nu suportă test real (unele modele low-end)
- Test prea scurt pentru a fi detectat
- Baterie foarte sănătoasă (scădere < 1%)
**Verificare:**
```bash
# Monitorizează tensiune în loc de charge
watch -n 1 'upsc nutdev1 battery.voltage'
# Apoi rulează test manual și observă scăderea
upscmd -u admin -p parola99 nutdev1 test.battery.start.quick
```
### Email nu ajunge
**Verificări:**
```bash
# Mail command instalat?
which mail
# Postfix rulează?
systemctl status postfix
# Verifică logs
tail -50 /var/log/mail.log
# Test manual
echo "Test" | mail -s "Test Subject" root@pam
```
### Script blochează sau timeout
**Cauze:**
- Testul baterie durează prea mult
- UPS nu răspunde
- Probleme rețea
**Soluție:**
Editează scriptul și reduce timeout-urile:
```bash
# Reduce monitorizare de la 15 la 5 iterații
for i in {1..5}; do
```
## Întreținere
### Lunar (După Rulare Automată)
```bash
# Verifică că testul a rulat
ssh root@10.0.20.201 "tail -100 /var/log/ups-monthly-test.log | grep 'COMPLETE'"
# Vezi rezultatul
ssh root@10.0.20.201 "grep 'Sănătate baterie' /var/log/ups-monthly-test.log | tail -1"
# Verifică raportul HTML
ssh root@10.0.20.201 "ls -lh /tmp/ups-test-*/ups-test-report.html"
```
### Anual
```bash
# Cleanup rapoarte vechi (> 12 luni)
ssh root@10.0.20.201 "find /tmp/ups-test-* -type d -mtime +365 -exec rm -rf {} +"
# Rotare log dacă devine prea mare (> 100MB)
ssh root@10.0.20.201 "
if [ \$(stat -f%z /var/log/ups-monthly-test.log) -gt 104857600 ]; then
mv /var/log/ups-monthly-test.log /var/log/ups-monthly-test.log.old
gzip /var/log/ups-monthly-test.log.old
fi
"
```
### La Înlocuire Baterie
După înlocuirea bateriei UPS:
```bash
# Rulează test manual pentru baseline
ssh root@10.0.20.201 "/opt/scripts/ups-monthly-test.sh"
# Verifică că rezultatul este EXCELLENT
ssh root@10.0.20.201 "tail -20 /var/log/ups-monthly-test.log"
# Notează data înlocuirii în log
ssh root@10.0.20.201 "echo '[$(date)] Baterie UPS înlocuită - baseline test executat' >> /var/log/ups-monthly-test.log"
```
## Interpretare Rezultate
### Exemplu rezultat bun:
```
Sănătate baterie: EXCELLENT
Scădere încărcare: 5%
Scădere tensiune: 1.64V
Recuperare: 5% în 30 secunde
```
**Interpretare:** Baterie în stare excelentă, poate susține sarcina, se reîncarcă rapid.
### Exemplu rezultat acceptabil:
```
Sănătate baterie: FAIR
Scădere încărcare: 35%
Scădere tensiune: 4.2V
Recuperare: 15% în 120 secunde
```
**Interpretare:** Baterie uzată, planifică înlocuire în 3-6 luni.
### Exemplu rezultat critic:
```
Sănătate baterie: POOR
Scădere încărcare: 65%
Scădere tensiune: 8.5V
Recuperare: 25% în 300 secunde
```
**Interpretare:** **URGENT!** Baterie critică, înlocuiește imediat! Risc mare de shutdown neplanificat.
## Recomandări Baterie
### Când să înlocuiești bateria:
| Indicator | Bun | Acceptabil | Critic |
|-----------|-----|------------|--------|
| **Vârstă baterie** | < 2 ani | 2-4 ani | > 4 ani |
| **Raport față de linia de bază** | < 1.25x | 1.25-2.0x | > 2.0x |
| **Tensiune minimă în test** | > 25.0V | 24.0-25.0V | < 24.0V |
| **Timp recuperare** | < 1 min | 1-5 min | > 5 min |
| **Teste failed** | 0 | 1-2 | > 3 |
Scăderea încărcării nu mai e criteriu — la acest UPS e tensiunea rescalată, nu o
măsurătoare separată.
### Factori care afectează durata de viață:
- **Temperatură:** Ideal 20-25°C (fiecare +10°C reduce durata cu 50%)
- **Cicluri descărcare:** < 20 cicluri/an = bun
- **Profunzime descărcare:** Descărcări până la 50% = OK, sub 20% = deteriorare
- **Calitate baterie:** Baterii branded (APC, Eaton) vs. generice
## Automatizare Avansată
### Alertare automată când bateria devine POOR:
Adaugă în script (după evaluarea sănătății):
```bash
if [ "$BATTERY_HEALTH" == "POOR" ]; then
# Trimite alert urgent
echo "URGENT: Bateria UPS necesită înlocuire!" | \
mail -s "🔴 ALERT UPS: Baterie CRITICĂ!" admin@company.com
# Notificare SMS (dacă ai configurat)
curl -X POST "https://api.service.com/sms" \
-d "to=+40xxxxxxxxx&message=ALERT: Baterie UPS critica!"
fi
```
### Integrare cu Prometheus/Grafana:
Exportă metrici pentru monitorizare long-term:
```bash
# La final de script, exportă metrici
cat >> /var/lib/node_exporter/textfile_collector/ups_battery.prom << EOF
# HELP ups_battery_health Battery health score (0-100)
# TYPE ups_battery_health gauge
ups_battery_health{ups="nutdev1"} $(( 100 - CHARGE_DROP ))
# HELP ups_battery_charge_drop Battery charge drop during test
# TYPE ups_battery_charge_drop gauge
ups_battery_charge_drop{ups="nutdev1"} $CHARGE_DROP
# HELP ups_battery_test_timestamp Last battery test timestamp
# TYPE ups_battery_test_timestamp gauge
ups_battery_test_timestamp{ups="nutdev1"} $(date +%s)
EOF
```
## Referințe
- **NUT Commands:** https://networkupstools.org/docs/user-manual.chunked/ar01s07.html
- **Battery Testing Best Practices:** https://www.apc.com/us/en/faqs/FAQ000267818/
- **Proxmox Notifications:** https://pve.proxmox.com/wiki/Notifications
## Istoric Versiuni
- **v1.0** (2025-10-06)
- Release inițial
- Test automat baterie cu `test.battery.start.quick`
- Rapoarte HTML și text
- Email notifications
- Cron lunar (1 ale lunii)
- Evaluare sănătate baterie (4 nivele)
- Monitorizare recuperare 5 minute
---
**Autor:** Claude Code
**Ultima actualizare:** 2025-10-06