[Libvir] PATCH: 3/7 internal driver API

Daniel P. Berrange berrange at redhat.com
Mon Oct 29 03:57:29 UTC 2007


This patch defines the internal driver API for the storage API calls.
It also provides the cache implementation for the virStoragePoolPtr
and virStorageVolPtr objects. The virStorageVolPtr object is a little
different in that it doesn't reference the virConnectPtr object
directly. Instead it points to the virStoragePoolPtr object. This
makes the reference counting 'interesting', because when we get a
virStorageVolPtr object, we have increment the count on both the pool
and the connection. This was starting to get complex, so to keep it
sane I don't bother with referencing counting on the virStorageVolPtr
object itself.


 include/libvirt/virterror.h |    3 
 src/driver.h                |  119 +++++
 src/hash.c                  |  349 +++++++++++++--
 src/internal.h              |   93 +++-
 src/libvirt.c               |  975 +++++++++++++++++++++++++++++++++++++++++++-
 src/libvirt_sym.version     |    4 
 6 files changed, 1464 insertions(+), 79 deletions(-)


diff -r b5447763aad6 include/libvirt/virterror.h
--- a/include/libvirt/virterror.h	Sat Oct 27 16:56:42 2007 -0400
+++ b/include/libvirt/virterror.h	Sun Oct 28 22:44:08 2007 -0400
@@ -129,6 +129,9 @@ typedef enum {
     VIR_ERR_NO_DOMAIN, /* domain not found or unexpectedly disappeared */
     VIR_ERR_NO_NETWORK, /* network not found */
     VIR_ERR_INVALID_MAC, /* invalid MAC adress */
+    VIR_ERR_INVALID_STORAGE_POOL, /* invalid storage pool object */
+    VIR_ERR_INVALID_STORAGE_VOL, /* invalid storage vol object */
+    VIR_WAR_NO_STORAGE, /* failed to start storage */
 } virErrorNumber;
 
 /**
diff -r b5447763aad6 src/driver.h
--- a/src/driver.h	Sat Oct 27 16:56:42 2007 -0400
+++ b/src/driver.h	Sun Oct 28 14:34:03 2007 -0400
@@ -414,6 +414,124 @@ struct _virNetworkDriver {
 	virDrvNetworkSetAutostart	networkSetAutostart;
 };
 
+
+typedef int
+    (*virDrvConnectNumOfStoragePools)(virConnectPtr conn);
+typedef int
+    (*virDrvConnectListStoragePools)(virConnectPtr conn,
+                                  char **const names,
+                                  int maxnames);
+typedef int
+    (*virDrvConnectNumOfDefinedStoragePools)(virConnectPtr conn);
+typedef int
+    (*virDrvConnectListDefinedStoragePools)(virConnectPtr conn,
+                                            char **const names,
+                                            int maxnames);
+typedef virStoragePoolPtr
+    (*virDrvStoragePoolLookupByName)(virConnectPtr conn,
+                                     const char *name);
+typedef virStoragePoolPtr
+    (*virDrvStoragePoolLookupByUUID)(virConnectPtr conn,
+                                     const unsigned char *uuid);
+typedef virStoragePoolPtr
+    (*virDrvStoragePoolCreateXML)(virConnectPtr conn,
+                                  const char *xmlDesc);
+typedef virStoragePoolPtr
+    (*virDrvStoragePoolDefineXML)(virConnectPtr conn,
+                                  const char *xmlDesc);
+typedef int
+    (*virDrvStoragePoolUndefine)(virStoragePoolPtr pool);
+typedef int
+    (*virDrvStoragePoolCreate)(virStoragePoolPtr pool);
+typedef int
+    (*virDrvStoragePoolShutdown)(virStoragePoolPtr pool);
+typedef int
+    (*virDrvStoragePoolDestroy)(virStoragePoolPtr pool);
+typedef int
+    (*virDrvStoragePoolGetInfo)(virStoragePoolPtr vol,
+                                virStoragePoolInfoPtr info);
+typedef char *
+    (*virDrvStoragePoolGetXMLDesc)(virStoragePoolPtr pool,
+                                   int flags);
+typedef int
+    (*virDrvStoragePoolGetAutostart)(virStoragePoolPtr pool,
+                                     int *autostart);
+typedef int
+    (*virDrvStoragePoolSetAutostart)(virStoragePoolPtr pool,
+                                     int autostart);
+typedef int
+    (*virDrvStoragePoolNumOfVolumes)(virStoragePoolPtr pool);
+typedef int
+    (*virDrvStoragePoolListVolumes)(virStoragePoolPtr pool,
+                                    char **const names,
+                                    int maxnames);
+typedef virStorageVolPtr
+    (*virDrvStorageVolLookupByName)(virStoragePoolPtr pool,
+                                    const char *name);
+typedef virStorageVolPtr
+    (*virDrvStorageVolLookupByUUID)(virStoragePoolPtr pool,
+                                    const unsigned char *uuid);
+typedef virStorageVolPtr
+    (*virDrvStorageVolCreateXML)(virStoragePoolPtr pool,
+                                 const char *xmldesc,
+                                 int flags);
+typedef int
+    (*virDrvStorageVolDestroy)(virStorageVolPtr vol);
+typedef int
+    (*virDrvStorageVolGetInfo)(virStorageVolPtr vol,
+                               virStorageVolInfoPtr info);
+typedef char *
+    (*virDrvStorageVolGetXMLDesc)(virStorageVolPtr pool,
+                                  int flags);
+typedef char *
+    (*virDrvStorageVolGetPath)(virStorageVolPtr vol);
+
+
+
+typedef struct _virStorageDriver virStorageDriver;
+typedef virStorageDriver *virStorageDriverPtr;
+
+/**
+ * _virStorageDriver:
+ *
+ * Structure associated to a network virtualization driver, defining the various
+ * entry points for it.
+ *
+ * All drivers must support the following fields/methods:
+ *  - open
+ *  - close
+ */
+struct _virStorageDriver {
+	const char * name;	/* the name of the driver */
+	virDrvOpen			open;
+	virDrvClose			close;
+    virDrvConnectNumOfStoragePools numOfPools;
+    virDrvConnectListStoragePools listPools;
+    virDrvConnectNumOfDefinedStoragePools numOfDefinedPools;
+    virDrvConnectListDefinedStoragePools listDefinedPools;
+    virDrvStoragePoolLookupByName poolLookupByName;
+    virDrvStoragePoolLookupByUUID poolLookupByUUID;
+    virDrvStoragePoolCreateXML poolCreateXML;
+    virDrvStoragePoolDefineXML poolDefineXML;
+    virDrvStoragePoolUndefine poolUndefine;
+    virDrvStoragePoolCreate poolCreate;
+    virDrvStoragePoolShutdown poolShutdown;
+    virDrvStoragePoolDestroy poolDestroy;
+    virDrvStoragePoolGetInfo poolGetInfo;
+    virDrvStoragePoolGetXMLDesc poolGetXMLDesc;
+    virDrvStoragePoolGetAutostart poolGetAutostart;
+    virDrvStoragePoolSetAutostart poolSetAutostart;
+    virDrvStoragePoolNumOfVolumes poolNumOfVolumes;
+    virDrvStoragePoolListVolumes poolListVolumes;
+    virDrvStorageVolLookupByName volLookupByName;
+    virDrvStorageVolLookupByUUID volLookupByUUID;
+    virDrvStorageVolCreateXML volCreateXML;
+    virDrvStorageVolDestroy volDestroy;
+    virDrvStorageVolGetInfo volGetInfo;
+    virDrvStorageVolGetXMLDesc volGetXMLDesc;
+    virDrvStorageVolGetPath volGetPath;
+};
+
 typedef int (*virDrvStateInitialize) (void);
 typedef int (*virDrvStateCleanup) (void);
 typedef int (*virDrvStateReload) (void);
