[libvirt] 'build' on FS pool now unconditionally formats?

Daniel P. Berrange berrange at redhat.com
Tue Mar 16 10:22:50 UTC 2010


On Mon, Mar 15, 2010 at 05:21:26PM -0400, Dave Allan wrote:
> 
> Now that 0.7.7 is done, we need to revisit fs pool building.
> 
> Because it is impossible to implement a check for arbitrary existing 
> data, the only safe option is to require the overwrite flag in all 
> cases.  If we do not require the flag in all cases, virt-manager and 
> virsh will format unknown partitions without providing any indication to 
> the user that a destructive operation is about to take place.  The only 
> input from the user will be the selection of the partition.  All other 
> instances of destructive behavior require explicit confirmation from the 
> user, or as Cole aptly put it, are loudly warned about by virt-manager. 
>  I wish that a safe alternative existed, but none does.

There are two alternatives that are safe

 1. Do a per filesystem magic check on the volume in question. libvirt has
    a list of filesystems that I knows about "ext2", "ext3", "ext4", 
    "ufs", "iso9660", "udf", "gfs", "gfs2", "vfat", "hfs+", "xfs", "ocfs2"
    All of these will have an easily identified magic header that could
    be positively checked for.

Or

 2. Do a check for the first 512 or 4096 bytes being all zeros. This should
    detect the absence of any filesystem AFAIK.

The semantics we should have for these APIs are

 - virStoragePoolBuild(flags=0)   - format the filesystem/volgroup/partition table
                                    only if not already formatted.
 - virStoragePoolBuild(flags=OVERWRITE) - unconditionally format
 - virStoragePoolDelete()         - wipe data such that Build(flags=0) is guaranteed
                                    to be successful next time.

So I see several things that need to be implemented

 - Make disk & logical  pool backends check for existing formatted data
 - Implement the 'Delete' operation for all pool types, 
 - Add (checked) formatting of filesystem pools
 - Add  OVERWRITE flag to disk, logical, filesystem pool types to skip the check

> The attached patch implements this behavior.

NACK in this form.

