2008-09-08 18:54:30 +00:00
#!/usr/bin/env perl
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
package xCAT_plugin::updatenode ;
2009-11-12 20:13:34 +00:00
2008-09-08 18:54:30 +00:00
BEGIN
{
2009-11-12 20:13:34 +00:00
$ ::XCATROOT = $ ENV { 'XCATROOT' } ? $ ENV { 'XCATROOT' } : '/opt/xcat' ;
2008-09-08 18:54:30 +00:00
}
use lib "$::XCATROOT/lib/perl" ;
use xCAT::Table ;
use xCAT::Schema ;
use Data::Dumper ;
use xCAT::Utils ;
2012-02-19 16:09:21 +00:00
use xCAT::SvrUtils ;
use xCAT::Usage ;
2012-08-29 10:21:39 +00:00
use Storable qw( dclone ) ;
2012-08-09 04:07:40 +00:00
use xCAT::TableUtils ;
use xCAT::ServiceNodeUtils ;
2010-05-10 09:21:56 +00:00
use xCAT::NetworkUtils ;
2009-11-12 20:13:34 +00:00
use xCAT::InstUtils ;
2012-09-27 13:51:15 +00:00
use xCAT::CFMUtils ;
2013-05-16 13:55:55 +00:00
use xCAT::Postage ;
2008-09-08 18:54:30 +00:00
use Getopt::Long ;
use xCAT::GlobalDef ;
use Sys::Hostname ;
2009-11-12 20:13:34 +00:00
use File::Basename ;
2008-09-25 03:04:56 +00:00
use xCAT::GlobalDef ;
use xCAT_monitoring::monitorctrl ;
2009-11-12 20:13:34 +00:00
use Socket ;
2012-08-29 10:21:39 +00:00
use strict ;
2010-07-01 19:55:11 +00:00
my $ CALLBACK ;
my $ RERUNPS4SECURITY ;
2008-09-08 18:54:30 +00:00
1 ;
#-------------------------------------------------------------------------------
2009-11-12 20:13:34 +00:00
2008-09-08 18:54:30 +00:00
= head1 xCAT_plugin:updatenode
= head2 Package Description
xCAT plug - in module . It handles the updatenode command .
= cut
2009-11-12 20:13:34 +00:00
2008-09-08 18:54:30 +00:00
#------------------------------------------------------------------------------
#--------------------------------------------------------------------------------
2009-11-12 20:13:34 +00:00
2008-09-08 18:54:30 +00:00
= head3 handled_commands
It returns a list of commands handled by this plugin .
Arguments:
none
Returns:
a list of commands .
= cut
2009-11-12 20:13:34 +00:00
#------------------------------------------------------------------------------
2008-09-08 18:54:30 +00:00
sub handled_commands
{
2009-11-12 20:13:34 +00:00
return {
2012-10-16 16:05:16 +00:00
updatenode = > "updatenode" ,
updatenodestat = > "updatenode" ,
updatemynodestat = > "updatenode" ,
updatenodeappstat = > "updatenode" ,
2009-11-12 20:13:34 +00:00
} ;
2008-09-08 18:54:30 +00:00
}
#-------------------------------------------------------
2009-11-12 20:13:34 +00:00
2008-09-08 18:54:30 +00:00
= head3 preprocess_request
Check and setup for hierarchy
= cut
2009-11-12 20:13:34 +00:00
2008-09-08 18:54:30 +00:00
#-------------------------------------------------------
sub preprocess_request
{
my $ request = shift ;
my $ callback = shift ;
2009-11-12 20:13:34 +00:00
$ ::subreq = shift ;
2010-03-25 18:15:06 +00:00
# needed for runcmd output
$ ::CALLBACK = $ callback ;
2009-11-12 20:13:34 +00:00
my $ command = $ request - > { command } - > [ 0 ] ;
2009-07-15 19:12:07 +00:00
if ( $ request - > { _xcatpreprocessed } - > [ 0 ] == 1 ) { return [ $ request ] ; }
2009-11-12 20:13:34 +00:00
my @ requests = ( ) ;
2008-09-08 18:54:30 +00:00
if ( $ command eq "updatenode" )
{
2009-11-12 20:13:34 +00:00
return & preprocess_updatenode ( $ request , $ callback , $ ::subreq ) ;
}
elsif ( $ command eq "updatenodestat" )
{
return [ $ request ] ;
}
2012-08-24 17:12:57 +00:00
elsif ( $ command eq "updatemynodestat" )
{
return [ $ request ] ;
}
2010-11-24 07:07:56 +00:00
elsif ( $ command eq "updatenodeappstat" )
{
return [ $ request ] ;
}
2009-11-12 20:13:34 +00:00
else
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Unsupported command: $command." ;
$ callback - > ( $ rsp ) ;
2012-08-29 10:21:39 +00:00
return ;
2008-09-25 03:04:56 +00:00
}
2008-09-08 18:54:30 +00:00
}
2009-11-12 20:13:34 +00:00
#-----------------------------------------------------------------------------
2008-09-08 18:54:30 +00:00
= head3 process_request
2009-11-12 20:13:34 +00:00
It processes the updatenode command .
2008-09-08 18:54:30 +00:00
Arguments:
request - - a hash table which contains the command name and the arguments .
callback - - a callback pointer to return the response to .
Returns:
2009-11-12 20:13:34 +00:00
0 - for success . The output is returned through the callback pointer .
1 - for error . The error messages are returns through the
callback pointer .
2008-09-08 18:54:30 +00:00
= cut
2009-11-12 20:13:34 +00:00
#------------------------------------------------------------------------------
2008-09-08 18:54:30 +00:00
sub process_request
{
my $ request = shift ;
my $ callback = shift ;
2009-11-12 20:13:34 +00:00
$ ::subreq = shift ;
2010-03-25 18:15:06 +00:00
# needed for runcmd output
$ ::CALLBACK = $ callback ;
2009-11-12 20:13:34 +00:00
my $ command = $ request - > { command } - > [ 0 ] ;
my $ localhostname = hostname ( ) ;
if ( $ command eq "updatenode" )
{
return updatenode ( $ request , $ callback , $ ::subreq ) ;
}
elsif ( $ command eq "updatenodestat" )
{
return updatenodestat ( $ request , $ callback ) ;
}
2012-08-24 17:12:57 +00:00
elsif ( $ command eq "updatemynodestat" )
{
2012-08-29 10:21:39 +00:00
delete $ request
- > { node } ; #the restricted form of this command must be forbidden from specifying other nodes, only can set it's own value
2012-08-24 17:12:57 +00:00
return updatenodestat ( $ request , $ callback ) ;
}
2010-11-24 07:07:56 +00:00
elsif ( $ command eq "updatenodeappstat" )
{
return updatenodeappstat ( $ request , $ callback ) ;
}
2009-11-12 20:13:34 +00:00
else
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "$localhostname: Unsupported command: $command." ;
$ callback - > ( $ rsp ) ;
return 1 ;
}
return 0 ;
2008-09-08 18:54:30 +00:00
}
2009-11-12 20:13:34 +00:00
#-----------------------------------------------------------------------------
2008-09-08 18:54:30 +00:00
= head3 preprocess_updatenode
This function checks for the syntax of the updatenode command
2009-11-12 20:13:34 +00:00
and distributes the command to the right server .
2008-09-08 18:54:30 +00:00
Arguments:
2009-11-12 20:13:34 +00:00
request - the request .
2008-09-08 18:54:30 +00:00
callback - the pointer to the callback function .
2009-11-12 20:13:34 +00:00
subreq - the sub request
2008-09-08 18:54:30 +00:00
Returns:
A pointer to an array of requests .
= cut
2009-11-12 20:13:34 +00:00
#------------------------------------------------------------------------------
sub preprocess_updatenode
{
my $ request = shift ;
my $ callback = shift ;
my $ subreq = shift ;
my $ args = $ request - > { arg } ;
my @ requests = ( ) ;
2012-08-09 04:07:40 +00:00
my $ installdir = xCAT::TableUtils - > getInstallDir ( ) ;
2010-02-24 08:23:36 +00:00
2009-11-12 20:13:34 +00:00
# subroutine to display the usage
sub updatenode_usage
{
2012-08-29 10:21:39 +00:00
my $ cb = shift ;
my $ rsp = { } ;
2010-03-21 13:11:47 +00:00
my $ usage_string = xCAT::Usage - > getUsage ( "updatenode" ) ;
2012-08-29 10:21:39 +00:00
push @ { $ rsp - > { data } } , $ usage_string ;
2010-03-21 13:11:47 +00:00
2009-11-12 20:13:34 +00:00
$ cb - > ( $ rsp ) ;
}
@ ARGV = ( ) ;
if ( $ args )
{
@ ARGV = @ { $ args } ;
}
# parse the options
Getopt::Long:: Configure ( "bundling" ) ;
Getopt::Long:: Configure ( "no_pass_through" ) ;
if (
! GetOptions (
2012-08-29 10:21:39 +00:00
'A|updateallsw' = > \ $ ::ALLSW ,
'c|cmdlineonly' = > \ $ ::CMDLINE ,
'd=s' = > \ $ ::ALTSRC ,
'h|help' = > \ $ ::HELP ,
'v|version' = > \ $ ::VERSION ,
'V|verbose' = > \ $ ::VERBOSE ,
'F|sync' = > \ $ ::FILESYNC ,
2013-01-02 17:19:48 +00:00
'l|user:s' = > \ $ ::USER ,
2012-08-29 10:21:39 +00:00
'f|snsync' = > \ $ ::SNFILESYNC ,
'S|sw' = > \ $ ::SWMAINTENANCE ,
's|sn' = > \ $ ::SETSERVER ,
'P|scripts:s' = > \ $ ::RERUNPS ,
'k|security' = > \ $ ::SECURITY ,
'o|os:s' = > \ $ ::OS ,
2013-02-28 20:48:25 +00:00
'fanout=i' = > \ $ ::fanout ,
2009-11-12 20:13:34 +00:00
)
)
{
& updatenode_usage ( $ callback ) ;
2012-08-29 10:21:39 +00:00
return ;
2009-11-12 20:13:34 +00:00
}
# display the usage if -h or --help is specified
if ( $ ::HELP )
{
& updatenode_usage ( $ callback ) ;
2012-08-29 10:21:39 +00:00
return ;
2009-11-12 20:13:34 +00:00
}
# display the version statement if -v or --verison is specified
if ( $ ::VERSION )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = xCAT::Utils - > Version ( ) ;
$ callback - > ( $ rsp ) ;
2012-08-29 10:21:39 +00:00
return ;
2009-11-12 20:13:34 +00:00
}
2010-03-21 13:11:47 +00:00
# -c must work with -S for AIX node
2012-08-29 10:21:39 +00:00
if ( $ ::CMDLINE && ! $ ::SWMAINTENANCE )
{
2012-08-22 19:05:10 +00:00
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"If you specify the -c flag you must specify the -S flag" ;
$ callback - > ( $ rsp ) ;
2012-08-29 10:21:39 +00:00
return ;
2010-03-21 13:11:47 +00:00
}
2012-08-29 10:21:39 +00:00
2010-03-21 13:11:47 +00:00
# -s must work with -P or -S or --security
2012-08-29 10:21:39 +00:00
if ( $ ::SETSERVER && ! ( $ ::SWMAINTENANCE || $ ::RERUNPS || $ ::SECURITY ) )
{
2012-08-22 19:05:10 +00:00
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
" If you specify the - s flag you must specify either the - S or - k or - P
flags " ;
$ callback - > ( $ rsp ) ;
2012-08-29 10:21:39 +00:00
return ;
2010-03-21 13:11:47 +00:00
}
2012-08-29 10:21:39 +00:00
2011-05-13 13:29:05 +00:00
# -f or -F not both
2012-08-29 10:21:39 +00:00
if ( ( $ ::FILESYNC ) && ( $ ::SNFILESYNC ) )
{
my $ rsp = { } ;
2012-08-22 19:05:10 +00:00
$ rsp - > { data } - > [ 0 ] = "You can not specify both the -f and -F flags." ;
$ callback - > ( $ rsp ) ;
2012-08-29 10:21:39 +00:00
return ;
2011-05-13 13:29:05 +00:00
}
2010-03-21 13:11:47 +00:00
# --security cannot work with -S -P -F
2012-08-29 10:21:39 +00:00
if ( $ ::SECURITY
&& ( $ ::SWMAINTENANCE || $ ::RERUNPS || defined ( $ ::RERUNPS ) ) )
{
2012-08-22 19:05:10 +00:00
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"If you use the -k flag, you cannot specify the -S,-P or -F flags." ;
$ callback - > ( $ rsp ) ;
2012-08-29 10:21:39 +00:00
return ;
2010-03-21 13:11:47 +00:00
}
2012-09-06 19:23:22 +00:00
# the -P flag is omitted when only postscripts are specified,
2009-11-12 20:13:34 +00:00
# so if there are parameters without any flags, it may mean
2012-09-06 19:23:22 +00:00
# to re-run the postscripts. Except for the -k flag
2009-11-12 20:13:34 +00:00
if ( @ ARGV )
{
# we have one or more operands on the cmd line
2012-08-29 10:21:39 +00:00
if (
$# ARGV == 0
&& ! (
$ ::FILESYNC
|| $ ::SNFILESYNC
|| $ ::SWMAINTENANCE
|| defined ( $ ::RERUNPS )
|| $ ::SECURITY
)
)
2009-11-12 20:13:34 +00:00
{
# there is only one operand
# if it doesn't contain an = sign then it must be postscripts
if ( ! ( $ ARGV [ 0 ] =~ /=/ ) )
{
$ ::RERUNPS = $ ARGV [ 0 ] ;
2010-03-21 13:11:47 +00:00
$ ARGV [ 0 ] = "" ;
2009-11-12 20:13:34 +00:00
}
2010-06-07 12:04:48 +00:00
2009-11-12 20:13:34 +00:00
}
}
else
{
2012-08-29 10:21:39 +00:00
2011-05-13 13:29:05 +00:00
# if not syncing Service Node
2012-08-29 10:21:39 +00:00
if ( ! ( $ ::SNFILESYNC ) )
{
2009-11-12 20:13:34 +00:00
2012-08-29 10:21:39 +00:00
# no flags and no operands, set defaults
if (
! (
$ ::FILESYNC
|| $ ::SWMAINTENANCE
|| defined ( $ ::RERUNPS )
|| $ ::SECURITY
)
)
{
$ ::FILESYNC = 1 ;
$ ::SWMAINTENANCE = 1 ;
$ ::RERUNPS = "" ;
}
}
2010-03-21 13:11:47 +00:00
}
2009-11-12 20:13:34 +00:00
my $ nodes = $ request - > { node } ;
2012-10-11 08:48:20 +00:00
2009-11-12 20:13:34 +00:00
if ( ! $ nodes )
{
2012-08-22 19:05:10 +00:00
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"A noderange is required for the updatenode command." ;
$ callback - > ( $ rsp ) ;
2012-08-29 10:21:39 +00:00
return ;
2009-11-12 20:13:34 +00:00
}
2012-08-22 19:05:10 +00:00
if ( $ ::SECURITY )
{
# check to see if the Management Node is in the noderange and
# if it is abort
my $ mname = xCAT::Utils - > noderangecontainsMn ( @$ nodes ) ;
if ( $ mname )
{ # MN in the nodelist
my $ rsp = { } ;
$ rsp - > { error } - > [ 0 ] =
2013-02-28 20:48:25 +00:00
"You must not run -k option against the Management Node:$mname." ;
2012-08-22 19:05:10 +00:00
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback , 1 ) ;
return ;
}
2012-10-16 16:05:16 +00:00
# now build a list of all service nodes that are either in the
2012-09-06 19:23:22 +00:00
# noderange or a service node of a node in the noderange
# and update there ssh keys and credentials
# get computenodes and servicenodes from the noderange
my @ SN ;
my @ CN ;
2012-10-16 16:05:16 +00:00
xCAT::ServiceNodeUtils - > getSNandCPnodes ( \ @$ nodes , \ @ SN , \ @ CN ) ;
2012-09-06 19:23:22 +00:00
$ ::NODEOUT = ( ) ;
2012-10-16 16:05:16 +00:00
& update_SN_security ( $ request , $ callback , $ subreq , \ @ SN ) ;
# are there compute nodes, then we want to change the request to
2012-09-06 19:23:22 +00:00
# just update the compute nodes
2012-10-16 16:05:16 +00:00
if ( scalar ( @ CN ) )
{
$ request - > { node } = \ @ CN ;
$ request - > { noderange } = \ @ CN ;
$ ::RERUNPS = "remoteshell" ;
}
else
{ # no more nodes
return ;
2012-09-06 19:23:22 +00:00
}
2012-08-22 19:05:10 +00:00
}
2012-08-29 10:21:39 +00:00
#
2010-03-25 18:15:06 +00:00
# process @ARGV
2009-11-12 20:13:34 +00:00
#
2010-03-25 18:15:06 +00:00
# the first arg should be a noderange - the other should be attr=val
# - put attr=val operands in %attrvals hash
2008-09-08 18:54:30 +00:00
2009-11-12 20:13:34 +00:00
my % attrvals ;
2012-08-29 10:21:39 +00:00
if ( $ ::SWMAINTENANCE )
{
2010-03-21 13:11:47 +00:00
while ( my $ a = shift ( @ ARGV ) )
2009-11-12 20:13:34 +00:00
{
2010-03-21 13:11:47 +00:00
if ( $ a =~ /=/ )
2009-11-12 20:13:34 +00:00
{
2012-08-29 10:21:39 +00:00
2010-03-21 13:11:47 +00:00
# if it has an "=" sign its an attr=val - we hope
my ( $ attr , $ value ) = $ a =~ /^\s*(\S+?)\s*=\s*(\S*.*)$/ ;
2012-08-29 10:21:39 +00:00
2010-03-21 13:11:47 +00:00
if ( ! defined ( $ attr ) || ! defined ( $ value ) )
{
my $ rsp ;
$ rsp - > { data } - > [ 0 ] = "Incorrect \'attr=val\' pair - $a\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::callback ) ;
return 3 ;
}
2012-08-29 10:21:39 +00:00
2010-03-21 13:11:47 +00:00
# put attr=val in hash
$ attrvals { $ attr } = $ value ;
2009-11-12 20:13:34 +00:00
}
}
}
my @ nodes = @$ nodes ;
my $ postscripts ;
2012-08-29 10:21:39 +00:00
# Handle updating operating system
if ( defined ( $ ::OS ) )
{
my $ reqcopy = { %$ request } ;
2010-07-12 00:40:50 +00:00
$ reqcopy - > { os } - > [ 0 ] = "yes" ;
push @ requests , $ reqcopy ;
2012-08-29 10:21:39 +00:00
return \ @ requests ;
2010-07-12 00:40:50 +00:00
}
2012-08-29 10:21:39 +00:00
# handle the validity of postscripts
2012-10-15 12:58:02 +00:00
# check to see if they exist except for the internal xCAT
# postscripts-start-here,postbootscripts-start-here,
# defaults-postbootscripts-start-here, osimage-postbootscripts-start-here,
2012-10-16 16:05:16 +00:00
# etc
2009-11-12 20:13:34 +00:00
if ( defined ( $ ::RERUNPS ) )
{
if ( $ ::RERUNPS eq "" )
{
$ postscripts = "" ;
}
else
{
$ postscripts = $ ::RERUNPS ;
2012-08-29 10:21:39 +00:00
my @ posts = split ( ',' , $ postscripts ) ;
2012-10-16 16:05:16 +00:00
if ( ! grep ( /start-here/ , @ posts ) )
{
foreach ( @ posts )
2009-11-12 20:13:34 +00:00
{
2012-10-16 16:05:16 +00:00
my @ aa = split ( ' ' , $ _ ) ;
if ( ! - e "$installdir/postscripts/$aa[0]" )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"The postscript $installdir/postscripts/$aa[0] does not exist." ;
$ callback - > ( $ rsp ) ;
return ;
}
}
}
else
{
# can only input one internal postscript on call
# updatenode -P defaults-postscripts-start-here
my $ arraySize = @ posts ;
if ( $ arraySize > 1 )
{ # invalid
2009-11-12 20:13:34 +00:00
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
2012-10-16 16:05:16 +00:00
"Only one internal postscript can be used with -P. Postscripts input were as follows:$postscripts" ;
2009-11-12 20:13:34 +00:00
$ callback - > ( $ rsp ) ;
2012-08-29 10:21:39 +00:00
return ;
2009-11-12 20:13:34 +00:00
}
}
2012-10-16 16:05:16 +00:00
}
2009-11-12 20:13:34 +00:00
}
2012-08-29 10:21:39 +00:00
# If -F or -f option specified, sync files to the noderange or their
2011-05-13 13:29:05 +00:00
# service nodes.
2010-03-21 13:11:47 +00:00
# Note: This action only happens on MN, since xdcp, xdsh handles the
# hierarchical scenario inside
2009-11-12 20:13:34 +00:00
if ( $ ::FILESYNC )
{
my $ reqcopy = { %$ request } ;
$ reqcopy - > { FileSyncing } - > [ 0 ] = "yes" ;
push @ requests , $ reqcopy ;
}
2012-08-29 10:21:39 +00:00
if ( $ ::SNFILESYNC ) # either sync service node
2011-05-13 13:29:05 +00:00
{
my $ reqcopy = { %$ request } ;
$ reqcopy - > { SNFileSyncing } - > [ 0 ] = "yes" ;
push @ requests , $ reqcopy ;
}
2009-11-12 20:13:34 +00:00
2012-10-16 16:05:16 +00:00
# If -F or -f then, call CFMUtils to check if any PCM CFM data is to be
# built for the node. This will also create the synclists attribute in
2012-09-25 18:19:37 +00:00
# the osimage for each node in the noderange
2012-10-16 16:05:16 +00:00
if ( ( $ ::FILESYNC ) || ( $ ::SNFILESYNC ) )
{
2012-09-25 18:19:37 +00:00
2012-10-16 16:05:16 +00:00
# determine the list of osimages names in the noderange to pass into
# the CFMUtils
my @ imagenames = xCAT::TableUtils - > getimagenames ( \ @ nodes ) ;
# Now here we will call CFMUtils
$ ::CALLBACK = $ callback ;
my $ rc = 0 ;
$ rc = xCAT::CFMUtils - > updateCFMSynclistFile ( \ @ imagenames ) ;
if ( $ rc != 0 )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"The call to CFMUtils to build synclist returned an errorcode=$rc." ;
$ callback - > ( $ rsp ) ;
return ;
}
}
2012-10-11 08:48:20 +00:00
2012-08-29 10:21:39 +00:00
# if not -S or -P or --security
2010-03-21 13:11:47 +00:00
unless ( defined ( $ ::SWMAINTENANCE ) || defined ( $ ::RERUNPS ) || $ ::SECURITY )
2010-01-27 10:23:03 +00:00
{
return \ @ requests ;
}
2009-11-12 20:13:34 +00:00
# - need to consider the mixed cluster case
2012-09-10 07:55:07 +00:00
# - can't depend on the os of the MN - need to split out the AIX nodes
2012-10-16 16:05:16 +00:00
my ( $ rc , $ AIXnodes , $ Linuxnodes ) = xCAT::InstUtils - > getOSnodes ( $ nodes ) ;
2009-11-12 20:13:34 +00:00
my @ aixnodes = @$ AIXnodes ;
2012-08-29 10:21:39 +00:00
2009-11-12 20:13:34 +00:00
# for AIX nodes we need to copy software to SNs first - if needed
2010-03-25 18:15:06 +00:00
my ( $ imagedef , $ updateinfo ) ;
2009-11-12 20:13:34 +00:00
if ( defined ( $ ::SWMAINTENANCE ) && scalar ( @ aixnodes ) )
{
( $ rc , $ imagedef , $ updateinfo ) =
& doAIXcopy ( $ callback , \ % attrvals , $ AIXnodes , $ subreq ) ;
if ( $ rc != 0 )
{
2012-08-29 10:21:39 +00:00
2009-11-18 06:51:59 +00:00
# Do nothing when doAIXcopy failed
return undef ;
2009-11-12 20:13:34 +00:00
}
}
2012-08-09 04:07:40 +00:00
my $ sn = xCAT::ServiceNodeUtils - > get_ServiceNode ( \ @ nodes , "xcat" , "MN" ) ;
2009-11-12 20:13:34 +00:00
if ( $ ::ERROR_RC )
{
my $ rsp ;
push @ { $ rsp - > { data } } , "Could not get list of xCAT service nodes." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
2012-08-29 10:21:39 +00:00
return ;
2009-11-12 20:13:34 +00:00
}
2012-10-16 16:05:16 +00:00
# Get the MN names
my @ MNip = xCAT::NetworkUtils - > determinehostname ;
2013-06-26 18:08:14 +00:00
my @ MNnodeinfo = xCAT::NetworkUtils - > determinehostname ;
my $ MNnodename = pop @ MNnodeinfo ; # hostname
my @ MNnodeipaddr = @ MNnodeinfo ; # ipaddresses
2012-10-16 16:05:16 +00:00
2013-06-26 18:08:14 +00:00
# if no service nodes, or I am on a Service Node, then no hierarchy to deal with
2009-11-12 20:13:34 +00:00
2013-06-26 18:08:14 +00:00
my @ sns = ( ) ;
if ( ! ( xCAT::Utils - > isServiceNode ( ) ) ) { # not on a servicenode
if ( $ sn )
{
foreach my $ snkey ( keys %$ sn )
{
if ( ! grep ( /$snkey/ , @ MNnodeipaddr ) ) # don't put the MN in the array
{ # if not the MN
push @ sns , $ snkey ;
}
}
}
}
# my @sns = ();
# foreach my $s (keys %$sn)
# {
# my @tmp_a = split(',', $s);
# foreach my $s1 (@tmp_a)
# {
# if (!grep (/^$s1$/, @MNip))
# {
# push @sns, $s1;
# }
# }
# }
if ( defined ( $ ::SWMAINTENANCE ) )
{
$ request - > { swmaintenance } - > [ 0 ] = "yes" ;
2012-08-29 10:21:39 +00:00
2012-09-10 07:55:07 +00:00
# send along the update info and osimage defs
if ( $ imagedef )
2012-08-29 10:21:39 +00:00
{
2012-09-10 07:55:07 +00:00
xCAT::InstUtils - > taghash ( $ imagedef ) ;
2013-06-26 18:08:14 +00:00
$ request - > { imagedef } = [ $ imagedef ] ;
2009-11-12 20:13:34 +00:00
}
2012-09-10 07:55:07 +00:00
if ( $ updateinfo )
2012-08-29 10:21:39 +00:00
{
2012-09-10 07:55:07 +00:00
xCAT::InstUtils - > taghash ( $ updateinfo ) ;
2013-06-26 18:08:14 +00:00
$ request - > { updateinfo } = [ $ updateinfo ] ;
2009-11-12 20:13:34 +00:00
}
2013-06-26 18:08:14 +00:00
}
if ( defined ( $ ::RERUNPS ) )
{
$ request - > { rerunps } - > [ 0 ] = "yes" ;
$ request - > { postscripts } = [ $ postscripts ] ;
2012-08-29 10:21:39 +00:00
if ( defined ( $ ::SECURITY ) )
{
2013-06-26 18:08:14 +00:00
$ request - > { rerunps4security } - > [ 0 ] = "yes" ;
2010-03-21 13:11:47 +00:00
}
2013-06-26 18:08:14 +00:00
}
2010-03-21 13:11:47 +00:00
2013-06-26 18:08:14 +00:00
if ( defined ( $ ::SECURITY ) )
{
$ request - > { security } - > [ 0 ] = "yes" ;
}
#
# Handle updating OS
#
if ( defined ( $ ::OS ) )
{
$ request - > { os } - > [ 0 ] = "yes" ;
}
#
# if hierarchy, then split the request -F must run on the MN and -P -S on the service nodes
#
if ( @ sns ) { # if servicenodes
# build each request for each servicenode
foreach my $ snkey ( keys %$ sn )
{
2012-08-29 10:21:39 +00:00
2013-06-26 18:08:14 +00:00
# build request
my $ reqcopy = { %$ request } ;
$ reqcopy - > { node } = $ sn - > { $ snkey } ;
$ reqcopy - > { '_xcatdest' } = $ snkey ;
$ reqcopy - > { _xcatpreprocessed } - > [ 0 ] = 1 ;
2009-11-12 20:13:34 +00:00
push @ requests , $ reqcopy ;
2013-06-26 18:08:14 +00:00
}
} else { # no hierarchy, process it right now , here on the MN
$ request - > { _xcatpreprocessed } - > [ 0 ] = 1 ;
& updatenode ( $ request , $ callback , $ subreq ) ;
return ;
2009-11-12 20:13:34 +00:00
}
return \ @ requests ;
}
2008-09-08 18:54:30 +00:00
2012-08-29 10:21:39 +00:00
#-------------------------------------------------------------------------------
2012-09-06 19:23:22 +00:00
= head3 update_SN_security
process updatenode - k command
determine all the service nodes that must be processed from the
input noderange and then update the ssh keys and credentials
= cut
#-----------------------------------------------------------------------------
sub update_SN_security
{
2012-10-16 16:05:16 +00:00
my $ request = shift ;
my $ callback = shift ;
my $ subreq = shift ;
my $ servicenodes = shift ;
my @ SN = @$ servicenodes ;
my $ nodes = $ request - > { node } ;
my @ nodes = @$ nodes ;
2012-09-06 19:23:22 +00:00
my $ sn = xCAT::ServiceNodeUtils - > get_ServiceNode ( \ @ nodes , "xcat" , "MN" ) ;
2012-10-16 16:05:16 +00:00
2012-09-06 19:23:22 +00:00
if ( $ ::ERROR_RC )
{
my $ rsp ;
push @ { $ rsp - > { data } } , "Could not get list of xCAT service nodes." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return ;
}
2012-10-16 16:05:16 +00:00
2012-09-06 19:23:22 +00:00
# take out the Management Node
2012-10-16 16:05:16 +00:00
my @ MNip = xCAT::NetworkUtils - > determinehostname ;
my @ sns = ( ) ;
2012-09-06 19:23:22 +00:00
foreach my $ s ( keys %$ sn )
{
my @ tmp_a = split ( ',' , $ s ) ;
foreach my $ s1 ( @ tmp_a )
{
if ( ! grep ( /^$s1$/ , @ MNip ) )
{
push @ sns , $ s1 ;
}
}
}
2012-10-16 16:05:16 +00:00
2012-09-06 19:23:22 +00:00
# now add any service nodes in the input noderange, we missed
2012-10-16 16:05:16 +00:00
foreach my $ sn ( @ SN )
{
if ( ! grep ( /^$sn$/ , @ sns ) )
{
push @ sns , $ sn ;
}
2012-09-06 19:23:22 +00:00
}
2012-10-16 16:05:16 +00:00
2012-09-06 19:23:22 +00:00
# if we have any service nodes to process
if ( scalar ( @ sns ) )
{
2012-10-16 16:05:16 +00:00
2012-09-06 19:23:22 +00:00
# setup the ssh keys on the service nodes
# run the postscripts: remoteshell, servicenode
# These are all servicenodes
$ ::RERUNPS = "remoteshell,servicenode" ;
my $ req_rs = { %$ request } ;
my $ ps ;
$ ps = $ ::RERUNPS ;
$ req_rs - > { rerunps } - > [ 0 ] = "yes" ;
2012-10-16 16:05:16 +00:00
$ req_rs - > { security } - > [ 0 ] = "yes" ;
2012-09-06 19:23:22 +00:00
$ req_rs - > { rerunps4security } - > [ 0 ] = "yes" ;
$ req_rs - > { node } = \ @ sns ;
$ req_rs - > { noderange } = \ @ sns ;
$ req_rs - > { postscripts } = [ $ ps ] ;
updatenode ( $ req_rs , $ callback , $ subreq ) ;
# parse the output of update security for sns
foreach my $ sn ( keys % { $ ::NODEOUT } )
{
if ( ! grep /^$sn$/ , @ sns )
{
next ;
}
if ( ( grep /ps ok/ , @ { $ ::NODEOUT - > { $ sn } } )
&& ( grep /ssh ok/ , @ { $ ::NODEOUT - > { $ sn } } ) )
{
push @ ::good_sns , $ sn ;
}
}
if ( $ ::VERBOSE )
{
my $ rsp ;
push @ { $ rsp - > { data } } ,
"Update security for following service nodes: @sns." ;
push @ { $ rsp - > { data } } ,
" Following service nodes have been updated successfully: @::good_sns" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
}
}
return ;
}
2012-10-16 16:05:16 +00:00
2012-09-06 19:23:22 +00:00
#-------------------------------------------------------------------------------
2012-08-29 10:21:39 +00:00
= head3 security_update_sshkeys
process updatenode - k command
the ssh keys on the service nodes and nodes
by calling xdsh - K
= cut
#-----------------------------------------------------------------------------
sub security_update_sshkeys
{
2012-10-16 16:05:16 +00:00
my $ request = shift ;
my $ callback = shift ;
my $ subreq = shift ;
my $ nodes = shift ;
my @ nodes = @$ nodes ;
2012-08-29 10:21:39 +00:00
my $ localhostname = hostname ( ) ;
# remove the host key from known_hosts
xCAT::Utils - > runxcmd (
{
command = > [ 'makeknownhosts' ] ,
node = > \ @$ nodes ,
arg = > [ '-r' ] ,
} ,
$ subreq , 0 , 1
) ;
if ( $ ::VERBOSE )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
" $localhostname: run makeknownhosts to clean known_hosts file for nodes: @$nodes" ;
$ callback - > ( $ rsp ) ;
}
# call the xdsh -K to set up the ssh keys
my @ envs = @ { $ request - > { environment } } ;
my @ args = ( "-K" ) ;
my $ res =
xCAT::Utils - > runxcmd (
{
command = > [ 'xdsh' ] ,
node = > \ @$ nodes ,
arg = > \ @ args ,
env = > \ @ envs ,
} ,
$ subreq , 0 , 1
) ;
if ( $ ::VERBOSE )
{
my $ rsp = { } ;
2013-01-15 06:43:25 +00:00
# not display password in verbose mode.
2012-08-29 10:21:39 +00:00
$ rsp - > { data } - > [ 0 ] =
2013-01-15 06:43:25 +00:00
" $localhostname: Internal call command: xdsh -K. nodes = @$nodes, arguments = @args, env = xxxxxx" ;
2012-08-29 10:21:39 +00:00
$ rsp - > { data } - > [ 1 ] =
" $localhostname: return messages of last command: @$res" ;
$ callback - > ( $ rsp ) ;
}
# parse the output of xdsh -K
my @ failednodes = @$ nodes ;
foreach my $ line ( @$ res )
{
chomp ( $ line ) ;
if ( $ line =~ /SSH setup failed for the following nodes: (.*)\./ )
{
@ failednodes = split ( /,/ , $ 1 ) ;
}
elsif ( $ line =~ /setup is complete/ )
{
@ failednodes = ( ) ;
}
}
my $ rsp = { } ;
foreach my $ node ( @$ nodes )
{
if ( grep /^$node$/ , @ failednodes )
{
push @ { $ rsp - > { data } } , "$node: Setup ssh keys failed." ;
}
else
{
push @ { $ rsp - > { data } } , "$node: Setup ssh keys has completed." ;
}
}
$ callback - > ( $ rsp ) ;
return ;
}
2010-03-21 13:11:47 +00:00
2008-09-08 18:54:30 +00:00
#--------------------------------------------------------------------------------
2009-11-12 20:13:34 +00:00
2008-09-08 18:54:30 +00:00
= head3 updatenode
This function implements the updatenode command .
Arguments:
request - the request .
callback - the pointer to the callback function .
2009-11-12 20:13:34 +00:00
subreq - the sub request
2008-09-08 18:54:30 +00:00
Returns:
2009-11-12 20:13:34 +00:00
0 - for success . The output is returned through the callback pointer .
1 - for error . The error messages are returned through the
callback pointer .
2008-09-08 18:54:30 +00:00
= cut
2009-11-12 20:13:34 +00:00
#-----------------------------------------------------------------------------
sub updatenode
{
my $ request = shift ;
my $ callback = shift ;
my $ subreq = shift ;
2012-11-15 18:25:01 +00:00
@ ::SUCCESSFULLNODES = ( ) ;
@ ::FAILEDNODES = ( ) ;
2009-11-12 20:13:34 +00:00
#print Dumper($request);
my $ nodes = $ request - > { node } ;
2013-05-23 19:08:38 +00:00
# $request->{status}= "yes"; for testing
my $ requeststatus ;
if ( defined ( $ request - > { status } ) ) {
$ requeststatus = $ request - > { status } ;
}
2009-11-12 20:13:34 +00:00
my $ localhostname = hostname ( ) ;
2013-05-23 19:08:38 +00:00
# if status return requested
my $ numberofnodes ;
# This is an internal call from another plugin requesting status
# currently this is not displayed is only returned and not displayed
# by updatenode.
if ( defined ( $ requeststatus ) && ( $ requeststatus eq "yes" ) ) {
$ numberofnodes = @$ nodes ;
my $ rsp = { } ;
$ rsp - > { status } - > [ 0 ] = "TOTAL NODES: $numberofnodes" ;
$ callback - > ( $ rsp ) ;
}
2009-11-12 20:13:34 +00:00
# in a mixed cluster we could potentially have both AIX and Linux
# nodes provided on the command line ????
my ( $ rc , $ AIXnodes , $ Linuxnodes ) = xCAT::InstUtils - > getOSnodes ( $ nodes ) ;
my $ args = $ request - > { arg } ;
@ ARGV = ( ) ;
if ( $ args )
{
@ ARGV = @ { $ args } ;
2009-08-24 09:53:55 +00:00
}
2010-02-24 08:23:36 +00:00
# Lookup Install dir location at this Mangment Node.
# XXX: Suppose that compute nodes has the same Install dir location.
2012-08-09 04:07:40 +00:00
my $ installdir = xCAT::TableUtils - > getInstallDir ( ) ;
2010-02-24 08:23:36 +00:00
2012-08-29 10:21:39 +00:00
#if the postscripts directory exists then make sure it is
# world readable and executable by root
2012-06-04 18:41:45 +00:00
my $ postscripts = "$installdir/postscripts" ;
2012-08-29 10:21:39 +00:00
if ( - e $ postscripts )
{
my $ cmd = "chmod -R u+x,a+r $postscripts" ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
my $ rsp = { } ;
if ( $ ::RUNCMD_RC != 0 )
{
$ rsp - > { data } - > [ 0 ] = "$cmd failed.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
2012-08-28 11:39:41 +00:00
2012-08-29 10:21:39 +00:00
}
2012-08-28 11:39:41 +00:00
2012-06-04 18:41:45 +00:00
}
2013-05-16 13:55:55 +00:00
#create each /tftpboot/mypostscript/mypostscript.<nodename> for each node
# This first removes the old one if precreatemypostscripts =0 or undefined
# call create files but no tmp files
my $ notmpfiles = 1 ;
my $ nofiles = 0 ;
#my $nofiles=1;
2013-05-16 15:45:03 +00:00
xCAT::Postage:: create_mypostscript_or_not ( $ request , $ callback , $ subreq , $ notmpfiles , $ nofiles ) ;
2012-10-12 06:45:21 +00:00
2009-11-12 20:13:34 +00:00
# convert the hashes back to the way they were passed in
my $ flatreq = xCAT::InstUtils - > restore_request ( $ request , $ callback ) ;
my $ imgdefs ;
my $ updates ;
if ( $ flatreq - > { imagedef } )
{
$ imgdefs = $ flatreq - > { imagedef } ;
}
if ( $ flatreq - > { updateinfo } )
{
$ updates = $ flatreq - > { updateinfo } ;
}
# get the NIM primary server name
my $ nimprime = xCAT::InstUtils - > getnimprime ( ) ;
chomp $ nimprime ;
2012-08-29 10:21:39 +00:00
# parse the options
2009-11-12 20:13:34 +00:00
Getopt::Long:: Configure ( "bundling" ) ;
Getopt::Long:: Configure ( "no_pass_through" ) ;
if (
! GetOptions (
2012-08-29 10:21:39 +00:00
'A|updateallsw' = > \ $ ::ALLSW ,
'c|cmdlineonly' = > \ $ ::CMDLINE ,
'd=s' = > \ $ ::ALTSRC ,
'h|help' = > \ $ ::HELP ,
'v|version' = > \ $ ::VERSION ,
'V|verbose' = > \ $ ::VERBOSE ,
'F|sync' = > \ $ ::FILESYNC ,
2013-02-28 20:48:25 +00:00
'l|user:s' = > \ $ ::USER ,
2012-08-29 10:21:39 +00:00
'f|snsync' = > \ $ ::SNFILESYNC ,
'S|sw' = > \ $ ::SWMAINTENANCE ,
's|sn' = > \ $ ::SETSERVER ,
'P|scripts:s' = > \ $ ::RERUNPS ,
'k|security' = > \ $ ::SECURITY ,
'o|os:s' = > \ $ ::OS ,
2013-02-28 20:48:25 +00:00
'fanout=i' = > \ $ ::fanout ,
2009-11-12 20:13:34 +00:00
)
)
{
}
#
# process @ARGV
#
2012-08-29 10:21:39 +00:00
# - put attr=val operands in %::attrres hash
2009-11-12 20:13:34 +00:00
while ( my $ a = shift ( @ ARGV ) )
{
if ( $ a =~ /=/ )
{
# if it has an "=" sign its an attr=val - we hope
my ( $ attr , $ value ) = $ a =~ /^\s*(\S+?)\s*=\s*(\S*.*)$/ ;
if ( ! defined ( $ attr ) || ! defined ( $ value ) )
{
my $ rsp ;
$ rsp - > { data } - > [ 0 ] = "Incorrect \'attr=val\' pair - $a\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::callback ) ;
return 3 ;
}
2012-08-29 10:21:39 +00:00
# put attr=val in hash
2009-11-12 20:13:34 +00:00
$ ::attrres { $ attr } = $ value ;
}
}
2013-05-30 11:47:00 +00:00
# if not just using the -k flag, then set all nodes to syncing in
# nodelist updatestatus for the other updatenode options
2013-05-29 11:29:22 +00:00
if ( ! ( $ ::SECURITY ) ) {
my $ stat = "syncing" ;
xCAT::TableUtils - > setUpdateStatus ( \ @$ nodes , $ stat ) ;
}
2009-11-12 20:13:34 +00:00
#
# handle file synchronization
#
2012-10-16 15:32:00 +00:00
if ( ( $ request - > { FileSyncing } && $ request - > { FileSyncing } - > [ 0 ] eq "yes" )
|| (
( $ request - > { SNFileSyncing }
&& $ request - > { SNFileSyncing } - > [ 0 ] eq "yes" ) ) )
{
2012-10-16 16:05:16 +00:00
& updatenodesyncfiles ( $ request , $ subreq , $ callback ) ;
2012-10-16 15:32:00 +00:00
}
2009-11-12 20:13:34 +00:00
2009-11-23 10:59:29 +00:00
if ( scalar ( @$ AIXnodes ) )
{
if ( xCAT::Utils - > isLinux ( ) )
{
2012-08-29 10:21:39 +00:00
2009-11-23 10:59:29 +00:00
# mixed cluster enviornment, Linux MN=>AIX node
# linux nfs client can not mount AIX nfs directory with default settings.
# settting nfs_use_reserved_ports=1 could solve the problem
2012-08-29 10:21:39 +00:00
my $ cmd = qq~nfso -o nfs_use_reserved_ports=1~ ;
2009-11-23 10:59:29 +00:00
my $ output =
2012-08-29 10:21:39 +00:00
xCAT::InstUtils - > xcmd ( $ callback , $ subreq , "xdsh" , $ AIXnodes , $ cmd ,
0 ) ;
2009-11-23 10:59:29 +00:00
if ( $ ::RUNCMD_RC != 0 )
{
my $ rsp ;
push @ { $ rsp - > { data } } ,
"Could not set nfs_use_reserved_ports=1 on nodes. Error message is:\n" ;
push @ { $ rsp - > { data } } , "$output\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return 1 ;
}
}
}
2009-11-12 20:13:34 +00:00
#
# handle software updates
#
if ( $ request - > { swmaintenance } && $ request - > { swmaintenance } - > [ 0 ] eq "yes" )
{
2012-10-16 16:05:16 +00:00
& updatenodesoftware ( $ request , $ subreq , $ callback , $ imgdefs , $ updates ) ;
2012-10-16 15:32:00 +00:00
}
2009-11-12 20:13:34 +00:00
2010-03-21 13:11:47 +00:00
#
# handle of setting up ssh keys
#
2012-08-29 10:21:39 +00:00
if ( $ request - > { security } && $ request - > { security } - > [ 0 ] eq "yes" )
{
# check to see if the Management Node is in the noderange and
# if it is abort
my $ mname = xCAT::Utils - > noderangecontainsMn ( @$ nodes ) ;
if ( $ mname )
{ # MN in the nodelist
2012-06-26 15:15:19 +00:00
my $ rsp = { } ;
$ rsp - > { error } - > [ 0 ] =
2013-02-28 20:48:25 +00:00
"You must not run -k option against the Management Node:$mname." ;
2012-06-26 15:15:19 +00:00
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK , 1 ) ;
return ;
}
2012-08-29 10:21:39 +00:00
2012-10-16 16:05:16 +00:00
# setup the root ssh keys ( runs xdsh -k)
& security_update_sshkeys ( $ request , $ callback , $ subreq , \ @$ nodes ) ;
2010-03-21 13:11:47 +00:00
}
2009-11-12 20:13:34 +00:00
#
# handle the running of cust scripts
#
2012-10-16 16:05:16 +00:00
if ( $ request - > { rerunps } && $ request - > { rerunps } - > [ 0 ] eq "yes" )
{
& updatenoderunps ( $ request , $ subreq , $ callback ) ;
2012-10-16 15:55:13 +00:00
}
#
# Handle updating OS
#
if ( $ request - > { os } && $ request - > { os } - > [ 0 ] eq "yes" )
2009-11-12 20:13:34 +00:00
{
2012-10-16 15:55:13 +00:00
my $ os = $ ::OS ;
# Process ID for xfork()
my $ pid ;
# Child process IDs
my @ children ;
# Go through each node
foreach my $ node ( @$ nodes )
2009-11-12 20:13:34 +00:00
{
2012-10-16 15:55:13 +00:00
$ pid = xCAT::Utils - > xfork ( ) ;
# Parent process
if ( $ pid )
{
push ( @ children , $ pid ) ;
}
# Child process
elsif ( $ pid == 0 )
{
# Update OS
updateOS ( $ callback , $ node , $ os ) ;
# Exit process
exit ( 0 ) ;
}
else
{
# Ran out of resources
die "Error: Could not fork\n" ;
}
} # End of foreach
2009-11-12 20:13:34 +00:00
2012-10-16 15:55:13 +00:00
# Wait for all processes to end
foreach ( @ children )
2012-08-29 10:21:39 +00:00
{
2012-10-16 15:55:13 +00:00
waitpid ( $ _ , 0 ) ;
}
}
2012-10-16 16:05:16 +00:00
2012-11-15 18:25:01 +00:00
# update the node status, this is done when -F -S -P are run
2012-11-16 13:25:07 +00:00
# make sure the nodes only appear in one array good or bad
& cleanstatusarrays ;
2012-11-15 18:25:01 +00:00
if ( @ ::SUCCESSFULLNODES )
{
my $ stat = "synced" ;
xCAT::TableUtils - > setUpdateStatus ( \ @ ::SUCCESSFULLNODES , $ stat ) ;
}
if ( @ ::FAILEDNODES )
{
2013-05-29 11:29:22 +00:00
my $ stat = "failed" ;
2012-11-15 18:25:01 +00:00
xCAT::TableUtils - > setUpdateStatus ( \ @ ::FAILEDNODES , $ stat ) ;
}
2013-05-23 19:08:38 +00:00
# internal call request for status, not output to CLI
if ( defined ( $ requeststatus ) && ( $ requeststatus eq "yes" ) ) {
foreach my $ n ( @ ::SUCCESSFULLNODES ) {
my $ rsp = { } ;
$ rsp - > { status } - > [ 0 ] = "$n: SUCCEEDED" ;
$ callback - > ( $ rsp ) ;
}
foreach my $ n ( @ ::FAILEDNODES ) {
my $ rsp = { } ;
$ rsp - > { status } - > [ 0 ] = "$n: FAILED" ;
$ callback - > ( $ rsp ) ;
}
my $ numberofgoodnodes = 0 ;
my $ numberofbadnodes = 0 ;
$ numberofgoodnodes = @ ::SUCCESSFULLNODES ;
$ numberofbadnodes = @ ::FAILEDNODES ;
my $ rsp = { } ;
$ rsp - > { status } - > [ 0 ] = "TOTAL NODES: $numberofnodes, SUCCEEDED: $numberofgoodnodes, FAILED: $numberofbadnodes" ;
$ callback - > ( $ rsp ) ;
}
2013-05-16 13:55:55 +00:00
# if site.precreatemypostscripts = not 1 or yes or undefined,
# remove all the
# node files in the noderange in /tftpboot/mypostscripts
my $ removeentries = 0 ;
my @ entries =
xCAT::TableUtils - > get_site_attribute ( "precreatemypostscripts" ) ;
if ( $ entries [ 0 ] ) { # not 1 or yes and defined
$ entries [ 0 ] =~ tr /a-z/ A - Z / ;
if ( $ entries [ 0 ] !~ /^(1|YES)$/ ) {
$ removeentries = 1 ;
}
} else { # or not defined
$ removeentries = 1 ;
}
if ( $ removeentries == 1 ) {
my $ tftpdir = xCAT::TableUtils:: getTftpDir ( ) ;
foreach my $ n ( @$ nodes ) {
unlink ( "$tftpdir/mypostscripts/mypostscript.$n" ) ;
}
}
2012-10-16 15:55:13 +00:00
return 0 ;
}
#-------------------------------------------------------------------------------
2012-11-14 18:29:37 +00:00
= head3 updatenoderunps - run postscripts or the updatenode - P option
2012-10-16 15:55:13 +00:00
Arguments: request
Returns:
0 - for success .
1 - for error .
= cut
#-----------------------------------------------------------------------------
sub updatenoderunps
2013-02-28 20:48:25 +00:00
2012-10-16 15:55:13 +00:00
{
2012-10-16 16:05:16 +00:00
my $ request = shift ;
my $ subreq = shift ;
my $ callback = shift ;
2012-10-16 15:55:13 +00:00
my $ nodes = $ request - > { node } ;
my $ localhostname = hostname ( ) ;
2012-10-16 16:05:16 +00:00
my $ installdir = xCAT::TableUtils - > getInstallDir ( ) ;
2012-11-23 07:27:06 +00:00
my $ tftpdir = xCAT::TableUtils - > getTftpDir ( ) ;
2012-10-16 15:55:13 +00:00
my $ postscripts = "" ;
my $ orig_postscripts = "" ;
2012-12-04 20:38:37 +00:00
# For AIX nodes check NFS
my $ nfsv4 ;
my @ nfsv4 =
xCAT::TableUtils - > get_site_attribute ( "useNFSv4onAIX" ) ;
if ( $ nfsv4 [ 0 ] && ( $ nfsv4 [ 0 ] =~ /1|Yes|yes|YES|Y|y/ ) ) {
$ nfsv4 = "yes" ;
} else {
$ nfsv4 = "no" ;
}
if ( ( $ request - > { postscripts } ) && ( $ request - > { postscripts } - > [ 0 ] ) )
{
2012-10-16 16:05:16 +00:00
$ orig_postscripts = $ request - > { postscripts } - > [ 0 ] ;
2012-12-04 20:38:37 +00:00
}
2012-10-16 16:05:16 +00:00
$ postscripts = $ orig_postscripts ;
2012-08-29 10:21:39 +00:00
2012-10-16 16:05:16 +00:00
my $ cmd ;
2012-08-29 10:21:39 +00:00
2012-10-16 16:05:16 +00:00
# get server names as known by the nodes
my % servernodes =
2012-12-01 12:54:31 +00:00
% { xCAT::InstUtils - > get_server_nodes ( $ callback , \ @$ nodes ) } ;
2012-08-29 10:21:39 +00:00
2012-10-16 16:05:16 +00:00
# it's possible that the nodes could have diff server names
# do all the nodes for a particular server at once
2013-02-28 20:48:25 +00:00
2012-10-16 16:05:16 +00:00
foreach my $ snkey ( keys % servernodes )
{
my $ nodestring = join ( ',' , @ { $ servernodes { $ snkey } } ) ;
my $ args ;
my $ mode ;
2013-02-28 20:48:25 +00:00
#now build the actual updatenode command
2012-10-16 16:05:16 +00:00
if ( $ request - > { rerunps4security }
&& $ request - > { rerunps4security } - > [ 0 ] eq "yes" )
2012-08-29 10:21:39 +00:00
{
2012-10-16 16:05:16 +00:00
# for updatenode --security
$ mode = "5" ;
}
else
{
2012-08-29 10:21:39 +00:00
2012-10-16 16:05:16 +00:00
# for updatenode -P
$ mode = "1" ;
}
my $ args1 ;
2012-12-04 20:38:37 +00:00
# Note order of parameters to xcatdsklspost
#is important and cannot be changed
2013-01-09 12:58:43 +00:00
my $ runpscmd ;
if ( $ ::SETSERVER ) {
$ runpscmd =
2013-02-28 20:48:25 +00:00
"$installdir/postscripts/xcatdsklspost $mode -M $snkey '$postscripts' --tftp $tftpdir --installdir $installdir --nfsv4 $nfsv4 -c" ;
2013-01-09 12:58:43 +00:00
} else {
$ runpscmd =
2013-02-28 20:48:25 +00:00
"$installdir/postscripts/xcatdsklspost $mode -m $snkey '$postscripts' --tftp $tftpdir --installdir $installdir --nfsv4 $nfsv4 -c"
}
push @$ args1 , "--nodestatus" ; # return nodestatus
if ( defined ( $ ::fanout ) ) { # fanout
push @$ args1 , "-f" ;
push @$ args1 , $ ::fanout ;
2013-01-02 17:19:48 +00:00
}
2013-02-28 20:48:25 +00:00
if ( defined ( $ ::USER ) ) { # -l contains sudo user
push @$ args1 , "--sudo" ;
push @$ args1 , "-l" ;
push @$ args1 , "$::USER" ;
}
push @$ args1 , "-s" ; # streaming
push @$ args1 , "-v" ; # streaming
push @$ args1 , "-e" ; # execute
push @$ args1 , "$runpscmd" ; # the command
2013-01-02 17:19:48 +00:00
2012-08-29 10:21:39 +00:00
2012-10-16 16:05:16 +00:00
if ( $ ::VERBOSE )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
" $localhostname: Internal call command: xdsh $nodestring "
. join ( ' ' , @$ args1 ) ;
$ callback - > ( $ rsp ) ;
}
2012-08-29 10:21:39 +00:00
2012-10-16 16:05:16 +00:00
$ CALLBACK = $ callback ;
if ( $ request - > { rerunps4security } )
{
$ RERUNPS4SECURITY = $ request - > { rerunps4security } - > [ 0 ] ;
2012-08-29 10:21:39 +00:00
}
2012-10-16 16:05:16 +00:00
else
{
$ RERUNPS4SECURITY = "" ;
}
$ subreq - > (
{
command = > [ "xdsh" ] ,
node = > $ servernodes { $ snkey } ,
arg = > $ args1 ,
_xcatpreprocessed = > [ 1 ]
} ,
\ & getdata
) ;
2012-08-29 10:21:39 +00:00
}
2012-10-16 16:05:16 +00:00
if ( $ request - > { rerunps4security }
&& $ request - > { rerunps4security } - > [ 0 ] eq "yes" )
{
2012-08-29 10:21:39 +00:00
2012-10-16 16:05:16 +00:00
# clean the know_hosts
xCAT::Utils - > runxcmd (
{
command = > [ 'makeknownhosts' ] ,
node = > \ @$ nodes ,
arg = > [ '-r' ] ,
} ,
$ subreq , 0 , 1
) ;
}
2012-09-04 02:37:01 +00:00
2012-10-16 15:55:13 +00:00
return ;
2009-11-12 20:13:34 +00:00
}
2012-10-16 15:01:04 +00:00
#-------------------------------------------------------------------------------
2012-10-16 15:32:00 +00:00
= head3 updatenodesyncfiles - performs node rsync updatenode - F
2012-10-16 15:01:04 +00:00
Arguments: request
Returns:
0 - for success .
1 - for error .
= cut
#-----------------------------------------------------------------------------
sub updatenodesyncfiles
{
2012-10-16 16:05:16 +00:00
my $ request = shift ;
my $ subreq = shift ;
my $ callback = shift ;
my $ nodes = $ request - > { node } ;
my $ localhostname = hostname ( ) ;
2012-10-16 15:32:00 +00:00
my % syncfile_node = ( ) ;
my % syncfile_rootimage = ( ) ;
my $ node_syncfile = xCAT::SvrUtils - > getsynclistfile ( $ nodes ) ;
foreach my $ node ( @$ nodes )
2012-10-16 15:01:04 +00:00
{
2012-10-16 16:05:16 +00:00
my $ synclist = $$ node_syncfile { $ node } ;
2012-10-16 15:01:04 +00:00
2012-10-16 16:05:16 +00:00
if ( $ synclist )
{
2012-10-31 15:36:45 +00:00
2012-10-16 16:05:16 +00:00
# this can be a comma separated list of multiple
# syncfiles
my @ sl = split ( ',' , $ synclist ) ;
foreach my $ s ( @ sl )
2012-10-16 15:01:04 +00:00
{
2012-10-16 16:05:16 +00:00
push @ { $ syncfile_node { $ s } } , $ node ;
2012-10-16 15:01:04 +00:00
}
2012-10-16 16:05:16 +00:00
}
}
2012-10-16 15:01:04 +00:00
2012-11-01 12:38:30 +00:00
my $ numberofsynclists = 0 ;
2012-10-16 16:05:16 +00:00
# Check the existence of the synclist file
if ( % syncfile_node )
{ # there are files to sync defined
foreach my $ synclist ( keys % syncfile_node )
{
if ( ! ( - r $ synclist ) )
2012-10-16 15:01:04 +00:00
{
2012-10-16 16:05:16 +00:00
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"The Synclist file $synclist which specified for certain node does NOT existed." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return 1 ;
2012-10-16 15:01:04 +00:00
}
2012-10-16 16:05:16 +00:00
}
2012-10-16 15:01:04 +00:00
2012-10-16 16:05:16 +00:00
# Sync files to the target nodes
2012-10-18 14:13:32 +00:00
my $ output ;
2012-10-16 16:05:16 +00:00
foreach my $ synclist ( keys % syncfile_node )
{
2012-11-01 12:38:30 +00:00
$ numberofsynclists + + ;
2013-02-28 20:48:25 +00:00
my $ args ;
my $ env ;
if ( $ request - > { FileSyncing } - > [ 0 ] ne "yes" ) { # sync SN only
push @$ args , "-s" ;
$ env = [ "DSH_RSYNC_FILE=$synclist" , "RSYNCSNONLY=1" ] ;
} else {
$ env = [ "DSH_RSYNC_FILE=$synclist" ] ;
}
push @$ args , "--nodestatus" ;
if ( defined ( $ ::fanout ) ) { # fanout
push @$ args , "-f" ;
push @$ args , $ ::fanout ;
}
2013-03-07 14:29:13 +00:00
if ( defined ( $ ::USER ) ) { # -l must sudo
push @$ args , "--sudo" ;
push @$ args , "-l" ;
push @$ args , "$::USER" ;
}
2013-02-28 20:48:25 +00:00
push @$ args , "-F" ;
push @$ args , "$synclist" ;
my $ nodestring = join ( ',' , @ { $ syncfile_node { $ synclist } } ) ;
2012-10-16 16:05:16 +00:00
if ( $ ::VERBOSE )
2012-10-16 15:01:04 +00:00
{
2012-10-16 16:05:16 +00:00
my $ rsp = { } ;
2013-02-28 20:48:25 +00:00
$ rsp - > { data } - > [ 0 ] =
" $localhostname: Internal call command: xdcp $nodestring " . join ( ' ' , @$ args ) ;
2012-10-16 16:05:16 +00:00
$ callback - > ( $ rsp ) ;
2012-10-16 15:01:04 +00:00
}
2013-02-28 20:48:25 +00:00
$ CALLBACK = $ callback ;
2012-10-18 14:13:32 +00:00
$ output =
xCAT::Utils - > runxcmd (
{
command = > [ "xdcp" ] ,
node = > $ syncfile_node { $ synclist } ,
arg = > $ args ,
env = > $ env
} ,
$ subreq , - 1 , 1 ) ;
2012-11-14 18:29:37 +00:00
# build the list of good and bad nodes
& buildnodestatus ( \ @$ output , $ callback ) ;
2012-10-31 15:36:45 +00:00
}
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "File synchronization has completed." ;
$ callback - > ( $ rsp ) ;
2012-10-16 16:05:16 +00:00
}
else
{ # no syncfiles defined
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"There were no syncfiles defined to process. File synchronization has completed." ;
$ callback - > ( $ rsp ) ;
2013-06-21 10:28:17 +00:00
my $ stat = "synced" ;
xCAT::TableUtils - > setUpdateStatus ( \ @$ nodes , $ stat ) ;
2012-10-16 15:01:04 +00:00
2012-10-16 16:05:16 +00:00
}
2012-10-16 15:32:00 +00:00
2012-10-16 16:05:16 +00:00
return ;
2012-10-16 15:32:00 +00:00
}
2012-11-14 18:29:37 +00:00
#-------------------------------------------------------------------------------
= head3 buildnodestatus - Takes the output of the updatenode run
2012-11-16 13:07:17 +00:00
and builds a global array of successfull nodes and one of failed nodes
and then outputs the remaining user info
2012-11-14 18:29:37 +00:00
Arguments: output , callback
2012-11-16 13:07:17 +00:00
Globals @ ::SUCCESSFULLNODES , @ ::FAILEDNODES
2012-11-14 18:29:37 +00:00
= cut
2012-11-16 13:07:17 +00:00
2012-11-14 18:29:37 +00:00
#-----------------------------------------------------------------------------
sub buildnodestatus
{
my $ output = shift ;
my $ callback = shift ;
my @ userinfo = ( ) ;
# determine if the sync was successful or not
foreach my $ line ( @$ output ) {
if ( $ line =~ /^\s*(\S+)\s*:\s*Remote_command_successful/ )
{
my ( $ node , $ info ) = split ( /:/ , $ line ) ;
push ( @ ::SUCCESSFULLNODES , $ node ) ;
}
elsif ( $ line =~ /^\s*(\S+)\s*:\s*Remote_command_failed/ )
{
my ( $ node , $ info ) = split ( /:/ , $ line ) ;
push ( @ ::FAILEDNODES , $ node ) ;
}
else
{
push ( @ userinfo , $ line ) ; # user data
}
}
# output user data
if ( @ userinfo ) {
foreach my $ line ( @ userinfo ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = $ line ;
$ callback - > ( $ rsp ) ;
}
}
2012-11-16 13:25:07 +00:00
return ;
}
#-------------------------------------------------------------------------------
= head3 cleanstatusarrays
Makes sure no Failed nodes are in the successfull nodes list
Removes dups
Globals @ ::SUCCESSFULLNODES , @ ::FAILEDNODES
= cut
#-----------------------------------------------------------------------------
sub cleanstatusarrays
{
2012-11-14 18:29:37 +00:00
my % m = ( ) ;
my % n = ( ) ;
for ( @ ::FAILEDNODES )
{
$ m { $ _ } + + ;
}
for ( @ ::SUCCESSFULLNODES )
{
$ m { $ _ } + + || $ n { $ _ } + + ;
}
@ ::SUCCESSFULLNODES = keys % n ;
return ;
}
2012-10-16 15:32:00 +00:00
#-------------------------------------------------------------------------------
= head3 updatenodesoftware - software updates updatenode - S
Arguments: request , subreq , callback , imgdefs , updates
Returns:
0 - for success .
1 - for error .
= cut
#-----------------------------------------------------------------------------
sub updatenodesoftware
{
2012-10-16 16:05:16 +00:00
my $ request = shift ;
my $ subreq = shift ;
my $ callback = shift ;
my $ imgdefs = shift ;
my $ updates = shift ;
2012-10-16 15:32:00 +00:00
my $ nodes = $ request - > { node } ;
2012-10-16 16:05:16 +00:00
my $ installdir = xCAT::TableUtils - > getInstallDir ( ) ;
2012-11-23 07:27:06 +00:00
my $ tftpdir = xCAT::TableUtils - > getTftpDir ( ) ;
2012-10-16 15:32:00 +00:00
my $ localhostname = hostname ( ) ;
my $ rsp ;
2012-11-16 16:12:23 +00:00
$ CALLBACK = $ callback ;
2012-10-16 15:32:00 +00:00
push @ { $ rsp - > { data } } ,
2013-06-21 10:28:17 +00:00
"Performing software maintenance operations. This could take a while, if there are packages to install.\n" ;
2012-10-16 15:32:00 +00:00
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
my ( $ rc , $ AIXnodes_nd , $ Linuxnodes_nd ) =
2012-10-16 16:05:16 +00:00
xCAT::InstUtils - > getOSnodes ( $ nodes ) ;
2012-10-16 15:32:00 +00:00
2012-10-16 15:55:13 +00:00
#
# do linux nodes
#
if ( scalar ( @$ Linuxnodes_nd ) )
{ # we have a list of linux nodes
2012-10-16 16:05:16 +00:00
my $ cmd ;
2012-10-16 15:32:00 +00:00
2012-10-16 16:05:16 +00:00
# get server names as known by the nodes
my % servernodes =
% { xCAT::InstUtils - > get_server_nodes ( $ callback , \ @$ Linuxnodes_nd ) } ;
2012-10-16 15:32:00 +00:00
2012-10-16 16:05:16 +00:00
# it's possible that the nodes could have diff server names
# do all the nodes for a particular server at once
foreach my $ snkey ( keys % servernodes )
{
my $ nodestring = join ( ',' , @ { $ servernodes { $ snkey } } ) ;
my $ cmd ;
2012-11-16 16:12:23 +00:00
my $ args1 ;
2012-10-16 16:05:16 +00:00
if ( $ ::SETSERVER )
2012-10-16 15:32:00 +00:00
{
2012-11-16 16:12:23 +00:00
$ cmd =
2012-11-23 07:27:06 +00:00
"$installdir/postscripts/xcatdsklspost 2 -M $snkey 'ospkgs,otherpkgs' --tftp $tftpdir" ;
2012-11-16 16:12:23 +00:00
2012-10-16 15:32:00 +00:00
2012-10-16 16:05:16 +00:00
}
else
{
$ cmd =
2012-11-23 07:27:06 +00:00
"$installdir/postscripts/xcatdsklspost 2 -m $snkey 'ospkgs,otherpkgs' --tftp $tftpdir" ;
2013-01-09 18:39:30 +00:00
}
2013-02-28 20:48:25 +00:00
2013-01-09 18:39:30 +00:00
# build xdsh command
2013-02-28 20:48:25 +00:00
push @$ args1 , "--nodestatus" ; # return nodestatus
if ( defined ( $ ::fanout ) ) { # fanout
push @$ args1 , "-f" ;
push @$ args1 , $ ::fanout ;
2013-01-02 17:19:48 +00:00
}
2013-02-28 20:48:25 +00:00
if ( defined ( $ ::USER ) ) { # -l contains sudo user
push @$ args1 , "--sudo" ;
push @$ args1 , "-l" ;
push @$ args1 , "$::USER" ;
}
push @$ args1 , "-s" ; # streaming
push @$ args1 , "-v" ; # streaming
push @$ args1 , "-e" ; # execute
push @$ args1 , "$cmd" ; # the command
2012-10-16 15:32:00 +00:00
2012-10-16 16:05:16 +00:00
if ( $ ::VERBOSE )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
2012-11-16 16:12:23 +00:00
" $localhostname: Internal call command: xdsh $nodestring "
. join ( ' ' , @$ args1 ) ;
2012-10-16 16:05:16 +00:00
$ callback - > ( $ rsp ) ;
}
2012-11-16 16:12:23 +00:00
$ subreq - > (
{
command = > [ "xdsh" ] ,
node = > $ servernodes { $ snkey } ,
arg = > $ args1 ,
_xcatpreprocessed = > [ 1 ]
} ,
\ & getdata2
) ;
2012-10-16 15:32:00 +00:00
}
2012-10-16 16:05:16 +00:00
}
2012-10-16 15:32:00 +00:00
2012-10-16 16:05:16 +00:00
#
# do AIX nodes
#
2012-10-16 15:32:00 +00:00
2012-10-16 16:05:16 +00:00
if ( scalar ( @$ AIXnodes_nd ) )
{
2012-10-16 15:32:00 +00:00
2012-10-16 16:05:16 +00:00
# update the software on an AIX node
if (
& updateAIXsoftware (
$ callback , \ % ::attrres , $ imgdefs ,
$ updates , $ AIXnodes_nd , $ subreq
) != 0
)
{
# my $rsp;
# push @{$rsp->{data}}, "Could not update software for AIX nodes \'@$AIXnodes\'.";
# xCAT::MsgUtils->message("E", $rsp, $callback);;
return 1 ;
}
}
2012-10-16 15:01:04 +00:00
2012-10-16 16:05:16 +00:00
return ;
2012-10-16 15:01:04 +00:00
}
2012-11-16 13:07:17 +00:00
#-------------------------------------------------------------------------------
2012-10-16 15:01:04 +00:00
2012-11-16 13:07:17 +00:00
= head3 getdata - This is the local callback that handles the response from
2012-11-16 16:12:23 +00:00
the xdsh streaming calls when running postscripts
2012-11-16 13:07:17 +00:00
= cut
#-------------------------------------------------------------------------------
2012-08-29 10:21:39 +00:00
sub getdata
{
no strict ;
my $ response = shift ;
my $ rsp ;
foreach my $ type ( keys %$ response )
{
foreach my $ output ( @ { $ response - > { $ type } } )
{
chomp ( $ output ) ;
$ output =~ s/\\cM// ;
2012-11-16 14:45:01 +00:00
if ( $ output =~ /^\s*(\S+)\s*:\s*Remote_command_successful/ )
{
my ( $ node , $ info ) = split ( /:/ , $ output ) ;
push ( @ ::SUCCESSFULLNODES , $ node ) ;
}
if ( $ output =~ /^\s*(\S+)\s*:\s*Remote_command_failed/ )
{
my ( $ node , $ info ) = split ( /:/ , $ output ) ;
push ( @ ::FAILEDNODES , $ node ) ;
}
2012-08-29 10:21:39 +00:00
if ( $ output =~ /returned from postscript/ )
{
$ output =~
s/returned from postscript/Running of postscripts has completed./ ;
}
if ( $ RERUNPS4SECURITY && $ RERUNPS4SECURITY eq "yes" )
{
if ( $ output =~ /Running of postscripts has completed/ )
{
$ output =~
2012-09-06 19:23:22 +00:00
s/Running of postscripts has completed/Redeliver security files has completed/ ;
2012-08-29 10:21:39 +00:00
push @ { $ rsp - > { $ type } } , $ output ;
}
elsif ( $ output !~ /Running postscript|Error loading module/ )
{
push @ { $ rsp - > { $ type } } , "$output" ;
}
2013-05-30 11:47:00 +00:00
} else { # for non -k option then get the rest of the output
if ( ( $ output !~ ( /Error loading module/ ) ) && ( $ output !~ /^\s*(\S+)\s*:\s*Remote_command_successful/ ) && ( $ output !~ /^\s*(\S+)\s*:\s*Remote_command_failed/ ) )
{
2012-08-29 10:21:39 +00:00
push @ { $ rsp - > { $ type } } , "$output" ;
2013-05-30 11:47:00 +00:00
}
2012-08-29 10:21:39 +00:00
}
}
}
$ CALLBACK - > ( $ rsp ) ;
2010-07-01 19:55:11 +00:00
}
2012-11-16 16:12:23 +00:00
#-------------------------------------------------------------------------------
= head3 getdata2 - This is the local callback that handles the response from
the xdsh streaming calls when running software updates
= cut
#-------------------------------------------------------------------------------
sub getdata2
{
no strict ;
my $ response = shift ;
my $ rsp ;
foreach my $ type ( keys %$ response )
{
2012-12-05 15:42:51 +00:00
my $ alreadyinstalled = 0 ;
2012-11-16 16:12:23 +00:00
foreach my $ output ( @ { $ response - > { $ type } } )
{
chomp ( $ output ) ;
$ output =~ s/\\cM// ;
if ( $ output =~ /^\s*(\S+)\s*:\s*Remote_command_successful/ )
{
my ( $ node , $ info ) = split ( /:/ , $ output ) ;
push ( @ ::SUCCESSFULLNODES , $ node ) ;
}
2012-12-05 15:42:51 +00:00
# check for already installed, this is not an error
if ( $ output =~ /^\s*(\S+)\s*:\s*already installed/ )
{
$ alreadyinstalled = 1 ;
}
2012-11-16 16:12:23 +00:00
if ( $ output =~ /^\s*(\S+)\s*:\s*Remote_command_failed/ )
{
2012-12-05 15:42:51 +00:00
if ( $ alreadyinstalled == 0 ) { # not an already install error
my ( $ node , $ info ) = split ( /:/ , $ output ) ;
push ( @ ::FAILEDNODES , $ node ) ;
}
2012-11-16 16:12:23 +00:00
}
if ( $ output =~ /returned from postscript/ )
{
$ output =~
s/returned from postscript/Running of Software Maintenance has completed./ ;
}
if ( ( $ output !~ /^\s*(\S+)\s*:\s*Remote_command_successful/ ) && ( $ output !~ /^\s*(\S+)\s*:\s*Remote_command_failed/ ) )
{
push @ { $ rsp - > { $ type } } , "$output" ;
}
}
}
$ CALLBACK - > ( $ rsp ) ;
}
2010-07-01 19:55:11 +00:00
2010-03-25 18:15:06 +00:00
#-------------------------------------------------------------------------------
= head3 updatenodestat
Arguments:
Returns:
0 - for success .
1 - for error .
= cut
#-----------------------------------------------------------------------------
2009-11-12 20:13:34 +00:00
sub updatenodestat
{
my $ request = shift ;
my $ callback = shift ;
my @ nodes = ( ) ;
my @ args = ( ) ;
if ( ref ( $ request - > { node } ) )
{
@ nodes = @ { $ request - > { node } } ;
}
else
{
2012-08-29 10:21:39 +00:00
if ( $ request - > { node } ) { @ nodes = ( $ request - > { node } ) ; }
else
{ #client asking to update its own status...
unless ( ref $ request - > { username } )
{
return ;
} #TODO: log an attempt without credentials?
@ nodes = @ { $ request - > { username } } ;
2012-08-24 17:12:57 +00:00
}
2009-11-12 20:13:34 +00:00
}
if ( ref ( $ request - > { arg } ) )
{
@ args = @ { $ request - > { arg } } ;
}
else
{
@ args = ( $ request - > { arg } ) ;
}
if ( ( @ nodes > 0 ) && ( @ args > 0 ) )
{
my % node_status = ( ) ;
my $ stat = $ args [ 0 ] ;
2012-08-29 10:21:39 +00:00
unless ( $ ::VALID_STATUS_VALUES { $ stat } )
{
return ;
} #don't accept just any string, see GlobalDef for updates
2009-11-12 20:13:34 +00:00
$ node_status { $ stat } = [] ;
foreach my $ node ( @ nodes )
{
2012-10-23 09:31:12 +00:00
2009-11-12 20:13:34 +00:00
my $ pa = $ node_status { $ stat } ;
push ( @$ pa , $ node ) ;
}
xCAT_monitoring::monitorctrl:: setNodeStatusAttributes ( \ % node_status , 1 ) ;
}
return 0 ;
2008-09-08 18:54:30 +00:00
}
2012-10-16 16:05:16 +00:00
2012-10-11 08:48:20 +00:00
#-------------------------------------------------------------------------------
2009-11-12 20:13:34 +00:00
= head3 doAIXcopy
Copy software update files to SNs - if needed .
Arguments:
Returns:
errors:
0 - OK
1 - error
hash refs:
- osimage definitions
- node update information
Example
my ( $ rc , $ imagedef , $ updateinfo ) = & doAIXcopy ( $ callback , \ % attrvals ,
$ nodes , $ subreq ) ;
Comments:
- running on MN
= cut
#------------------------------------------------------------------------------
sub doAIXcopy
{
my $ callback = shift ;
my $ av = shift ;
my $ nodes = shift ;
my $ subreq = shift ;
my @ nodelist ; # node list
my % attrvals ; # cmd line attr=val pairs
if ( $ nodes )
{
@ nodelist = @$ nodes ;
}
if ( $ av )
{
% attrvals = % { $ av } ;
}
2013-01-10 13:18:27 +00:00
if ( defined ( $ ::USER ) ) { # not supported on AIX
my $ rsp ;
$ rsp - > { error } - > [ 0 ] = " The -l option is not supported on AIX" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ; ;
return 1 ;
}
2009-11-12 20:13:34 +00:00
# get the NIM primary server name
my $ nimprime = xCAT::InstUtils - > getnimprime ( ) ;
chomp $ nimprime ;
my % nodeupdateinfo ;
#
# do we have to copy files to any SNs????
#
# get a list of service nodes for this node list
2012-08-09 04:07:40 +00:00
my $ sn = xCAT::ServiceNodeUtils - > get_ServiceNode ( \ @ nodelist , "xcat" , "MN" ) ;
2009-11-12 20:13:34 +00:00
if ( $ ::ERROR_RC )
{
my $ rsp ;
push @ { $ rsp - > { data } } , "Could not get list of xCAT service nodes." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return 1 ;
}
# want list of remote service nodes - to copy files to
2010-03-25 18:15:06 +00:00
# get the ip of the NIM primary (normally the management node)
2010-05-10 09:21:56 +00:00
my $ ip = xCAT::NetworkUtils - > getipaddr ( $ nimprime ) ;
2009-11-12 20:13:34 +00:00
chomp $ ip ;
my ( $ p1 , $ p2 , $ p3 , $ p4 ) = split /\./ , $ ip ;
my @ SNlist ;
foreach my $ snkey ( keys %$ sn )
{
2010-05-10 09:21:56 +00:00
my $ sip = xCAT::NetworkUtils - > getipaddr ( $ snkey ) ;
2012-10-16 14:42:03 +00:00
chomp $ sip ;
2010-05-10 09:21:56 +00:00
if ( $ ip eq $ sip )
2009-11-12 20:13:34 +00:00
{
next ;
}
else
{
if ( ! grep ( /^$snkey$/ , @ SNlist ) )
{
push ( @ SNlist , $ snkey ) ;
}
}
}
# get a list of osimage names needed for the nodes
my $ nodetab = xCAT::Table - > new ( 'nodetype' ) ;
my $ images =
$ nodetab - > getNodesAttribs ( \ @ nodelist , [ 'node' , 'provmethod' , 'profile' ] ) ;
my @ imagenames ;
2010-12-20 09:16:29 +00:00
my @ noimage ;
2009-11-12 20:13:34 +00:00
foreach my $ node ( @ nodelist )
{
my $ imgname ;
if ( $ images - > { $ node } - > [ 0 ] - > { provmethod } )
{
$ imgname = $ images - > { $ node } - > [ 0 ] - > { provmethod } ;
}
elsif ( $ images - > { $ node } - > [ 0 ] - > { profile } )
{
$ imgname = $ images - > { $ node } - > [ 0 ] - > { profile } ;
}
2010-12-20 09:16:29 +00:00
2012-08-29 10:21:39 +00:00
if ( ! $ imgname )
{
2010-12-20 09:16:29 +00:00
push @ noimage , $ node ;
2012-08-29 10:21:39 +00:00
}
elsif ( ! grep ( /^$imgname$/ , @ imagenames ) )
2009-11-12 20:13:34 +00:00
{
push @ imagenames , $ imgname ;
}
$ nodeupdateinfo { $ node } { imagename } = $ imgname ;
}
$ nodetab - > close ;
2012-08-29 10:21:39 +00:00
if ( @ noimage )
{
2010-12-20 09:16:29 +00:00
my $ rsp ;
my $ allnodes = join ( ',' , @ noimage ) ;
2012-08-29 10:21:39 +00:00
push @ { $ rsp - > { data } } ,
"No osimage specified for the following nodes: $allnodes. You can try to run the nimnodeset command or set the profile|provmethod attributes manually." ;
2010-12-20 09:16:29 +00:00
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return 1 ;
}
2009-11-12 20:13:34 +00:00
my $ osimageonly = 0 ;
if ( ( ! $ attrvals { installp_bundle } && ! $ attrvals { otherpkgs } ) && ! $ ::CMDLINE )
{
# if nothing is provided on the cmd line and we don't set CMDLINE
2010-03-25 18:15:06 +00:00
# then we just use the osimage def - used for permanent updates
2009-11-12 20:13:34 +00:00
$ osimageonly = 1 ;
}
#
# get the osimage defs
#
my % imagedef ;
my @ pkglist ; # list of all software to go to SNs
my % bndloc ;
2011-05-13 13:29:05 +00:00
foreach my $ img ( @ imagenames )
2009-11-12 20:13:34 +00:00
{
my % objtype ;
$ objtype { $ img } = 'osimage' ;
% imagedef = xCAT::DBobjUtils - > getobjdefs ( \ % objtype , $ callback ) ;
2010-03-25 18:15:06 +00:00
if ( ! ( % imagedef ) )
2009-11-12 20:13:34 +00:00
{
my $ rsp ;
push @ { $ rsp - > { data } } ,
"Could not get the xCAT osimage definition for \'$img\'.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return 1 ;
}
#
# if this is not a "standalone" type image then this is an error
#
if ( $ imagedef { $ img } { nimtype } ne "standalone" )
{
my $ rsp ;
push @ { $ rsp - > { data } } ,
2009-11-18 06:51:59 +00:00
"The osimage \'$img\' is not a standalone type. \nThe software maintenance function of updatenode command can only be used for standalone (diskfull) type nodes. \nUse the mknimimage comamand to update diskless osimages." ;
2009-11-12 20:13:34 +00:00
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return 1 ;
}
2012-08-29 10:21:39 +00:00
# if we're not using the os image
2009-11-12 20:13:34 +00:00
if ( $ osimageonly != 1 )
{
2012-08-29 10:21:39 +00:00
# set the imagedef to the cmd line values
2009-11-12 20:13:34 +00:00
if ( $ attrvals { installp_bundle } )
{
$ imagedef { $ img } { installp_bundle } = $ attrvals { installp_bundle } ;
}
else
{
$ imagedef { $ img } { installp_bundle } = "" ;
}
if ( $ attrvals { otherpkgs } )
{
$ imagedef { $ img } { otherpkgs } = $ attrvals { otherpkgs } ;
}
else
{
$ imagedef { $ img } { otherpkgs } = "" ;
}
}
if ( $ attrvals { installp_flags } )
{
$ imagedef { $ img } { installp_flags } = $ attrvals { installp_flags } ;
}
if ( $ attrvals { rpm_flags } )
{
$ imagedef { $ img } { rpm_flags } = $ attrvals { rpm_flags } ;
}
2012-08-29 10:21:39 +00:00
if ( $ attrvals { emgr_flags } )
{
$ imagedef { $ img } { emgr_flags } = $ attrvals { emgr_flags } ;
}
2009-11-12 20:13:34 +00:00
2010-03-25 18:15:06 +00:00
# get loc of software for node
2012-08-29 10:21:39 +00:00
if ( $ ::ALTSRC )
{
$ imagedef { $ img } { alt_loc } = $ ::ALTSRC ;
}
else
{
if ( $ imagedef { $ img } { lpp_source } )
{
$ imagedef { $ img } { lpp_loc } =
xCAT::InstUtils - > get_nim_attr_val ( $ imagedef { $ img } { lpp_source } ,
'location' , $ callback , $ nimprime , $ subreq ) ;
}
else
{
$ imagedef { $ img } { lpp_loc } = "" ;
next ;
}
}
if ( $ ::ALLSW )
{
# get a list of all the files in the location
# if its an alternate loc than just check that dir
# if it's an lpp_source than check both RPM and installp
my $ rpmloc ;
my $ instploc ;
my $ emgrloc ;
if ( $ ::ALTSRC )
{
# use same loc for everything
$ rpmloc = $ instploc = $ imagedef { $ img } { alt_loc } ;
}
else
{
# use specific lpp_source loc
$ rpmloc = "$imagedef{$img}{lpp_loc}/RPMS/ppc" ;
$ instploc = "$imagedef{$img}{lpp_loc}/installp/ppc" ;
$ emgrloc = "$imagedef{$img}{lpp_loc}/emgr/ppc" ;
}
# get installp filesets in this dir
my $ icmd =
qq~installp -L -d $instploc | /usr/bin/cut -f1 -d':' 2>/dev/null~ ;
my @ ilist = xCAT::Utils - > runcmd ( "$icmd" , - 1 ) ;
foreach my $ f ( @ ilist )
{
if ( ! grep ( /^$f$/ , @ pkglist ) )
{
push ( @ pkglist , $ f ) ;
}
}
# get epkg files
my $ ecmd = qq~/usr/bin/ls $emgrloc 2>/dev/null~ ;
my @ elist = xCAT::Utils - > runcmd ( "$ecmd" , - 1 ) ;
foreach my $ f ( @ elist )
{
if ( ( $ f =~ /epkg\.Z/ ) )
{
push ( @ pkglist , $ f ) ;
}
}
# get rpm packages
my $ rcmd = qq~/usr/bin/ls $rpmloc 2>/dev/null~ ;
my @ rlist = xCAT::Utils - > runcmd ( "$rcmd" , - 1 ) ;
foreach my $ f ( @ rlist )
{
if ( $ f =~ /\.rpm/ )
{
push ( @ pkglist , $ f ) ;
}
}
}
else
{
# use otherpkgs and or installp_bundle
# keep a list of packages from otherpkgs and bndls
if ( $ imagedef { $ img } { otherpkgs } )
{
foreach my $ pkg ( split ( /,/ , $ imagedef { $ img } { otherpkgs } ) )
{
my ( $ junk , $ pname ) ;
$ pname = $ pkg ;
if ( ! grep ( /^$pname$/ , @ pkglist ) )
{
push ( @ pkglist , $ pname ) ;
}
}
}
if ( $ imagedef { $ img } { installp_bundle } )
{
my @ bndlist = split ( /,/ , $ imagedef { $ img } { installp_bundle } ) ;
foreach my $ bnd ( @ bndlist )
{
my ( $ rc , $ list , $ loc ) =
xCAT::InstUtils - > readBNDfile ( $ callback , $ bnd , $ nimprime ,
$ subreq ) ;
foreach my $ pkg ( @$ list )
{
chomp $ pkg ;
if ( ! grep ( /^$pkg$/ , @ pkglist ) )
{
push ( @ pkglist , $ pkg ) ;
}
}
$ bndloc { $ bnd } = $ loc ;
}
}
}
2009-11-12 20:13:34 +00:00
# put array in string to pass along to SN
$ imagedef { $ img } { pkglist } = join ( ',' , @ pkglist ) ;
}
# if there are no SNs to update then return
if ( scalar ( @ SNlist ) == 0 )
{
return ( 0 , \ % imagedef , \ % nodeupdateinfo ) ;
}
2010-03-25 18:15:06 +00:00
# copy pkgs from location on nim prime to same loc on SN
2009-11-12 20:13:34 +00:00
foreach my $ snkey ( @ SNlist )
{
2012-08-29 10:21:39 +00:00
2009-11-12 20:13:34 +00:00
# copy files to SN from nimprime!!
# for now - assume nimprime is management node
foreach my $ img ( @ imagenames )
{
2012-08-29 10:21:39 +00:00
if ( ! $ ::ALTSRC )
{
# if lpp_source is not defined on SN then next
my $ scmd =
qq~/usr/sbin/lsnim -l $imagedef{$img}{lpp_source} 2>/dev/null~ ;
my $ out =
xCAT::InstUtils - > xcmd ( $ callback , $ subreq , "xdsh" , $ snkey ,
$ scmd , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
my $ rsp ;
push @ { $ rsp - > { data } } ,
"The NIM lpp_source resource named $imagedef{$img}{lpp_source} is not defined on $snkey. Cannot copy software to $snkey.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
next ;
}
}
2012-10-16 16:05:16 +00:00
# get the dir names to copy to
my $ srcdir ;
if ( $ ::ALTSRC )
{
$ srcdir = "$imagedef{$img}{alt_loc}" ;
}
else
{
$ srcdir = "$imagedef{$img}{lpp_loc}" ;
}
my $ dir = dirname ( $ srcdir ) ;
if ( $ ::VERBOSE )
{
my $ rsp ;
push @ { $ rsp - > { data } } ,
"Copying $srcdir to $dir on service node $snkey.\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
}
# make sure the dir exists on the service node
# also make sure it's writeable by all
my $ mkcmd = qq~/usr/bin/mkdir -p $dir~ ;
my $ output =
xCAT::InstUtils - > xcmd ( $ callback , $ subreq , "xdsh" , $ snkey , $ mkcmd ,
0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
2012-08-29 10:21:39 +00:00
my $ rsp ;
push @ { $ rsp - > { data } } ,
"Could not create directories on $snkey.\n" ;
if ( $ ::VERBOSE )
{
push @ { $ rsp - > { data } } , "$output\n" ;
}
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
next ;
2012-10-16 16:05:16 +00:00
}
# sync source files to SN
my $ cpcmd =
qq~$::XCATROOT/bin/prsync -o "rlHpEAogDz" $srcdir $snkey:$dir 2>/dev/null~ ;
$ output =
xCAT::InstUtils - > xcmd ( $ callback , $ subreq , "xdsh" , $ nimprime ,
$ cpcmd , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
my $ rsp ;
push @ { $ rsp - > { data } } ,
"Could not copy $srcdir to $dir for service node $snkey.\n" ;
push @ { $ rsp - > { data } } , "Output from command: \n\n$output\n\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return ( 1 ) ;
}
# run inutoc in remote installp dir
my $ installpsrcdir ;
if ( $ ::ALTSRC )
{
$ installpsrcdir = $ srcdir ;
}
else
{
$ installpsrcdir = "$srcdir/installp/ppc" ;
}
my $ icmd = qq~cd $installpsrcdir; /usr/sbin/inutoc .~ ;
my $ output =
xCAT::InstUtils - > xcmd ( $ callback , $ subreq , "xdsh" , $ snkey , $ icmd ,
0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
my $ rsp ;
push @ { $ rsp - > { data } } ,
"Could not run inutoc for $installpsrcdir on $snkey\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
}
} # end for each osimage
2009-11-12 20:13:34 +00:00
} # end - for each service node
return ( 0 , \ % imagedef , \ % nodeupdateinfo ) ;
2008-09-25 03:04:56 +00:00
}
2009-11-12 20:13:34 +00:00
#-------------------------------------------------------------------------------
= head3 updateAIXsoftware
Update the software on an xCAT AIX cluster node .
2008-09-25 03:04:56 +00:00
2009-11-12 20:13:34 +00:00
Arguments:
Returns:
0 - OK
1 - error
Example
2010-03-25 18:15:06 +00:00
if ( & updateAIXsoftware ( $ callback , \ % attrres , $ imgdefs , $ updates , $ nodes , $ subreq ) != 0 )
2009-11-12 20:13:34 +00:00
Comments:
= cut
#-------------------------------------------------------------------------------
sub updateAIXsoftware
{
my $ callback = shift ;
2012-08-29 10:21:39 +00:00
my $ attrs = shift ;
2009-11-12 20:13:34 +00:00
my $ imgdefs = shift ;
my $ updates = shift ;
my $ nodes = shift ;
my $ subreq = shift ;
2008-09-08 18:54:30 +00:00
2009-11-12 20:13:34 +00:00
my @ noderange = @$ nodes ;
my % attrvals ; # cmd line attr=val pairs
2011-05-13 13:29:05 +00:00
my % imagedefs ;
my % nodeupdateinfo ;
2009-11-12 20:13:34 +00:00
my @ pkglist ; # list of ALL software to install
2008-09-08 18:54:30 +00:00
2009-11-12 20:13:34 +00:00
# att=val - bndls, otherpakgs, flags
if ( $ attrs )
{
% attrvals = % { $ attrs } ;
}
if ( $ imgdefs )
{
% imagedefs = % { $ imgdefs } ;
}
if ( $ updates )
{
% nodeupdateinfo = % { $ updates } ;
}
my % bndloc ;
2013-03-01 19:26:29 +00:00
# get the server name for each node - as known by the node
2009-11-12 20:13:34 +00:00
my $ noderestab = xCAT::Table - > new ( 'noderes' ) ;
my $ xcatmasters =
$ noderestab - > getNodesAttribs ( \ @ noderange , [ 'node' , 'xcatmaster' ] ) ;
# get the NIM primary server name
my $ nimprime = xCAT::InstUtils - > getnimprime ( ) ;
chomp $ nimprime ;
2013-03-01 19:26:29 +00:00
#
# get a list of servers and a hash of the servers name for each node
#
2009-11-12 20:13:34 +00:00
my % server ;
my @ servers ;
foreach my $ node ( @ noderange )
{
if ( $ xcatmasters - > { $ node } - > [ 0 ] - > { xcatmaster } )
{
$ server { $ node } = $ xcatmasters - > { $ node } - > [ 0 ] - > { xcatmaster } ;
}
else
{
2013-03-01 19:26:29 +00:00
# if it's not the xcatmaster then default to the NIM primary
2009-11-12 20:13:34 +00:00
$ server { $ node } = $ nimprime ;
}
if ( ! grep ( $ server { $ node } , @ servers ) )
{
push ( @ servers , $ server { $ node } ) ;
}
}
$ noderestab - > close ;
2013-03-01 19:26:29 +00:00
# need to sort nodes by osimage AND server
# - each aixswupdate call should go to all nodes with the same server
# and osimage
2012-08-29 10:21:39 +00:00
2013-03-01 19:26:29 +00:00
my % nodeoslist ;
foreach my $ node ( @ noderange ) {
my $ server = $ server { $ node } ;
my $ osimage = $ nodeupdateinfo { $ node } { imagename } ;
push ( @ { $ nodeoslist { $ server } { $ osimage } } , $ node ) ;
}
2008-09-08 18:54:30 +00:00
2013-03-01 19:26:29 +00:00
my $ error = 0 ;
2010-03-25 18:15:06 +00:00
2013-03-01 19:26:29 +00:00
# process nodes - all that have same serv and osimage go at once
foreach my $ serv ( keys % nodeoslist ) { # for each server
2012-02-15 20:13:51 +00:00
2013-03-01 19:26:29 +00:00
foreach my $ img ( keys % { $ nodeoslist { $ serv } } ) { # for each osimage
2012-02-15 20:13:51 +00:00
2013-03-01 19:26:29 +00:00
my @ nodes = @ { $ nodeoslist { $ serv } { $ img } } ;
if ( ! scalar ( @ nodes ) ) {
next ;
2009-11-12 20:13:34 +00:00
}
2013-03-01 19:26:29 +00:00
# set the location of the software
my $ pkgdir = "" ;
if ( $ ::ALTSRC )
{
$ pkgdir = $ ::ALTSRC ;
}
else
{
$ pkgdir = $ imagedefs { $ img } { lpp_loc } ;
}
# check for pkg dir
if ( ! - d $ pkgdir ) {
my $ rsp ;
push @ { $ rsp - > { data } } , "The source directory $pkgdir does not exist.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
$ error + + ;
next ;
}
# create a file in the pkgdir and add the pkg list to it
# the pkgdir is mounted and the pkglist file will be available
# on the node.
#
# create a unique name
my $ thisdate = `date +%s` ;
my $ pkglist_file_name = qq~pkglist_file.$thisdate~ ;
chomp $ pkglist_file_name ;
@ pkglist = split ( /,/ , $ imagedefs { $ img } { pkglist } ) ;
if ( ! scalar ( @ pkglist ) )
{
my $ rsp ;
push @ { $ rsp - > { data } } , "There is no list of packages for nodes: @nodes.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
$ error + + ;
next ;
}
# make sure the permissions are correct on pkgdir
# - we are running on MN
my $ chmcmd = qq~/bin/chmod -R +r $pkgdir~ ;
my @ result = xCAT::Utils - > runcmd ( "$chmcmd" , - 1 ) ;
if ( $ ::RUNCMD_RC != 0 )
2012-08-29 10:21:39 +00:00
{
2013-03-01 19:26:29 +00:00
my $ rsp ;
push @ { $ rsp - > { data } } ,
"Could not set permissions for $pkgdir.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
$ error + + ;
next ;
}
# create a pkglist file in the pkgdir on MN
my $ pkglist_file = qq~$pkgdir/$pkglist_file_name~ ;
if ( ! open ( PKGLISTFILE , ">$pkglist_file" ) )
{
my $ rsp ;
push @ { $ rsp - > { data } } , "Could not open $pkglist_file_name.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
$ error + + ;
next ;
}
else
{
foreach ( @ pkglist )
{
print PKGLISTFILE $ _ . "\n" ;
}
close ( PKGLISTFILE ) ;
}
# ndebug
# ??? has the whole pkgdir been copied to the SN yet???
if ( ! xCAT::InstUtils - > is_me ( $ serv ) ) {
# cp file to SN
# has pkgdir already been copied.
my $ rcpcmd = "$::XCATROOT/bin/xdcp $serv $pkglist_file $pkgdir " ;
my $ output = xCAT::Utils - > runcmd ( "$rcpcmd" , - 1 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
my $ rsp ;
push @ { $ rsp - > { data } } , "Could not copy $pkglist_file to $serv.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
$ error + + ;
next ;
}
}
# export the pkgdir on the server
my $ ecmd ;
my @ nfsv4 = xCAT::TableUtils - > get_site_attribute ( "useNFSv4onAIX" ) ;
if ( $ nfsv4 [ 0 ] && ( $ nfsv4 [ 0 ] =~ /1|Yes|yes|YES|Y|y/ ) )
{
$ ecmd = qq~exportfs -i -o vers=4 $pkgdir~ ;
}
else
{
$ ecmd = qq~exportfs -i $pkgdir~ ;
}
if ( ! xCAT::InstUtils - > is_me ( $ serv ) ) {
my $ output = xCAT::Utils - > runxcmd (
{
command = > [ "xdsh" ] ,
node = > [ $ serv ] ,
arg = > [ $ ecmd ]
} ,
$ subreq , - 1 , 1
) ;
if ( $ ::RUNCMD_RC != 0 )
{
my $ rsp ;
push @ { $ rsp - > { data } } , "Could not export $pkgdir on $serv.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
$ error + + ;
2010-03-25 18:15:06 +00:00
next ;
2013-03-01 19:26:29 +00:00
}
} else {
my $ output = xCAT::Utils - > runcmd ( "$ecmd" , - 1 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
my $ rsp ;
push @ { $ rsp - > { data } } , "Could not export $pkgdir on $serv.\n" ;
push @ { $ rsp - > { data } } , "$output\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
$ error + + ;
next ;
}
}
#
# call aixswupdate to install sw on the nodes
#
# put together the cmd string
my $ installcmd = qq~/install/postscripts/aixswupdate -f $pkglist_file ~ ;
# $serv is the name of the nodes server as known by the node
$ installcmd . = qq~ -s $serv ~ ;
if ( $ ::ALLSW ) {
$ installcmd . = qq~ -a ~ ;
}
if ( $ ::ALTSRC ) {
$ installcmd . = qq~ -d ~ ;
}
if ( $ ::NFSV4 ) {
$ installcmd . = qq~ -n ~ ;
}
# add installp flags
if ( $ imagedefs { $ img } { installp_flags } ) {
$ installcmd . = qq~ -i $imagedefs{$img}{installp_flags} ~ ;
}
# add rpm flags
if ( $ imagedefs { $ img } { rpm_flags } ) {
$ installcmd . = qq~ -r $imagedefs{$img}{rpm_flags} ~ ;
}
# add emgr flags
if ( $ imagedefs { $ img } { emgr_flags } ) {
$ installcmd . = qq~ -e $imagedefs{$img}{emgr_flags} ~ ;
}
my $ args1 ;
push @$ args1 , "--nodestatus" ;
push @$ args1 , "-s" ;
push @$ args1 , "-v" ;
push @$ args1 , "-e" ;
if ( defined ( $ ::fanout ) ) { # fanout input
push @$ args1 , "-f" ;
push @$ args1 , $ ::fanout ;
}
push @$ args1 , "$installcmd" ;
$ subreq - > (
{
command = > [ "xdsh" ] ,
node = > \ @ nodes ,
arg = > $ args1 ,
_xcatpreprocessed = > [ 1 ]
} ,
\ & getdata2
) ;
# remove pkglist_file from MN - local
my $ rcmd = qq~/bin/rm -f $pkglist_file~ ;
my $ output = xCAT::Utils - > runcmd ( "$rcmd" , - 1 ) ;
if ( $ ::RUNCMD_RC != 0 )
2012-08-29 10:21:39 +00:00
{
2013-03-01 19:26:29 +00:00
my $ rsp ;
push @ { $ rsp - > { data } } , "Could not remove $pkglist_file.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
2012-08-29 10:21:39 +00:00
}
2013-03-01 19:26:29 +00:00
# if not $serv then remove pkglist_file from $serv
if ( ! xCAT::InstUtils - > is_me ( $ serv ) ) {
my $ output = xCAT::Utils - > runxcmd (
{
command = > [ "xdsh" ] ,
node = > [ $ serv ] ,
arg = > [ $ rcmd ]
} ,
$ subreq , - 1 , 1
) ;
if ( $ ::RUNCMD_RC != 0 )
{
my $ rsp ;
push @ { $ rsp - > { data } } , "Could not remove $pkglist_file on $serv.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
$ error + + ;
}
}
# unexport pkgdir
my $ ucmd = qq~exportfs -u -F $pkgdir~ ;
if ( xCAT::InstUtils - > is_me ( $ serv ) ) {
my $ ucmd = qq~exportfs -u -F $pkgdir~ ;
my $ output = xCAT::Utils - > runcmd ( "$ucmd" , - 1 ) ;
2012-08-29 10:21:39 +00:00
if ( $ ::RUNCMD_RC != 0 )
{
my $ rsp ;
2013-03-01 19:26:29 +00:00
push @ { $ rsp - > { data } } , "Could not unexport $pkgdir.\n" ;
2012-08-29 10:21:39 +00:00
if ( $ ::VERBOSE )
{
push @ { $ rsp - > { data } } , "$output\n" ;
2013-03-01 19:26:29 +00:00
}
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
$ error + + ;
}
} else {
# unexport dirs on SNs
my $ output = xCAT::Utils - > runxcmd (
{
command = > [ "xdsh" ] ,
node = > [ $ serv ] ,
arg = > [ $ ucmd ]
} ,
$ subreq , - 1 , 1
) ;
2012-08-29 10:21:39 +00:00
if ( $ ::RUNCMD_RC != 0 )
{
my $ rsp ;
2013-03-01 19:26:29 +00:00
push @ { $ rsp - > { data } } , "Could not unexport $pkgdir on $serv.\n" ;
2012-08-29 10:21:39 +00:00
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
2013-03-01 19:26:29 +00:00
$ error + + ;
2012-08-29 10:21:39 +00:00
}
2013-03-01 19:26:29 +00:00
}
} # for each osimage
} # for each server
2009-11-12 20:13:34 +00:00
if ( $ error )
{
my $ rsp ;
push @ { $ rsp - > { data } } ,
"One or more errors occured while updating node software.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return 1 ;
}
else
{
my $ rsp ;
push @ { $ rsp - > { data } } ,
2013-03-01 19:26:29 +00:00
"Cluster node software update commands have completed.\n" ;
2009-11-12 20:13:34 +00:00
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
}
return 0 ;
}
2009-12-01 18:21:30 +00:00
2010-07-12 00:40:50 +00:00
#-------------------------------------------------------
= head3 updateOS
Description : Update the node operating system
Arguments :
Returns : Nothing
Example : updateOS ( $ callback , $ nodes , $ os ) ;
= cut
#-------------------------------------------------------
2012-08-29 10:21:39 +00:00
sub updateOS
{
# Get inputs
my ( $ callback , $ node , $ os ) = @ _ ;
my $ rsp ;
# Get install directory
my $ installDIR = xCAT::TableUtils - > getInstallDir ( ) ;
# Get HTTP server
my $ http = xCAT::NetworkUtils - > my_ip_facing ( $ node ) ;
if ( ! $ http )
{
push @ { $ rsp - > { data } } , "$node: (Error) Missing HTTP server" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
return ;
}
# Get OS to update to
my $ update2os = $ os ;
push @ { $ rsp - > { data } } , "$node: Upgrading $node to $os" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
# Get the OS that is installed on the node
my $ arch = `ssh -o ConnectTimeout=5 $node "uname -m"` ;
chomp ( $ arch ) ;
my $ installOS ;
my $ version ;
# Red Hat Linux
if (
`ssh -o ConnectTimeout=5 $node "test -f /etc/redhat-release && echo 'redhat'"`
)
{
$ installOS = "rh" ;
chomp ( $ version =
`ssh $node "tr -d '.' < /etc/redhat-release" | head -n 1` ) ;
$ version =~ s/[^0-9]*([0-9]+).*/$1/ ;
}
# SUSE Linux
elsif (
`ssh -o ConnectTimeout=5 $node "test -f /etc/SuSE-release && echo 'SuSE'"`
)
{
$ installOS = "sles" ;
chomp ( $ version =
`ssh $node "tr -d '.' < /etc/SuSE-release" | head -n 1` ) ;
$ version =~ s/[^0-9]*([0-9]+).*/$1/ ;
}
# Everything else
else
{
$ installOS = "Unknown" ;
push @ { $ rsp - > { data } } , "$node: (Error) Linux distribution not supported" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
return ;
}
# Is the installed OS and the update to OS of the same distributor
if ( ! ( $ update2os =~ m/$installOS/i ) )
{
push @ { $ rsp - > { data } } ,
"$node: (Error) Cannot not update $installOS$version to $os. Linux distribution does not match" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
return ;
}
# Setup the repository for the node
my $ path ;
my $ out ;
if ( "$installOS$version" =~ m/sles10/i )
{
# SUSE repository path - http://10.1.100.1/install/sles10.3/s390x/1/
$ path = "http://$http$installDIR/$os/$arch/1/" ;
if ( ! ( - e "$installDIR/$os/$arch/1/" ) )
{
push @ { $ rsp - > { data } } ,
"$node: (Error) Missing install directory $installDIR/$os/$arch/1/" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
return ;
}
# Add installation source using rug
$ out = `ssh $node "rug sa -t zypp $path $os"` ;
push @ { $ rsp - > { data } } , "$node: $out" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
# Subscribe to catalog
$ out = `ssh $node "rug sub $os"` ;
push @ { $ rsp - > { data } } , "$node: $out" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
# Refresh services
$ out = `ssh $node "rug ref"` ;
push @ { $ rsp - > { data } } , "$node: $out" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
# Update
$ out = `ssh $node "rug up -y"` ;
push @ { $ rsp - > { data } } , "$node: $out" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
}
elsif ( "$installOS$version" =~ m/sles11/i )
{
# SUSE repository path - http://10.1.100.1/install/sles10.3/s390x/1/
$ path = "http://$http$installDIR/$os/$arch/1/" ;
if ( ! ( - e "$installDIR/$os/$arch/1/" ) )
{
push @ { $ rsp - > { data } } ,
"$node: (Error) Missing install directory $installDIR/$os/$arch/1/" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
return ;
}
# Add installation source using zypper
$ out = `ssh $node "zypper ar $path $installOS$version"` ;
push @ { $ rsp - > { data } } , "$node: $out" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
# Refresh services
$ out = `ssh $node "zypper ref"` ;
push @ { $ rsp - > { data } } , "$node: $out" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
# Update
$ out =
`ssh $node "zypper --non-interactive update --auto-agree-with-licenses"` ;
push @ { $ rsp - > { data } } , "$node: $out" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
}
elsif ( "$installOS$version" =~ m/rh/i )
{
# Red Hat repository path - http://10.0.0.1/install/rhel5.4/s390x/Server/
$ path = "http://$http$installDIR/$os/$arch/Server/" ;
if ( ! ( - e "$installDIR/$os/$arch/Server/" ) )
{
push @ { $ rsp - > { data } } ,
"$node: (Error) Missing install directory $installDIR/$os/$arch/Server/" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
return ;
}
# Create a yum repository file
my $ exist =
`ssh $node "test -e /etc/yum.repos.d/$os.repo && echo 'File exists'"` ;
if ( ! $ exist )
{
$ out = `ssh $node "echo [$os] >> /etc/yum.repos.d/$os.repo"` ;
$ out =
`ssh $node "echo baseurl=$path >> /etc/yum.repos.d/$os.repo"` ;
$ out = `ssh $node "echo enabled=1 >> /etc/yum.repos.d/$os.repo"` ;
}
# Send over release key
my $ key = "$installDIR/$os/$arch/RPM-GPG-KEY-redhat-release" ;
my $ tmp = "/tmp/RPM-GPG-KEY-redhat-release" ;
my $ tgt = "root@" . $ node ;
$ out = `scp $key $tgt:$tmp` ;
# Import key
$ out = `ssh $node "rpm --import $tmp"` ;
# Upgrade
$ out = `ssh $node "yum -y upgrade"` ;
push @ { $ rsp - > { data } } , "$node: $out" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
}
else
{
push @ { $ rsp - > { data } } ,
"$node: (Error) Could not update operating system" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
}
return ;
2010-07-12 00:40:50 +00:00
}
2010-11-24 07:07:56 +00:00
#-------------------------------------------------------------------------------
= head3 updatenodeappstat
This subroutine is used to handle the messages reported by
HPCbootstatus postscript . Update appstatus node attribute .
Arguments:
Returns:
0 - for success .
1 - for error .
= cut
#-----------------------------------------------------------------------------
sub updatenodeappstat
{
my $ request = shift ;
my $ callback = shift ;
my @ nodes = ( ) ;
my @ args = ( ) ;
if ( ref ( $ request - > { node } ) )
{
@ nodes = @ { $ request - > { node } } ;
}
else
{
if ( $ request - > { node } ) { @ nodes = ( $ request - > { node } ) ; }
}
if ( ref ( $ request - > { arg } ) )
{
@ args = @ { $ request - > { arg } } ;
}
else
{
@ args = ( $ request - > { arg } ) ;
}
if ( ( @ nodes > 0 ) && ( @ args > 0 ) )
{
2012-08-29 10:21:39 +00:00
2010-11-24 07:07:56 +00:00
# format: apps=status
my $ appstat = $ args [ 0 ] ;
2012-08-29 10:21:39 +00:00
my ( $ apps , $ newstatus ) = split ( /=/ , $ appstat ) ;
2010-11-24 07:07:56 +00:00
2012-08-09 04:07:40 +00:00
xCAT::TableUtils - > setAppStatus ( \ @ nodes , $ apps , $ newstatus ) ;
2010-11-24 07:07:56 +00:00
2012-08-29 10:21:39 +00:00
}
2010-11-24 07:07:56 +00:00
return 0 ;
}