@@ -436,6 +554,7 @@ struct _virStateDriver {
  */
 int virRegisterDriver(virDriverPtr);
 int virRegisterNetworkDriver(virNetworkDriverPtr);
+int virRegisterStorageDriver(virStorageDriverPtr);
 int virRegisterStateDriver(virStateDriverPtr);
 
 #ifdef __cplusplus
diff -r b5447763aad6 src/hash.c
--- a/src/hash.c	Sat Oct 27 16:56:42 2007 -0400
+++ b/src/hash.c	Sun Oct 28 22:44:58 2007 -0400
@@ -649,6 +649,20 @@ virNetworkFreeName(virNetworkPtr network
 }
 
 /**
+ * virStoragePoolFreeName:
+ * @pool: a storage pool object
+ *
+ * Destroy the storage pool object, this is just used by the storage pool hash callback.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+static int
+virStoragePoolFreeName(virStoragePoolPtr pool, const char *name ATTRIBUTE_UNUSED)
+{
+    return (virStoragePoolFree(pool));
+}
+
+/**
  * virGetConnect:
  *
  * Allocates a new hypervisor connection structure
@@ -675,6 +689,9 @@ virGetConnect(void) {
     ret->networks = virHashCreate(20);
     if (ret->networks == NULL)
         goto failed;
+    ret->storagePools = virHashCreate(20);
+    if (ret->storagePools == NULL)
+        goto failed;
     ret->hashes_mux = xmlNewMutex();
     if (ret->hashes_mux == NULL)
         goto failed;
@@ -688,6 +705,8 @@ failed:
 	    virHashFree(ret->domains, (virHashDeallocator) virDomainFreeName);
 	if (ret->networks != NULL)
 	    virHashFree(ret->networks, (virHashDeallocator) virNetworkFreeName);
+	if (ret->storagePools != NULL)
+	    virHashFree(ret->storagePools, (virHashDeallocator) virStoragePoolFreeName);
 	if (ret->hashes_mux != NULL)
 	    xmlFreeMutex(ret->hashes_mux);
         free(ret);
@@ -695,39 +714,49 @@ failed:
     return(NULL);
 }
 
-/**
- * virFreeConnect:
- * @conn: the hypervisor connection
- *
- * Release the connection. if the use count drops to zero, the structure is
- * actually freed.
- *
- * Returns the reference count or -1 in case of failure.
- */
-int	
-virFreeConnect(virConnectPtr conn) {
+static int
+virFreeConnectLocked(virConnectPtr conn) {
     int ret;
-
-    if ((!VIR_IS_CONNECT(conn)) || (conn->hashes_mux == NULL)) {
-        virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return(-1);
-    }
-    xmlMutexLock(conn->hashes_mux);
     conn->uses--;
     ret = conn->uses;
-    if (ret > 0) {
-	xmlMutexUnlock(conn->hashes_mux);
-	return(ret);
-    }
+    if (ret > 0)
+        return(ret);
 
     if (conn->domains != NULL)
         virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName);
     if (conn->networks != NULL)
         virHashFree(conn->networks, (virHashDeallocator) virNetworkFreeName);
-    if (conn->hashes_mux != NULL)
-        xmlFreeMutex(conn->hashes_mux);
+    if (conn->storagePools != NULL)
+        virHashFree(conn->storagePools, (virHashDeallocator) virStoragePoolFreeName);
     free(conn);
     return(0);
+}
+
+/**
+ * virFreeConnect:
+ * @conn: the hypervisor connection
+ *
+ * Release the connection. if the use count drops to zero, the structure is
+ * actually freed.
+ *
+ * Returns the reference count or -1 in case of failure.
+ */
+int
+virFreeConnect(virConnectPtr conn) {
+    int ret;
+    xmlMutexPtr mux;
+
+    if ((!VIR_IS_CONNECT(conn)) || (conn->hashes_mux == NULL)) {
+        virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(-1);
+    }
+    mux = conn->hashes_mux;
+    xmlMutexLock(mux);
+    ret = virFreeConnectLocked(conn);
+    xmlMutexUnlock(mux);
+    if (ret == 0)
+        xmlFreeMutex(mux);
+    return ret;
 }
 
 /**
@@ -815,13 +844,15 @@ int
 int
 virFreeDomain(virConnectPtr conn, virDomainPtr domain) {
     int ret = 0;
+    xmlMutexPtr mux;
 
     if ((!VIR_IS_CONNECT(conn)) || (!VIR_IS_CONNECTED_DOMAIN(domain)) ||
         (domain->conn != conn) || (conn->hashes_mux == NULL)) {
         virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(-1);
     }
-    xmlMutexLock(conn->hashes_mux);
+    mux = conn->hashes_mux;
+    xmlMutexLock(mux);
 
     /*
      * decrement the count for the domain
@@ -844,22 +875,14 @@ virFreeDomain(virConnectPtr conn, virDom
         free(domain->name);
     free(domain);
 
-    /*
-     * decrement the count for the connection
-     */
-    conn->uses--;
-    if (conn->uses > 0)
-        goto done;
-    
-    if (conn->domains != NULL)
-        virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName);
-    if (conn->hashes_mux != NULL)
-        xmlFreeMutex(conn->hashes_mux);
-    free(conn);
+    ret = virFreeConnectLocked(conn);
+    xmlMutexUnlock(mux);
+    if (ret == 0)
+        xmlFreeMutex(mux);
     return(0);
 
 done:
-    xmlMutexUnlock(conn->hashes_mux);
+    xmlMutexUnlock(mux);
     return(ret);
 }
 
