dsa-check-hpasm: Add --fan-high to not tread high fan speeds as a warning condition
[mirror/dsa-nagios.git] / dsa-nagios-checks / checks / dsa-check-hpasm
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5 use English;
6 use Getopt::Long;
7
8 # check status of various hardware devices (fans, temp, dimms, powersupply)
9 # requires hpasmcli
10
11 # Copyright (c) 2009 Stephen Gran <steve@lobefin.net>
12 #
13 # Permission is hereby granted, free of charge, to any person obtaining
14 # a copy of this software and associated documentation files (the
15 # "Software"), to deal in the Software without restriction, including
16 # without limitation the rights to use, copy, modify, merge, publish,
17 # distribute, sublicense, and/or sell copies of the Software, and to
18 # permit persons to whom the Software is furnished to do so, subject to
19 # the following conditions:
20 #
21 # The above copyright notice and this permission notice shall be
22 # included in all copies or substantial portions of the Software.
23 #
24 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
32 my $command = <<EOF;
33 SHOW DIMM
34 SHOW FANS
35 SHOW POWERSUPPLY
36 SHOW TEMP
37 QUIT
38 EOF
39
40 my %callbacks = (
41   'SHOW DIMM'        => \&do_dimm,
42   'SHOW FANS'        => \&do_fans,
43   'SHOW POWERSUPPLY' => \&do_powersupply,
44   'SHOW TEMP'        => \&do_temp,
45 );
46
47
48 my $params = {};
49
50 my $USAGE = "PROGRAM_NAME: Usage: $PROGRAM_NAME [--help] [--ps-no-redundant] [--fan-no-redundant] [--fan-high]\n";
51 Getopt::Long::config('bundling');
52 if (!GetOptions (
53         '--help'                => \$params->{'help'},
54         '--ps-no-redundant'     => \$params->{'ps-no-redundant'},
55         '--fan-no-redundant'    => \$params->{'fan-no-redundant'},
56         '--fan-high'            => \$params->{'fan-high'},
57         )) {
58         die ("$USAGE");
59 };
60 if ($params->{'help'}) {
61         print "$USAGE";
62         print "Checks hp hardware health.\n";
63         exit (0);
64 };
65
66
67 my $prompt = "hpasmcli>";
68 my $exit_status = 0;
69 my $ret = '';
70
71 sub do_dimm {
72   my @output = @_;
73   my $dimm_num = my $status = my $return = my $message = '';
74   my $in_block = my $header_seen = my $num_dimms = 0;
75
76   for my $line (@output) {
77     chomp $line;
78     unless ($header_seen) {
79       next until ($line eq "$prompt SHOW DIMM");
80       $header_seen++;
81       next;
82     }
83
84     if ($line =~ /(^\s*$|-----)/) {
85       if ($in_block) {
86         if ($status ne 'Ok') {
87           $message = sprintf("DIMM%d: %s ", $dimm_num, $status);
88           $exit_status |= 2;
89         }
90         $return .= $message if ($message);
91         $message = $status = '';
92       } else {
93         $in_block++;
94       }
95     }
96
97     if ($line =~ /^Module #:\s+(\d)/) {
98       $dimm_num = $1;
99       $num_dimms++;
100     } elsif ($line =~ /Status:\s+(\S+(\s*(.*)?))/) {
101       $status = $1;
102     } elsif ($line =~ /$prompt/) {
103       last;
104     }
105   }
106
107   if ($return eq '') {
108     return "DIMMS OK ($num_dimms) ";
109   } else {
110     return $return;
111   }
112 }
113
114 sub do_fans {
115   my @output = @_;
116   my $fan_num = my $status = my $present = my $return = my $message = '';
117   my $header_seen = my $num_fans = 0;
118
119   for my $line (@output) {
120     chomp $line;
121     unless ($header_seen) {
122       next until ($line eq "$prompt SHOW FANS");
123       $header_seen++;
124       next;
125     }
126
127     if ($line =~ /^#(\d+)/) {
128       if ($num_fans) {
129         $return .= $message if ($message);
130         $message = '';
131       }
132
133       $fan_num = $1;
134       $num_fans++;
135       my @line = split /\s+/, $line;
136
137       if ($line[1] eq 'VIRTUAL') { # blade, etc
138         $message = 'FAN1: (virtual) OK ';
139         last;
140       }
141
142       if ($line[2] ne 'Yes') {
143         $message = sprintf("FAN%d: status=%s ", $fan_num, $line[2]);
144         $exit_status |= 2;
145       } elsif ($line[3] ne 'NORMAL') {
146         $message = sprintf("FAN%d: speed=%s ", $fan_num, $line[3]);
147         $exit_status |= 1 unless ($line[3] eq 'HIGH' && $params->{'fan-high'});
148       } elsif ($line[5] ne 'Yes') {
149         $message = sprintf("FAN%d: redundant=%s ",$fan_num, $line[5]);
150         $exit_status |= 1 unless ($params->{'fan-no-redundant'});
151       }
152     } elsif ($line =~ /($prompt|^\s*$)/) {
153       last;
154     }
155   }
156   $return .= $message if ($message);
157
158   if ($return eq '') {
159     return "FANS OK ($num_fans) ";
160   } else {
161     return $return;
162   }
163 }
164
165 sub do_powersupply {
166   my @output = @_;
167   my $ps_num = my $return = my $message = '';
168   my $header_seen = my $num_ps = 0;
169
170   for my $line (@output) {
171     chomp $line;
172     unless ($header_seen) {
173       next until ($line eq "$prompt SHOW POWERSUPPLY");
174       $header_seen++;
175       next;
176     }
177
178     if ($line =~ /^Power supply #(\d+)/) {
179       if ($num_ps) {
180         $return .= $message if ($message);
181         $message = '';
182       }
183       $ps_num = $1;
184       $num_ps++;
185     } elsif ($line =~ /\s+Present\s*:\s+(.*)/) {
186       my $present = $1;
187       if ($present ne 'Yes') {
188         $message = sprintf("PS%d missing ", $ps_num);
189         $exit_status |= 1;
190       }
191     } elsif ($line =~ /\s+Condition\s*:\s+(.*)/) {
192       my $status = $1;
193       if ($status ne 'Ok') {
194         $message = sprintf("PS%d: %s  ", $ps_num, $status);
195         $exit_status |= 2;
196       }
197     } elsif ($line =~ /\s+Redundant\s*:\s+(.*)/) {
198       my $redundant = $1;
199       if ($redundant ne 'Yes') {
200         $message = sprintf("PS%d not redundant ", $ps_num);
201         $exit_status |= 1 unless ($params->{'ps-no-redundant'});
202       }
203     } elsif ($line =~ /($prompt|^\s*$)/) {
204       last;
205     }
206   }
207   $return .= $message if ($message);
208
209   if ($return eq '') {
210     return "POWER OK ($num_ps) ";
211   } else {
212     return $return;
213   }
214 }
215
216 sub do_temp {
217   my @output = @_;
218   my $temp_num = my $return = my $message = '';
219   my $header_seen = my $num_temp = 0;
220
221   for my $line (@output) {
222     chomp $line;
223     unless ($header_seen) {
224       next until ($line eq "$prompt SHOW TEMP");
225       $header_seen++;
226       next;
227     }
228
229     if ($line =~ /^#(\d+)/) {
230       if ($num_temp) {
231         $return .= $message if ($message);
232         $message = '';
233       }
234
235       $temp_num = $1;
236       my @line = split /\s+/, $line;
237
238       my $zone = $line[1];
239       my $current_temp = $line[2];
240       my $threshold = $line[3];
241
242       $current_temp =~ s/(.*)C.*/$1/;
243       $threshold =~ s/(.*)C.*/$1/;
244       next if ($threshold eq '-');
245       $num_temp++;
246
247       if ($current_temp ne '-') {
248         my $off = $threshold - $current_temp;
249         if ($off <= 0) {
250           $message = sprintf("TEMP zone=%s %sC/%sC ", $zone, $current_temp, $threshold);
251           $exit_status |= 2;
252         } elsif ($off < ($threshold/10)) {
253           $message = sprintf("TEMP zone=%s %sC/%sC ", $zone, $current_temp, $threshold);
254           $exit_status |= 1;
255         }
256       }
257     } elsif ($line =~ /($prompt|^\s*$)/) {
258       last;
259     }
260   }
261   $return .= $message if ($message);
262   if ($return eq '') {
263     return "TEMP OK ($num_temp) ";
264   } else {
265     return $return;
266   }
267 }
268
269 my @output = `echo "$command"|sudo hpasmcli 2>&1`;
270 if (($? >> 8) != 0) {
271   print "UNKNOWN: Can't exec hpasmcli: @output\n";
272   exit 3;
273 }
274
275 for my $line (@output) {
276   chomp $line;
277   for my $check (sort keys %callbacks) {
278     if ($line eq "$prompt $check") {
279       $ret .= &{$callbacks{$check}}(@output);
280     }
281   }
282 }
283
284 if ($exit_status & 2) {
285   print "CRTICAL: $ret\n";
286   exit 2;
287 } elsif ($exit_status & 1) {
288   print "WARNING: $ret\n";
289   exit 1;
290 } else {
291   print "OK: $ret\n";
292   exit 0;
293 }