[Pkg-libvirt-commits] [libguestfs] 20/266: tests: Add test program to run qemu/appliance repeatedly.

Hilko Bengen bengen at moszumanska.debian.org
Fri Oct 3 14:41:32 UTC 2014


This is an automated email from the git hooks/post-receive script.

bengen pushed a commit to annotated tag debian/1%1.27.35-1
in repository libguestfs.

commit de5924a2294a6aeb09e4b41b55f06d2f3ea5e0ec
Author: Richard W.M. Jones <rjones at redhat.com>
Date:   Thu Jul 17 20:32:24 2014 +0000

    tests: Add test program to run qemu/appliance repeatedly.
    
    For example:
    
      $ time ./run ./tests/qemu/qemu-boot -n 100
      real 1m19.794s
      user 0m10.001s
      sys  0m5.928s
    
    will run 100 appliance start/stops, from multiple threads.
---
 .gitignore             |   1 +
 tests/qemu/Makefile.am |  27 ++++-
 tests/qemu/qemu-boot.c | 270 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 297 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore
index e9170f4..5c614d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -529,6 +529,7 @@ Makefile.in
 /tests/mountable/test-internal-parse-mountable
 /tests/parallel/test-parallel
 /tests/protocol/test-error-messages
+/tests/qemu/qemu-boot
 /tests/regressions/rhbz501893
 /tests/regressions/rhbz790721
 /tests/regressions/rhbz914931
diff --git a/tests/qemu/Makefile.am b/tests/qemu/Makefile.am
index 40237ca..fa2fe92 100644
--- a/tests/qemu/Makefile.am
+++ b/tests/qemu/Makefile.am
@@ -29,4 +29,29 @@ TESTS = \
 TESTS_ENVIRONMENT = $(top_builddir)/run --test
 
 EXTRA_DIST = \
