#!/usr/bin/perl -T
# $RedRiver: check_bioctl,v 1.7 2009/11/09 18:00:09 andrew Exp $
########################################################################
# check_bioctl *** A nagios check for OpenBSD bioctl
#
# 2006.07.26 #*#*# andrew fresh <andrew@mad-techies.org>
########################################################################
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 => 'CRITICAL',
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.8 $ ' );
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;
$state = 'OK';
foreach my $error ( sort { $ERRORS{$b} <=> $ERRORS{$a} } keys %ERRORS ) {
if ( exists $states{$error} ) {
$have_results++;
$state = $error if $ERRORS{$state} < $ERRORS{$error};
if (NAGIOS_OUTPUT) {
print "$error (" . scalar( @{ $states{$error} } ) . ")";
if ( $error ne 'OK' ) {
print '<br>';
print map {" - $_<br>"} @{ $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 <<EOL;
$PROGNAME plugin for Nagios monitors bioctl on OpenBSD
$PROGNAME -d <device> [ -d <device2> [ -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.8 $' );
}