#!/usr/bin/perl -wT
#
# Copyright (c) 2000 Hugo Gayosso
#
# Description:
#    Nagios plug-in that monitors the resources on an HP-UX machine
#    by querying the SNMP daemon
#
# License: General Public License (GPL)
#          http://www.gnu.org/copyleft/gpl.txt
#
# ChangeLog
#

require 5.004;
use strict;
use lib utils.pm ;
use Plugin;
use Plugin::Parameter qw($helpparameterlist $versionparameterlist $hostnameparameter $communityparameter
			 $warningparameter $criticalparameter $timeoutparameter $portparameter
			 $verboseparameter);

use Net::SNMP;

use vars qw($chk_fs $show_fs $chk_fsid $chk_cpu $fsid1_opt $fs_opt $opt_H $opt_C $opt_p
	    $opt_w $opt_c $PROGNAME);

use utils qw(%ERRORS &usage);

$warningparameter->description("Warning threshold dependent on test type");
$criticalparameter->description("Critical threshold dependent on test type");
$portparameter->default("snmp");
my $checkfilesystemparameter = new Plugin::Parameter(-name => "checkfilesystem", -flags => [ 'check-filesystem' ],
						     -optional => "yes", -valueoptional => "yes", -type => "NONE",
						     -binding => \$chk_fs,
						     -description => "Check filesystems on remote host");
my $showfilesystemsparameter = new  Plugin::Parameter(-name => "showfilesystems", -flags => [ 'show-filesystems' ],
						      -optional => "yes", -valueoptional => "yes", -type => "NONE",
						      -binding => \$show_fs,
						      -description => "Show filesystems on remote host");
my $checkfilesystemidparameter = new  Plugin::Parameter(-name => "checkfilesystemID", -flags => [ 'check-filesystemID' ],
							-optional => "yes", -valueoptional => "yes", -type => "NONE",
							-binding => \$chk_fsid,
							-description => "Check filesystems by ID on remote host");
my $checkcpuparameter = new  Plugin::Parameter(-name => "checkcpu", -flags => [ 'check-cpu' ],
					       -optional => "yes", -valueoptional => "yes", -type => "NONE",
					       -binding => \$chk_cpu,
					       -description => "Check 5-minute CPU load on remote host");
my $filesystemIDparameter = new  Plugin::Parameter(-name => "filesystemID", -flags => [ 'filesystemID1' ],
						   -optional => "yes", -valueoptional => "no", -type => "INTEGER",
						   -checker => \&Plugin::Parameter::_check_integer,
						   -binding => \$fsid1_opt,
						   -description => "Identifier for the remote file system");
my $filesystemparameter = new  Plugin::Parameter(-name => "filesystem", -flags => [ 'filesystem' ],
						 -optional => "yes", -valueoptional => "no", -type => "FILENAME",
						 -checker => \&Plugin::Parameter::_check_file,
						 -binding => \$fs_opt,
						 -description => "Path to the remote file system");

my $plugin = new Plugin(-revision => '$Revision: 1.1',
			-copyright => "2000 Hugo Gayosso, 2004 Howard Wilkinson <howard\@cohtech.com>",
			-shortcomment => "Perform various SNMP checks on an HP-UX machine",
			-longcomment => "",
			-checker => sub { my ($plugin) = @_;
					  unless ($chk_fs || $show_fs || $chk_fsid || $chk_cpu) {
					    $plugin->usage();
					    usage("$PROGNAME UNKNOWN: Must specify which test to run\n");
					  }
					  my $tests = ($chk_fs)?1:0 + ($show_fs)?1:0 + ($chk_fsid)?1:0 + ($chk_cpu)?1:0;
					  if($tests != 1) {
					    $plugin->usage();
					    usage("$PROGNAME UNKNOWN: Cannot specify more than one test at a time\n");
					  }
					  if ($chk_fs && $fsid1_opt) {
					    $plugin->usage();
					    usage("$PROGNAME UNKNOWN: Cannot specify Filesystem ID with a filesystem check\n");
					  }
					  if ($chk_fsid && $fs_opt) {
					    $plugin->usage();
					    usage("$PROGNAME UNKNOWN: Cannot specify a Filesystem with a filesystemID checker\n");
					  }
					  if (($show_fs || $chk_cpu) && ($chk_fs || $chk_fsid)) {
					    $plugin->usage();
					    usage("$PROGNAME UNKNOWN: Too many options\n");
					  }
					  if ($chk_fs && !$fs_opt) {
					    $plugin->usage();
					    usage("$PROGNAME UNKNOWN: Must specify filesystem to check for check-filesystem operation\n");
					  }
					  if ($chk_fsid && !$fsid1_opt) {
					    $plugin->usage();
					    usage("$PROGNAME UNKNOWN: Must specify filesystemID to check for check-filesystemID operation\n");
					  }
					},
			-parameterlists => [ [ $hostnameparameter,
					       $communityparameter,
					       $checkfilesystemparameter,
					       $showfilesystemsparameter,
					       $checkfilesystemidparameter,
					       $checkcpuparameter,
					       $filesystemIDparameter,
					       $filesystemparameter,
					       $warningparameter,
					       $criticalparameter,
					       $timeoutparameter,
					       $verboseparameter ],
					     $helpparameterlist,
					     $versionparameterlist ]);
