[libvirt] libvirt [PATCHv2 1/2] Refactor ESX storage driver to implement facade pattern

Ata E Husain Bohra ata.husain at hotmail.com
Sat Nov 10 07:18:07 UTC 2012


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 at 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 at 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 at googlemail.com>
+ * Copyright (C) 2012 Ata E Husain Bohra <ata.husain at 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




More information about the libvir-list mailing list