Module: check_mk
Branch: master
Commit: f3d2f550993f8a3bbe9e453b954cae3e2f798cbf
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=f3d2f550993f8a…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Mon Feb 25 08:02:34 2019 +0100
New generic item input validation method
When a dialog takes a parameter from HTTP variables that represents an
item of a collection, it normally searches for the item before
proceeding and raises an error in case it does not exist in the
collection.
This is done individually in many places with individual error messages
that all have to be localized individually. This new function does this
in a generic way and should reduce page individual code a bit.
Change-Id: I4b515f5d9c86a4e233d646fe3a22b4ad498d85e8
---
cmk/gui/htmllib.py | 8 ++++++++
cmk/gui/views.py | 14 +++-----------
2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/cmk/gui/htmllib.py b/cmk/gui/htmllib.py
index 9de825f..ab54b33 100644
--- a/cmk/gui/htmllib.py
+++ b/cmk/gui/htmllib.py
@@ -1151,6 +1151,14 @@ class html(HTMLGenerator):
_("The given text is wrong encoded. "
"You need to provide a UTF-8 encoded text."))
+ def get_item_input(self, varname, collection):
+ """Helper to get an item from the given collection
+ Raises a MKUserError() in case the requested item is not available."""
+ item = self.get_ascii_input(varname)
+ if item not in collection:
+ raise MKUserError(varname, _("The requested item %s does not exist") % item)
+ return collection[item], item
+
def get_integer_input(self, varname, deflt=None):
if deflt is not None and not self.request.has_var(varname):
return deflt
diff --git a/cmk/gui/views.py b/cmk/gui/views.py
index e53c389..effe3f3 100644
--- a/cmk/gui/views.py
+++ b/cmk/gui/views.py
@@ -451,13 +451,10 @@ def page_create_view(next_url=None):
@cmk.gui.pages.register("create_view_infos")
def page_create_view_infos():
- ds_name = html.request.var('datasource')
- if ds_name not in data_source_registry:
- raise MKGeneralException(_('The given datasource is not supported'))
-
+ ds_class, ds_name = html.get_item_input("datasource", data_source_registry)
visuals.page_create_visual(
'views',
- data_source_registry[ds_name]().infos,
+ ds_class().infos,
next_url='edit_view.py?mode=create&datasource=%s&single_infos=%%s' % ds_name)
@@ -907,12 +904,7 @@ def show_filter_form(is_open, filters):
@cmk.gui.pages.register("view")
def page_view():
- view_name = html.get_ascii_input("view_name")
- if view_name is None:
- raise MKUserError("view_name", _("Missing the variable view_name in the URL."))
- view = get_permitted_views().get(view_name)
- if not view:
- raise MKUserError("view_name", _("No view defined with the name '%s'.") % view_name)
+ view, view_name = html.get_item_input("view_name", get_permitted_views())
# Gather the page context which is needed for the "add to visual" popup menu
# to add e.g. views to dashboards or reports
Module: check_mk
Branch: master
Commit: f841b31ae8f57294e238575baddff591f2d4bfed
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=f841b31ae8f572…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Sun Feb 24 18:44:11 2019 +0100
7182 Improved GUI extension error handling
When extending the standard GUI functionality, using either a manually
installed <tt>local/share/check_mk/web</tt> plugin or a Check_MK extension
package (MKP), exceptions may occur while loading the plugin.
In previous versions these exceptions caused the whole GUI to fail making it
impossible to repair the problem using the GUI, for example via the extension
package manager of the CEE/CME.
The extension related loading errors are now all catched and logged to the
<tt>var/log/web.log</tt> instead of making the whole application fail. In
addition to this, an error message will be shown on the "Extension packages"
WATO page. We've also added a new Analyze configuration check "Broken GUI
extensions" which will report a CRIT state when broken GUI extensions are
found.
Change-Id: I8c1230a7c7a5df11242b76c24b0ea107df27546e
---
.werks/7182 | 23 +++++++++++++
cmk/gui/plugins/wato/ac_tests.py | 27 +++++++++++++++
cmk/gui/utils.py | 39 +++++++++++++++-------
.../cmk/gui/watolib/test_analyze_configuration.py | 1 +
4 files changed, 78 insertions(+), 12 deletions(-)
diff --git a/.werks/7182 b/.werks/7182
new file mode 100644
index 0000000..f78b439
--- /dev/null
+++ b/.werks/7182
@@ -0,0 +1,23 @@
+Title: Improved GUI extension error handling
+Level: 2
+Component: multisite
+Compatible: compat
+Edition: cre
+Version: 1.6.0i1
+Date: 1551029903
+Class: feature
+
+When extending the standard GUI functionality, using either a manually
+installed <tt>local/share/check_mk/web</tt> plugin or a Check_MK extension
+package (MKP), exceptions may occur while loading the plugin.
+
+In previous versions these exceptions caused the whole GUI to fail making it
+impossible to repair the problem using the GUI, for example via the extension
+package manager of the CEE/CME.
+
+The extension related loading errors are now all catched and logged to the
+<tt>var/log/web.log</tt> instead of making the whole application fail. In
+addition to this, an error message will be shown on the "Extension packages"
+WATO page. We've also added a new Analyze configuration check "Broken GUI
+extensions" which will report a CRIT state when broken GUI extensions are
+found.
diff --git a/cmk/gui/plugins/wato/ac_tests.py b/cmk/gui/plugins/wato/ac_tests.py
index ec191fb..f8213c1 100644
--- a/cmk/gui/plugins/wato/ac_tests.py
+++ b/cmk/gui/plugins/wato/ac_tests.py
@@ -30,6 +30,7 @@ import subprocess
import requests
import urllib3
+import cmk.gui.utils
import cmk.gui.userdb as userdb
import cmk.gui.sites as sites
import cmk.gui.watolib as watolib
@@ -771,6 +772,32 @@ class ACTestSizeOfExtensions(ACTest):
@ac_test_registry.register
+class ACTestBrokenGUIExtension(ACTest):
+ def category(self):
+ return ACTestCategories.deprecations
+
+ def title(self):
+ return _("Broken GUI extensions")
+
+ def help(self):
+ return _(
+ "Since 1.6.0i1 broken GUI extensions don't block the whole GUI initialization anymore. "
+ "Instead of this, the errors are logged in <tt>var/log/web.log</tt>. In addition to this, "
+ "the errors are displayed here.")
+
+ def is_relevant(self):
+ return True
+
+ def execute(self):
+ errors = cmk.gui.utils.get_failed_plugins()
+ if not errors:
+ yield ACResultOK(_("No broken extensions were found."))
+
+ for plugin_path, e in errors:
+ yield ACResultCRIT(_("Loading \"%s\" failed: %s") % (plugin_path, e))
+
+
+(a)ac_test_registry.register
class ACTestESXDatasources(ACTest):
def category(self):
return ACTestCategories.deprecations
diff --git a/cmk/gui/utils.py b/cmk/gui/utils.py
index 97e2457..a74a581 100644
--- a/cmk/gui/utils.py
+++ b/cmk/gui/utils.py
@@ -33,10 +33,12 @@ import re
import uuid
import marshal
import urlparse
+import itertools
import cmk.utils.paths
from cmk.gui.i18n import _
+from cmk.gui.log import logger
from cmk.gui.exceptions import MKUserError
@@ -158,13 +160,17 @@ def gen_id():
return str(uuid.uuid4())
-# Load all files below share/check_mk/web/plugins/WHAT into a
-# specified context (global variables). Also honors the
-# local-hierarchy for OMD
-# TODO: Couldn't we precompile all our plugins during packaging to make loading faster?
-# TODO: Replace the execfile thing by some more pythonic plugin structure. But this would
-# be a large rewrite :-/
+# This may not be moved to current_app.g, because this needs to be request
+# independent
+_failed_plugins = {}
+
+
+# Load all files below share/check_mk/web/plugins/WHAT into a specified context
+# (global variables). Also honors the local-hierarchy for OMD
+# TODO: This is kept for pre 1.6.0i1 plugins
def load_web_plugins(forwhat, globalvars):
+ _failed_plugins[forwhat] = []
+
for plugins_path in [
cmk.utils.paths.web_dir + "/plugins/" + forwhat,
cmk.utils.paths.local_web_dir + "/plugins/" + forwhat
@@ -175,10 +181,19 @@ def load_web_plugins(forwhat, globalvars):
for fn in sorted(os.listdir(plugins_path)):
file_path = plugins_path + "/" + fn
- if fn.endswith(".py") and not os.path.exists(file_path + "c"):
- execfile(file_path, globalvars)
+ try:
+ if fn.endswith(".py") and not os.path.exists(file_path + "c"):
+ execfile(file_path, globalvars)
+
+ elif fn.endswith(".pyc"):
+ code_bytes = file(file_path).read()[8:]
+ code = marshal.loads(code_bytes)
+ exec code in globalvars
+
+ except Exception as e:
+ logger.error("Failed to load plugin %s: %s", file_path, e, exc_info=True)
+ _failed_plugins[forwhat].append((file_path, e))
+
- elif fn.endswith(".pyc"):
- code_bytes = file(file_path).read()[8:]
- code = marshal.loads(code_bytes)
- exec code in globalvars
+def get_failed_plugins():
+ return itertools.chain(*_failed_plugins.values())
diff --git a/tests/unit/cmk/gui/watolib/test_analyze_configuration.py b/tests/unit/cmk/gui/watolib/test_analyze_configuration.py
index f66c44c..8081e21 100644
--- a/tests/unit/cmk/gui/watolib/test_analyze_configuration.py
+++ b/tests/unit/cmk/gui/watolib/test_analyze_configuration.py
@@ -11,6 +11,7 @@ def test_registered_ac_tests():
'ACTestApacheProcessUsage',
'ACTestBackupConfigured',
'ACTestBackupNotEncryptedConfigured',
+ 'ACTestBrokenGUIExtension',
'ACTestCheckMKHelperUsage',
'ACTestESXDatasources',
'ACTestGenericCheckHelperUsage',
Module: check_mk
Branch: master
Commit: bf6add740aa6f6f39189b0e27cf344c57d14a643
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=bf6add740aa6f6…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Sun Feb 10 17:04:56 2019 +0100
DCD: Cleaned up cross component import
The DCD was previously directly executing a remote automation call to a
WATO remote site for gathering information from the remote DCD instance.
At the moment this call is used for fetching phase 1 results from remote
sites.
This was done by using cmk.gui.watolib code, which should not be
imported by another component than the GUI. To solve this we now use a
new Web API call which makes the DCD cleanly operate on the Web API of
the local site. The Web API is then using it's configuration and code to
make the connection to the remote site and returns the result to the
DCD.
Change-Id: I6fe7f76b2b4d66e58a6174e9d7c95005fb9aecae
---
.../plugins/webapi/execute_remote_automation.py | 60 ++++++++++++++++++++++
tests/unit/cmk/gui/test_webapi_unit.py | 1 +
2 files changed, 61 insertions(+)
diff --git a/cmk/gui/plugins/webapi/execute_remote_automation.py b/cmk/gui/plugins/webapi/execute_remote_automation.py
new file mode 100644
index 0000000..0d5ee7b
--- /dev/null
+++ b/cmk/gui/plugins/webapi/execute_remote_automation.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8; py-indent-offset: 4 -*-
+# +------------------------------------------------------------------+
+# | ____ _ _ __ __ _ __ |
+# | / ___| |__ ___ ___| | __ | \/ | |/ / |
+# | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
+# | | |___| | | | __/ (__| < | | | | . \ |
+# | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
+# | |
+# | Copyright Mathias Kettner 2014 mk(a)mathias-kettner.de |
+# +------------------------------------------------------------------+
+#
+# This file is part of Check_MK.
+# The official homepage is at http://mathias-kettner.de/check_mk.
+#
+# check_mk is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation in version 2. check_mk is distributed
+# in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
+# out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. See the GNU General Public License for more de-
+# tails. You should have received a copy of the GNU General Public
+# License along with GNU Make; see the file COPYING. If not, write
+# to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+# Boston, MA 02110-1301 USA.
+
+from typing import Dict, List # pylint: disable=unused-import
+
+import cmk.gui.config as config
+from cmk.gui.i18n import _
+from cmk.gui.exceptions import MKUserError
+from cmk.gui.plugins.webapi import (
+ APICallCollection,
+ api_call_collection_registry,
+)
+
+import cmk.gui.watolib.automations
+
+
+(a)api_call_collection_registry.register
+class APICallExecuteRemoteAutomation(APICallCollection):
+ def get_api_calls(self):
+ return {
+ "execute_remote_automation": {
+ "handler": self._execute_remote_automation,
+ "required_keys": ["site_id", "command", "command_args"],
+ # TODO: Add a dedicated permission for this
+ "required_permissions": ["wato.dcd_connections"],
+ },
+ }
+
+ def _execute_remote_automation(self, request):
+ if request["site_id"] not in config.sitenames():
+ raise MKUserError("site_id", _("This site does not exist."))
+
+ if request["site_id"] not in dict(config.wato_slave_sites()):
+ raise MKUserError("site_id", _("This site is not a distributed WATO site."))
+
+ return cmk.gui.watolib.automations.do_remote_automation(
+ config.site(request["site_id"]), request["command"], request["command_args"])
diff --git a/tests/unit/cmk/gui/test_webapi_unit.py b/tests/unit/cmk/gui/test_webapi_unit.py
index b3319a1..7c15611 100644
--- a/tests/unit/cmk/gui/test_webapi_unit.py
+++ b/tests/unit/cmk/gui/test_webapi_unit.py
@@ -10,6 +10,7 @@ def test_registered_api_call_collections():
for action in cls().get_api_calls().iterkeys())
assert sorted(registered_api_actions) == sorted([
'activate_changes',
+ 'execute_remote_automation',
'add_contactgroup',
'add_folder',
'add_host',
Module: check_mk
Branch: master
Commit: cb4e3edacec4b96518f51c9ff9aadc8f655e5336
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=cb4e3edacec4b9…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Wed Feb 20 10:56:20 2019 +0100
Updated werk text
Change-Id: If9424ae5a33a7dcca3ca4d07684ee773dc478edd
---
.werks/7089 | 3 +++
1 file changed, 3 insertions(+)
diff --git a/.werks/7089 b/.werks/7089
index 7231cf9..5b9d2b0f 100644
--- a/.werks/7089
+++ b/.werks/7089
@@ -17,3 +17,6 @@ The werk #7088 made it possible to perform an update without having access to
the old version. Once we have this functionality it is now possible to replace
one container with a another container. In case the version has changed, the
container is performing the update during startup of the new container.
+
+The simplified update procedure can be used for Docker container updates to
+version 1.6 or newer when the previous version is 1.5.0p13 or newer.