#!/usr/bin/perl
# By Cléber Campanel
# cleber.campanel@gmail.com
#

# imports
use File::Basename;
use strict;
use Nagios::Plugin;
use Switch;
use Data::Dumper qw(Dumper);

# variables
our $scriptName = basename($0, ".pl");

# plugin setup
my $np = Nagios::Plugin->new(
	plugin      => $scriptName,
	shortname	=> ' ',
	version		=> '1.0',
	usage       => 'Usage: %s -H host -U username -p password -T type -m mode -s name/id [-w <warning >] [-c <critical >]
	Example: check_emc_naviseccli.pl -H 10.10.10.10 -U username -p password -T disk -m errors -s 0_0 -w 10 -c 20',
	blurb       => 'This plugin checks EMC',
	license     => 'This nagios plugin is free software, and comes with ABSOLUTELY no WARRANTY!'
	);

# add all arguments
$np->add_arg(spec => 'warning|w=s',
	help => "Warning threshold",
	required => 0
);

$np->add_arg(spec => 'critical|c=s',
	help => "Critical threshold",
	required => 0
);
$np->add_arg(
	spec => 'host|H=s',
	help => qq{Specify the host on the command line.},
	required => 1
);

$np->add_arg(
	spec => 'user|U=s',
	help => qq{Specify the username on the command line.},
	required => 1
);

$np->add_arg(
	spec => 'password|P=s',
	help => qq{Specify the password on the command line.},
	required => 1
);

$np->add_arg(
	spec => 'type|T=s',
	help => qq{Specify the type of check. Valid types are:
	disk - check information about Disks
	dpe - check information about DPEs
	dae - check information about DAEs
	array - check information about entire array
	port - chek information about Ports
	powersupply - check information about Power Supplies
	llc - check information about LLCs
	raidgroup - check information about Raid Groups
	storagepool - check information about Storage Pools
	sp - check information about SPs
	lun - check information about Luns
	},
	required => 1
);

$np->add_arg(
	spec => 'mode|m=s',
	help => qq{Each type of check have specific modes of check. Valid modes for each type are:
	disk [errors]: check the amout of errors on disk.
	     [state]: check the general state of disk.	
	dpe [powerstatus]: check the DPE general power status
            [temperature]: check temperature of DPE
	array [health]: check general array health
	port [status]: check port status
	powersupply [state]: check Power Supply state
	llc [state]: check LLC state
	raidgroup [usage]: check usage of Raid Group
	storagepool [state]: check state of Storage Pool
	            [usage]: check usage of Storage Pool
	sp [busy]: check Busy time of SP
	   [state]: check state of SP
	lun [usage]: check LUN usage in GB. Thresholds is supported.
	    [state]: check if LUN state is Ready		
	},
	required => 0
);

$np->add_arg(
	spec => 'subtype|s=s',
	help => qq{Specify subtype. Subtype is the name/id of the element that check will use},
	required => 0
);

$np->getopts;
#print Dumper $np;

my $cmdNavicli = '/opt/Navisphere/bin/naviseccli -h '.$np->opts->host.' -User '.$np->opts->user;
$cmdNavicli .=' -Password '.$np->opts->password.' -Scope 0 ';
#print Dumper $cmdNavicli;

