mirror of
https://github.com/ced4568/ceds-noc.git
synced 2026-08-12 21:04:02 +00:00
181 lines
4.4 KiB
Python
181 lines
4.4 KiB
Python
import json
|
|
import socket
|
|
import time
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
OUTPUT_FILE = Path(__file__).resolve().parent.parent / "data" / "noc-status.json"
|
|
|
|
SYSTEMS = [
|
|
{
|
|
"name": "Proxmox VE",
|
|
"type": "Virtualization Platform",
|
|
"host": "10.10.30.250",
|
|
"port": 8006,
|
|
"address": "10.10.30.250:8006",
|
|
"layer": "Core Infrastructure",
|
|
"label": "Hypervisor"
|
|
},
|
|
{
|
|
"name": "TrueNAS",
|
|
"type": "Storage Platform",
|
|
"host": "10.10.30.143",
|
|
"port": 80,
|
|
"address": "10.10.30.143",
|
|
"layer": "Storage",
|
|
"label": "NAS"
|
|
},
|
|
{
|
|
"name": "Nginx Proxy Manager",
|
|
"type": "Reverse Proxy",
|
|
"host": "10.10.30.210",
|
|
"port": 81,
|
|
"address": "10.10.30.210:81",
|
|
"layer": "Access Layer",
|
|
"label": "Proxy"
|
|
},
|
|
{
|
|
"name": "Dashy",
|
|
"type": "Service Dashboard",
|
|
"host": "10.10.30.61",
|
|
"port": 4000,
|
|
"address": "10.10.30.61:4000",
|
|
"layer": "Dashboard",
|
|
"label": "Portal"
|
|
},
|
|
{
|
|
"name": "Jellyfin",
|
|
"type": "Media Service",
|
|
"host": "10.10.30.143",
|
|
"port": 30013,
|
|
"address": "10.10.30.143:30013",
|
|
"layer": "Application Service",
|
|
"label": "App"
|
|
},
|
|
{
|
|
"name": "K3s API",
|
|
"type": "Kubernetes API",
|
|
"host": "10.10.30.72",
|
|
"port": 6443,
|
|
"address": "10.10.30.72:6443",
|
|
"layer": "Compute Cluster",
|
|
"label": "Cluster"
|
|
},
|
|
{
|
|
"name": "APRS Home iGate",
|
|
"type": "RF Edge Gateway",
|
|
"host": "10.10.30.129",
|
|
"port": 8001,
|
|
"address": "KJ5JCO-10 / Direwolf KISS 8001",
|
|
"layer": "Edge / RF",
|
|
"label": "iGate"
|
|
},
|
|
{
|
|
"name": "APRS-IS",
|
|
"type": "APRS Internet Service",
|
|
"host": "noam.aprs2.net",
|
|
"port": 14580,
|
|
"address": "noam.aprs2.net:14580",
|
|
"layer": "Edge / RF",
|
|
"label": "External"
|
|
}
|
|
]
|
|
|
|
|
|
def check_tcp(host, port, timeout=2):
|
|
start = time.perf_counter()
|
|
|
|
try:
|
|
with socket.create_connection((host, port), timeout=timeout):
|
|
latency_ms = round((time.perf_counter() - start) * 1000)
|
|
return True, latency_ms
|
|
except OSError:
|
|
return False, None
|
|
|
|
|
|
def severity_from_status(online, latency):
|
|
if not online:
|
|
return "Critical"
|
|
|
|
if latency is None:
|
|
return "Unknown"
|
|
|
|
if latency < 50:
|
|
return "Healthy"
|
|
|
|
if latency <= 150:
|
|
return "Degraded"
|
|
|
|
return "Critical"
|
|
|
|
|
|
def health_label(online_count, total):
|
|
if online_count == total:
|
|
return "All Systems Online"
|
|
|
|
if online_count >= max(1, total - 2):
|
|
return "Degraded"
|
|
|
|
return "Action Required"
|
|
|
|
|
|
def main():
|
|
checked_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
|
|
systems = []
|
|
online_count = 0
|
|
offline_count = 0
|
|
|
|
for system in SYSTEMS:
|
|
online, latency = check_tcp(system["host"], system["port"])
|
|
|
|
if online:
|
|
status = "Online"
|
|
online_count += 1
|
|
latency_value = f"{latency} ms"
|
|
else:
|
|
status = "Offline"
|
|
offline_count += 1
|
|
latency_value = "N/A"
|
|
|
|
systems.append({
|
|
"name": system["name"],
|
|
"type": system["type"],
|
|
"address": system["address"],
|
|
"status": status,
|
|
"severity": severity_from_status(online, latency),
|
|
"layer": system["layer"],
|
|
"label": system["label"],
|
|
"latency": latency_value,
|
|
"lastCheck": checked_at
|
|
})
|
|
|
|
total_systems = len(SYSTEMS)
|
|
|
|
data = {
|
|
"nocName": "Ced's NOC",
|
|
"status": health_label(online_count, total_systems),
|
|
"lastUpdated": checked_at,
|
|
"summary": {
|
|
"nodes": "12+",
|
|
"services": f"{online_count}/{total_systems}",
|
|
"online": str(online_count),
|
|
"offline": str(offline_count),
|
|
"vlans": "4",
|
|
"edgeSystems": "2"
|
|
},
|
|
"systems": systems
|
|
}
|
|
|
|
OUTPUT_FILE.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
with open(OUTPUT_FILE, "w", encoding="utf-8") as file:
|
|
json.dump(data, file, indent=2)
|
|
|
|
print(f"NOC status written to {OUTPUT_FILE}")
|
|
print(f"Online systems: {online_count}/{total_systems}")
|
|
print(f"Offline systems: {offline_count}/{total_systems}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |