2008-02-20 15:45:59 +00:00
|
|
|
/*
|
|
|
|
* storage_backend_fs.c: storage backend for FS and directory handling
|
|
|
|
*
|
2015-12-09 00:46:31 +00:00
|
|
|
* Copyright (C) 2007-2015 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
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2008-02-20 15:45:59 +00:00
|
|
|
#include "storage_backend_fs.h"
|
2017-01-11 17:04:15 +00:00
|
|
|
#include "storage_util.h"
|
2008-02-20 15:45:59 +00:00
|
|
|
#include "storage_conf.h"
|
2012-12-12 16:27:01 +00:00
|
|
|
#include "vircommand.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.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
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("storage.storage_backend_fs");
|
|
|
|
|
2008-02-20 15:45:59 +00:00
|
|
|
#if WITH_STORAGE_FS
|
2009-01-06 08:43:44 +00:00
|
|
|
|
2019-01-07 22:14:57 +00:00
|
|
|
# include <libxml/xpathInternals.h>
|
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
|
2014-03-18 14:35:01 +00:00
|
|
|
virStorageBackendFileSystemNetFindPoolSourcesFunc(char **const groups,
|
2008-08-27 20:05:58 +00:00
|
|
|
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;
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2009-10-15 15:41:53 +00:00
|
|
|
return ret;
|
2008-08-27 20:05:58 +00:00
|
|
|
}
|
|
|
|
|
2009-10-15 15:41:53 +00:00
|
|
|
|
2014-04-09 16:17:39 +00:00
|
|
|
static int
|
2014-03-26 16:25:40 +00:00
|
|
|
virStorageBackendFileSystemNetFindNFSPoolSources(virNetfsDiscoverState *state)
|
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
|
|
|
|
};
|
2014-03-26 16:25:40 +00:00
|
|
|
|
2019-01-31 18:16:44 +00:00
|
|
|
VIR_AUTOPTR(virCommand) cmd = NULL;
|
2014-03-26 16:25:40 +00:00
|
|
|
|
|
|
|
cmd = virCommandNewArgList(SHOWMOUNT,
|
|
|
|
"--no-headers",
|
|
|
|
"--exports",
|
|
|
|
state->host,
|
|
|
|
NULL);
|
|
|
|
|
2019-01-31 18:16:44 +00:00
|
|
|
return virCommandRunRegex(cmd, 1, regexes, vars,
|
|
|
|
virStorageBackendFileSystemNetFindPoolSourcesFunc,
|
|
|
|
state, NULL, NULL);
|
2014-03-26 16:25:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static char *
|
2018-01-26 13:31:58 +00:00
|
|
|
virStorageBackendFileSystemNetFindPoolSources(const char *srcSpec,
|
2014-03-26 16:25:40 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2008-11-04 21:54:21 +00:00
|
|
|
virNetfsDiscoverState state = {
|
|
|
|
.host = NULL,
|
|
|
|
.list = {
|
|
|
|
.type = VIR_STORAGE_POOL_NETFS,
|
|
|
|
.nsources = 0,
|
|
|
|
.sources = NULL
|
|
|
|
}
|
|
|
|
};
|
2014-03-26 16:25:40 +00:00
|
|
|
char *ret = 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;
|
2017-01-10 17:29:54 +00:00
|
|
|
int retNFS = -1;
|
|
|
|
int retGluster = 0;
|
2019-01-31 13:48:11 +00:00
|
|
|
VIR_AUTOPTR(virStoragePoolSource) source = 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) {
|
2014-03-26 16:25:40 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("hostname must be specified for netfs sources"));
|
2012-07-31 08:56:41 +00:00
|
|
|
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
|
|
|
|
2014-04-09 16:17:39 +00:00
|
|
|
retNFS = virStorageBackendFileSystemNetFindNFSPoolSources(&state);
|
2008-08-27 20:05:58 +00:00
|
|
|
|
2017-01-10 17:29:54 +00:00
|
|
|
retGluster = virStorageBackendFindGlusterPoolSources(state.host,
|
2017-03-30 13:08:06 +00:00
|
|
|
VIR_STORAGE_POOL_NETFS,
|
2017-01-09 14:56:12 +00:00
|
|
|
&state.list, false);
|
2017-01-10 17:29:54 +00:00
|
|
|
|
|
|
|
if (retGluster < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-04-09 16:17:39 +00:00
|
|
|
/* If both fail, then we won't return an empty list - return an error */
|
2017-01-10 17:29:54 +00:00
|
|
|
if (retNFS < 0 && retGluster == 0) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("no storage pools were found on host '%s'"),
|
|
|
|
state.host);
|
2014-03-26 18:17:55 +00:00
|
|
|
goto cleanup;
|
2017-01-10 17:29:54 +00:00
|
|
|
}
|
2014-03-26 18:17:55 +00:00
|
|
|
|
2014-03-26 16:25:40 +00:00
|
|
|
if (!(ret = virStoragePoolSourceListFormat(&state.list)))
|
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
|
|
|
|
2014-03-26 16:25:40 +00:00
|
|
|
return ret;
|
2008-08-27 20:05:58 +00:00
|
|
|
}
|
|
|
|
|
2015-06-02 23:35:35 +00:00
|
|
|
/**
|
|
|
|
* @pool storage pool to check FS types
|
|
|
|
*
|
|
|
|
* Determine if storage pool FS types are properly set up
|
|
|
|
*
|
|
|
|
* Return 0 if everything's OK, -1 on error
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
virStorageBackendFileSystemIsValid(virStoragePoolObjPtr pool)
|
|
|
|
{
|
2017-07-26 18:21:08 +00:00
|
|
|
virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
|
|
|
|
|
|
|
|
if (def->type == VIR_STORAGE_POOL_NETFS) {
|
|
|
|
if (def->source.nhost != 1) {
|
2015-06-02 23:35:35 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("expected exactly 1 host for the storage pool"));
|
|
|
|
return -1;
|
|
|
|
}
|
2017-07-26 18:21:08 +00:00
|
|
|
if (def->source.hosts[0].name == NULL) {
|
2015-06-02 23:35:35 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("missing source host"));
|
|
|
|
return -1;
|
|
|
|
}
|
2017-07-26 18:21:08 +00:00
|
|
|
if (def->source.dir == NULL) {
|
2015-06-02 23:35:35 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("missing source path"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
2017-07-26 18:21:08 +00:00
|
|
|
if (def->source.ndevice != 1) {
|
|
|
|
if (def->source.ndevice == 0)
|
2015-06-02 20:25:58 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("missing source device"));
|
|
|
|
else
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("expected exactly 1 device for the "
|
|
|
|
"storage pool"));
|
2015-06-02 23:35:35 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2008-08-27 20:05:58 +00:00
|
|
|
|
2015-12-07 13:19:34 +00:00
|
|
|
|
2008-02-20 15:45:59 +00:00
|
|
|
/**
|
|
|
|
* @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
|
2014-03-18 08:15:36 +00:00
|
|
|
virStorageBackendFileSystemIsMounted(virStoragePoolObjPtr pool)
|
|
|
|
{
|
2015-12-07 13:26:42 +00:00
|
|
|
int ret = -1;
|
2017-07-26 18:21:08 +00:00
|
|
|
virStoragePoolDefPtr def = virStoragePoolObjGetDef(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];
|
2017-02-07 09:19:21 +00:00
|
|
|
int rc1, rc2;
|
2019-01-31 17:09:38 +00:00
|
|
|
VIR_AUTOFREE(char *) src = NULL;
|
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);
|
2015-12-07 13:26:42 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:45:59 +00:00
|
|
|
}
|
|
|
|
|
2009-01-22 19:41:48 +00:00
|
|
|
while ((getmntent_r(mtab, &ent, buf, sizeof(buf))) != NULL) {
|
2015-12-07 13:35:57 +00:00
|
|
|
if (!(src = virStorageBackendFileSystemGetPoolSource(pool)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2017-02-07 09:19:21 +00:00
|
|
|
/* compare both mount destinations and sources to be sure the mounted
|
|
|
|
* FS pool is really the one we're looking for
|
|
|
|
*/
|
2017-07-26 18:21:08 +00:00
|
|
|
if ((rc1 = virFileComparePaths(ent.mnt_dir, def->target.path)) < 0 ||
|
2017-02-07 09:19:21 +00:00
|
|
|
(rc2 = virFileComparePaths(ent.mnt_fsname, src)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (rc1 && rc2) {
|
2015-12-07 13:26:42 +00:00
|
|
|
ret = 1;
|
|
|
|
goto cleanup;
|
2008-02-20 15:45:59 +00:00
|
|
|
}
|
2015-12-07 13:35:57 +00:00
|
|
|
|
|
|
|
VIR_FREE(src);
|
2008-02-20 15:45:59 +00:00
|
|
|
}
|
|
|
|
|
2015-12-07 13:26:42 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2010-11-17 02:13:29 +00:00
|
|
|
VIR_FORCE_FCLOSE(mtab);
|
2015-12-07 13:26:42 +00:00
|
|
|
return ret;
|
2008-02-20 15:45:59 +00:00
|
|
|
}
|
|
|
|
|
2018-12-04 11:28:34 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @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
|
|
|
|
virStorageBackendFileSystemMount(virStoragePoolObjPtr pool)
|
|
|
|
{
|
|
|
|
virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
|
|
|
|
int rc;
|
2019-01-31 17:09:38 +00:00
|
|
|
VIR_AUTOFREE(char *) src = NULL;
|
2019-01-31 18:16:44 +00:00
|
|
|
VIR_AUTOPTR(virCommand) cmd = NULL;
|
2018-12-04 11:28:34 +00:00
|
|
|
|
|
|
|
if (virStorageBackendFileSystemIsValid(pool) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if ((rc = virStorageBackendFileSystemIsMounted(pool)) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* Short-circuit if already mounted */
|
|
|
|
if (rc == 1) {
|
|
|
|
VIR_INFO("Target '%s' is already mounted", def->target.path);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(src = virStorageBackendFileSystemGetPoolSource(pool)))
|
|
|
|
return -1;
|
|
|
|
|
2018-12-13 16:11:18 +00:00
|
|
|
cmd = virStorageBackendFileSystemMountCmd(MOUNT, def, src);
|
2019-01-31 17:09:38 +00:00
|
|
|
return virCommandRun(cmd, NULL);
|
2008-02-20 15:45:59 +00:00
|
|
|
}
|
|
|
|
|
2017-01-21 16:47:23 +00:00
|
|
|
|
2008-02-20 15:45:59 +00:00
|
|
|
/**
|
2017-01-21 16:47:23 +00:00
|
|
|
* @pool storage pool to start
|
|
|
|
*
|
|
|
|
* Starts a directory or FS based storage pool. The underlying source
|
|
|
|
* device will be mounted for FS based pools.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
static int
|
2018-01-26 13:31:58 +00:00
|
|
|
virStorageBackendFileSystemStart(virStoragePoolObjPtr pool)
|
2017-01-21 16:47:23 +00:00
|
|
|
{
|
2017-07-26 18:21:08 +00:00
|
|
|
virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
|
|
|
|
|
|
|
|
if (def->type != VIR_STORAGE_POOL_DIR &&
|
2017-01-21 16:47:23 +00:00
|
|
|
virStorageBackendFileSystemMount(pool) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2008-02-20 15:45:59 +00:00
|
|
|
* @pool storage pool to unmount
|
|
|
|
*
|
2017-01-21 16:47:23 +00:00
|
|
|
* Stops a file storage pool. The underlying source device is unmounted
|
|
|
|
* for FS based pools. Any cached data about volumes is released.
|
|
|
|
*
|
2008-02-20 15:45:59 +00:00
|
|
|
* Ensure that a FS storage pool is not mounted on its target location.
|
2014-01-10 10:51:04 +00:00
|
|
|
* If already unmounted, this is a no-op.
|
2008-02-20 15:45:59 +00:00
|
|
|
*
|
|
|
|
* Returns 0 if successfully unmounted, -1 on error
|
|
|
|
*/
|
|
|
|
static int
|
2018-01-26 13:31:58 +00:00
|
|
|
virStorageBackendFileSystemStop(virStoragePoolObjPtr pool)
|
2014-03-18 08:15:36 +00:00
|
|
|
{
|
2017-07-26 18:21:08 +00:00
|
|
|
virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
|
2012-11-21 03:22:39 +00:00
|
|
|
int rc;
|
2019-01-31 18:16:44 +00:00
|
|
|
VIR_AUTOPTR(virCommand) cmd = NULL;
|
2008-02-20 15:45:59 +00:00
|
|
|
|
2015-06-02 23:35:35 +00:00
|
|
|
if (virStorageBackendFileSystemIsValid(pool) < 0)
|
|
|
|
return -1;
|
2008-02-20 15:45:59 +00:00
|
|
|
|
|
|
|
/* 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
|
|
|
|
2017-07-26 18:21:08 +00:00
|
|
|
cmd = virCommandNewArgList(UMOUNT, def->target.path, NULL);
|
2019-01-31 18:16:44 +00:00
|
|
|
return virCommandRun(cmd, NULL);
|
2008-02-20 15:45:59 +00:00
|
|
|
}
|
|
|
|
#endif /* WITH_STORAGE_FS */
|
|
|
|
|
|
|
|
|
2010-11-11 20:09:20 +00:00
|
|
|
static int
|
2015-03-09 14:34:35 +00:00
|
|
|
virStorageBackendFileSystemCheck(virStoragePoolObjPtr pool,
|
2010-11-11 20:09:20 +00:00
|
|
|
bool *isActive)
|
|
|
|
{
|
2017-07-26 18:21:08 +00:00
|
|
|
virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
|
|
|
|
|
|
|
|
if (def->type == VIR_STORAGE_POOL_DIR) {
|
|
|
|
*isActive = virFileExists(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;
|
2015-06-02 23:48:56 +00:00
|
|
|
|
|
|
|
if (virStorageBackendFileSystemIsValid(pool) < 0)
|
|
|
|
return -1;
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{
|
2019-01-31 18:16:44 +00:00
|
|
|
VIR_AUTOPTR(virCommand) cmd = NULL;
|
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
|
|
|
|
2014-04-03 09:09:14 +00:00
|
|
|
cmd = virCommandNewArgList(MKFS, "-t", format, NULL);
|
|
|
|
|
2016-11-15 20:29:47 +00:00
|
|
|
/* use the force, otherwise mkfs.xfs won't overwrite existing fs.
|
|
|
|
* Similarly mkfs.ext2, mkfs.ext3, and mkfs.ext4 require supplying -F
|
|
|
|
* and mkfs.vfat uses -I */
|
2014-04-03 09:09:14 +00:00
|
|
|
if (STREQ(format, "xfs"))
|
|
|
|
virCommandAddArg(cmd, "-f");
|
2016-11-15 20:29:47 +00:00
|
|
|
else if (STREQ(format, "ext2") ||
|
|
|
|
STREQ(format, "ext3") ||
|
|
|
|
STREQ(format, "ext4"))
|
|
|
|
virCommandAddArg(cmd, "-F");
|
|
|
|
else if (STREQ(format, "vfat"))
|
|
|
|
virCommandAddArg(cmd, "-I");
|
2014-04-03 09:09:14 +00:00
|
|
|
|
|
|
|
virCommandAddArg(cmd, 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
|
|
|
|
2019-04-01 12:56:23 +00:00
|
|
|
if (virCommandRun(cmd, NULL) < 0)
|
2019-01-31 18:16:44 +00:00
|
|
|
return -1;
|
2013-01-23 22:04:46 +00:00
|
|
|
|
2019-01-31 18:16:44 +00:00
|
|
|
return 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
|
|
|
}
|
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)
|
|
|
|
{
|
2017-07-26 18:21:08 +00:00
|
|
|
virStoragePoolDefPtr def = virStoragePoolObjGetDef(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
|
|
|
const char *device = NULL, *format = NULL;
|
|
|
|
bool ok_to_mkfs = false;
|
|
|
|
int ret = -1;
|
|
|
|
|
2017-07-26 18:21:08 +00:00
|
|
|
if (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'"),
|
2017-07-26 18:21:08 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-07-26 18:21:08 +00:00
|
|
|
device = def->source.devices[0].path;
|
|
|
|
format = virStoragePoolFormatFileSystemTypeToString(def->source.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
|
|
|
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'"),
|
2017-07-26 18:21:08 +00:00
|
|
|
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 &&
|
2016-12-14 23:03:20 +00:00
|
|
|
virStorageBackendDeviceIsEmpty(device, format, true)) {
|
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
|
|
|
ok_to_mkfs = true;
|
|
|
|
}
|
|
|
|
|
2014-11-13 14:25:27 +00:00
|
|
|
if (ok_to_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
|
|
|
ret = virStorageBackendExecuteMKFS(device, format);
|
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
error:
|
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;
|
|
|
|
}
|
|
|
|
|
2008-02-20 15:45:59 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @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: Fix implementation of no-overwrite for file system backend
https://bugzilla.redhat.com/show_bug.cgi?id=1363586
Commit id '27758859' introduced the "NO_OVERWRITE" flag check for
file system backends; however, the implementation, documentation,
and algorithm was inconsistent. For the "flag" description for the
API the flag was described as "Do not overwrite existing pool";
however, within the storage backend code the flag is described
as "it probes to determine if filesystem already exists on the
target device, renurning an error if exists".
The code itself was implemented using the paradigm to set up the
superblock probe by creating a filter that would cause the code
to only search for the provided format type. If that type wasn't
found, then the algorithm would return success allowing the caller
to format the device. If the format type already existed on the
device, then the code would fail indicating that the a filesystem
of the same type existed on the device.
The result is that if someone had a file system of one type on the
device, it was possible to overwrite it if a different format type
was specified in updated XML effectively trashing whatever was on
the device already.
This patch alters what NO_OVERWRITE does for a file system backend
to be more realistic and consistent with what should be expected when
the caller requests to not overwrite the data on the disk.
Rather than filter results based on the expected format type, the
code will allow success/failure be determined solely on whether the
blkid_do_probe calls finds some known format on the device. This
adjustment also allows removal of the virStoragePoolProbeResult
enum that was under utilized.
If it does find a formatted file system different errors will be
generated indicating a file system of a specific type already exists
or a file system of some other type already exists.
In the original virsh support commit id 'ddcd5674', the description
for '--no-overwrite' within the 'pool-build' command help output
has an ambiguous "of this type" included in the short description.
Compared to the longer description within the "Build a given pool."
section of the virsh.pod file it's more apparent that the meaning
of this flag would cause failure if a probe of the target already
has a filesystem.
So this patch also modifies the short description to just be the
antecedent of the 'overwrite' flag, which matches the API description.
This patch also modifies the grammar in virsh.pod for no-overwrite
as well as reworking the paragraph formats to make it easier to read.
Signed-off-by: John Ferlan <jferlan@redhat.com>
2016-12-14 20:14:19 +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
|
|
|
|
* any filesystem already exists on the target device, returning an error
|
|
|
|
* if one exists. If no filesystem already exists, use mkfs to format the
|
|
|
|
* target device.
|
|
|
|
*
|
|
|
|
* If VIR_STORAGE_POOL_BUILD_OVERWRITE is set, mkfs is always executed and
|
|
|
|
* any existing data on the target device is overwritten unconditionally.
|
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
|
|
|
*
|
2014-01-10 10:51:04 +00:00
|
|
|
* The underlying source device is mounted for FS based pools.
|
2008-02-20 15:45:59 +00:00
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
static int
|
2018-01-26 13:31:58 +00:00
|
|
|
virStorageBackendFileSystemBuild(virStoragePoolObjPtr pool,
|
2011-07-06 22:51:23 +00:00
|
|
|
unsigned int flags)
|
2008-02-20 15:45:59 +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 |
|
2017-01-18 19:17:21 +00:00
|
|
|
VIR_STORAGE_POOL_BUILD_NO_OVERWRITE, -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
|
|
|
|
2017-01-18 19:17:21 +00:00
|
|
|
VIR_EXCLUSIVE_FLAGS_RET(VIR_STORAGE_POOL_BUILD_OVERWRITE,
|
|
|
|
VIR_STORAGE_POOL_BUILD_NO_OVERWRITE,
|
|
|
|
-1);
|
2008-02-20 15:45:59 +00:00
|
|
|
|
2017-01-18 19:17:21 +00:00
|
|
|
if (virStorageBackendBuildLocal(pool) < 0)
|
2008-02-20 15:45:59 +00:00
|
|
|
return -1;
|
2017-01-18 19:17:21 +00:00
|
|
|
|
|
|
|
if (flags != 0)
|
|
|
|
return virStorageBackendMakeFileSystem(pool, flags);
|
2008-02-20 15:45:59 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-07 22:14:57 +00:00
|
|
|
#if WITH_STORAGE_FS
|
|
|
|
|
2019-01-31 11:14:09 +00:00
|
|
|
# define STORAGE_POOL_FS_NAMESPACE_HREF "http://libvirt.org/schemas/storagepool/fs/1.0"
|
2019-01-07 22:14:57 +00:00
|
|
|
|
|
|
|
/* Backend XML Namespace handling for fs or netfs specific mount options to
|
|
|
|
* be added to the mount -o {options_list} command line that are not otherwise
|
|
|
|
* supplied by supported XML. The XML will use the format, such as:
|
|
|
|
*
|
|
|
|
* <fs:mount_opts>
|
|
|
|
* <fs:option name='sync'/>
|
|
|
|
* <fs:option name='lazytime'/>
|
|
|
|
* </fs:mount_opts>
|
|
|
|
*
|
|
|
|
* and the <pool type='fs'> or <pool type='netfs'> is required to have a
|
|
|
|
* "xmlns:fs='%s'" attribute using the STORAGE_POOL_FS_NAMESPACE_HREF
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
|
|
|
virStoragePoolDefFSNamespaceFree(void *nsdata)
|
|
|
|
{
|
|
|
|
virStoragePoolFSMountOptionsDefPtr cmdopts = nsdata;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!cmdopts)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < cmdopts->noptions; i++)
|
|
|
|
VIR_FREE(cmdopts->options[i]);
|
|
|
|
VIR_FREE(cmdopts->options);
|
|
|
|
|
|
|
|
VIR_FREE(cmdopts);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virStoragePoolDefFSNamespaceParse(xmlXPathContextPtr ctxt,
|
|
|
|
void **data)
|
|
|
|
{
|
|
|
|
virStoragePoolFSMountOptionsDefPtr cmdopts = NULL;
|
|
|
|
int nnodes;
|
|
|
|
size_t i;
|
|
|
|
int ret = -1;
|
2019-01-31 17:09:38 +00:00
|
|
|
VIR_AUTOFREE(xmlNodePtr *)nodes = NULL;
|
2019-01-07 22:14:57 +00:00
|
|
|
|
|
|
|
if (xmlXPathRegisterNs(ctxt, BAD_CAST "fs",
|
|
|
|
BAD_CAST STORAGE_POOL_FS_NAMESPACE_HREF) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to register xml namespace '%s'"),
|
|
|
|
STORAGE_POOL_FS_NAMESPACE_HREF);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
nnodes = virXPathNodeSet("./fs:mount_opts/fs:option", ctxt, &nodes);
|
|
|
|
if (nnodes < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (nnodes == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(cmdopts) < 0 ||
|
|
|
|
VIR_ALLOC_N(cmdopts->options, nnodes) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
for (i = 0; i < nnodes; i++) {
|
|
|
|
if (!(cmdopts->options[cmdopts->noptions] =
|
|
|
|
virXMLPropString(nodes[i], "name"))) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
|
_("no fs mount option name specified"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
cmdopts->noptions++;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_STEAL_PTR(*data, cmdopts);
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virStoragePoolDefFSNamespaceFree(cmdopts);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virStoragePoolDefFSNamespaceFormatXML(virBufferPtr buf,
|
|
|
|
void *nsdata)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
virStoragePoolFSMountOptionsDefPtr def = nsdata;
|
|
|
|
|
|
|
|
if (!def)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
virBufferAddLit(buf, "<fs:mount_opts>\n");
|
|
|
|
virBufferAdjustIndent(buf, 2);
|
|
|
|
|
|
|
|
for (i = 0; i < def->noptions; i++)
|
|
|
|
virBufferEscapeString(buf, "<fs:option name='%s'/>\n",
|
|
|
|
def->options[i]);
|
|
|
|
|
|
|
|
virBufferAdjustIndent(buf, -2);
|
|
|
|
virBufferAddLit(buf, "</fs:mount_opts>\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
virStoragePoolDefFSNamespaceHref(void)
|
|
|
|
{
|
|
|
|
return "xmlns:fs='" STORAGE_POOL_FS_NAMESPACE_HREF "'";
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* WITH_STORAGE_FS */
|
|
|
|
|
|
|
|
|
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,
|
2017-01-18 19:17:21 +00:00
|
|
|
.refreshPool = virStorageBackendRefreshLocal,
|
|
|
|
.deletePool = virStorageBackendDeleteLocal,
|
2017-01-21 14:05:41 +00:00
|
|
|
.buildVol = virStorageBackendVolBuildLocal,
|
|
|
|
.buildVolFrom = virStorageBackendVolBuildFromLocal,
|
|
|
|
.createVol = virStorageBackendVolCreateLocal,
|
|
|
|
.refreshVol = virStorageBackendVolRefreshLocal,
|
|
|
|
.deleteVol = virStorageBackendVolDeleteLocal,
|
|
|
|
.resizeVol = virStorageBackendVolResizeLocal,
|
2014-07-07 14:50:11 +00:00
|
|
|
.uploadVol = virStorageBackendVolUploadLocal,
|
|
|
|
.downloadVol = virStorageBackendVolDownloadLocal,
|
2014-07-07 14:50:11 +00:00
|
|
|
.wipeVol = virStorageBackendVolWipeLocal,
|
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,
|
2017-01-18 19:17:21 +00:00
|
|
|
.refreshPool = virStorageBackendRefreshLocal,
|
2008-02-20 15:45:59 +00:00
|
|
|
.stopPool = virStorageBackendFileSystemStop,
|
2017-01-18 19:17:21 +00:00
|
|
|
.deletePool = virStorageBackendDeleteLocal,
|
2017-01-21 14:05:41 +00:00
|
|
|
.buildVol = virStorageBackendVolBuildLocal,
|
|
|
|
.buildVolFrom = virStorageBackendVolBuildFromLocal,
|
|
|
|
.createVol = virStorageBackendVolCreateLocal,
|
|
|
|
.refreshVol = virStorageBackendVolRefreshLocal,
|
|
|
|
.deleteVol = virStorageBackendVolDeleteLocal,
|
|
|
|
.resizeVol = virStorageBackendVolResizeLocal,
|
2014-07-07 14:50:11 +00:00
|
|
|
.uploadVol = virStorageBackendVolUploadLocal,
|
|
|
|
.downloadVol = virStorageBackendVolDownloadLocal,
|
2014-07-07 14:50:11 +00:00
|
|
|
.wipeVol = virStorageBackendVolWipeLocal,
|
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,
|
2017-01-18 19:17:21 +00:00
|
|
|
.refreshPool = virStorageBackendRefreshLocal,
|
2008-02-20 15:45:59 +00:00
|
|
|
.stopPool = virStorageBackendFileSystemStop,
|
2017-01-18 19:17:21 +00:00
|
|
|
.deletePool = virStorageBackendDeleteLocal,
|
2017-01-21 14:05:41 +00:00
|
|
|
.buildVol = virStorageBackendVolBuildLocal,
|
|
|
|
.buildVolFrom = virStorageBackendVolBuildFromLocal,
|
|
|
|
.createVol = virStorageBackendVolCreateLocal,
|
|
|
|
.refreshVol = virStorageBackendVolRefreshLocal,
|
|
|
|
.deleteVol = virStorageBackendVolDeleteLocal,
|
|
|
|
.resizeVol = virStorageBackendVolResizeLocal,
|
2014-07-07 14:50:11 +00:00
|
|
|
.uploadVol = virStorageBackendVolUploadLocal,
|
|
|
|
.downloadVol = virStorageBackendVolDownloadLocal,
|
2014-07-07 14:50:11 +00:00
|
|
|
.wipeVol = virStorageBackendVolWipeLocal,
|
2008-02-20 15:45:59 +00:00
|
|
|
};
|
2019-01-07 22:14:57 +00:00
|
|
|
|
2019-08-20 21:17:37 +00:00
|
|
|
static virXMLNamespace virStoragePoolFSXMLNamespace = {
|
2019-01-07 22:14:57 +00:00
|
|
|
.parse = virStoragePoolDefFSNamespaceParse,
|
|
|
|
.free = virStoragePoolDefFSNamespaceFree,
|
|
|
|
.format = virStoragePoolDefFSNamespaceFormatXML,
|
2019-08-20 22:02:50 +00:00
|
|
|
.prefix = "fs",
|
2019-01-07 22:14:57 +00:00
|
|
|
.href = virStoragePoolDefFSNamespaceHref,
|
|
|
|
};
|
2017-01-13 15:59:30 +00:00
|
|
|
#endif /* WITH_STORAGE_FS */
|
2014-02-03 15:41:49 +00:00
|
|
|
|
|
|
|
|
2017-01-13 15:50:11 +00:00
|
|
|
int
|
|
|
|
virStorageBackendFsRegister(void)
|
|
|
|
{
|
|
|
|
if (virStorageBackendRegister(&virStorageBackendDirectory) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
#if WITH_STORAGE_FS
|
|
|
|
if (virStorageBackendRegister(&virStorageBackendFileSystem) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2019-01-07 22:14:57 +00:00
|
|
|
if (virStorageBackendNamespaceInit(VIR_STORAGE_POOL_FS,
|
|
|
|
&virStoragePoolFSXMLNamespace) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2017-01-13 15:50:11 +00:00
|
|
|
if (virStorageBackendRegister(&virStorageBackendNetFileSystem) < 0)
|
|
|
|
return -1;
|
2019-01-07 22:14:57 +00:00
|
|
|
|
|
|
|
if (virStorageBackendNamespaceInit(VIR_STORAGE_POOL_NETFS,
|
|
|
|
&virStoragePoolFSXMLNamespace) < 0)
|
|
|
|
return -1;
|
2017-01-13 15:50:11 +00:00
|
|
|
#endif /* WITH_STORAGE_FS */
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|