Commit 6b505a32 authored by Daniel P. Berrange's avatar Daniel P. Berrange

Add support for accessing the shell console directly

Add a new libvirt_sandbox_context_get_shell_console() API
to access the console for the (optional) admin shell
parent d6248d46
......@@ -32,6 +32,8 @@ libvirt-sandbox/LibvirtSandbox-1.0.typelib
libvirt-sandbox/libvirt-sandbox-init-lxc
libvirt-sandbox/libvirt-sandbox-init-common
libvirt-sandbox/libvirt-sandbox-init-qemu
libvirt-sandbox/libvirt-sandbox-enum-types.h
libvirt-sandbox/libvirt-sandbox-enum-types.c
libvirt-sandbox/tests/*.cfg
libvirt-sandbox/tests/test-config
bin/virt-sandbox
......
......@@ -61,6 +61,10 @@ PKG_CHECK_MODULES(LIBVIRT_GOBJECT, libvirt-gobject-1.0 >= $LIBVIRT_GOBJECT_REQUI
GTK_DOC_CHECK([1.10],[--flavour no-tmpl])
# Setup GLIB_MKENUMS to use glib-mkenums even if GLib is uninstalled.
GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0`
AC_SUBST(GLIB_MKENUMS)
dnl Extra link-time flags for Cygwin.
dnl Copied from libxml2 configure.in, but I removed mingw changes
dnl for now since I'm not supporting mingw at present. - RWMJ
......
#!/usr/bin/python
from gi.repository import LibvirtGObject
from gi.repository import LibvirtSandbox
from gi.repository import GLib
from gi.repository import Gtk
LibvirtGObject.init_object_check(None)
config = LibvirtSandbox.Config.new("sandbox")
config.set_tty(True)
#conn=LibvirtGObject.Connection.new("qemu:///session")
conn=LibvirtGObject.Connection.new("lxc:///")
conn.open(None)
context = LibvirtSandbox.Context.new(conn, config)
context.attach()
def closed(obj, error):
Gtk.main_quit()
console = context.get_shell_console()
console.connect("closed", closed)
console.attach_stdio()
Gtk.main()
try:
console.detach()
except:
pass
......@@ -72,6 +72,16 @@ libvirt_sandbox_init_qemu_LDFLAGS = \
$(WARN_CFLAGS) \
$(NULL)
SANDBOX_TEMPLATE_FILES = \
libvirt-sandbox-enum-types.h.template \
libvirt-sandbox-enum-types.c.template \
$(NULL)
SANDBOX_GENERATED_FILES = \
libvirt-sandbox-enum-types.h \
libvirt-sandbox-enum-types.c \
$(NULL)
SANDBOX_HEADER_FILES = \
libvirt-sandbox.h \
libvirt-sandbox-main.h \
......@@ -115,6 +125,10 @@ libvirt_sandbox_1_0_la_HEADERS = \
$(SANDBOX_HEADER_FILES)
libvirt_sandbox_1_0_la_SOURCES = \
$(SANDBOX_SOURCE_FILES)
nodist_libvirt_sandbox_1_0_la_HEADERS = \
libvirt-sandbox-enum-types.h
nodist_libvirt_sandbox_1_0_la_SOURCES = \
libvirt-sandbox-enum-types.c
libvirt_sandbox_1_0_la_CFLAGS = \
-DBINDIR="\"$(bindir)\"" \
-DDATADIR="\"$(datadir)\"" \
......@@ -144,6 +158,20 @@ libvirt_sandbox_1_0_la_LDFLAGS = \
-Wl,--version-script=$(srcdir)/libvirt-sandbox.sym \
-version-info $(LIBVIRT_SANDBOX_VERSION_INFO)
EXTRA_DIST += $(SANDBOX_TEMPLATE_FILES)
BUILT_SOURCES = $(SANDBOX_GENERATED_FILES)
CLEANFILES += $(SANDBOX_GENERATED_FILES)
libvirt-sandbox-enum-types.h: $(SANDBOX_HEADER_FILES) libvirt-sandbox-enum-types.h.template
$(AM_V_GEN) ( $(GLIB_MKENUMS) --template $(srcdir)/libvirt-sandbox-enum-types.h.template $(SANDBOX_HEADER_FILES:%=$(srcdir)/%) ) | \
sed -e "s/G_TYPE_VIR_CONFIG/GVIR_CONFIG_TYPE/" -e "s/g_vir/gvir/" > libvirt-sandbox-enum-types.h
libvirt-sandbox-enum-types.c: $(SANDBOX_HEADER_FILES) libvirt-sandbox-enum-types.c.template
$(AM_V_GEN) ( $(GLIB_MKENUMS) --template $(srcdir)/libvirt-sandbox-enum-types.c.template $(SANDBOX_HEADER_FILES:%=$(srcdir)/%) ) | \
sed -e "s/G_TYPE_VIR_CONFIG/GVIR_CONFIG_TYPE/" -e "s/g_vir/gvir/" > libvirt-sandbox-enum-types.c
if WITH_INTROSPECTION
LibvirtSandbox-1.0.gir: libvirt-sandbox-1.0.la $(G_IR_SCANNER) Makefile.am
......@@ -165,7 +193,9 @@ LibvirtSandbox-1.0.gir: libvirt-sandbox-1.0.la $(G_IR_SCANNER) Makefile.am
--pkg-export=libvirt-sandbox-1.0 \
$(srcdir)/libvirt-sandbox.h \
$(SANDBOX_SOURCE_FILES:%=$(srcdir)/%) \
$(SANDBOX_HEADER_FILES:%=$(srcdir)/%)
$(SANDBOX_HEADER_FILES:%=$(srcdir)/%) \
$(SANDBOX_GENERATED_FILES:%=%) \
$(NULL)
girdir = $(datadir)/gir-1.0
gir_DATA = LibvirtSandbox-1.0.gir
......
......@@ -26,7 +26,6 @@
#include <termios.h>
#include <errno.h>
#include <string.h>
#include <libvirt/libvirt.h>
#include <libvirt-glib/libvirt-glib-error.h>
#include "libvirt-sandbox/libvirt-sandbox.h"
......@@ -57,6 +56,7 @@ struct _GVirSandboxConsolePrivate
GVirDomain *domain;
GVirStream *console;
GVirSandboxConsoleTarget target;
GUnixInputStream *localStdin;
GUnixOutputStream *localStdout;
......@@ -93,6 +93,7 @@ enum {
PROP_CONNECTION,
PROP_DOMAIN,
PROP_TARGET,
};
enum {
......@@ -110,9 +111,9 @@ gvir_sandbox_console_error_quark(void)
}
static void gvir_sandbox_console_get_property(GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GVirSandboxConsole *console = GVIR_SANDBOX_CONSOLE(object);
GVirSandboxConsolePrivate *priv = console->priv;
......@@ -126,6 +127,10 @@ static void gvir_sandbox_console_get_property(GObject *object,
g_value_set_object(value, priv->domain);
break;
case PROP_TARGET:
g_value_set_enum(value, priv->target);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
}
......@@ -153,6 +158,19 @@ static void gvir_sandbox_console_set_property(GObject *object,
priv->domain = g_value_dup_object(value);
break;
case PROP_TARGET:
priv->target = g_value_get_enum(value);
if (priv->target == GVIR_SANDBOX_CONSOLE_TARGET_PRIMARY) {
priv->guestHandshake = FALSE;
priv->guestError = FALSE;
} else {
/* Non primary consoles don't do handshake, so pretend
* we've already done it */
priv->guestHandshake = TRUE;
priv->guestError = FALSE;
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
}
......@@ -210,6 +228,19 @@ static void gvir_sandbox_console_class_init(GVirSandboxConsoleClass *klass)
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_NICK |
G_PARAM_STATIC_BLURB));
g_object_class_install_property(object_class,
PROP_TARGET,
g_param_spec_enum("target",
"Target",
"Target device",
GVIR_SANDBOX_TYPE_CONSOLE_TARGET,
GVIR_SANDBOX_CONSOLE_TARGET_PRIMARY,
G_PARAM_READABLE |
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_NICK |
G_PARAM_STATIC_BLURB));
g_signal_new("closed",
G_OBJECT_CLASS_TYPE(object_class),
......@@ -235,17 +266,20 @@ static void gvir_sandbox_console_init(GVirSandboxConsole *console)
* gvir_sandbox_console_new:
* @connection: (transfer none): the libvirt connection
* @domain: (transfer none): the libvirt domain whose console to run
* @target: which console to connect to
*
* Create a new sandbox console from the specified configuration
*
* Returns: (transfer full): a new sandbox console object
*/
GVirSandboxConsole *gvir_sandbox_console_new(GVirConnection *connection,
GVirDomain *domain)
GVirDomain *domain,
GVirSandboxConsoleTarget target)
{
return GVIR_SANDBOX_CONSOLE(g_object_new(GVIR_SANDBOX_TYPE_CONSOLE,
"connection", connection,
"domain", domain,
"target", target,
NULL));
}
......@@ -589,15 +623,14 @@ cleanup:
gboolean gvir_sandbox_console_attach(GVirSandboxConsole *console,
GUnixInputStream *localStdin,
GUnixOutputStream *localStdout,
GUnixOutputStream *localStderr,
GError **error)
GUnixInputStream *localStdin,
GUnixOutputStream *localStdout,
GUnixOutputStream *localStderr,
GError **error)
{
GVirSandboxConsolePrivate *priv = console->priv;
gboolean ret = FALSE;
virDomainPtr dom;
virStreamPtr st;
const char *devname = NULL;
if (priv->localStdin) {
g_set_error(error, GVIR_SANDBOX_CONSOLE_ERROR, 0, "%s",
......@@ -614,14 +647,12 @@ gboolean gvir_sandbox_console_attach(GVirSandboxConsole *console,
priv->console = gvir_connection_get_stream(priv->connection, 0);
g_object_get(priv->domain, "handle", &dom, NULL);
g_object_get(priv->console, "handle", &st, NULL);
if (priv->target != GVIR_SANDBOX_CONSOLE_TARGET_PRIMARY) {
devname = "console1";
}
if (virDomainOpenConsole(dom, NULL, st, 0) < 0) {
gvir_set_error(error, GVIR_SANDBOX_CONSOLE_ERROR, 0,
"%s", "Cannot open console");
if (!gvir_domain_open_console(priv->domain, priv->console, devname, 0, error))
goto cleanup;
}
priv->consoleToLocalLength = priv->localToConsoleLength = 4096;
priv->consoleToLocal = g_new0(gchar, priv->consoleToLocalLength);
......
......@@ -40,6 +40,7 @@ G_BEGIN_DECLS
#define GVIR_SANDBOX_CONSOLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GVIR_SANDBOX_TYPE_CONSOLE, GVirSandboxConsoleClass))
#define GVIR_SANDBOX_TYPE_CONSOLE_HANDLE (gvir_sandbox_console_handle_get_type ())
#define GVIR_SANDBOX_TYPE_CONSOLE_TARGET (gvir_sandbox_console_target_get_type ())
typedef struct _GVirSandboxConsole GVirSandboxConsole;
typedef struct _GVirSandboxConsolePrivate GVirSandboxConsolePrivate;
......@@ -61,19 +62,26 @@ struct _GVirSandboxConsoleClass
void (*closed)(GVirSandboxConsole *console, gboolean err);
};
typedef enum {
GVIR_SANDBOX_CONSOLE_TARGET_PRIMARY,
GVIR_SANDBOX_CONSOLE_TARGET_SHELL,
} GVirSandboxConsoleTarget;
GType gvir_sandbox_console_get_type(void);
GVirSandboxConsole *gvir_sandbox_console_new(GVirConnection *connection,
GVirDomain *domain);
GVirDomain *domain,
GVirSandboxConsoleTarget target);
gboolean gvir_sandbox_console_attach_stdio(GVirSandboxConsole *console,
GError **error);
GError **error);
gboolean gvir_sandbox_console_attach(GVirSandboxConsole *console,
GUnixInputStream *localStdin,
GUnixOutputStream *localStdout,
GUnixOutputStream *localStderr,
GError **error);
GUnixInputStream *localStdin,
GUnixOutputStream *localStdout,
GUnixOutputStream *localStderr,
GError **error);
gboolean gvir_sandbox_console_detach(GVirSandboxConsole *console,
GError **error);
......
......@@ -385,7 +385,8 @@ gboolean gvir_sandbox_context_start(GVirSandboxContext *ctxt, GError **error)
if (!(gvir_sandbox_cleaner_run_post_start(priv->cleaner, NULL)))
goto error;
priv->console = gvir_sandbox_console_new(priv->connection, priv->domain);
priv->console = gvir_sandbox_console_new(priv->connection, priv->domain,
GVIR_SANDBOX_CONSOLE_TARGET_PRIMARY);
priv->active = TRUE;
g_object_unref(config);
......@@ -484,5 +485,26 @@ GVirSandboxConsole *gvir_sandbox_context_get_console(GVirSandboxContext *ctxt)
{
GVirSandboxContextPrivate *priv = ctxt->priv;
if (!priv->console)
return NULL;
return g_object_ref(priv->console);
}
/**
* gvir_sandbox_context_get_shell_console:
* @ctxt: (transfer none): the sandbox context
*
* Returns: (transfer full)(allow-none): the sandbox console (or NULL)
*/
GVirSandboxConsole *gvir_sandbox_context_get_shell_console(GVirSandboxContext *ctxt)
{
GVirSandboxContextPrivate *priv = ctxt->priv;
if (!priv->domain)
return NULL;
return gvir_sandbox_console_new(priv->connection, priv->domain,
GVIR_SANDBOX_CONSOLE_TARGET_SHELL);
}
......@@ -73,6 +73,7 @@ GVirDomain *gvir_sandbox_context_get_domain(GVirSandboxContext *ctxt);
GVirConnection *gvir_sandbox_context_get_connection(GVirSandboxContext *ctxt);
GVirSandboxConsole *gvir_sandbox_context_get_console(GVirSandboxContext *ctxt);
GVirSandboxConsole *gvir_sandbox_context_get_shell_console(GVirSandboxContext *ctxt);
G_END_DECLS
......
/*** BEGIN file-header ***/
#include <libvirt-sandbox/libvirt-sandbox.h>
/*** END file-header ***/
/*** BEGIN file-production ***/
/* enumerations from "@filename@" */
/*** END file-production ***/
/*** BEGIN value-header ***/
GType
@enum_name@_get_type (void)
{
static volatile gsize g_define_type_id__volatile = 0;
if (g_once_init_enter (&g_define_type_id__volatile))
{
static const G@Type@Value values[] = {
/*** END value-header ***/
/*** BEGIN value-production ***/
{ @VALUENAME@, "@VALUENAME@", "@valuenick@" },
/*** END value-production ***/
/*** BEGIN value-tail ***/
{ 0, NULL, NULL }
};
GType g_define_type_id =
g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
}
return g_define_type_id__volatile;
}
/*** END value-tail ***/
/*** BEGIN file-header ***/
#ifndef __LIBVIRT_SANDBOX_ENUM_TYPES_H__
#define __LIBVIRT_SANDBOX_ENUM_TYPES_H__
G_BEGIN_DECLS
/*** END file-header ***/
/*** BEGIN file-production ***/
/* enumerations from "@filename@" */
/*** END file-production ***/
/*** BEGIN value-header ***/
GType @enum_name@_get_type (void) G_GNUC_CONST;
#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
/*** END value-header ***/
/*** BEGIN file-tail ***/
G_END_DECLS
#endif /* __LIBVIRT_SANDBOX_ENUM_TYPES_H__ */
/*** END file-tail ***/
......@@ -28,6 +28,7 @@
/* Local includes */
#include <libvirt-sandbox/libvirt-sandbox-main.h>
#include <libvirt-sandbox/libvirt-sandbox-enum-types.h>
#include <libvirt-sandbox/libvirt-sandbox-config-mount.h>
#include <libvirt-sandbox/libvirt-sandbox-config-network-address.h>
#include <libvirt-sandbox/libvirt-sandbox-config-network-route.h>
......
......@@ -103,6 +103,7 @@ LIBVIRT_SANDBOX_0.0.1 {
gvir_sandbox_config_initrd_set_kver;
gvir_sandbox_console_get_type;
gvir_sandbox_console_target_get_type;
gvir_sandbox_console_new;
gvir_sandbox_console_attach;
gvir_sandbox_console_attach_stdio;
......@@ -114,6 +115,7 @@ LIBVIRT_SANDBOX_0.0.1 {
gvir_sandbox_context_get_domain;
gvir_sandbox_context_get_connection;
gvir_sandbox_context_get_console;
gvir_sandbox_context_get_shell_console;
gvir_sandbox_context_new;
gvir_sandbox_context_start;
gvir_sandbox_context_stop;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment