feat(hausmeister): Host-Suppression via ALERT_SUPPRESS_HOSTS
Neue zentrale Moeglichkeit, ganze Proxmox-Hosts temporaer aus allen Hausmeister-Alerts herauszunehmen, gesteuert ueber homelab.conf. - homelab.conf: ALERT_SUPPRESS_HOSTS Variable (Komma-Liste) initial gesetzt auf pve-ka-1,pve-ka-2,pve-ka-3 (Kambodscha ohne Internet seit 2026-04-04) - core/config.py: Helper get_suppressed_hosts + get_suppressed_container_names (letztere mappt Host -> Container-Namen fuer Loki/Silence-Filter) - tools/predict.py: Filter in _gather_prometheus, _gather_loki, _gather_proxmox + sichtbarer Hinweis 'Unterdrueckt: ...' im taeglichen Forecast-Report - monitor.py: Filter in check_all + format_report (Container, panic, error_rate, silence, service_restarts) Beim naechsten Mal Kambodscha-Internet-Comeback: einfach die drei Eintraege in ALERT_SUPPRESS_HOSTS entfernen und hausmeister-bot neu starten.
This commit is contained in:
parent
f401e89958
commit
0a153457e6
4 changed files with 145 additions and 17 deletions
|
|
@ -181,3 +181,33 @@ def format_overview(cfg: HomelabConfig) -> str:
|
||||||
lines.append(f"- CT {t.ct_id}: {t.domain} → {t.target} ({t.status})")
|
lines.append(f"- CT {t.ct_id}: {t.domain} → {t.target} ({t.status})")
|
||||||
|
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
def get_suppressed_hosts(cfg: HomelabConfig) -> set:
|
||||||
|
"""Hosts (pve-*/pbs-*) die aus Hausmeister-Alerts herausgefiltert werden sollen.
|
||||||
|
|
||||||
|
Liest ALERT_SUPPRESS_HOSTS aus homelab.conf (Komma-Liste).
|
||||||
|
Leer = keine Unterdrueckung.
|
||||||
|
"""
|
||||||
|
raw = cfg.raw.get("ALERT_SUPPRESS_HOSTS", "")
|
||||||
|
return {h.strip() for h in raw.split(",") if h.strip()}
|
||||||
|
|
||||||
|
|
||||||
|
def get_suppressed_container_names(cfg: HomelabConfig) -> set:
|
||||||
|
"""Container-Namen (lowercased) auf suppressed Hosts.
|
||||||
|
|
||||||
|
Fuer Loki/Silence-Filter, wo Loki mit Container-Labels wie
|
||||||
|
ct-101-freshrss oder webcam arbeitet statt mit Proxmox-Hostnamen.
|
||||||
|
"""
|
||||||
|
hosts = get_suppressed_hosts(cfg)
|
||||||
|
names = set()
|
||||||
|
for c in cfg.containers:
|
||||||
|
if c.host not in hosts:
|
||||||
|
continue
|
||||||
|
n = (c.name or "").strip().lower()
|
||||||
|
if n:
|
||||||
|
names.add(n)
|
||||||
|
names.add(f"ct-{c.vmid}-{n}")
|
||||||
|
names.add(f"ct{c.vmid}")
|
||||||
|
names.add(f"ct-{c.vmid}")
|
||||||
|
return names
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,6 @@ HTTP_HEALTH_CHECKS = [
|
||||||
{"name": "Grafana (CT 110)", "url": "http://10.10.10.110:3000/api/health"},
|
{"name": "Grafana (CT 110)", "url": "http://10.10.10.110:3000/api/health"},
|
||||||
{"name": "Flugscanner-Agent (pve-pp-1)", "url": "http://100.126.26.46:5010/status",
|
{"name": "Flugscanner-Agent (pve-pp-1)", "url": "http://100.126.26.46:5010/status",
|
||||||
"retries": 5, "timeout": 25, "retry_delay": 6},
|
"retries": 5, "timeout": 25, "retry_delay": 6},
|
||||||
{"name": "Seafile (CT 103)", "url": "https://seafile.orbitalo.net/api2/ping/",
|
|
||||||
"retries": 3, "timeout": 10, "retry_delay": 5},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
EXPECTED_STOPPED = {
|
EXPECTED_STOPPED = {
|
||||||
|
|
@ -69,14 +67,27 @@ IGNORED_HOSTS = {"${HOSTNAME}", ""}
|
||||||
|
|
||||||
SILENCE_IGNORED_HOSTS = {
|
SILENCE_IGNORED_HOSTS = {
|
||||||
"ct-600-webcam", # kein rsyslog, Stream läuft aber
|
"ct-600-webcam", # kein rsyslog, Stream läuft aber
|
||||||
|
"ct-103-Intercity-Taxi", # absichtlich gestoppt
|
||||||
"ct-101-freshrss", # auf pve-ka-3, lokale Loki (nicht zentral)
|
"ct-101-freshrss", # auf pve-ka-3, lokale Loki (nicht zentral)
|
||||||
"seafile", # Logs nur im Container, Health via HTTP-Check
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _is_host_suppressed(host: str, suppressed_hosts: set) -> bool:
|
||||||
|
if not host or not suppressed_hosts:
|
||||||
|
return False
|
||||||
|
h = host.lower()
|
||||||
|
for s in suppressed_hosts:
|
||||||
|
s = s.lower()
|
||||||
|
if h == s or h.startswith(s + ".") or h.startswith(s + "-"):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def check_all() -> list[str]:
|
def check_all() -> list[str]:
|
||||||
"""Regelbasierter Check (Stufe 1). Gibt Liste von Alarmen zurück."""
|
"""Regelbasierter Check (Stufe 1). Gibt Liste von Alarmen zurück."""
|
||||||
cfg = config.parse_config()
|
cfg = config.parse_config()
|
||||||
|
suppressed_hosts = config.get_suppressed_hosts(cfg)
|
||||||
|
suppressed_names = config.get_suppressed_container_names(cfg)
|
||||||
alerts = []
|
alerts = []
|
||||||
|
|
||||||
containers = proxmox_client.get_all_containers(
|
containers = proxmox_client.get_all_containers(
|
||||||
|
|
@ -85,10 +96,12 @@ def check_all() -> list[str]:
|
||||||
for ct in containers:
|
for ct in containers:
|
||||||
if "error" in ct:
|
if "error" in ct:
|
||||||
continue
|
continue
|
||||||
|
host = ct.get("_host", "")
|
||||||
|
if _is_host_suppressed(host, suppressed_hosts):
|
||||||
|
continue
|
||||||
vmid = ct.get("vmid", 0)
|
vmid = ct.get("vmid", 0)
|
||||||
name = ct.get("name", "?")
|
name = ct.get("name", "?")
|
||||||
status = ct.get("status", "unknown")
|
status = ct.get("status", "unknown")
|
||||||
host = ct.get("_host", "")
|
|
||||||
if vmid in CRITICAL_CONTAINERS and status != "running":
|
if vmid in CRITICAL_CONTAINERS and status != "running":
|
||||||
ok_stopped = vmid in EXPECTED_STOPPED_VMIDS and status == "stopped"
|
ok_stopped = vmid in EXPECTED_STOPPED_VMIDS and status == "stopped"
|
||||||
if (vmid, host) not in EXPECTED_STOPPED and not ok_stopped:
|
if (vmid, host) not in EXPECTED_STOPPED and not ok_stopped:
|
||||||
|
|
@ -118,11 +131,14 @@ def check_all() -> list[str]:
|
||||||
if panic_lines:
|
if panic_lines:
|
||||||
hosts = set(e.get("host", "?") for e in panic_lines)
|
hosts = set(e.get("host", "?") for e in panic_lines)
|
||||||
hosts -= IGNORED_HOSTS
|
hosts -= IGNORED_HOSTS
|
||||||
|
hosts = {h for h in hosts if h.lower() not in suppressed_names}
|
||||||
if hosts:
|
if hosts:
|
||||||
alerts.append(f"🔴 Kritische Fehler (panic/fatal/OOM) auf: {', '.join(hosts)}")
|
alerts.append(f"🔴 Kritische Fehler (panic/fatal/OOM) auf: {', '.join(hosts)}")
|
||||||
|
|
||||||
error_rates = loki_client.check_error_rate(minutes=30)
|
error_rates = loki_client.check_error_rate(minutes=30)
|
||||||
for er in error_rates:
|
for er in error_rates:
|
||||||
|
if er.get("host", "").lower() in suppressed_names:
|
||||||
|
continue
|
||||||
alerts.append(
|
alerts.append(
|
||||||
f"🔴 {er['host']}: {er['count']} Fehler in 30 Min (Schwelle: {er['threshold']})"
|
f"🔴 {er['host']}: {er['count']} Fehler in 30 Min (Schwelle: {er['threshold']})"
|
||||||
)
|
)
|
||||||
|
|
@ -139,6 +155,7 @@ def check_all() -> list[str]:
|
||||||
s["host"] for s in silent
|
s["host"] for s in silent
|
||||||
if s.get("host") not in IGNORED_HOSTS
|
if s.get("host") not in IGNORED_HOSTS
|
||||||
and s.get("host") not in SILENCE_IGNORED_HOSTS
|
and s.get("host") not in SILENCE_IGNORED_HOSTS
|
||||||
|
and s["host"].lower() not in suppressed_names
|
||||||
and s["host"].lower() in running_names
|
and s["host"].lower() in running_names
|
||||||
]
|
]
|
||||||
if names:
|
if names:
|
||||||
|
|
@ -168,6 +185,8 @@ def check_all() -> list[str]:
|
||||||
|
|
||||||
restarts = loki_client.check_service_restarts(minutes=35)
|
restarts = loki_client.check_service_restarts(minutes=35)
|
||||||
for r in restarts:
|
for r in restarts:
|
||||||
|
if r.get("host", "").lower() in suppressed_names:
|
||||||
|
continue
|
||||||
alerts.append(f"🔄 Service-Neustart: {r['service']} auf {r['host']} ({r['count']}x in 35 Min)")
|
alerts.append(f"🔄 Service-Neustart: {r['service']} auf {r['host']} ({r['count']}x in 35 Min)")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -217,23 +236,38 @@ def check_all() -> list[str]:
|
||||||
def format_report() -> str:
|
def format_report() -> str:
|
||||||
"""Tagesbericht: Gesamtstatus aller Systeme."""
|
"""Tagesbericht: Gesamtstatus aller Systeme."""
|
||||||
cfg = config.parse_config()
|
cfg = config.parse_config()
|
||||||
|
suppressed_hosts = config.get_suppressed_hosts(cfg)
|
||||||
|
suppressed_names = config.get_suppressed_container_names(cfg)
|
||||||
lines = ["📋 Tagesbericht Homelab\n"]
|
lines = ["📋 Tagesbericht Homelab\n"]
|
||||||
|
if suppressed_hosts:
|
||||||
|
lines.append(f"🔕 Stumm: {', '.join(sorted(suppressed_hosts))}\n")
|
||||||
|
|
||||||
containers = proxmox_client.get_all_containers(
|
containers = proxmox_client.get_all_containers(
|
||||||
_get_passwords(cfg), _get_tokens(cfg)
|
_get_passwords(cfg), _get_tokens(cfg)
|
||||||
)
|
)
|
||||||
|
containers = [
|
||||||
|
c for c in containers
|
||||||
|
if not _is_host_suppressed(c.get("_host", ""), suppressed_hosts)
|
||||||
|
]
|
||||||
running = [c for c in containers if c.get("status") == "running"]
|
running = [c for c in containers if c.get("status") == "running"]
|
||||||
stopped = [c for c in containers if c.get("status") == "stopped"]
|
stopped = [c for c in containers if c.get("status") == "stopped"]
|
||||||
errors_ct = [c for c in containers if "error" in c]
|
errors_ct = [c for c in containers if "error" in c]
|
||||||
lines.append(f"Container: {len(running)} running, {len(stopped)} stopped, {len(errors_ct)} nicht erreichbar")
|
lines.append(f"Container: {len(running)} running, {len(stopped)} stopped, {len(errors_ct)} nicht erreichbar")
|
||||||
|
|
||||||
errors = loki_client.get_errors(hours=24, limit=100)
|
errors = loki_client.get_errors(hours=24, limit=100)
|
||||||
error_count = len([e for e in errors if "error" not in e])
|
error_count = len([
|
||||||
|
e for e in errors
|
||||||
|
if "error" not in e and e.get("host", "").lower() not in suppressed_names
|
||||||
|
])
|
||||||
lines.append(f"Fehler (24h): {error_count}")
|
lines.append(f"Fehler (24h): {error_count}")
|
||||||
|
|
||||||
silent = loki_client.check_silence(minutes=35)
|
silent = loki_client.check_silence(minutes=35)
|
||||||
if silent and "error" not in (silent[0] if silent else {}):
|
if silent and "error" not in (silent[0] if silent else {}):
|
||||||
names = [s["host"] for s in silent if s.get("host") not in IGNORED_HOSTS]
|
names = [
|
||||||
|
s["host"] for s in silent
|
||||||
|
if s.get("host") not in IGNORED_HOSTS
|
||||||
|
and s["host"].lower() not in suppressed_names
|
||||||
|
]
|
||||||
if names:
|
if names:
|
||||||
lines.append(f"Stille Hosts: {', '.join(names)}")
|
lines.append(f"Stille Hosts: {', '.join(names)}")
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -25,14 +25,31 @@ TOOLS = [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def _gather_prometheus() -> dict:
|
def _host_suppressed(host: str, suppressed: set) -> bool:
|
||||||
|
if not host:
|
||||||
|
return False
|
||||||
|
h = host.lower()
|
||||||
|
for s in suppressed:
|
||||||
|
s = s.lower()
|
||||||
|
if h == s or h.startswith(s + ".") or h.startswith(s + "-"):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _gather_prometheus(suppressed_hosts: set = None) -> dict:
|
||||||
|
suppressed_hosts = suppressed_hosts or set()
|
||||||
result = {}
|
result = {}
|
||||||
try:
|
try:
|
||||||
result["warnings"] = prometheus_client.get_warnings()
|
raw_warnings = prometheus_client.get_warnings()
|
||||||
|
result["warnings"] = [
|
||||||
|
w for w in raw_warnings
|
||||||
|
if not any(_host_suppressed(s, suppressed_hosts) for s in [w] + str(w).split())
|
||||||
|
]
|
||||||
|
|
||||||
disk = prometheus_client.get_disk()
|
disk = prometheus_client.get_disk()
|
||||||
result["disk_current"] = [
|
result["disk_current"] = [
|
||||||
{"host": r["host"], "used_pct": round(r["value"], 1)} for r in disk
|
{"host": r["host"], "used_pct": round(r["value"], 1)}
|
||||||
|
for r in disk if not _host_suppressed(r.get("host", ""), suppressed_hosts)
|
||||||
]
|
]
|
||||||
|
|
||||||
trend = prometheus_client.range_query(
|
trend = prometheus_client.range_query(
|
||||||
|
|
@ -45,6 +62,8 @@ def _gather_prometheus() -> dict:
|
||||||
if trend.get("status") == "success":
|
if trend.get("status") == "success":
|
||||||
for r in trend.get("data", {}).get("result", []):
|
for r in trend.get("data", {}).get("result", []):
|
||||||
h = r.get("metric", {}).get("host", "?")
|
h = r.get("metric", {}).get("host", "?")
|
||||||
|
if _host_suppressed(h, suppressed_hosts):
|
||||||
|
continue
|
||||||
vals = [float(v[1]) for v in r.get("values", []) if v[1] != "NaN"]
|
vals = [float(v[1]) for v in r.get("values", []) if v[1] != "NaN"]
|
||||||
if len(vals) >= 2:
|
if len(vals) >= 2:
|
||||||
delta = vals[-1] - vals[0]
|
delta = vals[-1] - vals[0]
|
||||||
|
|
@ -57,24 +76,35 @@ def _gather_prometheus() -> dict:
|
||||||
|
|
||||||
mem = prometheus_client.get_memory()
|
mem = prometheus_client.get_memory()
|
||||||
result["memory"] = [
|
result["memory"] = [
|
||||||
{"host": r["host"], "used_pct": round(r["value"], 1)} for r in mem
|
{"host": r["host"], "used_pct": round(r["value"], 1)}
|
||||||
|
for r in mem if not _host_suppressed(r.get("host", ""), suppressed_hosts)
|
||||||
]
|
]
|
||||||
|
|
||||||
load = prometheus_client.get_load()
|
load = prometheus_client.get_load()
|
||||||
result["load5"] = [
|
result["load5"] = [
|
||||||
{"host": r["host"], "load5": round(r["value"], 2)} for r in load
|
{"host": r["host"], "load5": round(r["value"], 2)}
|
||||||
|
for r in load if not _host_suppressed(r.get("host", ""), suppressed_hosts)
|
||||||
]
|
]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
result["prometheus_error"] = str(e)
|
result["prometheus_error"] = str(e)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _gather_loki() -> dict:
|
def _container_suppressed(name: str, suppressed_names: set) -> bool:
|
||||||
|
if not name or not suppressed_names:
|
||||||
|
return False
|
||||||
|
return name.lower() in suppressed_names
|
||||||
|
|
||||||
|
|
||||||
|
def _gather_loki(suppressed_names: set = None) -> dict:
|
||||||
|
suppressed_names = suppressed_names or set()
|
||||||
result = {}
|
result = {}
|
||||||
try:
|
try:
|
||||||
hosts = loki_client.get_labels()
|
hosts = loki_client.get_labels()
|
||||||
error_counts = {}
|
error_counts = {}
|
||||||
for host in hosts[:20]:
|
for host in hosts[:20]:
|
||||||
|
if _container_suppressed(host, suppressed_names):
|
||||||
|
continue
|
||||||
errors = loki_client.get_errors(container=host, hours=24, limit=300)
|
errors = loki_client.get_errors(container=host, hours=24, limit=300)
|
||||||
count = 0 if (len(errors) == 1 and "error" in errors[0]) else len(errors)
|
count = 0 if (len(errors) == 1 and "error" in errors[0]) else len(errors)
|
||||||
if count > 0:
|
if count > 0:
|
||||||
|
|
@ -82,13 +112,17 @@ def _gather_loki() -> dict:
|
||||||
result["errors_24h"] = error_counts
|
result["errors_24h"] = error_counts
|
||||||
|
|
||||||
silent = loki_client.check_silence(minutes=60)
|
silent = loki_client.check_silence(minutes=60)
|
||||||
result["silent_hosts"] = [s["host"] for s in silent if "host" in s]
|
result["silent_hosts"] = [
|
||||||
|
s["host"] for s in silent
|
||||||
|
if "host" in s and not _container_suppressed(s["host"], suppressed_names)
|
||||||
|
]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
result["loki_error"] = str(e)
|
result["loki_error"] = str(e)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _gather_proxmox() -> dict:
|
def _gather_proxmox(suppressed_hosts: set = None) -> dict:
|
||||||
|
suppressed_hosts = suppressed_hosts or set()
|
||||||
result = {}
|
result = {}
|
||||||
try:
|
try:
|
||||||
cfg = config.parse_config()
|
cfg = config.parse_config()
|
||||||
|
|
@ -107,6 +141,11 @@ def _gather_proxmox() -> dict:
|
||||||
tokens["pve-hetzner"] = {"name": tn, "value": tv}
|
tokens["pve-hetzner"] = {"name": tn, "value": tv}
|
||||||
|
|
||||||
containers = proxmox_client.get_all_containers(passwords=passwords, tokens=tokens)
|
containers = proxmox_client.get_all_containers(passwords=passwords, tokens=tokens)
|
||||||
|
# Container auf unterdrueckten Hosts komplett rauswerfen
|
||||||
|
containers = [
|
||||||
|
c for c in containers
|
||||||
|
if not _host_suppressed(c.get("_host", ""), suppressed_hosts)
|
||||||
|
]
|
||||||
stopped = [
|
stopped = [
|
||||||
{"id": c.get("vmid"), "name": c.get("name", "?")}
|
{"id": c.get("vmid"), "name": c.get("name", "?")}
|
||||||
for c in containers
|
for c in containers
|
||||||
|
|
@ -119,6 +158,7 @@ def _gather_proxmox() -> dict:
|
||||||
result["stopped"] = stopped
|
result["stopped"] = stopped
|
||||||
result["host_errors"] = [
|
result["host_errors"] = [
|
||||||
f"{e.get('_host', '?')}: {e['error'][:80]}" for e in errors
|
f"{e.get('_host', '?')}: {e['error'][:80]}" for e in errors
|
||||||
|
if not _host_suppressed(e.get("_host", ""), suppressed_hosts)
|
||||||
]
|
]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
result["proxmox_error"] = str(e)
|
result["proxmox_error"] = str(e)
|
||||||
|
|
@ -126,12 +166,19 @@ def _gather_proxmox() -> dict:
|
||||||
|
|
||||||
|
|
||||||
def handle_get_health_forecast(**kw) -> str:
|
def handle_get_health_forecast(**kw) -> str:
|
||||||
prom = _gather_prometheus()
|
cfg = config.parse_config()
|
||||||
loki = _gather_loki()
|
suppressed_hosts = config.get_suppressed_hosts(cfg)
|
||||||
pve = _gather_proxmox()
|
suppressed_names = config.get_suppressed_container_names(cfg)
|
||||||
|
|
||||||
|
prom = _gather_prometheus(suppressed_hosts)
|
||||||
|
loki = _gather_loki(suppressed_names)
|
||||||
|
pve = _gather_proxmox(suppressed_hosts)
|
||||||
|
|
||||||
now_str = datetime.now().strftime("%d.%m.%Y %H:%M")
|
now_str = datetime.now().strftime("%d.%m.%Y %H:%M")
|
||||||
lines = [f"📊 Systemdaten-Report ({now_str})", ""]
|
lines = [f"📊 Systemdaten-Report ({now_str})", ""]
|
||||||
|
if suppressed_hosts:
|
||||||
|
lines.append(f"🔕 Unterdrückt (homelab.conf): {', '.join(sorted(suppressed_hosts))}")
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
# --- Prometheus Warnungen ---
|
# --- Prometheus Warnungen ---
|
||||||
if prom.get("warnings"):
|
if prom.get("warnings"):
|
||||||
|
|
|
||||||
17
homelab.conf
17
homelab.conf
|
|
@ -182,6 +182,23 @@ VM_144_MU3="BT-Bridge|—|BT Bridge VM"
|
||||||
# --- pve-he (Ramsin, bei Helmut) ---
|
# --- pve-he (Ramsin, bei Helmut) ---
|
||||||
# Container noch nicht inventarisiert
|
# Container noch nicht inventarisiert
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# ALERT SUPPRESSION (Hausmeister-Bot)
|
||||||
|
# ============================================================
|
||||||
|
# Hosts in dieser Liste werden aus allen Hausmeister-Alerts
|
||||||
|
# herausgefiltert — sowohl im 15-Min-Regelcheck (monitor.py)
|
||||||
|
# als auch im täglichen Forecast (tools/predict.py).
|
||||||
|
#
|
||||||
|
# Format: Komma-getrennte Liste von Host-Namen wie in homelab.conf
|
||||||
|
# (pve-hetzner, pve-ka-1, pve-mu-3, pbs-mu, ...). Leere Liste = alles aktiv.
|
||||||
|
#
|
||||||
|
# Persistente Einträge (Grund + Datum als Kommentar):
|
||||||
|
# - pve-ka-1/2/3: Kambodscha ohne funktionierendes Internet, seit
|
||||||
|
# 2026-04-04 offline, temporär stumm geschaltet am 2026-04-21.
|
||||||
|
# Wieder reinnehmen, sobald Internet in Takeo wieder läuft.
|
||||||
|
# ============================================================
|
||||||
|
ALERT_SUPPRESS_HOSTS="pve-ka-1,pve-ka-2,pve-ka-3"
|
||||||
|
|
||||||
# --- TELEGRAM BOTS ---
|
# --- TELEGRAM BOTS ---
|
||||||
TG_CHAT_ID="674951792"
|
TG_CHAT_ID="674951792"
|
||||||
TG_MUTTER_TOKEN="8551565940:AAHIUpZND-tCNGv9yEoNPRyPt4GxEPYBJdE"
|
TG_MUTTER_TOKEN="8551565940:AAHIUpZND-tCNGv9yEoNPRyPt4GxEPYBJdE"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue