root/check_munin

Revision 9, 4.8 kB (checked in by ixs, 16 years ago)

typofix

  • Property svn:executable set to *
Line 
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2009 Andreas Thienemann <andreas@bawue.net>
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU Library General Public License as published by
7 # the Free Software Foundation; version 2 only
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU Library General Public License for more details.
13 #
14 # You should have received a copy of the GNU Library General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 #
18
19 #
20 # Nagios script to query a munin host for plugin values
21 #
22 # Can be used as an active check instead of check_dummy
23 #
24
25 import optparse
26 import socket
27 import pprint
28 import sys
29 import re
30
31 parser = optparse.OptionParser("usage: %prog -H <Host> -M <Module> [-P <Port>] -D [<warn>] [<crit>]")
32 parser.add_option("-H", "--host", dest="host", type="string",
33                         help="specify host to poll")
34 parser.add_option("-M", "--module", dest="module", type="string",
35                         help="munin module to poll")
36 parser.add_option("-P", "--port", dest="port", default=4949,
37                         type="int", help="port number to poll")
38 parser.add_option("-D", "--debug", action="store_true", dest="debug", default=False,
39                         help="Debug output")
40
41 (options, args) = parser.parse_args()
42
43 HOST = options.host
44 PORT = options.port
45 MODULE = options.module
46 DEBUG = options.debug
47
48 def compare(val, thresh):
49         # Compare value to warning and critical threshoulds
50         # Handle different threshold formats: max, :max, min:, min:max
51
52         val = float(val)
53
54         # max
55         match = re.match("^[:]?([-+]?[0-9]+)$", str(thresh))
56         if match:
57                 max = float(match.group(1))
58                 if val > max:
59                         return 3
60
61
62         # min
63         match = re.match("^([-+]?[0-9]+):$", str(thresh))
64         if match:
65                 min = float(match.group(1))
66                 if val < min:
67                         return 2
68
69         # min:max
70         match = re.match("^([-+]?[0-9]+):([-+]?[0-9]+)$", str(thresh))
71         if match:
72                 min, max = float(match.group(1)), float(match.group(2))
73                 if val <  min or val > max:
74                         return 1
75
76         # okay
77         return 0
78
79 def output(l, cat, desc, ret):
80         if len(l[cat]) > 0:
81                 print MODULE, desc + ";"
82                 for line in l["critical"]:
83                         print "CRITICAL: " + line + ";"
84                 for line in l["warning"]:
85                         print "WARNING: " + line + ";"
86                 for line in l["ok"]:
87                         print "OK: " + line + ";"
88                 sys.exit(ret)
89
90 try:
91         s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
92         s.connect((HOST, PORT))
93         conn = s.makefile('wb', 0)
94 except:
95         print "Couldn't connect to requested host"
96         sys.exit(3)
97
98
99 if conn.readline().startswith("# munin node at"):
100         conn.writelines("config" + MODULE + "\n")
101         order = []
102         data = {}
103         while True:
104                 line = conn.readline()
105                 if DEBUG:
106                         pprint.pprint(line)
107                 # Last message, bail
108                 if line == ".\n":
109                         break
110
111                 label = ""
112
113                 key, val = line.split(" ", 1)
114                 if key.find(".") is not -1:
115                         label = key.split(".")[0]
116                         if label not in data:
117                                 data[label] = { "warning" : "", "critical" : "", "value" : "" }
118                                 order.append(label)
119                                 # No thresholds passed on the command line
120                                 if len(args) == 2:
121                                         data[label]["warning"] = args[0]
122                                         data[label]["critical"] = args[1]
123
124                 # No thresholds passed on the command line, take the munin supplied ones
125                 if len(args) < 2:
126                         if key.endswith("warning"):
127                                 data[label]["warning"] = val[:-1]
128                         if key.endswith("critical"):
129                                 data[label]["critical"] = val[:-1]
130
131         if data[label]["warning"] == "" or data[label]["critical"] == "":
132                 print "UNKNOWN - Couldn't retrieve thresholds, pass some on the command line"
133                 sys.exit(3)
134
135
136         conn.writelines("fetch " + MODULE + "\n")
137         while True:
138                 line = conn.readline()
139                 # Last line, bail
140                 if line == ".\n":
141                         if DEBUG:
142                                 pprint.pprint(data)
143                         break
144
145                 key, val = line.split(" ", 1)
146                 label = key.split(".")[0]
147                 if key.endswith("value"):
148                         data[label]["value"] = val[:-1]
149
150         conn.writelines("quit\n")
151
152 else:
153         print "UNKNOWN - No munin node detected"
154         sys.exit(3)
155
156 conn.close()
157 s.close()
158
159 l = { "ok" : [], "warning" : [], "critical" : [] }
160 for entry in order:
161         # compare actual data: 3 max exceeded, 2 minimum underrun, 1 outside limit, 0 okay
162         for tresh in ["critical", "warning"]:
163                 val = data[entry]["value"]
164                 tval = data[entry][tresh]
165                 tmp = ""
166                 if compare(val, tval) == 3:
167                         tmp = entry + ": " + val + " has exceeded the maximum threshold of " + tval
168                         break
169                 elif compare(val, tval) == 2:
170                         tmp = entry + ": " + val + " has underrun the minimum threshold of " + tval
171                         break
172                 elif compare(val, tval) == 1:
173                         tmp = entry + ": " + val + " is outside of range " + tval
174                         break
175
176         if tmp != "":
177                 l[tresh].append(tmp)
178         else:
179                 l["ok"].append(entry + ": " + val + " is okay")
180
181
182 output(l, "critical", "CRITICAL", 2)
183 output(l, "warning", "WARNING", 1)
184 output(l, "ok", "OK", 0)
Note: See TracBrowser for help on using the browser.