#!/usr/bin/perl -w

# check_lefthand.pl Written by Eric Schoeller for the University of Colorado Boulder - 20120923
my $VERSION="1.0";

use Net::SNMP;
use Getopt::Std;
use Getopt::Long;
use Data::Dumper;
use strict;

my ($verbose, $timeout, $port, $help, $community, $host, $module_space, $module_status, $volume_space, $volume_status, $cluster_space, $cluster_status, $warning, $critical, $version);

GetOptions ("C=s"		=>	\$community,
	    "H=s"	=>	\$host,
	    "verbose"	=>	\$verbose,
	    "timeout=i"	=>	\$timeout,
	    "port=i"	=>	\$port,
	    "help"	=>	\$help,
	    "module-space" =>	\$module_space,
	    "module-status" =>	\$module_status,
	    "volume-space" =>	\$volume_space,
	    "volume-status" =>	\$volume_status,
	    "cluster-space" =>	\$cluster_space,
	    "cluster-status" => \$cluster_status,
	    "warning=i" =>	\$warning,
	    "critical=i" =>	\$critical,
	    "version" 	=>	\$version
);

if (! $host || ! $community) {
   usage();
}

if ($help) {
   usage();
}

if ($version) {
   version();
}
 
if (! $timeout) {
   $timeout = 2;
}

if (! $port) {
   $port = 161;
}

my @ok;
my @warning;
my @critical;
my @down_managers;
my $clusMgmtGroupManagerCount;
my $clusMgmtGroupName;
my $management_group_name;

my $cluster_module_raw_crit = $critical;
my $cluster_module_raw_warn = $warning;
my $cluster_module_prov_crit = $critical;
my $cluster_module_prov_warn = $warning;
my $cluster_volume_crit = $critical;
my $cluster_volume_warn = $warning;
my $cluster_used_crit = $critical;
my $cluster_used_warn = $warning;



###### fire it up

my ($session, $error) = Net::SNMP->session (
   hostname     =>      $host,
   community    =>      $community,
   version      =>      'snmpv2c',
   timeout      =>      $timeout,
   port         =>      $port,  
);

if ( !defined $session ) {
   print "UNKNOWN - SNMP ERROR: $error\n";
   $session->close();
   exit(3);
}

if (!$cluster_space && !$cluster_status && !$module_space && !$module_status && !$volume_space && !$volume_status) {
   print "Cowardly exiting, not instructed to check anything!\n";
   &usage;
}

&global;

if ($cluster_status) {
   &cluster_status;
}

if ($cluster_space) {
   if (! ($warning || $critical) ) {
      print "Need warning and critical thresholds!\n\n";
      &usage;
   }
   &cluster_space;
}

if ($module_space) {
   if (! ($warning || $critical) ) {
      print "Need warning and critical thresholds!\n\n";
      &usage; 
   }
   &cluster_module_space;
}

if ($module_status) {
   &cluster_module_status;
}

if ($volume_space) {
   if (! ($warning || $critical) ) {
      print "Need warning and critical thresholds!\n\n";
      &usage; 
   }
   &cluster_volume_space;
}

if ($volume_status) {
   &cluster_volume_status;
}

sub usage {
        print "check_lefthand.pl -H <host> -C <community> [-t timeout] [-p port] <additional options>\n\n";
        print "Additional Options:\n";
        print "\t--module-space\n";
	print "\t   report the available space on each 'module' within a management group\n\n";
        print "\t--module-status\n";
	print "\t   report on the various status elements for each 'module' within a management group\n\n";
	print "\t--volume-space\n";
	print "\t   report the available space on each volume within a management group\n\n";
	print "\t--volume-status\n";
	print "\t   report on the various status elements for each volume within a management group\n\n";
	print "\t--cluster-space\n";
	print "\t   report the available space for each cluster within a management group\n\n";
	print "\t--cluster-status\n";
	print "\t   report the status of each cluster within a management group\n\n";
	print "\n";
	print "Any of the storage space options require the use of --warning and --critical.\n\n";
	print "Any number of directives can be chained together, but this is not recommended for readability issues.\n";
	print "warning and critical thresholds will be applied across all chained options uniformly\n";
	print "\n";
        exit(3);
}

