[libvirt] [PATCH 1/8] Add event callbacks to libxl driver

Markus Groß gross at univention.de
Mon Mar 21 09:35:50 UTC 2011


---
 src/libxl/libxl_conf.h   |    8 ++-
 src/libxl/libxl_driver.c |  199 +++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 202 insertions(+), 5 deletions(-)

diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h
index bb49d35..a86df9a 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 615cb47..ad95e2b 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -1,6 +1,7 @@
 /*---------------------------------------------------------------------------*/
 /*  Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany.
  *  Copyright (C) 2011 Univention GmbH.
+ *  Copyright (C) 2006-2011 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -15,6 +16,11 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Authors:
+ *     Jim Fehlig <jfehlig at novell.com>
+ *     Markus Groß <gross at univention.de>
+ *     Daniel P. Berrange <berrange at redhat.com>
  */
 /*---------------------------------------------------------------------------*/
 
@@ -99,6 +105,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 +245,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 +284,9 @@ static void libxlEventHandler(int watch,
         switch (info.shutdown_reason) {
             case SHUTDOWN_poweroff:
             case 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 +306,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 +370,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 +415,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 +520,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 +636,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 +788,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 +1121,7 @@ libxlDomainDestroy(virDomainPtr dom)
     virDomainObjPtr vm;
     int ret = -1;
     libxlDomainObjPrivatePtr priv;
+    virDomainEventPtr event = NULL;
 
     libxlDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
@@ -1043,6 +1139,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 +1159,8 @@ libxlDomainDestroy(virDomainPtr dom)
 cleanup:
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        libxlDomainEventQueue(driver, event);
     libxlDriverUnlock(driver);
     return ret;
 }
@@ -1193,6 +1294,7 @@ libxlDomainDefineXML(virConnectPtr conn, const char *xml)
     virDomainDefPtr def = NULL;
     virDomainObjPtr vm = NULL;
     virDomainPtr dom = NULL;
+    virDomainEventPtr event = NULL;
     int dupVM;
 
     libxlDriverLock(driver);
@@ -1220,10 +1322,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;
 }
@@ -1233,6 +1342,7 @@ libxlDomainUndefine(virDomainPtr dom)
 {
     libxlDriverPrivatePtr driver = dom->conn->privateData;
     virDomainObjPtr vm;
+    virDomainEventPtr event = NULL;
     int ret = -1;
 
     libxlDriverLock(driver);
@@ -1264,6 +1374,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;
@@ -1271,11 +1384,51 @@ libxlDomainUndefine(virDomainPtr dom)
   cleanup:
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        libxlDomainEventQueue(driver, event);
     libxlDriverUnlock(driver);
     return ret;
 }
 
 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)
 {
     libxlDriverPrivatePtr driver = dom->conn->privateData;
@@ -1319,6 +1472,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,
@@ -1396,8 +1587,8 @@ static virDriver libxlDriver = {
     NULL,                       /* domainGetBlockInfo */
     NULL,                       /* nodeGetCellsFreeMemory */
     NULL,                       /* getFreeMemory */
-    NULL,                       /* domainEventRegister */
-    NULL,                       /* domainEventDeregister */
+    libxlDomainEventRegister,   /* domainEventRegister */
+    libxlDomainEventDeregister, /* domainEventDeregister */
     NULL,                       /* domainMigratePrepare2 */
     NULL,                       /* domainMigrateFinish2 */
     NULL,                       /* nodeDeviceDettach */
@@ -1414,8 +1605,8 @@ static virDriver libxlDriver = {
     NULL,                       /* domainGetJobInfo */
     NULL,                       /* domainAbortJob */
     NULL,                       /* domainMigrateSetMaxDowntime */
-    NULL,                       /* domainEventRegisterAny */
-    NULL,                       /* domainEventDeregisterAny */
+    libxlDomainEventRegisterAny,/* domainEventRegisterAny */
+    libxlDomainEventDeregisterAny,/* domainEventDeregisterAny */
     NULL,                       /* domainManagedSave */
     NULL,                       /* domainHasManagedSaveImage */
     NULL,                       /* domainManagedSaveRemove */
-- 
1.7.4.1




More information about the libvir-list mailing list