From: Daniel P. Berrange Date: Tue, 15 Sep 2009 17:38:50 +0000 (+0100) Subject: Move test driver into src/test/ X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=0b648155e7ad577c5e0ff42c1633fe913dca4946;p=libvirt.git Move test driver into src/test/ * src/Makefile.am, src/libvirt.c: Adjust for changed paths * src/test.c: Rename to src/test/test_driver.c, * src/test.h: Rename to src/test/test_driver.h --- diff --git a/src/Makefile.am b/src/Makefile.am index 81c40e45a8..b2c2ca6187 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -104,7 +104,7 @@ REMOTE_DRIVER_SOURCES = \ # Mock driver, covering domains, storage, networks, etc TEST_DRIVER_SOURCES = \ - test.c test.h + test/test_driver.c test/test_driver.h diff --git a/src/libvirt.c b/src/libvirt.c index 6a0fb00a64..98f17ffc98 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -44,7 +44,7 @@ #ifndef WITH_DRIVER_MODULES #ifdef WITH_TEST -#include "test.h" +#include "test/test_driver.h" #endif #ifdef WITH_XEN #include "xen/xen_driver.h" diff --git a/src/test.c b/src/test.c deleted file mode 100644 index 368a3cbfcc..0000000000 --- a/src/test.c +++ /dev/null @@ -1,4375 +0,0 @@ -/* - * test.c: A "mock" hypervisor for use by application unit tests - * - * Copyright (C) 2006-2009 Red Hat, Inc. - * Copyright (C) 2006 Daniel P. Berrange - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Daniel Berrange - */ - -#include - -#include -#include -#include -#include -#include -#include -#include - - -#include "virterror_internal.h" -#include "datatypes.h" -#include "test.h" -#include "buf.h" -#include "util.h" -#include "uuid.h" -#include "capabilities.h" -#include "memory.h" -#include "network_conf.h" -#include "interface_conf.h" -#include "domain_conf.h" -#include "domain_event.h" -#include "event.h" -#include "storage_conf.h" -#include "xml.h" -#include "threads.h" -#include "logging.h" - -#define VIR_FROM_THIS VIR_FROM_TEST - -#define MAX_CPUS 128 - -struct _testCell { - unsigned long mem; - int numCpus; - int cpus[MAX_CPUS]; -}; -typedef struct _testCell testCell; -typedef struct _testCell *testCellPtr; - -#define MAX_CELLS 128 - -struct _testConn { - virMutex lock; - - char path[PATH_MAX]; - int nextDomID; - virCapsPtr caps; - virNodeInfo nodeInfo; - virDomainObjList domains; - virNetworkObjList networks; - virInterfaceObjList ifaces; - virStoragePoolObjList pools; - int numCells; - testCell cells[MAX_CELLS]; - - - /* An array of callbacks */ - virDomainEventCallbackListPtr domainEventCallbacks; - virDomainEventQueuePtr domainEventQueue; - int domainEventTimer; - int domainEventDispatching; -}; -typedef struct _testConn testConn; -typedef struct _testConn *testConnPtr; - -#define TEST_MODEL "i686" -#define TEST_MODEL_WORDSIZE 32 -#define TEST_EMULATOR "/usr/bin/test-hv" - -static const virNodeInfo defaultNodeInfo = { - TEST_MODEL, - 1024*1024*3, /* 3 GB */ - 16, - 1400, - 2, - 2, - 2, - 2, -}; - - -#define testError(conn, code, fmt...) \ - virReportErrorHelper(conn, VIR_FROM_TEST, code, __FILE__, \ - __FUNCTION__, __LINE__, fmt) - -static int testClose(virConnectPtr conn); -static void testDomainEventFlush(int timer, void *opaque); -static void testDomainEventQueue(testConnPtr driver, - virDomainEventPtr event); - - -static void testDriverLock(testConnPtr driver) -{ - virMutexLock(&driver->lock); -} - -static void testDriverUnlock(testConnPtr driver) -{ - virMutexUnlock(&driver->lock); -} - -static virCapsPtr -testBuildCapabilities(virConnectPtr conn) { - testConnPtr privconn = conn->privateData; - virCapsPtr caps; - virCapsGuestPtr guest; - const char *const guest_types[] = { "hvm", "xen" }; - int i; - - if ((caps = virCapabilitiesNew(TEST_MODEL, 0, 0)) == NULL) - goto no_memory; - - if (virCapabilitiesAddHostFeature(caps, "pae") < 0) - goto no_memory; - if (virCapabilitiesAddHostFeature(caps ,"nonpae") < 0) - goto no_memory; - - for (i = 0; i < privconn->numCells; i++) { - if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].numCpus, - privconn->cells[i].cpus) < 0) - goto no_memory; - } - - for (i = 0; i < ARRAY_CARDINALITY(guest_types) ; i++) { - if ((guest = virCapabilitiesAddGuest(caps, - guest_types[i], - TEST_MODEL, - TEST_MODEL_WORDSIZE, - TEST_EMULATOR, - NULL, - 0, - NULL)) == NULL) - goto no_memory; - - if (virCapabilitiesAddGuestDomain(guest, - "test", - NULL, - NULL, - 0, - NULL) == NULL) - goto no_memory; - - if (virCapabilitiesAddGuestFeature(guest, "pae", 1, 1) == NULL) - goto no_memory; - if (virCapabilitiesAddGuestFeature(guest ,"nonpae", 1, 1) == NULL) - goto no_memory; - } - - return caps; - -no_memory: - virReportOOMError(conn); - virCapabilitiesFree(caps); - return NULL; -} - - -static const char *defaultDomainXML = -"" -" test" -" 8388608" -" 2097152" -" 2" -" " -" hvm" -" " -""; - - -static const char *defaultNetworkXML = -"" -" default" -" " -" " -" " -" " -" " -" " -" " -""; - -static const char *defaultInterfaceXML = -"" -" " -" " -" " -" " -" " -" " -" " -""; - -static const char *defaultPoolXML = -"" -" default-pool" -" " -" /default-pool" -" " -""; - -static const unsigned long long defaultPoolCap = (100 * 1024 * 1024 * 1024ull); -static const unsigned long long defaultPoolAlloc = 0; - -static int testStoragePoolObjSetDefaults(virConnectPtr conn, virStoragePoolObjPtr pool); - -static char * -testDomainGenerateIfname(virConnectPtr conn, - virDomainDefPtr domdef) { - int maxif = 1024; - int ifctr, i; - - for (ifctr = 0; ifctr < maxif; ++ifctr) { - char *ifname; - int found = 0; - - if (virAsprintf(&ifname, "testnet%d", ifctr) < 0) { - virReportOOMError(conn); - return NULL; - } - - /* Generate network interface names */ - for (i = 0 ; i < domdef->nnets ; i++) { - if (domdef->nets[i]->ifname && - STREQ (domdef->nets[i]->ifname, ifname)) { - found = 1; - break; - } - } - - if (!found) - return ifname; - } - - testError(conn, VIR_ERR_INTERNAL_ERROR, - _("Exceeded max iface limit %d"), maxif); - return NULL; -} - -static int -testDomainGenerateIfnames(virConnectPtr conn, - virDomainDefPtr domdef) -{ - int i = 0; - - for (i = 0; i < domdef->nnets; i++) { - char *ifname; - if (domdef->nets[i]->ifname) - continue; - - ifname = testDomainGenerateIfname(conn, domdef); - if (!ifname) - return -1; - - domdef->nets[i]->ifname = ifname; - } - - return 0; -} - - -static int testOpenDefault(virConnectPtr conn) { - int u; - struct timeval tv; - testConnPtr privconn; - virDomainDefPtr domdef = NULL; - virDomainObjPtr domobj = NULL; - virNetworkDefPtr netdef = NULL; - virNetworkObjPtr netobj = NULL; - virInterfaceDefPtr interfacedef = NULL; - virInterfaceObjPtr interfaceobj = NULL; - virStoragePoolDefPtr pooldef = NULL; - virStoragePoolObjPtr poolobj = NULL; - - if (VIR_ALLOC(privconn) < 0) { - virReportOOMError(conn); - return VIR_DRV_OPEN_ERROR; - } - if (virMutexInit(&privconn->lock) < 0) { - testError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("cannot initialize mutex")); - VIR_FREE(privconn); - return VIR_DRV_OPEN_ERROR; - } - - testDriverLock(privconn); - conn->privateData = privconn; - - if (gettimeofday(&tv, NULL) < 0) { - virReportSystemError(conn, errno, - "%s", _("getting time of day")); - goto error; - } - - memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo)); - - // Numa setup - privconn->numCells = 2; - for (u = 0; u < 2; ++u) { - privconn->cells[u].numCpus = 8; - privconn->cells[u].mem = (u + 1) * 2048 * 1024; - } - for (u = 0 ; u < 16 ; u++) { - privconn->cells[u % 2].cpus[(u / 2)] = u; - } - - if (!(privconn->caps = testBuildCapabilities(conn))) - goto error; - - privconn->nextDomID = 1; - - if (!(domdef = virDomainDefParseString(conn, privconn->caps, - defaultDomainXML, - VIR_DOMAIN_XML_INACTIVE))) - goto error; - if (testDomainGenerateIfnames(conn, domdef) < 0) - goto error; - if (!(domobj = virDomainAssignDef(conn, &privconn->domains, domdef))) - goto error; - domdef = NULL; - domobj->def->id = privconn->nextDomID++; - domobj->state = VIR_DOMAIN_RUNNING; - domobj->persistent = 1; - virDomainObjUnlock(domobj); - - if (!(netdef = virNetworkDefParseString(conn, defaultNetworkXML))) - goto error; - if (!(netobj = virNetworkAssignDef(conn, &privconn->networks, netdef))) { - virNetworkDefFree(netdef); - goto error; - } - netobj->active = 1; - netobj->persistent = 1; - virNetworkObjUnlock(netobj); - - if (!(interfacedef = virInterfaceDefParseString(conn, defaultInterfaceXML))) - goto error; - if (!(interfaceobj = virInterfaceAssignDef(conn, &privconn->ifaces, interfacedef))) { - virInterfaceDefFree(interfacedef); - goto error; - } - interfaceobj->active = 1; - virInterfaceObjUnlock(interfaceobj); - - if (!(pooldef = virStoragePoolDefParseString(conn, defaultPoolXML))) - goto error; - - if (!(poolobj = virStoragePoolObjAssignDef(conn, &privconn->pools, - pooldef))) { - virStoragePoolDefFree(pooldef); - goto error; - } - - if (testStoragePoolObjSetDefaults(conn, poolobj) == -1) { - virStoragePoolObjUnlock(poolobj); - goto error; - } - poolobj->active = 1; - virStoragePoolObjUnlock(poolobj); - - testDriverUnlock(privconn); - - return VIR_DRV_OPEN_SUCCESS; - -error: - virDomainObjListFree(&privconn->domains); - virNetworkObjListFree(&privconn->networks); - virInterfaceObjListFree(&privconn->ifaces); - virStoragePoolObjListFree(&privconn->pools); - virCapabilitiesFree(privconn->caps); - testDriverUnlock(privconn); - conn->privateData = NULL; - VIR_FREE(privconn); - virDomainDefFree(domdef); - return VIR_DRV_OPEN_ERROR; -} - - -static char *testBuildFilename(const char *relativeTo, - const char *filename) { - char *offset; - int baseLen; - if (!filename || filename[0] == '\0') - return (NULL); - if (filename[0] == '/') - return strdup(filename); - - offset = strrchr(relativeTo, '/'); - if ((baseLen = (offset-relativeTo+1))) { - char *absFile; - if (VIR_ALLOC_N(absFile, baseLen + strlen(filename) + 1) < 0) - return NULL; - strncpy(absFile, relativeTo, baseLen); - absFile[baseLen] = '\0'; - strcat(absFile, filename); - return absFile; - } else { - return strdup(filename); - } -} - -static int testOpenVolumesForPool(virConnectPtr conn, - xmlDocPtr xml, - xmlXPathContextPtr ctxt, - const char *file, - virStoragePoolObjPtr pool, - int poolidx) { - char *vol_xpath; - int i, ret, func_ret = -1; - xmlNodePtr *vols = NULL; - virStorageVolDefPtr def = NULL; - - /* Find storage volumes */ - if (virAsprintf(&vol_xpath, "/node/pool[%d]/volume", poolidx) < 0) { - virReportOOMError(NULL); - goto error; - } - - ret = virXPathNodeSet(conn, vol_xpath, ctxt, &vols); - VIR_FREE(vol_xpath); - if (ret < 0) { - testError(NULL, VIR_ERR_XML_ERROR, - _("node vol list for pool '%s'"), pool->def->name); - goto error; - } - - for (i = 0 ; i < ret ; i++) { - char *relFile = virXMLPropString(vols[i], "file"); - if (relFile != NULL) { - char *absFile = testBuildFilename(file, relFile); - VIR_FREE(relFile); - if (!absFile) { - testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", - _("resolving volume filename")); - goto error; - } - - def = virStorageVolDefParseFile(conn, pool->def, absFile); - VIR_FREE(absFile); - if (!def) - goto error; - } else { - if ((def = virStorageVolDefParseNode(conn, pool->def, xml, - vols[i])) == NULL) { - goto error; - } - } - - if (VIR_REALLOC_N(pool->volumes.objs, - pool->volumes.count+1) < 0) { - virReportOOMError(conn); - goto error; - } - - if (virAsprintf(&def->target.path, "%s/%s", - pool->def->target.path, - def->name) == -1) { - virReportOOMError(conn); - goto error; - } - - def->key = strdup(def->target.path); - if (def->key == NULL) { - virReportOOMError(conn); - goto error; - } - - pool->def->allocation += def->allocation; - pool->def->available = (pool->def->capacity - - pool->def->allocation); - - pool->volumes.objs[pool->volumes.count++] = def; - def = NULL; - } - - func_ret = 0; -error: - virStorageVolDefFree(def); - VIR_FREE(vols); - return func_ret; -} - -static int testOpenFromFile(virConnectPtr conn, - const char *file) { - int fd = -1, i, ret; - long l; - char *str; - xmlDocPtr xml = NULL; - xmlNodePtr root = NULL; - xmlNodePtr *domains = NULL, *networks = NULL, *ifaces = NULL, *pools = NULL; - xmlXPathContextPtr ctxt = NULL; - virNodeInfoPtr nodeInfo; - virNetworkObjPtr net; - virInterfaceObjPtr iface; - virDomainObjPtr dom; - testConnPtr privconn; - if (VIR_ALLOC(privconn) < 0) { - virReportOOMError(conn); - return VIR_DRV_OPEN_ERROR; - } - if (virMutexInit(&privconn->lock) < 0) { - testError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("cannot initialize mutex")); - VIR_FREE(privconn); - return VIR_DRV_OPEN_ERROR; - } - - testDriverLock(privconn); - conn->privateData = privconn; - - if (!(privconn->caps = testBuildCapabilities(conn))) - goto error; - - if ((fd = open(file, O_RDONLY)) < 0) { - virReportSystemError(NULL, errno, - _("loading host definition file '%s'"), - file); - goto error; - } - - if (!(xml = xmlReadFd(fd, file, NULL, - XML_PARSE_NOENT | XML_PARSE_NONET | - XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) { - testError(NULL, VIR_ERR_INTERNAL_ERROR, - _("Invalid XML in file '%s'"), file); - goto error; - } - close(fd); - fd = -1; - - root = xmlDocGetRootElement(xml); - if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "node"))) { - testError(NULL, VIR_ERR_XML_ERROR, "%s", - _("Root element is not 'node'")); - goto error; - } - - ctxt = xmlXPathNewContext(xml); - if (ctxt == NULL) { - testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", - _("creating xpath context")); - goto error; - } - - privconn->nextDomID = 1; - privconn->numCells = 0; - strncpy(privconn->path, file, PATH_MAX-1); - privconn->path[PATH_MAX-1] = '\0'; - memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo)); - - nodeInfo = &privconn->nodeInfo; - ret = virXPathLong(conn, "string(/node/cpu/nodes[1])", ctxt, &l); - if (ret == 0) { - nodeInfo->nodes = l; - } else if (ret == -2) { - testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu numa nodes")); - goto error; - } - - ret = virXPathLong(conn, "string(/node/cpu/sockets[1])", ctxt, &l); - if (ret == 0) { - nodeInfo->sockets = l; - } else if (ret == -2) { - testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu sockets")); - goto error; - } - - ret = virXPathLong(conn, "string(/node/cpu/cores[1])", ctxt, &l); - if (ret == 0) { - nodeInfo->cores = l; - } else if (ret == -2) { - testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu cores")); - goto error; - } - - ret = virXPathLong(conn, "string(/node/cpu/threads[1])", ctxt, &l); - if (ret == 0) { - nodeInfo->threads = l; - } else if (ret == -2) { - testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu threads")); - goto error; - } - - nodeInfo->cpus = nodeInfo->cores * nodeInfo->threads * nodeInfo->sockets * nodeInfo->nodes; - ret = virXPathLong(conn, "string(/node/cpu/active[1])", ctxt, &l); - if (ret == 0) { - if (l < nodeInfo->cpus) { - nodeInfo->cpus = l; - } - } else if (ret == -2) { - testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node active cpu")); - goto error; - } - ret = virXPathLong(conn, "string(/node/cpu/mhz[1])", ctxt, &l); - if (ret == 0) { - nodeInfo->mhz = l; - } else if (ret == -2) { - testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu mhz")); - goto error; - } - - str = virXPathString(conn, "string(/node/cpu/model[1])", ctxt); - if (str != NULL) { - strncpy(nodeInfo->model, str, sizeof(nodeInfo->model)-1); - nodeInfo->model[sizeof(nodeInfo->model)-1] = '\0'; - VIR_FREE(str); - } - - ret = virXPathLong(conn, "string(/node/memory[1])", ctxt, &l); - if (ret == 0) { - nodeInfo->memory = l; - } else if (ret == -2) { - testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node memory")); - goto error; - } - - ret = virXPathNodeSet(conn, "/node/domain", ctxt, &domains); - if (ret < 0) { - testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node domain list")); - goto error; - } - - for (i = 0 ; i < ret ; i++) { - virDomainDefPtr def; - char *relFile = virXMLPropString(domains[i], "file"); - if (relFile != NULL) { - char *absFile = testBuildFilename(file, relFile); - VIR_FREE(relFile); - if (!absFile) { - testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("resolving domain filename")); - goto error; - } - def = virDomainDefParseFile(conn, privconn->caps, absFile, - VIR_DOMAIN_XML_INACTIVE); - VIR_FREE(absFile); - if (!def) - goto error; - } else { - if ((def = virDomainDefParseNode(conn, privconn->caps, xml, domains[i], - VIR_DOMAIN_XML_INACTIVE)) == NULL) - goto error; - } - - if (testDomainGenerateIfnames(conn, def) < 0 || - !(dom = virDomainAssignDef(conn, &privconn->domains, def))) { - virDomainDefFree(def); - goto error; - } - - dom->state = VIR_DOMAIN_RUNNING; - dom->def->id = privconn->nextDomID++; - dom->persistent = 1; - virDomainObjUnlock(dom); - } - VIR_FREE(domains); - - ret = virXPathNodeSet(conn, "/node/network", ctxt, &networks); - if (ret < 0) { - testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node network list")); - goto error; - } - for (i = 0 ; i < ret ; i++) { - virNetworkDefPtr def; - char *relFile = virXMLPropString(networks[i], "file"); - if (relFile != NULL) { - char *absFile = testBuildFilename(file, relFile); - VIR_FREE(relFile); - if (!absFile) { - testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("resolving network filename")); - goto error; - } - - def = virNetworkDefParseFile(conn, absFile); - VIR_FREE(absFile); - if (!def) - goto error; - } else { - if ((def = virNetworkDefParseNode(conn, xml, networks[i])) == NULL) - goto error; - } - if (!(net = virNetworkAssignDef(conn, &privconn->networks, - def))) { - virNetworkDefFree(def); - goto error; - } - net->persistent = 1; - net->active = 1; - virNetworkObjUnlock(net); - } - VIR_FREE(networks); - - /* Parse interface definitions */ - ret = virXPathNodeSet(conn, "/node/interface", ctxt, &ifaces); - if (ret < 0) { - testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node interface list")); - goto error; - } - for (i = 0 ; i < ret ; i++) { - virInterfaceDefPtr def; - char *relFile = virXMLPropString(ifaces[i], "file"); - if (relFile != NULL) { - char *absFile = testBuildFilename(file, relFile); - VIR_FREE(relFile); - if (!absFile) { - testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("resolving interface filename")); - goto error; - } - - def = virInterfaceDefParseFile(conn, absFile); - VIR_FREE(absFile); - if (!def) - goto error; - } else { - if ((def = virInterfaceDefParseNode(conn, xml, ifaces[i])) == NULL) - goto error; - } - if (!(iface = virInterfaceAssignDef(conn, &privconn->ifaces, def))) { - virInterfaceDefFree(def); - goto error; - } - virInterfaceObjUnlock(iface); - } - VIR_FREE(ifaces); - - /* 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 = virStoragePoolDefParseFile(conn, absFile); - VIR_FREE(absFile); - if (!def) - goto error; - } else { - if ((def = virStoragePoolDefParseNode(conn, xml, - pools[i])) == NULL) { - goto error; - } - } - - if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, - def))) { - virStoragePoolDefFree(def); - goto error; - } - - if (testStoragePoolObjSetDefaults(conn, pool) == -1) { - virStoragePoolObjUnlock(pool); - goto error; - } - pool->active = 1; - - /* Find storage volumes */ - if (testOpenVolumesForPool(conn, xml, ctxt, file, pool, i+1) < 0) { - virStoragePoolObjUnlock(pool); - goto error; - } - - virStoragePoolObjUnlock(pool); - } - VIR_FREE(pools); - - xmlXPathFreeContext(ctxt); - xmlFreeDoc(xml); - testDriverUnlock(privconn); - - return (0); - - error: - xmlXPathFreeContext(ctxt); - xmlFreeDoc(xml); - VIR_FREE(domains); - VIR_FREE(networks); - VIR_FREE(ifaces); - VIR_FREE(pools); - if (fd != -1) - close(fd); - virDomainObjListFree(&privconn->domains); - virNetworkObjListFree(&privconn->networks); - virInterfaceObjListFree(&privconn->ifaces); - virStoragePoolObjListFree(&privconn->pools); - testDriverUnlock(privconn); - VIR_FREE(privconn); - conn->privateData = NULL; - return VIR_DRV_OPEN_ERROR; -} - - -static virDrvOpenStatus testOpen(virConnectPtr conn, - virConnectAuthPtr auth ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED) -{ - int ret; - - if (!conn->uri) - return VIR_DRV_OPEN_DECLINED; - - if (!conn->uri->scheme || STRNEQ(conn->uri->scheme, "test")) - return VIR_DRV_OPEN_DECLINED; - - /* Remote driver should handle these. */ - if (conn->uri->server) - return VIR_DRV_OPEN_DECLINED; - - /* From this point on, the connection is for us. */ - if (!conn->uri->path - || conn->uri->path[0] == '\0' - || (conn->uri->path[0] == '/' && conn->uri->path[1] == '\0')) { - testError (NULL, VIR_ERR_INVALID_ARG, - "%s", _("testOpen: supply a path or use test:///default")); - return VIR_DRV_OPEN_ERROR; - } - - if (STREQ(conn->uri->path, "/default")) - ret = testOpenDefault(conn); - else - ret = testOpenFromFile(conn, - conn->uri->path); - - if (ret == VIR_DRV_OPEN_SUCCESS) { - testConnPtr privconn = conn->privateData; - testDriverLock(privconn); - /* Init callback list */ - if (VIR_ALLOC(privconn->domainEventCallbacks) < 0 || - !(privconn->domainEventQueue = virDomainEventQueueNew())) { - virReportOOMError(NULL); - testDriverUnlock(privconn); - testClose(conn); - return VIR_DRV_OPEN_ERROR; - } - - if ((privconn->domainEventTimer = - virEventAddTimeout(-1, testDomainEventFlush, privconn, NULL)) < 0) - DEBUG0("virEventAddTimeout failed: No addTimeoutImpl defined. " - "continuing without events."); - testDriverUnlock(privconn); - } - - return (ret); -} - -static int testClose(virConnectPtr conn) -{ - testConnPtr privconn = conn->privateData; - testDriverLock(privconn); - virCapabilitiesFree(privconn->caps); - virDomainObjListFree(&privconn->domains); - virNetworkObjListFree(&privconn->networks); - virInterfaceObjListFree(&privconn->ifaces); - virStoragePoolObjListFree(&privconn->pools); - - virDomainEventCallbackListFree(privconn->domainEventCallbacks); - virDomainEventQueueFree(privconn->domainEventQueue); - - if (privconn->domainEventTimer != -1) - virEventRemoveTimeout(privconn->domainEventTimer); - - testDriverUnlock(privconn); - virMutexDestroy(&privconn->lock); - - VIR_FREE (privconn); - conn->privateData = NULL; - return 0; -} - -static int testGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED, - unsigned long *hvVer) -{ - *hvVer = 2; - return (0); -} - -static char *testGetHostname (virConnectPtr conn) -{ - char *result; - - result = virGetHostname(); - if (result == NULL) { - virReportSystemError(conn, errno, - "%s", _("cannot lookup hostname")); - return NULL; - } - /* Caller frees this string. */ - return result; -} - -static int testGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED, - const char *type ATTRIBUTE_UNUSED) -{ - return 32; -} - -static int testNodeGetInfo(virConnectPtr conn, - virNodeInfoPtr info) -{ - testConnPtr privconn = conn->privateData; - testDriverLock(privconn); - memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo)); - testDriverUnlock(privconn); - return (0); -} - -static char *testGetCapabilities (virConnectPtr conn) -{ - testConnPtr privconn = conn->privateData; - char *xml; - testDriverLock(privconn); - if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL) - virReportOOMError(conn); - testDriverUnlock(privconn); - return xml; -} - -static int testNumOfDomains(virConnectPtr conn) -{ - testConnPtr privconn = conn->privateData; - unsigned int numActive = 0, i; - - testDriverLock(privconn); - for (i = 0 ; i < privconn->domains.count ; i++) - if (virDomainIsActive(privconn->domains.objs[i])) - numActive++; - testDriverUnlock(privconn); - - return numActive; -} - -static virDomainPtr -testDomainCreateXML(virConnectPtr conn, const char *xml, - unsigned int flags ATTRIBUTE_UNUSED) -{ - testConnPtr privconn = conn->privateData; - virDomainPtr ret = NULL; - virDomainDefPtr def; - virDomainObjPtr dom = NULL; - virDomainEventPtr event = NULL; - - testDriverLock(privconn); - if ((def = virDomainDefParseString(conn, privconn->caps, xml, - VIR_DOMAIN_XML_INACTIVE)) == NULL) - goto cleanup; - - if (testDomainGenerateIfnames(conn, def) < 0) - goto cleanup; - if (!(dom = virDomainAssignDef(conn, &privconn->domains, def))) - goto cleanup; - def = NULL; - dom->state = VIR_DOMAIN_RUNNING; - dom->def->id = privconn->nextDomID++; - - event = virDomainEventNewFromObj(dom, - VIR_DOMAIN_EVENT_STARTED, - VIR_DOMAIN_EVENT_STARTED_BOOTED); - - ret = virGetDomain(conn, dom->def->name, dom->def->uuid); - if (ret) - ret->id = dom->def->id; - -cleanup: - if (dom) - virDomainObjUnlock(dom); - if (event) - testDomainEventQueue(privconn, event); - if (def) - virDomainDefFree(def); - testDriverUnlock(privconn); - return ret; -} - - -static virDomainPtr testLookupDomainByID(virConnectPtr conn, - int id) -{ - testConnPtr privconn = conn->privateData; - virDomainPtr ret = NULL; - virDomainObjPtr dom; - - testDriverLock(privconn); - dom = virDomainFindByID(&privconn->domains, id); - testDriverUnlock(privconn); - - if (dom == NULL) { - testError (conn, VIR_ERR_NO_DOMAIN, NULL); - goto cleanup; - } - - ret = virGetDomain(conn, dom->def->name, dom->def->uuid); - if (ret) - ret->id = dom->def->id; - -cleanup: - if (dom) - virDomainObjUnlock(dom); - return ret; -} - -static virDomainPtr testLookupDomainByUUID(virConnectPtr conn, - const unsigned char *uuid) -{ - testConnPtr privconn = conn->privateData; - virDomainPtr ret = NULL; - virDomainObjPtr dom ; - - testDriverLock(privconn); - dom = virDomainFindByUUID(&privconn->domains, uuid); - testDriverUnlock(privconn); - - if (dom == NULL) { - testError (conn, VIR_ERR_NO_DOMAIN, NULL); - goto cleanup; - } - - ret = virGetDomain(conn, dom->def->name, dom->def->uuid); - if (ret) - ret->id = dom->def->id; - -cleanup: - if (dom) - virDomainObjUnlock(dom); - return ret; -} - -static virDomainPtr testLookupDomainByName(virConnectPtr conn, - const char *name) -{ - testConnPtr privconn = conn->privateData; - virDomainPtr ret = NULL; - virDomainObjPtr dom; - - testDriverLock(privconn); - dom = virDomainFindByName(&privconn->domains, name); - testDriverUnlock(privconn); - - if (dom == NULL) { - testError (conn, VIR_ERR_NO_DOMAIN, NULL); - goto cleanup; - } - - ret = virGetDomain(conn, dom->def->name, dom->def->uuid); - if (ret) - ret->id = dom->def->id; - -cleanup: - if (dom) - virDomainObjUnlock(dom); - return ret; -} - -static int testListDomains (virConnectPtr conn, - int *ids, - int maxids) -{ - testConnPtr privconn = conn->privateData; - unsigned int n = 0, i; - - testDriverLock(privconn); - for (i = 0 ; i < privconn->domains.count && n < maxids ; i++) { - virDomainObjLock(privconn->domains.objs[i]); - if (virDomainIsActive(privconn->domains.objs[i])) - ids[n++] = privconn->domains.objs[i]->def->id; - virDomainObjUnlock(privconn->domains.objs[i]); - } - testDriverUnlock(privconn); - - return n; -} - -static int testDestroyDomain (virDomainPtr domain) -{ - testConnPtr privconn = domain->conn->privateData; - virDomainObjPtr privdom; - virDomainEventPtr event = NULL; - int ret = -1; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - privdom->state = VIR_DOMAIN_SHUTOFF; - privdom->def->id = -1; - domain->id = -1; - event = virDomainEventNewFromObj(privdom, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_DESTROYED); - if (!privdom->persistent) { - virDomainRemoveInactive(&privconn->domains, - privdom); - privdom = NULL; - } - - - ret = 0; -cleanup: - if (privdom) - virDomainObjUnlock(privdom); - if (event) - testDomainEventQueue(privconn, event); - testDriverUnlock(privconn); - return ret; -} - -static int testResumeDomain (virDomainPtr domain) -{ - testConnPtr privconn = domain->conn->privateData; - virDomainObjPtr privdom; - virDomainEventPtr event = NULL; - int ret = -1; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - testDriverUnlock(privconn); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (privdom->state != VIR_DOMAIN_PAUSED) { - testError(domain->conn, - VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"), - domain->name); - goto cleanup; - } - - privdom->state = VIR_DOMAIN_RUNNING; - event = virDomainEventNewFromObj(privdom, - VIR_DOMAIN_EVENT_RESUMED, - VIR_DOMAIN_EVENT_RESUMED_UNPAUSED); - ret = 0; - -cleanup: - if (privdom) - virDomainObjUnlock(privdom); - if (event) { - testDriverLock(privconn); - testDomainEventQueue(privconn, event); - testDriverUnlock(privconn); - } - return ret; -} - -static int testPauseDomain (virDomainPtr domain) -{ - testConnPtr privconn = domain->conn->privateData; - virDomainObjPtr privdom; - virDomainEventPtr event = NULL; - int ret = -1; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - testDriverUnlock(privconn); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (privdom->state == VIR_DOMAIN_SHUTOFF || - privdom->state == VIR_DOMAIN_PAUSED) { - testError(domain->conn, - VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"), - domain->name); - goto cleanup; - } - - privdom->state = VIR_DOMAIN_PAUSED; - event = virDomainEventNewFromObj(privdom, - VIR_DOMAIN_EVENT_SUSPENDED, - VIR_DOMAIN_EVENT_SUSPENDED_PAUSED); - ret = 0; - -cleanup: - if (privdom) - virDomainObjUnlock(privdom); - - if (event) { - testDriverLock(privconn); - testDomainEventQueue(privconn, event); - testDriverUnlock(privconn); - } - return ret; -} - -static int testShutdownDomain (virDomainPtr domain) -{ - testConnPtr privconn = domain->conn->privateData; - virDomainObjPtr privdom; - virDomainEventPtr event = NULL; - int ret = -1; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (privdom->state == VIR_DOMAIN_SHUTOFF) { - testError(domain->conn, VIR_ERR_INTERNAL_ERROR, - _("domain '%s' not running"), domain->name); - goto cleanup; - } - - privdom->state = VIR_DOMAIN_SHUTOFF; - domain->id = -1; - privdom->def->id = -1; - event = virDomainEventNewFromObj(privdom, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); - if (!privdom->persistent) { - virDomainRemoveInactive(&privconn->domains, - privdom); - privdom = NULL; - } - ret = 0; - -cleanup: - if (privdom) - virDomainObjUnlock(privdom); - if (event) - testDomainEventQueue(privconn, event); - testDriverUnlock(privconn); - return ret; -} - -/* Similar behaviour as shutdown */ -static int testRebootDomain (virDomainPtr domain, - unsigned int action ATTRIBUTE_UNUSED) -{ - testConnPtr privconn = domain->conn->privateData; - virDomainObjPtr privdom; - virDomainEventPtr event = NULL; - int ret = -1; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - privdom->state = VIR_DOMAIN_SHUTDOWN; - switch (privdom->def->onReboot) { - case VIR_DOMAIN_LIFECYCLE_DESTROY: - privdom->state = VIR_DOMAIN_SHUTOFF; - domain->id = -1; - privdom->def->id = -1; - break; - - case VIR_DOMAIN_LIFECYCLE_RESTART: - privdom->state = VIR_DOMAIN_RUNNING; - break; - - case VIR_DOMAIN_LIFECYCLE_PRESERVE: - privdom->state = VIR_DOMAIN_SHUTOFF; - domain->id = -1; - privdom->def->id = -1; - break; - - case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME: - privdom->state = VIR_DOMAIN_RUNNING; - break; - - default: - privdom->state = VIR_DOMAIN_SHUTOFF; - domain->id = -1; - privdom->def->id = -1; - break; - } - - if (privdom->state == VIR_DOMAIN_SHUTOFF) { - event = virDomainEventNewFromObj(privdom, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); - if (!privdom->persistent) { - virDomainRemoveInactive(&privconn->domains, - privdom); - privdom = NULL; - } - } - - ret = 0; - -cleanup: - if (privdom) - virDomainObjUnlock(privdom); - if (event) - testDomainEventQueue(privconn, event); - testDriverUnlock(privconn); - return ret; -} - -static int testGetDomainInfo (virDomainPtr domain, - virDomainInfoPtr info) -{ - testConnPtr privconn = domain->conn->privateData; - struct timeval tv; - virDomainObjPtr privdom; - int ret = -1; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - testDriverUnlock(privconn); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (gettimeofday(&tv, NULL) < 0) { - testError(domain->conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("getting time of day")); - goto cleanup; - } - - info->state = privdom->state; - info->memory = privdom->def->memory; - info->maxMem = privdom->def->maxmem; - info->nrVirtCpu = privdom->def->vcpus; - info->cpuTime = ((tv.tv_sec * 1000ll * 1000ll * 1000ll) + (tv.tv_usec * 1000ll)); - ret = 0; - -cleanup: - if (privdom) - virDomainObjUnlock(privdom); - return ret; -} - -#define TEST_SAVE_MAGIC "TestGuestMagic" - -static int testDomainSave(virDomainPtr domain, - const char *path) -{ - testConnPtr privconn = domain->conn->privateData; - char *xml = NULL; - int fd = -1; - int len; - virDomainObjPtr privdom; - virDomainEventPtr event = NULL; - int ret = -1; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - xml = virDomainDefFormat(domain->conn, - privdom->def, - VIR_DOMAIN_XML_SECURE); - - if (xml == NULL) { - virReportSystemError(domain->conn, errno, - _("saving domain '%s' failed to allocate space for metadata"), - domain->name); - goto cleanup; - } - - if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) { - virReportSystemError(domain->conn, errno, - _("saving domain '%s' to '%s': open failed"), - domain->name, path); - goto cleanup; - } - len = strlen(xml); - if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) { - virReportSystemError(domain->conn, errno, - _("saving domain '%s' to '%s': write failed"), - domain->name, path); - goto cleanup; - } - if (safewrite(fd, (char*)&len, sizeof(len)) < 0) { - virReportSystemError(domain->conn, errno, - _("saving domain '%s' to '%s': write failed"), - domain->name, path); - goto cleanup; - } - if (safewrite(fd, xml, len) < 0) { - virReportSystemError(domain->conn, errno, - _("saving domain '%s' to '%s': write failed"), - domain->name, path); - goto cleanup; - } - - if (close(fd) < 0) { - virReportSystemError(domain->conn, errno, - _("saving domain '%s' to '%s': write failed"), - domain->name, path); - goto cleanup; - } - fd = -1; - - privdom->state = VIR_DOMAIN_SHUTOFF; - event = virDomainEventNewFromObj(privdom, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_SAVED); - if (!privdom->persistent) { - virDomainRemoveInactive(&privconn->domains, - privdom); - privdom = NULL; - } - ret = 0; - -cleanup: - VIR_FREE(xml); - - /* Don't report failure in close or unlink, because - * in either case we're already in a failure scenario - * and have reported a earlier error */ - if (ret != 0) { - if (fd != -1) - close(fd); - unlink(path); - } - if (privdom) - virDomainObjUnlock(privdom); - if (event) - testDomainEventQueue(privconn, event); - testDriverUnlock(privconn); - return ret; -} - -static int testDomainRestore(virConnectPtr conn, - const char *path) -{ - testConnPtr privconn = conn->privateData; - char *xml = NULL; - char magic[15]; - int fd = -1; - int len; - virDomainDefPtr def = NULL; - virDomainObjPtr dom = NULL; - virDomainEventPtr event = NULL; - int ret = -1; - - if ((fd = open(path, O_RDONLY)) < 0) { - virReportSystemError(conn, errno, - _("cannot read domain image '%s'"), - path); - goto cleanup; - } - if (saferead(fd, magic, sizeof(magic)) != sizeof(magic)) { - virReportSystemError(conn, errno, - _("incomplete save header in '%s'"), - path); - goto cleanup; - } - if (memcmp(magic, TEST_SAVE_MAGIC, sizeof(magic))) { - testError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("mismatched header magic")); - goto cleanup; - } - if (saferead(fd, (char*)&len, sizeof(len)) != sizeof(len)) { - virReportSystemError(conn, errno, - _("failed to read metadata length in '%s'"), - path); - goto cleanup; - } - if (len < 1 || len > 8192) { - testError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("length of metadata out of range")); - goto cleanup; - } - if (VIR_ALLOC_N(xml, len+1) < 0) { - virReportOOMError(conn); - goto cleanup; - } - if (saferead(fd, xml, len) != len) { - virReportSystemError(conn, errno, - _("incomplete metdata in '%s'"), path); - goto cleanup; - } - xml[len] = '\0'; - - testDriverLock(privconn); - def = virDomainDefParseString(conn, privconn->caps, xml, - VIR_DOMAIN_XML_INACTIVE); - if (!def) - goto cleanup; - - if (testDomainGenerateIfnames(conn, def) < 0) - goto cleanup; - if (!(dom = virDomainAssignDef(conn, &privconn->domains, def))) - goto cleanup; - def = NULL; - - dom->state = VIR_DOMAIN_RUNNING; - dom->def->id = privconn->nextDomID++; - event = virDomainEventNewFromObj(dom, - VIR_DOMAIN_EVENT_STARTED, - VIR_DOMAIN_EVENT_STARTED_RESTORED); - ret = 0; - -cleanup: - virDomainDefFree(def); - VIR_FREE(xml); - if (fd != -1) - close(fd); - if (dom) - virDomainObjUnlock(dom); - if (event) - testDomainEventQueue(privconn, event); - testDriverUnlock(privconn); - return ret; -} - -static int testDomainCoreDump(virDomainPtr domain, - const char *to, - int flags ATTRIBUTE_UNUSED) -{ - testConnPtr privconn = domain->conn->privateData; - int fd = -1; - virDomainObjPtr privdom; - virDomainEventPtr event = NULL; - int ret = -1; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) { - virReportSystemError(domain->conn, errno, - _("domain '%s' coredump: failed to open %s"), - domain->name, to); - goto cleanup; - } - if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) { - virReportSystemError(domain->conn, errno, - _("domain '%s' coredump: failed to write header to %s"), - domain->name, to); - goto cleanup; - } - if (close(fd) < 0) { - virReportSystemError(domain->conn, errno, - _("domain '%s' coredump: write failed: %s"), - domain->name, to); - goto cleanup; - } - privdom->state = VIR_DOMAIN_SHUTOFF; - event = virDomainEventNewFromObj(privdom, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_CRASHED); - if (!privdom->persistent) { - virDomainRemoveInactive(&privconn->domains, - privdom); - privdom = NULL; - } - ret = 0; - -cleanup: - if (fd != -1) - close(fd); - if (privdom) - virDomainObjUnlock(privdom); - if (event) - testDomainEventQueue(privconn, event); - testDriverUnlock(privconn); - return ret; -} - -static char *testGetOSType(virDomainPtr dom) { - char *ret = strdup("linux"); - if (!ret) - virReportOOMError(dom->conn); - return ret; -} - -static unsigned long testGetMaxMemory(virDomainPtr domain) { - testConnPtr privconn = domain->conn->privateData; - virDomainObjPtr privdom; - unsigned long ret = 0; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - testDriverUnlock(privconn); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - ret = privdom->def->maxmem; - -cleanup: - if (privdom) - virDomainObjUnlock(privdom); - return ret; -} - -static int testSetMaxMemory(virDomainPtr domain, - unsigned long memory) -{ - testConnPtr privconn = domain->conn->privateData; - virDomainObjPtr privdom; - int ret = -1; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - testDriverUnlock(privconn); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - /* XXX validate not over host memory wrt to other domains */ - privdom->def->maxmem = memory; - ret = 0; - -cleanup: - if (privdom) - virDomainObjUnlock(privdom); - return ret; -} - -static int testSetMemory(virDomainPtr domain, - unsigned long memory) -{ - testConnPtr privconn = domain->conn->privateData; - virDomainObjPtr privdom; - int ret = -1; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - testDriverUnlock(privconn); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (memory > privdom->def->maxmem) { - testError(domain->conn, - VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - privdom->def->memory = memory; - ret = 0; - -cleanup: - if (privdom) - virDomainObjUnlock(privdom); - return ret; -} - -static int testSetVcpus(virDomainPtr domain, - unsigned int nrCpus) { - testConnPtr privconn = domain->conn->privateData; - virDomainObjPtr privdom; - int ret = -1; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - testDriverUnlock(privconn); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - /* We allow more cpus in guest than host */ - if (nrCpus > 32) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - privdom->def->vcpus = nrCpus; - ret = 0; - -cleanup: - if (privdom) - virDomainObjUnlock(privdom); - return ret; -} - -static char *testDomainDumpXML(virDomainPtr domain, int flags) -{ - testConnPtr privconn = domain->conn->privateData; - virDomainDefPtr def; - virDomainObjPtr privdom; - char *ret = NULL; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - testDriverUnlock(privconn); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - def = (flags & VIR_DOMAIN_XML_INACTIVE) && - privdom->newDef ? privdom->newDef : privdom->def; - - ret = virDomainDefFormat(domain->conn, - def, - flags); - -cleanup: - if (privdom) - virDomainObjUnlock(privdom); - return ret; -} - -static int testNumOfDefinedDomains(virConnectPtr conn) { - testConnPtr privconn = conn->privateData; - unsigned int numInactive = 0, i; - - testDriverLock(privconn); - for (i = 0 ; i < privconn->domains.count ; i++) { - virDomainObjLock(privconn->domains.objs[i]); - if (!virDomainIsActive(privconn->domains.objs[i])) - numInactive++; - virDomainObjUnlock(privconn->domains.objs[i]); - } - testDriverUnlock(privconn); - - return numInactive; -} - -static int testListDefinedDomains(virConnectPtr conn, - char **const names, - int maxnames) { - testConnPtr privconn = conn->privateData; - unsigned int n = 0, i; - - testDriverLock(privconn); - memset(names, 0, sizeof(*names)*maxnames); - for (i = 0 ; i < privconn->domains.count && n < maxnames ; i++) { - virDomainObjLock(privconn->domains.objs[i]); - if (!virDomainIsActive(privconn->domains.objs[i]) && - !(names[n++] = strdup(privconn->domains.objs[i]->def->name))) { - virDomainObjUnlock(privconn->domains.objs[i]); - goto no_memory; - } - virDomainObjUnlock(privconn->domains.objs[i]); - } - testDriverUnlock(privconn); - - return n; - -no_memory: - virReportOOMError(conn); - for (n = 0 ; n < maxnames ; n++) - VIR_FREE(names[n]); - testDriverUnlock(privconn); - return -1; -} - -static virDomainPtr testDomainDefineXML(virConnectPtr conn, - const char *xml) { - testConnPtr privconn = conn->privateData; - virDomainPtr ret = NULL; - virDomainDefPtr def; - virDomainObjPtr dom = NULL; - virDomainEventPtr event = NULL; - - testDriverLock(privconn); - if ((def = virDomainDefParseString(conn, privconn->caps, xml, - VIR_DOMAIN_XML_INACTIVE)) == NULL) - goto cleanup; - - if (testDomainGenerateIfnames(conn, def) < 0) - goto cleanup; - if (!(dom = virDomainAssignDef(conn, &privconn->domains, def))) - goto cleanup; - def = NULL; - dom->persistent = 1; - - event = virDomainEventNewFromObj(dom, - VIR_DOMAIN_EVENT_DEFINED, - VIR_DOMAIN_EVENT_DEFINED_ADDED); - - ret = virGetDomain(conn, dom->def->name, dom->def->uuid); - if (ret) - ret->id = dom->def->id; - -cleanup: - virDomainDefFree(def); - if (dom) - virDomainObjUnlock(dom); - if (event) - testDomainEventQueue(privconn, event); - testDriverUnlock(privconn); - return ret; -} - -static int testNodeGetCellsFreeMemory(virConnectPtr conn, - unsigned long long *freemems, - int startCell, int maxCells) { - testConnPtr privconn = conn->privateData; - int i, j; - int ret = -1; - - testDriverLock(privconn); - if (startCell > privconn->numCells) { - testError(conn, VIR_ERR_INVALID_ARG, - "%s", _("Range exceeds available cells")); - goto cleanup; - } - - for (i = startCell, j = 0; - (i < privconn->numCells && j < maxCells) ; - ++i, ++j) { - freemems[j] = privconn->cells[i].mem; - } - ret = j; - -cleanup: - testDriverUnlock(privconn); - return ret; -} - - -static int testDomainCreate(virDomainPtr domain) { - testConnPtr privconn = domain->conn->privateData; - virDomainObjPtr privdom; - virDomainEventPtr event = NULL; - int ret = -1; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (privdom->state != VIR_DOMAIN_SHUTOFF) { - testError(domain->conn, VIR_ERR_INTERNAL_ERROR, - _("Domain '%s' is already running"), domain->name); - goto cleanup; - } - - domain->id = privdom->def->id = privconn->nextDomID++; - privdom->state = VIR_DOMAIN_RUNNING; - event = virDomainEventNewFromObj(privdom, - VIR_DOMAIN_EVENT_STARTED, - VIR_DOMAIN_EVENT_STARTED_BOOTED); - ret = 0; - -cleanup: - if (privdom) - virDomainObjUnlock(privdom); - if (event) - testDomainEventQueue(privconn, event); - testDriverUnlock(privconn); - return ret; -} - -static int testDomainUndefine(virDomainPtr domain) { - testConnPtr privconn = domain->conn->privateData; - virDomainObjPtr privdom; - virDomainEventPtr event = NULL; - int ret = -1; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (privdom->state != VIR_DOMAIN_SHUTOFF) { - testError(domain->conn, VIR_ERR_INTERNAL_ERROR, - _("Domain '%s' is still running"), domain->name); - goto cleanup; - } - - privdom->state = VIR_DOMAIN_SHUTOFF; - event = virDomainEventNewFromObj(privdom, - VIR_DOMAIN_EVENT_UNDEFINED, - VIR_DOMAIN_EVENT_UNDEFINED_REMOVED); - virDomainRemoveInactive(&privconn->domains, - privdom); - privdom = NULL; - ret = 0; - -cleanup: - if (privdom) - virDomainObjUnlock(privdom); - if (event) - testDomainEventQueue(privconn, event); - testDriverUnlock(privconn); - return ret; -} - -static int testDomainGetAutostart(virDomainPtr domain, - int *autostart) -{ - testConnPtr privconn = domain->conn->privateData; - virDomainObjPtr privdom; - int ret = -1; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - testDriverUnlock(privconn); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - *autostart = privdom->autostart; - ret = 0; - -cleanup: - if (privdom) - virDomainObjUnlock(privdom); - return ret; -} - - -static int testDomainSetAutostart(virDomainPtr domain, - int autostart) -{ - testConnPtr privconn = domain->conn->privateData; - virDomainObjPtr privdom; - int ret = -1; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - testDriverUnlock(privconn); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - privdom->autostart = autostart ? 1 : 0; - ret = 0; - -cleanup: - if (privdom) - virDomainObjUnlock(privdom); - return ret; -} - -static char *testDomainGetSchedulerType(virDomainPtr domain, - int *nparams) -{ - char *type = NULL; - - *nparams = 1; - type = strdup("fair"); - if (!type) - virReportOOMError(domain->conn); - - return type; -} - -static int testDomainGetSchedulerParams(virDomainPtr domain, - virSchedParameterPtr params, - int *nparams) -{ - testConnPtr privconn = domain->conn->privateData; - virDomainObjPtr privdom; - int ret = -1; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - testDriverUnlock(privconn); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (*nparams != 1) { - testError(domain->conn, VIR_ERR_INVALID_ARG, "nparams"); - goto cleanup; - } - strcpy(params[0].field, "weight"); - params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT; - /* XXX */ - /*params[0].value.ui = privdom->weight;*/ - params[0].value.ui = 50; - ret = 0; - -cleanup: - if (privdom) - virDomainObjUnlock(privdom); - return ret; -} - - -static int testDomainSetSchedulerParams(virDomainPtr domain, - virSchedParameterPtr params, - int nparams) -{ - testConnPtr privconn = domain->conn->privateData; - virDomainObjPtr privdom; - int ret = -1; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - testDriverUnlock(privconn); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (nparams != 1) { - testError(domain->conn, VIR_ERR_INVALID_ARG, "nparams"); - goto cleanup; - } - if (STRNEQ(params[0].field, "weight")) { - testError(domain->conn, VIR_ERR_INVALID_ARG, "field"); - goto cleanup; - } - if (params[0].type != VIR_DOMAIN_SCHED_FIELD_UINT) { - testError(domain->conn, VIR_ERR_INVALID_ARG, "type"); - goto cleanup; - } - /* XXX */ - /*privdom->weight = params[0].value.ui;*/ - ret = 0; - -cleanup: - if (privdom) - virDomainObjUnlock(privdom); - return ret; -} - -static int testDomainBlockStats(virDomainPtr domain, - const char *path, - struct _virDomainBlockStats *stats) -{ - testConnPtr privconn = domain->conn->privateData; - virDomainObjPtr privdom; - struct timeval tv; - unsigned long long statbase; - int i, found = 0, ret = -1; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - testDriverUnlock(privconn); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto error; - } - - for (i = 0 ; i < privdom->def->ndisks ; i++) { - if (STREQ(path, privdom->def->disks[i]->dst)) { - found = 1; - break; - } - } - - if (!found) { - testError(domain->conn, VIR_ERR_INVALID_ARG, - _("invalid path: %s"), path); - goto error; - } - - if (gettimeofday(&tv, NULL) < 0) { - virReportSystemError(domain->conn, errno, - "%s", _("getting time of day")); - goto error; - } - - /* No significance to these numbers, just enough to mix it up*/ - statbase = (tv.tv_sec * 1000UL * 1000UL) + tv.tv_usec; - stats->rd_req = statbase / 10; - stats->rd_bytes = statbase / 20; - stats->wr_req = statbase / 30; - stats->wr_bytes = statbase / 40; - stats->errs = tv.tv_sec / 2; - - ret = 0; -error: - if (privdom) - virDomainObjUnlock(privdom); - return ret; -} - -static int testDomainInterfaceStats(virDomainPtr domain, - const char *path, - struct _virDomainInterfaceStats *stats) -{ - testConnPtr privconn = domain->conn->privateData; - virDomainObjPtr privdom; - struct timeval tv; - unsigned long long statbase; - int i, found = 0, ret = -1; - - testDriverLock(privconn); - privdom = virDomainFindByName(&privconn->domains, - domain->name); - testDriverUnlock(privconn); - - if (privdom == NULL) { - testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto error; - } - - for (i = 0 ; i < privdom->def->nnets ; i++) { - if (privdom->def->nets[i]->ifname && - STREQ (privdom->def->nets[i]->ifname, path)) { - found = 1; - break; - } - } - - if (!found) { - testError(domain->conn, VIR_ERR_INVALID_ARG, - _("invalid path, '%s' is not a known interface"), path); - goto error; - } - - if (gettimeofday(&tv, NULL) < 0) { - virReportSystemError(domain->conn, errno, - "%s", _("getting time of day")); - goto error; - } - - /* No significance to these numbers, just enough to mix it up*/ - statbase = (tv.tv_sec * 1000UL * 1000UL) + tv.tv_usec; - stats->rx_bytes = statbase / 10; - stats->rx_packets = statbase / 100; - stats->rx_errs = tv.tv_sec / 1; - stats->rx_drop = tv.tv_sec / 2; - stats->tx_bytes = statbase / 20; - stats->tx_packets = statbase / 110; - stats->tx_errs = tv.tv_sec / 3; - stats->tx_drop = tv.tv_sec / 4; - - ret = 0; -error: - if (privdom) - virDomainObjUnlock(privdom); - return ret; -} - -static virDrvOpenStatus testOpenNetwork(virConnectPtr conn, - virConnectAuthPtr auth ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED) { - if (STRNEQ(conn->driver->name, "Test")) - return VIR_DRV_OPEN_DECLINED; - - conn->networkPrivateData = conn->privateData; - return VIR_DRV_OPEN_SUCCESS; -} - -static int testCloseNetwork(virConnectPtr conn) { - conn->networkPrivateData = NULL; - return 0; -} - - -static virNetworkPtr testLookupNetworkByUUID(virConnectPtr conn, - const unsigned char *uuid) -{ - testConnPtr privconn = conn->privateData; - virNetworkObjPtr net; - virNetworkPtr ret = NULL; - - testDriverLock(privconn); - net = virNetworkFindByUUID(&privconn->networks, uuid); - testDriverUnlock(privconn); - - if (net == NULL) { - testError (conn, VIR_ERR_NO_NETWORK, NULL); - goto cleanup; - } - - ret = virGetNetwork(conn, net->def->name, net->def->uuid); - -cleanup: - if (net) - virNetworkObjUnlock(net); - return ret; -} - -static virNetworkPtr testLookupNetworkByName(virConnectPtr conn, - const char *name) -{ - testConnPtr privconn = conn->privateData; - virNetworkObjPtr net; - virNetworkPtr ret = NULL; - - testDriverLock(privconn); - net = virNetworkFindByName(&privconn->networks, name); - testDriverUnlock(privconn); - - if (net == NULL) { - testError (conn, VIR_ERR_NO_NETWORK, NULL); - goto cleanup; - } - - ret = virGetNetwork(conn, net->def->name, net->def->uuid); - -cleanup: - if (net) - virNetworkObjUnlock(net); - return ret; -} - - -static int testNumNetworks(virConnectPtr conn) { - testConnPtr privconn = conn->privateData; - int numActive = 0, i; - - testDriverLock(privconn); - for (i = 0 ; i < privconn->networks.count ; i++) { - virNetworkObjLock(privconn->networks.objs[i]); - if (virNetworkIsActive(privconn->networks.objs[i])) - numActive++; - virNetworkObjUnlock(privconn->networks.objs[i]); - } - testDriverUnlock(privconn); - - return numActive; -} - -static int testListNetworks(virConnectPtr conn, char **const names, int nnames) { - testConnPtr privconn = conn->privateData; - int n = 0, i; - - testDriverLock(privconn); - memset(names, 0, sizeof(*names)*nnames); - for (i = 0 ; i < privconn->networks.count && n < nnames ; i++) { - virNetworkObjLock(privconn->networks.objs[i]); - if (virNetworkIsActive(privconn->networks.objs[i]) && - !(names[n++] = strdup(privconn->networks.objs[i]->def->name))) { - virNetworkObjUnlock(privconn->networks.objs[i]); - goto no_memory; - } - virNetworkObjUnlock(privconn->networks.objs[i]); - } - testDriverUnlock(privconn); - - return n; - -no_memory: - virReportOOMError(conn); - for (n = 0 ; n < nnames ; n++) - VIR_FREE(names[n]); - testDriverUnlock(privconn); - return -1; -} - -static int testNumDefinedNetworks(virConnectPtr conn) { - testConnPtr privconn = conn->privateData; - int numInactive = 0, i; - - testDriverLock(privconn); - for (i = 0 ; i < privconn->networks.count ; i++) { - virNetworkObjLock(privconn->networks.objs[i]); - if (!virNetworkIsActive(privconn->networks.objs[i])) - numInactive++; - virNetworkObjUnlock(privconn->networks.objs[i]); - } - testDriverUnlock(privconn); - - return numInactive; -} - -static int testListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) { - testConnPtr privconn = conn->privateData; - int n = 0, i; - - testDriverLock(privconn); - memset(names, 0, sizeof(*names)*nnames); - for (i = 0 ; i < privconn->networks.count && n < nnames ; i++) { - virNetworkObjLock(privconn->networks.objs[i]); - if (!virNetworkIsActive(privconn->networks.objs[i]) && - !(names[n++] = strdup(privconn->networks.objs[i]->def->name))) { - virNetworkObjUnlock(privconn->networks.objs[i]); - goto no_memory; - } - virNetworkObjUnlock(privconn->networks.objs[i]); - } - testDriverUnlock(privconn); - - return n; - -no_memory: - virReportOOMError(conn); - for (n = 0 ; n < nnames ; n++) - VIR_FREE(names[n]); - testDriverUnlock(privconn); - return -1; -} - -static virNetworkPtr testNetworkCreate(virConnectPtr conn, const char *xml) { - testConnPtr privconn = conn->privateData; - virNetworkDefPtr def; - virNetworkObjPtr net = NULL; - virNetworkPtr ret = NULL; - - testDriverLock(privconn); - if ((def = virNetworkDefParseString(conn, xml)) == NULL) - goto cleanup; - - if ((net = virNetworkAssignDef(conn, &privconn->networks, def)) == NULL) - goto cleanup; - def = NULL; - net->active = 1; - - ret = virGetNetwork(conn, net->def->name, net->def->uuid); - -cleanup: - virNetworkDefFree(def); - if (net) - virNetworkObjUnlock(net); - testDriverUnlock(privconn); - return ret; -} - -static virNetworkPtr testNetworkDefine(virConnectPtr conn, const char *xml) { - testConnPtr privconn = conn->privateData; - virNetworkDefPtr def; - virNetworkObjPtr net = NULL; - virNetworkPtr ret = NULL; - - testDriverLock(privconn); - if ((def = virNetworkDefParseString(conn, xml)) == NULL) - goto cleanup; - - if ((net = virNetworkAssignDef(conn, &privconn->networks, def)) == NULL) - goto cleanup; - def = NULL; - net->persistent = 1; - - ret = virGetNetwork(conn, net->def->name, net->def->uuid); - -cleanup: - virNetworkDefFree(def); - if (net) - virNetworkObjUnlock(net); - testDriverUnlock(privconn); - return ret; -} - -static int testNetworkUndefine(virNetworkPtr network) { - testConnPtr privconn = network->conn->privateData; - virNetworkObjPtr privnet; - int ret = -1; - - testDriverLock(privconn); - privnet = virNetworkFindByName(&privconn->networks, - network->name); - - if (privnet == NULL) { - testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (virNetworkIsActive(privnet)) { - testError(network->conn, VIR_ERR_INTERNAL_ERROR, - _("Network '%s' is still running"), network->name); - goto cleanup; - } - - virNetworkRemoveInactive(&privconn->networks, - privnet); - privnet = NULL; - ret = 0; - -cleanup: - if (privnet) - virNetworkObjUnlock(privnet); - testDriverUnlock(privconn); - return ret; -} - -static int testNetworkStart(virNetworkPtr network) { - testConnPtr privconn = network->conn->privateData; - virNetworkObjPtr privnet; - int ret = -1; - - testDriverLock(privconn); - privnet = virNetworkFindByName(&privconn->networks, - network->name); - testDriverUnlock(privconn); - - if (privnet == NULL) { - testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (virNetworkIsActive(privnet)) { - testError(network->conn, VIR_ERR_INTERNAL_ERROR, - _("Network '%s' is already running"), network->name); - goto cleanup; - } - - privnet->active = 1; - ret = 0; - -cleanup: - if (privnet) - virNetworkObjUnlock(privnet); - return ret; -} - -static int testNetworkDestroy(virNetworkPtr network) { - testConnPtr privconn = network->conn->privateData; - virNetworkObjPtr privnet; - int ret = -1; - - testDriverLock(privconn); - privnet = virNetworkFindByName(&privconn->networks, - network->name); - - if (privnet == NULL) { - testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - privnet->active = 0; - if (!privnet->persistent) { - virNetworkRemoveInactive(&privconn->networks, - privnet); - privnet = NULL; - } - ret = 0; - -cleanup: - if (privnet) - virNetworkObjUnlock(privnet); - testDriverUnlock(privconn); - return ret; -} - -static char *testNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) { - testConnPtr privconn = network->conn->privateData; - virNetworkObjPtr privnet; - char *ret = NULL; - - testDriverLock(privconn); - privnet = virNetworkFindByName(&privconn->networks, - network->name); - testDriverUnlock(privconn); - - if (privnet == NULL) { - testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - ret = virNetworkDefFormat(network->conn, privnet->def); - -cleanup: - if (privnet) - virNetworkObjUnlock(privnet); - return ret; -} - -static char *testNetworkGetBridgeName(virNetworkPtr network) { - testConnPtr privconn = network->conn->privateData; - char *bridge = NULL; - virNetworkObjPtr privnet; - - testDriverLock(privconn); - privnet = virNetworkFindByName(&privconn->networks, - network->name); - testDriverUnlock(privconn); - - if (privnet == NULL) { - testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (privnet->def->bridge && - !(bridge = strdup(privnet->def->bridge))) { - virReportOOMError(network->conn); - goto cleanup; - } - -cleanup: - if (privnet) - virNetworkObjUnlock(privnet); - return bridge; -} - -static int testNetworkGetAutostart(virNetworkPtr network, - int *autostart) { - testConnPtr privconn = network->conn->privateData; - virNetworkObjPtr privnet; - int ret = -1; - - testDriverLock(privconn); - privnet = virNetworkFindByName(&privconn->networks, - network->name); - testDriverUnlock(privconn); - - if (privnet == NULL) { - testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - *autostart = privnet->autostart; - ret = 0; - -cleanup: - if (privnet) - virNetworkObjUnlock(privnet); - return ret; -} - -static int testNetworkSetAutostart(virNetworkPtr network, - int autostart) { - testConnPtr privconn = network->conn->privateData; - virNetworkObjPtr privnet; - int ret = -1; - - testDriverLock(privconn); - privnet = virNetworkFindByName(&privconn->networks, - network->name); - testDriverUnlock(privconn); - - if (privnet == NULL) { - testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - privnet->autostart = autostart ? 1 : 0; - ret = 0; - -cleanup: - if (privnet) - virNetworkObjUnlock(privnet); - return ret; -} - - -/* - * Physical host interface routines - */ - -static virDrvOpenStatus testOpenInterface(virConnectPtr conn, - virConnectAuthPtr auth ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED) -{ - if (STRNEQ(conn->driver->name, "Test")) - return VIR_DRV_OPEN_DECLINED; - - conn->interfacePrivateData = conn->privateData; - return VIR_DRV_OPEN_SUCCESS; -} - -static int testCloseInterface(virConnectPtr conn) -{ - conn->interfacePrivateData = NULL; - return 0; -} - - -static int testNumOfInterfaces(virConnectPtr conn) -{ - testConnPtr privconn = conn->privateData; - int i, count = 0; - - testDriverLock(privconn); - for (i = 0 ; (i < privconn->ifaces.count); i++) { - virInterfaceObjLock(privconn->ifaces.objs[i]); - if (virInterfaceIsActive(privconn->ifaces.objs[i])) { - count++; - } - virInterfaceObjUnlock(privconn->ifaces.objs[i]); - } - testDriverUnlock(privconn); - return count; -} - -static int testListInterfaces(virConnectPtr conn, char **const names, int nnames) -{ - testConnPtr privconn = conn->privateData; - int n = 0, i; - - testDriverLock(privconn); - memset(names, 0, sizeof(*names)*nnames); - for (i = 0 ; (i < privconn->ifaces.count) && (n < nnames); i++) { - virInterfaceObjLock(privconn->ifaces.objs[i]); - if (virInterfaceIsActive(privconn->ifaces.objs[i])) { - if (!(names[n++] = strdup(privconn->ifaces.objs[i]->def->name))) { - virInterfaceObjUnlock(privconn->ifaces.objs[i]); - goto no_memory; - } - } - virInterfaceObjUnlock(privconn->ifaces.objs[i]); - } - testDriverUnlock(privconn); - - return n; - -no_memory: - virReportOOMError(conn); - for (n = 0 ; n < nnames ; n++) - VIR_FREE(names[n]); - testDriverUnlock(privconn); - return -1; -} - -static int testNumOfDefinedInterfaces(virConnectPtr conn) -{ - testConnPtr privconn = conn->privateData; - int i, count = 0; - - testDriverLock(privconn); - for (i = 0 ; i < privconn->ifaces.count; i++) { - virInterfaceObjLock(privconn->ifaces.objs[i]); - if (!virInterfaceIsActive(privconn->ifaces.objs[i])) { - count++; - } - virInterfaceObjUnlock(privconn->ifaces.objs[i]); - } - testDriverUnlock(privconn); - return count; -} - -static int testListDefinedInterfaces(virConnectPtr conn, char **const names, int nnames) -{ - testConnPtr privconn = conn->privateData; - int n = 0, i; - - testDriverLock(privconn); - memset(names, 0, sizeof(*names)*nnames); - for (i = 0 ; (i < privconn->ifaces.count) && (n < nnames); i++) { - virInterfaceObjLock(privconn->ifaces.objs[i]); - if (!virInterfaceIsActive(privconn->ifaces.objs[i])) { - if (!(names[n++] = strdup(privconn->ifaces.objs[i]->def->name))) { - virInterfaceObjUnlock(privconn->ifaces.objs[i]); - goto no_memory; - } - } - virInterfaceObjUnlock(privconn->ifaces.objs[i]); - } - testDriverUnlock(privconn); - - return n; - -no_memory: - virReportOOMError(conn); - for (n = 0 ; n < nnames ; n++) - VIR_FREE(names[n]); - testDriverUnlock(privconn); - return -1; -} - -static virInterfacePtr testLookupInterfaceByName(virConnectPtr conn, - const char *name) -{ - testConnPtr privconn = conn->privateData; - virInterfaceObjPtr iface; - virInterfacePtr ret = NULL; - - testDriverLock(privconn); - iface = virInterfaceFindByName(&privconn->ifaces, name); - testDriverUnlock(privconn); - - if (iface == NULL) { - testError (conn, VIR_ERR_NO_INTERFACE, NULL); - goto cleanup; - } - - ret = virGetInterface(conn, iface->def->name, iface->def->mac); - -cleanup: - if (iface) - virInterfaceObjUnlock(iface); - return ret; -} - -static virInterfacePtr testLookupInterfaceByMACString(virConnectPtr conn, - const char *mac) -{ - testConnPtr privconn = conn->privateData; - virInterfaceObjPtr iface; - int ifacect; - virInterfacePtr ret = NULL; - - testDriverLock(privconn); - ifacect = virInterfaceFindByMACString(&privconn->ifaces, mac, &iface, 1); - testDriverUnlock(privconn); - - if (ifacect == 0) { - testError (conn, VIR_ERR_NO_INTERFACE, NULL); - goto cleanup; - } - - if (ifacect > 1) { - testError (conn, VIR_ERR_MULTIPLE_INTERFACES, NULL); - goto cleanup; - } - - ret = virGetInterface(conn, iface->def->name, iface->def->mac); - -cleanup: - if (iface) - virInterfaceObjUnlock(iface); - return ret; -} - -static char *testInterfaceGetXMLDesc(virInterfacePtr iface, - unsigned int flags ATTRIBUTE_UNUSED) -{ - testConnPtr privconn = iface->conn->privateData; - virInterfaceObjPtr privinterface; - char *ret = NULL; - - testDriverLock(privconn); - privinterface = virInterfaceFindByName(&privconn->ifaces, - iface->name); - testDriverUnlock(privconn); - - if (privinterface == NULL) { - testError(iface->conn, VIR_ERR_NO_INTERFACE, __FUNCTION__); - goto cleanup; - } - - ret = virInterfaceDefFormat(iface->conn, privinterface->def); - -cleanup: - if (privinterface) - virInterfaceObjUnlock(privinterface); - return ret; -} - - -static virInterfacePtr testInterfaceDefineXML(virConnectPtr conn, const char *xmlStr, - unsigned int flags ATTRIBUTE_UNUSED) -{ - testConnPtr privconn = conn->privateData; - virInterfaceDefPtr def; - virInterfaceObjPtr iface = NULL; - virInterfacePtr ret = NULL; - - testDriverLock(privconn); - if ((def = virInterfaceDefParseString(conn, xmlStr)) == NULL) - goto cleanup; - - if ((iface = virInterfaceAssignDef(conn, &privconn->ifaces, def)) == NULL) - goto cleanup; - def = NULL; - - ret = virGetInterface(conn, iface->def->name, iface->def->mac); - -cleanup: - virInterfaceDefFree(def); - if (iface) - virInterfaceObjUnlock(iface); - testDriverUnlock(privconn); - return ret; -} - -static int testInterfaceUndefine(virInterfacePtr iface) -{ - testConnPtr privconn = iface->conn->privateData; - virInterfaceObjPtr privinterface; - int ret = -1; - - testDriverLock(privconn); - privinterface = virInterfaceFindByName(&privconn->ifaces, - iface->name); - - if (privinterface == NULL) { - testError (iface->conn, VIR_ERR_NO_INTERFACE, NULL); - goto cleanup; - } - - virInterfaceRemove(&privconn->ifaces, - privinterface); - ret = 0; - -cleanup: - testDriverUnlock(privconn); - return ret; -} - -static int testInterfaceCreate(virInterfacePtr iface, - unsigned int flags ATTRIBUTE_UNUSED) -{ - testConnPtr privconn = iface->conn->privateData; - virInterfaceObjPtr privinterface; - int ret = -1; - - testDriverLock(privconn); - privinterface = virInterfaceFindByName(&privconn->ifaces, - iface->name); - - if (privinterface == NULL) { - testError (iface->conn, VIR_ERR_NO_INTERFACE, NULL); - goto cleanup; - } - - if (privinterface->active != 0) { - testError (iface->conn, VIR_ERR_OPERATION_INVALID, NULL); - goto cleanup; - } - - privinterface->active = 1; - ret = 0; - -cleanup: - if (privinterface) - virInterfaceObjUnlock(privinterface); - testDriverUnlock(privconn); - return ret; -} - -static int testInterfaceDestroy(virInterfacePtr iface, - unsigned int flags ATTRIBUTE_UNUSED) -{ - testConnPtr privconn = iface->conn->privateData; - virInterfaceObjPtr privinterface; - int ret = -1; - - testDriverLock(privconn); - privinterface = virInterfaceFindByName(&privconn->ifaces, - iface->name); - - if (privinterface == NULL) { - testError (iface->conn, VIR_ERR_NO_INTERFACE, NULL); - goto cleanup; - } - - if (privinterface->active == 0) { - testError (iface->conn, VIR_ERR_OPERATION_INVALID, NULL); - goto cleanup; - } - - privinterface->active = 0; - ret = 0; - -cleanup: - if (privinterface) - virInterfaceObjUnlock(privinterface); - testDriverUnlock(privconn); - return ret; -} - - - -/* - * Storage Driver routines - */ - -static int testStoragePoolObjSetDefaults(virConnectPtr conn, - virStoragePoolObjPtr pool) { - - pool->def->capacity = defaultPoolCap; - pool->def->allocation = defaultPoolAlloc; - pool->def->available = defaultPoolCap - defaultPoolAlloc; - - pool->configFile = strdup("\0"); - if (!pool->configFile) { - virReportOOMError(conn); - return -1; - } - - return 0; -} - -static virDrvOpenStatus testStorageOpen(virConnectPtr conn, - virConnectAuthPtr auth ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED) { - if (STRNEQ(conn->driver->name, "Test")) - return VIR_DRV_OPEN_DECLINED; - - conn->storagePrivateData = conn->privateData; - return VIR_DRV_OPEN_SUCCESS; -} - -static int testStorageClose(virConnectPtr conn) { - conn->storagePrivateData = NULL; - return 0; -} - -static virStoragePoolPtr -testStoragePoolLookupByUUID(virConnectPtr conn, - const unsigned char *uuid) { - testConnPtr privconn = conn->privateData; - virStoragePoolObjPtr pool; - virStoragePoolPtr ret = NULL; - - testDriverLock(privconn); - pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid); - testDriverUnlock(privconn); - - if (pool == NULL) { - testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL); - goto cleanup; - } - - ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); - -cleanup: - if (pool) - virStoragePoolObjUnlock(pool); - return ret; -} - -static virStoragePoolPtr -testStoragePoolLookupByName(virConnectPtr conn, - const char *name) { - testConnPtr privconn = conn->privateData; - virStoragePoolObjPtr pool; - virStoragePoolPtr ret = NULL; - - testDriverLock(privconn); - pool = virStoragePoolObjFindByName(&privconn->pools, name); - testDriverUnlock(privconn); - - if (pool == NULL) { - testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL); - goto cleanup; - } - - ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); - -cleanup: - if (pool) - virStoragePoolObjUnlock(pool); - return ret; -} - -static virStoragePoolPtr -testStoragePoolLookupByVolume(virStorageVolPtr vol) { - return testStoragePoolLookupByName(vol->conn, vol->pool); -} - -static int -testStorageNumPools(virConnectPtr conn) { - testConnPtr privconn = conn->privateData; - int numActive = 0, i; - - testDriverLock(privconn); - for (i = 0 ; i < privconn->pools.count ; i++) - if (virStoragePoolObjIsActive(privconn->pools.objs[i])) - numActive++; - testDriverUnlock(privconn); - - return numActive; -} - -static int -testStorageListPools(virConnectPtr conn, - char **const names, - int nnames) { - testConnPtr privconn = conn->privateData; - int n = 0, i; - - testDriverLock(privconn); - memset(names, 0, sizeof(*names)*nnames); - for (i = 0 ; i < privconn->pools.count && n < nnames ; i++) { - virStoragePoolObjLock(privconn->pools.objs[i]); - if (virStoragePoolObjIsActive(privconn->pools.objs[i]) && - !(names[n++] = strdup(privconn->pools.objs[i]->def->name))) { - virStoragePoolObjUnlock(privconn->pools.objs[i]); - goto no_memory; - } - virStoragePoolObjUnlock(privconn->pools.objs[i]); - } - testDriverUnlock(privconn); - - return n; - -no_memory: - virReportOOMError(conn); - for (n = 0 ; n < nnames ; n++) - VIR_FREE(names[n]); - testDriverUnlock(privconn); - return -1; -} - -static int -testStorageNumDefinedPools(virConnectPtr conn) { - testConnPtr privconn = conn->privateData; - int numInactive = 0, i; - - testDriverLock(privconn); - for (i = 0 ; i < privconn->pools.count ; i++) { - virStoragePoolObjLock(privconn->pools.objs[i]); - if (!virStoragePoolObjIsActive(privconn->pools.objs[i])) - numInactive++; - virStoragePoolObjUnlock(privconn->pools.objs[i]); - } - testDriverUnlock(privconn); - - return numInactive; -} - -static int -testStorageListDefinedPools(virConnectPtr conn, - char **const names, - int nnames) { - testConnPtr privconn = conn->privateData; - int n = 0, i; - - testDriverLock(privconn); - memset(names, 0, sizeof(*names)*nnames); - for (i = 0 ; i < privconn->pools.count && n < nnames ; i++) { - virStoragePoolObjLock(privconn->pools.objs[i]); - if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) && - !(names[n++] = strdup(privconn->pools.objs[i]->def->name))) { - virStoragePoolObjUnlock(privconn->pools.objs[i]); - goto no_memory; - } - virStoragePoolObjUnlock(privconn->pools.objs[i]); - } - testDriverUnlock(privconn); - - return n; - -no_memory: - virReportOOMError(conn); - for (n = 0 ; n < nnames ; n++) - VIR_FREE(names[n]); - testDriverUnlock(privconn); - return -1; -} - - -static int -testStoragePoolStart(virStoragePoolPtr pool, - unsigned int flags ATTRIBUTE_UNUSED) { - testConnPtr privconn = pool->conn->privateData; - virStoragePoolObjPtr privpool; - int ret = -1; - - testDriverLock(privconn); - privpool = virStoragePoolObjFindByName(&privconn->pools, - pool->name); - testDriverUnlock(privconn); - - if (privpool == NULL) { - testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (virStoragePoolObjIsActive(privpool)) { - testError(pool->conn, VIR_ERR_INTERNAL_ERROR, - _("storage pool '%s' is already active"), pool->name); - goto cleanup; - } - - privpool->active = 1; - ret = 0; - -cleanup: - if (privpool) - virStoragePoolObjUnlock(privpool); - return ret; -} - -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) { - testConnPtr privconn = conn->privateData; - virStoragePoolDefPtr def; - virStoragePoolObjPtr pool = NULL; - virStoragePoolPtr ret = NULL; - - testDriverLock(privconn); - if (!(def = virStoragePoolDefParseString(conn, xml))) - goto cleanup; - - pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid); - if (!pool) - pool = virStoragePoolObjFindByName(&privconn->pools, def->name); - if (pool) { - testError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("storage pool already exists")); - goto cleanup; - } - - if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, def))) - goto cleanup; - def = NULL; - - if (testStoragePoolObjSetDefaults(conn, pool) == -1) { - virStoragePoolObjRemove(&privconn->pools, pool); - pool = NULL; - goto cleanup; - } - pool->active = 1; - - ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); - -cleanup: - virStoragePoolDefFree(def); - if (pool) - virStoragePoolObjUnlock(pool); - testDriverUnlock(privconn); - return ret; -} - -static virStoragePoolPtr -testStoragePoolDefine(virConnectPtr conn, - const char *xml, - unsigned int flags ATTRIBUTE_UNUSED) { - testConnPtr privconn = conn->privateData; - virStoragePoolDefPtr def; - virStoragePoolObjPtr pool = NULL; - virStoragePoolPtr ret = NULL; - - testDriverLock(privconn); - if (!(def = virStoragePoolDefParseString(conn, xml))) - goto cleanup; - - def->capacity = defaultPoolCap; - def->allocation = defaultPoolAlloc; - def->available = defaultPoolCap - defaultPoolAlloc; - - if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, def))) - goto cleanup; - def = NULL; - - if (testStoragePoolObjSetDefaults(conn, pool) == -1) { - virStoragePoolObjRemove(&privconn->pools, pool); - pool = NULL; - goto cleanup; - } - - ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); - -cleanup: - virStoragePoolDefFree(def); - if (pool) - virStoragePoolObjUnlock(pool); - testDriverUnlock(privconn); - return ret; -} - -static int -testStoragePoolUndefine(virStoragePoolPtr pool) { - testConnPtr privconn = pool->conn->privateData; - virStoragePoolObjPtr privpool; - int ret = -1; - - testDriverLock(privconn); - privpool = virStoragePoolObjFindByName(&privconn->pools, - pool->name); - - if (privpool == NULL) { - testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (virStoragePoolObjIsActive(privpool)) { - testError(pool->conn, VIR_ERR_INTERNAL_ERROR, - _("storage pool '%s' is already active"), pool->name); - goto cleanup; - } - - virStoragePoolObjRemove(&privconn->pools, privpool); - ret = 0; - -cleanup: - if (privpool) - virStoragePoolObjUnlock(privpool); - testDriverUnlock(privconn); - return ret; -} - -static int -testStoragePoolBuild(virStoragePoolPtr pool, - unsigned int flags ATTRIBUTE_UNUSED) { - testConnPtr privconn = pool->conn->privateData; - virStoragePoolObjPtr privpool; - int ret = -1; - - testDriverLock(privconn); - privpool = virStoragePoolObjFindByName(&privconn->pools, - pool->name); - testDriverUnlock(privconn); - - if (privpool == NULL) { - testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (virStoragePoolObjIsActive(privpool)) { - testError(pool->conn, VIR_ERR_INTERNAL_ERROR, - _("storage pool '%s' is already active"), pool->name); - goto cleanup; - } - ret = 0; - -cleanup: - if (privpool) - virStoragePoolObjUnlock(privpool); - return ret; -} - - -static int -testStoragePoolDestroy(virStoragePoolPtr pool) { - testConnPtr privconn = pool->conn->privateData; - virStoragePoolObjPtr privpool; - int ret = -1; - - testDriverLock(privconn); - privpool = virStoragePoolObjFindByName(&privconn->pools, - pool->name); - - if (privpool == NULL) { - testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (!virStoragePoolObjIsActive(privpool)) { - testError(pool->conn, VIR_ERR_INTERNAL_ERROR, - _("storage pool '%s' is not active"), pool->name); - goto cleanup; - } - - privpool->active = 0; - - if (privpool->configFile == NULL) { - virStoragePoolObjRemove(&privconn->pools, privpool); - privpool = NULL; - } - ret = 0; - -cleanup: - if (privpool) - virStoragePoolObjUnlock(privpool); - testDriverUnlock(privconn); - return ret; -} - - -static int -testStoragePoolDelete(virStoragePoolPtr pool, - unsigned int flags ATTRIBUTE_UNUSED) { - testConnPtr privconn = pool->conn->privateData; - virStoragePoolObjPtr privpool; - int ret = -1; - - testDriverLock(privconn); - privpool = virStoragePoolObjFindByName(&privconn->pools, - pool->name); - testDriverUnlock(privconn); - - if (privpool == NULL) { - testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (virStoragePoolObjIsActive(privpool)) { - testError(pool->conn, VIR_ERR_INTERNAL_ERROR, - _("storage pool '%s' is already active"), pool->name); - goto cleanup; - } - - ret = 0; - -cleanup: - if (privpool) - virStoragePoolObjUnlock(privpool); - return ret; -} - - -static int -testStoragePoolRefresh(virStoragePoolPtr pool, - unsigned int flags ATTRIBUTE_UNUSED) { - testConnPtr privconn = pool->conn->privateData; - virStoragePoolObjPtr privpool; - int ret = -1; - - testDriverLock(privconn); - privpool = virStoragePoolObjFindByName(&privconn->pools, - pool->name); - testDriverUnlock(privconn); - - if (privpool == NULL) { - testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (!virStoragePoolObjIsActive(privpool)) { - testError(pool->conn, VIR_ERR_INTERNAL_ERROR, - _("storage pool '%s' is not active"), pool->name); - goto cleanup; - } - ret = 0; - -cleanup: - if (privpool) - virStoragePoolObjUnlock(privpool); - return ret; -} - - -static int -testStoragePoolGetInfo(virStoragePoolPtr pool, - virStoragePoolInfoPtr info) { - testConnPtr privconn = pool->conn->privateData; - virStoragePoolObjPtr privpool; - int ret = -1; - - testDriverLock(privconn); - privpool = virStoragePoolObjFindByName(&privconn->pools, - pool->name); - testDriverUnlock(privconn); - - if (privpool == NULL) { - testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - 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; - ret = 0; - -cleanup: - if (privpool) - virStoragePoolObjUnlock(privpool); - return ret; -} - -static char * -testStoragePoolDumpXML(virStoragePoolPtr pool, - unsigned int flags ATTRIBUTE_UNUSED) { - testConnPtr privconn = pool->conn->privateData; - virStoragePoolObjPtr privpool; - char *ret = NULL; - - testDriverLock(privconn); - privpool = virStoragePoolObjFindByName(&privconn->pools, - pool->name); - testDriverUnlock(privconn); - - if (privpool == NULL) { - testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - ret = virStoragePoolDefFormat(pool->conn, privpool->def); - -cleanup: - if (privpool) - virStoragePoolObjUnlock(privpool); - return ret; -} - -static int -testStoragePoolGetAutostart(virStoragePoolPtr pool, - int *autostart) { - testConnPtr privconn = pool->conn->privateData; - virStoragePoolObjPtr privpool; - int ret = -1; - - testDriverLock(privconn); - privpool = virStoragePoolObjFindByName(&privconn->pools, - pool->name); - testDriverUnlock(privconn); - - if (privpool == NULL) { - testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (!privpool->configFile) { - *autostart = 0; - } else { - *autostart = privpool->autostart; - } - ret = 0; - -cleanup: - if (privpool) - virStoragePoolObjUnlock(privpool); - return ret; -} - -static int -testStoragePoolSetAutostart(virStoragePoolPtr pool, - int autostart) { - testConnPtr privconn = pool->conn->privateData; - virStoragePoolObjPtr privpool; - int ret = -1; - - testDriverLock(privconn); - privpool = virStoragePoolObjFindByName(&privconn->pools, - pool->name); - testDriverUnlock(privconn); - - if (privpool == NULL) { - testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (!privpool->configFile) { - testError(pool->conn, VIR_ERR_INVALID_ARG, - "%s", _("pool has no config file")); - goto cleanup; - } - - autostart = (autostart != 0); - privpool->autostart = autostart; - ret = 0; - -cleanup: - if (privpool) - virStoragePoolObjUnlock(privpool); - return ret; -} - - -static int -testStoragePoolNumVolumes(virStoragePoolPtr pool) { - testConnPtr privconn = pool->conn->privateData; - virStoragePoolObjPtr privpool; - int ret = -1; - - testDriverLock(privconn); - privpool = virStoragePoolObjFindByName(&privconn->pools, - pool->name); - testDriverUnlock(privconn); - - if (privpool == NULL) { - testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (!virStoragePoolObjIsActive(privpool)) { - testError(pool->conn, VIR_ERR_INTERNAL_ERROR, - _("storage pool '%s' is not active"), pool->name); - goto cleanup; - } - - ret = privpool->volumes.count; - -cleanup: - if (privpool) - virStoragePoolObjUnlock(privpool); - return ret; -} - -static int -testStoragePoolListVolumes(virStoragePoolPtr pool, - char **const names, - int maxnames) { - testConnPtr privconn = pool->conn->privateData; - virStoragePoolObjPtr privpool; - int i = 0, n = 0; - - memset(names, 0, maxnames * sizeof(*names)); - - testDriverLock(privconn); - privpool = virStoragePoolObjFindByName(&privconn->pools, - pool->name); - testDriverUnlock(privconn); - - if (privpool == NULL) { - testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - - if (!virStoragePoolObjIsActive(privpool)) { - testError(pool->conn, VIR_ERR_INTERNAL_ERROR, - _("storage pool '%s' is not active"), pool->name); - goto cleanup; - } - - for (i = 0 ; i < privpool->volumes.count && n < maxnames ; i++) { - if ((names[n++] = strdup(privpool->volumes.objs[i]->name)) == NULL) { - virReportOOMError(pool->conn); - goto cleanup; - } - } - - virStoragePoolObjUnlock(privpool); - return n; - - cleanup: - for (n = 0 ; n < maxnames ; n++) - VIR_FREE(names[i]); - - memset(names, 0, maxnames * sizeof(*names)); - if (privpool) - virStoragePoolObjUnlock(privpool); - return -1; -} - - -static virStorageVolPtr -testStorageVolumeLookupByName(virStoragePoolPtr pool, - const char *name ATTRIBUTE_UNUSED) { - testConnPtr privconn = pool->conn->privateData; - virStoragePoolObjPtr privpool; - virStorageVolDefPtr privvol; - virStorageVolPtr ret = NULL; - - testDriverLock(privconn); - privpool = virStoragePoolObjFindByName(&privconn->pools, - pool->name); - testDriverUnlock(privconn); - - if (privpool == NULL) { - testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - - if (!virStoragePoolObjIsActive(privpool)) { - testError(pool->conn, VIR_ERR_INTERNAL_ERROR, - _("storage pool '%s' is not active"), pool->name); - goto cleanup; - } - - privvol = virStorageVolDefFindByName(privpool, name); - - if (!privvol) { - testError(pool->conn, VIR_ERR_INVALID_STORAGE_VOL, - _("no storage vol with matching name '%s'"), name); - goto cleanup; - } - - ret = virGetStorageVol(pool->conn, privpool->def->name, - privvol->name, privvol->key); - -cleanup: - if (privpool) - virStoragePoolObjUnlock(privpool); - return ret; -} - - -static virStorageVolPtr -testStorageVolumeLookupByKey(virConnectPtr conn, - const char *key) { - testConnPtr privconn = conn->privateData; - unsigned int i; - virStorageVolPtr ret = NULL; - - testDriverLock(privconn); - for (i = 0 ; i < privconn->pools.count ; i++) { - virStoragePoolObjLock(privconn->pools.objs[i]); - if (virStoragePoolObjIsActive(privconn->pools.objs[i])) { - virStorageVolDefPtr privvol = - virStorageVolDefFindByKey(privconn->pools.objs[i], key); - - if (privvol) { - ret = virGetStorageVol(conn, - privconn->pools.objs[i]->def->name, - privvol->name, - privvol->key); - virStoragePoolObjUnlock(privconn->pools.objs[i]); - break; - } - } - virStoragePoolObjUnlock(privconn->pools.objs[i]); - } - testDriverUnlock(privconn); - - if (!ret) - testError(conn, VIR_ERR_INVALID_STORAGE_VOL, - _("no storage vol with matching key '%s'"), key); - - return ret; -} - -static virStorageVolPtr -testStorageVolumeLookupByPath(virConnectPtr conn, - const char *path) { - testConnPtr privconn = conn->privateData; - unsigned int i; - virStorageVolPtr ret = NULL; - - testDriverLock(privconn); - for (i = 0 ; i < privconn->pools.count ; i++) { - virStoragePoolObjLock(privconn->pools.objs[i]); - if (virStoragePoolObjIsActive(privconn->pools.objs[i])) { - virStorageVolDefPtr privvol = - virStorageVolDefFindByPath(privconn->pools.objs[i], path); - - if (privvol) { - ret = virGetStorageVol(conn, - privconn->pools.objs[i]->def->name, - privvol->name, - privvol->key); - virStoragePoolObjUnlock(privconn->pools.objs[i]); - break; - } - } - virStoragePoolObjUnlock(privconn->pools.objs[i]); - } - testDriverUnlock(privconn); - - if (!ret) - testError(conn, VIR_ERR_INVALID_STORAGE_VOL, - _("no storage vol with matching path '%s'"), path); - - return ret; -} - -static virStorageVolPtr -testStorageVolumeCreateXML(virStoragePoolPtr pool, - const char *xmldesc, - unsigned int flags ATTRIBUTE_UNUSED) { - testConnPtr privconn = pool->conn->privateData; - virStoragePoolObjPtr privpool; - virStorageVolDefPtr privvol = NULL; - virStorageVolPtr ret = NULL; - - testDriverLock(privconn); - privpool = virStoragePoolObjFindByName(&privconn->pools, - pool->name); - testDriverUnlock(privconn); - - if (privpool == NULL) { - testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (!virStoragePoolObjIsActive(privpool)) { - testError(pool->conn, VIR_ERR_INTERNAL_ERROR, - _("storage pool '%s' is not active"), pool->name); - goto cleanup; - } - - privvol = virStorageVolDefParseString(pool->conn, privpool->def, xmldesc); - if (privvol == NULL) - goto cleanup; - - if (virStorageVolDefFindByName(privpool, privvol->name)) { - testError(pool->conn, VIR_ERR_INVALID_STORAGE_VOL, - "%s", _("storage vol already exists")); - goto cleanup; - } - - /* Make sure enough space */ - if ((privpool->def->allocation + privvol->allocation) > - privpool->def->capacity) { - testError(pool->conn, VIR_ERR_INTERNAL_ERROR, - _("Not enough free space in pool for volume '%s'"), - privvol->name); - goto cleanup; - } - - if (VIR_REALLOC_N(privpool->volumes.objs, - privpool->volumes.count+1) < 0) { - virReportOOMError(pool->conn); - goto cleanup; - } - - if (virAsprintf(&privvol->target.path, "%s/%s", - privpool->def->target.path, - privvol->name) == -1) { - virReportOOMError(pool->conn); - goto cleanup; - } - - privvol->key = strdup(privvol->target.path); - if (privvol->key == NULL) { - virReportOOMError(pool->conn); - goto cleanup; - } - - privpool->def->allocation += privvol->allocation; - privpool->def->available = (privpool->def->capacity - - privpool->def->allocation); - - privpool->volumes.objs[privpool->volumes.count++] = privvol; - - ret = virGetStorageVol(pool->conn, privpool->def->name, - privvol->name, privvol->key); - privvol = NULL; - -cleanup: - virStorageVolDefFree(privvol); - if (privpool) - virStoragePoolObjUnlock(privpool); - return ret; -} - -static virStorageVolPtr -testStorageVolumeCreateXMLFrom(virStoragePoolPtr pool, - const char *xmldesc, - virStorageVolPtr clonevol, - unsigned int flags ATTRIBUTE_UNUSED) { - testConnPtr privconn = pool->conn->privateData; - virStoragePoolObjPtr privpool; - virStorageVolDefPtr privvol = NULL, origvol = NULL; - virStorageVolPtr ret = NULL; - - testDriverLock(privconn); - privpool = virStoragePoolObjFindByName(&privconn->pools, - pool->name); - testDriverUnlock(privconn); - - if (privpool == NULL) { - testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - if (!virStoragePoolObjIsActive(privpool)) { - testError(pool->conn, VIR_ERR_INTERNAL_ERROR, - _("storage pool '%s' is not active"), pool->name); - goto cleanup; - } - - privvol = virStorageVolDefParseString(pool->conn, privpool->def, xmldesc); - if (privvol == NULL) - goto cleanup; - - if (virStorageVolDefFindByName(privpool, privvol->name)) { - testError(pool->conn, VIR_ERR_INVALID_STORAGE_VOL, - "%s", _("storage vol already exists")); - goto cleanup; - } - - origvol = virStorageVolDefFindByName(privpool, clonevol->name); - if (!origvol) { - testError(pool->conn, VIR_ERR_INVALID_STORAGE_VOL, - _("no storage vol with matching name '%s'"), - clonevol->name); - goto cleanup; - } - - /* Make sure enough space */ - if ((privpool->def->allocation + privvol->allocation) > - privpool->def->capacity) { - testError(pool->conn, VIR_ERR_INTERNAL_ERROR, - _("Not enough free space in pool for volume '%s'"), - privvol->name); - goto cleanup; - } - privpool->def->available = (privpool->def->capacity - - privpool->def->allocation); - - if (VIR_REALLOC_N(privpool->volumes.objs, - privpool->volumes.count+1) < 0) { - virReportOOMError(pool->conn); - goto cleanup; - } - - if (virAsprintf(&privvol->target.path, "%s/%s", - privpool->def->target.path, - privvol->name) == -1) { - virReportOOMError(pool->conn); - goto cleanup; - } - - privvol->key = strdup(privvol->target.path); - if (privvol->key == NULL) { - virReportOOMError(pool->conn); - goto cleanup; - } - - privpool->def->allocation += privvol->allocation; - privpool->def->available = (privpool->def->capacity - - privpool->def->allocation); - - privpool->volumes.objs[privpool->volumes.count++] = privvol; - - ret = virGetStorageVol(pool->conn, privpool->def->name, - privvol->name, privvol->key); - privvol = NULL; - -cleanup: - virStorageVolDefFree(privvol); - if (privpool) - virStoragePoolObjUnlock(privpool); - return ret; -} - -static int -testStorageVolumeDelete(virStorageVolPtr vol, - unsigned int flags ATTRIBUTE_UNUSED) { - testConnPtr privconn = vol->conn->privateData; - virStoragePoolObjPtr privpool; - virStorageVolDefPtr privvol; - int i; - int ret = -1; - - testDriverLock(privconn); - privpool = virStoragePoolObjFindByName(&privconn->pools, - vol->pool); - testDriverUnlock(privconn); - - if (privpool == NULL) { - testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - - privvol = virStorageVolDefFindByName(privpool, vol->name); - - if (privvol == NULL) { - testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL, - _("no storage vol with matching name '%s'"), - vol->name); - goto cleanup; - } - - if (!virStoragePoolObjIsActive(privpool)) { - testError(vol->conn, VIR_ERR_INTERNAL_ERROR, - _("storage pool '%s' is not active"), vol->pool); - goto cleanup; - } - - - 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; - } - } - ret = 0; - -cleanup: - if (privpool) - virStoragePoolObjUnlock(privpool); - return ret; -} - - -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 vol, - virStorageVolInfoPtr info) { - testConnPtr privconn = vol->conn->privateData; - virStoragePoolObjPtr privpool; - virStorageVolDefPtr privvol; - int ret = -1; - - testDriverLock(privconn); - privpool = virStoragePoolObjFindByName(&privconn->pools, - vol->pool); - testDriverUnlock(privconn); - - if (privpool == NULL) { - testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - privvol = virStorageVolDefFindByName(privpool, vol->name); - - if (privvol == NULL) { - testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL, - _("no storage vol with matching name '%s'"), - vol->name); - goto cleanup; - } - - if (!virStoragePoolObjIsActive(privpool)) { - testError(vol->conn, VIR_ERR_INTERNAL_ERROR, - _("storage pool '%s' is not active"), vol->pool); - goto cleanup; - } - - memset(info, 0, sizeof(*info)); - info->type = testStorageVolumeTypeForPool(privpool->def->type); - info->capacity = privvol->capacity; - info->allocation = privvol->allocation; - ret = 0; - -cleanup: - if (privpool) - virStoragePoolObjUnlock(privpool); - return ret; -} - -static char * -testStorageVolumeGetXMLDesc(virStorageVolPtr vol, - unsigned int flags ATTRIBUTE_UNUSED) { - testConnPtr privconn = vol->conn->privateData; - virStoragePoolObjPtr privpool; - virStorageVolDefPtr privvol; - char *ret = NULL; - - testDriverLock(privconn); - privpool = virStoragePoolObjFindByName(&privconn->pools, - vol->pool); - testDriverUnlock(privconn); - - if (privpool == NULL) { - testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - privvol = virStorageVolDefFindByName(privpool, vol->name); - - if (privvol == NULL) { - testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL, - _("no storage vol with matching name '%s'"), - vol->name); - goto cleanup; - } - - if (!virStoragePoolObjIsActive(privpool)) { - testError(vol->conn, VIR_ERR_INTERNAL_ERROR, - _("storage pool '%s' is not active"), vol->pool); - goto cleanup; - } - - ret = virStorageVolDefFormat(vol->conn, privpool->def, privvol); - -cleanup: - if (privpool) - virStoragePoolObjUnlock(privpool); - return ret; -} - -static char * -testStorageVolumeGetPath(virStorageVolPtr vol) { - testConnPtr privconn = vol->conn->privateData; - virStoragePoolObjPtr privpool; - virStorageVolDefPtr privvol; - char *ret = NULL; - - testDriverLock(privconn); - privpool = virStoragePoolObjFindByName(&privconn->pools, - vol->pool); - testDriverUnlock(privconn); - - if (privpool == NULL) { - testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; - } - - privvol = virStorageVolDefFindByName(privpool, vol->name); - - if (privvol == NULL) { - testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL, - _("no storage vol with matching name '%s'"), - vol->name); - goto cleanup; - } - - if (!virStoragePoolObjIsActive(privpool)) { - testError(vol->conn, VIR_ERR_INTERNAL_ERROR, - _("storage pool '%s' is not active"), vol->pool); - goto cleanup; - } - - ret = strdup(privvol->target.path); - if (ret == NULL) - virReportOOMError(vol->conn); - -cleanup: - if (privpool) - virStoragePoolObjUnlock(privpool); - return ret; -} - - -static virDrvOpenStatus testDevMonOpen(virConnectPtr conn, - virConnectAuthPtr auth ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED) { - if (STRNEQ(conn->driver->name, "Test")) - return VIR_DRV_OPEN_DECLINED; - - conn->devMonPrivateData = conn->privateData; - return VIR_DRV_OPEN_SUCCESS; -} - -static int testDevMonClose(virConnectPtr conn) { - conn->devMonPrivateData = NULL; - return 0; -} - - -static int -testDomainEventRegister (virConnectPtr conn, - virConnectDomainEventCallback callback, - void *opaque, - virFreeCallback freecb) -{ - testConnPtr driver = conn->privateData; - int ret; - - testDriverLock(driver); - ret = virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks, - callback, opaque, freecb); - testDriverUnlock(driver); - - return ret; -} - -static int -testDomainEventDeregister (virConnectPtr conn, - virConnectDomainEventCallback callback) -{ - testConnPtr driver = conn->privateData; - int ret; - - testDriverLock(driver); - if (driver->domainEventDispatching) - ret = virDomainEventCallbackListMarkDelete(conn, driver->domainEventCallbacks, - callback); - else - ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks, - callback); - testDriverUnlock(driver); - - return ret; -} - -static void testDomainEventDispatchFunc(virConnectPtr conn, - virDomainEventPtr event, - virConnectDomainEventCallback cb, - void *cbopaque, - void *opaque) -{ - testConnPtr driver = opaque; - - /* Drop the lock whle dispatching, for sake of re-entrancy */ - testDriverUnlock(driver); - virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL); - testDriverLock(driver); -} - -static void testDomainEventFlush(int timer ATTRIBUTE_UNUSED, void *opaque) -{ - testConnPtr driver = opaque; - virDomainEventQueue tempQueue; - - testDriverLock(driver); - - driver->domainEventDispatching = 1; - - /* Copy the queue, so we're reentrant safe */ - tempQueue.count = driver->domainEventQueue->count; - tempQueue.events = driver->domainEventQueue->events; - driver->domainEventQueue->count = 0; - driver->domainEventQueue->events = NULL; - - virEventUpdateTimeout(driver->domainEventTimer, -1); - virDomainEventQueueDispatch(&tempQueue, - driver->domainEventCallbacks, - testDomainEventDispatchFunc, - driver); - - /* Purge any deleted callbacks */ - virDomainEventCallbackListPurgeMarked(driver->domainEventCallbacks); - - driver->domainEventDispatching = 0; - testDriverUnlock(driver); -} - - -/* driver must be locked before calling */ -static void testDomainEventQueue(testConnPtr driver, - virDomainEventPtr event) -{ - if (driver->domainEventTimer < 0) { - virDomainEventFree(event); - return; - } - - if (virDomainEventQueuePush(driver->domainEventQueue, - event) < 0) - virDomainEventFree(event); - - if (driver->domainEventQueue->count == 1) - virEventUpdateTimeout(driver->domainEventTimer, 0); -} - -static virDrvOpenStatus testSecretOpen(virConnectPtr conn, - virConnectAuthPtr auth ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED) { - if (STRNEQ(conn->driver->name, "Test")) - return VIR_DRV_OPEN_DECLINED; - - conn->secretPrivateData = conn->privateData; - return VIR_DRV_OPEN_SUCCESS; -} - -static int testSecretClose(virConnectPtr conn) { - conn->secretPrivateData = NULL; - return 0; -} - -static virDriver testDriver = { - VIR_DRV_TEST, - "Test", - testOpen, /* open */ - testClose, /* close */ - NULL, /* supports_feature */ - NULL, /* type */ - testGetVersion, /* version */ - testGetHostname, /* getHostname */ - testGetMaxVCPUs, /* getMaxVcpus */ - testNodeGetInfo, /* nodeGetInfo */ - testGetCapabilities, /* getCapabilities */ - testListDomains, /* listDomains */ - testNumOfDomains, /* numOfDomains */ - testDomainCreateXML, /* domainCreateXML */ - testLookupDomainByID, /* domainLookupByID */ - testLookupDomainByUUID, /* domainLookupByUUID */ - testLookupDomainByName, /* domainLookupByName */ - testPauseDomain, /* domainSuspend */ - testResumeDomain, /* domainResume */ - testShutdownDomain, /* domainShutdown */ - testRebootDomain, /* domainReboot */ - testDestroyDomain, /* domainDestroy */ - testGetOSType, /* domainGetOSType */ - testGetMaxMemory, /* domainGetMaxMemory */ - testSetMaxMemory, /* domainSetMaxMemory */ - testSetMemory, /* domainSetMemory */ - testGetDomainInfo, /* domainGetInfo */ - testDomainSave, /* domainSave */ - testDomainRestore, /* domainRestore */ - testDomainCoreDump, /* domainCoreDump */ - testSetVcpus, /* domainSetVcpus */ - NULL, /* domainPinVcpu */ - NULL, /* domainGetVcpus */ - NULL, /* domainGetMaxVcpus */ - NULL, /* domainGetSecurityLabel */ - NULL, /* nodeGetSecurityModel */ - testDomainDumpXML, /* domainDumpXML */ - NULL, /* domainXmlFromNative */ - NULL, /* domainXmlToNative */ - testListDefinedDomains, /* listDefinedDomains */ - testNumOfDefinedDomains, /* numOfDefinedDomains */ - testDomainCreate, /* domainCreate */ - testDomainDefineXML, /* domainDefineXML */ - testDomainUndefine, /* domainUndefine */ - NULL, /* domainAttachDevice */ - NULL, /* domainDetachDevice */ - testDomainGetAutostart, /* domainGetAutostart */ - testDomainSetAutostart, /* domainSetAutostart */ - testDomainGetSchedulerType, /* domainGetSchedulerType */ - testDomainGetSchedulerParams, /* domainGetSchedulerParameters */ - testDomainSetSchedulerParams, /* domainSetSchedulerParameters */ - NULL, /* domainMigratePrepare */ - NULL, /* domainMigratePerform */ - NULL, /* domainMigrateFinish */ - testDomainBlockStats, /* domainBlockStats */ - testDomainInterfaceStats, /* domainInterfaceStats */ - NULL, /* domainBlockPeek */ - NULL, /* domainMemoryPeek */ - testNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ - NULL, /* getFreeMemory */ - testDomainEventRegister, /* domainEventRegister */ - testDomainEventDeregister, /* domainEventDeregister */ - NULL, /* domainMigratePrepare2 */ - NULL, /* domainMigrateFinish2 */ - NULL, /* nodeDeviceDettach */ - NULL, /* nodeDeviceReAttach */ - NULL, /* nodeDeviceReset */ -}; - -static virNetworkDriver testNetworkDriver = { - "Test", - testOpenNetwork, /* open */ - testCloseNetwork, /* close */ - testNumNetworks, /* numOfNetworks */ - testListNetworks, /* listNetworks */ - testNumDefinedNetworks, /* numOfDefinedNetworks */ - testListDefinedNetworks, /* listDefinedNetworks */ - testLookupNetworkByUUID, /* networkLookupByUUID */ - testLookupNetworkByName, /* networkLookupByName */ - testNetworkCreate, /* networkCreateXML */ - testNetworkDefine, /* networkDefineXML */ - testNetworkUndefine, /* networkUndefine */ - testNetworkStart, /* networkCreate */ - testNetworkDestroy, /* networkDestroy */ - testNetworkDumpXML, /* networkDumpXML */ - testNetworkGetBridgeName, /* networkGetBridgeName */ - testNetworkGetAutostart, /* networkGetAutostart */ - testNetworkSetAutostart, /* networkSetAutostart */ -}; - -static virInterfaceDriver testInterfaceDriver = { - "Test", /* name */ - testOpenInterface, /* open */ - testCloseInterface, /* close */ - testNumOfInterfaces, /* numOfInterfaces */ - testListInterfaces, /* listInterfaces */ - testNumOfDefinedInterfaces, /* numOfDefinedInterfaces */ - testListDefinedInterfaces, /* listDefinedInterfaces */ - testLookupInterfaceByName, /* interfaceLookupByName */ - testLookupInterfaceByMACString, /* interfaceLookupByMACString */ - testInterfaceGetXMLDesc, /* interfaceGetXMLDesc */ - testInterfaceDefineXML, /* interfaceDefineXML */ - testInterfaceUndefine, /* interfaceUndefine */ - testInterfaceCreate, /* interfaceCreate */ - testInterfaceDestroy, /* interfaceDestroy */ -}; - - -static virStorageDriver testStorageDriver = { - .name = "Test", - .open = testStorageOpen, - .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, - .volCreateXMLFrom = testStorageVolumeCreateXMLFrom, - .volDelete = testStorageVolumeDelete, - .volGetInfo = testStorageVolumeGetInfo, - .volGetXMLDesc = testStorageVolumeGetXMLDesc, - .volGetPath = testStorageVolumeGetPath, -}; - -static virDeviceMonitor testDevMonitor = { - .name = "Test", - .open = testDevMonOpen, - .close = testDevMonClose, -}; - -static virSecretDriver testSecretDriver = { - .name = "Test", - .open = testSecretOpen, - .close = testSecretClose, -}; - - -/** - * testRegister: - * - * Registers the test driver - */ -int -testRegister(void) -{ - if (virRegisterDriver(&testDriver) < 0) - return -1; - if (virRegisterNetworkDriver(&testNetworkDriver) < 0) - return -1; - if (virRegisterInterfaceDriver(&testInterfaceDriver) < 0) - return -1; - if (virRegisterStorageDriver(&testStorageDriver) < 0) - return -1; - if (virRegisterDeviceMonitor(&testDevMonitor) < 0) - return -1; - if (virRegisterSecretDriver(&testSecretDriver) < 0) - return -1; - - return 0; -} diff --git a/src/test.h b/src/test.h deleted file mode 100644 index c6bdbd04dd..0000000000 --- a/src/test.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * test.h: A "mock" hypervisor for use by application unit tests - * - * Copyright (C) 2006-2006 Red Hat, Inc. - * Copyright (C) 2006 Daniel P. Berrange - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Daniel Berrange - */ - -#ifndef __VIR_TEST_INTERNAL_H__ -#define __VIR_TEST_INTERNAL_H__ - -#include "internal.h" - -int testRegister(void); - -#endif /* __VIR_TEST_INTERNAL_H__ */ diff --git a/src/test/test_driver.c b/src/test/test_driver.c new file mode 100644 index 0000000000..778992c68c --- /dev/null +++ b/src/test/test_driver.c @@ -0,0 +1,4375 @@ +/* + * test.c: A "mock" hypervisor for use by application unit tests + * + * Copyright (C) 2006-2009 Red Hat, Inc. + * Copyright (C) 2006 Daniel P. Berrange + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Daniel Berrange + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + + +#include "virterror_internal.h" +#include "datatypes.h" +#include "test_driver.h" +#include "buf.h" +#include "util.h" +#include "uuid.h" +#include "capabilities.h" +#include "memory.h" +#include "network_conf.h" +#include "interface_conf.h" +#include "domain_conf.h" +#include "domain_event.h" +#include "event.h" +#include "storage_conf.h" +#include "xml.h" +#include "threads.h" +#include "logging.h" + +#define VIR_FROM_THIS VIR_FROM_TEST + +#define MAX_CPUS 128 + +struct _testCell { + unsigned long mem; + int numCpus; + int cpus[MAX_CPUS]; +}; +typedef struct _testCell testCell; +typedef struct _testCell *testCellPtr; + +#define MAX_CELLS 128 + +struct _testConn { + virMutex lock; + + char path[PATH_MAX]; + int nextDomID; + virCapsPtr caps; + virNodeInfo nodeInfo; + virDomainObjList domains; + virNetworkObjList networks; + virInterfaceObjList ifaces; + virStoragePoolObjList pools; + int numCells; + testCell cells[MAX_CELLS]; + + + /* An array of callbacks */ + virDomainEventCallbackListPtr domainEventCallbacks; + virDomainEventQueuePtr domainEventQueue; + int domainEventTimer; + int domainEventDispatching; +}; +typedef struct _testConn testConn; +typedef struct _testConn *testConnPtr; + +#define TEST_MODEL "i686" +#define TEST_MODEL_WORDSIZE 32 +#define TEST_EMULATOR "/usr/bin/test-hv" + +static const virNodeInfo defaultNodeInfo = { + TEST_MODEL, + 1024*1024*3, /* 3 GB */ + 16, + 1400, + 2, + 2, + 2, + 2, +}; + + +#define testError(conn, code, fmt...) \ + virReportErrorHelper(conn, VIR_FROM_TEST, code, __FILE__, \ + __FUNCTION__, __LINE__, fmt) + +static int testClose(virConnectPtr conn); +static void testDomainEventFlush(int timer, void *opaque); +static void testDomainEventQueue(testConnPtr driver, + virDomainEventPtr event); + + +static void testDriverLock(testConnPtr driver) +{ + virMutexLock(&driver->lock); +} + +static void testDriverUnlock(testConnPtr driver) +{ + virMutexUnlock(&driver->lock); +} + +static virCapsPtr +testBuildCapabilities(virConnectPtr conn) { + testConnPtr privconn = conn->privateData; + virCapsPtr caps; + virCapsGuestPtr guest; + const char *const guest_types[] = { "hvm", "xen" }; + int i; + + if ((caps = virCapabilitiesNew(TEST_MODEL, 0, 0)) == NULL) + goto no_memory; + + if (virCapabilitiesAddHostFeature(caps, "pae") < 0) + goto no_memory; + if (virCapabilitiesAddHostFeature(caps ,"nonpae") < 0) + goto no_memory; + + for (i = 0; i < privconn->numCells; i++) { + if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].numCpus, + privconn->cells[i].cpus) < 0) + goto no_memory; + } + + for (i = 0; i < ARRAY_CARDINALITY(guest_types) ; i++) { + if ((guest = virCapabilitiesAddGuest(caps, + guest_types[i], + TEST_MODEL, + TEST_MODEL_WORDSIZE, + TEST_EMULATOR, + NULL, + 0, + NULL)) == NULL) + goto no_memory; + + if (virCapabilitiesAddGuestDomain(guest, + "test", + NULL, + NULL, + 0, + NULL) == NULL) + goto no_memory; + + if (virCapabilitiesAddGuestFeature(guest, "pae", 1, 1) == NULL) + goto no_memory; + if (virCapabilitiesAddGuestFeature(guest ,"nonpae", 1, 1) == NULL) + goto no_memory; + } + + return caps; + +no_memory: + virReportOOMError(conn); + virCapabilitiesFree(caps); + return NULL; +} + + +static const char *defaultDomainXML = +"" +" test" +" 8388608" +" 2097152" +" 2" +" " +" hvm" +" " +""; + + +static const char *defaultNetworkXML = +"" +" default" +" " +" " +" " +" " +" " +" " +" " +""; + +static const char *defaultInterfaceXML = +"" +" " +" " +" " +" " +" " +" " +" " +""; + +static const char *defaultPoolXML = +"" +" default-pool" +" " +" /default-pool" +" " +""; + +static const unsigned long long defaultPoolCap = (100 * 1024 * 1024 * 1024ull); +static const unsigned long long defaultPoolAlloc = 0; + +static int testStoragePoolObjSetDefaults(virConnectPtr conn, virStoragePoolObjPtr pool); + +static char * +testDomainGenerateIfname(virConnectPtr conn, + virDomainDefPtr domdef) { + int maxif = 1024; + int ifctr, i; + + for (ifctr = 0; ifctr < maxif; ++ifctr) { + char *ifname; + int found = 0; + + if (virAsprintf(&ifname, "testnet%d", ifctr) < 0) { + virReportOOMError(conn); + return NULL; + } + + /* Generate network interface names */ + for (i = 0 ; i < domdef->nnets ; i++) { + if (domdef->nets[i]->ifname && + STREQ (domdef->nets[i]->ifname, ifname)) { + found = 1; + break; + } + } + + if (!found) + return ifname; + } + + testError(conn, VIR_ERR_INTERNAL_ERROR, + _("Exceeded max iface limit %d"), maxif); + return NULL; +} + +static int +testDomainGenerateIfnames(virConnectPtr conn, + virDomainDefPtr domdef) +{ + int i = 0; + + for (i = 0; i < domdef->nnets; i++) { + char *ifname; + if (domdef->nets[i]->ifname) + continue; + + ifname = testDomainGenerateIfname(conn, domdef); + if (!ifname) + return -1; + + domdef->nets[i]->ifname = ifname; + } + + return 0; +} + + +static int testOpenDefault(virConnectPtr conn) { + int u; + struct timeval tv; + testConnPtr privconn; + virDomainDefPtr domdef = NULL; + virDomainObjPtr domobj = NULL; + virNetworkDefPtr netdef = NULL; + virNetworkObjPtr netobj = NULL; + virInterfaceDefPtr interfacedef = NULL; + virInterfaceObjPtr interfaceobj = NULL; + virStoragePoolDefPtr pooldef = NULL; + virStoragePoolObjPtr poolobj = NULL; + + if (VIR_ALLOC(privconn) < 0) { + virReportOOMError(conn); + return VIR_DRV_OPEN_ERROR; + } + if (virMutexInit(&privconn->lock) < 0) { + testError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot initialize mutex")); + VIR_FREE(privconn); + return VIR_DRV_OPEN_ERROR; + } + + testDriverLock(privconn); + conn->privateData = privconn; + + if (gettimeofday(&tv, NULL) < 0) { + virReportSystemError(conn, errno, + "%s", _("getting time of day")); + goto error; + } + + memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo)); + + // Numa setup + privconn->numCells = 2; + for (u = 0; u < 2; ++u) { + privconn->cells[u].numCpus = 8; + privconn->cells[u].mem = (u + 1) * 2048 * 1024; + } + for (u = 0 ; u < 16 ; u++) { + privconn->cells[u % 2].cpus[(u / 2)] = u; + } + + if (!(privconn->caps = testBuildCapabilities(conn))) + goto error; + + privconn->nextDomID = 1; + + if (!(domdef = virDomainDefParseString(conn, privconn->caps, + defaultDomainXML, + VIR_DOMAIN_XML_INACTIVE))) + goto error; + if (testDomainGenerateIfnames(conn, domdef) < 0) + goto error; + if (!(domobj = virDomainAssignDef(conn, &privconn->domains, domdef))) + goto error; + domdef = NULL; + domobj->def->id = privconn->nextDomID++; + domobj->state = VIR_DOMAIN_RUNNING; + domobj->persistent = 1; + virDomainObjUnlock(domobj); + + if (!(netdef = virNetworkDefParseString(conn, defaultNetworkXML))) + goto error; + if (!(netobj = virNetworkAssignDef(conn, &privconn->networks, netdef))) { + virNetworkDefFree(netdef); + goto error; + } + netobj->active = 1; + netobj->persistent = 1; + virNetworkObjUnlock(netobj); + + if (!(interfacedef = virInterfaceDefParseString(conn, defaultInterfaceXML))) + goto error; + if (!(interfaceobj = virInterfaceAssignDef(conn, &privconn->ifaces, interfacedef))) { + virInterfaceDefFree(interfacedef); + goto error; + } + interfaceobj->active = 1; + virInterfaceObjUnlock(interfaceobj); + + if (!(pooldef = virStoragePoolDefParseString(conn, defaultPoolXML))) + goto error; + + if (!(poolobj = virStoragePoolObjAssignDef(conn, &privconn->pools, + pooldef))) { + virStoragePoolDefFree(pooldef); + goto error; + } + + if (testStoragePoolObjSetDefaults(conn, poolobj) == -1) { + virStoragePoolObjUnlock(poolobj); + goto error; + } + poolobj->active = 1; + virStoragePoolObjUnlock(poolobj); + + testDriverUnlock(privconn); + + return VIR_DRV_OPEN_SUCCESS; + +error: + virDomainObjListFree(&privconn->domains); + virNetworkObjListFree(&privconn->networks); + virInterfaceObjListFree(&privconn->ifaces); + virStoragePoolObjListFree(&privconn->pools); + virCapabilitiesFree(privconn->caps); + testDriverUnlock(privconn); + conn->privateData = NULL; + VIR_FREE(privconn); + virDomainDefFree(domdef); + return VIR_DRV_OPEN_ERROR; +} + + +static char *testBuildFilename(const char *relativeTo, + const char *filename) { + char *offset; + int baseLen; + if (!filename || filename[0] == '\0') + return (NULL); + if (filename[0] == '/') + return strdup(filename); + + offset = strrchr(relativeTo, '/'); + if ((baseLen = (offset-relativeTo+1))) { + char *absFile; + if (VIR_ALLOC_N(absFile, baseLen + strlen(filename) + 1) < 0) + return NULL; + strncpy(absFile, relativeTo, baseLen); + absFile[baseLen] = '\0'; + strcat(absFile, filename); + return absFile; + } else { + return strdup(filename); + } +} + +static int testOpenVolumesForPool(virConnectPtr conn, + xmlDocPtr xml, + xmlXPathContextPtr ctxt, + const char *file, + virStoragePoolObjPtr pool, + int poolidx) { + char *vol_xpath; + int i, ret, func_ret = -1; + xmlNodePtr *vols = NULL; + virStorageVolDefPtr def = NULL; + + /* Find storage volumes */ + if (virAsprintf(&vol_xpath, "/node/pool[%d]/volume", poolidx) < 0) { + virReportOOMError(NULL); + goto error; + } + + ret = virXPathNodeSet(conn, vol_xpath, ctxt, &vols); + VIR_FREE(vol_xpath); + if (ret < 0) { + testError(NULL, VIR_ERR_XML_ERROR, + _("node vol list for pool '%s'"), pool->def->name); + goto error; + } + + for (i = 0 ; i < ret ; i++) { + char *relFile = virXMLPropString(vols[i], "file"); + if (relFile != NULL) { + char *absFile = testBuildFilename(file, relFile); + VIR_FREE(relFile); + if (!absFile) { + testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("resolving volume filename")); + goto error; + } + + def = virStorageVolDefParseFile(conn, pool->def, absFile); + VIR_FREE(absFile); + if (!def) + goto error; + } else { + if ((def = virStorageVolDefParseNode(conn, pool->def, xml, + vols[i])) == NULL) { + goto error; + } + } + + if (VIR_REALLOC_N(pool->volumes.objs, + pool->volumes.count+1) < 0) { + virReportOOMError(conn); + goto error; + } + + if (virAsprintf(&def->target.path, "%s/%s", + pool->def->target.path, + def->name) == -1) { + virReportOOMError(conn); + goto error; + } + + def->key = strdup(def->target.path); + if (def->key == NULL) { + virReportOOMError(conn); + goto error; + } + + pool->def->allocation += def->allocation; + pool->def->available = (pool->def->capacity - + pool->def->allocation); + + pool->volumes.objs[pool->volumes.count++] = def; + def = NULL; + } + + func_ret = 0; +error: + virStorageVolDefFree(def); + VIR_FREE(vols); + return func_ret; +} + +static int testOpenFromFile(virConnectPtr conn, + const char *file) { + int fd = -1, i, ret; + long l; + char *str; + xmlDocPtr xml = NULL; + xmlNodePtr root = NULL; + xmlNodePtr *domains = NULL, *networks = NULL, *ifaces = NULL, *pools = NULL; + xmlXPathContextPtr ctxt = NULL; + virNodeInfoPtr nodeInfo; + virNetworkObjPtr net; + virInterfaceObjPtr iface; + virDomainObjPtr dom; + testConnPtr privconn; + if (VIR_ALLOC(privconn) < 0) { + virReportOOMError(conn); + return VIR_DRV_OPEN_ERROR; + } + if (virMutexInit(&privconn->lock) < 0) { + testError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot initialize mutex")); + VIR_FREE(privconn); + return VIR_DRV_OPEN_ERROR; + } + + testDriverLock(privconn); + conn->privateData = privconn; + + if (!(privconn->caps = testBuildCapabilities(conn))) + goto error; + + if ((fd = open(file, O_RDONLY)) < 0) { + virReportSystemError(NULL, errno, + _("loading host definition file '%s'"), + file); + goto error; + } + + if (!(xml = xmlReadFd(fd, file, NULL, + XML_PARSE_NOENT | XML_PARSE_NONET | + XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) { + testError(NULL, VIR_ERR_INTERNAL_ERROR, + _("Invalid XML in file '%s'"), file); + goto error; + } + close(fd); + fd = -1; + + root = xmlDocGetRootElement(xml); + if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "node"))) { + testError(NULL, VIR_ERR_XML_ERROR, "%s", + _("Root element is not 'node'")); + goto error; + } + + ctxt = xmlXPathNewContext(xml); + if (ctxt == NULL) { + testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("creating xpath context")); + goto error; + } + + privconn->nextDomID = 1; + privconn->numCells = 0; + strncpy(privconn->path, file, PATH_MAX-1); + privconn->path[PATH_MAX-1] = '\0'; + memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo)); + + nodeInfo = &privconn->nodeInfo; + ret = virXPathLong(conn, "string(/node/cpu/nodes[1])", ctxt, &l); + if (ret == 0) { + nodeInfo->nodes = l; + } else if (ret == -2) { + testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu numa nodes")); + goto error; + } + + ret = virXPathLong(conn, "string(/node/cpu/sockets[1])", ctxt, &l); + if (ret == 0) { + nodeInfo->sockets = l; + } else if (ret == -2) { + testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu sockets")); + goto error; + } + + ret = virXPathLong(conn, "string(/node/cpu/cores[1])", ctxt, &l); + if (ret == 0) { + nodeInfo->cores = l; + } else if (ret == -2) { + testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu cores")); + goto error; + } + + ret = virXPathLong(conn, "string(/node/cpu/threads[1])", ctxt, &l); + if (ret == 0) { + nodeInfo->threads = l; + } else if (ret == -2) { + testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu threads")); + goto error; + } + + nodeInfo->cpus = nodeInfo->cores * nodeInfo->threads * nodeInfo->sockets * nodeInfo->nodes; + ret = virXPathLong(conn, "string(/node/cpu/active[1])", ctxt, &l); + if (ret == 0) { + if (l < nodeInfo->cpus) { + nodeInfo->cpus = l; + } + } else if (ret == -2) { + testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node active cpu")); + goto error; + } + ret = virXPathLong(conn, "string(/node/cpu/mhz[1])", ctxt, &l); + if (ret == 0) { + nodeInfo->mhz = l; + } else if (ret == -2) { + testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu mhz")); + goto error; + } + + str = virXPathString(conn, "string(/node/cpu/model[1])", ctxt); + if (str != NULL) { + strncpy(nodeInfo->model, str, sizeof(nodeInfo->model)-1); + nodeInfo->model[sizeof(nodeInfo->model)-1] = '\0'; + VIR_FREE(str); + } + + ret = virXPathLong(conn, "string(/node/memory[1])", ctxt, &l); + if (ret == 0) { + nodeInfo->memory = l; + } else if (ret == -2) { + testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node memory")); + goto error; + } + + ret = virXPathNodeSet(conn, "/node/domain", ctxt, &domains); + if (ret < 0) { + testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node domain list")); + goto error; + } + + for (i = 0 ; i < ret ; i++) { + virDomainDefPtr def; + char *relFile = virXMLPropString(domains[i], "file"); + if (relFile != NULL) { + char *absFile = testBuildFilename(file, relFile); + VIR_FREE(relFile); + if (!absFile) { + testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("resolving domain filename")); + goto error; + } + def = virDomainDefParseFile(conn, privconn->caps, absFile, + VIR_DOMAIN_XML_INACTIVE); + VIR_FREE(absFile); + if (!def) + goto error; + } else { + if ((def = virDomainDefParseNode(conn, privconn->caps, xml, domains[i], + VIR_DOMAIN_XML_INACTIVE)) == NULL) + goto error; + } + + if (testDomainGenerateIfnames(conn, def) < 0 || + !(dom = virDomainAssignDef(conn, &privconn->domains, def))) { + virDomainDefFree(def); + goto error; + } + + dom->state = VIR_DOMAIN_RUNNING; + dom->def->id = privconn->nextDomID++; + dom->persistent = 1; + virDomainObjUnlock(dom); + } + VIR_FREE(domains); + + ret = virXPathNodeSet(conn, "/node/network", ctxt, &networks); + if (ret < 0) { + testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node network list")); + goto error; + } + for (i = 0 ; i < ret ; i++) { + virNetworkDefPtr def; + char *relFile = virXMLPropString(networks[i], "file"); + if (relFile != NULL) { + char *absFile = testBuildFilename(file, relFile); + VIR_FREE(relFile); + if (!absFile) { + testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("resolving network filename")); + goto error; + } + + def = virNetworkDefParseFile(conn, absFile); + VIR_FREE(absFile); + if (!def) + goto error; + } else { + if ((def = virNetworkDefParseNode(conn, xml, networks[i])) == NULL) + goto error; + } + if (!(net = virNetworkAssignDef(conn, &privconn->networks, + def))) { + virNetworkDefFree(def); + goto error; + } + net->persistent = 1; + net->active = 1; + virNetworkObjUnlock(net); + } + VIR_FREE(networks); + + /* Parse interface definitions */ + ret = virXPathNodeSet(conn, "/node/interface", ctxt, &ifaces); + if (ret < 0) { + testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node interface list")); + goto error; + } + for (i = 0 ; i < ret ; i++) { + virInterfaceDefPtr def; + char *relFile = virXMLPropString(ifaces[i], "file"); + if (relFile != NULL) { + char *absFile = testBuildFilename(file, relFile); + VIR_FREE(relFile); + if (!absFile) { + testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("resolving interface filename")); + goto error; + } + + def = virInterfaceDefParseFile(conn, absFile); + VIR_FREE(absFile); + if (!def) + goto error; + } else { + if ((def = virInterfaceDefParseNode(conn, xml, ifaces[i])) == NULL) + goto error; + } + if (!(iface = virInterfaceAssignDef(conn, &privconn->ifaces, def))) { + virInterfaceDefFree(def); + goto error; + } + virInterfaceObjUnlock(iface); + } + VIR_FREE(ifaces); + + /* 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 = virStoragePoolDefParseFile(conn, absFile); + VIR_FREE(absFile); + if (!def) + goto error; + } else { + if ((def = virStoragePoolDefParseNode(conn, xml, + pools[i])) == NULL) { + goto error; + } + } + + if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, + def))) { + virStoragePoolDefFree(def); + goto error; + } + + if (testStoragePoolObjSetDefaults(conn, pool) == -1) { + virStoragePoolObjUnlock(pool); + goto error; + } + pool->active = 1; + + /* Find storage volumes */ + if (testOpenVolumesForPool(conn, xml, ctxt, file, pool, i+1) < 0) { + virStoragePoolObjUnlock(pool); + goto error; + } + + virStoragePoolObjUnlock(pool); + } + VIR_FREE(pools); + + xmlXPathFreeContext(ctxt); + xmlFreeDoc(xml); + testDriverUnlock(privconn); + + return (0); + + error: + xmlXPathFreeContext(ctxt); + xmlFreeDoc(xml); + VIR_FREE(domains); + VIR_FREE(networks); + VIR_FREE(ifaces); + VIR_FREE(pools); + if (fd != -1) + close(fd); + virDomainObjListFree(&privconn->domains); + virNetworkObjListFree(&privconn->networks); + virInterfaceObjListFree(&privconn->ifaces); + virStoragePoolObjListFree(&privconn->pools); + testDriverUnlock(privconn); + VIR_FREE(privconn); + conn->privateData = NULL; + return VIR_DRV_OPEN_ERROR; +} + + +static virDrvOpenStatus testOpen(virConnectPtr conn, + virConnectAuthPtr auth ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED) +{ + int ret; + + if (!conn->uri) + return VIR_DRV_OPEN_DECLINED; + + if (!conn->uri->scheme || STRNEQ(conn->uri->scheme, "test")) + return VIR_DRV_OPEN_DECLINED; + + /* Remote driver should handle these. */ + if (conn->uri->server) + return VIR_DRV_OPEN_DECLINED; + + /* From this point on, the connection is for us. */ + if (!conn->uri->path + || conn->uri->path[0] == '\0' + || (conn->uri->path[0] == '/' && conn->uri->path[1] == '\0')) { + testError (NULL, VIR_ERR_INVALID_ARG, + "%s", _("testOpen: supply a path or use test:///default")); + return VIR_DRV_OPEN_ERROR; + } + + if (STREQ(conn->uri->path, "/default")) + ret = testOpenDefault(conn); + else + ret = testOpenFromFile(conn, + conn->uri->path); + + if (ret == VIR_DRV_OPEN_SUCCESS) { + testConnPtr privconn = conn->privateData; + testDriverLock(privconn); + /* Init callback list */ + if (VIR_ALLOC(privconn->domainEventCallbacks) < 0 || + !(privconn->domainEventQueue = virDomainEventQueueNew())) { + virReportOOMError(NULL); + testDriverUnlock(privconn); + testClose(conn); + return VIR_DRV_OPEN_ERROR; + } + + if ((privconn->domainEventTimer = + virEventAddTimeout(-1, testDomainEventFlush, privconn, NULL)) < 0) + DEBUG0("virEventAddTimeout failed: No addTimeoutImpl defined. " + "continuing without events."); + testDriverUnlock(privconn); + } + + return (ret); +} + +static int testClose(virConnectPtr conn) +{ + testConnPtr privconn = conn->privateData; + testDriverLock(privconn); + virCapabilitiesFree(privconn->caps); + virDomainObjListFree(&privconn->domains); + virNetworkObjListFree(&privconn->networks); + virInterfaceObjListFree(&privconn->ifaces); + virStoragePoolObjListFree(&privconn->pools); + + virDomainEventCallbackListFree(privconn->domainEventCallbacks); + virDomainEventQueueFree(privconn->domainEventQueue); + + if (privconn->domainEventTimer != -1) + virEventRemoveTimeout(privconn->domainEventTimer); + + testDriverUnlock(privconn); + virMutexDestroy(&privconn->lock); + + VIR_FREE (privconn); + conn->privateData = NULL; + return 0; +} + +static int testGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED, + unsigned long *hvVer) +{ + *hvVer = 2; + return (0); +} + +static char *testGetHostname (virConnectPtr conn) +{ + char *result; + + result = virGetHostname(); + if (result == NULL) { + virReportSystemError(conn, errno, + "%s", _("cannot lookup hostname")); + return NULL; + } + /* Caller frees this string. */ + return result; +} + +static int testGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED, + const char *type ATTRIBUTE_UNUSED) +{ + return 32; +} + +static int testNodeGetInfo(virConnectPtr conn, + virNodeInfoPtr info) +{ + testConnPtr privconn = conn->privateData; + testDriverLock(privconn); + memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo)); + testDriverUnlock(privconn); + return (0); +} + +static char *testGetCapabilities (virConnectPtr conn) +{ + testConnPtr privconn = conn->privateData; + char *xml; + testDriverLock(privconn); + if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL) + virReportOOMError(conn); + testDriverUnlock(privconn); + return xml; +} + +static int testNumOfDomains(virConnectPtr conn) +{ + testConnPtr privconn = conn->privateData; + unsigned int numActive = 0, i; + + testDriverLock(privconn); + for (i = 0 ; i < privconn->domains.count ; i++) + if (virDomainIsActive(privconn->domains.objs[i])) + numActive++; + testDriverUnlock(privconn); + + return numActive; +} + +static virDomainPtr +testDomainCreateXML(virConnectPtr conn, const char *xml, + unsigned int flags ATTRIBUTE_UNUSED) +{ + testConnPtr privconn = conn->privateData; + virDomainPtr ret = NULL; + virDomainDefPtr def; + virDomainObjPtr dom = NULL; + virDomainEventPtr event = NULL; + + testDriverLock(privconn); + if ((def = virDomainDefParseString(conn, privconn->caps, xml, + VIR_DOMAIN_XML_INACTIVE)) == NULL) + goto cleanup; + + if (testDomainGenerateIfnames(conn, def) < 0) + goto cleanup; + if (!(dom = virDomainAssignDef(conn, &privconn->domains, def))) + goto cleanup; + def = NULL; + dom->state = VIR_DOMAIN_RUNNING; + dom->def->id = privconn->nextDomID++; + + event = virDomainEventNewFromObj(dom, + VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_BOOTED); + + ret = virGetDomain(conn, dom->def->name, dom->def->uuid); + if (ret) + ret->id = dom->def->id; + +cleanup: + if (dom) + virDomainObjUnlock(dom); + if (event) + testDomainEventQueue(privconn, event); + if (def) + virDomainDefFree(def); + testDriverUnlock(privconn); + return ret; +} + + +static virDomainPtr testLookupDomainByID(virConnectPtr conn, + int id) +{ + testConnPtr privconn = conn->privateData; + virDomainPtr ret = NULL; + virDomainObjPtr dom; + + testDriverLock(privconn); + dom = virDomainFindByID(&privconn->domains, id); + testDriverUnlock(privconn); + + if (dom == NULL) { + testError (conn, VIR_ERR_NO_DOMAIN, NULL); + goto cleanup; + } + + ret = virGetDomain(conn, dom->def->name, dom->def->uuid); + if (ret) + ret->id = dom->def->id; + +cleanup: + if (dom) + virDomainObjUnlock(dom); + return ret; +} + +static virDomainPtr testLookupDomainByUUID(virConnectPtr conn, + const unsigned char *uuid) +{ + testConnPtr privconn = conn->privateData; + virDomainPtr ret = NULL; + virDomainObjPtr dom ; + + testDriverLock(privconn); + dom = virDomainFindByUUID(&privconn->domains, uuid); + testDriverUnlock(privconn); + + if (dom == NULL) { + testError (conn, VIR_ERR_NO_DOMAIN, NULL); + goto cleanup; + } + + ret = virGetDomain(conn, dom->def->name, dom->def->uuid); + if (ret) + ret->id = dom->def->id; + +cleanup: + if (dom) + virDomainObjUnlock(dom); + return ret; +} + +static virDomainPtr testLookupDomainByName(virConnectPtr conn, + const char *name) +{ + testConnPtr privconn = conn->privateData; + virDomainPtr ret = NULL; + virDomainObjPtr dom; + + testDriverLock(privconn); + dom = virDomainFindByName(&privconn->domains, name); + testDriverUnlock(privconn); + + if (dom == NULL) { + testError (conn, VIR_ERR_NO_DOMAIN, NULL); + goto cleanup; + } + + ret = virGetDomain(conn, dom->def->name, dom->def->uuid); + if (ret) + ret->id = dom->def->id; + +cleanup: + if (dom) + virDomainObjUnlock(dom); + return ret; +} + +static int testListDomains (virConnectPtr conn, + int *ids, + int maxids) +{ + testConnPtr privconn = conn->privateData; + unsigned int n = 0, i; + + testDriverLock(privconn); + for (i = 0 ; i < privconn->domains.count && n < maxids ; i++) { + virDomainObjLock(privconn->domains.objs[i]); + if (virDomainIsActive(privconn->domains.objs[i])) + ids[n++] = privconn->domains.objs[i]->def->id; + virDomainObjUnlock(privconn->domains.objs[i]); + } + testDriverUnlock(privconn); + + return n; +} + +static int testDestroyDomain (virDomainPtr domain) +{ + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + virDomainEventPtr event = NULL; + int ret = -1; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + privdom->state = VIR_DOMAIN_SHUTOFF; + privdom->def->id = -1; + domain->id = -1; + event = virDomainEventNewFromObj(privdom, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_DESTROYED); + if (!privdom->persistent) { + virDomainRemoveInactive(&privconn->domains, + privdom); + privdom = NULL; + } + + + ret = 0; +cleanup: + if (privdom) + virDomainObjUnlock(privdom); + if (event) + testDomainEventQueue(privconn, event); + testDriverUnlock(privconn); + return ret; +} + +static int testResumeDomain (virDomainPtr domain) +{ + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + virDomainEventPtr event = NULL; + int ret = -1; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + testDriverUnlock(privconn); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (privdom->state != VIR_DOMAIN_PAUSED) { + testError(domain->conn, + VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"), + domain->name); + goto cleanup; + } + + privdom->state = VIR_DOMAIN_RUNNING; + event = virDomainEventNewFromObj(privdom, + VIR_DOMAIN_EVENT_RESUMED, + VIR_DOMAIN_EVENT_RESUMED_UNPAUSED); + ret = 0; + +cleanup: + if (privdom) + virDomainObjUnlock(privdom); + if (event) { + testDriverLock(privconn); + testDomainEventQueue(privconn, event); + testDriverUnlock(privconn); + } + return ret; +} + +static int testPauseDomain (virDomainPtr domain) +{ + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + virDomainEventPtr event = NULL; + int ret = -1; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + testDriverUnlock(privconn); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (privdom->state == VIR_DOMAIN_SHUTOFF || + privdom->state == VIR_DOMAIN_PAUSED) { + testError(domain->conn, + VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"), + domain->name); + goto cleanup; + } + + privdom->state = VIR_DOMAIN_PAUSED; + event = virDomainEventNewFromObj(privdom, + VIR_DOMAIN_EVENT_SUSPENDED, + VIR_DOMAIN_EVENT_SUSPENDED_PAUSED); + ret = 0; + +cleanup: + if (privdom) + virDomainObjUnlock(privdom); + + if (event) { + testDriverLock(privconn); + testDomainEventQueue(privconn, event); + testDriverUnlock(privconn); + } + return ret; +} + +static int testShutdownDomain (virDomainPtr domain) +{ + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + virDomainEventPtr event = NULL; + int ret = -1; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (privdom->state == VIR_DOMAIN_SHUTOFF) { + testError(domain->conn, VIR_ERR_INTERNAL_ERROR, + _("domain '%s' not running"), domain->name); + goto cleanup; + } + + privdom->state = VIR_DOMAIN_SHUTOFF; + domain->id = -1; + privdom->def->id = -1; + event = virDomainEventNewFromObj(privdom, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); + if (!privdom->persistent) { + virDomainRemoveInactive(&privconn->domains, + privdom); + privdom = NULL; + } + ret = 0; + +cleanup: + if (privdom) + virDomainObjUnlock(privdom); + if (event) + testDomainEventQueue(privconn, event); + testDriverUnlock(privconn); + return ret; +} + +/* Similar behaviour as shutdown */ +static int testRebootDomain (virDomainPtr domain, + unsigned int action ATTRIBUTE_UNUSED) +{ + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + virDomainEventPtr event = NULL; + int ret = -1; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + privdom->state = VIR_DOMAIN_SHUTDOWN; + switch (privdom->def->onReboot) { + case VIR_DOMAIN_LIFECYCLE_DESTROY: + privdom->state = VIR_DOMAIN_SHUTOFF; + domain->id = -1; + privdom->def->id = -1; + break; + + case VIR_DOMAIN_LIFECYCLE_RESTART: + privdom->state = VIR_DOMAIN_RUNNING; + break; + + case VIR_DOMAIN_LIFECYCLE_PRESERVE: + privdom->state = VIR_DOMAIN_SHUTOFF; + domain->id = -1; + privdom->def->id = -1; + break; + + case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME: + privdom->state = VIR_DOMAIN_RUNNING; + break; + + default: + privdom->state = VIR_DOMAIN_SHUTOFF; + domain->id = -1; + privdom->def->id = -1; + break; + } + + if (privdom->state == VIR_DOMAIN_SHUTOFF) { + event = virDomainEventNewFromObj(privdom, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); + if (!privdom->persistent) { + virDomainRemoveInactive(&privconn->domains, + privdom); + privdom = NULL; + } + } + + ret = 0; + +cleanup: + if (privdom) + virDomainObjUnlock(privdom); + if (event) + testDomainEventQueue(privconn, event); + testDriverUnlock(privconn); + return ret; +} + +static int testGetDomainInfo (virDomainPtr domain, + virDomainInfoPtr info) +{ + testConnPtr privconn = domain->conn->privateData; + struct timeval tv; + virDomainObjPtr privdom; + int ret = -1; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + testDriverUnlock(privconn); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (gettimeofday(&tv, NULL) < 0) { + testError(domain->conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("getting time of day")); + goto cleanup; + } + + info->state = privdom->state; + info->memory = privdom->def->memory; + info->maxMem = privdom->def->maxmem; + info->nrVirtCpu = privdom->def->vcpus; + info->cpuTime = ((tv.tv_sec * 1000ll * 1000ll * 1000ll) + (tv.tv_usec * 1000ll)); + ret = 0; + +cleanup: + if (privdom) + virDomainObjUnlock(privdom); + return ret; +} + +#define TEST_SAVE_MAGIC "TestGuestMagic" + +static int testDomainSave(virDomainPtr domain, + const char *path) +{ + testConnPtr privconn = domain->conn->privateData; + char *xml = NULL; + int fd = -1; + int len; + virDomainObjPtr privdom; + virDomainEventPtr event = NULL; + int ret = -1; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + xml = virDomainDefFormat(domain->conn, + privdom->def, + VIR_DOMAIN_XML_SECURE); + + if (xml == NULL) { + virReportSystemError(domain->conn, errno, + _("saving domain '%s' failed to allocate space for metadata"), + domain->name); + goto cleanup; + } + + if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) { + virReportSystemError(domain->conn, errno, + _("saving domain '%s' to '%s': open failed"), + domain->name, path); + goto cleanup; + } + len = strlen(xml); + if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) { + virReportSystemError(domain->conn, errno, + _("saving domain '%s' to '%s': write failed"), + domain->name, path); + goto cleanup; + } + if (safewrite(fd, (char*)&len, sizeof(len)) < 0) { + virReportSystemError(domain->conn, errno, + _("saving domain '%s' to '%s': write failed"), + domain->name, path); + goto cleanup; + } + if (safewrite(fd, xml, len) < 0) { + virReportSystemError(domain->conn, errno, + _("saving domain '%s' to '%s': write failed"), + domain->name, path); + goto cleanup; + } + + if (close(fd) < 0) { + virReportSystemError(domain->conn, errno, + _("saving domain '%s' to '%s': write failed"), + domain->name, path); + goto cleanup; + } + fd = -1; + + privdom->state = VIR_DOMAIN_SHUTOFF; + event = virDomainEventNewFromObj(privdom, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SAVED); + if (!privdom->persistent) { + virDomainRemoveInactive(&privconn->domains, + privdom); + privdom = NULL; + } + ret = 0; + +cleanup: + VIR_FREE(xml); + + /* Don't report failure in close or unlink, because + * in either case we're already in a failure scenario + * and have reported a earlier error */ + if (ret != 0) { + if (fd != -1) + close(fd); + unlink(path); + } + if (privdom) + virDomainObjUnlock(privdom); + if (event) + testDomainEventQueue(privconn, event); + testDriverUnlock(privconn); + return ret; +} + +static int testDomainRestore(virConnectPtr conn, + const char *path) +{ + testConnPtr privconn = conn->privateData; + char *xml = NULL; + char magic[15]; + int fd = -1; + int len; + virDomainDefPtr def = NULL; + virDomainObjPtr dom = NULL; + virDomainEventPtr event = NULL; + int ret = -1; + + if ((fd = open(path, O_RDONLY)) < 0) { + virReportSystemError(conn, errno, + _("cannot read domain image '%s'"), + path); + goto cleanup; + } + if (saferead(fd, magic, sizeof(magic)) != sizeof(magic)) { + virReportSystemError(conn, errno, + _("incomplete save header in '%s'"), + path); + goto cleanup; + } + if (memcmp(magic, TEST_SAVE_MAGIC, sizeof(magic))) { + testError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("mismatched header magic")); + goto cleanup; + } + if (saferead(fd, (char*)&len, sizeof(len)) != sizeof(len)) { + virReportSystemError(conn, errno, + _("failed to read metadata length in '%s'"), + path); + goto cleanup; + } + if (len < 1 || len > 8192) { + testError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("length of metadata out of range")); + goto cleanup; + } + if (VIR_ALLOC_N(xml, len+1) < 0) { + virReportOOMError(conn); + goto cleanup; + } + if (saferead(fd, xml, len) != len) { + virReportSystemError(conn, errno, + _("incomplete metdata in '%s'"), path); + goto cleanup; + } + xml[len] = '\0'; + + testDriverLock(privconn); + def = virDomainDefParseString(conn, privconn->caps, xml, + VIR_DOMAIN_XML_INACTIVE); + if (!def) + goto cleanup; + + if (testDomainGenerateIfnames(conn, def) < 0) + goto cleanup; + if (!(dom = virDomainAssignDef(conn, &privconn->domains, def))) + goto cleanup; + def = NULL; + + dom->state = VIR_DOMAIN_RUNNING; + dom->def->id = privconn->nextDomID++; + event = virDomainEventNewFromObj(dom, + VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_RESTORED); + ret = 0; + +cleanup: + virDomainDefFree(def); + VIR_FREE(xml); + if (fd != -1) + close(fd); + if (dom) + virDomainObjUnlock(dom); + if (event) + testDomainEventQueue(privconn, event); + testDriverUnlock(privconn); + return ret; +} + +static int testDomainCoreDump(virDomainPtr domain, + const char *to, + int flags ATTRIBUTE_UNUSED) +{ + testConnPtr privconn = domain->conn->privateData; + int fd = -1; + virDomainObjPtr privdom; + virDomainEventPtr event = NULL; + int ret = -1; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) { + virReportSystemError(domain->conn, errno, + _("domain '%s' coredump: failed to open %s"), + domain->name, to); + goto cleanup; + } + if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) { + virReportSystemError(domain->conn, errno, + _("domain '%s' coredump: failed to write header to %s"), + domain->name, to); + goto cleanup; + } + if (close(fd) < 0) { + virReportSystemError(domain->conn, errno, + _("domain '%s' coredump: write failed: %s"), + domain->name, to); + goto cleanup; + } + privdom->state = VIR_DOMAIN_SHUTOFF; + event = virDomainEventNewFromObj(privdom, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_CRASHED); + if (!privdom->persistent) { + virDomainRemoveInactive(&privconn->domains, + privdom); + privdom = NULL; + } + ret = 0; + +cleanup: + if (fd != -1) + close(fd); + if (privdom) + virDomainObjUnlock(privdom); + if (event) + testDomainEventQueue(privconn, event); + testDriverUnlock(privconn); + return ret; +} + +static char *testGetOSType(virDomainPtr dom) { + char *ret = strdup("linux"); + if (!ret) + virReportOOMError(dom->conn); + return ret; +} + +static unsigned long testGetMaxMemory(virDomainPtr domain) { + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + unsigned long ret = 0; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + testDriverUnlock(privconn); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + ret = privdom->def->maxmem; + +cleanup: + if (privdom) + virDomainObjUnlock(privdom); + return ret; +} + +static int testSetMaxMemory(virDomainPtr domain, + unsigned long memory) +{ + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + int ret = -1; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + testDriverUnlock(privconn); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + /* XXX validate not over host memory wrt to other domains */ + privdom->def->maxmem = memory; + ret = 0; + +cleanup: + if (privdom) + virDomainObjUnlock(privdom); + return ret; +} + +static int testSetMemory(virDomainPtr domain, + unsigned long memory) +{ + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + int ret = -1; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + testDriverUnlock(privconn); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (memory > privdom->def->maxmem) { + testError(domain->conn, + VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + privdom->def->memory = memory; + ret = 0; + +cleanup: + if (privdom) + virDomainObjUnlock(privdom); + return ret; +} + +static int testSetVcpus(virDomainPtr domain, + unsigned int nrCpus) { + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + int ret = -1; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + testDriverUnlock(privconn); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + /* We allow more cpus in guest than host */ + if (nrCpus > 32) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + privdom->def->vcpus = nrCpus; + ret = 0; + +cleanup: + if (privdom) + virDomainObjUnlock(privdom); + return ret; +} + +static char *testDomainDumpXML(virDomainPtr domain, int flags) +{ + testConnPtr privconn = domain->conn->privateData; + virDomainDefPtr def; + virDomainObjPtr privdom; + char *ret = NULL; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + testDriverUnlock(privconn); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + def = (flags & VIR_DOMAIN_XML_INACTIVE) && + privdom->newDef ? privdom->newDef : privdom->def; + + ret = virDomainDefFormat(domain->conn, + def, + flags); + +cleanup: + if (privdom) + virDomainObjUnlock(privdom); + return ret; +} + +static int testNumOfDefinedDomains(virConnectPtr conn) { + testConnPtr privconn = conn->privateData; + unsigned int numInactive = 0, i; + + testDriverLock(privconn); + for (i = 0 ; i < privconn->domains.count ; i++) { + virDomainObjLock(privconn->domains.objs[i]); + if (!virDomainIsActive(privconn->domains.objs[i])) + numInactive++; + virDomainObjUnlock(privconn->domains.objs[i]); + } + testDriverUnlock(privconn); + + return numInactive; +} + +static int testListDefinedDomains(virConnectPtr conn, + char **const names, + int maxnames) { + testConnPtr privconn = conn->privateData; + unsigned int n = 0, i; + + testDriverLock(privconn); + memset(names, 0, sizeof(*names)*maxnames); + for (i = 0 ; i < privconn->domains.count && n < maxnames ; i++) { + virDomainObjLock(privconn->domains.objs[i]); + if (!virDomainIsActive(privconn->domains.objs[i]) && + !(names[n++] = strdup(privconn->domains.objs[i]->def->name))) { + virDomainObjUnlock(privconn->domains.objs[i]); + goto no_memory; + } + virDomainObjUnlock(privconn->domains.objs[i]); + } + testDriverUnlock(privconn); + + return n; + +no_memory: + virReportOOMError(conn); + for (n = 0 ; n < maxnames ; n++) + VIR_FREE(names[n]); + testDriverUnlock(privconn); + return -1; +} + +static virDomainPtr testDomainDefineXML(virConnectPtr conn, + const char *xml) { + testConnPtr privconn = conn->privateData; + virDomainPtr ret = NULL; + virDomainDefPtr def; + virDomainObjPtr dom = NULL; + virDomainEventPtr event = NULL; + + testDriverLock(privconn); + if ((def = virDomainDefParseString(conn, privconn->caps, xml, + VIR_DOMAIN_XML_INACTIVE)) == NULL) + goto cleanup; + + if (testDomainGenerateIfnames(conn, def) < 0) + goto cleanup; + if (!(dom = virDomainAssignDef(conn, &privconn->domains, def))) + goto cleanup; + def = NULL; + dom->persistent = 1; + + event = virDomainEventNewFromObj(dom, + VIR_DOMAIN_EVENT_DEFINED, + VIR_DOMAIN_EVENT_DEFINED_ADDED); + + ret = virGetDomain(conn, dom->def->name, dom->def->uuid); + if (ret) + ret->id = dom->def->id; + +cleanup: + virDomainDefFree(def); + if (dom) + virDomainObjUnlock(dom); + if (event) + testDomainEventQueue(privconn, event); + testDriverUnlock(privconn); + return ret; +} + +static int testNodeGetCellsFreeMemory(virConnectPtr conn, + unsigned long long *freemems, + int startCell, int maxCells) { + testConnPtr privconn = conn->privateData; + int i, j; + int ret = -1; + + testDriverLock(privconn); + if (startCell > privconn->numCells) { + testError(conn, VIR_ERR_INVALID_ARG, + "%s", _("Range exceeds available cells")); + goto cleanup; + } + + for (i = startCell, j = 0; + (i < privconn->numCells && j < maxCells) ; + ++i, ++j) { + freemems[j] = privconn->cells[i].mem; + } + ret = j; + +cleanup: + testDriverUnlock(privconn); + return ret; +} + + +static int testDomainCreate(virDomainPtr domain) { + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + virDomainEventPtr event = NULL; + int ret = -1; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (privdom->state != VIR_DOMAIN_SHUTOFF) { + testError(domain->conn, VIR_ERR_INTERNAL_ERROR, + _("Domain '%s' is already running"), domain->name); + goto cleanup; + } + + domain->id = privdom->def->id = privconn->nextDomID++; + privdom->state = VIR_DOMAIN_RUNNING; + event = virDomainEventNewFromObj(privdom, + VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_BOOTED); + ret = 0; + +cleanup: + if (privdom) + virDomainObjUnlock(privdom); + if (event) + testDomainEventQueue(privconn, event); + testDriverUnlock(privconn); + return ret; +} + +static int testDomainUndefine(virDomainPtr domain) { + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + virDomainEventPtr event = NULL; + int ret = -1; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (privdom->state != VIR_DOMAIN_SHUTOFF) { + testError(domain->conn, VIR_ERR_INTERNAL_ERROR, + _("Domain '%s' is still running"), domain->name); + goto cleanup; + } + + privdom->state = VIR_DOMAIN_SHUTOFF; + event = virDomainEventNewFromObj(privdom, + VIR_DOMAIN_EVENT_UNDEFINED, + VIR_DOMAIN_EVENT_UNDEFINED_REMOVED); + virDomainRemoveInactive(&privconn->domains, + privdom); + privdom = NULL; + ret = 0; + +cleanup: + if (privdom) + virDomainObjUnlock(privdom); + if (event) + testDomainEventQueue(privconn, event); + testDriverUnlock(privconn); + return ret; +} + +static int testDomainGetAutostart(virDomainPtr domain, + int *autostart) +{ + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + int ret = -1; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + testDriverUnlock(privconn); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + *autostart = privdom->autostart; + ret = 0; + +cleanup: + if (privdom) + virDomainObjUnlock(privdom); + return ret; +} + + +static int testDomainSetAutostart(virDomainPtr domain, + int autostart) +{ + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + int ret = -1; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + testDriverUnlock(privconn); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + privdom->autostart = autostart ? 1 : 0; + ret = 0; + +cleanup: + if (privdom) + virDomainObjUnlock(privdom); + return ret; +} + +static char *testDomainGetSchedulerType(virDomainPtr domain, + int *nparams) +{ + char *type = NULL; + + *nparams = 1; + type = strdup("fair"); + if (!type) + virReportOOMError(domain->conn); + + return type; +} + +static int testDomainGetSchedulerParams(virDomainPtr domain, + virSchedParameterPtr params, + int *nparams) +{ + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + int ret = -1; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + testDriverUnlock(privconn); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (*nparams != 1) { + testError(domain->conn, VIR_ERR_INVALID_ARG, "nparams"); + goto cleanup; + } + strcpy(params[0].field, "weight"); + params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT; + /* XXX */ + /*params[0].value.ui = privdom->weight;*/ + params[0].value.ui = 50; + ret = 0; + +cleanup: + if (privdom) + virDomainObjUnlock(privdom); + return ret; +} + + +static int testDomainSetSchedulerParams(virDomainPtr domain, + virSchedParameterPtr params, + int nparams) +{ + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + int ret = -1; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + testDriverUnlock(privconn); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (nparams != 1) { + testError(domain->conn, VIR_ERR_INVALID_ARG, "nparams"); + goto cleanup; + } + if (STRNEQ(params[0].field, "weight")) { + testError(domain->conn, VIR_ERR_INVALID_ARG, "field"); + goto cleanup; + } + if (params[0].type != VIR_DOMAIN_SCHED_FIELD_UINT) { + testError(domain->conn, VIR_ERR_INVALID_ARG, "type"); + goto cleanup; + } + /* XXX */ + /*privdom->weight = params[0].value.ui;*/ + ret = 0; + +cleanup: + if (privdom) + virDomainObjUnlock(privdom); + return ret; +} + +static int testDomainBlockStats(virDomainPtr domain, + const char *path, + struct _virDomainBlockStats *stats) +{ + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + struct timeval tv; + unsigned long long statbase; + int i, found = 0, ret = -1; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + testDriverUnlock(privconn); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + for (i = 0 ; i < privdom->def->ndisks ; i++) { + if (STREQ(path, privdom->def->disks[i]->dst)) { + found = 1; + break; + } + } + + if (!found) { + testError(domain->conn, VIR_ERR_INVALID_ARG, + _("invalid path: %s"), path); + goto error; + } + + if (gettimeofday(&tv, NULL) < 0) { + virReportSystemError(domain->conn, errno, + "%s", _("getting time of day")); + goto error; + } + + /* No significance to these numbers, just enough to mix it up*/ + statbase = (tv.tv_sec * 1000UL * 1000UL) + tv.tv_usec; + stats->rd_req = statbase / 10; + stats->rd_bytes = statbase / 20; + stats->wr_req = statbase / 30; + stats->wr_bytes = statbase / 40; + stats->errs = tv.tv_sec / 2; + + ret = 0; +error: + if (privdom) + virDomainObjUnlock(privdom); + return ret; +} + +static int testDomainInterfaceStats(virDomainPtr domain, + const char *path, + struct _virDomainInterfaceStats *stats) +{ + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + struct timeval tv; + unsigned long long statbase; + int i, found = 0, ret = -1; + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + testDriverUnlock(privconn); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + for (i = 0 ; i < privdom->def->nnets ; i++) { + if (privdom->def->nets[i]->ifname && + STREQ (privdom->def->nets[i]->ifname, path)) { + found = 1; + break; + } + } + + if (!found) { + testError(domain->conn, VIR_ERR_INVALID_ARG, + _("invalid path, '%s' is not a known interface"), path); + goto error; + } + + if (gettimeofday(&tv, NULL) < 0) { + virReportSystemError(domain->conn, errno, + "%s", _("getting time of day")); + goto error; + } + + /* No significance to these numbers, just enough to mix it up*/ + statbase = (tv.tv_sec * 1000UL * 1000UL) + tv.tv_usec; + stats->rx_bytes = statbase / 10; + stats->rx_packets = statbase / 100; + stats->rx_errs = tv.tv_sec / 1; + stats->rx_drop = tv.tv_sec / 2; + stats->tx_bytes = statbase / 20; + stats->tx_packets = statbase / 110; + stats->tx_errs = tv.tv_sec / 3; + stats->tx_drop = tv.tv_sec / 4; + + ret = 0; +error: + if (privdom) + virDomainObjUnlock(privdom); + return ret; +} + +static virDrvOpenStatus testOpenNetwork(virConnectPtr conn, + virConnectAuthPtr auth ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED) { + if (STRNEQ(conn->driver->name, "Test")) + return VIR_DRV_OPEN_DECLINED; + + conn->networkPrivateData = conn->privateData; + return VIR_DRV_OPEN_SUCCESS; +} + +static int testCloseNetwork(virConnectPtr conn) { + conn->networkPrivateData = NULL; + return 0; +} + + +static virNetworkPtr testLookupNetworkByUUID(virConnectPtr conn, + const unsigned char *uuid) +{ + testConnPtr privconn = conn->privateData; + virNetworkObjPtr net; + virNetworkPtr ret = NULL; + + testDriverLock(privconn); + net = virNetworkFindByUUID(&privconn->networks, uuid); + testDriverUnlock(privconn); + + if (net == NULL) { + testError (conn, VIR_ERR_NO_NETWORK, NULL); + goto cleanup; + } + + ret = virGetNetwork(conn, net->def->name, net->def->uuid); + +cleanup: + if (net) + virNetworkObjUnlock(net); + return ret; +} + +static virNetworkPtr testLookupNetworkByName(virConnectPtr conn, + const char *name) +{ + testConnPtr privconn = conn->privateData; + virNetworkObjPtr net; + virNetworkPtr ret = NULL; + + testDriverLock(privconn); + net = virNetworkFindByName(&privconn->networks, name); + testDriverUnlock(privconn); + + if (net == NULL) { + testError (conn, VIR_ERR_NO_NETWORK, NULL); + goto cleanup; + } + + ret = virGetNetwork(conn, net->def->name, net->def->uuid); + +cleanup: + if (net) + virNetworkObjUnlock(net); + return ret; +} + + +static int testNumNetworks(virConnectPtr conn) { + testConnPtr privconn = conn->privateData; + int numActive = 0, i; + + testDriverLock(privconn); + for (i = 0 ; i < privconn->networks.count ; i++) { + virNetworkObjLock(privconn->networks.objs[i]); + if (virNetworkIsActive(privconn->networks.objs[i])) + numActive++; + virNetworkObjUnlock(privconn->networks.objs[i]); + } + testDriverUnlock(privconn); + + return numActive; +} + +static int testListNetworks(virConnectPtr conn, char **const names, int nnames) { + testConnPtr privconn = conn->privateData; + int n = 0, i; + + testDriverLock(privconn); + memset(names, 0, sizeof(*names)*nnames); + for (i = 0 ; i < privconn->networks.count && n < nnames ; i++) { + virNetworkObjLock(privconn->networks.objs[i]); + if (virNetworkIsActive(privconn->networks.objs[i]) && + !(names[n++] = strdup(privconn->networks.objs[i]->def->name))) { + virNetworkObjUnlock(privconn->networks.objs[i]); + goto no_memory; + } + virNetworkObjUnlock(privconn->networks.objs[i]); + } + testDriverUnlock(privconn); + + return n; + +no_memory: + virReportOOMError(conn); + for (n = 0 ; n < nnames ; n++) + VIR_FREE(names[n]); + testDriverUnlock(privconn); + return -1; +} + +static int testNumDefinedNetworks(virConnectPtr conn) { + testConnPtr privconn = conn->privateData; + int numInactive = 0, i; + + testDriverLock(privconn); + for (i = 0 ; i < privconn->networks.count ; i++) { + virNetworkObjLock(privconn->networks.objs[i]); + if (!virNetworkIsActive(privconn->networks.objs[i])) + numInactive++; + virNetworkObjUnlock(privconn->networks.objs[i]); + } + testDriverUnlock(privconn); + + return numInactive; +} + +static int testListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) { + testConnPtr privconn = conn->privateData; + int n = 0, i; + + testDriverLock(privconn); + memset(names, 0, sizeof(*names)*nnames); + for (i = 0 ; i < privconn->networks.count && n < nnames ; i++) { + virNetworkObjLock(privconn->networks.objs[i]); + if (!virNetworkIsActive(privconn->networks.objs[i]) && + !(names[n++] = strdup(privconn->networks.objs[i]->def->name))) { + virNetworkObjUnlock(privconn->networks.objs[i]); + goto no_memory; + } + virNetworkObjUnlock(privconn->networks.objs[i]); + } + testDriverUnlock(privconn); + + return n; + +no_memory: + virReportOOMError(conn); + for (n = 0 ; n < nnames ; n++) + VIR_FREE(names[n]); + testDriverUnlock(privconn); + return -1; +} + +static virNetworkPtr testNetworkCreate(virConnectPtr conn, const char *xml) { + testConnPtr privconn = conn->privateData; + virNetworkDefPtr def; + virNetworkObjPtr net = NULL; + virNetworkPtr ret = NULL; + + testDriverLock(privconn); + if ((def = virNetworkDefParseString(conn, xml)) == NULL) + goto cleanup; + + if ((net = virNetworkAssignDef(conn, &privconn->networks, def)) == NULL) + goto cleanup; + def = NULL; + net->active = 1; + + ret = virGetNetwork(conn, net->def->name, net->def->uuid); + +cleanup: + virNetworkDefFree(def); + if (net) + virNetworkObjUnlock(net); + testDriverUnlock(privconn); + return ret; +} + +static virNetworkPtr testNetworkDefine(virConnectPtr conn, const char *xml) { + testConnPtr privconn = conn->privateData; + virNetworkDefPtr def; + virNetworkObjPtr net = NULL; + virNetworkPtr ret = NULL; + + testDriverLock(privconn); + if ((def = virNetworkDefParseString(conn, xml)) == NULL) + goto cleanup; + + if ((net = virNetworkAssignDef(conn, &privconn->networks, def)) == NULL) + goto cleanup; + def = NULL; + net->persistent = 1; + + ret = virGetNetwork(conn, net->def->name, net->def->uuid); + +cleanup: + virNetworkDefFree(def); + if (net) + virNetworkObjUnlock(net); + testDriverUnlock(privconn); + return ret; +} + +static int testNetworkUndefine(virNetworkPtr network) { + testConnPtr privconn = network->conn->privateData; + virNetworkObjPtr privnet; + int ret = -1; + + testDriverLock(privconn); + privnet = virNetworkFindByName(&privconn->networks, + network->name); + + if (privnet == NULL) { + testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (virNetworkIsActive(privnet)) { + testError(network->conn, VIR_ERR_INTERNAL_ERROR, + _("Network '%s' is still running"), network->name); + goto cleanup; + } + + virNetworkRemoveInactive(&privconn->networks, + privnet); + privnet = NULL; + ret = 0; + +cleanup: + if (privnet) + virNetworkObjUnlock(privnet); + testDriverUnlock(privconn); + return ret; +} + +static int testNetworkStart(virNetworkPtr network) { + testConnPtr privconn = network->conn->privateData; + virNetworkObjPtr privnet; + int ret = -1; + + testDriverLock(privconn); + privnet = virNetworkFindByName(&privconn->networks, + network->name); + testDriverUnlock(privconn); + + if (privnet == NULL) { + testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (virNetworkIsActive(privnet)) { + testError(network->conn, VIR_ERR_INTERNAL_ERROR, + _("Network '%s' is already running"), network->name); + goto cleanup; + } + + privnet->active = 1; + ret = 0; + +cleanup: + if (privnet) + virNetworkObjUnlock(privnet); + return ret; +} + +static int testNetworkDestroy(virNetworkPtr network) { + testConnPtr privconn = network->conn->privateData; + virNetworkObjPtr privnet; + int ret = -1; + + testDriverLock(privconn); + privnet = virNetworkFindByName(&privconn->networks, + network->name); + + if (privnet == NULL) { + testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + privnet->active = 0; + if (!privnet->persistent) { + virNetworkRemoveInactive(&privconn->networks, + privnet); + privnet = NULL; + } + ret = 0; + +cleanup: + if (privnet) + virNetworkObjUnlock(privnet); + testDriverUnlock(privconn); + return ret; +} + +static char *testNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) { + testConnPtr privconn = network->conn->privateData; + virNetworkObjPtr privnet; + char *ret = NULL; + + testDriverLock(privconn); + privnet = virNetworkFindByName(&privconn->networks, + network->name); + testDriverUnlock(privconn); + + if (privnet == NULL) { + testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + ret = virNetworkDefFormat(network->conn, privnet->def); + +cleanup: + if (privnet) + virNetworkObjUnlock(privnet); + return ret; +} + +static char *testNetworkGetBridgeName(virNetworkPtr network) { + testConnPtr privconn = network->conn->privateData; + char *bridge = NULL; + virNetworkObjPtr privnet; + + testDriverLock(privconn); + privnet = virNetworkFindByName(&privconn->networks, + network->name); + testDriverUnlock(privconn); + + if (privnet == NULL) { + testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (privnet->def->bridge && + !(bridge = strdup(privnet->def->bridge))) { + virReportOOMError(network->conn); + goto cleanup; + } + +cleanup: + if (privnet) + virNetworkObjUnlock(privnet); + return bridge; +} + +static int testNetworkGetAutostart(virNetworkPtr network, + int *autostart) { + testConnPtr privconn = network->conn->privateData; + virNetworkObjPtr privnet; + int ret = -1; + + testDriverLock(privconn); + privnet = virNetworkFindByName(&privconn->networks, + network->name); + testDriverUnlock(privconn); + + if (privnet == NULL) { + testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + *autostart = privnet->autostart; + ret = 0; + +cleanup: + if (privnet) + virNetworkObjUnlock(privnet); + return ret; +} + +static int testNetworkSetAutostart(virNetworkPtr network, + int autostart) { + testConnPtr privconn = network->conn->privateData; + virNetworkObjPtr privnet; + int ret = -1; + + testDriverLock(privconn); + privnet = virNetworkFindByName(&privconn->networks, + network->name); + testDriverUnlock(privconn); + + if (privnet == NULL) { + testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + privnet->autostart = autostart ? 1 : 0; + ret = 0; + +cleanup: + if (privnet) + virNetworkObjUnlock(privnet); + return ret; +} + + +/* + * Physical host interface routines + */ + +static virDrvOpenStatus testOpenInterface(virConnectPtr conn, + virConnectAuthPtr auth ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED) +{ + if (STRNEQ(conn->driver->name, "Test")) + return VIR_DRV_OPEN_DECLINED; + + conn->interfacePrivateData = conn->privateData; + return VIR_DRV_OPEN_SUCCESS; +} + +static int testCloseInterface(virConnectPtr conn) +{ + conn->interfacePrivateData = NULL; + return 0; +} + + +static int testNumOfInterfaces(virConnectPtr conn) +{ + testConnPtr privconn = conn->privateData; + int i, count = 0; + + testDriverLock(privconn); + for (i = 0 ; (i < privconn->ifaces.count); i++) { + virInterfaceObjLock(privconn->ifaces.objs[i]); + if (virInterfaceIsActive(privconn->ifaces.objs[i])) { + count++; + } + virInterfaceObjUnlock(privconn->ifaces.objs[i]); + } + testDriverUnlock(privconn); + return count; +} + +static int testListInterfaces(virConnectPtr conn, char **const names, int nnames) +{ + testConnPtr privconn = conn->privateData; + int n = 0, i; + + testDriverLock(privconn); + memset(names, 0, sizeof(*names)*nnames); + for (i = 0 ; (i < privconn->ifaces.count) && (n < nnames); i++) { + virInterfaceObjLock(privconn->ifaces.objs[i]); + if (virInterfaceIsActive(privconn->ifaces.objs[i])) { + if (!(names[n++] = strdup(privconn->ifaces.objs[i]->def->name))) { + virInterfaceObjUnlock(privconn->ifaces.objs[i]); + goto no_memory; + } + } + virInterfaceObjUnlock(privconn->ifaces.objs[i]); + } + testDriverUnlock(privconn); + + return n; + +no_memory: + virReportOOMError(conn); + for (n = 0 ; n < nnames ; n++) + VIR_FREE(names[n]); + testDriverUnlock(privconn); + return -1; +} + +static int testNumOfDefinedInterfaces(virConnectPtr conn) +{ + testConnPtr privconn = conn->privateData; + int i, count = 0; + + testDriverLock(privconn); + for (i = 0 ; i < privconn->ifaces.count; i++) { + virInterfaceObjLock(privconn->ifaces.objs[i]); + if (!virInterfaceIsActive(privconn->ifaces.objs[i])) { + count++; + } + virInterfaceObjUnlock(privconn->ifaces.objs[i]); + } + testDriverUnlock(privconn); + return count; +} + +static int testListDefinedInterfaces(virConnectPtr conn, char **const names, int nnames) +{ + testConnPtr privconn = conn->privateData; + int n = 0, i; + + testDriverLock(privconn); + memset(names, 0, sizeof(*names)*nnames); + for (i = 0 ; (i < privconn->ifaces.count) && (n < nnames); i++) { + virInterfaceObjLock(privconn->ifaces.objs[i]); + if (!virInterfaceIsActive(privconn->ifaces.objs[i])) { + if (!(names[n++] = strdup(privconn->ifaces.objs[i]->def->name))) { + virInterfaceObjUnlock(privconn->ifaces.objs[i]); + goto no_memory; + } + } + virInterfaceObjUnlock(privconn->ifaces.objs[i]); + } + testDriverUnlock(privconn); + + return n; + +no_memory: + virReportOOMError(conn); + for (n = 0 ; n < nnames ; n++) + VIR_FREE(names[n]); + testDriverUnlock(privconn); + return -1; +} + +static virInterfacePtr testLookupInterfaceByName(virConnectPtr conn, + const char *name) +{ + testConnPtr privconn = conn->privateData; + virInterfaceObjPtr iface; + virInterfacePtr ret = NULL; + + testDriverLock(privconn); + iface = virInterfaceFindByName(&privconn->ifaces, name); + testDriverUnlock(privconn); + + if (iface == NULL) { + testError (conn, VIR_ERR_NO_INTERFACE, NULL); + goto cleanup; + } + + ret = virGetInterface(conn, iface->def->name, iface->def->mac); + +cleanup: + if (iface) + virInterfaceObjUnlock(iface); + return ret; +} + +static virInterfacePtr testLookupInterfaceByMACString(virConnectPtr conn, + const char *mac) +{ + testConnPtr privconn = conn->privateData; + virInterfaceObjPtr iface; + int ifacect; + virInterfacePtr ret = NULL; + + testDriverLock(privconn); + ifacect = virInterfaceFindByMACString(&privconn->ifaces, mac, &iface, 1); + testDriverUnlock(privconn); + + if (ifacect == 0) { + testError (conn, VIR_ERR_NO_INTERFACE, NULL); + goto cleanup; + } + + if (ifacect > 1) { + testError (conn, VIR_ERR_MULTIPLE_INTERFACES, NULL); + goto cleanup; + } + + ret = virGetInterface(conn, iface->def->name, iface->def->mac); + +cleanup: + if (iface) + virInterfaceObjUnlock(iface); + return ret; +} + +static char *testInterfaceGetXMLDesc(virInterfacePtr iface, + unsigned int flags ATTRIBUTE_UNUSED) +{ + testConnPtr privconn = iface->conn->privateData; + virInterfaceObjPtr privinterface; + char *ret = NULL; + + testDriverLock(privconn); + privinterface = virInterfaceFindByName(&privconn->ifaces, + iface->name); + testDriverUnlock(privconn); + + if (privinterface == NULL) { + testError(iface->conn, VIR_ERR_NO_INTERFACE, __FUNCTION__); + goto cleanup; + } + + ret = virInterfaceDefFormat(iface->conn, privinterface->def); + +cleanup: + if (privinterface) + virInterfaceObjUnlock(privinterface); + return ret; +} + + +static virInterfacePtr testInterfaceDefineXML(virConnectPtr conn, const char *xmlStr, + unsigned int flags ATTRIBUTE_UNUSED) +{ + testConnPtr privconn = conn->privateData; + virInterfaceDefPtr def; + virInterfaceObjPtr iface = NULL; + virInterfacePtr ret = NULL; + + testDriverLock(privconn); + if ((def = virInterfaceDefParseString(conn, xmlStr)) == NULL) + goto cleanup; + + if ((iface = virInterfaceAssignDef(conn, &privconn->ifaces, def)) == NULL) + goto cleanup; + def = NULL; + + ret = virGetInterface(conn, iface->def->name, iface->def->mac); + +cleanup: + virInterfaceDefFree(def); + if (iface) + virInterfaceObjUnlock(iface); + testDriverUnlock(privconn); + return ret; +} + +static int testInterfaceUndefine(virInterfacePtr iface) +{ + testConnPtr privconn = iface->conn->privateData; + virInterfaceObjPtr privinterface; + int ret = -1; + + testDriverLock(privconn); + privinterface = virInterfaceFindByName(&privconn->ifaces, + iface->name); + + if (privinterface == NULL) { + testError (iface->conn, VIR_ERR_NO_INTERFACE, NULL); + goto cleanup; + } + + virInterfaceRemove(&privconn->ifaces, + privinterface); + ret = 0; + +cleanup: + testDriverUnlock(privconn); + return ret; +} + +static int testInterfaceCreate(virInterfacePtr iface, + unsigned int flags ATTRIBUTE_UNUSED) +{ + testConnPtr privconn = iface->conn->privateData; + virInterfaceObjPtr privinterface; + int ret = -1; + + testDriverLock(privconn); + privinterface = virInterfaceFindByName(&privconn->ifaces, + iface->name); + + if (privinterface == NULL) { + testError (iface->conn, VIR_ERR_NO_INTERFACE, NULL); + goto cleanup; + } + + if (privinterface->active != 0) { + testError (iface->conn, VIR_ERR_OPERATION_INVALID, NULL); + goto cleanup; + } + + privinterface->active = 1; + ret = 0; + +cleanup: + if (privinterface) + virInterfaceObjUnlock(privinterface); + testDriverUnlock(privconn); + return ret; +} + +static int testInterfaceDestroy(virInterfacePtr iface, + unsigned int flags ATTRIBUTE_UNUSED) +{ + testConnPtr privconn = iface->conn->privateData; + virInterfaceObjPtr privinterface; + int ret = -1; + + testDriverLock(privconn); + privinterface = virInterfaceFindByName(&privconn->ifaces, + iface->name); + + if (privinterface == NULL) { + testError (iface->conn, VIR_ERR_NO_INTERFACE, NULL); + goto cleanup; + } + + if (privinterface->active == 0) { + testError (iface->conn, VIR_ERR_OPERATION_INVALID, NULL); + goto cleanup; + } + + privinterface->active = 0; + ret = 0; + +cleanup: + if (privinterface) + virInterfaceObjUnlock(privinterface); + testDriverUnlock(privconn); + return ret; +} + + + +/* + * Storage Driver routines + */ + +static int testStoragePoolObjSetDefaults(virConnectPtr conn, + virStoragePoolObjPtr pool) { + + pool->def->capacity = defaultPoolCap; + pool->def->allocation = defaultPoolAlloc; + pool->def->available = defaultPoolCap - defaultPoolAlloc; + + pool->configFile = strdup("\0"); + if (!pool->configFile) { + virReportOOMError(conn); + return -1; + } + + return 0; +} + +static virDrvOpenStatus testStorageOpen(virConnectPtr conn, + virConnectAuthPtr auth ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED) { + if (STRNEQ(conn->driver->name, "Test")) + return VIR_DRV_OPEN_DECLINED; + + conn->storagePrivateData = conn->privateData; + return VIR_DRV_OPEN_SUCCESS; +} + +static int testStorageClose(virConnectPtr conn) { + conn->storagePrivateData = NULL; + return 0; +} + +static virStoragePoolPtr +testStoragePoolLookupByUUID(virConnectPtr conn, + const unsigned char *uuid) { + testConnPtr privconn = conn->privateData; + virStoragePoolObjPtr pool; + virStoragePoolPtr ret = NULL; + + testDriverLock(privconn); + pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid); + testDriverUnlock(privconn); + + if (pool == NULL) { + testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL); + goto cleanup; + } + + ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); + +cleanup: + if (pool) + virStoragePoolObjUnlock(pool); + return ret; +} + +static virStoragePoolPtr +testStoragePoolLookupByName(virConnectPtr conn, + const char *name) { + testConnPtr privconn = conn->privateData; + virStoragePoolObjPtr pool; + virStoragePoolPtr ret = NULL; + + testDriverLock(privconn); + pool = virStoragePoolObjFindByName(&privconn->pools, name); + testDriverUnlock(privconn); + + if (pool == NULL) { + testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL); + goto cleanup; + } + + ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); + +cleanup: + if (pool) + virStoragePoolObjUnlock(pool); + return ret; +} + +static virStoragePoolPtr +testStoragePoolLookupByVolume(virStorageVolPtr vol) { + return testStoragePoolLookupByName(vol->conn, vol->pool); +} + +static int +testStorageNumPools(virConnectPtr conn) { + testConnPtr privconn = conn->privateData; + int numActive = 0, i; + + testDriverLock(privconn); + for (i = 0 ; i < privconn->pools.count ; i++) + if (virStoragePoolObjIsActive(privconn->pools.objs[i])) + numActive++; + testDriverUnlock(privconn); + + return numActive; +} + +static int +testStorageListPools(virConnectPtr conn, + char **const names, + int nnames) { + testConnPtr privconn = conn->privateData; + int n = 0, i; + + testDriverLock(privconn); + memset(names, 0, sizeof(*names)*nnames); + for (i = 0 ; i < privconn->pools.count && n < nnames ; i++) { + virStoragePoolObjLock(privconn->pools.objs[i]); + if (virStoragePoolObjIsActive(privconn->pools.objs[i]) && + !(names[n++] = strdup(privconn->pools.objs[i]->def->name))) { + virStoragePoolObjUnlock(privconn->pools.objs[i]); + goto no_memory; + } + virStoragePoolObjUnlock(privconn->pools.objs[i]); + } + testDriverUnlock(privconn); + + return n; + +no_memory: + virReportOOMError(conn); + for (n = 0 ; n < nnames ; n++) + VIR_FREE(names[n]); + testDriverUnlock(privconn); + return -1; +} + +static int +testStorageNumDefinedPools(virConnectPtr conn) { + testConnPtr privconn = conn->privateData; + int numInactive = 0, i; + + testDriverLock(privconn); + for (i = 0 ; i < privconn->pools.count ; i++) { + virStoragePoolObjLock(privconn->pools.objs[i]); + if (!virStoragePoolObjIsActive(privconn->pools.objs[i])) + numInactive++; + virStoragePoolObjUnlock(privconn->pools.objs[i]); + } + testDriverUnlock(privconn); + + return numInactive; +} + +static int +testStorageListDefinedPools(virConnectPtr conn, + char **const names, + int nnames) { + testConnPtr privconn = conn->privateData; + int n = 0, i; + + testDriverLock(privconn); + memset(names, 0, sizeof(*names)*nnames); + for (i = 0 ; i < privconn->pools.count && n < nnames ; i++) { + virStoragePoolObjLock(privconn->pools.objs[i]); + if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) && + !(names[n++] = strdup(privconn->pools.objs[i]->def->name))) { + virStoragePoolObjUnlock(privconn->pools.objs[i]); + goto no_memory; + } + virStoragePoolObjUnlock(privconn->pools.objs[i]); + } + testDriverUnlock(privconn); + + return n; + +no_memory: + virReportOOMError(conn); + for (n = 0 ; n < nnames ; n++) + VIR_FREE(names[n]); + testDriverUnlock(privconn); + return -1; +} + + +static int +testStoragePoolStart(virStoragePoolPtr pool, + unsigned int flags ATTRIBUTE_UNUSED) { + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + int ret = -1; + + testDriverLock(privconn); + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + testDriverUnlock(privconn); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is already active"), pool->name); + goto cleanup; + } + + privpool->active = 1; + ret = 0; + +cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); + return ret; +} + +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) { + testConnPtr privconn = conn->privateData; + virStoragePoolDefPtr def; + virStoragePoolObjPtr pool = NULL; + virStoragePoolPtr ret = NULL; + + testDriverLock(privconn); + if (!(def = virStoragePoolDefParseString(conn, xml))) + goto cleanup; + + pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid); + if (!pool) + pool = virStoragePoolObjFindByName(&privconn->pools, def->name); + if (pool) { + testError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("storage pool already exists")); + goto cleanup; + } + + if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, def))) + goto cleanup; + def = NULL; + + if (testStoragePoolObjSetDefaults(conn, pool) == -1) { + virStoragePoolObjRemove(&privconn->pools, pool); + pool = NULL; + goto cleanup; + } + pool->active = 1; + + ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); + +cleanup: + virStoragePoolDefFree(def); + if (pool) + virStoragePoolObjUnlock(pool); + testDriverUnlock(privconn); + return ret; +} + +static virStoragePoolPtr +testStoragePoolDefine(virConnectPtr conn, + const char *xml, + unsigned int flags ATTRIBUTE_UNUSED) { + testConnPtr privconn = conn->privateData; + virStoragePoolDefPtr def; + virStoragePoolObjPtr pool = NULL; + virStoragePoolPtr ret = NULL; + + testDriverLock(privconn); + if (!(def = virStoragePoolDefParseString(conn, xml))) + goto cleanup; + + def->capacity = defaultPoolCap; + def->allocation = defaultPoolAlloc; + def->available = defaultPoolCap - defaultPoolAlloc; + + if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, def))) + goto cleanup; + def = NULL; + + if (testStoragePoolObjSetDefaults(conn, pool) == -1) { + virStoragePoolObjRemove(&privconn->pools, pool); + pool = NULL; + goto cleanup; + } + + ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); + +cleanup: + virStoragePoolDefFree(def); + if (pool) + virStoragePoolObjUnlock(pool); + testDriverUnlock(privconn); + return ret; +} + +static int +testStoragePoolUndefine(virStoragePoolPtr pool) { + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + int ret = -1; + + testDriverLock(privconn); + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is already active"), pool->name); + goto cleanup; + } + + virStoragePoolObjRemove(&privconn->pools, privpool); + ret = 0; + +cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); + testDriverUnlock(privconn); + return ret; +} + +static int +testStoragePoolBuild(virStoragePoolPtr pool, + unsigned int flags ATTRIBUTE_UNUSED) { + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + int ret = -1; + + testDriverLock(privconn); + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + testDriverUnlock(privconn); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is already active"), pool->name); + goto cleanup; + } + ret = 0; + +cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); + return ret; +} + + +static int +testStoragePoolDestroy(virStoragePoolPtr pool) { + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + int ret = -1; + + testDriverLock(privconn); + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (!virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), pool->name); + goto cleanup; + } + + privpool->active = 0; + + if (privpool->configFile == NULL) { + virStoragePoolObjRemove(&privconn->pools, privpool); + privpool = NULL; + } + ret = 0; + +cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); + testDriverUnlock(privconn); + return ret; +} + + +static int +testStoragePoolDelete(virStoragePoolPtr pool, + unsigned int flags ATTRIBUTE_UNUSED) { + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + int ret = -1; + + testDriverLock(privconn); + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + testDriverUnlock(privconn); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is already active"), pool->name); + goto cleanup; + } + + ret = 0; + +cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); + return ret; +} + + +static int +testStoragePoolRefresh(virStoragePoolPtr pool, + unsigned int flags ATTRIBUTE_UNUSED) { + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + int ret = -1; + + testDriverLock(privconn); + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + testDriverUnlock(privconn); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (!virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), pool->name); + goto cleanup; + } + ret = 0; + +cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); + return ret; +} + + +static int +testStoragePoolGetInfo(virStoragePoolPtr pool, + virStoragePoolInfoPtr info) { + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + int ret = -1; + + testDriverLock(privconn); + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + testDriverUnlock(privconn); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + 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; + ret = 0; + +cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); + return ret; +} + +static char * +testStoragePoolDumpXML(virStoragePoolPtr pool, + unsigned int flags ATTRIBUTE_UNUSED) { + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + char *ret = NULL; + + testDriverLock(privconn); + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + testDriverUnlock(privconn); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + ret = virStoragePoolDefFormat(pool->conn, privpool->def); + +cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); + return ret; +} + +static int +testStoragePoolGetAutostart(virStoragePoolPtr pool, + int *autostart) { + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + int ret = -1; + + testDriverLock(privconn); + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + testDriverUnlock(privconn); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (!privpool->configFile) { + *autostart = 0; + } else { + *autostart = privpool->autostart; + } + ret = 0; + +cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); + return ret; +} + +static int +testStoragePoolSetAutostart(virStoragePoolPtr pool, + int autostart) { + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + int ret = -1; + + testDriverLock(privconn); + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + testDriverUnlock(privconn); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (!privpool->configFile) { + testError(pool->conn, VIR_ERR_INVALID_ARG, + "%s", _("pool has no config file")); + goto cleanup; + } + + autostart = (autostart != 0); + privpool->autostart = autostart; + ret = 0; + +cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); + return ret; +} + + +static int +testStoragePoolNumVolumes(virStoragePoolPtr pool) { + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + int ret = -1; + + testDriverLock(privconn); + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + testDriverUnlock(privconn); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (!virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), pool->name); + goto cleanup; + } + + ret = privpool->volumes.count; + +cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); + return ret; +} + +static int +testStoragePoolListVolumes(virStoragePoolPtr pool, + char **const names, + int maxnames) { + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + int i = 0, n = 0; + + memset(names, 0, maxnames * sizeof(*names)); + + testDriverLock(privconn); + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + testDriverUnlock(privconn); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + + if (!virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), pool->name); + goto cleanup; + } + + for (i = 0 ; i < privpool->volumes.count && n < maxnames ; i++) { + if ((names[n++] = strdup(privpool->volumes.objs[i]->name)) == NULL) { + virReportOOMError(pool->conn); + goto cleanup; + } + } + + virStoragePoolObjUnlock(privpool); + return n; + + cleanup: + for (n = 0 ; n < maxnames ; n++) + VIR_FREE(names[i]); + + memset(names, 0, maxnames * sizeof(*names)); + if (privpool) + virStoragePoolObjUnlock(privpool); + return -1; +} + + +static virStorageVolPtr +testStorageVolumeLookupByName(virStoragePoolPtr pool, + const char *name ATTRIBUTE_UNUSED) { + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + virStorageVolDefPtr privvol; + virStorageVolPtr ret = NULL; + + testDriverLock(privconn); + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + testDriverUnlock(privconn); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + + if (!virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), pool->name); + goto cleanup; + } + + privvol = virStorageVolDefFindByName(privpool, name); + + if (!privvol) { + testError(pool->conn, VIR_ERR_INVALID_STORAGE_VOL, + _("no storage vol with matching name '%s'"), name); + goto cleanup; + } + + ret = virGetStorageVol(pool->conn, privpool->def->name, + privvol->name, privvol->key); + +cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); + return ret; +} + + +static virStorageVolPtr +testStorageVolumeLookupByKey(virConnectPtr conn, + const char *key) { + testConnPtr privconn = conn->privateData; + unsigned int i; + virStorageVolPtr ret = NULL; + + testDriverLock(privconn); + for (i = 0 ; i < privconn->pools.count ; i++) { + virStoragePoolObjLock(privconn->pools.objs[i]); + if (virStoragePoolObjIsActive(privconn->pools.objs[i])) { + virStorageVolDefPtr privvol = + virStorageVolDefFindByKey(privconn->pools.objs[i], key); + + if (privvol) { + ret = virGetStorageVol(conn, + privconn->pools.objs[i]->def->name, + privvol->name, + privvol->key); + virStoragePoolObjUnlock(privconn->pools.objs[i]); + break; + } + } + virStoragePoolObjUnlock(privconn->pools.objs[i]); + } + testDriverUnlock(privconn); + + if (!ret) + testError(conn, VIR_ERR_INVALID_STORAGE_VOL, + _("no storage vol with matching key '%s'"), key); + + return ret; +} + +static virStorageVolPtr +testStorageVolumeLookupByPath(virConnectPtr conn, + const char *path) { + testConnPtr privconn = conn->privateData; + unsigned int i; + virStorageVolPtr ret = NULL; + + testDriverLock(privconn); + for (i = 0 ; i < privconn->pools.count ; i++) { + virStoragePoolObjLock(privconn->pools.objs[i]); + if (virStoragePoolObjIsActive(privconn->pools.objs[i])) { + virStorageVolDefPtr privvol = + virStorageVolDefFindByPath(privconn->pools.objs[i], path); + + if (privvol) { + ret = virGetStorageVol(conn, + privconn->pools.objs[i]->def->name, + privvol->name, + privvol->key); + virStoragePoolObjUnlock(privconn->pools.objs[i]); + break; + } + } + virStoragePoolObjUnlock(privconn->pools.objs[i]); + } + testDriverUnlock(privconn); + + if (!ret) + testError(conn, VIR_ERR_INVALID_STORAGE_VOL, + _("no storage vol with matching path '%s'"), path); + + return ret; +} + +static virStorageVolPtr +testStorageVolumeCreateXML(virStoragePoolPtr pool, + const char *xmldesc, + unsigned int flags ATTRIBUTE_UNUSED) { + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + virStorageVolDefPtr privvol = NULL; + virStorageVolPtr ret = NULL; + + testDriverLock(privconn); + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + testDriverUnlock(privconn); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (!virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), pool->name); + goto cleanup; + } + + privvol = virStorageVolDefParseString(pool->conn, privpool->def, xmldesc); + if (privvol == NULL) + goto cleanup; + + if (virStorageVolDefFindByName(privpool, privvol->name)) { + testError(pool->conn, VIR_ERR_INVALID_STORAGE_VOL, + "%s", _("storage vol already exists")); + goto cleanup; + } + + /* Make sure enough space */ + if ((privpool->def->allocation + privvol->allocation) > + privpool->def->capacity) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("Not enough free space in pool for volume '%s'"), + privvol->name); + goto cleanup; + } + + if (VIR_REALLOC_N(privpool->volumes.objs, + privpool->volumes.count+1) < 0) { + virReportOOMError(pool->conn); + goto cleanup; + } + + if (virAsprintf(&privvol->target.path, "%s/%s", + privpool->def->target.path, + privvol->name) == -1) { + virReportOOMError(pool->conn); + goto cleanup; + } + + privvol->key = strdup(privvol->target.path); + if (privvol->key == NULL) { + virReportOOMError(pool->conn); + goto cleanup; + } + + privpool->def->allocation += privvol->allocation; + privpool->def->available = (privpool->def->capacity - + privpool->def->allocation); + + privpool->volumes.objs[privpool->volumes.count++] = privvol; + + ret = virGetStorageVol(pool->conn, privpool->def->name, + privvol->name, privvol->key); + privvol = NULL; + +cleanup: + virStorageVolDefFree(privvol); + if (privpool) + virStoragePoolObjUnlock(privpool); + return ret; +} + +static virStorageVolPtr +testStorageVolumeCreateXMLFrom(virStoragePoolPtr pool, + const char *xmldesc, + virStorageVolPtr clonevol, + unsigned int flags ATTRIBUTE_UNUSED) { + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + virStorageVolDefPtr privvol = NULL, origvol = NULL; + virStorageVolPtr ret = NULL; + + testDriverLock(privconn); + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + testDriverUnlock(privconn); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + if (!virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), pool->name); + goto cleanup; + } + + privvol = virStorageVolDefParseString(pool->conn, privpool->def, xmldesc); + if (privvol == NULL) + goto cleanup; + + if (virStorageVolDefFindByName(privpool, privvol->name)) { + testError(pool->conn, VIR_ERR_INVALID_STORAGE_VOL, + "%s", _("storage vol already exists")); + goto cleanup; + } + + origvol = virStorageVolDefFindByName(privpool, clonevol->name); + if (!origvol) { + testError(pool->conn, VIR_ERR_INVALID_STORAGE_VOL, + _("no storage vol with matching name '%s'"), + clonevol->name); + goto cleanup; + } + + /* Make sure enough space */ + if ((privpool->def->allocation + privvol->allocation) > + privpool->def->capacity) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("Not enough free space in pool for volume '%s'"), + privvol->name); + goto cleanup; + } + privpool->def->available = (privpool->def->capacity - + privpool->def->allocation); + + if (VIR_REALLOC_N(privpool->volumes.objs, + privpool->volumes.count+1) < 0) { + virReportOOMError(pool->conn); + goto cleanup; + } + + if (virAsprintf(&privvol->target.path, "%s/%s", + privpool->def->target.path, + privvol->name) == -1) { + virReportOOMError(pool->conn); + goto cleanup; + } + + privvol->key = strdup(privvol->target.path); + if (privvol->key == NULL) { + virReportOOMError(pool->conn); + goto cleanup; + } + + privpool->def->allocation += privvol->allocation; + privpool->def->available = (privpool->def->capacity - + privpool->def->allocation); + + privpool->volumes.objs[privpool->volumes.count++] = privvol; + + ret = virGetStorageVol(pool->conn, privpool->def->name, + privvol->name, privvol->key); + privvol = NULL; + +cleanup: + virStorageVolDefFree(privvol); + if (privpool) + virStoragePoolObjUnlock(privpool); + return ret; +} + +static int +testStorageVolumeDelete(virStorageVolPtr vol, + unsigned int flags ATTRIBUTE_UNUSED) { + testConnPtr privconn = vol->conn->privateData; + virStoragePoolObjPtr privpool; + virStorageVolDefPtr privvol; + int i; + int ret = -1; + + testDriverLock(privconn); + privpool = virStoragePoolObjFindByName(&privconn->pools, + vol->pool); + testDriverUnlock(privconn); + + if (privpool == NULL) { + testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + + privvol = virStorageVolDefFindByName(privpool, vol->name); + + if (privvol == NULL) { + testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL, + _("no storage vol with matching name '%s'"), + vol->name); + goto cleanup; + } + + if (!virStoragePoolObjIsActive(privpool)) { + testError(vol->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), vol->pool); + goto cleanup; + } + + + 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; + } + } + ret = 0; + +cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); + return ret; +} + + +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 vol, + virStorageVolInfoPtr info) { + testConnPtr privconn = vol->conn->privateData; + virStoragePoolObjPtr privpool; + virStorageVolDefPtr privvol; + int ret = -1; + + testDriverLock(privconn); + privpool = virStoragePoolObjFindByName(&privconn->pools, + vol->pool); + testDriverUnlock(privconn); + + if (privpool == NULL) { + testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + privvol = virStorageVolDefFindByName(privpool, vol->name); + + if (privvol == NULL) { + testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL, + _("no storage vol with matching name '%s'"), + vol->name); + goto cleanup; + } + + if (!virStoragePoolObjIsActive(privpool)) { + testError(vol->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), vol->pool); + goto cleanup; + } + + memset(info, 0, sizeof(*info)); + info->type = testStorageVolumeTypeForPool(privpool->def->type); + info->capacity = privvol->capacity; + info->allocation = privvol->allocation; + ret = 0; + +cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); + return ret; +} + +static char * +testStorageVolumeGetXMLDesc(virStorageVolPtr vol, + unsigned int flags ATTRIBUTE_UNUSED) { + testConnPtr privconn = vol->conn->privateData; + virStoragePoolObjPtr privpool; + virStorageVolDefPtr privvol; + char *ret = NULL; + + testDriverLock(privconn); + privpool = virStoragePoolObjFindByName(&privconn->pools, + vol->pool); + testDriverUnlock(privconn); + + if (privpool == NULL) { + testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + privvol = virStorageVolDefFindByName(privpool, vol->name); + + if (privvol == NULL) { + testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL, + _("no storage vol with matching name '%s'"), + vol->name); + goto cleanup; + } + + if (!virStoragePoolObjIsActive(privpool)) { + testError(vol->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), vol->pool); + goto cleanup; + } + + ret = virStorageVolDefFormat(vol->conn, privpool->def, privvol); + +cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); + return ret; +} + +static char * +testStorageVolumeGetPath(virStorageVolPtr vol) { + testConnPtr privconn = vol->conn->privateData; + virStoragePoolObjPtr privpool; + virStorageVolDefPtr privvol; + char *ret = NULL; + + testDriverLock(privconn); + privpool = virStoragePoolObjFindByName(&privconn->pools, + vol->pool); + testDriverUnlock(privconn); + + if (privpool == NULL) { + testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + privvol = virStorageVolDefFindByName(privpool, vol->name); + + if (privvol == NULL) { + testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL, + _("no storage vol with matching name '%s'"), + vol->name); + goto cleanup; + } + + if (!virStoragePoolObjIsActive(privpool)) { + testError(vol->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), vol->pool); + goto cleanup; + } + + ret = strdup(privvol->target.path); + if (ret == NULL) + virReportOOMError(vol->conn); + +cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); + return ret; +} + + +static virDrvOpenStatus testDevMonOpen(virConnectPtr conn, + virConnectAuthPtr auth ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED) { + if (STRNEQ(conn->driver->name, "Test")) + return VIR_DRV_OPEN_DECLINED; + + conn->devMonPrivateData = conn->privateData; + return VIR_DRV_OPEN_SUCCESS; +} + +static int testDevMonClose(virConnectPtr conn) { + conn->devMonPrivateData = NULL; + return 0; +} + + +static int +testDomainEventRegister (virConnectPtr conn, + virConnectDomainEventCallback callback, + void *opaque, + virFreeCallback freecb) +{ + testConnPtr driver = conn->privateData; + int ret; + + testDriverLock(driver); + ret = virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks, + callback, opaque, freecb); + testDriverUnlock(driver); + + return ret; +} + +static int +testDomainEventDeregister (virConnectPtr conn, + virConnectDomainEventCallback callback) +{ + testConnPtr driver = conn->privateData; + int ret; + + testDriverLock(driver); + if (driver->domainEventDispatching) + ret = virDomainEventCallbackListMarkDelete(conn, driver->domainEventCallbacks, + callback); + else + ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks, + callback); + testDriverUnlock(driver); + + return ret; +} + +static void testDomainEventDispatchFunc(virConnectPtr conn, + virDomainEventPtr event, + virConnectDomainEventCallback cb, + void *cbopaque, + void *opaque) +{ + testConnPtr driver = opaque; + + /* Drop the lock whle dispatching, for sake of re-entrancy */ + testDriverUnlock(driver); + virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL); + testDriverLock(driver); +} + +static void testDomainEventFlush(int timer ATTRIBUTE_UNUSED, void *opaque) +{ + testConnPtr driver = opaque; + virDomainEventQueue tempQueue; + + testDriverLock(driver); + + driver->domainEventDispatching = 1; + + /* Copy the queue, so we're reentrant safe */ + tempQueue.count = driver->domainEventQueue->count; + tempQueue.events = driver->domainEventQueue->events; + driver->domainEventQueue->count = 0; + driver->domainEventQueue->events = NULL; + + virEventUpdateTimeout(driver->domainEventTimer, -1); + virDomainEventQueueDispatch(&tempQueue, + driver->domainEventCallbacks, + testDomainEventDispatchFunc, + driver); + + /* Purge any deleted callbacks */ + virDomainEventCallbackListPurgeMarked(driver->domainEventCallbacks); + + driver->domainEventDispatching = 0; + testDriverUnlock(driver); +} + + +/* driver must be locked before calling */ +static void testDomainEventQueue(testConnPtr driver, + virDomainEventPtr event) +{ + if (driver->domainEventTimer < 0) { + virDomainEventFree(event); + return; + } + + if (virDomainEventQueuePush(driver->domainEventQueue, + event) < 0) + virDomainEventFree(event); + + if (driver->domainEventQueue->count == 1) + virEventUpdateTimeout(driver->domainEventTimer, 0); +} + +static virDrvOpenStatus testSecretOpen(virConnectPtr conn, + virConnectAuthPtr auth ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED) { + if (STRNEQ(conn->driver->name, "Test")) + return VIR_DRV_OPEN_DECLINED; + + conn->secretPrivateData = conn->privateData; + return VIR_DRV_OPEN_SUCCESS; +} + +static int testSecretClose(virConnectPtr conn) { + conn->secretPrivateData = NULL; + return 0; +} + +static virDriver testDriver = { + VIR_DRV_TEST, + "Test", + testOpen, /* open */ + testClose, /* close */ + NULL, /* supports_feature */ + NULL, /* type */ + testGetVersion, /* version */ + testGetHostname, /* getHostname */ + testGetMaxVCPUs, /* getMaxVcpus */ + testNodeGetInfo, /* nodeGetInfo */ + testGetCapabilities, /* getCapabilities */ + testListDomains, /* listDomains */ + testNumOfDomains, /* numOfDomains */ + testDomainCreateXML, /* domainCreateXML */ + testLookupDomainByID, /* domainLookupByID */ + testLookupDomainByUUID, /* domainLookupByUUID */ + testLookupDomainByName, /* domainLookupByName */ + testPauseDomain, /* domainSuspend */ + testResumeDomain, /* domainResume */ + testShutdownDomain, /* domainShutdown */ + testRebootDomain, /* domainReboot */ + testDestroyDomain, /* domainDestroy */ + testGetOSType, /* domainGetOSType */ + testGetMaxMemory, /* domainGetMaxMemory */ + testSetMaxMemory, /* domainSetMaxMemory */ + testSetMemory, /* domainSetMemory */ + testGetDomainInfo, /* domainGetInfo */ + testDomainSave, /* domainSave */ + testDomainRestore, /* domainRestore */ + testDomainCoreDump, /* domainCoreDump */ + testSetVcpus, /* domainSetVcpus */ + NULL, /* domainPinVcpu */ + NULL, /* domainGetVcpus */ + NULL, /* domainGetMaxVcpus */ + NULL, /* domainGetSecurityLabel */ + NULL, /* nodeGetSecurityModel */ + testDomainDumpXML, /* domainDumpXML */ + NULL, /* domainXmlFromNative */ + NULL, /* domainXmlToNative */ + testListDefinedDomains, /* listDefinedDomains */ + testNumOfDefinedDomains, /* numOfDefinedDomains */ + testDomainCreate, /* domainCreate */ + testDomainDefineXML, /* domainDefineXML */ + testDomainUndefine, /* domainUndefine */ + NULL, /* domainAttachDevice */ + NULL, /* domainDetachDevice */ + testDomainGetAutostart, /* domainGetAutostart */ + testDomainSetAutostart, /* domainSetAutostart */ + testDomainGetSchedulerType, /* domainGetSchedulerType */ + testDomainGetSchedulerParams, /* domainGetSchedulerParameters */ + testDomainSetSchedulerParams, /* domainSetSchedulerParameters */ + NULL, /* domainMigratePrepare */ + NULL, /* domainMigratePerform */ + NULL, /* domainMigrateFinish */ + testDomainBlockStats, /* domainBlockStats */ + testDomainInterfaceStats, /* domainInterfaceStats */ + NULL, /* domainBlockPeek */ + NULL, /* domainMemoryPeek */ + testNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ + NULL, /* getFreeMemory */ + testDomainEventRegister, /* domainEventRegister */ + testDomainEventDeregister, /* domainEventDeregister */ + NULL, /* domainMigratePrepare2 */ + NULL, /* domainMigrateFinish2 */ + NULL, /* nodeDeviceDettach */ + NULL, /* nodeDeviceReAttach */ + NULL, /* nodeDeviceReset */ +}; + +static virNetworkDriver testNetworkDriver = { + "Test", + testOpenNetwork, /* open */ + testCloseNetwork, /* close */ + testNumNetworks, /* numOfNetworks */ + testListNetworks, /* listNetworks */ + testNumDefinedNetworks, /* numOfDefinedNetworks */ + testListDefinedNetworks, /* listDefinedNetworks */ + testLookupNetworkByUUID, /* networkLookupByUUID */ + testLookupNetworkByName, /* networkLookupByName */ + testNetworkCreate, /* networkCreateXML */ + testNetworkDefine, /* networkDefineXML */ + testNetworkUndefine, /* networkUndefine */ + testNetworkStart, /* networkCreate */ + testNetworkDestroy, /* networkDestroy */ + testNetworkDumpXML, /* networkDumpXML */ + testNetworkGetBridgeName, /* networkGetBridgeName */ + testNetworkGetAutostart, /* networkGetAutostart */ + testNetworkSetAutostart, /* networkSetAutostart */ +}; + +static virInterfaceDriver testInterfaceDriver = { + "Test", /* name */ + testOpenInterface, /* open */ + testCloseInterface, /* close */ + testNumOfInterfaces, /* numOfInterfaces */ + testListInterfaces, /* listInterfaces */ + testNumOfDefinedInterfaces, /* numOfDefinedInterfaces */ + testListDefinedInterfaces, /* listDefinedInterfaces */ + testLookupInterfaceByName, /* interfaceLookupByName */ + testLookupInterfaceByMACString, /* interfaceLookupByMACString */ + testInterfaceGetXMLDesc, /* interfaceGetXMLDesc */ + testInterfaceDefineXML, /* interfaceDefineXML */ + testInterfaceUndefine, /* interfaceUndefine */ + testInterfaceCreate, /* interfaceCreate */ + testInterfaceDestroy, /* interfaceDestroy */ +}; + + +static virStorageDriver testStorageDriver = { + .name = "Test", + .open = testStorageOpen, + .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, + .volCreateXMLFrom = testStorageVolumeCreateXMLFrom, + .volDelete = testStorageVolumeDelete, + .volGetInfo = testStorageVolumeGetInfo, + .volGetXMLDesc = testStorageVolumeGetXMLDesc, + .volGetPath = testStorageVolumeGetPath, +}; + +static virDeviceMonitor testDevMonitor = { + .name = "Test", + .open = testDevMonOpen, + .close = testDevMonClose, +}; + +static virSecretDriver testSecretDriver = { + .name = "Test", + .open = testSecretOpen, + .close = testSecretClose, +}; + + +/** + * testRegister: + * + * Registers the test driver + */ +int +testRegister(void) +{ + if (virRegisterDriver(&testDriver) < 0) + return -1; + if (virRegisterNetworkDriver(&testNetworkDriver) < 0) + return -1; + if (virRegisterInterfaceDriver(&testInterfaceDriver) < 0) + return -1; + if (virRegisterStorageDriver(&testStorageDriver) < 0) + return -1; + if (virRegisterDeviceMonitor(&testDevMonitor) < 0) + return -1; + if (virRegisterSecretDriver(&testSecretDriver) < 0) + return -1; + + return 0; +} diff --git a/src/test/test_driver.h b/src/test/test_driver.h new file mode 100644 index 0000000000..c6bdbd04dd --- /dev/null +++ b/src/test/test_driver.h @@ -0,0 +1,31 @@ +/* + * test.h: A "mock" hypervisor for use by application unit tests + * + * Copyright (C) 2006-2006 Red Hat, Inc. + * Copyright (C) 2006 Daniel P. Berrange + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Daniel Berrange + */ + +#ifndef __VIR_TEST_INTERNAL_H__ +#define __VIR_TEST_INTERNAL_H__ + +#include "internal.h" + +int testRegister(void); + +#endif /* __VIR_TEST_INTERNAL_H__ */