fixed scenario loading
This commit is contained in:
@@ -4,9 +4,9 @@ ipsec_PROGRAMS = dumm
|
|||||||
libdumm_la_SOURCES = dumm.c dumm.h guest.c guest.h iface.c iface.h bridge.c bridge.h mconsole.c mconsole.h cowfs.h cowfs.c
|
libdumm_la_SOURCES = dumm.c dumm.h guest.c guest.h iface.c iface.h bridge.c bridge.h mconsole.c mconsole.h cowfs.h cowfs.c
|
||||||
dumm_SOURCES = main.c
|
dumm_SOURCES = main.c
|
||||||
|
|
||||||
libdumm_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -lpthread -lbridge -lfuse -lutil
|
libdumm_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -lpthread -lbridge -lfuse -lutil ${xml_LIBS}
|
||||||
dumm_LDADD = -ldumm -lreadline
|
dumm_LDADD = -ldumm -lreadline
|
||||||
|
|
||||||
INCLUDES = -I$(top_srcdir)/src/libstrongswan
|
INCLUDES = -I$(top_srcdir)/src/libstrongswan ${xml_CFLAGS}
|
||||||
|
|
||||||
AM_CFLAGS = -D_FILE_OFFSET_BITS=64
|
AM_CFLAGS = -D_FILE_OFFSET_BITS=64
|
||||||
|
|||||||
+29
-29
@@ -55,14 +55,14 @@ struct private_cowfs_t {
|
|||||||
char *master;
|
char *master;
|
||||||
/** host filesystem path */
|
/** host filesystem path */
|
||||||
char *host;
|
char *host;
|
||||||
/** scenario filesystem path */
|
/** overlay filesystem path */
|
||||||
char *scen;
|
char *over;
|
||||||
/** fd of read only master filesystem */
|
/** fd of read only master filesystem */
|
||||||
int master_fd;
|
int master_fd;
|
||||||
/** copy on write overlay to master */
|
/** copy on write overlay to master */
|
||||||
int host_fd;
|
int host_fd;
|
||||||
/** optional scenario COW overlay */
|
/** optional COW overlay */
|
||||||
int scen_fd;
|
int over_fd;
|
||||||
/** thread processing FUSE */
|
/** thread processing FUSE */
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
};
|
};
|
||||||
@@ -97,9 +97,9 @@ static int get_rd(const char *path)
|
|||||||
{
|
{
|
||||||
private_cowfs_t *this = get_this();
|
private_cowfs_t *this = get_this();
|
||||||
|
|
||||||
if (this->scen_fd > 0 && faccessat(this->scen_fd, path, F_OK, 0) == 0)
|
if (this->over_fd > 0 && faccessat(this->over_fd, path, F_OK, 0) == 0)
|
||||||
{
|
{
|
||||||
return this->scen_fd;
|
return this->over_fd;
|
||||||
}
|
}
|
||||||
if (faccessat(this->host_fd, path, F_OK, 0) == 0)
|
if (faccessat(this->host_fd, path, F_OK, 0) == 0)
|
||||||
{
|
{
|
||||||
@@ -114,9 +114,9 @@ static int get_rd(const char *path)
|
|||||||
static int get_wr(const char *path)
|
static int get_wr(const char *path)
|
||||||
{
|
{
|
||||||
private_cowfs_t *this = get_this();
|
private_cowfs_t *this = get_this();
|
||||||
if (this->scen_fd > 0)
|
if (this->over_fd > 0)
|
||||||
{
|
{
|
||||||
return this->scen_fd;
|
return this->over_fd;
|
||||||
}
|
}
|
||||||
return this->host_fd;
|
return this->host_fd;
|
||||||
}
|
}
|
||||||
@@ -318,7 +318,7 @@ static int cowfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
|||||||
|
|
||||||
d1 = get_dir(this->master, path);
|
d1 = get_dir(this->master, path);
|
||||||
d2 = get_dir(this->host, path);
|
d2 = get_dir(this->host, path);
|
||||||
d3 = get_dir(this->scen, path);
|
d3 = get_dir(this->over, path);
|
||||||
|
|
||||||
if (d1)
|
if (d1)
|
||||||
{
|
{
|
||||||
@@ -741,9 +741,9 @@ static int cowfs_statfs(const char *path, struct statvfs *stbuf)
|
|||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
fd = this->host_fd;
|
fd = this->host_fd;
|
||||||
if (this->scen_fd > 0)
|
if (this->over_fd > 0)
|
||||||
{
|
{
|
||||||
fd = this->scen_fd;
|
fd = this->over_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fstatvfs(fd, stbuf) < 0)
|
if (fstatvfs(fd, stbuf) < 0)
|
||||||
@@ -793,29 +793,29 @@ static struct fuse_operations cowfs_operations = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of cowfs_t.set_scenario.
|
* Implementation of cowfs_t.set_overlay.
|
||||||
*/
|
*/
|
||||||
static bool set_scenario(private_cowfs_t *this, char *path)
|
static bool set_overlay(private_cowfs_t *this, char *path)
|
||||||
{
|
{
|
||||||
if (this->scen)
|
if (this->over)
|
||||||
{
|
{
|
||||||
free(this->scen);
|
free(this->over);
|
||||||
this->scen = NULL;
|
this->over = NULL;
|
||||||
}
|
}
|
||||||
if (this->scen_fd > 0)
|
if (this->over_fd > 0)
|
||||||
{
|
{
|
||||||
close(this->scen_fd);
|
close(this->over_fd);
|
||||||
this->scen_fd = -1;
|
this->over_fd = -1;
|
||||||
}
|
}
|
||||||
if (path)
|
if (path)
|
||||||
{
|
{
|
||||||
this->scen_fd = open(path, O_RDONLY | O_DIRECTORY);
|
this->over_fd = open(path, O_RDONLY | O_DIRECTORY);
|
||||||
if (this->scen_fd < 0)
|
if (this->over_fd < 0)
|
||||||
{
|
{
|
||||||
DBG1("failed to open scenario overlay directory '%s': %m", path);
|
DBG1("failed to open overlay directory '%s': %m", path);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
this->scen = strdup(path);
|
this->over = strdup(path);
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -832,12 +832,12 @@ static void destroy(private_cowfs_t *this)
|
|||||||
free(this->mount);
|
free(this->mount);
|
||||||
free(this->master);
|
free(this->master);
|
||||||
free(this->host);
|
free(this->host);
|
||||||
free(this->scen);
|
free(this->over);
|
||||||
close(this->master_fd);
|
close(this->master_fd);
|
||||||
close(this->host_fd);
|
close(this->host_fd);
|
||||||
if (this->scen_fd > 0)
|
if (this->over_fd > 0)
|
||||||
{
|
{
|
||||||
close(this->scen_fd);
|
close(this->over_fd);
|
||||||
}
|
}
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
@@ -850,7 +850,7 @@ cowfs_t *cowfs_create(char *master, char *host, char *mount)
|
|||||||
struct fuse_args args = {0, NULL, 0};
|
struct fuse_args args = {0, NULL, 0};
|
||||||
private_cowfs_t *this = malloc_thing(private_cowfs_t);
|
private_cowfs_t *this = malloc_thing(private_cowfs_t);
|
||||||
|
|
||||||
this->public.set_scenario = (bool(*)(cowfs_t*, char *path))set_scenario;
|
this->public.set_overlay = (bool(*)(cowfs_t*, char *path))set_overlay;
|
||||||
this->public.destroy = (void(*)(cowfs_t*))destroy;
|
this->public.destroy = (void(*)(cowfs_t*))destroy;
|
||||||
|
|
||||||
this->master_fd = open(master, O_RDONLY | O_DIRECTORY);
|
this->master_fd = open(master, O_RDONLY | O_DIRECTORY);
|
||||||
@@ -866,7 +866,7 @@ cowfs_t *cowfs_create(char *master, char *host, char *mount)
|
|||||||
close(this->master_fd);
|
close(this->master_fd);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
this->scen_fd = -1;
|
this->over_fd = -1;
|
||||||
|
|
||||||
this->chan = fuse_mount(mount, &args);
|
this->chan = fuse_mount(mount, &args);
|
||||||
if (this->chan == NULL)
|
if (this->chan == NULL)
|
||||||
@@ -893,7 +893,7 @@ cowfs_t *cowfs_create(char *master, char *host, char *mount)
|
|||||||
this->mount = strdup(mount);
|
this->mount = strdup(mount);
|
||||||
this->master = strdup(master);
|
this->master = strdup(master);
|
||||||
this->host = strdup(host);
|
this->host = strdup(host);
|
||||||
this->scen = NULL;
|
this->over = NULL;
|
||||||
|
|
||||||
if (pthread_create(&this->thread, NULL, (void*)fuse_loop, this->fuse) != 0)
|
if (pthread_create(&this->thread, NULL, (void*)fuse_loop, this->fuse) != 0)
|
||||||
{
|
{
|
||||||
|
|||||||
+2
-2
@@ -27,12 +27,12 @@ typedef struct cowfs_t cowfs_t;
|
|||||||
struct cowfs_t {
|
struct cowfs_t {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the scenario copy on write overlay.
|
* @brief Set an additional copy on write overlay.
|
||||||
*
|
*
|
||||||
* @param path path of the overlay
|
* @param path path of the overlay
|
||||||
* @return FALSE if failed
|
* @return FALSE if failed
|
||||||
*/
|
*/
|
||||||
bool (*set_scenario)(cowfs_t *this, char *path);
|
bool (*set_overlay)(cowfs_t *this, char *path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stop, umount and destroy a cowfs FUSE filesystem.
|
* @brief Stop, umount and destroy a cowfs FUSE filesystem.
|
||||||
|
|||||||
+47
-45
@@ -21,6 +21,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <libxml/xmlreader.h>
|
||||||
|
#include <libxml/xmlwriter.h>
|
||||||
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
@@ -28,8 +30,8 @@
|
|||||||
|
|
||||||
#define PERME (S_IRWXU | S_IRWXG)
|
#define PERME (S_IRWXU | S_IRWXG)
|
||||||
#define GUEST_DIR "guests"
|
#define GUEST_DIR "guests"
|
||||||
#define SCENARIO_DIR "scenarios"
|
#define TEMPLATE_DIR "templates"
|
||||||
#define SCENARIO_DIFF_DIR "diff"
|
#define TEMPLATE_DIR_DIR "diff"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* instances of dumm, used to deliver signals
|
* instances of dumm, used to deliver signals
|
||||||
@@ -45,10 +47,10 @@ struct private_dumm_t {
|
|||||||
char *dir;
|
char *dir;
|
||||||
/** directory of guests */
|
/** directory of guests */
|
||||||
char *guest_dir;
|
char *guest_dir;
|
||||||
/** directory of scenarios */
|
/** directory of templates */
|
||||||
char *scenario_dir;
|
char *template_dir;
|
||||||
/** directory of loaded scenario */
|
/** directory of loaded template */
|
||||||
char *scenario;
|
char *template;
|
||||||
/** list of managed guests */
|
/** list of managed guests */
|
||||||
linked_list_t *guests;
|
linked_list_t *guests;
|
||||||
/** list of managed bridges */
|
/** list of managed bridges */
|
||||||
@@ -105,73 +107,77 @@ static iterator_t* create_bridge_iterator(private_dumm_t *this)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* disable the currently enabled scenario
|
* disable the currently enabled template
|
||||||
*/
|
*/
|
||||||
static void clear_scenario(private_dumm_t *this)
|
static void clear_template(private_dumm_t *this)
|
||||||
{
|
{
|
||||||
iterator_t *iterator;
|
iterator_t *iterator, *ifaces;
|
||||||
guest_t *guest;
|
guest_t *guest;
|
||||||
|
iface_t *iface;
|
||||||
|
|
||||||
free(this->scenario);
|
free(this->template);
|
||||||
this->scenario = NULL;
|
this->template = NULL;
|
||||||
|
|
||||||
iterator = this->guests->create_iterator(this->guests, TRUE);
|
iterator = this->guests->create_iterator(this->guests, TRUE);
|
||||||
while (iterator->iterate(iterator, (void**)&guest))
|
while (iterator->iterate(iterator, (void**)&guest))
|
||||||
{
|
{
|
||||||
guest->set_scenario(guest, NULL);
|
guest->load_template(guest, NULL);
|
||||||
|
ifaces = guest->create_iface_iterator(guest);
|
||||||
|
while (ifaces->iterate(ifaces, (void**)&iface))
|
||||||
|
{
|
||||||
|
ifaces->remove(ifaces);
|
||||||
|
iface->destroy(iface);
|
||||||
|
}
|
||||||
|
ifaces->destroy(ifaces);
|
||||||
}
|
}
|
||||||
iterator->destroy(iterator);
|
iterator->destroy(iterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of dumm_t.load_scenario.
|
* Implementation of dumm_t.load_template.
|
||||||
*/
|
*/
|
||||||
static bool load_scenario(private_dumm_t *this, char *name)
|
static bool load_template(private_dumm_t *this, char *name)
|
||||||
{
|
{
|
||||||
iterator_t *iterator;
|
iterator_t *iterator;
|
||||||
guest_t *guest;
|
guest_t *guest;
|
||||||
char dir[PATH_MAX];
|
char dir[PATH_MAX];
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
|
clear_template(this);
|
||||||
|
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
{
|
{
|
||||||
clear_scenario(this);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(this->scenario);
|
free(this->template);
|
||||||
asprintf(&this->scenario, "%s/%s", this->scenario_dir, name);
|
asprintf(&this->template, "%s/%s", this->template_dir, name);
|
||||||
mkdir(this->scenario_dir, PERME);
|
len = snprintf(dir, sizeof(dir), "%s/%s", this->template, TEMPLATE_DIR_DIR);
|
||||||
|
|
||||||
len = snprintf(dir, sizeof(dir), "%s/%s", this->scenario, SCENARIO_DIFF_DIR);
|
|
||||||
if (len < 0 || len >= sizeof(dir))
|
if (len < 0 || len >= sizeof(dir))
|
||||||
{
|
{
|
||||||
clear_scenario(this);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (access(this->scenario, F_OK) != 0)
|
if (access(this->template, F_OK) != 0)
|
||||||
{ /* does not exist, create scenario */
|
{ /* does not exist, create template */
|
||||||
if (mkdir(this->scenario, PERME) != 0)
|
if (mkdir(this->template, PERME) != 0)
|
||||||
{
|
{
|
||||||
DBG1("creating scenario directory '%s' failed: %m", this->scenario);
|
DBG1("creating template directory '%s' failed: %m", this->template);
|
||||||
clear_scenario(this);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (mkdir(dir, PERME) != 0)
|
if (mkdir(dir, PERME) != 0)
|
||||||
{
|
{
|
||||||
DBG1("creating scenario overlay directory '%s' failed: %m", dir);
|
DBG1("creating template overlay directory '%s' failed: %m", dir);
|
||||||
clear_scenario(this);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iterator = this->guests->create_iterator(this->guests, TRUE);
|
iterator = this->guests->create_iterator(this->guests, TRUE);
|
||||||
while (iterator->iterate(iterator, (void**)&guest))
|
while (iterator->iterate(iterator, (void**)&guest))
|
||||||
{
|
{
|
||||||
if (!guest->set_scenario(guest, dir))
|
if (!guest->load_template(guest, dir))
|
||||||
{
|
{
|
||||||
iterator->destroy(iterator);
|
iterator->destroy(iterator);
|
||||||
clear_scenario(this);
|
clear_template(this);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,15 +185,6 @@ static bool load_scenario(private_dumm_t *this, char *name)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of dumm_t.save_scenario.
|
|
||||||
*/
|
|
||||||
static bool save_scenario(private_dumm_t *this)
|
|
||||||
{
|
|
||||||
DBG1("scenario loading unimplemented.");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* signal handler
|
* signal handler
|
||||||
*/
|
*/
|
||||||
@@ -303,8 +300,8 @@ static void destroy(private_dumm_t *this)
|
|||||||
this->destroying = TRUE;
|
this->destroying = TRUE;
|
||||||
this->guests->destroy_offset(this->guests, offsetof(guest_t, destroy));
|
this->guests->destroy_offset(this->guests, offsetof(guest_t, destroy));
|
||||||
free(this->guest_dir);
|
free(this->guest_dir);
|
||||||
free(this->scenario_dir);
|
free(this->template_dir);
|
||||||
free(this->scenario);
|
free(this->template);
|
||||||
free(this->dir);
|
free(this->dir);
|
||||||
remove_instance(this);
|
remove_instance(this);
|
||||||
free(this);
|
free(this);
|
||||||
@@ -357,8 +354,7 @@ dumm_t *dumm_create(char *dir)
|
|||||||
this->public.create_guest_iterator = (iterator_t*(*)(dumm_t*))create_guest_iterator;
|
this->public.create_guest_iterator = (iterator_t*(*)(dumm_t*))create_guest_iterator;
|
||||||
this->public.create_bridge = (bridge_t*(*)(dumm_t*, char *name))create_bridge;
|
this->public.create_bridge = (bridge_t*(*)(dumm_t*, char *name))create_bridge;
|
||||||
this->public.create_bridge_iterator = (iterator_t*(*)(dumm_t*))create_bridge_iterator;
|
this->public.create_bridge_iterator = (iterator_t*(*)(dumm_t*))create_bridge_iterator;
|
||||||
this->public.load_scenario = (bool(*)(dumm_t*, char *name))load_scenario;
|
this->public.load_template = (bool(*)(dumm_t*, char *name))load_template;
|
||||||
this->public.save_scenario = (bool(*)(dumm_t*))save_scenario;
|
|
||||||
this->public.destroy = (void(*)(dumm_t*))destroy;
|
this->public.destroy = (void(*)(dumm_t*))destroy;
|
||||||
|
|
||||||
this->destroying = FALSE;
|
this->destroying = FALSE;
|
||||||
@@ -370,9 +366,9 @@ dumm_t *dumm_create(char *dir)
|
|||||||
{
|
{
|
||||||
asprintf(&this->dir, "%s/%s", cwd, dir);
|
asprintf(&this->dir, "%s/%s", cwd, dir);
|
||||||
}
|
}
|
||||||
this->scenario = NULL;
|
this->template = NULL;
|
||||||
asprintf(&this->guest_dir, "%s/%s", this->dir, GUEST_DIR);
|
asprintf(&this->guest_dir, "%s/%s", this->dir, GUEST_DIR);
|
||||||
asprintf(&this->scenario_dir, "%s/%s", this->dir, SCENARIO_DIR);
|
asprintf(&this->template_dir, "%s/%s", this->dir, TEMPLATE_DIR);
|
||||||
this->guests = linked_list_create();
|
this->guests = linked_list_create();
|
||||||
this->bridges = linked_list_create();
|
this->bridges = linked_list_create();
|
||||||
|
|
||||||
@@ -384,6 +380,12 @@ dumm_t *dumm_create(char *dir)
|
|||||||
destroy(this);
|
destroy(this);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (mkdir(this->template_dir, PERME) < 0 && errno != EEXIST)
|
||||||
|
{
|
||||||
|
DBG1("creating template directory '%s' failed: %m", this->template_dir);
|
||||||
|
destroy(this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
load_guests(this);
|
load_guests(this);
|
||||||
return &this->public;
|
return &this->public;
|
||||||
|
|||||||
+4
-11
@@ -70,19 +70,12 @@ struct dumm_t {
|
|||||||
iterator_t* (*create_bridge_iterator)(dumm_t *this);
|
iterator_t* (*create_bridge_iterator)(dumm_t *this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Loads a scenario, create a new one if it does not exist.
|
* @brief Loads a template, create a new one if it does not exist.
|
||||||
*
|
*
|
||||||
* @param name name of the scenario to load/create
|
* @param name name of the template, NULL to clonse
|
||||||
* @return FALSE if load/crate failed
|
* @return FALSE if load/create failed
|
||||||
*/
|
*/
|
||||||
bool (*load_scenario)(dumm_t *this, char *name);
|
bool (*load_template)(dumm_t *this, char *name);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Saves the current loaded scenario.
|
|
||||||
*
|
|
||||||
* @return FALSE if saving scenario failed
|
|
||||||
*/
|
|
||||||
bool (*save_scenario)(dumm_t *this);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief stop all guests and destroy the modeler
|
* @brief stop all guests and destroy the modeler
|
||||||
|
|||||||
+6
-29
@@ -69,19 +69,6 @@ struct private_guest_t {
|
|||||||
cowfs_t *cowfs;
|
cowfs_t *cowfs;
|
||||||
/** mconsole to control running UML */
|
/** mconsole to control running UML */
|
||||||
mconsole_t *mconsole;
|
mconsole_t *mconsole;
|
||||||
/** pty consoles */
|
|
||||||
struct {
|
|
||||||
/** pty master fd */
|
|
||||||
int master;
|
|
||||||
/** pty slave fd */
|
|
||||||
int slave;
|
|
||||||
/** name of the pty */
|
|
||||||
char name[16];
|
|
||||||
/** currently in use */
|
|
||||||
bool occupied;
|
|
||||||
/** is valid */
|
|
||||||
bool valid;
|
|
||||||
} pty[PTYS];
|
|
||||||
/** list of interfaces attached to the guest */
|
/** list of interfaces attached to the guest */
|
||||||
linked_list_t *ifaces;
|
linked_list_t *ifaces;
|
||||||
};
|
};
|
||||||
@@ -273,16 +260,16 @@ static bool start(private_guest_t *this)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of guest_t.set_scenario.
|
* Implementation of guest_t.load_template.
|
||||||
*/
|
*/
|
||||||
static bool set_scenario(private_guest_t *this, char *path)
|
static bool load_template(private_guest_t *this, char *path)
|
||||||
{
|
{
|
||||||
char dir[PATH_MAX];
|
char dir[PATH_MAX];
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
if (path == NULL)
|
if (path == NULL)
|
||||||
{
|
{
|
||||||
return this->cowfs->set_scenario(this->cowfs, NULL);
|
return this->cowfs->set_overlay(this->cowfs, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
len = snprintf(dir, sizeof(dir), "%s/%s", path, this->name);
|
len = snprintf(dir, sizeof(dir), "%s/%s", path, this->name);
|
||||||
@@ -294,11 +281,11 @@ static bool set_scenario(private_guest_t *this, char *path)
|
|||||||
{
|
{
|
||||||
if (mkdir(dir, PERME) != 0)
|
if (mkdir(dir, PERME) != 0)
|
||||||
{
|
{
|
||||||
DBG1("creating scenario overlay for guest '%s' failed: %m", this->name);
|
DBG1("creating overlay for guest '%s' failed: %m", this->name);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this->cowfs->set_scenario(this->cowfs, dir);
|
return this->cowfs->set_overlay(this->cowfs, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -306,22 +293,12 @@ static bool set_scenario(private_guest_t *this, char *path)
|
|||||||
*/
|
*/
|
||||||
static void sigchild(private_guest_t *this)
|
static void sigchild(private_guest_t *this)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
if (this->state != GUEST_STOPPING)
|
if (this->state != GUEST_STOPPING)
|
||||||
{ /* collect zombie if uml crashed */
|
{ /* collect zombie if uml crashed */
|
||||||
waitpid(this->pid, NULL, WNOHANG);
|
waitpid(this->pid, NULL, WNOHANG);
|
||||||
}
|
}
|
||||||
DESTROY_IF(this->mconsole);
|
DESTROY_IF(this->mconsole);
|
||||||
this->mconsole = NULL;
|
this->mconsole = NULL;
|
||||||
for (i = 0; i < PTYS; i++)
|
|
||||||
{
|
|
||||||
if (this->pty[i].valid)
|
|
||||||
{
|
|
||||||
close(this->pty[i].master);
|
|
||||||
close(this->pty[i].slave);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this->state = GUEST_STOPPED;
|
this->state = GUEST_STOPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,7 +434,7 @@ static private_guest_t *guest_create_generic(char *parent, char *name,
|
|||||||
this->public.start = (void*)start;
|
this->public.start = (void*)start;
|
||||||
this->public.stop = (void*)stop;
|
this->public.stop = (void*)stop;
|
||||||
this->public.get_console = (char*(*)(guest_t*,int))get_console;
|
this->public.get_console = (char*(*)(guest_t*,int))get_console;
|
||||||
this->public.set_scenario = (bool(*)(guest_t*, char *path))set_scenario;
|
this->public.load_template = (bool(*)(guest_t*, char *path))load_template;
|
||||||
this->public.sigchild = (void(*)(guest_t*))sigchild;
|
this->public.sigchild = (void(*)(guest_t*))sigchild;
|
||||||
this->public.destroy = (void*)destroy;
|
this->public.destroy = (void*)destroy;
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -89,10 +89,10 @@ struct guest_t {
|
|||||||
/**
|
/**
|
||||||
* @brief Get a console pts device.
|
* @brief Get a console pts device.
|
||||||
*
|
*
|
||||||
* Every guest has 6 consoles, numbered from 1 to 6. These are associated
|
* Every guest has 5 consoles, numbered from 1 to 5. These are associated
|
||||||
* to a unique pts device on the host.
|
* to a unique pts device on the host.
|
||||||
*
|
*
|
||||||
* @param console console number to get (1-6)
|
* @param console console number to get (1-5)
|
||||||
* @return pts device file name, NULL if failed
|
* @return pts device file name, NULL if failed
|
||||||
*/
|
*/
|
||||||
char* (*get_console) (guest_t *this, int console);
|
char* (*get_console) (guest_t *this, int console);
|
||||||
@@ -113,12 +113,12 @@ struct guest_t {
|
|||||||
iterator_t* (*create_iface_iterator)(guest_t *this);
|
iterator_t* (*create_iface_iterator)(guest_t *this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the scenario COWFS overlay to use.
|
* @brief Set the template COWFS overlay to use.
|
||||||
*
|
*
|
||||||
* @param parent parent directory where scenario diff should point to
|
* @param parent parent directory where template diff should point to
|
||||||
* @return FALSE if failed
|
* @return FALSE if failed
|
||||||
*/
|
*/
|
||||||
bool (*set_scenario)(guest_t *this, char *parent);
|
bool (*load_template)(guest_t *this, char *parent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Called whenever a SIGCHILD for the guests PID is received.
|
* @brief Called whenever a SIGCHILD for the guests PID is received.
|
||||||
|
|||||||
+69
-6
@@ -21,6 +21,8 @@
|
|||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
#include <readline/history.h>
|
#include <readline/history.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
#include "dumm.h"
|
#include "dumm.h"
|
||||||
|
|
||||||
@@ -469,17 +471,73 @@ static void bridge_list_menu()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scenario_menu()
|
static void template_menu()
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
name = get_line("scenario name (or 'none'): ");
|
name = get_line("template name (or 'none'): ");
|
||||||
|
|
||||||
dumm->load_scenario(dumm, streq(name, "none") ? NULL : name);
|
dumm->load_template(dumm, streq(name, "none") ? NULL : name);
|
||||||
|
|
||||||
free(name);
|
free(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef bool (*uml_test_t)(dumm_t *dumm);
|
||||||
|
|
||||||
|
static void test_menu()
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
void *handle;
|
||||||
|
struct dirent *ent;
|
||||||
|
DIR *dir;
|
||||||
|
uml_test_t test;
|
||||||
|
|
||||||
|
name = get_line("test name: ");
|
||||||
|
|
||||||
|
dir = opendir("tests");
|
||||||
|
if (dir)
|
||||||
|
{
|
||||||
|
while ((ent = readdir(dir)))
|
||||||
|
{
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
len = strlen(ent->d_name);
|
||||||
|
if (strlen(ent->d_name) < 4 || !streq(ent->d_name + len - 3, ".so"))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "%s/%s", "tests", ent->d_name);
|
||||||
|
handle = dlopen(buf, RTLD_LAZY);
|
||||||
|
if (!handle)
|
||||||
|
{
|
||||||
|
printf("failed to open test %s\n", ent->d_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
test = dlsym(handle, "test");
|
||||||
|
if (test && dumm->load_template(dumm, ent->d_name))
|
||||||
|
{
|
||||||
|
printf("running test %s: ", ent->d_name);
|
||||||
|
if (test(dumm))
|
||||||
|
{
|
||||||
|
printf("success\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("failed\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("failed to open test %s\n", ent->d_name);
|
||||||
|
}
|
||||||
|
dlclose(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(name);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signal handler
|
* Signal handler
|
||||||
*/
|
*/
|
||||||
@@ -552,16 +610,21 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
bridge_list_menu();
|
bridge_list_menu();
|
||||||
}
|
}
|
||||||
else if (streq(line, "scenario"))
|
else if (streq(line, "template"))
|
||||||
{
|
{
|
||||||
scenario_menu();
|
template_menu();
|
||||||
|
}
|
||||||
|
else if (streq(line, "test"))
|
||||||
|
{
|
||||||
|
test_menu();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("quit|guest|bridge|scenario\n");
|
printf("quit|guest|bridge|template|test\n");
|
||||||
}
|
}
|
||||||
free(line);
|
free(line);
|
||||||
}
|
}
|
||||||
|
dumm->load_template(dumm, NULL);
|
||||||
dumm->destroy(dumm);
|
dumm->destroy(dumm);
|
||||||
clear_history();
|
clear_history();
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -199,6 +199,31 @@ static char* get_console_pts(private_mconsole_t *this, int con)
|
|||||||
return strndup(pos, len - (pos - buf));
|
return strndup(pos, len - (pos - buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Poll until guest is ready
|
||||||
|
*/
|
||||||
|
static bool wait_bootup(private_mconsole_t *this)
|
||||||
|
{
|
||||||
|
char *cmd, buf[128];
|
||||||
|
int len, res;
|
||||||
|
|
||||||
|
cmd = "config con0";
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
len = sizeof(buf);
|
||||||
|
res = request(this, cmd, buf, &len);
|
||||||
|
if (res < 0)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (res == 0)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
usleep(50000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of mconsole_t.destroy.
|
* Implementation of mconsole_t.destroy.
|
||||||
*/
|
*/
|
||||||
@@ -313,6 +338,12 @@ mconsole_t *mconsole_create(char *notify)
|
|||||||
}
|
}
|
||||||
unlink(notify);
|
unlink(notify);
|
||||||
|
|
||||||
|
if (!wait_bootup(this))
|
||||||
|
{
|
||||||
|
destroy(this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user