Add UPS email notifications and automatic UPS shutdown
- Add email notifications via PVE::Notify for all UPS events: - ONBATT: when UPS switches to battery - ONLINE: when power is restored - LOWBATT: critical battery level - SHUTDOWN_START/NODE/PRIMARY: during cluster shutdown - COMMBAD: communication lost with UPS - Add automatic UPS shutdown command after cluster shutdown (protects against power surge when power returns) - Update upssched.conf with ONLINE handler and immediate ONBATT notification - Add notification templates for HTML and text emails - Update documentation with new features and timer configuration Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -68,24 +68,33 @@ Restart servicii
|
|||||||
|
|
||||||
### Scenario 1: Întrerupere scurtă (< 3 minute)
|
### Scenario 1: Întrerupere scurtă (< 3 minute)
|
||||||
1. Curent se întrerupe → UPS trece pe baterie (status: OB)
|
1. Curent se întrerupe → UPS trece pe baterie (status: OB)
|
||||||
2. upssched pornește timer de 180 secunde
|
2. **📧 Email: "Trecere pe baterie"** - notificare imediată
|
||||||
3. Curent revine înainte de 3 minute
|
3. upssched pornește timer de 180 secunde
|
||||||
4. Timer anulat → **Niciun sistem nu se oprește**
|
4. Curent revine înainte de 3 minute
|
||||||
|
5. **📧 Email: "Curent revenit - OK"**
|
||||||
|
6. Timer anulat → **Niciun sistem nu se oprește**
|
||||||
|
|
||||||
### Scenario 2: Întrerupere lungă (> 3 minute)
|
### Scenario 2: Întrerupere lungă (> 3 minute)
|
||||||
1. Curent se întrerupe → UPS pe baterie
|
1. Curent se întrerupe → UPS pe baterie
|
||||||
2. Timer 180 secunde expiră
|
2. **📧 Email: "Trecere pe baterie"**
|
||||||
3. `/usr/local/bin/ups-shutdown-cluster.sh` pornește:
|
3. Timer 180 secunde expiră
|
||||||
- **Step 1:** Oprește toate VM-urile de pe toate nodurile (paralel)
|
4. **📧 Email: "Pe baterie 3 min - SHUTDOWN"**
|
||||||
|
5. `/usr/local/bin/ups-shutdown-cluster.sh` pornește:
|
||||||
|
- **📧 Email: "Shutdown cluster PORNIT"**
|
||||||
|
- **Step 1:** Oprește toate VM-urile și LXC de pe toate nodurile
|
||||||
- **Step 2:** Așteaptă 90 secunde pentru oprire graceful
|
- **Step 2:** Așteaptă 90 secunde pentru oprire graceful
|
||||||
- **Step 3:** Shutdown pve1 și pve2 (noduri secundare)
|
- **Step 3:** Shutdown pve1 → **📧 Email: "Shutdown pve1 trimis"**
|
||||||
- **Step 4:** Așteaptă 30 secunde
|
- **Step 4:** Shutdown pveelite → **📧 Email: "Shutdown pveelite trimis"**
|
||||||
- **Step 5:** Shutdown pvemini (nod primary - ultimul)
|
- **Step 5:** Așteaptă 60 secunde
|
||||||
|
- **📧 Email: "Shutdown pvemini (ULTIMUL NOD)"**
|
||||||
|
- **Step 6:** Comandă UPS shutdown (oprire completă)
|
||||||
|
- **Step 7:** Shutdown pvemini (nod primary - ultimul)
|
||||||
|
|
||||||
### Scenario 3: Baterie scăzută imediată
|
### Scenario 3: Baterie scăzută imediată
|
||||||
1. UPS raportează LOWBATT (baterie critică)
|
1. UPS raportează LOWBATT (baterie critică)
|
||||||
2. Shutdown **IMEDIAT** (fără timer)
|
2. **📧 Email: "BATERIE CRITICĂ - SHUTDOWN IMEDIAT"**
|
||||||
3. Același flux de shutdown orchestrat ca mai sus
|
3. Shutdown **IMEDIAT** (fără timer)
|
||||||
|
4. Același flux de shutdown orchestrat ca mai sus
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
@@ -300,17 +309,29 @@ tail -50 /var/log/ups-monthly-test.log
|
|||||||
|
|
||||||
## Configurare Personalizată
|
## Configurare Personalizată
|
||||||
|
|
||||||
### Modificare timp de așteptare (default: 3 minute)
|
### Modificare timp de asteptare (default: 3 minute)
|
||||||
|
|
||||||
Editează `/etc/nut/upssched.conf` pe pvemini:
|
Fisier: `/etc/nut/upssched.conf` pe pvemini
|
||||||
|
|
||||||
```bash
|
Linia relevanta:
|
||||||
# Schimbă din 180 (3 min) la 300 (5 min)
|
```
|
||||||
AT ONBATT * START-TIMER onbatt 300
|
AT ONBATT * START-TIMER onbatt 180
|
||||||
```
|
```
|
||||||
|
|
||||||
Apoi:
|
Valoarea **180** = secunde (3 minute). Exemple:
|
||||||
|
- 180 = 3 minute
|
||||||
|
- 300 = 5 minute
|
||||||
|
- 600 = 10 minute
|
||||||
|
|
||||||
|
Pentru a modifica:
|
||||||
```bash
|
```bash
|
||||||
|
# Editare manuala
|
||||||
|
nano /etc/nut/upssched.conf
|
||||||
|
|
||||||
|
# Sau comanda directa (exemplu: 5 minute)
|
||||||
|
sed -i 's/START-TIMER onbatt [0-9]*/START-TIMER onbatt 300/' /etc/nut/upssched.conf
|
||||||
|
|
||||||
|
# Restart serviciu pentru a aplica
|
||||||
systemctl restart nut-monitor
|
systemctl restart nut-monitor
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -381,12 +402,31 @@ iptables -A INPUT -p tcp --dport 3493 -s 10.0.20.0/24 -j ACCEPT
|
|||||||
- **Hardware Compatibility:** https://networkupstools.org/stable-hcl.html
|
- **Hardware Compatibility:** https://networkupstools.org/stable-hcl.html
|
||||||
- **WinNUT GitHub:** https://github.com/gawindx/WinNUT-V2
|
- **WinNUT GitHub:** https://github.com/gawindx/WinNUT-V2
|
||||||
|
|
||||||
|
## Notificări Email
|
||||||
|
|
||||||
|
Sistemul trimite notificări email via **PVE::Notify** pentru toate evenimentele importante:
|
||||||
|
|
||||||
|
| Eveniment | Când | Severity |
|
||||||
|
|-----------|------|----------|
|
||||||
|
| **ONBATT** | UPS trece pe baterie | warning |
|
||||||
|
| **ONLINE** | Curentul revine | info |
|
||||||
|
| **LOWBATT** | Baterie critică | error |
|
||||||
|
| **SHUTDOWN_START** | Începe shutdown cluster | error |
|
||||||
|
| **SHUTDOWN_NODE** | Shutdown nod secundar (pentru fiecare) | error |
|
||||||
|
| **SHUTDOWN_PRIMARY** | Shutdown nod primary (ultimul) | error |
|
||||||
|
| **COMMBAD** | Comunicație pierdută cu UPS | warning |
|
||||||
|
|
||||||
|
**Configurare:** Email-urile folosesc notificările Proxmox existente. Verifică că ai configurat un target email în **Datacenter → Notifications**.
|
||||||
|
|
||||||
|
**Template-uri:** `/etc/pve/notification-templates/default/ups-power-event-*`
|
||||||
|
|
||||||
## Funcționalități Complete
|
## Funcționalități Complete
|
||||||
|
|
||||||
### ✅ Shutdown Orchestrat Automat
|
### ✅ Shutdown Orchestrat Automat
|
||||||
- Detectare întrerupere curent (3 minute grace period)
|
- Detectare întrerupere curent (3 minute grace period)
|
||||||
- Oprire ordonată: VM-uri → noduri secundare → nod primary
|
- Oprire ordonată: VM-uri/LXC → noduri secundare → nod primary
|
||||||
- Notificări în timp real prin upssched
|
- **Oprire automată UPS** după shutdown (protecție power surge)
|
||||||
|
- Notificări email la fiecare pas
|
||||||
|
|
||||||
### ✅ Test Lunar Automat Baterie (NOU!)
|
### ✅ Test Lunar Automat Baterie (NOU!)
|
||||||
- Rulare automată pe 1 ale lunii la 00:00
|
- Rulare automată pe 1 ale lunii la 00:00
|
||||||
@@ -410,10 +450,11 @@ iptables -A INPUT -p tcp --dport 3493 -s 10.0.20.0/24 -j ACCEPT
|
|||||||
## Autori și Istoric
|
## Autori și Istoric
|
||||||
|
|
||||||
- **Creat:** 2025-10-06
|
- **Creat:** 2025-10-06
|
||||||
- **Versiune:** 1.1
|
- **Versiune:** 1.2
|
||||||
- **Ultima modificare:** 2025-10-06
|
- **Ultima modificare:** 2026-01-13
|
||||||
- **Autor:** Configurat automat via Claude Code
|
- **Autor:** Configurat automat via Claude Code
|
||||||
- **Changelog:**
|
- **Changelog:**
|
||||||
|
- v1.2 (2026-01-13): Adăugat notificări email pentru toate evenimentele UPS + oprire automată UPS
|
||||||
- v1.1 (2025-10-06): Adăugat test lunar automat baterie cu notificări PVE::Notify
|
- v1.1 (2025-10-06): Adăugat test lunar automat baterie cu notificări PVE::Notify
|
||||||
- v1.0 (2025-10-06): Release inițial cu shutdown orchestrat și monitorizare NUT
|
- v1.0 (2025-10-06): Release inițial cu shutdown orchestrat și monitorizare NUT
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<style>
|
||||||
|
body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background-color: #f5f5f5; }
|
||||||
|
.container { max-width: 600px; margin: 0 auto; background: white; padding: 25px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
|
||||||
|
h1 { margin-top: 0; padding-bottom: 15px; border-bottom: 3px solid #3498db; }
|
||||||
|
.status-onbatt { color: #e67e22; border-color: #e67e22; }
|
||||||
|
.status-online { color: #27ae60; border-color: #27ae60; }
|
||||||
|
.status-lowbatt { color: #c0392b; border-color: #c0392b; }
|
||||||
|
.status-shutdown { color: #8e44ad; border-color: #8e44ad; }
|
||||||
|
.alert-box { padding: 15px; border-radius: 5px; margin: 20px 0; border-left: 4px solid; }
|
||||||
|
.alert-warning { background: #fef9e7; border-color: #f39c12; }
|
||||||
|
.alert-danger { background: #fdedec; border-color: #e74c3c; }
|
||||||
|
.alert-success { background: #eafaf1; border-color: #2ecc71; }
|
||||||
|
.alert-info { background: #ebf5fb; border-color: #3498db; }
|
||||||
|
.metrics { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin: 20px 0; }
|
||||||
|
.metric { background: #ecf0f1; padding: 15px; border-radius: 5px; text-align: center; }
|
||||||
|
.metric-label { font-size: 12px; color: #7f8c8d; text-transform: uppercase; }
|
||||||
|
.metric-value { font-size: 24px; font-weight: bold; color: #2c3e50; margin-top: 5px; }
|
||||||
|
.footer { margin-top: 25px; padding-top: 15px; border-top: 1px solid #ecf0f1; font-size: 12px; color: #7f8c8d; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="status-{{ event_class }}">[UPS] {{ event_title }}</h1>
|
||||||
|
|
||||||
|
<p><strong>Hostname:</strong> {{ hostname }}<br>
|
||||||
|
<strong>Date:</strong> {{ event_date }}<br>
|
||||||
|
<strong>Event:</strong> {{ event_type }}</p>
|
||||||
|
|
||||||
|
<div class="alert-box alert-{{ alert_type }}">
|
||||||
|
<strong>{{ event_description }}</strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>UPS Status</h3>
|
||||||
|
<div class="metrics">
|
||||||
|
<div class="metric">
|
||||||
|
<div class="metric-label">Status</div>
|
||||||
|
<div class="metric-value">{{ ups_status }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="metric">
|
||||||
|
<div class="metric-label">Battery</div>
|
||||||
|
<div class="metric-value">{{ battery_charge }}%</div>
|
||||||
|
</div>
|
||||||
|
<div class="metric">
|
||||||
|
<div class="metric-label">Input Voltage</div>
|
||||||
|
<div class="metric-value">{{ input_voltage }}V</div>
|
||||||
|
</div>
|
||||||
|
{{#if battery_runtime}}
|
||||||
|
<div class="metric">
|
||||||
|
<div class="metric-label">Runtime</div>
|
||||||
|
<div class="metric-value">{{ battery_runtime }} min</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if action_taken}}
|
||||||
|
<p><strong>Action:</strong> {{ action_taken }}</p>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if next_steps}}
|
||||||
|
<p><strong>Next Steps:</strong> {{ next_steps }}</p>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
<p>Log: /var/log/ups-events.log<br>
|
||||||
|
Proxmox UPS Monitoring System</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
========================================
|
||||||
|
UPS POWER EVENT - {{ event_title }}
|
||||||
|
========================================
|
||||||
|
|
||||||
|
Hostname: {{ hostname }}
|
||||||
|
Date: {{ event_date }}
|
||||||
|
Event: {{ event_type }}
|
||||||
|
|
||||||
|
{{ event_description }}
|
||||||
|
|
||||||
|
UPS STATUS:
|
||||||
|
-----------
|
||||||
|
Status: {{ ups_status }}
|
||||||
|
Battery Charge: {{ battery_charge }}%
|
||||||
|
Input Voltage: {{ input_voltage }}V
|
||||||
|
{{#if battery_runtime}}
|
||||||
|
Battery Runtime: {{ battery_runtime }} min
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if action_taken}}
|
||||||
|
ACTION: {{ action_taken }}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if next_steps}}
|
||||||
|
NEXT STEPS: {{ next_steps }}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
========================================
|
||||||
|
Log: /var/log/ups-events.log
|
||||||
|
Script: /usr/local/bin/upssched-cmd
|
||||||
|
========================================
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
[{{ hostname }}] UPS {{ event_type }} - {{ event_title }}
|
||||||
@@ -6,15 +6,18 @@ CMDSCRIPT /usr/local/bin/upssched-cmd
|
|||||||
PIPEFN /run/nut/upssched.pipe
|
PIPEFN /run/nut/upssched.pipe
|
||||||
LOCKFN /run/nut/upssched.lock
|
LOCKFN /run/nut/upssched.lock
|
||||||
|
|
||||||
# Când UPS trece pe baterie (ONBATT), așteaptă 180 secunde (3 minute)
|
# Când UPS trece pe baterie (ONBATT):
|
||||||
# Dacă curentul revine în acest timp, anulează shutdown-ul
|
# 1. Trimite notificare imediată
|
||||||
|
# 2. Așteaptă 180 secunde (3 minute) înainte de shutdown
|
||||||
|
AT ONBATT * EXECUTE onbatt_start
|
||||||
AT ONBATT * START-TIMER onbatt 180
|
AT ONBATT * START-TIMER onbatt 180
|
||||||
|
|
||||||
# Când UPS raportează baterie scăzută (LOWBATT), shutdown imediat
|
# Când UPS raportează baterie scăzută (LOWBATT), shutdown imediat
|
||||||
AT LOWBATT * EXECUTE lowbatt
|
AT LOWBATT * EXECUTE lowbatt
|
||||||
|
|
||||||
# Când curentul revine (ONLINE), anulează toate timer-ele
|
# Când curentul revine (ONLINE), anulează timer-ele și trimite notificare
|
||||||
AT ONLINE * CANCEL-TIMER onbatt
|
AT ONLINE * CANCEL-TIMER onbatt
|
||||||
|
AT ONLINE * EXECUTE online
|
||||||
|
|
||||||
# Când comunicația cu UPS se pierde (COMMBAD), așteaptă 30 secunde
|
# Când comunicația cu UPS se pierde (COMMBAD), așteaptă 30 secunde
|
||||||
AT COMMBAD * START-TIMER commbad 30
|
AT COMMBAD * START-TIMER commbad 30
|
||||||
|
|||||||
@@ -56,9 +56,9 @@ NOTIFYFLAG LOWBATT SYSLOG+WALL+EXEC
|
|||||||
|
|
||||||
#### 5. /etc/nut/upssched.conf
|
#### 5. /etc/nut/upssched.conf
|
||||||
Scheduler pentru evenimente:
|
Scheduler pentru evenimente:
|
||||||
- **ONBATT:** Așteaptă 180 secunde (3 minute) înainte de shutdown
|
- **ONBATT:** Notificare email imediată + așteaptă 180 secunde (3 minute) înainte de shutdown
|
||||||
- **LOWBATT:** Shutdown imediat
|
- **LOWBATT:** Shutdown imediat + notificare email
|
||||||
- **ONLINE:** Anulează toate timer-ele
|
- **ONLINE:** Anulează timer-ele + notificare email "curent revenit"
|
||||||
|
|
||||||
### Scripturi Create
|
### Scripturi Create
|
||||||
|
|
||||||
@@ -67,13 +67,17 @@ Scheduler pentru evenimente:
|
|||||||
|
|
||||||
Ordinea de operații:
|
Ordinea de operații:
|
||||||
1. Verifică status UPS (trebuie OB sau LB)
|
1. Verifică status UPS (trebuie OB sau LB)
|
||||||
2. Oprește toate VM-urile de pe toate nodurile (paralel)
|
2. **📧 Email: "Shutdown cluster PORNIT"**
|
||||||
3. Așteaptă 90 secunde
|
3. Oprește toate VM-urile și LXC de pe toate nodurile (paralel)
|
||||||
4. Shutdown pve1 și pve2 (secundare)
|
4. Așteaptă 90 secunde pentru oprire graceful
|
||||||
5. Așteaptă 30 secunde
|
5. Shutdown pve1 → **📧 Email: "Shutdown pve1 trimis"**
|
||||||
6. Shutdown pvemini (primary - ultimul)
|
6. Shutdown pveelite → **📧 Email: "Shutdown pveelite trimis"**
|
||||||
|
7. Așteaptă 60 secunde
|
||||||
|
8. **📧 Email: "Shutdown pvemini (ULTIMUL NOD)"**
|
||||||
|
9. Comandă UPS shutdown (oprire completă UPS)
|
||||||
|
10. Shutdown pvemini (primary - ultimul)
|
||||||
|
|
||||||
Logare: `/var/log/ups-shutdown.log`
|
Logare: `/var/log/ups-shutdown.log` + `journalctl -t ups-shutdown`
|
||||||
|
|
||||||
#### 2. /usr/local/bin/ups-shutdown-test.sh
|
#### 2. /usr/local/bin/ups-shutdown-test.sh
|
||||||
**Script de test (DRY RUN) - NU oprește nimic**
|
**Script de test (DRY RUN) - NU oprește nimic**
|
||||||
@@ -85,12 +89,15 @@ tail -f /var/log/ups-shutdown-test.log
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### 3. /usr/local/bin/upssched-cmd
|
#### 3. /usr/local/bin/upssched-cmd
|
||||||
**Handler pentru evenimente UPS**
|
**Handler pentru evenimente UPS** - trimite notificări email via PVE::Notify
|
||||||
|
|
||||||
Apelat automat de upssched când:
|
| Eveniment | Acțiune | Email |
|
||||||
- UPS pe baterie 3 minute → lansează shutdown orchestrat
|
|-----------|---------|-------|
|
||||||
- Baterie scăzută → shutdown imediat
|
| `onbatt_start` | UPS trece pe baterie | "Trecere pe baterie - Timer 3 min" |
|
||||||
- Pierdere comunicație → doar logging
|
| `onbatt` | Timer 3 min expirat | "Pe baterie 3 min - SHUTDOWN" + lansare shutdown |
|
||||||
|
| `online` | Curent revenit | "Curent revenit - OK" |
|
||||||
|
| `lowbatt` | Baterie critică | "BATERIE CRITICĂ" + shutdown imediat |
|
||||||
|
| `commbad` | Comunicație pierdută | "Comunicație pierdută cu UPS" |
|
||||||
|
|
||||||
Logare: `/var/log/ups-events.log`
|
Logare: `/var/log/ups-events.log`
|
||||||
|
|
||||||
@@ -156,24 +163,33 @@ tail -f /var/log/ups-events.log
|
|||||||
|
|
||||||
### Scenario 1: Întrerupere Scurtă (< 3 minute)
|
### Scenario 1: Întrerupere Scurtă (< 3 minute)
|
||||||
1. Curent se întrerupe → UPS trece pe baterie
|
1. Curent se întrerupe → UPS trece pe baterie
|
||||||
2. Timer de 180 secunde pornește
|
2. **📧 Email: "Trecere pe baterie"**
|
||||||
3. Curent revine → Timer anulat
|
3. Timer de 180 secunde pornește
|
||||||
4. **Rezultat:** Niciun sistem nu se oprește
|
4. Curent revine → Timer anulat
|
||||||
|
5. **📧 Email: "Curent revenit - OK"**
|
||||||
|
6. **Rezultat:** Niciun sistem nu se oprește
|
||||||
|
|
||||||
### Scenario 2: Întrerupere Lungă (> 3 minute)
|
### Scenario 2: Întrerupere Lungă (> 3 minute)
|
||||||
1. Curent se întrerupe → UPS trece pe baterie
|
1. Curent se întrerupe → UPS trece pe baterie
|
||||||
2. Timer 180 secunde expiră
|
2. **📧 Email: "Trecere pe baterie"**
|
||||||
3. Scriptu de shutdown pornește:
|
3. Timer 180 secunde expiră
|
||||||
- VM-uri se opresc pe toate nodurile
|
4. **📧 Email: "Pe baterie 3 min - SHUTDOWN"**
|
||||||
- După 90s: pve1, pve2 se opresc
|
5. Script de shutdown pornește:
|
||||||
- După încă 30s: pvemini se oprește
|
- **📧 Email: "Shutdown cluster PORNIT"**
|
||||||
4. **Rezultat:** Shutdown orchestrat complet
|
- VM-uri/LXC se opresc pe toate nodurile
|
||||||
|
- După 90s: pve1 se oprește → **📧 Email**
|
||||||
|
- pveelite se oprește → **📧 Email**
|
||||||
|
- După 60s: **📧 Email: "Shutdown pvemini (ULTIMUL NOD)"**
|
||||||
|
- UPS primește comandă shutdown
|
||||||
|
- pvemini se oprește
|
||||||
|
6. **Rezultat:** Shutdown orchestrat complet + UPS oprit
|
||||||
|
|
||||||
### Scenario 3: Baterie Scăzută Imediată
|
### Scenario 3: Baterie Scăzută Imediată
|
||||||
1. UPS raportează LOWBATT
|
1. UPS raportează LOWBATT
|
||||||
2. Shutdown **IMEDIAT** (fără timer)
|
2. **📧 Email: "BATERIE CRITICĂ - SHUTDOWN IMEDIAT"**
|
||||||
3. Același flux de shutdown orchestrat
|
3. Shutdown **IMEDIAT** (fără timer)
|
||||||
4. **Rezultat:** Shutdown rapid pentru protecție
|
4. Același flux de shutdown orchestrat
|
||||||
|
5. **Rezultat:** Shutdown rapid pentru protecție + UPS oprit
|
||||||
|
|
||||||
## Loguri și Troubleshooting
|
## Loguri și Troubleshooting
|
||||||
|
|
||||||
@@ -234,4 +250,4 @@ tail -20 /var/log/ups-events.log
|
|||||||
## Contact și Suport
|
## Contact și Suport
|
||||||
- Documentație NUT: https://networkupstools.org/
|
- Documentație NUT: https://networkupstools.org/
|
||||||
- Script creat: 2025-10-06
|
- Script creat: 2025-10-06
|
||||||
- Ultima modificare: 2025-10-06
|
- Ultima modificare: 2026-01-13 (adăugat notificări email + UPS shutdown)
|
||||||
|
|||||||
@@ -1,33 +1,104 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
# Script de shutdown orchestrat pentru cluster Proxmox când UPS este pe baterie critică
|
# Script de shutdown orchestrat pentru cluster Proxmox cand UPS este pe baterie critica
|
||||||
# Autor: Generat automat
|
# Trimite notificari email via PVE::Notify pentru fiecare pas
|
||||||
# Data: 2025-10-06
|
#
|
||||||
# Actualizat: 2025-10-06 - Adăugat suport LXC containers
|
# Creat: 2025-10-06
|
||||||
|
# Actualizat: 2026-01-13 - Adaugat notificari email si UPS shutdown
|
||||||
|
|
||||||
LOGFILE=/var/log/ups-shutdown.log
|
LOGFILE=/var/log/ups-shutdown.log
|
||||||
NODES=(10.0.20.200 10.0.20.202) # pve1, pveelite (pvemini va fi ultimul)
|
NODES=("10.0.20.200" "10.0.20.202") # pve1, pveelite (pvemini va fi ultimul)
|
||||||
|
NODE_NAMES=("pve1" "pveelite") # Nume pentru notificari
|
||||||
|
UPS_NAME="nutdev1"
|
||||||
|
UPS_USER="admin"
|
||||||
|
UPS_PASS="parola99"
|
||||||
|
TEMPLATE_DIR="/etc/pve/notification-templates/default"
|
||||||
|
HOSTNAME=$(hostname)
|
||||||
|
FQDN=$(hostname -f 2>/dev/null || hostname)
|
||||||
|
|
||||||
log_message() {
|
log_message() {
|
||||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a $LOGFILE
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a $LOGFILE
|
||||||
|
logger -t ups-shutdown "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Obtine status UPS
|
||||||
|
get_ups_info() {
|
||||||
|
echo "Status: $(upsc $UPS_NAME ups.status 2>/dev/null || echo 'UNKNOWN')"
|
||||||
|
echo "Battery: $(upsc $UPS_NAME battery.charge 2>/dev/null || echo '?')%"
|
||||||
|
echo "Input: $(upsc $UPS_NAME input.voltage 2>/dev/null || echo '?')V"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Trimite notificare email via PVE::Notify
|
||||||
|
send_notification() {
|
||||||
|
local EVENT_TYPE="$1"
|
||||||
|
local EVENT_TITLE="$2"
|
||||||
|
local EVENT_DESC="$3"
|
||||||
|
local SEVERITY="$4"
|
||||||
|
|
||||||
|
local UPS_STATUS=$(upsc $UPS_NAME ups.status 2>/dev/null || echo "UNKNOWN")
|
||||||
|
local BATTERY_CHARGE=$(upsc $UPS_NAME battery.charge 2>/dev/null || echo "0")
|
||||||
|
local INPUT_VOLTAGE=$(upsc $UPS_NAME input.voltage 2>/dev/null || echo "0")
|
||||||
|
local EVENT_DATE=$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
log_message "Sending notification: $EVENT_TITLE"
|
||||||
|
|
||||||
|
perl -I/usr/share/perl5 << EOFPERL 2>&1 | tee -a $LOGFILE
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use PVE::Notify;
|
||||||
|
|
||||||
|
my \$template_data = {
|
||||||
|
'hostname' => '$FQDN',
|
||||||
|
'event_date' => '$EVENT_DATE',
|
||||||
|
'event_type' => '$EVENT_TYPE',
|
||||||
|
'event_title' => '$EVENT_TITLE',
|
||||||
|
'event_description' => '$EVENT_DESC',
|
||||||
|
'event_class' => 'shutdown',
|
||||||
|
'alert_type' => 'danger',
|
||||||
|
'ups_status' => '$UPS_STATUS',
|
||||||
|
'battery_charge' => '$BATTERY_CHARGE',
|
||||||
|
'input_voltage' => '$INPUT_VOLTAGE',
|
||||||
|
'action_taken' => 'Shutdown in curs',
|
||||||
|
'next_steps' => ''
|
||||||
|
};
|
||||||
|
|
||||||
|
my \$fields = {
|
||||||
|
'hostname' => '$HOSTNAME',
|
||||||
|
'type' => 'ups-power-event'
|
||||||
|
};
|
||||||
|
|
||||||
|
eval {
|
||||||
|
PVE::Notify::notify('$SEVERITY', 'ups-power-event', \$template_data, \$fields);
|
||||||
|
print "Notification sent\\n";
|
||||||
|
};
|
||||||
|
if (\$@) {
|
||||||
|
print STDERR "Notification failed: \$@\\n";
|
||||||
|
}
|
||||||
|
EOFPERL
|
||||||
}
|
}
|
||||||
|
|
||||||
log_message "========================================"
|
log_message "========================================"
|
||||||
log_message "UPS SHUTDOWN ORCHESTRATION STARTED"
|
log_message "UPS SHUTDOWN ORCHESTRATION STARTED"
|
||||||
log_message "UPS Status: $(upsc nutdev1 ups.status 2>/dev/null || echo 'UNKNOWN')"
|
log_message "$(get_ups_info)"
|
||||||
log_message "Battery Charge: $(upsc nutdev1 battery.charge 2>/dev/null || echo 'UNKNOWN')%"
|
|
||||||
log_message "========================================"
|
log_message "========================================"
|
||||||
|
|
||||||
# Verifică dacă UPS este într-adevăr pe baterie critică
|
# Verifica daca UPS este intr-adevar pe baterie critica
|
||||||
UPS_STATUS=$(upsc nutdev1 ups.status 2>/dev/null)
|
UPS_STATUS=$(upsc $UPS_NAME ups.status 2>/dev/null)
|
||||||
if [[ ! $UPS_STATUS =~ (OB|LB) ]]; then
|
if [[ ! $UPS_STATUS =~ (OB|LB) ]]; then
|
||||||
log_message "WARNING: UPS status is $UPS_STATUS - not critical. Aborting shutdown."
|
log_message "WARNING: UPS status is $UPS_STATUS - not critical. Aborting shutdown."
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Email: START SHUTDOWN
|
||||||
|
send_notification \
|
||||||
|
"SHUTDOWN_START" \
|
||||||
|
"Shutdown cluster PORNIT" \
|
||||||
|
"UPS pe baterie critica. Se initiaza oprirea ordonata a cluster-ului Proxmox." \
|
||||||
|
"error"
|
||||||
|
|
||||||
log_message "Step 1: Oprire VM-uri pe toate nodurile..."
|
log_message "Step 1: Oprire VM-uri pe toate nodurile..."
|
||||||
|
|
||||||
# Oprește VM-uri pe toate nodurile (inclusiv local)
|
# Opreste VM-uri pe toate nodurile (inclusiv local)
|
||||||
for node in ${NODES[@]} localhost; do
|
for node in ${NODES[@]} localhost; do
|
||||||
if [ "$node" == "localhost" ]; then
|
if [ "$node" == "localhost" ]; then
|
||||||
NODE_NAME="pvemini (local)"
|
NODE_NAME="pvemini (local)"
|
||||||
@@ -38,7 +109,6 @@ for node in ${NODES[@]} localhost; do
|
|||||||
log_message " - Oprire VM-uri pe $NODE_NAME..."
|
log_message " - Oprire VM-uri pe $NODE_NAME..."
|
||||||
|
|
||||||
if [ "$node" == "localhost" ]; then
|
if [ "$node" == "localhost" ]; then
|
||||||
# Local - oprește VM-urile direct
|
|
||||||
for vmid in $(qm list | awk 'NR>1 {print $1}'); do
|
for vmid in $(qm list | awk 'NR>1 {print $1}'); do
|
||||||
vm_status=$(qm status $vmid | awk '{print $2}')
|
vm_status=$(qm status $vmid | awk '{print $2}')
|
||||||
if [ "$vm_status" == "running" ]; then
|
if [ "$vm_status" == "running" ]; then
|
||||||
@@ -47,7 +117,6 @@ for node in ${NODES[@]} localhost; do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
else
|
else
|
||||||
# Remote - SSH către alt nod
|
|
||||||
ssh -o ConnectTimeout=5 root@$node "
|
ssh -o ConnectTimeout=5 root@$node "
|
||||||
for vmid in \$(qm list | awk 'NR>1 {print \$1}'); do
|
for vmid in \$(qm list | awk 'NR>1 {print \$1}'); do
|
||||||
vm_status=\$(qm status \$vmid | awk '{print \$2}')
|
vm_status=\$(qm status \$vmid | awk '{print \$2}')
|
||||||
@@ -62,7 +131,7 @@ done
|
|||||||
|
|
||||||
log_message "Step 2: Oprire containere LXC pe toate nodurile..."
|
log_message "Step 2: Oprire containere LXC pe toate nodurile..."
|
||||||
|
|
||||||
# Oprește containere LXC pe toate nodurile
|
# Opreste containere LXC pe toate nodurile
|
||||||
for node in ${NODES[@]} localhost; do
|
for node in ${NODES[@]} localhost; do
|
||||||
if [ "$node" == "localhost" ]; then
|
if [ "$node" == "localhost" ]; then
|
||||||
NODE_NAME="pvemini (local)"
|
NODE_NAME="pvemini (local)"
|
||||||
@@ -73,13 +142,11 @@ for node in ${NODES[@]} localhost; do
|
|||||||
log_message " - Oprire LXC pe $NODE_NAME..."
|
log_message " - Oprire LXC pe $NODE_NAME..."
|
||||||
|
|
||||||
if [ "$node" == "localhost" ]; then
|
if [ "$node" == "localhost" ]; then
|
||||||
# Local - oprește containerele direct
|
|
||||||
pct list 2>/dev/null | awk 'NR>1 && $2=="running" {print $1}' | while read ctid; do
|
pct list 2>/dev/null | awk 'NR>1 && $2=="running" {print $1}' | while read ctid; do
|
||||||
log_message " * Oprire container $ctid pe pvemini..."
|
log_message " * Oprire container $ctid pe pvemini..."
|
||||||
pct shutdown $ctid --timeout 60 &
|
pct shutdown $ctid --timeout 60 &
|
||||||
done
|
done
|
||||||
else
|
else
|
||||||
# Remote - SSH către alt nod
|
|
||||||
ssh -o ConnectTimeout=5 root@$node "
|
ssh -o ConnectTimeout=5 root@$node "
|
||||||
pct list 2>/dev/null | awk 'NR>1 && \$2==\"running\" {print \$1}' | while read ctid; do
|
pct list 2>/dev/null | awk 'NR>1 && \$2==\"running\" {print \$1}' | while read ctid; do
|
||||||
echo ' * Oprire container '\$ctid' pe $node...'
|
echo ' * Oprire container '\$ctid' pe $node...'
|
||||||
@@ -89,25 +156,61 @@ for node in ${NODES[@]} localhost; do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
log_message "Step 3: Așteptare 90 secunde pentru oprirea VM-urilor și LXC..."
|
log_message "Step 3: Asteptare 90 secunde pentru oprirea VM-urilor si LXC..."
|
||||||
sleep 90
|
sleep 90
|
||||||
|
|
||||||
log_message "Step 4: Oprire noduri secundare (pve1, pveelite)..."
|
log_message "Step 4: Oprire noduri secundare..."
|
||||||
for node in ${NODES[@]}; do
|
|
||||||
log_message " - Shutdown nod $node..."
|
# Opreste nodurile secundare si trimite notificare pentru fiecare
|
||||||
ssh -o ConnectTimeout=5 root@$node "shutdown -h +1 'UPS on battery critical - shutting down'" 2>&1 | tee -a $LOGFILE &
|
for i in "${!NODES[@]}"; do
|
||||||
|
node="${NODES[$i]}"
|
||||||
|
node_name="${NODE_NAMES[$i]}"
|
||||||
|
|
||||||
|
log_message " - Shutdown nod $node_name ($node)..."
|
||||||
|
|
||||||
|
# Email: SHUTDOWN NOD SECUNDAR
|
||||||
|
send_notification \
|
||||||
|
"SHUTDOWN_NODE" \
|
||||||
|
"Shutdown $node_name trimis" \
|
||||||
|
"Comanda shutdown a fost trimisa catre nodul $node_name ($node)." \
|
||||||
|
"error"
|
||||||
|
|
||||||
|
ssh -o ConnectTimeout=5 root@$node "shutdown -h +1 'UPS battery critical - shutting down'" 2>&1 | tee -a $LOGFILE &
|
||||||
done
|
done
|
||||||
|
|
||||||
log_message "Step 5: Așteptare 30 secunde pentru shutdown noduri secundare..."
|
log_message "Step 5: Asteptare 60 secunde pentru shutdown noduri secundare..."
|
||||||
sleep 30
|
sleep 60
|
||||||
|
|
||||||
log_message "Step 6: Oprire nod local (pvemini - primary)..."
|
log_message "Step 6: Oprire nod local (pvemini - primary)..."
|
||||||
|
|
||||||
|
# Email: SHUTDOWN NOD PRIMARY (ultimul email inainte de shutdown)
|
||||||
|
send_notification \
|
||||||
|
"SHUTDOWN_PRIMARY" \
|
||||||
|
"Shutdown pvemini (ULTIMUL NOD)" \
|
||||||
|
"Se opreste nodul primary pvemini. Acesta este ultimul nod din cluster. UPS-ul se va opri dupa shutdown." \
|
||||||
|
"error"
|
||||||
|
|
||||||
|
log_message "Step 7: Oprire UPS dupa shutdown..."
|
||||||
|
|
||||||
|
# Comanda UPS sa se opreasca dupa un delay (permite shutdown-ul sa se finalizeze)
|
||||||
|
# Verifica daca comanda este disponibila
|
||||||
|
if upscmd -l $UPS_NAME 2>/dev/null | grep -q "shutdown.stayoff"; then
|
||||||
|
log_message " - Comanda UPS shutdown.stayoff (oprire completa)..."
|
||||||
|
upscmd -u $UPS_USER -p $UPS_PASS $UPS_NAME shutdown.stayoff 2>&1 | tee -a $LOGFILE
|
||||||
|
elif upscmd -l $UPS_NAME 2>/dev/null | grep -q "shutdown.return"; then
|
||||||
|
log_message " - Comanda UPS shutdown.return (oprire cu restart la revenire curent)..."
|
||||||
|
upscmd -u $UPS_USER -p $UPS_PASS $UPS_NAME shutdown.return 2>&1 | tee -a $LOGFILE
|
||||||
|
else
|
||||||
|
log_message " - WARNING: Nu s-a gasit comanda UPS shutdown disponibila"
|
||||||
|
fi
|
||||||
|
|
||||||
log_message "========================================"
|
log_message "========================================"
|
||||||
log_message "UPS SHUTDOWN ORCHESTRATION COMPLETED"
|
log_message "UPS SHUTDOWN ORCHESTRATION COMPLETED"
|
||||||
|
log_message "$(get_ups_info)"
|
||||||
log_message "Local node will shutdown in 1 minute"
|
log_message "Local node will shutdown in 1 minute"
|
||||||
log_message "========================================"
|
log_message "========================================"
|
||||||
|
|
||||||
# Oprește nodul local (ultimul)
|
# Opreste nodul local (ultimul)
|
||||||
shutdown -h +1 "UPS on battery critical - primary node shutting down"
|
shutdown -h +1 "UPS battery critical - primary node shutting down"
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -1,30 +1,297 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
# Script apelat de upssched pentru a gestiona evenimentele UPS
|
# Script apelat de upssched pentru a gestiona evenimentele UPS
|
||||||
|
# Trimite notificari email via PVE::Notify
|
||||||
#
|
#
|
||||||
|
# Creat: 2025-10-06
|
||||||
|
# Actualizat: 2026-01-13 - Adaugat notificari email
|
||||||
|
|
||||||
LOGFILE=/var/log/ups-events.log
|
LOGFILE=/var/log/ups-events.log
|
||||||
|
UPS_NAME="nutdev1"
|
||||||
|
TEMPLATE_DIR="/etc/pve/notification-templates/default"
|
||||||
|
HOSTNAME=$(hostname)
|
||||||
|
FQDN=$(hostname -f 2>/dev/null || hostname)
|
||||||
|
|
||||||
log_event() {
|
log_event() {
|
||||||
echo "[2025-10-06 20:03:38] $1" >> $LOGFILE
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> $LOGFILE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Obtine status UPS
|
||||||
|
get_ups_status() {
|
||||||
|
upsc $UPS_NAME ups.status 2>/dev/null || echo "UNKNOWN"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_battery_charge() {
|
||||||
|
upsc $UPS_NAME battery.charge 2>/dev/null || echo "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_input_voltage() {
|
||||||
|
upsc $UPS_NAME input.voltage 2>/dev/null || echo "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_battery_runtime() {
|
||||||
|
local runtime=$(upsc $UPS_NAME battery.runtime 2>/dev/null)
|
||||||
|
if [ -n "$runtime" ] && [ "$runtime" != "0" ]; then
|
||||||
|
echo $((runtime / 60))
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Creeaza template-uri daca nu exista
|
||||||
|
create_templates() {
|
||||||
|
mkdir -p $TEMPLATE_DIR
|
||||||
|
|
||||||
|
cat > "$TEMPLATE_DIR/ups-power-event-subject.txt.hbs" << 'EOFTEMPLATE'
|
||||||
|
[{{ hostname }}] UPS {{ event_type }} - {{ event_title }}
|
||||||
|
EOFTEMPLATE
|
||||||
|
|
||||||
|
cat > "$TEMPLATE_DIR/ups-power-event-body.txt.hbs" << 'EOFTEMPLATE'
|
||||||
|
========================================
|
||||||
|
UPS POWER EVENT - {{ event_title }}
|
||||||
|
========================================
|
||||||
|
|
||||||
|
Hostname: {{ hostname }}
|
||||||
|
Date: {{ event_date }}
|
||||||
|
Event: {{ event_type }}
|
||||||
|
|
||||||
|
{{ event_description }}
|
||||||
|
|
||||||
|
UPS STATUS:
|
||||||
|
-----------
|
||||||
|
Status: {{ ups_status }}
|
||||||
|
Battery Charge: {{ battery_charge }}%
|
||||||
|
Input Voltage: {{ input_voltage }}V
|
||||||
|
{{#if battery_runtime}}
|
||||||
|
Battery Runtime: {{ battery_runtime }} min
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if action_taken}}
|
||||||
|
ACTION: {{ action_taken }}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if next_steps}}
|
||||||
|
NEXT STEPS: {{ next_steps }}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
========================================
|
||||||
|
Log: /var/log/ups-events.log
|
||||||
|
========================================
|
||||||
|
EOFTEMPLATE
|
||||||
|
|
||||||
|
cat > "$TEMPLATE_DIR/ups-power-event-body.html.hbs" << 'EOFTEMPLATE'
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<style>
|
||||||
|
body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background-color: #f5f5f5; }
|
||||||
|
.container { max-width: 600px; margin: 0 auto; background: white; padding: 25px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
|
||||||
|
h1 { margin-top: 0; padding-bottom: 15px; border-bottom: 3px solid #3498db; }
|
||||||
|
.status-onbatt { color: #e67e22; border-color: #e67e22; }
|
||||||
|
.status-online { color: #27ae60; border-color: #27ae60; }
|
||||||
|
.status-lowbatt { color: #c0392b; border-color: #c0392b; }
|
||||||
|
.status-shutdown { color: #8e44ad; border-color: #8e44ad; }
|
||||||
|
.alert-box { padding: 15px; border-radius: 5px; margin: 20px 0; border-left: 4px solid; }
|
||||||
|
.alert-warning { background: #fef9e7; border-color: #f39c12; }
|
||||||
|
.alert-danger { background: #fdedec; border-color: #e74c3c; }
|
||||||
|
.alert-success { background: #eafaf1; border-color: #2ecc71; }
|
||||||
|
.alert-info { background: #ebf5fb; border-color: #3498db; }
|
||||||
|
.metrics { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin: 20px 0; }
|
||||||
|
.metric { background: #ecf0f1; padding: 15px; border-radius: 5px; text-align: center; }
|
||||||
|
.metric-label { font-size: 12px; color: #7f8c8d; text-transform: uppercase; }
|
||||||
|
.metric-value { font-size: 24px; font-weight: bold; color: #2c3e50; margin-top: 5px; }
|
||||||
|
.footer { margin-top: 25px; padding-top: 15px; border-top: 1px solid #ecf0f1; font-size: 12px; color: #7f8c8d; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="status-{{ event_class }}">[UPS] {{ event_title }}</h1>
|
||||||
|
<p><strong>Hostname:</strong> {{ hostname }}<br>
|
||||||
|
<strong>Date:</strong> {{ event_date }}<br>
|
||||||
|
<strong>Event:</strong> {{ event_type }}</p>
|
||||||
|
<div class="alert-box alert-{{ alert_type }}">
|
||||||
|
<strong>{{ event_description }}</strong>
|
||||||
|
</div>
|
||||||
|
<h3>UPS Status</h3>
|
||||||
|
<div class="metrics">
|
||||||
|
<div class="metric">
|
||||||
|
<div class="metric-label">Status</div>
|
||||||
|
<div class="metric-value">{{ ups_status }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="metric">
|
||||||
|
<div class="metric-label">Battery</div>
|
||||||
|
<div class="metric-value">{{ battery_charge }}%</div>
|
||||||
|
</div>
|
||||||
|
<div class="metric">
|
||||||
|
<div class="metric-label">Input Voltage</div>
|
||||||
|
<div class="metric-value">{{ input_voltage }}V</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{#if action_taken}}
|
||||||
|
<p><strong>Action:</strong> {{ action_taken }}</p>
|
||||||
|
{{/if}}
|
||||||
|
{{#if next_steps}}
|
||||||
|
<p><strong>Next Steps:</strong> {{ next_steps }}</p>
|
||||||
|
{{/if}}
|
||||||
|
<div class="footer">
|
||||||
|
<p>Log: /var/log/ups-events.log<br>Proxmox UPS Monitoring</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
EOFTEMPLATE
|
||||||
|
|
||||||
|
log_event "Templates created in $TEMPLATE_DIR/"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Trimite notificare email via PVE::Notify
|
||||||
|
send_notification() {
|
||||||
|
local EVENT_TYPE="$1"
|
||||||
|
local EVENT_TITLE="$2"
|
||||||
|
local EVENT_DESC="$3"
|
||||||
|
local EVENT_CLASS="$4"
|
||||||
|
local ALERT_TYPE="$5"
|
||||||
|
local SEVERITY="$6"
|
||||||
|
local ACTION="$7"
|
||||||
|
local NEXT_STEPS="$8"
|
||||||
|
|
||||||
|
# Verifica si creeaza template-uri
|
||||||
|
if [ ! -f "$TEMPLATE_DIR/ups-power-event-subject.txt.hbs" ]; then
|
||||||
|
create_templates
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Obtine status UPS
|
||||||
|
local UPS_STATUS=$(get_ups_status)
|
||||||
|
local BATTERY_CHARGE=$(get_battery_charge)
|
||||||
|
local INPUT_VOLTAGE=$(get_input_voltage)
|
||||||
|
local BATTERY_RUNTIME=$(get_battery_runtime)
|
||||||
|
local EVENT_DATE=$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
log_event "Sending $SEVERITY notification: $EVENT_TITLE"
|
||||||
|
|
||||||
|
perl -I/usr/share/perl5 << EOFPERL 2>&1 | tee -a $LOGFILE
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use PVE::Notify;
|
||||||
|
|
||||||
|
my \$template_data = {
|
||||||
|
'hostname' => '$FQDN',
|
||||||
|
'event_date' => '$EVENT_DATE',
|
||||||
|
'event_type' => '$EVENT_TYPE',
|
||||||
|
'event_title' => '$EVENT_TITLE',
|
||||||
|
'event_description' => '$EVENT_DESC',
|
||||||
|
'event_class' => '$EVENT_CLASS',
|
||||||
|
'alert_type' => '$ALERT_TYPE',
|
||||||
|
'ups_status' => '$UPS_STATUS',
|
||||||
|
'battery_charge' => '$BATTERY_CHARGE',
|
||||||
|
'input_voltage' => '$INPUT_VOLTAGE',
|
||||||
|
'battery_runtime' => '$BATTERY_RUNTIME',
|
||||||
|
'action_taken' => '$ACTION',
|
||||||
|
'next_steps' => '$NEXT_STEPS'
|
||||||
|
};
|
||||||
|
|
||||||
|
my \$fields = {
|
||||||
|
'hostname' => '$HOSTNAME',
|
||||||
|
'type' => 'ups-power-event'
|
||||||
|
};
|
||||||
|
|
||||||
|
eval {
|
||||||
|
PVE::Notify::notify('$SEVERITY', 'ups-power-event', \$template_data, \$fields);
|
||||||
|
print "Email notification sent successfully\\n";
|
||||||
|
};
|
||||||
|
if (\$@) {
|
||||||
|
print STDERR "Failed to send notification: \$@\\n";
|
||||||
|
}
|
||||||
|
EOFPERL
|
||||||
|
}
|
||||||
|
|
||||||
|
# Handler principal
|
||||||
case $1 in
|
case $1 in
|
||||||
|
onbatt_start)
|
||||||
|
log_event "=========================================="
|
||||||
|
log_event "UPS EVENT: Trecere pe baterie - Timer 3 minute pornit"
|
||||||
|
logger -t upssched-cmd "UPS switched to battery - 3 minute timer started"
|
||||||
|
|
||||||
|
send_notification \
|
||||||
|
"ONBATT" \
|
||||||
|
"Trecere pe baterie" \
|
||||||
|
"UPS a trecut pe baterie! Daca curentul nu revine in 3 minute, se va initia shutdown-ul cluster-ului." \
|
||||||
|
"onbatt" \
|
||||||
|
"warning" \
|
||||||
|
"warning" \
|
||||||
|
"Timer 3 minute pornit" \
|
||||||
|
"Asteptare revenire curent sau shutdown automat"
|
||||||
|
;;
|
||||||
|
|
||||||
onbatt)
|
onbatt)
|
||||||
log_event "UPS EVENT: Pe baterie de 3 minute - Începe shutdown orchestrat"
|
log_event "=========================================="
|
||||||
|
log_event "UPS EVENT: Pe baterie de 3 minute - Incepe shutdown orchestrat"
|
||||||
logger -t upssched-cmd "UPS on battery for 3 minutes - starting orchestrated shutdown"
|
logger -t upssched-cmd "UPS on battery for 3 minutes - starting orchestrated shutdown"
|
||||||
|
|
||||||
|
send_notification \
|
||||||
|
"ONBATT_TIMEOUT" \
|
||||||
|
"Pe baterie 3 min - SHUTDOWN" \
|
||||||
|
"UPS a fost pe baterie timp de 3 minute. Se initiaza shutdown-ul orchestrat al cluster-ului." \
|
||||||
|
"onbatt" \
|
||||||
|
"danger" \
|
||||||
|
"error" \
|
||||||
|
"Pornire shutdown orchestrat cluster" \
|
||||||
|
"Toate nodurile se vor opri in ordine"
|
||||||
|
|
||||||
/usr/local/bin/ups-shutdown-cluster.sh &
|
/usr/local/bin/ups-shutdown-cluster.sh &
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
online)
|
||||||
|
log_event "=========================================="
|
||||||
|
log_event "UPS EVENT: Curent revenit - UPS online"
|
||||||
|
logger -t upssched-cmd "Power restored - UPS back online"
|
||||||
|
|
||||||
|
send_notification \
|
||||||
|
"ONLINE" \
|
||||||
|
"Curent revenit - OK" \
|
||||||
|
"Curentul electric a revenit. UPS functioneaza normal pe linia AC." \
|
||||||
|
"online" \
|
||||||
|
"success" \
|
||||||
|
"info" \
|
||||||
|
"Sistem stabil" \
|
||||||
|
"Nicio actiune necesara"
|
||||||
|
;;
|
||||||
|
|
||||||
lowbatt)
|
lowbatt)
|
||||||
log_event "UPS EVENT: BATERIE SCĂZUTĂ - Shutdown IMEDIAT"
|
log_event "=========================================="
|
||||||
|
log_event "UPS EVENT: BATERIE SCAZUTA - Shutdown IMEDIAT"
|
||||||
logger -t upssched-cmd "UPS LOW BATTERY - immediate shutdown"
|
logger -t upssched-cmd "UPS LOW BATTERY - immediate shutdown"
|
||||||
|
|
||||||
|
send_notification \
|
||||||
|
"LOWBATT" \
|
||||||
|
"BATERIE CRITICA - SHUTDOWN IMEDIAT" \
|
||||||
|
"UPS raporteaza baterie critica! Shutdown imediat pentru protectia datelor." \
|
||||||
|
"lowbatt" \
|
||||||
|
"danger" \
|
||||||
|
"error" \
|
||||||
|
"Shutdown imediat cluster" \
|
||||||
|
"Sistemele se opresc ACUM"
|
||||||
|
|
||||||
/usr/local/bin/ups-shutdown-cluster.sh &
|
/usr/local/bin/ups-shutdown-cluster.sh &
|
||||||
;;
|
;;
|
||||||
|
|
||||||
commbad)
|
commbad)
|
||||||
log_event "UPS EVENT: Comunicație pierdută cu UPS de 30 secunde"
|
log_event "=========================================="
|
||||||
|
log_event "UPS EVENT: Comunicatie pierduta cu UPS de 30 secunde"
|
||||||
logger -t upssched-cmd "Lost communication with UPS for 30 seconds"
|
logger -t upssched-cmd "Lost communication with UPS for 30 seconds"
|
||||||
# Nu facem shutdown automat pentru pierdere comunicație
|
|
||||||
|
send_notification \
|
||||||
|
"COMMBAD" \
|
||||||
|
"Comunicatie pierduta cu UPS" \
|
||||||
|
"Nu se poate comunica cu UPS-ul de 30 de secunde. Verificati conexiunea USB." \
|
||||||
|
"commbad" \
|
||||||
|
"warning" \
|
||||||
|
"warning" \
|
||||||
|
"Monitorizare activa" \
|
||||||
|
"Verificati conexiunea fizica USB a UPS-ului"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
log_event "UPS EVENT: Eveniment necunoscut - $1"
|
log_event "UPS EVENT: Eveniment necunoscut - $1"
|
||||||
logger -t upssched-cmd "Unknown UPS event: $1"
|
logger -t upssched-cmd "Unknown UPS event: $1"
|
||||||
|
|||||||
Reference in New Issue
Block a user