switch ($np->opts->type) {
	case "disk"	{ 
		if( $np->opts->mode eq "errors"){
			diskErrors();
		}elsif( $np->opts->mode eq "state"){
			diskState();
		}else{
			$np->nagios_exit(3,'Invalid mode argument for disk. Available modes: errors,state');
		}
	}
	case "dpe"	{ 
		if( $np->opts->mode eq "powerstatus"){
			dpePowerstatus();
		}elsif( $np->opts->mode eq "temperature"){
			dpeTemperature();
		}else{
			$np->nagios_exit(3,'Invalid mode argument for dpe. Available modes:powerstatus,temperature');
		}
	}
	case "dae"	{ 
		if( $np->opts->mode eq "powerstatus"){
			dpePowerstatus();
		}elsif( $np->opts->mode eq "temperature"){
			dpeTemperature();
		}else{
			$np->nagios_exit(3,'Invalid mode argument for dae. Available modes: powerstatus,temperature');
		}
	}
	case "array"	{ 
		if( $np->opts->mode eq "health"){
			arrayHealth();
		}else{
			$np->nagios_exit(3,'Invalid mode argument for array. Available modes: health');
		}
	}
	case "port"	{ 
		if( $np->opts->mode eq "status"){
			portStatus();
		}else{
			$np->nagios_exit(3,'Invalid mode argument for port. Available modes: status');
		}
	}
	case "powersupply"	{ 
		if( $np->opts->mode eq "state"){
			powersupplyState();
		}else{
			$np->nagios_exit(3,'Invalid mode argument for powersupply. Available modes: state');
		}
	}
	case "lcc"	{ 
		if( $np->opts->mode eq "state"){
			lccState();
		}else{
			$np->nagios_exit(3,'Invalid mode argument for llc. Available modes: state');
		}
	}
	case "raidgroup"	{ 
		if( $np->opts->mode eq "usage"){
			raidgroupUsage();
		}else{
			$np->nagios_exit(3,'Invalid mode argument for raidgroup. Available modes: usage');
		}
	}
	case "storagepool"	{ 
		if( $np->opts->mode eq "state"){
			poolState();
		}elsif($np->opts->mode eq "usage"){
			poolUsage();
		}else{
			$np->nagios_exit(3,'Invalid mode argument for raidgroup. Available modes: state,usage');
		}
	}
	case "sp"{ 
		if( $np->opts->mode eq "busy"){
			busy();
		}if( $np->opts->mode eq "state"){
			spState();
		}else{
			$np->nagios_exit(3,'Invalid mode argument for sp. Available modes: busy,state');
		}
	}
	case "lun"{ 
		if( $np->opts->mode eq "usage"){
			lunUsage();
		}if( $np->opts->mode eq "state"){
			lunState();
		}else{
			$np->nagios_exit(3,'Invalid mode argument for lun. Available modes: usage,state');
		}
	}
	else{#este pertence aos cases
		$np->nagios_exit(3,'Value "'.$np->opts->type.'" invalid for option.');
	}
}

$np->nagios_exit(3,'ops! Error.');
#fim

sub lunState {
	my $lunName = $np->opts->subtype;
	my $state;
	my $exitCode = 'CRITICAL';
	my $msg = 'Not Found';

	$np->nagios_exit(3,'Missing argument: s') if( !defined $lunName);

	my $command = "$cmdNavicli lun -list -name \"".$lunName."\" -state";
	print Dumper $command if ($np->opts->verbose);

	open (NAVICLIOUT ,"$command |");

	while (<NAVICLIOUT>) {
		chomp $_;
		check_for_errors($_);
		#print Dumper $_;
		if  ( $_ =~ m/^Current State:\s+(.*)/){
			$state = $1 ;
			$msg = $_;
		}
	}
	close (NAVICLIOUT);

	
	if( $state eq 'Ready'){
		$exitCode = "OK";
		$msg = "Lun:".$lunName." ".$msg;
	}
	$np->nagios_exit($exitCode, $msg);	
}

sub lunUsage {
	my $lunName = $np->opts->subtype;
	my $warning = $np->opts->warning;
	my $critical = $np->opts->critical;
	my $percConsumed;
	my $userCap;
	my $consumedCap;
	my $metadataAllocation;
	my $exitCode = 'CRITICAL';
	my $msg = 'Not Found';

	$np->nagios_exit(3,'Missing argument: s') if( !defined $lunName );

	#valor warning deve ser menor que critical
	if( $warning && $critical ){
		$np->nagios_exit(3,'The "critical" value must be larger than the "warning" value') if ( $warning > $critical );
	}

	my $command = "$cmdNavicli lun -list -name \"".$lunName."\" -userCap -consumedCap -metadataAllocation";
	print $command if ($np->opts->verbose);
	open (NAVICLIOUT ,"$command |");

	while (<NAVICLIOUT>) {
		chomp $_;
		check_for_errors($_);
		#print Dumper $_;
		$userCap = sprintf "%.0f", $1 if ( $_ =~ m/^User Capacity \(GBs\):\s+(.*)$/);
		$consumedCap = sprintf "%.0f", $1 if ( $_ =~ m/^Consumed Capacity \(GBs\):\s+(.*)$/);
		$metadataAllocation = sprintf "%.0f", $1 if ( $_ =~ m/^Metadata Allocation \(GBs\):\s+(.*)$/);
	}
	close (NAVICLIOUT);
	
	$consumedCap = $consumedCap - $metadataAllocation;

	#print Dumper $userCap;
	#print Dumper $consumedCap;

	$percConsumed = sprintf "%.0f", ($consumedCap * 100 ) / $userCap;
	#print Dumper $percConsumed;

	$exitCode = metric($percConsumed);
	$msg = "Lun:".$lunName." Percent Consumed:".$percConsumed."% User Capacity:".$userCap."GBs Consumed Capacity:".$consumedCap."GBs ";
	$msg .="|'percConsumed'=".$percConsumed."%;".$warning.";".$critical.";0;100 'consumed'=".$consumedCap.";;;;";

	$np->nagios_exit($exitCode, $msg);
	
}

