[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

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



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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]