Module: check_mk
Branch: master
Commit: 5dec65a23ac46acf3dd918fa207aa3fd1353ec93
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=5dec65a23ac46a…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Tue Jan 8 10:11:53 2019 +0100
7021 haproxy: Add agent implementation to standard linux agent
Change-Id: I9c9f2665535db4e1b2a39ce297fafed24497c98b
---
.werks/7021 | 10 ++++++++++
agents/check_mk_agent.linux | 5 +++++
checkman/haproxy.frontend | 5 +++--
checkman/haproxy.server | 5 +++--
4 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/.werks/7021 b/.werks/7021
new file mode 100644
index 0000000..bf3de05
--- /dev/null
+++ b/.werks/7021
@@ -0,0 +1,10 @@
+Title: haproxy: Add agent implementation to standard linux agent
+Level: 1
+Component: checks
+Compatible: compat
+Edition: cre
+Version: 1.6.0i1
+Date: 1546938683
+Class: feature
+
+
diff --git a/agents/check_mk_agent.linux b/agents/check_mk_agent.linux
index 4f81e61..8e895b0 100755
--- a/agents/check_mk_agent.linux
+++ b/agents/check_mk_agent.linux
@@ -1032,6 +1032,11 @@ if type pvecm > /dev/null 2>&1 ; then
pvecm nodes
fi
+if [ -r /run/haproxy/admin.sock ] && type socat >/dev/null 2>&1; then
+ echo "<<<haproxy:sep(44)>>>"
+ echo "show stat" | socat - UNIX-CONNECT:/run/haproxy/admin.sock
+fi
+
# Start new liveupdate process in background on each agent execution. Starting
# a new live update process will terminate the old one automatically after
# max. 1 sec.
diff --git a/checkman/haproxy.frontend b/checkman/haproxy.frontend
index a315c24..170de44 100644
--- a/checkman/haproxy.frontend
+++ b/checkman/haproxy.frontend
@@ -1,5 +1,5 @@
title: HAProxy: Status of the Frontends
-agents: freebsd
+agents: freebsd linux
catalog: hw/app/haproxy
license: GPL
distribution: check_mk
@@ -7,7 +7,8 @@ description:
This check monitors the status of the frontends of the HAProxy loadbalancer
for TCP and HTTP connections. It requires the mk_haproxy.freebsd agent plugin
- to be installed on the FreeBSD host to be monitored.
+ to be installed on the FreeBSD host to be monitored. On linux it works with the
+ standard agent.
The check is {OK} if the frontend has the status {OPEN}. It is {CRIT}
otherwise.
diff --git a/checkman/haproxy.server b/checkman/haproxy.server
index 2bba86a..1d4ecd0 100644
--- a/checkman/haproxy.server
+++ b/checkman/haproxy.server
@@ -1,5 +1,5 @@
title: HAProxy: Server Status
-agents: freebsd
+agents: freebsd linux
catalog: hw/app/haproxy
license: GPL
distribution: check_mk
@@ -7,7 +7,8 @@ description:
This check monitors the status of the servers of the HAProxy loadbalancer
for TCP and HTTP connections. It requires the mk_haproxy.freebsd agent
- plugin to be installed on the FreeBSD host to be monitored.
+ plugin to be installed on the FreeBSD host to be monitored. On linux it
+ works with the standard agent.
The check is {OK} if the server indicates the status {UP} and either {active}
or {backup}. It is {CRIT} otherwise.
Module: check_mk
Branch: master
Commit: 7317cdfea77d2fc4b8d070616f33ffe167155d2b
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=7317cdfea77d2f…
Author: Sven Panne <sp(a)mathias-kettner.de>
Date: Mon Jan 7 17:14:37 2019 +0100
Fixed a TODO.
Change-Id: Ie116c39d6336daff77223b4bb00ebb0df9d9d40c
---
cmk/gui/htmllib.py | 9 +--------
cmk/gui/valuespec.py | 2 +-
2 files changed, 2 insertions(+), 9 deletions(-)
diff --git a/cmk/gui/htmllib.py b/cmk/gui/htmllib.py
index 2d4996d..8828f34 100644
--- a/cmk/gui/htmllib.py
+++ b/cmk/gui/htmllib.py
@@ -1134,13 +1134,6 @@ class html(HTMLGenerator):
def all_varnames_with_prefix(self, prefix):
return self.request.all_varnames_with_prefix(prefix)
- # Return all values of a variable that possible occurs more
- # than once in the URL. note: self.listvars does contain those
- # variable only, if the really occur more than once.
- # TODO: Refactor call sites to html.request.*
- def list_var(self, varname):
- return self.request.list_var(varname)
-
# Adds a variable to listvars and also set it
# TODO: Refactor call sites to html.request.*
def add_var(self, varname, value):
@@ -1967,7 +1960,7 @@ class html(HTMLGenerator):
return self.has_var("filled_in") and (
form_name is None or \
- form_name in self.list_var("filled_in"))
+ form_name in self.request.list_var("filled_in"))
def do_actions(self):
return self.var("_do_actions") not in ["", None, _("No")]
diff --git a/cmk/gui/valuespec.py b/cmk/gui/valuespec.py
index 105aaa0..f822c93 100644
--- a/cmk/gui/valuespec.py
+++ b/cmk/gui/valuespec.py
@@ -2251,7 +2251,7 @@ class MultiSelect(ListChoice):
def from_html_vars(self, varprefix):
self.load_elements()
value = []
- hv = html.list_var(varprefix)
+ hv = html.request.list_var(varprefix)
for key, _title in self._elements:
if key in hv:
value.append(key)
Module: check_mk
Branch: master
Commit: 3f32a8b60d38d761dbf4a4df0af242618eb995fb
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=3f32a8b60d38d7…
Author: Sven Panne <sp(a)mathias-kettner.de>
Date: Mon Jan 7 15:02:48 2019 +0100
Reduce direct access to Request.vars, only html.unstash_vars() left.
Change-Id: Iea1d5786e8ae56a1dad01a2225f2e7f53a09af6d
---
cmk/gui/crash_reporting.py | 2 +-
cmk/gui/htmllib.py | 26 +++++++++-------------
cmk/gui/http.py | 4 ++--
cmk/gui/login.py | 2 +-
cmk/gui/plugins/views/availability.py | 6 ++---
cmk/gui/plugins/wato/utils/__init__.py | 2 +-
cmk/gui/watolib.py | 2 +-
.../cmk/gui/test_htmllib_TransactionManager.py | 8 +++----
8 files changed, 22 insertions(+), 30 deletions(-)
diff --git a/cmk/gui/crash_reporting.py b/cmk/gui/crash_reporting.py
index ff3e86c..98ac397 100644
--- a/cmk/gui/crash_reporting.py
+++ b/cmk/gui/crash_reporting.py
@@ -476,7 +476,7 @@ def create_crash_dump_info_file(tar, what):
"page": html.myfile + ".py",
"vars": {
key: "***" if value in ["password", "_password"] else value
- for key, value in html.request.vars.iteritems()
+ for key, value in html.request.all_vars()
},
"username": config.user.id,
"user_agent": html.request.user_agent,
diff --git a/cmk/gui/htmllib.py b/cmk/gui/htmllib.py
index 6d43700..2d4996d 100644
--- a/cmk/gui/htmllib.py
+++ b/cmk/gui/htmllib.py
@@ -1131,10 +1131,6 @@ class html(HTMLGenerator):
return self.request.var_utf8(varname, deflt)
# TODO: Refactor call sites to html.request.*
- def all_vars(self):
- return self.request.all_vars()
-
- # TODO: Refactor call sites to html.request.*
def all_varnames_with_prefix(self, prefix):
return self.request.all_varnames_with_prefix(prefix)
@@ -1163,7 +1159,7 @@ class html(HTMLGenerator):
self.request.del_all_vars(prefix)
def stash_vars(self):
- self._var_stash.append(self.request.vars.copy())
+ self._var_stash.append(dict(self.request.all_vars()))
def unstash_vars(self):
self.request.vars = self._var_stash.pop()
@@ -1250,7 +1246,7 @@ class html(HTMLGenerator):
raise MKUserError("request",
_("Failed to parse JSON request: '%s': %s") % (json_request, e))
- for key, val in self.all_vars().items():
+ for key, val in self.request.all_vars():
if key not in ["request", "output_format"] + exclude_vars:
request[key] = val.decode("utf-8")
@@ -1586,8 +1582,8 @@ class html(HTMLGenerator):
# [('varname1', value1), ('varname2', value2) ]
def makeuri(self, addvars, remove_prefix=None, filename=None, delvars=None):
new_vars = [nv[0] for nv in addvars]
- vars_ = [(v, self.var(v))
- for v in self.request.vars
+ vars_ = [(v, val)
+ for v, val in self.request.all_vars()
if v[0] != "_" and v not in new_vars and (not delvars or v not in delvars)]
if remove_prefix is not None:
vars_ = [i for i in vars_ if not i[0].startswith(remove_prefix)]
@@ -1940,10 +1936,9 @@ class html(HTMLGenerator):
add_action_vars = args.get("add_action_vars", False)
if varlist is not None:
for var in varlist:
- value = self.request.vars.get(var, "")
- self.hidden_field(var, value)
+ self.hidden_field(var, self.request.var(var, ""))
else: # add *all* get variables, that are not set by any input!
- for var in self.request.vars:
+ for var, _val in self.request.all_vars():
if var not in self.form_vars and \
(var[0] != "_" or add_action_vars): # and var != "filled_in":
self.hidden_field(var, self.get_unicode_input(var))
@@ -2176,7 +2171,7 @@ class html(HTMLGenerator):
# Model
error = self.user_errors.get(varname)
- value = self.request.vars.get(varname, default_value)
+ value = self.request.var(varname, default_value)
if not value:
value = ""
if error:
@@ -2434,7 +2429,7 @@ class html(HTMLGenerator):
self.open_center()
self.open_div(class_="really")
self.write_text(msg)
- # FIXME: When this confirms another form, use the form name from self.request.vars()
+ # FIXME: When this confirms another form, use the form name from self.request.all_vars()
self.begin_form("confirm", method=method, action=action, add_transid=add_transid)
self.hidden_fields(add_action_vars=True)
self.button("_do_confirm", _("Yes!"), "really")
@@ -2914,12 +2909,11 @@ hy
self.end_foldable_container()
def debug_vars(self, prefix=None, hide_with_mouse=True, vars_=None):
- if not vars_:
- vars_ = self.request.vars
+ it = self.request.all_vars() if vars_ is None else vars_.iteritems()
hover = "this.style.display=\'none\';"
self.open_table(class_=["debug_vars"], onmouseover=hover if hide_with_mouse else None)
self.tr(self.render_th(_("POST / GET Variables"), colspan="2"))
- for name, value in sorted(vars_.items()):
+ for name, value in sorted(it):
if name in ["_password", "password"]:
value = "***"
if not prefix or name.startswith(prefix):
diff --git a/cmk/gui/http.py b/cmk/gui/http.py
index 46453c6..c7c4cf4 100644
--- a/cmk/gui/http.py
+++ b/cmk/gui/http.py
@@ -60,7 +60,7 @@ class Request(object):
values = [(k, vs) for k, vs in self._wrequest.values.lists() if _valid_varname(k)]
# Last occurrence takes precedence, making appending to current URL simpler
- # TODO: Some code *directly* accesses and modifies vars, remove that!
+ # TODO: html.unstash_vars() *directly* modifies vars, remove that!
self.vars = {k: vs[-1] for k, vs in values}
self._listvars = {k: vs for k, vs in values if len(vs) > 1}
@@ -165,7 +165,7 @@ class Request(object):
return val
def all_vars(self):
- return self.vars
+ return self.vars.iteritems()
def all_varnames_with_prefix(self, prefix):
for varname in self.vars:
diff --git a/cmk/gui/login.py b/cmk/gui/login.py
index bc186f4..6ddf4ec 100644
--- a/cmk/gui/login.py
+++ b/cmk/gui/login.py
@@ -211,7 +211,7 @@ def renew_cookie(cookie_name, username):
if (html.myfile != 'logout' and not html.has_var('_ajaxid')) \
and cookie_name == auth_cookie_name():
auth_logger.debug(
- "Renewing auth cookie (%s.py, vars: %r)" % (html.myfile, html.request.vars))
+ "Renewing auth cookie (%s.py, vars: %r)" % (html.myfile, dict(html.request.all_vars())))
renew_auth_session(username)
diff --git a/cmk/gui/plugins/views/availability.py b/cmk/gui/plugins/views/availability.py
index a55dc0c..c5266f5 100644
--- a/cmk/gui/plugins/views/availability.py
+++ b/cmk/gui/plugins/views/availability.py
@@ -81,10 +81,8 @@ def get_availability_options_from_url(what):
def render_availability_options(what):
if html.var("_reset"):
config.user.save_file("avoptions", {})
- for varname in html.request.vars.keys():
- if varname.startswith("avo_"):
- html.del_var(varname)
- html.del_var("avoptions")
+ html.request.del_all_vars("avo_")
+ html.del_var("avoptions")
avoptions = availability.get_default_avoptions()
diff --git a/cmk/gui/plugins/wato/utils/__init__.py b/cmk/gui/plugins/wato/utils/__init__.py
index 71c78f9..1ced1c3a 100644
--- a/cmk/gui/plugins/wato/utils/__init__.py
+++ b/cmk/gui/plugins/wato/utils/__init__.py
@@ -928,7 +928,7 @@ class TimeperiodValuespec(ValueSpec):
def render_input(self, varprefix, value):
# The display mode differs when the valuespec is activated
- vars_copy = html.request.vars.copy()
+ vars_copy = dict(html.request.all_vars())
# The timeperiod mode can be set by either the GUI switch or by the value itself
# GUI switch overrules the information stored in the value
diff --git a/cmk/gui/watolib.py b/cmk/gui/watolib.py
index 2697e23..f185a29 100644
--- a/cmk/gui/watolib.py
+++ b/cmk/gui/watolib.py
@@ -2691,7 +2691,7 @@ class SearchFolder(BaseFolder):
url_vars = [("host_search", "1")] + add_vars
- for varname, value in html.all_vars().items():
+ for varname, value in html.request.all_vars():
if varname.startswith("host_search_") \
or varname.startswith("_change"):
url_vars.append((varname, value))
diff --git a/tests/unit/cmk/gui/test_htmllib_TransactionManager.py b/tests/unit/cmk/gui/test_htmllib_TransactionManager.py
index 1de0fd7..10f8fa0 100644
--- a/tests/unit/cmk/gui/test_htmllib_TransactionManager.py
+++ b/tests/unit/cmk/gui/test_htmllib_TransactionManager.py
@@ -49,7 +49,7 @@ def test_transaction_valid(tm, transid, ignore_transids, result, monkeypatch, is
assert tm._ignore_transids == True
if transid is not None:
- tm._request.vars["_transid"] = transid
+ tm._request.set_var("_transid", transid)
assert tm._request.has_var("_transid")
assert tm._request.var("_transid") == transid
@@ -63,7 +63,7 @@ def test_transaction_valid(tm, transid, ignore_transids, result, monkeypatch, is
def test_is_transaction(tm):
assert not tm.is_transaction()
- tm._request.vars["_transid"] = "123"
+ tm._request.set_var("_transid", "123")
assert tm.is_transaction()
@@ -72,7 +72,7 @@ def test_check_transaction_invalid(tm, monkeypatch):
def test_check_transaction_valid(tm, monkeypatch, mocker):
valid_transid = "%d/abc" % time.time()
- tm._request.vars["_transid"] = valid_transid
+ tm._request.set_var("_transid", valid_transid)
monkeypatch.setattr(tm, "_load_transids", lambda: [valid_transid])
@@ -83,7 +83,7 @@ def test_check_transaction_valid(tm, monkeypatch, mocker):
def test_check_transaction_automation(tm, monkeypatch, mocker):
tm.ignore()
- tm._request.vars["_transid"] = "-1"
+ tm._request.set_var("_transid", "-1")
invalidate = mocker.patch.object(tm, "_invalidate")
assert tm.check_transaction() == True
Module: check_mk
Branch: master
Commit: d9956a5ee1b9fc944778ca9d5d5411298f141d30
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=d9956a5ee1b9fc…
Author: Sven Panne <sp(a)mathias-kettner.de>
Date: Mon Jan 7 12:57:09 2019 +0100
Handle form data via werkzeug.Request.
The call sites and helper functions are left untouched for now, we will
simplify things further in upcoming commits.
Made some form-related properties non-public on the way, making the fact
explicit that we access them via our helpers only.
Change-Id: I438949b9323f0703e39a60f04f04c164b0803bdf
---
cmk/gui/http.py | 99 ++++++++++++++++++++-------------------------------------
1 file changed, 35 insertions(+), 64 deletions(-)
diff --git a/cmk/gui/http.py b/cmk/gui/http.py
index 0aafcad..46453c6 100644
--- a/cmk/gui/http.py
+++ b/cmk/gui/http.py
@@ -25,7 +25,6 @@
# Boston, MA 02110-1301 USA.
"""Wrapper layer between WSGI and the GUI application code"""
-import cgi
import re
import six
@@ -35,6 +34,14 @@ import werkzeug.wrappers
import cmk.gui.log as log
from cmk.gui.i18n import _
+# TODO: For some aracane reason, we are a bit restrictive about the allowed
+# variable names. Try to figure out why...
+_VARNAME_REGEX = re.compile(r'^[\w.%*+=-]+$')
+
+
+def _valid_varname(v):
+ return _VARNAME_REGEX.match(v)
+
class Request(object):
"""Provides information about the users HTTP request to the application
@@ -49,64 +56,28 @@ class Request(object):
self._logger = log.logger.getChild("http.Request")
self._wsgi_environ = wsgi_environ
+ self._wrequest = werkzeug.wrappers.Request(wsgi_environ)
+
+ values = [(k, vs) for k, vs in self._wrequest.values.lists() if _valid_varname(k)]
+ # Last occurrence takes precedence, making appending to current URL simpler
+ # TODO: Some code *directly* accesses and modifies vars, remove that!
+ self.vars = {k: vs[-1] for k, vs in values}
+ self._listvars = {k: vs for k, vs in values if len(vs) > 1}
+
+ # NOTE: There could be multiple entries with the same key, we ignore that for now...
+ self._uploads = {}
+ for k, f in self._wrequest.files.iteritems():
+ # TODO: We read the whole data here and remember it. Should we
+ # offer the underlying stream directly?
+ self._uploads[k] = (f.filename, f.mimetype, f.read())
+ f.close()
- # Structures filled using the request environment
- self.vars = {}
- self.listvars = {} # for variables with more than one occurrence
- self.uploads = {}
# TODO: To be compatible with Check_MK <1.5 handling / code base we
# prevent parse_cookie() from decoding the stuff to unicode. One bright
# day we'll switch all input stuff to be parsed to unicode, then we'll
# clean this up!
self.cookies = werkzeug.http.parse_cookie(wsgi_environ, charset=None)
- self._init_vars(wsgi_environ)
-
- def _init_vars(self, wsgi_environ):
- wsgi_input = wsgi_environ["wsgi.input"]
- if not wsgi_input:
- return
-
- fields = None
- try:
- fields = cgi.FieldStorage(wsgi_input, None, "", wsgi_environ, keep_blank_values=1)
- except MemoryError:
- raise Exception('The maximum request size has been exceeded.')
-
- self._init_vars_from_field_storage(fields)
-
- def _init_vars_from_field_storage(self, fields):
- # TODO: Previously the regex below matched any alphanumeric character plus any character
- # from set(r'%*+,-./:;<=>?@[\_'), but this was very probably unintended. Now we only allow
- # alphanumeric characters plus any character from set('%*+-._'), which is probably still a
- # bit too broad. We should really figure out what we need and make sure that we only use
- # that restricted set.
- varname_regex = re.compile(r'^[\w.%*+=-]+$')
-
- for field in fields.list:
- varname = field.name
-
- # To prevent variours injections, we only allow a defined set
- # of characters to be used in variables
- if not varname_regex.match(varname):
- continue
-
- # put uploaded file infos into separate storage
- if field.filename is not None:
- self.uploads[varname] = (field.filename, field.type, field.value)
-
- else: # normal variable
- # Multiple occurrance of a variable? Store in extra list dict
- if varname in self.vars:
- if varname in self.listvars:
- self.listvars[varname].append(field.value)
- else:
- self.listvars[varname] = [self.vars[varname], field.value]
- # In the single-value-store the last occurrance of a variable
- # has precedence. That makes appending variables to the current
- # URL simpler.
- self.vars[varname] = field.value
-
@property
def requested_file(self):
return self._wsgi_environ["SCRIPT_NAME"]
@@ -202,19 +173,19 @@ class Request(object):
yield varname
# Return all values of a variable that possible occurs more
- # than once in the URL. note: self.listvars does contain those
+ # than once in the URL. note: self._listvars does contain those
# variable only, if the really occur more than once.
def list_var(self, varname):
- if varname in self.listvars:
- return self.listvars[varname]
+ if varname in self._listvars:
+ return self._listvars[varname]
elif varname in self.vars:
return [self.vars[varname]]
return []
- # Adds a variable to listvars and also set it
+ # Adds a variable to _listvars and also set it
def add_var(self, varname, value):
- self.listvars.setdefault(varname, [])
- self.listvars[varname].append(value)
+ self._listvars.setdefault(varname, [])
+ self._listvars[varname].append(value)
self.vars[varname] = value
# TODO: self.vars should be strictly read only in the Request() object
@@ -232,20 +203,20 @@ class Request(object):
# TODO: self.vars should be strictly read only in the Request() object
def del_var(self, varname):
self.vars.pop(varname, None)
- self.listvars.pop(varname, None)
+ self._listvars.pop(varname, None)
# TODO: self.vars should be strictly read only in the Request() object
def del_all_vars(self, prefix=None):
if not prefix:
self.vars = {}
- self.listvars = {}
+ self._listvars = {}
else:
self.vars = dict(p for p in self.vars.iteritems() if not p[0].startswith(prefix))
- self.listvars = dict(
- p for p in self.listvars.iteritems() if not p[0].startswith(prefix))
+ self._listvars = dict(
+ p for p in self._listvars.iteritems() if not p[0].startswith(prefix))
- def uploaded_file(self, varname, default=None):
- return self.uploads.get(varname, default)
+ def uploaded_file(self, varname):
+ return self._uploads.get(varname)
class Response(werkzeug.wrappers.Response):