#!/usr/bin/perl ######################################################################### # Description: Checks Datacore sansymphony 9 via SNMP. # # Date : 23 March 2015 # Author: Fabrice Le Dorze # Licence : GPL - http://www.fsf.org/licenses/gpl.txt # Purpose: Monitor Datacore sansymphony 9 with Nagios # Can be used to query status and performance info # # Date : 09 January 2017 # Modified by : Frederic Larive # Changelog : add filtering on all parts of retrieved SNMP data # removed 'Available' from FallingThresholdPerfMonitor $message parser regex # ######################################################################### # use strict; use Getopt::Long; my $PROGNAME=`basename $0`; chomp $PROGNAME; #----------------------------------------------------- # Usage function #----------------------------------------------------- sub Print_Usage() { print < -C -t [-s [,]] [-T ] [-n [-e]] [ -w ][-c ] [ -y ][-z ] [-S] USAGE } #----------------------------------------------------- # Parameters #----------------------------------------------------- our %subtypes=( PhysicalDisks => { DiskPoolStateMonitor => "Monitors the state of disk pools.", FallingThresholdPerfMonitor => "Monitors the disk pools available space percentage.", PhysicalDiskStateMonitor => "Monitors the state of physical disks.", PoolMemberStateMonitor => "Monitors the state of the relation between a pair of mirrored physical disks in a pool.", RisingThresholdPerfMonitor => "Monitors the disk pools latency.", }, Servers => { ServeriScsiPortStateMonitor => "Monitors the state of server iSCSI ports.", ServerMachineLicenseMonitor => "Monitors the license expiration date of DataCore Servers.", ServerMachinePowerStateMonitor => "Monitors the battery power state for DataCore Servers.", ServerMachineStateMonitor => "Monitors the state of DataCore Servers.", ServerMSiScsiInitiatorStateMonitor => "Monitors the state of MS iSCSI Initiator ports.", }, Scsi => { ScsiPortConnectionStateMonitor => "Monitors the connection state of SCSI ports." }, VirtualDisks => { LogicalDiskAccessRightsMonitor => "Monitors the access rights of virtual disk sources.", LogicalDiskDataStatusMonitor => "Monitors the data status of virtual disk sources.", LogicalDiskFailureMonitor => "Monitors the failure status of virtual disk sources.", LogicalDiskStateMonitor => "Monitors the state of virtual disk sources.", StreamLogicalDiskStateMonitor => "Monitors the state of the data protection of virtual disk sources.", VirtualDiskAccessRightsMonitor => "Monitors the access rights of virtual disk sources.", VirtualDiskDataStatusMonitor => "Monitors the status of virtual disks.", }, Clients => { ClientMachineStateMonitor => "Monitors the state of hosts."} ); my $datacore_oid="1.3.6.1.4.1.7652.1.1.1"; my $monitor_oid=$datacore_oid.".2."; my $state_oid=$datacore_oid.".5."; my $id_oid=$datacore_oid.".3."; my $item_oid=$datacore_oid.".4."; my $message_oid=$datacore_oid.".6."; #----------------------------------------------------- # Help function #----------------------------------------------------- sub Print_Help { print <".$t."\n"; my %hash=%{$subtypes{$t}}; for my $key (keys %hash) { print "\t\t ".$key." : ".$hash{$key}."\n"; } } print < is a regular expression) : -p : include only 'item' matching given pattern --sp : include only 'state' matching given pattern --ip : include only 'id' matching given pattern --mp : include only 'message' matching given pattern --stp : include only 'subtype' matching given pattern -e : use above patterns to EXCLUDE data --pdbg : print debug info to identify fields for filtering HELP exit 1; } #----------------------------------------------------- # Get user-given variables #----------------------------------------------------- my ($host, $community, $type, $subtypes, $pattern, $StatePattern, $IdPattern, $MessagePattern, $SubtypePattern, $patternDebug, $exclude, $warning, $lwarning, $critical, $lcritical, $help, $debug, $short, $timeout); $pattern='.*'; $StatePattern='.*'; $IdPattern='.*'; $MessagePattern='.*'; $SubtypePattern='.*'; Getopt::Long::Configure ("bundling"); GetOptions ( 'H=s' => \$host, 'C=s' => \$community, 'T=s' => \$timeout, 't=s' => \$type, 's=s' => \$subtypes, 'd' => \$debug, 'S' => \$short, 'w=s' => \$warning, 'c=s' => \$critical, 'y=s' => \$lwarning, 'z=s' => \$lcritical, 'e' => \$exclude, 'p=s' => \$pattern, 'sp=s' => \$StatePattern, 'ip=s' => \$IdPattern, 'mp=s' => \$MessagePattern, 'stp=s' => \$SubtypePattern, 'pdbg' => \$patternDebug, 'h' => \$help ); if( $pattern eq '.*' && $StatePattern eq '.*' && $IdPattern eq '.*' && $MessagePattern eq '.*' && $SubtypePattern eq '.*') { $pattern=0; $StatePattern=0; $IdPattern=0; $MessagePattern=0; $SubtypePattern=0; } $timeout="15" unless ($timeout); &Print_Help if ($help); &Print_Help unless ($community && $host && $type); &Print_Help unless ($subtypes{$type}); my @subtype_array=keys %{$subtypes{$type}}; if ($subtypes) { @subtype_array=(); for my $sub (split(/,/,$subtypes)) { push @subtype_array, $sub if (${$subtypes{$type}}{$sub}); } } if (grep {/FallingThresholdPerfMonitor/} @subtype_array) { $warning="90" unless ($warning); $critical="95" unless ($critical); } if (grep {/RisingThresholdPerfMonitor/} @subtype_array) { $lwarning="10" unless ($lwarning); $lcritical="20" unless ($lcritical); } my $STATE_OK=0; my $STATE_WARNING=1; my $STATE_CRITICAL=2; my $STATE_UNKNOWN=3; #----------------------------------------------------- # SNMP request #----------------------------------------------------- my $command="snmpwalk -v 2c -O n -c $community $host $datacore_oid"; my $output=`$command`; print $output if($debug); #print "No result." and exit $STATE_UNKNOWN if ($?!=0 or $output =~ /No more variables left in this MIB View/); print "No result." and exit $STATE_UNKNOWN if ($?!=0); chomp $output; my @result=split(/\n/,$output); #----------------------------------------------------- # Loop on selected subtypes #----------------------------------------------------- my $critstate=0; my $warnstate=0; my $i=0; my $failure=0; my @details; my @failed; my @perfs; my @indexes; for my $subtype (@subtype_array) { # Look for matching indexes @indexes=grep{/\"$subtype/} @result; map{s/$monitor_oid//} @indexes; map{s/ = STRING.*//} @indexes; for my $index (@indexes) { my @res=grep {/$index =/} @result; print join("\n",@res)."\n" if ($debug); my $state=(grep{/$state_oid/} @res)[0]; my $item=(grep{/$item_oid/} @res)[0]; my $id=(grep{/$id_oid/} @res)[0]; my $message=(grep{/$message_oid/} @res)[0]; map {s/.*$datacore_oid.*= STRING: //} ($state, $item, $id, $message); map {s/"|{|}//g} ($state, $item, $id, $message); # Add Disk ID for some subtypes $item.="(".$id.")" if ($subtype =~ /PhysicalDiskStateMonitor|PoolMemberStateMonitor/); # Compare item with patterns if ($pattern || $StatePattern || $IdPattern || $MessagePattern || $SubtypePattern) { if ($exclude) { next if ($item =~ /$pattern/ && $state =~ /$StatePattern/ && $id =~ /$IdPattern/ && $message =~ /$MessagePattern/); } else { next unless ($item =~ /$pattern/ && $state =~ /$StatePattern/ && $id =~ /$IdPattern/ && $message =~ /$MessagePattern/); } } if( $patternDebug ) {print "*****\n\tITEM: $item\n\tSTATE: $state\n\tID: $id\n\tMSG: $message\n\tSUBTYPE: $subtype\n*****\n";} # Disk Pool usage if ( $subtype eq "FallingThresholdPerfMonitor") { print "$item $state : $message\n" if ($debug); my $freeValue=($message=~/ space.* (\d+)%/)[0]; my $usedvalue=100-$freeValue; if ($usedvalue>$critical) { $critstate=1; push @failed, $item."=".$usedvalue."%(>".$critical."%)"; push @details, $item."=".$usedvalue."%(>".$critical."%) from ".$subtype; } elsif ($usedvalue>$warning) { $warnstate=1; push @failed, "'".$item."'=".$usedvalue."%(>".$warning."%)"; push @details, "'".$item."'=".$usedvalue."%(>".$warning."%) from ".$subtype; } else { push @details, "'".$item."'=".$usedvalue."%(<=".$warning."%) from ".$subtype; } push @perfs, "'".$item."'=".$usedvalue."%;".$warning.";".$critical.";0;100"; } # Disk Pool latency elsif ( $subtype eq "RisingThresholdPerfMonitor" ) { print "$item $state : $message\n" if ($debug); my $latency=($message=~/.*latency.* (\d+)s/)[0]; if ($latency>$lcritical) { push @failed, "'".$item."'=".$latency."s(>".$lcritical."s)"; push @details, "'".$item."'=".$latency."s(>".$lcritical."s) from ".$subtype; $critstate=1 } elsif ($latency>$lwarning) { push @failed, "'".$item."'=".$latency."s(>".$lwarning."s)"; push @details, "'".$item."'=".$latency."s(>".$lwarning."s) from ".$subtype; $warnstate=1 } else { push @details, "'".$item."'=".$latency."s(<=".$lwarning."s) from ".$subtype; } push @perfs, "'".$item."'=".$latency.";".$lwarning.";".$lwarning.";0;"; } # Other cases else { $i++; print "$item $state : $message\n" if ($debug); unless ($state=~/Healthy/ && $item) { push @failed, "'".$item."' ".$state."(".$message.")"; $failure++; $critstate=1; } push @details, "'".$item."' ".$state."(".$message.") from ".$subtype; } } } print "No result." and exit $STATE_UNKNOWN if ($#details<0); my %seen=(); #my @unique=grep { ! $seen{$_} ++ } @failed; #@failed=@unique; #@unique=grep { ! $seen{$_} ++ } @details; #@details=@unique; ### # Output ### my $code; my $status; if ($critstate==1) { $code=$STATE_CRITICAL; $status=$type." CRITICAL : ".join(", ",@failed); } elsif ($warnstate==1) { $code=$STATE_WARNING; $status=$type." WARNING : ".join(", ",@failed); } else { $code=$STATE_OK; $status="All ".$type." Monitors OK, see details."; } $status.="\n".join("\n",@details) unless ($short); print $status; print "|".join(" ",@perfs); print " Failures=".$failure.";;;0;".$i."\n" if ($i>0); exit $code;