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


# Output of old agent (< 1.1.10i2):
# AeLookupSvc        running  Application Experience Lookup Service
# Alerter            stopped  Alerter
# ALG                stopped  Application Layer Gateway Service
# AppMgmt            stopped  Application Management
# appmgr             running  Remote Server Manager

# Output of new agent (>= 1.1.10i2):
# Alerter stopped/disabled Warndienst
# ALG running/demand Gatewaydienst auf Anwendungsebene
# Apple_Mobile_Device running/auto Apple Mobile Device
# AppMgmt stopped/demand Anwendungsverwaltung
# AudioSrv running/auto Windows Audio
# BITS running/demand Intelligenter Hintergrund<FC>bertragungsdienst
# Bonjour_Service running/auto Dienst "Bonjour"

inventory_services = []

# Examples for inventory_services:
# inventory_services = [
#   "HirnTest",               # add service, if currently running
#   "TapiSrv running",        # the same
#   "TermService auto",       # add service, if start type is auto (regardless if running)
#   "BackupSrv running/auto", # add, if start type is auto and it's running
#   "~Backup.* running/auto",  # same, but add all services matching a regex
#   ( [ "termserver" ] , ALL_HOSTS, [ "HirnTest running", "Sppoller auto" ] ), # same with tags..
#   ( ALL_HOSTS, [ "!Backup.*", "FooBar auto" ] ),
# ]

def inventory_windows_services(info):

    # Handle single entries (type str)
    def add_matching_services(name, state, start_type, entry):
        if ' ' in entry and len(entry.split()) == 2:
            svc, statespec = entry.split()
        else:
            svc = entry
            statespec = "running"

        # First match name
        if svc.startswith("~"):
            if not get_regex(svc[1:]).match(name):
                return []
        elif svc != name:
            return []

        for n in statespec.split("/"):
            if n not in [ state, start_type ]:
                return []

        return [(name, {})]

    # Handle entries like ( [ "term" ], ALL_HOSTS, [ "FooBar auto", ".*TEST running" ] )
    def add_services_with_tags(name, state, start_type, entry):
        matching = []
        if len(entry) == 2:
            entry = ( [], ) + entry
        taglist, hostlist, svclist = entry
        if hosttags_match_taglist(tags_of_host(g_hostname), taglist):
            if in_extraconf_hostlist(hostlist, g_hostname):
                for svc in svclist:
                    matching += add_matching_services(name, state, start_type, svc)
        return matching


    inventory = []
    for line in info:
        name = line[1]
        if '/' in line[2]:
            state, start_type = line[2].split('/')
        else:
            state = line[2]
            start_type = "unknown"

        for entry in inventory_services:
            if type(entry) == str:
                inventory += add_matching_services(name, state, start_type, entry)
            elif type(entry) == tuple:
                inventory += add_services_with_tags(name, state, start_type, entry)
            else:
                raise MKGeneralException("Invalid entry %r in inventory_services" % entry)

    return inventory


# Format of parameters
# {
#    "states" : [ ( "running", "demand", 1 ),
#                  ( "stopped", None, 2 ) ],
#    "else" : 2,
# }

def check_windows_services(item, params, info):
    # Hack for old manually defined checks:
    if params == None:
        params = factory_settings["services_default_levels"];

    # A service may appear more than once (due to clusters).
    # First make a list of all matching entries with their 
    # states
    found = []
    for line in info:
        if item == line[1]:
            # newer agents also send start type as part of state,
            # e.g. running/auto
            if '/' in line[2]:
                state, start_type = line[2].split('/')
            else:
                state = line[2]
                start_type = "unknown"
            found.append((line[0], state, start_type, " ".join(line[3:])))

    if len(found) == 0:
        return (3, "UNKNOWN - service not found")


    # We take the best found state (neccessary for clusters)
    best_state = None
    for running_on, state, start_type, desc in found:
        for t_state, t_start_type, mon_state in params["states"]:
            if (t_state == None or t_state == state) \
             and (t_start_type == None or t_start_type == start_type): 
                this_state = mon_state 
                break
        else:
            this_state = params["else"]

        if best_state == None or this_state < best_state:
            best_state = this_state
            best_info = state, start_type
            best_running_on = running_on
    infotext = nagios_state_names[best_state] + " - " + desc + ": %s (start type is %s)" % best_info
    if best_running_on and best_state != 2: #if best state ist critical, there should no message "running on"
        infotext += " (running on: %s)" % best_running_on

    return (best_state, infotext)



# check_info['services'] = (check_windows_services, "service_%s", 0, inventory_windows_services)
# checkgroup_of['services'] = 'services'

factory_settings["services_default_levels"] = { 
    "states"      : [ ( "running", None, 0 ) ],
    "else"        : 2,
}

check_info['services'] = {
    "check_function"          : check_windows_services,
    "inventory_function"      : inventory_windows_services,
    "service_description"     : "service_%s",
    "has_perfdata"            : False,
    "node_info"               : True,
    "group"                   : "services",
    "default_levels_variable" : "services_default_levels",
}
