[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [Libvir] PATCH: 3/7 internal driver API



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  -=| 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]