# if error do not add to good_SN array, add to bad_SN
foreachmy$node(@snodes)
{
# run the command to each servicenode
# xdcp <sn> -s -F <syncfile>
my@sn=();
push@sn,$node;
# don't use runxcmd, because can go straight to process_request,
# these are all service nodes. Also servicenode is taken from
# the noderes table and may not be the same name as in the nodelist
# table, for example may be an ip address.
# here on the MN
my$addreq;
$addreq->{'_xcatdest'}=$::mnname;
$addreq->{node}=\@sn;
$addreq->{noderange}=\@sn;
$addreq->{arg}->[0]="-s";
$addreq->{arg}->[1]="-F";
$addreq->{arg}->[2]=$::syncsnfile;
$addreq->{command}->[0]=$cmd;
$addreq->{cwd}->[0]=$req->{cwd}->[0];
$addreq->{env}=$req->{env};
&process_request($addreq,$callback,$sub_req);
if($::FAILED_NODES==0)
{
push@::good_SN,$node;
}
else
{
push@::bad_SN,$node;
}
}# end foreach good servicenode
# for all the service nodes that are still good
# need to xdcp rsync file( -F input)
# to the service node to the /tmp/xcatrf.tmp file
my@good_SN2=@::good_SN;
@::good_SN=();
foreachmy$node(@good_SN2)
{
my@sn=();
push@sn,$node;
# run the command to each good servicenode
# xdcp <sn> <syncfile> <tmp/xcatrf.tmp>
my$addreq;
$addreq->{'_xcatdest'}=$::mnname;
$addreq->{node}=\@sn;
$addreq->{noderange}=\@sn;
$addreq->{arg}->[0]="$::syncsnfile";
$addreq->{arg}->[1]="$::tmpsyncsnfile";
$addreq->{command}->[0]=$cmd;
$addreq->{cwd}->[0]=$req->{cwd}->[0];
$addreq->{env}=$req->{env};
&process_request($addreq,$callback,$sub_req);
if($::FAILED_NODES==0)
{
push@::good_SN,$node;
}
else
{
push@::bad_SN,$node;
}
}# end foreach good service node
}# end xdcp -F
else
{
# if other xdcp commands, and not pull function
# mk the directory on the SN to hold the files
# to be sent to the SN.
# build a command to update the service nodes
# change the destination to the tmp location on
# the service node
# hierarchical support for pull (TBD)
#make the needed directory on the service node
# create new directory for path on Service Node
# xdsh <sn> mkdir -p $SNdir
my$frompath=$req->{arg}->[-2];
$::SNpath=$synfiledir;
$::SNpath.=$frompath;
my$SNdir;
$SNdir=dirname($::SNpath);# get directory
foreachmy$node(@snodes)
{
my@sn=();
push@sn,$node;
# run the command to each servicenode
# to make the directory under the temporary
# SNsyncfiledir to hold the files that will be
# sent to the service nodes
# xdsh <sn> mkdir -p <SNsyncfiledir>/$::SNpath
my$addreq;
$addreq->{'_xcatdest'}=$::mnname;
$addreq->{node}=\@sn;
$addreq->{noderange}=\@sn;
$addreq->{arg}->[0]="mkdir ";
$addreq->{arg}->[1]="-p ";
$addreq->{arg}->[2]=$SNdir;
$addreq->{command}->[0]='xdsh';
$addreq->{cwd}->[0]=$req->{cwd}->[0];
$addreq->{env}=$req->{env};
&process_request($addreq,$callback,$sub_req);
if($::FAILED_NODES==0)
{
push@::good_SN,$node;
}
else
{
push@::bad_SN,$node;
}
}# end foreach good servicenode
# now xdcp file to the service node to the new
# tmp path
# for all the service nodes that are still good
my@good_SN2=@::good_SN;
@::good_SN=();
foreachmy$node(@good_SN2)
{
my@sn;
push@sn,$node;
# copy the file to each good servicenode
# xdcp <sn> <file> <SNsyncfiledir/../file>
my$addreq=dclone($req);# get original request
$addreq->{arg}->[-1]=$SNdir;# change to tmppath on servicenode
$addreq->{'_xcatdest'}=$::mnname;
$addreq->{node}=\@sn;
$addreq->{noderange}=\@sn;
&process_request($addreq,$callback,$sub_req);
if($::FAILED_NODES==0)
{
push@::good_SN,$node;
}
else
{
push@::bad_SN,$node;
}
}# end foreach good service node
}
# report bad service nodes]
if(@::bad_SN)
{
my$rsp={};
my$badnodes;
foreachmy$badnode(@::bad_SN)
{
$badnodes.=$badnode;
$badnodes.=", ";
}
chop$badnodes;
my$msg=
"\nThe following servicenodes: $badnodes have errors and cannot be updated\n Until the error is fixed, xdcp will not work to nodes serviced by these service nodes. Run xdsh <servicenode,...> -c , to clean up the xdcp servicenode directory, and run the command again.";
# if xdsh -e <executable> command, service nodes first need
# to be rsync with the executable file to the $synfiledir
if($::dshexecute)
{
if(!-f$::dshexecute)
{# -e file does not exist, quit
my$rsp={};
$rsp->{data}->[0]="File:$::dshexecute does not exist.";
xCAT::MsgUtils->message("E",$rsp,$callback,1);
return(1);# process no service nodes
}
# xdcp the executable from the xdsh -e to the service node first
# change noderange to the service nodes
# sync to each SN and check for error
# if error do not add to good_SN array, add to bad_SN
# build a tmp syncfile with
# $::dshexecute -> $synfiledir . $::dshexecute
my$tmpsyncfile=POSIX::tmpnam.".dsh";
my$destination=$synfiledir.$::dshexecute;
open(TMPFILE,"> $tmpsyncfile")
ordie"can not open file $tmpsyncfile";
printTMPFILE"$::dshexecute -> $destination\n";
closeTMPFILE;
chmod0755,$tmpsyncfile;
foreachmy$node(@snodes)
{
# sync the file to the SN /var/xcat/syncfiles directory
# (site.SNsyncfiledir)
# xdcp <sn> -s -F <tmpsyncfile>
my@sn=();
push@sn,$node;
# don't use runxcmd, because can go straight to process_request,
# these are all service nodes. Also servicenode is taken from
# the noderes table and may not be the same name as in the nodelist
# table, for example may be an ip address.
# here on the MN
my$addreq;
$addreq->{'_xcatdest'}=$::mnname;
$addreq->{node}=\@sn;
$addreq->{noderange}=\@sn;
$addreq->{arg}->[0]="-s";
$addreq->{arg}->[1]="-F";
$addreq->{arg}->[2]=$tmpsyncfile;
$addreq->{command}->[0]="xdcp";
$addreq->{cwd}->[0]=$req->{cwd}->[0];
$addreq->{env}=$req->{env};
&process_request($addreq,$callback,$sub_req);
if($::FAILED_NODES==0)
{
push@::good_SN,$node;
}
else
{
push@::bad_SN,$node;
}
}# end foreach good servicenode
# remove the tmp syncfile
`/bin/rm $tmpsyncfile`;
}# end xdsh -E
# report bad service nodes]
if(@::bad_SN)
{
my$rsp={};
my$badnodes;
foreachmy$badnode(@::bad_SN)
{
$badnodes.=$badnode;
$badnodes.=", ";
}
chop$badnodes;
my$msg=
"\nThe following servicenodes: $badnodes have errors and cannot be updated\n Until the error is fixed, xdsh -e will not work to nodes serviced by these service nodes. Run xdsh <servicenode,...> -c , to clean up the xdcp servicenode directory, and run the command again.";