Commit 463ee6b1 authored by Timothy Stack's avatar Timothy Stack

Mote and robot related stuff.  The main thing is the addition of relay
capabilities to capture and related things.

	* GNUmakefile.in: Add the capture and tip subdirectories to the
	client and client-install targets.

	* configure, configure.in, config.h.in: Detect srandomdev() for
	capture and add "mote/newmote" script.

	* capture/GNUmakefile.in, capture/capture.c: Add "relay"
	capabilities to capture.

	* capture/capquery.c: Query the capserver for the relay receiver's
	port number.

	* capture/capserver.c: Small hack to return the port number
        for a node.

	* db/libdb.pm.in, db/xmlconvert.in: Add virt_tiptunnels table.

	* event/program-agent/program-agent.c: Change log file names to
	something a little more user-friendly.  Add a "MODIFY" event
	handler that lets the user set agent attributes (command, tag,
	timeout) without having to run a program.

	* event/sched/GNUmakefile.in, event/sched/console-agent.cc,
	event/sched/console-agent.h, event/sched/event-sched.c: Add
	console agents that can be used to snapshot a section of the
	capture log file.

	* event/sched/node-agent.cc: Some minor cleanup.

	* event/sched/simulator-agent.cc, event/sched/simulator-agent.h:
	Add the config data to the report mail.  Add a "RESET" event
	handler that runs "loghole clean".  Save the report mail in a file
	so it gets archived with the rest of the logs.

	* lib/libtb/tbdefs.h: Add CONSOLE object type.

	* mote/GNUmakefile.in, mote/newmote: Add newmote script, just a
	quick hack to add motes to the DB.

	* mote/tbuisp.in: Add another backend for loading motes through
	their relay capture server.

	* robots/mtp/mtp_dump.c: Dump the min/max values for x and y,
	handy for figuring out the bounds of the camera.

	* sql/database-fill.sql: Change the RELOAD-MOTE/SHUTDOWN ->
	ALWAYSUP/SHUTDOWN mode transition to ALWAYSUP/ISUP since stated
	doesn't seem to run triggers after a state change by a mode
	transition.

	* tbsetup/tbreport.in: Change the ordering of the eventlist so it
	displays event-sequences appropriately.

	* tbsetup/ns2ir/GNUmakefile.in, tbsetup/ns2ir/console.tcl,
	tbsetup/ns2ir/node.tcl, tbsetup/ns2ir/parse.tcl.in,
	tbsetup/ns2ir/sim.tcl.in: Add a "console" agent that represents
	the serial console for a node.

	* tbsetup/ns2ir/sequence.tcl: Add an "append" method so it is
	easier to build sequences dynamically.

	* tbsetup/ns2ir/topography.tcl: Make checkdest available to
	regular users.

	* tip/GNUmakefile.in, tip/tiptunnel.c: Add support for uploading a
	file to a relay version of capture and exporting the end
	connection as a pty.

	* tmcd/decls.h, tmcd/common/libsetup.pm: Bump version number since
	the dosubnodelist change is not backwards compatible.

	* tmcd/tmcd.c: Make dosubnodelist and dosubconfig callable even
	when a node isn't allocated.  Add dotiptunnels command that
	returns which serial consoles are to be mounted on a node.  Add
	mote version of subconfig that returns information needed to
	startup the relay version of capture.

	* tmcd/common/bootsubnodes: For motes, startup the relay version
	of capture (XXX stargate specific).

	* tmcd/common/libsetup.pm, tmcd/common/libtmcc.pm,
	tmcd/common/config/rc.config, tmcd/common/config/rc.tiptunnels:
	Client side changes for mounting another nodes serial line.

	* tmcd/common/rc.bootsetup: Always boot the subnodes, even when
	free.  This is used for motes since their capture needs to be up
	for reloading at the time.

	* tmcd/linux/ixpboot: Shuffle some code around so the script
	doesn't fail if the ixp isn't allocated.

	* utils/loghole.in: Add "digest.out" and "report.mail" as global
	logs to be saved in archives and display the "report.mail" file
	when showing a loghole archive.

	* xmlrpc/emulabserver.py.in: Scrub more of the return values to
	get rid of "None"s.
