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.
28 # Output of old agent (< 1.1.10i2):
29 # AeLookupSvc running Application Experience Lookup Service
30 # Alerter stopped Alerter
31 # ALG stopped Application Layer Gateway Service
32 # AppMgmt stopped Application Management
33 # appmgr running Remote Server Manager
35 # Output of new agent (>= 1.1.10i2):
36 # Alerter stopped/disabled Warndienst
37 # ALG running/demand Gatewaydienst auf Anwendungsebene
38 # Apple_Mobile_Device running/auto Apple Mobile Device
39 # AppMgmt stopped/demand Anwendungsverwaltung
40 # AudioSrv running/auto Windows Audio
41 # BITS running/demand Intelligenter Hintergrund<FC>bertragungsdienst
42 # Bonjour_Service running/auto Dienst "Bonjour"
44 inventory_services
= []
46 # Examples for inventory_services:
47 # inventory_services = [
48 # "HirnTest", # add service, if currently running
49 # "TapiSrv running", # the same
50 # "TermService auto", # add service, if start type is auto (regardless if running)
51 # "BackupSrv running/auto", # add, if start type is auto and it's running
52 # "~Backup.* running/auto", # same, but add all services matching a regex
53 # ( [ "termserver" ] , ALL_HOSTS, [ "HirnTest running", "Sppoller auto" ] ), # same with tags..
54 # ( ALL_HOSTS, [ "!Backup.*", "FooBar auto" ] ),
57 # Implemented in 1.2.1i2:
58 # New rule-style (WATO compatible) notation:
59 # [({'start_mode': 'demand', 'service': ['Netman']}, [], ['@all'], {'docu_url': ''})]
61 # <services> is list of regexes matching the service name
62 # <state> is the expected state to inventorize services of (running, stopped, ...)
63 # <start_mode> is the expected state to inventorize services of (auto, manual, ...)
65 # All above attributes can be set to None or not set to disable this filter option for the entry.
66 inventory_services_rules
= []
68 def inventory_windows_services(info
):
69 # Handle single entries (type str)
70 def add_matching_services(name
, description
, state
, start_type
, entry
):
71 if type(entry
) == tuple:
72 # New wato rule handling
76 elif ' ' in entry
and len(entry
.split()) == 2:
77 svc
, statespec
= entry
.split()
83 # First match name or description (optional since rule based config option available)
85 if svc
.startswith("~"):
87 if not r
.match(name
) and not r
.match(description
):
89 elif svc
!= name
and svc
!= description
:
92 if type(statespec
) == tuple:
93 # New wato rule handling (always given as tuple of two)
94 if (statespec
[0] and statespec
[0] != state
) \
95 or (statespec
[1] and statespec
[1] != start_type
):
99 for n
in statespec
.split("/"):
100 if n
not in [ state
, start_type
]:
105 # Handle entries like ( [ "term" ], ALL_HOSTS, [ "FooBar auto", ".*TEST running" ] )
106 def add_services_with_tags(name
, description
, state
, start_type
, entry
):
109 entry
= ( [], ) + entry
110 taglist
, hostlist
, svclist
= entry
111 if hosttags_match_taglist(tags_of_host(host_name()), taglist
):
112 if in_extraconf_hostlist(hostlist
, host_name()):
114 matching
+= add_matching_services(name
, description
, state
, start_type
, svc
)
117 # Filter WATO compatible rules by tags/hostlist
119 for rule
in inventory_services_rules
:
122 if options
.get("disabled"):
125 # 1. Get all rules matching the current host
126 taglist
, hostlist
= rule
[1:3]
127 if not hosttags_match_taglist(tags_of_host(host_name()), taglist
) \
128 or not in_extraconf_hostlist(hostlist
, host_name()):
131 # 2. Now extract the list of service regexes
133 svcs
= value
.get('services', [])
134 state
= value
.get('state', None)
135 start_mode
= value
.get('start_mode', None)
138 rules
.append(('~' + svc
, state
, start_mode
))
140 rules
.append((None, state
, start_mode
))
145 description
= " ".join(line
[3:])
147 state
, start_type
= line
[2].split('/')
150 start_type
= "unknown"
153 # Handle "old" inventory_services notation
155 for entry
in inventory_services
:
156 if type(entry
) == str:
157 inventory
+= add_matching_services(name
, description
, state
, start_type
, entry
)
158 elif type(entry
) == tuple:
159 inventory
+= add_services_with_tags(name
, description
, state
, start_type
, entry
)
161 raise MKGeneralException("Invalid entry %r in inventory_services" % entry
)
164 # New WATO compatible rule matching
168 inventory
+= add_matching_services(name
, description
, state
, start_type
, rule
)
173 # Format of parameters
175 # "states" : [ ( "running", "demand", 1 ),
176 # ( "stopped", None, 2 ) ],
180 def check_windows_services(item
, params
, info
):
181 # Hack for old manually defined checks:
183 params
= factory_settings
["services_default_levels"]
185 # A service may appear more than once (due to clusters).
186 # First make a list of all matching entries with their
190 # allow to match agains the internal name or agains the display name
192 display_name
= " ".join(line
[3:])
193 if item
== line
[1] or item
== display_name \
194 or line
[1] in params
['additional_servicenames'] \
195 or display_name
in params
['additional_servicenames']:
196 # newer agents also send start type as part of state,
199 state
, start_type
= line
[2].split('/')
202 start_type
= "unknown"
203 found
.append((line
[0], state
, start_type
, " ".join(line
[3:])))
206 return params
["else"], "service not found"
208 # We take the best found state (neccessary for clusters)
209 best_desc
, best_state
, best_info
, best_running_on
= None, None, None, None
210 for running_on
, state
, start_type
, desc
in found
:
211 for t_state
, t_start_type
, mon_state
in params
["states"]:
212 if (t_state
is None or t_state
== state
) \
213 and (t_start_type
is None or t_start_type
== start_type
):
214 this_state
= mon_state
217 this_state
= params
["else"]
219 if best_state
is None or this_state
< best_state
:
220 best_state
= this_state
221 best_info
= state
, start_type
222 best_running_on
= running_on
225 infotext
= best_desc
+ ": %s (start type is %s)" % best_info
226 if best_running_on
and best_state
!= 2: #if best state ist critical, there should no message "running on"
227 infotext
+= " (running on: %s)" % best_running_on
229 return (best_state
, infotext
)
232 factory_settings
["services_default_levels"] = {
233 "states" : [ ( "running", None, 0 ) ],
235 "additional_servicenames" : [],
238 check_info
['services'] = {
239 "check_function" : check_windows_services
,
240 "inventory_function" : inventory_windows_services
,
241 "service_description" : "Service %s",
243 "group" : "services",
244 "default_levels_variable" : "services_default_levels",
247 factory_settings
["services_summary_default_levels"] = {
249 "state_if_stopped": 0
252 def inventory_services_summary(info
):
254 return [ (None, "services_summary_default_levels") ]
256 def check_services_summary(item
, params
, info
):
257 blacklist
= params
.get("ignored", () )
262 # newer agents also send start type as part of state,
265 startstop
, auto
= line
[2].split('/')
272 if startstop
== "stopped":
274 for srv
in blacklist
:
275 if re
.match(srv
,srv_name
):
278 stoplist
.append(srv_name
)
282 num_stoplist
= len(stoplist
)
285 if len(stoplist
) > 0:
286 stopped_srvs
= " ("+", ".join(stoplist
)+")"
287 state
= params
.get("state_if_stopped")
300 infotext
= "%d services, %d services in autostart - of which %d services are stopped%s%s, %d services stopped but ignored" % \
301 ( num_srv
, num_auto
, num_stoplist
, sym
, stopped_srvs
, num_blacklist
)
303 return state
, infotext
305 check_info
['services.summary'] = {
306 "check_function" : check_services_summary
,
307 "inventory_function" : inventory_services_summary
,
308 "default_levels_variable" : "services_summary_default_levels",
309 "service_description" : "Services Summary",
311 "group" : "services_summary",