Module: check_mk
Branch: master
Commit: e95ca3af09f75b525ff0fa41c093c815f5e056d0
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=e95ca3af09f75b…
Author: Óscar Nájera <on(a)mathias-kettner.de>
Date: Mon Sep 17 15:59:36 2018 +0200
Notification script that messages to slack webhook
- Deals with host state changes and service state changes
- Config WATO GUI
- Split contexts so that multiple users can be mentioned in the message
- Referenced Host and services are hyperlinked to Check_MK
Change-Id: Iffaa4a9b00365bbcdcbc9d4394f2eefb3d519bc4
---
.werks/6639 | 21 +++++
cmk/gui/plugins/wato/notifications.py | 47 ++++++++++++
cmk_base/notify.py | 2 +-
notifications/slack | 139 ++++++++++++++++++++++++++++++++++
4 files changed, 208 insertions(+), 1 deletion(-)
diff --git a/.werks/6639 b/.werks/6639
new file mode 100644
index 0000000..0227c3e
--- /dev/null
+++ b/.werks/6639
@@ -0,0 +1,21 @@
+Title: slack: New notification plugin for slack
+Level: 1
+Component: notifications
+Compatible: compat
+Edition: cre
+Version: 1.6.0i1
+Date: 1537357015
+Class: feature
+
+It is now possible to for Check_MK to send notifications about state
+changes of hosts and services into a Slack channel.
+
+Slack needs to be first configured to recieve messages from Check_MK. This
+can be done by setting up a Webhook <a
+href=\"https://my.slack.com/services/new/incoming-webhook/\"
+target=\"_blank\"> here </a>, where you specify which channel wil recieve
+the notifications. In Check_MK, under WATO->Notifications, create a new
+notification rule. And select under Notification Method Slack. Copy the URL
+that Slack gives you after completing the configuration into the Slack
+Webhook-URL field. Optionally if you want sent messages to include
+hyperlinks to Check_MK, enable the field URL prefix for links to Check_MK.
diff --git a/cmk/gui/plugins/wato/notifications.py b/cmk/gui/plugins/wato/notifications.py
old mode 100644
new mode 100755
index b014aa8..19f362f
--- a/cmk/gui/plugins/wato/notifications.py
+++ b/cmk/gui/plugins/wato/notifications.py
@@ -196,6 +196,53 @@ register_notification_parameters(
)
)
+register_notification_parameters(
+ "slack",
+ Dictionary(
+ optional_keys=["url_prefix"],
+ elements=[
+ ("webhook_url",
+ TextAscii(
+ title=_("Slack Webhook-URL"),
+ size=80,
+ allow_empty=False,
+ help=_(
+ "URL from Slack Webhook. Setup one <a href=\"https://my.slack.com/services/new/incoming-webhook/\" target=\"_blank\"> here </a>"),
+ regex="^https://hooks.slack.com/services/.+",
+ regex_error=_("The Webhook-URL must begin with "
+ "<tt>https://hooks.slack.com/services/</tt>"),
+ )
+ ),
+ ("url_prefix",
+ Transform(CascadingDropdown(
+ style="dropdown",
+ title=_("URL prefix for links to Check_MK"),
+ help=_("If you use <b>Automatic HTTP/s</b> the URL prefix for "
+ "host and service links within the notification mail "
+ "is filled automatically. "
+ "If you specify an URL prefix here, then several parts of the "
+ "slack message are armed with hyperlinks to your Check_MK GUI. In both cases "
+ "the recipient of the message can directly visit the host or "
+ "service in question in Check_MK. Specify an absolute URL including "
+ "the <tt>.../check_mk/</tt>"),
+ choices=[
+ ("automatic_http", _("Automatic HTTP")),
+ ("automatic_https", _("Automatic HTTPs")),
+ ("manual", _("Specify URL prefix"), TextAscii(
+ regex="^(http|https)://.*/check_mk/$",
+ regex_error=_("The URL must begin with <tt>http</tt> or "
+ "<tt>https</tt> and end with <tt>/check_mk/</tt>."),
+ size=64,
+ default_value="http://" + socket.gethostname() + "/" + (
+ config.omd_site() and config.omd_site() + "/" or "") + "check_mk/",
+ )),
+ ],
+ ), forth=transform_forth_html_mail_url_prefix,
+ back=transform_back_html_mail_url_prefix)
+ ),
+ ]
+ )
+)
register_notification_parameters(
"asciimail",
diff --git a/cmk_base/notify.py b/cmk_base/notify.py
old mode 100644
new mode 100755
index 28f6ce8..2b1e745
--- a/cmk_base/notify.py
+++ b/cmk_base/notify.py
@@ -526,7 +526,7 @@ def notify_rulebased(raw_context, analyse=False):
plugin_context = create_plugin_context(raw_context, params)
rbn_add_contact_information(plugin_context, contacts)
- split_contexts = (plugin not in ["", "mail", "asciimail"] or
+ split_contexts = (plugin not in ["", "mail", "asciimail", "slack"] or
# params can be a list (e.g. for custom notificatios)
params.get("disable_multiplexing") or
bulk)
diff --git a/notifications/slack b/notifications/slack
new file mode 100755
index 0000000..2410324
--- /dev/null
+++ b/notifications/slack
@@ -0,0 +1,139 @@
+#!/usr/bin/env python
+# Slack
+
+# +------------------------------------------------------------------+
+# | ____ _ _ __ __ _ __ |
+# | / ___| |__ ___ ___| | __ | \/ | |/ / |
+# | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
+# | | |___| | | | __/ (__| < | | | | . \ |
+# | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
+# | |
+# | Copyright Mathias Kettner 2018 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.
+r"""
+Send notification messages to slack
+===================================
+
+Use a slack webhook to send notification messages
+"""
+
+from typing import Dict # pylint: disable=unused-import
+import os
+import sys
+import requests
+
+COLORS = {
+ "CRITICAL": "#EE0000",
+ "DOWN": "#EE0000",
+ "WARNING": "#FFDD00",
+ "OK": "#00CC00",
+ "UP": "#00CC00",
+ "UNKNOWN": "#CCCCCC",
+ "UNREACHABLE": "#CCCCCC",
+}
+
+
+def extend_context_with_link_urls(context):
+ if context.get("PARAMETER_URL_PREFIX"):
+ url_prefix = context["PARAMETER_URL_PREFIX"]
+ elif context.get("PARAMETER_URL_PREFIX_MANUAL"):
+ url_prefix = context["PARAMETER_URL_PREFIX_MANUAL"]
+ elif context.get("PARAMETER_URL_PREFIX_AUTOMATIC") == "http":
+ url_prefix = "http://%s/%s" % (context["MONITORING_HOST"], context["OMD_SITE"])
+ elif context.get("PARAMETER_URL_PREFIX_AUTOMATIC") == "https":
+ url_prefix = "https://%s/%s" % (context["MONITORING_HOST"], context["OMD_SITE"])
+ else:
+ url_prefix = None
+
+ if url_prefix:
+ base_url = url_prefix.rstrip('/')
+ if base_url.endswith("/check_mk"):
+ base_url = base_url[:-9]
+ host_url = base_url + context['HOSTURL']
+
+ context['LINKEDHOSTNAME'] = '<%s|%s>' % (host_url, context['HOSTNAME'])
+
+ if context['WHAT'] == 'SERVICE':
+ service_url = base_url + context['SERVICEURL']
+ context['LINKEDSERVICEDESC'] = '<%s|%s>' % (service_url, context['SERVICEDESC'])
+
+ else:
+ context['LINKEDHOSTNAME'] = context['HOSTNAME']
+ context['LINKEDSERVICEDESC'] = context.get('SERVICEDESC', '')
+
+
+def construct_message(context):
+ # type: (Dict) -> Dict
+ """Build the message for slack"""
+
+ extend_context_with_link_urls(context)
+
+ if context.get('SERVICESTATE', None):
+ color = COLORS.get(context["SERVICESTATE"])
+ title = "Service {NOTIFICATIONTYPE} notification".format(**context)
+ text = "Host: {LINKEDHOSTNAME} (IP: {HOSTADDRESS})\nService: {LINKEDSERVICEDESC}\nState: {SERVICESTATE}".format(
+ **context)
+ output = context["SERVICEOUTPUT"]
+ else:
+ color = COLORS.get(context["HOSTSTATE"])
+ title = "Host {NOTIFICATIONTYPE} notification".format(**context)
+ text = "Host: {LINKEDHOSTNAME} (IP: {HOSTADDRESS})\nState: {HOSTSTATE}".format(**context)
+ output = context["HOSTOUTPUT"]
+
+ return {
+ "attachments": [
+ {
+ "color": color,
+ "title": title,
+ "text": text,
+ },
+ {
+ "color":
+ color,
+ "title":
+ "Additional Info",
+ "text":
+ output + "\nPlease take a look: " + ", ".join(
+ map("@{}".format, context["CONTACTNAME"].split(','))),
+ "footer":
+ "Check_MK notification: {LONGDATETIME}".format(**context),
+ },
+ ]
+ }
+
+
+def main():
+ context = {
+ var[7:]: value.decode("utf-8")
+ for (var, value) in os.environ.items()
+ if var.startswith("NOTIFY_")
+ }
+
+ url = context.get("PARAMETER_WEBHOOK_URL")
+
+ r = requests.post(url=url, json=construct_message(context))
+
+ if r.status_code == 200:
+ sys.exit(0)
+ else:
+ sys.stderr.write(
+ "Failed to send notification. Status: %i, Response: %s\n" % (r.status_code, r.text))
+ sys.exit(2)
+
+
+if __name__ == '__main__':
+ main()
Module: check_mk
Branch: master
Commit: 4b7a09b0ef5cbd97534abcdef4f462a04ec6e316
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=4b7a09b0ef5cbd…
Author: Simon Betz <si(a)mathias-kettner.de>
Date: Thu Sep 20 14:57:25 2018 +0200
6603 FIX CRE: Fixed Check_MK service crash if a check plugin is unknown to the check context
Change-Id: I6e4103da535162f18d8eb2cd51948f42b0239db4
---
.werks/6603 | 19 +++++++++++++++++++
cmk_base/check_table.py | 11 ++++++++---
2 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/.werks/6603 b/.werks/6603
new file mode 100644
index 0000000..213796c
--- /dev/null
+++ b/.werks/6603
@@ -0,0 +1,19 @@
+Title: CRE: Fixed Check_MK service crash if a check plugin is unknown to the check context
+Level: 1
+Component: checks
+Class: fix
+Compatible: compat
+Edition: cre
+State: unknown
+Version: 1.6.0i1
+Date: 1537441766
+
+A host has discovered a set of check plugin names which are triggered by the
+Check_MK service. If the agent type of this host changes without performing a
+rediscovery afterwards and the configuration changes are activated then there
+may be new or vanished check plugins which are unknown to the current check
+context. This leads to a KeyError of the Check_MK service.
+
+Now if a check plugin is unknown to the current check context Check_MK ignores
+this check plugin. Aside from that the Check_MK Discovery service reports about
+vanished or unmonitored serices.
diff --git a/cmk_base/check_table.py b/cmk_base/check_table.py
index 2a28d16..03d6dd4 100644
--- a/cmk_base/check_table.py
+++ b/cmk_base/check_table.py
@@ -78,14 +78,19 @@ def get_check_table(hostname, remove_duplicates=False, use_cache=True,
return is_checkname_valid_cache[the_id]
passed = True
+ if checkname not in config.check_info:
+ passed = False
+
# Skip SNMP checks for non SNMP hosts (might have been discovered before with other
# agent setting. Remove them without rediscovery). Same for agent based checks.
- if not config.is_snmp_host(hostname) and cmk_base.check_utils.is_snmp_check(checkname) and \
+ elif not config.is_snmp_host(hostname) and cmk_base.check_utils.is_snmp_check(checkname) and \
(not config.has_management_board(hostname) or config.management_protocol_of(hostname) != "snmp"):
- passed = False
- if not config.is_tcp_host(hostname) and not piggyback.has_piggyback_raw_data(config.piggyback_max_cachefile_age, hostname) \
+ passed = False
+
+ elif not config.is_tcp_host(hostname) and not piggyback.has_piggyback_raw_data(config.piggyback_max_cachefile_age, hostname) \
and cmk_base.check_utils.is_tcp_check(checkname):
passed = False
+
is_checkname_valid_cache[the_id] = passed
return passed
Module: check_mk
Branch: master
Commit: e84c0d1e20f68eccb9031e7a6db2f7a76c7f3ad9
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=e84c0d1e20f68e…
Author: Konstantin Büttner <kb(a)mathias-kettner.de>
Date: Thu Sep 20 13:25:27 2018 +0200
6467 FIX jolokia_metrics.tp: Only discover services which can be checked
In some circumstances, Check_MK would discover services for which the maxThreads
value of the thread pool was missing, leading to permanently unknown services.
This has been fixed.
Change-Id: I4ac30ba799eb67bc6ed450df8ada4c2cee73aed8
---
.werks/6467 | 13 +++++++++++++
checks/jolokia_metrics | 5 +++--
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/.werks/6467 b/.werks/6467
new file mode 100644
index 0000000..6d683d6
--- /dev/null
+++ b/.werks/6467
@@ -0,0 +1,13 @@
+Title: jolokia_metrics.tp: Only discover services which can be checked
+Level: 1
+Component: checks
+Class: fix
+Compatible: compat
+Edition: cre
+State: unknown
+Version: 1.6.0i1
+Date: 1537442631
+
+In some circumstances, Check_MK would discover services for which the maxThreads
+value of the thread pool was missing, leading to permanently unknown services.
+This has been fixed.
diff --git a/checks/jolokia_metrics b/checks/jolokia_metrics
index 4709cea..c3ff118 100644
--- a/checks/jolokia_metrics
+++ b/checks/jolokia_metrics
@@ -460,8 +460,9 @@ def inventory_jolokia_metrics_tp(info):
for inst, vals in parsed.iteritems():
if vals is None:
continue # no data from agent
- for threadpool_name, _threadpool_info in vals.get('tp', {}).iteritems():
- inv.append(("%s ThreadPool %s" % (inst, threadpool_name) , {}))
+ for threadpool_name, threadpool_info in vals.get('tp', {}).iteritems():
+ if "maxThreads" in threadpool_info:
+ inv.append(("%s ThreadPool %s" % (inst, threadpool_name) , {}))
return inv