@@ -947,13 +970,15 @@ int
 int
 virFreeNetwork(virConnectPtr conn, virNetworkPtr network) {
     int ret = 0;
+    xmlMutexPtr mux;
 
     if ((!VIR_IS_CONNECT(conn)) || (!VIR_IS_CONNECTED_NETWORK(network)) ||
         (network->conn != conn) || (conn->hashes_mux == NULL)) {
         virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(-1);
     }
-    xmlMutexLock(conn->hashes_mux);
+    mux = conn->hashes_mux;
+    xmlMutexLock(mux);
 
     /*
      * decrement the count for the network
@@ -975,23 +1000,255 @@ virFreeNetwork(virConnectPtr conn, virNe
         free(network->name);
     free(network);
 
+    ret = virFreeConnectLocked(conn);
+    xmlMutexUnlock(mux);
+    if (ret == 0)
+        xmlFreeMutex(mux);
+    return(0);
+
+done:
+    xmlMutexUnlock(mux);
+    return(ret);
+}
+
+/**
+ * virGetStoragePool:
+ * @conn: the hypervisor connection
+ * @name: pointer to the pool name
+ * @uuid: pointer to the uuid
+ *
+ * Lookup if the pool is already registered for that connection,
+ * if yes return a new pointer to it, if no allocate a new structure,
+ * and register it in the table. In any case a corresponding call to
+ * virFreeStoragePool() is needed to not leak data.
+ *
+ * Returns a pointer to the pool, or NULL in case of failure
+ */
+virStoragePoolPtr
+__virGetStoragePool(virConnectPtr conn, const char *name, const unsigned char *uuid) {
+    virStoragePoolPtr ret = NULL;
+
+    if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL) ||
+        (conn->hashes_mux == NULL)) {
+        virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(NULL);
+    }
+    xmlMutexLock(conn->hashes_mux);
+
+    /* TODO search by UUID first as they are better differenciators */
+
+    ret = (virStoragePoolPtr) virHashLookup(conn->storagePools, name);
+    if (ret != NULL) {
+        /* TODO check the UUID */
+        goto done;
+    }
+
     /*
-     * decrement the count for the connection
+     * not found, allocate a new one
      */
-    conn->uses--;
-    if (conn->uses > 0)
+    ret = (virStoragePoolPtr) calloc(1, sizeof(virStoragePool));
+    if (ret == NULL) {
+        virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating storage pool"));
+        goto error;
+    }
+    ret->name = strdup(name);
+    if (ret->name == NULL) {
+        virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating storage pool"));
+        goto error;
+    }
+    ret->magic = VIR_STORAGE_POOL_MAGIC;
+    ret->conn = conn;
+    if (uuid != NULL)
+        memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
+
+    if (virHashAddEntry(conn->storagePools, name, ret) < 0) {
+        virHashError(conn, VIR_ERR_INTERNAL_ERROR,
+	             _("failed to add storage pool to connection hash table"));
+        goto error;
+    }
+    conn->uses++;
+done:
+    ret->uses++;
+    xmlMutexUnlock(conn->hashes_mux);
+    return(ret);
+
+error:
+    xmlMutexUnlock(conn->hashes_mux);
+    if (ret != NULL) {
+        if (ret->name != NULL)
+            free(ret->name);
+        free(ret);
+    }
+    return(NULL);
+}
+
+static int
+virFreeStoragePoolLocked(virConnectPtr conn, virStoragePoolPtr pool) {
+    int ret = 0;
+    /*
+     * decrement the count for the pool
+     */
+    pool->uses--;
+    ret = pool->uses;
+    if (ret > 0)
         goto done;
 
-    if (conn->networks != NULL)
-        virHashFree(conn->networks, (virHashDeallocator) virNetworkFreeName);
-    if (conn->hashes_mux != NULL)
-        xmlFreeMutex(conn->hashes_mux);
-    free(conn);
+    /* TODO search by UUID first as they are better differenciators */
+
+    if (virHashRemoveEntry(conn->storagePools, pool->name, NULL) < 0) {
+        virHashError(conn, VIR_ERR_INTERNAL_ERROR,
+	             _("pool missing from connection hash table"));
+        goto done;
+    }
+    pool->magic = -1;
+    if (pool->name)
+        free(pool->name);
+    free(pool);
     return(0);
 
 done:
     xmlMutexUnlock(conn->hashes_mux);
     return(ret);
+}
+/**
+ * virFreeStoragePool:
+ * @conn: the hypervisor connection
+ * @pool: the pool to release
+ *
+ * Release the given storage pool, if the reference count drops to zero, then
+ * the pool is really freed.
+ *
+ * Returns the reference count or -1 in case of failure.
+ */
+int
+virFreeStoragePool(virConnectPtr conn, virStoragePoolPtr pool) {
+    int ret = 0;
+    xmlMutexPtr mux;
+
+    if ((!VIR_IS_CONNECT(conn)) || (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) ||
+        (pool->conn != conn) || (conn->hashes_mux == NULL)) {
+        virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(-1);
+    }
+    mux = conn->hashes_mux;
+    xmlMutexLock(mux);
+
+    ret = virFreeStoragePoolLocked(conn, pool);
+    if (ret > 0)
+        goto done;
+
+    ret = virFreeConnectLocked(conn);
+    xmlMutexUnlock(mux);
+    if (ret == 0)
+        xmlFreeMutex(mux);
+    return(0);
+
+done:
+    xmlMutexUnlock(mux);
+    return(ret);
+}
+
+/**
+ * virGetStorageVol:
+ * @pool: the storage pool
+ * @name: pointer to the pool name
+ * @uuid: pointer to the uuid
+ *
+ * Lookup if the storage is already registered for that connection,
+ * if yes return a new pointer to it, if no allocate a new structure,
+ * and register it in the table. In any case a corresponding call to
+ * virFreeStorageVol() is needed to not leak data.
+ *
+ * Returns a pointer to the vol, or NULL in case of failure
+ */
+virStorageVolPtr
+__virGetStorageVol(virStoragePoolPtr pool, const char *name, const unsigned char *uuid) {
+    virStorageVolPtr ret = NULL;
+
+    if ((!VIR_IS_STORAGE_POOL(pool)) || (name == NULL) || (uuid == NULL) ||
+        (pool->conn->hashes_mux == NULL)) {
+        virHashError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(NULL);
+    }
+    xmlMutexLock(pool->conn->hashes_mux);
+
+    /*
+     * not found, allocate a new one
+     */
+    ret = (virStorageVolPtr) calloc(1, sizeof(virStorageVol));
+    if (ret == NULL) {
+        virHashError(pool->conn, VIR_ERR_NO_MEMORY, _("allocating storage vol"));
+        goto error;
+    }
+    ret->name = strdup(name);
+    if (ret->name == NULL) {
+        virHashError(pool->conn, VIR_ERR_NO_MEMORY, _("allocating storage vol"));
+        goto error;
+    }
+    ret->magic = VIR_STORAGE_VOL_MAGIC;
+    ret->pool = pool;
+    if (uuid != NULL)
+        memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
+
+    pool->uses++;
+    pool->conn->uses++;
+    xmlMutexUnlock(pool->conn->hashes_mux);
+    return(ret);
+
+error:
+    xmlMutexUnlock(pool->conn->hashes_mux);
+    if (ret != NULL) {
+        if (ret->name != NULL)
+            free(ret->name);
+        free(ret);
+    }
+    return(NULL);
+}
+
+/**
+ * virFreeStorageVol:
+ * @conn: the hypervisor connection
+ * @vol: the vol to release
+ *
+ * Release the given storage volume
+ *
+ * Returns zero on success, or -1 in case of failure.
+ */
+int
+virFreeStorageVol(virConnectPtr conn, virStorageVolPtr vol) {
+    int ret = 0;
+    xmlMutexPtr mux;
+    virStoragePoolPtr pool;
+
+    if ((!VIR_IS_CONNECT(conn)) || (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) ||
+        (vol->pool->conn != conn)) {
+        virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(-1);
+    }
+    pool = vol->pool;
+    mux = conn->hashes_mux;
+    xmlMutexLock(conn->hashes_mux);
+
+    vol->magic = -1;
+    if (vol->name)
+        free(vol->name);
+    free(vol);
+
+    ret = virFreeStoragePoolLocked(conn, pool);
+    if (ret > 0)
+        goto done;
+
+    ret = virFreeConnectLocked(conn);
+    xmlMutexUnlock(mux);
+    if (ret == 0)
+        xmlFreeMutex(mux);
+    return(0);
+
+    return(0);
+
+done:
+    xmlMutexUnlock(mux);
+    return(0);
 }
 
 /*
diff -r b5447763aad6 src/internal.h
--- a/src/internal.h	Sat Oct 27 16:56:42 2007 -0400
+++ b/src/internal.h	Sun Oct 28 14:34:03 2007 -0400
@@ -90,7 +90,7 @@ extern "C" {
  * VIR_DOMAIN_MAGIC:
  *
  * magic value used to protect the API when pointers to domain structures
- * are passed down by the uers.
+ * are passed down by the users.
  */
 #define VIR_DOMAIN_MAGIC		0xDEAD4321
 #define VIR_IS_DOMAIN(obj)		((obj) && (obj)->magic==VIR_DOMAIN_MAGIC)
