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


# <<<websphere_mq_instance:sep(41)>>>
# QMNAME(QMIMIQ11) STATUS(Running)
#     INSTANCE(iasv0001) MODE(Active)
#     INSTANCE(tasv0397) MODE(Standby)
# MQv8.0.0.5,p800-005-160516.2,64-bit;
# QMNAME(QMIMIQ11) STATUS(Running) DEFAULT(no) STANDBY(Permitted) INSTNAME(Installation1) INSTPATH(/usr/mqm) INSTVER(8.0.0.5)$

# <<<websphere_mq_instance:sep(41)>>>
# QMNAME(QMTEMQS02A) STATUS(Ended immediately)
# QMNAME(QMTEMQS02)  STATUS(Running)
#     INSTANCE(tasv0065) MODE(Active)
# MQv8.0.0.4,p800-004-151017,64-bit;
# QMNAME(QMTEMQS02A) STATUS(Ended immediately) DEFAULT(no) STANDBY(Not applicable) INSTNAME(Installation1) INSTPATH(/usr/mqm) INSTVER(8.0.0.4)
# QMNAME(QMTEMQS02)  STATUS(Running) DEFAULT(yes) STANDBY(Not permitted) INSTNAME(Installation1) INSTPATH(/usr/mqm) INSTVER(8.0.0.4)

# <<<websphere_mq_instance:sep(41)>>>
# QMNAME(QMIMIQ11) STATUS(Running as standby)
#     INSTANCE(iasv0001) MODE(Active)
#     INSTANCE(tasv0397) MODE(Standby)
# MQv8.0.0.5,p800-005-160516.2,64-bit;
# QMNAME(QMIMIQ11) STATUS(Running as standby) DEFAULT(yes) STANDBY(Permitted) INSTNAME(Installation1) INSTPATH(/usr/mqm) INSTVER(8.0.0.5)


#   .--helpers-------------------------------------------------------------.
#   |                  _          _                                        |
#   |                 | |__   ___| |_ __   ___ _ __ ___                    |
#   |                 | '_ \ / _ \ | '_ \ / _ \ '__/ __|                   |
#   |                 | | | |  __/ | |_) |  __/ |  \__ \                   |
#   |                 |_| |_|\___|_| .__/ \___|_|  |___/                   |
#   |                              |_|                                     |
#   '----------------------------------------------------------------------'


def get_websphere_mq_status(what, status, params):
    state, statekey = {
        "manager" : {
            "Starting"              : (0, "starting"             ),
            "Running"               : (0, "running"              ),
            "Running as standby"    : (0, "running_as_standby"   ),
            "Running elsewhere"     : (0, "running_elsewhere"    ),
            "Quiescing"             : (0, "quiescing"            ),
            "Ending immediately"    : (0, "ending_immediately"   ),
            "Ending pre-emptively"  : (0, "ending_pre_emptively" ),
            "Ended normally"        : (0, "ended_normally"       ),
            "Ended immediately"     : (0, "ended_immediately"    ),
            "Ended unexpectedly"    : (2, "ended_unexpectedly"   ),
            "Ended pre-emptively"   : (1, "ended_pre_emptively"  ),
            "Status not available"  : (0, "status_not_available" ),
        },
        "standby" : {
            "Permitted"      : (0, "permitted"),
            "Not permitted"  : (0, "not_permitted"),
            "Not applicable" : (0, "not_applicable"),
        },
        "instance" : {
            "Active"  : (0, "active"),
            "Standby" : (0, "standby"),
        }
    }[what].get(status, (3, "unknown"))

    if statekey in dict(params.get("map_%s_states" % what, [])):
        return dict(params["map_%s_states" % what])[statekey]
    return state


def parse_websphere_mq_instance(info):
    def get_data_of_line(line):
        data = {}
        for elem in line:
            if "(" in elem:
                key, exp = elem.split("(", 1)
                data.setdefault(key.strip(), exp.strip())
        return data

    parsed = { "manager" : {}, "instances" : {} }
    for line in info:
        data = get_data_of_line(line)
        if data:
            if "QMNAME" in data:
                this_qm_name = data["QMNAME"]
                parsed["manager"].setdefault(this_qm_name, {})
                parsed["manager"][this_qm_name].update(data)

            elif "INSTANCE" in data:
                this_inst_name = data["INSTANCE"]
                parsed["instances"].setdefault(this_inst_name, {})
                parsed["instances"][this_inst_name].update(data)
                if this_qm_name is not None:
                    parsed["instances"][this_inst_name].setdefault("QMNAME", this_qm_name)

    return parsed


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


def inventory_websphere_mq_instance(parsed):
    return [ (item, {}) for item in parsed["instances"] ]


def check_websphere_mq_instance(item, params, parsed):
    get_other_state = {
        "Active"  : "Standby",
        "Standby" : "Active",
    }

    if item in parsed["instances"]:
        data    = parsed["instances"][item]
        mode    = data["MODE"]
        qm_name = data["QMNAME"]
        return get_websphere_mq_status("instance", mode, params), \
               'Status: %s, Manager: %s' % (mode.lower(), qm_name)


check_info['websphere_mq_instance'] = {
    'parse_function'        : parse_websphere_mq_instance,
    'inventory_function'    : inventory_websphere_mq_instance,
    'check_function'        : check_websphere_mq_instance,
    'service_description'   : 'MQ Instance %s',
    'group'                 : 'websphere_mq_instance',
}


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


def inventory_websphere_mq_manager(parsed):
    for item in parsed["manager"]:
        yield item, {}


def check_websphere_mq_manager(item, params, parsed):
    if item in parsed["manager"]:
        data    = parsed["manager"][item]
        status  = data["STATUS"]
        default = data["DEFAULT"]
        standby = data["STANDBY"]
        installation_name    = data.get("INSTNAME")
        installation_path    = data.get("INSTPATH")
        installation_version = data.get("INSTVER")

        instances_modes = []
        for instance, instance_info in parsed["instances"].items():
            if instance_info["QMNAME"] == item:
                instances_modes.append( instance_info["MODE"] )

        yield get_websphere_mq_status("manager", status, params), \
              'Status: %s' % status.lower()

        extra_info = ""
        if standby.startswith("Not"):
            if len(instances_modes) == 1:
                state = 0
                extra_info += " (standalone)"
            else:
                state = 1
                extra_info += " (standalone but %d instances)" % len(instances_modes)
        elif standby == "Permitted":
            if instances_modes in [ [ "Active", "Standby" ], [ "Standby", "Active" ] ]:
                state = 0
            else:
                state = 1
                extra_info += " (Missing partner)"
        else:
            state = 1
            extra_info += " (unknown)"

        if "map_instance_states" in params:
            state = get_websphere_mq_status("standby", standby, params)

        yield state, "Status: %s%s, Default: %s" % (standby.lower(), extra_info, default)

        for what, title in [ (installation_name,    "Name"),
                             (installation_path,    "Path"),
                             (installation_version, "Version") ]:
            if what:
                yield 0, "%s: %s" % (title, what)


check_info['websphere_mq_instance.manager'] = {
    'inventory_function'    : inventory_websphere_mq_manager,
    'check_function'        : check_websphere_mq_manager,
    'service_description'   : 'MQ Manager %s',
    'group'                 : 'websphere_mq_manager',
}
