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