Blob Blame History Raw
From 10d8b7f16ceeb9a43aff3d88544b075e58e336ab Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 5 May 2015 15:10:27 +0100
Subject: [PATCH] p2v: Warn if vcpus or memory would be larger than supported
 by RHEL (RHBZ#823758).

Display a warning if the number of vCPUs or memory selected in the GUI
would be larger than the limits currently supported on RHEL 6 and RHEL 7.

This is just a warning -- the user is free to ignore it and continue
anyway.

This warning does not apply if the selections were made through the
kernel command line, because there is no place to display the warning
for automated conversions.

(cherry picked from commit 1189d5919e4b3edceaa6a58b914ae29123754074)
---
 p2v/gui.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 113 insertions(+), 2 deletions(-)

diff --git a/p2v/gui.c b/p2v/gui.c
index 8a5cda1..f32ac53 100644
--- a/p2v/gui.c
+++ b/p2v/gui.c
@@ -20,6 +20,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdarg.h>
 #include <string.h>
 #include <inttypes.h>
 #include <unistd.h>
@@ -58,6 +59,7 @@ static GtkWidget *conn_dlg,
 /* The conversion dialog. */
 static GtkWidget *conv_dlg,
   *guestname_entry, *vcpus_entry, *memory_entry,
+  *vcpus_warning, *memory_warning, *target_warning_label,
   *o_combo, *oc_entry, *os_entry, *of_entry, *oa_combo,
   *info_label,
   *debug_button,
@@ -374,6 +376,7 @@ static void set_removable_from_ui (struct config *);
 static void set_interfaces_from_ui (struct config *);
 static void conversion_back_clicked (GtkWidget *w, gpointer data);
 static void start_conversion_clicked (GtkWidget *w, gpointer data);
+static void vcpus_or_memory_check_callback (GtkWidget *w, gpointer data);
 static void notify_ui_callback (int type, const char *data);
 static int get_vcpus_from_conv_dlg (void);
 static uint64_t get_memory_from_conv_dlg (void);
@@ -421,7 +424,7 @@ create_conversion_dialog (struct config *config)
   /* XXX It would be nice not to have to set this explicitly, but
    * if we don't then Gtk chooses a very small window.
    */
-  gtk_widget_set_size_request (conv_dlg, 800, 500);
+  gtk_widget_set_size_request (conv_dlg, 800, 560);
 
   /* The main dialog area. */
   hbox = gtk_hbox_new (TRUE, 1);
@@ -434,7 +437,7 @@ create_conversion_dialog (struct config *config)
 
   target_vbox = gtk_vbox_new (FALSE, 1);
 
-  target_tbl = gtk_table_new (3, 2, FALSE);
+  target_tbl = gtk_table_new (3, 3, FALSE);
   guestname_label = gtk_label_new (_("Name:"));
   gtk_misc_set_alignment (GTK_MISC (guestname_label), 1., 0.5);
   gtk_table_attach (GTK_TABLE (target_tbl), guestname_label,
@@ -454,6 +457,10 @@ create_conversion_dialog (struct config *config)
   gtk_entry_set_text (GTK_ENTRY (vcpus_entry), vcpus_str);
   gtk_table_attach (GTK_TABLE (target_tbl), vcpus_entry,
                     1, 2, 1, 2, GTK_FILL, GTK_FILL, 1, 1);
+  vcpus_warning = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
+                                            GTK_ICON_SIZE_BUTTON);
+  gtk_table_attach (GTK_TABLE (target_tbl), vcpus_warning,
+                    2, 3, 1, 2, 0, 0, 1, 1);
 
   memory_label = gtk_label_new (_("Memory (MB):"));
   gtk_misc_set_alignment (GTK_MISC (memory_label), 1., 0.5);
@@ -465,8 +472,20 @@ create_conversion_dialog (struct config *config)
   gtk_entry_set_text (GTK_ENTRY (memory_entry), memory_str);
   gtk_table_attach (GTK_TABLE (target_tbl), memory_entry,
                     1, 2, 2, 3, GTK_FILL, GTK_FILL, 1, 1);
+  memory_warning = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
+                                             GTK_ICON_SIZE_BUTTON);
+  gtk_table_attach (GTK_TABLE (target_tbl), memory_warning,
+                    2, 3, 2, 3, 0, 0, 1, 1);
 
   gtk_box_pack_start (GTK_BOX (target_vbox), target_tbl, TRUE, TRUE, 0);
