[virt-tools-list] [virt-viewer v3 6/6] Create foreign menu from .vv file information

Christophe Fergeau cfergeau at redhat.com
Thu Aug 7 12:47:59 UTC 2014


When the .vv file has an [ovirt] section, we should try to create a foreign
menu out of it. This will allow remote-viewer to offer a menu to change the
currenty inserted cdrom.

Contrary to the ovirt:// case when we already have fetched an OvirtAPI
and OvirtVm instance in order to get the SPICE/VNC connection details,
when working from a .vv file, we'll need to get them from the REST API.
Authentication should happen through the JSESSIONID cookie, if that
fails we want to give up on using the foreign menu, so we don't need to
set up authentication callbacks.
---
 src/ovirt-foreign-menu.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++
 src/ovirt-foreign-menu.h |   2 +
 src/remote-viewer.c      |   9 +++
 3 files changed, 197 insertions(+)

diff --git a/src/ovirt-foreign-menu.c b/src/ovirt-foreign-menu.c
index 0453ca1..6fc9577 100644
--- a/src/ovirt-foreign-menu.c
+++ b/src/ovirt-foreign-menu.c
@@ -25,12 +25,16 @@
 
 #include <config.h>
 
+#include <string.h>
+
 #include "ovirt-foreign-menu.h"
 #include "virt-glib-compat.h"
 #include "virt-viewer-util.h"
 
 typedef enum {
     STATE_0,
+    STATE_API,
+    STATE_VM,
     STATE_STORAGE_DOMAIN,
     STATE_VM_CDROM,
     STATE_CDROM_FILE,
@@ -38,6 +42,8 @@ typedef enum {
 } OvirtForeignMenuState;
 
 static void ovirt_foreign_menu_next_async_step(OvirtForeignMenu *menu, OvirtForeignMenuState state);
+static void ovirt_foreign_menu_fetch_api_async(OvirtForeignMenu *menu);
+static void ovirt_foreign_menu_fetch_vm_async(OvirtForeignMenu *menu);
 static void ovirt_foreign_menu_fetch_storage_domain_async(OvirtForeignMenu *menu);
 static void ovirt_foreign_menu_fetch_vm_cdrom_async(OvirtForeignMenu *menu);
 static void ovirt_foreign_menu_refresh_cdrom_file_async(OvirtForeignMenu *menu);
@@ -50,6 +56,7 @@ struct _OvirtForeignMenuPrivate {
     OvirtProxy *proxy;
     OvirtApi *api;
     OvirtVm *vm;
+    char *vm_guid;
 
     OvirtCollection *files;
     OvirtCdrom *cdrom;
@@ -75,6 +82,7 @@ enum {
     PROP_VM,
     PROP_FILE,
     PROP_FILES,
+    PROP_VM_GUID,
 };
 
 
@@ -117,6 +125,10 @@ ovirt_foreign_menu_get_property(GObject *object, guint property_id,
     case PROP_FILES:
         g_value_set_pointer(value, priv->iso_names);
         break;
+    case PROP_VM_GUID:
+        g_value_set_string(value, priv->vm_guid);
+        break;
+
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     }
@@ -148,6 +160,19 @@ ovirt_foreign_menu_set_property(GObject *object, guint property_id,
             g_object_unref(priv->vm);
         }
         priv->vm = g_value_dup_object(value);
+        g_free(priv->vm_guid);
+        priv->vm_guid = NULL;
+        if (priv->vm != NULL) {
+            g_object_get(G_OBJECT(priv->vm), "guid", &priv->vm_guid, NULL);
+        }
+        break;
+    case PROP_VM_GUID:
+        if (priv->vm != NULL) {
+            g_object_unref(priv->vm);
+            priv->vm = NULL;
+        }
+        g_free(priv->vm_guid);
+        priv->vm_guid = g_value_dup_string(value);
         break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -175,6 +200,9 @@ ovirt_foreign_menu_dispose(GObject *obj)
         self->priv->vm = NULL;
     }
 
+    g_free(self->priv->vm_guid);
+    self->priv->vm_guid = NULL;
+
     if (self->priv->files) {
         g_object_unref(self->priv->files);
         self->priv->files = NULL;
@@ -251,6 +279,15 @@ ovirt_foreign_menu_class_init(OvirtForeignMenuClass *klass)
                                                          "GSList of ISO names for this oVirt VM",
                                                          G_PARAM_READABLE |
                                                          G_PARAM_STATIC_STRINGS));
