#!/usr/bin/env perl
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
use strict;
use Fcntl qw(:DEFAULT :flock);

sub get_lock {
    unless (flock(LOCKHANDLE, LOCK_EX | LOCK_NB)) {
        $| = 1;
        print "Acquiring startup lock...";
        flock(LOCKHANDLE, LOCK_EX) or die "Fatal error securing startup lock";
        print "done\n";
    }
    truncate(LOCKHANDLE, 0);
    print LOCKHANDLE $$ . "\n";
}

sub release_lock {
    truncate(LOCKHANDLE, 0);
    flock(LOCKHANDLE, LOCK_UN);
}

BEGIN
{
    use Time::HiRes qw(sleep);
    use File::Path;
    use Fcntl qw(:DEFAULT :flock);
    $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
    umask 0077;
}

my $sleepint;
use lib "$::XCATROOT/lib/perl";
require xCAT::Client;
require xCAT::Utils;
require File::Basename;

my $scriptname = $0;

mkpath("/tmp/xcat/");
unless (sysopen(LOCKHANDLE, "/tmp/xcat/consolelock", O_WRONLY | O_CREAT)) {
    xCAT::Utils::console_sleep(15, "Unable to open lock file");
    exit 0;
}
get_lock();

my $cmdref = {
    command   => ["getcons"],
    arg       => ["text"],
    noderange => [ $ARGV[0] ]
};
use Data::Dumper;
my $dsthost;
my $dstty;
my $speed;

sub getans {
    my $rsp = shift;
    if ($rsp->{node}) {
        $dsthost = $rsp->{node}->[0]->{sshhost}->[0];
        $dstty   = $rsp->{node}->[0]->{psuedotty}->[0];
        $speed   = $rsp->{node}->[0]->{baudrate}->[0];
    }
}
xCAT::Client::submit_request($cmdref, \&getans);
until ($dsthost and $speed and $dstty) {
    release_lock();
    $sleepint = int(rand(30)) + 60;
    xCAT::Utils::console_sleep($sleepint, "Console not ready, retrying in $sleepint seconds ( Ctrl-E c o to skip delay)\n");
}
release_lock();

# TERM may be empty (SLES 12, PowerKVM); a terminal multiplexer needs it.
if (!$ENV{'TERM'}) {
    $ENV{'TERM'} = "vt100";
}

# Attach to the KVM guest's serial console inside a shared tmux session on the
# hypervisor. tmux (unlike screen) is present on every libvirt host we target,
# incl. ppc64le power hosts that ship no screen; `new-session -A` gives the same
# detach/reattach + multi-client behaviour screen provided (goconserver and an
# interactive rcons share one session). The console itself is opened by
# `virsh console` keyed on the domain name (== the xCAT node name for KVM), which
# is stable across guest reboots (the raw serial pty is not). -x/-y size the
# pane so the guest sees a sane terminal geometry.
my $node = $ARGV[0];
my $session = "serial-$node-cons";
my $virshcons = "virsh -c qemu:///system console --force $node";
# Create the session once, detached, with the status bar OFF so the captured
# console log stays clean serial (no tmux chrome/clock redraws) -- matching what
# screen gave; then attach. `new-session -d -A` is a no-op if it already exists,
# so concurrent clients (goconserver + rcons) share the single session.
exec "ssh -t $dsthost \"tmux -u new-session -d -A -x 200 -y 50 -s $session '$virshcons'; tmux set-option -t $session status off; exec tmux -u attach -t $session\"";
