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.
36 import urllib3
# type: ignore
37 from pathlib2
import Path
39 import cmk
.utils
.password_store
41 cmk
.utils
.password_store
.replace_passwords()
43 urllib3
.disable_warnings(urllib3
.exceptions
.InsecureRequestWarning
)
45 # tell requests not to honour "http(s)_proxy" env variables
54 USAGE: check_bi_aggr -b <BASE_URL> -a <AGGR_NAME> -u <USER> -s <SECRET>
55 [-m <AUTH_MODE>] [-r] [-n <HOSTNAME>] [-t <TIMEOUT>] [-d]
58 -b BASE_URL The base URL to the monitoring environment, e.g.
59 http://<hostname>/<site-id>
60 -a AGGR_NAME Name of the aggregation, not the aggregation group.
61 It is possible that there are multiple aggregations
62 with an equal name, but you should ensure, that it
63 is a unique one to prevent confusions
64 -u USER User-ID of an automation user which is permitted to
65 see all contents of the aggregation
66 -s SECRET Automation secret of the user
67 --use-automation-user Use credentials from the local "automation" user
68 -m AUTH_MODE Authentication mode, either "cookie", "basic", "digest"
69 or "kerberos", defaults to "cookie"
70 -t TIMEOUT HTTP connect timeout in seconds (Default: 60)
71 -r track downtimes. This requires the hostname to be set.
72 -n HOSTNAME The hostname for which this check is run.
73 --in-downtime S S can be "ok" or "warn". Force this state if the
74 aggregate is in scheduled downtime. OK states will always
76 --acknowledged S Same as --in-downtime, but for acknowledged aggregates.
78 -h, --help Show this help message and exit
83 short_options
= 'b:a:u:s:m:t:n:dhr'
84 long_options
= ["help", "in-downtime=", "acknowledged=", "use-automation-user"]
87 opts
, args
= getopt
.getopt(sys
.argv
[1:], short_options
, long_options
)
88 except getopt
.GetoptError
, err
:
89 sys
.stderr
.write("%s\n" % err
)
97 use_automation_user
= False
102 opt_in_downtime
= None
103 opt_acknowledged
= None
104 track_downtime
= False
108 if o
in ['-h', '--help']:
124 track_downtime
= True
129 elif o
== '--in-downtime':
131 elif o
== '--acknowledged':
133 elif o
== '--use-automation-user':
134 use_automation_user
= True
137 sys
.stderr
.write('Please provide the URL to the monitoring instance.\n')
142 sys
.stderr
.write('Please provide the name of the aggregation.\n')
146 if use_automation_user
:
147 username
= "automation"
148 secret_file_path
= Path(cmk
.utils
.paths
.var_dir
) / "web" / username
/ "automation.secret"
150 with secret_file_path
.open(encoding
="utf-8") as f
: # pylint: disable=no-member
153 sys
.stderr
.write('Unable to read credentials for "automation" user.\n')
156 if not username
or not password
:
157 sys
.stderr
.write('Please provide valid user credentials.\n')
161 if track_downtime
and not hostname
:
162 sys
.stderr
.write('Please provide a hostname when using downtime tracking.\n')
169 if username
and password
:
170 if auth_mode
== 'kerberos':
171 from requests_kerberos
import HTTPKerberosAuth
# type: ignore
173 from subprocess
import Popen
, PIPE
174 kinit
= Popen(["kinit", username
], stdin
=PIPE
, stdout
=PIPE
, stderr
=PIPE
)
175 output
, errors
= kinit
.communicate("%s\n" % password
)
177 if kinit
.returncode
or errors
:
178 sys
.stderr
.write("Error getting Kerberos Ticket:\n")
180 "stdout: %s\nstderr: %s\nrc: %s" % (output
, errors
, kinit
.returncode
))
183 auth_obj
= HTTPKerberosAuth(principal
=username
)
184 elif auth_mode
== 'digest':
185 auth_obj
= requests
.auth
.HTTPDigestAuth(username
, password
)
187 auth_obj
= requests
.auth
.HTTPBasicAuth(username
, password
)
190 url
= "%s/check_mk/view.py" \
191 "?view_name=aggr_single_api" \
192 "&aggr_name=%s&output_format=python" % \
193 (base_url
.rstrip('/'), urllib
.quote(aggr_name
))
196 if auth_mode
in ['basic', 'digest', 'kerberos']:
199 url
+= "&_username=%s&_secret=%s" % \
203 sys
.stderr
.write('URL: %s\n' % url
)
206 r
= requests
.get(url
, timeout
=timeout
, auth
=auth
, proxies
=proxies
)
208 raw_response
= r
.text
209 except requests
.Timeout
:
210 sys
.stdout
.write('ERROR: Socket timeout while opening URL: %s\n' % (url
))
212 except requests
.URLRequired
, e
:
213 sys
.stdout
.write("UNKNOWN: %s\n" % e
)
217 'ERROR: Exception while opening URL: %s - %s\n%s' % (url
, e
, traceback
.format_exc()))
220 if raw_response
.startswith("ERROR:"):
221 sys
.stdout
.write(raw_response
.rstrip() + "\n")
225 obj
= ast
.literal_eval(raw_response
)
227 sys
.stdout
.write('ERROR: Invalid response (%s): %s\n' % (e
, raw_response
))
232 'ERROR: Aggregation "%s" does not exist or user is not permitted\n' % aggr_name
)
235 if not isinstance(obj
, list):
236 sys
.stdout
.write('ERROR: Invalid response: %s\n' % (raw_response
.replace("\n", "")))
240 row
= dict(zip(headers
, obj
[1]))
242 aggr_output
= row
["aggr_output"]
243 aggr_state
= int(row
["aggr_state_num"])
248 if aggr_output
== '':
249 aggr_output
= 'Aggregation state is %s' % ['OK', 'WARN', 'CRIT', 'UNKNOWN'][aggr_state
]
251 # Handle downtimes and acknowledgements
252 if opt_in_downtime
and row
["aggr_in_downtime"] == '1':
253 aggr_output
+= ", currently in downtime"
254 if opt_in_downtime
== "ok":
257 aggr_state
= min(aggr_state
, 1)
260 # connect to livestatus
264 sys
.stderr
.write('The python livestatus api module is missing. Please install from\n'
265 'Check_MK livestatus sources to a python import path.\n')
268 socket_path
= os
.environ
['OMD_ROOT'] + '/tmp/run/live'
270 conn
= livestatus
.SingleSiteConnection('unix:' + socket_path
)
273 # find out if, according to previous tracking, there already is a downtime
274 ids
= conn
.query_table(("GET downtimes\n"
276 "Filter: service_description = Aggr Host %s\n"
277 "Filter: author = tracking\n"
278 "Filter: end_time > %d") % (hostname
, now
))
279 downtime_tracked
= len(ids
) > 0
280 if downtime_tracked
!= (row
["aggr_in_downtime"] == '1'):
281 # there is a discrepance between tracked downtime state and the real state
282 if row
["aggr_in_downtime"] == '1':
283 # need to track downtime
284 conn
.command("[%d] SCHEDULE_SVC_DOWNTIME;%s;Aggr Host %s;%d;%d;1;0;0;"
285 "tracking;Automatic downtime" % (now
, hostname
, hostname
, now
, 2147483647))
288 conn
.command("[%d] DEL_SVC_DOWNTIME;%d" % (now
, dt_id
[0]))
290 if opt_acknowledged
and row
["aggr_acknowledged"] == '1':
291 aggr_output
+= ", is acknowledged"
292 if opt_acknowledged
== "ok":
295 aggr_state
= min(aggr_state
, 1)
297 sys
.stdout
.write('%s\n' % aggr_output
)