Aggiunge notifier server per scheduler

This commit is contained in:
2026-07-01 12:56:27 +02:00
parent ad7265183c
commit 6232bb240c
7 changed files with 137 additions and 2 deletions

View File

@@ -46,6 +46,7 @@ class StorageConfig:
change_registry: Path
logs_dir: Path
status_file: Path
notifier_state_file: Path
@dataclass(frozen=True)
@@ -104,11 +105,11 @@ def save_config_data(data: dict[str, Any], path: Path | None = None) -> Path:
def migrate_config_data(data: dict[str, Any]) -> bool:
changed = _migrate_storage_config(data)
backup = data.get("backup")
if not isinstance(backup, dict):
return False
return changed
changed = False
engine = str(backup.get("engine", "robocopy")).lower()
if "engine" not in backup:
backup["engine"] = engine
@@ -138,6 +139,16 @@ def migrate_config_data(data: dict[str, Any]) -> bool:
return changed
def _migrate_storage_config(data: dict[str, Any]) -> bool:
storage = data.get("storage")
if not isinstance(storage, dict):
return False
if "notifier_state_file" in storage:
return False
storage["notifier_state_file"] = "%PROGRAMDATA%\\BakRest\\notifier-state.json"
return True
def parse_config(data: dict[str, Any], path: Path) -> AppConfig:
service = data.get("service", {})
tray = data.get("tray", {})
@@ -159,6 +170,9 @@ def parse_config(data: dict[str, Any], path: Path) -> AppConfig:
),
logs_dir=expand_path(storage.get("logs_dir", "%PROGRAMDATA%\\BakRest\\logs")),
status_file=expand_path(storage.get("status_file", "%PROGRAMDATA%\\BakRest\\status.json")),
notifier_state_file=expand_path(
storage.get("notifier_state_file", "%PROGRAMDATA%\\BakRest\\notifier-state.json")
),
)
return AppConfig(

View File

@@ -69,4 +69,5 @@ unchanged_checks_required = 2
change_registry = "%PROGRAMDATA%\\\\BakRest\\\\changes.sqlite"
logs_dir = "%PROGRAMDATA%\\\\BakRest\\\\logs"
status_file = "%PROGRAMDATA%\\\\BakRest\\\\status.json"
notifier_state_file = "%PROGRAMDATA%\\\\BakRest\\\\notifier-state.json"
"""

View File

@@ -0,0 +1,83 @@
from __future__ import annotations
import argparse
import json
import tkinter as tk
from pathlib import Path
from tkinter import messagebox
from .config import load_config
from .logging_setup import close_logger, configure_logging
from .registry import ChangeRegistry
from .server_check import ServerStatus, check_server, write_status
ALERT_MESSAGE = "Accendi il server di backup o verifica che sia connesso alla rete"
def run_server_notifier(always_alert: bool = False) -> int:
config = load_config()
logger = configure_logging(config.storage.logs_dir, "server-notifier")
try:
status = check_server(config.backup)
pending_count = ChangeRegistry(config.storage.change_registry).pending_count()
write_status(config.storage.status_file, status, pending_count)
if status.reachable:
logger.info("Backup server reachable")
_write_state(config.storage.notifier_state_file, "reachable")
return 0
logger.warning("Backup server unreachable: %s", status.message)
previous_state = _read_state(config.storage.notifier_state_file)
if always_alert or previous_state != "unreachable":
_show_error_message("Bak&Rest", ALERT_MESSAGE)
_write_state(config.storage.notifier_state_file, "unreachable")
return 20
finally:
close_logger(logger)
def should_alert(status: ServerStatus, previous_state: str | None, always_alert: bool = False) -> bool:
if status.reachable:
return False
return always_alert or previous_state != "unreachable"
def _read_state(path: Path) -> str | None:
try:
data = json.loads(path.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError):
return None
state = data.get("server_state")
return str(state) if state else None
def _write_state(path: Path, state: str) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps({"server_state": state}, indent=2), encoding="utf-8")
def _show_error_message(title: str, message: str) -> None:
root = tk.Tk()
root.withdraw()
root.attributes("-topmost", True)
try:
messagebox.showerror(title, message, parent=root)
finally:
root.destroy()
def main() -> int:
parser = argparse.ArgumentParser(description="Notify the user if the backup server is unreachable")
parser.add_argument(
"--always-alert",
action="store_true",
help="Show the warning even if it was already shown while the server was down",
)
args = parser.parse_args()
return run_server_notifier(always_alert=args.always_alert)
if __name__ == "__main__":
raise SystemExit(main())