<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Apr 16, 2014 at 6:59 PM, Christophe Fergeau <span dir="ltr"><<a href="mailto:cfergeau@redhat.com" target="_blank">cfergeau@redhat.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This class is used to implement the so-called oVirt 'foreign menu'<br>
which is a menu populated with ISO images available on the<br>
oVirt instance that the user can dynamically insert into the<br>
virtual machine he is currently viewing.<br>
---<br>
<a href="http://configure.ac" target="_blank">configure.ac</a> | 1 +<br>
src/Makefile.am | 4 +<br>
src/ovirt-foreign-menu.c | 580 +++++++++++++++++++++++++++++++++++++++++++++++<br>
src/ovirt-foreign-menu.h | 82 +++++++<br>
4 files changed, 667 insertions(+)<br>
create mode 100644 src/ovirt-foreign-menu.c<br>
create mode 100644 src/ovirt-foreign-menu.h<br>
<br>
diff --git a/<a href="http://configure.ac" target="_blank">configure.ac</a> b/<a href="http://configure.ac" target="_blank">configure.ac</a><br>
index f966688..4e0d7b3 100644<br>
--- a/<a href="http://configure.ac" target="_blank">configure.ac</a><br>
+++ b/<a href="http://configure.ac" target="_blank">configure.ac</a><br>
@@ -200,6 +200,7 @@ AS_IF([test "x$have_ovirt" = "xyes"],<br>
[AC_MSG_ERROR([oVirt support requested but libgovirt not found])<br>
])<br>
])<br>
+AM_CONDITIONAL([HAVE_OVIRT], [test "x$have_ovirt" = "xyes"])<br>
<br>
dnl Decide if this platform can support the SSH tunnel feature.<br>
AC_CHECK_HEADERS([sys/socket.h sys/un.h windows.h])<br>
diff --git a/src/Makefile.am b/src/Makefile.am<br>
index b3a9637..ee8f885 100644<br>
--- a/src/Makefile.am<br>
+++ b/src/Makefile.am<br>
@@ -67,6 +67,10 @@ COMMON_SOURCES += \<br>
$(NULL)<br>
endif<br>
<br>
+if HAVE_OVIRT<br>
+COMMON_SOURCES += \<br>
+ ovirt-foreign-menu.h ovirt-foreign-menu.c<br>
+endif<br>
<br>
if HAVE_LIBVIRT<br>
bin_PROGRAMS += virt-viewer<br>
diff --git a/src/ovirt-foreign-menu.c b/src/ovirt-foreign-menu.c<br>
new file mode 100644<br>
index 0000000..642c0ef<br>
--- /dev/null<br>
+++ b/src/ovirt-foreign-menu.c<br>
@@ -0,0 +1,580 @@<br>
+/*<br>
+ * Virt Viewer: A virtual machine console viewer<br>
+ *<br>
+ * Copyright (C) 2007-2013 Red Hat, Inc.<br>
+ * Copyright (C) 2009-2012 Daniel P. Berrange<br>
+ * Copyright (C) 2010 Marc-André Lureau<br>
+ *<br>
+ * This program is free software; you can redistribute it and/or modify<br>
+ * it under the terms of the GNU General Public License as published by<br>
+ * the Free Software Foundation; either version 2 of the License, or<br>
+ * (at your option) any later version.<br>
+ *<br>
+ * This program is distributed in the hope that it will be useful,<br>
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>
+ * GNU General Public License for more details.<br>
+ *<br>
+ * You should have received a copy of the GNU General Public License<br>
+ * along with this program; if not, write to the Free Software<br>
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA<br>
+ *<br>
+ * Author: Daniel P. Berrange <<a href="mailto:berrange@redhat.com">berrange@redhat.com</a>><br>
+ * Christope Fergeau <<a href="mailto:cfergeau@redhat.com">cfergeau@redhat.com</a>><br>
+ */<br>
+<br>
+#include <config.h><br>
+<br>
+#include "ovirt-foreign-menu.h"<br>
+#include "virt-glib-compat.h"<br>
+<br>
+#if !GLIB_CHECK_VERSION(2, 26, 0)<br>
+#include "gbinding.h"<br>
+#include "gbinding.c"<br>
+#endif<br>
+<br>
+typedef enum {<br>
+ STATE_0,<br>
+ STATE_STORAGE_DOMAIN,<br>
+ STATE_VM_CDROM,<br>
+ STATE_ISOS<br>
+} OvirtForeignMenuState;<br>
+<br>
+static void ovirt_foreign_menu_next_async_step(OvirtForeignMenu *menu, OvirtForeignMenuState state);<br>
+static void ovirt_foreign_menu_fetch_storage_domain_async(OvirtForeignMenu *menu);<br>
+static void ovirt_foreign_menu_fetch_vm_cdrom_async(OvirtForeignMenu *menu);<br>
+static gboolean ovirt_foreign_menu_refresh_iso_list(gpointer user_data);<br>
+<br>
+G_DEFINE_TYPE (OvirtForeignMenu, ovirt_foreign_menu, G_TYPE_OBJECT)<br>
+<br>
+<br>
+struct _OvirtForeignMenuPrivate {<br>
+ OvirtProxy *proxy;<br>
+ OvirtApi *api;<br>
+ OvirtVm *vm;<br>
+<br>
+ OvirtCollection *files;<br>
+ OvirtCdrom *cdrom;<br>
+<br>
+ GList *iso_names;<br>
+};<br>
+<br>
+<br>
+#define OVIRT_FOREIGN_MENU_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), OVIRT_TYPE_FOREIGN_MENU, OvirtForeignMenuPrivate))<br>
+<br>
+<br>
+enum {<br>
+ PROP_0,<br>
+ PROP_PROXY,<br>
+ PROP_API,<br>
+ PROP_VM,<br>
+ PROP_FILES,<br>
+};<br>
+<br>
+static void<br>
+ovirt_foreign_menu_get_property(GObject *object, guint property_id,<br>
+ GValue *value, GParamSpec *pspec)<br>
+{<br>
+ OvirtForeignMenu *self = OVIRT_FOREIGN_MENU(object);<br>
+ OvirtForeignMenuPrivate *priv = self->priv;<br>
+<br>
+ switch (property_id) {<br>
+ case PROP_PROXY:<br>
+ g_value_set_object(value, priv->proxy);<br>
+ break;<br>
+ case PROP_API:<br>
+ g_value_set_object(value, priv->api);<br>
+ break;<br>
+ case PROP_VM:<br>
+ g_value_set_object(value, priv->vm);<br>
+ break;<br>
+ case PROP_FILES:<br>
+ g_value_set_pointer(value, priv->iso_names);<br>
+<br>
+ default:<br>
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);<br>
+ }<br>
+}<br>
+<br>
+<br>
+static void<br>
+ovirt_foreign_menu_set_property(GObject *object, guint property_id,<br>
+ const GValue *value G_GNUC_UNUSED, GParamSpec *pspec)<br>
+{<br>
+ OvirtForeignMenu *self = OVIRT_FOREIGN_MENU(object);<br>
+ OvirtForeignMenuPrivate *priv = self->priv;<br>
+<br>
+ switch (property_id) {<br>
+ case PROP_PROXY:<br>
+ if (priv->proxy != NULL) {<br>
+ g_object_unref(priv->proxy);<br>
+ }<br></blockquote><div><br></div><div>newly written code can really benefit g_clear_object() / g_clear_pointer() - true for all the remaining if { unref ; foo = NULL } all over.<br><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ priv->proxy = g_value_dup_object(value);<br>
+ break;<br>
+ case PROP_API:<br>
+ if (priv->api != NULL) {<br>
+ g_object_unref(priv->api);<br>
+ }<br>
+ priv->api = g_value_dup_object(value);<br>
+ break;<br>
+ case PROP_VM:<br>
+ if (priv->vm != NULL) {<br>
+ g_object_unref(priv->vm);<br>
+ }<br>
+ priv->vm = g_value_dup_object(value);<br>
+ break;<br>
+ default:<br>
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);<br>
+ }<br>
+}<br>
+<br>
+<br>
+static void<br>
+ovirt_foreign_menu_dispose(GObject *obj)<br>
+{<br>
+ OvirtForeignMenu *self = OVIRT_FOREIGN_MENU(obj);<br>
+<br>
+ g_debug("Disposing of foreign menu");<br>
+ if (self->priv->proxy) {<br>
+ g_object_unref(self->priv->proxy);<br>
+ self->priv->proxy = NULL;<br>
+ }<br>
+<br>
+ if (self->priv->api != NULL) {<br>
+ g_object_unref(self->priv->api);<br>
+ self->priv->api = NULL;<br>
+ }<br>
+<br>
+ if (self->priv->vm) {<br>
+ g_object_unref(self->priv->vm);<br>
+ self->priv->vm = NULL;<br>
+ }<br>
+<br>
+ if (self->priv->files) {<br>
+ g_object_unref(self->priv->files);<br>
+ self->priv->files = NULL;<br>
+ }<br>
+<br>
+ if (self->priv->cdrom) {<br>
+ g_object_unref(self->priv->cdrom);<br>
+ self->priv->cdrom = NULL;<br>
+ }<br>
+<br>
+ if (self->priv->iso_names) {<br>
+ g_list_free_full(self->priv->iso_names, (GDestroyNotify)g_free);<br>
+ self->priv->iso_names = NULL;<br>
+ }<br>
+<br>
+ G_OBJECT_CLASS(ovirt_foreign_menu_parent_class)->dispose(obj);<br>
+}<br>
+<br>
+<br>
+static void<br>
+ovirt_foreign_menu_class_init(OvirtForeignMenuClass *klass)<br>
+{<br>
+ GObjectClass *oclass = G_OBJECT_CLASS(klass);<br>
+<br>
+ oclass->get_property = ovirt_foreign_menu_get_property;<br>
+ oclass->set_property = ovirt_foreign_menu_set_property;<br>
+ oclass->dispose = ovirt_foreign_menu_dispose;<br>
+<br>
+ g_type_class_add_private(klass, sizeof(OvirtForeignMenuPrivate));<br>
+<br>
+ g_object_class_install_property(oclass,<br>
+ PROP_PROXY,<br>
+ g_param_spec_object("proxy",<br>
+ "OvirtProxy instance",<br>
+ "OvirtProxy instance",<br>
+ OVIRT_TYPE_PROXY,<br>
+ G_PARAM_READWRITE |<br>
+ G_PARAM_CONSTRUCT_ONLY |<br>
+ G_PARAM_STATIC_STRINGS));<br>
+ g_object_class_install_property(oclass,<br>
+ PROP_API,<br>
+ g_param_spec_object("api",<br>
+ "OvirtApi instance",<br>
+ "Ovirt api root",<br>
+ OVIRT_TYPE_API,<br>
+ G_PARAM_READWRITE |<br>
+ G_PARAM_STATIC_STRINGS));<br>
+ g_object_class_install_property(oclass,<br>
+ PROP_VM,<br>
+ g_param_spec_object("vm",<br>
+ "OvirtVm instance",<br>
+ "OvirtVm being handled",<br>
+ OVIRT_TYPE_VM,<br>
+ G_PARAM_READWRITE |<br>
+ G_PARAM_STATIC_STRINGS));<br>
+ g_object_class_install_property(oclass,<br>
+ PROP_FILES,<br>
+ g_param_spec_pointer("files",<br>
+ "ISO names",<br>
+ "GSList of ISO names for this oVirt VM",<br>
+ G_PARAM_READABLE |<br>
+ G_PARAM_STATIC_STRINGS));<br>
+}<br>
+<br>
+<br>
+static void<br>
+ovirt_foreign_menu_init(OvirtForeignMenu *self)<br>
+{<br>
+ self->priv = OVIRT_FOREIGN_MENU_GET_PRIVATE(self);<br>
+}<br>
+<br>
+<br>
+OvirtForeignMenu* ovirt_foreign_menu_new(OvirtProxy *proxy)<br>
+{<br>
+ return g_object_new(OVIRT_TYPE_FOREIGN_MENU,<br>
+ "proxy", proxy,<br>
+ NULL);<br>
+}<br>
+<br>
+<br>
+static void<br>
+ovirt_foreign_menu_next_async_step(OvirtForeignMenu *menu,<br>
+ OvirtForeignMenuState current_state)<br>
+{<br>
+ current_state++;<br></blockquote><div><br></div><div>I would add a few g_return_if_fail() check about current_state values.<br> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+ if (current_state == STATE_STORAGE_DOMAIN) {<br>
+ if (menu->priv->files == NULL) {<br>
+ ovirt_foreign_menu_fetch_storage_domain_async(menu);<br>
+ } else {<br>
+ current_state++;<br>
+ }<br>
+ }<br>
+<br>
+ if (current_state == STATE_VM_CDROM) {<br>
+ if (menu->priv->cdrom == NULL) {<br>
+ ovirt_foreign_menu_fetch_vm_cdrom_async(menu);<br>
+ } else {<br>
+ current_state++;<br>
+ }<br>
+ }<br>
+<br>
+ if (current_state == STATE_ISOS) {<br>
+ g_warn_if_fail(menu->priv->api != NULL);<br>
+ g_warn_if_fail(menu->priv->vm != NULL);<br>
+ g_warn_if_fail(menu->priv->files != NULL);<br>
+ g_warn_if_fail(menu->priv->cdrom != NULL);<br>
+<br>
+ ovirt_foreign_menu_refresh_iso_list(menu);<br>
+ }<br>
+}<br>
+<br>
+<br>
+void<br>
+ovirt_foreign_menu_start(OvirtForeignMenu *menu)<br>
+{<br>
+ ovirt_foreign_menu_next_async_step(menu, STATE_0);<br></blockquote><div><br></div><div>Why not calling all the async simultaneously? If they need to be chained, isn't it simpler to do it through the normal code flow?<br>
<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+}<br>
+<br>
+<br>
+static void updated_cdrom_cb(GObject *source_object,<br>
+ GAsyncResult *result,<br>
+ G_GNUC_UNUSED gpointer user_data)<br>
+{<br>
+ GError *error = NULL;<br>
+ ovirt_cdrom_update_finish(OVIRT_CDROM(source_object),<br>
+ result, &error);<br>
+ g_debug("Finished updating cdrom content");<br>
+ if (error != NULL) {<br>
+ g_debug("Failed to update cdrom resource: %s", error->message);<br></blockquote><div><br>doesn't this deserve a warning? (same for similar errors)<br> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ g_clear_error(&error);<br>
+ }<br>
+}<br>
+<br>
+<br>
+static void<br>
+ovirt_foreign_menu_activate_item_cb(GtkMenuItem *menuitem, gpointer user_data)<br>
+{<br>
+ GList *children;<br>
+ GList *it;<br>
+ GtkWidget *menu;<br>
+ OvirtForeignMenu *foreign_menu;<br>
+<br>
+ foreign_menu = OVIRT_FOREIGN_MENU(user_data);<br>
+ if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) {<br>
+ return;<br>
+ }<br>
+<br>
+ menu = gtk_widget_get_parent(GTK_WIDGET(menuitem));<br>
+ g_debug("'%s' clicked", gtk_menu_item_get_label(menuitem));<br>
+ g_return_if_fail(GTK_IS_MENU(menu));<br>
+ /* Unselect all other menu items, we want a GtkRadioMenuItem-like<br>
+ * behaviour, but we need to allow to have no item set<br>
+ */<br>
+ children = gtk_container_get_children(GTK_CONTAINER(menu));<br>
+ for (it = children; it != NULL; it = it->next) {<br>
+ if (it->data != menuitem) {<br>
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(it->data), FALSE);<br>
+ }<br>
+ }<br>
+ g_list_free(children);<br>
+<br>
+ if (foreign_menu->priv->cdrom != NULL) {<br>
+ const char *iso_name;<br>
+<br>
+ iso_name = gtk_menu_item_get_label(menuitem);<br>
+ g_object_set(G_OBJECT(foreign_menu->priv->cdrom),<br>
+ "file", iso_name,<br>
+ NULL);<br>
+ g_debug("Updating VM cdrom image to '%s'", iso_name);<br>
+ ovirt_cdrom_update_async(foreign_menu->priv->cdrom, TRUE,<br>
+ foreign_menu->priv->proxy, NULL,<br>
+ updated_cdrom_cb, foreign_menu);<br>
+ }<br>
+}<br>
+<br>
+<br>
+static char *<br>
+ovirt_foreign_menu_get_current_iso_name(OvirtForeignMenu *foreign_menu)<br>
+{<br>
+ char *name;<br>
+<br>
+ if (foreign_menu->priv->cdrom == NULL) {<br>
+ return NULL;<br>
+ }<br>
+<br>
+ g_object_get(G_OBJECT(foreign_menu->priv->cdrom), "file", &name, NULL);<br></blockquote><div><br></div><div>g_object_get()/set() don't need explicit cast.<br> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ return name;<br>
+}<br>
+<br>
+<br>
+GtkWidget *ovirt_foreign_menu_get_gtk_menu(OvirtForeignMenu *foreign_menu)<br>
+{<br>
+ GtkWidget *gtk_menu;<br>
+ GList *it;<br>
+ char *current_iso;<br>
+<br>
+ g_debug("Creating GtkMenu for foreign menu");<br>
+ current_iso = ovirt_foreign_menu_get_current_iso_name(foreign_menu);<br></blockquote><div><br>Could be NULL,<br> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ gtk_menu = gtk_menu_new();<br>
+ for (it = foreign_menu->priv->iso_names; it != NULL; it = it->next) {<br>
+ GtkWidget *menuitem;<br>
+<br>
+ menuitem = gtk_check_menu_item_new_with_label((char *)it->data);<br>
+ if (g_strcmp0((char *)it->data, current_iso) == 0) {<br></blockquote><div><br></div><div>why not use safer and clearer g_str_equal() ? (same all over)<br> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem),<br>
+ TRUE);<br>
+ }<br>
+ g_signal_connect(menuitem, "activate",<br>
+ G_CALLBACK(ovirt_foreign_menu_activate_item_cb),<br>
+ foreign_menu);<br>
+ gtk_menu_shell_append(GTK_MENU_SHELL(gtk_menu), menuitem);<br>
+ }<br>
+ g_free(current_iso);<br>
+<br>
+ return gtk_menu;<br>
+}<br>
+<br>
+<br>
+static void ovirt_foreign_menu_set_files(OvirtForeignMenu *menu,<br>
+ const GList *files)<br>
+{<br>
+ GList *sorted_files = NULL;<br>
+ const GList *it;<br>
+ GList *it2;<br>
+<br>
+ for (it = files; it != NULL; it = it->next) {<br>
+ char *name;<br>
+ g_object_get(G_OBJECT(it->data), "name", &name, NULL);<br>
+ /* The oVirt REST API is supposed to have a 'type' node<br>
+ * associated with file resources , but as of 3.2, this node<br>
+ * is not present, so we do an extension check instead<br>
+ * to differentiate between ISOs and floppy images */<br>
+ if (g_str_has_suffix(name, ".vfd")) {<br>
+ g_free(name);<br>
+ continue;<br>
+ }<br>
+ sorted_files = g_list_insert_sorted(sorted_files, name,<br>
+ (GCompareFunc)g_strcmp0);<br>
+ }<br>
+<br>
+ for (it = sorted_files, it2 = menu->priv->iso_names;<br>
+ (it != NULL) && (it2 != NULL);<br></blockquote><div><br></div><div>nitpick those extra parentheses aren't needed<br> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ it = it->next, it2 = it2->next) {<br>
+ if (g_strcmp0(it->data, it2->data) != 0) {<br>
+ break;<br>
+ }<br>
+ }<br>
+<br>
+ if ((it == NULL) && (it2 == NULL)) {<br>
+ /* sorted_files and menu->priv->files content was the same */<br>
+ g_list_free_full(sorted_files, (GDestroyNotify)g_free);<br>
+ return;<br>
+ }<br>
+<br>
+ g_list_free_full(menu->priv->iso_names, (GDestroyNotify)g_free);<br>
+ menu->priv->iso_names = sorted_files;<br>
+ g_object_notify(G_OBJECT(menu), "files");<br>
+}<br>
+<br>
+<br>
+static void cdroms_fetched_cb(GObject *source_object,<br>
+ GAsyncResult *result,<br>
+ gpointer user_data)<br>
+{<br>
+ GHashTable *cdroms;<br>
+ OvirtCollection *cdrom_collection = OVIRT_COLLECTION(source_object);<br>
+ OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(user_data);<br>
+ GList *cdrom_list;<br>
+ GError *error = NULL;<br>
+<br>
+ ovirt_collection_fetch_finish(cdrom_collection, result, &error);<br>
+ if (error != NULL) {<br>
+ g_debug("Failed to fetch cdrom collection: %s", error->message);<br>
+ g_clear_error(&error);<br>
+ return;<br>
+ }<br>
+<br>
+ cdroms = ovirt_collection_get_resources(cdrom_collection);<br>
+<br>
+ g_warn_if_fail(g_hash_table_size(cdroms) <= 1);<br>
+<br>
+ cdrom_list = g_hash_table_get_values(cdroms);<br>
+ if (cdrom_list != NULL) {<br>
+ OvirtCdrom *cdrom;<br>
+<br>
+ cdrom = OVIRT_CDROM(cdrom_list->data);<br>
+ if (menu->priv->cdrom != NULL) {<br>
+ g_object_unref(G_OBJECT(menu->priv->cdrom));<br>
+ }<br>
+<br>
+ menu->priv->cdrom = g_object_ref(G_OBJECT(cdrom));<br>
+ g_debug("Set VM cdrom to %p", menu->priv->cdrom);<br>
+ }<br>
+ g_list_free(cdrom_list);<br>
+<br>
+ if (menu->priv->cdrom != NULL) {<br>
+ ovirt_foreign_menu_next_async_step(menu, STATE_VM_CDROM);<br>
+ } else {<br>
+ g_debug("Could not find VM cdrom through oVirt REST API");<br>
+ }<br>
+}<br>
+<br>
+<br>
+static void ovirt_foreign_menu_fetch_vm_cdrom_async(OvirtForeignMenu *menu)<br>
+{<br>
+ OvirtCollection *cdrom_collection;<br>
+<br>
+ cdrom_collection = ovirt_vm_get_cdroms(menu->priv->vm);<br>
+ ovirt_collection_fetch_async(cdrom_collection, menu->priv->proxy, NULL,<br>
+ cdroms_fetched_cb, menu);<br>
+ g_object_unref(G_OBJECT(cdrom_collection));<br>
+}<br>
+<br>
+<br>
+static void storage_domains_fetched_cb(GObject *source_object,<br>
+ GAsyncResult *result,<br>
+ gpointer user_data)<br>
+{<br>
+ GError *error = NULL;<br>
+ OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(user_data);<br>
+ OvirtCollection *collection = OVIRT_COLLECTION(source_object);<br>
+ GList *storage_domains;<br>
+ GList *it;<br>
+<br>
+ ovirt_collection_fetch_finish(collection, result, &error);<br>
+ if (error != NULL) {<br>
+ g_debug("failed to fetch storage domains: %s", error->message);<br>
+ g_clear_error(&error);<br>
+ return;<br>
+ }<br>
+<br>
+ storage_domains = g_hash_table_get_values(ovirt_collection_get_resources(collection));<br>
+ for (it = storage_domains; it != NULL; it = it->next) {<br>
+ OvirtStorageDomain *domain;<br>
+ OvirtCollection *file_collection;<br>
+ char *name;<br>
+ int type;<br>
+<br>
+ domain = OVIRT_STORAGE_DOMAIN(it->data);<br>
+ g_object_get(G_OBJECT(domain), "type", &type, "name", &name, NULL);<br>
+ g_free(name);<br>
+<br>
+ if (type != OVIRT_STORAGE_DOMAIN_TYPE_ISO) {<br>
+ continue;<br>
+ }<br>
+<br>
+ file_collection = ovirt_storage_domain_get_files(domain);<br>
+ if (file_collection != NULL) {<br>
+ if (menu->priv->files) {<br>
+ g_object_unref(G_OBJECT(menu->priv->files));<br>
+ }<br>
+ menu->priv->files = g_object_ref(G_OBJECT(file_collection));<br>
+ g_debug("Set VM files to %p", menu->priv->files);<br>
+ break;<br>
+ }<br>
+ }<br>
+ g_list_free(storage_domains);<br>
+<br>
+ if (menu->priv->files != NULL) {<br>
+ ovirt_foreign_menu_next_async_step(menu, STATE_STORAGE_DOMAIN);<br>
+ } else {<br>
+ g_debug("Could not find iso file collection");<br>
+ }<br>
+}<br>
+<br>
+<br>
+static void ovirt_foreign_menu_fetch_storage_domain_async(OvirtForeignMenu *menu)<br>
+{<br>
+ OvirtCollection *collection;<br>
+<br>
+ g_debug("Start fetching oVirt REST collection");<br>
+ collection = ovirt_api_get_storage_domains(menu->priv->api);<br>
+ ovirt_collection_fetch_async(collection, menu->priv->proxy, NULL,<br>
+ storage_domains_fetched_cb, menu);<br>
+ g_object_unref(G_OBJECT(collection));<br>
+}<br>
+<br>
+<br>
+static void iso_list_fetched_cb(GObject *source_object,<br>
+ GAsyncResult *result,<br>
+ gpointer user_data)<br>
+{<br>
+ OvirtCollection *collection = OVIRT_COLLECTION(source_object);<br>
+ GList *files;<br>
+ GError *error = NULL;<br>
+<br>
+ ovirt_collection_fetch_finish(collection, result, &error);<br>
+ files = g_hash_table_get_values(ovirt_collection_get_resources(collection));<br>
+ if (error != NULL) {<br>
+ g_debug("failed to fetch files for ISO storage domain: %s",<br>
+ error->message);<br>
+ g_clear_error(&error);<br>
+ return;<br>
+ } else {<br>
+ ovirt_foreign_menu_set_files(OVIRT_FOREIGN_MENU(user_data), files);<br>
+ }<br>
+ g_list_free(files);<br>
+<br>
+ g_timeout_add_seconds(15, ovirt_foreign_menu_refresh_iso_list, user_data);<br></blockquote><div><br></div><div>Depending on the load of the server, this could be quite heavy. Is this the recommended value by ovirt folks?<br>
<br> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+}<br>
+<br>
+<br>
+static void ovirt_foreign_menu_fetch_iso_list_async(OvirtForeignMenu *menu)<br>
+{<br>
+ if (menu->priv->files == NULL) {<br>
+ return;<br>
+ }<br>
+<br>
+ ovirt_collection_fetch_async(menu->priv->files, menu->priv->proxy,<br>
+ NULL, iso_list_fetched_cb, menu);<br>
+}<br>
+<br>
+<br>
+static gboolean ovirt_foreign_menu_refresh_iso_list(gpointer user_data)<br>
+{<br>
+ OvirtForeignMenu *menu;<br>
+<br>
+ g_debug("Refreshing foreign menu iso list");<br>
+ menu = OVIRT_FOREIGN_MENU(user_data);<br>
+ ovirt_foreign_menu_fetch_iso_list_async(menu);<br>
+<br>
+ /* ovirt_foreign_menu_fetch_iso_list() will program a new call to that<br>
+ * function when it has finished fetching the iso list<br>
+ */<br>
+ return G_SOURCE_REMOVE;<br>
+}<br>
diff --git a/src/ovirt-foreign-menu.h b/src/ovirt-foreign-menu.h<br>
new file mode 100644<br>
index 0000000..ffadd46<br>
--- /dev/null<br>
+++ b/src/ovirt-foreign-menu.h<br>
@@ -0,0 +1,82 @@<br>
+/*<br>
+ * Virt Viewer: A virtual machine console viewer<br>
+ *<br>
+ * Copyright (C) 2007-2013 Red Hat, Inc.<br>
+ * Copyright (C) 2009-2012 Daniel P. Berrange<br>
+ * Copyright (C) 2010 Marc-André Lureau<br>
+ *<br>
+ * This program is free software; you can redistribute it and/or modify<br>
+ * it under the terms of the GNU General Public License as published by<br>
+ * the Free Software Foundation; either version 2 of the License, or<br>
+ * (at your option) any later version.<br>
+ *<br>
+ * This program is distributed in the hope that it will be useful,<br>
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>
+ * GNU General Public License for more details.<br>
+ *<br>
+ * You should have received a copy of the GNU General Public License<br>
+ * along with this program; if not, write to the Free Software<br>
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA<br>
+ *<br>
+ * Author: Daniel P. Berrange <<a href="mailto:berrange@redhat.com">berrange@redhat.com</a>><br>
+ * Christophe Fergeau <<a href="mailto:cfergeau@redhat.com">cfergeau@redhat.com</a>><br>
+ */<br>
+#ifndef _OVIRT_FOREIGN_MENU_H<br>
+#define _OVIRT_FOREIGN_MENU_H<br>
+<br>
+#include <glib-object.h><br>
+#include <govirt/govirt.h><br>
+#include <gtk/gtk.h><br>
+<br>
+<br>
+G_BEGIN_DECLS<br>
+<br>
+#define OVIRT_TYPE_FOREIGN_MENU ovirt_foreign_menu_get_type()<br>
+<br>
+#define OVIRT_FOREIGN_MENU(obj) \<br>
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), OVIRT_TYPE_FOREIGN_MENU, OvirtForeignMenu))<br>
+<br>
+#define OVIRT_FOREIGN_MENU_CLASS(klass) \<br>
+ (G_TYPE_CHECK_CLASS_CAST ((klass), OVIRT_TYPE_FOREIGN_MENU, OvirtForeignMenuClass))<br>
+<br>
+#define OVIRT_IS_FOREIGN_MENU(obj) \<br>
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OVIRT_TYPE_FOREIGN_MENU))<br>
+<br>
+#define OVIRTIS_FOREIGN_MENU_CLASS(klass) \<br>
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), OVIRT_TYPE_FOREIGN_MENU))<br>
+<br>
+#define OVIRT_FOREIGN_MENU_GET_CLASS(obj) \<br>
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), OVIRT_TYPE_FOREIGN_MENU, OvirtForeignMenuClass))<br>
+<br>
+typedef struct _OvirtForeignMenu OvirtForeignMenu;<br>
+typedef struct _OvirtForeignMenuClass OvirtForeignMenuClass;<br>
+typedef struct _OvirtForeignMenuPrivate OvirtForeignMenuPrivate;<br>
+<br>
+struct _OvirtForeignMenu {<br>
+ GObject parent;<br>
+<br>
+ OvirtForeignMenuPrivate *priv;<br>
+};<br>
+<br>
+struct _OvirtForeignMenuClass {<br>
+ GObjectClass parent_class;<br>
+};<br>
+<br>
+GType ovirt_foreign_menu_get_type(void);<br>
+<br>
+OvirtForeignMenu* ovirt_foreign_menu_new(OvirtProxy *proxy);<br>
+void ovirt_foreign_menu_start(OvirtForeignMenu *menu);<br>
+<br>
+GtkWidget *ovirt_foreign_menu_get_gtk_menu(OvirtForeignMenu *foreign_menu);<br>
+<br>
+G_END_DECLS<br>
+<br>
+#endif /* _OVIRT_FOREIGN_MENU_H */<br>
+/*<br>
+ * Local variables:<br>
+ * c-indent-level: 4<br>
+ * c-basic-offset: 4<br>
+ * indent-tabs-mode: nil<br>
+ * End:<br>
+ */<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.9.0<br>
<br>
_______________________________________________<br>
virt-tools-list mailing list<br>
<a href="mailto:virt-tools-list@redhat.com">virt-tools-list@redhat.com</a><br>
<a href="https://www.redhat.com/mailman/listinfo/virt-tools-list" target="_blank">https://www.redhat.com/mailman/listinfo/virt-tools-list</a></font></span></blockquote></div><br><br clear="all"><br>-- <br>Marc-André Lureau
</div></div>