Files
SystemsMonitor/server/remote-health-json-legacy
2026-10-22 09:27:17 +01:00

312 lines
6.4 KiB
Python
Executable File

#!/usr/bin/env python
import os
import sys
import time
import socket
import commands
def command(args):
try:
quoted = []
for arg in args:
value = str(arg)
quoted.append("'" + value.replace("'", "'\\''") + "'")
cmd = " ".join(quoted)
return commands.getoutput(cmd).strip()
except:
return ""
def escape(value):
value = str(value)
return value.replace("\\", "\\\\").replace('"', '\\"').replace("\n", "\\n").replace("\r", "\\r")
def string(value):
return '"' + escape(value) + '"'
def status(name, state, detail):
return '{"name":%s,"state":%s,"detail":%s}' % (
string(name), string(state), string(detail)
)
def check(section, name, state, detail):
return '{"section":%s,"name":%s,"status":%s,"detail":%s}' % (
string(section), string(name), string(state), string(detail)
)
def group(name, state):
return '{"name":%s,"status":%s,"missing":[]}' % (
string(name), string(state)
)
def read_file(path):
try:
f = open(path)
data = f.read()
f.close()
return data
except:
return ""
def process_running(name):
output = command(["ps", "ax"])
return name in output
hostname = socket.gethostname()
# CPU
try:
load = float(read_file("/proc/loadavg").split()[0])
except:
load = 0.0
try:
cpu_count = len([
x for x in read_file("/proc/cpuinfo").splitlines()
if x.startswith("processor")
])
if cpu_count < 1:
cpu_count = 1
except:
cpu_count = 1
cpu_state = "ok"
if load > cpu_count * 2:
cpu_state = "fail"
elif load > cpu_count:
cpu_state = "warn"
# Memory
mem = {}
for line in read_file("/proc/meminfo").splitlines():
parts = line.replace(":", "").split()
if len(parts) >= 2:
try:
mem[parts[0]] = int(parts[1])
except:
pass
total = mem.get("MemTotal", 1)
free = (
mem.get("MemFree", 0) +
mem.get("Buffers", 0) +
mem.get("Cached", 0)
)
memory_percent = int(100 * (total - free) / total)
memory_state = "ok"
if memory_percent >= 95:
memory_state = "fail"
elif memory_percent >= 85:
memory_state = "warn"
# Disk
disk_percent = 0
disk_state = "ok"
try:
st = os.statvfs("/")
disk_percent = int(
100 * (st.f_blocks - st.f_bavail) / st.f_blocks
)
except:
pass
if disk_percent >= 95:
disk_state = "fail"
elif disk_percent >= 85:
disk_state = "warn"
# Notes data partition
notes_disk_state = "ok"
notes_disk_percent = 0
notes_disk_detail = "Not checked"
try:
mounts = open("/proc/mounts").read()
mounted = 0
for line in mounts.splitlines():
parts = line.split()
if len(parts) >= 2 and parts[1] == "/local/notesdata":
mounted = 1
break
if not mounted:
notes_disk_state = "fail"
notes_disk_detail = "/local/notesdata is not mounted"
else:
st = os.statvfs("/local/notesdata")
if st.f_blocks > 0:
notes_disk_percent = int(
100 * (st.f_blocks - st.f_bavail) / st.f_blocks
)
notes_disk_detail = "%d%% used" % notes_disk_percent
if notes_disk_percent >= 95:
notes_disk_state = "fail"
elif notes_disk_percent >= 85:
notes_disk_state = "warn"
else:
notes_disk_state = "fail"
notes_disk_detail = "Filesystem size unavailable"
except:
notes_disk_state = "fail"
notes_disk_detail = "Cannot read Notes data filesystem"
# Uptime
try:
uptime = int(float(read_file("/proc/uptime").split()[0]))
except:
uptime = 0
checks = [
check(
"System",
"CPU load",
cpu_state,
"1m load %.2f; %d CPUs" % (load, cpu_count)
),
check(
"System",
"Memory",
memory_state,
"%d%% used" % memory_percent
),
check(
"Storage",
"Disk /",
disk_state,
"%d%% used" % disk_percent
),
check(
"Storage",
"Notes data disk",
notes_disk_state,
notes_disk_detail
)
]
# Legacy SysV services
services = []
service_names = [
("ssh", "sshd"),
("apache2", "apache2"),
("nginx", "nginx"),
("mysql", "mysqld"),
("postgresql", "postgres"),
("redis-server", "redis-server"),
("domino", "server")
]
for service_name, process_name in service_names:
init_script = "/etc/init.d/" + service_name
if not os.path.exists(init_script):
services.append(
status(service_name, "not_installed", "SysV service not found")
)
continue
running = process_running(process_name)
if running:
service_state = "running"
else:
service_state = "stopped"
services.append(
status(
service_name,
service_state,
"SysV process check"
)
)
# Domino is a required service on Europa.
domino_state = "ok"
domino_detail = "Domino process running"
if not process_running("server"):
domino_state = "fail"
domino_detail = "Domino server process not running"
checks.append(
check(
"Services",
"Domino",
domino_state,
domino_detail
)
)
states = [
cpu_state,
memory_state,
disk_state,
notes_disk_state,
domino_state
]
overall = "ok"
if "fail" in states:
overall = "fail"
elif "warn" in states:
overall = "warn"
ok_count = states.count("ok")
warn_count = states.count("warn")
fail_count = states.count("fail")
if cpu_state == "fail" or memory_state == "fail":
system_state = "fail"
elif cpu_state == "warn" or memory_state == "warn":
system_state = "warn"
else:
system_state = "ok"
if disk_state == "fail" or notes_disk_state == "fail":
storage_state = "fail"
elif disk_state == "warn" or notes_disk_state == "warn":
storage_state = "warn"
else:
storage_state = "ok"
groups = [
group("System", system_state),
group("Storage", storage_state),
group("Services", domino_state)
]
output = """{
"schema":1,
"host":%s,
"generatedAt":%s,
"overall":%s,
"counts":{"ok":%d,"warn":%d,"fail":%d},
"groups":[%s],
"checks":[%s],
"diagnostics":null,
"services":[%s],
"uptimeSeconds":%d
}""" % (
string(hostname),
string(time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())),
string(overall),
ok_count,
warn_count,
fail_count,
",".join(groups),
",".join(checks),
",".join(services),
uptime
)
print output