#!/usr/bin/perl

##################################################################################################################
# Description : Check Hardware Health by ssh on Fortigate devices
# Date : 11 March 2016
# Author : Fabrice LE DORZE  
# Licence : GPL - http://www.fsf.org/licenses/gpl.txt
#
##################################################################################################################

use strict;
use Net::OpenSSH;
use Getopt::Long;

my $PROGNAME=`basename $0`;
my %CODES=(
0 => 'OK',
1 => 'WARNING',
2 => 'CRITICAL',
3 => 'UNKWOWN');

#-----------------------------------------------------
# Usage function
#-----------------------------------------------------
sub Print_Usage() {
	print <<USAGE;

Usage: $PROGNAME -H <host> [-d] [-u <user>] [-p <password>] [-P <prompt>] [-t timeout] [-c <criticity_code>] [-r <regexp>] [-e]

USAGE
}

#-----------------------------------------------------
# Help function
#-----------------------------------------------------
sub Print_Help() {
	print <<HELP;

This plugin execute 'execute sensor list' on Fortigate devices to check Hardware Health
HELP
	Print_Usage;
        print <<HELP;
Options :	
	-H <hostname> : the hostname.
	-u <user> :  user to connect to the host.
	-p <password> :  password to connect to the host.
        -r <regexp>  : to select hardware items
        -e : to exclude hardware items from regexp above
        -c <criticity> : Nagios status. Default is 1 (WARNING) 
        -P <prompt> : prompt to wait for once connected. Default is '<.*>';
        -t <timeout> : timeout. Default is 10s
        -d : debug mode


 Example :
$0 -H fw -u admin -p toto -r fan

        
HELP
	exit 3;
}

#-----------------------------------------------------
# Print debug
#-----------------------------------------------------
sub Debug
{
    my $debug=shift;
    return unless ($debug);
    open(DEBUG,"<$::input_log");
    while (<DEBUG>)
    {
        print $_;
    }
    close DEBUG;
}

#-----------------------------------------------------
# Get user-given variables
#-----------------------------------------------------
my ($help, $host, $user, $password, $timeout, $command, $prompt, $criticity, $debug, $regexp, $exclude);
Getopt::Long::Configure ("bundling");
GetOptions (
'H=s' => \$host,
'u=s' => \$user,
'p=s' => \$password,
'C=s' => \$command,
'c=s' => \$criticity,
'd' => \$debug,
'r=s' => \$regexp,
'e' => \$exclude,
't=s' => \$timeout,
'P=s' => \$prompt,
'h' => \$help
);

($help) and Print_Help;
($criticity) or $criticity=2;

print "\nOption missing.\n" and Print_Help unless ($host && $user && $password);
print "\n-e implies -r" and Print_Help if ($exclude && !$regexp);

#-----------------------------------------------------
# Execute command
#-----------------------------------------------------
my $code=0;
$timeout=10 unless $timeout;
$prompt="<.*>" unless ($prompt);
my @a=getpwuid($<);
my $whoami=$a[0];
our $input_log="/tmp/ssh.$$";

# Connect
my @opts=('-o' => 'StrictHostKeyChecking no');
if ($debug)
{
      $Net::ssh::debug |= 16;
      @opts=( @opts, '-v');
}
open my $stderr_fh, '>>', "/dev/null";
my %params = ( 'user'=>$user, ssh_cmd=>'/usr/bin/ssh', timeout=>$timeout, master_opts => \@opts, default_stderr_fh => $stderr_fh);
%params = ( %params, 'password'=>$password) if ($password);
my $ssh;

$ssh = Net::OpenSSH->new($host,%params);
unless ($?==0 and $ssh)
{
    print "$CODES{3} :";
    print $ssh->error."\n";
    exit 3;
}

# Execute command
my $command="execute sensor list";
my @results;
@results = $ssh->capture($command);
unless ($#results>-1)
{
    print "$CODES{3} :could not get result of 'execute sensor list' command\n";
    exit 3;
}

#-----------------------------------------------------
# Close Connexion
#-----------------------------------------------------
kill 9, $ssh->get_master_pid;

#-----------------------------------------------------
# Parse command result
#-----------------------------------------------------
# Cleanup
map {s/\r|\n//g} @results;
map {s/\s+/ /g} @results;
my @defaults;
my @details;
my @perfs;
my ($hostname)=($results[0]=~/(^.*) # 1/);
$hostname=($hostname ? "on ".$hostname : "");
$results[0]=~s/(^.*) # 1/1/;

foreach my $line (@results)
{ 
    next unless ($line =~ /^\d+.*alarm/);
    if ($regexp)
    {
        # Skip if match exclude regexp
        if ($exclude)
        {
           next if ($line=~/$regexp/i);
        }
        else
        {
           next unless ($line=~/$regexp/i);
        }
    }
    my ($item,$alarm)=($line=~/\d+\s(.*)\s+alarm=(\d)/);
    my ($value)=($line=~/.*value=([^\s]+)/);

    if ($alarm!=0)
    {
        $item="'$item'";
        $item.=" alarm=$alarm";
        $item.=" value=$value" if($value);
        push @defaults, $item;
    }
    push @perfs, "'$item'=$value" if ($value);
    push @details, $line;
}

#-----------------------------------------------------
# Print status
#-----------------------------------------------------
if (@defaults)
{
    $code=$criticity;
    print "$CODES{$code}, Faulty Hardware $hostname: " . join(", ",@defaults);
} 
else
{
    print "$CODES{$code} : Hardware NORMAL $hostname, see details.";
}
print "\n".join("\n",@details)."|".join(" ",@perfs);

#-----------------------------------------------------
# Cleanup
#-----------------------------------------------------
unlink $input_log;

exit $code;
