Update notification service

This commit is contained in:
MacRimi
2026-03-23 20:14:25 +01:00
parent ab34fb08c1
commit c7ef51a73c
2 changed files with 50 additions and 7 deletions

View File

@@ -31,7 +31,7 @@ except ImportError:
# To analyze: grep "\[PERF\]" /var/log/proxmenux-monitor.log | sort -t'=' -k2 -n # To analyze: grep "\[PERF\]" /var/log/proxmenux-monitor.log | sort -t'=' -k2 -n
# Set to False or remove this section after debugging # Set to False or remove this section after debugging
# ============================================================================ # ============================================================================
DEBUG_PERF = True DEBUG_PERF = False
def _perf_log(section: str, elapsed_ms: float): def _perf_log(section: str, elapsed_ms: float):
"""Log performance timing for a section. Only logs if DEBUG_PERF is True.""" """Log performance timing for a section. Only logs if DEBUG_PERF is True."""

View File

@@ -8,18 +8,32 @@ Monitors configured Proxmox storages and tracks unavailable storages
import json import json
import subprocess import subprocess
import socket import socket
import time
from typing import Dict, List, Any, Optional from typing import Dict, List, Any, Optional
class ProxmoxStorageMonitor: class ProxmoxStorageMonitor:
"""Monitor Proxmox storage configuration and status""" """Monitor Proxmox storage configuration and status"""
# Cache TTL: 177 seconds (~3 min) - offset to avoid sync with other processes
_CACHE_TTL = 177
def __init__(self): def __init__(self):
self.configured_storages: Dict[str, Dict[str, Any]] = {} self.configured_storages: Dict[str, Dict[str, Any]] = {}
self._node_name_cache = {'name': None, 'time': 0}
self._storage_status_cache = {'data': None, 'time': 0}
self._config_cache_time = 0 # Track when config was last loaded
self._load_configured_storages() self._load_configured_storages()
def _get_node_name(self) -> str: def _get_node_name(self) -> str:
"""Get current Proxmox node name""" """Get current Proxmox node name (cached)"""
current_time = time.time()
cache = self._node_name_cache
# Return cached result if fresh
if cache['name'] and (current_time - cache['time']) < self._CACHE_TTL:
return cache['name']
try: try:
result = subprocess.run( result = subprocess.run(
['pvesh', 'get', '/nodes', '--output-format', 'json'], ['pvesh', 'get', '/nodes', '--output-format', 'json'],
@@ -32,9 +46,14 @@ class ProxmoxStorageMonitor:
hostname = socket.gethostname() hostname = socket.gethostname()
for node in nodes: for node in nodes:
if node.get('node') == hostname: if node.get('node') == hostname:
cache['name'] = hostname
cache['time'] = current_time
return hostname return hostname
if nodes: if nodes:
return nodes[0].get('node', hostname) name = nodes[0].get('node', hostname)
cache['name'] = name
cache['time'] = current_time
return name
return socket.gethostname() return socket.gethostname()
except Exception: except Exception:
return socket.gethostname() return socket.gethostname()
@@ -84,7 +103,7 @@ class ProxmoxStorageMonitor:
def get_storage_status(self) -> Dict[str, List[Dict[str, Any]]]: def get_storage_status(self) -> Dict[str, List[Dict[str, Any]]]:
""" """
Get storage status, including unavailable storages Get storage status, including unavailable storages (cached)
Returns: Returns:
{ {
@@ -92,6 +111,13 @@ class ProxmoxStorageMonitor:
'unavailable': [...] 'unavailable': [...]
} }
""" """
current_time = time.time()
cache = self._storage_status_cache
# Return cached result if fresh
if cache['data'] and (current_time - cache['time']) < self._CACHE_TTL:
return cache['data']
try: try:
local_node = self._get_node_name() local_node = self._get_node_name()
@@ -176,10 +202,16 @@ class ProxmoxStorageMonitor:
'node': local_node 'node': local_node
}) })
return { result_data = {
'available': available_storages, 'available': available_storages,
'unavailable': unavailable_storages 'unavailable': unavailable_storages
} }
# Cache the result
cache['data'] = result_data
cache['time'] = current_time
return result_data
except Exception: except Exception:
return { return {
@@ -192,10 +224,21 @@ class ProxmoxStorageMonitor:
status = self.get_storage_status() status = self.get_storage_status()
return len(status['unavailable']) return len(status['unavailable'])
def reload_configuration(self) -> None: def reload_configuration(self, force: bool = False) -> None:
"""Reload storage configuration from Proxmox""" """Reload storage configuration from Proxmox (cached)
Args:
force: If True, bypass cache and force reload
"""
current_time = time.time()
# Skip reload if cache is still fresh (unless forced)
if not force and (current_time - self._config_cache_time) < self._CACHE_TTL:
return
self.configured_storages.clear() self.configured_storages.clear()
self._load_configured_storages() self._load_configured_storages()
self._config_cache_time = current_time
# Global instance # Global instance