mirror of
https://github.com/xcat2/xcat-core.git
synced 2025-05-21 19:22:05 +00:00
648 lines
23 KiB
Perl
648 lines
23 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 xCAT::Usage;
|
|
|
|
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 $CONSOLE;
|
|
my $OSIMAGE;
|
|
my $STATES;
|
|
my $ignorekernelchk;
|
|
my $noupdateinitrd;
|
|
my $VERBOSE;
|
|
my $HELP;
|
|
my $VERSION;
|
|
my $UEFIMODE;
|
|
|
|
# Could be rinstall or winstall
|
|
my $command = $req->{command}->[0];
|
|
|
|
my $nodes;
|
|
my @nodes;
|
|
my %nodes;
|
|
my $rsp = {};
|
|
|
|
# There are nodes
|
|
if (defined($req->{node})) {
|
|
$nodes = $req->{node};
|
|
@nodes = @$nodes;
|
|
}
|
|
|
|
my $args;
|
|
|
|
# There are arguments
|
|
if (defined($req->{arg})) {
|
|
$args = $req->{arg};
|
|
@ARGV = @{$args};
|
|
}
|
|
|
|
if (($command =~ /rinstall/) or ($command =~ /winstall/)) {
|
|
my $ret=xCAT::Usage->validateArgs($command,@ARGV);
|
|
if ($ret->[0]!=0) {
|
|
$rsp->{error}->[0] = $ret->[1];
|
|
$rsp->{errorcode}->[0] = $ret->[0];
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
&usage($command,$callback);
|
|
return;
|
|
}
|
|
|
|
my $state = $ARGV[0];
|
|
chomp($state);
|
|
if ($state =~ /^osimage=(\S+)/) {
|
|
$OSIMAGE = $1; # osimage was specified
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
}
|
|
elsif ($state =~ /^boot$|^shell$|^osimage$|^runcmd=|^runimage=/) {
|
|
# the rest are valid actions, just pass to nodeset
|
|
$STATES=$state;
|
|
}
|
|
elsif ($state =~ /^-/) {
|
|
# if starts with dash, let GetOptions below to process
|
|
}
|
|
else {
|
|
if ($state) {
|
|
$rsp->{errorcode}->[0]=1;
|
|
$rsp->{error}->[0]="Invalid option $state";
|
|
xCAT::MsgUtils->message("E",$rsp,$callback);
|
|
&usage($command, $callback);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
Getopt::Long::Configure("bundling");
|
|
Getopt::Long::Configure("no_pass_through");
|
|
unless (
|
|
GetOptions(
|
|
'ignorekernelchk' => \$ignorekernelchk,
|
|
'noupdateinitrd' => \$noupdateinitrd,
|
|
'V|verbose' => \$VERBOSE,
|
|
'h|help' => \$HELP,
|
|
'v|version' => \$VERSION,
|
|
'u|uefimode' => \$UEFIMODE,
|
|
'c|console' => \$CONSOLE)
|
|
) {
|
|
&usage($command, $callback);
|
|
return 1;
|
|
}
|
|
}
|
|
if ($HELP) {
|
|
&usage($command, $callback);
|
|
return 0;
|
|
}
|
|
if ($VERSION) {
|
|
my $version = xCAT::Utils->Version();
|
|
$rsp->{data}->[0] = "$version";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
return 0;
|
|
}
|
|
if (scalar(@nodes) == 0) {
|
|
&usage($command, $callback);
|
|
return 1;
|
|
}
|
|
|
|
if($command eq "rinstall" and scalar(@nodes) > 1 and $CONSOLE){
|
|
$rsp->{errorcode}->[0]=1;
|
|
$rsp->{error}->[0]="rinstall -c/--console can only be run against one node! Please use winstall -c/--console for multiple nodes.";
|
|
xCAT::MsgUtils->message("E",$rsp,$callback);
|
|
return 1;
|
|
}
|
|
|
|
my $rc = 0;
|
|
my @parameter;
|
|
|
|
my $nodehmtable = xCAT::Table->new("nodehm");
|
|
my $nodehmcache = $nodehmtable->getNodesAttribs(\@nodes, ['mgt']);
|
|
$nodehmtable->close();
|
|
|
|
if ($OSIMAGE) {
|
|
|
|
# if osimage=<imagename> is specified,
|
|
# 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.
|
|
|
|
my $noderestable = xCAT::Table->new("noderes");
|
|
my $noderescache = $noderestable->getNodesAttribs(\@nodes, ['netboot']);
|
|
$noderestable->close();
|
|
my $nodetypetable = xCAT::Table->new("nodetype");
|
|
my $nodetypecache = $nodetypetable->getNodesAttribs(\@nodes, ['arch']);
|
|
$nodetypetable->close();
|
|
my $osimagetable = xCAT::Table->new("osimage");
|
|
(my $ref) = $osimagetable->getAttribs({ imagename => $OSIMAGE }, 'osvers', 'osarch', 'imagetype');
|
|
$osimagetable->close();
|
|
|
|
unless ($ref) {
|
|
# Nothing was returned from getAttrbs for the specified image
|
|
$rsp->{data}->[0] = "Cannot find the OS image $OSIMAGE in the osimage table.";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
unless (defined($ref->{osarch})) {
|
|
$rsp->{error}->[0] = "$OSIMAGE 'osarch' attribute not defined in 'osimage' table.";
|
|
$rsp->{errorcode}->[0] = 1;
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
my $osimagearch = $ref->{osarch};
|
|
my $netbootval = xCAT::Utils->lookupNetboot($ref->{osvers}, $ref->{osarch}, $ref->{imagetype});
|
|
my @validnodes;
|
|
foreach my $node (@nodes) {
|
|
unless ($noderescache) { next; }
|
|
unless ($nodetypecache) { next; }
|
|
unless ($nodehmcache) { next; }
|
|
my $noderesattribs = $noderescache->{$node}->[0];
|
|
my $nodetypeattribs = $nodetypecache->{$node}->[0];
|
|
my $nodehmattribs = $nodehmcache->{$node}->[0];
|
|
unless (defined($noderesattribs) and defined($noderesattribs->{'netboot'})) {
|
|
$rsp->{error}->[0] = "$node: Missing the 'netboot' attribute.";
|
|
$rsp->{errorcode}->[0] = 1;
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
next;
|
|
}
|
|
else {
|
|
unless ($netbootval =~ /$noderesattribs->{'netboot'}/i) {
|
|
$callback->({ warning => [ $node . ": $noderesattribs->{'netboot'} might be invalid when provisioning $OSIMAGE,valid options: \"$netbootval\". For more details see the 'netboot' description in the output of \"tabdump -d noderes\"." ] });
|
|
next;
|
|
}
|
|
}
|
|
|
|
unless (defined($nodetypeattribs) and defined($nodetypeattribs->{'arch'})) {
|
|
$rsp->{error}->[0] = "$node: 'arch' attribute not defined in 'nodetype' table.";
|
|
$rsp->{errorcode}->[0] = 1;
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
next;
|
|
}
|
|
my $nodetypearch = $nodetypeattribs->{'arch'};
|
|
if ($nodetypearch ne $osimagearch) {
|
|
unless(($nodetypearch =~ /^ppc64(le|el)?$/i) and ($osimagearch =~ /^ppc64(le|el)?$/i)){
|
|
$rsp->{error}->[0] = "$node: The value of 'arch' attribute of node does not match the 'osarch' attribute of osimage.";
|
|
$rsp->{errorcode}->[0] = 1;
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
next;
|
|
}
|
|
}
|
|
|
|
unless (defined($nodehmattribs) and defined($nodehmattribs->{'mgt'})) {
|
|
$rsp->{error}->[0] = "$node: 'mgt' attribute not defined in 'nodehm' table.";
|
|
$rsp->{errorcode}->[0] = 1;
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
next;
|
|
}
|
|
push @validnodes, $node;
|
|
}
|
|
|
|
#only provision the normal nodes
|
|
@nodes = @validnodes;
|
|
|
|
push @parameter, "osimage=$OSIMAGE";
|
|
|
|
}
|
|
elsif ($STATES) {
|
|
push @parameter, "$STATES";
|
|
}
|
|
else {
|
|
|
|
# No osimage specified, set the boot state of each node based on the nodetype.provmethod:
|
|
# 1) if nodetype.provmethod = [install/netboot/statelite],
|
|
# then output error message.
|
|
# 2) if nodetype.provmethod = <osimage>,
|
|
# then call "nodeset ... osimage"
|
|
|
|
# Group the nodes according to the nodetype.provmethod
|
|
my %tphash;
|
|
my $nodetypetable = xCAT::Table->new("nodetype");
|
|
my $nodetypecache = $nodetypetable->getNodesAttribs(\@nodes, ['provmethod']);
|
|
$nodetypetable->close();
|
|
foreach my $node (@nodes) {
|
|
unless ($nodetypecache) { next; }
|
|
my $nodetypeattribs = $nodetypecache->{$node}->[0];
|
|
unless (defined($nodetypeattribs) and defined($nodetypeattribs->{'provmethod'})) {
|
|
$rsp->{error}->[0] = "$node: 'provmethod' attribute not defined in 'nodetype' table.";
|
|
$rsp->{errorcode}->[0] = 1;
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
next;
|
|
}
|
|
else {
|
|
push(@{ $tphash{ $nodetypeattribs->{'provmethod'} } }, $node);
|
|
}
|
|
}
|
|
|
|
# Now for each group based on provmethod
|
|
my @validnodes;
|
|
foreach my $key (keys %tphash) {
|
|
$::RUNCMD_RC = 0;
|
|
my @pnnodes = @{ $tphash{$key} };
|
|
|
|
# If nodetype.provmethod = [install|netboot|statelite]
|
|
if ($key =~ /^(install|netboot|statelite)$/) {
|
|
my $rsp = {};
|
|
$rsp->{error}->[0] = "@pnnodes: The options 'install', 'netboot', and 'statelite' have been deprecated, use 'nodeset <noderange> osimage=<imagename>' instead.";
|
|
$rsp->{errorcode}->[0] = 1;
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
next;
|
|
}
|
|
|
|
# If nodetype.provmethod != [install|netboot|statelite]
|
|
else {
|
|
push @validnodes, @pnnodes;
|
|
}
|
|
}
|
|
|
|
#only provision the normal nodes
|
|
@nodes = @validnodes;
|
|
push @parameter, "osimage";
|
|
|
|
}
|
|
|
|
if ( grep( /osimage/, @parameter ) ) {
|
|
# Task is osimage, check --ignorekernelchk and --noupdateinitrd flags and set if needed
|
|
|
|
if ($ignorekernelchk) {
|
|
push @parameter, "--ignorekernelchk";
|
|
}
|
|
if ($noupdateinitrd) {
|
|
push @parameter, "--noupdateinitrd";
|
|
}
|
|
}
|
|
|
|
if (scalar(@nodes) == 0) {
|
|
$rsp->{error}->[0] = "No available nodes for provision.";
|
|
$rsp->{errorcode}->[0] = 1;
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
else {
|
|
$rsp->{data}->[0] = "Provision node(s): @nodes";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
}
|
|
|
|
%nodes = map { $_, 1 } @nodes;
|
|
|
|
# Run nodeset $noderange $parameter
|
|
my $res =
|
|
xCAT::Utils->runxcmd(
|
|
{
|
|
command => ["nodeset"],
|
|
node => \@nodes,
|
|
arg => \@parameter
|
|
},
|
|
$subreq, -1, 1);
|
|
|
|
$rc = $::RUNCMD_RC;
|
|
my $rsp = {};
|
|
if ($VERBOSE) {
|
|
my @cmd = "Run command: nodeset @nodes @parameter";
|
|
push @{ $rsp->{data} }, @cmd;
|
|
push @{ $rsp->{data} }, @$res;
|
|
xCAT::MsgUtils->message("D", $rsp, $callback);
|
|
}
|
|
|
|
unless ($rc == 0) {
|
|
# We got an error with the nodeset
|
|
my @successnodes;
|
|
my @failurenodes;
|
|
my @failuresns;
|
|
my $snfailure;
|
|
# copy into a temporary variable to avoid of circular reference
|
|
my @lines = @$res;
|
|
foreach my $line (@lines) {
|
|
$rsp->{data}->[0] = $line;
|
|
if($line =~ /The (\S+) can not be resolved/){
|
|
push @failurenodes,$1;
|
|
}
|
|
if ($line =~ /dhcp server is not running/) {
|
|
my $rsp = {};
|
|
$rsp->{error}->[0] = "Fatal error: dhcp server is not running";
|
|
$rsp->{errorcode}->[0] = 1;
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
if ($line =~ /Cannot wget/) {
|
|
# If nodeset returns error that runimage can not be downloaded by wget,
|
|
# display the error from nodeset (if not alredy displayed by VERBOSE above), stop processing and return.
|
|
unless ($VERBOSE) {
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
if ($line =~ /Unable to dispatch hierarchical sub-command to (\S+):3001/) {
|
|
$snfailure=1;
|
|
push @failuresns,$1;
|
|
}
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
}
|
|
|
|
# if only provision one node and failed nodeset, will exit the command
|
|
# instead of continue with rnetboot/rsetboot, rpower.
|
|
if ( (scalar(@nodes) == 1) ) {
|
|
#exit the command if it's service node failure
|
|
if ($snfailure) {
|
|
my $node = $nodes[0];
|
|
my $nrtab = xCAT::Table->new('noderes');
|
|
my $nrents = $nrtab->getNodeAttribs($node, [qw(servicenode)]);
|
|
my $nodesn = $nrents->{servicenode};
|
|
foreach my $tmpsn (@failuresns) {
|
|
if ($nodesn eq $tmpsn) {
|
|
$rsp->{error}->[0] = "Unable connect to Service node $nodesn, failed to run 'nodeset' against the node: @nodes";
|
|
$rsp->{errorcode}->[0] = 1;
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
}
|
|
} else {
|
|
$rsp->{error}->[0] = "Failed to run 'nodeset' against the node: @nodes";
|
|
$rsp->{errorcode}->[0] = 1;
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
foreach my $node (@failurenodes) {
|
|
delete $nodes{$node};
|
|
}
|
|
|
|
if (0+@failurenodes > 0) {
|
|
$rsp->{error}->[0] = "Failed to run 'nodeset' against the following nodes: @failurenodes";
|
|
$rsp->{errorcode}->[0] = 1;
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
}
|
|
@nodes = keys %nodes;
|
|
}
|
|
|
|
# Group the nodes according to the nodehm.mgt
|
|
my %hmhash;
|
|
foreach my $node (@nodes) {
|
|
unless ($nodehmcache) { next; }
|
|
my $nodehmattribs = $nodehmcache->{$node}->[0];
|
|
push(@{ $hmhash{ $nodehmattribs->{'mgt'} } }, $node);
|
|
}
|
|
|
|
# Now for each group based on mgt
|
|
foreach my $hmkey (keys %hmhash) {
|
|
$::RUNCMD_RC = 0;
|
|
my @nodes = @{ $hmhash{$hmkey} };
|
|
unless ($hmkey =~ /^(ipmi|blade|hmc|ivm|fsp|kvm|esx|rhevm|openbmc)$/) {
|
|
$rsp->{error}->[0] = "@nodes: rinstall only support nodehm.mgt type 'ipmi', 'blade', 'hmc', 'ivm', 'fsp', 'kvm', 'esx', 'rhevm', 'openbmc'.";
|
|
$rsp->{errorcode}->[0] = 1;
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
next;
|
|
}
|
|
if (($hmkey =~ /^ivm$/) or ($hmkey =~ /^fsp$/) or ($hmkey =~ /^hmc$/)) {
|
|
%nodes = map { $_, 1 } @nodes;
|
|
|
|
# Run rnetboot $noderange
|
|
my $res =
|
|
xCAT::Utils->runxcmd(
|
|
{
|
|
command => ["rnetboot"],
|
|
node => \@nodes
|
|
},
|
|
$subreq, -1, 1);
|
|
|
|
$rc = $::RUNCMD_RC;
|
|
if ($VERBOSE) {
|
|
my @cmd = "Run command: rnetboot @nodes";
|
|
push @{ $rsp->{data} }, @cmd;
|
|
push @{ $rsp->{data} }, @$res;
|
|
xCAT::MsgUtils->message("D", $rsp, $callback);
|
|
}
|
|
unless ($rc == 0) {
|
|
|
|
# We got an error with the rnetboot
|
|
my @failurenodes;
|
|
# copy into a temporary variable to avoid of circular reference
|
|
my @lines = @$res;
|
|
foreach my $line (@lines) {
|
|
$rsp->{data}->[0] = $line;
|
|
if ($line =~ /: Success/) {
|
|
my $successnode;
|
|
my $restline;
|
|
($successnode, $restline) = split(/:/, $line, 2);
|
|
$nodes{$successnode} = 0;
|
|
}
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
}
|
|
foreach my $node (@nodes) {
|
|
if ($nodes{$node} == 1) {
|
|
push @failurenodes, $node;
|
|
}
|
|
}
|
|
if (0+@failurenodes > 0) {
|
|
$rsp->{error}->[0] = "Failed to run 'rnetboot' against the following nodes: @failurenodes";
|
|
$rsp->{errorcode}->[0] = 1;
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
# Call "rsetboot" to set the boot order of the nodehm.mgt=ipmi/openbmc nodes
|
|
if ($hmkey =~ /^(ipmi|openbmc)$/) {
|
|
%nodes = map { $_, 1 } @nodes;
|
|
|
|
# Run rsetboot $noderange net
|
|
my @rsetbootarg;
|
|
push @rsetbootarg, "net";
|
|
if ($UEFIMODE) {
|
|
push @rsetbootarg, "-u";
|
|
}
|
|
|
|
my %req=(
|
|
command => ["rsetboot"],
|
|
node => \@nodes,
|
|
arg => \@rsetbootarg
|
|
);
|
|
|
|
#TODO: When OPENBMC support is finished, this line should be removed
|
|
if($hmkey =~ /^openbmc$/){
|
|
$req{environment}{XCAT_OPENBMC_DEVEL}= "YES";
|
|
}
|
|
|
|
my $res =
|
|
xCAT::Utils->runxcmd(
|
|
\%req,
|
|
$subreq, -1, 1);
|
|
|
|
|
|
$rc = $::RUNCMD_RC;
|
|
my $rsp = {};
|
|
if ($VERBOSE) {
|
|
my @cmd = "Run command: rsetboot @nodes @rsetbootarg";
|
|
push @{ $rsp->{data} }, @cmd;
|
|
push @{ $rsp->{data} }, @$res;
|
|
xCAT::MsgUtils->message("D", $rsp, $callback);
|
|
}
|
|
unless ($rc == 0) {
|
|
# We got an error with the rsetboot
|
|
my @successnodes;
|
|
my @failurenodes;
|
|
# copy into a temporary variable to avoid of circular reference
|
|
my @lines = @$res;
|
|
foreach my $line (@lines) {
|
|
$rsp->{data}->[0] = $line;
|
|
if ($line =~ /: Network/) {
|
|
my $successnode;
|
|
my $restline;
|
|
($successnode, $restline) = split(/:/, $line, 2);
|
|
$nodes{$successnode} = 0;
|
|
push @successnodes, $successnode;
|
|
}
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
}
|
|
foreach my $node (@nodes) {
|
|
if ($nodes{$node} == 1) {
|
|
push @failurenodes, $node;
|
|
}
|
|
}
|
|
my $rsp = {};
|
|
if (0+@failurenodes > 0) {
|
|
$rsp->{error}->[0] = "Failed to run 'rsetboot' against the following nodes: @failurenodes";
|
|
$rsp->{errorcode}->[0] = 1;
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
}
|
|
@nodes = @successnodes;
|
|
}
|
|
}
|
|
|
|
# Call "rpower" to start the node provision process
|
|
%nodes = map { $_, 1 } @nodes;
|
|
|
|
# Run rpower $noderange boot
|
|
my @rpowerarg;
|
|
push @rpowerarg, "boot";
|
|
my %req=(
|
|
command => ["rpower"],
|
|
node => \@nodes,
|
|
arg => \@rpowerarg
|
|
);
|
|
|
|
my $res =
|
|
xCAT::Utils->runxcmd(
|
|
\%req,
|
|
$subreq, -1, 1);
|
|
|
|
$rc = $::RUNCMD_RC;
|
|
if ($VERBOSE) {
|
|
my @cmd = "Run command: rpower @nodes @rpowerarg";
|
|
push @{ $rsp->{data} }, @cmd;
|
|
push @{ $rsp->{data} }, @$res;
|
|
xCAT::MsgUtils->message("D", $rsp, $callback);
|
|
}
|
|
unless ($rc == 0) {
|
|
# We got an error with the rpower
|
|
my @failurenodes;
|
|
# copy into a temporary variable to avoid of circular reference
|
|
my @lines = @$res;
|
|
foreach my $line (@lines) {
|
|
$rsp->{data}->[0] = $line;
|
|
if (($line =~ /: on reset/) or ($line =~ /: off on/)) {
|
|
my $successnode;
|
|
my $restline;
|
|
($successnode, $restline) = split(/:/, $line, 2);
|
|
$nodes{$successnode} = 0;
|
|
}
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
}
|
|
foreach my $node (@nodes) {
|
|
if ($nodes{$node} == 1) {
|
|
push @failurenodes, $node;
|
|
}
|
|
}
|
|
my $rsp = {};
|
|
if (0+@failurenodes > 0) {
|
|
$rsp->{error}->[0] = "Failed to run 'rpower' against the following nodes: @failurenodes";
|
|
$rsp->{errorcode}->[0] = 1;
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#-------------------------------------------------------
|
|
|
|
=head3 Usage
|
|
|
|
|
|
=cut
|
|
|
|
#-------------------------------------------------------
|
|
sub usage {
|
|
my $command = shift;
|
|
my $callback = shift;
|
|
my $rsp = {};
|
|
$rsp->{data}->[0] = "Usage:";
|
|
$rsp->{data}->[1] = " $command <noderange> [boot | shell | runcmd=<command>] [-c|--console] [-u|--uefimode] [-V|--verbose]";
|
|
$rsp->{data}->[2] = " $command <noderange> [osimage[=<imagename>]] [--noupdateinitrd] [--ignorekernelchk] [-c|--console] [-u|--uefimode] [-V|--verbose]";
|
|
$rsp->{data}->[3] = " $command <noderange> runimage=<task>";
|
|
$rsp->{data}->[4] = " $command [-h|--help|-v|--version]";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
}
|
|
|
|
|
|
|
|
1;
|