#!/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)); #Stagger start to avoid overwhelming conserver/xCATd #print "Opening console in ".(2+(0.5*$sleepint))." seconds...\n"; #sleep $sleepint; } 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 xCAT::PPCcli qw(SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR); use Data::Dumper; require File::Basename; import File::Basename; my $scriptname = $0; ############################################## # Globals ############################################## my $verbose = 0; my $node; my $host; my $lparid; my $mtms; ########################################## # 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); #} ########################################################################## # Open remote console ########################################################################## sub invoke_cmd { #my @attribs = qw(id parent hcp); #my %tabs = (); # ################################### ## Open databases needed ################################### #foreach ( qw(ppc vpd nodetype) ) { # $tabs{$_} = xCAT::Table->new($_); # # if ( !exists( $tabs{$_} )) { # return( sprintf( $errmsg{DB_UNDEF}, $_ )); # } #} ################################### ## Get node power type ################################### #my $hwtype = __FILE__; #$hwtype =~ s/.*([\w]{3})$/$1/; # ################################## ## 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" )); # } #} ################################## ## Find MTMS in vpd database ################################## #my @attrs = qw(mtm serial); #my ($vpd) = $tabs{vpd}->getNodeAttribs($att->{parent}, \@attrs ); # #if ( !defined( $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 $host = $att->{hcp}; #my $lparid = $att->{id}; #$type = "lpar"; my $type = "lpar"; my $hwtype = "hmc"; my %request = ( ppcretry => 1, verbose => $verbose ); ################################# # Get userid and password ################################# my @cred = xCAT::PPCdb::credentials( $host, $hwtype ); $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 ############################################## #if ( parse_args() ) { # exit(1); #} sub getans { my $rsp = shift; if ($rsp->{node}) { $host = $rsp->{node}->[0]->{host}->[0]; $lparid = $rsp->{node}->[0]->{lparid}->[0]; $mtms = $rsp->{node}->[0]->{mtms}->[0]; } } my $cmdref={ command=>["gethmccon"], arg=>["text"], noderange=>[$ARGV[0]] }; xCAT::Client::submit_request($cmdref,\&getans); until ($lparid and $host and $mtms) { 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 $result = invoke_cmd($host, $lparid, $mtms); if ( $result ne "0" ) { print STDERR "$node: $result\n"; exit(1); } exit(0);