+    g_object_class_install_property(oclass,
+                                    PROP_VM_GUID,
+                                    g_param_spec_string("vm-guid",
+                                                         "VM GUID",
+                                                         "GUID of the virtual machine to provide a foreign menu for",
+                                                         NULL,
+                                                         G_PARAM_READWRITE |
+                                                         G_PARAM_CONSTRUCT_ONLY |
+                                                         G_PARAM_STATIC_STRINGS));
 }
 
 
@@ -278,6 +315,22 @@ ovirt_foreign_menu_next_async_step(OvirtForeignMenu *menu,
 
     current_state++;
 
+    if (current_state == STATE_API) {
+        if (menu->priv->api == NULL) {
+            ovirt_foreign_menu_fetch_api_async(menu);
+        } else {
+            current_state++;
+        }
+    }
+
+    if (current_state == STATE_VM) {
+        if (menu->priv->vm == NULL) {
+            ovirt_foreign_menu_fetch_vm_async(menu);
+        } else {
+            current_state++;
+        }
+    }
+
     if (current_state == STATE_STORAGE_DOMAIN) {
         if (menu->priv->files == NULL) {
             ovirt_foreign_menu_fetch_storage_domain_async(menu);
@@ -635,6 +688,90 @@ static void ovirt_foreign_menu_fetch_storage_domain_async(OvirtForeignMenu *menu
 }
 
 
+static void vms_fetched_cb(GObject *source_object,
+                           GAsyncResult *result,
+                           gpointer user_data)
+{
+    GError *error = NULL;
+    OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(user_data);
+    OvirtCollection *collection;
+    GHashTableIter iter;
+    OvirtVm *vm;
+
+    collection = OVIRT_COLLECTION(source_object);
+    ovirt_collection_fetch_finish(collection, result, &error);
+    if (error != NULL) {
+        g_debug("failed to fetch VM list: %s", error->message);
+        g_clear_error(&error);
+        return;
+    }
+
+    g_hash_table_iter_init(&iter, ovirt_collection_get_resources(collection));
+    while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&vm)) {
+        char *guid;
+
+        g_object_get(G_OBJECT(vm), "guid", &guid, NULL);
+        if (g_strcmp0(guid, menu->priv->vm_guid) == 0) {
+            menu->priv->vm = g_object_ref(vm);
+            g_free(guid);
+            break;
+        }
+        g_free(guid);
+    }
+    if (menu->priv->vm != NULL) {
+        ovirt_foreign_menu_next_async_step(menu, STATE_VM);
+    } else {
+        g_warning("failed to find a VM with guid \"%s\"", menu->priv->vm_guid);
+    }
+}
+
+
+static void ovirt_foreign_menu_fetch_vm_async(OvirtForeignMenu *menu)
+{
+    OvirtCollection *vms;
+
+    g_return_if_fail(OVIRT_IS_FOREIGN_MENU(menu));
+    g_return_if_fail(OVIRT_IS_PROXY(menu->priv->proxy));
+    g_return_if_fail(OVIRT_IS_API(menu->priv->api));
+
+    vms = ovirt_api_get_vms(menu->priv->api);
+    ovirt_collection_fetch_async(vms, menu->priv->proxy,
+                                 NULL, vms_fetched_cb, menu);
+}
+
+
+static void api_fetched_cb(GObject *source_object,
+                           GAsyncResult *result,
+                           gpointer user_data)
+{
+    GError *error = NULL;
+    OvirtProxy *proxy;
+    OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(user_data);
+
+    proxy = OVIRT_PROXY(source_object);
+    menu->priv->api = ovirt_proxy_fetch_api_finish(proxy, result, &error);
+    if (error != NULL) {
+        g_debug("failed to fetch toplevel API object: %s", error->message);
+        g_clear_error(&error);
+        return;
+    }
+    g_return_if_fail(OVIRT_IS_API(menu->priv->api));
+
+    ovirt_foreign_menu_next_async_step(menu, STATE_API);
+}
+
+
+static void ovirt_foreign_menu_fetch_api_async(OvirtForeignMenu *menu)
+{
+    g_debug("Start fetching oVirt main entry point");
+
+    g_return_if_fail(OVIRT_IS_FOREIGN_MENU(menu));
+    g_return_if_fail(OVIRT_IS_PROXY(menu->priv->proxy));
+
+    ovirt_proxy_fetch_api_async(menu->priv->proxy, NULL, api_fetched_cb, menu);
+}
+
+
 static void iso_list_fetched_cb(GObject *source_object,
                                 GAsyncResult *result,
                                 gpointer user_data)
@@ -684,3 +821,52 @@ static gboolean ovirt_foreign_menu_refresh_iso_list(gpointer user_data)
      */
     return G_SOURCE_REMOVE;
 }
