This adds support for the domain events in the test driver. Code
is following the same pattern as the impl in the QEMU driver.
test.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 217 insertions(+), 6 deletions(-)
Daniel
diff --git a/src/test.c b/src/test.c
--- a/src/test.c
+++ b/src/test.c
@@ -42,6 +42,8 @@
#include "memory.h"
#include "network_conf.h"
#include "domain_conf.h"
+#include "domain_event.h"
+#include "event.h"
#include "storage_conf.h"
#include "xml.h"
#include "threads.h"
@@ -72,6 +74,13 @@ struct _testConn {
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;
@@ -96,6 +105,12 @@ static const virNodeInfo defaultNodeInfo
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);
@@ -644,6 +659,23 @@ static virDrvOpenStatus testOpen(virConn
ret = testOpenFromFile(conn,
conn->uri->path);
+ if (ret == VIR_DRV_OPEN_SUCCESS) {
+ testConnPtr privconn = conn->privateData;
+ /* Init callback list */
+ if (VIR_ALLOC(privconn->domainEventCallbacks) < 0 ||
+ !(privconn->domainEventQueue = virDomainEventQueueNew())) {
+ virReportOOMError(NULL);
+ testClose(conn);
+ return VIR_DRV_OPEN_ERROR;
+ }
+
+ if ((privconn->domainEventTimer =
+ virEventAddTimeout(-1, testDomainEventFlush, privconn, NULL)) < 0) {
+ testClose(conn);
+ return VIR_DRV_OPEN_ERROR;
+ }
+ }
+
return (ret);
}
@@ -655,6 +687,13 @@ static int testClose(virConnectPtr conn)
virDomainObjListFree(&privconn->domains);
virNetworkObjListFree(&privconn->networks);
virStoragePoolObjListFree(&privconn->pools);
+
+ virDomainEventCallbackListFree(privconn->domainEventCallbacks);
+ virDomainEventQueueFree(privconn->domainEventQueue);
+
+ if (privconn->domainEventTimer != -1)
+ virEventRemoveTimeout(privconn->domainEventTimer);
+
testDriverUnlock(privconn);
virMutexDestroy(&privconn->lock);
@@ -733,6 +772,7 @@ testDomainCreateXML(virConnectPtr conn,
virDomainPtr ret = NULL;
virDomainDefPtr def;
virDomainObjPtr dom = NULL;
+ virDomainEventPtr event = NULL;
testDriverLock(privconn);
if ((def = virDomainDefParseString(conn, privconn->caps, xml,
@@ -747,6 +787,10 @@ testDomainCreateXML(virConnectPtr conn,
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, def->name, def->uuid);
if (ret)
ret->id = def->id;
@@ -754,6 +798,8 @@ testDomainCreateXML(virConnectPtr conn,
cleanup:
if (dom)
virDomainObjUnlock(dom);
+ if (event)
+ testDomainEventQueue(privconn, event);
testDriverUnlock(privconn);
return ret;
}
@@ -860,6 +906,7 @@ static int testDestroyDomain (virDomainP
{
testConnPtr privconn = domain->conn->privateData;
virDomainObjPtr privdom;
+ virDomainEventPtr event = NULL;
int ret = -1;
testDriverLock(privconn);
@@ -874,16 +921,22 @@ static int testDestroyDomain (virDomainP
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;
}
@@ -892,6 +945,7 @@ static int testResumeDomain (virDomainPt
{
testConnPtr privconn = domain->conn->privateData;
virDomainObjPtr privdom;
+ virDomainEventPtr event = NULL;
int ret = -1;
testDriverLock(privconn);
@@ -912,11 +966,18 @@ static int testResumeDomain (virDomainPt
}
privdom->state = VIR_DOMAIN_RUNNING;
+ event = virDomainEventNewFromObj(privdom,
+ VIR_DOMAIN_EVENT_RESUMED,
+ VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
ret = 0;
cleanup:
if (privdom)
virDomainObjUnlock(privdom);
+ testDriverLock(privconn);
+ if (event)
+ testDomainEventQueue(privconn, event);
+ testDriverUnlock(privconn);
return ret;
}
@@ -924,6 +985,7 @@ static int testPauseDomain (virDomainPtr
{
testConnPtr privconn = domain->conn->privateData;
virDomainObjPtr privdom;
+ virDomainEventPtr event = NULL;
int ret = -1;
testDriverLock(privconn);
@@ -945,11 +1007,18 @@ static int testPauseDomain (virDomainPtr
}
privdom->state = VIR_DOMAIN_PAUSED;
+ event = virDomainEventNewFromObj(privdom,
+ VIR_DOMAIN_EVENT_SUSPENDED,
+ VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
ret = 0;
cleanup:
if (privdom)
virDomainObjUnlock(privdom);
+ testDriverLock(privconn);
+ if (event)
+ testDomainEventQueue(privconn, event);
+ testDriverUnlock(privconn);
return ret;
}
@@ -957,6 +1026,7 @@ static int testShutdownDomain (virDomain
{
testConnPtr privconn = domain->conn->privateData;
virDomainObjPtr privdom;
+ virDomainEventPtr event = NULL;
int ret = -1;
testDriverLock(privconn);
@@ -977,6 +1047,9 @@ static int testShutdownDomain (virDomain
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);
@@ -987,6 +1060,8 @@ static int testShutdownDomain (virDomain
cleanup:
if (privdom)
virDomainObjUnlock(privdom);
+ if (event)
+ testDomainEventQueue(privconn, event);
testDriverUnlock(privconn);
return ret;
}
@@ -997,6 +1072,7 @@ static int testRebootDomain (virDomainPt
{
testConnPtr privconn = domain->conn->privateData;
virDomainObjPtr privdom;
+ virDomainEventPtr event = NULL;
int ret = -1;
testDriverLock(privconn);
@@ -1037,10 +1113,15 @@ static int testRebootDomain (virDomainPt
break;
}
- if (privdom->state == VIR_DOMAIN_SHUTOFF && !privdom->persistent) {
- virDomainRemoveInactive(&privconn->domains,
- privdom);
- privdom = NULL;
+ 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;
@@ -1048,6 +1129,8 @@ static int testRebootDomain (virDomainPt
cleanup:
if (privdom)
virDomainObjUnlock(privdom);
+ if (event)
+ testDomainEventQueue(privconn, event);
testDriverUnlock(privconn);
return ret;
}
@@ -1101,6 +1184,7 @@ static int testDomainSave(virDomainPtr d
int fd = -1;
int len;
virDomainObjPtr privdom;
+ virDomainEventPtr event = NULL;
int ret = -1;
testDriverLock(privconn);
@@ -1155,6 +1239,9 @@ static int testDomainSave(virDomainPtr d
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);
@@ -1175,6 +1262,8 @@ cleanup:
}
if (privdom)
virDomainObjUnlock(privdom);
+ if (event)
+ testDomainEventQueue(privconn, event);
testDriverUnlock(privconn);
return ret;
}
@@ -1189,6 +1278,7 @@ static int testDomainRestore(virConnectP
int len;
virDomainDefPtr def = NULL;
virDomainObjPtr dom = NULL;
+ virDomainEventPtr event = NULL;
int ret = -1;
if ((fd = open(path, O_RDONLY)) < 0) {
@@ -1243,6 +1333,9 @@ static int testDomainRestore(virConnectP
dom->state = VIR_DOMAIN_RUNNING;
dom->def->id = privconn->nextDomID++;
def = NULL;
+ event = virDomainEventNewFromObj(dom,
+ VIR_DOMAIN_EVENT_STARTED,
+ VIR_DOMAIN_EVENT_STARTED_RESTORED);
ret = dom->def->id;
cleanup:
@@ -1252,6 +1345,8 @@ cleanup:
close(fd);
if (dom)
virDomainObjUnlock(dom);
+ if (event)
+ testDomainEventQueue(privconn, event);
testDriverUnlock(privconn);
return ret;
}
@@ -1263,6 +1358,7 @@ static int testDomainCoreDump(virDomainP
testConnPtr privconn = domain->conn->privateData;
int fd = -1;
virDomainObjPtr privdom;
+ virDomainEventPtr event = NULL;
int ret = -1;
testDriverLock(privconn);
@@ -1293,6 +1389,9 @@ static int testDomainCoreDump(virDomainP
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);
@@ -1305,6 +1404,8 @@ cleanup:
close(fd);
if (privdom)
virDomainObjUnlock(privdom);
+ if (event)
+ testDomainEventQueue(privconn, event);
testDriverUnlock(privconn);
return ret;
}
@@ -1510,6 +1611,7 @@ static virDomainPtr testDomainDefineXML(
virDomainPtr ret = NULL;
virDomainDefPtr def;
virDomainObjPtr dom = NULL;
+ virDomainEventPtr event = NULL;
testDriverLock(privconn);
if ((def = virDomainDefParseString(conn, privconn->caps, xml,
@@ -1522,6 +1624,9 @@ static virDomainPtr testDomainDefineXML(
}
dom->persistent = 1;
dom->def->id = -1;
+ event = virDomainEventNewFromObj(dom,
+ VIR_DOMAIN_EVENT_DEFINED,
+ VIR_DOMAIN_EVENT_DEFINED_ADDED);
ret = virGetDomain(conn, def->name, def->uuid);
def = NULL;
@@ -1532,6 +1637,8 @@ cleanup:
virDomainDefFree(def);
if (dom)
virDomainObjUnlock(dom);
+ if (event)
+ testDomainEventQueue(privconn, event);
testDriverUnlock(privconn);
return ret;
}
@@ -1566,6 +1673,7 @@ cleanup:
static int testDomainCreate(virDomainPtr domain) {
testConnPtr privconn = domain->conn->privateData;
virDomainObjPtr privdom;
+ virDomainEventPtr event = NULL;
int ret = -1;
testDriverLock(privconn);
@@ -1585,11 +1693,16 @@ static int testDomainCreate(virDomainPtr
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;
}
@@ -1597,6 +1710,7 @@ cleanup:
static int testDomainUndefine(virDomainPtr domain) {
testConnPtr privconn = domain->conn->privateData;
virDomainObjPtr privdom;
+ virDomainEventPtr event = NULL;
int ret = -1;
testDriverLock(privconn);
@@ -1615,6 +1729,9 @@ static int testDomainUndefine(virDomainP
}
privdom->state = VIR_DOMAIN_SHUTOFF;
+ event = virDomainEventNewFromObj(privdom,
+ VIR_DOMAIN_EVENT_UNDEFINED,
+ VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
virDomainRemoveInactive(&privconn->domains,
privdom);
privdom = NULL;
@@ -1623,6 +1740,8 @@ static int testDomainUndefine(virDomainP
cleanup:
if (privdom)
virDomainObjUnlock(privdom);
+ if (event)
+ testDomainEventQueue(privconn, event);
testDriverUnlock(privconn);
return ret;
}
@@ -3255,6 +3374,98 @@ static int testDevMonClose(virConnectPtr
}
+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 (virDomainEventQueuePush(driver->domainEventQueue,
+ event) < 0)
+ virDomainEventFree(event);
+
+ if (driver->domainEventQueue->count == 1)
+ virEventUpdateTimeout(driver->domainEventTimer, 0);
+}
+
+
static virDriver testDriver = {
VIR_DRV_TEST,
"Test",
@@ -3313,8 +3524,8 @@ static virDriver testDriver = {
NULL, /* domainMemoryPeek */
testNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
NULL, /* getFreeMemory */
- NULL, /* domainEventRegister */
- NULL, /* domainEventDeregister */
+ testDomainEventRegister, /* domainEventRegister */
+ testDomainEventDeregister, /* domainEventDeregister */
NULL, /* domainMigratePrepare2 */
NULL, /* domainMigrateFinish2 */
};
--
|: Red Hat, Engineering, London -o-
http://people.redhat.com/berrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org -o-
http://ovirt.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|