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
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.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
|
|
|
|
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"
|
2019-02-07 17:03:08 +00:00
|
|
|
#include "storage_capabilities.h"
|
2008-02-20 15:34:52 +00:00
|
|
|
#include "storage_conf.h"
|
2016-06-15 18:48:30 +00:00
|
|
|
#include "storage_event.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"
|
2017-03-07 09:34:47 +00:00
|
|
|
#include "virfdstream.h"
|
2019-05-23 10:34:08 +00:00
|
|
|
#include "virpidfile.h"
|
2010-11-16 14:54:17 +00:00
|
|
|
#include "configmake.h"
|
2017-09-15 18:55:46 +00:00
|
|
|
#include "virsecret.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
2013-04-23 10:56:22 +00:00
|
|
|
#include "viraccessapicheck.h"
|
2017-06-21 11:18:53 +00:00
|
|
|
//#include "dirname.h"
|
2017-01-11 17:04:15 +00:00
|
|
|
#include "storage_util.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;
|
2016-04-11 16:16:25 +00:00
|
|
|
char *vol_path;
|
2014-07-28 12:39:09 +00:00
|
|
|
};
|
|
|
|
|
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
|
|
|
|
2017-03-30 11:45:45 +00:00
|
|
|
|
2018-09-12 13:35:42 +00:00
|
|
|
static void
|
|
|
|
storagePoolRefreshFailCleanup(virStorageBackendPtr backend,
|
|
|
|
virStoragePoolObjPtr obj,
|
|
|
|
const char *stateFile)
|
|
|
|
{
|
2018-12-06 17:33:30 +00:00
|
|
|
virErrorPtr orig_err;
|
2018-09-12 15:25:37 +00:00
|
|
|
|
2018-12-06 17:33:30 +00:00
|
|
|
virErrorPreserveLast(&orig_err);
|
2019-02-28 17:07:02 +00:00
|
|
|
virStoragePoolObjClearVols(obj);
|
|
|
|
|
2018-09-12 13:35:42 +00:00
|
|
|
if (stateFile)
|
2018-09-20 12:08:19 +00:00
|
|
|
unlink(stateFile);
|
2018-09-12 13:35:42 +00:00
|
|
|
if (backend->stopPool)
|
|
|
|
backend->stopPool(obj);
|
2018-12-06 17:33:30 +00:00
|
|
|
virErrorRestore(&orig_err);
|
2018-09-12 13:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-03-01 09:55:23 +00:00
|
|
|
static int
|
|
|
|
storagePoolRefreshImpl(virStorageBackendPtr backend,
|
|
|
|
virStoragePoolObjPtr obj,
|
|
|
|
const char *stateFile)
|
|
|
|
{
|
|
|
|
virStoragePoolObjClearVols(obj);
|
|
|
|
if (backend->refreshPool(obj) < 0) {
|
|
|
|
storagePoolRefreshFailCleanup(backend, obj, stateFile);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-30 11:45:45 +00:00
|
|
|
/**
|
|
|
|
* virStoragePoolUpdateInactive:
|
2019-05-24 14:35:40 +00:00
|
|
|
* @obj: pool object
|
2017-03-30 11:45:45 +00:00
|
|
|
*
|
|
|
|
* This function is supposed to be called after a pool becomes inactive. The
|
|
|
|
* function switches to the new config object for persistent pools. Inactive
|
|
|
|
* pools are removed.
|
|
|
|
*/
|
|
|
|
static void
|
2019-05-24 14:35:40 +00:00
|
|
|
virStoragePoolUpdateInactive(virStoragePoolObjPtr obj)
|
2017-03-30 11:45:45 +00:00
|
|
|
{
|
2017-07-26 15:56:31 +00:00
|
|
|
if (!virStoragePoolObjGetConfigFile(obj)) {
|
2017-10-07 11:24:24 +00:00
|
|
|
virStoragePoolObjRemove(driver->pools, obj);
|
2017-07-26 17:05:03 +00:00
|
|
|
} else if (virStoragePoolObjGetNewDef(obj)) {
|
|
|
|
virStoragePoolObjDefUseNewDef(obj);
|
2017-03-30 11:45:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-27 14:43:22 +00:00
|
|
|
static void
|
2017-10-08 12:14:56 +00:00
|
|
|
storagePoolUpdateStateCallback(virStoragePoolObjPtr obj,
|
2019-10-14 12:45:33 +00:00
|
|
|
const void *opaque G_GNUC_UNUSED)
|
2015-04-27 14:43:22 +00:00
|
|
|
{
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def = virStoragePoolObjGetDef(obj);
|
2017-03-30 11:47:45 +00:00
|
|
|
bool active = false;
|
2015-04-27 14:43:22 +00:00
|
|
|
virStorageBackendPtr backend;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *stateFile = NULL;
|
2015-04-27 14:43:22 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if ((backend = virStorageBackendForType(def->type)) == NULL) {
|
2016-05-23 18:36:01 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2017-05-08 16:41:11 +00:00
|
|
|
_("Missing backend %d"), def->type);
|
2018-09-12 15:05:51 +00:00
|
|
|
return;
|
2015-04-27 14:43:22 +00:00
|
|
|
}
|
|
|
|
|
2018-09-12 15:05:51 +00:00
|
|
|
if (!(stateFile = virFileBuildPath(driver->stateDir, def->name, ".xml")))
|
|
|
|
return;
|
|
|
|
|
2015-04-27 14:43:22 +00:00
|
|
|
/* Backends which do not support 'checkPool' are considered
|
2017-03-30 11:47:45 +00:00
|
|
|
* inactive by default. */
|
2015-04-27 14:43:22 +00:00
|
|
|
if (backend->checkPool &&
|
2017-05-08 15:05:12 +00:00
|
|
|
backend->checkPool(obj, &active) < 0) {
|
2016-05-23 18:36:01 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to initialize storage pool '%s': %s"),
|
2017-05-08 16:41:11 +00:00
|
|
|
def->name, virGetLastErrorMessage());
|
2018-09-20 12:08:19 +00:00
|
|
|
unlink(stateFile);
|
2017-03-30 11:47:45 +00:00
|
|
|
active = false;
|
2015-04-27 14:43:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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.
|
|
|
|
*/
|
2019-03-01 09:55:23 +00:00
|
|
|
if (active &&
|
|
|
|
storagePoolRefreshImpl(backend, obj, stateFile) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to restart storage pool '%s': %s"),
|
|
|
|
def->name, virGetLastErrorMessage());
|
|
|
|
active = false;
|
2015-04-27 14:43:22 +00:00
|
|
|
}
|
|
|
|
|
2017-07-26 16:15:42 +00:00
|
|
|
virStoragePoolObjSetActive(obj, active);
|
2017-03-30 11:47:45 +00:00
|
|
|
|
2017-07-26 16:15:42 +00:00
|
|
|
if (!virStoragePoolObjIsActive(obj))
|
2019-05-24 14:35:40 +00:00
|
|
|
virStoragePoolUpdateInactive(obj);
|
2017-03-30 11:47:45 +00:00
|
|
|
|
2015-04-27 14:43:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-10-08 12:14:56 +00:00
|
|
|
|
2015-03-16 15:30:03 +00:00
|
|
|
static void
|
|
|
|
storagePoolUpdateAllState(void)
|
|
|
|
{
|
2017-10-07 11:24:24 +00:00
|
|
|
virStoragePoolObjListForEach(driver->pools,
|
2017-10-08 12:14:56 +00:00
|
|
|
storagePoolUpdateStateCallback,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
storageDriverAutostartCallback(virStoragePoolObjPtr obj,
|
2019-10-14 12:45:33 +00:00
|
|
|
const void *opaque G_GNUC_UNUSED)
|
2017-10-08 12:14:56 +00:00
|
|
|
{
|
|
|
|
virStoragePoolDefPtr def = virStoragePoolObjGetDef(obj);
|
|
|
|
virStorageBackendPtr backend;
|
|
|
|
bool started = false;
|
2015-03-16 15:30:03 +00:00
|
|
|
|
2017-10-08 12:14:56 +00:00
|
|
|
if (!(backend = virStorageBackendForType(def->type)))
|
|
|
|
return;
|
2015-03-16 15:30:03 +00:00
|
|
|
|
2017-10-08 12:14:56 +00:00
|
|
|
if (virStoragePoolObjIsAutostart(obj) &&
|
|
|
|
!virStoragePoolObjIsActive(obj)) {
|
2019-05-24 14:35:46 +00:00
|
|
|
|
|
|
|
virStoragePoolObjSetStarting(obj, true);
|
2017-10-08 12:14:56 +00:00
|
|
|
if (backend->startPool &&
|
2018-01-26 13:31:58 +00:00
|
|
|
backend->startPool(obj) < 0) {
|
2017-10-08 12:14:56 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to autostart storage pool '%s': %s"),
|
|
|
|
def->name, virGetLastErrorMessage());
|
2019-05-24 14:35:46 +00:00
|
|
|
goto cleanup;
|
2017-10-08 12:14:56 +00:00
|
|
|
}
|
|
|
|
started = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (started) {
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *stateFile = NULL;
|
2017-10-08 12:14:56 +00:00
|
|
|
|
|
|
|
stateFile = virFileBuildPath(driver->stateDir, def->name, ".xml");
|
|
|
|
if (!stateFile ||
|
|
|
|
virStoragePoolSaveState(stateFile, def) < 0 ||
|
2019-03-01 09:55:23 +00:00
|
|
|
storagePoolRefreshImpl(backend, obj, stateFile) < 0) {
|
2017-10-08 12:14:56 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to autostart storage pool '%s': %s"),
|
|
|
|
def->name, virGetLastErrorMessage());
|
|
|
|
} else {
|
|
|
|
virStoragePoolObjSetActive(obj, true);
|
|
|
|
}
|
2015-03-16 15:30:03 +00:00
|
|
|
}
|
2019-05-24 14:35:46 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (virStoragePoolObjIsStarting(obj)) {
|
|
|
|
if (!virStoragePoolObjIsActive(obj))
|
|
|
|
virStoragePoolUpdateInactive(obj);
|
|
|
|
virStoragePoolObjSetStarting(obj, false);
|
|
|
|
}
|
2015-03-16 15:30:03 +00:00
|
|
|
}
|
|
|
|
|
2017-10-08 12:14:56 +00:00
|
|
|
|
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
|
|
|
{
|
2017-10-07 11:24:24 +00:00
|
|
|
virStoragePoolObjListForEach(driver->pools,
|
2017-10-08 12:14:56 +00:00
|
|
|
storageDriverAutostartCallback,
|
2018-01-26 13:31:58 +00:00
|
|
|
NULL);
|
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,
|
2019-10-14 12:45:33 +00:00
|
|
|
virStateInhibitCallback callback G_GNUC_UNUSED,
|
|
|
|
void *opaque G_GNUC_UNUSED)
|
2011-01-15 16:38:57 +00:00
|
|
|
{
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *configdir = NULL;
|
|
|
|
g_autofree char *rundir = NULL;
|
2019-10-05 07:15:24 +00:00
|
|
|
bool autostart = true;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
if (VIR_ALLOC(driver) < 0)
|
2019-07-23 12:05:18 +00:00
|
|
|
return VIR_DRV_STATE_INIT_ERROR;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2019-05-23 10:34:08 +00:00
|
|
|
driver->lockFD = -1;
|
2014-10-23 14:17:18 +00:00
|
|
|
if (virMutexInit(&driver->lock) < 0) {
|
|
|
|
VIR_FREE(driver);
|
2019-07-23 12:05:18 +00:00
|
|
|
return VIR_DRV_STATE_INIT_ERROR;
|
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
|
|
|
|
2017-10-07 11:24:24 +00:00
|
|
|
if (!(driver->pools = virStoragePoolObjListNew()))
|
|
|
|
goto error;
|
|
|
|
|
2009-06-12 13:20:13 +00:00
|
|
|
if (privileged) {
|
2019-10-20 11:49:46 +00:00
|
|
|
driver->configDir = g_strdup(SYSCONFDIR "/libvirt/storage");
|
|
|
|
driver->autostartDir = g_strdup(SYSCONFDIR "/libvirt/storage/autostart");
|
|
|
|
driver->stateDir = g_strdup(RUNSTATEDIR "/libvirt/storage");
|
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;
|
|
|
|
}
|
|
|
|
|
2019-05-23 10:34:08 +00:00
|
|
|
if ((driver->lockFD =
|
|
|
|
virPidFileAcquire(driver->stateDir, "driver",
|
|
|
|
true, getpid())) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2017-10-07 11:24:24 +00:00
|
|
|
if (virStoragePoolObjLoadAllState(driver->pools,
|
2017-03-07 21:10:38 +00:00
|
|
|
driver->stateDir) < 0)
|
2015-03-10 12:59:51 +00:00
|
|
|
goto error;
|
|
|
|
|
2017-10-07 11:24:24 +00:00
|
|
|
if (virStoragePoolObjLoadAllConfigs(driver->pools,
|
2017-03-07 21:10:38 +00:00
|
|
|
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();
|
|
|
|
|
2019-10-05 07:15:24 +00:00
|
|
|
if (virDriverShouldAutostart(driver->stateDir, &autostart) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (autostart)
|
|
|
|
storageDriverAutostart();
|
2019-03-01 14:16:45 +00:00
|
|
|
|
2016-06-15 18:48:30 +00:00
|
|
|
driver->storageEventState = virObjectEventStateNew();
|
|
|
|
|
2019-01-10 12:23:26 +00:00
|
|
|
/* Only one load of storage driver plus backends exists. Unlike
|
|
|
|
* domains where new binaries could change the capabilities. A
|
|
|
|
* new/changed backend requires a reinitialization. */
|
|
|
|
if (!(driver->caps = virStorageBackendGetCapabilities()))
|
|
|
|
goto error;
|
|
|
|
|
2014-10-23 14:17:18 +00:00
|
|
|
storageDriverUnlock();
|
2015-03-09 14:36:44 +00:00
|
|
|
|
2019-07-23 12:05:18 +00:00
|
|
|
return VIR_DRV_STATE_INIT_COMPLETE;
|
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();
|
2019-07-23 12:05:18 +00:00
|
|
|
return VIR_DRV_STATE_INIT_ERROR;
|
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();
|
2017-10-07 11:24:24 +00:00
|
|
|
virStoragePoolObjLoadAllState(driver->pools,
|
2017-03-07 21:10:38 +00:00
|
|
|
driver->stateDir);
|
2017-10-07 11:24:24 +00:00
|
|
|
virStoragePoolObjLoadAllConfigs(driver->pools,
|
2017-03-07 21:10:38 +00:00
|
|
|
driver->configDir,
|
|
|
|
driver->autostartDir);
|
2014-10-23 14:17:18 +00:00
|
|
|
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
|
|
|
|
2019-01-10 12:23:26 +00:00
|
|
|
virObjectUnref(driver->caps);
|
2016-10-11 07:48:36 +00:00
|
|
|
virObjectUnref(driver->storageEventState);
|
2016-06-15 18:48:30 +00:00
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
/* free inactive pools */
|
2017-10-09 17:34:45 +00:00
|
|
|
virObjectUnref(driver->pools);
|
2008-10-10 15:13:28 +00:00
|
|
|
|
2019-05-23 10:34:08 +00:00
|
|
|
if (driver->lockFD != -1)
|
|
|
|
virPidFileRelease(driver->stateDir, "driver",
|
|
|
|
driver->lockFD);
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-01-26 11:16:00 +00:00
|
|
|
static virDrvOpenStatus
|
|
|
|
storageConnectOpen(virConnectPtr conn,
|
2019-10-14 12:45:33 +00:00
|
|
|
virConnectAuthPtr auth G_GNUC_UNUSED,
|
|
|
|
virConfPtr conf G_GNUC_UNUSED,
|
2018-01-26 11:16:00 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
|
|
|
|
|
2018-03-28 11:49:29 +00:00
|
|
|
if (driver == NULL) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("storage state driver is not active"));
|
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
|
|
|
|
2019-09-26 14:56:42 +00:00
|
|
|
if (!virConnectValidateURIPath(conn->uri->path,
|
|
|
|
"storage",
|
|
|
|
driver->privileged))
|
|
|
|
return VIR_DRV_OPEN_ERROR;
|
2018-01-26 11:16:00 +00:00
|
|
|
|
|
|
|
if (virConnectOpenEnsureACL(conn) < 0)
|
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
|
|
|
|
return VIR_DRV_OPEN_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2019-10-14 12:45:33 +00:00
|
|
|
static int storageConnectClose(virConnectPtr conn G_GNUC_UNUSED)
|
2018-01-26 11:16:00 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-10-14 12:45:33 +00:00
|
|
|
static int storageConnectIsSecure(virConnectPtr conn G_GNUC_UNUSED)
|
2018-01-26 11:16:00 +00:00
|
|
|
{
|
|
|
|
/* Trivially secure, since always inside the daemon */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-10-14 12:45:33 +00:00
|
|
|
static int storageConnectIsEncrypted(virConnectPtr conn G_GNUC_UNUSED)
|
2018-01-26 11:16:00 +00:00
|
|
|
{
|
|
|
|
/* Not encrypted, but remote driver takes care of that */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-10-14 12:45:33 +00:00
|
|
|
static int storageConnectIsAlive(virConnectPtr conn G_GNUC_UNUSED)
|
2018-01-26 11:16:00 +00:00
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-03-21 14:53:23 +00:00
|
|
|
static virStoragePoolObjPtr
|
|
|
|
storagePoolObjFindByUUID(const unsigned char *uuid,
|
|
|
|
const char *name)
|
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2017-03-21 14:53:23 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
|
2017-10-07 11:24:24 +00:00
|
|
|
if (!(obj = virStoragePoolObjFindByUUID(driver->pools, uuid))) {
|
2017-03-21 14:53:23 +00:00
|
|
|
virUUIDFormat(uuid, uuidstr);
|
|
|
|
if (name)
|
|
|
|
virReportError(VIR_ERR_NO_STORAGE_POOL,
|
|
|
|
_("no storage pool with matching uuid '%s' (%s)"),
|
|
|
|
uuidstr, name);
|
|
|
|
else
|
|
|
|
virReportError(VIR_ERR_NO_STORAGE_POOL,
|
|
|
|
_("no storage pool with matching uuid '%s'"),
|
|
|
|
uuidstr);
|
|
|
|
}
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
return obj;
|
2017-03-21 14:53:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static virStoragePoolObjPtr
|
|
|
|
virStoragePoolObjFromStoragePool(virStoragePoolPtr pool)
|
|
|
|
{
|
2017-11-24 14:32:38 +00:00
|
|
|
return storagePoolObjFindByUUID(pool->uuid, pool->name);
|
2017-03-21 14:53:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static virStoragePoolObjPtr
|
|
|
|
storagePoolObjFindByName(const char *name)
|
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2017-03-21 14:53:23 +00:00
|
|
|
|
2017-10-07 11:24:24 +00:00
|
|
|
if (!(obj = virStoragePoolObjFindByName(driver->pools, name)))
|
2017-03-21 14:53:23 +00:00
|
|
|
virReportError(VIR_ERR_NO_STORAGE_POOL,
|
|
|
|
_("no storage pool with matching name '%s'"), name);
|
2017-05-08 15:05:12 +00:00
|
|
|
return obj;
|
2017-03-21 14:53:23 +00:00
|
|
|
}
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
|
|
|
|
static virStoragePoolPtr
|
|
|
|
storagePoolLookupByUUID(virConnectPtr conn,
|
2014-03-18 08:15:36 +00:00
|
|
|
const unsigned char *uuid)
|
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolPtr pool = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
obj = storagePoolObjFindByUUID(uuid, NULL);
|
|
|
|
if (!obj)
|
2014-06-05 08:40:59 +00:00
|
|
|
return NULL;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolLookupByUUIDEnsureACL(conn, def) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2017-05-08 15:05:12 +00:00
|
|
|
return pool;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static virStoragePoolPtr
|
|
|
|
storagePoolLookupByName(virConnectPtr conn,
|
2014-03-18 08:15:36 +00:00
|
|
|
const char *name)
|
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolPtr pool = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(obj = storagePoolObjFindByName(name)))
|
2014-06-12 07:55:17 +00:00
|
|
|
return NULL;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolLookupByNameEnsureACL(conn, def) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2017-05-08 15:05:12 +00:00
|
|
|
return pool;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static virStoragePoolPtr
|
2014-03-18 08:15:36 +00:00
|
|
|
storagePoolLookupByVolume(virStorageVolPtr vol)
|
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolPtr pool = NULL;
|
2013-04-23 10:56:22 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(obj = storagePoolObjFindByName(vol->pool)))
|
2014-06-12 07:55:17 +00:00
|
|
|
return NULL;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2013-04-23 10:56:22 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolLookupByVolumeEnsureACL(vol->conn, def) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
pool = virGetStoragePool(vol->conn, def->name, def->uuid, NULL, NULL);
|
2013-04-23 10:56:22 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2017-05-08 15:05:12 +00:00
|
|
|
return pool;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-03-18 08:15:36 +00:00
|
|
|
storageConnectNumOfStoragePools(virConnectPtr conn)
|
|
|
|
{
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virConnectNumOfStoragePoolsEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2017-11-24 14:32:38 +00:00
|
|
|
return virStoragePoolObjNumOfStoragePools(driver->pools, conn, true,
|
|
|
|
virConnectNumOfStoragePoolsCheckACL);
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2017-03-21 13:15:18 +00:00
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
storageConnectListStoragePools(virConnectPtr conn,
|
|
|
|
char **const names,
|
2017-03-21 13:15:18 +00:00
|
|
|
int maxnames)
|
2014-03-18 08:15:36 +00:00
|
|
|
{
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virConnectListStoragePoolsEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2017-11-24 14:32:38 +00:00
|
|
|
return virStoragePoolObjGetNames(driver->pools, conn, true,
|
|
|
|
virConnectListStoragePoolsCheckACL,
|
|
|
|
names, maxnames);
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2019-01-10 12:23:26 +00:00
|
|
|
|
|
|
|
static char *
|
|
|
|
storageConnectGetCapabilities(virConnectPtr conn)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (virConnectGetCapabilitiesEnsureACL(conn) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return virCapabilitiesFormatXML(driver->caps);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
static int
|
2014-03-18 08:15:36 +00:00
|
|
|
storageConnectNumOfDefinedStoragePools(virConnectPtr conn)
|
|
|
|
{
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virConnectNumOfDefinedStoragePoolsEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2017-11-24 14:32:38 +00:00
|
|
|
return virStoragePoolObjNumOfStoragePools(driver->pools, conn, false,
|
|
|
|
virConnectNumOfDefinedStoragePoolsCheckACL);
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2017-03-21 13:15:18 +00:00
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
storageConnectListDefinedStoragePools(virConnectPtr conn,
|
|
|
|
char **const names,
|
2017-03-21 13:15:18 +00:00
|
|
|
int maxnames)
|
2014-03-18 08:15:36 +00:00
|
|
|
{
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virConnectListDefinedStoragePoolsEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2017-11-24 14:32:38 +00:00
|
|
|
return virStoragePoolObjGetNames(driver->pools, conn, false,
|
|
|
|
virConnectListDefinedStoragePoolsCheckACL,
|
|
|
|
names, maxnames);
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-01-26 13:31:58 +00:00
|
|
|
ret = backend->findPoolSources(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
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-02-07 17:03:08 +00:00
|
|
|
static char *
|
|
|
|
storageConnectGetStoragePoolCapabilities(virConnectPtr conn,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
virStoragePoolCapsPtr caps = NULL;
|
|
|
|
char *ret;
|
|
|
|
|
|
|
|
virCheckFlags(0, NULL);
|
|
|
|
|
|
|
|
if (virConnectGetStoragePoolCapabilitiesEnsureACL(conn) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(caps = virStoragePoolCapsNew(driver->caps)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ret = virStoragePoolCapsFormat(caps);
|
|
|
|
|
|
|
|
virObjectUnref(caps);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
static int
|
|
|
|
storagePoolIsActive(virStoragePoolPtr pool)
|
2014-06-05 08:40:59 +00:00
|
|
|
{
|
|
|
|
virStoragePoolObjPtr obj;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2014-06-05 08:40:59 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!(obj = virStoragePoolObjFromStoragePool(pool)))
|
|
|
|
return -1;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2013-04-23 10:56:22 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolIsActiveEnsureACL(pool->conn, def) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
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:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&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;
|
|
|
|
}
|
|
|
|
|
2017-05-08 15:05:12 +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;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
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
|
|
|
int ret = -1;
|
|
|
|
|
2014-06-05 08:40:59 +00:00
|
|
|
if (!(obj = virStoragePoolObjFromStoragePool(pool)))
|
|
|
|
return -1;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2013-04-23 10:56:22 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolIsPersistentEnsureACL(pool->conn, def) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-07-26 15:56:31 +00:00
|
|
|
ret = virStoragePoolObjGetConfigFile(obj) ? 1 : 0;
|
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-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&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
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj = NULL;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolPtr pool = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageBackendPtr backend;
|
2016-06-15 18:48:30 +00:00
|
|
|
virObjectEventPtr event = NULL;
|
2015-11-25 15:01:45 +00:00
|
|
|
unsigned int build_flags = 0;
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virStoragePoolDef) newDef = NULL;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *stateFile = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2015-11-25 15:01:45 +00:00
|
|
|
virCheckFlags(VIR_STORAGE_POOL_CREATE_WITH_BUILD |
|
|
|
|
VIR_STORAGE_POOL_CREATE_WITH_BUILD_OVERWRITE |
|
|
|
|
VIR_STORAGE_POOL_CREATE_WITH_BUILD_NO_OVERWRITE, NULL);
|
|
|
|
|
|
|
|
VIR_EXCLUSIVE_FLAGS_RET(VIR_STORAGE_POOL_BUILD_OVERWRITE,
|
|
|
|
VIR_STORAGE_POOL_BUILD_NO_OVERWRITE, NULL);
|
2011-07-06 22:51:23 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (!(newDef = virStoragePoolDefParseString(xml)))
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolCreateXMLEnsureACL(conn, newDef) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if ((backend = virStorageBackendForType(newDef->type)) == NULL)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2019-05-24 14:35:42 +00:00
|
|
|
if (!(obj = virStoragePoolObjListAdd(driver->pools, newDef,
|
2019-05-24 14:35:45 +00:00
|
|
|
VIR_STORAGE_POOL_OBJ_LIST_ADD_LIVE |
|
2019-05-24 14:35:42 +00:00
|
|
|
VIR_STORAGE_POOL_OBJ_LIST_ADD_CHECK_LIVE)))
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2017-05-08 16:41:11 +00:00
|
|
|
newDef = NULL;
|
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2019-05-24 14:35:46 +00:00
|
|
|
virStoragePoolObjSetStarting(obj, true);
|
|
|
|
|
2015-11-25 15:01:45 +00:00
|
|
|
if (backend->buildPool) {
|
|
|
|
if (flags & VIR_STORAGE_POOL_CREATE_WITH_BUILD_OVERWRITE)
|
|
|
|
build_flags |= VIR_STORAGE_POOL_BUILD_OVERWRITE;
|
|
|
|
else if (flags & VIR_STORAGE_POOL_CREATE_WITH_BUILD_NO_OVERWRITE)
|
|
|
|
build_flags |= VIR_STORAGE_POOL_BUILD_NO_OVERWRITE;
|
|
|
|
|
|
|
|
if (build_flags ||
|
|
|
|
(flags & VIR_STORAGE_POOL_CREATE_WITH_BUILD)) {
|
2019-05-24 14:35:37 +00:00
|
|
|
if (backend->buildPool(obj, build_flags) < 0)
|
|
|
|
goto error;
|
2015-11-25 15:01:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-17 15:10:48 +00:00
|
|
|
if (backend->startPool &&
|
2018-09-12 15:17:17 +00:00
|
|
|
backend->startPool(obj) < 0)
|
|
|
|
goto error;
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
stateFile = virFileBuildPath(driver->stateDir, def->name, ".xml");
|
2015-03-09 14:36:44 +00:00
|
|
|
|
2019-03-01 09:55:23 +00:00
|
|
|
if (!stateFile ||
|
|
|
|
virStoragePoolSaveState(stateFile, def) < 0 ||
|
|
|
|
storagePoolRefreshImpl(backend, obj, stateFile) < 0) {
|
2018-09-12 15:17:17 +00:00
|
|
|
goto error;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2016-06-15 18:48:30 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
event = virStoragePoolEventLifecycleNew(def->name,
|
|
|
|
def->uuid,
|
2016-06-15 18:48:30 +00:00
|
|
|
VIR_STORAGE_POOL_EVENT_STARTED,
|
|
|
|
0);
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
VIR_INFO("Creating storage pool '%s'", def->name);
|
2017-07-26 16:15:42 +00:00
|
|
|
virStoragePoolObjSetActive(obj, true);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2019-08-23 13:11:20 +00:00
|
|
|
if (obj && virStoragePoolObjIsStarting(obj)) {
|
2019-05-24 14:35:46 +00:00
|
|
|
if (!virStoragePoolObjIsActive(obj))
|
|
|
|
virStoragePoolUpdateInactive(obj);
|
|
|
|
virStoragePoolObjSetStarting(obj, false);
|
|
|
|
}
|
2018-06-11 19:38:17 +00:00
|
|
|
virObjectEventStateQueue(driver->storageEventState, event);
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2017-05-08 15:05:12 +00:00
|
|
|
return pool;
|
2018-09-12 15:17:17 +00:00
|
|
|
|
|
|
|
error:
|
2019-05-24 14:35:45 +00:00
|
|
|
virStoragePoolUpdateInactive(obj);
|
2018-09-12 15:17:17 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj = NULL;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolPtr pool = NULL;
|
2016-06-15 18:48:30 +00:00
|
|
|
virObjectEventPtr event = NULL;
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virStoragePoolDef) newDef = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2011-07-06 22:51:23 +00:00
|
|
|
virCheckFlags(0, NULL);
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (!(newDef = virStoragePoolDefParseString(xml)))
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virXMLCheckIllegalChars("name", newDef->name, "\n") < 0)
|
2016-11-11 09:17:38 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolDefineXMLEnsureACL(conn, newDef) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStorageBackendForType(newDef->type) == NULL)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2019-05-24 14:35:42 +00:00
|
|
|
if (!(obj = virStoragePoolObjListAdd(driver->pools, newDef, 0)))
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2018-07-10 07:15:24 +00:00
|
|
|
newDef = virStoragePoolObjGetNewDef(obj);
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2018-07-10 07:15:24 +00:00
|
|
|
if (virStoragePoolObjSaveDef(driver, obj, newDef ? newDef : def) < 0) {
|
2017-10-07 11:24:24 +00:00
|
|
|
virStoragePoolObjRemove(driver->pools, obj);
|
2018-07-10 07:15:24 +00:00
|
|
|
newDef = NULL;
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2016-06-15 18:48:30 +00:00
|
|
|
|
|
|
|
event = virStoragePoolEventLifecycleNew(def->name, def->uuid,
|
|
|
|
VIR_STORAGE_POOL_EVENT_DEFINED,
|
|
|
|
0);
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
VIR_INFO("Defining storage pool '%s'", def->name);
|
|
|
|
pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
|
2018-07-10 07:15:24 +00:00
|
|
|
newDef = NULL;
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2018-06-11 19:38:17 +00:00
|
|
|
virObjectEventStateQueue(driver->storageEventState, event);
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2017-05-08 15:05:12 +00:00
|
|
|
return pool;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2017-05-08 15:05:12 +00:00
|
|
|
storagePoolUndefine(virStoragePoolPtr pool)
|
2014-03-18 08:15:36 +00:00
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2017-07-26 16:06:58 +00:00
|
|
|
const char *autostartLink;
|
2016-06-15 18:48:30 +00:00
|
|
|
virObjectEventPtr event = NULL;
|
2008-12-04 21:39:45 +00:00
|
|
|
int ret = -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(obj = storagePoolObjFindByUUID(pool->uuid, pool->name)))
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolUndefineEnsureACL(pool->conn, def) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (virStoragePoolObjIsActive(obj)) {
|
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"),
|
2017-05-08 16:41:11 +00:00
|
|
|
def->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2019-05-24 14:35:46 +00:00
|
|
|
if (virStoragePoolObjIsStarting(obj)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("storage pool '%s' is starting up"),
|
|
|
|
def->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-07-26 16:27:26 +00:00
|
|
|
if (virStoragePoolObjGetAsyncjobs(obj) > 0) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("pool '%s' has asynchronous jobs running."),
|
2017-05-08 16:41:11 +00:00
|
|
|
def->name);
|
2009-04-17 19:12:37 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-07-26 16:06:58 +00:00
|
|
|
autostartLink = virStoragePoolObjGetAutostartLink(obj);
|
2017-05-08 15:05:12 +00:00
|
|
|
if (virStoragePoolObjDeleteDef(obj) < 0)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-07-26 16:06:58 +00:00
|
|
|
if (autostartLink && unlink(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"),
|
2017-07-26 16:06:58 +00:00
|
|
|
autostartLink, virStrerror(errno, ebuf, sizeof(ebuf)));
|
2009-02-05 16:28:30 +00:00
|
|
|
}
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
event = virStoragePoolEventLifecycleNew(def->name,
|
|
|
|
def->uuid,
|
2016-06-15 18:48:30 +00:00
|
|
|
VIR_STORAGE_POOL_EVENT_UNDEFINED,
|
|
|
|
0);
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
VIR_INFO("Undefining storage pool '%s'", def->name);
|
2017-10-07 11:24:24 +00:00
|
|
|
virStoragePoolObjRemove(driver->pools, obj);
|
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:
|
2018-06-11 19:38:17 +00:00
|
|
|
virObjectEventStateQueue(driver->storageEventState, event);
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2017-05-08 15:05:12 +00:00
|
|
|
storagePoolCreate(virStoragePoolPtr pool,
|
2013-04-23 12:50:18 +00:00
|
|
|
unsigned int flags)
|
2011-07-06 22:51:23 +00:00
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageBackendPtr backend;
|
2016-06-15 18:48:30 +00:00
|
|
|
virObjectEventPtr event = NULL;
|
2008-12-04 21:39:45 +00:00
|
|
|
int ret = -1;
|
2015-11-25 15:01:45 +00:00
|
|
|
unsigned int build_flags = 0;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *stateFile = NULL;
|
2019-05-24 14:35:46 +00:00
|
|
|
bool restoreStarting = false;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2015-11-25 15:01:45 +00:00
|
|
|
virCheckFlags(VIR_STORAGE_POOL_CREATE_WITH_BUILD |
|
|
|
|
VIR_STORAGE_POOL_CREATE_WITH_BUILD_OVERWRITE |
|
|
|
|
VIR_STORAGE_POOL_CREATE_WITH_BUILD_NO_OVERWRITE, -1);
|
|
|
|
|
|
|
|
VIR_EXCLUSIVE_FLAGS_RET(VIR_STORAGE_POOL_BUILD_OVERWRITE,
|
|
|
|
VIR_STORAGE_POOL_BUILD_NO_OVERWRITE, -1);
|
2011-07-06 22:51:23 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(obj = virStoragePoolObjFromStoragePool(pool)))
|
2014-06-05 08:40:59 +00:00
|
|
|
return -1;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolCreateEnsureACL(pool->conn, def) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if ((backend = virStorageBackendForType(def->type)) == NULL)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (virStoragePoolObjIsActive(obj)) {
|
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"),
|
2017-05-08 16:41:11 +00:00
|
|
|
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
|
|
|
|
2019-05-24 14:35:46 +00:00
|
|
|
if (virStoragePoolObjIsStarting(obj)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("storage pool '%s' is starting up"),
|
|
|
|
def->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
virStoragePoolObjSetStarting(obj, true);
|
|
|
|
restoreStarting = true;
|
|
|
|
|
2015-11-25 15:01:45 +00:00
|
|
|
if (backend->buildPool) {
|
|
|
|
if (flags & VIR_STORAGE_POOL_CREATE_WITH_BUILD_OVERWRITE)
|
|
|
|
build_flags |= VIR_STORAGE_POOL_BUILD_OVERWRITE;
|
|
|
|
else if (flags & VIR_STORAGE_POOL_CREATE_WITH_BUILD_NO_OVERWRITE)
|
|
|
|
build_flags |= VIR_STORAGE_POOL_BUILD_NO_OVERWRITE;
|
|
|
|
|
|
|
|
if (build_flags ||
|
|
|
|
(flags & VIR_STORAGE_POOL_CREATE_WITH_BUILD)) {
|
2018-01-26 13:31:58 +00:00
|
|
|
if (backend->buildPool(obj, build_flags) < 0)
|
2015-11-25 15:01:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
VIR_INFO("Starting up storage pool '%s'", def->name);
|
2008-02-20 15:34:52 +00:00
|
|
|
if (backend->startPool &&
|
2018-01-26 13:31:58 +00:00
|
|
|
backend->startPool(obj) < 0)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
stateFile = virFileBuildPath(driver->stateDir, def->name, ".xml");
|
2015-03-09 14:36:44 +00:00
|
|
|
|
2019-03-01 09:55:23 +00:00
|
|
|
if (!stateFile ||
|
|
|
|
virStoragePoolSaveState(stateFile, def) < 0 ||
|
|
|
|
storagePoolRefreshImpl(backend, obj, stateFile) < 0) {
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
event = virStoragePoolEventLifecycleNew(def->name,
|
|
|
|
def->uuid,
|
2016-06-15 18:48:30 +00:00
|
|
|
VIR_STORAGE_POOL_EVENT_STARTED,
|
|
|
|
0);
|
|
|
|
|
2017-07-26 16:15:42 +00:00
|
|
|
virStoragePoolObjSetActive(obj, true);
|
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:
|
2019-05-24 14:35:46 +00:00
|
|
|
if (restoreStarting &&
|
|
|
|
virStoragePoolObjIsStarting(obj)) {
|
|
|
|
if (!virStoragePoolObjIsActive(obj))
|
|
|
|
virStoragePoolUpdateInactive(obj);
|
|
|
|
virStoragePoolObjSetStarting(obj, false);
|
|
|
|
}
|
2018-06-11 19:38:17 +00:00
|
|
|
virObjectEventStateQueue(driver->storageEventState, event);
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2017-05-08 15:05:12 +00:00
|
|
|
storagePoolBuild(virStoragePoolPtr pool,
|
2014-03-18 08:15:36 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageBackendPtr backend;
|
2017-09-09 15:09:49 +00:00
|
|
|
virObjectEventPtr event = NULL;
|
2019-05-24 14:35:46 +00:00
|
|
|
bool restoreStarting = false;
|
2008-12-04 21:39:45 +00:00
|
|
|
int ret = -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(obj = virStoragePoolObjFromStoragePool(pool)))
|
2014-06-05 08:40:59 +00:00
|
|
|
return -1;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolBuildEnsureACL(pool->conn, def) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if ((backend = virStorageBackendForType(def->type)) == NULL)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (virStoragePoolObjIsActive(obj)) {
|
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"),
|
2017-05-08 16:41:11 +00:00
|
|
|
def->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2019-05-24 14:35:46 +00:00
|
|
|
if (virStoragePoolObjIsStarting(obj)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("storage pool '%s' is starting up"),
|
|
|
|
def->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
virStoragePoolObjSetStarting(obj, true);
|
|
|
|
restoreStarting = true;
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
if (backend->buildPool &&
|
2018-01-26 13:31:58 +00:00
|
|
|
backend->buildPool(obj, flags) < 0)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2017-09-09 15:09:49 +00:00
|
|
|
|
2017-10-06 14:31:34 +00:00
|
|
|
event = virStoragePoolEventLifecycleNew(def->name,
|
|
|
|
def->uuid,
|
2017-09-09 15:09:49 +00:00
|
|
|
VIR_STORAGE_POOL_EVENT_CREATED,
|
|
|
|
0);
|
|
|
|
|
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:
|
2019-05-24 14:35:46 +00:00
|
|
|
if (restoreStarting &&
|
|
|
|
virStoragePoolObjIsStarting(obj)) {
|
|
|
|
virStoragePoolUpdateInactive(obj);
|
|
|
|
virStoragePoolObjSetStarting(obj, false);
|
|
|
|
}
|
2018-06-11 19:38:17 +00:00
|
|
|
virObjectEventStateQueue(driver->storageEventState, event);
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2017-05-08 15:05:12 +00:00
|
|
|
storagePoolDestroy(virStoragePoolPtr pool)
|
2014-03-18 08:15:36 +00:00
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageBackendPtr backend;
|
2016-06-15 18:48:30 +00:00
|
|
|
virObjectEventPtr event = NULL;
|
2008-12-04 21:39:45 +00:00
|
|
|
int ret = -1;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *stateFile = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(obj = storagePoolObjFindByUUID(pool->uuid, pool->name)))
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolDestroyEnsureACL(pool->conn, def) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if ((backend = virStorageBackendForType(def->type)) == NULL)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
VIR_INFO("Destroying storage pool '%s'", def->name);
|
2015-03-09 14:36:44 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!virStoragePoolObjIsActive(obj)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2017-05-08 16:41:11 +00:00
|
|
|
_("storage pool '%s' is not active"), def->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2019-05-24 14:35:46 +00:00
|
|
|
if (virStoragePoolObjIsStarting(obj)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("storage pool '%s' is starting up"),
|
|
|
|
def->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-07-26 16:27:26 +00:00
|
|
|
if (virStoragePoolObjGetAsyncjobs(obj) > 0) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("pool '%s' has asynchronous jobs running."),
|
2017-05-08 16:41:11 +00:00
|
|
|
def->name);
|
2009-04-17 19:12:37 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (!(stateFile = virFileBuildPath(driver->stateDir, def->name, ".xml")))
|
2015-03-09 14:36:44 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
unlink(stateFile);
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
if (backend->stopPool &&
|
2018-01-26 13:31:58 +00:00
|
|
|
backend->stopPool(obj) < 0)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjClearVols(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
event = virStoragePoolEventLifecycleNew(def->name,
|
|
|
|
def->uuid,
|
2016-06-15 18:48:30 +00:00
|
|
|
VIR_STORAGE_POOL_EVENT_STOPPED,
|
|
|
|
0);
|
|
|
|
|
2017-07-26 16:15:42 +00:00
|
|
|
virStoragePoolObjSetActive(obj, false);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2019-05-24 14:35:40 +00:00
|
|
|
virStoragePoolUpdateInactive(obj);
|
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:
|
2018-06-11 19:38:17 +00:00
|
|
|
virObjectEventStateQueue(driver->storageEventState, event);
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2017-05-08 15:05:12 +00:00
|
|
|
storagePoolDelete(virStoragePoolPtr pool,
|
2014-03-18 08:15:36 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageBackendPtr backend;
|
2017-09-09 15:09:49 +00:00
|
|
|
virObjectEventPtr event = NULL;
|
2008-12-04 21:39:45 +00:00
|
|
|
int ret = -1;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *stateFile = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(obj = virStoragePoolObjFromStoragePool(pool)))
|
2014-06-05 08:40:59 +00:00
|
|
|
return -1;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolDeleteEnsureACL(pool->conn, def) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if ((backend = virStorageBackendForType(def->type)) == NULL)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
VIR_INFO("Deleting storage pool '%s'", def->name);
|
2015-03-09 14:36:44 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (virStoragePoolObjIsActive(obj)) {
|
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"),
|
2017-05-08 16:41:11 +00:00
|
|
|
def->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2019-05-24 14:35:46 +00:00
|
|
|
if (virStoragePoolObjIsStarting(obj)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("storage pool '%s' is starting up"),
|
|
|
|
def->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-07-26 16:27:26 +00:00
|
|
|
if (virStoragePoolObjGetAsyncjobs(obj) > 0) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("pool '%s' has asynchronous jobs running."),
|
2017-05-08 16:41:11 +00:00
|
|
|
def->name);
|
2009-04-17 19:12:37 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (!(stateFile = virFileBuildPath(driver->stateDir, def->name, ".xml")))
|
2015-03-09 14:36:44 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
unlink(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
|
|
|
}
|
2018-01-26 13:31:58 +00:00
|
|
|
if (backend->deletePool(obj, flags) < 0)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2015-03-09 14:36:44 +00:00
|
|
|
|
2017-10-06 14:31:34 +00:00
|
|
|
event = virStoragePoolEventLifecycleNew(def->name,
|
|
|
|
def->uuid,
|
2017-09-09 15:09:49 +00:00
|
|
|
VIR_STORAGE_POOL_EVENT_DELETED,
|
|
|
|
0);
|
|
|
|
|
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:
|
2018-06-11 19:38:17 +00:00
|
|
|
virObjectEventStateQueue(driver->storageEventState, event);
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2017-05-08 15:05:12 +00:00
|
|
|
storagePoolRefresh(virStoragePoolPtr pool,
|
2011-07-06 22:51:23 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageBackendPtr backend;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *stateFile = NULL;
|
2008-12-04 21:39:45 +00:00
|
|
|
int ret = -1;
|
2016-06-15 18:48:30 +00:00
|
|
|
virObjectEventPtr event = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2011-07-06 22:51:23 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(obj = storagePoolObjFindByUUID(pool->uuid, pool->name)))
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolRefreshEnsureACL(pool->conn, def) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if ((backend = virStorageBackendForType(def->type)) == NULL)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!virStoragePoolObjIsActive(obj)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2017-05-08 16:41:11 +00:00
|
|
|
_("storage pool '%s' is not active"), def->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2019-05-24 14:35:46 +00:00
|
|
|
if (virStoragePoolObjIsStarting(obj)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("storage pool '%s' is starting up"),
|
|
|
|
def->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-07-26 16:27:26 +00:00
|
|
|
if (virStoragePoolObjGetAsyncjobs(obj) > 0) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("pool '%s' has asynchronous jobs running."),
|
2017-05-08 16:41:11 +00:00
|
|
|
def->name);
|
2009-04-17 19:12:37 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2019-03-01 09:55:23 +00:00
|
|
|
stateFile = virFileBuildPath(driver->stateDir, def->name, ".xml");
|
|
|
|
if (storagePoolRefreshImpl(backend, obj, stateFile) < 0) {
|
2017-05-08 16:41:11 +00:00
|
|
|
event = virStoragePoolEventLifecycleNew(def->name,
|
|
|
|
def->uuid,
|
2016-06-15 18:48:30 +00:00
|
|
|
VIR_STORAGE_POOL_EVENT_STOPPED,
|
|
|
|
0);
|
2017-07-26 16:15:42 +00:00
|
|
|
virStoragePoolObjSetActive(obj, false);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2019-05-24 14:35:40 +00:00
|
|
|
virStoragePoolUpdateInactive(obj);
|
2017-03-30 11:45:45 +00:00
|
|
|
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2016-06-15 18:48:30 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
event = virStoragePoolEventRefreshNew(def->name,
|
|
|
|
def->uuid);
|
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:
|
2018-06-11 19:38:17 +00:00
|
|
|
virObjectEventStateQueue(driver->storageEventState, event);
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2017-05-08 15:05:12 +00:00
|
|
|
storagePoolGetInfo(virStoragePoolPtr pool,
|
2014-03-18 08:15:36 +00:00
|
|
|
virStoragePoolInfoPtr info)
|
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2008-12-04 21:39:45 +00:00
|
|
|
int ret = -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(obj = virStoragePoolObjFromStoragePool(pool)))
|
2014-06-05 08:40:59 +00:00
|
|
|
return -1;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolGetInfoEnsureACL(pool->conn, def) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 16:41:11 +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
|
|
|
|
|
|
|
memset(info, 0, sizeof(virStoragePoolInfo));
|
2017-07-26 16:15:42 +00:00
|
|
|
if (virStoragePoolObjIsActive(obj))
|
2008-02-20 15:34:52 +00:00
|
|
|
info->state = VIR_STORAGE_POOL_RUNNING;
|
|
|
|
else
|
|
|
|
info->state = VIR_STORAGE_POOL_INACTIVE;
|
2017-05-08 16:41:11 +00:00
|
|
|
info->capacity = def->capacity;
|
|
|
|
info->allocation = def->allocation;
|
|
|
|
info->available = 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:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
2017-05-08 15:05:12 +00:00
|
|
|
storagePoolGetXMLDesc(virStoragePoolPtr pool,
|
2011-07-06 22:51:23 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2012-06-25 10:24:45 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr newDef;
|
|
|
|
virStoragePoolDefPtr curDef;
|
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
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(obj = virStoragePoolObjFromStoragePool(pool)))
|
2014-06-05 08:40:59 +00:00
|
|
|
return NULL;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
|
|
|
newDef = virStoragePoolObjGetNewDef(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolGetXMLDescEnsureACL(pool->conn, def) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if ((flags & VIR_STORAGE_XML_INACTIVE) && newDef)
|
|
|
|
curDef = newDef;
|
2012-06-25 10:24:45 +00:00
|
|
|
else
|
2017-05-08 16:41:11 +00:00
|
|
|
curDef = def;
|
2012-06-25 10:24:45 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
ret = virStoragePoolDefFormat(curDef);
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2017-05-08 15:05:12 +00:00
|
|
|
storagePoolGetAutostart(virStoragePoolPtr pool,
|
2014-03-18 08:15:36 +00:00
|
|
|
int *autostart)
|
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2008-12-04 21:39:45 +00:00
|
|
|
int ret = -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(obj = virStoragePoolObjFromStoragePool(pool)))
|
2014-06-05 08:40:59 +00:00
|
|
|
return -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolGetAutostartEnsureACL(pool->conn,
|
|
|
|
virStoragePoolObjGetDef(obj)) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-07-26 16:23:11 +00:00
|
|
|
*autostart = virStoragePoolObjIsAutostart(obj) ? 1 : 0;
|
2017-05-08 15:05:12 +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:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2017-05-08 15:05:12 +00:00
|
|
|
storagePoolSetAutostart(virStoragePoolPtr pool,
|
2014-03-18 08:15:36 +00:00
|
|
|
int autostart)
|
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2017-07-26 15:56:31 +00:00
|
|
|
const char *configFile;
|
2017-07-26 16:06:58 +00:00
|
|
|
const char *autostartLink;
|
2017-07-26 16:23:11 +00:00
|
|
|
bool new_autostart;
|
|
|
|
bool cur_autostart;
|
2008-12-04 21:39:45 +00:00
|
|
|
int ret = -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(obj = storagePoolObjFindByUUID(pool->uuid, pool->name)))
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolSetAutostartEnsureACL(pool->conn,
|
|
|
|
virStoragePoolObjGetDef(obj)) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-07-26 15:56:31 +00:00
|
|
|
if (!(configFile = virStoragePoolObjGetConfigFile(obj))) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("pool has no config file"));
|
2017-07-22 11:05:55 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2017-07-26 16:06:58 +00:00
|
|
|
autostartLink = virStoragePoolObjGetAutostartLink(obj);
|
|
|
|
|
2017-07-26 16:23:11 +00:00
|
|
|
new_autostart = (autostart != 0);
|
|
|
|
cur_autostart = virStoragePoolObjIsAutostart(obj);
|
|
|
|
if (cur_autostart != new_autostart) {
|
|
|
|
if (new_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
|
|
|
|
2017-07-26 16:06:58 +00:00
|
|
|
if (symlink(configFile, 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'"),
|
2017-07-26 16:06:58 +00:00
|
|
|
autostartLink, configFile);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
} else {
|
2017-07-26 16:06:58 +00:00
|
|
|
if (autostartLink && unlink(autostartLink) < 0 &&
|
2008-12-04 21:39:45 +00:00
|
|
|
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'"),
|
2017-07-26 16:06:58 +00:00
|
|
|
autostartLink);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2017-08-19 12:16:18 +00:00
|
|
|
virStoragePoolObjSetAutostart(obj, new_autostart);
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2017-05-08 15:05:12 +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:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2017-05-08 15:05:12 +00:00
|
|
|
storagePoolNumOfVolumes(virStoragePoolPtr pool)
|
2014-03-18 08:15:36 +00:00
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
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;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(obj = virStoragePoolObjFromStoragePool(pool)))
|
2014-06-05 08:40:59 +00:00
|
|
|
return -1;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolNumOfVolumesEnsureACL(pool->conn, def) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!virStoragePoolObjIsActive(obj)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2017-05-08 16:41:11 +00:00
|
|
|
_("storage pool '%s' is not active"), def->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2017-03-20 14:13:27 +00:00
|
|
|
|
2017-05-09 11:00:41 +00:00
|
|
|
ret = virStoragePoolObjNumOfVolumes(obj, pool->conn,
|
2017-03-20 14:13:27 +00:00
|
|
|
virStoragePoolNumOfVolumesCheckACL);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2017-03-20 16:16:26 +00:00
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
static int
|
2017-05-08 15:05:12 +00:00
|
|
|
storagePoolListVolumes(virStoragePoolPtr pool,
|
2008-02-20 15:34:52 +00:00
|
|
|
char **const names,
|
2014-03-18 08:15:36 +00:00
|
|
|
int maxnames)
|
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2017-03-20 16:16:26 +00:00
|
|
|
int n = -1;
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(obj = virStoragePoolObjFromStoragePool(pool)))
|
2014-06-05 08:40:59 +00:00
|
|
|
return -1;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolListVolumesEnsureACL(pool->conn, def) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!virStoragePoolObjIsActive(obj)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2017-05-08 16:41:11 +00:00
|
|
|
_("storage pool '%s' is not active"), def->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2017-05-09 11:00:41 +00:00
|
|
|
n = virStoragePoolObjVolumeGetNames(obj, pool->conn,
|
2017-03-20 16:16:26 +00:00
|
|
|
virStoragePoolListVolumesCheckACL,
|
|
|
|
names, maxnames);
|
2008-02-20 15:34:52 +00:00
|
|
|
cleanup:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2017-03-20 16:16:26 +00:00
|
|
|
return n;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2017-03-20 17:48:47 +00:00
|
|
|
|
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;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2012-09-04 15:32:55 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2014-06-05 08:40:59 +00:00
|
|
|
if (!(obj = virStoragePoolObjFromStoragePool(pool)))
|
|
|
|
return -1;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2012-09-04 15:32:55 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStoragePoolListAllVolumesEnsureACL(pool->conn, def) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
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,
|
2017-05-08 16:41:11 +00:00
|
|
|
_("storage pool '%s' is not active"), def->name);
|
2012-09-04 15:32:55 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-05-09 11:00:41 +00:00
|
|
|
ret = virStoragePoolObjVolumeListExport(pool->conn, obj, vols,
|
2017-03-20 17:48:47 +00:00
|
|
|
virStoragePoolListAllVolumesCheckACL);
|
2012-09-04 15:32:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
cleanup:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2012-09-04 15:32:55 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2008-02-20 15:34:52 +00:00
|
|
|
|
|
|
|
static virStorageVolPtr
|
2017-05-08 15:05:12 +00:00
|
|
|
storageVolLookupByName(virStoragePoolPtr pool,
|
2014-03-18 08:15:36 +00:00
|
|
|
const char *name)
|
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStorageVolDefPtr voldef;
|
|
|
|
virStorageVolPtr vol = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(obj = virStoragePoolObjFromStoragePool(pool)))
|
2014-06-05 08:40:59 +00:00
|
|
|
return NULL;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!virStoragePoolObjIsActive(obj)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2017-05-08 16:41:11 +00:00
|
|
|
_("storage pool '%s' is not active"), def->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
voldef = virStorageVolDefFindByName(obj, name);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!voldef) {
|
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
|
|
|
}
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStorageVolLookupByNameEnsureACL(pool->conn, def, voldef) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
vol = virGetStorageVol(pool->conn, def->name, voldef->name,
|
2017-05-08 15:05:12 +00:00
|
|
|
voldef->key, NULL, NULL);
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2017-05-08 15:05:12 +00:00
|
|
|
return vol;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-08 12:44:31 +00:00
|
|
|
struct storageVolLookupData {
|
|
|
|
const char *key;
|
|
|
|
char *cleanpath;
|
|
|
|
const char *path;
|
|
|
|
virStorageVolDefPtr voldef;
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
storageVolLookupByKeyCallback(virStoragePoolObjPtr obj,
|
|
|
|
const void *opaque)
|
|
|
|
{
|
2018-04-25 12:42:34 +00:00
|
|
|
struct storageVolLookupData *data = (struct storageVolLookupData *)opaque;
|
2017-10-08 12:44:31 +00:00
|
|
|
|
|
|
|
if (virStoragePoolObjIsActive(obj))
|
|
|
|
data->voldef = virStorageVolDefFindByKey(obj, data->key);
|
|
|
|
|
|
|
|
return !!data->voldef;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2017-10-08 12:44:31 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
|
|
|
virStoragePoolDefPtr def;
|
|
|
|
struct storageVolLookupData data = {
|
2018-04-06 12:01:02 +00:00
|
|
|
.key = key, .voldef = NULL };
|
2017-05-08 15:05:12 +00:00
|
|
|
virStorageVolPtr vol = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-10-07 11:24:24 +00:00
|
|
|
if ((obj = virStoragePoolObjListSearch(driver->pools,
|
2017-10-08 12:44:31 +00:00
|
|
|
storageVolLookupByKeyCallback,
|
|
|
|
&data)) && data.voldef) {
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2017-10-08 12:44:31 +00:00
|
|
|
if (virStorageVolLookupByKeyEnsureACL(conn, def, data.voldef) == 0) {
|
|
|
|
vol = virGetStorageVol(conn, def->name,
|
|
|
|
data.voldef->name, data.voldef->key,
|
|
|
|
NULL, NULL);
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!vol)
|
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
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
return vol;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2017-10-08 12:44:31 +00:00
|
|
|
|
|
|
|
static bool
|
|
|
|
storageVolLookupByPathCallback(virStoragePoolObjPtr obj,
|
|
|
|
const void *opaque)
|
|
|
|
{
|
2018-04-25 12:42:34 +00:00
|
|
|
struct storageVolLookupData *data = (struct storageVolLookupData *)opaque;
|
2017-10-08 12:44:31 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *stable_path = NULL;
|
2017-10-08 12:44:31 +00:00
|
|
|
|
|
|
|
if (!virStoragePoolObjIsActive(obj))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
def = virStoragePoolObjGetDef(obj);
|
|
|
|
|
2018-04-25 12:42:34 +00:00
|
|
|
switch ((virStoragePoolType)def->type) {
|
2017-10-08 12:44:31 +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:
|
2018-07-31 08:44:21 +00:00
|
|
|
case VIR_STORAGE_POOL_ISCSI_DIRECT:
|
2017-10-08 12:44:31 +00:00
|
|
|
case VIR_STORAGE_POOL_SCSI:
|
|
|
|
case VIR_STORAGE_POOL_MPATH:
|
|
|
|
case VIR_STORAGE_POOL_VSTORAGE:
|
|
|
|
stable_path = virStorageBackendStablePath(obj, data->cleanpath,
|
|
|
|
false);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_STORAGE_POOL_GLUSTER:
|
|
|
|
case VIR_STORAGE_POOL_RBD:
|
|
|
|
case VIR_STORAGE_POOL_SHEEPDOG:
|
|
|
|
case VIR_STORAGE_POOL_ZFS:
|
|
|
|
case VIR_STORAGE_POOL_LAST:
|
2019-10-18 11:27:03 +00:00
|
|
|
stable_path = g_strdup(data->path);
|
2017-10-08 12:44:31 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Don't break the whole lookup process if it fails on
|
|
|
|
* getting the stable path for some of the pools. */
|
|
|
|
if (!stable_path) {
|
|
|
|
VIR_WARN("Failed to get stable path for pool '%s'", def->name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
data->voldef = virStorageVolDefFindByPath(obj, stable_path);
|
|
|
|
|
|
|
|
return !!data->voldef;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2017-10-08 12:44:31 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
|
|
|
virStoragePoolDefPtr def;
|
|
|
|
struct storageVolLookupData data = {
|
2018-04-06 12:01:02 +00:00
|
|
|
.path = path, .voldef = NULL };
|
2017-05-08 15:05:12 +00:00
|
|
|
virStorageVolPtr vol = NULL;
|
2010-05-20 15:41:31 +00:00
|
|
|
|
2017-10-08 12:44:31 +00:00
|
|
|
if (!(data.cleanpath = virFileSanitizePath(path)))
|
2010-05-20 15:41:31 +00:00
|
|
|
return NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-10-07 11:24:24 +00:00
|
|
|
if ((obj = virStoragePoolObjListSearch(driver->pools,
|
2017-10-08 12:44:31 +00:00
|
|
|
storageVolLookupByPathCallback,
|
|
|
|
&data)) && data.voldef) {
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2008-11-17 11:19:33 +00:00
|
|
|
|
2017-10-08 12:44:31 +00:00
|
|
|
if (virStorageVolLookupByPathEnsureACL(conn, def, data.voldef) == 0) {
|
2017-05-08 16:41:11 +00:00
|
|
|
vol = virGetStorageVol(conn, def->name,
|
2017-10-08 12:44:31 +00:00
|
|
|
data.voldef->name, data.voldef->key,
|
2014-02-25 14:51:15 +00:00
|
|
|
NULL, NULL);
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!vol) {
|
2017-10-08 12:44:31 +00:00
|
|
|
if (STREQ(path, data.cleanpath)) {
|
2014-02-24 15:07:40 +00:00
|
|
|
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)"),
|
2017-10-08 12:44:31 +00:00
|
|
|
path, data.cleanpath);
|
2014-02-24 15:07:40 +00:00
|
|
|
}
|
|
|
|
}
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2017-10-08 12:44:31 +00:00
|
|
|
VIR_FREE(data.cleanpath);
|
2017-05-08 15:05:12 +00:00
|
|
|
return vol;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2017-10-08 12:44:31 +00:00
|
|
|
|
|
|
|
static bool
|
|
|
|
storagePoolLookupByTargetPathCallback(virStoragePoolObjPtr obj,
|
|
|
|
const void *opaque)
|
|
|
|
{
|
|
|
|
const char *path = opaque;
|
|
|
|
virStoragePoolDefPtr def;
|
|
|
|
|
|
|
|
if (!virStoragePoolObjIsActive(obj))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
def = virStoragePoolObjGetDef(obj);
|
|
|
|
return STREQ(path, def->target.path);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-11-26 16:13:00 +00:00
|
|
|
virStoragePoolPtr
|
|
|
|
storagePoolLookupByTargetPath(virConnectPtr conn,
|
|
|
|
const char *path)
|
|
|
|
{
|
2017-10-08 12:44:31 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
|
|
|
virStoragePoolDefPtr def;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolPtr pool = NULL;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *cleanpath = NULL;
|
2014-11-26 16:13:00 +00:00
|
|
|
|
|
|
|
cleanpath = virFileSanitizePath(path);
|
|
|
|
if (!cleanpath)
|
|
|
|
return NULL;
|
|
|
|
|
2017-10-07 11:24:24 +00:00
|
|
|
if ((obj = virStoragePoolObjListSearch(driver->pools,
|
2017-11-24 14:42:07 +00:00
|
|
|
storagePoolLookupByTargetPathCallback,
|
2017-11-24 13:17:02 +00:00
|
|
|
cleanpath))) {
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2018-01-25 09:35:52 +00:00
|
|
|
if (virStoragePoolLookupByTargetPathEnsureACL(conn, def) < 0)
|
2019-01-31 18:41:29 +00:00
|
|
|
return NULL;
|
2018-01-25 09:35:52 +00:00
|
|
|
|
2017-10-08 12:44:31 +00:00
|
|
|
pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2014-11-26 16:13:00 +00:00
|
|
|
}
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!pool) {
|
2017-11-24 13:17:02 +00:00
|
|
|
if (STREQ(path, cleanpath)) {
|
|
|
|
virReportError(VIR_ERR_NO_STORAGE_POOL,
|
|
|
|
_("no storage pool with matching target path '%s'"),
|
|
|
|
path);
|
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_NO_STORAGE_POOL,
|
|
|
|
_("no storage pool with matching target path '%s' (%s)"),
|
|
|
|
path, cleanpath);
|
|
|
|
}
|
2014-11-26 16:13:00 +00:00
|
|
|
}
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
return pool;
|
2014-11-26 16:13:00 +00:00
|
|
|
}
|
|
|
|
|
2013-12-10 14:28:58 +00:00
|
|
|
|
2014-04-08 22:54:14 +00:00
|
|
|
static int
|
2018-01-26 13:31:58 +00:00
|
|
|
storageVolDeleteInternal(virStorageBackendPtr backend,
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj,
|
|
|
|
virStorageVolDefPtr voldef,
|
2014-04-08 22:54:14 +00:00
|
|
|
unsigned int flags,
|
|
|
|
bool updateMeta)
|
|
|
|
{
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def = virStoragePoolObjGetDef(obj);
|
2014-04-08 22:54:14 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!backend->deleteVol) {
|
|
|
|
virReportError(VIR_ERR_NO_SUPPORT,
|
|
|
|
"%s", _("storage pool does not support vol deletion"));
|
|
|
|
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2018-01-26 13:31:58 +00:00
|
|
|
if (backend->deleteVol(obj, voldef, flags) < 0)
|
2014-04-08 22:54:14 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2018-01-09 13:40:24 +00:00
|
|
|
/* The disk backend updated the pool data including removing the
|
|
|
|
* voldef from the pool (for both the deleteVol and the createVol
|
|
|
|
* failure path. */
|
|
|
|
if (def->type == VIR_STORAGE_POOL_DISK) {
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-04-08 22:54:14 +00:00
|
|
|
/* 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) {
|
2018-01-09 13:40:24 +00:00
|
|
|
def->allocation -= voldef->target.allocation;
|
|
|
|
def->available += voldef->target.allocation;
|
2014-04-08 22:54:14 +00:00
|
|
|
}
|
|
|
|
|
2017-05-09 12:05:16 +00:00
|
|
|
virStoragePoolObjRemoveVol(obj, voldef);
|
2014-04-08 22:54:14 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-05 11:29:37 +00:00
|
|
|
static virStorageVolDefPtr
|
2017-05-08 15:05:12 +00:00
|
|
|
virStorageVolDefFromVol(virStorageVolPtr vol,
|
|
|
|
virStoragePoolObjPtr *obj,
|
2014-06-05 11:29:37 +00:00
|
|
|
virStorageBackendPtr *backend)
|
2013-12-10 14:28:58 +00:00
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStorageVolDefPtr voldef = NULL;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2014-06-05 11:29:37 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(*obj = storagePoolObjFindByName(vol->pool)))
|
2014-06-05 11:29:37 +00:00
|
|
|
return NULL;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(*obj);
|
2013-12-10 14:28:58 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!virStoragePoolObjIsActive(*obj)) {
|
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"),
|
2017-05-08 16:41:11 +00:00
|
|
|
def->name);
|
2014-06-05 11:29:37 +00:00
|
|
|
goto error;
|
2013-12-10 14:28:58 +00:00
|
|
|
}
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(voldef = virStorageVolDefFindByName(*obj, vol->name))) {
|
2013-12-10 14:28:58 +00:00
|
|
|
virReportError(VIR_ERR_NO_STORAGE_VOL,
|
|
|
|
_("no storage vol with matching name '%s'"),
|
2017-05-08 15:05:12 +00:00
|
|
|
vol->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) {
|
2017-05-08 16:41:11 +00:00
|
|
|
if (!(*backend = virStorageBackendForType(def->type)))
|
2014-06-05 11:29:37 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
return voldef;
|
2014-06-05 11:29:37 +00:00
|
|
|
|
|
|
|
error:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(obj);
|
2014-06-05 11:29:37 +00:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2017-05-08 15:05:12 +00:00
|
|
|
storageVolDelete(virStorageVolPtr vol,
|
2014-06-05 11:29:37 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2014-06-05 11:29:37 +00:00
|
|
|
virStorageBackendPtr backend;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStorageVolDefPtr voldef = NULL;
|
2014-06-05 11:29:37 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(voldef = virStorageVolDefFromVol(vol, &obj, &backend)))
|
2014-06-05 11:29:37 +00:00
|
|
|
return -1;
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStorageVolDeleteEnsureACL(vol->conn, virStoragePoolObjGetDef(obj),
|
|
|
|
voldef) < 0)
|
2013-12-10 14:28:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (voldef->in_use) {
|
2014-04-16 13:16:20 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still in use."),
|
2017-05-08 15:05:12 +00:00
|
|
|
voldef->name);
|
2014-04-16 13:16:20 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (voldef->building) {
|
2013-12-10 14:28:58 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still being allocated."),
|
2017-05-08 15:05:12 +00:00
|
|
|
voldef->name);
|
2013-12-10 14:28:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2018-01-26 13:31:58 +00:00
|
|
|
if (storageVolDeleteInternal(backend, obj, voldef, flags, true) < 0)
|
2013-12-10 14:28:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
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
|
2017-05-08 15:05:12 +00:00
|
|
|
storageVolCreateXML(virStoragePoolPtr pool,
|
2013-04-23 12:50:18 +00:00
|
|
|
const char *xmldesc,
|
|
|
|
unsigned int flags)
|
2011-07-06 22:51:23 +00:00
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageBackendPtr backend;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStorageVolPtr vol = NULL, newvol = NULL;
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virStorageVolDef) voldef = 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
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(obj = virStoragePoolObjFromStoragePool(pool)))
|
2014-06-05 08:40:59 +00:00
|
|
|
return NULL;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!virStoragePoolObjIsActive(obj)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2017-05-08 16:41:11 +00:00
|
|
|
_("storage pool '%s' is not active"), def->name);
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if ((backend = virStorageBackendForType(def->type)) == NULL)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
voldef = virStorageVolDefParseString(def, xmldesc,
|
2015-02-17 15:57:02 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStorageVolCreateXMLEnsureACL(pool->conn, def, voldef) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (virStorageVolDefFindByName(obj, 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
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2018-01-26 13:31:58 +00:00
|
|
|
if (backend->createVol(obj, voldef) < 0)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (!(newvol = virGetStorageVol(pool->conn, def->name, voldef->name,
|
2017-05-09 12:05:16 +00:00
|
|
|
voldef->key, NULL, NULL)))
|
2015-07-09 09:17:12 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-09 12:05:16 +00:00
|
|
|
/* NB: Upon success voldef "owned" by storage pool for deletion purposes */
|
|
|
|
if (virStoragePoolObjAddVol(obj, voldef) < 0)
|
|
|
|
goto cleanup;
|
2009-04-17 19:12:37 +00:00
|
|
|
|
2013-08-16 12:08:07 +00:00
|
|
|
if (backend->buildVol) {
|
|
|
|
int buildret;
|
2015-09-24 15:12:02 +00:00
|
|
|
virStorageVolDefPtr buildvoldef = NULL;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(buildvoldef) < 0) {
|
|
|
|
voldef = NULL;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
|
|
|
/* Drop the pool lock during volume allocation */
|
2017-07-26 16:27:26 +00:00
|
|
|
virStoragePoolObjIncrAsyncjobs(obj);
|
2014-07-17 16:41:21 +00:00
|
|
|
voldef->building = true;
|
2017-10-09 10:19:37 +00:00
|
|
|
virObjectUnlock(obj);
|
2009-04-17 19:12:37 +00:00
|
|
|
|
2018-01-26 13:31:58 +00:00
|
|
|
buildret = backend->buildVol(obj, buildvoldef, flags);
|
2009-04-17 19:12:37 +00:00
|
|
|
|
2015-10-08 20:24:47 +00:00
|
|
|
VIR_FREE(buildvoldef);
|
|
|
|
|
2017-10-09 10:19:37 +00:00
|
|
|
virObjectLock(obj);
|
2009-05-19 11:06:25 +00:00
|
|
|
|
2014-07-17 16:41:21 +00:00
|
|
|
voldef->building = false;
|
2017-07-26 16:27:26 +00:00
|
|
|
virStoragePoolObjDecrAsyncjobs(obj);
|
2009-04-17 19:12:37 +00:00
|
|
|
|
2015-07-09 09:17:12 +00:00
|
|
|
if (buildret < 0) {
|
storage: On 'buildVol' failure don't delete the volume
https://bugzilla.redhat.com/show_bug.cgi?id=1233003
Commit id 'fdda3760' only managed a symptom where it was possible to
create a file in a pool without libvirt's knowledge, so it was reverted.
The real fix is to have all the createVol API's which actually create
a volume (disk, logical, zfs) and the buildVol API's which handle the
real creation of some volume file (fs, rbd, sheepdog) manage deleting
any volume which they create when there is some sort of error in
processing the volume.
This way the onus isn't left up to the storage_driver to determine whether
the buildVol failure was due to some failure as a result of adjustments
made to the volume after creation such as getting sizes, changing ownership,
changing volume protections, etc. or simple a failure in creation.
Without needing to consider that the volume has to be removed, the
buildVol failure path only needs to remove the volume from the pool.
This way if a creation failed due to duplicate name, libvirt wouldn't
remove a volume that it didn't create in the pool target.
2015-10-08 20:44:02 +00:00
|
|
|
/* buildVol handles deleting volume on failure */
|
2017-05-09 12:05:16 +00:00
|
|
|
virStoragePoolObjRemoveVol(obj, voldef);
|
2015-07-09 09:17:12 +00:00
|
|
|
voldef = NULL;
|
2009-04-17 19:12:37 +00:00
|
|
|
goto cleanup;
|
2015-07-09 09:17:12 +00:00
|
|
|
}
|
2015-05-28 15:00:01 +00:00
|
|
|
|
2015-07-09 09:17:12 +00:00
|
|
|
}
|
2015-05-28 15:00:01 +00:00
|
|
|
|
2015-02-17 15:57:02 +00:00
|
|
|
if (backend->refreshVol &&
|
2018-01-26 13:31:58 +00:00
|
|
|
backend->refreshVol(obj, voldef) < 0) {
|
|
|
|
storageVolDeleteInternal(backend, obj, voldef,
|
2015-08-24 16:38:13 +00:00
|
|
|
0, false);
|
|
|
|
voldef = NULL;
|
2015-02-17 15:57:02 +00:00
|
|
|
goto cleanup;
|
2015-08-24 16:38:13 +00:00
|
|
|
}
|
2015-02-17 15:57:02 +00:00
|
|
|
|
2015-05-26 13:23:28 +00:00
|
|
|
/* Update pool metadata ignoring the disk backend since
|
|
|
|
* it updates the pool values.
|
|
|
|
*/
|
2017-05-08 16:41:11 +00:00
|
|
|
if (def->type != VIR_STORAGE_POOL_DISK) {
|
|
|
|
def->allocation += voldef->target.allocation;
|
|
|
|
def->available -= voldef->target.allocation;
|
2015-05-26 13:23:28 +00:00
|
|
|
}
|
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'",
|
2017-05-08 16:41:11 +00:00
|
|
|
newvol->name, def->name);
|
2019-10-16 11:45:15 +00:00
|
|
|
vol = g_steal_pointer(&newvol);
|
2009-04-17 19:12:37 +00:00
|
|
|
voldef = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2017-05-08 15:05:12 +00:00
|
|
|
virObjectUnref(newvol);
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2017-05-08 15:05:12 +00:00
|
|
|
return vol;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2009-05-19 13:37:51 +00:00
|
|
|
static virStorageVolPtr
|
2017-05-08 15:05:12 +00:00
|
|
|
storageVolCreateXMLFrom(virStoragePoolPtr pool,
|
2013-04-23 12:50:18 +00:00
|
|
|
const char *xmldesc,
|
2017-05-08 15:05:12 +00:00
|
|
|
virStorageVolPtr volsrc,
|
2013-04-23 12:50:18 +00:00
|
|
|
unsigned int flags)
|
2011-07-06 22:51:23 +00:00
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr objsrc = NULL;
|
2009-05-19 13:37:51 +00:00
|
|
|
virStorageBackendPtr backend;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStorageVolDefPtr voldefsrc = NULL;
|
|
|
|
virStorageVolDefPtr shadowvol = NULL;
|
|
|
|
virStorageVolPtr newvol = NULL;
|
|
|
|
virStorageVolPtr vol = NULL;
|
2009-09-02 13:02:06 +00:00
|
|
|
int buildret;
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virStorageVolDef) voldef = NULL;
|
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
|
|
|
|
2017-10-07 11:24:24 +00:00
|
|
|
obj = virStoragePoolObjFindByUUID(driver->pools, pool->uuid);
|
2017-05-08 15:05:12 +00:00
|
|
|
if (obj && STRNEQ(pool->name, volsrc->pool)) {
|
2017-10-09 10:19:37 +00:00
|
|
|
virObjectUnlock(obj);
|
2017-10-07 11:24:24 +00:00
|
|
|
objsrc = virStoragePoolObjFindByName(driver->pools, volsrc->pool);
|
2017-10-09 10:19:37 +00:00
|
|
|
virObjectLock(obj);
|
2009-09-02 13:02:06 +00:00
|
|
|
}
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!obj) {
|
2014-06-05 08:40:59 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
2017-05-08 15:05:12 +00:00
|
|
|
virUUIDFormat(pool->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)"),
|
2017-05-08 15:05:12 +00:00
|
|
|
uuidstr, pool->name);
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2009-05-19 13:37:51 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (STRNEQ(pool->name, volsrc->pool) && !objsrc) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_NO_STORAGE_POOL,
|
|
|
|
_("no storage pool with matching name '%s'"),
|
2017-05-08 15:05:12 +00:00
|
|
|
volsrc->pool);
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!virStoragePoolObjIsActive(obj)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2017-05-08 16:41:11 +00:00
|
|
|
_("storage pool '%s' is not active"), def->name);
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (objsrc && !virStoragePoolObjIsActive(objsrc)) {
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr objsrcdef = virStoragePoolObjGetDef(objsrc);
|
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"),
|
2017-05-08 16:41:11 +00:00
|
|
|
objsrcdef->name);
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if ((backend = virStorageBackendForType(def->type)) == NULL)
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
voldefsrc = virStorageVolDefFindByName(objsrc ?
|
|
|
|
objsrc : obj, volsrc->name);
|
|
|
|
if (!voldefsrc) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_NO_STORAGE_VOL,
|
|
|
|
_("no storage vol with matching name '%s'"),
|
2017-05-08 15:05:12 +00:00
|
|
|
volsrc->name);
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
voldef = virStorageVolDefParseString(def, xmldesc,
|
2015-02-17 15:54:53 +00:00
|
|
|
VIR_VOL_XML_PARSE_NO_CAPACITY);
|
2017-05-08 15:05:12 +00:00
|
|
|
if (voldef == NULL)
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStorageVolCreateXMLFromEnsureACL(pool->conn, def, voldef) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (virStorageVolDefFindByName(obj, voldef->name)) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("storage volume name '%s' already in use."),
|
2017-05-08 15:05:12 +00:00
|
|
|
voldef->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 */
|
2017-05-08 15:05:12 +00:00
|
|
|
if (voldef->target.capacity < voldefsrc->target.capacity)
|
|
|
|
voldef->target.capacity = voldefsrc->target.capacity;
|
2009-05-19 13:37:51 +00:00
|
|
|
|
2016-04-29 11:43:57 +00:00
|
|
|
/* If the allocation was not provided in the XML, then use capacity
|
|
|
|
* as it's specifically documented "If omitted when creating a volume,
|
|
|
|
* the volume will be fully allocated at time of creation.". This
|
|
|
|
* is especially important for logical volume creation. */
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!voldef->target.has_allocation)
|
|
|
|
voldef->target.allocation = voldef->target.capacity;
|
2016-04-29 11:43:57 +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;
|
|
|
|
}
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (voldefsrc->building) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still being allocated."),
|
2017-05-08 15:05:12 +00:00
|
|
|
voldefsrc->name);
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (backend->refreshVol &&
|
2018-01-26 13:31:58 +00:00
|
|
|
backend->refreshVol(obj, voldefsrc) < 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. */
|
2017-05-08 15:05:12 +00:00
|
|
|
VIR_FREE(voldef->key);
|
2018-01-26 13:31:58 +00:00
|
|
|
if (backend->createVol(obj, voldef) < 0)
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-06-26 11:35:11 +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
|
|
|
|
*/
|
|
|
|
if (VIR_ALLOC(shadowvol) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
memcpy(shadowvol, voldef, sizeof(*voldef));
|
2015-06-26 11:35:11 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (!(newvol = virGetStorageVol(pool->conn, def->name, voldef->name,
|
2017-05-09 12:05:16 +00:00
|
|
|
voldef->key, NULL, NULL)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* NB: Upon success voldef "owned" by storage pool for deletion purposes */
|
|
|
|
if (virStoragePoolObjAddVol(obj, voldef) < 0)
|
2014-02-12 11:05:51 +00:00
|
|
|
goto cleanup;
|
2009-05-19 13:37:51 +00:00
|
|
|
|
|
|
|
/* Drop the pool lock during volume allocation */
|
2017-07-26 16:27:26 +00:00
|
|
|
virStoragePoolObjIncrAsyncjobs(obj);
|
2017-05-08 15:05:12 +00:00
|
|
|
voldef->building = true;
|
|
|
|
voldefsrc->in_use++;
|
2017-10-09 10:19:37 +00:00
|
|
|
virObjectUnlock(obj);
|
2009-05-19 13:37:51 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (objsrc) {
|
2017-07-26 16:27:26 +00:00
|
|
|
virStoragePoolObjIncrAsyncjobs(objsrc);
|
2017-10-09 10:19:37 +00:00
|
|
|
virObjectUnlock(objsrc);
|
2009-05-19 13:37:51 +00:00
|
|
|
}
|
|
|
|
|
2018-01-26 13:31:58 +00:00
|
|
|
buildret = backend->buildVolFrom(obj, shadowvol, voldefsrc, flags);
|
2009-05-19 13:37:51 +00:00
|
|
|
|
2017-10-09 10:19:37 +00:00
|
|
|
virObjectLock(obj);
|
2017-05-08 15:05:12 +00:00
|
|
|
if (objsrc)
|
2017-10-09 10:19:37 +00:00
|
|
|
virObjectLock(objsrc);
|
2009-05-19 13:37:51 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
voldefsrc->in_use--;
|
|
|
|
voldef->building = false;
|
2017-07-26 16:27:26 +00:00
|
|
|
virStoragePoolObjDecrAsyncjobs(obj);
|
2009-05-19 13:37:51 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (objsrc) {
|
2017-07-26 16:27:26 +00:00
|
|
|
virStoragePoolObjDecrAsyncjobs(objsrc);
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&objsrc);
|
2009-05-19 13:37:51 +00:00
|
|
|
}
|
|
|
|
|
2015-09-24 15:01:40 +00:00
|
|
|
if (buildret < 0 ||
|
|
|
|
(backend->refreshVol &&
|
2018-01-26 13:31:58 +00:00
|
|
|
backend->refreshVol(obj, voldef) < 0)) {
|
|
|
|
storageVolDeleteInternal(backend, obj, voldef, 0, false);
|
2017-05-08 15:05:12 +00:00
|
|
|
voldef = NULL;
|
2009-05-19 13:37:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2015-05-26 13:23:28 +00:00
|
|
|
/* Updating pool metadata ignoring the disk backend since
|
|
|
|
* it updates the pool values
|
|
|
|
*/
|
2017-05-08 16:41:11 +00:00
|
|
|
if (def->type != VIR_STORAGE_POOL_DISK) {
|
|
|
|
def->allocation += voldef->target.allocation;
|
|
|
|
def->available -= voldef->target.allocation;
|
2015-05-26 13:23:28 +00:00
|
|
|
}
|
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'",
|
2017-05-08 16:41:11 +00:00
|
|
|
newvol->name, def->name);
|
2019-10-16 11:45:15 +00:00
|
|
|
vol = g_steal_pointer(&newvol);
|
2017-05-08 15:05:12 +00:00
|
|
|
voldef = NULL;
|
2009-05-19 13:37:51 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2017-05-08 15:05:12 +00:00
|
|
|
virObjectUnref(newvol);
|
2015-06-26 11:35:11 +00:00
|
|
|
VIR_FREE(shadowvol);
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
|
|
|
virStoragePoolObjEndAPI(&objsrc);
|
2017-05-08 15:05:12 +00:00
|
|
|
return vol;
|
2009-05-19 13:37:51 +00:00
|
|
|
}
|
|
|
|
|
2010-02-23 03:13:18 +00:00
|
|
|
|
2009-07-14 15:24:42 +00:00
|
|
|
static int
|
2017-05-08 15:05:12 +00:00
|
|
|
storageVolDownload(virStorageVolPtr vol,
|
2013-04-23 12:50:18 +00:00
|
|
|
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;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj = NULL;
|
|
|
|
virStorageVolDefPtr voldef = NULL;
|
2009-07-14 15:24:42 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
2016-04-08 13:41:18 +00:00
|
|
|
virCheckFlags(VIR_STORAGE_VOL_DOWNLOAD_SPARSE_STREAM, -1);
|
2009-07-14 15:24:42 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(voldef = virStorageVolDefFromVol(vol, &obj, &backend)))
|
2014-06-05 11:29:37 +00:00
|
|
|
return -1;
|
2009-07-14 15:24:42 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStorageVolDownloadEnsureACL(vol->conn, virStoragePoolObjGetDef(obj),
|
|
|
|
voldef) < 0)
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2013-04-23 10:56:22 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (voldef->building) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still being allocated."),
|
2017-05-08 15:05:12 +00:00
|
|
|
voldef->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
|
|
|
|
2018-08-18 16:42:07 +00:00
|
|
|
virStoragePoolObjIncrAsyncjobs(obj);
|
|
|
|
voldef->in_use++;
|
2018-08-19 06:26:04 +00:00
|
|
|
virObjectUnlock(obj);
|
2018-08-18 16:42:07 +00:00
|
|
|
|
|
|
|
ret = backend->downloadVol(obj, voldef, stream, offset, length, flags);
|
|
|
|
|
2018-08-19 06:26:04 +00:00
|
|
|
virObjectLock(obj);
|
2018-08-18 16:42:07 +00:00
|
|
|
voldef->in_use--;
|
|
|
|
virStoragePoolObjDecrAsyncjobs(obj);
|
2009-07-14 15:24:42 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
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);
|
|
|
|
}
|
|
|
|
|
2016-04-11 16:16:25 +00:00
|
|
|
static int
|
|
|
|
virStorageBackendPloopRestoreDesc(char *path)
|
|
|
|
{
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virCommand) cmd = NULL;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *refresh_tool = NULL;
|
|
|
|
g_autofree char *desc = NULL;
|
2016-04-11 16:16:25 +00:00
|
|
|
|
|
|
|
if (virAsprintf(&desc, "%s/DiskDescriptor.xml", path) < 0)
|
2019-01-31 18:41:29 +00:00
|
|
|
return -1;
|
2016-04-11 16:16:25 +00:00
|
|
|
|
|
|
|
if (virFileRemove(desc, 0, 0) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("refresh ploop failed:"
|
2016-04-29 18:22:36 +00:00
|
|
|
" unable to delete DiskDescriptor.xml"));
|
2019-01-31 18:41:29 +00:00
|
|
|
return -1;
|
2016-04-11 16:16:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
refresh_tool = virFindFileInPath("ploop");
|
|
|
|
if (!refresh_tool) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("unable to find ploop, please install ploop tools"));
|
2019-01-31 18:41:29 +00:00
|
|
|
return -1;
|
2016-04-11 16:16:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cmd = virCommandNewArgList(refresh_tool, "restore-descriptor",
|
|
|
|
path, NULL);
|
|
|
|
virCommandAddArgFormat(cmd, "%s/root.hds", path);
|
2019-01-31 18:41:29 +00:00
|
|
|
return virCommandRun(cmd, NULL);
|
2016-04-11 16:16:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-07-28 12:39:09 +00:00
|
|
|
/**
|
|
|
|
* 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;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj = NULL;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2014-07-28 12:39:09 +00:00
|
|
|
virStorageBackendPtr backend;
|
2016-06-15 18:48:30 +00:00
|
|
|
virObjectEventPtr event = NULL;
|
2014-07-28 12:39:09 +00:00
|
|
|
|
2016-04-11 16:16:25 +00:00
|
|
|
if (cbdata->vol_path) {
|
|
|
|
if (virStorageBackendPloopRestoreDesc(cbdata->vol_path) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2017-10-07 11:24:24 +00:00
|
|
|
if (!(obj = virStoragePoolObjFindByName(driver->pools,
|
2017-05-08 15:05:12 +00:00
|
|
|
cbdata->pool_name)))
|
2014-07-28 12:39:09 +00:00
|
|
|
goto cleanup;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2014-07-28 12:39:09 +00:00
|
|
|
|
2017-11-06 20:22:07 +00:00
|
|
|
/* If some thread is building a new volume in the pool, then we cannot
|
|
|
|
* clear out all vols and refresh the pool. So we'll just pass. */
|
|
|
|
if (virStoragePoolObjGetAsyncjobs(obj) > 0) {
|
|
|
|
VIR_DEBUG("Asyncjob in process, cannot refresh storage pool");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (!(backend = virStorageBackendForType(def->type)))
|
2014-07-28 12:39:09 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2019-03-01 09:55:23 +00:00
|
|
|
if (storagePoolRefreshImpl(backend, obj, NULL) < 0)
|
2014-07-28 12:39:09 +00:00
|
|
|
VIR_DEBUG("Failed to refresh storage pool");
|
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
event = virStoragePoolEventRefreshNew(def->name, def->uuid);
|
2016-06-15 18:48:30 +00:00
|
|
|
|
2014-07-28 12:39:09 +00:00
|
|
|
cleanup:
|
2018-06-11 19:38:17 +00:00
|
|
|
virObjectEventStateQueue(driver->storageEventState, event);
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
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
|
2019-10-14 12:45:33 +00:00
|
|
|
virStorageVolFDStreamCloseCb(virStreamPtr st G_GNUC_UNUSED,
|
2014-07-28 12:39:09 +00:00
|
|
|
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
|
2017-05-08 15:05:12 +00:00
|
|
|
storageVolUpload(virStorageVolPtr vol,
|
2013-04-23 12:50:18 +00:00
|
|
|
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;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj = NULL;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStorageVolDefPtr voldef = NULL;
|
2014-07-28 12:39:09 +00:00
|
|
|
virStorageVolStreamInfoPtr cbdata = NULL;
|
2018-08-18 16:42:07 +00:00
|
|
|
int rc;
|
2009-07-14 15:24:42 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
2016-04-08 13:41:18 +00:00
|
|
|
virCheckFlags(VIR_STORAGE_VOL_UPLOAD_SPARSE_STREAM, -1);
|
2009-07-14 15:24:42 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(voldef = virStorageVolDefFromVol(vol, &obj, &backend)))
|
2014-06-05 11:29:37 +00:00
|
|
|
return -1;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2009-07-14 15:24:42 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStorageVolUploadEnsureACL(vol->conn, def, voldef) < 0)
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2013-04-23 10:56:22 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (voldef->in_use) {
|
2014-04-16 13:16:20 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still in use."),
|
2017-05-08 15:05:12 +00:00
|
|
|
voldef->name);
|
2014-04-16 13:16:20 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (voldef->building) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still being allocated."),
|
2017-05-08 15:05:12 +00:00
|
|
|
voldef->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
|
|
|
|
2016-06-23 00:28:09 +00:00
|
|
|
/* Use the callback routine in order to
|
2014-07-28 12:39:09 +00:00
|
|
|
* 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.
|
|
|
|
*/
|
2019-10-20 11:49:46 +00:00
|
|
|
if (VIR_ALLOC(cbdata) < 0)
|
2016-06-23 00:28:09 +00:00
|
|
|
goto cleanup;
|
2019-10-20 11:49:46 +00:00
|
|
|
cbdata->pool_name = g_strdup(def->name);
|
|
|
|
if (voldef->type == VIR_STORAGE_VOL_PLOOP)
|
|
|
|
cbdata->vol_path = g_strdup(voldef->target.path);
|
2014-07-28 12:39:09 +00:00
|
|
|
|
2018-08-18 16:42:07 +00:00
|
|
|
virStoragePoolObjIncrAsyncjobs(obj);
|
|
|
|
voldef->in_use++;
|
2018-08-19 06:26:04 +00:00
|
|
|
virObjectUnlock(obj);
|
2018-08-18 16:42:07 +00:00
|
|
|
|
|
|
|
rc = backend->uploadVol(obj, voldef, stream, offset, length, flags);
|
|
|
|
|
2018-08-19 06:26:04 +00:00
|
|
|
virObjectLock(obj);
|
2018-08-18 16:42:07 +00:00
|
|
|
voldef->in_use--;
|
|
|
|
virStoragePoolObjDecrAsyncjobs(obj);
|
|
|
|
|
|
|
|
if (rc < 0)
|
2014-12-03 15:01:32 +00:00
|
|
|
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
|
|
|
|
*/
|
2016-06-23 22:40:00 +00:00
|
|
|
virFDStreamSetInternalCloseCb(stream,
|
|
|
|
virStorageVolFDStreamCloseCb,
|
|
|
|
cbdata, NULL);
|
|
|
|
cbdata = NULL;
|
2018-08-18 16:42:07 +00:00
|
|
|
ret = 0;
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
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
|
2017-05-08 15:05:12 +00:00
|
|
|
storageVolResize(virStorageVolPtr vol,
|
2013-04-23 12:50:18 +00:00
|
|
|
unsigned long long capacity,
|
|
|
|
unsigned int flags)
|
2012-01-30 07:40:00 +00:00
|
|
|
{
|
|
|
|
virStorageBackendPtr backend;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj = NULL;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStorageVolDefPtr voldef = 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
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(voldef = virStorageVolDefFromVol(vol, &obj, &backend)))
|
2014-06-05 11:29:37 +00:00
|
|
|
return -1;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2012-01-30 07:40:00 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStorageVolResizeEnsureACL(vol->conn, def, voldef) < 0)
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2013-04-23 10:56:22 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (voldef->in_use) {
|
2014-04-16 13:16:20 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still in use."),
|
2017-05-08 15:05:12 +00:00
|
|
|
voldef->name);
|
2014-04-16 13:16:20 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (voldef->building) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still being allocated."),
|
2017-05-08 15:05:12 +00:00
|
|
|
voldef->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)
|
2017-05-08 15:05:12 +00:00
|
|
|
abs_capacity = voldef->target.capacity - MIN(capacity, voldef->target.capacity);
|
2015-05-27 14:33:22 +00:00
|
|
|
else
|
2017-05-08 15:05:12 +00:00
|
|
|
abs_capacity = voldef->target.capacity + capacity;
|
2012-01-30 07:40:00 +00:00
|
|
|
flags &= ~VIR_STORAGE_VOL_RESIZE_DELTA;
|
|
|
|
} else {
|
|
|
|
abs_capacity = capacity;
|
|
|
|
}
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (abs_capacity < voldef->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
|
|
|
}
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (abs_capacity < voldef->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)
|
2017-05-08 15:05:12 +00:00
|
|
|
delta = abs_capacity - voldef->target.allocation;
|
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
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (delta > 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
|
|
|
}
|
|
|
|
|
2018-01-26 13:31:58 +00:00
|
|
|
if (backend->resizeVol(obj, voldef, abs_capacity, flags) < 0)
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2012-01-30 07:40:00 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
voldef->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) {
|
2017-05-08 15:05:12 +00:00
|
|
|
voldef->target.allocation = abs_capacity;
|
2017-05-08 16:41:11 +00:00
|
|
|
def->allocation += delta;
|
|
|
|
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:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
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
|
2017-05-08 15:05:12 +00:00
|
|
|
storageVolWipePattern(virStorageVolPtr vol,
|
2013-04-23 12:50:18 +00:00
|
|
|
unsigned int algorithm,
|
|
|
|
unsigned int flags)
|
2010-02-23 03:13:18 +00:00
|
|
|
{
|
2014-07-07 14:50:11 +00:00
|
|
|
virStorageBackendPtr backend;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj = NULL;
|
|
|
|
virStorageVolDefPtr voldef = NULL;
|
2018-08-18 16:42:07 +00:00
|
|
|
int rc;
|
2010-02-23 03:13:18 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(voldef = virStorageVolDefFromVol(vol, &obj, &backend)))
|
2014-06-05 11:29:37 +00:00
|
|
|
return -1;
|
2010-02-23 03:13:18 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStorageVolWipePatternEnsureACL(vol->conn,
|
|
|
|
virStoragePoolObjGetDef(obj),
|
|
|
|
voldef) < 0)
|
2014-03-03 14:47:32 +00:00
|
|
|
goto cleanup;
|
2013-04-23 10:56:22 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (voldef->in_use) {
|
2014-04-16 13:16:20 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still in use."),
|
2017-05-08 15:05:12 +00:00
|
|
|
voldef->name);
|
2014-04-16 13:16:20 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (voldef->building) {
|
2012-07-18 11:38:29 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("volume '%s' is still being allocated."),
|
2017-05-08 15:05:12 +00:00
|
|
|
voldef->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
|
|
|
|
2018-08-18 16:42:07 +00:00
|
|
|
virStoragePoolObjIncrAsyncjobs(obj);
|
|
|
|
voldef->in_use++;
|
2018-08-19 06:26:04 +00:00
|
|
|
virObjectUnlock(obj);
|
2018-08-18 16:42:07 +00:00
|
|
|
|
|
|
|
rc = backend->wipeVol(obj, voldef, algorithm, flags);
|
|
|
|
|
2018-08-19 06:26:04 +00:00
|
|
|
virObjectLock(obj);
|
2018-08-18 16:42:07 +00:00
|
|
|
voldef->in_use--;
|
|
|
|
virStoragePoolObjDecrAsyncjobs(obj);
|
|
|
|
|
|
|
|
if (rc < 0)
|
2015-12-17 12:30:03 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2019-02-28 16:35:14 +00:00
|
|
|
/* For local volumes, Instead of using the refreshVol, since
|
|
|
|
* much changes on the target volume, let's update using the
|
|
|
|
* same function as refreshPool would use when it discovers a
|
|
|
|
* volume. The only failure to capture is -1, we can ignore
|
|
|
|
* -2. */
|
|
|
|
if ((backend->type == VIR_STORAGE_POOL_DIR ||
|
|
|
|
backend->type == VIR_STORAGE_POOL_FS ||
|
|
|
|
backend->type == VIR_STORAGE_POOL_NETFS ||
|
|
|
|
backend->type == VIR_STORAGE_POOL_VSTORAGE) &&
|
|
|
|
virStorageBackendRefreshVolTargetUpdate(voldef) == -1)
|
2015-12-17 12:30:03 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
2010-02-23 03:13:18 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2010-02-23 03:13:18 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-01-09 16:05:03 +00:00
|
|
|
static int
|
2017-05-08 15:05:12 +00:00
|
|
|
storageVolWipe(virStorageVolPtr vol,
|
2013-04-23 12:50:18 +00:00
|
|
|
unsigned int flags)
|
2012-01-09 16:05:03 +00:00
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
return storageVolWipePattern(vol, 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
|
2017-05-08 15:05:12 +00:00
|
|
|
storageVolGetInfoFlags(virStorageVolPtr vol,
|
2016-11-29 15:44:36 +00:00
|
|
|
virStorageVolInfoPtr info,
|
|
|
|
unsigned int flags)
|
2014-03-18 08:15:36 +00:00
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageBackendPtr backend;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStorageVolDefPtr voldef;
|
2008-12-04 21:39:45 +00:00
|
|
|
int ret = -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2016-11-29 15:44:36 +00:00
|
|
|
virCheckFlags(VIR_STORAGE_VOL_GET_PHYSICAL, -1);
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(voldef = virStorageVolDefFromVol(vol, &obj, &backend)))
|
2014-06-05 11:29:37 +00:00
|
|
|
return -1;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStorageVolGetInfoFlagsEnsureACL(vol->conn,
|
|
|
|
virStoragePoolObjGetDef(obj),
|
|
|
|
voldef) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
if (backend->refreshVol &&
|
2018-01-26 13:31:58 +00:00
|
|
|
backend->refreshVol(obj, voldef) < 0)
|
2008-12-04 21:39:45 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
|
|
|
memset(info, 0, sizeof(*info));
|
2017-05-08 15:05:12 +00:00
|
|
|
info->type = voldef->type;
|
|
|
|
info->capacity = voldef->target.capacity;
|
2016-11-29 15:44:36 +00:00
|
|
|
if (flags & VIR_STORAGE_VOL_GET_PHYSICAL)
|
2017-05-08 15:05:12 +00:00
|
|
|
info->allocation = voldef->target.physical;
|
2016-11-29 15:44:36 +00:00
|
|
|
else
|
2017-05-08 15:05:12 +00:00
|
|
|
info->allocation = voldef->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:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
2008-12-04 21:39:45 +00:00
|
|
|
return ret;
|
2008-02-20 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2016-11-29 15:44:36 +00:00
|
|
|
|
|
|
|
static int
|
2017-05-08 15:05:12 +00:00
|
|
|
storageVolGetInfo(virStorageVolPtr vol,
|
2016-11-29 15:44:36 +00:00
|
|
|
virStorageVolInfoPtr info)
|
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
return storageVolGetInfoFlags(vol, info, 0);
|
2016-11-29 15:44:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
static char *
|
2017-05-08 15:05:12 +00:00
|
|
|
storageVolGetXMLDesc(virStorageVolPtr vol,
|
2013-04-23 12:50:18 +00:00
|
|
|
unsigned int flags)
|
2011-07-06 22:51:23 +00:00
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def;
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageBackendPtr backend;
|
2017-05-08 15:05:12 +00:00
|
|
|
virStorageVolDefPtr voldef;
|
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);
|
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(voldef = virStorageVolDefFromVol(vol, &obj, &backend)))
|
2014-06-05 11:29:37 +00:00
|
|
|
return NULL;
|
2017-05-08 16:41:11 +00:00
|
|
|
def = virStoragePoolObjGetDef(obj);
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStorageVolGetXMLDescEnsureACL(vol->conn, def, voldef) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2009-04-03 14:15:30 +00:00
|
|
|
if (backend->refreshVol &&
|
2018-01-26 13:31:58 +00:00
|
|
|
backend->refreshVol(obj, voldef) < 0)
|
2009-04-03 14:15:30 +00:00
|
|
|
goto cleanup;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
ret = virStorageVolDefFormat(def, voldef);
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
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 *
|
2017-05-08 15:05:12 +00:00
|
|
|
storageVolGetPath(virStorageVolPtr vol)
|
2014-03-18 08:15:36 +00:00
|
|
|
{
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjPtr obj;
|
|
|
|
virStorageVolDefPtr voldef;
|
2008-12-04 21:39:45 +00:00
|
|
|
char *ret = NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 15:05:12 +00:00
|
|
|
if (!(voldef = virStorageVolDefFromVol(vol, &obj, NULL)))
|
2014-06-05 11:29:37 +00:00
|
|
|
return NULL;
|
2008-02-20 15:34:52 +00:00
|
|
|
|
2017-05-08 16:41:11 +00:00
|
|
|
if (virStorageVolGetPathEnsureACL(vol->conn, virStoragePoolObjGetDef(obj),
|
|
|
|
voldef) < 0)
|
2013-04-23 10:56:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2019-10-18 11:27:03 +00:00
|
|
|
ret = g_strdup(voldef->target.path);
|
2008-12-04 21:39:45 +00:00
|
|
|
|
2014-03-25 06:52:40 +00:00
|
|
|
cleanup:
|
2017-10-08 13:09:09 +00:00
|
|
|
virStoragePoolObjEndAPI(&obj);
|
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
|
|
|
{
|
|
|
|
virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);
|
|
|
|
|
2013-04-23 10:56:22 +00:00
|
|
|
if (virConnectListAllStoragePoolsEnsureACL(conn) < 0)
|
2017-11-24 14:32:38 +00:00
|
|
|
return -1;
|
2012-09-04 15:16:27 +00:00
|
|
|
|
2017-11-24 14:32:38 +00:00
|
|
|
return virStoragePoolObjListExport(conn, driver->pools, pools,
|
|
|
|
virConnectListAllStoragePoolsCheckACL,
|
|
|
|
flags);
|
2012-09-04 15:16:27 +00:00
|
|
|
}
|
|
|
|
|
2016-06-15 18:48:30 +00:00
|
|
|
static int
|
|
|
|
storageConnectStoragePoolEventRegisterAny(virConnectPtr conn,
|
|
|
|
virStoragePoolPtr pool,
|
|
|
|
int eventID,
|
|
|
|
virConnectStoragePoolEventGenericCallback callback,
|
|
|
|
void *opaque,
|
|
|
|
virFreeCallback freecb)
|
|
|
|
{
|
|
|
|
int callbackID = -1;
|
|
|
|
|
|
|
|
if (virConnectStoragePoolEventRegisterAnyEnsureACL(conn) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virStoragePoolEventStateRegisterID(conn, driver->storageEventState,
|
|
|
|
pool, eventID, callback,
|
|
|
|
opaque, freecb, &callbackID) < 0)
|
|
|
|
callbackID = -1;
|
|
|
|
cleanup:
|
|
|
|
return callbackID;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
storageConnectStoragePoolEventDeregisterAny(virConnectPtr conn,
|
|
|
|
int callbackID)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (virConnectStoragePoolEventDeregisterAnyEnsureACL(conn) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virObjectEventStateDeregisterID(conn,
|
|
|
|
driver->storageEventState,
|
2017-06-14 11:32:15 +00:00
|
|
|
callbackID, true) < 0)
|
2016-06-15 18:48:30 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-02 22:15:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* virStoragePoolObjFindPoolByUUID
|
|
|
|
* @uuid: The uuid to lookup
|
|
|
|
*
|
|
|
|
* Using the passed @uuid, search the driver pools for a matching uuid.
|
|
|
|
* If found, then lock the pool
|
|
|
|
*
|
|
|
|
* Returns NULL if pool is not found or a locked pool object pointer
|
|
|
|
*/
|
|
|
|
virStoragePoolObjPtr
|
|
|
|
virStoragePoolObjFindPoolByUUID(const unsigned char *uuid)
|
|
|
|
{
|
2017-11-24 14:32:38 +00:00
|
|
|
return virStoragePoolObjFindByUUID(driver->pools, uuid);
|
2015-11-02 22:15:41 +00:00
|
|
|
}
|
2016-06-21 22:17:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* virStoragePoolObjBuildTempFilePath
|
2017-05-08 15:05:12 +00:00
|
|
|
* @obj: pool object pointer
|
2016-06-21 22:17:51 +00:00
|
|
|
* @vol: volume definition
|
|
|
|
*
|
|
|
|
* Generate a name for a temporary file using the driver stateDir
|
|
|
|
* as a path, the pool name, and the volume name to be used as input
|
|
|
|
* for a mkostemp
|
|
|
|
*
|
|
|
|
* Returns a string pointer on success, NULL on failure
|
|
|
|
*/
|
|
|
|
char *
|
2017-05-08 15:05:12 +00:00
|
|
|
virStoragePoolObjBuildTempFilePath(virStoragePoolObjPtr obj,
|
|
|
|
virStorageVolDefPtr voldef)
|
2016-06-21 22:17:51 +00:00
|
|
|
|
|
|
|
{
|
2017-05-08 16:41:11 +00:00
|
|
|
virStoragePoolDefPtr def = virStoragePoolObjGetDef(obj);
|
2016-06-21 22:17:51 +00:00
|
|
|
char *tmp = NULL;
|
|
|
|
|
|
|
|
ignore_value(virAsprintf(&tmp, "%s/%s.%s.secret.XXXXXX",
|
2017-05-08 16:41:11 +00:00
|
|
|
driver->stateDir, def->name, voldef->name));
|
2016-06-21 22:17:51 +00:00
|
|
|
return tmp;
|
|
|
|
}
|
2018-01-26 11:21:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
static virStorageDriver storageDriver = {
|
|
|
|
.name = "storage",
|
|
|
|
.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 */
|
|
|
|
.connectStoragePoolEventRegisterAny = storageConnectStoragePoolEventRegisterAny, /* 2.0.0 */
|
|
|
|
.connectStoragePoolEventDeregisterAny = storageConnectStoragePoolEventDeregisterAny, /* 2.0.0 */
|
|
|
|
.connectFindStoragePoolSources = storageConnectFindStoragePoolSources, /* 0.4.0 */
|
2019-02-07 17:03:08 +00:00
|
|
|
.connectGetStoragePoolCapabilities = storageConnectGetStoragePoolCapabilities, /* 5.2.0 */
|
2018-01-26 11:21:09 +00:00
|
|
|
.storagePoolLookupByName = storagePoolLookupByName, /* 0.4.0 */
|
|
|
|
.storagePoolLookupByUUID = storagePoolLookupByUUID, /* 0.4.0 */
|
|
|
|
.storagePoolLookupByVolume = storagePoolLookupByVolume, /* 0.4.0 */
|
2018-01-25 09:35:52 +00:00
|
|
|
.storagePoolLookupByTargetPath = storagePoolLookupByTargetPath, /* 4.1.0 */
|
2018-01-26 11:21:09 +00:00
|
|
|
.storagePoolCreateXML = storagePoolCreateXML, /* 0.4.0 */
|
|
|
|
.storagePoolDefineXML = storagePoolDefineXML, /* 0.4.0 */
|
|
|
|
.storagePoolBuild = storagePoolBuild, /* 0.4.0 */
|
|
|
|
.storagePoolUndefine = storagePoolUndefine, /* 0.4.0 */
|
|
|
|
.storagePoolCreate = storagePoolCreate, /* 0.4.0 */
|
|
|
|
.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 */
|
|
|
|
.storagePoolNumOfVolumes = storagePoolNumOfVolumes, /* 0.4.0 */
|
|
|
|
.storagePoolListVolumes = storagePoolListVolumes, /* 0.4.0 */
|
|
|
|
.storagePoolListAllVolumes = storagePoolListAllVolumes, /* 0.10.2 */
|
|
|
|
|
|
|
|
.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 */
|
|
|
|
.storageVolGetInfoFlags = storageVolGetInfoFlags, /* 3.0.0 */
|
|
|
|
.storageVolGetXMLDesc = storageVolGetXMLDesc, /* 0.4.0 */
|
|
|
|
.storageVolGetPath = storageVolGetPath, /* 0.4.0 */
|
|
|
|
.storageVolResize = storageVolResize, /* 0.9.10 */
|
|
|
|
|
|
|
|
.storagePoolIsActive = storagePoolIsActive, /* 0.7.3 */
|
|
|
|
.storagePoolIsPersistent = storagePoolIsPersistent, /* 0.7.3 */
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2018-01-26 11:16:00 +00:00
|
|
|
static virHypervisorDriver storageHypervisorDriver = {
|
|
|
|
.name = "storage",
|
|
|
|
.connectOpen = storageConnectOpen, /* 4.1.0 */
|
|
|
|
.connectClose = storageConnectClose, /* 4.1.0 */
|
|
|
|
.connectIsEncrypted = storageConnectIsEncrypted, /* 4.1.0 */
|
|
|
|
.connectIsSecure = storageConnectIsSecure, /* 4.1.0 */
|
|
|
|
.connectIsAlive = storageConnectIsAlive, /* 4.1.0 */
|
2019-01-10 12:23:26 +00:00
|
|
|
.connectGetCapabilities = storageConnectGetCapabilities, /* 5.2.0 */
|
2018-01-26 11:16:00 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static virConnectDriver storageConnectDriver = {
|
2018-03-28 09:53:31 +00:00
|
|
|
.localOnly = true,
|
2018-03-27 14:51:45 +00:00
|
|
|
.uriSchemes = (const char *[]){ "storage", NULL },
|
2018-01-26 11:16:00 +00:00
|
|
|
.hypervisorDriver = &storageHypervisorDriver,
|
|
|
|
.storageDriver = &storageDriver,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2018-01-26 11:21:09 +00:00
|
|
|
static virStateDriver stateDriver = {
|
|
|
|
.name = "storage",
|
|
|
|
.stateInitialize = storageStateInitialize,
|
|
|
|
.stateCleanup = storageStateCleanup,
|
|
|
|
.stateReload = storageStateReload,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
storageRegisterFull(bool allbackends)
|
|
|
|
{
|
2018-01-26 11:16:00 +00:00
|
|
|
if (virRegisterConnectDriver(&storageConnectDriver, false) < 0)
|
|
|
|
return -1;
|
2018-01-26 11:21:09 +00:00
|
|
|
if (virStorageBackendDriversRegister(allbackends) < 0)
|
|
|
|
return -1;
|
|
|
|
if (virSetSharedStorageDriver(&storageDriver) < 0)
|
|
|
|
return -1;
|
|
|
|
if (virRegisterStateDriver(&stateDriver) < 0)
|
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
storageRegister(void)
|
|
|
|
{
|
|
|
|
return storageRegisterFull(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
storageRegisterAll(void)
|
|
|
|
{
|
|
|
|
return storageRegisterFull(true);
|
|
|
|
}
|