#!/usr/bin/python
# ADSL connection speed, and line information from a Technicolor
# Telnet interface
#
# This plugin should be symlinked in as one of:
#     technicolor_adsl_speed
#     technicolor_adsl_noise

import os
import re
import sys
from telnetlib import Telnet

# Make sure we got the host to talk to
if not os.environ.has_key("host"):
	print "Environment host not given"
	print "This program must be run with the Technicolor hostname set"
	print ""
	print "Try adding to /etc/munin/munin-node.conf something like:"
	print ""
	print "[technicolor_adsl]"
	print "env.host 192.168.1.1"
	sys.exit(1)
host = os.environ["host"]

# Make sure we got login details
if not os.environ.has_key("user"):
	print "Environment user/pass not given"
	print "This program must be run with the DGN2000 username+password set"
	print ""
	print "Try adding to /etc/munin/munin-node.conf something like:"
	print ""
	print "[technicolor_adsl]"
	print "env.host 192.168.1.1"
	print "env.user admin"
	print "env.pass admin"
	sys.exit(1)
username = os.environ["user"]
password = os.environ.get("pass","")

def invalid_cmd(given):
	print "Error - must be called one of:"
	print "    technicolor_adsl_speed"
	print "    technicolor_adsl_noise"
	if given:
		print ""
		print "Option \"%s\" not recognised" % given
	sys.exit(1)

# How are they calling us?
cmd = re.search("technicolor_adsl_(\w+)", sys.argv[0])
if not cmd:
	invalid_cmd(None)
mode = cmd.groups(1)[0]

# Config mode
if len(sys.argv) > 1 and sys.argv[1] == "config":
	print "graph_title ADSL Connection %s for %s" % (mode, host)
	print "graph_category network"
	print "graph_args --base 1024 -l 0"
	print "graph_scale no" # for now, don't turn into k/m automatically
	if mode == "speed":
		print "graph_vlabel kbps"
		print "graph_info The upstream and downstream ADSL connection speeds"
		print "upstream.label Upstream speed"
		print "downstream.label Downstream speed"
	elif mode == "noise":
		print "graph_vlabel dB"
		print "graph_info The upstream and downstream ADSL connection attenuation and signal/noise ratio"
		print "upstream_snr.label Upstream SNR"
		print "upstream_attn.label Upstream Attenuation"
		print "upstream_power.label Upstream Output Power"
		print "downstream_snr.label Downstream SNR"
		print "downstream_attn.label Downstream Attenuation"
		print "downstream_power.label Downstream Output Power"
	else:
		invalid_cmd(mode)
else:
	if mode == "speed":
		data_re = re.compile("Bandwidth.*?\s+(\d+)\/(\d+)")
	elif mode == "noise":
		data_re = re.compile("Attenuation.*?\s+(\d+.\d)\s+(\d+.\d).*?Margins.*?\s+(\d+.\d)\s+(\d+.\d).*?Output power.*?\s+(\d+.\d)\s+(\d+.\d)", flags=re.S)
	else:
		invalid_cmd(mode)

	t = Telnet(host, 23)
	info = t.read_until("Username :", 5)
	t.write("%s\r\n" % username)
	info = t.read_until("assword :", 2)
	t.write("%s\r\n" % password)
	info = t.read_until("}=>", 2)

	if mode == "speed":
	    t.write("xdsl info\r\n")
	elif mode == "noise":
	    t.write("xdsl info expand=enabled\r\n")
	else:
		invalid_cmd(mode)

	info = t.read_until("}=>", 10)
	t.write("exit\r\n")
	t.read_all()

	data = data_re.search(info)

	if data:
		if mode == "speed":
			print "upstream.value %s" % data.group(1)
			print "downstream.value %s" % data.group(2)
		elif mode == "noise":
			print "downstream_snr.value %s" % data.group(1)
			print "upstream_snr.value %s" % data.group(2)
			print "downstream_attn.value %s" % data.group(3)
			print "upstream_attn.value %s" % data.group(4)
			print "downstream_power.value %s" % data.group(5)
			print "upstream_power.value %s" % data.group(6)
		else:
			invalid_cmd(mode)
	else:
		print "Error - Regular Expression didn't match! Found"
		print ""
		print info
		sys.exit(1)
