Interface web Flask securisee pour surveiller CPU, RAM, disques et processus (JVM, Nginx, Amadea Web 8 x64). Alertes email SMTP configurables, seuils reglables, compilation PyInstaller en .exe, installation service Windows via NSSM. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
127 lines
3.4 KiB
Python
127 lines
3.4 KiB
Python
"""Gestion de la configuration persistante (JSON)."""
|
|
|
|
import json
|
|
import os
|
|
import secrets
|
|
from pathlib import Path
|
|
from werkzeug.security import generate_password_hash
|
|
|
|
DATA_DIR = Path(__file__).parent / "data"
|
|
CONFIG_FILE = DATA_DIR / "config.json"
|
|
ALERTS_FILE = DATA_DIR / "alerts.json"
|
|
MAX_ALERTS = 500
|
|
|
|
|
|
def get_default_config():
|
|
return {
|
|
"secret_key": secrets.token_hex(32),
|
|
"port": 5000,
|
|
"check_interval_minutes": 1,
|
|
"alert_cooldown_minutes": 30,
|
|
"thresholds": {
|
|
"cpu_percent": 90,
|
|
"ram_percent": 85,
|
|
"disk_percent": 90,
|
|
},
|
|
"processes": [
|
|
{
|
|
"name": "JVM",
|
|
"pattern": "java",
|
|
"memory_threshold_mb": 0,
|
|
"enabled": True,
|
|
"alert_on_down": True,
|
|
},
|
|
{
|
|
"name": "Nginx",
|
|
"pattern": "nginx",
|
|
"memory_threshold_mb": 0,
|
|
"enabled": False,
|
|
"alert_on_down": False,
|
|
},
|
|
{
|
|
"name": "Amadea Web 8 x64",
|
|
"pattern": "amadea",
|
|
"memory_threshold_mb": 0,
|
|
"enabled": True,
|
|
"alert_on_down": True,
|
|
},
|
|
],
|
|
"smtp": {
|
|
"server": "",
|
|
"port": 587,
|
|
"use_tls": True,
|
|
"username": "",
|
|
"password": "",
|
|
"from_email": "",
|
|
"to_emails": [],
|
|
},
|
|
"admin": {
|
|
"username": "admin",
|
|
"password_hash": generate_password_hash("admin"),
|
|
},
|
|
}
|
|
|
|
|
|
class ConfigManager:
|
|
def __init__(self):
|
|
DATA_DIR.mkdir(exist_ok=True)
|
|
self._config = self._load()
|
|
|
|
def _load(self):
|
|
if CONFIG_FILE.exists():
|
|
with open(CONFIG_FILE, "r", encoding="utf-8") as f:
|
|
saved = json.load(f)
|
|
# Fusionner avec les valeurs par defaut (nouvelles cles)
|
|
default = get_default_config()
|
|
for key, val in default.items():
|
|
if key not in saved:
|
|
saved[key] = val
|
|
return saved
|
|
else:
|
|
config = get_default_config()
|
|
self._save(config)
|
|
return config
|
|
|
|
def _save(self, config=None):
|
|
if config is None:
|
|
config = self._config
|
|
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
|
|
json.dump(config, f, indent=2, ensure_ascii=False)
|
|
|
|
def reload(self):
|
|
self._config = self._load()
|
|
|
|
def get(self, key, default=None):
|
|
return self._config.get(key, default)
|
|
|
|
def set(self, key, value):
|
|
self._config[key] = value
|
|
self._save()
|
|
|
|
def update(self, data: dict):
|
|
self._config.update(data)
|
|
self._save()
|
|
|
|
@property
|
|
def config(self):
|
|
return self._config
|
|
|
|
# --- Alertes persistees ---
|
|
|
|
def load_alerts(self):
|
|
if ALERTS_FILE.exists():
|
|
with open(ALERTS_FILE, "r", encoding="utf-8") as f:
|
|
return json.load(f)
|
|
return []
|
|
|
|
def save_alert(self, alert: dict):
|
|
alerts = self.load_alerts()
|
|
alerts.insert(0, alert)
|
|
alerts = alerts[:MAX_ALERTS]
|
|
with open(ALERTS_FILE, "w", encoding="utf-8") as f:
|
|
json.dump(alerts, f, indent=2, ensure_ascii=False)
|
|
|
|
def clear_alerts(self):
|
|
with open(ALERTS_FILE, "w", encoding="utf-8") as f:
|
|
json.dump([], f)
|