#!/usr/bin/env perl
# IBM(c) 2017 EPL license http://www.eclipse.org/legal/epl-v10.html
use Fcntl qw(:DEFAULT :flock);
use Time::HiRes qw(sleep);
use File::Path;
use IO::Socket;
BEGIN {
    $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr';
}
my $sleepint = int(rand(10)); #Stagger start to avoid overwhelming conserver/xCATd
my ($lockfd, $bmcip);
my $username = 'root';
my $password = '0penBmc';
my $node     = $ARGV[0];

use constant CONSOLE_LOCK_FILE => "/tmp/xcat/consolelock";
use constant CONSOLE_LOCK_DIR => "/tmp/xcat";

sub acquire_lock {
    umask 0077;
    mkpath(CONSOLE_LOCK_DIR);
    print "Acquiring startup lock...";
    unless (sysopen($lockfd, CONSOLE_LOCK_FILE, O_WRONLY | O_CREAT)) {
        print "Unable to open file ".CONSOLE_LOCK_FILE."\n";
        sleep(15);
        exit 1;
    }
    unless (flock($lockfd, LOCK_EX)) {
        print "Unable to lock file ".CONSOLE_LOCK_FILE."\n";
        close($lockfd);
        sleep(15);
        exit 1;
    }
    print "done\n";
    unless (syswrite($lockfd, $$, length($$))) {
        print "Unable to write file ".CONSOLE_LOCK_FILE."\n";
        close($lockfd);
        sleep(15);
        exit 1;
    }
}

sub release_lock {
    flock($lockfd, LOCK_UN);
    close($lockfd);
}


use lib "$::XCATROOT/lib/perl";
require xCAT::Client;

sub getans {
    my $rsp = shift;
    if ($rsp->{node}) {
        $bmcip = $rsp->{node}->[0]->{bmcip}->[0];
        $username = $rsp->{node}->[0]->{username}->[0];
        $password = $rsp->{node}->[0]->{passwd}->[0];
        if (exists $rsp->{node}->[0]->{error}) {
            my $error = $rsp->{node}->[0]->{error}->[0];
            print "$error\n";
        }
    }
}
my $cmdref = {
    command   => ["getopenbmccons"],
    arg       => ["text"],
    noderange => [ $ARGV[0] ]
};
acquire_lock();
# avoid of congestion
sleep(0.1);
release_lock();
xCAT::Client::submit_request($cmdref, \&getans);

until (($username or $password) and $bmcip ) {
    #Let other clients have a go
    $sleepint = 10 + int(rand(20));
    print "Console not ready, retrying in $sleepint seconds (Ctrl-e,c,o to skip delay) \n";
    sleep ($sleepint);
    acquire_lock();
    sleep(0.1);
    release_lock();
    xCAT::Client::submit_request($cmdref, \&getans);
}

my $isintel = 0;
my $sleepint;
my $rc;
 
my $sshport = 2200;
if ($ENV{SSHCONSOLEPORT}) {
    $sshport= $ENV{SSHCONSOLEPORT};
}

#check if sshport is up 
my $sock = IO::Socket::INET->new(
    PeerAddr => $bmcip,
    PeerPort => $sshport,
    Proto => "tcp",
    Timeout => 10
    );
while (!defined($sock)) {
    $sleepint = 10 + int(rand(20));
    print "No BMC active at IP $bmcip, retrying in $sleepint seconds (Hit Ctrl-E,c,o to skip)\n";
    sleep ($sleepint);
    acquire_lock();
    sleep(0.1);
    release_lock();
    $sock = IO::Socket::INET->new(
        PeerAddr => $bmcip,
        PeerPort => $sshport,
        Proto => "tcp",
        Timeout => 10
        );
}
$sock->close();


# To automatically connect to the console without the need to send over the ssh keys, 
# ensure sshpass is installed on the Management and/or Service Nodes.
print "Unable to open console.  If BMC pings, ensure sshpass is installed or ssh keys have been configured on the BMC.\n";
if (-x '/usr/bin/sshpass') {
    exec "/usr/bin/sshpass -p $password ssh -p $sshport -l $username -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $bmcip";
} else {
    exec "ssh -p $sshport -l $username -o PasswordAuthentication=no -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $bmcip";
}