sub version {
print <<"EOF";
This is version $VERSION of check_lefthand.

Copyright (c) 2012 Eric Schoeller (eric.schoeller <at> coloradoDOTedu).
All rights reserved.

This module is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License.
See http://www.fsf.org/licensing/licenses/gpl.html

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

EOF

    exit 3;
}

sub global {
   my $clusMgmtGroupName = $session->get_request(
      varbindlist       =>      ['.1.3.6.1.4.1.9804.3.1.1.2.12.1.0'],
   );
   if (!defined $clusMgmtGroupName) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   $management_group_name = $clusMgmtGroupName->{'.1.3.6.1.4.1.9804.3.1.1.2.12.1.0'};
}

sub cluster_status {
   my @clusMgmtGroupOIDs = (
#      ".1.3.6.1.4.1.9804.3.1.1.2.12.1.0",		# clusMgmtGroupName
      ".1.3.6.1.4.1.9804.3.1.1.2.12.2.0",		# clusMgmtGroupIsEnabled
      ".1.3.6.1.4.1.9804.3.1.1.2.12.3.0",		# clusMgmtGroupQuorum
      ".1.3.6.1.4.1.9804.3.1.1.2.12.5.0",		# clusMgmtGroupActiveManagerCount
      ".1.3.6.1.4.1.9804.3.1.1.2.12.6.0",		# clusMgmtGroupManagerCount
      ".1.3.6.1.4.1.9804.3.1.1.2.12.43.0"		# clusMgmtGroupLicenseTimeRemaining
   );

   my $clusMgmtGroup = $session->get_request(
      varbindlist	=>	\@clusMgmtGroupOIDs,
   );
   if (!defined $clusMgmtGroup) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

#   $clusMgmtGroupName = $clusMgmtGroup->{'.1.3.6.1.4.1.9804.3.1.1.2.12.1.0'};
   my $clusMgmtGroupIsEnabled = $clusMgmtGroup->{'.1.3.6.1.4.1.9804.3.1.1.2.12.2.0'};
   my $clusMgmtGroupQuorum = $clusMgmtGroup->{'.1.3.6.1.4.1.9804.3.1.1.2.12.3.0'};
   my $clusMgmtGroupActiveManagerCount = $clusMgmtGroup->{'.1.3.6.1.4.1.9804.3.1.1.2.12.5.0'};
   $clusMgmtGroupManagerCount = $clusMgmtGroup->{'.1.3.6.1.4.1.9804.3.1.1.2.12.6.0'};
   my $clusMgmtGroupLicenseTimeRemaining = $clusMgmtGroup->{'.1.3.6.1.4.1.9804.3.1.1.2.12.43.0'};

#$clusMgmtGroupActiveManagerCount=2;

   if ($clusMgmtGroupManagerCount eq $clusMgmtGroupActiveManagerCount) {
      push @ok, "$clusMgmtGroupActiveManagerCount/$clusMgmtGroupManagerCount Cluster Managers Active.";
   }

   if ($clusMgmtGroupActiveManagerCount < $clusMgmtGroupQuorum) {
      # call managers report, include down_managers in output
      &manager_report;
      push @critical, "QUORUM LOST. $clusMgmtGroupActiveManagerCount Active Cluster Managers $clusMgmtGroupQuorum needed for Quorum @down_managers";
   }
 
   elsif ($clusMgmtGroupActiveManagerCount < $clusMgmtGroupManagerCount) {
      # call managers report, include down_managers in output
      &manager_report;
      push @warning, "$clusMgmtGroupActiveManagerCount/$clusMgmtGroupManagerCount Cluster Managers Active @down_managers";
   }

}

