summaryrefslogtreecommitdiffstats
path: root/plugins/check_gluster_syslog.py
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_gluster_syslog.py')
-rwxr-xr-xplugins/check_gluster_syslog.py117
1 files changed, 117 insertions, 0 deletions
diff --git a/plugins/check_gluster_syslog.py b/plugins/check_gluster_syslog.py
new file mode 100755
index 0000000..a52667c
--- /dev/null
+++ b/plugins/check_gluster_syslog.py
@@ -0,0 +1,117 @@
+#! /usr/bin/python
+# check_gluster_syslog.py
+# Script to act on syslog messages related to gluster
+# and send output to Nagios via nsca
+#
+# 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 re
+import sys
+import select
+
+import nscautils
+from glusternagios import utils
+
+# skeleton config parameters
+__pollPeriod = 0.75 # the number of seconds between polling for new messages
+__maxAtOnce = 1024 # max no of messages that are processed within one batch
+
+
+def findVolName(pattern):
+ # pattern is of the form <graphid>-<volume name>-<translator name>
+ return pattern[pattern.find('-') + 1:pattern.rfind('-')]
+
+
+def getStatusCode(alertlevel):
+ if alertlevel == 'ALERT':
+ return utils.PluginStatusCode.CRITICAL
+ else:
+ return utils.PluginStatusCode.WARNING
+
+
+def processQuotaMsg(msg, alertlevel):
+ quotapat = re.compile(r'\b\d*-[a-zA-Z0-9_-]*-quota\b')
+ matches = quotapat.search(msg)
+ if matches:
+ volname = findVolName(matches.group())
+ # Now get the actual msg
+ alertMsg = "QUOTA: " + msg[msg.rfind(matches.group()) +
+ len(matches.group()) + 1:]
+ serviceName = nscautils.vol_service_name(volname, "Quota")
+ nscautils.send_to_nsca(nscautils.getNagiosClusterName(),
+ serviceName,
+ getStatusCode(alertlevel),
+ alertMsg)
+
+
+def processMsg(msg):
+ 'Check if msg is indeed from gluster app'
+ custom_logvars = msg[:msg.find(' ')]
+ level = custom_logvars.split('/')[2]
+ appname = custom_logvars.split('/')[3]
+ if appname != 'GLUSTERFSD':
+ return
+ # For gluster messages, need to check the source of message
+ logsource = msg[msg.rfind('['):msg.rfind(']')]
+ if logsource.find('quota') > -1:
+ processQuotaMsg(msg, level)
+
+
+def onReceive(msgs):
+ """This is the entry point where actual work needs to be done. It receives
+ a list with all messages pulled from rsyslog. The list is of variable
+ length, but contains all messages that are currently available. It is
+ suggested NOT to use any further buffering, as we do not know when the
+ next message will arrive. It may be in a nanosecond from now, but it
+ may also be in three hours...
+ """
+ for msg in msgs:
+ processMsg(msg)
+
+
+"""
+-------------------------------------------------------
+This is plumbing that DOES NOT need to be CHANGED
+-------------------------------------------------------
+Implementor's note: Python seems to very agressively
+buffer stdouot. The end result was that rsyslog does not
+receive the script's messages in a timely manner (sometimes
+even never, probably due to races). To prevent this, we
+flush stdout after we have done processing. This is especially
+important once we get to the point where the plugin does
+two-way conversations with rsyslog. Do NOT change this!
+See also: https://github.com/rsyslog/rsyslog/issues/22
+"""
+if __name__ == '__main__':
+ keepRunning = 1
+ while keepRunning == 1:
+ while keepRunning and sys.stdin in \
+ select.select([sys.stdin], [], [], __pollPeriod)[0]:
+ msgs = []
+ while keepRunning and sys.stdin in \
+ select.select([sys.stdin], [], [], 0)[0]:
+ line = sys.stdin.readline()
+ if line:
+ msgs.append(line)
+ else: # an empty line means stdin has been closed
+ keepRunning = 0
+ if len(msgs) >= __maxAtOnce:
+ break
+ if len(msgs) > 0:
+ onReceive(msgs)
+ sys.stdout.flush() # important,Python buffers far too much
+ sys.exit(0)