sub poolUsage {
	my $poolname = $np->opts->subtype;
	my $warning = $np->opts->warning;
	my $critical = $np->opts->critical;
	my $perc_full;
	my $userCap;
	my $consumedCap;
	my $exitCode = 'CRITICAL';
	my $msg = 'Not Found';

	$np->nagios_exit(3,'Missing argument: poolname') if( !defined $poolname );

	#valor warning deve ser menor que critical
	if( $warning && $critical ){
		$np->nagios_exit(3,'The "critical" value must be larger than the "warning" value') if ( $warning > $critical );
	}

	my $command = "$cmdNavicli storagepool -list -name ".$poolname." -userCap -consumedCap -prcntFull";
	print $command if ($np->opts->verbose);
	open (NAVICLIOUT ,"$command |");

	while (<NAVICLIOUT>) {
		chomp $_;
		check_for_errors($_);
		#print Dumper $_;
		$userCap = sprintf "%.0f", $1 if ( $_ =~ m/^User Capacity \(GBs\):\s+(.*)$/);
		$consumedCap = sprintf "%.0f", $1 if ( $_ =~ m/^Consumed Capacity \(GBs\):\s+(.*)$/);
		$perc_full = sprintf "%.0f", $1 if ( $_ =~ m/^Percent Full:\s+(.*)$/);

	}
	close (NAVICLIOUT);

	$exitCode = metric($perc_full);
	$msg = "Poolname:".$poolname." Percent Full:".$perc_full."% User Capacity:".$userCap."GBs Consumed Capacity:".$consumedCap."GBs ";
	$msg .="|'perc_full'=".$perc_full."%;".$warning.";".$critical.";0;100 'consumed'=".$consumedCap.";;;;";

	$np->nagios_exit($exitCode, $msg);
	
}

sub raidgroupUsage {
	my $raidgroupId =  $np->opts->subtype;
	my $warning = $np->opts->warning;
	my $critical = $np->opts->critical;
	my $exitCode = 'CRITICAL';
	my $msg = 'Not Found';
	my $logicalCapacity;
	my $freeCapacity;
	my $percFree;
	my $percUsage;


	$np->nagios_exit(3,'Missing argument: s') if( !defined $raidgroupId);

	#valor warning deve ser menor que critical
	if( $warning && $critical ){
		$np->nagios_exit(3,'The "critical" value must be larger than the "warning" value') if ( $warning > $critical );
	}

	my $command = "$cmdNavicli getrg ".$raidgroupId." -tcap -ucap";
	print Dumper $command if ($np->opts->verbose);

	open (NAVICLIOUT ,"$command |");

	while (<NAVICLIOUT>) {
		chomp $_;
		check_for_errors($_);
		#print Dumper $_;
		$logicalCapacity = $1 if ( $_ =~ m/Logical Capacity \(Blocks\):\s+(.*)$/);
		$freeCapacity = $1 if ( $_ =~ m/Free Capacity \(Blocks,non-contiguous\):\s+(.*)$/);
	}
	close (NAVICLIOUT);
	$percFree =  sprintf "%.0f", ($freeCapacity * 100) / $logicalCapacity;
	$percUsage = 100 - $percFree;

	$logicalCapacity =  sprintf "%.1f", $logicalCapacity / 2097152;
	$freeCapacity =  sprintf "%.1f", $freeCapacity / 2097152;

	$exitCode = metric($percUsage);
	$msg = "RaidGroup ID:".$raidgroupId." Usage:".$percUsage."% Logical Capacity:".$logicalCapacity."GBs Free Capacity:".$freeCapacity."GBs ";
	$msg .="|'usage_perc'=".$percUsage."%;".$warning.";".$critical.";0;100 'free'=".$freeCapacity."GB;;;0;";

	$np->nagios_exit($exitCode, $msg);
}

