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

# Example output from agent:
# <<<esx_vsphere_objects:sep(9)>>>
# hostsystem  esx.wacker.corp
# virtualmachine  LinuxI
# virtualmachine  OpenSUSE_II
# virtualmachine  OpenSUSE_III
# virtualmachine  OpenSUSE_IV
# virtualmachine  OpenSUSE_V
# virtualmachine  WindowsXP I
# virtualmachine  LinuxII
# virtualmachine  LinuxIII
# virtualmachine  LinuxIV
# virtualmachine  LinuxV
# virtualmachine  OpenSUSE_I

vsphere_object_names = {
    "hostsystem": "HostSystem",
    "virtualmachine": "VM",
}

factory_settings["esx_vsphere_objects_default_levels"] = {
    "states": {
        "poweredOn": 0,
        "poweredOff": 1,
        "suspended": 1,
        "unknown": 3,
    }
}


def parse_esx_vsphere_objects(info):
    parsed = {}
    Obj = collections.namedtuple("EsxObj", ["name", "hostsystem", "state"])
    for line in info:
        if len(line) < 2:
            continue
        if len(line) < 4:
            line += [''] * (4 - len(line))
        obj_type = vsphere_object_names.get(line[0], "Unknown Object")
        name = "%s %s" % (obj_type, line[1])
        obj = Obj(name, line[2], line[3])
        parsed[obj.name] = obj

    return parsed


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


def inventory_esx_vsphere_objects(parsed):
    for key in parsed:
        yield key, {}


def check_esx_vsphere_objects(item, params, parsed):
    if params is None:
        params = {}

    obj = parsed.get(item)
    if obj is None:
        yield 3, "Missing item: %s" % item
        return

    if not obj.state:
        what, name = item.split()
        if what == "VM":
            yield 3, "Virtual machine %s is missing" % name
        else:
            yield 3, "No data about host system %s" % name
        return

    state = params.get("states", {}).get(obj.state, 3)
    yield state, "power state: %s" % obj.state

    if obj.hostsystem:
        if obj.state == "poweredOn":
            yield 0, 'running on [%s]' % obj.hostsystem
        else:
            yield 0, 'defined on [%s]' % obj.hostsystem


check_info['esx_vsphere_objects'] = {
    "parse_function": parse_esx_vsphere_objects,
    "inventory_function": inventory_esx_vsphere_objects,
    "check_function": check_esx_vsphere_objects,
    "service_description": "%s",
    "group": "esx_vsphere_objects",
    "default_levels_variable": "esx_vsphere_objects_default_levels",
}


def inventory_esx_vsphere_objects_count(parsed):
    yield None, {}


def check_esx_vsphere_objects_count(_no_item, params, parsed):
    if params is None:
        params = {}

    virtualmachines = [o for o in parsed.itervalues() if o.name.startswith("VM ")]
    yield 0, "Virtualmachines: %d" % len(virtualmachines), [('vms', len(virtualmachines))]

    hostsystems = [o for o in parsed.itervalues() if o.name.startswith("HostSystem")]
    if not hostsystems:
        return

    yield 0, "Hostsystems: %d" % len(hostsystems), [('hosts', len(hostsystems))]

    for distribution in params.get("distribution", []):
        ruled_vms = distribution.get("vm_names", [])
        hosts = set(vm.hostsystem for vm in virtualmachines if vm.name[3:] in ruled_vms)
        count = len(hosts)
        hosts = sorted(hosts)
        if count < distribution["hosts_count"]:
            yield distribution.get(
                "state",
                2), ("VMs %s are running on %d host%s: %s" %
                     (', '.join(ruled_vms), count, '' if count == 1 else 's', ', '.join(hosts)))


check_info['esx_vsphere_objects.count'] = {
    "inventory_function": inventory_esx_vsphere_objects_count,
    "check_function": check_esx_vsphere_objects_count,
    "service_description": "Object count",
    "has_perfdata": True,
    "group": "esx_vsphere_objects_count",
}
