#!/usr/bin/python

import sys
import netsnmp

channels = 10
tiers = 8

class NagiosAPI(object):
    states = ('OK', 'WARNING', 'CRITICAL', 'UNKNOWN')
    OK = 0
    WARNING = 1
    CRITICAL = 2
    UNKNOWN = 3

    @staticmethod
    def toState(error):
	return NagiosAPI.states[error]

    @staticmethod
    def elevate(error):
	if error == NagiosAPI.OK:
	    error = NagiosAPI.WARNING
	elif error == NagiosAPI.WARNING:
	    error = NagiosAPI.CRITICAL
	return error


class S2aController(object):
    channelNames = ('', '', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'P', 'S')
    statusNames = ('', 'Healthy', 'Failure', 'Missing')
    HEALTHY = 1
    FAILURE = 2
    MISSING = 3

    def __init__(self, channels, tiers, params, debug = False):
	self.channels = channels
	self.tiers = tiers
	self.params = params
	self.debug = debug
	error = ''
	self.session = netsnmp.Session(DestHost = params['DestHost'],
				       Version = params['Version'],
				       Community = params['Community'],
				       Retries = params['Retries'],
				       Timeout = (params['Timeout'] * 100000))
	# should query to make sure S2A

    def toStatus(self, value):
        return self.statusNames[value]

    def getOid(self, oid):
	varList = netsnmp.VarList(netsnmp.Varbind(oid))
	result, = self.session.get(varList)
	if type(result) is type(None):
	    raise TypeError
	return int(result)

    def getFans(self):
	oid = '.1.3.6.1.4.1.6894.1.2.0'
	result = self.getOid(oid)
	if debug:
	    print 'found', result, 'fans'
	return result

    def getFanStatus(self, fanIndex):
	oid = '.1.3.6.1.4.1.6894.1.3.1.2.%d' % (fanIndex)
	result = self.getOid(oid)
	if debug:
	    print 'fan', fanIndex, self.toStatus(result)
	return result

    def getPowerSupplies(self):
	oid = '.1.3.6.1.4.1.6894.1.4.0'
	result = self.getOid(oid)
	if debug:
	    print 'found', result, 'power supplies'
	return result

    def getPowerSupplyStatus(self, supplyIndex):
	oid = '.1.3.6.1.4.1.6894.1.5.1.2.%d' % (supplyIndex)
	result = self.getOid(oid)
	if debug:
	    print 'power supply', supplyIndex, self.toStatus(result)
	return result

    def getDiskStatus(self, tier, channel):
        oid = '.1.3.6.1.4.1.6894.1.7.1.%d.%d' % (channel, tier)
	result = self.getOid(oid)
	if debug:
	    print 'disk', self.getDiskName(tier, channel), 'status', self.toStatus(result)
	return result

    def getDiskName(self, tier, channel):
	return '%d%s' % (tier, S2aController.channelNames[channel])

    def iterateDisks(self):
        for channel in range(2, (self.channels + 2)):
            for tier in range(1, (self.tiers + 1)):
		yield (tier, channel)


debug = False
version = 1
community = 'public'
destHost = None
timeout = 10
retries = 3


def usage():
    print "Usage: check_s2a.py -H <ip address or hostname> [-P snmp version]"
    print "       [-C community] [-t timeout] [-e retries]"
    print "       [--tiers number of tiers] [--channels number of channels]"
    sys.exit(NagiosAPI.UNKNOWN)

argv = sys.argv[1:]

while argv:
    if argv[0] == '-d':
	debug = True
	next

    if argv[0] == '-P':
	argv.pop(0)
	version = int(argv[0])
	next
    if argv[0] == '-C':
	argv.pop(0)
	if not argv:
	    usage()
	community = argv[0]
	next
    if argv[0] == '-H':
	argv.pop(0)
	if not argv:
	    usage()
	destHost = argv[0]
	next
    if argv[0] == '-t':
	argv.pop(0)
	if not argv:
	    usage()
	timeout = int(argv[0])
	next
    if argv[0] == '-e':
	argv.pop(0)
	if not argv:
	    usage()
	retries = int(argv[0])
	next

    if argv[0] == '--tiers':
	argv.pop(0)
	tiers = int(argv[0])
	next
    if argv[0] == '--channels':
	argv.pop(0)
	channels = int(argv[0])
	next

    argv.pop(0)


''' validate the input -- TBD '''
if not destHost:
    usage()

failures = []

controller = S2aController(channels, tiers,
			   {'DestHost' : destHost,
			    'Version' : version,
			    'Community' : community,
			    'Timeout' : timeout,
			    'Retries' : retries},
			   debug = debug)

try:
    ''' check fans '''

    fanStatus = NagiosAPI.OK
    fans = controller.getFans()
    for fan in range(1, fans + 1):
	status = controller.getFanStatus(fan)
	if status != S2aController.HEALTHY:
	    fanStatus = NagiosAPI.elevate(fanStatus)
	    failures.append('Fan %d %s' % (fan, controller.toStatus(status)))

    ''' check power supplies '''

    psStatus = NagiosAPI.OK
    supplies = controller.getPowerSupplies()
    for supply in range(1, supplies + 1):
	status = controller.getPowerSupplyStatus(supply)
	if status != S2aController.HEALTHY:
	    psStatus = NagiosAPI.elevate(psStatus)
	    failures.append('Power Supply %d %s' % (supply, controller.toStatus(status)))

    ''' check disks '''

    diskStatus = NagiosAPI.OK
    for tier, channel in controller.iterateDisks():
	status = controller.getDiskStatus(tier, channel)
	if status != S2aController.HEALTHY:
	    diskStatus = NagiosAPI.elevate(diskStatus)
	    failures.append('Disk %s %s' % (controller.getDiskName(tier, channel),
					    controller.toStatus(status)))

    exitStatus = max(fanStatus, psStatus, diskStatus)

except TypeError:
    exitStatus = NagiosAPI.UNKNOWN

print 'Controller', NagiosAPI.toState(exitStatus)
for failure in failures:
    print failure

sys.exit(exitStatus)
