Commit a0d0c95e authored by Kevin Atkinson's avatar Kevin Atkinson

Add support for all node "tb-set-tarfiles".

"tb-set-tarfiles" is like "tb-set-node-tarfiles" except that it
distributes the tarfile to all nodes rather than just one and that it
uses frisbee to distribute the file.

These changes involved 1) refactoring frisbee info from images table
into a new table, frisbee_blobs, 2) a new experiment_blobs table, and
3) a new tmcd command so the node knows how to get the files from the
server.

The changes where designed to be general purpose enough to eventually
support:
  1) Distributing arbitrary files (not just tarfiles) to nodes
  2) Perform arbitrary actions on those files
  3) Use arbitrary methods to get the files

As such the tmcd line is as follows:
  URL=* ACTION=*

where URL is currently:
  frisbee.mcast://<ADDR>/<FILE>
for example
  frisbee.mcast://234.16.184.192:18092/users/kevina/home-dir.tar.gz
and when we get around to using a master Frisbee server it could be
  frisbee://*
or it could be a file://, http://, etc.

and ACTION is currently:
  unpack:<LOCATION>
for example
  unpackt:/users
with future syntax to be determined.
parent c34c390c
......@@ -139,8 +139,9 @@ my %xmlfields =
"description" => ["description", $SLOT_OPTIONAL],
"path" => ["path", $SLOT_OPTIONAL],
"mtype_*" => ["mtype", $SLOT_OPTIONAL],
"load_address" => ["load_address", $SLOT_ADMINONLY],
"frisbee_pid" => ["frisbee_pid", $SLOT_ADMINONLY]);
#"load_address" => ["load_address", $SLOT_ADMINONLY],
#"frisbee_pid" => ["frisbee_pid", $SLOT_ADMINONLY]
);
#
# Need a list of node types. We join this over the nodes table so that
# we get a list of just the nodes that are currently in the testbed, not
......@@ -376,28 +377,28 @@ UserError("Node Types: Must select at least one node type")
#
# Only admins can edit the load_address or the frisbee pid.
#
if ($isadmin) {
if (exists($editimageid_args{"load_address"}) &&
$editimageid_args{"load_address"} ne "") {
$foo = escapeshellarg($editimageid_args{"load_address"});
if ($editimageid_args{"load_address"} ne $foo) {
UserError("Load Address: Contains illegal characters!");
}
}
# Frisbee_pid has already been checked to be a valid int coming from XML.
}
else { # Not isadmin.
if (exists($editimageid_args{"load_address"}) &&
$editimageid_args{"load_address"} ne $image->load_address()) {
UserError("Load Address: No permission, admin-only");
}
if (exists($editimageid_args{"frisbee_pid"}) &&
$editimageid_args{"frisbee_pid"} ne $image->frisbee_pid()) {
UserError("Frisbee PID: No permission, admin-only");
}
}
# XXX: Bring back functionally is some way
#if ($isadmin) {
# if (exists($editimageid_args{"load_address"}) &&
# $editimageid_args{"load_address"} ne "") {
# $foo = escapeshellarg($editimageid_args{"load_address"});
#
# if ($editimageid_args{"load_address"} ne $foo) {
# UserError("Load Address: Contains illegal characters!");
# }
# }
# # Frisbee_pid has already been checked to be a valid int coming from XML.
#}
#else { # Not isadmin.
# if (exists($editimageid_args{"load_address"}) &&
# $editimageid_args{"load_address"} ne $image->load_address()) {
# UserError("Load Address: No permission, admin-only");
# }
# if (exists($editimageid_args{"frisbee_pid"}) &&
# $editimageid_args{"frisbee_pid"} ne $image->frisbee_pid()) {
# UserError("Frisbee PID: No permission, admin-only");
# }
#}
#
# Mereusers are not allowed to create more than one osid/imageid mapping
......
......@@ -127,9 +127,9 @@ sub part4_osid($) { return field($_[0], "part4_osid"); }
sub default_osid($) { return field($_[0], "default_osid"); }
sub path($) { return field($_[0], "path"); }
sub magic($) { return field($_[0], "magic"); }
sub load_address($) { return field($_[0], "load_address"); }
sub frisbee_pid($) { return field($_[0], "frisbee_pid"); }
sub load_busy($) { return field($_[0], "load_busy"); }
#sub load_address($) { return field($_[0], "load_address"); }
#sub frisbee_pid($) { return field($_[0], "frisbee_pid"); }
#sub load_busy($) { return field($_[0], "load_busy"); }
sub ezid($) { return field($_[0], "ezid"); }
sub shared($) { return field($_[0], "shared"); }
sub global($) { return field($_[0], "global"); }
......@@ -370,7 +370,8 @@ sub EditImageid($$$$)
# (Others above already did their own updates.)
#
my %updates;
foreach my $col ("description", "path", "load_address", "frisbee_pid" ) {
#foreach my $col ("description", "path", "load_address", "frisbee_pid" ) {
foreach my $col ("description", "path") {
# Copy args we want so that others can't get through.
if (exists($argref->{$col})) {
$updates{$col} = $mods{$col} = $argref->{$col};
......@@ -659,25 +660,6 @@ sub UnLockTables($)
return 0;
}
#
# Bump the busy indicator to keep the frisbeed going.
#
sub KeepBusy($)
{
my ($self) = @_;
# Must be a real reference.
return -1
if (! ref($self));
my $imageid = $self->imageid();
DBQueryFatal("update images set load_busy=GREATEST(load_busy,1) " .
"where imageid='$imageid'");
return 0;
}
#
# Mark the update time in the record,
#
......
......@@ -72,6 +72,7 @@ my $debug = 0;
"virt_tiptunnels" => [ "host", "vnode" ],
"virt_parameters" => [ "name", "value" ],
"virt_paths" => [ "pathname", "segmentname"],
"experiment_blobs" => [ "path", "action" ],
);
#
......@@ -1193,5 +1194,10 @@ use vars qw(@ISA);
@ISA = "VirtExperiment::VirtTableRow";
use VirtExperiment;
package VirtExperiment::VirtTableRow::experiment_blobs;
use vars qw(@ISA);
@ISA = "VirtExperiment::VirtTableRow";
use VirtExperiment;
# _Always_ make sure that this 1 is at the end of the file...
1;
......@@ -53,10 +53,10 @@ open(STDERR, ">> $logname") or die("opening $logname for STDERR: $!");
open(STDOUT, ">> $logname") or die("opening $logname for STDOUT: $!");
#
# Clear the load_address field of the images table since any frisbee's
# Clear the frisbee_blobs table since any frisbee's
# that were running are obviously not running anymore!
#
DBQueryFatal("update images set load_address='',frisbee_pid=0,load_busy=0");
DBQueryFatel("delete from frisbee_blobs");
#
# Clear the event scheduler pids. Its okay to set them to zero since
......
......@@ -122,6 +122,9 @@ my %virtual_tables =
"virt_paths" => { rows => undef,
tag => "path_members",
row => "path_member"},
"experiment_blobs" => { rows => undef,
tag => "blobs",
row => "blob"},
# This is a fake table. See below. If we add more, lets generalize.
"external_sourcefiles" => { rows => undef,
tag => "nsfiles",
......
......@@ -43,6 +43,7 @@ endif
$(MAKE) -C syncd client
$(MAKE) -C dijkstra client
$(MAKE) -C genhostsfile client
$(MAKE) -C frisbee.redux client
client-install: client
-mkdir -p $(LBINDIR)
......@@ -59,6 +60,7 @@ endif
$(MAKE) -C syncd client-install
$(MAKE) -C dijkstra client-install
$(MAKE) -C genhostsfile client-install
$(MAKE) -C frisbee.redux client-install
subboss: client
$(MAKE) -C frisbee.redux all
......
......@@ -656,6 +656,22 @@ CREATE TABLE `eventlist` (
KEY `vnode` (`vnode`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Table structure for table `experiment_blobs`
--
DROP TABLE IF EXISTS `experiment_blobs`;
CREATE TABLE `experiment_blobs` (
`idx` int(11) unsigned NOT NULL auto_increment,
`pid` varchar(12) NOT NULL default '',
`eid` varchar(32) NOT NULL default '',
`exptidx` int(11) NOT NULL default '0',
`path` varchar(255) NOT NULL default '',
`action` varchar(255) NOT NULL default '',
PRIMARY KEY (`idx`),
UNIQUE KEY `exptidx` (`exptidx`, `path`, `action`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
--
-- Table structure for table `experiment_features`
--
......@@ -1319,6 +1335,23 @@ CREATE TABLE `fs_resources` (
KEY `fileidx` (`fileidx`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Table structure for table `frisbee_blobs`
--
DROP TABLE IF EXISTS `frisbee_blobs`;
CREATE TABLE `frisbee_blobs` (
`idx` int(11) unsigned NOT NULL auto_increment,
`path` varchar(255) NOT NULL default '',
`imageid` int(8) unsigned default NULL,
`load_address` text,
`frisbee_pid` int(11) default '0',
`load_busy` tinyint(4) NOT NULL default '0',
PRIMARY KEY (`idx`),
UNIQUE KEY `path` (`path`),
UNIQUE KEY `imageid` (`imageid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Table structure for table `global_policies`
--
......@@ -1565,9 +1598,6 @@ CREATE TABLE `images` (
`default_osid` int(8) unsigned NOT NULL default '0',
`path` tinytext,
`magic` tinytext,
`load_address` text,
`frisbee_pid` int(11) default '0',
`load_busy` tinyint(4) NOT NULL default '0',
`ezid` tinyint(4) NOT NULL default '0',
`shared` tinyint(4) NOT NULL default '0',
`global` tinyint(4) NOT NULL default '0',
......
......@@ -1039,6 +1039,9 @@ REPLACE INTO table_regex VALUES ('images','auth_key','text','regex','^[0-9a-fA-F
REPLACE INTO table_regex VALUES ('images','auth_uuid','text','regex','^[0-9a-fA-F]+$',0,0,NULL);
REPLACE INTO table_regex VALUES ('images','decryption_key','text','regex','^[0-9a-fA-F]+$',0,0,NULL);
REPLACE INTO table_regex VALUES ('experiment_blobs','path','text','redirect','default:text',0,0,NULL);
REPLACE INTO table_regex VALUES ('experiment_blobs','action','text','redirect','default:text',0,0,NULL);
REPLACE INTO table_regex VALUES ('default','tinytext_utf8','text','regex','^(?:[\\x20-\\x7E]|[\\xC2-\\xDF][\\x80-\\xBF]|\\xE0[\\xA0-\\xBF][\\x80-\\xBF]|[\\xE1-\\xEC\\xEE\\xEF][\\x80-\\xBF]{2}|\\xED[\\x80-\\x9F][\\x80-\\xBF])*$',0,256,'adopted from http://www.w3.org/International/questions/qa-forms-utf-8.en.php');
REPLACE INTO table_regex VALUES ('default','text_utf8','text','regex','^(?:[\\x20-\\x7E]|[\\xC2-\\xDF][\\x80-\\xBF]|\\xE0[\\xA0-\\xBF][\\x80-\\xBF]|[\\xE1-\\xEC\\xEE\\xEF][\\x80-\\xBF]{2}|\\xED[\\x80-\\x9F][\\x80-\\xBF])*$',0,65535,'adopted from http://www.w3.org/International/questions/qa-forms-utf-8.en.php');
REPLACE INTO table_regex VALUES ('default','fulltext_utf8','text','regex','^(?:[\\x09\\x0A\\x0D\\x20-\\x7E]|[\\xC2-\\xDF][\\x80-\\xBF]|\\xE0[\\xA0-\\xBF][\\x80-\\xBF]|[\\xE1-\\xEC\\xEE\\xEF][\\x80-\\xBF]{2}|\\xED[\\x80-\\x9F][\\x80-\\xBF])*$',0,65535,'adopted from http://www.w3.org/International/questions/qa-forms-utf-8.en.php');
......
use strict;
use libdb;
#
# Refactor frisbee info into its own table and create new
# experiment_blobs table
#
my $running_frisbee_messages = <<EOF;
You appear to have running frisbee servers. Please make sure the
testbed is shutdown before applying this upgrade. This should normally
be taken care of automatically if you use "gmake update-testbed". If
the testbed is shutdown than see the instruction at the end of
sql/updates/4/XXX for how to rectify the situation.
EOF
chop $running_frisbee_messages;
sub DoUpdate($$$)
{
my ($dbhandle, $dbname, $version) = @_;
if (DBSlotExists("images", "load_address")) {
my $query_result =
DBQueryFatal("select load_address, frisbee_pid from images where load_address != '' or frisbee_pid != 0");
if ($query_result->numrows) {
Fatal($running_frisbee_messages);
}
DBQueryFatal("alter table images drop load_address, drop frisbee_pid, drop load_busy");
}
if (!DBTableExists("frisbee_blobs")) {
DBQueryFatal("CREATE TABLE `frisbee_blobs` ("
." `idx` int(11) unsigned NOT NULL auto_increment,"
." `path` varchar(255) NOT NULL default '',"
." `imageid` int(8) unsigned default NULL,"
." `load_address` text,"
." `frisbee_pid` int(11) default '0',"
." `load_busy` tinyint(4) NOT NULL default '0',"
." PRIMARY KEY (`idx`),"
." UNIQUE KEY `path` (`path`),"
." UNIQUE KEY `imageid` (`imageid`)"
.") ENGINE=MyISAM DEFAULT CHARSET=latin1");
}
if (!DBTableExists("experiment_blobs")) {
DBQueryFatal("CREATE TABLE `experiment_blobs` ("
." `idx` int(11) unsigned NOT NULL auto_increment,"
." `pid` varchar(12) NOT NULL default '',"
." `eid` varchar(32) NOT NULL default '',"
." `exptidx` int(11) NOT NULL default '0',"
." `path` varchar(255) NOT NULL default '',"
." `action` varchar(255) NOT NULL default '',"
." PRIMARY KEY (`idx`),"
." UNIQUE KEY `exptidx` (`exptidx`, `path`, `action`)"
.") ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=latin1");
}
DBQueryFatal("REPLACE INTO table_regex VALUES "
."('experiment_blobs','path','text','redirect','default:text',0,0,NULL)");
DBQueryFatal("REPLACE INTO table_regex VALUES "
."('experiment_blobs','action','text','redirect','default:text',0,0,NULL)");
return 0;
}
1;
#
# Dealing with stale database state:
#
# If you made sure the testbed was shutdown and you are still having
# problems running this script it is likely that there is some stale
# database state in the table. To rectify the situation, make sure
# there are no running frisbee servers:
# ps xa | grep "frisbeed"
# than execute the following query to clean out the state:
# update images set load_address = '', frisbee_pid = 0
# and try the update process again
#
......@@ -12,13 +12,14 @@ use Sys::Syslog;
use English;
use Socket;
use Errno;
use Cwd 'realpath';
#
# This also kills a running frisbee.
#
sub usage()
{
print "Usage: $0 [-d] [-k] <imageid>\n";
print "Usage: $0 [-d] [-k] <imageid or path>\n";
print "-k: Kill running frisbee.\n";
print "-d: Print debugging output.\n";
exit(1);
......@@ -54,14 +55,16 @@ use User;
use Image;
# Protos.
sub Refresh();
sub LockTables();
sub UnlockTables();
sub PickAddress();
sub SetAddress($);
sub SetPid($);
sub TestBusy();
sub KeepBusy();
sub ClearPid();
sub ClearAddress();
sub ClearEntry();
sub Fatal($);
sub debug($);
......@@ -99,28 +102,53 @@ usage()
my $this_user = User->ThisUser();
#
# Grab the Image.
# Determine if we have an imageid or a filename and take
# appropriate action
#
my $image = Image->Lookup($ARGV[0]);
if (! defined($image)) {
Fatal("No such image in the Emulab Database.\n");
}
my $imageid = $image->imageid();
my $filename = $image->path();
my $image;
my $imageid;
my $filename;
if ($ARGV[0] =~ /^(\/.+)$/) {
$filename = $1;
#
# Make sure that the user has sufficient permissions.
#
if (defined($this_user) &&
!$image->AccessCheck($this_user,
($killmode ? TB_IMAGEID_DESTROY :
TB_IMAGEID_READINFO))) {
Fatal("Not enough permission!");
}
if (!-R $filename) {
Fatal("You do not have permission to read the file: $filename");
}
if (!$killmode && !$ELABINELAB && ! -R $filename) {
Fatal("You do not have permission to read the image file for".
"$image: $filename\n");
if ($UID != 0) {
my $fn = realpath($filename);
my @valid_prefixes = qw(/groups /proj /users /share);
push @valid_prefixes, "/scratch" if "@FSDIR_SCRATCH@";
my $test = join('|', map {"^$_"} @valid_prefixes);
if ($fn !~ /$test/) {
Fatal("$fn (after resolving symbolic links) must be in one of: @valid_prefixes");
}
}
} else {
#
# Grab the Image.
#
$image = Image->Lookup($ARGV[0]);
if (! defined($image)) {
Fatal("No such image in the Emulab Database.\n");
}
$imageid = $image->imageid();
$filename = $image->path();
#
# Make sure that the user has sufficient permissions.
#
if (defined($this_user) &&
!$image->AccessCheck($this_user,
($killmode ? TB_IMAGEID_DESTROY :
TB_IMAGEID_READINFO))) {
Fatal("Not enough permission!");
}
if (!$killmode && !$ELABINELAB && ! -R $filename) {
Fatal("You do not have permission to read the image file for".
"$image: $filename\n");
}
}
#
......@@ -139,8 +167,23 @@ my $naddress = PickAddress()
LockTables();
# Try to discover if some other process is handling this address
my $address = $image->load_address();
my $pid = $image->frisbee_pid();
debug("creating table row if it doesn't already exist\n");
my $path_db = DBQuoteSpecial($filename);
my $imageid_db = defined $imageid ? $imageid : "NULL";
DBQueryFatal("insert ignore into frisbee_blobs (path,imageid) values ($path_db, $imageid_db)")
unless $killmode;
my $idx;
my $address;
my $pid;
my $load_busy;
my $frisbee_query = DBQueryFatal("select idx,load_address,frisbee_pid,load_busy,imageid ".
" from frisbee_blobs where path = $path_db");
if ($frisbee_query->num_rows) {
my $imageid_check;
($idx,$address, $pid, $load_busy,$imageid_check) = $frisbee_query->fetchrow_array();
# XXX: If $imageid is defined make sure it matches $imageid_check
}
#debug("idx=$idx address=$address pid=$pid busy=$load_busy\n");
if ($killmode) {
#
......@@ -164,7 +207,7 @@ if ($killmode) {
SENDMAIL($TBOPS,
"Frisbee Killer Inconsistency",
"Image: $image\n".
"File: $filename\n".
$mesg);
}
elsif ($address && !$pid) {
......@@ -174,10 +217,7 @@ if ($killmode) {
# try again. If still no pid, bail.
#
sleep(1);
$image->Refresh();
$address = $image->load_address();
$pid = $image->frisbee_pid();
Refresh();
# Okay, situation resolved itself; other frisbeelauncher bailed.
exit(0)
......@@ -191,7 +231,7 @@ if ($killmode) {
SENDMAIL($TBOPS,
"Frisbee Killer Failed!",
"Image: $image\n".
"File: $filename\n".
$mesg);
Fatal($mesg);
......@@ -207,15 +247,15 @@ if ($killmode) {
if (! kill('TERM', $pid)) {
SENDMAIL($TBOPS,
"Frisbee Killer Failed!",
"Failed to stop frisbee daemon for $image\n".
"Failed to stop frisbee daemon for $filename\n".
"Could not kill(TERM) process $pid: $? $!");
Fatal("Failed to stop frisbee daemon for $image!");
Fatal("Failed to stop frisbee daemon for $filename!");
}
}
else {
# The original process is gone, so just clear the DB state.
ClearAddress();
ClearEntry();
}
exit(0);
}
......@@ -224,9 +264,9 @@ if ($killmode) {
# Keep the current frisbeed running for another time period.
#
if ($address) {
$image->KeepBusy();
KeepBusy();
UnlockTables();
debug("A server ($address) is already running for image $image\n");
debug("A server ($address) is already running for image $filename\n");
exit(0);
}
......@@ -242,7 +282,7 @@ if ($pid) {
SENDMAIL($TBOPS,
"Frisbee Startup Failure!",
"Image: $image\n".
"File: $filename\n".
$mesg);
Fatal($mesg);
}
......@@ -271,7 +311,7 @@ debug("Picked address $address\n");
# downloaded image if interrupted. We also record our pid so that -k will
# work in another frisbeelauncher instance.
#
if ($ELABINELAB && ! -e $filename) {
if ($ELABINELAB && ! -e $filename && defined $imageid) {
debug("Fetching image $filename ($imageid) from real boss\n");
$SIG{HUP} = $SIG{INT} = $SIG{TERM} = \&cleanup;
SetPid($PID);
......@@ -297,7 +337,7 @@ if (my $childpid = TBBackGround($LOGFILE)) {
my $foo = waitpid($childpid, &WNOHANG);
if ($foo) {
LockTables();
ClearAddress();
ClearEntry();
UnlockTables();
Fatal("Error $? backgrounding frisbeelauncher!");
}
......@@ -375,7 +415,7 @@ while (1) {
next;
}
SENDMAIL($TBOPS, "Frisbeed Failed!",
"Image: $image\n".
"File: $filename\n".
"Address: $address\n\n".
"Process $child_pid exited with value $err.\n".
"Please look at the syslog for frisbeed!\n\n".
......@@ -400,14 +440,17 @@ while (1) {
my $addr = $1;
my $port = $2;
if (!exec("$FRISBEED $args -m $addr -p $port $filename")) {
# pass args in as array to avoid shell and hence problems
# with unsafe characters in $filename
if (!exec($FRISBEED, split(' ', "$args -m $addr -p $port"), $filename)) {
Fatal("$$: Unable to exec $FRISBEED");
}
}
Fatal("$$: Bad address format: $address!");
}
}
ClearAddress();
debug("Done.\n");
ClearEntry();
UnlockTables();
exit(0);
......@@ -425,19 +468,30 @@ sub debug($)
if ($debug);
}
sub Refresh()
{
my $frisbee_query = DBQueryFatal("select load_address,frisbee_pid,load_busy ".
" from frisbee_blobs where idx = $idx");
if ($frisbee_query->num_rows) {
($address,$pid,$load_busy) = $frisbee_query->fetchrow_array();
} else {
undef $address;
undef $pid;
undef $load_busy;
}
}
# Lock the tables used in this script
sub LockTables()
{
debug("Locking tables\n");
if ($image->LockTables("images write") != 0) {
Fatal("Error locking tables");
}
DBQueryFatal("lock table frisbee_blobs write");
}
# Unlock the tables used in this script
sub UnlockTables()
{
$image->UnLockTables();
DBQueryFatal("unlock tables");
debug("Unlocked tables\n");
}
......@@ -489,7 +543,7 @@ sub PickAddress()
my $msg = "Doing one-time creation of frisbee_index in emulab_indicies table";
SENDMAIL($TBOPS,
"FrisbeeLauncher Notice!",
"Image: $image\n".
"File: $filename\n".
$msg);
$idx = CreateIndex();
......@@ -516,7 +570,7 @@ sub PickAddress()
SENDMAIL($TBOPS,
"FrisbeeLauncher Failed!",
"Image: $image\n".
"File: $filename\n".
$mesg);
Fatal($mesg);
......@@ -536,22 +590,20 @@ sub SetAddress($)
{
my ($address) = @_;
$image->Update({"load_address" => $address, "load_busy" => 1}) == 0 or
Fatal("Could not update load address for $image");
DBQueryFatal("update frisbee_blobs set load_address = \"$address\", load_busy = 1 where idx=$idx");
Refresh();
}
#
# Clear out the address (and pid) registered to this process
# Might be called with tables locked.
#
sub ClearAddress()
sub ClearEntry()
{
debug("Clearing out registered load_address and pid\n");
$image->Update({"load_address" => '',
"load_busy" => 0,
"frisbee_pid" => 0}) == 0 or
Fatal("Could not clear load address for $image");
DBQueryFatal("delete from frisbee_blobs where idx=$idx");
Refresh();
}
#
......@@ -561,13 +613,14 @@ sub ClearAddress()
sub SetPid($)
{
my ($pid) = @_;
$image->Update({"frisbee_pid" => $pid}) == 0 or
Fatal("Could not update load address for $image");
DBQueryFatal("update frisbee_blobs set frisbee_pid = $pid where idx=$idx");
Refresh();
}
sub ClearPid()
{
SetPid(0);
DBQueryFatal("update frisbee_blobs set frisbee_pid = 0 where idx=$idx");
Refresh();
}
#
......@@ -576,17 +629,27 @@ sub ClearPid()
#
sub TestBusy()
{
my $busy = $image->load_busy();
my $busy = $load_busy;
if ($busy) {
if ($image->Update({"load_busy" => 0}) != 0) {
UnlockTables();
Fatal("Could not clear busy for $image");
}
DBQueryFatal("update frisbee_blobs set load_busy = 0 where idx=$idx");
Refresh();
}
return $busy;
}
#
# Bump the busy indicator to keep the frisbeed going.
#
sub KeepBusy()
{
DBQueryFatal("update frisbee_blobs set load_busy=GREATEST(load_busy,1) " .
"where idx=$idx");
Refresh();
return 0;
}
#
# Kill off our child process, if started, and clear out registered address
# Also, die off
......@@ -602,7 +665,7 @@ sub cleanup
if ($child_pid) {
kill(15, $child_pid);
}
ClearAddress();
ClearEntry();
exit(1);
}
......
......@@ -28,6 +28,7 @@ proc tb-set-node-rpms {node args} {}
proc tb-set-node-startup {node cmd} {}
proc tb-set-node-cmdline {node cmd} {}
proc tb-set-node-tarfiles {node args} {}
proc tb-set-tarfiles {args} {}
proc tb-set-node-lan-delay {node lan delay} {}
proc tb-set-node-lan-bandwidth {node lan bw} {}
proc tb-set-node-lan-loss {node lan loss} {}
......
......@@ -751,6 +751,13 @@ Simulator instproc run {} {
}
}
if [info exists ::TBCOMPAT::tarfiles] {
foreach tarfile $::TBCOMPAT::tarfiles {
set path [lindex $tarfile 1]
set dest [lindex $tarfile 0]
$self spitxml_data "experiment_blobs" [list "path" "action"] [list $path "unpack:$dest"]
}
}
$self spitxml_finish
}
......
......@@ -442,17 +442,18 @@ proc tb-set-node-rpms {node args} {
proc tb-set-node-startup {node cmd} {
$node set startup $cmd
}
proc tb-set-node-tarfiles {node args} {
if {$args == {}} {
perror "\[tb-set-node-tarfiles] tb-set-node-tarfiles <node> (<dir> <tar>)+"
return
}
proc tb-proc-tarfiles {cmd args0} { ; # args has special meaning that we
# don't want here
set SHAREDNFS [expr {! "@NOSHAREDFS@"}]
set args $args0
# Lets assume that a single argument is a string and break it up.
if {[llength $args] == 1} {
set args [split [lindex $args 0] " "]
}