2007-11-16 19:47:00 +00:00
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
package xCAT::PPC ;
use strict ;
2008-06-02 17:54:15 +00:00
use lib "/opt/xcat/lib/perl" ;
2007-11-16 19:47:00 +00:00
use xCAT::Table ;
2008-01-21 19:49:59 +00:00
use xCAT::Utils ;
2009-03-20 21:36:49 +00:00
use xCAT::SvrUtils ;
2008-04-12 14:53:11 +00:00
use xCAT::Usage ;
2007-11-16 19:47:00 +00:00
use POSIX "WNOHANG" ;
use Storable qw( freeze thaw ) ;
2008-05-02 19:15:23 +00:00
use Time::HiRes qw( gettimeofday sleep ) ;
2007-11-16 19:47:00 +00:00
use IO::Select ;
2008-03-19 17:44:30 +00:00
use Socket ;
2008-03-10 19:08:34 +00:00
use xCAT::PPCcli ;
2008-02-14 19:47:42 +00:00
use xCAT::GlobalDef ;
2008-03-19 17:44:30 +00:00
use xCAT::DBobjUtils ;
2008-09-25 03:04:56 +00:00
use xCAT_monitoring::monitorctrl ;
2008-10-21 02:50:13 +00:00
use Thread qw( yield ) ;
2007-11-16 19:47:00 +00:00
##########################################
# Globals
##########################################
my % modules = (
rinv = > "xCAT::PPCinv" ,
rpower = > "xCAT::PPCpower" ,
rvitals = > "xCAT::PPCvitals" ,
rscan = > "xCAT::PPCscan" ,
mkvm = > "xCAT::PPCvm" ,
rmvm = > "xCAT::PPCvm" ,
lsvm = > "xCAT::PPCvm" ,
chvm = > "xCAT::PPCvm" ,
rnetboot = > "xCAT::PPCboot" ,
getmacs = > "xCAT::PPCmac" ,
2008-01-11 16:15:51 +00:00
reventlog = > "xCAT::PPClog" ,
2009-01-06 11:06:25 +00:00
rspconfig = > "xCAT::PPCcfg" ,
rflash = > "xCAT::PPCrflash"
2007-11-16 19:47:00 +00:00
) ;
##########################################
# Database errors
##########################################
my % errmsg = (
NODE_UNDEF = > "Node not defined in '%s' database" ,
NO_ATTR = > "'%s' not defined in '%s' database" ,
DB_UNDEF = > "'%s' database not defined"
) ;
##########################################################################
# Invokes the callback with the specified message
##########################################################################
2008-02-18 20:26:39 +00:00
sub send_msg {
2007-11-16 19:47:00 +00:00
my $ request = shift ;
2008-02-18 20:26:39 +00:00
my $ ecode = shift ;
2007-11-16 19:47:00 +00:00
my % output ;
#################################################
# Called from child process - send to parent
#################################################
if ( exists ( $ request - > { pipe } ) ) {
my $ out = $ request - > { pipe } ;
2008-02-18 20:26:39 +00:00
$ output { errorcode } = $ ecode ;
2007-11-16 19:47:00 +00:00
$ output { data } = \ @ _ ;
print $ out freeze ( [ \ % output ] ) ;
2007-12-06 16:36:32 +00:00
print $ out "\nENDOFFREEZE6sK4ci\n" ;
2007-11-16 19:47:00 +00:00
}
#################################################
# Called from parent - invoke callback directly
#################################################
elsif ( exists ( $ request - > { callback } ) ) {
my $ callback = $ request - > { callback } ;
2008-02-18 20:26:39 +00:00
$ output { errorcode } = $ ecode ;
2007-11-16 19:47:00 +00:00
$ output { data } = \ @ _ ;
$ callback - > ( \ % output ) ;
}
}
##########################################################################
# Fork child to execute remote commands
##########################################################################
sub process_command {
my $ request = shift ;
my % nodes = ( ) ;
my $ callback = $ request - > { callback } ;
2008-03-19 17:44:30 +00:00
my $ sitetab = xCAT::Table - > new ( 'site' ) ;
2008-05-02 19:15:23 +00:00
my @ site = qw( ppcmaxp ppctimeout maxssh ppcretry fsptimeout ) ;
2007-11-16 19:47:00 +00:00
my $ start ;
2007-12-04 15:39:28 +00:00
#######################################
2008-05-02 19:15:23 +00:00
# Default site table attributes
#######################################
$ request - > { ppcmaxp } = 64 ;
$ request - > { ppctimeout } = 0 ;
$ request - > { fsptimeout } = 0 ;
$ request - > { ppcretry } = 3 ;
$ request - > { maxssh } = 10 ;
#######################################
# Get site table attributes
2007-12-04 15:39:28 +00:00
#######################################
if ( defined ( $ sitetab ) ) {
2008-05-02 19:15:23 +00:00
foreach ( @ site ) {
my ( $ ent ) = $ sitetab - > getAttribs ( { key = > $ _ } , 'value' ) ;
if ( defined ( $ ent ) ) {
$ request - > { $ _ } = $ ent - > { value } ;
}
2008-05-01 19:57:58 +00:00
}
2007-12-04 15:39:28 +00:00
}
2007-11-16 19:47:00 +00:00
if ( exists ( $ request - > { verbose } ) ) {
$ start = Time::HiRes:: gettimeofday ( ) ;
}
#######################################
# Group nodes based on command
#######################################
my $ nodes = preprocess_nodes ( $ request ) ;
if ( ! defined ( $ nodes ) ) {
return ( 1 ) ;
}
2008-09-25 03:04:56 +00:00
#get new node status
2009-03-25 02:56:58 +00:00
my % oldnodestatus = ( ) ; #saves the old node status
my @ allerrornodes = ( ) ;
2008-09-25 03:04:56 +00:00
my $ check = 0 ;
2009-03-24 03:12:03 +00:00
my $ global_check = 1 ;
if ( $ sitetab ) {
2009-03-24 19:44:23 +00:00
( my $ ref ) = $ sitetab - > getAttribs ( { key = > 'nodestatus' } , 'value' ) ;
2009-03-24 23:56:42 +00:00
if ( $ ref ) {
2009-03-24 19:44:23 +00:00
if ( $ ref - > { value } =~ /0|n|N/ ) { $ global_check = 0 ; }
2009-03-24 03:12:03 +00:00
}
}
2009-03-25 02:56:58 +00:00
my $ command = $ request - > { command } ;
if ( ( $ command eq 'rpower' ) || ( $ command eq 'rnetboot' ) ) {
my $ subcommand = "temp" ;
if ( $ command eq 'rpower' ) { $ subcommand = $ request - > { op } ; }
2009-03-24 03:12:03 +00:00
if ( ( $ global_check ) && ( $ subcommand ne 'stat' ) && ( $ subcommand ne 'status' ) && ( $ subcommand ne 'state' ) ) {
2009-03-25 02:56:58 +00:00
$ check = 1 ;
2008-09-25 03:04:56 +00:00
my $ noderange = $ request - > { node } ;
my @ allnodes = @$ noderange ;
2009-03-25 02:56:58 +00:00
#save the old status
my $ nodelisttab = xCAT::Table - > new ( 'nodelist' ) ;
if ( $ nodelisttab ) {
my $ tabdata = $ nodelisttab - > getNodesAttribs ( \ @ allnodes , [ 'node' , 'status' ] ) ;
foreach my $ node ( @ allnodes )
{
my $ tmp1 = $ tabdata - > { $ node } - > [ 0 ] ;
if ( $ tmp1 ) {
if ( $ tmp1 - > { status } ) { $ oldnodestatus { $ node } = $ tmp1 - > { status } ; }
else { $ oldnodestatus { $ node } = "" ; }
}
}
}
#print "oldstatus:" . Dumper(\%oldnodestatus);
#set the new status to the nodelist.status
my % newnodestatus = ( ) ;
my $ newstat ;
if ( ( $ subcommand eq 'off' ) || ( $ subcommand eq 'softoff' ) ) {
my $ newstat = $ ::STATUS_POWERING_OFF ;
$ newnodestatus { $ newstat } = \ @ allnodes ;
} else {
2008-09-25 03:04:56 +00:00
#get the current nodeset stat
if ( @ allnodes > 0 ) {
2009-03-25 02:56:58 +00:00
my $ nsh = { } ;
2009-03-20 21:36:49 +00:00
my ( $ ret , $ msg ) = xCAT::SvrUtils - > getNodesetStates ( \ @ allnodes , $ nsh ) ;
2009-03-25 02:56:58 +00:00
if ( ! $ ret ) {
2008-09-26 23:07:45 +00:00
foreach ( keys %$ nsh ) {
2009-03-25 02:56:58 +00:00
my $ newstat = xCAT_monitoring::monitorctrl - > getNodeStatusFromNodesetState ( $ _ , $ command ) ;
$ newnodestatus { $ newstat } = $ nsh - > { $ _ } ;
}
} else {
trace ( $ request , $ msg ) ;
}
2008-09-26 23:07:45 +00:00
}
}
2009-03-25 02:56:58 +00:00
#print "newstatus" . Dumper(\%newnodestatus);
xCAT_monitoring::monitorctrl:: setNodeStatusAttributes ( \ % newnodestatus , 1 ) ;
2008-09-26 23:07:45 +00:00
}
2008-09-25 03:04:56 +00:00
}
2008-10-21 02:50:13 +00:00
2009-03-25 02:56:58 +00:00
2008-10-21 02:50:13 +00:00
#######################################
# Fork process
#######################################
my $ children = 0 ;
my $ fds = new IO:: Select ;
2009-04-09 11:08:56 +00:00
# For the commands getmacs and rnetboot, each time
# to fork process, pick out the HMC that has the
# least process number created to connect to the HMC.
# After the process by preprocess_nodes, the $nodes
# variable has following structure:
# $nodes
# |hcp
# |[[hcp,node1_attr], [hcp,node2_attr] ...]
# |count //node number managed by the hcp
# |runprocess //the process number connect to the hcp
# |index //the index of node will be forked of the hcp
if ( $ request - > { command } =~ /^(getmacs|rnetboot)$/ ) {
my % pid_owner = ( ) ;
# Use the CHID signal to control the
#connection number of certain hcp
$ SIG { CHLD } = sub { my $ pid = 0 ; while ( ( $ pid = waitpid ( - 1 , WNOHANG ) ) > 0 )
{ $ nodes - > { $ pid_owner { $ pid } } { 'runprocess' } - - ; $ children - - ; } } ;
my $ hasnode = 1 ;
while ( $ hasnode ) {
while ( $ children >= $ request - > { ppcmaxp } ) {
my $ handlednodes = { } ;
child_response ( $ callback , $ fds , $ handlednodes ) ;
#update the node status to the nodelist.status table
if ( $ check ) {
updateNodeStatus ( $ handlednodes , \ @ allerrornodes ) ;
}
Time::HiRes:: sleep ( 0.1 ) ;
}
# Pick out the hcp which has least processes
my $ least_processes = $ request - > { maxssh } ;
my $ least_hcp ;
my $ got_one = 0 ;
while ( ! $ got_one ) {
$ hasnode = 0 ;
foreach my $ hcp ( keys %$ nodes ) {
if ( $ nodes - > { $ hcp } { 'index' } < $ nodes - > { $ hcp } { 'count' } ) {
$ hasnode = 1 ;
if ( $ nodes - > { $ hcp } { 'runprocess' } < $ least_processes ) {
$ least_processes = $ nodes - > { $ hcp } { 'runprocess' } ;
$ least_hcp = $ hcp ;
}
}
}
if ( ! $ hasnode ) {
# There are no node in the $nodes
goto ENDOFFORK ;
}
if ( $ least_processes < $ request - > { maxssh } ) {
$ got_one = 1 ;
} else {
my $ handlednodes = { } ;
child_response ( $ callback , $ fds , $ handlednodes ) ;
#update the node status to the nodelist.status table
if ( $ check ) {
updateNodeStatus ( $ handlednodes , \ @ allerrornodes ) ;
}
Time::HiRes:: sleep ( 0.1 ) ;
}
}
my ( $ pipe , $ pid ) = fork_cmd ( $ nodes - > { $ least_hcp } { 'nodegroup' } - > [ $ nodes - > { $ least_hcp } { 'index' } ] - > [ 0 ] ,
$ nodes - > { $ least_hcp } { 'nodegroup' } - > [ $ nodes - > { $ least_hcp } { 'index' } ] - > [ 1 ] , $ request ) ;
if ( $ pid ) {
$ pid_owner { $ pid } = $ least_hcp ;
$ nodes - > { $ least_hcp } { 'index' } + + ;
$ nodes - > { $ least_hcp } { 'runprocess' } + + ;
}
if ( $ pipe ) {
$ fds - > add ( $ pipe ) ;
$ children + + ;
}
2008-05-01 19:57:58 +00:00
}
2009-04-09 11:08:56 +00:00
} else {
$ SIG { CHLD } = sub { while ( waitpid ( - 1 , WNOHANG ) > 0 ) { $ children - - ; } } ;
my $ hw ;
my $ sessions ;
foreach ( @$ nodes ) {
while ( $ children >= $ request - > { ppcmaxp } ) {
my $ handlednodes = { } ;
child_response ( $ callback , $ fds , $ handlednodes ) ;
#update the node status to the nodelist.status table
if ( $ check ) {
updateNodeStatus ( $ handlednodes , \ @ allerrornodes ) ;
}
Time::HiRes:: sleep ( 0.1 ) ;
}
###################################
# sleep between connects to same
# HMC/IVM so as not to overwelm it
###################################
if ( $ hw ne @$ _ [ 0 ] ) {
$ sessions = 1 ;
} elsif ( $ sessions + + >= $ request - > { maxssh } ) {
sleep ( 1 ) ;
$ sessions = 1 ;
}
$ hw = @$ _ [ 0 ] ;
my ( $ pipe ) = fork_cmd ( @$ _ [ 0 ] , @$ _ [ 1 ] , $ request ) ;
if ( $ pipe ) {
$ fds - > add ( $ pipe ) ;
$ children + + ;
}
2007-11-16 19:47:00 +00:00
}
}
2009-04-09 11:08:56 +00:00
ENDOFFORK:
2007-11-16 19:47:00 +00:00
#######################################
# Process responses from children
#######################################
2008-10-21 02:50:13 +00:00
while ( $ fds - > count > 0 or $ children > 0 ) {
2009-03-25 02:56:58 +00:00
my $ handlednodes = { } ;
child_response ( $ callback , $ fds , $ handlednodes ) ;
2008-10-21 02:50:13 +00:00
#update the node status to the nodelist.status table
if ( $ check ) {
2009-03-25 02:56:58 +00:00
updateNodeStatus ( $ handlednodes , \ @ allerrornodes ) ;
2008-10-21 02:50:13 +00:00
}
2008-05-02 19:15:23 +00:00
Time::HiRes:: sleep ( 0.1 ) ;
2008-02-18 20:00:34 +00:00
}
2008-10-21 02:50:13 +00:00
#drain one more time
my $ rc = 1 ;
while ( $ rc > 0 ) {
2009-03-25 02:56:58 +00:00
my $ handlednodes = { } ;
$ rc = child_response ( $ callback , $ fds , $ handlednodes ) ;
2008-10-21 02:50:13 +00:00
#update the node status to the nodelist.status table
if ( $ check ) {
2009-03-25 02:56:58 +00:00
updateNodeStatus ( $ handlednodes , \ @ allerrornodes ) ;
2008-10-21 02:50:13 +00:00
}
}
2007-11-16 19:47:00 +00:00
if ( exists ( $ request - > { verbose } ) ) {
2008-06-02 17:54:15 +00:00
my $ elapsed = Time::HiRes:: gettimeofday ( ) - $ start ;
my $ msg = sprintf ( "Total Elapsed Time: %.3f sec\n" , $ elapsed ) ;
trace ( $ request , $ msg ) ;
2007-11-16 19:47:00 +00:00
}
2008-09-25 03:04:56 +00:00
2009-03-25 02:56:58 +00:00
if ( $ check ) {
#print "allerrornodes=@allerrornodes\n";
#revert the status back for there is no-op for the nodes
my % old = ( ) ;
foreach my $ node ( @ allerrornodes ) {
my $ stat = $ oldnodestatus { $ node } ;
if ( exists ( $ old { $ stat } ) ) {
my $ pa = $ old { $ stat } ;
push ( @$ pa , $ node ) ;
}
else {
$ old { $ stat } = [ $ node ] ;
}
}
xCAT_monitoring::monitorctrl:: setNodeStatusAttributes ( \ % old , 1 ) ;
}
2008-10-21 02:50:13 +00:00
return ( 0 ) ;
}
2008-09-25 03:04:56 +00:00
2008-10-21 02:50:13 +00:00
##########################################################################
# updateNodeStatus
##########################################################################
sub updateNodeStatus {
2009-03-25 02:56:58 +00:00
my $ handlednodes = shift ;
my $ allerrornodes = shift ;
foreach my $ node ( keys ( %$ handlednodes ) ) {
if ( $ handlednodes - > { $ node } == - 1 ) { push ( @$ allerrornodes , $ node ) ; }
2008-09-25 03:04:56 +00:00
}
2007-11-16 19:47:00 +00:00
}
2007-12-06 16:36:32 +00:00
##########################################################################
# Verbose mode (-V)
##########################################################################
sub trace {
my $ request = shift ;
2008-06-02 17:54:15 +00:00
my $ msg = shift ;
2007-12-06 16:36:32 +00:00
my ( $ sec , $ min , $ hour , $ mday , $ mon , $ yr , $ wday , $ yday , $ dst ) = localtime ( time ) ;
2008-06-02 17:54:15 +00:00
my $ formatted = sprintf "%02d:%02d:%02d %5d %s" , $ hour , $ min , $ sec , $$ , $ msg ;
2008-02-18 20:00:34 +00:00
my $ callback = $ request - > { callback } ;
2008-06-02 17:54:15 +00:00
$ callback - > ( { data = > [ $ formatted ] } ) ;
2007-12-06 16:36:32 +00:00
}
2007-11-16 19:47:00 +00:00
##########################################################################
# Send response from child process back to xCAT client
##########################################################################
sub child_response {
my $ callback = shift ;
my $ fds = shift ;
2008-09-25 03:04:56 +00:00
my $ errornodes = shift ;
2007-11-16 19:47:00 +00:00
my @ ready_fds = $ fds - > can_read ( 1 ) ;
2008-10-21 02:50:13 +00:00
my $ rc = @ ready_fds ;
2007-11-16 19:47:00 +00:00
foreach my $ rfh ( @ ready_fds ) {
2008-06-02 17:54:15 +00:00
my $ data = <$rfh> ;
2007-11-16 19:47:00 +00:00
#################################
2007-12-06 16:36:32 +00:00
# Read from child process
2007-11-16 19:47:00 +00:00
#################################
2008-06-02 17:54:15 +00:00
if ( defined ( $ data ) ) {
2007-12-06 16:36:32 +00:00
while ( $ data !~ /ENDOFFREEZE6sK4ci/ ) {
$ data . = <$rfh> ;
}
my $ responses = thaw ( $ data ) ;
foreach ( @$ responses ) {
2008-09-25 03:04:56 +00:00
#save the nodes that has errors for node status monitoring
if ( ( exists ( $ _ - > { errorcode } ) ) && ( $ _ - > { errorcode } != 0 ) ) {
2008-10-21 02:50:13 +00:00
if ( $ errornodes ) { $ errornodes - > { $ _ - > { node } - > [ 0 ] - > { name } - > [ 0 ] } = - 1 ; }
2008-11-07 13:34:47 +00:00
} else {
2008-09-25 03:04:56 +00:00
if ( $ errornodes ) { $ errornodes - > { $ _ - > { node } - > [ 0 ] - > { name } - > [ 0 ] } = 1 ; }
2008-10-21 02:50:13 +00:00
}
2007-12-06 16:36:32 +00:00
$ callback - > ( $ _ ) ;
}
next ;
2007-11-16 19:47:00 +00:00
}
#################################
2007-12-06 16:36:32 +00:00
# Done - close handle
2007-11-16 19:47:00 +00:00
#################################
$ fds - > remove ( $ rfh ) ;
close ( $ rfh ) ;
2007-12-06 16:36:32 +00:00
}
2008-10-21 02:50:13 +00:00
yield ; #Try to avoid useless iterations as much as possible
return $ rc ;
2007-11-16 19:47:00 +00:00
}
2008-03-19 17:44:30 +00:00
##########################################################################
# Finds attributes for given node is various databases
##########################################################################
sub resolve_hcp {
my $ request = shift ;
my $ noderange = shift ;
my @ nodegroup = ( ) ;
2009-01-19 08:58:29 +00:00
my $ tab = ( $ request - > { hwtype } eq "fsp" or $ request - > { hwtype } eq "bpa" ) ? "ppcdirect" : "ppchcp" ;
2008-03-19 17:44:30 +00:00
my $ db = xCAT::Table - > new ( $ tab ) ;
####################################
# Database not defined
####################################
if ( ! defined ( $ db ) ) {
send_msg ( $ request , 1 , sprintf ( $ errmsg { DB_UNDEF } , $ tab ) ) ;
return undef ;
}
####################################
# Process each node
####################################
2008-05-02 19:46:29 +00:00
foreach my $ hcp ( @$ noderange ) {
my ( $ ent ) = $ db - > getAttribs ( { hcp = > $ hcp } , "hcp" ) ;
2008-03-19 17:44:30 +00:00
if ( ! defined ( $ ent ) ) {
2008-05-02 19:46:29 +00:00
my $ msg = sprintf ( "$hcp: $errmsg{NODE_UNDEF}" , $ tab ) ;
2008-03-19 17:44:30 +00:00
send_msg ( $ request , 1 , $ msg ) ;
next ;
}
2008-05-02 19:46:29 +00:00
################################
# Get userid and password
################################
my @ cred = xCAT::PPCdb:: credentials ( $ hcp , $ request - > { hwtype } ) ;
$ request - > { $ hcp } { cred } = \ @ cred ;
2008-03-19 17:44:30 +00:00
################################
# Save values
################################
2008-05-02 19:46:29 +00:00
push @ nodegroup , [ $ hcp ] ;
2008-03-19 17:44:30 +00:00
}
return ( \ @ nodegroup ) ;
}
2007-11-16 19:47:00 +00:00
##########################################################################
# Group nodes depending on command
##########################################################################
sub preprocess_nodes {
my $ request = shift ;
my $ noderange = $ request - > { node } ;
my $ method = $ request - > { method } ;
my % nodehash = ( ) ;
my @ nodegroup = ( ) ;
2009-04-09 11:08:56 +00:00
my % hcpgroup = ( ) ;
2007-11-16 19:47:00 +00:00
my % tabs = ( ) ;
2008-03-19 17:44:30 +00:00
my $ netwk ;
2007-11-16 19:47:00 +00:00
########################################
# Special cases
# rscan - Nodes are hardware control pts
# Direct-attached FSP
########################################
2008-05-27 13:56:51 +00:00
if ( ( $ request - > { command } =~ /^(rscan|rspconfig)$/ ) or
2009-01-19 08:58:29 +00:00
( $ request - > { hwtype } eq "fsp" or $ request - > { hwtype } eq "bpa" ) ) {
2008-03-19 17:44:30 +00:00
my $ result = resolve_hcp ( $ request , $ noderange ) ;
return ( $ result ) ;
}
##########################################
# Special processing - rnetboot
##########################################
if ( $ request - > { command } eq "rnetboot" ) {
$ netwk = resolve_netwk ( $ request , $ noderange ) ;
if ( ! defined ( %$ netwk ) ) {
2007-11-16 19:47:00 +00:00
return undef ;
}
}
##########################################
# Open databases needed
##########################################
2008-03-19 14:18:39 +00:00
foreach ( qw( ppc vpd nodetype ) ) {
2007-11-16 19:47:00 +00:00
$ tabs { $ _ } = xCAT::Table - > new ( $ _ ) ;
if ( ! exists ( $ tabs { $ _ } ) ) {
2008-02-18 20:26:39 +00:00
send_msg ( $ request , 1 , sprintf ( $ errmsg { DB_UNDEF } , $ _ ) ) ;
2007-11-16 19:47:00 +00:00
return undef ;
}
}
2009-01-15 03:01:54 +00:00
####################
# $f1 and $f2 are the flags for rflash, to check if there are BPAs and CECs at the same time.
#################
my $ f1 = 0 ;
my $ f2 = 0 ;
2007-11-16 19:47:00 +00:00
##########################################
# Group nodes
##########################################
foreach my $ node ( @$ noderange ) {
my $ d = resolve ( $ request , $ node , \ % tabs ) ;
######################################
# Error locating node attributes
######################################
if ( ref ( $ d ) ne 'ARRAY' ) {
2008-02-18 20:26:39 +00:00
send_msg ( $ request , 1 , "$node: $d" ) ;
2007-11-16 19:47:00 +00:00
next ;
}
######################################
# Get data values
######################################
my $ hcp = @$ d [ 3 ] ;
my $ mtms = @$ d [ 2 ] ;
2009-01-15 03:01:54 +00:00
if ( $ request - > { command } eq "rflash" ) {
if ( @$ d [ 4 ] =~ /^(fsp|lpar)$/ ) {
$ f1 = 1 ;
} else {
2009-03-12 07:28:21 +00:00
$ f2 = 1 ;
my $ exargs = $ request - > { arg } ;
my $ t = xCAT::PPCrflash:: print_var ( $ exargs , "exargs" ) ;
if ( grep ( /commit/ , @$ exargs ) != 0 || grep ( /recover/ , @$ exargs ) != 0 ) {
send_msg ( $ request , 1 , "When run \"rflash\" with the \"commit\" or \"recover\" operation, the noderange cannot be BPA and can only be CEC or LPAR." ) ;
send_msg ( $ request , 1 , "And then, it will do the operation for both managed systems and power subsystems." ) ;
return undef ;
}
2009-01-15 03:01:54 +00:00
}
}
2007-11-16 19:47:00 +00:00
$ nodehash { $ hcp } { $ mtms } { $ node } = $ d ;
}
2009-01-15 03:01:54 +00:00
if ( $ f1 * $ f2 ) {
send_msg ( $ request , 1 , "The argument noderange of rflash can't be BPA and CEC(or LPAR) at the same time" ) ;
return undef ;
}
2007-11-16 19:47:00 +00:00
##########################################
2008-05-02 19:46:29 +00:00
# Get userid and password
##########################################
while ( my ( $ hcp , $ hash ) = each ( % nodehash ) ) {
my @ cred = xCAT::PPCdb:: credentials ( $ hcp , $ request - > { hwtype } ) ;
$ request - > { $ hcp } { cred } = \ @ cred ;
}
##########################################
2007-11-16 19:47:00 +00:00
# Group the nodes - we will fork one
# process per nodegroup array element.
##########################################
##########################################
# These commands are grouped on an
# LPAR-by-LPAR basis - fork one process
# per LPAR.
##########################################
2008-05-02 19:15:23 +00:00
if ( $ method =~ /^(getmacs|rnetboot)$/ ) {
2007-11-16 19:47:00 +00:00
while ( my ( $ hcp , $ hash ) = each ( % nodehash ) ) {
2009-04-09 11:08:56 +00:00
@ nodegroup = ( ) ;
2007-11-16 19:47:00 +00:00
while ( my ( $ mtms , $ h ) = each ( %$ hash ) ) {
while ( my ( $ lpar , $ d ) = each ( %$ h ) ) {
push @$ d , $ lpar ;
2008-03-19 17:44:30 +00:00
##########################
# Save network info
##########################
if ( $ method =~ /^rnetboot$/ ) {
push @$ d , $ netwk - > { $ lpar } ;
}
2007-11-16 19:47:00 +00:00
push @ nodegroup , [ $ hcp , $ d ] ;
}
}
2009-04-09 11:08:56 +00:00
$ hcpgroup { $ hcp } { 'nodegroup' } = [ @ nodegroup ] ;
$ hcpgroup { $ hcp } { 'count' } = $# nodegroup + 1 ;
$ hcpgroup { $ hcp } { 'runprocess' } = 0 ;
$ hcpgroup { $ hcp } { 'index' } = 0 ;
2007-11-16 19:47:00 +00:00
}
2009-04-09 11:08:56 +00:00
return ( \ % hcpgroup ) ;
2007-11-16 19:47:00 +00:00
}
2009-04-09 11:08:56 +00:00
2007-11-16 19:47:00 +00:00
##########################################
# Power control commands are grouped
# by CEC which is the smallest entity
# that commands can be sent to in parallel.
# If commands are sent in parallel to a
# single CEC, the CEC itself will serialize
# them - fork one process per CEC.
##########################################
elsif ( $ method =~ /^powercmd/ ) {
while ( my ( $ hcp , $ hash ) = each ( % nodehash ) ) {
while ( my ( $ mtms , $ h ) = each ( %$ hash ) ) {
push @ nodegroup , [ $ hcp , $ h ] ;
}
}
return ( \ @ nodegroup ) ;
}
##########################################
# All other commands are grouped by
# hardware control point - fork one
# process per hardware control point.
##########################################
while ( my ( $ hcp , $ hash ) = each ( % nodehash ) ) {
push @ nodegroup , [ $ hcp , $ hash ] ;
}
return ( \ @ nodegroup ) ;
}
2008-03-19 17:44:30 +00:00
##########################################################################
# Finds attributes for given node is various databases
##########################################################################
sub resolve_netwk {
my $ request = shift ;
my $ noderange = shift ;
my % nethash = xCAT::DBobjUtils - > getNetwkInfo ( $ noderange ) ;
my $ tab = xCAT::Table - > new ( 'mac' ) ;
my % result = ( ) ;
2008-04-15 18:51:35 +00:00
my $ ip ;
2008-03-19 17:44:30 +00:00
#####################################
# Network attributes undefined
#####################################
2008-06-02 17:54:15 +00:00
if ( ! % nethash ) {
2008-03-19 17:44:30 +00:00
send_msg ( $ request , 1 , sprintf ( $ errmsg { NODE_UNDEF } , "networks" ) ) ;
return undef ;
}
#####################################
# mac database undefined
#####################################
if ( ! defined ( $ tab ) ) {
send_msg ( $ request , 1 , sprintf ( $ errmsg { DB_UNDEF } , "mac" ) ) ;
return undef ;
}
foreach ( @$ noderange ) {
#################################
# Get gateway (-G)
#################################
if ( ! exists ( $ nethash { $ _ } ) ) {
my $ msg = sprintf ( "$_: $errmsg{NODE_UNDEF}" , "networks" ) ;
send_msg ( $ request , 1 , $ msg ) ;
next ;
}
2008-04-02 12:43:12 +00:00
my $ gateway = $ nethash { $ _ } { gateway } ;
if ( ! defined ( $ gateway ) ) {
2008-03-19 17:44:30 +00:00
my $ msg = sprintf ( "$_: $errmsg{NO_ATTR}" , "gateway" , "networks" ) ;
send_msg ( $ request , 1 , $ msg ) ;
next ;
}
2008-04-15 18:51:35 +00:00
$ ip = xCAT::Utils:: toIP ( $ gateway ) ;
if ( @$ ip [ 0 ] != 0 ) {
2008-04-02 12:43:12 +00:00
send_msg ( $ request , 1 , "$_: Cannot resolve '$gateway'" ) ;
next ;
}
2008-04-15 18:51:35 +00:00
my $ gateway_ip = @$ ip [ 1 ] ;
2008-03-19 17:44:30 +00:00
#################################
# Get server (-S)
#################################
my $ server = xCAT::Utils - > GetMasterNodeName ( $ _ ) ;
if ( $ server == 1 ) {
send_msg ( $ request , 1 , "$_: Unable to identify master" ) ;
next ;
}
2008-04-18 15:20:53 +00:00
$ ip = xCAT::Utils:: toIP ( $ server ) ;
2008-04-15 18:51:35 +00:00
if ( @$ ip [ 0 ] != 0 ) {
2008-04-02 12:43:12 +00:00
send_msg ( $ request , 1 , "$_: Cannot resolve '$server'" ) ;
next ;
}
2008-04-15 18:51:35 +00:00
my $ server_ip = @$ ip [ 1 ] ;
2008-04-02 12:43:12 +00:00
#################################
# Get client (-C)
#################################
2008-04-18 15:20:53 +00:00
$ ip = xCAT::Utils:: toIP ( $ _ ) ;
2008-04-15 18:51:35 +00:00
if ( @$ ip [ 0 ] != 0 ) {
2008-04-02 12:43:12 +00:00
send_msg ( $ request , 1 , "$_: Cannot resolve '$_'" ) ;
next ;
}
2008-04-15 18:51:35 +00:00
my $ client_ip = @$ ip [ 1 ] ;
2008-03-19 17:44:30 +00:00
#################################
# Get mac-address (-m)
#################################
2008-11-07 13:34:47 +00:00
my ( $ ent ) = $ tab - > getNodeAttribs ( $ _ , [ 'mac' ] ) ;
2008-03-19 17:44:30 +00:00
if ( ! defined ( $ ent ) ) {
my $ msg = sprintf ( "$_: $errmsg{NO_ATTR}" , "mac" , "mac" ) ;
send_msg ( $ request , 1 , $ msg ) ;
next ;
}
#################################
# Save results
#################################
2008-04-02 12:43:12 +00:00
$ result { $ _ } { gateway } = $ gateway_ip ;
$ result { $ _ } { server } = $ server_ip ;
$ result { $ _ } { client } = $ client_ip ;
2008-03-19 17:44:30 +00:00
$ result { $ _ } { mac } = $ ent - > { mac } ;
}
return ( \ % result ) ;
}
2007-11-16 19:47:00 +00:00
##########################################################################
2008-03-19 17:44:30 +00:00
# Finds attributes for given node is various databases
2007-11-16 19:47:00 +00:00
##########################################################################
sub resolve {
my $ request = shift ;
my $ node = shift ;
my $ tabs = shift ;
2008-03-20 18:32:18 +00:00
my @ attribs = qw( id pprofile parent hcp ) ;
2007-11-16 19:47:00 +00:00
my @ values = ( ) ;
#################################
# Get node type
#################################
2008-07-23 12:33:27 +00:00
my $ ent = $ tabs - > { nodetype } - > getNodeAttribs ( $ node , [ qw( nodetype node ) ] ) ;
2007-11-16 19:47:00 +00:00
if ( ! defined ( $ ent ) ) {
2008-07-23 12:33:27 +00:00
return ( sprintf ( $ errmsg { NODE_UNDEF } , "nodetype" ) ) ;
2007-11-16 19:47:00 +00:00
}
#################################
# Check for type
#################################
if ( ! exists ( $ ent - > { nodetype } ) ) {
2008-07-23 12:33:27 +00:00
return ( sprintf ( $ errmsg { NO_ATTR } , "nodetype" , "nodetype" ) ) ;
2007-11-16 19:47:00 +00:00
}
#################################
# Check for valid "type"
#################################
2008-02-14 19:47:42 +00:00
my ( $ type ) = grep (
/^$::NODETYPE_LPAR|$::NODETYPE_OSI|$::NODETYPE_BPA|$::NODETYPE_FSP$/ ,
split /,/ , $ ent - > { nodetype } ) ;
2008-02-13 19:26:13 +00:00
if ( ! defined ( $ type ) ) {
2007-11-16 19:47:00 +00:00
return ( "Invalid node type: $ent->{nodetype}" ) ;
}
#################################
# Get attributes
#################################
2008-11-07 13:34:47 +00:00
my ( $ att ) = $ tabs - > { ppc } - > getNodeAttribs ( $ node , \ @ attribs ) ;
2007-11-16 19:47:00 +00:00
if ( ! defined ( $ att ) ) {
return ( sprintf ( $ errmsg { NODE_UNDEF } , "ppc" ) ) ;
}
#################################
# Special lpar processing
#################################
2008-02-14 19:47:42 +00:00
if ( $ type =~ /^$::NODETYPE_OSI|$::NODETYPE_LPAR$/ ) {
2007-11-16 19:47:00 +00:00
$ att - > { bpa } = 0 ;
$ att - > { type } = "lpar" ;
2007-11-19 16:39:20 +00:00
$ att - > { node } = $ att - > { parent } ;
2007-11-16 19:47:00 +00:00
2007-11-19 16:39:20 +00:00
if ( ! exists ( $ att - > { parent } ) ) {
return ( sprintf ( $ errmsg { NO_ATTR } , "parent" , "ppc" ) ) ;
2007-11-16 19:47:00 +00:00
}
#############################
# Get BPA (if any)
#############################
if ( ( $ request - > { command } eq "rvitals" ) &&
( $ request - > { method } =~ /^all|temp$/ ) ) {
2008-11-07 13:34:47 +00:00
my ( $ ent ) = $ tabs - > { ppc } - > getNodeAttribs ( $ att - > { parent } , [ 'parent' ] ) ;
2007-11-16 19:47:00 +00:00
#############################
# Find MTMS in vpd database
#############################
2007-11-19 16:39:20 +00:00
if ( ( defined ( $ ent ) ) && exists ( $ ent - > { parent } ) ) {
2007-11-16 19:47:00 +00:00
my @ attrs = qw( mtm serial ) ;
2008-11-07 13:34:47 +00:00
my ( $ vpd ) = $ tabs - > { vpd } - > getAttribs ( $ ent - > { parent } , \ @ attrs ) ;
2007-11-16 19:47:00 +00:00
if ( ! defined ( $ vpd ) ) {
return ( sprintf ( $ errmsg { NO_UNDEF } , "vpd" ) ) ;
}
########################
# Verify attributes
########################
foreach ( @ attrs ) {
if ( ! exists ( $ vpd - > { $ _ } ) ) {
return ( sprintf ( $ errmsg { NO_ATTR } , $ _ , "vpd" ) ) ;
}
}
$ att - > { bpa } = "$vpd->{mtm}*$vpd->{serial}" ;
}
}
}
#################################
# Optional and N/A fields
#################################
2008-02-14 19:47:42 +00:00
elsif ( $ type =~ /^$::NODETYPE_FSP$/ ) {
2008-03-20 18:32:18 +00:00
$ att - > { pprofile } = 0 ;
$ att - > { id } = 0 ;
$ att - > { fsp } = 0 ;
$ att - > { node } = $ node ;
$ att - > { type } = $ type ;
$ att - > { parent } = exists ( $ att - > { parent } ) ? $ att - > { parent } : 0 ;
$ att - > { bpa } = $ att - > { parent } ;
2007-11-16 19:47:00 +00:00
}
2008-03-06 15:17:30 +00:00
elsif ( $ type =~ /^$::NODETYPE_BPA$/ ) {
2008-03-20 18:32:18 +00:00
$ att - > { pprofile } = 0 ;
$ att - > { id } = 0 ;
$ att - > { bpa } = 0 ;
$ att - > { parent } = 0 ;
$ att - > { fsp } = 0 ;
$ att - > { node } = $ node ;
$ att - > { type } = $ type ;
2007-11-16 19:47:00 +00:00
}
#################################
# Find MTMS in vpd database
#################################
my @ attrs = qw( mtm serial ) ;
2008-11-07 13:34:47 +00:00
my ( $ vpd ) = $ tabs - > { vpd } - > getNodeAttribs ( $ att - > { node } , \ @ attrs ) ;
2007-11-16 19:47:00 +00:00
if ( ! defined ( $ vpd ) ) {
2008-06-02 17:54:15 +00:00
return ( sprintf ( $ errmsg { NODE_UNDEF } , "vpd: ($att->{node})" ) ) ;
2007-11-16 19:47:00 +00:00
}
################################
# Verify both vpd attributes
################################
foreach ( @ attrs ) {
if ( ! exists ( $ vpd - > { $ _ } ) ) {
2008-06-02 17:54:15 +00:00
return ( sprintf ( $ errmsg { NO_ATTR } , $ _ , "vpd: ($att->{node})" ) ) ;
2007-11-16 19:47:00 +00:00
}
}
$ att - > { fsp } = "$vpd->{mtm}*$vpd->{serial}" ;
#################################
# Verify required attributes
#################################
foreach my $ at ( @ attribs ) {
if ( ! exists ( $ att - > { $ at } ) ) {
return ( sprintf ( $ errmsg { NO_ATTR } , $ at , "ppc" ) ) ;
}
}
#################################
# Build array of data
#################################
2008-03-20 18:32:18 +00:00
foreach ( qw( id pprofile fsp hcp type bpa ) ) {
2007-11-16 19:47:00 +00:00
push @ values , $ att - > { $ _ } ;
}
return ( \ @ values ) ;
}
##########################################################################
# Forks a process to run the ssh command
##########################################################################
sub fork_cmd {
my $ host = shift ;
my $ nodes = shift ;
my $ request = shift ;
#######################################
# Pipe childs output back to parent
#######################################
my $ parent ;
my $ child ;
pipe $ parent , $ child ;
2008-01-21 19:49:59 +00:00
my $ pid = xCAT::Utils - > xfork ;
2007-11-16 19:47:00 +00:00
if ( ! defined ( $ pid ) ) {
###################################
# Fork error
###################################
2008-02-18 20:26:39 +00:00
send_msg ( $ request , 1 , "Fork error: $!" ) ;
2007-11-16 19:47:00 +00:00
return undef ;
}
elsif ( $ pid == 0 ) {
###################################
# Child process
###################################
close ( $ parent ) ;
$ request - > { pipe } = $ child ;
2008-05-02 19:15:23 +00:00
invoke_cmd ( $ host , $ nodes , $ request ) ;
2007-11-16 19:47:00 +00:00
exit ( 0 ) ;
}
else {
###################################
# Parent process
###################################
close ( $ child ) ;
2009-04-09 11:08:56 +00:00
return ( $ parent , $ pid ) ;
2007-11-16 19:47:00 +00:00
}
return ( 0 ) ;
}
##########################################################################
# Run the command, process the response, and send to parent
##########################################################################
sub invoke_cmd {
my $ host = shift ;
my $ nodes = shift ;
my $ request = shift ;
my $ hwtype = $ request - > { hwtype } ;
my $ verbose = $ request - > { verbose } ;
my @ exp ;
2007-12-07 16:10:10 +00:00
my $ verbose_log ;
2007-11-16 19:47:00 +00:00
my @ outhash ;
2008-05-27 13:56:51 +00:00
2007-11-16 19:47:00 +00:00
########################################
# Direct-attached FSP handler
########################################
2009-01-19 08:58:29 +00:00
if ( $ hwtype eq "fsp" or $ hwtype eq "bpa" ) {
2008-04-15 18:51:35 +00:00
2008-03-10 19:08:34 +00:00
####################################
# Dynamically load FSP module
####################################
eval { require xCAT::PPCfsp } ;
if ( $@ ) {
send_msg ( $ request , 1 , $@ ) ;
return ;
}
2008-05-02 19:15:23 +00:00
my @ exp = xCAT::PPCfsp:: connect ( $ request , $ host ) ;
2007-11-16 19:47:00 +00:00
2007-12-06 19:09:40 +00:00
####################################
# Error connecting
####################################
if ( ref ( $ exp [ 0 ] ) ne "LWP::UserAgent" ) {
2008-02-18 20:26:39 +00:00
send_msg ( $ request , 1 , $ exp [ 0 ] ) ;
2007-12-06 19:09:40 +00:00
return ;
}
my $ result = xCAT::PPCfsp:: handler ( $ host , $ request , \ @ exp ) ;
####################################
# Output verbose Perl::LWP
####################################
if ( $ verbose ) {
2007-12-07 16:10:10 +00:00
$ verbose_log = $ exp [ 3 ] ;
my % output ;
$ output { data } = [ $$ verbose_log ] ;
unshift @$ result , \ % output ;
2007-12-06 19:09:40 +00:00
}
2007-11-16 19:47:00 +00:00
my $ out = $ request - > { pipe } ;
print $ out freeze ( $ result ) ;
2007-12-06 16:36:32 +00:00
print $ out "\nENDOFFREEZE6sK4ci\n" ;
2007-11-16 19:47:00 +00:00
return ;
}
2007-12-07 16:10:10 +00:00
2007-11-16 19:47:00 +00:00
########################################
2007-12-07 16:10:10 +00:00
# HMC and IVM-managed handler
2007-11-16 19:47:00 +00:00
# Connect to list of remote servers
########################################
foreach ( split /,/ , $ host ) {
2008-05-02 19:15:23 +00:00
@ exp = xCAT::PPCcli:: connect ( $ request , $ hwtype , $ _ ) ;
2007-11-16 19:47:00 +00:00
####################################
# Successfully connected
####################################
if ( ref ( $ exp [ 0 ] ) eq "Expect" ) {
last ;
}
}
########################################
# Error connecting
########################################
if ( ref ( $ exp [ 0 ] ) ne "Expect" ) {
2008-02-18 20:26:39 +00:00
send_msg ( $ request , 1 , $ exp [ 0 ] ) ;
2007-11-16 19:47:00 +00:00
return ;
}
########################################
# Process specific command
########################################
my $ result = runcmd ( $ request , $ nodes , \ @ exp ) ;
2007-12-06 19:09:40 +00:00
########################################
# Close connection to remote server
########################################
xCAT::PPCcli:: disconnect ( \ @ exp ) ;
2007-12-06 16:36:32 +00:00
########################################
2007-12-07 16:10:10 +00:00
# Get verbose Expect output
2007-12-06 16:36:32 +00:00
########################################
if ( $ verbose ) {
2007-12-07 16:10:10 +00:00
$ verbose_log = $ exp [ 6 ] ;
2007-12-06 16:36:32 +00:00
}
2007-11-16 19:47:00 +00:00
########################################
# Return error
########################################
if ( ref ( $ result ) ne 'ARRAY' ) {
2008-02-18 20:26:39 +00:00
send_msg ( $ request , 1 , $$ verbose_log . $ result ) ;
2007-11-16 19:47:00 +00:00
return ;
}
########################################
2007-12-07 16:10:10 +00:00
# Prepend verbose output
########################################
if ( defined ( $ verbose_log ) ) {
my % output ;
$ output { data } = [ $$ verbose_log ] ;
push @ outhash , \ % output ;
}
########################################
2007-11-16 19:47:00 +00:00
# Send result back to parent process
########################################
2007-12-06 16:36:32 +00:00
if ( @$ result [ 0 ] eq "FORMATDATA6sK4ci" ) {
2007-11-16 19:47:00 +00:00
my $ out = $ request - > { pipe } ;
2007-12-07 16:10:10 +00:00
push @ outhash , @$ result [ 1 ] ;
print $ out freeze ( [ @ outhash ] ) ;
2007-12-06 16:36:32 +00:00
print $ out "\nENDOFFREEZE6sK4ci\n" ;
2007-11-16 19:47:00 +00:00
return ;
}
########################################
# Format and send back to parent
########################################
foreach ( @$ result ) {
my % output ;
$ output { node } - > [ 0 ] - > { name } - > [ 0 ] = @$ _ [ 0 ] ;
$ output { node } - > [ 0 ] - > { data } - > [ 0 ] - > { contents } - > [ 0 ] = @$ _ [ 1 ] ;
2008-03-04 20:16:35 +00:00
$ output { errorcode } = @$ _ [ 2 ] ;
2007-11-16 19:47:00 +00:00
push @ outhash , \ % output ;
}
my $ out = $ request - > { pipe } ;
print $ out freeze ( [ @ outhash ] ) ;
2007-12-06 16:36:32 +00:00
print $ out "\nENDOFFREEZE6sK4ci\n" ;
2007-11-16 19:47:00 +00:00
}
##########################################################################
# Run the command method specified
##########################################################################
sub runcmd {
my $ request = shift ;
my $ cmd = $ request - > { command } ;
my $ method = $ request - > { method } ;
2007-11-30 20:04:17 +00:00
my $ hwtype = $ request - > { hwtype } ;
2007-11-16 19:47:00 +00:00
my $ modname = $ modules { $ cmd } ;
2007-11-30 20:04:17 +00:00
######################################
# Command not supported
######################################
if ( ! defined ( $ modname ) ) {
return ( [ "$cmd not a supported command by $hwtype method" ] ) ;
}
2007-11-16 19:47:00 +00:00
######################################
# Load specific module
######################################
2008-01-10 14:34:34 +00:00
eval "require $modname" ;
if ( $@ ) {
return ( [ $@ ] ) ;
2007-11-16 19:47:00 +00:00
}
######################################
2008-05-27 13:56:51 +00:00
# Invoke method
2007-11-16 19:47:00 +00:00
######################################
no strict 'refs' ;
my $ result = $ { $ modname . "::" } { $ method } - > ( $ request , @ _ ) ;
use strict ;
return ( $ result ) ;
}
2008-04-16 16:45:14 +00:00
##########################################################################
# Pre-process request from xCat daemon. Send the request to the the service
# nodes of the HCPs.
##########################################################################
sub preprocess_request {
2008-05-02 19:15:23 +00:00
2008-04-16 16:45:14 +00:00
my $ package = shift ;
my $ req = shift ;
if ( $ req - > { _xcatdest } ) { return [ $ req ] ; } #exit if preprocessed
my $ callback = shift ;
my @ requests ;
2009-04-02 15:37:19 +00:00
#####################################
# Special cases for mkvm
#####################################
if ( $ req - > { command } - > [ 0 ] eq 'mkvm' )
{
$ req = mkvm_prepare ( $ req ) ;
if ( ref ( $ req ) eq 'ARRAY' ) #Something wrong
{
$ callback - > ( { data = > $ req } ) ;
$ req = { } ;
return ;
}
}
2008-04-16 16:45:14 +00:00
####################################
# Get hwtype
####################################
$ package =~ s/xCAT_plugin::// ;
####################################
# Prompt for usage if needed
####################################
my $ noderange = $ req - > { node } ; #Should be arrayref
my $ command = $ req - > { command } - > [ 0 ] ;
my $ extrargs = $ req - > { arg } ;
my @ exargs = ( $ req - > { arg } ) ;
if ( ref ( $ extrargs ) ) {
@ exargs = @$ extrargs ;
}
my $ usage_string = xCAT::Usage - > parseCommand ( $ command , @ exargs ) ;
if ( $ usage_string ) {
2008-06-17 13:38:54 +00:00
$ callback - > ( { data = > [ $ usage_string ] } ) ;
2008-04-16 16:45:14 +00:00
$ req = { } ;
return ;
}
if ( ! $ noderange ) {
$ usage_string = xCAT::Usage - > getUsage ( $ command ) ;
2008-06-17 13:38:54 +00:00
$ callback - > ( { data = > [ $ usage_string ] } ) ;
2008-04-16 16:45:14 +00:00
$ req = { } ;
return ;
}
##################################################################
# get the HCPs for the LPARs in order to figure out which service
# nodes to send the requests to
###################################################################
2009-01-19 08:58:29 +00:00
my $ hcptab_name = ( $ package eq "fsp" or $ package eq "bpa" ) ? "ppcdirect" : "ppchcp" ;
2008-04-16 16:45:14 +00:00
my $ hcptab = xCAT::Table - > new ( $ hcptab_name ) ;
unless ( $ hcptab ) {
2008-06-17 13:38:54 +00:00
$ callback - > ( { data = > [ "Cannot open $hcptab_name table" ] } ) ;
2008-04-16 16:45:14 +00:00
$ req = { } ;
return ;
}
# Check if each node is hcp
my % hcp_hash = ( ) ;
my @ missednodes = ( ) ;
foreach ( @$ noderange ) {
my ( $ ent ) = $ hcptab - > getAttribs ( { hcp = > $ _ } , "hcp" ) ;
if ( ! defined ( $ ent ) ) {
push @ missednodes , $ _ ;
next ;
}
push @ { $ hcp_hash { $ _ } { nodes } } , $ _ ;
}
#check if the left-over nodes are lpars
if ( @ missednodes > 0 ) {
my $ ppctab = xCAT::Table - > new ( "ppc" ) ;
unless ( $ ppctab ) {
2008-06-17 13:38:54 +00:00
$ callback - > ( { data = > [ "Cannot open ppc table" ] } ) ;
2008-04-16 16:45:14 +00:00
$ req = { } ;
return ;
}
foreach my $ node ( @ missednodes ) {
my $ ent = $ ppctab - > getNodeAttribs ( $ node , [ 'hcp' ] ) ;
if ( defined ( $ ent - > { hcp } ) ) { push @ { $ hcp_hash { $ ent - > { hcp } } { nodes } } , $ node ; }
else {
2008-06-17 13:38:54 +00:00
$ callback - > ( { data = > [ "The node $node is neither a hcp nor an lpar" ] } ) ;
2008-04-16 16:45:14 +00:00
$ req = { } ;
return ;
}
}
}
2009-01-07 10:38:18 +00:00
####################
#suport for "rflash", copy the rpm and xml packages from user-spcefied-directory to /install/packages_fw
#####################
2009-02-19 08:31:50 +00:00
if ( ( $ command eq "rflash" ) && ( grep ( /commit/ , @ exargs ) == 0 && grep ( /recover/ , @ exargs ) == 0 ) ) {
# if ( $command eq "rflash" ) {
2009-01-15 03:01:54 +00:00
preprocess_for_rflash ( $ req , $ callback , \ @ exargs ) ;
}
# find service nodes for the HCPs
# build an individual request for each service node
my $ service = "xcat" ;
my @ hcps = keys ( % hcp_hash ) ;
my $ sn = xCAT::Utils - > get_ServiceNode ( \ @ hcps , $ service , "MN" ) ;
# build each request for each service node
foreach my $ snkey ( keys %$ sn )
{
2009-02-19 08:31:50 +00:00
#$callback->({data=>["The service node $snkey "]});
2009-01-15 03:01:54 +00:00
my $ reqcopy = { %$ req } ;
$ reqcopy - > { '_xcatdest' } = $ snkey ;
my $ hcps1 = $ sn - > { $ snkey } ;
my @ nodes = ( ) ;
foreach ( @$ hcps1 ) {
push @ nodes , @ { $ hcp_hash { $ _ } { nodes } } ;
}
$ reqcopy - > { node } = \ @ nodes ;
#print "nodes=@nodes\n";
push @ requests , $ reqcopy ;
}
return \ @ requests ;
}
2009-04-02 15:37:19 +00:00
####################################
# Special case for mkvm
####################################
sub mkvm_prepare
{
my $ req = shift ;
# Following code could be changed more flexibly, as we did in PPC::runcmd
# But since we only mkvm need to be handled in this specific way, keep the code simple
######################################
# Load specific module
######################################
eval "require xCAT::PPCvm" ;
if ( $@ ) {
return ( $@ ) ;
}
my $ opt = xCAT::PPCvm:: mkvm_parse_args ( $ req ) ;
if ( ref ( $ opt ) eq 'ARRAY' )
{
return $ opt ;
}
$ req - > { opt } = $ opt ;
########################################################
#Check lpar number in command line and profile
########################################################
if ( exists $ opt - > { c } )
{
my @ profile = @ { $ opt - > { profile } } ;
my @ lpars = @ { $ opt - > { target } } ;
my $ min_lpar_num = scalar ( @ profile ) ;
if ( scalar ( @ profile ) > scalar ( @ lpars ) )
{
xCAT::MsgUtils - > message ( 'W' , "Warning: Lpar configuration number in profile is greater than lpars in command line. Only first " . scalar ( @ lpars ) . " lpars will be created.\n" ) ;
$ min_lpar_num = scalar ( @ lpars ) ;
}
elsif ( scalar ( @ profile ) < scalar ( @ lpars ) )
{
xCAT::MsgUtils - > message ( 'W' , "Warning: Lpar number in command line is greater than lpar configuration number in profile. Only lpars " . join "," , @ lpars [ 0 .. $ min_lpar_num - 1 ] . " will be created.\n" ) ;
}
}
return $ req ;
}
2009-01-15 03:01:54 +00:00
sub preprocess_for_rflash {
my $ req = shift ;
my $ callback = shift ;
my $ exargs = shift ;
2009-01-07 10:38:18 +00:00
my $ packages_fw = "/install/packages_fw" ;
my $ c = 0 ;
my $ packages_d ;
2009-01-15 03:01:54 +00:00
foreach ( @$ exargs ) {
2009-01-07 10:38:18 +00:00
$ c + + ;
if ( $ _ eq "-p" ) {
2009-01-15 03:01:54 +00:00
$ packages_d = $$ exargs [ $ c ] ;
2009-01-07 10:38:18 +00:00
last ;
}
}
if ( $ packages_d ne $ packages_fw ) {
2009-01-15 03:01:54 +00:00
$$ exargs [ $ c ] = $ packages_fw ;
2009-01-07 10:38:18 +00:00
if ( ! - d $ packages_d ) {
$ callback - > ( { data = > [ "The directory $packages_d doesn't exist!" ] } ) ;
$ req = ( ) ;
return ;
}
#print "opening directory and reading names\n";
opendir DIRHANDLE , $ packages_d ;
my @ dirlist = readdir DIRHANDLE ;
closedir DIRHANDLE ;
@ dirlist = File::Spec - > no_upwards ( @ dirlist ) ;
# Make sure we have some files to process
#
if ( ! scalar ( @ dirlist ) ) {
$ callback - > ( { data = > [ "The directory $packages_d is empty !" ] } ) ;
$ req = ( ) ;
return ;
}
#Find the rpm lic file
my @ rpmlist = grep /\.rpm$/ , @ dirlist ;
my @ xmllist = grep /\.xml$/ , @ dirlist ;
if ( @ rpmlist == 0 | @ xmllist == 0 ) {
$ callback - > ( { data = > [ "There isn't any rpm and xml files in the directory $packages_d!" ] } ) ;
$ req = ( ) ;
return ;
}
my $ rpm_list = join ( " " , @ rpmlist ) ;
my $ xml_list = join ( " " , @ xmllist ) ;
my $ cmd ;
if ( - d $ packages_fw ) {
$ cmd = "rm -rf $packages_fw" ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
$ callback - > ( { data = > [ "Failed to remove the old packages in $packages_fw." ] } ) ;
$ req = ( ) ;
return ;
}
}
$ cmd = "mkdir $packages_fw" ;
xCAT::Utils - > runcmd ( "$cmd" , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
$ callback - > ( { data = > [ "$cmd failed." ] } ) ;
$ req = ( ) ;
return ;
}
$ cmd = "cp $packages_d/*.rpm $packages_d/*.xml $packages_fw" ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
$ callback - > ( { data = > [ "$cmd failed." ] } ) ;
$ req = ( ) ;
return ;
}
2009-01-15 03:01:54 +00:00
$ req - > { arg } = $ exargs ;
2009-01-07 10:38:18 +00:00
}
2008-04-16 16:45:14 +00:00
}
2007-11-16 19:47:00 +00:00
##########################################################################
# Process request from xCat daemon
##########################################################################
sub process_request {
my $ package = shift ;
my $ req = shift ;
my $ callback = shift ;
####################################
# Get hwtype
####################################
$ package =~ s/xCAT_plugin::// ;
2008-04-12 14:53:11 +00:00
2007-11-16 19:47:00 +00:00
####################################
# Build hash to pass around
####################################
my % request ;
$ request { command } = $ req - > { command } - > [ 0 ] ;
$ request { arg } = $ req - > { arg } ;
$ request { node } = $ req - > { node } ;
$ request { stdin } = $ req - > { stdin } - > [ 0 ] ;
$ request { hwtype } = $ package ;
$ request { callback } = $ callback ;
$ request { method } = "parse_args" ;
2009-04-02 15:37:19 +00:00
#For mkvm only so far
$ request { opt } = $ req - > { opt } if ( exists $ req - > { opt } ) ;
2007-11-16 19:47:00 +00:00
####################################
# Process command-specific options
####################################
my $ opt = runcmd ( \ % request ) ;
####################################
# Return error
####################################
if ( ref ( $ opt ) eq 'ARRAY' ) {
2008-02-18 20:26:39 +00:00
send_msg ( \ % request , 1 , @$ opt ) ;
2007-11-16 19:47:00 +00:00
return ( 1 ) ;
}
####################################
# Option -V for verbose output
####################################
if ( exists ( $ opt - > { V } ) ) {
$ request { verbose } = 1 ;
}
####################################
# Process remote command
####################################
$ request { opt } = $ opt ;
process_command ( \ % request ) ;
}
2008-09-30 13:44:19 +00:00
##########################################################################
# connect hmc via ssh and execute remote command
##########################################################################
sub sshcmds_on_hmc
{
my $ ip = shift ;
my $ user = shift ;
my $ password = shift ;
my @ cmds = @ _ ;
my % handled ;
my @ data ;
my @ exp ;
for my $ cmd ( @ cmds )
{
if ( $ cmd =~ /(.+?)=(.*)/ )
{
my ( $ command , $ value ) = ( $ 1 , $ 2 ) ;
$ handled { $ command } = $ value ;
}
}
my % request = (
ppcretry = > 1 ,
verbose = > 0 ,
ppcmaxp = > 64 ,
ppctimeout = > 0 ,
fsptimeout = > 0 ,
ppcretry = > 3 ,
maxssh = > 10
) ;
my $ valid_ip ;
foreach my $ individual_ip ( split /,/ , $ ip ) {
################################
# Get userid and password
################################
my @ cred = xCAT::PPCdb:: credentials ( $ individual_ip , "hmc" ) ;
$ request { $ individual_ip } { cred } = \ @ cred ;
@ exp = xCAT::PPCcli:: connect ( \ % request , 'hmc' , $ individual_ip ) ;
####################################
# Successfully connected
####################################
if ( ref ( $ exp [ 0 ] ) eq "Expect" ) {
$ valid_ip = $ individual_ip ;
last ;
}
}
2007-11-16 19:47:00 +00:00
2008-09-30 13:44:19 +00:00
########################################
# Error connecting
########################################
if ( ref ( $ exp [ 0 ] ) ne "Expect" ) {
return ( [ 1 , @ cmds ] ) ;
}
########################################
# Process specific command
########################################
for my $ cmd ( keys % handled )
{
my $ result ;
if ( $ cmd eq 'network_reset' )
{
$ result = xCAT::PPCcli:: network_reset ( \ @ exp , $ valid_ip , $ handled { $ cmd } ) ;
my $ RC = shift ( @$ result ) ;
}
push @ data , @$ result [ 0 ] ;
}
########################################
# Close connection to remote server
########################################
xCAT::PPCcli:: disconnect ( \ @ exp ) ;
2007-11-16 19:47:00 +00:00
2008-09-30 13:44:19 +00:00
return ( [ 0 , undef , \ @ data ] ) ;
}
2007-11-16 19:47:00 +00:00
2009-01-19 08:58:29 +00:00
##########################################################################
# logon asm and update configuration
##########################################################################
sub updconf_in_asm
{
my $ ip = shift ;
my $ target_dev = shift ;
my @ cmds = @ _ ;
eval { require xCAT::PPCfsp } ;
if ( $@ ) {
return ( [ 1 , @ cmds ] ) ;
}
my % handled ;
for my $ cmd ( @ cmds )
{
if ( $ cmd =~ /(.+?)=(.*)/ )
{
my ( $ command , $ value ) = ( $ 1 , $ 2 ) ;
$ handled { $ command } = $ value ;
}
}
my % request = (
ppcretry = > 1 ,
verbose = > 0 ,
ppcmaxp = > 64 ,
ppctimeout = > 0 ,
fsptimeout = > 0 ,
ppcretry = > 3 ,
maxssh = > 10 ,
arg = > \ @ cmds ,
method = > \ % handled ,
command = > 'rspconfig' ,
hwtype = > lc ( $ target_dev - > { 'type' } ) ,
) ;
my $ valid_ip ;
my @ exp ;
foreach my $ individual_ip ( split /,/ , $ ip ) {
################################
# Get userid and password
################################
my @ cred = xCAT::PPCdb:: credentials ( $ individual_ip , lc ( $ target_dev - > { 'type' } ) ) ;
$ request { $ individual_ip } { cred } = \ @ cred ;
$ request { node } = [ $ individual_ip ] ;
@ exp = xCAT::PPCfsp:: connect ( \ % request , $ individual_ip ) ;
####################################
# Successfully connected
####################################
if ( ref ( $ exp [ 0 ] ) eq "LWP::UserAgent" ) {
$ valid_ip = $ individual_ip ;
last ;
}
}
####################################
# Error connecting
####################################
if ( ref ( $ exp [ 0 ] ) ne "LWP::UserAgent" ) {
return ( [ 1 , @ cmds ] ) ;
}
my $ result = xCAT::PPCfsp:: handler ( $ valid_ip , \ % request , \ @ exp ) ;
my $ RC = shift ( @$ result ) ;
my @ data ;
push @ data , @$ result [ 0 ] ;
return ( [ 0 , undef , \ @ data ] ) ;
}
2007-11-16 19:47:00 +00:00
1 ;
2008-11-07 13:34:47 +00:00