Aggiunge backup no-GUI per scheduler
This commit is contained in:
38
README.md
38
README.md
@@ -46,6 +46,44 @@ python -m bakrest.tray_app
|
||||
|
||||
La tray app legge lo stato prodotto dal servizio e offre il comando `Backup e spegni`. Se il backup fallisce, lo spegnimento non viene eseguito.
|
||||
|
||||
## Backup senza GUI per Task Scheduler
|
||||
|
||||
Lo stesso entry point della tray puo' eseguire il backup senza mostrare icone o finestre:
|
||||
|
||||
```powershell
|
||||
python -m bakrest.tray_app --nogui
|
||||
```
|
||||
|
||||
Per testare senza spegnere il PC:
|
||||
|
||||
```powershell
|
||||
python -m bakrest.tray_app --nogui --no-shutdown
|
||||
```
|
||||
|
||||
In alternativa si puo' chiamare direttamente il modulo dedicato:
|
||||
|
||||
```powershell
|
||||
python -m bakrest.backup_nogui
|
||||
```
|
||||
|
||||
Questo percorso e' pensato per Task Scheduler, per esempio su evento di disconnessione o fine sessione. Se il server non e' raggiungibile o il backup fallisce, il comando termina con errore e non spegne il PC.
|
||||
|
||||
Azione Task Scheduler consigliata in sviluppo:
|
||||
|
||||
```text
|
||||
Programma: C:\Python314\python.exe
|
||||
Argomenti: -m bakrest.tray_app --nogui
|
||||
Avvia in: C:\devel\bak&rest
|
||||
```
|
||||
|
||||
Per una prova senza spegnimento:
|
||||
|
||||
```text
|
||||
Programma: C:\Python314\python.exe
|
||||
Argomenti: -m bakrest.tray_app --nogui --no-shutdown
|
||||
Avvia in: C:\devel\bak&rest
|
||||
```
|
||||
|
||||
## Avvio GUI configurazione
|
||||
|
||||
```powershell
|
||||
|
||||
@@ -58,6 +58,8 @@ La tray app deve:
|
||||
|
||||
La tray app e' il componente piu' adatto per eseguire `rsync` e richiedere lo spegnimento, perche' queste sono azioni esplicite dell'utente.
|
||||
|
||||
La stessa logica di backup deve essere disponibile anche senza interfaccia grafica, tramite opzione `--nogui`, per permettere l'esecuzione da Task Scheduler alla disconnessione o fine sessione. In modalita' no-GUI non devono comparire icone tray o finestre di messaggio: gli errori devono essere registrati nei log e il processo deve restituire un codice di uscita diverso da zero.
|
||||
|
||||
### GUI CustomTkinter
|
||||
|
||||
La GUI di configurazione deve permettere di:
|
||||
@@ -398,6 +400,7 @@ dist/
|
||||
BakRestWatchdog.exe
|
||||
BakRestTray.exe
|
||||
BakRestConfig.exe
|
||||
BakRestNoGui.exe
|
||||
```
|
||||
|
||||
## Decisioni aperte
|
||||
|
||||
52
src/bakrest/backup_nogui.py
Normal file
52
src/bakrest/backup_nogui.py
Normal file
@@ -0,0 +1,52 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
|
||||
from .backup import run_backup, shutdown_after_backup
|
||||
from .config import load_config
|
||||
from .logging_setup import close_logger, configure_logging
|
||||
|
||||
|
||||
def run_nogui_backup(shutdown: bool = True) -> int:
|
||||
config = load_config()
|
||||
logger = configure_logging(config.storage.logs_dir, "backup-nogui")
|
||||
logger.info("BakRest no-GUI backup started")
|
||||
try:
|
||||
result = run_backup(config, logger)
|
||||
if not result.success:
|
||||
logger.error("BakRest no-GUI backup failed: %s", result.message)
|
||||
return _exit_code_for_error(result.error_code)
|
||||
|
||||
logger.info("BakRest no-GUI backup completed: %s", result.message)
|
||||
if shutdown:
|
||||
shutdown_after_backup(config, logger)
|
||||
else:
|
||||
logger.info("Shutdown skipped by command line")
|
||||
return 0
|
||||
finally:
|
||||
close_logger(logger)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="Run Bak&Rest backup without GUI")
|
||||
parser.add_argument(
|
||||
"--no-shutdown",
|
||||
action="store_true",
|
||||
help="Run the backup but do not shut down the computer",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
return run_nogui_backup(shutdown=not args.no_shutdown)
|
||||
|
||||
|
||||
def _exit_code_for_error(error_code: str | None) -> int:
|
||||
if error_code == "server_unreachable":
|
||||
return 20
|
||||
if error_code == "rsync_start_failed":
|
||||
return 30
|
||||
if error_code == "rsync_failed":
|
||||
return 31
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
import threading
|
||||
@@ -11,6 +12,7 @@ from PIL import Image, ImageDraw
|
||||
import pystray
|
||||
|
||||
from .backup import run_backup, shutdown_after_backup
|
||||
from .backup_nogui import run_nogui_backup
|
||||
from .config import AppConfig, load_config
|
||||
from .logging_setup import configure_logging
|
||||
from .registry import ChangeRegistry
|
||||
@@ -101,7 +103,22 @@ def _show_error_message(title: str, message: str) -> None:
|
||||
root.destroy()
|
||||
|
||||
|
||||
def main() -> int:
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
parser = argparse.ArgumentParser(description="Bak&Rest tray app")
|
||||
parser.add_argument(
|
||||
"--nogui",
|
||||
action="store_true",
|
||||
help="Run backup and shutdown without tray icon",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-shutdown",
|
||||
action="store_true",
|
||||
help="With --nogui, run the backup but do not shut down the computer",
|
||||
)
|
||||
args = parser.parse_args(argv)
|
||||
if args.nogui:
|
||||
return run_nogui_backup(shutdown=not args.no_shutdown)
|
||||
|
||||
config = load_config()
|
||||
logger = configure_logging(config.storage.logs_dir, "tray")
|
||||
app = BakRestTrayApp(config, logger)
|
||||
|
||||
10
tests/test_backup_nogui.py
Normal file
10
tests/test_backup_nogui.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from bakrest.backup_nogui import _exit_code_for_error
|
||||
|
||||
|
||||
def test_nogui_exit_codes_are_specific() -> None:
|
||||
assert _exit_code_for_error("server_unreachable") == 20
|
||||
assert _exit_code_for_error("rsync_start_failed") == 30
|
||||
assert _exit_code_for_error("rsync_failed") == 31
|
||||
assert _exit_code_for_error(None) == 1
|
||||
Reference in New Issue
Block a user