Annotation of nagios/check_bioctl/check_bioctl, Revision 1.11
1.1 andrew 1: #!/usr/bin/perl -T
1.11 ! andrew 2: # $RedRiver: check_bioctl,v 1.10 2009/11/12 18:54:38 andrew Exp $
1.1 andrew 3: ########################################################################
4: # check_bioctl *** A nagios check for OpenBSD bioctl
1.7 andrew 5: #
1.9 andrew 6: # 2006.07.26 #*#*# andrew fresh <andrew@afresh1.com>
1.1 andrew 7: ########################################################################
8: use strict;
9: use warnings;
10:
1.11 ! andrew 11: use 5.010;
1.1 andrew 12:
1.11 ! andrew 13: local %ENV = ();
! 14:
! 15: my $NAGIOS_OUTPUT => 1;
1.1 andrew 16:
1.9 andrew 17: my $License = <<'EOL';
18: Copyright (c) 2009 Andrew Fresh <andrew@afresh1.com>
19: Permission to use, copy, modify, and distribute this software for any
20: purpose with or without fee is hereby granted, provided that the above
21: copyright notice and this permission notice appear in all copies.
22:
23: THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
24: WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
25: MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
26: ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
27: WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
28: ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
29: OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30: EOL
31:
1.11 ! andrew 32: my $PROGNAME = 'check_bioctl';
1.10 andrew 33: my $BIOCTL = '/sbin/bioctl';
34:
1.1 andrew 35: use POSIX;
1.10 andrew 36: my $PREFIX;
1.11 ! andrew 37:
1.10 andrew 38: BEGIN {
39: ## no critic 'warnings'
40: no warnings 'uninitialized';
1.11 ! andrew 41: $PREFIX = "${PREFIX}" || '/usr/local'; # Magic for OpenBSD ports tree
1.10 andrew 42: }
43: use lib $PREFIX . '/libexec/nagios';
1.9 andrew 44: use utils qw($TIMEOUT %ERRORS &support);
1.1 andrew 45:
1.10 andrew 46: $SIG{'ALRM'} = sub {
1.11 ! andrew 47: say "ERROR: $PROGNAME timeout";
! 48: exit $ERRORS{'UNKNOWN'};
1.10 andrew 49: };
50: alarm($TIMEOUT);
51:
1.1 andrew 52: use Getopt::Long;
53: Getopt::Long::Configure('bundling');
54:
1.3 andrew 55: # This maps the status we get from bioctl to something nagios can use
1.1 andrew 56: my %Status_Map = (
1.7 andrew 57: Online => 'OK',
58: Offline => 'CRITICAL',
59: Degraded => 'CRITICAL',
60: Failed => 'CRITICAL',
61: Building => 'WARNING',
62: Rebuild => 'WARNING',
63: 'Hot spare' => 'OK',
64: Unused => 'OK',
65: Scrubbing => 'WARNING',
66: Invalid => 'CRITICAL',
1.1 andrew 67: );
68:
1.7 andrew 69: my $state = 'UNKNOWN'; # tells whether the it is warning, critical, or OK
1.2 andrew 70: my @devices;
1.1 andrew 71: my $opt_h;
72: my $opt_V;
73:
74: #Option checking
75: my $status = GetOptions(
1.7 andrew 76: "version|V" => \$opt_V,
77: "help|h" => \$opt_h,
78: "device|d=s" => \@devices,
1.1 andrew 79: );
80:
1.7 andrew 81: if ( $status == 0 ) {
82: print_help();
83: exit $ERRORS{'OK'};
1.1 andrew 84: }
85:
86: if ($opt_V) {
1.11 ! andrew 87: print_revision( $PROGNAME, '$Revision: 1.10 $ ' );
1.7 andrew 88: exit $ERRORS{'OK'};
1.1 andrew 89: }
90:
1.11 ! andrew 91: if ( $opt_h || !@devices ) {
1.7 andrew 92: print_help();
93: exit $ERRORS{'OK'};
1.1 andrew 94: }
95:
1.11 ! andrew 96: my %VOLUMES = read_bioctl( \@devices );
! 97: my %STATES = check_status( \%VOLUMES );
1.1 andrew 98:
99: my $have_results = 0;
1.8 andrew 100: $state = 'OK';
1.7 andrew 101: foreach my $error ( sort { $ERRORS{$b} <=> $ERRORS{$a} } keys %ERRORS ) {
1.11 ! andrew 102: if ( exists $STATES{$error} ) {
1.7 andrew 103: $have_results++;
1.6 andrew 104: $state = $error if $ERRORS{$state} < $ERRORS{$error};
1.5 andrew 105:
1.11 ! andrew 106: if ($NAGIOS_OUTPUT) {
! 107: print "$error (" . scalar( @{ $STATES{$error} } ) . ")";
1.8 andrew 108: if ( $error ne 'OK' ) {
1.7 andrew 109: print '<br>';
1.11 ! andrew 110: print map {" - $_<br>"} @{ $STATES{$error} };
1.7 andrew 111: }
112: }
113: else {
1.11 ! andrew 114: print "$error (" . scalar( @{ $STATES{$error} } ) . "):\n";
! 115: print map {" $_\n"} @{ $STATES{$error} };
1.7 andrew 116: }
117: }
1.1 andrew 118: }
1.7 andrew 119: if ( $have_results == 0 ) {
120: print "No results found\n";
1.1 andrew 121: }
122: exit $ERRORS{$state};
123:
1.11 ! andrew 124: sub read_bioctl {
! 125: my ($devices) = @_;
! 126: my %volumes;
! 127:
! 128: foreach my $d ( @{$devices} ) {
! 129: open my $bioctl, q{-|}, $BIOCTL, $d
! 130: or die "Couldn't open bioctl: $!\n";
! 131: while ( my $line = <$bioctl> ) {
! 132: my ( $i, $item ) = parse_bioctl_line($line);
! 133: $volumes{$d}{$i} = $item;
! 134: }
! 135: ## no critic 'die'
! 136: close $bioctl
! 137: or die $!
! 138: ? "Error closing bioctl pipe: $!\n"
! 139: : "Exit status $? from bioctl \n";
! 140: }
! 141:
! 142: foreach my $d ( keys %volumes ) {
! 143: foreach my $i ( keys %{ $volumes{$d} } ) {
! 144: my $item = $volumes{$d}{$i};
! 145: if ( $item->{device} =~ /^\d+:\d+/xms ) {
! 146: $item->{'volume'} = $volumes{$d}{ $i->{volume_id} };
! 147: }
! 148: }
! 149: }
! 150:
! 151: return %volumes;
! 152: }
! 153:
! 154: sub parse_bioctl_line {
! 155: my ($line) = @_;
! 156: state $vid;
! 157: chomp $line;
! 158:
! 159: # Do these by columns cuZ that is the easiest for now
! 160: my @o = unpack( "A6 A1 A11 A15 A7 A9 A*", $line );
! 161: next if $o[0] eq 'Volume';
! 162:
! 163: foreach (@o) {
! 164: s/^\s+//xms;
! 165: s/\s+$//xms;
! 166: }
! 167:
! 168: my ( $controller, $id, $status, $size, $dev, $details, $name ) = @o;
! 169: my $index = $id;
! 170: if ($controller) {
! 171: $vid = $id;
! 172: }
! 173: else {
! 174: $index = "$vid.$id";
! 175: }
! 176:
! 177: my %item = (
! 178: type => 'volume',
! 179: controller => $controller,
! 180: id => $id,
! 181: status => $status,
! 182: size => $size,
! 183: device => $dev,
! 184: details => $details,
! 185: name => $name,
! 186: volume_id => $vid,
! 187: );
! 188:
! 189: return $index, \%item;
! 190: }
! 191:
! 192: sub check_status {
! 193: my ($volumes) = @_;
! 194:
! 195: my %states;
! 196: foreach my $device ( sort keys %{$volumes} ) {
! 197: foreach my $index ( sort keys %{ $volumes->{$device} } ) {
! 198: my $cur_volume = $volumes->{$device}->{$index};
! 199: my $cur_state = $Status_Map{ $cur_volume->{'status'} }
! 200: || 'UNKNOWN';
! 201:
! 202: if ( $cur_volume->{'device'} =~ /^\d+:\d/xms ) {
! 203: push @{ $states{$cur_state} },
! 204: sprintf(
! 205: "%5s %-7s %-11s %s",
! 206: $cur_volume->{'volume'}{'controller'},
! 207: $cur_volume->{'device'},
! 208: $cur_volume->{'status'},
! 209: $cur_volume->{'name'}
! 210: );
! 211: }
! 212: else {
! 213: push @{ $states{$cur_state} },
! 214: sprintf( "%5s %-7s %s",
! 215: $cur_volume->{'controller'},
! 216: $cur_volume->{'device'},
! 217: $cur_volume->{'status'} );
! 218: }
! 219: }
! 220: }
! 221: return %states;
! 222: }
! 223:
1.1 andrew 224: sub print_help {
1.9 andrew 225: print <<"EOL";
1.1 andrew 226: $PROGNAME plugin for Nagios monitors bioctl on OpenBSD
1.2 andrew 227: $PROGNAME -d <device> [ -d <device2> [ -d ... ] ]
1.1 andrew 228:
229: Usage:
230: -d, --device=DEVICE
1.3 andrew 231: DEVICE to check. Can be any device that bioctl(8) accepts
1.1 andrew 232: -h (--help) usage help
233: -V (--version) version information
234:
235: EOL
1.7 andrew 236:
1.11 ! andrew 237: print_revision( $PROGNAME, '$Revision: 1.10 $' );
1.9 andrew 238:
239: print $License;
1.11 ! andrew 240:
! 241: return 1;
1.1 andrew 242: }
243:
1.9 andrew 244: sub print_revision {
1.11 ! andrew 245: my ( $prog, $rev ) = @_;
1.9 andrew 246: $rev =~ s/^\D+([\d\.]+)\D+$/v$1/xms;
247:
1.11 ! andrew 248: say "$prog $rev";
! 249:
! 250: return 1;
1.9 andrew 251: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>