#! /usr/bin/perl -w
################################################################################
#####################################################################################
#
# Script init
#

use strict;
use Net::SNMP qw(:snmp);
use FindBin;
use lib "$FindBin::Bin";
use lib "/usr/local/nagios/libexec";
use utils qw($TIMEOUT %ERRORS &print_revision &support);

if (eval "require centreon" ) {
    use centreon qw(get_parameters);
    use vars qw(%centreon);
    %centreon = get_parameters();
} else {
	print "Unable to load centreon perl module\n";
    exit $ERRORS{'UNKNOWN'};
}
use vars qw($PROGNAME);
use Getopt::Long;
use vars qw($opt_V $opt_t $opt_P $opt_h $opt_v $opt_f $opt_C $opt_d $opt_k $opt_u $opt_p $opt_n $opt_w $opt_c $opt_H $opt_s $opt_L $opt_M @test);

# Plugin var init

my ($hrStorageAllocationUnits, $hrStorageSize, $hrStorageUsed, $hrStorageLabel);
my ($AllocationUnits, $Size, $Used);
my ($tot, $used, $pourcent, $return_code);

$PROGNAME = "$0";
sub print_help ();
sub print_usage ();

Getopt::Long::Configure('bundling');
GetOptions
    ("h"   => \$opt_h, "help"         => \$opt_h,
     "u=s" => \$opt_u, "username=s"   => \$opt_u,
     "p=s" => \$opt_p, "password=s"   => \$opt_p,
     "k=s" => \$opt_k, "key=s"        => \$opt_k,
     "P=s" => \$opt_P, "snmp-port=s"  => \$opt_P,
     "V"   => \$opt_V, "version"      => \$opt_V,
     "s"   => \$opt_s, "show"         => \$opt_s,
     "v=s" => \$opt_v, "snmp=s"       => \$opt_v,
     "C=s" => \$opt_C, "community=s"  => \$opt_C,
     "d=s" => \$opt_d, "disk=s"       => \$opt_d,
     "n"   => \$opt_n, "name"         => \$opt_n,
     "w=s" => \$opt_w, "warning=s"    => \$opt_w,
     "c=s" => \$opt_c, "critical=s"   => \$opt_c,
     "H=s" => \$opt_H, "hostname=s"   => \$opt_H,
     "L"   => \$opt_L, "label"        => \$opt_L,
     "M"   => \$opt_M, 
     "t=s" => \$opt_t);


if ($opt_V) {
    print_revision($PROGNAME,'$Revision: 1.3 $');
    exit $ERRORS{'OK'};
}
if (!defined($opt_P)) {
	$opt_P = 161;
}
if ($opt_h) {
	print_help();
	exit $ERRORS{'OK'};
}
if (!$opt_H) {
	print_usage();
	exit $ERRORS{'OK'};
}

if ($opt_n && !$opt_d) {
    print "Option -n (--name) need option -d (--disk)\n";
    exit $ERRORS{'UNKNOWN'};
}
my $snmp = "2";
$snmp = $opt_v if ($opt_v && $opt_v =~ /^[0-9]$/);

if ($snmp eq "3") {
	if (!$opt_u) {
		print "Option -u (--username) is required for snmpV3\n";
		exit $ERRORS{'OK'};
	}
	if (!$opt_p && !$opt_k) {
		print "Option -k (--key) or -p (--password) is required for snmpV3\n";
		exit $ERRORS{'OK'};
	} elsif ($opt_p && $opt_k) {
		print "Only option -k (--key) or -p (--password) is needed for snmpV3\n";
		exit $ERRORS{'OK'};
	}
}

$opt_C = "public" if (!$opt_C);
$opt_d = 2 if (!$opt_d);

($opt_d) || ($opt_d = shift) || ($opt_d = 2);

my $partition = 0;
if ($opt_d =~ /([0-9]+)/ && !$opt_n){
    $partition = $1;
} elsif (!$opt_n){
    print "Unknown -d number expected... or it doesn't exist, try another disk - number\n";
    exit $ERRORS{'UNKNOWN'};
}
if (!$opt_c) {
	$opt_c = 97;
}
if (!$opt_w) {
	$opt_w = 95;
}

# this are boolean variables to see if --warn or --crit were set in MB/GB
# --warn and --crit values will be stored in $warning and $critical variables
# if they are set in GB they are converted to MB 
my $criticalMB = 0;
my $warningMB = 0;

