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 -=| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list