#!/usr/bin/perl -w
#
# Nagios host script to get the status of a process from 2K snmp
#
# Requires Net::SNMP on Nagios host 
#
# Changes and Modifications
# =========================
# 20-Apr-2012 - tibo P. added Graph construction via perfdata.
# 29-Nov-2003 - Gilles Poiret rewrite
#		- using of utils.pm Nagios module 
#	 	- using Getopt module, for better options input
#		- modification of state/output in snmp error case	
#		- new parameter : community name
# 20-May-2003 - Xavier Dusart Created (http://xavier.dusart.free.fr/nagios/plugins/index.html). Thanks to him.
# 

use POSIX;
use strict;
use Getopt::Long;
use Net::SNMP qw(:snmp);

use lib "/usr/local/nagios/libexec";
use vars qw($opt_V $opt_h $opt_H $verbose $community $drive $opt_w $opt_c);
use vars qw($PROGNAME $answer $state $default_community $default_warn $default_crit);
use utils qw(%ERRORS &print_revision &support &usage);

$answer="No defined answer";
$state="UNKNOWN";
$PROGNAME="check_disk_hpux.pl";
$default_community="public";
$default_warn = 15;
$default_crit = 10;

$Getopt::Long::autoabbrev = 0;
$Getopt::Long::ignorecase = 0;
&Getopt::Long::GetOptions ("v"   => \$verbose, "verbose"    => \$verbose,
	    "V"   => \$opt_V, "version"    => \$opt_V,
	    "help"       => \$opt_h,
	    "H=s" => \$opt_H, "hostname=s" => \$opt_H,
	    "C=s" => \$community, "community=s" => \$community,
	    "d=s" => \$drive, "drive=s" => \$drive,
	   "w=s" => \$opt_w, "warning=s" => \$opt_w,
	   "c=s" => \$opt_c, "critical=s" => \$opt_c,

);


sub print_usage{
	my $error_msg = shift;
	
	print "ERROR : $error_msg\n" if ($error_msg);
	print "Usage : \n";
	print "\t$PROGNAME -H <hostname> -d <drive letter> [-C <SNMP community>] [-w <warning threshold, in %>] [-c <critical threshold, in %>] \n";
	print "\t$PROGNAME --help\n";
	print "\t$PROGNAME --version\n";
	exit($ERRORS{'OK'}) if ($error_msg);	
}

sub print_help{
        print_revision($PROGNAME,'$Revision: 1.0b $');
        print "\n";
        print_usage();
        print "\n";
 	print "Perl Check disk HP-UX plugin for Nagios\n";

        print "\t-H (--hostname) = HP-UX box hostname (or IP address)\n";
        print "\t-d (--drive)    = HP-UX box mount point (ex : /var)\n";

        print "\t-w (--warning)  = percent of disk usage warning threshold  (defaults:$default_warn)\n";
        print "\t-c (--critical) = percent of disk usage critical threshold  (defaults:$default_crit)\n";
        print "\t--help          = this screen\n";


        print "\t-V (--version)  = plugin version\n";
        print "\t-v (--verbose)  = debugging output\n";
        print "\n\n";
        support();
}


if ($opt_V) {
        print_revision($PROGNAME,'$Revision: 1.0b $'); #'
        exit $ERRORS{'OK'};
}

if ($opt_h) {print_help(); exit $ERRORS{'OK'};}



#Options checking

($opt_H) || ($opt_H = shift) || print_usage("Host name not specified\n");
my $hostname=$opt_H;
($community) || ($community = $default_community);

($drive) || ($drive = shift) || print_usage("Drive name not specified\n");
($opt_H) || ($opt_H = shift) || print_usage("Host name not specified\n");

($opt_w) || ($opt_w = $default_warn);
my $warn=$opt_w;

($opt_c) || ($opt_c = $default_crit);
my $crit=$opt_c;



if ($verbose) {
	print "critical : $opt_c\n";
	print "warning : $opt_w\n";
}

