2010-01-07 06:00:53 +00:00
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
package xCAT::FSPboot ;
use strict ;
use Getopt::Long ;
use xCAT::PPCcli qw( SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR ) ;
use xCAT::Usage ;
use xCAT::Utils ;
use xCAT::MsgUtils ;
use xCAT::PPCboot ;
2012-02-17 06:05:41 +00:00
use xCAT::LparNetbootExp ;
2010-01-07 06:00:53 +00:00
##########################################################################
# Parse the command line for options and operands
##########################################################################
sub parse_args {
xCAT::PPCboot:: parse_args ( @ _ ) ;
}
##########################################################################
# Netboot the lpar
##########################################################################
sub do_rnetboot {
my $ request = shift ;
my $ d = shift ;
my $ exp = shift ;
my $ name = shift ;
my $ node = shift ;
my $ opt = shift ;
my $ ssh = @$ exp [ 0 ] ;
my $ userid = @$ exp [ 4 ] ;
my $ pw = @$ exp [ 5 ] ;
2011-08-30 12:17:23 +00:00
my $ result = "" ;
my $ Rc = SUCCESS ;
2010-01-07 06:00:53 +00:00
my $ cmd ;
2012-02-17 06:05:41 +00:00
my % optarg ;
2010-05-25 05:15:41 +00:00
2010-01-07 06:00:53 +00:00
#######################################
# Disconnect Expect session
#######################################
#xCAT::PPCcli::disconnect( $exp );
#######################################
# Get node data
#######################################
my $ id = @$ d [ 0 ] ;
my $ pprofile = @$ d [ 1 ] ;
my $ fsp = @$ d [ 2 ] ;
my $ hcp = @$ d [ 3 ] ;
2012-02-17 06:05:41 +00:00
########################################
## Find Expect script
########################################
#$cmd = ($::XCATROOT) ? "$::XCATROOT/sbin/" : "/opt/xcat/sbin/";
#$cmd .= "lpar_netboot.expect";
#
########################################
## Check command installed
########################################
#if ( !-x $cmd ) {
# return( [RC_ERROR,"Command not installed: $cmd"] );
#}
2010-01-07 06:00:53 +00:00
#######################################
# Save user name and passwd of hcp to
# environment variables.
# lpar_netboot.expect depends on it
#######################################
$ ENV { HCP_USERID } = $ userid ;
$ ENV { HCP_PASSWD } = $ pw ;
#######################################
# Turn on verbose and debugging
#######################################
2012-03-08 05:15:41 +00:00
if ( $ { $ request - > { arg } } [ 0 ] eq '-V' ) {
2012-02-17 06:05:41 +00:00
#$cmd.= " -v -x";
$ optarg { 'v' } = 1 ; #for verbose
$ optarg { 'x' } = 1 ; #for debug
2010-01-07 06:00:53 +00:00
}
#######################################
# Force LPAR shutdown
#######################################
if ( exists ( $ opt - > { f } ) || ! xCAT::Utils - > isAIX ( ) ) {
2012-02-17 06:05:41 +00:00
#$cmd.= " -i";
$ optarg { 'i' } = 1 ;
2010-01-07 06:00:53 +00:00
}
#######################################
# Write boot order
#######################################
if ( exists ( $ opt - > { s } ) ) {
foreach ( $ opt - > { s } ) {
if ( /^net$/ ) {
2012-02-17 06:05:41 +00:00
#$cmd.= " -w 1";
$ optarg { 'w' } = 1 ;
2010-01-07 06:00:53 +00:00
} elsif ( /^net,hd$/ ) {
2012-02-17 06:05:41 +00:00
#$cmd.= " -w 2";
$ optarg { 'w' } = 2 ;
2010-01-07 06:00:53 +00:00
} elsif ( /^hd,net$/ ) {
2012-02-17 06:05:41 +00:00
#$cmd.= " -w 3";
$ optarg { 'w' } = 3 ;
2010-01-07 06:00:53 +00:00
} elsif ( /^hd$/ ) {
2012-02-17 06:05:41 +00:00
#$cmd.= " -w 4";
$ optarg { 'w' } = 4 ;
2010-01-07 06:00:53 +00:00
}
}
}
2011-08-31 10:18:43 +00:00
my @ macs = split /\|/ , $ opt - > { m } ;
foreach my $ mac ( @ macs ) {
$ mac = lc ( $ mac ) ;
2010-01-07 06:00:53 +00:00
#######################################
2011-08-31 10:18:43 +00:00
# Network specified
2010-01-07 06:00:53 +00:00
#######################################
2012-02-17 06:05:41 +00:00
#$cmd.= " -s auto -d auto -m \"$mac\" -S $opt->{S} -G $opt->{G} -C $opt->{C}";
$ optarg { 's' } = 'auto' ;
$ optarg { 'd' } = 'auto' ;
$ optarg { 'm' } = $ mac ;
$ optarg { 'S' } = $ opt - > { S } ;
$ optarg { 'C' } = $ opt - > { C } ;
$ optarg { 'N' } = $ opt - > { N } ;
$ optarg { 'G' } = $ opt - > { G } ;
2011-08-31 10:18:43 +00:00
if ( exists ( $ opt - > { o } ) ) {
2012-02-17 06:05:41 +00:00
#$cmd.= " -o";
$ optarg { 'o' } = 1 ;
2010-01-07 06:00:53 +00:00
}
2011-08-31 10:18:43 +00:00
my % client_nethash = xCAT::DBobjUtils - > getNetwkInfo ( [ $ node ] ) ;
if ( grep /hf/ , $ client_nethash { $ node } { mgtifname } ) {
2012-02-17 06:05:41 +00:00
#$cmd.= " -t hfi-ent";
$ optarg { 't' } = "hfi-ent" ;
2011-08-31 10:18:43 +00:00
} else {
2012-02-17 06:05:41 +00:00
#$cmd.= " -t ent";
$ optarg { 't' } = "ent" ;
2010-01-07 06:00:53 +00:00
}
2011-08-31 10:18:43 +00:00
$ pprofile = "not_use" ; #lpar_netboot.expect need pprofile for p5 & p6, but for p7 ih, we don't use this attribute.
2010-01-07 06:00:53 +00:00
#######################################
2011-08-31 10:18:43 +00:00
# Add command options
2010-01-07 06:00:53 +00:00
#######################################
2012-02-17 06:05:41 +00:00
#$cmd.= " -f \"$name\" \"$pprofile\" \"$fsp\" $id $hcp \"$node\"";
#print "cmd: $cmd\n";
$ optarg { 'f' } = 1 ;
$ optarg { 'name' } = $ name ;
$ optarg { 'pprofile' } = $ pprofile ;
$ optarg { 'fsp' } = $ fsp ;
$ optarg { 'id' } = $ id ;
$ optarg { 'hcp' } = $ hcp ;
$ optarg { 'node' } = $ node ;
2011-08-31 10:18:43 +00:00
my $ done = 0 ;
while ( $ done < 2 ) {
$ result = "" ;
$ Rc = SUCCESS ;
2012-02-17 06:05:41 +00:00
########################################
## Execute command
########################################
#print "cmd:$cmd\n";
#my $pid = open( OUTPUT, "$cmd 2>&1 |");
#$SIG{INT} = $SIG{TERM} = sub { #prepare to process job termination and propogate it down
# kill 9, $pid;
# return( [RC_ERROR,"Received INT or TERM signal"] );
#};
#if ( !$pid ) {
# return( [RC_ERROR,"$cmd fork error: $!"] );
#}
########################################
## Get command output
########################################
#while ( <OUTPUT> ) {
# $result.=$_;
#}
#close OUTPUT;
2011-08-31 10:18:43 +00:00
2012-02-17 06:05:41 +00:00
########################################
## Get command exit code
########################################
#foreach ( split /\n/, $result ) {
# if ( /^lpar_netboot / ) {
# $Rc = RC_ERROR;
# last;
# }
#}
2011-08-31 10:18:43 +00:00
#######################################
2012-02-17 06:05:41 +00:00
# Invoke the lpar_netbootexp
2011-08-31 10:18:43 +00:00
#######################################
2012-02-17 06:05:41 +00:00
$ result = xCAT::LparNetbootExp - > lparnetbootexp ( \ % optarg , $ request ) ;
$ Rc = @$ result [ 0 ] ;
2011-08-31 10:18:43 +00:00
if ( $ Rc == SUCCESS ) {
$ done = 2 ;
} else {
$ done = $ done + 1 ;
sleep 1 ;
2010-01-07 06:00:53 +00:00
}
}
if ( $ Rc == SUCCESS ) {
2011-08-31 10:18:43 +00:00
last ;
2010-01-07 06:00:53 +00:00
}
}
2012-02-17 06:05:41 +00:00
return $ result ;
2010-01-07 06:00:53 +00:00
}
##########################################################################
# Get LPAR MAC addresses
##########################################################################
sub rnetboot {
my $ request = shift ;
my $ d = shift ;
my $ exp = shift ;
my $ options = $ request - > { opt } ;
my $ hwtype = @$ exp [ 2 ] ;
my $ result ;
2013-01-07 09:11:13 +00:00
my $ name = $ request - > { node } ;
2010-01-07 06:00:53 +00:00
my $ callback = $ request - > { callback } ;
#####################################
# Get node data
#####################################
my $ lparid = @$ d [ 0 ] ;
my $ mtms = @$ d [ 2 ] ;
my $ type = @$ d [ 4 ] ;
my $ node = @$ d [ 6 ] ;
my $ o = @$ d [ 7 ] ;
#####################################
# Gateway (-G)
# Server (-S)
# Client (-C)
# mac (-m)
#####################################
my % opt = (
G = > $ o - > { gateway } ,
S = > $ o - > { server } ,
C = > $ o - > { client } ,
m = > $ o - > { mac }
) ;
2013-01-07 09:11:13 +00:00
#####################################
# Parse node range
#####################################
if ( $ name =~ /ARRAY/ ) {
$ name = join ( ',' , @$ name ) ;
}
2010-01-07 06:00:53 +00:00
#####################################
# Strip colons from mac address
#####################################
$ opt { m } =~ s/://g ;
#####################################
# Force LPAR shutdown
#####################################
if ( exists ( $ options - > { f } ) ) {
$ opt { f } = 1 ;
}
#####################################
# Write boot device order
#####################################
if ( exists ( $ options - > { s } ) ) {
$ opt { s } = $ options - > { s } ;
}
2010-05-25 05:15:41 +00:00
if ( exists ( $ options - > { o } ) ) {
$ opt { o } = $ options - > { o } ;
}
2010-06-01 08:46:21 +00:00
2010-01-07 06:00:53 +00:00
#####################################
# Invalid target hardware
#####################################
if ( $ type !~ /^lpar$/ ) {
return ( [ [ $ name , "Not supported" , RC_ERROR ] ] ) ;
}
#########################################
# Get name known by HCP
#########################################
#my $filter = "name,lpar_id";
#my $values = xCAT::PPCcli::lssyscfg( $exp, $type, $mtms, $filter );
#my $Rc = shift(@$values);
#########################################
# Return error
#########################################
#if ( $Rc != SUCCESS ) {
# return( [[$node,@$values[0],$Rc]] );
#}
#########################################
# Find LPARs by lpar_id
#########################################
#foreach ( @$values ) {
# if ( /^(.*),$lparid$/ ) {
# $name = $1;
# last;
# }
#}
#########################################
# Node not found by lpar_id
#########################################
#if ( !defined( $name )) {
# return( [[$node,"Node not found, lparid=$lparid",RC_ERROR]] );
#}
my $ Rc ;
#########################################
# Check current node state.
# It is not allowed to rinitialize node
# if it is in boot state
#########################################
if ( ! exists ( $ options - > { F } ) && ! xCAT::Utils - > isAIX ( ) ) {
my $ chaintab = xCAT::Table - > new ( 'chain' ) ;
my $ vcon = $ chaintab - > getAttribs ( { node = > "$node" } , 'currstate' ) ;
if ( $ vcon and $ vcon - > { "currstate" } and $ vcon - > { "currstate" } eq "boot" ) {
2010-03-09 11:36:23 +00:00
return ( [ [ $ node , "Node is in boot state. Use nodeset command before rnetboot or use -F option with rnetboot" , RC_ERROR ] ] ) ;
2010-01-07 06:00:53 +00:00
}
}
2011-01-06 09:28:20 +00:00
#my $sitetab = xCAT::Table->new('site');
#my $vcon = $sitetab->getAttribs({key => "conserverondemand"}, 'value');
#if ($vcon and $vcon->{"value"} and $vcon->{"value"} eq "yes" ) {
2010-01-07 06:00:53 +00:00
# $result = xCAT::PPCcli::lpar_netboot(
# $exp,
# $request->{verbose},
# $name,
# $d,
# \%opt );
2011-01-06 09:28:20 +00:00
# return( [[$node,"Not support conserverondemand's value is yes",RC_ERROR]] );
#} else {
2010-01-07 06:00:53 +00:00
#########################################
# Manually perform boot.
#########################################
$ result = do_rnetboot ( $ request , $ d , $ exp , $ name , $ node , \ % opt ) ;
2011-01-06 09:28:20 +00:00
#}
2011-01-20 06:49:48 +00:00
#$sitetab->close;
2010-01-07 06:00:53 +00:00
if ( defined ( $ request - > { opt } - > { m } ) ) {
my $ retries = 0 ;
my @ monnodes = ( $ name ) ;
my $ monsettings = xCAT::Utils - > generate_monsettings ( $ request , \ @ monnodes ) ;
xCAT::Utils - > monitor_installation ( $ request , $ monsettings ) ; ;
while ( $ retries + + < $ monsettings - > { 'retrycount' } && scalar ( keys % { $ monsettings - > { 'nodes' } } ) > 0 ) {
####lparnetboot can not support multiple nodes in one invocation
####for now, does not know how the $d and \%opt will be changed if
####support mulitiple nodes in one invocation,
####so just use the original node name and node attribute array and hash
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "$node: Reinitializing the installation: $retries retry" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
2011-01-20 06:31:35 +00:00
#if ($vcon and $vcon->{"value"} and $vcon->{"value"} eq "yes" ) {
2010-01-07 06:00:53 +00:00
# $result = xCAT::PPCcli::lpar_netboot(
# $exp,
# $request->{verbose},
# $name,
# $d,
# \%opt );
2011-01-20 06:31:35 +00:00
#return( [[$node,"Not support conserverondemand's value is yes",RC_ERROR]] );
#} else {
2010-01-07 06:00:53 +00:00
$ result = do_rnetboot ( $ request , $ d , $ exp , $ name , $ node , \ % opt ) ;
2011-01-20 06:31:35 +00:00
#}
2010-01-07 06:00:53 +00:00
xCAT::Utils - > monitor_installation ( $ request , $ monsettings ) ;
}
#failed after retries
if ( scalar ( keys % { $ monsettings - > { 'nodes' } } ) > 0 ) {
foreach my $ node ( keys % { $ monsettings - > { 'nodes' } } ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "The node \"$node\" can not reach the expected status after $monsettings->{'retrycount'} retries, the installation for this done failed" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
}
}
}
$ Rc = shift ( @$ result ) ;
##################################
# Form string from array results
##################################
if ( exists ( $ request - > { verbose } ) ) {
return ( [ [ $ node , join ( '' , @$ result ) , $ Rc ] ] ) ;
}
##################################
# Return error
# lpar_netboot returns (for example):
# # Connecting to lpar1
# # Connected
# # Checking for power off.
# # Power off the node
# # Wait for power off.
# # Power off complete.
# # Power on lpar1 to Open Firmware.
# # Power on complete.
# lpar_netboot: can not find mac address 42DAB.
#
##################################
if ( $ Rc != SUCCESS ) {
2010-12-20 09:14:15 +00:00
if ( @$ result [ 0 ] =~ /lpar_netboot (.*)/ ) {
2010-01-07 06:00:53 +00:00
return ( [ [ $ node , $ 1 , $ Rc ] ] ) ;
}
return ( [ [ $ node , join ( '' , @$ result ) , $ Rc ] ] ) ;
}
##################################
# Split array into string
##################################
my $ data = @$ result [ 0 ] ;
if ( $ hwtype eq "hmc" ) {
$ data = join ( '' , @$ result ) ;
}
##################################
# lpar_netboot returns:
#
# # Connecting to lpar1
# # Connected
# ...
# lpar_netboot Status: network boot initiated
# # bootp sent over network.
# lpar_netboot Status: waiting for the boot image to boot up.
# # Network boot proceeding, lpar_netboot is exiting.
# # Finished.
#
#####################################
if ( $ data =~ /Finished/ ) {
return ( [ [ $ node , "Success" , $ Rc ] ] ) ;
}
#####################################
# Can still be error w/ Rc=0:
#
# # Connecting to lpar1
# # Connected
# ...
# lpar_netboot Status: network boot initiated
# # bootp sent over network.
# lpar_netboot Status: waiting for the boot image to boot up.
# lpar_netboot: bootp operation failed.
#
#####################################
2010-12-20 09:14:15 +00:00
if ( $ data =~ /lpar_netboot (.*)/ ) {
2010-01-07 06:00:53 +00:00
return ( [ [ $ node , $ 1 , RC_ERROR ] ] ) ;
}
return ( [ [ $ node , $ data , RC_ERROR ] ] ) ;
}
1 ;