#!/usr/bin/perl -Tw

# Copyright (C) 2006,2008,2009,2016 Peter Palfrader <peter@palfrader.org>
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


# Need to allow /usr/local/bin/tw_cli info c0 u0 status in sudoers:
#
#  nagios          ALL=(ALL) NOPASSWD: /usr/local/bin/tw_cli info c0 u0 status
#

use strict;
use English;
use Getopt::Long;

$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/sbin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

my $TW_CLI = '/usr/local/bin/tw_cli';
my $SVN_REVISION_STRING = '$Rev: 410 $';
my ($SVN_REVISION) = ($SVN_REVISION_STRING =~ /([0-9]+)/);
    $SVN_REVISION  = 'unknown' unless defined $SVN_REVISION;
my $VERSION = '0.0.0.'.$SVN_REVISION;

# nagios exit codes
my $UNKNOWN = -1;
my $OK = 0;
my $WARNING = 1;
my $CRITICAL = 2;

my $params = {
	'no-sudo'    => 0,
	'controller' => 0,
	'unit'       => 0
	};

Getopt::Long::config('bundling');
if (!GetOptions (
	'--help'		=> \$params->{'help'},
	'--version'		=> \$params->{'version'},
	'--verbose'		=> \$params->{'verbose'},
	'--controller=i'	=> \$params->{'controller'},
	'--unit=i'		=> \$params->{'unit'},
	'--no-sudo'		=> \$params->{'no-sudo'},
	)) {
	die ("$PROGRAM_NAME: Usage: $PROGRAM_NAME [--help|--version] [--verbose] [--no-sudo] [--controller=<n>] [--unit=<n>]\n");
};
if ($params->{'help'}) {
	print "$PROGRAM_NAME: Usage: $PROGRAM_NAME [--help|--version] [--verbose] [--no-sudo] [--controller=<n>] [--unit=<n>]\n";
	print "Checks status of 3ware raid arrays.\n";
	exit (0);
};
if ($params->{'version'}) {
	print "nagios-check-raid-3ware $VERSION\n";
	print "nagios check for 3ware raids\n";
	print "Copyright (c) 2006,2008,2009,2016 Peter Palfrader <peter\@palfrader.org>\n";
	exit (0);
};

$SIG{'__DIE__'} = sub {
	print STDERR @_;
	exit $UNKNOWN;
};

unless (-e $TW_CLI) {
	print "Cannot find '$TW_CLI'.\n";
	exit $UNKNOWN;
};

for my $thing (qw{controller unit}) {
	if ($params->{$thing} =~ m/^([0-9]+)$/) {
		$params->{$thing} = $1;
	} else {
		die("Invalid $thing $1.\n");
	}
};

my @command;
push @command, "sudo" if $params->{'no-sudo'};
push @command, ($TW_CLI, 'info', "c$params->{'controller'}", "u$params->{'unit'}", "status");
my $command = join(' ', @command);
print STDERR "Running $command\n" if $params->{'verbose'};
open (TW, "-|", @command) or die ("Cannot run $command: $!\n");
my @tw=<TW>;
close TW;
if ($CHILD_ERROR) { # program failed
	die("$command returned with non-zero exit code: ".($CHILD_ERROR / 256)."\n");
};


my $exit = $UNKNOWN;
my $msg = '';
for my $line (@tw)  {
	chomp $line;
	next if $line =~ /^$/;
	my ($device, $status) = $line =~ m#^(/c[0-9]+/u[0-9]+) status = ([A-Z]+)$#;
	unless (defined($device) && defined($status)) {
		print "Cannot parse line '$line'\n";
		exit $UNKNOWN;
	};
	if ($status eq 'OK' ||
	    $status eq 'VERIFYING') {
		$msg .= ($msg eq '' ? '' : '; '). "$device: $status";
		$exit = $exit > $OK ? $exit : $OK;
	} elsif ($status eq 'REBUILDING') {
		$msg .= ($msg eq '' ? '' : '; '). "$device: $status";
		$exit = $exit > $WARNING ? $exit : $WARNING;
	} elsif ($status eq 'DEGRADED') {
		$msg .= ($msg eq '' ? '' : '; '). "$device: $status";
		$exit = $exit > $CRITICAL ? $exit : $CRITICAL;
	} elsif ($status eq 'OFFLINE') {
		$msg .= ($msg eq '' ? '' : '; '). "$device: $status";
		$exit = $exit > $CRITICAL ? $exit : $CRITICAL;
	} else {
		$msg .= ($msg eq '' ? '' : '; '). "$device: UNKNOWN STATUS '$status'";
		$exit = $exit > $UNKNOWN ? $exit : $UNKNOWN;
	};
};

if ($msg eq '') {
	$msg = "No devices found";
	die ("exit is not UNKNOWN but $exit") if ($exit != $UNKNOWN);
}

print $msg,"\n";
exit $exit;
