#!/usr/bin/perl -w
use strict;
use Getopt::Std;
use vars qw($opt_h);

getopts('h');

my $result = '';
my $status = '0';
my ($bbustate);

# Set the warning and error thresholds
my $error = 30;
my $warning = 40;
my $reverse_error = 100;

# Usage Instructions -h
if ( $opt_h ) {
	print "Usage: $0 \n";
	print "This is a netsaint script and it prints the battery % info for lsi, 3ware, and areca raid cards. \n";
	print "Example outputs may be OK: BBU: Charged (55%), WARNING: BBU: Learning (55%), WARNING: BBU: Charging (6%) CRITICAL: BBU: Charged (20%) \n";
	exit;
}

# Tool to check which kind of raid were dealing with currently supports lsi, areca and 3ware raid cards.
my $lspci = "/usr/bin/lspci";
# lets check and make sure we can execute LSPCI before we try to use it and if not CRITIAL!
(-e $lspci) || exitreport('2',"error: lspci does not exist");

my $raid_check_cmd = "$lspci 2>/dev/null | /bin/grep -i raid";
my $raid_check_output = qx($raid_check_cmd);

# Sorts based on command above and sends to subroutines
if ( $raid_check_output =~ m/lsi/i) {
	&megacli;
} elsif ( $raid_check_output =~ m/areca/i ) {
	&areca;
} elsif ( $raid_check_output =~ m/3ware/i ) {
	&three_ware;
} elsif ( $raid_check_output =~ m/intel/i ) {
	# we currently only use intel intergraded raid cards.
	$status = '0';
	$result .= "BBU: Intel Raid detected (No BBU)";
} else {
	# No raid card found? Then obviously it does not have a BBU!
	$status = '0';
	$result .= "BBU: No Raid Card Detected";
} # End if raid_check_output

#################### SUBROUTINES ####################

sub exitreport {
	my $status = shift;
	my $message = shift;

	my $result = "OK" if $status == 0; # OK
	$result = "WARNING" if $status == 1; # Warning
	$result = "CRITICAL" if $status == 2; # Critical
	$result = "UNKNOWN" if $status == 3; # Unknown
	print $result . " " . $message . "\n";
	exit $status;
} # End sub exitreport

#################### MEGACLI ####################

sub megacli {
	my $megaclibin = '/usr/sbin/megacli';
	my $megacli = "$megaclibin";
	my $megapostopt = '-NoLog';
	my ($adapters);

	# Some sanity checks that you actually have something where you think megacli is
	(-e $megaclibin)
		|| exitreport('2',"error: $megaclibin does not exist");

	# Get the number of RAID controllers we have
	open (ADPCOUNT, "$megacli -adpCount $megapostopt |")
		|| exitreport('2',"error: Could not execute $megacli -adpCount $megapostopt");

	while (<ADPCOUNT>) {
		if ( m/Controller Count:\s*(\d+)/ ) {
			$adapters = $1;
			last;
		}
	}
	close ADPCOUNT;

	for ( my $adp = 0; $adp < $adapters; $adp++ ) {
			# Get the Battery Back Up state for this adapter
			open (BBUGETSTATUS, "$megacli -AdpBbuCmd -a$adp $megapostopt |")
				|| exitreport('2', "error: Could not execute $megacli -AdpBbuCmd -GetBbuStatus -a$adp $megapostopt");

			my ($bbucharging, $bbufullycharged, $bburelativecharge, $bbulearning, $bbuexitcode, $failed) =  ("", "", "", "", "", "");
			while (<BBUGETSTATUS>) {
				# Charging Status
				if ( m/Charging Status\s*:\s*(\w+)/i ) {
					$bbucharging = $1;
				# Is it fully charged?
				} elsif ( m/Fully Charged\s*:\s*(\w+)/i ) {
					$bbufullycharged = $1;
				# Get Absolute state of charge %
				} elsif ( m/Absolute State of charge\s*:\s*(\w+)/i ) {
					$bburelativecharge = $1;
				# Grab the exit code
				} elsif ( m/Get BBU Status Failed/i ) {
					$failed = "0x01";
				} elsif ( m/Exit Code\s*:\s*(\w+)/i ) {
					$bbuexitcode = $1;
				# Is a learn cycle active?
				} elsif ( m/Learn Cycle Requested\s*:\s*(\w+)/i ) {
					$bbulearning = $1;
				} elsif ( m/Learn Cycle Active\s*:\s*(\w+)/i ) {
					$bbulearning = $1;
				}
			} # End while (<BBUGETSTATUS>)
			close BBUGETSTATUS;
			# if the exit code is not clean - CRITICAL
			if ( $bbuexitcode ne '0x00' or $failed eq '0x01' ) {
				$bbustate = 'NOT FOUND';
				$status = '2';
			# If the battery is charging/discharging check for learn cycle - WARNING
			} elsif ( $bbucharging ne 'None' ) {
				if ( $bbulearning eq 'Yes' ) {
					$bbustate = 'Learning (' . $bburelativecharge . '%)';
				} elsif ( $bbucharging eq 'Discharging' ) {
					$bbustate = 'Discharging (' . $bburelativecharge . '%)';
				} else {
					$bbustate = 'Charging (' . $bburelativecharge . '%)';
				}
				$status = '1';
			# If the battery is not fully charged check for a learn cycle and print Not Charging % - WARNING
			} elsif ( $bbufullycharged ne 'Yes' ) {
				if ( $bbulearning eq 'Yes' ) {
					$bbustate = 'Learning (' . $bburelativecharge . '%)';
					$status = '1';
				} else {
					if ($bburelativecharge <= $error or $bburelativecharge > $reverse_error) {
						$bbustate = 'Not Charging (' . $bburelativecharge . '%)';
						$status = '2';
					} elsif ($bburelativecharge <= $warning) {
						$bbustate = 'Not Charging (' . $bburelativecharge . '%)';
						$status = '1';
					} else {
						$bbustate = 'Not Charging (' . $bburelativecharge . '%)';
					}
				}
			# or else the battery is fully charged, and not in a learn cycle print % - OK
			} else {
				if ($bburelativecharge <= $error or $bburelativecharge > $reverse_error) {
					$bbustate = 'Charged (' . $bburelativecharge . '%)';
					$status = '2';
				} elsif ($bburelativecharge <= $warning) {
					$bbustate = 'Charged (' . $bburelativecharge . '%)';
					$status = '1';
				} else {
					$bbustate = 'Charged (' . $bburelativecharge . '%)';
				}
			}
		$result .= "BBU: $bbustate";
	} # End For

} # End sub megacli

#################### ARECA ####################

sub areca {
	my $cli64 = "/usr/sbin/cli64";
	# lets try to execute it first!
	(-e $cli64) || exitreport('2',"error: cli64 does not exist");

	my $command = qx($cli64 hw info | grep -i -e batt);
	if ($command) {
		my @output = split(' ',$command);
		my ($bburelativecharge) = $output[-1] =~ /(\d+)%/;
		if (grep /Not Installed/, @output) {
			$bbustate = 'Dead (0%)';
			$status = '2';
		} else {
			if ($bburelativecharge <= $error or $bburelativecharge > $reverse_error) {
				$bbustate = 'Charged (' . $bburelativecharge . '%)';
				$status = '2';
			} elsif ($bburelativecharge <= $warning) {
				$bbustate = 'Charged (' . $bburelativecharge . '%)';
				$status = '1';
			} else {
				$bbustate = 'Charged (' . $bburelativecharge . '%)';
			}
		}
	} else {
		$bbustate = 'Not Installed';
		$status = '2'
	}
	$result .= "BBU: $bbustate"
} # End sub areca

#################### 3WARE ####################
# This still needs some work currently even if
# the battery has a backup time of 0 it still
# reports as 100% since it says the battery is OK
# But currently it does work.

sub three_ware {
	my $twcli = "/usr/sbin/tw_cli";
	# lets try to execute it first!
	(-e $twcli) || exitreport('2',"error: twcli does not exist");

	my $command = qx($twcli /c0/bbu show show all);
	my $total_output = $command;
	my @output_array = split("\n",$total_output);
	foreach my $line (@output_array) {
		if ( $line =~ m/BBU Status/ ) {
			my @output = split(' ',$line);
				if ( $output[-1] =~ m/OK/ ) {
					$bbustate = "Charged (100%)";
				} else {
					$bbustate = "Dead (0%)";
					$status = '2';
				}
		}
	}
	$result .= "BBU: $bbustate";
} # End sub 3ware

# Send status and result to sub exitreport
exitreport($status, $result);
