Generate progress messages during launch.
authorRichard W.M. Jones <rjones@redhat.com>
Fri, 1 Apr 2011 12:30:48 +0000 (13:30 +0100)
committerRichard W.M. Jones <rjones@redhat.com>
Fri, 1 Apr 2011 15:05:30 +0000 (16:05 +0100)
This commit generates approximate progress messages during the
guestfs_launch call.  Currently this code generates:

   0 / 12: launch clock starts
   3 / 12: appliance created
   6 / 12: detected that guest kernel started
   9 / 12: detected that /init script is running
  12 / 12: launch completed successfully

(Note this is not an ABI and may be changed or removed in a future
version).

Progress messages are only generated at all if 5 seconds have elapsed
since the launch, and they are only generated for the ordinary
appliance (not if using attach-method to attach to an existing virtio
serial port).

generator/generator_actions.ml
src/guestfs-internal.h
src/launch.c
src/proto.c

index 75b1cb3..a324d99 100644 (file)
@@ -103,7 +103,7 @@ You probably don't want to call this function.")]
  *)
 
 let non_daemon_functions = test_functions @ [
-  ("launch", (RErr, [], []), -1, [FishAlias "run"],
+  ("launch", (RErr, [], []), -1, [FishAlias "run"; Progress],
    [],
    "launch the qemu subprocess",
    "\
index 2729097..3a63f2e 100644 (file)
@@ -302,6 +302,7 @@ extern int guestfs___recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **
 extern int guestfs___accept_from_daemon (guestfs_h *g);
 extern void guestfs___progress_message_callback (guestfs_h *g, const struct guestfs_progress *message);
 extern int guestfs___build_appliance (guestfs_h *g, char **kernel, char **initrd, char **appliance);
+extern void guestfs___launch_send_progress (guestfs_h *g, int perdozen);
 extern void guestfs___print_BufferIn (FILE *out, const char *buf, size_t buf_size);
 extern void guestfs___print_BufferOut (FILE *out, const char *buf, size_t buf_size);
 #ifdef HAVE_PCRE
index 367d3ff..a60ef7b 100644 (file)
@@ -407,12 +407,15 @@ launch_appliance (guestfs_h *g)
 
   /* Start the clock ... */
   gettimeofday (&g->launch_t, NULL);
+  guestfs___launch_send_progress (g, 0);
 
   /* Locate and/or build the appliance. */
   char *kernel = NULL, *initrd = NULL, *appliance = NULL;
   if (guestfs___build_appliance (g, &kernel, &initrd, &appliance) == -1)
     return -1;
 
+  guestfs___launch_send_progress (g, 3);
+
   if (g->verbose)
     guestfs___print_timestamped_message (g, "begin testing qemu features");
 
@@ -761,6 +764,8 @@ launch_appliance (guestfs_h *g)
     goto cleanup1;
   }
 
+  guestfs___launch_send_progress (g, 12);
+
   return 0;
 
  cleanup1:
@@ -862,6 +867,36 @@ connect_unix_socket (guestfs_h *g, const char *sockpath)
   return -1;
 }
 
+/* launch (of the ordinary appliance) generates approximate progress
+ * messages.  Currently these are defined as follows:
+ *
+ *    0 / 12: launch clock starts
+ *    3 / 12: appliance created
+ *    6 / 12: detected that guest kernel started
+ *    9 / 12: detected that /init script is running
+ *   12 / 12: launch completed successfully
+ *
+ * Notes:
+ * (1) This is not a documented ABI and the behaviour may be changed
+ * or removed in future.
+ * (2) Messages are only sent if more than 5 seconds has elapsed
+ * since the launch clock started.
+ * (3) There is a gross hack in proto.c to make this work.
+ */
+void
+guestfs___launch_send_progress (guestfs_h *g, int perdozen)
+{
+  struct timeval tv;
+
+  gettimeofday (&tv, NULL);
+  if (timeval_diff (&g->launch_t, &tv) >= 5000) {
+    guestfs_progress progress_message =
+      { .proc = 0, .serial = 0, .position = perdozen, .total = 12 };
+
+    guestfs___progress_message_callback (g, &progress_message);
+  }
+}
+
 /* Return the location of the tmpdir (eg. "/tmp") and allow users
  * to override it at runtime using $TMPDIR.
  * http://www.pathname.com/fhs/pub/fhs-2.3.html#TMPTEMPORARYFILES
index 7cd1d31..63aea68 100644 (file)
@@ -285,6 +285,24 @@ read_log_message_or_eof (guestfs_h *g, int fd, int error_if_eof)
   /* It's an actual log message, send it upwards if anyone is listening. */
   guestfs___call_callbacks_message (g, GUESTFS_EVENT_APPLIANCE, buf, n);
 
+  /* This is a gross hack.  See the comment above
+   * guestfs___launch_send_progress.
+   */
+  if (g->state == LAUNCHING) {
+    const char *sentinel;
+    size_t len;
+
+    sentinel = "Linux version"; /* kernel up */
+    len = strlen (sentinel);
+    if (memmem (buf, n, sentinel, len) != NULL)
+      guestfs___launch_send_progress (g, 6);
+
+    sentinel = "Starting /init script"; /* /init running */
+    len = strlen (sentinel);
+    if (memmem (buf, n, sentinel, len) != NULL)
+      guestfs___launch_send_progress (g, 9);
+  }
+
   return 0;
 }