diff --git a/proxmox/ups/README.md b/proxmox/ups/README.md
index 616a2eb..d4172c6 100644
--- a/proxmox/ups/README.md
+++ b/proxmox/ups/README.md
@@ -68,24 +68,33 @@ Restart servicii
### Scenario 1: Întrerupere scurtă (< 3 minute)
1. Curent se întrerupe → UPS trece pe baterie (status: OB)
-2. upssched pornește timer de 180 secunde
-3. Curent revine înainte de 3 minute
-4. Timer anulat → **Niciun sistem nu se oprește**
+2. **📧 Email: "Trecere pe baterie"** - notificare imediată
+3. upssched pornește timer de 180 secunde
+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)
1. Curent se întrerupe → UPS pe baterie
-2. Timer 180 secunde expiră
-3. `/usr/local/bin/ups-shutdown-cluster.sh` pornește:
- - **Step 1:** Oprește toate VM-urile de pe toate nodurile (paralel)
+2. **📧 Email: "Trecere pe baterie"**
+3. Timer 180 secunde expiră
+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 3:** Shutdown pve1 și pve2 (noduri secundare)
- - **Step 4:** Așteaptă 30 secunde
- - **Step 5:** Shutdown pvemini (nod primary - ultimul)
+ - **Step 3:** Shutdown pve1 → **📧 Email: "Shutdown pve1 trimis"**
+ - **Step 4:** Shutdown pveelite → **📧 Email: "Shutdown pveelite trimis"**
+ - **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ă
1. UPS raportează LOWBATT (baterie critică)
-2. Shutdown **IMEDIAT** (fără timer)
-3. Același flux de shutdown orchestrat ca mai sus
+2. **📧 Email: "BATERIE CRITICĂ - SHUTDOWN IMEDIAT"**
+3. Shutdown **IMEDIAT** (fără timer)
+4. Același flux de shutdown orchestrat ca mai sus
## Quick Start
@@ -300,17 +309,29 @@ tail -50 /var/log/ups-monthly-test.log
## 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
-# Schimbă din 180 (3 min) la 300 (5 min)
-AT ONBATT * START-TIMER onbatt 300
+Linia relevanta:
+```
+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
+# 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
```
@@ -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
- **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
### ✅ Shutdown Orchestrat Automat
- Detectare întrerupere curent (3 minute grace period)
-- Oprire ordonată: VM-uri → noduri secundare → nod primary
-- Notificări în timp real prin upssched
+- Oprire ordonată: VM-uri/LXC → noduri secundare → nod primary
+- **Oprire automată UPS** după shutdown (protecție power surge)
+- Notificări email la fiecare pas
### ✅ Test Lunar Automat Baterie (NOU!)
- 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
- **Creat:** 2025-10-06
-- **Versiune:** 1.1
-- **Ultima modificare:** 2025-10-06
+- **Versiune:** 1.2
+- **Ultima modificare:** 2026-01-13
- **Autor:** Configurat automat via Claude Code
- **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.0 (2025-10-06): Release inițial cu shutdown orchestrat și monitorizare NUT
diff --git a/proxmox/ups/config/notification-templates/ups-power-event-body.html.hbs b/proxmox/ups/config/notification-templates/ups-power-event-body.html.hbs
new file mode 100644
index 0000000..32de518
--- /dev/null
+++ b/proxmox/ups/config/notification-templates/ups-power-event-body.html.hbs
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
[UPS] {{ event_title }}
+
+
Hostname: {{ hostname }}
+ Date: {{ event_date }}
+ Event: {{ event_type }}
+
+
+ {{ event_description }}
+
+
+
UPS Status
+
+
+
Status
+
{{ ups_status }}
+
+
+
Battery
+
{{ battery_charge }}%
+
+
+
Input Voltage
+
{{ input_voltage }}V
+
+ {{#if battery_runtime}}
+
+
Runtime
+
{{ battery_runtime }} min
+
+ {{/if}}
+
+
+ {{#if action_taken}}
+
Action: {{ action_taken }}
+ {{/if}}
+
+ {{#if next_steps}}
+
Next Steps: {{ next_steps }}
+ {{/if}}
+
+
+
+
+
diff --git a/proxmox/ups/config/notification-templates/ups-power-event-body.txt.hbs b/proxmox/ups/config/notification-templates/ups-power-event-body.txt.hbs
new file mode 100644
index 0000000..bca4ded
--- /dev/null
+++ b/proxmox/ups/config/notification-templates/ups-power-event-body.txt.hbs
@@ -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
+========================================
diff --git a/proxmox/ups/config/notification-templates/ups-power-event-subject.txt.hbs b/proxmox/ups/config/notification-templates/ups-power-event-subject.txt.hbs
new file mode 100644
index 0000000..fe1724d
--- /dev/null
+++ b/proxmox/ups/config/notification-templates/ups-power-event-subject.txt.hbs
@@ -0,0 +1 @@
+[{{ hostname }}] UPS {{ event_type }} - {{ event_title }}
diff --git a/proxmox/ups/config/upssched.conf b/proxmox/ups/config/upssched.conf
index dbe2ca1..9a8b315 100644
--- a/proxmox/ups/config/upssched.conf
+++ b/proxmox/ups/config/upssched.conf
@@ -6,15 +6,18 @@ CMDSCRIPT /usr/local/bin/upssched-cmd
PIPEFN /run/nut/upssched.pipe
LOCKFN /run/nut/upssched.lock
-# Când UPS trece pe baterie (ONBATT), așteaptă 180 secunde (3 minute)
-# Dacă curentul revine în acest timp, anulează shutdown-ul
+# Când UPS trece pe baterie (ONBATT):
+# 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
# Când UPS raportează baterie scăzută (LOWBATT), shutdown imediat
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 * EXECUTE online
# Când comunicația cu UPS se pierde (COMMBAD), așteaptă 30 secunde
AT COMMBAD * START-TIMER commbad 30
diff --git a/proxmox/ups/docs/UPS-SHUTDOWN-README.md b/proxmox/ups/docs/UPS-SHUTDOWN-README.md
index 6312e32..5f52756 100644
--- a/proxmox/ups/docs/UPS-SHUTDOWN-README.md
+++ b/proxmox/ups/docs/UPS-SHUTDOWN-README.md
@@ -56,9 +56,9 @@ NOTIFYFLAG LOWBATT SYSLOG+WALL+EXEC
#### 5. /etc/nut/upssched.conf
Scheduler pentru evenimente:
-- **ONBATT:** Așteaptă 180 secunde (3 minute) înainte de shutdown
-- **LOWBATT:** Shutdown imediat
-- **ONLINE:** Anulează toate timer-ele
+- **ONBATT:** Notificare email imediată + așteaptă 180 secunde (3 minute) înainte de shutdown
+- **LOWBATT:** Shutdown imediat + notificare email
+- **ONLINE:** Anulează timer-ele + notificare email "curent revenit"
### Scripturi Create
@@ -67,13 +67,17 @@ Scheduler pentru evenimente:
Ordinea de operații:
1. Verifică status UPS (trebuie OB sau LB)
-2. Oprește toate VM-urile de pe toate nodurile (paralel)
-3. Așteaptă 90 secunde
-4. Shutdown pve1 și pve2 (secundare)
-5. Așteaptă 30 secunde
-6. Shutdown pvemini (primary - ultimul)
+2. **📧 Email: "Shutdown cluster PORNIT"**
+3. Oprește toate VM-urile și LXC de pe toate nodurile (paralel)
+4. Așteaptă 90 secunde pentru oprire graceful
+5. Shutdown pve1 → **📧 Email: "Shutdown pve1 trimis"**
+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
**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
-**Handler pentru evenimente UPS**
+**Handler pentru evenimente UPS** - trimite notificări email via PVE::Notify
-Apelat automat de upssched când:
-- UPS pe baterie 3 minute → lansează shutdown orchestrat
-- Baterie scăzută → shutdown imediat
-- Pierdere comunicație → doar logging
+| Eveniment | Acțiune | Email |
+|-----------|---------|-------|
+| `onbatt_start` | UPS trece pe baterie | "Trecere pe baterie - Timer 3 min" |
+| `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`
@@ -156,24 +163,33 @@ tail -f /var/log/ups-events.log
### Scenario 1: Întrerupere Scurtă (< 3 minute)
1. Curent se întrerupe → UPS trece pe baterie
-2. Timer de 180 secunde pornește
-3. Curent revine → Timer anulat
-4. **Rezultat:** Niciun sistem nu se oprește
+2. **📧 Email: "Trecere pe baterie"**
+3. Timer de 180 secunde porneș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)
1. Curent se întrerupe → UPS trece pe baterie
-2. Timer 180 secunde expiră
-3. Scriptu de shutdown pornește:
- - VM-uri se opresc pe toate nodurile
- - După 90s: pve1, pve2 se opresc
- - După încă 30s: pvemini se oprește
-4. **Rezultat:** Shutdown orchestrat complet
+2. **📧 Email: "Trecere pe baterie"**
+3. Timer 180 secunde expiră
+4. **📧 Email: "Pe baterie 3 min - SHUTDOWN"**
+5. Script de shutdown pornește:
+ - **📧 Email: "Shutdown cluster PORNIT"**
+ - 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ă
1. UPS raportează LOWBATT
-2. Shutdown **IMEDIAT** (fără timer)
-3. Același flux de shutdown orchestrat
-4. **Rezultat:** Shutdown rapid pentru protecție
+2. **📧 Email: "BATERIE CRITICĂ - SHUTDOWN IMEDIAT"**
+3. Shutdown **IMEDIAT** (fără timer)
+4. Același flux de shutdown orchestrat
+5. **Rezultat:** Shutdown rapid pentru protecție + UPS oprit
## Loguri și Troubleshooting
@@ -234,4 +250,4 @@ tail -20 /var/log/ups-events.log
## Contact și Suport
- Documentație NUT: https://networkupstools.org/
- Script creat: 2025-10-06
-- Ultima modificare: 2025-10-06
+- Ultima modificare: 2026-01-13 (adăugat notificări email + UPS shutdown)
diff --git a/proxmox/ups/scripts/ups-shutdown-cluster.sh b/proxmox/ups/scripts/ups-shutdown-cluster.sh
index 0564203..5672a18 100644
--- a/proxmox/ups/scripts/ups-shutdown-cluster.sh
+++ b/proxmox/ups/scripts/ups-shutdown-cluster.sh
@@ -1,44 +1,114 @@
#!/bin/bash
#
-# Script de shutdown orchestrat pentru cluster Proxmox când UPS este pe baterie critică
-# Autor: Generat automat
-# Data: 2025-10-06
-# Actualizat: 2025-10-06 - Adăugat suport LXC containers
+# Script de shutdown orchestrat pentru cluster Proxmox cand UPS este pe baterie critica
+# Trimite notificari email via PVE::Notify pentru fiecare pas
+#
+# Creat: 2025-10-06
+# Actualizat: 2026-01-13 - Adaugat notificari email si UPS shutdown
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() {
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 "UPS SHUTDOWN ORCHESTRATION STARTED"
-log_message "UPS Status: $(upsc nutdev1 ups.status 2>/dev/null || echo 'UNKNOWN')"
-log_message "Battery Charge: $(upsc nutdev1 battery.charge 2>/dev/null || echo 'UNKNOWN')%"
+log_message "$(get_ups_info)"
log_message "========================================"
-# Verifică dacă UPS este într-adevăr pe baterie critică
-UPS_STATUS=$(upsc nutdev1 ups.status 2>/dev/null)
+# Verifica daca UPS este intr-adevar pe baterie critica
+UPS_STATUS=$(upsc $UPS_NAME ups.status 2>/dev/null)
if [[ ! $UPS_STATUS =~ (OB|LB) ]]; then
log_message "WARNING: UPS status is $UPS_STATUS - not critical. Aborting shutdown."
exit 0
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..."
-# Oprește VM-uri pe toate nodurile (inclusiv local)
+# Opreste VM-uri pe toate nodurile (inclusiv local)
for node in ${NODES[@]} localhost; do
if [ "$node" == "localhost" ]; then
NODE_NAME="pvemini (local)"
else
NODE_NAME=$node
fi
-
+
log_message " - Oprire VM-uri pe $NODE_NAME..."
-
+
if [ "$node" == "localhost" ]; then
- # Local - oprește VM-urile direct
for vmid in $(qm list | awk 'NR>1 {print $1}'); do
vm_status=$(qm status $vmid | awk '{print $2}')
if [ "$vm_status" == "running" ]; then
@@ -47,7 +117,6 @@ for node in ${NODES[@]} localhost; do
fi
done
else
- # Remote - SSH către alt nod
ssh -o ConnectTimeout=5 root@$node "
for vmid in \$(qm list | awk 'NR>1 {print \$1}'); do
vm_status=\$(qm status \$vmid | awk '{print \$2}')
@@ -62,24 +131,22 @@ done
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
if [ "$node" == "localhost" ]; then
NODE_NAME="pvemini (local)"
else
NODE_NAME=$node
fi
-
+
log_message " - Oprire LXC pe $NODE_NAME..."
-
+
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
log_message " * Oprire container $ctid pe pvemini..."
pct shutdown $ctid --timeout 60 &
done
else
- # Remote - SSH către alt nod
ssh -o ConnectTimeout=5 root@$node "
pct list 2>/dev/null | awk 'NR>1 && \$2==\"running\" {print \$1}' | while read ctid; do
echo ' * Oprire container '\$ctid' pe $node...'
@@ -89,25 +156,61 @@ for node in ${NODES[@]} localhost; do
fi
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
-log_message "Step 4: Oprire noduri secundare (pve1, pveelite)..."
-for node in ${NODES[@]}; do
- log_message " - Shutdown nod $node..."
- ssh -o ConnectTimeout=5 root@$node "shutdown -h +1 'UPS on battery critical - shutting down'" 2>&1 | tee -a $LOGFILE &
+log_message "Step 4: Oprire noduri secundare..."
+
+# Opreste nodurile secundare si trimite notificare pentru fiecare
+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
-log_message "Step 5: Așteptare 30 secunde pentru shutdown noduri secundare..."
-sleep 30
+log_message "Step 5: Asteptare 60 secunde pentru shutdown noduri secundare..."
+sleep 60
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 "UPS SHUTDOWN ORCHESTRATION COMPLETED"
+log_message "$(get_ups_info)"
log_message "Local node will shutdown in 1 minute"
log_message "========================================"
-# Oprește nodul local (ultimul)
-shutdown -h +1 "UPS on battery critical - primary node shutting down"
+# Opreste nodul local (ultimul)
+shutdown -h +1 "UPS battery critical - primary node shutting down"
exit 0
diff --git a/proxmox/ups/scripts/upssched-cmd b/proxmox/ups/scripts/upssched-cmd
index 99d15f0..1099746 100644
--- a/proxmox/ups/scripts/upssched-cmd
+++ b/proxmox/ups/scripts/upssched-cmd
@@ -1,30 +1,297 @@
#!/bin/bash
#
# 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
+UPS_NAME="nutdev1"
+TEMPLATE_DIR="/etc/pve/notification-templates/default"
+HOSTNAME=$(hostname)
+FQDN=$(hostname -f 2>/dev/null || hostname)
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'
+
+
+
+
+
+
+
+
+
[UPS] {{ event_title }}
+
Hostname: {{ hostname }}
+ Date: {{ event_date }}
+ Event: {{ event_type }}
+
+ {{ event_description }}
+
+
UPS Status
+
+
+
Status
+
{{ ups_status }}
+
+
+
Battery
+
{{ battery_charge }}%
+
+
+
Input Voltage
+
{{ input_voltage }}V
+
+
+ {{#if action_taken}}
+
Action: {{ action_taken }}
+ {{/if}}
+ {{#if next_steps}}
+
Next Steps: {{ next_steps }}
+ {{/if}}
+
+
+
+
+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
+ 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)
- 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"
+
+ 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 &
;;
+
+ 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)
- 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"
+
+ 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 &
;;
+
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"
- # 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"
logger -t upssched-cmd "Unknown UPS event: $1"