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 inventory_services
= []
45 # Examples for inventory_services:
46 # inventory_services = [
47 # "HirnTest", # add service, if currently running
48 # "TapiSrv running", # the same
49 # "TermService auto", # add service, if start type is auto (regardless if running)
50 # "BackupSrv running/auto", # add, if start type is auto and it's running
51 # "~Backup.* running/auto", # same, but add all services matching a regex
52 # ( [ "termserver" ] , ALL_HOSTS, [ "HirnTest running", "Sppoller auto" ] ), # same with tags..
53 # ( ALL_HOSTS, [ "!Backup.*", "FooBar auto" ] ),
56 # Implemented in 1.2.1i2:
57 # New rule-style (WATO compatible) notation:
58 # [({'start_mode': 'demand', 'service': ['Netman']}, [], ['@all'], {'docu_url': ''})]
60 # <services> is list of regexes matching the service name
61 # <state> is the expected state to inventorize services of (running, stopped, ...)
62 # <start_mode> is the expected state to inventorize services of (auto, manual, ...)
64 # All above attributes can be set to None or not set to disable this filter option for the entry.
65 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 isinstance(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 isinstance(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 isinstance(entry
, str):
157 inventory
+= add_matching_services(name
, description
, state
, start_type
, entry
)
158 elif isinstance(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 ) ],
181 def check_windows_services(item
, params
, info
):
182 # Hack for old manually defined checks:
184 params
= factory_settings
["services_default_levels"]
186 # A service may appear more than once (due to clusters).
187 # First make a list of all matching entries with their
191 # allow to match agains the internal name or agains the display name
193 display_name
= " ".join(line
[3:])
194 if item
== line
[1] or item
== display_name \
195 or line
[1] in params
['additional_servicenames'] \
196 or display_name
in params
['additional_servicenames']:
197 # newer agents also send start type as part of state,
200 state
, start_type
= line
[2].split('/')
203 start_type
= "unknown"
204 found
.append((line
[0], state
, start_type
, " ".join(line
[3:])))
207 return params
["else"], "service not found"
209 # We take the best found state (neccessary for clusters)
210 best_desc
, best_state
, best_info
, best_running_on
= None, None, None, None
211 for running_on
, state
, start_type
, desc
in found
:
212 for t_state
, t_start_type
, mon_state
in params
["states"]:
213 if (t_state
is None or t_state
== state
) \
214 and (t_start_type
is None or t_start_type
== start_type
):
215 this_state
= mon_state
218 this_state
= params
["else"]
220 if best_state
is None or this_state
< best_state
:
221 best_state
= this_state
222 best_info
= state
, start_type
223 best_running_on
= running_on
226 infotext
= best_desc
+ ": %s (start type is %s)" % best_info
227 if best_running_on
and best_state
!= 2: #if best state ist critical, there should no message "running on"
228 infotext
+= " (running on: %s)" % best_running_on
230 return (best_state
, infotext
)
233 factory_settings
["services_default_levels"] = {
234 "states": [("running", None, 0)],
236 "additional_servicenames": [],
239 check_info
['services'] = {
240 "check_function": check_windows_services
,
241 "inventory_function": inventory_windows_services
,
242 "service_description": "Service %s",
245 "default_levels_variable": "services_default_levels",
248 factory_settings
["services_summary_default_levels"] = {"ignored": [], "state_if_stopped": 0}
251 def inventory_services_summary(info
):
253 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
306 check_info
['services.summary'] = {
307 "check_function": check_services_summary
,
308 "inventory_function": inventory_services_summary
,
309 "default_levels_variable": "services_summary_default_levels",
310 "service_description": "Services Summary",
312 "group": "services_summary",