parent d75ced68
......@@ -114,6 +114,8 @@ ifeq ($(EVENTSYS),1)
@$(MAKE) -C event client
endif
@$(MAKE) -C os client
@$(MAKE) -C capture client
@$(MAKE) -C tip client
@$(MAKE) -C sensors client
@$(MAKE) -C tmcd client
......@@ -122,6 +124,8 @@ ifeq ($(EVENTSYS),1)
@$(MAKE) -C event client-install
endif
@$(MAKE) -C os client-install
@$(MAKE) -C capture client-install
@$(MAKE) -C tip client-install
@$(MAKE) -C sensors client-install
@$(MAKE) -C tmcd client-install
......
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2004 University of Utah and the Flux Group.
# Copyright (c) 2000-2005 University of Utah and the Flux Group.
# All rights reserved.
#
......@@ -9,11 +9,14 @@ TESTBED_SRCDIR = @top_srcdir@
OBJDIR = ..
SUBDIR = capture
SYSTEM := $(shell uname -s)
include $(OBJDIR)/Makeconf
all: boss-all tipserv-all
boss-all: capserver
tipserv-all: capture capture-tty
tipserv-all: capture capture-tty capquery
client: capture capquery
include $(TESTBED_SRCDIR)/GNUmakerules
......@@ -25,25 +28,44 @@ DESTDIR=
# Define LOG_DROPS to record warnings in syslog whenever chars were dropped
# due to the output device/pty being full.
#
CFLAGS= -g -O2 -DLOG_DROPS -I${OBJDIR} -DLOG_TESTBED=$(LOG_TESTBED)
CFLAGS += -g -O2 -DLOG_DROPS -I${OBJDIR} -DLOG_TESTBED=$(LOG_TESTBED)
ifeq ($(SYSTEM),Linux)
ifeq ($(host_cpu),arm)
LDFLAGS += -static
else
CFLAGS += -I/usr/kerberos/include
LDFLAGS += -L/usr/kerberos/lib -lkrb5 -lk5crypto -lcom_err
endif
else
LDFLAGS += -static
endif
capture: capture.c capdecls.h
cc -static $(CFLAGS) -DUSESOCKETS -DWITHSSL -DPREFIX=\"$(TBROOT)\" -o capture $< -lssl -lcrypto
$(CC) $(CFLAGS) -DUSESOCKETS -DWITHSSL -DPREFIX=\"$(TBROOT)\" -o capture $< -lssl -lcrypto $(LDFLAGS)
capquery: capquery.c capdecls.h
$(CC) $(CFLAGS) -DPREFIX=\"$(TBROOT)\" -o $@ $<
capture-nossl: capture.c capdecls.h
cc $(CFLAGS) -DUSESOCKETS -DPREFIX=\"$(TBROOT)\" -o capture-nossl $<
$(CC) $(CFLAGS) -DUSESOCKETS -DPREFIX=\"$(TBROOT)\" -o capture-nossl $<
capture-tty: capture.c capdecls.h
cc $(CFLAGS) -o capture-tty $<
$(CC) $(CFLAGS) -o capture-tty $<
capserver: capserver.c capdecls.h
cc $(CFLAGS) $(DBFLAGS) -o capserver $< \
$(CC) $(CFLAGS) $(DBFLAGS) -o capserver $< \
-L/usr/local/lib/mysql -lmysqlclient
#
# Do not capture install by default.
#
install: all $(INSTALL_SBINDIR)/capserver
$(INSTALL_PROGRAM) capture $(INSTALL_DIR)/opsdir/sbin/capture
client-install: client
$(INSTALL_PROGRAM) capture$(EXE) $(DESTDIR)$(CLIENT_BINDIR)/capture$(EXE)
$(INSTALL_PROGRAM) capquery$(EXE) $(DESTDIR)$(CLIENT_BINDIR)/capquery$(EXE)
real-install: all $(INSTALL_SBINDIR)/capserver $(INSTALL_SBINDIR)/capture
......
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2005 University of Utah and the Flux Group.
* All rights reserved.
*/
#include "config.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <syslog.h>
#include <assert.h>
#include <stdarg.h>
#include <sys/time.h>
#include <grp.h>
#include "capdecls.h"
static int debug = 0;
static char *usagestr =
"usage: capquery [-d] [-s server] [-p #] name\n"
" -d Turn on debugging.\n"
" -s server Specify a name to connect to.\n"
" -p portnum Specify a port number to connect to.\n"
"\n";
void
usage()
{
fprintf(stderr, usagestr);
exit(1);
}
static int
mygethostbyname(struct sockaddr_in *host_addr, char *host, int port)
{
struct hostent *host_ent;
int retval = 0;
assert(host_addr != NULL);
assert(host != NULL);
assert(strlen(host) > 0);
memset(host_addr, 0, sizeof(struct sockaddr_in));
#ifndef linux
host_addr->sin_len = sizeof(struct sockaddr_in);
#endif
host_addr->sin_family = AF_INET;
host_addr->sin_port = htons(port);
if( (host_ent = gethostbyname(host)) != NULL ) {
memcpy((char *)&host_addr->sin_addr.s_addr,
host_ent->h_addr,
host_ent->h_length);
retval = 1;
}
else {
retval = inet_aton(host, &host_addr->sin_addr);
}
return( retval );
}
int
main(int argc, char **argv)
{
int sock, ch, rc, retval = EXIT_FAILURE;
int length, port = SERVERPORT;
char *server = BOSSNODE;
struct sockaddr_in sin;
whoami_t whoami;
while ((ch = getopt(argc, argv, "ds:p:")) != -1)
switch(ch) {
case 's':
server = optarg;
break;
case 'p':
port = atoi(optarg);
break;
case 'd':
debug++;
break;
case 'h':
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
if (argc != 1)
usage();
if (strlen(argv[0]) >= sizeof(whoami.name))
fprintf(stderr, "Name too long: %s\n", argv[0]);
if (getuid() != 0)
fprintf(stderr, "Must be run as root\n");
memset(&whoami, 0, sizeof(whoami));
strcpy(whoami.name, argv[0]);
whoami.portnum = -1;
if (!mygethostbyname(&sin, server, port))
fprintf(stderr, "Bad server name: %s\n", server);
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
perror("socket");
else if (bindresvport(sock, NULL) < 0)
perror("bindresvport");
else if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
perror("connect");
else if (write(sock, &whoami, sizeof(whoami)) != sizeof(whoami))
perror("write");
else if ((rc = read(sock, &port, sizeof(port))) != sizeof(port))
perror("read");
else {
printf("%d\n", port);
retval = EXIT_SUCCESS;
}
close(sock);
return retval;
}
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2003 University of Utah and the Flux Group.
* Copyright (c) 2000-2003, 2005 University of Utah and the Flux Group.
* All rights reserved.
*/
......@@ -137,6 +137,8 @@ main(int argc, char **argv)
unsigned char buf[BUFSIZ], node_id[64];
secretkey_t secretkey;
tipowner_t tipown;
void *reply = &tipown;
size_t reply_size = sizeof(tipown);
if ((clientsock = accept(tcpsock,
(struct sockaddr *)&client,
......@@ -193,9 +195,9 @@ main(int argc, char **argv)
* message in the log file. Local tip will still work but
* remote tip will not.
*/
res = mydb_query("select server,node_id from tiplines "
res = mydb_query("select server,node_id,portnum from tiplines "
"where tipname='%s'",
2, whoami.name);
3, whoami.name);
if (!res) {
syslog(LOG_ERR, "DB Error getting tiplines for %s!",
whoami.name);
......@@ -209,6 +211,8 @@ main(int argc, char **argv)
}
row = mysql_fetch_row(res);
strcpy(node_id, row[1]);
port = -1;
sscanf(row[2], "%d", &port);
mysql_free_result(res);
/*
......@@ -246,15 +250,19 @@ main(int argc, char **argv)
}
mysql_free_result(res);
if (whoami.portnum == -1) {
reply = &port;
reply_size = sizeof(port);
}
/*
* Update the DB.
*/
if (mydb_update("update tiplines set portnum=%d, "
"keylen=%d, keydata='%s' "
"where tipname='%s'",
whoami.portnum,
whoami.key.keylen, whoami.key.key,
whoami.name)) {
else if (mydb_update("update tiplines set portnum=%d, "
"keylen=%d, keydata='%s' "
"where tipname='%s'",
whoami.portnum,
whoami.key.keylen, whoami.key.key,
whoami.name)) {
syslog(LOG_ERR, "DB Error updating tiplines for %s!",
whoami.name);
goto done;
......@@ -263,13 +271,13 @@ main(int argc, char **argv)
/*
* And now send the reply.
*/
if ((cc = write(clientsock, &tipown, sizeof(tipown))) <= 0) {
if ((cc = write(clientsock, reply, reply_size)) <= 0) {
if (cc < 0)
syslog(LOG_ERR, "Writing reply: %m");
syslog(LOG_ERR, "Connection aborted (write)");
goto done;
}
if (cc != sizeof(tipown)) {
if (cc != reply_size) {
syslog(LOG_ERR, "Wrong byte count (write)!");
goto done;
}
......
This diff is collapsed.
......@@ -30,5 +30,7 @@
#undef EVENTSERVER
#undef BOSSEVENTPORT
#undef HAVE_SRANDOMDEV
#undef HAVE_LINUX_VIDEODEV_H
#undef HAVE_MEZZANINE
......@@ -1222,6 +1222,62 @@ fi
for ac_func in srandomdev
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:1229: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1234 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
builtin and then its argument prototype would still apply. */
char $ac_func();
int main() {
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
choke me
#else
$ac_func();
#endif
; return 0; }
EOF
if { (eval echo configure:1257: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
eval "ac_cv_func_$ac_func=no"
fi
rm -f conftest*
fi
if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
echo "$ac_t""yes" 1>&6
ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
cat >> confdefs.h <<EOF
#define $ac_tr_func 1
EOF
else
echo "$ac_t""no" 1>&6
fi
done
#
......@@ -1854,17 +1910,17 @@ for ac_hdr in ulxmlrpcpp/ulxr_config.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:1858: checking for $ac_hdr" >&5
echo "configure:1914: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1863 "configure"
#line 1919 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1868: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:1924: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
......@@ -1903,17 +1959,17 @@ for ac_hdr in linux/videodev.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:1907: checking for $ac_hdr" >&5
echo "configure:1963: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1912 "configure"
#line 1968 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1917: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:1973: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
......@@ -1946,7 +2002,7 @@ done
# Extract the first word of "gtk-config", so it can be a program name with args.
set dummy gtk-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1950: checking for $ac_word" >&5
echo "configure:2006: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_GTK_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
......@@ -2025,7 +2081,7 @@ fi
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
echo "configure:2029: checking for a BSD compatible install" >&5
echo "configure:2085: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
......@@ -2086,7 +2142,7 @@ esac
# Extract the first word of "rsync", so it can be a program name with args.
set dummy rsync; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:2090: checking for $ac_word" >&5
echo "configure:2146: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_RSYNC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
......@@ -2256,7 +2312,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
dhcpd/dhcpd.conf.template dhcpd/GNUmakefile \
install/GNUmakefile install/ops-install install/boss-install \
install/newnode_sshkeys/GNUmakefile install/smb.conf.head \
mote/GNUmakefile mote/tbuisp mote/tbsgmotepower \
mote/GNUmakefile mote/tbuisp mote/tbsgmotepower mote/newmote \
robots/GNUmakefile robots/tbsetdest/GNUmakefile \
robots/mtp/GNUmakefile robots/emc/GNUmakefile \
robots/emc/test_emcd.sh robots/emc/loclistener \
......
......@@ -57,6 +57,8 @@ AC_PATH_PROG(JAR,jar)
AC_CHECK_TOOL(SSH,ssh)
AC_CHECK_FUNCS(srandomdev)
AC_SUBST(optional_subdirs)
#
......@@ -751,7 +753,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
dhcpd/dhcpd.conf.template dhcpd/GNUmakefile \
install/GNUmakefile install/ops-install install/boss-install \
install/newnode_sshkeys/GNUmakefile install/smb.conf.head \
mote/GNUmakefile mote/tbuisp mote/tbsgmotepower \
mote/GNUmakefile mote/tbuisp mote/tbsgmotepower mote/newmote \
robots/GNUmakefile robots/tbsetdest/GNUmakefile \
robots/mtp/GNUmakefile robots/emc/GNUmakefile \
robots/emc/test_emcd.sh robots/emc/loclistener \
......
......@@ -3144,6 +3144,7 @@ sub TBRobotLabExpt($$)
"event_groups",
"firewalls",
"firewall_rules",
"virt_tiptunnels",
"ipsubnets",
"nsfiles");
......
......@@ -130,7 +130,11 @@ my %virtual_tables =
"firewall_rules" => { rows => undef,
tag => "firewall_rules",
row => "firewall_rule",
attrs => [ "fwname", "ruleno", "rule" ]}
attrs => [ "fwname", "ruleno", "rule" ]},
"virt_tiptunnels" => { rows => undef,
tag => "tiptunnels",
row => "tiptunnel",
attrs => [ "host", "vnode" ]}
);
# XXX
......
......@@ -182,6 +182,8 @@ static void start_program(struct proginfo *pinfo,
unsigned long token,
char *args);
static void set_program(struct proginfo *pinfo, char *args);
/**
* Stop a running program.
*
......@@ -825,12 +827,40 @@ callback(event_handle_t handle, event_notification_t notification, void *data)
else if (strcmp(event, TBDB_EVENTTYPE_KILL) == 0) {
signal_program(pinfo, args);
}
else if (strcmp(event, TBDB_EVENTTYPE_MODIFY) == 0) {
set_program(pinfo, args);
}
else {
error("Invalid event: %s\n", event);
return;
}
}
static char *fileext(char *path)
{
int has_token = 0, lpc, len;
char *retval = NULL;
assert(path != NULL);
len = strlen(path);
for (lpc = len - 1; lpc > 0; lpc--) {
if (path[lpc] == '.') {
if (has_token) {
retval = &path[lpc + 1];
}
else if (sscanf(&path[lpc + 1], "%*d") == 1) {
has_token = 1;
}
else {
retval = &path[lpc + 1];
}
}
}
return retval;
}
static void
start_callback(event_handle_t handle,
event_notification_t notification,
......@@ -880,20 +910,17 @@ start_callback(event_handle_t handle,
char path[1024];
while ((de = readdir(dir)) != NULL) {
unsigned int token = 0;
char ext[16];
char *ext = NULL;
if ((strlen(de->d_name) < sizeof(path)) &&
((sscanf(de->d_name,
"%[^.].%u.%16s",
path, &token, ext) == 3) ||
(sscanf(de->d_name,
"%[^.].%16s",
path, ext) == 2)) &&
(sscanf(de->d_name,
"%1024[^.].",
path) == 1) &&
(find_agent(path) != NULL) &&
((strcmp(ext, "out") == 0) ||
(strcmp(ext, "err") == 0) ||
(strcmp(ext, "status") == 0))) {
((ext = fileext(de->d_name)) != NULL) &&
((strncmp(ext, "out", 3) == 0) ||
(strncmp(ext, "err", 3) == 0) ||
(strncmp(ext, "status", 6) == 0))) {
snprintf(path,
sizeof(path),
"%s/%s",
......@@ -940,16 +967,16 @@ open_logfile(struct proginfo *pinfo, const char *type)
* agent name, the event token, and the type (e.g. out, err).
*/
snprintf(buf, sizeof(buf),
"%s/%s.%lu.%s",
LOGDIR, pinfo->name, pinfo->token, type);
"%s/%s.%s.%lu",
LOGDIR, pinfo->name, type, pinfo->token);
if ((retval = open(buf, O_WRONLY|O_CREAT|O_APPEND, 0640)) >= 0) {
/*
* We've successfully created the file, now create the
* symlinks to that refer to the last run and a tagged run.
*/
snprintf(buf, sizeof(buf),
"./%s.%lu.%s",
pinfo->name, pinfo->token, type);
"./%s.%s.%lu",
pinfo->name, type, pinfo->token);
snprintf(buf2, sizeof(buf2),
"%s/%s.%s",
LOGDIR, pinfo->name, type);
......@@ -968,16 +995,11 @@ open_logfile(struct proginfo *pinfo, const char *type)
}
static void
start_program(struct proginfo *pinfo, unsigned long token, char *args)
set_program(struct proginfo *pinfo, char *args)
{
int pid, in_fd, out_fd = -1, err_fd = -1;
assert(pinfo != NULL);
assert(args != NULL);
if (pinfo->pid != 0) {
warning("start_program: %s is still running: %d\n",
pinfo->name, pinfo->pid);
return;
}
/*
* The args string holds the command line to execute. We allow
* this to be reset in dynamic events, but is optional; the cuurent
......@@ -1043,17 +1065,30 @@ start_program(struct proginfo *pinfo, unsigned long token, char *args)
value = NULL;
}
}
}
static void
start_program(struct proginfo *pinfo, unsigned long token, char *args)
{
int pid, in_fd, out_fd = -1, err_fd = -1;
if (pinfo->pid != 0) {
warning("start_program: %s is still running: %d\n",
pinfo->name, pinfo->pid);
return;
}
set_program(pinfo, args);
gettimeofday(&pinfo->started, NULL);
pinfo->token = token;
if ((pinfo->timeout > 0) &&
(pinfo->timeout_handle =
elvin_sync_add_timeout(NULL,
pinfo->timeout * 1000,
timeout_callback,
pinfo,
pinfo,
elvin_error)) == NULL) {
error("Could not add timeout for %s!", pinfo->name);
}
......@@ -1525,13 +1560,16 @@ child_callback(elvin_io_handler_t handler,
}
}
else {
exit_code = status;
if (status == pi->expected_exit_code)
exit_code = 0;
else
exit_code = status;
}
/* Dump a status file and */
snprintf(path,
sizeof(path),
"%s/%s.%lu.status",
"%s/%s.status.%lu",
LOGDIR,
pi->name,
pi->token);
......@@ -1580,6 +1618,11 @@ child_callback(elvin_io_handler_t handler,
ru.ru_maxrss);
fclose(file);
}
snprintf(path,
sizeof(path),
"./%s.status.%lu",
pi->name,
pi->token);
snprintf(path2,
sizeof(path),
"%s/%s.status",
......@@ -1591,7 +1634,7 @@ child_callback(elvin_io_handler_t handler,
snprintf(path2,
sizeof(path),
"%s/%s.%s.status",
LOGDIR, pi->tag, pi->name);
LOGDIR, pi->name, pi->tag);
unlink(path2);
symlink(path, path2);
}
......
......@@ -46,6 +46,7 @@ version.c: event-sched.c
echo >$@ "char build_info[] = \"Built on `date +%d-%b-%Y` by `id -nu`@`hostname | sed 's/\..*//'`:`pwd`\";"
OBJS = \
console-agent.o \
error-record.o \
event-sched_rpc.o \
group-agent.o \
......@@ -62,7 +63,7 @@ event-sched_rrpc: $(OBJS) event-sched.h ../lib/libevent.a
$(CXX) $(CFLAGS) -static $(LDFLAGS) -o $@ $(OBJS) $(ULXRLIBS) $(LIBS)
DEPS = \
error-record.h event-sched.h group-agent.h listNode.h \
console-agent.h error-record.h event-sched.h group-agent.h listNode.h \
local-agent.h node-agent.h rpc.h simulator-agent.h timeline-agent.h \
../lib/event.h
......@@ -72,6 +73,7 @@ error-record.o: error-record.c $(DEPS)
local-agent.o: local-agent.c $(DEPS)
group-agent.o: group-agent.c $(DEPS)
simulator-agent.o: simulator-agent.cc $(DEPS)
console-agent.o: console-agent.cc $(DEPS)
node-agent.o: node-agent.cc $(DEPS)
event-sched_rpc.o: event-sched.c $(DEPS)
$(CC) $(CFLAGS) -DRPC -c -o $@ $<
......
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2004, 2005 University of Utah and the Flux Group.
* All rights reserved.
*/
#include "config.h"
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include "console-agent.h"
#ifndef min
#define min(x, y) ((x) < (y)) ? (x) : (y)
#endif
/**
* A "looper" function for console agents that dequeues and processes events
* for a particular console. This function will be passed to pthread_create
* when a new thread needs to be created to handle events.
*
* @param arg The console agent object to handle events for.
* @return NULL