From 5bc4c0b342f0ebe330f0db61a0a40cf009d2b1ba Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Fri, 21 Oct 2011 13:57:11 +0100 Subject: Support for virDomainOpenGraphics API Add a new flag --attach, which instructs virt-viewer to attach to the target display using virDomainOpenGraphics, instead of initiating a VNC/SPICE connection directly. --- src/virt-viewer-app.c | 57 ++++++++++++++++++++++++++++++++++++++++++---- src/virt-viewer-app.h | 3 +++ src/virt-viewer-main.c | 5 ++++- src/virt-viewer.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++- src/virt-viewer.h | 1 + 5 files changed, 121 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/virt-viewer-app.c b/src/virt-viewer-app.c index f340917..1126ddf 100644 --- a/src/virt-viewer-app.c +++ b/src/virt-viewer-app.c @@ -111,6 +111,7 @@ struct _VirtViewerAppPrivate { gboolean authretry; gboolean started; gboolean fullscreen; + gboolean attach; VirtViewerSession *session; gboolean active; @@ -650,6 +651,26 @@ virt_viewer_app_create_session(VirtViewerApp *self, const gchar *type) return 0; } +static gboolean +virt_viewer_app_default_open_connection(VirtViewerApp *self G_GNUC_UNUSED, int *fd) +{ + *fd = -1; + return TRUE; +} + + +static int +virt_viewer_app_open_connection(VirtViewerApp *self, int *fd) +{ + VirtViewerAppClass *klass; + + g_return_val_if_fail(VIRT_VIEWER_IS_APP(self), -1); + klass = VIRT_VIEWER_APP_GET_CLASS(self); + + return klass->open_connection(self, fd); +} + + #if defined(HAVE_SOCKETPAIR) && defined(HAVE_FORK) static void virt_viewer_app_channel_open(VirtViewerSession *session, @@ -661,13 +682,18 @@ virt_viewer_app_channel_open(VirtViewerSession *session, g_return_if_fail(self != NULL); + if (!virt_viewer_app_open_connection(self, &fd)) + return; + + DEBUG_LOG("After open connection callback fd=%d", fd); + priv = self->priv; if (priv->transport && g_ascii_strcasecmp(priv->transport, "ssh") == 0 && - !priv->direct) { + !priv->direct && fd == -1) { if ((fd = virt_viewer_app_open_tunnel_ssh(priv->host, priv->port, priv->user, priv->ghost, priv->gport, NULL)) < 0) virt_viewer_app_simple_message_dialog(self, _("Connect to ssh failed.")); - } else { + } else if (fd == -1) { virt_viewer_app_simple_message_dialog(self, _("Can't connect to channel, SSH only supported.")); } @@ -690,10 +716,16 @@ virt_viewer_app_default_activate(VirtViewerApp *self) VirtViewerAppPrivate *priv = self->priv; int fd = -1; + if (!virt_viewer_app_open_connection(self, &fd)) + return -1; + + DEBUG_LOG("After open connection callback fd=%d", fd); + #if defined(HAVE_SOCKETPAIR) && defined(HAVE_FORK) if (priv->transport && g_ascii_strcasecmp(priv->transport, "ssh") == 0 && - !priv->direct) { + !priv->direct && + fd == -1) { gchar *p = NULL; if (priv->gport) { @@ -716,7 +748,7 @@ virt_viewer_app_default_activate(VirtViewerApp *self) priv->user, priv->ghost, priv->gport, priv->unixsock)) < 0) return -1; - } else if (priv->unixsock) { + } else if (priv->unixsock && fd == -1) { virt_viewer_app_trace(self, "Opening direct UNIX connection to display at %s", priv->unixsock); if ((fd = virt_viewer_app_open_unix_sock(priv->unixsock)) < 0) @@ -1190,6 +1222,7 @@ virt_viewer_app_class_init (VirtViewerAppClass *klass) klass->initial_connect = virt_viewer_app_default_initial_connect; klass->activate = virt_viewer_app_default_activate; klass->deactivated = virt_viewer_app_default_deactivated; + klass->open_connection = virt_viewer_app_default_open_connection; g_object_class_install_property(object_class, PROP_VERBOSE, @@ -1292,6 +1325,22 @@ virt_viewer_app_set_direct(VirtViewerApp *self, gboolean direct) self->priv->direct = direct; } +void +virt_viewer_app_set_attach(VirtViewerApp *self, gboolean attach) +{ + g_return_if_fail(VIRT_VIEWER_IS_APP(self)); + + self->priv->attach = attach; +} + +gboolean +virt_viewer_app_get_attach(VirtViewerApp *self) +{ + g_return_val_if_fail(VIRT_VIEWER_IS_APP(self), FALSE); + + return self->priv->attach; +} + gboolean virt_viewer_app_is_active(VirtViewerApp *self) { diff --git a/src/virt-viewer-app.h b/src/virt-viewer-app.h index 320e75c..7280873 100644 --- a/src/virt-viewer-app.h +++ b/src/virt-viewer-app.h @@ -55,6 +55,7 @@ typedef struct { int (*initial_connect) (VirtViewerApp *self); int (*activate) (VirtViewerApp *self); void (*deactivated) (VirtViewerApp *self); + gboolean (*open_connection)(VirtViewerApp *self, int *fd); } VirtViewerAppClass; GType virt_viewer_app_get_type (void); @@ -73,6 +74,8 @@ int virt_viewer_app_initial_connect(VirtViewerApp *self); void virt_viewer_app_start_reconnect_poll(VirtViewerApp *self); void virt_viewer_app_set_zoom_level(VirtViewerApp *self, gint zoom_level); void virt_viewer_app_set_direct(VirtViewerApp *self, gboolean direct); +void virt_viewer_app_set_attach(VirtViewerApp *self, gboolean attach); +gboolean virt_viewer_app_get_attach(VirtViewerApp *self); gboolean virt_viewer_app_has_session(VirtViewerApp *self); void virt_viewer_app_set_connect_info(VirtViewerApp *self, const gchar *host, diff --git a/src/virt-viewer-main.c b/src/virt-viewer-main.c index c8e1082..bb967bb 100644 --- a/src/virt-viewer-main.c +++ b/src/virt-viewer-main.c @@ -52,6 +52,7 @@ int main(int argc, char **argv) gboolean verbose = FALSE; gboolean debug = FALSE; gboolean direct = FALSE; + gboolean attach = FALSE; gboolean waitvm = FALSE; gboolean reconnect = FALSE; gboolean fullscreen = FALSE; @@ -64,6 +65,8 @@ int main(int argc, char **argv) N_("Display verbose information"), NULL }, { "direct", 'd', 0, G_OPTION_ARG_NONE, &direct, N_("Direct connection with no automatic tunnels"), NULL }, + { "attach", 'a', 0, G_OPTION_ARG_NONE, &attach, + N_("Attach to the local display using libvirt"), NULL }, { "connect", 'c', 0, G_OPTION_ARG_STRING, &uri, N_("Connect to hypervisor"), "URI"}, { "wait", 'w', 0, G_OPTION_ARG_NONE, &waitvm, @@ -121,7 +124,7 @@ int main(int argc, char **argv) virt_viewer_app_set_debug(debug); - viewer = virt_viewer_new(uri, args[0], zoom, direct, waitvm, reconnect, verbose, NULL); + viewer = virt_viewer_new(uri, args[0], zoom, direct, attach, waitvm, reconnect, verbose, NULL); if (viewer == NULL) goto cleanup; diff --git a/src/virt-viewer.c b/src/virt-viewer.c index 10865ec..9dc0ad8 100644 --- a/src/virt-viewer.c +++ b/src/virt-viewer.c @@ -40,6 +40,10 @@ #include #include +#if defined(HAVE_SOCKETPAIR) +#include +#endif + #include "virt-viewer.h" #include "virt-viewer-app.h" #include "virt-viewer-events.h" @@ -48,6 +52,7 @@ struct _VirtViewerPrivate { char *uri; virConnectPtr conn; + virDomainPtr dom; char *domkey; gboolean withEvents; gboolean waitvm; @@ -59,6 +64,7 @@ G_DEFINE_TYPE (VirtViewer, virt_viewer, VIRT_VIEWER_TYPE_APP) (G_TYPE_INSTANCE_GET_PRIVATE ((o), VIRT_VIEWER_TYPE, VirtViewerPrivate)) static int virt_viewer_initial_connect(VirtViewerApp *self); +static gboolean virt_viewer_open_connection(VirtViewerApp *self, int *fd); static void virt_viewer_deactivated(VirtViewerApp *self); static gboolean virt_viewer_start(VirtViewerApp *self); @@ -85,6 +91,12 @@ virt_viewer_set_property (GObject *object, guint property_id, static void virt_viewer_dispose (GObject *object) { + VirtViewer *self = VIRT_VIEWER(object); + VirtViewerPrivate *priv = self->priv; + if (priv->dom) + virDomainFree(priv->dom); + if (priv->conn) + virConnectClose(priv->conn); G_OBJECT_CLASS(virt_viewer_parent_class)->dispose (object); } @@ -102,6 +114,7 @@ virt_viewer_class_init (VirtViewerClass *klass) app_class->initial_connect = virt_viewer_initial_connect; app_class->deactivated = virt_viewer_deactivated; + app_class->open_connection = virt_viewer_open_connection; app_class->start = virt_viewer_start; } @@ -117,6 +130,11 @@ virt_viewer_deactivated(VirtViewerApp *app) VirtViewer *self = VIRT_VIEWER(app); VirtViewerPrivate *priv = self->priv; + if (priv->dom) { + virDomainFree(priv->dom); + priv->dom = NULL; + } + if (priv->reconnect) { if (!priv->withEvents) { DEBUG_LOG("No domain events, falling back to polling"); @@ -365,6 +383,11 @@ virt_viewer_update_display(VirtViewer *self, virDomainPtr dom) VirtViewerPrivate *priv = self->priv; VirtViewerApp *app = VIRT_VIEWER_APP(self); + if (priv->dom) + virDomainFree(priv->dom); + priv->dom = dom; + virDomainRef(priv->dom); + virt_viewer_app_trace(app, "Guest %s is running, determining display\n", priv->domkey); @@ -378,6 +401,36 @@ virt_viewer_update_display(VirtViewer *self, virDomainPtr dom) return 0; } +static gboolean +virt_viewer_open_connection(VirtViewerApp *self G_GNUC_UNUSED, int *fd) +{ +#if defined(HAVE_SOCKETPAIR) + VirtViewer *viewer = VIRT_VIEWER(self); + VirtViewerPrivate *priv = viewer->priv; + int pair[2]; +#endif + *fd = -1; +#if defined(HAVE_SOCKETPAIR) + if (!priv->dom) + return TRUE; + + if (socketpair(PF_UNIX, SOCK_STREAM, 0, pair) < 0) + return FALSE; + + if (virDomainOpenGraphics(priv->dom, 0, pair[0], + VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH) < 0) { + virErrorPtr err = virGetLastError(); + DEBUG_LOG("Error %s", err && err->message ? err->message : "Unknown"); + close(pair[0]); + close(pair[1]); + return TRUE; + } + close(pair[0]); + *fd = pair[1]; +#endif + return TRUE; +} + static int virt_viewer_domain_event(virConnectPtr conn G_GNUC_UNUSED, virDomainPtr dom, @@ -488,6 +541,10 @@ virt_viewer_start(VirtViewerApp *app) .cb = virt_viewer_auth_libvirt_credentials, .cbdata = (void *)priv->uri, }; + int oflags = 0; + + if (!virt_viewer_app_get_attach(app)) + oflags |= VIR_CONNECT_RO; virt_viewer_events_register(); @@ -498,7 +555,7 @@ virt_viewer_start(VirtViewerApp *app) priv->conn = virConnectOpenAuth(priv->uri, //virConnectAuthPtrDefault, &auth_libvirt, - VIR_CONNECT_RO); + oflags); if (!priv->conn) { virt_viewer_app_simple_message_dialog(app, _("Unable to connect to libvirt with URI %s"), priv->uri ? priv->uri : _("[none]")); @@ -530,6 +587,7 @@ virt_viewer_new(const char *uri, const char *name, gint zoom, gboolean direct, + gboolean attach, gboolean waitvm, gboolean reconnect, gboolean verbose, @@ -553,6 +611,7 @@ virt_viewer_new(const char *uri, g_object_set(app, "title", name, NULL); virt_viewer_window_set_zoom_level(virt_viewer_app_get_main_window(app), zoom); virt_viewer_app_set_direct(app, direct); + virt_viewer_app_set_attach(app, attach); /* should probably be properties instead */ priv->uri = g_strdup(uri); diff --git a/src/virt-viewer.h b/src/virt-viewer.h index 886a0f3..02512ca 100644 --- a/src/virt-viewer.h +++ b/src/virt-viewer.h @@ -53,6 +53,7 @@ virt_viewer_new(const char *uri, const char *name, gint zoom, gboolean direct, + gboolean attach, gboolean waitvm, gboolean reconnect, gboolean verbose, -- cgit