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

factory_settings["netscaler_vserver_default_levels"] = {
    "health_levels": (100.0, 0.1),
    "cluster_status": "best",
}

netscaler_vserver_states = {
    "0": (1, "unknown"),
    "1": (2, "down"),
    "2": (1, "unknown"),
    "3": (1, "busy"),
    "4": (1, "out of service"),
    "5": (1, "transition to out of service"),
    "7": (0, "up"),
}

netscaler_vserver_types = {
    "0": "http",
    "1": "ftp",
    "2": "tcp",
    "3": "udp",
    "4": "ssl bridge",
    "5": "monitor",
    "6": "monitor udp",
    "7": "nntp",
    "8": "http server",
    "9": "http client",
    "10": "rpc server",
    "11": "rpc client",
    "12": "nat",
    "13": "any",
    "14": "ssl",
    "15": "dns",
    "16": "adns",
    "17": "snmp",
    "18": "ha",
    "19": "monitor ping",
    "20": "sslOther tcp",
    "21": "aaa",
    "23": "secure monitor",
    "24": "ssl vpn udp",
    "25": "rip",
    "26": "dns client",
    "27": "rpc server",
    "28": "rpc client",
    "62": "service unknown",
    "69": "tftp",
}

netscaler_vserver_entitytypes = {
    "0": "unknown",
    "1": "loadbalancing",
    "2": "loadbalancing group",
    "3": "ssl vpn",
    "4": "content switching",
    "5": "cache redirection",
}


def inventory_netscaler_vserver(parsed):
    for srv_name in parsed:
        yield srv_name, {}


def parse_netscaler_vserver(info):
    parsed = {}
    for (node, name, ip, port, svr_type, svr_state, svr_health, svr_entitytype, request_rate,
         rx_bytes, tx_bytes, full_name) in info:

        server_name = full_name if full_name else name
        svr_state, svr_state_readable = netscaler_vserver_states.get(svr_state, (1, "unknown"))

        tmp_dict = {
            'node': node,
            'service_state': (svr_state, svr_state_readable),
            'entity_service_type': netscaler_vserver_entitytypes.get(
                svr_entitytype, "unknown (%s)" % svr_entitytype),
            'protocol': netscaler_vserver_types.get(svr_type, "service unknown (%s)" % svr_type),
            'socket': '%s:%s' % (ip, port),
            'request_rate': int(request_rate),
            'rx_bytes': int(rx_bytes),
            'tx_bytes': int(tx_bytes),
        }

        if svr_entitytype in ["1", "2"]:
            tmp_dict['health'] = float(svr_health)

        parsed.setdefault(server_name, []).append(tmp_dict)
    return parsed


@get_parsed_item_data
def check_netscaler_vserver(item, params, data):
    if params is None:
        params = {}

    cluster_status = params.get('cluster_status', 'best')
    node_stat_list = []
    req_rate_list, rx_list, tx_list = [0], [0], [0]

    for node in data:
        node_stat_list.append(node['service_state'][0])
        req_rate_list.append(node.get('request_rate'))
        rx_list.append(node.get('rx_bytes'))
        tx_list.append(node.get('tx_bytes'))

    for node in data:
        if node['node']:
            txt = "Status: %s (%s)" % (node['service_state'][1], node['node'])
        else:
            txt = "Status: %s" % node['service_state'][1]
        if cluster_status == 'best':
            yield min(node_stat_list), txt
        else:
            yield node['service_state'][0], txt

    if data[0].get('entity_service_type') in ['loadbalancing', 'loadbalancing group']:
        warn, crit = params.get("health_levels", (None, None))
        health_perc = data[0]['health']
        info_txt = "Health: %s" % get_percent_human_readable(health_perc)
        health_state = 0
        if crit and health_perc < crit:
            health_state = 2
        elif warn and health_perc < warn:
            health_state = 1

        if health_state > 0:
            info_txt += " (warn/crit below %s/%s)" % (get_percent_human_readable(warn),
                                                      get_percent_human_readable(crit))
        yield health_state, info_txt, [("health_perc", health_perc, warn, crit, 0, 100)]

    yield 0, "Type: %s, Protocol: %s, Socket: %s" % (
        data[0]['entity_service_type'],
        data[0]['protocol'],
        data[0]['socket'],
    )

    info_txt = "Request rate: %s/s, In: %s/s, Out: %s/s" % (max(req_rate_list),
                                                            get_bytes_human_readable(max(rx_list)),
                                                            get_bytes_human_readable(max(tx_list)))
    yield 0, info_txt, [("request_rate", max(req_rate_list)), ("if_in_octets", max(rx_list)),
                        ("if_out_octets", max(tx_list))]


check_info["netscaler_vserver"] = {
    "parse_function": parse_netscaler_vserver,
    "check_function": check_netscaler_vserver,
    "inventory_function": inventory_netscaler_vserver,
    "service_description": "VServer %s",
    "snmp_info": (
        ".1.3.6.1.4.1.5951.4.1.3.1.1",
        [  # nsVserverGroup.vserverTable.vserverEntry
            1,  # vsvrName
            2,  # vsvrIpAddress
            3,  # vsvrPort
            4,  # vsvrType
            5,  # vsvrState
            62,  # vsvrHealth
            64,  # vsvrEntityType
            43,  # NS-ROOT-MIB::vsvrRequestRate
            44,  # NS-ROOT-MIB::vsvrRxBytesRate
            45,  # NS-ROOT-MIB::vsvrTxBytesRate
            59,  # vsvrFullName
        ]),
    "has_perfdata": True,
    "snmp_scan_function": lambda oid: oid(".1.3.6.1.2.1.1.2.0").startswith(".1.3.6.1.4.1.5951.1"),
    "group": "netscaler_vserver",
    "default_levels_variable": "netscaler_vserver_default_levels",
    "node_info": True,
}