> From cf05596823881448725cd67094f39c136144683b Mon Sep 17 00:00:00 2001
> From: David Allan <dallan at redhat.com>
> Date: Mon, 15 Mar 2010 14:04:41 -0400
> Subject: [PATCH 1/1] Add fs pool formatting
> 
> * This patch reinstates pool formatting and adds a flag to enable overwriting of data.
> ---
>  configure.ac                     |    5 +++++
>  include/libvirt/libvirt.h.in     |    5 +++--
>  libvirt.spec.in                  |    2 ++
>  src/storage/storage_backend_fs.c |   34 +++++++++++++++++++++++++++++++++-
>  tools/virsh.c                    |    8 +++++++-
>  5 files changed, 50 insertions(+), 4 deletions(-)
> 
> diff --git a/configure.ac b/configure.ac
> index 654b9a8..3869f45 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -1300,12 +1300,15 @@ AM_CONDITIONAL([WITH_STORAGE_DIR], [test "$with_storage_dir" = "yes"])
>  if test "$with_storage_fs" = "yes" -o "$with_storage_fs" = "check"; then
>    AC_PATH_PROG([MOUNT], [mount], [], [$PATH:/sbin:/usr/sbin])
>    AC_PATH_PROG([UMOUNT], [umount], [], [$PATH:/sbin:/usr/sbin])
> +  AC_PATH_PROG([MKFS], [mkfs], [], [$PATH:/sbin:/usr/sbin])
>    if test "$with_storage_fs" = "yes" ; then
>      if test -z "$MOUNT" ; then AC_MSG_ERROR([We need mount for FS storage driver]) ; fi
>      if test -z "$UMOUNT" ; then AC_MSG_ERROR([We need umount for FS storage driver]) ; fi
> +    if test -z "$MKFS" ; then AC_MSG_ERROR([We need mkfs for FS storage driver]) ; fi
>    else
>      if test -z "$MOUNT" ; then with_storage_fs=no ; fi
>      if test -z "$UMOUNT" ; then with_storage_fs=no ; fi
> +    if test -z "$MKFS" ; then with_storage_fs=no ; fi
> 
>      if test "$with_storage_fs" = "check" ; then with_storage_fs=yes ; fi
>    fi
> @@ -1316,6 +1319,8 @@ if test "$with_storage_fs" = "yes" -o "$with_storage_fs" = "check"; then
>          [Location or name of the mount program])
>      AC_DEFINE_UNQUOTED([UMOUNT],["$UMOUNT"],
>          [Location or name of the mount program])
> +    AC_DEFINE_UNQUOTED([MKFS],["$MKFS"],
> +        [Location or name of the mkfs program])
>    fi
>  fi
>  AM_CONDITIONAL([WITH_STORAGE_FS], [test "$with_storage_fs" = "yes"])
> diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
> index 0d1b5b5..77e6b8d 100644
> --- a/include/libvirt/libvirt.h.in
> +++ b/include/libvirt/libvirt.h.in
> @@ -1052,8 +1052,9 @@ typedef enum {
> 
>  typedef enum {
>    VIR_STORAGE_POOL_BUILD_NEW  = 0,   /* Regular build from scratch */
> -  VIR_STORAGE_POOL_BUILD_REPAIR = 1, /* Repair / reinitialize */
> -  VIR_STORAGE_POOL_BUILD_RESIZE = 2  /* Extend existing pool */
> +  VIR_STORAGE_POOL_BUILD_REPAIR = (1 << 0), /* Repair / reinitialize */
> +  VIR_STORAGE_POOL_BUILD_RESIZE = (1 << 1),  /* Extend existing pool */
> +  VIR_STORAGE_POOL_BUILD_OVERWRITE = (1 << 2)  /* Overwrite data */
>  } virStoragePoolBuildFlags;
> 
>  typedef enum {
> diff --git a/libvirt.spec.in b/libvirt.spec.in
> index a54d546..c6e0678 100644
> --- a/libvirt.spec.in
> +++ b/libvirt.spec.in
> @@ -209,6 +209,8 @@ BuildRequires: util-linux
>  # For showmount in FS driver (netfs discovery)
>  BuildRequires: nfs-utils
>  Requires: nfs-utils
> +# For mkfs
> +Requires: util-linux
>  # For glusterfs
>  %if 0%{?fedora} >= 11
>  Requires: glusterfs-client >= 2.0.1
> diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
> index a83fc01..fe43af2 100644
> --- a/src/storage/storage_backend_fs.c
> +++ b/src/storage/storage_backend_fs.c
> @@ -45,6 +45,7 @@
>  #include "util.h"
>  #include "memory.h"
>  #include "xml.h"
> +#include "logging.h"
> 
>  #define VIR_FROM_THIS VIR_FROM_STORAGE
> 
> @@ -498,8 +499,9 @@ virStorageBackendFileSystemStart(virConnectPtr conn ATTRIBUTE_UNUSED,
>  static int
>  virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED,
>                                   virStoragePoolObjPtr pool,
> -                                 unsigned int flags ATTRIBUTE_UNUSED)
> +                                 unsigned int flags)
>  {
> +    const char *mkfsargv[5], *device = NULL, *format = NULL;
>      int err, ret = -1;
>      char *parent;
>      char *p;
> @@ -552,6 +554,36 @@ virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED,
>              goto error;
>          }
>      }
> +
> +    if (flags & VIR_STORAGE_POOL_BUILD_OVERWRITE) {
> +
> +        if (pool->def->source.devices == NULL) {
> +            virStorageReportError(VIR_ERR_INVALID_ARG,
> +                                  _("No source device specified when formatting pool '%s'"),
> +                                  pool->def->name);
> +            goto error;
> +        }
> +
> +        device = pool->def->source.devices[0].path;
> +        format = virStoragePoolFormatFileSystemTypeToString(pool->def->source.format);
> +
> +        VIR_DEBUG("source device: '%s' format: '%s'", device, format);
> +
> +        mkfsargv[0] = MKFS;
> +        mkfsargv[1] = "-t";
> +        mkfsargv[2] = format;
> +        mkfsargv[3] = device;
> +        mkfsargv[4] = NULL;
> +
> +        if (virRun(mkfsargv, NULL) < 0) {
> +            virReportSystemError(errno,
> +                                 _("Failed to make filesystem of "
> +                                   "type '%s' on device '%s'"),
> +                                 format, device);
> +            goto error;
> +        }
> +    }
> +
>      ret = 0;
>  error:
>      VIR_FREE(parent);
> diff --git a/tools/virsh.c b/tools/virsh.c
> index aa85ee6..4b2e3e9 100644
> --- a/tools/virsh.c
> +++ b/tools/virsh.c
> @@ -4216,6 +4216,7 @@ static const vshCmdInfo info_pool_build[] = {
> 
>  static const vshCmdOptDef opts_pool_build[] = {
>      {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")},
> +    {"overwrite", VSH_OT_BOOL, 0, gettext_noop("overwrite existing data")},
>      {NULL, 0, 0, NULL}
>  };
> 
> @@ -4224,6 +4225,7 @@ cmdPoolBuild(vshControl *ctl, const vshCmd *cmd)
>  {
>      virStoragePoolPtr pool;
>      int ret = TRUE;
> +    int flags = 0;
>      char *name;
> 
>      if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
> @@ -4232,7 +4234,11 @@ cmdPoolBuild(vshControl *ctl, const vshCmd *cmd)
>      if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
>          return FALSE;
> 
> -    if (virStoragePoolBuild(pool, 0) == 0) {
> +    if (vshCommandOptBool (cmd, "overwrite")) {
> +        flags |= VIR_STORAGE_POOL_BUILD_OVERWRITE;
> +    }
> +
> +    if (virStoragePoolBuild(pool, flags) == 0) {
>          vshPrint(ctl, _("Pool %s built\n"), name);
>      } else {
>          vshError(ctl, _("Failed to build pool %s"), name);
> -- 
> 1.6.5.5
> 

Daniel
-- 
|: Red Hat, Engineering, London    -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :|
|: http://autobuild.org        -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-   F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list