Devel
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- 20 participants
- 40105 discussions
[libvirt] libvirt [PATCHv2 1/2] Refactor ESX storage driver to implement facade pattern
by Ata E Husain Bohra 27 Nov '12
by Ata E Husain Bohra 27 Nov '12
27 Nov '12
The patch refactors the current ESX storage driver due to following reasons:
1. Given most of the public APIs exposed by the storage driver in Libvirt
remains same, ESX storage driver should not implement logic specific
for only one supported format (current implementation only supports VMFS).
2. Decoupling interface from specific storage implementation gives us an
extensible design to hook implementation for other supported storage
formats.
This patch refactors the current driver to implement it as a facade pattern i.e.
the driver exposes all the public libvirt APIs, but uses backend drivers to get
the required task done. The backend drivers provide implementation specific to
the type of storage device.
File changes:
------------------
esx_storage_driver.c ----> esx_storage_driver.c (base storage driver)
|
|---> esx_storage_backend_vmfs.c (VMFS backend)
One of the task base storage driver need to do is to decide which backend
driver needs to be invoked for a given request. This approach extends
virStoragePool and virStorageVol to store extra parameters:
1. privateData: stores pointer to respective backend storage driver.
2. privateDataFreeFunc: stores cleanup function pointer.
virGetStoragePool and virGetStorageVol are modfiied to accept these extra
parameters as user params. virStoragePoolDispose and virStorageVolDispose
checks for cleanup operation if available.
---
daemon/remote.c | 6 +-
src/Makefile.am | 1 +
src/conf/storage_conf.c | 3 +-
src/datatypes.c | 25 +-
src/datatypes.h | 24 +-
src/esx/esx_driver.c | 6 +-
src/esx/esx_storage_backend_vmfs.c | 1491 ++++++++++++++++++++++++++++++++++++
src/esx/esx_storage_backend_vmfs.h | 30 +
src/esx/esx_storage_driver.c | 1319 +++++--------------------------
src/esx/esx_vi.c | 5 +-
src/esx/esx_vi.h | 3 +-
src/parallels/parallels_storage.c | 24 +-
src/remote/remote_driver.c | 6 +-
src/storage/storage_driver.c | 28 +-
src/test/test_driver.c | 30 +-
src/vbox/vbox_tmpl.c | 14 +-
16 files changed, 1843 insertions(+), 1172 deletions(-)
create mode 100644 src/esx/esx_storage_backend_vmfs.c
create mode 100644 src/esx/esx_storage_backend_vmfs.h
diff --git a/daemon/remote.c b/daemon/remote.c
index 340d07d..41b8ea8 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -4651,14 +4651,16 @@ get_nonnull_interface(virConnectPtr conn, remote_nonnull_interface iface)
static virStoragePoolPtr
get_nonnull_storage_pool(virConnectPtr conn, remote_nonnull_storage_pool pool)
{
- return virGetStoragePool(conn, pool.name, BAD_CAST pool.uuid);
+ return virGetStoragePool(conn, pool.name, BAD_CAST pool.uuid,
+ NULL, NULL);
}
static virStorageVolPtr
get_nonnull_storage_vol(virConnectPtr conn, remote_nonnull_storage_vol vol)
{
virStorageVolPtr ret;
- ret = virGetStorageVol(conn, vol.pool, vol.name, vol.key);
+ ret = virGetStorageVol(conn, vol.pool, vol.name, vol.key,
+ NULL, NULL);
return ret;
}
diff --git a/src/Makefile.am b/src/Makefile.am
index 1f32263..4026a15 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -493,6 +493,7 @@ ESX_DRIVER_SOURCES = \
esx/esx_interface_driver.c esx/esx_interface_driver.h \
esx/esx_network_driver.c esx/esx_network_driver.h \
esx/esx_storage_driver.c esx/esx_storage_driver.h \
+ esx/esx_storage_backend_vmfs.c esx/esx_storage_backend_vmfs.h \
esx/esx_device_monitor.c esx/esx_device_monitor.h \
esx/esx_secret_driver.c esx/esx_secret_driver.h \
esx/esx_nwfilter_driver.c esx/esx_nwfilter_driver.h \
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index 9a765d8..1c9934c 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -1981,7 +1981,8 @@ virStoragePoolList(virConnectPtr conn,
if (pools) {
if (!(pool = virGetStoragePool(conn,
poolobj->def->name,
- poolobj->def->uuid))) {
+ poolobj->def->uuid,
+ NULL, NULL))) {
virStoragePoolObjUnlock(poolobj);
goto cleanup;
}
diff --git a/src/datatypes.c b/src/datatypes.c
index ff7c524..eab7500 100644
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -379,6 +379,8 @@ virInterfaceDispose(void *obj)
* @conn: the hypervisor connection
* @name: pointer to the storage pool name
* @uuid: pointer to the uuid
+ * @void*: pointer to driver specific privateData
+ * @virFreeCallback: cleanup function pointer specfic to driver
*
* Lookup if the storage pool is already registered for that connection,
* if yes return a new pointer to it, if no allocate a new structure,
@@ -389,7 +391,8 @@ virInterfaceDispose(void *obj)
*/
virStoragePoolPtr
virGetStoragePool(virConnectPtr conn, const char *name,
- const unsigned char *uuid)
+ const unsigned char *uuid,
+ void *privateData, virFreeCallback func)
{
virStoragePoolPtr ret = NULL;
@@ -412,6 +415,10 @@ virGetStoragePool(virConnectPtr conn, const char *name,
ret->conn = virObjectRef(conn);
memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
+ /* set the driver specific data */
+ ret->privateData = privateData;
+ ret->privateDataFreeFunc = func;
+
return ret;
no_memory:
@@ -444,6 +451,10 @@ virStoragePoolDispose(void *obj)
VIR_FREE(pool->name);
virObjectUnref(pool->conn);
+
+ if (pool->privateDataFreeFunc) {
+ pool->privateDataFreeFunc(pool->privateData);
+ }
}
@@ -453,6 +464,8 @@ virStoragePoolDispose(void *obj)
* @pool: pool owning the volume
* @name: pointer to the storage vol name
* @key: pointer to unique key of the volume
+ * @void*: pointer to driver specific privateData
+ * @virFreeCallback: cleanup function pointer specfic to driver
*
* Lookup if the storage vol is already registered for that connection,
* if yes return a new pointer to it, if no allocate a new structure,
@@ -463,7 +476,7 @@ virStoragePoolDispose(void *obj)
*/
virStorageVolPtr
virGetStorageVol(virConnectPtr conn, const char *pool, const char *name,
- const char *key)
+ const char *key, void *privateData, virFreeCallback func)
{
virStorageVolPtr ret = NULL;
@@ -489,6 +502,10 @@ virGetStorageVol(virConnectPtr conn, const char *pool, const char *name,
ret->conn = virObjectRef(conn);
+ /* set driver specific data */
+ ret->privateData = privateData;
+ ret->privateDataFreeFunc = func;
+
return ret;
no_memory:
@@ -520,6 +537,10 @@ virStorageVolDispose(void *obj)
VIR_FREE(vol->name);
VIR_FREE(vol->pool);
virObjectUnref(vol->conn);
+
+ if (vol->privateDataFreeFunc) {
+ vol->privateDataFreeFunc(vol->privateData);
+ }
}
diff --git a/src/datatypes.h b/src/datatypes.h
index e4c8262..264d9f6 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -196,6 +196,13 @@ struct _virStoragePool {
virConnectPtr conn; /* pointer back to the connection */
char *name; /* the storage pool external name */
unsigned char uuid[VIR_UUID_BUFLEN]; /* the storage pool unique identifier */
+
+ /* Private data pointer which can be used by driver as they wish
+ * Cleanup function pointer can be hooked to provide custom cleanup
+ * operation.
+ */
+ void *privateData;
+ virFreeCallback privateDataFreeFunc;
};
/**
@@ -209,6 +216,13 @@ struct _virStorageVol {
char *pool; /* Pool name of owner */
char *name; /* the storage vol external name */
char *key; /* unique key for storage vol */
+
+ /* Private data pointer which can be used by driver as they wish
+ * Cleanup function pointer can be hooked to provide custom cleanup
+ * operation.
+ */
+ void *privateData;
+ virFreeCallback privateDataFreeFunc;
};
/**
@@ -293,12 +307,16 @@ virInterfacePtr virGetInterface(virConnectPtr conn,
const char *name,
const char *mac);
virStoragePoolPtr virGetStoragePool(virConnectPtr conn,
- const char *name,
- const unsigned char *uuid);
+ const char *name,
+ const unsigned char *uuid,
+ void *privateData,
+ virFreeCallback func);
virStorageVolPtr virGetStorageVol(virConnectPtr conn,
const char *pool,
const char *name,
- const char *key);
+ const char *key,
+ void *privateData,
+ virFreeCallback func);
virNodeDevicePtr virGetNodeDevice(virConnectPtr conn,
const char *name);
virSecretPtr virGetSecret(virConnectPtr conn,
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index 56f31bb..0374a98 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -163,7 +163,8 @@ esxParseVMXFileName(const char *fileName, void *opaque)
datastoreName = NULL;
if (esxVI_LookupDatastoreHostMount(data->ctx, datastore->obj,
- &hostMount) < 0 ||
+ &hostMount,
+ esxVI_Occurrence_RequiredItem) < 0 ||
esxVI_GetStringValue(datastore, "summary.name", &datastoreName,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
@@ -307,7 +308,8 @@ esxFormatVMXFileName(const char *fileName, void *opaque)
if (esxVI_LookupDatastoreByName(data->ctx, datastoreName, NULL, &datastore,
esxVI_Occurrence_RequiredItem) < 0 ||
esxVI_LookupDatastoreHostMount(data->ctx, datastore->obj,
- &hostMount) < 0) {
+ &hostMount,
+ esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
diff --git a/src/esx/esx_storage_backend_vmfs.c b/src/esx/esx_storage_backend_vmfs.c
new file mode 100644
index 0000000..d934e57
--- /dev/null
+++ b/src/esx/esx_storage_backend_vmfs.c
@@ -0,0 +1,1491 @@
+
+/*
+ * esx_storage_backend_vmfs.c: ESX backend storage driver for
+ * managing VMFS datastores
+ *
+ * Copyright (C) 2012 Ata E Husain Bohra <ata.husain(a)hotmail.com>
+ *
+ * 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
+ * License along with this library; If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "internal.h"
+#include "md5.h"
+#include "util.h"
+#include "memory.h"
+#include "logging.h"
+#include "uuid.h"
+
+#include "storage_conf.h"
+#include "storage_file.h"
+#include "esx_storage_backend_vmfs.h"
+#include "esx_private.h"
+#include "esx_vi.h"
+#include "esx_vi_methods.h"
+#include "esx_util.h"
+
+#define VIR_FROM_THIS VIR_FROM_STORAGE
+
+/*
+ * The UUID of a storage pool is the MD5 sum of it's mount path. Therefore,
+ * verify that UUID and MD5 sum match in size, because we rely on that.
+ */
+verify(MD5_DIGEST_SIZE == VIR_UUID_BUFLEN);
+
+
+
+static int
+esxStorageBackendVMFSPoolLookupType(virConnectPtr conn, const char *poolName,
+ int *poolType)
+{
+ int result = -1;
+ esxPrivate *priv = conn->storagePrivateData;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+ esxVI_DatastoreInfo *datastoreInfo = NULL;
+
+ if (esxVI_String_AppendValueToList(&propertyNameList, "info") < 0 ||
+ esxVI_LookupDatastoreByName(priv->primary, poolName,
+ propertyNameList, &datastore,
+ esxVI_Occurrence_OptionalItem) < 0) {
+ goto cleanup;
+ }
+
+ if (datastore == NULL) {
+ /* not found, let the base driver handle the error reporting */
+ goto cleanup;
+ }
+
+ for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name, "info")) {
+ if (esxVI_DatastoreInfo_CastFromAnyType(dynamicProperty->val,
+ &datastoreInfo) < 0) {
+ goto cleanup;
+ }
+
+ break;
+ }
+ }
+
+ if (esxVI_LocalDatastoreInfo_DynamicCast(datastoreInfo) != NULL) {
+ *poolType = VIR_STORAGE_POOL_DIR;
+ } else if (esxVI_NasDatastoreInfo_DynamicCast(datastoreInfo) != NULL) {
+ *poolType = VIR_STORAGE_POOL_NETFS;
+ } else if (esxVI_VmfsDatastoreInfo_DynamicCast(datastoreInfo) != NULL) {
+ *poolType = VIR_STORAGE_POOL_FS;
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("DatastoreInfo has unexpected type"));
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastore);
+ esxVI_DatastoreInfo_Free(&datastoreInfo);
+
+ return result;
+}
+
+
+
+
+static int
+esxStorageBackendVMFSNumberOfStoragePools(virConnectPtr conn)
+{
+ esxPrivate *priv = conn->storagePrivateData;
+ esxVI_ObjectContent *datastoreList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ int count = 0;
+
+ if (esxVI_LookupDatastoreList(priv->primary, NULL, &datastoreList) < 0) {
+ goto cleanup;
+ }
+
+ for (datastore = datastoreList; datastore != NULL;
+ datastore = datastore->_next) {
+ ++count;
+ }
+
+ cleanup:
+ esxVI_ObjectContent_Free(&datastoreList);
+
+ return count;
+}
+
+static int
+esxStorageBackendVMFSListStoragePools(virConnectPtr conn,
+ char **const names,
+ const int maxnames)
+{
+ esxPrivate *priv = conn->storagePrivateData;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+ esxVI_ObjectContent *datastoreList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ int count = 0;
+ int i = 0;
+ bool success = false;
+
+ if (maxnames == 0) {
+ return 0;
+ }
+
+ if (esxVI_String_AppendValueToList(&propertyNameList,
+ "summary.name") < 0 ||
+ esxVI_LookupDatastoreList(priv->primary, propertyNameList,
+ &datastoreList) < 0) {
+ goto cleanup;
+ }
+
+ for (datastore = datastoreList; datastore != NULL;
+ datastore = datastore->_next) {
+ for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name, "summary.name")) {
+ if (esxVI_AnyType_ExpectType(dynamicProperty->val,
+ esxVI_Type_String) < 0) {
+ goto cleanup;
+ }
+
+ names[count] = strdup(dynamicProperty->val->string);
+
+ if (names[count] == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ ++count;
+ break;
+ } else {
+ VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+ }
+ }
+ }
+
+ success = true;
+
+ cleanup:
+ if (! success) {
+ for (i = 0; i < count; ++i) {
+ VIR_FREE(names[i]);
+ }
+
+ count = -1;
+ }
+
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastoreList);
+
+ return count;
+}
+
+static virStoragePoolPtr
+esxStorageBackendVMFSPoolLookupByName(virConnectPtr conn,
+ const char *name)
+{
+ esxPrivate *priv = conn->storagePrivateData;
+ esxVI_ObjectContent *datastore = NULL;
+ esxVI_DatastoreHostMount *hostMount = NULL;
+ /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
+ unsigned char md5[MD5_DIGEST_SIZE];
+ virStoragePoolPtr pool = NULL;
+
+ virCheckNonNullArgReturn(name, NULL);
+
+ if (esxVI_LookupDatastoreByName(priv->primary, name, NULL, &datastore,
+ esxVI_Occurrence_OptionalItem) < 0) {
+ goto cleanup;
+ }
+
+ if (datastore == NULL) {
+ /* not found, let the base driver handle the error reporting */
+ goto cleanup;
+ }
+
+ /*
+ * Datastores don't have a UUID, but we can use the 'host.mountInfo.path'
+ * property as source for a UUID. The mount path is unique per host and
+ * cannot change during the lifetime of the datastore.
+ *
+ * The MD5 sum of the mount path can be used as UUID, assuming MD5 is
+ * considered to be collision-free enough for this use case.
+ */
+ if (esxVI_LookupDatastoreHostMount(priv->primary, datastore->obj,
+ &hostMount, esxVI_Occurrence_OptionalItem) < 0) {
+ goto cleanup;
+ }
+
+ if (hostMount == NULL) {
+ /* routine called by base storage driver to determine correct backend
+ * driver, leave error reporting to the base driver
+ */
+ goto cleanup;
+ }
+
+ md5_buffer(hostMount->mountInfo->path,
+ strlen(hostMount->mountInfo->path), md5);
+
+ pool = virGetStoragePool(conn, name, md5,
+ &esxStorageBackendVMFSDrv, NULL);
+
+ cleanup:
+ esxVI_ObjectContent_Free(&datastore);
+ esxVI_DatastoreHostMount_Free(&hostMount);
+
+ return pool;
+}
+
+static virStoragePoolPtr
+esxStorageBackendVMFSPoolLookupByUUID(virConnectPtr conn,
+ const unsigned char *uuid)
+{
+ esxPrivate *priv = conn->storagePrivateData;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastoreList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ esxVI_DatastoreHostMount *hostMount = NULL;
+ unsigned char md5[MD5_DIGEST_SIZE]; /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
+ char *name = NULL;
+ virStoragePoolPtr pool = NULL;
+
+
+ if (esxVI_String_AppendValueToList(&propertyNameList, "summary.name") < 0 ||
+ esxVI_LookupDatastoreList(priv->primary, propertyNameList,
+ &datastoreList) < 0) {
+ goto cleanup;
+ }
+
+ for (datastore = datastoreList; datastore != NULL;
+ datastore = datastore->_next) {
+ esxVI_DatastoreHostMount_Free(&hostMount);
+ if (esxVI_LookupDatastoreHostMount(priv->primary, datastore->obj,
+ &hostMount, esxVI_Occurrence_OptionalItem) < 0) {
+ goto cleanup;
+ }
+
+ if (hostMount == NULL) {
+ /* it may happen that the storage pool belong to non VMFS type,
+ * leave error reporting to the base storage driver.
+ */
+ goto cleanup;
+ }
+
+ md5_buffer(hostMount->mountInfo->path,
+ strlen(hostMount->mountInfo->path), md5);
+
+ if (memcmp(uuid, md5, VIR_UUID_BUFLEN) == 0) {
+ break;
+ }
+ }
+
+ if (datastore == NULL) {
+ goto cleanup;
+ }
+
+ if (esxVI_GetStringValue(datastore, "summary.name", &name,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ pool = virGetStoragePool(conn, name, uuid,
+ &esxStorageBackendVMFSDrv, NULL);
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastoreList);
+ esxVI_DatastoreHostMount_Free(&hostMount);
+
+ return pool;
+}
+
+static int
+esxStorageBackendVMFSPoolRefresh(virStoragePoolPtr pool, unsigned int flags)
+{
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_ObjectContent *datastore = NULL;
+ int result = -1;
+
+ virCheckFlags(0, -1);
+
+ if (esxVI_LookupDatastoreByName(priv->primary, pool->name, NULL, &datastore,
+ esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_RefreshDatastore(priv->primary, datastore->obj) < 0) {
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ esxVI_ObjectContent_Free(&datastore);
+
+ return result;
+}
+
+
+static int
+esxStorageBackendVMFSPoolGetInfo(virStoragePoolPtr pool,
+ virStoragePoolInfoPtr info)
+{
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+ esxVI_Boolean accessible = esxVI_Boolean_Undefined;
+ int result = -1;
+
+ if (esxVI_String_AppendValueListToList(&propertyNameList,
+ "summary.accessible\0"
+ "summary.capacity\0"
+ "summary.freeSpace\0") < 0 ||
+ esxVI_LookupDatastoreByName(priv->primary, pool->name,
+ propertyNameList, &datastore,
+ esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_GetBoolean(datastore, "summary.accessible",
+ &accessible, esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ if (accessible == esxVI_Boolean_True) {
+ info->state = VIR_STORAGE_POOL_RUNNING;
+
+ for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name, "summary.capacity")) {
+ if (esxVI_AnyType_ExpectType(dynamicProperty->val,
+ esxVI_Type_Long) < 0) {
+ goto cleanup;
+ }
+
+ info->capacity = dynamicProperty->val->int64;
+ } else if (STREQ(dynamicProperty->name, "summary.freeSpace")) {
+ if (esxVI_AnyType_ExpectType(dynamicProperty->val,
+ esxVI_Type_Long) < 0) {
+ goto cleanup;
+ }
+
+ info->available = dynamicProperty->val->int64;
+ }
+ }
+
+ info->allocation = info->capacity - info->available;
+ } else {
+ info->state = VIR_STORAGE_POOL_INACCESSIBLE;
+ }
+
+ result = 0;
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastore);
+
+ return result;
+}
+
+static char *
+esxStorageBackendVMFSPoolGetXMLDesc(virStoragePoolPtr pool, unsigned int flags)
+{
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ esxVI_DatastoreHostMount *hostMount = NULL;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+ esxVI_Boolean accessible = esxVI_Boolean_Undefined;
+ virStoragePoolDef def;
+ esxVI_DatastoreInfo *info = NULL;
+ esxVI_NasDatastoreInfo *nasInfo = NULL;
+ char *xml = NULL;
+
+ virCheckFlags(0, NULL);
+
+ memset(&def, 0, sizeof(def));
+
+ if (esxVI_String_AppendValueListToList(&propertyNameList,
+ "summary.accessible\0"
+ "summary.capacity\0"
+ "summary.freeSpace\0"
+ "info\0") < 0 ||
+ esxVI_LookupDatastoreByName(priv->primary, pool->name,
+ propertyNameList, &datastore,
+ esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_GetBoolean(datastore, "summary.accessible",
+ &accessible, esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_LookupDatastoreHostMount(priv->primary, datastore->obj,
+ &hostMount, esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ def.name = pool->name;
+ memcpy(def.uuid, pool->uuid, VIR_UUID_BUFLEN);
+
+ def.target.path = hostMount->mountInfo->path;
+
+ if (accessible == esxVI_Boolean_True) {
+ for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name, "summary.capacity")) {
+ if (esxVI_AnyType_ExpectType(dynamicProperty->val,
+ esxVI_Type_Long) < 0) {
+ goto cleanup;
+ }
+
+ def.capacity = dynamicProperty->val->int64;
+ } else if (STREQ(dynamicProperty->name, "summary.freeSpace")) {
+ if (esxVI_AnyType_ExpectType(dynamicProperty->val,
+ esxVI_Type_Long) < 0) {
+ goto cleanup;
+ }
+
+ def.available = dynamicProperty->val->int64;
+ }
+ }
+
+ def.allocation = def.capacity - def.available;
+ }
+
+ for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name, "info")) {
+ if (esxVI_DatastoreInfo_CastFromAnyType(dynamicProperty->val,
+ &info) < 0) {
+ goto cleanup;
+ }
+
+ break;
+ }
+ }
+
+ /* See vSphere API documentation about HostDatastoreSystem for details */
+ if (esxVI_LocalDatastoreInfo_DynamicCast(info) != NULL) {
+ def.type = VIR_STORAGE_POOL_DIR;
+ } else if ((nasInfo = esxVI_NasDatastoreInfo_DynamicCast(info)) != NULL) {
+ if (VIR_ALLOC_N(def.source.hosts, 1) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ def.type = VIR_STORAGE_POOL_NETFS;
+ def.source.hosts[0].name = nasInfo->nas->remoteHost;
+ def.source.dir = nasInfo->nas->remotePath;
+
+ if (STRCASEEQ(nasInfo->nas->type, "NFS")) {
+ def.source.format = VIR_STORAGE_POOL_NETFS_NFS;
+ } else if (STRCASEEQ(nasInfo->nas->type, "CIFS")) {
+ def.source.format = VIR_STORAGE_POOL_NETFS_CIFS;
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Datastore has unexpected type '%s'"),
+ nasInfo->nas->type);
+ goto cleanup;
+ }
+ } else if (esxVI_VmfsDatastoreInfo_DynamicCast(info) != NULL) {
+ def.type = VIR_STORAGE_POOL_FS;
+ /*
+ * FIXME: I'm not sure how to represent the source and target of a
+ * VMFS based datastore in libvirt terms
+ */
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("DatastoreInfo has unexpected type"));
+ goto cleanup;
+ }
+
+ xml = virStoragePoolDefFormat(&def);
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastore);
+ esxVI_DatastoreHostMount_Free(&hostMount);
+ esxVI_DatastoreInfo_Free(&info);
+
+ return xml;
+}
+
+
+static int
+esxStorageBackendVMFSPoolNumberOfStorageVolumes(virStoragePoolPtr pool)
+{
+ bool success = false;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_HostDatastoreBrowserSearchResults *searchResultsList = NULL;
+ esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+ int count = 0;
+
+ if (esxVI_LookupDatastoreContentByDatastoreName(priv->primary, pool->name,
+ &searchResultsList) < 0) {
+ goto cleanup;
+ }
+
+ /* Interpret search result */
+ for (searchResults = searchResultsList; searchResults != NULL;
+ searchResults = searchResults->_next) {
+ for (fileInfo = searchResults->file; fileInfo != NULL;
+ fileInfo = fileInfo->_next) {
+ ++count;
+ }
+ }
+
+ success = true;
+
+ cleanup:
+ esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList);
+
+ return success ? count : -1;
+}
+
+static int
+esxStorageBackendVMFSPoolListStorageVolumes(virStoragePoolPtr pool,
+ char **const names,
+ int maxnames)
+
+{
+ bool success = false;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_HostDatastoreBrowserSearchResults *searchResultsList = NULL;
+ esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+ char *directoryAndFileName = NULL;
+ size_t length;
+ int count = 0;
+ int i;
+
+ if (names == NULL || maxnames < 0) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s", _("Invalid argument"));
+ return -1;
+ }
+
+ if (maxnames == 0) {
+ return 0;
+ }
+
+ if (esxVI_LookupDatastoreContentByDatastoreName(priv->primary, pool->name,
+ &searchResultsList) < 0) {
+ goto cleanup;
+ }
+
+ /* Interpret search result */
+ for (searchResults = searchResultsList; searchResults != NULL;
+ searchResults = searchResults->_next) {
+ VIR_FREE(directoryAndFileName);
+
+ if (esxUtil_ParseDatastorePath(searchResults->folderPath, NULL, NULL,
+ &directoryAndFileName) < 0) {
+ goto cleanup;
+ }
+
+ /* Strip trailing separators */
+ length = strlen(directoryAndFileName);
+
+ while (length > 0 && directoryAndFileName[length - 1] == '/') {
+ directoryAndFileName[length - 1] = '\0';
+ --length;
+ }
+
+ /* Build volume names */
+ for (fileInfo = searchResults->file; fileInfo != NULL;
+ fileInfo = fileInfo->_next) {
+ if (length < 1) {
+ names[count] = strdup(fileInfo->path);
+
+ if (names[count] == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ } else if (virAsprintf(&names[count], "%s/%s", directoryAndFileName,
+ fileInfo->path) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ ++count;
+ }
+ }
+
+ success = true;
+
+ cleanup:
+ if (! success) {
+ for (i = 0; i < count; ++i) {
+ VIR_FREE(names[i]);
+ }
+
+ count = -1;
+ }
+
+ esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList);
+ VIR_FREE(directoryAndFileName);
+
+ return count;
+
+}
+
+static virStorageVolPtr
+esxStorageBackendVMFSVolumeLookupByName(virStoragePoolPtr pool,
+ const char *name)
+{
+ virStorageVolPtr volume = NULL;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ char *datastorePath = NULL;
+ char *key = NULL;
+
+ if (virAsprintf(&datastorePath, "[%s] %s", pool->name, name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (esxVI_LookupStorageVolumeKeyByDatastorePath(priv->primary,
+ datastorePath, &key) < 0) {
+ goto cleanup;
+ }
+
+ volume = virGetStorageVol(pool->conn, pool->name, name, key,
+ &esxStorageBackendVMFSDrv, NULL);
+
+ cleanup:
+ VIR_FREE(datastorePath);
+ VIR_FREE(key);
+
+ return volume;
+}
+
+static virStorageVolPtr
+esxStorageBackendVMFSVolumeLookupByPath(virConnectPtr conn, const char *path)
+{
+ virStorageVolPtr volume = NULL;
+ esxPrivate *priv = conn->storagePrivateData;
+ char *datastoreName = NULL;
+ char *directoryAndFileName = NULL;
+ char *key = NULL;
+
+ if (esxUtil_ParseDatastorePath(path, &datastoreName, NULL,
+ &directoryAndFileName) < 0) {
+ goto cleanup;
+ }
+
+ if (esxVI_LookupStorageVolumeKeyByDatastorePath(priv->primary, path,
+ &key) < 0) {
+ goto cleanup;
+ }
+
+ volume = virGetStorageVol(conn, datastoreName, directoryAndFileName, key,
+ &esxStorageBackendVMFSDrv, NULL);
+
+ cleanup:
+ VIR_FREE(datastoreName);
+ VIR_FREE(directoryAndFileName);
+ VIR_FREE(key);
+
+ return volume;
+}
+
+
+
+static virStorageVolPtr
+esxStorageBackendVMFSVolumeLookupByKey(virConnectPtr conn, const char *key)
+{
+ virStorageVolPtr volume = NULL;
+ esxPrivate *priv = conn->storagePrivateData;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastoreList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ char *datastoreName = NULL;
+ esxVI_HostDatastoreBrowserSearchResults *searchResultsList = NULL;
+ esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL;
+ char *directoryAndFileName = NULL;
+ size_t length;
+ char *datastorePath = NULL;
+ char *volumeName = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+ char *uuid_string = NULL;
+ char key_candidate[VIR_UUID_STRING_BUFLEN] = "";
+
+ if (STRPREFIX(key, "[")) {
+ /* Key is probably a datastore path */
+ return esxStorageBackendVMFSVolumeLookupByPath(conn, key);
+ }
+
+ if (!priv->primary->hasQueryVirtualDiskUuid) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("QueryVirtualDiskUuid not available, "
+ "cannot lookup storage volume by UUID"));
+ return NULL;
+ }
+
+ /* Lookup all datastores */
+ if (esxVI_String_AppendValueToList(&propertyNameList, "summary.name") < 0 ||
+ esxVI_LookupDatastoreList(priv->primary, propertyNameList,
+ &datastoreList) < 0) {
+ goto cleanup;
+ }
+
+ for (datastore = datastoreList; datastore != NULL;
+ datastore = datastore->_next) {
+ datastoreName = NULL;
+
+ if (esxVI_GetStringValue(datastore, "summary.name", &datastoreName,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ /* Lookup datastore content */
+ esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList);
+
+ if (esxVI_LookupDatastoreContentByDatastoreName
+ (priv->primary, datastoreName, &searchResultsList) < 0) {
+ goto cleanup;
+ }
+
+ /* Interpret search result */
+ for (searchResults = searchResultsList; searchResults != NULL;
+ searchResults = searchResults->_next) {
+ VIR_FREE(directoryAndFileName);
+
+ if (esxUtil_ParseDatastorePath(searchResults->folderPath, NULL,
+ NULL, &directoryAndFileName) < 0) {
+ goto cleanup;
+ }
+
+ /* Strip trailing separators */
+ length = strlen(directoryAndFileName);
+
+ while (length > 0 && directoryAndFileName[length - 1] == '/') {
+ directoryAndFileName[length - 1] = '\0';
+ --length;
+ }
+
+ /* Build datastore path and query the UUID */
+ for (fileInfo = searchResults->file; fileInfo != NULL;
+ fileInfo = fileInfo->_next) {
+ VIR_FREE(datastorePath);
+
+ if (length < 1) {
+ if (virAsprintf(&volumeName, "%s",
+ fileInfo->path) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ } else if (virAsprintf(&volumeName, "%s/%s",
+ directoryAndFileName,
+ fileInfo->path) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (virAsprintf(&datastorePath, "[%s] %s", datastoreName,
+ volumeName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (esxVI_VmDiskFileInfo_DynamicCast(fileInfo) == NULL) {
+ /* Only a VirtualDisk has a UUID */
+ continue;
+ }
+
+ VIR_FREE(uuid_string);
+
+ if (esxVI_QueryVirtualDiskUuid
+ (priv->primary, datastorePath,
+ priv->primary->datacenter->_reference,
+ &uuid_string) < 0) {
+ goto cleanup;
+ }
+
+ if (esxUtil_ReformatUuid(uuid_string, key_candidate) < 0) {
+ goto cleanup;
+ }
+
+ if (STREQ(key, key_candidate)) {
+ /* Found matching UUID */
+ volume = virGetStorageVol(conn, datastoreName,
+ volumeName, key,
+ &esxStorageBackendVMFSDrv,
+ NULL);
+ goto cleanup;
+ }
+ }
+ }
+ }
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastoreList);
+ esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList);
+ VIR_FREE(directoryAndFileName);
+ VIR_FREE(datastorePath);
+ VIR_FREE(volumeName);
+ VIR_FREE(uuid_string);
+
+ return volume;
+}
+
+static virStorageVolPtr
+esxStorageBackendVMFSVolumeCreateXML(virStoragePoolPtr pool,
+ const char *xmldesc,
+ unsigned int flags)
+{
+ virStorageVolPtr volume = NULL;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ virStoragePoolDef poolDef;
+ virStorageVolDefPtr def = NULL;
+ char *tmp;
+ char *unescapedDatastorePath = NULL;
+ char *unescapedDirectoryName = NULL;
+ char *unescapedDirectoryAndFileName = NULL;
+ char *directoryName = NULL;
+ char *fileName = NULL;
+ char *datastorePathWithoutFileName = NULL;
+ char *datastorePath = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+ esxVI_FileBackedVirtualDiskSpec *virtualDiskSpec = NULL;
+ esxVI_ManagedObjectReference *task = NULL;
+ esxVI_TaskInfoState taskInfoState;
+ char *taskInfoErrorMessage = NULL;
+ char *uuid_string = NULL;
+ char *key = NULL;
+
+ virCheckFlags(0, NULL);
+
+ memset(&poolDef, 0, sizeof(poolDef));
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return NULL;
+ }
+
+ if (esxStorageBackendVMFSPoolLookupType(
+ pool->conn, pool->name, &poolDef.type) < 0) {
+ return NULL;
+ }
+
+ /* Parse config */
+ def = virStorageVolDefParseString(&poolDef, xmldesc);
+
+ if (def == NULL) {
+ goto cleanup;
+ }
+
+ if (def->type != VIR_STORAGE_VOL_FILE) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Creating non-file volumes is not supported"));
+ goto cleanup;
+ }
+
+ /* Validate config */
+ tmp = strrchr(def->name, '/');
+
+ if (tmp == NULL || *def->name == '/' || tmp[1] == '\0') {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Volume name '%s' doesn't have expected format "
+ "'<directory>/<file>'"), def->name);
+ goto cleanup;
+ }
+
+ if (! virFileHasSuffix(def->name, ".vmdk")) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Volume name '%s' has unsupported suffix, "
+ "expecting '.vmdk'"), def->name);
+ goto cleanup;
+ }
+
+ if (virAsprintf(&unescapedDatastorePath, "[%s] %s", pool->name,
+ def->name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (def->target.format == VIR_STORAGE_FILE_VMDK) {
+ /* Parse and escape datastore path */
+ if (esxUtil_ParseDatastorePath(unescapedDatastorePath, NULL,
+ &unescapedDirectoryName,
+ &unescapedDirectoryAndFileName) < 0) {
+ goto cleanup;
+ }
+
+ directoryName = esxUtil_EscapeDatastoreItem(unescapedDirectoryName);
+
+ if (directoryName == NULL) {
+ goto cleanup;
+ }
+
+ fileName = esxUtil_EscapeDatastoreItem(unescapedDirectoryAndFileName +
+ strlen(unescapedDirectoryName) + 1);
+
+ if (fileName == NULL) {
+ goto cleanup;
+ }
+
+ if (virAsprintf(&datastorePathWithoutFileName, "[%s] %s", pool->name,
+ directoryName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (virAsprintf(&datastorePath, "[%s] %s/%s", pool->name, directoryName,
+ fileName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ /* Create directory, if it doesn't exist yet */
+ if (esxVI_LookupFileInfoByDatastorePath
+ (priv->primary, datastorePathWithoutFileName, true, &fileInfo,
+ esxVI_Occurrence_OptionalItem) < 0) {
+ goto cleanup;
+ }
+
+ if (fileInfo == NULL) {
+ if (esxVI_MakeDirectory(priv->primary, datastorePathWithoutFileName,
+ priv->primary->datacenter->_reference,
+ esxVI_Boolean_True) < 0) {
+ goto cleanup;
+ }
+ }
+
+ /* Create VirtualDisk */
+ if (esxVI_FileBackedVirtualDiskSpec_Alloc(&virtualDiskSpec) < 0 ||
+ esxVI_Long_Alloc(&virtualDiskSpec->capacityKb) < 0) {
+ goto cleanup;
+ }
+
+ /* From the vSphere API documentation about VirtualDiskType ... */
+ if (def->allocation == def->capacity) {
+ /*
+ * "A preallocated disk has all space allocated at creation time
+ * and the space is zeroed on demand as the space is used."
+ */
+ virtualDiskSpec->diskType = (char *)"preallocated";
+ } else if (def->allocation == 0) {
+ /*
+ * "Space required for thin-provisioned virtual disk is allocated
+ * and zeroed on demand as the space is used."
+ */
+ virtualDiskSpec->diskType = (char *)"thin";
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unsupported capacity-to-allocation relation"));
+ goto cleanup;
+ }
+
+ /*
+ * FIXME: The adapter type is a required parameter, but there is no
+ * way to let the user specify it in the volume XML config. Therefore,
+ * default to 'busLogic' here.
+ */
+ virtualDiskSpec->adapterType = (char *)"busLogic";
+
+ virtualDiskSpec->capacityKb->value =
+ VIR_DIV_UP(def->capacity, 1024); /* Scale from byte to kilobyte */
+
+ if (esxVI_CreateVirtualDisk_Task
+ (priv->primary, datastorePath,
+ priv->primary->datacenter->_reference,
+ esxVI_VirtualDiskSpec_DynamicCast(virtualDiskSpec), &task) < 0 ||
+ esxVI_WaitForTaskCompletion(priv->primary, task, NULL,
+ esxVI_Occurrence_None,
+ priv->parsedUri->autoAnswer,
+ &taskInfoState,
+ &taskInfoErrorMessage) < 0) {
+ goto cleanup;
+ }
+
+ if (taskInfoState != esxVI_TaskInfoState_Success) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not create volume: %s"),
+ taskInfoErrorMessage);
+ goto cleanup;
+ }
+
+ if (priv->primary->hasQueryVirtualDiskUuid) {
+ if (VIR_ALLOC_N(key, VIR_UUID_STRING_BUFLEN) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (esxVI_QueryVirtualDiskUuid(priv->primary, datastorePath,
+ priv->primary->datacenter->_reference,
+ &uuid_string) < 0) {
+ goto cleanup;
+ }
+
+ if (esxUtil_ReformatUuid(uuid_string, key) < 0) {
+ goto cleanup;
+ }
+ } else {
+ /* Fall back to the path as key */
+ if (esxVI_String_DeepCopyValue(&key, datastorePath) < 0) {
+ goto cleanup;
+ }
+ }
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Creation of %s volumes is not supported"),
+ virStorageFileFormatTypeToString(def->target.format));
+ goto cleanup;
+ }
+
+ volume = virGetStorageVol(pool->conn, pool->name, def->name, key,
+ &esxStorageBackendVMFSDrv, NULL);
+
+ cleanup:
+ if (virtualDiskSpec != NULL) {
+ virtualDiskSpec->diskType = NULL;
+ virtualDiskSpec->adapterType = NULL;
+ }
+
+ virStorageVolDefFree(def);
+ VIR_FREE(unescapedDatastorePath);
+ VIR_FREE(unescapedDirectoryName);
+ VIR_FREE(unescapedDirectoryAndFileName);
+ VIR_FREE(directoryName);
+ VIR_FREE(fileName);
+ VIR_FREE(datastorePathWithoutFileName);
+ VIR_FREE(datastorePath);
+ esxVI_FileInfo_Free(&fileInfo);
+ esxVI_FileBackedVirtualDiskSpec_Free(&virtualDiskSpec);
+ esxVI_ManagedObjectReference_Free(&task);
+ VIR_FREE(taskInfoErrorMessage);
+ VIR_FREE(uuid_string);
+ VIR_FREE(key);
+
+ return volume;
+}
+
+static virStorageVolPtr
+esxStorageBackendVMFSVolumeCreateXMLFrom(virStoragePoolPtr pool,
+ const char *xmldesc,
+ virStorageVolPtr sourceVolume,
+ unsigned int flags)
+{
+ virStorageVolPtr volume = NULL;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ virStoragePoolDef poolDef;
+ char *sourceDatastorePath = NULL;
+ virStorageVolDefPtr def = NULL;
+ char *tmp;
+ char *unescapedDatastorePath = NULL;
+ char *unescapedDirectoryName = NULL;
+ char *unescapedDirectoryAndFileName = NULL;
+ char *directoryName = NULL;
+ char *fileName = NULL;
+ char *datastorePathWithoutFileName = NULL;
+ char *datastorePath = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+ esxVI_ManagedObjectReference *task = NULL;
+ esxVI_TaskInfoState taskInfoState;
+ char *taskInfoErrorMessage = NULL;
+ char *uuid_string = NULL;
+ char *key = NULL;
+
+ virCheckFlags(0, NULL);
+
+ memset(&poolDef, 0, sizeof(poolDef));
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return NULL;
+ }
+
+ if (esxStorageBackendVMFSPoolLookupType(
+ pool->conn, pool->name, &poolDef.type) < 0) {
+ return NULL;
+ }
+
+ if (virAsprintf(&sourceDatastorePath, "[%s] %s", sourceVolume->pool,
+ sourceVolume->name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ /* Parse config */
+ def = virStorageVolDefParseString(&poolDef, xmldesc);
+
+ if (def == NULL) {
+ goto cleanup;
+ }
+
+ if (def->type != VIR_STORAGE_VOL_FILE) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Creating non-file volumes is not supported"));
+ goto cleanup;
+ }
+
+ /* Validate config */
+ tmp = strrchr(def->name, '/');
+
+ if (tmp == NULL || *def->name == '/' || tmp[1] == '\0') {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Volume name '%s' doesn't have expected format "
+ "'<directory>/<file>'"), def->name);
+ goto cleanup;
+ }
+
+ if (! virFileHasSuffix(def->name, ".vmdk")) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Volume name '%s' has unsupported suffix, "
+ "expecting '.vmdk'"), def->name);
+ goto cleanup;
+ }
+
+ if (virAsprintf(&unescapedDatastorePath, "[%s] %s", pool->name,
+ def->name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (def->target.format == VIR_STORAGE_FILE_VMDK) {
+ /* Parse and escape datastore path */
+ if (esxUtil_ParseDatastorePath(unescapedDatastorePath, NULL,
+ &unescapedDirectoryName,
+ &unescapedDirectoryAndFileName) < 0) {
+ goto cleanup;
+ }
+
+ directoryName = esxUtil_EscapeDatastoreItem(unescapedDirectoryName);
+
+ if (directoryName == NULL) {
+ goto cleanup;
+ }
+
+ fileName = esxUtil_EscapeDatastoreItem(unescapedDirectoryAndFileName +
+ strlen(unescapedDirectoryName) + 1);
+
+ if (fileName == NULL) {
+ goto cleanup;
+ }
+
+ if (virAsprintf(&datastorePathWithoutFileName, "[%s] %s", pool->name,
+ directoryName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (virAsprintf(&datastorePath, "[%s] %s/%s", pool->name, directoryName,
+ fileName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ /* Create directory, if it doesn't exist yet */
+ if (esxVI_LookupFileInfoByDatastorePath
+ (priv->primary, datastorePathWithoutFileName, true, &fileInfo,
+ esxVI_Occurrence_OptionalItem) < 0) {
+ goto cleanup;
+ }
+
+ if (fileInfo == NULL) {
+ if (esxVI_MakeDirectory(priv->primary, datastorePathWithoutFileName,
+ priv->primary->datacenter->_reference,
+ esxVI_Boolean_True) < 0) {
+ goto cleanup;
+ }
+ }
+
+ /* Copy VirtualDisk */
+ if (esxVI_CopyVirtualDisk_Task(priv->primary, sourceDatastorePath,
+ priv->primary->datacenter->_reference,
+ datastorePath,
+ priv->primary->datacenter->_reference,
+ NULL, esxVI_Boolean_False, &task) < 0 ||
+ esxVI_WaitForTaskCompletion(priv->primary, task, NULL,
+ esxVI_Occurrence_None,
+ priv->parsedUri->autoAnswer,
+ &taskInfoState,
+ &taskInfoErrorMessage) < 0) {
+ goto cleanup;
+ }
+
+ if (taskInfoState != esxVI_TaskInfoState_Success) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not copy volume: %s"),
+ taskInfoErrorMessage);
+ goto cleanup;
+ }
+
+ if (priv->primary->hasQueryVirtualDiskUuid) {
+ if (VIR_ALLOC_N(key, VIR_UUID_STRING_BUFLEN) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (esxVI_QueryVirtualDiskUuid(priv->primary, datastorePath,
+ priv->primary->datacenter->_reference,
+ &uuid_string) < 0) {
+ goto cleanup;
+ }
+
+ if (esxUtil_ReformatUuid(uuid_string, key) < 0) {
+ goto cleanup;
+ }
+ } else {
+ /* Fall back to the path as key */
+ if (esxVI_String_DeepCopyValue(&key, datastorePath) < 0) {
+ goto cleanup;
+ }
+ }
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Creation of %s volumes is not supported"),
+ virStorageFileFormatTypeToString(def->target.format));
+ goto cleanup;
+ }
+
+ volume = virGetStorageVol(pool->conn, pool->name, def->name, key,
+ &esxStorageBackendVMFSDrv, NULL);
+
+ cleanup:
+ VIR_FREE(sourceDatastorePath);
+ virStorageVolDefFree(def);
+ VIR_FREE(unescapedDatastorePath);
+ VIR_FREE(unescapedDirectoryName);
+ VIR_FREE(unescapedDirectoryAndFileName);
+ VIR_FREE(directoryName);
+ VIR_FREE(fileName);
+ VIR_FREE(datastorePathWithoutFileName);
+ VIR_FREE(datastorePath);
+ esxVI_FileInfo_Free(&fileInfo);
+ esxVI_ManagedObjectReference_Free(&task);
+ VIR_FREE(taskInfoErrorMessage);
+ VIR_FREE(uuid_string);
+ VIR_FREE(key);
+
+ return volume;
+}
+
+
+
+static char *
+esxStorageBackendVMFSVolumeGetXMLDesc(virStorageVolPtr volume,
+ unsigned int flags)
+{
+ esxPrivate *priv = volume->conn->storagePrivateData;
+ virStoragePoolDef pool;
+ char *datastorePath = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+ esxVI_VmDiskFileInfo *vmDiskFileInfo = NULL;
+ esxVI_IsoImageFileInfo *isoImageFileInfo = NULL;
+ esxVI_FloppyImageFileInfo *floppyImageFileInfo = NULL;
+ virStorageVolDef def;
+ char *xml = NULL;
+
+ virCheckFlags(0, NULL);
+
+ memset(&pool, 0, sizeof(pool));
+ memset(&def, 0, sizeof(def));
+
+ if (esxStorageBackendVMFSPoolLookupType(
+ volume->conn, volume->pool, &pool.type) < 0) {
+ return NULL;
+ }
+
+ /* Lookup file info */
+ if (virAsprintf(&datastorePath, "[%s] %s", volume->pool, volume->name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (esxVI_LookupFileInfoByDatastorePath(priv->primary, datastorePath,
+ false, &fileInfo,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ vmDiskFileInfo = esxVI_VmDiskFileInfo_DynamicCast(fileInfo);
+ isoImageFileInfo = esxVI_IsoImageFileInfo_DynamicCast(fileInfo);
+ floppyImageFileInfo = esxVI_FloppyImageFileInfo_DynamicCast(fileInfo);
+
+ def.name = volume->name;
+
+ if (esxVI_LookupStorageVolumeKeyByDatastorePath(priv->primary, datastorePath,
+ &def.key) < 0) {
+ goto cleanup;
+ }
+
+ def.type = VIR_STORAGE_VOL_FILE;
+ def.target.path = datastorePath;
+
+ if (vmDiskFileInfo != NULL) {
+ /* Scale from kilobyte to byte */
+ def.capacity = vmDiskFileInfo->capacityKb->value * 1024;
+ def.allocation = vmDiskFileInfo->fileSize->value;
+
+ def.target.format = VIR_STORAGE_FILE_VMDK;
+ } else if (isoImageFileInfo != NULL) {
+ def.capacity = fileInfo->fileSize->value;
+ def.allocation = fileInfo->fileSize->value;
+
+ def.target.format = VIR_STORAGE_FILE_ISO;
+ } else if (floppyImageFileInfo != NULL) {
+ def.capacity = fileInfo->fileSize->value;
+ def.allocation = fileInfo->fileSize->value;
+
+ def.target.format = VIR_STORAGE_FILE_RAW;
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("File '%s' has unknown type"), datastorePath);
+ goto cleanup;
+ }
+
+ xml = virStorageVolDefFormat(&pool, &def);
+
+ cleanup:
+ VIR_FREE(datastorePath);
+ esxVI_FileInfo_Free(&fileInfo);
+ VIR_FREE(def.key);
+
+ return xml;
+}
+
+
+
+static int
+esxStorageBackendVMFSVolumeDelete(virStorageVolPtr volume, unsigned int flags)
+{
+ int result = -1;
+ esxPrivate *priv = volume->conn->storagePrivateData;
+ char *datastorePath = NULL;
+ esxVI_ManagedObjectReference *task = NULL;
+ esxVI_TaskInfoState taskInfoState;
+ char *taskInfoErrorMessage = NULL;
+
+ virCheckFlags(0, -1);
+
+ if (virAsprintf(&datastorePath, "[%s] %s", volume->pool, volume->name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (esxVI_DeleteVirtualDisk_Task(priv->primary, datastorePath,
+ priv->primary->datacenter->_reference,
+ &task) < 0 ||
+ esxVI_WaitForTaskCompletion(priv->primary, task, NULL,
+ esxVI_Occurrence_None,
+ priv->parsedUri->autoAnswer,
+ &taskInfoState, &taskInfoErrorMessage) < 0) {
+ goto cleanup;
+ }
+
+ if (taskInfoState != esxVI_TaskInfoState_Success) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not delete volume: %s"),
+ taskInfoErrorMessage);
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ VIR_FREE(datastorePath);
+ esxVI_ManagedObjectReference_Free(&task);
+ VIR_FREE(taskInfoErrorMessage);
+
+ return result;
+
+}
+
+
+
+static int
+esxStorageBackendVMFSVolumeWipe(virStorageVolPtr volume, unsigned int flags)
+{
+ int result = -1;
+ esxPrivate *priv = volume->conn->storagePrivateData;
+ char *datastorePath = NULL;
+ esxVI_ManagedObjectReference *task = NULL;
+ esxVI_TaskInfoState taskInfoState;
+ char *taskInfoErrorMessage = NULL;
+
+ virCheckFlags(0, -1);
+
+ if (virAsprintf(&datastorePath, "[%s] %s", volume->pool, volume->name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (esxVI_ZeroFillVirtualDisk_Task(priv->primary, datastorePath,
+ priv->primary->datacenter->_reference,
+ &task) < 0 ||
+ esxVI_WaitForTaskCompletion(priv->primary, task, NULL,
+ esxVI_Occurrence_None,
+ priv->parsedUri->autoAnswer,
+ &taskInfoState, &taskInfoErrorMessage) < 0) {
+ goto cleanup;
+ }
+
+ if (taskInfoState != esxVI_TaskInfoState_Success) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not wipe volume: %s"),
+ taskInfoErrorMessage);
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ VIR_FREE(datastorePath);
+ esxVI_ManagedObjectReference_Free(&task);
+ VIR_FREE(taskInfoErrorMessage);
+
+ return result;
+
+}
+
+
+static char*
+esxStorageBackendVMFSVolumeGetPath(virStorageVolPtr volume)
+{
+ char *path;
+
+ if (virAsprintf(&path, "[%s] %s", volume->pool, volume->name) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ return path;
+
+}
+
+
+
+
+virStorageDriver esxStorageBackendVMFSDrv = {
+ .name = "ESX VMFS backend",
+ .open = NULL, /* 1.0.0 */
+ .close = NULL, /* 1.0.0 */
+ .numOfPools = esxStorageBackendVMFSNumberOfStoragePools, /* 1.0.0 */
+ .listPools = esxStorageBackendVMFSListStoragePools, /* 1.0.0 */
+ .poolLookupByName = esxStorageBackendVMFSPoolLookupByName, /* 1.0.0 */
+ .poolLookupByUUID = esxStorageBackendVMFSPoolLookupByUUID, /* 1.0.0 */
+ .poolRefresh = esxStorageBackendVMFSPoolRefresh, /* 1.0.0 */
+ .poolGetInfo = esxStorageBackendVMFSPoolGetInfo, /* 1.0.0 */
+ .poolGetXMLDesc = esxStorageBackendVMFSPoolGetXMLDesc, /* 1.0.0 */
+ .poolNumOfVolumes = esxStorageBackendVMFSPoolNumberOfStorageVolumes, /* 1.0.0 */
+ .poolListVolumes = esxStorageBackendVMFSPoolListStorageVolumes, /* 1.0.0 */
+ .volLookupByName = esxStorageBackendVMFSVolumeLookupByName, /* 1.0.0 */
+ .volLookupByKey = esxStorageBackendVMFSVolumeLookupByKey, /* 1.0.0 */
+ .volLookupByPath = esxStorageBackendVMFSVolumeLookupByPath, /* 1.0.0 */
+ .volCreateXML = esxStorageBackendVMFSVolumeCreateXML, /* 1.0.0 */
+ .volCreateXMLFrom = esxStorageBackendVMFSVolumeCreateXMLFrom, /* 1.0.0 */
+ .volGetXMLDesc = esxStorageBackendVMFSVolumeGetXMLDesc, /* 1.0.0 */
+ .volDelete = esxStorageBackendVMFSVolumeDelete, /* 1.0.0 */
+ .volWipe = esxStorageBackendVMFSVolumeWipe, /* 1.0.0 */
+ .volGetPath = esxStorageBackendVMFSVolumeGetPath, /* 1.0.0 */
+
+};
diff --git a/src/esx/esx_storage_backend_vmfs.h b/src/esx/esx_storage_backend_vmfs.h
new file mode 100644
index 0000000..d48a519
--- /dev/null
+++ b/src/esx/esx_storage_backend_vmfs.h
@@ -0,0 +1,30 @@
+/*
+ * esx_storage_backend_vmfs.h: ESX storage backend for VMFS datastores
+ *
+ * Copyright (C) 2012 Ata E Husain Bohra <ata.husain(a)hotmail.com>
+ *
+ * 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
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __ESX_STORAGE_BACKEND_VMFS_H__
+# define __ESX_STORAGE_BACKEND_VMFS_H__
+
+# include "driver.h"
+
+extern virStorageDriver esxStorageBackendVMFSDrv;
+
+#endif /* __ESX_STORAGE_BACKEND_VMFS_H__ */
+
diff --git a/src/esx/esx_storage_driver.c b/src/esx/esx_storage_driver.c
index 08d5ab1..5530ea7 100644
--- a/src/esx/esx_storage_driver.c
+++ b/src/esx/esx_storage_driver.c
@@ -5,6 +5,7 @@
*
* Copyright (C) 2010-2011 Red Hat, Inc.
* Copyright (C) 2010 Matthias Bolte <matthias.bolte(a)googlemail.com>
+ * Copyright (C) 2012 Ata E Husain Bohra <ata.husain(a)hotmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,82 +25,29 @@
#include <config.h>
-#include "md5.h"
-#include "verify.h"
-#include "internal.h"
-#include "util.h"
-#include "memory.h"
-#include "logging.h"
#include "uuid.h"
+#include "memory.h"
#include "storage_conf.h"
-#include "storage_file.h"
#include "esx_private.h"
#include "esx_storage_driver.h"
-#include "esx_vi.h"
-#include "esx_vi_methods.h"
-#include "esx_util.h"
+#include "esx_storage_backend_vmfs.h"
#define VIR_FROM_THIS VIR_FROM_ESX
-/*
- * The UUID of a storage pool is the MD5 sum of it's mount path. Therefore,
- * verify that UUID and MD5 sum match in size, because we rely on that.
- */
-verify(MD5_DIGEST_SIZE == VIR_UUID_BUFLEN);
-
-
-
-static int
-esxStoragePoolLookupType(esxVI_Context *ctx, const char *poolName,
- int *poolType)
-{
- int result = -1;
- esxVI_String *propertyNameList = NULL;
- esxVI_ObjectContent *datastore = NULL;
- esxVI_DynamicProperty *dynamicProperty = NULL;
- esxVI_DatastoreInfo *datastoreInfo = NULL;
-
- if (esxVI_String_AppendValueToList(&propertyNameList, "info") < 0 ||
- esxVI_LookupDatastoreByName(ctx, poolName, propertyNameList, &datastore,
- esxVI_Occurrence_RequiredItem) < 0) {
- goto cleanup;
- }
-
- for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
- dynamicProperty = dynamicProperty->_next) {
- if (STREQ(dynamicProperty->name, "info")) {
- if (esxVI_DatastoreInfo_CastFromAnyType(dynamicProperty->val,
- &datastoreInfo) < 0) {
- goto cleanup;
- }
-
- break;
- }
- }
-
- if (esxVI_LocalDatastoreInfo_DynamicCast(datastoreInfo) != NULL) {
- *poolType = VIR_STORAGE_POOL_DIR;
- } else if (esxVI_NasDatastoreInfo_DynamicCast(datastoreInfo) != NULL) {
- *poolType = VIR_STORAGE_POOL_NETFS;
- } else if (esxVI_VmfsDatastoreInfo_DynamicCast(datastoreInfo) != NULL) {
- *poolType = VIR_STORAGE_POOL_FS;
- } else {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("DatastoreInfo has unexpected type"));
- goto cleanup;
- }
-
- result = 0;
-
- cleanup:
- esxVI_String_Free(&propertyNameList);
- esxVI_ObjectContent_Free(&datastore);
- esxVI_DatastoreInfo_Free(&datastoreInfo);
-
- return result;
-}
-
+/**
+* ESX storage driver implements a facade pattern;
+* the driver exposes the routines supported by Libvirt
+* public interface to manage ESX storage devices. Internally
+* it uses backend drivers to perform the required task.
+*/
+enum {
+ VMFS = 0,
+ LAST_DRIVER
+};
+static virStorageDriverPtr backendDrv[] = {
+ &esxStorageBackendVMFSDrv
+};
static virDrvOpenStatus
esxStorageOpen(virConnectPtr conn,
@@ -132,27 +80,28 @@ esxStorageClose(virConnectPtr conn)
static int
esxNumberOfStoragePools(virConnectPtr conn)
{
- int count = 0;
esxPrivate *priv = conn->storagePrivateData;
- esxVI_ObjectContent *datastoreList = NULL;
- esxVI_ObjectContent *datastore = NULL;
+ int count = 0;
+ int i = 0;
+ bool success = false;
if (esxVI_EnsureSession(priv->primary) < 0) {
- return -1;
+ goto cleanup;
}
- if (esxVI_LookupDatastoreList(priv->primary, NULL, &datastoreList) < 0) {
- return -1;
+ for (i = 0; i < LAST_DRIVER; ++i) {
+ int tempCount = backendDrv[i]->numOfPools(conn);
+ if (tempCount < 0) {
+ goto cleanup;
+ }
+ count += tempCount;
}
- for (datastore = datastoreList; datastore != NULL;
- datastore = datastore->_next) {
- ++count;
- }
+ success = true;
- esxVI_ObjectContent_Free(&datastoreList);
+ cleanup:
- return count;
+ return success ? count : -1;
}
@@ -162,56 +111,32 @@ esxListStoragePools(virConnectPtr conn, char **const names, int maxnames)
{
bool success = false;
esxPrivate *priv = conn->storagePrivateData;
- esxVI_String *propertyNameList = NULL;
- esxVI_DynamicProperty *dynamicProperty = NULL;
- esxVI_ObjectContent *datastoreList = NULL;
- esxVI_ObjectContent *datastore = NULL;
int count = 0;
- int i;
+ int i = 0;
if (maxnames == 0) {
return 0;
}
if (esxVI_EnsureSession(priv->primary) < 0) {
- return -1;
- }
-
- if (esxVI_String_AppendValueToList(&propertyNameList,
- "summary.name") < 0 ||
- esxVI_LookupDatastoreList(priv->primary, propertyNameList,
- &datastoreList) < 0) {
goto cleanup;
}
- for (datastore = datastoreList; datastore != NULL;
- datastore = datastore->_next) {
- for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
- dynamicProperty = dynamicProperty->_next) {
- if (STREQ(dynamicProperty->name, "summary.name")) {
- if (esxVI_AnyType_ExpectType(dynamicProperty->val,
- esxVI_Type_String) < 0) {
- goto cleanup;
- }
-
- names[count] = strdup(dynamicProperty->val->string);
-
- if (names[count] == NULL) {
- virReportOOMError();
- goto cleanup;
- }
-
- ++count;
- break;
- } else {
- VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
- }
+ for (i = 0; i < LAST_DRIVER; ++i) {
+ int tempCount =
+ backendDrv[i]->listPools(conn, &names[count], maxnames-count);
+
+ if (tempCount < 0) {
+ goto cleanup;
}
+
+ count += tempCount;
}
success = true;
cleanup:
+
if (! success) {
for (i = 0; i < count; ++i) {
VIR_FREE(names[i]);
@@ -220,10 +145,8 @@ esxListStoragePools(virConnectPtr conn, char **const names, int maxnames)
count = -1;
}
- esxVI_String_Free(&propertyNameList);
- esxVI_ObjectContent_Free(&datastoreList);
-
return count;
+
}
@@ -252,43 +175,31 @@ static virStoragePoolPtr
esxStoragePoolLookupByName(virConnectPtr conn, const char *name)
{
esxPrivate *priv = conn->storagePrivateData;
- esxVI_ObjectContent *datastore = NULL;
- esxVI_DatastoreHostMount *hostMount = NULL;
- unsigned char md5[MD5_DIGEST_SIZE]; /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
virStoragePoolPtr pool = NULL;
+ int i = 0;
- if (esxVI_EnsureSession(priv->primary) < 0) {
- return NULL;
- }
+ virCheckNonNullArgGoto(name, cleanup);
- if (esxVI_LookupDatastoreByName(priv->primary, name, NULL, &datastore,
- esxVI_Occurrence_RequiredItem) < 0) {
+ if (esxVI_EnsureSession(priv->primary) < 0) {
goto cleanup;
}
- /*
- * Datastores don't have a UUID, but we can use the 'host.mountInfo.path'
- * property as source for a UUID. The mount path is unique per host and
- * cannot change during the lifetime of the datastore.
- *
- * The MD5 sum of the mount path can be used as UUID, assuming MD5 is
- * considered to be collision-free enough for this use case.
- */
- if (esxVI_LookupDatastoreHostMount(priv->primary, datastore->obj,
- &hostMount) < 0) {
- goto cleanup;
+ for (i = 0; i < LAST_DRIVER; ++i) {
+ pool = backendDrv[i]->poolLookupByName(conn, name);
+ if (pool != NULL) {
+ break;
+ }
}
- md5_buffer(hostMount->mountInfo->path,
- strlen(hostMount->mountInfo->path), md5);
-
- pool = virGetStoragePool(conn, name, md5);
+ if (pool == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find storage pool with name '%s'"), name);
+ }
- cleanup:
- esxVI_ObjectContent_Free(&datastore);
- esxVI_DatastoreHostMount_Free(&hostMount);
+cleanup:
return pool;
+
}
@@ -297,65 +208,36 @@ static virStoragePoolPtr
esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
{
esxPrivate *priv = conn->storagePrivateData;
- esxVI_String *propertyNameList = NULL;
- esxVI_ObjectContent *datastoreList = NULL;
- esxVI_ObjectContent *datastore = NULL;
- esxVI_DatastoreHostMount *hostMount = NULL;
- unsigned char md5[MD5_DIGEST_SIZE]; /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
- char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
- char *name = NULL;
virStoragePoolPtr pool = NULL;
+ char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
+ int i = 0;
- if (esxVI_EnsureSession(priv->primary) < 0) {
- return NULL;
- }
+ virCheckNonNullArgGoto(uuid, cleanup);
- if (esxVI_String_AppendValueToList(&propertyNameList, "summary.name") < 0 ||
- esxVI_LookupDatastoreList(priv->primary, propertyNameList,
- &datastoreList) < 0) {
+ if (esxVI_EnsureSession(priv->primary) < 0) {
goto cleanup;
}
- for (datastore = datastoreList; datastore != NULL;
- datastore = datastore->_next) {
- esxVI_DatastoreHostMount_Free(&hostMount);
-
- if (esxVI_LookupDatastoreHostMount(priv->primary, datastore->obj,
- &hostMount) < 0) {
- goto cleanup;
- }
-
- md5_buffer(hostMount->mountInfo->path,
- strlen(hostMount->mountInfo->path), md5);
-
- if (memcmp(uuid, md5, VIR_UUID_BUFLEN) == 0) {
+ /* invoke backend drive method to search all known pools */
+ for (i = 0; i < LAST_DRIVER; ++i) {
+ pool = backendDrv[i]->poolLookupByUUID(conn, uuid);
+ if (pool != NULL) {
break;
}
}
- if (datastore == NULL) {
+ if (pool == NULL) {
virUUIDFormat(uuid, uuid_string);
virReportError(VIR_ERR_NO_STORAGE_POOL,
- _("Could not find datastore with UUID '%s'"),
- uuid_string);
-
- goto cleanup;
- }
-
- if (esxVI_GetStringValue(datastore, "summary.name", &name,
- esxVI_Occurrence_RequiredItem) < 0) {
- goto cleanup;
+ _("Could not find storage pool with uuid '%s'"),
+ uuid_string);
}
- pool = virGetStoragePool(conn, name, uuid);
-
- cleanup:
- esxVI_String_Free(&propertyNameList);
- esxVI_ObjectContent_Free(&datastoreList);
- esxVI_DatastoreHostMount_Free(&hostMount);
+cleanup:
return pool;
+
}
@@ -373,26 +255,26 @@ esxStoragePoolRefresh(virStoragePoolPtr pool, unsigned int flags)
{
int result = -1;
esxPrivate *priv = pool->conn->storagePrivateData;
- esxVI_ObjectContent *datastore = NULL;
+ virStorageDriverPtr backendDrvPtr = NULL;
- virCheckFlags(0, -1);
+ virCheckNonNullArgGoto(pool->privateData, cleanup);
if (esxVI_EnsureSession(priv->primary) < 0) {
- return -1;
+ goto cleanup;
}
- if (esxVI_LookupDatastoreByName(priv->primary, pool->name, NULL, &datastore,
- esxVI_Occurrence_RequiredItem) < 0 ||
- esxVI_RefreshDatastore(priv->primary, datastore->obj) < 0) {
+ backendDrvPtr = (virStorageDriverPtr) pool->privateData;
+
+ if (backendDrvPtr->poolRefresh(pool, flags) < 0) {
goto cleanup;
}
result = 0;
cleanup:
- esxVI_ObjectContent_Free(&datastore);
return result;
+
}
@@ -402,63 +284,28 @@ esxStoragePoolGetInfo(virStoragePoolPtr pool, virStoragePoolInfoPtr info)
{
int result = -1;
esxPrivate *priv = pool->conn->storagePrivateData;
- esxVI_String *propertyNameList = NULL;
- esxVI_ObjectContent *datastore = NULL;
- esxVI_DynamicProperty *dynamicProperty = NULL;
- esxVI_Boolean accessible = esxVI_Boolean_Undefined;
+ virStorageDriverPtr backendDrvPtr = NULL;
+
+ virCheckNonNullArgGoto(pool->privateData, cleanup);
memset(info, 0, sizeof(*info));
if (esxVI_EnsureSession(priv->primary) < 0) {
- return -1;
- }
-
- if (esxVI_String_AppendValueListToList(&propertyNameList,
- "summary.accessible\0"
- "summary.capacity\0"
- "summary.freeSpace\0") < 0 ||
- esxVI_LookupDatastoreByName(priv->primary, pool->name,
- propertyNameList, &datastore,
- esxVI_Occurrence_RequiredItem) < 0 ||
- esxVI_GetBoolean(datastore, "summary.accessible",
- &accessible, esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
- if (accessible == esxVI_Boolean_True) {
- info->state = VIR_STORAGE_POOL_RUNNING;
-
- for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
- dynamicProperty = dynamicProperty->_next) {
- if (STREQ(dynamicProperty->name, "summary.capacity")) {
- if (esxVI_AnyType_ExpectType(dynamicProperty->val,
- esxVI_Type_Long) < 0) {
- goto cleanup;
- }
-
- info->capacity = dynamicProperty->val->int64;
- } else if (STREQ(dynamicProperty->name, "summary.freeSpace")) {
- if (esxVI_AnyType_ExpectType(dynamicProperty->val,
- esxVI_Type_Long) < 0) {
- goto cleanup;
- }
-
- info->available = dynamicProperty->val->int64;
- }
- }
+ backendDrvPtr = (virStorageDriverPtr) pool->privateData;
- info->allocation = info->capacity - info->available;
- } else {
- info->state = VIR_STORAGE_POOL_INACCESSIBLE;
+ if (backendDrvPtr->poolGetInfo(pool, info) < 0) {
+ goto cleanup;
}
result = 0;
cleanup:
- esxVI_String_Free(&propertyNameList);
- esxVI_ObjectContent_Free(&datastore);
return result;
+
}
@@ -466,123 +313,23 @@ esxStoragePoolGetInfo(virStoragePoolPtr pool, virStoragePoolInfoPtr info)
static char *
esxStoragePoolGetXMLDesc(virStoragePoolPtr pool, unsigned int flags)
{
- esxPrivate *priv = pool->conn->storagePrivateData;
- esxVI_String *propertyNameList = NULL;
- esxVI_ObjectContent *datastore = NULL;
- esxVI_DatastoreHostMount *hostMount = NULL;
- esxVI_DynamicProperty *dynamicProperty = NULL;
- esxVI_Boolean accessible = esxVI_Boolean_Undefined;
- virStoragePoolDef def;
- esxVI_DatastoreInfo *info = NULL;
- esxVI_NasDatastoreInfo *nasInfo = NULL;
char *xml = NULL;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ virStorageDriverPtr backendDrvPtr = NULL;
- virCheckFlags(0, NULL);
-
- memset(&def, 0, sizeof(def));
+ virCheckNonNullArgGoto(pool->privateData, cleanup);
if (esxVI_EnsureSession(priv->primary) < 0) {
- return NULL;
- }
-
- if (esxVI_String_AppendValueListToList(&propertyNameList,
- "summary.accessible\0"
- "summary.capacity\0"
- "summary.freeSpace\0"
- "info\0") < 0 ||
- esxVI_LookupDatastoreByName(priv->primary, pool->name,
- propertyNameList, &datastore,
- esxVI_Occurrence_RequiredItem) < 0 ||
- esxVI_GetBoolean(datastore, "summary.accessible",
- &accessible, esxVI_Occurrence_RequiredItem) < 0 ||
- esxVI_LookupDatastoreHostMount(priv->primary, datastore->obj,
- &hostMount) < 0) {
- goto cleanup;
- }
-
- def.name = pool->name;
- memcpy(def.uuid, pool->uuid, VIR_UUID_BUFLEN);
-
- def.target.path = hostMount->mountInfo->path;
-
- if (accessible == esxVI_Boolean_True) {
- for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
- dynamicProperty = dynamicProperty->_next) {
- if (STREQ(dynamicProperty->name, "summary.capacity")) {
- if (esxVI_AnyType_ExpectType(dynamicProperty->val,
- esxVI_Type_Long) < 0) {
- goto cleanup;
- }
-
- def.capacity = dynamicProperty->val->int64;
- } else if (STREQ(dynamicProperty->name, "summary.freeSpace")) {
- if (esxVI_AnyType_ExpectType(dynamicProperty->val,
- esxVI_Type_Long) < 0) {
- goto cleanup;
- }
-
- def.available = dynamicProperty->val->int64;
- }
- }
-
- def.allocation = def.capacity - def.available;
- }
-
- for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
- dynamicProperty = dynamicProperty->_next) {
- if (STREQ(dynamicProperty->name, "info")) {
- if (esxVI_DatastoreInfo_CastFromAnyType(dynamicProperty->val,
- &info) < 0) {
- goto cleanup;
- }
-
- break;
- }
- }
-
- /* See vSphere API documentation about HostDatastoreSystem for details */
- if (esxVI_LocalDatastoreInfo_DynamicCast(info) != NULL) {
- def.type = VIR_STORAGE_POOL_DIR;
- } else if ((nasInfo = esxVI_NasDatastoreInfo_DynamicCast(info)) != NULL) {
- if (VIR_ALLOC_N(def.source.hosts, 1) < 0) {
- virReportOOMError();
- goto cleanup;
- }
- def.type = VIR_STORAGE_POOL_NETFS;
- def.source.hosts[0].name = nasInfo->nas->remoteHost;
- def.source.dir = nasInfo->nas->remotePath;
-
- if (STRCASEEQ(nasInfo->nas->type, "NFS")) {
- def.source.format = VIR_STORAGE_POOL_NETFS_NFS;
- } else if (STRCASEEQ(nasInfo->nas->type, "CIFS")) {
- def.source.format = VIR_STORAGE_POOL_NETFS_CIFS;
- } else {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Datastore has unexpected type '%s'"),
- nasInfo->nas->type);
- goto cleanup;
- }
- } else if (esxVI_VmfsDatastoreInfo_DynamicCast(info) != NULL) {
- def.type = VIR_STORAGE_POOL_FS;
- /*
- * FIXME: I'm not sure how to represent the source and target of a
- * VMFS based datastore in libvirt terms
- */
- } else {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("DatastoreInfo has unexpected type"));
goto cleanup;
}
- xml = virStoragePoolDefFormat(&def);
+ backendDrvPtr = (virStorageDriverPtr) pool->privateData;
+ xml = backendDrvPtr->poolGetXMLDesc(pool, flags);
cleanup:
- esxVI_String_Free(&propertyNameList);
- esxVI_ObjectContent_Free(&datastore);
- esxVI_DatastoreHostMount_Free(&hostMount);
- esxVI_DatastoreInfo_Free(&info);
return xml;
+
}
@@ -622,33 +369,24 @@ esxStoragePoolNumberOfStorageVolumes(virStoragePoolPtr pool)
{
bool success = false;
esxPrivate *priv = pool->conn->storagePrivateData;
- esxVI_HostDatastoreBrowserSearchResults *searchResultsList = NULL;
- esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL;
- esxVI_FileInfo *fileInfo = NULL;
+ virStorageDriverPtr backendDrvPtr = NULL;
int count = 0;
- if (esxVI_EnsureSession(priv->primary) < 0) {
- return -1;
- }
+ virCheckNonNullArgGoto(pool->privateData, cleanup);
- if (esxVI_LookupDatastoreContentByDatastoreName(priv->primary, pool->name,
- &searchResultsList) < 0) {
+ if (esxVI_EnsureSession(priv->primary) < 0) {
goto cleanup;
}
- /* Interpret search result */
- for (searchResults = searchResultsList; searchResults != NULL;
- searchResults = searchResults->_next) {
- for (fileInfo = searchResults->file; fileInfo != NULL;
- fileInfo = fileInfo->_next) {
- ++count;
- }
+ backendDrvPtr = (virStorageDriverPtr) pool->privateData;
+ count = backendDrvPtr->poolNumOfVolumes(pool);
+ if (count < 0) {
+ goto cleanup;
}
success = true;
cleanup:
- esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList);
return success ? count : -1;
}
@@ -659,87 +397,28 @@ static int
esxStoragePoolListStorageVolumes(virStoragePoolPtr pool, char **const names,
int maxnames)
{
- bool success = false;
+ int result = -1;
esxPrivate *priv = pool->conn->storagePrivateData;
- esxVI_HostDatastoreBrowserSearchResults *searchResultsList = NULL;
- esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL;
- esxVI_FileInfo *fileInfo = NULL;
- char *directoryAndFileName = NULL;
- size_t length;
- int count = 0;
- int i;
-
- if (names == NULL || maxnames < 0) {
- virReportError(VIR_ERR_INVALID_ARG, "%s", _("Invalid argument"));
- return -1;
- }
+ virStorageDriverPtr backendDrvPtr = NULL;
- if (maxnames == 0) {
- return 0;
- }
+ virCheckNonNullArgGoto(pool->privateData, cleanup);
if (esxVI_EnsureSession(priv->primary) < 0) {
- return -1;
- }
-
- if (esxVI_LookupDatastoreContentByDatastoreName(priv->primary, pool->name,
- &searchResultsList) < 0) {
goto cleanup;
}
- /* Interpret search result */
- for (searchResults = searchResultsList; searchResults != NULL;
- searchResults = searchResults->_next) {
- VIR_FREE(directoryAndFileName);
-
- if (esxUtil_ParseDatastorePath(searchResults->folderPath, NULL, NULL,
- &directoryAndFileName) < 0) {
- goto cleanup;
- }
-
- /* Strip trailing separators */
- length = strlen(directoryAndFileName);
-
- while (length > 0 && directoryAndFileName[length - 1] == '/') {
- directoryAndFileName[length - 1] = '\0';
- --length;
- }
+ backendDrvPtr = (virStorageDriverPtr) pool->privateData;
- /* Build volume names */
- for (fileInfo = searchResults->file; fileInfo != NULL;
- fileInfo = fileInfo->_next) {
- if (length < 1) {
- names[count] = strdup(fileInfo->path);
-
- if (names[count] == NULL) {
- virReportOOMError();
- goto cleanup;
- }
- } else if (virAsprintf(&names[count], "%s/%s", directoryAndFileName,
- fileInfo->path) < 0) {
- virReportOOMError();
- goto cleanup;
- }
-
- ++count;
- }
+ if (backendDrvPtr->poolListVolumes(pool, names, maxnames) < 0) {
+ goto cleanup;
}
- success = true;
+ result = 0;
cleanup:
- if (! success) {
- for (i = 0; i < count; ++i) {
- VIR_FREE(names[i]);
- }
-
- count = -1;
- }
- esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList);
- VIR_FREE(directoryAndFileName);
+ return result;
- return count;
}
@@ -749,30 +428,22 @@ esxStorageVolumeLookupByName(virStoragePoolPtr pool, const char *name)
{
virStorageVolPtr volume = NULL;
esxPrivate *priv = pool->conn->storagePrivateData;
- char *datastorePath = NULL;
- char *key = NULL;
-
- if (esxVI_EnsureSession(priv->primary) < 0) {
- return NULL;
- }
+ virStorageDriverPtr backendDrvPtr = NULL;
- if (virAsprintf(&datastorePath, "[%s] %s", pool->name, name) < 0) {
- virReportOOMError();
- goto cleanup;
- }
+ virCheckNonNullArgGoto(name, cleanup);
+ virCheckNonNullArgGoto(pool->privateData, cleanup);
- if (esxVI_LookupStorageVolumeKeyByDatastorePath(priv->primary,
- datastorePath, &key) < 0) {
+ if (esxVI_EnsureSession(priv->primary) < 0) {
goto cleanup;
}
- volume = virGetStorageVol(pool->conn, pool->name, name, key);
+ backendDrvPtr = (virStorageDriverPtr) pool->privateData;
+ volume = backendDrvPtr->volLookupByName(pool, name);
cleanup:
- VIR_FREE(datastorePath);
- VIR_FREE(key);
return volume;
+
}
@@ -782,32 +453,30 @@ esxStorageVolumeLookupByPath(virConnectPtr conn, const char *path)
{
virStorageVolPtr volume = NULL;
esxPrivate *priv = conn->storagePrivateData;
- char *datastoreName = NULL;
- char *directoryAndFileName = NULL;
- char *key = NULL;
- if (esxVI_EnsureSession(priv->primary) < 0) {
- return NULL;
- }
+ virCheckNonNullArgGoto(path, cleanup);
- if (esxUtil_ParseDatastorePath(path, &datastoreName, NULL,
- &directoryAndFileName) < 0) {
+ if (esxVI_EnsureSession(priv->primary) < 0) {
goto cleanup;
}
- if (esxVI_LookupStorageVolumeKeyByDatastorePath(priv->primary, path,
- &key) < 0) {
- goto cleanup;
+ /* FIXME: calling backend blindly may set unwanted error codes
+ *
+ * VMFS Datastore path follows cannonical format i.e.:
+ * [<datastore_name>] <file_path>
+ * WHEREAS
+ */
+ if (STRPREFIX(path, "[")) {
+ volume = backendDrv[VMFS]->volLookupByPath(conn, path);
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unexpected volume path format: %s"), path);
}
- volume = virGetStorageVol(conn, datastoreName, directoryAndFileName, key);
-
- cleanup:
- VIR_FREE(datastoreName);
- VIR_FREE(directoryAndFileName);
- VIR_FREE(key);
+cleanup:
return volume;
+
}
@@ -817,140 +486,29 @@ esxStorageVolumeLookupByKey(virConnectPtr conn, const char *key)
{
virStorageVolPtr volume = NULL;
esxPrivate *priv = conn->storagePrivateData;
- esxVI_String *propertyNameList = NULL;
- esxVI_ObjectContent *datastoreList = NULL;
- esxVI_ObjectContent *datastore = NULL;
- char *datastoreName = NULL;
- esxVI_HostDatastoreBrowserSearchResults *searchResultsList = NULL;
- esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL;
- char *directoryAndFileName = NULL;
- size_t length;
- char *datastorePath = NULL;
- char *volumeName = NULL;
- esxVI_FileInfo *fileInfo = NULL;
- char *uuid_string = NULL;
- char key_candidate[VIR_UUID_STRING_BUFLEN] = "";
-
- if (STRPREFIX(key, "[")) {
- /* Key is probably a datastore path */
- return esxStorageVolumeLookupByPath(conn, key);
- }
+ int i = 0;
- if (!priv->primary->hasQueryVirtualDiskUuid) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("QueryVirtualDiskUuid not available, cannot lookup storage "
- "volume by UUID"));
- return NULL;
- }
+ virCheckNonNullArgGoto(key, cleanup);
if (esxVI_EnsureSession(priv->primary) < 0) {
- return NULL;
- }
-
- /* Lookup all datastores */
- if (esxVI_String_AppendValueToList(&propertyNameList, "summary.name") < 0 ||
- esxVI_LookupDatastoreList(priv->primary, propertyNameList,
- &datastoreList) < 0) {
goto cleanup;
}
- for (datastore = datastoreList; datastore != NULL;
- datastore = datastore->_next) {
- datastoreName = NULL;
-
- if (esxVI_GetStringValue(datastore, "summary.name", &datastoreName,
- esxVI_Occurrence_RequiredItem) < 0) {
- goto cleanup;
- }
-
- /* Lookup datastore content */
- esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList);
-
- if (esxVI_LookupDatastoreContentByDatastoreName
- (priv->primary, datastoreName, &searchResultsList) < 0) {
- goto cleanup;
- }
-
- /* Interpret search result */
- for (searchResults = searchResultsList; searchResults != NULL;
- searchResults = searchResults->_next) {
- VIR_FREE(directoryAndFileName);
-
- if (esxUtil_ParseDatastorePath(searchResults->folderPath, NULL,
- NULL, &directoryAndFileName) < 0) {
- goto cleanup;
- }
-
- /* Strip trailing separators */
- length = strlen(directoryAndFileName);
-
- while (length > 0 && directoryAndFileName[length - 1] == '/') {
- directoryAndFileName[length - 1] = '\0';
- --length;
- }
-
- /* Build datastore path and query the UUID */
- for (fileInfo = searchResults->file; fileInfo != NULL;
- fileInfo = fileInfo->_next) {
- VIR_FREE(datastorePath);
-
- if (length < 1) {
- if (virAsprintf(&volumeName, "%s",
- fileInfo->path) < 0) {
- virReportOOMError();
- goto cleanup;
- }
- } else if (virAsprintf(&volumeName, "%s/%s",
- directoryAndFileName,
- fileInfo->path) < 0) {
- virReportOOMError();
- goto cleanup;
- }
-
- if (virAsprintf(&datastorePath, "[%s] %s", datastoreName,
- volumeName) < 0) {
- virReportOOMError();
- goto cleanup;
- }
-
- if (esxVI_VmDiskFileInfo_DynamicCast(fileInfo) == NULL) {
- /* Only a VirtualDisk has a UUID */
- continue;
- }
-
- VIR_FREE(uuid_string);
-
- if (esxVI_QueryVirtualDiskUuid
- (priv->primary, datastorePath,
- priv->primary->datacenter->_reference,
- &uuid_string) < 0) {
- goto cleanup;
- }
-
- if (esxUtil_ReformatUuid(uuid_string, key_candidate) < 0) {
- goto cleanup;
- }
-
- if (STREQ(key, key_candidate)) {
- /* Found matching UUID */
- volume = virGetStorageVol(conn, datastoreName,
- volumeName, key);
- goto cleanup;
- }
- }
+ /* lookup by key operation is supported using connection
+ * pointer, so poke all supported backend drivers to perform
+ * the desired operation
+ */
+ for (i = 0; i < LAST_DRIVER; ++i) {
+ volume = backendDrv[i]->volLookupByKey(conn, key);
+ if (volume != NULL) {
+ break;
}
}
- cleanup:
- esxVI_String_Free(&propertyNameList);
- esxVI_ObjectContent_Free(&datastoreList);
- esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList);
- VIR_FREE(directoryAndFileName);
- VIR_FREE(datastorePath);
- VIR_FREE(volumeName);
- VIR_FREE(uuid_string);
+cleanup:
return volume;
+
}
@@ -961,224 +519,22 @@ esxStorageVolumeCreateXML(virStoragePoolPtr pool, const char *xmldesc,
{
virStorageVolPtr volume = NULL;
esxPrivate *priv = pool->conn->storagePrivateData;
- virStoragePoolDef poolDef;
- virStorageVolDefPtr def = NULL;
- char *tmp;
- char *unescapedDatastorePath = NULL;
- char *unescapedDirectoryName = NULL;
- char *unescapedDirectoryAndFileName = NULL;
- char *directoryName = NULL;
- char *fileName = NULL;
- char *datastorePathWithoutFileName = NULL;
- char *datastorePath = NULL;
- esxVI_FileInfo *fileInfo = NULL;
- esxVI_FileBackedVirtualDiskSpec *virtualDiskSpec = NULL;
- esxVI_ManagedObjectReference *task = NULL;
- esxVI_TaskInfoState taskInfoState;
- char *taskInfoErrorMessage = NULL;
- char *uuid_string = NULL;
- char *key = NULL;
-
- virCheckFlags(0, NULL);
-
- memset(&poolDef, 0, sizeof(poolDef));
-
- if (esxVI_EnsureSession(priv->primary) < 0) {
- return NULL;
- }
-
- if (esxStoragePoolLookupType(priv->primary, pool->name, &poolDef.type) < 0) {
- return NULL;
- }
-
- /* Parse config */
- def = virStorageVolDefParseString(&poolDef, xmldesc);
-
- if (def == NULL) {
- goto cleanup;
- }
-
- if (def->type != VIR_STORAGE_VOL_FILE) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Creating non-file volumes is not supported"));
- goto cleanup;
- }
-
- /* Validate config */
- tmp = strrchr(def->name, '/');
-
- if (tmp == NULL || *def->name == '/' || tmp[1] == '\0') {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Volume name '%s' doesn't have expected format "
- "'<directory>/<file>'"), def->name);
- goto cleanup;
- }
-
- if (! virFileHasSuffix(def->name, ".vmdk")) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Volume name '%s' has unsupported suffix, expecting '.vmdk'"),
- def->name);
- goto cleanup;
- }
-
- if (virAsprintf(&unescapedDatastorePath, "[%s] %s", pool->name,
- def->name) < 0) {
- virReportOOMError();
- goto cleanup;
- }
-
- if (def->target.format == VIR_STORAGE_FILE_VMDK) {
- /* Parse and escape datastore path */
- if (esxUtil_ParseDatastorePath(unescapedDatastorePath, NULL,
- &unescapedDirectoryName,
- &unescapedDirectoryAndFileName) < 0) {
- goto cleanup;
- }
-
- directoryName = esxUtil_EscapeDatastoreItem(unescapedDirectoryName);
-
- if (directoryName == NULL) {
- goto cleanup;
- }
-
- fileName = esxUtil_EscapeDatastoreItem(unescapedDirectoryAndFileName +
- strlen(unescapedDirectoryName) + 1);
-
- if (fileName == NULL) {
- goto cleanup;
- }
-
- if (virAsprintf(&datastorePathWithoutFileName, "[%s] %s", pool->name,
- directoryName) < 0) {
- virReportOOMError();
- goto cleanup;
- }
-
- if (virAsprintf(&datastorePath, "[%s] %s/%s", pool->name, directoryName,
- fileName) < 0) {
- virReportOOMError();
- goto cleanup;
- }
-
- /* Create directory, if it doesn't exist yet */
- if (esxVI_LookupFileInfoByDatastorePath
- (priv->primary, datastorePathWithoutFileName, true, &fileInfo,
- esxVI_Occurrence_OptionalItem) < 0) {
- goto cleanup;
- }
-
- if (fileInfo == NULL) {
- if (esxVI_MakeDirectory(priv->primary, datastorePathWithoutFileName,
- priv->primary->datacenter->_reference,
- esxVI_Boolean_True) < 0) {
- goto cleanup;
- }
- }
+ virStorageDriverPtr backendDrvPtr = NULL;
- /* Create VirtualDisk */
- if (esxVI_FileBackedVirtualDiskSpec_Alloc(&virtualDiskSpec) < 0 ||
- esxVI_Long_Alloc(&virtualDiskSpec->capacityKb) < 0) {
- goto cleanup;
- }
-
- /* From the vSphere API documentation about VirtualDiskType ... */
- if (def->allocation == def->capacity) {
- /*
- * "A preallocated disk has all space allocated at creation time
- * and the space is zeroed on demand as the space is used."
- */
- virtualDiskSpec->diskType = (char *)"preallocated";
- } else if (def->allocation == 0) {
- /*
- * "Space required for thin-provisioned virtual disk is allocated
- * and zeroed on demand as the space is used."
- */
- virtualDiskSpec->diskType = (char *)"thin";
- } else {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Unsupported capacity-to-allocation relation"));
- goto cleanup;
- }
-
- /*
- * FIXME: The adapter type is a required parameter, but there is no
- * way to let the user specify it in the volume XML config. Therefore,
- * default to 'busLogic' here.
- */
- virtualDiskSpec->adapterType = (char *)"busLogic";
-
- virtualDiskSpec->capacityKb->value =
- VIR_DIV_UP(def->capacity, 1024); /* Scale from byte to kilobyte */
-
- if (esxVI_CreateVirtualDisk_Task
- (priv->primary, datastorePath, priv->primary->datacenter->_reference,
- esxVI_VirtualDiskSpec_DynamicCast(virtualDiskSpec), &task) < 0 ||
- esxVI_WaitForTaskCompletion(priv->primary, task, NULL,
- esxVI_Occurrence_None,
- priv->parsedUri->autoAnswer,
- &taskInfoState,
- &taskInfoErrorMessage) < 0) {
- goto cleanup;
- }
-
- if (taskInfoState != esxVI_TaskInfoState_Success) {
- virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not create volume: %s"),
- taskInfoErrorMessage);
- goto cleanup;
- }
+ virCheckNonNullArgGoto(xmldesc, cleanup);
+ virCheckNonNullArgGoto(pool->privateData, cleanup);
- if (priv->primary->hasQueryVirtualDiskUuid) {
- if (VIR_ALLOC_N(key, VIR_UUID_STRING_BUFLEN) < 0) {
- virReportOOMError();
- goto cleanup;
- }
-
- if (esxVI_QueryVirtualDiskUuid(priv->primary, datastorePath,
- priv->primary->datacenter->_reference,
- &uuid_string) < 0) {
- goto cleanup;
- }
-
- if (esxUtil_ReformatUuid(uuid_string, key) < 0) {
- goto cleanup;
- }
- } else {
- /* Fall back to the path as key */
- if (esxVI_String_DeepCopyValue(&key, datastorePath) < 0) {
- goto cleanup;
- }
- }
- } else {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Creation of %s volumes is not supported"),
- virStorageFileFormatTypeToString(def->target.format));
+ if (esxVI_EnsureSession(priv->primary) < 0) {
goto cleanup;
}
- volume = virGetStorageVol(pool->conn, pool->name, def->name, key);
+ backendDrvPtr = (virStorageDriverPtr) pool->privateData;
+ volume = backendDrvPtr->volCreateXML(pool, xmldesc, flags);
cleanup:
- if (virtualDiskSpec != NULL) {
- virtualDiskSpec->diskType = NULL;
- virtualDiskSpec->adapterType = NULL;
- }
-
- virStorageVolDefFree(def);
- VIR_FREE(unescapedDatastorePath);
- VIR_FREE(unescapedDirectoryName);
- VIR_FREE(unescapedDirectoryAndFileName);
- VIR_FREE(directoryName);
- VIR_FREE(fileName);
- VIR_FREE(datastorePathWithoutFileName);
- VIR_FREE(datastorePath);
- esxVI_FileInfo_Free(&fileInfo);
- esxVI_FileBackedVirtualDiskSpec_Free(&virtualDiskSpec);
- esxVI_ManagedObjectReference_Free(&task);
- VIR_FREE(taskInfoErrorMessage);
- VIR_FREE(uuid_string);
- VIR_FREE(key);
return volume;
+
}
@@ -1189,193 +545,22 @@ esxStorageVolumeCreateXMLFrom(virStoragePoolPtr pool, const char *xmldesc,
{
virStorageVolPtr volume = NULL;
esxPrivate *priv = pool->conn->storagePrivateData;
- virStoragePoolDef poolDef;
- char *sourceDatastorePath = NULL;
- virStorageVolDefPtr def = NULL;
- char *tmp;
- char *unescapedDatastorePath = NULL;
- char *unescapedDirectoryName = NULL;
- char *unescapedDirectoryAndFileName = NULL;
- char *directoryName = NULL;
- char *fileName = NULL;
- char *datastorePathWithoutFileName = NULL;
- char *datastorePath = NULL;
- esxVI_FileInfo *fileInfo = NULL;
- esxVI_ManagedObjectReference *task = NULL;
- esxVI_TaskInfoState taskInfoState;
- char *taskInfoErrorMessage = NULL;
- char *uuid_string = NULL;
- char *key = NULL;
-
- virCheckFlags(0, NULL);
-
- memset(&poolDef, 0, sizeof(poolDef));
-
- if (esxVI_EnsureSession(priv->primary) < 0) {
- return NULL;
- }
-
- if (esxStoragePoolLookupType(priv->primary, pool->name, &poolDef.type) < 0) {
- return NULL;
- }
-
- if (virAsprintf(&sourceDatastorePath, "[%s] %s", sourceVolume->pool,
- sourceVolume->name) < 0) {
- virReportOOMError();
- goto cleanup;
- }
-
- /* Parse config */
- def = virStorageVolDefParseString(&poolDef, xmldesc);
-
- if (def == NULL) {
- goto cleanup;
- }
-
- if (def->type != VIR_STORAGE_VOL_FILE) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Creating non-file volumes is not supported"));
- goto cleanup;
- }
-
- /* Validate config */
- tmp = strrchr(def->name, '/');
-
- if (tmp == NULL || *def->name == '/' || tmp[1] == '\0') {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Volume name '%s' doesn't have expected format "
- "'<directory>/<file>'"), def->name);
- goto cleanup;
- }
-
- if (! virFileHasSuffix(def->name, ".vmdk")) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Volume name '%s' has unsupported suffix, expecting '.vmdk'"),
- def->name);
- goto cleanup;
- }
-
- if (virAsprintf(&unescapedDatastorePath, "[%s] %s", pool->name,
- def->name) < 0) {
- virReportOOMError();
- goto cleanup;
- }
+ virStorageDriverPtr backendDrvPtr = NULL;
- if (def->target.format == VIR_STORAGE_FILE_VMDK) {
- /* Parse and escape datastore path */
- if (esxUtil_ParseDatastorePath(unescapedDatastorePath, NULL,
- &unescapedDirectoryName,
- &unescapedDirectoryAndFileName) < 0) {
- goto cleanup;
- }
+ virCheckNonNullArgGoto(xmldesc, cleanup);
+ virCheckNonNullArgGoto(pool->privateData, cleanup);
- directoryName = esxUtil_EscapeDatastoreItem(unescapedDirectoryName);
-
- if (directoryName == NULL) {
- goto cleanup;
- }
-
- fileName = esxUtil_EscapeDatastoreItem(unescapedDirectoryAndFileName +
- strlen(unescapedDirectoryName) + 1);
-
- if (fileName == NULL) {
- goto cleanup;
- }
-
- if (virAsprintf(&datastorePathWithoutFileName, "[%s] %s", pool->name,
- directoryName) < 0) {
- virReportOOMError();
- goto cleanup;
- }
-
- if (virAsprintf(&datastorePath, "[%s] %s/%s", pool->name, directoryName,
- fileName) < 0) {
- virReportOOMError();
- goto cleanup;
- }
-
- /* Create directory, if it doesn't exist yet */
- if (esxVI_LookupFileInfoByDatastorePath
- (priv->primary, datastorePathWithoutFileName, true, &fileInfo,
- esxVI_Occurrence_OptionalItem) < 0) {
- goto cleanup;
- }
-
- if (fileInfo == NULL) {
- if (esxVI_MakeDirectory(priv->primary, datastorePathWithoutFileName,
- priv->primary->datacenter->_reference,
- esxVI_Boolean_True) < 0) {
- goto cleanup;
- }
- }
-
- /* Copy VirtualDisk */
- if (esxVI_CopyVirtualDisk_Task(priv->primary, sourceDatastorePath,
- priv->primary->datacenter->_reference,
- datastorePath,
- priv->primary->datacenter->_reference,
- NULL, esxVI_Boolean_False, &task) < 0 ||
- esxVI_WaitForTaskCompletion(priv->primary, task, NULL,
- esxVI_Occurrence_None,
- priv->parsedUri->autoAnswer,
- &taskInfoState,
- &taskInfoErrorMessage) < 0) {
- goto cleanup;
- }
-
- if (taskInfoState != esxVI_TaskInfoState_Success) {
- virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not copy volume: %s"),
- taskInfoErrorMessage);
- goto cleanup;
- }
-
- if (priv->primary->hasQueryVirtualDiskUuid) {
- if (VIR_ALLOC_N(key, VIR_UUID_STRING_BUFLEN) < 0) {
- virReportOOMError();
- goto cleanup;
- }
-
- if (esxVI_QueryVirtualDiskUuid(priv->primary, datastorePath,
- priv->primary->datacenter->_reference,
- &uuid_string) < 0) {
- goto cleanup;
- }
-
- if (esxUtil_ReformatUuid(uuid_string, key) < 0) {
- goto cleanup;
- }
- } else {
- /* Fall back to the path as key */
- if (esxVI_String_DeepCopyValue(&key, datastorePath) < 0) {
- goto cleanup;
- }
- }
- } else {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Creation of %s volumes is not supported"),
- virStorageFileFormatTypeToString(def->target.format));
+ if (esxVI_EnsureSession(priv->primary) < 0) {
goto cleanup;
}
- volume = virGetStorageVol(pool->conn, pool->name, def->name, key);
+ backendDrvPtr = (virStorageDriverPtr) pool->privateData;
+ volume = backendDrvPtr->volCreateXMLFrom(pool, xmldesc, sourceVolume, flags);
cleanup:
- VIR_FREE(sourceDatastorePath);
- virStorageVolDefFree(def);
- VIR_FREE(unescapedDatastorePath);
- VIR_FREE(unescapedDirectoryName);
- VIR_FREE(unescapedDirectoryAndFileName);
- VIR_FREE(directoryName);
- VIR_FREE(fileName);
- VIR_FREE(datastorePathWithoutFileName);
- VIR_FREE(datastorePath);
- esxVI_FileInfo_Free(&fileInfo);
- esxVI_ManagedObjectReference_Free(&task);
- VIR_FREE(taskInfoErrorMessage);
- VIR_FREE(uuid_string);
- VIR_FREE(key);
return volume;
+
}
@@ -1383,48 +568,27 @@ esxStorageVolumeCreateXMLFrom(virStoragePoolPtr pool, const char *xmldesc,
static int
esxStorageVolumeDelete(virStorageVolPtr volume, unsigned int flags)
{
- int result = -1;
+ int err = -1;
esxPrivate *priv = volume->conn->storagePrivateData;
- char *datastorePath = NULL;
- esxVI_ManagedObjectReference *task = NULL;
- esxVI_TaskInfoState taskInfoState;
- char *taskInfoErrorMessage = NULL;
+ virStorageDriverPtr backendDrvPtr = NULL;
- virCheckFlags(0, -1);
+ virCheckNonNullArgGoto(volume->privateData, cleanup);
if (esxVI_EnsureSession(priv->primary) < 0) {
return -1;
}
- if (virAsprintf(&datastorePath, "[%s] %s", volume->pool, volume->name) < 0) {
- virReportOOMError();
- goto cleanup;
- }
-
- if (esxVI_DeleteVirtualDisk_Task(priv->primary, datastorePath,
- priv->primary->datacenter->_reference,
- &task) < 0 ||
- esxVI_WaitForTaskCompletion(priv->primary, task, NULL,
- esxVI_Occurrence_None,
- priv->parsedUri->autoAnswer,
- &taskInfoState, &taskInfoErrorMessage) < 0) {
+ backendDrvPtr = (virStorageDriverPtr) volume->privateData;
+ if (backendDrvPtr->volDelete(volume , flags) < 0) {
goto cleanup;
}
- if (taskInfoState != esxVI_TaskInfoState_Success) {
- virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not delete volume: %s"),
- taskInfoErrorMessage);
- goto cleanup;
- }
+ err = 0;
- result = 0;
+cleanup:
- cleanup:
- VIR_FREE(datastorePath);
- esxVI_ManagedObjectReference_Free(&task);
- VIR_FREE(taskInfoErrorMessage);
+ return err;
- return result;
}
@@ -1432,97 +596,54 @@ esxStorageVolumeDelete(virStorageVolPtr volume, unsigned int flags)
static int
esxStorageVolumeWipe(virStorageVolPtr volume, unsigned int flags)
{
- int result = -1;
+ int err = -1;
esxPrivate *priv = volume->conn->storagePrivateData;
- char *datastorePath = NULL;
- esxVI_ManagedObjectReference *task = NULL;
- esxVI_TaskInfoState taskInfoState;
- char *taskInfoErrorMessage = NULL;
+ virStorageDriverPtr backendDrvPtr = NULL;
- virCheckFlags(0, -1);
+ virCheckNonNullArgGoto(volume->privateData, cleanup);
if (esxVI_EnsureSession(priv->primary) < 0) {
- return -1;
- }
-
- if (virAsprintf(&datastorePath, "[%s] %s", volume->pool, volume->name) < 0) {
- virReportOOMError();
goto cleanup;
}
- if (esxVI_ZeroFillVirtualDisk_Task(priv->primary, datastorePath,
- priv->primary->datacenter->_reference,
- &task) < 0 ||
- esxVI_WaitForTaskCompletion(priv->primary, task, NULL,
- esxVI_Occurrence_None,
- priv->parsedUri->autoAnswer,
- &taskInfoState, &taskInfoErrorMessage) < 0) {
+ backendDrvPtr = (virStorageDriverPtr) volume->privateData;
+ if (backendDrvPtr->volWipe(volume , flags) < 0) {
goto cleanup;
}
- if (taskInfoState != esxVI_TaskInfoState_Success) {
- virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not wipe volume: %s"),
- taskInfoErrorMessage);
- goto cleanup;
- }
+ err = 0;
- result = 0;
+ cleanup:
- cleanup:
- VIR_FREE(datastorePath);
- esxVI_ManagedObjectReference_Free(&task);
- VIR_FREE(taskInfoErrorMessage);
+ return err;
- return result;
}
-
static int
esxStorageVolumeGetInfo(virStorageVolPtr volume, virStorageVolInfoPtr info)
{
- int result = -1;
+ int err = -1;
esxPrivate *priv = volume->conn->storagePrivateData;
- char *datastorePath = NULL;
- esxVI_FileInfo *fileInfo = NULL;
- esxVI_VmDiskFileInfo *vmDiskFileInfo = NULL;
+ virStorageDriverPtr backendDrvPtr = NULL;
- memset(info, 0, sizeof(*info));
+ virCheckNonNullArgGoto(volume->privateData, cleanup);
if (esxVI_EnsureSession(priv->primary) < 0) {
- return -1;
- }
-
- if (virAsprintf(&datastorePath, "[%s] %s", volume->pool, volume->name) < 0) {
- virReportOOMError();
goto cleanup;
}
- if (esxVI_LookupFileInfoByDatastorePath(priv->primary, datastorePath,
- false, &fileInfo,
- esxVI_Occurrence_RequiredItem) < 0) {
+ backendDrvPtr = (virStorageDriverPtr) volume->privateData;
+ if (backendDrvPtr->volGetInfo(volume , info) < 0) {
goto cleanup;
}
- vmDiskFileInfo = esxVI_VmDiskFileInfo_DynamicCast(fileInfo);
+ err = 0;
- info->type = VIR_STORAGE_VOL_FILE;
+ cleanup:
- if (vmDiskFileInfo != NULL) {
- info->capacity = vmDiskFileInfo->capacityKb->value * 1024; /* Scale from kilobyte to byte */
- info->allocation = vmDiskFileInfo->fileSize->value;
- } else {
- info->capacity = fileInfo->fileSize->value;
- info->allocation = fileInfo->fileSize->value;
- }
-
- result = 0;
-
- cleanup:
- VIR_FREE(datastorePath);
- esxVI_FileInfo_Free(&fileInfo);
+ return err;
- return result;
}
@@ -1530,84 +651,24 @@ esxStorageVolumeGetInfo(virStorageVolPtr volume, virStorageVolInfoPtr info)
static char *
esxStorageVolumeGetXMLDesc(virStorageVolPtr volume, unsigned int flags)
{
- esxPrivate *priv = volume->conn->storagePrivateData;
- virStoragePoolDef pool;
- char *datastorePath = NULL;
- esxVI_FileInfo *fileInfo = NULL;
- esxVI_VmDiskFileInfo *vmDiskFileInfo = NULL;
- esxVI_IsoImageFileInfo *isoImageFileInfo = NULL;
- esxVI_FloppyImageFileInfo *floppyImageFileInfo = NULL;
- virStorageVolDef def;
char *xml = NULL;
+ esxPrivate *priv = volume->conn->storagePrivateData;
+ virStorageDriverPtr backendDrvPtr = NULL;
- virCheckFlags(0, NULL);
-
- memset(&pool, 0, sizeof(pool));
- memset(&def, 0, sizeof(def));
+ virCheckNonNullArgGoto(volume->privateData, cleanup);
if (esxVI_EnsureSession(priv->primary) < 0) {
- return NULL;
- }
-
- if (esxStoragePoolLookupType(priv->primary, volume->pool, &pool.type) < 0) {
- return NULL;
- }
-
- /* Lookup file info */
- if (virAsprintf(&datastorePath, "[%s] %s", volume->pool, volume->name) < 0) {
- virReportOOMError();
goto cleanup;
}
- if (esxVI_LookupFileInfoByDatastorePath(priv->primary, datastorePath,
- false, &fileInfo,
- esxVI_Occurrence_RequiredItem) < 0) {
- goto cleanup;
- }
+ backendDrvPtr = (virStorageDriverPtr) volume->privateData;
- vmDiskFileInfo = esxVI_VmDiskFileInfo_DynamicCast(fileInfo);
- isoImageFileInfo = esxVI_IsoImageFileInfo_DynamicCast(fileInfo);
- floppyImageFileInfo = esxVI_FloppyImageFileInfo_DynamicCast(fileInfo);
+ xml = backendDrvPtr->volGetXMLDesc(volume, flags);
- def.name = volume->name;
-
- if (esxVI_LookupStorageVolumeKeyByDatastorePath(priv->primary, datastorePath,
- &def.key) < 0) {
- goto cleanup;
- }
-
- def.type = VIR_STORAGE_VOL_FILE;
- def.target.path = datastorePath;
-
- if (vmDiskFileInfo != NULL) {
- def.capacity = vmDiskFileInfo->capacityKb->value * 1024; /* Scale from kilobyte to byte */
- def.allocation = vmDiskFileInfo->fileSize->value;
-
- def.target.format = VIR_STORAGE_FILE_VMDK;
- } else if (isoImageFileInfo != NULL) {
- def.capacity = fileInfo->fileSize->value;
- def.allocation = fileInfo->fileSize->value;
-
- def.target.format = VIR_STORAGE_FILE_ISO;
- } else if (floppyImageFileInfo != NULL) {
- def.capacity = fileInfo->fileSize->value;
- def.allocation = fileInfo->fileSize->value;
-
- def.target.format = VIR_STORAGE_FILE_RAW;
- } else {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("File '%s' has unknown type"), datastorePath);
- goto cleanup;
- }
-
- xml = virStorageVolDefFormat(&pool, &def);
-
- cleanup:
- VIR_FREE(datastorePath);
- esxVI_FileInfo_Free(&fileInfo);
- VIR_FREE(def.key);
+ cleanup:
return xml;
+
}
@@ -1615,14 +676,24 @@ esxStorageVolumeGetXMLDesc(virStorageVolPtr volume, unsigned int flags)
static char *
esxStorageVolumeGetPath(virStorageVolPtr volume)
{
- char *path;
+ char *path = NULL;
+ esxPrivate *priv = volume->conn->storagePrivateData;
+ virStorageDriverPtr backendDrvPtr = NULL;
- if (virAsprintf(&path, "[%s] %s", volume->pool, volume->name) < 0) {
- virReportOOMError();
- return NULL;
+ virCheckNonNullArgGoto(volume->privateData, cleanup);
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ goto cleanup;
}
+ backendDrvPtr = (virStorageDriverPtr) volume->privateData;
+
+ path = backendDrvPtr->volGetPath(volume);
+
+ cleanup:
+
return path;
+
}
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index f3224f8..9fb2c11 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -3107,7 +3107,8 @@ esxVI_LookupDatastoreByAbsolutePath(esxVI_Context *ctx,
int
esxVI_LookupDatastoreHostMount(esxVI_Context *ctx,
esxVI_ManagedObjectReference *datastore,
- esxVI_DatastoreHostMount **hostMount)
+ esxVI_DatastoreHostMount **hostMount,
+ esxVI_Occurrence occurrence)
{
int result = -1;
esxVI_String *propertyNameList = NULL;
@@ -3155,7 +3156,7 @@ esxVI_LookupDatastoreHostMount(esxVI_Context *ctx,
break;
}
- if (*hostMount == NULL) {
+ if (*hostMount == NULL && occurrence == esxVI_Occurrence_RequiredItem) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not lookup datastore host mount"));
goto cleanup;
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index a9c12c8..d7895a0 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -441,7 +441,8 @@ int esxVI_LookupDatastoreByAbsolutePath(esxVI_Context *ctx,
int esxVI_LookupDatastoreHostMount(esxVI_Context *ctx,
esxVI_ManagedObjectReference *datastore,
- esxVI_DatastoreHostMount **hostMount);
+ esxVI_DatastoreHostMount **hostMount,
+ esxVI_Occurrence occurrence);
int esxVI_LookupTaskInfoByTask(esxVI_Context *ctx,
esxVI_ManagedObjectReference *task,
diff --git a/src/parallels/parallels_storage.c b/src/parallels/parallels_storage.c
index 71f3f89..8d4e2c6 100644
--- a/src/parallels/parallels_storage.c
+++ b/src/parallels/parallels_storage.c
@@ -350,7 +350,8 @@ parallelsStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
goto cleanup;
}
- ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);
+ ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
+ NULL, NULL);
cleanup:
if (pool)
@@ -374,7 +375,8 @@ parallelsStoragePoolLookupByName(virConnectPtr conn, const char *name)
goto cleanup;
}
- ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);
+ ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
+ NULL, NULL);
cleanup:
if (pool)
@@ -459,7 +461,8 @@ parallelsStoragePoolDefine(virConnectPtr conn,
goto cleanup;
}
- ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);
+ ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
+ NULL, NULL);
cleanup:
virStoragePoolDefFree(def);
@@ -831,7 +834,8 @@ parallelsStorageVolumeLookupByName(virStoragePoolPtr pool,
}
ret = virGetStorageVol(pool->conn, privpool->def->name,
- privvol->name, privvol->key);
+ privvol->name, privvol->key,
+ NULL, NULL);
cleanup:
if (privpool)
@@ -857,7 +861,8 @@ parallelsStorageVolumeLookupByKey(virConnectPtr conn, const char *key)
if (privvol) {
ret = virGetStorageVol(conn,
privconn->pools.objs[i]->def->name,
- privvol->name, privvol->key);
+ privvol->name, privvol->key,
+ NULL, NULL);
virStoragePoolObjUnlock(privconn->pools.objs[i]);
break;
}
@@ -889,7 +894,8 @@ parallelsStorageVolumeLookupByPathLocked(virConnectPtr conn, const char *path)
if (privvol) {
ret = virGetStorageVol(conn,
privconn->pools.objs[i]->def->name,
- privvol->name, privvol->key);
+ privvol->name, privvol->key,
+ NULL, NULL);
virStoragePoolObjUnlock(privconn->pools.objs[i]);
break;
}
@@ -1026,7 +1032,8 @@ parallelsStorageVolumeCreateXML(virStoragePoolPtr pool,
goto cleanup;
ret = virGetStorageVol(pool->conn, privpool->def->name,
- privvol->name, privvol->key);
+ privvol->name, privvol->key,
+ NULL, NULL);
cleanup:
if (privpool)
virStoragePoolObjUnlock(privpool);
@@ -1115,7 +1122,8 @@ parallelsStorageVolumeCreateXMLFrom(virStoragePoolPtr pool,
privpool->volumes.objs[privpool->volumes.count++] = privvol;
ret = virGetStorageVol(pool->conn, privpool->def->name,
- privvol->name, privvol->key);
+ privvol->name, privvol->key,
+ NULL, NULL);
privvol = NULL;
cleanup:
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 62b7729..ec33698 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -5863,13 +5863,15 @@ get_nonnull_interface(virConnectPtr conn, remote_nonnull_interface iface)
static virStoragePoolPtr
get_nonnull_storage_pool(virConnectPtr conn, remote_nonnull_storage_pool pool)
{
- return virGetStoragePool(conn, pool.name, BAD_CAST pool.uuid);
+ return virGetStoragePool(conn, pool.name, BAD_CAST pool.uuid,
+ NULL, NULL);
}
static virStorageVolPtr
get_nonnull_storage_vol(virConnectPtr conn, remote_nonnull_storage_vol vol)
{
- return virGetStorageVol(conn, vol.pool, vol.name, vol.key);
+ return virGetStorageVol(conn, vol.pool, vol.name, vol.key,
+ NULL, NULL);
}
static virNodeDevicePtr
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index faca2a2..2e33b80 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -273,7 +273,8 @@ storagePoolLookupByUUID(virConnectPtr conn,
goto cleanup;
}
- ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);
+ ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
+ NULL, NULL);
cleanup:
if (pool)
@@ -298,7 +299,8 @@ storagePoolLookupByName(virConnectPtr conn,
goto cleanup;
}
- ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);
+ ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
+ NULL, NULL);
cleanup:
if (pool)
@@ -555,7 +557,8 @@ storagePoolCreate(virConnectPtr conn,
VIR_INFO("Creating storage pool '%s'", pool->def->name);
pool->active = 1;
- ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);
+ ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
+ NULL, NULL);
cleanup:
virStoragePoolDefFree(def);
@@ -601,7 +604,8 @@ storagePoolDefine(virConnectPtr conn,
def = NULL;
VIR_INFO("Defining storage pool '%s'", pool->def->name);
- ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);
+ ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
+ NULL, NULL);
cleanup:
virStoragePoolDefFree(def);
@@ -1202,7 +1206,8 @@ storagePoolListAllVolumes(virStoragePoolPtr pool,
for (i = 0 ; i < obj->volumes.count; i++) {
if (!(vol = virGetStorageVol(pool->conn, obj->def->name,
obj->volumes.objs[i]->name,
- obj->volumes.objs[i]->key)))
+ obj->volumes.objs[i]->key,
+ NULL, NULL)))
goto cleanup;
tmp_vols[nvols++] = vol;
}
@@ -1258,7 +1263,8 @@ storageVolumeLookupByName(virStoragePoolPtr obj,
goto cleanup;
}
- ret = virGetStorageVol(obj->conn, pool->def->name, vol->name, vol->key);
+ ret = virGetStorageVol(obj->conn, pool->def->name, vol->name, vol->key,
+ NULL, NULL);
cleanup:
if (pool)
@@ -1285,7 +1291,8 @@ storageVolumeLookupByKey(virConnectPtr conn,
ret = virGetStorageVol(conn,
driver->pools.objs[i]->def->name,
vol->name,
- vol->key);
+ vol->key,
+ NULL, NULL);
}
virStoragePoolObjUnlock(driver->pools.objs[i]);
}
@@ -1338,7 +1345,8 @@ storageVolumeLookupByPath(virConnectPtr conn,
ret = virGetStorageVol(conn,
driver->pools.objs[i]->def->name,
vol->name,
- vol->key);
+ vol->key,
+ NULL, NULL);
}
virStoragePoolObjUnlock(driver->pools.objs[i]);
}
@@ -1415,7 +1423,7 @@ storageVolumeCreateXML(virStoragePoolPtr obj,
pool->volumes.objs[pool->volumes.count++] = voldef;
volobj = virGetStorageVol(obj->conn, pool->def->name, voldef->name,
- voldef->key);
+ voldef->key, NULL, NULL);
if (!volobj) {
pool->volumes.count--;
goto cleanup;
@@ -1587,7 +1595,7 @@ storageVolumeCreateXMLFrom(virStoragePoolPtr obj,
pool->volumes.objs[pool->volumes.count++] = newvol;
volobj = virGetStorageVol(obj->conn, pool->def->name, newvol->name,
- newvol->key);
+ newvol->key, NULL, NULL);
/* Drop the pool lock during volume allocation */
pool->asyncjobs++;
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 9e4d9f2..6ca59e2 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -3885,7 +3885,8 @@ testStoragePoolLookupByUUID(virConnectPtr conn,
goto cleanup;
}
- ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);
+ ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
+ NULL, NULL);
cleanup:
if (pool)
@@ -3909,7 +3910,8 @@ testStoragePoolLookupByName(virConnectPtr conn,
goto cleanup;
}
- ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);
+ ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
+ NULL, NULL);
cleanup:
if (pool)
@@ -4201,7 +4203,8 @@ testStoragePoolCreate(virConnectPtr conn,
}
pool->active = 1;
- ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);
+ ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
+ NULL, NULL);
cleanup:
virStoragePoolDefFree(def);
@@ -4241,7 +4244,8 @@ testStoragePoolDefine(virConnectPtr conn,
goto cleanup;
}
- ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);
+ ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
+ NULL, NULL);
cleanup:
virStoragePoolDefFree(def);
@@ -4668,7 +4672,8 @@ testStoragePoolListAllVolumes(virStoragePoolPtr obj,
for (i = 0 ; i < pool->volumes.count; i++) {
if (!(vol = virGetStorageVol(obj->conn, pool->def->name,
pool->volumes.objs[i]->name,
- pool->volumes.objs[i]->key)))
+ pool->volumes.objs[i]->key,
+ NULL, NULL)))
goto cleanup;
tmp_vols[nvols++] = vol;
}
@@ -4725,7 +4730,8 @@ testStorageVolumeLookupByName(virStoragePoolPtr pool,
}
ret = virGetStorageVol(pool->conn, privpool->def->name,
- privvol->name, privvol->key);
+ privvol->name, privvol->key,
+ NULL, NULL);
cleanup:
if (privpool)
@@ -4752,7 +4758,8 @@ testStorageVolumeLookupByKey(virConnectPtr conn,
ret = virGetStorageVol(conn,
privconn->pools.objs[i]->def->name,
privvol->name,
- privvol->key);
+ privvol->key,
+ NULL, NULL);
virStoragePoolObjUnlock(privconn->pools.objs[i]);
break;
}
@@ -4786,7 +4793,8 @@ testStorageVolumeLookupByPath(virConnectPtr conn,
ret = virGetStorageVol(conn,
privconn->pools.objs[i]->def->name,
privvol->name,
- privvol->key);
+ privvol->key,
+ NULL, NULL);
virStoragePoolObjUnlock(privconn->pools.objs[i]);
break;
}
@@ -4875,7 +4883,8 @@ testStorageVolumeCreateXML(virStoragePoolPtr pool,
privpool->volumes.objs[privpool->volumes.count++] = privvol;
ret = virGetStorageVol(pool->conn, privpool->def->name,
- privvol->name, privvol->key);
+ privvol->name, privvol->key,
+ NULL, NULL);
privvol = NULL;
cleanup:
@@ -4969,7 +4978,8 @@ testStorageVolumeCreateXMLFrom(virStoragePoolPtr pool,
privpool->volumes.objs[privpool->volumes.count++] = privvol;
ret = virGetStorageVol(pool->conn, privpool->def->name,
- privvol->name, privvol->key);
+ privvol->name, privvol->key,
+ NULL, NULL);
privvol = NULL;
cleanup:
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index bcffb2f..f9fa442 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -8321,7 +8321,7 @@ static virStoragePoolPtr vboxStoragePoolLookupByName(virConnectPtr conn, const c
ignore_value(virUUIDParse(uuidstr, uuid));
- ret = virGetStoragePool(conn, name, uuid);
+ ret = virGetStoragePool(conn, name, uuid, NULL, NULL);
}
return ret;
@@ -8450,7 +8450,8 @@ static virStorageVolPtr vboxStorageVolLookupByName(virStoragePoolPtr pool, const
vboxIIDToUUID(&hddIID, uuid);
virUUIDFormat(uuid, key);
- ret = virGetStorageVol(pool->conn, pool->name, name, key);
+ ret = virGetStorageVol(pool->conn, pool->name, name, key,
+ NULL, NULL);
VIR_DEBUG("virStorageVolPtr: %p", ret);
VIR_DEBUG("Storage Volume Name: %s", name);
@@ -8511,7 +8512,8 @@ static virStorageVolPtr vboxStorageVolLookupByKey(virConnectPtr conn, const char
if (hddNameUtf8) {
if (vboxStorageNumOfPools(conn) == 1) {
- ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key);
+ ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key,
+ NULL, NULL);
VIR_DEBUG("Storage Volume Pool: %s", "default-pool");
} else {
/* TODO: currently only one default pool and thus
@@ -8583,7 +8585,8 @@ static virStorageVolPtr vboxStorageVolLookupByPath(virConnectPtr conn, const cha
* the check below, change it when pools are supported
*/
if (vboxStorageNumOfPools(conn) == 1)
- ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key);
+ ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key,
+ NULL, NULL);
VIR_DEBUG("Storage Volume Pool: %s", "default-pool");
VIR_DEBUG("Storage Volume Name: %s", hddNameUtf8);
@@ -8683,7 +8686,8 @@ static virStorageVolPtr vboxStorageVolCreateXML(virStoragePoolPtr pool,
vboxIIDToUUID(&hddIID, uuid);
virUUIDFormat(uuid, key);
- ret = virGetStorageVol(pool->conn, pool->name, def->name, key);
+ ret = virGetStorageVol(pool->conn, pool->name, def->name, key,
+ NULL, NULL);
}
vboxIIDUnalloc(&hddIID);
--
1.7.9.5
2
1
[libvirt] Proposal: no dnsmasq (no dhcp and no dns) and no radvd option
by Gene Czarcinski 27 Nov '12
by Gene Czarcinski 27 Nov '12
27 Nov '12
Laine mentioned something yesterday that got me to thinking: being able
to specify that dnsmasq is not to be started for an interface.
Let me expand that by saying that libvirt would not start dnsmasq for
either dns or dhcp and also would not start radvd. However, the IPv4
and IPv6 gateway addresses would be defined on the virtual network
interface and the "usual" iptables and ip6tables rules would be in force.
This would allow a user to configure dnsmasq to meet any user desires or
use something completely different instead of dnsmasq.
Questions: Useful? Worth the time and effort? And then there is how
should this be specified in the network xml file? ... some new
parameter? ... A subperameter of <dns> such as <dns disable='yes' /> ?
... a subparameter of <bridge> such as <bridge name="virbr0"
dns="disable" /> ?
Comments? Suggestions?
Gene
4
16
Hi,
currently running libvirtd without DBus fails due to:
error : nwfilterDriverStartup:208 : DBus matches could not be installed. Disabling nwfilter driver
error : virDBusGetSystemBus:77 : internal error Unable to get DBus system bus connection: Failed to connect to socket /var/run/dbus/system_bus_socket: No such file or directory
error : virStateInitialize:810 : Initialization of NWFilter state driver failed
error : daemonRunStateInit:784 : Driver state initialization failed
because we fail driver initialization hard in nwfilter_driver.c:
if (nwfilterDriverInstallDBusMatches(sysbus) < 0) {
VIR_ERROR(_("DBus matches could not be installed. Disabling nwfilter "
"driver"));
/*
* unfortunately this is fatal since virNWFilterTechDriversInit
* may have caused the ebiptables driver to use the firewall tool
* but now that the watches don't work, we just disable the nwfilter
* driver
*/
goto error;
}
I wonder if this on prupose or if we can just make this a soft error and
go on without DBus? At least in the !HAVE_FIREWALLD case it should be
o.k. to continue. Shouldn't it? See attached patch.
Cheers,
-- Guido
2
2
This patch series resolves the libvirt part of CVE 2012-3411:
https://bugzilla.redhat.com/show_bug.cgi?id=833033
Further details are in PATCH 3/3.
3
12
When logging an error, don't throw away the detailed information.
Example record when using the journald output:
MESSAGE=Domain not found
PRIORITY=4
LIBVIRT_SOURCE=error
CODE_FILE=../../src/test/test_driver.c
CODE_LINE=1406
CODE_FUNC=testLookupDomainByName
DOMAIN=12
CODE=42
The format used in other output destinations (e.g. "syslog", "file") is
still unchanged.
The "domain" and "code" numbers are part of the libvirt ABI in
<libvirt/virterror.h>; therefore log processing tools can rely on them,
unlike the text log string (which is translated depending on locale,
and may be modified for other reasons as well).
Alternatively, the "domain" and "code" fields could contain strings
instead of numbers, but it's not clear that it's worth it:
Advantages of numbers:
* the numbers are shorter
* the ABI guarantees that the numbers won't change
Disadvantages of strings:
* adding a ABI-stable string mapping for virErrorNumber would result
in additional work each time a new error number is added
(note that virErrorMsg cannot be used for this because it is
translated)
* a change in the string mapping would be less likely to be noticed
The advantage of using strings is more readability, but note that the
"msg" field above already contains a readable description of the
error.
The inability to allocate memory imposes a fixed limit on the number
of metadata fields that can be supported by the journal; fields beyond
this limit are silently dropped (but the initial part of the message
sent). This was implemented in the previous patch, here we just
increase the limit to 32 fields total.
Signed-off-by: Miloslav Trmač <mitr(a)redhat.com>
---
This version drops logging the str[123] and int[12] fields.
The META_ADD_STRING macro is unused; it was left there just to
demonstrate the use of the API in case someone wanted to add more
error-specific information.
---
src/util/logging.c | 13 +++++++++++--
src/util/virterror.c | 23 ++++++++++++++++++++++-
2 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/src/util/logging.c b/src/util/logging.c
index e8fed55..dbffaa1 100644
--- a/src/util/logging.c
+++ b/src/util/logging.c
@@ -1125,7 +1125,7 @@ virLogOutputToJournald(virLogSource source,
int linenr,
const char *funcname,
const char *timestamp ATTRIBUTE_UNUSED,
- virLogMetadataPtr metadata ATTRIBUTE_UNUSED,
+ virLogMetadataPtr metadata,
unsigned int flags,
const char *rawstr,
const char *str ATTRIBUTE_UNUSED,
@@ -1145,7 +1145,7 @@ virLogOutputToJournald(virLogSource source,
* and where unprivileged users can create files. */
char path[] = "/dev/shm/journal.XXXXXX";
-# define NUM_FIELDS 6
+# define NUM_FIELDS 32
struct iovec iov[NUM_FIELDS * 5];
char iov_bufs[NUM_FIELDS][JOURNAL_BUF_SIZE];
struct journalState state;
@@ -1162,6 +1162,15 @@ virLogOutputToJournald(virLogSource source,
journalAddString(&state, "CODE_FILE", filename);
journalAddInt(&state, "CODE_LINE", linenr);
journalAddString(&state, "CODE_FUNC", funcname);
+ if (metadata != NULL) {
+ while (metadata->key != NULL) {
+ if (metadata->s != NULL)
+ journalAddString(&state, metadata->key, metadata->s);
+ else
+ journalAddInt(&state, metadata->key, metadata->i);
+ metadata++;
+ }
+ }
memset(&sa, 0, sizeof(sa));
sa.sun_family = AF_UNIX;
diff --git a/src/util/virterror.c b/src/util/virterror.c
index 213188e..10b627f 100644
--- a/src/util/virterror.c
+++ b/src/util/virterror.c
@@ -619,6 +619,8 @@ virRaiseErrorFull(const char *filename ATTRIBUTE_UNUSED,
virErrorPtr to;
char *str;
int priority;
+ virLogMetadata meta[3];
+ size_t i;
/*
* All errors are recorded in thread local storage
@@ -676,10 +678,29 @@ virRaiseErrorFull(const char *filename ATTRIBUTE_UNUSED,
priority = virErrorLevelPriority(level);
if (virErrorLogPriorityFilter)
priority = virErrorLogPriorityFilter(to, priority);
+
+ i = 0;
+#define META_ADD_STRING(KEY, VALUE) \
+ do { \
+ meta[i].key = (KEY); \
+ meta[i].s = (VALUE); \
+ i++; \
+ } while (0)
+#define META_ADD_INT(KEY, VALUE) \
+ do { \
+ meta[i].key = (KEY); \
+ meta[i].s = NULL; \
+ meta[i].i = (VALUE); \
+ i++; \
+ } while (0)
+
+ META_ADD_INT("DOMAIN", domain);
+ META_ADD_INT("CODE", code);
+ meta[i].key = NULL;
virLogMessage(virErrorLogPriorityFilter ? VIR_LOG_FROM_FILE : VIR_LOG_FROM_ERROR,
priority,
filename, linenr, funcname,
- NULL, "%s", str);
+ meta, "%s", str);
errno = save_errno;
}
--
1.7.11.7
1
0
26 Nov '12
The S390 architecture comes with a native console type (SCLP
console) which is now also supported by current QEMU.
This series is enabling libvirt to configure S390 domains with SCLP
consoles.
The domain XML has to be extended for the new console target types
'sclp' and 'sclplm' (line mode = dumb).
As usual the QEMU driver must do capability probing in order to find
out whether SCLP is supported and format the QEMU command line
for the new console type.
V2 Changes:
Rebased to current master, resolving conflicts.
J.B. Joret (2):
S390: Add SCLP console front end support
S390: Enable SCLP Console in QEMU driver
docs/formatdomain.html.in | 19 ++++++-
docs/schemas/domaincommon.rng | 2 +
src/conf/domain_conf.c | 4 +-
src/conf/domain_conf.h | 2 +
src/qemu/qemu_capabilities.c | 3 ++
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_command.c | 59 ++++++++++++++++++++++
.../qemuxml2argv-console-sclp.args | 8 +++
.../qemuxml2argvdata/qemuxml2argv-console-sclp.xml | 24 +++++++++
tests/qemuxml2argvtest.c | 3 ++
10 files changed, 123 insertions(+), 2 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-console-sclp.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-console-sclp.xml
--
1.7.12.4
1
2
[libvirt] [PATCH v4] qemu: Allow the user to specify vendor and product for disk
by Osier Yang 26 Nov '12
by Osier Yang 26 Nov '12
26 Nov '12
QEMU supports setting vendor and product strings for disk since
1.2.0 (only scsi-disk, scsi-hd, scsi-cd support it), this patch
exposes it with new XML elements <vendor> and <product> of disk
device.
v3 - v4:
* Per Paolo's feedback, allows all printable chars.
---
docs/formatdomain.html.in | 11 +++++
docs/schemas/domaincommon.rng | 14 ++++++
src/conf/domain_conf.c | 44 ++++++++++++++++++++
src/conf/domain_conf.h | 2 +
src/libvirt_private.syms | 1 +
src/qemu/qemu_command.c | 29 +++++++++++++
src/util/util.c | 12 +++++
src/util/util.h | 1 +
...qemuxml2argv-disk-scsi-disk-vpd-build-error.xml | 35 ++++++++++++++++
.../qemuxml2argv-disk-scsi-disk-vpd.args | 13 ++++++
.../qemuxml2argv-disk-scsi-disk-vpd.xml | 38 +++++++++++++++++
tests/qemuxml2argvtest.c | 8 ++++
tests/qemuxml2xmltest.c | 2 +
13 files changed, 210 insertions(+), 0 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd-build-error.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 6a3b976..903c069 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1657,6 +1657,17 @@
of 16 hexadecimal digits.
<span class='since'>Since 0.10.1</span>
</dd>
+ <dt><code>vendor</code></dt>
+ <dd>If present, this element specifies the vendor of a virtual hard
+ disk or CD-ROM device. It must not be longer than 8 printable
+ characters.
+ <span class='since'>Since 1.0.1</span>
+ </dd>
+ <dt><code>product</code></dt>
+ <dd>If present, this element specifies the product of a virtual hard
+ disk or CD-ROM device. It must not be longer than 16 printable
+ <span class='since'>Since 1.0.1</span>
+ </dd>
<dt><code>host</code></dt>
<dd>The <code>host</code> element has two attributes "name" and "port",
which specify the hostname and the port number. The meaning of this
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 02ad477..19bf597 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -905,6 +905,20 @@
<ref name="wwn"/>
</element>
</optional>
+ <optional>
+ <element name="vendor">
+ <data type="string">
+ <param name="pattern">[x20-x7E]{0,8}</param>
+ </data>
+ </element>
+ </optional>
+ <optional>
+ <element name="product">
+ <data type="string">
+ <param name="pattern">[x20-x7E]{0,16}</param>
+ </data>
+ </element>
+ </optional>
</interleave>
</define>
<define name="snapshot">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 047c4fc..e975f74 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -979,6 +979,8 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def)
VIR_FREE(def->mirror);
VIR_FREE(def->auth.username);
VIR_FREE(def->wwn);
+ VIR_FREE(def->vendor);
+ VIR_FREE(def->product);
if (def->auth.secretType == VIR_DOMAIN_DISK_SECRET_TYPE_USAGE)
VIR_FREE(def->auth.secret.usage);
virStorageEncryptionFree(def->encryption);
@@ -3490,6 +3492,8 @@ cleanup:
goto cleanup;
}
+#define VENDOR_LEN 8
+#define PRODUCT_LEN 16
/* Parse the XML definition for a disk
* @param node XML nodeset to parse for disk definition
@@ -3542,6 +3546,8 @@ virDomainDiskDefParseXML(virCapsPtr caps,
char *logical_block_size = NULL;
char *physical_block_size = NULL;
char *wwn = NULL;
+ char *vendor = NULL;
+ char *product = NULL;
if (VIR_ALLOC(def) < 0) {
virReportOOMError();
@@ -3880,6 +3886,36 @@ virDomainDiskDefParseXML(virCapsPtr caps,
if (!virValidateWWN(wwn))
goto error;
+ } else if (!vendor &&
+ xmlStrEqual(cur->name, BAD_CAST "vendor")) {
+ vendor = (char *)xmlNodeGetContent(cur);
+
+ if (strlen(vendor) > VENDOR_LEN) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("disk vendor is more than 8 characters"));
+ goto error;
+ }
+
+ if (!virStrIsPrint(vendor)) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("disk vendor is not printable string"));
+ goto error;
+ }
+ } else if (!product &&
+ xmlStrEqual(cur->name, BAD_CAST "product")) {
+ product = (char *)xmlNodeGetContent(cur);
+
+ if (strlen(vendor) > PRODUCT_LEN) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("disk product is more than 16 characters"));
+ goto error;
+ }
+
+ if (!virStrIsPrint(product)) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("disk product is not printable string"));
+ goto error;
+ }
} else if (xmlStrEqual(cur->name, BAD_CAST "boot")) {
/* boot is parsed as part of virDomainDeviceInfoParseXML */
}
@@ -4176,6 +4212,10 @@ virDomainDiskDefParseXML(virCapsPtr caps,
serial = NULL;
def->wwn = wwn;
wwn = NULL;
+ def->vendor = vendor;
+ vendor = NULL;
+ def->product = product;
+ product = NULL;
if (driverType) {
def->format = virStorageFileFormatTypeFromString(driverType);
@@ -4249,6 +4289,8 @@ cleanup:
VIR_FREE(logical_block_size);
VIR_FREE(physical_block_size);
VIR_FREE(wwn);
+ VIR_FREE(vendor);
+ VIR_FREE(product);
ctxt->node = save_ctxt;
return def;
@@ -12085,6 +12127,8 @@ virDomainDiskDefFormat(virBufferPtr buf,
virBufferAddLit(buf, " <transient/>\n");
virBufferEscapeString(buf, " <serial>%s</serial>\n", def->serial);
virBufferEscapeString(buf, " <wwn>%s</wwn>\n", def->wwn);
+ virBufferEscapeString(buf, " <vendor>%s</vendor>\n", def->vendor);
+ virBufferEscapeString(buf, " <product>%s</product>\n", def->product);
if (def->encryption) {
virBufferAdjustIndent(buf, 6);
if (virStorageEncryptionFormat(buf, def->encryption) < 0)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index c3e8c16..e3522a5 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -591,6 +591,8 @@ struct _virDomainDiskDef {
char *serial;
char *wwn;
+ char *vendor;
+ char *product;
int cachemode;
int error_policy; /* enum virDomainDiskErrorPolicy */
int rerror_policy; /* enum virDomainDiskErrorPolicy */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 756d7bd..8a1f9df 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1280,6 +1280,7 @@ virSetUIDGID;
virSkipSpaces;
virSkipSpacesAndBackslash;
virSkipSpacesBackwards;
+virStrIsPrint;
virStrToDouble;
virStrToLong_i;
virStrToLong_l;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 02e105d..2217ccd 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -2428,6 +2428,13 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
}
}
+ if ((disk->vendor || disk->product) &&
+ disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Only scsi disk supports vendor and product"));
+ goto error;
+ }
+
if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
/* make sure that both the bus and the qemu binary support
* type='lun' (SG_IO).
@@ -2455,6 +2462,11 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
_("Setting wwn is not supported for lun device"));
goto error;
}
+ if (disk->vendor || disk->product) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting vendor or product is not supported for lun device"));
+ goto error;
+ }
}
switch (disk->bus) {
@@ -2504,6 +2516,17 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
goto error;
}
+ /* Properties wwn, vendor and product were introduced in the
+ * same QEMU release (1.2.0).
+ */
+ if ((disk->vendor || disk->product) &&
+ !qemuCapsGet(caps, QEMU_CAPS_SCSI_DISK_WWN)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting vendor or product for scsi disk is not "
+ "supported by this QEMU"));
+ goto error;
+ }
+
controllerModel =
virDomainDiskFindControllerModel(def, disk,
VIR_DOMAIN_CONTROLLER_TYPE_SCSI);
@@ -2649,6 +2672,12 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
if (disk->wwn)
virBufferAsprintf(&opt, ",wwn=%s", disk->wwn);
+ if (disk->vendor)
+ virBufferAsprintf(&opt, ",vendor=%s", disk->vendor);
+
+ if (disk->product)
+ virBufferAsprintf(&opt, ",product=%s", disk->product);
+
if (virBufferError(&opt)) {
virReportOOMError();
goto error;
diff --git a/src/util/util.c b/src/util/util.c
index 75b18c1..ea5d12e 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -3114,3 +3114,15 @@ virValidateWWN(const char *wwn) {
return true;
}
+
+bool
+virStrIsPrint(const char *str)
+{
+ int i;
+
+ for (i = 0; str[i]; i++)
+ if (!c_isprint(str[i]))
+ return false;
+
+ return true;
+}
diff --git a/src/util/util.h b/src/util/util.h
index 4316ab1..6d5dd03 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -280,4 +280,5 @@ bool virIsDevMapperDevice(const char *dev_name) ATTRIBUTE_NONNULL(1);
bool virValidateWWN(const char *wwn);
+bool virStrIsPrint(const char *str);
#endif /* __VIR_UTIL_H__ */
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd-build-error.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd-build-error.xml
new file mode 100644
index 0000000..ca68275
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd-build-error.xml
@@ -0,0 +1,35 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='cdrom'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='sda' bus='virtio'/>
+ <vendor>SEAGATE</vendor>
+ <product>ST3146707LC</product>
+ </disk>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest2'/>
+ <target dev='sdb' bus='scsi'/>
+ <vendor>SEAGATE</vendor>
+ <product>ST3567807GD</product>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'/>
+ <controller type='scsi' index='0' model='virtio-scsi'/>
+ <controller type='scsi' index='1' model='lsilogic'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.args
new file mode 100644
index 0000000..f5c1999
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.args
@@ -0,0 +1,13 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+/usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
+-device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x3 \
+-device lsi,id=scsi1,bus=pci.0,addr=0x4 \
+-usb \
+-drive file=/dev/HostVG/QEMUGuest1,if=none,id=drive-scsi0-0-0-0 \
+-device scsi-cd,bus=scsi0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0-0-0-0,\
+id=scsi0-0-0-0,vendor=SEAGATE,product=ST3146707LC \
+-drive file=/dev/HostVG/QEMUGuest2,if=none,id=drive-scsi1-0-0 \
+-device scsi-hd,bus=scsi1.0,scsi-id=0,drive=drive-scsi1-0-0,\
+id=scsi1-0-0,vendor=SEAGATE,product=ST3567807GD \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.xml
new file mode 100644
index 0000000..96786e3
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.xml
@@ -0,0 +1,38 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='cdrom'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='sda' bus='scsi'/>
+ <readonly/>
+ <vendor>SEAGATE</vendor>
+ <product>ST3146707LC</product>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest2'/>
+ <target dev='sdb' bus='scsi'/>
+ <readonly/>
+ <vendor>SEAGATE</vendor>
+ <product>ST3567807GD</product>
+ <address type='drive' controller='1' bus='0' target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'/>
+ <controller type='scsi' index='0' model='virtio-scsi'/>
+ <controller type='scsi' index='1' model='lsilogic'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 4cccbb0..1f69b6c 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -505,6 +505,14 @@ mymain(void)
QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
QEMU_CAPS_SCSI_CD, QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI_PCI,
QEMU_CAPS_SCSI_DISK_WWN);
+ DO_TEST("disk-scsi-disk-vpd",
+ QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
+ QEMU_CAPS_SCSI_CD, QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI_PCI,
+ QEMU_CAPS_SCSI_DISK_WWN);
+ DO_TEST_FAILURE("disk-scsi-disk-vpd-build-error",
+ QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
+ QEMU_CAPS_SCSI_CD, QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI_PCI,
+ QEMU_CAPS_SCSI_DISK_WWN);
DO_TEST("disk-scsi-vscsi",
QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
DO_TEST("disk-scsi-virtio-scsi",
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 1d366f1..88ef050 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -239,6 +239,8 @@ mymain(void)
DO_TEST("seclabel-none");
DO_TEST("numad-static-vcpu-no-numatune");
+ DO_TEST("disk-scsi-disk-vpd");
+
/* These tests generate different XML */
DO_TEST_DIFFERENT("balloon-device-auto");
DO_TEST_DIFFERENT("channel-virtio-auto");
--
1.7.7.6
1
1
[libvirt] [PATCH] lxc: Avoid segfault of libvirt_lxc helper on early cleanup paths
by Peter Krempa 26 Nov '12
by Peter Krempa 26 Nov '12
26 Nov '12
Early jumps to the cleanup label caused a crash of the libvirt_lxc
container helper as the cleanup section called
virLXCControllerDeleteInterfaces(ctrl) without checking the ctrl argument
for NULL. The argument was de-referenced soon after.
$ /usr/libexec/libvirt_lxc
/usr/libexec/libvirt_lxc: missing --name argument for configuration
Segmentation fault
---
src/lxc/lxc_controller.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index a9d2d40..ea5bc58 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -1672,7 +1672,8 @@ int main(int argc, char *argv[])
cleanup:
virPidFileDelete(LXC_STATE_DIR, name);
- virLXCControllerDeleteInterfaces(ctrl);
+ if (ctrl)
+ virLXCControllerDeleteInterfaces(ctrl);
for (i = 0 ; i < nttyFDs ; i++)
VIR_FORCE_CLOSE(ttyFDs[i]);
VIR_FREE(ttyFDs);
--
1.8.0
2
2
[libvirt] [PATCH] lxc: Don't crash if no security driver is specified in libvirt_lxc
by Peter Krempa 26 Nov '12
by Peter Krempa 26 Nov '12
26 Nov '12
When no security driver is specified libvirt_lxc segfaults as a debug
message tries to access security labels for the container that are not
present.
This problem was introduced in commit 6c3cf57d6cb27cf10064baf8cca0f39.
---
src/lxc/lxc_controller.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index ea5bc58..16cda9d 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -1612,11 +1612,15 @@ int main(int argc, char *argv[])
false, false, false)))
goto cleanup;
- VIR_DEBUG("Security model %s type %s label %s imagelabel %s",
- NULLSTR(ctrl->def->seclabels[0]->model),
- virDomainSeclabelTypeToString(ctrl->def->seclabels[0]->type),
- NULLSTR(ctrl->def->seclabels[0]->label),
- NULLSTR(ctrl->def->seclabels[0]->imagelabel));
+ if (ctrl->def->seclabels) {
+ VIR_DEBUG("Security model %s type %s label %s imagelabel %s",
+ NULLSTR(ctrl->def->seclabels[0]->model),
+ virDomainSeclabelTypeToString(ctrl->def->seclabels[0]->type),
+ NULLSTR(ctrl->def->seclabels[0]->label),
+ NULLSTR(ctrl->def->seclabels[0]->imagelabel));
+ } else {
+ VIR_DEBUG("Security model not initialized");
+ }
ctrl->veths = veths;
ctrl->nveths = nveths;
--
1.8.0
2
2
The managedsave test cases and test suite cover test include
verifying virsh commands managedsave(include all flags and their
combination)/managedsave-remove and managedSaveRemove/ManagedSave/
hasManagedSaveImage python APIs.
The following new files be created.
new file: cases/managedsave.conf
- Test all test cases
new file: repos/managedsave/__init__.py
new file: repos/managedsave/managedsave.py
- Test mangaedsave command/API and all flags
new file: repos/managedsave/managedsave_remove.py
- Test managedsave-remove command/API
new file: repos/managedsave/managedsave_start.py
- Verfiy managedsave'flags and start from managedsave image
---
cases/managedsave.conf | 63 ++++++++++++
repos/managedsave/managedsave.py | 162 +++++++++++++++++++++++++++++++
repos/managedsave/managedsave_remove.py | 61 ++++++++++++
repos/managedsave/managedsave_start.py | 152 +++++++++++++++++++++++++++++
4 files changed, 438 insertions(+), 0 deletions(-)
create mode 100644 cases/managedsave.conf
create mode 100644 repos/managedsave/__init__.py
create mode 100644 repos/managedsave/managedsave.py
create mode 100644 repos/managedsave/managedsave_remove.py
create mode 100644 repos/managedsave/managedsave_start.py
diff --git a/cases/managedsave.conf b/cases/managedsave.conf
new file mode 100644
index 0000000..8dcafe2
--- /dev/null
+++ b/cases/managedsave.conf
@@ -0,0 +1,63 @@
+domain:install_linux_cdrom
+ guestname
+ $defaultname
+ guestos
+ $defaultos
+ guestarch
+ $defaultarch
+ vcpu
+ $defaultvcpu
+ memory
+ $defaultmem
+ hddriver
+ $defaulthd
+ nicdriver
+ $defaultnic
+ imageformat
+ qcow2
+ macaddr
+ 54:52:00:4a:16:30
+
+#VIR_DOMAIN_SAVE_BYPASS_CACHE = 1
+#VIR_DOMAIN_SAVE_RUNNING = 2
+#VIR_DOMAIN_SAVE_PAUSED = 4
+#No_FLAGS = 0
+managedsave:managedsave
+ guestname
+ $defaultname
+ flags
+ 1|2
+
+managedsave:managedsave_start
+ guestname
+ $defaultname
+ flags
+ noping
+
+managedsave:managedsave
+ guestname
+ $defaultname
+ flags
+ 1|4
+
+managedsave:managedsave_start
+ guestname
+ $defaultname
+ flags
+ noping
+
+managedsave:managedsave
+ guestname
+ $defaultname
+ flags
+ 0
+
+managedsave:managedsave_remove
+ guestname
+ $defaultname
+
+managedsave:managedsave_start
+ guestname
+ $defaultname
+ flags
+ noping
diff --git a/repos/managedsave/__init__.py b/repos/managedsave/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/repos/managedsave/managedsave.py b/repos/managedsave/managedsave.py
new file mode 100644
index 0000000..5e7c105
--- /dev/null
+++ b/repos/managedsave/managedsave.py
@@ -0,0 +1,162 @@
+#!/usr/bin/env python
+
+import os
+import math
+
+import libvirt
+from libvirt import libvirtError
+
+from src import sharedmod
+from utils import utils
+
+required_params = ('guestname', 'flags',)
+optional_params = {}
+
+def check_guest_status(*args):
+ """Check guest current status"""
+ (domobj, logger) = args
+ state = domobj.info()[0]
+ logger.debug("current guest status: %s" % state)
+
+ if state == libvirt.VIR_DOMAIN_SHUTOFF or \
+ state == libvirt.VIR_DOMAIN_SHUTDOWN or \
+ state == libvirt.VIR_DOMAIN_BLOCKED:
+ return False
+ else:
+ return True
+
+def check_savefile_create(*args):
+ """Check guest's managed save file be created"""
+
+ (guestname) = args
+ cmds = "ls /var/lib/libvirt/qemu/save/%s" % guestname + ".save -lh"
+ logger.info("Execute cmd %s" % cmds)
+ (status, output) = utils.exec_cmd(cmds, shell=True)
+ if status != 0:
+ logger.error("No managed save file")
+ return False
+ else :
+ logger.info("managed save file exists")
+ return True
+
+def compare_cachedfile(cachebefore, cacheafter):
+ """Compare cached value before managed save and its value after
+ managed save """
+
+ diff = cacheafter - cachebefore
+ logger.info("diff is %s " % diff)
+ percent = math.fabs(diff)/cachebefore
+ logger.info("diff percent is %s " % percent)
+ if math.fabs(diff)/cachebefore < 0.05:
+ return True
+ else:
+ return False
+
+def get_cachevalue():
+ """Get the file system cached value """
+
+ cmds = "head -n4 /proc/meminfo|grep Cached|awk '{print $2}'"
+ (status, output) = utils.exec_cmd(cmds, shell=True)
+ if status != 0:
+ logger.error("failed to run cmd line to get cache")
+ return 1
+ else:
+ logger.debug(output[0])
+ cachevalue= int(output[0])
+ return cachevalue
+
+def managedsave(params):
+ """Managed save a running domain"""
+
+ global logger
+ logger = params['logger']
+ guestname = params['guestname']
+ flags = params ['flags']
+ #Save given flags to sharedmod.data
+ sharedmod.data['flagsave'] = flags
+
+ logger.info("The given flags are %s " % flags)
+ if not '|' in flags:
+ flagn = int(flags)
+ else:
+ flagstr = flags.split('|')
+ flagcont = ''.join(flagstr)
+ length = len(flagcont)
+ # bitwise-OR of flags of managedsave
+ flagn = int(flagcont[0])
+ for i in range(0,length-1):
+ flagn = flagn |int(flagcont[i+1])
+
+ conn = sharedmod.libvirtobj['conn']
+ domobj = conn.lookupByName(guestname)
+
+ if not check_guest_status(domobj, logger):
+ logger.error("Error: current guest status is shutoff")
+ return 1
+
+ try:
+
+ logger.info("bitwise OR value of flags is %s" % flagn)
+
+ if flagn == 0:
+ logger.info("managedsave %s domain with no flag" % guestname)
+ elif flagn == 1:
+ logger.info("managedsave %s domain --bypass-cache" % guestname)
+ elif flagn == 2:
+ logger.info("managedsave %s domain --running" % guestname)
+ elif flagn == 3:
+ logger.info("managedsave %s domain --running --bypass-cache"\
+ % guestname)
+ elif flagn == 4:
+ logger.info("managedsave %s domain --paused" % guestname)
+ elif flagn == 5:
+ logger.info("managedsave %s domain --paused --bypass-cache"\
+ % guestname)
+ elif flagn == 6:
+ logger.error("Error:--running and --paused are mutually exclusive")
+ return 1
+ elif flagn == 7:
+ logger.error("Error:--running and --paused are mutually exclusive")
+ return 1
+ else:
+ logger.error("Error:Wrong flags be given and fail to \
+ managedsave domain")
+ return 1
+
+ #If given flags include bypass-cache,check if bypass file system cache
+ if flagn %2 == 1:
+ logger.info("Given flags include --bypass-cache")
+ os.system('echo 3 > /proc/sys/vm/drop_caches')
+ cache_before = get_cachevalue()
+ logger.info("Cached value before managedsave is %s" % cache_before)
+
+ domobj.managedSave(flagn)
+
+ cache_after = get_cachevalue()
+ logger.info("Cached value after managedsave is %s" % cache_after)
+
+ if compare_cachedfile(cache_before, cache_after):
+ logger.info("Bypass file system cache successfully")
+ else:
+ logger.error("Bypass file system cache failed")
+ return 1
+ else:
+ domobj.managedSave(flagn)
+
+ #Check if domain has managedsave image
+ if domobj.hasManagedSaveImage(0) and \
+ domobj.info()[0]==libvirt.VIR_DOMAIN_SHUTOFF and \
+ check_savefile_create(guestname):
+ logger.info("Domain %s managedsave successfully " % guestname)
+ else:
+ logger.error("Error: fail to managedsave domain")
+ return 1
+
+ except libvirtError, e:
+ logger.error("API error message: %s, error code is %s" \
+ % e.message)
+ logger.error("Error: fail to managedsave %s domain" % guestname)
+ return 1
+
+ return 0
+
diff --git a/repos/managedsave/managedsave_remove.py b/repos/managedsave/managedsave_remove.py
new file mode 100644
index 0000000..143312f
--- /dev/null
+++ b/repos/managedsave/managedsave_remove.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+# Save domain as a statefile
+
+import libvirt
+from libvirt import libvirtError
+
+from src import sharedmod
+from utils import utils
+
+required_params = ('guestname',)
+optional_params = {}
+
+def check_savefile_remove(*args):
+ """Check if guest's managedsave file be removed """
+
+ (guestname) = args
+ cmds = "ls /var/lib/libvirt/qemu/save/%s" % guestname + ".save -lh"
+ logger.info("Execute cmd %s" % cmds)
+ (status, output) = utils.exec_cmd(cmds, shell=True)
+ if status != 0:
+ logger.info("No managed save file")
+ return True
+ else :
+ logger.error("managed save file exits")
+ return False
+
+
+def managedsave_remove(params):
+ """Remove an existing managed save state file from a domain"""
+
+ global logger
+ logger = params['logger']
+ guestname = params['guestname']
+
+ conn = sharedmod.libvirtobj['conn']
+ domobj = conn.lookupByName(guestname)
+
+ if not domobj.hasManagedSaveImage(0) and check_savefile_remove(guestname):
+ logger.info("Domain %s hasn't managedsave image" % guestname)
+ return 1
+ else:
+ logger.info("Domain %s has managedsave image" % guestname)
+
+ try:
+ domobj.managedSaveRemove(0)
+ #Check if domain has managedsave image
+ if not domobj.hasManagedSaveImage(0) and \
+ check_savefile_remove(guestname):
+ logger.info("Domain %s's managedsave image has been removed"\
+ % guestname)
+ else:
+ logger.error("Error: fail to remove managedsave domain")
+ return 1
+
+ except libvirtError, e:
+ logger.error("API error message: %s, error code is %s" % e.message)
+ logger.error("Error: fail to managedsave %s domain" % guestname)
+ return 1
+
+ return 0
+
diff --git a/repos/managedsave/managedsave_start.py b/repos/managedsave/managedsave_start.py
new file mode 100644
index 0000000..f5da0b3
--- /dev/null
+++ b/repos/managedsave/managedsave_start.py
@@ -0,0 +1,152 @@
+#!/usr/bin/env python
+
+import time
+
+import libvirt
+from libvirt import libvirtError
+
+from src import sharedmod
+from utils import utils
+
+required_params = ('guestname',)
+optional_params = {'flags' : ''}
+
+NONE = 0
+START_PAUSED = 1
+START_BYPASS_CACHE = 4
+START_FORCE_BOOT = 8
+
+def check_savefile_remove(*args):
+ """Check guest managed save file"""
+ (guestname) = args
+ cmds = "ls /var/lib/libvirt/qemu/save/%s" % guestname + ".save -lh"
+ logger.info("Execute cmd %s" % cmds)
+ (status, output) = utils.exec_cmd(cmds, shell=True)
+ if status != 0:
+ logger.info("No managed save file")
+ return True
+ else :
+ logger.error("managed save file exists")
+ return False
+
+def managedsave_start(params):
+ """ Start domain with managedsave image and check if its status is rigth
+ according to given flags of running managedsave command.If it is
+ correctly paused , resume it.
+
+ Argument is a dictionary with two keys:
+ {'logger': logger, 'guestname': guestname}
+
+ logger -- an object of utils/log.py
+ mandatory arguments : guestname -- same as the domain name
+ optional arguments : flags -- domain create flags <none|start_paused
+ |noping>.It allows only one flag be given.
+
+ Return 0 on SUCCESS or 1 on FAILURE
+ """
+ domname = params['guestname']
+ global logger
+ logger = params['logger']
+ flags = params.get('flags', '')
+ # Get given flags of managedsave
+ if sharedmod.data.has_key('flagsave'):
+ flagsave = sharedmod.data.get('flagsave')
+ else:
+ logger.error("Failed to get flags from managedsave")
+ # Clean sharedmod.data
+ sharedmod.data = {}
+
+ conn = sharedmod.libvirtobj['conn']
+ domobj = conn.lookupByName(domname)
+
+ timeout = 600
+ logger.info('start domain')
+ # Check if guest has managedsave image before start
+ if domobj.hasManagedSaveImage(0) :
+ logger.info("Domain has managedsave image")
+ else:
+ logger.info("Domain hasn't managedsave image")
+
+ try:
+ if "none" in flags:
+ domobj.createWithFlags(NONE)
+ elif "start_paused" in flags:
+ domobj.createWithFlags(START_PAUSED)
+ else:
+ # this covers flags = None as well as flags = 'noping'
+ domobj.create()
+ except libvirtError, e:
+ logger.error("API error message: %s, error code is %s" \
+ % e.message)
+ logger.error("start failed")
+ return 1
+
+ while timeout:
+ state = domobj.info()[0]
+ expect_states = [libvirt.VIR_DOMAIN_RUNNING,libvirt.VIR_DOMAIN_PAUSED,\
+ libvirt.VIR_DOMAIN_NOSTATE,libvirt.VIR_DOMAIN_BLOCKED]
+
+ if state in expect_states:
+ break
+
+ time.sleep(10)
+ timeout -= 10
+ logger.info(str(timeout) + "s left")
+
+ if timeout <= 0:
+ logger.error('The domain state is not as expected, state: ' + state)
+ return 1
+
+ logger.info("Guest started")
+
+ """If domain's current state is paused. Check if start command has
+ --paused flag or managedsave has --paused flag (given flags in managedsave
+ include '4'). If yes, it means domain successfully paused , then resume it.
+ If not, throw error -guest state error."""
+
+ if state == libvirt.VIR_DOMAIN_PAUSED:
+ if "start_paused" in flags or "4" in flagsave:
+ logger.info("Guest paused successfully ")
+
+ try:
+ domobj.resume()
+
+ except libvirtError, e:
+ logger.error("API error message: %s, error code is %s" \
+ % e.message)
+ logger.error("resume failed")
+ return 1
+ stateresume = domobj.info()[0]
+ expect_states = [libvirt.VIR_DOMAIN_RUNNING, \
+ libvirt.VIR_DOMAIN_NOSTATE, \
+ libvirt.VIR_DOMAIN_BLOCKED]
+ if stateresume not in expect_states:
+ logger.error('The domain state is not equal to "paused"')
+ return 1
+ else:
+ logger.info('Domain resume successfully')
+ return 0
+ else:
+ logger.error("guest state error")
+ return 1
+
+ # Get domain ip and ping ip to check domain's status
+ if not "noping" in flags:
+ mac = utils.get_dom_mac_addr(domname)
+ logger.info("get ip by mac address")
+ ip = utils.mac_to_ip(mac, 180)
+
+ logger.info('ping guest')
+ if not utils.do_ping(ip, 300):
+ logger.error('Failed on ping guest, IP: ' + str(ip))
+ return 1
+
+ # Check if domain' managedsave image exists,if not, return 0.
+ if not domobj.hasManagedSaveImage(0) and check_savefile_remove(domname):
+ logger.info("Domain %s with managedsave image successfully start" \
+ % domname)
+ return 0
+ else:
+ logger.info("Failed to start domain s% with managedsave image" \
+ % domname)
+ return 1
--
1.7.7.6
2
1