#!/usr/bin/python

""" Module to check UBNT-M radio links """
__version__ = "1.0"
__author__ = "Omni Flux"

import os
import sys
import traceback
import paramiko
import simplejson as json
from optparse import OptionGroup
from NagiosPlugin import NagiosPlugin

# Setup plugin
plugin = NagiosPlugin (version="1.0", usage="Usage: %prog -H <hostname> [-I <identity> | -P <password>] [options]", description="Nagios plugin for UBNT-M radios")

plugin.parser.get_option ("-w").help += "s (signal,signal chain0,signal chain1,noise,ccq,airmax quality,airmax capacity,tx rate,rx rate)"
plugin.parser.get_option ("-c").help += "s (signal,signal chain0,signal chain1,noise,ccq,airmax quality,airmax capacity,tx rate,rx rate)"

connGroup = OptionGroup (plugin.parser, "Connection options")
connGroup.add_option ("-H", "--hostname", help="hostname")
connGroup.add_option ("-p", "--port", type="int", default=22, help="port (default: 22)")
plugin.parser.add_option_group (connGroup)

authGroup = OptionGroup (plugin.parser, "Authentication options")
authGroup.add_option ("-U", "--username", default="ubnt", help="username (default: 'ubnt')")
authGroup.add_option ("-P", "--password", help="password")
authGroup.add_option ("-I", "--identity", help="identity file")
authGroup.add_option ("-K", "--known-hosts", help="known hosts file")
plugin.parser.add_option_group (authGroup)

try:
	plugin.begin()
	verbose = plugin.options.verbose

	# Validate arguments
	if (plugin.options.hostname is None):
		plugin.parser.error ("-H/--hostname is required")

	if (plugin.options.password is None and plugin.options.identity is None):
		plugin.parser.error ("Either -P/--password or -I/--identity option is required")

	if (plugin.options.password is not None and plugin.options.identity is not None):
		plugin.parser.error ("Only one of -P/--password and -I/--identity option may be specified")

	try:
		client = paramiko.SSHClient()

		# Load host keys
		if (verbose >= 2):
			print "Loading known host keys"
		try:
			client.load_system_host_keys ("/etc/ssh/ssh_known_hosts")
		except IOError:
			if (verbose):
				print "Unable to load '/etc/ssh/ssh_known_hosts'"
			pass
		client.load_system_host_keys()
		if (plugin.options.known_hosts is not None):
			client.load_host_keys (plugin.options.known_hosts)

		client.set_missing_host_key_policy (paramiko.AutoAddPolicy())

		# Connect to SSH server
		if (verbose >= 2):
			print "Attempting to connect to '" + plugin.options.hostname + ":" + str (plugin.options.port) + "' as '" + plugin.options.username + "'",
		if (plugin.options.identity is not None):
			if (verbose >= 2):
				print "with identity '" + plugin.options.identity + "'"
			client.connect (plugin.options.hostname, plugin.options.port, plugin.options.username, key_filename=plugin.options.identity)
		else:
			if (verbose >= 2):
				print "with specified password"
			client.connect (plugin.options.hostname, plugin.options.port, plugin.options.username, plugin.options.password)

		# Execute command and capture output
		if (verbose >= 2):
			print "Collecting data"
		(stdin, stdout, stderr) = client.exec_command ("/usr/www/status.cgi")

		# Parse data
		if (verbose >= 2):
			print "Parsing data"
		stdout.readline()
		data = json.load (stdout)

		# Disconnect
		if (verbose >= 2):
			print "Closing connection"

	finally:
		client.close()

	# Collect performance data
	plugin.addPerformanceData ('signal', str (data['wireless']['signal']), 0, min='-100', max='0')
	plugin.addPerformanceData ('signalchain0', str ((96 - data['wireless']['chainrssi'][0]) * -1), 1, min='-100', max='0')
	plugin.addPerformanceData ('signalchain1', str ((96 - data['wireless']['chainrssi'][1]) * -1), 2, min='-100', max='0')
	plugin.addPerformanceData ('noise', str (data['wireless']['noisef']), 3, min='-100', max='0')
	plugin.addPerformanceData ('ccq', str (data['wireless']['ccq'] / 10), 4, UOM='%')
	plugin.addPerformanceData ('airmaxquality', str (data['wireless']['polling']['quality']), 5, UOM='%')
	plugin.addPerformanceData ('airmaxcapacity', str (data['wireless']['polling']['capacity']), 6, UOM='%')
	plugin.addPerformanceData ('txrate', data['wireless']['txrate'], 7, min='0', max='270')
	plugin.addPerformanceData ('rxrate', data['wireless']['rxrate'], 8, min='0', max='270')

	# Check thresholds
	if (plugin.checkThreshold (data['wireless']['signal'], 0) != plugin.returnValues['OK']):
		plugin.returnString += " signal"
	if (plugin.checkThreshold ((96 - data['wireless']['chainrssi'][0]) * -1, 1) != plugin.returnValues['OK']):
		plugin.returnString += " signalchain0"
	if (plugin.checkThreshold ((96 - data['wireless']['chainrssi'][1]) * -1, 2) != plugin.returnValues['OK']):
		plugin.returnString += " signalchain1"
	if (plugin.checkThreshold (data['wireless']['noisef'], 3) != plugin.returnValues['OK']):
		plugin.returnString += " noise"
	if (plugin.checkThreshold (data['wireless']['ccq'] / 10, 4) != plugin.returnValues['OK']):
		plugin.returnString += " ccq"
	if (plugin.checkThreshold (data['wireless']['polling']['quality'], 5) != plugin.returnValues['OK']):
		plugin.returnString += " airmaxquality"
	if (plugin.checkThreshold (data['wireless']['polling']['capacity'], 6) != plugin.returnValues['OK']):
		plugin.returnString += " airmaxcapacity"
	if (plugin.checkThreshold (data['wireless']['txrate'], 7) != plugin.returnValues['OK']):
		plugin.returnString += " txrate"
	if (plugin.checkThreshold (data['wireless']['rxrate'], 8) != plugin.returnValues['OK']):
		plugin.returnString += " rxrate"

	# Output result
	plugin.finish()

except Exception, e:
	if (verbose >= 2):
		traceback.print_exc(e)
	plugin.returnValue = plugin.returnValues['UNKNOWN']
	plugin.returnString = e.message

	# Output result
	plugin.finish()
