On Tue, Jan 13, 2009 at 05:48:12PM +0000, Daniel P. Berrange wrote: > 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(-) Updated patch to not queue events if no event loop impl is defined (as is common from virsh). This is what was breaking the tests cases Daniel diff --git a/src/test.c b/src/test.c --- a/src/test.c +++ b/src/test.c @@ -42,9 +42,12 @@ #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" +#include "logging.h" #define VIR_FROM_THIS VIR_FROM_TEST @@ -72,6 +75,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 +106,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 +660,22 @@ 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) + DEBUG0("virEventAddTimeout failed: No addTimeoutImpl defined. " + "continuing without events."); + } + 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,103 @@ 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 (driver->domainEventTimer < 0) { + virDomainEventFree(event); + return; + } + + 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 +3529,8 @@ static virDriver testDriver = { NULL, /* domainMemoryPeek */ testNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ NULL, /* getFreeMemory */ - NULL, /* domainEventRegister */ - NULL, /* domainEventDeregister */ + testDomainEventRegister, /* domainEventRegister */ + testDomainEventDeregister, /* domainEventDeregister */ NULL, /* domainMigratePrepare2 */ NULL, /* domainMigrateFinish2 */ }; diff --git a/tests/read-bufsiz b/tests/read-bufsiz --- a/tests/read-bufsiz +++ b/tests/read-bufsiz @@ -21,6 +21,9 @@ if test "$VERBOSE" = yes; then virsh --version fi +test -z "$srcdir" && srcdir=`pwd` +test -z "$abs_top_srcdir" && abs_top_srcdir=`pwd`/.. + . $srcdir/test-lib.sh fail=0 -- |: 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 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list