#!/usr/bin/env python3 """ Webhook-Empfänger für Lexware-Dump-Benachrichtigungen vom Windows-Server. POST /restore?db=f1 → nur f1 wiederherstellen POST /restore → alle DBs prüfen und bei Bedarf wiederherstellen GET /health → Liveness-Check """ import http.server import subprocess import threading import urllib.parse import logging import sys import os PORT = 9055 RESTORE_SCRIPT = "/opt/lexware-dumps/restore-latest.sh" LOG_FILE = "/var/log/lexware-restore.log" VALID_DBS = {"f1", "f2", "lexkonto", "lexkk", "rk", "lxoffice", "lx", "lxcatalog"} logging.basicConfig( level=logging.INFO, format="%(asctime)s [webhook] %(message)s", datefmt="%Y-%m-%d %H:%M:%S", handlers=[ logging.FileHandler(LOG_FILE), logging.StreamHandler(sys.stdout), ], ) def run_restore(db: str | None): env = os.environ.copy() cmd = [RESTORE_SCRIPT] if db: env["RESTORE_DB"] = db logging.info(f"Starte Restore: db={db or 'alle'}") result = subprocess.run(cmd, env=env, capture_output=True, text=True) if result.stdout: for line in result.stdout.strip().splitlines(): logging.info(line) if result.returncode not in (0, 1): logging.error(f"Restore-Skript exit {result.returncode}") class WebhookHandler(http.server.BaseHTTPRequestHandler): def log_message(self, fmt, *args): logging.info(f"{self.address_string()} {fmt % args}") def do_POST(self): parsed = urllib.parse.urlparse(self.path) params = urllib.parse.parse_qs(parsed.query) if parsed.path != "/restore": self._respond(404, "Not found") return db = params.get("db", [None])[0] if db and db not in VALID_DBS: self._respond(400, f"Unbekannte Datenbank: {db}") return self._respond(200, f"OK: Restore gestartet (db={db or 'alle'})") # Restore asynchron starten damit der Webhook sofort antwortet threading.Thread(target=run_restore, args=(db,), daemon=True).start() def do_GET(self): if self.path == "/health": self._respond(200, "OK") else: self._respond(404, "Not found") def _respond(self, code: int, body: str): data = body.encode() self.send_response(code) self.send_header("Content-Type", "text/plain") self.send_header("Content-Length", str(len(data))) self.end_headers() self.wfile.write(data) if __name__ == "__main__": server = http.server.ThreadingHTTPServer(("0.0.0.0", PORT), WebhookHandler) logging.info(f"Webhook-Server läuft auf Port {PORT}") server.serve_forever()