my $critical = 95;
if ($opt_c && $opt_c =~ /^[0-9]+$/) {
    $critical = $opt_c;
}
if ($opt_c && $opt_c =~ /^([0-9]+)(.)[Bb]$/) {
    $criticalMB = 1;
    $critical = $1;
    ($critical = $critical * 1024) if $2 =~ /[Gg]/ ;
}

my $warning = 90;
if ($opt_w && $opt_w =~ /^[0-9]+$/) {
    $warning = $opt_w;
}
if ($opt_w && $opt_w =~ /^([0-9]+)(.)[Bb]$/) {
    $warningMB = 1;
    $warning = $1;
    ($warning = $warning * 1024) if $2 =~ /[Gg]/ ;
}

# If one of the warning/critical thresholds is set in MB/GB and the other in percent the check will fail
# if both are percent or storage size the check will be performed in different ways
# percent applies to used space so --crit must be higher than --warn
# MB applies to free space so --crit must be lower than --warn
if ($criticalMB == $warningMB) {
    if ($criticalMB && ($critical >= $warning)) {
	print "(--crit) must be inferior to (--warn) when using absolute size";
	print_usage();
	exit $ERRORS{'OK'};
    } 
    if (!$criticalMB && ($critical <= $warning)) {
	print "(--crit) must be superior to (--warn)";
	print_usage();
	exit $ERRORS{'OK'};
    }
} else {
	print "(--crit) and (--warn) must both use either percent or absolute sizes";
	print_usage();
	exit $ERRORS{'OK'};
}


my $name = $0;
$name =~ s/\.pl.*//g;

# Plugin snmp requests

my $OID_hrStorageUsed = ".1.3.6.1.4.1.12124.1.3.2.0";
my $OID_hrStorageSize = ".1.3.6.1.4.1.12124.1.3.3.0";

# create a SNMP session
my ($session, $error);
if ($snmp eq "1" || $snmp eq "2") {
	($session, $error) = Net::SNMP->session(-hostname => $opt_H, -community => $opt_C, -version => $snmp, -port => $opt_P, -timeout => 45);
	if (!defined($session)) {
	    print("UNKNOWN: SNMP Session : $error\n");
	    exit $ERRORS{'UNKNOWN'};
	}
} elsif ($opt_k) {
    ($session, $error) = Net::SNMP->session(-hostname => $opt_H, -version => $snmp, -username => $opt_u, -authkey => $opt_k, -port => $opt_P, -timeout => 45);
	if (!defined($session)) {
	    print("UNKNOWN: SNMP Session : $error\n");
	    exit $ERRORS{'UNKNOWN'};
	}
} elsif ($opt_p) {
    ($session, $error) = Net::SNMP->session(-hostname => $opt_H, -version => $snmp,  -username => $opt_u, -authpassword => $opt_p, -port => $opt_P, -timeout => 45);
	if (!defined($session)) {
	    print("UNKNOWN: SNMP Session : $error\n");
	    exit $ERRORS{'UNKNOWN'};
	}
}
$session->translate(Net::SNMP->TRANSLATE_NONE) if (defined($session));

my $result = $session->get_request(
                                   -varbindlist => [$OID_hrStorageSize,
                                                    $OID_hrStorageUsed
                                                    ]
                                   );
if (!defined($result)) {
    printf("ERROR:  %s.\n", $session->error);
    if ($opt_n) { print(" - You must specify the disk name when option -n is used");}
    print ".\n";
    $session->close;
    exit $ERRORS{'UNKNOWN'};
}

$Size  =  $result->{$OID_hrStorageSize };
$Used  =  $result->{$OID_hrStorageUsed };

$hrStorageLabel = "/ifs";


# Plugins var treatmen

if (!$Size){
    print "Disk CRITICAL - no output (-p number expected... it doesn't exist, try another disk number)\n";
    exit $ERRORS{'CRITICAL'};
}

