2007-11-16 19:47:00 +00:00
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
package xCAT::PPCpower ;
use strict ;
use Getopt::Long ;
use xCAT::PPCcli qw( SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR ) ;
2008-04-12 14:53:11 +00:00
use xCAT::Usage ;
2009-07-03 08:56:14 +00:00
use xCAT::MsgUtils ;
2009-12-10 02:19:40 +00:00
use xCAT::FSPpower ;
2007-11-16 19:47:00 +00:00
##########################################################################
# Parse the command line for options and operands
##########################################################################
sub parse_args {
my $ request = shift ;
2008-04-12 14:53:11 +00:00
my $ command = $ request - > { command } ;
2007-11-16 19:47:00 +00:00
my $ args = $ request - > { arg } ;
my % opt = ( ) ;
2012-03-13 14:19:45 +00:00
my @ rpower = qw( on onstandby off softoff stat state reset boot of sms rackstandby exit_rackstandby lowpower resetsp cycle ) ;
2007-11-16 19:47:00 +00:00
#############################################
# Responds with usage statement
#############################################
local * usage = sub {
2008-04-16 18:00:18 +00:00
my $ usage_string = xCAT::Usage - > getUsage ( $ command ) ;
return ( [ $ _ [ 0 ] , $ usage_string ] ) ;
2007-11-16 19:47:00 +00:00
} ;
#############################################
# Process command-line arguments
#############################################
if ( ! defined ( $ args ) ) {
return ( usage ( "No command specified" ) ) ;
}
#############################################
# Checks case in GetOptions, allows opts
# to be grouped (e.g. -vx), and terminates
# at the first unrecognized option.
#############################################
@ ARGV = @$ args ;
$ Getopt:: Long:: ignorecase = 0 ;
Getopt::Long:: Configure ( "bundling" ) ;
2012-04-12 08:09:50 +00:00
if ( ! GetOptions ( \ % opt , qw( V|Verbose m:s@ t=s T=s r=s nodeps ) ) ) {
2007-11-16 19:47:00 +00:00
return ( usage ( ) ) ;
}
####################################
# Check for "-" with no option
####################################
if ( grep ( /^-$/ , @ ARGV ) ) {
return ( usage ( "Missing option: -" ) ) ;
}
####################################
# Unsupported commands
####################################
my ( $ cmd ) = grep ( /^$ARGV[0]$/ , @ rpower ) ;
if ( ! defined ( $ cmd ) ) {
return ( usage ( "Invalid command: $ARGV[0]" ) ) ;
}
####################################
# Check for an extra argument
####################################
shift @ ARGV ;
if ( defined ( $ ARGV [ 0 ] ) ) {
return ( usage ( "Invalid Argument: $ARGV[0]" ) ) ;
}
####################################
# Change "stat" to "state"
####################################
$ request - > { op } = $ cmd ;
$ cmd =~ s/^stat$/state/ ;
####################################
# Power commands special case
####################################
if ( $ cmd ne "state" ) {
$ cmd = ( $ cmd eq "boot" ) ? "powercmd_boot" : "powercmd" ;
}
$ request - > { method } = $ cmd ;
2009-07-03 08:56:14 +00:00
if ( exists ( $ opt { m } ) ) {
my $ res = xCAT::Utils - > check_deployment_monitoring_settings ( $ request , \ % opt ) ;
if ( $ res != SUCCESS ) {
return ( usage ( ) ) ;
}
}
2012-04-12 08:09:50 +00:00
if ( ! exists $ opt { T } )
{
$ opt { T } = "lpar" ; #defaut value is lpar.
}
if ( $ opt { T } eq "lpar" ) {
$ opt { T } = 0 ;
} elsif ( $ opt { T } eq "fnm" ) {
$ opt { T } = 1 ;
if ( $ request - > { op } !~ /^(onstandby|state|stat)$/ ) {
return ( usage ( "The tooltype fnm only could be used with onstandby/state/stat action." ) ) ;
}
} else {
return ( usage ( 'Wrong value of -T option. The value can be lpar or fnm. The defaut value is lpar.' ) ) ;
}
2007-11-16 19:47:00 +00:00
return ( \ % opt ) ;
}
##########################################################################
# Builds a hash of CEC/LPAR information returned from HMC/IVM
##########################################################################
sub enumerate {
my $ exp = shift ;
my $ node = shift ;
my $ mtms = shift ;
my % outhash = ( ) ;
my % cmds = ( ) ;
######################################
# Check for CEC/LPAR/BPAs in list
######################################
while ( my ( $ name , $ d ) = each ( %$ node ) ) {
2008-03-06 13:26:58 +00:00
my $ type = @$ d [ 4 ] ;
$ cmds { $ type } = ( $ type =~ /^lpar$/ ) ? "state,lpar_id" : "state" ;
2007-11-16 19:47:00 +00:00
}
2008-03-06 13:26:58 +00:00
foreach my $ type ( keys % cmds ) {
my $ filter = $ cmds { $ type } ;
my $ values = xCAT::PPCcli:: lssyscfg ( $ exp , $ type , $ mtms , $ filter ) ;
2007-11-16 19:47:00 +00:00
my $ Rc = shift ( @$ values ) ;
##################################
# Return error
##################################
if ( $ Rc != SUCCESS ) {
return ( [ $ Rc , @$ values [ 0 ] ] ) ;
}
##################################
2008-03-06 13:26:58 +00:00
# Save LPARs by id
2007-11-16 19:47:00 +00:00
##################################
foreach ( @$ values ) {
2008-03-06 13:26:58 +00:00
my ( $ state , $ lparid ) = split /,/ ;
##############################
# No lparid for fsp/bpa
##############################
2011-02-12 08:02:53 +00:00
if ( $ type =~ /^(fsp|bpa|cec|frame)$/ ) {
2008-03-06 13:26:58 +00:00
$ lparid = $ type ;
}
$ outhash { $ lparid } = $ state ;
2007-11-16 19:47:00 +00:00
}
}
return ( [ SUCCESS , \ % outhash ] ) ;
}
##########################################################################
# Performs boot operation (Off->On, On->Reset)
##########################################################################
sub powercmd_boot {
my $ request = shift ;
my $ hash = shift ;
my $ exp = shift ;
my @ output = ( ) ;
2009-07-03 08:56:14 +00:00
my $ callback = $ request - > { 'callback' } ;
2007-11-16 19:47:00 +00:00
2009-12-02 09:38:51 +00:00
2007-11-16 19:47:00 +00:00
######################################
# Power commands are grouped by CEC
# not Hardware Control Point
######################################
######################################
# Get CEC MTMS
######################################
my ( $ name ) = keys %$ hash ;
my $ mtms = @ { $ hash - > { $ name } } [ 2 ] ;
######################################
# Build CEC/LPAR information hash
######################################
2008-03-06 13:26:58 +00:00
my $ stat = enumerate ( $ exp , $ hash , $ mtms ) ;
2007-11-16 19:47:00 +00:00
my $ Rc = shift ( @$ stat ) ;
my $ data = @$ stat [ 0 ] ;
while ( my ( $ name , $ d ) = each ( %$ hash ) ) {
2008-03-06 13:26:58 +00:00
##################################
# Look up by lparid
##################################
my $ type = @$ d [ 4 ] ;
2011-02-12 08:02:53 +00:00
my $ id = ( $ type =~ /^(fsp|bpa|frame|cec)$/ ) ? $ type : @$ d [ 0 ] ;
2008-03-06 13:26:58 +00:00
2007-11-16 19:47:00 +00:00
##################################
# Output error
##################################
if ( $ Rc != SUCCESS ) {
2008-03-05 19:10:39 +00:00
push @ output , [ $ name , $ data , $ Rc ] ;
2007-11-16 19:47:00 +00:00
next ;
}
##################################
# Node not found
##################################
2008-03-06 13:26:58 +00:00
if ( ! exists ( $ data - > { $ id } ) ) {
2008-03-05 19:10:39 +00:00
push @ output , [ $ name , "Node not found" , 1 ] ;
2007-11-16 19:47:00 +00:00
next ;
}
##################################
# Convert state to on/off
##################################
2008-03-06 13:26:58 +00:00
my $ state = power_status ( $ data - > { $ id } ) ;
2008-05-28 14:22:01 +00:00
my $ op = ( $ state =~ /^off$/ ) ? "on" : "reset" ;
2007-11-16 19:47:00 +00:00
2009-12-30 03:14:47 +00:00
# Attribute powerinterval in site table,
# to control the rpower forking speed
if ( ( defined ( $ request - > { op } ) ) && ( $ request - > { op } ne 'stat' ) && ( $ request - > { op } ne 'status' )
&& ( $ request - > { op } ne 'state' ) && ( $ request - > { op } ne 'off' ) && ( $ request - > { op } ne 'softoff' ) ) {
if ( defined ( $ request - > { 'powerinterval' } ) && ( $ request - > { 'powerinterval' } ne '' ) ) {
Time::HiRes:: sleep ( $ request - > { 'powerinterval' } ) ;
}
}
2007-11-16 19:47:00 +00:00
##############################
# Send power command
##############################
my $ result = xCAT::PPCcli:: chsysstate (
$ exp ,
$ op ,
$ d ) ;
2008-03-05 19:10:39 +00:00
push @ output , [ $ name , @$ result [ 1 ] , @$ result [ 0 ] ] ;
2007-11-16 19:47:00 +00:00
}
2009-07-03 08:56:14 +00:00
if ( defined ( $ request - > { opt } - > { m } ) ) {
my $ retries = 0 ;
my @ monnodes = keys %$ hash ;
my $ monsettings = xCAT::Utils - > generate_monsettings ( $ request , \ @ monnodes ) ;
xCAT::Utils - > monitor_installation ( $ request , $ monsettings ) ;
while ( $ retries + + < $ monsettings - > { 'retrycount' } && scalar ( keys % { $ monsettings - > { nodes } } ) > 0 ) {
#The nodes that need to retry
my @ nodesretry = keys % { $ monsettings - > { 'nodes' } } ;
my $ nodes = join ',' , @ nodesretry ;
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "$nodes: Reinitializing the installation: $retries retry" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
foreach my $ node ( keys %$ hash )
{
# The installation for this node has been finished
if ( ! grep ( /^$node$/ , @ nodesretry ) ) {
delete ( $ hash - > { $ node } ) ;
}
}
while ( my ( $ name , $ d ) = each ( %$ hash ) ) {
my $ type = @$ d [ 4 ] ;
my $ id = ( $ type =~ /^(fsp|bpa)$/ ) ? $ type : @$ d [ 0 ] ;
if ( $ Rc != SUCCESS ) {
push @ output , [ $ name , $ data , $ Rc ] ;
next ;
}
if ( ! exists ( $ data - > { $ id } ) ) {
push @ output , [ $ name , "Node not found" , 1 ] ;
next ;
}
my $ state = power_status ( $ data - > { $ id } ) ;
my $ op = ( $ state =~ /^off$/ ) ? "on" : "reset" ;
my $ result = xCAT::PPCcli:: chsysstate (
$ exp ,
$ op ,
$ d ) ;
push @ output , [ $ name , @$ result [ 1 ] , @$ result [ 0 ] ] ;
}
my @ monnodes = keys % { $ monsettings - > { nodes } } ;
xCAT::Utils - > monitor_installation ( $ request , $ monsettings ) ;
}
#failed after retries
if ( scalar ( keys % { $ monsettings - > { 'nodes' } } ) > 0 ) {
foreach my $ node ( keys % { $ monsettings - > { nodes } } ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "The node \"$node\" can not reach the expected status after $monsettings->{'retrycount'} retries, the installation for this done failed" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
}
}
}
2007-11-16 19:47:00 +00:00
return ( \ @ output ) ;
}
##########################################################################
# Performs power control operations (on,off,reboot,etc)
##########################################################################
sub powercmd {
my $ request = shift ;
my $ hash = shift ;
my $ exp = shift ;
my @ result = ( ) ;
2009-07-03 08:56:14 +00:00
my $ callback = $ request - > { 'callback' } ;
2007-11-16 19:47:00 +00:00
2009-12-02 09:38:51 +00:00
2007-11-16 19:47:00 +00:00
####################################
# Power commands are grouped by CEC
# not Hardware Control Point
####################################
while ( my ( $ name , $ d ) = each ( %$ hash ) ) {
2009-12-30 03:14:47 +00:00
# Attribute powerinterval in site table,
# to control the rpower forking speed
if ( ( defined ( $ request - > { op } ) ) && ( $ request - > { op } ne 'stat' ) && ( $ request - > { op } ne 'status' )
&& ( $ request - > { op } ne 'state' ) && ( $ request - > { op } ne 'off' ) && ( $ request - > { op } ne 'softoff' ) ) {
if ( defined ( $ request - > { 'powerinterval' } ) && ( $ request - > { 'powerinterval' } ne '' ) ) {
Time::HiRes:: sleep ( $ request - > { 'powerinterval' } ) ;
}
}
2007-11-16 19:47:00 +00:00
################################
# Send command to each LPAR
################################
my $ values = xCAT::PPCcli:: chsysstate (
$ exp ,
$ request - > { op } ,
$ d ) ;
my $ Rc = shift ( @$ values ) ;
################################
# Return result
################################
2008-03-05 19:10:39 +00:00
push @ result , [ $ name , @$ values [ 0 ] , $ Rc ] ;
2007-11-16 19:47:00 +00:00
}
2009-07-03 08:56:14 +00:00
if ( defined ( $ request - > { opt } - > { m } ) ) {
my $ retries = 0 ;
my @ monnodes = keys %$ hash ;
my $ monsettings = xCAT::Utils - > generate_monsettings ( $ request , \ @ monnodes ) ;
xCAT::Utils - > monitor_installation ( $ request , $ monsettings ) ;
while ( $ retries + + < $ monsettings - > { 'retrycount' } && scalar ( keys % { $ monsettings - > { nodes } } ) > 0 ) {
#The nodes that need to retry
my @ nodesretry = keys % { $ monsettings - > { 'nodes' } } ;
my $ nodes = join ',' , @ nodesretry ;
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "$nodes: Reinitializing the installation: $retries retry" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
foreach my $ node ( keys %$ hash )
{
# The installation for this node has been finished
if ( ! grep ( /^$node$/ , @ nodesretry ) ) {
delete ( $ hash - > { $ node } ) ;
}
}
while ( my ( $ name , $ d ) = each ( %$ hash ) ) {
my $ values = xCAT::PPCcli:: chsysstate (
$ exp ,
$ request - > { op } ,
$ d ) ;
my $ Rc = shift ( @$ values ) ;
push @ result , [ $ name , @$ values [ 0 ] , $ Rc ] ;
}
my @ monnodes = keys % { $ monsettings - > { nodes } } ;
xCAT::Utils - > monitor_installation ( $ request , $ monsettings ) ;
}
#failed after retries
if ( scalar ( keys % { $ monsettings - > { 'nodes' } } ) > 0 ) {
foreach my $ node ( keys % { $ monsettings - > { nodes } } ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "The node \"$node\" can not reach the expected status after $monsettings->{'retrycount'} retries, the installation for this done failed" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
}
}
}
2007-11-16 19:47:00 +00:00
return ( \ @ result ) ;
}
##########################################################################
# Queries CEC/LPAR power status (On or Off)
##########################################################################
sub power_status {
my @ states = (
"Operating" ,
"Running" ,
"Open Firmware"
) ;
foreach ( @ states ) {
if ( /^$_[0]$/ ) {
return ( "on" ) ;
}
}
return ( "off" ) ;
}
##########################################################################
# Queries CEC/LPAR power state
##########################################################################
sub state {
my $ request = shift ;
my $ hash = shift ;
my $ exp = shift ;
my $ prefix = shift ;
my $ convert = shift ;
my @ result = ( ) ;
2009-12-02 09:38:51 +00:00
2007-11-16 19:47:00 +00:00
if ( ! defined ( $ prefix ) ) {
$ prefix = "" ;
}
while ( my ( $ mtms , $ h ) = each ( %$ hash ) ) {
######################################
# Build CEC/LPAR information hash
######################################
2008-03-06 13:26:58 +00:00
my $ stat = enumerate ( $ exp , $ h , $ mtms ) ;
2007-11-16 19:47:00 +00:00
my $ Rc = shift ( @$ stat ) ;
my $ data = @$ stat [ 0 ] ;
while ( my ( $ name , $ d ) = each ( %$ h ) ) {
2008-03-06 13:26:58 +00:00
##################################
# Look up by lparid
##################################
my $ type = @$ d [ 4 ] ;
2011-02-12 08:02:53 +00:00
my $ id = ( $ type =~ /^(fsp|bpa|cec|frame)$/ ) ? $ type : @$ d [ 0 ] ;
2008-03-06 13:26:58 +00:00
2007-11-16 19:47:00 +00:00
##################################
# Output error
##################################
if ( $ Rc != SUCCESS ) {
2008-03-05 19:10:39 +00:00
push @ result , [ $ name , "$prefix$data" , $ Rc ] ;
2007-11-16 19:47:00 +00:00
next ;
}
##################################
# Node not found
##################################
2008-03-06 13:26:58 +00:00
if ( ! exists ( $ data - > { $ id } ) ) {
2008-03-05 19:10:39 +00:00
push @ result , [ $ name , $ prefix . "Node not found" , 1 ] ;
2007-11-16 19:47:00 +00:00
next ;
}
##################################
# Output value
##################################
2008-03-06 13:26:58 +00:00
my $ value = $ data - > { $ id } ;
2007-11-16 19:47:00 +00:00
##############################
# Convert state to on/off
##############################
if ( defined ( $ convert ) ) {
$ value = power_status ( $ value ) ;
}
2008-03-05 19:10:39 +00:00
push @ result , [ $ name , "$prefix$value" , $ Rc ] ;
2007-11-16 19:47:00 +00:00
}
}
return ( \ @ result ) ;
}
1 ;
2008-03-05 19:10:39 +00:00