sub lccState {
	my @subtype = split('_', $np->opts->subtype);
	my $bus = @subtype[0];
	my $enclosure = @subtype[1];
	my $powersupplyID = @subtype[2];
	my $state;
	my $exitCode = 'CRITICAL';
	my $msg = 'Not Found';

	$np->nagios_exit(3,'Missing argument: s') if( !defined $np->opts->subtype);
	$np->nagios_exit(3,'Erro format argument s, example: 0_0_A') unless ($np->opts->subtype =~ m/^[0-9]_[0-9]_[A,B]/);

	my $command = "$cmdNavicli getcrus";
	print Dumper $command if ($np->opts->verbose);

	open (NAVICLIOUT ,"$command |");

	while (<NAVICLIOUT>) {
		chomp $_;
		check_for_errors($_);
		#print Dumper $_;
		if  ( $_ =~ m/^Bus\s+$bus\s+Enclosure\s+$enclosure\s+LCC\s+$powersupplyID\s+State:\s+(.*)/){
			$state = $1 ;
			$msg = $_;
		}
	}
	close (NAVICLIOUT);

	
	if( $state eq 'Present'){
		$exitCode = "OK";	
	}
	$np->nagios_exit($exitCode, $msg);	
}

sub powersupplyState {
	my @subtype = split('_', $np->opts->subtype);
	my $bus = @subtype[0];
	my $enclosure = @subtype[1];
	my $powersupplyID = @subtype[2];
	my $state;
	my $msg = 'Not Found';

	$np->nagios_exit(3,'Missing argument: s') if( !defined $np->opts->subtype);
	$np->nagios_exit(3,'Erro format argument s, example: 0_0_A') unless ($np->opts->subtype =~ m/^[0-9]_[0-9]_[A,B]/);

	my $command = "$cmdNavicli getcrus";
	print Dumper $command if ($np->opts->verbose);

	open (NAVICLIOUT ,"$command |");

	while (<NAVICLIOUT>) {
		chomp $_;
		check_for_errors($_);
		#print Dumper $_;
		if  ( $_ =~ m/^Bus\s+$bus\s+Enclosure\s+$enclosure\s+Power\s+$powersupplyID\s+State:\s+(.*)/){
			$state = $1 ;
			$msg = $_;
		}
	}
	close (NAVICLIOUT);

	my $exitCode = 'CRITICAL';
	if( $state eq 'Present'){
		$exitCode = "OK";	
	}
	$np->nagios_exit($exitCode, $msg);	
}

sub diskState {
	my $idsDpeDisk = $np->opts->subtype;
	my $state;
	my $dpeName;
	my $stateCritical;
	my $msg;

	$np->nagios_exit(3,'Missing argument: s') if( !defined $idsDpeDisk);

	my $command = "$cmdNavicli getdisk ".$idsDpeDisk." -state";
	print Dumper $command if ($np->opts->verbose);

	open (NAVICLIOUT ,"$command |");

	while (<NAVICLIOUT>) {
		chomp $_;
		check_for_errors($_);
		#print Dumper $_;
		$dpeName = $_ if ( $_ =~ m/Enclosure/);
		$state = $1 if ( $_ =~ m/State:\s+(.*)$/);

		if ( $_ =~ m/Verify that the disk exists and proper slot notation is used.\s+(.*)$/){
			$stateCritical = "Too few or invalid command line parameters:".$idsDpeDisk."'. ";
			$stateCritical .= "Verify that the disk exists and proper slot notation is used. For valid disk names" ;
		}
		
	}
	close (NAVICLIOUT);

	#se der erro sai do programa
	$np->nagios_exit(3, $stateCritical) if ( defined $stateCritical );

	$dpeName =~ s/\s+$//; #retirar espaço em branco a direita

	my $exitCode = 'CRITICAL';
	$msg = $dpeName.": ".$state;

	if( $state eq 'Enabled' || $state eq 'Unbound' ){
		$exitCode = "OK";	
	}

	$np->nagios_exit($exitCode, $msg);
}