-	$(TESTS)
+	$(TESTS) \
+	qemu-boot.c
+
+# qemu-boot is built but not run by default as it is mainly
+# a qemu & kernel diagnostic tool.
+
+check_PROGRAMS = qemu-boot
+
+qemu_boot_SOURCES = \
+	../../df/estimate-max-threads.c \
+	../../df/estimate-max-threads.h \
+	qemu-boot.c
+qemu_boot_CPPFLAGS = \
+	-DGUESTFS_PRIVATE=1 \
+	-I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib \
+	-I$(top_srcdir)/src -I$(top_builddir)/src \
+	-I$(top_srcdir)/df
+qemu_boot_CFLAGS = \
+	-pthread \
+	$(WARN_CFLAGS) $(WERROR_CFLAGS)
+qemu_boot_LDADD = \
+	$(top_builddir)/src/libutils.la \
+	$(top_builddir)/src/libguestfs.la \
+	$(LIBXML2_LIBS) \
+	$(LIBVIRT_LIBS) \
+	$(top_builddir)/gnulib/lib/libgnu.la
diff --git a/tests/qemu/qemu-boot.c b/tests/qemu/qemu-boot.c
new file mode 100644
index 0000000..56eec57
--- /dev/null
+++ b/tests/qemu/qemu-boot.c
@@ -0,0 +1,270 @@
+/* libguestfs
+ * Copyright (C) 2014 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* Ancient libguestfs had a script called test-bootbootboot which just
+ * booted up the appliance in a loop.  This was necessary back in the
+ * bad old days when qemu was not very reliable.  This is the
+ * spiritual successor of that script, designed to find bugs in
+ * aarch64 KVM.  You can control the number of boots that are done and
+ * the amount of parallelism.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <limits.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include "guestfs.h"
+#include "guestfs-internal-frontend.h"
+#include "estimate-max-threads.h"
+
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+/* Maximum number of threads we would ever run.  Note this should not
+ * be > 20, unless libvirt is modified to increase the maximum number
+ * of clients.  User can override this limit using -P.
+ */
+#define MAX_THREADS 12
+
+static size_t n;       /* Number of qemu processes to run in total. */
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static int ignore_errors = 0;
+static int trace = 0;
+static int verbose = 0;
+
+struct thread_data {
+  int thread_num;
+  int r;
+};
+
+static void *start_thread (void *thread_data_vp);
+
+static void
+usage (int exitcode)
+{
+  fprintf (stderr,
+           "qemu-boot: A program for repeatedly running the libguestfs appliance.\n"
+           "qemu-boot [-i] [-P <nr-threads>] -n <nr-appliances>\n"
+           "  -i     Ignore errors\n"
+           "  -P <n> Set number of parallel threads\n"
+           "           (default is based on the amount of free memory)\n"
+           "  -n <n> Set number of appliances to run before exiting\n"
+           "  -v     Verbose appliance\n"
+           "  -x     Enable libguestfs tracing\n");
+  exit (exitcode);
+}
+
+int
+main (int argc, char *argv[])
+{
+  enum { HELP_OPTION = CHAR_MAX + 1 };
+  static const char *options = "in:P:vx";
+  static const struct option long_options[] = {
+    { "help", 0, 0, HELP_OPTION },
+    { "ignore", 0, 0, 'i' },
+    { "number", 1, 0, 'n' },
+    { "processes", 1, 0, 'P' },
+    { "trace", 0, 0, 'x' },
+    { "verbose", 0, 0, 'v' },
+    { 0, 0, 0, 0 }
+  };
+  size_t P = 0, i, errors;
+  int c, option_index;
+  int err;
+  void *status;
+
+  for (;;) {
+    c = getopt_long (argc, argv, options, long_options, &option_index);
+    if (c == -1) break;
+
+    switch (c) {
+    case 0:
+      /* Options which are long only. */
+      fprintf (stderr, "%s: unknown long option: %s (%d)\n",
+               program_name, long_options[option_index].name, option_index);
+      exit (EXIT_FAILURE);
+
+    case 'i':
+      ignore_errors = 1;
+      break;
+
+    case 'n':
+      if (sscanf (optarg, "%zu", &n) != 1 || n == 0) {
+        fprintf (stderr, "%s: -n option not numeric and greater than 0\n",
+                 program_name);
+        exit (EXIT_FAILURE);
+      }
+      break;
+
+    case 'P':
+      if (sscanf (optarg, "%zu", &P) != 1) {
+        fprintf (stderr, "%s: -P option not numeric\n", program_name);
+        exit (EXIT_FAILURE);
+      }
+      break;
+
+    case 'v':
+      verbose = 1;
+      break;
+
+    case 'x':
+      trace = 1;
+      break;
+
+    case HELP_OPTION:
+      usage (EXIT_SUCCESS);
+
+    default:
+      usage (EXIT_FAILURE);
+    }
+  }
+
+  if (n == 0) {
+    fprintf (stderr,
+             "%s: must specify number of processes to run (-n option)\n",
+             program_name);
+    exit (EXIT_FAILURE);
+  }
+
+  /* Calculate the number of threads to use. */
+  if (P > 0)
+    P = MIN (n, P);
+  else
+    P = MIN (n, MIN (MAX_THREADS, estimate_max_threads ()));
+
+  /* Start the worker threads. */
+  struct thread_data thread_data[P];
+  pthread_t threads[P];
+
+  for (i = 0; i < P; ++i) {
+    thread_data[i].thread_num = i;
+    err = pthread_create (&threads[i], NULL, start_thread, &thread_data[i]);
+    if (err != 0) {
+      fprintf (stderr, "%s: pthread_create[%zu]: %s\n",
+               program_name, i, strerror (err));
+      exit (EXIT_FAILURE);
+    }
+  }
+
+  /* Wait for the threads to exit. */
+  errors = 0;
+  for (i = 0; i < P; ++i) {
+    err = pthread_join (threads[i], &status);
+    if (err != 0) {
+      fprintf (stderr, "%s: pthread_join[%zu]: %s\n",
+               program_name, i, strerror (err));
+      errors++;
+    }
+    if (*(int *)status == -1)
+      errors++;
+  }
+
+  exit (errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+/* Worker thread. */
+static void *
+start_thread (void *thread_data_vp)
+{
+  struct thread_data *thread_data = thread_data_vp;
+  int quit = 0;
+  int err;
+  size_t i;
+  guestfs_h *g;
+  unsigned errors = 0;
+
+  for (;;) {
+    /* Take the next process. */
+    err = pthread_mutex_lock (&mutex);
+    if (err != 0) {
+      fprintf (stderr, "%s: pthread_mutex_lock: %s",
+               program_name, strerror (err));
+      goto error;
+    }
+
+    i = n;
+    if (i > 0) {
+      printf ("%zu to go ...          \r", n);
+      fflush (stdout);
+
+      n--;
+    }
+    else
+      quit = 1;
+
+    err = pthread_mutex_unlock (&mutex);
+    if (err != 0) {
+      fprintf (stderr, "%s: pthread_mutex_unlock: %s",
+               program_name, strerror (err));
+      goto error;
+    }
+
+    if (quit)                   /* Work finished. */
+      break;
+
+    g = guestfs_create ();
+    if (g == NULL) {
+      perror ("guestfs_create");
+      errors++;
+      if (!ignore_errors)
+        goto error;
+    }
+
+    guestfs_set_trace (g, trace);
+    guestfs_set_verbose (g, verbose);
+
+    if (guestfs_add_drive_ro (g, "/dev/null") == -1) {
+      errors++;
+      if (!ignore_errors)
+        goto error;
+    }
+
+    if (guestfs_launch (g) == -1) {
+      errors++;
+      if (!ignore_errors)
+        goto error;
+    }
+
+    if (guestfs_shutdown (g) == -1) {
+      errors++;
+      if (!ignore_errors)
+        goto error;
+    }
+
+    guestfs_close (g);
+  }
+
+  if (errors > 0) {
+    fprintf (stderr, "%s: thread %d: %u errors were ignored\n",
+             program_name, thread_data->thread_num, errors);
+    goto error;
+  }
+
+  thread_data->r = 0;
+  return &thread_data->r;
+
+ error:
+  thread_data->r = -1;
+  return &thread_data->r;
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-libvirt/libguestfs.git



More information about the Pkg-libvirt-commits mailing list