#!/usr/bin/perl -T
# $RedRiver$
########################################################################
# check_bioctl *** A nagios check for OpenBSD bioctl
#
# 2006.07.26 #*#*# andrew fresh <andrew@mad-techies.org>
########################################################################
# 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 '<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>
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 $');
}