# Function to determine names and statuses of each Cluster Manager. Code is only executed if
# NSM agent reports that certain registered managers are not active. This logic may not actually
# be valid, the attempt is to save SNMP traffic and not query these tables unless necessary.
sub manager_report {

   # Fetch the Cluster Manager names via SNMP 
   my $clusManagerName = $session->get_table(
      baseoid	=>	'.1.3.6.1.4.1.9804.3.1.1.2.12.44.1.2',
   );
   if (!defined $clusManagerName) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # Fetch the Cluster Manager Status via SNMP
   my $clusManagerStatus = $session->get_table(
      baseoid	=>	'.1.3.6.1.4.1.9804.3.1.1.2.12.44.1.5',
   );
   if (!defined $clusManagerStatus) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # Initialize two new hashes
   my $manager_name;
   my $manager_status;

   # Create a new hash with just the Manager 'id' and Name. The ID is derived from the last
   # significant integer from the OID.
   while( my ($key, $value) = each %$clusManagerName ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $manager_name->{$subkey} = $value;
   }

   # Create a new hash with just the Manager 'id' and Status. The ID is derived from the last
   # significant integer from the OID.
   while( my ($key, $value) = each %$clusManagerStatus ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;  
      my $subkey = $1;
      $manager_status->{$subkey} = $value;
   }

   # Loop through managers and determine status. 1 is (up) 2 is (down).
   # build the @down_managers array to be included in the plugin output.
   for (my $i=1; $i<=$clusMgmtGroupManagerCount; $i++) {
      if ($manager_status->{$i} eq 2) {
        push @down_managers, "$manager_name->{$i}(down)"  
      }
   }

}

sub cluster_module_space {

   my $clusModuleCount = $session->get_request(
      varbindlist	=>	['.1.3.6.1.4.1.9804.3.1.1.2.12.45.0'],
   );
   if (!defined $clusModuleCount) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   my $cluster_module_count = $clusModuleCount->{'.1.3.6.1.4.1.9804.3.1.1.2.12.45.0'};

   # Fetch the Cluster Module names via SNMP 
   my $clusModuleName = $session->get_table(
      baseoid		=>      '.1.3.6.1.4.1.9804.3.1.1.2.12.46.1.2',
   );
   if (!defined $clusModuleName) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # Fetch the Cluster Module Usable Space via SNMP 
   my $clusModuleUsableSpace = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.46.1.5',
   );
   if (!defined $clusModuleUsableSpace) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }
 
   # Fetch the Cluster Module Available Space via SNMP 
   my $clusModuleAvailableSpace = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.46.1.6',
   );
   if (!defined $clusModuleAvailableSpace) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }
 
#   # Fetch the Cluster Module Provisioned Space via SNMP 
#   my $clusModuleProvisionedSpace = $session->get_table(
#      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.46.1.28',
#   );
#   if (!defined $clusModuleProvisionedSpace) {
#      $error = $session->error();
#      print "UNKNOWN - SNMP ERROR: $error\n";
#      exit(3);
#   }

#   # Fetch the Cluster Module Used Space via SNMP 
#   my $clusModuleUsedSpace = $session->get_table(
#      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.46.1.29',
#   );
#   if (!defined $clusModuleUsedSpace) {
#      $error = $session->error();
#      print "UNKNOWN - SNMP ERROR: $error\n";
#      exit(3);
#   }


   # initialize new reformatted hashes
   my $cluster_module_name;
   my $cluster_module_usable_space;
   my $cluster_module_available_space;
#   my $cluster_module_provisioned_space;
#   my $cluster_module_used_space;

   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusModuleName ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_module_name->{$subkey} = $value;
   }

   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusModuleUsableSpace ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_module_usable_space->{$subkey} = $value;
   }

   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusModuleAvailableSpace ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_module_available_space->{$subkey} = $value;
   }

#   # rebuild hash with correct id,value
#   while( my ($key, $value) = each %$clusModuleProvisionedSpace ) {
#      # Match the last octet in the OID string
#      $key =~ /.*\.(\d*)$/;
#      my $subkey = $1;
#      $cluster_module_provisioned_space->{$subkey} = $value;
#   }

#   # rebuild hash with correct id,value
#   while( my ($key, $value) = each %$clusModuleUsedSpace ) {
#      # Match the last octet in the OID string
#      $key =~ /.*\.(\d*)$/;
#      my $subkey = $1;
#      $cluster_module_used_space->{$subkey} = $value;
#   }

   my $module_issue=0;
   for (my $i=1; $i<=$cluster_module_count; $i++) {

      my $raw_used_pct = sprintf("%.2f", ((($cluster_module_usable_space->{$i} - $cluster_module_available_space->{$i}) / $cluster_module_usable_space->{$i}) * 100));

#      my $prov_used_pct = sprintf("%.2f", (($cluster_module_used_space->{$i} / $cluster_module_provisioned_space->{$i}) * 100));

      if ($raw_used_pct >= $cluster_module_raw_crit) {
         push @critical, "$cluster_module_name->{$i} usage: $raw_used_pct%";
         $module_issue=1;
      }
      elsif ($raw_used_pct >= $cluster_module_raw_warn) {
         push @warning, "$cluster_module_name->{$i} usage: $raw_used_pct%";
         $module_issue=1;
      }

#      if ($prov_used_pct >= $cluster_module_prov_crit) {
#         push @critical, "$cluster_module_name->{$i} provisioned usage: $prov_used_pct%";
#      }
#      elsif ($prov_used_pct >= $cluster_module_prov_warn) {
#         push @warning, "$cluster_module_name->{$i} provisioned usage: $prov_used_pct%";
#      }


   }   

   if(!$module_issue) {
      push @ok, "$cluster_module_count cluster modules have adequate storage space.";
   }
}

