433 lines
11 KiB
Perl
433 lines
11 KiB
Perl
|
# IBM(c) 2010 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||
|
#-------------------------------------------------------
|
||
|
|
||
|
=head1
|
||
|
xCAT plugin package to handle xdsh
|
||
|
|
||
|
Supported command:
|
||
|
nodenetconn
|
||
|
ipforward (internal command)
|
||
|
|
||
|
=cut
|
||
|
|
||
|
#-------------------------------------------------------
|
||
|
package xCAT_plugin::snmove;
|
||
|
BEGIN
|
||
|
{
|
||
|
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
|
||
|
}
|
||
|
use lib "$::XCATROOT/lib/perl";
|
||
|
use strict;
|
||
|
use xCAT::Table;
|
||
|
use xCAT::Utils;
|
||
|
use xCAT::NetworkUtils;
|
||
|
use xCAT::MsgUtils;
|
||
|
use Getopt::Long;
|
||
|
use xCAT::NodeRange;
|
||
|
use Data::Dumper;
|
||
|
|
||
|
|
||
|
1;
|
||
|
|
||
|
#-------------------------------------------------------
|
||
|
|
||
|
=head3 handled_commands
|
||
|
|
||
|
Return list of commands handled by this plugin
|
||
|
|
||
|
=cut
|
||
|
|
||
|
#-------------------------------------------------------
|
||
|
|
||
|
sub handled_commands
|
||
|
{
|
||
|
return {
|
||
|
snmove => "snmove",
|
||
|
};
|
||
|
}
|
||
|
|
||
|
|
||
|
#-------------------------------------------------------
|
||
|
|
||
|
=head3 preprocess_request
|
||
|
|
||
|
Preprocess the command
|
||
|
|
||
|
=cut
|
||
|
|
||
|
#-------------------------------------------------------
|
||
|
sub preprocess_request
|
||
|
{
|
||
|
|
||
|
my $request = shift;
|
||
|
my $callback = shift;
|
||
|
my $sub_req = shift;
|
||
|
my $command = $request->{command}->[0];
|
||
|
my $args = $request->{arg};
|
||
|
|
||
|
#if already preprocessed, go straight to request
|
||
|
if ((defined($request->{_xcatpreprocessed}))
|
||
|
&& ($request->{_xcatpreprocessed}->[0] == 1))
|
||
|
{
|
||
|
return [$request];
|
||
|
}
|
||
|
|
||
|
#let process _request to handle it
|
||
|
my $reqcopy = {%$request};
|
||
|
$reqcopy->{_xcatpreprocessed}->[0] = 1;
|
||
|
return [$reqcopy];
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
#-------------------------------------------------------
|
||
|
|
||
|
=head3 process_request
|
||
|
|
||
|
Process the command
|
||
|
|
||
|
=cut
|
||
|
|
||
|
#-------------------------------------------------------
|
||
|
sub process_request
|
||
|
{
|
||
|
my $request = shift;
|
||
|
my $callback = shift;
|
||
|
my $sub_req = shift;
|
||
|
|
||
|
my $command = $request->{command}->[0];
|
||
|
my $args = $request->{arg};
|
||
|
# parse the options
|
||
|
@ARGV=();
|
||
|
if ($args) {
|
||
|
@ARGV=@{$args};
|
||
|
}
|
||
|
Getopt::Long::Configure("bundling");
|
||
|
Getopt::Long::Configure("no_pass_through");
|
||
|
|
||
|
my $SN1;
|
||
|
my $SN1N;
|
||
|
my $SN2;
|
||
|
my $SN2N;
|
||
|
if(!GetOptions(
|
||
|
'h|help' => \$::HELP,
|
||
|
'v|version' => \$::VERSION,
|
||
|
's|source=s' => \$SN1,
|
||
|
'S|sourcen=s' => \$SN1N,
|
||
|
'd|dest=s' => \$SN2,
|
||
|
'D|destn=s' => \$SN2N,
|
||
|
'i|ignorenodes' => \$::IGNORE,
|
||
|
))
|
||
|
{
|
||
|
&usage($callback);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
# display the usage if -h or --help is specified
|
||
|
if ($::HELP) {
|
||
|
&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;
|
||
|
}
|
||
|
|
||
|
#-d must be specified
|
||
|
if ((!$SN2) || (!$SN2N)) {
|
||
|
my $rsp={};
|
||
|
$rsp->{data}->[0]="The destination service node must be specified using -d and -D flags.\n";
|
||
|
$callback->($rsp);
|
||
|
&usage($callback);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
if (@ARGV > 1) {
|
||
|
my $rsp={};
|
||
|
$rsp->{data}->[0]="Too manay paramters.\n";
|
||
|
$callback->($rsp);
|
||
|
&usage($callback);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
if ((@ARGV == 0) && (!$SN1)) {
|
||
|
my $rsp={};
|
||
|
$rsp->{data}->[0]="A node range or the source service node must be specified.\n";
|
||
|
$callback->($rsp);
|
||
|
&usage($callback);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
my @nodes=();
|
||
|
if (@ARGV == 1) {
|
||
|
my $nr=$ARGV[0];
|
||
|
@nodes = noderange($nr);
|
||
|
if (nodesmissed) {
|
||
|
my $rsp={};
|
||
|
$rsp->{data}->[0]= "Invalid nodes in noderange:".join(',',nodesmissed);
|
||
|
$callback->($rsp);
|
||
|
return 1;
|
||
|
}
|
||
|
} else {
|
||
|
#get all the nodes that uses SN1 as the primary service nodes
|
||
|
my $pn_hash= xCAT::Utils->getSNandNodes();
|
||
|
foreach my $snlist (keys %$pn_hash) {
|
||
|
if (($snlist =~ /^$SN1$/) || ($snlist =~ /^$SN1\,/)) {
|
||
|
push(@nodes, @{$pn_hash->{$snlist}});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#now do some database changes
|
||
|
my $rsp={};
|
||
|
$rsp->{data}->[0]= "Changing database setting for nodes: @nodes";
|
||
|
$callback->($rsp);
|
||
|
|
||
|
my $nrtab=xCAT::Table->new('noderes',-create=>1);
|
||
|
my $nodehash={};
|
||
|
if ($nrtab) {
|
||
|
$nodehash = $nrtab->getNodesAttribs(\@nodes, ['servicenode', 'tftpserver', 'nfsserver', 'monserver', 'xcatmaster']);
|
||
|
} else {
|
||
|
my $rsp={};
|
||
|
$rsp->{data}->[0]= "Cannot open noderes table\n";
|
||
|
$callback->($rsp);
|
||
|
return 1;
|
||
|
}
|
||
|
my $sn_hash={};
|
||
|
my $old_node_hash={};
|
||
|
if ($nodehash) {
|
||
|
#print Dumper($nodehash);
|
||
|
foreach my $node (@nodes) {
|
||
|
foreach my $rec (@{$nodehash->{$node}}) {
|
||
|
if (!$rec) { next; }
|
||
|
my $sn1;
|
||
|
my $sn1n;
|
||
|
if ($SN1N) { $sn1n=$SN1N; }
|
||
|
elsif ($rec->{'xcatmaster'}) { $sn1n=$rec->{'xcatmaster'};}
|
||
|
else {
|
||
|
my $rsp={};
|
||
|
$rsp->{error}->[0]= "xcatmaster is not set for some nodes.";
|
||
|
$callback->($rsp);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
my $snlist=$rec->{'servicenode'};
|
||
|
my @sn_a=split(',', $snlist);
|
||
|
if ($SN1) { $sn1=$SN1; }
|
||
|
else { $sn1=$sn_a[0];}
|
||
|
my @sn_temp=grep(!/^$SN2$/, @sn_a);
|
||
|
unshift(@sn_temp,$SN2);
|
||
|
my $t=join(',', @sn_temp);
|
||
|
|
||
|
$sn_hash->{$node}->{'servicenode'}=$t;
|
||
|
$sn_hash->{$node}->{'xcatmaster'}=$SN2N;
|
||
|
$old_node_hash->{$node}->{'oldsn'}=$sn1;
|
||
|
$old_node_hash->{$node}->{'oldmaster'}=$sn1n;
|
||
|
|
||
|
if ($rec->{'tftpserver'} && ($rec->{'tftpserver'} eq $sn1n)) {
|
||
|
$sn_hash->{$node}->{'tftpserver'}=$SN2N;
|
||
|
}
|
||
|
if ($rec->{'nfsserver'} && ($rec->{'nfsserver'} eq $sn1n)) {
|
||
|
$sn_hash->{$node}->{'nfsserver'}=$SN2N;
|
||
|
}
|
||
|
if ($rec->{'monserver'}) {
|
||
|
my @tmp_a=split(',', $rec->{'monserver'});
|
||
|
if ((@tmp_a > 1) && ($tmp_a[1] eq $sn1n)) {
|
||
|
$sn_hash->{$node}->{'monserver'}="$SN2,$SN2N";
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (keys(%$sn_hash) > 0) {
|
||
|
$nrtab->setNodesAttribs($sn_hash);
|
||
|
}
|
||
|
#print "noderes=" . Dumper($old_node_hash);
|
||
|
}
|
||
|
|
||
|
|
||
|
#handle conserver
|
||
|
my $nhtab=xCAT::Table->new('nodehm',-create=>1);
|
||
|
my $nodehmhash={};
|
||
|
if ($nhtab) {
|
||
|
$nodehmhash = $nhtab->getNodesAttribs(\@nodes, ['conserver']);
|
||
|
} else {
|
||
|
my $rsp={};
|
||
|
$rsp->{data}->[0]= "Cannot open nodehm table\n";
|
||
|
$callback->($rsp);
|
||
|
return 1;
|
||
|
}
|
||
|
# print Dumper($nodehmhash);
|
||
|
my $sn_hash1={};
|
||
|
if ($nodehmhash) {
|
||
|
foreach my $node (@nodes) {
|
||
|
foreach my $rec (@{$nodehmhash->{$node}}) {
|
||
|
if ($rec and $rec->{'conserver'} and ($rec->{'conserver'} eq $old_node_hash->{$node}->{'oldsn'})) {
|
||
|
$sn_hash1->{$node}->{'conserver'}=$SN2;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (keys(%$sn_hash1) > 0) {
|
||
|
$nhtab->setNodesAttribs($sn_hash1);
|
||
|
}
|
||
|
#print "nodehm=" . Dumper($sn_hash1);
|
||
|
}
|
||
|
|
||
|
#change the services
|
||
|
#conserver
|
||
|
my @nodes_con=keys(%$sn_hash1);
|
||
|
if (@nodes_con > 0) {
|
||
|
my $rsp={};
|
||
|
$rsp->{data}->[0]= "Running makeconservercf " . join(',', @nodes_con);
|
||
|
$callback->($rsp);
|
||
|
my $ret = xCAT::Utils->runxcmd({ command => ['makeconservercf'],
|
||
|
node => \@nodes_con,
|
||
|
},
|
||
|
$sub_req, 0, 1);
|
||
|
$callback->({data=>$ret});
|
||
|
}
|
||
|
|
||
|
if (xCAT::Utils->isLinux()) {
|
||
|
#tftp, dhcp and nfs (site.disjointdhcps should be set to 1)
|
||
|
my $nttab=xCAT::Table->new('nodetype',-create=>1);
|
||
|
my $nodetypehash={};
|
||
|
if ($nttab) {
|
||
|
$nodetypehash = $nttab->getNodesAttribs(\@nodes, ['provmethod']);
|
||
|
} else {
|
||
|
my $rsp={};
|
||
|
$rsp->{error}->[0]= "Cannot open nodetype table\n";
|
||
|
$callback->($rsp);
|
||
|
return 1;
|
||
|
}
|
||
|
my $nodeset_hash = {};
|
||
|
foreach my $node (@nodes) {
|
||
|
foreach my $rec (@{$nodetypehash->{$node}}) {
|
||
|
if ($rec && $rec->{'provmethod'}) {
|
||
|
if (exists($nodeset_hash->{$rec->{'provmethod'}})) {
|
||
|
my $pa=$nodeset_hash->{$rec->{'provmethod'}};
|
||
|
push (@$pa, $node);
|
||
|
} else {
|
||
|
$nodeset_hash->{$rec->{'provmethod'}}=[$node];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
foreach my $provmethod (keys(%$nodeset_hash)) {
|
||
|
my $nodeset_nodes=$nodeset_hash->{$provmethod};
|
||
|
if (($provmethod eq 'netboot') || ($provmethod eq 'netboot') || ($provmethod eq 'netboot')) {
|
||
|
my $rsp={};
|
||
|
$rsp->{data}->[0]= "Running nodeset " . join(',', @$nodeset_nodes) . " $provmethod";
|
||
|
$callback->($rsp);
|
||
|
my $ret = xCAT::Utils->runxcmd({ command => ['nodeset'],
|
||
|
node => $nodeset_nodes,
|
||
|
arg => [$provmethod],
|
||
|
},
|
||
|
$sub_req, 0, 1);
|
||
|
$callback->({data=>$ret});
|
||
|
} else {
|
||
|
my $rsp={};
|
||
|
$rsp->{data}->[0]= "Running nodeset " . join(',', @$nodeset_nodes) . " osimage=$provmethod";
|
||
|
$callback->($rsp);
|
||
|
my $ret = xCAT::Utils->runxcmd({ command => ['nodeset'],
|
||
|
node => $nodeset_nodes,
|
||
|
arg => ["osimage=$provmethod"],
|
||
|
},
|
||
|
$sub_req, 0, 1);
|
||
|
$callback->({data=>$ret});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#postscripts to takecare of syslog server, ntp server, it will run syslog and setupntp scripts if they are in the postscripts table for the nodes
|
||
|
if (!$::IGNORE) {
|
||
|
my $pstab=xCAT::Table->new('postscripts',-create=>1);
|
||
|
my $nodeposhash={};
|
||
|
if ($pstab) {
|
||
|
$nodeposhash = $pstab->getNodesAttribs(\@nodes, ['postscripts', 'postbootscripts']);
|
||
|
} else {
|
||
|
my $rsp={};
|
||
|
$rsp->{error}->[0]= "Cannot open postsripts table\n";
|
||
|
$callback->($rsp);
|
||
|
return 1;
|
||
|
}
|
||
|
my $et = $pstab->getAttribs({node=>"xcatdefaults"},'postscripts','postbootscripts');
|
||
|
my $defscripts="";
|
||
|
my $defbootscripts="";
|
||
|
if ($et) {
|
||
|
$defscripts = $et->{'postscripts'};
|
||
|
$defbootscripts = $et->{'postbootscripts'};
|
||
|
}
|
||
|
#print "defscripts=$defscripts; defbootscripts=$defbootscripts\n";
|
||
|
#print "nodeposhash=" . Dumper($nodeposhash). "\n";
|
||
|
|
||
|
my $pos_hash = {};
|
||
|
foreach my $node (@nodes) {
|
||
|
foreach my $rec (@{$nodeposhash->{$node}}) {
|
||
|
my $scripts;
|
||
|
if ($rec) {
|
||
|
$scripts=join(',', $defscripts, $defbootscripts, $rec->{'postscripts'}, $rec->{'postsbootcripts'} );
|
||
|
} else {
|
||
|
$scripts=join(',', $defscripts, $defbootscripts);
|
||
|
}
|
||
|
my @tmp_a=split(',', $scripts);
|
||
|
my $scripts1;
|
||
|
if (grep (/^syslog$/, @tmp_a)) {
|
||
|
$scripts1="syslog";
|
||
|
}
|
||
|
if (grep (/^setupntp$/, @tmp_a)) {
|
||
|
if ($scripts1) { $scripts1= "$scripts1,setupntp"; }
|
||
|
else { $scripts1="setupntp"; }
|
||
|
}
|
||
|
if ($scripts1) {
|
||
|
if (exists($pos_hash->{$scripts1})) {
|
||
|
my $pa=$pos_hash->{$scripts1};
|
||
|
push (@$pa, $node);
|
||
|
} else {
|
||
|
$pos_hash->{$scripts1}=[$node];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#print "postscripts=" . Dumper($pos_hash);
|
||
|
foreach my $scripts (keys(%$pos_hash)) {
|
||
|
my $pos_nodes=$pos_hash->{$scripts};
|
||
|
my $rsp={};
|
||
|
$rsp->{data}->[0]= "Running updatenode " . join(',', @$pos_nodes) . " -P $scripts -s";
|
||
|
$callback->($rsp);
|
||
|
my $ret = xCAT::Utils->runxcmd({ command => ['updatenode'],
|
||
|
node => $pos_nodes,
|
||
|
arg => ["-P", $scripts, "-s"],
|
||
|
},
|
||
|
$sub_req, 0, 1);
|
||
|
$callback->({data=>$ret});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
sub usage {
|
||
|
my $cb=shift;
|
||
|
my $rsp={};
|
||
|
|
||
|
$rsp->{data}->[0]= "Usage: snmove -h";
|
||
|
$rsp->{data}->[1]= " snmove -v";
|
||
|
$rsp->{data}->[2]= " snmove noderange -d sn2 -D sn2n [-i]";
|
||
|
$rsp->{data}->[3]= " snmove -s sn1 [-S sn1n] -d sn2 -D sn2n [-i]";
|
||
|
$rsp->{data}->[4]= " where sn1 is the hostname of the source service node adapter facing the mn.";
|
||
|
$rsp->{data}->[5]= " sn1n is the hostname of the source service node adapter facing the nodes.";
|
||
|
$rsp->{data}->[6]= " sn2 is the hostname of the destination service node adapter facing the mn.";
|
||
|
$rsp->{data}->[7]= " sn2n is the hostname of the destination service node adapter facing the nodes.";
|
||
|
$cb->($rsp);
|
||
|
}
|
||
|
|
||
|
|