Module: check_mk
Branch: master
Commit: 59f6f7e32c41046a91a348f820b76fd2e4c408f3
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=59f6f7e32c4104…
Author: Andreas Boesl <ab(a)mathias-kettner.de>
Date: Tue Jul 23 10:06:15 2013 +0200
new script cmk_delete_host.py
---
doc/treasures/cmk_delete_host.py | 130 ++++++++++++++++++++++++++++++++++++++
1 file changed, 130 insertions(+)
diff --git a/doc/treasures/cmk_delete_host.py b/doc/treasures/cmk_delete_host.py
new file mode 100755
index 0000000..978a1c5
--- /dev/null
+++ b/doc/treasures/cmk_delete_host.py
@@ -0,0 +1,130 @@
+#!/usr/bin/python
+# -*- encoding: utf-8; py-indent-offset: 4 -*-
+# +------------------------------------------------------------------+
+# | ____ _ _ __ __ _ __ |
+# | / ___| |__ ___ ___| | __ | \/ | |/ / |
+# | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
+# | | |___| | | | __/ (__| < | | | | . \ |
+# | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
+# | |
+# | Copyright Mathias Kettner 2013 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-
+# ails. 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.
+
+#Author: Andreas Boesl ab(a)mathias-kettner.de
+
+# This script
+# 1) deletes the given hosts from WATO
+# 2) creates new core config
+# 3) restarts omd site
+# 4) removes all data (including rrd files) from the given hosts
+
+import os, sys, shutil, pprint
+
+# Set automation user login credentials
+automation_user = "cmdb_automation"
+automation_secret = "UVEMFMCBITYUURHPILKP"
+
+
+def usage():
+ print "usage: cmk_delete_host {hostname1 hostname2}"
+ print "Script needs to be executed as site user"
+
+if len(sys.argv) == 1:
+ usage()
+ sys.exit(1)
+
+# Check if the given host exists
+# Simple approach: Each host managed by wato has a host tag for its folder
+# which starts with /wato/
+# If this is missing -> host does not exist
+
+# Remove the host in WATO
+omd_site = os.environ["OMD_SITE"]
+if not omd_site:
+ print "This script is only executable as site user"
+ sys.exit(1)
+
+g_current_host = None
+def log(text):
+ print "%s: %s" % (g_current_host, text)
+
+def get_wato_folder(hostname):
+ process = os.popen("cmk -D " + hostname, "r")
+ output = process.read().split("\n")
+ for line in output:
+ if line.startswith("Tags:"):
+ for tag in line.split()[1:]:
+ if tag.startswith("/wato/"):
+ return tag[6:-1]
+ else:
+ log("Host not managed by WATO")
+ break
+ else:
+ log("Host has no tags")
+ return
+
+
+# Start deletion
+wato_config_changed = False
+for hostname in sys.argv[1:]:
+ if not hostname.strip():
+ continue
+
+ g_current_host = hostname
+ wato_folder = get_wato_folder(hostname)
+ if wato_folder == None:
+ continue
+
+ wato_config_changed = True
+ # Remove the host in WATO
+ command = "curl -s 'http://localhost/%(omd_site)s/check_mk/wato.py?mode=folder"\
+ "&_username=%(automation_user)s"\
+ "&_secret=%(automation_secret)s"\
+ "&_do_actions=yes"\
+ "&_do_confirm=yes"\
+ "&_delete_host=%(hostname)s"\
+ "&_transid=-1"\
+ "&folder=%(wato_folder)s' 1>/dev/null" % { "automation_user": automation_user,
+ "automation_secret": automation_secret,
+ "omd_site": omd_site,
+ "hostname": hostname,
+ "wato_folder": wato_folder }
+
+ os.system(command)
+
+# Generate monitoring configuration and restart core
+if wato_config_changed:
+ os.system("cmk -R ; omd restart")
+
+# Flushing counters, cache files, piggy files, logfiles and autochecks
+print "Flushing data"
+os.system("cmk --flush %s" % " ".join(sys.argv[1:]))
+for hostname in sys.argv[1:]:
+ if not hostname.strip():
+ continue
+
+ g_current_host = hostname
+
+ # Remove rrd files
+ path_rrd = "~/var/pnp4nagios/perfdata/" + hostname
+ path_rrd = os.path.expanduser(path_rrd)
+ if os.path.exists(path_rrd):
+ log("Removing path " + path_rrd)
+ shutil.rmtree(path_rrd)
+ else:
+ log("Host has no perfdata")
+
Module: check_mk
Branch: master
Commit: 006fbac37a02b38c1bef096847dc3ddab9cc6876
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=006fbac37a02b3…
Author: Andreas Boesl <ab(a)mathias-kettner.de>
Date: Tue Jul 23 09:11:55 2013 +0200
fixed typo
---
web/htdocs/wato.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/web/htdocs/wato.py b/web/htdocs/wato.py
index 8a3223c..d2149c7 100644
--- a/web/htdocs/wato.py
+++ b/web/htdocs/wato.py
@@ -9778,7 +9778,7 @@ def mode_ineffective_rules(phase):
html.write('<div class=rulesets>')
all_hosts = load_all_hosts()
- html.write("<div class=info>" + _("The following rules do match match to any of the existing hosts.") + "</div>")
+ html.write("<div class=info>" + _("The following rules do not match to any of the existing hosts.") + "</div>")
have_ineffective = False
for groupname in groupnames:
Module: check_mk
Branch: master
Commit: 3335179923e78ad11a6b6f3d9e6e28e72bfdc6dd
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=3335179923e78a…
Author: Mathias Kettner <mk(a)mathias-kettner.de>
Date: Mon Jul 22 17:51:47 2013 +0200
Simplify implementation of notify --keepalive
---
modules/notify.py | 131 +++++++++++++++++++++++++++++------------------------
1 file changed, 72 insertions(+), 59 deletions(-)
diff --git a/modules/notify.py b/modules/notify.py
index 9102a46..39dd198 100644
--- a/modules/notify.py
+++ b/modules/notify.py
@@ -311,7 +311,7 @@ def do_notify(args):
notify_keepalive()
else:
- notify_notify()
+ notify_notify(notification_context_from_env())
except Exception, e:
if g_interactive:
@@ -345,81 +345,91 @@ def notify_config_timestamp():
def notify_keepalive():
- global g_notify_readahead_buffer
- g_notify_readahead_buffer = ""
config_timestamp = notify_config_timestamp()
- # Send signal that we are ready to receive the next notification
- sys.stdout.write("*")
- sys.stdout.flush()
+ # Send signal that we are ready to receive the next notification, but
+ # not after a config-reload-restart (see below)
+ if os.getenv("CMK_NOTIFY_RESTART") != "1":
+ notify_log("Starting in keepalive mode with PID %d" % os.getpid())
+ sys.stdout.write("*")
+ sys.stdout.flush()
+ else:
+ notify_log("We are back after a restart.")
while True:
try:
# If the configuration has changed, we do a restart. But we do
# this check just before the next notification arrives. We must
- # *not* read data from stdin, just peek! On the other hand we
- # must *not* restart when there is danger that the buffered
- # sys.stdin has already read data from the next notification. That
- # would get lost! So we do restart if:
- # - The last time we look *no* data was available on stdin.
- # - Now there *is* data available
- # - The buffer of stdin is empty
- # - The timestamp of the youngest configuration file has changed.
+ # *not* read data from stdin, just peek! There is still one
+ # problem: when restarting we must *not* send the initial '*'
+ # byte, because that must be not no sooner then the notification
+ # has been sent. We do this by setting the environment variable
+ # CMK_NOTIFY_RESTART=1
+
if notify_data_available():
- if not g_notify_readahead_buffer:
- current_config_timestamp = notify_config_timestamp()
- if current_config_timestamp > config_timestamp:
- notify_log("Configuration has changed. Restarting myself.")
- os.execvp("cmk", sys.argv)
-
- new_data = os.read(0, 20000)
- if not new_data:
- sys.exit(0) # closed stdin
- g_notify_readahead_buffer += new_data
- if g_notify_readahead_buffer.startswith('\n\n'):
- sys.exit(0)
- while '\n\n' in g_notify_readahead_buffer:
+ current_config_timestamp = notify_config_timestamp()
+ if current_config_timestamp > config_timestamp:
+ notify_log("Configuration has changed. Restarting myself.")
+ os.putenv("CMK_NOTIFY_RESTART", "1")
+ os.execvp("cmk", sys.argv)
+
+ data = ""
+ while not data.endswith("\n\n"):
try:
- notify_notify()
+ new_data = ""
+ new_data = os.read(0, 32768)
+ except IOError, e:
+ new_data = ""
except Exception, e:
if opt_debug:
raise
- notify_log("ERROR %s\n%s" % (e, format_exception()))
- sys.stdout.write("*")
- sys.stdout.flush()
+ notify_log("Cannot read data from CMC: %s" % e)
+
+ if not new_data:
+ notify_log("CMC has closed the connection. Shutting down.")
+ sys.exit(0) # closed stdin, this is
+ data += new_data
+
+ try:
+ context = notification_context_from_string(data.rstrip('\n'))
+ notify_notify(context)
+ except Exception, e:
+ if opt_debug:
+ raise
+ notify_log("ERROR %s\n%s" % (e, format_exception()))
+
+ # Signal that we are ready for the next notification
+ sys.stdout.write("*")
+ sys.stdout.flush()
except Exception, e:
if opt_debug:
raise
notify_log("ERROR %s\n%s" % (e, format_exception()))
-# Note: The values of the context are *always* unicode!
-def notify_get_context():
- global g_notify_readahead_buffer
- if opt_keepalive:
- # Context is line-by-line in g_notify_readahead_buffer
- this_part, rest = g_notify_readahead_buffer.split('\n\n', 1)
- g_notify_readahead_buffer = rest
- context = {}
- try:
- for line in this_part.split('\n'):
- varname, value = line.strip().split("=", 1)
- context[varname] = value
- except Exception, e: # line without '=' ignored or alerted
- if opt_debug:
- raise
- return context
- else:
- # Information about notification is excpected in the
- # environment in variables with the prefix NOTIFY_
- return dict([
- (var[7:], value)
- for (var, value)
- in os.environ.items()
- if var.startswith("NOTIFY_")
- and not re.match('^\$[A-Z]+\$$', value)])
+def notification_context_from_string(data):
+ # Context is line-by-line in g_notify_readahead_buffer
+ context = {}
+ try:
+ for line in data.split('\n'):
+ varname, value = line.strip().split("=", 1)
+ context[varname] = value
+ except Exception, e: # line without '=' ignored or alerted
+ if opt_debug:
+ raise
+ return context
+
+def notification_context_from_env():
+ # Information about notification is excpected in the
+ # environment in variables with the prefix NOTIFY_
+ return dict([
+ (var[7:], value)
+ for (var, value)
+ in os.environ.items()
+ if var.startswith("NOTIFY_")
+ and not re.match('^\$[A-Z]+\$$', value)])
def convert_context_to_unicode(context):
@@ -435,8 +445,7 @@ def convert_context_to_unicode(context):
value_unicode = u"(Invalid byte sequence)"
context[key] = value_unicode
-def notify_notify():
- context = notify_get_context()
+def notify_notify(context):
notify_log("Got notification context with %s variables" % len(context))
# Add a few further helper variables
@@ -516,7 +525,7 @@ def notify_via_email(context, write_into_spoolfile):
subject = substitute_context(subject_t, context)
context["SUBJECT"] = subject
body = substitute_context(notification_common_body + body_t, context)
- command = substitute_context(notification_mail_command, context)
+ command = substitute_context(notification_mail_command, context) + " >/dev/null 2>&1"
command_utf8 = command.encode("utf-8")
if notification_logging >= 2:
notify_log("Executing command: %s" % command)
@@ -528,6 +537,10 @@ def notify_via_email(context, write_into_spoolfile):
os.putenv("LANG", "C.UTF-8")
if notification_logging >= 2:
file(var_dir + "/notify/body.log", "w").write(body.encode("utf-8"))
+
+ # Important: we must not output anything on stdout or stderr. Data of stdout
+ # goes back into the socket to the CMC in keepalive mode and garbles the
+ # handshake signal.
return os.popen(command_utf8, "w").write(body.encode("utf-8"))
Module: check_mk
Branch: master
Commit: 3d433c095126fa1c2ce95a59564bf17e4dfd6622
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=3d433c095126fa…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Mon Jul 22 17:05:32 2013 +0200
FIX: fix logwatch pattern analyzer after direct access to the page
---
ChangeLog | 3 ++-
web/htdocs/wato.py | 1 +
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/ChangeLog b/ChangeLog
index 3232296..d38b6d2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -274,7 +274,8 @@
* FIX: avoid exception when called first time and first page ist host tags
* FIX: fix validation of time-of-day input field (24:00)
* FIX: automation users can now be deleted again (bug was introduced in 1.2.2p1)
-
+ * FIX: fix logwatch pattern analyzer message "The host xyz is not
+ managed by WATO." after direct access via snapin
1.2.2p2:
Core:
diff --git a/web/htdocs/wato.py b/web/htdocs/wato.py
index f35d554..ebdae6d 100644
--- a/web/htdocs/wato.py
+++ b/web/htdocs/wato.py
@@ -11841,6 +11841,7 @@ def mode_pattern_editor(phase):
html.text_input('match', cssclass = 'match', size=100)
forms.end()
html.button('_try', _('Try out'))
+ html.del_var('folder') # Never hand over the folder here
html.hidden_fields()
html.end_form()