#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# |             ____ _               _        __  __ _  __           |
# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
# |                                                                  |
# | Copyright Mathias Kettner 2014             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-
# tails. 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.

condition_map = {
    '1': ('other', 3),  # the status could not be determined or not present.
    '2': ('ok', 0),  # operating normally
    '3': ('degraded', 2),  # component is outside of normal operating range.
    '4': ('failed', 2),  # component detects condition that could damage system
}

factory_settings["hp_proliant_psu_levels"] = {
    "levels": (80, 90),
}


def parse_hp_proliant_psu(info):
    parsed = {}
    Psu = collections.namedtuple("Psu", ['chassis', 'bay', 'condition', 'used', 'max'])
    for chassis, bay, present, cond, used, capacity_maximum in info:
        if present != '3' or capacity_maximum == '0':
            continue
        item = "%s/%s" % (chassis, bay)
        try:
            parsed[item] = Psu(chassis, bay, cond, int(used), int(capacity_maximum))
        except ValueError:
            pass
    if parsed:
        PsuTotal = collections.namedtuple("Psu", ['used', 'max'])
        parsed['Total'] = PsuTotal(sum(v.used for v in parsed.values()),
                                   sum(v.max for v in parsed.values()))
    return parsed


def inventory_hp_proliant_psu(parsed):
    """Inventorizes all present PSUs, as well as the Sum over all PSUs"""
    for item in parsed:
        yield item, None


@get_parsed_item_data
def check_hp_proliant_psu(item, params, psu):
    if item != 'Total':
        yield 0, "Chassis %s/Bay %s" % (psu.chassis, psu.bay)
        snmp_state, status = condition_map[psu.condition]
        yield status, 'State: "%s"' % snmp_state

    # usage info
    info = 'Usage: %d Watts' % psu.used
    cap_perc = psu.used * 100 / psu.max
    perf_data = [
        ('power_usage_percentage', cap_perc),
        ('power_usage', psu.used),
    ]

    # check for user defined thresholds here
    warn, crit = params["levels"]
    msg = " (warn/crit at %s/%s)" % (warn, crit)
    if cap_perc > crit:
        yield 2, info + msg, perf_data
    elif cap_perc > warn:
        yield 1, info + msg, perf_data
    else:
        yield 0, info, perf_data


check_info["hp_proliant_psu"] = {
    'check_function': check_hp_proliant_psu,
    'inventory_function': inventory_hp_proliant_psu,
    'parse_function': parse_hp_proliant_psu,
    'default_levels_variable': "hp_proliant_psu_levels",
    'service_description': 'HW PSU %s',
    'group': 'hw_psu',
    'snmp_info': (
        ".1.3.6.1.4.1.232.6.2.9.3.1",
        [
            "1",  # cpqHeFltTolPowerSupplyChassis
            "2",  # cpqHeFltTolPowerSupplyBay
            "3",  # cpqHeFltTolPowerSupplyPresent
            "4",  # cpqHeFltTolPowerSupplyCondition
            "7",  # cpqHeFltTolPowerSupplyCapacityUsed
            "8",  # cpqHeFltTolPowerSupplyCapacityMaximum
        ]),
    'snmp_scan_function': lambda oid: "proliant" in oid(".1.3.6.1.4.1.232.2.2.4.2.0", "").lower(),
    'has_perfdata': True,
}
