Commit d0fd2185 authored by Leigh B. Stoller's avatar Leigh B. Stoller
Browse files

Add an event to the program agent that tells it to reload its user

environment from the environment strings contained in the event.
This is currently used when starting a new template run so that new
parameters can be passed along.
parent 8e2b9a20
......@@ -180,6 +180,18 @@ static void start_callback(event_handle_t handle,
event_notification_t notification,
void *data);
/**
* Handler for the RELOAD event, which tells the program agent to reload
* its environment, and includes the new environment strings.
*
* @param handle The connection to the event system.
* @param notification The start event.
* @param data NULL
*/
static void newenv_callback(event_handle_t handle,
event_notification_t notification,
void *data);
/**
* Start a program.
*
......@@ -719,6 +731,17 @@ main(int argc, char **argv)
fatal("could not subscribe to event");
}
tuple->objtype = TBDB_OBJECTTYPE_PROGRAM;
tuple->objname = ADDRESSTUPLE_ALL;
tuple->eventtype = TBDB_EVENTTYPE_RELOAD;
/*
* Subscribe to the RELOAD start event we specified above.
*/
if (! event_subscribe(handle, newenv_callback, tuple, NULL)) {
fatal("could not subscribe to event");
}
/*
* Begin the event loop, waiting to receive event notifications:
*/
......@@ -731,6 +754,10 @@ main(int argc, char **argv)
got_siginfo = 0;
}
#endif
if (got_sigterm) {
sigterm_handler();
/* Does not return */
}
}
elvin_sync_remove_io_handler(eih, elvin_error);
......@@ -982,6 +1009,46 @@ start_callback(event_handle_t handle,
}
}
static void
newenv_callback(event_handle_t handle,
event_notification_t notification,
void *data)
{
char envdata[2*BUFSIZ], buf[BUFSIZ];
char *bp, *cp;
FILE *file;
assert(handle != NULL);
assert(notification != NULL);
assert(data == NULL);
event_notification_get_string(handle, notification,
"environment", envdata, sizeof(envdata));
warning("New Environment received!\n");
warning("%s\n", envdata);
bp = cp = envdata;
while ((bp = strsep(&cp, "\n")) != NULL) {
/* XXX Kind of a stupid way to eval any variables. */
if ((file = popenf("echo %s", "r", bp)) != NULL) {
if (fgets(buf, sizeof(buf), file) != NULL) {
char *idx;
if ((idx = strchr(buf, '\n')) != NULL)
*idx = '\0';
if ((idx = strchr(buf, '=')) != NULL) {
*idx = '\0';
setenv(strdup(buf), idx + 1, 1);
}
}
pclose(file);
file = NULL;
}
}
}
/*
* There are three commands:
*
......
......@@ -90,7 +90,7 @@ my $eventcontrol= "$TB/bin/eventsys_control";
sub ParseArgs();
sub fatal($$);
sub sighandler($);
sub SendNewEnv();
#
# Testbed Support libraries
#
......@@ -100,6 +100,7 @@ use libtestbed;
use libtblog;
use libArchive;
use Template;
use event;
# Be careful not to exit on transient error
$libdb::DBQUERY_MAXTRIES = 0;
......@@ -302,27 +303,32 @@ if ($waitmode) {
POSIX::setsid();
}
# This sets the stop time.
$instance->StopCurrentRun() == 0
or fatal(-1, "Could not stop experiment run for $instance!");
#
# Might not be a current run, which is okay.
#
if (defined($instance->runidx())) {
# This sets the stop time.
$instance->StopCurrentRun() == 0
or fatal(-1, "Could not stop experiment run for $instance!");
# This runs loghole.
print "Asking loghole to sync the logfiles ... this will take a minute.\n";
$instance->LogHole() == 0
or fatal(-1, "Loghole failed");
# This runs loghole.
print "Asking loghole to sync the logfiles ... this will take a minute.\n";
$instance->LogHole() == 0
or fatal(-1, "Loghole failed");
print "Dumping the instance database ... this will take a minute.\n";
$instance->DumpDB() == 0
or fatal(-1, "Dump Database failed");
print "Dumping the instance database ... this will take a minute.\n";
$instance->DumpDB() == 0
or fatal(-1, "Dump Database failed");
#
# Commit the archive.
#
system("$archcontrol -t $runid commit $pid $eid");
#
# Commit the archive.
#
system("$archcontrol -t $runid commit $pid $eid");
# This has to be done after the archive commit, so we can find the tag.
$instance->FinalizeCurrentRun() == 0
or fatal(-1, "Could not finalize experiment run for $instance!");
# This has to be done after the archive commit, so we can find the tag.
$instance->FinalizeCurrentRun() == 0
or fatal(-1, "Could not finalize experiment run for $instance!");
}
goto done
if ($action eq "stop");
......@@ -349,7 +355,23 @@ if ($paramfile) {
$instance->NewRunBinding($name, $value) == 0
or fatal(-1, "Could not create new experiment run binding ".
"for $instance!");
#
# Hmm. Before we actually swapin, copy the parameters to the
# environment table so that they are available to the program
# agent when it starts up on the nodes (say, on reboot).
#
if (defined($value)) {
$value = DBQuoteSpecial($value);
}
else {
$value = "''";
}
DBQueryFatal("replace into virt_user_environment set ".
" name='$name', value=$value, ".
" pid='$pid', eid='$eid'");
}
SendNewEnv();
}
#
......@@ -529,7 +551,7 @@ sub fatal($$)
exit($errorstat);
}
sub sighandler ($) {
sub sighandler($) {
my ($signame) = @_;
$SIG{TERM} = 'IGNORE';
......@@ -539,6 +561,53 @@ sub sighandler ($) {
fatal(-1, "Caught SIG${signame}!");
}
#
# Send the new environement strings to the program agents as an event.
# This bypasses the scheduler and goes directly. Not sure if this is the
# best approach, but I like it better then restarting the agents and having
# them contact tmcd.
#
sub SendNewEnv()
{
my $URL = "elvin://" . TB_EVENTSERVER();
my $keyfile = TBDB_EVENTKEY($pid, $eid);
my $handle = event_register_withkeyfile($URL, 0, $keyfile);
fatal(-1, "Could not connect to event system!")
if (!$handle);
my $tuple = address_tuple_alloc();
fatal(-1, "Could not allocate an address tuple\n")
if (!$tuple);
%$tuple = (host => $event::ADDRESSTUPLE_ALL,
objtype => "PROGRAM",
objname => $event::ADDRESSTUPLE_ALL,
eventtype => "RELOAD",
expt => "$pid/$eid");
my $notification = event_notification_alloc($handle, $tuple);
fatal(-1, "Could not allocate a notification\n")
if (!$notification);
# Add in the new environ strings.
my $binding_string = "";
foreach my $name (keys(%parameters)) {
my $value = $parameters{$name};
$binding_string .= "$name=$value\n";
}
if (! event_notification_put_string($handle, $notification,
"environment", $binding_string)) {
fatal(-1, "Could not add environment strings to notification\n")
}
if (!event_notify($handle, $notification)) {
fatal(-1, "could not send environment event notification!");
}
}
END {
# Normal exit, nothing to do.
if (!$? || $justexit) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment