The first phase code drop for CFM like funtion

git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@3514 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
daniceexi 2009-06-04 15:33:44 +00:00
parent 845afe2051
commit 05c9e4b58f
10 changed files with 427 additions and 5 deletions

View File

@ -3959,4 +3959,128 @@ sub checkCredFiles
}
#-----------------------------------------------------------------------------
=head3 getsynclistfile
Get the synclist file for the nodes;
The arguments $os,$arch,$profile,$insttype are only available when no $nodes is specified
Arguments:
$nodes
$os
$arch
$profile
$insttype - installation type (can be install or netboot)
Returns:
When specified $nodes: reference of a hash of node=>synclist
Otherwise: full path of the synclist file
Globals:
none
Error:
Example:
my $node_syncfile=xCAT::Utils->getsynclistfile($nodes);
my $syncfile=xCAT::Utils->getsynclistfile(undef, 'sles11', 'ppc64', 'compute', 'netboot');
Comments:
none
=cut
#-----------------------------------------------------------------------------
sub getsynclistfile()
{
my $nodes = shift;
if (($nodes) && ($nodes =~ /xCAT::Utils/))
{
$nodes = shift;
}
my ($os, $arch, $profile, $inst_type) = @_;
# if does not specify the $node param, default consider for genimage command
if ($nodes) {
my %node_syncfile = ();
my %node_insttype = ();
my %insttype_node = ();
# get the nodes installation type
xCAT::SvrUtils->getNodesetStates($nodes, \%insttype_node);
# convert the hash to the node=>type
foreach my $type (keys %insttype_node) {
foreach my $node (@{$insttype_node{$type}}) {
$node_insttype{$node} = $type;
}
}
# get the os,arch,profile attributes for the nodes
my $nodetype_t = xCAT::Table->new('nodetype');
unless ($nodetype_t) {
return ;
}
my $nodetype_v = $nodetype_t->getNodesAttribs($nodes, ['profile','os','arch']);
foreach my $node (@$nodes) {
$inst_type = $node_insttype{$node};
if ($inst_type eq "netboot" || $inst_type eq "diskless") {
$inst_type = "netboot";
} else {
$inst_type = "install";
}
$profile = $nodetype_v->{$node}->[0]->{'profile'};
$os = $nodetype_v->{$node}->[0]->{'os'};
$arch = $nodetype_v->{$node}->[0]->{'arch'};
my $platform = "";
if ($os) {
if ($os =~ /rh.*/) { $platform = "rh"; }
elsif ($os =~ /centos.*/) { $platform = "centos"; }
elsif ($os =~ /fedora.*/) { $platform = "fedora"; }
elsif ($os =~ /sles.*/) { $platform = "sles"; }
elsif ($os =~ /AIX.*/) { $platform = "AIX"; }
}
my $base = "/install/custom/$inst_type/$platform";
if (-r "$base/$profile.$os.$arch.synclist") {
$node_syncfile{$node} = "$base/$profile.$os.$arch.synclist";
} elsif (-r "$base/$profile.$arch.synclist") {
$node_syncfile{$node} = "$base/$profile.$arch.synclist";
} elsif (-r "$base/$profile.$os.synclist") {
$node_syncfile{$node} = "$base/$profile.$os.synclist";
} elsif (-r "$base/$profile.synclist") {
$node_syncfile{$node} = "$base/$profile.synclist";
}
}
return \%node_syncfile;
} else {
my $platform = "";
if ($os) {
if ($os =~ /rh.*/) { $platform = "rh"; }
elsif ($os =~ /centos.*/) { $platform = "centos"; }
elsif ($os =~ /fedora.*/) { $platform = "fedora"; }
elsif ($os =~ /sles.*/) { $platform = "sles"; }
elsif ($os =~ /AIX.*/) { $platform = "AIX"; }
}
my $base = "/install/custom/$inst_type/$platform";
if (-r "$base/$profile.$os.$arch.synclist") {
return "$base/$profile.$os.$arch.synclist";
} elsif (-r "$base/$profile.$arch.synclist") {
return "$base/$profile.$arch.synclist";
} elsif (-r "$base/$profile.$os.synclist") {
return "$base/$profile.$os.synclist";
} elsif (-r "$base/$profile.synclist") {
return "$base/$profile.synclist";
}
}
}
1;