if (($Size =~  /([0-9]+)/)){
	
    if (!$Size){
        print "The number of the option -p is not a hard drive\n";
        exit $ERRORS{'CRITICAL'};
    }
    $tot = 1;
    $tot = $Size + $Used;
    if (!$tot){$tot = 1;}
    $used = $Used;
    $pourcent = ($used * 100.0) / ($tot * 1.0);

    #if (length($pourcent) > 2){
    #    @test = split (/\./, $pourcent);
    #    $pourcent = $test[0];
    #}
    my $totMB = $tot / 1048576;
    my $usedMB = $used / 1048576;
    my $freeMB = $totMB - $usedMB;
    my $totGB = $totMB / 1024;
    my $usedGB = $usedMB / 1024;
    my $freeGB = $freeMB / 1024;
    my $totTB = $totGB / 1024;
    my $usedTB = $usedGB / 1024;
    my $freeTB = $freeGB / 1024;
	
    # Plugin return code
    
    if ($criticalMB ? ($freeMB <= $critical) : ($pourcent >= $critical)) {
        print "Disk CRITICAL - ";
        $return_code = 2;
    } elsif ($warningMB ? ($freeMB <= $warning) : ($pourcent >= $warning)) {
        print "Disk WARNING - ";
        $return_code = 1;
    } else {
        print "Disk OK - ";
        $return_code = 0;
    }

	my $warn; my $crit;
        $warn = $warningMB ? $tot-$warning*1024*1024 : int($warning * $tot / 100);
        $crit = $criticalMB ? $tot-$critical*1024*1024 : int($critical * $tot / 100);
	if ($opt_M){
           printf($hrStorageLabel . " TOTAL: %dGB USED: %dGB (%.1f%%) FREE: %dGB (%.1f%%)", $totGB, $usedGB, $pourcent, $freeGB, 100-$pourcent );
	} else {
           printf($hrStorageLabel . " TOTAL: %.3fTB USED: %.3fTB (%.1f%%) FREE: %.3fTB (%.1f%%)", $totTB, $usedTB, $pourcent, $freeTB, 100-$pourcent );
	}
	if ($opt_L) {
		print " - ".$hrStorageLabel;
	}
        print "|used=".$used."B;".$warn.";".$crit.";0;".$tot." size=".$tot."B\n";
        exit $return_code;

} else {
    print "Disk CRITICAL - no output (-d number expected... it doesn't exist, try another disk number)\n";
    exit $ERRORS{'CRITICAL'};
}

sub print_usage () {
    print "\nUsage:\n";
    print "$PROGNAME\n";
    print "   -H (--hostname)   Hostname to query - (required)\n";
    print "   -C (--community)  SNMP read community (default: public)\n";
    print "                     used with SNMP v1 and v2c\n";
    print "   -v (--snmp_version)  1 for SNMP v1 (default)\n";
    print "                        2 for SNMP v2c\n";
    print "   -P (--snmp-port)	SNMP port (default: 161)\n";
    print "   -k (--key)        snmp V3 key\n";
    print "   -p (--password)   snmp V3 password\n";
    print "   -u (--username)   snmp v3 username \n";
    print "   -d (--disk)       Set the disk (number expected) ex: 1, 2,... (default: 2 )\n";
    print "   -n (--name)       Allows to use disk name with option -d instead of disk oid index\n";
    print "                     (ex: -d \"C:\" -n, -d \"E:\" -n, -d \"Swap Memory\" -n, -d \"Real Memory\" -n\n";
    print "                     (choose an unique expression for each disk)\n";
    print "   -s (--show)       Lists all disks (debug mode)\n";
    print "   -w (--warn)       Minimum fill level at which a warning message will be generated\n";
    print "                     (default 80)\n";
    print "                     By using the optional suffixes MB/GB the argument is interpreted as absolute size \n";
    print "                     and it becomes a threshold for free space. (ex. 100MB; 3GB)\n";
    print "   -c (--crit)       Minimum fill level at which a critical message will be generated\n";
    print "                     (default 95)\n";
    print "                     By using the optional suffixes MB/GB the argument is interpreted as absolute size \n";
    print "                     and it becomes a threshold for free space. (ex. 50MB; 1GB)\n";
    print "                     ex.: -w 1GB -c 256MB generates a warning when free space reaches 1GB\n";
    print "                          and critical when there are less than 256MB left\n";
    print "   -V (--version)    Plugin version\n";
    print "   -L                add Windows drive label to output\n";
    print "   -M                Shows the size in output in MB instead of GB\n";
    print "   -h (--help)       usage help\n";

}

sub print_help () {
    print "##############################################\n";
    print "#    Copyright (c) 2004-2007 Centreon        #\n";
    print "#    Bugs to http://forge.centreon.com/      #\n";
    print "##############################################\n";
    print_usage();
    print "\n";
}
