#!/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