2008-09-08 18:54:30 +00:00
|
|
|
#!/usr/bin/env perl
|
|
|
|
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
|
|
|
|
|
|
|
|
package xCAT_plugin::updatenode;
|
|
|
|
BEGIN
|
|
|
|
{
|
|
|
|
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
|
|
|
|
}
|
|
|
|
use lib "$::XCATROOT/lib/perl";
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
use xCAT::Table;
|
|
|
|
use xCAT::Schema;
|
|
|
|
use Data::Dumper;
|
|
|
|
use xCAT::Utils;
|
|
|
|
use Getopt::Long;
|
|
|
|
use xCAT::GlobalDef;
|
|
|
|
use Sys::Hostname;
|
2008-09-25 03:04:56 +00:00
|
|
|
use xCAT::GlobalDef;
|
|
|
|
use xCAT_monitoring::monitorctrl;
|
2008-09-08 18:54:30 +00:00
|
|
|
|
|
|
|
1;
|
|
|
|
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head1 xCAT_plugin:updatenode
|
|
|
|
=head2 Package Description
|
|
|
|
xCAT plug-in module. It handles the updatenode command.
|
|
|
|
=cut
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#--------------------------------------------------------------------------------
|
|
|
|
=head3 handled_commands
|
|
|
|
It returns a list of commands handled by this plugin.
|
|
|
|
Arguments:
|
|
|
|
none
|
|
|
|
Returns:
|
|
|
|
a list of commands.
|
|
|
|
=cut
|
|
|
|
#--------------------------------------------------------------------------------
|
|
|
|
sub handled_commands
|
|
|
|
{
|
|
|
|
return {
|
2008-09-25 03:04:56 +00:00
|
|
|
updatenode => "updatenode",
|
|
|
|
updatenodestat => "updatenode"};
|
2008-09-08 18:54:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#-------------------------------------------------------
|
|
|
|
=head3 preprocess_request
|
|
|
|
Check and setup for hierarchy
|
|
|
|
=cut
|
|
|
|
#-------------------------------------------------------
|
|
|
|
sub preprocess_request
|
|
|
|
{
|
|
|
|
my $request = shift;
|
|
|
|
my $callback = shift;
|
2009-06-04 15:33:44 +00:00
|
|
|
my $subreq = shift;
|
2008-09-08 18:54:30 +00:00
|
|
|
my $command = $request->{command}->[0];
|
|
|
|
if ($request->{_xcatdest}) { return [$request]; } #exit if preprocessed
|
|
|
|
my @requests=();
|
|
|
|
|
|
|
|
if ($command eq "updatenode")
|
|
|
|
{
|
2009-06-04 15:33:44 +00:00
|
|
|
return preprocess_updatenode($request, $callback, $subreq);
|
2008-09-25 03:04:56 +00:00
|
|
|
} elsif ($command eq "updatenodestat") {
|
|
|
|
return [$request];
|
|
|
|
}
|
2008-09-08 18:54:30 +00:00
|
|
|
else {
|
|
|
|
my $rsp={};
|
|
|
|
$rsp->{data}->[0]= "unsupported command: $command.";
|
|
|
|
$callback->($rsp);
|
|
|
|
return \@requests;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#--------------------------------------------------------------------------------
|
|
|
|
=head3 process_request
|
|
|
|
It processes the monitoring control commands.
|
|
|
|
Arguments:
|
|
|
|
request -- a hash table which contains the command name and the arguments.
|
|
|
|
callback -- a callback pointer to return the response to.
|
|
|
|
Returns:
|
|
|
|
0 for success. The output is returned through the callback pointer.
|
|
|
|
1. for unsuccess. The error messages are returns through the callback pointer.
|
|
|
|
=cut
|
|
|
|
#--------------------------------------------------------------------------------
|
|
|
|
sub process_request
|
|
|
|
{
|
|
|
|
my $request = shift;
|
|
|
|
my $callback = shift;
|
2009-06-04 15:33:44 +00:00
|
|
|
my $subreq = shift;
|
2008-09-08 18:54:30 +00:00
|
|
|
my $command = $request->{command}->[0];
|
|
|
|
my $localhostname=hostname();
|
|
|
|
|
2008-09-25 03:04:56 +00:00
|
|
|
if ($command eq "updatenode") {
|
2009-06-04 15:33:44 +00:00
|
|
|
return updatenode($request, $callback, $subreq);
|
2008-09-25 03:04:56 +00:00
|
|
|
} elsif ($command eq "updatenodestat") {
|
|
|
|
return updatenodestat($request, $callback);
|
|
|
|
} else {
|
2008-09-08 18:54:30 +00:00
|
|
|
my $rsp={};
|
|
|
|
$rsp->{data}->[0]= "$localhostname: unsupported command: $command.";
|
|
|
|
$callback->($rsp);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#--------------------------------------------------------------------------------
|
|
|
|
=head3 preprocess_updatenode
|
|
|
|
This function checks for the syntax of the updatenode command
|
|
|
|
and distribute the command to the right server.
|
|
|
|
Arguments:
|
|
|
|
request - the request. The request->{arg} is of the format:
|
|
|
|
[-h|--help|-v|--version] or
|
2009-06-04 15:33:44 +00:00
|
|
|
[noderange [-s | -S] [postscripts]]
|
2008-09-08 18:54:30 +00:00
|
|
|
callback - the pointer to the callback function.
|
|
|
|
Returns:
|
|
|
|
A pointer to an array of requests.
|
|
|
|
=cut
|
|
|
|
#--------------------------------------------------------------------------------
|
|
|
|
sub preprocess_updatenode {
|
|
|
|
my $request = shift;
|
|
|
|
my $callback = shift;
|
2009-06-04 15:33:44 +00:00
|
|
|
my $subreq = shift;
|
2008-09-08 18:54:30 +00:00
|
|
|
my $args=$request->{arg};
|
|
|
|
my @requests=();
|
|
|
|
|
|
|
|
# subroutine to display the usage
|
|
|
|
sub updatenode_usage
|
|
|
|
{
|
|
|
|
my $cb=shift;
|
|
|
|
my $rsp={};
|
|
|
|
$rsp->{data}->[0]= "Usage:";
|
2009-06-04 15:33:44 +00:00
|
|
|
$rsp->{data}->[1]= " updatenode <noderange> [-s | -S] [posts]";
|
2008-09-11 04:43:33 +00:00
|
|
|
$rsp->{data}->[2]= " updatenode [-h|--help|-v|--version]";
|
2008-09-08 20:59:07 +00:00
|
|
|
$rsp->{data}->[3]= " noderange is a list of nodes or groups.";
|
|
|
|
$rsp->{data}->[4]= " posts is a comma separated list of postscript names.";
|
2008-09-08 18:54:30 +00:00
|
|
|
$rsp->{data}->[5]= " if omitted, all the postscripts will be run.";
|
|
|
|
$cb->($rsp);
|
|
|
|
}
|
|
|
|
|
|
|
|
@ARGV=();
|
|
|
|
if ($args) {
|
|
|
|
@ARGV=@{$args};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# parse the options
|
|
|
|
Getopt::Long::Configure("bundling");
|
|
|
|
Getopt::Long::Configure("no_pass_through");
|
|
|
|
if(!GetOptions(
|
|
|
|
'h|help' => \$::HELP,
|
2009-06-04 15:33:44 +00:00
|
|
|
'v|version' => \$::VERSION,
|
|
|
|
's' => \$::SYNCSN,
|
|
|
|
'S' => \$::SKIPSYNCFILE ))
|
2008-09-08 18:54:30 +00:00
|
|
|
{
|
|
|
|
&updatenode_usage($callback);
|
|
|
|
return \@requests;;
|
|
|
|
}
|
|
|
|
|
|
|
|
# display the usage if -h or --help is specified
|
|
|
|
if ($::HELP) {
|
|
|
|
&updatenode_usage($callback);
|
|
|
|
return \@requests;;
|
|
|
|
}
|
|
|
|
|
|
|
|
# display the version statement if -v or --verison is specified
|
|
|
|
if ($::VERSION)
|
|
|
|
{
|
|
|
|
my $rsp={};
|
|
|
|
$rsp->{data}->[0]= xCAT::Utils->Version();
|
|
|
|
$callback->($rsp);
|
|
|
|
return \@requests;
|
|
|
|
}
|
|
|
|
|
2008-09-08 20:59:07 +00:00
|
|
|
my $nodes = $request->{node};
|
|
|
|
if (!$nodes) {
|
|
|
|
&updatenode_usage($callback);
|
|
|
|
return \@requests;;
|
2008-09-08 18:54:30 +00:00
|
|
|
}
|
|
|
|
|
2008-09-08 20:59:07 +00:00
|
|
|
my @nodes=@$nodes;
|
|
|
|
my $postscripts;
|
2008-09-08 18:54:30 +00:00
|
|
|
|
|
|
|
if (@nodes == 0) { return \@requests; }
|
|
|
|
|
2008-09-08 20:59:07 +00:00
|
|
|
if (@ARGV > 0) {
|
|
|
|
$postscripts=$ARGV[0];
|
2008-09-08 18:54:30 +00:00
|
|
|
my @posts=split(',',$postscripts);
|
|
|
|
foreach (@posts) {
|
|
|
|
if ( ! -e "/install/postscripts/$_") {
|
|
|
|
my $rsp={};
|
|
|
|
$rsp->{data}->[0]= "The postcript /install/postscripts/$_ does not exist.";
|
|
|
|
$callback->($rsp);
|
|
|
|
return \@requests;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-08 20:59:07 +00:00
|
|
|
# find service nodes for requested nodes
|
|
|
|
# build an individual request for each service node
|
|
|
|
my $sn = xCAT::Utils->get_ServiceNode(\@nodes, "xcat", "MN");
|
|
|
|
|
2009-06-04 15:33:44 +00:00
|
|
|
# If -s argument specified, sync files to the service node firstly
|
|
|
|
if ($::SYNCSN) {
|
|
|
|
my @MNnodeinfo = xCAT::Utils->determinehostname;
|
|
|
|
my $MNnodename = pop @MNnodeinfo; # hostname
|
|
|
|
my @MNnodeipaddr = @MNnodeinfo; # ipaddresses
|
|
|
|
|
|
|
|
my $node_syncfile = xCAT::Utils->getsynclistfile($nodes);
|
|
|
|
my %syncfile_sn = ();
|
|
|
|
foreach my $snkey (keys %$sn)
|
|
|
|
{
|
|
|
|
# exclude the Management node
|
|
|
|
if (grep(/$snkey/, @MNnodeipaddr)) {
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
my @synclists = ();
|
|
|
|
# Figure out the synclist files for the service node
|
|
|
|
foreach my $node (@{$sn->{$snkey}}) {
|
|
|
|
my $synclist = $$node_syncfile{$node};
|
|
|
|
|
|
|
|
unless ($synclist) {
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
if (! grep /\Q$synclist\E/, @synclists) {
|
|
|
|
push @synclists, $synclist;
|
|
|
|
push @{$syncfile_sn{$synclist}}, $node;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# If there are multiple synclist files for certain SN,
|
|
|
|
# the synclist files maybe have conflicted content, so
|
|
|
|
# display an warning message
|
|
|
|
if ($#synclists > 0) {
|
|
|
|
my $rsp = {};
|
|
|
|
my $files = join(',', @synclists);
|
|
|
|
$rsp->{data}->[0]= "Warning: The Service Node $snkey will be synced by following synclist files: $files";
|
|
|
|
$callback->($rsp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach my $syncfile (keys %syncfile_sn) {
|
|
|
|
my $arg = ["-s", "-F", "$syncfile"];
|
|
|
|
my $env = ["RSYNCSN=yes", "DSH_RSYNC_FILE=$syncfile"];
|
|
|
|
$subreq->({command=>['xdcp'], node=>$syncfile_sn{$syncfile}, arg=>$arg, env=>$env}, $callback);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-08 20:59:07 +00:00
|
|
|
# build each request for each service node
|
|
|
|
foreach my $snkey (keys %$sn)
|
|
|
|
{
|
|
|
|
my $reqcopy = {%$request};
|
|
|
|
$reqcopy->{node} = $sn->{$snkey};
|
|
|
|
$reqcopy->{'_xcatdest'} = $snkey;
|
|
|
|
$reqcopy->{postscripts} = [$postscripts];
|
|
|
|
push @requests, $reqcopy;
|
2008-09-08 18:54:30 +00:00
|
|
|
}
|
|
|
|
return \@requests;
|
2008-09-08 20:59:07 +00:00
|
|
|
|
2008-09-08 18:54:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#--------------------------------------------------------------------------------
|
|
|
|
=head3 updatenode
|
|
|
|
This function implements the updatenode command.
|
|
|
|
Arguments:
|
|
|
|
request - the request.
|
|
|
|
callback - the pointer to the callback function.
|
|
|
|
Returns:
|
|
|
|
0 for success. The output is returned through the callback pointer.
|
|
|
|
1. for unsuccess. The error messages are returns through the callback pointer.
|
|
|
|
=cut
|
|
|
|
#--------------------------------------------------------------------------------
|
|
|
|
sub updatenode {
|
|
|
|
my $request = shift;
|
|
|
|
my $callback = shift;
|
2009-06-04 15:33:44 +00:00
|
|
|
my $subreq = shift;
|
2008-09-08 18:54:30 +00:00
|
|
|
my $postscripts="";
|
|
|
|
if (($request->{postscripts}) && ($request->{postscripts}->[0])) { $postscripts=$request->{postscripts}->[0];}
|
2008-09-08 20:59:07 +00:00
|
|
|
my $nodes =$request->{node};
|
2008-09-08 18:54:30 +00:00
|
|
|
my $localhostname=hostname();
|
|
|
|
|
2009-06-04 15:33:44 +00:00
|
|
|
# if not specifying -S, do the sync file operation
|
|
|
|
unless ($::SKIPSYNCFILE) {
|
|
|
|
my %syncfile_node = ();
|
|
|
|
my $node_syncfile = xCAT::Utils->getsynclistfile($nodes);
|
|
|
|
foreach my $node (@$nodes) {
|
|
|
|
my $synclist = $$node_syncfile{$node};
|
|
|
|
|
|
|
|
if ($synclist) {
|
|
|
|
push @{$syncfile_node{$synclist}}, $node;
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach my $synclist (keys %syncfile_node) {
|
|
|
|
my $args = ["-F", "$synclist"];
|
|
|
|
my $env = ["DSH_RSYNC_FILE=$synclist"];
|
|
|
|
$subreq->({command=>['xdcp'], node=>$syncfile_node{$synclist}, arg=>$args, env=>$env}, $callback);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-08 18:54:30 +00:00
|
|
|
my $nodestring=join(',', @$nodes);
|
2008-09-26 23:07:45 +00:00
|
|
|
#print "postscripts=$postscripts, nodestring=$nodestring\n";
|
2008-09-08 18:54:30 +00:00
|
|
|
|
|
|
|
if ($nodestring) {
|
2008-11-09 03:20:21 +00:00
|
|
|
my $cmd;
|
2008-09-11 04:43:33 +00:00
|
|
|
if (xCAT::Utils->isLinux()) {
|
2008-11-09 03:20:21 +00:00
|
|
|
$cmd="XCATBYPASS=Y $::XCATROOT/bin/xdsh $nodestring -s -e /install/postscripts/xcatdsklspost 1 $postscripts 2>&1";
|
2008-09-11 04:43:33 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-03-31 17:41:15 +00:00
|
|
|
$cmd="XCATBYPASS=Y $::XCATROOT/bin/xdsh $nodestring -s -e /install/postscripts/xcataixpost -c 1 $postscripts 2>&1";
|
2008-11-09 03:20:21 +00:00
|
|
|
}
|
|
|
|
if (! open (CMD, "$cmd |")) {
|
|
|
|
my $rsp={};
|
|
|
|
$rsp->{data}->[0]= "Cannot run command $cmd";
|
|
|
|
$callback->($rsp);
|
|
|
|
} else {
|
|
|
|
while (<CMD>) {
|
|
|
|
my $rsp={};
|
|
|
|
$rsp->{data}->[0]= "$_";
|
|
|
|
$callback->($rsp);
|
|
|
|
}
|
|
|
|
close(CMD);
|
2008-09-11 04:43:33 +00:00
|
|
|
}
|
2008-09-08 18:54:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-09-25 03:04:56 +00:00
|
|
|
sub updatenodestat {
|
|
|
|
my $request = shift;
|
|
|
|
my $callback = shift;
|
|
|
|
my @nodes=();
|
|
|
|
my @args=();
|
|
|
|
if (ref($request->{node})) {
|
|
|
|
@nodes = @{$request->{node}};
|
|
|
|
} else {
|
|
|
|
if ($request->{node}) { @nodes = ($request->{node}); }
|
|
|
|
}
|
|
|
|
if (ref($request->{arg})) {
|
|
|
|
@args=@{$request->{arg}};
|
|
|
|
} else {
|
|
|
|
@args=($request->{arg});
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((@nodes>0) && (@args>0)) {
|
|
|
|
my %node_status=();
|
|
|
|
my $stat=$args[0];
|
|
|
|
$node_status{$stat}=[];
|
|
|
|
foreach my $node (@nodes) {
|
|
|
|
my $pa=$node_status{$stat};
|
|
|
|
push(@$pa, $node);
|
|
|
|
}
|
2008-11-09 04:01:11 +00:00
|
|
|
xCAT_monitoring::monitorctrl::setNodeStatusAttributes(\%node_status, 1);
|
2008-09-25 03:04:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-09-08 18:54:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
|