mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-30 01:43:23 +00:00
Add a test storage driver.
This commit is contained in:
parent
f22d0fcd8d
commit
c5ee075dd9
@ -1,3 +1,7 @@
|
|||||||
|
Thu Oct 30 13:39:00 EST 2008 Cole Robinson <crobinso@redhat.com>
|
||||||
|
|
||||||
|
* src/test.c: Add a test storage driver.
|
||||||
|
|
||||||
Wed Oct 29 16:33:16 CET 2008 Daniel Veillard <veillard@redhat.com>
|
Wed Oct 29 16:33:16 CET 2008 Daniel Veillard <veillard@redhat.com>
|
||||||
|
|
||||||
* docs/relatedlinks.html docs/relatedlinks.html.in: add link
|
* docs/relatedlinks.html docs/relatedlinks.html.in: add link
|
||||||
|
753
src/test.c
753
src/test.c
@ -29,6 +29,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <libxml/xmlsave.h>
|
||||||
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
#include "buf.h"
|
#include "buf.h"
|
||||||
@ -38,6 +39,7 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "network_conf.h"
|
#include "network_conf.h"
|
||||||
#include "domain_conf.h"
|
#include "domain_conf.h"
|
||||||
|
#include "storage_conf.h"
|
||||||
#include "xml.h"
|
#include "xml.h"
|
||||||
|
|
||||||
#define MAX_CPUS 128
|
#define MAX_CPUS 128
|
||||||
@ -59,6 +61,7 @@ struct _testConn {
|
|||||||
virNodeInfo nodeInfo;
|
virNodeInfo nodeInfo;
|
||||||
virDomainObjList domains;
|
virDomainObjList domains;
|
||||||
virNetworkObjList networks;
|
virNetworkObjList networks;
|
||||||
|
virStoragePoolObjList pools;
|
||||||
int numCells;
|
int numCells;
|
||||||
testCell cells[MAX_CELLS];
|
testCell cells[MAX_CELLS];
|
||||||
};
|
};
|
||||||
@ -106,11 +109,56 @@ static const virNodeInfo defaultNodeInfo = {
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define GET_POOL(pool, ret) \
|
||||||
|
testConnPtr privconn; \
|
||||||
|
virStoragePoolObjPtr privpool; \
|
||||||
|
\
|
||||||
|
privconn = (testConnPtr)pool->conn->privateData; \
|
||||||
|
do { \
|
||||||
|
if ((privpool = virStoragePoolObjFindByName(&privconn->pools, \
|
||||||
|
(pool)->name)) == NULL) {\
|
||||||
|
testError((pool)->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); \
|
||||||
|
return (ret); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define GET_POOL_FROM_VOL(vol, ret) \
|
||||||
|
GET_POOL(testStoragePoolLookupByName((virConnectPtr) \
|
||||||
|
vol->conn, \
|
||||||
|
vol->pool), ret)
|
||||||
|
|
||||||
|
#define GET_VOL(vol, pool, ret) \
|
||||||
|
virStorageVolDefPtr privvol; \
|
||||||
|
\
|
||||||
|
privvol = virStorageVolDefFindByName(pool, vol->name); \
|
||||||
|
do { \
|
||||||
|
if (!privvol) { \
|
||||||
|
testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL, \
|
||||||
|
_("no storage vol with matching name '%s'"), \
|
||||||
|
vol->name); \
|
||||||
|
return (ret); \
|
||||||
|
} \
|
||||||
|
} while (0) \
|
||||||
|
|
||||||
|
|
||||||
#define GET_CONNECTION(conn) \
|
#define GET_CONNECTION(conn) \
|
||||||
testConnPtr privconn; \
|
testConnPtr privconn; \
|
||||||
\
|
\
|
||||||
privconn = (testConnPtr)conn->privateData;
|
privconn = (testConnPtr)conn->privateData;
|
||||||
|
|
||||||
|
#define POOL_IS_ACTIVE(pool, ret) \
|
||||||
|
if (!virStoragePoolObjIsActive(pool)) { \
|
||||||
|
testError(obj->conn, VIR_ERR_INTERNAL_ERROR, \
|
||||||
|
_("storage pool '%s' is not active"), pool->def->name); \
|
||||||
|
return (ret); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define POOL_IS_NOT_ACTIVE(pool, ret) \
|
||||||
|
if (virStoragePoolObjIsActive(pool)) { \
|
||||||
|
testError(obj->conn, VIR_ERR_INTERNAL_ERROR, \
|
||||||
|
_("storage pool '%s' is already active"), pool->def->name); \
|
||||||
|
return (ret); \
|
||||||
|
} \
|
||||||
|
|
||||||
#define testError(conn, code, fmt...) \
|
#define testError(conn, code, fmt...) \
|
||||||
__virReportErrorHelper(conn, VIR_FROM_TEST, code, __FILE__, \
|
__virReportErrorHelper(conn, VIR_FROM_TEST, code, __FILE__, \
|
||||||
@ -196,6 +244,18 @@ static const char *defaultNetworkXML =
|
|||||||
" </ip>"
|
" </ip>"
|
||||||
"</network>";
|
"</network>";
|
||||||
|
|
||||||
|
static const char *defaultPoolXML =
|
||||||
|
"<pool type='dir'>"
|
||||||
|
" <name>default-pool</name>"
|
||||||
|
" <target>"
|
||||||
|
" <path>/default-pool</path>"
|
||||||
|
" </target>"
|
||||||
|
"</pool>";
|
||||||
|
|
||||||
|
static const unsigned long long defaultPoolCap = (100 * 1024 * 1024 * 1024ul);
|
||||||
|
static const unsigned long long defaultPoolAlloc = 0;
|
||||||
|
|
||||||
|
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool);
|
||||||
|
|
||||||
static int testOpenDefault(virConnectPtr conn) {
|
static int testOpenDefault(virConnectPtr conn) {
|
||||||
int u;
|
int u;
|
||||||
@ -205,6 +265,8 @@ static int testOpenDefault(virConnectPtr conn) {
|
|||||||
virDomainObjPtr domobj = NULL;
|
virDomainObjPtr domobj = NULL;
|
||||||
virNetworkDefPtr netdef = NULL;
|
virNetworkDefPtr netdef = NULL;
|
||||||
virNetworkObjPtr netobj = NULL;
|
virNetworkObjPtr netobj = NULL;
|
||||||
|
virStoragePoolDefPtr pooldef = NULL;
|
||||||
|
virStoragePoolObjPtr poolobj = NULL;
|
||||||
|
|
||||||
if (VIR_ALLOC(privconn) < 0) {
|
if (VIR_ALLOC(privconn) < 0) {
|
||||||
testError(conn, VIR_ERR_NO_MEMORY, "testConn");
|
testError(conn, VIR_ERR_NO_MEMORY, "testConn");
|
||||||
@ -250,15 +312,27 @@ static int testOpenDefault(virConnectPtr conn) {
|
|||||||
virNetworkDefFree(netdef);
|
virNetworkDefFree(netdef);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
netobj->active = 1;
|
netobj->active = 1;
|
||||||
netobj->persistent = 1;
|
netobj->persistent = 1;
|
||||||
|
|
||||||
|
if (!(pooldef = virStoragePoolDefParse(conn, defaultPoolXML, NULL)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!(poolobj = virStoragePoolObjAssignDef(conn, &privconn->pools,
|
||||||
|
pooldef))) {
|
||||||
|
virStoragePoolDefFree(pooldef);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (testStoragePoolObjSetDefaults(poolobj) == -1)
|
||||||
|
goto error;
|
||||||
|
poolobj->active = 1;
|
||||||
|
|
||||||
return VIR_DRV_OPEN_SUCCESS;
|
return VIR_DRV_OPEN_SUCCESS;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
virDomainObjListFree(&privconn->domains);
|
virDomainObjListFree(&privconn->domains);
|
||||||
virNetworkObjListFree(&privconn->networks);
|
virNetworkObjListFree(&privconn->networks);
|
||||||
|
virStoragePoolObjListFree(&privconn->pools);
|
||||||
virCapabilitiesFree(privconn->caps);
|
virCapabilitiesFree(privconn->caps);
|
||||||
VIR_FREE(privconn);
|
VIR_FREE(privconn);
|
||||||
return VIR_DRV_OPEN_ERROR;
|
return VIR_DRV_OPEN_ERROR;
|
||||||
@ -295,7 +369,7 @@ static int testOpenFromFile(virConnectPtr conn,
|
|||||||
char *str;
|
char *str;
|
||||||
xmlDocPtr xml = NULL;
|
xmlDocPtr xml = NULL;
|
||||||
xmlNodePtr root = NULL;
|
xmlNodePtr root = NULL;
|
||||||
xmlNodePtr *domains = NULL, *networks = NULL;
|
xmlNodePtr *domains = NULL, *networks = NULL, *pools = NULL;
|
||||||
xmlXPathContextPtr ctxt = NULL;
|
xmlXPathContextPtr ctxt = NULL;
|
||||||
virNodeInfoPtr nodeInfo;
|
virNodeInfoPtr nodeInfo;
|
||||||
virNetworkObjPtr net;
|
virNetworkObjPtr net;
|
||||||
@ -311,7 +385,9 @@ static int testOpenFromFile(virConnectPtr conn,
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if ((fd = open(file, O_RDONLY)) < 0) {
|
if ((fd = open(file, O_RDONLY)) < 0) {
|
||||||
testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("loading host definition file"));
|
testError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("loading host definition file '%s': %s"),
|
||||||
|
file, strerror(errno));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,7 +408,8 @@ static int testOpenFromFile(virConnectPtr conn,
|
|||||||
|
|
||||||
ctxt = xmlXPathNewContext(xml);
|
ctxt = xmlXPathNewContext(xml);
|
||||||
if (ctxt == NULL) {
|
if (ctxt == NULL) {
|
||||||
testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("creating xpath context"));
|
testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("creating xpath context"));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,6 +557,58 @@ static int testOpenFromFile(virConnectPtr conn,
|
|||||||
if (networks != NULL)
|
if (networks != NULL)
|
||||||
VIR_FREE(networks);
|
VIR_FREE(networks);
|
||||||
|
|
||||||
|
/* Parse Storage Pool list */
|
||||||
|
ret = virXPathNodeSet(conn, "/node/pool", ctxt, &pools);
|
||||||
|
if (ret < 0) {
|
||||||
|
testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node pool list"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
for (i = 0 ; i < ret ; i++) {
|
||||||
|
virStoragePoolDefPtr def;
|
||||||
|
virStoragePoolObjPtr pool;
|
||||||
|
char *relFile = virXMLPropString(pools[i], "file");
|
||||||
|
if (relFile != NULL) {
|
||||||
|
char *absFile = testBuildFilename(file, relFile);
|
||||||
|
VIR_FREE(relFile);
|
||||||
|
if (!absFile) {
|
||||||
|
testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("resolving pool filename"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
def = virStoragePoolDefParse(conn, NULL, absFile);
|
||||||
|
VIR_FREE(absFile);
|
||||||
|
if (!def)
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
xmlBufferPtr buf;
|
||||||
|
xmlSaveCtxtPtr sctxt;
|
||||||
|
|
||||||
|
buf = xmlBufferCreate();
|
||||||
|
sctxt = xmlSaveToBuffer(buf, NULL, 0);
|
||||||
|
xmlSaveTree(sctxt, pools[i]);
|
||||||
|
xmlSaveClose(sctxt);
|
||||||
|
if ((def = virStoragePoolDefParse(conn,
|
||||||
|
(const char *) buf->content,
|
||||||
|
NULL)) == NULL) {
|
||||||
|
xmlBufferFree(buf);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools,
|
||||||
|
def))) {
|
||||||
|
virStoragePoolDefFree(def);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (testStoragePoolObjSetDefaults(pool) == -1)
|
||||||
|
goto error;
|
||||||
|
pool->active = 1;
|
||||||
|
}
|
||||||
|
if (pools != NULL)
|
||||||
|
VIR_FREE(pools);
|
||||||
|
|
||||||
xmlXPathFreeContext(ctxt);
|
xmlXPathFreeContext(ctxt);
|
||||||
xmlFreeDoc(xml);
|
xmlFreeDoc(xml);
|
||||||
|
|
||||||
@ -490,10 +619,12 @@ static int testOpenFromFile(virConnectPtr conn,
|
|||||||
xmlFreeDoc(xml);
|
xmlFreeDoc(xml);
|
||||||
VIR_FREE(domains);
|
VIR_FREE(domains);
|
||||||
VIR_FREE(networks);
|
VIR_FREE(networks);
|
||||||
|
VIR_FREE(pools);
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
close(fd);
|
close(fd);
|
||||||
virDomainObjListFree(&privconn->domains);
|
virDomainObjListFree(&privconn->domains);
|
||||||
virNetworkObjListFree(&privconn->networks);
|
virNetworkObjListFree(&privconn->networks);
|
||||||
|
virStoragePoolObjListFree(&privconn->pools);
|
||||||
VIR_FREE(privconn);
|
VIR_FREE(privconn);
|
||||||
conn->privateData = NULL;
|
conn->privateData = NULL;
|
||||||
return VIR_DRV_OPEN_ERROR;
|
return VIR_DRV_OPEN_ERROR;
|
||||||
@ -545,6 +676,7 @@ static int testClose(virConnectPtr conn)
|
|||||||
virCapabilitiesFree(privconn->caps);
|
virCapabilitiesFree(privconn->caps);
|
||||||
virDomainObjListFree(&privconn->domains);
|
virDomainObjListFree(&privconn->domains);
|
||||||
virNetworkObjListFree(&privconn->networks);
|
virNetworkObjListFree(&privconn->networks);
|
||||||
|
virStoragePoolObjListFree(&privconn->pools);
|
||||||
|
|
||||||
VIR_FREE (privconn);
|
VIR_FREE (privconn);
|
||||||
conn->privateData = conn;
|
conn->privateData = conn;
|
||||||
@ -1475,6 +1607,26 @@ static int testNetworkSetAutostart(virNetworkPtr network,
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Storage Driver routines
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool) {
|
||||||
|
|
||||||
|
pool->def->capacity = defaultPoolCap;
|
||||||
|
pool->def->allocation = defaultPoolAlloc;
|
||||||
|
pool->def->available = defaultPoolCap - defaultPoolAlloc;
|
||||||
|
|
||||||
|
pool->configFile = strdup("\0");
|
||||||
|
if (!pool->configFile) {
|
||||||
|
testError(NULL, VIR_ERR_NO_MEMORY, "configFile");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static virDrvOpenStatus testStorageOpen(virConnectPtr conn,
|
static virDrvOpenStatus testStorageOpen(virConnectPtr conn,
|
||||||
xmlURIPtr uri ATTRIBUTE_UNUSED,
|
xmlURIPtr uri ATTRIBUTE_UNUSED,
|
||||||
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
||||||
@ -1491,6 +1643,566 @@ static int testStorageClose(virConnectPtr conn) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static virStoragePoolPtr
|
||||||
|
testStoragePoolLookupByUUID(virConnectPtr conn,
|
||||||
|
const unsigned char *uuid) {
|
||||||
|
virStoragePoolObjPtr pool = NULL;
|
||||||
|
GET_CONNECTION(conn);
|
||||||
|
|
||||||
|
if ((pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid)) == NULL) {
|
||||||
|
testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return virGetStoragePool(conn, pool->def->name, pool->def->uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static virStoragePoolPtr
|
||||||
|
testStoragePoolLookupByName(virConnectPtr conn,
|
||||||
|
const char *name) {
|
||||||
|
virStoragePoolObjPtr pool = NULL;
|
||||||
|
GET_CONNECTION(conn);
|
||||||
|
|
||||||
|
if ((pool = virStoragePoolObjFindByName(&privconn->pools, name)) == NULL) {
|
||||||
|
testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return virGetStoragePool(conn, pool->def->name, pool->def->uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static virStoragePoolPtr
|
||||||
|
testStoragePoolLookupByVolume(virStorageVolPtr vol) {
|
||||||
|
return testStoragePoolLookupByName(vol->conn, vol->pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
testStorageNumPools(virConnectPtr conn) {
|
||||||
|
|
||||||
|
int numActive = 0, i;
|
||||||
|
GET_CONNECTION(conn);
|
||||||
|
|
||||||
|
for (i = 0 ; i < privconn->pools.count ; i++)
|
||||||
|
if (virStoragePoolObjIsActive(privconn->pools.objs[i]))
|
||||||
|
numActive++;
|
||||||
|
|
||||||
|
return numActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
testStorageListPools(virConnectPtr conn,
|
||||||
|
char **const names,
|
||||||
|
int nnames) {
|
||||||
|
int n = 0, i;
|
||||||
|
GET_CONNECTION(conn);
|
||||||
|
|
||||||
|
memset(names, 0, sizeof(*names)*nnames);
|
||||||
|
for (i = 0 ; i < privconn->pools.count && n < nnames ; i++)
|
||||||
|
if (virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
|
||||||
|
!(names[n++] = strdup(privconn->pools.objs[i]->def->name)))
|
||||||
|
goto no_memory;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
|
||||||
|
no_memory:
|
||||||
|
testError(conn, VIR_ERR_NO_MEMORY, NULL);
|
||||||
|
for (n = 0 ; n < nnames ; n++)
|
||||||
|
VIR_FREE(names[n]);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
testStorageNumDefinedPools(virConnectPtr conn) {
|
||||||
|
|
||||||
|
int numInactive = 0, i;
|
||||||
|
GET_CONNECTION(conn);
|
||||||
|
|
||||||
|
for (i = 0 ; i < privconn->pools.count ; i++)
|
||||||
|
if (!virStoragePoolObjIsActive(privconn->pools.objs[i]))
|
||||||
|
numInactive++;
|
||||||
|
|
||||||
|
return numInactive;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
testStorageListDefinedPools(virConnectPtr conn,
|
||||||
|
char **const names,
|
||||||
|
int nnames) {
|
||||||
|
int n = 0, i;
|
||||||
|
GET_CONNECTION(conn);
|
||||||
|
|
||||||
|
memset(names, 0, sizeof(*names)*nnames);
|
||||||
|
for (i = 0 ; i < privconn->pools.count && n < nnames ; i++)
|
||||||
|
if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
|
||||||
|
!(names[n++] = strdup(privconn->pools.objs[i]->def->name)))
|
||||||
|
goto no_memory;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
|
||||||
|
no_memory:
|
||||||
|
testError(conn, VIR_ERR_NO_MEMORY, NULL);
|
||||||
|
for (n = 0 ; n < nnames ; n++)
|
||||||
|
VIR_FREE(names[n]);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
testStoragePoolRefresh(virStoragePoolPtr obj,
|
||||||
|
unsigned int flags ATTRIBUTE_UNUSED);
|
||||||
|
|
||||||
|
static int
|
||||||
|
testStoragePoolStart(virStoragePoolPtr obj,
|
||||||
|
unsigned int flags ATTRIBUTE_UNUSED) {
|
||||||
|
GET_POOL(obj, -1);
|
||||||
|
POOL_IS_NOT_ACTIVE(privpool, -1);
|
||||||
|
|
||||||
|
if (testStoragePoolRefresh(obj, 0) == 0)
|
||||||
|
return -1;
|
||||||
|
privpool->active = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
testStorageFindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||||
|
const char *type ATTRIBUTE_UNUSED,
|
||||||
|
const char *srcSpec ATTRIBUTE_UNUSED,
|
||||||
|
unsigned int flags ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static virStoragePoolPtr
|
||||||
|
testStoragePoolCreate(virConnectPtr conn,
|
||||||
|
const char *xml,
|
||||||
|
unsigned int flags ATTRIBUTE_UNUSED) {
|
||||||
|
virStoragePoolDefPtr def;
|
||||||
|
virStoragePoolObjPtr pool;
|
||||||
|
GET_CONNECTION(conn);
|
||||||
|
|
||||||
|
if (!(def = virStoragePoolDefParse(conn, xml, NULL)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (virStoragePoolObjFindByUUID(&privconn->pools, def->uuid) ||
|
||||||
|
virStoragePoolObjFindByName(&privconn->pools, def->name)) {
|
||||||
|
testError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("storage pool already exists"));
|
||||||
|
virStoragePoolDefFree(def);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, def))) {
|
||||||
|
virStoragePoolDefFree(def);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (testStoragePoolObjSetDefaults(pool) == -1) {
|
||||||
|
virStoragePoolObjRemove(&privconn->pools, pool);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
pool->active = 1;
|
||||||
|
|
||||||
|
return virGetStoragePool(conn, pool->def->name, pool->def->uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static virStoragePoolPtr
|
||||||
|
testStoragePoolDefine(virConnectPtr conn,
|
||||||
|
const char *xml,
|
||||||
|
unsigned int flags ATTRIBUTE_UNUSED) {
|
||||||
|
virStoragePoolDefPtr def;
|
||||||
|
virStoragePoolObjPtr pool;
|
||||||
|
GET_CONNECTION(conn);
|
||||||
|
|
||||||
|
if (!(def = virStoragePoolDefParse(conn, xml, NULL)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
def->capacity = defaultPoolCap;
|
||||||
|
def->allocation = defaultPoolAlloc;
|
||||||
|
def->available = defaultPoolCap - defaultPoolAlloc;
|
||||||
|
|
||||||
|
if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, def))) {
|
||||||
|
virStoragePoolDefFree(def);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (testStoragePoolObjSetDefaults(pool) == -1) {
|
||||||
|
virStoragePoolObjRemove(&privconn->pools, pool);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return virGetStoragePool(conn, pool->def->name, pool->def->uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
testStoragePoolUndefine(virStoragePoolPtr obj) {
|
||||||
|
GET_POOL(obj, -1);
|
||||||
|
POOL_IS_NOT_ACTIVE(privpool, -1);
|
||||||
|
|
||||||
|
virStoragePoolObjRemove(&privconn->pools, privpool);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
testStoragePoolBuild(virStoragePoolPtr obj,
|
||||||
|
unsigned int flags ATTRIBUTE_UNUSED) {
|
||||||
|
GET_POOL(obj, -1);
|
||||||
|
POOL_IS_NOT_ACTIVE(privpool, -1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
testStoragePoolDestroy(virStoragePoolPtr obj) {
|
||||||
|
GET_POOL(obj, -1);
|
||||||
|
POOL_IS_ACTIVE(privpool, -1);
|
||||||
|
|
||||||
|
privpool->active = 0;
|
||||||
|
|
||||||
|
if (privpool->configFile == NULL)
|
||||||
|
virStoragePoolObjRemove(&privconn->pools, privpool);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
testStoragePoolDelete(virStoragePoolPtr obj,
|
||||||
|
unsigned int flags ATTRIBUTE_UNUSED) {
|
||||||
|
GET_POOL(obj, -1);
|
||||||
|
POOL_IS_NOT_ACTIVE(privpool, -1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
testStoragePoolRefresh(virStoragePoolPtr obj,
|
||||||
|
unsigned int flags ATTRIBUTE_UNUSED) {
|
||||||
|
GET_POOL(obj, -1);
|
||||||
|
POOL_IS_ACTIVE(privpool, -1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
testStoragePoolGetInfo(virStoragePoolPtr obj,
|
||||||
|
virStoragePoolInfoPtr info) {
|
||||||
|
GET_POOL(obj, -1);
|
||||||
|
|
||||||
|
memset(info, 0, sizeof(virStoragePoolInfo));
|
||||||
|
if (privpool->active)
|
||||||
|
info->state = VIR_STORAGE_POOL_RUNNING;
|
||||||
|
else
|
||||||
|
info->state = VIR_STORAGE_POOL_INACTIVE;
|
||||||
|
info->capacity = privpool->def->capacity;
|
||||||
|
info->allocation = privpool->def->allocation;
|
||||||
|
info->available = privpool->def->available;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
testStoragePoolDumpXML(virStoragePoolPtr obj,
|
||||||
|
unsigned int flags ATTRIBUTE_UNUSED) {
|
||||||
|
GET_POOL(obj, NULL);
|
||||||
|
|
||||||
|
return virStoragePoolDefFormat(obj->conn, privpool->def);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
testStoragePoolGetAutostart(virStoragePoolPtr obj,
|
||||||
|
int *autostart) {
|
||||||
|
GET_POOL(obj, -1);
|
||||||
|
|
||||||
|
if (!privpool->configFile) {
|
||||||
|
*autostart = 0;
|
||||||
|
} else {
|
||||||
|
*autostart = privpool->autostart;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
testStoragePoolSetAutostart(virStoragePoolPtr obj,
|
||||||
|
int autostart) {
|
||||||
|
GET_POOL(obj, -1);
|
||||||
|
|
||||||
|
if (!privpool->configFile) {
|
||||||
|
testError(obj->conn, VIR_ERR_INVALID_ARG,
|
||||||
|
"%s", _("pool has no config file"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
autostart = (autostart != 0);
|
||||||
|
|
||||||
|
if (privpool->autostart == autostart)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
privpool->autostart = autostart;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
testStoragePoolNumVolumes(virStoragePoolPtr obj) {
|
||||||
|
GET_POOL(obj, -1);
|
||||||
|
POOL_IS_ACTIVE(privpool, -1);
|
||||||
|
|
||||||
|
return privpool->volumes.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
testStoragePoolListVolumes(virStoragePoolPtr obj,
|
||||||
|
char **const names,
|
||||||
|
int maxnames) {
|
||||||
|
GET_POOL(obj, -1);
|
||||||
|
POOL_IS_ACTIVE(privpool, -1);
|
||||||
|
int i = 0, n = 0;
|
||||||
|
|
||||||
|
memset(names, 0, maxnames);
|
||||||
|
for (i = 0 ; i < privpool->volumes.count && n < maxnames ; i++) {
|
||||||
|
if ((names[n++] = strdup(privpool->volumes.objs[i]->name)) == NULL) {
|
||||||
|
testError(obj->conn, VIR_ERR_NO_MEMORY, "%s", _("name"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
for (n = 0 ; n < maxnames ; n++)
|
||||||
|
VIR_FREE(names[i]);
|
||||||
|
|
||||||
|
memset(names, 0, maxnames);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static virStorageVolPtr
|
||||||
|
testStorageVolumeLookupByName(virStoragePoolPtr obj,
|
||||||
|
const char *name ATTRIBUTE_UNUSED) {
|
||||||
|
GET_POOL(obj, NULL);
|
||||||
|
POOL_IS_ACTIVE(privpool, NULL);
|
||||||
|
virStorageVolDefPtr vol = virStorageVolDefFindByName(privpool, name);
|
||||||
|
|
||||||
|
if (!vol) {
|
||||||
|
testError(obj->conn, VIR_ERR_INVALID_STORAGE_VOL,
|
||||||
|
_("no storage vol with matching name '%s'"), name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return virGetStorageVol(obj->conn, privpool->def->name,
|
||||||
|
vol->name, vol->key);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static virStorageVolPtr
|
||||||
|
testStorageVolumeLookupByKey(virConnectPtr conn,
|
||||||
|
const char *key) {
|
||||||
|
GET_CONNECTION(conn);
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0 ; i < privconn->pools.count ; i++) {
|
||||||
|
if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
|
||||||
|
virStorageVolDefPtr vol =
|
||||||
|
virStorageVolDefFindByKey(privconn->pools.objs[i], key);
|
||||||
|
|
||||||
|
if (vol)
|
||||||
|
return virGetStorageVol(conn,
|
||||||
|
privconn->pools.objs[i]->def->name,
|
||||||
|
vol->name,
|
||||||
|
vol->key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testError(conn, VIR_ERR_INVALID_STORAGE_VOL,
|
||||||
|
_("no storage vol with matching key '%s'"), key);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static virStorageVolPtr
|
||||||
|
testStorageVolumeLookupByPath(virConnectPtr conn,
|
||||||
|
const char *path) {
|
||||||
|
GET_CONNECTION(conn);
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0 ; i < privconn->pools.count ; i++) {
|
||||||
|
if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
|
||||||
|
virStorageVolDefPtr vol =
|
||||||
|
virStorageVolDefFindByPath(privconn->pools.objs[i], path);
|
||||||
|
|
||||||
|
if (vol)
|
||||||
|
return virGetStorageVol(conn,
|
||||||
|
privconn->pools.objs[i]->def->name,
|
||||||
|
vol->name,
|
||||||
|
vol->key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testError(conn, VIR_ERR_INVALID_STORAGE_VOL,
|
||||||
|
_("no storage vol with matching path '%s'"), path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static virStorageVolPtr
|
||||||
|
testStorageVolumeCreateXML(virStoragePoolPtr obj,
|
||||||
|
const char *xmldesc,
|
||||||
|
unsigned int flags ATTRIBUTE_UNUSED) {
|
||||||
|
GET_POOL(obj, NULL);
|
||||||
|
POOL_IS_ACTIVE(privpool, NULL);
|
||||||
|
virStorageVolDefPtr vol;
|
||||||
|
|
||||||
|
vol = virStorageVolDefParse(obj->conn, privpool->def, xmldesc, NULL);
|
||||||
|
if (vol == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (virStorageVolDefFindByName(privpool, vol->name)) {
|
||||||
|
testError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
|
||||||
|
"%s", _("storage vol already exists"));
|
||||||
|
virStorageVolDefFree(vol);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure enough space */
|
||||||
|
if ((privpool->def->allocation + vol->allocation) >
|
||||||
|
privpool->def->capacity) {
|
||||||
|
testError(obj->conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Not enough free space in pool for volume '%s'"),
|
||||||
|
vol->name);
|
||||||
|
virStorageVolDefFree(vol);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
privpool->def->available = (privpool->def->capacity -
|
||||||
|
privpool->def->allocation);
|
||||||
|
|
||||||
|
if (VIR_REALLOC_N(privpool->volumes.objs,
|
||||||
|
privpool->volumes.count+1) < 0) {
|
||||||
|
testError(obj->conn, VIR_ERR_NO_MEMORY, NULL);
|
||||||
|
virStorageVolDefFree(vol);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VIR_ALLOC_N(vol->target.path, strlen(privpool->def->target.path) +
|
||||||
|
1 + strlen(vol->name) + 1) < 0) {
|
||||||
|
virStorageVolDefFree(vol);
|
||||||
|
testError(obj->conn, VIR_ERR_NO_MEMORY, "%s", _("target"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(vol->target.path, privpool->def->target.path);
|
||||||
|
strcat(vol->target.path, "/");
|
||||||
|
strcat(vol->target.path, vol->name);
|
||||||
|
vol->key = strdup(vol->target.path);
|
||||||
|
if (vol->key == NULL) {
|
||||||
|
virStorageVolDefFree(vol);
|
||||||
|
testError(obj->conn, VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("storage vol key"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
privpool->def->allocation += vol->allocation;
|
||||||
|
privpool->def->available = (privpool->def->capacity -
|
||||||
|
privpool->def->allocation);
|
||||||
|
|
||||||
|
privpool->volumes.objs[privpool->volumes.count++] = vol;
|
||||||
|
|
||||||
|
return virGetStorageVol(obj->conn, privpool->def->name, vol->name,
|
||||||
|
vol->key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
testStorageVolumeDelete(virStorageVolPtr obj,
|
||||||
|
unsigned int flags ATTRIBUTE_UNUSED) {
|
||||||
|
GET_POOL_FROM_VOL(obj, -1);
|
||||||
|
POOL_IS_ACTIVE(privpool, -1);
|
||||||
|
GET_VOL(obj, privpool, -1);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
privpool->def->allocation -= privvol->allocation;
|
||||||
|
privpool->def->available = (privpool->def->capacity -
|
||||||
|
privpool->def->allocation);
|
||||||
|
|
||||||
|
for (i = 0 ; i < privpool->volumes.count ; i++) {
|
||||||
|
if (privpool->volumes.objs[i] == privvol) {
|
||||||
|
virStorageVolDefFree(privvol);
|
||||||
|
|
||||||
|
if (i < (privpool->volumes.count - 1))
|
||||||
|
memmove(privpool->volumes.objs + i,
|
||||||
|
privpool->volumes.objs + i + 1,
|
||||||
|
sizeof(*(privpool->volumes.objs)) *
|
||||||
|
(privpool->volumes.count - (i + 1)));
|
||||||
|
|
||||||
|
if (VIR_REALLOC_N(privpool->volumes.objs,
|
||||||
|
privpool->volumes.count - 1) < 0) {
|
||||||
|
; /* Failure to reduce memory allocation isn't fatal */
|
||||||
|
}
|
||||||
|
privpool->volumes.count--;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int testStorageVolumeTypeForPool(int pooltype) {
|
||||||
|
|
||||||
|
switch(pooltype) {
|
||||||
|
case VIR_STORAGE_POOL_DIR:
|
||||||
|
case VIR_STORAGE_POOL_FS:
|
||||||
|
case VIR_STORAGE_POOL_NETFS:
|
||||||
|
return VIR_STORAGE_VOL_FILE;
|
||||||
|
default:
|
||||||
|
return VIR_STORAGE_VOL_BLOCK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
testStorageVolumeGetInfo(virStorageVolPtr obj,
|
||||||
|
virStorageVolInfoPtr info) {
|
||||||
|
GET_POOL_FROM_VOL(obj, -1);
|
||||||
|
POOL_IS_ACTIVE(privpool, -1);
|
||||||
|
GET_VOL(obj, privpool, -1);
|
||||||
|
|
||||||
|
memset(info, 0, sizeof(*info));
|
||||||
|
info->type = testStorageVolumeTypeForPool(privpool->def->type);
|
||||||
|
info->capacity = privvol->capacity;
|
||||||
|
info->allocation = privvol->allocation;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
testStorageVolumeGetXMLDesc(virStorageVolPtr obj,
|
||||||
|
unsigned int flags ATTRIBUTE_UNUSED) {
|
||||||
|
GET_POOL_FROM_VOL(obj, NULL);
|
||||||
|
POOL_IS_ACTIVE(privpool, NULL);
|
||||||
|
GET_VOL(obj, privpool, NULL);
|
||||||
|
|
||||||
|
return virStorageVolDefFormat(obj->conn, privpool->def, privvol);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
testStorageVolumeGetPath(virStorageVolPtr obj) {
|
||||||
|
GET_POOL_FROM_VOL(obj, NULL);
|
||||||
|
POOL_IS_ACTIVE(privpool, NULL);
|
||||||
|
GET_VOL(obj, privpool, NULL);
|
||||||
|
char *ret;
|
||||||
|
|
||||||
|
ret = strdup(privvol->target.path);
|
||||||
|
if (ret == NULL) {
|
||||||
|
testError(obj->conn, VIR_ERR_NO_MEMORY, "%s", _("path"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static virDriver testDriver = {
|
static virDriver testDriver = {
|
||||||
VIR_DRV_TEST,
|
VIR_DRV_TEST,
|
||||||
@ -1577,11 +2289,42 @@ static virNetworkDriver testNetworkDriver = {
|
|||||||
testNetworkSetAutostart, /* networkSetAutostart */
|
testNetworkSetAutostart, /* networkSetAutostart */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static virStorageDriver testStorageDriver = {
|
static virStorageDriver testStorageDriver = {
|
||||||
.name = "Test",
|
.name = "Test",
|
||||||
.open = testStorageOpen,
|
.open = testStorageOpen,
|
||||||
.close = testStorageClose,
|
.close = testStorageClose,
|
||||||
|
|
||||||
|
.numOfPools = testStorageNumPools,
|
||||||
|
.listPools = testStorageListPools,
|
||||||
|
.numOfDefinedPools = testStorageNumDefinedPools,
|
||||||
|
.listDefinedPools = testStorageListDefinedPools,
|
||||||
|
.findPoolSources = testStorageFindPoolSources,
|
||||||
|
.poolLookupByName = testStoragePoolLookupByName,
|
||||||
|
.poolLookupByUUID = testStoragePoolLookupByUUID,
|
||||||
|
.poolLookupByVolume = testStoragePoolLookupByVolume,
|
||||||
|
.poolCreateXML = testStoragePoolCreate,
|
||||||
|
.poolDefineXML = testStoragePoolDefine,
|
||||||
|
.poolBuild = testStoragePoolBuild,
|
||||||
|
.poolUndefine = testStoragePoolUndefine,
|
||||||
|
.poolCreate = testStoragePoolStart,
|
||||||
|
.poolDestroy = testStoragePoolDestroy,
|
||||||
|
.poolDelete = testStoragePoolDelete,
|
||||||
|
.poolRefresh = testStoragePoolRefresh,
|
||||||
|
.poolGetInfo = testStoragePoolGetInfo,
|
||||||
|
.poolGetXMLDesc = testStoragePoolDumpXML,
|
||||||
|
.poolGetAutostart = testStoragePoolGetAutostart,
|
||||||
|
.poolSetAutostart = testStoragePoolSetAutostart,
|
||||||
|
.poolNumOfVolumes = testStoragePoolNumVolumes,
|
||||||
|
.poolListVolumes = testStoragePoolListVolumes,
|
||||||
|
|
||||||
|
.volLookupByName = testStorageVolumeLookupByName,
|
||||||
|
.volLookupByKey = testStorageVolumeLookupByKey,
|
||||||
|
.volLookupByPath = testStorageVolumeLookupByPath,
|
||||||
|
.volCreateXML = testStorageVolumeCreateXML,
|
||||||
|
.volDelete = testStorageVolumeDelete,
|
||||||
|
.volGetInfo = testStorageVolumeGetInfo,
|
||||||
|
.volGetXMLDesc = testStorageVolumeGetXMLDesc,
|
||||||
|
.volGetPath = testStorageVolumeGetPath,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user