#!/usr/bin/perl
use strict;
use Getopt::Long;

# Developed: Wed Mar 12 11:58:16 BRST 2008 

our ($opt_debug, $opt_dev, $opt_metric, $opt_h, $opt_warn, $opt_crit, $opt_warn2, $opt_crit2);
our ($mount_cmd) = "/bin/mount";
our ($iostat_cmd) = "/usr/bin/iostat -d -x";
our (@valid_metrics) = ( "all", "rrqms", "wrqms", "rs", "ws", "rsecs", 
		         "wsecs", "rkBs", "wkBs", "avgrq-sz", 
			 "avgqu-sz", "await", "svctm", "util", "requests_merged",
			 "requests", "sectors_by_sec", "kbs" );
our ($metric_pos);

sub main {
	
	parse_args();
	my $data = get_data_line();
	
	if (!device_exists($opt_dev) || !$data) {
		print "Unknown device $opt_dev\n";
		usage();
	}

	process_all_metrics($data) if ($metric_pos == 0);
	process_merged_metrics($data) if ($metric_pos >= 14);

	my @values = split(/\s+/, $data);
	my $value = $values[$metric_pos];	

	if ($value > $opt_crit) {
		print "CRITICAL - $opt_metric metric in $value |$opt_metric=$value;$opt_warn;$opt_crit;;\n";
		exit(2);
	}

	if ($value > $opt_warn) {
		print "WARNING - $opt_metric metric in $value |$opt_metric=$value;$opt_warn;$opt_crit;;\n";
		exit(1);
	}

	print "OK - $opt_metric metric in $value |$opt_metric=$value;$opt_warn;$opt_crit;;\n";
	exit(0);

}

sub process_merged_metrics {
	my $data = shift;
	my @values = split(/\s+/, $data);

	my $reads;
	my $rdesc;
	my $writes;
	my $wdesc;

	if ($metric_pos == 14) {
		$reads = $values[1];
		$rdesc = $valid_metrics[1];
		$writes = $values[2];
		$wdesc = $valid_metrics[2];
	} elsif ($metric_pos == 15) {
		$reads = $values[3];
		$rdesc = $valid_metrics[3];
		$writes = $values[4];
		$wdesc = $valid_metrics[4];
	} elsif ($metric_pos == 16) {
		$reads = $values[5];
		$rdesc = $valid_metrics[5];
		$writes = $values[6];
		$wdesc = $valid_metrics[6];
	} elsif ($metric_pos == 17) {
		$reads = $values[7];
		$rdesc = $valid_metrics[7];
		$writes = $values[8];
		$wdesc = $valid_metrics[8];
	} else {
		print "Unknown error\n";
		exit(3);
	}

	my $ecode = 0;
	if ($reads > $opt_crit || $writes > $opt_crit2) {
		$ecode = 2;
	} elsif ($reads > $opt_warn || $writes > $opt_warn2) {
		$ecode = 1;
	}

	print "$rdesc in $reads and $wdesc in $writes |$rdesc=$reads;$opt_warn;$opt_crit;; $wdesc=$writes;$opt_warn2;$opt_crit2;;\n";
	exit($ecode);
}

sub process_all_metrics {

	my $data = shift;
	my $msg = "";
	my $pmsg = "";
	my @values = split(/\s+/, $data);
	my $c = 0;
	my $w = 0;
	my $i;
	for ($i=1;$i<=$#values;$i++) {
		$msg .= $valid_metrics[$i]."=".$values[$i]." ";
		$pmsg .= $valid_metrics[$i]."=".$values[$i].";$opt_warn;$opt_crit;; ";
		$c = 1 if ($values[$i] > $opt_crit);
		$w = 1 if ($values[$i] > $opt_warn);
	}

	print "$msg | $pmsg\n";
	exit(2) if ($c == 1);
	exit(1) if ($w == 1);
	exit(0);

}

sub get_data_line {
	my @ret = `$iostat_cmd $opt_dev`;

	print "@ret\n" if ($opt_debug);

	foreach (@ret) {
		if (m/^$opt_dev\s+.*$/) {
			return $_;
		}
	}
	
	return 0; 
}

sub device_exists {
	my @ret = `$mount_cmd`;
	foreach (@ret) {
		return 1 if ( $_ =~ /$opt_dev/);
	}
	return 0;
}

sub parse_args {

	GetOptions(
		"h"   => \$opt_h,       "help"        => \$opt_h,
		"v"   => \$opt_debug,   "verbose"     => \$opt_debug,
		"d=s" => \$opt_dev,     "device=s"    => \$opt_dev,
		"m=s" => \$opt_metric,  "metric"      => \$opt_metric,
		"w=s" => \$opt_warn,    "warning"     => \$opt_warn,
		"c=s" => \$opt_crit,    "critical"    => \$opt_crit,
	);

	usage() if ($opt_h);
	usage() if (!defined($opt_dev));
	usage() if (!defined($opt_metric));

	my $f = 0;
	my $c = 0;
	foreach (@valid_metrics) {
		if ($opt_metric eq $_) {
			$f = 1;
			$metric_pos = $c;
		}
		$c++;
	}

	if ($opt_warn =~ ":") {
		($opt_warn, $opt_warn2) = split(/:/,$opt_warn); 
	}

	if ($opt_crit =~ ":") {
		($opt_crit, $opt_crit2) = split(/:/,$opt_crit); 
	}

	if ($opt_debug) {
		print "Warning 1 - $opt_warn\n";
		print "Warning 2 - $opt_warn2\n";
		print "Critical 1 - $opt_crit\n";
		print "Critical 2 - $opt_crit2\n";
	}

	usage() if (!$f);

}


sub usage {
	print "Usage:\n\t$0 -d <device> -m <metric> -w <warning>:<warning 2> -c <critical>:<critical 2> [-v] [-h]\n";
	print "\tMetric can be : @valid_metrics \n\n";
	exit(3);
}

main();
