[libvirt] PATCH: 23/25: Add domain events to test driver

Daniel P. Berrange berrange at redhat.com
Tue Jan 13 17:48:12 UTC 2009


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 :|




More information about the libvir-list mailing list