2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
10 # | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
11 # +------------------------------------------------------------------+
13 # This file is part of Check_MK.
14 # The official homepage is at http://mathias-kettner.de/check_mk.
16 # check_mk is free software; you can redistribute it and/or modify it
17 # under the terms of the GNU General Public License as published by
18 # the Free Software Foundation in version 2. check_mk is distributed
19 # in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
20 # out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
21 # PARTICULAR PURPOSE. See the GNU General Public License for more de-
22 # tails. You should have received a copy of the GNU General Public
23 # License along with GNU Make; see the file COPYING. If not, write
24 # to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
25 # Boston, MA 02110-1301 USA.
27 # Output of old agent (< 1.1.10i2):
28 # AeLookupSvc running Application Experience Lookup Service
29 # Alerter stopped Alerter
30 # ALG stopped Application Layer Gateway Service
31 # AppMgmt stopped Application Management
32 # appmgr running Remote Server Manager
34 # Output of new agent (>= 1.1.10i2):
35 # Alerter stopped/disabled Warndienst
36 # ALG running/demand Gatewaydienst auf Anwendungsebene
37 # Apple_Mobile_Device running/auto Apple Mobile Device
38 # AppMgmt stopped/demand Anwendungsverwaltung
39 # AudioSrv running/auto Windows Audio
40 # BITS running/demand Intelligenter Hintergrund<FC>bertragungsdienst
41 # Bonjour_Service running/auto Dienst "Bonjour"
43 # Deprecated option since 1.6. cmk_base creates a config warning when finding rules
44 # for this ruleset. Can be dropped with 1.7.
45 inventory_services
= []
47 # Implemented in 1.2.1i2:
48 # New rule-style (WATO compatible) notation:
49 # [({'start_mode': 'demand', 'service': ['Netman']}, [], ['@all'], {'docu_url': ''})]
51 # <services> is list of regexes matching the service name
52 # <state> is the expected state to inventorize services of (running, stopped, ...)
53 # <start_mode> is the expected state to inventorize services of (auto, manual, ...)
55 # All above attributes can be set to None or not set to disable this filter option for the entry.
56 inventory_services_rules
= []
59 def inventory_windows_services(info
):
60 # Handle single entries (type str)
61 def add_matching_services(name
, description
, state
, start_type
, entry
):
62 if isinstance(entry
, tuple):
63 # New wato rule handling
67 elif ' ' in entry
and len(entry
.split()) == 2:
68 svc
, statespec
= entry
.split()
74 # First match name or description (optional since rule based config option available)
76 if svc
.startswith("~"):
78 if not r
.match(name
) and not r
.match(description
):
80 elif svc
!= name
and svc
!= description
:
83 if isinstance(statespec
, tuple):
84 # New wato rule handling (always given as tuple of two)
85 if (statespec
[0] and statespec
[0] != state
) \
86 or (statespec
[1] and statespec
[1] != start_type
):
90 for n
in statespec
.split("/"):
91 if n
not in [state
, start_type
]:
96 # Extract the WATO compatible rules for the current host
98 for value
in host_extra_conf(host_name(), inventory_services_rules
):
99 # Now extract the list of service regexes
100 svcs
= value
.get('services', [])
101 state
= value
.get('state', None)
102 start_mode
= value
.get('start_mode', None)
105 rules
.append(('~' + svc
, state
, start_mode
))
107 rules
.append((None, state
, start_mode
))
112 description
= " ".join(line
[3:])
114 state
, start_type
= line
[2].split('/')
117 start_type
= "unknown"
120 inventory
+= add_matching_services(name
, description
, state
, start_type
, rule
)
125 # Format of parameters
127 # "states" : [ ( "running", "demand", 1 ),
128 # ( "stopped", None, 2 ) ],
133 def check_windows_services(item
, params
, info
):
134 # Hack for old manually defined checks:
136 params
= factory_settings
["services_default_levels"]
138 # A service may appear more than once (due to clusters).
139 # First make a list of all matching entries with their
143 # allow to match agains the internal name or agains the display name
145 display_name
= " ".join(line
[3:])
146 if item
== line
[1] or item
== display_name \
147 or line
[1] in params
['additional_servicenames'] \
148 or display_name
in params
['additional_servicenames']:
149 # newer agents also send start type as part of state,
152 state
, start_type
= line
[2].split('/')
155 start_type
= "unknown"
156 found
.append((line
[0], state
, start_type
, " ".join(line
[3:])))
159 return params
["else"], "service not found"
161 # We take the best found state (neccessary for clusters)
162 best_desc
, best_state
, best_info
, best_running_on
= None, None, None, None
163 for running_on
, state
, start_type
, desc
in found
:
164 for t_state
, t_start_type
, mon_state
in params
["states"]:
165 if (t_state
is None or t_state
== state
) \
166 and (t_start_type
is None or t_start_type
== start_type
):
167 this_state
= mon_state
170 this_state
= params
["else"]
172 if best_state
is None or this_state
< best_state
:
173 best_state
= this_state
174 best_info
= state
, start_type
175 best_running_on
= running_on
178 infotext
= best_desc
+ ": %s (start type is %s)" % best_info
179 if best_running_on
and best_state
!= 2: #if best state ist critical, there should no message "running on"
180 infotext
+= " (running on: %s)" % best_running_on
182 return (best_state
, infotext
)
185 factory_settings
["services_default_levels"] = {
186 "states": [("running", None, 0)],
188 "additional_servicenames": [],
191 check_info
['services'] = {
192 "check_function": check_windows_services
,
193 "inventory_function": inventory_windows_services
,
194 "service_description": "Service %s",
197 "default_levels_variable": "services_default_levels",
200 factory_settings
["services_summary_default_levels"] = {"ignored": [], "state_if_stopped": 0}
203 def inventory_services_summary(info
):
205 return [(None, "services_summary_default_levels")]
208 def check_services_summary(item
, params
, info
):
209 blacklist
= params
.get("ignored", ())
214 # newer agents also send start type as part of state,
217 startstop
, auto
= line
[2].split('/')
224 if startstop
== "stopped":
226 for srv
in blacklist
:
227 if re
.match(srv
, srv_name
):
230 stoplist
.append(srv_name
)
234 num_stoplist
= len(stoplist
)
237 if len(stoplist
) > 0:
238 stopped_srvs
= " (" + ", ".join(stoplist
) + ")"
239 state
= params
.get("state_if_stopped")
252 infotext
= "%d services, %d services in autostart - of which %d services are stopped%s%s, %d services stopped but ignored" % \
253 ( num_srv
, num_auto
, num_stoplist
, sym
, stopped_srvs
, num_blacklist
)
255 return state
, infotext
258 check_info
['services.summary'] = {
259 "check_function": check_services_summary
,
260 "inventory_function": inventory_services_summary
,
261 "default_levels_variable": "services_summary_default_levels",
262 "service_description": "Services Summary",
264 "group": "services_summary",