dsa-check-hpasm: Support a --fan-no-redundant option. If supplied then non-redundant...
[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 Getopt::Long::config('bundling');
51 if (!GetOptions (
52         '--help'                => \$params->{'help'},
53         '--ps-no-redundant'     => \$params->{'ps-no-redundant'},
54         '--fan-no-redundant'    => \$params->{'fan-no-redundant'},
55         )) {
56         die ("$PROGRAM_NAME: Usage: $PROGRAM_NAME [--help] [--ps-no-redundant] [--fan-no-redundant]\n");
57 };
58 if ($params->{'help'}) {
59         print "$PROGRAM_NAME: Usage: $PROGRAM_NAME [--help] [--ps-no-redundant] [--fan-no-redundant]\n";
60         print "Checks hp hardware health.\n";
61         exit (0);
62 };
63
64
65 my $prompt = "hpasmcli>";
66 my $exit_status = 0;
67 my $ret = '';
68
69 sub do_dimm {
70   my @output = @_;
71   my $dimm_num = my $status = my $return = my $message = '';
72   my $in_block = my $header_seen = my $num_dimms = 0;
73
74   for my $line (@output) {
75     chomp $line;
76     unless ($header_seen) {
77       next until ($line eq "$prompt SHOW DIMM");
78       $header_seen++;
79       next;
80     }
81
82     if ($line =~ /(^\s*$|-----)/) {
83       if ($in_block) {
84         if ($status ne 'Ok') {
85           $message = sprintf("DIMM%d: %s ", $dimm_num, $status);
86           $exit_status |= 2;
87         }
88         $return .= $message if ($message);
89         $message = $status = '';
90       } else {
91         $in_block++;
92       }
93     }
94
95     if ($line =~ /^Module #:\s+(\d)/) {
96       $dimm_num = $1;
97       $num_dimms++;
98     } elsif ($line =~ /Status:\s+(\S+(\s*(.*)?))/) {
99       $status = $1;
100     } elsif ($line =~ /$prompt/) {
101       last;
102     }
103   }
104
105   if ($return eq '') {
106     return "DIMMS OK ($num_dimms) ";
107   } else {
108     return $return;
109   }
110 }
111
112 sub do_fans {
113   my @output = @_;
114   my $fan_num = my $status = my $present = my $return = my $message = '';
115   my $header_seen = my $num_fans = 0;
116
117   for my $line (@output) {
118     chomp $line;
119     unless ($header_seen) {
120       next until ($line eq "$prompt SHOW FANS");
121       $header_seen++;
122       next;
123     }
124
125     if ($line =~ /^#(\d+)/) {
126       if ($num_fans) {
127         $return .= $message if ($message);
128         $message = '';
129       }
130
131       $fan_num = $1;
132       $num_fans++;
133       my @line = split /\s+/, $line;
134
135       if ($line[1] eq 'VIRTUAL') { # blade, etc
136         $message = 'FAN1: (virtual) OK ';
137         last;
138       }
139
140       if ($line[2] ne 'Yes') {
141         $message = sprintf("FAN%d: status=%s ", $fan_num, $line[2]);
142         $exit_status |= 2;
143       } elsif ($line[3] ne 'NORMAL') {
144         $message = sprintf("FAN%d: speed=%s ", $fan_num, $line[3]);
145         $exit_status |= 1;
146       } elsif ($line[5] ne 'Yes') {
147         $message = sprintf("FAN%d: redundant=%s ",$fan_num, $line[5]);
148         $exit_status |= 1 unless ($params->{'fan-no-redundant'});
149       }
150     } elsif ($line =~ /($prompt|^\s*$)/) {
151       last;
152     }
153   }
154   $return .= $message if ($message);
155
156   if ($return eq '') {
157     return "FANS OK ($num_fans) ";
158   } else {
159     return $return;
160   }
161 }
162
163 sub do_powersupply {
164   my @output = @_;
165   my $ps_num = my $return = my $message = '';
166   my $header_seen = my $num_ps = 0;
167
168   for my $line (@output) {
169     chomp $line;
170     unless ($header_seen) {
171       next until ($line eq "$prompt SHOW POWERSUPPLY");
172       $header_seen++;
173       next;
174     }
175
176     if ($line =~ /^Power supply #(\d+)/) {
177       if ($num_ps) {
178         $return .= $message if ($message);
179         $message = '';
180       }
181       $ps_num = $1;
182       $num_ps++;
183     } elsif ($line =~ /\s+Present\s*:\s+(.*)/) {
184       my $present = $1;
185       if ($present ne 'Yes') {
186         $message = sprintf("PS%d missing ", $ps_num);
187         $exit_status |= 1;
188       }
189     } elsif ($line =~ /\s+Condition\s*:\s+(.*)/) {
190       my $status = $1;
191       if ($status ne 'Ok') {
192         $message = sprintf("PS%d: %s  ", $ps_num, $status);
193         $exit_status |= 2;
194       }
195     } elsif ($line =~ /\s+Redundant\s*:\s+(.*)/) {
196       my $redundant = $1;
197       if ($redundant ne 'Yes') {
198         $message = sprintf("PS%d not redundant ", $ps_num);
199         $exit_status |= 1 unless ($params->{'ps-no-redundant'});
200       }
201     } elsif ($line =~ /($prompt|^\s*$)/) {
202       last;
203     }
204   }
205   $return .= $message if ($message);
206
207   if ($return eq '') {
208     return "POWER OK ($num_ps) ";
209   } else {
210     return $return;
211   }
212 }
213
214 sub do_temp {
215   my @output = @_;
216   my $temp_num = my $return = my $message = '';
217   my $header_seen = my $num_temp = 0;
218
219   for my $line (@output) {
220     chomp $line;
221     unless ($header_seen) {
222       next until ($line eq "$prompt SHOW TEMP");
223       $header_seen++;
224       next;
225     }
226
227     if ($line =~ /^#(\d+)/) {
228       if ($num_temp) {
229         $return .= $message if ($message);
230         $message = '';
231       }
232
233       $temp_num = $1;
234       my @line = split /\s+/, $line;
235
236       my $zone = $line[1];
237       my $current_temp = $line[2];
238       my $threshold = $line[3];
239
240       $current_temp =~ s/(.*)C.*/$1/;
241       $threshold =~ s/(.*)C.*/$1/;
242       next if ($threshold eq '-');
243       $num_temp++;
244
245       if ($current_temp ne '-') {
246         my $off = $threshold - $current_temp;
247         if ($off <= 0) {
248           $message = sprintf("TEMP zone=%s %sC/%sC ", $zone, $current_temp, $threshold);
249           $exit_status |= 2;
250         } elsif ($off < ($threshold/10)) {
251           $message = sprintf("TEMP zone=%s %sC/%sC ", $zone, $current_temp, $threshold);
252           $exit_status |= 1;
253         }
254       }
255     } elsif ($line =~ /($prompt|^\s*$)/) {
256       last;
257     }
258   }
259   $return .= $message if ($message);
260   if ($return eq '') {
261     return "TEMP OK ($num_temp) ";
262   } else {
263     return $return;
264   }
265 }
266
267 my @output = `echo "$command"|sudo hpasmcli 2>&1`;
268 if (($? >> 8) != 0) {
269   print "UNKNOWN: Can't exec hpasmcli: @output\n";
270   exit 3;
271 }
272
273 for my $line (@output) {
274   chomp $line;
275   for my $check (sort keys %callbacks) {
276     if ($line eq "$prompt $check") {
277       $ret .= &{$callbacks{$check}}(@output);
278     }
279   }
280 }
281
282 if ($exit_status & 2) {
283   print "CRTICAL: $ret\n";
284   exit 2;
285 } elsif ($exit_status & 1) {
286   print "WARNING: $ret\n";
287   exit 1;
288 } else {
289   print "OK: $ret\n";
290   exit 0;
291 }