sub cluster_module_status {

   my $clusModuleCount = $session->get_request(
      varbindlist       =>      ['.1.3.6.1.4.1.9804.3.1.1.2.12.45.0'],
   );
   if (!defined $clusModuleCount) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   my $cluster_module_count = $clusModuleCount->{'.1.3.6.1.4.1.9804.3.1.1.2.12.45.0'};

   # Fetch the Cluster Module names via SNMP 
   my $clusModuleName = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.46.1.2',
   );
   if (!defined $clusModuleName) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # Fetch the Cluster Module Storage State via SNMP DisplayString
   my $clusModuleStorageState = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.46.1.9',
   );
   if (!defined $clusModuleStorageState) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # Fetch the Cluster Module Storage Status via SNMP INTEGER { up(1), down(2) }
   my $clusModuleStorageStatus = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.46.1.10',
   );
   if (!defined $clusModuleStorageStatus) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # Fetch the Cluster Module Storage Readiness via SNMP TruthValue
   my $clusModuleStorageIsReady = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.46.1.11',
   );
   if (!defined $clusModuleStorageIsReady) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # Fetch the Cluster Module Storage Condition via SNMP INTEGER { notReady(1), inoperable(2), overloaded(3), ready(4)
   my $clusModuleStorageCondition = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.46.1.19',
   );
   if (!defined $clusModuleStorageCondition) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # initialize new reformatted hashes
   my $cluster_module_name;
   my $cluster_module_storage_state;
   my $cluster_module_storage_status;
   my $cluster_module_storage_ready;
   my $cluster_module_storage_condition;

   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusModuleName ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_module_name->{$subkey} = $value;
   }

   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusModuleStorageState ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_module_storage_state->{$subkey} = $value;
   }

   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusModuleStorageStatus ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_module_storage_status->{$subkey} = $value;
   }

   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusModuleStorageIsReady ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_module_storage_ready->{$subkey} = $value;
   }

   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusModuleStorageCondition ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_module_storage_condition->{$subkey} = $value;
   }

   my $module_issue = 0;

   for (my $i=1; $i<=$cluster_module_count; $i++) {
      if ($cluster_module_storage_state->{$i} ne 'ok') {
         push @warning, "$cluster_module_name->{$i} state: $cluster_module_storage_state->{$i}";
         $module_issue=1;
      }
      if ($cluster_module_storage_status->{$i} ne 1) {
         push @warning, "$cluster_module_name->{$i} status: DOWN";
         $module_issue=1;
      }
      if ($cluster_module_storage_ready->{$i} ne 1) {
         push @warning, "$cluster_module_name->{$i} StorageNotReady";
         $module_issue=1;
      }
      if ($cluster_module_storage_condition->{$i} ne 4) {
         $module_issue=1;
         if ($cluster_module_storage_condition->{$i} eq 1) {
            push @critical, "$cluster_module_name->{$i}: notReady";
         }
         if ($cluster_module_storage_condition->{$i} eq 2) {
            push @critical, "$cluster_module_name->{$i}: inoperable";
         }
         if ($cluster_module_storage_condition->{$i} eq 3) {
            push @critical, "$cluster_module_name->{$i}: overloaded";
         }
      }
 
   }
   if(!$module_issue) {
      push @ok, "$cluster_module_count cluster modules Online and Ready."
   }

}

