2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-09-05 12:37:54 +00:00
Files
xcat-core/xCAT-server/share/xcat/cons/kvm
T
Daniel Hilst e331290414 fix(console): drive the KVM serial console via tmux+virsh, not screen
cons/kvm ran `ssh -t <vmhost> screen ... <pty>`, which requires screen on every
hypervisor. Bare libvirt hosts (notably ppc64le power servers) ship tmux but not
screen, so goconserver's console fork failed and no console was captured.

Use tmux (present on all our libvirt hosts) for the shared detach/reattach
session, wrapping `virsh console` keyed on the domain name (== the xCAT node name
for KVM) -- stable across guest reboots, unlike the raw serial pty. The session
status bar is disabled so the captured console log stays clean serial.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-07-01 06:00:02 -03:00

93 lines
3.0 KiB
Perl
Executable File

#!/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\"";