xcat-core/xCAT-server/lib/xcat/plugins/updatenode.pm
2008-11-09 03:20:21 +00:00

299 lines
7.8 KiB
Perl

#!/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;
use xCAT::GlobalDef;
use xCAT_monitoring::monitorctrl;
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 {
updatenode => "updatenode",
updatenodestat => "updatenode"};
}
#-------------------------------------------------------
=head3 preprocess_request
Check and setup for hierarchy
=cut
#-------------------------------------------------------
sub preprocess_request
{
my $request = shift;
my $callback = shift;
my $command = $request->{command}->[0];
if ($request->{_xcatdest}) { return [$request]; } #exit if preprocessed
my @requests=();
if ($command eq "updatenode")
{
return preprocess_updatenode($request, $callback);
} elsif ($command eq "updatenodestat") {
return [$request];
}
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;
my $command = $request->{command}->[0];
my $localhostname=hostname();
if ($command eq "updatenode") {
return updatenode($request, $callback);
} elsif ($command eq "updatenodestat") {
return updatenodestat($request, $callback);
} else {
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
[noderange [postscripts]]
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;
my $args=$request->{arg};
my @requests=();
# subroutine to display the usage
sub updatenode_usage
{
my $cb=shift;
my $rsp={};
$rsp->{data}->[0]= "Usage:";
$rsp->{data}->[1]= " updatenode <noderange> [posts]";
$rsp->{data}->[2]= " updatenode [-h|--help|-v|--version]";
$rsp->{data}->[3]= " noderange is a list of nodes or groups.";
$rsp->{data}->[4]= " posts is a comma separated list of postscript names.";
$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,
'v|version' => \$::VERSION))
{
&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;
}
my $nodes = $request->{node};
if (!$nodes) {
&updatenode_usage($callback);
return \@requests;;
}
my @nodes=@$nodes;
my $postscripts;
if (@nodes == 0) { return \@requests; }
if (@ARGV > 0) {
$postscripts=$ARGV[0];
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;
}
}
}
# find service nodes for requested nodes
# build an individual request for each service node
my $sn = xCAT::Utils->get_ServiceNode(\@nodes, "xcat", "MN");
# 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;
}
return \@requests;
}
#--------------------------------------------------------------------------------
=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;
my $postscripts="";
if (($request->{postscripts}) && ($request->{postscripts}->[0])) { $postscripts=$request->{postscripts}->[0];}
my $nodes =$request->{node};
my $localhostname=hostname();
my $nodestring=join(',', @$nodes);
#print "postscripts=$postscripts, nodestring=$nodestring\n";
if ($nodestring) {
my $cmd;
if (xCAT::Utils->isLinux()) {
$cmd="XCATBYPASS=Y $::XCATROOT/bin/xdsh $nodestring -s -e /install/postscripts/xcatdsklspost 1 $postscripts 2>&1";
}
else {
$cmd="XCATBYPASS=Y $::XCATROOT/bin/xdsh $nodestring -s -e /install/postscripts/xcataixpost 1 $postscripts 2>&1";
}
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);
}
}
return 0;
}
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);
}
xCAT_monitoring::monitorctrl::setNodeStatusAttributes(\%node_status, 1);
}
return 0;
}