#!/usr/bin/perl -T # $RedRiver: check_bioctl,v 1.2 2006/07/27 01:08:13 andrew Exp $ ######################################################################## # check_bioctl *** A nagios check for OpenBSD bioctl # # 2006.07.26 #*#*# andrew fresh ######################################################################## # TODO: # Really need real documentation. ######################################################################## use strict; use warnings; %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'; # This maps the status we get from bioctl to something nagios can use 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 @devices; my $opt_h; my $opt_V; #Option checking my $status = GetOptions( "version|V" => \$opt_V, "help|h" => \$opt_h, "device|d=s" => \@devices, ); if ($status == 0) { print_help() ; exit $ERRORS{'OK'}; } if ($opt_V) { print_revision($PROGNAME,'$Revision: 1.3 $ '); exit $ERRORS{'OK'}; } if ($opt_h || not @devices) { print_help(); exit $ERRORS{'OK'}; } my %VOLUMES; foreach my $device (@devices) { 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 my @o = unpack("A6 A1 A11 A15 A7 A9 A*", $_); next if $o[0] eq 'Volume'; foreach (@o) { s/^\s+//; s/\s+$//; } my ($controller, $id, $status, $size, $dev, $details, $name) = @o; my $index = $id; if ($controller) { $volume_id = $id; } else { $index = "$volume_id.$id"; } $VOLUMES{$device}{$index} = { type => 'volume', controller => $controller, id => $id, status => $status, size => $size, device => $dev, details => $details, name => $name, }; if ($dev =~ /^\d+:\d+/) { $VOLUMES{$device}{$index}{'volume'} = $VOLUMES{$device}{$volume_id}; } } close $bioctl; } foreach my $device (sort keys %VOLUMES) { foreach my $index (sort keys %{ $VOLUMES{$device} }) { my $cur_state = $Status_Map{ $VOLUMES{$device}{$index}{'status'} } ? $Status_Map{ $VOLUMES{$device}{$index}{'status'} } : 'UNKNOWN'; if ($VOLUMES{$device}{$index}{'device'} =~ /^\d+:\d/) { push @{ $states{$cur_state} }, sprintf("%5s %-7s %-11s %s", $VOLUMES{$device}{$index}{'volume'}{'controller'}, $VOLUMES{$device}{$index}{'device'}, $VOLUMES{$device}{$index}{'status'}, $VOLUMES{$device}{$index}{'name'} ); } else { push @{ $states{$cur_state} }, sprintf("%5s %-7s %s", $VOLUMES{$device}{$index}{'controller'}, $VOLUMES{$device}{$index}{'device'}, $VOLUMES{$device}{$index}{'status'} ); } } } 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 < [ -d [ -d ... ] ] Usage: -d, --device=DEVICE DEVICE to check. Can be any device that bioctl(8) accepts -h (--help) usage help -V (--version) version information EOL print_revision($PROGNAME, '$Revision: 1.3 $'); }