diff options
-rw-r--r-- | config/nrpe.in | 2 | ||||
-rw-r--r-- | gluster-nagios-addons.spec.in | 4 | ||||
-rw-r--r-- | plugins/Makefile.am | 2 | ||||
-rwxr-xr-x | plugins/check_disk_and_inode.py | 443 | ||||
-rwxr-xr-x | plugins/check_mounts.py | 265 | ||||
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/mounts.txt | 21 | ||||
-rw-r--r-- | tests/test_disk.py | 187 | ||||
-rw-r--r-- | tests/test_mounts.py | 380 |
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) |