#!/usr/bin/perl
# 
# This perl script uses the _admin volume to query nss directory information
#
# Modify:
#  
# 2010.01.27 - added output: quota 
#

use POSIX;
use Getopt::Long;
use XML::Parser;
use XML::DOM;
use strict;
use Switch;

use vars qw($sversion $help $debug $directory $xmlcommand $xmlreply $error $size);
use vars qw($status $result $exitcode $warn $crit $freedata);
use vars qw($div $warnval $critval $ent $entq);

sub print_usage ();

my $version = "0.12";
my $parserdir = XML::DOM::Parser->new();
my $nssmgmtfile = "+</_admin/Manage_NSS/files.cmd";


Getopt::Long::Configure('bundling');
GetOptions
  ("v"     => \$sversion, "sversion"     => \$sversion,
   "w=s"   => \$warn,     "warn=s"       => \$warn,
   "c=s"   => \$crit,     "crit=s"       => \$crit,
   "h"     => \$help,     "help"         => \$help,
   "d"     => \$debug,    "debug"        => \$debug,
   "D=s"   => \$directory,"directory=s"  => \$directory);

# print the program version
if ($sversion) {
  print "Program version: " . $version . "\n\n";
  exit 3;
}

# print the help screen
if ($help) {
  print_usage;
  exit 3;
}

# check if the volume name is provided
if (!$directory) {
  print "ERROR: missing directory name \n\n";
  print_usage;
  exit 3;
}

sub print_usage () {
  print "

Usage: check_oesnss_quota.pl -D <NSS Directory> -w <Warning Level> -c <Critical Level> [-d] [-h] [-v]

Paramters:
    -c		critical level for the free space in [k|M|G|%]
		if no extension is given I assume it is in GB
    -d		print debug info
    -h		print help
    -v		version
    -D		define the NSS directory you want to monitor
		thin value fully quality path!
    -w		warning level for the free space in [k|M|G|%]
		if no extension is given I assume it is in GB

Samples:
# check_oesnss_quota.pl -D DATA:datadir -w 10GB -c 2GB
OK: DATA:datadir free: 4GB of 38GB|DATA:datadir=4691116032;36268883968

# check_oesnss_quota.pl -D DATA:datadir -w 10% -c 5%
WARNING: DATA:datadir free: 7% of 38GB|DATA:datadir=4691116032;36268883968


facy - faczanlaszlo at gmail.com, 27.01.2010 \n\n";
}

sub query_nss_admin () {
  local($xmlcommand) = @_;

  if ($debug) {
    print "NSS management file: " . $nssmgmtfile . "\n\n";
    print "NSS XML request:     " . $xmlcommand . "\n\n";
  }

  # open the nss management file
  open(NSSMGMT, $nssmgmtfile) or die "Error opening NSS management file ($!) on server";

  if (!syswrite(NSSMGMT, $xmlcommand, length($xmlcommand))) 
  {
    seek NSSMGMT, 0, 0;	               # set to the beginning of the file.
    sysread (NSSMGMT, $error, 10000);  # check the error message.
    print "Error writing initialization to management file. \n";
    print "$error  \n\n";	       # print the error message to the screen.
    close (NSSMGMT);
  }
  else
  {
    seek NSSMGMT, 0, 0;	  # Make sure to start at the beginning of the file.
    sysread (NSSMGMT, $xmlreply, 10000);  #Read the reply.
    close (NSSMGMT);
    if ($debug) {
      print "NSS XML response:    " . $xmlreply . "\n\n";
    }
    return $xmlreply;
  }
}

#######################################
# START WITH NSS DIRECTORY INFORMATION
#######################################

if ($debug) {
  print "NSS Directory:          " . $directory . "\n\n";
}

