summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config/nrpe.in2
-rw-r--r--gluster-nagios-addons.spec.in4
-rw-r--r--plugins/Makefile.am2
-rwxr-xr-xplugins/check_disk_and_inode.py443
-rwxr-xr-xplugins/check_mounts.py265
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/mounts.txt21
-rw-r--r--tests/test_disk.py187
-rw-r--r--tests/test_mounts.py380
9 files changed, 672 insertions, 634 deletions
diff --git a/config/nrpe.in b/config/nrpe.in
index 8b4f6e9..f2cf3b0 100644
--- a/config/nrpe.in
+++ b/config/nrpe.in
@@ -1,5 +1,5 @@
Cmnd_Alias NRPE_PATHS = @sbindir@/send_nsca, \
- @libdir@/nagios/plugins/gluster/check_disk_and_inode.py, \
+ @libdir@/nagios/plugins/gluster/check_mounts.py, \
@libdir@/nagios/plugins/gluster/check_vol_utilization.py, \
@libdir@/nagios/plugins/gluster/check_volume_status.py, \
@libdir@/nagios/plugins/gluster/check_gluster_proc_status.py, \
diff --git a/gluster-nagios-addons.spec.in b/gluster-nagios-addons.spec.in
index f3b9f07..dc35720 100644
--- a/gluster-nagios-addons.spec.in
+++ b/gluster-nagios-addons.spec.in
@@ -132,12 +132,12 @@ fi
cat >> %{_sysconfdir}/nagios/nrpe.cfg <<EOF
%{_start_conf_section}
-command[check_disk_and_inode]=sudo %{_libdir}/nagios/plugins/gluster/check_disk_and_inode.py -w 80 -c 90 -l -i /boot -i /var -i /root -n --inode -s
+command[check_disk_and_inode]=sudo %{_libdir}/nagios/plugins/gluster/check_mounts.py -w 80 -c 90
command[check_memory]=%{_libdir}/nagios/plugins/gluster/memory.py -w 80 -c 90 -t 2
command[check_swap_usage]=%{_libdir}/nagios/plugins/gluster/swap.py -w 80 -c 90 -t 2
command[check_cpu_multicore]=%{_libdir}/nagios/plugins/gluster/cpu.py -w 80 -c 90 -t 2
command[check_interfaces]=%{_libdir}/nagios/plugins/gluster/network.py -e lo -e ';vdsmdummy;' -t 2
-command[check_brick_usage]=sudo %{_libdir}/nagios/plugins/gluster/check_disk_and_inode.py -w 80 -c 90 -n -t -i \$ARG1\$
+command[check_brick_usage]=sudo %{_libdir}/nagios/plugins/gluster/check_mounts.py -w 80 -c 90 -i \$ARG1\$
command[check_vol_utilization]=sudo %{_libdir}/nagios/plugins/gluster/check_vol_utilization.py \$ARG1\$ -w \$ARG2\$ -c \$ARG3\$
command[check_vol_status]=sudo %{_libdir}/nagios/plugins/gluster/check_volume_status.py -v \$ARG1\$ -t \$ARG2\$
command[check_proc_status]=sudo %{_libdir}/nagios/plugins/gluster/check_gluster_proc_status.py -t \$ARG1\$
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 47ff64d..ffc121f 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -9,8 +9,8 @@ crond_DATA = \
$(NULL)
dist_glusternagiosplugins_PYTHON = \
- check_disk_and_inode.py \
check_gluster_syslog.py \
+ check_mounts.py \
check_vol_utilization.py \
check_volume_status.py \
check_proc_status.py \
diff --git a/plugins/check_disk_and_inode.py b/plugins/check_disk_and_inode.py
deleted file mode 100755
index d1fc3f5..0000000
--- a/plugins/check_disk_and_inode.py
+++ /dev/null
@@ -1,443 +0,0 @@
-#!/usr/bin/python
-# Copyright (C) 2014 Red Hat Inc
-#
-# This program 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; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-#
-
-
-import os
-import re
-import sys
-import commands
-from optparse import OptionParser
-from glusternagios import utils
-
-WARNING_LEVEL = 80
-CRITICAL_LEVEL = 90
-INVALID_STATUS_CODE = -1
-
-
-def getVal(val):
- dmatch = re.compile('[0-9]+').match(val)
- if (dmatch):
- return float(eval(dmatch.group(0)))
- else:
- return 0
-
-
-def getLVdetails(filename, lvs):
- dev_name = os.path.realpath(filename)
-
- pool = ""
- disk = {}
- for a in lvs:
- dev = os.path.realpath(a['LVM2_LV_PATH'])
- if dev_name == dev:
- if a['LVM2_LV_ATTR'][0] == 'V':
- pool = a['LVM2_POOL_LV']
- disk['thinLv'] = True
- break
- else:
- disk['thinLv'] = False
- return disk
- else:
- return None
- for b in lvs:
- if b['LVM2_LV_NAME'] == pool:
- disk['actualUsedPercent'] = float(b['LVM2_DATA_PERCENT'])
- disk['actualTotalSize'] = float(b['LVM2_LV_SIZE'])
- disk['actualUsed'] = disk['actualTotalSize'] * disk[
- 'actualUsedPercent'] / 100
- return disk
- else:
- return None
-
-
-def getUsageAndFree(command, path, crit, warn, lvm):
- disk = {'path': None, 'usePcent': 0, 'avail': 0,
- 'used': 0, 'size': 0, 'fs': None,
- 'status': None, 'msg': None, 'availPcent': 0,
- 'statusCode': utils.PluginStatusCode.UNKNOWN}
-
- # Check if device exists and permissions are ok
- if not os.access(path, os.F_OK):
- disk['status'] = "Device not found!"
- disk['msg'] = 'no device'
- disk['fs'] = path
- disk['statusCode'] = utils.PluginStatusCode.CRITICAL
- return disk
-
- if not os.access(path, os.R_OK):
- disk['status'] = "Unable to access the device"
- disk['msg'] = 'no access'
- disk['fs'] = path
- disk['statusCode'] = utils.PluginStatusCode.CRITICAL
- return disk
-
- status = commands.getstatusoutput(command)
- # Sample output
- # (0, 'Filesystem 1G-blocks Used Available Use% Mounted on\n/dev/sda1
- # 290G 196G 79G 72% /')
- if status[0] != 0:
- disk['msg'] = 'error:%s' % status[0]
- if status[0] == 256:
- disk['status'] = "Brick/Device path not found!"
- else:
- disk['status'] = status[1]
- disk['statusCode'] = utils.PluginStatusCode.CRITICAL
- return disk
-
- status = status[1].split()
- disk['path'] = status[-1]
- disk['avail'] = getVal(status[-3])
- disk['used'] = getVal(status[-4])
- disk['size'] = getVal(status[-5])
- disk['fs'] = status[-6]
- disk['usePcent'] = getVal(status[-2])
-
- if disk['usePcent'] >= crit:
- disk['statusCode'] = utils.PluginStatusCode.CRITICAL
- elif disk['usePcent'] >= warn:
- disk['statusCode'] = utils.PluginStatusCode.WARNING
- elif disk['usePcent'] < warn:
- disk['statusCode'] = utils.PluginStatusCode.OK
- disk['availPcent'] = 100 - disk['usePcent']
- return disk
-
-
-def getDisk(path, crit, warn, usage=None, lvm=False):
- if usage:
- return getUsageAndFree("df -B%s %s" % (usage, path),
- path, crit, warn, lvm)
- else:
- return getUsageAndFree("df -BG %s" % path,
- path, crit, warn, lvm)
-
-
-def getInode(path, crit, warn, lvm=False):
- return getUsageAndFree("df -i %s" % path,
- path, crit, warn, lvm)
-
-
-def getMounts(searchQuery, excludeList=[]):
- mountPaths = []
- f = open("/etc/mtab")
- for i in f.readlines():
- if i.startswith(searchQuery):
- if not excludeList:
- mountPaths.append(i.split()[0])
- else:
- device = i.split()
- if not device[0] in options.exclude and\
- not device[1] in options.exclude:
- mountPaths.append(device[0])
- f.close()
- return mountPaths
-
-
-def parse_input():
- parser = OptionParser()
- parser.add_option('-w', '--warning', action='store', type='int',
- dest='warn',
- help='Warning count in %', default=WARNING_LEVEL)
- parser.add_option('-c', '--critical', action='store', type='int',
- dest='crit',
- help='Critical count in %', default=CRITICAL_LEVEL)
- parser.add_option('-u', '--usage', action="store", dest='usage',
- help='Usage in %/GB/MB/KB', default=None)
- parser.add_option('-l', '--lvm', action="store_true",
- dest='lvm',
- help='List lvm mounts', default=False)
- parser.add_option('-d', '--inode', action="store_true", dest='inode',
- help='List inode usage along with disk/brick usage',
- default=False)
- parser.add_option('-a', '--all', action="store_true",
- dest='all',
- help='List all mounts', default=False)
- parser.add_option('-n', '--ignore', action="store_true",
- dest='ignore',
- help='Ignore errors', default=False)
- parser.add_option('-i', '--include', action='append', type='string',
- dest='mountPath',
- help='Mount path', default=[])
- parser.add_option('-x', '--exclude', action="append", type='string',
- dest='exclude',
- help='Exclude disk/brick')
- parser.add_option('-s', action="store_true", default=False,
- dest='showErrorDisk',
- help='Show critical or warning disks in the status')
- parser.add_option('-t', '--thinPool', action="store_true",
- dest='thinPool',
- help='Lists detail of underlying thin pool',
- default=False)
- return parser.parse_args()
-
-
-def _getMsg(okList, warnList, critList):
- msg = ", ".join(critList)
- errorDiskMsg = msg
- if critList and (warnList or okList):
- msg = "CRITICAL: " + msg
- if warnList:
- if msg:
- msg += "; WARNING: "
- msg += ", ".join(warnList)
- if errorDiskMsg:
- errorDiskMsg += "; WARNING: " + ", ".join(warnList)
- else:
- errorDiskMsg = msg
- if okList:
- if msg:
- msg += "; OK: "
- msg += ", ".join(okList)
- return msg, errorDiskMsg
-
-
-def _getUnitAndType(val):
- unit = utils.convertSize(val, "GB", "TB")
- if unit >= 1:
- return unit, "TB"
- else:
- return val, "GB"
-
-
-def showDiskUsage(warn, crit, mountPaths, toListInode, usage=False,
- isLvm=False, ignoreError=False, showErrorDisk=True,
- thinPool=False):
- diskPerf = []
- warnList = []
- critList = []
- okList = []
- mounts = []
- statusCode = INVALID_STATUS_CODE
- totalUsed = 0
- totalSize = 0
- noOfMounts = len(mountPaths)
- maxPercentUsed = 0
-
- if thinPool:
- rc, out, err = utils.execCmd(["lvm"] +
- ("vgs --unquoted --noheading " +
- "--nameprefixes --separator : " +
- "--nosuffix --units g -o " +
- "lv_path,data_percent,pool_lv,lv_attr,"
- "lv_size,lv_name").split())
- if rc == 0:
- res = []
- for i in out:
- tem = i.split(":")
- dct = {}
- for j in tem:
- tp = j.split("=")
- dct[tp[0].replace(" ", "")] = tp[1]
- res.append(dct)
- else:
- thinPool = False
-
- for path in mountPaths:
- disk = getDisk(path, crit, warn, usage, isLvm)
- inode = getInode(path, crit, warn, isLvm)
- if thinPool:
- thinLv = getLVdetails(disk['fs'], res)
- if thinLv and thinLv['thinLv']:
- if disk['usePcent'] >= crit or thinLv[
- 'actualUsedPercent'] >= crit:
- disk['statusCode'] = utils.PluginStatusCode.CRITICAL
- elif disk['usePcent'] >= warn or thinLv[
- 'actualUsedPercent'] >= warn:
- disk['statusCode'] = utils.PluginStatusCode.WARNING
- elif disk['usePcent'] < warn or thinLv[
- 'actualUsedPercent'] < warn:
- disk['statusCode'] = utils.PluginStatusCode.OK
- else:
- thinPool = False
-
- if disk['path'] in mounts:
- continue
- if not disk['used'] or not inode['used']:
- if not ignoreError:
- sys.exit(utils.PluginStatusCode.UNKNOWN)
-
- if disk['path']:
- mounts.append(disk['path'])
- data = ""
- if usage and disk['path']:
- data = "%s=%.1f%s;%.1f;%.1f;0;%.1f" % (
- disk['path'],
- disk['used'],
- usage,
- warn * disk['size'] / 100,
- crit * disk['size'] / 100,
- disk['size'])
- if toListInode:
- data += " %s=%.1f;%.1f;%.1f;0;%.1f" % (
- inode['path'],
- inode['used'],
- warn * inode['used'] / 100,
- crit * inode['used'] / 100,
- inode['size'])
- elif disk['path']:
- if thinPool and thinLv['thinLv']:
- data = "%s=%.2f%%;%s;%s;0;%s" % (
- disk['path'],
- disk['usePcent'],
- warn,
- crit,
- disk['size'])
- data += " Thin-pool=%.2f%%;%s;%s;0;%.1f" % (
- thinLv['actualUsedPercent'],
- warn,
- crit,
- thinLv['actualTotalSize'])
- else:
- data = "%s=%.2f%%;%s;%s;0;%s" % (
- disk['path'],
- disk['usePcent'],
- warn,
- crit,
- disk['size'])
- if toListInode:
- data += " %s=%.2f%%;%s;%s;0;%s" % (
- inode['path'],
- inode['usePcent'],
- warn,
- crit,
- inode['size'])
- diskPerf.append(data)
-
- totalUsed += disk['used']
- totalSize += disk['size']
- if disk['usePcent'] > maxPercentUsed:
- maxPercentUsed = disk['usePcent']
-
- # adding into status message if there is any
- # specfic status found (short msg for list of disks)
- msg = ""
- if disk['status'] and disk['msg']:
- if noOfMounts == 1:
- msg = "%s=%s(%s)" % (disk['fs'], disk['path'],
- disk['status'])
- else:
- msg = "%s(%s)" % (disk['fs'], disk['msg'])
- else:
- if noOfMounts == 1:
- msg = "%s=%s" % (disk['fs'], disk['path'])
- else:
- msg = "%s" % (disk['path'])
-
- if disk['statusCode'] == utils.PluginStatusCode.CRITICAL or \
- inode['statusCode'] == utils.PluginStatusCode.CRITICAL:
- statusCode = utils.PluginStatusCode.CRITICAL
- critList.append(msg)
- elif (disk['statusCode'] == utils.PluginStatusCode.WARNING or
- inode['statusCode'] == utils.PluginStatusCode.WARNING):
- # if any previous disk statusCode is not critical
- # we should not change the statusCode into warning
- if statusCode != utils.PluginStatusCode.CRITICAL:
- statusCode = utils.PluginStatusCode.WARNING
- # just adding warning values into the list
- warnList.append(msg)
- elif disk['statusCode'] == utils.PluginStatusCode.OK:
- if statusCode == INVALID_STATUS_CODE or \
- statusCode == utils.PluginStatusCode.OK:
- statusCode = utils.PluginStatusCode.OK
- okList.append(msg)
- else:
- # added \ to fix E125 pep8 error
- if statusCode != utils.PluginStatusCode.CRITICAL or \
- statusCode != utils.PluginStatusCode.WARNING:
- statusCode = utils.PluginStatusCode.UNKNOWN
- okList.append(msg)
-
- msg, errorDiskMsg = _getMsg(okList, warnList, critList)
-
- if totalUsed == 0 and totalSize == 0:
- # avoid zero div error
- return statusCode, "mount: %s" % msg, diskPerf
- if totalUsed == 0:
- # avoid zero div error
- totUsagePercent = 0
- elif len(mounts) > 1:
- totUsagePercent = totalUsed / totalSize * 100
- else:
- totUsagePercent = maxPercentUsed
- usageMsg = ""
- if not usage:
- totUsedSz, totUsedSzUnit = _getUnitAndType(totalUsed)
- totSpaceSz, totSpaceSzUnit = _getUnitAndType(totalSize)
- usageMsg = "%.1f%% used (%s%s out of %s%s)" % (totUsagePercent,
- totUsedSz,
- totUsedSzUnit,
- totSpaceSz,
- totSpaceSzUnit)
- if thinPool and thinLv['thinLv']:
- usageMsg += " [Thin-pool: %.1f%% (%.1fG out of %.1fG)]" % (
- thinLv['actualUsedPercent'],
- thinLv['actualUsed'],
- thinLv['actualTotalSize'])
- else:
- usageMsg = "%.1f%% used (%s%s out of %s%s)" % (totUsagePercent,
- totalUsed,
- usage,
- totalSize,
- usage)
- if showErrorDisk:
- msg = "%s\n:mount(s): (%s)" % (errorDiskMsg, msg)
- else:
- msg = "%s\n:mount(s): (%s)" % (usageMsg, msg)
-
- return statusCode, msg, diskPerf
-
-
-if __name__ == '__main__':
- (options, args) = parse_input()
-
- if options.lvm:
- searchQuery = "/dev/mapper"
- else:
- searchQuery = "/"
-
- if not options.mountPath or options.lvm or options.all:
- options.mountPath += getMounts(searchQuery, options.exclude)
-
- statusCode, msg, diskPerf = showDiskUsage(options.warn,
- options.crit,
- options.mountPath,
- options.inode,
- options.usage,
- options.lvm,
- options.ignore,
- options.showErrorDisk,
- options.thinPool)
-
- if utils.PluginStatusCode.CRITICAL == statusCode:
- sys.stdout.write("%s : %s | %s\n" % (
- utils.PluginStatus.CRITICAL,
- msg,
- " ".join(diskPerf)))
- sys.exit(utils.PluginStatusCode.CRITICAL)
- elif utils.PluginStatusCode.WARNING == statusCode:
- sys.stdout.write("%s : %s | %s\n" % (
- utils.PluginStatus.WARNING,
- msg,
- " ".join(diskPerf)))
- sys.exit(utils.PluginStatusCode.WARNING)
- else:
- if options.showErrorDisk:
- sys.stdout.write("%s %s | %s\n" % (
- utils.PluginStatus.OK, msg, " ".join(diskPerf)))
- else:
- sys.stdout.write("%s : %s | %s\n" % (
- utils.PluginStatus.OK, msg, " ".join(diskPerf)))
diff --git a/plugins/check_mounts.py b/plugins/check_mounts.py
new file mode 100755
index 0000000..342c20a
--- /dev/null
+++ b/plugins/check_mounts.py
@@ -0,0 +1,265 @@
+#!/usr/bin/python
+# Copyright (C) 2015 Red Hat Inc
+#
+# This program 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; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+#
+
+
+import os
+import sys
+import argparse
+import logging
+
+from glusternagios import utils
+from glusternagios.utils import PluginStatusCode, PluginStatus
+
+ONE_GB_BYTES = 1073741824.0
+
+
+def _getMountPoint(path):
+ mount = os.path.realpath(path)
+ while not os.path.ismount(mount):
+ mount = os.path.dirname(mount)
+ return mount
+
+
+def _parseProcMounts(filter=True):
+ mountPoints = {}
+ with open('/proc/mounts', 'r') as f:
+ for line in f:
+ if line.startswith("/") or not filter:
+ mount = {}
+ tokens = line.split()
+ mount['device'] = tokens[0]
+ mount['fsType'] = tokens[2]
+ mount['mountOptions'] = tokens[3]
+ mountPoints[tokens[1]] = mount
+ return mountPoints
+
+
+def _getStats(mountPoint):
+ data = os.statvfs(mountPoint)
+ total = (data.f_blocks * data.f_bsize) / ONE_GB_BYTES
+ free = (data.f_bfree * data.f_bsize) / ONE_GB_BYTES
+ used_percent = 100 - (100.0 * free / total)
+ total_inode = data.f_files
+ free_inode = data.f_ffree
+ used_percent_inode = 100 - (100.0 * free_inode / total_inode)
+ used = total - free
+ used_inode = total_inode - free_inode
+ return {'total': total,
+ 'free': free,
+ 'used_percent': used_percent,
+ 'total_inode': total_inode,
+ 'free_inode': free_inode,
+ 'used_inode': used_inode,
+ 'used': used,
+ 'used_percent_inode': used_percent_inode}
+
+
+def _getOutputText(detail):
+ template = "{mount_point} - {{space - free: {free:0.3f} GiB, " \
+ "used: {used_percent:0.3f}%}}, {{inode - free: {free_inode}" \
+ " , used: {used_percent_inode:0.3f}%}}"
+
+ if detail['thinpool_size']:
+ template += ", {{thinpool-data - free: {thinpool_free:.3f} GiB," \
+ " used: {thinpool_used_percent:.3f}%}}, " \
+ "{{thinpool-metadata - free: {metadata_free:.3f} GiB," \
+ " used: {metadata_used_percent:.3f}%}}"
+ return template.format(**detail)
+
+
+def _getPerfdata(detail, warn, crit):
+ template = "{mount_point}={used_percent:.3f}%;{warn};{crit};0;{total:.3f}"\
+ " {mount_point}.inode={used_percent_inode:.3f}%;{warn};{crit}" \
+ ";0;{total_inode}"
+ if detail['thinpool_size']:
+ template += " {mount_point}.thinpool={thinpool_used_percent:.3f}%;" \
+ "{warn};{crit};0;{thinpool_size:.3f} {mount_point}." \
+ "thinpool-metadata={metadata_used_percent:.3f}%;{warn};{crit};0;" \
+ "{metadata_size:.3f}"
+ return template.format(warn=warn, crit=crit, **detail)
+
+
+def _getStatusInfo(detail, warn, crit):
+ rc = PluginStatus.OK
+ msg = []
+
+ parameter = {'metadata_used_percent': ['thinpool-metadata',
+ 'metadata_used',
+ 'metadata_size', ' GiB'],
+ 'thinpool_used_percent': ['thinpool-data', 'thinpool_used',
+ 'thinpool_size', ' GiB'],
+ 'used_percent': ['space', 'used',
+ 'total', ' GiB'],
+ 'used_percent_inode': ['inode', 'used_inode',
+ 'total_inode', '']}
+
+ for k, v in parameter.iteritems():
+ if not detail[k]:
+ continue
+ if k == 'used_percent_inode':
+ m = "%s used %d / %d%s" % (v[0], detail[v[1]],
+ detail[v[2]], v[3])
+ else:
+ m = "%s used %0.3f / %0.3f%s" % (v[0], detail[v[1]],
+ detail[v[2]], v[3])
+ if detail[k] >= crit:
+ rc = PluginStatus.CRITICAL
+ msg.append(m)
+ elif detail[k] >= warn:
+ if rc != PluginStatus.CRITICAL:
+ rc = PluginStatus.WARNING
+ msg.append(m)
+
+ if rc == PluginStatus.OK:
+ out = ''
+ else:
+ out = "mount point {mount_point} {{{msg}}}".format(msg=", ".join(msg),
+ **detail)
+ return rc, out
+
+
+def parse_input():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("-w", "--warning", action="store",
+ required=True, type=int,
+ help="Warning threshold in percentage")
+ parser.add_argument("-c", "--critical", action="store",
+ required=True, type=int,
+ help="Critical threshold in percentage")
+ group = parser.add_mutually_exclusive_group()
+ group.add_argument("-e", "--exclude", action="append", default=[],
+ help="exclude given interface")
+ group.add_argument("-i", "--include", action="append", default=[],
+ help="add given interface for monitoring")
+ args = parser.parse_args()
+ return args
+
+
+def getLvs():
+ lvmCommand = ["lvm", "vgs", "--unquoted", "--noheading",
+ "--nameprefixes", "--separator", "$",
+ "--nosuffix", "--units", "m", "-o",
+ "lv_uuid,lv_name,data_percent,pool_lv,lv_attr,"
+ "lv_size,lv_path,lv_metadata_size,"
+ "metadata_percent,vg_name"]
+ rc, out, err = utils.execCmd(lvmCommand)
+ if rc != 0:
+ logging.error(
+ "lvm command failed.\nCommand=%s\nrc=%s\nout=%s\nerr=%s"
+ % (lvmCommand, rc, out, err)
+ )
+ return None
+ l = map(lambda x: dict(x),
+ map(lambda x: [e.split('=') for e in x],
+ map(lambda x: x.strip().split('$'), out)))
+
+ d = {}
+ for i in l:
+ if i['LVM2_LV_ATTR'][0] == 't':
+ k = "%s/%s" % (i['LVM2_VG_NAME'], i['LVM2_LV_NAME'])
+ else:
+ k = os.path.realpath(i['LVM2_LV_PATH'])
+ d.update({k: i})
+ return d
+
+
+def getMountStats(exclude, include):
+ def _getMounts(exclude=[], include=[]):
+ excludeList = map(_getMountPoint, exclude)
+ includeList = map(_getMountPoint, include)
+ mountPoints = _parseProcMounts()
+ if excludeList:
+ outList = set(mountPoints) - set(excludeList)
+ elif includeList:
+ outList = set(mountPoints).intersection(set(includeList))
+ else:
+ return mountPoints
+ # list comprehension to build dictionary does not work in python 2.6.6
+ mounts = {}
+ for k in outList:
+ mounts[k] = mountPoints[k]
+ return mounts
+
+ def _getThinPoolStat(device):
+ out = {'thinpool_size': None,
+ 'thinpool_used_percent': None,
+ 'metadata_size': None,
+ 'metadata_used_percent': None,
+ 'thinpool_free': None,
+ 'metadata_free': None,
+ 'thinpool_used': None,
+ 'metadata_used': None}
+
+ if lvs and device in lvs and \
+ lvs[device]['LVM2_LV_ATTR'][0] == 'V':
+ thinpool = "%s/%s" % (lvs[device]['LVM2_VG_NAME'],
+ lvs[device]['LVM2_POOL_LV'])
+ out['thinpool_size'] = float(
+ lvs[thinpool]['LVM2_LV_SIZE']) / 1024
+ out['thinpool_used_percent'] = float(
+ lvs[thinpool]['LVM2_DATA_PERCENT'])
+ out['metadata_size'] = float(
+ lvs[thinpool]['LVM2_LV_METADATA_SIZE']) / 1024
+ out['metadata_used_percent'] = float(
+ lvs[thinpool]['LVM2_METADATA_PERCENT'])
+ out['thinpool_free'] = out['thinpool_size'] * (
+ 1 - out['thinpool_used_percent']/100.0)
+ out['thinpool_used'] = out['thinpool_size'] - out['thinpool_free']
+ out['metadata_free'] = out['metadata_size'] * (
+ 1 - out['metadata_used_percent']/100.0)
+ out['metadata_used'] = out['metadata_size'] - out['metadata_free']
+ return out
+
+ mountPoints = _getMounts(exclude, include)
+ lvs = getLvs()
+ mountDetail = {}
+ for mount, info in mountPoints.iteritems():
+ mountDetail[mount] = _getStats(mount)
+ mountDetail[mount].update(
+ _getThinPoolStat(os.path.realpath(info['device']))
+ )
+ mountDetail[mount].update({'mount_point': mount})
+ return mountDetail
+
+
+def getPrintableStatus(mountDetail, warning, critical):
+ finalRc = utils.PluginStatus.OK
+ finalMsg = []
+ finalOut = []
+ finalPerfdata = []
+ for mount, detail in mountDetail.iteritems():
+ finalOut.append(_getOutputText(detail))
+ finalPerfdata.append(_getPerfdata(detail, warning, critical))
+ rc, msg = _getStatusInfo(detail, warning, critical)
+ if msg:
+ finalMsg.append(msg)
+ if getattr(PluginStatusCode, rc) > getattr(PluginStatusCode, finalRc):
+ finalRc = rc
+ return finalRc, finalMsg, finalOut, finalPerfdata
+
+
+if __name__ == '__main__':
+ args = parse_input()
+ mountDetail = getMountStats(args.exclude, args.include)
+ rc, msg, msgDet, perfdata = getPrintableStatus(mountDetail,
+ args.warning,
+ args.critical)
+
+ print "%s: %s" % (rc, ", ".join(msg))
+ print "%s | %s" % ("\n".join(msgDet), "\n".join(perfdata))
+ sys.exit(getattr(PluginStatusCode, rc))
diff --git a/tests/Makefile.am b/tests/Makefile.am
index cdf62d4..1994d43 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -24,6 +24,7 @@ test_modules = \
check_proc_test_data.py \
test_cpu.py \
test_cpu_dataFile.py \
+ test_mounts.py \
test_gluster_proc.py \
test_memory.py \
test_memory_dataFile.py \
@@ -37,6 +38,7 @@ test_modules = \
dist_glusternagiosaddonstests_DATA = \
getLatestStat_exception.xml \
getLatestStat_success.xml \
+ mounts.txt \
$(NULL)
dist_glusternagiosaddonstests_PYTHON = \
diff --git a/tests/mounts.txt b/tests/mounts.txt
new file mode 100644
index 0000000..41c43c8
--- /dev/null
+++ b/tests/mounts.txt
@@ -0,0 +1,21 @@
+rootfs / rootfs rw 0 0
+proc /proc proc rw,relatime 0 0
+sysfs /sys sysfs rw,relatime 0 0
+devtmpfs /dev devtmpfs rw,relatime,size=1016068k,nr_inodes=254017,mode=755 0 0
+devpts /dev/pts devpts rw,relatime,gid=5,mode=620,ptmxmode=000 0 0
+tmpfs /dev/shm tmpfs rw,relatime 0 0
+/dev/mapper/vg_dhcp42149-lv_root / ext4 rw,relatime,barrier=1,data=ordered 0 0
+/proc/bus/usb /proc/bus/usb usbfs rw,relatime 0 0
+/dev/vda1 /boot ext4 rw,relatime,barrier=1,data=ordered 0 0
+/dev/mapper/vg_dhcp42149-lv_home /home ext4 rw,relatime,barrier=1,data=ordered 0 0
+none /proc/sys/fs/binfmt_misc binfmt_misc rw,relatime 0 0
+cgroup /cgroup/cpuset cgroup rw,relatime,cpuset 0 0
+cgroup /cgroup/cpu cgroup rw,relatime,cpu 0 0
+cgroup /cgroup/cpuacct cgroup rw,relatime,cpuacct 0 0
+cgroup /cgroup/memory cgroup rw,relatime,memory 0 0
+cgroup /cgroup/devices cgroup rw,relatime,devices 0 0
+cgroup /cgroup/freezer cgroup rw,relatime,freezer 0 0
+cgroup /cgroup/net_cls cgroup rw,relatime,net_cls 0 0
+cgroup /cgroup/blkio cgroup rw,relatime,blkio 0 0
+/dev/mapper/mygroup-thinv1 /bricks/brick1 xfs rw,relatime,attr2,delaylog,logbsize=64k,sunit=128,swidth=128,noquota 0 0
+/dev/mapper/mygroup-thinv2 /bricks/brick2 xfs rw,relatime,attr2,delaylog,logbsize=64k,sunit=128,swidth=128,noquota 0 0
diff --git a/tests/test_disk.py b/tests/test_disk.py
deleted file mode 100644
index b41d3bf..0000000
--- a/tests/test_disk.py
+++ /dev/null
@@ -1,187 +0,0 @@
-#
-# Copyright 2014 Red Hat, Inc.
-#
-# This program 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; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#
-# Refer to the README and COPYING files for full details of the license
-#
-
-import os
-import commands
-from testrunner import PluginsTestCase as TestCaseBase
-from plugins import check_disk_and_inode as checkDisk
-
-
-class TestDisk(TestCaseBase):
- def mock_osaccess(self, path=None, osflag=None):
- return True
-
- def mock_getstatusoutput(self, i):
- out = [
- "Filesystem Size Used Avail Use% Mounted on",
- "/dev/sda1 290G 174G 102G 64% /",
- "/dev/sdb1 3.9G 0 3.9G 0% /var",
- "/dev/sdc1 290G 200G 100G 40% /mnt1",
- "/dev/mapper/vg_test1-lv_one "
- "35852 1774 32257 85% /lvm1",
- "- 994 1 994 1% /dev",
- "/dev/mapper/vg_demonode2-lv1 "
- "50G 11G 36G 24% /mnt/lv4",
- "/dev/vda1 485M 36M 424M 8% /mnt/abc1",
- "/dev/mapper/vg_demonode2-lv_2 "
- "5.5G 4.3G 933M 83% /mnt/abc2",
- "none 0 0 0 - "
- "/proc/sys/fs/binfmt_misc",
- "10.70.43.190:/exports/abc 50G 11G 36G 24% /mnt",
- "10.70.43.190:vol3 50G 11G 36G 24% /mnt/vol3",
- "10.70.43.190:vol2 52846MB 23228MB 26934MB 47% /mnt/vol2"]
-
- if type(i) is str:
- disk = i.split()[-1]
- for diskDetail in out:
- if diskDetail.find(disk) >= 0:
- return 0, diskDetail
- else:
- return 0, out[0] + out[i]
- return 0, ""
-
- def mock_open(self, fileName):
- out = ["/dev/mapper/vg_demonode2-lv_1 /mnt/abc1 ext4 rw 0 0",
- "proc /proc proc rw 0 0",
- "sysfs /sys sysfs rw 0 0",
- "devpts /dev/pts devpts rw,gid=5,mode=620 0 0",
- "tmpfs /dev/shm tmpfs rw 0 0",
- "/dev/sda1 /boot ext4 rw 0 0",
- "/dev/mapper/vg_demonode2-lv_2 /mnt/abc2 ext4 rw 0 0",
- "none /proc/sys/fs/binfmt_misc binfmt_misc rw 0 0",
- "sunrpc /var/lib/nfs/rpc_pipefs rpc_pipefs rw 0 0",
- "10.70.43.190:/exports/abc /mnt nfs rw,vers=4,addr=10.70.43.190"
- ",clientaddr=10.70.43.190 0 0",
- "10.70.43.190:vol2 /mnt/vol2 nfs rw,addr=10.70.43.190 0 0",
- "10.70.43.190:vol3 /mnt/vol3 nfs rw,addr=10.70.43.190 0 0"]
-
- class file():
- def readlines(self):
- return out
-
- def close(self):
- return None
- return file()
-
- def test_getUsageAndFree(self):
- commands.getstatusoutput = self.mock_getstatusoutput
- os.access = self.mock_osaccess
- disk = checkDisk.getUsageAndFree(1, "", 80, 90, "")
- self.assertEqual(disk['usePcent'], 64)
- self.assertEqual(disk['availPcent'], 36)
- self.assertEqual(disk['used'], 174)
- self.assertEqual(disk['avail'], 102)
- self.assertEqual(disk['path'], '/')
-
- disk = checkDisk.getUsageAndFree(2, "", 80, 90, "")
- self.assertEqual(disk['usePcent'], 0)
- self.assertEqual(disk['availPcent'], 100)
- self.assertEqual(disk['used'], 0)
- self.assertEqual(disk['avail'], 3.0)
- self.assertEqual(disk['path'], '/var')
-
- disk = checkDisk.getUsageAndFree(3, "", 80, 90, "")
- self.assertEqual(disk['usePcent'], 40)
- self.assertEqual(disk['availPcent'], 60)
- self.assertEqual(disk['used'], 200)
- self.assertEqual(disk['avail'], 100)
- self.assertEqual(disk['path'], '/mnt1')
-
- disk = checkDisk.getUsageAndFree(4, "", 80, 90, "")
- self.assertEqual(disk['usePcent'], 85)
- self.assertEqual(disk['availPcent'], 15)
- self.assertEqual(disk['used'], 1774)
- self.assertEqual(disk['avail'], 32257)
- self.assertEqual(disk['path'], '/lvm1')
-
- def test_getMounts(self):
- checkDisk.open = self.mock_open
- mounts = checkDisk.getMounts("/", [])
- self.assertEqual(mounts[0], "/dev/mapper/vg_demonode2-lv_1")
- self.assertEqual(mounts[1], "/dev/sda1")
- self.assertEqual(mounts[2], "/dev/mapper/vg_demonode2-lv_2")
-
- mounts = checkDisk.getMounts("/dev/mapper", [])
- self.assertEqual(mounts[0], "/dev/mapper/vg_demonode2-lv_1")
- self.assertEqual(mounts[1], "/dev/mapper/vg_demonode2-lv_2")
-
- mounts = checkDisk.getMounts("", [])
- self.assertEqual(len(mounts), 12)
-
- def test_diskUsage(self):
- commands.getstatusoutput = self.mock_getstatusoutput
- checkDisk.open = self.mock_open
- os.access = self.mock_osaccess
- mounts = checkDisk.getMounts("/", [])
-
- self.assertEqual(checkDisk.showDiskUsage(80,
- 90,
- [mounts[1]],
- True,
- usage='BGB'),
- (0, '64.0% used (174.0BGB out of 290.0BGB)\n'
- ':mount(s): (/dev/sda1=/)',
- ['/=174.0BGB;232.0;261.0;0;290.0 '
- '/=174.0;139.2;156.6;0;290.0']))
-
- self.assertEqual(checkDisk.showDiskUsage(80,
- 90,
- [mounts[1]],
- True),
- (0, '64.0% used (174.0GB out of 290.0GB)\n'
- ':mount(s): (/dev/sda1=/)',
- ['/=64.00%;80;90;0;290.0GB '
- '/=64.00%;80;90;0;290.0']))
-
- self.assertEqual(checkDisk.showDiskUsage(80,
- 90,
- [mounts[1]], True),
- (0, '64.0% used (174.0GB out of 290.0GB)\n'
- ':mount(s): (/dev/sda1=/)',
- ['/=64.00%;80;90;0;290.0GB '
- '/=64.00%;80;90;0;290.0']))
-
- self.assertEqual(checkDisk.showDiskUsage(80,
- 90,
- ["/mnt/vol2"], True),
- (0, '47.0% used (22.68359375TB out of '
- '51.607421875TB)\n'
- ':mount(s): (10.70.43.190:vol2=/mnt/vol2)',
- ['/mnt/vol2=47.00%;80;90;0;52846.0GB '
- '/mnt/vol2=47.00%;80;90;0;52846.0']))
-
- self.assertEqual(checkDisk.showDiskUsage(10,
- 20,
- ["/mnt/vol2"], True),
- (2, '47.0% used (22.68359375TB out of '
- '51.607421875TB)\n'
- ':mount(s): (10.70.43.190:vol2=/mnt/vol2)',
- ['/mnt/vol2=47.00%;10;20;0;52846.0GB '
- '/mnt/vol2=47.00%;10;20;0;52846.0']))
-
- # negative test
- self.assertEqual(checkDisk.showDiskUsage(1,
- 100,
- ["/mnt/vol2"], True),
- (1, '47.0% used (22.68359375TB out of '
- '51.607421875TB)\n'
- ':mount(s): (10.70.43.190:vol2=/mnt/vol2)',
- ['/mnt/vol2=47.00%;1;100;0;52846.0GB '
- '/mnt/vol2=47.00%;1;100;0;52846.0']))
diff --git a/tests/test_mounts.py b/tests/test_mounts.py
new file mode 100644
index 0000000..5503e50
--- /dev/null
+++ b/tests/test_mounts.py
@@ -0,0 +1,380 @@
+#
+# Copyright 2014 Red Hat, Inc.
+#
+# This program 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; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Refer to the README and COPYING files for full details of the license
+#
+
+import mock
+import os
+
+from testrunner import PluginsTestCase as TestCaseBase
+from plugins import check_mounts
+
+
+class diskTests(TestCaseBase):
+ def mock_getMountPoint(self, mount):
+ return mount
+
+ def mock_open(self, filename, mode):
+ return open('mounts.txt', 'r')
+
+ def test_parseProcMounts(self):
+ check_mounts.open = self.mock_open
+ expected = {
+ '/bricks/brick2': {
+ 'device': '/dev/mapper/mygroup-thinv2',
+ 'mountOptions': 'rw,relatime,attr2,delaylog,'
+ 'logbsize=64k,sunit=128,swidth=128,noquota',
+ 'fsType': 'xfs'},
+ '/bricks/brick1': {
+ 'device': '/dev/mapper/mygroup-thinv1',
+ 'mountOptions': 'rw,relatime,attr2,delaylog,'
+ 'logbsize=64k,sunit=128,swidth=128,noquota',
+ 'fsType': 'xfs'},
+ '/home': {
+ 'device': '/dev/mapper/vg_dhcp42149-lv_home',
+ 'mountOptions': 'rw,relatime,barrier=1,'
+ 'data=ordered',
+ 'fsType': 'ext4'},
+ '/boot': {
+ 'device': '/dev/vda1',
+ 'mountOptions': 'rw,relatime,barrier=1,'
+ 'data=ordered',
+ 'fsType': 'ext4'},
+ '/': {
+ 'device': '/dev/mapper/vg_dhcp42149-lv_root',
+ 'mountOptions': 'rw,relatime,barrier=1,data=ordered',
+ 'fsType': 'ext4'},
+ '/proc/bus/usb': {
+ 'device': '/proc/bus/usb',
+ 'mountOptions': 'rw,relatime',
+ 'fsType': 'usbfs'}
+ }
+ actual = check_mounts._parseProcMounts()
+ self.assertEquals(expected, actual)
+
+ def mock_os_statvfs(self):
+ f_bsize = 4096
+ f_frsize = 4096
+ f_blocks = 12868767
+ f_bfree = 11503139
+ f_bavail = 10847779
+ f_files = 3276800
+ f_ffree = 3220784
+ f_favail = 3220784
+ f_flag = 4096
+ f_namemax = 255
+ return os.statvfs_result((f_bsize, f_frsize,
+ f_blocks, f_bfree,
+ f_bavail, f_files,
+ f_ffree, f_favail,
+ f_flag, f_namemax))
+
+ @mock.patch('plugins.check_mounts.os.statvfs')
+ def test_getStats(self, mock_os_statvfs):
+ mock_os_statvfs.return_value = self.mock_os_statvfs()
+ expected = {'used_percent': 10.611956840931228,
+ 'used': 5.2094573974609375,
+ 'free_inode': 3220784,
+ 'used_inode': 56016,
+ 'total_inode': 3276800,
+ 'used_percent_inode': 1.70947265625,
+ 'total': 49.090450286865234,
+ 'free': 43.8809928894043}
+ actual = check_mounts._getStats("mount_point")
+ self.assertEquals(expected, actual)
+
+ def mock_utils_execCommand(self):
+ rc = 0
+ out = [' LVM2_LV_UUID=jTHoCy-qFBS-K1FS-WSUp-SG8J-4R7W-2hI01n$LVM2_LV'
+ '_NAME=mythinpool$LVM2_DATA_PERCENT=1.09$LVM2_POOL_LV=$LVM2_LV'
+ '_ATTR=twi-a-tz--$LVM2_LV_SIZE=1024.00$LVM2_LV_PATH=$LVM2_LV_'
+ 'METADATA_SIZE=4.00$LVM2_METADATA_PERCENT=1.07$LVM2_VG_NAME='
+ 'mygroup']
+ err = []
+ return rc, out, err
+
+ @mock.patch('plugins.check_mounts.utils.execCmd')
+ def test_getLvs(self, mock_utils_execCmd):
+ mock_utils_execCmd.return_value = self.mock_utils_execCommand()
+ expected = {
+ 'mygroup/mythinpool': {
+ 'LVM2_LV_PATH': '',
+ 'LVM2_DATA_PERCENT': '1.09',
+ 'LVM2_LV_ATTR': 'twi-a-tz--',
+ 'LVM2_POOL_LV': '',
+ 'LVM2_LV_NAME': 'mythinpool',
+ 'LVM2_METADATA_PERCENT': '1.07',
+ 'LVM2_VG_NAME': 'mygroup',
+ 'LVM2_LV_SIZE': '1024.00',
+ 'LVM2_LV_UUID': 'jTHoCy-qFBS-K1FS-WSUp-SG8J-4R7W-2hI01n',
+ 'LVM2_LV_METADATA_SIZE': '4.00'}
+ }
+ actual = check_mounts.getLvs()
+ self.assertEquals(expected, actual)
+
+ def mock_getStats(self):
+ return {'used_percent': 3.194726947731752,
+ 'used': 0.031635284423828125,
+ 'free_inode': 1048562,
+ 'used_inode': 14,
+ 'total_inode': 1048576,
+ 'used_percent_inode': 1,
+ 'total': 0.990234375,
+ 'free': 0.9585990905761719}
+
+ def mock_parseProcMounts(self):
+ return {
+ '/brick/brk1': {
+ 'device': '/dev/mapper/mygroup-thinv1',
+ 'mountOptions': 'rw,seclabel,relatime,'
+ 'attr2,inode64,noquota',
+ 'fsType': 'xfs'},
+ '/': {
+ 'device': '/dev/mapper/fedora_dhcp43--63-root',
+ 'mountOptions': 'rw,seclabel,relatime,data=ordered',
+ 'fsType': 'ext4'}
+ }
+
+ def mock_getLvs(self):
+ return {
+ '/dev/mygroup/lvol0': {
+ 'LVM2_LV_PATH': '/dev/mygroup/lvol0',
+ 'LVM2_DATA_PERCENT': '',
+ 'LVM2_LV_ATTR': '-wi-------',
+ 'LVM2_POOL_LV': '',
+ 'LVM2_LV_NAME': 'lvol0',
+ 'LVM2_METADATA_PERCENT': '',
+ 'LVM2_VG_NAME': 'mygroup',
+ 'LVM2_LV_SIZE': '4.00',
+ 'LVM2_LV_UUID': 'NDYC4q-Z57a-DKY3-FQt1-FT63-BuHd-ZScwJZ',
+ 'LVM2_LV_METADATA_SIZE': ''},
+ 'mygroup/mythinpool': {
+ 'LVM2_LV_PATH': '/dev/mygroup/mythinpool',
+ 'LVM2_DATA_PERCENT': '1.21',
+ 'LVM2_LV_ATTR': 'twi-a-tz--',
+ 'LVM2_POOL_LV': '',
+ 'LVM2_LV_NAME': 'mythinpool',
+ 'LVM2_METADATA_PERCENT': '1.37',
+ 'LVM2_VG_NAME': 'mygroup',
+ 'LVM2_LV_SIZE': '1536.00',
+ 'LVM2_LV_UUID': 'viQeR0-JHrs-5g27-vVTp-WoOw-bWFy-goaJfO',
+ 'LVM2_LV_METADATA_SIZE': '4.00'},
+ '/dev/dm-7': {
+ 'LVM2_LV_PATH': '/dev/mygroup/thinv1',
+ 'LVM2_DATA_PERCENT': '1.04',
+ 'LVM2_LV_ATTR': 'Vwi-aotz--',
+ 'LVM2_POOL_LV': 'mythinpool',
+ 'LVM2_LV_NAME': 'thinv1',
+ 'LVM2_METADATA_PERCENT': '',
+ 'LVM2_VG_NAME': 'mygroup',
+ 'LVM2_LV_SIZE': '1024.00',
+ 'LVM2_LV_UUID': 'am1XA3-AgYh-IKL4-LfeB-7XR7-dm8U-vbX2Fr',
+ 'LVM2_LV_METADATA_SIZE': ''}
+ }
+
+ def mock_getThinpoolStat(self):
+ return {'metadata_used': 5.351562500000018e-05,
+ 'thinpool_used_percent': 1.21,
+ 'thinpool_used': 0.01814999999999989,
+ 'metadata_used_percent': 1.37,
+ 'metadata_size': 0.00390625,
+ 'metadata_free': 0.003852734375,
+ 'thinpool_size': 1.5,
+ 'thinpool_free': 1.4818500000000001}
+
+ @mock.patch('plugins.check_mounts.getLvs')
+ @mock.patch('plugins.check_mounts._getStats')
+ @mock.patch('plugins.check_mounts.os.path.realpath')
+ @mock.patch('plugins.check_mounts._parseProcMounts')
+ @mock.patch('plugins.check_mounts._getMountPoint')
+ def test_getMountStats(self, mock_getMountPoint, mock_parseProcMounts,
+ mock_os_path_realpath,
+ mock_getStats, mock_getLvs):
+ mock_getMountPoint.return_value = '/brick/brk1'
+ mock_os_path_realpath.return_value = '/dev/dm-7'
+ mock_parseProcMounts.return_value = self.mock_parseProcMounts()
+ mock_getLvs.return_value = self.mock_getLvs()
+ mock_getStats.return_value = self.mock_getStats()
+ expected = {'/brick/brk1': {
+ 'used_percent': 3.194726947731752,
+ 'used': 0.031635284423828125,
+ 'free_inode': 1048562,
+ 'used_inode': 14,
+ 'free': 0.9585990905761719,
+ 'total_inode': 1048576,
+ 'mount_point': '/brick/brk1',
+ 'metadata_used_percent': 1.37,
+ 'total': 0.990234375,
+ 'thinpool_free': 1.4818500000000001,
+ 'metadata_used': 5.351562500000018e-05,
+ 'thinpool_used_percent': 1.21,
+ 'used_percent_inode': 1,
+ 'thinpool_used': 0.01814999999999989,
+ 'metadata_size': 0.00390625,
+ 'metadata_free': 0.003852734375,
+ 'thinpool_size': 1.5}
+ }
+ include = ['/brick/brk1']
+ exclude = []
+ actual = check_mounts.getMountStats(exclude, include)
+ self.assertEquals(expected, actual)
+
+ def _getDetail(self):
+ return {'used_percent': 3.194726947731752,
+ 'used': 0.031635284423828125,
+ 'free_inode': 1048562,
+ 'used_inode': 14,
+ 'free': 0.9585990905761719,
+ 'total_inode': 1048576,
+ 'mount_point': '/run/gluster/snaps/680bdbbeed47'
+ '44a9bcba941580a5feed/brick1',
+ 'metadata_used_percent': 1.37,
+ 'total': 0.990234375,
+ 'thinpool_free': 1.4818500000000001,
+ 'metadata_used': 5.351562500000018e-05,
+ 'thinpool_used_percent': 1.21,
+ 'used_percent_inode': 1,
+ 'thinpool_used': 0.01814999999999989,
+ 'metadata_size': 0.00390625,
+ 'metadata_free': 0.003852734375,
+ 'thinpool_size': 1.5}
+
+ def test_getOutputTest(self):
+ detail = self._getDetail()
+ actual = check_mounts._getOutputText(detail)
+ expected = "/run/gluster/snaps/680bdbbeed4744a9bcba941580a5feed/" \
+ "brick1 - {space - free: 0.959 GiB, used: 3.195%}, " \
+ "{inode - free: 1048562 , used: 1.000%}, {thinpool-data " \
+ "- free: 1.482 GiB, used: 1.210%}, {thinpool-metadata " \
+ "- free: 0.004 GiB, used: 1.370%}"
+ self.assertEquals(actual, expected)
+
+ def test_getPerfdata(self):
+ detail = self._getDetail()
+ warn = 80
+ crit = 90
+ actual = check_mounts._getPerfdata(detail, warn, crit)
+ expected = "/run/gluster/snaps/680bdbbeed4744a9bcba941580a5feed/" \
+ "brick1=3.195%;80;90;0;0.990 /run/gluster/snaps/" \
+ "680bdbbeed4744a9bcba941580a5feed/brick1.inode=1.000%;80;" \
+ "90;0;1048576 /run/gluster/snaps/680bdbbeed4744a9bcba941" \
+ "580a5feed/brick1.thinpool=1.210%;80;90;0;1.500 /run/" \
+ "gluster/snaps/680bdbbeed4744a9bcba941580a5feed/brick1." \
+ "metadata=1.370%;80;90;0;0.004"
+ self.assertEquals(actual, expected)
+
+ def test_getStatusInfo(self):
+ detail = self._getDetail()
+ warn = 2
+ crit = 4
+ actual = check_mounts._getStatusInfo(detail, warn, crit)
+ expected = ('WARNING',
+ "mount point /run/gluster/snaps/"
+ "680bdbbeed4744a9bcba941580a5feed/brick1 "
+ "{space used 0.032 / 0.990 GiB}")
+ self.assertEquals(actual, expected)
+
+ def test_getPrintableStatus(self):
+ mountDetail = {
+ '/home': {
+ 'used_percent': 0.24067115853902976,
+ 'used': 0.0429229736328125,
+ 'free_inode': 1196017,
+ 'used_inode': 15,
+ 'free': 17.79177474975586,
+ 'total_inode': 1196032,
+ 'mount_point': '/home',
+ 'metadata_used_percent': None,
+ 'total': 17.834697723388672,
+ 'thinpool_free': None,
+ 'metadata_used': None,
+ 'thinpool_used_percent': None,
+ 'used_percent_inode': 1,
+ 'thinpool_used': None,
+ 'metadata_size': None,
+ 'metadata_free': None,
+ 'thinpool_size': None},
+ '/boot': {
+ 'used_percent': 13.709776644000229,
+ 'used': 0.06375885009765625,
+ 'free_inode': 127662,
+ 'used_inode': 354,
+ 'free': 0.4013023376464844,
+ 'total_inode': 128016,
+ 'mount_point': '/boot',
+ 'metadata_used_percent': None,
+ 'total': 0.4650611877441406,
+ 'thinpool_free': None,
+ 'metadata_used': None,
+ 'thinpool_used_percent': None,
+ 'used_percent_inode': 1,
+ 'thinpool_used': None,
+ 'metadata_size': None,
+ 'metadata_free': None,
+ 'thinpool_size': None},
+ '/brick/brk1': {
+ 'used_percent': 3.194726947731752,
+ 'used': 0.031635284423828125,
+ 'free_inode': 1048562,
+ 'used_inode': 14,
+ 'free': 0.9585990905761719,
+ 'total_inode': 1048576,
+ 'mount_point': '/brick/brk1',
+ 'metadata_used_percent': 1.37,
+ 'total': 0.990234375,
+ 'thinpool_free': 1.4818500000000001,
+ 'metadata_used': 5.351562500000018e-05,
+ 'thinpool_used_percent': 1.21,
+ 'used_percent_inode': 1,
+ 'thinpool_used': 0.01814999999999989,
+ 'metadata_size': 0.00390625,
+ 'metadata_free': 0.003852734375,
+ 'thinpool_size': 1.5
+ }
+ }
+ expRc = 'CRITICAL'
+ expMsg = ['mount point /boot {space used 0.064 / 0.465 GiB}',
+ 'mount point /brick/brk1 '
+ '{space used 0.032 / 0.990 GiB}']
+ expOut = ['/boot - {space - free: 0.401 GiB, used: 13.710%},'
+ ' {inode - free: 127662 , used: 1.000%}',
+ '/brick/brk1 - {space - free: 0.959 GiB, used: 3.195%},'
+ ' {inode - free: 1048562 , used: 1.000%}, '
+ '{thinpool-data - free: 1.482 GiB, used: 1.210%},'
+ ' {thinpool-metadata - free: 0.004 GiB, used: 1.370%}',
+ '/home - {space - free: 17.792 GiB, used: 0.241%},'
+ ' {inode - free: 1196017 , used: 1.000%}']
+ expPerfData = ['/boot=13.710%;2;4;0;0.465 /boot.inode='
+ '1.000%;2;4;0;128016',
+ '/brick/brk1=3.195%;2;4;0;0.990 '
+ '/brick/brk1.inode=1.000%;2;4;0;1048576 '
+ '/brick/brk1.thinpool=1.210%;2;4;0;1.500 '
+ '/brick/brk1.metadata=1.370%;2;4;0;0.004',
+ '/home=0.241%;2;4;0;17.835 '
+ '/home.inode=1.000%;2;4;0;1196032']
+ warning = 2
+ critical = 4
+ actRc, actMsg, actOut, actPerfData = check_mounts.getPrintableStatus(
+ mountDetail,
+ warning,
+ critical
+ )
+ self.assertEquals(actRc, expRc)
+ self.assertEquals(actMsg, expMsg)
+ self.assertEquals(actOut, expOut)
+ self.assertEquals(actPerfData, expPerfData)