sub diskErrors {
	my $warning = $np->opts->warning;
	my $critical = $np->opts->critical;
	my $idsDpeDisk = $np->opts->subtype;
	my $dpeName;
	my $statusCritical;
	my $msg;
	my $exitCode;
	my $hardReadErrors;
	my $hardWriteErrors;
	my $softReadErrors;
	my $softWriteErrors;
	my $totalErrors;

	$np->nagios_exit(3,'Missing argument: s') if( !defined $idsDpeDisk);

	#valor warning deve ser menor que critical
	if( $warning && $critical ){
		$np->nagios_exit(3,'The "critical" value must be larger than the "warning" value') if ( $warning > $critical );
	}

	my $command = "$cmdNavicli getdisk ".$idsDpeDisk;
	print $command if ($np->opts->verbose);
	open (NAVICLIOUT ,"$command |");

	while (<NAVICLIOUT>) {
		chomp $_;
		# First lets check for errors before proceeding
		check_for_errors($_);
		#print Dumper $_;
		$dpeName = $_ if ( $_ =~ m/Enclosure/);
		$hardReadErrors = $1 if ( $_ =~ m/Hard Read Errors:\s+(.*)$/);
		$hardWriteErrors = $1 if ( $_ =~ m/Hard Write Errors:\s+(.*)$/);
		$softReadErrors = $1 if ( $_ =~ m/Soft Read Errors:\s+(.*)$/);
		$softWriteErrors = $1 if ( $_ =~ m/Soft Write Errors:\s+(.*)$/);
		if ( $_ =~ m/Verify that the disk exists and proper slot notation is used.\s+(.*)$/){
			$statusCritical = "Too few or invalid command line parameters:".$idsDpeDisk."'. ";
			$statusCritical .= "Verify that the disk exists and proper slot notation is used. For valid disk names" ;
		}
	}
	close (NAVICLIOUT);

	#se der erro sai do programa
	$np->nagios_exit(3, $statusCritical) if ( defined $statusCritical );

	$dpeName =~ s/\s+$//; #retirar espaço em branco a direita
	$totalErrors = $hardReadErrors + $hardWriteErrors + $softReadErrors + $softWriteErrors;

	$exitCode = metric($totalErrors);
	$msg = $dpeName." Total Errors:".$totalErrors." |'totalerrors'=".$totalErrors.";".$warning.";".$critical.";;";

	$np->nagios_exit($exitCode, $msg);
}

sub dpeTemperature {
	my $warning = $np->opts->warning;
	my $critical = $np->opts->critical;
	my $dpeId = $np->opts->subtype;
	my $dpeName;
	my $statusCritical;
	my $msg;
	my $temp;
	my $exitCode;
	
	$np->nagios_exit(3,'Missing argument: s') if( !defined $dpeId);

	#valor warning deve ser menor que critical
	if( $warning && $critical ){
		$np->nagios_exit(3,'The "critical" value must be larger than the "warning" value') if ( $warning > $critical );
	}

	my $command = "$cmdNavicli environment -list -enclosure ".$dpeId." -intemp c";
	print $command if ($np->opts->verbose);
	open (NAVICLIOUT ,"$command |");

	while (<NAVICLIOUT>) {
		chomp $_;
		# First lets check for errors before proceeding
		check_for_errors($_);
		#print Dumper $_;
		$dpeName = $_ if ( $_ =~ m/Enclosure/);
		if ( $_ =~ m/^Present\(degree C\):\s+(.*)$/){
			$temp = $1  ;
		}else{
			$statusCritical .= $_.". ";
		}
		
	}
	close (NAVICLIOUT);

	$dpeName =~ s/\s+$//; #retirar espaço em branco a direita

	$exitCode = metric($temp);
	$msg = $dpeName." Temperature:".$temp."C|'temperature'=".$temp."C;".$warning.";".$critical.";;";

	if (!defined $temp){
		$exitCode = 3;
		$msg = $statusCritical;
	}

	$np->nagios_exit($exitCode, $msg);
}

sub dpePowerstatus {
	my $dpeId = $np->opts->subtype;
	my $status;
	my $dpeName;
	my $statusCritical;
	my $msg;

	$np->nagios_exit(3,'Missing argument: s') if( !defined $dpeId);

	my $command = "$cmdNavicli environment -list -enclosure ".$dpeId." -power";
	print Dumper $command if ($np->opts->verbose);

	open (NAVICLIOUT ,"$command |");

	while (<NAVICLIOUT>) {
		chomp $_;
		check_for_errors($_);
		#print Dumper $_;
		$dpeName = $_ if ( $_ =~ m/Enclosure/);

		if ( $_ =~ m/Status:\s+(.*)$/){
			$status = $1 ;
		}else{
			$statusCritical .= $_.". ";
		}
		
	}
	close (NAVICLIOUT);

	$dpeName =~ s/\s+$//; #retirar espaço em branco a direita

	my $exitCode = 'CRITICAL';
	if( $status eq 'Valid' ){
		$exitCode = "OK";
		$msg = $dpeName.": ".$status;
	}else{
		$msg = $statusCritical;
		$exitCode = 3;
	}
	$np->nagios_exit($exitCode, $msg);
}

