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.
26 """Verify or find out a hosts agent related configuration"""
31 import cmk
.gui
.config
as config
32 import cmk
.gui
.watolib
as watolib
33 import cmk
.gui
.forms
as forms
34 from cmk
.gui
.exceptions
import MKAuthException
, MKGeneralException
, MKUserError
35 from cmk
.gui
.plugins
.wato
.utils
.base_modes
import WatoWebApiMode
36 from cmk
.gui
.i18n
import _
37 from cmk
.gui
.globals import html
38 from cmk
.gui
.plugins
.wato
.utils
.context_buttons
import host_status_button
40 from cmk
.gui
.valuespec
import (
51 from cmk
.gui
.plugins
.wato
import (
54 monitoring_macro_help
,
58 @mode_registry.register
59 class ModeDiagHost(WatoMode
):
66 return ["hosts", "diag_host"]
69 def diag_host_tests(cls
):
72 ('agent', _('Agent')),
73 ('snmpv1', _('SNMPv1')),
74 ('snmpv2', _('SNMPv2c')),
75 ('snmpv2_nobulk', _('SNMPv2c (without Bulkwalk)')),
76 ('snmpv3', _('SNMPv3')),
77 ('traceroute', _('Traceroute')),
81 self
._hostname
= html
.var("host")
82 if not self
._hostname
:
83 raise MKGeneralException(_('The hostname is missing.'))
85 self
._host
= watolib
.Folder
.current().host(self
._hostname
)
86 self
._host
.need_permission("read")
88 if self
._host
.is_cluster():
89 raise MKGeneralException(_('This page does not support cluster hosts.'))
92 return _('Diagnostic of host') + " " + self
._hostname
95 html
.context_button(_("Folder"), watolib
.folder_preserving_link([("mode", "folder")]), "back")
96 host_status_button(self
._hostname
, "hoststatus")
97 html
.context_button(_("Properties"), self
._host
.edit_url(), "edit")
98 if config
.user
.may('wato.rulesets'):
99 html
.context_button(_("Parameters"), self
._host
.params_url(), "rulesets")
100 html
.context_button(_("Services"), self
._host
.services_url(), "services")
103 if not html
.check_transaction():
108 self
._validate
_diag
_html
_vars
()
109 except MKUserError
, e
:
110 html
.add_user_error(e
.varname
, e
)
113 if html
.var('_save'):
114 # Save the ipaddress and/or community
115 vs_host
= self
._vs
_host
()
116 new
= vs_host
.from_html_vars('vs_host')
117 vs_host
.validate_value(new
, 'vs_host')
119 # If both snmp types have credentials set - snmpv3 takes precedence
121 if "ipaddress" in new
:
122 return_message
.append(_("IP address"))
123 if "snmp_v3_credentials" in new
:
124 if "snmp_community" in new
:
125 return_message
.append(_("SNMPv3 credentials (SNMPv2 community was discarded)"))
127 return_message
.append(_("SNMPv3 credentials"))
128 new
["snmp_community"] = new
["snmp_v3_credentials"]
129 elif "snmp_community" in new
:
130 return_message
.append(_("SNMP credentials"))
131 return_message
= _("Updated attributes: ") + ", ".join(return_message
)
133 self
._host
.update_attributes(new
)
135 html
.set_var("host", self
._hostname
)
136 html
.set_var("folder", watolib
.Folder
.current().path())
137 return "edit_host", return_message
139 def _validate_diag_html_vars(self
):
140 vs_host
= self
._vs
_host
()
141 host_vars
= vs_host
.from_html_vars("vs_host")
142 vs_host
.validate_value(host_vars
, "vs_host")
144 vs_rules
= self
._vs
_rules
()
145 rule_vars
= vs_rules
.from_html_vars("vs_rules")
146 vs_rules
.validate_value(rule_vars
, "vs_rules")
149 html
.open_div(class_
="diag_host")
154 html
.begin_form('diag_host', method
="POST")
155 html
.prevent_password_auto_completion()
157 forms
.header(_('Host Properties'))
159 forms
.section(legend
=False)
161 # The diagnose page shows both snmp variants at the same time
162 # We need to analyse the preconfigured community and set either the
163 # snmp_community or the snmp_v3_credentials
165 for key
, value
in self
._host
.attributes().items():
166 if key
== "snmp_community" and isinstance(value
, tuple):
167 vs_dict
["snmp_v3_credentials"] = value
171 vs_host
= self
._vs
_host
()
172 vs_host
.render_input("vs_host", vs_dict
)
173 html
.help(vs_host
.help())
177 html
.open_div(style
="margin-bottom:10px")
178 html
.button("_save", _("Save & Exit"))
181 forms
.header(_('Options'))
184 forms
.section(legend
=False)
185 vs_rules
= self
._vs
_rules
()
186 vs_rules
.render_input("vs_rules", value
)
187 html
.help(vs_rules
.help())
190 html
.button("_try", _("Test"))
196 html
.open_td(style
="padding-left:10px;")
198 self
._show
_diagnose
_output
()
200 def _show_diagnose_output(self
):
201 if not html
.var('_try'):
202 html
.message(_('You can diagnose the connection to a specific host using this dialog. '
203 'You can either test whether your current configuration is still working '
204 'or investigate in which ways a host can be reached. Simply configure the '
205 'connection options you like to try on the right side of the screen and '
206 'press the "Test" button. The results will be displayed here.'))
209 if html
.has_user_errors():
210 html
.show_user_errors()
214 # TODO: Insert any vs_host valuespec validation
215 # These tests can be called with invalid valuespec settings...
216 # TODO: Replace hard coded icon paths with dynamic ones to old or new theme
217 for ident
, title
in ModeDiagHost
.diag_host_tests():
219 html
.open_table(class_
=["data", "test"])
220 html
.open_tr(class_
=["data", "odd0"])
222 html
.open_td(class_
="icons")
224 html
.img("images/icon_reload.png", class_
="icon", id_
="%s_img" % ident
)
226 html
.img("images/icon_reload.png", class_
=["icon", "retry"], id_
="%s_retry" % ident
, title
=_('Retry this test'))
232 html
.div('', class_
="log", id="%s_log" % ident
)
237 html
.javascript('start_host_diag_test(%s, %s, %s)' %
238 (json
.dumps(ident
), json
.dumps(self
._hostname
),
239 json
.dumps(html
.transaction_manager
.fresh_transid())))
244 required_keys
= ['hostname'],
246 ('hostname', FixedValue(self
._hostname
,
247 title
= _('Hostname'),
250 ('ipaddress', HostAddress(
251 title
= _("IPv4 Address"),
253 allow_ipv6_address
= False,
255 ('snmp_community', Password(
256 title
= _("SNMPv1/2 community"),
259 ('snmp_v3_credentials',
260 cmk
.gui
.plugins
.wato
.SNMPCredentials(default_value
= None, only_v3
= True)
266 if config
.user
.may('wato.add_or_modify_executables'):
268 ('datasource_program', TextAscii(
269 title
= _("Datasource Program (<a href=\"%s\">Rules</a>)") % \
270 watolib
.folder_preserving_link([('mode', 'edit_ruleset'), ('varname', 'datasource_programs')]),
271 help = _("For agent based checks Check_MK allows you to specify an alternative "
272 "program that should be called by Check_MK instead of connecting the agent "
273 "via TCP. That program must output the agent's data on standard output in "
274 "the same format the agent would do. This is for example useful for monitoring "
275 "via SSH.") + monitoring_macro_help(),
282 optional_keys
= False,
284 ('agent_port', Integer(
288 default_value
= 6556,
289 title
= _("Check_MK Agent Port (<a href=\"%s\">Rules</a>)") % \
290 watolib
.folder_preserving_link([('mode', 'edit_ruleset'), ('varname', 'agent_ports')]),
291 help = _("This variable allows to specify the TCP port to "
292 "be used to connect to the agent on a per-host-basis.")
294 ('tcp_connect_timeout', Float(
299 display_format
= "%.0f", # show values consistent to
300 size
= 2, # SNMP-Timeout
301 title
= _("TCP Connection Timeout (<a href=\"%s\">Rules</a>)") % \
302 watolib
.folder_preserving_link([('mode', 'edit_ruleset'), ('varname', 'tcp_connect_timeouts')]),
303 help = _("This variable allows to specify a timeout for the "
304 "TCP connection to the Check_MK agent on a per-host-basis."
305 "If the agent does not respond within this time, it is considered to be unreachable.")
307 ('snmp_timeout', Integer(
309 title
= _("SNMP-Timeout (<a href=\"%s\">Rules</a>)") % \
310 watolib
.folder_preserving_link([('mode', 'edit_ruleset'), ('varname', 'snmp_timing')]),
311 help = _("After a request is sent to the remote SNMP agent we will wait up to this "
312 "number of seconds until assuming the answer get lost and retrying."),
318 ('snmp_retries', Integer(
320 title
= _("SNMP-Retries (<a href=\"%s\">Rules</a>)") % \
321 watolib
.folder_preserving_link([('mode', 'edit_ruleset'), ('varname', 'snmp_timing')]),
330 class ModeAjaxDiagHost(WatoWebApiMode
):
332 watolib
.init_wato_datastructures(with_wato_lock
=True)
334 if not config
.user
.may('wato.diag_host'):
335 raise MKAuthException(_('You are not permitted to perform this action.'))
337 if not html
.check_transaction():
338 raise MKAuthException(_("Invalid transaction"))
340 request
= self
.webapi_request()
342 hostname
= request
.get("host")
344 raise MKGeneralException(_('The hostname is missing.'))
346 host
= watolib
.Host
.host(hostname
)
349 raise MKGeneralException(_('The given host does not exist.'))
350 if host
.is_cluster():
351 raise MKGeneralException(_('This view does not support cluster hosts.'))
353 host
.need_permission("read")
355 _test
= request
.get('_test')
357 raise MKGeneralException(_('The test is missing.'))
359 # Execute a specific test
360 if _test
not in dict(ModeDiagHost
.diag_host_tests()).keys():
361 raise MKGeneralException(_('Invalid test.'))
363 # TODO: Use ModeDiagHost._vs_rules() for processing/validation?
365 for idx
, what
in enumerate([
371 'tcp_connect_timeout',
373 args
[idx
] = request
.get(what
, "")
375 if config
.user
.may('wato.add_or_modify_executables'):
376 args
[6] = request
.get("datasource_program", "")
378 if request
.get("snmpv3_use"):
383 }.get(request
.get("snmpv3_use"))
385 if snmpv3_use
!= "noAuthNoPriv":
386 snmpv3_auth_proto
= {
387 DropdownChoice
.option_id("md5"): "md5",
388 DropdownChoice
.option_id("sha"): "sha"
389 }.get(request
.get("snmpv3_auth_proto"))
390 args
[8] = snmpv3_auth_proto
391 args
[9] = request
.get("snmpv3_security_name")
392 args
[10] = request
.get("snmpv3_security_password")
393 if snmpv3_use
== "authPriv":
394 snmpv3_privacy_proto
= {
395 DropdownChoice
.option_id("DES"): "DES",
396 DropdownChoice
.option_id("AES"): "AES"
397 }.get(request
.get("snmpv3_privacy_proto"))
398 args
[11] = snmpv3_privacy_proto
399 args
[12] = request
.get("snmpv3_privacy_password")
401 args
[9] = request
.get("snmpv3_security_name")
403 result
= watolib
.check_mk_automation(host
.site_id(), "diag-host", [hostname
, _test
] + args
)
405 "next_transid": html
.transaction_manager
.fresh_transid(),
406 "status_code": result
[0],
411 cmk
.gui
.pages
.register_page_handler("wato_ajax_diag_host", lambda: ModeAjaxDiagHost().handle_page())