Index: /check_munin =================================================================== --- /check_munin (revision 7) +++ /check_munin (revision 7) @@ -0,0 +1,184 @@ +#!/usr/bin/python +# +# Copyright (C) 2009 Andreas Thienemann +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; version 2 only +# +# 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 Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +# +# Nagios script to query a munin host for plugin values +# +# Can be used as an active check instead of check_dummy +# + +import optparse +import socket +import pprint +import sys +import re + +parser = optparse.OptionParser("usage: %prog -H -M [-P ] [warn] [crit]") +parser.add_option("-H", "--host", dest="host", type="string", + help="specify host to poll") +parser.add_option("-M", "--module", dest="module", type="string", + help="munin module to poll") +parser.add_option("-P", "--port", dest="port", default=4949, + type="int", help="port number to poll") +parser.add_option("-D", "--debug", action="store_true", dest="debug", default=False, + help="Debug output") + +(options, args) = parser.parse_args() + +HOST = options.host +PORT = options.port +MODULE = options.module +DEBUG = options.debug + +def compare(val, thresh): + # Compare value to warning and critical threshoulds + # Handle different threshold formats: max, :max, min:, min:max + + val = float(val) + + # max + match = re.match("^[:]?([-+]?[0-9]+)$", str(thresh)) + if match: + max = float(match.group(1)) + if val > max: + return 3 + + + # min + match = re.match("^([-+]?[0-9]+):$", str(thresh)) + if match: + min = float(match.group(1)) + if val < min: + return 2 + + # min:max + match = re.match("^([-+]?[0-9]+):([-+]?[0-9]+)$", str(thresh)) + if match: + min, max = float(match.group(1)), float(match.group(2)) + if val < min or val > max: + return 1 + + # okay + return 0 + +def output(l, cat, desc, ret): + if len(l[cat]) > 0: + print MODULE, desc + ";" + for line in l["critical"]: + print "CRITICAL: " + line + ";" + for line in l["warning"]: + print "WARNING: " + line + ";" + for line in l["ok"]: + print "OK: " + line + ";" + sys.exit(ret) + +try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect((HOST, PORT)) + conn = s.makefile('wb', 0) +except: + print "Couldn't connect to requested host" + sys.exit(3) + + +if conn.readline().startswith("# munin node at"): + conn.writelines("config" + MODULE + "\n") + order = [] + data = {} + while True: + line = conn.readline() + if DEBUG: + pprint.pprint(line) + # Last message, bail + if line == ".\n": + break + + label = "" + + key, val = line.split(" ", 1) + if key.find(".") is not -1: + label = key.split(".")[0] + if label not in data: + data[label] = { "warning" : "", "critical" : "", "value" : "" } + order.append(label) + # No thresholds passed on the command line + if len(args) == 2: + data[label]["warning"] = args[0] + data[label]["critical"] = args[1] + + # No thresholds passed on the command line, take the munin supplied ones + if len(args) < 2: + if key.endswith("warning"): + data[label]["warning"] = val[:-1] + if key.endswith("critical"): + data[label]["critical"] = val[:-1] + + if data[label]["warning"] == "" or data[label]["critical"] == "": + print "UNKNOWN - Couldn't retrieve thresholds, pass some on the command line" + sys.exit(3) + + + conn.writelines("fetch " + MODULE + "\n") + while True: + line = conn.readline() + # Last line, bail + if line == ".\n": + if DEBUG: + pprint.pprint(data) + break + + key, val = line.split(" ", 1) + label = key.split(".")[0] + if key.endswith("value"): + data[label]["value"] = val[:-1] + + conn.writelines("quit\n") + +else: + print "UNKNOWN - No munin node detected" + sys.exit(3) + +conn.close() +s.close() + +l = { "ok" : [], "warning" : [], "critical" : [] } +for entry in order: + # compare actual data: 3 max exceeded, 2 minimum underrun, 1 outside limit, 0 okay + for tresh in ["critical", "warning"]: + val = data[entry]["value"] + tval = data[entry][tresh] + tmp = "" + if compare(val, tval) == 3: + tmp = entry + ": " + val + " has exceeded the maximum threshold of " + tval + break + elif compare(val, tval) == 2: + tmp = entry + ": " + val + " has underrun the minimum threshold of " + tval + break + elif compare(val, tval) == 1: + tmp = entry + ": " + val + " is outside of range " + tval + break + + if tmp != "": + l[tresh].append(tmp) + else: + l["ok"].append(entry + ": " + val + " is okay") + + +output(l, "critical", "CRITICAL", 2) +output(l, "warning", "WARNING", 1) +output(l, "ok", "OK", 0)