diff options
author | Sahina Bose <sabose@redhat.com> | 2014-03-14 12:49:59 +0530 |
---|---|---|
committer | Bala.FA <barumuga@redhat.com> | 2014-04-29 10:21:36 +0530 |
commit | ad004f45088ee81723b2a2420b3bce01f0bd845b (patch) | |
tree | 126104f6a84140b5f459b44d641e94ae4376d3d9 | |
parent | 998e1f9ef43f8fd6e2a7a3722bfd4f3f734c450d (diff) |
plugins: Plugin to check the cluster utilization
This plugin sums up the volume utilization outputs in
a cluster
Added a utils livestatus for common code related to
mk_livestatus
Added constants for livestatussocket path
Change-Id: Id665ad3aaa1140e54c831d721ee874421ae84fa3
Signed-off-by: Sahina Bose <sabose@redhat.com>
Reviewed-on: https://cuckoo.blr.redhat.com:8443/10
Reviewed-by: Bala FA <barumuga@redhat.com>
-rw-r--r-- | config/gluster-commands.cfg | 6 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | nagios-server-addons.spec.in | 4 | ||||
-rw-r--r-- | plugins/Makefile.am | 3 | ||||
-rwxr-xr-x | plugins/check_cluster_vol_usage.py | 105 | ||||
-rw-r--r-- | plugins/constants.py.in | 1 | ||||
-rw-r--r-- | plugins/livestatus.py | 48 | ||||
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rw-r--r-- | tests/test_check_cluster_volusage.py | 80 |
9 files changed, 248 insertions, 2 deletions
diff --git a/config/gluster-commands.cfg b/config/gluster-commands.cfg index ccf2998..21ff226 100644 --- a/config/gluster-commands.cfg +++ b/config/gluster-commands.cfg @@ -44,3 +44,9 @@ define command { command_line $USER1$/gluster/notify_ovirt_engine_handler.py -c $HOSTGROUPNAME$ -H $HOSTNAME$ -g $_SERVICEGLUSTER_ENTITY$ -s "$SERVICEDESC$" -t $SERVICESTATE$ -o $_CONTACTOVIRT_REST_API$ -u $_CONTACTOVIRT_USER$ -p $USER3$ } + +define command{ + command_name check_cluster_vol_usage + command_line $USER1$/gluster/check_cluster_vol_usage.py -w $ARG1$ -c $ARG2$ -hg $HOSTNAME$ +} + diff --git a/configure.ac b/configure.ac index b400b9c..e890e53 100644 --- a/configure.ac +++ b/configure.ac @@ -53,6 +53,7 @@ AC_SUBST([nagiospluginsdir], ['${libdir}/nagios/plugins']) AC_SUBST([glusternagiospluginsdir], ['${nagiospluginsdir}/gluster']) AC_SUBST([glusternagioscommonpylibdir], ['${pyexecdir}/glusternagios']) AC_SUBST([nagiosserveraddonstestsdir], ['${datarootdir}/${PACKAGE_NAME}/tests']) +AC_SUBST([nagioslivestatussocketpath], ['${localstatedir}/spool/nagios/cmd/live']) # Checking for pyflakes AC_PATH_PROG([PYFLAKES], [pyflakes]) @@ -93,6 +94,7 @@ AC_CONFIG_FILES([ Makefile nagios-server-addons.spec config/Makefile + plugins/constants.py plugins/Makefile templates/Makefile tests/Makefile diff --git a/nagios-server-addons.spec.in b/nagios-server-addons.spec.in index 08615de..865db79 100644 --- a/nagios-server-addons.spec.in +++ b/nagios-server-addons.spec.in @@ -120,7 +120,7 @@ fi if grep -q "#enable_environment_macros=0" $NagiosCFGFile; then sed -i -e 's/#enable_environment_macros=0/enable_environment_macros=1/g' $NagiosCFGFile elif grep -q "process_performance_data=0" $NagiosCFGFile ; then - sed -i -e 's/process_performance_data=0/process_performance_data=1/g' $NagiosCFGFile + sed -i -e 's/enable_environment_macros=0/enable_environment_macros=1/g' $NagiosCFGFile fi if ! grep -q "#rhs performance monitoring" $NagiosCFGFile; then @@ -132,7 +132,7 @@ cfg_dir=/etc/nagios/gluster service_perfdata_command=process-service-perfdata host_perfdata_command=process-host-perfdata -broker_module=/usr/lib64/check_mk/livestatus.o /var/spool/nagios/cmd/live +broker_module=/usr/lib64/check_mk/livestatus.o @nagioslivestatussocketpath@ EOF fi diff --git a/plugins/Makefile.am b/plugins/Makefile.am index fa515d7..9c943f7 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -1,6 +1,9 @@ dist_glusternagiosplugins_PYTHON = \ + constants.py \ + check_cluster_vol_usage.py \ check_remote_host.py \ gluster_host_service_handler.py \ + livestatus.py \ notify_ovirt_engine_handler.py \ $(NULL) diff --git a/plugins/check_cluster_vol_usage.py b/plugins/check_cluster_vol_usage.py new file mode 100755 index 0000000..2225634 --- /dev/null +++ b/plugins/check_cluster_vol_usage.py @@ -0,0 +1,105 @@ +#!/usr/bin/python +# +# check_cluster_vol_usage +# Aggregated cluster capacity utilization for a +# gluster cluster +# The plugin reads status data using mk-livestatus +# Assumptions: +# - Volume utilization service names begin with "Volume-" +# - Host name associated is cluster name +# - All volume utilization output is of form +# "used=<val>;warn;crit;min;max" +# +# 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 re +from argparse import ArgumentParser +from plugins import livestatus + + +def checkVolumePerfData(clusterName): + + # Write command to socket + cmd = "GET services\nColumns: description host_name " \ + "perf_data custom_variables\nFilter: " \ + "description ~~ %s\n" % 'Volume-' + table = livestatus.readLiveStatus(cmd) + totalUsed = 0.0 + totalAvail = 0.0 + for row in table: + if len(row) <= 3: + return 0.0, 0.0 + host = row[1] + perf_data = row[2] + if len(perf_data) > 2: + perf_arr = perf_data.split(' ') + used = perf_arr[2].split('=')[1] + avail = perf_arr[1].split('=')[1] + if host == clusterName: + totalUsed += float(re.match(r'\d*\.?\d+', used).group()) + totalAvail += float(re.match(r'\d*\.?\d+', avail).group()) + return totalUsed, totalAvail + +# Main method +if __name__ == "__main__": + + parser = ArgumentParser(description= + "Calculate the aggregate " + "capacity usage in cluster") + parser.add_argument('-w', '--warning', + action='store', + type=int, + dest='warn', + help='Warning in %', + default=70) + parser.add_argument('-c', '--critical', + action='store', + type=int, + dest='crit', + help='Critical threshold Warning in %', + default=95) + parser.add_argument('-hg', '--host-group', + action='store', + type=str, + dest='hostgroup', + help='Name of cluster or hostgroup', + required=True) + args = parser.parse_args() + # Check the various performance statuses for the host + used, avail = checkVolumePerfData(args.hostgroup) + statusstr = "OK" + exitstatus = 0 + if used == 0 and avail == 0: + statusstr = "UNKNOWN" + exitstatus = 3 + else: + warn = int((args.warn * avail) / 100.0) + crit = int((args.crit * avail) / 100.0) + usedpercent = int((used/avail) * 100.0) + if (usedpercent >= args.warn): + statusstr = "WARNING" + exitstatus = 1 + if (usedpercent >= args.crit): + statusstr = "CRITICAL" + exitstatus = 2 + + print ("%s - used %s%% of available %s|used=%s;%s;%s;0;%s;" + % (statusstr, usedpercent, + avail, usedpercent, args.warn, args.crit, 100)) + sys.exit(exitstatus) diff --git a/plugins/constants.py.in b/plugins/constants.py.in new file mode 100644 index 0000000..40dd304 --- /dev/null +++ b/plugins/constants.py.in @@ -0,0 +1 @@ +LIVESTATUS_SOCKETPATH = "@nagioslivestatussocketpath@" diff --git a/plugins/livestatus.py b/plugins/livestatus.py new file mode 100644 index 0000000..ce546ce --- /dev/null +++ b/plugins/livestatus.py @@ -0,0 +1,48 @@ +#!/usr/bin/python +# +# livestatus.py +# Utils to query livestatus +# +# 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 socket +from plugins import constants + +_socketPath = constants.LIVESTATUS_SOCKETPATH + + +def readLiveStatus(cmd): + # Change the default separators to + # Linefeed for row, | for columns, + # comma for lists such as contacts, semicolon for lists such as hosts + cmd += "\nSeparators: 10 124 44 59" + s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + s.connect(_socketPath) + + # Write command to socket + s.send(cmd) + + # Close socket + s.shutdown(socket.SHUT_WR) + + # Read the answer + answer = s.recv(1000) + # Parse the answer into a table + table = [line.split('|') for line in answer.split('\n')[:-1]] + + return table diff --git a/tests/Makefile.am b/tests/Makefile.am index e4543f7..40a09a3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -19,6 +19,7 @@ # test_modules = \ + test_check_cluster_volusage.py \ test_check_remote_host.py \ test_notify_ovirt_engine_handler.py \ $(NULL) diff --git a/tests/test_check_cluster_volusage.py b/tests/test_check_cluster_volusage.py new file mode 100644 index 0000000..54e75c6 --- /dev/null +++ b/tests/test_check_cluster_volusage.py @@ -0,0 +1,80 @@ +# +# 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 + +from testrunner import PluginsTestCase as TestCaseBase +from plugins import check_cluster_vol_usage + + +class TestClusterVolUsage(TestCaseBase): + + # Method to test volume perf data when no matching host method + @mock.patch('plugins.livestatus.readLiveStatus') + def test_checkVolumePerfDataNoMatch(self, mock_readLiveStatus): + mock_readLiveStatus.return_value = _getTable() + testTotalUsed, testTotalAvail = (check_cluster_vol_usage + .checkVolumePerfData + ("dummy-cluster")) + assert testTotalUsed == 0 + + # Method to test volume perf data when no matching host method + @mock.patch('plugins.livestatus.readLiveStatus') + def test_checkVolumePerfDataMatch(self, mock_readLiveStatus): + mock_readLiveStatus.return_value = _getTable() + testTotalUsed, testTotalAvail = (check_cluster_vol_usage + .checkVolumePerfData + ("test-cluster")) + print ("testTotal %s" % testTotalUsed) + assert (testTotalUsed == 700) + assert (testTotalAvail == 1134) + + # Method to test volume perf data when no matching host method + @mock.patch('plugins.livestatus.readLiveStatus') + def test_checkVolumePerfNoData(self, mock_readLiveStatus): + mock_readLiveStatus.return_value = _getTableWithoutCustomAndPerData() + testTotalUsed, testTotalAvail = (check_cluster_vol_usage + .checkVolumePerfData + ("test-cluster")) + assert testTotalUsed == 0 + + +def _getTable(): + table = [["Volume Utilization - data-vol", + "test-cluster", + "utilization=4%;70;90 total=734 used=300 free=434", + "VOL_NAME;data-vol"], + ["Volume Utilization - dist-rep", + "test-cluster", + "utilization=100%;70;90 total=400 used=400 free=0", + "VOL_NAME;dist-rep"]] + return table + + +def _getTableWithoutCustomAndPerData(): + table = [["brick1", + "test-cluster", + "", + ""], + ["brick2", + "test-cluster", + "", + ""]] + return table |