@@ -100,12 +100,33 @@ extern "C" {
  * VIR_NETWORK_MAGIC:
  *
  * magic value used to protect the API when pointers to network structures
- * are passed down by the uers.
+ * are passed down by the users.
  */
 #define VIR_NETWORK_MAGIC		0xDEAD1234
 #define VIR_IS_NETWORK(obj)		((obj) && (obj)->magic==VIR_NETWORK_MAGIC)
 #define VIR_IS_CONNECTED_NETWORK(obj)	(VIR_IS_NETWORK(obj) && VIR_IS_CONNECT((obj)->conn))
 
+/**
+ * VIR_STORAGE_POOL_MAGIC:
+ *
+ * magic value used to protect the API when pointers to storage pool structures
+ * are passed down by the users.
+ */
+#define VIR_STORAGE_POOL_MAGIC		0xDEAD5678
+#define VIR_IS_STORAGE_POOL(obj)		((obj) && (obj)->magic==VIR_STORAGE_POOL_MAGIC)
+#define VIR_IS_CONNECTED_STORAGE_POOL(obj)	(VIR_IS_STORAGE_POOL(obj) && VIR_IS_CONNECT((obj)->conn))
+
+/**
+ * VIR_STORAGE_VOL_MAGIC:
+ *
+ * magic value used to protect the API when pointers to storage vol structures
+ * are passed down by the users.
+ */
+#define VIR_STORAGE_VOL_MAGIC		0xDEAD8765
+#define VIR_IS_STORAGE_VOL(obj)		((obj) && (obj)->magic==VIR_STORAGE_VOL_MAGIC)
+#define VIR_IS_CONNECTED_STORAGE_VOL(obj)	(VIR_IS_STORAGE_VOL(obj) && VIR_IS_CONNECTED_STORAGE_POOL((obj)->pool) \
+                                             && VIR_IS_CONNECT((obj)->pool->conn))
+
 /*
  * arbitrary limitations
  */
