Initial revision
[manu/check_sas2ircu.git] / check_sas2ircu
1 #!/usr/bin/perl -w
2 # Nagios plugin that checks LSI SAS2 controllers RAID status via sas2ircu
3 # program
4
5 # Copyright (C) 2011 Emmanuel Lacour <elacour@home-dn.net>
6 #
7 # This file is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by the
9 # Free Software Foundation; either version 2, or (at your option) any
10 # later version.
11 #
12 # This file is distributed in the hope that it will be
13 # useful, but WITHOUT ANY WARRANTY; without even the implied warranty
14 # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 # General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this file; see the file COPYING.  If not, write to the Free
19 # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 # 02110-1301, USA.
21
22
23
24 use strict;
25 use lib qw(/usr/local/lib/nagios/plugins /usr/lib/nagios/plugins);
26 use utils qw(%ERRORS);
27
28 my $sas2ircu = '/usr/sbin/sas2ircu';
29 my $status = $ERRORS{'OK'};
30 my %controllers;
31 my $errors_message;
32
33 unless ( -x $sas2ircu ) {
34     print "$sas2ircu not found or not executable\n";
35     exit ($ERRORS{'UNKNOWN'});
36 }
37
38 unless ( $> == 0 ) {
39     print "This program must be run as root. You may use wrappers like sudo to do this.\n";
40     exit ($ERRORS{'UNKNOWN'});
41 }
42
43 foreach my $line (split /\n/, `$sas2ircu LIST`) {
44     if ( $line =~ /^\s+(\d+)\s+(.+)\s+(.+)\s+(.+)\s+(.+)\s+(.+)\s+(.+)\s*$/ ) {
45         my $ctrl_id = $1;
46         my $ctrl_type = $2;
47         $controllers{$ctrl_id}{type} = $ctrl_type;
48     }
49 }
50
51 unless ( scalar keys %controllers ) {
52     print "No controller found\n";
53     exit ($ERRORS{'UNKNOWN'});
54 }
55
56 foreach my $ctrl_id (keys %controllers) {
57     my $infos = `$sas2ircu $ctrl_id DISPLAY`;
58
59     my %ctrl_infos;
60     my $ctrl_start;
61     foreach my $line (split /\n/, $infos) {
62         chomp($line);
63         if ( $line =~ /^Controller information/ ) {
64             $ctrl_start = 1;
65             next;
66         }
67         next unless ( $ctrl_start );
68         if ( $line =~ /^-/ && $ctrl_start == 1 ) {
69             $ctrl_start = 2;
70             next;
71         }
72         if ( $line =~ /^-/ && $ctrl_start == 2 ) {
73             $ctrl_start = 0;
74             next;
75         }
76         next unless ( $ctrl_start == 2 );
77         if ( $line =~ /^\s*(.*)\s+:\s+(.*)$/ ) {
78             my $key = $1;
79             my $value = $2;
80             $key =~ s/\s+$//;
81             $key =~ s/^\s+//;
82             $value =~ s/\s+$//;
83             $value =~ s/^\s+//;
84             $ctrl_infos{$key} = $value;
85         }
86     }
87
88     # Volumes
89     my %volumes_infos;
90     my $volume_id = undef;
91     foreach my $line (split /\n/, $infos) {
92         chomp($line);
93         if ( $line =~ /^IR volume (\d+)\s*$/ ) {
94             $volume_id = $1;
95             next;
96         }
97         if ( defined($volume_id) && $line =~ /^\s*$/ ) {
98             $volume_id = undef;
99             next;
100         }
101         next unless ( defined($volume_id) );
102         if ( $line =~ /^\s*(.*)\s+:\s+(.*)\s*$/ ) {
103             my $key = $1;
104             my $value = $2;
105             $key =~ s/\s+$//;
106             $key =~ s/^\s+//;
107             $value =~ s/\s+$//;
108             $value =~ s/^\s+//;
109             if ( $key =~ /^PHY/ ) {
110                 push @{$volumes_infos{$volume_id}{'disks'}}, $value;
111             } else {
112                 $volumes_infos{$volume_id}{$key} = $value;
113             }
114         }
115     }
116
117     unless ( scalar keys %volumes_infos ) {
118         print "\tNo volume found\n";
119         next;
120     }
121
122     # Disks
123     my %disks_infos;
124     my $disk_start = 0;
125     my $disk_encl = undef;
126     my $disk_slot = undef;
127     foreach my $line (split /\n/, $infos) {
128         chomp($line);
129         if ( $line =~ /^Device is a Hard disk/ ) {
130             $disk_start = 1;
131             next;
132         }
133         if ( $disk_start && $line =~ /^\s*$/ ) {
134             $disk_start = 0;
135             $disk_encl = undef;
136             $disk_slot = undef;
137             next;
138         }
139         next unless ( $disk_start );
140         if ( $line =~ /^\s*(.*)\s+:\s+(.*)\s*$/ ) {
141             my $key = $1;
142             my $value = $2;
143             $key =~ s/\s+$//;
144             $key =~ s/^\s+//;
145             $value =~ s/\s+$//;
146             $value =~ s/^\s+//;
147             if ( $key eq 'Enclosure #' ) {
148                 $disk_encl = $value;
149                 next;
150             }
151             if ( $key eq 'Slot #' ) {
152                 $disk_slot = $value;
153                 next;
154             }
155             if ( defined($disk_encl) && defined($disk_slot) ) {
156                 $disks_infos{$disk_encl.':'.$disk_slot}{$key} = $value;
157             }
158         }
159     }
160
161     foreach my $volume_id (keys %volumes_infos) {
162         unless ( $volumes_infos{$volume_id}{'Status of volume'} eq 'Okay (OKY)' ) {
163             $errors_message .= "Ctrl $ctrl_id: vol $volume_id ".$volumes_infos{$volume_id}{'Status of volume'};
164             $status = $ERRORS{'CRITICAL'} unless ( $volumes_infos{$volume_id}{'Status of volume'} eq 'Okay (OKY)' );
165         }
166
167         unless ( scalar @{$volumes_infos{$volume_id}{disks}} ) {
168             # FIXME is this critical, can this happens ?
169             next;
170         }
171
172         foreach my $disk (@{$volumes_infos{$volume_id}{disks}}) {
173             unless ( $disks_infos{$disk} ) {
174                 $errors_message .= ", disk $disk not found!";
175                 $status = $ERRORS{'CRITICAL'};
176                 next;
177             }
178             unless ( $disks_infos{$disk}{'State'} eq 'Optimal (OPT)' ) {
179                 $errors_message .= ", disk: ".$disk." : ".$disks_infos{$disk}{'State'};
180                 $status = $ERRORS{'CRITICAL'} unless ( $disks_infos{$disk}{'State'} eq 'Optimal (OPT)' );
181             }
182         }
183     }
184 }
185
186 if ( $status == $ERRORS{'OK'} ) {
187     print "All arrays OK\n";
188 } elsif ( $errors_message ) {
189     print "$errors_message\n";
190 }
191
192 exit ($status);