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


#   .--Parse function------------------------------------------------------.
#   |  ____                        __                  _   _               |
#   | |  _ \ __ _ _ __ ___  ___   / _|_   _ _ __   ___| |_(_) ___  _ __    |
#   | | |_) / _` | '__/ __|/ _ \ | |_| | | | '_ \ / __| __| |/ _ \| '_ \   |
#   | |  __/ (_| | |  \__ \  __/ |  _| |_| | | | | (__| |_| | (_) | | | |  |
#   | |_|   \__,_|_|  |___/\___| |_|  \__,_|_| |_|\___|\__|_|\___/|_| |_|  |
#   |                                                                      |
#   '----------------------------------------------------------------------'

def parse_ddn_s2a_faultsbasic(info):
    parsed = parse_ddn_s2a_api_response(info)

    non_unique_keys=[ u"failed_avr_fan_ctrl_item",
                      u"failed_avr_pwr_sup_item",
                      u"failed_avr_temp_W_item",
                      u"failed_avr_temp_C_item",
                      u"failed_disk_item",
                    ]

    for key in parsed.keys():
        if key not in non_unique_keys:
            parsed[key] = parsed[key][0]

    return parsed

#.
#   .--Disks---------------------------------------------------------------.
#   |                        ____  _     _                                 |
#   |                       |  _ \(_)___| | _____                          |
#   |                       | | | | / __| |/ / __|                         |
#   |                       | |_| | \__ \   <\__ \                         |
#   |                       |____/|_|___/_|\_\___/                         |
#   |                                                                      |
#   '----------------------------------------------------------------------'

ddn_s2a_faultsbasic_disks_default_levels = (1, 2)

def inventory_ddn_s2a_faultsbasic_disks(parsed):
    if u"disk_failures_count" in parsed:
        return [ (None, "ddn_s2a_faultsbasic_disks_default_levels") ]


def check_ddn_s2a_faultsbasic_disks(_no_item, params, parsed):
    warn, crit = params
    num_failures = int(parsed[u"disk_failures_count"])

    if num_failures >= crit:
        status = 2
    elif num_failures >= warn:
        status = 1
    else:
        status = 0

    infotext = "%d failures detected" % num_failures
    if parsed.get(u"failed_disk_item"):
        infotext += ". Failed disks: " + ", ".join(parsed[u"failed_disk_item"])

    return status, infotext


check_info["ddn_s2a_faultsbasic.disks"] = {
    "inventory_function"    : inventory_ddn_s2a_faultsbasic_disks,
    "check_function"        : check_ddn_s2a_faultsbasic_disks,
    "service_description"   : "DDN S2A Disks",
    "group"                 : "disk_failures",
}

#.
#   .--Temperature---------------------------------------------------------.
#   |     _____                                   _                        |
#   |    |_   _|__ _ __ ___  _ __   ___ _ __ __ _| |_ _   _ _ __ ___       |
#   |      | |/ _ \ '_ ` _ \| '_ \ / _ \ '__/ _` | __| | | | '__/ _ \      |
#   |      | |  __/ | | | | | |_) |  __/ | | (_| | |_| |_| | | |  __/      |
#   |      |_|\___|_| |_| |_| .__/ \___|_|  \__,_|\__|\__,_|_|  \___|      |
#   |                       |_|                                            |
#   '----------------------------------------------------------------------'

def inventory_ddn_s2a_faultsbasic_temp(parsed):
    if u"avr_temp_W_failures_count" in parsed:
        return [ (None, None) ]


def check_ddn_s2a_faultsbasic_temp(_no_item, _no_params, parsed):
    crit_failures = int(parsed[u"avr_temp_C_failures_count"])
    warn_failures = int(parsed[u"avr_temp_W_failures_count"])

    if crit_failures:
        status = 2
    elif warn_failures:
        status = 1
    else:
        status = 0

    infotext = "%d critical failures, %d warnings" % (crit_failures, warn_failures)

    crit_failures_items = parsed.get(u"failed_avr_temp_C_item")
    if crit_failures_items:
        infotext += ". Critical failures: " + ", ".join(crit_failures_items)

    warn_failures_items = parsed.get(u"failed_avr_temp_W_item")
    if warn_failures_items:
        infotext += ". Warnings: " + ", ".join(warn_failures_items)

    return status, infotext


