#!/usr/local/bin/perl -w

# Copyright (c) 2007, 2008 
# Written by Nathan Butcher
#
# Released under the GNU Public License
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# Version: 1.3
# This plugin currently supports : 
# "mirror", "stripe", "raid3", "concat", and "shsec" GEOM classes.
# With a bit of fondling, it could be expanded to recognize other classes
#
# Usage:   check_geom <geom class> <volume>
# Example: check_geom mirror gm0
#          WARNING gm0 DEGRADED, { ad0 , ad1 (32%) }

use strict;

my %ERRORS=('DEPENDENT'=>4,'UNKNOWN'=>3,'OK'=>0,'WARNING'=>1,'CRITICAL'=>2);
my $state="UNKNOWN";
my $msg="FAILURE";

if ($#ARGV < 1) {
	print "Not enough arguments!\nUsage: $0 <class> <device>\n";
	exit $ERRORS{$state};
}

if ($^O ne 'freebsd') {
	print "This plugin is only applicable on FreeBSD.\n";
	exit $ERRORS{$state};
}

my $class=$ARGV[0];
my $volume=$ARGV[1];
my $statcommand="geom $class status";

if (! open STAT, "$statcommand|") {
	print ("$state $statcommand returns no result!");
	exit $ERRORS{$state};
}

my $found=0;
my $unit=0;
my $status="";
my $name="";
my $compo="";

while(<STAT>) {

	chomp;
	if ($found) {
		if (/^\s*$class\//) {
			last;
		} else {
			my ($vgh) = /\s+(.*)/;
			$compo="$compo , $vgh";
			$found++;
		}
	}

	if (/^\s*$class\/$volume\s/) {
		($name, $status, $compo) = /(\S+)\s+(\S+)\s+(.*)$/;
		$found=1;
	}
	
}

close(STAT);

if (! $found ) {
	$state = "CRITICAL";
	$msg = sprintf "%s/%s does not exist and/or is not responding!\n", $class, $volume;
	print $state, " ", $msg;
	exit ($ERRORS{$state});
}

if (($class eq "mirror" || $class eq "raid3") && $status =~ /COMPLETE/ ) {
		$state = "OK";
}

if (($class eq "stripe" || $class eq "concat" || $class eq "shsec") && $status =~ /UP/) {
		$state = "OK";
}

if ($state ne "OK") {

	if ($class eq "mirror" && $found >= 2 ) {
		$state = "WARNING";
	} else {
		$state = "CRITICAL";
	}

	if ($class eq "raid3") {
	
		$statcommand="geom $class list $volume";
		
		if (! open STAT, "$statcommand|") {
			print ("$state $statcommand returns no result!");
			exit $ERRORS{$state};
		}

		while (<STAT>) {
			next unless (/Components:/);
			($unit) = /([0-9]+)$/;
			next;
		}

		if ($found == $unit) {
			$state = "WARNING";
		}

	}
}

#goats away!
my $perfdata = sprintf "%s=%d;;;0;", "geom_" . $class, $found;
$msg = sprintf "%s/%s %s { %s }|%s\n", $class, $volume, $status, $compo,
    $perfdata;
print $state, " ", $msg;
exit ($ERRORS{$state});
