#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-

# Example for output from agent
# ---------------------------------------------------------
#<<<mtr>>>
#www.google.com|1451237587|8|80.69.76.120|0.0%|10|39.2|7.0|0.3|39.2|14.2|80.249.209.100|0.0%|10|1.2|1.2|1.0|1.4|0.0|209.85.240.61|0.0%|10|1.4|1.6|1.2|2.4|0.0|209.85.248.247|0.0%|10|1.6|1.7|1.5|2.1|0.0|216.239.51.17|0.0%|10|4.8|5.0|4.7|5.3|0.0|216.239.49.36|0.0%|10|6.1|5.5|4.7|8.8|1.1|???|100.0|10|0.0|0.0|0.0|0.0|0.0|74.125.136.105|0.0%|10|4.7|5.0|4.7|5.4|0.0
# ---------------------------------------------------------

def inventory_mtr(checkname, info):
	for line in info:
		line = line[0]
		if line.startswith("**ERR*"):
		 	continue
		host = line.split('|')[0]
		yield host, {}

def parse_host(statusline):
	parts = statusline.split('|')
	ret = {'hops':{} }
	if not len(parts) > 0:
		return ret
	ret['hostname'] = parts.pop(0)
	ret['lasttime'] = parts.pop(0)
	ret['hopcount'] = int(float(parts.pop(0)))

	if ret['hopcount'] > 0:
		for hopnum in range(0, ret['hopcount']):
			ret['hops'][hopnum + 1] = {
			    'hopname': parts[0 + 8*hopnum],
			    'loss'   : parts[1 + 8*hopnum].replace("%","").rstrip(),
			    'snt'    : parts[2 + 8*hopnum],
			    'last'   : parts[3 + 8*hopnum],
			    'avg'    : parts[4 + 8*hopnum],
			    'best'   : parts[5 + 8*hopnum],
			    'wrst'   : parts[6 + 8*hopnum],
			    'stddev' : parts[7 + 8*hopnum],
			}
	return ret

def check_mtr(item, params, info):
	found = False
	for line in info:
		hostinfo = parse_host(line[0])
		if not hostinfo['hostname'] == item:
			continue
		found = True
		break

	if not found:
		return (3, "UNKNOWN - status for host %s not found in agent output" % item)

	loss_warn, loss_crit, avg_warn, avg_crit, stddev_warn, stddev_crit = None, None, None, None, None, None
	if "loss" in params:
		loss_warn, loss_crit = params["loss"]
	if "avg" in params:
		avg_warn, avg_crit = params["avg"]
	if "stddev" in params:
		stddev_warn, stddev_crit = params["stddev"]

	perfdata = []
	hops = hostinfo['hops']

	hc     = saveint(hostinfo['hopcount'])
	loss   = savefloat(hops[hc]['loss'])
	avg    = savefloat(hops[hc]['avg'])
	last   = savefloat(hops[hc]['last'])
	snt    = savefloat(hops[hc]['snt'])
	stddev = savefloat(hops[hc]['stddev'])
	worst  = savefloat(hops[hc]['wrst'])
	best   = savefloat(hops[hc]['best'])

	for hop in range(0, hc):
		if hop == hc - 1:
			perfdata.append( ( 'loss', loss, loss_warn, loss_crit, "", "" ) )
			perfdata.append( ( 'avg', avg, avg_warn, avg_crit, "", "" ) )
			perfdata.append( ( 'last', last, "", "", "", "" ) )
			perfdata.append( ( 'snt', snt, "", "", "", "" ) )
			perfdata.append( ( 'best', best, "", "", "", "" ) )
			perfdata.append( ( 'worst', worst, "", "", "", "" ) )
			perfdata.append( ( 'stddev', stddev, stddev_warn, stddev_crit, "", "" ) )
			perfdata.append( ( 'hopcount', hc, "", "", "", "" ) )
		else:
			hloss   = savefloat(hops[hop + 1]['loss'])
			havg    = savefloat(hops[hop + 1]['avg'])
			hlast   = savefloat(hops[hop + 1]['last'])
			hsnt    = savefloat(hops[hop + 1]['snt'])
			hstddev = savefloat(hops[hop + 1]['stddev'])
			hworst  = savefloat(hops[hop + 1]['wrst'])
			hbest   = savefloat(hops[hop + 1]['best'])
			perfdata.append( ( 'hop_%s_loss' % str(hop + 1), hloss, "", "", "", "" ) )
			perfdata.append( ( 'hop_%s_avg' % str(hop + 1), havg, "", "", "", "" ) )
			perfdata.append( ( 'hop_%s_last' % str(hop + 1), hlast, "", "", "", "" ) )
			perfdata.append( ( 'hop_%s_snt' % str(hop + 1), hsnt, "", "", "", "" ) )
			perfdata.append( ( 'hop_%s_best' % str(hop + 1), hbest, "", "", "", "" ) )
			perfdata.append( ( 'hop_%s_worst' % str(hop + 1), hworst, "", "", "", "" ) )
			perfdata.append( ( 'hop_%s_stddev' % str(hop + 1), hstddev, "", "", "", "" ) )

	if loss_crit != None and loss > loss_crit:
		return (2, "CRIT (loss level high! (current %d%% > %d%% crit level)" % (loss, loss_crit), perfdata)
	if avg_crit != None and avg > avg_crit:
		return (2, "CRIT (avg level high! (current %fms > %fms crit level)" % (avg, avg_crit), perfdata)
	if stddev_crit != None and stddev > stddev_crit:
		return (2, "CRIT (stddev level high! (current %fms > %fms crit level)" % (stddev, stddev_crit), perfdata)
	if loss_warn != None and loss > loss_warn:
		return (1, "WARN (loss level high! (current %d%% > %d%% warn level)" % (loss, loss_warn), perfdata)
	if avg_warn != None and avg > avg_warn:
		return (1, "WARN (avg level high! (current %fms > %fms warn level)" % (avg, avg_warn), perfdata)
	if stddev_warn != None and stddev > stddev_warn:
		return (1, "WARN (stddev level high! (current %fms > %fms warn level)" % (stddev, stddev_warn), perfdata)
	return (0, "OK - loss %s%% avg %sms stddev %sms" % (loss, avg, stddev), perfdata)

factory_settings["mtr_default_params"] = {
	"loss"     : (10 , 25),  # warn/crit for loss percentage
	"avg"      : (150, 250), # warn/crit for average roundtrip time
	"stddev"   : (150, 250), # warn/crit for standard deviation
}

check_info['mtr'] = {
	"check_function"          : check_mtr,
	"inventory_function"      : inventory_mtr,
	"service_description"     : "mtr to %s",
	"has_perfdata"            : True,
	"group"                   : "mtr",
	"default_levels_variable" : "mtr_default_params",
}
