Commit a2a896ab authored by Mike Hibler's avatar Mike Hibler

First crack at a frisbee "master server" for handling GET (download) requests.

There are a couple of new packet types in the frisbee protocol which are
exchanged via TCP with the master server: GETREQUEST and GETREPLY.  The
client passes to the master server an opaque imageid and a couple of options
and gets back the addr/port to use to actually download the image.  The
implementation of the master server is fragile and is more of a test
framework, Grant is working on a more robust master server.  I am mostly
doing a backend that communicates with the Emulab DB to do its authentication
and making the client changes.

The client now uses the -S option to specify the IP address of the master
server and the -F option to specify an imageid.  If no error is returned,
the image is downloaded using the returned addr/port.  If -Q is used in place
of -F, then the client makes a "status only" call getting back info about
whether the named image is accessible to the client and whether a server is
currently running.

On the server side, the new master server (mserver.c) has an Emulab
configuration "backend" that supports host-based authentication.
The IP address of the caller is mapped to a node_id/pid/gid/eid combo
that is used to determine access.  On a request, the specified imageid is
treated either as a pathname (if it starts with '/') or an image identifier
of the form "<pid>/<imagename>".  If it is a pathname, we check to make
sure that pathname (after running through "realpath") is contained in one
of the directories accessible to that node in its current experiment context;
i.e., /share, /proj/<pid>, /groups/<pid>/<gid>, or /users/<swapper-uid>.
If it is an image identifier, the DB is queried to ensure that access is
allowed to that image; i.e., it must be "global" or in the appropriate
project/group.

The master server forks a frisbeed for each valid request, if one is not
already running.  The multicast address selection is still based on the
emulab_indicies.frisbee_index field, but the address/port/server info is no
longer stored in the frisbee_blobs table (frisbee_pid, load_address,
load_busy are not set).

