#!/usr/bin/env python
#
# Provides: push-client-new
#
# simple push-client checker

import argparse
import commands
import json
import time
import os

def print_formated(status, text):
    if status == 'ok':
        print('PASSIVE-CHECK:push-client-new;0;{}'.format(text))
    elif status == 'warn':
        print('PASSIVE-CHECK:push-client-new;1;{}'.format(text))
    else:
        print('PASSIVE-CHECK:push-client-new;2;{}'.format(text))

def main(args):
    instance_dir = os.environ.get('BSCONFIG_IDIR')
    if not instance_dir:
        raise Exception("Environment variablee BSCONFIG_IDIR not defined")

    push_client_path = os.path.join(instance_dir, "wrap-pushclient-80")
    push_client_conf_real = os.path.join(instance_dir, "push-client_real.conf")
    push_client_conf = os.path.join(instance_dir, "push-client.conf")

    if not os.path.isfile(push_client_path) or not os.access(push_client_path, os.X_OK):
        raise Exception("No executable push client was found in {0}".format(push_client_path))
        
    config_path = None
    if os.path.isfile(push_client_conf_real):
        config_path = push_client_conf_real
    elif os.path.isfile(push_client_conf):
        config_path = push_client_conf
    else:
        raise Exception("No config file was found in {0}, {1}".format(push_client_conf_real, push_client_conf))

    code, out = commands.getstatusoutput("{0} -c {1} --status --json".format(push_client_path, config_path))
    if code != 0:
        print_formated("crit", "Incorrect status code {0}: {1}".format(code, out))
        exit()

    loaded_logs = json.loads(out)
    if not isinstance(loaded_logs, list):
        print_formated("crit", "Push client returned invalid json")
        exit()

    if len(loaded_logs) == 0:
        print_formated("crit", "No logs was loadeded")
        exit()

    check_failed = False
    errors = set()
    for log in loaded_logs:
        if "name" not in log:
            check_failed = True
            errors.add("No log name in returned json")
            continue

        name = log["name"]

        if "last send time" not in log:
            check_failed = True
            errors.add("No 'last send time' in returned json for {0} log".format(name))
            continue
        if "lag" not in log:
            check_failed = True
            errors.add("No 'lag' in returned json for {0} log".format(name))
            continue
        if "last commit time" not in log:
            check_failed = True
            errors.add("No 'last commit time' in returned json for {0} log".format(name))
            continue

        send_delay = time.time() - log["last send time"]
        commit_delay = time.time() - log["last commit time"]
        lag = log["lag"]

        # file is adding, data is sending - ok
        if send_delay < args.s and commit_delay < args.c and lag < args.l:
            continue
        # not write to file, data is sending - ok
        elif send_delay < args.s and commit_delay >= args.c and lag == 0:
            continue
        elif send_delay < args.s and commit_delay >= args.c and lag > 0:
            check_failed = True
            errors.add("Push client has connection, but could not send data")
        else:
            check_failed = True
            errors.add("Push client could not connect")

    if check_failed:
        print_formated("crit", "problems: {0}".format(", ".join(errors)))
    else:
        print_formated("ok", "ok")


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Push client checker for L7 balancer")
    parser.add_argument("-c", type=int, default=10*60, help="max push client commit delay")
    parser.add_argument("-s", type=int, default=10*60, help="max push client send delay")
    parser.add_argument("-l", type=int, default=2000000, help="max push client lag size")

    main(parser.parse_args())
