#!/usr/bin/env perl # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html 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 "Error trying to secure a 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; mkpath("/tmp/xcat/"); unless (sysopen(LOCKHANDLE,"/tmp/xcat/consolelock",O_WRONLY | O_CREAT)) { sleep 15; print "Unable to open lock file"; exit 0; } get_lock(); } my $sleepint=int(rand(10)); use lib "$::XCATROOT/lib/perl"; require xCAT::Client; use strict; use Expect; use xCAT::PPCcli qw(SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR); require File::Basename; import File::Basename; ############################################## # Globals ############################################## my $verbose = 0; my $node; my $host; my $lparid; my $mtms; my @cred; my $credencial; my $fsp_ip; my $id; my $hcps; my $result; ########################################################################## # Open remote console thourgh fsp ########################################################################## sub invoke_fsp { my $fsp_api = ($::XCATROOT) ? "$::XCATROOT/sbin/fsp-api" : "/opt/xcat/sbin/fsp-api"; my $action = "console"; my $type = "0"; my $Rc = 0; if( !(-e $fsp_api) && !(-x $fsp_api) ) { return "please check the $fsp_api"; } my $cmd = "$fsp_api -a $action -t $type:$fsp_ip:$id:$node:\r"; #print "cmd: $cmd\n"; my $running_failed_code = "Reason code: 0x1000000"; my $fsp_standby_msg = "Reason code: 0x1300"; my $timeout = 30; my $failed = 0; my $exp = new Expect; $exp->log_stdout( 1 ); $exp->spawn( $cmd ) or die "Can't spawn $cmd\r\n"; my @result = $exp->expect( $timeout, [ "$running_failed_code", sub { $failed = 1; } ], [ "$fsp_standby_msg", sub { $failed = 2; }], [ "Session closed, back from open_vterm", sub { $failed = 3; }] ); if($failed == 1) { $exp->hard_close(); return("Virtual terminal is already connected"); } if($failed == 2) { $exp->hard_close(); return("Failed to open the console. Please check the related FSP's status"); } if($failed == 3) { $exp->hard_close(); return("Failed to open the console. Please check the related FSP's IP"); } my $escape = "\030"; $exp->send( "\r" ); $exp->interact( \*STDIN, $escape ); $exp->hard_close(); return(0); } ########################################################################## # Open remote console through hmc ########################################################################## sub invoke_hmc { my $type = "lpar"; my $hwtype = "hmc"; my %request = ( ppcretry => 1, verbose => $verbose ); ################################# # Get userid and password ################################# #my @cred = xCAT::PPCdb::credentials( $host, $hwtype ); @cred = split(/,/, $credencial); $request{$host}{cred} = \@cred; ################################# # Connect to the remote server ################################# my @exp = xCAT::PPCcli::connect( \%request, $hwtype, $host ); if ( ref($exp[0]) ne "Expect" ) { return( $exp[0] ); } ################################# # Open console connection ################################# my $result = xCAT::PPCcli::mkvterm( \@exp, $type, $lparid, $mtms ); my $Rc = shift(@$result); if ( $Rc != SUCCESS ) { return( @$result[0] ); } return(0); } ############################################## # Start main body of code ############################################## sub getans { my $rsp = shift; if ($rsp->{node}) { $hcps = $rsp->{node}->[0]->{hcp}; if ( $rsp->{node}->[0]->{errorcode} ) { print STDERR "$rsp->{node}->[0]->{error}"; } } } my $cmdref={ command=>["getmulcon"], arg=>["text"], noderange=>[$ARGV[0]] }; xCAT::Client::submit_request($cmdref,\&getans); until ($hcps) { release_lock(); #Let other clients have a go $sleepint=10+int(rand(20)); #Stagger to minimize lock collisions, but no big deal when it does happen print "Console not ready, retrying in $sleepint seconds (Hit Ctrl-E,c,o to skip delay)\n"; sleep $sleepint; get_lock(); xCAT::Client::submit_request($cmdref,\&getans); } release_lock(); #done with xcatd, can run with near impunity $node = $ARGV[0]; my $c = scalar ( keys %{${$hcps}[0]}); for my $thishcp (keys %{${$hcps}[0]}) { my $nt = ${${${${${$hcps}[0]}{$thishcp}}[0]}{nodetype}}[0]; if ( $nt =~ /^(fsp)$/ ) { $fsp_ip = ${${${${${$hcps}[0]}{$thishcp}}[0]}{fsp_ip}}[0]; $id = ${${${${${$hcps}[0]}{$thishcp}}[0]}{id}}[0]; if ($fsp_ip and $id ) { $result = invoke_fsp(); } else { print STDERR "fsp_ip or id is not available\n"; } } elsif ( $nt =~ /^(hmc)$/) { $host = ${${${${${$hcps}[0]}{$thishcp}}[0]}{host}}[0]; $lparid = ${${${${${$hcps}[0]}{$thishcp}}[0]}{lparid}}[0]; $mtms = ${${${${${$hcps}[0]}{$thishcp}}[0]}{mtms}}[0]; $credencial = ${${${${${$hcps}[0]}{$thishcp}}[0]}{credencial}}[0]; if ($host and $lparid and $mtms and $credencial) { $result = invoke_hmc(); } else { print STDERR "hcp or lparid or mtms or user/passwd is not available\n"; } } if($result eq 0) { last; } ############## #Once every hcp is tried, if the $res!=0, it will return -1; ############### $c--; if($c == 0) { print STDERR "$node: $result\n"; exit(1) } } exit(0);