#!/usr/bin/perl -T # $RedRiver$ ######################################################################## # check_bioctl *** A nagios check for OpenBSD bioctl # # 2006.07.26 #*#*# andrew fresh ######################################################################## # TODO: # Really need real documentation. ######################################################################## use strict; use warnings; #use Data::Dumper; %ENV = (); use constant NAGIOS_OUTPUT => 1; use POSIX; use lib "/usr/local/libexec/nagios"; use utils qw($TIMEOUT %ERRORS &print_revision &support); use Getopt::Long; Getopt::Long::Configure('bundling'); my $PROGNAME = "check_bioctl"; my $BIOCTL = '/sbin/bioctl'; my %Status_Map = ( Online => 'OK', Offline => 'WARNING', Degraded => 'CRITICAL', Failed => 'CRITICAL', Building => 'WARNING', Rebuild => 'WARNING', 'Hot spare' => 'OK', Unused => 'OK', Scrubbing => 'WARNING', Invalid => 'CRITICAL', ); my $state = 'UNKNOWN'; # tells whether the it is warning, critical, or OK my %states; # This stores the count of states; my $device; my $opt_h; my $opt_V; #Option checking my $status = GetOptions( "version|V" => \$opt_V, "help|h" => \$opt_h, "device|d=s" => \$device, ); if ($status == 0) { print_help() ; exit $ERRORS{'OK'}; } if ($opt_V) { print_revision($PROGNAME,'$Revision: 1.1 $ '); exit $ERRORS{'OK'}; } if ($opt_h || not $device) { print_help(); exit $ERRORS{'OK'}; } my %DISKS; my %VOLUMES; open my $bioctl, "-|", $BIOCTL, $device or die "Couldn't open bioctl: $!"; my $volume_id; while (<$bioctl>) { chomp; # Do these by columns cuZ that is the easiest for now # Volume Status Size Device my @o = unpack("A6 A1 A11 A15 A7 A9 A*", $_); next if $o[0] eq 'Volume'; foreach (@o) { s/^\s+//; s/\s+$//; } #print Dumper \@o; my ($controller, $id, $status, $size, $dev, $details, $name) = @o; if ($controller) { $volume_id = $id; $VOLUMES{$volume_id} = { controller => $controller, id => $volume_id, status => $status, size => $size, device => $dev, details => $details, name => $name, } } if ($dev =~ /^\d+:\d+/) { $DISKS{$volume_id}{$id} = { volume => $VOLUMES{$volume_id}, id => $id, status => $status, size => $size, device => $dev, details => $details, name => $name, }; } } close $bioctl; #print Dumper \%VOLUMES, \%DISKS; foreach my $volume (sort keys %VOLUMES) { next if $VOLUMES{$volume}{'device'} =~ /^\d+:\d+/; my $cur_state = $Status_Map{ $VOLUMES{$volume}{'status'} } ? $Status_Map{ $VOLUMES{$volume}{'status'} } : 'UNKNOWN'; push @{ $states{$cur_state} }, sprintf("%5s %-7s %s", $VOLUMES{$volume}{'controller'}, $VOLUMES{$volume}{'device'}, $VOLUMES{$volume}{'status'} ); } foreach my $volume (sort keys %DISKS) { foreach my $disk (sort keys %{ $DISKS{$volume} }) { my $cur_state = $Status_Map{ $DISKS{$volume}{$disk}{'status'} } ? $Status_Map{ $DISKS{$volume}{$disk}{'status'} } : 'UNKNOWN'; push @{ $states{$cur_state} }, sprintf("%5s %-7s %-11s %s", $DISKS{$volume}{$disk}{'volume'}{'controller'}, $DISKS{$volume}{$disk}{'device'}, $DISKS{$volume}{$disk}{'status'}, $DISKS{$volume}{$disk}{'name'} ); } } #print Dumper \%states; $state = 'OK'; my $have_results = 0; foreach my $error (sort { $ERRORS{$a} <=> $ERRORS{$b} } keys %ERRORS) { if (exists $states{$error}) { $have_results++; $state = $error; } } foreach my $error (sort { $ERRORS{$b} <=> $ERRORS{$a} } keys %ERRORS) { if (exists $states{$error}) { if (NAGIOS_OUTPUT) { print "$error (" . scalar(@{ $states{ $error } }) . ")"; unless ($error eq 'OK') { print '
'; print map { " - $_
" } @{ $states{ $error } }; } } else { print "$error (" . scalar(@{ $states{ $error } }) . "):\n"; print map { " $_\n" } @{ $states{ $error } }; } } } if ($have_results == 0) { print "No results found\n"; } exit $ERRORS{$state}; sub print_help { print < Usage: -d, --device=DEVICE DEVICE to check. Can either be a disk, as in sd0 or a raid card like ami0 -h (--help) usage help -V (--version) version information EOL print_revision($PROGNAME, '$Revision: 1.1 $'); }