sub arrayHealth {
	my $state;
	my $msg;

	my $command = "$cmdNavicli faults -list";
	print Dumper $command if ($np->opts->verbose);

	open (NAVICLIOUT ,"$command |");

	while (<NAVICLIOUT>) {
		chomp $_;
		check_for_errors($_);
		$state .= $_;
	}
	close (NAVICLIOUT);

	my $exitCode = 'CRITICAL';
	$exitCode = "OK" if( $state eq 'The array is operating normally.' );
	$np->nagios_exit($exitCode, $state);	
}

sub spState {
	my $sp = $np->opts->subtype;
	my $spLowercase = lc $sp;
	my $state;
	my $msg;

	$np->nagios_exit(3,'Missing argument: s') if( !defined $sp);
	$np->nagios_exit(3,'SP is A or B') if( $sp ne 'A' and $sp ne 'B');

	my $command = "$cmdNavicli getcrus -sp".$spLowercase;
	print Dumper $command if ($np->opts->verbose);

	open (NAVICLIOUT ,"$command |");

	while (<NAVICLIOUT>) {
		chomp $_;
		check_for_errors($_);
		$state = $1 if ( $_ =~ m/State:\s+(.*)$/);
	}
	close (NAVICLIOUT);

	my $exitCode = 'CRITICAL';
	$exitCode = "OK" if( $state eq 'Present' );
	$np->nagios_exit($exitCode, "SP ".$sp." State: ".$state);	
}

sub busy {
	my $warning = $np->opts->warning;
	my $critical = $np->opts->critical;
	my $busy;
	my $exitCode;
	my $msg;
	
	#valor warning deve ser menor que critical
	if( $warning && $critical ){
		$np->nagios_exit(3,'The "critical" value must be larger than the "warning" value') if ( $warning > $critical );
	}

	my $command = "$cmdNavicli getcontrol -busy";
	print $command if ($np->opts->verbose);
	open (NAVICLIOUT ,"$command |");

	while (<NAVICLIOUT>) {
		chomp $_;
		# First lets check for errors before proceeding
		check_for_errors($_);
		$busy = $1 if ( $_ =~ m/^Prct Busy:\s+(.*)$/);
		
	}
	close (NAVICLIOUT);

	$exitCode = metric($busy);
	$msg = "Busy is ".$busy."%|'Busy'=".$busy."%;".$warning.";".$critical.";0;100";

	$np->nagios_exit($exitCode, $msg);
}

sub portStatus {
	my @subtype = split('_', $np->opts->subtype);
	my $sp = @subtype[0];
	my $port = @subtype[1];
	my $spPort = "SP ".$sp.", Port:".$port;
	my $txt; # Coloca tudo nume linha só para fazer o parse depois

	$np->nagios_exit(3,'Missing argument: s') if( !defined $sp);
	$np->nagios_exit(3,'SP is A or B') if( $sp ne 'A' and $sp ne 'B');

	print Dumper "$cmdNavicli port -list -sp" if ($np->opts->verbose) ;
	open (NAVICLIOUT ,"$cmdNavicli port -list -sp |") || die "Failed: $!\n";

	while (<NAVICLIOUT>) {
		chomp $_;
		check_for_errors($_);
		#print Dumper $_;
		$txt .= $1.',' if  ( $_ =~ m/^SP Name:\s+(.*)/);
		$txt .= ' Port:'.$1.';' if ( $_ =~ m/^SP Port ID:\s+(.*)$/);
		$txt .= 'Link Status:'.$1.',' if ( $_ =~ m/^Link Status:\s+(.*)$/);
		$txt .= ' Port Status:'.$1.';#' if ( $_ =~ m/^Port Status:\s+(.*)$/);
	}
	close (NAVICLIOUT);

	#print Dumper $txt;
	my @SPs = split('#', $txt);
	my @returnSps;
	my $existSpPort = 0;
	my $code = CRITICAL;
	my $msg;

	foreach my $spNew (@SPs) {
		print "$spNew\n" if ($np->opts->verbose); 
		my @spss = split(';', $spNew);
		if($spPort eq @spss[0]){		
			$existSpPort = $existSpPort + 1;
			$msg = @spss[1];
			$code = "OK" if ("Link Status:Up, Port Status:Online" eq $msg);
		}
	}

	$np->nagios_exit(3,"Not found Port:$port and SP:$sp") if ($existSpPort < 1) ;
	$np->nagios_exit($code, "Status ".$spPort.", ".$msg);
}

