Add linux/webhook.py
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user