# Variable initialization
$ENV{'PATH'}="";
$ENV{'ENV'}="";
$ENV{'BASH_ENV'}="";

$plugin->init();

my $snmpwalk = (-e "/usr/bin/snmpwalk")?"/usr/bin/snmpwalk"
  :(-e "/usr/local/bin/snmpwalk")?"/usr/local/snmpwalk"
  :"snmpwalk";

# HP-UX SNMP OIDs
my $target_host         = $opt_H;
my $target_community    = $opt_C;
my $warning_opt         = $opt_w;
my $critical_opt        = $opt_c;
my $filesystemID1_OID   = ".1.3.6.1.4.1.11.2.3.1.2.2.1.1";
my $mounted_OID         = ".1.3.6.1.4.1.11.2.3.1.2.2.1.3";
my $totalspace_OID      = ".1.3.6.1.4.1.11.2.3.1.2.2.1.4";
my $freespace_OID       = ".1.3.6.1.4.1.11.2.3.1.2.2.1.6";
my $path_OID            = ".1.3.6.1.4.1.11.2.3.1.2.2.1.10";
my $cpu_5min_OID        = ".1.3.6.1.4.1.11.2.3.1.1.4";
my %mounted = ();
my %totalspace = ();
my %freespace = ();
my %filesystempath = ();

if ($chk_fs) {
  walk_data($snmpwalk, $target_host, $target_community, $mounted_OID );
  walk_data($snmpwalk, $target_host, $target_community, $totalspace_OID );
  walk_data($snmpwalk, $target_host, $target_community, $freespace_OID );
  check_filesystem($fs_opt, $warning_opt, $critical_opt);
} elsif ($show_fs) {
  walk_data($snmpwalk, $target_host, $target_community, $filesystemID1_OID);
  walk_data($snmpwalk, $target_host, $target_community, $mounted_OID );
  walk_data($snmpwalk, $target_host, $target_community, $path_OID);
  show_filesystem();
} elsif ($chk_fsid){
  my $totalspace_fsID_OID = "$totalspace_OID.$fsid1_opt";
  my $freespace_fsID_OID = "$freespace_OID.$fsid1_opt";
  walk_data($snmpwalk, $target_host, $target_community, $totalspace_fsID_OID);
  walk_data($snmpwalk, $target_host, $target_community, $freespace_fsID_OID);
  check_filesystemID1($fsid1_opt, $warning_opt, $critical_opt);
} elsif ($chk_cpu) {
  my $cpu = get_cpu_load($snmpwalk, $target_host, $target_community, $cpu_5min_OID);
  check_cpu_5min($cpu, $warning_opt, $critical_opt);
}

#------------ Can't get here ------------------------------------------
exit;

sub get_cpu_load {
  my ($snmpwalk, $target_host, $target_community, $OID) = @_;
  my $pid = open(SNMPWALK, "-|");
  die "cannot fork: $!" unless defined($pid);
  if ($pid) {   # parent
    my $cpu = -1;
    while (<SNMPWALK>) {
      my @snmpdata = split(/:/,$_);
      $cpu = $snmpdata[1]/100;
    }
    close(SNMPWALK) or warn "kid exited $?";
    return $cpu;
  } else {      # child
    exec($snmpwalk,$target_host,$target_community,$OID)  or die "can't exec program: $!";
  }
}

