5
This file is part of RemoteBOINC.
7
Copyright (C) 2010 Toni Giorgino, Universitat Pompeu Fabra
9
RemoteBOINC is free software; you can redistribute it and/or modify it
10
under the terms of the GNU Lesser General Public License as published
11
by the Free Software Foundation, either version 3 of the License, or
12
(at your option) any later version.
14
RemoteBOINC is distributed in the hope that it will be useful, but
15
WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
Lesser General Public License for more details.
19
You should have received a copy of the GNU Lesser General Public
20
License along with BOINC. If not, see <http://www.gnu.org/licenses/>.
25
# $Id: boinc_retrieve.pl 356 2010-03-02 15:00:31Z toni $
30
use FindBin qw($Bin); # where was script installed?
31
use lib $FindBin::Bin; # use that dir for libs, too
32
use lib "$Bin/lib/$]";
34
use Getopt::Long qw(:config ignore_case auto_help);
36
use HTTP::Request::Common qw(POST);
43
use constant XMLROOT => "BoincRemote";
45
require qw(boinc_lib.pl);
49
# Constant, relative to url
50
my $cgi_retrieve="boinc_retrieve_server.pl";
55
# Parsing command line
70
my $url=$ENV{RBOINC_URL};
82
'verbose' => \$verbose,
88
'gridstatus' => \$gridstatus,
94
'authenticator=s' => \$authenticator,
95
) or die "Error parsing command line";
98
pod2usage(1) if $help;
105
checkMandatoryArguments(["group","url"]) or exit 1;
106
my $cgi_url = "$url/$cgi_retrieve";
112
# Authentication TODO
119
# Remote action invocation
127
} elsif($gridstatus) {
144
########################################
145
# Handle purge action
151
print STDERR "Action --purge deletes only. It makes no sense in combination with --into.\n";
155
confirmOrDie("The operation will IRREVERSIBLY delete results from the server.\n".
156
"Note: You won't be able to submit new WUs with equal names until old ones\nwill be pending in the server (check with -gridstatus).\nConfirm? ");
157
my $xmlcontent=invokeRMI({action=>'purge',group=>$group,name=>$name});
158
my $message=$xmlcontent->{Success}->{Message};
159
print "Success. Message from server: $message\n";
165
########################################
172
print STDERR "Action --stop makes no sense in combination with --into or --name.\n";
175
confirmOrDie("The operation will IRREVERSIBLY stop the WU. Results can still be retrieved. Confirm? ");
176
my $xmlcontent=invokeRMI({action=>'stop',group=>$group});
177
my $message=$xmlcontent->{Success}->{Message};
178
print "Success. Message from server: $message\n";
184
########################################
185
# Handle status action
191
print STDERR "Action --status makes no sense in combination with --into or --name.\n";
194
my $xmlcontent=invokeRMI({action=>'status',group=>$group});
195
my $message=$xmlcontent->{Success}->{Message};
196
print "Success. Message from server: $message\n";
198
my $steps=$xmlcontent->{Success}->{StepList};
200
foreach my $n (keys %st) {
201
my $nn=$n; # strip "bin_"
203
print "$nn\t".$st{$n}."\n";
210
########################################
211
# Handle status action
214
sub handleGridStatus {
217
print STDERR "Action --gridstatus makes no sense in combination with --into or --name.\n";
220
my $xmlcontent=invokeRMI({action=>'gridstatus'});
221
my $message=$xmlcontent->{Success}->{Message};
222
print "Success. Message from server: $message\n";
224
my $list=$xmlcontent->{Success}->{content};
235
########################################
236
# Handle retrieve action
242
# Change dir and fail early
245
print STDERR "Cannot chdir to -into directory `$into': $!\n";
252
my $xmlcontent=invokeRMI({action=>'retrieve',group=>$group,name=>$name});
256
my $rfilelist=$xmlcontent->{FileList}->{File};
258
die "No files ready for retrieval.\n";
261
my $dav_dir=$xmlcontent->{Success}->{Directory};
263
die "Error requesting download location";
266
my $aliasTable=$xmlcontent->{AliasTable};
267
my $finalOutputs=$xmlcontent->{Success}->{FinalOutputs};
268
my $nMeta=$xmlcontent->{Success}->{MetadataFileCount};
273
logInfo("Requesting the DAV address");
274
my $dav_url=getDavUrl($cgi_url);
276
logInfo("Connecting to DAV server");
277
my $dav = new HTTP::DAV;
278
$dav->open( -url=> $dav_url )
279
or die("Couldn’t open $dav_url: " .$dav->message . "\n");
281
or die("Couldn’t set remote directory $dav_dir: " .$dav->message . "\n");
286
my $nexpected=scalar @$rfilelist;
287
foreach my $fn (@$rfilelist) {
288
if( fileOrAliasExists($fn,$aliasTable) ) {
289
if(!$quiet && $nskip==0) {
290
print "Warning: some files are present locally and will not be overwritten.\n";
295
$dav->get(-url => $fn,
301
print sprintf("Retrieved $ndone, already present $nskip, out of $nexpected (% 3d%%)\r",100.*($ndone+$nskip)/$nexpected);
306
print "The following files were not overwritten: @skiplist\n";
309
print "Successfully retrieved $ndone, already present $nskip, out of $nexpected ($nMeta metadata).\n";
314
# Request deletion of remote files
317
logInfo("Going to remove retrieved files");
319
$xmlcontent=invokeRMI({action=>'remove',dir=>$dav_dir});
321
my $nremoved=$xmlcontent->{Success}->{NumberRemoved};
322
my $nkept= $xmlcontent->{Success}->{NumberKept} ;
325
print "Removed $nremoved server files, $nkept were too recent to remove.\n";
329
my $mess=$ex->text();
330
print STDERR "Error requesting removal of remote files: $mess; continuing.\n";
342
logInfo("Removing retrieval directory");
343
foreach my $fn (@$rfilelist) {
344
$dav->delete(-url => $fn);
347
$dav->delete($dav_dir);
354
# Check if file exists in current directory (1st arg), checking both
355
# the literal file name and its aliases, appending extensions
356
# described in the alias list (2nd arg)
358
sub fileOrAliasExists {
362
logInfo("Testing existence of $fn...");
364
logInfo("...is there");
368
# Extract trailing number
372
# iterate over the alias list
373
my $rAliasList=$at->{File};
374
foreach my $curAlias ( @$rAliasList ) {
375
if($curAlias->{Extension} eq "_$fileExt") {
376
# if alias for current extension, check appending all extensions
377
my $rExtList=$curAlias->{Alias};
378
foreach my $extToTest (@$rExtList) {
379
logInfo("Testing existence of $fn + $extToTest...");
380
if(-e $fn.$extToTest) {
381
logInfo("...is there");
398
# ########################################
399
# Misc. utility functions, shared by all handlers
404
# Ask for positive confirmation, or throw exception.
407
my $answer=promptUser(shift,"N");
408
die "Operation aborted." if($answer !~ /^[yY]/ );
415
# Performs the remote method invokation, die-ing on failure
416
# Returns a parsed XML structure or throws an exception.
417
# Will use the $user global variable
422
logInfo("Invoking CGI");
424
$params->{loginname}=$user;
427
my $ua = new LWP::UserAgent;
428
my $response = $ua->post( $cgi_url,
430
if($response->is_success) {
431
my $content = $response->content;
433
print "Response received:\n";
436
$xmlcontent=XMLin($content,ForceArray=>["File","Alias"]);
438
my $reason=$response->status_line;
439
die "Error in POST from remote: $reason. Server may be down.\n";
442
if($xmlcontent->{Failure}) {
443
die "Server error message: $xmlcontent->{Failure}->{Reason}";
444
} elsif(!$xmlcontent->{Success}) {
445
die "Undefined state returned. This is a bug.";
459
# Check if the calling environment has all the given variables
460
# defined. If not, print one of them. Else, return false. These are
461
# passed as string in order to be able to be able to print their name.
462
# Sadly, must be duplicated because otherwise does not have access to
465
sub checkMandatoryArguments {
467
foreach my $f (@$l) {
468
if(! eval('$'."$f")) {
469
print STDERR "Missing mandatory argument: $f. See -help.\n";
486
boinc_retrieve - Retrieving and administering remote boinc jobs
491
boinc_retrieve [options]
496
=head2 Mandatory parameters
500
-group GROUP The simulation group to be retrieved
508
-name NAME Retrieve only a specific job and its metadata
509
-into DIR Put files into specified directory (default ".")
511
-quiet Hide download progress indicator
512
-keep Do not remove retrieved files from server
513
-purge Completely remove GROUP from server (if finished)
514
-stop Prevent more work to be spawned for a given group
515
-status Show step numbers for given group
516
-gridstatus Show resources consumed and statuses for all groups
521
=head2 Authentication
525
-url URL RBoinc URL contact point (*)
526
-user NAME Override username [$user]
527
-email ADDRESS (Not implemented)
528
-authenticator ID (Not implemented)
530
(*) You can also use the RBOINC_URL environment variable
531
For example: http://www.ps3grid.net:8383/rboinc_cgi