Commit 1f16a276 authored by Timothy Stack's avatar Timothy Stack
Browse files

Make the dots move on the robot map web page:

	* configure, configure.in: Add robots/emc/loclistener.

	* event/lib/event.h, event/lib/event.c: Add some helper functions
	for sending events and parsing args.

	* event/lib/tbevent.py.tail, event/lib/tbevent.py: Add support for
	clients that register using keyfiles.

	* robots/emc/GNUmakefile.in: Install loclistener on boss.

	* robots/emc/emcd.h, robots/emc/emcd.c: Send update events every
	two seconds with the node's location.  Fill out a little more of
	the event callback, not sure what to do with the requested
	destination though.  Add some code to the vmc callback to store
	position updates.  Changed the config file format to also include
	the vname of the robot.

	* robots/emc/loclistener.in: Listen for NODE MODIFY events with
	coordinates and update the database accordingly.  Kinda sucks, but
	it works.

	* robots/emc/test_emcd.config: Add vnames to the robots to reflect
	change in the config file format.

	* tbsetup/ns2ir/node.tcl: Add nodes to the virt_agents table.
parent ffa60e93
......@@ -1584,7 +1584,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
install/newnode_sshkeys/GNUmakefile \
mote/GNUmakefile mote/tbuisp \
robots/GNUmakefile robots/mtp/GNUmakefile robots/emc/GNUmakefile \
robots/emc/test_emcd.sh "
robots/emc/test_emcd.sh robots/emc/loclistener "
#
# Do this for easy distclean.
......
......@@ -614,7 +614,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
install/newnode_sshkeys/GNUmakefile \
mote/GNUmakefile mote/tbuisp \
robots/GNUmakefile robots/mtp/GNUmakefile robots/emc/GNUmakefile \
robots/emc/test_emcd.sh "
robots/emc/test_emcd.sh robots/emc/loclistener "
#
# Do this for easy distclean.
......
......@@ -1611,3 +1611,222 @@ event_notification_unpack(event_handle_t handle,
return 0;
}
static char *match_quote(char *str)
{
char *retval = NULL;
int count;
assert(str != NULL);
assert(str[0] == '{');
for (count = 1, str++; (count > 0) && *str; str++) {
switch (*str) {
case '{':
count += 1;
break;
case '}':
count -= 1;
break;
default:
break;
}
}
if (count == 0)
retval = str - 1;
return retval;
}
int event_arg_get(char *args, char *key, char **value_out)
{
static char *WHITESPACE = " \t";
int retval = -1;
*value_out = NULL;
args += strspn(args, WHITESPACE);
while( (args[0] != '\0') && (retval < 0) ) {
char *key_end;
if (strlen(args) == 0) {
}
else if ((key_end = strchr(args, '=')) == NULL) {
errno = EINVAL;
break;
}
else if (strncasecmp(args, key, (key_end - args)) != 0) {
errno = ESRCH;
}
else if (key_end[1] == '{') {
char *value_end;
if ((value_end = match_quote(&key_end[1])) == NULL) {
errno = EINVAL;
break;
}
else {
*value_out = &key_end[2];
retval = (value_end - *value_out);
}
}
else if (key_end[1] == '\'') {
char *value_end;
*value_out = &key_end[2];
if ((value_end = strchr(*value_out, '\'')) == NULL) {
errno = EINVAL;
break;
}
else {
retval = (value_end - *value_out);
}
}
else {
*value_out = &key_end[1];
retval = strcspn(*value_out, WHITESPACE);
}
args += strcspn(args, WHITESPACE);
args += strspn(args, WHITESPACE);
}
return retval;
}
int event_arg_dup(char *args, char *key, char **value_out)
{
char *value;
int retval;
*value_out = NULL;
if ((retval = event_arg_get(args, key, &value)) >= 0) {
if ((*value_out = malloc(retval + 1)) != NULL) {
strncpy(*value_out, value, retval);
(*value_out)[retval] = '\0';
}
else {
retval = -1;
errno = ENOMEM;
}
}
return retval;
}
int event_do_v(event_handle_t handle, ea_tag_t tag, va_list args)
{
address_tuple_t tuple;
int retval = 0;
if ((tuple = address_tuple_alloc()) == NULL) {
ERROR("could not allocate address tuple");
errno = ENOMEM;
}
else {
char *arg_name, *event_args, *event_args_cursor;
char event_args_buffer[1024] = "";
struct timeval *when = NULL;
event_notification_t en;
event_args = event_args_buffer;
event_args_cursor = event_args_buffer;
while (tag != EA_TAG_DONE) {
switch (tag) {
case EA_Site:
tuple->site = va_arg(args, char *);
break;
case EA_Experiment:
tuple->expt = va_arg(args, char *);
break;
case EA_Group:
tuple->group = va_arg(args, char *);
break;
case EA_Host:
tuple->host = va_arg(args, char *);
break;
case EA_Type:
tuple->objtype = va_arg(args, char *);
break;
case EA_Name:
tuple->objname = va_arg(args, char *);
break;
case EA_Event:
tuple->eventtype = va_arg(args, char *);
break;
case EA_Arguments:
event_args = va_arg(args, char *);
break;
case EA_ArgInteger:
arg_name = va_arg(args, char *);
sprintf(event_args_cursor,
" %s=%d",
arg_name,
va_arg(args, int));
event_args_cursor += strlen(event_args_cursor);
break;
case EA_ArgFloat:
arg_name = va_arg(args, char *);
sprintf(event_args_cursor,
" %s=%f",
arg_name,
va_arg(args, double));
event_args_cursor += strlen(event_args_cursor);
break;
case EA_ArgString:
arg_name = va_arg(args, char *);
sprintf(event_args_cursor,
" %s=%s",
arg_name,
va_arg(args, char *));
event_args_cursor += strlen(event_args_cursor);
break;
case EA_When:
when = va_arg(args, struct timeval *);
break;
default:
ERROR("unknown tag value");
errno = EINVAL;
return 0;
}
tag = va_arg(args, ea_tag_t);
}
if ((en = event_notification_alloc(handle, tuple)) == NULL) {
ERROR("could not allocate notification");
errno = ENOMEM;
}
else {
struct timeval tv;
if (when == NULL) {
when = &tv;
gettimeofday(when, NULL);
}
if (strlen(event_args) > 0) {
event_notification_set_arguments(handle,
en,
event_args);
}
retval = event_schedule(handle, en, when);
event_notification_free(handle, en);
en = NULL;
}
address_tuple_free(tuple);
tuple = NULL;
}
return retval;
}
int event_do(event_handle_t handle, ea_tag_t tag, ...)
{
va_list args;
int retval;
va_start(args, tag);
retval = event_do_v(handle, tag, args);
va_end(args);
return retval;
}
......@@ -214,6 +214,28 @@ int event_notification_unpack(event_handle_t handle,
event_notification_t *notification,
unsigned char *data, int len);
int event_arg_get(char *args, char *key, char **value);
int event_arg_dup(char *args, char *key, char **value);
typedef enum {
EA_TAG_DONE,
EA_Site,
EA_Experiment,
EA_Group,
EA_Host,
EA_Type,
EA_Name,
EA_Event,
EA_Arguments,
EA_ArgInteger,
EA_ArgFloat,
EA_ArgString,
EA_When,
} ea_tag_t;
int event_do_v(event_handle_t handle, ea_tag_t tag, va_list args);
int event_do(event_handle_t handle, ea_tag_t tag, ...);
/* util.c */
void *xmalloc(int size);
void *xrealloc(void *p, int size);
......
......@@ -698,19 +698,21 @@ SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]) {
#define SWIGTYPE_p_elvin_notification_t swig_types[12]
#define SWIGTYPE_event_notification_t swig_types[13]
#define SWIGTYPE_p_event_notification_t swig_types[14]
#define SWIGTYPE_event_notify_callback_t swig_types[15]
#define SWIGTYPE_p_callback_data swig_types[16]
#define SWIGTYPE_p_address_tuple swig_types[17]
#define SWIGTYPE_p_timeval swig_types[18]
#define SWIGTYPE_p_f_void__elvin_error_t swig_types[19]
#define SWIGTYPE_p_elvin_error_t swig_types[20]
#define SWIGTYPE_p_f_p_int_elvin_error_t__int swig_types[21]
#define SWIGTYPE_p_f_int_elvin_error_t__int swig_types[22]
#define SWIGTYPE_p_f_elvin_handle_t_elvin_error_t__int swig_types[23]
#define SWIGTYPE_callback_data_t swig_types[24]
#define SWIGTYPE_p_f_elvin_handle_t_elvin_notification_t_int_elvin_keys_t_elvin_error_t__int swig_types[25]
#define SWIGTYPE_p_int swig_types[26]
static swig_type_info *swig_types[28];
#define SWIGTYPE_p_p_char swig_types[15]
#define SWIGTYPE_p_va_list swig_types[16]
#define SWIGTYPE_event_notify_callback_t swig_types[17]
#define SWIGTYPE_p_callback_data swig_types[18]
#define SWIGTYPE_p_address_tuple swig_types[19]
#define SWIGTYPE_p_timeval swig_types[20]
#define SWIGTYPE_p_f_void__elvin_error_t swig_types[21]
#define SWIGTYPE_p_elvin_error_t swig_types[22]
#define SWIGTYPE_p_f_p_int_elvin_error_t__int swig_types[23]
#define SWIGTYPE_p_f_int_elvin_error_t__int swig_types[24]
#define SWIGTYPE_p_f_elvin_handle_t_elvin_error_t__int swig_types[25]
#define SWIGTYPE_callback_data_t swig_types[26]
#define SWIGTYPE_p_f_elvin_handle_t_elvin_notification_t_int_elvin_keys_t_elvin_error_t__int swig_types[27]
#define SWIGTYPE_p_int swig_types[28]
static swig_type_info *swig_types[30];
/* -------- TYPES TABLE (END) -------- */
......@@ -2420,6 +2422,100 @@ static PyObject *_wrap_event_notification_unpack(PyObject *self, PyObject *args)
}
static PyObject *_wrap_event_arg_get(PyObject *self, PyObject *args) {
PyObject *resultobj;
char *arg1 ;
char *arg2 ;
char **arg3 = (char **) 0 ;
int result;
PyObject * obj2 = 0 ;
if(!PyArg_ParseTuple(args,(char *)"ssO:event_arg_get",&arg1,&arg2,&obj2)) goto fail;
if ((SWIG_ConvertPtr(obj2,(void **) &arg3, SWIGTYPE_p_p_char,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail;
result = (int)event_arg_get(arg1,arg2,arg3);
resultobj = PyInt_FromLong((long)result);
return resultobj;
fail:
return NULL;
}
static PyObject *_wrap_event_arg_dup(PyObject *self, PyObject *args) {
PyObject *resultobj;
char *arg1 ;
char *arg2 ;
char **arg3 = (char **) 0 ;
int result;
PyObject * obj2 = 0 ;
if(!PyArg_ParseTuple(args,(char *)"ssO:event_arg_dup",&arg1,&arg2,&obj2)) goto fail;
if ((SWIG_ConvertPtr(obj2,(void **) &arg3, SWIGTYPE_p_p_char,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail;
result = (int)event_arg_dup(arg1,arg2,arg3);
resultobj = PyInt_FromLong((long)result);
return resultobj;
fail:
return NULL;
}
static PyObject *_wrap_event_do_v(PyObject *self, PyObject *args) {
PyObject *resultobj;
event_handle_t arg1 = (event_handle_t) 0 ;
int arg2 ;
va_list arg3 ;
int result;
va_list *argp3 ;
PyObject * obj0 = 0 ;
PyObject * obj2 = 0 ;
if(!PyArg_ParseTuple(args,(char *)"OiO:event_do_v",&obj0,&arg2,&obj2)) goto fail;
if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_event_handle_t,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail;
if ((SWIG_ConvertPtr(obj2,(void **) &argp3, SWIGTYPE_p_va_list,SWIG_POINTER_EXCEPTION) == -1)) SWIG_fail;
arg3 = *argp3;
result = (int)event_do_v(arg1,(ea_tag_t )arg2,arg3);
resultobj = PyInt_FromLong((long)result);
return resultobj;
fail:
return NULL;
}
static PyObject *_wrap_event_do__varargs__(PyObject *self, PyObject *args, PyObject *varargs) {
PyObject *resultobj;
event_handle_t arg1 = (event_handle_t) 0 ;
int arg2 ;
void *arg3 = 0 ;
int result;
PyObject * obj0 = 0 ;
if(!PyArg_ParseTuple(args,(char *)"Oi:event_do",&obj0,&arg2)) goto fail;
if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_event_handle_t,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail;
result = (int)event_do(arg1,(ea_tag_t )arg2,arg3);
resultobj = PyInt_FromLong((long)result);
return resultobj;
fail:
return NULL;
}
static PyObject *_wrap_event_do(PyObject *self, PyObject *args) {
PyObject *resultobj;
PyObject *varargs;
PyObject *newargs;
newargs = PyTuple_GetSlice(args,0,2);
varargs = PyTuple_GetSlice(args,2,PyTuple_Size(args)+1);
resultobj = _wrap_event_do__varargs__(self,newargs,varargs);
Py_XDECREF(newargs);
Py_XDECREF(varargs);
return resultobj;
}
static PyObject *_wrap_xmalloc(PyObject *self, PyObject *args) {
PyObject *resultobj;
int arg1 ;
......@@ -3035,6 +3131,10 @@ static PyMethodDef SwigMethods[] = {
{ (char *)"event_notification_insert_hmac", _wrap_event_notification_insert_hmac, METH_VARARGS },
{ (char *)"event_notification_pack", _wrap_event_notification_pack, METH_VARARGS },
{ (char *)"event_notification_unpack", _wrap_event_notification_unpack, METH_VARARGS },
{ (char *)"event_arg_get", _wrap_event_arg_get, METH_VARARGS },
{ (char *)"event_arg_dup", _wrap_event_arg_dup, METH_VARARGS },
{ (char *)"event_do_v", _wrap_event_do_v, METH_VARARGS },
{ (char *)"event_do", _wrap_event_do, METH_VARARGS },
{ (char *)"xmalloc", _wrap_xmalloc, METH_VARARGS },
{ (char *)"xrealloc", _wrap_xrealloc, METH_VARARGS },
{ (char *)"callback_data_callback_notification_set", _wrap_callback_data_callback_notification_set, METH_VARARGS },
......@@ -3083,6 +3183,8 @@ static swig_type_info _swigt__p_void[] = {{"_p_void", 0, "void *", 0},{"_p_void"
static swig_type_info _swigt__p_elvin_notification_t[] = {{"_p_elvin_notification_t", 0, "elvin_notification_t *", 0},{"_p_elvin_notification_t"},{0}};
static swig_type_info _swigt__event_notification_t[] = {{"_event_notification_t", 0, "event_notification_t", 0},{"_p_event_notification"},{"_event_notification_t"},{0}};
static swig_type_info _swigt__p_event_notification_t[] = {{"_p_event_notification_t", 0, "event_notification_t *", 0},{"_p_event_notification_t"},{0}};
static swig_type_info _swigt__p_p_char[] = {{"_p_p_char", 0, "char **", 0},{"_p_p_char"},{0}};
static swig_type_info _swigt__p_va_list[] = {{"_p_va_list", 0, "va_list *", 0},{"_p_va_list"},{0}};
static swig_type_info _swigt__event_notify_callback_t[] = {{"_event_notify_callback_t", 0, "event_notify_callback_t", 0},{"_event_notify_callback_t"},{0}};
static swig_type_info _swigt__p_callback_data[] = {{"_p_callback_data", 0, "callback_data *", 0},{"_p_callback_data"},{"_callback_data_t"},{0}};
static swig_type_info _swigt__p_address_tuple[] = {{"_p_address_tuple", 0, "address_tuple *", 0},{"_address_tuple_t"},{"_p_address_tuple"},{0}};
......@@ -3112,6 +3214,8 @@ _swigt__p_void,
_swigt__p_elvin_notification_t,
_swigt__event_notification_t,
_swigt__p_event_notification_t,
_swigt__p_p_char,
_swigt__p_va_list,
_swigt__event_notify_callback_t,
_swigt__p_callback_data,
_swigt__p_address_tuple,
......@@ -3141,6 +3245,19 @@ static swig_const_info swig_const_table[] = {
{ SWIG_PY_INT, (char *)"EVENT_SCHEDULE", (long) EVENT_SCHEDULE, 0, 0, 0},
{ SWIG_PY_INT, (char *)"EVENT_TRAFGEN_START", (long) EVENT_TRAFGEN_START, 0, 0, 0},
{ SWIG_PY_INT, (char *)"EVENT_TRAFGEN_STOP", (long) EVENT_TRAFGEN_STOP, 0, 0, 0},
{ SWIG_PY_INT, (char *)"EA_TAG_DONE", (long) EA_TAG_DONE, 0, 0, 0},
{ SWIG_PY_INT, (char *)"EA_Site", (long) EA_Site, 0, 0, 0},
{ SWIG_PY_INT, (char *)"EA_Experiment", (long) EA_Experiment, 0, 0, 0},
{ SWIG_PY_INT, (char *)"EA_Group", (long) EA_Group, 0, 0, 0},
{ SWIG_PY_INT, (char *)"EA_Host", (long) EA_Host, 0, 0, 0},
{ SWIG_PY_INT, (char *)"EA_Type", (long) EA_Type, 0, 0, 0},
{ SWIG_PY_INT, (char *)"EA_Name", (long) EA_Name, 0, 0, 0},
{ SWIG_PY_INT, (char *)"EA_Event", (long) EA_Event, 0, 0, 0},
{ SWIG_PY_INT, (char *)"EA_Arguments", (long) EA_Arguments, 0, 0, 0},
{ SWIG_PY_INT, (char *)"EA_ArgInteger", (long) EA_ArgInteger, 0, 0, 0},
{ SWIG_PY_INT, (char *)"EA_ArgFloat", (long) EA_ArgFloat, 0, 0, 0},
{ SWIG_PY_INT, (char *)"EA_ArgString", (long) EA_ArgString, 0, 0, 0},
{ SWIG_PY_INT, (char *)"EA_When", (long) EA_When, 0, 0, 0},
{0}};
#ifdef __cplusplus
......
......@@ -228,6 +228,27 @@ event_notification_pack = _tbevent.event_notification_pack
event_notification_unpack = _tbevent.event_notification_unpack
event_arg_get = _tbevent.event_arg_get
event_arg_dup = _tbevent.event_arg_dup
EA_TAG_DONE = _tbevent.EA_TAG_DONE
EA_Site = _tbevent.EA_Site
EA_Experiment = _tbevent.EA_Experiment
EA_Group = _tbevent.EA_Group
EA_Host = _tbevent.EA_Host
EA_Type = _tbevent.EA_Type
EA_Name = _tbevent.EA_Name
EA_Event = _tbevent.EA_Event
EA_Arguments = _tbevent.EA_Arguments
EA_ArgInteger = _tbevent.EA_ArgInteger
EA_ArgFloat = _tbevent.EA_ArgFloat
EA_ArgString = _tbevent.EA_ArgString
EA_When = _tbevent.EA_When
event_do_v = _tbevent.event_do_v
event_do = _tbevent.event_do
xmalloc = _tbevent.xmalloc
xrealloc = _tbevent.xrealloc
......@@ -453,7 +474,7 @@ class EventClient:
Event client class, mostly just wraps the SWIG'd versions of the functions.
"""
def __init__(self, server=None, port=None, url=None):
def __init__(self, server=None, port=None, url=None, keyfile=None):
"""
Construct an EventClient object.
......@@ -475,7 +496,14 @@ class EventClient:
url = url + ":" + port
pass
pass
self.handle = event_register(url, 0)
if keyfile:
self.handle = event_register_withkeyfile(url, 0, keyfile)
pass
else:
self.handle = event_register(url, 0)
pass
self.timeout = 0
if not _hack_handle:
......
......@@ -154,7 +154,7 @@ class EventClient:
Event client class, mostly just wraps the SWIG'd versions of the functions.
"""
def __init__(self, server=None, port=None, url=None):
def __init__(self, server=None, port=None, url=None, keyfile=None):
"""
Construct an EventClient object.
......@@ -176,7 +176,14 @@ class EventClient:
url = url + ":" + port
pass
pass
self.handle = event_register(url, 0)
if keyfile:
self.handle = event_register_withkeyfile(url, 0, keyfile)
pass
else:
self.handle = event_register(url, 0)
pass
self.timeout = 0
if not _hack_handle:
......
......@@ -11,7 +11,7 @@ SUBDIR = robots/emc
include $(OBJDIR)/Makeconf
PROGS = emcd
PROGS = emcd loclistener
TESTS = test_emcd.sh
all: $(PROGS)
......@@ -36,6 +36,7 @@ emcd: emcd.o robot_list.o ../mtp/libmtp.a
install: all
-mkdir -p $(INSTALL_DIR)/opsdir/sbin
$(INSTALL_PROGRAM) emcd $(INSTALL_DIR)/opsdir/sbin/emcd
$(INSTALL_PROGRAM) loclistener $(INSTALL_SBINDIR)/loclistener
clean:
rm -f *.o
......@@ -44,8 +44,10 @@
#include <signal.h>
#include <paths.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include "log.h"
......@@ -116,6 +118,10 @@ static int vmc_callback(elvin_io_handler_t handler,
void *rock,
elvin_error_t eerror);
static int update_callback(elvin_timeout_t timeout,
void *rock,
elvin_error_t eerror);
static void parse_config_file(char *filename);
static void parse_movement_file(char *filename);
......@@ -167,7 +173,7 @@ int main(int argc, char *argv[])
char *logfile = NULL;
char *pidfile = NULL;
char *eport = NULL;
char buf[BUFSIZ];
char buf[BUFSIZ], buf2[BUFSIZ];
char *idx;
FILE *fp;
......@@ -314,6 +320,11 @@ int main(int argc, char *argv[])
(eport ? eport : ""));
server = buf;
}
if (!keyfile && pideid) {
snprintf(buf2, sizeof(buf2), "/proj/%s/exp/%s/tbdata/eventkey", pid, eid);
keyfile = buf2;
}
/*
* Register with the event system.
......@@ -356,6 +367,14 @@ int main(int argc, char *argv[])
elvin_error)) == NULL) {
fatal("could not register I/O callback");
}
if (elvin_sync_add_timeout(NULL,
EMC_UPDATE_HZ,
update_callback,
NULL,
elvin_error) == NULL) {
fatal("could not add timeout");
}
event_main(handle);
......@@ -380,24 +399,25 @@ void parse_config_file(char *config_file) {
// read line by line
while (fgets(line, sizeof(line), fp) != NULL) {
int id;
char *hostname;
char *hostname, *vname;
float init_x;
float init_y;