117 lines
4.1 KiB
Python
Executable File
117 lines
4.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
checkmk local check: Geoblocking
|
|
|
|
Wertet die Log-Datei von geoblock.py aus und meldet an checkmk, ob
|
|
der letzte Lauf (systemd-Timer: beim Boot + taeglich) erfolgreich und
|
|
aktuell war.
|
|
|
|
INSTALLATION:
|
|
1. LOG_FILE unten auf den Pfad anpassen, der in der geoblock.ini
|
|
unter [geoblock] log_file konfiguriert ist (Default passt zum
|
|
mitgelieferten install_geoblock.sh).
|
|
2. Datei ausfuehrbar machen und ins checkmk-Agent local-Verzeichnis legen:
|
|
cp geoblock_checkmk /usr/lib/check_mk_agent/local/
|
|
chmod 755 /usr/lib/check_mk_agent/local/geoblock_checkmk
|
|
(Pfad haengt von Distro/Checkmk-Setup ab - ueblich sind
|
|
/usr/lib/check_mk_agent/local/ oder bei OMD-Sites
|
|
~/local/lib/check_mk_agent/local/. Bei Bedarf: 'check_mk_agent' Pfad
|
|
des jeweiligen Hosts pruefen.)
|
|
3. Naechster Agent-Abruf zeigt den Service "Geoblock" in checkmk.
|
|
|
|
AUSGABE-LOGIK:
|
|
- Keine Log-Datei / keine RESULT-Zeile gefunden -> UNKNOWN (3)
|
|
- Letzter Lauf hatte status=ERROR -> CRIT (2)
|
|
- Letzter erfolgreicher Lauf zu alt (> CRIT_AGE) -> CRIT (2)
|
|
- Letzter erfolgreicher Lauf etwas alt (> WARN) -> WARN (1)
|
|
- Sonst -> OK (0)
|
|
"""
|
|
|
|
import datetime
|
|
import os
|
|
import re
|
|
import time
|
|
|
|
# --- Anpassen: muss zum log_file-Pfad aus der geoblock.ini passen ---
|
|
LOG_FILE = "/var/log/geoblock/geoblock.log"
|
|
|
|
# Timer laeuft taeglich -> grosszuegig bemessen, damit ein einzelner
|
|
# verpasster Lauf (Host kurz aus) nicht sofort CRIT ausloest.
|
|
WARN_AGE_SEC = 36 * 3600 # 36h
|
|
CRIT_AGE_SEC = 72 * 3600 # 72h
|
|
|
|
SERVICE_NAME = "Geoblock"
|
|
|
|
# Beispiel-Zeile in der Log-Datei (von geoblock.py log_result() geschrieben):
|
|
# 2026-07-21T10:00:00+02:00 [geoblock] RESULT ts=2026-07-21T10:00:00+02:00
|
|
# status=OK action=apply countries=4 entries=123456 msg="Geoblock aktualisiert (..)"
|
|
RESULT_RE = re.compile(
|
|
r'RESULT ts=(?P<ts>\S+) status=(?P<status>\S+) action=(?P<action>\S+)'
|
|
r'(?: countries=(?P<countries>\d+))?(?: entries=(?P<entries>\d+))? '
|
|
r'msg="(?P<msg>.*)"\s*$'
|
|
)
|
|
|
|
|
|
def emit(status, perfdata, text):
|
|
perf = perfdata if perfdata else "-"
|
|
print(f"{status} {SERVICE_NAME} {perf} {text}")
|
|
|
|
|
|
def main():
|
|
if not os.path.isfile(LOG_FILE):
|
|
emit(3, "-", f"Log-Datei nicht gefunden ({LOG_FILE}) - lief geoblock.py schon einmal mit --apply?")
|
|
return
|
|
|
|
last_match = None
|
|
try:
|
|
with open(LOG_FILE, "r", encoding="utf-8", errors="ignore") as f:
|
|
for line in f:
|
|
m = RESULT_RE.search(line.strip())
|
|
if m:
|
|
last_match = m # letzte Übereinstimmung gewinnt (Datei waechst append-only)
|
|
except OSError as e:
|
|
emit(3, "-", f"Log-Datei nicht lesbar: {e}")
|
|
return
|
|
|
|
if not last_match:
|
|
emit(3, "-", f"Keine RESULT-Zeile in {LOG_FILE} gefunden - lief geoblock.py schon mit --apply?")
|
|
return
|
|
|
|
ts_raw = last_match.group("ts")
|
|
action = last_match.group("action")
|
|
status_str = last_match.group("status")
|
|
countries = last_match.group("countries")
|
|
entries = last_match.group("entries")
|
|
msg = last_match.group("msg")
|
|
|
|
try:
|
|
last_dt = datetime.datetime.fromisoformat(ts_raw)
|
|
age = time.time() - last_dt.timestamp()
|
|
except ValueError:
|
|
emit(3, "-", f"Konnte Zeitstempel nicht parsen: {ts_raw}")
|
|
return
|
|
|
|
perf = f"age={int(age)}s;{WARN_AGE_SEC};{CRIT_AGE_SEC}"
|
|
if entries is not None:
|
|
perf += f"|entries={entries}"
|
|
|
|
if status_str != "OK":
|
|
emit(2, perf, f"Letzter Lauf ({action}) fehlgeschlagen: {msg}")
|
|
return
|
|
|
|
if age > CRIT_AGE_SEC:
|
|
emit(2, perf, f"Letzter erfolgreicher Lauf ist {int(age / 3600)}h alt "
|
|
f"(Schwelle {CRIT_AGE_SEC // 3600}h) - Timer laeuft nicht mehr? Letzte msg: {msg}")
|
|
return
|
|
if age > WARN_AGE_SEC:
|
|
emit(1, perf, f"Letzter erfolgreicher Lauf ist {int(age / 3600)}h alt "
|
|
f"(Schwelle {WARN_AGE_SEC // 3600}h) - Letzte msg: {msg}")
|
|
return
|
|
|
|
extra = f", {countries} Laender" if countries else ""
|
|
emit(0, perf, f"OK - letzter Lauf vor {int(age / 60)}min{extra}: {msg}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|