mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-04 13:22:36 +00:00 
			
		
		
		
	git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@6617 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
		
			
				
	
	
		
			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);
 | 
						|
}
 | 
						|
 | 
						|
 |