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);
 | |
| }
 | |
| 
 | |
| 
 |