diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h index bb49d35a1e6032148ea692ecd287c64430a56044..a86df9a911b60d4f51aad5baefc619f1c64ae8fa 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -26,6 +26,7 @@ # include "internal.h" # include "domain_conf.h" +# include "domain_event.h" # include "capabilities.h" # include "configmake.h" # include "bitmap.h" @@ -57,6 +58,12 @@ struct _libxlDriverPrivate { virBitmapPtr reservedVNCPorts; virDomainObjList domains; + /* A list of callbacks */ + virDomainEventCallbackListPtr domainEventCallbacks; + virDomainEventQueuePtr domainEventQueue; + int domainEventTimer; + int domainEventDispatching; + char *configDir; char *autostartDir; char *logDir; @@ -87,5 +94,4 @@ int libxlBuildDomainConfig(libxlDriverPrivatePtr driver, virDomainDefPtr def, libxl_domain_config *d_config); - #endif /* LIBXL_CONF_H */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 80a43a045a590b43953c3277f963311877bc5199..64f1505d560a02c84dbfc5f8f9f7aa975c914597 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -99,6 +99,58 @@ libxlDomainObjPrivateFree(void *data) VIR_FREE(priv); } +static void +libxlDomainEventDispatchFunc(virConnectPtr conn, virDomainEventPtr event, + virConnectDomainEventGenericCallback cb, + void *cbopaque, void *opaque) +{ + libxlDriverPrivatePtr driver = opaque; + + /* Drop the lock whle dispatching, for sake of re-entrancy */ + libxlDriverUnlock(driver); + virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL); + libxlDriverLock(driver); +} + +static void +libxlDomainEventFlush(int timer ATTRIBUTE_UNUSED, void *opaque) +{ + libxlDriverPrivatePtr driver = opaque; + virDomainEventQueue tempQueue; + + libxlDriverLock(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, + libxlDomainEventDispatchFunc, + driver); + + /* Purge any deleted callbacks */ + virDomainEventCallbackListPurgeMarked(driver->domainEventCallbacks); + + driver->domainEventDispatching = 0; + libxlDriverUnlock(driver); +} + +/* driver must be locked before calling */ +static void +libxlDomainEventQueue(libxlDriverPrivatePtr driver, virDomainEventPtr event) +{ + if (virDomainEventQueuePush(driver->domainEventQueue, event) < 0) + virDomainEventFree(event); + if (driver->domainEventQueue->count == 1) + virEventUpdateTimeout(driver->domainEventTimer, 0); +} + /* * Remove reference to domain object. */ @@ -187,6 +239,7 @@ static void libxlEventHandler(int watch, libxlDriverPrivatePtr driver = libxl_driver; virDomainObjPtr vm = data; libxlDomainObjPrivatePtr priv; + virDomainEventPtr dom_event = NULL; libxl_event event; libxl_dominfo info; @@ -225,6 +278,10 @@ static void libxlEventHandler(int watch, switch (info.shutdown_reason) { case SHUTDOWN_poweroff: case SHUTDOWN_crash: + if (info.shutdown_reason == SHUTDOWN_crash) + dom_event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_CRASHED); libxlVmReap(driver, vm, 0); if (!vm->persistent) { virDomainRemoveInactive(&driver->domains, vm); @@ -244,6 +301,11 @@ static void libxlEventHandler(int watch, cleanup: if (vm) virDomainObjUnlock(vm); + if (dom_event) { + libxlDriverLock(driver); + libxlDomainEventQueue(driver, dom_event); + libxlDriverUnlock(driver); + } libxl_free_event(&event); } @@ -303,6 +365,7 @@ libxlVmStart(libxlDriverPrivatePtr driver, { libxl_domain_config d_config; virDomainDefPtr def = vm->def; + virDomainEventPtr event = NULL; int ret; uint32_t domid = 0; char *dom_xml = NULL; @@ -347,9 +410,14 @@ libxlVmStart(libxlDriverPrivatePtr driver, vm->state = VIR_DOMAIN_PAUSED; } + if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) goto error; + event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_BOOTED); + libxlDomainEventQueue(driver, event); + libxl_domain_config_destroy(&d_config); VIR_FREE(dom_xml); return 0; @@ -447,6 +515,13 @@ libxlShutdown(void) VIR_FREE(libxl_driver->libDir); VIR_FREE(libxl_driver->saveDir); + /* Free domain callback list */ + virDomainEventCallbackListFree(libxl_driver->domainEventCallbacks); + virDomainEventQueueFree(libxl_driver->domainEventQueue); + + if (libxl_driver->domainEventTimer != -1) + virEventRemoveTimeout(libxl_driver->domainEventTimer); + libxlDriverUnlock(libxl_driver); virMutexDestroy(&libxl_driver->lock); VIR_FREE(libxl_driver); @@ -556,6 +631,16 @@ libxlStartup(int privileged) { } VIR_FREE(log_file); + /* Init callback list */ + if (VIR_ALLOC(libxl_driver->domainEventCallbacks) < 0) + goto out_of_memory; + if (!(libxl_driver->domainEventQueue = virDomainEventQueueNew())) + goto out_of_memory; + if ((libxl_driver->domainEventTimer = + virEventAddTimeout(-1, libxlDomainEventFlush, libxl_driver, NULL)) < 0) + goto error; + + libxl_driver->logger = (xentoollog_logger *)xtl_createlogger_stdiostream(libxl_driver->logger_file, XTL_DEBUG, 0); if (!libxl_driver->logger) { @@ -698,6 +783,11 @@ libxlOpen(virConnectPtr conn, static int libxlClose(virConnectPtr conn ATTRIBUTE_UNUSED) { + libxlDriverPrivatePtr driver = conn->privateData; + + libxlDriverLock(driver); + virDomainEventCallbackListRemoveConn(conn, driver->domainEventCallbacks); + libxlDriverUnlock(driver); conn->privateData = NULL; return 0; } @@ -1026,6 +1116,7 @@ libxlDomainDestroy(virDomainPtr dom) virDomainObjPtr vm; int ret = -1; libxlDomainObjPrivatePtr priv; + virDomainEventPtr event = NULL; libxlDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); @@ -1043,6 +1134,9 @@ libxlDomainDestroy(virDomainPtr dom) goto cleanup; } + event = virDomainEventNewFromObj(vm,VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_DESTROYED); + priv = vm->privateData; if (libxlVmReap(driver, vm, 1) != 0) { libxlError(VIR_ERR_INTERNAL_ERROR, @@ -1060,6 +1154,8 @@ libxlDomainDestroy(virDomainPtr dom) cleanup: if (vm) virDomainObjUnlock(vm); + if (event) + libxlDomainEventQueue(driver, event); libxlDriverUnlock(driver); return ret; } @@ -1308,6 +1404,7 @@ libxlDomainDefineXML(virConnectPtr conn, const char *xml) virDomainDefPtr def = NULL; virDomainObjPtr vm = NULL; virDomainPtr dom = NULL; + virDomainEventPtr event = NULL; int dupVM; libxlDriverLock(driver); @@ -1335,10 +1432,17 @@ libxlDomainDefineXML(virConnectPtr conn, const char *xml) if (dom) dom->id = vm->def->id; + event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_DEFINED, + !dupVM ? + VIR_DOMAIN_EVENT_DEFINED_ADDED : + VIR_DOMAIN_EVENT_DEFINED_UPDATED); + cleanup: virDomainDefFree(def); if (vm) virDomainObjUnlock(vm); + if (event) + libxlDomainEventQueue(driver, event); libxlDriverUnlock(driver); return dom; } @@ -1348,6 +1452,7 @@ libxlDomainUndefine(virDomainPtr dom) { libxlDriverPrivatePtr driver = dom->conn->privateData; virDomainObjPtr vm; + virDomainEventPtr event = NULL; int ret = -1; libxlDriverLock(driver); @@ -1379,6 +1484,9 @@ libxlDomainUndefine(virDomainPtr dom) vm) < 0) goto cleanup; + event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_UNDEFINED, + VIR_DOMAIN_EVENT_UNDEFINED_REMOVED); + virDomainRemoveInactive(&driver->domains, vm); vm = NULL; ret = 0; @@ -1386,6 +1494,8 @@ libxlDomainUndefine(virDomainPtr dom) cleanup: if (vm) virDomainObjUnlock(vm); + if (event) + libxlDomainEventQueue(driver, event); libxlDriverUnlock(driver); return ret; } @@ -1410,6 +1520,44 @@ libxlNodeGetFreeMemory(virConnectPtr conn) return phy_info.free_pages * ver_info->pagesize; } +static int +libxlDomainEventRegister(virConnectPtr conn, + virConnectDomainEventCallback callback, void *opaque, + virFreeCallback freecb) +{ + libxlDriverPrivatePtr driver = conn->privateData; + int ret; + + libxlDriverLock(driver); + ret = virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks, + callback, opaque, freecb); + libxlDriverUnlock(driver); + + return ret; +} + + +static int +libxlDomainEventDeregister(virConnectPtr conn, + virConnectDomainEventCallback callback) +{ + libxlDriverPrivatePtr driver = conn->privateData; + int ret; + + libxlDriverLock(driver); + if (driver->domainEventDispatching) + ret = virDomainEventCallbackListMarkDelete(conn, + driver->domainEventCallbacks, + callback); + else + ret = virDomainEventCallbackListRemove(conn, + driver->domainEventCallbacks, + callback); + libxlDriverUnlock(driver); + + return ret; +} + static int libxlDomainIsActive(virDomainPtr dom) { @@ -1454,6 +1602,44 @@ libxlDomainIsPersistent(virDomainPtr dom) return ret; } +static int +libxlDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eventID, + virConnectDomainEventGenericCallback callback, + void *opaque, virFreeCallback freecb) +{ + libxlDriverPrivatePtr driver = conn->privateData; + int ret; + + libxlDriverLock(driver); + ret = virDomainEventCallbackListAddID(conn, driver->domainEventCallbacks, + dom, eventID, callback, opaque, + freecb); + libxlDriverUnlock(driver); + + return ret; +} + + +static int +libxlDomainEventDeregisterAny(virConnectPtr conn, int callbackID) +{ + libxlDriverPrivatePtr driver = conn->privateData; + int ret; + + libxlDriverLock(driver); + if (driver->domainEventDispatching) + ret = virDomainEventCallbackListMarkDeleteID(conn, + driver->domainEventCallbacks, + callbackID); + else + ret = virDomainEventCallbackListRemoveID(conn, + driver->domainEventCallbacks, + callbackID); + libxlDriverUnlock(driver); + + return ret; +} + static virDriver libxlDriver = { VIR_DRV_LIBXL, @@ -1531,8 +1717,8 @@ static virDriver libxlDriver = { NULL, /* domainGetBlockInfo */ NULL, /* nodeGetCellsFreeMemory */ libxlNodeGetFreeMemory, /* getFreeMemory */ - NULL, /* domainEventRegister */ - NULL, /* domainEventDeregister */ + libxlDomainEventRegister, /* domainEventRegister */ + libxlDomainEventDeregister, /* domainEventDeregister */ NULL, /* domainMigratePrepare2 */ NULL, /* domainMigrateFinish2 */ NULL, /* nodeDeviceDettach */ @@ -1550,8 +1736,8 @@ static virDriver libxlDriver = { NULL, /* domainAbortJob */ NULL, /* domainMigrateSetMaxDowntime */ NULL, /* domainMigrateSetMaxSpeed */ - NULL, /* domainEventRegisterAny */ - NULL, /* domainEventDeregisterAny */ + libxlDomainEventRegisterAny,/* domainEventRegisterAny */ + libxlDomainEventDeregisterAny,/* domainEventDeregisterAny */ NULL, /* domainManagedSave */ NULL, /* domainHasManagedSaveImage */ NULL, /* domainManagedSaveRemove */