Module: check_mk
Branch: master
Commit: f01183dc594ef43beca8befeef55461ba6b0f9e7
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=f01183dc594ef4…
Author: Moritz Kiemer <mo(a)mathias-kettner.de>
Date: Fri Nov 23 09:44:54 2018 +0100
6941 FIX mk_logwatch.aix: Don't clear systems error log
The systems error log (errpt) is no longer cleared ("errclear 0").
Previously the errorlog has been cleared after each run of the plugin,
and a backup file of the error log has been created as
/var/log/errpt_$DATE.log.
This is no longer the case, as a less intrusive way to avoid
redundant log messages has been established.
Change-Id: I239d67767e7d5f258fee4616bbd45cd3a89c803f
---
.werks/6941 | 16 +++++
agents/plugins/mk_logwatch.aix | 33 ++++++++---
tests/unit/plugins/test_mk_logwatch_aix.py | 93 ++++++++++++++++++++++++++++++
3 files changed, 135 insertions(+), 7 deletions(-)
diff --git a/.werks/6941 b/.werks/6941
new file mode 100644
index 0000000..1225d43
--- /dev/null
+++ b/.werks/6941
@@ -0,0 +1,16 @@
+Title: mk_logwatch.aix: Don't clear systems error log
+Level: 1
+Component: checks
+Compatible: compat
+Edition: cre
+Version: 1.6.0i1
+Date: 1542962724
+Class: fix
+
+The systems error log (errpt) is no longer cleared ("errclear 0").
+Previously the errorlog has been cleared after each run of the plugin,
+and a backup file of the error log has been created as
+/var/log/errpt_$DATE.log.
+
+This is no longer the case, as a less intrusive way to avoid
+redundant log messages has been established.
diff --git a/agents/plugins/mk_logwatch.aix b/agents/plugins/mk_logwatch.aix
index 8996093..ceb7ec0 100755
--- a/agents/plugins/mk_logwatch.aix
+++ b/agents/plugins/mk_logwatch.aix
@@ -1,13 +1,32 @@
#!/usr/bin/ksh
# Logfile monitoring for AIX via errpt
-# Beware: This Plugin clears the errors after each run,
-# but it creates an detailed backup in /var/log/errpt_TIMESTAMP.log
+
+## Output of errpt looks like this, newest first
+## (timestamp is month-day-hour-minute-year):
+# IDENTIFIER TIMESTAMP T C RESOURCE_NAME DESCRIPTION
+# 8650BE3F 0820122810 I H ent2 ETHERCHANNEL RECOVERY
+# F3846E13 0820122510 P H ent2 ETHERCHANNEL FAILOVER
+# 8650BE3F 0820104410 I H ent2 ETHERCHANNEL RECOVERY
+# F3846E13 0820093810 P H ent2 ETHERCHANNEL FAILOVER
+# 8650BE3F 0820090910 I H ent2 ETHERCHANNEL RECOVERY
+#
+
+MK_LOGWATCH_AIX_STATE="$MK_VARDIR/mk_logwatch_aix.last_reported"
echo "<<<logwatch>>>"
echo "[[[errorlog]]]"
-OUT=$(errpt | awk 'NR>1 { printf "C %s\n", $0 }')
-if [[ $OUT != '' ]];then
- echo "$OUT"
- errpt -a > /var/log/errpt_$(date +%s).log
- errclear 0
+
+# the last line we already reported (may be empty)
+LINE=$(tail -n1 "$MK_LOGWATCH_AIX_STATE" 2> /dev/null)
+
+if [[ "$LINE" ]]; then # get rid of all lines after that:
+ OUT=$(errpt | awk '/'"$LINE"'/ {exit}; (NR>1) {printf
"C %s\n", $0}')
+else # LINE is empty -> report all
+ OUT=$(errpt | awk '(NR>1) {printf "C %s\n", $0}')
fi
+
+if [[ "$OUT" ]]; then
+ # output data; if successful, remember most recent
+ echo "$OUT" && echo "$OUT" | head -n1 | sed 's/^C\
//' > "$MK_LOGWATCH_AIX_STATE"
+fi
+
diff --git a/tests/unit/plugins/test_mk_logwatch_aix.py
b/tests/unit/plugins/test_mk_logwatch_aix.py
new file mode 100644
index 0000000..2840f37
--- /dev/null
+++ b/tests/unit/plugins/test_mk_logwatch_aix.py
@@ -0,0 +1,93 @@
+import os
+import subprocess
+import pytest
+from testlib import cmk_path
+
+PLUGIN = os.path.join(cmk_path(), 'agents', 'plugins',
'mk_logwatch.aix')
+
+ERRPT_OUTPUT = [
+ 'IDENTIFIER TIMESTAMP T C RESOURCE_NAME DESCRIPTION',
+ '8650BE3F 0820122810 I H ent2 ETHERCHANNEL RECOVERY',
+ 'F3846E13 0820122510 P H ent2 ETHERCHANNEL FAILOVER',
+ '8650BE3F 0820104410 I H ent2 ETHERCHANNEL RECOVERY',
+ 'F3846E13 0820093810 P H ent2 ETHERCHANNEL FAILOVER',
+ '8650BE3F 0820090910 I H ent2 ETHERCHANNEL RECOVERY',
+]
+
+
+def _prepare_mock_errpt(tmpdir, errpt_output):
+ errpt_name = str(tmpdir.join('errpt'))
+ errpt_script = ''.join(['#!/bin/sh\n'] + ['echo
"%s"\n' % line for line in errpt_output])
+ with open(errpt_name, 'w') as errpt_file:
+ errpt_file.write(errpt_script)
+ os.chmod(errpt_name, 0777)
+
+
+def _get_env(tmpdir):
+ env = os.environ.copy()
+ env.update({"PATH": '%s:%s' % (tmpdir,
os.getenv("PATH")), "MK_VARDIR": "%s" % tmpdir})
+ return env
+
+
+class StateFile(object):
+ def __init__(self, tmpdir):
+ super(StateFile, self).__init__()
+ self.name = str(tmpdir.join('mk_logwatch_aix.last_reported'))
+
+ def set(self, state):
+ if state is None:
+ try:
+ os.remove(self.name)
+ except OSError:
+ pass
+ return
+ with open(self.name, 'w') as statefile:
+ statefile.write("%s\n" % state)
+
+ def content(self):
+ try:
+ content = open(self.name).read()
+ # ends with newline
+ assert content[-1] == '\n'
+ return content[:-1]
+ except IOError:
+ return None
+
+
+def _format_expected(lines):
+ added_prefix = ['C %s\n' % line for line in lines]
+ added_header = ['<<<logwatch>>>\n',
'[[[errorlog]]]\n'] + added_prefix
+ return ''.join(added_header)
+
+
+(a)pytest.mark.parametrize(
+ "errpt_output,last_reported,expectations",
+ [
+ (
+ ERRPT_OUTPUT,
+ [None, "", ERRPT_OUTPUT[3], ERRPT_OUTPUT[1], "something else
entirely"],
+ [ERRPT_OUTPUT[1:], ERRPT_OUTPUT[1:], ERRPT_OUTPUT[1:3], [],
ERRPT_OUTPUT[1:]],
+ ),
+ (
+ ERRPT_OUTPUT[:1], # no output, just header
+ [None, "", "what ever"],
+ [[], [], []],
+ ),
+ ])
+def test_mk_logwatch_aix(tmpdir, errpt_output, last_reported, expectations):
+
+ _prepare_mock_errpt(tmpdir, errpt_output)
+ env = _get_env(tmpdir)
+ statefile = StateFile(tmpdir)
+
+ for state, expected in zip(last_reported, expectations):
+
+ statefile.set(state)
+
+ output = subprocess.check_output(PLUGIN, env=env)
+
+ assert output == _format_expected(expected)
+ if len(errpt_output) > 1: # we should have updated state file
+ assert statefile.content() == errpt_output[1]
+ else: # it should not have changed
+ assert statefile.content() == state