#! /usr/bin/perl -w

use strict;
use warnings;
use Getopt::Long;

# change path if you need
use lib "/usr/lib/nagios/plugins";
use lib "/usr/lib64/nagios/plugins";
use lib "/usr/local/nagios/libexec";

use Net::SNMP qw(oid_lex_sort oid_base_match);


# use Net::SNMP;
# snmpwalk -On -m All -v2c -c 'your-community' 'your ip-address' .1.3.6.1.4.1.3417.2.2.1.1.1.1.x.y the full mib disk tree

	my $mibthree_stat='.1.3.6.1.4.1.3417.2.2.1.1.1.1.3';
	my $mibthree_vendor='.1.3.6.1.4.1.3417.2.2.1.1.1.1.5';
	my $mibthree_type='.1.3.6.1.4.1.3417.2.2.1.1.1.1.6';
	my $mibthree_serial='.1.3.6.1.4.1.3417.2.2.1.1.1.1.8';
	my $OID_Sysname='.1.3.6.1.2.1.1.5.0'; 
	my $OID_Hardware='.1.3.6.1.2.1.1.1.0';
	my ($status,@state,$sysname,$opt_version,$opt_license,$opt_help,$opt_timeout,$opt_hostname,$opt_community,$opt_port,$opt_retries,$opt_verbose,$opt_warning,$opt_critical);
	
	my $PROGNAME = "check_bcdisk";
	my $REVISION = "1.0";
	use constant DEFAULT_TIMEOUT		=>3;
	use constant DEFAULT_PORT    		=>161;
	use constant DEFAULT_COMMUNITY  	=>"public";
	use constant DEFAULT_SNMPVERS 		=>"2c";
	use constant DEFAULT_RETRIES 		=>2;
	use constant DEFAULT_WARNING		=>0;
	use constant DEFAULT_CRITICAL		=>0;

sub print_gpl {
	print <<EOD;

	License Information:
	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 3 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, see <http://www.gnu.org/licenses/>. 

EOD
	}


sub print_usage {
	print "Usage: $PROGNAME [-h] [-L] [-t timeout] [-r retries] [-V] [-C community] [-p port] -H hostname [-w warning] [-c critical] [-v verbose]\n\n";
	print "Example: $PROGNAME -H 'ip-address or [DNS,host]name' -t 3 -r 2 -C public -p 161 -w 2 -c 1 -v\n\n";

	}

sub check_args {
	Getopt::Long::Configure('bundling');
	GetOptions
	("V"   			=> \$opt_version,
	"version"   		=> \$opt_version,
	"L"   			=> \$opt_license, 
	"license"   		=> \$opt_license, 
	"h|?" 			=> \$opt_help,
	"help"   		=> \$opt_help,
	"t=i" 			=> \$opt_timeout, 
	"timeout=i" 		=> \$opt_timeout, 
	"H=s" 			=> \$opt_hostname, 
	"hostname=s" 		=> \$opt_hostname, 
	"C=s" 			=> \$opt_community, 
	"community=s" 		=> \$opt_community, 
	"p=i" 			=> \$opt_port, 
	"port=i" 		=> \$opt_port, 
	"r=i" 			=> \$opt_retries, 
	"retries=i" 		=> \$opt_retries,
	"v"			=> \$opt_verbose,
	"verbose"		=> \$opt_verbose, 
	"w=i"			=> \$opt_warning,
	"warning=i"		=> \$opt_warning,
	"c=i"			=> \$opt_critical,
	"critical=i"		=> \$opt_critical,
	 );
	}

sub open_snmp_session {
	my ($session, $error) = Net::SNMP->session(
		-hostname  => shift || $opt_hostname,
		-community => shift || $opt_community,
		-port      => shift || $opt_port,
		-timeout   => shift || $opt_timeout,
		-retries   => shift || $opt_retries, 
		);
		return ($session,$error)
		}

sub print_help {
	print_revision($PROGNAME,$REVISION);
	print "\n";
	print_usage();
	print "\n";
	print "   Check BlueCoat Proxy Diskstatus SNMP MIB\n";
	print "-H (--hostname)     Host to monitor\n";
	print "-C (--community)    SNMP Community (default=",DEFAULT_COMMUNITY,")\n";
	print "-p (--port)         SNMP Port (default=",DEFAULT_PORT,")\n";
	print "-t (--timeout)      Timeout in seconds (default=",DEFAULT_TIMEOUT, ")\n";
	print "-r (--retries)      Retries (default=",DEFAULT_RETRIES,")\n";
	print "-w (--warning)      Warning Threshold (default=",DEFAULT_WARNING,")\n";
	print "-c (--critical)     Critical Threshold (default=",DEFAULT_CRITICAL,")\n";
	print "-v (--verbose)      Verbose Output\n";
	print "-h (--help)         Help\n";
	print "-V (--version)      Programm version\n";
	print "-L (--license)      Print license information\n";
	print "\n";
	}

sub print_revision {
	my ($l_prog,$l_revision)=@_;
	print <<EOD
	$l_prog $l_revision
	This program comes with ABSOLUTELY NO WARRANTY; 
	for details type "$l_prog -L".
EOD
	}

##==============main=============##

