Blame SOURCES/0049-Create-foreign-menu-from-.vv-file-information.patch

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 :