1 /* libguestfs-test-tool
2 * Copyright (C) 2009 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #include <sys/types.h>
37 #define _(str) dgettext(PACKAGE, (str))
38 #define N_(str) dgettext(PACKAGE, (str))
44 #define STREQ(a,b) (strcmp((a),(b)) == 0)
45 #define STRCASEEQ(a,b) (strcasecmp((a),(b)) == 0)
46 #define STRNEQ(a,b) (strcmp((a),(b)) != 0)
47 #define STRCASENEQ(a,b) (strcasecmp((a),(b)) != 0)
48 #define STREQLEN(a,b,n) (strncmp((a),(b),(n)) == 0)
49 #define STRCASEEQLEN(a,b,n) (strncasecmp((a),(b),(n)) == 0)
50 #define STRNEQLEN(a,b,n) (strncmp((a),(b),(n)) != 0)
51 #define STRCASENEQLEN(a,b,n) (strncasecmp((a),(b),(n)) != 0)
52 #define STRPREFIX(a,b) (strncmp((a),(b),strlen((b))) == 0)
54 #define DEFAULT_TIMEOUT 120
56 static const char *helper = DEFAULT_HELPER;
57 static int timeout = DEFAULT_TIMEOUT;
58 static char tmpf[] = "/tmp/libguestfs-test-tool-sda-XXXXXX";
59 static char isof[] = "/tmp/libguestfs-test-tool-iso-XXXXXX";
62 static void preruncheck (void);
63 static void make_files (void);
64 static void set_qemu (const char *path, int use_wrapper);
69 printf (_("libguestfs-test-tool: interactive test tool\n"
70 "Copyright (C) 2009 Red Hat Inc.\n"
72 " libguestfs-test-tool [--options]\n"
74 " --help Display usage\n"
75 " --helper libguestfs-test-tool-helper\n"
76 " Helper program (default: %s)\n"
77 " --qemudir dir Specify QEMU source directory\n"
78 " --qemu qemu Specify QEMU binary\n"
80 " -t n Set launch timeout (default: %d seconds)\n"
82 DEFAULT_HELPER, DEFAULT_TIMEOUT);
86 main (int argc, char *argv[])
88 static const char *options = "t:?";
89 static const struct option long_options[] = {
90 { "help", 0, 0, '?' },
91 { "helper", 1, 0, 0 },
93 { "qemudir", 1, 0, 0 },
94 { "timeout", 1, 0, 't' },
99 extern char **environ;
101 struct guestfs_version *vers;
102 char *sfdisk_lines[] = { ",", NULL };
104 /* XXX This is wrong if the user renames the helper. */
105 char *helper_args[] = { "/iso/libguestfs-test-tool-helper", NULL };
108 c = getopt_long (argc, argv, options, long_options, &option_index);
112 case 0: /* options which are long only */
113 if (STREQ (long_options[option_index].name, "helper"))
115 else if (STREQ (long_options[option_index].name, "qemu"))
116 set_qemu (optarg, 0);
117 else if (STREQ (long_options[option_index].name, "qemudir"))
118 set_qemu (optarg, 1);
121 _("libguestfs-test-tool: unknown long option: %s (%d)\n"),
122 long_options[option_index].name, option_index);
128 if (sscanf (optarg, "%d", &timeout) != 1 || timeout < 0) {
130 _("libguestfs-test-tool: invalid timeout: %s\n"),
142 _("libguestfs-test-tool: unexpected command line option 0x%x\n"),
151 printf ("===== Test starts here =====\n");
153 /* Must set LIBGUESTFS_DEBUG=1 */
154 setenv ("LIBGUESTFS_DEBUG", "1", 1);
156 /* Print out any environment variables which may relate to this test. */
157 for (i = 0; environ[i] != NULL; ++i)
158 if (STREQLEN (environ[i], "LIBGUESTFS_", 11))
159 printf ("%s\n", environ[i]);
161 /* Create the handle and configure it. */
162 g = guestfs_create ();
165 _("libguestfs-test-tool: failed to create libguestfs handle\n"));
168 if (guestfs_add_drive (g, tmpf) == -1) {
170 _("libguestfs-test-tool: failed to add drive '%s'\n"),
174 if (guestfs_add_drive (g, isof) == -1) {
176 _("libguestfs-test-tool: failed to add drive '%s'\n"),
181 /* Print any version info etc. */
182 vers = guestfs_version (g);
184 fprintf (stderr, _("libguestfs-test-tool: guestfs_version failed\n"));
187 printf ("library version: %"PRIi64".%"PRIi64".%"PRIi64"%s\n",
188 vers->major, vers->minor, vers->release, vers->extra);
189 guestfs_free_version (vers);
191 printf ("guestfs_get_append: %s\n", guestfs_get_append (g) ? : "(null)");
192 printf ("guestfs_get_autosync: %d\n", guestfs_get_autosync (g));
193 printf ("guestfs_get_memsize: %d\n", guestfs_get_memsize (g));
194 printf ("guestfs_get_path: %s\n", guestfs_get_path (g));
195 printf ("guestfs_get_qemu: %s\n", guestfs_get_qemu (g));
196 printf ("guestfs_get_verbose: %d\n", guestfs_get_verbose (g));
198 /* Launch the guest handle. */
199 printf ("Launching appliance, timeout set to %d seconds.\n", timeout);
204 if (guestfs_launch (g) == -1) {
206 _("libguestfs-test-tool: failed to launch appliance\n"));
212 printf ("Guest launched OK.\n");
215 /* Create the filesystem and mount everything. */
216 if (guestfs_sfdiskM (g, "/dev/sda", sfdisk_lines) == -1) {
218 _("libguestfs-test-tool: failed to run sfdisk\n"));
222 if (guestfs_mkfs (g, "ext2", "/dev/sda1") == -1) {
224 _("libguestfs-test-tool: failed to mkfs.ext2\n"));
228 if (guestfs_mount (g, "/dev/sda1", "/") == -1) {
230 _("libguestfs-test-tool: failed to mount /dev/sda1 on /\n"));
234 if (guestfs_mkdir (g, "/iso") == -1) {
236 _("libguestfs-test-tool: failed to mkdir /iso\n"));
240 if (guestfs_mount (g, "/dev/sdb", "/iso") == -1) {
242 _("libguestfs-test-tool: failed to mount /dev/sdb on /iso\n"));
246 /* Let's now run some simple tests using the helper program. */
247 str = guestfs_command (g, helper_args);
250 _("libguestfs-test-tool: could not run helper program, or helper failed\n"));
255 printf ("===== TEST FINISHED OK =====\n");
259 static char qemuwrapper[] = "/tmp/libguestfs-test-tool-wrapper-XXXXXX";
262 cleanup_wrapper (void)
264 unlink (qemuwrapper);
267 /* Handle the --qemu and --qemudir parameters. use_wrapper is true
268 * in the --qemudir (source directory) case, where we have to create
269 * a wrapper shell script.
272 set_qemu (const char *path, int use_wrapper)
274 char buffer[PATH_MAX];
279 if (getenv ("LIBGUESTFS_QEMU")) {
281 _("LIBGUESTFS_QEMU environment variable is already set, so\n"
282 "--qemu/--qemudir options cannot be used.\n"));
287 if (access (path, X_OK) == -1) {
289 _("Binary '%s' does not exist or is not executable\n"),
294 setenv ("LIBGUESTFS_QEMU", path, 1);
298 /* This should be a source directory, so check it. */
299 snprintf (buffer, sizeof buffer, "%s/pc-bios", path);
300 if (stat (buffer, &statbuf) == -1 ||
301 !S_ISDIR (statbuf.st_mode)) {
303 _("%s: does not look like a qemu source directory\n"),
308 /* Make a wrapper script. */
309 fd = mkstemp (qemuwrapper);
311 perror (qemuwrapper);
317 fp = fdopen (fd, "w");
324 /* Select the right qemu binary for the wrapper script. */
326 fprintf (fp, "i386-softmmu/qemu");
328 fprintf (fp, host_cpu "-softmmu/qemu-system-" host_cpu);
331 fprintf (fp, " -L \"$qemudir\"/pc-bios \"$@\"\n");
335 setenv ("LIBGUESTFS_QEMU", qemuwrapper, 1);
336 atexit (cleanup_wrapper);
339 /* After getting the command line args, but before running
340 * anything, we check everything is in place to do the tests.
350 if (access (helper, R_OK) == -1) {
352 _("Test tool helper program 'libguestfs-test-tool-helper' is not\n"
353 "available. Expected to find it in '%s'\n"
355 "Use the --helper option to specify the location of this program.\n"),
360 snprintf (cmd, sizeof cmd, "file '%s'", helper);
361 fp = popen (cmd, "r");
366 r = fread (buffer, 1, sizeof buffer - 1, fp);
368 fprintf (stderr, _("command failed: %s"), cmd);
374 if (strstr (buffer, "statically linked") == NULL) {
376 _("Test tool helper program %s\n"
377 "is not statically linked. This is a build error when this test tool\n"
385 cleanup_tmpfiles (void)
397 /* Make the ISO which will contain the helper program. */
405 snprintf (cmd, sizeof cmd, "mkisofs -quiet -rJT -o '%s' '%s'",
408 if (r == -1 || WEXITSTATUS(r) != 0) {
410 _("mkisofs command failed: %s\n"), cmd);
414 /* Allocate the sparse file for /dev/sda. */
422 if (lseek (fd, 100 * 1024 * 1024 - 1, SEEK_SET) == -1) {
430 if (write (fd, "\0", 1) == -1) {
440 atexit (cleanup_tmpfiles); /* Removes tmpf and isof. */