#!/usr/bin/env python
import requests
import argparse
import csv
from sys import exit

OK=0
WARN=1
CRIT=2
UNKN=3

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-H', '--host', dest='host', default='localhost', help='Host to check against, default localhost')
    parser.add_argument('-f', '--haproxy-frontend', dest='hafrontend', default='', help='The haproxy frontend to check')
    parser.add_argument('-w', '--warn', dest='warn', default=0, type=int, help='Number of hosts down to warn at')
    parser.add_argument('-c', '--crit', dest='crit', default=0, type=int, help='Number of hosts down to crit at')
    parser.add_argument('-p', '--percent', dest='percent', default=0, action="store_true", help='Use warn/crit as percents')
    parser.add_argument('-P', '--port', dest='port', default=2015, type=int, help='Port to connect to haproxy management on')
    args = parser.parse_args()

    try:
        r = requests.get('http://%s:%s/stats;csv' % (args.host, args.port), auth=('oxygen', 'atom'))
    except requests.exceptions.ConnectionError:
        print "UNKN: Can't connect to haproxy"
        exit(UNKN)
    except Exception, e:
        print "UNKN: HTTP Error '%s'" % e
        exit(UNKN)

    if r.status_code != 200:
        print "UNKN: Status Code %s" % r.status_code
        exit(UNKN)

    csv_reader = csv.DictReader(r.text.splitlines())

    up = []
    down = []
    for line in csv_reader:
        if not line["# pxname"] == args.hafrontend:
            continue

        # Haproxy has collected stats for the Frontend and Backend. Skip these.
        if line["svname"].lower() == "frontend" or line["svname"].lower() == "backend":
            continue

        if line["status"] == "UP":
            up.append(line["svname"])
        else:
            down.append(line["svname"])

    total = len(down) + len(up)
    # If args.percent calculate how many hosts need to be down to alert
    if args.percent:
        warn_percent = args.warn
        crit_percent = args.crit

        warn = int((args.warn / 100.0) * total)
        crit = int((args.crit / 100.0) * total)
    else:
        warn = args.warn
        crit = args.crit

    formatted_down = map(lambda x: '"' + x + '"', down) # Wrap "" around each down
    formatted_report = "%s/%s hosts down - warn: %s, crit: %s - [%s]" % (len(down), total, warn, crit, ",".join(formatted_down))
    if len(down) > crit:
        print "CRIT: %s" % formatted_report
        exit(CRIT)
    elif len(down) > warn:
        print "WARN: %s" % formatted_report
        exit(WARN)
    elif total == 0:
        print "CRIT: no entries for '%s' found" % args.hafrontend
        exit(CRIT)
    else:
        print "OK: %s" % formatted_report
        exit(OK)

if __name__ == "__main__":
    main()
