Fix bug 3261047:ExtTab loads user tables for every perl process
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@9262 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
		| @@ -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); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user