View File

@ -228,6 +228,9 @@ sub makescript {
push @scriptd, "NODESETSTATE=".$nodesetstate."\n";
push @scriptd, "export NODESETSTATE\n";
# set the UPDATENODE flag in the script, the default it 0, that means not in the updatenode process
push @scriptd, "UPDATENODE=0\n";
push @scriptd, "export UPDATENODE\n";
# see if this is a service or compute node?
if (xCAT::Utils->isSN($node) ) {
@ -356,4 +359,44 @@ sub get_otherpkg_file_name {
return "";
}
#----------------------------------------------------------------------------
=head3 syncfiles
Use the xdcp command to sync files from Management node/Service node to the Compute node
Arguments:
Returns: 0 - failed; 1 - succeeded;
Example:
xCAT::Postage->syncfiles($node, $callback);
Comments:
=cut
#-----------------------------------------------------------------------------
sub syncfiles {
my $node = shift;
if ($node =~ /xCAT::Postage/) {
$node = shift;
}
my $callback = shift;
my $subreq = shift;
#get the sync file base on the node type
my $synclist = xCAT::Utils->getsynclistfile([$node]);
if (!$synclist) {
xCAT::MsgUtils->message("S", "Cannot find synclist file for the $node");
return 0;
}
# call the xdcp plugin to handle the syncfile operation
my $args = ["-F", "$$synclist{$node}"];
my $env = ["DSH_RSYNC_FILE=$$synclist{$node}"];
$subreq->({command=>['xdcp'], node=>[$node], arg=>$args, env=>$env}, $callback);
return 1;
}
1;

View File

@ -0,0 +1,67 @@
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
#-------------------------------------------------------
=head1
xCAT plugin package to handle syncfiles command
=cut
#-------------------------------------------------------
package xCAT_plugin::syncfiles;
use xCAT::Utils;
use xCAT::MsgUtils;
use xCAT::NodeRange;
1;
#-------------------------------------------------------
=head3 handled_commands
Return list of commands handled by this plugin
=cut
#-------------------------------------------------------
sub handled_commands
{
return {'syncfiles' => "syncfiles"};
}
#-------------------------------------------------------
=head3 process_request
Process the command
=cut
#-------------------------------------------------------
sub process_request
{
my $request = shift;
my $callback = shift;
my $subreq = shift;
my $client;
if ($request->{'_xcat_clienthost'}) {
$client = $request->{'_xcat_clienthost'}->[0];
}
if ($client) { ($client) = noderange($client) };
unless ($client) { #Not able to do identify the host in question
xCAT::MsgUtils->message("S","Received syncfiles from $client, which couldn't be correlated to a node (domain mismatch?)");
return;
}
require xCAT::Postage;
my $rc = xCAT::Postage->syncfiles($client,$callback,$subreq);
if ($rc) {
xCAT::MsgUtils->message("S","Sync files to node $client completed");
} else {
xCAT::MsgUtils->message("S","Encountered error when using xdcp sync files to $client");
}
}

View File

@ -56,13 +56,14 @@ sub preprocess_request
{
my $request = shift;
my $callback = shift;
my $subreq = shift;
my $command = $request->{command}->[0];
if ($request->{_xcatdest}) { return [$request]; } #exit if preprocessed
my @requests=();
if ($command eq "updatenode")
{
return preprocess_updatenode($request, $callback);
return preprocess_updatenode($request, $callback, $subreq);
} elsif ($command eq "updatenodestat") {
return [$request];
}
@ -89,11 +90,12 @@ sub process_request
{
my $request = shift;
my $callback = shift;
my $subreq = shift;
my $command = $request->{command}->[0];
my $localhostname=hostname();
if ($command eq "updatenode") {
return updatenode($request, $callback);
return updatenode($request, $callback, $subreq);
} elsif ($command eq "updatenodestat") {
return updatenodestat($request, $callback);
} else {
@ -112,7 +114,7 @@ sub process_request
Arguments:
request - the request. The request->{arg} is of the format:
[-h|--help|-v|--version] or
[noderange [postscripts]]
[noderange [-s | -S] [postscripts]]
callback - the pointer to the callback function.
Returns:
A pointer to an array of requests.
@ -121,6 +123,7 @@ sub process_request
sub preprocess_updatenode {
my $request = shift;
my $callback = shift;
my $subreq = shift;
my $args=$request->{arg};
my @requests=();
@ -130,7 +133,7 @@ sub preprocess_updatenode {
my $cb=shift;
my $rsp={};
$rsp->{data}->[0]= "Usage:";
$rsp->{data}->[1]= " updatenode <noderange> [posts]";
$rsp->{data}->[1]= " updatenode <noderange> [-s | -S] [posts]";
$rsp->{data}->[2]= " updatenode [-h|--help|-v|--version]";
$rsp->{data}->[3]= " noderange is a list of nodes or groups.";
$rsp->{data}->[4]= " posts is a comma separated list of postscript names.";
@ -149,7 +152,9 @@ sub preprocess_updatenode {
Getopt::Long::Configure("no_pass_through");
if(!GetOptions(
'h|help' => \$::HELP,
'v|version' => \$::VERSION))
'v|version' => \$::VERSION,
's' => \$::SYNCSN,
'S' => \$::SKIPSYNCFILE ))
{
&updatenode_usage($callback);
return \@requests;;
@ -198,6 +203,52 @@ sub preprocess_updatenode {
# build an individual request for each service node
my $sn = xCAT::Utils->get_ServiceNode(\@nodes, "xcat", "MN");
# If -s argument specified, sync files to the service node firstly
if ($::SYNCSN) {
my @MNnodeinfo = xCAT::Utils->determinehostname;
my $MNnodename = pop @MNnodeinfo; # hostname
my @MNnodeipaddr = @MNnodeinfo; # ipaddresses
my $node_syncfile = xCAT::Utils->getsynclistfile($nodes);
my %syncfile_sn = ();
foreach my $snkey (keys %$sn)
{
# exclude the Management node
if (grep(/$snkey/, @MNnodeipaddr)) {
next;
}
my @synclists = ();
# Figure out the synclist files for the service node
foreach my $node (@{$sn->{$snkey}}) {
my $synclist = $$node_syncfile{$node};
unless ($synclist) {
next;
}
if (! grep /\Q$synclist\E/, @synclists) {
push @synclists, $synclist;
push @{$syncfile_sn{$synclist}}, $node;
}
}
# If there are multiple synclist files for certain SN,
# the synclist files maybe have conflicted content, so
# display an warning message
if ($#synclists > 0) {
my $rsp = {};
my $files = join(',', @synclists);
$rsp->{data}->[0]= "Warning: The Service Node $snkey will be synced by following synclist files: $files";
$callback->($rsp);
}
}
foreach my $syncfile (keys %syncfile_sn) {
my $arg = ["-s", "-F", "$syncfile"];
my $env = ["RSYNCSN=yes", "DSH_RSYNC_FILE=$syncfile"];
$subreq->({command=>['xdcp'], node=>$syncfile_sn{$syncfile}, arg=>$arg, env=>$env}, $callback);
}
}
# build each request for each service node
foreach my $snkey (keys %$sn)
{
@ -227,11 +278,32 @@ sub preprocess_updatenode {
sub updatenode {
my $request = shift;
my $callback = shift;
my $subreq = shift;
my $postscripts="";
if (($request->{postscripts}) && ($request->{postscripts}->[0])) { $postscripts=$request->{postscripts}->[0];}
my $nodes =$request->{node};
my $localhostname=hostname();
# if not specifying -S, do the sync file operation
unless ($::SKIPSYNCFILE) {
my %syncfile_node = ();
my $node_syncfile = xCAT::Utils->getsynclistfile($nodes);
foreach my $node (@$nodes) {
my $synclist = $$node_syncfile{$node};
if ($synclist) {
push @{$syncfile_node{$synclist}}, $node;
next;
}
}
foreach my $synclist (keys %syncfile_node) {
my $args = ["-F", "$synclist"];
my $env = ["DSH_RSYNC_FILE=$synclist"];
$subreq->({command=>['xdcp'], node=>$syncfile_node{$synclist}, arg=>$args, env=>$env}, $callback);
}
}
my $nodestring=join(',', @$nodes);
#print "postscripts=$postscripts, nodestring=$nodestring\n";

View File

@ -257,6 +257,10 @@ if ($inet6support) {
}
print $conn "#END OF SCRIPT\n";
close($conn);
} elsif ($text =~ /^syncfiles/) {
plugin_command({command=>['syncfiles'],_xcat_clienthost=>[$node]},undef,\&build_response);
print $conn "syncfiles done\n";
close($conn);
} elsif ($text =~ /^rebootnodes/) {
my @cmdargs = split(/\s+/,$text);
my $rebootcmd = shift(@cmdargs);

View File

@ -143,4 +143,8 @@ fi
if [ -r /root/.ssh/id_rsa ]; then
ssh-keygen -y -f /root/.ssh/id_rsa > /root/.ssh/id_rsa.pub
fi
# start up the sshd for syncfiles postscript to do the sync work
service sshd start
kill -9 $CREDPID

View File

@ -0,0 +1,24 @@
#!/usr/bin/awk -f
BEGIN {
if (ENVIRON["USEOPENSSLFORXCAT"]) {
server = "openssl s_client -quiet -connect " ENVIRON["XCATSERVER"]
} else {
server = "/inet/tcp/0/127.0.0.1/400"
}
quit = "no"
print "<xcatrequest>" |& server
print " <command>syncfiles</command>" |& server
print "</xcatrequest>" |& server
while (server |& getline) {
if (match($0,"<syncfiles done>")) {
quit = "yes"
}
if (match($0,"</xcatresponse>") && match(quit,"yes")) {
close(server)
exit
}
}
}

View File

@ -0,0 +1,69 @@
#!/usr/bin/perl
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
#####################################################
#
# xCAT post script for configuration files distribution
#
# It should be run after the remoteshell
# It is also run by the updatenode cmd
#
#####################################################
# do nothing when UPDATENODE=1
if ($ENV{'UPDATENODE'} == 1
|| $ENV{'NODESETSTATE'} eq "netboot"
|| $ENV{'NODESETSTATE'} eq "diskless") {
exit 0;
}
`logger -t xCAT "Performing syncfiles postscript"`;
# get platform
my $osname = `uname`;
chomp $osname;
# run the xdcp on the MN/SN
my $xcatpostdir = "/xcatpost";
my $startsync = "";
if ($osname eq "Linux") {
`logger -t xCAT "run $xcatpostdir/startsyncfiles.awk"`;
$startsync = "$xcatpostdir/startsyncfiles.awk";
`$startsync`;
} else {
`logger -t xCAT "run $xcatpostdir/startsyncfilesaix.awk"`;
&startsyncfilesaix();
}
exit 0;
sub startsyncfilesaix
{
use IO::Socket;
my $port = "3002";
my $remote = IO::Socket::INET->new( Proto => "tcp", PeerAddr => $ENV{'MASTER'}, PeerPort => $port, );
unless ($remote) {
`logger -t xCAT "startsyncfiles: Cannot connect to host $ENV{'MASTER'}"`;
}
$remote->autoflush(1);
while (<$remote>) {
my $line = $_;
chomp($line);
if ($line =~ /ready/) {
print $remote "syncfiles\n";
}
if ($line =~ /syncfiles done/) {
close $remote;
return 0;
}
}
close $remote;
return 0;
}

View File

@ -153,6 +153,13 @@ if (-f $scriptname) {
my $nodesetstat="standalone";
if (-f $scriptname)
{
# when called by the updatenode command,
#modify the UPDATENODE flag to 1
if (@ARGV > 0) {
$TMP=`sed -e 's/UPDATENODE=0/UPDATENODE=1/g' $scriptname`;
`echo "$TMP" > $scriptname`;
}
if (@ARGV>1) {
my $scripts=$ARGV[1];
my $POSTS=join('\n', split(',', $scripts));

View File

@ -88,6 +88,14 @@ while [ -z "$MYCONT" ]; do
MYCONT=`cat /tmp/mypostscript`
# echo "MYCONT=$MYCONT"
done
# when called by the updatenode command,
#modify the UPDATENODE flag to 1
if [ $# -gt 0 ]; then
TMP=`sed -e 's/UPDATENODE=0/UPDATENODE=1/g' /tmp/mypostscript`;
echo "$TMP" > /tmp/mypostscript;
fi
if [ $# -gt 1 ]; then
POSTS=$2
#remove all the postscripts