Module: check_mk
Branch: master
Commit: 06285f2269ffb7558c2420d842ffbf48860bdddc
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=06285f2269ffb7…
Author: Andreas Boesl <ab(a)mathias-kettner.de>
Date: Mon Feb 20 14:01:02 2017 +0100
4026 mk_logwatch: plugin now also supports windows
The mk_logwatch plugin is no longer restricted to windows.
It now runs as a frozen python binary under windows, which requires no extra python installation.
The plugin reads its configuration from the config/logwatch.cfg file.
The syntax of the windows and linux logwatch.cfg is identical.
The plugin may be configured through the WATO agent bakery with the rule "Text logfiles (Linux, Windows)".
The former rule "Text logfiles (Windows)" still works, but is considered as deprecated.
Keep in mind, there is difference in regex pattern matching.
The legacy windows logwatch always did a case insenstive match.
The new mk_logwatch.exe now also checks case sensitive, just like the linux plugin.
Change-Id: I8711bcfb72963e854c64fb6dbd8ec892189e588c
---
.werks/4026 | 20 +++++++
agents/plugins/mk_logwatch | 139 +++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 153 insertions(+), 6 deletions(-)
diff --git a/.werks/4026 b/.werks/4026
new file mode 100644
index 0000000..a4928bb
--- /dev/null
+++ b/.werks/4026
@@ -0,0 +1,20 @@
+Title: mk_logwatch: plugin now also supports windows
+Level: 2
+Component: checks
+Compatible: compat
+Version: 1.5.0i1
+Date: 1487595108
+Class: feature
+
+The mk_logwatch plugin is no longer restricted to windows.
+It now runs as a frozen python binary under windows, which requires no extra python installation.
+
+The plugin reads its configuration from the config/logwatch.cfg file.
+The syntax of the windows and linux logwatch.cfg is identical.
+
+The plugin may be configured through the WATO agent bakery with the rule "Text logfiles (Linux, Windows)".
+The former rule "Text logfiles (Windows)" still works, but is considered as deprecated.
+
+Keep in mind, there is difference in regex pattern matching.
+The legacy windows logwatch always did a case insenstive match.
+The new mk_logwatch.exe now also checks case sensitive, just like the linux plugin.
diff --git a/agents/plugins/mk_logwatch b/agents/plugins/mk_logwatch
index 55cd720..0da34a8 100755
--- a/agents/plugins/mk_logwatch
+++ b/agents/plugins/mk_logwatch
@@ -28,6 +28,90 @@
import sys, os, re, time, glob
+
+# .--MEI-Cleanup---------------------------------------------------------.
+# | __ __ _____ ___ ____ _ |
+# | | \/ | ____|_ _| / ___| | ___ __ _ _ __ _ _ _ __ |
+# | | |\/| | _| | |_____| | | |/ _ \/ _` | '_ \| | | | '_ \ |
+# | | | | | |___ | |_____| |___| | __/ (_| | | | | |_| | |_) | |
+# | |_| |_|_____|___| \____|_|\___|\__,_|_| |_|\__,_| .__/ |
+# | |_| |
+# +----------------------------------------------------------------------+
+# In case the program crashes or is killed in a hard way, the frozen binary .exe
+# may leave temporary directories named "_MEI..." in the temporary path. Clean them
+# up to prevent eating disk space over time.
+
+########################################################################
+############## DUPLICATE CODE WARNING ##################################
+### This code is also used in the cmk-update-agent frozen binary #######
+### Any changes to this class should also be made in cmk-update-agent ##
+### In the bright future we will move this code into a library #########
+########################################################################
+
+class MEIFolderCleaner(object):
+ def pid_running(self, pid):
+ import ctypes
+ kernel32 = ctypes.windll.kernel32
+ SYNCHRONIZE = 0x100000
+
+ process = kernel32.OpenProcess(SYNCHRONIZE, 0, pid)
+
+ if process != 0:
+ kernel32.CloseHandle(process)
+ return True
+ else:
+ return False
+
+
+ def find_and_remove_leftover_folders(self, hint_filenames):
+ if not hasattr(sys, "frozen"):
+ return
+
+ import win32file
+ import tempfile
+ base_path = tempfile.gettempdir()
+ for f in os.listdir(base_path):
+ try:
+ path = os.path.join(base_path, f)
+
+ if not os.path.isdir(path):
+ continue
+
+ # Only care about directories related to our program
+ invalid_dir = False
+ for hint_filename in hint_filenames:
+ if not os.path.exists(os.path.join(path, hint_filename)):
+ invalid_dir = True
+ break
+ if invalid_dir:
+ continue
+
+ pyinstaller_tmp_path = win32file.GetLongPathName(sys._MEIPASS).lower() # pylint: disable=no-member
+ if pyinstaller_tmp_path == path.lower():
+ continue # Skip our own directory
+
+ # Extract the process id from the directory and check whether or not it is still
+ # running. Don't delete directories of running processes!
+ # The name of the temporary directories is "_MEI<PID><NR>". We try to extract the PID
+ # by stripping of a single digit from the right. In the hope the NR is a single digit
+ # in all relevant cases.
+ pid = int(f[4:-1])
+ if self.pid_running(pid):
+ continue
+
+ shutil.rmtree(path)
+ except Exception, e:
+ # TODO: introduce verbose mode for mk_logwatch
+ pass
+
+
+os_type = "linux"
+try:
+ import platform
+ os_type = platform.system().lower()
+except:
+ pass
+
if '-d' in sys.argv[1:] or '--debug' in sys.argv[1:]:
tty_red = '\033[1;31m'
tty_green = '\033[1;32m'
@@ -192,7 +276,8 @@ def next_line(file_handle):
line = file_handle.next()
# Avoid parsing of (yet) incomplete lines (when acutal application
# is just in the process of writing)
- if not line.endswith(os.linesep):
+ # Just check if the line ends with a \n. This handles \n and \r\n
+ if not line.endswith("\n"):
begin_of_line_offset = file_handle.tell() - len(line)
os.lseek(file_handle.fileno(), begin_of_line_offset, 0)
return None
@@ -201,6 +286,22 @@ def next_line(file_handle):
return None
+def is_inode_cabable(path):
+ if "linux" in os_type:
+ return True
+ elif "windows" in os_type:
+ volume_name = "%s:\\\\" % path.split(":", 1)[0]
+ import win32api
+ volume_info = win32api.GetVolumeInformation(volume_name)
+ volume_type = volume_info[-1]
+ if "ntfs" in volume_type.lower():
+ return True
+ else:
+ return False
+ else:
+ return False
+
+
def process_logfile(logfile, patterns):
global pushed_back_line
@@ -210,7 +311,10 @@ def process_logfile(logfile, patterns):
offset, prev_inode = status.get(logfile, (-1, -1))
try:
file_desc = os.open(logfile, os.O_RDONLY)
- inode = os.fstat(file_desc)[1] # 1 = st_ino
+ if not is_inode_cabable(logfile):
+ inode = 1 # Create a dummy inode
+ else:
+ inode = os.fstat(file_desc)[1] # 1 = st_ino
except:
if debug:
raise
@@ -227,10 +331,10 @@ def process_logfile(logfile, patterns):
# current pointer to the file end. We do not want to make
# a fuss about ancient log messages...
if offset == -1:
- if not debug:
+ if not debug:
return
- else:
- offset = 0
+ else:
+ offset = 0
# If the inode of the logfile has changed it has appearently
@@ -254,7 +358,23 @@ def process_logfile(logfile, patterns):
# now seek to offset where interesting data begins
os.lseek(file_desc, offset, 0) # os.SEEK_SET not available in Python 2.4
- file_handle = os.fdopen(file_desc)
+ if os_type == "windows":
+ import io # Available with python 2.6
+ import codecs
+ # Some windows files are encoded in utf_16
+ # Peak the first two bytes to determine the encoding...
+ peak_handle = os.fdopen(file_desc, "rb")
+ first_two_bytes = peak_handle.read(2)
+ use_encoding = None
+ if first_two_bytes == "\xFF\xFE":
+ use_encoding = "utf_16"
+ elif first_two_bytes == "\xFE\xFF":
+ use_encoding = "utf_16_be"
+
+ os.lseek(file_desc, offset, 0) # os.SEEK_SET not available in Python 2.4
+ file_handle = io.open(file_desc, encoding = use_encoding)
+ else:
+ file_handle = os.fdopen(file_desc)
worst = -1
outputtxt = ""
lines_parsed = 0
@@ -346,6 +466,13 @@ def process_logfile(logfile, patterns):
sys.stdout.write("%sW Maximum allowed logfile size (%d bytes) exceeded for the %dth time.%s\n" %
(tty_yellow, opt_maxfilesize, new_offset / opt_maxfilesize, tty_normal))
+try:
+ # This removes leftover folders which may be generated by crashing frozen binaries
+ folder_cleaner = MEIFolderCleaner()
+ folder_cleaner.find_and_remove_leftover_folders(hint_filenames = ["mk_logwatch.exe.manifest"])
+except Exception, e:
+ sys.stdout.write("ERROR WHILE DOING FOLDER: %s\n" % e)
+ sys.exit(1)
try:
config = read_config()
Module: check_mk
Branch: master
Commit: 3550ec10d445e723dd3074552339149cb3f578a7
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=3550ec10d445e7…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Tue Feb 21 09:37:01 2017 +0100
Updated bug entries #2473
Change-Id: I47c65d6da83ca7a5748ff3918cd9dc054d793a80
---
.bugs/2473 | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/.bugs/2473 b/.bugs/2473
index 9fffa17..d506bdd 100644
--- a/.bugs/2473
+++ b/.bugs/2473
@@ -1,10 +1,13 @@
Title: Virtual host trees should have ids
Component: multisite
-State: open
+Class: bug
+State: done
Date: 2016-12-05 13:37:42
Targetversion: 1.2.9
-Class: bug
The virtual host trees are currently being referenced by their index. In case a tree is deleted, the
tree that a user references may change because the elements in the list virtual_host_trees have
different indexes now.
+
+2017-02-21 09:36:58: changed state open -> done
+Fixed.
Module: check_mk
Branch: master
Commit: b958e9fc7d668740fc967033b0dc403467c9994e
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=b958e9fc7d6687…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Mon Feb 20 11:46:16 2017 +0100
4381 FIX Fixed exception when WATO ruleset without main group definition exists
An exception "AttributeError ('NoneType' object has no attribute 'title')" could occur on
WATO ruleset list pages when a custom Check_MK ruleset definition exists without previous
register_rulegroup() call for the main group.
Change-Id: I188ae4404086ffa82b9c83a44a4f6bb8a84a641a
---
.werks/4381 | 11 +++++++++++
web/htdocs/watolib.py | 6 +++++-
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/.werks/4381 b/.werks/4381
new file mode 100644
index 0000000..947ec16
--- /dev/null
+++ b/.werks/4381
@@ -0,0 +1,11 @@
+Title: Fixed exception when WATO ruleset without main group definition exists
+Level: 1
+Component: wato
+Compatible: compat
+Version: 1.5.0i1
+Date: 1487587493
+Class: fix
+
+An exception "AttributeError ('NoneType' object has no attribute 'title')" could occur on
+WATO ruleset list pages when a custom Check_MK ruleset definition exists without previous
+register_rulegroup() call for the main group.
diff --git a/web/htdocs/watolib.py b/web/htdocs/watolib.py
index cab353d..63786cc 100644
--- a/web/htdocs/watolib.py
+++ b/web/htdocs/watolib.py
@@ -5913,7 +5913,11 @@ class Rulespecs(object):
choices = []
for main_group_name in self.get_main_groups():
- main_group_title = g_rulegroups.get(main_group_name).title
+ main_group = g_rulegroups.get(main_group_name)
+ if main_group:
+ main_group_title = main_group.title
+ else:
+ main_group_title = main_group_name
if mode == "static_checks" and main_group_name != "static":
continue
Module: check_mk
Branch: master
Commit: 042cad8f3d5b3f74599717d39c06fab825760831
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=042cad8f3d5b3f…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Mon Feb 20 11:53:48 2017 +0100
4382 FIX Views: Silently ignore configured but not existing view filters
Change-Id: Ie7097827f0b5edbefb6b381c12c8a5335a6fdc7a
---
.werks/4382 | 10 ++++++++++
web/htdocs/visuals.py | 17 +++++++++++++++--
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/.werks/4382 b/.werks/4382
new file mode 100644
index 0000000..f4bb6b9
--- /dev/null
+++ b/.werks/4382
@@ -0,0 +1,10 @@
+Title: Views: Silently ignore configured but not existing view filters
+Level: 1
+Component: multisite
+Class: fix
+Compatible: compat
+State: unknown
+Version: 1.5.0i1
+Date: 1487588005
+
+
diff --git a/web/htdocs/visuals.py b/web/htdocs/visuals.py
index c202d99..8be6f07 100644
--- a/web/htdocs/visuals.py
+++ b/web/htdocs/visuals.py
@@ -999,10 +999,14 @@ def filters_of_visual(visual, info_keys, show_all=False, link_filters=None):
if info_key in visual['single_infos']:
for key in info_params(info_key):
filters.append(get_filter(key))
+
elif not show_all:
for key, val in visual['context'].items():
if type(val) == dict: # this is a real filter
- filters.append(get_filter(key))
+ try:
+ filters.append(get_filter(key))
+ except KeyError:
+ pass # Silently ignore not existing filters
# See get_link_filter_names() comment for details
for key, dst_key in get_link_filter_names(visual, info_keys, link_filters):
@@ -1015,6 +1019,7 @@ def filters_of_visual(visual, info_keys, show_all=False, link_filters=None):
for fn in ubiquitary_filters:
# Disable 'wato_folder' filter, if WATO is disabled or there is a single host view
filter = get_filter(fn)
+
if fn == "wato_folder" and (not filter.available() or 'host' in visual['single_infos']):
continue
if not filter.info or filter.info in info_keys:
@@ -1272,9 +1277,16 @@ def visual_title(what, visual):
# the value of the context variable(s) is None. In order to avoid exceptions,
# we simply drop these here.
extra_titles = [ v for k, v in get_singlecontext_html_vars(visual).items() if v != None ]
+
# FIXME: Is this really only needed for visuals without single infos?
if not visual['single_infos']:
- used_filters = [ multisite_filters[fn] for fn in visual["context"].keys() ]
+ used_filters = []
+ for fn in visual["context"].keys():
+ try:
+ used_filters.append(get_filter(fn))
+ except KeyError:
+ pass # silently ignore not existing filters
+
for filt in used_filters:
heading = filt.heading_info()
if heading:
@@ -1288,6 +1300,7 @@ def visual_title(what, visual):
# Disable 'wato_folder' filter, if WATO is disabled or there is a single host view
if fn == "wato_folder" and (not config.wato_enabled or 'host' in visual['single_infos']):
continue
+
heading = get_filter(fn).heading_info()
if heading:
title = heading + " - " + title