Module: check_mk
Branch: master
Commit: 9bb9a12ade18e92333aafd4afed4b6b51ad75124
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=9bb9a12ade18e9…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Thu Oct 11 20:46:24 2018 +0200
6780 FIX Fixed random alert / notify helper crashes on some platforms
The alert and notify helpers of the Microcore could crash "randomly"
after hours of operation.
The crash was visible in form of "ImportError: cannot import name" messages
in the var/log/notify.log or var/log/alert.log.
Due to another problem, which will also be fixed soon, the crash of the
helper process made the Microcore process crash.
As far as we know this happened only on Debian Jessie, CentOS/RedHat 7 and
SLES12 SP1/SP2.
CMK-1085
Change-Id: I50abefc35f89ba688752e1b83a16c6acdc9122ef
---
.werks/6780 | 23 +++++++++++++++++++++++
cmk/daemon.py | 18 ++++++++++++++++++
cmk/gui/background_job.py | 16 ++--------------
cmk_base/events.py | 10 ++++++++++
4 files changed, 53 insertions(+), 14 deletions(-)
diff --git a/.werks/6780 b/.werks/6780
new file mode 100644
index 0000000..b11376e
--- /dev/null
+++ b/.werks/6780
@@ -0,0 +1,23 @@
+Title: Fixed random alert / notify helper crashes on some platforms
+Level: 2
+Component: core
+Class: fix
+Compatible: compat
+Edition: cee
+State: unknown
+Version: 1.6.0i1
+Date: 1539283109
+
+The alert and notify helpers of the Microcore could crash "randomly"
+after hours of operation.
+
+The crash was visible in form of "ImportError: cannot import name" messages
+in the var/log/notify.log or var/log/alert.log.
+
+Due to another problem, which will also be fixed soon, the crash of the
+helper process made the Microcore process crash.
+
+As far as we know this happened only on Debian Jessie, CentOS/RedHat 7 and
+SLES12 SP1/SP2.
+
+CMK-1085
diff --git a/cmk/daemon.py b/cmk/daemon.py
index 7578b8f..24bbf3f 100644
--- a/cmk/daemon.py
+++ b/cmk/daemon.py
@@ -81,6 +81,24 @@ def daemonize(user=0, group=0):
os.close(so)
+def closefrom(lowfd):
+ """Closes all file descriptors starting with "lowfd", ignoring errors
+
+ Deletes all open file descriptors greater than or equal to lowfd from the
+ per-process object reference table. Any errors encountered while closing
+ file descriptors are ignored.
+
+ Difference to os.closerange() is that this automatically determines the
+ highest fd number to close.
+ """
+ try:
+ highfd = os.sysconf("SC_OPEN_MAX")
+ except ValueError:
+ highfd = 1024
+
+ os.closerange(lowfd, highfd)
+
+
def lock_with_pid_file(path):
"""
Use this after daemonizing or in foreground mode to ensure there is only
diff --git a/cmk/gui/background_job.py b/cmk/gui/background_job.py
index 76f9c64..0766d67 100644
--- a/cmk/gui/background_job.py
+++ b/cmk/gui/background_job.py
@@ -44,6 +44,7 @@ import cmk
import cmk.log
import cmk.daemon as daemon
import cmk.store as store
+import cmk.daemon as daemon
from cmk.exceptions import MKGeneralException
import cmk.gui.log
@@ -183,9 +184,7 @@ class BackgroundProcess(multiprocessing.Process):
os.setsid()
daemon.set_procname(BackgroundJobDefines.process_name)
-
- # Close file descpriptors. This also closes logfile handles!
- self._close_fds()
+ daemon.closefrom(0)
##################### ALL HANDLES HAVE BEEN CLOSED BOUNDARY ###########################
@@ -205,17 +204,6 @@ class BackgroundProcess(multiprocessing.Process):
"state": JobStatus.state_exception})
-
- def _close_fds(self):
- try:
- MAXFD = os.sysconf("SC_OPEN_MAX")
- except:
- MAXFD = 256
-
- # Close all file descriptors
- os.closerange(0, MAXFD)
-
-
def initialize_environment(self):
if not self._logger:
self._logger = cmk.gui.log.logger
diff --git a/cmk_base/events.py b/cmk_base/events.py
index 5f0494d..6da2963 100755
--- a/cmk_base/events.py
+++ b/cmk_base/events.py
@@ -38,6 +38,7 @@ import urllib
import livestatus
import cmk
from cmk.regex import regex
+import cmk.daemon
import cmk_base.config as config
import cmk_base.core
@@ -72,7 +73,16 @@ def event_keepalive(event_function, log_function, call_every_loop=None, loop_int
log_function("Configuration has changed. Restarting myself.")
if shutdown_function:
shutdown_function()
+
os.putenv("CMK_EVENT_RESTART", "1")
+
+ # Close all unexpected file descriptors before invoking
+ # execvp() to prevent inheritance of them. In CMK-1085 we
+ # had an issue related to os.urandom() which kept FDs open.
+ # This specific issue of Python 2.7.9 should've been fixed
+ # since Python 2.7.10. Just to be sure we keep cleaning up.
+ cmk.daemon.closefrom(3)
+
os.execvp("cmk", sys.argv)
data = ""
Module: check_mk
Branch: master
Commit: 0378ed2502fa79dcb2d0f5ee82e335a282c26fc7
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=0378ed2502fa79…
Author: Simon Betz <si(a)mathias-kettner.de>
Date: Mon Oct 8 14:40:52 2018 +0200
6742 mgmt_snmp_info: New check for SNMP management board
Change-Id: I225171505df5c506d411d3f45923c25012599cab
---
.werks/6742 | 10 ++++++++++
checkman/mgmt_snmp_info | 11 +++++++++++
checkman/snmp_info | 6 ------
checks/mgmt_snmp_info | 36 ++++++++++++++++++++++++++++++++++++
checks/snmp_info | 13 ++-----------
checks/snmp_info.include | 35 +++++++++++++++++++++++++++++++++++
6 files changed, 94 insertions(+), 17 deletions(-)
diff --git a/.werks/6742 b/.werks/6742
new file mode 100644
index 0000000..d62e88b
--- /dev/null
+++ b/.werks/6742
@@ -0,0 +1,10 @@
+Title: mgmt_snmp_info: New check for SNMP management board
+Level: 1
+Component: checks
+Compatible: compat
+Edition: cre
+Version: 1.6.0i1
+Date: 1539002444
+Class: feature
+
+
diff --git a/checkman/mgmt_snmp_info b/checkman/mgmt_snmp_info
new file mode 100644
index 0000000..2d5f153
--- /dev/null
+++ b/checkman/mgmt_snmp_info
@@ -0,0 +1,11 @@
+title: SNMP Management board: Retrieve informational SNMP data about host
+agents: snmp
+catalog: os/misc
+license: GPL
+distribution: check_mk
+description:
+ This check retrieves the values {sysDescr}, {sysContact}, {sysName} and
+ {sysLocation} and displays them. It is alwas OK.
+
+inventory:
+ One check per SNMP host will be created.
diff --git a/checkman/snmp_info b/checkman/snmp_info
index 09ba4b7..566386e 100644
--- a/checkman/snmp_info
+++ b/checkman/snmp_info
@@ -9,9 +9,3 @@ description:
inventory:
One check per SNMP host will be created.
-
- Please note: This check is not found be then SNMP scan (which you do with
- a simple {cmk -I}). You need to explicitely specify the check, if you
- want to inventorize it ({cmk --checks snmp_info -I}). Alternatively you
- can specify it as a manual check.
-
diff --git a/checks/mgmt_snmp_info b/checks/mgmt_snmp_info
new file mode 100644
index 0000000..4aeb963
--- /dev/null
+++ b/checks/mgmt_snmp_info
@@ -0,0 +1,36 @@
+#!/usr/bin/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.
+
+
+check_info["mgmt_snmp_info"] = {
+ 'check_function': check_snmp_info,
+ 'inventory_function': inventory_snmp_info,
+ 'service_description': 'Management Interface: SNMP Info',
+ 'snmp_info': ('.1.3.6.1.2.1.1', ['1.0', '4.0', '5.0', '6.0']),
+ 'snmp_scan_function': lambda oid: oid(".1.3.6.1.2.1.1.1.0") is not None,
+ 'includes': ['snmp_info.include'],
+ "management_board": MGMT_ONLY,
+}
diff --git a/checks/snmp_info b/checks/snmp_info
index 64ff07c..862b494 100644
--- a/checks/snmp_info
+++ b/checks/snmp_info
@@ -24,17 +24,6 @@
# to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301 USA.
-def inventory_snmp_info(info):
- if len(info[0]) >= 4:
- return [ (None, None) ]
-
-def check_snmp_info(checktype, params, info):
- if len(info[0]) >= 4:
- return (0, ', '.join([ info[0][i] for i in [0, 2, 3, 1] if info[0][i] ]))
- return (3, "No data retrieved")
-
-
-# This check works on all SNMP hosts
check_info["snmp_info"] = {
'check_function': check_snmp_info,
@@ -42,4 +31,6 @@ check_info["snmp_info"] = {
'service_description': 'SNMP Info',
'snmp_info': ('.1.3.6.1.2.1.1', ['1.0', '4.0', '5.0', '6.0']),
'snmp_scan_function': lambda oid: oid(".1.3.6.1.2.1.1.1.0") is not None,
+ 'includes': ['snmp_info.include'],
+ "management_board": HOST_ONLY,
}
diff --git a/checks/snmp_info.include b/checks/snmp_info.include
new file mode 100644
index 0000000..687fef3
--- /dev/null
+++ b/checks/snmp_info.include
@@ -0,0 +1,35 @@
+#!/usr/bin/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.
+
+
+def inventory_snmp_info(info):
+ if len(info[0]) >= 4:
+ return [ (None, None) ]
+
+def check_snmp_info(checktype, params, info):
+ if len(info[0]) >= 4:
+ return (0, ', '.join([ info[0][i] for i in [0, 2, 3, 1] if info[0][i] ]))
+ return (3, "No data retrieved")
Module: check_mk
Branch: master
Commit: 1812a1639088363ce9fbb9074360faf769ad8f21
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=1812a163908836…
Author: Kenneth Okoh <ko(a)mathias-kettner.de>
Date: Wed Oct 10 13:01:32 2018 +0200
Check function decorator for unwrapping of data (CMK-1015)
Change-Id: I8a64040b1813963d2b3f895e0fc218b44de1b561
---
cmk_base/check_api.py | 27 +++++++++++++++++++++++++++
tests/unit/cmk_base/test_check_api.py | 21 +++++++++++++++++++++
2 files changed, 48 insertions(+)
diff --git a/cmk_base/check_api.py b/cmk_base/check_api.py
index 4c2ff6f..888edfa 100644
--- a/cmk_base/check_api.py
+++ b/cmk_base/check_api.py
@@ -108,6 +108,7 @@ import cmk_base.snmp_utils as _snmp_utils
import cmk_base.item_state as _item_state
import cmk_base.prediction as _prediction
import cmk_base.check_api_utils as _check_api_utils
+import functools as _functools
def get_check_api_context():
"""This is called from cmk_base code to get the Check API things. Don't
@@ -479,6 +480,32 @@ def _agent_cache_file_age(hostname, check_plugin_name):
return None
+def get_parsed_item_data(check_function):
+ """Use this decorator to determine the parsed item data outside
+ of the respective check function.
+
+ The check function can hence be defined as follows:
+
+ @get_parsed_item_data
+ def check_<check_name>(item, params, data):
+ ...
+
+ In case of parsed not being a dict the decorator returns 3
+ (UNKN state) with a wrong usage message.
+ In case of item not existing in parsed the decorator gives an
+ empty return leading to cmk_base returning 3 (UNKN state) with
+ an item not found message (see cmk_base/checking.py).
+ """
+ @_functools.wraps(check_function)
+ def wrapped_check_function(item, params, parsed):
+ if not isinstance(parsed, dict):
+ return 3, "Wrong usage of decorator function 'get_parsed_item_data': parsed is not a dict"
+ if item not in parsed:
+ return
+ return check_function(item, params, parsed[item])
+ return wrapped_check_function
+
+
# NOTE: Currently this is not really needed, it is just here to keep any start
# import in sync with our intended API.
# TODO: Do we really need this? Is there code which uses a star import for this
diff --git a/tests/unit/cmk_base/test_check_api.py b/tests/unit/cmk_base/test_check_api.py
new file mode 100644
index 0000000..2222e31
--- /dev/null
+++ b/tests/unit/cmk_base/test_check_api.py
@@ -0,0 +1,21 @@
+import pytest
+
+import cmk_base.discovery as discovery
+import cmk_base.config as config
+import cmk_base.check_utils
+import cmk_base.check_api as check_api
+from cmk.exceptions import MKGeneralException
+
+(a)check_api.get_parsed_item_data
+def check_foo(item, params, parsed_item_data):
+ return 2, "bar"
+
+def test_get_parsed_item_data():
+ params = {}
+ parsed = {1: "one"}
+ info = [[1, "one"], [2, "two"]]
+ assert check_foo(1, params, parsed) == (2, "bar")
+ assert check_foo(2, params, parsed) == None
+ assert check_foo(1, params, info) == (3, "Wrong usage of decorator function 'get_parsed_item_data': parsed is not a dict")
+ assert check_foo.__name__ == "check_foo"
+
Module: check_mk
Branch: master
Commit: fd5d10166af845feb657159974d1b8a67e03cf65
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=fd5d10166af845…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Tue Oct 9 19:33:53 2018 +0200
6777 FIX Background job logs were not always shown in job output
In some situations log entries which should be written to the job output,
which is visible from the GUI, was not written to it.
Background: The default logger was based on cmk.log logger which is not
initialized with the GUI log level. The job logger is now based on cmk.gui.log
logger as intended which makes the job log entries now available in the job
progress dialog by default.
Change-Id: I92e65bb7a2ab467fd567c7456c4fbe2761bbfc66
---
.werks/6777 | 17 +++++++++++++++++
cmk/gui/background_job.py | 5 +++--
2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/.werks/6777 b/.werks/6777
new file mode 100644
index 0000000..27e239a
--- /dev/null
+++ b/.werks/6777
@@ -0,0 +1,17 @@
+Title: Background job logs were not always shown in job output
+Level: 1
+Component: multisite
+Class: fix
+Compatible: compat
+Edition: cre
+State: unknown
+Version: 1.6.0i1
+Date: 1539106361
+
+In some situations log entries which should be written to the job output,
+which is visible from the GUI, was not written to it.
+
+Background: The default logger was based on cmk.log logger which is not
+initialized with the GUI log level. The job logger is now based on cmk.gui.log
+logger as intended which makes the job log entries now available in the job
+progress dialog by default.
diff --git a/cmk/gui/background_job.py b/cmk/gui/background_job.py
index b0d0f0c..3995335 100644
--- a/cmk/gui/background_job.py
+++ b/cmk/gui/background_job.py
@@ -46,6 +46,7 @@ import cmk.daemon as daemon
import cmk.store as store
from cmk.exceptions import MKGeneralException
+import log
class BackgroundJobAlreadyRunning(MKGeneralException):
pass
@@ -217,7 +218,7 @@ class BackgroundProcess(multiprocessing.Process):
def initialize_environment(self):
if not self._logger:
- self._logger = cmk.log.logger
+ self._logger = log.logger
self._open_stdout_and_stderr()
self._enable_logging_to_stdout()
@@ -295,7 +296,7 @@ class BackgroundProcess(multiprocessing.Process):
in stdout (which results in job progress info)"""
handler = logging.StreamHandler(stream=sys.stdout)
handler.setFormatter(cmk.log.get_formatter())
- cmk.log.logger.addHandler(handler)
+ log.logger.addHandler(handler)