sub poolState {
	my $state;
	my $poolname = $np->opts->subtype;

	$np->nagios_exit(3,'Missing argument: poolname') if( !defined $poolname );

	my $command = "$cmdNavicli storagepool -list -name $poolname -state";
	print $command if ($np->opts->verbose);
	open (NAVICLIOUT ,"$command |");

	while (<NAVICLIOUT>) {
		chomp $_;
		check_for_errors($_);
		$state = $1 if ( $_ =~ m/^State:\s+(.*)$/);
	}
	close (NAVICLIOUT);
	#$state = "oi nelson";
	my $exitCode = 'CRITICAL';
	$exitCode = "OK" if( $state eq 'Ready' );
	$np->nagios_exit($exitCode, "Storage Pool:".$poolname." State:".$state);
}

sub poolCapacity {
	my $poolname = $np->opts->poolname;
	my $warning = $np->opts->warning;
	my $critical = $np->opts->critical;
	my $available;
	my $total;

	$np->nagios_exit(3,'Missing argument: poolname') if( !defined $poolname );
	
	#valor warning deve ser maior que critical
	if( $warning && $critical ){
		$np->nagios_exit(3,'The "warning" value must be larger than the "critical" value') if ( ( $warning < $critical ) || ( $warning == $critical ) );
	}

	print Dumper "$cmdNavicli storagepool -list -name ".$poolname." -capacities" if ($np->opts->verbose) ;
	open (NAVICLIOUT ,"$cmdNavicli storagepool -list -name ".$poolname." -capacities |") || die "Failed: $!\n";

	while (<NAVICLIOUT>) {
		chomp $_;
		# First lets check for errors before proceeding
		check_for_errors($_);

		$available = $1 if ( $_ =~ m/^Available Capacity \(GBs\):\s+(.*)$/);
		$total = $1 if ( $_ =~ m/^User Capacity \(GBs\):\s+(.*)$/);
	}
	close (NAVICLIOUT);

	my $percAvailable = sprintf("%.1f", ($available * 100) / $total);
		
	my $exitCode = metric($percAvailable);
	my $msg = "Storage Pool:".$poolname." Available:".$available."GB(".$percAvailable."%), Total:".$total;
	my $perf = " | 'available'=".$available."GB;;;0;".$total." 'perc_available'=".$percAvailable."%;".$warning.";".$critical.";0;100";
	$np->nagios_exit( $exitCode,$msg.$perf );

}

sub check_for_errors {
	my $value = shift;
	# General checks to see if we had issues connecting
	$np->nagios_exit(3,$value) if ($value =~ /^(A network error)/) ;  
	$np->nagios_exit(3,$value) if ($value =~ /^(Exception)/);
	$np->nagios_exit(3,$value) if ($value =~ /^(Could not connect to the specified host)/) ;
	$np->nagios_exit(3,$value) if ($value =~ m/Could not retrieve the specified/) ;
	$np->nagios_exit(3,$value) if ($value =~ /^(Error)/) ;
}

sub metric {
	my $value = shift;
	my $warning = $np->opts->warning;
	my $critical = $np->opts->critical;

	if(!defined  $warning || !defined $critical ){
		return 'OK';
	}
	
	if($warning <= $critical){
		if ($value >= $critical) {
			return 'CRITICAL';
		}elsif ($value >= $warning) {
			return 'WARNING';
		}elsif ($value < $warning) {
			return 'OK';
		}else {
			$np->nagios_exit( "UNKNOWN", "Unable to check.");
		}
	}elsif ($warning > $critical){
		if ($value <= $critical) {
			return 'CRITICAL';
		}elsif ($value <= $warning) {
			return 'WARNING';
		}elsif($value > $warning) {
			return 'OK';
		}else {
			$np->nagios_exit( "UNKNOWN", "Unable to check.");
		}
	}
}
