Module: check_mk
Branch: master
Commit: bb99da0d078225677896587db4785e4dd22e09af
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=bb99da0d078225…
Author: Mathias Kettner <mk(a)mathias-kettner.de>
Date: Mon Jan 5 15:15:04 2015 +0100
#1831 diskstat: detect multipath devices and handle them instead of the physical paths
The Linux <i>Disk IO</i> check now uses the information about the
Multipathing
if available and the drops single checks for the various
<tt>sd</tt><i>XY</i>
devices of the paths and instead adds checks for the resulting multipath
devices.
That drastically reduces the number of services and displays more useful
information at the same time.
---
.werks/1831 | 15 +++++++++++++++
ChangeLog | 1 +
checks/diskstat | 48 ++++++++++++++++++++++++++++++++++--------------
checks/multipath | 23 +++++++++++++++--------
4 files changed, 65 insertions(+), 22 deletions(-)
diff --git a/.werks/1831 b/.werks/1831
new file mode 100644
index 0000000..1d43113
--- /dev/null
+++ b/.werks/1831
@@ -0,0 +1,15 @@
+Title: diskstat: detect multipath devices and handle them instead of the physical paths
+Level: 2
+Component: checks
+Compatible: compat
+Version: 1.2.7i1
+Date: 1420467168
+Class: feature
+
+The Linux <i>Disk IO</i> check now uses the information about the
Multipathing
+if available and the drops single checks for the various
<tt>sd</tt><i>XY</i>
+devices of the paths and instead adds checks for the resulting multipath
+devices.
+
+That drastically reduces the number of services and displays more useful
+information at the same time.
diff --git a/ChangeLog b/ChangeLog
index 29b760d..1f1eefb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -22,6 +22,7 @@
* 1460 df_netscaler: new check to monitor filesystem usage on Citrix Netscaler
devices
* 1820 mem.linux: new dedicated check for Linux memory management...
NOTE: Please refer to the migration notes!
+ * 1831 diskstat: detect multipath devices and handle them instead of the physical
paths...
* 1457 FIX: logins: new check renamed from "users" check...
NOTE: Please refer to the migration notes!
* 1762 FIX: lnx_thermal: Now ignoring trip points with level 0...
diff --git a/checks/diskstat b/checks/diskstat
index 10a0caa..1758f74 100644
--- a/checks/diskstat
+++ b/checks/diskstat
@@ -113,27 +113,43 @@ def diskstat_parse_info(info):
return info_plain, nameinfo
-def diskstat_rewrite_device(nameinfo, linestart):
+def diskstat_rewrite_device(nameinfo, multipath_nameinfo, linestart):
node = linestart[0]
major, minor = map(int, linestart[1:3])
device = linestart[3]
- return nameinfo.get((node, major, minor), device)
+ if device in multipath_nameinfo:
+ return multipath_nameinfo[device]
+ else:
+ return nameinfo.get((node, major, minor), device)
def linux_diskstat_convert(info):
- info, nameinfo = diskstat_parse_info(info)
+ diskstat_info, multipath_info = info
+ info, nameinfo = diskstat_parse_info(diskstat_info)
+
+ # For multipath devices use the entries for dm-?? and rename
+ # them with their multipath UUID/alias - and drop the according
+ # sdXY that belong to the paths.
+ multipath_nameinfo = {}
+ skipped_devices = set([])
+ if multipath_info:
+ for uuid, multipath in multipath_info.items():
+ skipped_devices.update(multipath["paths"])
+ multipath_nameinfo[multipath["device"]] = uuid # map dm-8 to its
alias
+
# The generic function takes the following values per line:
- # 0: devname
- # 1: read bytes counter
- # 2: write bytes counter
+ # 0: None or node name
+ # 1: devname
+ # 2: read bytes counter
+ # 3: write bytes counter
# Optional ones:
- # 3: number of reads
- # 4: number of writes
- # 5: timems
- # 6: read queue length *counters*
- # 7: write queue length *counters*
+ # 4: number of reads
+ # 5: number of writes
+ # 6: timems
+ # 7: read queue length *counters*
+ # 8: write queue length *counters*
rewritten = [
( l[0], # node name or None
- diskstat_rewrite_device(nameinfo, l[0:4]),
+ diskstat_rewrite_device(nameinfo, multipath_nameinfo, l[0:4]),
int(l[6]),
int(l[10]),
int(l[4]),
@@ -143,13 +159,16 @@ def linux_diskstat_convert(info):
]
# Remove device mapper devices without a translated name
- return [ line for line in rewritten if not line[1].startswith("dm-") ]
+ return [ line for line in rewritten
+ if not line[1].startswith("dm-")
+ and not line[1] in skipped_devices ]
def inventory_diskstat(info):
return inventory_diskstat_generic(linux_diskstat_convert(info))
def check_diskstat(item, params, info):
- this_time = int(info[0][1])
+ diskstat_info, multipath_info = info
+ this_time = int(diskstat_info[0][1])
return check_diskstat_generic(item, params, this_time, linux_diskstat_convert(info))
@@ -162,5 +181,6 @@ check_info["diskstat"] = {
'group' : 'disk_io',
"node_info" : True, # add first column with actual host name
'includes' : [ "diskstat.include" ],
+ 'extra_sections' : [ "multipath" ],
}
diff --git a/checks/multipath b/checks/multipath
index 7aab5f9..6025113 100644
--- a/checks/multipath
+++ b/checks/multipath
@@ -158,13 +158,14 @@ def parse_multipath(info):
# 0: matching regex
# 1: matched regex-group id of UUID
# 2: matched regex-group id of alias (optional)
+ # 3: matched regex-group id of dm-device (optional)
reg_headers = [
- (get_regex(r"^[0-9a-z]{33}$"), 0, None), # 1.
(should be included in 3.)
- (get_regex(r"^([^\s]+)\s\(([0-9A-Za-z_-]+)\)"), 2, 1), # 2.
- (get_regex(r"^[a-zA-Z0-9_]+$"), 0, None), # 3.
- (get_regex(r"^([0-9a-z]{33}|[0-9a-z]{49})\s?dm.+$"), 1, None), # 4.
- (get_regex(r"^[a-zA-Z0-9_]+dm-.+$"), 0, None), # 5.
Remove this line in 1.2.0
- (get_regex(r"^([-a-zA-Z0-9_ ]+)\s?dm-[0-9]+.*$"), 1, None), # 6. and
7.
+ (get_regex(r"^[0-9a-z]{33}$"), 0, None,
None), # 1. (should be included in 3.)
+ (get_regex(r"^([^\s]+)\s\(([0-9A-Za-z_-]+)\)"), 2, 1,
None), # 2.
+ (get_regex(r"^[a-zA-Z0-9_]+$"), 0, None,
None), # 3.
+ (get_regex(r"^([0-9a-z]{33}|[0-9a-z]{49})\s?(dm.[0-9]+).*$"), 1, None,
2), # 4.
+ (get_regex(r"^[a-zA-Z0-9_]+(dm-[0-9]+).*$"), 0, None,
1), # 5. Remove this line in 1.2.0
+ (get_regex(r"^([-a-zA-Z0-9_ ]+)\s?(dm-[0-9]+).*$"), 1, None,
2), # 6. and 7.
]
reg_prio = get_regex("[[ ]prio=")
@@ -201,17 +202,22 @@ def parse_multipath(info):
if line[0][0] not in [ '[', '`', '|', '\\' ] and
not line[0].startswith("size="):
# Try to match header lines
matchobject = None
- for regex, uuid_pos, alias_pos in reg_headers:
+ for regex, uuid_pos, alias_pos, dm_pos in reg_headers:
matchobject = regex.search(l)
if matchobject:
- uuid = matchobject.group(uuid_pos)
+ uuid = matchobject.group(uuid_pos).strip()
if alias_pos:
alias = matchobject.group(alias_pos)
else:
alias = None
+ if dm_pos:
+ dm_device = matchobject.group(dm_pos)
+ else:
+ dm_device = None
+
break
# No data row and no matching header row
@@ -230,6 +236,7 @@ def parse_multipath(info):
group['uuid'] = uuid
group['state'] = None
group['numpaths'] = 0
+ group['device'] = dm_device
groups[uuid] = group
# If the device has an alias, then extract it