+
+
+OvirtForeignMenu *ovirt_foreign_menu_new_from_file(VirtViewerFile *file)
+{
+    OvirtProxy *proxy = NULL;
+    OvirtForeignMenu *menu = NULL;
+    char *ca_str = NULL;
+    char *jsessionid = NULL;
+    char *url = NULL;
+    char *vm_guid = NULL;
+    GByteArray *ca = NULL;
+
+    url = virt_viewer_file_get_ovirt_host(file);
+    vm_guid = virt_viewer_file_get_ovirt_vm_guid(file);
+    jsessionid = virt_viewer_file_get_ovirt_jsessionid(file);
+    ca_str = virt_viewer_file_get_ovirt_ca(file);
+
+    if ((url == NULL) || (vm_guid == NULL))
+        goto end;
+
+    proxy = ovirt_proxy_new(url);
+    if (proxy == NULL)
+        goto end;
+
+    if (ca_str != NULL) {
+        ca = g_byte_array_new_take((guint8 *)ca_str, strlen(ca_str) + 1);
+        ca_str = NULL;
+    }
+
+    g_object_set(G_OBJECT(proxy),
+                 "session-id", jsessionid,
+                 "ca-cert", ca,
+                 NULL);
+    menu = g_object_new(OVIRT_TYPE_FOREIGN_MENU,
+                        "proxy", proxy,
+                        "vm-guid", vm_guid,
+                        NULL);
+
+end:
+    g_free(url);
+    g_free(vm_guid);
+    g_free(jsessionid);
+    g_free(ca_str);
+    if (ca != NULL) {
+        g_byte_array_unref(ca);
+    }
+
+    return menu;
+}
diff --git a/src/ovirt-foreign-menu.h b/src/ovirt-foreign-menu.h
index 7d28f0b..cf18b52 100644
--- a/src/ovirt-foreign-menu.h
+++ b/src/ovirt-foreign-menu.h
@@ -29,6 +29,7 @@
 #include <govirt/govirt.h>
 #include <gtk/gtk.h>
 
+#include "virt-viewer-file.h"
 
 G_BEGIN_DECLS
 
@@ -66,6 +67,7 @@ struct _OvirtForeignMenuClass {
 GType ovirt_foreign_menu_get_type(void);
 
 OvirtForeignMenu* ovirt_foreign_menu_new(OvirtProxy *proxy);
+OvirtForeignMenu *ovirt_foreign_menu_new_from_file(VirtViewerFile *self);
 void ovirt_foreign_menu_start(OvirtForeignMenu *menu);
 
 GtkWidget *ovirt_foreign_menu_get_gtk_menu(OvirtForeignMenu *foreign_menu);
diff --git a/src/remote-viewer.c b/src/remote-viewer.c
index 9539b93..1e1a575 100644
--- a/src/remote-viewer.c
+++ b/src/remote-viewer.c
@@ -1171,6 +1171,15 @@ retry_dialog:
         }
 
         virt_viewer_session_set_file(virt_viewer_app_get_session(app), vvfile);
+#ifdef HAVE_OVIRT
+        if (vvfile != NULL) {
+            OvirtForeignMenu *ovirt_menu;
+            ovirt_menu = ovirt_foreign_menu_new_from_file(vvfile);
+            if (ovirt_menu != NULL) {
+                virt_viewer_app_set_ovirt_foreign_menu(app, ovirt_menu);
+            }
+        }
+#endif
 
         if (!virt_viewer_app_initial_connect(app, &error)) {
             const gchar *msg = error ? error->message :
-- 
1.9.3




More information about the virt-tools-list mailing list