#!/usr/local/bin/perl # # check the output of solaris metastat for errors use strict; use warnings; no warnings 'redefine'; use Getopt::Long; use vars qw( $metastat $diskset $verbose $help @crits @warns @unknowns @oks $rc $sep ); $ENV{PATH} = "/usr/bin"; $metastat = "/usr/sbin/metastat"; $diskset = ''; $verbose = 0; $help = 0; ############################### sub usage { die "Usage: $0 [-vh] [-s ]\n"; } Getopt::Long::Configure ("bundling"); GetOptions( 's=s' => \$diskset, 'v+' => \$verbose, 'h' => \$help, ); &usage( 0 ) if ( $help ); &check_metastat(); $rc = 0; $sep = ''; if ( $#crits >= 0 ) { $rc = 2; print "CRITICAL ", join( ", ", @crits ); $sep = '; '; } if ( $#warns >= 0 ) { $rc = 1 if ( $rc == 0 ); print $sep, "Warning ", join( ", ", @warns ); $sep = '; '; } if ( $#unknowns >= 0 ) { $rc = 3 if ( $rc == 0 ); print $sep, "Unknown ", join( ", ", @unknowns ); $sep = '; '; } if ( $rc == 0 || $verbose ) { print $sep, "Ok ", join( ", ", @oks ); } print "\n"; exit $rc; ####################################### sub check_metastat { my( $cmd, $md, $mirror, $state, $cont, $target, $disk, $slice, $cdev, $reloc, $dev, $start, $dbase, $spare, %hsp_count, %hsp_not_avail, $junk, $mds_ok ); if ( ! -d '/dev/md/rdsk' ) { push @oks, "no meta disk devices to check"; return; } $cmd = $metastat; $cmd .= " -s $diskset" if ( $diskset ); $cmd .= " 2>&1 |"; $verbose && print "cmd = $cmd\n"; if ( ! open ( pH, $cmd ) ) { push @unknowns, "can't run metastat: $!"; return; } $md = 'oops'; $mds_ok = 0; while( ) { $verbose && print ">> $_"; chomp; if ( ! m/^\s/ ) { $mirror = ''; m/^Original device:/ && next; $md = $_; $md =~ s/:.*//; $md =~ s!.*/!!; $verbose && print "md $md\n"; if ( m!Submirror of (\w+/)?(d\d+)! ) { $mirror = $2; $verbose && print "mirror $mirror\n"; } } elsif ( m/^\s+State:\s+(\S.*\S)\s*/ ) { $state = $1; $verbose && print "state $state\n"; if ( $state eq 'Okay' ) { $mds_ok++; } elsif ( $state =~ m/resyncing/i ) { push @warns, "$md: $state"; } else { push @crits, "$md: $state"; } } elsif ( m/^\s+c(\d+)t(\d+)d(\d+)s(\d+)/ ) { ( $cont, $target, $disk, $slice ) = ( $1, $2, $3, $4 ); $cdev = "c${cont}t${target}d${disk}s${slice}"; $verbose && print "cdev $cdev\n"; #$maxcont = $cont if ( $cont > $maxcont ); if ( $md =~ m/^d\d+/ ) { $reloc = ''; ( $dev, $start, $dbase, $state, $reloc, $spare ) = split; if ( $spare || ( $state ne '' && $state ne 'Okay' && $state ne 'Yes' ) ) { push @crits, $spare ? "$md: $cdev spared by $spare" : "$md: $cdev $state"; } } elsif ( $md =~ m/^hsp\d+/ ) { $hsp_count{ $md }++; s/^\s+//; ( $dev, $state, $junk, $junk ) = split( /\s\s+/ ); if ( $state ne 'Available' ) { push @crits, "$md: $cdev $state"; $hsp_not_avail{ $md }++; } } else { push @warns, "line $.: $cdev in an unknown metadevice type"; } } } close pH; $verbose && print "$mds_ok things ok\n"; # check the hot spare pool foreach $md ( sort keys %hsp_not_avail ) { push @warns, sprintf "%s: %d available of %d in pool, %d%%", $md, $hsp_count{ $md } - $hsp_not_avail{ $md }, $hsp_count{ $md }, ( $hsp_count{ $md } - $hsp_not_avail{ $md } ) * 100 / $hsp_count{ $md }; } }