From 5e598f3fc9f54b6bf3cab32e094dbcbbcab4ff25 Mon Sep 17 00:00:00 2001 From: linggao Date: Mon, 28 Jun 2010 21:25:56 +0000 Subject: [PATCH] added support to move nodes from one sn to another on Linux git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@6617 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd --- xCAT-client/pods/man1/snmove.1.pod | 77 +++++ xCAT-client/pods/man8/makeroutes.8.pod | 97 ++++++ xCAT-client/xCAT-client.spec | 2 + xCAT-server/lib/xcat/plugins/snmove.pm | 432 +++++++++++++++++++++++++ 4 files changed, 608 insertions(+) create mode 100644 xCAT-client/pods/man1/snmove.1.pod create mode 100644 xCAT-client/pods/man8/makeroutes.8.pod create mode 100644 xCAT-server/lib/xcat/plugins/snmove.pm diff --git a/xCAT-client/pods/man1/snmove.1.pod b/xCAT-client/pods/man1/snmove.1.pod new file mode 100644 index 000000000..769dc86fb --- /dev/null +++ b/xCAT-client/pods/man1/snmove.1.pod @@ -0,0 +1,77 @@ +=head1 NAME + +B - move the nodes from one service node to another service node. + +=head1 SYNOPSIS + +B I B<-d>|B<--dest> I B<-D>|B<--destn> I [B<-i>|B<--ignorenodes>] + +B B<-s>|B<--source> I [B<-S>|B<--sourcen> I] B<-d>|B<--dest> I B<-D>|B<--destn> I [B<-i>|B<--ignorenodes>] + +B [B<-h>|B<--help>|B<-v>|B<--version>] + +=head1 DESCRIPTION + +The B command moves the nodes from one service nodes to another. It assumes that both service nodes can reach the nodes in terms of network. Both are configured as service nodes and listed in the B for the nodes. The source service node is the first in the list and also in B. This command will move the desination service node I to the first in the list for B and also change to match I. It'll also change the services so that TFTP, NFS, serial console and DHCP will use the new server for the nodes. If -i is specified, the nodes themselves will be untouched. Otherwise, syslog and NTP will be changed to use the new service node as the master. The user can run other postscripts using updatenode command after this command is done to setup other applications such as monitoring. The destination service node has to be up and running, but the source service node does not have to. + +=head1 OPTIONS + +=over 10 + +=item B<-s|--source> + +Specifies the hostname of the source service node adapter facing the management node. It can be found in the B table. + +=item B<-S|--sourcen> + +Specifies the hostname of the source service node adapter facing the nodes. + +=item B<-d|--dest> + +Specifies the hostname of the destination service node adapter facing the management node. It can be found in the B table. + +=item B<-D|--destn> + +Specifies the hostname of the destination service node adapter facing the nodes. + +=item B<-i|--ignorenodes> + +No action will be done on the nodes. If not specified, the syslog and setup ntp postscritps will be rerun on the nodes to switch the syslog and NTP server. + +=item B<-h|--help> + +Display usage message. + +=item B<-v|--version> + +Command Version. + + +=back + +=head1 EXAMPLES + +=over 3 + +=item 1. + +To move a groups of nodes from one server nodes to another: + + snmove group1 -d xcatsn02 -D xcatsn02-eth1 + +=item 2. + +To move all the nodes from one service nodes to another: + + snmove -s xcatsn01 -S xcatsn01-eth1 -d xcatsn02 -D xcatsn02-eth1 + +=back + +=head1 FILES + +/opt/xcat/sbin/snmove + +=head1 SEE ALSO + +L + diff --git a/xCAT-client/pods/man8/makeroutes.8.pod b/xCAT-client/pods/man8/makeroutes.8.pod new file mode 100644 index 000000000..3fce2f37d --- /dev/null +++ b/xCAT-client/pods/man8/makeroutes.8.pod @@ -0,0 +1,97 @@ +=head1 NAME + +B - add routes to connect the mn to the nodes via the service nodes. + +=head1 SYNOPSIS + +B [B<-r>|B<--routename> I[I<,r2...>]] + +B B<-d>|B<--delete> [B<-r>|B<--routenames> I[I<,r2...>]] + +B [B<-n>|B<--net> I] [B<-g>|B<--gateway> I] [B<-m>|B<--mask> I] + +B B<-d>|B<--delete> [B<-n>|B<--net> I] [B<-g>|B<--gateway> I] [B<-m>|B<--mask> I] + +B [B<-h> B<--help>|B<-v>|B<--version>] + +=head1 DESCRIPTION + +The B command adds routes to connect the mn to the nodes via the service nodes. It first reads the routing info from xCAT's B table and then adds the routes to the Kernel IP routing table for the os. It also gets all the gateways from the table. If a gateway is a service node, it sets b to 1 and then goes to the service node to enable the ipforwarding. + + +=head1 OPTIONS + +=over 10 + +=item B<-d|--delete> + +Specifies to delete the given routes. If not specified, the action is to add routes. + +=item B<-r|--routename> + +Specifies a list of comma separated route names defined in the B table. If omitted, all routes defined in the B table will be used. + +=item B<-n|--net> + +Specifies the network address. + +=item B<-g|--gateway> + +Specifies the gateway that routes the ip traffic from the mn to the nodes. + +=item B<-m|--mask> + +Specified the network mask. + +=item B<-h|--help> + +Display usage message. + +=item B<-v|--version> + +Command Version. + + +=back + +=head1 EXAMPLES + +=over 3 + +=item 1. + +To add all routes from the B table to the os route table: + + makeroutes + +=item 2. + +To add route rr1 and rr2 to the os route table. + + makeroutes -r rr1,rr2 + +=item 3. + +To delete route rr1 and rr2 from the os route table. + + makeroutes -d -r rr1,rr2 + +=item 4. + +To add a specific route to the os route table. + + makeroutes -n 10.0.1.0 + + The 10.0.1.0 netrwork must be defined in the xCAT's routes table. + + +=back + +=head1 FILES + +/opt/xcat/sbin/makeroutes + +=head1 SEE ALSO + + + diff --git a/xCAT-client/xCAT-client.spec b/xCAT-client/xCAT-client.spec index b6923c3bf..9b742baed 100644 --- a/xCAT-client/xCAT-client.spec +++ b/xCAT-client/xCAT-client.spec @@ -186,6 +186,8 @@ ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/sbin/mknb ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/bin/mkhwconn ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/bin/rmhwconn ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/bin/lshwconn +ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/sbin/makeroute +ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/sbin/snmove set -x diff --git a/xCAT-server/lib/xcat/plugins/snmove.pm b/xCAT-server/lib/xcat/plugins/snmove.pm new file mode 100644 index 000000000..2fc77d160 --- /dev/null +++ b/xCAT-server/lib/xcat/plugins/snmove.pm @@ -0,0 +1,432 @@ +# 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); +} + +