[libvirt] Add filesystem pool formatting (v4)

This patch series are based on Dave Allan's previous posts: https://www.redhat.com/archives/libvir-list/2010-June/msg00040.html I rebased them and make changes per last feedback from Eric, and also other some small changes. <QUOTE> The following patches add the ability to format filesystem pools when the appropriate flags are passed to pool build. As before, I have implemented two new flags: VIR_STORAGE_POOL_BUILD_NO_OVERWRITE causes the build to probe for an existing pool of the requested type. The build operation formats the filesystem if it does not find an existing filesystem of that type. VIR_STORAGE_POOL_BUILD_OVERWRITE causes the build to format unconditionally. These patches incorporate all the feedback received on earlier versions. The incremental is pretty unhelpful, so these are complete replacement patches. Dave </QUOTE>

New changes: * Define LIBBLKID_REQUIRED, which is missed in previous posts. * Remove libblkid requires per Eric's feedback. --- configure.ac | 26 ++++++++++++++++++++++++++ libvirt.spec.in | 4 ++++ src/Makefile.am | 4 ++++ 3 files changed, 34 insertions(+), 0 deletions(-) diff --git a/configure.ac b/configure.ac index 190bf40..184236c 100644 --- a/configure.ac +++ b/configure.ac @@ -68,6 +68,7 @@ DEVMAPPER_REQUIRED=1.0.0 LIBCURL_REQUIRED="7.18.0" LIBPCAP_REQUIRED="1.0.0" LIBNL_REQUIRED="1.1" +LIBBLKID_REQUIRED="2.18" dnl Checks for C compiler. AC_PROG_CC @@ -1593,12 +1594,15 @@ fi if test "$with_storage_fs" = "yes" || test "$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 @@ -1609,6 +1613,8 @@ if test "$with_storage_fs" = "yes" || test "$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"]) @@ -2238,6 +2244,26 @@ if test "$with_nwfilter" = "yes" ; then fi AM_CONDITIONAL([WITH_NWFILTER], [test "$with_nwfilter" = "yes"]) +dnl libblkid is used by several storage drivers; therefore we probe +dnl for it unconditionally. +AC_ARG_WITH([libblkid], + [AS_HELP_STRING([--with-libblkid], + [use libblkid to scan for filesystems and partitions @<:@default=check@:>@])], + [], + [with_libblkid=check]) + +if test "x$with_libblkid" = "xyes" || test "x$with_libblkid" = "xcheck"; then + PKG_CHECK_MODULES([BLKID], + [blkid >= $LIBBLKID_REQUIRED], + [with_libblkid="yes"], + [with_libblkid="no"]) +fi + +if test "x$with_libblkid" = "xyes"; then + AC_DEFINE([HAVE_LIBBLKID], [1], [libblkid is present]) +fi +AM_CONDITIONAL([HAVE_LIBBLKID], [test "x$with_libblkid" = "xyes"]) + AC_ARG_WITH([qemu-user], AC_HELP_STRING([--with-qemu-user], [username to run QEMU system instance as @<:@default=root@:>@]), [QEMU_USER=${withval}], diff --git a/libvirt.spec.in b/libvirt.spec.in index 4162fba..88f65da 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -265,6 +265,10 @@ Requires: PolicyKit >= 0.6 %endif %if %{with_storage_fs} Requires: nfs-utils +# For mkfs +Requires: nfs-utils +# For pool-build probing for existing pools +BuildRequires: libblkid-devel >= 2.17 # For glusterfs %if 0%{?fedora} >= 11 Requires: glusterfs-client >= 2.0.1 diff --git a/src/Makefile.am b/src/Makefile.am index 3649106..f6cb52d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -900,6 +900,10 @@ if WITH_DRIVER_MODULES libvirt_driver_storage_la_LIBADD += ../gnulib/lib/libgnu.la libvirt_driver_storage_la_LDFLAGS += -module -avoid-version endif +if HAVE_LIBBLKID +libvirt_driver_storage_la_CFLAGS += $(BLKID_CFLAGS) +libvirt_driver_storage_la_LIBADD += $(BLKID_LIBS) +endif libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_SOURCES) libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_FS_SOURCES) endif -- 1.7.4

