mirror of
https://github.com/xcat2/xcat-core.git
synced 2025-05-30 01:26:38 +00:00
2114 lines
70 KiB
Perl
2114 lines
70 KiB
Perl
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
|
|
|
|
package xCAT::PPCvm;
|
|
use strict;
|
|
use Getopt::Long;
|
|
use xCAT::PPCcli qw(SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR);
|
|
use xCAT::PPCdb;
|
|
use xCAT::Usage;
|
|
use xCAT::NodeRange;
|
|
use Data::Dumper;
|
|
use xCAT::MsgUtils qw(verbose_message);
|
|
|
|
##############################################
|
|
# 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) && !defined($request->{stdin})) {
|
|
$request->{method} = $cmd;
|
|
return (usage());
|
|
}
|
|
#############################################
|
|
# Checks case in GetOptions, allows opts
|
|
# to be grouped (e.g. -vx), and terminates
|
|
# at the first unrecognized option.
|
|
#############################################
|
|
if ($args) { @ARGV = @$args; }
|
|
else { @ARGV = (); }
|
|
$Getopt::Long::ignorecase = 0;
|
|
Getopt::Long::Configure("bundling");
|
|
|
|
if (!GetOptions(\%opt, qw(V|verbose p=s))) {
|
|
return (usage());
|
|
}
|
|
####################################
|
|
# Check for "-" with no option
|
|
####################################
|
|
if (grep(/^-$/, @ARGV)) {
|
|
return (usage("Missing option: -"));
|
|
}
|
|
####################################
|
|
# Check for an extra argument
|
|
####################################
|
|
if (defined($ARGV[0])) {
|
|
$opt{a} = [@ARGV];
|
|
for my $attr (@{ $opt{a} })
|
|
{
|
|
if ($attr !~ /(\w+)=(\w*)/)
|
|
{
|
|
return (usage("Invalid argument or attribute: $attr"));
|
|
}
|
|
}
|
|
}
|
|
####################################
|
|
# Configuration file required
|
|
####################################
|
|
if (!exists($opt{p}) and !exists($opt{a})) {
|
|
if (!defined($request->{stdin})) {
|
|
return (usage("Configuration file or attributes not specified"));
|
|
}
|
|
}
|
|
####################################
|
|
# Both configuration file and
|
|
# attributes are specified
|
|
####################################
|
|
if (exists($opt{p}) and exists($opt{a})) {
|
|
return (usage("Flag -p cannot be used together with attribute list"));
|
|
}
|
|
####################################
|
|
# 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());
|
|
}
|
|
####################################
|
|
# Check for "-" with no option
|
|
####################################
|
|
if (grep(/^-$/, @ARGV)) {
|
|
return (usage("Missing option: -"));
|
|
}
|
|
#############################################################
|
|
# Check if only ibacap or ibautocfg specified with the other
|
|
#############################################################
|
|
#if ( exists $opt{ibautocfg} and ! exists $opt{ibacap})
|
|
#{
|
|
# return(usage( "Missing option ibacap when ibautocfg is specified"));
|
|
#}
|
|
#elsif ( exists $opt{ibacap} and !exists $opt{ibautocfg})
|
|
#{
|
|
# return(usage( "Missing option ibautocfg when ibacap is specified"));
|
|
#}
|
|
#if ( $opt{ibacap} ne '1' and $opt{ibacap} ne '2' and $opt{ibacap} ne '3' and $opt{ibacap} ne '4')
|
|
#{
|
|
# return(usage( "IB adapter virtual capability (option --ibacap) can only be number 1,2,3,4. \n\t 1 means 'Low utilization': 6.25% of HCA resources (1/16 of an HCA); \n\t 2 means 'Medium utilization': 12.5% of HCA resources (1/8 of an HCA); \n\t 3 means 'High utilization': 25% of HCA resources (1/4 of an HCA);\n\t 4 means 'Dedicated HCA': 100% of HCA resources (complete HCA).\n"));
|
|
#}
|
|
|
|
####################################
|
|
# 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}"));
|
|
|
|
}
|
|
}
|
|
####################################
|
|
# -i and -l not valid with -c
|
|
####################################
|
|
if (exists($opt{c})) {
|
|
if (exists($opt{i}) or exists($opt{l}) or exists($opt{full})) {
|
|
return (usage());
|
|
}
|
|
####################################
|
|
# -p is required for -c
|
|
####################################
|
|
if (!exists($opt{p})) {
|
|
return (usage());
|
|
}
|
|
}
|
|
####################################
|
|
# -i, -l and -c not valid with -f
|
|
####################################
|
|
elsif (exists($opt{full})) {
|
|
if (exists($opt{c}) or exists($opt{i}) or exists($opt{l})) {
|
|
return (usage());
|
|
}
|
|
}
|
|
####################################
|
|
# If -i and -l, both required
|
|
####################################
|
|
elsif (!exists($opt{l}) or !exists($opt{i})) {
|
|
return (usage());
|
|
}
|
|
####################################
|
|
# Check for an extra argument
|
|
####################################
|
|
if (defined($ARGV[0])) {
|
|
return (usage("Invalid Argument: $ARGV[0]"));
|
|
}
|
|
####################################
|
|
# Expand -l noderange
|
|
####################################
|
|
if (exists($opt{l})) {
|
|
my @noderange = xCAT::NodeRange::noderange($opt{l}, 0);
|
|
if (!@noderange) {
|
|
return (usage("Invalid noderange: '$opt{l}'"));
|
|
}
|
|
@noderange = sort @noderange;
|
|
$opt{lpar} = \@noderange;
|
|
}
|
|
####################################
|
|
# Expand -c noderange
|
|
####################################
|
|
if (exists($opt{c})) {
|
|
my @noderange = xCAT::NodeRange::noderange($opt{c}, 0);
|
|
if (!@noderange) {
|
|
return (usage("Invalid noderange: '$opt{l}'"));
|
|
}
|
|
$opt{cec} = \@noderange;
|
|
}
|
|
#################################################
|
|
# Swap the targets to be processed in PPC.pm
|
|
#################################################
|
|
$opt{target} = [ @{ $request->{node} } ];
|
|
if ($opt{l})
|
|
{
|
|
$request->{node} = [ @{ $opt{lpar} } ];
|
|
$request->{noderange} = $opt{l};
|
|
}
|
|
|
|
if ($opt{c})
|
|
{
|
|
$request->{node} = [ @{ $opt{cec} } ];
|
|
$request->{noderange} = $opt{c};
|
|
}
|
|
#############################################
|
|
# Only 1 node allowed
|
|
#############################################
|
|
if (!exists($opt{full}) && scalar(@{ $request->{node} }) > 1) {
|
|
return (usage("Multiple source specified"));
|
|
}
|
|
|
|
################################################
|
|
# Check if the multiple nodes of the same CEC are specified with -f
|
|
################################################
|
|
|
|
if ((exists($opt{full})) && (scalar(@{ $opt{target} }) > 1)) {
|
|
my $lparparent;
|
|
my $ppctab = xCAT::Table->new('ppc');
|
|
foreach my $vnode (@{ $opt{target} }) {
|
|
my $vcon = $ppctab->getNodeAttribs($vnode, ('node', 'parent'));
|
|
if ($vcon and $vcon->{"node"} and $vcon->{"parent"}) {
|
|
my $lparent = $vcon->{"parent"};
|
|
$lparparent->{$lparent}->{$vnode} = $vnode;
|
|
}
|
|
}
|
|
|
|
$ppctab->close;
|
|
my $cbmsg = "mkvm: multiple LPAR nodes which belong to the same CEC have been defined.\n";
|
|
my $sameflag = 0;
|
|
foreach my $iparent (keys %$lparparent) {
|
|
if (scalar(keys %{ $lparparent->{$iparent} }) > 1) {
|
|
$sameflag = 1;
|
|
$cbmsg = $cbmsg . $iparent . ":" . "\t";
|
|
foreach my $inode (keys %{ $lparparent->{$iparent} }) {
|
|
$cbmsg = $cbmsg . $inode . ",";
|
|
}
|
|
}
|
|
|
|
$cbmsg =~ s/,$/ /;
|
|
$cbmsg = $cbmsg . "\n";
|
|
}
|
|
if ($sameflag) {
|
|
return (usage($cbmsg));
|
|
}
|
|
}
|
|
|
|
####################################
|
|
# Read and check profile
|
|
####################################
|
|
if (exists($opt{p})) {
|
|
$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}"));
|
|
my @cfgdata = ();
|
|
while (<PROFFILE>)
|
|
{
|
|
chomp;
|
|
/\w+/ or next;
|
|
if (/name=/ and /lpar_name/ and /lpar_id/ and /lpar_env/)
|
|
{
|
|
push @cfgdata, $_;
|
|
}
|
|
else
|
|
{
|
|
s/^[^,]*:\s*(name=.*)$/$1/;
|
|
return (usage("Invalid line in profile: $_"));
|
|
}
|
|
}
|
|
return (usage("No valid line was found in profile $opt{p}.")) if (scalar(@cfgdata) < 1);
|
|
|
|
my @lpars = @{ $opt{target} };
|
|
my $min_lpar_num = scalar(@cfgdata);
|
|
if (scalar(@cfgdata) > 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(@cfgdata) < scalar(@lpars))
|
|
{
|
|
my $lparlist = join ",", @lpars[ 0 .. ($min_lpar_num - 1) ];
|
|
xCAT::MsgUtils->message('W', "Warning: Lpar number in command line is greater than lpar configuration number in profile. Only lpars " . $lparlist . " will be created.\n");
|
|
}
|
|
|
|
$opt{profile} = \@cfgdata;
|
|
}
|
|
|
|
####################################
|
|
# 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());
|
|
}
|
|
####################################
|
|
# 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");
|
|
|
|
if (!GetOptions(\%opt, qw(V|verbose a|all))) {
|
|
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);
|
|
}
|
|
|
|
|
|
|
|
##########################################################################
|
|
# Clones all the LPARs from one CEC to another (must be on same HMC)
|
|
##########################################################################
|
|
sub clone {
|
|
my $request = shift;
|
|
my $exp = shift;
|
|
my $targets = shift;
|
|
my $profile = shift;
|
|
my $destd = shift;
|
|
my $destname = shift;
|
|
my $hwtype = @$exp[2];
|
|
my $server = @$exp[3];
|
|
my @values = ();
|
|
my @lpars = @$targets;
|
|
my $destcec;
|
|
my $opt = $request->{opt};
|
|
|
|
#####################################
|
|
# Always one source CEC specified
|
|
#####################################
|
|
my $lparid = @$destd[0];
|
|
my $mtms = @$destd[2];
|
|
my $type = @$destd[4];
|
|
|
|
#####################################
|
|
# Not supported on IVM
|
|
#####################################
|
|
if ($hwtype eq "ivm") {
|
|
return ([ [ RC_ERROR, "Not supported for IVM" ] ]);
|
|
}
|
|
#####################################
|
|
# Source must be CEC
|
|
#####################################
|
|
#if ( $type ne "fsp" ) {
|
|
unless ($type =~ /^(cec|fsp)$/) {
|
|
return ([ [ RC_ERROR, "Node must be an FSP" ] ]);
|
|
}
|
|
#####################################
|
|
# Attributes not found
|
|
#####################################
|
|
if (!$mtms) {
|
|
return ([ [ RC_ERROR, "Cannot found serial and mtm for $destname" ] ]);
|
|
}
|
|
|
|
#####################################
|
|
# Enumerate CECs
|
|
#####################################
|
|
my $filter = "type_model,serial_num";
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} :lssyscfg fsps.filter:'$filter'.");
|
|
my $cecs = xCAT::PPCcli::lssyscfg($exp, "fsps", $filter);
|
|
my $Rc = shift(@$cecs);
|
|
|
|
#####################################
|
|
# Return error
|
|
#####################################
|
|
if ($Rc != SUCCESS) {
|
|
return ([ [ $Rc, @$cecs[0] ] ]);
|
|
}
|
|
|
|
#####################################
|
|
# Get HCA info
|
|
#####################################
|
|
my $unassigned_iba = undef;
|
|
my $iba_replace_pair = undef;
|
|
if (exists $opt->{ibautocfg})
|
|
{
|
|
$unassigned_iba = get_unassigned_iba($exp, $mtms, $opt->{ibacap});
|
|
}
|
|
else
|
|
{
|
|
$unassigned_iba = get_unassigned_iba($exp, $mtms, undef);
|
|
$iba_replace_pair = get_iba_replace_pair($unassigned_iba, $profile);
|
|
}
|
|
|
|
#####################################
|
|
# Find source/dest CEC
|
|
#####################################
|
|
foreach (@$cecs) {
|
|
s/(.*),(.*)/$1*$2/;
|
|
|
|
if ($_ eq $mtms) {
|
|
$destcec = $_;
|
|
}
|
|
}
|
|
#####################################
|
|
# Destination CEC not found
|
|
#####################################
|
|
if (!defined($destcec)) {
|
|
return ([ [ RC_ERROR, "Destination CEC '$destname' not found on '$server'" ] ]);
|
|
}
|
|
#####################################
|
|
# Modify read back profile
|
|
#####################################
|
|
my $min_lpar_num = scalar(@$profile) < scalar(@$targets) ? scalar(@$profile) : scalar(@$targets);
|
|
my $i;
|
|
for ($i = 0 ; $i < $min_lpar_num ; $i++)
|
|
{
|
|
my $cfg = $profile->[$i];
|
|
$cfg =~ s/^[^,]*:\s*(name=.*)$/$1/;
|
|
$cfg =~ s/^name=([^,]+|$)/profile_name=$1/;
|
|
my $profile = $1;
|
|
|
|
$cfg =~ s/\blpar_name=([^,]+|$)/name=$targets->[$i]/;
|
|
|
|
$cfg = strip_profile($cfg, $hwtype);
|
|
$cfg =~ /lpar_id=([^,]+)/;
|
|
$lparid = $1;
|
|
|
|
if (exists $opt->{ibautocfg})
|
|
{
|
|
$cfg = hcaautoconf($cfg, $unassigned_iba);
|
|
}
|
|
else
|
|
{
|
|
$cfg = hcasubst($cfg, $iba_replace_pair);
|
|
}
|
|
#################################
|
|
# Create new LPAR
|
|
#################################
|
|
my @temp = @$destd;
|
|
$temp[0] = $lparid;
|
|
$temp[2] = $destcec;
|
|
$temp[4] = 'lpar';
|
|
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} :mksyscfg lpar.cfg:'$cfg'.");
|
|
my $result = xCAT::PPCcli::mksyscfg($exp, "lpar", \@temp, $cfg);
|
|
$Rc = shift(@$result);
|
|
|
|
#################################
|
|
# Success - add LPAR to database
|
|
#################################
|
|
if ($Rc == SUCCESS) {
|
|
my $err = xCATdB(
|
|
"mkvm", $targets->[$i], $profile, $lparid, $destd, $hwtype, $targets->[$i], $destname);
|
|
|
|
if (defined($err)) {
|
|
push @values, [ $err, RC_ERROR ];
|
|
}
|
|
next;
|
|
}
|
|
#################################
|
|
# Error - Save error
|
|
#################################
|
|
push @values, [ @$result[0], $Rc ];
|
|
}
|
|
if (!scalar(@values)) {
|
|
return ([ [ SUCCESS, "Success" ] ]);
|
|
}
|
|
return (\@values);
|
|
}
|
|
|
|
|
|
##########################################################################
|
|
# Removes logical partitions
|
|
##########################################################################
|
|
sub remove {
|
|
|
|
my $request = shift;
|
|
my $hash = shift;
|
|
my $exp = shift;
|
|
my $opt = $request->{opt};
|
|
my @lpars = ();
|
|
my @values = ();
|
|
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} START.");
|
|
while (my ($mtms, $h) = each(%$hash)) {
|
|
while (my ($lpar, $d) = each(%$h)) {
|
|
my $lparid = @$d[0];
|
|
my $mtms = @$d[2];
|
|
my $type = @$d[4];
|
|
####################################
|
|
# Must be CEC or LPAR
|
|
####################################
|
|
if ($type !~ /^(lpar|fsp|cec)$/) {
|
|
push @values, [ $lpar, "Node must be LPAR or CEC", RC_ERROR ];
|
|
next;
|
|
}
|
|
####################################
|
|
# This is a single LPAR
|
|
####################################
|
|
if ($type eq "lpar") {
|
|
$lpars[0] = "$lpar,$lparid";
|
|
}
|
|
####################################
|
|
# This is a CEC - remove all LPARs
|
|
####################################
|
|
else {
|
|
my $filter = "name,lpar_id";
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} :lssyscfg lpar.filter:'$filter'.");
|
|
my $result = xCAT::PPCcli::lssyscfg(
|
|
$exp,
|
|
"lpar",
|
|
$mtms,
|
|
$filter);
|
|
my $Rc = shift(@$result);
|
|
################################
|
|
# Expect error
|
|
################################
|
|
if ($Rc != SUCCESS) {
|
|
push @values, [ $lpar, @$result[0], $Rc ];
|
|
next;
|
|
}
|
|
################################
|
|
# Success - save LPARs
|
|
################################
|
|
foreach (@$result) {
|
|
push @lpars, $_;
|
|
}
|
|
}
|
|
####################################
|
|
# Remove the LPARs
|
|
####################################
|
|
foreach (@lpars) {
|
|
my $lparinfo = $_; # shift(@lpars);
|
|
my ($name, $id) = split /,/, $lparinfo;
|
|
my $mtms = @$d[2];
|
|
|
|
if ($opt->{service}) {
|
|
###############################################
|
|
# begin to retrieve the CEC's service lpar id
|
|
###############################################
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} :lssyscfg fsp.filter:'service_lpar_id'.");
|
|
my $service_lparid = xCAT::PPCcli::lssyscfg(
|
|
$exp,
|
|
"fsp",
|
|
$mtms,
|
|
"service_lpar_id");
|
|
my $Rc = shift(@$service_lparid);
|
|
|
|
#####################################################
|
|
# Change the CEC's state to standby and set it's service lpar id to none
|
|
#####################################################
|
|
if ($Rc == SUCCESS) {
|
|
my $cfgdata = @$service_lparid[0];
|
|
if (($id == $cfgdata) && ($cfgdata !~ /none/)) {
|
|
$cfgdata = "service_lpar_id=none";
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} :lssyscfg fsp.filter:'$cfgdata'.");
|
|
my $result = xCAT::PPCcli::chsyscfg($exp, "fsp", $d, $cfgdata);
|
|
$Rc = shift(@$result);
|
|
if ($Rc != SUCCESS) {
|
|
return ([ [ $lpar, @$service_lparid[0], $Rc ] ]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
################################
|
|
# id profile mtms hcp type frame
|
|
################################
|
|
my @d = ($id, 0, $mtms, 0, "lpar", 0);
|
|
################################
|
|
# Send remove command
|
|
################################
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} :rmsyscfg lpar.id:$id.");
|
|
my $result = xCAT::PPCcli::rmsyscfg($exp, \@d);
|
|
my $Rc = shift(@$result);
|
|
|
|
################################
|
|
# Remove LPAR from database
|
|
################################
|
|
if ($Rc == SUCCESS and !exists($opt->{r})) {
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} :remove lpar:$name from xCATdb.");
|
|
my $err = xCATdB("rmvm", $name, "", $id, "", $type, "", $lpar);
|
|
if (defined($err)) {
|
|
push @values, [ $lpar, $err, RC_ERROR ];
|
|
next;
|
|
}
|
|
}
|
|
push @values, [ $lpar, @$result[0], $Rc ];
|
|
}
|
|
}
|
|
}
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} END.");
|
|
return (\@values);
|
|
}
|
|
|
|
|
|
##########################################################################
|
|
# Finds the partition profile specified by examining all CECs
|
|
##########################################################################
|
|
sub getprofile {
|
|
|
|
my $exp = shift;
|
|
my $name = shift;
|
|
|
|
###############################
|
|
# Get all CECs
|
|
###############################
|
|
my $cecs = xCAT::PPCcli::lssyscfg($exp, "fsps", "name");
|
|
|
|
###############################
|
|
# Return error
|
|
###############################
|
|
if (@$cecs[0] != NR_ERROR) {
|
|
if (@$cecs[0] != SUCCESS) {
|
|
return ($cecs);
|
|
}
|
|
my $Rc = shift(@$cecs);
|
|
|
|
###########################
|
|
# List profiles for CECs
|
|
###########################
|
|
foreach my $mtms (@$cecs) {
|
|
my $prof = xCAT::PPCcli::lssyscfg(
|
|
$exp,
|
|
"prof",
|
|
$mtms,
|
|
"profile_names=$name");
|
|
|
|
my $Rc = shift(@$prof);
|
|
if ($Rc == SUCCESS) {
|
|
return ([ SUCCESS, $mtms, @$prof[0] ]);
|
|
}
|
|
}
|
|
}
|
|
return ([ RC_ERROR, "The partition profile named '$name' was not found" ]);
|
|
}
|
|
|
|
|
|
##########################################################################
|
|
# Changes the configuration of an existing partition
|
|
##########################################################################
|
|
sub modify {
|
|
my $request = shift;
|
|
my $hash = shift;
|
|
my $exp = shift;
|
|
return modify_by_prof($request, $hash, $exp) if ($request->{opt}->{p});
|
|
return modify_by_attr($request, $hash, $exp);
|
|
}
|
|
|
|
##########################################################################
|
|
# Changes the configuration of an existing
|
|
# partition based on the attributes specified
|
|
##########################################################################
|
|
sub modify_by_attr {
|
|
my $request = shift;
|
|
my $hash = shift;
|
|
my $exp = shift;
|
|
my $hwtype = @$exp[2];
|
|
my $name = @{ $request->{node} }[0];
|
|
my $opt = $request->{opt};
|
|
my $attrstr = $opt->{a};
|
|
my @values;
|
|
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} START.");
|
|
|
|
# attrstr will be in stdin for "cat vmdef | chvm nodename"
|
|
if (!defined($attrstr) && defined($request->{stdin})) {
|
|
my $tempattr = $request->{stdin};
|
|
$tempattr =~ s/\s+$//;
|
|
$tempattr =~ s/^[\w]+: //;
|
|
my $newcfg = strip_profile($tempattr, $hwtype);
|
|
$newcfg =~ s/,*lpar_env=[^,]+|$//;
|
|
$newcfg =~ s/,*all_resources=[^,]+|$//;
|
|
$newcfg =~ s/,*lpar_name=[^,]+|$//;
|
|
$newcfg =~ s/\\\"/\"/g;
|
|
my @cfgarray = split /,/, $newcfg;
|
|
##########################################
|
|
# Repair those lines splitted incorrectly
|
|
##########################################
|
|
my @newcfgarray;
|
|
my $full_line;
|
|
while (my $line = shift(@cfgarray))
|
|
{
|
|
if (!$full_line)
|
|
{
|
|
$full_line = $line;
|
|
}
|
|
else
|
|
{
|
|
$full_line = "$full_line,$line";
|
|
}
|
|
if ($full_line =~ /^[^\"]/ or $full_line =~ /^\".+\"$/)
|
|
{
|
|
$full_line =~ s/^\"(.+)\"$/$1/;
|
|
push @newcfgarray, $full_line;
|
|
$full_line = undef;
|
|
next;
|
|
}
|
|
}
|
|
$attrstr = \@newcfgarray;
|
|
}
|
|
if (defined($attrstr)) {
|
|
###################################
|
|
# Get LPAR active profiles
|
|
###################################
|
|
while (my ($cec, $h) = each(%$hash)) {
|
|
while (my ($lpar, $d) = each(%$h)) {
|
|
###########################
|
|
# Get current profile
|
|
###########################
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} :lssyscfg node.id:'@$d[0]'.");
|
|
my $cfg_res = xCAT::PPCcli::lssyscfg(
|
|
$exp,
|
|
"node",
|
|
$cec,
|
|
'curr_profile',
|
|
@$d[0]);
|
|
my $Rc = shift(@$cfg_res);
|
|
if ($Rc != SUCCESS) {
|
|
push @values, [ $lpar, @$cfg_res[0], $Rc ];
|
|
next;
|
|
}
|
|
##############################################
|
|
# If there is no curr_profile, which means no
|
|
# profile has been applied yet (before first
|
|
# boot?), use the default_profile
|
|
##############################################
|
|
if ((!@$cfg_res[0]) || (@$cfg_res[0] =~ /^none$/))
|
|
{
|
|
$cfg_res = xCAT::PPCcli::lssyscfg(
|
|
$exp,
|
|
"node",
|
|
$cec,
|
|
'default_profile',
|
|
@$d[0]);
|
|
$Rc = shift(@$cfg_res);
|
|
if ($Rc != SUCCESS) {
|
|
push @values, [ $lpar, @$cfg_res[0], $Rc ];
|
|
next;
|
|
}
|
|
}
|
|
|
|
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} :lssyscfg prof.filter:'lpar_ids=@$d[0],profile_names=@$cfg_res[0]'.");
|
|
my $prof = xCAT::PPCcli::lssyscfg(
|
|
$exp,
|
|
"prof",
|
|
$cec,
|
|
"lpar_ids=@$d[0],profile_names=@$cfg_res[0]");
|
|
$Rc = shift(@$prof);
|
|
|
|
if ($Rc != SUCCESS) {
|
|
push @values, [ $lpar, @$prof[0], $Rc ];
|
|
next;
|
|
}
|
|
my $cfgdata = @$prof[0];
|
|
###########################
|
|
# Modify profile
|
|
###########################
|
|
$cfgdata = strip_profile($cfgdata, $hwtype);
|
|
$cfgdata =~ s/,*lpar_env=[^,]+|$//;
|
|
$cfgdata =~ s/,*all_resources=[^,]+|$//;
|
|
$cfgdata =~ s/,*lpar_name=[^,]+|$//;
|
|
my $err_msg;
|
|
($Rc, $err_msg, $cfgdata) = subst_profile($cfgdata, $attrstr);
|
|
if ($Rc != SUCCESS) {
|
|
push @values, [ $lpar, $err_msg, $Rc ];
|
|
next;
|
|
}
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} :chsyscfg prof.cfg:'$cfgdata'.");
|
|
my $result = xCAT::PPCcli::chsyscfg($exp, "prof", $d, $cfgdata);
|
|
$Rc = shift(@$result);
|
|
push @values, [ $lpar, @$result[0], $Rc ];
|
|
}
|
|
}
|
|
}
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} END.");
|
|
return (\@values);
|
|
}
|
|
|
|
##########################################################################
|
|
# Substitue attributes-value pairs in profile
|
|
##########################################################################
|
|
sub subst_profile
|
|
{
|
|
my $cfgdata = shift;
|
|
my $attrlist = shift;
|
|
|
|
$cfgdata =~ s/\\\"/\"/g;
|
|
my @cfgarray = split /,/, $cfgdata;
|
|
##########################################
|
|
# Repair those lines splitted incorrectly
|
|
##########################################
|
|
my @newcfgarray;
|
|
my $full_line;
|
|
while (my $line = shift(@cfgarray))
|
|
{
|
|
if (!$full_line)
|
|
{
|
|
$full_line = $line;
|
|
}
|
|
else
|
|
{
|
|
$full_line = "$full_line,$line";
|
|
}
|
|
if ($full_line =~ /^[^\"]/ or $full_line =~ /^\".+\"$/)
|
|
{
|
|
$full_line =~ s/^\"(.+)\"$/$1/;
|
|
push @newcfgarray, $full_line;
|
|
$full_line = undef;
|
|
next;
|
|
}
|
|
}
|
|
|
|
##########################################
|
|
# Substitute attributes in new array
|
|
##########################################
|
|
my @final_array;
|
|
my @attrs = @$attrlist;
|
|
for my $cfgline (@newcfgarray)
|
|
{
|
|
for (my $i = 0 ; $i < scalar(@attrs) ; $i++)
|
|
{
|
|
my $av_pair = $attrs[$i];
|
|
next if (!$av_pair);
|
|
|
|
#assuming there will not be too many attributes to be changed
|
|
my ($attr, $value) = $av_pair =~ /^\s*(\S+?)\s*=\s*(\S+)\s*$/;
|
|
if ($cfgline =~ /^$attr=/)
|
|
{
|
|
if ($cfgline =~ /lhea_logical_ports/)
|
|
{
|
|
$cfgline = "$attr=\\\"\\\"$value\\\"\\\"";
|
|
} else
|
|
{
|
|
$cfgline = "$attr=$value";
|
|
}
|
|
|
|
delete $attrs[$i];
|
|
last;
|
|
}
|
|
|
|
}
|
|
if ($cfgline =~ /,/)
|
|
{
|
|
$cfgline = "\\\"$cfgline\\\"";
|
|
}
|
|
push @final_array, $cfgline;
|
|
}
|
|
$cfgdata = join ',', @final_array;
|
|
|
|
##########################################
|
|
# Get not found attribute list
|
|
##########################################
|
|
my %not_found = ();
|
|
for (@attrs)
|
|
{
|
|
if ($_)
|
|
{
|
|
my ($a) = split /=/;
|
|
$not_found{$a} = 1;
|
|
}
|
|
}
|
|
my $Rc = scalar(keys %not_found);
|
|
my $incorrect_attrs = join ',', (keys %not_found);
|
|
return ($Rc, "Incorrect attribute(s) $incorrect_attrs", $cfgdata);
|
|
}
|
|
|
|
##########################################################################
|
|
# Changes the configuration of an existing
|
|
# partition based on the profile specified
|
|
##########################################################################
|
|
sub modify_by_prof {
|
|
my $request = shift;
|
|
my $hash = shift;
|
|
my $exp = shift;
|
|
my $hwtype = @$exp[2];
|
|
my $name = @{ $request->{node} }[0];
|
|
my $opt = $request->{opt};
|
|
my $cfgdata = $request->{stdin};
|
|
my $profile = $opt->{p};
|
|
my @values;
|
|
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} START.");
|
|
#######################################
|
|
# -p flag, find profile specified
|
|
#######################################
|
|
if (defined($profile)) {
|
|
my $prof = getprofile($exp, $profile);
|
|
|
|
###################################
|
|
# Return error
|
|
###################################
|
|
my $Rc = shift(@$prof);
|
|
if ($Rc != SUCCESS) {
|
|
return ([ [ $name, @$prof, RC_ERROR ] ]);
|
|
}
|
|
$cfgdata = @$prof[1];
|
|
my $mtms = @$prof[0];
|
|
|
|
###################################
|
|
# Check if LPAR profile exists
|
|
###################################
|
|
while (my ($cec, $h) = each(%$hash)) {
|
|
while (my ($lpar, $d) = each(%$h)) {
|
|
|
|
###########################
|
|
# Get LPAR profiles
|
|
###########################
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} :lssyscfg prof.filter:'lpar_ids=@$d[0],profile_names=$profile'.");
|
|
my $prof = xCAT::PPCcli::lssyscfg(
|
|
$exp,
|
|
"prof",
|
|
$cec,
|
|
"lpar_ids=@$d[0],profile_names=$profile");
|
|
my $Rc = shift(@$prof);
|
|
|
|
###########################
|
|
# Already has that profile
|
|
###########################
|
|
if ($Rc == SUCCESS) {
|
|
push @values, [ $lpar, "Success", $Rc ];
|
|
xCATdB("chvm", $lpar, $profile);
|
|
delete $h->{$lpar};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#######################################
|
|
# Remove "node: " in case the
|
|
# configuration file was created as
|
|
# the result of an "lsvm" command.
|
|
# "lpar9: name=lpar9, lpar_name=..."
|
|
#######################################
|
|
$cfgdata =~ s/^[\w]+: //;
|
|
if ($cfgdata !~ /^name=/) {
|
|
my $text = "Invalid file format: must begin with 'name='";
|
|
return ([ [ $name, $text, RC_ERROR ] ]);
|
|
}
|
|
my $cfg = strip_profile($cfgdata, $hwtype);
|
|
$cfg =~ s/,*lpar_env=[^,]+|$//;
|
|
$cfg =~ s/,*all_resources=[^,]+|$//;
|
|
$cfg =~ s/,*lpar_name=[^,]+|$//;
|
|
|
|
#######################################
|
|
# Send change profile command
|
|
#######################################
|
|
while (my ($cec, $h) = each(%$hash)) {
|
|
while (my ($lpar, $d) = each(%$h)) {
|
|
|
|
###############################
|
|
# Only valid for LPARs
|
|
###############################
|
|
if (@$d[4] ne "lpar") {
|
|
push @values, [ $lpar, "Command not supported on '@$d[4]'", RC_ERROR ];
|
|
next;
|
|
}
|
|
###############################
|
|
# Change LPAR Id
|
|
###############################
|
|
$cfg =~ s/lpar_id=[^,]+/lpar_id=@$d[0]/;
|
|
|
|
#################################
|
|
# Modify SCSI/LHEA adapters
|
|
#################################
|
|
if (exists($opt->{p})) {
|
|
if ($cfg =~ /virtual_scsi_adapters=(\w+)/) {
|
|
if ($1 !~ /^none$/i) {
|
|
$cfg = scsi_adapter($cfg);
|
|
}
|
|
}
|
|
if ($cfg =~ /lhea_logical_ports=(\w+)/) {
|
|
if ($1 !~ /^none$/i) {
|
|
$cfg = lhea_adapter($cfg);
|
|
}
|
|
}
|
|
}
|
|
###############################
|
|
# Send command
|
|
###############################
|
|
if (defined($profile)) {
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} :mksyscfg prof.cfg:'$cfg'.");
|
|
my $result = xCAT::PPCcli::mksyscfg($exp, "prof", $d, $cfg);
|
|
my $Rc = shift(@$result);
|
|
|
|
############################
|
|
# Update database
|
|
############################
|
|
if ($Rc == SUCCESS) {
|
|
xCATdB("chvm", $lpar, $profile);
|
|
}
|
|
push @values, [ $lpar, @$result[0], $Rc ];
|
|
}
|
|
else {
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} :chsyscfg prof.cfg:'$cfg'.");
|
|
my $result = xCAT::PPCcli::chsyscfg($exp, "prof", $d, $cfg);
|
|
my $Rc = shift(@$result);
|
|
push @values, [ $lpar, @$result[0], $Rc ];
|
|
}
|
|
}
|
|
}
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} END.");
|
|
return (\@values);
|
|
}
|
|
|
|
|
|
##########################################################################
|
|
# Lists logical partitions
|
|
##########################################################################
|
|
sub list {
|
|
|
|
my $request = shift;
|
|
my $hash = shift;
|
|
my $exp = shift;
|
|
my $args = $request->{opt};
|
|
my $values = ();
|
|
my @value = ();
|
|
my @lpars = ();
|
|
my $result;
|
|
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} START.");
|
|
while (my ($mtms, $h) = each(%$hash)) {
|
|
while (my ($lpar, $d) = each(%$h)) {
|
|
my $lparid = @$d[0];
|
|
my $mtms = @$d[2];
|
|
my $type = @$d[4];
|
|
my $pprofile;
|
|
|
|
####################################
|
|
# Must be CEC or LPAR
|
|
####################################
|
|
if ($type !~ /^(lpar|fsp|cec)$/) {
|
|
$values->{$lpar} = [ $lpar, "Node must be LPAR or CEC", RC_ERROR ];
|
|
next;
|
|
}
|
|
####################################
|
|
# This is a single LPAR
|
|
####################################
|
|
if ($type eq "lpar") {
|
|
$lpars[0] = "$lpar,$lparid";
|
|
}
|
|
####################################
|
|
# This is a CEC
|
|
####################################
|
|
else {
|
|
my $filter = "name,lpar_id";
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} :lssyscfg lpar.filter:'$filter'.");
|
|
my $result = xCAT::PPCcli::lssyscfg(
|
|
$exp,
|
|
"lpar",
|
|
$mtms,
|
|
$filter);
|
|
my $Rc = shift(@$result);
|
|
|
|
################################
|
|
# Expect error
|
|
################################
|
|
if ($Rc != SUCCESS) {
|
|
$values->{$lpar} = [ $lpar, @$result[0], $Rc ];
|
|
next;
|
|
}
|
|
################################
|
|
# Success - save LPARs
|
|
################################
|
|
foreach (@$result) {
|
|
push @lpars, $_;
|
|
}
|
|
}
|
|
####################################
|
|
# Get LPAR profile
|
|
####################################
|
|
foreach (sort @lpars) {
|
|
my ($name, $id) = split /,/;
|
|
|
|
#################################
|
|
# Get source LPAR profile
|
|
#################################
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} :lssyscfg prof.filter:'lpar_ids=$id'.");
|
|
my $prof = xCAT::PPCcli::lssyscfg(
|
|
$exp,
|
|
"prof",
|
|
$mtms,
|
|
"lpar_ids=$id");
|
|
my $Rc = shift(@$prof);
|
|
|
|
#################################
|
|
# Return error
|
|
#################################
|
|
if ($Rc != SUCCESS) {
|
|
$values->{$lpar} = [ $lpar, @$prof[0], $Rc ];
|
|
next;
|
|
}
|
|
#################################
|
|
# List the default LPAR profile,
|
|
# or all the profiles if option
|
|
# -a|--all is assigned
|
|
#################################
|
|
if (exists($args->{a})) {
|
|
my $count = 0;
|
|
foreach (@$prof) {
|
|
$pprofile .= "@$prof[$count]\n\n";
|
|
$count++;
|
|
}
|
|
} else {
|
|
|
|
#$pprofile .= "@$prof[0]\n\n";
|
|
my $lparprof = xCAT::PPCcli::lssyscfg(
|
|
$exp,
|
|
"lpar2",
|
|
$mtms,
|
|
"lpar_ids=$id");
|
|
my $Rc = shift(@$lparprof);
|
|
if ($Rc != SUCCESS) {
|
|
$pprofile .= "@$lparprof[0]\n\n";
|
|
} else {
|
|
@$lparprof[0] =~ /curr_profile=(\w+)/;
|
|
my $pname = $1;
|
|
foreach my $pr (@$prof) {
|
|
if ($pr =~ /name=$pname/) {
|
|
$pprofile .= "$pr\n\n";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
$values->{$lpar} = [ $lpar, $pprofile, SUCCESS ];
|
|
}
|
|
}
|
|
|
|
foreach (sort keys %$values) {
|
|
push @value, $values->{$_};
|
|
}
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} END.");
|
|
return (\@value);
|
|
}
|
|
##########################################################################
|
|
# Increments hca adapter in partition profile
|
|
##########################################################################
|
|
sub hca_adapter {
|
|
|
|
my $cfgdata = shift;
|
|
|
|
#########################################
|
|
# Increment HCA adapters if present
|
|
# "23001eff/2550010250300/2,23001eff/2550010250400/2"
|
|
# Increment the last 2 number of 2550010250300 and
|
|
# 2550010250400 in example above.
|
|
#########################################
|
|
if ($cfgdata =~ /(\"*hca_adapters)/) {
|
|
|
|
#####################################
|
|
# If double-quoted, has comma-
|
|
# seperated list of adapters
|
|
#####################################
|
|
my $delim = ($1 =~ /^\"/) ? "\\\\\"" : ",";
|
|
$cfgdata =~ /hca_adapters=([^$delim]+)|$/;
|
|
my @hcas = split ",", $1;
|
|
my $adapters = "hca_adapters=";
|
|
for my $hca (@hcas)
|
|
{
|
|
my @hcainfo = split /\//, $hca;
|
|
######################################################
|
|
# split it to 2 part, only increase the last 2 number
|
|
# otherwise it can overflow if change it to dec
|
|
######################################################
|
|
my $portlen = length($hcainfo[1]);
|
|
my $portprefix = substr($hcainfo[1], 0, $portlen - 2);
|
|
my $portpostfix = substr($hcainfo[1], $portlen - 2);
|
|
my $portnum = hex $portpostfix;
|
|
$portnum++;
|
|
$portpostfix = sprintf '%x', $portnum;
|
|
if (length($portpostfix) == 1)
|
|
{
|
|
$portpostfix = '0' . $portpostfix;
|
|
}
|
|
$hcainfo[1] = $portprefix . $portpostfix;
|
|
|
|
$adapters = $adapters . join("/", @hcainfo) . ',';
|
|
}
|
|
$adapters =~ s/^(.*),$/$1/;
|
|
$cfgdata =~ s/hca_adapters=[^$delim]+/$adapters/;
|
|
}
|
|
return ($cfgdata);
|
|
}
|
|
##########################################################################
|
|
# Get unassigned hca guid
|
|
##########################################################################
|
|
sub get_unassigned_iba
|
|
{
|
|
my $exp = shift;
|
|
my $mtms = shift;
|
|
my $ibacap = shift;
|
|
my $max_ib_num = 0;
|
|
if (!$ibacap)
|
|
{
|
|
$ibacap = '1';
|
|
}
|
|
if ($ibacap eq '1')
|
|
{
|
|
$max_ib_num = 16;
|
|
}
|
|
elsif ($ibacap eq '2')
|
|
{
|
|
$max_ib_num = 8;
|
|
}
|
|
elsif ($ibacap eq '3')
|
|
{
|
|
$max_ib_num = 4;
|
|
}
|
|
elsif ($ibacap eq '4')
|
|
{
|
|
$max_ib_num = 1;
|
|
}
|
|
else
|
|
{
|
|
return undef;
|
|
}
|
|
|
|
my $hwres = xCAT::PPCcli::lshwres($exp, [ 'sys', 'hca', 'adapter_id:phys_loc:unassigned_guids' ], $mtms);
|
|
my $Rc = shift(@$hwres);
|
|
if ($Rc == SUCCESS)
|
|
{
|
|
my @unassigned_ibas;
|
|
my $ib_hash = {};
|
|
for my $hca_info (@$hwres)
|
|
{
|
|
chomp $hca_info;
|
|
if ($hca_info =~ /^(.+):(.+):(.+)$/)
|
|
{
|
|
my $adapter_id = $1;
|
|
my $phys_loc = $2;
|
|
my $unassigned_guids = $3;
|
|
if ($phys_loc =~ /C65$/ or $phys_loc =~ /C66$/ or $phys_loc =~ /C7$/)
|
|
{
|
|
my @guids = split /,/, $unassigned_guids;
|
|
$max_ib_num = scalar(@guids) if (scalar(@guids) < $max_ib_num);
|
|
for (my $i = 0 ; $i < $max_ib_num ; $i++)
|
|
{
|
|
my $guid = @guids[$i];
|
|
$guid =~ s/\s*(\S+)\s*/$1/;
|
|
unshift @{ $ib_hash->{$phys_loc}->{$adapter_id} }, "$adapter_id/$guid/$ibacap";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for my $loc (sort keys %$ib_hash)
|
|
{
|
|
my $min_guid_num = -1;
|
|
for my $id (keys %{ $ib_hash->{$loc} })
|
|
{
|
|
if ($min_guid_num == -1 or $min_guid_num > scalar(@{ $ib_hash->{$loc}->{$id} }))
|
|
{
|
|
$min_guid_num = scalar(@{ $ib_hash->{$loc}->{$id} });
|
|
}
|
|
}
|
|
for (my $i = 0 ; $i < $min_guid_num ; $i++)
|
|
{
|
|
my $unassigned_iba = undef;
|
|
for my $adp_id (sort keys %{ $ib_hash->{$loc} })
|
|
{
|
|
my $iba = $ib_hash->{$loc}->{$adp_id}->[$i];
|
|
$unassigned_iba .= ",$iba";
|
|
}
|
|
if ($unassigned_iba)
|
|
{
|
|
$unassigned_iba =~ s/^,//;
|
|
push @unassigned_ibas, $unassigned_iba;
|
|
}
|
|
}
|
|
}
|
|
return \@unassigned_ibas;
|
|
}
|
|
else
|
|
{
|
|
return undef;
|
|
}
|
|
}
|
|
|
|
##########################################################################
|
|
# get iba replacement pair (from source profile to target)
|
|
##########################################################################
|
|
sub get_iba_replace_pair
|
|
{
|
|
my $unassigned_iba = shift;
|
|
my $profile = shift;
|
|
|
|
#############################
|
|
# Get hca info from profile
|
|
#############################
|
|
my @oldhca_prefixes;
|
|
for my $cfg (@$profile)
|
|
{
|
|
if ($cfg =~ /(\"*hca_adapters)/)
|
|
{
|
|
my $delim = ($1 =~ /^\"/) ? "\\\\\"" : ",";
|
|
$cfg =~ /hca_adapters=([^$delim]+)|$/;
|
|
my $oldhca = $1;
|
|
my @oldhcas = split /,/, $oldhca;
|
|
for my $oldhca_entry (@oldhcas)
|
|
{
|
|
if ($oldhca_entry =~ /(.+\/.+)..\/\d+/)
|
|
{
|
|
my $oldhca_prefix = $1;
|
|
if (!grep /\Q$oldhca_prefix\E/, @oldhca_prefixes)
|
|
{
|
|
push @oldhca_prefixes, $oldhca_prefix;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
###########################################
|
|
# Get hca info from unasigned hca array
|
|
###########################################
|
|
my @newhca_prefixes;
|
|
for my $newhca (@$unassigned_iba)
|
|
{
|
|
my @newhcas = split /,/, $newhca;
|
|
for my $newhca_entry (@newhcas)
|
|
{
|
|
if ($newhca_entry =~ /(.+\/.+)..\/\d+/)
|
|
{
|
|
my $newhca_prefix = $1;
|
|
if (!grep /\Q$newhca_prefix\E/, @newhca_prefixes)
|
|
{
|
|
push @newhca_prefixes, $newhca_prefix;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#############################
|
|
# Create replacement pair
|
|
#############################
|
|
my %pair_hash;
|
|
for (my $i = 0 ; $i < scalar @oldhca_prefixes ; $i++)
|
|
{
|
|
$pair_hash{ @oldhca_prefixes[$i] } = @newhca_prefixes[$i];
|
|
}
|
|
|
|
return \%pair_hash;
|
|
}
|
|
##########################################################################
|
|
# Substitue hca info
|
|
##########################################################################
|
|
sub hcasubst
|
|
{
|
|
my $cfgdata = shift;
|
|
my $replace_hash = shift;
|
|
if ($cfgdata =~ /(\"*hca_adapters)/) {
|
|
for my $oldhca_prefix (keys %$replace_hash)
|
|
{
|
|
$cfgdata =~ s/\Q$oldhca_prefix\E/$replace_hash->{$oldhca_prefix}/g;
|
|
}
|
|
}
|
|
return $cfgdata;
|
|
}
|
|
##########################################################################
|
|
# Automatically configure HCA adapters
|
|
##########################################################################
|
|
sub hcaautoconf
|
|
{
|
|
my $cfgdata = shift;
|
|
my $unassignedhca = shift;
|
|
$unassignedhca = [] if (!$unassignedhca);
|
|
|
|
if ($cfgdata =~ /(\"*hca_adapters)/) {
|
|
|
|
#####################################
|
|
# If double-quoted, has comma-
|
|
# seperated list of adapters
|
|
#####################################
|
|
my $delim = ($1 =~ /^\"/) ? "\\\\\"" : ",";
|
|
$cfgdata =~ /hca_adapters=([^$delim]+)|$/;
|
|
my $oldhca = $1;
|
|
my $newhca;
|
|
$newhca = shift @$unassignedhca;
|
|
|
|
my $adapters = undef;
|
|
if ($newhca)
|
|
{
|
|
$adapters = "hca_adapters=$newhca";
|
|
}
|
|
else
|
|
{
|
|
$adapters = "hca_adapters=none";
|
|
}
|
|
if ($adapters =~ /,/ and $delim ne "\\\\\"")
|
|
{
|
|
$adapters = "\\\\\"" . $adapters . "\\\\\"";
|
|
}
|
|
$cfgdata =~ s/hca_adapters=[^$delim]+/$adapters/;
|
|
}
|
|
return $cfgdata;
|
|
}
|
|
|
|
##########################################################################
|
|
# Increments virtual lhea adapter in partition profile
|
|
##########################################################################
|
|
sub lhea_adapter {
|
|
|
|
my $cfgdata = shift;
|
|
|
|
#########################################
|
|
# Increment LHEA adapters if present
|
|
# 23000000/2/1/7/none,23000008/2/1/4/none
|
|
# Increment 7 and 4 in example above.
|
|
#########################################
|
|
if ($cfgdata =~ /(\"*lhea_logical_ports)/) {
|
|
|
|
#####################################
|
|
# If double-quoted, has comma-
|
|
# seperated list of adapters
|
|
#####################################
|
|
#my $delim = ( $1 =~ /^\"/ ) ? "\\\\\"" : ",";
|
|
#$cfgdata =~ /lhea_logical_ports=([^$delim]+)|$/;
|
|
$cfgdata =~ /lhea_logical_ports=(.*)lhea_capabilities/;
|
|
my @lhea = split ",", $1;
|
|
foreach (@lhea)
|
|
{
|
|
if (/(\d+)\/(\d+)\/(\d+)\/(\d+)/)
|
|
{
|
|
my $id = $4;
|
|
if ($id =~ /\d+/)
|
|
{
|
|
$id = $id + 1;
|
|
}
|
|
s/(\d+)\/(\d+)\/(\d+)\/(\d+)/$1\/$2\/$3\/$id/;
|
|
}
|
|
}
|
|
my $adapters = "lhea_logical_ports=" . join(",", @lhea);
|
|
|
|
#$cfgdata =~ s/lhea_logical_ports=[^$delim]+/$adapters/;
|
|
$cfgdata =~ s/lhea_logical_ports=(.*)lhea_capabilities/$adapters,lhea_capabilities/;
|
|
}
|
|
return ($cfgdata);
|
|
}
|
|
|
|
|
|
##########################################################################
|
|
# Increments virtual scsi adapter in partition profile
|
|
##########################################################################
|
|
sub scsi_adapter {
|
|
|
|
my $cfgdata = shift;
|
|
|
|
#########################################
|
|
# Increment SCSI adapters if present
|
|
# 15/server/6/1ae0-node1/11/1,
|
|
# 14/server/5/1ae0-ms04/12/1,
|
|
# 20/server/any//any/1
|
|
# Increment 11 and 12 in example above.
|
|
#########################################
|
|
if ($cfgdata =~ /(\"*virtual_scsi_adapters)/) {
|
|
|
|
#####################################
|
|
# If double-quoted, has comma-
|
|
# seperated list of adapters
|
|
#####################################
|
|
my $delim = ($1 =~ /^\"/) ? "\\\\\"" : ",";
|
|
$cfgdata =~ /virtual_scsi_adapters=([^$delim]+)|$/;
|
|
|
|
my @scsi = split ",", $1;
|
|
foreach (@scsi) {
|
|
if (/(\w+)\/(\w+)$/) {
|
|
my $id = ($1 =~ /(\d+)/) ? $1 + 1 : $1;
|
|
s/(\w+)\/(\w+)$/$id\/$2/;
|
|
}
|
|
}
|
|
my $adapters = "virtual_scsi_adapters=" . join(",", @scsi);
|
|
$cfgdata =~ s/virtual_scsi_adapters=[^$delim]+/$adapters/;
|
|
}
|
|
return ($cfgdata);
|
|
}
|
|
|
|
|
|
##########################################################################
|
|
# Creates/changes logical partitions
|
|
##########################################################################
|
|
sub create {
|
|
|
|
my $request = shift;
|
|
my $hash = shift;
|
|
my $exp = shift;
|
|
my $hwtype = @$exp[2];
|
|
my $opt = $request->{opt};
|
|
my @values = ();
|
|
my $result;
|
|
my $lpar;
|
|
my $d;
|
|
my $lparid;
|
|
my $mtms;
|
|
my $type;
|
|
my $profile;
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} START.");
|
|
#####################################
|
|
# 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];
|
|
$lpar = $name;
|
|
}
|
|
}
|
|
#####################################
|
|
# Must be CEC or LPAR
|
|
#####################################
|
|
if ($type !~ /^(lpar|fsp|cec)$/) {
|
|
return ([ [ $lpar, "Node must be LPAR or CEC", RC_ERROR ] ]);
|
|
}
|
|
#####################################
|
|
# Clone all the LPARs on CEC
|
|
#####################################
|
|
if (exists($opt->{c})) {
|
|
my $result = clone($request,
|
|
$exp,
|
|
$opt->{target},
|
|
$opt->{profile},
|
|
$d,
|
|
$request->{node}->[0]
|
|
);
|
|
foreach (@$result) {
|
|
my $Rc = shift(@$_);
|
|
push @values, [ $opt->{c}, @$_[0], $Rc ];
|
|
}
|
|
return (\@values);
|
|
}
|
|
#####################################
|
|
# Get source LPAR profile
|
|
#####################################
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} :lssyscfg prof.filter:'lpar_ids=$lparid'.");
|
|
my $prof = xCAT::PPCcli::lssyscfg(
|
|
$exp,
|
|
"prof",
|
|
$mtms,
|
|
"lpar_ids=$lparid");
|
|
my $Rc = shift(@$prof);
|
|
|
|
#####################################
|
|
# Return error
|
|
#####################################
|
|
if ($Rc != SUCCESS) {
|
|
return ([ [ $lpar, @$prof[0], $Rc ] ]);
|
|
}
|
|
#####################################
|
|
# Get source node pprofile attribute
|
|
#####################################
|
|
my $pprofile = @$d[1];
|
|
|
|
#####################################
|
|
# Find pprofile on source node
|
|
#####################################
|
|
my ($prof) = grep /^name=$pprofile\,/, @$prof;
|
|
if (!$prof) {
|
|
return ([ [ $lpar, "'pprofile=$pprofile' not found on '$lpar'", RC_ERROR ] ]);
|
|
}
|
|
#####################################
|
|
# Get command-line options
|
|
#####################################
|
|
my $id = $opt->{i};
|
|
my $cfgdata = strip_profile($prof, $hwtype);
|
|
|
|
#####################################
|
|
# Set profile name for all LPARs
|
|
#####################################
|
|
if ($hwtype eq "hmc") {
|
|
$cfgdata =~ s/^name=([^,]+|$)/profile_name=$1/;
|
|
$profile = $1;
|
|
$cfgdata =~ s/lpar_name=/name=/;
|
|
}
|
|
|
|
foreach my $name (@{ $opt->{target} }) {
|
|
|
|
#################################
|
|
# Modify read-back profile.
|
|
# See HMC or IVM mksyscfg man
|
|
# page for valid attributes.
|
|
#
|
|
#################################
|
|
$cfgdata =~ s/\blpar_id=[^,]+|$/lpar_id=$id/;
|
|
$cfgdata =~ s/\bname=[^,]+|$/name=$name/;
|
|
|
|
#################################
|
|
# Modify LHEA adapters
|
|
#################################
|
|
if ($cfgdata =~ /lhea_logical_ports=(\w+)/) {
|
|
if ($1 !~ /^none$/i) {
|
|
$cfgdata = lhea_adapter($cfgdata);
|
|
}
|
|
}
|
|
#################################
|
|
# Modify HCA adapters
|
|
#################################
|
|
if ($cfgdata =~ /hca_adapters=(\w+)/) {
|
|
if ($1 !~ /^none$/i) {
|
|
$cfgdata = hca_adapter($cfgdata);
|
|
}
|
|
}
|
|
#################################
|
|
# Modify SCSI adapters
|
|
#################################
|
|
if ($cfgdata =~ /virtual_scsi_adapters=(\w+)/) {
|
|
if ($1 !~ /^none$/i) {
|
|
$cfgdata = scsi_adapter($cfgdata);
|
|
}
|
|
}
|
|
#################################
|
|
# Create new LPAR
|
|
#################################
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} :mksyscfg lpar.cfg:'$cfgdata'.");
|
|
$result = xCAT::PPCcli::mksyscfg($exp, "lpar", $d, $cfgdata);
|
|
$Rc = shift(@$result);
|
|
|
|
#################################
|
|
# Add new LPAR to database
|
|
#################################
|
|
if ($Rc == SUCCESS) {
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} :add lpar:$name from xCATdb.");
|
|
my $err = xCATdB("mkvm", $name, $profile, $id, $d, $hwtype, $lpar);
|
|
if (defined($err)) {
|
|
push @values, [ $name, $err, RC_ERROR ];
|
|
$id++;
|
|
next;
|
|
}
|
|
}
|
|
push @values, [ $name, @$result[0], $Rc ];
|
|
$id++;
|
|
}
|
|
xCAT::MsgUtils->verbose_message($request, "$request->{command} END.");
|
|
return (\@values);
|
|
}
|
|
|
|
|
|
##########################################################################
|
|
# Strips attributes from profile not valid for creation
|
|
##########################################################################
|
|
sub strip_profile {
|
|
|
|
my $cfgdata = shift;
|
|
my $hwtype = shift;
|
|
|
|
#####################################
|
|
# Modify read-back profile. See
|
|
# HMC mksyscfg man page for valid
|
|
# attributes.
|
|
#####################################
|
|
if ($hwtype eq "hmc") {
|
|
$cfgdata =~ s/,*\"virtual_serial_adapters=[^\"]+\"//;
|
|
$cfgdata =~ s/,*electronic_err_reporting=[^,]+|$//;
|
|
$cfgdata =~ s/,*shared_proc_pool_id=[^,]+|$//;
|
|
$cfgdata =~ s/,*lpar_proc_compat_mode=[^,]+|$//;
|
|
$cfgdata =~ s/\"/\\"/g;
|
|
$cfgdata =~ s/\n//g;
|
|
return ($cfgdata);
|
|
}
|
|
#####################################
|
|
# Modify read-back profile. See
|
|
# IVM mksyscfg man page for valid
|
|
# attributes.
|
|
#####################################
|
|
$cfgdata =~ s/,*lpar_name=[^,]+|$//;
|
|
$cfgdata =~ s/os_type=/lpar_env=/;
|
|
$cfgdata =~ s/,*all_resources=[^,]+|$//;
|
|
$cfgdata =~ s/,*\"virtual_serial_adapters=[^\"]+\"//;
|
|
$cfgdata =~ s/,*lpar_io_pool_ids=[^,]+|$//;
|
|
$cfgdata =~ s/,*conn_monitoring=[^,]+|$//;
|
|
$cfgdata =~ s/,*power_ctrl_lpar_ids=[^,]+|$//;
|
|
$cfgdata =~ s/\"/\\"/g;
|
|
return ($cfgdata);
|
|
}
|
|
|
|
|
|
##########################################################################
|
|
# 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") {
|
|
|
|
my $ppctab = xCAT::Table->new('ppc');
|
|
unless ($ppctab) { # no ppc table
|
|
return ("Error opening 'ppc' database");
|
|
}
|
|
|
|
my @nodes = $ppctab->getAllNodeAttribs([ 'node', 'id', 'parent' ]);
|
|
|
|
foreach my $node (@nodes) {
|
|
my $type = xCAT::DBobjUtils->getnodetype($node->{node});
|
|
if ($type =~ /lpar/ and $lparid eq $node->{id} and $parent eq $node->{parent}) {
|
|
return (xCAT::PPCdb::rm_ppc($node->{node}));
|
|
}
|
|
}
|
|
}
|
|
#######################################
|
|
# 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], '', '', "PPC"));
|
|
}
|
|
return undef;
|
|
}
|
|
|
|
|
|
##########################################################################
|
|
# The mkfulllpar function is written in ksh, and used to create a full
|
|
# system partition for each CECs Managed by the HMC. It will use ssh to
|
|
# login the HMC with the hscroot userid in order to rename the CECs based
|
|
# on a certain pattern specified through command line and create full
|
|
# partition for all the CECs.
|
|
##########################################################################
|
|
|
|
sub mkfulllpar {
|
|
|
|
my $request = shift;
|
|
my $hash = shift;
|
|
my $exp = shift;
|
|
my $hwtype = @$exp[2];
|
|
my $opt = $request->{opt};
|
|
my @values = ();
|
|
my $result;
|
|
my $lpar;
|
|
my $d;
|
|
my $lparid;
|
|
my $mtms;
|
|
my $type;
|
|
my $profile;
|
|
|
|
my $ppctab = xCAT::Table->new('ppc');
|
|
#####################################
|
|
# Get source node information
|
|
#####################################
|
|
while (my ($cec, $h) = each(%$hash)) {
|
|
my ($name, $data) = each(%$h);
|
|
$d = $data;
|
|
$lparid = @$d[0];
|
|
$mtms = @$d[2];
|
|
$type = @$d[4];
|
|
$lpar = $name;
|
|
#####################################
|
|
# Must be CEC or LPAR
|
|
#####################################
|
|
if ($type !~ /^(lpar|fsp|cec)$/) {
|
|
return ([ [ $lpar, "Node must be LPAR or CEC", RC_ERROR ] ]);
|
|
}
|
|
|
|
my $ppctab = xCAT::Table->new('ppc');
|
|
#####################################
|
|
# Check if a existing with requested LPAR ID has existed
|
|
#####################################
|
|
my $value = xCAT::PPCcli::lssyscfg(
|
|
$exp,
|
|
"profs",
|
|
$mtms,
|
|
"all_resources",
|
|
"lpar_ids=$lparid");
|
|
my $Rc = shift(@$value);
|
|
#######################################
|
|
# make how to handle according to the result of lssyscfg
|
|
#######################################
|
|
if ($Rc == SUCCESS) {
|
|
|
|
# close the DB handler of the ppc table
|
|
$ppctab->close;
|
|
|
|
# change the lpar's attribute before removing it.
|
|
my $all_res_flag = @$value[0];
|
|
if ($all_res_flag != 1) {
|
|
return ([ [ $lpar, "The LPAR ID has been occupied", RC_ERROR ] ]);
|
|
}
|
|
else {
|
|
return ([ [ $lpar, "This full LPAR has been created", RC_ERROR ] ]);
|
|
}
|
|
}
|
|
|
|
#################################
|
|
# Create the new full LPAR's configure data
|
|
#################################
|
|
my ($lpar_id, $profname);
|
|
my $vcon = $ppctab->getAttribs($name, ('id', 'pprofile'));
|
|
if ($vcon) {
|
|
if ($vcon->{"id"}) {
|
|
$lpar_id = $vcon->{"id"};
|
|
} else {
|
|
$lpar_id = 1;
|
|
}
|
|
|
|
if ($vcon->{"pprofile"}) {
|
|
$profname = $vcon->{"pprofile"};
|
|
} else {
|
|
$profname = $name;
|
|
}
|
|
} else {
|
|
$lpar_id = 1;
|
|
$profname = $name;
|
|
}
|
|
|
|
my $cfgdata = "name=$name,profile_name=$profname,lpar_id=$lpar_id,lpar_env=aixlinux,all_resources=1,boot_mode=norm,conn_monitoring=0";
|
|
|
|
#################################
|
|
# Create a new full LPAR
|
|
#################################
|
|
$result = xCAT::PPCcli::mksyscfg($exp, "lpar", $d, $cfgdata);
|
|
$Rc = shift(@$result);
|
|
|
|
###########################################
|
|
# Set the CEC's service_lpar_id to the lpar_id of the full LPAR
|
|
###########################################
|
|
if ($Rc == SUCCESS) {
|
|
$cfgdata = "service_lpar_id=$lpar_id";
|
|
$result = xCAT::PPCcli::chsyscfg($exp, "fsp", $d, $cfgdata);
|
|
$Rc = shift(@$result);
|
|
if ($Rc != SUCCESS) {
|
|
$ppctab->close;
|
|
return ([ [ $lpar, @$result[0], $Rc ] ]);
|
|
}
|
|
}
|
|
|
|
#################################
|
|
# Add a new full LPAR to database
|
|
#################################
|
|
if ($Rc == SUCCESS) {
|
|
$profile = $profname;
|
|
my $id = $lpar_id;
|
|
my $err = xCATdB("mkvm", $name, $profile, $id, $d, $hwtype, $lpar);
|
|
if (defined($err)) {
|
|
push @values, [ $name, $err, RC_ERROR ];
|
|
next;
|
|
}
|
|
}
|
|
push @values, [ $name, @$result[0], $Rc ];
|
|
}
|
|
|
|
$ppctab->close;
|
|
return (\@values);
|
|
}
|
|
|
|
|
|
##########################################################################
|
|
# 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(@_));
|
|
}
|
|
|
|
|
|
##########################################################################
|
|
# Removes logical partitions
|
|
##########################################################################
|
|
sub rmvm {
|
|
return (remove(@_));
|
|
}
|
|
|
|
##########################################################################
|
|
# Lists logical partition profile
|
|
##########################################################################
|
|
sub lsvm {
|
|
return (list(@_));
|
|
}
|
|
|
|
|
|
|
|
1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|