2008-02-20 15:45:59 +00:00
|
|
|
/*
|
|
|
|
* storage_backend_fs.c: storage backend for FS and directory handling
|
|
|
|
*
|
2013-11-05 21:12:02 +00:00
|
|
|
* Copyright (C) 2007-2013 Red Hat, Inc.
|
2008-02-20 15:45:59 +00:00
|
|
|
* Copyright (C) 2007-2008 Daniel P. Berrange
|
|
|
|
*
|
|
|
|
* 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.1 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
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2008-02-20 15:45:59 +00:00
|
|
|
*
|
|
|
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <sys/statvfs.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2008-08-27 20:05:58 +00:00
|
|
|
#include <libxml/parser.h>
|
|
|
|
#include <libxml/tree.h>
|
|
|
|
#include <libxml/xpath.h>
|
|
|
|
|
2012-09-20 14:43:12 +00:00
|
|
|
#if WITH_BLKID
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
# include <blkid/blkid.h>
|
|
|
|
#endif
|
|
|
|
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2008-02-20 15:45:59 +00:00
|
|
|
#include "storage_backend_fs.h"
|
|
|
|
#include "storage_conf.h"
|
2012-12-13 15:25:48 +00:00
|
|
|
#include "virstoragefile.h"
|
2012-12-12 16:27:01 +00:00
|
|
|
#include "vircommand.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-13 18:13:21 +00:00
|
|
|
#include "virxml.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
#include "virfile.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
2008-02-20 15:45:59 +00:00
|
|
|
|
2009-01-20 17:13:33 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_STORAGE
|
2008-02-20 15:45:59 +00:00
|
|
|
|
2011-05-26 18:05:32 +00:00
|
|
|
#define VIR_STORAGE_VOL_FS_OPEN_FLAGS (VIR_STORAGE_VOL_OPEN_DEFAULT |\
|
|
|
|
VIR_STORAGE_VOL_OPEN_DIR)
|
|
|
|
#define VIR_STORAGE_VOL_FS_REFRESH_FLAGS (VIR_STORAGE_VOL_FS_OPEN_FLAGS &\
|
|
|
|
~VIR_STORAGE_VOL_OPEN_ERROR)
|
|
|
|
|
2010-07-30 16:24:17 +00:00
|
|
|
static int ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
|
2010-02-04 22:46:55 +00:00
|
|
|
virStorageBackendProbeTarget(virStorageVolTargetPtr target,
|
2009-09-29 08:07:14 +00:00
|
|
|
char **backingStore,
|
2010-07-09 10:28:40 +00:00
|
|
|
int *backingStoreFormat,
|
2009-09-29 08:07:14 +00:00
|
|
|
unsigned long long *allocation,
|
|
|
|
unsigned long long *capacity,
|
|
|
|
virStorageEncryptionPtr *encryption)
|
|
|
|
{
|
2011-07-14 10:53:45 +00:00
|
|
|
int fd = -1;
|
|
|
|
int ret = -1;
|
2012-10-13 17:01:27 +00:00
|
|
|
virStorageFileMetadata *meta = NULL;
|
2013-11-05 15:30:01 +00:00
|
|
|
struct stat sb;
|
2013-11-05 21:12:02 +00:00
|
|
|
char *header = NULL;
|
|
|
|
ssize_t len = VIR_STORAGE_MAX_HEADER;
|
2009-09-29 08:07:14 +00:00
|
|
|
|
2010-07-30 16:24:17 +00:00
|
|
|
*backingStore = NULL;
|
|
|
|
*backingStoreFormat = VIR_STORAGE_FILE_AUTO;
|
2009-09-29 08:07:14 +00:00
|
|
|
if (encryption)
|
|
|
|
*encryption = NULL;
|
|
|
|
|
2013-11-05 15:30:01 +00:00
|
|
|
if ((ret = virStorageBackendVolOpenCheckMode(target->path, &sb,
|
2011-05-26 18:05:32 +00:00
|
|
|
VIR_STORAGE_VOL_FS_REFRESH_FLAGS)) < 0)
|
2011-07-14 10:53:45 +00:00
|
|
|
goto error; /* Take care to propagate ret, it is not always -1 */
|
storage: Check for invalid storage mode before opening
If a directory pool contains pipes or sockets, a pool start can fail or hang:
https://bugzilla.redhat.com/show_bug.cgi?id=589577
We already try to avoid these special files, but only attempt after
opening the path, which is where the problems lie. Unify volume opening
into helper functions, which use the proper open() flags to avoid error,
followed by fstat to validate storage mode.
Previously, virStorageBackendUpdateVolTargetInfoFD attempted to enforce the
storage mode check, but allowed callers to detect this case and silently
continue. In practice, only the FS backend was using this feature, the rest
were treating unknown mode as an error condition. Unfortunately the InfoFD
function wasn't raising an error message here, so error reporting was
busted.
This patch adds 2 functions: virStorageBackendVolOpen, and
virStorageBackendVolOpenModeSkip. The latter retains the original opt out
semantics, the former now throws an explicit error.
This patch maintains the previous volume mode checks: allowing specific
modes for specific pool types requires a bit of surgery, since VolOpen
is called through several different helper functions.
v2: Use ATTRIBUTE_NONNULL. Drop stat check, just open with
O_NONBLOCK|O_NOCTTY.
v3: Move mode check logic back to VolOpen. Use 2 VolOpen functions with
different error semantics.
v4: Make second VolOpen function more extensible. Didn't opt to change
FS backend defaults, this can just be to fix the original bug.
v5: Prefix default flags with VIR_, use ATTRIBUTE_RETURN_CHECK
2010-05-20 18:25:01 +00:00
|
|
|
fd = ret;
|
2009-09-29 08:07:14 +00:00
|
|
|
|
2013-11-05 15:30:01 +00:00
|
|
|
if ((ret = virStorageBackendUpdateVolTargetInfoFD(target, fd, &sb,
|
2009-09-29 08:07:14 +00:00
|
|
|
allocation,
|
|
|
|
capacity)) < 0) {
|
2011-07-14 10:53:45 +00:00
|
|
|
goto error;
|
2009-09-29 08:07:14 +00:00
|
|
|
}
|
|
|
|
|
2013-11-05 21:12:02 +00:00
|
|
|
if (S_ISDIR(sb.st_mode)) {
|
|
|
|
target->format = VIR_STORAGE_FILE_DIR;
|
|
|
|
} else {
|
|
|
|
if ((len = virFileReadHeaderFD(fd, len, &header)) < 0) {
|
|
|
|
virReportSystemError(errno, _("cannot read header '%s'"),
|
|
|
|
target->path);
|
|
|
|
goto error;
|
|
|
|
}
|
2009-09-29 08:07:14 +00:00
|
|
|
|
2013-11-05 21:12:02 +00:00
|
|
|
target->format = virStorageFileProbeFormatFromBuf(target->path,
|
|
|
|
header, len);
|
|
|
|
if (target->format < 0) {
|
|
|
|
ret = -1;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(meta = virStorageFileGetMetadataFromBuf(target->path,
|
|
|
|
header, len,
|
|
|
|
target->format))) {
|
|
|
|
ret = -1;
|
|
|
|
goto error;
|
|
|
|
}
|
2010-06-15 15:15:51 +00:00
|
|
|
}
|
2009-09-29 08:07:14 +00:00
|
|
|
|
2010-11-09 20:48:48 +00:00
|
|
|
VIR_FORCE_CLOSE(fd);
|
2009-09-29 08:23:04 +00:00
|
|
|
|
2013-11-05 21:12:02 +00:00
|
|
|
if (meta && meta->backingStore) {
|
2011-07-14 10:53:45 +00:00
|
|
|
*backingStore = meta->backingStore;
|
|
|
|
meta->backingStore = NULL;
|
2012-10-09 23:50:14 +00:00
|
|
|
if (meta->backingStoreFormat == VIR_STORAGE_FILE_AUTO &&
|
|
|
|
meta->backingStoreIsFile) {
|
2012-10-20 19:56:35 +00:00
|
|
|
if ((ret = virStorageFileProbeFormat(*backingStore, -1, -1)) < 0) {
|
Ignore backing file errors in FS storage pool
Currently a single storage volume with a broken backing file will disable the
whole storage pool. This can happen when the backing file is on some
unavailable network storage or if the backing volume is deleted, while the
storage volumes using it remain.
Since the storage pool can not be re-activated, re-creating the missing
or deleting the now useless volumes using libvirt only is not possible.
Fixing this is a little bit tricky:
1. virStorageBackendProbeTarget() only detects the missing backing file,
if the backing file format is not explicitly specified. If the
backing file is created using
kvm-img create -f qcow2 -o backing_fmt=qcow2,backing_file=... ...
no error is detected at this stage.
The new return code -3 signals that the backing file could not be
opened.
2. The backingStore.format must be >= 0, since values < 0 would break
virStorageVolTargetDefFormat() when dumping the XML data such as
<format type='...'/>
Because of this the format is faked as VIR_STORAGE_FILE_RAW.
3. virStorageBackendUpdateVolTargetInfo() always opens the backing file
and thus always detects a missing backing file.
Since it "only" updates the capacity, allocation, owner, group, mode
and SELinux label, just ignore errors at this stage, print an error
message and continue.
4. Using vol-dump on a broken volume still doesn't work, but at least
vol-destroy and pool-refresh do work now.
To reproduce:
dir=$(mktemp -d)
virsh pool-create-as tmp dir '' '' '' '' "$dir"
virsh vol-create-as --format qcow2 tmp back 1G
virsh vol-create-as --format qcow2 --backing-vol-format qcow2 --backing-vol back tmp cow 1G
virsh vol-delete --pool tmp back
virsh pool-refresh tmp
After the last step, the pool will be gone (because it was not persistent). As
long as the now broken image stays in the directory, you will not be able to
re-create or re-start the pool.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2011-03-01 15:48:20 +00:00
|
|
|
/* If the backing file is currently unavailable, only log an error,
|
|
|
|
* but continue. Returning -1 here would disable the whole storage
|
|
|
|
* pool, making it unavailable for even maintenance. */
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot probe backing volume format: %s"),
|
|
|
|
*backingStore);
|
Ignore backing file errors in FS storage pool
Currently a single storage volume with a broken backing file will disable the
whole storage pool. This can happen when the backing file is on some
unavailable network storage or if the backing volume is deleted, while the
storage volumes using it remain.
Since the storage pool can not be re-activated, re-creating the missing
or deleting the now useless volumes using libvirt only is not possible.
Fixing this is a little bit tricky:
1. virStorageBackendProbeTarget() only detects the missing backing file,
if the backing file format is not explicitly specified. If the
backing file is created using
kvm-img create -f qcow2 -o backing_fmt=qcow2,backing_file=... ...
no error is detected at this stage.
The new return code -3 signals that the backing file could not be
opened.
2. The backingStore.format must be >= 0, since values < 0 would break
virStorageVolTargetDefFormat() when dumping the XML data such as
<format type='...'/>
Because of this the format is faked as VIR_STORAGE_FILE_RAW.
3. virStorageBackendUpdateVolTargetInfo() always opens the backing file
and thus always detects a missing backing file.
Since it "only" updates the capacity, allocation, owner, group, mode
and SELinux label, just ignore errors at this stage, print an error
message and continue.
4. Using vol-dump on a broken volume still doesn't work, but at least
vol-destroy and pool-refresh do work now.
To reproduce:
dir=$(mktemp -d)
virsh pool-create-as tmp dir '' '' '' '' "$dir"
virsh vol-create-as --format qcow2 tmp back 1G
virsh vol-create-as --format qcow2 --backing-vol-format qcow2 --backing-vol back tmp cow 1G
virsh vol-delete --pool tmp back
virsh pool-refresh tmp
After the last step, the pool will be gone (because it was not persistent). As
long as the now broken image stays in the directory, you will not be able to
re-create or re-start the pool.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2011-03-01 15:48:20 +00:00
|
|
|
ret = -3;
|
|
|
|
} else {
|
|
|
|
*backingStoreFormat = ret;
|
|
|
|
ret = 0;
|
2010-07-09 10:28:40 +00:00
|
|
|
}
|
|
|
|
} else {
|
2011-07-14 10:53:45 +00:00
|
|
|
*backingStoreFormat = meta->backingStoreFormat;
|
Ignore backing file errors in FS storage pool
Currently a single storage volume with a broken backing file will disable the
whole storage pool. This can happen when the backing file is on some
unavailable network storage or if the backing volume is deleted, while the
storage volumes using it remain.
Since the storage pool can not be re-activated, re-creating the missing
or deleting the now useless volumes using libvirt only is not possible.
Fixing this is a little bit tricky:
1. virStorageBackendProbeTarget() only detects the missing backing file,
if the backing file format is not explicitly specified. If the
backing file is created using
kvm-img create -f qcow2 -o backing_fmt=qcow2,backing_file=... ...
no error is detected at this stage.
The new return code -3 signals that the backing file could not be
opened.
2. The backingStore.format must be >= 0, since values < 0 would break
virStorageVolTargetDefFormat() when dumping the XML data such as
<format type='...'/>
Because of this the format is faked as VIR_STORAGE_FILE_RAW.
3. virStorageBackendUpdateVolTargetInfo() always opens the backing file
and thus always detects a missing backing file.
Since it "only" updates the capacity, allocation, owner, group, mode
and SELinux label, just ignore errors at this stage, print an error
message and continue.
4. Using vol-dump on a broken volume still doesn't work, but at least
vol-destroy and pool-refresh do work now.
To reproduce:
dir=$(mktemp -d)
virsh pool-create-as tmp dir '' '' '' '' "$dir"
virsh vol-create-as --format qcow2 tmp back 1G
virsh vol-create-as --format qcow2 --backing-vol-format qcow2 --backing-vol back tmp cow 1G
virsh vol-delete --pool tmp back
virsh pool-refresh tmp
After the last step, the pool will be gone (because it was not persistent). As
long as the now broken image stays in the directory, you will not be able to
re-create or re-start the pool.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2011-03-01 15:48:20 +00:00
|
|
|
ret = 0;
|
2010-07-09 10:28:40 +00:00
|
|
|
}
|
2010-07-30 16:24:17 +00:00
|
|
|
} else {
|
Ignore backing file errors in FS storage pool
Currently a single storage volume with a broken backing file will disable the
whole storage pool. This can happen when the backing file is on some
unavailable network storage or if the backing volume is deleted, while the
storage volumes using it remain.
Since the storage pool can not be re-activated, re-creating the missing
or deleting the now useless volumes using libvirt only is not possible.
Fixing this is a little bit tricky:
1. virStorageBackendProbeTarget() only detects the missing backing file,
if the backing file format is not explicitly specified. If the
backing file is created using
kvm-img create -f qcow2 -o backing_fmt=qcow2,backing_file=... ...
no error is detected at this stage.
The new return code -3 signals that the backing file could not be
opened.
2. The backingStore.format must be >= 0, since values < 0 would break
virStorageVolTargetDefFormat() when dumping the XML data such as
<format type='...'/>
Because of this the format is faked as VIR_STORAGE_FILE_RAW.
3. virStorageBackendUpdateVolTargetInfo() always opens the backing file
and thus always detects a missing backing file.
Since it "only" updates the capacity, allocation, owner, group, mode
and SELinux label, just ignore errors at this stage, print an error
message and continue.
4. Using vol-dump on a broken volume still doesn't work, but at least
vol-destroy and pool-refresh do work now.
To reproduce:
dir=$(mktemp -d)
virsh pool-create-as tmp dir '' '' '' '' "$dir"
virsh vol-create-as --format qcow2 tmp back 1G
virsh vol-create-as --format qcow2 --backing-vol-format qcow2 --backing-vol back tmp cow 1G
virsh vol-delete --pool tmp back
virsh pool-refresh tmp
After the last step, the pool will be gone (because it was not persistent). As
long as the now broken image stays in the directory, you will not be able to
re-create or re-start the pool.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2011-03-01 15:48:20 +00:00
|
|
|
ret = 0;
|
2009-09-29 08:23:04 +00:00
|
|
|
}
|
|
|
|
|
2013-11-05 21:12:02 +00:00
|
|
|
if (capacity && meta && meta->capacity)
|
2011-07-14 10:53:45 +00:00
|
|
|
*capacity = meta->capacity;
|
2009-09-29 08:23:04 +00:00
|
|
|
|
2013-11-05 21:12:02 +00:00
|
|
|
if (encryption && meta && meta->encrypted) {
|
2013-07-04 10:16:29 +00:00
|
|
|
if (VIR_ALLOC(*encryption) < 0)
|
2010-07-09 10:28:40 +00:00
|
|
|
goto cleanup;
|
2009-09-29 08:07:14 +00:00
|
|
|
|
|
|
|
switch (target->format) {
|
|
|
|
case VIR_STORAGE_FILE_QCOW:
|
|
|
|
case VIR_STORAGE_FILE_QCOW2:
|
|
|
|
(*encryption)->format = VIR_STORAGE_ENCRYPTION_FORMAT_QCOW;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX ideally we'd fill in secret UUID here
|
2011-07-20 22:53:31 +00:00
|
|
|
* but we cannot guarantee 'conn' is non-NULL
|
2009-09-29 08:07:14 +00:00
|
|
|
* at this point in time :-( So we only fill
|
|
|
|
* in secrets when someone first queries a vol
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
2013-05-16 10:38:26 +00:00
|
|
|
virBitmapFree(target->features);
|
2013-11-05 21:12:02 +00:00
|
|
|
if (meta) {
|
|
|
|
target->features = meta->features;
|
|
|
|
meta->features = NULL;
|
|
|
|
}
|
2013-05-16 10:38:26 +00:00
|
|
|
|
2013-11-05 21:12:02 +00:00
|
|
|
if (meta && meta->compat) {
|
2013-05-16 10:38:26 +00:00
|
|
|
VIR_FREE(target->compat);
|
|
|
|
target->compat = meta->compat;
|
|
|
|
meta->compat = NULL;
|
|
|
|
}
|
|
|
|
|
2013-11-05 21:12:02 +00:00
|
|
|
goto cleanup;
|
2010-07-09 10:28:40 +00:00
|
|
|
|
2011-07-14 10:53:45 +00:00
|
|
|
error:
|
|
|
|
VIR_FORCE_CLOSE(fd);
|
|
|
|
|
2010-07-09 10:28:40 +00:00
|
|
|
cleanup:
|
2011-07-14 10:53:45 +00:00
|
|
|
virStorageFileFreeMetadata(meta);
|
2013-11-05 21:12:02 +00:00
|
|
|
VIR_FREE(header);
|
2011-07-14 10:53:45 +00:00
|
|
|
return ret;
|
|
|
|
|
2008-02-20 15:45:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if WITH_STORAGE_FS
|
2009-01-06 08:43:44 +00:00
|
|
|
|
2010-03-09 18:22:22 +00:00
|
|
|
# include <mntent.h>
|
2009-01-06 08:43:44 +00:00
|
|
|
|
2008-08-27 20:05:58 +00:00
|
|
|
struct _virNetfsDiscoverState {
|
|
|
|
const char *host;
|
2008-11-04 21:54:21 +00:00
|
|
|
virStoragePoolSourceList list;
|
2008-08-27 20:05:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct _virNetfsDiscoverState virNetfsDiscoverState;
|
|
|
|
|
|
|
|
static int
|
2010-02-10 11:42:56 +00:00
|
|
|
virStorageBackendFileSystemNetFindPoolSourcesFunc(virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
|
2008-08-27 20:05:58 +00:00
|
|
|
char **const groups,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
virNetfsDiscoverState *state = data;
|
|
|
|
const char *name, *path;
|
2009-10-15 15:41:53 +00:00
|
|
|
virStoragePoolSource *src = NULL;
|
|
|
|
int ret = -1;
|
2008-08-27 20:05:58 +00:00
|
|
|
|
|
|
|
path = groups[0];
|
|
|
|
|
2012-07-09 12:08:00 +00:00
|
|
|
if (!(name = strrchr(path, '/'))) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("invalid netfs path (no /): %s"), path);
|
2009-10-15 15:41:53 +00:00
|
|
|
goto cleanup;
|
2008-08-27 20:05:58 +00:00
|
|
|
}
|
|
|
|
name += 1;
|
|
|
|
if (*name == '\0') {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("invalid netfs path (ends in /): %s"), path);
|
2009-10-15 15:41:53 +00:00
|
|
|
goto cleanup;
|
2008-08-27 20:05:58 +00:00
|
|
|
}
|
|
|
|
|
2010-02-10 11:42:56 +00:00
|
|
|
if (!(src = virStoragePoolSourceListNewSource(&state->list)))
|
2009-10-15 15:41:53 +00:00
|
|
|
goto cleanup;
|
2008-08-27 20:05:58 +00:00
|
|
|
|
2013-07-04 10:16:29 +00:00
|
|
|
if (VIR_ALLOC_N(src->hosts, 1) < 0)
|
2012-04-25 10:43:09 +00:00
|
|
|
goto cleanup;
|
2012-07-09 12:37:01 +00:00
|
|
|
src->nhost = 1;
|
2012-04-25 10:43:09 +00:00
|
|
|
|
2013-05-03 12:49:08 +00:00
|
|
|
if (VIR_STRDUP(src->hosts[0].name, state->host) < 0 ||
|
|
|
|
VIR_STRDUP(src->dir, path) < 0)
|
2009-10-15 15:41:53 +00:00
|
|
|
goto cleanup;
|
2008-11-04 21:54:21 +00:00
|
|
|
src->format = VIR_STORAGE_POOL_NETFS_NFS;
|
2008-08-27 20:05:58 +00:00
|
|
|
|
2009-10-15 15:41:53 +00:00
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
2008-08-27 20:05:58 +00:00
|
|
|
}
|
|
|
|
|
2009-10-15 15:41:53 +00:00
|
|
|
|
2008-08-27 20:05:58 +00:00
|
|
|
static char *
|
2010-02-10 11:42:56 +00:00
|
|
|
virStorageBackendFileSystemNetFindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
|
2008-08-27 20:05:58 +00:00
|
|
|
const char *srcSpec,
|
2011-07-06 22:51:23 +00:00
|
|
|
unsigned int flags)
|
2008-08-27 20:05:58 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* # showmount --no-headers -e HOSTNAME
|
|
|
|
* /tmp *
|
|
|
|
* /A dir demo1.foo.bar,demo2.foo.bar
|
|
|
|
*
|
|
|
|
* Extract directory name (including possible interior spaces ...).
|
|
|
|
*/
|
|
|
|
|
|
|
|
const char *regexes[] = {
|
|
|
|
"^(/.*\\S) +\\S+$"
|
|
|
|
};
|
|
|
|
int vars[] = {
|
|
|
|
1
|
|
|
|
};
|
2008-11-04 21:54:21 +00:00
|
|
|
virNetfsDiscoverState state = {
|
|
|
|
.host = NULL,
|
|
|
|
.list = {
|
|
|
|
.type = VIR_STORAGE_POOL_NETFS,
|
|
|
|
.nsources = 0,
|
|
|
|
.sources = NULL
|
|
|
|
}
|
|
|
|
};
|
2009-10-15 15:58:35 +00:00
|
|
|
virStoragePoolSourcePtr source = NULL;
|
2008-08-27 20:05:58 +00:00
|
|
|
char *retval = NULL;
|
Convert 'int i' to 'size_t i' in src/storage/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2012-07-11 14:56:55 +00:00
|
|
|
virCommandPtr cmd = NULL;
|
2008-08-27 20:05:58 +00:00
|
|
|
|
2011-07-06 22:51:23 +00:00
|
|
|
virCheckFlags(0, NULL);
|
|
|
|
|
2012-07-31 08:56:41 +00:00
|
|
|
if (!srcSpec) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
"%s", _("hostname must be specified for netfs sources"));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(source = virStoragePoolDefParseSourceString(srcSpec,
|
|
|
|
VIR_STORAGE_POOL_NETFS)))
|
|
|
|
return NULL;
|
2008-08-27 20:05:58 +00:00
|
|
|
|
2012-04-25 10:43:09 +00:00
|
|
|
if (source->nhost != 1) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Expected exactly 1 host for the storage pool"));
|
2012-04-25 10:43:09 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
state.host = source->hosts[0].name;
|
2008-08-27 20:05:58 +00:00
|
|
|
|
2012-07-11 14:56:55 +00:00
|
|
|
cmd = virCommandNewArgList(SHOWMOUNT,
|
|
|
|
"--no-headers",
|
|
|
|
"--exports",
|
|
|
|
source->hosts[0].name,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (virStorageBackendRunProgRegex(NULL, cmd, 1, regexes, vars,
|
2011-05-10 19:36:50 +00:00
|
|
|
virStorageBackendFileSystemNetFindPoolSourcesFunc,
|
2011-09-28 20:08:34 +00:00
|
|
|
&state, NULL) < 0)
|
2008-08-27 20:05:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2010-02-10 11:42:56 +00:00
|
|
|
retval = virStoragePoolSourceListFormat(&state.list);
|
2013-07-04 10:16:29 +00:00
|
|
|
if (retval == NULL)
|
2008-08-27 20:05:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
cleanup:
|
2008-11-04 21:54:21 +00:00
|
|
|
for (i = 0; i < state.list.nsources; i++)
|
2011-10-21 22:44:52 +00:00
|
|
|
virStoragePoolSourceClear(&state.list.sources[i]);
|
|
|
|
VIR_FREE(state.list.sources);
|
2008-11-04 21:54:21 +00:00
|
|
|
|
2010-02-05 16:09:43 +00:00
|
|
|
virStoragePoolSourceFree(source);
|
2012-07-11 14:56:55 +00:00
|
|
|
virCommandFree(cmd);
|
2008-08-27 20:05:58 +00:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 15:45:59 +00:00
|
|
|
/**
|
|
|
|
* @conn connection to report errors against
|
|
|
|
* @pool storage pool to check for status
|
|
|
|
*
|
|
|
|
* Determine if a storage pool is already mounted
|
|
|
|
*
|
|
|
|
* Return 0 if not mounted, 1 if mounted, -1 on error
|
|
|
|
*/
|
|
|
|
static int
|
2010-02-04 20:02:58 +00:00
|
|
|
virStorageBackendFileSystemIsMounted(virStoragePoolObjPtr pool) {
|
2008-02-20 15:45:59 +00:00
|
|
|
FILE *mtab;
|
2009-01-22 19:41:48 +00:00
|
|
|
struct mntent ent;
|
|
|
|
char buf[1024];
|
2008-02-20 15:45:59 +00:00
|
|
|
|
|
|
|
if ((mtab = fopen(_PATH_MOUNTED, "r")) == NULL) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot read mount list '%s'"),
|
|
|
|
_PATH_MOUNTED);
|
2008-02-20 15:45:59 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-01-22 19:41:48 +00:00
|
|
|
while ((getmntent_r(mtab, &ent, buf, sizeof(buf))) != NULL) {
|
|
|
|
if (STREQ(ent.mnt_dir, pool->def->target.path)) {
|
2010-11-17 02:13:29 +00:00
|
|
|
VIR_FORCE_FCLOSE(mtab);
|
2008-02-20 15:45:59 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-17 02:13:29 +00:00
|
|
|
VIR_FORCE_FCLOSE(mtab);
|
2008-02-20 15:45:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @conn connection to report errors against
|
|
|
|
* @pool storage pool to mount
|
|
|
|
*
|
|
|
|
* Ensure that a FS storage pool is mounted on its target location.
|
|
|
|
* If already mounted, this is a no-op
|
|
|
|
*
|
|
|
|
* Returns 0 if successfully mounted, -1 on error
|
|
|
|
*/
|
|
|
|
static int
|
2010-02-10 11:42:56 +00:00
|
|
|
virStorageBackendFileSystemMount(virStoragePoolObjPtr pool) {
|
2012-07-11 14:56:55 +00:00
|
|
|
char *src = NULL;
|
2008-07-17 15:20:28 +00:00
|
|
|
/* 'mount -t auto' doesn't seem to auto determine nfs (or cifs),
|
|
|
|
* while plain 'mount' does. We have to craft separate argvs to
|
|
|
|
* accommodate this */
|
2012-07-11 14:56:55 +00:00
|
|
|
bool netauto = (pool->def->type == VIR_STORAGE_POOL_NETFS &&
|
|
|
|
pool->def->source.format == VIR_STORAGE_POOL_NETFS_AUTO);
|
|
|
|
bool glusterfs = (pool->def->type == VIR_STORAGE_POOL_NETFS &&
|
|
|
|
pool->def->source.format == VIR_STORAGE_POOL_NETFS_GLUSTERFS);
|
|
|
|
virCommandPtr cmd = NULL;
|
|
|
|
int ret = -1;
|
2013-07-11 10:36:59 +00:00
|
|
|
int rc;
|
2008-02-20 15:45:59 +00:00
|
|
|
|
|
|
|
if (pool->def->type == VIR_STORAGE_POOL_NETFS) {
|
2012-04-25 10:43:09 +00:00
|
|
|
if (pool->def->source.nhost != 1) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Expected exactly 1 host for the storage pool"));
|
2012-04-25 10:43:09 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (pool->def->source.hosts[0].name == NULL) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("missing source host"));
|
2008-02-20 15:45:59 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (pool->def->source.dir == NULL) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("missing source path"));
|
2008-02-20 15:45:59 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (pool->def->source.ndevice != 1) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("missing source device"));
|
2008-02-20 15:45:59 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-03 23:06:02 +00:00
|
|
|
/* Short-circuit if already mounted */
|
2013-07-11 10:36:59 +00:00
|
|
|
if ((rc = virStorageBackendFileSystemIsMounted(pool)) != 0) {
|
|
|
|
if (rc == 1) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("Target '%s' is already mounted"),
|
|
|
|
pool->def->target.path);
|
|
|
|
}
|
2012-06-27 14:02:23 +00:00
|
|
|
return -1;
|
2008-02-20 15:45:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (pool->def->type == VIR_STORAGE_POOL_NETFS) {
|
2009-05-19 13:15:50 +00:00
|
|
|
if (virAsprintf(&src, "%s:%s",
|
2012-04-25 10:43:09 +00:00
|
|
|
pool->def->source.hosts[0].name,
|
2013-07-04 10:16:29 +00:00
|
|
|
pool->def->source.dir) == -1)
|
2008-06-06 11:09:57 +00:00
|
|
|
return -1;
|
2009-05-19 13:15:50 +00:00
|
|
|
|
2008-02-20 15:45:59 +00:00
|
|
|
} else {
|
2013-05-03 12:49:08 +00:00
|
|
|
if (VIR_STRDUP(src, pool->def->source.devices[0].path) < 0)
|
2008-06-06 11:09:57 +00:00
|
|
|
return -1;
|
2008-02-20 15:45:59 +00:00
|
|
|
}
|
|
|
|
|
2012-07-11 14:56:55 +00:00
|
|
|
if (netauto)
|
|
|
|
cmd = virCommandNewArgList(MOUNT,
|
|
|
|
src,
|
|
|
|
pool->def->target.path,
|
|
|
|
NULL);
|
|
|
|
else if (glusterfs)
|
2012-10-17 09:23:12 +00:00
|
|
|
cmd = virCommandNewArgList(MOUNT,
|
|
|
|
"-t",
|
|
|
|
(pool->def->type == VIR_STORAGE_POOL_FS ?
|
|
|
|
virStoragePoolFormatFileSystemTypeToString(pool->def->source.format) :
|
|
|
|
virStoragePoolFormatFileSystemNetTypeToString(pool->def->source.format)),
|
|
|
|
src,
|
|
|
|
"-o",
|
|
|
|
"direct-io-mode=1",
|
|
|
|
pool->def->target.path,
|
|
|
|
NULL);
|
2012-07-11 14:56:55 +00:00
|
|
|
else
|
|
|
|
cmd = virCommandNewArgList(MOUNT,
|
|
|
|
"-t",
|
|
|
|
(pool->def->type == VIR_STORAGE_POOL_FS ?
|
|
|
|
virStoragePoolFormatFileSystemTypeToString(pool->def->source.format) :
|
|
|
|
virStoragePoolFormatFileSystemNetTypeToString(pool->def->source.format)),
|
|
|
|
src,
|
|
|
|
pool->def->target.path,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (virCommandRun(cmd, NULL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
virCommandFree(cmd);
|
2008-06-06 11:09:57 +00:00
|
|
|
VIR_FREE(src);
|
2012-07-11 14:56:55 +00:00
|
|
|
return ret;
|
2008-02-20 15:45:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @conn connection to report errors against
|
|
|
|
* @pool storage pool to unmount
|
|
|
|
*
|
|
|
|
* Ensure that a FS storage pool is not mounted on its target location.
|
|
|
|
* If already unmounted, this is a no-op
|
|
|
|
*
|
|
|
|
* Returns 0 if successfully unmounted, -1 on error
|
|
|
|
*/
|
|
|
|
static int
|
2010-02-10 11:42:56 +00:00
|
|
|
virStorageBackendFileSystemUnmount(virStoragePoolObjPtr pool) {
|
2012-07-11 14:56:55 +00:00
|
|
|
virCommandPtr cmd = NULL;
|
|
|
|
int ret = -1;
|
2012-11-21 03:22:39 +00:00
|
|
|
int rc;
|
2008-02-20 15:45:59 +00:00
|
|
|
|
|
|
|
if (pool->def->type == VIR_STORAGE_POOL_NETFS) {
|
2012-04-25 10:43:09 +00:00
|
|
|
if (pool->def->source.nhost != 1) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Expected exactly 1 host for the storage pool"));
|
2012-04-25 10:43:09 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (pool->def->source.hosts[0].name == NULL) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("missing source host"));
|
2008-02-20 15:45:59 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (pool->def->source.dir == NULL) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("missing source dir"));
|
2008-02-20 15:45:59 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (pool->def->source.ndevice != 1) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("missing source device"));
|
2008-02-20 15:45:59 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Short-circuit if already unmounted */
|
2012-11-21 03:22:39 +00:00
|
|
|
if ((rc = virStorageBackendFileSystemIsMounted(pool)) != 1)
|
|
|
|
return rc;
|
2008-02-20 15:45:59 +00:00
|
|
|
|
2012-07-11 14:56:55 +00:00
|
|
|
cmd = virCommandNewArgList(UMOUNT,
|
|
|
|
pool->def->target.path,
|
|
|
|
NULL);
|
2008-02-20 15:45:59 +00:00
|
|
|
|
2012-07-11 14:56:55 +00:00
|
|
|
if (virCommandRun(cmd, NULL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
virCommandFree(cmd);
|
|
|
|
return ret;
|
2008-02-20 15:45:59 +00:00
|
|
|
}
|
|
|
|
#endif /* WITH_STORAGE_FS */
|
|
|
|
|
|
|
|
|
2010-11-11 20:09:20 +00:00
|
|
|
static int
|
|
|
|
virStorageBackendFileSystemCheck(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|
|
|
virStoragePoolObjPtr pool,
|
|
|
|
bool *isActive)
|
|
|
|
{
|
|
|
|
if (pool->def->type == VIR_STORAGE_POOL_DIR) {
|
2013-09-13 13:32:43 +00:00
|
|
|
*isActive = virFileExists(pool->def->target.path);
|
2010-11-11 20:09:20 +00:00
|
|
|
#if WITH_STORAGE_FS
|
|
|
|
} else {
|
|
|
|
int ret;
|
2013-09-13 13:32:43 +00:00
|
|
|
*isActive = false;
|
2010-11-11 20:09:20 +00:00
|
|
|
if ((ret = virStorageBackendFileSystemIsMounted(pool)) != 0) {
|
|
|
|
if (ret < 0)
|
|
|
|
return -1;
|
|
|
|
*isActive = true;
|
|
|
|
}
|
|
|
|
#endif /* WITH_STORAGE_FS */
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if WITH_STORAGE_FS
|
2008-02-20 15:45:59 +00:00
|
|
|
/**
|
|
|
|
* @conn connection to report errors against
|
|
|
|
* @pool storage pool to start
|
|
|
|
*
|
|
|
|
* Starts a directory or FS based storage pool.
|
|
|
|
*
|
|
|
|
* - If it is a FS based pool, mounts the unlying source device on the pool
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
static int
|
2010-02-10 11:42:56 +00:00
|
|
|
virStorageBackendFileSystemStart(virConnectPtr conn ATTRIBUTE_UNUSED,
|
2008-02-20 15:45:59 +00:00
|
|
|
virStoragePoolObjPtr pool)
|
|
|
|
{
|
|
|
|
if (pool->def->type != VIR_STORAGE_POOL_DIR &&
|
2010-02-10 11:42:56 +00:00
|
|
|
virStorageBackendFileSystemMount(pool) < 0)
|
2008-02-20 15:45:59 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif /* WITH_STORAGE_FS */
|
|
|
|
|
2012-09-20 14:43:12 +00:00
|
|
|
#if WITH_BLKID
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
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) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_STORAGE_PROBE_FAILED,
|
|
|
|
_("Not capable of probing for "
|
|
|
|
"filesystem of type %s"),
|
|
|
|
format);
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
probe = blkid_new_probe_from_filename(device);
|
|
|
|
if (probe == NULL) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_STORAGE_PROBE_FAILED,
|
|
|
|
_("Failed to create filesystem probe "
|
|
|
|
"for device %s"),
|
|
|
|
device);
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2013-05-03 12:49:08 +00:00
|
|
|
if (VIR_STRDUP(libblkid_format, format) < 0)
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
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) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_STORAGE_POOL_BUILT,
|
|
|
|
_("Existing filesystem of type '%s' found on "
|
|
|
|
"device '%s'"),
|
|
|
|
fstype, device);
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
ret = FILESYSTEM_PROBE_FOUND;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (blkid_do_probe(probe) != 1) {
|
maint: don't permit format strings without %
Any time we have a string with no % passed through gettext, a
translator can inject a % to cause a stack overread. When there
is nothing to format, it's easier to ask for a string that cannot
be used as a formatter, by using a trivial "%s" format instead.
In the past, we have used --disable-nls to catch some of the
offenders, but that doesn't get run very often, and many more
uses have crept in. Syntax check to the rescue!
The syntax check can catch uses such as
virReportError(code,
_("split "
"string"));
by using a sed script to fold context lines into one pattern
space before checking for a string without %.
This patch is just mechanical insertion of %s; there are probably
several messages touched by this patch where we would be better
off giving the user more information than a fixed string.
* cfg.mk (sc_prohibit_diagnostic_without_format): New rule.
* src/datatypes.c (virUnrefConnect, virGetDomain)
(virUnrefDomain, virGetNetwork, virUnrefNetwork, virGetInterface)
(virUnrefInterface, virGetStoragePool, virUnrefStoragePool)
(virGetStorageVol, virUnrefStorageVol, virGetNodeDevice)
(virGetSecret, virUnrefSecret, virGetNWFilter, virUnrefNWFilter)
(virGetDomainSnapshot, virUnrefDomainSnapshot): Add %s wrapper.
* src/lxc/lxc_driver.c (lxcDomainSetBlkioParameters)
(lxcDomainGetBlkioParameters): Likewise.
* src/conf/domain_conf.c (virSecurityDeviceLabelDefParseXML)
(virDomainDiskDefParseXML, virDomainGraphicsDefParseXML):
Likewise.
* src/conf/network_conf.c (virNetworkDNSHostsDefParseXML)
(virNetworkDefParseXML): Likewise.
* src/conf/nwfilter_conf.c (virNWFilterIsValidChainName):
Likewise.
* src/conf/nwfilter_params.c (virNWFilterVarValueCreateSimple)
(virNWFilterVarAccessParse): Likewise.
* src/libvirt.c (virDomainSave, virDomainSaveFlags)
(virDomainRestore, virDomainRestoreFlags)
(virDomainSaveImageGetXMLDesc, virDomainSaveImageDefineXML)
(virDomainCoreDump, virDomainGetXMLDesc)
(virDomainMigrateVersion1, virDomainMigrateVersion2)
(virDomainMigrateVersion3, virDomainMigrate, virDomainMigrate2)
(virStreamSendAll, virStreamRecvAll)
(virDomainSnapshotGetXMLDesc): Likewise.
* src/nwfilter/nwfilter_dhcpsnoop.c (virNWFilterSnoopReqLeaseDel)
(virNWFilterDHCPSnoopReq): Likewise.
* src/openvz/openvz_driver.c (openvzUpdateDevice): Likewise.
* src/openvz/openvz_util.c (openvzKBPerPages): Likewise.
* src/qemu/qemu_cgroup.c (qemuSetupCgroup): Likewise.
* src/qemu/qemu_command.c (qemuBuildHubDevStr, qemuBuildChrChardevStr)
(qemuBuildCommandLine): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetPercpuStats): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Likewise.
* src/rpc/virnetsaslcontext.c (virNetSASLSessionGetIdentity):
Likewise.
* src/rpc/virnetsocket.c (virNetSocketNewConnectUNIX)
(virNetSocketSendFD, virNetSocketRecvFD): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskBuildPool): Likewise.
* src/storage/storage_backend_fs.c
(virStorageBackendFileSystemProbe)
(virStorageBackendFileSystemBuild): Likewise.
* src/storage/storage_backend_rbd.c
(virStorageBackendRBDOpenRADOSConn): Likewise.
* src/storage/storage_driver.c (storageVolumeResize): Likewise.
* src/test/test_driver.c (testInterfaceChangeBegin)
(testInterfaceChangeCommit, testInterfaceChangeRollback):
Likewise.
* src/vbox/vbox_tmpl.c (vboxListAllDomains): Likewise.
* src/xenxs/xen_sxpr.c (xenFormatSxprDisk, xenFormatSxpr):
Likewise.
* src/xenxs/xen_xm.c (xenXMConfigGetUUID, xenFormatXMDisk)
(xenFormatXM): Likewise.
2012-07-23 20:33:08 +00:00
|
|
|
virReportError(VIR_ERR_STORAGE_PROBE_FAILED, "%s",
|
2012-07-18 11:38:29 +00:00
|
|
|
_("Found additional probes to run, "
|
|
|
|
"filesystem probing may be incorrect"));
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
ret = FILESYSTEM_PROBE_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_FREE(libblkid_format);
|
|
|
|
|
|
|
|
if (probe != NULL) {
|
|
|
|
blkid_free_probe(probe);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-09-20 14:43:12 +00:00
|
|
|
#else /* #if WITH_BLKID */
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
|
|
|
|
static virStoragePoolProbeResult
|
|
|
|
virStorageBackendFileSystemProbe(const char *device ATTRIBUTE_UNUSED,
|
|
|
|
const char *format ATTRIBUTE_UNUSED)
|
|
|
|
{
|
maint: don't permit format strings without %
Any time we have a string with no % passed through gettext, a
translator can inject a % to cause a stack overread. When there
is nothing to format, it's easier to ask for a string that cannot
be used as a formatter, by using a trivial "%s" format instead.
In the past, we have used --disable-nls to catch some of the
offenders, but that doesn't get run very often, and many more
uses have crept in. Syntax check to the rescue!
The syntax check can catch uses such as
virReportError(code,
_("split "
"string"));
by using a sed script to fold context lines into one pattern
space before checking for a string without %.
This patch is just mechanical insertion of %s; there are probably
several messages touched by this patch where we would be better
off giving the user more information than a fixed string.
* cfg.mk (sc_prohibit_diagnostic_without_format): New rule.
* src/datatypes.c (virUnrefConnect, virGetDomain)
(virUnrefDomain, virGetNetwork, virUnrefNetwork, virGetInterface)
(virUnrefInterface, virGetStoragePool, virUnrefStoragePool)
(virGetStorageVol, virUnrefStorageVol, virGetNodeDevice)
(virGetSecret, virUnrefSecret, virGetNWFilter, virUnrefNWFilter)
(virGetDomainSnapshot, virUnrefDomainSnapshot): Add %s wrapper.
* src/lxc/lxc_driver.c (lxcDomainSetBlkioParameters)
(lxcDomainGetBlkioParameters): Likewise.
* src/conf/domain_conf.c (virSecurityDeviceLabelDefParseXML)
(virDomainDiskDefParseXML, virDomainGraphicsDefParseXML):
Likewise.
* src/conf/network_conf.c (virNetworkDNSHostsDefParseXML)
(virNetworkDefParseXML): Likewise.
* src/conf/nwfilter_conf.c (virNWFilterIsValidChainName):
Likewise.
* src/conf/nwfilter_params.c (virNWFilterVarValueCreateSimple)
(virNWFilterVarAccessParse): Likewise.
* src/libvirt.c (virDomainSave, virDomainSaveFlags)
(virDomainRestore, virDomainRestoreFlags)
(virDomainSaveImageGetXMLDesc, virDomainSaveImageDefineXML)
(virDomainCoreDump, virDomainGetXMLDesc)
(virDomainMigrateVersion1, virDomainMigrateVersion2)
(virDomainMigrateVersion3, virDomainMigrate, virDomainMigrate2)
(virStreamSendAll, virStreamRecvAll)
(virDomainSnapshotGetXMLDesc): Likewise.
* src/nwfilter/nwfilter_dhcpsnoop.c (virNWFilterSnoopReqLeaseDel)
(virNWFilterDHCPSnoopReq): Likewise.
* src/openvz/openvz_driver.c (openvzUpdateDevice): Likewise.
* src/openvz/openvz_util.c (openvzKBPerPages): Likewise.
* src/qemu/qemu_cgroup.c (qemuSetupCgroup): Likewise.
* src/qemu/qemu_command.c (qemuBuildHubDevStr, qemuBuildChrChardevStr)
(qemuBuildCommandLine): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetPercpuStats): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Likewise.
* src/rpc/virnetsaslcontext.c (virNetSASLSessionGetIdentity):
Likewise.
* src/rpc/virnetsocket.c (virNetSocketNewConnectUNIX)
(virNetSocketSendFD, virNetSocketRecvFD): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskBuildPool): Likewise.
* src/storage/storage_backend_fs.c
(virStorageBackendFileSystemProbe)
(virStorageBackendFileSystemBuild): Likewise.
* src/storage/storage_backend_rbd.c
(virStorageBackendRBDOpenRADOSConn): Likewise.
* src/storage/storage_driver.c (storageVolumeResize): Likewise.
* src/test/test_driver.c (testInterfaceChangeBegin)
(testInterfaceChangeCommit, testInterfaceChangeRollback):
Likewise.
* src/vbox/vbox_tmpl.c (vboxListAllDomains): Likewise.
* src/xenxs/xen_sxpr.c (xenFormatSxprDisk, xenFormatSxpr):
Likewise.
* src/xenxs/xen_xm.c (xenXMConfigGetUUID, xenFormatXMDisk)
(xenFormatXM): Likewise.
2012-07-23 20:33:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
2012-07-18 11:38:29 +00:00
|
|
|
_("probing for filesystems is unsupported "
|
|
|
|
"by this build"));
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
|
|
|
|
return FILESYSTEM_PROBE_ERROR;
|
|
|
|
}
|
|
|
|
|
2012-09-20 14:43:12 +00:00
|
|
|
#endif /* #if WITH_BLKID */
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
|
2011-09-16 12:14:16 +00:00
|
|
|
/* some platforms don't support mkfs */
|
|
|
|
#ifdef MKFS
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
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;
|
|
|
|
}
|
2013-01-23 22:04:46 +00:00
|
|
|
|
|
|
|
virCommandFree(cmd);
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2011-09-16 12:14:16 +00:00
|
|
|
#else /* #ifdef MKFS */
|
|
|
|
static int
|
|
|
|
virStorageBackendExecuteMKFS(const char *device ATTRIBUTE_UNUSED,
|
|
|
|
const char *format ATTRIBUTE_UNUSED)
|
|
|
|
{
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("mkfs is not supported on this platform: "
|
|
|
|
"Failed to make filesystem of "
|
|
|
|
"type '%s' on device '%s'"),
|
|
|
|
format, device);
|
2011-09-16 12:14:16 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif /* #ifdef MKFS */
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
|
|
|
|
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) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("No source device specified when formatting pool '%s'"),
|
|
|
|
pool->def->name);
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
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)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("Source device does not exist when formatting pool '%s'"),
|
|
|
|
pool->def->name);
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2008-02-20 15:45:59 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @conn connection to report errors against
|
|
|
|
* @pool storage pool to build
|
2011-12-01 23:08:34 +00:00
|
|
|
* @flags controls the pool formatting behaviour
|
2008-02-20 15:45:59 +00:00
|
|
|
*
|
|
|
|
* Build a directory or FS based storage pool.
|
|
|
|
*
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
* If no flag is set, it only makes the directory; If
|
|
|
|
* VIR_STORAGE_POOL_BUILD_NO_OVERWRITE set, it probes to determine if
|
|
|
|
* filesystem already exists on the target device, renurning 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.
|
|
|
|
*
|
2008-02-20 15:45:59 +00:00
|
|
|
* - If it is a FS based pool, mounts the unlying source device on the pool
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
static int
|
2010-02-10 11:42:56 +00:00
|
|
|
virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED,
|
2008-02-20 15:45:59 +00:00
|
|
|
virStoragePoolObjPtr pool,
|
2011-07-06 22:51:23 +00:00
|
|
|
unsigned int flags)
|
2008-02-20 15:45:59 +00:00
|
|
|
{
|
2010-01-20 23:46:32 +00:00
|
|
|
int err, ret = -1;
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
char *parent = NULL;
|
|
|
|
char *p = NULL;
|
2010-01-20 23:46:32 +00:00
|
|
|
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
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)) {
|
|
|
|
|
maint: don't permit format strings without %
Any time we have a string with no % passed through gettext, a
translator can inject a % to cause a stack overread. When there
is nothing to format, it's easier to ask for a string that cannot
be used as a formatter, by using a trivial "%s" format instead.
In the past, we have used --disable-nls to catch some of the
offenders, but that doesn't get run very often, and many more
uses have crept in. Syntax check to the rescue!
The syntax check can catch uses such as
virReportError(code,
_("split "
"string"));
by using a sed script to fold context lines into one pattern
space before checking for a string without %.
This patch is just mechanical insertion of %s; there are probably
several messages touched by this patch where we would be better
off giving the user more information than a fixed string.
* cfg.mk (sc_prohibit_diagnostic_without_format): New rule.
* src/datatypes.c (virUnrefConnect, virGetDomain)
(virUnrefDomain, virGetNetwork, virUnrefNetwork, virGetInterface)
(virUnrefInterface, virGetStoragePool, virUnrefStoragePool)
(virGetStorageVol, virUnrefStorageVol, virGetNodeDevice)
(virGetSecret, virUnrefSecret, virGetNWFilter, virUnrefNWFilter)
(virGetDomainSnapshot, virUnrefDomainSnapshot): Add %s wrapper.
* src/lxc/lxc_driver.c (lxcDomainSetBlkioParameters)
(lxcDomainGetBlkioParameters): Likewise.
* src/conf/domain_conf.c (virSecurityDeviceLabelDefParseXML)
(virDomainDiskDefParseXML, virDomainGraphicsDefParseXML):
Likewise.
* src/conf/network_conf.c (virNetworkDNSHostsDefParseXML)
(virNetworkDefParseXML): Likewise.
* src/conf/nwfilter_conf.c (virNWFilterIsValidChainName):
Likewise.
* src/conf/nwfilter_params.c (virNWFilterVarValueCreateSimple)
(virNWFilterVarAccessParse): Likewise.
* src/libvirt.c (virDomainSave, virDomainSaveFlags)
(virDomainRestore, virDomainRestoreFlags)
(virDomainSaveImageGetXMLDesc, virDomainSaveImageDefineXML)
(virDomainCoreDump, virDomainGetXMLDesc)
(virDomainMigrateVersion1, virDomainMigrateVersion2)
(virDomainMigrateVersion3, virDomainMigrate, virDomainMigrate2)
(virStreamSendAll, virStreamRecvAll)
(virDomainSnapshotGetXMLDesc): Likewise.
* src/nwfilter/nwfilter_dhcpsnoop.c (virNWFilterSnoopReqLeaseDel)
(virNWFilterDHCPSnoopReq): Likewise.
* src/openvz/openvz_driver.c (openvzUpdateDevice): Likewise.
* src/openvz/openvz_util.c (openvzKBPerPages): Likewise.
* src/qemu/qemu_cgroup.c (qemuSetupCgroup): Likewise.
* src/qemu/qemu_command.c (qemuBuildHubDevStr, qemuBuildChrChardevStr)
(qemuBuildCommandLine): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetPercpuStats): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Likewise.
* src/rpc/virnetsaslcontext.c (virNetSASLSessionGetIdentity):
Likewise.
* src/rpc/virnetsocket.c (virNetSocketNewConnectUNIX)
(virNetSocketSendFD, virNetSocketRecvFD): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskBuildPool): Likewise.
* src/storage/storage_backend_fs.c
(virStorageBackendFileSystemProbe)
(virStorageBackendFileSystemBuild): Likewise.
* src/storage/storage_backend_rbd.c
(virStorageBackendRBDOpenRADOSConn): Likewise.
* src/storage/storage_driver.c (storageVolumeResize): Likewise.
* src/test/test_driver.c (testInterfaceChangeBegin)
(testInterfaceChangeCommit, testInterfaceChangeRollback):
Likewise.
* src/vbox/vbox_tmpl.c (vboxListAllDomains): Likewise.
* src/xenxs/xen_sxpr.c (xenFormatSxprDisk, xenFormatSxpr):
Likewise.
* src/xenxs/xen_xm.c (xenXMConfigGetUUID, xenFormatXMDisk)
(xenFormatXM): Likewise.
2012-07-23 20:33:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
2012-07-18 11:38:29 +00:00
|
|
|
_("Overwrite and no overwrite flags"
|
|
|
|
" are mutually exclusive"));
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2011-07-06 22:51:23 +00:00
|
|
|
|
2013-05-03 12:49:08 +00:00
|
|
|
if (VIR_STRDUP(parent, pool->def->target.path) < 0)
|
2010-01-20 23:46:32 +00:00
|
|
|
goto error;
|
|
|
|
if (!(p = strrchr(parent, '/'))) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("path '%s' is not absolute"),
|
|
|
|
pool->def->target.path);
|
2010-01-20 23:46:32 +00:00
|
|
|
goto error;
|
2008-02-20 15:45:59 +00:00
|
|
|
}
|
|
|
|
|
2010-01-20 23:46:32 +00:00
|
|
|
if (p != parent) {
|
|
|
|
/* assure all directories in the path prior to the final dir
|
|
|
|
* exist, with default uid/gid/mode. */
|
|
|
|
*p = '\0';
|
2011-07-05 21:02:53 +00:00
|
|
|
if (virFileMakePath(parent) < 0) {
|
|
|
|
virReportSystemError(errno, _("cannot create path '%s'"),
|
2010-01-20 23:46:32 +00:00
|
|
|
parent);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now create the final dir in the path with the uid/gid/mode
|
|
|
|
* requested in the config. If the dir already exists, just set
|
|
|
|
* the perms. */
|
2012-06-19 08:15:27 +00:00
|
|
|
if ((err = virDirCreate(pool->def->target.path,
|
|
|
|
pool->def->target.perms.mode,
|
2012-06-21 07:11:20 +00:00
|
|
|
pool->def->target.perms.uid,
|
|
|
|
pool->def->target.perms.gid,
|
2012-06-19 08:15:27 +00:00
|
|
|
VIR_DIR_CREATE_FORCE_PERMS |
|
|
|
|
VIR_DIR_CREATE_ALLOW_EXIST |
|
|
|
|
(pool->def->type == VIR_STORAGE_POOL_NETFS
|
|
|
|
? VIR_DIR_CREATE_AS_UID : 0)) < 0)) {
|
|
|
|
virReportSystemError(-err, _("cannot create path '%s'"),
|
|
|
|
pool->def->target.path);
|
|
|
|
goto error;
|
2010-01-20 23:46:32 +00:00
|
|
|
}
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
|
2012-06-19 08:15:27 +00:00
|
|
|
/* Reflect the actual uid and gid to the config. */
|
|
|
|
if (pool->def->target.perms.uid == (uid_t) -1)
|
2013-10-09 11:13:45 +00:00
|
|
|
pool->def->target.perms.uid = geteuid();
|
2012-06-19 08:15:27 +00:00
|
|
|
if (pool->def->target.perms.gid == (gid_t) -1)
|
2013-10-09 11:13:45 +00:00
|
|
|
pool->def->target.perms.gid = getegid();
|
2012-06-19 08:15:27 +00:00
|
|
|
|
storage: Add fs pool formatting
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.
2011-08-31 13:54:07 +00:00
|
|
|
if (flags != 0) {
|
|
|
|
ret = virStorageBackendMakeFileSystem(pool, flags);
|
|
|
|
} else {
|
|
|
|
ret = 0;
|
|
|
|
}
|
|
|
|
|
2010-01-20 23:46:32 +00:00
|
|
|
error:
|
|
|
|
VIR_FREE(parent);
|
|
|
|
return ret;
|
2008-02-20 15:45:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Iterate over the pool's directory and enumerate all disk images
|
|
|
|
* within it. This is non-recursive.
|
|
|
|
*/
|
|
|
|
static int
|
2010-02-04 22:46:55 +00:00
|
|
|
virStorageBackendFileSystemRefresh(virConnectPtr conn ATTRIBUTE_UNUSED,
|
2008-02-20 15:45:59 +00:00
|
|
|
virStoragePoolObjPtr pool)
|
|
|
|
{
|
|
|
|
DIR *dir;
|
|
|
|
struct dirent *ent;
|
|
|
|
struct statvfs sb;
|
2008-10-10 15:13:28 +00:00
|
|
|
virStorageVolDefPtr vol = NULL;
|
2008-02-20 15:45:59 +00:00
|
|
|
|
|
|
|
if (!(dir = opendir(pool->def->target.path))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot open path '%s'"),
|
|
|
|
pool->def->target.path);
|
2008-02-20 15:45:59 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((ent = readdir(dir)) != NULL) {
|
|
|
|
int ret;
|
2009-01-27 18:30:03 +00:00
|
|
|
char *backingStore;
|
2010-07-09 10:28:40 +00:00
|
|
|
int backingStoreFormat;
|
2008-02-20 15:45:59 +00:00
|
|
|
|
2008-10-10 15:13:28 +00:00
|
|
|
if (VIR_ALLOC(vol) < 0)
|
2013-07-04 10:16:29 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:45:59 +00:00
|
|
|
|
2013-05-03 12:49:08 +00:00
|
|
|
if (VIR_STRDUP(vol->name, ent->d_name) < 0)
|
|
|
|
goto cleanup;
|
2008-02-20 15:45:59 +00:00
|
|
|
|
2008-11-17 11:19:33 +00:00
|
|
|
vol->type = VIR_STORAGE_VOL_FILE;
|
2009-09-25 13:20:13 +00:00
|
|
|
vol->target.format = VIR_STORAGE_FILE_RAW; /* Real value is filled in during probe */
|
2009-05-19 13:15:50 +00:00
|
|
|
if (virAsprintf(&vol->target.path, "%s/%s",
|
|
|
|
pool->def->target.path,
|
|
|
|
vol->name) == -1)
|
2013-07-04 10:16:29 +00:00
|
|
|
goto cleanup;
|
2008-10-10 15:13:28 +00:00
|
|
|
|
2013-05-03 12:49:08 +00:00
|
|
|
if (VIR_STRDUP(vol->key, vol->target.path) < 0)
|
|
|
|
goto cleanup;
|
2008-02-20 15:45:59 +00:00
|
|
|
|
2010-02-04 22:46:55 +00:00
|
|
|
if ((ret = virStorageBackendProbeTarget(&vol->target,
|
2009-01-27 18:30:03 +00:00
|
|
|
&backingStore,
|
2010-07-09 10:28:40 +00:00
|
|
|
&backingStoreFormat,
|
2009-01-27 18:30:03 +00:00
|
|
|
&vol->allocation,
|
2009-07-20 23:26:09 +00:00
|
|
|
&vol->capacity,
|
2010-01-18 09:34:53 +00:00
|
|
|
&vol->target.encryption)) < 0) {
|
Ignore backing file errors in FS storage pool
Currently a single storage volume with a broken backing file will disable the
whole storage pool. This can happen when the backing file is on some
unavailable network storage or if the backing volume is deleted, while the
storage volumes using it remain.
Since the storage pool can not be re-activated, re-creating the missing
or deleting the now useless volumes using libvirt only is not possible.
Fixing this is a little bit tricky:
1. virStorageBackendProbeTarget() only detects the missing backing file,
if the backing file format is not explicitly specified. If the
backing file is created using
kvm-img create -f qcow2 -o backing_fmt=qcow2,backing_file=... ...
no error is detected at this stage.
The new return code -3 signals that the backing file could not be
opened.
2. The backingStore.format must be >= 0, since values < 0 would break
virStorageVolTargetDefFormat() when dumping the XML data such as
<format type='...'/>
Because of this the format is faked as VIR_STORAGE_FILE_RAW.
3. virStorageBackendUpdateVolTargetInfo() always opens the backing file
and thus always detects a missing backing file.
Since it "only" updates the capacity, allocation, owner, group, mode
and SELinux label, just ignore errors at this stage, print an error
message and continue.
4. Using vol-dump on a broken volume still doesn't work, but at least
vol-destroy and pool-refresh do work now.
To reproduce:
dir=$(mktemp -d)
virsh pool-create-as tmp dir '' '' '' '' "$dir"
virsh vol-create-as --format qcow2 tmp back 1G
virsh vol-create-as --format qcow2 --backing-vol-format qcow2 --backing-vol back tmp cow 1G
virsh vol-delete --pool tmp back
virsh pool-refresh tmp
After the last step, the pool will be gone (because it was not persistent). As
long as the now broken image stays in the directory, you will not be able to
re-create or re-start the pool.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2011-03-01 15:48:20 +00:00
|
|
|
if (ret == -2) {
|
2008-02-20 15:45:59 +00:00
|
|
|
/* Silently ignore non-regular files,
|
2010-12-21 06:45:24 +00:00
|
|
|
* eg '.' '..', 'lost+found', dangling symbolic link */
|
2008-10-10 15:13:28 +00:00
|
|
|
virStorageVolDefFree(vol);
|
|
|
|
vol = NULL;
|
2008-02-20 15:45:59 +00:00
|
|
|
continue;
|
Ignore backing file errors in FS storage pool
Currently a single storage volume with a broken backing file will disable the
whole storage pool. This can happen when the backing file is on some
unavailable network storage or if the backing volume is deleted, while the
storage volumes using it remain.
Since the storage pool can not be re-activated, re-creating the missing
or deleting the now useless volumes using libvirt only is not possible.
Fixing this is a little bit tricky:
1. virStorageBackendProbeTarget() only detects the missing backing file,
if the backing file format is not explicitly specified. If the
backing file is created using
kvm-img create -f qcow2 -o backing_fmt=qcow2,backing_file=... ...
no error is detected at this stage.
The new return code -3 signals that the backing file could not be
opened.
2. The backingStore.format must be >= 0, since values < 0 would break
virStorageVolTargetDefFormat() when dumping the XML data such as
<format type='...'/>
Because of this the format is faked as VIR_STORAGE_FILE_RAW.
3. virStorageBackendUpdateVolTargetInfo() always opens the backing file
and thus always detects a missing backing file.
Since it "only" updates the capacity, allocation, owner, group, mode
and SELinux label, just ignore errors at this stage, print an error
message and continue.
4. Using vol-dump on a broken volume still doesn't work, but at least
vol-destroy and pool-refresh do work now.
To reproduce:
dir=$(mktemp -d)
virsh pool-create-as tmp dir '' '' '' '' "$dir"
virsh vol-create-as --format qcow2 tmp back 1G
virsh vol-create-as --format qcow2 --backing-vol-format qcow2 --backing-vol back tmp cow 1G
virsh vol-delete --pool tmp back
virsh pool-refresh tmp
After the last step, the pool will be gone (because it was not persistent). As
long as the now broken image stays in the directory, you will not be able to
re-create or re-start the pool.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2011-03-01 15:48:20 +00:00
|
|
|
} else if (ret == -3) {
|
|
|
|
/* The backing file is currently unavailable, its format is not
|
|
|
|
* explicitly specified, the probe to auto detect the format
|
|
|
|
* failed: continue with faked RAW format, since AUTO will
|
|
|
|
* break virStorageVolTargetDefFormat() generating the line
|
|
|
|
* <format type='...'/>. */
|
|
|
|
backingStoreFormat = VIR_STORAGE_FILE_RAW;
|
|
|
|
} else
|
|
|
|
goto cleanup;
|
2008-02-20 15:45:59 +00:00
|
|
|
}
|
|
|
|
|
2011-08-11 09:37:17 +00:00
|
|
|
/* directory based volume */
|
|
|
|
if (vol->target.format == VIR_STORAGE_FILE_DIR)
|
|
|
|
vol->type = VIR_STORAGE_VOL_DIR;
|
|
|
|
|
2009-01-27 18:30:03 +00:00
|
|
|
if (backingStore != NULL) {
|
2010-07-09 10:28:40 +00:00
|
|
|
vol->backingStore.path = backingStore;
|
|
|
|
vol->backingStore.format = backingStoreFormat;
|
|
|
|
|
|
|
|
if (virStorageBackendUpdateVolTargetInfo(&vol->backingStore,
|
2011-05-26 18:05:32 +00:00
|
|
|
NULL, NULL,
|
|
|
|
VIR_STORAGE_VOL_OPEN_DEFAULT) < 0) {
|
Ignore backing file errors in FS storage pool
Currently a single storage volume with a broken backing file will disable the
whole storage pool. This can happen when the backing file is on some
unavailable network storage or if the backing volume is deleted, while the
storage volumes using it remain.
Since the storage pool can not be re-activated, re-creating the missing
or deleting the now useless volumes using libvirt only is not possible.
Fixing this is a little bit tricky:
1. virStorageBackendProbeTarget() only detects the missing backing file,
if the backing file format is not explicitly specified. If the
backing file is created using
kvm-img create -f qcow2 -o backing_fmt=qcow2,backing_file=... ...
no error is detected at this stage.
The new return code -3 signals that the backing file could not be
opened.
2. The backingStore.format must be >= 0, since values < 0 would break
virStorageVolTargetDefFormat() when dumping the XML data such as
<format type='...'/>
Because of this the format is faked as VIR_STORAGE_FILE_RAW.
3. virStorageBackendUpdateVolTargetInfo() always opens the backing file
and thus always detects a missing backing file.
Since it "only" updates the capacity, allocation, owner, group, mode
and SELinux label, just ignore errors at this stage, print an error
message and continue.
4. Using vol-dump on a broken volume still doesn't work, but at least
vol-destroy and pool-refresh do work now.
To reproduce:
dir=$(mktemp -d)
virsh pool-create-as tmp dir '' '' '' '' "$dir"
virsh vol-create-as --format qcow2 tmp back 1G
virsh vol-create-as --format qcow2 --backing-vol-format qcow2 --backing-vol back tmp cow 1G
virsh vol-delete --pool tmp back
virsh pool-refresh tmp
After the last step, the pool will be gone (because it was not persistent). As
long as the now broken image stays in the directory, you will not be able to
re-create or re-start the pool.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2011-03-01 15:48:20 +00:00
|
|
|
/* The backing file is currently unavailable, the capacity,
|
|
|
|
* allocation, owner, group and mode are unknown. Just log the
|
2011-12-04 00:06:07 +00:00
|
|
|
* error and continue.
|
Ignore backing file errors in FS storage pool
Currently a single storage volume with a broken backing file will disable the
whole storage pool. This can happen when the backing file is on some
unavailable network storage or if the backing volume is deleted, while the
storage volumes using it remain.
Since the storage pool can not be re-activated, re-creating the missing
or deleting the now useless volumes using libvirt only is not possible.
Fixing this is a little bit tricky:
1. virStorageBackendProbeTarget() only detects the missing backing file,
if the backing file format is not explicitly specified. If the
backing file is created using
kvm-img create -f qcow2 -o backing_fmt=qcow2,backing_file=... ...
no error is detected at this stage.
The new return code -3 signals that the backing file could not be
opened.
2. The backingStore.format must be >= 0, since values < 0 would break
virStorageVolTargetDefFormat() when dumping the XML data such as
<format type='...'/>
Because of this the format is faked as VIR_STORAGE_FILE_RAW.
3. virStorageBackendUpdateVolTargetInfo() always opens the backing file
and thus always detects a missing backing file.
Since it "only" updates the capacity, allocation, owner, group, mode
and SELinux label, just ignore errors at this stage, print an error
message and continue.
4. Using vol-dump on a broken volume still doesn't work, but at least
vol-destroy and pool-refresh do work now.
To reproduce:
dir=$(mktemp -d)
virsh pool-create-as tmp dir '' '' '' '' "$dir"
virsh vol-create-as --format qcow2 tmp back 1G
virsh vol-create-as --format qcow2 --backing-vol-format qcow2 --backing-vol back tmp cow 1G
virsh vol-delete --pool tmp back
virsh pool-refresh tmp
After the last step, the pool will be gone (because it was not persistent). As
long as the now broken image stays in the directory, you will not be able to
re-create or re-start the pool.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2011-03-01 15:48:20 +00:00
|
|
|
* Unfortunately virStorageBackendProbeTarget() might already
|
|
|
|
* have logged a similar message for the same problem, but only
|
|
|
|
* if AUTO format detection was used. */
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot probe backing volume info: %s"),
|
|
|
|
vol->backingStore.path);
|
2009-01-27 18:30:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-10 15:13:28 +00:00
|
|
|
if (VIR_REALLOC_N(pool->volumes.objs,
|
|
|
|
pool->volumes.count+1) < 0)
|
2013-07-04 10:16:29 +00:00
|
|
|
goto cleanup;
|
2008-10-10 15:13:28 +00:00
|
|
|
pool->volumes.objs[pool->volumes.count++] = vol;
|
|
|
|
vol = NULL;
|
2008-02-20 15:45:59 +00:00
|
|
|
}
|
|
|
|
closedir(dir);
|
|
|
|
|
|
|
|
|
|
|
|
if (statvfs(pool->def->target.path, &sb) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot statvfs path '%s'"),
|
|
|
|
pool->def->target.path);
|
2008-02-20 15:45:59 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
pool->def->capacity = ((unsigned long long)sb.f_frsize *
|
|
|
|
(unsigned long long)sb.f_blocks);
|
|
|
|
pool->def->available = ((unsigned long long)sb.f_bfree *
|
2013-02-22 23:43:00 +00:00
|
|
|
(unsigned long long)sb.f_frsize);
|
2008-02-20 15:45:59 +00:00
|
|
|
pool->def->allocation = pool->def->capacity - pool->def->available;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
cleanup:
|
2009-09-02 07:42:32 +00:00
|
|
|
if (dir)
|
|
|
|
closedir(dir);
|
2008-10-10 15:13:28 +00:00
|
|
|
virStorageVolDefFree(vol);
|
2008-02-20 15:45:59 +00:00
|
|
|
virStoragePoolObjClearVols(pool);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @conn connection to report errors against
|
|
|
|
* @pool storage pool to start
|
|
|
|
*
|
2012-11-21 02:41:02 +00:00
|
|
|
* Stops a FS based storage pool.
|
2008-02-20 15:45:59 +00:00
|
|
|
*
|
|
|
|
* - If it is a FS based pool, unmounts the unlying source device on the pool
|
|
|
|
* - Releases all cached data about volumes
|
|
|
|
*/
|
|
|
|
#if WITH_STORAGE_FS
|
|
|
|
static int
|
2010-02-10 11:42:56 +00:00
|
|
|
virStorageBackendFileSystemStop(virConnectPtr conn ATTRIBUTE_UNUSED,
|
2008-02-20 15:45:59 +00:00
|
|
|
virStoragePoolObjPtr pool)
|
|
|
|
{
|
2012-11-21 02:41:02 +00:00
|
|
|
if (virStorageBackendFileSystemUnmount(pool) < 0)
|
2008-02-20 15:45:59 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif /* WITH_STORAGE_FS */
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @conn connection to report errors against
|
|
|
|
* @pool storage pool to build
|
|
|
|
*
|
|
|
|
* Build a directory or FS based storage pool.
|
|
|
|
*
|
|
|
|
* - If it is a FS based pool, mounts the unlying source device on the pool
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
static int
|
2010-02-04 20:02:58 +00:00
|
|
|
virStorageBackendFileSystemDelete(virConnectPtr conn ATTRIBUTE_UNUSED,
|
2008-02-20 15:45:59 +00:00
|
|
|
virStoragePoolObjPtr pool,
|
2011-07-06 22:51:23 +00:00
|
|
|
unsigned int flags)
|
2008-02-20 15:45:59 +00:00
|
|
|
{
|
2011-07-06 22:51:23 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2008-02-20 15:45:59 +00:00
|
|
|
/* XXX delete all vols first ? */
|
|
|
|
|
2009-12-14 15:15:28 +00:00
|
|
|
if (rmdir(pool->def->target.path) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-12-14 15:15:28 +00:00
|
|
|
_("failed to remove pool '%s'"),
|
2009-01-20 17:13:33 +00:00
|
|
|
pool->def->target.path);
|
2008-02-20 15:45:59 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2009-04-17 19:12:37 +00:00
|
|
|
* Set up a volume definition to be added to a pool's volume list, but
|
|
|
|
* don't do any file creation or allocation. By separating the two processes,
|
|
|
|
* we allow allocation progress reporting (by polling the volume's 'info'
|
|
|
|
* function), and can drop the parent pool lock during the (slow) allocation.
|
2008-02-20 15:45:59 +00:00
|
|
|
*/
|
|
|
|
static int
|
2010-02-04 18:19:08 +00:00
|
|
|
virStorageBackendFileSystemVolCreate(virConnectPtr conn ATTRIBUTE_UNUSED,
|
2008-02-20 15:45:59 +00:00
|
|
|
virStoragePoolObjPtr pool,
|
|
|
|
virStorageVolDefPtr vol)
|
|
|
|
{
|
|
|
|
|
2009-05-19 13:15:50 +00:00
|
|
|
vol->type = VIR_STORAGE_VOL_FILE;
|
|
|
|
|
2009-09-04 13:56:32 +00:00
|
|
|
VIR_FREE(vol->target.path);
|
2009-05-19 13:15:50 +00:00
|
|
|
if (virAsprintf(&vol->target.path, "%s/%s",
|
|
|
|
pool->def->target.path,
|
2013-07-04 10:16:29 +00:00
|
|
|
vol->name) == -1)
|
2008-02-20 15:45:59 +00:00
|
|
|
return -1;
|
2009-05-19 13:15:50 +00:00
|
|
|
|
2012-12-05 04:44:11 +00:00
|
|
|
if (virFileExists(vol->target.path)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume target path '%s' already exists"),
|
|
|
|
vol->target.path);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-09-04 13:56:32 +00:00
|
|
|
VIR_FREE(vol->key);
|
2013-05-03 12:49:08 +00:00
|
|
|
return VIR_STRDUP(vol->key, vol->target.path);
|
2009-04-17 19:12:37 +00:00
|
|
|
}
|
|
|
|
|
2010-02-10 11:42:56 +00:00
|
|
|
static int createFileDir(virConnectPtr conn ATTRIBUTE_UNUSED,
|
2010-01-20 23:41:52 +00:00
|
|
|
virStoragePoolObjPtr pool,
|
2009-05-19 13:43:48 +00:00
|
|
|
virStorageVolDefPtr vol,
|
2009-07-16 16:27:07 +00:00
|
|
|
virStorageVolDefPtr inputvol,
|
2011-07-06 22:51:23 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2010-01-20 23:41:52 +00:00
|
|
|
int err;
|
|
|
|
|
2011-07-06 22:51:23 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2009-05-19 13:43:48 +00:00
|
|
|
if (inputvol) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s",
|
|
|
|
_("cannot copy from volume to a directory volume"));
|
2009-05-19 13:43:48 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-01-20 23:41:52 +00:00
|
|
|
if ((err = virDirCreate(vol->target.path, vol->target.perms.mode,
|
2012-06-21 07:11:20 +00:00
|
|
|
vol->target.perms.uid,
|
|
|
|
vol->target.perms.gid,
|
Rename virFileCreate to virFileOperation, add hook function
It turns out it is also useful to be able to perform other operations
on a file created while running as a different uid (eg, write things
to that file), and possibly to do this to a file that already
exists. This patch adds an optional hook function to the renamed (for
more accuracy of purpose) virFileOperation; the hook will be called
after the file has been opened (possibly created) and gid/mode
checked/set, before closing it.
As with the other operations on the file, if the VIR_FILE_OP_AS_UID
flag is set, this hook function will be called in the context of a
child process forked from the process that called virFileOperation.
The implication here is that, while all data in memory is available to
this hook function, any modification to that data will not be seen by
the caller - the only indication in memory of what happened in the
hook will be the return value (which the hook should set to 0 on
success, or one of the standard errno values on failure).
Another piece of making the function more flexible was to add an
"openflags" argument. This arg should contain exactly the flags to be
passed to open(2), eg O_RDWR | O_EXCL, etc.
In the process of adding the hook to virFileOperation, I also realized
that the bits to fix up file owner/group/mode settings after creation
were being done in the parent process, which could fail, so I moved
them to the child process where they should be.
* src/util/util.[ch]: rename and rework virFileCreate-->virFileOperation,
and redo flags in virDirCreate
* storage/storage_backend.c, storage/storage_backend_fs.c: update the
calls to virFileOperation/virDirCreate to reflect changes in the API,
but don't yet take advantage of the hook.
2010-02-19 16:43:22 +00:00
|
|
|
VIR_DIR_CREATE_FORCE_PERMS |
|
2010-01-20 23:41:52 +00:00
|
|
|
(pool->def->type == VIR_STORAGE_POOL_NETFS
|
2010-07-19 23:48:59 +00:00
|
|
|
? VIR_DIR_CREATE_AS_UID : 0))) < 0) {
|
|
|
|
virReportSystemError(-err, _("cannot create path '%s'"),
|
2009-05-12 20:27:17 +00:00
|
|
|
vol->target.path);
|
|
|
|
return -1;
|
|
|
|
}
|
2008-02-20 15:45:59 +00:00
|
|
|
|
2009-05-12 20:27:17 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2008-02-20 15:45:59 +00:00
|
|
|
|
2009-05-12 20:27:17 +00:00
|
|
|
static int
|
2009-05-19 13:43:48 +00:00
|
|
|
_virStorageBackendFileSystemVolBuild(virConnectPtr conn,
|
2010-01-20 23:41:52 +00:00
|
|
|
virStoragePoolObjPtr pool,
|
2009-05-19 13:43:48 +00:00
|
|
|
virStorageVolDefPtr vol,
|
2012-12-05 10:48:07 +00:00
|
|
|
virStorageVolDefPtr inputvol,
|
|
|
|
unsigned int flags)
|
2009-05-12 20:27:17 +00:00
|
|
|
{
|
2009-07-16 16:27:07 +00:00
|
|
|
virStorageBackendBuildVolFrom create_func;
|
2009-06-25 21:28:23 +00:00
|
|
|
int tool_type;
|
2009-05-12 20:27:17 +00:00
|
|
|
|
2009-06-25 21:28:23 +00:00
|
|
|
if (inputvol) {
|
2009-07-21 02:40:50 +00:00
|
|
|
if (vol->target.encryption != NULL) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
"%s", _("storage pool does not support "
|
|
|
|
"building encrypted volumes from "
|
|
|
|
"other volumes"));
|
2009-07-21 02:40:50 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2010-02-10 11:42:56 +00:00
|
|
|
create_func = virStorageBackendGetBuildVolFromFunction(vol,
|
2009-07-16 16:09:26 +00:00
|
|
|
inputvol);
|
2009-06-25 21:28:23 +00:00
|
|
|
if (!create_func)
|
|
|
|
return -1;
|
2009-09-25 13:20:13 +00:00
|
|
|
} else if (vol->target.format == VIR_STORAGE_FILE_RAW) {
|
2009-07-16 16:09:26 +00:00
|
|
|
create_func = virStorageBackendCreateRaw;
|
2009-09-25 13:20:13 +00:00
|
|
|
} else if (vol->target.format == VIR_STORAGE_FILE_DIR) {
|
2009-05-12 20:27:17 +00:00
|
|
|
create_func = createFileDir;
|
2009-07-16 16:09:26 +00:00
|
|
|
} else if ((tool_type = virStorageBackendFindFSImageTool(NULL)) != -1) {
|
2010-02-10 11:42:56 +00:00
|
|
|
create_func = virStorageBackendFSImageToolTypeToFunc(tool_type);
|
2009-07-16 16:09:26 +00:00
|
|
|
|
|
|
|
if (!create_func)
|
2009-06-25 21:28:23 +00:00
|
|
|
return -1;
|
2009-06-11 13:18:56 +00:00
|
|
|
} else {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("creation of non-raw images "
|
|
|
|
"is not supported without qemu-img"));
|
2008-02-20 15:45:59 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-12-05 10:48:07 +00:00
|
|
|
if (create_func(conn, pool, vol, inputvol, flags) < 0)
|
2009-05-12 20:27:17 +00:00
|
|
|
return -1;
|
2008-02-20 15:45:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-05-19 13:43:48 +00:00
|
|
|
/**
|
|
|
|
* Allocate a new file as a volume. This is either done directly
|
|
|
|
* for raw/sparse files, or by calling qemu-img/qcow-create for
|
|
|
|
* special kinds of files
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
virStorageBackendFileSystemVolBuild(virConnectPtr conn,
|
2010-01-20 23:41:52 +00:00
|
|
|
virStoragePoolObjPtr pool,
|
2012-12-05 10:48:07 +00:00
|
|
|
virStorageVolDefPtr vol,
|
2013-05-31 12:26:16 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2012-12-05 10:48:07 +00:00
|
|
|
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1);
|
|
|
|
|
|
|
|
return _virStorageBackendFileSystemVolBuild(conn, pool, vol, NULL, flags);
|
2009-05-19 13:43:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create a storage vol using 'inputvol' as input
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
virStorageBackendFileSystemVolBuildFrom(virConnectPtr conn,
|
2010-01-20 23:41:52 +00:00
|
|
|
virStoragePoolObjPtr pool,
|
2009-05-19 13:43:48 +00:00
|
|
|
virStorageVolDefPtr vol,
|
|
|
|
virStorageVolDefPtr inputvol,
|
2011-07-06 22:51:23 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2012-12-05 10:48:07 +00:00
|
|
|
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1);
|
2011-07-06 22:51:23 +00:00
|
|
|
|
2012-12-05 10:48:07 +00:00
|
|
|
return _virStorageBackendFileSystemVolBuild(conn, pool, vol, inputvol, flags);
|
2009-05-19 13:43:48 +00:00
|
|
|
}
|
2008-02-20 15:45:59 +00:00
|
|
|
|
|
|
|
/**
|
2012-07-11 15:34:58 +00:00
|
|
|
* Remove a volume - no support for BLOCK and NETWORK yet
|
2008-02-20 15:45:59 +00:00
|
|
|
*/
|
|
|
|
static int
|
2010-02-04 20:02:58 +00:00
|
|
|
virStorageBackendFileSystemVolDelete(virConnectPtr conn ATTRIBUTE_UNUSED,
|
2008-02-20 15:45:59 +00:00
|
|
|
virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
|
|
|
|
virStorageVolDefPtr vol,
|
2011-07-06 22:51:23 +00:00
|
|
|
unsigned int flags)
|
2008-02-20 15:45:59 +00:00
|
|
|
{
|
2011-07-06 22:51:23 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2013-11-18 23:43:06 +00:00
|
|
|
switch ((virStorageVolType) vol->type) {
|
2012-07-11 15:34:58 +00:00
|
|
|
case VIR_STORAGE_VOL_FILE:
|
|
|
|
if (unlink(vol->target.path) < 0) {
|
|
|
|
/* Silently ignore failures where the vol has already gone away */
|
|
|
|
if (errno != ENOENT) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("cannot unlink file '%s'"),
|
|
|
|
vol->target.path);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case VIR_STORAGE_VOL_DIR:
|
|
|
|
if (rmdir(vol->target.path) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2012-07-11 15:34:58 +00:00
|
|
|
_("cannot remove directory '%s'"),
|
2009-01-20 17:13:33 +00:00
|
|
|
vol->target.path);
|
2008-02-20 15:45:59 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2012-07-11 15:34:58 +00:00
|
|
|
break;
|
|
|
|
case VIR_STORAGE_VOL_BLOCK:
|
|
|
|
case VIR_STORAGE_VOL_NETWORK:
|
2013-11-18 23:43:06 +00:00
|
|
|
case VIR_STORAGE_VOL_NETDIR:
|
|
|
|
case VIR_STORAGE_VOL_LAST:
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_NO_SUPPORT,
|
|
|
|
_("removing block or network volumes is not supported: %s"),
|
|
|
|
vol->target.path);
|
2012-07-11 15:34:58 +00:00
|
|
|
return -1;
|
2008-02-20 15:45:59 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Update info about a volume's capacity/allocation
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
virStorageBackendFileSystemVolRefresh(virConnectPtr conn,
|
|
|
|
virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
|
|
|
|
virStorageVolDefPtr vol)
|
|
|
|
{
|
2009-09-11 13:13:45 +00:00
|
|
|
int ret;
|
|
|
|
|
2008-02-20 15:45:59 +00:00
|
|
|
/* Refresh allocation / permissions info in case its changed */
|
2011-05-26 18:05:32 +00:00
|
|
|
ret = virStorageBackendUpdateVolInfoFlags(vol, 0,
|
|
|
|
VIR_STORAGE_VOL_FS_OPEN_FLAGS);
|
2009-09-11 13:13:45 +00:00
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
/* Load any secrets if posible */
|
|
|
|
if (vol->target.encryption &&
|
|
|
|
vol->target.encryption->format == VIR_STORAGE_ENCRYPTION_FORMAT_QCOW &&
|
|
|
|
vol->target.encryption->nsecrets == 0) {
|
|
|
|
virSecretPtr sec;
|
|
|
|
virStorageEncryptionSecretPtr encsec = NULL;
|
|
|
|
|
|
|
|
sec = virSecretLookupByUsage(conn,
|
|
|
|
VIR_SECRET_USAGE_TYPE_VOLUME,
|
|
|
|
vol->target.path);
|
|
|
|
if (sec) {
|
|
|
|
if (VIR_ALLOC_N(vol->target.encryption->secrets, 1) < 0 ||
|
|
|
|
VIR_ALLOC(encsec) < 0) {
|
|
|
|
VIR_FREE(vol->target.encryption->secrets);
|
|
|
|
virSecretFree(sec);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
vol->target.encryption->nsecrets = 1;
|
|
|
|
vol->target.encryption->secrets[0] = encsec;
|
|
|
|
|
|
|
|
encsec->type = VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE;
|
|
|
|
virSecretGetUUID(sec, encsec->uuid);
|
|
|
|
virSecretFree(sec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2008-02-20 15:45:59 +00:00
|
|
|
}
|
|
|
|
|
2012-01-30 07:40:00 +00:00
|
|
|
static int
|
|
|
|
virStorageBackendFilesystemResizeQemuImg(const char *path,
|
|
|
|
unsigned long long capacity)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
char *img_tool;
|
|
|
|
virCommandPtr cmd = NULL;
|
|
|
|
|
|
|
|
/* KVM is usually ahead of qemu on features, so try that first */
|
|
|
|
img_tool = virFindFileInPath("kvm-img");
|
|
|
|
if (!img_tool)
|
|
|
|
img_tool = virFindFileInPath("qemu-img");
|
|
|
|
|
|
|
|
if (!img_tool) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("unable to find kvm-img or qemu-img"));
|
2012-01-30 07:40:00 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-05-14 13:48:21 +00:00
|
|
|
/* Round capacity as qemu-img resize errors out on sizes which are not
|
|
|
|
* a multiple of 512 */
|
|
|
|
capacity = VIR_ROUND_UP(capacity, 512);
|
|
|
|
|
2012-01-30 07:40:00 +00:00
|
|
|
cmd = virCommandNew(img_tool);
|
|
|
|
virCommandAddArgList(cmd, "resize", path, NULL);
|
|
|
|
virCommandAddArgFormat(cmd, "%llu", capacity);
|
|
|
|
|
|
|
|
ret = virCommandRun(cmd, NULL);
|
|
|
|
|
|
|
|
VIR_FREE(img_tool);
|
|
|
|
virCommandFree(cmd);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Resize a volume
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
virStorageBackendFileSystemVolResize(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|
|
|
virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
|
|
|
|
virStorageVolDefPtr vol,
|
|
|
|
unsigned long long capacity,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2013-05-31 05:16:14 +00:00
|
|
|
virCheckFlags(VIR_STORAGE_VOL_RESIZE_ALLOCATE, -1);
|
|
|
|
|
|
|
|
bool pre_allocate = flags & VIR_STORAGE_VOL_RESIZE_ALLOCATE;
|
|
|
|
|
|
|
|
if (vol->target.format == VIR_STORAGE_FILE_RAW) {
|
|
|
|
return virStorageFileResize(vol->target.path, capacity,
|
2013-12-16 05:00:00 +00:00
|
|
|
vol->allocation, pre_allocate);
|
2013-05-31 05:16:14 +00:00
|
|
|
} else {
|
|
|
|
if (pre_allocate) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
|
|
|
_("preallocate is only supported for raw "
|
|
|
|
"type volume"));
|
|
|
|
return -1;
|
|
|
|
}
|
2012-01-30 07:40:00 +00:00
|
|
|
|
|
|
|
return virStorageBackendFilesystemResizeQemuImg(vol->target.path,
|
|
|
|
capacity);
|
2013-05-31 05:16:14 +00:00
|
|
|
}
|
2012-01-30 07:40:00 +00:00
|
|
|
}
|
|
|
|
|
2008-02-20 15:45:59 +00:00
|
|
|
virStorageBackend virStorageBackendDirectory = {
|
|
|
|
.type = VIR_STORAGE_POOL_DIR,
|
|
|
|
|
|
|
|
.buildPool = virStorageBackendFileSystemBuild,
|
2010-11-11 20:09:20 +00:00
|
|
|
.checkPool = virStorageBackendFileSystemCheck,
|
2008-02-20 15:45:59 +00:00
|
|
|
.refreshPool = virStorageBackendFileSystemRefresh,
|
|
|
|
.deletePool = virStorageBackendFileSystemDelete,
|
2009-04-17 19:12:37 +00:00
|
|
|
.buildVol = virStorageBackendFileSystemVolBuild,
|
2009-05-19 13:43:48 +00:00
|
|
|
.buildVolFrom = virStorageBackendFileSystemVolBuildFrom,
|
2008-02-20 15:45:59 +00:00
|
|
|
.createVol = virStorageBackendFileSystemVolCreate,
|
|
|
|
.refreshVol = virStorageBackendFileSystemVolRefresh,
|
|
|
|
.deleteVol = virStorageBackendFileSystemVolDelete,
|
2012-01-30 07:40:00 +00:00
|
|
|
.resizeVol = virStorageBackendFileSystemVolResize,
|
2008-02-20 15:45:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#if WITH_STORAGE_FS
|
|
|
|
virStorageBackend virStorageBackendFileSystem = {
|
|
|
|
.type = VIR_STORAGE_POOL_FS,
|
|
|
|
|
|
|
|
.buildPool = virStorageBackendFileSystemBuild,
|
2010-11-11 20:09:20 +00:00
|
|
|
.checkPool = virStorageBackendFileSystemCheck,
|
2008-02-20 15:45:59 +00:00
|
|
|
.startPool = virStorageBackendFileSystemStart,
|
|
|
|
.refreshPool = virStorageBackendFileSystemRefresh,
|
|
|
|
.stopPool = virStorageBackendFileSystemStop,
|
|
|
|
.deletePool = virStorageBackendFileSystemDelete,
|
2009-04-17 19:12:37 +00:00
|
|
|
.buildVol = virStorageBackendFileSystemVolBuild,
|
2009-05-19 13:43:48 +00:00
|
|
|
.buildVolFrom = virStorageBackendFileSystemVolBuildFrom,
|
2008-02-20 15:45:59 +00:00
|
|
|
.createVol = virStorageBackendFileSystemVolCreate,
|
|
|
|
.refreshVol = virStorageBackendFileSystemVolRefresh,
|
|
|
|
.deleteVol = virStorageBackendFileSystemVolDelete,
|
2012-01-30 07:40:00 +00:00
|
|
|
.resizeVol = virStorageBackendFileSystemVolResize,
|
2008-02-20 15:45:59 +00:00
|
|
|
};
|
|
|
|
virStorageBackend virStorageBackendNetFileSystem = {
|
|
|
|
.type = VIR_STORAGE_POOL_NETFS,
|
|
|
|
|
|
|
|
.buildPool = virStorageBackendFileSystemBuild,
|
2010-11-11 20:09:20 +00:00
|
|
|
.checkPool = virStorageBackendFileSystemCheck,
|
2008-02-20 15:45:59 +00:00
|
|
|
.startPool = virStorageBackendFileSystemStart,
|
2008-08-27 20:05:58 +00:00
|
|
|
.findPoolSources = virStorageBackendFileSystemNetFindPoolSources,
|
2008-02-20 15:45:59 +00:00
|
|
|
.refreshPool = virStorageBackendFileSystemRefresh,
|
|
|
|
.stopPool = virStorageBackendFileSystemStop,
|
|
|
|
.deletePool = virStorageBackendFileSystemDelete,
|
2009-04-17 19:12:37 +00:00
|
|
|
.buildVol = virStorageBackendFileSystemVolBuild,
|
2009-05-19 13:43:48 +00:00
|
|
|
.buildVolFrom = virStorageBackendFileSystemVolBuildFrom,
|
2008-02-20 15:45:59 +00:00
|
|
|
.createVol = virStorageBackendFileSystemVolCreate,
|
|
|
|
.refreshVol = virStorageBackendFileSystemVolRefresh,
|
|
|
|
.deleteVol = virStorageBackendFileSystemVolDelete,
|
2012-01-30 07:40:00 +00:00
|
|
|
.resizeVol = virStorageBackendFileSystemVolResize,
|
2008-02-20 15:45:59 +00:00
|
|
|
};
|
|
|
|
#endif /* WITH_STORAGE_FS */
|