#!/usr/bin/perl # \file check_infortrend # \author Bill Hill # \date November 2008 # \version $Id: check_infortrend,v 1.1 2008/12/01 08:58:25 bill Exp $ # \par # Address: # MRC Human Genetics Unit, # Western General Hospital, # Edinburgh, EH4 2XU, UK. # \par # Copyright (C) 2008 Medical research Council, UK. # # 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., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA. # \brief Nagios plugin to check the status of an Infortrend storage # array. This script has been hacked to work with the telnet # interface of the Infortrend arrays. # \todo - # \bug None known. use strict; use warnings; use File::Spec::Unix; use Getopt::Long; use Net::Telnet; my %statusTab = ( 'OK' => 0, 'WARNING' => 1, 'CRITICAL' => 2, 'UNKNOWN' => 3 ); my %statusStrTab = ( 0 => "OK", 1 => "WARNING", 2 => "CRITICAL", 3 => "UNKNOWN" ); my $arrayname = 'array'; my $arraypwd = ''; my $debug = 0; my $drvCnt = 0; my $drvOkCnt = 0; my @drvStatus; my $expDrvCnt = 16; my $maxDrvCnt = 16; my $esc = "\x1b"; my $help = 0; my $mesg = ''; my $model = "T6100F"; # Known models are T6100F, PV610F and A24F-R2430 my $progname = 'check_infortrend'; my $state = $statusTab{'UNKNOWN'}; sub makeExit { my $msg = $_[0]; print "$statusStrTab{$state} - array $arrayname"; if(length($msg) > 0) { print " ($msg)"; } print ".\n"; exit($state); } sub showUsage { print STDERR "Nagios plugin which checks the status of an infortrend\n"; print STDERR "EonStor RAID array.\n"; print STDERR "Usage: $progname [options]\n"; print STDERR "where the valid options are\n"; print STDERR " -h, --help Output this usage information.\n"; print STDERR " -d, --debug Debug level.\n"; print STDERR " -a, --array The name of the infortrend array.\n"; print STDERR " -p, --password The password for the array.\n"; print STDERR " -m, --model The model of array (known models are:\n"; print STDERR " T6100F, PV610F and A24F-R2430.\n"; print STDERR " -e, --expected The number of drives expected.\n"; } sub initialScreenSleep() { my $ary = $_[0]; my $cnt = 5; for(my $idx = 0; $idx < $cnt; ++$idx) { $ary->put($esc); sleep(1); } } sub initialScreenGoble() { my $ary = $_[0]; my $cnt = 4; my $irs; if($debug > 0) { print "selecting initial screen\n"; } $irs = $ary->input_record_separator("Enter:Main Menu"); for(my $idx = 0; $idx < $cnt; ++$idx) { $ary->put($esc); $ary->getlines(Timeout => 1); } $ary->input_record_separator($irs); } sub initialScreen() { my $ary = $_[0]; if(($model eq "T6100F") || ($model eq "PV610F")) { &initialScreenSleep($ary); } elsif ($model eq "A24F-R2430") { &initialScreenGoble($ary); } } sub selectVT100Interface() { my $ary = $_[0]; my $down = "\x1bOB"; $ary->print(''); sleep(1); $ary->put($esc); sleep(1); $ary->put($down); sleep(1); } sub getDrvStatus() { my $arrayname = $_[0]; my $arraypwd = $_[1]; my $eol = "\x1b\x5b"; my $rec; my $idx = 0; my $drvIdx = 0; if($debug > 0) { print "telnet $arrayname\n"; } my $ary = new Net::Telnet(Errmode => "return", Timeout => 5, Prompt => '/.*/') or &makeExit("can't connect to array $arrayname"); $ary->open($arrayname) or &makeExit("can't connect"); if($debug > 0) { $ary->dump_log(); print "waiting for password prompt\n"; } $ary->waitfor('/Password:.*/') or &makeExit("timed out"); $ary->print($arraypwd); if($debug > 0) { print "initial password given\n"; } &initialScreen($ary); &selectVT100Interface($ary); $ary->print(''); # Send a return to get to the main menu and re-login $ary->waitfor('/(Enter)|(Input) Password:.*/') or &makeExit("timed out"); $ary->print($arraypwd); $ary->waitfor('/.*view and edit .*vent logs.*/') or &makeExit("timed out"); $ary->buffer_empty(); # Empty the input buffer $ary->put('D'); # Send a 'D' for the drives menu. my $rs = $ary->rs($eol); while(($drvIdx < $maxDrvCnt) && ($idx < 300)) { if($debug > 0) { print "== $idx == $drvIdx ==\n"; print "== $rec ==\n"; } $rec = $ary->getline() or &makeExit("timed out"); $_ = $rec; if(($model eq "T6100F") || ($model eq "PV610F")) { # Parse the output looking for lines like: # | 11| 715399|300MB| 1| ON-LINE|Seagate ST3750640AS | if(/(\x0e.\x0f)?\s*(\d+)\x0e.\x0f\s*\w*\x0e.\x0f\s*\w*\x0e.\x0f\s*\w+\x0e.\x0f\s*([A-Z_\-]+)\s*\x0e.\x0f\s*.*\s*(\x0e.\x0f)?/) { if($debug > 0) { print "MATCH == $2 == $3 ==\n"; } if($drvIdx + 1 == $2) { $drvStatus[$drvIdx] = $3; ++$drvIdx; } } if(($drvIdx % 8) == 7) { $ary->put("\x0e"); # Send ^N for the next screen. $ary->put("\x0c"); # Send a ^L to redraw the whole of the new screen. } ++$idx; } elsif($model eq "A24F-R2430") { # Parse the output looking for lines like: # | │ 2│ 2│ 1│ 953609│300MB│ 0│ON-LINE │Hitachi HDS721010KLA330 │ if(/(\x0e.\x0f\s*\x0e.\x0f)?\s*(\d+)\x0e.\x0f\s*\w*\x0e.\x0f\s*\w*\x0e.\x0f\s*\w*\x0e.\x0f\s*\w*\x0e.\x0f\s*\w+\x0e.\x0f\s*([A-Z_\-]+)\s*\x0e.\x0f\s*.*\s*(\x0e.\x0f)?/) { if($debug > 0) { print "MATCH == $2 == $3 ==\n"; } if($drvIdx + 1 == $2) { $drvStatus[$drvIdx] = $3; ++$drvIdx; } } if(($drvIdx % 8) == 7) { $ary->put("\x0e"); # Send ^N for the next screen. } ++$idx; } } $ary->rs($rs); &initialScreen($ary); $ary->close(); return($drvIdx); } ## Main ## # Parse command line options Getopt::Long::config('no_ignore_case'); GetOptions ( "d|debug=i" => \$debug, "e|expected=i" => \$expDrvCnt, "h|help" => \$help, "a|array=s" => \$arrayname, "m|model=s" => \$model, "p|password=s" => \$arraypwd ); if(($model ne "T6100F") && ($model ne "PV610F") && ($model ne "A24F-R2430")) { $help = 1; } # Show usage and exit if appropriate if($help) { &showUsage(); &makeExit("usage"); } # Get status of the physical drives if(($model eq "T6100F") || ($model eq "PV610F")) { $maxDrvCnt = 16; } elsif($model eq "A24F-R2430") { $maxDrvCnt = 24; } $drvCnt = &getDrvStatus($arrayname, $arraypwd); if($debug > 1) { print("== $drvCnt ==\n"); } for(my $idx = 0; $idx < $drvCnt; ++$idx) { $_ = $drvStatus[$idx]; if(m/ON-LINE/) { ++$drvOkCnt; } } # Decide if there is an error or all is OK. if($expDrvCnt != $drvCnt) { $state = $statusTab{'CRITICAL'}; $mesg = "only $drvCnt/ $expDrvCnt physical drives found"; } elsif($drvCnt != $drvOkCnt) { $state = $statusTab{'CRITICAL'}; $mesg = "only $drvOkCnt / $drvCnt physical drives on-line"; } else { $state = $statusTab{'OK'}; $mesg = "$drvOkCnt / $drvCnt physical drives OK"; } &makeExit($mesg);