File check_infortrend of Package monitoring-plugins-infortrend

#!/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);
openSUSE Build Service is sponsored by