966 lines
26 KiB
Perl
966 lines
26 KiB
Perl
# IBM(c) 2013 EPL license http://www.eclipse.org/legal/epl-v10.html
|
|
package xCAT_plugin::openstack;
|
|
BEGIN
|
|
{
|
|
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
|
|
}
|
|
use lib "$::XCATROOT/lib/perl";
|
|
use xCAT::Utils;
|
|
use xCAT::TableUtils;
|
|
use xCAT::SvrUtils;
|
|
use xCAT::NetworkUtils;
|
|
use xCAT::Table;
|
|
use Data::Dumper;
|
|
use File::Path;
|
|
use File::Copy;
|
|
use Getopt::Long;
|
|
Getopt::Long::Configure("bundling");
|
|
Getopt::Long::Configure("pass_through");
|
|
|
|
|
|
sub handled_commands {
|
|
return {
|
|
opsaddbmnode => "openstack", #external command
|
|
opsaddimage => "openstack", #external command
|
|
deploy_ops_bm_node => "openstack", #internal command called from the baremetal driver
|
|
cleanup_ops_bm_node => "openstack", #internal command called from the baremetal driver
|
|
}
|
|
}
|
|
|
|
sub process_request {
|
|
my $request = shift;
|
|
my $callback = shift;
|
|
my $doreq = shift;
|
|
my $command = $request->{command}->[0];
|
|
|
|
if ($command eq "opsaddbmnode") {
|
|
return opsaddbmnode($request, $callback, $doreq);
|
|
} elsif ($command eq "opsaddimage") {
|
|
return opsaddimage($request, $callback, $doreq);
|
|
} elsif ($command eq "deploy_ops_bm_node") {
|
|
return deploy_ops_bm_node($request, $callback, $doreq);
|
|
} elsif ($command eq "cleanup_ops_bm_node") {
|
|
return cleanup_ops_bm_node($request, $callback, $doreq);
|
|
} else {
|
|
$callback->({error=>["Unsupported command: $command."],errorcode=>[1]});
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 opsaddbmnode
|
|
This function takes the xCAT nodes and register them
|
|
as the OpenStack baremetal nodes
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub opsaddbmnode {
|
|
my $request = shift;
|
|
my $callback = shift;
|
|
my $doreq = shift;
|
|
|
|
@ARGV = @{$request->{arg}};
|
|
Getopt::Long::Configure("bundling");
|
|
Getopt::Long::Configure("no_pass_through");
|
|
|
|
my $help;
|
|
my $version;
|
|
my $verbose;
|
|
my $host;
|
|
|
|
if(!GetOptions(
|
|
'h|help' => \$help,
|
|
'v|version' => \$version,
|
|
'V|verbose' => \$verbose,
|
|
's=s' => \$host,
|
|
))
|
|
{
|
|
&opsaddbmnode_usage($callback);
|
|
return 1;
|
|
}
|
|
# display the usage if -h or --help is specified
|
|
if ($help) {
|
|
&opsaddbmnode_usage($callback);
|
|
return 0;
|
|
}
|
|
# display the version statement if -v or --verison is specified
|
|
if ($version)
|
|
{
|
|
my $rsp={};
|
|
$rsp->{data}->[0]= xCAT::Utils->Version();
|
|
$callback->($rsp);
|
|
return 0;
|
|
}
|
|
|
|
if (!$request->{node}) {
|
|
$callback->({error=>["Please specify at least one node."],errorcode=>[1]});
|
|
return 1;
|
|
}
|
|
if (!$host) {
|
|
$callback->({error=>["Please specify the OpenStack compute host name with -s flag."],errorcode=>[1]});
|
|
return 1;
|
|
}
|
|
|
|
my $nodes = $request->{node};
|
|
|
|
#get node mgt
|
|
my $nodehmhash;
|
|
my $nodehmtab = xCAT::Table->new("nodehm");
|
|
if ($nodehmtab) {
|
|
$nodehmhash = $nodehmtab->getNodesAttribs($nodes,['power', 'mgt']);
|
|
}
|
|
|
|
#get bmc info for the nodes
|
|
my $ipmitab = xCAT::Table->new("ipmi", -create => 0);
|
|
my $tmp_ipmi;
|
|
if ($ipmitab) {
|
|
$tmp_ipmi = $ipmitab->getNodesAttribs($nodes, ['bmc','username', 'password'], prefetchcache=>1);
|
|
#print Dumper($tmp_ipmi);
|
|
} else {
|
|
$callback->({error=>["Cannot open the ipmi table."],errorcode=>[1]});
|
|
return 1;
|
|
}
|
|
|
|
#get mac for the nodes
|
|
my $mactab = xCAT::Table->new("mac", -create => 0);
|
|
my $tmp_mac;
|
|
if ($mactab) {
|
|
$tmp_mac = $mactab->getNodesAttribs($nodes, ['mac'], prefetchcache=>1);
|
|
#print Dumper($tmp_mac);
|
|
} else {
|
|
$callback->({error=>["Cannot open the mac table."],errorcode=>[1]});
|
|
return 1;
|
|
}
|
|
|
|
#get cpu, memory and disk info for the nodes
|
|
my $hwinvtab = xCAT::Table->new("hwinv", -create => 0);
|
|
my $tmp_hwinv;
|
|
if ($hwinvtab) {
|
|
$tmp_hwinv = $hwinvtab->getNodesAttribs($nodes, ['cpucount', 'memory', 'disksize'], prefetchcache=>1);
|
|
#print Dumper($tmp_hwinv);
|
|
} else {
|
|
$callback->({error=>["Cannot open the hwinv table."],errorcode=>[1]});
|
|
return 1;
|
|
}
|
|
|
|
#get default username and password for bmc
|
|
my $d_bmcuser;
|
|
my $d_bmcpasswd;
|
|
my $passtab = xCAT::Table->new('passwd');
|
|
if ($passtab) {
|
|
($tmp_passwd)=$passtab->getAttribs({'key'=>'ipmi'},'username','password');
|
|
if (defined($tmp_passwd)) {
|
|
$d_bmcuser = $tmp_passwd->{username};
|
|
$d_bmcpasswd = $tmp_passwd->{password};
|
|
}
|
|
}
|
|
|
|
#print "d_bmcuser=$d_bmcuser, d_bmcpasswd=$d_bmcpasswd \n";
|
|
foreach my $node (@$nodes) {
|
|
#collect the node infomation needed for each node, some info
|
|
my $mgt;
|
|
my $ref_nodehm = $nodehmhash->{$node}->[0];
|
|
if ($ref_nodehm) {
|
|
if ($ref_nodehm->{'power'}) {
|
|
$mgt = $ref_nodehm->{'power'};
|
|
} elsif ($ref_nodehm->{'mgt'}) {
|
|
$mgt = $ref_nodehm->{'mgt'};
|
|
}
|
|
}
|
|
|
|
my ($bmc, $bmc_user, $bmc_password, $mac, $cpu, $memory, $disk);
|
|
if (($mgt) && ($mgt eq 'ipmi')) {
|
|
my $ref_ipmi = $tmp_ipmi->{$node}->[0];
|
|
if ($ref_ipmi) {
|
|
if (exists($ref_ipmi->{bmc})) {
|
|
$bmc = $ref_ipmi->{bmc};
|
|
}
|
|
if (exists($ref_ipmi->{username})) {
|
|
$bmc_user = $ref_ipmi->{username};
|
|
if (exists($ref_ipmi->{password})) {
|
|
$bmc_password = $ref_ipmi->{password};
|
|
}
|
|
} else { #take the default if they cannot be found on ipmi table
|
|
if ($d_bmcuser) { $bmc_user = $d_bmcuser; }
|
|
if ($d_bmcpasswd) { $bmc_password = $d_bmcpasswd; }
|
|
}
|
|
}
|
|
} # else { # for hardware control point other than ipmi, just fake it in OpenStack.
|
|
#$bmc = "0.0.0.0";
|
|
#$bmc_user = "xCAT";
|
|
#$bmc_password = "xCAT";
|
|
#}
|
|
|
|
my $ref_mac = $tmp_mac->{$node}->[0];
|
|
if ($ref_mac) {
|
|
if (exists($ref_mac->{mac})) {
|
|
$mac = $ref_mac->{mac};
|
|
}
|
|
}
|
|
|
|
$ref_hwinv = $tmp_hwinv->{$node}->[0];
|
|
if ($ref_hwinv) {
|
|
if (exists($ref_hwinv->{cpucount})) {
|
|
$cpu = $ref_hwinv->{cpucount};
|
|
}
|
|
if (exists($ref_hwinv->{memory})) {
|
|
$memory = $ref_hwinv->{memory};
|
|
#TODO: what if the unit is not in MB? We need to convert it to MB
|
|
$memory =~ s/MB|mb//g;
|
|
}
|
|
if (exists($ref_hwinv->{disksize})) {
|
|
#The format of the the disk size is: sda:250GB,sdb:250GB or just 250GB
|
|
#We need to get the size of the first one
|
|
$disk = $ref_hwinv->{disksize};
|
|
my @a = split(',', $disk);
|
|
my @b = split(':', $a[0]);
|
|
if (@b > 1) {
|
|
$disk = $b[1];
|
|
} else {
|
|
$disk = $b[0];
|
|
}
|
|
#print "a=@a, b=@b\n";
|
|
#TODO: what if the unit is not in GB? We need to convert it to MB
|
|
$disk =~ s/GB|gb//g;
|
|
}
|
|
}
|
|
|
|
#some info are mendatory
|
|
if (!$mac) {
|
|
$callback->({error=>["Mac address is not defined in the mac table for node $node."],errorcode=>[1]});
|
|
next;
|
|
}
|
|
if (!$cpu) {
|
|
#default cpu count is 1
|
|
$cpu = 1;
|
|
}
|
|
if (!$memory) {
|
|
#default memory size is 1024MB=1GB
|
|
$memory = 1024;
|
|
}
|
|
if (!$disk) {
|
|
#default disk size is 1GB
|
|
$disk = 1;
|
|
}
|
|
|
|
if ($verbose) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "Attributes gathered from the xCAT database:";
|
|
push @{$rsp->{data}}, " bmc=$bmc";
|
|
push @{$rsp->{data}}, " bmc_user=$bmc_user";
|
|
push @{$rsp->{data}}, " bmc_password=$bmc_password";
|
|
push @{$rsp->{data}}, " mac=$mac";
|
|
push @{$rsp->{data}}, " cpu=$cpu";
|
|
push @{$rsp->{data}}, " memory=$memory";
|
|
push @{$rsp->{data}}, " disk=$disk";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
}
|
|
|
|
#call OpenStack command to add the node into the OpenStack as
|
|
#a baremetal node.
|
|
my $cmd_tmp = "nova baremetal-node-create";
|
|
if ($bmc) {
|
|
#make sure it is an ip address
|
|
if (($bmc !~ /\d+\.\d+\.\d+\.\d+/) && ($bmc !~ /:/)) {
|
|
$bmc = xCAT::NetworkUtils->getipaddr($bmc);
|
|
}
|
|
$cmd_tmp .= " --pm_address=$bmc";
|
|
}
|
|
if ($bmc_user) {
|
|
$cmd_tmp .= " --pm_user=$bmc_user";
|
|
}
|
|
if ($bmc_password) {
|
|
$cmd_tmp .= " --pm_password=$bmc_password";
|
|
}
|
|
$cmd_tmp .= " $host $cpu $memory $disk $mac";
|
|
|
|
my $cmd = qq~$cmd_tmp~;
|
|
if ($verbose) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "The command to run on $host:";
|
|
push @{$rsp->{data}}, " $cmd";
|
|
push @{$rsp->{data}}, " ";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
}
|
|
#print "cmd=$cmd\n";
|
|
my $output =
|
|
xCAT::InstUtils->xcmd($callback, $doreq, "xdsh", [$host], $cmd, 0);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "OpenStack creating baremetal node $node:";
|
|
push @{$rsp->{data}}, "$output";
|
|
push @{$rsp->{data}}, "The command was: $cmd";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
} else {
|
|
if (($verbose) && ($output)) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "$output";
|
|
push @{$rsp->{data}}, " ";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 opsaddimage
|
|
This function takes the xCAT nodes and register them
|
|
as the OpenStack baremetal nodes
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub opsaddimage {
|
|
my $request = shift;
|
|
my $callback = shift;
|
|
my $doreq = shift;
|
|
|
|
@ARGV = @{$request->{arg}};
|
|
Getopt::Long::Configure("bundling");
|
|
Getopt::Long::Configure("no_pass_through");
|
|
|
|
my $help;
|
|
my $version;
|
|
my $verbose;
|
|
#my $cloud;
|
|
my $ops_img_names;
|
|
my $controller;
|
|
|
|
if(!GetOptions(
|
|
'h|help' => \$help,
|
|
'v|version' => \$version,
|
|
'V|verbose' => \$verbose,
|
|
'c=s' => \$controller,
|
|
'n=s' => \$ops_img_names,
|
|
))
|
|
{
|
|
&opsaddimage_usage($callback);
|
|
return 1;
|
|
}
|
|
# display the usage if -h or --help is specified
|
|
if ($help) {
|
|
&opsaddimage_usage($callback);
|
|
return 0;
|
|
}
|
|
# display the version statement if -v or --verison is specified
|
|
if ($version)
|
|
{
|
|
my $rsp={};
|
|
$rsp->{data}->[0]= xCAT::Utils->Version();
|
|
$callback->($rsp);
|
|
return 0;
|
|
}
|
|
|
|
if (@ARGV ==0) {
|
|
$callback->({error=>["Please specify an image name or a list of image names."],errorcode=>[1]});
|
|
return 1;
|
|
}
|
|
|
|
#make sure the input cloud name is valid.
|
|
#if (!$cloud) {
|
|
# $callback->({error=>["Please specify the name of the cloud with -c flag."],errorcode=>[1]});
|
|
# return 1;
|
|
#} else {
|
|
# my $cloudstab = xCAT::Table->new('clouds', -create => 0);
|
|
# my @et = $cloudstab->getAllAttribs('name', 'controller');
|
|
# if(@et) {
|
|
# foreach my $tmp_et (@et) {
|
|
# if ($tmp_et->{name} eq $cloud) {
|
|
# if ($tmp_et->{controller}) {
|
|
# $controller = $tmp_et->{controller};
|
|
# last;
|
|
# } else {
|
|
# $callback->({error=>["Please specify the controller in the clouds table for the cloud: $cloud."],errorcode=>[1]});
|
|
# return 1;
|
|
# }
|
|
# }
|
|
# }
|
|
# }
|
|
|
|
if (!$controller) {
|
|
$callback->({error=>["Please specify the OpenStack controller node name with -c."],errorcode=>[1]});
|
|
return 1;
|
|
}
|
|
#}
|
|
|
|
#make sure that the images from the command are valid image names
|
|
@images = split(',', $ARGV[0]);
|
|
@new_names = ();
|
|
if ($ops_img_names) {
|
|
@new_names = split(',', $ops_img_names);
|
|
}
|
|
#print "images=@images, new image names=@new_names, controller=$controller\n";
|
|
|
|
my $image_hash = {};
|
|
my $osimgtab = xCAT::Table->new('osimage', -create => 0);
|
|
my @et = $osimgtab->getAllAttribs('imagename');
|
|
if(@et) {
|
|
foreach my $tmp_et (@et) {
|
|
$image_hash->{$tmp_et->{imagename}}{'xCAT'} = 1;
|
|
}
|
|
}
|
|
my @bad_images;
|
|
foreach my $image (@images) {
|
|
if (!exists($image_hash->{$image})) {
|
|
push @bad_images, $image;
|
|
}
|
|
}
|
|
if (@bad_images > 0) {
|
|
$callback->({error=>["The following images cannot be found in xCAT osimage table:\n " . join("\n ", @bad_images) . "\n"],errorcode=>[1]});
|
|
return 1;
|
|
}
|
|
|
|
my $index=0;
|
|
foreach my $image (@images) {
|
|
my $new_name = shift(@new_names);
|
|
if (!$new_name) {
|
|
$new_name = $image; #the default new name is xCAT image name
|
|
}
|
|
my $cmd_tmp = "glance image-create --name $new_name --public --disk-format qcow2 --container-format bare --property xcat_image_name=\'$image\' < /tmp/$image.qcow2";
|
|
|
|
my $cmd = qq~touch /tmp/$image.qcow2;$cmd_tmp~;
|
|
if ($verbose) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "The command to run on $controller:";
|
|
push @{$rsp->{data}}, " $cmd";
|
|
push @{$rsp->{data}}, " ";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
}
|
|
my $output =
|
|
xCAT::InstUtils->xcmd($callback, $doreq, "xdsh", [$controller], $cmd, 0);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "OpenStack creating image $new_name:";
|
|
push @{$rsp->{data}}, "$output";
|
|
push @{$rsp->{data}}, "The command was: $cmd";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
} else {
|
|
if (($verbose) && ($output)) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "$output";
|
|
push @{$rsp->{data}}, " ";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
}
|
|
}
|
|
my $cmd1 = qq~rm /tmp/$image.qcow2~;
|
|
if ($verbose) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "The command to run on $controller:";
|
|
push @{$rsp->{data}}, " $cmd1";
|
|
push @{$rsp->{data}}, " ";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
}
|
|
my $output1 =
|
|
xCAT::InstUtils->xcmd($callback, $doreq, "xdsh", [$controller], $cmd1, 0);
|
|
if (($verbose) && ($output1)) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "$output1";
|
|
push @{$rsp->{data}}, " ";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
}
|
|
}
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 deploy_ops_bm_node
|
|
This is a internel command called by OpenStack xCAT-baremetal driver.
|
|
It prepares the node by adding the config_ops_bm_node postbootscript
|
|
to the postscript table for the node, then call nodeset and then boot
|
|
the node up.
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub deploy_ops_bm_node {
|
|
my $request = shift;
|
|
my $callback = shift;
|
|
my $doreq = shift;
|
|
|
|
@ARGV = @{$request->{arg}};
|
|
Getopt::Long::Configure("bundling");
|
|
Getopt::Long::Configure("no_pass_through");
|
|
|
|
my $node = $request->{node}->[0];
|
|
|
|
my $help;
|
|
my $version;
|
|
my $img_name;
|
|
my $hostname;
|
|
my $fixed_ip;
|
|
my $netmask;
|
|
|
|
if(!GetOptions(
|
|
'h|help' => \$help,
|
|
'v|version' => \$version,
|
|
'image=s' => \$img_name,
|
|
'host=s' => \$hostname,
|
|
'ip=s' => \$fixed_ip,
|
|
'mask=s' => \$netmask,
|
|
))
|
|
{
|
|
&deploy_ops_bm_node_usage($callback);
|
|
return 1;
|
|
}
|
|
# display the usage if -h or --help is specified
|
|
if ($help) {
|
|
&deploy_ops_bm_node_usage($callback);
|
|
return 0;
|
|
}
|
|
# display the version statement if -v or --verison is specified
|
|
if ($version)
|
|
{
|
|
my $rsp={};
|
|
$rsp->{data}->[0]= xCAT::Utils->Version();
|
|
$callback->($rsp);
|
|
return 0;
|
|
}
|
|
#print "node=$node, image=$img_name, host=$hostname, ip=$fixed_ip, mask=$netmask\n";
|
|
|
|
#validate the image name
|
|
my $osimagetab = xCAT::Table->new('osimage', -create=>1);
|
|
my $ref = $osimagetab->getAttribs({imagename => $img_name}, 'imagename');
|
|
if (!$ref) {
|
|
$callback->({error=>["Invalid image name: $img_name."],errorcode=>[1]});
|
|
return 1;
|
|
}
|
|
|
|
#check if the fixed ip is within the xCAT management network.
|
|
#get the master ip address for the node then check if the master ip and
|
|
#the OpenStack fixed_ip are on the same subnet.
|
|
#my $same_nw = 0;
|
|
#my $master = xCAT::TableUtils->GetMasterNodeName($node);
|
|
#my $master_ip = xCAT::NetworkUtils->toIP($master);
|
|
#if (xCAT::NetworkUtils::isInSameSubnet($master_ip, $fixed_ip, $netmask, 0)) {
|
|
# $same_nw = 1;
|
|
#}
|
|
|
|
|
|
#add config_ops_bm_node to the node's postbootscript
|
|
my $script = "config_ops_bm_node $hostname $fixed_ip $netmask";
|
|
add_postscript($callback, $node, $script);
|
|
|
|
#run nodeset
|
|
my $cmd = qq~osimage=$img_name~;
|
|
my $output = xCAT::Utils->runxcmd(
|
|
{command => ["nodeset"],
|
|
node => [$node],
|
|
arg => [$cmd]},
|
|
$doreq, -1, 1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "nodeset:";
|
|
push @{$rsp->{data}}, "$output";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
#deploy the node now, supported nodehm.mgt values: ipmi, blade,fsp, hmc.
|
|
my $hmtab = xCAT::Table->new('nodehm');
|
|
my $hment = $hmtab->getNodeAttribs($node,['mgt']);
|
|
if ($hment && $hment->{'mgt'}) {
|
|
my $mgt = $hment->{'mgt'};
|
|
if ($mgt eq 'ipmi') {
|
|
deploy_bmc_node($callback, $doreq, $node);
|
|
} elsif (($mgt eq 'blade') || ($mgt eq 'fsp')) {
|
|
deploy_blade($callback, $doreq, $node);
|
|
} elsif ($mgt eq 'hmc') {
|
|
deploy_hmc_node($callback, $doreq, $node);
|
|
} else {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "Node $node: nodehm.mgt=$mgt is not supported in the OpenStack cloud.";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
} else {
|
|
#nodehm.mgt must setup for node
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "Node $node: nodehm.mgt cannot be empty in order to deploy.";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
|
|
# Deploy a rack-mounted node
|
|
sub deploy_bmc_node {
|
|
my $callback = shift;
|
|
my $doreq = shift;
|
|
my $node = shift;
|
|
|
|
#set boot order
|
|
my $cmd = qq~net~;
|
|
my $output = xCAT::Utils->runxcmd(
|
|
{command => ["rsetboot"],
|
|
node => [$node],
|
|
arg => [$cmd]},
|
|
$doreq, -1, 1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "rsetboot:";
|
|
push @{$rsp->{data}}, "$output";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
}
|
|
|
|
#reboot the node
|
|
my $cmd = qq~boot~;
|
|
my $output = xCAT::Utils->runxcmd(
|
|
{command => ["rpower"],
|
|
node => [$node],
|
|
arg => [$cmd]},
|
|
$doreq, -1, 1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "rpower:";
|
|
push @{$rsp->{data}}, "$output";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
# Deploy a blade or fsp controlled node
|
|
sub deploy_blade {
|
|
my $callback = shift;
|
|
my $doreq = shift;
|
|
my $node = shift;
|
|
|
|
#set boot order
|
|
my $cmd = qq~net~;
|
|
my $output = xCAT::Utils->runxcmd(
|
|
{command => ["rbootseq"],
|
|
node => [$node],
|
|
arg => [$cmd]},
|
|
$doreq, -1, 1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "rbootseq:";
|
|
push @{$rsp->{data}}, "$output";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
}
|
|
|
|
#reboot the node
|
|
my $cmd = qq~boot~;
|
|
my $output = xCAT::Utils->runxcmd(
|
|
{command => ["rpower"],
|
|
node => [$node],
|
|
arg => [$cmd]},
|
|
$doreq, -1, 1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "rpower:";
|
|
push @{$rsp->{data}}, "$output";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
# Deploy a node controlled by HMC
|
|
sub deploy_hmc_node {
|
|
my $callback = shift;
|
|
my $doreq = shift;
|
|
my $node = shift;
|
|
|
|
my $output = xCAT::Utils->runxcmd(
|
|
{command => ["rnetboot"],
|
|
node => [$node]},
|
|
$doreq, -1, 1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "rnetboot:";
|
|
push @{$rsp->{data}}, "$output";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 cleanup_ops_bm_node
|
|
This is a internel command called by OpenStack xCAT-baremetal driver.
|
|
It undoes all the changes made by deploy_ops_bm_node command. It removes
|
|
the config_ops_bmn_ode postbootscript from the postscript table for the
|
|
node, removes the alias ip and then power off the node.
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub cleanup_ops_bm_node {
|
|
my $request = shift;
|
|
my $callback = shift;
|
|
my $doreq = shift;
|
|
|
|
@ARGV = @{$request->{arg}};
|
|
Getopt::Long::Configure("bundling");
|
|
Getopt::Long::Configure("no_pass_through");
|
|
|
|
my $node = $request->{node}->[0];
|
|
|
|
my $help;
|
|
my $version;
|
|
my $fixed_ip;
|
|
|
|
if(!GetOptions(
|
|
'h|help' => \$help,
|
|
'v|version' => \$version,
|
|
'ip=s' => \$fixed_ip,
|
|
))
|
|
{
|
|
&cleanup_ops_bm_node_usage($callback);
|
|
return 1;
|
|
}
|
|
# display the usage if -h or --help is specified
|
|
if ($help) {
|
|
&cleanup_ops_bm_node_usage($callback);
|
|
return 0;
|
|
}
|
|
# display the version statement if -v or --verison is specified
|
|
if ($version)
|
|
{
|
|
my $rsp={};
|
|
$rsp->{data}->[0]= xCAT::Utils->Version();
|
|
$callback->($rsp);
|
|
return 0;
|
|
}
|
|
#print "node=$node, ip=$fixed_ip\n";
|
|
|
|
#removes the config_ops_bm_node postbootscript from the postscripts table
|
|
remove_postscript($callback, $node, "config_ops_bm_node");
|
|
|
|
|
|
#run updatenode to remove the ip alias
|
|
my $cmd = qq~-P deconfig_ops_bm_node $fixed_ip~;
|
|
my $output = xCAT::Utils->runxcmd(
|
|
{command => ["updatenode"],
|
|
node => [$node],
|
|
arg => [$cmd]},
|
|
$doreq, -1, 1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "updatenode:";
|
|
push @{$rsp->{data}}, "$output";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
}
|
|
|
|
#turn the node power off
|
|
$ssh_ok = 0;
|
|
my $cmd = qq~stat~;
|
|
my $output = xCAT::Utils->runxcmd(
|
|
{command => ["rpower"],
|
|
node => [$node],
|
|
arg => [$cmd]},
|
|
$doreq, -1, 1);
|
|
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "rpower:";
|
|
push @{$rsp->{data}}, "$output";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
} else {
|
|
if ($output !~ /: off/) {
|
|
#power off the node
|
|
my $cmd = qq~off~;
|
|
my $output = xCAT::Utils->runxcmd(
|
|
{command => ["rpower"],
|
|
node => [$node],
|
|
arg => [$cmd]},
|
|
$doreq, -1, 1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "rpower:";
|
|
push @{$rsp->{data}}, "$output";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#-------------------------------------------------------
|
|
=head3 add_postscript
|
|
|
|
It adds the 'config_ops_bm_node' postbootscript to the
|
|
postscript table for the given node.
|
|
|
|
=cut
|
|
#-------------------------------------------------------
|
|
sub add_postscript {
|
|
my $callback=shift;
|
|
my $node=shift;
|
|
my $script=shift;
|
|
#print "script=$script\n";
|
|
|
|
my $posttab=xCAT::Table->new("postscripts", -create =>1);
|
|
my %setup_hash;
|
|
my $ref = $posttab->getNodeAttribs($node,[qw(postscripts postbootscripts)]);
|
|
my $found=0;
|
|
if ($ref) {
|
|
if (exists($ref->{postscripts})) {
|
|
my @a = split(/,/, $ref->{postscripts});
|
|
if (grep(/^config_ops_bm_node/, @a)) {
|
|
$found = 1;
|
|
if (!grep(/^$script$/, @a)) {
|
|
#not exact match, must replace it with the new script
|
|
for (@a) {
|
|
s/^config_ops_bm_node.*$/$script/;
|
|
}
|
|
my $new_post = join(',', @a);
|
|
$setup_hash{$node}={postscripts=>"$new_post"};
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (exists($ref->{postbootscripts})) {
|
|
my $post=$ref->{postbootscripts};
|
|
my @old_a=split(',', $post);
|
|
if (grep(/^config_ops_bm_node/, @old_a)) {
|
|
if (!grep(/^$script$/, @old_a)) {
|
|
#not exact match, will replace it with new script
|
|
for (@old_a) {
|
|
s/^config_ops_bm_node.*$/$script/;
|
|
}
|
|
my $new_postboot = join(',', @old_a);
|
|
$setup_hash{$node}={postbootscripts=>"$new_postboot"};
|
|
}
|
|
} else {
|
|
if (! $found) {
|
|
$setup_hash{$node}={postbootscripts=>"$post,$script"};
|
|
}
|
|
}
|
|
} else {
|
|
if (! $found) {
|
|
$setup_hash{$node}={postbootscripts=>"$script"};
|
|
}
|
|
}
|
|
} else {
|
|
$setup_hash{$node}={postbootscripts=>"$script"};
|
|
}
|
|
|
|
if (keys(%setup_hash) > 0) {
|
|
$posttab->setNodesAttribs(\%setup_hash);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#-------------------------------------------------------
|
|
=head3 remove_postscript
|
|
|
|
It removes the 'config_ops_bm_node' postbootscript from
|
|
the postscript table for the given node.
|
|
|
|
=cut
|
|
#-------------------------------------------------------
|
|
sub remove_postscript {
|
|
my $callback=shift;
|
|
my $node=shift;
|
|
my $script=shift;
|
|
|
|
my $posttab=xCAT::Table->new("postscripts", -create =>1);
|
|
my %setup_hash;
|
|
my $ref = $posttab->getNodeAttribs($node,[qw(postscripts postbootscripts)]);
|
|
my $found=0;
|
|
if ($ref) {
|
|
if (exists($ref->{postscripts})) {
|
|
my @old_a = split(/,/, $ref->{postscripts});
|
|
my @new_a = grep(!/^$script/, @old_a);
|
|
if (scalar(@new_a) != scalar(@old_a)) {
|
|
my $new_post = join(',', @new_a);
|
|
$setup_hash{$node}={postscripts=>"$new_post"};
|
|
}
|
|
}
|
|
|
|
if (exists($ref->{postbootscripts})) {
|
|
my @old_b = split(/,/, $ref->{postbootscripts});
|
|
my @new_b = grep(!/^$script/, @old_b);
|
|
if (scalar(@new_b) != scalar(@old_b)) {
|
|
my $new_post = join(',', @new_b);
|
|
$setup_hash{$node}={postbootscripts=>"$new_post"};
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (keys(%setup_hash) > 0) {
|
|
$posttab->setNodesAttribs(\%setup_hash);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 opsaddbmnode_usage
|
|
The usage text for opsaddbmnode command.
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub opsaddbmnode_usage {
|
|
my $cb=shift;
|
|
my $rsp={};
|
|
|
|
$rsp->{data}->[0]= "Usage: opsaddbmnode -h";
|
|
$rsp->{data}->[1]= " opsaddbmnode -v";
|
|
$rsp->{data}->[2]= " opsaddbmnode <noderange> -s <service_host> [-V]";
|
|
$cb->($rsp);
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 opsaddimage_usage
|
|
The usage text for opsaddimage command.
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub opsaddimage_usage {
|
|
my $cb=shift;
|
|
my $rsp={};
|
|
|
|
$rsp->{data}->[0]= "Usage: opsaddimage -h";
|
|
$rsp->{data}->[1]= " opsaddimage -v";
|
|
$rsp->{data}->[2]= " opsaddimage <image1,image2...> [-n <new_name1,new_name2...> -c <controller> [-V]";
|
|
$cb->($rsp);
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 deploy_ops_bm_node_usage
|
|
The usage text for deploy_ops_bm_node command.
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub deploy_ops_bm_node_usage {
|
|
my $cb=shift;
|
|
my $rsp={};
|
|
|
|
$rsp->{data}->[0]= "Usage: deploy_ops_bm_node -h";
|
|
$rsp->{data}->[1]= " deploy_ops_bm_node -v";
|
|
$rsp->{data}->[2]= " deploy_ops_bm_node <node> --image <image_name> --host <ops_hostname> --ip <ops_fixed_ip> --mask <netmask>";
|
|
$cb->($rsp);
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 cleanup_ops_bm_node_usage
|
|
The usage text cleanup_ops_bm_node command.
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub cleanup_ops_bm_node_usage {
|
|
my $cb=shift;
|
|
my $rsp={};
|
|
|
|
$rsp->{data}->[0]= "Usage: cleanup_ops_bm_node -h";
|
|
$rsp->{data}->[1]= " cleanup_ops_bm_node -v";
|
|
$rsp->{data}->[2]= " cleanup_ops_bm_node <node> [--ip <ops_fixed_ip>]";
|
|
$cb->($rsp);
|
|
}
|
|
|
|
1;
|