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(a)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 :|