#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# |             ____ _               _        __  __ _  __           |
# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
# |                                                                  |
# | Copyright Mathias Kettner 2013             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-
# ails.  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 esx_vsphere_vm_convert(info):
    data = {}
    for line in info:
        data[line[0]] = line[1:]
    return data

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


def inventory_esx_vsphere_vm_mem(info):
    data = esx_vsphere_vm_convert(info).keys()
    if 'summary.quickStats.guestMemoryUsage' in data:
        return [(None, {})]

def check_esx_vsphere_vm_mem(_no_item, _no_params, info):
    data = esx_vsphere_vm_convert(info)

    # If the machine is powered of, we do not get data
    powerstate = data["runtime.powerState"][0]
    if powerstate != "poweredOn":
        raise MKCounterWrapped("", "VM is %s, skipping this check" % powerstate)


    try:
        #consumed host memory
        host_memory_usage   = savefloat(data["summary.quickStats.hostMemoryUsage"][0]) * 1024 * 1024
        #active guest memory
        guest_memory_usage  = savefloat(data["summary.quickStats.guestMemoryUsage"][0]) * 1024 * 1024
        #size of the balloon driver in the VM
        ballooned_memory    = savefloat(data["summary.quickStats.balloonedMemory"][0]) * 1024 * 1024
        #The portion of memory, in MB, that is granted to this VM from non-shared host memor(musst not be set)
        shared_memory       = savefloat(data["summary.quickStats.sharedMemory"][0]) * 1024 * 1024
        #The portion of memory, in MB, that is granted to this VM from host memory that is shared between VMs.
        private_memory      = savefloat(data.get("summary.quickStats.privateMemory",[0])[0]) * 1024 * 1024
    except:
        raise MKCounterWrapped("", "Hostsystem did not provide memory information (reason may be high load)")

    perf = [
        ("host",      host_memory_usage ),
        ("guest",     guest_memory_usage ),
        ("ballooned", ballooned_memory ),
        ("shared",    shared_memory ),
        ("private",   private_memory ),
    ]

    message = "Host: %s, Guest: %s, " \
              "Ballooned: %s, Private: %s, Shared: %s" % \
    (get_bytes_human_readable(host_memory_usage), \
     get_bytes_human_readable(guest_memory_usage), get_bytes_human_readable(ballooned_memory), \
     get_bytes_human_readable(private_memory), get_bytes_human_readable(shared_memory) )
    return(0, message, perf)


check_info['esx_vsphere_vm.mem_usage'] = {
  "inventory_function"  : inventory_esx_vsphere_vm_mem,
  "check_function"      : check_esx_vsphere_vm_mem,
  "service_description" : "ESX Memory",
  "has_perfdata"        : True
}

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

def inventory_esx_vsphere_vm_name(info):
    data = esx_vsphere_vm_convert(info).keys()
    if 'name' in data:
        return [(None, None)]

def check_esx_vsphere_vm_name(_no_item, _no_params, info):
    data = esx_vsphere_vm_convert(info)
    return(0, " ".join(data['name']))


check_info['esx_vsphere_vm.name'] = {
  "inventory_function"  : inventory_esx_vsphere_vm_name,
  "check_function"      : check_esx_vsphere_vm_name,
  "service_description" : "ESX Name",
}

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

# Possible values (this list is taken from the official documentation)
#    gray - VMware Tools are not installed or not running.
#    red - No heartbeat. Guest operating system may have stopped responding.
#    yellow - Intermittent heartbeat. May be due to guest load.
#    green - Guest operating system is responding normally.
#
def inventory_esx_vsphere_vm_hb_status(info):
    data = esx_vsphere_vm_convert(info)
    if 'guestHeartbeatStatus' in data:
        return [(None, None)]

def check_esx_vsphere_vm_hb_status(_no_item, params, info):
    data = esx_vsphere_vm_convert(info)

    vm_status = data['guestHeartbeatStatus'][0]
    state = 3

    vm_heartbeat_map = { "gray"   : (1, "heartbeat_no_tools"),
                         "green"  : (0, "heartbeat_ok"),
                         "red"    : (2, "heartbeat_missing"),
                         "yellow" : (1, "heartbeat_intermittend") }
    if vm_status in vm_heartbeat_map:
        if params:
            state = params.get(vm_heartbeat_map.get(vm_status)[1], 3)
        else:
            state = vm_heartbeat_map.get(vm_status)[0]
        if vm_status == 'gray':
            return state, "No VMWare Tools installed"
        else:
            return state, "Heartbeat status is %s" % vm_status
    else:
        return 3, "Unknown heartbeat status %s" % vm_status



check_info['esx_vsphere_vm.heartbeat'] = {
  "inventory_function"  : inventory_esx_vsphere_vm_hb_status,
  "check_function"      : check_esx_vsphere_vm_hb_status,
  "service_description" : "ESX Heartbeat",
  "group"               : "vm_heartbeat"
}

#.
#   .--CPU-----------------------------------------------------------------.
#   |                           ____ ____  _   _                           |
#   |                          / ___|  _ \| | | |                          |
#   |                         | |   | |_) | | | |                          |
#   |                         | |___|  __/| |_| |                          |
#   |                          \____|_|    \___/                           |
#   |                                                                      |
#   +----------------------------------------------------------------------+
#   |                                                                      |
#   '----------------------------------------------------------------------'

# <<<esx_vsphere_vm>>>
# config.hardware.numCPU 8
# config.hardware.numCoresPerSocket 2
# summary.quickStats.overallCpuUsage 8

def inventory_esx_vsphere_vm_cpu(info):
    data = esx_vsphere_vm_convert(info)
    if 'summary.quickStats.overallCpuUsage' in data:
        return [(None, None)]

def check_esx_vsphere_vm_cpu(_no_item, _no_params, info):
    data = esx_vsphere_vm_convert(info)
    # VMs that are currently down do not have this entry
    if 'summary.quickStats.overallCpuUsage' not in data:
        raise MKCounterWrapped("", "No information about CPU usage. VM is probably powered off.")

    usage_mhz = int(data['summary.quickStats.overallCpuUsage'][0])
    cpus = int(data['config.hardware.numCPU'][0])
    return 0, "demand is %.3f Ghz, %d virtual CPUs" % (usage_mhz / 1000.0, cpus), [ ("demand", usage_mhz) ]



check_info['esx_vsphere_vm.cpu'] = {
  "inventory_function"  : inventory_esx_vsphere_vm_cpu,
  "check_function"      : check_esx_vsphere_vm_cpu,
  "service_description" : "ESX CPU",
  "has_perfdata"        : True,
}
