Commit 3112df80 authored by Daniel P. Berrange's avatar Daniel P. Berrange

Switch service sandboxes to use persistent libvirt configs

Move all the start/stop code out of the base sandbox context,
into the sub-classes. The current code using transient guests
is used for the interactive context, while the service context
is changed to use persistent guests.
Signed-off-by: 's avatarDaniel P. Berrange <berrange@redhat.com>
parent 2ea23705
......@@ -22,6 +22,7 @@
#include <config.h>
#include <string.h>
#include <errno.h>
#include "libvirt-sandbox/libvirt-sandbox.h"
......@@ -107,14 +108,212 @@ static void gvir_sandbox_context_interactive_finalize(GObject *object)
}
static gboolean gvir_sandbox_context_clean_post_start(GVirSandboxContext *ctxt,
GVirSandboxBuilder *builder,
GError **error)
{
const gchar *cachedir;
gchar *tmpdir;
gboolean ret = TRUE;
GVirSandboxConfig *config = gvir_sandbox_context_get_config(ctxt);
cachedir = (getuid() ? g_get_user_cache_dir() : RUNDIR);
tmpdir = g_build_filename(cachedir, "libvirt-sandbox",
gvir_sandbox_config_get_name(config),
NULL);
if (!gvir_sandbox_builder_clean_post_start(builder,
config,
tmpdir,
error))
ret = FALSE;
g_free(tmpdir);
g_object_unref(config);
return ret;
}
static gboolean gvir_sandbox_context_clean_post_stop(GVirSandboxContext *ctxt,
GVirSandboxBuilder *builder,
GError **error)
{
const gchar *cachedir;
gchar *statedir;
gchar *configdir;
gchar *configfile;
gchar *emptydir;
gboolean ret = TRUE;
GVirSandboxConfig *config = gvir_sandbox_context_get_config(ctxt);
cachedir = (getuid() ? g_get_user_cache_dir() : RUNDIR);
statedir = g_build_filename(cachedir, "libvirt-sandbox",
gvir_sandbox_config_get_name(config),
NULL);
configdir = g_build_filename(statedir, "config", NULL);
configfile = g_build_filename(configdir, "sandbox.cfg", NULL);
emptydir = g_build_filename(configdir, "empty", NULL);
if (unlink(configfile) < 0 &&
errno != ENOENT)
ret = FALSE;
if (rmdir(emptydir) < 0 &&
errno != ENOENT)
ret = FALSE;
if (rmdir(configdir) < 0 &&
errno != ENOENT)
ret = FALSE;
if (rmdir(statedir) < 0 &&
errno != ENOENT)
ret = FALSE;
if (!gvir_sandbox_builder_clean_post_stop(builder,
config,
statedir,
error))
ret = FALSE;
g_object_unref(config);
g_free(configfile);
g_free(emptydir);
g_free(statedir);
g_free(configdir);
return ret;
}
static gboolean gvir_sandbox_context_interactive_start(GVirSandboxContext *ctxt, GError **error)
{
GVirConfigDomain *configdom = NULL;
GVirSandboxBuilder *builder = NULL;
GVirConnection *connection = NULL;
GVirDomain *domain = NULL;
GVirSandboxConfig *config = NULL;
const gchar *cachedir;
gchar *statedir;
gchar *configdir;
gchar *emptydir;
gchar *configfile;
gboolean ret = FALSE;
if (!GVIR_SANDBOX_CONTEXT_CLASS(gvir_sandbox_context_interactive_parent_class)->start(ctxt, error))
return FALSE;
connection = gvir_sandbox_context_get_connection(ctxt);
config = gvir_sandbox_context_get_config(ctxt);
cachedir = (getuid() ? g_get_user_cache_dir() : RUNDIR);
statedir = g_build_filename(cachedir, "libvirt-sandbox",
gvir_sandbox_config_get_name(config),
NULL);
configdir = g_build_filename(statedir, "config", NULL);
configfile = g_build_filename(configdir, "sandbox.cfg", NULL);
emptydir = g_build_filename(configdir, "empty", NULL);
if (!(builder = gvir_sandbox_builder_for_connection(connection,
error)))
goto cleanup;
g_mkdir_with_parents(statedir, 0700);
g_mkdir_with_parents(configdir, 0700);
unlink(configfile);
if (!gvir_sandbox_config_save_to_path(config, configfile, error))
goto cleanup;
g_mkdir_with_parents(emptydir, 0755);
if (!(configdom = gvir_sandbox_builder_construct(builder,
config,
statedir,
error))) {
goto cleanup;
}
if (!(domain = gvir_connection_start_domain(connection,
configdom,
GVIR_DOMAIN_START_AUTODESTROY,
error)))
goto cleanup;
if (!gvir_sandbox_context_clean_post_start(ctxt, builder, error))
goto cleanup;
g_object_set(ctxt, "domain", domain, NULL);
ret = TRUE;
cleanup:
if (!ret && domain)
gvir_domain_stop(domain, 0, NULL);
g_free(statedir);
g_free(configdir);
g_free(configfile);
g_free(emptydir);
if (configdom)
g_object_unref(configdom);
if (builder)
g_object_unref(builder);
g_object_unref(config);
g_object_unref(connection);
if (domain)
g_object_unref(domain);
return ret;
}
static gboolean gvir_sandbox_context_interactive_stop(GVirSandboxContext *ctxt, GError **error)
{
GVirDomain *domain;
GVirConnection *connection;
GVirSandboxBuilder *builder;
gboolean ret = TRUE;
if (!GVIR_SANDBOX_CONTEXT_CLASS(gvir_sandbox_context_interactive_parent_class)->stop(ctxt, error))
return FALSE;
if (!(domain = gvir_sandbox_context_get_domain(ctxt, error)))
return FALSE;
if (!gvir_domain_stop(domain, 0, error))
ret = FALSE;
g_object_set(ctxt, "domain", NULL, NULL);
g_object_unref(domain);
connection = gvir_sandbox_context_get_connection(ctxt);
if (!(builder = gvir_sandbox_builder_for_connection(connection,
error)))
ret = FALSE;
if (builder &&
!gvir_sandbox_context_clean_post_stop(ctxt, builder, error))
ret = FALSE;
if (builder)
g_object_unref(builder);
g_object_unref(connection);
return ret;
}
static void gvir_sandbox_context_interactive_class_init(GVirSandboxContextInteractiveClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
GVirSandboxContextClass *context_class = GVIR_SANDBOX_CONTEXT_CLASS(klass);
object_class->finalize = gvir_sandbox_context_interactive_finalize;
object_class->get_property = gvir_sandbox_context_interactive_get_property;
object_class->set_property = gvir_sandbox_context_interactive_set_property;
context_class->start = gvir_sandbox_context_interactive_start;
context_class->stop = gvir_sandbox_context_interactive_stop;
g_type_class_add_private(klass, sizeof(GVirSandboxContextInteractivePrivate));
}
......
......@@ -22,6 +22,7 @@
#include <config.h>
#include <string.h>
#include <errno.h>
#include "libvirt-sandbox/libvirt-sandbox.h"
......@@ -59,6 +60,14 @@ enum {
//static gint signals[LAST_SIGNAL];
#define GVIR_SANDBOX_CONTEXT_SERVICE_ERROR gvir_sandbox_context_service_error_quark()
static GQuark
gvir_sandbox_context_service_error_quark(void)
{
return g_quark_from_static_string("gvir-sandbox-context-service");
}
static void gvir_sandbox_context_service_get_property(GObject *object,
guint prop_id,
GValue *value G_GNUC_UNUSED,
......@@ -94,6 +103,197 @@ static void gvir_sandbox_context_service_set_property(GObject *object,
}
}
static gboolean gvir_sandbox_context_service_define_default(GVirSandboxContextService *ctxt, GError **error)
{
GVirConfigDomain *configdom = NULL;
GVirSandboxBuilder *builder = NULL;
GVirSandboxConfig *config;
GVirConnection *connection;
const gchar *cachedir;
gchar *statedir;
gchar *configdir;
gchar *emptydir;
gchar *configfile;
gboolean ret = FALSE;
connection = gvir_sandbox_context_get_connection(GVIR_SANDBOX_CONTEXT(ctxt));
config = gvir_sandbox_context_get_config(GVIR_SANDBOX_CONTEXT(ctxt));
cachedir = (getuid() ? g_get_user_cache_dir() : RUNDIR);
statedir = g_build_filename(cachedir, "libvirt-sandbox",
gvir_sandbox_config_get_name(config),
NULL);
configdir = g_build_filename(statedir, "config", NULL);
configfile = g_build_filename(configdir, "sandbox.cfg", NULL);
emptydir = g_build_filename(configdir, "empty", NULL);
if (!(builder = gvir_sandbox_builder_for_connection(connection,
error)))
goto cleanup;
g_mkdir_with_parents(statedir, 0700);
g_mkdir_with_parents(configdir, 0700);
unlink(configfile);
if (!gvir_sandbox_config_save_to_path(config, configfile, error))
goto cleanup;
g_mkdir_with_parents(emptydir, 0755);
if (!(configdom = gvir_sandbox_builder_construct(builder,
config,
statedir,
error))) {
goto cleanup;
}
ret = TRUE;
cleanup:
g_free(statedir);
g_free(configdir);
g_free(configfile);
g_free(emptydir);
if (configdom)
g_object_unref(configdom);
if (builder)
g_object_unref(builder);
if (connection)
g_object_unref(connection);
if (config)
g_object_unref(config);
return ret;
}
static gboolean gvir_sandbox_context_service_undefine_default(GVirSandboxContextService *ctxt, GError **error)
{
GVirSandboxBuilder *builder = NULL;
GVirSandboxConfig *config;
GVirConnection *connection;
const gchar *cachedir;
gchar *statedir;
gchar *configdir;
gchar *configfile;
gchar *emptydir;
gboolean ret = TRUE;
connection = gvir_sandbox_context_get_connection(GVIR_SANDBOX_CONTEXT(ctxt));
config = gvir_sandbox_context_get_config(GVIR_SANDBOX_CONTEXT(ctxt));
cachedir = (getuid() ? g_get_user_cache_dir() : RUNDIR);
statedir = g_build_filename(cachedir, "libvirt-sandbox",
gvir_sandbox_config_get_name(config),
NULL);
configdir = g_build_filename(statedir, "config", NULL);
configfile = g_build_filename(configdir, "sandbox.cfg", NULL);
emptydir = g_build_filename(configdir, "empty", NULL);
if (!(builder = gvir_sandbox_builder_for_connection(connection,
error))) {
ret = FALSE;
goto cleanup;
}
if (unlink(configfile) < 0 &&
errno != ENOENT)
ret = FALSE;
if (rmdir(emptydir) < 0 &&
errno != ENOENT)
ret = FALSE;
if (rmdir(configdir) < 0 &&
errno != ENOENT)
ret = FALSE;
if (rmdir(statedir) < 0 &&
errno != ENOENT)
ret = FALSE;
if (!gvir_sandbox_builder_clean_post_stop(builder,
config,
statedir,
error))
ret = FALSE;
cleanup:
if (builder)
g_object_unref(builder);
if (connection)
g_object_unref(connection);
if (config)
g_object_unref(config);
g_free(configfile);
g_free(emptydir);
g_free(statedir);
g_free(configdir);
return ret;
}
static gboolean gvir_sandbox_context_service_start(GVirSandboxContext *ctxt, GError **error)
{
GVirConnection *connection = NULL;
GVirDomain *domain = NULL;
GVirSandboxConfig *config = NULL;
gboolean ret = FALSE;
if (!GVIR_SANDBOX_CONTEXT_CLASS(gvir_sandbox_context_service_parent_class)->start(ctxt, error))
return FALSE;
connection = gvir_sandbox_context_get_connection(ctxt);
config = gvir_sandbox_context_get_config(ctxt);
if (!gvir_connection_fetch_domains(connection, NULL, error))
goto cleanup;
if (!(domain = gvir_connection_find_domain_by_name(
connection,
gvir_sandbox_config_get_name(config)))) {
*error = g_error_new(GVIR_SANDBOX_CONTEXT_SERVICE_ERROR, 0,
"Sandbox %s does not exist",
gvir_sandbox_config_get_name(config));
goto cleanup;
}
if (!gvir_domain_start(domain, 0, error))
goto cleanup;
g_object_set(ctxt, "domain", domain, NULL);
ret = TRUE;
cleanup:
g_object_unref(config);
g_object_unref(connection);
if (domain)
g_object_unref(domain);
return ret;
}
static gboolean gvir_sandbox_context_service_stop(GVirSandboxContext *ctxt, GError **error)
{
GVirDomain *domain;
gboolean ret = TRUE;
if (!GVIR_SANDBOX_CONTEXT_CLASS(gvir_sandbox_context_service_parent_class)->stop(ctxt, error))
return FALSE;
if (!(domain = gvir_sandbox_context_get_domain(ctxt, error)))
return FALSE;
if (!gvir_domain_stop(domain, 0, error))
ret = FALSE;
g_object_set(ctxt, "domain", NULL, NULL);
g_object_unref(domain);
return ret;
}
static void gvir_sandbox_context_service_finalize(GObject *object)
{
......@@ -109,11 +309,18 @@ static void gvir_sandbox_context_service_finalize(GObject *object)
static void gvir_sandbox_context_service_class_init(GVirSandboxContextServiceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
GVirSandboxContextClass *context_class = GVIR_SANDBOX_CONTEXT_CLASS(klass);
object_class->finalize = gvir_sandbox_context_service_finalize;
object_class->get_property = gvir_sandbox_context_service_get_property;
object_class->set_property = gvir_sandbox_context_service_set_property;
context_class->start = gvir_sandbox_context_service_start;
context_class->stop = gvir_sandbox_context_service_stop;
klass->define = gvir_sandbox_context_service_define_default;
klass->undefine = gvir_sandbox_context_service_undefine_default;
g_type_class_add_private(klass, sizeof(GVirSandboxContextServicePrivate));
}
......@@ -142,3 +349,15 @@ GVirSandboxContextService *gvir_sandbox_context_service_new(GVirConnection *conn
"autodestroy", FALSE,
NULL));
}
gboolean gvir_sandbox_context_service_define(GVirSandboxContextService *ctxt, GError **error)
{
return GVIR_SANDBOX_CONTEXT_SERVICE_GET_CLASS(ctxt)->define(ctxt, error);
}
gboolean gvir_sandbox_context_service_undefine(GVirSandboxContextService *ctxt, GError **error)
{
return GVIR_SANDBOX_CONTEXT_SERVICE_GET_CLASS(ctxt)->undefine(ctxt, error);
}
......@@ -53,6 +53,9 @@ struct _GVirSandboxContextServiceClass
{
GVirSandboxContextClass parent_class;
gboolean (*define)(GVirSandboxContextService *ctxt, GError **error);
gboolean (*undefine)(GVirSandboxContextService *ctxt, GError **error);
gpointer padding[LIBVIRT_SANDBOX_CLASS_PADDING];
};
......@@ -61,6 +64,9 @@ GType gvir_sandbox_context_service_get_type(void);
GVirSandboxContextService *gvir_sandbox_context_service_new(GVirConnection *connection,
GVirSandboxConfigService *config);
gboolean gvir_sandbox_context_service_define(GVirSandboxContextService *ctxt, GError **error);
gboolean gvir_sandbox_context_service_undefine(GVirSandboxContextService *ctxt, GError **error);
G_END_DECLS
#endif /* __LIBVIRT_SANDBOX_CONTEXT_SERVICE_H__ */
......@@ -336,93 +336,9 @@ gboolean gvir_sandbox_context_get_autodestroy(GVirSandboxContext *ctxt)
}
static gboolean gvir_sandbox_context_clean_post_start(GVirSandboxContext *ctxt,
GVirSandboxBuilder *builder,
GError **error)
{
GVirSandboxContextPrivate *priv = ctxt->priv;
const gchar *cachedir;
gchar *tmpdir;
gboolean ret = TRUE;
cachedir = (getuid() ? g_get_user_cache_dir() : RUNDIR);
tmpdir = g_build_filename(cachedir, "libvirt-sandbox",
gvir_sandbox_config_get_name(priv->config),
NULL);
if (!gvir_sandbox_builder_clean_post_start(builder,
priv->config,
tmpdir,
error))
ret = FALSE;
g_free(tmpdir);
return ret;
}
static gboolean gvir_sandbox_context_clean_post_stop(GVirSandboxContext *ctxt,
GVirSandboxBuilder *builder,
GError **error)
{
GVirSandboxContextPrivate *priv = ctxt->priv;
const gchar *cachedir;
gchar *statedir;
gchar *configdir;
gchar *configfile;
gchar *emptydir;
gboolean ret = TRUE;
cachedir = (getuid() ? g_get_user_cache_dir() : RUNDIR);
statedir = g_build_filename(cachedir, "libvirt-sandbox",
gvir_sandbox_config_get_name(priv->config),
NULL);
configdir = g_build_filename(statedir, "config", NULL);
configfile = g_build_filename(configdir, "sandbox.cfg", NULL);
emptydir = g_build_filename(configdir, "empty", NULL);
if (unlink(configfile) < 0 &&
errno != ENOENT)
ret = FALSE;
if (rmdir(emptydir) < 0 &&
errno != ENOENT)
ret = FALSE;
if (rmdir(configdir) < 0 &&
errno != ENOENT)
ret = FALSE;
if (rmdir(statedir) < 0 &&
errno != ENOENT)
ret = FALSE;
if (!gvir_sandbox_builder_clean_post_stop(builder,
priv->config,
statedir,
error))
ret = FALSE;
g_free(configfile);
g_free(emptydir);
g_free(statedir);
g_free(configdir);
return ret;
}
static gboolean gvir_sandbox_context_start_default(GVirSandboxContext *ctxt, GError **error)
{
GVirSandboxContextPrivate *priv = ctxt->priv;
GVirConfigDomain *config = NULL;
GVirSandboxBuilder *builder = NULL;
const gchar *cachedir;
gchar *statedir;
gchar *configdir;
gchar *emptydir;
gchar *configfile;
gboolean ret = FALSE;
int flags = 0;
if (priv->domain) {
*error = g_error_new(GVIR_SANDBOX_CONTEXT_ERROR, 0,
......@@ -430,67 +346,7 @@ static gboolean gvir_sandbox_context_start_default(GVirSandboxContext *ctxt, GEr
return FALSE;
}
if (!(builder = gvir_sandbox_builder_for_connection(priv->connection,
error)))
return FALSE;
cachedir = (getuid() ? g_get_user_cache_dir() : RUNDIR);
statedir = g_build_filename(cachedir, "libvirt-sandbox",
gvir_sandbox_config_get_name(priv->config),
NULL);
configdir = g_build_filename(statedir, "config", NULL);
configfile = g_build_filename(configdir, "sandbox.cfg", NULL);
emptydir = g_build_filename(configdir, "empty", NULL);
g_mkdir_with_parents(statedir, 0700);
g_mkdir_with_parents(configdir, 0700);
unlink(configfile);
if (!gvir_sandbox_config_save_to_path(priv->config, configfile, error))
goto error;
g_mkdir_with_parents(emptydir, 0755);
if (!(config = gvir_sandbox_builder_construct(builder,
priv->config,
statedir,
error))) {
goto error;
}
if (priv->autodestroy)
flags |= GVIR_DOMAIN_START_AUTODESTROY;
if (!(priv->domain = gvir_connection_start_domain(priv->connection,
config,
flags,
error)))
goto error;
if (!gvir_sandbox_context_clean_post_start(ctxt, builder, error))
goto error;
ret = TRUE;
cleanup:
g_free(statedir);
g_free(configdir);
g_free(configfile);
g_free(emptydir);
if (config)
g_object_unref(config);
if (builder)
g_object_unref(builder);
return ret;
error:
if (priv->domain) {
gvir_domain_stop(priv->domain, 0, NULL);
g_object_unref(priv->domain);
priv->domain = NULL;
}
goto cleanup;
return TRUE;
}
......@@ -524,8 +380,11 @@ static gboolean gvir_sandbox_context_detach_default(GVirSandboxContext *ctxt, GE
{
GVirSandboxContextPrivate *priv = ctxt->priv;
if (!priv->domain)
return TRUE;
if (!priv->domain) {
g_set_error(error, GVIR_SANDBOX_CONTEXT_ERROR, 0,
_("Sandbox is not currently running"));
return FALSE;
}
g_object_unref(priv->domain);
priv->domain = NULL;
......@@ -537,30 +396,14 @@ static gboolean gvir_sandbox_context_detach_default(GVirSandboxContext *ctxt, GE
static gboolean gvir_sandbox_context_stop_default(GVirSandboxContext *ctxt, GError **error)
{
GVirSandboxContextPrivate *priv = ctxt->priv;
GVirSandboxBuilder *builder;
gboolean ret = TRUE;
if (!priv->domain)
return TRUE;
if (!gvir_domain_stop(priv->domain, 0, error))
ret = FALSE;
g_object_unref(priv->domain);
priv->domain = NULL;
if (!(builder = gvir_sandbox_builder_for_connection(priv->connection,
error)))
ret = FALSE;
if (builder &&
!gvir_sandbox_context_clean_post_stop(ctxt, builder, error))
ret = FALSE;
if (builder)
g_object_unref(builder);
if (!priv->domain) {
g_set_error(error, GVIR_SANDBOX_CONTEXT_ERROR, 0,
_("Sandbox is not currently running"));
return FALSE;
}
return ret;
return TRUE;
}
......@@ -579,7 +422,7 @@ GVirSandboxConsole *gvir_sandbox_context_get_log_console(GVirSandboxContext *ctx
if (!priv->domain) {
g_set_error(error, GVIR_SANDBOX_CONTEXT_ERROR, 0,