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 """Mode for managing sites"""
31 import cmk
.gui
.config
as config
32 import cmk
.gui
.watolib
as watolib
33 import cmk
.gui
.userdb
as userdb
34 import cmk
.gui
.forms
as forms
35 import cmk
.gui
.table
as table
37 from cmk
.gui
.plugins
.wato
.utils
import mode_registry
, sort_sites
38 from cmk
.gui
.plugins
.wato
.utils
.base_modes
import WatoMode
39 from cmk
.gui
.plugins
.wato
.utils
.html_elements
import wato_html_head
, wato_confirm
40 from cmk
.gui
.plugins
.wato
.utils
.context_buttons
import global_buttons
41 from cmk
.gui
.i18n
import _
42 from cmk
.gui
.globals import html
43 from cmk
.gui
.exceptions
import MKUserError
44 from cmk
.gui
.log
import logger
46 from cmk
.gui
.wato
.pages
.global_settings
import GlobalSettingsMode
49 # TODO: Rename to SitesMode()
50 class ModeSites(WatoMode
):
52 super(ModeSites
, self
).__init
__()
53 self
._site
_mgmt
= watolib
.SiteManagementFactory().factory()
59 @mode_registry.register
60 class ModeEditSite(ModeSites
):
70 super(ModeEditSite
, self
).__init
__()
71 self
._from
_html
_vars
()
73 self
._new
= self
._site
_id
== None
75 configured_sites
= self
._site
_mgmt
.load_sites()
78 self
._site
= configured_sites
[self
._clone
_id
]
81 self
._site
= {"replicate_mkps": True}
84 self
._site
= configured_sites
.get(self
._site
_id
, {})
86 def _from_html_vars(self
):
87 self
._site
_id
= html
.var("edit")
88 self
._clone
_id
= html
.var("clone")
89 self
._id
= html
.var("id")
90 self
._url
_prefix
= html
.var("url_prefix", "").strip()
91 self
._timeout
= html
.var("timeout", "").strip()
92 self
._sh
_site
= html
.var("sh_site")
93 self
._sh
_host
= html
.var("sh_host")
94 self
._repl
= html
.var("replication")
95 self
._multisiteurl
= html
.var("multisiteurl", "").strip()
99 return _("Create new site connection")
100 return _("Edit site connection %s") % html
.render_tt(self
._site
_id
)
103 super(ModeEditSite
, self
).buttons()
104 html
.context_button(_("All Sites"), watolib
.folder_preserving_link([("mode", "sites")]), "back")
105 if not self
._new
and self
._site
.get("replication"):
106 html
.context_button(_("Site-Globals"),
107 watolib
.folder_preserving_link([("mode", "edit_site_globals"),
108 ("site", self
._site
_id
)]), "configuration")
111 if not html
.check_transaction():
115 self
._id
= self
._id
.strip()
117 self
._id
= self
._site
_id
119 configured_sites
= self
._site
_mgmt
.load_sites()
120 if self
._new
and self
._id
in configured_sites
:
121 raise MKUserError("id", _("This id is already being used by another connection."))
123 if not re
.match("^[-a-z0-9A-Z_]+$", self
._id
):
124 raise MKUserError("id", _("The site id must consist only of letters, digit and the underscore."))
126 detail_msg
= self
._set
_site
_attributes
()
127 configured_sites
[self
._id
] = self
._new
_site
128 self
._site
_mgmt
.save_sites(configured_sites
)
131 msg
= _("Created new connection to site %s") % html
.render_tt(self
._id
)
133 msg
= _("Modified site connection %s") % html
.render_tt(self
._id
)
135 # Don't know exactly what have been changed, so better issue a change
136 # affecting all domains
138 "edit-sites", msg
, sites
=[self
._id
], domains
=watolib
.ConfigDomain
.enabled_domains())
140 # In case a site is not being replicated anymore, confirm all changes for this site!
142 watolib
.clear_site_replication_status(self
._id
)
144 if self
._id
!= config
.omd_site():
145 # On central site issue a change only affecting the GUI
147 "edit-sites", msg
, sites
=[config
.omd_site()], domains
=[watolib
.ConfigDomainGUI
])
149 return "sites", detail_msg
151 def _set_site_attributes(self
):
152 # Save copy of old site for later
153 configured_sites
= self
._site
_mgmt
.load_sites()
155 old_site
= configured_sites
[self
._site
_id
]
158 self
._new
_site
["alias"] = html
.get_unicode_input("alias", "").strip()
160 self
._new
_site
["url_prefix"] = self
._url
_prefix
161 self
._new
_site
["disabled"] = html
.get_checkbox("disabled")
164 vs_connection
= self
._site
_mgmt
.connection_method_valuespec()
165 method
= vs_connection
.from_html_vars("method")
166 vs_connection
.validate_value(method
, "method")
167 if isinstance(method
, tuple) and method
[0] in ["unix", "tcp"]:
168 if method
[0] == "unix":
169 self
._new
_site
["socket"] = "unix:" + method
[1]
171 self
._new
_site
["socket"] = "tcp:%s:%d" % method
[1]
173 self
._new
_site
["socket"] = method
175 elif "socket" in self
._new
_site
:
176 del self
._new
_site
["socket"]
179 if self
._timeout
!= "":
181 self
._new
_site
["timeout"] = int(self
._timeout
)
183 raise MKUserError("timeout", _("The timeout %s is not a valid integer number.") % self
._timeout
)
186 self
._new
_site
["persist"] = html
.get_checkbox("persist")
190 self
._new
_site
["status_host"] = (self
._sh
_site
, self
._sh
_host
)
192 self
._new
_site
["status_host"] = None
195 if self
._repl
== "none":
197 self
._new
_site
["replication"] = self
._repl
198 self
._new
_site
["multisiteurl"] = self
._multisiteurl
200 # Save Multisite-URL even if replication is turned off. That way that
201 # setting is not lost if replication is turned off for a while.
204 self
._new
_site
["disable_wato"] = html
.get_checkbox("disable_wato")
206 # Handle the insecure replication flag
207 self
._new
_site
["insecure"] = html
.get_checkbox("insecure")
209 # Allow direct user login
210 self
._new
_site
["user_login"] = html
.get_checkbox("user_login")
212 # User synchronization
213 user_sync
= self
._site
_mgmt
.user_sync_valuespec().from_html_vars("user_sync")
214 self
._new
_site
["user_sync"] = user_sync
216 # Event Console Replication
217 self
._new
_site
["replicate_ec"] = html
.get_checkbox("replicate_ec")
220 self
._new
_site
["replicate_mkps"] = html
.get_checkbox("replicate_mkps")
222 # Secret is not checked here, just kept
223 if not self
._new
and "secret" in old_site
:
224 self
._new
_site
["secret"] = old_site
["secret"]
226 # Do not forget to add those settings (e.g. "globals") that
227 # are not edited with this dialog
229 for key
in old_site
.keys():
230 if key
not in self
._new
_site
and key
!= "socket":
231 self
._new
_site
[key
] = old_site
[key
]
233 self
._site
_mgmt
.validate_configuration(self
._site
_id
or self
._id
, self
._new
_site
,
237 html
.begin_form("site")
239 self
._page
_basic
_settings
()
240 self
._page
_livestatus
_settings
()
241 self
._page
_replication
_configuration
()
244 html
.button("save", _("Save"))
248 def _page_basic_settings(self
):
249 forms
.header(_("Basic settings"))
251 forms
.section(_("Site ID"), simple
= not self
._new
)
253 html
.text_input("id", self
._site
_id
or self
._clone
_id
)
256 html
.write_text(self
._site
_id
)
258 html
.help(_("The site ID must be identical (case sensitive) with the instance's exact name."))
260 forms
.section(_("Alias"))
261 html
.text_input("alias", self
._site
.get("alias", ""), size
=60)
263 html
.set_focus("alias")
264 html
.help(_("An alias or description of the site."))
266 def _page_livestatus_settings(self
):
267 forms
.header(_("Livestatus settings"))
268 forms
.section(_("Connection"))
269 method
= self
._site
.get("socket", None)
271 if isinstance(method
, str) and method
.startswith("unix:"):
272 method
= ('unix', method
[5:])
274 elif isinstance(method
, str) and method
.startswith("tcp:"):
275 parts
= method
.split(":")[1:] # pylint: disable=no-member
276 method
= ('tcp', (parts
[0], int(parts
[1])))
278 self
._site
_mgmt
.connection_method_valuespec().render_input("method", method
)
279 html
.help( _("When connecting to remote site please make sure "
280 "that Livestatus over TCP is activated there. You can use UNIX sockets "
281 "to connect to foreign sites on localhost. Please make sure that this "
282 "site has proper read and write permissions to the UNIX socket of the "
286 forms
.section(_("Connect Timeout"))
287 timeout
= self
._site
.get("timeout", 10)
288 html
.number_input("timeout", timeout
, size
=2)
289 html
.write_text(_(" seconds"))
290 html
.help(_("This sets the time that Multisite waits for a connection "
291 "to the site to be established before the site is considered to be unreachable. "
292 "If not set, the operating system defaults are begin used and just one login attempt is being. "
295 # Persistent connections
296 forms
.section(_("Persistent Connection"), simple
=True)
297 html
.checkbox("persist", self
._site
.get("persist", False), label
=_("Use persistent connections"))
298 html
.help(_("If you enable persistent connections then Multisite will try to keep open "
299 "the connection to the remote sites. This brings a great speed up in high-latency "
300 "situations but locks a number of threads in the Livestatus module of the target site."))
303 docu_url
= "https://mathias-kettner.com/checkmk_multisite_modproxy.html"
304 forms
.section(_("URL prefix"))
305 html
.text_input("url_prefix", self
._site
.get("url_prefix", ""), size
=60)
306 html
.help(_("The URL prefix will be prepended to links of addons like PNP4Nagios "
307 "or the classical Nagios GUI when a link to such applications points to a host or "
308 "service on that site. You can either use an absolute URL prefix like <tt>http://some.host/mysite/</tt> "
309 "or a relative URL like <tt>/mysite/</tt>. When using relative prefixes you needed a mod_proxy "
310 "configuration in your local system apache that proxies such URLs to the according remote site. "
311 "Please refer to the <a target=_blank href='%s'>online documentation</a> for details. "
312 "The prefix should end with a slash. Omit the <tt>/pnp4nagios/</tt> from the prefix.") % docu_url
)
315 docu_url
= "https://mathias-kettner.com/checkmk_multisite_statushost.html"
316 forms
.section(_("Status host"))
318 sh
= self
._site
.get("status_host")
320 self
._sh
_site
, self
._sh
_host
= sh
325 html
.write_text(_("host: "))
326 html
.text_input("sh_host", self
._sh
_host
, size
=10)
327 html
.write_text(_(" on monitoring site: "))
329 choices
= [ ("", _("(no status host)")) ] + [ (sk
, si
.get("alias", sk
)) for (sk
, si
) in self
._site
_mgmt
.load_sites().items() ]
330 html
.dropdown("sh_site", choices
, deflt
=self
._sh
_site
, ordered
=True)
332 html
.help( _("By specifying a status host for each non-local connection "
333 "you prevent Multisite from running into timeouts when remote sites do not respond. "
334 "You need to add the remote monitoring servers as hosts into your local monitoring "
335 "site and use their host state as a reachability state of the remote site. Please "
336 "refer to the <a target=_blank href='%s'>online documentation</a> for details.") % docu_url
)
339 forms
.section(_("Disable"), simple
=True)
340 html
.checkbox("disabled", self
._site
.get("disabled", False), label
= _("Temporarily disable this connection"))
341 html
.help( _("If you disable a connection, then no data of this site will be shown in the status GUI. "
342 "The replication is not affected by this, however."))
344 def _page_replication_configuration(self
):
346 forms
.header(_("Configuration Replication (Distributed WATO)"))
347 forms
.section(_("Replication method"))
348 html
.dropdown("replication",
349 [ (None, _("No replication with this site")),
350 ("slave", _("Slave: push configuration to this site"))
351 ], deflt
=self
._site
.get("replication"))
352 html
.help( _("WATO replication allows you to manage several monitoring sites with a "
353 "logically centralized WATO. Slave sites receive their configuration "
354 "from master sites. <br><br>Note: Slave sites "
355 "do not need any replication configuration. They will be remote-controlled "
356 "by the master sites."))
358 forms
.section(_("Multisite-URL of remote site"))
359 html
.text_input("multisiteurl", self
._site
.get("multisiteurl", ""), size
=60)
360 html
.help( _("URL of the remote Check_MK including <tt>/check_mk/</tt>. "
361 "This URL is in many cases the same as the URL-Prefix but with <tt>check_mk/</tt> "
362 "appended, but it must always be an absolute URL. Please note, that "
363 "that URL will be fetched by the Apache server of the local "
364 "site itself, whilst the URL-Prefix is used by your local Browser."))
366 forms
.section(_("WATO"), simple
=True)
367 html
.checkbox("disable_wato", self
._site
.get("disable_wato", True),
368 label
= _('Disable configuration via WATO on this site'))
369 html
.help( _('It is a good idea to disable access to WATO completely on the slave site. '
370 'Otherwise a user who does not now about the replication could make local '
371 'changes that are overridden at the next configuration activation.'))
373 forms
.section(_("SSL"), simple
=True)
374 html
.checkbox("insecure", self
._site
.get("insecure", False),
375 label
= _('Ignore SSL certificate errors'))
376 html
.help( _('This might be needed to make the synchronization accept problems with '
377 'SSL certificates when using an SSL secured connection.'))
379 forms
.section(_('Direct login to Web GUI allowed'), simple
=True)
380 html
.checkbox('user_login', self
._site
.get('user_login', True),
381 label
= _('Users are allowed to directly login into the Web GUI of this site'))
382 html
.help(_('When enabled, this site is marked for synchronisation every time a Web GUI '
383 'related option is changed in the master site.'))
385 forms
.section(_("Sync with LDAP connections"), simple
=True)
386 self
._site
_mgmt
.user_sync_valuespec().render_input(
388 self
._site
.get("user_sync",
389 None if self
._new
else userdb
.user_sync_default_config(self
._site
_id
)))
391 html
.help(_('By default the users are synchronized automatically in the interval configured '
392 'in the connection. For example the LDAP connector synchronizes the users every '
393 'five minutes by default. The interval can be changed for each connection '
394 'individually in the <a href="wato.py?mode=ldap_config">connection settings</a>. '
395 'Please note that the synchronization is only performed on the master site in '
396 'distributed setups by default.<br>'
397 'The remote sites don\'t perform automatic user synchronizations with the '
398 'configured connections. But you can configure each site to either '
399 'synchronize the users with all configured connections or a specific list of '
402 if config
.mkeventd_enabled
:
403 forms
.section(_('Event Console'), simple
=True)
404 html
.checkbox('replicate_ec', self
._site
.get("replicate_ec", True),
405 label
= _("Replicate Event Console configuration to this site"))
406 html
.help(_("This option enables the distribution of global settings and rules of the Event Console "
407 "to the remote site. Any change in the local Event Console settings will mark the site "
408 "as <i>need sync</i>. A synchronization will automatically reload the Event Console of "
411 forms
.section(_("Extensions"), simple
=True)
412 html
.checkbox("replicate_mkps", self
._site
.get("replicate_mkps", False),
413 label
= _("Replicate extensions (MKPs and files in <tt>~/local/</tt>)"))
414 html
.help(_("If you enable the replication of MKPs then during each <i>Activate Changes</i> MKPs "
415 "that are installed on your master site and all other files below the <tt>~/local/</tt> "
416 "directory will be also transferred to the slave site. Note: <b>all other MKPs and files "
417 "below <tt>~/local/</tt> on the slave will be removed</b>."))
420 @mode_registry.register
421 class ModeDistributedMonitoring(ModeSites
):
427 def permissions(cls
):
431 return _("Distributed Monitoring")
434 super(ModeDistributedMonitoring
, self
).buttons()
435 html
.context_button(_("New connection"),
436 watolib
.folder_preserving_link([("mode", "edit_site")]),
440 delete_id
= html
.var("_delete")
441 if delete_id
and html
.transaction_valid():
442 self
._action
_delete
(delete_id
)
444 logout_id
= html
.var("_logout")
446 return self
._action
_logout
(logout_id
)
448 login_id
= html
.var("_login")
450 return self
._action
_login
(login_id
)
452 def _action_delete(self
, delete_id
):
453 configured_sites
= self
._site
_mgmt
.load_sites()
454 # The last connection can always be deleted. In that case we
455 # fall back to non-distributed-WATO and the site attribute
457 test_sites
= dict(configured_sites
.items())
458 del test_sites
[delete_id
]
460 # Make sure that site is not being used by hosts and folders
461 if delete_id
in watolib
.Folder
.root_folder().all_site_ids():
462 search_url
= html
.makeactionuri([
463 ("host_search_change_site", "on"),
464 ("host_search_site", delete_id
),
465 ("host_search", "1"),
468 ("filled_in", "edit_host"),
470 raise MKUserError(None,
471 _("You cannot delete this connection. It has folders/hosts "
472 "assigned to it. You can use the <a href=\"%s\">host "
473 "search</a> to get a list of the hosts.") % search_url
)
476 c
= wato_confirm(_("Confirm deletion of site %s") % html
.render_tt(delete_id
),
477 _("Do you really want to delete the connection to the site %s?") % \
478 html
.render_tt(delete_id
))
480 self
._site
_mgmt
.delete_site(delete_id
)
488 def _action_logout(self
, logout_id
):
489 configured_sites
= self
._site
_mgmt
.load_sites()
490 site
= configured_sites
[logout_id
]
491 c
= wato_confirm(_("Confirm logout"),
492 _("Do you really want to log out of '%s'?") % \
493 html
.render_tt(site
["alias"]))
497 self
._site
_mgmt
.save_sites(configured_sites
)
498 watolib
.add_change("edit-site", _("Logged out of remote site %s") % html
.render_tt(site
["alias"]),
499 domains
=[watolib
.ConfigDomainGUI
], sites
=[watolib
.default_site()])
500 return None, _("Logged out.")
508 def _action_login(self
, login_id
):
509 configured_sites
= self
._site
_mgmt
.load_sites()
510 if html
.var("_abort"):
513 if not html
.check_transaction():
516 site
= configured_sites
[login_id
]
518 # Fetch name/password of admin account
519 if html
.has_var("_name"):
520 name
= html
.var("_name", "").strip()
521 passwd
= html
.var("_passwd", "").strip()
523 secret
= watolib
.do_site_login(login_id
, name
, passwd
)
524 site
["secret"] = secret
525 self
._site
_mgmt
.save_sites(configured_sites
)
526 message
= _("Successfully logged into remote site %s.") % html
.render_tt(site
["alias"])
527 watolib
.log_audit(None, "edit-site", message
)
530 except watolib
.MKAutomationException
, e
:
531 error
= _("Cannot connect to remote site: %s") % e
533 except MKUserError
, e
:
534 html
.add_user_error(e
.varname
, e
)
541 html
.add_user_error("_name", error
)
542 error
= (_("Internal error: %s\n%s") % (e
, traceback
.format_exc())).replace("\n", "\n<br>")
544 wato_html_head(_("Login into site \"%s\"") % site
["alias"])
546 html
.show_error(error
)
548 html
.p(_("For the initial login into the slave site %s "
549 "we need once your administration login for the Multsite "
550 "GUI on that site. Your credentials will only be used for "
551 "the initial handshake and not be stored. If the login is "
552 "successful then both side will exchange a login secret "
553 "which is used for the further remote calls.") % html
.render_tt(site
["alias"]))
555 html
.begin_form("login", method
="POST")
556 forms
.header(_('Login credentials'))
557 forms
.section(_('Administrator name:'))
558 html
.text_input("_name")
559 html
.set_focus("_name")
560 forms
.section(_('Administrator password:'))
561 html
.password_input("_passwd")
563 html
.button("_do_login", _("Login"))
564 html
.button("_abort", _("Abort"))
565 html
.hidden_field("_login", login_id
)
572 table
.begin("sites", _("Connections to local and remote sites"),
573 empty_text
= _("You have not configured any local or remotes sites. Multisite will "
574 "implicitely add the data of the local monitoring site. If you add remotes "
575 "sites, please do not forget to add your local monitoring site also, if "
576 "you want to display its data."))
578 sites
= sort_sites(self
._site
_mgmt
.load_sites().items())
579 for site_id
, site
in sites
:
582 self
._page
_buttons
(site_id
, site
)
583 self
._page
_basic
_settings
(site_id
, site
)
584 self
._page
_livestatus
_settings
(site_id
, site
)
585 self
._page
_replication
_configuration
(site_id
, site
)
589 def _page_buttons(self
, site_id
, site
):
590 table
.cell(_("Actions"), css
="buttons")
591 edit_url
= watolib
.folder_preserving_link([("mode", "edit_site"), ("edit", site_id
)])
592 html
.icon_button(edit_url
, _("Properties"), "edit")
594 clone_url
= watolib
.folder_preserving_link([("mode", "edit_site"), ("clone", site_id
)])
595 html
.icon_button(clone_url
, _("Clone this connection in order to create a new one"), "clone")
597 delete_url
= html
.makeactionuri([("_delete", site_id
)])
598 html
.icon_button(delete_url
, _("Delete"), "delete")
600 if (config
.has_wato_slave_sites()
601 and (site
.get("replication") or config
.site_is_local(site_id
))) \
602 or watolib
.is_wato_slave_site():
603 globals_url
= watolib
.folder_preserving_link([("mode", "edit_site_globals"),
606 has_site_globals
= bool(site
.get("globals"))
607 title
= _("Site specific global configuration")
609 icon
= "site_globals_modified"
610 title
+= " (%s)" % (_("%d specific settings") % len(site
.get("globals")))
612 icon
= "site_globals"
614 html
.icon_button(globals_url
, title
, icon
)
616 def _page_basic_settings(self
, site_id
, site
):
617 table
.text_cell(_("ID"), site_id
)
618 table
.text_cell(_("Alias"), site
.get("alias", ""))
620 def _page_livestatus_settings(self
, site_id
, site
):
622 socket
= site
.get("socket", _("local site"))
623 if socket
== "disabled:":
624 socket
= _("don't query status")
625 table
.cell(_("Socket"))
626 if isinstance(socket
, tuple) and socket
[0] == "proxy":
627 html
.write_text(_("Use livestatus Proxy-Daemon"))
629 html
.write_text(socket
)
632 if site
.get("status_host"):
633 sh_site
, sh_host
= site
["status_host"]
634 table
.text_cell(_("Status host"), "%s/%s" % (sh_site
, sh_host
))
636 table
.text_cell(_("Status host"))
639 if site
.get("disabled", False) == True:
640 table
.text_cell(_("Disabled"), "<b>%s</b>" % _("yes"))
642 table
.text_cell(_("Disabled"), _("no"))
645 if "timeout" in site
:
646 table
.text_cell(_("Timeout"), _("%d sec") % int(site
["timeout"]), css
="number")
648 table
.text_cell(_("Timeout"), "")
651 if site
.get("persist", False):
652 table
.text_cell(_("Pers."), "<b>%s</b>" % _("yes"))
654 table
.text_cell(_("Pers."), _("no"))
656 def _page_replication_configuration(self
, site_id
, site
):
658 if site
.get("replication"):
660 if site
.get("replicate_ec"):
661 repl
+= ", " + _("EC")
662 if site
.get("replicate_mkps"):
663 repl
+= ", " + _("MKPs")
666 table
.text_cell(_("Replication"), repl
)
668 # Login-Button for Replication
669 table
.cell(_("Login"))
671 if site
.get("secret"):
672 logout_url
= watolib
.make_action_link([("mode", "sites"), ("_logout", site_id
)])
673 html
.buttonlink(logout_url
, _("Logout"))
675 login_url
= watolib
.make_action_link([("mode", "sites"), ("_login", site_id
)])
676 html
.buttonlink(login_url
, _("Login"))
679 @mode_registry.register
680 class ModeEditSiteGlobals(ModeSites
, GlobalSettingsMode
):
683 return "edit_site_globals"
686 def permissions(cls
):
690 super(ModeEditSiteGlobals
, self
).__init
__()
691 self
._site
_id
= html
.var("site")
692 self
._configured
_sites
= self
._site
_mgmt
.load_sites()
694 self
._site
= self
._configured
_sites
[self
._site
_id
]
696 raise MKUserError("site", _("This site does not exist."))
698 # 2. Values of global settings
699 self
._global
_settings
= watolib
.load_configuration_settings()
701 # 3. Site specific global settings
703 if watolib
.is_wato_slave_site():
704 self
._current
_settings
= watolib
.load_configuration_settings(site_specific
=True)
706 self
._current
_settings
= self
._site
.get("globals", {})
709 return _("Edit site specific global settings of %s") % \
710 html
.render_tt(self
._site
_id
)
713 super(ModeEditSiteGlobals
, self
).buttons()
714 html
.context_button(_("All Sites"),
715 watolib
.folder_preserving_link([("mode", "sites")]),
717 html
.context_button(_("Connection"),
718 watolib
.folder_preserving_link([("mode", "edit_site"),
719 ("edit", self
._site
_id
)]), "sites")
721 # TODO: Consolidate with ModeEditGlobals.action()
723 varname
= html
.var("_varname")
724 action
= html
.var("_action")
728 _domain
, valuespec
, need_restart
, _allow_reset
, _in_global_settings
= watolib
.configvars(
730 def_value
= self
._global
_settings
.get(varname
, self
._default
_values
[varname
])
732 if action
== "reset" and not watolib
.is_a_checkbox(valuespec
):
734 _("Removing site specific configuration variable"),
735 _("Do you really want to remove the configuration variable <b>%s</b> "
736 "of the specific configuration of this site and that way use the global value "
737 "of <b><tt>%s</tt></b>?") %
738 (varname
, valuespec
.value_to_text(def_value
)))
741 if not html
.check_transaction():
743 # No confirmation for direct toggle
747 if varname
in self
._current
_settings
:
748 self
._current
_settings
[varname
] = not self
._current
_settings
[varname
]
750 self
._current
_settings
[varname
] = not def_value
752 msg
= _("Changed site specific configuration variable %s to %s.") % \
753 (varname
, _("on") if self
._current
_settings
[varname
] else _("off"))
755 self
._site
.setdefault("globals", {})[varname
] = self
._current
_settings
[varname
]
756 self
._site
_mgmt
.save_sites(self
._configured
_sites
, activate
=False)
759 "edit-configvar", msg
, sites
=[self
._site
_id
], need_restart
=need_restart
)
761 if action
== "_reset":
762 return "edit_site_globals", msg
763 return "edit_site_globals"
771 def _edit_mode(self
):
772 return "edit_site_configvar"
775 html
.help(_("Here you can configure global settings, that should just be applied "
776 "on that site. <b>Note</b>: this only makes sense if the site "
777 "is part of a distributed setup."))
779 if not watolib
.is_wato_slave_site():
780 if not config
.has_wato_slave_sites():
781 html
.show_error(_("You can not configure site specific global settings "
782 "in non distributed setups."))
785 if not self
._site
.get("replication") and not config
.site_is_local(self
._site
_id
):
786 html
.show_error(_("This site is not the master site nor a replication slave. "
787 "You cannot configure specific settings for it."))
790 group_names
= self
._group
_names
(show_all
=True)
791 self
._show
_configuration
_variables
(group_names
)