#!/usr/bin/python # # check_ups_socomec # Check Socomec UPS (via NetVision network interface) health # Author: Angelo Conforti # Version: 0.2 # # Changelog: # 0.1 @ 07.10.01 - First realease # 0.2 @ 08.02.14 - Added support to UPS's Alarms # # Warning # - if Input Voltage is lower than --voltage # - if Load % is more than --load # # Critical # - if battery capacity il lower than --battery # import sys, threading, StringIO from optparse import OptionParser from pysnmp import asn1, v1, v2c from pysnmp import role import pysnmp # # Definizione del dizionario che contiene la corrispondenza Alert <-> Messaggio # snmpalerts_alarms = "" snmpalerts_root = '.1.3.6.1.4.1.4555.1.1.1.1.6.3' snmpalerts_leaf = { '1': 'AlarmBatteryBad', '2': 'AlarmOnBattery', '3': 'AlarmLowBattery', '4': 'AlarmDepletedBattery', '5': 'AlarmTempBad', '6': 'AlarmInputBad', '7': 'AlarmOutputBad', '8': 'AlarmOutputOverload', '9': 'AlarmOnBypass', '10': 'AlarmBypassBad', '11': 'AlarmOutputOffAsRequested', '12': 'AlarmUpsOffAsRequested', '13': 'AlarmChargerFailed', '14': 'AlarmUpsOutputOff', '15': 'AlarmUpsSystemOff', '16': 'AlarmFanFailure', '17': 'AlarmFuseFailure', '18': 'AlarmGeneralFault', '19': 'AlarmDiagnosticTestFailed', '20': 'AlarmCommunicationLost', '21': 'AlarmAwaitingPower', '22': 'AlarmShutdownPending', '23': 'AlarmShutdownImminent', '24': 'AlarmTestInProgress', '25': 'AlarmPowerSupplyFault', '26': 'AlarmAuxMainFail', '27': 'AlarmManualBypassClose', '28': 'AlarmShortCircuit', '29': 'AlarmBatteryChargerFailure', '30': 'AlarmInverterOverCurrent', '31': 'AlarmInverterDistorsion', '32': 'AlarmPrechargeVoltageFail', '33': 'AlarmBoostTooLow', '34': 'AlarmBoostTooHigh', '35': 'AlarmBatteryTooHigh', '36': 'AlarmImproperCondition', '37': 'AlarmOverloadTimeout', '38': 'AlarmControlSystemFailure', '39': 'AlarmDataCorrupted', '40': 'AlarmPllFault', '41': 'AlarmInputGeneralAlarm', '42': 'AlarmRectifierGeneralAlarm', '43': 'AlarmBoostGeneralAlarm', '44': 'AlarmInverterGeneralAlarm', '45': 'AlarmBatteryGeneralAlarm', '46': 'AlarmOutputOver', '47': 'AlarmOutputUnder', '48': 'AlarmBypassGeneralAlarm', '49': 'AlarmStopForOverload', '50': 'AlarmImminentStop', '51': 'AlarmModule1Alarm', '52': 'AlarmModule2Alarm', '53': 'AlarmModule3Alarm', '54': 'AlarmModule4Alarm', '55': 'AlarmModule5Alarm', '56': 'AlarmModule6Alarm', '57': 'AlarmExternalAlarm1', '58': 'AlarmExternalAlarm2', '59': 'AlarmExternalAlarm3', '60': 'AlarmExternalAlarm4', '61': 'AlarmEService', '62': 'AlarmRedundancyLost', '63': 'AlarmPeriodicServiceCheck', '64': 'AlarmAllTransferDisabled', '65': 'AlarmAutoTransferDisabled', '66': 'AlarmBatteryRoom', '67': 'AlarmManualBypass', '68': 'AlarmBatteryDischarged', '69': 'AlarmInsufficientResources', '70': 'AlarmOptionalBoards', '71': 'AlarmRectifierFault', '72': 'AlarmBoostFault', '73': 'AlarmInverterFault', '74': 'AlarmParallelModuleFault', '75': 'AlarmGenSetGeneral', '76': 'AlarmGenSetFault', '77': 'AlarmEmergencyStopActive', '78': 'AlarmBatteryCircuitOpen', '79': 'AlarmFansFailure', '80': 'AlarmPhaseRotationFault', '81': 'AlarmA62', '82': 'AlarmA63' } def snmpquery(host,qry): client = role.manager((host, 161)) req = eval('v1').GETREQUEST() rsp = eval('v1').GETRESPONSE() try: (answer, src) = client.send_and_receive(req.encode(community='public', encoded_oids=map(asn1.OBJECTID().encode, [qry]))) except role.NetworkError: print "KO: Unable to contact or resolve name of remote SensorProbe" sys.exit(NAGIOS_CRITICAL) # Decode SNMP response rsp.decode(answer) vals = map(lambda x: x[0](), map(asn1.decode, rsp['encoded_vals'])) return vals[0] NAGIOS_OK = 0 NAGIOS_WARNING = 1 NAGIOS_CRITICAL = 2 NAGIOS_UNKNOWN = 3 uso = "%prog -r host --battery 50 --voltage 200 --load 90" parser = OptionParser(uso) parser.add_option("-r", "--host", dest="host", help="host", default="") parser.add_option("-c", "--community", dest="community", help="community SNMP", default="public") parser.add_option("-b", "--battery", dest="battery", help="soglia di crit per valore di carica", default='50') parser.add_option("-l", "--load", dest="load", help="soglia di warn per valore di carico", default='90') parser.add_option("-v", "--voltage", dest="voltage", help="soglia di warn per valore di voltage", default='200') (options, args) = parser.parse_args() if not options.host: parser.error("option host is mandatory") sys.exit(NAGIOS_UNKNOWN) capacity = snmpquery(options.host,".1.3.6.1.4.1.4555.1.1.1.1.2.4.0"); load1 = snmpquery(options.host,".1.3.6.1.4.1.4555.1.1.1.1.4.4.1.4.1"); load2 = snmpquery(options.host,".1.3.6.1.4.1.4555.1.1.1.1.4.4.1.4.2"); load3 = snmpquery(options.host,".1.3.6.1.4.1.4555.1.1.1.1.4.4.1.4.3"); voltage1 = snmpquery(options.host,".1.3.6.1.4.1.4555.1.1.1.1.3.3.1.2.1") / 10; voltage2 = snmpquery(options.host,".1.3.6.1.4.1.4555.1.1.1.1.3.3.1.2.2") / 10; voltage3 = snmpquery(options.host,".1.3.6.1.4.1.4555.1.1.1.1.3.3.1.2.3") / 10; for k,v in snmpalerts_leaf.iteritems(): read = snmpquery(options.host,snmpalerts_root + "."+ k + ".0"); if read == 1: snmpalerts_alarms = snmpalerts_alarms + v + " " if snmpalerts_alarms == '': snmpalerts_alarms = 'None' ## Si potrebbe comprimere e di molto il programma, qui... values = "Battery %s - Load %s,%s,%s - Input Voltage %s,%s,%s - Alarms %s" % (capacity,load1,load2,load3,voltage1,voltage2,voltage3,snmpalerts_alarms) if capacity <= int(options.battery): print "CRIT: " + values sys.exit(NAGIOS_CRITICAL) if voltage1 <= int(options.voltage) or voltage2 <= int(options.voltage) or voltage3 <= int(options.voltage): print "WARN1: " + values sys.exit(NAGIOS_WARNING) if load1 >= int(options.load) or load2 >= int(options.load) or load3>= int(options.load): print "WARN2: " + values sys.exit(NAGIOS_WARNING) if snmpalerts_alarms != 'None': print "CRIT: " + values sys.exit(NAGIOS_CRITICAL) print "OK: " + values sys.exit(NAGIOS_OK)