my %snmpOIDs = ("driveLetter"        => ".1.3.6.1.4.1.11.2.3.1.2.2.1.10",
		"allocationUnitSize" => ".1.3.6.1.4.1.11.2.3.1.2.2.1.7",
		"driveSize"          => ".1.3.6.1.4.1.11.2.3.1.2.2.1.4",
		"driveFreeSpace"     => ".1.3.6.1.4.1.11.2.3.1.2.2.1.5"
	       );
	

sub EXIT(){
  print $answer;
  exit $ERRORS{$state};
}


my ($session, $error) = Net::SNMP->session(
					-hostname  => $hostname,
					-community => $community,
					-version => "snmpv2c",
					-timeout => 10
                           );
			   




if (!defined($session)) {
  $state="UNKNOWN";
  $answer=$state." : ".$error;

  EXIT();
}







# Search for requested process name
my $index = 0;
my $result = 0;
$result = $session->get_table($snmpOIDs{driveLetter});

if (!defined($result)) {
  $state="UNKNOWN";
  $answer="SNMP ERROR: Unable to get SNMP answer for related OID";
  $session->close();
  EXIT();
}



foreach (keys %$result) {
   if ($result->{$_} =~ /^$drive$/i)
    {
	s/$snmpOIDs{driveLetter}(\.[0-9]+)/$1/;
	$index = $_;
	last;
    }
}

if (!$index)
{
    $answer="Drive $drive not found\n";
    $state="UNKNOWN";
    $session->close;
    
    EXIT();
}


# Search for drive index size & free space
my ($unit_size, $drive_size, $drive_free);

# Start with allocation unit size
$result = $session->get_request($snmpOIDs{allocationUnitSize}.$index);
if (!defined($result)) {
  $state="UNKNOWN";
  $answer="SNMP ERROR:".$session->error();
  $session->close();
  EXIT();
}
$unit_size = $result->{$snmpOIDs{allocationUnitSize}.$index};



# Then drive size
$result = $session->get_request($snmpOIDs{driveSize}.$index);
if (!defined($result)) {
  $state="UNKNOWN";
  $answer="SNMP ERROR:".$session->error();
  $session->close();
  EXIT();
}

$drive_size = $unit_size * $result->{$snmpOIDs{driveSize}.$index};
if ($drive_size == 0){
  $state="UNKNOWN";
  $answer="Warning : drive $drive size is zero.\n";
  $session->close;
  EXIT();
}

# At last drive free space
$result = $session->get_request($snmpOIDs{driveFreeSpace}.$index);
if (!defined($result)) {
  $state="UNKNOWN";
  $answer="SNMP ERROR:".$session->error();
  $session->close();
  EXIT();
}

$drive_free = $unit_size * $result->{$snmpOIDs{driveFreeSpace}.$index};

$session->close;

my $percent_free =  ($drive_free / $drive_size) * 100;
my $drive_used = ($drive_size - $drive_free);

if ($percent_free < $crit) {
     $state = "CRITICAL";
} elsif ($percent_free < $warn) {
    $state = "WARNING";
} else {
    $state="OK";
}

$answer= $state.sprintf(" - %.2d%% free (%s) [ %d Mo / %d Mo used ]|size=$drive_size, used=$drive_used\n", $percent_free, byte_print($drive_free),megaByte_print($drive_size - $drive_free),megaByte_print($drive_size),megaByte_print($drive_size - $drive_free));
EXIT();


sub megaByte_print {
    my $octets = shift;

    return $octets /=1048576;
}



sub byte_print {
    my $octets = shift;
    my $index = 0;
    my @unit = ("o", "Ko", "Mo", "Go", "To", "Po", "Eo", "Zo");
    my $result;

    while ($octets > 1024)
    {
	$octets /= 1024;
	$index++;
	last if $index == scalar(@unit)- 1;
    }
    $result = sprintf "%.2f %s", $octets, $unit[$index];
    return $result;
}


