|
|
4ab194 |
From da9529ca4c5bb4424f258275c5678a9190444b78 Mon Sep 17 00:00:00 2001
|
|
|
4ab194 |
From: Christophe Fergeau <cfergeau@redhat.com>
|
|
|
4ab194 |
Date: Thu, 17 Apr 2014 21:00:28 +0200
|
|
|
4ab194 |
Subject: [PATCH] Create foreign menu from .vv file information
|
|
|
4ab194 |
|
|
|
4ab194 |
When the .vv file has an [ovirt] section, we should try to create a foreign
|
|
|
4ab194 |
menu out of it. This will allow remote-viewer to offer a menu to change the
|
|
|
4ab194 |
currenty inserted cdrom.
|
|
|
4ab194 |
|
|
|
4ab194 |
Contrary to the ovirt:// case when we already have fetched an OvirtAPI
|
|
|
4ab194 |
and OvirtVm instance in order to get the SPICE/VNC connection details,
|
|
|
4ab194 |
when working from a .vv file, we'll need to get them from the REST API.
|
|
|
4ab194 |
Authentication should happen through the JSESSIONID cookie, if that
|
|
|
4ab194 |
fails we want to give up on using the foreign menu, so we don't need to
|
|
|
4ab194 |
set up authentication callbacks.
|
|
|
4ab194 |
|
|
|
4ab194 |
Resolves: rhbz#1127156
|
|
|
4ab194 |
(cherry picked from commit 6ab5444c81a8f6a15012a55283e2737406fb08b1)
|
|
|
4ab194 |
---
|
|
|
4ab194 |
src/ovirt-foreign-menu.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
4ab194 |
src/ovirt-foreign-menu.h | 2 +
|
|
|
4ab194 |
src/remote-viewer.c | 9 +++
|
|
|
4ab194 |
3 files changed, 197 insertions(+)
|
|
|
4ab194 |
|
|
|
4ab194 |
diff --git a/src/ovirt-foreign-menu.c b/src/ovirt-foreign-menu.c
|
|
|
4ab194 |
index 0453ca1..6fc9577 100644
|
|
|
4ab194 |
--- a/src/ovirt-foreign-menu.c
|
|
|
4ab194 |
+++ b/src/ovirt-foreign-menu.c
|
|
|
4ab194 |
@@ -25,12 +25,16 @@
|
|
|
4ab194 |
|
|
|
4ab194 |
#include <config.h>
|
|
|
4ab194 |
|
|
|
4ab194 |
+#include <string.h>
|
|
|
4ab194 |
+
|
|
|
4ab194 |
#include "ovirt-foreign-menu.h"
|
|
|
4ab194 |
#include "virt-glib-compat.h"
|
|
|
4ab194 |
#include "virt-viewer-util.h"
|
|
|
4ab194 |
|
|
|
4ab194 |
typedef enum {
|
|
|
4ab194 |
STATE_0,
|
|
|
4ab194 |
+ STATE_API,
|
|
|
4ab194 |
+ STATE_VM,
|
|
|
4ab194 |
STATE_STORAGE_DOMAIN,
|
|
|
4ab194 |
STATE_VM_CDROM,
|
|
|
4ab194 |
STATE_CDROM_FILE,
|
|
|
4ab194 |
@@ -38,6 +42,8 @@ typedef enum {
|
|
|
4ab194 |
} OvirtForeignMenuState;
|
|
|
4ab194 |
|
|
|
4ab194 |
static void ovirt_foreign_menu_next_async_step(OvirtForeignMenu *menu, OvirtForeignMenuState state);
|
|
|
4ab194 |
+static void ovirt_foreign_menu_fetch_api_async(OvirtForeignMenu *menu);
|
|
|
4ab194 |
+static void ovirt_foreign_menu_fetch_vm_async(OvirtForeignMenu *menu);
|
|
|
4ab194 |
static void ovirt_foreign_menu_fetch_storage_domain_async(OvirtForeignMenu *menu);
|
|
|
4ab194 |
static void ovirt_foreign_menu_fetch_vm_cdrom_async(OvirtForeignMenu *menu);
|
|
|
4ab194 |
static void ovirt_foreign_menu_refresh_cdrom_file_async(OvirtForeignMenu *menu);
|
|
|
4ab194 |
@@ -50,6 +56,7 @@ struct _OvirtForeignMenuPrivate {
|
|
|
4ab194 |
OvirtProxy *proxy;
|
|
|
4ab194 |
OvirtApi *api;
|
|
|
4ab194 |
OvirtVm *vm;
|
|
|
4ab194 |
+ char *vm_guid;
|
|
|
4ab194 |
|
|
|
4ab194 |
OvirtCollection *files;
|
|
|
4ab194 |
OvirtCdrom *cdrom;
|
|
|
4ab194 |
@@ -75,6 +82,7 @@ enum {
|
|
|
4ab194 |
PROP_VM,
|
|
|
4ab194 |
PROP_FILE,
|
|
|
4ab194 |
PROP_FILES,
|
|
|
4ab194 |
+ PROP_VM_GUID,
|
|
|
4ab194 |
};
|
|
|
4ab194 |
|
|
|
4ab194 |
|
|
|
4ab194 |
@@ -117,6 +125,10 @@ ovirt_foreign_menu_get_property(GObject *object, guint property_id,
|
|
|
4ab194 |
case PROP_FILES:
|
|
|
4ab194 |
g_value_set_pointer(value, priv->iso_names);
|
|
|
4ab194 |
break;
|
|
|
4ab194 |
+ case PROP_VM_GUID:
|
|
|
4ab194 |
+ g_value_set_string(value, priv->vm_guid);
|
|
|
4ab194 |
+ break;
|
|
|
4ab194 |
+
|
|
|
4ab194 |
default:
|
|
|
4ab194 |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
|
4ab194 |
}
|
|
|
4ab194 |
@@ -148,6 +160,19 @@ ovirt_foreign_menu_set_property(GObject *object, guint property_id,
|
|
|
4ab194 |
g_object_unref(priv->vm);
|
|
|
4ab194 |
}
|
|
|
4ab194 |
priv->vm = g_value_dup_object(value);
|
|
|
4ab194 |
+ g_free(priv->vm_guid);
|
|
|
4ab194 |
+ priv->vm_guid = NULL;
|
|
|
4ab194 |
+ if (priv->vm != NULL) {
|
|
|
4ab194 |
+ g_object_get(G_OBJECT(priv->vm), "guid", &priv->vm_guid, NULL);
|
|
|
4ab194 |
+ }
|
|
|
4ab194 |
+ break;
|
|
|
4ab194 |
+ case PROP_VM_GUID:
|
|
|
4ab194 |
+ if (priv->vm != NULL) {
|
|
|
4ab194 |
+ g_object_unref(priv->vm);
|
|
|
4ab194 |
+ priv->vm = NULL;
|
|
|
4ab194 |
+ }
|
|
|
4ab194 |
+ g_free(priv->vm_guid);
|
|
|
4ab194 |
+ priv->vm_guid = g_value_dup_string(value);
|
|
|
4ab194 |
break;
|
|
|
4ab194 |
default:
|
|
|
4ab194 |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
|
4ab194 |
@@ -175,6 +200,9 @@ ovirt_foreign_menu_dispose(GObject *obj)
|
|
|
4ab194 |
self->priv->vm = NULL;
|
|
|
4ab194 |
}
|
|
|
4ab194 |
|
|
|
4ab194 |
+ g_free(self->priv->vm_guid);
|
|
|
4ab194 |
+ self->priv->vm_guid = NULL;
|
|
|
4ab194 |
+
|
|
|
4ab194 |
if (self->priv->files) {
|
|
|
4ab194 |
g_object_unref(self->priv->files);
|
|
|
4ab194 |
self->priv->files = NULL;
|
|
|
4ab194 |
@@ -251,6 +279,15 @@ ovirt_foreign_menu_class_init(OvirtForeignMenuClass *klass)
|
|
|
4ab194 |
"GSList of ISO names for this oVirt VM",
|
|
|
4ab194 |
G_PARAM_READABLE |
|
|
|
4ab194 |
G_PARAM_STATIC_STRINGS));
|
|
|
4ab194 |
+ g_object_class_install_property(oclass,
|
|
|
4ab194 |
+ PROP_VM_GUID,
|
|
|
4ab194 |
+ g_param_spec_string("vm-guid",
|
|
|
4ab194 |
+ "VM GUID",
|
|
|
4ab194 |
+ "GUID of the virtual machine to provide a foreign menu for",
|
|
|
4ab194 |
+ NULL,
|
|
|
4ab194 |
+ G_PARAM_READWRITE |
|
|
|
4ab194 |
+ G_PARAM_CONSTRUCT_ONLY |
|
|
|
4ab194 |
+ G_PARAM_STATIC_STRINGS));
|
|
|
4ab194 |
}
|
|
|
4ab194 |
|
|
|
4ab194 |
|
|
|
4ab194 |
@@ -278,6 +315,22 @@ ovirt_foreign_menu_next_async_step(OvirtForeignMenu *menu,
|
|
|
4ab194 |
|
|
|
4ab194 |
current_state++;
|
|
|
4ab194 |
|
|
|
4ab194 |
+ if (current_state == STATE_API) {
|
|
|
4ab194 |
+ if (menu->priv->api == NULL) {
|
|
|
4ab194 |
+ ovirt_foreign_menu_fetch_api_async(menu);
|
|
|
4ab194 |
+ } else {
|
|
|
4ab194 |
+ current_state++;
|
|
|
4ab194 |
+ }
|
|
|
4ab194 |
+ }
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+ if (current_state == STATE_VM) {
|
|
|
4ab194 |
+ if (menu->priv->vm == NULL) {
|
|
|
4ab194 |
+ ovirt_foreign_menu_fetch_vm_async(menu);
|
|
|
4ab194 |
+ } else {
|
|
|
4ab194 |
+ current_state++;
|
|
|
4ab194 |
+ }
|
|
|
4ab194 |
+ }
|
|
|
4ab194 |
+
|
|
|
4ab194 |
if (current_state == STATE_STORAGE_DOMAIN) {
|
|
|
4ab194 |
if (menu->priv->files == NULL) {
|
|
|
4ab194 |
ovirt_foreign_menu_fetch_storage_domain_async(menu);
|
|
|
4ab194 |
@@ -635,6 +688,90 @@ static void ovirt_foreign_menu_fetch_storage_domain_async(OvirtForeignMenu *menu
|
|
|
4ab194 |
}
|
|
|
4ab194 |
|
|
|
4ab194 |
|
|
|
4ab194 |
+static void vms_fetched_cb(GObject *source_object,
|
|
|
4ab194 |
+ GAsyncResult *result,
|
|
|
4ab194 |
+ gpointer user_data)
|
|
|
4ab194 |
+{
|
|
|
4ab194 |
+ GError *error = NULL;
|
|
|
4ab194 |
+ OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(user_data);
|
|
|
4ab194 |
+ OvirtCollection *collection;
|
|
|
4ab194 |
+ GHashTableIter iter;
|
|
|
4ab194 |
+ OvirtVm *vm;
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+ collection = OVIRT_COLLECTION(source_object);
|
|
|
4ab194 |
+ ovirt_collection_fetch_finish(collection, result, &error);
|
|
|
4ab194 |
+ if (error != NULL) {
|
|
|
4ab194 |
+ g_debug("failed to fetch VM list: %s", error->message);
|
|
|
4ab194 |
+ g_clear_error(&error);
|
|
|
4ab194 |
+ return;
|
|
|
4ab194 |
+ }
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+ g_hash_table_iter_init(&iter, ovirt_collection_get_resources(collection));
|
|
|
4ab194 |
+ while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&vm)) {
|
|
|
4ab194 |
+ char *guid;
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+ g_object_get(G_OBJECT(vm), "guid", &guid, NULL);
|
|
|
4ab194 |
+ if (g_strcmp0(guid, menu->priv->vm_guid) == 0) {
|
|
|
4ab194 |
+ menu->priv->vm = g_object_ref(vm);
|
|
|
4ab194 |
+ g_free(guid);
|
|
|
4ab194 |
+ break;
|
|
|
4ab194 |
+ }
|
|
|
4ab194 |
+ g_free(guid);
|
|
|
4ab194 |
+ }
|
|
|
4ab194 |
+ if (menu->priv->vm != NULL) {
|
|
|
4ab194 |
+ ovirt_foreign_menu_next_async_step(menu, STATE_VM);
|
|
|
4ab194 |
+ } else {
|
|
|
4ab194 |
+ g_warning("failed to find a VM with guid \"%s\"", menu->priv->vm_guid);
|
|
|
4ab194 |
+ }
|
|
|
4ab194 |
+}
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+static void ovirt_foreign_menu_fetch_vm_async(OvirtForeignMenu *menu)
|
|
|
4ab194 |
+{
|
|
|
4ab194 |
+ OvirtCollection *vms;
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+ g_return_if_fail(OVIRT_IS_FOREIGN_MENU(menu));
|
|
|
4ab194 |
+ g_return_if_fail(OVIRT_IS_PROXY(menu->priv->proxy));
|
|
|
4ab194 |
+ g_return_if_fail(OVIRT_IS_API(menu->priv->api));
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+ vms = ovirt_api_get_vms(menu->priv->api);
|
|
|
4ab194 |
+ ovirt_collection_fetch_async(vms, menu->priv->proxy,
|
|
|
4ab194 |
+ NULL, vms_fetched_cb, menu);
|
|
|
4ab194 |
+}
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+static void api_fetched_cb(GObject *source_object,
|
|
|
4ab194 |
+ GAsyncResult *result,
|
|
|
4ab194 |
+ gpointer user_data)
|
|
|
4ab194 |
+{
|
|
|
4ab194 |
+ GError *error = NULL;
|
|
|
4ab194 |
+ OvirtProxy *proxy;
|
|
|
4ab194 |
+ OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(user_data);
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+ proxy = OVIRT_PROXY(source_object);
|
|
|
4ab194 |
+ menu->priv->api = ovirt_proxy_fetch_api_finish(proxy, result, &error);
|
|
|
4ab194 |
+ if (error != NULL) {
|
|
|
4ab194 |
+ g_debug("failed to fetch toplevel API object: %s", error->message);
|
|
|
4ab194 |
+ g_clear_error(&error);
|
|
|
4ab194 |
+ return;
|
|
|
4ab194 |
+ }
|
|
|
4ab194 |
+ g_return_if_fail(OVIRT_IS_API(menu->priv->api));
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+ ovirt_foreign_menu_next_async_step(menu, STATE_API);
|
|
|
4ab194 |
+}
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+static void ovirt_foreign_menu_fetch_api_async(OvirtForeignMenu *menu)
|
|
|
4ab194 |
+{
|
|
|
4ab194 |
+ g_debug("Start fetching oVirt main entry point");
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+ g_return_if_fail(OVIRT_IS_FOREIGN_MENU(menu));
|
|
|
4ab194 |
+ g_return_if_fail(OVIRT_IS_PROXY(menu->priv->proxy));
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+ ovirt_proxy_fetch_api_async(menu->priv->proxy, NULL, api_fetched_cb, menu);
|
|
|
4ab194 |
+}
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+
|
|
|
4ab194 |
static void iso_list_fetched_cb(GObject *source_object,
|
|
|
4ab194 |
GAsyncResult *result,
|
|
|
4ab194 |
gpointer user_data)
|
|
|
4ab194 |
@@ -684,3 +821,52 @@ static gboolean ovirt_foreign_menu_refresh_iso_list(gpointer user_data)
|
|
|
4ab194 |
*/
|
|
|
4ab194 |
return G_SOURCE_REMOVE;
|
|
|
4ab194 |
}
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+OvirtForeignMenu *ovirt_foreign_menu_new_from_file(VirtViewerFile *file)
|
|
|
4ab194 |
+{
|
|
|
4ab194 |
+ OvirtProxy *proxy = NULL;
|
|
|
4ab194 |
+ OvirtForeignMenu *menu = NULL;
|
|
|
4ab194 |
+ char *ca_str = NULL;
|
|
|
4ab194 |
+ char *jsessionid = NULL;
|
|
|
4ab194 |
+ char *url = NULL;
|
|
|
4ab194 |
+ char *vm_guid = NULL;
|
|
|
4ab194 |
+ GByteArray *ca = NULL;
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+ url = virt_viewer_file_get_ovirt_host(file);
|
|
|
4ab194 |
+ vm_guid = virt_viewer_file_get_ovirt_vm_guid(file);
|
|
|
4ab194 |
+ jsessionid = virt_viewer_file_get_ovirt_jsessionid(file);
|
|
|
4ab194 |
+ ca_str = virt_viewer_file_get_ovirt_ca(file);
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+ if ((url == NULL) || (vm_guid == NULL))
|
|
|
4ab194 |
+ goto end;
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+ proxy = ovirt_proxy_new(url);
|
|
|
4ab194 |
+ if (proxy == NULL)
|
|
|
4ab194 |
+ goto end;
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+ if (ca_str != NULL) {
|
|
|
4ab194 |
+ ca = g_byte_array_new_take((guint8 *)ca_str, strlen(ca_str) + 1);
|
|
|
4ab194 |
+ ca_str = NULL;
|
|
|
4ab194 |
+ }
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+ g_object_set(G_OBJECT(proxy),
|
|
|
4ab194 |
+ "session-id", jsessionid,
|
|
|
4ab194 |
+ "ca-cert", ca,
|
|
|
4ab194 |
+ NULL);
|
|
|
4ab194 |
+ menu = g_object_new(OVIRT_TYPE_FOREIGN_MENU,
|
|
|
4ab194 |
+ "proxy", proxy,
|
|
|
4ab194 |
+ "vm-guid", vm_guid,
|
|
|
4ab194 |
+ NULL);
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+end:
|
|
|
4ab194 |
+ g_free(url);
|
|
|
4ab194 |
+ g_free(vm_guid);
|
|
|
4ab194 |
+ g_free(jsessionid);
|
|
|
4ab194 |
+ g_free(ca_str);
|
|
|
4ab194 |
+ if (ca != NULL) {
|
|
|
4ab194 |
+ g_byte_array_unref(ca);
|
|
|
4ab194 |
+ }
|
|
|
4ab194 |
+
|
|
|
4ab194 |
+ return menu;
|
|
|
4ab194 |
+}
|
|
|
4ab194 |
diff --git a/src/ovirt-foreign-menu.h b/src/ovirt-foreign-menu.h
|
|
|
4ab194 |
index 7d28f0b..cf18b52 100644
|
|
|
4ab194 |
--- a/src/ovirt-foreign-menu.h
|
|
|
4ab194 |
+++ b/src/ovirt-foreign-menu.h
|
|
|
4ab194 |
@@ -29,6 +29,7 @@
|
|
|
4ab194 |
#include <govirt/govirt.h>
|
|
|
4ab194 |
#include <gtk/gtk.h>
|
|
|
4ab194 |
|
|
|
4ab194 |
+#include "virt-viewer-file.h"
|
|
|
4ab194 |
|
|
|
4ab194 |
G_BEGIN_DECLS
|
|
|
4ab194 |
|
|
|
4ab194 |
@@ -66,6 +67,7 @@ struct _OvirtForeignMenuClass {
|
|
|
4ab194 |
GType ovirt_foreign_menu_get_type(void);
|
|
|
4ab194 |
|
|
|
4ab194 |
OvirtForeignMenu* ovirt_foreign_menu_new(OvirtProxy *proxy);
|
|
|
4ab194 |
+OvirtForeignMenu *ovirt_foreign_menu_new_from_file(VirtViewerFile *self);
|
|
|
4ab194 |
void ovirt_foreign_menu_start(OvirtForeignMenu *menu);
|
|
|
4ab194 |
|
|
|
4ab194 |
GtkWidget *ovirt_foreign_menu_get_gtk_menu(OvirtForeignMenu *foreign_menu);
|
|
|
4ab194 |
diff --git a/src/remote-viewer.c b/src/remote-viewer.c
|
|
|
4ab194 |
index 2b9b24d..11b3136 100644
|
|
|
4ab194 |
--- a/src/remote-viewer.c
|
|
|
4ab194 |
+++ b/src/remote-viewer.c
|
|
|
4ab194 |
@@ -1119,6 +1119,15 @@ retry_dialog:
|
|
|
4ab194 |
}
|
|
|
4ab194 |
|
|
|
4ab194 |
virt_viewer_session_set_file(virt_viewer_app_get_session(app), vvfile);
|
|
|
4ab194 |
+#ifdef HAVE_OVIRT
|
|
|
4ab194 |
+ if (vvfile != NULL) {
|
|
|
4ab194 |
+ OvirtForeignMenu *ovirt_menu;
|
|
|
4ab194 |
+ ovirt_menu = ovirt_foreign_menu_new_from_file(vvfile);
|
|
|
4ab194 |
+ if (ovirt_menu != NULL) {
|
|
|
4ab194 |
+ virt_viewer_app_set_ovirt_foreign_menu(app, ovirt_menu);
|
|
|
4ab194 |
+ }
|
|
|
4ab194 |
+ }
|
|
|
4ab194 |
+#endif
|
|
|
4ab194 |
|
|
|
4ab194 |
if (!virt_viewer_app_initial_connect(app, &error)) {
|
|
|
4ab194 |
const gchar *msg = error ? error->message :
|