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


def parse_aws_elbv2_network(info):
    metrics = _extract_aws_metrics_by_labels([
        'ConsumedLCUs',
        'ActiveFlowCount',
        'ActiveFlowCount_TLS',
        'NewFlowCount',
        'NewFlowCount_TLS',
        'HealthyHostCount',
        'UnHealthyHostCount',
        'ProcessedBytes',
        'ProcessedBytes_TLS',
        'ClientTLSNegotiationErrorCount',
        'TargetTLSNegotiationErrorCount',
        'TCP_Client_Reset_Count',
        'TCP_ELB_Reset_Count',
        'TCP_Target_Reset_Count',
    ], parse_aws(info))
    # We get exactly one entry: {INST-ID: METRICS}
    # INST-ID is the piggyback host name
    try:
        return metrics.values()[-1]
    except IndexError:
        return {}


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


def check_aws_elbv2_network_lcu(item, params, parsed):
    lcus = parsed['ConsumedLCUs']
    yield check_levels(lcus,
                       'aws_consumed_lcus',
                       params.get('levels'),
                       human_readable_func=int,
                       infoname="Consumed")


check_info['aws_elbv2_network'] = {
    'parse_function': parse_aws_elbv2_network,
    'inventory_function': lambda p: inventory_aws_generic_single(p, ['ConsumedLCUs']),
    'check_function': check_aws_elbv2_network_lcu,
    'service_description': 'AWS/NetworkELB LCUs',
    'includes': ['aws.include'],
    'group': 'aws_elbv2_lcu',
    'has_perfdata': True,
}

#.
#   .--connections---------------------------------------------------------.
#   |                                        _   _                         |
#   |         ___ ___  _ __  _ __   ___  ___| |_(_) ___  _ __  ___         |
#   |        / __/ _ \| '_ \| '_ \ / _ \/ __| __| |/ _ \| '_ \/ __|        |
#   |       | (_| (_) | | | | | | |  __/ (__| |_| | (_) | | | \__ \        |
#   |        \___\___/|_| |_|_| |_|\___|\___|\__|_|\___/|_| |_|___/        |
#   |                                                                      |
#   '----------------------------------------------------------------------'

_aws_elbv2_network_connection_types = [
    'ActiveFlowCount',
    'ActiveFlowCount_TLS',
    'NewFlowCount',
    'NewFlowCount_TLS',
]


def inventory_aws_elbv2_network_connections(parsed):
    for conn_ty in _aws_elbv2_network_connection_types:
        if conn_ty in parsed:
            return [(None, {})]


def check_aws_elbv2_network_connections(item, params, parsed):
    for conn_ty, (title, key) in zip(_aws_elbv2_network_connection_types, [
        ('Active', 'active'),
        ('Active TLS', 'active_tls'),
        ('New', 'new'),
        ('New TLS', 'new_tls'),
    ]):
        conns = parsed.get(conn_ty)
        if conns is None:
            continue
        yield check_levels(conns,
                           'aws_%s_connections' % key,
                           None,
                           human_readable_func=int,
                           infoname=title)


check_info['aws_elbv2_network.connections'] = {
    'parse_function': parse_aws_elbv2_network,
    'inventory_function': inventory_aws_elbv2_network_connections,
    'check_function': check_aws_elbv2_network_connections,
    'service_description': 'AWS/NetworkELB Connections',
    'includes': ['aws.include'],
    'has_perfdata': True,
}

#.
#   .--Healthy hosts-------------------------------------------------------.
#   |    _   _            _ _   _             _               _            |
#   |   | | | | ___  __ _| | |_| |__  _   _  | |__   ___  ___| |_ ___      |
#   |   | |_| |/ _ \/ _` | | __| '_ \| | | | | '_ \ / _ \/ __| __/ __|     |
#   |   |  _  |  __/ (_| | | |_| | | | |_| | | | | | (_) \__ \ |_\__ \     |
#   |   |_| |_|\___|\__,_|_|\__|_| |_|\__, | |_| |_|\___/|___/\__|___/     |
#   |                                 |___/                                |
#   '----------------------------------------------------------------------'


def check_aws_elbv2_network_healthy_hosts(item, params, parsed):
    try:
        healthy_hosts = int(parsed["HealthyHostCount"])
    except (KeyError, ValueError):
        healthy_hosts = None

    try:
        unhealthy_hosts = int(parsed["UnHealthyHostCount"])
    except (KeyError, ValueError):
        unhealthy_hosts = None

    if healthy_hosts is not None:
        yield 0, 'Healthy hosts: %s' % healthy_hosts

    if unhealthy_hosts is not None:
        yield 0, 'Unhealthy hosts: %s' % unhealthy_hosts

    if healthy_hosts is not None and unhealthy_hosts is not None:
        total_hosts = unhealthy_hosts + healthy_hosts
        yield 0, 'Total: %s' % total_hosts

        try:
            perc = 100.0 * healthy_hosts / total_hosts
        except ZeroDivisionError:
            perc = None

        if perc is not None:
            yield check_levels(perc,
                               'aws_overall_hosts_health_perc',
                               params.get('levels_overall_hosts_health_perc'),
                               human_readable_func=get_percent_human_readable,
                               infoname="Proportion of healthy hosts")


check_info['aws_elbv2_network.healthy_hosts'] = {
    'inventory_function': lambda p: inventory_aws_generic_single(
        p, ['HealthyHostCount', 'UnHealthyHostCount']),
    'check_function': check_aws_elbv2_network_healthy_hosts,
    'service_description': 'AWS/NetworkELB Healthy Hosts',
    'includes': ['aws.include'],
    'group': 'aws_elb_healthy_hosts',
    'has_perfdata': True,
}

#.
#   .--TLS handshakes------------------------------------------------------.
#   |                          _____ _     ____                            |
#   |                         |_   _| |   / ___|                           |
#   |                           | | | |   \___ \                           |
#   |                           | | | |___ ___) |                          |
#   |                           |_| |_____|____/                           |
#   |                                                                      |
#   |        _                     _     _           _                     |
#   |       | |__   __ _ _ __   __| |___| |__   __ _| | _____  ___         |
#   |       | '_ \ / _` | '_ \ / _` / __| '_ \ / _` | |/ / _ \/ __|        |
#   |       | | | | (_| | | | | (_| \__ \ | | | (_| |   <  __/\__ \        |
#   |       |_| |_|\__,_|_| |_|\__,_|___/_| |_|\__,_|_|\_\___||___/        |
#   |                                                                      |
#   '----------------------------------------------------------------------'

_aws_elbv2_network_tls_types = [
    'ClientTLSNegotiationErrorCount',
    'TargetTLSNegotiationErrorCount',
]


def inventory_aws_elbv2_network_tls_handshakes(parsed):
    for metric in _aws_elbv2_network_tls_types:
        if metric in parsed:
            return [(None, {})]


def check_aws_elbv2_network_tls_handshakes(item, params, parsed):
    for handshake_ty, (title, key) in zip(_aws_elbv2_network_tls_types, [
        ('Client', 'client'),
        ('Target', 'target'),
    ]):
        handshake = parsed.get(handshake_ty)
        if handshake is None:
            continue
        yield check_levels(handshake,
                           'aws_failed_tls_%s_handshake' % key,
                           None,
                           human_readable_func=int,
                           infoname=title)


check_info['aws_elbv2_network.tls_handshakes'] = {
    'inventory_function': inventory_aws_elbv2_network_tls_handshakes,
    'check_function': check_aws_elbv2_network_tls_handshakes,
    'service_description': 'AWS/NetworkELB TLS Handshakes',
    'includes': ['aws.include'],
    'has_perfdata': True,
}

#.
#   .--RST packets---------------------------------------------------------.
#   |        ____  ____ _____                    _        _                |
#   |       |  _ \/ ___|_   _|  _ __   __ _  ___| | _____| |_ ___          |
#   |       | |_) \___ \ | |   | '_ \ / _` |/ __| |/ / _ \ __/ __|         |
#   |       |  _ < ___) || |   | |_) | (_| | (__|   <  __/ |_\__ \         |
#   |       |_| \_\____/ |_|   | .__/ \__,_|\___|_|\_\___|\__|___/         |
#   |                          |_|                                         |
#   '----------------------------------------------------------------------'

_aws_elbv2_network_rst_packets_types = [
    'TCP_Client_Reset_Count',
    'TCP_ELB_Reset_Count',
    'TCP_Target_Reset_Count',
]


def inventory_aws_elbv2_network_rst_packets(parsed):
    for metric in _aws_elbv2_network_rst_packets_types:
        if metric in parsed:
            return [(None, {})]


def check_aws_elbv2_network_rst_packets(item, params, parsed):
    for reset_ty, (title, key) in zip(_aws_elbv2_network_rst_packets_types, [
        ('From client to target', 'tcp_client_rst'),
        ('Generated by load balancer', 'tcp_elb_rst'),
        ('From target to client', 'tcp_target_rst'),
    ]):
        resets = parsed.get(reset_ty)
        if resets is None:
            continue
        yield check_levels(resets, 'aws_%s' % key, None, human_readable_func=int, infoname=title)


check_info['aws_elbv2_network.rst_packets'] = {
    'inventory_function': inventory_aws_elbv2_network_rst_packets,
    'check_function': check_aws_elbv2_network_rst_packets,
    'service_description': 'AWS/NetworkELB Reset Packets',
    'includes': ['aws.include'],
    'has_perfdata': True,
}

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


def inventory_aws_elbv2_network_statistics(parsed):
    for metric in [
            'ProcessedBytes',
            'ProcessedBytes_TLS',
    ]:
        if metric in parsed:
            return [(None, {})]


def check_aws_elbv2_network_statistics(item, params, parsed):
    processed_bytes = parsed.get('ProcessedBytes')
    if processed_bytes is not None:
        yield check_levels(processed_bytes,
                           'aws_proc_bytes',
                           None,
                           human_readable_func=get_bytes_human_readable,
                           infoname="Processed bytes")

    processed_bytes_tls = parsed.get('ProcessedBytes_TLS')
    if processed_bytes_tls is not None:
        yield check_levels(processed_bytes_tls,
                           'aws_proc_bytes_tls',
                           None,
                           human_readable_func=get_bytes_human_readable,
                           infoname="Processed bytes TLS")


check_info['aws_elbv2_network.statistics'] = {
    'inventory_function': inventory_aws_elbv2_network_statistics,
    'check_function': check_aws_elbv2_network_statistics,
    'service_description': 'AWS/NetworkELB Statistics',
    'includes': ['aws.include'],
    'has_perfdata': True,
}
