ac0be1cb609a3eaec194f62f58e9dc445e5ba079
[nagios-monitoring] / check_mem_ucd_snmp / check_mem_ucd_snmp
1 #!/usr/bin/perl -w
2 #
3 # check_mem_ucd_snmp: nagios-check testing the memory of a linux-system via SNMP
4 #
5 # see http://www.intra2net.com/en/developer/monitoring/
6 # for current version, documentation, contact information etc.
7 #
8 # (C) 2009 by Gerd v. Egidy <gerd.von.egidy@intra2net.com>
9 #
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2 of the License, or
13 # (at your option) any later version.
14 #
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 # GNU General Public License for more details.
19 #
20
21 use strict;
22 use Nagios::Plugin;
23 use Net::SNMP;
24 use Data::Dumper;
25
26 my $np = Nagios::Plugin->new(
27             plugin  => "check_mem_ucd_snmp",
28             version => "0.1",
29             blurb   => "nagios-check testing the memory of a linux-system via SNMP",
30             usage   => "Usage: %s [-h|--help] -H <hostname> [-p <port>] [-t <timeout>] [-T <retries>] [-v] [-i (KB|MB|GB)]\n"
31                      . "[-1 | -2] [-c <community>]\n"
32                      . "[-3] [-u <username>] [-a (md5|sha)] [-A <authpasswd>] [-x (des|aes)] [-X <privpasswd>]\n"
33                      . "     [-E <contextengineid>] [-n <contextname>]\n"
34                      . "[-t <total-threshold>] [-T <total-threshold>] [-r <real-threshold>] [-R <real-threshold>]",
35             extra   => "\nAll thresholds are in nagios standard format, see\n"
36                      . "http://nagiosplug.sourceforge.net/developer-guidelines.html#THRESHOLDFORMAT\n"
37                      . "for a description\n"
38                      . "\n"
39                      . "This check does currently not support setting the security engine id.\n",
40             url     => "http://www.intra2net.com/en/developer/monitoring/",
41             license => "This nagios plugin is free software, and comes with ABSOLUTELY\n"
42                      . "NO WARRANTY. It may be used, redistributed and/or modified under\n"
43                      . "the terms of the GNU General Public Licence; either version 2\n"
44                      . "of the License, or (at your option) any later version."
45         );
46
47 # basic options
48 $np->add_arg(
49         spec     => "hostname|H=s",
50         help     => "hostname or IP",
51         required => 1
52     );
53 $np->add_arg(
54         spec     => "port|p=i",
55         help     => "portnumber",
56         default  => 161
57     );
58 $np->add_arg(
59         spec     => "retries|T=i",
60         help     => "SNMP retries on error, default: %s",
61         default  => 1
62     );
63 $np->add_arg(
64         spec     => "unit|i=s",
65         help     => "unit for output and thresholds (KB|MB|GB), default: %s",
66         default  => "MB"
67     );
68
69 # snmp v1/v2c
70 $np->add_arg(
71         spec     => "snmpv1|1",
72         help     => "use SNMP version 1"
73     );
74 $np->add_arg(
75         spec     => "snmpv2c|2",
76         help     => "use SNMP version 2c"
77     );
78 $np->add_arg(
79         spec     => "community|c=s",
80         help     => "SNMPv1/SNMPv2c community name, default: %s",
81         default  => "public"
82     );
83
84 # snmp v3
85 $np->add_arg(
86         spec     => "snmpv3|3",
87         help     => "use SNMP version 3"
88     );
89
90 $np->add_arg(
91         spec     => "username|u=s",
92         help     => "SNMPv3 username"
93     );
94 $np->add_arg(
95         spec     => "authprotocol|a=s",
96         help     => "SNMPv3 authentication protocol (md5|sha), default: %s",
97         default  => "md5"
98     );
99 $np->add_arg(
100         spec     => "authpassword|A=s",
101         help     => "SNMPv3 authentication password"
102     );
103 $np->add_arg(
104         spec     => "privprotocol|x=s",
105         help     => "SNMPv3 privacy protocol (des|aes), default: %s",
106         default  => "des"
107     );
108 $np->add_arg(
109         spec     => "privpassword|X=s",
110         help     => "SNMPv3 privacy password"
111     );
112 $np->add_arg(
113         spec     => "contextengineid|E=s",
114         help     => "SNMPv3 context engine ID"
115     );
116 $np->add_arg(
117         spec     => "contextname|n=s",
118         help     => "SNMPv3 context name"
119     );
120
121 # thresholds
122 $np->add_arg(
123         spec     => "totalavail-warning|m=s",
124         help     => "Warning threshold for the total memory (real+swap) available, default: %s",
125         label    => [ "FLOAT:FLOAT" ],
126         default  => "500:"
127     );
128 $np->add_arg(
129         spec     => "totalavail-critical|M=s",
130         help     => "Critical threshold for the total memory (real+swap) available, default: %s",
131         label    => [ "FLOAT:FLOAT" ],
132         default  => "200:"
133     );
134 $np->add_arg(
135         spec     => "realavail-warning|r=s",
136         help     => "Warning threshold for the real memory available (free+buffer+cache), default: %s",
137         label    => [ "FLOAT:FLOAT" ],
138         default  => "200:"
139     );
140 $np->add_arg(
141         spec     => "realavail-critical|R=s",
142         help     => "Critical threshold for the real memory available (free+buffer+cache), default: %s",
143         label    => [ "FLOAT:FLOAT" ],
144         default  => "50:"
145     );
146
147 # parse arguments
148 $np->getopts;
149
150 # care for the unit parameter
151 my $unitstr;
152 my $unitdiv;
153 if (uc($np->opts->get("unit")) eq "KB")
154 {
155     $unitstr="KB";
156     $unitdiv=1;
157 }
158 elsif (uc($np->opts->get("unit")) eq "MB")
159 {
160     $unitstr="MB";
161     $unitdiv=1024;
162 }
163 elsif (uc($np->opts->get("unit")) eq "GB")
164 {
165     $unitstr="GB";
166     $unitdiv=1024*1024;
167 }
168 else
169 {
170     $np->nagios_die("illegal unit requested");
171 }
172
173 # sanity-check the snmp-version
174 my $snmpversion=undef;
175
176 if ($np->opts->get("snmpv1"))
177 {
178     $snmpversion=1;
179 }
180 if ($np->opts->get("snmpv2c"))
181 {
182     if (defined $snmpversion)
183     {
184         $np->nagios_die("you can only define one SNMP version");
185     }
186     else
187     {
188         $snmpversion=2;
189     }
190 }
191 if ($np->opts->get("snmpv3"))
192 {
193     if (defined $snmpversion)
194     {
195         $np->nagios_die("you can only define one SNMP version");
196     }
197     else
198     {
199         $snmpversion=3;
200     }
201 }
202 if (not defined $snmpversion)
203 {
204     # snmp default version
205     $snmpversion=2;
206 }
207
208 # create the SNMP session
209 my %snmpsessionparam = (
210                         -hostname   => $np->opts->get("hostname"),
211                         -port       => $np->opts->get("port"),
212                         -version    => $snmpversion,
213                         -timeout    => $np->opts->get("timeout"),
214                         -retries    => $np->opts->get("retries"),
215                         );
216 my %snmprequestparam = ();
217
218 if ($snmpversion == 1 || $snmpversion == 2)
219 {
220     $snmpsessionparam{-community}=$np->opts->get("community");
221 }
222 else
223 {
224     $snmpsessionparam{-username}=$np->opts->get("username");
225
226     if (defined $np->opts->get("authpassword"))
227     {
228         $snmpsessionparam{-authprotocol}=$np->opts->get("authprotocol");
229         $snmpsessionparam{-authpassword}=$np->opts->get("authpassword");
230     }
231
232     if (defined $np->opts->get("privpassword"))
233     {
234         $snmpsessionparam{-privprotocol}=$np->opts->get("privprotocol");
235         $snmpsessionparam{-privpassword}=$np->opts->get("privpassword");
236     }
237
238     if (defined $np->opts->get("contextname"))
239     {
240         $snmprequestparam{-contextname}=$np->opts->get("contextname");
241     }
242     if (defined $np->opts->get("contextengineid"))
243     {
244         $snmprequestparam{-contextengineid}=$np->opts->get("contextengineid");
245     }
246 }
247
248 ($np->opts->get("verbose") > 1) && print Data::Dumper->Dump([\%snmpsessionparam], [qw(snmp_session_data)]);
249
250 my ($session,$snmperror)=Net::SNMP->session(%snmpsessionparam);
251
252 if (!defined $session)
253 {
254     $np->nagios_die("Error opening SNMP session: $snmperror");
255 }
256
257 # prepare & execute the snmp request
258 my $oid_memTotalSwap  = "1.3.6.1.4.1.2021.4.3.0";
259 my $oid_memAvailSwap  = "1.3.6.1.4.1.2021.4.4.0";
260 my $oid_memTotalReal  = "1.3.6.1.4.1.2021.4.5.0";
261 my $oid_memAvailReal  = "1.3.6.1.4.1.2021.4.6.0";
262 my $oid_memBuffer     = "1.3.6.1.4.1.2021.4.14.0";
263 my $oid_memCached     = "1.3.6.1.4.1.2021.4.15.0";
264 my $oid_ssSwapIn      = "1.3.6.1.4.1.2021.11.3.0";
265 my $oid_ssSwapOut     = "1.3.6.1.4.1.2021.11.4.0";
266 my $oid_intranator_swap_warning = "1.3.6.1.4.1.30475.1.1.3";
267
268 # we really need these oids to complete the check
269 my @essential_oidlist = ($oid_memTotalSwap, $oid_memAvailSwap, $oid_memTotalReal, $oid_memAvailReal,
270                          $oid_memBuffer, $oid_memCached);
271 # all oids, including the additional ones
272 my @oidlist = (@essential_oidlist, $oid_ssSwapIn, $oid_ssSwapOut, $oid_intranator_swap_warning);
273
274 my %thisrequest=%snmprequestparam;
275 $thisrequest{-varbindlist}=\@oidlist;
276
277 ($np->opts->get("verbose") > 2) && print Data::Dumper->Dump([\%thisrequest], [qw(snmp_request_data)]);
278
279 my $result = $session->get_request(%thisrequest);
280 if (!defined $result)
281 {
282     $snmperror=$session->error;
283     $session->close();
284     $np->nagios_die("Error in SNMP request: $snmperror");
285 }
286
287 ($np->opts->get("verbose") > 0) && print Data::Dumper->Dump([$result], [qw(snmp_result)]);
288
289 $session->close();
290
291 # check if the essential oids are there
292 foreach my $oid (@essential_oidlist)
293 {
294     if (!defined $result->{$oid} || $result->{$oid} eq "noSuchObject")
295     {
296         $np->nagios_die("Essential OID $oid missing in result");
297     }
298 }
299
300 # interpret the results: use only OIDs listed as essential here!
301 my $realmem=$result->{$oid_memTotalReal};
302 my $realavail=$result->{$oid_memAvailReal}+$result->{$oid_memBuffer}+$result->{$oid_memCached};
303 my $swap=$result->{$oid_memTotalSwap};
304 my $swapused=$swap-$result->{$oid_memAvailSwap};
305 my $totalavail=$realavail+$result->{$oid_memAvailSwap};
306
307 my @resultvar=(\$realmem, \$realavail, \$swap, \$swapused, \$totalavail);
308 foreach my $varref (@resultvar) 
309 {
310     $$varref/=$unitdiv;
311 }
312
313 # check the thresholds: do this BEFORE the rounding
314 my @results = ();
315
316 push (@results, $np->check_threshold(
317         check    => $totalavail,
318         warning  => $np->opts->get("totalavail-warning"),
319         critical => $np->opts->get("totalavail-critical")
320     ));
321 push (@results, $np->check_threshold(
322         check    => $realavail,
323         warning  => $np->opts->get("realavail-warning"),
324         critical => $np->opts->get("realavail-critical")
325     ));
326
327 # rounding: show decimals only if value less than limit
328 foreach my $varref (@resultvar)
329 {
330     if ($$varref < 20)
331     {
332         $$varref=sprintf("%.2f",$$varref)
333     }
334     else
335     {
336         $$varref=sprintf("%.0f",$$varref)
337     }
338 }
339
340 # output the performance data
341 $np->add_perfdata(
342         label     => "total_avail",
343         value     => $totalavail,
344         uom       => $unitstr,
345         warning   => $np->opts->get("totalavail-warning"),
346         critical  => $np->opts->get("totalavail-critical"),
347         min       => 0,
348         max       => $swap+$realmem
349      );
350 $np->add_perfdata(
351         label     => "real_avail",
352         value     => $realavail,
353         uom       => $unitstr,
354         warning   => $np->opts->get("realavail-warning"),
355         critical  => $np->opts->get("realavail-critical"),
356         min       => 0,
357         max       => $realmem
358      );
359 $np->add_perfdata(
360         label     => "swap_used",
361         value     => $swapused,
362         uom       => $unitstr,
363         min       => 0,
364         max       => $swap
365      );
366
367 # compose message
368 $np->nagios_exit(
369         $np->max_state(@results),
370         "Real av: $realavail $unitstr, Total av: $totalavail $unitstr, Swapped: $swapused $unitstr",
371      );