Richard W.M. Jones
2014-Jan-28 16:24 UTC
[Libguestfs] [PATCH 00/10] New API: disk-create for creating blank disks.
A lot of code runs 'qemu-img create' or 'truncate' to create blank disk images. In the past I resisted adding an API to do this, since it essentially duplicates what you can already do using other tools (ie. qemu-img). However this does simplify calling code quite a lot since qemu-img is somewhat error-prone to use (eg: don't try to create a disk called "foo:bar") and it's generally hard to safely construct and run external commands from C. This is in preparation for finishing off the virt-make-fs rewrite (patch coming later). Rich.
Richard W.M. Jones
2014-Jan-28 16:24 UTC
[Libguestfs] [PATCH 01/10] src/Makefile.am: Reorder SOURCES into alphabetical order.
--- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index f5c8d2d..ba02061 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -87,8 +87,8 @@ libguestfs_la_SOURCES = \ alloc.c \ appliance.c \ bindtests.c \ - command.c \ canonical-name.c \ + command.c \ conn-socket.c \ dbdump.c \ drives.c \ -- 1.8.4.2
Richard W.M. Jones
2014-Jan-28 16:24 UTC
[Libguestfs] [PATCH 02/10] New API: disk-create for creating blank disks.
This is a wrapper around either 'qemu-img create' or calls to open,
truncate and posix_fallocate which litter and complicate existing
code.
---
Makefile.am | 1 +
configure.ac | 1 +
generator/actions.ml | 52 ++++++-
gobject/Makefile.inc | 2 +
po/POTFILES | 2 +
src/Makefile.am | 1 +
src/create.c | 319 +++++++++++++++++++++++++++++++++++++++
tests/create/Makefile.am | 27 ++++
tests/create/test-disk-create.sh | 48 ++++++
9 files changed, 451 insertions(+), 2 deletions(-)
create mode 100644 src/create.c
create mode 100644 tests/create/Makefile.am
create mode 100755 tests/create/test-disk-create.sh
diff --git a/Makefile.am b/Makefile.am
index e39d11f..5b8f109 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -39,6 +39,7 @@ SUBDIRS += tests/tmpdirs
SUBDIRS += tests/protocol
SUBDIRS += tests/events
SUBDIRS += tests/parallel
+SUBDIRS += tests/create
SUBDIRS += tests/disks
SUBDIRS += tests/mountable
SUBDIRS += tests/network
diff --git a/configure.ac b/configure.ac
index c07462e..df8e962 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1745,6 +1745,7 @@ AC_CONFIG_FILES([Makefile
tests/btrfs/Makefile
tests/c-api/Makefile
tests/charsets/Makefile
+ tests/create/Makefile
tests/data/Makefile
tests/disks/Makefile
tests/disks/test-qemu-drive-libvirt.xml
diff --git a/generator/actions.ml b/generator/actions.ml
index fa1a2c5..3637da0 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -3093,6 +3093,54 @@ Return the current backend settings.
See L<guestfs(3)/BACKEND>, L<guestfs(3)/BACKEND SETTINGS>." };
+ { defaults with
+ name = "disk_create";
+ style = RErr, [String "filename"; String "format";
Int64 "size"], [OString "backingfile"; OString
"backingformat"; OString "preallocation"; OString
"compat"; OInt "clustersize"];
+ test_excuse = "tests in tests/create subdirectory";
+ shortdesc = "create a blank disk image";
+ longdesc = "\
+Create a blank disk image called C<filename> (a host file or device)
+with format C<format> (usually C<raw> or C<qcow2>, but other
formats
+are possible). The size is C<size> bytes.
+
+If used with the optional C<backingfile> parameter, then a snapshot
+is created on top of the backing file. In this case, C<size> must
+be passed as C<-1>. The size of the snapshot is the same as the
+size of the backing file, which is discovered automatically. You
+are encouraged to also pass C<backingformat> to describe the format
+of C<backingfile>.
+
+The other optional parameters are:
+
+=over 4
+
+=item C<preallocation>
+
+If format is C<raw>, then this can be either C<sparse> or
C<full>
+to create a sparse or fully allocated file respectively. The default
+is C<sparse>.
+
+If format is C<qcow2>, then this can be either C<off> or
+C<metadata>. Preallocating metadata can be faster when doing lots
+of writes, but uses more space.
+
+=item C<compat>
+
+C<qcow2> only:
+Pass the string C<1.1> to use the advanced qcow2 format supported
+by qemu E<ge> 1.1.
+
+=item C<clustersize>
+
+C<qcow2> only:
+Change the qcow2 cluster size. The default is 65536 (bytes) and
+this settig may be any power of two between 512 and 2097152.
+
+=back
+
+Note that this call does not add the new disk to the handle. You
+may need to call C<guestfs_add_drive_opts> separately." };
+
]
(* daemon_functions are any functions which cause some action
@@ -11739,7 +11787,7 @@ let fish_commands = [
This creates an empty (zeroed) file of the given size, and then adds
so it can be further examined.
-For more advanced image creation, see L<qemu-img(1)> utility.
+For more advanced image creation, see L</disk-create>.
Size can be specified using standard suffixes, eg. C<1M>.
@@ -11983,7 +12031,7 @@ not assigned to the file until they are needed. Sparse
disk files
only use space when written to, but they are slower and there is a
danger you could run out of real disk space during a write operation.
-For more advanced image creation, see L<qemu-img(1)> utility.
+For more advanced image creation, see L</disk-create>.
Size can be specified using standard suffixes, eg. C<1M>.
diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc
index 7024754..7a8493a 100644
--- a/gobject/Makefile.inc
+++ b/gobject/Makefile.inc
@@ -52,6 +52,7 @@ guestfs_gobject_headers= \
include/guestfs-gobject/optargs-mount_local.h \
include/guestfs-gobject/optargs-umount_local.h \
include/guestfs-gobject/optargs-add_drive_scratch.h \
+ include/guestfs-gobject/optargs-disk_create.h \
include/guestfs-gobject/optargs-is_file.h \
include/guestfs-gobject/optargs-is_dir.h \
include/guestfs-gobject/optargs-umount.h \
@@ -127,6 +128,7 @@ guestfs_gobject_sources= \
src/optargs-mount_local.c \
src/optargs-umount_local.c \
src/optargs-add_drive_scratch.c \
+ src/optargs-disk_create.c \
src/optargs-is_file.c \
src/optargs-is_dir.c \
src/optargs-umount.c \
diff --git a/po/POTFILES b/po/POTFILES
index c6277e9..76d1b1d 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -170,6 +170,7 @@ gobject/src/optargs-copy_device_to_device.c
gobject/src/optargs-copy_device_to_file.c
gobject/src/optargs-copy_file_to_device.c
gobject/src/optargs-copy_file_to_file.c
+gobject/src/optargs-disk_create.c
gobject/src/optargs-e2fsck.c
gobject/src/optargs-fstrim.c
gobject/src/optargs-grep.c
@@ -267,6 +268,7 @@ src/canonical-name.c
src/cleanup.c
src/command.c
src/conn-socket.c
+src/create.c
src/dbdump.c
src/drives.c
src/errnostring-gperf.c
diff --git a/src/Makefile.am b/src/Makefile.am
index ba02061..4475281 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -90,6 +90,7 @@ libguestfs_la_SOURCES = \
canonical-name.c \
command.c \
conn-socket.c \
+ create.c \
dbdump.c \
drives.c \
errors.c \
diff --git a/src/create.c b/src/create.c
new file mode 100644
index 0000000..18c4402
--- /dev/null
+++ b/src/create.c
@@ -0,0 +1,319 @@
+/* libguestfs
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+#include "guestfs.h"
+#include "guestfs-internal.h"
+#include "guestfs-internal-actions.h"
+#include "guestfs_protocol.h"
+
+static int disk_create_raw (guestfs_h *g, const char *filename, int64_t size,
const struct guestfs_disk_create_argv *optargs);
+static int disk_create_qcow2 (guestfs_h *g, const char *filename, int64_t size,
const char *backingfile, const struct guestfs_disk_create_argv *optargs);
+static char *qemu_escape_param (guestfs_h *g, const char *param);
+
+int
+guestfs__disk_create (guestfs_h *g, const char *filename,
+ const char *format, int64_t size,
+ const struct guestfs_disk_create_argv *optargs)
+{
+ const char *backingfile;
+
+ backingfile = optargs->bitmask &
GUESTFS_DISK_CREATE_BACKINGFILE_BITMASK ?
+ optargs->backingfile : NULL;
+
+ /* Ensure size is valid. */
+ if (backingfile) {
+ if (size != -1) {
+ error (g, _("if using a backing file, size must be passed as
-1"));
+ return -1;
+ }
+ } else {
+ /* XXX Actually size == 0 could be valid, although not useful and
+ * it causes qemu to break.
+ */
+ if (size <= 0) {
+ error (g, _("invalid size: %" PRIi64), size);
+ return -1;
+ }
+ }
+
+ /* Now the format-specific code. */
+ if (STREQ (format, "raw")) {
+ if (backingfile) {
+ error (g, _("backingfile cannot be used for raw format
disks"));
+ return -1;
+ }
+ if (disk_create_raw (g, filename, size, optargs) == -1)
+ return -1;
+ }
+ else if (STREQ (format, "qcow2")) {
+ if (disk_create_qcow2 (g, filename, size, backingfile, optargs) == -1)
+ return -1;
+ }
+ else {
+ /* Be conservative about what formats we support, since we don't
+ * want to make unlimited promises through the API. We can always
+ * add more later.
+ */
+ error (g, _("unsupported format '%s'"), format);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+disk_create_raw (guestfs_h *g, const char *filename, int64_t size,
+ const struct guestfs_disk_create_argv *optargs)
+{
+ int allocated = 0;
+ int fd;
+ struct stat statbuf;
+
+ /* backingfile parameter not present checked above */
+
+ if (optargs->bitmask & GUESTFS_DISK_CREATE_BACKINGFORMAT_BITMASK) {
+ error (g, _("backingformat parameter cannot be used with raw
format"));
+ return -1;
+ }
+ if (optargs->bitmask & GUESTFS_DISK_CREATE_PREALLOCATION_BITMASK) {
+ if (STREQ (optargs->preallocation, "sparse"))
+ allocated = 0;
+ else if (STREQ (optargs->preallocation, "full"))
+ allocated = 1;
+ else {
+ error (g, _("invalid value for preallocation parameter
'%s'"),
+ optargs->preallocation);
+ return -1;
+ }
+ }
+ if (optargs->bitmask & GUESTFS_DISK_CREATE_COMPAT_BITMASK) {
+ error (g, _("compat parameter cannot be used with raw format"));
+ return -1;
+ }
+ if (optargs->bitmask & GUESTFS_DISK_CREATE_CLUSTERSIZE_BITMASK) {
+ error (g, _("clustersize parameter cannot be used with raw
format"));
+ return -1;
+ }
+
+ /* This version refuses the overwrite block devices or char devices.
+ * XXX It would be possible to make it work with block devices.
+ */
+ if (stat (filename, &statbuf) == 0) {
+ if (S_ISBLK (statbuf.st_mode)) {
+ error (g, _("refusing to overwrite block device '%s'"),
filename);
+ return -1;
+ }
+ if (S_ISCHR (statbuf.st_mode)) {
+ error (g, _("refusing to overwrite char device '%s'"),
filename);
+ return -1;
+ }
+ }
+
+ fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_TRUNC|O_CLOEXEC, 0666);
+ if (fd == -1) {
+ perrorf (g, _("cannot create raw file: %s"), filename);
+ return -1;
+ }
+
+ if (!allocated) { /* Sparse file. */
+ if (ftruncate (fd, size) == -1) {
+ perrorf (g, _("%s: truncate"), filename);
+ close (fd);
+ unlink (filename);
+ return -1;
+ }
+ }
+ else { /* Allocated file. */
+#ifdef HAVE_POSIX_FALLOCATE
+ int err;
+
+ err = posix_fallocate (fd, 0, size);
+ if (err != 0) {
+ errno = err;
+ perrorf (g, _("%s: fallocate"), filename);
+ close (fd);
+ unlink (filename);
+ return -1;
+ }
+#else
+ /* Slow emulation of posix_fallocate on platforms which don't have it.
*/
+ char buffer[BUFSIZ];
+ size_t remaining = size;
+ size_t n;
+ ssize_t r;
+
+ memset (buffer, 0, sizeof buffer);
+
+ while (remaining > 0) {
+ n = remaining > sizeof buffer ? sizeof buffer : remaining;
+ r = write (fd, buffer, n);
+ if (r == -1) {
+ perrorf (g, _("%s: write"), filename);
+ close (fd);
+ unlink (filename);
+ return -1;
+ }
+ remaining -= r;
+ }
+#endif
+ }
+
+ if (close (fd) == -1) {
+ perrorf (g, _("%s: close"), filename);
+ unlink (filename);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* http://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2 */
+static int
+is_power_of_2 (unsigned v)
+{
+ return v && ((v & (v - 1)) == 0);
+}
+
+static int
+disk_create_qcow2 (guestfs_h *g, const char *orig_filename, int64_t size,
+ const char *backingfile,
+ const struct guestfs_disk_create_argv *optargs)
+{
+ CLEANUP_FREE char *filename = NULL;
+ const char *backingformat = NULL;
+ const char *preallocation = NULL;
+ const char *compat = NULL;
+ int clustersize = -1;
+ CLEANUP_FREE_STRINGSBUF DECLARE_STRINGSBUF (optionsv);
+ CLEANUP_CMD_CLOSE struct command *cmd = guestfs___new_command (g);
+ int r;
+
+ /* If the filename is something like "file:foo" then qemu-img will
+ * try to interpret that as "foo" in the file:/// protocol. To
+ * avoid that, if the path is relative prefix it with "./" since
+ * qemu-img won't try to interpret such a path.
+ */
+ if (orig_filename[0] != '/')
+ filename = safe_asprintf (g, "./%s", orig_filename);
+ else
+ filename = safe_strdup (g, orig_filename);
+
+ if (optargs->bitmask & GUESTFS_DISK_CREATE_BACKINGFORMAT_BITMASK) {
+ backingformat = optargs->backingformat;
+ if (STRNEQ (backingformat, "raw") && STRNEQ
(backingformat, "qcow2")) {
+ error (g, _("invalid value for backingformat parameter
'%s'"),
+ backingformat);
+ return -1;
+ }
+ }
+ if (optargs->bitmask & GUESTFS_DISK_CREATE_PREALLOCATION_BITMASK) {
+ preallocation = optargs->preallocation;
+ if (STRNEQ (preallocation, "off") && STRNEQ
(preallocation, "metadata")) {
+ error (g, _("invalid value for preallocation parameter
'%s'"),
+ preallocation);
+ return -1;
+ }
+ }
+ if (optargs->bitmask & GUESTFS_DISK_CREATE_COMPAT_BITMASK) {
+ compat = optargs->compat;
+ if (STRNEQ (compat, "0.10") && STRNEQ (compat,
"1.1")) {
+ error (g, _("invalid value for compat parameter '%s'"),
compat);
+ return -1;
+ }
+ }
+ if (optargs->bitmask & GUESTFS_DISK_CREATE_CLUSTERSIZE_BITMASK) {
+ clustersize = optargs->clustersize;
+ if (clustersize < 512 || clustersize > 2097152 ||
+ !is_power_of_2 ((unsigned) clustersize)) {
+ error (g, _("invalid value for clustersize parameter
'%d'"),
+ clustersize);
+ return -1;
+ }
+ }
+
+ /* Assemble the qemu-img command line. */
+ guestfs___cmd_add_arg (cmd, "qemu-img");
+ guestfs___cmd_add_arg (cmd, "create");
+ guestfs___cmd_add_arg (cmd, "-f");
+ guestfs___cmd_add_arg (cmd, "qcow2");
+
+ /* -o parameter. */
+ if (backingfile) {
+ CLEANUP_FREE char *p = qemu_escape_param (g, backingfile);
+ guestfs___add_sprintf (g, &optionsv, "backing_file=%s", p);
+ }
+ if (backingformat)
+ guestfs___add_sprintf (g, &optionsv, "backing_fmt=%s",
backingformat);
+ if (preallocation)
+ guestfs___add_sprintf (g, &optionsv, "preallocation=%s",
preallocation);
+ if (compat)
+ guestfs___add_sprintf (g, &optionsv, "compat=%s", compat);
+ if (clustersize >= 0)
+ guestfs___add_sprintf (g, &optionsv, "cluster_size=%d",
clustersize);
+ guestfs___end_stringsbuf (g, &optionsv);
+
+ if (optionsv.size > 1) {
+ CLEANUP_FREE char *options = guestfs___join_strings (",",
optionsv.argv);
+ guestfs___cmd_add_arg (cmd, "-o");
+ guestfs___cmd_add_arg (cmd, options);
+ }
+
+ /* Complete the command line. */
+ guestfs___cmd_add_arg (cmd, filename);
+ if (size >= 0)
+ guestfs___cmd_add_arg_format (cmd, "%" PRIi64, size);
+
+ r = guestfs___cmd_run (cmd);
+ if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
+ guestfs___external_command_failed (g, r, "qemu-img",
orig_filename);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* XXX Duplicated in launch-direct.c. */
+static char *
+qemu_escape_param (guestfs_h *g, const char *param)
+{
+ size_t i, len = strlen (param);
+ char *p, *ret;
+
+ ret = p = safe_malloc (g, len*2 + 1); /* max length of escaped name*/
+ for (i = 0; i < len; ++i) {
+ *p++ = param[i];
+ if (param[i] == ',')
+ *p++ = ',';
+ }
+ *p = '\0';
+
+ return ret;
+}
diff --git a/tests/create/Makefile.am b/tests/create/Makefile.am
new file mode 100644
index 0000000..cdcecd2
--- /dev/null
+++ b/tests/create/Makefile.am
@@ -0,0 +1,27 @@
+# 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.
+
+include $(top_srcdir)/subdir-rules.mk
+
+TESTS = \
+ test-disk-create.sh
+
+TESTS_ENVIRONMENT = \
+ $(top_builddir)/run --test
+
+EXTRA_DIST = \
+ $(TESTS)
diff --git a/tests/create/test-disk-create.sh b/tests/create/test-disk-create.sh
new file mode 100755
index 0000000..b287233
--- /dev/null
+++ b/tests/create/test-disk-create.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# 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.
+
+# Test the disk-create API.
+
+export LANG=C
+
+set -e
+
+rm -f disk*.img file:*.img
+
+# XXX We should also test failure paths.
+
+../../fish/guestfish <<EOF
+ disk-create disk1.img raw 256K
+ disk-create disk2.img raw 256K preallocation:sparse
+ disk-create disk3.img raw 256K preallocation:full
+ disk-create disk4.img qcow2 256K
+ disk-create disk5.img qcow2 256K preallocation:off
+ disk-create disk6.img qcow2 256K preallocation:metadata
+ disk-create disk7.img qcow2 256K compat:1.1
+ disk-create disk8.img qcow2 256K clustersize:128K
+ disk-create disk9.img qcow2 -1 backingfile:disk1.img compat:1.1
+ disk-create disk10.img qcow2 -1 backingfile:disk2.img backingformat:raw
+ disk-create disk11.img qcow2 -1 backingfile:disk4.img backingformat:qcow2
+
+ # Some annoying corner-cases in qemu-img.
+ disk-create disk:0.img qcow2 256K
+ disk-create file:0.img qcow2 256K
+ disk-create disk,0.img qcow2 256K
+ disk-create disk,,0.img qcow2 256K
+EOF
+
+rm disk*.img file:*.img
--
1.8.4.2
Richard W.M. Jones
2014-Jan-28 16:24 UTC
[Libguestfs] [PATCH 03/10] lib: Use disk-create API instead of qemu-img/truncate inside the library.
---
src/drives.c | 35 ++++-------------------------------
src/launch-direct.c | 37 ++++++++++++-------------------------
src/launch-libvirt.c | 38 +++++++++++---------------------------
3 files changed, 27 insertions(+), 83 deletions(-)
diff --git a/src/drives.c b/src/drives.c
index dd2b96c..733a6c4 100644
--- a/src/drives.c
+++ b/src/drives.c
@@ -509,7 +509,6 @@ create_drive_dev_null (guestfs_h *g, bool readonly, const
char *format,
const char *disk_label)
{
CLEANUP_FREE char *tmpfile = NULL;
- int fd = -1;
if (format && STRNEQ (format, "raw")) {
error (g, _("for device '/dev/null', format must be
'raw'"));
@@ -525,20 +524,9 @@ create_drive_dev_null (guestfs_h *g, bool readonly, const
char *format,
readonly = false;
tmpfile = safe_asprintf (g, "%s/devnull%d", g->tmpdir,
++g->unique);
- fd = open (tmpfile, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0600);
- if (fd == -1) {
- perrorf (g, "open: %s", tmpfile);
+
+ if (guestfs_disk_create (g, tmpfile, "raw", 4096, -1) == -1)
return NULL;
- }
- if (ftruncate (fd, 4096) == -1) {
- perrorf (g, "truncate: %s", tmpfile);
- close (fd);
- return NULL;
- }
- if (close (fd) == -1) {
- perrorf (g, "close: %s", tmpfile);
- return NULL;
- }
return create_drive_file (g, tmpfile, readonly, format, iface, name,
disk_label, 0);
@@ -1083,11 +1071,10 @@ guestfs__add_drive_ro_with_if (guestfs_h *g, const char
*filename,
int
guestfs__add_drive_scratch (guestfs_h *g, int64_t size,
- const struct guestfs_add_drive_scratch_argv
*optargs)
+ const struct guestfs_add_drive_scratch_argv
*optargs)
{
struct guestfs_add_drive_opts_argv add_drive_optargs = { .bitmask = 0 };
CLEANUP_FREE char *filename = NULL;
- int fd;
/* Some parameters we always set. */
add_drive_optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK;
@@ -1114,22 +1101,8 @@ guestfs__add_drive_scratch (guestfs_h *g, int64_t size,
filename = safe_asprintf (g, "%s/scratch.%d", g->tmpdir,
++g->unique);
/* Create a raw format temporary disk. */
- fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0600);
- if (fd == -1) {
- perrorf (g, "open: %s", filename);
+ if (guestfs_disk_create (g, filename, "raw", size, -1) == -1)
return -1;
- }
-
- if (ftruncate (fd, size) == -1) {
- perrorf (g, "ftruncate: %s", filename);
- close (fd);
- return -1;
- }
-
- if (close (fd) == -1) {
- perrorf (g, "close: %s", filename);
- return -1;
- }
/* Call guestfs_add_drive_opts to add the drive. */
return guestfs_add_drive_opts_argv (g, filename, &add_drive_optargs);
diff --git a/src/launch-direct.c b/src/launch-direct.c
index 2b22ed0..964a507 100644
--- a/src/launch-direct.c
+++ b/src/launch-direct.c
@@ -107,48 +107,35 @@ static char *qemu_escape_param (guestfs_h *g, const char
*param);
static char *
create_cow_overlay_direct (guestfs_h *g, void *datav, struct drive *drv)
{
- char *overlay = NULL;
+ char *overlay;
CLEANUP_FREE char *backing_drive = NULL;
- CLEANUP_CMD_CLOSE struct command *cmd = guestfs___new_command (g);
- int r;
+ struct guestfs_disk_create_argv optargs;
backing_drive = guestfs___drive_source_qemu_param (g, &drv->src);
if (!backing_drive)
- goto error;
+ return NULL;
if (guestfs___lazy_make_tmpdir (g) == -1)
- goto error;
+ return NULL;
overlay = safe_asprintf (g, "%s/overlay%d", g->tmpdir,
++g->unique);
- guestfs___cmd_add_arg (cmd, "qemu-img");
- guestfs___cmd_add_arg (cmd, "create");
- guestfs___cmd_add_arg (cmd, "-f");
- guestfs___cmd_add_arg (cmd, "qcow2");
- guestfs___cmd_add_arg (cmd, "-b");
- guestfs___cmd_add_arg (cmd, backing_drive);
+ optargs.bitmask = GUESTFS_DISK_CREATE_BACKINGFILE_BITMASK;
+ optargs.backingfile = backing_drive;
if (drv->src.format) {
- guestfs___cmd_add_arg (cmd, "-o");
- guestfs___cmd_add_arg_format (cmd, "backing_fmt=%s",
drv->src.format);
+ optargs.bitmask |= GUESTFS_DISK_CREATE_BACKINGFORMAT_BITMASK;
+ optargs.backingformat = drv->src.format;
}
- guestfs___cmd_add_arg (cmd, overlay);
- r = guestfs___cmd_run (cmd);
- if (r == -1)
- goto error;
- if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
- guestfs___external_command_failed (g, r, "qemu-img create",
backing_drive);
- goto error;
+
+ if (guestfs_disk_create_argv (g, overlay, "qcow2", -1,
&optargs) == -1) {
+ free (overlay);
+ return NULL;
}
/* Caller sets g->overlay in the handle to this, and then manages
* the memory.
*/
return overlay;
-
- error:
- free (overlay);
-
- return NULL;
}
#ifdef QEMU_OPTIONS
diff --git a/src/launch-libvirt.c b/src/launch-libvirt.c
index 8cc261d..60213fd 100644
--- a/src/launch-libvirt.c
+++ b/src/launch-libvirt.c
@@ -145,33 +145,22 @@ static char *
make_qcow2_overlay (guestfs_h *g, const char *backing_drive,
const char *format)
{
- CLEANUP_CMD_CLOSE struct command *cmd = guestfs___new_command (g);
- char *overlay = NULL;
- int r;
+ char *overlay;
+ struct guestfs_disk_create_argv optargs;
if (guestfs___lazy_make_tmpdir (g) == -1)
return NULL;
overlay = safe_asprintf (g, "%s/overlay%d", g->tmpdir,
++g->unique);
- guestfs___cmd_add_arg (cmd, "qemu-img");
- guestfs___cmd_add_arg (cmd, "create");
- guestfs___cmd_add_arg (cmd, "-f");
- guestfs___cmd_add_arg (cmd, "qcow2");
- guestfs___cmd_add_arg (cmd, "-b");
- guestfs___cmd_add_arg (cmd, backing_drive);
+ optargs.bitmask = GUESTFS_DISK_CREATE_BACKINGFILE_BITMASK;
+ optargs.backingfile = backing_drive;
if (format) {
- guestfs___cmd_add_arg (cmd, "-o");
- guestfs___cmd_add_arg_format (cmd, "backing_fmt=%s", format);
+ optargs.bitmask |= GUESTFS_DISK_CREATE_BACKINGFORMAT_BITMASK;
+ optargs.backingformat = format;
}
- guestfs___cmd_add_arg (cmd, overlay);
- r = guestfs___cmd_run (cmd);
- if (r == -1) {
- free (overlay);
- return NULL;
- }
- if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
- guestfs___external_command_failed (g, r, "qemu-img create",
backing_drive);
+
+ if (guestfs_disk_create_argv (g, overlay, "qcow2", -1,
&optargs) == -1) {
free (overlay);
return NULL;
}
@@ -184,15 +173,15 @@ create_cow_overlay_libvirt (guestfs_h *g, void *datav,
struct drive *drv)
{
struct backend_libvirt_data *data = datav;
CLEANUP_FREE char *backing_drive = NULL;
- char *overlay = NULL;
+ char *overlay;
backing_drive = guestfs___drive_source_qemu_param (g, &drv->src);
if (!backing_drive)
- goto error;
+ return NULL;
overlay = make_qcow2_overlay (g, backing_drive, drv->src.format);
if (!overlay)
- goto error;
+ return NULL;
#if HAVE_LIBSELINUX
if (data->selinux_imagelabel) {
@@ -208,11 +197,6 @@ create_cow_overlay_libvirt (guestfs_h *g, void *datav,
struct drive *drv)
* the memory.
*/
return overlay;
-
- error:
- free (overlay);
-
- return NULL;
}
static int
--
1.8.4.2
Richard W.M. Jones
2014-Jan-28 16:24 UTC
[Libguestfs] [PATCH 04/10] fish: Use disk-create API to implement guestfish 'alloc' and 'sparse' commands.
---
fish/Makefile.am | 1 +
fish/alloc.c | 60 ++++--------------------------------------------------
fish/test-alloc.sh | 47 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 52 insertions(+), 56 deletions(-)
create mode 100755 fish/test-alloc.sh
diff --git a/fish/Makefile.am b/fish/Makefile.am
index 54ba875..c39c968 100644
--- a/fish/Makefile.am
+++ b/fish/Makefile.am
@@ -301,6 +301,7 @@ EXTRA_DIST += \
test-a.sh \
test-add-domain.sh \
test-add-uri.sh \
+ test-alloc.sh \
test-copy.sh \
test-d.sh \
test-edit.sh \
diff --git a/fish/alloc.c b/fish/alloc.c
index 18597f7..06dd8cf 100644
--- a/fish/alloc.c
+++ b/fish/alloc.c
@@ -66,67 +66,15 @@ int
alloc_disk (const char *filename, const char *size_str, int add, int sparse)
{
off_t size;
- int fd;
- char c = 0;
+ const char *prealloc = sparse ? "sparse" : "full";
if (parse_size (size_str, &size) == -1)
return -1;
- fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_TRUNC|O_CLOEXEC, 0666);
- if (fd == -1) {
- perror (filename);
+ if (guestfs_disk_create (g, filename, "raw", (int64_t) size,
+ GUESTFS_DISK_CREATE_PREALLOCATION, prealloc,
+ -1) == -1)
return -1;
- }
-
- if (!sparse) { /* Not sparse */
-#ifdef HAVE_POSIX_FALLOCATE
- int err = posix_fallocate (fd, 0, size);
- if (err != 0) {
- errno = err;
- perror ("fallocate");
- close (fd);
- unlink (filename);
- return -1;
- }
-#else
- /* Slow emulation of posix_fallocate on platforms which don't have it.
*/
- char buffer[BUFSIZ];
- memset (buffer, 0, sizeof buffer);
-
- size_t remaining = size;
- while (remaining > 0) {
- size_t n = remaining > sizeof buffer ? sizeof buffer : remaining;
- ssize_t r = write (fd, buffer, n);
- if (r == -1) {
- perror ("write");
- close (fd);
- unlink (filename);
- return -1;
- }
- remaining -= r;
- }
-#endif
- } else { /* Sparse */
- if (lseek (fd, size-1, SEEK_SET) == (off_t) -1) {
- perror ("lseek");
- close (fd);
- unlink (filename);
- return -1;
- }
-
- if (write (fd, &c, 1) != 1) {
- perror ("write");
- close (fd);
- unlink (filename);
- return -1;
- }
- }
-
- if (close (fd) == -1) {
- perror (filename);
- unlink (filename);
- return -1;
- }
if (add) {
if (guestfs_add_drive_opts (g, filename,
diff --git a/fish/test-alloc.sh b/fish/test-alloc.sh
new file mode 100755
index 0000000..3f46f8b
--- /dev/null
+++ b/fish/test-alloc.sh
@@ -0,0 +1,47 @@
+#!/bin/bash -
+# 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.
+
+# Test guestfish alloc and sparse commands.
+
+set -e
+
+rm -f test-alloc.img
+
+$VG ./guestfish alloc test-alloc.img 200000
+if [ "$(stat -c '%s' test-alloc.img)" -ne 200000 ]; then
+ echo "$0: alloc command failed to create file of the correct
size"
+ exit 1
+fi
+
+if [ "$(stat -c '%b' test-alloc.img)" -eq 0 ]; then
+ echo "$0: alloc command failed to create a fully allocated file"
+ exit 1
+fi
+
+$VG ./guestfish sparse test-alloc.img 100000
+if [ "$(stat -c '%s' test-alloc.img)" -ne 100000 ]; then
+ echo "$0: sparse command failed to create file of the correct
size"
+ exit 1
+fi
+
+if [ "$(stat -c '%b' test-alloc.img)" -ne 0 ]; then
+ echo "$0: sparse command failed to create a sparse file"
+ exit 1
+fi
+
+rm test-alloc.img
--
1.8.4.2
Richard W.M. Jones
2014-Jan-28 16:24 UTC
[Libguestfs] [PATCH 05/10] examples: Update various examples to use new disk-create API.
---
examples/create-disk.c | 20 +++++---------------
examples/mount-local.c | 22 +++++-----------------
golang/examples/create-disk.go | 12 ++----------
ocaml/examples/create_disk.ml | 4 +---
perl/examples/create_disk.pl | 4 +---
python/examples/create_disk.py | 5 +----
ruby/examples/create_disk.rb | 4 +---
7 files changed, 16 insertions(+), 55 deletions(-)
diff --git a/examples/create-disk.c b/examples/create-disk.c
index 620efed..4326a45 100644
--- a/examples/create-disk.c
+++ b/examples/create-disk.c
@@ -17,26 +17,16 @@ main (int argc, char *argv[])
if (g == NULL) {
perror ("failed to create libguestfs handle");
exit (EXIT_FAILURE);
- }
-
- /* Create a raw-format sparse disk image, 512 MB in size. */
- int fd = open ("disk.img", O_CREAT|O_WRONLY|O_TRUNC|O_NOCTTY,
0666);
- if (fd == -1) {
- perror ("disk.img");
- exit (EXIT_FAILURE);
- }
- if (ftruncate (fd, 512 * 1024 * 1024) == -1) {
- perror ("disk.img: truncate");
- exit (EXIT_FAILURE);
- }
- if (close (fd) == -1) {
- perror ("disk.img: close");
- exit (EXIT_FAILURE);
}
/* Set the trace flag so that we can see each libguestfs call. */
guestfs_set_trace (g, 1);
+ /* Create a raw-format sparse disk image, 512 MB in size. */
+ if (guestfs_disk_create (g, "disk.img", "raw",
UINT64_C(512)*1024*1024,
+ -1) == -1)
+ exit (EXIT_FAILURE);
+
/* Add the disk image to libguestfs. */
if (guestfs_add_drive_opts (g, "disk.img",
GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", /* raw format */
diff --git a/examples/mount-local.c b/examples/mount-local.c
index 18970d0..291cb26 100644
--- a/examples/mount-local.c
+++ b/examples/mount-local.c
@@ -43,7 +43,7 @@ int
main (int argc, char *argv[])
{
guestfs_h *g;
- int fd, r;
+ int r;
char tempdir[] = "/tmp/mlXXXXXX";
pid_t pid;
char *shell, *p;
@@ -65,22 +65,6 @@ main (int argc, char *argv[])
"Creating and formatting the disk image, please wait a moment
...\n");
fflush (stdout);
- /* Create the output disk image: raw sparse. */
- fd = open (argv[1], O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644);
- if (fd == -1) {
- perror (argv[1]);
- exit (EXIT_FAILURE);
- }
- if (ftruncate (fd, SIZE_MB * 1024 * 1024) == -1) {
- perror ("truncate");
- close (fd);
- exit (EXIT_FAILURE);
- }
- if (close (fd) == -1) {
- perror ("close");
- exit (EXIT_FAILURE);
- }
-
/* Guestfs handle. */
g = guestfs_create ();
if (g == NULL) {
@@ -88,6 +72,10 @@ main (int argc, char *argv[])
exit (EXIT_FAILURE);
}
+ /* Create the output disk image: raw sparse. */
+ if (guestfs_disk_create (g, argv[1], "raw", SIZE_MB * 1024 * 1024,
-1) == -1)
+ exit (EXIT_FAILURE);
+
/* Create the disk image and format it with a partition and a filesystem. */
if (guestfs_add_drive_opts (g, argv[1],
GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
diff --git a/golang/examples/create-disk.go b/golang/examples/create-disk.go
index 336fd6c..a59d3f4 100644
--- a/golang/examples/create-disk.go
+++ b/golang/examples/create-disk.go
@@ -4,7 +4,6 @@ package main
import (
"fmt"
- "os"
"libguestfs.org/guestfs"
)
@@ -18,15 +17,8 @@ func main() {
defer g.Close ()
/* Create a raw-format sparse disk image, 512 MB in size. */
- f, ferr := os.Create (output)
- if ferr != nil {
- panic (fmt.Sprintf ("could not create file: %s: %s",
- output, ferr))
- }
- defer f.Close ()
-
- if ferr := f.Truncate (512 * 1024 * 1024); ferr != nil {
- panic (fmt.Sprintf ("could not truncate file: %s", ferr))
+ if err := g.Disk_create (output, "raw", 512 * 1024 * 1024); err !=
nil {
+ panic (err)
}
/* Set the trace flag so that we can see each libguestfs call. */
diff --git a/ocaml/examples/create_disk.ml b/ocaml/examples/create_disk.ml
index 73d51e3..5083d39 100644
--- a/ocaml/examples/create_disk.ml
+++ b/ocaml/examples/create_disk.ml
@@ -9,9 +9,7 @@ let () let g = new Guestfs.guestfs () in
(* Create a raw-format sparse disk image, 512 MB in size. *)
- let fd = openfile output [O_WRONLY;O_CREAT;O_TRUNC;O_NOCTTY] 0o666 in
- ftruncate fd (512 * 1024 * 1024);
- close fd;
+ g#disk_create output "raw" 536870912L;
(* Set the trace flag so that we can see each libguestfs call. *)
g#set_trace true;
diff --git a/perl/examples/create_disk.pl b/perl/examples/create_disk.pl
index 2186ce7..0b9fa8d 100755
--- a/perl/examples/create_disk.pl
+++ b/perl/examples/create_disk.pl
@@ -10,9 +10,7 @@ my $output = "disk.img";
my $g = new Sys::Guestfs ();
# Create a raw-format sparse disk image, 512 MB in size.
-open FILE, ">$output" or die "$output: $!";
-truncate FILE, 512 * 1024 * 1024 or die "$output: truncate: $!";
-close FILE or die "$output: $!";
+$g->disk_create ($output, "raw", 512 * 1024 * 1024);
# Set the trace flag so that we can see each libguestfs call.
$g->set_trace (1);
diff --git a/python/examples/create_disk.py b/python/examples/create_disk.py
index 2f57f3f..ed42e70 100644
--- a/python/examples/create_disk.py
+++ b/python/examples/create_disk.py
@@ -1,6 +1,5 @@
# Example showing how to create a disk image.
-import os
import guestfs
output = "disk.img"
@@ -12,9 +11,7 @@ output = "disk.img"
g = guestfs.GuestFS (python_return_dict=True)
# Create a raw-format sparse disk image, 512 MB in size.
-f = open (output, "w")
-f.truncate (512 * 1024 * 1024)
-f.close ()
+g.disk_create (output, "raw", 512 * 1024 * 1024);
# Set the trace flag so that we can see each libguestfs call.
g.set_trace (1)
diff --git a/ruby/examples/create_disk.rb b/ruby/examples/create_disk.rb
index fba85ff..00310de 100644
--- a/ruby/examples/create_disk.rb
+++ b/ruby/examples/create_disk.rb
@@ -7,9 +7,7 @@ output = "disk.img"
g = Guestfs::Guestfs.new()
# Create a raw-format sparse disk image, 512 MB in size.
-File.open(output, "w") {
- |f| f.truncate(512 * 1024 * 1024)
-}
+g.disk_create (output, "raw", 512 * 1024 * 1024)
# Set the trace flag so that we can see each libguestfs call.
g.set_trace(1)
--
1.8.4.2
Richard W.M. Jones
2014-Jan-28 16:24 UTC
[Libguestfs] [PATCH 06/10] builder: Use disk-create API instead of calling qemu-img create.
---
builder/builder.ml | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/builder/builder.ml b/builder/builder.ml
index 3c45fa5..b01f4eb 100644
--- a/builder/builder.ml
+++ b/builder/builder.ml
@@ -513,14 +513,8 @@ let main () let { Index_parser.expand = expand;
lvexpand = lvexpand } = entry in
msg (f_"Resizing (using virt-resize) to expand the disk to %s")
(human_size osize);
- let cmd - sprintf "qemu-img create -f %s%s %s %Ld%s"
- (quote oformat)
- (if oformat = "qcow2" then " -o
preallocation=metadata" else "")
- (quote ofile) osize
- (if debug then "" else " >/dev/null
2>&1") in
- if debug then eprintf "%s\n%!" cmd;
- if Sys.command cmd <> 0 then exit 1;
+ let preallocation = if oformat = "qcow2" then Some
"metadata" else None in
+ (new G.guestfs ())#disk_create ?preallocation ofile oformat osize;
let cmd sprintf "virt-resize%s%s%s --output-format %s%s%s
%s %s"
(if debug then " --verbose" else " --quiet")
--
1.8.4.2
Richard W.M. Jones
2014-Jan-28 16:24 UTC
[Libguestfs] [PATCH 07/10] tests: Update miscellaneous tests to use disk-create API.
Instead of calling out to qemu-img / truncate.
---
diff/test-virt-diff.sh | 4 +++-
edit/test-virt-edit.sh | 4 +++-
fish/test-a.sh | 2 +-
fish/test-add-domain.sh | 2 +-
fish/test-d.sh | 2 +-
fuse/test-fuse-umount-race.sh | 4 +++-
python/t/810-rhbz811650.py | 6 ++----
resize/test-virt-resize.sh | 4 +++-
sysprep/test-virt-sysprep-passwords.sh | 4 +++-
tests/guests/guest-aux/make-fedora-img.pl | 15 ++++-----------
tests/hotplug/test-hot-add.pl | 13 ++++---------
tests/hotplug/test-hot-remove.pl | 13 ++++---------
tests/hotplug/test-hotplug-repeated.pl | 7 +------
tests/md/test-inspect-fstab.sh | 4 +++-
tests/mountable/test-mountable-inspect.sh | 4 +++-
tests/qemu/qemu-snapshot-isolation.sh | 3 ++-
tests/syslinux/test-syslinux.pl | 10 ++++------
17 files changed, 45 insertions(+), 56 deletions(-)
diff --git a/diff/test-virt-diff.sh b/diff/test-virt-diff.sh
index 95778d8..3a3a1aa 100755
--- a/diff/test-virt-diff.sh
+++ b/diff/test-virt-diff.sh
@@ -32,7 +32,9 @@ fi
rm -f fedora.qcow2
# Modify a copy of the image.
-qemu-img create -f qcow2 -b ../tests/guests/fedora.img fedora.qcow2
+../fish/guestfish -- \
+ disk-create fedora.qcow2 qcow2 -1 \
+ backingfile:../tests/guests/fedora.img backingformat:raw
../fish/guestfish -a fedora.qcow2 -i <<EOF
touch /diff
diff --git a/edit/test-virt-edit.sh b/edit/test-virt-edit.sh
index 572ad22..99c2e7c 100755
--- a/edit/test-virt-edit.sh
+++ b/edit/test-virt-edit.sh
@@ -28,7 +28,9 @@ rm -f test.qcow2
# Make a copy of the Fedora image so we can write to it then
# discard it.
-qemu-img create -F raw -b ../tests/guests/fedora.img -f qcow2 test.qcow2
+../fish/guestfish -- \
+ disk-create test.qcow2 qcow2 -1 \
+ backingfile:../tests/guests/fedora.img backingformat:raw
# Edit interactively. We have to simulate this by setting $EDITOR.
# The command will be: echo newline >> /tmp/file
diff --git a/fish/test-a.sh b/fish/test-a.sh
index df892fe..52194c2 100755
--- a/fish/test-a.sh
+++ b/fish/test-a.sh
@@ -30,7 +30,7 @@ $VG ./guestfish -x -a test-a.img </dev/null >test-a.out
2>&1
! grep -sq 'add_drive.*format' test-a.out
rm test-a.img
-qemu-img create -f qcow2 test-a.img 100M
+$VG ./guestfish disk-create test-a.img qcow2 100M
$VG ./guestfish -x --format=qcow2 -a test-a.img </dev/null >test-a.out
2>&1
diff --git a/fish/test-add-domain.sh b/fish/test-add-domain.sh
index 419c5cf..a6b0e10 100755
--- a/fish/test-add-domain.sh
+++ b/fish/test-add-domain.sh
@@ -27,7 +27,7 @@ cwd="$(pwd)"
$VG ./guestfish sparse test-add-domain-1.img 1M
$VG ./guestfish sparse test-add-domain-2.img 1M
-qemu-img create -f qcow2 test-add-domain-3.img 1M
+$VG ./guestfish disk-create test-add-domain-3.img qcow2 1M
$VG ./guestfish sparse test-add-domain-4.img 1M
# Libvirt test XML, see libvirt.git/examples/xml/test/testnode.xml
diff --git a/fish/test-d.sh b/fish/test-d.sh
index b891505..1e16bdc 100755
--- a/fish/test-d.sh
+++ b/fish/test-d.sh
@@ -27,7 +27,7 @@ cwd="$(pwd)"
$VG ./guestfish sparse test-d-1.img 1M
$VG ./guestfish sparse test-d-2.img 1M
-qemu-img create -f qcow2 test-d-3.img 1M
+$VG ./guestfish disk-create test-d-3.img qcow2 1M
$VG ./guestfish sparse test-d-4.img 1M
# Libvirt test XML, see libvirt.git/examples/xml/test/testnode.xml
diff --git a/fuse/test-fuse-umount-race.sh b/fuse/test-fuse-umount-race.sh
index 67dbac9..7624219 100755
--- a/fuse/test-fuse-umount-race.sh
+++ b/fuse/test-fuse-umount-race.sh
@@ -42,7 +42,9 @@ rm -f test.qcow2 test-copy.qcow2 test.pid
rm -rf mp
# Make a copy of the Fedora image so we can write to it then discard it.
-qemu-img create -F raw -b ../tests/guests/fedora.img -f qcow2 test.qcow2
+../fish/guestfish -- \
+ disk-create test.qcow2 qcow2 -1 \
+ backingfile:../tests/guests/fedora.img backingformat:raw
mkdir mp
./guestmount -a test.qcow2 -m /dev/VG/Root --pid-file test.pid mp
diff --git a/python/t/810-rhbz811650.py b/python/t/810-rhbz811650.py
index 128f3b5..56d8062 100644
--- a/python/t/810-rhbz811650.py
+++ b/python/t/810-rhbz811650.py
@@ -18,12 +18,10 @@
import os
import guestfs
-f = open ("rhbz811650.img", "w")
-f.truncate (500 * 1024 * 1024)
-f.close ()
-
g = guestfs.GuestFS (python_return_dict=True)
+g.disk_create ("rhbz811650.img", "raw", 500 * 1024 * 1024)
+
# Deliberate error: the disk format is supposed to be raw.
g.add_drive ("rhbz811650.img", format="qcow2");
diff --git a/resize/test-virt-resize.sh b/resize/test-virt-resize.sh
index 944301c..29c1e4c 100755
--- a/resize/test-virt-resize.sh
+++ b/resize/test-virt-resize.sh
@@ -32,7 +32,9 @@ fi
$VG ../fish/guestfish \
-N test-virt-resize-1.img=bootrootlv:/dev/VG/LV:ext2:ext4:400M:32M:gpt
</dev/null
-qemu-img create -f qcow2 -o preallocation=metadata test-virt-resize-2.img 500M
+$VG ../fish/guestfish \
+ disk-create test-virt-resize-2.img qcow2 500M preallocation:metadata
+
$VG ./virt-resize -d --debug-gc \
--expand /dev/sda2 \
--lv-expand /dev/VG/LV \
diff --git a/sysprep/test-virt-sysprep-passwords.sh
b/sysprep/test-virt-sysprep-passwords.sh
index f606501..488187c 100755
--- a/sysprep/test-virt-sysprep-passwords.sh
+++ b/sysprep/test-virt-sysprep-passwords.sh
@@ -35,7 +35,9 @@ fi
# so we fake that now.
rm -f passwords.qcow2 password
-qemu-img create -F raw -b ../tests/guests/fedora.img -f qcow2 passwords.qcow2
+../fish/guestfish -- \
+ disk-create passwords.qcow2 qcow2 -1 \
+ backingfile:../tests/guests/fedora.img backingformat:raw
../fish/guestfish -a passwords.qcow2 -i <<'EOF'
write-append /etc/shadow "test01::15677:0:99999:7:::\n"
diff --git a/tests/guests/guest-aux/make-fedora-img.pl
b/tests/guests/guest-aux/make-fedora-img.pl
index 0537bd2..4eb08b5 100755
--- a/tests/guests/guest-aux/make-fedora-img.pl
+++ b/tests/guests/guest-aux/make-fedora-img.pl
@@ -60,9 +60,7 @@ EOF
$bootdev = '/dev/sda1';
- open (my $img, '>', "fedora.img.tmp.$$") or die;
- truncate ($img, $IMAGE_SIZE) or die;
- close ($img) or die;
+ $g->disk_create ("fedora.img.tmp.$$", "raw",
$IMAGE_SIZE);
$g->add_drive ("fedora.img.tmp.$$");
$g->launch ();
@@ -88,11 +86,8 @@ EOF
$bootdev = '/dev/md/boot';
foreach my $img (@images) {
- open (my $fh, '>', $img) or die;
- truncate ($fh, $IMAGE_SIZE) or die;
- close ($fh) or die;
-
- $g->add_drive ($img);
+ $g->disk_create ($img, "raw", $IMAGE_SIZE);
+ $g->add_drive ($img);
}
$g->launch ();
@@ -140,9 +135,7 @@ EOF
$bootdev = '/dev/sda1';
- open (my $img, '>', "fedora-btrfs.img.tmp.$$") or die;
- truncate ($img, $IMAGE_SIZE) or die;
- close ($img) or die;
+ $g->disk_create ("fedora-btrfs.img.tmp.$$", "raw",
$IMAGE_SIZE);
$g->add_drive ("fedora-btrfs.img.tmp.$$");
$g->launch ();
diff --git a/tests/hotplug/test-hot-add.pl b/tests/hotplug/test-hot-add.pl
index 310440e..2496e08 100755
--- a/tests/hotplug/test-hot-add.pl
+++ b/tests/hotplug/test-hot-add.pl
@@ -36,15 +36,10 @@ unless ($backend eq "libvirt" || $backend =~
/^libvirt:/) {
$g->launch ();
# Create some temporary disks.
-open FILE, ">test-hot-add-1.img" or die "test-hot-add-1.img:
$!";
-truncate FILE, 512 * 1024 * 1024 or die "test-hot-add-1.img: truncate:
$!";
-close FILE;
-
-open FILE, ">test-hot-add-2.img" or die "test-hot-add-2.img:
$!";
-truncate FILE, 512 * 1024 * 1024 or die "test-hot-add-2.img: truncate:
$!";
-close FILE;
-
-die unless system ("qemu-img create -f qcow2 -o preallocation=metadata
test-hot-add-3.img 1G") == 0;
+$g->disk_create ("test-hot-add-1.img", "raw", 512 * 1024
* 1024);
+$g->disk_create ("test-hot-add-2.img", "raw", 512 * 1024
* 1024);
+$g->disk_create ("test-hot-add-3.img", "qcow2", 1024 *
1024 * 1024,
+ preallocation => "metadata");
# Hot-add them. Labels are required.
$g->add_drive ("test-hot-add-1.img", label => "a"); #
autodetect format
diff --git a/tests/hotplug/test-hot-remove.pl b/tests/hotplug/test-hot-remove.pl
index c9e4146..aa6ab93 100755
--- a/tests/hotplug/test-hot-remove.pl
+++ b/tests/hotplug/test-hot-remove.pl
@@ -33,15 +33,10 @@ unless ($backend eq "libvirt" || $backend =~
/^libvirt:/) {
}
# Create some temporary disks.
-open FILE, ">test-hot-remove-1.img" or die
"test-hot-remove-1.img: $!";
-truncate FILE, 512 * 1024 * 1024 or die "test-hot-remove-1.img: truncate:
$!";
-close FILE;
-
-open FILE, ">test-hot-remove-2.img" or die
"test-hot-remove-2.img: $!";
-truncate FILE, 512 * 1024 * 1024 or die "test-hot-remove-2.img: truncate:
$!";
-close FILE;
-
-die unless system ("qemu-img create -f qcow2 -o preallocation=metadata
test-hot-remove-3.img 1G") == 0;
+$g->disk_create ("test-hot-remove-1.img", "raw", 512 *
1024 * 1024);
+$g->disk_create ("test-hot-remove-2.img", "raw", 512 *
1024 * 1024);
+$g->disk_create ("test-hot-remove-3.img", "qcow2", 1024
* 1024 * 1024,
+ preallocation => "metadata");
# Hot-add them. Labels are required.
$g->add_drive ("test-hot-remove-1.img", label =>
"a"); # autodetect format
diff --git a/tests/hotplug/test-hotplug-repeated.pl
b/tests/hotplug/test-hotplug-repeated.pl
index 635bf41..306bceb 100755
--- a/tests/hotplug/test-hotplug-repeated.pl
+++ b/tests/hotplug/test-hotplug-repeated.pl
@@ -35,12 +35,7 @@ unless ($backend eq "libvirt" || $backend =~
/^libvirt:/) {
$g->launch ();
# Create a temporary disk.
-open FILE, ">test-hotplug-repeated.img" or
- die "test-hotplug-repeated.img: $!";
-truncate FILE, 512 * 1024 * 1024 or
- die "test-hotplug-repeated.img: truncate: $!";
-close FILE or
- die "test-hotplug-repeated.img: close: $!";
+$g->disk_create ("test-hotplug-repeated.img", "raw", 512
* 1024 * 1024);
my $start_t = time ();
while (time () - $start_t <= 60) {
diff --git a/tests/md/test-inspect-fstab.sh b/tests/md/test-inspect-fstab.sh
index 635c06c..04ee9d1 100755
--- a/tests/md/test-inspect-fstab.sh
+++ b/tests/md/test-inspect-fstab.sh
@@ -34,7 +34,9 @@ rm -f inspect-fstab-1.qcow2 inspect-fstab.fstab
inspect-fstab.output
# Start with the regular (good) fedora image, modify /etc/fstab
# and then inspect it.
-qemu-img create -F raw -b ../guests/fedora.img -f qcow2 inspect-fstab-1.qcow2
+$guestfish -- \
+ disk-create inspect-fstab-1.qcow2 qcow2 -1 \
+ backingfile:../guests/fedora.img backingformat:raw
cat <<'EOF' > inspect-fstab.fstab
/dev/VG/Root / ext2 default 0 0
diff --git a/tests/mountable/test-mountable-inspect.sh
b/tests/mountable/test-mountable-inspect.sh
index 10d1e9f..b248b01 100755
--- a/tests/mountable/test-mountable-inspect.sh
+++ b/tests/mountable/test-mountable-inspect.sh
@@ -43,7 +43,9 @@ rm -f root.tmp test.qcow2 test.output
# Start with the regular (good) fedora image, modify /etc/fstab
# and then inspect it.
-qemu-img create -F raw -b ../guests/fedora-btrfs.img -f qcow2 test.qcow2
+$guestfish -- \
+ disk-create test.qcow2 qcow2 -1 \
+ backingfile:../guests/fedora-btrfs.img backingformat:raw
# Test that basic inspection works and the expected filesystems are
# found
diff --git a/tests/qemu/qemu-snapshot-isolation.sh
b/tests/qemu/qemu-snapshot-isolation.sh
index 360e999..82b3892 100755
--- a/tests/qemu/qemu-snapshot-isolation.sh
+++ b/tests/qemu/qemu-snapshot-isolation.sh
@@ -38,7 +38,8 @@ isolation1_md5sum="$(md5sum isolation1.img | awk
'{print $1}')"
isolation2_md5sum="$(md5sum isolation2.img | awk '{print
$1}')"
if [ "$supports_qcow2" = "yes" ]; then
- qemu-img create -f qcow2 -o preallocation=metadata isolation3.img 100M
+ ../../fish/guestfish \
+ disk-create isolation3.img qcow2 100M preallocation:metadata
isolation3_md5sum="$(md5sum isolation3.img | awk '{print
$1}')"
add3="add-drive-opts isolation3.img format:qcow2 readonly:true"
cmds3="
diff --git a/tests/syslinux/test-syslinux.pl b/tests/syslinux/test-syslinux.pl
index 9844883..d86c095 100755
--- a/tests/syslinux/test-syslinux.pl
+++ b/tests/syslinux/test-syslinux.pl
@@ -55,13 +55,11 @@ unless ($kernel) {
}
print "kernel: $kernel\n";
-# Create the disk.
-unlink "$disk";
-open DISK, ">$disk" or die "$disk: $!";
-truncate DISK, 100*1024*1024;
-close DISK;
-
my $g = Sys::Guestfs->new ();
+
+# Create the disk.
+$g->disk_create ($disk, "raw", 100*1024*1024);
+
$g->add_drive ($disk, format => "raw");
$g->launch ();
--
1.8.4.2
Richard W.M. Jones
2014-Jan-28 16:24 UTC
[Libguestfs] [PATCH 08/10] rescue: Note that we're not using add-drive-scratch here, and maybe we should be.
---
rescue/rescue.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/rescue/rescue.c b/rescue/rescue.c
index 0442711..b46dad6 100644
--- a/rescue/rescue.c
+++ b/rescue/rescue.c
@@ -533,6 +533,8 @@ add_scratch_disk (struct drv **drvs)
struct scratch_disk *sd;
struct drv *drv;
+ /* XXX Is there a reason we're not using guestfs_add_drive_scratch here?
*/
+
/* Create a temporary file, raw sparse format. */
fd = mkstemp (filename_s);
if (fd == -1) {
--
1.8.4.2
Richard W.M. Jones
2014-Jan-28 16:24 UTC
[Libguestfs] [PATCH 09/10] sparsify: Use new disk-create API instead of calling qemu-img.
disk-create doesn't support the lazy_refcounts option.
---
sparsify/sparsify.ml | 71 ++++++----------------------------------------------
1 file changed, 7 insertions(+), 64 deletions(-)
diff --git a/sparsify/sparsify.ml b/sparsify/sparsify.ml
index 3e544db..212a23f 100644
--- a/sparsify/sparsify.ml
+++ b/sparsify/sparsify.ml
@@ -157,16 +157,6 @@ read the man page virt-sparsify(1).
else
Sys.getcwd () // indisk in
- let contains_colon filename - try ignore (String.index filename
':'); true with Not_found -> false in
-
- (* Check filenames don't contain a colon (limitation of qemu-img). *)
- if contains_colon indisk then
- error (f_"input filename '%s' contains a colon (':');
qemu-img command line syntax prevents us from using such an image") indisk;
-
- if contains_colon outdisk then
- error (f_"output filename '%s' contains a colon (':');
qemu-img command line syntax prevents us from using such an image")
outdisk;
-
(* Check the output is not a block or char special (RHBZ#1056290). *)
if is_block_device outdisk then
error (f_"output '%s' cannot be a block device, it must be a
regular file")
@@ -190,34 +180,6 @@ let () let do_sigint _ = exit 1 in
Sys.set_signal Sys.sigint (Sys.Signal_handle do_sigint)
-(* Try to determine which flag options qemu-img supports for qcow2.
- * We do this by creating and disposing of a few test images. This
- * also detects if qemu-img is completely broken.
- *)
-let qemu_img_supports_compat11, qemu_img_supports_lazy_refcounts - let test
options - let tmp = Filename.temp_file "test" ".qcow2" in
- unlink_on_exit tmp;
- let cmd = "qemu-img create -f qcow2" ^
- (match options with None -> "" | Some opts -> " -o
" ^ opts) ^
- " " ^ tmp ^ " 128K > /dev/null" in
- if verbose then printf "testing if '%s' works ... %!"
cmd;
- let r = Sys.command cmd = 0 in
- if verbose then printf "%b\n" r;
- r
- in
- if not (test None) then (
- eprintf (f_"\
-'qemu-img create' cannot create qcow2 files. Check the
'qemu-img'
-program is installed and working, and that it matches the version\
-of qemu installed.\n");
- exit 1
- );
- let supports_compat11 = test (Some "compat=1.1") in
- let supports_lazy_refcounts - test (Some
"compat=1.1,lazy_refcounts") in
- supports_compat11, supports_lazy_refcounts
-
(* What should the output format be? If the user specified an
* input format, use that, else detect it from the source image.
*)
@@ -298,32 +260,13 @@ let overlaydisk unlink_on_exit tmp;
(* Create it with the indisk as the backing file. *)
- let cmd - let options - let backing_file_option - [sprintf
"backing_file=%s" (replace_str indisk "," ",,")]
in
- let backing_fmt_option - match format with
- | None -> []
- | Some fmt -> [sprintf "backing_fmt=%s" fmt] in
- let compat11 - if qemu_img_supports_compat11 then
["compat=1.1"] else [] in
- let lazy_refcounts - if qemu_img_supports_lazy_refcounts then
- ["lazy_refcounts"]
- else [] in
- String.concat "," (
- backing_file_option @
- backing_fmt_option @
- compat11 @
- lazy_refcounts
- ) in
- sprintf "qemu-img create -f qcow2 -o %s %s > /dev/null"
- (Filename.quote options) (Filename.quote tmp) in
- if verbose then
- printf "%s\n%!" cmd;
- if Sys.command cmd <> 0 then
- error (f_"external command failed: %s") cmd;
+ (* XXX Old code used to:
+ * - detect if compat=1.1 was supported
+ * - add lazy_refcounts option
+ *)
+ (new G.guestfs ())#disk_create
+ ~backingfile:indisk ?backingformat:format ~compat:"1.1"
+ tmp "qcow2" Int64.minus_one;
tmp
--
1.8.4.2
Richard W.M. Jones
2014-Jan-28 16:24 UTC
[Libguestfs] [PATCH 10/10] virt-make-fs: Use disk-create API instead of calling qemu-img create.
Strictly speaking this reduces the number of formats that virt-make-fs
can output to, but it's likely that no one cares and if they do we can
add new formats in future.
---
tools/virt-make-fs | 44 ++++++--------------------------------------
1 file changed, 6 insertions(+), 38 deletions(-)
diff --git a/tools/virt-make-fs b/tools/virt-make-fs
index 605d067..f1cc09d 100755
--- a/tools/virt-make-fs
+++ b/tools/virt-make-fs
@@ -231,9 +231,6 @@ Choose the output disk image format.
The default is C<raw> (raw sparse disk image).
-For other choices, see the L<qemu-img(1)> manpage. The only other
-choice that would really make sense here is C<qcow2>.
-
=cut
my $type = "ext2";
@@ -425,46 +422,17 @@ if (!defined $size) {
$size = int ($size);
-# Create the output disk.
-#
-# Use qemu-img so we can control the output format, but capture any
-# output temporarily and only display it if the command fails.
-
-my @options = ();
-@options = ("-o", "preallocation=metadata") if $format eq
"qcow2";
-
-my @cmd = ("qemu-img", "create", "-f", $format,
@options, $output, $size);
-if ($debug) {
- print STDERR ("running: ", join (" ", @cmd),
"\n");
-}
-
-{
- my $tmpfh = tempfile ();
- my ($r, $oldout, $olderr);
-
- open $oldout, ">&STDOUT" or die __"cannot dup
STDOUT";
- open $olderr, ">&STDERR" or die __"cannot dup
STDERR";
- close STDOUT;
- close STDERR;
- open STDOUT, ">&", \$tmpfh or die __"cannot redirect
STDOUT";
- open STDERR, ">&", \$tmpfh or die __"cannot redirect
STDERR";
- $r = system (@cmd);
- open STDOUT, ">&", $oldout or die __"cannot restore
STDOUT";
- open STDERR, ">&", $olderr or die __"cannot restore
STDERR";
-
- unless ($r == 0) {
- print STDERR __"qemu-img create: failed to create disk
image:\n";
- seek $tmpfh, 0, SEEK_SET;
- print STDERR $_ while <$tmpfh>;
- die "\n";
- }
-}
-
eval {
print STDERR "starting libguestfs ...\n" if $debug;
# Run libguestfs.
my $g = Sys::Guestfs->new ();
+
+ # Create the output disk.
+ my %options = ();
+ $options{preallocation} = "metadata" if $format eq
"qcow2";
+ $g->disk_create ($output, $format, $size, %options);
+
$g->add_drive ($output, format => $format);
$g->launch ();
--
1.8.4.2
Pino Toscano
2014-Jan-28 16:53 UTC
Re: [Libguestfs] [PATCH 05/10] examples: Update various examples to use new disk-create API.
On Tuesday 28 January 2014 16:24:52 Richard W.M. Jones wrote:> --- a/ocaml/examples/create_disk.ml > +++ b/ocaml/examples/create_disk.ml > @@ -9,9 +9,7 @@ let () > let g = new Guestfs.guestfs () in > > (* Create a raw-format sparse disk image, 512 MB in size. *) > - let fd = openfile output [O_WRONLY;O_CREAT;O_TRUNC;O_NOCTTY] 0o666 in > - ftruncate fd (512 * 1024 * 1024); > - close fd; > + g#disk_create output "raw" 536870912L;Minor niptick: I'd leave the multiplication, as it was before and as the other examples do (easier to spot and to change). -- Pino Toscano
Apparently Analagous Threads
- [PATCH] lib: Autodetect backing format and specify it explicitly.
- Re: [PATCH] lib: Autodetect backing format and specify it explicitly.
- [PATCH v3] v2v: -o vdsm: Add --vdsm-compat flag.
- Re: [PATCH] lib: Autodetect backing format and specify it explicitly.
- [PATCH 0/2] Change guestfs__*