#!/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.


# .1.3.6.1.4.1.9.9.117.1.1.2.1.2.22 2
# .1.3.6.1.4.1.9.9.117.1.1.2.1.2.23 2
# .1.3.6.1.4.1.9.9.117.1.1.2.1.2.470 2
# .1.3.6.1.4.1.9.9.117.1.1.2.1.2.471 2
# .1.3.6.1.4.1.9.9.117.1.1.2.1.2.472 2
# .1.3.6.1.4.1.9.9.117.1.1.2.1.2.473 2
# .1.3.6.1.4.1.9.9.117.1.1.2.1.2.113000022 2
# .1.3.6.1.4.1.9.9.117.1.1.2.1.2.113000470 2
# .1.3.6.1.4.1.9.9.117.1.1.2.1.2.113000471 2
# .1.3.6.1.4.1.9.9.117.1.1.2.1.2.116000022 2
# .1.3.6.1.4.1.9.9.117.1.1.2.1.2.116000470 2
# .1.3.6.1.4.1.9.9.117.1.1.2.1.2.116000471 2

# .1.3.6.1.2.1.47.1.1.1.1.7.10 Fabric [VPC domain:12]
# .1.3.6.1.2.1.47.1.1.1.1.7.22 Nexus 56128P Supervisor in Fixed Module-1
# .1.3.6.1.2.1.47.1.1.1.1.7.23 24 ports 10GE SFP+ and 2xQSFP ports Ethernet Module
# .1.3.6.1.2.1.47.1.1.1.1.7.149 Nexus 56128P Chassis
# .1.3.6.1.2.1.47.1.1.1.1.7.214 Fixed Slot-1
# .1.3.6.1.2.1.47.1.1.1.1.7.215 Module Slot-2
# .1.3.6.1.2.1.47.1.1.1.1.7.216 Module Slot-3
# .1.3.6.1.2.1.47.1.1.1.1.7.278 PowerSupplyBay-1
# .1.3.6.1.2.1.47.1.1.1.1.7.279 PowerSupplyBay-2
# .1.3.6.1.2.1.47.1.1.1.1.7.280 PowerSupplyBay-3
# .1.3.6.1.2.1.47.1.1.1.1.7.281 PowerSupplyBay-4
# .1.3.6.1.2.1.47.1.1.1.1.7.342 FanBay-1
# .1.3.6.1.2.1.47.1.1.1.1.7.343 FanBay-2
# .1.3.6.1.2.1.47.1.1.1.1.7.344 FanBay-3
# .1.3.6.1.2.1.47.1.1.1.1.7.345 FanBay-4
# .1.3.6.1.2.1.47.1.1.1.1.7.470 PowerSupply-1
# .1.3.6.1.2.1.47.1.1.1.1.7.471 PowerSupply-2
# .1.3.6.1.2.1.47.1.1.1.1.7.472 PowerSupply-3
# .1.3.6.1.2.1.47.1.1.1.1.7.473 PowerSupply-4
# .1.3.6.1.2.1.47.1.1.1.1.7.534 FanModule-1
# .1.3.6.1.2.1.47.1.1.1.1.7.535 FanModule-2
# .1.3.6.1.2.1.47.1.1.1.1.7.536 FanModule-3
# .1.3.6.1.2.1.47.1.1.1.1.7.537 FanModule-4
# .1.3.6.1.2.1.47.1.1.1.1.7.538 PowerSupply-1 Fan-1
# .1.3.6.1.2.1.47.1.1.1.1.7.539 PowerSupply-1 Fan-2
# .1.3.6.1.2.1.47.1.1.1.1.7.540 PowerSupply-2 Fan-1
# .1.3.6.1.2.1.47.1.1.1.1.7.541 PowerSupply-2 Fan-2
# ...


def parse_cisco_fru_power(info):
    map_states = {
      '1' : (1, 'off env other'),
      '2' : (0, 'on'),
      '3' : (1, 'off admin'),
      '4' : (2, 'off denied'),
      '5' : (2, 'off env power'),
      '6' : (2, 'off env temp'),
      '7' : (2, 'off env fan'),
      '8' : (2, 'failed'),
      '9' : (1, 'on but fan fail'),
      '10': (1, 'off cooling'),
      '11': (1, 'off connector rating'),
      '12': (2, 'on but inline power fail'),
    }

    ppre_parsed = {}
    for end_oid, oper_state, fru_current in info[0]:
        # We discover only "real" power supplies which have current value >= 0
        # Others such as modules do not have such values
        if oper_state not in [ "", "0", "1", "5" ] and \
           fru_current and int(fru_current) >= 0:
            ppre_parsed.setdefault(end_oid, map_states.get(oper_state, (3, "unexpected(%s)" % oper_state)))

    pre_parsed = {}
    for end_oid, name in info[1]:
        if end_oid in ppre_parsed:
            pre_parsed.setdefault(name, [])
            pre_parsed[name].append(ppre_parsed[end_oid])

    parsed = {}
    for name, infos in pre_parsed.items():
        if len(infos) > 1:
            for k, state_info in enumerate(infos):
                parsed["%s-%d" % (name, k+1)] = state_info
        else:
            parsed[name] = infos[0]

    return parsed


def inventory_cisco_fru_power(parsed):
    for item in parsed:
        yield item, None


def check_cisco_fru_power(item, _no_params, parsed):
    if item in parsed:
        state, state_readable = parsed[item]
        return state, "Status: %s" % state_readable


check_info["cisco_fru_power"] = {
    'parse_function'      : parse_cisco_fru_power,
    'inventory_function'  : inventory_cisco_fru_power,
    'check_function'      : check_cisco_fru_power,
    'service_description' : 'FRU Power %s',
    'snmp_info'           : [('.1.3.6.1.4.1.9.9.117.1.1.2.1', [
                                OID_END,
                                "2",        # CISCO-ENTITY-FRU-CONTROL-MIB::cefcFRUPowerOperStatus
                                "3",        # CISCO-ENTITY-FRU-CONTROL-MIB::cefcFRUCurrent
                             ]),
                             ('.1.3.6.1.2.1.47.1.1.1.1', [
                                OID_END,
                                CACHED_OID(7), # ENTITY-MIB::entPhysicalName
                            ])],
    'snmp_scan_function'  : lambda oid: "cisco" in oid(".1.3.6.1.2.1.1.1.0").lower() \
                            # Exclude cisco_power check
                            and not oid(".1.3.6.1.4.1.9.9.13.1.5.1.*"),
}
