ovirt-foreign-menu: Support changing ISO from Data StorageDomain
With the possibility of having ISO images in storage domains of DATA
type, we need to store the id of the object as well as its name. This is
not the case with ISO storage domains, which only hold the name of the
image. This patch makes it possible to use deal with both types
transparently for the user.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1835640
Signed-off-by: Eduardo Lima (Etrunko) <etrunko@redhat.com>
Eduardo Lima (Etrunko)
2 years ago
14 | 14 | #include <config.h> |
15 | 15 | |
16 | 16 | #include "glib-compat.h" |
17 | ||
18 | #if !GLIB_CHECK_VERSION(2,60,0) | |
19 | gboolean | |
20 | g_strv_equal (const gchar * const *strv1, | |
21 | const gchar * const *strv2) | |
22 | { | |
23 | g_return_val_if_fail (strv1 != NULL, FALSE); | |
24 | g_return_val_if_fail (strv2 != NULL, FALSE); | |
25 | ||
26 | if (strv1 == strv2) | |
27 | return TRUE; | |
28 | ||
29 | for (; *strv1 != NULL && *strv2 != NULL; strv1++, strv2++) | |
30 | { | |
31 | if (!g_str_equal (*strv1, *strv2)) | |
32 | return FALSE; | |
33 | } | |
34 | ||
35 | return (*strv1 == NULL && *strv2 == NULL); | |
36 | } | |
37 | #endif |
22 | 22 | #pragma once |
23 | 23 | |
24 | 24 | #include <glib.h> |
25 | ||
26 | #if !GLIB_CHECK_VERSION(2,60,0) | |
27 | gboolean g_strv_equal (const gchar * const *strv1, | |
28 | const gchar * const *strv2); | |
29 | #endif |
90 | 90 | /* The next 2 members are used when changing the ISO image shown in |
91 | 91 | * a VM */ |
92 | 92 | /* Name of the ISO which is currently used by the VM OvirtCdrom */ |
93 | char *current_iso_name; | |
93 | GStrv current_iso_info; | |
94 | 94 | /* Name of the ISO we are trying to insert in the VM OvirtCdrom */ |
95 | char *next_iso_name; | |
95 | GStrv next_iso_info; | |
96 | 96 | |
97 | 97 | GList *iso_names; |
98 | 98 | }; |
125 | 125 | return name; |
126 | 126 | } |
127 | 127 | |
128 | static GStrv | |
129 | iso_info_new(const gchar *name, const gchar *id) | |
130 | { | |
131 | GStrv info = g_new0(gchar *, 3); | |
132 | info[0] = g_strdup(name); | |
133 | info[1] = id != NULL ? g_strdup(id) : g_strdup(name); | |
134 | return info; | |
135 | } | |
136 | ||
137 | ||
138 | GStrv | |
139 | ovirt_foreign_menu_get_current_iso_info(OvirtForeignMenu *menu) | |
140 | { | |
141 | if (menu->cdrom == NULL) | |
142 | return NULL; | |
143 | ||
144 | return menu->current_iso_info; | |
145 | } | |
146 | ||
147 | static void | |
148 | ovirt_foreign_menu_set_current_iso_info(OvirtForeignMenu *menu, const gchar *name, const gchar *id) | |
149 | { | |
150 | GStrv info = NULL; | |
151 | ||
152 | g_debug("Setting current ISO to: name '%s', id '%s'", name, id); | |
153 | if (menu->cdrom == NULL) | |
154 | return; | |
155 | ||
156 | if (name != NULL) | |
157 | info = iso_info_new(name, id); | |
158 | ||
159 | g_strfreev(menu->current_iso_info); | |
160 | menu->current_iso_info = info; | |
161 | } | |
128 | 162 | |
129 | 163 | GList* |
130 | 164 | ovirt_foreign_menu_get_iso_names(OvirtForeignMenu *foreign_menu) |
220 | 254 | self->iso_names = NULL; |
221 | 255 | } |
222 | 256 | |
223 | g_clear_pointer(&self->current_iso_name, g_free); | |
224 | g_clear_pointer(&self->next_iso_name, g_free); | |
257 | g_clear_pointer(&self->current_iso_info, g_strfreev); | |
258 | g_clear_pointer(&self->next_iso_info, g_strfreev); | |
225 | 259 | |
226 | 260 | G_OBJECT_CLASS(ovirt_foreign_menu_parent_class)->dispose(obj); |
227 | 261 | } |
408 | 442 | updated = ovirt_cdrom_update_finish(OVIRT_CDROM(source_object), |
409 | 443 | result, &error); |
410 | 444 | if (updated) { |
411 | g_debug("Finished updating cdrom content: %s", foreign_menu->next_iso_name); | |
412 | g_free(foreign_menu->current_iso_name); | |
413 | foreign_menu->current_iso_name = foreign_menu->next_iso_name; | |
414 | foreign_menu->next_iso_name = NULL; | |
445 | g_debug("Finished updating cdrom content"); | |
446 | g_strfreev(foreign_menu->current_iso_info); | |
447 | foreign_menu->current_iso_info = foreign_menu->next_iso_info; | |
448 | foreign_menu->next_iso_info = NULL; | |
415 | 449 | g_task_return_boolean(task, TRUE); |
416 | 450 | goto end; |
417 | 451 | } |
418 | 452 | |
419 | 453 | /* Reset old state back as we were not successful in switching to |
420 | 454 | * the new ISO */ |
421 | g_debug("setting OvirtCdrom:file back to '%s'", | |
422 | foreign_menu->current_iso_name); | |
455 | g_debug("setting OvirtCdrom:file back"); | |
423 | 456 | g_object_set(foreign_menu->cdrom, "file", |
424 | foreign_menu->current_iso_name, NULL); | |
425 | g_clear_pointer(&foreign_menu->next_iso_name, g_free); | |
457 | foreign_menu->current_iso_info ? foreign_menu->current_iso_info[1] : NULL, | |
458 | NULL); | |
459 | g_clear_pointer(&foreign_menu->next_iso_info, g_strfreev); | |
426 | 460 | |
427 | 461 | if (error != NULL) { |
428 | 462 | g_warning("failed to update cdrom resource: %s", error->message); |
440 | 474 | |
441 | 475 | void ovirt_foreign_menu_set_current_iso_name_async(OvirtForeignMenu *foreign_menu, |
442 | 476 | const char *name, |
477 | const char *id, | |
443 | 478 | GCancellable *cancellable, |
444 | 479 | GAsyncReadyCallback callback, |
445 | 480 | gpointer user_data) |
447 | 482 | GTask *task; |
448 | 483 | |
449 | 484 | g_return_if_fail(foreign_menu->cdrom != NULL); |
450 | g_return_if_fail(foreign_menu->next_iso_name == NULL); | |
485 | g_return_if_fail(foreign_menu->next_iso_info == NULL); | |
451 | 486 | |
452 | 487 | if (name) { |
453 | 488 | g_debug("Updating VM cdrom image to '%s'", name); |
454 | foreign_menu->next_iso_name = g_strdup(name); | |
489 | foreign_menu->next_iso_info = iso_info_new(name, id); | |
455 | 490 | } else { |
456 | 491 | g_debug("Removing current cdrom image"); |
457 | foreign_menu->next_iso_name = NULL; | |
492 | foreign_menu->next_iso_info = NULL; | |
458 | 493 | } |
459 | 494 | |
460 | 495 | g_object_set(foreign_menu->cdrom, |
461 | "file", name, | |
496 | "file", id, | |
462 | 497 | NULL); |
463 | 498 | |
464 | 499 | task = g_task_new(foreign_menu, cancellable, callback, user_data); |
483 | 518 | GList *sorted_files = NULL; |
484 | 519 | const GList *it; |
485 | 520 | GList *it2; |
521 | gchar *current_iso_name = ovirt_foreign_menu_get_current_iso_name(menu); | |
486 | 522 | |
487 | 523 | for (it = files; it != NULL; it = it->next) { |
488 | char *name; | |
489 | g_object_get(it->data, "name", &name, NULL); | |
524 | char *name = NULL, *id = NULL; | |
525 | g_object_get(it->data, "name", &name, "guid", &id, NULL); | |
490 | 526 | |
491 | 527 | #ifdef HAVE_OVIRT_STORAGE_DOMAIN_GET_DISKS |
492 | 528 | if (OVIRT_IS_DISK(it->data)) { |
494 | 530 | g_object_get(it->data, "content-type", &content_type, NULL); |
495 | 531 | if (content_type != OVIRT_DISK_CONTENT_TYPE_ISO) { |
496 | 532 | g_debug("Ignoring %s disk which content-type is not ISO", name); |
497 | g_free(name); | |
498 | continue; | |
533 | goto loop_end; | |
499 | 534 | } |
500 | 535 | } |
501 | 536 | #endif |
506 | 541 | * to differentiate between ISOs and floppy images */ |
507 | 542 | if (!g_str_has_suffix(name, ".iso")) { |
508 | 543 | g_debug("Ignoring %s which does not have a .iso extension", name); |
509 | g_free(name); | |
510 | continue; | |
511 | } | |
512 | sorted_files = g_list_insert_sorted(sorted_files, name, | |
544 | goto loop_end; | |
545 | } | |
546 | ||
547 | g_debug("Adding ISO to the list: name '%s', id '%s'", name, id); | |
548 | sorted_files = g_list_insert_sorted(sorted_files, iso_info_new(name, id), | |
513 | 549 | (GCompareFunc)g_strcmp0); |
514 | } | |
550 | ||
551 | /* Check if info matches with current cdrom file */ | |
552 | if (current_iso_name != NULL && | |
553 | (g_strcmp0(current_iso_name, name) == 0 || | |
554 | g_strcmp0(current_iso_name, id) == 0)) { | |
555 | ovirt_foreign_menu_set_current_iso_info(menu, name, id); | |
556 | } | |
557 | ||
558 | loop_end: | |
559 | g_free(name); | |
560 | g_free(id); | |
561 | } | |
562 | ||
563 | g_free(current_iso_name); | |
515 | 564 | |
516 | 565 | for (it = sorted_files, it2 = menu->iso_names; |
517 | 566 | (it != NULL) && (it2 != NULL); |
523 | 572 | |
524 | 573 | if ((it == NULL) && (it2 == NULL)) { |
525 | 574 | /* sorted_files and menu->files content was the same */ |
526 | g_list_free_full(sorted_files, (GDestroyNotify)g_free); | |
575 | g_list_free_full(sorted_files, (GDestroyNotify)g_strfreev); | |
527 | 576 | return; |
528 | 577 | } |
529 | 578 | |
530 | g_list_free_full(menu->iso_names, (GDestroyNotify)g_free); | |
579 | g_list_free_full(menu->iso_names, (GDestroyNotify)g_strfreev); | |
531 | 580 | menu->iso_names = sorted_files; |
532 | 581 | } |
533 | 582 | |
550 | 599 | } |
551 | 600 | |
552 | 601 | /* Content of OvirtCdrom is now current */ |
553 | g_clear_pointer(&menu->current_iso_name, g_free); | |
554 | if (menu->cdrom != NULL) { | |
555 | g_object_get(G_OBJECT(menu->cdrom), | |
556 | "file", &menu->current_iso_name, | |
557 | NULL); | |
558 | } | |
559 | 602 | if (menu->cdrom != NULL) { |
560 | 603 | ovirt_foreign_menu_next_async_step(menu, task, STATE_CDROM_FILE); |
561 | 604 | } else { |
52 | 52 | |
53 | 53 | void ovirt_foreign_menu_set_current_iso_name_async(OvirtForeignMenu *foreign_menu, |
54 | 54 | const char *name, |
55 | const char *id, | |
55 | 56 | GCancellable *cancellable, |
56 | 57 | GAsyncReadyCallback callback, |
57 | 58 | gpointer user_data); |
63 | 64 | GtkWidget *ovirt_foreign_menu_get_gtk_menu(OvirtForeignMenu *foreign_menu); |
64 | 65 | gchar *ovirt_foreign_menu_get_current_iso_name(OvirtForeignMenu *menu); |
65 | 66 | GList *ovirt_foreign_menu_get_iso_names(OvirtForeignMenu *menu); |
66 | ||
67 | GStrv ovirt_foreign_menu_get_current_iso_info(OvirtForeignMenu *menu); |
21 | 21 | |
22 | 22 | #include <glib/gi18n.h> |
23 | 23 | |
24 | #include "glib-compat.h" | |
24 | 25 | #include "remote-viewer-iso-list-dialog.h" |
25 | 26 | #include "virt-viewer-util.h" |
26 | 27 | #include "ovirt-foreign-menu.h" |
47 | 48 | ISO_IS_ACTIVE = 0, |
48 | 49 | ISO_NAME, |
49 | 50 | FONT_WEIGHT, |
51 | ISO_ID, | |
50 | 52 | }; |
51 | 53 | |
52 | 54 | enum RemoteViewerISOListDialogProperties { |
113 | 115 | } |
114 | 116 | |
115 | 117 | static void |
116 | remote_viewer_iso_list_dialog_foreach(char *name, RemoteViewerISOListDialog *self) | |
117 | { | |
118 | gchar *current_iso = ovirt_foreign_menu_get_current_iso_name(self->foreign_menu); | |
119 | gboolean active = (g_strcmp0(current_iso, name) == 0); | |
118 | remote_viewer_iso_list_dialog_foreach(GStrv info, RemoteViewerISOListDialog *self) | |
119 | { | |
120 | GStrv current_iso = ovirt_foreign_menu_get_current_iso_info(self->foreign_menu); | |
121 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS | |
122 | gboolean active = (g_strv_equal((const gchar * const *) current_iso, | |
123 | (const gchar * const *) info) == TRUE); | |
124 | G_GNUC_END_IGNORE_DEPRECATIONS | |
120 | 125 | gint weight = active ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL; |
121 | 126 | GtkTreeIter iter; |
122 | 127 | |
123 | 128 | gtk_list_store_append(self->list_store, &iter); |
124 | 129 | gtk_list_store_set(self->list_store, &iter, |
125 | 130 | ISO_IS_ACTIVE, active, |
126 | ISO_NAME, name, | |
127 | FONT_WEIGHT, weight, -1); | |
131 | ISO_NAME, info[0], | |
132 | FONT_WEIGHT, weight, | |
133 | ISO_ID, info[1], | |
134 | -1); | |
128 | 135 | |
129 | 136 | if (active) { |
130 | 137 | GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(self->list_store), &iter); |
132 | 139 | gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(self->tree_view), path, NULL, TRUE, 0.5, 0.5); |
133 | 140 | gtk_tree_path_free(path); |
134 | 141 | } |
135 | ||
136 | g_free(current_iso); | |
137 | 142 | } |
138 | 143 | |
139 | 144 | static void |
214 | 219 | GtkTreePath *tree_path = gtk_tree_path_new_from_string(path); |
215 | 220 | GtkTreeIter iter; |
216 | 221 | gboolean active; |
217 | gchar *name; | |
222 | gchar *name, *id; | |
218 | 223 | |
219 | 224 | gtk_tree_view_set_cursor(GTK_TREE_VIEW(self->tree_view), tree_path, NULL, FALSE); |
220 | 225 | gtk_tree_model_get_iter(model, &iter, tree_path); |
221 | 226 | gtk_tree_model_get(model, &iter, |
222 | 227 | ISO_IS_ACTIVE, &active, |
223 | ISO_NAME, &name, -1); | |
228 | ISO_NAME, &name, | |
229 | ISO_ID, &id, | |
230 | -1); | |
224 | 231 | |
225 | 232 | gtk_dialog_set_response_sensitive(GTK_DIALOG(self), GTK_RESPONSE_NONE, FALSE); |
226 | 233 | gtk_widget_set_sensitive(self->tree_view, FALSE); |
227 | 234 | |
228 | 235 | self->cancellable = g_cancellable_new(); |
229 | ovirt_foreign_menu_set_current_iso_name_async(self->foreign_menu, active ? NULL : name, | |
236 | ovirt_foreign_menu_set_current_iso_name_async(self->foreign_menu, | |
237 | active ? NULL : name, | |
238 | active ? NULL : id, | |
230 | 239 | self->cancellable, |
231 | 240 | (GAsyncReadyCallback)ovirt_foreign_menu_iso_name_changed, |
232 | 241 | self); |
233 | 242 | gtk_tree_path_free(tree_path); |
234 | 243 | g_free(name); |
244 | g_free(id); | |
235 | 245 | } |
236 | 246 | |
237 | 247 | G_MODULE_EXPORT void |
300 | 310 | RemoteViewerISOListDialog *self) |
301 | 311 | { |
302 | 312 | GtkTreeModel *model = GTK_TREE_MODEL(self->list_store); |
303 | gchar *current_iso; | |
313 | GStrv current_iso; | |
304 | 314 | GtkTreeIter iter; |
305 | gchar *name; | |
315 | gchar *name, *id; | |
306 | 316 | gboolean active, match = FALSE; |
307 | 317 | GError *error = NULL; |
308 | 318 | |
323 | 333 | if (!gtk_tree_model_get_iter_first(model, &iter)) |
324 | 334 | goto end; |
325 | 335 | |
326 | current_iso = ovirt_foreign_menu_get_current_iso_name(foreign_menu); | |
336 | current_iso = ovirt_foreign_menu_get_current_iso_info(foreign_menu); | |
327 | 337 | |
328 | 338 | do { |
329 | 339 | gtk_tree_model_get(model, &iter, |
330 | 340 | ISO_IS_ACTIVE, &active, |
331 | ISO_NAME, &name, -1); | |
332 | match = (g_strcmp0(current_iso, name) == 0); | |
341 | ISO_NAME, &name, | |
342 | ISO_ID, &id, | |
343 | -1); | |
344 | ||
345 | if (current_iso) | |
346 | match = (g_strcmp0(current_iso[0], name) == 0 && | |
347 | g_strcmp0(current_iso[1], id) == 0); | |
333 | 348 | |
334 | 349 | /* iso is not active anymore */ |
335 | 350 | if (active && !match) { |
343 | 358 | } |
344 | 359 | |
345 | 360 | g_free(name); |
361 | g_free(id); | |
346 | 362 | } while (gtk_tree_model_iter_next(model, &iter)); |
347 | 363 | |
348 | 364 | gtk_dialog_set_response_sensitive(GTK_DIALOG(self), GTK_RESPONSE_NONE, TRUE); |
349 | 365 | gtk_widget_set_sensitive(self->tree_view, TRUE); |
350 | g_free(current_iso); | |
351 | 366 | |
352 | 367 | end: |
353 | 368 | g_clear_error(&error); |