Module: check_mk
Branch: master
Commit: 73533e25139c4d12cd43cc7364845c0be600edf1
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=73533e25139c4d…
Author: Óscar Nájera <on(a)mathias-kettner.de>
Date: Fri Mar 15 11:20:12 2019 +0100
6658 FIX Differentiation of host & service problems notifications
For REST notification plugins like Slack, PagerDuty and VictorOPS. Problems
where classified by the presence of the SERVICESTATE context variable. But
in the RAW edition this variable is completed by its macro and thus the
classification leads to host problems to be described as service problems
too. Classifying after the WHAT context variable solves the issue.
Change-Id: I08aa651604c60d2810777c73746ba43ede14c2f3
---
.werks/6658 | 16 ++++++++++++++++
cmk/notification_plugins/pagerduty.py | 2 +-
cmk/notification_plugins/slack.py | 2 +-
cmk/notification_plugins/victorops.py | 2 +-
4 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/.werks/6658 b/.werks/6658
new file mode 100644
index 0000000..ac2f7b0
--- /dev/null
+++ b/.werks/6658
@@ -0,0 +1,16 @@
+Title: Differentiation of host & service problems notifications
+Level: 1
+Component: notifications
+Class: fix
+Compatible: compat
+Edition: cre
+State: unknown
+Version: 1.6.0i1
+Date: 1552646385
+
+
+For REST notification plugins like Slack, PagerDuty and VictorOPS. Problems
+where classified by the presence of the SERVICESTATE context variable. But
+in the RAW edition this variable is completed by its macro and thus the
+classification leads to host problems to be described as service problems
+too. Classifying after the WHAT context variable solves the issue.
diff --git a/cmk/notification_plugins/pagerduty.py b/cmk/notification_plugins/pagerduty.py
index b1dfd08..80cbaed 100644
--- a/cmk/notification_plugins/pagerduty.py
+++ b/cmk/notification_plugins/pagerduty.py
@@ -71,7 +71,7 @@ def pagerduty_msg(context):
host_url, service_url = cmk_links(context)
- if context.get('SERVICESTATE', None):
+ if context.get('WHAT', None) == "SERVICE":
state = context["SERVICESTATE"]
incident_key = '{SERVICEDESC}/{HOSTNAME}:{HOSTADDRESS}'.format(**context).replace(" ", "")
incident = "{SERVICESTATE}: {SERVICEDESC} on {HOSTNAME}".format(**context)
diff --git a/cmk/notification_plugins/slack.py b/cmk/notification_plugins/slack.py
index 98518aa..0b46d45 100644
--- a/cmk/notification_plugins/slack.py
+++ b/cmk/notification_plugins/slack.py
@@ -51,7 +51,7 @@ def slack_msg(context):
extend_context_with_link_urls(context, '<{}|{}>')
- if context.get('SERVICESTATE', None):
+ if context.get('WHAT', None) == "SERVICE":
color = COLORS.get(context["SERVICESTATE"])
title = "Service {NOTIFICATIONTYPE} notification".format(**context)
text = "Host: {LINKEDHOSTNAME} (IP: {HOSTADDRESS})\nService: {LINKEDSERVICEDESC}\nState: {SERVICESTATE}".format(
diff --git a/cmk/notification_plugins/victorops.py b/cmk/notification_plugins/victorops.py
index d50dfca..bf80d79 100644
--- a/cmk/notification_plugins/victorops.py
+++ b/cmk/notification_plugins/victorops.py
@@ -51,7 +51,7 @@ def victorops_msg(context):
extend_context_with_link_urls(context, '{0}')
- if context.get('SERVICESTATE', None):
+ if context.get('WHAT', None) == "SERVICE":
state = translate_states(context["SERVICESTATE"])
entity_id = '{SERVICEDESC}/{HOSTNAME}:{HOSTADDRESS}'.format(**context).replace(" ", "")
title = "{SERVICEDESC} on {HOSTNAME}".format(**context)
Module: check_mk
Branch: master
Commit: 6ada74d0c575aacfb8e56975959dbf519891b45f
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=6ada74d0c575aa…
Author: Moritz Kiemer <mo(a)mathias-kettner.de>
Date: Fri Mar 15 14:35:12 2019 +0100
7217 FIX HW/SW-Inventory: Execution order of plugins
The order in which the HW/SW inventory plugins are executed is now deterministic.
Previously dependencies between inventory plugins could lead to missing data if
the plugins happend to be executed in the wrong order.
Plugins are now executed in alphabetical order by default. You can force a plugin
to be executed after another plugin by setting the <tt>depends_on</tt> key in
the inventory info variable <tt>inv_info</tt>. For instance writing
<tt>inv_info['plugin_a'] = {
...
'depends_on' = ['plugin_b'],
}</tt>
will enforce "plugin_b" to be executed before "plugin_a".
Change-Id: I388bf0c0fe334ad87ca38905f66bf2d5141be98f
---
.werks/7217 | 21 ++++++++++++
cmk_base/inventory.py | 5 +--
cmk_base/inventory_plugins.py | 46 +++++++++++++++++++++++++
inventory/cisco_vlans | 1 +
tests/unit/cmk_base/test_inventory_plugins.py | 48 +++++++++++++++++++++++++++
5 files changed, 117 insertions(+), 4 deletions(-)
diff --git a/.werks/7217 b/.werks/7217
new file mode 100644
index 0000000..732fe11
--- /dev/null
+++ b/.werks/7217
@@ -0,0 +1,21 @@
+Title: HW/SW-Inventory: Execution order of plugins
+Level: 1
+Component: checks
+Compatible: compat
+Edition: cre
+Version: 1.6.0i1
+Date: 1552656409
+Class: fix
+
+The order in which the HW/SW inventory plugins are executed is now deterministic.
+Previously dependencies between inventory plugins could lead to missing data if
+the plugins happend to be executed in the wrong order.
+
+Plugins are now executed in alphabetical order by default. You can force a plugin
+to be executed after another plugin by setting the <tt>depends_on</tt> key in
+the inventory info variable <tt>inv_info</tt>. For instance writing
+<tt>inv_info['plugin_a'] = {
+ ...
+ 'depends_on' = ['plugin_b'],
+}</tt>
+will enforce "plugin_b" to be executed before "plugin_a".
diff --git a/cmk_base/inventory.py b/cmk_base/inventory.py
index cb6794f..f1f54fb 100644
--- a/cmk_base/inventory.py
+++ b/cmk_base/inventory.py
@@ -237,12 +237,9 @@ def _do_inv_for_realhost(sources, multi_host_sections, hostname, ipaddress, inve
console.step("Executing inventory plugins")
import cmk_base.inventory_plugins as inventory_plugins
console.verbose("Plugins:")
- for section_name, plugin in inventory_plugins.inv_info.items():
+ for section_name, plugin in inventory_plugins.sorted_inventory_plugins():
section_content = multi_host_sections.get_section_content(
hostname, ipaddress, section_name, for_discovery=False)
- if section_content is None: # No data for this check type
- continue
-
# TODO: Don't we need to take config.check_info[check_plugin_name]["handle_empty_info"]:
# like it is done in checking.execute_check()? Standardize this!
if not section_content: # section not present (None or [])
diff --git a/cmk_base/inventory_plugins.py b/cmk_base/inventory_plugins.py
index 076682b..366143a 100644
--- a/cmk_base/inventory_plugins.py
+++ b/cmk_base/inventory_plugins.py
@@ -29,6 +29,7 @@ from typing import Any, Dict # pylint: disable=unused-import
import cmk.utils.paths
import cmk.utils.debug
+from cmk.utils.exceptions import MKGeneralException
import cmk_base.config as config
import cmk_base.console as console
@@ -127,3 +128,48 @@ def is_snmp_plugin(plugin_type):
section_name = cmk_base.check_utils.section_name_of(plugin_type)
return "snmp_info" in inv_info.get(section_name, {}) \
or cmk_base.check_utils.is_snmp_check(plugin_type)
+
+
+def sorted_inventory_plugins():
+
+ # First resolve *all* dependencies. This ensures that there
+ # are no cyclic dependencies, and that the 'depends on'
+ # relation is transitive.
+ resolved_dependencies = {}
+
+ def resolve_plugin_dependencies(plugin_name, known_dependencies=None):
+ '''recursively aggregate all plugin dependencies'''
+ if known_dependencies is None:
+ known_dependencies = set()
+ if plugin_name in resolved_dependencies:
+ known_dependencies.update(resolved_dependencies[plugin_name])
+ return known_dependencies
+
+ try:
+ direct_dependencies = set(inv_info[plugin_name].get('depends_on', []))
+ except KeyError:
+ raise MKGeneralException("unknown plugin dependency: %r" % plugin_name)
+
+ new_dependencies = direct_dependencies - known_dependencies
+ known_dependencies.update(new_dependencies)
+ for dependency in new_dependencies:
+ known_dependencies = resolve_plugin_dependencies(dependency, known_dependencies)
+ return known_dependencies
+
+ for plugin_name in inv_info:
+ resolved_dependencies[plugin_name] = resolve_plugin_dependencies(plugin_name)
+ if plugin_name in resolved_dependencies[plugin_name]:
+ raise MKGeneralException("cyclic plugin dependencies for %r" % plugin_name)
+
+ # The plugins are now a partially ordered set with respect to
+ # the 'depends on' relation. That means we can iteratively
+ # yield the minimal elements
+ remaining_plugins = set(inv_info.keys())
+ yielded_plugins = set()
+ while remaining_plugins:
+ for plugin_name in sorted(remaining_plugins):
+ dependencies = resolved_dependencies[plugin_name]
+ if dependencies <= yielded_plugins:
+ yield plugin_name, inv_info[plugin_name]
+ yielded_plugins.add(plugin_name)
+ remaining_plugins.remove(plugin_name)
diff --git a/inventory/cisco_vlans b/inventory/cisco_vlans
index 795417b..7ec6b6d 100644
--- a/inventory/cisco_vlans
+++ b/inventory/cisco_vlans
@@ -112,6 +112,7 @@ def inv_cisco_vlans(info, params):
inv_info['inv_cisco_vlans'] = {
+ 'depends_on': ['inv_if'],
"inv_function": inv_cisco_vlans,
'snmp_info': (
".1.3.6.1.4.1.9.9.68.1.2.2.1",
diff --git a/tests/unit/cmk_base/test_inventory_plugins.py b/tests/unit/cmk_base/test_inventory_plugins.py
new file mode 100644
index 0000000..35499cf
--- /dev/null
+++ b/tests/unit/cmk_base/test_inventory_plugins.py
@@ -0,0 +1,48 @@
+import pytest
+import cmk_base.inventory_plugins
+from cmk.utils.exceptions import MKGeneralException
+
+
+(a)pytest.mark.parametrize("inv_info,expected_order", [
+ ({
+ 'a_plugin': {},
+ 'b_plugin': {}
+ }, ['a_plugin', 'b_plugin']),
+ ({
+ 'a_plugin': {
+ 'depends_on': ['b_plugin']
+ },
+ 'b_plugin': {}
+ }, ['b_plugin', 'a_plugin']),
+])
+def test_iteritems_sorted_by_dependency(monkeypatch, inv_info, expected_order):
+ monkeypatch.setattr(cmk_base.inventory_plugins, "inv_info", inv_info)
+ order = [item[0] for item in cmk_base.inventory_plugins.sorted_inventory_plugins()]
+ assert order == expected_order
+
+
+def test_iteritems_sorted_by_dependency_cyclic(monkeypatch):
+ monkeypatch.setattr(
+ cmk_base.inventory_plugins, "inv_info", {
+ "a_plugin": {
+ 'depends_on': ["b_plugin"]
+ },
+ "b_plugin": {
+ 'depends_on': ["c_plugin"]
+ },
+ "c_plugin": {
+ 'depends_on': ["a_plugin"]
+ },
+ })
+ with pytest.raises(MKGeneralException, match="cyclic plugin dependencies for '._plugin'"):
+ list(cmk_base.inventory_plugins.sorted_inventory_plugins())
+
+
+def test_iteritems_sorted_by_dependency_unknown(monkeypatch):
+ monkeypatch.setattr(cmk_base.inventory_plugins, "inv_info", {
+ "a_plugin": {
+ 'depends_on': ["whoopdeedoo"]
+ },
+ })
+ with pytest.raises(MKGeneralException, match="unknown plugin dependency: 'whoopdeedoo'"):
+ list(cmk_base.inventory_plugins.sorted_inventory_plugins())
Module: check_mk
Branch: master
Commit: 69d580c062666a9cb88d6d0ce8d8495dae768d97
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=69d580c062666a…
Author: Ronny Bruska <rb(a)mathias-kettner.de>
Date: Fri Mar 15 15:24:10 2019 +0100
Fixed level and werk description
Change-Id: Id8f0093e91302e418001783263431d37f8143ac6
---
.werks/7195 | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/.werks/7195 b/.werks/7195
index 1f931d1..b6dabce 100644
--- a/.werks/7195
+++ b/.werks/7195
@@ -1,5 +1,5 @@
Title: Jira: Notification plugin
-Level: 1
+Level: 2
Component: notifications
Compatible: compat
Edition: cre
@@ -13,21 +13,22 @@ You can create issues for Host an Service Problems and optional set a resolution
In Jira you have to add two custom fields to your project screen as described <a href "https://confluence.atlassian.com/adminjiraserver/adding-a-custom-field-9388…">here</a>.
In Check_MK, under "WATO - Notifications", create a new notification rule and select Jira.
+
Parameters to set:
-<i>JIRA URL<i>: The URL to your Jira environment
-<i>User Name<i>: Jira username
-<i>Password<i>: Jira password
-<i>Project ID<i>: The Project ID the issues should be created in
-<i>Issue type ID<i>: The issue type ID
-<i>Host custom field ID<i>: The first custom field ID you created in Jira
-<i>Service custom field ID<i>: The second custom field ID you created in Jira
-<i>Monitoring URL<i>: URL of your Check_MK environment to create hyperlinks back to Check_MK (eg. https://server/site)
-<i>Priority ID<i>: The priority ID (optional)
-<i>Summary for host notifications<i>: The summary the created host issue should use (optional)
-<i>Summary for service notifications<i>: The summary the created service issue shoud use (optional)
-<i>Label<i>: Label for Jira issues. If not set, 'monitoring' will be used. (optional)
-<i>Activate resultion with following resolution transistion ID<i>: If set, the created issue will be resolved with the configured resolution ID (optional)
-<i>Set optional timeout for connections to JIRA<i>: Timeout in seconds, default is 10 (optional)
+LI:JIRA URL: The URL to your Jira environment
+LI:User Name: Jira username
+LI:Password: Jira password
+LI:Project ID: The Project ID the issues should be created in
+LI:Issue type ID: The issue type ID
+LI:Host custom field ID: The first custom field ID you created in Jira
+LI:Service custom field ID: The second custom field ID you created in Jira
+LI:Monitoring URL: URL of your Check_MK environment to create hyperlinks back to Check_MK (eg. https://server/site)
+LI:Priority ID: The priority ID (optional)
+LI:Summary for host notifications: The summary the created host issue should use (optional)
+LI:Summary for service notifications: The summary the created service issue shoud use (optional)
+LI:Label: Label for Jira issues. If not set, 'monitoring' will be used. (optional)
+LI:Activate resultion with following resolution transistion ID: If set, the created issue will be resolved with the configured resolution ID (optional)
+LI:Set optional timeout for connections to JIRA: Timeout in seconds, default is 10 (optional)
You need different Jira IDs to open/resolve issues. There are different ways to get this IDs:
LI: <a href="https://confluence.atlassian.com/jirakb/how-to-get-project-id-from-the-jira…">Jira_support</a>
Module: check_mk
Branch: master
Commit: 9146123e0d8446d2093ed57b3ca9b182a97e0629
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=9146123e0d8446…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Fri Mar 15 20:00:04 2019 +0100
Fixed title of hostname painter
The previous title was useful for the selection of painters in
the view editor, but not for the view tables when displaying a view
as user.
Change-Id: I427f52eceda78cf8a116c22dc43a6b21839e2ed0
---
cmk/gui/plugins/views/painters.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cmk/gui/plugins/views/painters.py b/cmk/gui/plugins/views/painters.py
index 2e7d50c..487c6d2 100644
--- a/cmk/gui/plugins/views/painters.py
+++ b/cmk/gui/plugins/views/painters.py
@@ -2616,7 +2616,7 @@ class PainterHost(Painter):
@property
def title(self):
- return _("Hostname, with configurable colors")
+ return _("Hostname")
@property
def short_title(self):