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