#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# |             ____ _               _        __  __ _  __           |
# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
# |                                                                  |
# | Copyright Mathias Kettner 2013             mk@mathias-kettner.de |
# +------------------------------------------------------------------+
#
# This file is part of Check_MK.
# The official homepage is at http://mathias-kettner.de/check_mk.
#
# check_mk is free software;  you can redistribute it and/or modify it
# under the  terms of the  GNU General Public License  as published by
# the Free Software Foundation in version 2.  check_mk is  distributed
# in the hope that it will be useful, but WITHOUT ANY WARRANTY;  with-
# out even the implied warranty of  MERCHANTABILITY  or  FITNESS FOR A
# PARTICULAR PURPOSE. See the  GNU General Public License for more de-
# ails.  You should have  received  a copy of the  GNU  General Public
# License along with GNU Make; see the file  COPYING.  If  not,  write
# to the Free Software Foundation, Inc., 51 Franklin St,  Fifth Floor,
# Boston, MA 02110-1301 USA.

# We use the following OIDs:
# PowerNet-MIB::upsBasicBatteryStatus.0    .1.3.6.1.4.1.318.1.1.1.2.1.1.0
# PowerNet-MIB::upsBasicOutputStatus.0     .1.3.6.1.4.1.318.1.1.1.4.1.1.0
# PowerNet-MIB::upsAdvBatteryCapacity.0    .1.3.6.1.4.1.318.1.1.1.2.2.1.0
# PowerNet-MIB::upsAdvBatteryTemperature.0 .1.3.6.1.4.1.318.1.1.1.2.2.2.0
# PowerNet-MIB::upsAdvBatteryCurrent.0     .1.3.6.1.4.1.318.1.1.1.2.2.9.0
# PowerNet-MIB::upsAdvOutputVoltage.0      .1.3.6.1.4.1.318.1.1.1.4.2.1.0
# PowerNet-MIB::upsAdvOutputCurrent.0      .1.3.6.1.4.1.318.1.1.1.4.2.4.0

# upsBasicBatteryStatus: unknown(1), batteryNormal(2), batteryLow(3)
# upsBasicOutputStatus: unknown(1),  onLine(2), onBattery(3), onSmartBoost(4),
#   timedSleeping(5), softwareBypass(6), off(7), rebooting(8), switchedBypass(9),
#   hardwareFailureBypass(10), sleepingUntilPowerReturn(11), onSmartTrim(12)

apc_default_levels = ( 95, 40, 1, 220 )

def check_apc(item, params, info):
    BasicBatteryStatus, BasicOutputStatus, AdvBatteryCapacity, \
    AdvBatteryTemperature, AdvBatteryCurrent, AdvOutputVoltage, \
    AdvOutputCurrent = [ saveint(x) for x in info[0][:7] ]
    RunTimeRemaining = int(info[0][7]) / 100

    crit_capacity, crit_batt_temp, crit_batt_curr, crit_voltage = params

    single_states = []

    # 1. Check battery status
    status_text = { 1:"unknown", 2:"normal", 3:"low" }
    infotxt = "Battery status %s" % (status_text.get(BasicBatteryStatus))
    if BasicBatteryStatus != 2:
        state = 2
        infotxt += "(!!)"
    else:
        state = 0
    single_states.append( (state, infotxt, None) )

    # 2. Check basic output status
    status_text = { 1:"unknown", 2:"online", 3:"on battery", 4:"on smart boost", 5:"timed sleeping",
                    6:"software bypass", 7:"off", 8:"rebooting", 9:"switched bypass",
                   10:"hardware failure bypass", 11:"sleeping until power return",
                   12:"on smart trim" }
    infotxt = "output status %s" % (status_text.get(BasicOutputStatus))
    if BasicOutputStatus not in [2, 4, 12]:
        state = 2
        infotxt += "(!!)"
    else:
        state = 0
    single_states.append( (state, infotxt, None) )

    # 3. Check battery capacity
    infotxt = "capacity %d%%" % AdvBatteryCapacity
    if AdvBatteryCapacity <= crit_capacity:
        state = 2
        infotxt += "(!!)"
    else:
        state = 0
    single_states.append( (state, infotxt, ("capacity", AdvBatteryCapacity, "", crit_capacity, 0, 100)) )

    # 4. Check battery temperature
    infotxt = "bat. temp. %dC" % AdvBatteryTemperature
    if AdvBatteryTemperature >= crit_batt_temp:
        state = 2
        infotxt += "(!!)"
    else:
        state = 0
    single_states.append( (state, infotxt, ("battemp", AdvBatteryTemperature, "", crit_batt_temp) ) )

    # 5. Check battery current
    infotxt = "bat. curr. %dA" % AdvBatteryCurrent
    if AdvBatteryCurrent >= crit_batt_curr:
        state = 2
        infotxt += "(!!)"
    else:
        state = 0
    single_states.append( (state, infotxt, ("batcurr", AdvBatteryCurrent, "", crit_batt_curr, 0) ) )

    # 6. Check output voltage
    infotxt = "output voltage %dV" % AdvOutputVoltage
    if AdvOutputVoltage <= crit_voltage:
        state = 2
        infotxt += "(!!)"
    else:
        state = 0
    single_states.append( (state, infotxt, ("voltage", AdvOutputVoltage, "", crit_voltage, 0) ) )

    # 7. Simply add output current as perfdata
    single_states.append( (0, "output current %dA" % AdvOutputCurrent, ("current", AdvOutputCurrent)) )

    # 8. run time remaining
    # RunTimeRemaining == "0:0:26:00.00"
    hrs = int(RunTimeRemaining) / 3600
    mins, secs = divmod(int(RunTimeRemaining) % 3600, 60)
    single_states.append( (0, "run time remaining: %02d:%02d:%02d" % (hrs, mins, secs), None) )

    # create summary state
    worst_state = max([x[0] for x in single_states])
    info_text = ", ".join([x[1] for x in single_states])
    state_text = { 0:"OK", 1:"WARN", 2:"CRIT" }.get(worst_state)

    return (worst_state, "%s - %s" % (state_text, info_text), [x[2] for x in single_states if x[2] != None])

def inventory_apc(info):
    if len(info) > 0:
        return [(None, "apc_default_levels")]


check_info['apc_symmetra'] = {
  "inventory_function"  : inventory_apc,
  "check_function"      : check_apc,
  "service_description" : "APC Symmetra status",
  "has_perfdata"        : True,
  "group"               : "apc_symentra",
  "snmp_scan_function"  : lambda oid: oid(".1.3.6.1.2.1.1.2.0").startswith(".1.3.6.1.4.1.318.1.3"),
  "snmp_info"           : (".1.3.6.1.4.1.318.1.1.1",
                          [ "2.1.1.0", "4.1.1.0", "2.2.1.0", "2.2.2.0",
                             "2.2.9.0", "4.2.1.0", "4.2.4.0", "2.2.3.0" ] )
}
