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