Note that this is not yet integrated in the os_load path.  Further work is
required to replace frisbeelauncher.
parent b1e4b205
...@@ -46,6 +46,8 @@ ...@@ -46,6 +46,8 @@
#undef TPM #undef TPM
#undef NOSHAREDFS #undef NOSHAREDFS
#undef NFSRACY #undef NFSRACY
#undef FRISEBEEMCASTADDR
#undef FRISEBEEMCASTPORT
#undef HAVE_SRANDOMDEV #undef HAVE_SRANDOMDEV
......
...@@ -1784,6 +1784,14 @@ cat >> confdefs.h <<EOF ...@@ -1784,6 +1784,14 @@ cat >> confdefs.h <<EOF
#define BOSSEVENTPORT "$BOSSEVENTPORT" #define BOSSEVENTPORT "$BOSSEVENTPORT"
EOF EOF
cat >> confdefs.h <<EOF
#define FRISEBEEMCASTADDR "$FRISEBEEMCASTADDR"
EOF
cat >> confdefs.h <<EOF
#define FRISEBEEMCASTPORT "$FRISEBEEMCASTPORT"
EOF
if test $OPSDBSUPPORT -eq 1; then if test $OPSDBSUPPORT -eq 1; then
cat >> confdefs.h <<EOF cat >> confdefs.h <<EOF
...@@ -2222,17 +2230,17 @@ for ac_hdr in ulxmlrpcpp/ulxr_config.h ...@@ -2222,17 +2230,17 @@ for ac_hdr in ulxmlrpcpp/ulxr_config.h
do do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:2225: checking for $ac_hdr" >&5 echo "configure:2234: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 2230 "configure" #line 2239 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <$ac_hdr> #include <$ac_hdr>
EOF EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2235: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } { (eval echo configure:2244: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then if test -z "$ac_err"; then
rm -rf conftest* rm -rf conftest*
...@@ -2271,17 +2279,17 @@ for ac_hdr in linux/videodev.h ...@@ -2271,17 +2279,17 @@ for ac_hdr in linux/videodev.h
do do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:2274: checking for $ac_hdr" >&5 echo "configure:2283: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 2279 "configure" #line 2288 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <$ac_hdr> #include <$ac_hdr>
EOF EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2284: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } { (eval echo configure:2293: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then if test -z "$ac_err"; then
rm -rf conftest* rm -rf conftest*
...@@ -2314,7 +2322,7 @@ done ...@@ -2314,7 +2322,7 @@ done
# Extract the first word of "gtk-config", so it can be a program name with args. # Extract the first word of "gtk-config", so it can be a program name with args.
set dummy gtk-config; ac_word=$2 set dummy gtk-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:2317: checking for $ac_word" >&5 echo "configure:2326: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_GTK_CONFIG'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_prog_GTK_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
...@@ -2371,7 +2379,7 @@ ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftes ...@@ -2371,7 +2379,7 @@ ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftes
cross_compiling=$ac_cv_prog_cxx_cross cross_compiling=$ac_cv_prog_cxx_cross
echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6 echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6
echo "configure:2374: checking how to run the C++ preprocessor" >&5 echo "configure:2383: checking how to run the C++ preprocessor" >&5
if test -z "$CXXCPP"; then if test -z "$CXXCPP"; then
if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
...@@ -2384,12 +2392,12 @@ ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftes ...@@ -2384,12 +2392,12 @@ ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftes
cross_compiling=$ac_cv_prog_cxx_cross cross_compiling=$ac_cv_prog_cxx_cross
CXXCPP="${CXX-g++} -E" CXXCPP="${CXX-g++} -E"
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 2387 "configure" #line 2396 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <stdlib.h> #include <stdlib.h>
EOF EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2392: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } { (eval echo configure:2401: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then if test -z "$ac_err"; then
: :
...@@ -2415,17 +2423,17 @@ echo "$ac_t""$CXXCPP" 1>&6 ...@@ -2415,17 +2423,17 @@ echo "$ac_t""$CXXCPP" 1>&6
ac_safe=`echo "xercesc/dom/DOM.hpp" | sed 'y%./+-%__p_%'` ac_safe=`echo "xercesc/dom/DOM.hpp" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for xercesc/dom/DOM.hpp""... $ac_c" 1>&6 echo $ac_n "checking for xercesc/dom/DOM.hpp""... $ac_c" 1>&6
echo "configure:2418: checking for xercesc/dom/DOM.hpp" >&5 echo "configure:2427: checking for xercesc/dom/DOM.hpp" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 2423 "configure" #line 2432 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <xercesc/dom/DOM.hpp> #include <xercesc/dom/DOM.hpp>
EOF EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2428: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } { (eval echo configure:2437: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then if test -z "$ac_err"; then
rm -rf conftest* rm -rf conftest*
...@@ -2489,7 +2497,7 @@ fi ...@@ -2489,7 +2497,7 @@ fi
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh. # ./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 $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
echo "configure:2492: checking for a BSD compatible install" >&5 echo "configure:2501: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
...@@ -2550,7 +2558,7 @@ esac ...@@ -2550,7 +2558,7 @@ esac
# Extract the first word of "rsync", so it can be a program name with args. # Extract the first word of "rsync", so it can be a program name with args.
set dummy rsync; ac_word=$2 set dummy rsync; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:2553: checking for $ac_word" >&5 echo "configure:2562: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_RSYNC'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_path_RSYNC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
......
...@@ -406,6 +406,8 @@ if test -n "$FSDIR_SCRATCH"; then ...@@ -406,6 +406,8 @@ if test -n "$FSDIR_SCRATCH"; then
AC_DEFINE_UNQUOTED(FSDIR_SCRATCH, "$FSDIR_SCRATCH") AC_DEFINE_UNQUOTED(FSDIR_SCRATCH, "$FSDIR_SCRATCH")
fi fi
AC_DEFINE_UNQUOTED(BOSSEVENTPORT, "$BOSSEVENTPORT") AC_DEFINE_UNQUOTED(BOSSEVENTPORT, "$BOSSEVENTPORT")
AC_DEFINE_UNQUOTED(FRISEBEEMCASTADDR, "$FRISEBEEMCASTADDR")
AC_DEFINE_UNQUOTED(FRISEBEEMCASTPORT, "$FRISEBEEMCASTPORT")
if test $OPSDBSUPPORT -eq 1; then if test $OPSDBSUPPORT -eq 1; then
AC_DEFINE_UNQUOTED(OPSDBSUPPORT, 1) AC_DEFINE_UNQUOTED(OPSDBSUPPORT, 1)
......
...@@ -175,6 +175,12 @@ mydb_update(char *query, ...) ...@@ -175,6 +175,12 @@ mydb_update(char *query, ...)
return 1; return 1;
} }
int
mydb_insertid()
{
return (int)mysql_insert_id(&db);
}
/* /*
* Map IP to node ID. * Map IP to node ID.
*/ */
......
...@@ -33,6 +33,7 @@ int mydb_seteventschedulerpid(char *pid, char *eid, int processid); ...@@ -33,6 +33,7 @@ int mydb_seteventschedulerpid(char *pid, char *eid, int processid);
*/ */
MYSQL_RES *mydb_query(char *query, int ncols, ...); MYSQL_RES *mydb_query(char *query, int ncols, ...);
int mydb_update(char *query, ...); int mydb_update(char *query, ...);
int mydb_insertid(void);
unsigned long mydb_escape_string(char *to, const char *from, unsigned long mydb_escape_string(char *to, const char *from,
unsigned long length); unsigned long length);
# #
# EMULAB-COPYRIGHT # EMULAB-COPYRIGHT
# Copyright (c) 2000-2009 University of Utah and the Flux Group. # Copyright (c) 2000-2010 University of Utah and the Flux Group.
# All rights reserved. # All rights reserved.
# #
...@@ -63,7 +63,13 @@ SERVERFLAGS = $(CFLAGS) ...@@ -63,7 +63,13 @@ SERVERFLAGS = $(CFLAGS)
SERVERLIBS = $(PTHREADLIBS) SERVERLIBS = $(PTHREADLIBS)
SERVEROBJS = server.o $(SHAREDOBJS) SERVEROBJS = server.o $(SHAREDOBJS)
CFLAGS = -O2 -g -Wall -fno-builtin-log $(LDSTATIC) $(PTHREADCFLAGS) -DSTATS MYSQLCFLAGS = -I/usr/local/include
MYSQLLIBS = -L/usr/local/lib/mysql -lmysqlclient
MSERVERFLAGS = $(CFLAGS) $(MYSQLCFLAGS) -DUSE_EMULAB_CONFIG -I$(TESTBED_SRCDIR)/lib/libtb -I$(OBJDIR)
MSERVERLIBS = $(OBJDIR)/lib/libtb/libtb.a $(MYSQLLIBS) $(PTHREADLIBS)
MSERVEROBJS = mserver.o config.o config_emulab.o $(SHAREDOBJS)
CFLAGS = -O2 -g -Wall -fno-builtin-log $(LDSTATIC) $(PTHREADCFLAGS) -DSTATS -DMASTER_SERVER
LDFLAGS = $(LDSTATIC) LDFLAGS = $(LDSTATIC)
# #
...@@ -110,6 +116,15 @@ frisbeed: $(SERVEROBJS) ...@@ -110,6 +116,15 @@ frisbeed: $(SERVEROBJS)
cp frisbeed frisbeed.debug cp frisbeed frisbeed.debug
strip frisbeed strip frisbeed
mfrisbeed: $(MSERVEROBJS)
$(CC) $(LDFLAGS) $(MSERVERFLAGS) $(MSERVEROBJS) $(MSERVERLIBS) -o mfrisbeed
cp mfrisbeed mfrisbeed.debug
strip mfrisbeed
config.o: $(SRCDIR)/config.c configdefs.h log.h
$(CC) -c $(MSERVERFLAGS) $(SRCDIR)/config.c
config_emulab.o: $(SRCDIR)/config_emulab.c configdefs.h log.h
$(CC) -c $(MSERVERFLAGS) $(SRCDIR)/config_emulab.c
log.o: $(SRCDIR)/log.c decls.h log.h log.o: $(SRCDIR)/log.c decls.h log.h
$(CC) $(CFLAGS) -DLOG_TESTBED=$(LOG_TESTBED) -c $(SRCDIR)/log.c $(CC) $(CFLAGS) -DLOG_TESTBED=$(LOG_TESTBED) -c $(SRCDIR)/log.c
......
...@@ -60,6 +60,8 @@ int zero = 0; ...@@ -60,6 +60,8 @@ int zero = 0;
int portnum; int portnum;
struct in_addr mcastaddr; struct in_addr mcastaddr;
struct in_addr mcastif; struct in_addr mcastif;
char *imageid;
int askonly;
static struct timeval stamp; static struct timeval stamp;
static struct in_addr serverip; static struct in_addr serverip;
...@@ -137,18 +139,28 @@ ClientStats_t Stats; ...@@ -137,18 +139,28 @@ ClientStats_t Stats;
#endif #endif
char *usagestr = char *usagestr =
"usage: frisbee [-drzbn] [-s #] <-p #> <-m ipaddr> <output filename>\n" "usage: frisbee [-drzbnN] [-s #] <-m ipaddr> <-p #> <output filename>\n"
" or\n"
"usage: frisbee [-drzbnN] [-s #] <-S server> <-F fileid> <output filename>\n"
"\n"
" -d Turn on debugging. Multiple -d options increase output.\n" " -d Turn on debugging. Multiple -d options increase output.\n"
" -r Randomly delay first request by up to one second.\n" " -r Randomly delay first request by up to one second.\n"
" -z Zero fill unused block ranges (default is to seek past).\n" " -z Zero fill unused block ranges (default is to seek past).\n"
" -b Use broadcast instead of multicast\n" " -b Use broadcast instead of multicast\n"
" -n Do not use extra threads in diskwriter\n" " -n Do not use extra threads in diskwriter\n"
" -N Do not decompress the received data, just write to output.\n" " -N Do not decompress the received data, just write to output.\n"
" -S server-IP Specify the IP address of the server to use.\n"
" -p portnum Specify a port number.\n" " -p portnum Specify a port number.\n"
" -m mcastaddr Specify a multicast address in dotted notation.\n" " -m mcastaddr Specify a multicast address in dotted notation.\n"
" -i mcastif Specify a multicast interface in dotted notation.\n" " -i mcastif Specify a multicast interface in dotted notation.\n"
" -s slice Output to DOS slice (DOS numbering 1-4)\n" " -s slice Output to DOS slice (DOS numbering 1-4)\n"
" NOTE: Must specify a raw disk device for output filename.\n" " NOTE: Must specify a raw disk device for output filename.\n"
" -D DOS-type With -s, sets the DOS type of the slice in the MBR\n"
" -F file-ID Specify the ID of the file (image) to download.\n"
" Here -S specifies the 'master' server which will\n"
" return unicast/multicast info to use for image download.\n"
" -Q file-ID Ask the server (-S) about the indicated file (image).\n"
" Tells whether the image is accessible by this node/user.\n"
"\n" "\n"
"tuning options (if you don't know what they are, don't use em!):\n" "tuning options (if you don't know what they are, don't use em!):\n"
" -C MB Max MB of memory to use for network chunk buffering.\n" " -C MB Max MB of memory to use for network chunk buffering.\n"
...@@ -187,11 +199,11 @@ int ...@@ -187,11 +199,11 @@ int
main(int argc, char **argv) main(int argc, char **argv)
{ {
int ch, mem; int ch, mem;
char *filename; char *filename = NULL;
int dostype = -1; int dostype = -1;
int slice = 0; int slice = 0;
while ((ch = getopt(argc, argv, "dhp:m:s:i:tbznT:r:E:D:C:W:S:M:R:I:ON")) != -1) while ((ch = getopt(argc, argv, "dhp:m:s:i:tbznT:r:E:D:C:W:S:M:R:I:ONF:Q:")) != -1)
switch(ch) { switch(ch) {
case 'd': case 'd':
debug++; debug++;
...@@ -239,6 +251,15 @@ main(int argc, char **argv) ...@@ -239,6 +251,15 @@ main(int argc, char **argv)
} }
break; break;
case 'F':
imageid = optarg;
break;
case 'Q':
imageid = optarg;
askonly = 1;
break;
case 't': case 't':
tracing++; tracing++;
break; break;
...@@ -314,14 +335,26 @@ main(int argc, char **argv) ...@@ -314,14 +335,26 @@ main(int argc, char **argv)
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (argc != 1) if (!askonly) {
usage(); if (argc != 1)
filename = argv[0]; usage();
filename = argv[0];
}
if (!portnum || ! mcastaddr.s_addr) if (!((imageid != NULL && serverip.s_addr != 0) ||
(mcastaddr.s_addr != 0 && portnum != 0)))
usage(); usage();
ClientLogInit(); ClientLogInit();
#ifdef MASTER_SERVER
if (imageid && !ClientNetFindServer(&serverip, imageid, askonly, 5)) {
fprintf(stderr, "Could not get download info for '%s'\n",
imageid);
exit(1);
}
if (askonly)
exit(0);
#endif
ClientNetInit(); ClientNetInit();
#ifdef DOEVENTS #ifdef DOEVENTS
......
/*
* Configuration file functions.
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <assert.h>
#include "configdefs.h"
#include "log.h"
static struct config *myconfig;
/*
* Got a SIGHUP.
* Reread the config file.
*/
static void
config_signal(int sig)
{
void *savedconfig = NULL;
if (myconfig == NULL)
return;
savedconfig = myconfig->config_save();
if (myconfig->config_read() != 0) {
warning("WARNING: could not load new configuration, "
"restoring old config.");
if (savedconfig == NULL ||
myconfig->config_restore(savedconfig)) {
error("*** Could not restore old configuration; "
"aborting!");
abort();
}
} else
log("New configuration loaded.");
if (savedconfig)
myconfig->config_free(savedconfig);
}
int
config_init(int readit)
{
int rv;
#ifdef USE_EMULAB_CONFIG
extern struct config emulab_config;
myconfig = &emulab_config;
#else
extern struct config file_config;
myconfig = &file_config;
#endif
rv = myconfig->config_init();
if (rv)
return rv;
if (readit) {
rv = myconfig->config_read();
if (rv) {
myconfig->config_deinit();
return rv;
}
}
signal(SIGHUP, config_signal);
return 0;
}
int
config_read(void)
{
assert(myconfig != NULL);
return myconfig->config_read();
}
int
config_get_host_authinfo(struct in_addr *in, char *imageid,
struct config_host_authinfo **get,
struct config_host_authinfo **put)
{
assert(myconfig != NULL);
return myconfig->config_get_host_authinfo(in, imageid, get, put);
}
void
config_free_host_authinfo(struct config_host_authinfo *ai)
{
assert(myconfig != NULL);
return myconfig->config_free_host_authinfo(ai);
}
/*
* Authenticate access to an image based on the IP address of a host.
* Return zero and (optionally) a pointer to authentication information
* on success, an error code otherwise.
*/
int
config_auth_by_IP(struct in_addr *host, char *imageid,
struct config_host_authinfo **aip)
{
struct config_host_authinfo *ai;
if (config_get_host_authinfo(host, imageid, &ai, 0))
return CONFIG_ERR_HA_FAILED;
if (ai->hostid == NULL) {
config_free_host_authinfo(ai);
return CONFIG_ERR_HA_NOHOST;
}
if (ai->numimages == 0) {
config_free_host_authinfo(ai);
return CONFIG_ERR_HA_NOACCESS;
}
if (aip)
*aip = ai;
return 0;
}
int
config_get_server_address(struct config_host_authinfo *ai, int methods,
in_addr_t *addr, in_port_t *port, int *method)
{
assert(myconfig != NULL);
return myconfig->config_get_server_address(ai, methods,
addr, port, method);
}
char *
config_perror(int code)
{
switch (code) {
case CONFIG_ERR_HA_FAILED:
return "host authentication failed";
case CONFIG_ERR_HA_NOHOST:
return "unknown host";
case CONFIG_ERR_HA_NOIMAGE:
return "unknown image";
case CONFIG_ERR_HA_NOACCESS:
return "permission denied";
case CONFIG_ERR_HA_NOMETHOD:
return "invalid method";
default:
return "unknown error";
}
}
void
config_dump(FILE *fd)
{
signal(SIGHUP, SIG_IGN);
if (myconfig == NULL)
warning("config_dump: config file not yet read.");
else
myconfig->config_dump(fd);
signal(SIGHUP, config_signal);
}
/*
* Configuration "file" handling for Emulab.
*
* Uses info straight from the Emulab database.
*/
#ifdef USE_EMULAB_CONFIG
#include <sys/param.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <mysql/mysql.h>
#include "log.h"
#include "configdefs.h"
/* Emulab includes */
#include "tbdb.h" /* the DB library */
#include "config.h" /* the defs-* defines */
/* Extra info associated with a image information entry */
struct emulab_ii_extra_info {
int DB_imageid;
};
/* Extra info associated with a host authentication entry */
struct emulab_ha_extra_info {
char *pid; /* project */
char *gid; /* group */
char *eid; /* experiment */
char *suid; /* swapper user name */
};
static char *MC_BASEADDR = FRISEBEEMCASTADDR;
static char *MC_BASEPORT = FRISEBEEMCASTPORT;
static char *SHAREDIR = SHAREROOT_DIR;
static char *PROJDIR = PROJROOT_DIR;
static char *GROUPSDIR = GROUPSROOT_DIR;
static char *USERSDIR = USERSROOT_DIR;
static char *SCRATCHDIR = SCRATCHROOT_DIR;
/* XXX should be autoconfiged as part of Emulab build */
static char *IMAGEDIR = "/usr/testbed/images";
/* Emit aliases when dumping the config info; makes it smaller */
static int dump_doaliases = 1;
/* Multicast address/port base info */
static int mc_a, mc_b, mc_c, mc_port;
/* Memory alloc functions that abort when no memory */
static void *mymalloc(size_t size);
static void *myrealloc(void *ptr, size_t size);
static char *mystrdup(const char *str);
static int
emulab_init(void)