#!/usr/bin/python3

'''
Check NCPA

Check types:
	cpu/percent aggregate=true
	load
	memory/virtual
	memory/swap
	system/time
	system/version
	user/count
	disk/logical/C:|
	disk/physical/PhysicalDrive0
	interface/Ethernet
	processes
'''

import sys
import os
import time
from urllib.request import urlopen
from urllib.parse import urlencode
from urllib.error import HTTPError
import json
import ssl

states = {0: "OK", 1: "WARNING", 2: "CRITICAL"}

def get_state(value, warn, crit):
    if value>crit:
        return 2
    elif value>warn:
        return 1
    return 0

def get_json(host, service, args={}):
    url = f"https://{host}:5693/api/{service}"
    if args:
        url += "?" + urlencode(args)
    if os.environ.get("DEBUG"):
        print(url)
    ctx = ssl.create_default_context()
    ctx.check_hostname = False
    ctx.verify_mode = ssl.CERT_NONE
    try:
        data = json.load(urlopen(url, context=ctx))
    except HTTPError as err:
        print(f"WARNING: {err}")
        sys.exit(1)  # warning
    if os.environ.get("DEBUG"):
        print(data)
    if "error" in data:
        err = data["error"]
        print(f"ERROR: {err['path']}: {err['message']} [{err['node']}]")
        sys.exit(2)  # error
    return data

def run_check(host, service, delta=False, aggregate=""):
    args = dict(check="true", units="")
    if delta:
        args["delta"] = "true"
    if aggregate:
        args["aggregate"] = aggregate
    data = get_json(hostname, service, args)
    print(data["stdout"].split("\n")[0])
    sys.exit(data["returncode"])

def run_perf(host, service):
    data = get_json(hostname, service, dict(units=""))
    drives = []
    data_text = []
    data_perf = []
    for drive, values in data.items():
        drives.append(drive)
        for method, value in values.items():
            #print(method, value)
            unit = value[1]
            if unit=="B" or unit=="packets" or unit=="errors":
                unit = "c"  # force to counter
            data_text.append(f"{method}: {value[0]}{value[1]}")
            data_perf.append(f"{method}={value[0]}{unit};;;")
    print(
        f"OK: {','.join(drives)}: "
        f"{', '.join(data_text)} |{' '.join(data_perf)}"
    )
    # always return OK
    sys.exit(0)

def run_load(host):
    data = get_json(hostname, "cpu", dict(delta="true", aggregate="avg"))
    system = data["cpu"]["system"]
    user = data["cpu"]["user"]
    print(
        f"OK: system={system[0][0]} {system[1]}, user={user[0][0]} {user[1]}"
        f"|system={system[0][0]} user={user[0][0]}"
    )

def run_disk_logical(host, service):
    datas = get_json(hostname, service, dict(units=""))
    for disk, data in datas.items():
        warn = 80
        crit = 90
        status = get_state(data["used_percent"][0], warn, crit)
        used = int(data["used"][0])
        total = int(data["total"][0])
        print(
            f"{states[status]}: {data['used_percent'][0]} % used"
            f"|used={used}B;{total*warn//100};{total*crit//100};0;{total}"
        )
        sys.exit(status)

def run_timedelta(host, service):
    data = get_json(hostname, service, dict(units=""))
    dt = time.time()-data["time"]
    if dt>120:
        print(f"CRITICAL: {dt}s|offset={dt}s")
        sys.exit(2)
    elif dt>80:
        print(f"WARNING: {dt}s|offset={dt}s")
        sys.exit(1)
    print(f"OK: Offset is {dt}s|offset={dt}s")
    sys.exit(0)

def run_sysver(host, service):
    data = get_json(hostname, service, dict(units=""))
    ver = data['version'].split('.')
    print(f"OK: Version was {data['version']}|build_version={ver[-1]}")
    sys.exit(0)

if __name__ == "__main__":
    hostname = sys.argv[1]
    if not sys.argv[2:]:
        from pprint import pprint
        pprint(get_json(hostname, ""))
        sys.exit()
    service = sys.argv[2]
    if sys.argv[3:]:
        args = dict(
            x.split("=", 1)
            for x in sys.argv[3].split(",")
        )
    else:
        args = {}
    #data = get_json(hostname, service, check=True)
    #print(data)
    if service.startswith("disk/physical"):
        run_perf(hostname, service)
    elif service == "load":
        run_load(hostname)
    elif service.startswith("system/time"):
        run_timedelta(hostname, service)
    elif service.startswith("system/version"):
        run_sysver(hostname, service)
    elif service.startswith("interface/"):
        # ethernet check has broken performance data in ncpa-3.0.1
        run_perf(hostname, service)
    else:
        if service.startswith("disk/logical/") and service[-1]==":":
            service += "|"
            run_disk_logical(hostname, service)
        run_check(hostname, service, args)
