xcat-core/xCAT-server/lib/xcat/plugins/rinstall.pm
2014-06-24 07:49:45 -04:00

482 lines
14 KiB
Perl

# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
#-------------------------------------------------------
=head1
xCAT plugin package to handle rinstall and winstall
Supported command:
rinstall - runs nodeset, rsetboot,rpower commands
winstall - also opens the console
=cut
#-------------------------------------------------------
package xCAT_plugin::rinstall;
use strict;
require xCAT::Utils;
require xCAT::MsgUtils;
use xCAT::NodeRange;
use xCAT::Table;
use Data::Dumper;
use Getopt::Long;
#-------------------------------------------------------
=head3 handled_commands
Return list of commands handled by this plugin
=cut
#-------------------------------------------------------
sub handled_commands
{
return {
rinstall => "rinstall",
winstall => "rinstall",
};
}
#-------------------------------------------------------
=head3 Process the command
=cut
#-------------------------------------------------------
sub process_request
{
my $request = shift;
my $callback = shift;
my $subreq = shift;
rinstall($request, $callback, $subreq);
}
#-------------------------------------------------------
=head3 rinstall
Wrapper around nodeset, rsetboot, rpower for the admin convenience
=cut
#-------------------------------------------------------
sub rinstall
{
my ($req, $callback, $subreq) = @_;
$::CALLBACK=$callback;
my $OSVER;
my $PROFILE;
my $ARCH;
my $CONSOLE;
my $OSIMAGE;
my $HELP;
my $VERSION;
my $command = $req->{command}->[0]; # could be rinstall on winstall
my $args;
if (defined($req->{arg}) ) { # there are arguments
$args=$req->{arg}; # argument
@ARGV = @{$args};
}
my $nodes;
my @nodes;
if (defined ($req->{node})) { # there are nodes
$nodes = $req->{node};
@nodes=@$nodes;
}
# no arguments, no nodes then input wrong
if ((scalar(@nodes) == 0) && (scalar(@ARGV) == 0)){
&usage($command,$callback);
return 1;
}
#print Dumper($req);
Getopt::Long::Configure("bundling");
unless (
GetOptions(
'o|osver=s' => \$OSVER,
'p|profile=s' => \$PROFILE,
'a|arch=s' => \$ARCH,
'O|osimage=s' => \$OSIMAGE,
'h|help' => \$HELP,
'v|version' => \$VERSION,
'c|console' => \$CONSOLE
)
)
{
&usage($command,$callback);
return 1;
}
if ($HELP)
{
&usage($command,$callback);
return 0;
}
if ($VERSION)
{
my $version = xCAT::Utils->Version();
my $rsp = {};
$rsp->{data}->[0] = "$version";
xCAT::MsgUtils->message("I", $rsp, $callback);
return (0);
}
if (scalar @$nodes eq 0)
{
my $rsp = {};
$rsp->{error}->[0] ="noderange not supplied";
xCAT::MsgUtils->message("E", $rsp, $callback);
return 1;
}
my $rc = 0;
my %pnhash;
if ($OSIMAGE)
{
# -O|--osimage is specified, ignore any -a,-p,-o options,
# call "nodeset ... osimage= ..." to set the boot state of the noderange to the specified osimage,
# "nodeset" will handle the updating of node attributes such as os,arch,profile,provmethod
# verify input
&checkoption("[-O|--osimage] $OSIMAGE",$OSVER,$PROFILE,$ARCH,$callback);
# run nodeset $noderange osimage=$OSIMAGE
my @osimageargs;
push @osimageargs,"osimage=$OSIMAGE" ;
my $res =
xCAT::Utils->runxcmd(
{
command => ["nodeset"],
node => \@nodes,
arg => \@osimageargs
},
$subreq, -1, 1);
my $rsp = {};
if ($::RUNCMD_RC ==0 ) {
foreach my $line (@$res) {
$rsp->{data} ->[0] = $line;
xCAT::MsgUtils->message("I", $rsp, $callback);
}
} else {
foreach my $line (@$res) {
$rsp->{error} ->[0] = $line;
xCAT::MsgUtils->message("E", $rsp, $callback);
}
return 1;
}
}
else
{
# no osimage specified, update the node attributes specified by -a,-p,-o options thru "nodech",
# then set the boot state of each node based on the nodetype.provmethod:
# 1) if nodetype.provmethod = <osimage>, ignore any -p,-o,-a option,
# then call "nodeset ... osimage"
# 2) if nodetype.provmethod = [install/netboot/statelite],
# update the node attributes specified by -a,-p,-o options thru "nodech",
# call "nodeset ... [install/netboot/statelite]"
# 3) if nodetype.provmethod is not set, use 'install' as the default value
# group the nodes according to the nodetype.provmethod
foreach (@$nodes)
{
my $tab = xCAT::Table->new("nodetype");
my $nthash = $tab->getNodeAttribs($_, ['provmethod']);
$tab->close();
if (defined($nthash) and defined($nthash->{'provmethod'}))
{
push(@{$pnhash{$nthash->{'provmethod'}}}, $_);
}
else
{
#if nodetype.provmethod is not specified,
push(@{$pnhash{'install'}}, $_);
}
}
# Now for each group based on provmethod
foreach my $key (keys %pnhash)
{
$::RUNCMD_RC =0;
my $nodes = join(',', @{$pnhash{$key}});
if ($key =~ /^(install|netboot|statelite)$/)
{
# nodetype.provmethod = [install|netboot|statelite]
my @nodechline;
if ($OSVER)
{
push @nodechline, "nodetype.os=$OSVER";
}
if ($PROFILE)
{
push @nodechline, "nodetype.profile=$PROFILE";
}
if ($ARCH)
{
push @nodechline, "nodetype.arch=$ARCH";
}
if (@nodechline)
{
# run nodech $nodes $nodechline
my $res =
xCAT::Utils->runxcmd(
{
command => ["nodech"],
node => \@nodes,
arg => \@nodechline
},
$subreq, -1, 1);
my $rsp = {};
$rc=$::RUNCMD_RC;
if ($rc == 0 ) {
foreach my $line (@$res) {
$rsp->{data} ->[0] = $line;
xCAT::MsgUtils->message("I", $rsp, $callback);
}
} else { # error
$rsp->{error} ->[0] = "nodech error";
xCAT::MsgUtils->message("E", $rsp, $callback);
foreach my $line (@$res) {
$rsp->{error} ->[0] = $line;
xCAT::MsgUtils->message("E", $rsp, $callback);
}
}
} # end nodechline
if ($rc == 0) # if no error from nodech then run nodeset
{
# run nodeset $nodes $key ( where key is install/netboot/statelite)
my @nodesetarg;
push @nodesetarg, "$key";
my $res =
xCAT::Utils->runxcmd(
{
command => ["nodeset"],
node => \@nodes,
arg => \@nodesetarg
},
$subreq, -1, 1);
my $rsp = {};
$rc=$::RUNCMD_RC;
if ($rc ==0 ) {
foreach my $line (@$res) {
$rsp->{data} ->[0] = $line;
xCAT::MsgUtils->message("I", $rsp, $callback);
}
} else { # error
foreach my $line (@$res) {
$rsp->{error} ->[0] = $line;
xCAT::MsgUtils->message("E", $rsp, $callback);
}
}
}
}
else # if not install/netboot/statelite
{
# nodetype.provmethod = <osimage>
&checkoption("nodetype.provmethod=$key",$OSVER,$PROFILE,$ARCH,$callback);
# run nodeset $nodes osimage
my @nodesetarg;
push @nodesetarg, "osimage";
my $res =
xCAT::Utils->runxcmd(
{
command => ["nodeset"],
node => \@nodes,
arg => \@nodesetarg
},
$subreq, -1, 1);
my $rsp = {};
$rc=$::RUNCMD_RC;
if ($rc ==0 ) {
foreach my $line (@$res) {
$rsp->{data} ->[0] = $line;
xCAT::MsgUtils->message("I", $rsp, $callback);
}
} else { # error
foreach my $line (@$res) {
$rsp->{error} ->[0] = $line;
xCAT::MsgUtils->message("E", $rsp, $callback);
}
}
}
}
} # end nodech/nodeset for each group
if ($rc != 0) # we got an error with the nodeset
{
my $rsp = {};
$rsp->{error}->[0] = "nodeset failure will not continue ";
xCAT::MsgUtils->message("E", $rsp, $callback);
return 1;
}
# call "rsetboot" to set the boot order of the nodehm.mgt=ipmi nodes,for others,
# assume user has set the correct boot order before "rinstall"
# run rsetboot $noderange net
my @rsetbootarg;
push @rsetbootarg, "net";
my $res =
xCAT::Utils->runxcmd(
{
command => ["rsetboot"],
node => \@nodes,
arg => \@rsetbootarg
},
$subreq, -1, 1);
# fix output it is a hash and you must get error out of the hash.
my $rsp = {};
$rc=$::RUNCMD_RC;
if ($rc ==0 ) {
foreach my $line (@$res) {
$rsp->{data} ->[0] = $line;
xCAT::MsgUtils->message("I", $rsp, $callback);
}
} else { # error
foreach my $line (@$res) {
$rsp->{error} ->[0] = $line;
xCAT::MsgUtils->message("E", $rsp, $callback);
}
}
if ($rc != 0) # we got an error with the rsetboot
{
my $rsp = {};
$rsp->{error}->[0] = "rsetboot failure will not continue ";
xCAT::MsgUtils->message("E", $rsp, $callback);
return 1;
}
# call "rpower" to start the node provision process
#run rpower $noderange boot
my @rpowerarg;
push @rpowerarg, "boot";
my $res =
xCAT::Utils->runxcmd(
{
command => ["rpower"],
node => \@nodes,
arg => \@rpowerarg
},
$subreq, -1, 1);
my $rsp = {};
$rc=$::RUNCMD_RC;
if ($rc ==0 ) {
foreach my $line (@$res) {
$rsp->{data} ->[0] = $line;
xCAT::MsgUtils->message("I", $rsp, $callback);
}
} else { # error
foreach my $line (@$res) {
$rsp->{error} ->[0] = $line;
xCAT::MsgUtils->message("E", $rsp, $callback);
}
}
# Check if they asked to bring up a console ( -c) from rinstall always for winstall
$req->{startconsole}->[0] =0;
if ($command =~ /rinstall/)
{
# for rinstall, the -c|--console option can provide the remote console for only 1 node
if ($CONSOLE)
{
if (scalar @$nodes ne 1)
{
my $rsp = {};
$rsp->{error}->[0] = "rinstall -c only accepts one node in the noderange. See winstall for support for support of consoles on multiple nodes.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return 1;
} else { # tell rinstall client ok to start rcons
$req->{startconsole}->[0] =1;
}
}
}
elsif ($command =~ /winstall/)
{
# winstall can start a wcons command to multiple nodes for monitoring the provision cycle
$req->{startconsole}->[0] =1;
}
return 0;
}
#-------------------------------------------------------
=head3 Usage
=cut
#-------------------------------------------------------
sub usage
{
my $command = shift;
my $callback = shift;
my $rsp = {};
$rsp->{data}->[0] = "$command usage:";
if ($command =~ /rinstall/) {
$rsp->{data}->[1] = " [-o|--osver] [-p|--profile] [-a|--arch] [-c|--console] <noderange>";
} else { # winstall
$rsp->{data}->[1] = " [-o|--osver] [-p|--profile] [-a|--arch] <noderange>";
}
if ($command =~ /rinstall/) {
$rsp->{data}->[2] = " [-O|--osimage] [-c|--console] <noderange>";
} else { # wininstall
$rsp->{data}->[2] = " [-O|--osimage] <noderange>";
}
$rsp->{data}->[3] = " [-h|--help]";
$rsp->{data}->[4] = " [-v|--version]";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
# check and complain about the invalid combination of the options,
# ignore -o,-p and -a options and prompt a warning message when provmethod=osimagename
sub checkoption{
my $optstring=shift;
my $OSVER=shift;
my $PROFILE=shift;
my $ARCH=shift;
my $callback=shift;
my $rsp = {};
if($OSVER) {
$rsp->{data}->[0] = "-o option not valid with $optstring. It is ignored.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
if($PROFILE) {
$rsp->{data}->[0] = "-p option not valid with $optstring. It is ignored.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
if($ARCH) {
$rsp->{data}->[0] = "-a option not valid with $optstring. It is ignored.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
}
1;