Module: check_mk
Branch: master
Commit: 9799cc1c076819cf17bbaf605bd4eec13bff6c1d
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=9799cc1c076819…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Thu Jun 5 08:30:22 2014 +0200
Agent versions can now be checked with "at least version X" parameters
The rule "Check for correct version of Check_MK agent" can now check for
minimal
versions instead of specific ones. You can configure minimal build and/or release
versions your agents need to be.
---
.werks/814 | 10 ++++
ChangeLog | 1 +
modules/check_mk.py | 12 +++-
modules/check_mk_base.py | 88 +++++++++++++++++++++++++++-
web/plugins/wato/check_mk_configuration.py | 46 +++++++++++----
5 files changed, 140 insertions(+), 17 deletions(-)
diff --git a/.werks/814 b/.werks/814
new file mode 100644
index 0000000..977fc4a
--- /dev/null
+++ b/.werks/814
@@ -0,0 +1,10 @@
+Title: Agent versions can now be checked with "at least version X" parameters
+Level: 1
+Component: checks
+Version: 1.2.5i4
+Date: 1401949735
+Class: feature
+
+The rule "Check for correct version of Check_MK agent" can now check for
minimal
+versions instead of specific ones. You can configure minimal build and/or release
+versions your agents need to be.
diff --git a/ChangeLog b/ChangeLog
index 6bcfcdd..d5909c2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,7 @@
1.2.5i4:
Checks & Agents:
* 0812 nginx_status: New check for monitoring status information of the Nginx web
server...
+ * 0814 Agent versions can now be checked with "at least version X"
parameters...
Multisite:
* 0934 FIX: Logwatch messages with class unknown ( 'u' ) now displayed as
WARN...
diff --git a/modules/check_mk.py b/modules/check_mk.py
index eb34e88..867e8d0 100755
--- a/modules/check_mk.py
+++ b/modules/check_mk.py
@@ -651,12 +651,18 @@ def check_interval_of(hostname, checkname):
def agent_target_version(hostname):
agent_target_versions = host_extra_conf(hostname, check_mk_agent_target_versions)
if len(agent_target_versions) > 0:
- if agent_target_versions[0] == "ignore":
+ spec = agent_target_versions[0]
+ if spec == "ignore":
return None
- elif agent_target_versions[0] == "site":
+ elif spec == "site":
return check_mk_version
+ elif type(spec) == str:
+ # Compatibility to old value specification format (a single version string)
+ return spec
+ elif spec[0] == 'specific':
+ return spec[1]
else:
- return agent_target_versions[0]
+ return spec # return the whole spec in case of an "at least
version" config
regex_cache = {}
def regex(r):
diff --git a/modules/check_mk_base.py b/modules/check_mk_base.py
index 511adf0..7fbb1bb 100644
--- a/modules/check_mk_base.py
+++ b/modules/check_mk_base.py
@@ -973,8 +973,23 @@ def do_check(hostname, ipaddress, only_check_types = None):
elif num_errors > 0:
output = "Got no information from host, "
status = exit_spec.get("empty_output", 2)
- elif expected_version and agent_version != expected_version:
- output = "unexpected agent version %s (should be %s), " %
(agent_version, expected_version)
+ elif expected_version and agent_version \
+ and not is_expected_agent_version(agent_version, expected_version):
+ # expected version can either be:
+ # a) a single version string
+ # b) a tuple of ("at_least", {'daily_build':
'2014.06.01', 'release': '1.2.5i4'}
+ # (the dict keys are optional)
+ if type(expected_version) == tuple and expected_version[0] ==
'at_least':
+ expected = 'at least'
+ if 'daily_build' in expected_version[1]:
+ expected += ' build %s' %
expected_version[1]['daily_build']
+ if 'release' in expected_version[1]:
+ if 'daily_build' in expected_version[1]:
+ expected += ' or'
+ expected += ' release %s' %
expected_version[1]['release']
+ else:
+ expected = expected_version
+ output = "unexpected agent version %s (should be %s), " %
(agent_version, expected)
status = exit_spec.get("wrong_version", 1)
elif agent_min_version and agent_version < agent_min_version:
output = "old plugin version %s (should be at least %s), " %
(agent_version, agent_min_version)
@@ -1409,6 +1424,75 @@ def username():
def i_am_root():
return os.getuid() == 0
+# Parses versions of Check_MK and converts them into comparable integers.
+# This does not handle daily build numbers, only official release numbers.
+# 1.2.4p1 -> 01020450001
+# 1.2.4 -> 01020450000
+# 1.2.4b1 -> 01020420100
+# 1.2.3i1p1 -> 01020310101
+# 1.2.3i1 -> 01020310100
+def parse_version(v):
+ def extract_number(s):
+ number = ''
+ for i, c in enumerate(s):
+ try:
+ int(c)
+ number += c
+ except ValueError:
+ s = s[i:]
+ return number and int(number) or 0, s
+ return number and int(number) or 0, ''
+
+ major, minor, rest = v.split('.')
+ sub, rest = extract_number(rest)
+
+ if not rest:
+ val = 50000
+ elif rest[0] == 'p':
+ num, rest = extract_number(rest[1:])
+ val = 50000 + num
+ elif rest[0] == 'i':
+ num, rest = extract_number(rest[1:])
+ val = 10000 + num*100
+
+ if rest and rest[0] == 'p':
+ num, rest = extract_number(rest[1:])
+ val += num
+ elif rest[0] == 'b':
+ num, rest = extract_number(rest[1:])
+ val = 20000 + num*100
+
+ return int('%02d%02d%02d%05d' % (int(major), int(minor), sub, val))
+
+def is_expected_agent_version(agent_version, expected_version):
+ try:
+ if type(expected_version) == str and expected_version != agent_version:
+ return False
+
+ elif type(expected_version) == tuple and expected_version[0] ==
'at_least':
+ is_daily_build = len(agent_version) == 10 or '-' in agent_version
+
+ spec = expected_version[1]
+ if is_daily_build and 'daily_build' in spec:
+ expected = int(spec['daily_build'].replace('.',
''))
+ if len(agent_version) == 10: # master build
+ agent = int(agent_version.replace('.', ''))
+
+ else: # branch build (e.g. 1.2.4-2014.06.01)
+ agent = int(agent_version.split('-')[1].replace('.',
''))
+
+ if agent < expected:
+ return False
+
+ elif 'release' in spec:
+ if parse_version(agent_version) <
parse_version(spec['release']):
+ return False
+
+ return True
+ except Exception, e:
+ raise MKGeneralException("Unable to check agent version (Agent: %s Expected:
%s, Error: %s)" %
+ (agent_version, expected_version, e))
+
# Returns the nodes of a cluster, or None if hostname is
# not a cluster
g_nodesof_cache = {}
diff --git a/web/plugins/wato/check_mk_configuration.py
b/web/plugins/wato/check_mk_configuration.py
index 6e034b0..dd48836 100644
--- a/web/plugins/wato/check_mk_configuration.py
+++ b/web/plugins/wato/check_mk_configuration.py
@@ -2286,18 +2286,40 @@ register_rule(group,
register_rule(group,
"check_mk_agent_target_versions",
- OptionalDropdownChoice(
- title = _("Check for correct version of Check_MK agent"),
- help = _("If you want to make sure all of your Check_MK agents are
running"
- " one specific version, you may set it by this rule. Agents running
"
- " some different version return a none ok state then"),
- choices = [
- ("ignore", _("Ignore the version")),
- ("site", _("Same version as the monitoring site")),
- ],
- otherlabel = _("Specific version"),
- explicit = TextAscii(allow_empty = False),
- default_value = "ignore",
+ Transform(
+ CascadingDropdown(
+ title = _("Check for correct version of Check_MK agent"),
+ help = _("If you want to make sure all of your Check_MK agents are
running"
+ " one specific version, you may set it by this rule. Agents
running "
+ " some different version return a none ok state then"),
+ choices = [
+ ("ignore", _("Ignore the version")),
+ ("site", _("Same version as the monitoring
site")),
+ ("specific", _("Specific version"),
+ TextAscii(
+ allow_empty = False,
+ )
+ ),
+ ("at_least", _("At least"),
+ Dictionary(
+ elements = [
+ ('release', TextAscii(
+ title = _('Official Release version'),
+ allow_empty = False,
+ )),
+ ('daily_build', TextAscii(
+ title = _('Daily build'),
+ allow_empty = False,
+ )),
+ ]
+ ),
+ ),
+ ],
+ default_value = "ignore",
+ ),
+ # In the past, this was a OptionalDropdownChoice() which values could be
strings:
+ # ignore, site or a custom string representing a version number.
+ forth = lambda x: type(x) == str and x not in [ "ignore",
"site" ] and ("specific", x) or x
)
)