sub cluster_volume_space {
   
   my $clusVolumeCount = $session->get_request(
      varbindlist       =>      ['.1.3.6.1.4.1.9804.3.1.1.2.12.96.0'],
   );
   if (!defined $clusVolumeCount) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   my $cluster_volume_count = $clusVolumeCount->{'.1.3.6.1.4.1.9804.3.1.1.2.12.96.0'};

   # Fetch the Cluster Volume names via SNMP 
   my $clusVolumeName = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.97.1.2',
   );
   if (!defined $clusVolumeName) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # Fetch the Cluster Volume Membership via SNMP 
   my $clusVolumeClusterName = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.97.1.11',
   );
   if (!defined $clusVolumeClusterName) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # Fetch the Cluster Volume Used Percent via SNMP 
   my $clusVolumeUsedPercent = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.97.1.52',
   );
   if (!defined $clusVolumeUsedPercent) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # initialize new reformatted hashes
   my $cluster_volume_name;
   my $cluster_volume_cluster_name;
   my $cluster_volume_usage;
 
   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusVolumeName ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_volume_name->{$subkey} = $value;
   }
  
   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusVolumeClusterName ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_volume_cluster_name->{$subkey} = $value;
   }

   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusVolumeUsedPercent ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_volume_usage->{$subkey} = $value;
   }

   my $volume_issue=0;
   for (my $i=1; $i<=$cluster_volume_count; $i++) {
      if ($cluster_volume_usage->{$i} >= $cluster_volume_crit) {
         push @critical, "$cluster_volume_name->{$i}($cluster_volume_cluster_name->{$i}) $cluster_volume_usage->{$i}% used ";
         $volume_issue=1;
      }
      elsif ($cluster_volume_usage->{$i} >= $cluster_volume_warn) {
         push @warning, "$cluster_volume_name->{$i}($cluster_volume_cluster_name->{$i}) $cluster_volume_usage->{$i}% used ";
         $volume_issue=1;
      }
   }
   
   if(!$volume_issue) {
      push @ok, "$cluster_volume_count Volumes with adequate space."
   }

}   

sub cluster_volume_status {

   my $clusVolumeCount = $session->get_request(
      varbindlist       =>      ['.1.3.6.1.4.1.9804.3.1.1.2.12.96.0'],
   );
   if (!defined $clusVolumeCount) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   my $cluster_volume_count = $clusVolumeCount->{'.1.3.6.1.4.1.9804.3.1.1.2.12.96.0'};

   # Fetch the Cluster Volume names via SNMP 
   my $clusVolumeName = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.97.1.2',
   );
   if (!defined $clusVolumeName) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # Fetch the Cluster Volume Membership via SNMP 
   my $clusVolumeClusterName = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.97.1.11',
   );
   if (!defined $clusVolumeClusterName) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # Fetch the Cluster Volume Replica count via SNMP 
   my $clusVolumeReplicaCount = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.97.1.8',
   );
   if (!defined $clusVolumeReplicaCount) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # Fetch the Cluster Volume Replication Status via SNMP 
   my $clusVolumeReplicationStatus = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.97.1.15',
   );
   if (!defined $clusVolumeReplicationStatus) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # Fetch the Cluster Volume Minimum Replicas via SNMP 
   my $clusVolumeMinimumReplication = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.97.1.20',
   );
   if (!defined $clusVolumeMinimumReplication) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # Fetch the Cluster Volume Type via SNMP 
   my $clusVolumeType = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.97.1.47',
   );
   if (!defined $clusVolumeType) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # Fetch the Cluster Volume Data Protection Level via SNMP 
   my $clusVolumeDataProtectionLevel = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.97.1.48',
   );
   if (!defined $clusVolumeDataProtectionLevel) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # initialize new reformatted hashes
   my $cluster_volume_name;
   my $cluster_volume_cluster_name;
   my $cluster_volume_replica_count;
   my $cluster_volume_replication_status;
   my $cluster_volume_minimum_replication;
   my $cluster_volume_type;
   my $cluster_volume_data_protection_level;

   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusVolumeName ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_volume_name->{$subkey} = $value;
   }

   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusVolumeClusterName ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_volume_cluster_name->{$subkey} = $value;
   }

   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusVolumeReplicaCount ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_volume_replica_count->{$subkey} = $value;
   }

   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusVolumeReplicationStatus ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_volume_replication_status->{$subkey} = $value;
   }

   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusVolumeMinimumReplication ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_volume_minimum_replication->{$subkey} = $value;
   }

   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusVolumeType ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_volume_type->{$subkey} = $value;
   }

   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusVolumeDataProtectionLevel ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_volume_data_protection_level->{$subkey} = $value;
   }

   my $volume_issue = 0;
   for (my $i=1; $i<=$cluster_volume_count; $i++) {

      if ($cluster_volume_replication_status->{$i} ne 1) {
         push @warning, "$cluster_volume_name->{$i}($cluster_volume_cluster_name->{$i}): replication faulty($cluster_volume_replication_status->{$i})"; 
         $volume_issue=1;
      }
    
      if ($cluster_volume_type->{$i} eq 1) {  # mr(1) Mirrored Replication
         if($cluster_volume_replica_count->{$i} < $cluster_volume_minimum_replication->{$i}) {
            push @warning, "$cluster_volume_name->{$i}($cluster_volume_cluster_name->{$i}): $cluster_volume_replica_count->{$i}/$cluster_volume_minimum_replication->{$i} required replicas";
            $volume_issue=1;
         } 
      }
      if (! ($cluster_volume_data_protection_level->{$i} eq "Network RAID-10 (2-Way Mirror)")) {
         push @warning, "$cluster_volume_name->{$i}($cluster_volume_cluster_name->{$i}) DP: $cluster_volume_data_protection_level->{$i}";
         $volume_issue=1;
      }
   } 

   if(!$volume_issue) {
      push @ok, "$cluster_volume_count Volumes with valid replication and Data Protection."
   }

}