+
+  target_warning_label = gtk_label_new ("");
+  gtk_label_set_line_wrap (GTK_LABEL (target_warning_label), TRUE);
+  gtk_label_set_line_wrap_mode (GTK_LABEL (target_warning_label),
+                                GTK_WRAP_WORD);
+  gtk_widget_set_size_request (target_warning_label, -1, 7 * 16);
+  gtk_box_pack_end (GTK_BOX (target_vbox), target_warning_label, TRUE, TRUE, 0);
+
   gtk_container_add (GTK_CONTAINER (target_frame), target_vbox);
 
   output_frame = gtk_frame_new (_("Virt-v2v output options"));
@@ -619,6 +638,10 @@ create_conversion_dialog (struct config *config)
                     G_CALLBACK (conversion_back_clicked), NULL);
   g_signal_connect (G_OBJECT (start_button), "clicked",
                     G_CALLBACK (start_conversion_clicked), config);
+  g_signal_connect (G_OBJECT (vcpus_entry), "changed",
+                    G_CALLBACK (vcpus_or_memory_check_callback), NULL);
+  g_signal_connect (G_OBJECT (memory_entry), "changed",
+                    G_CALLBACK (vcpus_or_memory_check_callback), NULL);
 }
 
 static void
@@ -630,6 +653,8 @@ show_conversion_dialog (void)
 
   /* Show the conversion dialog. */
   gtk_widget_show_all (conv_dlg);
+  gtk_widget_hide (vcpus_warning);
+  gtk_widget_hide (memory_warning);
 
   /* output_drivers may have been updated, so repopulate o_combo. */
   repopulate_output_combo (NULL);
@@ -1053,6 +1078,92 @@ conversion_back_clicked (GtkWidget *w, gpointer data)
   gtk_widget_set_sensitive (next_button, FALSE);
 }
 
+/* Display a warning if the vCPUs or memory is outside the supported
+ * range.  (RHBZ#823758).  See also:
+ * https://access.redhat.com/articles/rhel-kvm-limits
+ */
+#define MAX_SUPPORTED_VCPUS 160
+#define MAX_SUPPORTED_MEMORY_MB (UINT64_C (4000 * 1024))
+
+static char *concat_warning (char *warning, const char *fs, ...)
+  __attribute__((format (printf,2,3)));
+
+static char *
+concat_warning (char *warning, const char *fs, ...)
+{
+  va_list args;
+  char *msg;
+  size_t len, len2;
+  int r;
+
+  if (warning == NULL) {
+    warning = strdup ("");
+    if (warning == NULL) {
+    malloc_fail:
+      perror ("malloc");
+      exit (EXIT_FAILURE);
+    }
+  }
+
+  len = strlen (warning);
+  if (len > 0 && warning[len-1] != '\n' && fs[0] != '\n') {
+    warning = concat_warning (warning, "\n");
+    len = strlen (warning);
+  }
+
+  va_start (args, fs);
+  r = vasprintf (&msg, fs, args);
+  va_end (args);
+  if (r == -1) goto malloc_fail;
+
+  len2 = strlen (msg);
+  warning = realloc (warning, len + len2 + 1);
+  if (warning == NULL) goto malloc_fail;
+  memcpy (&warning[len], msg, len2 + 1);
+  free (msg);
+
+  return warning;
+}
+
+static void
+vcpus_or_memory_check_callback (GtkWidget *w, gpointer data)
+{
+  int vcpus;
+  uint64_t memory;
+  CLEANUP_FREE char *warning = NULL;
+
+  vcpus = get_vcpus_from_conv_dlg ();
+  memory = get_memory_from_conv_dlg ();
+
+  if (vcpus > MAX_SUPPORTED_VCPUS) {
+    gtk_widget_show (vcpus_warning);
+
+    warning = concat_warning (warning,
+                              _("Number of virtual CPUs is larger than what is supported for KVM (max: %d)."),
+                              MAX_SUPPORTED_VCPUS);
+  }
+  else
+    gtk_widget_hide (vcpus_warning);
+
+  if (memory > MAX_SUPPORTED_MEMORY_MB * 1024 * 1024) {
+    gtk_widget_show (memory_warning);
+
+    warning = concat_warning (warning,
+                              _("Memory size is larger than what is supported for KVM (max: %" PRIu64 ")."),
+                              MAX_SUPPORTED_MEMORY_MB);
+  }
+  else
+    gtk_widget_hide (memory_warning);
+
+  if (warning != NULL) {
+    warning = concat_warning (warning,
+                              _("If you ignore this warning, conversion can still succeed, but the guest may not work or may not be supported on the target."));
+    gtk_label_set_text (GTK_LABEL (target_warning_label), warning);
+  }
+  else
+    gtk_label_set_text (GTK_LABEL (target_warning_label), "");
+}
+
 static int
 get_vcpus_from_conv_dlg (void)
 {
-- 
1.8.3.1