Previous description from Dave Allan. <QUOTE> This patch adds the ability to make the filesystem for a filesystem pool during a pool build. The patch adds two new flags, no overwrite and overwrite, to control when mkfs gets executed. By default, the patch preserves the current behavior, i.e., if no flags are specified, pool build on a filesystem pool only makes the directory on which the filesystem will be mounted. If the no overwrite flag is specified, the target device is checked to determine if a filesystem of the type specified in the pool is present. If a filesystem of that type is already present, mkfs is not executed and the build call returns an error. Otherwise, mkfs is executed and any data present on the device is overwritten. If the overwrite flag is specified, mkfs is always executed, and any existing data on the target device is overwritten unconditionally. Changes per feedback from eblake: * Made probe & overwrite flags exclusive * Changed LDFLAGS to LIBADD in Makefile.am * Added missing virCheckFlags() * Fixed copyright dates * Removed cast of char * passed to libblkid and replaced it with a strdup'd copy * Changed flags to an unsigned int in virsh.c Changes per feedback from Dan B. * Changed probe flag to no-overwrite * Moved libblkid probe code into storage_backend_fs.c </QUOTE> New changes: (per last feedback from Eric) * s/VIR_STORAGE_POOL_PROBE_BUILT/VIR_STORAGE_POOL_BUILT/ * Remove the internal function exporting in libvirt_private.syms * Correct wonky spacing --- include/libvirt/libvirt.h.in | 6 +- include/libvirt/virterror.h | 2 + src/libvirt.c | 5 +- src/storage/storage_backend_fs.c | 191 +++++++++++++++++++++++++++++++++++++- src/storage/storage_backend_fs.h | 7 ++ src/util/virterror.c | 64 ++++++++----- 6 files changed, 242 insertions(+), 33 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index d765412..e43c98a 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1335,8 +1335,10 @@ 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_NO_OVERWRITE = (1 << 2), /* Do not overwrite existing pool */ + VIR_STORAGE_POOL_BUILD_OVERWRITE = (1 << 3), /* Overwrite data */ } virStoragePoolBuildFlags; typedef enum { diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 0708e02..33fbe9a 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -231,6 +231,8 @@ typedef enum { VIR_ERR_INVALID_DOMAIN_SNAPSHOT = 71,/* invalid domain snapshot */ VIR_ERR_NO_DOMAIN_SNAPSHOT = 72, /* domain snapshot not found */ VIR_ERR_INVALID_STREAM = 73, /* stream pointer not valid */ + VIR_ERR_STORAGE_PROBE_FAILED = 74, /* storage pool proble failed */ + VIR_ERR_STORAGE_POOL_BUILT = 75, /* storage pool already built */ } virErrorNumber; /** diff --git a/src/libvirt.c b/src/libvirt.c index dde4bd4..03d870b 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -8001,7 +8001,10 @@ error: /** * virStoragePoolBuild: * @pool: pointer to storage pool - * @flags: future flags, use 0 for now + * @flags: flags to control pool build behaviour + * + * Currently only filesystem pool accepts flags VIR_STORAGE_POOL_BUILD_OVERWRITE + * and VIR_STORAGE_POOL_BUILD_NO_OVERWRITE. * * Build the underlying storage pool * diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c index 0a6b074..54afa7c 100644 --- a/src/storage/storage_backend_fs.c +++ b/src/storage/storage_backend_fs.c @@ -33,6 +33,10 @@ #include <unistd.h> #include <string.h> +#if HAVE_LIBBLKID +# include <blkid/blkid.h> +#endif + #include <libxml/parser.h> #include <libxml/tree.h> #include <libxml/xpath.h> @@ -45,6 +49,7 @@ #include "memory.h" #include "xml.h" #include "files.h" +#include "logging.h" #define VIR_FROM_THIS VIR_FROM_STORAGE @@ -533,13 +538,173 @@ virStorageBackendFileSystemStart(virConnectPtr conn ATTRIBUTE_UNUSED, } #endif /* WITH_STORAGE_FS */ +#if HAVE_LIBBLKID +static virStoragePoolProbeResult +virStorageBackendFileSystemProbe(const char *device, + const char *format) { + + virStoragePoolProbeResult ret = FILESYSTEM_PROBE_ERROR; + blkid_probe probe = NULL; + const char *fstype = NULL; + char *names[2], *libblkid_format = NULL; + + VIR_DEBUG("Probing for existing filesystem of type %s on device %s", + format, device); + + if (blkid_known_fstype(format) == 0) { + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, + _("Not capable of probing for " + "filesystem of type %s"), + format); + goto error; + } + + probe = blkid_new_probe_from_filename(device); + if (probe == NULL) { + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, + _("Failed to create filesystem probe " + "for device %s"), + device); + goto error; + } + + if ((libblkid_format = strdup(format)) == NULL) { + virReportOOMError(); + goto error; + } + + names[0] = libblkid_format; + names[1] = NULL; + + blkid_probe_filter_superblocks_type(probe, + BLKID_FLTR_ONLYIN, + names); + + if (blkid_do_probe(probe) != 0) { + VIR_INFO("No filesystem of type '%s' found on device '%s'", + format, device); + ret = FILESYSTEM_PROBE_NOT_FOUND; + } else if (blkid_probe_lookup_value(probe, "TYPE", &fstype, NULL) == 0) { + virStorageReportError(VIR_ERR_STORAGE_POOL_BUILT, + _("Existing filesystem of type '%s' found on " + "device '%s'"), + fstype, device); + ret = FILESYSTEM_PROBE_FOUND; + } + + if (blkid_do_probe(probe) != 1) { + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, + _("Found additional probes to run, " + "filesystem probing may be incorrect")); + ret = FILESYSTEM_PROBE_ERROR; + } + +error: + VIR_FREE(libblkid_format); + + if (probe != NULL) { + blkid_free_probe(probe); + } + + return ret; +} + +#else /* #if HAVE_LIBBLKID */ + +static virStoragePoolProbeResult +virStorageBackendFileSystemProbe(const char *device ATTRIBUTE_UNUSED, + const char *format ATTRIBUTE_UNUSED) +{ + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("probing for filesystems is unsupported " + "by this build")); + + return FILESYSTEM_PROBE_ERROR; +} + +#endif /* #if HAVE_LIBBLKID */ + +static int +virStorageBackendExecuteMKFS(const char *device, + const char *format) +{ + int ret = 0; + const char *mkfsargv[5] = { MKFS, + "-t", + format, + device, + NULL }; + + if (virRun(mkfsargv, NULL) < 0) { + virReportSystemError(errno, + _("Failed to make filesystem of " + "type '%s' on device '%s'"), + format, device); + ret = -1; + } + + return ret; +} + + +static int +virStorageBackendMakeFileSystem(virStoragePoolObjPtr pool, + unsigned int flags) +{ + const char *device = NULL, *format = NULL; + bool ok_to_mkfs = false; + int ret = -1; + + if (pool->def->source.devices == NULL) { + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("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); + + if (!virFileExists(device)) { + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("Source device does not exist when formatting pool '%s'"), + pool->def->name); + goto error; + } + + if (flags & VIR_STORAGE_POOL_BUILD_OVERWRITE) { + ok_to_mkfs = true; + } else if (flags & VIR_STORAGE_POOL_BUILD_NO_OVERWRITE && + virStorageBackendFileSystemProbe(device, format) == + FILESYSTEM_PROBE_NOT_FOUND) { + ok_to_mkfs = true; + } + + if (ok_to_mkfs) { + ret = virStorageBackendExecuteMKFS(device, format); + } + +error: + return ret; +} + + /** * @conn connection to report errors against * @pool storage pool to build + * @flags controls the pool formating behaviour * * Build a directory or FS based storage pool. * + * If no flag is set, it only makes the directory; If + * VIR_STORAGE_POOL_BUILD_NO_OVERWRITE set, it probes to determine if + * a filesystem already exists on the target device, returning an error + * if exists, or using mkfs to format the target device if not; If + * VIR_STORAGE_POOL_BUILD_OVERWRITE is set, mkfs is always executed, + * any existed data on the target device is overwritten unconditionally. + * * - If it is a FS based pool, mounts the unlying source device on the pool * * Returns 0 on success, -1 on error @@ -547,11 +712,23 @@ virStorageBackendFileSystemStart(virConnectPtr conn ATTRIBUTE_UNUSED, static int virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool, - unsigned int flags ATTRIBUTE_UNUSED) + unsigned int flags) { int err, ret = -1; - char *parent; - char *p; + char *parent = NULL; + char *p = NULL; + + virCheckFlags(VIR_STORAGE_POOL_BUILD_OVERWRITE | + VIR_STORAGE_POOL_BUILD_NO_OVERWRITE, ret); + + if (flags == (VIR_STORAGE_POOL_BUILD_OVERWRITE | + VIR_STORAGE_POOL_BUILD_NO_OVERWRITE)) { + + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("Overwrite and no overwrite flags" + " are mutually exclusive")); + goto error; + } if ((parent = strdup(pool->def->target.path)) == NULL) { virReportOOMError(); @@ -601,7 +778,13 @@ virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED, goto error; } } - ret = 0; + + if (flags != 0) { + ret = virStorageBackendMakeFileSystem(pool, flags); + } else { + ret = 0; + } + error: VIR_FREE(parent); return ret; diff --git a/src/storage/storage_backend_fs.h b/src/storage/storage_backend_fs.h index 7def53e..394e552 100644 --- a/src/storage/storage_backend_fs.h +++ b/src/storage/storage_backend_fs.h @@ -29,6 +29,13 @@ # if WITH_STORAGE_FS extern virStorageBackend virStorageBackendFileSystem; extern virStorageBackend virStorageBackendNetFileSystem; + +typedef enum { + FILESYSTEM_PROBE_FOUND, + FILESYSTEM_PROBE_NOT_FOUND, + FILESYSTEM_PROBE_ERROR, +} virStoragePoolProbeResult; + # endif extern virStorageBackend virStorageBackendDirectory; diff --git a/src/util/virterror.c b/src/util/virterror.c index b7d8924..4450a43 100644 --- a/src/util/virterror.c +++ b/src/util/virterror.c @@ -1041,63 +1041,75 @@ virErrorMsg(virErrorNumber error, const char *info) break; case VIR_ERR_NO_STORAGE_POOL: if (info == NULL) - errmsg = _("Storage pool not found"); + errmsg = _("Storage pool not found"); else - errmsg = _("Storage pool not found: %s"); + errmsg = _("Storage pool not found: %s"); break; case VIR_ERR_NO_STORAGE_VOL: if (info == NULL) - errmsg = _("Storage volume not found"); + errmsg = _("Storage volume not found"); else - errmsg = _("Storage volume not found: %s"); + errmsg = _("Storage volume not found: %s"); + break; + case VIR_ERR_STORAGE_PROBE_FAILED: + if (info == NULL) + errmsg = _("Storage pool probe failed"); + else + errmsg = _("Storage pool probe failed: %s"); + break; + case VIR_ERR_STORAGE_POOL_BUILT: + if (info == NULL) + errmsg = _("Storage pool already built"); + else + errmsg = _("Storage pool already built: %s"); break; case VIR_ERR_INVALID_STORAGE_POOL: if (info == NULL) - errmsg = _("invalid storage pool pointer in"); + errmsg = _("invalid storage pool pointer in"); else - errmsg = _("invalid storage pool pointer in %s"); + errmsg = _("invalid storage pool pointer in %s"); break; case VIR_ERR_INVALID_STORAGE_VOL: if (info == NULL) - errmsg = _("invalid storage volume pointer in"); + errmsg = _("invalid storage volume pointer in"); else - errmsg = _("invalid storage volume pointer in %s"); + errmsg = _("invalid storage volume pointer in %s"); break; case VIR_WAR_NO_STORAGE: if (info == NULL) - errmsg = _("Failed to find a storage driver"); + errmsg = _("Failed to find a storage driver"); else - errmsg = _("Failed to find a storage driver: %s"); + errmsg = _("Failed to find a storage driver: %s"); break; case VIR_WAR_NO_NODE: if (info == NULL) - errmsg = _("Failed to find a node driver"); + errmsg = _("Failed to find a node driver"); else - errmsg = _("Failed to find a node driver: %s"); + errmsg = _("Failed to find a node driver: %s"); break; case VIR_ERR_INVALID_NODE_DEVICE: if (info == NULL) - errmsg = _("invalid node device pointer"); + errmsg = _("invalid node device pointer"); else - errmsg = _("invalid node device pointer in %s"); + errmsg = _("invalid node device pointer in %s"); break; case VIR_ERR_NO_NODE_DEVICE: if (info == NULL) - errmsg = _("Node device not found"); + errmsg = _("Node device not found"); else - errmsg = _("Node device not found: %s"); + errmsg = _("Node device not found: %s"); break; case VIR_ERR_NO_SECURITY_MODEL: if (info == NULL) - errmsg = _("Security model not found"); + errmsg = _("Security model not found"); else - errmsg = _("Security model not found: %s"); + errmsg = _("Security model not found: %s"); break; case VIR_ERR_OPERATION_INVALID: if (info == NULL) - errmsg = _("Requested operation is not valid"); + errmsg = _("Requested operation is not valid"); else - errmsg = _("Requested operation is not valid: %s"); + errmsg = _("Requested operation is not valid: %s"); break; case VIR_WAR_NO_INTERFACE: if (info == NULL) @@ -1149,21 +1161,21 @@ virErrorMsg(virErrorNumber error, const char *info) break; case VIR_ERR_INVALID_NWFILTER: if (info == NULL) - errmsg = _("Invalid network filter"); + errmsg = _("Invalid network filter"); else - errmsg = _("Invalid network filter: %s"); + errmsg = _("Invalid network filter: %s"); break; case VIR_ERR_NO_NWFILTER: if (info == NULL) - errmsg = _("Network filter not found"); + errmsg = _("Network filter not found"); else - errmsg = _("Network filter not found: %s"); + errmsg = _("Network filter not found: %s"); break; case VIR_ERR_BUILD_FIREWALL: if (info == NULL) - errmsg = _("Error while building firewall"); + errmsg = _("Error while building firewall"); else - errmsg = _("Error while building firewall: %s"); + errmsg = _("Error while building firewall: %s"); break; case VIR_ERR_CONFIG_UNSUPPORTED: if (info == NULL) -- 1.7.4

