#!/usr/bin/perl -w
#
# Nagios plugin to check cluster status on Solaris.
# Copy to Nagios libexec directory (requires utils.pm from Nagios plugins).
#
# $Id: check_scstat.pl,v 1.1 2009/02/10 kaunt Exp $
#
# Copyright (C) 2006-2008  Thomas Kaun / Telefonica o2 Germany GmbH & Co OHG
#
# 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.
#

##################################################################################
### loading modules
##################################################################################

use strict;
use lib "/usr/local/nagios/libexec";
use utils qw(%ERRORS);

##################################################################################
### declarations
##################################################################################

my $stat = ""; my $perf = "";
my @line,my @sline,my @warning,my @critical,my @tmp,my $arg;
my $a = 0; my $warn = 0; my $crit = 0; my $state = 0;my $firstnode = 0;
my $hosts = 0;my $hostnok = 0;my $hostok = 0;
my $path = 0; my $pathok = 0; my $pathnok = 0;
my $qdef = 1000; my $qneed = 1000; my $qok = 0;
my $group = 0; my $groupok = 0; my $groupsw = 0; my $lastgroup = "";
my $res = 0; my $resok = 0; my $ressw = 0; my $lastres = ""; my $isonline = 0; my $risonline = 0; my $gisonline = 0;
my $ipmp = 0;my $ipmpnok = 0;my $ipmpok = 0;

##################################################################################
### parsing arguments
##################################################################################

foreach $arg (@ARGV) {
	if ($arg eq "-w") {
		 @warning = split (/,/, $ARGV[$a+1]);
	}
	if ($arg eq "-c") {
		 @critical = split (/,/, $ARGV[$a+1]);
	}
	if ($arg eq "-h") {
		print "\nusage: ./check_scstat.pl -w <w1,w2,w3> -c <c1,c2,c3>\n";
		print "\nOptions: -w <w1,w2,w3> Warning if number of <Hosts,Paths,IPMP-Paths> fails\n";
		print "         -c <c1,c2,c3> Critical if number of <Hosts,Paths,IPMP-Paths> fails\n";
		print "         -h print this help\n";
		print "Example: ./check_scstat.pl -w 1,1,1 -c 1,2,2\n\n";
		print "Critical as well if: less quorums ok than needed or\n";
		print "                     a resource or resource group is not online\n";
		print "Warning as well if : less quorums ok than defined or\n";
		print "                     a resource or resource group is online but not on the primary host\n";
		print "\n";
		exit;
	}
	$a++;
}

##################################################################################
### gather scstat informations
##################################################################################

open (SCSTAT, "/usr/cluster/bin/scstat 2>/dev/null|");
my @sc = grep { $_ =~ ( /^$/ || /^-/ || /^      / ) } <SCSTAT>;
close SCSTAT;

##################################################################################
### grep content into arrays
##################################################################################

my @cn = grep (/Cluster node: /,@sc);
my @tp = grep (/Transport path: /,@sc);
my @qv = grep (/Quorum votes possible/,@sc);
my @qn = grep (/Quorum votes needed/,@sc);
my @qp = grep (/Quorum votes present/,@sc);
my @vo = grep (/ votes:/,@sc);
my @rg = grep (/^ +Group:/,@sc);
my @rs = grep (/Resource: /,@sc);
my @mp = grep (/IPMP Group: /,@sc);

##################################################################################
### main
##################################################################################