@@ -130,6 +151,7 @@ struct _virConnect {
     /* The underlying hypervisor driver and network driver. */
     virDriverPtr      driver;
     virNetworkDriverPtr networkDriver;
+    virStorageDriverPtr storageDriver;
 
     /* Private data pointer which can be used by driver and
      * network driver as they wish.
@@ -137,6 +159,7 @@ struct _virConnect {
      */
     void *            privateData;
     void *            networkPrivateData;
+    void *            storagePrivateData;
 
     /* Per-connection error. */
     virError err;           /* the last error */
@@ -146,7 +169,8 @@ struct _virConnect {
     /* misc */
     xmlMutexPtr hashes_mux;/* a mutex to protect the domain and networks hash tables */
     virHashTablePtr domains;/* hash table for known domains */
-    virHashTablePtr networks;/* hash table for known domains */
+    virHashTablePtr networks;/* hash table for known networks */
+    virHashTablePtr storagePools;/* hash table for known storage pools */
     int flags;              /* a set of connection flags */
 };
 
@@ -175,6 +199,33 @@ struct _virNetwork {
     virConnectPtr conn;                  /* pointer back to the connection */
     char *name;                          /* the network external name */
     unsigned char uuid[VIR_UUID_BUFLEN]; /* the network unique identifier */
+};
+
+/**
+* _virNetwork:
+*
+* Internal structure associated to a domain
+*/
+struct _virStoragePool {
+    unsigned int magic;                  /* specific value to check */
+    int uses;                            /* reference count */
+    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 */
+};
+
+/**
+* _virNetwork:
+*
+* Internal structure associated to a domain.
+* NB, this is not reference counted. They
+* are directly created/freed as needed.
+*/
+struct _virStorageVol {
+    unsigned int magic;                  /* specific value to check */
+    virStoragePoolPtr pool;              /* pointer back to the storage pool */
+    char *name;                          /* the storage vol external name */
+    unsigned char uuid[VIR_UUID_BUFLEN]; /* the storage vol unique identifier */
 };
 
 /*
@@ -208,21 +259,33 @@ const char *__virErrorMsg(virErrorNumber
  *									*
  ************************************************************************/
 
-virConnectPtr	virGetConnect	(void);
-int		virFreeConnect	(virConnectPtr conn);
-virDomainPtr	__virGetDomain	(virConnectPtr conn,
-				 const char *name,
-				 const unsigned char *uuid);
-int		virFreeDomain	(virConnectPtr conn,
-				 virDomainPtr domain);
-virNetworkPtr	__virGetNetwork	(virConnectPtr conn,
-				 const char *name,
-				 const unsigned char *uuid);
-int		virFreeNetwork	(virConnectPtr conn,
-				 virNetworkPtr domain);
+virConnectPtr		virGetConnect		(void);
+int					virFreeConnect		(virConnectPtr conn);
+virDomainPtr		__virGetDomain		(virConnectPtr conn,
+                                         const char *name,
+                                         const unsigned char *uuid);
+int					virFreeDomain		(virConnectPtr conn,
+                                         virDomainPtr domain);
+virNetworkPtr		__virGetNetwork		(virConnectPtr conn,
+                                         const char *name,
+                                         const unsigned char *uuid);
+int					virFreeNetwork		(virConnectPtr conn,
+                                         virNetworkPtr domain);
+virStoragePoolPtr	__virGetStoragePool	(virConnectPtr conn,
+                                         const char *name,
+                                         const unsigned char *uuid);
+int					virFreeStoragePool	(virConnectPtr conn,
+                                         virStoragePoolPtr domain);
+virStorageVolPtr	__virGetStorageVol	(virStoragePoolPtr pool,
+                                         const char *name,
+                                         const unsigned char *uuid);
+int					virFreeStorageVol	(virConnectPtr conn,
+                                         virStorageVolPtr domain);
 
 #define virGetDomain(c,n,u) __virGetDomain((c),(n),(u))
 #define virGetNetwork(c,n,u) __virGetNetwork((c),(n),(u))
+#define virGetStoragePool(c,n,u) __virGetStoragePool((c),(n),(u))
+#define virGetStorageVol(c,n,u) __virGetStorageVol((c),(n),(u))
 
 int __virStateInitialize(void);
 int __virStateCleanup(void);
diff -r b5447763aad6 src/libvirt.c
--- a/src/libvirt.c	Sat Oct 27 16:56:42 2007 -0400
+++ b/src/libvirt.c	Sun Oct 28 22:44:52 2007 -0400
@@ -30,6 +30,7 @@
 #include "xen_unified.h"
 #include "remote_internal.h"
 #include "qemu_driver.h"
+#include "storage_driver.h"
 #ifdef WITH_OPENVZ
 #include "openvz_driver.h"
 #endif
@@ -44,6 +45,8 @@ static int virDriverTabCount = 0;
 static int virDriverTabCount = 0;
 static virNetworkDriverPtr virNetworkDriverTab[MAX_DRIVERS];
 static int virNetworkDriverTabCount = 0;
+static virStorageDriverPtr virStorageDriverTab[MAX_DRIVERS];
+static int virStorageDriverTabCount = 0;
 static virStateDriverPtr virStateDriverTab[MAX_DRIVERS];
 static int virStateDriverTabCount = 0;
 static int initialized = 0;
@@ -52,10 +55,11 @@ static int initialized = 0;
  * are printed to stderr for debugging.
  */
 #ifdef ENABLE_DEBUG
+static int debug = 0;
 #define DEBUG(fs,...)                                                   \
-    fprintf (stderr, "libvirt: %s (" fs ")\n", __func__, __VA_ARGS__)
+    do { if (debug) fprintf (stderr, "libvirt: %s (" fs ")\n", __func__, __VA_ARGS__); } while (0)
 #define DEBUG0                                                          \
-    fprintf (stderr, "libvirt: %s ()\n", __func__)
+    do { if (debug) fprintf (stderr, "libvirt: %s ()\n", __func__); } while (0)
 #else
 #define DEBUG0
 #define DEBUG(fs,...)
@@ -73,10 +77,14 @@ int
 int
 virInitialize(void)
 {
-    DEBUG0;
+    char *debugFlag = getenv("LIBVIRT_DEBUG");
+    if (debugFlag && *debugFlag)
+        debug = 1;
+
     if (initialized)
         return(0);
     initialized = 1;
+    DEBUG0;
 
     if (!bindtextdomain(GETTEXT_PACKAGE, LOCALEBASEDIR))
         return (-1);
@@ -97,6 +105,7 @@ virInitialize(void)
 #ifdef WITH_OPENVZ
     if (openvzRegister() == -1) return -1;
 #endif
+    if (storageRegister() == -1) return -1;
 #ifdef WITH_REMOTE
     if (remoteRegister () == -1) return -1;
 #endif
@@ -201,6 +210,58 @@ virLibNetworkError(virNetworkPtr network
 }
 
 /**
+ * virLibStoragePoolError:
+ * @conn: the connection if available
+ * @error: the error noumber
+ * @info: extra information string
+ *
+ * Handle an error at the connection level
+ */
+static void
+virLibStoragePoolError(virStoragePoolPtr pool, virErrorNumber error,
+                       const char *info)
+{
+    virConnectPtr conn = NULL;
+    const char *errmsg;
+
+    if (error == VIR_ERR_OK)
+        return;
+
+    errmsg = __virErrorMsg(error, info);
+    if (error != VIR_ERR_INVALID_STORAGE_POOL)
+        conn = pool->conn;
+
+    __virRaiseError(conn, NULL, NULL, VIR_FROM_STORAGE, error, VIR_ERR_ERROR,
+                    errmsg, info, NULL, 0, 0, errmsg, info);
+}
+
+/**
+ * virLibStorageVolError:
+ * @conn: the connection if available
+ * @error: the error noumber
+ * @info: extra information string
+ *
+ * Handle an error at the connection level
+ */
+static void
+virLibStorageVolError(virStorageVolPtr vol, virErrorNumber error,
+                      const char *info)
+{
+    virConnectPtr conn = NULL;
+    const char *errmsg;
+
+    if (error == VIR_ERR_OK)
+        return;
+
+    errmsg = __virErrorMsg(error, info);
+    if (error != VIR_ERR_INVALID_STORAGE_VOL)
+        conn = vol->pool->conn;
+
+    __virRaiseError(conn, NULL, NULL, VIR_FROM_STORAGE, error, VIR_ERR_ERROR,
+                    errmsg, info, NULL, 0, 0, errmsg, info);
+}
+
+/**
  * virRegisterNetworkDriver:
  * @driver: pointer to a network driver block
  *
@@ -226,6 +287,34 @@ virRegisterNetworkDriver(virNetworkDrive
 
     virNetworkDriverTab[virNetworkDriverTabCount] = driver;
     return virNetworkDriverTabCount++;
+}
+
+/**
+ * virRegisterStorageDriver:
+ * @driver: pointer to a storage driver block
+ *
+ * Register a storage virtualization driver
+ *
+ * Returns the driver priority or -1 in case of error.
+ */
+int
+virRegisterStorageDriver(virStorageDriverPtr driver)
+{
+    if (virInitialize() < 0)
+      return -1;
+
+    if (driver == NULL) {
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
+	return(-1);
+    }
+
+    if (virStorageDriverTabCount >= MAX_DRIVERS) {
+    	virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
+	return(-1);
+    }
+
+    virStorageDriverTab[virStorageDriverTabCount] = driver;
+    return virStorageDriverTabCount++;
 }
 
 /**
@@ -417,21 +506,24 @@ do_open (const char *name, int flags)
     }
 
 #ifdef ENABLE_DEBUG
-    fprintf (stderr, "libvirt: do_open: proceeding with name=%s\n", name);
+    DEBUG("proceeding with name=%s", name);
 #endif
 
+
+
+    /* Primary driver is for domains. At least one must succeed */
     for (i = 0; i < virDriverTabCount; i++) {
 #ifdef ENABLE_DEBUG
-        fprintf (stderr, "libvirt: do_open: trying driver %d (%s) ...\n",
-                 i, virDriverTab[i]->name);
+        DEBUG("trying driver %d (%s) ...",
+              i, virDriverTab[i]->name);
 #endif
         res = virDriverTab[i]->open (ret, name, flags);
 #ifdef ENABLE_DEBUG
-        fprintf (stderr, "libvirt: do_open: driver %d %s returned %s\n",
-                 i, virDriverTab[i]->name,
-                 res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
-                 (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
-                  (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
+        DEBUG("driver %d %s returned %s",
+              i, virDriverTab[i]->name,
+              res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
+              (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
+               (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
 #endif
         if (res == VIR_DRV_OPEN_ERROR) goto failed;
         else if (res == VIR_DRV_OPEN_SUCCESS) {
@@ -446,14 +538,16 @@ do_open (const char *name, int flags)
         goto failed;
     }
 
+
+    /* Secondary driver for networks. Optional */
     for (i = 0; i < virNetworkDriverTabCount; i++) {
         res = virNetworkDriverTab[i]->open (ret, name, flags);
 #ifdef ENABLE_DEBUG
-        fprintf (stderr, "libvirt: do_open: network driver %d %s returned %s\n",
-                 i, virNetworkDriverTab[i]->name,
-                 res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
-                 (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
-                  (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
+        DEBUG("network driver %d %s returned %s",
+              i, virNetworkDriverTab[i]->name,
+              res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
+              (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
+               (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
 #endif
         if (res == VIR_DRV_OPEN_ERROR) {
             if (STREQ(virNetworkDriverTab[i]->name, "remote")) {
@@ -467,6 +561,29 @@ do_open (const char *name, int flags)
         }
     }
 
+
+    /* Secondary driver for storage. Optional */
+    for (i = 0; i < virStorageDriverTabCount; i++) {
+        res = virStorageDriverTab[i]->open (ret, name, flags);
+#ifdef ENABLE_DEBUG
+        DEBUG("storage driver %d %s returned %s",
+              i, virStorageDriverTab[i]->name,
+              res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
+              (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
+               (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
+#endif
+        if (res == VIR_DRV_OPEN_ERROR) {
+            if (STREQ(virStorageDriverTab[i]->name, "remote")) {
+                virLibConnWarning (NULL, VIR_WAR_NO_STORAGE, 
+                                   "Is the daemon running ?");
+            }
+            break;
+        } else if (res == VIR_DRV_OPEN_SUCCESS) {
+            ret->storageDriver = virStorageDriverTab[i];
+            break;
+        }
+    }
+
     if (flags & VIR_DRV_OPEN_RO) {
         ret->flags = VIR_CONNECT_RO;
     }
@@ -537,6 +654,8 @@ virConnectClose(virConnectPtr conn)
 
     if (conn->networkDriver)
         conn->networkDriver->close (conn);
+    if (conn->storageDriver)
+        conn->storageDriver->close (conn);
     conn->driver->close (conn);
 
     if (virFreeConnect(conn) < 0)
@@ -3360,6 +3479,830 @@ virNetworkSetAutostart(virNetworkPtr net
     return -1;
 }
 
+
+/**
+ * virStoragePoolGetConnect:
+ * @net: pointer to a poool
+ *
+ * Provides the connection pointer associated with a storage poolk.  The
+ * reference counter on the connection is not increased by this
+ * call.
+ *
+ * WARNING: When writing libvirt bindings in other languages, do
+ * not use this function.  Instead, store the connection and
+ * the pool object together.
+ *
+ * Returns the virConnectPtr or NULL in case of failure.
+ */
+virConnectPtr
+virStoragePoolGetConnect (virStoragePoolPtr pool)
+{
+    DEBUG("pool=%p", pool);
+
+    if (!VIR_IS_STORAGE_POOL (pool)) {
+        virLibStoragePoolError (NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
+        return NULL;
+    }
+    return pool->conn;
+}
+
+/*
+ * List active storage pools
+ */
+int
+virConnectNumOfStoragePools	(virConnectPtr conn)
+{
+    DEBUG("conn=%p", conn);
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+
+    if (conn->storageDriver && conn->storageDriver->numOfPools)
+        return conn->storageDriver->numOfPools (conn);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int
+virConnectListStoragePools	(virConnectPtr conn,
+                             char **const names,
+                             int maxnames)
+{
+    DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames);
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+
+    if ((names == NULL) || (maxnames < 0)) {
+        virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+
+    if (conn->storageDriver && conn->storageDriver->listPools)
+        return conn->storageDriver->listPools (conn, names, maxnames);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+
+}
+
+int
+virConnectNumOfDefinedStoragePools(virConnectPtr conn)
+{
+    DEBUG("conn=%p", conn);
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+
+    if (conn->storageDriver && conn->storageDriver->numOfDefinedPools)
+        return conn->storageDriver->numOfDefinedPools (conn);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+
+int
+virConnectListDefinedStoragePools(virConnectPtr conn,
+                                  char **const names,
+                                  int maxnames)
+{
+    DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames);
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+
+    if ((names == NULL) || (maxnames < 0)) {
+        virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+
+    if (conn->storageDriver && conn->storageDriver->listDefinedPools)
+        return conn->storageDriver->listDefinedPools (conn, names, maxnames);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+
+virStoragePoolPtr
+virStoragePoolLookupByName(virConnectPtr conn,
+                           const char *name)
+{
+    DEBUG("conn=%p, name=%s", conn, name);
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+    if (name == NULL) {
+        virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+
+    if (conn->storageDriver && conn->storageDriver->poolLookupByName)
+        return conn->storageDriver->poolLookupByName (conn, name);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return NULL;
+}
+
+
+virStoragePoolPtr
+virStoragePoolLookupByUUID(virConnectPtr conn,
+                           const unsigned char *uuid)
+{
+    DEBUG("conn=%p, uuid=%s", conn, uuid);
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+    if (uuid == NULL) {
+        virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+
+    if (conn->storageDriver && conn->storageDriver->poolLookupByUUID)
+        return conn->storageDriver->poolLookupByUUID (conn, uuid);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return NULL;
+
+}
+
+
+virStoragePoolPtr
+virStoragePoolLookupByUUIDString(virConnectPtr conn,
+								 const char *uuidstr)
+{
+    unsigned char uuid[VIR_UUID_BUFLEN];
+    DEBUG("conn=%p, uuidstr=%s", conn, uuidstr);
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+    if (uuidstr == NULL) {
+        virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+
+    if (virUUIDParse(uuidstr, uuid) < 0) {
+        virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+
+    return virStoragePoolLookupByUUID(conn, uuid);
+}
+
+virStoragePoolPtr
+virStoragePoolCreateXML(virConnectPtr conn,
+                        const char *xmlDesc)
+{
+    DEBUG("conn=%p, xmlDesc=%s", conn, xmlDesc);
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+    if (xmlDesc == NULL) {
+        virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        return (NULL);
+    }
+
+    if (conn->storageDriver && conn->storageDriver->poolCreateXML)
+        return conn->storageDriver->poolCreateXML (conn, xmlDesc);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return NULL;
+}
+
+virStoragePoolPtr
+virStoragePoolDefineXML(virConnectPtr conn,
+                        const char *xml)
+{
+    DEBUG("conn=%p, xml=%s", conn, xml);
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        return (NULL);
+    }
+    if (xml == NULL) {
+        virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+
+    if (conn->storageDriver && conn->storageDriver->poolDefineXML)
+        return conn->storageDriver->poolDefineXML (conn, xml);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return NULL;
+
+}
+
+int
+virStoragePoolUndefine(virStoragePoolPtr pool)
+{
+    virConnectPtr conn;
+    DEBUG("pool=%p", pool);
+
+    if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
+        virLibStoragePoolError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
+        return (-1);
+    }
+    conn = pool->conn;
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        return (-1);
+    }
+
+    if (conn->storageDriver && conn->storageDriver->poolUndefine)
+        return conn->storageDriver->poolUndefine (pool);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+
+}
+
+int
+virStoragePoolCreate(virStoragePoolPtr pool)
+{
+    virConnectPtr conn;
+    DEBUG("pool=%p", pool);
+
+    if (pool == NULL) {
+        TODO;
+        return (-1);
+    }
+    if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
+        virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
+        return (-1);
+    }
+    conn = pool->conn;
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        return (-1);
+    }
+
+    if (conn->storageDriver && conn->storageDriver->poolCreate)
+        return conn->storageDriver->poolCreate (pool);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+
+}
+
+int
+virStoragePoolShutdown(virStoragePoolPtr pool)
+{
+    virConnectPtr conn;
+    DEBUG("pool=%p", pool);
+
+    if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
+        virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
+        return (-1);
+    }
+
+    conn = pool->conn;
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        return (-1);
+    }
+
+    if (conn->storageDriver && conn->storageDriver->poolShutdown)
+        return conn->storageDriver->poolShutdown (pool);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+
+int
+virStoragePoolDestroy	(virStoragePoolPtr pool)
+{
+    virConnectPtr conn;
+    DEBUG("pool=%p", pool);
+
+    if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
+        virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
+        return (-1);
+    }
+
+    conn = pool->conn;
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        return (-1);
+    }
+
+    if (conn->storageDriver && conn->storageDriver->poolDestroy)
+        return conn->storageDriver->poolDestroy (pool);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int
+virStoragePoolFree	(virStoragePoolPtr pool)
+{
+    DEBUG("pool=%p", pool);
+
+    if (!VIR_IS_STORAGE_POOL(pool)) {
+        virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
+        return (-1);
+    }
+    if (virFreeStoragePool(pool->conn, pool) < 0)
+        return (-1);
+    return(0);
+
+}
+
+const char*
+virStoragePoolGetName(virStoragePoolPtr pool)
+{
+    DEBUG("pool=%p", pool);
+
+    if (!VIR_IS_STORAGE_POOL(pool)) {
+        virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
+        return (NULL);
+    }
+    return (pool->name);
+
+}
+
+
+int
+virStoragePoolGetUUID(virStoragePoolPtr pool,
+                      unsigned char *uuid)
+{
+    DEBUG("pool=%p, uuid=%p", pool, uuid);
+
+    if (!VIR_IS_STORAGE_POOL(pool)) {
+        virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
+        return (-1);
+    }
+    if (uuid == NULL) {
+        virLibStoragePoolError(pool, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+
+    memcpy(uuid, &pool->uuid[0], VIR_UUID_BUFLEN);
+
+    return (0);
+
+}
+
+int
+virStoragePoolGetUUIDString(virStoragePoolPtr pool,
+                            char *buf)
+{
+    unsigned char uuid[VIR_UUID_BUFLEN];
+    DEBUG("pool=%p, buf=%p", pool, buf);
+
+    if (!VIR_IS_STORAGE_POOL(pool)) {
+        virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
+        return (-1);
+    }
+    if (buf == NULL) {
+        virLibStoragePoolError(pool, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+
+    if (virStoragePoolGetUUID(pool, &uuid[0]))
+        return (-1);
+
+    virUUIDFormat(uuid, buf);
+    return (0);
+
+}
+
+int
+virStoragePoolGetInfo(virStoragePoolPtr pool,
+                      virStoragePoolInfoPtr info)
+{
+    virConnectPtr conn;
+    DEBUG("pool=%p, info=%p", pool, info);
+
+    if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
+        virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
+        return (-1);
+    }
+    if (info == NULL) {
+        virLibStoragePoolError(pool, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+
+    memset(info, 0, sizeof(virStoragePoolInfo));
+
+    conn = pool->conn;
+
+    if (conn->storageDriver->poolGetInfo)
+        return conn->storageDriver->poolGetInfo (pool, info);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+
+}
+
+char *
+virStoragePoolGetXMLDesc(virStoragePoolPtr pool,
+                         int flags)
+{
+    virConnectPtr conn;
+    DEBUG("pool=%p, flags=%d", pool, flags);
+
+    if (!VIR_IS_STORAGE_POOL(pool)) {
+        virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
+        return (NULL);
+    }
+    if (flags != 0) {
+        virLibStoragePoolError(pool, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+
+    conn = pool->conn;
+
+    if (conn->storageDriver && conn->storageDriver->poolGetXMLDesc)
+        return conn->storageDriver->poolGetXMLDesc (pool, flags);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return NULL;
+
+}
+
+int
+virStoragePoolGetAutostart(virStoragePoolPtr pool,
+                           int *autostart)
+{
+    virConnectPtr conn;
+    DEBUG("pool=%p, autostart=%p", pool, autostart);
+
+    if (!VIR_IS_STORAGE_POOL(pool)) {
+        virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
+        return (-1);
+    }
+    if (!autostart) {
+        virLibStoragePoolError(pool, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+
+    conn = pool->conn;
+
+    if (conn->storageDriver && conn->storageDriver->poolGetAutostart)
+        return conn->storageDriver->poolGetAutostart (pool, autostart);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int
+virStoragePoolSetAutostart(virStoragePoolPtr pool,
+                           int autostart)
+{
+    virConnectPtr conn;
+    DEBUG("pool=%p, autostart=%d", pool, autostart);
+
+    if (!VIR_IS_STORAGE_POOL(pool)) {
+        virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
+        return (-1);
+    }
+
+    conn = pool->conn;
+
+    if (conn->storageDriver && conn->storageDriver->poolSetAutostart)
+        return conn->storageDriver->poolSetAutostart (pool, autostart);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int
+virStoragePoolNumOfVolumes(virStoragePoolPtr pool)
+{
+    DEBUG("pool=%p", pool);
+
+    if (!VIR_IS_STORAGE_POOL(pool)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
+        return (-1);
+    }
+
+    if (pool->conn->storageDriver && pool->conn->storageDriver->poolNumOfVolumes)
+        return pool->conn->storageDriver->poolNumOfVolumes (pool);
+
+    virLibConnError (pool->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+
+int
+virStoragePoolListVolumes(virStoragePoolPtr pool,
+                          char **const names,
+                          int maxnames)
+{
+    DEBUG("pool=%p, names=%p, maxnames=%d", pool, names, maxnames);
+
+    if (!VIR_IS_STORAGE_POOL(pool)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
+        return (-1);
+    }
+
+    if ((names == NULL) || (maxnames < 0)) {
+        virLibConnError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+
+    if (pool->conn->storageDriver && pool->conn->storageDriver->poolListVolumes)
+        return pool->conn->storageDriver->poolListVolumes (pool, names, maxnames);
+
+    virLibConnError (pool->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+virStorageVolPtr
+virStorageVolLookupByName(virStoragePoolPtr pool,
+                          const char *name)
+{
+    DEBUG("pool=%p, name=%s", pool, name);
+
+    if (!VIR_IS_STORAGE_POOL(pool)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+    if (name == NULL) {
+        virLibConnError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+
+    if (pool->conn->storageDriver && pool->conn->storageDriver->volLookupByName)
+        return pool->conn->storageDriver->volLookupByName (pool, name);
+
+    virLibConnError (pool->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return NULL;
+}
+
+virStorageVolPtr
+virStorageVolLookupByUUID(virStoragePoolPtr pool,
+                          const unsigned char *uuid)
+{
+    DEBUG("pool=%p, uuid=%p", pool, uuid);
+
+    if (!VIR_IS_STORAGE_POOL(pool)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+    if (uuid == NULL) {
+        virLibConnError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+
+    if (pool->conn->storageDriver && pool->conn->storageDriver->volLookupByUUID)
+        return pool->conn->storageDriver->volLookupByUUID (pool, uuid);
+
+    virLibConnError (pool->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return NULL;
+}
+
+virStorageVolPtr
+virStorageVolLookupByUUIDString(virStoragePoolPtr pool,
+                                const char *uuidstr)
+{
+    unsigned char uuid[VIR_UUID_BUFLEN];
+    DEBUG("pool=%p, uuidstr=%s", pool, uuidstr);
+
+    if (!VIR_IS_STORAGE_POOL(pool)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+    if (uuidstr == NULL) {
+        virLibConnError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+
+    if (virUUIDParse(uuidstr, uuid) < 0) {
+        virLibConnError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+
+    return virStorageVolLookupByUUID(pool, uuid);
+}
+
+const char*
+virStorageVolGetName(virStorageVolPtr vol)
+{
+    DEBUG("vol=%p", vol);
+
+    if (!VIR_IS_STORAGE_VOL(vol)) {
+        virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
+        return (NULL);
+    }
+    return (vol->name);
+}
+
+int
+virStorageVolGetUUID(virStorageVolPtr vol,
+                     unsigned char *uuid)
+{
+    DEBUG("vol=%p, uuid=%p", vol, uuid);
+
+    if (!VIR_IS_STORAGE_VOL(vol)) {
+        virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
+        return (-1);
+    }
+    if (uuid == NULL) {
+        virLibStorageVolError(vol, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+
+    memcpy(uuid, &vol->uuid[0], VIR_UUID_BUFLEN);
+
+    return (0);
+
+}
+
+
+int
+virStorageVolGetUUIDString(virStorageVolPtr vol,
+                           char *buf)
+{
+    unsigned char uuid[VIR_UUID_BUFLEN];
+    DEBUG("vol=%p, buf=%p", vol, buf);
+
+    if (!VIR_IS_STORAGE_VOL(vol)) {
+        virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
+        return (-1);
+    }
+    if (buf == NULL) {
+        virLibStorageVolError(vol, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+
+    if (virStorageVolGetUUID(vol, &uuid[0]))
+        return (-1);
+
+    virUUIDFormat(uuid, buf);
+    return (0);
+}
+
+
+
+virStorageVolPtr
+virStorageVolCreateXML(virStoragePoolPtr pool,
+                       const char *xmldesc,
+                       int flags)
+{
+    virConnectPtr conn;
+    DEBUG("pool=%p", pool);
+
+    if (pool == NULL) {
+        TODO;
+        return (NULL);
+    }
+    if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
+        virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
+        return (NULL);
+    }
+    conn = pool->conn;
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        return (NULL);
+    }
+
+    if (conn->storageDriver && conn->storageDriver->volCreateXML)
+        return conn->storageDriver->volCreateXML (pool, xmldesc, flags);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return NULL;
+}
+
+int
+virStorageVolDestroy(virStorageVolPtr vol)
+{
+    virConnectPtr conn;
+    DEBUG("vol=%p", vol);
+
+    if (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) {
+        virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
+        return (-1);
+    }
+
+    conn = vol->pool->conn;
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibStorageVolError(vol, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        return (-1);
+    }
+
+    if (conn->storageDriver && conn->storageDriver->volDestroy)
+        return conn->storageDriver->volDestroy (vol);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int
+virStorageVolFree(virStorageVolPtr vol)
+{
+    DEBUG("vol=%p", vol);
+
+    if (!VIR_IS_STORAGE_VOL(vol)) {
+        virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
+        return (-1);
+    }
+    if (virFreeStorageVol(vol->pool->conn, vol) < 0)
+        return (-1);
+    return(0);
+}
+
+int
+virStorageVolGetInfo(virStorageVolPtr vol,
+                     virStorageVolInfoPtr info)
+{
+    virConnectPtr conn;
+    DEBUG("vol=%p, info=%p", vol, info);
+
+    if (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) {
+        virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
+        return (-1);
+    }
+    if (info == NULL) {
+        virLibStorageVolError(vol, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+
+    memset(info, 0, sizeof(virStorageVolInfo));
+
+    conn = vol->pool->conn;
+
+    if (conn->storageDriver->volGetInfo)
+        return conn->storageDriver->volGetInfo (vol, info);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+char *
+virStorageVolGetXMLDesc(virStorageVolPtr vol,
+                        int flags)
+{
+    virConnectPtr conn;
+    DEBUG("vol=%p, flags=%d", vol, flags);
+
+    if (!VIR_IS_STORAGE_VOL(vol)) {
+        virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
+        return (NULL);
+    }
+    if (flags != 0) {
+        virLibStorageVolError(vol, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+
+    conn = vol->pool->conn;
+
+    if (conn->storageDriver && conn->storageDriver->volGetXMLDesc)
+        return conn->storageDriver->volGetXMLDesc (vol, flags);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return NULL;
+
+}
+
+char *
+virStorageVolGetPath(virStorageVolPtr vol)
+{
+    virConnectPtr conn;
+    DEBUG("vol=%p", vol);
+
+    if (!VIR_IS_STORAGE_VOL(vol)) {
+        virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
+        return (NULL);
+    }
+
+    conn = vol->pool->conn;
+
+    if (conn->storageDriver && conn->storageDriver->volGetPath)
+        return conn->storageDriver->volGetPath (vol);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return NULL;
+}
+
+
 /*
  * vim: set tabstop=4:
  * vim: set shiftwidth=4:
diff -r b5447763aad6 src/libvirt_sym.version
--- a/src/libvirt_sym.version	Sat Oct 27 16:56:42 2007 -0400
+++ b/src/libvirt_sym.version	Sun Oct 28 14:34:03 2007 -0400
@@ -119,8 +119,8 @@
 	virStoragePoolSetAutostart;
 	virStoragePoolGetAutostart;
 
-	virConnectNumOfStorageVolumes;
-	virConnectListStorageVolumes;
+	virStoragePoolNumOfVolumes;
+	virStoragePoolListVolumes;
 	virStorageVolCreateXML;
 	virStorageVolDestroy;
 	virStorageVolFree;

-- 
|=- Red Hat, Engineering, Emerging Technologies, Boston.  +1 978 392 2496 -=|
|=-           Perl modules: http://search.cpan.org/~danberr/              -=|
|=-               Projects: http://freshmeat.net/~danielpb/               -=|
|=-  GnuPG: 7D3B9505   F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505  -=| 




More information about the libvir-list mailing list