All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

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);
}
This diff is collapsed.
#include <netinet/in.h>
#include <arpa/inet.h>
/*
* Config info for a single image
* XXX needs to be extended for REs.
*/
struct config_imageinfo {
char *imageid; /* unique name of image */
char *path; /* path where image is stored */
int flags; /* */
char *get_options; /* options for GET operation */
int get_methods; /* allowed GET transfer mechanisms */
char *put_options; /* options for PUT operation */
void *extra; /* config-type specific info */
};
/* flags */
#define CONFIG_IMAGE_ISFILE 0x1 /* path is an image file */
#define CONFIG_IMAGE_ISDIR 0x2 /* path is a directory */
#define CONFIG_IMAGE_ISGLOB 0x4 /* path is a file glob */
#define CONFIG_IMAGE_ISRE 0x8 /* path is a perl RE */
/* methods */
#define CONFIG_IMAGE_UNKNOWN 0x0
#define CONFIG_IMAGE_UCAST 0x1
#define CONFIG_IMAGE_MCAST 0x2
#define CONFIG_IMAGE_BCAST 0x4
struct config_host_authinfo {
char *hostid; /* unique name of host */
int numimages; /* number of images in info array */
struct config_imageinfo *imageinfo; /* info array */
void *extra; /* config-type specific info */
};
/*
* Config file functions
*/
struct config {
int (*config_init)(void);
void (*config_deinit)(void);
int (*config_read)(void);
int (*config_get_host_authinfo)(struct in_addr *, char *,
struct config_host_authinfo **,
struct config_host_authinfo **);
void (*config_free_host_authinfo)(struct config_host_authinfo *);
int (*config_get_server_address)(struct config_host_authinfo *, int,
in_addr_t *, in_port_t *, int *);
void *(*config_save)(void);
int (*config_restore)(void *);
void (*config_free)(void *);
void (*config_dump)(FILE *);
};