#!/usr/bin/perl

##################################################################################################################
# Description : Check Cluster Role on EfficientIP devices
# Version : 1.0
# Date : June 29 2016
# Author : Fabrice LE DORZE  
# Licence : GPL - http://www.fsf.org/licenses/gpl.txt
##################################################################################################################

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

my $PROGNAME=`basename $0`;

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

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

USAGE
}

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

This plugin execute by SSH the command "psql -U root -c \" SELECT member_type,member_name from member where row_enabled='1';\" ness2" on EfficientIP devices
to determine Cluster status
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.
        -c <criticity> : Nagios status. Default is 1 (WARNING) 
        -r <expected role> : Master, HotStandBY or Standalone
        -C <command> : PSQL command. Default is "psql -U root -c \" SELECT member_type,member_name from member where row_enabled='1';\" ness2"
        -P <prompt> : prompt to wait for once connected. Default is '<.*>';
        -t <timeout> : timeout. Default is 10s
        -d : debug mode


 Example :
$0 -H switch -u admin -p toto -C env

        
HELP
	exit 3;
}

my %level=(
0 => 'OK',
1 => 'WARNING',
2 => 'CRITICAL',
3 => 'UNKNOWN'
);

#-----------------------------------------------------
# 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, $role);
Getopt::Long::Configure ("bundling");
GetOptions (
'H=s' => \$host,
'u=s' => \$user,
'p=s' => \$password,
'C=s' => \$command,
'c=s' => \$criticity,
'd' => \$debug,
't=s' => \$timeout,
'P=s' => \$prompt,
'r=s' => \$role,
'h' => \$help
);

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

print "\nOption missing.\n" and Print_Help unless ($host && $user && $password && $role);
print "\nBad role option.\n" and Print_Help unless ($role =~ /^(Master|HotstandBY|Standalone)$/);
$command="psql -U root -c \" SELECT member_type,member_name from member where row_enabled='1';\" ness2" unless ($command);

my %roles=(
'Master'=>'M',
'HotstandBY'=>'B',
'Standalone'=>'S'
);
my %reverse_roles=reverse %roles;

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

# Connect
my @opts=('-o' => 'StrictHostKeyChecking no');
if ($debug)
{
      $Net::ssh::debug |= 16;
      @opts=( @opts, '-v');
}
my %params = ( 'user'=>$user, ssh_cmd=>'/usr/bin/ssh', timeout=>$timeout, master_opts => \@opts);
%params = ( %params, 'password'=>$password) if ($password);
my $ssh;
$ssh = Net::OpenSSH->new($host,%params);
unless ($?==0 and $ssh)
{
    print $ssh->error;
    exit $criticity;
}

# Execute command
my ($hostname)=$ssh->capture('hostname');
chomp $hostname;
my @results;
@results = (@results, $ssh->capture($command));

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

#-----------------------------------------------------
# Parse command result
#-----------------------------------------------------
# Cleanup
my ($line, $state);
my %status;
my @defaults;
my %comments;
for $line (@results)
{ 
    # Skip comment lines
    next if ($line=~/member_type|-------/);
    my ($s,$m)=($line =~/([SMB]) *\| *(.*)/);
    $status{$m}=$s;
}
print Dumper %status if ($debug);
my $erole=$reverse_roles{$status{$hostname}};

#-----------------------------------------------------
# Print status
#-----------------------------------------------------
if ($status{$hostname} ne $roles{$role})
{
    $code=$criticity;
    print "$level{$criticity} : expected role is '$role' but effective role is '$erole'.";
} 
else
{
    print "$level{0} : effective role ($role) is as expected.";
}
print " See details.\n";
map{s/\|/#/g} @results;
print @results;

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

exit $code;