# Cluster nodes ##################################################################
chomp (@cn);
$hosts = ($#cn + 1);
foreach (@cn) {
	@line = split(/ +/, $_);
	if ($line[4] =~ /Online/) {
		$hostok++;
	}
	else {
		$stat = ($stat.$line[3]." FAILED, ");
		$hostnok++;
	}
}

# Transport path ##################################################################
chomp (@tp);
$path = ($#tp + 1);
foreach (@tp) {
	@line = split(/ +/, $_);
	if ( $line[$#line] =~ /online/) {
		$pathok++;
	}
	else {
		$stat = ($stat.$line[3]."-".$line[4]." ".$line[$#line].", ");
		$pathnok++;
	}
}

# Quorum votes possible ##################################################################
chomp (@qv);
@tmp = split(/ +/, $qv[0]);
$qdef = $tmp[4];

# Quorum votes needed ##################################################################
chomp (@qn);
@tmp = split(/ +/, $qn[0]);
$qneed = $tmp[4];

# Quorum votes present ##################################################################
chomp (@qp);
@tmp = split(/ +/, $qp[0]);
$qok = $tmp[4];

# Quorum votes online ##################################################################
chomp (@vo);
foreach (@vo) {
	if (!($_ =~ /Online/)) {
		@line = split(/ +/, $_);
		$stat = ($stat."vote ".$line[3]." ".$line[6].", ");
	}
}

# Resource groups ##################################################################
chomp (@rg);
foreach $_ (@rg) {
	@line = split(/ +/, $_);
	if ($lastgroup ne $line[2]) {
		$group++;$gisonline = 0;$firstnode = 1;
		$lastgroup = $line[2];
		@tmp = grep (/$line[2]/,@rg);
		foreach (@tmp) {
			@sline = split(/ +/, $_);
			if ($gisonline == 0) {
				if ($sline[4] eq "Online") {
					$gisonline = 1;
					if ($firstnode == 1) {
						$groupok++;
					}
					else {
						$groupsw++;
						$stat = ($stat.$sline[2]." SWITCHED, ");
					}
				}
			}
			$firstnode = 0;
		}
		if ($gisonline == 0) {
			$stat = ($stat.$line[2]." OFFLINE, ");
		}
	}

}


# Resources ##################################################################
chomp (@rs);
foreach (@rs) {
	@line = split(/ +/, $_);
	if ($lastres ne $line[2]) {
		$res++;$risonline = 0;$state = 0;$firstnode = 1;
		$lastres = $line[2];
		@tmp = grep (/$line[2]/,@rs);
		foreach (@tmp) {
			@sline = split(/ +/, $_);
			if ($risonline == 0) {
				if ($sline[4] eq "Online") {
					if ($sline[$#sline] =~ /online/i) {
						$risonline = 1;
						if ($firstnode == 1) {
							$resok++;
						}
						else {
							$ressw++;
						}
						if ($sline[$#sline] ne "online.") {
							$stat = ($stat."check ".$line[2].", ");
						}
					}
					else {
						$stat = ($stat.$sline[2]." ".$sline[5].", ");
						$state = 1;
					}
				}
			}
			$firstnode = 0;
		}	
		if (($risonline == 0) and ($state == 0)) {
			$stat = ($stat.$line[2]." OFFLINE, ");
		}
	}
}

# IPMP Groups ##################################################################
chomp (@mp);
foreach (@mp) {
	$ipmp++;
	@line = split(/ +/, $_);
	if (($line[5] =~ /Online/) && ($line[7] =~ /Online/)) {
		$ipmpok++;
	}
	else {
		$ipmpnok++;
		$stat = ($stat.$line[3]."-".$line[4]." not ok, ");
	}
}

$perf = ($hostok."/".$hosts." Hosts, ".$pathok."/".$path." Paths, ".$qok."/".$qneed."/".$qdef." Quorum, ".$groupok."/".$groupsw."/".$group." Groups, ".$resok."/".$ressw."/".$res." Resources, ".$ipmpok."/".$ipmp." IPMP");

##################################################################################
### generating return code and message
##################################################################################

if (($hostnok >= $critical[0]) || ($pathnok >= $critical[1]) || ($qok < $qneed) || (($group - ($groupok + $groupsw)) > 0) || (($res - ($resok + $ressw)) > 0) || ($ipmpnok >= $critical[2])) {
#	print "CLUSTER CRITICAL - $stat|$perf\n";
	print "$stat|$perf\n";
	exit $ERRORS{'CRITICAL'};
}
elsif (($hostnok >= $warning[0]) || ($pathnok >= $warning[1]) || ($qok < $qdef) || ($groupsw > 0) || ($ipmpnok >= $warning[2])) {
#	print "CLUSTER WARNING - $stat|$perf\n";
	print "$stat|$perf\n";
	exit $ERRORS{'WARNING'};
}
print "CLUSTER OK ! $stat|$perf\n";
exit $ERRORS{'OK'};