check_info["ddn_s2a_faultsbasic.temp"] = {
    "inventory_function"    : inventory_ddn_s2a_faultsbasic_temp,
    "check_function"        : check_ddn_s2a_faultsbasic_temp,
    "service_description"   : "DDN S2A Temperature",
}

#.
#   .--Power supplies------------------------------------------------------.
#   |  ____                                                _ _             |
#   | |  _ \ _____      _____ _ __   ___ _   _ _ __  _ __ | (_) ___  ___   |
#   | | |_) / _ \ \ /\ / / _ \ '__| / __| | | | '_ \| '_ \| | |/ _ \/ __|  |
#   | |  __/ (_) \ V  V /  __/ |    \__ \ |_| | |_) | |_) | | |  __/\__ \  |
#   | |_|   \___/ \_/\_/ \___|_|    |___/\__,_| .__/| .__/|_|_|\___||___/  |
#   |                                         |_|   |_|                    |
#   '----------------------------------------------------------------------'

def inventory_ddn_s2a_faultsbasic_ps(parsed):
    if u"avr_pwr_sup_failures_count" in parsed:
        return [ (None, None) ]


def check_ddn_s2a_faultsbasic_ps(_no_item, _no_params, parsed):
    ps_failures = int(parsed[u"avr_pwr_sup_failures_count"])
    if ps_failures > 0:
        infotext = "Power supply failure: "
        infotext += ", ".join(parsed[u"failed_avr_pwr_sup_item"])
        return 2, infotext
    else:
        return 0, "No power supply failures detected"


check_info["ddn_s2a_faultsbasic.ps"] = {
    "inventory_function"    : inventory_ddn_s2a_faultsbasic_ps,
    "check_function"        : check_ddn_s2a_faultsbasic_ps,
    "service_description"   : "DDN S2A Power Supplies",
}

#.
#   .--Fans----------------------------------------------------------------.
#   |                         _____                                        |
#   |                        |  ___|_ _ _ __  ___                          |
#   |                        | |_ / _` | '_ \/ __|                         |
#   |                        |  _| (_| | | | \__ \                         |
#   |                        |_|  \__,_|_| |_|___/                         |
#   |                                                                      |
#   '----------------------------------------------------------------------'

ddn_s2a_faultsbasic_fans_default_levels = (1, 2)

def inventory_ddn_s2a_faultsbasic_fans(parsed):
    if u'avr_fan_ctrl_failures_count' in parsed:
        return [ (None, "ddn_s2a_faultsbasic_fans_default_levels") ]


def check_ddn_s2a_faultsbasic_fans(_no_item, params, parsed):
    fan_failures = int(parsed[u"avr_fan_ctrl_failures_count"])
    warn, crit = params

    if fan_failures >= crit:
        status = 2
    elif fan_failures >= warn:
        status = 1
    else:
        status = 0

    if fan_failures:
        infotext = "%d fan failures detected: " % fan_failures
        infotext += ", ".join(parsed[u"failed_avr_fan_ctrl_item"])
    else:
        infotext = "No fan failures detected"

    return status, infotext


check_info["ddn_s2a_faultsbasic.fans"] = {
    "inventory_function"    : inventory_ddn_s2a_faultsbasic_fans,
    "check_function"        : check_ddn_s2a_faultsbasic_fans,
    "service_description"   : "DDN S2A Fans",
    "group"                 : "fan_failures",
}

#.
#   .--Ping fault----------------------------------------------------------.
#   |             ____  _                __             _ _                |
#   |            |  _ \(_)_ __   __ _   / _| __ _ _   _| | |_              |
#   |            | |_) | | '_ \ / _` | | |_ / _` | | | | | __|             |
#   |            |  __/| | | | | (_| | |  _| (_| | |_| | | |_              |
#   |            |_|   |_|_| |_|\__, | |_|  \__,_|\__,_|_|\__|             |
#   |                           |___/                                      |
#   '----------------------------------------------------------------------'

def inventory_ddn_s2a_faultsbasic_pingfault(parsed):
    if u"ping_fault" in parsed:
        return [ (None, None) ]


