2010-11-25 02:47:38 +00:00
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
2011-03-02 09:32:34 +00:00
BEGIN
{
$ ::XCATROOT = $ ENV { 'XCATROOT' } ? $ ENV { 'XCATROOT' } : '/opt/xcat' ;
}
2010-11-25 02:47:38 +00:00
package xCAT::FSPvm ;
2011-03-02 09:32:34 +00:00
use lib "$::XCATROOT/lib/perl" ;
2010-11-25 02:47:38 +00:00
use strict ;
use Getopt::Long ;
use xCAT::PPCdb ;
use xCAT::PPCcli qw( SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR ) ;
use xCAT::Usage ;
use xCAT::NodeRange ;
use xCAT::FSPUtils ;
2011-04-08 05:23:16 +00:00
#use Data::Dumper;
2010-11-25 02:47:38 +00:00
##############################################
# Globals
##############################################
my % method = (
mkvm = > \ & mkvm_parse_args ,
lsvm = > \ & lsvm_parse_args ,
rmvm = > \ & rmvm_parse_args ,
chvm = > \ & chvm_parse_args
) ;
##########################################################################
# Parse the command line for options and operands
##########################################################################
sub parse_args {
my $ request = shift ;
my $ cmd = $ request - > { command } ;
###############################
# Invoke correct parse_args
###############################
my $ result = $ method { $ cmd } ( $ request ) ;
return ( $ result ) ;
}
##########################################################################
# Parse the chvm command line for options and operands
##########################################################################
sub chvm_parse_args {
my $ request = shift ;
my % opt = ( ) ;
my $ cmd = $ request - > { command } ;
my $ args = $ request - > { arg } ;
#############################################
# Responds with usage statement
#############################################
local * usage = sub {
my $ usage_string = xCAT::Usage - > getUsage ( $ cmd ) ;
return ( [ $ _ [ 0 ] , $ usage_string ] ) ;
} ;
#############################################
# Process command-line arguments
#############################################
if ( ! defined ( $ args ) ) {
$ request - > { method } = $ cmd ;
2011-03-02 09:32:34 +00:00
return ( \ % opt ) ;
2010-11-25 02:47:38 +00:00
}
#############################################
# 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" ) ;
2011-04-06 06:49:42 +00:00
if ( ! GetOptions ( \ % opt , qw( V|verbose p=s i=s m=s r=s ) ) ) {
2010-11-25 02:47:38 +00:00
return ( usage ( ) ) ;
}
####################################
# Check for "-" with no option
####################################
if ( grep ( /^-$/ , @ ARGV ) ) {
return ( usage ( "Missing option: -" ) ) ;
}
####################################
# Check for an extra argument
####################################
if ( defined ( $ ARGV [ 0 ] ) ) {
2011-03-02 09:32:34 +00:00
return ( usage ( "Invalid argument: $ARGV[0]" ) ) ;
2010-11-25 02:47:38 +00:00
}
####################################
# Configuration file required
####################################
2011-04-06 06:49:42 +00:00
#if ( !exists( $opt{p}) ) {
# if ( !defined( $request->{stdin} )) {
# return(usage( "Configuration file or attributes not specified" ));
# }
#}
2011-03-02 09:32:34 +00:00
my @ cfgdata ;
if ( exists ( $ opt { p } ) ) {
2011-04-06 06:49:42 +00:00
if ( exists ( $ opt { i } ) || exists ( $ opt { r } ) || exists ( $ opt { m } ) ) {
return ( usage ( "-p should NOT be used with -i, -r or -m." ) ) ;
}
2011-03-02 09:32:34 +00:00
$ opt { p } = $ request - > { cwd } - > [ 0 ] . '/' . $ opt { p } if ( $ opt { p } !~ /^\// ) ;
return ( usage ( "Profile $opt{p} cannot be found" ) ) if ( ! - f $ opt { p } ) ;
open ( PROFFILE , "<$opt{p}" ) or return ( usage ( "Cannot open profile $opt{p}" ) ) ;
while ( <PROFFILE> ) {
chomp ;
2011-03-08 06:44:07 +00:00
if ( $ _ =~ /(\d+):(\s+)(\d+)\/([\w\.\-]+)\/(\w+)\// ) {
2011-03-02 09:32:34 +00:00
push @ cfgdata , $ _ ;
} else {
return ( usage ( "Invalid line in profile: $_" ) ) ;
}
}
$ opt { profile } = \ @ cfgdata ;
}
2011-04-06 06:49:42 +00:00
if ( defined ( $ request - > { stdin } ) ) {
$ opt { p } = 1 ;
if ( exists ( $ opt { i } ) || exists ( $ opt { r } ) || exists ( $ opt { m } ) ) {
return ( usage ( "When the profile is piped into the chvm command, the -i, -r and -m could NOT be used." ) ) ;
}
}
2011-03-07 06:18:23 +00:00
#if (defined( $request->{stdin} )) {
# my $p = $request->{stdin};
# my @io = split(/\n/, $p) ;
# foreach (@io) {
# chomp;
# if( $_ =~ /(\d+):(\s+)(\d+),([\w\.\-]+),(\w+),/) {
# push @cfgdata, $_;
# } else {
# return ( usage( "Invalid line in profile: $_"));
# }
2011-03-02 09:32:34 +00:00
2011-03-07 06:18:23 +00:00
# }
2011-03-02 09:32:34 +00:00
2011-03-07 06:18:23 +00:00
# $opt{profile} = \@cfgdata;
#}
#print "in parse args:\n";
2011-04-06 06:49:42 +00:00
#print Dumper(\%opt);
if ( exists ( $ opt { i } ) ) {
if ( ! exists ( $ opt { r } ) ) {
return ( usage ( "Option -i should be used with option -r ." ) ) ;
}
if ( $ opt { i } !~ /^([1-9]{1}|[1-9]{1}[0-9]+)$/ ) {
return ( usage ( "Invalid entry: $opt{i}" ) ) ;
}
my @ id = ( 1 , 5 , 9 , 13 , 17 , 21 , 25 , 29 ) ;
my @ found = grep ( /^$opt{i}$/ , @ id ) ;
if ( @ found != 1 ) {
return ( usage ( "Invalid entry: $opt{i}.\n For P7 IH, starting numeric id of the newly created partitions only could be 1, 5, 9, 13, 17, 21, 25 and 29." ) ) ;
}
#if ( !exists($opt{o}) ) {
# return(usage("For P7 IH, -i should be used with -o"));
#}
#my @value = (1, 2, 3, 4, 5);
#if ( grep(/^$opt{i}$/, @id ) != 1) {
# return(usage( "Invalid entry: $opt{o}.\n For P7 IH, octant configuration values only could be 1, 2, 3, 4, 5. Please see the details in manpage of mkvm." ));
#}
}
# pending memory interleaving mode (1- interleaved, 2- non-interleaved)
# non-interleaved mode means the memory cannot be shared across the processors in an octant.
# interleaved means the memory can be shared.
if ( exists ( $ opt { m } ) ) {
if ( $ opt { m } =~ /^interleaved$/ || $ opt { m } =~ /^1$/ ) {
$ opt { m } = 1 ;
} elsif ( $ opt { m } =~ /^non-interleaved$/ || $ opt { m } =~ /^2$/ ) {
$ opt { m } = 2 ;
} else {
return ( usage ( "Invalid entry: $opt{m}.\n For P7 IH, the pending memory interleaving mode only could be interleaved(or 1), or non-interleaved(or 2)." ) ) ;
}
} else {
$ opt { m } = 2 ; # non-interleaved, which is the default
}
my @ ratio = ( 1 , 2 , 3 , 4 , 5 ) ;
my % octant_cfg = ( ) ;
if ( exists ( $ opt { r } ) ) {
if ( ! exists ( $ opt { i } ) ) {
return ( usage ( "Option -r should be used with option -i ." ) ) ;
}
my @ elems = split ( /\,/ , $ opt { r } ) ;
my $ range = "" ;
while ( my $ elem = shift @ elems ) {
if ( $ elem !~ /\-/ ) {
my @ subelems = split ( /\:/ , $ elem ) ;
if ( $ subelems [ 0 ] < 0 || $ subelems [ 0 ] > 7 ) {
return ( usage ( "Octant ID only could be 0 to 7 in the octant configuration value $elem" ) ) ;
}
if ( grep ( /^$subelems[1]$/ , @ ratio ) != 1 ) {
return ( usage ( "Invalid octant configuration value in $elem.\n For P7 IH, octant configuration values only could be 1, 2, 3, 4, 5. Please see the details in manpage of mkvm." ) ) ;
}
if ( exists ( $ octant_cfg { $ subelems [ 0 ] } ) && $ octant_cfg { $ subelems [ 0 ] } == $ subelems [ 1 ] ) {
return ( usage ( "In the octant configuration rule, same octant with different octant configuration value. Error!" ) ) ;
}
$ octant_cfg { $ subelems [ 0 ] } = $ subelems [ 1 ] ;
$ range . = "$elem," ;
} else {
my @ subelems = split ( /\:/ , $ elem ) ;
my ( $ left , $ right ) = split ( /\-/ , $ subelems [ 0 ] ) ;
if ( $ left < 0 || $ left > 7 || $ right < 0 || $ right > 7 ) {
return ( usage ( "Octant ID only could be 0 to 7 in the octant configuration rule $elem" ) ) ;
}
if ( $ left == $ right ) {
if ( grep ( /^$subelems[1]$/ , @ ratio ) != 1 ) {
return ( usage ( "Invalid octant configuration value in $elem.\n For P7 IH, octant configuration values only could be 1, 2, 3, 4, 5. Please see the details in manpage of mkvm." ) ) ;
}
if ( exists ( $ octant_cfg { $ left } ) || $ octant_cfg { $ left } == $ subelems [ 1 ] ) {
return ( usage ( "In the octant configuration rule, same octant with different octant configuration value. Error!" ) ) ;
}
$ octant_cfg { $ left } = $ subelems [ 1 ] ;
$ range . = "$left:$subelems[1],"
} elsif ( $ left < $ right ) {
my $ i = $ left ;
for ( $ i ; $ i <= $ right ; $ i + + ) {
if ( exists ( $ octant_cfg { $ i } ) || $ octant_cfg { $ i } == $ subelems [ 1 ] ) {
return ( usage ( "In the octant configuration rule, same octant with different octant configuration value. Error!" ) ) ;
}
$ octant_cfg { $ i } = $ subelems [ 1 ] ;
$ range . = "$i:$subelems[1]," ;
}
} else {
return ( usage ( "In the octant configuration rule $elem, the left octant ID could NOT be bigger than the right octant ID" ) ) ;
}
} # end of "if .. else.."
} # end of while
} #end of if
if ( exists ( $ opt { i } ) && exists ( $ opt { r } ) ) {
$ opt { octant_cfg } { octant_cfg_value } = ( \ % octant_cfg ) ;
$ opt { octant_cfg } { memory_interleave } = $ opt { m } ;
$ opt { target } = \ @ { $ request - > { node } } ;
my $ ppctab = xCAT::Table - > new ( 'ppc' ) ;
unless ( $ ppctab ) {
return ( usage ( "Cannot open ppc table" ) ) ;
}
my $ other_p ;
foreach my $ node ( @ { $ request - > { node } } ) {
my $ parent_hash = $ ppctab - > getNodeAttribs ( $ node , [ qw( parent ) ] ) ;
my $ p = $ parent_hash - > { parent } ;
if ( ! $ p ) {
return ( usage ( "Not found the parent of $node" ) ) ;
}
if ( ! defined ( $ other_p ) ) {
$ other_p = $ p ;
}
if ( $ other_p ne $ p ) {
return ( usage ( "For P7 IH, please make sure the noderange are in one CEC " ) ) ;
}
}
$ request - > { node } = [ $ other_p ] ;
$ request - > { noderange } = $ other_p ;
}
2010-11-25 02:47:38 +00:00
####################################
# No operands - add command name
####################################
$ request - > { method } = $ cmd ;
return ( \ % opt ) ;
}
##########################################################################
# Parse the mkvm command line for options and operands
##########################################################################
sub mkvm_parse_args {
my $ request = shift ;
my % opt = ( ) ;
my $ cmd = $ request - > { command } ;
my $ args = $ request - > { arg } ;
#############################################
# Responds with usage statement
#############################################
local * usage = sub {
my $ usage_string = xCAT::Usage - > getUsage ( $ cmd ) ;
return ( [ $ _ [ 0 ] , $ usage_string ] ) ;
} ;
#############################################
# 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" ) ;
# if ( !GetOptions( \%opt, qw(V|verbose ibautocfg ibacap=s i=s l=s c=s p=s full) )) {
# return( usage() );
# }
2011-03-02 09:32:34 +00:00
if ( ! GetOptions ( \ % opt , qw( V|verbose i=s m=s r=s ) ) ) {
2010-11-25 02:47:38 +00:00
return ( usage ( ) ) ;
}
####################################
# Check for "-" with no option
####################################
if ( grep ( /^-$/ , @ ARGV ) ) {
return ( usage ( "Missing option: -" ) ) ;
}
####################################
# Check for non-zero integer
####################################
if ( exists ( $ opt { i } ) ) {
if ( $ opt { i } !~ /^([1-9]{1}|[1-9]{1}[0-9]+)$/ ) {
return ( usage ( "Invalid entry: $opt{i}" ) ) ;
}
my @ id = ( 1 , 5 , 9 , 13 , 17 , 21 , 25 , 29 ) ;
my @ found = grep ( /^$opt{i}$/ , @ id ) ;
if ( @ found != 1 ) {
return ( usage ( "Invalid entry: $opt{i}.\n For P7 IH, starting numeric id of the newly created partitions only could be 1, 5, 9, 13, 17, 21, 25 and 29." ) ) ;
}
2011-03-02 09:32:34 +00:00
#if ( !exists($opt{o}) ) {
# return(usage("For P7 IH, -i should be used with -o"));
#}
2010-11-25 02:47:38 +00:00
2011-03-02 09:32:34 +00:00
#my @value = (1, 2, 3, 4, 5);
#if ( grep(/^$opt{i}$/, @id ) != 1) {
# return(usage( "Invalid entry: $opt{o}.\n For P7 IH, octant configuration values only could be 1, 2, 3, 4, 5. Please see the details in manpage of mkvm." ));
#}
2010-11-25 02:47:38 +00:00
}
2011-03-02 09:32:34 +00:00
# pending memory interleaving mode (1- interleaved, 2- non-interleaved)
# non-interleaved mode means the memory cannot be shared across the processors in an octant.
# interleaved means the memory can be shared.
if ( exists ( $ opt { m } ) ) {
if ( $ opt { m } =~ /^interleaved$/ || $ opt { m } =~ /^1$/ ) {
$ opt { m } = 1 ;
} elsif ( $ opt { m } =~ /^non-interleaved$/ || $ opt { m } =~ /^2$/ ) {
$ opt { m } = 2 ;
} else {
return ( usage ( "Invalid entry: $opt{m}.\n For P7 IH, the pending memory interleaving mode only could be interleaved(or 1), or non-interleaved(or 2)." ) ) ;
2010-11-25 02:47:38 +00:00
}
2011-03-02 09:32:34 +00:00
} else {
$ opt { m } = 2 ; # non-interleaved, which is the default
}
my @ ratio = ( 1 , 2 , 3 , 4 , 5 ) ;
my % octant_cfg = ( ) ;
if ( exists ( $ opt { r } ) ) {
my @ elems = split ( /\,/ , $ opt { r } ) ;
my $ range = "" ;
while ( my $ elem = shift @ elems ) {
if ( $ elem !~ /\-/ ) {
my @ subelems = split ( /\:/ , $ elem ) ;
if ( $ subelems [ 0 ] < 0 || $ subelems [ 0 ] > 7 ) {
return ( usage ( "Octant ID only could be 0 to 7 in the octant configuration value $elem" ) ) ;
}
if ( grep ( /^$subelems[1]$/ , @ ratio ) != 1 ) {
return ( usage ( "Invalid octant configuration value in $elem.\n For P7 IH, octant configuration values only could be 1, 2, 3, 4, 5. Please see the details in manpage of mkvm." ) ) ;
}
if ( exists ( $ octant_cfg { $ subelems [ 0 ] } ) && $ octant_cfg { $ subelems [ 0 ] } == $ subelems [ 1 ] ) {
return ( usage ( "In the octant configuration rule, same octant with different octant configuration value. Error!" ) ) ;
}
$ octant_cfg { $ subelems [ 0 ] } = $ subelems [ 1 ] ;
$ range . = "$elem," ;
} else {
my @ subelems = split ( /\:/ , $ elem ) ;
my ( $ left , $ right ) = split ( /\-/ , $ subelems [ 0 ] ) ;
if ( $ left < 0 || $ left > 7 || $ right < 0 || $ right > 7 ) {
return ( usage ( "Octant ID only could be 0 to 7 in the octant configuration rule $elem" ) ) ;
}
if ( $ left == $ right ) {
if ( grep ( /^$subelems[1]$/ , @ ratio ) != 1 ) {
return ( usage ( "Invalid octant configuration value in $elem.\n For P7 IH, octant configuration values only could be 1, 2, 3, 4, 5. Please see the details in manpage of mkvm." ) ) ;
}
if ( exists ( $ octant_cfg { $ left } ) || $ octant_cfg { $ left } == $ subelems [ 1 ] ) {
return ( usage ( "In the octant configuration rule, same octant with different octant configuration value. Error!" ) ) ;
}
$ octant_cfg { $ left } = $ subelems [ 1 ] ;
$ range . = "$left:$subelems[1],"
} elsif ( $ left < $ right ) {
my $ i = $ left ;
for ( $ i ; $ i <= $ right ; $ i + + ) {
if ( exists ( $ octant_cfg { $ i } ) || $ octant_cfg { $ i } == $ subelems [ 1 ] ) {
return ( usage ( "In the octant configuration rule, same octant with different octant configuration value. Error!" ) ) ;
}
$ octant_cfg { $ i } = $ subelems [ 1 ] ;
$ range . = "$i:$subelems[1]," ;
}
} else {
return ( usage ( "In the octant configuration rule $elem, the left octant ID could NOT be bigger than the right octant ID" ) ) ;
}
} # end of "if .. else.."
} # end of while
} #end of if
2010-11-25 02:47:38 +00:00
2011-03-02 09:32:34 +00:00
$ opt { octant_cfg } { octant_cfg_value } = ( \ % octant_cfg ) ;
$ opt { octant_cfg } { memory_interleave } = $ opt { m } ;
if ( ! exists ( $ opt { i } ) || ! exists ( $ opt { r } ) ) {
return ( usage ( ) ) ;
2010-11-25 02:47:38 +00:00
}
2011-03-02 09:32:34 +00:00
$ opt { target } = \ @ { $ request - > { node } } ;
my $ ppctab = xCAT::Table - > new ( 'ppc' ) ;
unless ( $ ppctab ) {
return ( usage ( "Cannot open ppc table" ) ) ;
}
my $ other_p ;
foreach my $ node ( @ { $ request - > { node } } ) {
my $ parent_hash = $ ppctab - > getNodeAttribs ( $ node , [ qw( parent ) ] ) ;
my $ p = $ parent_hash - > { parent } ;
if ( ! $ p ) {
return ( usage ( "Not found the parent of $node" ) ) ;
}
if ( ! defined ( $ other_p ) ) {
$ other_p = $ p ;
}
if ( $ other_p ne $ p ) {
return ( usage ( "For P7 IH, please make sure the noderange are in one CEC " ) ) ;
}
}
$ request - > { node } = [ $ other_p ] ;
$ request - > { noderange } = $ other_p ;
2010-11-25 02:47:38 +00:00
####################################
# No operands - add command name
####################################
$ request - > { method } = $ cmd ;
return ( \ % opt ) ;
}
##########################################################################
# Parse the rmvm command line for options and operands
##########################################################################
sub rmvm_parse_args {
my $ request = shift ;
my % opt = ( ) ;
my $ cmd = $ request - > { command } ;
my $ args = $ request - > { arg } ;
#############################################
# Responds with usage statement
#############################################
local * usage = sub {
my $ usage_string = xCAT::Usage - > getUsage ( $ cmd ) ;
return ( [ $ _ [ 0 ] , $ usage_string ] ) ;
} ;
#############################################
# Process command-line arguments
#############################################
if ( ! defined ( $ args ) ) {
$ request - > { method } = $ cmd ;
return ( \ % opt ) ;
}
#############################################
# 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" ) ;
if ( ! GetOptions ( \ % opt , qw( V|verbose service r ) ) ) {
return ( usage ( ) ) ;
}
2011-03-02 09:32:34 +00:00
return ( usage ( "rmvm doesn't support for P7 IH." ) ) ;
2010-11-25 02:47:38 +00:00
####################################
# Check for "-" with no option
####################################
if ( grep ( /^-$/ , @ ARGV ) ) {
return ( usage ( "Missing option: -" ) ) ;
}
####################################
# Check for an extra argument
####################################
if ( defined ( $ ARGV [ 0 ] ) ) {
return ( usage ( "Invalid Argument: $ARGV[0]" ) ) ;
}
####################################
# No operands - add command name
####################################
$ request - > { method } = $ cmd ;
return ( \ % opt ) ;
}
##########################################################################
# Parse the lsvm command line for options and operands
##########################################################################
sub lsvm_parse_args {
my $ request = shift ;
my % opt = ( ) ;
my $ cmd = $ request - > { command } ;
my $ args = $ request - > { arg } ;
#############################################
# Responds with usage statement
#############################################
local * usage = sub {
my $ usage_string = xCAT::Usage - > getUsage ( $ cmd ) ;
return ( [ $ _ [ 0 ] , $ usage_string ] ) ;
} ;
#############################################
# Process command-line arguments
#############################################
if ( ! defined ( $ args ) ) {
$ request - > { method } = $ cmd ;
return ( \ % opt ) ;
}
#############################################
# 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" ) ;
2011-03-02 09:32:34 +00:00
if ( ! GetOptions ( \ % opt , qw( V|verbose ) ) ) {
2010-11-25 02:47:38 +00:00
return ( usage ( ) ) ;
}
####################################
# Check for "-" with no option
####################################
if ( grep ( /^-$/ , @ ARGV ) ) {
return ( usage ( "Missing option: -" ) ) ;
}
####################################
# Check for an extra argument
####################################
if ( defined ( $ ARGV [ 0 ] ) ) {
return ( usage ( "Invalid Argument: $ARGV[0]" ) ) ;
}
####################################
# No operands - add command name
####################################
$ request - > { method } = $ cmd ;
return ( \ % opt ) ;
}
##########################################################################
# Changes the configuration of an existing partition
##########################################################################
sub modify {
my $ request = shift ;
my $ hash = shift ;
2011-04-06 06:49:42 +00:00
return modify_by_prof ( $ request , $ hash ) if ( $ request - > { opt } - > { p } ) ;
return create ( $ request , $ hash ) if ( $ request - > { opt } - > { i } ) ;
2010-11-25 02:47:38 +00:00
}
2011-03-02 09:32:34 +00:00
2010-11-25 02:47:38 +00:00
##########################################################################
# Changes the configuration of an existing
2011-03-02 09:32:34 +00:00
# partition based on the profile specified
2010-11-25 02:47:38 +00:00
##########################################################################
2011-03-02 09:32:34 +00:00
sub modify_by_prof {
2010-11-25 02:47:38 +00:00
my $ request = shift ;
my $ hash = shift ;
my $ name = @ { $ request - > { node } } [ 0 ] ;
my $ opt = $ request - > { opt } ;
my @ values ;
2011-03-02 09:32:34 +00:00
my $ cfgdata = $ opt - > { profile } ;
my $ profile ;
my $ cec_name ;
my $ td ;
my % io = ( ) ;
my % lpar_state = ( ) ;
2011-03-24 02:02:15 +00:00
my @ result ;
2010-11-25 02:47:38 +00:00
2011-03-07 06:18:23 +00:00
if ( defined ( $ request - > { stdin } ) ) {
my $ p = $ request - > { stdin } ;
my @ io = split ( /\n/ , $ p ) ;
foreach ( @ io ) {
chomp ;
2011-03-08 06:44:07 +00:00
if ( $ _ =~ /(\d+):(\s+)(\d+)\/([\w\.\-]+)\/(\w+)\// ) {
2011-03-07 06:18:23 +00:00
push @$ cfgdata , $ _ ;
} else {
return ( \ [ "Error" , "Invalid line in profile: $_" , - 1 ] ) ;
}
}
}
2011-03-24 02:02:15 +00:00
#print Dumper($cfgdata);
2011-03-02 09:32:34 +00:00
while ( my ( $ cec , $ h ) = each ( %$ hash ) ) {
while ( my ( $ lpar , $ d ) = each ( %$ h ) ) {
$ td = $ d ;
@$ td [ 4 ] = "fsp" ;
$ cec_name = @$ d [ 3 ] ;
}
#get the current I/O slot information
my $ action = "get_io_slot_info" ;
my $ values = xCAT::FSPUtils:: fsp_api_action ( $ cec_name , $ td , $ action ) ;
my $ Rc = shift ( @$ values ) ;
if ( $ Rc != 0 ) {
2011-03-24 02:02:15 +00:00
push @ result , [ $ cec_name , $$ values [ 0 ] , $ Rc ] ;
return ( \ @ result ) ;
2011-03-02 09:32:34 +00:00
}
my @ data = split ( /\n/ , $$ values [ 0 ] ) ;
foreach my $ v ( @ data ) {
my ( $ lparid , $ busid , $ location , $ drc_index , $ owner_type , $ owner , $ descr ) = split ( /,/ , $ v ) ;
$ io { $ drc_index } { lparid } = $ lparid ;
$ io { $ drc_index } { owner_type } = $ owner_type ;
$ io { $ drc_index } { owner } = $ owner ;
}
#get all the nodes state in the same cec
$ action = "all_lpars_state" ;
undef ( $ values ) ;
my $ values = xCAT::FSPUtils:: fsp_state_action ( $ cec_name , "fsp" , $ action ) ;
$ Rc = shift ( @$ values ) ;
if ( $ Rc != 0 ) {
2011-03-24 02:02:15 +00:00
push @ result , [ $ cec_name , $$ values [ 0 ] , $ Rc ] ;
return ( \ @ result ) ;
2011-03-02 09:32:34 +00:00
}
foreach ( @$ values ) {
my ( $ state , $ lparid ) = split /,/ ;
$ lpar_state { $ lparid } = $ state ;
}
}
##################################
# Check if LPAR profile exists
###################################
while ( my ( $ cec , $ h ) = each ( %$ hash ) ) {
while ( my ( $ lpar , $ d ) = each ( %$ h ) ) {
my $ id = @$ d [ 0 ] ;
2011-03-07 06:18:23 +00:00
#print Dumper($cfgdata);
2011-03-02 09:32:34 +00:00
my @ found = grep ( /^$id:/ , @$ cfgdata ) ;
2011-03-08 06:44:07 +00:00
#print Dumper(\@found);
2011-03-02 09:32:34 +00:00
my $ action = "set_io_slot_owner" ;
my $ tooltype = 0 ;
foreach my $ f ( @ found ) {
2011-03-08 06:44:07 +00:00
#'1: 514/U78A9.001.0123456-P1-C17/0x21010202/2/1'
my ( $ bus , $ location , $ drc_index , @ t ) = split ( /\// , $ f ) ;
2011-03-02 09:32:34 +00:00
my $ orig_id = $ io { $ drc_index } { lparid } ;
# the current owning lpar and the new owning lpar must be in power off state
2011-03-07 06:18:23 +00:00
if ( ( $ lpar_state { $ orig_id } ne "Not Activated" ) || ( $ lpar_state { $ id } ne "Not Activated" ) ) {
2011-03-24 02:02:15 +00:00
push @ result , [ $ lpar , "For the I/O $location, the current owning lpar(id=$orig_id) of the I/O and the new owning lpar(id=$id) must be in Not Activated state at first. And then run chvm again" , - 1 ] ;
return ( \ @ result ) ;
2011-03-02 09:32:34 +00:00
}
my $ values = xCAT::FSPUtils:: fsp_api_action ( $ lpar , $ d , $ action , $ tooltype , $ drc_index ) ;
2011-03-24 02:02:15 +00:00
#my $Rc = shift(@$values);
my $ Rc = pop ( @$ values ) ;
2011-03-02 09:32:34 +00:00
if ( $ Rc != 0 ) {
2011-03-24 02:02:15 +00:00
push @ result , [ $ lpar , $$ values [ 1 ] , $ Rc ] ;
2010-11-25 02:47:38 +00:00
next ;
2011-03-02 09:32:34 +00:00
}
2010-11-25 02:47:38 +00:00
}
2011-03-02 09:32:34 +00:00
2010-11-25 02:47:38 +00:00
}
}
2011-03-24 02:02:15 +00:00
return ( \ @ result ) ;
2010-11-25 02:47:38 +00:00
}
2011-03-02 09:32:34 +00:00
sub enumerate {
my $ h = shift ;
my $ mtms = shift ;
my % outhash = ( ) ;
my $ cec ;
my $ type ;
2011-03-04 02:51:55 +00:00
my @ td ;
2011-03-02 09:32:34 +00:00
while ( my ( $ name , $ d ) = each ( %$ h ) ) {
$ cec = @$ d [ 3 ] ;
$ type = @$ d [ 4 ] ;
2011-03-04 02:51:55 +00:00
@ td = @$ d ;
2010-11-25 02:47:38 +00:00
}
2011-03-04 02:51:55 +00:00
$ td [ 4 ] = "fsp" ;
2011-03-02 09:32:34 +00:00
my $ action = "get_io_slot_info" ;
2011-03-04 02:51:55 +00:00
my $ values = xCAT::FSPUtils:: fsp_api_action ( $ cec , \ @ td , $ action ) ;
2011-03-02 09:32:34 +00:00
my $ Rc = shift ( @$ values ) ;
if ( $ Rc != 0 ) {
return ( [ $ Rc , @$ values [ 0 ] ] ) ;
2010-11-25 02:47:38 +00:00
}
2011-03-02 09:32:34 +00:00
2011-03-24 02:02:15 +00:00
$ outhash { 0 } = $$ values [ 0 ] ;
2011-03-02 09:32:34 +00:00
#my @t;
#foreach my $value ( @$values ) {
# my ($lparid, $busid, $slot_location_code, $drc_index,@t ) = split (/,/, $value);
# push (@{$outhash{$lparid}}, $value);
#}
if ( $ type =~ /^(fsp|cec)$/ ) {
$ action = "query_octant_cfg" ;
2011-03-04 02:51:55 +00:00
my $ values = xCAT::FSPUtils:: fsp_api_action ( $ cec , \ @ td , $ action ) ;
2011-03-02 09:32:34 +00:00
my $ Rc = shift ( @$ values ) ;
if ( $ Rc != 0 ) {
return ( [ $ Rc , @$ values [ 0 ] ] ) ;
}
2011-03-07 06:18:23 +00:00
#$outhash{ $cec } = @$values[0];
my $ data = @$ values [ 0 ] ;
my @ value = split ( /:/ , $ data ) ;
my $ pendingpumpmode = $ value [ 0 ] ;
my $ currentpumpMode = $ value [ 1 ] ;
my $ octantcount = $ value [ 2 ] ;
my $ j = 3 ;
my $ res = "PendingPumpMode=$pendingpumpmode,CurrentPumpMode=$currentpumpMode,OctantCount=$octantcount:" ;
for ( my $ i = 0 ; $ i < $ octantcount ; $ i + + ) {
$ res = $ res . "OctantID=" . $ value [ $ j + + ] . ",PendingOctCfg=" . $ value [ $ j + + ] . ",CurrentOctCfg=" . $ value [ $ j + + ] . ",PendingMemoryInterleaveMode=" . $ value [ $ j + + ] . ",CurrentMemoryInterleaveMode=" . $ value [ $ j + + ] . ";" ;
}
$ outhash { $ cec } = $ res ;
2011-03-02 09:32:34 +00:00
}
return ( [ 0 , \ % outhash ] ) ;
2010-11-25 02:47:38 +00:00
}
##########################################################################
2011-03-02 09:32:34 +00:00
# Lists logical partitions
2010-11-25 02:47:38 +00:00
##########################################################################
2011-03-02 09:32:34 +00:00
sub list {
2010-11-25 02:47:38 +00:00
my $ request = shift ;
my $ hash = shift ;
2011-03-02 09:32:34 +00:00
my $ args = $ request - > { opt } ;
my $ values = ( ) ;
my @ value = ( ) ;
my $ node_name ;
my $ d ;
my @ result ;
2011-03-24 02:02:15 +00:00
#print Dumper($hash);
2011-03-02 09:32:34 +00:00
while ( my ( $ mtms , $ h ) = each ( %$ hash ) ) {
my $ info = enumerate ( $ h , $ mtms ) ;
my $ Rc = shift ( @$ info ) ;
my $ data = @$ info [ 0 ] ;
2011-03-24 02:02:15 +00:00
my $ values = $ data - > { 0 } ;
2011-03-04 02:51:55 +00:00
2011-03-02 09:32:34 +00:00
while ( ( $ node_name , $ d ) = each ( %$ h ) ) {
my $ cec = @$ d [ 3 ] ;
my $ type = @$ d [ 4 ] ;
my $ id = @$ d [ 0 ] ;
if ( $ Rc != SUCCESS ) {
push @ result , [ $ node_name , $ data , $ Rc ] ;
next ;
}
# if ( !exists( $data->{$id} )) {
# push @result, [$node_name, "Node not found",1];
# next;
# }
# get the I/O slot information
my $ v ;
my @ t ;
my @ value = split ( /\n/ , $ values ) ;
foreach my $ v ( @ value ) {
my ( $ lparid , @ t ) = split ( /,/ , $ v ) ;
if ( $ type =~ /^(fsp|cec)$/ ) {
2011-03-08 06:44:07 +00:00
push @ result , [ $ lparid , join ( '/' , @ t ) , $ Rc ] ;
2011-03-02 09:32:34 +00:00
} else {
2011-03-04 02:51:55 +00:00
if ( $ lparid eq $ id ) {
2011-03-08 06:44:07 +00:00
push @ result , [ $ lparid , join ( '/' , @ t ) , $ Rc ] ;
2010-11-25 02:47:38 +00:00
}
2011-03-02 09:32:34 +00:00
}
2010-11-25 02:47:38 +00:00
}
2011-03-02 09:32:34 +00:00
# get the octant configuration value
if ( $ type =~ /^(fsp|cec)$/ ) {
my $ value = $ data - > { $ cec } ;
push @ result , [ $ node_name , $ value , $ Rc ] ;
}
} # end of while
} # end of while
return ( \ @ result ) ;
2010-11-25 02:47:38 +00:00
}
2011-03-02 09:32:34 +00:00
2010-11-25 02:47:38 +00:00
##########################################################################
# Lists logical partitions
##########################################################################
2011-03-02 09:32:34 +00:00
sub list_orig {
2010-11-25 02:47:38 +00:00
my $ request = shift ;
my $ hash = shift ;
my $ args = $ request - > { opt } ;
my $ values = ( ) ;
my @ value = ( ) ;
my $ node_name ;
my $ d ;
my @ result ;
while ( my ( $ mtms , $ h ) = each ( %$ hash ) ) {
while ( ( $ node_name , $ d ) = each ( %$ h ) ) {
my $ lparid = @$ d [ 0 ] ;
my $ mtms = @$ d [ 2 ] ;
my $ type = @$ d [ 4 ] ;
my $ pprofile ;
####################################
# Must be CEC or LPAR
####################################
2011-03-02 09:32:34 +00:00
if ( $ type !~ /^(lpar|fsp|cec)$/ ) {
2010-11-25 02:47:38 +00:00
#$values->{$lpar} = [$lpar,"Node must be LPAR or CEC",RC_ERROR];
return ( [ $ node_name , "Node must be LPAR or CEC" , RC_ERROR ] ) ;
#next;
}
####################################
# This is a single LPAR
####################################
if ( $ type eq "lpar" ) {
#$lpars[0] = "$lpar,$lparid";
2011-03-02 09:32:34 +00:00
2010-11-25 02:47:38 +00:00
}
####################################
# This is a CEC
####################################
else {
my $ values = xCAT::FSPUtils:: fsp_api_action ( $ node_name , $ d , "query_octant_cfg" ) ;
my $ Rc = @$ values [ 2 ] ;
my $ data = @$ values [ 1 ] ;
if ( $ Rc != SUCCESS ) {
push @ result , [ $ node_name , $ data , $ Rc ] ;
} else {
my @ value = split ( /,/ , $ data ) ;
my $ pendingpumpmode = $ value [ 0 ] ;
my $ currentpumpMode = $ value [ 1 ] ;
my $ octantcount = $ value [ 2 ] ;
my $ j = 3 ;
my $ res = "PendingPumpMode=$pendingpumpmode,CurrentPumpMode=$currentpumpMode,OctantCount=$octantcount:" ;
for ( my $ i = 0 ; $ i < $ octantcount ; $ i + + ) {
$ res = $ res . "OctantID=" . $ value [ $ j + + ] . ",PendingOctCfg=" . $ value [ $ j + + ] . ",CurrentOctCfg=" . $ value [ $ j + + ] . ",PendingMemoryInterleaveMode=" . $ value [ $ j + + ] . ",CurrentMemoryInterleaveMode" . $ value [ $ j + + ] . ";" ;
}
push @ result , [ $ node_name , $ res , $ Rc ] ;
}
}
}
}
return ( \ @ result ) ;
}
##########################################################################
# Creates/changes logical partitions
##########################################################################
sub create {
my $ request = shift ;
my $ hash = shift ;
my $ opt = $ request - > { opt } ;
my @ values = ( ) ;
my @ result ;
2011-03-04 01:55:51 +00:00
my $ cec_name ;
2010-11-25 02:47:38 +00:00
my $ d ;
my $ lparid ;
my $ mtms ;
my $ type ;
my $ profile ;
my $ starting_lpar_id = $ opt - > { i } ;
2011-03-02 09:32:34 +00:00
my $ octant_cfg = $ opt - > { octant_cfg } ;
2011-02-16 10:32:45 +00:00
my $ node_number = @ { $ opt - > { target } } ;
2011-03-04 01:55:51 +00:00
my % node_id = ( ) ;
my @ nodes = @ { $ opt - > { target } } ;
2011-03-08 06:44:07 +00:00
#print Dumper($request);
2010-11-25 02:47:38 +00:00
#####################################
# Get source node information
#####################################
while ( my ( $ cec , $ h ) = each ( %$ hash ) ) {
while ( my ( $ name , $ data ) = each ( %$ h ) ) {
$ d = $ data ;
$ lparid = @$ d [ 0 ] ;
$ mtms = @$ d [ 2 ] ;
$ type = @$ d [ 4 ] ;
2011-03-04 01:55:51 +00:00
$ cec_name = $ name ;
2010-11-25 02:47:38 +00:00
#####################################
# Must be LPAR
#####################################
2011-03-02 09:32:34 +00:00
if ( $ type !~ /^(fsp|cec)$/ ) {
2011-03-04 01:55:51 +00:00
return ( [ [ $ cec_name , "Node's parent must be fsp or CEC" , RC_ERROR ] ] ) ;
2010-11-25 02:47:38 +00:00
}
}
2011-03-04 01:55:51 +00:00
my $ values = xCAT::FSPUtils:: fsp_api_action ( $ cec_name , $ d , "query_octant_cfg" ) ;
2011-03-02 09:32:34 +00:00
my $ Rc = shift ( @$ values ) ;
if ( $ Rc != 0 ) {
2011-03-04 01:55:51 +00:00
return ( [ [ $ cec_name , $$ values [ 0 ] , $ Rc ] ] ) ;
2011-03-02 09:32:34 +00:00
}
my @ v = split ( /:/ , @$ values [ 0 ] ) ;
$ octant_cfg - > { pendingpumpmode } = $ v [ 0 ] ;
2011-03-04 01:55:51 +00:00
my $ number_of_lpars_per_octant ;
my $ octant_num_needed ;
my $ starting_octant_id ;
my $ octant_conf_value ;
my $ octant_cfg_value = $ octant_cfg - > { octant_cfg_value } ;
my $ new_pending_interleave_mode = $ octant_cfg - > { memory_interleave } ;
$ starting_octant_id = int ( $ starting_lpar_id / 4 ) ;
my $ lparnum_from_octant = 0 ;
my $ new_pending_pump_mode = $ octant_cfg - > { pendingpumpmode } ;
my $ parameters ;
#my $parameters = "$new_pending_pump_mode:$octant_num_needed";
my $ octant_id = $ starting_octant_id ;
my $ i = 0 ;
my $ res ;
for ( $ i = 0 ; $ i < ( keys %$ octant_cfg_value ) ; $ i + + ) {
if ( ! exists ( $ octant_cfg_value - > { $ octant_id } ) ) {
2011-03-07 06:18:23 +00:00
$ res = "starting LPAR id is $starting_lpar_id, starting octant id is $starting_octant_id. The octants should be used continuously. Octant $octant_id configuration value isn't provided. Wrong plan." ;
2011-03-04 01:55:51 +00:00
return ( [ [ $ cec_name , $ res , - 1 ] ] ) ;
}
my $ octant_conf_value = $ octant_cfg_value - > { $ octant_id } ;
#octant configuration values could be 1,2,3,4,5 ; AS following:
# 1 - 1 partition with all cpus and memory of the octant
# 2 - 2 partitions with a 50/50 split of cpus and memory
# 3 - 3 partitions with a 25/25/50 split of cpus and memory
# 4 - 4 partitions with a 25/25/25/25 split of cpus and memory
# 5 - 2 partitions with a 25/75 split of cpus and memory
if ( $ octant_conf_value == 1 ) {
$ number_of_lpars_per_octant = 1 ;
} elsif ( $ octant_conf_value == 2 ) {
$ number_of_lpars_per_octant = 2 ;
} elsif ( $ octant_conf_value == 3 ) {
$ number_of_lpars_per_octant = 3 ;
} elsif ( $ octant_conf_value == 4 ) {
$ number_of_lpars_per_octant = 4 ;
} elsif ( $ octant_conf_value == 5 ) {
$ number_of_lpars_per_octant = 2 ;
} else {
$ res = "octant $i, configuration values: $octant_conf_value. Wrong octant configuration values!\n" ;
return ( [ [ $ cec_name , $ res , - 1 ] ] ) ;
}
my $ j ;
for ( $ j = 1 ; $ j < $ number_of_lpars_per_octant + 1 ; $ j + + ) {
if ( @ nodes ) {
my $ node = shift ( @ nodes ) ;
$ node_id { $ node } = $ j + $ octant_id * 4 ;
}
}
$ lparnum_from_octant += $ number_of_lpars_per_octant ;
$ octant_num_needed + + ;
$ parameters . = ":$octant_id:$octant_conf_value:$new_pending_interleave_mode" ;
$ octant_id + + ;
}
$ parameters = "$new_pending_pump_mode:$octant_num_needed" . $ parameters ;
##if($node_number != $lparnum_from_octant ) {##
if ( $ node_number > $ lparnum_from_octant ) {
$ res = "According to the partition split rule and the starting LPAR id, $lparnum_from_octant LPARs will be gotten. But the noderange has $node_number node. Wrong plan.\n" ;
return ( [ [ $ cec_name , $ res , - 1 ] ] ) ;
}
#$values = xCAT::FSPUtils::fsp_api_create_parttion( $starting_lpar_id, $octant_cfg, $node_number, $d, "set_octant_cfg");
$ values = xCAT::FSPUtils:: fsp_api_action ( $ cec_name , $ d , "set_octant_cfg" , 0 , $ parameters ) ;
2010-11-25 02:47:38 +00:00
my $ Rc = @$ values [ 2 ] ;
my $ data = @$ values [ 1 ] ;
if ( $ Rc != SUCCESS ) {
2011-03-04 01:55:51 +00:00
push @ result , [ $ cec_name , $ data , $ Rc ] ;
2010-11-25 02:47:38 +00:00
} else {
foreach my $ name ( @ { $ opt - > { target } } ) {
2011-03-08 06:44:07 +00:00
push @ result , [ $ name , "Success" , $ Rc ] ;
2011-03-04 07:54:01 +00:00
xCAT::FSPvm:: xCATdB ( "mkvm" , $ name , "" , $ node_id { $ name } , $ d , "fsp" , $ name ) ;
2010-11-25 02:47:38 +00:00
}
2011-03-08 06:44:07 +00:00
push @ result , [ $ cec_name , "Please reboot the CEC $cec_name before using chvm to assign the I/O slots to the LPARs" , "mkvm" ] ;
#$request->{callback}->({info => ["Please reboot the CEC $cec_name before using chvm to assign the I/O slots to the LPARs"]});
2010-11-25 02:47:38 +00:00
}
}
return ( \ @ result ) ;
}
##########################################################################
# Adds/removes LPARs from the xCAT database
##########################################################################
sub xCATdB {
my $ cmd = shift ;
my $ name = shift ;
my $ profile = shift ;
my $ lparid = shift ;
my $ d = shift ;
my $ hwtype = shift ;
my $ lpar = shift ;
my $ parent = shift ;
#######################################
# Remove entry
#######################################
if ( $ cmd eq "rmvm" ) {
return ( xCAT::PPCdb:: rm_ppc ( $ name ) ) ;
}
#######################################
# Change entry
#######################################
elsif ( $ cmd eq "chvm" ) {
my $ ppctab = xCAT::Table - > new ( "ppc" , - create = > 1 , - autocommit = > 1 ) ;
###################################
# Error opening ppc database
###################################
if ( ! defined ( $ ppctab ) ) {
return ( "Error opening 'ppc' database" ) ;
}
$ ppctab - > setNodeAttribs ( $ name , { pprofile = > $ profile } ) ;
}
#######################################
# Add entry
#######################################
else {
if ( ! defined ( $ profile ) ) {
$ profile = $ name ;
}
my ( $ model , $ serial ) = split /\*/ , @$ d [ 2 ] ;
my $ server = @$ d [ 3 ] ;
my $ fsp = @$ d [ 2 ] ;
###################################
# Find FSP name in ppc database
###################################
my $ tab = xCAT::Table - > new ( "ppc" ) ;
###################################
# Error opening ppc database
###################################
if ( ! defined ( $ tab ) ) {
return ( "Error opening 'ppc' database" ) ;
}
###################################
# If there is no parent provided
# this lpar should be the cloned
# in the same cec
# Otherwise it should be cloned
# between cecs
###################################
if ( ! $ parent )
{
my ( $ ent ) = $ tab - > getNodeAttribs ( $ lpar , [ 'parent' ] ) ;
###################################
# Node not found
###################################
if ( ! defined ( $ ent ) ) {
return ( "'$lpar' not found in 'ppc' database" ) ;
}
###################################
# Attributes not found
###################################
if ( ! exists ( $ ent - > { parent } ) ) {
return ( "'parent' attribute not found in 'ppc' database" ) ;
}
$ parent = $ ent - > { parent } ;
}
my $ values = join ( "," ,
"lpar" ,
$ name ,
$ lparid ,
$ model ,
$ serial ,
"" ,
$ server ,
$ profile ,
$ parent ) ;
return ( xCAT::PPCdb:: add_ppc ( $ hwtype , [ $ values ] ) ) ;
}
return undef ;
}
##########################################################################
# Creates logical partitions
##########################################################################
sub mkvm {
my $ request = $ _ [ 0 ] ;
my $ opt = $ request - > { opt } ;
# decide if issuing mkvm with the option '-f'.
# if yes, mklpar will be invoked to
# create a full system partition for each CECs managed by the HMC.
if ( exists ( $ opt - > { full } ) ) {
return ( mkfulllpar ( @ _ ) ) ;
}
else {
# if no, it will execute the original function.
return ( create ( @ _ ) ) ;
}
}
##########################################################################
# Change logical partition
##########################################################################
sub chvm {
return ( modify ( @ _ ) ) ;
}
##########################################################################
2011-03-02 09:32:34 +00:00
# No rmvm for P7 IH
2010-11-25 02:47:38 +00:00
##########################################################################
2011-03-02 09:32:34 +00:00
#sub rmvm {
# return( remove(@_) );
#}
2010-11-25 02:47:38 +00:00
##########################################################################
# Lists logical partition profile
##########################################################################
sub lsvm {
return ( list ( @ _ ) ) ;
}
1 ;