diff options
author | ndarshan <dnarayan@redhat.com> | 2014-03-17 12:21:42 +0530 |
---|---|---|
committer | Bala.FA <barumuga@redhat.com> | 2014-04-29 10:14:32 +0530 |
commit | 686b574d3c1e55a778088b58a1a2fc75ce72d280 (patch) | |
tree | 89e6335b46c42dcea1c66e80cd7500059856ffd5 /plugins | |
parent | fcf78fd752dd24a8bb8b0bf8f62e7ba7ec0aac55 (diff) |
plugins:Fix to handle sadf not accepting time range, test case addition
This patch handles the issue of sadf not accepting time range
when used with -x (xml output) option(seen in version 9.0.4).
Added unit-test for memory, cpu, swap, network plugins and
refactored them.
Change-Id: Ie7c2ecfbb38060f236a6faed606bce0aedd27d7a
Signed-off-by: ndarshan <dnarayan@redhat.com>
Reviewed-on: https://cuckoo.blr.redhat.com:8443/14
Reviewed-by: Bala FA <barumuga@redhat.com>
Tested-by: Bala FA <barumuga@redhat.com>
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/Makefile.am | 6 | ||||
-rwxr-xr-x | plugins/check_disk_and_inode.py | 12 | ||||
-rwxr-xr-x | plugins/cpu.py | 108 | ||||
-rwxr-xr-x | plugins/memory.py | 100 | ||||
-rwxr-xr-x | plugins/network.py | 86 | ||||
-rwxr-xr-x | plugins/sadf.py | 314 | ||||
-rwxr-xr-x | plugins/swap.py | 94 |
7 files changed, 447 insertions, 273 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 2e2c03e..37da1cd 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -5,10 +5,14 @@ crond_DATA = \ dist_glusternagiosplugins_PYTHON = \ check_disk_and_inode.py \ + cpu.py \ + __init__.py \ + memory.py \ + network.py \ sadf.py \ + swap.py \ $(NULL) EXTRA_DIST = \ $(crond_DATA) \ - __init__.py \ $(NULL) diff --git a/plugins/check_disk_and_inode.py b/plugins/check_disk_and_inode.py index 052df3a..02c5cd2 100755 --- a/plugins/check_disk_and_inode.py +++ b/plugins/check_disk_and_inode.py @@ -155,8 +155,16 @@ if __name__ == '__main__': total = (float(used) + float(avail)) / 1000 itot = (float(iused) + float(iavail)) / 1000 disk.append("%s=%.1f;%.1f;%.1f;0;%.1f %s=%.1f;%.1f;%.1f;0;%.1f" % ( - mpath, float(used)/1000, warn*total/100, crit*total/100, total, - ipath, float(iused)/1000, warn*itot/100, crit*itot/100, itot)) + mpath, + float(used) / 1000, + warn * total / 100, + crit * total / 100, + total, + ipath, + float(iused) / 1000, + warn * itot / 100, + crit * itot / 100, + itot)) else: disk.append("%s=%.2f;%s;%s;0;100 %s=%.2f;%s;%s;0;100" % ( mpath, diskUsage, warn, crit, ipath, inodeUsage, warn, crit)) diff --git a/plugins/cpu.py b/plugins/cpu.py new file mode 100755 index 0000000..89e8b57 --- /dev/null +++ b/plugins/cpu.py @@ -0,0 +1,108 @@ +#!/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 sys +import argparse +from glusternagios import utils +import sadf + +_sadfCpuCommand = ["sadf", "-x", "--", "-P", "ALL"] + + +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") + sadf.add_common_args(parser) + args = parser.parse_args() + return args + + +def showCpuStat(warnLevel, critLevel, s): + pl_op = {} + if not s: + pl_op["message"] = ("CPU STATUS UNKNOWN") + pl_op['exit_status'] = utils.PluginStatusCode.UNKNOWN + return pl_op + perfLines = [] + idleCpu = 0 + try: + for cpu in s['cpu-load']['cpu']: + if cpu['number'] == 'all': + idleCpu = cpu['idle'] + perfLines.append( + ("cpu_%s_total=%s%%;%s;%s cpu_%s_system=%s%% " + "cpu_%s_user=%s%% cpu_%s_idle=%s%%" % ( + cpu['number'], 100 - float(cpu['idle']), + warnLevel, critLevel, + cpu['number'], cpu['system'], + cpu['number'], cpu['user'], + cpu['number'], cpu['idle']))) + if len(s['cpu-load']['cpu']) - 1 == 1: + break + except (KeyError, ValueError, TypeError) as e: + pl_op["message"] = "key: %s not found" % str(e) + pl_op["exit_status"] = utils.PluginStatusCode.UNKNOWN + return pl_op + + totalCpuUsage = 100 - float(idleCpu) + if totalCpuUsage > critLevel: + pl_op["message"] = ("CPU Status CRITICAL: Total CPU:" + "%s%% Idle CPU:%s%% " + "| num_of_cpu=%s %s" % ( + totalCpuUsage, idleCpu, + len(s['cpu-load']['cpu']) - 1, + " ".join(perfLines))) + pl_op['exit_status'] = utils.PluginStatusCode.CRITICAL + elif totalCpuUsage > warnLevel: + pl_op["message"] = ("CPU Status WARNING: Total CPU" + ":%s%% Idle CPU:%s%% " + "| num_of_cpu=%s %s" % ( + totalCpuUsage, idleCpu, + len(s['cpu-load']['cpu']) - 1, + " ".join(perfLines))) + pl_op['exit_status'] = utils.PluginStatusCode.WARNING + else: + pl_op["message"] = ("CPU Status OK: Total CPU:%s%% Idle CPU:%s%% " + "| num_of_cpu=%s %s" % ( + totalCpuUsage, idleCpu, + len(s['cpu-load']['cpu']) - 1, + " ".join(perfLines))) + pl_op['exit_status'] = utils.PluginStatusCode.OK + return pl_op + + +if __name__ == '__main__': + args = parse_input() + if args.critical <= args.warning: + print "UNKNOWN:Critical must be greater than Warning." + sys.exit(utils.PluginStatusCode.UNKNOWN) + try: + st = sadf.getLatestStat(sadf.sadfExecCmd(_sadfCpuCommand), + args.interval if args.interval else 1) + except (sadf.SadfCmdExecFailedException, + sadf.SadfXmlErrorException) as e: + print str(e) + exit(utils.PluginStatusCode.UNKNOWN) + d = showCpuStat(args.warning, args.critical, st) + print d["message"] + exit(d['exit_status']) diff --git a/plugins/memory.py b/plugins/memory.py new file mode 100755 index 0000000..c57a269 --- /dev/null +++ b/plugins/memory.py @@ -0,0 +1,100 @@ +#!/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 sys +import argparse +import sadf +from glusternagios import utils + +_sadfMemCommand = ["sadf", "-x", "--", "-r"] + + +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") + sadf.add_common_args(parser) + args = parser.parse_args() + return args + + +def showMemStat(warning, critical, s): + pl_op = {} + if not s: + pl_op["message"] = ("MEMORY STATUS UNKNOWN") + pl_op['exit_status'] = utils.PluginStatusCode.UNKNOWN + return pl_op + try: + totalMem = int(s['memory']['memfree']) + int(s['memory']['memused']) + except (KeyError, ValueError) as e: + pl_op["message"] = "key: %s not found" % str(e) + pl_op["exit_status"] = utils.PluginStatusCode.UNKNOWN + return pl_op + + crit_value = (totalMem * critical) / 100 + war_value = (totalMem * warning) / 100 + if int(s['memory']['memused']) >= crit_value: + pl_op["message"] = utils.PluginStatus.CRITICAL + pl_op['exit_status'] = utils.PluginStatusCode.CRITICAL + elif int(s['memory']['memused']) >= war_value: + pl_op["message"] = utils.PluginStatus.WARNING + pl_op['exit_status'] = utils.PluginStatusCode.WARNING + else: + pl_op["message"] = utils.PluginStatus.OK + pl_op['exit_status'] = utils.PluginStatusCode.OK + try: + pl_op["message"] += ("- %.2f%% used(%skB out of %skB)|" + "Total=%skB;%s;%s;0;%s" + " Used=%skB Buffered=%skB" + " Cached=%skB" % ( + float(s['memory']['memused-percent']), + s['memory']['memused'], + totalMem, + totalMem, + war_value, + crit_value, + totalMem, + s['memory']['memused'], + s['memory']['buffers'], + s['memory']['cached'])) + except (KeyError, ValueError, TypeError) as e: + pl_op["message"] = "key: %s not found" % str(e) + pl_op["exit_status"] = utils.PluginStatusCode.UNKNOWN + return pl_op + return pl_op + +if __name__ == '__main__': + args = parse_input() + if args.critical <= args.warning: + print "UNKNOWN:Critical must be greater than Warning." + sys.exit(utils.PluginStatusCode.UNKNOWN) + try: + st = sadf.getLatestStat(sadf.sadfExecCmd(_sadfMemCommand), + args.interval if args.interval else 1) + except (sadf.SadfCmdExecFailedException, + sadf.SadfXmlErrorException) as e: + print str(e) + exit(utils.PluginStatusCode.UNKNOWN) + d = showMemStat(args.warning, args.critical, st) + print d["message"] + sys.exit(d['exit_status']) diff --git a/plugins/network.py b/plugins/network.py new file mode 100755 index 0000000..d25c848 --- /dev/null +++ b/plugins/network.py @@ -0,0 +1,86 @@ +#!/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 sadf +import argparse +from glusternagios import utils + +_sadfNetCommand = ["sadf", "-x", "--", "-n", "DEV"] + + +def parse_input(): + parser = argparse.ArgumentParser() + group = parser.add_mutually_exclusive_group() + group.add_argument("-e", "--exclude", action="append", + help="Parameters to be excluded") + group.add_argument("-i", "--include", action="append", + help="Parameters to be included") + sadf.add_common_args(parser) + args = parser.parse_args() + return args + + +def showNetStat(s, iface_list=None, list_type=None): + pl_op = {} + if not s: + pl_op["message"] = ("IFACE UNKNOWN") + pl_op['exit_status'] = utils.PluginStatusCode.UNKNOWN + return pl_op + devNames = [] + perfLines = [] + try: + for dev in s['network']['net-dev']: + if list_type == "exclude": + if dev['iface'] in iface_list: + continue + elif list_type == "include": + if dev['iface'] not in iface_list: + continue + devNames.append(dev['iface']) + perfLines.append("%s.rxpck=%s %s.txpck=%s %s.rxkB=%s %s.txkB=%s" + % (dev['iface'], dev['rxpck'], + dev['iface'], dev['txpck'], + dev['iface'], dev['rxkB'], + dev['iface'], dev['txkB'])) + except (KeyError, ValueError, TypeError) as e: + pl_op["message"] = "key: %s not found" % str(e) + pl_op["exit_status"] = utils.PluginStatusCode.UNKNOWN + return pl_op + + pl_op["message"] = ("IFACE OK: %s |%s" % (", ".join(devNames), + " ".join(perfLines))) + pl_op['exit_status'] = utils.PluginStatusCode.OK + return pl_op + +if __name__ == '__main__': + args = parse_input() + try: + st = sadf.getLatestStat(sadf.sadfExecCmd(_sadfNetCommand), + args.interval if args.interval else 1) + except (sadf.SadfCmdExecFailedException, + sadf.SadfXmlErrorException) as e: + print str(e) + exit(utils.PluginStatusCode.UNKNOWN) + if args.exclude: + d = showNetStat(st, args.exclude, "exclude") + elif args.include: + d = showNetStat(st, args.include, "include") + else: + d = showNetStat(st) + print d["message"] + exit(d['exit_status']) diff --git a/plugins/sadf.py b/plugins/sadf.py index 0bafb4a..5ac1ed0 100755 --- a/plugins/sadf.py +++ b/plugins/sadf.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # sadf.py -- nagios plugin uses sadf output for perf data # Copyright (C) 2014 Red Hat Inc # @@ -17,22 +16,18 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA # -import sys -import shlex -import subprocess -import datetime -import argparse -import xml.etree.ElementTree as ET -from collections import defaultdict -_twoMinutes = datetime.timedelta(minutes=2) -_sadfCpuCommand = "sadf -x -- -P ALL" -_sadfMemoryCommand = "sadf -x -- -r" -_sadfNetworkCommand = "sadf -x -- -n DEV" -_sadfSwapSpaceCommand = "sadf -x -- -S" +from datetime import datetime, timedelta +from glusternagios import utils +import xml.etree.cElementTree as etree +if hasattr(etree, 'ParseError'): + _etreeExceptions = (etree.ParseError, AttributeError, ValueError) +else: + _etreeExceptions = (SyntaxError, AttributeError, ValueError) -class sadfCmdExecFailedException(Exception): - message = "sadf command failed" + +class SadfException(Exception): + message = "sadf exception" def __init__(self, rc=0, out=(), err=()): self.rc = rc @@ -55,274 +50,53 @@ class sadfCmdExecFailedException(Exception): return s -def execCmd(command): - proc = subprocess.Popen(command, - close_fds=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - (out, err) = proc.communicate() - return (proc.returncode, out, err) - +class SadfCmdExecFailedException(SadfException): + message = "sadf command failed" -def etree_to_dict(t): - d = {t.tag: {} if t.attrib else None} - children = list(t) - if children: - dd = defaultdict(list) - for dc in map(etree_to_dict, children): - for k, v in dc.iteritems(): - dd[k].append(v) - x = {} - for k, v in dd.iteritems(): - x[k] = v[0] if len(v) == 1 else v - d = {t.tag: x} - if t.attrib: - d[t.tag].update((k, v) for k, v in t.attrib.iteritems()) - if t.text: - text = t.text.strip() - if children or t.attrib: - if text: - d[t.tag]['#text'] = text - else: - d[t.tag] = text - return d +class SadfXmlErrorException(SadfException): + message = "XML error" -def _sadfExecCmd(sadfCmd): - now = datetime.datetime.now() - start = (now - _twoMinutes).strftime("%H:%M:%S") - end = now.strftime("%H:%M:%S") - cmd = sadfCmd + " -s %s -e %s" % (start, end) +def sadfExecCmd(sadfCmd): try: - (rc, out, err) = execCmd(shlex.split(cmd)) + (rc, out, err) = utils.execCmd(sadfCmd, raw=True) except (OSError, ValueError) as e: - raise sadfCmdExecFailedException(err=[str(e)]) + raise SadfCmdExecFailedException(err=[str(e)]) if rc != 0: - raise sadfCmdExecFailedException(rc, [out], [err]) - - root = ET.fromstring(out) - d = etree_to_dict(root) - return d['sysstat']['host']['statistics']['timestamp'] - - -def _getLatestStat(stats): - if not stats: - return {} - if not isinstance(stats, list): - return stats - lstat = stats[0] - latestTime = datetime.datetime.strptime(lstat['time'], - "%H:%M:%S") - for s in stats[1:]: - thisTime = datetime.datetime.strptime(s['time'], - "%H:%M:%S") - if latestTime < thisTime: - lstat = s - latestTime = thisTime - - return lstat - - -def getLatestSadfCpuStat(): - return _getLatestStat(_sadfExecCmd(_sadfCpuCommand)) - - -def getLatestSadfMemStat(): - return _getLatestStat(_sadfExecCmd(_sadfMemoryCommand)) - - -def getLatestSadfNetStat(): - return _getLatestStat(_sadfExecCmd(_sadfNetworkCommand)) + raise SadfCmdExecFailedException(rc, out, err) + try: + return etree.fromstring(out) + except _etreeExceptions: + raise SadfXmlErrorException(err=out) -def getLatestSadfSwapStat(): - return _getLatestStat(_sadfExecCmd(_sadfSwapSpaceCommand)) - - -def showCpuStat(warnLevel, critLevel): - s = getLatestSadfCpuStat() - if not s: - sys.stdout.write("CPU UNKNOWN\n") - sys.exit(3) - perfLines = [] - idleCpu = 0 - for cpu in s['cpu-load']['cpu']: - if cpu['number'] == 'all': - idleCpu = cpu['idle'] - perfLines.append( - ("cpu_%s_total=%s%%;%s;%s cpu_%s_system=%s%% " - "cpu_%s_user=%s%% cpu_%s_idle=%s%%" % ( - cpu['number'], 100-float(cpu['idle']), - warnLevel, critLevel, - cpu['number'], cpu['system'], - cpu['number'], cpu['user'], - cpu['number'], cpu['idle']))) - if len(s['cpu-load']['cpu'])-1 == 1: - break - totalCpuUsage = 100 - float(idleCpu) - if totalCpuUsage > critLevel: - sys.stdout.write( - ("CPU Status CRITICAL: Total CPU:%s%% Idle CPU:%s%% " - "| num_of_cpu=%s %s\n" % (totalCpuUsage, idleCpu, - len(s['cpu-load']['cpu'])-1, - " ".join(perfLines)))) - elif totalCpuUsage > warnLevel: - sys.stdout.write( - ("CPU Status WARNING: Total CPU:%s%% Idle CPU:%s%% " - "| num_of_cpu=%s %s\n" % (totalCpuUsage, idleCpu, - len(s['cpu-load']['cpu'])-1, - " ".join(perfLines)))) - else: - sys.stdout.write( - ("CPU Status OK: Total CPU:%s%% Idle CPU:%s%% " - "| num_of_cpu=%s %s\n" % (totalCpuUsage, idleCpu, - len(s['cpu-load']['cpu'])-1, - " ".join(perfLines)))) - - sys.exit(0) - - -def showSwapStat(warning, critical): - s = getLatestSadfSwapStat() - if not s: - sys.stdout.write("IFACE UNKNOWN\n") - sys.exit(3) - totalSwap = int(s['memory']['swpfree']) + int(s['memory']['swpused']) - crit_value = (totalSwap * critical) / 100 - war_value = (totalSwap * warning) / 100 - if int(s['memory']['swpused']) >= crit_value: - sys.stdout.write("CRITICAL") - eStat = 2 - elif int(s['memory']['swpused']) >= war_value: - sys.stdout.write("WARNING") - eStat = 1 - else: - sys.stdout.write("OK") - eStat = 0 - sys.stdout.write("- %.2f%% used(%skB out of %skB)|Used=%skB;%s;" - "%s;0;%s\n" % (float(s['memory']['swpused-percent']), - s['memory']['swpused'], - totalSwap, - s['memory']['swpused'], - war_value, - crit_value, - totalSwap)) - sys.exit(eStat) - - -def showMemStat(warning, critical): - s = getLatestSadfMemStat() - if not s: - sys.stdout.write("IFACE UNKNOWN\n") - sys.exit(3) - totalMem = int(s['memory']['memfree']) + int(s['memory']['memused']) - crit_value = (totalMem * critical) / 100 - war_value = (totalMem * warning) / 100 - if int(s['memory']['memused']) >= crit_value: - sys.stdout.write("CRITICAL") - eStat = 2 - elif int(s['memory']['memused']) >= war_value: - sys.stdout.write("WARNING") - eStat = 1 - else: - sys.stdout.write("OK") - eStat = 0 - sys.stdout.write("- %.2f%% used(%skB out of %skB)|Total=%skB;%s;%s;0;%s" - " Used=%skB Buffered=%skB" - " Cached=%skB\n" % (float(s['memory']['memused-percent']), - s['memory']['memused'], - totalMem, - totalMem, - war_value, - crit_value, - totalMem, - s['memory']['memused'], - s['memory']['buffers'], - s['memory']['cached'])) - sys.exit(eStat) - - -def showNetStat(iface_list=None, list_type=None): - s = getLatestSadfNetStat() - if not s: - sys.stdout.write("IFACE UNKNOWN\n") - sys.exit(3) - - devNames = [] - perfLines = [] - for dev in s['network']['net-dev']: - if list_type == "exclude": - if dev['iface'] in iface_list: - continue - elif list_type == "include": - if dev['iface'] not in iface_list: - continue - devNames.append(dev['iface']) - perfLines.append("%s.rxpck=%s %s.txpck=%s %s.rxkB=%s %s.txkB=%s" - % (dev['iface'], dev['rxpck'], - dev['iface'], dev['txpck'], - dev['iface'], dev['rxkB'], - dev['iface'], dev['txkB'])) - sys.stdout.write("IFACE OK: %s |%s\n" % (", ".join(devNames), - " ".join(perfLines))) - sys.exit(0) +def utcnow(): + return datetime.utcnow() -def parse_input(): - parser = argparse.ArgumentParser(usage='%(prog)s [-h] (\ -\n-m -w <warning> -c <critical> |\n-s -w <warning> -c <critical>\ - |\n-cp -w <warning> -c <critical> |\n-n [-e <exclude>\ - | -i <include>])') - group1 = parser.add_mutually_exclusive_group(required=True) - group1.add_argument('-m', '--memory', action='store_true', - help="Gives details related to memory") - group1.add_argument('-s', '--swap', action='store_true', - help="Gives details related to swap") - group1.add_argument('-cp', '--cpu', action='store_true', - help="Gives details related to cpu") - group1.add_argument('-n', '--network', action='store_true', - help="Gives details related to network") - parser.add_argument("-w", "--warning", action="store", type=int, - help="Warning threshold in percentage") - parser.add_argument("-c", "--critical", action="store", type=int, - help="Critical threshold in percentage") - group2 = parser.add_mutually_exclusive_group() - group2.add_argument("-e", "--exclude", action="append", - help="Parameters to be excluded") - group2.add_argument("-i", "--include", action="append", - help="Parameters to be included") - args = parser.parse_args() - if args.memory or args.swap or args.cpu: - if not args.critical or not args.warning: - print "UNKNOWN:Missing critical/warning threshold value." - sys.exit(3) - if args.exclude or args.include: - print "UNKNOWN:Exclude/Include is not valid for the given option." - sys.exit(3) - if args.critical <= args.warning: - print "UNKNOWN:Critical must be greater than Warning." - sys.exit(3) +def getLatestStat(root, interval=1): + try: + el = root.findall('host/statistics/timestamp')[-1] + except (_etreeExceptions + (IndexError,)): + raise SadfXmlErrorException(err=[etree.tostring(root)]) + + d = utils.xml2dict(el) + statTime = datetime.strptime("%s %s" % (d['timestamp']['date'], + d['timestamp']['time']), + "%Y-%m-%d %H:%M:%S") + minutes = timedelta(minutes=interval) + now = utcnow() + if (now - statTime) <= minutes: + return d['timestamp'] else: - if args.critical or args.warning: - print "UNKNOWN:Warning/Critical is not valid for the given option." - sys.exit(3) - return args + return None -if __name__ == '__main__': - args = parse_input() - if args.memory: - showMemStat(args.warning, args.critical) - if args.swap: - showSwapStat(args.warning, args.critical) - if args.cpu: - showCpuStat(args.warning, args.critical) - if args.network: - if args.exclude: - showNetStat(args.exclude, "exclude") - if args.include: - showNetStat(args.include, "include") - showNetStat() +def add_common_args(parser): + parser.add_argument("-t", "--interval", action="store", + type=int, + help="Interval of time(min) older than" + " which sadf output in considered stale") diff --git a/plugins/swap.py b/plugins/swap.py new file mode 100755 index 0000000..5e44f6e --- /dev/null +++ b/plugins/swap.py @@ -0,0 +1,94 @@ +#!/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 sadf +import sys +import argparse +from glusternagios import utils + +_sadfSwapCommand = ["sadf", "-x", "--", "-S"] + + +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") + sadf.add_common_args(parser) + args = parser.parse_args() + return args + + +def showSwapStat(warning, critical, s): + pl_op = {} + if not s: + pl_op["message"] = ("SWAP STATUS UNKNOWN") + pl_op['exit_status'] = utils.PluginStatusCode.UNKNOWN + return pl_op + try: + totalSwap = int(s['memory']['swpfree']) + int(s['memory']['swpused']) + except (KeyError, ValueError, TypeError) as e: + pl_op["message"] = "key: %s not found" % str(e) + pl_op["exit_status"] = utils.PluginStatusCode.UNKNOWN + return pl_op + + crit_value = (totalSwap * critical) / 100 + war_value = (totalSwap * warning) / 100 + if int(s['memory']['swpused']) >= crit_value: + pl_op["message"] = utils.PluginStatus.CRITICAL + pl_op['exit_status'] = utils.PluginStatusCode.CRITICAL + elif int(s['memory']['swpused']) >= war_value: + pl_op["message"] = utils.PluginStatus.WARNING + pl_op['exit_status'] = utils.PluginStatusCode.WARNING + else: + pl_op["message"] = utils.PluginStatus.OK + pl_op['exit_status'] = utils.PluginStatusCode.OK + try: + pl_op["message"] += ("- %.2f%% used(%skB out of %skB)|Used=%skB;%s;" + "%s;0;%s" % ( + float(s['memory']['swpused-percent']), + s['memory']['swpused'], + totalSwap, + s['memory']['swpused'], + war_value, + crit_value, + totalSwap)) + except (KeyError, ValueError, TypeError) as e: + pl_op["message"] = "key: %s not found" % str(e) + pl_op["exit_status"] = utils.PluginStatusCode.UNKNOWN + return pl_op + return pl_op + +if __name__ == '__main__': + args = parse_input() + if args.critical <= args.warning: + print "UNKNOWN:Critical must be greater than Warning." + sys.exit(utils.PluginStatusCode.UNKNOWN) + try: + st = sadf.getLatestStat(sadf.sadfExecCmd(_sadfSwapCommand), + args.interval if args.interval else 1) + except (sadf.SadfCmdExecFailedException, + sadf.SadfXmlErrorException) as e: + print str(e) + exit(utils.PluginStatusCode.UNKNOWN) + d = showSwapStat(args.warning, args.critical, st) + print d["message"] + exit(d['exit_status']) |