提交 cb228a0e 编写于 作者: D Daniel P. Berrange

Internal driver API for storage management

上级 e1d2e325
Wed Feb 20 10:01:27 EST 2008 Daniel P. Berrange <berrange@redhat.com>
* include/libvirt/virterror.h, src/virterror.c: Add error codes
for storage API drivers
* src/internal.h, src/hash.c: Add internal storage object structs
* src/driver.h: internal driver API for storage management
* src/libvirt.c: hook up storage API to internal driver API
Wed Feb 20 09:51:27 EST 2008 Daniel P. Berrange <berrange@redhat.com>
* include/libvirt/libvirt.h, include/libvirt/libvirt.h.in,
......
......@@ -54,6 +54,7 @@ typedef enum {
VIR_FROM_OPENVZ, /* Error from OpenVZ driver */
VIR_FROM_XENXM, /* Error at Xen XM layer */
VIR_FROM_STATS_LINUX, /* Error in the Linux Stats code */
VIR_FROM_STORAGE, /* Error from storage driver */
} virErrorDomain;
......@@ -132,6 +133,9 @@ typedef enum {
VIR_ERR_NO_NETWORK, /* network not found */
VIR_ERR_INVALID_MAC, /* invalid MAC adress */
VIR_ERR_AUTH_FAILED, /* authentication failed */
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;
/**
......
......@@ -412,6 +412,151 @@ 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
(*virDrvStoragePoolLookupByVolume) (virStorageVolPtr vol);
typedef virStoragePoolPtr
(*virDrvStoragePoolCreateXML) (virConnectPtr conn,
const char *xmlDesc,
unsigned int flags);
typedef virStoragePoolPtr
(*virDrvStoragePoolDefineXML) (virConnectPtr conn,
const char *xmlDesc,
unsigned int flags);
typedef int
(*virDrvStoragePoolUndefine) (virStoragePoolPtr pool);
typedef int
(*virDrvStoragePoolBuild) (virStoragePoolPtr pool,
unsigned int flags);
typedef int
(*virDrvStoragePoolCreate) (virStoragePoolPtr pool,
unsigned int flags);
typedef int
(*virDrvStoragePoolDestroy) (virStoragePoolPtr pool);
typedef int
(*virDrvStoragePoolDelete) (virStoragePoolPtr pool,
unsigned int flags);
typedef int
(*virDrvStoragePoolRefresh) (virStoragePoolPtr pool,
unsigned int flags);
typedef int
(*virDrvStoragePoolGetInfo) (virStoragePoolPtr vol,
virStoragePoolInfoPtr info);
typedef char *
(*virDrvStoragePoolGetXMLDesc) (virStoragePoolPtr pool,
unsigned 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
(*virDrvStorageVolLookupByKey) (virConnectPtr pool,
const char *key);
typedef virStorageVolPtr
(*virDrvStorageVolLookupByPath) (virConnectPtr pool,
const char *path);
typedef virStorageVolPtr
(*virDrvStorageVolCreateXML) (virStoragePoolPtr pool,
const char *xmldesc,
unsigned int flags);
typedef int
(*virDrvStorageVolDelete) (virStorageVolPtr vol,
unsigned int flags);
typedef int
(*virDrvStorageVolGetInfo) (virStorageVolPtr vol,
virStorageVolInfoPtr info);
typedef char *
(*virDrvStorageVolGetXMLDesc) (virStorageVolPtr pool,
unsigned 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;
virDrvStoragePoolLookupByVolume poolLookupByVolume;
virDrvStoragePoolCreateXML poolCreateXML;
virDrvStoragePoolDefineXML poolDefineXML;
virDrvStoragePoolBuild poolBuild;
virDrvStoragePoolUndefine poolUndefine;
virDrvStoragePoolCreate poolCreate;
virDrvStoragePoolDestroy poolDestroy;
virDrvStoragePoolDelete poolDelete;
virDrvStoragePoolRefresh poolRefresh;
virDrvStoragePoolGetInfo poolGetInfo;
virDrvStoragePoolGetXMLDesc poolGetXMLDesc;
virDrvStoragePoolGetAutostart poolGetAutostart;
virDrvStoragePoolSetAutostart poolSetAutostart;
virDrvStoragePoolNumOfVolumes poolNumOfVolumes;
virDrvStoragePoolListVolumes poolListVolumes;
virDrvStorageVolLookupByName volLookupByName;
virDrvStorageVolLookupByKey volLookupByKey;
virDrvStorageVolLookupByPath volLookupByPath;
virDrvStorageVolCreateXML volCreateXML;
virDrvStorageVolDelete volDelete;
virDrvStorageVolGetInfo volGetInfo;
virDrvStorageVolGetXMLDesc volGetXMLDesc;
virDrvStorageVolGetPath volGetPath;
};
typedef int (*virDrvStateInitialize) (void);
typedef int (*virDrvStateCleanup) (void);
typedef int (*virDrvStateReload) (void);
......@@ -434,6 +579,7 @@ struct _virStateDriver {
*/
int virRegisterDriver(virDriverPtr);
int virRegisterNetworkDriver(virNetworkDriverPtr);
int virRegisterStorageDriver(virStorageDriverPtr);
int virRegisterStateDriver(virStateDriverPtr);
#ifdef __cplusplus
......
......@@ -651,6 +651,34 @@ virNetworkFreeName(virNetworkPtr network, const char *name ATTRIBUTE_UNUSED)
return (virNetworkFree(network));
}
/**
* virStoragePoolFreeName:
* @pool: a pool object
*
* Destroy the pool object, this is just used by the 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));
}
/**
* virStorageVolFreeName:
* @vol: a vol object
*
* Destroy the vol object, this is just used by the vol hash callback.
*
* Returns 0 in case of success and -1 in case of failure.
*/
static int
virStorageVolFreeName(virStorageVolPtr vol, const char *name ATTRIBUTE_UNUSED)
{
return (virStorageVolFree(vol));
}
/**
* virGetConnect:
*
......@@ -678,6 +706,12 @@ virGetConnect(void) {
ret->networks = virHashCreate(20);
if (ret->networks == NULL)
goto failed;
ret->storagePools = virHashCreate(20);
if (ret->storagePools == NULL)
goto failed;
ret->storageVols = virHashCreate(20);
if (ret->storageVols == NULL)
goto failed;
pthread_mutex_init(&ret->lock, NULL);
......@@ -690,6 +724,10 @@ 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->storageVols != NULL)
virHashFree(ret->storageVols, (virHashDeallocator) virStorageVolFreeName);
pthread_mutex_destroy(&ret->lock);
free(ret);
......@@ -713,6 +751,11 @@ virReleaseConnect(virConnectPtr conn) {
virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName);
if (conn->networks != NULL)
virHashFree(conn->networks, (virHashDeallocator) virNetworkFreeName);
if (conn->storagePools != NULL)
virHashFree(conn->storagePools, (virHashDeallocator) virStoragePoolFreeName);
if (conn->storageVols != NULL)
virHashFree(conn->storageVols, (virHashDeallocator) virStorageVolFreeName);
virResetError(&conn->err);
free(conn->name);
......@@ -1017,6 +1060,280 @@ virUnrefNetwork(virNetworkPtr network) {
return (refs);
}
/**
* virGetStoragePool:
* @conn: the hypervisor connection
* @name: pointer to the storage pool name
* @uuid: pointer to the uuid
*
* Lookup if the storage pool is already registered for that connection,
* if yes return a new pointer to it, if no allocate a new structure,
* 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 network, 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)) {
virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL);
}
pthread_mutex_lock(&conn->lock);
/* TODO search by UUID first as they are better differenciators */
ret = (virStoragePoolPtr) virHashLookup(conn->storagePools, name);
/* TODO check the UUID */
if (ret == NULL) {
ret = (virStoragePoolPtr) calloc(1, sizeof(*ret));
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->refs++;
}
ret->refs++;
pthread_mutex_unlock(&conn->lock);
return(ret);
error:
pthread_mutex_unlock(&conn->lock);
if (ret != NULL) {
free(ret->name);
free(ret);
}
return(NULL);
}
/**
* virReleaseStoragePool:
* @pool: the pool to release
*
* Unconditionally release all memory associated with a pool.
* The conn.lock mutex must be held prior to calling this, and will
* be released prior to this returning. The pool obj must not
* be used once this method returns.
*
* It will also unreference the associated connection object,
* which may also be released if its ref count hits zero.
*/
static void
virReleaseStoragePool(virStoragePoolPtr pool) {
virConnectPtr conn = pool->conn;
DEBUG("release pool %p %s", pool, pool->name);
/* 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"));
pool->magic = -1;
free(pool->name);
free(pool);
DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs);
conn->refs--;
if (conn->refs == 0) {
virReleaseConnect(conn);
/* Already unlocked mutex */
return;
}
pthread_mutex_unlock(&conn->lock);
}
/**
* virUnrefStoragePool:
* @pool: the pool to unreference
*
* Unreference the pool. If the use count drops to zero, the structure is
* actually freed.
*
* Returns the reference count or -1 in case of failure.
*/
int
virUnrefStoragePool(virStoragePoolPtr pool) {
int refs;
if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
virHashError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
pthread_mutex_lock(&pool->conn->lock);
DEBUG("unref pool %p %s %d", pool, pool->name, pool->refs);
pool->refs--;
refs = pool->refs;
if (refs == 0) {
virReleaseStoragePool(pool);
/* Already unlocked mutex */
return (0);
}
pthread_mutex_unlock(&pool->conn->lock);
return (refs);
}
/**
* virGetStorageVol:
* @conn: the hypervisor connection
* @pool: pool owning the volume
* @name: pointer to the storage vol name
* @uuid: pointer to the uuid
*
* Lookup if the storage vol is already registered for that connection,
* if yes return a new pointer to it, if no allocate a new structure,
* 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 storage vol, or NULL in case of failure
*/
virStorageVolPtr
__virGetStorageVol(virConnectPtr conn, const char *pool, const char *name, const char *key) {
virStorageVolPtr ret = NULL;
if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (key == NULL)) {
virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL);
}
pthread_mutex_lock(&conn->lock);
ret = (virStorageVolPtr) virHashLookup(conn->storageVols, key);
if (ret == NULL) {
ret = (virStorageVolPtr) calloc(1, sizeof(*ret));
if (ret == NULL) {
virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating storage vol"));
goto error;
}
ret->pool = strdup(pool);
if (ret->pool == NULL) {
virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating storage vol"));
goto error;
}
ret->name = strdup(name);
if (ret->name == NULL) {
virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating storage vol"));
goto error;
}
strncpy(ret->key, key, sizeof(ret->key)-1);
ret->key[sizeof(ret->key)-1] = '\0';
ret->magic = VIR_STORAGE_VOL_MAGIC;
ret->conn = conn;
if (virHashAddEntry(conn->storageVols, key, ret) < 0) {
virHashError(conn, VIR_ERR_INTERNAL_ERROR,
_("failed to add storage vol to connection hash table"));
goto error;
}
conn->refs++;
}
ret->refs++;
pthread_mutex_unlock(&conn->lock);
return(ret);
error:
pthread_mutex_unlock(&conn->lock);
if (ret != NULL) {
free(ret->name);
free(ret->pool);
free(ret);
}
return(NULL);
}
/**
* virReleaseStorageVol:
* @vol: the vol to release
*
* Unconditionally release all memory associated with a vol.
* The conn.lock mutex must be held prior to calling this, and will
* be released prior to this returning. The vol obj must not
* be used once this method returns.
*
* It will also unreference the associated connection object,
* which may also be released if its ref count hits zero.
*/
static void
virReleaseStorageVol(virStorageVolPtr vol) {
virConnectPtr conn = vol->conn;
DEBUG("release vol %p %s", vol, vol->name);
/* TODO search by UUID first as they are better differenciators */
if (virHashRemoveEntry(conn->storageVols, vol->key, NULL) < 0)
virHashError(conn, VIR_ERR_INTERNAL_ERROR,
_("vol missing from connection hash table"));
vol->magic = -1;
free(vol->name);
free(vol->pool);
free(vol);
DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs);
conn->refs--;
if (conn->refs == 0) {
virReleaseConnect(conn);
/* Already unlocked mutex */
return;
}
pthread_mutex_unlock(&conn->lock);
}
/**
* virUnrefStorageVol:
* @vol: the vol to unreference
*
* Unreference the vol. If the use count drops to zero, the structure is
* actually freed.
*
* Returns the reference count or -1 in case of failure.
*/
int
virUnrefStorageVol(virStorageVolPtr vol) {
int refs;
if (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) {
virHashError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
pthread_mutex_lock(&vol->conn->lock);
DEBUG("unref vol %p %s %d", vol, vol->name, vol->refs);
vol->refs--;
refs = vol->refs;
if (refs == 0) {
virReleaseStorageVol(vol);
/* Already unlocked mutex */
return (0);
}
pthread_mutex_unlock(&vol->conn->lock);
return (refs);
}
/*
* vim: set tabstop=4:
* vim: set shiftwidth=4:
......
......@@ -120,7 +120,7 @@ extern int debugFlag;
* 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)
......@@ -130,12 +130,32 @@ extern int debugFlag;
* 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_CONNECT((obj)->conn))
/*
* arbitrary limitations
*/
......@@ -155,6 +175,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.
......@@ -162,6 +183,7 @@ struct _virConnect {
*/
void * privateData;
void * networkPrivateData;
void * storagePrivateData;
/* Per-connection error. */
virError err; /* the last error */
......@@ -177,6 +199,8 @@ struct _virConnect {
pthread_mutex_t lock;
virHashTablePtr domains; /* hash table for known domains */
virHashTablePtr networks; /* hash table for known domains */
virHashTablePtr storagePools;/* hash table for known storage pools */
virHashTablePtr storageVols;/* hash table for known storage vols */
int refs; /* reference count */
};
......@@ -207,6 +231,34 @@ struct _virNetwork {
unsigned char uuid[VIR_UUID_BUFLEN]; /* the network unique identifier */
};
/**
* _virStoragePool:
*
* Internal structure associated to a storage pool
*/
struct _virStoragePool {
unsigned int magic; /* specific value to check */
int refs; /* 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 */
};
/**
* _virStorageVol:
*
* Internal structure associated to a storage volume
*/
struct _virStorageVol {
unsigned int magic; /* specific value to check */
int refs; /* reference count */
virConnectPtr conn; /* pointer back to the connection */
char *pool; /* Pool name of owner */
char *name; /* the storage vol external name */
/* XXX currently abusing path for this. Ought not to be so evil */
char key[PATH_MAX]; /* unique key for storage vol */
};
/************************************************************************
* *
......@@ -243,8 +295,20 @@ virNetworkPtr __virGetNetwork (virConnectPtr conn,
const unsigned char *uuid);
int virUnrefNetwork (virNetworkPtr network);
virStoragePoolPtr __virGetStoragePool (virConnectPtr conn,
const char *name,
const unsigned char *uuid);
int virUnrefStoragePool (virStoragePoolPtr pool);
virStorageVolPtr __virGetStorageVol (virConnectPtr conn,
const char *pool,
const char *name,
const char *key);
int virUnrefStorageVol (virStorageVolPtr vol);
#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,p,n,u) __virGetStorageVol((c),(p),(n),(u))
int __virStateInitialize(void);
int __virStateCleanup(void);
......
此差异已折叠。
......@@ -296,6 +296,9 @@ virDefaultErrorFunc(virErrorPtr err)
case VIR_FROM_STATS_LINUX:
dom = "Linux Stats ";
break;
case VIR_FROM_STORAGE:
dom = "Storage ";
break;
}
if ((err->dom != NULL) && (err->code != VIR_ERR_INVALID_DOMAIN)) {
......@@ -675,6 +678,24 @@ __virErrorMsg(virErrorNumber error, const char *info)
else
errmsg = _("authentication failed: %s");
break;
case VIR_ERR_INVALID_STORAGE_POOL:
if (info == NULL)
errmsg = _("invalid storage pool pointer in");
else
errmsg = _("invalid storage pool pointer in %s");
break;
case VIR_ERR_INVALID_STORAGE_VOL:
if (info == NULL)
errmsg = _("invalid storage volume pointer in");
else
errmsg = _("invalid storage volume pointer in %s");
break;
case VIR_WAR_NO_STORAGE:
if (info == NULL)
errmsg = _("Failed to find a storage driver");
else
errmsg = _("Failed to find a storage driver: %s");
break;
}
return (errmsg);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册