diff --git a/xCAT-server/lib/xcat/plugins/snmove.pm b/xCAT-server/lib/xcat/plugins/snmove.pm index 2fc77d160..48f42f4ba 100644 --- a/xCAT-server/lib/xcat/plugins/snmove.pm +++ b/xCAT-server/lib/xcat/plugins/snmove.pm @@ -2,19 +2,16 @@ #------------------------------------------------------- =head1 - xCAT plugin package to handle xdsh - - Supported command: - nodenetconn - ipforward (internal command) + xCAT plugin package to handle the snmove command =cut #------------------------------------------------------- package xCAT_plugin::snmove; + BEGIN { - $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; } use lib "$::XCATROOT/lib/perl"; use strict; @@ -26,7 +23,6 @@ use Getopt::Long; use xCAT::NodeRange; use Data::Dumper; - 1; #------------------------------------------------------- @@ -41,12 +37,9 @@ Return list of commands handled by this plugin sub handled_commands { - return { - snmove => "snmove", - }; + return {snmove => "snmove",}; } - #------------------------------------------------------- =head3 preprocess_request @@ -62,21 +55,20 @@ sub preprocess_request my $request = shift; my $callback = shift; my $sub_req = shift; - my $command = $request->{command}->[0]; - my $args = $request->{arg}; + my $command = $request->{command}->[0]; + my $args = $request->{arg}; - #if already preprocessed, go straight to request - if ((defined($request->{_xcatpreprocessed})) + #if already preprocessed, go straight to process_request + if ( (defined($request->{_xcatpreprocessed})) && ($request->{_xcatpreprocessed}->[0] == 1)) { return [$request]; } - #let process _request to handle it + # let process_request handle it my $reqcopy = {%$request}; $reqcopy->{_xcatpreprocessed}->[0] = 1; return [$reqcopy]; - } @@ -97,336 +89,725 @@ sub process_request my $command = $request->{command}->[0]; my $args = $request->{arg}; + my $error=0; + # parse the options - @ARGV=(); - if ($args) { - @ARGV=@{$args}; + @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, - )) + my $SN1; # source SN akb MN + my $SN1N; # source SN akb node + my $SN2; # dest SN akb MN + my $SN2N; # dest SN akb node + 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; + &usage($callback); + return 1; } - + # display the usage if -h or --help is specified - if ($::HELP) { - &usage($callback); - return 0; + 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; + 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 many paramters.\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; } - 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; + # + # get the list of nodes + # - either from the command line or by checking which nodes are + # managed by the servicenode (SN1) + # + 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 use 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}}); + } + } } - 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; + # + # get the node object definitions + # + my %objtype; + my %nodehash; + foreach my $o (@nodes) + { + $objtype{$o} = 'node'; } - } 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}}); - } + my %nhash = xCAT::DBobjUtils->getobjdefs(\%objtype, $callback); + if (!(%nhash)) + { + my $rsp; + push @{$rsp->{data}}, "Could not get xCAT object definitions.\n"; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; } - } - #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 $rsp = {}; + $rsp->{data}->[0] = "Changing the service node for the following nodes: \n @nodes\n"; + $callback->($rsp); + + # + # get the nimtype for AIX nodes (diskless or standalone) + # + my %nimtype; + if (xCAT::Utils->isAIX()) + { + # need to check the nimimage table to find the nimtype + my $nimtab = xCAT::Table->new('nimimage', -create => 1); + if ($nimtab) + { + foreach my $node (@nodes) + { + my $provmethod = $nhash{$node}{'provmethod'}; + + # get the nimtype + my $ref = $nimtab->getAttribs({imagename => $provmethod},'nimtype'); + if ($ref) + { + $nimtype{$node} = $ref->{'nimtype'}; + } + } + } + } + + # + # get the backup sn for each node + # + my @servlist; # list of new service nodes + my %newsn; + my $nodehash; + if ($SN2) { # we have the backup for each node from cmd line + foreach my $n (@nodes) { + $newsn{$n}=$SN2; + } + push(@servlist, $SN2); + } else { + # check the 2nd value of the servicenode attr + foreach my $node (@nodes) + { + if ($nhash{$node}{'servicenode'} ) { + my @sn = split(',', $nhash{$node}{'servicenode'}); + if ( (scalar(@sn) > 2) && (xCAT::Utils->isAIX())) { + print "Error - The service node attribute cannot have more than two values.\n"; + } + + if ($sn[1]) { + $newsn{$node}=$sn[1]; + if (!grep(/^$sn[1]$/, @servlist)) { + push(@servlist, $sn[1]); + } + } + } + + if (!$newsn{$node}) { + print "Could not determine a backup service node for node $node.\n"; + $error++; + } + } + } + + # + # get the new xcatmaster for each node + # + my %newxcatmaster; + if ($SN2N) { # we have the xcatmaster for each node from cmd line + foreach my $n (@nodes) { + $newxcatmaster{$n}=$SN2N; + } + } else { + # try to calculate the xcatmaster value for each node + + # get all the interfaces from each SN + # $sni{$SN}= list of ip + my $s = &getSNinterfaces(\@servlist, $callback, $sub_req); + + my %sni = %$s; + + # get the network info for each node + # $nethash{nodename}{networks attr name} = value + my %nethash = xCAT::DBobjUtils->getNetwkInfo(\@nodes); + + # determine the xcatmaster value for the new SN + foreach my $node (@nodes) + { + # get the node ip + # or use getNodeIPaddress + my $nodeIP = xCAT::NetworkUtils->getipaddr($node); + chomp $nodeIP; + + # get the new SN for the node + my $mySN = $newsn{$node}; + + # check each interface on the service node + foreach my $IP (@{$sni{$mySN}} ) { + # if IP is in nodes subnet then thats the xcatmaster + if(xCAT::NetworkUtils->ishostinsubnet($IP, $nethash{$node}{mask}, $nethash{$node}{net})) { + # get the short hostname + my $xcatmaster = xCAT::NetworkUtils->gethostname($IP); + $xcatmaster =~ s/\..*//; + + # add the value to the hash + $newxcatmaster{$node}=$xcatmaster; + last; + } + } + if (!$newxcatmaster{$node}) { + print "error: Could not determine an xcatmaster value for node $node.\n"; + $error++; + } + } + } + + # + # reset the node attribute values + # + my %sn_hash; + my $old_node_hash = {}; + + foreach my $node (@nodes) + { 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; + + # get current xcatmaster + if ($SN1N) { # use command line value + $sn1n = $SN1N; + } + elsif ($nhash{$node}{'xcatmaster'} ) { # use xcatmaster attr + $sn1n = $nhash{$node}{'xcatmaster'}; } - - 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; + else + { + my $rsp; + push @{$rsp->{data}}, "The current xcatmaster attribute is not set for node $node.\n"; + xCAT::MsgUtils->message("W", $rsp, $callback); } - if ($rec->{'nfsserver'} && ($rec->{'nfsserver'} eq $sn1n)) { - $sn_hash->{$node}->{'nfsserver'}=$SN2N; + + # get current servicenode + my @sn_a; + if ($SN1) + { + # current SN from the command line + $sn1 = $SN1; } - if ($rec->{'monserver'}) { - my @tmp_a=split(',', $rec->{'monserver'}); - if ((@tmp_a > 1) && ($tmp_a[1] eq $sn1n)) { - $sn_hash->{$node}->{'monserver'}="$SN2,$SN2N"; - } + else + { + # current SN from node attribute + my $snlist = $nhash{$node}{'servicenode'}; + @sn_a = split(',', $snlist); + $sn1 = $sn_a[0]; } - } - } - if (keys(%$sn_hash) > 0) { - $nrtab->setNodesAttribs($sn_hash); - } - #print "noderes=" . Dumper($old_node_hash); - } + # switch the servicenode attr list + my @sn_temp = grep(!/^$newsn{$node}$/, @sn_a); + unshift(@sn_temp, $newsn{$node}); + my $t = join(',', @sn_temp); + $sn_hash{$node}{objtype} = 'node'; - #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; + # set servicenode and xcatmaster attr + $sn_hash{$node}{'servicenode'} = $t; + $sn_hash{$node}{'xcatmaster'} = $newxcatmaster{$node}; + $old_node_hash->{$node}->{'oldsn'} = $sn1; + $old_node_hash->{$node}->{'oldmaster'} = $sn1n; + + # set tftpserver + if ($nhash{$node}{'tftpserver'} && ($nhash{$node}{'tftpserver'} eq $sn1n)) + { + $sn_hash{$node}{'tftpserver'} = $newxcatmaster{$node}; } - } - } - 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]; - } + # set nfsserver + if ($nhash{$node}{'nfsserver'} && ($nhash{$node}{'nfsserver'} eq $sn1n)) + { + $sn_hash{$node}{'nfsserver'} = $newxcatmaster{$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]; + + #set monserver ( = "servicenode,xcatmaster" ) + if ($nhash{$node}{'monserver'}) + { + my @tmp_a = split(',', $nhash{$node}{'monserver'}); + if ((@tmp_a > 1) && ($tmp_a[1] eq $sn1n)) + { + $sn_hash{$node}{'monserver'} = "$newsn{$node},$newxcatmaster{$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}); - } } + + my $rsp; + push @{$rsp->{data}}, "Setting new values in the xCAT database.\n"; + xCAT::MsgUtils->message("I", $rsp, $callback); + + if (keys(%sn_hash) > 0) + { + # update the node definition + if (xCAT::DBobjUtils->setobjdefs(\%sn_hash) != 0) + { + my $rsp; + push @{$rsp->{data}}, "Could not update xCAT node definitions.\n"; + xCAT::MsgUtils->message("E", $rsp, $::callback); + $error++; + } + } + + # + # handle conserver + # + my %sn_hash1; + foreach my $node (@nodes) + { + if (($nhash{$node}{'conserver'}) and ($nhash{$node}{'conserver'} eq $old_node_hash->{$node}->{'oldsn'})) { + $sn_hash1{$node}{'conserver'} = $newsn{$node}; + $sn_hash1{$node}{objtype} = 'node'; + } + } + + # update the node definition + if (keys(%sn_hash1) > 0) + { + if (xCAT::DBobjUtils->setobjdefs(\%sn_hash1) != 0) + { + my $rsp; + push @{$rsp->{data}}, "Could not update xCAT node definitions.\n"; + xCAT::MsgUtils->message("E", $rsp, $::callback); + $error++; + } + } + + # run makeconservercf + 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}); } + + # + # Run niminit on AIX diskful nodes + # + if (!$::IGNORE) # unless the user does not want us to touch the node + { + if (xCAT::Utils->isAIX()) + { + #if the node is aix and the type is standalone + foreach my $node (@nodes) + { + # if this is a standalone node then run niminit + if (($nimtype{$node}) && ($nimtype{$node} eq 'standalone')) { + + my $nimcmd = qq~/usr/sbin/niminit -a name=$node -a master=$newsn{$node} >/dev/null 2>&1~; + + my $out = xCAT::InstUtils->xcmd($callback, $sub_req, "xdsh", $node, $nimcmd, 0); + + if ($::RUNCMD_RC != 0) + { + my $rsp; + push @{$rsp->{data}}, "Could not run niminit on node $node.\n"; + xCAT::MsgUtils->message("E", $rsp, $callback); + $error++; + } + } + } + } + } + + # for Linux system only + if (xCAT::Utils->isLinux()) + { + #tftp, dhcp and nfs (site.disjointdhcps should be set to 1) + + # get a list of nodes for each provmethod + my %nodeset_hash; + foreach my $node (@nodes) + { + my $provmethod = $nhash{$node}{'provmethod'}; + if ($provmethod) + { + if (!grep(/^$node$/, @{$nodeset_hash{$provmethod}})) { + push(@{$nodeset_hash{$provmethod}}, $node); + } + } + } + + # run the nodeset command + foreach my $provmethod (keys(%nodeset_hash)) + { + # need a node list to send to nodeset + my $nodeset_nodes = join ',', @{$nodeset_hash{$provmethod}}; + + if (($provmethod eq 'netboot') || ($provmethod eq 'install') || ($provmethod eq 'statelite')) + { + my $ret = + xCAT::Utils->runxcmd( + { + command => ['nodeset'], + node => $nodeset_nodes, + arg => [$provmethod], + }, + $sub_req, 0, 1 + ); + if ($::RUNCMD_RC != 0) + { + my $rsp; + push @{$rsp->{data}}, "Could not run the nodeset command.\n"; + xCAT::MsgUtils->message("E", $rsp, $callback); + $error++; + } + } + else + { + my $ret = xCAT::Utils->runxcmd( {command => ['nodeset'], node => $nodeset_nodes, arg => ["osimage=$provmethod"],}, $sub_req, 0, 1 ); + if ($::RUNCMD_RC != 0) + { + my $rsp; + push @{$rsp->{data}}, "Could not run the nodeset command.\n"; + xCAT::MsgUtils->message("E", $rsp, $callback); + $error++; + } + } + } + } # end - for Linux system only + + # + # for both AIX and Linux systems + # + # run postscripts to take care of syslog, ntp, and mkresolvconf + # - if they are icluded in the postscripts table + if (!$::IGNORE) # unless the user does not want us to touch the node + { + # get all the postscripts that should be run for the nodes + 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 postscripts 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'}; + } + + my $pos_hash = {}; + foreach my $node (@nodes) + { + + if (($nimtype{$node}) && ($nimtype{$node} eq 'diskless')) { + # don't run scripts on AIX diskless nodes + # - they will have to be rebooted anyway. + next; + } + + 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); + + # only consider running syslog, setupntp, and mkresolvconf + my @valid_scripts = ("syslog", "setupntp", "mkresolvconf"); + my $scripts1=""; + foreach my $s (@valid_scripts) { + + # if it was included in the original list then run it + if (grep(/^$s$/, @tmp_a)) + { + if ($scripts1) { + $scripts1 = "$scripts1,$s"; + } + else + { + $scripts1 = $s; + } + } + } + + if ($scripts1) + { + if (exists($pos_hash->{$scripts1})) + { + my $pa = $pos_hash->{$scripts1}; + push(@$pa, $node); + } + else + { + $pos_hash->{$scripts1} = [$node]; + } + } + } + } + + foreach my $scripts (keys(%$pos_hash)) + { + my $pos_nodes = $pos_hash->{$scripts}; + my $ret = + xCAT::Utils->runxcmd( + { + command => ['updatenode'], + node => $pos_nodes, + arg => ["-P", $scripts, "-s"], + }, + $sub_req, 0, 1 + ); + if ($::RUNCMD_RC != 0) + { + my $rsp; + push @{$rsp->{data}}, "Could not run the updatenode command.\n"; + xCAT::MsgUtils->message("E", $rsp, $callback); + $error++; + } + } + } # end -for both AIX and Linux systems + + my $retcode=0; + if ($error) + { + my $rsp; + push @{$rsp->{data}}, "One or more errors occurred while attempting to switch nodes to a new service node.\n"; + xCAT::MsgUtils->message("E", $rsp, $callback); + $retcode = 1; + } + else + { + my $rsp; + push @{$rsp->{data}}, "The nodes were successfully moved to the new service node.\n"; + xCAT::MsgUtils->message("I", $rsp, $callback); + } + + return $retcode; + } - +#---------------------------------------------------------------------------- +=head3 getSNinterfaces -sub usage { - my $cb=shift; - my $rsp={}; + Get a list of ip addresses for each service node in a list - $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."; + Arguments: + list of servcie nodes + Returns: + 1 - could not get list of ips + 0 - ok + Globals: + none + Error: + none + Example: + my $sni = xCAT::InstUtils->getSNinterfaces(\@servlist); + + Comments: + none + +=cut + +#----------------------------------------------------------------------------- +sub getSNinterfaces +{ + #my ($class, $list, $callback, $subreq) = @_; + my ($list, $callback, $subreq) = @_; + + my @snlist = @$list; + + my %SNinterfaces; + + # get all the possible IPs for the node I'm running on + my $ifcmd; + if (xCAT::Utils->isAIX()) + { + $ifcmd = "/usr/sbin/ifconfig -a "; + } + else + { + $ifcmd = "/sbin/ip addr "; + } + + foreach my $sn (@snlist) { + + my $SNIP; + + my $result = xCAT::InstUtils->xcmd($callback, $subreq, "xdsh", $sn, $ifcmd, 0); + if ($::RUNCMD_RC != 0) + { + print "Could not get IP addresses from service node $sn.\n"; + next; + } + + foreach my $int ( split(/\n/, $result) ) + { + if (!grep(/inet/, $int)) + { + # only want line with "inet" + next; + } + $int =~ s/$sn:\s+//; # skip hostname from xdsh output + my @elems = split(/\s+/, $int); + + if (xCAT::Utils->isLinux()) + { + if ($elems[0] eq 'inet6') + { + #Linux IPv6 TODO, do not return IPv6 networks on + # Linux for now + next; + } + + ($SNIP, my $mask) = split /\//, $elems[1]; + } + else + { + # for AIX + if ($elems[0] eq 'inet6') + { + $SNIP=$elems[1]; + $SNIP =~ s/\/.*//; # ipv6 address 4000::99/64 + $SNIP =~ s/\%.*//; # ipv6 address ::1%1/128 + } + else + { + $SNIP = $elems[1]; + } + } + + chomp $SNIP; + + push(@{$SNinterfaces{$sn}}, $SNIP); + } + } + + return \%SNinterfaces; +} + +#----------------------------------------------------------------------------- +sub usage +{ + my $cb = shift; + my $rsp = {}; + + push @{$rsp->{data}}, + "\nsnmove - Move xCAT compute nodes from one xCAT service node to a \nbackup service node."; + push @{$rsp->{data}}, "\nUsage: "; + push @{$rsp->{data}}, "\tsnmove -h"; + push @{$rsp->{data}}, "or"; + push @{$rsp->{data}}, "\tsnmove -v"; + push @{$rsp->{data}}, "or"; + push @{$rsp->{data}}, + "\tsnmove noderange [-d sn2] [-D sn2n] [-i|--ignorenodes]"; + push @{$rsp->{data}}, "or"; + push @{$rsp->{data}}, + "\tsnmove -s sn1 [-S sn1n] [-d sn2] [-D sn2n] [-i|--ignorenodes]"; + push @{$rsp->{data}}, "\n"; + push @{$rsp->{data}}, "\nWhere:"; + push @{$rsp->{data}}, + "\tsn1 is the hostname of the source service node as known by (facing) the management node."; + push @{$rsp->{data}}, + "\tsn1n is the hostname of the source service node as known by (facing) the nodes."; + push @{$rsp->{data}}, + "\tsn2 is the hostname of the destination service node as known by (facing) the management node."; + push @{$rsp->{data}}, + "\tsn2n is the hostname of the destination service node as known by (facing) the nodes."; $cb->($rsp); + + return 0; } -