#!/usr/bin/perl -w # nagios: -epn # ------------------------------------------------------------------------------ # check_emc_clariion.pl - checks the EMC CLARIION SAN devices # Copyright (C) 2005 NETWAYS GmbH, www.netways.de # Author: Michael Streb # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # 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. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # $Id$ # ------------------------------------------------------------------------------ # # basic requirements use strict; use Getopt::Long; use File::Basename; use Pod::Usage; # predeclared subs use subs qw/print_help check_sp check_disk check_portstate check_hbastate check_cache check_faults/; # predeclared vars use vars qw ( $PROGNAME $VERSION $NAVICLI $NAVISECCLI %state_names $state $opt_host $opt_sp $opt_verbose $opt_help $opt_checktype $opt_pathcount $opt_node $opt_user $opt_password $output $secure ); my $output; ### add some declaration in order to manage the --port option for check_portstate(); my $opt_port; $opt_port=-1; # a variable in order to manage the secure mode of Navicli my $secure; $secure=0; # Main values $PROGNAME = basename($0); $VERSION = '1.0'; $NAVICLI = '/opt/Navisphere/bin/navicli'; $NAVISECCLI = '/opt/Navisphere/bin/naviseccli'; # Nagios exit states our %states = ( OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 ); # Nagios state names %state_names = ( 0 => 'OK', 1 => 'WARNING', 2 => 'CRITICAL', 3 => 'UNKNOWN' ); # Get the options from cl Getopt::Long::Configure('bundling'); GetOptions( 'h' => \$opt_help, 'help' => \$opt_help, 'H=s' => \$opt_host, 'node=s' => \$opt_node, 'sp=s' => \$opt_sp, 't=s' => \$opt_checktype, 'u=s' => \$opt_user, 'p=s' => \$opt_password, 'port=s' => \$opt_port, 'paths=s' => \$opt_pathcount ) || print_help(2); # If somebody wants to the help ... if ($opt_help) { print_help(2); } # check if user and password for Naviseccli is given # If it is providen, then it passes in secure mode for the command to the array. # else we are staying in navicli mode if ( $opt_user && $opt_password ) { $secure = 1; } # Check if all needed options present. if ( $opt_host && $opt_checktype ) { # do the work if ($opt_checktype eq "sp" && $opt_sp ne "") { check_sp(); } if ($opt_checktype eq "disk") { check_disk(); } if ($opt_checktype eq "cache") { check_cache(); } if ($opt_checktype eq "faults") { check_faults(); } if ($opt_checktype eq "portstate" && $opt_sp ne "") { check_portstate(); } if ($opt_checktype eq "hbastate" && $opt_pathcount ne "" && $opt_node ne "") { check_hbastate(); } print_help(1, 'Wrong parameters specified!'); } else { print_help(2); } # ------------------------- # THE SUBS: # ------------------------- # check_sp(); # check state of the storage processors sub check_sp { if ($secure eq 0 ) { open (NAVICLIOUT ,"$NAVICLI -h $opt_host getcrus |"); } if ($secure eq 1 ) { open (NAVICLIOUT ,"$NAVISECCLI -User $opt_user -Password $opt_password -Scope 0 -h $opt_host getcrus |"); } my $sp_line = 0; my $error_count = 0; while () { if ($_ =~ m/^DPE|^SPE|^DAE/ ) { # got an DPE line $sp_line=1; } if ($sp_line == 1) { # check for SP lines if( $_ =~ m/^SP\s$opt_sp\s\w+:\s+(\w+)/) { if ($1 =~ m/(Present|Valid)/) { $output .= "SP $opt_sp $1,"; } else { $output .= "SP $opt_sp failed,"; $error_count++; } } # check for Enclosure lines if( $_ =~ m/Enclosure\s(\d+|\w+)\s(\w+)\s$opt_sp\d?\s\w+:\s+(.*)/) { my $check = $2; if ($3 =~ m/Removed|\d+.\d+|Present|Valid|N\/A|255.255/) { $output .= "$check ok,"; } else { $output .= "$check failed,"; $error_count++; } } # check for Cabling lines if( $_ =~ m/Enclosure\s(\d+|\w+)\s\w+\s$opt_sp\s(\w+)\s\w+:\s+(.*)/) { my $check = $2; if ($3 =~ m/Present|Valid|N\/A|255.255/) { $output .= "$check ok,"; } else { $output .= "$check failed,"; $error_count++; } } # end of section if ( $_ =~ m/^\s*$/) { $sp_line=0; } } } close (NAVICLIOUT); if ($error_count == 0 && $output ne "") { $state = 'OK'; } elsif ($output eq "") { $output = "UNKNOWN: No output from $NAVICLI"; $state = 'UNKNOWN'; } else { $state = 'CRITICAL'; } print $output."\n"; exit $states{$state}; } # check_disk(); # check state of the disks sub check_disk { my $disk_line = 0; my $crit_count = 0; my $warn_count = 0; my $hotspare_count = 0; my $disk_ok_count = 0; my ($bus,$enclosure,$disk) = 0; $state = 'UNKNOWN'; if ($secure eq 0 ) { open (NAVICLIOUT ,"$NAVICLI -h $opt_host getdisk -state |"); } if ($secure eq 1 ) { open (NAVICLIOUT ,"$NAVISECCLI -User $opt_user -Password $opt_password -Scope 0 -h $opt_host getdisk -state |"); } while () { # check for disk lines if( $_ =~ m/^Bus\s(\d+)\s\w+\s(\d+)\s+\w+\s+(\d+)/) { $bus = $1; $enclosure = $2; $disk = $3; $disk_line=1; } if ($disk_line == 1) { # check for States lines if( $_ =~ m/^State:\s+(.*)$/) { my $status = $1; if ($status =~ m/Hot Spare Ready/) { $hotspare_count++; $disk_ok_count++; } elsif ($status =~ m/Binding|Empty|Enabled|Expanding|Unbound|Powering Up|Ready|Transitioning/) { $disk_ok_count++; } elsif ($status =~ m/Equalizing|Rebuilding/) { $warn_count++; $output .= "Bus $bus, Enclosure $enclosure, Disk $disk is replaced or is being rebuilt, "; } else { $crit_count++; $output .= "Bus $bus, Enclosure $enclosure, Disk $disk is critical, "; } } } # end of section if ( $_ =~ m/^\s*$/) { $disk_line=0; } } close (NAVICLIOUT); if ($disk_ok_count eq 0) { print "No disk were founded !\n"; $state = 'UNKNOWN'; } elsif ($crit_count > 0) { $state='CRITICAL'; } elsif ($warn_count > 0 || $hotspare_count eq 0) { $state='WARNING'; } else { $state='OK'; } $output .= $disk_ok_count." physical disks are OK. ".$hotspare_count." Hotspares are ready."; print $output."\n"; exit $states{$state}; } # check_cache(); # check state of the read and write cache sub check_cache { my $read_state = 0; my $write_state = 0; my $write_mirrored_state = 0; my $crit_count = 0; my $warn_count = 0; $state = 'UNKNOWN'; if ($secure eq 0 ) { open (NAVICLIOUT ,"$NAVICLI -h $opt_host getcache |"); } if ($secure eq 1 ) { open (NAVICLIOUT ,"$NAVISECCLI -User $opt_user -Password $opt_password -Scope 0 -h $opt_host getcache |"); } while () { # check for cache if( $_ =~ m/^SP Read Cache State\s+(\w+)/) { $read_state = $1; if ($read_state =~ m/Enabled/) { $output .= "Read cache is enable, "; } else { $output .= "Read cache is not enable ! "; $warn_count++; } } elsif ( $_ =~ m/^SP Write Cache State\s+(\w+)/) { $write_state = $1; if ($write_state =~ m/Enabled/) { $output .= "Write cache is enable, "; } else { $output .= "Write cache is not enable ! "; $crit_count++; } } elsif ( $_ =~ m/^Write Cache Mirrored\:\s+(\w+)/) { $write_mirrored_state = $1; if ($write_mirrored_state =~ m/YES/) { $output .= "Write cache mirroring is enable."; } else { $output .= "The Write cache mirroring is not enable !"; $crit_count++; } } } close (NAVICLIOUT); if ( !defined($output) ) { print "No output from the command getcache !\n"; $state = 'UNKNOWN'; exit $states{$state}; } elsif ($crit_count > 0) { $state='CRITICAL'; } elsif ($warn_count > 0 ) { $state='WARNING'; } else { $state='OK'; } print $output."\n"; exit $states{$state}; } # check_faults(); # check state of the different faults # only works with naviseccli sub check_faults { $state = 'UNKNOWN'; if ($secure eq 0 ) { print "The check of the faults only works with Naviseccli. Please provide user and password with -u and -p options !\n"; exit $states{$state}; } if ($secure eq 1 ) { open (NAVICLIOUT ,"$NAVISECCLI -User $opt_user -Password $opt_password -Scope 0 -h $opt_host Faults -list |"); } while () { # check for faults on the array if( $_ =~ m/^The array is operating normally/) { $state='OK'; $output .= $_ ; close (NAVICLIOUT); print $output."\n"; exit $states{$state}; } else { $state='CRITICAL'; $output .= $_ ; } } close (NAVICLIOUT); if ( !defined($output) ) { print "No output from the command Faults -list !\n"; $state = 'UNKNOWN'; exit $states{$state}; } print $output."\n"; exit $states{$state}; } # check_portstate(); # check port state of the sp`s sub check_portstate { my $sp_section = 0; my $sp_line = 0; my $portstate_line = 0; my $error_count = -1; my ($port_id,$enclosure,$disk) = 0; $state = 'UNKNOWN'; if ($secure eq 0 ) { open (NAVICLIOUT ,"$NAVICLI -h $opt_host getall -hba |"); } if ($secure eq 1 ) { open (NAVICLIOUT ,"$NAVISECCLI -User $opt_user -Password $opt_password -Scope 0 -h $opt_host getall -hba |"); } while () { # check for port lines if ($_ =~ m/SPPORT/ ) { $sp_section = 1; } # check for requested SP if( $_ =~ m/^SP\sName:\s+SP\s$opt_sp/ ) { $sp_line = 1; } # check for requested port id if ($opt_port >=0) { if( $_ =~ m/^SP\sPort\sID:\s+($opt_port)$/) { $port_id = $1; $portstate_line = 1; $error_count = 0; } } else { ### if( $_ =~ m/^SP\sPort\sID:\s+($opt_port)$/) { if( $_ =~ m/^SP\sPort\sID:\s+(\d+)$/) { $port_id = $1; $portstate_line = 1; $error_count = 0; } } if ($sp_section == 1 && $sp_line == 1 && $portstate_line == 1) { # check for Link line if( $_ =~ m/^Link\sStatus:\s+(.*)$/) { my $status = $1; if ($status =~ m/Up/) { $output .= "SP $opt_sp Port: $port_id, Link: $status, "; } else { $output .= "SP $opt_sp Port: $port_id, Link: $status, "; $error_count++; } } # check for Link line ### check for Port line if( $_ =~ m/^Port\sStatus:\s+(.*)$/) { my $status = $1; if ($status =~ m/Online/) { $output .= "State: $status, "; } else { $output .= "State: $status, "; $error_count++; } } # check for Connection Type if( $_ =~ m/^Connection\sType:\s+(.*)$/) { my $type = $1; $output .= "Connection Type: $type. "; } # end of section if ( $_ =~ m/^\s*$/) { $portstate_line = 0; ### $sp_section = 0; if ($opt_port >=0 ) { $sp_section = 0; } $sp_line = 0; } } } close (NAVICLIOUT); if ($error_count == 0) { $state='OK'; } elsif ($error_count == -1) { $state='UNKNOWN'; $output = 'UNKNOWN: specified port not found '.$opt_port; } else { $state='CRITICAL'; } print $output."\n"; exit $states{$state}; } # check_hbastate(); # check hba and path states for specific client sub check_hbastate { $state = 'UNKNOWN'; my $hba_node; my $hba_node_line = 0; my $hba_section = 0; my $hba_port_section = 0; my $hba_port_count = 0; my $hba_uid = ""; my $error_count = 0; my $output = ""; if ($secure eq 0 ) { open (NAVICLIOUT ,"$NAVICLI -h $opt_host getall -hba |"); } if ($secure eq 1 ) { open (NAVICLIOUT ,"$NAVISECCLI -User $opt_user -Password $opt_password -Scope 0 -h $opt_host getall -hba |"); } while () { if ($_ =~ m/Information\sabout\seach\sHBA/) { $hba_section = 1; $hba_port_section = 0; $hba_node_line = 0; } if ($hba_section == 1) { if ($_ =~ m/^HBA\sUID:\s+((\w+:?)+)/i) { $hba_uid=$1; } if ($_ =~ m/^Server\sName:\s+($opt_node)/i) { $hba_node = $1; $hba_node_line = 1; } if ($_ =~ m/Information\sabout\seach\sport\sof\sthis\sHBA/) { $hba_section = 0; $hba_port_section = 1; } } if ($hba_port_section && $hba_node_line) { if ($_ =~ m/SP\sName:\s+(\w+\s+\w+)/) { $output .= "$hba_uid connected to: $1, "; } if ($_ =~ m/SP\sPort\sID:\s+(\d+)/) { $output .= "port: $1, "; } if ($_ =~ m/Logged\sIn:\s+(YES)/) { $output .= "Logged in: $1; "; $hba_port_count++; } elsif ($_ =~ m/Logged\sIn:\s+(\w+)/) { $output .= "Logged in: $1;
"; $error_count++; } } } close (NAVICLIOUT); if ($error_count == 0 && $hba_port_count == $opt_pathcount) { $state='OK'; } elsif (lc($opt_node) ne lc($hba_node) ) { $state='UNKNOWN'; $output = 'UNKNOWN: specified node not found '.$opt_node; } elsif ($hba_port_count != $opt_pathcount) { $output .= " error in pathcount from client to SAN: suggested $opt_pathcount detected $hba_port_count"; $state='CRITICAL'; } elsif ($error_count != 0 && $hba_port_count == $opt_pathcount) { $output .= " Error in Configuration, one path not connected !"; $state='CRITICAL'; } print $opt_node."
".$output."\n"; exit $states{$state}; } # print_help($level, $msg); # prints some message and the POD DOC sub print_help { my ( $level, $msg ) = @_; $level = 0 unless ($level); pod2usage( { -message => $msg, -verbose => $level, -noperldoc => 1 } ); exit( $states{UNKNOWN} ); } 1; __END__ =head1 NAME check_emc_clariion.pl - Checks EMC SAN devices for NAGIOS. =head1 SYNOPSIS check_emc_clariion.pl -h | --help check_emc_clariion.pl -H -t check_emc_clariion.pl -H -u -p -t =head1 DESCRIPTION B receives the data from the emc devices via Navicli or Naviseccli if user and password are provided. =head1 OPTIONS =over 8 =item B<-h> Display this helpmessage. =item B<-H> The hostname or ipaddress of the emc storage processor device. =item B<-u> The user used to connect to the emc storage processor device with Naviseccli. You must use this option with -password ! =item B<-p> The password of the user used to connect to the emc storage processor device with Naviseccli. =item B<-t> The check type to execute: =back =head2 TYPES the following checks are currently available sp - check the status of the storage processors disk - check the status of the physical disks attached in the DAE`s cache - check the status of the read and write cache faults - Report the different faults on the array portstate - check the status of the FC ports in the SP`s hbastate - check the connection state of the specified node =head3 TYPE OPTIONS =head4 sp =over 8 =item B<--sp> The storageprocessor to check e.g. A or B =back =head4 portstate =over 8 =item B<--sp> The storageprocessor to check e.g. A or B =item B<--port> The port ID to check e.g. 0 or 1 or 0, 1, 2 or 3 for Clariion CX3-80 - if not specified, all ports are checked =back =head4 hbastate =over 8 =item B<--node> The node name to check out of navisphere =item B<--paths> The number of available FC Paths from the client to the SAN Infrastructure e.g. 2 =cut =back =head1 VERSION $Id$ =head1 AUTHOR NETWAYS GmbH, 2008, http://www.netways.de. Written by Michael Streb . Please report bugs through the contact of Nagios Exchange, http://www.nagiosexchange.org.