def check_ddn_s2a_faultsbasic_pingfault(_no_item, _no_params, parsed):
    if parsed[u"ping_fault"] == u"FALSE":
        return 0, "No fault detected"
    elif u"ping_fault_tag" in parsed:
        return 1, "Ping Fault: " + parsed[u"ping_fault_tag"]
    elif parsed[u"ping_fault"] == u"TRUE":
        return 1, "Ping Fault"


check_info["ddn_s2a_faultsbasic.pingfault"] = {
    "inventory_function"    : inventory_ddn_s2a_faultsbasic_pingfault,
    "check_function"        : check_ddn_s2a_faultsbasic_pingfault,
    "service_description"   : "DDN S2A Ping Fault Status",
}


#.
#   .--Boot status---------------------------------------------------------.
#   |         ____              _         _        _                       |
#   |        | __ )  ___   ___ | |_   ___| |_ __ _| |_ _   _ ___           |
#   |        |  _ \ / _ \ / _ \| __| / __| __/ _` | __| | | / __|          |
#   |        | |_) | (_) | (_) | |_  \__ \ || (_| | |_| |_| \__ \          |
#   |        |____/ \___/ \___/ \__| |___/\__\__,_|\__|\__,_|___/          |
#   |                                                                      |
#   '----------------------------------------------------------------------'

def inventory_ddn_s2a_faultsbasic_bootstatus(parsed):
    if u"system_fully_booted" in parsed:
        return [ (None, None) ]


def check_ddn_s2a_faultsbasic_bootstatus(_no_item, _no_params, parsed):
    if parsed[u"system_fully_booted"] == u"TRUE":
        return 0, "System fully booted"
    else:
        return 1, "System not fully booted"


check_info["ddn_s2a_faultsbasic.bootstatus"] = {
    "inventory_function"    : inventory_ddn_s2a_faultsbasic_bootstatus,
    "check_function"        : check_ddn_s2a_faultsbasic_bootstatus,
    "service_description"   : "DDN S2A Boot Status",
}


#.
#   .--Cache coherency-----------------------------------------------------.
#   |                      ____           _                                |
#   |                     / ___|__ _  ___| |__   ___                       |
#   |                    | |   / _` |/ __| '_ \ / _ \                      |
#   |                    | |__| (_| | (__| | | |  __/                      |
#   |                     \____\__,_|\___|_| |_|\___|                      |
#   |                                                                      |
#   |                     _                                                |
#   |            ___ ___ | |__   ___ _ __ ___ _ __   ___ _   _             |
#   |           / __/ _ \| '_ \ / _ \ '__/ _ \ '_ \ / __| | | |            |
#   |          | (_| (_) | | | |  __/ | |  __/ | | | (__| |_| |            |
#   |           \___\___/|_| |_|\___|_|  \___|_| |_|\___|\__, |            |
#   |                                                    |___/             |
#   '----------------------------------------------------------------------'


def inventory_ddn_s2a_faultsbasic_cachecoh(parsed):
    if u"hstd1_online_failure" in parsed:
        return [ (None, None) ]


def check_ddn_s2a_faultsbasic_cachecoh(_no_item, _no_params, parsed):
    cache_coherency = parsed.get(u"cache_coherency")
    if cache_coherency:

        cache_coherency_states = {
            u"established"      : 0,
            u"not enabled"      : 1,
            u"not established"  : 2,
        }

        return cache_coherency_states.get(cache_coherency, 3), "Cache coherency: " + cache_coherency
    else: # The value is only supplied in case of a failure. A missing value is an implicit OK
          # according to the API documentation.
        return 0, "Cache coherency: established"


check_info["ddn_s2a_faultsbasic.cachecoh"] = {
    "inventory_function"    : inventory_ddn_s2a_faultsbasic_cachecoh,
    "check_function"        : check_ddn_s2a_faultsbasic_cachecoh,
    "service_description"   : "DDN S2A Cache Coherency",
}

#.
#   .--Dual communication--------------------------------------------------.
#   |         ____              _                                          |
#   |        |  _ \ _   _  __ _| |   ___ ___  _ __ ___  _ __ ___           |
#   |        | | | | | | |/ _` | |  / __/ _ \| '_ ` _ \| '_ ` _ \          |
#   |        | |_| | |_| | (_| | | | (_| (_) | | | | | | | | | | |         |
#   |        |____/ \__,_|\__,_|_|  \___\___/|_| |_| |_|_| |_| |_|         |
#   |                                                                      |
#   '----------------------------------------------------------------------'

