2008-02-20 15:34:52 +00:00
|
|
|
/*
|
|
|
|
* storage_driver.c: core driver for storage APIs
|
|
|
|
*
|
2015-05-28 15:00:01 +00:00
|
|
|
* Copyright (C) 2006-2015 Red Hat, Inc.
|
2008-02-20 15:34:52 +00:00
|
|
|
* Copyright (C) 2006-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:34:52 +00:00
|
|
|
*
|
|
|
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/types.h>
|
2010-02-23 03:13:18 +00:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
2008-04-18 08:33:23 +00:00
|
|
|
#if HAVE_PWD_H
|
2010-03-09 18:22:22 +00:00
|
|
|
# include <pwd.h>
|
2008-04-18 08:33:23 +00:00
|
|
|
#endif
|
2008-02-20 15:34:52 +00:00
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2008-11-04 23:22:06 +00:00
|
|
|
#include "datatypes.h"
|
2008-02-20 15:34:52 +00:00
|
|
|
#include "driver.h"
|
|
|
|
#include "storage_driver.h"
|
|
|
|
#include "storage_conf.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2008-02-20 15:34:52 +00:00
|
|
|
#include "storage_backend.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
#include "virfile.h"
|
2009-07-14 15:24:42 +00:00
|
|
|
#include "fdstream.h"
|
2010-11-16 14:54:17 +00:00
|
|
|
#include "configmake.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
2013-04-23 10:56:22 +00:00
|
|
|
#include "viraccessapicheck.h"
|
2014-04-24 10:14:01 +00:00
|
|
|
#include "dirname.h"
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2009-01-20 17:13:33 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_STORAGE
|
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("storage.storage_driver");
|
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
static virStorageDriverStatePtr driver;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2013-04-23 12:50:18 +00:00
|
|
|
static int storageStateCleanup(void);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-07-28 12:39:09 +00:00
|
|
|
typedef struct _virStorageVolStreamInfo virStorageVolStreamInfo;
|
|
|
|
typedef virStorageVolStreamInfo *virStorageVolStreamInfoPtr;
|
|
|
|
struct _virStorageVolStreamInfo {
|
|
|
|
char *pool_name;
|
|
|
|
};
|
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
static void storageDriverLock(void)
|
2008-12-04 21:40:42 +00:00
|
|
|
{
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexLock(&driver->lock);
|
2008-12-04 21:40:42 +00:00
|
|
|
}
|
2014-10-23 14:17:18 +00:00
|
|
|
static void storageDriverUnlock(void)
|
2008-12-04 21:40:42 +00:00
|
|
|
{
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexUnlock(&driver->lock);
|
2008-12-04 21:40:42 +00:00
|
|
|
}
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2015-04-27 14:43:22 +00:00
|
|
|
static void
|
|
|
|
storagePoolUpdateState(virStoragePoolObjPtr pool)
|
|
|
|
{
|
|
|
|
bool active;
|
|
|
|
virStorageBackendPtr backend;
|
2015-04-27 14:43:22 +00:00
|
|
|
int ret = -1;
|
|
|
|
char *stateFile;
|
|
|
|
|
|
|
|
if (!(stateFile = virFileBuildPath(driver->stateDir,
|
|
|
|
pool->def->name, ".xml")))
|
|
|
|
goto error;
|
2015-04-27 14:43:22 +00:00
|
|
|
|
|
|
|
if ((backend = virStorageBackendForType(pool->def->type)) == NULL) {
|
|
|
|
VIR_ERROR(_("Missing backend %d"), pool->def->type);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Backends which do not support 'checkPool' are considered
|
|
|
|
* inactive by default.
|
|
|
|
*/
|
|
|
|
active = false;
|
|
|
|
if (backend->checkPool &&
|
|
|
|
backend->checkPool(pool, &active) < 0) {
|
|
|
|
virErrorPtr err = virGetLastError();
|
|
|
|
VIR_ERROR(_("Failed to initialize storage pool '%s': %s"),
|
|
|
|
pool->def->name, err ? err->message :
|
|
|
|
_("no error message found"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We can pass NULL as connection, most backends do not use
|
|
|
|
* it anyway, but if they do and fail, we want to log error and
|
|
|
|
* continue with other pools.
|
|
|
|
*/
|
|
|
|
if (active) {
|
|
|
|
virStoragePoolObjClearVols(pool);
|
|
|
|
if (backend->refreshPool(NULL, pool) < 0) {
|
|
|
|
virErrorPtr err = virGetLastError();
|
|
|
|
if (backend->stopPool)
|
|
|
|
backend->stopPool(NULL, pool);
|
|
|
|
VIR_ERROR(_("Failed to restart storage pool '%s': %s"),
|
|
|
|
pool->def->name, err ? err->message :
|
|
|
|
_("no error message found"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pool->active = active;
|
2015-04-27 14:43:22 +00:00
|
|
|
ret = 0;
|
2015-04-27 14:43:22 +00:00
|
|
|
error:
|
2015-04-27 14:43:22 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
if (stateFile)
|
|
|
|
unlink(stateFile);
|
|
|
|
}
|
|
|
|
VIR_FREE(stateFile);
|
|
|
|
|
2015-04-27 14:43:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-03-16 15:30:03 +00:00
|
|
|
static void
|
|
|
|
storagePoolUpdateAllState(void)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < driver->pools.count; i++) {
|
|
|
|
virStoragePoolObjPtr pool = driver->pools.objs[i];
|
|
|
|
|
|
|
|
virStoragePoolObjLock(pool);
|
|
|
|
if (!virStoragePoolObjIsActive(pool)) {
|
|
|
|
virStoragePoolObjUnlock(pool);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-04-27 14:43:22 +00:00
|
|
|
storagePoolUpdateState(pool);
|
2015-03-16 15:30:03 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
static void
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverAutostart(void)
|
2014-03-18 08:15:36 +00:00
|
|
|
{
|
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;
|
2015-03-09 14:36:44 +00:00
|
|
|
char *stateFile = NULL;
|
2013-07-15 20:26:10 +00:00
|
|
|
virConnectPtr conn = NULL;
|
|
|
|
|
|
|
|
/* XXX Remove hardcoding of QEMU URI */
|
2014-10-23 14:17:18 +00:00
|
|
|
if (driver->privileged)
|
2013-07-15 20:26:10 +00:00
|
|
|
conn = virConnectOpen("qemu:///system");
|
|
|
|
else
|
|
|
|
conn = virConnectOpen("qemu:///session");
|
|
|
|
/* Ignoring NULL conn - let backends decide */
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2013-05-21 07:21:21 +00:00
|
|
|
for (i = 0; i < driver->pools.count; i++) {
|
2008-10-10 15:13:28 +00:00
|
|
|
virStoragePoolObjPtr pool = driver->pools.objs[i];
|
2010-11-11 20:09:20 +00:00
|
|
|
virStorageBackendPtr backend;
|
|
|
|
bool started = false;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2008-12-04 21:40:42 +00:00
|
|
|
virStoragePoolObjLock(pool);
|
2010-11-11 20:09:20 +00:00
|
|
|
if ((backend = virStorageBackendForType(pool->def->type)) == NULL) {
|
|
|
|
virStoragePoolObjUnlock(pool);
|
|
|
|
continue;
|
|
|
|
}
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2015-03-16 15:30:03 +00:00
|
|
|
if (pool->autostart &&
|
2010-11-11 20:09:20 +00:00
|
|
|
!virStoragePoolObjIsActive(pool)) {
|
2008-02-20 15:34:52 +00:00
|
|
|
if (backend->startPool &&
|
2013-07-15 20:26:10 +00:00
|
|
|
backend->startPool(conn, pool) < 0) {
|
2008-02-20 15:34:52 +00:00
|
|
|
virErrorPtr err = virGetLastError();
|
2010-05-20 06:15:46 +00:00
|
|
|
VIR_ERROR(_("Failed to autostart storage pool '%s': %s"),
|
2010-01-31 17:12:05 +00:00
|
|
|
pool->def->name, err ? err->message :
|
2010-11-11 20:09:20 +00:00
|
|
|
_("no error message found"));
|
2008-12-04 21:40:42 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2008-02-20 15:34:52 +00:00
|
|
|
continue;
|
|
|
|
}
|
2010-11-11 20:09:20 +00:00
|
|
|
started = true;
|
|
|
|
}
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2010-11-11 20:09:20 +00:00
|
|
|
if (started) {
|
2015-01-30 18:21:49 +00:00
|
|
|
virStoragePoolObjClearVols(pool);
|
2015-03-09 14:36:44 +00:00
|
|
|
stateFile = virFileBuildPath(driver->stateDir,
|
|
|
|
pool->def->name, ".xml");
|
|
|
|
if (!stateFile ||
|
|
|
|
virStoragePoolSaveState(stateFile, pool->def) < 0 ||
|
|
|
|
backend->refreshPool(conn, pool) < 0) {
|
2008-02-20 15:34:52 +00:00
|
|
|
virErrorPtr err = virGetLastError();
|
2015-04-27 14:43:22 +00:00
|
|
|
if (stateFile)
|
|
|
|
unlink(stateFile);
|
2008-02-20 15:34:52 +00:00
|
|
|
if (backend->stopPool)
|
2013-07-15 20:26:10 +00:00
|
|
|
backend->stopPool(conn, pool);
|
2010-05-20 06:15:46 +00:00
|
|
|
VIR_ERROR(_("Failed to autostart storage pool '%s': %s"),
|
2010-01-31 17:12:05 +00:00
|
|
|
pool->def->name, err ? err->message :
|
2010-11-11 20:09:20 +00:00
|
|
|
_("no error message found"));
|
2015-03-09 14:36:44 +00:00
|
|
|
VIR_FREE(stateFile);
|
2008-12-04 21:40:42 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2008-02-20 15:34:52 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
pool->active = 1;
|
|
|
|
}
|
2008-12-04 21:40:42 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2013-07-15 20:26:10 +00:00
|
|
|
|
2014-01-03 15:08:52 +00:00
|
|
|
virObjectUnref(conn);
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageStartup:
|
|
|
|
*
|
2015-03-09 14:36:44 +00:00
|
|
|
* Initialization function for the Storage Driver
|
2008-02-20 15:34:52 +00:00
|
|
|
*/
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
storageStateInitialize(bool privileged,
|
|
|
|
virStateInhibitCallback callback ATTRIBUTE_UNUSED,
|
|
|
|
void *opaque ATTRIBUTE_UNUSED)
|
2011-01-15 16:38:57 +00:00
|
|
|
{
|
2015-03-09 14:36:44 +00:00
|
|
|
int ret = -1;
|
|
|
|
char *configdir = NULL;
|
|
|
|
char *rundir = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
if (VIR_ALLOC(driver) < 0)
|
2015-03-09 14:36:44 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
if (virMutexInit(&driver->lock) < 0) {
|
|
|
|
VIR_FREE(driver);
|
2015-03-09 14:36:44 +00:00
|
|
|
return ret;
|
2009-01-15 19:56:05 +00:00
|
|
|
}
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2008-12-04 21:40:42 +00:00
|
|
|
|
2009-06-12 13:20:13 +00:00
|
|
|
if (privileged) {
|
2015-03-09 14:36:44 +00:00
|
|
|
if (VIR_STRDUP(driver->configDir,
|
|
|
|
SYSCONFDIR "/libvirt/storage") < 0 ||
|
|
|
|
VIR_STRDUP(driver->autostartDir,
|
|
|
|
SYSCONFDIR "/libvirt/storage/autostart") < 0 ||
|
|
|
|
VIR_STRDUP(driver->stateDir,
|
|
|
|
LOCALSTATEDIR "/run/libvirt/storage") < 0)
|
2013-05-03 12:49:08 +00:00
|
|
|
goto error;
|
2008-02-20 15:34:52 +00:00
|
|
|
} else {
|
2015-03-09 14:36:44 +00:00
|
|
|
configdir = virGetUserConfigDirectory();
|
|
|
|
rundir = virGetUserRuntimeDirectory();
|
|
|
|
if (!(configdir && rundir))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if ((virAsprintf(&driver->configDir,
|
|
|
|
"%s/storage", configdir) < 0) ||
|
|
|
|
(virAsprintf(&driver->autostartDir,
|
2015-04-27 14:43:22 +00:00
|
|
|
"%s/storage/autostart", configdir) < 0) ||
|
2015-03-09 14:36:44 +00:00
|
|
|
(virAsprintf(&driver->stateDir,
|
|
|
|
"%s/storage/run", rundir) < 0))
|
2009-01-22 19:41:48 +00:00
|
|
|
goto error;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2014-10-23 14:17:18 +00:00
|
|
|
driver->privileged = privileged;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2015-03-10 12:59:51 +00:00
|
|
|
if (virFileMakePath(driver->stateDir) < 0) {
|
|
|
|
virReportError(errno,
|
|
|
|
_("cannot create directory %s"),
|
|
|
|
driver->stateDir);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virStoragePoolLoadAllState(&driver->pools,
|
|
|
|
driver->stateDir) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
if (virStoragePoolLoadAllConfigs(&driver->pools,
|
|
|
|
driver->configDir,
|
|
|
|
driver->autostartDir) < 0)
|
2008-12-04 21:40:42 +00:00
|
|
|
goto error;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2015-03-16 15:30:03 +00:00
|
|
|
storagePoolUpdateAllState();
|
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2015-03-09 14:36:44 +00:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(configdir);
|
|
|
|
VIR_FREE(rundir);
|
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
error:
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2013-04-23 12:50:18 +00:00
|
|
|
storageStateCleanup();
|
2015-03-09 14:36:44 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2013-07-25 12:03:38 +00:00
|
|
|
/**
|
|
|
|
* storageStateAutoStart:
|
|
|
|
*
|
|
|
|
* Function to auto start the storage driver
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
storageStateAutoStart(void)
|
|
|
|
{
|
2014-10-23 14:17:18 +00:00
|
|
|
if (!driver)
|
2013-07-25 12:03:38 +00:00
|
|
|
return;
|
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
|
|
|
storageDriverAutostart();
|
|
|
|
storageDriverUnlock();
|
2013-07-25 12:03:38 +00:00
|
|
|
}
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
/**
|
2013-04-23 12:50:18 +00:00
|
|
|
* storageStateReload:
|
2008-02-20 15:34:52 +00:00
|
|
|
*
|
|
|
|
* Function to restart the storage driver, it will recheck the configuration
|
|
|
|
* files and update its state
|
|
|
|
*/
|
|
|
|
static int
|
2014-03-18 08:15:36 +00:00
|
|
|
storageStateReload(void)
|
|
|
|
{
|
2014-10-23 14:17:18 +00:00
|
|
|
if (!driver)
|
2008-10-10 15:13:28 +00:00
|
|
|
return -1;
|
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2015-03-10 12:59:51 +00:00
|
|
|
virStoragePoolLoadAllState(&driver->pools,
|
|
|
|
driver->stateDir);
|
2014-10-23 14:17:18 +00:00
|
|
|
virStoragePoolLoadAllConfigs(&driver->pools,
|
|
|
|
driver->configDir,
|
|
|
|
driver->autostartDir);
|
|
|
|
storageDriverAutostart();
|
|
|
|
storageDriverUnlock();
|
2008-02-20 15:34:52 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2013-04-23 12:50:18 +00:00
|
|
|
* storageStateCleanup
|
2008-02-20 15:34:52 +00:00
|
|
|
*
|
|
|
|
* Shutdown the storage driver, it will stop all active storage pools
|
|
|
|
*/
|
|
|
|
static int
|
2014-03-18 08:15:36 +00:00
|
|
|
storageStateCleanup(void)
|
|
|
|
{
|
2014-10-23 14:17:18 +00:00
|
|
|
if (!driver)
|
2008-02-20 15:34:52 +00:00
|
|
|
return -1;
|
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2008-02-20 15:34:52 +00:00
|
|
|
|
|
|
|
/* free inactive pools */
|
2014-10-23 14:17:18 +00:00
|
|
|
virStoragePoolObjListFree(&driver->pools);
|
2008-10-10 15:13:28 +00:00
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
VIR_FREE(driver->configDir);
|
|
|
|
VIR_FREE(driver->autostartDir);
|
2015-03-09 14:36:44 +00:00
|
|
|
VIR_FREE(driver->stateDir);
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
|
|
|
virMutexDestroy(&driver->lock);
|
|
|
|
VIR_FREE(driver);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static virStoragePoolPtr
|
|
|
|
storagePoolLookupByUUID(virConnectPtr conn,
|
2014-03-18 08:15:36 +00:00
|
|
|
const unsigned char *uuid)
|
|
|
|
{
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
|
|
|
virStoragePoolPtr ret = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2008-12-04 21:39:45 +00:00
|
|
|
pool = virStoragePoolObjFindByUUID(&driver->pools, uuid);
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2008-12-04 21:40:42 +00:00
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
if (!pool) {
|
2014-06-05 08:40:59 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(uuid, uuidstr);
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_NO_STORAGE_POOL,
|
2014-06-05 08:40:59 +00:00
|
|
|
_("no storage pool with matching uuid '%s'"), uuidstr);
|
|
|
|
return NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStoragePoolLookupByUUIDEnsureACL(conn, pool->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-11-10 07:18:07 +00:00
|
|
|
ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
|
|
|
|
NULL, NULL);
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-12 07:55:17 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2008-02-20 15:34:52 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virStoragePoolPtr
|
|
|
|
storagePoolLookupByName(virConnectPtr conn,
|
2014-03-18 08:15:36 +00:00
|
|
|
const char *name)
|
|
|
|
{
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
|
|
|
virStoragePoolPtr ret = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2008-12-04 21:39:45 +00:00
|
|
|
pool = virStoragePoolObjFindByName(&driver->pools, name);
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2008-12-04 21:40:42 +00:00
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
if (!pool) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_NO_STORAGE_POOL,
|
2012-10-08 22:37:22 +00:00
|
|
|
_("no storage pool with matching name '%s'"), name);
|
2014-06-12 07:55:17 +00:00
|
|
|
return NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStoragePoolLookupByNameEnsureACL(conn, pool->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-11-10 07:18:07 +00:00
|
|
|
ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
|
|
|
|
NULL, NULL);
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-12 07:55:17 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2008-02-20 15:34:52 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virStoragePoolPtr
|
2014-03-18 08:15:36 +00:00
|
|
|
storagePoolLookupByVolume(virStorageVolPtr vol)
|
|
|
|
{
|
2013-04-23 10:56:22 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
|
|
|
virStoragePoolPtr ret = NULL;
|
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2013-04-23 10:56:22 +00:00
|
|
|
pool = virStoragePoolObjFindByName(&driver->pools, vol->pool);
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2013-04-23 10:56:22 +00:00
|
|
|
|
|
|
|
if (!pool) {
|
|
|
|
virReportError(VIR_ERR_NO_STORAGE_POOL,
|
2014-11-19 08:48:09 +00:00
|
|
|
_("no storage pool with matching name '%s'"),
|
|
|
|
vol->pool);
|
2014-06-12 07:55:17 +00:00
|
|
|
return NULL;
|
2013-04-23 10:56:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (virStoragePoolLookupByVolumeEnsureACL(vol->conn, pool->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = virGetStoragePool(vol->conn, pool->def->name, pool->def->uuid,
|
|
|
|
NULL, NULL);
|
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-12 07:55:17 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2013-04-23 10:56:22 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-03-18 08:15:36 +00:00
|
|
|
storageConnectNumOfStoragePools(virConnectPtr conn)
|
|
|
|
{
|
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;
|
|
|
|
int nactive = 0;
|
2008-10-10 15:13:28 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virConnectNumOfStoragePoolsEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2013-05-21 07:21:21 +00:00
|
|
|
for (i = 0; i < driver->pools.count; i++) {
|
2013-06-26 17:47:48 +00:00
|
|
|
virStoragePoolObjPtr obj = driver->pools.objs[i];
|
|
|
|
virStoragePoolObjLock(obj);
|
|
|
|
if (virConnectNumOfStoragePoolsCheckACL(conn, obj->def) &&
|
2014-02-14 15:03:22 +00:00
|
|
|
virStoragePoolObjIsActive(obj))
|
2008-10-10 15:13:28 +00:00
|
|
|
nactive++;
|
2013-06-26 17:47:48 +00:00
|
|
|
virStoragePoolObjUnlock(obj);
|
2008-12-04 21:40:42 +00:00
|
|
|
}
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2008-10-10 15:13:28 +00:00
|
|
|
|
|
|
|
return nactive;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
storageConnectListStoragePools(virConnectPtr conn,
|
|
|
|
char **const names,
|
2014-03-18 08:15:36 +00:00
|
|
|
int nnames)
|
|
|
|
{
|
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
|
|
|
int got = 0;
|
|
|
|
size_t i;
|
2008-10-10 15:13:28 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virConnectListStoragePoolsEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2013-05-21 07:21:21 +00:00
|
|
|
for (i = 0; i < driver->pools.count && got < nnames; i++) {
|
2013-06-26 17:47:48 +00:00
|
|
|
virStoragePoolObjPtr obj = driver->pools.objs[i];
|
|
|
|
virStoragePoolObjLock(obj);
|
|
|
|
if (virConnectListStoragePoolsCheckACL(conn, obj->def) &&
|
2014-02-14 15:03:22 +00:00
|
|
|
virStoragePoolObjIsActive(obj)) {
|
2013-06-26 17:47:48 +00:00
|
|
|
if (VIR_STRDUP(names[got], obj->def->name) < 0) {
|
|
|
|
virStoragePoolObjUnlock(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
got++;
|
|
|
|
}
|
2013-06-26 17:47:48 +00:00
|
|
|
virStoragePoolObjUnlock(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2008-02-20 15:34:52 +00:00
|
|
|
return got;
|
|
|
|
|
|
|
|
cleanup:
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2013-05-21 07:21:21 +00:00
|
|
|
for (i = 0; i < got; i++)
|
2008-12-04 21:40:42 +00:00
|
|
|
VIR_FREE(names[i]);
|
2008-12-02 15:59:14 +00:00
|
|
|
memset(names, 0, nnames * sizeof(*names));
|
2008-02-20 15:34:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-03-18 08:15:36 +00:00
|
|
|
storageConnectNumOfDefinedStoragePools(virConnectPtr conn)
|
|
|
|
{
|
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;
|
|
|
|
int nactive = 0;
|
2008-10-10 15:13:28 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virConnectNumOfDefinedStoragePoolsEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2013-05-21 07:21:21 +00:00
|
|
|
for (i = 0; i < driver->pools.count; i++) {
|
2013-06-26 17:47:48 +00:00
|
|
|
virStoragePoolObjPtr obj = driver->pools.objs[i];
|
|
|
|
virStoragePoolObjLock(obj);
|
|
|
|
if (virConnectNumOfDefinedStoragePoolsCheckACL(conn, obj->def) &&
|
2014-02-14 15:03:22 +00:00
|
|
|
!virStoragePoolObjIsActive(obj))
|
2008-10-10 15:13:28 +00:00
|
|
|
nactive++;
|
2013-06-26 17:47:48 +00:00
|
|
|
virStoragePoolObjUnlock(obj);
|
2008-12-04 21:40:42 +00:00
|
|
|
}
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2008-10-10 15:13:28 +00:00
|
|
|
|
|
|
|
return nactive;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
storageConnectListDefinedStoragePools(virConnectPtr conn,
|
|
|
|
char **const names,
|
2014-03-18 08:15:36 +00:00
|
|
|
int nnames)
|
|
|
|
{
|
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
|
|
|
int got = 0;
|
|
|
|
size_t i;
|
2008-10-10 15:13:28 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virConnectListDefinedStoragePoolsEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2013-05-21 07:21:21 +00:00
|
|
|
for (i = 0; i < driver->pools.count && got < nnames; i++) {
|
2013-06-26 17:47:48 +00:00
|
|
|
virStoragePoolObjPtr obj = driver->pools.objs[i];
|
|
|
|
virStoragePoolObjLock(obj);
|
|
|
|
if (virConnectListDefinedStoragePoolsCheckACL(conn, obj->def) &&
|
2014-02-14 15:03:22 +00:00
|
|
|
!virStoragePoolObjIsActive(obj)) {
|
2013-06-26 17:47:48 +00:00
|
|
|
if (VIR_STRDUP(names[got], obj->def->name) < 0) {
|
|
|
|
virStoragePoolObjUnlock(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
got++;
|
|
|
|
}
|
2013-06-26 17:47:48 +00:00
|
|
|
virStoragePoolObjUnlock(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2008-02-20 15:34:52 +00:00
|
|
|
return got;
|
|
|
|
|
|
|
|
cleanup:
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2014-11-13 14:25:27 +00:00
|
|
|
for (i = 0; i < got; i++)
|
2009-12-09 23:00:50 +00:00
|
|
|
VIR_FREE(names[i]);
|
2008-12-02 15:59:14 +00:00
|
|
|
memset(names, 0, nnames * sizeof(*names));
|
2008-02-20 15:34:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-12-04 21:40:42 +00:00
|
|
|
/* This method is required to be re-entrant / thread safe, so
|
|
|
|
uses no driver lock */
|
2008-08-27 20:05:58 +00:00
|
|
|
static char *
|
2013-04-23 12:50:18 +00:00
|
|
|
storageConnectFindStoragePoolSources(virConnectPtr conn,
|
|
|
|
const char *type,
|
|
|
|
const char *srcSpec,
|
|
|
|
unsigned int flags)
|
2008-08-27 20:05:58 +00:00
|
|
|
{
|
|
|
|
int backend_type;
|
|
|
|
virStorageBackendPtr backend;
|
2008-12-04 21:39:45 +00:00
|
|
|
char *ret = NULL;
|
2008-08-27 20:05:58 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virConnectFindStoragePoolSourcesEnsureACL(conn) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2008-11-17 11:19:33 +00:00
|
|
|
backend_type = virStoragePoolTypeFromString(type);
|
2009-10-08 14:24:37 +00:00
|
|
|
if (backend_type < 0) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unknown storage pool type %s"), type);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2009-10-08 14:24:37 +00:00
|
|
|
}
|
2008-08-27 20:05:58 +00:00
|
|
|
|
|
|
|
backend = virStorageBackendForType(backend_type);
|
|
|
|
if (backend == NULL)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-08-27 20:05:58 +00:00
|
|
|
|
2009-10-08 14:24:37 +00:00
|
|
|
if (!backend->findPoolSources) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_NO_SUPPORT,
|
|
|
|
_("pool type '%s' does not support source "
|
|
|
|
"discovery"), type);
|
2009-10-08 14:24:37 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = backend->findPoolSources(conn, srcSpec, flags);
|
2008-08-27 20:05:58 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-08-27 20:05:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-05 08:40:59 +00:00
|
|
|
static virStoragePoolObjPtr
|
|
|
|
virStoragePoolObjFromStoragePool(virStoragePoolPtr pool)
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
{
|
2014-06-05 08:40:59 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virStoragePoolObjPtr ret;
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2014-06-05 08:40:59 +00:00
|
|
|
if (!(ret = virStoragePoolObjFindByUUID(&driver->pools, pool->uuid))) {
|
|
|
|
virUUIDFormat(pool->uuid, uuidstr);
|
|
|
|
virReportError(VIR_ERR_NO_STORAGE_POOL,
|
|
|
|
_("no storage pool with matching uuid '%s' (%s)"),
|
|
|
|
uuidstr, pool->name);
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
}
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2014-06-05 08:40:59 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int storagePoolIsActive(virStoragePoolPtr pool)
|
|
|
|
{
|
|
|
|
virStoragePoolObjPtr obj;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!(obj = virStoragePoolObjFromStoragePool(pool)))
|
|
|
|
return -1;
|
2013-04-23 10:56:22 +00:00
|
|
|
|
|
|
|
if (virStoragePoolIsActiveEnsureACL(pool->conn, obj->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
ret = virStoragePoolObjIsActive(obj);
|
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-12 07:55:17 +00:00
|
|
|
virStoragePoolObjUnlock(obj);
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-12-09 09:38:11 +00:00
|
|
|
static int storagePoolIsPersistent(virStoragePoolPtr pool)
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
{
|
|
|
|
virStoragePoolObjPtr obj;
|
|
|
|
int ret = -1;
|
|
|
|
|
2014-06-05 08:40:59 +00:00
|
|
|
if (!(obj = virStoragePoolObjFromStoragePool(pool)))
|
|
|
|
return -1;
|
2013-04-23 10:56:22 +00:00
|
|
|
|
|
|
|
if (virStoragePoolIsPersistentEnsureACL(pool->conn, obj->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
ret = obj->configFile ? 1 : 0;
|
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-12 07:55:17 +00:00
|
|
|
virStoragePoolObjUnlock(obj);
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
static virStoragePoolPtr
|
2013-04-23 12:50:18 +00:00
|
|
|
storagePoolCreateXML(virConnectPtr conn,
|
|
|
|
const char *xml,
|
|
|
|
unsigned int flags)
|
2011-07-06 22:51:23 +00:00
|
|
|
{
|
2008-02-20 15:34:52 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2008-12-04 21:40:42 +00:00
|
|
|
virStoragePoolObjPtr pool = NULL;
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolPtr ret = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageBackendPtr backend;
|
2015-03-09 14:36:44 +00:00
|
|
|
char *stateFile = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2011-07-06 22:51:23 +00:00
|
|
|
virCheckFlags(0, NULL);
|
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2010-02-10 11:42:56 +00:00
|
|
|
if (!(def = virStoragePoolDefParseString(xml)))
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStoragePoolCreateXMLEnsureACL(conn, def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2010-05-27 11:41:30 +00:00
|
|
|
if (virStoragePoolObjIsDuplicate(&driver->pools, def, 1) < 0)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-11-14 14:50:59 +00:00
|
|
|
if (virStoragePoolSourceFindDuplicate(conn, &driver->pools, def) < 0)
|
2011-09-05 07:52:03 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2008-12-04 21:39:45 +00:00
|
|
|
if ((backend = virStorageBackendForType(def->type)) == NULL)
|
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2010-02-10 11:42:56 +00:00
|
|
|
if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
def = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2008-03-17 15:10:48 +00:00
|
|
|
if (backend->startPool &&
|
2009-09-02 13:02:06 +00:00
|
|
|
backend->startPool(conn, pool) < 0) {
|
|
|
|
virStoragePoolObjRemove(&driver->pools, pool);
|
|
|
|
pool = NULL;
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2009-09-02 13:02:06 +00:00
|
|
|
}
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2015-03-09 14:36:44 +00:00
|
|
|
stateFile = virFileBuildPath(driver->stateDir,
|
|
|
|
pool->def->name, ".xml");
|
|
|
|
|
|
|
|
if (!stateFile || virStoragePoolSaveState(stateFile, pool->def) < 0 ||
|
|
|
|
backend->refreshPool(conn, pool) < 0) {
|
2015-04-27 14:43:22 +00:00
|
|
|
if (stateFile)
|
|
|
|
unlink(stateFile);
|
2008-03-17 15:10:48 +00:00
|
|
|
if (backend->stopPool)
|
|
|
|
backend->stopPool(conn, pool);
|
2009-09-02 13:02:06 +00:00
|
|
|
virStoragePoolObjRemove(&driver->pools, pool);
|
|
|
|
pool = NULL;
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
maint: omit translation for all VIR_INFO
We were 31/73 on whether to translate; since less than 50% translated
and since VIR_INFO is less than VIR_WARN which also doesn't translate,
this makes sense.
* cfg.mk (sc_prohibit_gettext_markup): Add VIR_INFO, since it
falls between WARN and DEBUG.
* daemon/libvirtd.c (qemudDispatchSignalEvent, remoteCheckAccess)
(qemudDispatchServer): Adjust offenders.
* daemon/remote.c (remoteDispatchAuthPolkit): Likewise.
* src/network/bridge_driver.c (networkReloadIptablesRules)
(networkStartNetworkDaemon, networkShutdownNetworkDaemon)
(networkCreate, networkDefine, networkUndefine): Likewise.
* src/qemu/qemu_driver.c (qemudDomainDefine)
(qemudDomainUndefine): Likewise.
* src/storage/storage_driver.c (storagePoolCreate)
(storagePoolDefine, storagePoolUndefine, storagePoolStart)
(storagePoolDestroy, storagePoolDelete, storageVolumeCreateXML)
(storageVolumeCreateXMLFrom, storageVolumeDelete): Likewise.
* src/util/bridge.c (brProbeVnetHdr): Likewise.
* po/POTFILES.in: Drop src/util/bridge.c.
2011-05-11 15:08:44 +00:00
|
|
|
VIR_INFO("Creating storage pool '%s'", pool->def->name);
|
2008-02-20 15:34:52 +00:00
|
|
|
pool->active = 1;
|
|
|
|
|
2012-11-10 07:18:07 +00:00
|
|
|
ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
|
|
|
|
NULL, NULL);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2015-03-09 14:36:44 +00:00
|
|
|
VIR_FREE(stateFile);
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolDefFree(def);
|
2008-12-04 21:40:42 +00:00
|
|
|
if (pool)
|
2009-09-02 13:02:06 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2008-02-20 15:34:52 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virStoragePoolPtr
|
2013-04-23 12:50:18 +00:00
|
|
|
storagePoolDefineXML(virConnectPtr conn,
|
|
|
|
const char *xml,
|
|
|
|
unsigned int flags)
|
2011-07-06 22:51:23 +00:00
|
|
|
{
|
2008-02-20 15:34:52 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2008-12-04 21:40:42 +00:00
|
|
|
virStoragePoolObjPtr pool = NULL;
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolPtr ret = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2011-07-06 22:51:23 +00:00
|
|
|
virCheckFlags(0, NULL);
|
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2010-02-10 11:42:56 +00:00
|
|
|
if (!(def = virStoragePoolDefParseString(xml)))
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStoragePoolDefineXMLEnsureACL(conn, def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2010-05-27 11:41:30 +00:00
|
|
|
if (virStoragePoolObjIsDuplicate(&driver->pools, def, 0) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-11-14 14:50:59 +00:00
|
|
|
if (virStoragePoolSourceFindDuplicate(conn, &driver->pools, def) < 0)
|
2011-09-05 07:52:03 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2009-09-04 15:18:29 +00:00
|
|
|
if (virStorageBackendForType(def->type) == NULL)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2010-02-10 11:42:56 +00:00
|
|
|
if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2010-02-10 11:42:56 +00:00
|
|
|
if (virStoragePoolObjSaveDef(driver, pool, def) < 0) {
|
2008-10-10 15:13:28 +00:00
|
|
|
virStoragePoolObjRemove(&driver->pools, pool);
|
2008-12-22 16:30:57 +00:00
|
|
|
def = NULL;
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2008-12-22 16:30:57 +00:00
|
|
|
def = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
maint: omit translation for all VIR_INFO
We were 31/73 on whether to translate; since less than 50% translated
and since VIR_INFO is less than VIR_WARN which also doesn't translate,
this makes sense.
* cfg.mk (sc_prohibit_gettext_markup): Add VIR_INFO, since it
falls between WARN and DEBUG.
* daemon/libvirtd.c (qemudDispatchSignalEvent, remoteCheckAccess)
(qemudDispatchServer): Adjust offenders.
* daemon/remote.c (remoteDispatchAuthPolkit): Likewise.
* src/network/bridge_driver.c (networkReloadIptablesRules)
(networkStartNetworkDaemon, networkShutdownNetworkDaemon)
(networkCreate, networkDefine, networkUndefine): Likewise.
* src/qemu/qemu_driver.c (qemudDomainDefine)
(qemudDomainUndefine): Likewise.
* src/storage/storage_driver.c (storagePoolCreate)
(storagePoolDefine, storagePoolUndefine, storagePoolStart)
(storagePoolDestroy, storagePoolDelete, storageVolumeCreateXML)
(storageVolumeCreateXMLFrom, storageVolumeDelete): Likewise.
* src/util/bridge.c (brProbeVnetHdr): Likewise.
* po/POTFILES.in: Drop src/util/bridge.c.
2011-05-11 15:08:44 +00:00
|
|
|
VIR_INFO("Defining storage pool '%s'", pool->def->name);
|
2012-11-10 07:18:07 +00:00
|
|
|
ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
|
|
|
|
NULL, NULL);
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolDefFree(def);
|
2008-12-04 21:40:42 +00:00
|
|
|
if (pool)
|
|
|
|
virStoragePoolObjUnlock(pool);
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2008-02-20 15:34:52 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-03-18 08:15:36 +00:00
|
|
|
storagePoolUndefine(virStoragePoolPtr obj)
|
|
|
|
{
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
|
|
|
int ret = -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2014-06-05 08:40:59 +00:00
|
|
|
if (!(pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid))) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(obj->uuid, uuidstr);
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_NO_STORAGE_POOL,
|
2014-06-05 08:40:59 +00:00
|
|
|
_("no storage pool with matching uuid '%s' (%s)"),
|
|
|
|
uuidstr, obj->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStoragePoolUndefineEnsureACL(obj->conn, pool->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
if (virStoragePoolObjIsActive(pool)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2012-10-08 22:37:22 +00:00
|
|
|
_("storage pool '%s' is still active"),
|
|
|
|
pool->def->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2009-04-17 19:12:37 +00:00
|
|
|
if (pool->asyncjobs > 0) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("pool '%s' has asynchronous jobs running."),
|
|
|
|
pool->def->name);
|
2009-04-17 19:12:37 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2010-02-10 11:42:56 +00:00
|
|
|
if (virStoragePoolObjDeleteDef(pool) < 0)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-11-19 08:48:09 +00:00
|
|
|
if (unlink(pool->autostartLink) < 0 &&
|
|
|
|
errno != ENOENT &&
|
|
|
|
errno != ENOTDIR) {
|
2009-02-05 16:28:30 +00:00
|
|
|
char ebuf[1024];
|
2010-05-20 06:15:46 +00:00
|
|
|
VIR_ERROR(_("Failed to delete autostart link '%s': %s"),
|
2012-03-29 09:52:04 +00:00
|
|
|
pool->autostartLink, virStrerror(errno, ebuf, sizeof(ebuf)));
|
2009-02-05 16:28:30 +00:00
|
|
|
}
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2008-10-10 15:13:28 +00:00
|
|
|
VIR_FREE(pool->configFile);
|
|
|
|
VIR_FREE(pool->autostartLink);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
maint: omit translation for all VIR_INFO
We were 31/73 on whether to translate; since less than 50% translated
and since VIR_INFO is less than VIR_WARN which also doesn't translate,
this makes sense.
* cfg.mk (sc_prohibit_gettext_markup): Add VIR_INFO, since it
falls between WARN and DEBUG.
* daemon/libvirtd.c (qemudDispatchSignalEvent, remoteCheckAccess)
(qemudDispatchServer): Adjust offenders.
* daemon/remote.c (remoteDispatchAuthPolkit): Likewise.
* src/network/bridge_driver.c (networkReloadIptablesRules)
(networkStartNetworkDaemon, networkShutdownNetworkDaemon)
(networkCreate, networkDefine, networkUndefine): Likewise.
* src/qemu/qemu_driver.c (qemudDomainDefine)
(qemudDomainUndefine): Likewise.
* src/storage/storage_driver.c (storagePoolCreate)
(storagePoolDefine, storagePoolUndefine, storagePoolStart)
(storagePoolDestroy, storagePoolDelete, storageVolumeCreateXML)
(storageVolumeCreateXMLFrom, storageVolumeDelete): Likewise.
* src/util/bridge.c (brProbeVnetHdr): Likewise.
* po/POTFILES.in: Drop src/util/bridge.c.
2011-05-11 15:08:44 +00:00
|
|
|
VIR_INFO("Undefining storage pool '%s'", pool->def->name);
|
2008-10-10 15:13:28 +00:00
|
|
|
virStoragePoolObjRemove(&driver->pools, pool);
|
2008-12-04 21:40:42 +00:00
|
|
|
pool = NULL;
|
2008-12-04 21:39:45 +00:00
|
|
|
ret = 0;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2008-12-04 21:40:42 +00:00
|
|
|
if (pool)
|
|
|
|
virStoragePoolObjUnlock(pool);
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
storagePoolCreate(virStoragePoolPtr obj,
|
|
|
|
unsigned int flags)
|
2011-07-06 22:51:23 +00:00
|
|
|
{
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageBackendPtr backend;
|
2008-12-04 21:39:45 +00:00
|
|
|
int ret = -1;
|
2015-03-09 14:36:44 +00:00
|
|
|
char *stateFile = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2011-07-06 22:51:23 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2014-06-05 08:40:59 +00:00
|
|
|
if (!(pool = virStoragePoolObjFromStoragePool(obj)))
|
|
|
|
return -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStoragePoolCreateEnsureACL(obj->conn, pool->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2008-12-04 21:39:45 +00:00
|
|
|
if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
|
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
|
|
|
if (virStoragePoolObjIsActive(pool)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2012-10-08 22:37:22 +00:00
|
|
|
_("storage pool '%s' is already active"),
|
|
|
|
pool->def->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2015-03-09 14:36:44 +00:00
|
|
|
|
|
|
|
VIR_INFO("Starting up storage pool '%s'", pool->def->name);
|
2008-02-20 15:34:52 +00:00
|
|
|
if (backend->startPool &&
|
|
|
|
backend->startPool(obj->conn, pool) < 0)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-03-09 14:36:44 +00:00
|
|
|
stateFile = virFileBuildPath(driver->stateDir,
|
|
|
|
pool->def->name, ".xml");
|
|
|
|
|
|
|
|
if (!stateFile || virStoragePoolSaveState(stateFile, pool->def) < 0 ||
|
|
|
|
backend->refreshPool(obj->conn, pool) < 0) {
|
2015-04-27 14:43:22 +00:00
|
|
|
if (stateFile)
|
|
|
|
unlink(stateFile);
|
2008-02-20 15:34:52 +00:00
|
|
|
if (backend->stopPool)
|
|
|
|
backend->stopPool(obj->conn, pool);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pool->active = 1;
|
2008-12-04 21:39:45 +00:00
|
|
|
ret = 0;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2015-03-09 14:36:44 +00:00
|
|
|
VIR_FREE(stateFile);
|
2014-06-12 07:55:17 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
storagePoolBuild(virStoragePoolPtr obj,
|
2014-03-18 08:15:36 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageBackendPtr backend;
|
2008-12-04 21:39:45 +00:00
|
|
|
int ret = -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-06-05 08:40:59 +00:00
|
|
|
if (!(pool = virStoragePoolObjFromStoragePool(obj)))
|
|
|
|
return -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStoragePoolBuildEnsureACL(obj->conn, pool->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2008-12-04 21:39:45 +00:00
|
|
|
if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
|
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
|
|
|
if (virStoragePoolObjIsActive(pool)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2012-10-08 22:37:22 +00:00
|
|
|
_("storage pool '%s' is already active"),
|
|
|
|
pool->def->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (backend->buildPool &&
|
|
|
|
backend->buildPool(obj->conn, pool, flags) < 0)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
ret = 0;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-12 07:55:17 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2014-03-18 08:15:36 +00:00
|
|
|
storagePoolDestroy(virStoragePoolPtr obj)
|
|
|
|
{
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageBackendPtr backend;
|
2015-03-09 14:36:44 +00:00
|
|
|
char *stateFile = NULL;
|
2008-12-04 21:39:45 +00:00
|
|
|
int ret = -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2014-06-05 08:40:59 +00:00
|
|
|
if (!(pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid))) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(obj->uuid, uuidstr);
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_NO_STORAGE_POOL,
|
2014-06-05 08:40:59 +00:00
|
|
|
_("no storage pool with matching uuid '%s' (%s)"),
|
|
|
|
uuidstr, obj->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStoragePoolDestroyEnsureACL(obj->conn, pool->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2008-12-04 21:39:45 +00:00
|
|
|
if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
|
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2015-03-09 14:36:44 +00:00
|
|
|
VIR_INFO("Destroying storage pool '%s'", pool->def->name);
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
if (!virStoragePoolObjIsActive(pool)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2012-10-08 22:37:22 +00:00
|
|
|
_("storage pool '%s' is not active"), pool->def->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2009-04-17 19:12:37 +00:00
|
|
|
if (pool->asyncjobs > 0) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("pool '%s' has asynchronous jobs running."),
|
|
|
|
pool->def->name);
|
2009-04-17 19:12:37 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2015-03-09 14:36:44 +00:00
|
|
|
if (!(stateFile = virFileBuildPath(driver->stateDir,
|
|
|
|
pool->def->name,
|
|
|
|
".xml")))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
unlink(stateFile);
|
|
|
|
VIR_FREE(stateFile);
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
if (backend->stopPool &&
|
|
|
|
backend->stopPool(obj->conn, pool) < 0)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
|
|
|
virStoragePoolObjClearVols(pool);
|
|
|
|
|
|
|
|
pool->active = 0;
|
|
|
|
|
2008-12-04 21:40:42 +00:00
|
|
|
if (pool->configFile == NULL) {
|
2008-10-10 15:13:28 +00:00
|
|
|
virStoragePoolObjRemove(&driver->pools, pool);
|
2008-12-04 21:40:42 +00:00
|
|
|
pool = NULL;
|
2012-06-25 09:38:17 +00:00
|
|
|
} else if (pool->newDef) {
|
|
|
|
virStoragePoolDefFree(pool->def);
|
|
|
|
pool->def = pool->newDef;
|
|
|
|
pool->newDef = NULL;
|
2008-12-04 21:40:42 +00:00
|
|
|
}
|
2015-03-09 14:36:44 +00:00
|
|
|
|
2008-12-04 21:39:45 +00:00
|
|
|
ret = 0;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2008-12-04 21:40:42 +00:00
|
|
|
if (pool)
|
|
|
|
virStoragePoolObjUnlock(pool);
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
storagePoolDelete(virStoragePoolPtr obj,
|
2014-03-18 08:15:36 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageBackendPtr backend;
|
2015-03-09 14:36:44 +00:00
|
|
|
char *stateFile = NULL;
|
2008-12-04 21:39:45 +00:00
|
|
|
int ret = -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-06-05 08:40:59 +00:00
|
|
|
if (!(pool = virStoragePoolObjFromStoragePool(obj)))
|
|
|
|
return -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStoragePoolDeleteEnsureACL(obj->conn, pool->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2008-12-04 21:39:45 +00:00
|
|
|
if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
|
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2015-03-09 14:36:44 +00:00
|
|
|
VIR_INFO("Deleting storage pool '%s'", pool->def->name);
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
if (virStoragePoolObjIsActive(pool)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2012-10-08 22:37:22 +00:00
|
|
|
_("storage pool '%s' is still active"),
|
|
|
|
pool->def->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2009-04-17 19:12:37 +00:00
|
|
|
if (pool->asyncjobs > 0) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("pool '%s' has asynchronous jobs running."),
|
2009-04-17 19:12:37 +00:00
|
|
|
pool->def->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2015-03-09 14:36:44 +00:00
|
|
|
if (!(stateFile = virFileBuildPath(driver->stateDir,
|
|
|
|
pool->def->name,
|
|
|
|
".xml")))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
unlink(stateFile);
|
|
|
|
VIR_FREE(stateFile);
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
if (!backend->deletePool) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_NO_SUPPORT,
|
|
|
|
"%s", _("pool does not support pool deletion"));
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
if (backend->deletePool(obj->conn, pool, flags) < 0)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2015-03-09 14:36:44 +00:00
|
|
|
|
2008-12-04 21:39:45 +00:00
|
|
|
ret = 0;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-12 07:55:17 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
storagePoolRefresh(virStoragePoolPtr obj,
|
2011-07-06 22:51:23 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageBackendPtr backend;
|
2008-12-04 21:39:45 +00:00
|
|
|
int ret = -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2011-07-06 22:51:23 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2014-06-05 08:40:59 +00:00
|
|
|
if (!(pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid))) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(obj->uuid, uuidstr);
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_NO_STORAGE_POOL,
|
2014-06-05 08:40:59 +00:00
|
|
|
_("no storage pool with matching uuid '%s' (%s)"),
|
|
|
|
uuidstr, obj->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStoragePoolRefreshEnsureACL(obj->conn, pool->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2008-12-04 21:39:45 +00:00
|
|
|
if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
|
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
|
|
|
if (!virStoragePoolObjIsActive(pool)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2012-10-08 22:37:22 +00:00
|
|
|
_("storage pool '%s' is not active"), pool->def->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2009-04-17 19:12:37 +00:00
|
|
|
if (pool->asyncjobs > 0) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("pool '%s' has asynchronous jobs running."),
|
|
|
|
pool->def->name);
|
2009-04-17 19:12:37 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
virStoragePoolObjClearVols(pool);
|
2008-12-04 21:39:45 +00:00
|
|
|
if (backend->refreshPool(obj->conn, pool) < 0) {
|
2008-02-20 15:34:52 +00:00
|
|
|
if (backend->stopPool)
|
|
|
|
backend->stopPool(obj->conn, pool);
|
|
|
|
|
|
|
|
pool->active = 0;
|
|
|
|
|
2008-12-04 21:40:42 +00:00
|
|
|
if (pool->configFile == NULL) {
|
2008-10-10 15:13:28 +00:00
|
|
|
virStoragePoolObjRemove(&driver->pools, pool);
|
2008-12-04 21:40:42 +00:00
|
|
|
pool = NULL;
|
|
|
|
}
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2008-12-04 21:39:45 +00:00
|
|
|
ret = 0;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2008-12-04 21:40:42 +00:00
|
|
|
if (pool)
|
|
|
|
virStoragePoolObjUnlock(pool);
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2008-02-20 15:34:52 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
storagePoolGetInfo(virStoragePoolPtr obj,
|
2014-03-18 08:15:36 +00:00
|
|
|
virStoragePoolInfoPtr info)
|
|
|
|
{
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
|
|
|
int ret = -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-06-05 08:40:59 +00:00
|
|
|
if (!(pool = virStoragePoolObjFromStoragePool(obj)))
|
|
|
|
return -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStoragePoolGetInfoEnsureACL(obj->conn, pool->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2009-09-04 15:18:29 +00:00
|
|
|
if (virStorageBackendForType(pool->def->type) == NULL)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
|
|
|
memset(info, 0, sizeof(virStoragePoolInfo));
|
|
|
|
if (pool->active)
|
|
|
|
info->state = VIR_STORAGE_POOL_RUNNING;
|
|
|
|
else
|
|
|
|
info->state = VIR_STORAGE_POOL_INACTIVE;
|
|
|
|
info->capacity = pool->def->capacity;
|
|
|
|
info->allocation = pool->def->allocation;
|
|
|
|
info->available = pool->def->available;
|
2008-12-04 21:39:45 +00:00
|
|
|
ret = 0;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-12 07:55:17 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
2011-05-06 19:53:10 +00:00
|
|
|
storagePoolGetXMLDesc(virStoragePoolPtr obj,
|
2011-07-06 22:51:23 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
2012-06-25 10:24:45 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2008-12-04 21:39:45 +00:00
|
|
|
char *ret = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2012-06-25 10:24:45 +00:00
|
|
|
virCheckFlags(VIR_STORAGE_XML_INACTIVE, NULL);
|
2011-07-06 22:51:23 +00:00
|
|
|
|
2014-06-05 08:40:59 +00:00
|
|
|
if (!(pool = virStoragePoolObjFromStoragePool(obj)))
|
|
|
|
return NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStoragePoolGetXMLDescEnsureACL(obj->conn, pool->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-06-25 10:24:45 +00:00
|
|
|
if ((flags & VIR_STORAGE_XML_INACTIVE) && pool->newDef)
|
|
|
|
def = pool->newDef;
|
|
|
|
else
|
|
|
|
def = pool->def;
|
|
|
|
|
|
|
|
ret = virStoragePoolDefFormat(def);
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-12 07:55:17 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
storagePoolGetAutostart(virStoragePoolPtr obj,
|
2014-03-18 08:15:36 +00:00
|
|
|
int *autostart)
|
|
|
|
{
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
|
|
|
int ret = -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-06-05 08:40:59 +00:00
|
|
|
if (!(pool = virStoragePoolObjFromStoragePool(obj)))
|
|
|
|
return -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStoragePoolGetAutostartEnsureACL(obj->conn, pool->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
if (!pool->configFile) {
|
|
|
|
*autostart = 0;
|
|
|
|
} else {
|
|
|
|
*autostart = pool->autostart;
|
|
|
|
}
|
2008-12-04 21:39:45 +00:00
|
|
|
ret = 0;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-12 07:55:17 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
storagePoolSetAutostart(virStoragePoolPtr obj,
|
2014-03-18 08:15:36 +00:00
|
|
|
int autostart)
|
|
|
|
{
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
|
|
|
int ret = -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2008-12-04 21:39:45 +00:00
|
|
|
pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
|
2008-12-04 21:40:42 +00:00
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
if (!pool) {
|
2014-06-05 08:40:59 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(obj->uuid, uuidstr);
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_NO_STORAGE_POOL,
|
2014-06-05 08:40:59 +00:00
|
|
|
_("no storage pool with matching uuid '%s' (%s)"),
|
|
|
|
uuidstr, obj->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStoragePoolSetAutostartEnsureACL(obj->conn, pool->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
if (!pool->configFile) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("pool has no config file"));
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
autostart = (autostart != 0);
|
|
|
|
|
2008-12-04 21:39:45 +00:00
|
|
|
if (pool->autostart != autostart) {
|
|
|
|
if (autostart) {
|
2011-07-05 21:02:53 +00:00
|
|
|
if (virFileMakePath(driver->autostartDir) < 0) {
|
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot create autostart directory %s"),
|
|
|
|
driver->autostartDir);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2008-12-04 21:39:45 +00:00
|
|
|
if (symlink(pool->configFile, pool->autostartLink) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("Failed to create symlink '%s' to '%s'"),
|
|
|
|
pool->autostartLink, pool->configFile);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (unlink(pool->autostartLink) < 0 &&
|
|
|
|
errno != ENOENT && errno != ENOTDIR) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("Failed to delete symlink '%s'"),
|
|
|
|
pool->autostartLink);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2008-12-04 21:39:45 +00:00
|
|
|
pool->autostart = autostart;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2008-12-04 21:39:45 +00:00
|
|
|
ret = 0;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2008-12-04 21:40:42 +00:00
|
|
|
if (pool)
|
|
|
|
virStoragePoolObjUnlock(pool);
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2014-03-18 08:15:36 +00:00
|
|
|
storagePoolNumOfVolumes(virStoragePoolPtr obj)
|
|
|
|
{
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
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
|
|
|
int ret = -1;
|
|
|
|
size_t i;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-06-05 08:40:59 +00:00
|
|
|
if (!(pool = virStoragePoolObjFromStoragePool(obj)))
|
|
|
|
return -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStoragePoolNumOfVolumesEnsureACL(obj->conn, pool->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
if (!virStoragePoolObjIsActive(pool)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2012-10-08 22:37:22 +00:00
|
|
|
_("storage pool '%s' is not active"), pool->def->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2013-06-26 17:47:48 +00:00
|
|
|
ret = 0;
|
|
|
|
for (i = 0; i < pool->volumes.count; i++) {
|
|
|
|
if (virStoragePoolNumOfVolumesCheckACL(obj->conn, pool->def,
|
|
|
|
pool->volumes.objs[i]))
|
|
|
|
ret++;
|
|
|
|
}
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-12 07:55:17 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
storagePoolListVolumes(virStoragePoolPtr obj,
|
|
|
|
char **const names,
|
2014-03-18 08:15:36 +00:00
|
|
|
int maxnames)
|
|
|
|
{
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
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;
|
|
|
|
int n = 0;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2008-12-04 21:39:45 +00:00
|
|
|
memset(names, 0, maxnames * sizeof(*names));
|
|
|
|
|
2014-06-05 08:40:59 +00:00
|
|
|
if (!(pool = virStoragePoolObjFromStoragePool(obj)))
|
|
|
|
return -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStoragePoolListVolumesEnsureACL(obj->conn, pool->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
if (!virStoragePoolObjIsActive(pool)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2012-10-08 22:37:22 +00:00
|
|
|
_("storage pool '%s' is not active"), pool->def->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2013-05-21 07:21:21 +00:00
|
|
|
for (i = 0; i < pool->volumes.count && n < maxnames; i++) {
|
2013-06-26 17:47:48 +00:00
|
|
|
if (!virStoragePoolListVolumesCheckACL(obj->conn, pool->def,
|
|
|
|
pool->volumes.objs[i]))
|
|
|
|
continue;
|
2013-05-03 12:49:08 +00:00
|
|
|
if (VIR_STRDUP(names[n++], pool->volumes.objs[i]->name) < 0)
|
2008-02-20 15:34:52 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2008-12-04 21:40:42 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2008-10-10 15:13:28 +00:00
|
|
|
return n;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
|
|
|
cleanup:
|
2014-06-12 07:55:17 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2013-05-21 07:21:21 +00:00
|
|
|
for (n = 0; n < maxnames; n++)
|
2008-12-04 21:39:45 +00:00
|
|
|
VIR_FREE(names[n]);
|
2008-10-10 15:13:28 +00:00
|
|
|
|
2008-12-02 15:59:14 +00:00
|
|
|
memset(names, 0, maxnames * sizeof(*names));
|
2008-02-20 15:34:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-09-04 15:32:55 +00:00
|
|
|
static int
|
|
|
|
storagePoolListAllVolumes(virStoragePoolPtr pool,
|
|
|
|
virStorageVolPtr **vols,
|
2014-03-18 08:15:36 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2012-09-04 15:32:55 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
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-09-04 15:32:55 +00:00
|
|
|
virStorageVolPtr *tmp_vols = NULL;
|
|
|
|
virStorageVolPtr vol = NULL;
|
|
|
|
int nvols = 0;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2014-06-05 08:40:59 +00:00
|
|
|
if (!(obj = virStoragePoolObjFromStoragePool(pool)))
|
|
|
|
return -1;
|
2012-09-04 15:32:55 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStoragePoolListAllVolumesEnsureACL(pool->conn, obj->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-09-04 15:32:55 +00:00
|
|
|
if (!virStoragePoolObjIsActive(obj)) {
|
2012-10-08 22:37:22 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("storage pool '%s' is not active"), obj->def->name);
|
2012-09-04 15:32:55 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Just returns the volumes count */
|
|
|
|
if (!vols) {
|
|
|
|
ret = obj->volumes.count;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-07-04 10:16:29 +00:00
|
|
|
if (VIR_ALLOC_N(tmp_vols, obj->volumes.count + 1) < 0)
|
2013-06-26 17:47:48 +00:00
|
|
|
goto cleanup;
|
2012-09-04 15:32:55 +00:00
|
|
|
|
2013-05-21 07:21:21 +00:00
|
|
|
for (i = 0; i < obj->volumes.count; i++) {
|
2013-06-26 17:47:48 +00:00
|
|
|
if (!virStoragePoolListAllVolumesCheckACL(pool->conn, obj->def,
|
|
|
|
obj->volumes.objs[i]))
|
|
|
|
continue;
|
2012-09-04 15:32:55 +00:00
|
|
|
if (!(vol = virGetStorageVol(pool->conn, obj->def->name,
|
|
|
|
obj->volumes.objs[i]->name,
|
2012-11-10 07:18:07 +00:00
|
|
|
obj->volumes.objs[i]->key,
|
|
|
|
NULL, NULL)))
|
2012-09-04 15:32:55 +00:00
|
|
|
goto cleanup;
|
|
|
|
tmp_vols[nvols++] = vol;
|
|
|
|
}
|
|
|
|
|
|
|
|
*vols = tmp_vols;
|
|
|
|
tmp_vols = NULL;
|
|
|
|
ret = nvols;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (tmp_vols) {
|
2014-11-30 14:26:02 +00:00
|
|
|
for (i = 0; i < nvols; i++)
|
|
|
|
virObjectUnref(tmp_vols[i]);
|
2013-01-09 14:54:15 +00:00
|
|
|
VIR_FREE(tmp_vols);
|
2012-09-04 15:32:55 +00:00
|
|
|
}
|
|
|
|
|
2014-06-12 07:55:17 +00:00
|
|
|
virStoragePoolObjUnlock(obj);
|
2012-09-04 15:32:55 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2008-02-20 15:34:52 +00:00
|
|
|
|
|
|
|
static virStorageVolPtr
|
2013-04-23 12:50:18 +00:00
|
|
|
storageVolLookupByName(virStoragePoolPtr obj,
|
2014-03-18 08:15:36 +00:00
|
|
|
const char *name)
|
|
|
|
{
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageVolDefPtr vol;
|
2008-12-04 21:39:45 +00:00
|
|
|
virStorageVolPtr ret = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-06-05 08:40:59 +00:00
|
|
|
if (!(pool = virStoragePoolObjFromStoragePool(obj)))
|
|
|
|
return NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
|
|
|
if (!virStoragePoolObjIsActive(pool)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2012-10-08 22:37:22 +00:00
|
|
|
_("storage pool '%s' is not active"), pool->def->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
vol = virStorageVolDefFindByName(pool, name);
|
|
|
|
|
|
|
|
if (!vol) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_NO_STORAGE_VOL,
|
|
|
|
_("no storage vol with matching name '%s'"),
|
|
|
|
name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStorageVolLookupByNameEnsureACL(obj->conn, pool->def, vol) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-11-10 07:18:07 +00:00
|
|
|
ret = virGetStorageVol(obj->conn, pool->def->name, vol->name, vol->key,
|
|
|
|
NULL, NULL);
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-12 07:55:17 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static virStorageVolPtr
|
2013-04-23 12:50:18 +00:00
|
|
|
storageVolLookupByKey(virConnectPtr conn,
|
2014-03-18 08:15:36 +00:00
|
|
|
const char *key)
|
|
|
|
{
|
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;
|
2008-12-04 21:39:45 +00:00
|
|
|
virStorageVolPtr ret = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2013-05-21 07:21:21 +00:00
|
|
|
for (i = 0; i < driver->pools.count && !ret; i++) {
|
2008-12-04 21:40:42 +00:00
|
|
|
virStoragePoolObjLock(driver->pools.objs[i]);
|
2008-10-10 15:13:28 +00:00
|
|
|
if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
|
|
|
|
virStorageVolDefPtr vol =
|
|
|
|
virStorageVolDefFindByKey(driver->pools.objs[i], key);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (vol) {
|
2014-11-19 08:48:09 +00:00
|
|
|
virStoragePoolDefPtr def = driver->pools.objs[i]->def;
|
|
|
|
if (virStorageVolLookupByKeyEnsureACL(conn, def, vol) < 0) {
|
2013-07-04 12:41:46 +00:00
|
|
|
virStoragePoolObjUnlock(driver->pools.objs[i]);
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
2013-07-04 12:41:46 +00:00
|
|
|
}
|
2013-04-23 10:56:22 +00:00
|
|
|
|
2008-12-04 21:39:45 +00:00
|
|
|
ret = virGetStorageVol(conn,
|
2014-11-19 08:48:09 +00:00
|
|
|
def->name,
|
2008-12-04 21:40:42 +00:00
|
|
|
vol->name,
|
2012-11-10 07:18:07 +00:00
|
|
|
vol->key,
|
|
|
|
NULL, NULL);
|
2013-04-23 10:56:22 +00:00
|
|
|
}
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2008-12-04 21:40:42 +00:00
|
|
|
virStoragePoolObjUnlock(driver->pools.objs[i]);
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:39:45 +00:00
|
|
|
if (!ret)
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_NO_STORAGE_VOL,
|
2012-10-08 22:37:22 +00:00
|
|
|
_("no storage vol with matching key %s"), key);
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static virStorageVolPtr
|
2013-04-23 12:50:18 +00:00
|
|
|
storageVolLookupByPath(virConnectPtr conn,
|
2014-03-18 08:15:36 +00:00
|
|
|
const char *path)
|
|
|
|
{
|
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;
|
2008-12-04 21:39:45 +00:00
|
|
|
virStorageVolPtr ret = NULL;
|
2010-05-20 15:41:31 +00:00
|
|
|
char *cleanpath;
|
|
|
|
|
|
|
|
cleanpath = virFileSanitizePath(path);
|
|
|
|
if (!cleanpath)
|
|
|
|
return NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2013-05-21 07:21:21 +00:00
|
|
|
for (i = 0; i < driver->pools.count && !ret; i++) {
|
2014-02-25 14:51:15 +00:00
|
|
|
virStoragePoolObjPtr pool = driver->pools.objs[i];
|
|
|
|
virStorageVolDefPtr vol;
|
|
|
|
char *stable_path = NULL;
|
|
|
|
|
|
|
|
virStoragePoolObjLock(pool);
|
2008-11-17 11:19:33 +00:00
|
|
|
|
2014-02-25 14:51:15 +00:00
|
|
|
if (!virStoragePoolObjIsActive(pool)) {
|
|
|
|
virStoragePoolObjUnlock(pool);
|
|
|
|
continue;
|
|
|
|
}
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-05-11 15:08:50 +00:00
|
|
|
switch ((virStoragePoolType) pool->def->type) {
|
2014-02-25 14:51:15 +00:00
|
|
|
case VIR_STORAGE_POOL_DIR:
|
|
|
|
case VIR_STORAGE_POOL_FS:
|
|
|
|
case VIR_STORAGE_POOL_NETFS:
|
|
|
|
case VIR_STORAGE_POOL_LOGICAL:
|
|
|
|
case VIR_STORAGE_POOL_DISK:
|
|
|
|
case VIR_STORAGE_POOL_ISCSI:
|
|
|
|
case VIR_STORAGE_POOL_SCSI:
|
|
|
|
case VIR_STORAGE_POOL_MPATH:
|
|
|
|
stable_path = virStorageBackendStablePath(pool,
|
|
|
|
cleanpath,
|
|
|
|
false);
|
|
|
|
if (stable_path == NULL) {
|
|
|
|
/* Don't break the whole lookup process if it fails on
|
|
|
|
* getting the stable path for some of the pools.
|
|
|
|
*/
|
|
|
|
VIR_WARN("Failed to get stable path for pool '%s'",
|
|
|
|
pool->def->name);
|
|
|
|
virStoragePoolObjUnlock(pool);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_STORAGE_POOL_GLUSTER:
|
|
|
|
case VIR_STORAGE_POOL_RBD:
|
|
|
|
case VIR_STORAGE_POOL_SHEEPDOG:
|
2014-07-21 14:38:42 +00:00
|
|
|
case VIR_STORAGE_POOL_ZFS:
|
2014-02-25 14:51:15 +00:00
|
|
|
case VIR_STORAGE_POOL_LAST:
|
|
|
|
if (VIR_STRDUP(stable_path, path) < 0) {
|
|
|
|
virStoragePoolObjUnlock(pool);
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
2013-07-04 12:41:46 +00:00
|
|
|
}
|
2014-02-25 14:51:15 +00:00
|
|
|
break;
|
|
|
|
}
|
2013-04-23 10:56:22 +00:00
|
|
|
|
2014-02-25 14:51:15 +00:00
|
|
|
vol = virStorageVolDefFindByPath(pool, stable_path);
|
|
|
|
VIR_FREE(stable_path);
|
|
|
|
|
|
|
|
if (vol) {
|
|
|
|
if (virStorageVolLookupByPathEnsureACL(conn, pool->def, vol) < 0) {
|
|
|
|
virStoragePoolObjUnlock(pool);
|
|
|
|
goto cleanup;
|
2013-04-23 10:56:22 +00:00
|
|
|
}
|
2014-02-25 14:51:15 +00:00
|
|
|
|
|
|
|
ret = virGetStorageVol(conn, pool->def->name,
|
|
|
|
vol->name, vol->key,
|
|
|
|
NULL, NULL);
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2014-02-25 14:51:15 +00:00
|
|
|
|
|
|
|
virStoragePoolObjUnlock(pool);
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2014-02-24 15:07:40 +00:00
|
|
|
if (!ret) {
|
|
|
|
if (STREQ(path, cleanpath)) {
|
|
|
|
virReportError(VIR_ERR_NO_STORAGE_VOL,
|
|
|
|
_("no storage vol with matching path '%s'"), path);
|
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_NO_STORAGE_VOL,
|
|
|
|
_("no storage vol with matching path '%s' (%s)"),
|
|
|
|
path, cleanpath);
|
|
|
|
}
|
|
|
|
}
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2010-05-20 15:41:31 +00:00
|
|
|
VIR_FREE(cleanpath);
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2014-11-26 16:13:00 +00:00
|
|
|
virStoragePoolPtr
|
|
|
|
storagePoolLookupByTargetPath(virConnectPtr conn,
|
|
|
|
const char *path)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
virStoragePoolPtr ret = NULL;
|
|
|
|
char *cleanpath;
|
|
|
|
|
|
|
|
cleanpath = virFileSanitizePath(path);
|
|
|
|
if (!cleanpath)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
storageDriverLock();
|
|
|
|
for (i = 0; i < driver->pools.count && !ret; i++) {
|
|
|
|
virStoragePoolObjPtr pool = driver->pools.objs[i];
|
|
|
|
|
|
|
|
virStoragePoolObjLock(pool);
|
|
|
|
|
|
|
|
if (!virStoragePoolObjIsActive(pool)) {
|
|
|
|
virStoragePoolObjUnlock(pool);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (STREQ(path, pool->def->target.path)) {
|
|
|
|
ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
|
|
|
|
NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
virStoragePoolObjUnlock(pool);
|
|
|
|
}
|
|
|
|
storageDriverUnlock();
|
|
|
|
|
|
|
|
if (!ret) {
|
|
|
|
virReportError(VIR_ERR_NO_STORAGE_VOL,
|
|
|
|
_("no storage pool with matching target path '%s'"),
|
|
|
|
path);
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(cleanpath);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-12-10 14:28:58 +00:00
|
|
|
|
2014-04-08 22:54:14 +00:00
|
|
|
static int
|
|
|
|
storageVolDeleteInternal(virStorageVolPtr obj,
|
|
|
|
virStorageBackendPtr backend,
|
|
|
|
virStoragePoolObjPtr pool,
|
|
|
|
virStorageVolDefPtr vol,
|
|
|
|
unsigned int flags,
|
|
|
|
bool updateMeta)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!backend->deleteVol) {
|
|
|
|
virReportError(VIR_ERR_NO_SUPPORT,
|
|
|
|
"%s", _("storage pool does not support vol deletion"));
|
|
|
|
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (backend->deleteVol(obj->conn, pool, vol, flags) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* Update pool metadata - don't update meta data from error paths
|
2015-05-26 13:23:28 +00:00
|
|
|
* in this module since the allocation/available weren't adjusted yet.
|
|
|
|
* Ignore the disk backend since it updates the pool values.
|
2014-04-08 22:54:14 +00:00
|
|
|
*/
|
|
|
|
if (updateMeta) {
|
2015-05-26 13:23:28 +00:00
|
|
|
if (pool->def->type != VIR_STORAGE_POOL_DISK) {
|
|
|
|
pool->def->allocation -= vol->target.allocation;
|
|
|
|
pool->def->available += vol->target.allocation;
|
|
|
|
}
|
2014-04-08 22:54:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < pool->volumes.count; i++) {
|
|
|
|
if (pool->volumes.objs[i] == vol) {
|
|
|
|
VIR_INFO("Deleting volume '%s' from storage pool '%s'",
|
|
|
|
vol->name, pool->def->name);
|
|
|
|
virStorageVolDefFree(vol);
|
|
|
|
|
|
|
|
VIR_DELETE_ELEMENT(pool->volumes.objs, i, pool->volumes.count);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-05 11:29:37 +00:00
|
|
|
static virStorageVolDefPtr
|
|
|
|
virStorageVolDefFromVol(virStorageVolPtr obj,
|
|
|
|
virStoragePoolObjPtr *pool,
|
|
|
|
virStorageBackendPtr *backend)
|
2013-12-10 14:28:58 +00:00
|
|
|
{
|
|
|
|
virStorageVolDefPtr vol = NULL;
|
2014-06-05 11:29:37 +00:00
|
|
|
|
|
|
|
*pool = NULL;
|
2013-12-10 14:28:58 +00:00
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2014-06-05 11:29:37 +00:00
|
|
|
*pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2013-12-10 14:28:58 +00:00
|
|
|
|
2014-06-05 11:29:37 +00:00
|
|
|
if (!*pool) {
|
2013-12-10 14:28:58 +00:00
|
|
|
virReportError(VIR_ERR_NO_STORAGE_POOL,
|
|
|
|
_("no storage pool with matching name '%s'"),
|
|
|
|
obj->pool);
|
2014-06-05 11:29:37 +00:00
|
|
|
return NULL;
|
2013-12-10 14:28:58 +00:00
|
|
|
}
|
|
|
|
|
2014-06-05 11:29:37 +00:00
|
|
|
if (!virStoragePoolObjIsActive(*pool)) {
|
2013-12-10 14:28:58 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2014-06-05 11:29:37 +00:00
|
|
|
_("storage pool '%s' is not active"),
|
|
|
|
(*pool)->def->name);
|
|
|
|
goto error;
|
2013-12-10 14:28:58 +00:00
|
|
|
}
|
|
|
|
|
2014-06-05 11:29:37 +00:00
|
|
|
if (!(vol = virStorageVolDefFindByName(*pool, obj->name))) {
|
2013-12-10 14:28:58 +00:00
|
|
|
virReportError(VIR_ERR_NO_STORAGE_VOL,
|
|
|
|
_("no storage vol with matching name '%s'"),
|
|
|
|
obj->name);
|
2014-06-05 11:29:37 +00:00
|
|
|
goto error;
|
2013-12-10 14:28:58 +00:00
|
|
|
}
|
|
|
|
|
2014-06-05 11:29:37 +00:00
|
|
|
if (backend) {
|
|
|
|
if (!(*backend = virStorageBackendForType((*pool)->def->type)))
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
return vol;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virStoragePoolObjUnlock(*pool);
|
|
|
|
*pool = NULL;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
storageVolDelete(virStorageVolPtr obj,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
virStoragePoolObjPtr pool;
|
|
|
|
virStorageBackendPtr backend;
|
|
|
|
virStorageVolDefPtr vol = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!(vol = virStorageVolDefFromVol(obj, &pool, &backend)))
|
|
|
|
return -1;
|
|
|
|
|
2013-12-10 14:28:58 +00:00
|
|
|
if (virStorageVolDeleteEnsureACL(obj->conn, pool->def, vol) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-04-16 13:16:20 +00:00
|
|
|
if (vol->in_use) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still in use."),
|
|
|
|
vol->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-12-10 14:28:58 +00:00
|
|
|
if (vol->building) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still being allocated."),
|
|
|
|
vol->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-04-08 22:54:14 +00:00
|
|
|
if (storageVolDeleteInternal(obj, backend, pool, vol, flags, true) < 0)
|
2013-12-10 14:28:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-05 11:29:37 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2013-12-10 14:28:58 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-04-17 19:12:37 +00:00
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
static virStorageVolPtr
|
2013-04-23 12:50:18 +00:00
|
|
|
storageVolCreateXML(virStoragePoolPtr obj,
|
|
|
|
const char *xmldesc,
|
|
|
|
unsigned int flags)
|
2011-07-06 22:51:23 +00:00
|
|
|
{
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageBackendPtr backend;
|
2009-04-17 19:12:37 +00:00
|
|
|
virStorageVolDefPtr voldef = NULL;
|
|
|
|
virStorageVolPtr ret = NULL, volobj = NULL;
|
2013-08-16 12:08:07 +00:00
|
|
|
virStorageVolDefPtr buildvoldef = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2012-12-05 10:48:07 +00:00
|
|
|
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
|
2011-07-06 22:51:23 +00:00
|
|
|
|
2014-06-05 08:40:59 +00:00
|
|
|
if (!(pool = virStoragePoolObjFromStoragePool(obj)))
|
|
|
|
return NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
|
|
|
if (!virStoragePoolObjIsActive(pool)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2012-10-08 22:37:22 +00:00
|
|
|
_("storage pool '%s' is not active"), pool->def->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2015-02-17 15:57:02 +00:00
|
|
|
voldef = virStorageVolDefParseString(pool->def, xmldesc,
|
|
|
|
VIR_VOL_XML_PARSE_OPT_CAPACITY);
|
2009-04-17 19:12:37 +00:00
|
|
|
if (voldef == NULL)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2015-02-17 15:57:02 +00:00
|
|
|
if (!voldef->target.capacity && !backend->buildVol) {
|
|
|
|
virReportError(VIR_ERR_NO_SUPPORT,
|
|
|
|
"%s", _("volume capacity required for this "
|
|
|
|
"storage pool"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStorageVolCreateXMLEnsureACL(obj->conn, pool->def, voldef) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2009-04-17 19:12:37 +00:00
|
|
|
if (virStorageVolDefFindByName(pool, voldef->name)) {
|
2013-10-07 17:21:47 +00:00
|
|
|
virReportError(VIR_ERR_STORAGE_VOL_EXIST,
|
2013-10-07 14:04:26 +00:00
|
|
|
_("'%s'"), voldef->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2008-10-10 15:13:28 +00:00
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
if (!backend->createVol) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_NO_SUPPORT,
|
|
|
|
"%s", _("storage pool does not support volume "
|
|
|
|
"creation"));
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
storage: use valid XML for awkward volume names
$ touch /var/lib/libvirt/images/'a<b>c'
$ virsh pool-refresh default
$ virsh vol-dumpxml 'a<b>c' default | head -n2
<volume>
<name>a<b>c</name>
Oops. That's not valid XML. And when we fix the XML
generation, it fails RelaxNG validation.
I'm also tired of seeing <key>(null)</key> in the example
output for volume xml; while we used NULLSTR() to avoid
a NULL deref rather than relying on glibc's printf
extension behavior, it's even better if we avoid the issue
in the first place. But this requires being careful that
we don't invalidate any storage backends that were relying
on key being unassigned during virStoragVolCreateXML[From].
I would have split this into two patches (one for escaping,
one for avoiding <key>(null)</key>), but since they both
end up touching a lot of the same test files, I ended up
merging it into one.
Note that this patch allows pretty much any volume name
that can appear in a directory (excluding . and .. because
those are special), but does nothing to change the current
(unenforced) RelaxNG claim that pool names will consist
only of letters, numbers, _, -, and +. Tightening the C
code to match RelaxNG patterns and/or relaxing the grammar
to match the C code for pool names is a task for another
day (but remember, we DID recently tighten C code for
domain names to exclude a leading '.').
* src/conf/storage_conf.c (virStoragePoolSourceFormat)
(virStoragePoolDefFormat, virStorageVolTargetDefFormat)
(virStorageVolDefFormat): Escape user-controlled strings.
(virStorageVolDefParseXML): Parse key, for use in unit tests.
* src/storage/storage_driver.c (storageVolCreateXML)
(storageVolCreateXMLFrom): Ensure parsed key doesn't confuse
volume creation.
* docs/schemas/basictypes.rng (volName): Relax definition.
* tests/storagepoolxml2xmltest.c (mymain): Test it.
* tests/storagevolxml2xmltest.c (mymain): Likewise.
* tests/storagepoolxml2xmlin/pool-dir-naming.xml: New file.
* tests/storagepoolxml2xmlout/pool-dir-naming.xml: Likewise.
* tests/storagevolxml2xmlin/vol-file-naming.xml: Likewise.
* tests/storagevolxml2xmlout/vol-file-naming.xml: Likewise.
* tests/storagevolxml2xmlout/vol-*.xml: Fix fallout.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-21 00:04:05 +00:00
|
|
|
/* Wipe any key the user may have suggested, as volume creation
|
|
|
|
* will generate the canonical key. */
|
|
|
|
VIR_FREE(voldef->key);
|
2014-11-13 14:25:27 +00:00
|
|
|
if (backend->createVol(obj->conn, pool, voldef) < 0)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2013-08-16 12:08:07 +00:00
|
|
|
if (VIR_ALLOC(buildvoldef) < 0) {
|
|
|
|
voldef = NULL;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-04-17 19:12:37 +00:00
|
|
|
|
2013-08-16 12:08:07 +00:00
|
|
|
/* Make a shallow copy of the 'defined' volume definition, since the
|
|
|
|
* original allocation value will change as the user polls 'info',
|
|
|
|
* but we only need the initial requested values
|
|
|
|
*/
|
|
|
|
memcpy(buildvoldef, voldef, sizeof(*voldef));
|
2009-04-17 19:12:37 +00:00
|
|
|
|
2013-08-16 12:08:07 +00:00
|
|
|
if (backend->buildVol) {
|
|
|
|
int buildret;
|
2009-04-17 19:12:37 +00:00
|
|
|
|
|
|
|
/* Drop the pool lock during volume allocation */
|
|
|
|
pool->asyncjobs++;
|
2014-07-17 16:41:21 +00:00
|
|
|
voldef->building = true;
|
2009-04-17 19:12:37 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
|
|
|
|
2012-12-05 10:48:07 +00:00
|
|
|
buildret = backend->buildVol(obj->conn, pool, buildvoldef, flags);
|
2009-04-17 19:12:37 +00:00
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2009-04-17 19:12:37 +00:00
|
|
|
virStoragePoolObjLock(pool);
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2009-05-19 11:06:25 +00:00
|
|
|
|
2014-07-17 16:41:21 +00:00
|
|
|
voldef->building = false;
|
2009-04-17 19:12:37 +00:00
|
|
|
pool->asyncjobs--;
|
|
|
|
|
2015-05-28 15:00:01 +00:00
|
|
|
if (buildret < 0)
|
2009-04-17 19:12:37 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2015-05-28 15:00:01 +00:00
|
|
|
if (VIR_REALLOC_N(pool->volumes.objs,
|
|
|
|
pool->volumes.count+1) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
pool->volumes.objs[pool->volumes.count++] = voldef;
|
|
|
|
if (!(volobj = virGetStorageVol(obj->conn, pool->def->name, voldef->name,
|
|
|
|
voldef->key, NULL, NULL)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2015-02-17 15:57:02 +00:00
|
|
|
if (backend->refreshVol &&
|
|
|
|
backend->refreshVol(obj->conn, pool, voldef) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2015-05-26 13:23:28 +00:00
|
|
|
/* Update pool metadata ignoring the disk backend since
|
|
|
|
* it updates the pool values.
|
|
|
|
*/
|
|
|
|
if (pool->def->type != VIR_STORAGE_POOL_DISK) {
|
|
|
|
pool->def->allocation += buildvoldef->target.allocation;
|
|
|
|
pool->def->available -= buildvoldef->target.allocation;
|
|
|
|
}
|
2013-08-16 12:08:07 +00:00
|
|
|
|
maint: omit translation for all VIR_INFO
We were 31/73 on whether to translate; since less than 50% translated
and since VIR_INFO is less than VIR_WARN which also doesn't translate,
this makes sense.
* cfg.mk (sc_prohibit_gettext_markup): Add VIR_INFO, since it
falls between WARN and DEBUG.
* daemon/libvirtd.c (qemudDispatchSignalEvent, remoteCheckAccess)
(qemudDispatchServer): Adjust offenders.
* daemon/remote.c (remoteDispatchAuthPolkit): Likewise.
* src/network/bridge_driver.c (networkReloadIptablesRules)
(networkStartNetworkDaemon, networkShutdownNetworkDaemon)
(networkCreate, networkDefine, networkUndefine): Likewise.
* src/qemu/qemu_driver.c (qemudDomainDefine)
(qemudDomainUndefine): Likewise.
* src/storage/storage_driver.c (storagePoolCreate)
(storagePoolDefine, storagePoolUndefine, storagePoolStart)
(storagePoolDestroy, storagePoolDelete, storageVolumeCreateXML)
(storageVolumeCreateXMLFrom, storageVolumeDelete): Likewise.
* src/util/bridge.c (brProbeVnetHdr): Likewise.
* po/POTFILES.in: Drop src/util/bridge.c.
2011-05-11 15:08:44 +00:00
|
|
|
VIR_INFO("Creating volume '%s' in storage pool '%s'",
|
2011-03-30 01:19:47 +00:00
|
|
|
volobj->name, pool->def->name);
|
2009-04-17 19:12:37 +00:00
|
|
|
ret = volobj;
|
|
|
|
volobj = NULL;
|
|
|
|
voldef = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
Convert public datatypes to inherit from virObject
This converts the following public API datatypes to use the
virObject infrastructure:
virConnectPtr
virDomainPtr
virDomainSnapshotPtr
virInterfacePtr
virNetworkPtr
virNodeDevicePtr
virNWFilterPtr
virSecretPtr
virStreamPtr
virStorageVolPtr
virStoragePoolPtr
The code is significantly simplified, since the mutex in the
virConnectPtr object now only needs to be held when accessing
the per-connection virError object instance. All other operations
are completely lock free.
* src/datatypes.c, src/datatypes.h, src/libvirt.c: Convert
public datatypes to use virObject
* src/conf/domain_event.c, src/phyp/phyp_driver.c,
src/qemu/qemu_command.c, src/qemu/qemu_migration.c,
src/qemu/qemu_process.c, src/storage/storage_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xend_internal.c,
tests/qemuxml2argvtest.c, tests/qemuxmlnstest.c,
tests/sexpr2xmltest.c, tests/xmconfigtest.c: Convert
to use virObjectUnref/virObjectRef
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-31 16:55:36 +00:00
|
|
|
virObjectUnref(volobj);
|
2009-04-17 19:12:37 +00:00
|
|
|
virStorageVolDefFree(voldef);
|
2013-08-20 09:08:49 +00:00
|
|
|
VIR_FREE(buildvoldef);
|
2008-12-04 21:40:42 +00:00
|
|
|
if (pool)
|
|
|
|
virStoragePoolObjUnlock(pool);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2009-05-19 13:37:51 +00:00
|
|
|
static virStorageVolPtr
|
2013-04-23 12:50:18 +00:00
|
|
|
storageVolCreateXMLFrom(virStoragePoolPtr obj,
|
|
|
|
const char *xmldesc,
|
|
|
|
virStorageVolPtr vobj,
|
|
|
|
unsigned int flags)
|
2011-07-06 22:51:23 +00:00
|
|
|
{
|
2009-05-19 13:37:51 +00:00
|
|
|
virStoragePoolObjPtr pool, origpool = NULL;
|
|
|
|
virStorageBackendPtr backend;
|
|
|
|
virStorageVolDefPtr origvol = NULL, newvol = NULL;
|
|
|
|
virStorageVolPtr ret = NULL, volobj = NULL;
|
2013-08-20 15:28:28 +00:00
|
|
|
unsigned long long allocation;
|
2009-09-02 13:02:06 +00:00
|
|
|
int buildret;
|
2009-05-19 13:37:51 +00:00
|
|
|
|
2015-01-23 10:22:35 +00:00
|
|
|
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA |
|
|
|
|
VIR_STORAGE_VOL_CREATE_REFLINK,
|
|
|
|
NULL);
|
2011-07-06 22:51:23 +00:00
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2009-05-19 13:37:51 +00:00
|
|
|
pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
|
2009-09-02 13:02:06 +00:00
|
|
|
if (pool && STRNEQ(obj->name, vobj->pool)) {
|
2009-07-10 16:56:12 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2009-05-19 13:37:51 +00:00
|
|
|
origpool = virStoragePoolObjFindByName(&driver->pools, vobj->pool);
|
2009-07-10 16:56:12 +00:00
|
|
|
virStoragePoolObjLock(pool);
|
2009-09-02 13:02:06 +00:00
|
|
|
}
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2009-05-19 13:37:51 +00:00
|
|
|
if (!pool) {
|
2014-06-05 08:40:59 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(obj->uuid, uuidstr);
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_NO_STORAGE_POOL,
|
2014-06-05 08:40:59 +00:00
|
|
|
_("no storage pool with matching uuid '%s' (%s)"),
|
|
|
|
uuidstr, obj->name);
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2009-09-02 13:02:06 +00:00
|
|
|
if (STRNEQ(obj->name, vobj->pool) && !origpool) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_NO_STORAGE_POOL,
|
|
|
|
_("no storage pool with matching name '%s'"),
|
|
|
|
vobj->pool);
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virStoragePoolObjIsActive(pool)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2012-10-08 22:37:22 +00:00
|
|
|
_("storage pool '%s' is not active"), pool->def->name);
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2009-09-02 13:02:06 +00:00
|
|
|
if (origpool && !virStoragePoolObjIsActive(origpool)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2012-10-08 22:37:22 +00:00
|
|
|
_("storage pool '%s' is not active"),
|
|
|
|
origpool->def->name);
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-11-19 08:48:09 +00:00
|
|
|
origvol = virStorageVolDefFindByName(origpool ?
|
|
|
|
origpool : pool, vobj->name);
|
2009-05-19 13:37:51 +00:00
|
|
|
if (!origvol) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_NO_STORAGE_VOL,
|
|
|
|
_("no storage vol with matching name '%s'"),
|
|
|
|
vobj->name);
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2015-02-17 15:54:53 +00:00
|
|
|
newvol = virStorageVolDefParseString(pool->def, xmldesc,
|
|
|
|
VIR_VOL_XML_PARSE_NO_CAPACITY);
|
2009-05-19 13:37:51 +00:00
|
|
|
if (newvol == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStorageVolCreateXMLFromEnsureACL(obj->conn, pool->def, newvol) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2009-05-19 13:37:51 +00:00
|
|
|
if (virStorageVolDefFindByName(pool, newvol->name)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("storage volume name '%s' already in use."),
|
|
|
|
newvol->name);
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2015-02-17 15:54:53 +00:00
|
|
|
/* Use the original volume's capacity in case the new capacity
|
|
|
|
* is less than that, or it was omitted */
|
conf: track sizes directly in source struct
One of the features of qcow2 is that a wrapper file can have
more capacity than its backing file from the guest's perspective;
what's more, sparse files make tracking allocation of both
the active and backing file worthwhile. As such, it makes
more sense to show allocation numbers for each file in a chain,
and not just the top-level file. This sets up the fields for
the tracking, although it does not modify XML to display any
new information.
* src/util/virstoragefile.h (_virStorageSource): Add fields.
* src/conf/storage_conf.h (_virStorageVolDef): Drop redundant
fields.
* src/storage/storage_backend.c (virStorageBackendCreateBlockFrom)
(createRawFile, virStorageBackendCreateQemuImgCmd)
(virStorageBackendCreateQcowCreate): Update clients.
* src/storage/storage_driver.c (storageVolDelete)
(storageVolCreateXML, storageVolCreateXMLFrom, storageVolResize)
(storageVolWipeInternal, storageVolGetInfo): Likewise.
* src/storage/storage_backend_fs.c (virStorageBackendProbeTarget)
(virStorageBackendFileSystemRefresh)
(virStorageBackendFileSystemVolResize)
(virStorageBackendFileSystemVolRefresh): Likewise.
* src/storage/storage_backend_logical.c
(virStorageBackendLogicalMakeVol)
(virStorageBackendLogicalCreateVol): Likewise.
* src/storage/storage_backend_scsi.c
(virStorageBackendSCSINewLun): Likewise.
* src/storage/storage_backend_mpath.c
(virStorageBackendMpathNewVol): Likewise.
* src/storage/storage_backend_rbd.c
(volStorageBackendRBDRefreshVolInfo)
(virStorageBackendRBDCreateImage): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol): Likewise.
* src/storage/storage_backend_sheepdog.c
(virStorageBackendSheepdogBuildVol)
(virStorageBackendSheepdogParseVdiList): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageBackendGlusterRefreshVol): Likewise.
* src/conf/storage_conf.c (virStorageVolDefFormat)
(virStorageVolDefParseXML): Likewise.
* src/test/test_driver.c (testOpenVolumesForPool)
(testStorageVolCreateXML, testStorageVolCreateXMLFrom)
(testStorageVolDelete, testStorageVolGetInfo): Likewise.
* src/esx/esx_storage_backend_iscsi.c (esxStorageVolGetXMLDesc):
Likewise.
* src/esx/esx_storage_backend_vmfs.c (esxStorageVolGetXMLDesc)
(esxStorageVolCreateXML): Likewise.
* src/parallels/parallels_driver.c (parallelsAddHddByVolume):
Likewise.
* src/parallels/parallels_storage.c (parallelsDiskDescParseNode)
(parallelsStorageVolDefineXML, parallelsStorageVolCreateXMLFrom)
(parallelsStorageVolDefRemove, parallelsStorageVolGetInfo):
Likewise.
* src/vbox/vbox_tmpl.c (vboxStorageVolCreateXML)
(vboxStorageVolGetXMLDesc): Likewise.
* tests/storagebackendsheepdogtest.c (test_vdi_list_parser):
Likewise.
* src/phyp/phyp_driver.c (phypStorageVolCreateXML): Likewise.
2014-04-01 23:43:36 +00:00
|
|
|
if (newvol->target.capacity < origvol->target.capacity)
|
|
|
|
newvol->target.capacity = origvol->target.capacity;
|
2009-05-19 13:37:51 +00:00
|
|
|
|
2009-06-22 16:33:24 +00:00
|
|
|
/* Make sure allocation is at least as large as the destination cap,
|
|
|
|
* to make absolutely sure we copy all possible contents */
|
conf: track sizes directly in source struct
One of the features of qcow2 is that a wrapper file can have
more capacity than its backing file from the guest's perspective;
what's more, sparse files make tracking allocation of both
the active and backing file worthwhile. As such, it makes
more sense to show allocation numbers for each file in a chain,
and not just the top-level file. This sets up the fields for
the tracking, although it does not modify XML to display any
new information.
* src/util/virstoragefile.h (_virStorageSource): Add fields.
* src/conf/storage_conf.h (_virStorageVolDef): Drop redundant
fields.
* src/storage/storage_backend.c (virStorageBackendCreateBlockFrom)
(createRawFile, virStorageBackendCreateQemuImgCmd)
(virStorageBackendCreateQcowCreate): Update clients.
* src/storage/storage_driver.c (storageVolDelete)
(storageVolCreateXML, storageVolCreateXMLFrom, storageVolResize)
(storageVolWipeInternal, storageVolGetInfo): Likewise.
* src/storage/storage_backend_fs.c (virStorageBackendProbeTarget)
(virStorageBackendFileSystemRefresh)
(virStorageBackendFileSystemVolResize)
(virStorageBackendFileSystemVolRefresh): Likewise.
* src/storage/storage_backend_logical.c
(virStorageBackendLogicalMakeVol)
(virStorageBackendLogicalCreateVol): Likewise.
* src/storage/storage_backend_scsi.c
(virStorageBackendSCSINewLun): Likewise.
* src/storage/storage_backend_mpath.c
(virStorageBackendMpathNewVol): Likewise.
* src/storage/storage_backend_rbd.c
(volStorageBackendRBDRefreshVolInfo)
(virStorageBackendRBDCreateImage): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol): Likewise.
* src/storage/storage_backend_sheepdog.c
(virStorageBackendSheepdogBuildVol)
(virStorageBackendSheepdogParseVdiList): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageBackendGlusterRefreshVol): Likewise.
* src/conf/storage_conf.c (virStorageVolDefFormat)
(virStorageVolDefParseXML): Likewise.
* src/test/test_driver.c (testOpenVolumesForPool)
(testStorageVolCreateXML, testStorageVolCreateXMLFrom)
(testStorageVolDelete, testStorageVolGetInfo): Likewise.
* src/esx/esx_storage_backend_iscsi.c (esxStorageVolGetXMLDesc):
Likewise.
* src/esx/esx_storage_backend_vmfs.c (esxStorageVolGetXMLDesc)
(esxStorageVolCreateXML): Likewise.
* src/parallels/parallels_driver.c (parallelsAddHddByVolume):
Likewise.
* src/parallels/parallels_storage.c (parallelsDiskDescParseNode)
(parallelsStorageVolDefineXML, parallelsStorageVolCreateXMLFrom)
(parallelsStorageVolDefRemove, parallelsStorageVolGetInfo):
Likewise.
* src/vbox/vbox_tmpl.c (vboxStorageVolCreateXML)
(vboxStorageVolGetXMLDesc): Likewise.
* tests/storagebackendsheepdogtest.c (test_vdi_list_parser):
Likewise.
* src/phyp/phyp_driver.c (phypStorageVolCreateXML): Likewise.
2014-04-01 23:43:36 +00:00
|
|
|
if (newvol->target.allocation < origvol->target.capacity)
|
|
|
|
newvol->target.allocation = origvol->target.capacity;
|
2009-06-22 16:33:24 +00:00
|
|
|
|
2009-05-19 13:37:51 +00:00
|
|
|
if (!backend->buildVolFrom) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_NO_SUPPORT,
|
2014-11-19 08:48:09 +00:00
|
|
|
"%s", _("storage pool does not support"
|
|
|
|
" volume creation from an existing volume"));
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (origvol->building) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still being allocated."),
|
|
|
|
origvol->name);
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (backend->refreshVol &&
|
|
|
|
backend->refreshVol(obj->conn, pool, origvol) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (VIR_REALLOC_N(pool->volumes.objs,
|
2013-07-04 10:16:29 +00:00
|
|
|
pool->volumes.count+1) < 0)
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
storage: use valid XML for awkward volume names
$ touch /var/lib/libvirt/images/'a<b>c'
$ virsh pool-refresh default
$ virsh vol-dumpxml 'a<b>c' default | head -n2
<volume>
<name>a<b>c</name>
Oops. That's not valid XML. And when we fix the XML
generation, it fails RelaxNG validation.
I'm also tired of seeing <key>(null)</key> in the example
output for volume xml; while we used NULLSTR() to avoid
a NULL deref rather than relying on glibc's printf
extension behavior, it's even better if we avoid the issue
in the first place. But this requires being careful that
we don't invalidate any storage backends that were relying
on key being unassigned during virStoragVolCreateXML[From].
I would have split this into two patches (one for escaping,
one for avoiding <key>(null)</key>), but since they both
end up touching a lot of the same test files, I ended up
merging it into one.
Note that this patch allows pretty much any volume name
that can appear in a directory (excluding . and .. because
those are special), but does nothing to change the current
(unenforced) RelaxNG claim that pool names will consist
only of letters, numbers, _, -, and +. Tightening the C
code to match RelaxNG patterns and/or relaxing the grammar
to match the C code for pool names is a task for another
day (but remember, we DID recently tighten C code for
domain names to exclude a leading '.').
* src/conf/storage_conf.c (virStoragePoolSourceFormat)
(virStoragePoolDefFormat, virStorageVolTargetDefFormat)
(virStorageVolDefFormat): Escape user-controlled strings.
(virStorageVolDefParseXML): Parse key, for use in unit tests.
* src/storage/storage_driver.c (storageVolCreateXML)
(storageVolCreateXMLFrom): Ensure parsed key doesn't confuse
volume creation.
* docs/schemas/basictypes.rng (volName): Relax definition.
* tests/storagepoolxml2xmltest.c (mymain): Test it.
* tests/storagevolxml2xmltest.c (mymain): Likewise.
* tests/storagepoolxml2xmlin/pool-dir-naming.xml: New file.
* tests/storagepoolxml2xmlout/pool-dir-naming.xml: Likewise.
* tests/storagevolxml2xmlin/vol-file-naming.xml: Likewise.
* tests/storagevolxml2xmlout/vol-file-naming.xml: Likewise.
* tests/storagevolxml2xmlout/vol-*.xml: Fix fallout.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-21 00:04:05 +00:00
|
|
|
/* 'Define' the new volume so we get async progress reporting.
|
|
|
|
* Wipe any key the user may have suggested, as volume creation
|
|
|
|
* will generate the canonical key. */
|
|
|
|
VIR_FREE(newvol->key);
|
2014-11-13 14:25:27 +00:00
|
|
|
if (backend->createVol(obj->conn, pool, newvol) < 0)
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
pool->volumes.objs[pool->volumes.count++] = newvol;
|
|
|
|
volobj = virGetStorageVol(obj->conn, pool->def->name, newvol->name,
|
2012-11-10 07:18:07 +00:00
|
|
|
newvol->key, NULL, NULL);
|
2014-02-12 11:05:51 +00:00
|
|
|
if (!volobj) {
|
|
|
|
pool->volumes.count--;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-05-19 13:37:51 +00:00
|
|
|
|
|
|
|
/* Drop the pool lock during volume allocation */
|
|
|
|
pool->asyncjobs++;
|
2014-07-17 16:41:21 +00:00
|
|
|
newvol->building = true;
|
2014-04-16 13:16:20 +00:00
|
|
|
origvol->in_use++;
|
2009-05-19 13:37:51 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
|
|
|
|
2009-09-02 13:02:06 +00:00
|
|
|
if (origpool) {
|
2009-05-19 13:37:51 +00:00
|
|
|
origpool->asyncjobs++;
|
|
|
|
virStoragePoolObjUnlock(origpool);
|
|
|
|
}
|
|
|
|
|
2010-01-20 23:41:52 +00:00
|
|
|
buildret = backend->buildVolFrom(obj->conn, pool, newvol, origvol, flags);
|
2009-05-19 13:37:51 +00:00
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2009-05-19 13:37:51 +00:00
|
|
|
virStoragePoolObjLock(pool);
|
2009-09-02 13:02:06 +00:00
|
|
|
if (origpool)
|
2009-05-19 13:37:51 +00:00
|
|
|
virStoragePoolObjLock(origpool);
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2009-05-19 13:37:51 +00:00
|
|
|
|
2014-04-16 13:16:20 +00:00
|
|
|
origvol->in_use--;
|
2014-07-17 16:41:21 +00:00
|
|
|
newvol->building = false;
|
conf: track sizes directly in source struct
One of the features of qcow2 is that a wrapper file can have
more capacity than its backing file from the guest's perspective;
what's more, sparse files make tracking allocation of both
the active and backing file worthwhile. As such, it makes
more sense to show allocation numbers for each file in a chain,
and not just the top-level file. This sets up the fields for
the tracking, although it does not modify XML to display any
new information.
* src/util/virstoragefile.h (_virStorageSource): Add fields.
* src/conf/storage_conf.h (_virStorageVolDef): Drop redundant
fields.
* src/storage/storage_backend.c (virStorageBackendCreateBlockFrom)
(createRawFile, virStorageBackendCreateQemuImgCmd)
(virStorageBackendCreateQcowCreate): Update clients.
* src/storage/storage_driver.c (storageVolDelete)
(storageVolCreateXML, storageVolCreateXMLFrom, storageVolResize)
(storageVolWipeInternal, storageVolGetInfo): Likewise.
* src/storage/storage_backend_fs.c (virStorageBackendProbeTarget)
(virStorageBackendFileSystemRefresh)
(virStorageBackendFileSystemVolResize)
(virStorageBackendFileSystemVolRefresh): Likewise.
* src/storage/storage_backend_logical.c
(virStorageBackendLogicalMakeVol)
(virStorageBackendLogicalCreateVol): Likewise.
* src/storage/storage_backend_scsi.c
(virStorageBackendSCSINewLun): Likewise.
* src/storage/storage_backend_mpath.c
(virStorageBackendMpathNewVol): Likewise.
* src/storage/storage_backend_rbd.c
(volStorageBackendRBDRefreshVolInfo)
(virStorageBackendRBDCreateImage): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol): Likewise.
* src/storage/storage_backend_sheepdog.c
(virStorageBackendSheepdogBuildVol)
(virStorageBackendSheepdogParseVdiList): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageBackendGlusterRefreshVol): Likewise.
* src/conf/storage_conf.c (virStorageVolDefFormat)
(virStorageVolDefParseXML): Likewise.
* src/test/test_driver.c (testOpenVolumesForPool)
(testStorageVolCreateXML, testStorageVolCreateXMLFrom)
(testStorageVolDelete, testStorageVolGetInfo): Likewise.
* src/esx/esx_storage_backend_iscsi.c (esxStorageVolGetXMLDesc):
Likewise.
* src/esx/esx_storage_backend_vmfs.c (esxStorageVolGetXMLDesc)
(esxStorageVolCreateXML): Likewise.
* src/parallels/parallels_driver.c (parallelsAddHddByVolume):
Likewise.
* src/parallels/parallels_storage.c (parallelsDiskDescParseNode)
(parallelsStorageVolDefineXML, parallelsStorageVolCreateXMLFrom)
(parallelsStorageVolDefRemove, parallelsStorageVolGetInfo):
Likewise.
* src/vbox/vbox_tmpl.c (vboxStorageVolCreateXML)
(vboxStorageVolGetXMLDesc): Likewise.
* tests/storagebackendsheepdogtest.c (test_vdi_list_parser):
Likewise.
* src/phyp/phyp_driver.c (phypStorageVolCreateXML): Likewise.
2014-04-01 23:43:36 +00:00
|
|
|
allocation = newvol->target.allocation;
|
2009-05-19 13:37:51 +00:00
|
|
|
pool->asyncjobs--;
|
|
|
|
|
2009-09-02 13:02:06 +00:00
|
|
|
if (origpool) {
|
2009-05-19 13:37:51 +00:00
|
|
|
origpool->asyncjobs--;
|
|
|
|
virStoragePoolObjUnlock(origpool);
|
|
|
|
origpool = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (buildret < 0) {
|
2014-04-08 22:54:14 +00:00
|
|
|
storageVolDeleteInternal(volobj, backend, pool, newvol, 0, false);
|
|
|
|
newvol = NULL;
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-04-08 22:54:14 +00:00
|
|
|
newvol = NULL;
|
2009-05-19 13:37:51 +00:00
|
|
|
|
2015-05-26 13:23:28 +00:00
|
|
|
/* Updating pool metadata ignoring the disk backend since
|
|
|
|
* it updates the pool values
|
|
|
|
*/
|
|
|
|
if (pool->def->type != VIR_STORAGE_POOL_DISK) {
|
|
|
|
pool->def->allocation += allocation;
|
|
|
|
pool->def->available -= allocation;
|
|
|
|
}
|
2013-08-16 12:08:07 +00:00
|
|
|
|
maint: omit translation for all VIR_INFO
We were 31/73 on whether to translate; since less than 50% translated
and since VIR_INFO is less than VIR_WARN which also doesn't translate,
this makes sense.
* cfg.mk (sc_prohibit_gettext_markup): Add VIR_INFO, since it
falls between WARN and DEBUG.
* daemon/libvirtd.c (qemudDispatchSignalEvent, remoteCheckAccess)
(qemudDispatchServer): Adjust offenders.
* daemon/remote.c (remoteDispatchAuthPolkit): Likewise.
* src/network/bridge_driver.c (networkReloadIptablesRules)
(networkStartNetworkDaemon, networkShutdownNetworkDaemon)
(networkCreate, networkDefine, networkUndefine): Likewise.
* src/qemu/qemu_driver.c (qemudDomainDefine)
(qemudDomainUndefine): Likewise.
* src/storage/storage_driver.c (storagePoolCreate)
(storagePoolDefine, storagePoolUndefine, storagePoolStart)
(storagePoolDestroy, storagePoolDelete, storageVolumeCreateXML)
(storageVolumeCreateXMLFrom, storageVolumeDelete): Likewise.
* src/util/bridge.c (brProbeVnetHdr): Likewise.
* po/POTFILES.in: Drop src/util/bridge.c.
2011-05-11 15:08:44 +00:00
|
|
|
VIR_INFO("Creating volume '%s' in storage pool '%s'",
|
2011-03-30 01:19:47 +00:00
|
|
|
volobj->name, pool->def->name);
|
2009-05-19 13:37:51 +00:00
|
|
|
ret = volobj;
|
|
|
|
volobj = NULL;
|
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
Convert public datatypes to inherit from virObject
This converts the following public API datatypes to use the
virObject infrastructure:
virConnectPtr
virDomainPtr
virDomainSnapshotPtr
virInterfacePtr
virNetworkPtr
virNodeDevicePtr
virNWFilterPtr
virSecretPtr
virStreamPtr
virStorageVolPtr
virStoragePoolPtr
The code is significantly simplified, since the mutex in the
virConnectPtr object now only needs to be held when accessing
the per-connection virError object instance. All other operations
are completely lock free.
* src/datatypes.c, src/datatypes.h, src/libvirt.c: Convert
public datatypes to use virObject
* src/conf/domain_event.c, src/phyp/phyp_driver.c,
src/qemu/qemu_command.c, src/qemu/qemu_migration.c,
src/qemu/qemu_process.c, src/storage/storage_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xend_internal.c,
tests/qemuxml2argvtest.c, tests/qemuxmlnstest.c,
tests/sexpr2xmltest.c, tests/xmconfigtest.c: Convert
to use virObjectUnref/virObjectRef
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-31 16:55:36 +00:00
|
|
|
virObjectUnref(volobj);
|
2009-05-19 13:37:51 +00:00
|
|
|
virStorageVolDefFree(newvol);
|
|
|
|
if (pool)
|
|
|
|
virStoragePoolObjUnlock(pool);
|
2009-09-02 13:02:06 +00:00
|
|
|
if (origpool)
|
2009-05-19 13:37:51 +00:00
|
|
|
virStoragePoolObjUnlock(origpool);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-02-23 03:13:18 +00:00
|
|
|
|
2009-07-14 15:24:42 +00:00
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
storageVolDownload(virStorageVolPtr obj,
|
|
|
|
virStreamPtr stream,
|
|
|
|
unsigned long long offset,
|
|
|
|
unsigned long long length,
|
|
|
|
unsigned int flags)
|
2009-07-14 15:24:42 +00:00
|
|
|
{
|
2014-07-07 14:50:11 +00:00
|
|
|
virStorageBackendPtr backend;
|
2009-07-14 15:24:42 +00:00
|
|
|
virStoragePoolObjPtr pool = NULL;
|
|
|
|
virStorageVolDefPtr vol = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2014-07-07 14:50:11 +00:00
|
|
|
if (!(vol = virStorageVolDefFromVol(obj, &pool, &backend)))
|
2014-06-05 11:29:37 +00:00
|
|
|
return -1;
|
2009-07-14 15:24:42 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStorageVolDownloadEnsureACL(obj->conn, pool->def, vol) < 0)
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2013-04-23 10:56:22 +00:00
|
|
|
|
2009-07-14 15:24:42 +00:00
|
|
|
if (vol->building) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still being allocated."),
|
|
|
|
vol->name);
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2009-07-14 15:24:42 +00:00
|
|
|
}
|
|
|
|
|
2014-07-07 14:50:11 +00:00
|
|
|
if (!backend->downloadVol) {
|
|
|
|
virReportError(VIR_ERR_NO_SUPPORT, "%s",
|
|
|
|
_("storage pool doesn't support volume download"));
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2014-07-07 14:50:11 +00:00
|
|
|
}
|
2009-07-14 15:24:42 +00:00
|
|
|
|
2014-07-07 14:50:11 +00:00
|
|
|
ret = backend->downloadVol(obj->conn, pool, vol, stream,
|
|
|
|
offset, length, flags);
|
2009-07-14 15:24:42 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-05 11:29:37 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2009-07-14 15:24:42 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-28 12:39:09 +00:00
|
|
|
/**
|
|
|
|
* Frees opaque data.
|
|
|
|
*
|
|
|
|
* @opaque Data to be freed.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
virStorageVolPoolRefreshDataFree(void *opaque)
|
|
|
|
{
|
|
|
|
virStorageVolStreamInfoPtr cbdata = opaque;
|
|
|
|
|
|
|
|
VIR_FREE(cbdata->pool_name);
|
|
|
|
VIR_FREE(cbdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Thread to handle the pool refresh
|
|
|
|
*
|
|
|
|
* @st Pointer to stream being closed.
|
|
|
|
* @opaque Domain's device information structure.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
virStorageVolPoolRefreshThread(void *opaque)
|
|
|
|
{
|
|
|
|
|
|
|
|
virStorageVolStreamInfoPtr cbdata = opaque;
|
|
|
|
virStoragePoolObjPtr pool = NULL;
|
|
|
|
virStorageBackendPtr backend;
|
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
|
|
|
if (!(pool = virStoragePoolObjFindByName(&driver->pools,
|
2014-07-28 12:39:09 +00:00
|
|
|
cbdata->pool_name)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(backend = virStorageBackendForType(pool->def->type)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
virStoragePoolObjClearVols(pool);
|
|
|
|
if (backend->refreshPool(NULL, pool) < 0)
|
|
|
|
VIR_DEBUG("Failed to refresh storage pool");
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (pool)
|
|
|
|
virStoragePoolObjUnlock(pool);
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2014-07-28 12:39:09 +00:00
|
|
|
virStorageVolPoolRefreshDataFree(cbdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Callback being called if a FDstream is closed. Will spin off a thread
|
|
|
|
* to perform a pool refresh.
|
|
|
|
*
|
|
|
|
* @st Pointer to stream being closed.
|
2014-11-24 06:13:20 +00:00
|
|
|
* @opaque Buffer to hold the pool name to be refreshed
|
2014-07-28 12:39:09 +00:00
|
|
|
*/
|
|
|
|
static void
|
|
|
|
virStorageVolFDStreamCloseCb(virStreamPtr st ATTRIBUTE_UNUSED,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
virThread thread;
|
|
|
|
|
|
|
|
if (virThreadCreate(&thread, false, virStorageVolPoolRefreshThread,
|
|
|
|
opaque) < 0) {
|
|
|
|
/* Not much else can be done */
|
|
|
|
VIR_ERROR(_("Failed to create thread to handle pool refresh"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
return; /* Thread will free opaque data */
|
|
|
|
|
|
|
|
error:
|
|
|
|
virStorageVolPoolRefreshDataFree(opaque);
|
|
|
|
}
|
|
|
|
|
2009-07-14 15:24:42 +00:00
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
storageVolUpload(virStorageVolPtr obj,
|
|
|
|
virStreamPtr stream,
|
|
|
|
unsigned long long offset,
|
|
|
|
unsigned long long length,
|
|
|
|
unsigned int flags)
|
2009-07-14 15:24:42 +00:00
|
|
|
{
|
2014-07-07 14:50:11 +00:00
|
|
|
virStorageBackendPtr backend;
|
2009-07-14 15:24:42 +00:00
|
|
|
virStoragePoolObjPtr pool = NULL;
|
|
|
|
virStorageVolDefPtr vol = NULL;
|
2014-07-28 12:39:09 +00:00
|
|
|
virStorageVolStreamInfoPtr cbdata = NULL;
|
2009-07-14 15:24:42 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2014-07-07 14:50:11 +00:00
|
|
|
if (!(vol = virStorageVolDefFromVol(obj, &pool, &backend)))
|
2014-06-05 11:29:37 +00:00
|
|
|
return -1;
|
2009-07-14 15:24:42 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStorageVolUploadEnsureACL(obj->conn, pool->def, vol) < 0)
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2013-04-23 10:56:22 +00:00
|
|
|
|
2014-04-16 13:16:20 +00:00
|
|
|
if (vol->in_use) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still in use."),
|
|
|
|
vol->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2009-07-14 15:24:42 +00:00
|
|
|
if (vol->building) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still being allocated."),
|
|
|
|
vol->name);
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2009-07-14 15:24:42 +00:00
|
|
|
}
|
|
|
|
|
2014-07-07 14:50:11 +00:00
|
|
|
if (!backend->uploadVol) {
|
|
|
|
virReportError(VIR_ERR_NO_SUPPORT, "%s",
|
|
|
|
_("storage pool doesn't support volume upload"));
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2014-03-03 15:11:28 +00:00
|
|
|
}
|
2009-07-14 15:24:42 +00:00
|
|
|
|
2014-07-28 12:39:09 +00:00
|
|
|
/* If we have a refreshPool, use the callback routine in order to
|
|
|
|
* refresh the pool after the volume upload stream closes. This way
|
|
|
|
* we make sure the volume and pool data are refreshed without user
|
|
|
|
* interaction and we can just lookup the backend in the callback
|
|
|
|
* routine in order to call the refresh API.
|
|
|
|
*/
|
|
|
|
if (backend->refreshPool) {
|
|
|
|
if (VIR_ALLOC(cbdata) < 0 ||
|
|
|
|
VIR_STRDUP(cbdata->pool_name, pool->def->name) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-12-03 15:01:32 +00:00
|
|
|
if ((ret = backend->uploadVol(obj->conn, pool, vol, stream,
|
|
|
|
offset, length, flags)) < 0)
|
|
|
|
goto cleanup;
|
2009-07-14 15:24:42 +00:00
|
|
|
|
2014-07-28 12:39:09 +00:00
|
|
|
/* Add cleanup callback - call after uploadVol since the stream
|
|
|
|
* is then fully set up
|
|
|
|
*/
|
|
|
|
if (cbdata) {
|
|
|
|
virFDStreamSetInternalCloseCb(stream,
|
|
|
|
virStorageVolFDStreamCloseCb,
|
|
|
|
cbdata, NULL);
|
|
|
|
cbdata = NULL;
|
|
|
|
}
|
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-05 11:29:37 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2014-07-28 12:39:09 +00:00
|
|
|
if (cbdata)
|
|
|
|
virStorageVolPoolRefreshDataFree(cbdata);
|
2009-07-14 15:24:42 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-01-30 07:40:00 +00:00
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
storageVolResize(virStorageVolPtr obj,
|
|
|
|
unsigned long long capacity,
|
|
|
|
unsigned int flags)
|
2012-01-30 07:40:00 +00:00
|
|
|
{
|
|
|
|
virStorageBackendPtr backend;
|
|
|
|
virStoragePoolObjPtr pool = NULL;
|
|
|
|
virStorageVolDefPtr vol = NULL;
|
2015-05-27 13:39:07 +00:00
|
|
|
unsigned long long abs_capacity, delta = 0;
|
2012-01-30 07:40:00 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
2013-05-31 05:16:14 +00:00
|
|
|
virCheckFlags(VIR_STORAGE_VOL_RESIZE_ALLOCATE |
|
2013-05-31 05:16:15 +00:00
|
|
|
VIR_STORAGE_VOL_RESIZE_DELTA |
|
|
|
|
VIR_STORAGE_VOL_RESIZE_SHRINK, -1);
|
2012-01-30 07:40:00 +00:00
|
|
|
|
2014-06-05 11:29:37 +00:00
|
|
|
if (!(vol = virStorageVolDefFromVol(obj, &pool, &backend)))
|
|
|
|
return -1;
|
2012-01-30 07:40:00 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStorageVolResizeEnsureACL(obj->conn, pool->def, vol) < 0)
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2013-04-23 10:56:22 +00:00
|
|
|
|
2014-04-16 13:16:20 +00:00
|
|
|
if (vol->in_use) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still in use."),
|
|
|
|
vol->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-01-30 07:40:00 +00:00
|
|
|
if (vol->building) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still being allocated."),
|
|
|
|
vol->name);
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2012-01-30 07:40:00 +00:00
|
|
|
}
|
2009-07-14 15:24:42 +00:00
|
|
|
|
2012-01-30 07:40:00 +00:00
|
|
|
if (flags & VIR_STORAGE_VOL_RESIZE_DELTA) {
|
2015-05-27 14:33:22 +00:00
|
|
|
if (flags & VIR_STORAGE_VOL_RESIZE_SHRINK)
|
|
|
|
abs_capacity = vol->target.capacity - MIN(capacity, vol->target.capacity);
|
|
|
|
else
|
|
|
|
abs_capacity = vol->target.capacity + capacity;
|
2012-01-30 07:40:00 +00:00
|
|
|
flags &= ~VIR_STORAGE_VOL_RESIZE_DELTA;
|
|
|
|
} else {
|
|
|
|
abs_capacity = capacity;
|
|
|
|
}
|
|
|
|
|
conf: track sizes directly in source struct
One of the features of qcow2 is that a wrapper file can have
more capacity than its backing file from the guest's perspective;
what's more, sparse files make tracking allocation of both
the active and backing file worthwhile. As such, it makes
more sense to show allocation numbers for each file in a chain,
and not just the top-level file. This sets up the fields for
the tracking, although it does not modify XML to display any
new information.
* src/util/virstoragefile.h (_virStorageSource): Add fields.
* src/conf/storage_conf.h (_virStorageVolDef): Drop redundant
fields.
* src/storage/storage_backend.c (virStorageBackendCreateBlockFrom)
(createRawFile, virStorageBackendCreateQemuImgCmd)
(virStorageBackendCreateQcowCreate): Update clients.
* src/storage/storage_driver.c (storageVolDelete)
(storageVolCreateXML, storageVolCreateXMLFrom, storageVolResize)
(storageVolWipeInternal, storageVolGetInfo): Likewise.
* src/storage/storage_backend_fs.c (virStorageBackendProbeTarget)
(virStorageBackendFileSystemRefresh)
(virStorageBackendFileSystemVolResize)
(virStorageBackendFileSystemVolRefresh): Likewise.
* src/storage/storage_backend_logical.c
(virStorageBackendLogicalMakeVol)
(virStorageBackendLogicalCreateVol): Likewise.
* src/storage/storage_backend_scsi.c
(virStorageBackendSCSINewLun): Likewise.
* src/storage/storage_backend_mpath.c
(virStorageBackendMpathNewVol): Likewise.
* src/storage/storage_backend_rbd.c
(volStorageBackendRBDRefreshVolInfo)
(virStorageBackendRBDCreateImage): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol): Likewise.
* src/storage/storage_backend_sheepdog.c
(virStorageBackendSheepdogBuildVol)
(virStorageBackendSheepdogParseVdiList): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageBackendGlusterRefreshVol): Likewise.
* src/conf/storage_conf.c (virStorageVolDefFormat)
(virStorageVolDefParseXML): Likewise.
* src/test/test_driver.c (testOpenVolumesForPool)
(testStorageVolCreateXML, testStorageVolCreateXMLFrom)
(testStorageVolDelete, testStorageVolGetInfo): Likewise.
* src/esx/esx_storage_backend_iscsi.c (esxStorageVolGetXMLDesc):
Likewise.
* src/esx/esx_storage_backend_vmfs.c (esxStorageVolGetXMLDesc)
(esxStorageVolCreateXML): Likewise.
* src/parallels/parallels_driver.c (parallelsAddHddByVolume):
Likewise.
* src/parallels/parallels_storage.c (parallelsDiskDescParseNode)
(parallelsStorageVolDefineXML, parallelsStorageVolCreateXMLFrom)
(parallelsStorageVolDefRemove, parallelsStorageVolGetInfo):
Likewise.
* src/vbox/vbox_tmpl.c (vboxStorageVolCreateXML)
(vboxStorageVolGetXMLDesc): Likewise.
* tests/storagebackendsheepdogtest.c (test_vdi_list_parser):
Likewise.
* src/phyp/phyp_driver.c (phypStorageVolCreateXML): Likewise.
2014-04-01 23:43:36 +00:00
|
|
|
if (abs_capacity < vol->target.allocation) {
|
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_INVALID_ARG, "%s",
|
2012-07-18 11:38:29 +00:00
|
|
|
_("can't shrink capacity below "
|
|
|
|
"existing allocation"));
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2012-01-30 07:40:00 +00:00
|
|
|
}
|
|
|
|
|
conf: track sizes directly in source struct
One of the features of qcow2 is that a wrapper file can have
more capacity than its backing file from the guest's perspective;
what's more, sparse files make tracking allocation of both
the active and backing file worthwhile. As such, it makes
more sense to show allocation numbers for each file in a chain,
and not just the top-level file. This sets up the fields for
the tracking, although it does not modify XML to display any
new information.
* src/util/virstoragefile.h (_virStorageSource): Add fields.
* src/conf/storage_conf.h (_virStorageVolDef): Drop redundant
fields.
* src/storage/storage_backend.c (virStorageBackendCreateBlockFrom)
(createRawFile, virStorageBackendCreateQemuImgCmd)
(virStorageBackendCreateQcowCreate): Update clients.
* src/storage/storage_driver.c (storageVolDelete)
(storageVolCreateXML, storageVolCreateXMLFrom, storageVolResize)
(storageVolWipeInternal, storageVolGetInfo): Likewise.
* src/storage/storage_backend_fs.c (virStorageBackendProbeTarget)
(virStorageBackendFileSystemRefresh)
(virStorageBackendFileSystemVolResize)
(virStorageBackendFileSystemVolRefresh): Likewise.
* src/storage/storage_backend_logical.c
(virStorageBackendLogicalMakeVol)
(virStorageBackendLogicalCreateVol): Likewise.
* src/storage/storage_backend_scsi.c
(virStorageBackendSCSINewLun): Likewise.
* src/storage/storage_backend_mpath.c
(virStorageBackendMpathNewVol): Likewise.
* src/storage/storage_backend_rbd.c
(volStorageBackendRBDRefreshVolInfo)
(virStorageBackendRBDCreateImage): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol): Likewise.
* src/storage/storage_backend_sheepdog.c
(virStorageBackendSheepdogBuildVol)
(virStorageBackendSheepdogParseVdiList): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageBackendGlusterRefreshVol): Likewise.
* src/conf/storage_conf.c (virStorageVolDefFormat)
(virStorageVolDefParseXML): Likewise.
* src/test/test_driver.c (testOpenVolumesForPool)
(testStorageVolCreateXML, testStorageVolCreateXMLFrom)
(testStorageVolDelete, testStorageVolGetInfo): Likewise.
* src/esx/esx_storage_backend_iscsi.c (esxStorageVolGetXMLDesc):
Likewise.
* src/esx/esx_storage_backend_vmfs.c (esxStorageVolGetXMLDesc)
(esxStorageVolCreateXML): Likewise.
* src/parallels/parallels_driver.c (parallelsAddHddByVolume):
Likewise.
* src/parallels/parallels_storage.c (parallelsDiskDescParseNode)
(parallelsStorageVolDefineXML, parallelsStorageVolCreateXMLFrom)
(parallelsStorageVolDefRemove, parallelsStorageVolGetInfo):
Likewise.
* src/vbox/vbox_tmpl.c (vboxStorageVolCreateXML)
(vboxStorageVolGetXMLDesc): Likewise.
* tests/storagebackendsheepdogtest.c (test_vdi_list_parser):
Likewise.
* src/phyp/phyp_driver.c (phypStorageVolCreateXML): Likewise.
2014-04-01 23:43:36 +00:00
|
|
|
if (abs_capacity < vol->target.capacity &&
|
2013-05-31 05:16:15 +00:00
|
|
|
!(flags & VIR_STORAGE_VOL_RESIZE_SHRINK)) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("Can't shrink capacity below current "
|
storage: Fix issues in storageVolResize
https://bugzilla.redhat.com/show_bug.cgi?id=1073305
When creating a volume in a pool, the creation allows the 'capacity'
value to be larger than the available space in the pool. As long as
the 'allocation' value will fit in the space, the volume will be created.
However, resizing the volume checks were made with the new absolute
capacity value against existing capacity + the available space without
regard for whether the new absolute capacity was actually allocating
space or not. For example, a pool with 75G of available space creates
a volume of 10G using a capacity of 100G and allocation of 10G will succeed;
however, if the allocation used a capacity of 10G instead and then tried
to resize the allocation to 100G the code would fail to allow the backend
to try the resize.
Furthermore, when updating the pool "available" and "allocation" values,
the resize code would just "blindly" adjust them regardless of whether
space was "allocated" or just "capacity" was being adjusted. This left
a scenario whereby a resize to 100G would fail; however, a resize to 50G
followed by one to 100G would both succeed. Again, neither was adjusting
the allocation value, just the "capacity" value.
This patch adds more logic to the resize code to understand whether the
new capacity value is actually "allocating" space as well and whether it
shrinking or expanding. Since unsigned arithmatic is involved, the possibility
that we adjust the pool size values incorrectly is probable.
This patch also ensures that updates to the pool values only occur if we
actually performed the allocation.
NB: The storageVolDelete, storageVolCreateXML, and storageVolCreateXMLFrom
each only updates the pool allocation/availability values by the target
volume allocation value.
2015-03-27 13:48:59 +00:00
|
|
|
"capacity unless shrink flag explicitly specified"));
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2013-05-31 05:16:15 +00:00
|
|
|
}
|
|
|
|
|
2015-05-27 13:39:07 +00:00
|
|
|
if (flags & VIR_STORAGE_VOL_RESIZE_ALLOCATE)
|
storage: Fix issues in storageVolResize
https://bugzilla.redhat.com/show_bug.cgi?id=1073305
When creating a volume in a pool, the creation allows the 'capacity'
value to be larger than the available space in the pool. As long as
the 'allocation' value will fit in the space, the volume will be created.
However, resizing the volume checks were made with the new absolute
capacity value against existing capacity + the available space without
regard for whether the new absolute capacity was actually allocating
space or not. For example, a pool with 75G of available space creates
a volume of 10G using a capacity of 100G and allocation of 10G will succeed;
however, if the allocation used a capacity of 10G instead and then tried
to resize the allocation to 100G the code would fail to allow the backend
to try the resize.
Furthermore, when updating the pool "available" and "allocation" values,
the resize code would just "blindly" adjust them regardless of whether
space was "allocated" or just "capacity" was being adjusted. This left
a scenario whereby a resize to 100G would fail; however, a resize to 50G
followed by one to 100G would both succeed. Again, neither was adjusting
the allocation value, just the "capacity" value.
This patch adds more logic to the resize code to understand whether the
new capacity value is actually "allocating" space as well and whether it
shrinking or expanding. Since unsigned arithmatic is involved, the possibility
that we adjust the pool size values incorrectly is probable.
This patch also ensures that updates to the pool values only occur if we
actually performed the allocation.
NB: The storageVolDelete, storageVolCreateXML, and storageVolCreateXMLFrom
each only updates the pool allocation/availability values by the target
volume allocation value.
2015-03-27 13:48:59 +00:00
|
|
|
delta = abs_capacity - vol->target.allocation;
|
|
|
|
|
2015-05-27 13:39:07 +00:00
|
|
|
if (delta > pool->def->available) {
|
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_FAILED, "%s",
|
storage: Fix issues in storageVolResize
https://bugzilla.redhat.com/show_bug.cgi?id=1073305
When creating a volume in a pool, the creation allows the 'capacity'
value to be larger than the available space in the pool. As long as
the 'allocation' value will fit in the space, the volume will be created.
However, resizing the volume checks were made with the new absolute
capacity value against existing capacity + the available space without
regard for whether the new absolute capacity was actually allocating
space or not. For example, a pool with 75G of available space creates
a volume of 10G using a capacity of 100G and allocation of 10G will succeed;
however, if the allocation used a capacity of 10G instead and then tried
to resize the allocation to 100G the code would fail to allow the backend
to try the resize.
Furthermore, when updating the pool "available" and "allocation" values,
the resize code would just "blindly" adjust them regardless of whether
space was "allocated" or just "capacity" was being adjusted. This left
a scenario whereby a resize to 100G would fail; however, a resize to 50G
followed by one to 100G would both succeed. Again, neither was adjusting
the allocation value, just the "capacity" value.
This patch adds more logic to the resize code to understand whether the
new capacity value is actually "allocating" space as well and whether it
shrinking or expanding. Since unsigned arithmatic is involved, the possibility
that we adjust the pool size values incorrectly is probable.
This patch also ensures that updates to the pool values only occur if we
actually performed the allocation.
NB: The storageVolDelete, storageVolCreateXML, and storageVolCreateXMLFrom
each only updates the pool allocation/availability values by the target
volume allocation value.
2015-03-27 13:48:59 +00:00
|
|
|
_("Not enough space left in storage pool"));
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2012-01-30 07:40:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!backend->resizeVol) {
|
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_NO_SUPPORT, "%s",
|
2012-07-18 11:38:29 +00:00
|
|
|
_("storage pool does not support changing of "
|
|
|
|
"volume capacity"));
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2012-01-30 07:40:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (backend->resizeVol(obj->conn, pool, vol, abs_capacity, flags) < 0)
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2012-01-30 07:40:00 +00:00
|
|
|
|
conf: track sizes directly in source struct
One of the features of qcow2 is that a wrapper file can have
more capacity than its backing file from the guest's perspective;
what's more, sparse files make tracking allocation of both
the active and backing file worthwhile. As such, it makes
more sense to show allocation numbers for each file in a chain,
and not just the top-level file. This sets up the fields for
the tracking, although it does not modify XML to display any
new information.
* src/util/virstoragefile.h (_virStorageSource): Add fields.
* src/conf/storage_conf.h (_virStorageVolDef): Drop redundant
fields.
* src/storage/storage_backend.c (virStorageBackendCreateBlockFrom)
(createRawFile, virStorageBackendCreateQemuImgCmd)
(virStorageBackendCreateQcowCreate): Update clients.
* src/storage/storage_driver.c (storageVolDelete)
(storageVolCreateXML, storageVolCreateXMLFrom, storageVolResize)
(storageVolWipeInternal, storageVolGetInfo): Likewise.
* src/storage/storage_backend_fs.c (virStorageBackendProbeTarget)
(virStorageBackendFileSystemRefresh)
(virStorageBackendFileSystemVolResize)
(virStorageBackendFileSystemVolRefresh): Likewise.
* src/storage/storage_backend_logical.c
(virStorageBackendLogicalMakeVol)
(virStorageBackendLogicalCreateVol): Likewise.
* src/storage/storage_backend_scsi.c
(virStorageBackendSCSINewLun): Likewise.
* src/storage/storage_backend_mpath.c
(virStorageBackendMpathNewVol): Likewise.
* src/storage/storage_backend_rbd.c
(volStorageBackendRBDRefreshVolInfo)
(virStorageBackendRBDCreateImage): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol): Likewise.
* src/storage/storage_backend_sheepdog.c
(virStorageBackendSheepdogBuildVol)
(virStorageBackendSheepdogParseVdiList): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageBackendGlusterRefreshVol): Likewise.
* src/conf/storage_conf.c (virStorageVolDefFormat)
(virStorageVolDefParseXML): Likewise.
* src/test/test_driver.c (testOpenVolumesForPool)
(testStorageVolCreateXML, testStorageVolCreateXMLFrom)
(testStorageVolDelete, testStorageVolGetInfo): Likewise.
* src/esx/esx_storage_backend_iscsi.c (esxStorageVolGetXMLDesc):
Likewise.
* src/esx/esx_storage_backend_vmfs.c (esxStorageVolGetXMLDesc)
(esxStorageVolCreateXML): Likewise.
* src/parallels/parallels_driver.c (parallelsAddHddByVolume):
Likewise.
* src/parallels/parallels_storage.c (parallelsDiskDescParseNode)
(parallelsStorageVolDefineXML, parallelsStorageVolCreateXMLFrom)
(parallelsStorageVolDefRemove, parallelsStorageVolGetInfo):
Likewise.
* src/vbox/vbox_tmpl.c (vboxStorageVolCreateXML)
(vboxStorageVolGetXMLDesc): Likewise.
* tests/storagebackendsheepdogtest.c (test_vdi_list_parser):
Likewise.
* src/phyp/phyp_driver.c (phypStorageVolCreateXML): Likewise.
2014-04-01 23:43:36 +00:00
|
|
|
vol->target.capacity = abs_capacity;
|
storage: Fix issues in storageVolResize
https://bugzilla.redhat.com/show_bug.cgi?id=1073305
When creating a volume in a pool, the creation allows the 'capacity'
value to be larger than the available space in the pool. As long as
the 'allocation' value will fit in the space, the volume will be created.
However, resizing the volume checks were made with the new absolute
capacity value against existing capacity + the available space without
regard for whether the new absolute capacity was actually allocating
space or not. For example, a pool with 75G of available space creates
a volume of 10G using a capacity of 100G and allocation of 10G will succeed;
however, if the allocation used a capacity of 10G instead and then tried
to resize the allocation to 100G the code would fail to allow the backend
to try the resize.
Furthermore, when updating the pool "available" and "allocation" values,
the resize code would just "blindly" adjust them regardless of whether
space was "allocated" or just "capacity" was being adjusted. This left
a scenario whereby a resize to 100G would fail; however, a resize to 50G
followed by one to 100G would both succeed. Again, neither was adjusting
the allocation value, just the "capacity" value.
This patch adds more logic to the resize code to understand whether the
new capacity value is actually "allocating" space as well and whether it
shrinking or expanding. Since unsigned arithmatic is involved, the possibility
that we adjust the pool size values incorrectly is probable.
This patch also ensures that updates to the pool values only occur if we
actually performed the allocation.
NB: The storageVolDelete, storageVolCreateXML, and storageVolCreateXMLFrom
each only updates the pool allocation/availability values by the target
volume allocation value.
2015-03-27 13:48:59 +00:00
|
|
|
/* Only update the allocation and pool values if we actually did the
|
|
|
|
* allocation; otherwise, this is akin to a create operation with a
|
|
|
|
* capacity value different and potentially much larger than available
|
|
|
|
*/
|
|
|
|
if (flags & VIR_STORAGE_VOL_RESIZE_ALLOCATE) {
|
conf: track sizes directly in source struct
One of the features of qcow2 is that a wrapper file can have
more capacity than its backing file from the guest's perspective;
what's more, sparse files make tracking allocation of both
the active and backing file worthwhile. As such, it makes
more sense to show allocation numbers for each file in a chain,
and not just the top-level file. This sets up the fields for
the tracking, although it does not modify XML to display any
new information.
* src/util/virstoragefile.h (_virStorageSource): Add fields.
* src/conf/storage_conf.h (_virStorageVolDef): Drop redundant
fields.
* src/storage/storage_backend.c (virStorageBackendCreateBlockFrom)
(createRawFile, virStorageBackendCreateQemuImgCmd)
(virStorageBackendCreateQcowCreate): Update clients.
* src/storage/storage_driver.c (storageVolDelete)
(storageVolCreateXML, storageVolCreateXMLFrom, storageVolResize)
(storageVolWipeInternal, storageVolGetInfo): Likewise.
* src/storage/storage_backend_fs.c (virStorageBackendProbeTarget)
(virStorageBackendFileSystemRefresh)
(virStorageBackendFileSystemVolResize)
(virStorageBackendFileSystemVolRefresh): Likewise.
* src/storage/storage_backend_logical.c
(virStorageBackendLogicalMakeVol)
(virStorageBackendLogicalCreateVol): Likewise.
* src/storage/storage_backend_scsi.c
(virStorageBackendSCSINewLun): Likewise.
* src/storage/storage_backend_mpath.c
(virStorageBackendMpathNewVol): Likewise.
* src/storage/storage_backend_rbd.c
(volStorageBackendRBDRefreshVolInfo)
(virStorageBackendRBDCreateImage): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol): Likewise.
* src/storage/storage_backend_sheepdog.c
(virStorageBackendSheepdogBuildVol)
(virStorageBackendSheepdogParseVdiList): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageBackendGlusterRefreshVol): Likewise.
* src/conf/storage_conf.c (virStorageVolDefFormat)
(virStorageVolDefParseXML): Likewise.
* src/test/test_driver.c (testOpenVolumesForPool)
(testStorageVolCreateXML, testStorageVolCreateXMLFrom)
(testStorageVolDelete, testStorageVolGetInfo): Likewise.
* src/esx/esx_storage_backend_iscsi.c (esxStorageVolGetXMLDesc):
Likewise.
* src/esx/esx_storage_backend_vmfs.c (esxStorageVolGetXMLDesc)
(esxStorageVolCreateXML): Likewise.
* src/parallels/parallels_driver.c (parallelsAddHddByVolume):
Likewise.
* src/parallels/parallels_storage.c (parallelsDiskDescParseNode)
(parallelsStorageVolDefineXML, parallelsStorageVolCreateXMLFrom)
(parallelsStorageVolDefRemove, parallelsStorageVolGetInfo):
Likewise.
* src/vbox/vbox_tmpl.c (vboxStorageVolCreateXML)
(vboxStorageVolGetXMLDesc): Likewise.
* tests/storagebackendsheepdogtest.c (test_vdi_list_parser):
Likewise.
* src/phyp/phyp_driver.c (phypStorageVolCreateXML): Likewise.
2014-04-01 23:43:36 +00:00
|
|
|
vol->target.allocation = abs_capacity;
|
2015-05-27 13:39:07 +00:00
|
|
|
pool->def->allocation += delta;
|
|
|
|
pool->def->available -= delta;
|
storage: Fix issues in storageVolResize
https://bugzilla.redhat.com/show_bug.cgi?id=1073305
When creating a volume in a pool, the creation allows the 'capacity'
value to be larger than the available space in the pool. As long as
the 'allocation' value will fit in the space, the volume will be created.
However, resizing the volume checks were made with the new absolute
capacity value against existing capacity + the available space without
regard for whether the new absolute capacity was actually allocating
space or not. For example, a pool with 75G of available space creates
a volume of 10G using a capacity of 100G and allocation of 10G will succeed;
however, if the allocation used a capacity of 10G instead and then tried
to resize the allocation to 100G the code would fail to allow the backend
to try the resize.
Furthermore, when updating the pool "available" and "allocation" values,
the resize code would just "blindly" adjust them regardless of whether
space was "allocated" or just "capacity" was being adjusted. This left
a scenario whereby a resize to 100G would fail; however, a resize to 50G
followed by one to 100G would both succeed. Again, neither was adjusting
the allocation value, just the "capacity" value.
This patch adds more logic to the resize code to understand whether the
new capacity value is actually "allocating" space as well and whether it
shrinking or expanding. Since unsigned arithmatic is involved, the possibility
that we adjust the pool size values incorrectly is probable.
This patch also ensures that updates to the pool values only occur if we
actually performed the allocation.
NB: The storageVolDelete, storageVolCreateXML, and storageVolCreateXMLFrom
each only updates the pool allocation/availability values by the target
volume allocation value.
2015-03-27 13:48:59 +00:00
|
|
|
}
|
2013-08-16 12:08:07 +00:00
|
|
|
|
2013-04-13 07:22:01 +00:00
|
|
|
ret = 0;
|
2012-01-30 07:40:00 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-05 11:29:37 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2012-01-30 07:40:00 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2009-07-14 15:24:42 +00:00
|
|
|
|
2010-02-23 03:13:18 +00:00
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
storageVolWipePattern(virStorageVolPtr obj,
|
|
|
|
unsigned int algorithm,
|
|
|
|
unsigned int flags)
|
2010-02-23 03:13:18 +00:00
|
|
|
{
|
2014-07-07 14:50:11 +00:00
|
|
|
virStorageBackendPtr backend;
|
2010-02-23 03:13:18 +00:00
|
|
|
virStoragePoolObjPtr pool = NULL;
|
|
|
|
virStorageVolDefPtr vol = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
2010-04-16 12:04:31 +00:00
|
|
|
virCheckFlags(0, -1);
|
2010-02-23 03:13:18 +00:00
|
|
|
|
2012-01-09 16:05:03 +00:00
|
|
|
if (algorithm >= VIR_STORAGE_VOL_WIPE_ALG_LAST) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("wiping algorithm %d not supported"),
|
|
|
|
algorithm);
|
2012-01-09 16:05:03 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-07-07 14:50:11 +00:00
|
|
|
if (!(vol = virStorageVolDefFromVol(obj, &pool, &backend)))
|
2014-06-05 11:29:37 +00:00
|
|
|
return -1;
|
2010-02-23 03:13:18 +00:00
|
|
|
|
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStorageVolWipePatternEnsureACL(obj->conn, pool->def, vol) < 0)
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2013-04-23 10:56:22 +00:00
|
|
|
|
2014-04-16 13:16:20 +00:00
|
|
|
if (vol->in_use) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still in use."),
|
|
|
|
vol->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2010-02-23 03:13:18 +00:00
|
|
|
if (vol->building) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still being allocated."),
|
|
|
|
vol->name);
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2010-02-23 03:13:18 +00:00
|
|
|
}
|
|
|
|
|
2014-07-07 14:50:11 +00:00
|
|
|
if (!backend->wipeVol) {
|
|
|
|
virReportError(VIR_ERR_NO_SUPPORT, "%s",
|
|
|
|
_("storage pool doesn't support volume wiping"));
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2014-07-07 14:50:11 +00:00
|
|
|
}
|
2010-02-23 03:13:18 +00:00
|
|
|
|
2014-07-07 14:50:11 +00:00
|
|
|
ret = backend->wipeVol(obj->conn, pool, vol, algorithm, flags);
|
2010-02-23 03:13:18 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-05 11:29:37 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2010-02-23 03:13:18 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-01-09 16:05:03 +00:00
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
storageVolWipe(virStorageVolPtr obj,
|
|
|
|
unsigned int flags)
|
2012-01-09 16:05:03 +00:00
|
|
|
{
|
2013-04-23 12:50:18 +00:00
|
|
|
return storageVolWipePattern(obj, VIR_STORAGE_VOL_WIPE_ALG_ZERO, flags);
|
2012-01-09 16:05:03 +00:00
|
|
|
}
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
storageVolGetInfo(virStorageVolPtr obj,
|
2014-03-18 08:15:36 +00:00
|
|
|
virStorageVolInfoPtr info)
|
|
|
|
{
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageBackendPtr backend;
|
|
|
|
virStorageVolDefPtr vol;
|
2008-12-04 21:39:45 +00:00
|
|
|
int ret = -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-06-05 11:29:37 +00:00
|
|
|
if (!(vol = virStorageVolDefFromVol(obj, &pool, &backend)))
|
|
|
|
return -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStorageVolGetInfoEnsureACL(obj->conn, pool->def, vol) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
if (backend->refreshVol &&
|
|
|
|
backend->refreshVol(obj->conn, pool, vol) < 0)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
|
|
|
memset(info, 0, sizeof(*info));
|
2008-11-17 11:19:33 +00:00
|
|
|
info->type = vol->type;
|
conf: track sizes directly in source struct
One of the features of qcow2 is that a wrapper file can have
more capacity than its backing file from the guest's perspective;
what's more, sparse files make tracking allocation of both
the active and backing file worthwhile. As such, it makes
more sense to show allocation numbers for each file in a chain,
and not just the top-level file. This sets up the fields for
the tracking, although it does not modify XML to display any
new information.
* src/util/virstoragefile.h (_virStorageSource): Add fields.
* src/conf/storage_conf.h (_virStorageVolDef): Drop redundant
fields.
* src/storage/storage_backend.c (virStorageBackendCreateBlockFrom)
(createRawFile, virStorageBackendCreateQemuImgCmd)
(virStorageBackendCreateQcowCreate): Update clients.
* src/storage/storage_driver.c (storageVolDelete)
(storageVolCreateXML, storageVolCreateXMLFrom, storageVolResize)
(storageVolWipeInternal, storageVolGetInfo): Likewise.
* src/storage/storage_backend_fs.c (virStorageBackendProbeTarget)
(virStorageBackendFileSystemRefresh)
(virStorageBackendFileSystemVolResize)
(virStorageBackendFileSystemVolRefresh): Likewise.
* src/storage/storage_backend_logical.c
(virStorageBackendLogicalMakeVol)
(virStorageBackendLogicalCreateVol): Likewise.
* src/storage/storage_backend_scsi.c
(virStorageBackendSCSINewLun): Likewise.
* src/storage/storage_backend_mpath.c
(virStorageBackendMpathNewVol): Likewise.
* src/storage/storage_backend_rbd.c
(volStorageBackendRBDRefreshVolInfo)
(virStorageBackendRBDCreateImage): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol): Likewise.
* src/storage/storage_backend_sheepdog.c
(virStorageBackendSheepdogBuildVol)
(virStorageBackendSheepdogParseVdiList): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageBackendGlusterRefreshVol): Likewise.
* src/conf/storage_conf.c (virStorageVolDefFormat)
(virStorageVolDefParseXML): Likewise.
* src/test/test_driver.c (testOpenVolumesForPool)
(testStorageVolCreateXML, testStorageVolCreateXMLFrom)
(testStorageVolDelete, testStorageVolGetInfo): Likewise.
* src/esx/esx_storage_backend_iscsi.c (esxStorageVolGetXMLDesc):
Likewise.
* src/esx/esx_storage_backend_vmfs.c (esxStorageVolGetXMLDesc)
(esxStorageVolCreateXML): Likewise.
* src/parallels/parallels_driver.c (parallelsAddHddByVolume):
Likewise.
* src/parallels/parallels_storage.c (parallelsDiskDescParseNode)
(parallelsStorageVolDefineXML, parallelsStorageVolCreateXMLFrom)
(parallelsStorageVolDefRemove, parallelsStorageVolGetInfo):
Likewise.
* src/vbox/vbox_tmpl.c (vboxStorageVolCreateXML)
(vboxStorageVolGetXMLDesc): Likewise.
* tests/storagebackendsheepdogtest.c (test_vdi_list_parser):
Likewise.
* src/phyp/phyp_driver.c (phypStorageVolCreateXML): Likewise.
2014-04-01 23:43:36 +00:00
|
|
|
info->capacity = vol->target.capacity;
|
|
|
|
info->allocation = vol->target.allocation;
|
2008-12-04 21:39:45 +00:00
|
|
|
ret = 0;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-05 11:29:37 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
2013-04-23 12:50:18 +00:00
|
|
|
storageVolGetXMLDesc(virStorageVolPtr obj,
|
|
|
|
unsigned int flags)
|
2011-07-06 22:51:23 +00:00
|
|
|
{
|
2008-12-04 21:39:45 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageBackendPtr backend;
|
|
|
|
virStorageVolDefPtr vol;
|
2008-12-04 21:39:45 +00:00
|
|
|
char *ret = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2011-07-06 22:51:23 +00:00
|
|
|
virCheckFlags(0, NULL);
|
|
|
|
|
2014-06-05 11:29:37 +00:00
|
|
|
if (!(vol = virStorageVolDefFromVol(obj, &pool, &backend)))
|
|
|
|
return NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStorageVolGetXMLDescEnsureACL(obj->conn, pool->def, vol) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2009-04-03 14:15:30 +00:00
|
|
|
if (backend->refreshVol &&
|
|
|
|
backend->refreshVol(obj->conn, pool, vol) < 0)
|
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2010-02-10 11:42:56 +00:00
|
|
|
ret = virStorageVolDefFormat(pool->def, vol);
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-05 11:29:37 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2008-12-04 21:40:42 +00:00
|
|
|
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
2014-03-18 08:15:36 +00:00
|
|
|
storageVolGetPath(virStorageVolPtr obj)
|
|
|
|
{
|
2008-12-04 21:40:42 +00:00
|
|
|
virStoragePoolObjPtr pool;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageVolDefPtr vol;
|
2008-12-04 21:39:45 +00:00
|
|
|
char *ret = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-06-05 11:29:37 +00:00
|
|
|
if (!(vol = virStorageVolDefFromVol(obj, &pool, NULL)))
|
|
|
|
return NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virStorageVolGetPathEnsureACL(obj->conn, pool->def, vol) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-05-03 12:49:08 +00:00
|
|
|
ignore_value(VIR_STRDUP(ret, vol->target.path));
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2014-06-05 11:29:37 +00:00
|
|
|
virStoragePoolObjUnlock(pool);
|
2008-02-20 15:34:52 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-09-04 15:16:27 +00:00
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
storageConnectListAllStoragePools(virConnectPtr conn,
|
|
|
|
virStoragePoolPtr **pools,
|
|
|
|
unsigned int flags)
|
2012-09-04 15:16:27 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);
|
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virConnectListAllStoragePoolsEnsureACL(conn) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverLock();
|
2013-06-26 17:47:48 +00:00
|
|
|
ret = virStoragePoolObjListExport(conn, driver->pools, pools,
|
2014-11-19 08:48:09 +00:00
|
|
|
virConnectListAllStoragePoolsCheckACL,
|
|
|
|
flags);
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2012-09-04 15:16:27 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2012-09-04 15:16:27 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-02-03 15:12:57 +00:00
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
static virStorageDriver storageDriver = {
|
2008-09-22 19:53:42 +00:00
|
|
|
.name = "storage",
|
2013-04-23 12:50:18 +00:00
|
|
|
.connectNumOfStoragePools = storageConnectNumOfStoragePools, /* 0.4.0 */
|
|
|
|
.connectListStoragePools = storageConnectListStoragePools, /* 0.4.0 */
|
|
|
|
.connectNumOfDefinedStoragePools = storageConnectNumOfDefinedStoragePools, /* 0.4.0 */
|
|
|
|
.connectListDefinedStoragePools = storageConnectListDefinedStoragePools, /* 0.4.0 */
|
|
|
|
.connectListAllStoragePools = storageConnectListAllStoragePools, /* 0.10.2 */
|
|
|
|
.connectFindStoragePoolSources = storageConnectFindStoragePoolSources, /* 0.4.0 */
|
2013-04-22 17:26:01 +00:00
|
|
|
.storagePoolLookupByName = storagePoolLookupByName, /* 0.4.0 */
|
|
|
|
.storagePoolLookupByUUID = storagePoolLookupByUUID, /* 0.4.0 */
|
|
|
|
.storagePoolLookupByVolume = storagePoolLookupByVolume, /* 0.4.0 */
|
2013-04-23 12:50:18 +00:00
|
|
|
.storagePoolCreateXML = storagePoolCreateXML, /* 0.4.0 */
|
|
|
|
.storagePoolDefineXML = storagePoolDefineXML, /* 0.4.0 */
|
2013-04-22 17:26:01 +00:00
|
|
|
.storagePoolBuild = storagePoolBuild, /* 0.4.0 */
|
|
|
|
.storagePoolUndefine = storagePoolUndefine, /* 0.4.0 */
|
2013-04-23 12:50:18 +00:00
|
|
|
.storagePoolCreate = storagePoolCreate, /* 0.4.0 */
|
2013-04-22 17:26:01 +00:00
|
|
|
.storagePoolDestroy = storagePoolDestroy, /* 0.4.0 */
|
|
|
|
.storagePoolDelete = storagePoolDelete, /* 0.4.0 */
|
|
|
|
.storagePoolRefresh = storagePoolRefresh, /* 0.4.0 */
|
|
|
|
.storagePoolGetInfo = storagePoolGetInfo, /* 0.4.0 */
|
|
|
|
.storagePoolGetXMLDesc = storagePoolGetXMLDesc, /* 0.4.0 */
|
|
|
|
.storagePoolGetAutostart = storagePoolGetAutostart, /* 0.4.0 */
|
|
|
|
.storagePoolSetAutostart = storagePoolSetAutostart, /* 0.4.0 */
|
2013-04-23 12:50:18 +00:00
|
|
|
.storagePoolNumOfVolumes = storagePoolNumOfVolumes, /* 0.4.0 */
|
2013-04-22 17:26:01 +00:00
|
|
|
.storagePoolListVolumes = storagePoolListVolumes, /* 0.4.0 */
|
|
|
|
.storagePoolListAllVolumes = storagePoolListAllVolumes, /* 0.10.2 */
|
|
|
|
|
2013-04-23 12:50:18 +00:00
|
|
|
.storageVolLookupByName = storageVolLookupByName, /* 0.4.0 */
|
|
|
|
.storageVolLookupByKey = storageVolLookupByKey, /* 0.4.0 */
|
|
|
|
.storageVolLookupByPath = storageVolLookupByPath, /* 0.4.0 */
|
|
|
|
.storageVolCreateXML = storageVolCreateXML, /* 0.4.0 */
|
|
|
|
.storageVolCreateXMLFrom = storageVolCreateXMLFrom, /* 0.6.4 */
|
|
|
|
.storageVolDownload = storageVolDownload, /* 0.9.0 */
|
|
|
|
.storageVolUpload = storageVolUpload, /* 0.9.0 */
|
|
|
|
.storageVolDelete = storageVolDelete, /* 0.4.0 */
|
|
|
|
.storageVolWipe = storageVolWipe, /* 0.8.0 */
|
|
|
|
.storageVolWipePattern = storageVolWipePattern, /* 0.9.10 */
|
|
|
|
.storageVolGetInfo = storageVolGetInfo, /* 0.4.0 */
|
|
|
|
.storageVolGetXMLDesc = storageVolGetXMLDesc, /* 0.4.0 */
|
|
|
|
.storageVolGetPath = storageVolGetPath, /* 0.4.0 */
|
|
|
|
.storageVolResize = storageVolResize, /* 0.9.10 */
|
2013-04-22 17:26:01 +00:00
|
|
|
|
|
|
|
.storagePoolIsActive = storagePoolIsActive, /* 0.7.3 */
|
|
|
|
.storagePoolIsPersistent = storagePoolIsPersistent, /* 0.7.3 */
|
2008-02-20 15:34:52 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static virStateDriver stateDriver = {
|
2015-01-20 16:16:26 +00:00
|
|
|
.name = "storage",
|
2013-04-23 12:50:18 +00:00
|
|
|
.stateInitialize = storageStateInitialize,
|
2013-07-25 12:03:38 +00:00
|
|
|
.stateAutoStart = storageStateAutoStart,
|
2013-04-23 12:50:18 +00:00
|
|
|
.stateCleanup = storageStateCleanup,
|
|
|
|
.stateReload = storageStateReload,
|
2008-02-20 15:34:52 +00:00
|
|
|
};
|
|
|
|
|
2013-12-02 20:31:42 +00:00
|
|
|
int storageRegister(void)
|
|
|
|
{
|
2015-01-20 16:16:26 +00:00
|
|
|
if (virSetSharedStorageDriver(&storageDriver) < 0)
|
2013-12-02 20:31:42 +00:00
|
|
|
return -1;
|
2014-03-17 13:35:42 +00:00
|
|
|
if (virRegisterStateDriver(&stateDriver) < 0)
|
|
|
|
return -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2014-02-03 15:12:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* ----------- file handlers cooperating with storage driver --------------- */
|
2014-04-08 10:07:24 +00:00
|
|
|
static bool
|
|
|
|
virStorageFileIsInitialized(virStorageSourcePtr src)
|
|
|
|
{
|
2014-06-30 14:24:33 +00:00
|
|
|
return src && src->drv;
|
2014-04-08 10:07:24 +00:00
|
|
|
}
|
|
|
|
|
2014-04-24 14:59:56 +00:00
|
|
|
|
|
|
|
static bool
|
|
|
|
virStorageFileSupportsBackingChainTraversal(virStorageSourcePtr src)
|
|
|
|
{
|
2014-08-27 11:56:00 +00:00
|
|
|
int actualType;
|
2014-04-24 14:59:56 +00:00
|
|
|
virStorageFileBackendPtr backend;
|
|
|
|
|
|
|
|
if (!src)
|
|
|
|
return false;
|
2014-08-27 11:56:00 +00:00
|
|
|
actualType = virStorageSourceGetActualType(src);
|
2014-04-24 14:59:56 +00:00
|
|
|
|
|
|
|
if (src->drv) {
|
|
|
|
backend = src->drv->backend;
|
|
|
|
} else {
|
|
|
|
if (!(backend = virStorageFileBackendForTypeInternal(actualType,
|
|
|
|
src->protocol,
|
|
|
|
false)))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return backend->storageFileGetUniqueIdentifier &&
|
|
|
|
backend->storageFileReadHeader &&
|
|
|
|
backend->storageFileAccess;
|
|
|
|
}
|
|
|
|
|
2014-07-09 14:52:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileSupportsSecurityDriver:
|
|
|
|
*
|
|
|
|
* @src: a storage file structure
|
|
|
|
*
|
|
|
|
* Check if a storage file supports operations needed by the security
|
|
|
|
* driver to perform labelling
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
virStorageFileSupportsSecurityDriver(virStorageSourcePtr src)
|
|
|
|
{
|
2014-08-27 11:56:00 +00:00
|
|
|
int actualType;
|
2014-07-09 14:52:06 +00:00
|
|
|
virStorageFileBackendPtr backend;
|
|
|
|
|
|
|
|
if (!src)
|
|
|
|
return false;
|
2014-08-27 11:56:00 +00:00
|
|
|
actualType = virStorageSourceGetActualType(src);
|
2014-07-09 14:52:06 +00:00
|
|
|
|
|
|
|
if (src->drv) {
|
|
|
|
backend = src->drv->backend;
|
|
|
|
} else {
|
|
|
|
if (!(backend = virStorageFileBackendForTypeInternal(actualType,
|
|
|
|
src->protocol,
|
|
|
|
false)))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return !!backend->storageFileChown;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-02-03 15:12:57 +00:00
|
|
|
void
|
2014-04-08 10:07:24 +00:00
|
|
|
virStorageFileDeinit(virStorageSourcePtr src)
|
2014-02-03 15:12:57 +00:00
|
|
|
{
|
2014-04-08 10:07:24 +00:00
|
|
|
if (!virStorageFileIsInitialized(src))
|
2014-02-03 15:12:57 +00:00
|
|
|
return;
|
|
|
|
|
2014-04-08 10:07:24 +00:00
|
|
|
if (src->drv->backend &&
|
|
|
|
src->drv->backend->backendDeinit)
|
|
|
|
src->drv->backend->backendDeinit(src);
|
2014-02-03 15:12:57 +00:00
|
|
|
|
2014-04-08 10:07:24 +00:00
|
|
|
VIR_FREE(src->drv);
|
2014-02-03 15:12:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-25 11:45:48 +00:00
|
|
|
/**
|
|
|
|
* virStorageFileInitAs:
|
|
|
|
*
|
|
|
|
* @src: storage source definition
|
|
|
|
* @uid: uid used to access the file, or -1 for current uid
|
|
|
|
* @gid: gid used to access the file, or -1 for current gid
|
|
|
|
*
|
|
|
|
* Initialize a storage source to be used with storage driver. Use the provided
|
|
|
|
* uid and gid if possible for the operations.
|
|
|
|
*
|
|
|
|
* Returns 0 if the storage file was successfully initialized, -1 if the
|
|
|
|
* initialization failed. Libvirt error is reported.
|
|
|
|
*/
|
2014-04-08 10:07:24 +00:00
|
|
|
int
|
2014-04-25 11:45:48 +00:00
|
|
|
virStorageFileInitAs(virStorageSourcePtr src,
|
|
|
|
uid_t uid, gid_t gid)
|
2014-02-03 15:12:57 +00:00
|
|
|
{
|
2014-04-08 10:07:24 +00:00
|
|
|
int actualType = virStorageSourceGetActualType(src);
|
|
|
|
if (VIR_ALLOC(src->drv) < 0)
|
|
|
|
return -1;
|
2014-02-03 15:12:57 +00:00
|
|
|
|
2014-04-25 11:45:48 +00:00
|
|
|
if (uid == (uid_t) -1)
|
|
|
|
src->drv->uid = geteuid();
|
|
|
|
else
|
|
|
|
src->drv->uid = uid;
|
|
|
|
|
|
|
|
if (gid == (gid_t) -1)
|
|
|
|
src->drv->gid = getegid();
|
|
|
|
else
|
|
|
|
src->drv->gid = gid;
|
|
|
|
|
2014-04-08 10:07:24 +00:00
|
|
|
if (!(src->drv->backend = virStorageFileBackendForType(actualType,
|
|
|
|
src->protocol)))
|
2014-02-03 15:12:57 +00:00
|
|
|
goto error;
|
|
|
|
|
2014-04-08 10:07:24 +00:00
|
|
|
if (src->drv->backend->backendInit &&
|
|
|
|
src->drv->backend->backendInit(src) < 0)
|
2014-02-03 15:12:57 +00:00
|
|
|
goto error;
|
|
|
|
|
2014-04-08 10:07:24 +00:00
|
|
|
return 0;
|
2014-02-03 15:12:57 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
error:
|
2014-04-08 10:07:24 +00:00
|
|
|
VIR_FREE(src->drv);
|
|
|
|
return -1;
|
2014-04-25 11:45:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileInit:
|
|
|
|
*
|
|
|
|
* See virStorageFileInitAs. The file is initialized to be accessed by the
|
|
|
|
* current user.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virStorageFileInit(virStorageSourcePtr src)
|
|
|
|
{
|
|
|
|
return virStorageFileInitAs(src, -1, -1);
|
2014-02-03 15:12:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileCreate: Creates an empty storage file via storage driver
|
|
|
|
*
|
2014-04-08 10:07:24 +00:00
|
|
|
* @src: file structure pointing to the file
|
2014-02-03 15:12:57 +00:00
|
|
|
*
|
|
|
|
* Returns 0 on success, -2 if the function isn't supported by the backend,
|
|
|
|
* -1 on other failure. Errno is set in case of failure.
|
|
|
|
*/
|
|
|
|
int
|
2014-04-08 10:07:24 +00:00
|
|
|
virStorageFileCreate(virStorageSourcePtr src)
|
2014-02-03 15:12:57 +00:00
|
|
|
{
|
2014-05-02 14:51:48 +00:00
|
|
|
int ret;
|
|
|
|
|
2014-04-08 10:07:24 +00:00
|
|
|
if (!virStorageFileIsInitialized(src) ||
|
|
|
|
!src->drv->backend->storageFileCreate) {
|
2014-02-03 15:12:57 +00:00
|
|
|
errno = ENOSYS;
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
2014-05-02 14:51:48 +00:00
|
|
|
ret = src->drv->backend->storageFileCreate(src);
|
|
|
|
|
|
|
|
VIR_DEBUG("created storage file %p: ret=%d, errno=%d",
|
|
|
|
src, ret, errno);
|
|
|
|
|
|
|
|
return ret;
|
2014-02-03 15:12:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileUnlink: Unlink storage file via storage driver
|
|
|
|
*
|
2014-04-08 10:07:24 +00:00
|
|
|
* @src: file structure pointing to the file
|
2014-02-03 15:12:57 +00:00
|
|
|
*
|
|
|
|
* Unlinks the file described by the @file structure.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -2 if the function isn't supported by the backend,
|
|
|
|
* -1 on other failure. Errno is set in case of failure.
|
|
|
|
*/
|
|
|
|
int
|
2014-04-08 10:07:24 +00:00
|
|
|
virStorageFileUnlink(virStorageSourcePtr src)
|
2014-02-03 15:12:57 +00:00
|
|
|
{
|
2014-05-02 14:51:48 +00:00
|
|
|
int ret;
|
|
|
|
|
2014-04-08 10:07:24 +00:00
|
|
|
if (!virStorageFileIsInitialized(src) ||
|
|
|
|
!src->drv->backend->storageFileUnlink) {
|
2014-02-03 15:12:57 +00:00
|
|
|
errno = ENOSYS;
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
2014-05-02 14:51:48 +00:00
|
|
|
ret = src->drv->backend->storageFileUnlink(src);
|
|
|
|
|
|
|
|
VIR_DEBUG("unlinked storage file %p: ret=%d, errno=%d",
|
|
|
|
src, ret, errno);
|
|
|
|
|
|
|
|
return ret;
|
2014-02-03 15:12:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileStat: returns stat struct of a file via storage driver
|
|
|
|
*
|
2014-04-08 10:07:24 +00:00
|
|
|
* @src: file structure pointing to the file
|
2014-02-03 15:12:57 +00:00
|
|
|
* @stat: stat structure to return data
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -2 if the function isn't supported by the backend,
|
|
|
|
* -1 on other failure. Errno is set in case of failure.
|
|
|
|
*/
|
|
|
|
int
|
2014-04-08 10:07:24 +00:00
|
|
|
virStorageFileStat(virStorageSourcePtr src,
|
2014-02-03 15:12:57 +00:00
|
|
|
struct stat *st)
|
|
|
|
{
|
2014-05-02 14:51:48 +00:00
|
|
|
int ret;
|
|
|
|
|
2014-04-08 10:07:24 +00:00
|
|
|
if (!virStorageFileIsInitialized(src) ||
|
|
|
|
!src->drv->backend->storageFileStat) {
|
2014-02-03 15:12:57 +00:00
|
|
|
errno = ENOSYS;
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
2014-05-02 14:51:48 +00:00
|
|
|
ret = src->drv->backend->storageFileStat(src, st);
|
|
|
|
|
|
|
|
VIR_DEBUG("stat of storage file %p: ret=%d, errno=%d",
|
|
|
|
src, ret, errno);
|
|
|
|
|
|
|
|
return ret;
|
2014-02-03 15:12:57 +00:00
|
|
|
}
|
2014-03-07 10:53:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileReadHeader: read the beginning bytes of a file into a buffer
|
|
|
|
*
|
|
|
|
* @src: file structure pointing to the file
|
|
|
|
* @max_len: maximum number of bytes read from the storage file
|
|
|
|
* @buf: buffer to read the data into. buffer shall be freed by caller)
|
|
|
|
*
|
|
|
|
* Returns the count of bytes read on success and -1 on failure, -2 if the
|
2014-11-19 08:48:09 +00:00
|
|
|
* function isn't supported by the backend.
|
|
|
|
* Libvirt error is reported on failure.
|
2014-03-07 10:53:18 +00:00
|
|
|
*/
|
|
|
|
ssize_t
|
|
|
|
virStorageFileReadHeader(virStorageSourcePtr src,
|
|
|
|
ssize_t max_len,
|
|
|
|
char **buf)
|
|
|
|
{
|
|
|
|
ssize_t ret;
|
|
|
|
|
|
|
|
if (!virStorageFileIsInitialized(src)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("storage file backend not initialized"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!src->drv->backend->storageFileReadHeader) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("storage file header reading is not supported for "
|
2014-05-26 13:51:26 +00:00
|
|
|
"storage type %s (protocol: %s)"),
|
2014-03-07 10:53:18 +00:00
|
|
|
virStorageTypeToString(src->type),
|
|
|
|
virStorageNetProtocolTypeToString(src->protocol));
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = src->drv->backend->storageFileReadHeader(src, max_len, buf);
|
|
|
|
|
|
|
|
VIR_DEBUG("read of storage header %p: ret=%zd", src, ret);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2014-04-22 14:02:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* virStorageFileGetUniqueIdentifier: Get a unique string describing the volume
|
|
|
|
*
|
|
|
|
* @src: file structure pointing to the file
|
|
|
|
*
|
|
|
|
* Returns a string uniquely describing a single volume (canonical path).
|
|
|
|
* The string shall not be freed and is valid until the storage file is
|
|
|
|
* deinitialized. Returns NULL on error and sets a libvirt error code */
|
|
|
|
const char *
|
|
|
|
virStorageFileGetUniqueIdentifier(virStorageSourcePtr src)
|
|
|
|
{
|
|
|
|
if (!virStorageFileIsInitialized(src)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("storage file backend not initialized"));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!src->drv->backend->storageFileGetUniqueIdentifier) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unique storage file identifier not implemented for "
|
|
|
|
"storage type %s (protocol: %s)'"),
|
|
|
|
virStorageTypeToString(src->type),
|
|
|
|
virStorageNetProtocolTypeToString(src->protocol));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return src->drv->backend->storageFileGetUniqueIdentifier(src);
|
|
|
|
}
|
2014-04-26 16:15:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileAccess: Check accessibility of a storage file
|
|
|
|
*
|
|
|
|
* @src: storage file to check access permissions
|
|
|
|
* @mode: accessibility check options (see man 2 access)
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error and sets errno. No libvirt
|
|
|
|
* error is reported. Returns -2 if the operation isn't supported
|
|
|
|
* by libvirt storage backend.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virStorageFileAccess(virStorageSourcePtr src,
|
|
|
|
int mode)
|
|
|
|
{
|
|
|
|
if (!virStorageFileIsInitialized(src) ||
|
|
|
|
!src->drv->backend->storageFileAccess) {
|
|
|
|
errno = ENOSYS;
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
return src->drv->backend->storageFileAccess(src, mode);
|
|
|
|
}
|
2014-04-24 10:14:01 +00:00
|
|
|
|
|
|
|
|
2014-07-09 14:42:10 +00:00
|
|
|
/**
|
|
|
|
* virStorageFileChown: Change owner of a storage file
|
|
|
|
*
|
|
|
|
* @src: storage file to change owner of
|
|
|
|
* @uid: new owner id
|
|
|
|
* @gid: new group id
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error and sets errno. No libvirt
|
|
|
|
* error is reported. Returns -2 if the operation isn't supported
|
|
|
|
* by libvirt storage backend.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virStorageFileChown(virStorageSourcePtr src,
|
|
|
|
uid_t uid,
|
|
|
|
gid_t gid)
|
|
|
|
{
|
|
|
|
if (!virStorageFileIsInitialized(src) ||
|
|
|
|
!src->drv->backend->storageFileChown) {
|
|
|
|
errno = ENOSYS;
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
2014-12-05 08:51:23 +00:00
|
|
|
VIR_DEBUG("chown of storage file %p to %u:%u",
|
|
|
|
src, (unsigned int)uid, (unsigned int)gid);
|
2014-07-09 14:42:10 +00:00
|
|
|
|
|
|
|
return src->drv->backend->storageFileChown(src, uid, gid);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-24 10:14:01 +00:00
|
|
|
/* Recursive workhorse for virStorageFileGetMetadata. */
|
|
|
|
static int
|
|
|
|
virStorageFileGetMetadataRecurse(virStorageSourcePtr src,
|
2014-09-11 17:09:48 +00:00
|
|
|
virStorageSourcePtr parent,
|
2014-04-24 10:14:01 +00:00
|
|
|
uid_t uid, gid_t gid,
|
|
|
|
bool allow_probe,
|
2014-09-11 16:28:47 +00:00
|
|
|
bool report_broken,
|
2014-04-24 10:14:01 +00:00
|
|
|
virHashTablePtr cycle)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
2014-04-24 14:59:56 +00:00
|
|
|
const char *uniqueName;
|
2014-04-25 19:38:40 +00:00
|
|
|
char *buf = NULL;
|
|
|
|
ssize_t headerLen;
|
2014-04-24 10:14:01 +00:00
|
|
|
virStorageSourcePtr backingStore = NULL;
|
|
|
|
int backingFormat;
|
|
|
|
|
2014-12-05 08:51:23 +00:00
|
|
|
VIR_DEBUG("path=%s format=%d uid=%u gid=%u probe=%d",
|
2014-05-27 13:32:21 +00:00
|
|
|
src->path, src->format,
|
2014-12-05 08:51:23 +00:00
|
|
|
(unsigned int)uid, (unsigned int)gid, allow_probe);
|
2014-04-24 10:14:01 +00:00
|
|
|
|
2014-04-24 14:59:56 +00:00
|
|
|
/* exit if we can't load information about the current image */
|
|
|
|
if (!virStorageFileSupportsBackingChainTraversal(src))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (virStorageFileInitAs(src, uid, gid) < 0)
|
2014-04-24 10:14:01 +00:00
|
|
|
return -1;
|
2014-04-24 14:59:56 +00:00
|
|
|
|
2014-04-28 06:44:42 +00:00
|
|
|
if (virStorageFileAccess(src, F_OK) < 0) {
|
2014-09-11 17:09:48 +00:00
|
|
|
if (src == parent) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Cannot access storage file '%s' "
|
2014-12-05 08:51:23 +00:00
|
|
|
"(as uid:%u, gid:%u)"),
|
|
|
|
src->path, (unsigned int)uid,
|
|
|
|
(unsigned int)gid);
|
2014-09-11 17:09:48 +00:00
|
|
|
} else {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Cannot access backing file '%s' "
|
2014-12-05 08:51:23 +00:00
|
|
|
"of storage file '%s' (as uid:%u, gid:%u)"),
|
|
|
|
src->path, parent->path,
|
|
|
|
(unsigned int)uid, (unsigned int)gid);
|
2014-09-11 17:09:48 +00:00
|
|
|
}
|
|
|
|
|
2014-04-28 06:44:42 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-04-24 14:59:56 +00:00
|
|
|
if (!(uniqueName = virStorageFileGetUniqueIdentifier(src)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virHashLookup(cycle, uniqueName)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("backing store for %s (%s) is self-referential"),
|
|
|
|
src->path, uniqueName);
|
|
|
|
goto cleanup;
|
2014-04-24 10:14:01 +00:00
|
|
|
}
|
|
|
|
|
2014-04-24 14:59:56 +00:00
|
|
|
if (virHashAddEntry(cycle, uniqueName, (void *)1) < 0)
|
|
|
|
goto cleanup;
|
2014-04-24 10:14:01 +00:00
|
|
|
|
2014-04-25 19:38:40 +00:00
|
|
|
if ((headerLen = virStorageFileReadHeader(src, VIR_STORAGE_MAX_HEADER,
|
|
|
|
&buf)) < 0)
|
|
|
|
goto cleanup;
|
2014-04-24 10:14:01 +00:00
|
|
|
|
2014-04-25 19:38:40 +00:00
|
|
|
if (virStorageFileGetMetadataInternal(src, buf, headerLen,
|
|
|
|
&backingFormat) < 0)
|
2014-04-24 14:59:56 +00:00
|
|
|
goto cleanup;
|
2014-04-24 10:14:01 +00:00
|
|
|
|
|
|
|
/* check whether we need to go deeper */
|
2014-04-24 14:59:56 +00:00
|
|
|
if (!src->backingStoreRaw) {
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-04-24 10:14:01 +00:00
|
|
|
|
2014-05-05 16:05:03 +00:00
|
|
|
if (!(backingStore = virStorageSourceNewFromBacking(src)))
|
2014-04-24 14:59:56 +00:00
|
|
|
goto cleanup;
|
2014-04-24 10:14:01 +00:00
|
|
|
|
|
|
|
if (backingFormat == VIR_STORAGE_FILE_AUTO && !allow_probe)
|
|
|
|
backingStore->format = VIR_STORAGE_FILE_RAW;
|
|
|
|
else if (backingFormat == VIR_STORAGE_FILE_AUTO_SAFE)
|
|
|
|
backingStore->format = VIR_STORAGE_FILE_AUTO;
|
|
|
|
else
|
|
|
|
backingStore->format = backingFormat;
|
|
|
|
|
2014-09-11 17:09:48 +00:00
|
|
|
if ((ret = virStorageFileGetMetadataRecurse(backingStore, parent,
|
2014-09-11 16:28:47 +00:00
|
|
|
uid, gid,
|
|
|
|
allow_probe, report_broken,
|
|
|
|
cycle)) < 0) {
|
|
|
|
if (report_broken)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-04-24 10:14:01 +00:00
|
|
|
/* if we fail somewhere midway, just accept and return a
|
|
|
|
* broken chain */
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
src->backingStore = backingStore;
|
|
|
|
backingStore = NULL;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2014-06-24 12:35:59 +00:00
|
|
|
VIR_FREE(buf);
|
2014-04-24 14:59:56 +00:00
|
|
|
virStorageFileDeinit(src);
|
2014-04-24 10:14:01 +00:00
|
|
|
virStorageSourceFree(backingStore);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileGetMetadata:
|
|
|
|
*
|
|
|
|
* Extract metadata about the storage volume with the specified
|
|
|
|
* image format. If image format is VIR_STORAGE_FILE_AUTO, it
|
|
|
|
* will probe to automatically identify the format. Recurses through
|
|
|
|
* the entire chain.
|
|
|
|
*
|
|
|
|
* Open files using UID and GID (or pass -1 for the current user/group).
|
|
|
|
* Treat any backing files without explicit type as raw, unless ALLOW_PROBE.
|
|
|
|
*
|
|
|
|
* Callers are advised never to use VIR_STORAGE_FILE_AUTO as a
|
|
|
|
* format, since a malicious guest can turn a raw file into any
|
|
|
|
* other non-raw format at will.
|
|
|
|
*
|
2014-09-11 16:28:47 +00:00
|
|
|
* If @report_broken is true, the whole function fails with a possibly sane
|
|
|
|
* error instead of just returning a broken chain.
|
|
|
|
*
|
2014-04-24 10:14:01 +00:00
|
|
|
* Caller MUST free result after use via virStorageSourceFree.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virStorageFileGetMetadata(virStorageSourcePtr src,
|
|
|
|
uid_t uid, gid_t gid,
|
2014-09-11 16:28:47 +00:00
|
|
|
bool allow_probe,
|
|
|
|
bool report_broken)
|
2014-04-24 10:14:01 +00:00
|
|
|
{
|
2014-12-05 08:51:23 +00:00
|
|
|
VIR_DEBUG("path=%s format=%d uid=%u gid=%u probe=%d, report_broken=%d",
|
|
|
|
src->path, src->format, (unsigned int)uid, (unsigned int)gid,
|
2014-09-11 16:28:47 +00:00
|
|
|
allow_probe, report_broken);
|
2014-04-24 10:14:01 +00:00
|
|
|
|
|
|
|
virHashTablePtr cycle = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!(cycle = virHashCreate(5, NULL)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (src->format <= VIR_STORAGE_FILE_NONE)
|
2014-11-19 08:48:09 +00:00
|
|
|
src->format = allow_probe ?
|
|
|
|
VIR_STORAGE_FILE_AUTO : VIR_STORAGE_FILE_RAW;
|
2014-04-24 10:14:01 +00:00
|
|
|
|
2014-09-11 17:09:48 +00:00
|
|
|
ret = virStorageFileGetMetadataRecurse(src, src, uid, gid,
|
2014-09-11 16:28:47 +00:00
|
|
|
allow_probe, report_broken, cycle);
|
2014-04-24 10:14:01 +00:00
|
|
|
|
|
|
|
virHashFree(cycle);
|
|
|
|
return ret;
|
|
|
|
}
|
2014-08-14 16:05:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virStorageAddISCSIPoolSourceHost(virDomainDiskDefPtr def,
|
|
|
|
virStoragePoolDefPtr pooldef)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
char **tokens = NULL;
|
|
|
|
|
|
|
|
/* Only support one host */
|
|
|
|
if (pooldef->source.nhost != 1) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Expected exactly 1 host for the storage pool"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* iscsi pool only supports one host */
|
|
|
|
def->src->nhosts = 1;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(def->src->hosts, def->src->nhosts) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(def->src->hosts[0].name, pooldef->source.hosts[0].name) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virAsprintf(&def->src->hosts[0].port, "%d",
|
|
|
|
pooldef->source.hosts[0].port ?
|
|
|
|
pooldef->source.hosts[0].port :
|
|
|
|
3260) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* iscsi volume has name like "unit:0:0:1" */
|
|
|
|
if (!(tokens = virStringSplit(def->src->srcpool->volume, ":", 0)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virStringListLength(tokens) != 4) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected iscsi volume name '%s'"),
|
|
|
|
def->src->srcpool->volume);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* iscsi pool has only one source device path */
|
|
|
|
if (virAsprintf(&def->src->path, "%s/%s",
|
|
|
|
pooldef->source.devices[0].path,
|
|
|
|
tokens[3]) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* Storage pool have not supported these 2 attributes yet,
|
|
|
|
* use the defaults.
|
|
|
|
*/
|
|
|
|
def->src->hosts[0].transport = VIR_STORAGE_NET_HOST_TRANS_TCP;
|
|
|
|
def->src->hosts[0].socket = NULL;
|
|
|
|
|
|
|
|
def->src->protocol = VIR_STORAGE_NET_PROTOCOL_ISCSI;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virStringFreeList(tokens);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virStorageTranslateDiskSourcePoolAuth(virDomainDiskDefPtr def,
|
|
|
|
virStoragePoolSourcePtr source)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
/* Only necessary when authentication set */
|
|
|
|
if (!source->auth) {
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
def->src->auth = virStorageAuthDefCopy(source->auth);
|
|
|
|
if (!def->src->auth)
|
|
|
|
goto cleanup;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virStorageTranslateDiskSourcePool(virConnectPtr conn,
|
|
|
|
virDomainDiskDefPtr def)
|
|
|
|
{
|
|
|
|
virStoragePoolDefPtr pooldef = NULL;
|
|
|
|
virStoragePoolPtr pool = NULL;
|
|
|
|
virStorageVolPtr vol = NULL;
|
|
|
|
char *poolxml = NULL;
|
|
|
|
virStorageVolInfo info;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (def->src->type != VIR_STORAGE_TYPE_VOLUME)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!def->src->srcpool)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!(pool = virStoragePoolLookupByName(conn, def->src->srcpool->pool)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (virStoragePoolIsActive(pool) != 1) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("storage pool '%s' containing volume '%s' "
|
|
|
|
"is not active"),
|
|
|
|
def->src->srcpool->pool, def->src->srcpool->volume);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(vol = virStorageVolLookupByName(pool, def->src->srcpool->volume)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virStorageVolGetInfo(vol, &info) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(poolxml = virStoragePoolGetXMLDesc(pool, 0)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(pooldef = virStoragePoolDefParseString(poolxml)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
def->src->srcpool->pooltype = pooldef->type;
|
|
|
|
def->src->srcpool->voltype = info.type;
|
|
|
|
|
|
|
|
if (def->src->srcpool->mode && pooldef->type != VIR_STORAGE_POOL_ISCSI) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
|
_("disk source mode is only valid when "
|
|
|
|
"storage pool is of iscsi type"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(def->src->path);
|
|
|
|
virStorageNetHostDefFree(def->src->nhosts, def->src->hosts);
|
|
|
|
virStorageAuthDefFree(def->src->auth);
|
|
|
|
|
|
|
|
switch ((virStoragePoolType) pooldef->type) {
|
|
|
|
case VIR_STORAGE_POOL_DIR:
|
|
|
|
case VIR_STORAGE_POOL_FS:
|
|
|
|
case VIR_STORAGE_POOL_NETFS:
|
|
|
|
case VIR_STORAGE_POOL_LOGICAL:
|
|
|
|
case VIR_STORAGE_POOL_DISK:
|
|
|
|
case VIR_STORAGE_POOL_SCSI:
|
|
|
|
case VIR_STORAGE_POOL_ZFS:
|
|
|
|
if (!(def->src->path = virStorageVolGetPath(vol)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (def->startupPolicy && info.type != VIR_STORAGE_VOL_FILE) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
|
_("'startupPolicy' is only valid for "
|
|
|
|
"'file' type volume"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch (info.type) {
|
|
|
|
case VIR_STORAGE_VOL_FILE:
|
|
|
|
def->src->srcpool->actualtype = VIR_STORAGE_TYPE_FILE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_STORAGE_VOL_DIR:
|
|
|
|
def->src->srcpool->actualtype = VIR_STORAGE_TYPE_DIR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_STORAGE_VOL_BLOCK:
|
|
|
|
def->src->srcpool->actualtype = VIR_STORAGE_TYPE_BLOCK;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_STORAGE_VOL_NETWORK:
|
|
|
|
case VIR_STORAGE_VOL_NETDIR:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected storage volume type '%s' "
|
|
|
|
"for storage pool type '%s'"),
|
|
|
|
virStorageVolTypeToString(info.type),
|
|
|
|
virStoragePoolTypeToString(pooldef->type));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_STORAGE_POOL_ISCSI:
|
|
|
|
if (def->startupPolicy) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
|
_("'startupPolicy' is only valid for "
|
|
|
|
"'file' type volume"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (def->src->srcpool->mode) {
|
|
|
|
case VIR_STORAGE_SOURCE_POOL_MODE_DEFAULT:
|
|
|
|
case VIR_STORAGE_SOURCE_POOL_MODE_LAST:
|
|
|
|
def->src->srcpool->mode = VIR_STORAGE_SOURCE_POOL_MODE_HOST;
|
|
|
|
/* fallthrough */
|
|
|
|
case VIR_STORAGE_SOURCE_POOL_MODE_HOST:
|
|
|
|
def->src->srcpool->actualtype = VIR_STORAGE_TYPE_BLOCK;
|
|
|
|
if (!(def->src->path = virStorageVolGetPath(vol)))
|
|
|
|
goto cleanup;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_STORAGE_SOURCE_POOL_MODE_DIRECT:
|
|
|
|
def->src->srcpool->actualtype = VIR_STORAGE_TYPE_NETWORK;
|
|
|
|
def->src->protocol = VIR_STORAGE_NET_PROTOCOL_ISCSI;
|
|
|
|
|
2014-11-19 08:48:09 +00:00
|
|
|
if (virStorageTranslateDiskSourcePoolAuth(def,
|
|
|
|
&pooldef->source) < 0)
|
2014-08-14 16:05:48 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-06-08 22:41:28 +00:00
|
|
|
/* Source pool may not fill in the secrettype field,
|
|
|
|
* so we need to do so here
|
|
|
|
*/
|
|
|
|
if (def->src->auth && !def->src->auth->secrettype) {
|
|
|
|
const char *secrettype =
|
|
|
|
virSecretUsageTypeToString(VIR_SECRET_USAGE_TYPE_ISCSI);
|
|
|
|
if (VIR_STRDUP(def->src->auth->secrettype, secrettype) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-08-14 16:05:48 +00:00
|
|
|
if (virStorageAddISCSIPoolSourceHost(def, pooldef) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_STORAGE_POOL_MPATH:
|
|
|
|
case VIR_STORAGE_POOL_RBD:
|
|
|
|
case VIR_STORAGE_POOL_SHEEPDOG:
|
|
|
|
case VIR_STORAGE_POOL_GLUSTER:
|
|
|
|
case VIR_STORAGE_POOL_LAST:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("using '%s' pools for backing 'volume' disks "
|
|
|
|
"isn't yet supported"),
|
|
|
|
virStoragePoolTypeToString(pooldef->type));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
2014-11-30 14:35:12 +00:00
|
|
|
virObjectUnref(pool);
|
2014-11-30 14:26:02 +00:00
|
|
|
virObjectUnref(vol);
|
2014-08-14 16:05:48 +00:00
|
|
|
VIR_FREE(poolxml);
|
|
|
|
virStoragePoolDefFree(pooldef);
|
|
|
|
return ret;
|
|
|
|
}
|