# checking commandline arguments
	my $arg_status = check_args();
	if (!$arg_status){
		print "ERROR: some arguments wrong\n";
		print_usage();
		exit 2;
		}
	if ($opt_version) {
		print_revision($PROGNAME,$REVISION);
		exit 0;
		}
	if ($opt_license) {
		print_gpl();
		exit 0;
		}
	if ($opt_help) {
		print_help();
		exit 0;
		}
	if ( ! defined($opt_hostname)){
		print "\nERROR: Hostname not defined\n\n";
		print_usage();
		exit 2;
		}
	unless (defined $opt_timeout) {
		$opt_timeout = DEFAULT_TIMEOUT;
		}
	unless (defined $opt_retries) {
		$opt_retries = DEFAULT_RETRIES;
		}
	unless (defined $opt_port) {
		$opt_port = DEFAULT_PORT;
		}
	unless (defined $opt_community) {
		$opt_community = DEFAULT_COMMUNITY;
		}
	unless (defined $opt_warning) {
		$opt_warning = DEFAULT_WARNING;
		}
	unless (defined $opt_critical) {
		$opt_critical =DEFAULT_CRITICAL;
		}
# set alarmhandler for timeout handling
	$SIG{'ALRM'} = sub {
		print ("ERROR: plugin timed out after $opt_timeout seconds \n");
		exit 2;
		};
	alarm($opt_timeout);



# let's see if the bluecoat wants to speak with us
	my $state=0;
	my ($session,$error)=open_snmp_session($opt_hostname);
	if ( ! defined ($session)) {
		print "ERROR1: Could not open connection: $error \n";
		exit 2;
		}

	if (!defined $session) {
		printf "ERROR2: %s.\n", $error;
		exit 1;
		}

	# open the connection
	# ask the bluecoat
	my $nagios_view="";
	my $nagios_view1="";
	my %status=(1=>"present",2=>"initializing",3=>"inserted",4=>"offline",5=>"removed",6=>"not-present",7=>"empty",8=>"bad",9=>"unknown");
	my @oids_sgos4=($OID_Hardware,$OID_Sysname);
	my $result = $session->get_request(-varbindlist => \@oids_sgos4,);
	my $result1 = $session->get_table(-baseoid => $mibthree_stat);
	my $result2 = $session->get_table(-baseoid => $mibthree_vendor);
	my $result3 = $session->get_table(-baseoid => $mibthree_type);
	my $result4 = $session->get_table(-baseoid => $mibthree_serial);
	my $bc_system = $result->{$OID_Sysname}.", ".$result->{$OID_Hardware};
	my ($min_disk,$real_disk,$max_disk)=0;
	
	$nagios_view=$bc_system;
	foreach (oid_lex_sort(keys(%{$result1}))) {
		my $disk_id=substr($_,32,2); 
		$nagios_view1=$nagios_view1."\nDisk $disk_id Status: $status{$result1->{$_}}";
		if ( $result1->{$_} eq 1) {
			$real_disk++;
			$nagios_view=$nagios_view.", Disk$disk_id:$status{$result1->{$_}}";
			$state[$disk_id-1]=0;
			if($disk_id == 1) {$min_disk=$disk_id};
			foreach (oid_lex_sort(keys(%{$result2}))) {
				if ($disk_id eq substr($_,32,2)){
					$nagios_view1=$nagios_view1.", Vendor:$result2->{$_},";
					foreach (oid_lex_sort(keys(%{$result3}))) {
					if ($disk_id eq substr($_,32,2)){
						$result3->{$_} =~ s/\s+$//;
						$nagios_view1=$nagios_view1." Model:$result3->{$_},";
						foreach (oid_lex_sort(keys(%{$result4}))) {
							if ($disk_id eq substr($_,32,2)){
									$nagios_view1=$nagios_view1." Serial:$result4->{$_}";
									}
								}
							}
						}
					}
				}
			} else {
				if ( $result1->{$_} eq 7 || $result1->{$_} eq 6 ) {
					# 6 is "not-present" in SGOS 4.x
					# 7 is "empty" in SGOS 5.x
					$state[$disk_id-1]=0;
					}
				elsif ( $result1->{$_} eq 2 || $result1->{$_} eq 3 || $result1->{$_} eq 4 || $result1->{$_} eq 5 || $result1->{$_} eq 9 ) {
					$real_disk++;
					$state[$disk_id-1]=1;
					$nagios_view=$nagios_view.", Disk$disk_id:$status{$result1->{$_}}";
					}
				elsif ( $result1->{$_} eq 8 ) {
					$real_disk++;
					$state[$disk_id-1]=2;
					$nagios_view=$nagios_view.", Disk$disk_id:$status{$result1->{$_}}";
					}
				else { $state[$disk_id-1]=1;}
				}
		$max_disk=$disk_id;
		}

	$nagios_view=$nagios_view."|Disk=$real_disk;$opt_warning;$opt_critical;$min_disk;$max_disk";

	$session->close();

	
	########### Exitstate ##########################
	my %exitstates = (0 => "OK", 1 => "Warning", 2 => "Critical", 3 => "Unknown");
	my $diskstate=0;
	foreach $diskstate (@state){
		if ($state < $diskstate){$state=$diskstate;}
		}
	if ($real_disk < $opt_warning) { $state = 1;}
	if ($real_disk < $opt_critical) { $state = 2;}

	print "Disk $exitstates{$state} - $nagios_view\n";
	if ($opt_verbose) {
		print "\nList View\n=================\n\n$bc_system\n$nagios_view1\n";	
		}
	exit $state;