于 2011年04月08日 16:51, Osier Yang 写道:
Previous description from Dave Allan.
<QUOTE> This patch adds the ability to make the filesystem for a filesystem pool during a pool build.
The patch adds two new flags, no overwrite and overwrite, to control when mkfs gets executed. By default, the patch preserves the current behavior, i.e., if no flags are specified, pool build on a filesystem pool only makes the directory on which the filesystem will be mounted.
If the no overwrite flag is specified, the target device is checked to determine if a filesystem of the type specified in the pool is present. If a filesystem of that type is already present, mkfs is not executed and the build call returns an error. Otherwise, mkfs is executed and any data present on the device is overwritten.
If the overwrite flag is specified, mkfs is always executed, and any existing data on the target device is overwritten unconditionally.
Changes per feedback from eblake: * Made probe& overwrite flags exclusive * Changed LDFLAGS to LIBADD in Makefile.am * Added missing virCheckFlags() * Fixed copyright dates * Removed cast of char * passed to libblkid and replaced it with a strdup'd copy * Changed flags to an unsigned int in virsh.c
Changes per feedback from Dan B. * Changed probe flag to no-overwrite * Moved libblkid probe code into storage_backend_fs.c </QUOTE>
New changes: (per last feedback from Eric) * s/VIR_STORAGE_POOL_PROBE_BUILT/VIR_STORAGE_POOL_BUILT/ * Remove the internal function exporting in libvirt_private.syms * Correct wonky spacing
--- include/libvirt/libvirt.h.in | 6 +- include/libvirt/virterror.h | 2 + src/libvirt.c | 5 +- src/storage/storage_backend_fs.c | 191 +++++++++++++++++++++++++++++++++++++- src/storage/storage_backend_fs.h | 7 ++ src/util/virterror.c | 64 ++++++++----- 6 files changed, 242 insertions(+), 33 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index d765412..e43c98a 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1335,8 +1335,10 @@ 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_NO_OVERWRITE = (1<< 2), /* Do not overwrite existing pool */ + VIR_STORAGE_POOL_BUILD_OVERWRITE = (1<< 3), /* Overwrite data */ } virStoragePoolBuildFlags;
typedef enum { diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 0708e02..33fbe9a 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -231,6 +231,8 @@ typedef enum { VIR_ERR_INVALID_DOMAIN_SNAPSHOT = 71,/* invalid domain snapshot */ VIR_ERR_NO_DOMAIN_SNAPSHOT = 72, /* domain snapshot not found */ VIR_ERR_INVALID_STREAM = 73, /* stream pointer not valid */ + VIR_ERR_STORAGE_PROBE_FAILED = 74, /* storage pool proble failed */ + VIR_ERR_STORAGE_POOL_BUILT = 75, /* storage pool already built */ } virErrorNumber;
/** diff --git a/src/libvirt.c b/src/libvirt.c index dde4bd4..03d870b 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -8001,7 +8001,10 @@ error: /** * virStoragePoolBuild: * @pool: pointer to storage pool - * @flags: future flags, use 0 for now + * @flags: flags to control pool build behaviour + * + * Currently only filesystem pool accepts flags VIR_STORAGE_POOL_BUILD_OVERWRITE + * and VIR_STORAGE_POOL_BUILD_NO_OVERWRITE. * * Build the underlying storage pool * diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c index 0a6b074..54afa7c 100644 --- a/src/storage/storage_backend_fs.c +++ b/src/storage/storage_backend_fs.c @@ -33,6 +33,10 @@ #include<unistd.h> #include<string.h>
+#if HAVE_LIBBLKID +# include<blkid/blkid.h> +#endif + #include<libxml/parser.h> #include<libxml/tree.h> #include<libxml/xpath.h> @@ -45,6 +49,7 @@ #include "memory.h" #include "xml.h" #include "files.h" +#include "logging.h"
#define VIR_FROM_THIS VIR_FROM_STORAGE
@@ -533,13 +538,173 @@ virStorageBackendFileSystemStart(virConnectPtr conn ATTRIBUTE_UNUSED, } #endif /* WITH_STORAGE_FS */
+#if HAVE_LIBBLKID +static virStoragePoolProbeResult +virStorageBackendFileSystemProbe(const char *device, + const char *format) { + + virStoragePoolProbeResult ret = FILESYSTEM_PROBE_ERROR; + blkid_probe probe = NULL; + const char *fstype = NULL; + char *names[2], *libblkid_format = NULL; + + VIR_DEBUG("Probing for existing filesystem of type %s on device %s", + format, device); + + if (blkid_known_fstype(format) == 0) { + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, + _("Not capable of probing for " + "filesystem of type %s"), + format); + goto error; + } + + probe = blkid_new_probe_from_filename(device); + if (probe == NULL) { + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, + _("Failed to create filesystem probe " + "for device %s"), + device); + goto error; + } + + if ((libblkid_format = strdup(format)) == NULL) { + virReportOOMError(); + goto error; + } + + names[0] = libblkid_format; + names[1] = NULL; + + blkid_probe_filter_superblocks_type(probe, + BLKID_FLTR_ONLYIN, + names); + + if (blkid_do_probe(probe) != 0) { + VIR_INFO("No filesystem of type '%s' found on device '%s'", + format, device); + ret = FILESYSTEM_PROBE_NOT_FOUND; + } else if (blkid_probe_lookup_value(probe, "TYPE",&fstype, NULL) == 0) { + virStorageReportError(VIR_ERR_STORAGE_POOL_BUILT, + _("Existing filesystem of type '%s' found on " + "device '%s'"), + fstype, device); + ret = FILESYSTEM_PROBE_FOUND; + } + + if (blkid_do_probe(probe) != 1) { + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, + _("Found additional probes to run, " + "filesystem probing may be incorrect")); + ret = FILESYSTEM_PROBE_ERROR; + } + +error: + VIR_FREE(libblkid_format); + + if (probe != NULL) { + blkid_free_probe(probe); + } + + return ret; +} + +#else /* #if HAVE_LIBBLKID */ + +static virStoragePoolProbeResult +virStorageBackendFileSystemProbe(const char *device ATTRIBUTE_UNUSED, + const char *format ATTRIBUTE_UNUSED) +{ + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("probing for filesystems is unsupported " + "by this build")); + + return FILESYSTEM_PROBE_ERROR; +} + +#endif /* #if HAVE_LIBBLKID */ + +static int +virStorageBackendExecuteMKFS(const char *device, + const char *format) +{ + int ret = 0; + const char *mkfsargv[5] = { MKFS, + "-t", + format, + device, + NULL };
Ah, I kept in my mind to change this to virCommandRun, but forgot finally.
+ + if (virRun(mkfsargv, NULL)< 0) { + virReportSystemError(errno, + _("Failed to make filesystem of " + "type '%s' on device '%s'"), + format, device); + ret = -1; + } + + return ret; +} + + +static int +virStorageBackendMakeFileSystem(virStoragePoolObjPtr pool, + unsigned int flags) +{ + const char *device = NULL, *format = NULL; + bool ok_to_mkfs = false; + int ret = -1; + + if (pool->def->source.devices == NULL) { + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("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); + + if (!virFileExists(device)) { + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("Source device does not exist when formatting pool '%s'"), + pool->def->name); + goto error; + } + + if (flags& VIR_STORAGE_POOL_BUILD_OVERWRITE) { + ok_to_mkfs = true; + } else if (flags& VIR_STORAGE_POOL_BUILD_NO_OVERWRITE&& + virStorageBackendFileSystemProbe(device, format) == + FILESYSTEM_PROBE_NOT_FOUND) { + ok_to_mkfs = true; + } + + if (ok_to_mkfs) { + ret = virStorageBackendExecuteMKFS(device, format); + } + +error: + return ret; +} + +
/** * @conn connection to report errors against * @pool storage pool to build + * @flags controls the pool formating behaviour * * Build a directory or FS based storage pool. * + * If no flag is set, it only makes the directory; If + * VIR_STORAGE_POOL_BUILD_NO_OVERWRITE set, it probes to determine if + * a filesystem already exists on the target device, returning an error + * if exists, or using mkfs to format the target device if not; If + * VIR_STORAGE_POOL_BUILD_OVERWRITE is set, mkfs is always executed, + * any existed data on the target device is overwritten unconditionally. + * * - If it is a FS based pool, mounts the unlying source device on the pool * * Returns 0 on success, -1 on error @@ -547,11 +712,23 @@ virStorageBackendFileSystemStart(virConnectPtr conn ATTRIBUTE_UNUSED, static int virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool, - unsigned int flags ATTRIBUTE_UNUSED) + unsigned int flags) { int err, ret = -1; - char *parent; - char *p; + char *parent = NULL; + char *p = NULL; + + virCheckFlags(VIR_STORAGE_POOL_BUILD_OVERWRITE | + VIR_STORAGE_POOL_BUILD_NO_OVERWRITE, ret); + + if (flags == (VIR_STORAGE_POOL_BUILD_OVERWRITE | + VIR_STORAGE_POOL_BUILD_NO_OVERWRITE)) { + + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("Overwrite and no overwrite flags" + " are mutually exclusive")); + goto error; + }
if ((parent = strdup(pool->def->target.path)) == NULL) { virReportOOMError(); @@ -601,7 +778,13 @@ virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED, goto error; } } - ret = 0; + + if (flags != 0) { + ret = virStorageBackendMakeFileSystem(pool, flags); + } else { + ret = 0; + } + error: VIR_FREE(parent); return ret; diff --git a/src/storage/storage_backend_fs.h b/src/storage/storage_backend_fs.h index 7def53e..394e552 100644 --- a/src/storage/storage_backend_fs.h +++ b/src/storage/storage_backend_fs.h @@ -29,6 +29,13 @@ # if WITH_STORAGE_FS extern virStorageBackend virStorageBackendFileSystem; extern virStorageBackend virStorageBackendNetFileSystem; + +typedef enum { + FILESYSTEM_PROBE_FOUND, + FILESYSTEM_PROBE_NOT_FOUND, + FILESYSTEM_PROBE_ERROR, +} virStoragePoolProbeResult; + # endif extern virStorageBackend virStorageBackendDirectory;
diff --git a/src/util/virterror.c b/src/util/virterror.c index b7d8924..4450a43 100644 --- a/src/util/virterror.c +++ b/src/util/virterror.c @@ -1041,63 +1041,75 @@ virErrorMsg(virErrorNumber error, const char *info) break; case VIR_ERR_NO_STORAGE_POOL: if (info == NULL) - errmsg = _("Storage pool not found"); + errmsg = _("Storage pool not found"); else - errmsg = _("Storage pool not found: %s"); + errmsg = _("Storage pool not found: %s"); break; case VIR_ERR_NO_STORAGE_VOL: if (info == NULL) - errmsg = _("Storage volume not found"); + errmsg = _("Storage volume not found"); else - errmsg = _("Storage volume not found: %s"); + errmsg = _("Storage volume not found: %s"); + break; + case VIR_ERR_STORAGE_PROBE_FAILED: + if (info == NULL) + errmsg = _("Storage pool probe failed"); + else + errmsg = _("Storage pool probe failed: %s"); + break; + case VIR_ERR_STORAGE_POOL_BUILT: + if (info == NULL) + errmsg = _("Storage pool already built"); + else + errmsg = _("Storage pool already built: %s"); break; case VIR_ERR_INVALID_STORAGE_POOL: if (info == NULL) - errmsg = _("invalid storage pool pointer in"); + errmsg = _("invalid storage pool pointer in"); else - errmsg = _("invalid storage pool pointer in %s"); + errmsg = _("invalid storage pool pointer in %s"); break; case VIR_ERR_INVALID_STORAGE_VOL: if (info == NULL) - errmsg = _("invalid storage volume pointer in"); + errmsg = _("invalid storage volume pointer in"); else - errmsg = _("invalid storage volume pointer in %s"); + errmsg = _("invalid storage volume pointer in %s"); break; case VIR_WAR_NO_STORAGE: if (info == NULL) - errmsg = _("Failed to find a storage driver"); + errmsg = _("Failed to find a storage driver"); else - errmsg = _("Failed to find a storage driver: %s"); + errmsg = _("Failed to find a storage driver: %s"); break; case VIR_WAR_NO_NODE: if (info == NULL) - errmsg = _("Failed to find a node driver"); + errmsg = _("Failed to find a node driver"); else - errmsg = _("Failed to find a node driver: %s"); + errmsg = _("Failed to find a node driver: %s"); break; case VIR_ERR_INVALID_NODE_DEVICE: if (info == NULL) - errmsg = _("invalid node device pointer"); + errmsg = _("invalid node device pointer"); else - errmsg = _("invalid node device pointer in %s"); + errmsg = _("invalid node device pointer in %s"); break; case VIR_ERR_NO_NODE_DEVICE: if (info == NULL) - errmsg = _("Node device not found"); + errmsg = _("Node device not found"); else - errmsg = _("Node device not found: %s"); + errmsg = _("Node device not found: %s"); break; case VIR_ERR_NO_SECURITY_MODEL: if (info == NULL) - errmsg = _("Security model not found"); + errmsg = _("Security model not found"); else - errmsg = _("Security model not found: %s"); + errmsg = _("Security model not found: %s"); break; case VIR_ERR_OPERATION_INVALID: if (info == NULL) - errmsg = _("Requested operation is not valid"); + errmsg = _("Requested operation is not valid"); else - errmsg = _("Requested operation is not valid: %s"); + errmsg = _("Requested operation is not valid: %s"); break; case VIR_WAR_NO_INTERFACE: if (info == NULL) @@ -1149,21 +1161,21 @@ virErrorMsg(virErrorNumber error, const char *info) break; case VIR_ERR_INVALID_NWFILTER: if (info == NULL) - errmsg = _("Invalid network filter"); + errmsg = _("Invalid network filter"); else - errmsg = _("Invalid network filter: %s"); + errmsg = _("Invalid network filter: %s"); break; case VIR_ERR_NO_NWFILTER: if (info == NULL) - errmsg = _("Network filter not found"); + errmsg = _("Network filter not found"); else - errmsg = _("Network filter not found: %s"); + errmsg = _("Network filter not found: %s"); break; case VIR_ERR_BUILD_FIREWALL: if (info == NULL) - errmsg = _("Error while building firewall"); + errmsg = _("Error while building firewall"); else - errmsg = _("Error while building firewall: %s"); + errmsg = _("Error while building firewall: %s"); break; case VIR_ERR_CONFIG_UNSUPPORTED: if (info == NULL)

Previous description from Dave Allan. <QUOTE> This patch adds the ability to make the filesystem for a filesystem pool during a pool build. The patch adds two new flags, no overwrite and overwrite, to control when mkfs gets executed. By default, the patch preserves the current behavior, i.e., if no flags are specified, pool build on a filesystem pool only makes the directory on which the filesystem will be mounted. If the no overwrite flag is specified, the target device is checked to determine if a filesystem of the type specified in the pool is present. If a filesystem of that type is already present, mkfs is not executed and the build call returns an error. Otherwise, mkfs is executed and any data present on the device is overwritten. If the overwrite flag is specified, mkfs is always executed, and any existing data on the target device is overwritten unconditionally. Changes per feedback from eblake: * Made probe & overwrite flags exclusive * Changed LDFLAGS to LIBADD in Makefile.am * Added missing virCheckFlags() * Fixed copyright dates * Removed cast of char * passed to libblkid and replaced it with a strdup'd copy * Changed flags to an unsigned int in virsh.c Changes per feedback from Dan B. * Changed probe flag to no-overwrite * Moved libblkid probe code into storage_backend_fs.c </QUOTE> New changes: (per last feedback from Eric) * s/VIR_STORAGE_POOL_PROBE_BUILT/VIR_STORAGE_POOL_BUILT/ * Add virsh document * Remove the internal function exporting in libvirt_private.syms * Correct wonky spacing * use virCommand instead of array for the command. --- include/libvirt/libvirt.h.in | 6 +- include/libvirt/virterror.h | 2 + src/libvirt.c | 5 +- src/storage/storage_backend_fs.c | 194 +++++++++++++++++++++++++++++++++++++- src/storage/storage_backend_fs.h | 7 ++ src/util/virterror.c | 64 ++++++++----- 6 files changed, 245 insertions(+), 33 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index d765412..e43c98a 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1335,8 +1335,10 @@ 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_NO_OVERWRITE = (1 << 2), /* Do not overwrite existing pool */ + VIR_STORAGE_POOL_BUILD_OVERWRITE = (1 << 3), /* Overwrite data */ } virStoragePoolBuildFlags; typedef enum { diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 0708e02..33fbe9a 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -231,6 +231,8 @@ typedef enum { VIR_ERR_INVALID_DOMAIN_SNAPSHOT = 71,/* invalid domain snapshot */ VIR_ERR_NO_DOMAIN_SNAPSHOT = 72, /* domain snapshot not found */ VIR_ERR_INVALID_STREAM = 73, /* stream pointer not valid */ + VIR_ERR_STORAGE_PROBE_FAILED = 74, /* storage pool proble failed */ + VIR_ERR_STORAGE_POOL_BUILT = 75, /* storage pool already built */ } virErrorNumber; /** diff --git a/src/libvirt.c b/src/libvirt.c index dde4bd4..03d870b 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -8001,7 +8001,10 @@ error: /** * virStoragePoolBuild: * @pool: pointer to storage pool - * @flags: future flags, use 0 for now + * @flags: flags to control pool build behaviour + * + * Currently only filesystem pool accepts flags VIR_STORAGE_POOL_BUILD_OVERWRITE + * and VIR_STORAGE_POOL_BUILD_NO_OVERWRITE. * * Build the underlying storage pool * diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c index 0a6b074..d1c8794 100644 --- a/src/storage/storage_backend_fs.c +++ b/src/storage/storage_backend_fs.c @@ -33,6 +33,10 @@ #include <unistd.h> #include <string.h> +#if HAVE_LIBBLKID +# include <blkid/blkid.h> +#endif + #include <libxml/parser.h> #include <libxml/tree.h> #include <libxml/xpath.h> @@ -45,6 +49,8 @@ #include "memory.h" #include "xml.h" #include "files.h" +#include "logging.h" +#include "command.h" #define VIR_FROM_THIS VIR_FROM_STORAGE @@ -533,13 +539,175 @@ virStorageBackendFileSystemStart(virConnectPtr conn ATTRIBUTE_UNUSED, } #endif /* WITH_STORAGE_FS */ +#if HAVE_LIBBLKID +static virStoragePoolProbeResult +virStorageBackendFileSystemProbe(const char *device, + const char *format) { + + virStoragePoolProbeResult ret = FILESYSTEM_PROBE_ERROR; + blkid_probe probe = NULL; + const char *fstype = NULL; + char *names[2], *libblkid_format = NULL; + + VIR_DEBUG("Probing for existing filesystem of type %s on device %s", + format, device); + + if (blkid_known_fstype(format) == 0) { + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, + _("Not capable of probing for " + "filesystem of type %s"), + format); + goto error; + } + + probe = blkid_new_probe_from_filename(device); + if (probe == NULL) { + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, + _("Failed to create filesystem probe " + "for device %s"), + device); + goto error; + } + + if ((libblkid_format = strdup(format)) == NULL) { + virReportOOMError(); + goto error; + } + + names[0] = libblkid_format; + names[1] = NULL; + + blkid_probe_filter_superblocks_type(probe, + BLKID_FLTR_ONLYIN, + names); + + if (blkid_do_probe(probe) != 0) { + VIR_INFO("No filesystem of type '%s' found on device '%s'", + format, device); + ret = FILESYSTEM_PROBE_NOT_FOUND; + } else if (blkid_probe_lookup_value(probe, "TYPE", &fstype, NULL) == 0) { + virStorageReportError(VIR_ERR_STORAGE_POOL_BUILT, + _("Existing filesystem of type '%s' found on " + "device '%s'"), + fstype, device); + ret = FILESYSTEM_PROBE_FOUND; + } + + if (blkid_do_probe(probe) != 1) { + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, + _("Found additional probes to run, " + "filesystem probing may be incorrect")); + ret = FILESYSTEM_PROBE_ERROR; + } + +error: + VIR_FREE(libblkid_format); + + if (probe != NULL) { + blkid_free_probe(probe); + } + + return ret; +} + +#else /* #if HAVE_LIBBLKID */ + +static virStoragePoolProbeResult +virStorageBackendFileSystemProbe(const char *device ATTRIBUTE_UNUSED, + const char *format ATTRIBUTE_UNUSED) +{ + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("probing for filesystems is unsupported " + "by this build")); + + return FILESYSTEM_PROBE_ERROR; +} + +#endif /* #if HAVE_LIBBLKID */ + +static int +virStorageBackendExecuteMKFS(const char *device, + const char *format) +{ + int ret = 0; + virCommandPtr cmd = NULL; + + cmd = virCommandNewArgList(MKFS, + "-t", + format, + device, + NULL); + + if (virCommandRun(cmd, NULL) < 0) { + virReportSystemError(errno, + _("Failed to make filesystem of " + "type '%s' on device '%s'"), + format, device); + ret = -1; + } + + return ret; +} + + +static int +virStorageBackendMakeFileSystem(virStoragePoolObjPtr pool, + unsigned int flags) +{ + const char *device = NULL, *format = NULL; + bool ok_to_mkfs = false; + int ret = -1; + + if (pool->def->source.devices == NULL) { + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("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); + + if (!virFileExists(device)) { + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("Source device does not exist when formatting pool '%s'"), + pool->def->name); + goto error; + } + + if (flags & VIR_STORAGE_POOL_BUILD_OVERWRITE) { + ok_to_mkfs = true; + } else if (flags & VIR_STORAGE_POOL_BUILD_NO_OVERWRITE && + virStorageBackendFileSystemProbe(device, format) == + FILESYSTEM_PROBE_NOT_FOUND) { + ok_to_mkfs = true; + } + + if (ok_to_mkfs) { + ret = virStorageBackendExecuteMKFS(device, format); + } + +error: + return ret; +} + + /** * @conn connection to report errors against * @pool storage pool to build + * @flags controls the pool formating behaviour * * Build a directory or FS based storage pool. * + * If no flag is set, it only makes the directory; If + * VIR_STORAGE_POOL_BUILD_NO_OVERWRITE set, it probes to determine if + * a filesystem already exists on the target device, returning an error + * if exists, or using mkfs to format the target device if not; If + * VIR_STORAGE_POOL_BUILD_OVERWRITE is set, mkfs is always executed, + * any existed data on the target device is overwritten unconditionally. + * * - If it is a FS based pool, mounts the unlying source device on the pool * * Returns 0 on success, -1 on error @@ -547,11 +715,23 @@ virStorageBackendFileSystemStart(virConnectPtr conn ATTRIBUTE_UNUSED, static int virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool, - unsigned int flags ATTRIBUTE_UNUSED) + unsigned int flags) { int err, ret = -1; - char *parent; - char *p; + char *parent = NULL; + char *p = NULL; + + virCheckFlags(VIR_STORAGE_POOL_BUILD_OVERWRITE | + VIR_STORAGE_POOL_BUILD_NO_OVERWRITE, ret); + + if (flags == (VIR_STORAGE_POOL_BUILD_OVERWRITE | + VIR_STORAGE_POOL_BUILD_NO_OVERWRITE)) { + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("Overwrite and no overwrite flags" + " are mutually exclusive")); + goto error; + } if ((parent = strdup(pool->def->target.path)) == NULL) { virReportOOMError(); @@ -601,7 +781,13 @@ virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED, goto error; } } - ret = 0; + + if (flags != 0) { + ret = virStorageBackendMakeFileSystem(pool, flags); + } else { + ret = 0; + } + error: VIR_FREE(parent); return ret; diff --git a/src/storage/storage_backend_fs.h b/src/storage/storage_backend_fs.h index 7def53e..394e552 100644 --- a/src/storage/storage_backend_fs.h +++ b/src/storage/storage_backend_fs.h @@ -29,6 +29,13 @@ # if WITH_STORAGE_FS extern virStorageBackend virStorageBackendFileSystem; extern virStorageBackend virStorageBackendNetFileSystem; + +typedef enum { + FILESYSTEM_PROBE_FOUND, + FILESYSTEM_PROBE_NOT_FOUND, + FILESYSTEM_PROBE_ERROR, +} virStoragePoolProbeResult; + # endif extern virStorageBackend virStorageBackendDirectory; diff --git a/src/util/virterror.c b/src/util/virterror.c index b7d8924..4450a43 100644 --- a/src/util/virterror.c +++ b/src/util/virterror.c @@ -1041,63 +1041,75 @@ virErrorMsg(virErrorNumber error, const char *info) break; case VIR_ERR_NO_STORAGE_POOL: if (info == NULL) - errmsg = _("Storage pool not found"); + errmsg = _("Storage pool not found"); else - errmsg = _("Storage pool not found: %s"); + errmsg = _("Storage pool not found: %s"); break; case VIR_ERR_NO_STORAGE_VOL: if (info == NULL) - errmsg = _("Storage volume not found"); + errmsg = _("Storage volume not found"); else - errmsg = _("Storage volume not found: %s"); + errmsg = _("Storage volume not found: %s"); + break; + case VIR_ERR_STORAGE_PROBE_FAILED: + if (info == NULL) + errmsg = _("Storage pool probe failed"); + else + errmsg = _("Storage pool probe failed: %s"); + break; + case VIR_ERR_STORAGE_POOL_BUILT: + if (info == NULL) + errmsg = _("Storage pool already built"); + else + errmsg = _("Storage pool already built: %s"); break; case VIR_ERR_INVALID_STORAGE_POOL: if (info == NULL) - errmsg = _("invalid storage pool pointer in"); + errmsg = _("invalid storage pool pointer in"); else - errmsg = _("invalid storage pool pointer in %s"); + errmsg = _("invalid storage pool pointer in %s"); break; case VIR_ERR_INVALID_STORAGE_VOL: if (info == NULL) - errmsg = _("invalid storage volume pointer in"); + errmsg = _("invalid storage volume pointer in"); else - errmsg = _("invalid storage volume pointer in %s"); + errmsg = _("invalid storage volume pointer in %s"); break; case VIR_WAR_NO_STORAGE: if (info == NULL) - errmsg = _("Failed to find a storage driver"); + errmsg = _("Failed to find a storage driver"); else - errmsg = _("Failed to find a storage driver: %s"); + errmsg = _("Failed to find a storage driver: %s"); break; case VIR_WAR_NO_NODE: if (info == NULL) - errmsg = _("Failed to find a node driver"); + errmsg = _("Failed to find a node driver"); else - errmsg = _("Failed to find a node driver: %s"); + errmsg = _("Failed to find a node driver: %s"); break; case VIR_ERR_INVALID_NODE_DEVICE: if (info == NULL) - errmsg = _("invalid node device pointer"); + errmsg = _("invalid node device pointer"); else - errmsg = _("invalid node device pointer in %s"); + errmsg = _("invalid node device pointer in %s"); break; case VIR_ERR_NO_NODE_DEVICE: if (info == NULL) - errmsg = _("Node device not found"); + errmsg = _("Node device not found"); else - errmsg = _("Node device not found: %s"); + errmsg = _("Node device not found: %s"); break; case VIR_ERR_NO_SECURITY_MODEL: if (info == NULL) - errmsg = _("Security model not found"); + errmsg = _("Security model not found"); else - errmsg = _("Security model not found: %s"); + errmsg = _("Security model not found: %s"); break; case VIR_ERR_OPERATION_INVALID: if (info == NULL) - errmsg = _("Requested operation is not valid"); + errmsg = _("Requested operation is not valid"); else - errmsg = _("Requested operation is not valid: %s"); + errmsg = _("Requested operation is not valid: %s"); break; case VIR_WAR_NO_INTERFACE: if (info == NULL) @@ -1149,21 +1161,21 @@ virErrorMsg(virErrorNumber error, const char *info) break; case VIR_ERR_INVALID_NWFILTER: if (info == NULL) - errmsg = _("Invalid network filter"); + errmsg = _("Invalid network filter"); else - errmsg = _("Invalid network filter: %s"); + errmsg = _("Invalid network filter: %s"); break; case VIR_ERR_NO_NWFILTER: if (info == NULL) - errmsg = _("Network filter not found"); + errmsg = _("Network filter not found"); else - errmsg = _("Network filter not found: %s"); + errmsg = _("Network filter not found: %s"); break; case VIR_ERR_BUILD_FIREWALL: if (info == NULL) - errmsg = _("Error while building firewall"); + errmsg = _("Error while building firewall"); else - errmsg = _("Error while building firewall: %s"); + errmsg = _("Error while building firewall: %s"); break; case VIR_ERR_CONFIG_UNSUPPORTED: if (info == NULL) -- 1.7.4

New changes: Add doc --- tools/virsh.c | 13 ++++++++++++- tools/virsh.pod | 12 +++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index e186c75..c9fbbf8 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -5723,6 +5723,8 @@ static const vshCmdInfo info_pool_build[] = { static const vshCmdOptDef opts_pool_build[] = { {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")}, + {"no-overwrite", VSH_OT_BOOL, 0, N_("do not overwrite an existing pool of this type")}, + {"overwrite", VSH_OT_BOOL, 0, N_("overwrite any existing data")}, {NULL, 0, 0, NULL} }; @@ -5731,6 +5733,7 @@ cmdPoolBuild(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; int ret = TRUE; + unsigned int flags = 0; const char *name; if (!vshConnectionUsability(ctl, ctl->conn)) @@ -5739,7 +5742,15 @@ cmdPoolBuild(vshControl *ctl, const vshCmd *cmd) if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name))) return FALSE; - if (virStoragePoolBuild(pool, 0) == 0) { + if (vshCommandOptBool (cmd, "no-overwrite")) { + flags |= VIR_STORAGE_POOL_BUILD_NO_OVERWRITE; + } + + 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); diff --git a/tools/virsh.pod b/tools/virsh.pod index 580e1dc..7975d30 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -940,10 +940,20 @@ query is performed. Configure whether I<pool> should automatically start at boot. -=item B<pool-build> I<pool-or-uuid> +=item B<pool-build> I<pool-or-uuid> optional I<--overwrite> +I<--no-overwite> Build a given pool. +Options I<--overwrite> and I<--no-overwrite> can only be used for +B<pool-build> a filesystem pool. If neither of them is specified, +B<pool-build> on a filesystem pool only makes the directory; If +I<--no-overwrite> is specified, it probes to determine if a +filesystem already exists on the target device, returning an error +if exists, or using mkfs to format the target device if not; If +I<--overwrite> is specified, mkfs is always executed, any existed +data on the target device is overwritten unconditionally. + =item B<pool-create> I<file> Create and start a pool object from the XML I<file>. -- 1.7.4
participants (1)
-
Osier Yang