Commit 763c6aca authored by Mike Hibler's avatar Mike Hibler

Client half of the fetch-tarballs-via-the-web change.

For every tarball and rpm, tmcd will now pass a SERVER= string as well
telling the client where the file should be downloaded from (if using
the web rather than NFS). Right now this value is the same for all
tarballs and rpms, and is hardwired in tmcd as either "www" (if
SPEWFROMOPS=0) or "users" (if 1). Note: BUMPED THE TMCC VERSION NUMBER
for this.

Made a common routine for doing an error-check-and-retry copy of a file
across "racy" NFS. This is used by install-{tarfile,rpm} and rc.topomap.
parent b4c12259
...@@ -46,4 +46,4 @@ ...@@ -46,4 +46,4 @@
* it in clientside/tmcc/common/libsetup.pm! * it in clientside/tmcc/common/libsetup.pm!
*/ */
#define DEFAULT_VERSION 2 #define DEFAULT_VERSION 2
#define CURRENT_VERSION 35 #define CURRENT_VERSION 36
...@@ -43,10 +43,10 @@ BEGIN { require "/etc/emulab/paths.pm"; import emulabpaths; } ...@@ -43,10 +43,10 @@ BEGIN { require "/etc/emulab/paths.pm"; import emulabpaths; }
# #
sub usage() sub usage()
{ {
print STDOUT "Usage: install-rpm [-d] [-ct] [-n nodeid] <filename>\n"; print STDOUT "Usage: install-rpm [-d] [-ct] [-n nodeid] [-S server] <filename>\n";
exit(-1); exit(-1);
} }
my $optlist = "dctn:"; my $optlist = "dctn:S:";
# #
# Turn off line buffering on output # Turn off line buffering on output
...@@ -64,6 +64,7 @@ delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; ...@@ -64,6 +64,7 @@ delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
my $IDENTFILE = "$DBDIR/testbed.rpms"; my $IDENTFILE = "$DBDIR/testbed.rpms";
my $rpm = ""; my $rpm = "";
my $usewget = 0; my $usewget = 0;
my $wgetserver = "";
my $copymode = 0; my $copymode = 0;
my $debug = 0; my $debug = 0;
my $copyfile; my $copyfile;
...@@ -81,7 +82,7 @@ use libsetup; ...@@ -81,7 +82,7 @@ use libsetup;
use libtmcc; use libtmcc;
# Protos # Protos
sub GetRPMFile($$$$$$$); sub GetRPMFile($$$$$$$$);
sub GetMD5($); sub GetMD5($);
sub WriteIdentFile(); sub WriteIdentFile();
...@@ -110,6 +111,12 @@ if (defined($options{"t"})) { ...@@ -110,6 +111,12 @@ if (defined($options{"t"})) {
$usewget = 1; $usewget = 1;
$copymode = 1; $copymode = 1;
} }
if (defined($options{"S"})) {
$wgetserver = $options{"S"};
if ($wgetserver =~ /^([-\w\.]+)$/) {
$wgetserver = $1;
}
}
if (defined($options{"n"})) { if (defined($options{"n"})) {
$nodeid = $options{"n"}; $nodeid = $options{"n"};
if ($nodeid =~ /^([-\w]+)$/) { if ($nodeid =~ /^([-\w]+)$/) {
...@@ -190,6 +197,7 @@ if (! $copymode) { ...@@ -190,6 +197,7 @@ if (! $copymode) {
print STDOUT "RPM $rpm has already been installed!\n"; print STDOUT "RPM $rpm has already been installed!\n";
exit(1); exit(1);
} }
# #
# Otherwise compare MD5. # Otherwise compare MD5.
# #
...@@ -216,7 +224,7 @@ else { ...@@ -216,7 +224,7 @@ else {
# Returns >0 if server copy has not been modifed. # Returns >0 if server copy has not been modifed.
# Returns =0 if okay to install, and gives us new stamp/md5. # Returns =0 if okay to install, and gives us new stamp/md5.
# #
if (GetRPMFile($rpm, $copyfile, $usewget, if (GetRPMFile($rpm, $copyfile, $usewget, $wgetserver,
$oldstamp, $oldmd5, \$filestamp, \$filemd5)) { $oldstamp, $oldmd5, \$filestamp, \$filemd5)) {
print STDOUT "RPM $rpm has already been installed!\n"; print STDOUT "RPM $rpm has already been installed!\n";
if (defined($filestamp) && $filestamp != $oldstamp) { if (defined($filestamp) && $filestamp != $oldstamp) {
...@@ -270,78 +278,41 @@ sub fatal { ...@@ -270,78 +278,41 @@ sub fatal {
# #
# Get an RPM from the server via tmcc and stash. # Get an RPM from the server via tmcc and stash.
# #
sub GetRPMFile($$$$$$$) sub GetRPMFile($$$$$$$$)
{ {
my ($rpm, $copyfile, $usewget, my ($rpm, $copyfile, $usewget, $wgetserver,
$oldstamp, $oldmd5, $filestamp, $filemd5) = @_; $oldstamp, $oldmd5, $filestamp, $filemd5) = @_;
my $buf; my $buf;
#
# If copying via NFS, must watch for read errors and retry.
#
if (! $usewget) { if (! $usewget) {
print STDOUT "Copying RPM $rpm across NFS\n"
if ($debug);
# #
# Compare timestamp. If no change, we are done. # Compare timestamp. If no change, we are done.
# #
my (undef,undef,undef,undef,undef,undef,undef,$bytelen, my (undef,undef,undef,undef,undef,undef,undef,undef,undef,$stamp) =
undef,$stamp) = stat($rpm); stat($rpm);
if (defined($oldstamp) && $oldstamp >= $stamp) { if (defined($oldstamp) && $oldstamp >= $stamp) {
print STDOUT "Timestamp ($stamp) for $rpm unchanged!\n" print STDOUT "Timestamp ($stamp) for $rpm unchanged!\n"
if ($debug); if ($debug);
return 1; return 1;
} }
#
# Must do this for caller so that if the MD5 has not changed, # Must do this for caller so that if the MD5 has not changed,
# the caller can update the timestamp in the ident file. # the caller can update the timestamp in the ident file.
#
$$filestamp = $stamp; $$filestamp = $stamp;
open(TMCC, "< $rpm")
or fatal("Could not open rpm on server!");
binmode TMCC;
#
# Open the target file and start dumping the data in.
#
open(JFILE, "> $copyfile")
or fatal("Could not open local file $copyfile: $!");
binmode JFILE;
# #
# Deal with NFS read failures # If copying via NFS, use special copy routine which retries on error.
# #
my $foffset = 0; if (!copyfilefromnfs($rpm, $copyfile, 1)) {
my $retries = 5; unlink($copyfile);
fatal("Could not copy RPM $rpm from server!");
while ($bytelen) {
my $rlen = sysread(TMCC, $buf, 8192);
if (! defined($rlen)) {
#
# If we are copying the file via NFS, retry a few times
# on error to avoid the changing-exports-file server problem.
if ($retries > 0 && sysseek(TMCC, $foffset, 0)) {
warn("*** WARNING retrying read of $rpm ".
"at offset $foffset\n");
$retries--;
sleep(2);
next;
}
fatal("Error reading tarball $rpm: $!");
}
if ($rlen == 0) {
last;
}
if (! syswrite(JFILE, $buf)) {
fatal("Error writing rpm $copyfile: $!");
}
$foffset += $rlen;
$bytelen -= $rlen;
$retries = 5;
} }
close(JFILE);
close(TMCC);
# #
# Compare md5. # Compare md5.
...@@ -355,6 +326,9 @@ sub GetRPMFile($$$$$$$) ...@@ -355,6 +326,9 @@ sub GetRPMFile($$$$$$$)
$$filemd5 = $md5; $$filemd5 = $md5;
} }
else { else {
print STDOUT "Fetching RPM $rpm from $wgetserver via HTTP\n"
if ($debug);
# #
# Need the nodeid and the keyhash. We allow the nodeid to be # Need the nodeid and the keyhash. We allow the nodeid to be
# overridden on the command line, but thats just a debugging # overridden on the command line, but thats just a debugging
...@@ -389,30 +363,30 @@ sub GetRPMFile($$$$$$$) ...@@ -389,30 +363,30 @@ sub GetRPMFile($$$$$$$)
} }
# #
# Lastly, need our boss node. # Lastly, need the server.
# For compat, use boss (aka, www) if not specified.
# #
my ($www) = tmccbossname(); if ($wgetserver eq "") {
($wgetserver) = tmccbossname();
if ($www =~ /^[-\w]+\.(.*)$/) { if ($wgetserver =~ /^[-\w]+\.(.*)$/) {
$www = "www.${1}"; $wgetserver = "www.${1}";
} }
else { else {
fatal("Tainted bossinfo $www!"); fatal("Tainted bossinfo $wgetserver!");
}
} }
$www = "https://${www}"; my $www = "https://$wgetserver";
#$www = "https://${www}/dev/stoller";
#$www = "http://golden-gw.ballmoss.com:9876/~stoller/testbed";
# #
# Okay, run wget with the proper arguments. # Okay, run wget with the proper arguments.
# #
my $cmd = "wget -nv -O $copyfile ". my $cmd = "wget -nv -O --no-check-certificate $copyfile ".
($debug ? "--server-response " : "") . ($debug ? "--server-response " : "") .
"'${www}/spewrpmtar.php3". "'${www}/spewrpmtar.php3".
"?nodeid=${nodeid}&file=${rpm}&key=${keyhash}". "?nodeid=${nodeid}&file=${rpm}&key=${keyhash}".
(defined($oldstamp) ? "&stamp=$oldstamp" : "") . (defined($oldstamp) ? "&stamp=$oldstamp" : "") .
(defined($oldmd5) ? "&md5=$oldmd5" : "") . (defined($oldmd5) ? "&md5=$oldmd5" : "") .
"'"; "'";
if ($debug) { if ($debug) {
print STDERR "$cmd\n"; print STDERR "$cmd\n";
......
...@@ -41,7 +41,7 @@ BEGIN { require "/etc/emulab/paths.pm"; import emulabpaths; } ...@@ -41,7 +41,7 @@ BEGIN { require "/etc/emulab/paths.pm"; import emulabpaths; }
sub usage() sub usage()
{ {
print STDOUT print STDOUT
"Usage: install-tarfile [-hVdfvct] [-n nodeid] [-u user] <installdir> ". "Usage: install-tarfile [-hVdfvct] [-n nodeid] [-u user] [-S server] <installdir> ".
"<filename>\n". "<filename>\n".
" install-tarfile [-l]\n". " install-tarfile [-l]\n".
"Options:\n". "Options:\n".
...@@ -55,6 +55,7 @@ sub usage() ...@@ -55,6 +55,7 @@ sub usage()
" -n nodeid Override the default node ID when downloading from Emulab\n". " -n nodeid Override the default node ID when downloading from Emulab\n".
" -u user User that should own files with unknown uid/gid\n". " -u user User that should own files with unknown uid/gid\n".
" -l List the currently installed tar files and exit\n". " -l List the currently installed tar files and exit\n".
" -S server Specifies the Emulab server (for -t)\n".
"\n". "\n".
"Required Arguments:". "Required Arguments:".
" installdir The absolute path of the install directory.\n". " installdir The absolute path of the install directory.\n".
...@@ -62,7 +63,7 @@ sub usage() ...@@ -62,7 +63,7 @@ sub usage()
exit(-1); exit(-1);
} }
my $optlist = "hVlvcdftn:u:"; my $optlist = "hVlvcdftn:u:S:";
# #
# Turn off line buffering on output # Turn off line buffering on output
...@@ -84,6 +85,7 @@ my $installdir = "/"; ...@@ -84,6 +85,7 @@ my $installdir = "/";
my $unknownuser = ""; my $unknownuser = "";
my $force = 0; my $force = 0;
my $usewget = 0; my $usewget = 0;
my $wgetserver = "";
my $listmode = 0; my $listmode = 0;
my $copymode = 0; my $copymode = 0;
my $verifymode = 0; my $verifymode = 0;
...@@ -105,7 +107,7 @@ use libsetup; ...@@ -105,7 +107,7 @@ use libsetup;
use libtmcc; use libtmcc;
# Protos # Protos
sub GetTarFile($$$$$$$); sub GetTarFile($$$$$$$$);
sub GetMD5($); sub GetMD5($);
sub WriteIdentFile(); sub WriteIdentFile();
...@@ -144,6 +146,15 @@ if (defined($options{"t"})) { ...@@ -144,6 +146,15 @@ if (defined($options{"t"})) {
$copymode = 1; $copymode = 1;
$usewget = 1; $usewget = 1;
} }
if (defined($options{"S"})) {
$wgetserver = $options{"S"};
if ($wgetserver =~ /^([-\w\.]+)$/) {
$wgetserver = $1;
}
else {
fatal("Tainted server: $wgetserver");
}
}
if (defined($options{"v"})) { if (defined($options{"v"})) {
$verifymode = 1; $verifymode = 1;
} }
...@@ -340,7 +351,7 @@ else { ...@@ -340,7 +351,7 @@ else {
# Returns >0 if server copy has not been modifed. # Returns >0 if server copy has not been modifed.
# Returns =0 if okay to install, and gives us new stamp/md5. # Returns =0 if okay to install, and gives us new stamp/md5.
# #
if (GetTarFile($tarfile, $copyfile, $usewget, if (GetTarFile($tarfile, $copyfile, $usewget, $wgetserver,
$oldstamp, $oldmd5, \$filestamp, \$filemd5)) { $oldstamp, $oldmd5, \$filestamp, \$filemd5)) {
print STDOUT "Tarfile $tarfile has already been installed!\n"; print STDOUT "Tarfile $tarfile has already been installed!\n";
if (defined($filestamp) && $filestamp != $oldstamp) { if (defined($filestamp) && $filestamp != $oldstamp) {
...@@ -483,79 +494,41 @@ sub fatal { ...@@ -483,79 +494,41 @@ sub fatal {
# #
# Get a tarfile from the server via tmcc and stash. # Get a tarfile from the server via tmcc and stash.
# #
sub GetTarFile($$$$$$$) sub GetTarFile($$$$$$$$)
{ {
my ($tarfile, $copyfile, $usewget, my ($tarfile, $copyfile, $usewget, $wgetserver,
$oldstamp, $oldmd5, $filestamp, $filemd5) = @_; $oldstamp, $oldmd5, $filestamp, $filemd5) = @_;
my $buf; my $buf;
#
# If copying via NFS, must watch for read errors and retry.
#
if (! $usewget) { if (! $usewget) {
print STDOUT "Copying tarball $tarfile across NFS\n"
if ($debug);
# #
# Compare timestamp. If no change, we are done. # Compare timestamp. If no change, we are done.
# #
my (undef,undef,undef,undef,undef,undef,undef,$bytelen, my (undef,undef,undef,undef,undef,undef,undef,undef,undef,$stamp) =
undef,$stamp) = stat($tarfile); stat($tarfile);
if (defined($oldstamp) && $oldstamp >= $stamp && !$force) { if (defined($oldstamp) && $oldstamp >= $stamp && !$force) {
print STDOUT "Timestamp ($stamp) for $tarfile unchanged!\n" print STDOUT "Timestamp ($stamp) for $tarfile unchanged!\n"
if ($debug); if ($debug);
return 1; return 1;
} }
#
# Must do this for caller so that if the MD5 has not changed, # Must do this for caller so that if the MD5 has not changed,
# the caller can update the timestamp in the ident file. # the caller can update the timestamp in the ident file.
#
$$filestamp = $stamp; $$filestamp = $stamp;
open(TMCC, "< $tarfile")
or fatal("Could not open tarfile on server!");
binmode TMCC;
#
# Open the target file and start dumping the data in.
#
open(JFILE, "> $copyfile")
or fatal("Could not open local file $copyfile: $!");
binmode JFILE;
# #
# Deal with NFS read failures # If copying via NFS, use special copy routine which retries on error.
# #
my $foffset = 0; if (!copyfilefromnfs($tarfile, $copyfile, 1)) {
my $retries = 5; unlink($copyfile);
fatal("Could not copy tarfile $tarfile from server!");
while ($bytelen) {
my $rlen = sysread(TMCC, $buf, 8192);
if (! defined($rlen)) {
#
# If we are copying the file via NFS, retry a few times
# on error to avoid the changing-exports-file server problem.
if ($retries > 0 && sysseek(TMCC, $foffset, 0)) {
warn("*** WARNING retrying read of $tarfile ".
"at offset $foffset\n");
$retries--;
sleep(2);
next;
}
fatal("Error reading tarball $tarfile: $!");
}
if ($rlen == 0) {
last;
}
if (! syswrite(JFILE, $buf)) {
fatal("Error writing tarfile $copyfile: $!");
}
$foffset += $rlen;
$bytelen -= $rlen;
$retries = 5;
} }
close(JFILE);
close(TMCC);
# #
# Compare md5. # Compare md5.
...@@ -569,6 +542,9 @@ sub GetTarFile($$$$$$$) ...@@ -569,6 +542,9 @@ sub GetTarFile($$$$$$$)
$$filemd5 = $md5; $$filemd5 = $md5;
} }
else { else {
print STDOUT "Fetching tarball $tarfile from $wgetserver via HTTP\n"
if ($debug);
# #
# Need the nodeid and the keyhash. We allow the nodeid to be # Need the nodeid and the keyhash. We allow the nodeid to be
# overridden on the command line, but thats just a debugging # overridden on the command line, but thats just a debugging
...@@ -603,31 +579,31 @@ sub GetTarFile($$$$$$$) ...@@ -603,31 +579,31 @@ sub GetTarFile($$$$$$$)
} }
# #
# Lastly, need our boss node. # Lastly, need the server.
# For compat, use boss (aka, www) if not specified.
# #
my ($www) = tmccbossname(); if ($wgetserver eq "") {
($wgetserver) = tmccbossname();
if ($www =~ /^[-\w]+\.(.*)$/) { if ($wgetserver =~ /^[-\w]+\.(.*)$/) {
$www = "www.${1}"; $wgetserver = "www.${1}";
} }
else { else {
fatal("Tainted bossinfo $www!"); fatal("Tainted bossinfo $wgetserver!");
}
} }
$www = "https://${www}"; my $www = "https://$wgetserver";
#$www = "https://${www}/dev/stoller";
#$www = "http://golden-gw.ballmoss.com:9876/~stoller/testbed";
# #
# Okay, run wget with the proper arguments. # Okay, run wget with the proper arguments.
# #
my $cmd = "wget -nv -O $copyfile ". my $cmd = "wget -nv -O $copyfile ".
"--no-check-certificate ".
($debug ? "--server-response " : "") . ($debug ? "--server-response " : "") .
"'${www}/spewrpmtar.php3". "'${www}/spewrpmtar.php3".
"?nodeid=${nodeid}&file=${tarfile}&key=${keyhash}" . "?nodeid=${nodeid}&file=${tarfile}&key=${keyhash}" .
(defined($oldstamp) ? "&stamp=$oldstamp" : "") . (defined($oldstamp) ? "&stamp=$oldstamp" : "") .
(defined($oldmd5) ? "&md5=$oldmd5" : "") . (defined($oldmd5) ? "&md5=$oldmd5" : "") .
"'"; "'";
if ($debug) { if ($debug) {
print STDERR "$cmd\n"; print STDERR "$cmd\n";
...@@ -645,7 +621,7 @@ sub GetTarFile($$$$$$$) ...@@ -645,7 +621,7 @@ sub GetTarFile($$$$$$$)
while (<WGET>) { while (<WGET>) {
print $_ print $_
if ($debug); if ($debug);
# Ick! # Ick!
if ($_ =~ /^.* ERROR 304.*$/i) { if ($_ =~ /^.* ERROR 304.*$/i) {
$nochange = 1; $nochange = 1;
......
...@@ -111,7 +111,7 @@ sub doboot() ...@@ -111,7 +111,7 @@ sub doboot()
{ {
my @rpms = (); my @rpms = ();
my $errors = 0; my $errors = 0;
print STDOUT "Checking Testbed RPM configuration ... \n"; print STDOUT "Checking Testbed RPM configuration ... \n";
if (tmcc(TMCCCMD_RPM, undef, \@rpms) < 0) { if (tmcc(TMCCCMD_RPM, undef, \@rpms) < 0) {
...@@ -128,19 +128,50 @@ sub doboot() ...@@ -128,19 +128,50 @@ sub doboot()
# #
# Note: Windows also uses the -t option since root does not have access # Note: Windows also uses the -t option since root does not have access
# to NFS mounted FSes. # to NFS mounted FSes.
# #
my $installoption = ((REMOTE() || SHADOW() || WINDOWS()) ? "-t" : "-c"); my $MAXCPSIZE = (256 * 1024 * 1024);
my $useweb = (REMOTE() || SHADOW() || WINDOWS()) ? 1 : 0;
foreach my $rpm (@rpms) { foreach my $rpm (@rpms) {
if ($rpm =~ /RPM=(.+)/) { if ($rpm =~ /(?:SERVER=(\S+)\s+)?RPM=(.+)/) {
my $rpmline = sprintf($RPMINSTALL, $installoption, $1); my $server = $1;
my $rpm = $2;
my $installoption = $useweb ? "-t" : "-c";
#
# We also use -t if the file is large. This way we avoid
# thrashing the NFS server's link for an extended period
# (in particular, if we are using UDP-based NFS) and also
# avoids the stupid server race mentioned above. But we only
# do this if SERVER=user, since otherwise boss will have to
# get the file across NFS from the server before sending it
# to us via the web, which doesn't save any wear and tear
# on the NFS server link.
#
# Why "user" instead of "fs"? Because in a configuration
# where the fs node is seperate from the user node, we don't
# currently install a web server on fs.
#
if (!$useweb && $server && $server =~ /^users\./ &&
-s "$rpm" > $MAXCPSIZE) {
print STDOUT "NOTICE: downloading large RPM via https\n";
$installoption = "-t";
}
if ($server && $installoption eq "-t") {
$installoption .= " -S $server";
}
my $rpmline = sprintf($RPMINSTALL, $installoption, $rpm);
print STDOUT "Installing RPM $1\n"; $server = "www" if (!$server);
print STDOUT "$server:$rpm: Installing RPM\n";
my $stamp = time();
if (system($rpmline)) { if (system($rpmline)) {
if ($? >> 8 == 255) { if ($? >> 8 == 255) {
$errors++; $errors++;
} }
} }
print STDOUT "$server:$rpm: finished in ", time() - $stamp, " seconds\n";
} }
else { else {
warning("Bad RPM line: $rpm\n"); warning("Bad RPM line: $rpm\n");
......
...@@ -128,19 +128,51 @@ sub doboot() ...@@ -128,19 +128,51 @@ sub doboot()
# #
# Note: Windows also uses the -t option since root does not have access # Note: Windows also uses the -t option since root does not have access
# to NFS mounted FSes. # to NFS mounted FSes.
# #
my $installoption = ((REMOTE() || SHADOW() || WINDOWS()) ? "-t" : "-c"); my $MAXCPSIZE = (256 * 1024 * 1024);
my $useweb = (REMOTE() || SHADOW() || WINDOWS()) ? 1 : 0;
foreach my $tarball (@tarballs) { foreach my $tarball (@tarballs) {
if ($tarball =~ /DIR=(.+)\s+TARBALL=(.+)/) { if ($tarball =~ /(?:SERVER=(\S+)\s+)?DIR=(.+)\s+TARBALL=(.+)/) {
my $tbline = sprintf($TARINSTALL, $installoption, $1, $2); my $server = $1;
my $idir = $2;
my $tball = $3;
my $installoption = $useweb ? "-t" : "-c";
#
# We also use -t if the file is large. This way we avoid
# thrashing the NFS server's link for an extended period
# (in particular, if we are using UDP-based NFS) and also
# avoids the stupid server race mentioned above. But we only
# do this if SERVER=user, since otherwise boss will have to
# get the file across NFS from the server before sending it
# to us via the web, which doesn't save any wear and tear
# on the NFS server link.
#
# Why "user" instead of "fs"? Because in a configuration
# where the fs node is seperate from the user node, we don't
# currently install a web server on fs.
#
if (!$useweb && $server && $server =~ /^users\./ &&
-s "$tball" > $MAXCPSIZE) {
print STDOUT "NOTICE: downloading large tarball via https\n";
$installoption = "-t";
}
if ($server && $installoption eq "-t") {
$installoption .= " -S $server";
}
my $tbline = sprintf($TARINSTALL, $installoption, $idir, $tball);
print STDOUT "Installing Tarball $2 in dir $1\n"; $server = "www" if (!$server);
print STDOUT "$server:$tball: Installing tarball in $idir\n";
my $stamp = time();
if (system($tbline)) { if (system($tbline)) {
if ($? >> 8 == 255) { if ($? >> 8 == 255) {
$errors++; $errors++;
} }
} }
print STDOUT "$server:$tball: finished in ", time() - $stamp, " seconds\n";
} }
else { else {
warning("Bad Tarballs line: $tarball\n"); warning("Bad Tarballs line: $tarball\n");
......
#!/usr/bin/perl -w #!/usr/bin/perl -w
# #
# Copyright (c) 2004-2010 University of Utah and the Flux Group. # Copyright (c) 2004-2012 University of Utah and the Flux Group.
# #
# {{{EMULAB-LICENSE # {{{EMULAB-LICENSE
# #
...@@ -170,15 +170,15 @@ sub dotopomap() ...@@ -170,15 +170,15 @@ sub dotopomap()
unlink("$templtp"); unlink("$templtp");
if (! (USESFS() || WINDOWS() || REMOTEDED() || (FSRVTYPE() eq "LOCAL"))) { if (! (USESFS() || WINDOWS() || REMOTEDED() || (FSRVTYPE() eq "LOCAL"))) {
if (!forcecopy($topomap, $tempmap))</