def inventory_ddn_s2a_faultsbasic_dualcomm(parsed):
    if u"hstd1_online_failure" in parsed:
        return [ (None, None) ]


def check_ddn_s2a_faultsbasic_dualcomm(_no_item, _no_params, parsed):
    dual_comm_established = parsed.get(u"dual_comm_established")

    # This value is only transmitted by the API in case of a failure.
    # Therefore, a non-existant value is an implicit "TRUE" here.
    if dual_comm_established == "TRUE" or dual_comm_established is None:
        return 0, "Dual comm established"
    elif dual_comm_established == "FALSE":
        return 2, "Dual comm not established"


check_info["ddn_s2a_faultsbasic.dualcomm"] = {
    "inventory_function"    : inventory_ddn_s2a_faultsbasic_dualcomm,
    "check_function"        : check_ddn_s2a_faultsbasic_dualcomm,
    "service_description"   : "DDN S2A Dual Communication",
}


#.
#   .--Ethernet------------------------------------------------------------.
#   |              _____ _   _                          _                  |
#   |             | ____| |_| |__   ___ _ __ _ __   ___| |_                |
#   |             |  _| | __| '_ \ / _ \ '__| '_ \ / _ \ __|               |
#   |             | |___| |_| | | |  __/ |  | | | |  __/ |_                |
#   |             |_____|\__|_| |_|\___|_|  |_| |_|\___|\__|               |
#   |                                                                      |
#   '----------------------------------------------------------------------'

def inventory_ddn_s2a_faultsbasic_ethernet(parsed):
    if u"hstd1_online_failure" in parsed:
        return [ (None, None) ]


def check_ddn_s2a_faultsbasic_ethernet(_no_item, _no_params, parsed):
    ethernet_working = parsed.get(u"ethernet_working")

    # This value is only transmitted by the API in case of a failure.
    # Therefore, a non-existant value is an implicit "established" here.
    if ethernet_working == u"established" or ethernet_working is None:
        yield 0, "Ethernet connection established"
    else:
        yield 1, "Ethernet " + ethernet_working


check_info["ddn_s2a_faultsbasic.ethernet"] = {
    "inventory_function"    : inventory_ddn_s2a_faultsbasic_ethernet,
    "check_function"        : check_ddn_s2a_faultsbasic_ethernet,
    "service_description"   : "DDN S2A Ethernet",
}

#.
#   .--Unit status---------------------------------------------------------.
#   |           _   _       _ _         _        _                         |
#   |          | | | |_ __ (_) |_   ___| |_ __ _| |_ _   _ ___             |
#   |          | | | | '_ \| | __| / __| __/ _` | __| | | / __|            |
#   |          | |_| | | | | | |_  \__ \ || (_| | |_| |_| \__ \            |
#   |           \___/|_| |_|_|\__| |___/\__\__,_|\__|\__,_|___/            |
#   |                                                                      |
#   '----------------------------------------------------------------------'

def inventory_ddn_s2a_faultsbasic(parsed):
    for index in ["1", "2"]:
        if u"hstd%s_online_failure" % index in parsed:
            yield index, None


def check_ddn_s2a_faultsbasic(item, _no_params, parsed):
    online_failure = parsed[u"hstd%s_online_failure" % item]
    online_status = parsed.get(u"hstd%s_online_status" % item, u"")

    if online_failure == "TRUE":
        if online_status.lower() in [ "restarting", "not installed" ]:
            yield 1, "Unit " + online_status
        else:
            yield 2, "Failure detected - Online status: " + online_status
    elif online_failure == "FALSE":
        yield 0, "No failure detected"


check_info['ddn_s2a_faultsbasic'] = {
    'parse_function'        : parse_ddn_s2a_faultsbasic,
    "inventory_function"    : inventory_ddn_s2a_faultsbasic,
    "check_function"        : check_ddn_s2a_faultsbasic,
    "service_description"   : "DDN S2A Unit %s",
    'includes'              : [ "ddn_s2a.include" ],
}
