2009-12-02 09:41:51 +00:00
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
2009-12-10 02:19:40 +00:00
package xCAT::FSPpower ;
2009-12-02 09:41:51 +00:00
use strict ;
#use Getopt::Long;
use xCAT::PPCcli qw( SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR ) ;
2009-12-10 02:19:40 +00:00
use xCAT::PPCpower ;
2010-06-04 09:05:30 +00:00
use xCAT::FSPUtils ;
2010-09-16 08:42:43 +00:00
#use Data::Dumper;
2011-11-30 08:21:48 +00:00
2009-12-10 02:19:40 +00:00
##########################################################################
# Parse the command line for options and operands
##########################################################################
sub parse_args {
xCAT::PPCpower:: parse_args ( @ _ ) ;
}
2010-06-04 09:05:30 +00:00
##########################################################################
# Builds a hash of CEC/LPAR information returned from FSP
##########################################################################
sub enumerate {
my $ h = shift ;
my $ mtms = shift ;
my % outhash = ( ) ;
my % cmds = ( ) ;
my $ type = ( ) ;
my $ cec_bpa = ( ) ;
######################################
# Check for CEC/LPAR/BPAs in list
######################################
while ( my ( $ name , $ d ) = each ( %$ h ) ) {
$ cec_bpa = @$ d [ 3 ] ;
$ type = @$ d [ 4 ] ;
2011-04-08 03:22:02 +00:00
#$cmds{$type} = ($type=~/^lpar$/) ? "all_lpars_state" : "cec_state";
if ( $ type =~ /^lpar$/ ) {
$ cmds { $ type } = "all_lpars_state" ;
} elsif ( $ type =~ /^(fsp|cec)$/ ) {
$ cmds { $ type } = "cec_state" ;
} else {
$ cmds { $ type } = "bpa_state" ;
}
2010-06-04 09:05:30 +00:00
}
foreach my $ type ( keys % cmds ) {
my $ action = $ cmds { $ type } ;
my $ values = xCAT::FSPUtils:: fsp_state_action ( $ cec_bpa , $ type , $ action ) ; ;
my $ Rc = shift ( @$ values ) ;
##################################
# Return error
##################################
if ( $ Rc != 0 ) {
return ( [ $ Rc , @$ values [ 0 ] ] ) ;
}
##################################
# Save LPARs by id
##################################
foreach ( @$ values ) {
my ( $ state , $ lparid ) = split /,/ ;
##############################
# No lparid for fsp/bpa
##############################
2011-03-04 06:44:51 +00:00
if ( $ type =~ /^(fsp|bpa|cec|frame)$/ ) {
2010-06-04 09:05:30 +00:00
$ lparid = $ type ;
}
$ outhash { $ lparid } = $ state ;
}
}
return ( [ 0 , \ % outhash ] ) ;
}
2009-12-10 02:19:40 +00:00
2009-12-02 09:41:51 +00:00
##########################################################################
# Performs boot operation (Off->On, On->Reset)
##########################################################################
sub powercmd_boot {
my $ request = shift ;
my $ hash = shift ;
my @ output = ( ) ;
######################################
# Power commands are grouped by CEC
# not Hardware Control Point
######################################
#Example of $hash
# $VAR1 = {
# 'Server-9110-51A-SN1075ECF' => [
2009-12-10 02:19:40 +00:00
# 0,
# 0,
# '9110-51A*1075ECF',
# 'Server-9110-51A-SN1075ECF',
# 'fsp',
# 0
# ]
2009-12-02 09:41:51 +00:00
# }
foreach my $ node_name ( keys %$ hash )
{
2009-12-10 02:19:40 +00:00
my $ d = $ hash - > { $ node_name } ;
2010-02-26 09:42:41 +00:00
if ( ! ( $$ d [ 4 ] =~ /^lpar$/ ) ) {
push @ output , [ $ node_name , "\'boot\' command not supported for CEC or BPA" , - 1 ] ;
#return (\@output);
next ;
}
2010-06-04 09:05:30 +00:00
my $ res = xCAT::FSPUtils:: fsp_api_action ( $ node_name , $ d , "state" ) ;
2010-03-17 06:44:06 +00:00
#print "In boot, state\n";
#print Dumper($res);
2010-02-26 09:42:41 +00:00
my $ Rc = @$ res [ 2 ] ;
my $ data = @$ res [ 1 ] ;
#my $type = @$d[4];
#my $id = ($type=~/^(fsp|bpa)$/) ? $type : @$d[0];
2009-12-02 09:41:51 +00:00
2010-02-26 09:42:41 +00:00
##################################
2009-12-10 02:19:40 +00:00
# Output error
##################################
if ( $ Rc != SUCCESS ) {
push @ output , [ $ node_name , $ data , $ Rc ] ;
next ;
}
2010-02-26 09:42:41 +00:00
2009-12-10 02:19:40 +00:00
##################################
# Convert state to on/off
##################################
2010-02-26 09:42:41 +00:00
my $ state = power_status ( $ data ) ;
2010-03-17 06:44:06 +00:00
#print "boot:state:$state\n";
2010-02-26 09:42:41 +00:00
my $ op = ( $ state =~ /^off$/ ) ? "on" : "reset" ;
2011-08-25 09:11:06 +00:00
# Attribute powerinterval in site table,
# to control the rpower speed
2011-10-30 06:11:55 +00:00
if ( defined ( $ request - > { 'powerinterval' } ) ) {
2011-08-25 09:11:06 +00:00
Time::HiRes:: sleep ( $ request - > { 'powerinterval' } ) ;
}
2010-06-04 09:05:30 +00:00
$ res = xCAT::FSPUtils:: fsp_api_action ( $ node_name , $ d , $ op ) ;
2009-12-02 09:41:51 +00:00
2009-12-10 02:19:40 +00:00
# @output ...
2010-02-26 09:42:41 +00:00
$ Rc = @$ res [ 2 ] ;
$ data = @$ res [ 1 ] ;
if ( $ Rc != SUCCESS ) {
push @ output , [ $ node_name , $ data , $ Rc ] ;
next ;
2009-12-10 02:19:40 +00:00
}
2010-02-26 09:42:41 +00:00
push @ output , [ $ node_name , "Success" , 0 ] ;
2009-12-02 09:41:51 +00:00
}
return ( \ @ output ) ;
}
##########################################################################
# Performs power control operations (on,off,reboot,etc)
##########################################################################
sub powercmd {
my $ request = shift ;
my $ hash = shift ;
my @ result = ( ) ;
my @ output ;
2011-11-30 08:21:48 +00:00
my $ action ;
my $ node_name ;
my $ newids ;
my $ newnames ;
my $ newd ;
my $ lpar_flag = 0 ;
my $ cec_flag = 0 ;
my $ frame_flag = 0 ;
2011-12-07 07:54:44 +00:00
2010-03-17 06:44:06 +00:00
#print "++++in powercmd++++\n";
#print Dumper($hash);
2009-12-02 09:41:51 +00:00
####################################
# Power commands are grouped by cec or lpar
# not Hardware Control Point
####################################
#Example of $hash.
#$VAR1 = {
# 'lpar01' => [
# '1',
# 'lpar01_normal',
# '9110-51A*1075ECF',
# 'Server-9110-51A-SN1075ECF',
# 'lpar',
# 0
# ]
# };
2011-11-30 08:21:48 +00:00
foreach $ node_name ( keys %$ hash )
2009-12-02 09:41:51 +00:00
{
2011-12-07 07:54:44 +00:00
$ action = $ request - > { 'op' } ;
2009-12-10 02:19:40 +00:00
my $ d = $ hash - > { $ node_name } ;
2011-04-08 03:22:02 +00:00
if ( $$ d [ 4 ] =~ /^lpar$/ ) {
if ( ! ( $ action =~ /^(on|off|of|reset|sms)$/ ) ) {
push @ output , [ $ node_name , "\'$action\' command not supported for LPAR" , - 1 ] ;
return ( \ @ output ) ;
}
2011-11-30 08:21:48 +00:00
$ newids . = "$$d[0]," ;
$ newnames . = "$node_name," ;
$ newd = $ d ;
$ lpar_flag = 1 ;
2011-04-08 03:22:02 +00:00
} elsif ( $$ d [ 4 ] =~ /^(fsp|cec)$/ ) {
if ( $ action =~ /^on$/ ) { $ action = "cec_on_autostart" ; }
if ( $ action =~ /^off$/ ) { $ action = "cec_off" ; }
2011-06-24 09:29:12 +00:00
if ( $ action =~ /^resetsp$/ ) { $ action = "reboot_service_processor" ; }
2011-04-08 03:22:02 +00:00
if ( $ action =~ /^lowpower$/ ) { $ action = "cec_on_low_power" ; }
2011-06-24 09:29:12 +00:00
if ( $ action !~ /^cec_on_autostart$/ && $ action !~ /^cec_off$/ && $ action !~ /^cec_on_low_power$/ && $ action !~ /^onstandby$/ && $ action !~ /^reboot_service_processor$/ ) {
2011-04-08 03:22:02 +00:00
push @ output , [ $ node_name , "\'$action\' command not supported for CEC" , - 1 ] ;
2011-11-30 08:21:48 +00:00
next ;
}
$ newids = $$ d [ 0 ] ;
$ newnames = $ node_name ;
$ newd = $ d ;
$ cec_flag = 1 ;
2010-02-26 09:42:41 +00:00
} else {
2011-11-30 08:21:48 +00:00
if ( $ action =~ /^rackstandby$/ ) {
$ action = "enter_rack_standby" ;
} elsif ( $ action =~ /^exit_rackstandby$/ ) {
$ action = "exit_rack_standby" ;
2011-12-07 07:54:44 +00:00
} elsif ( $ action =~ /^resetsp$/ ) {
$ action = "reboot_service_processor" ;
} else {
2011-11-30 08:21:48 +00:00
push @ output , [ $ node_name , "$node_name\'s type isn't fsp or lpar. Not allow doing this operation" , - 1 ] ;
#return (\@output);
next ;
}
$ newids = $$ d [ 0 ] ;
$ newnames = $ node_name ;
$ newd = $ d ;
$ frame_flag = 1 ;
}
2011-08-25 09:11:06 +00:00
2011-11-30 08:21:48 +00:00
if ( $ lpar_flag && $ cec_flag ) {
2011-12-07 07:54:44 +00:00
push @ output , [ $ node_name , " $node_name\'s type is different from the last node. The noderange of power control operation could NOT be lpar/cec mixed" , - 1 ] ;
2011-11-30 08:21:48 +00:00
return ( \ @ output ) ;
}
2011-08-25 09:11:06 +00:00
2011-11-30 08:21:48 +00:00
if ( $ lpar_flag && $ frame_flag ) {
2011-12-07 07:54:44 +00:00
push @ output , [ $ node_name , " $node_name\'s type is different from the last node. The noderange of power control operation could NOT be lpar/frame mixed" , - 1 ] ;
2011-11-30 08:21:48 +00:00
return ( \ @ output ) ;
}
if ( $ cec_flag && $ frame_flag ) {
2011-12-07 07:54:44 +00:00
push @ output , [ $ node_name , " $node_name\'s type is different from the last node. The noderange of power control operation could NOT be cec/frame mixed" , - 1 ] ;
2011-11-30 08:21:48 +00:00
return ( \ @ output ) ;
2010-02-26 09:42:41 +00:00
}
2011-11-30 08:21:48 +00:00
2009-12-02 09:41:51 +00:00
}
2011-11-30 08:21:48 +00:00
$$ newd [ 0 ] = $ newids ;
#print Dumper($newd);
2011-12-07 07:54:44 +00:00
my $ res = xCAT::FSPUtils:: fsp_api_action ( $ newnames , $ newd , $ action , 0 , $ request - > { 'powerinterval' } ) ;
2011-11-30 08:21:48 +00:00
# print "In boot, state\n";
# print Dumper($res);
my $ Rc = @$ res [ 2 ] ;
my $ data = @$ res [ 1 ] ;
foreach $ node_name ( keys %$ hash )
{
my $ d = $ hash - > { $ node_name } ;
if ( $ data =~ /Error/ ) {
2011-12-07 08:10:17 +00:00
if ( $ data =~ /Power interval/ ) {
$ data = "Error: Invalid powerinterval value in the site table. The valid powerinerval value could be 0 to 300 ." ;
2012-02-01 06:08:51 +00:00
push @ output , [ $ node_name , $ data , - 1 ] ;
next ;
} elsif ( $ data =~ /$node_name/ ) {
push @ output , [ $ node_name , $ data , - 1 ] ;
next ;
2011-12-07 08:10:17 +00:00
}
2011-11-30 08:21:48 +00:00
}
2012-02-01 06:08:51 +00:00
push @ output , [ $ node_name , "Success" , 0 ] ;
2011-11-30 08:21:48 +00:00
}
2009-12-02 09:41:51 +00:00
return ( \ @ output ) ;
}
##########################################################################
2009-12-10 02:19:40 +00:00
# Queries CEC/LPAR power status (On or Off) for powercmd_boot
2009-12-02 09:41:51 +00:00
##########################################################################
sub power_status {
2011-04-22 07:53:51 +00:00
my $ value = shift ;
2009-12-02 09:41:51 +00:00
my @ states = (
"Operating|operating" ,
"Running|running" ,
2011-04-22 07:53:51 +00:00
"standby" ,
2009-12-02 09:41:51 +00:00
"Open Firmware|open-firmware"
) ;
2011-04-22 07:53:51 +00:00
foreach my $ s ( @ states ) {
if ( $ value =~ /$s/ ) {
2009-12-02 09:41:51 +00:00
return ( "on" ) ;
}
}
return ( "off" ) ;
}
2009-12-10 02:19:40 +00:00
##########################################################################
# Queries CEC/LPAR power status
##########################################################################
2009-12-02 09:41:51 +00:00
sub state {
my $ request = shift ;
my $ hash = shift ;
2010-01-18 06:14:05 +00:00
my $ exp = shift ; # NOt use
my $ prefix = shift ;
my $ convert = shift ;
2009-12-02 09:41:51 +00:00
my @ output = ( ) ;
2010-06-04 09:05:30 +00:00
#print "------in state--------\n";
#print Dumper($request);
#print Dumper($hash);
####################################
# Power commands are grouped by hardware control point
# In FSPpower, the hcp is the related fsp.
####################################
# Example of $hash.
#VAR1 = {
# '9110-51A*1075ECF' => {
# 'Server-9110-51A-SN1075ECF' => [
# 0,
# 0,
# '9110-51A*1075ECF',
# 'fsp1_name',
# 'fsp',
# 0
# ]
# }
# };
my @ result = ( ) ;
if ( ! defined ( $ prefix ) ) {
$ prefix = "" ;
}
while ( my ( $ mtms , $ h ) = each ( %$ hash ) ) {
######################################
# Build CEC/LPAR information hash
######################################
my $ stat = enumerate ( $ h , $ mtms ) ;
my $ Rc = shift ( @$ stat ) ;
my $ data = @$ stat [ 0 ] ;
2010-08-05 06:48:09 +00:00
#if($Rc != 0) {
# push @result,[$mtms ,$$data[0],$Rc];
# return(\@result);
#}
2010-06-04 09:05:30 +00:00
while ( my ( $ name , $ d ) = each ( %$ h ) ) {
##################################
# Look up by lparid
##################################
my $ type = @$ d [ 4 ] ;
2011-03-04 06:44:51 +00:00
my $ id = ( $ type =~ /^(fsp|bpa|cec|frame)$/ ) ? $ type : @$ d [ 0 ] ;
2010-06-04 09:05:30 +00:00
##################################
# Output error
##################################
if ( $ Rc != SUCCESS ) {
push @ result , [ $ name , "$prefix$data" , $ Rc ] ;
next ;
}
2010-09-16 08:42:43 +00:00
#print Dumper($data);
my @ k = keys ( %$ data ) ;
if ( grep ( /all/ , @ k ) == 1 ) {
$ data - > { $ id } = $ data - > { all } ;
}
2010-06-04 09:05:30 +00:00
##################################
# Node not found
##################################
if ( ! exists ( $ data - > { $ id } ) ) {
push @ result , [ $ name , $ prefix . "Node not found" , 1 ] ;
next ;
}
##################################
# Output value
##################################
my $ value = $ data - > { $ id } ;
##############################
# Convert state to on/off
##############################
if ( defined ( $ convert ) ) {
$ value = power_status ( $ value ) ;
}
push @ result , [ $ name , "$prefix$value" , $ Rc ] ;
}
}
return ( \ @ result ) ;
}
##########################################################################
# Queries CEC/LPAR power status
##########################################################################
sub state1 {
my $ request = shift ;
my $ hash = shift ;
my $ exp = shift ; # NOt use
my $ prefix = shift ;
my $ convert = shift ;
my @ output = ( ) ;
2010-02-26 09:42:41 +00:00
my $ action = "state" ;
2010-01-18 06:14:05 +00:00
2009-12-02 09:41:51 +00:00
#print "------in state--------\n";
#print Dumper($request);
#print Dumper($hash);
####################################
# Power commands are grouped by hardware control point
2009-12-10 02:19:40 +00:00
# In FSPpower, the hcp is the related fsp.
2009-12-02 09:41:51 +00:00
####################################
# Example of $hash.
#VAR1 = {
# '9110-51A*1075ECF' => {
# 'Server-9110-51A-SN1075ECF' => [
# 0,
# 0,
2010-02-26 09:42:41 +00:00
# '9110-51A*1075ECF',
# 'fsp1_name',
# 'fsp',
# 0
# ]
2009-12-10 02:19:40 +00:00
# }
2009-12-02 09:41:51 +00:00
# };
foreach my $ cec_bpa ( keys %$ hash )
2010-06-04 09:05:30 +00:00
{
2009-12-02 09:41:51 +00:00
my $ node_hash = $ hash - > { $ cec_bpa } ;
for my $ node_name ( keys %$ node_hash )
{
my $ d = $ node_hash - > { $ node_name } ;
2010-02-26 09:42:41 +00:00
if ( $$ d [ 4 ] =~ /^fsp$/ || $$ d [ 4 ] =~ /^bpa$/ ) {
$ action = "cec_state" ;
2010-06-04 09:05:30 +00:00
}
2010-08-04 07:06:48 +00:00
my $ stat = xCAT::FSPUtils:: fsp_api_action ( $ node_name , $ d , $ action ) ;
2010-02-26 09:42:41 +00:00
my $ Rc = @$ stat [ 2 ] ;
my $ data = @$ stat [ 1 ] ;
2009-12-02 09:41:51 +00:00
my $ type = @$ d [ 4 ] ;
2010-02-26 09:42:41 +00:00
#my $id = ($type=~/^(fsp|bpa)$/) ? $type : @$d[0];
2009-12-02 09:41:51 +00:00
##################################
# Output error
##################################
if ( $ Rc != SUCCESS ) {
2010-02-26 09:42:41 +00:00
push @ output , [ $ node_name , $ data , $ Rc ] ;
2009-12-02 09:41:51 +00:00
next ;
}
2010-02-26 09:42:41 +00:00
##############################
# Convert state to on/off
##############################
if ( defined ( $ convert ) ) {
$ data = power_status ( $ data ) ;
}
2009-12-02 09:41:51 +00:00
2010-02-26 09:42:41 +00:00
#print Dumper($prefix);
##################
# state cec_state
#################
if ( defined ( $ prefix ) ) {
$ data = "$prefix $data" ;
}
2009-12-02 09:41:51 +00:00
2010-02-26 09:42:41 +00:00
push @ output , [ $ node_name , $ data , $ Rc ] ;
2009-12-10 02:19:40 +00:00
}
2009-12-02 09:41:51 +00:00
2009-12-10 02:19:40 +00:00
}
2010-02-26 09:42:41 +00:00
return ( \ @ output ) ;
2009-12-02 09:41:51 +00:00
}
1 ;