sub walk_data {
  #This function queries the SNMP daemon for the specific OID
  my ($snmpwalk, $target_host, $target_community, $OID) = @_;
  my $pid = open(SNMPWALK, "-|");
  die "cannot fork: $!" unless defined($pid);
  if ($pid) {   # parent
    while (<SNMPWALK>) {
      my $output = $_;
      sort_walk_data($output);
    }
    close(SNMPWALK) or warn "kid exited $?";
  } else {      # child
    exec($snmpwalk,$target_host,$target_community,$OID)  or die "can't exec program: $!";
  }
}

sub sort_walk_data {
  my ($snmp_data) = @_;
  my @fields = split(/\./,$snmp_data);
  my $item = $fields[8];
  my $filesystemID1 = $fields[9];
  my @fields2 = split(/=/,$fields[10]);
  my $value = $fields2[1];
  chomp($value);
  if ($value =~ /"/) {
    my @fields3 = split(/"/,$value);
    $value = $fields3[1];
  }
  if ($item == 3) {
    $mounted{$filesystemID1} = "$value";
  } elsif ($item == 4) {
    $totalspace{$filesystemID1} = "$value";
  } elsif ($item == 6) {
    $freespace{$filesystemID1} = "$value";
  } elsif ($item == 10) {
    $filesystempath{$filesystemID1} = "$value";
  }
}

sub show_filesystem {
  print "\n\nfilesystemID1\tmounted filesystem\tfilesystem path\n";
  foreach my $element (keys %mounted) {
    print "$element\t$mounted{$element}\t\t$filesystempath{$element}\n";
  }
  print "\n\n";
}

sub check_filesystem {

  # Warning  = percentage of used space >= $warning and < $critical
  # Critical = percentage of used space > $warning and >= $critical
  # OK       = percentage of used space < $warning and < $critical

  my ($mounted_filesystem, $warning, $critical) = @_;
  foreach my $element (keys %mounted) {
    if ($mounted{$element} eq $mounted_filesystem) {
      my $warning_result = $totalspace{$element}*(100-$warning)/100;
      my $critical_result = $totalspace{$element}*(100-$critical)/100;
      my $result_percent = $freespace{$element}*100/$totalspace{$element};
      if (($freespace{$element} <= $warning_result) && ($freespace{$element} > $critical_result)) {
	printf "Only %d M (%d%s) free\n",$freespace{$element}/1024,$result_percent,"%";
	exit 1;
      } elsif ($freespace{$element} <= $critical_result) {
	printf "Only %d M (%d%s) free\n",$freespace{$element}/1024,$result_percent,"%";
	exit 2;
      } else {
	printf "Disk ok - %d M (%d%s) free\n",$freespace{$element}/1024,$result_percent,"%";
	exit 0;
      }
    }
  }
  print "$mounted_filesystem doesn't exist in $target_host\n\n";
  exit -1;
}

sub check_filesystemID1{
  # Warning  = percentage of used space >= $warning and < $critical
  # Critical = percentage of used space > $warning and >= $critical
  # OK       = percentage of used space < $warning and < $critical

  my ($fsid1, $warning, $critical) = @_;
  foreach my $element (keys %totalspace) {
    if ($element eq  $fsid1) {
      my $warning_result = $totalspace{$element}*(100-$warning)/100;
      my $critical_result = $totalspace{$element}*(100-$critical)/100;
      my $result_percent = $freespace{$element}*100/$totalspace{$element};
      if (($freespace{$element} <= $warning_result) && ($freespace{$element} >= $critical_result)) {
	printf "Only %d M (%d%s) free\n",$freespace{$element}/1024,$result_percent,"%";
	exit 1;
      } elsif ($freespace{$element} <= $critical_result) {
	printf "Only %d M (%d%s) free\n",$freespace{$element}/1024,$result_percent,"%";
	exit 2;
      } else {
	printf "Disk ok - %d M (%d%s) free\n",$freespace{$element}/1024,$result_percent,"%";
	exit 0;
      }
    }
  }
  print "$fsid1 doesn't exist in $target_host\n\n";
  exit -1;
}

sub check_cpu_5min {
  my ($cpu, $warn, $crit) = @_;
  if ($cpu >= $crit) {
    print "Critical- 5-min load: $cpu\n";
    exit 2;
  } elsif ($cpu >= $warn) {
    print "Warning - 5-min load: $cpu\n";
    exit 1;
  } else {
    print "Load ok - 5-min load: $cpu\n";
    exit 0;
  }
}



