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