# generate the xml query
my $dircommand = "<virtualIO><datastream name=\"command\"/></virtualIO>".
                 "<fileRequest><fileInfo><getFileInfo><fileName>".$directory.
                 "</fileName><typeOfInfo><directoryQuotaInfo><quotaAmount/>".
		 "<usedAmount/></directoryQuotaInfo></typeOfInfo></getFileInfo></fileInfo></fileRequest>";

my $dirxml = &query_nss_admin($dircommand);
my $doc      = $parserdir->parse($dirxml);
my $result   = $doc->getElementsByTagName('result')->item(0)->getAttribute('value');

# check the result of the xml response to see if we got the directory info
if ($result ne "0") {
  print "ERROR: problems getting directory information. Is the directory name correct ? \n";
  exit 3;
}

# extract the different values
my $fileinfo = $doc->getElementsByTagName('quotaInfo')->item(0);
my $quota    = $fileinfo->getElementsByTagName("quotaAmount")->item(0)->getFirstChild->getData;
my $amount   = $fileinfo->getElementsByTagName("usedAmount")->item(0)->getFirstChild->getData;

if($quota==-1) {
    $status="OK";
    print "UNKNOWN: nothing set quota this directory:" . $directory . "\n";
    exit 0;
}



my $free = $quota - $amount;

# recalculate warning and critical value depending on the value type
# warning
if (substr($warn,-1,1) eq "k") {
  $warnval=substr($warn,0,length($warn)-1)*1024; $ent="kB";
} elsif (substr($warn,-1,1) eq "M") {
  $warnval=substr($warn,0,length($warn)-1)*1047552; $ent="MB";
} elsif (substr($warn,-1,1) eq "G") {
  $warnval=substr($warn,0,length($warn)-1)*1073741824; $ent="GB";
} elsif (substr($warn,-1,1) eq "%") {
  $warnval=$quota*substr($warn,0,length($warn)-1)/100; $ent="%";
} else {
  # default value is in GB
  $warnval=$warn*1073741824; $ent="GB";
}
# critical
if (substr($crit,-1,1) eq "k") {
  $critval=substr($crit,0,length($crit)-1)*1024;
} elsif (substr($crit,-1,1) eq "M") {
  $critval=substr($crit,0,length($crit)-1)*1047552;
} elsif (substr($crit,-1,1) eq "G") {
  $critval=substr($crit,0,length($crit)-1)*1073741824;
} elsif (substr($crit,-1,1) eq "%") {
  $critval=$quota*substr($crit,0,length($crit)-1)/100;
} else {
  # default value is in GB
  $critval=$crit*1073741824;
}

if ($debug) {
  print "warning level:  " . $warnval . " byte\n";
  print "critical level: " . $critval . " byte\n\n";
}

# check the warning and critical levels
if (!$warnval || !$critval || $warnval<$critval) {
  print "ERROR: incorrect warning and critial levels defined \n\n";
  print_usage;
  exit 3;
}


# critical and warning levels are defined in MB, therefor multiply it with 
# 1047552 to compare it against the current used space
if (abs($free)<=($critval)) {
  $status="CRITICAL";
  $exitcode=2;
} elsif (abs($free)<=($warnval)) {
  $status="WARNING";
  $exitcode=1;
} else {
  $status="OK";
  $exitcode=0;
}

switch ($ent) {
    case "kB"	{ $freedata=$free / 1024;     $quota=$quota / 1024; $entq="kb"; }
    case "MB"	{ $freedata=$free / 1047552;  $quota=$quota / 1047552; $entq="MB"; }
    case "GB"	{ $freedata=$free / 1073741824; $quota=$quota / 1073741824; $entq="GB"; }
    case "%"	{ $freedata=($free/$quota)*100; $quota=$quota / 1073741824; $entq="GB"; }
    }

printf ("%s %.0f%s of %.0f%s",$status . " - " . $directory . " free: " , $freedata , $ent, $quota, $entq .  "\n|" . $directory . "=" . $free . ";" . $amount);
exit $exitcode;
