diff --git a/xCAT-server/share/xcat/cons/multiple b/xCAT-server/share/xcat/cons/multiple index ffcb3f72e..5323de339 100755 --- a/xCAT-server/share/xcat/cons/multiple +++ b/xCAT-server/share/xcat/cons/multiple @@ -1,151 +1,76 @@ #!/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 Getopt::Long; -use xCAT::Table; -use xCAT::PPCdb; use Expect; -use xCAT::DBobjUtils; -use Data::Dumper; use xCAT::PPCcli qw(SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR); -use xCAT::FSPUtils; +require File::Basename; +import File::Basename; ############################################## # Globals ############################################## my $verbose = 0; my $node; - -########################################## -# Database errors -########################################## -my %errmsg = ( - NODE_UNDEF =>"Node not defined in '%s' database", - NO_ATTR =>"'%s' not defined in '%s' database", - DB_UNDEF =>"'%s' database not defined" -); - - - -########################################################################## -# Parse the command line for options and operands -########################################################################## -sub parse_args { - - my %opt = (); - my @VERSION = qw( 2.0 ); - - ############################################# - # Responds with usage statement - ############################################# - local *usage = sub { - - my $cmd = __FILE__; - $cmd =~ s/.*([\w]{3}$)/$1/; - - if ( defined( $_[0] )) { - print STDERR "$_[0]\n"; - } - my @msg = ( - "$cmd -h|--help\n", - "$cmd -v|--version\n", - "$cmd singlenode [-V|-Verbose]\n" ); - print STDERR @msg; - }; - ############################################# - # Process command-line arguments - ############################################# - if ( !defined( @ARGV )) { - usage( "No node specified" ); - return(1); - } - ############################################# - # Checks case in GetOptions, allows opts - # to be grouped (e.g. -vx), and terminates - # at the first unrecognized option. - ############################################# - $Getopt::Long::ignorecase = 0; - Getopt::Long::Configure( "bundling" ); - - if ( !GetOptions( \%opt, qw(h|help V|Verbose v|version) )) { - usage(); - return(1); - } - ####################################### - # Option -h for Help - ####################################### - if ( exists( $opt{h} )) { - usage(); - return(1); - } - ####################################### - # Option -v for version - ####################################### - if ( exists( $opt{v} )) { - print STDERR \@VERSION; - return(1); - } - ####################################### - # Option -V for verbose output - ####################################### - if ( exists( $opt{V} )) { - $verbose = 1; - } - ####################################### - # Check for "-" with no option - ####################################### - if ( grep(/^-$/, @ARGV )) { - usage( "Missing option: -" ); - return(1); - } - ####################################### - # Get node - ####################################### - if ( !defined( $ARGV[0] )) { - usage( "No node specified" ); - return(1); - } - ####################################### - # Check for extra argument - ####################################### - $node = shift @ARGV; - if ( defined( $ARGV[0] )) { - usage( "Invalid Argument: $ARGV[0]" ); - return(1); - } - return(0); -} - +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_name = shift; - my $id = shift; my $fsp_api = ($::XCATROOT) ? "$::XCATROOT/sbin/fsp-api" : "/opt/xcat/sbin/fsp-api"; my $action = "console"; my $type = "0"; - my $fsp_ip = (); my $Rc = 0; if( !(-e $fsp_api) && !(-x $fsp_api) ) { return "please check the $fsp_api"; } - - $fsp_ip = xCAT::Utils::getNodeIPaddress( $fsp_name ); - if(!defined($fsp_ip)) { - return "Failed to get the $fsp_name\'s ip"; - } - + my $cmd = "$fsp_api -a $action -t $type:$fsp_ip:$id:$node:\r"; -# print "cmd: $cmd\n"; + #print "cmd: $cmd\n"; my $running_failed_code = "Reason code: 0x1000000"; my $fsp_standby_msg = "Reason code: 0x1300"; my $timeout = 30; @@ -153,7 +78,6 @@ sub invoke_fsp { my $exp = new Expect; $exp->log_stdout( 1 ); $exp->spawn( $cmd ) or die "Can't spawn $cmd\r\n"; - #$exp->spawn( $cmd ) or return("Can't spawn $cmd)"; my @result = $exp->expect( $timeout, [ "$running_failed_code", @@ -201,46 +125,9 @@ sub invoke_fsp { # Open remote console through hmc ########################################################################## sub invoke_hmc { - my $host = shift; - my $lparid = shift; - my $parent = shift; - my @attribs = qw(id parent hcp); - my %tabs = (); - - ################################## - # Get node power type - ################################## - my $hwtype = "hmc"; - - ################################## - # Open databases needed - ################################## - my $vpdtab = xCAT::Table->new('vpd'); - - if ( !$vpdtab ) { - return( sprintf( $errmsg{DB_UNDEF},'vpd' )); - } - - ################################# - # Find MTMS in vpd database - ################################# - my @attrs = qw(mtm serial); - my ($vpd) = $vpdtab->getNodeAttribs($parent, \@attrs ); - - if ( !$vpd ) { - return( sprintf( $errmsg{NODE_UNDEF}, "vpd" )); - } - ################################ - # Verify both vpd attributes - ################################ - foreach ( @attrs ) { - if ( !exists( $vpd->{$_} )) { - return( sprintf( $errmsg{NO_ATTR}, $_, "vpd" )); - } - } - my $mtms = "$vpd->{mtm}*$vpd->{serial}"; - my $type = "lpar"; + my $type = "lpar"; + my $hwtype = "hmc"; my %request = ( ppcretry => 1, verbose => $verbose @@ -248,9 +135,9 @@ sub invoke_hmc { ################################# # Get userid and password ################################# - my @cred = xCAT::PPCdb::credentials( $host, $hwtype ); + #my @cred = xCAT::PPCdb::credentials( $host, $hwtype ); + @cred = split(/,/, $credencial); $request{$host}{cred} = \@cred; - ################################# # Connect to the remote server ################################# @@ -270,112 +157,69 @@ sub invoke_hmc { return(0); } -########################################################################## -# Open remote console -########################################################################## -sub invoke_cmd { - - my @attribs = qw(id parent hcp); - my %tabs = (); - - ################################## - # Open databases needed - ################################## - foreach ( qw(ppc nodetype) ) { - $tabs{$_} = xCAT::Table->new($_); - - if ( !exists( $tabs{$_} )) { - return( sprintf( $errmsg{DB_UNDEF}, $_ )); - } - } - - ################################# - # Get node type - ################################# - my ($ent) = $tabs{nodetype}->getNodeAttribs($node, ["nodetype"] ); - if ( !defined( $ent )) { - return( sprintf( $errmsg{NODE_UNDEF}, "nodetype" )); - } - ################################# - # Check for type - ################################# - if ( !exists( $ent->{nodetype} )) { - return( sprintf( $errmsg{NO_ATTR}, $ent->{nodetype},"nodetype" )); - } - ################################# - # Check for valid "type" - ################################# - my @types = split /,/, $ent->{nodetype}; - my ($type) = grep( /^(lpar|osi)$/, @types ); - - if ( !defined( $type )) { - return( "Invalid node type: $ent->{nodetype}" ); - } - - ################################# - # Get attributes - ################################# - my ($att) = $tabs{ppc}->getAttribs({'node'=>$node}, @attribs ); - - if ( !defined( $att )) { - return( sprintf( $errmsg{NODE_UNDEF}, "ppc" )); - } - ################################# - # Verify required attributes - ################################# - foreach my $at ( @attribs ) { - if ( !exists( $att->{$at} )) { - return( sprintf( $errmsg{NO_ATTR}, $at, "ppc" )); - } - } - - my $id = $att->{id}; - my $parent = $att->{parent}; - my $hcps = $att->{hcp}; - my @hcp_list = split(",", $hcps); - my $cmd = (); - my $res; - my $Rc; - my $c = @hcp_list; - foreach my $thishcp ( @hcp_list ) { - my $thishcp_type = xCAT::FSPUtils->getTypeOfNode($thishcp); - if(!defined($thishcp_type)) { - next; - } - if($thishcp_type =~ /^(fsp)$/) { - $res = invoke_fsp($thishcp, $id); - } elsif ($thishcp_type =~ /^(hmc)$/) { - $res = invoke_hmc($thishcp, $id, $parent); - } else { - return "Couldn't open the console. Please check this node's hcp. "; - } - - if($res eq 0) { - return 0; - } - - ############## - #Once once every hcp is tried, if the $res!=0, it will return -1; - ############### - $c--; - if($c == 0) { - return -1; - } - } - -} ############################################## # Start main body of code ############################################## -if ( parse_args() ) { - exit(1); +sub getans { + my $rsp = shift; + if ($rsp->{node}) { + $hcps = $rsp->{node}->[0]->{hcp}; + } } -my $result = invoke_cmd(); -if ( $result ne "0" ) { - print STDERR "$node: $result\n"; - exit(1); +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);