sub cluster_space {

   my $clusClusterCount = $session->get_request(
      varbindlist       =>      ['.1.3.6.1.4.1.9804.3.1.1.2.12.47.0'],
   ); 
   if (!defined $clusClusterCount) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   my $cluster_count = $clusClusterCount->{'.1.3.6.1.4.1.9804.3.1.1.2.12.47.0'};

   # Fetch the Cluster Names via SNMP 
   my $clusClusterName = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.48.1.2',
   );
   if (!defined $clusClusterName) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # Fetch the Cluster Available Space via SNMP 
   my $clusClusterAvailableSpace = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.48.1.17',
   );
   if (!defined $clusClusterAvailableSpace) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }

   # Fetch the Cluster Available Space via SNMP 
   my $clusClusterTotalSpace = $session->get_table(
      baseoid           =>      '.1.3.6.1.4.1.9804.3.1.1.2.12.48.1.29',
   );
   if (!defined $clusClusterTotalSpace) {
      $error = $session->error();
      print "UNKNOWN - SNMP ERROR: $error\n";
      exit(3);
   }
   
   # initialize new reformatted hashes
   my $cluster_name;
   my $cluster_space_avail;
   my $cluster_space_total;

   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusClusterName ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_name->{$subkey} = $value;
   }

   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusClusterAvailableSpace ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_space_avail->{$subkey} = $value;
   }

   # rebuild hash with correct id,value
   while( my ($key, $value) = each %$clusClusterTotalSpace ) {
      # Match the last octet in the OID string
      $key =~ /.*\.(\d*)$/;
      my $subkey = $1;
      $cluster_space_total->{$subkey} = $value;
   }

   my $cluster_issue = 0;
   for (my $i=1; $i<=$cluster_count; $i++) {
      my $clus_used_pct = sprintf("%.2f", ((($cluster_space_total->{$i} - $cluster_space_avail->{$i}) / $cluster_space_total->{$i}) * 100));
      if ($clus_used_pct >= $cluster_used_crit) {
         push @critical, "$cluster_name->{$i} usage: $clus_used_pct%.";
         $cluster_issue=1;
      }
      if ($clus_used_pct >= $cluster_used_warn) {
         push @warning, "$cluster_name->{$i} usage: $clus_used_pct%.";
         $cluster_issue=1;
      }
   }

   if(!$cluster_issue) {
      push @ok, "$cluster_count Clusters with adequate space."
   }

}

if (@critical && @warning) {
   print "CRITICAL - mgmt group: $management_group_name @critical WARNING - @warning\n";
   exit(2);
}

if (@critical) {
   print "CRITICAL - mgmt group: $management_group_name @critical\n";
   exit(2);
}

if (@warning) {
   print "WARNING - mgmt group: $management_group_name @warning\n";
   exit(1);
}

if (@ok) {
   print "OK - mgmt group: $management_group_name @ok\n";
   exit(0);
}

else {
   print "UNKNOWN - unhandled exception\n";
   exit(3);
}
