[libvirt] [PATCH] Add domain events support to UML driver

Daniel P. Berrange berrange at redhat.com
Mon Jul 4 12:32:23 UTC 2011


* src/uml_conf.h: Add queue for dispatch of domain events
* src/uml_driver.c: Trigger domain events upon important lifecycle transitions
---
 src/uml/uml_conf.h   |    4 +
 src/uml/uml_driver.c |  194 ++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 194 insertions(+), 4 deletions(-)

diff --git a/src/uml/uml_conf.h b/src/uml/uml_conf.h
index 1105f84..5401a7e 100644
--- a/src/uml/uml_conf.h
+++ b/src/uml/uml_conf.h
@@ -29,6 +29,7 @@
 # include "capabilities.h"
 # include "network_conf.h"
 # include "domain_conf.h"
+# include "domain_event.h"
 # include "virterror_internal.h"
 # include "threads.h"
 # include "command.h"
@@ -60,6 +61,9 @@ struct uml_driver {
     int inotifyWatch;
 
     virCapsPtr caps;
+
+    /* Event handling */
+    virDomainEventStatePtr domainEventState;
 };
 
 
diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
index 91591f1..d0736df 100644
--- a/src/uml/uml_driver.c
+++ b/src/uml/uml_driver.c
@@ -113,6 +113,9 @@ static int umlOpenMonitor(struct uml_driver *driver,
                           virDomainObjPtr vm);
 static int umlReadPidFile(struct uml_driver *driver,
                           virDomainObjPtr vm);
+static void umlDomainEventFlush(int timer, void *opaque);
+static void umlDomainEventQueue(struct uml_driver *driver,
+                                virDomainEventPtr event);
 
 static int umlSetCloseExec(int fd) {
     int flags;
@@ -166,6 +169,13 @@ umlAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaqu
             virErrorPtr err = virGetLastError();
             VIR_ERROR(_("Failed to autostart VM '%s': %s"),
                       vm->def->name, err ? err->message : _("unknown error"));
+        } else {
+            virDomainEventPtr event =
+                virDomainEventNewFromObj(vm,
+                                         VIR_DOMAIN_EVENT_STARTED,
+                                         VIR_DOMAIN_EVENT_STARTED_BOOTED);
+            if (event)
+                umlDomainEventQueue(data->driver, event);
         }
     }
     virDomainObjUnlock(vm);
@@ -185,7 +195,9 @@ umlAutostartConfigs(struct uml_driver *driver) {
 
     struct umlAutostartData data = { driver, conn };
 
+    umlDriverLock(driver);
     virHashForEach(driver->domains.objs, umlAutostartDomain, &data);
+    umlDriverUnlock(driver);
 
     if (conn)
         virConnectClose(conn);
@@ -266,6 +278,7 @@ umlInotifyEvent(int watch,
     char *tmp, *name;
     struct uml_driver *driver = data;
     virDomainObjPtr dom;
+    virDomainEventPtr event = NULL;
 
     umlDriverLock(driver);
     if (watch != driver->inotifyWatch)
@@ -311,6 +324,9 @@ reread:
 
             umlShutdownVMDaemon(NULL, driver, dom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
             virDomainAuditStop(dom, "shutdown");
+            event = virDomainEventNewFromObj(dom,
+                                             VIR_DOMAIN_EVENT_STOPPED,
+                                             VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
             if (!dom->persistent) {
                 virDomainRemoveInactive(&driver->domains,
                                         dom);
@@ -337,6 +353,9 @@ reread:
                 umlShutdownVMDaemon(NULL, driver, dom,
                                     VIR_DOMAIN_SHUTOFF_FAILED);
                 virDomainAuditStop(dom, "failed");
+                event = virDomainEventNewFromObj(dom,
+                                                 VIR_DOMAIN_EVENT_STOPPED,
+                                                 VIR_DOMAIN_EVENT_STOPPED_FAILED);
                 if (!dom->persistent) {
                     virDomainRemoveInactive(&driver->domains,
                                             dom);
@@ -347,6 +366,9 @@ reread:
                 umlShutdownVMDaemon(NULL, driver, dom,
                                     VIR_DOMAIN_SHUTOFF_FAILED);
                 virDomainAuditStop(dom, "failed");
+                event = virDomainEventNewFromObj(dom,
+                                                 VIR_DOMAIN_EVENT_STOPPED,
+                                                 VIR_DOMAIN_EVENT_STOPPED_FAILED);
                 if (!dom->persistent) {
                     virDomainRemoveInactive(&driver->domains,
                                             dom);
@@ -359,6 +381,8 @@ reread:
     }
 
 cleanup:
+    if (event)
+        umlDomainEventQueue(driver, event);
     umlDriverUnlock(driver);
 }
 
@@ -392,6 +416,13 @@ umlStartup(int privileged)
     if (virDomainObjListInit(&uml_driver->domains) < 0)
         goto error;
 
+    uml_driver->domainEventState = virDomainEventStateNew(umlDomainEventFlush,
+                                                          uml_driver,
+                                                          NULL,
+                                                          true);
+    if (!uml_driver->domainEventState)
+        goto error;
+
     userdir = virGetUserDirectory(uid);
     if (!userdir)
         goto error;
@@ -469,9 +500,10 @@ umlStartup(int privileged)
                                 0, NULL, NULL) < 0)
         goto error;
 
+    umlDriverUnlock(uml_driver);
+
     umlAutostartConfigs(uml_driver);
 
-    umlDriverUnlock(uml_driver);
     VIR_FREE(userdir);
 
     return 0;
@@ -487,6 +519,21 @@ error:
     return -1;
 }
 
+static void umlNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
+{
+    struct uml_driver *driver = opaque;
+
+    if (newVM) {
+        virDomainEventPtr event =
+            virDomainEventNewFromObj(vm,
+                                     VIR_DOMAIN_EVENT_DEFINED,
+                                     VIR_DOMAIN_EVENT_DEFINED_ADDED);
+        if (event)
+            umlDomainEventQueue(driver, event);
+    }
+}
+
+
 /**
  * umlReload:
  *
@@ -503,10 +550,10 @@ umlReload(void) {
                             &uml_driver->domains,
                             uml_driver->configDir,
                             uml_driver->autostartDir,
-                            0, NULL, NULL);
+                            0, umlNotifyLoadDomain, uml_driver);
+    umlDriverUnlock(uml_driver);
 
     umlAutostartConfigs(uml_driver);
-    umlDriverUnlock(uml_driver);
 
     return 0;
 }
@@ -569,6 +616,8 @@ umlShutdown(void) {
 
     virDomainObjListDeinit(&uml_driver->domains);
 
+    virDomainEventStateFree(uml_driver->domainEventState);
+
     VIR_FREE(uml_driver->logDir);
     VIR_FREE(uml_driver->configDir);
     VIR_FREE(uml_driver->autostartDir);
@@ -929,6 +978,7 @@ cleanup:
     /* XXX what if someone else tries to start it again
        before we get the inotification ? Sounds like
        trouble.... */
+    /* XXX this is bad for events too. must fix this better */
 
     return ret;
 }
@@ -1025,7 +1075,12 @@ static virDrvOpenStatus umlOpen(virConnectPtr conn,
 }
 
 static int umlClose(virConnectPtr conn) {
-    /*struct uml_driver *driver = conn->privateData;*/
+    struct uml_driver *driver = conn->privateData;
+
+    umlDriverLock(driver);
+    virDomainEventCallbackListRemoveConn(conn,
+                                         driver->domainEventState->callbacks);
+    umlDriverUnlock(driver);
 
     conn->privateData = NULL;
 
@@ -1293,6 +1348,7 @@ static virDomainPtr umlDomainCreate(virConnectPtr conn, const char *xml,
     virDomainDefPtr def;
     virDomainObjPtr vm = NULL;
     virDomainPtr dom = NULL;
+    virDomainEventPtr event = NULL;
 
     virCheckFlags(0, NULL);
 
@@ -1318,6 +1374,9 @@ static virDomainPtr umlDomainCreate(virConnectPtr conn, const char *xml,
         goto cleanup;
     }
     virDomainAuditStart(vm, "booted", true);
+    event = virDomainEventNewFromObj(vm,
+                                     VIR_DOMAIN_EVENT_STARTED,
+                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
 
     dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
     if (dom) dom->id = vm->def->id;
@@ -1326,6 +1385,8 @@ cleanup:
     virDomainDefFree(def);
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        umlDomainEventQueue(driver, event);
     umlDriverUnlock(driver);
     return dom;
 }
@@ -1366,6 +1427,7 @@ cleanup:
 static int umlDomainDestroy(virDomainPtr dom) {
     struct uml_driver *driver = dom->conn->privateData;
     virDomainObjPtr vm;
+    virDomainEventPtr event = NULL;
     int ret = -1;
 
     umlDriverLock(driver);
@@ -1378,6 +1440,9 @@ static int umlDomainDestroy(virDomainPtr dom) {
 
     umlShutdownVMDaemon(dom->conn, driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED);
     virDomainAuditStop(vm, "destroyed");
+    event = virDomainEventNewFromObj(vm,
+                                     VIR_DOMAIN_EVENT_STOPPED,
+                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
     if (!vm->persistent) {
         virDomainRemoveInactive(&driver->domains,
                                 vm);
@@ -1388,6 +1453,8 @@ static int umlDomainDestroy(virDomainPtr dom) {
 cleanup:
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        umlDomainEventQueue(driver, event);
     umlDriverUnlock(driver);
     return ret;
 }
@@ -1640,6 +1707,7 @@ static int umlNumDefinedDomains(virConnectPtr conn) {
 static int umlDomainStartWithFlags(virDomainPtr dom, unsigned int flags) {
     struct uml_driver *driver = dom->conn->privateData;
     virDomainObjPtr vm;
+    virDomainEventPtr event = NULL;
     int ret = -1;
 
     virCheckFlags(0, -1);
@@ -1655,10 +1723,16 @@ static int umlDomainStartWithFlags(virDomainPtr dom, unsigned int flags) {
 
     ret = umlStartVMDaemon(dom->conn, driver, vm);
     virDomainAuditStart(vm, "booted", ret >= 0);
+    if (ret == 0)
+        event = virDomainEventNewFromObj(vm,
+                                         VIR_DOMAIN_EVENT_STARTED,
+                                         VIR_DOMAIN_EVENT_STARTED_BOOTED);
 
 cleanup:
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        umlDomainEventQueue(driver, event);
     umlDriverUnlock(driver);
     return ret;
 }
@@ -2208,6 +2282,114 @@ cleanup:
 }
 
 
+static int
+umlDomainEventRegister(virConnectPtr conn,
+                       virConnectDomainEventCallback callback,
+                       void *opaque,
+                       virFreeCallback freecb)
+{
+    struct uml_driver *driver = conn->privateData;
+    int ret;
+
+    umlDriverLock(driver);
+    ret = virDomainEventCallbackListAdd(conn,
+                                        driver->domainEventState->callbacks,
+                                        callback, opaque, freecb);
+    umlDriverUnlock(driver);
+
+    return ret;
+}
+
+static int
+umlDomainEventDeregister(virConnectPtr conn,
+                         virConnectDomainEventCallback callback)
+{
+    struct uml_driver *driver = conn->privateData;
+    int ret;
+
+    umlDriverLock(driver);
+    ret = virDomainEventStateDeregister(conn,
+                                        driver->domainEventState,
+                                        callback);
+    umlDriverUnlock(driver);
+
+    return ret;
+}
+static int
+umlDomainEventRegisterAny(virConnectPtr conn,
+                          virDomainPtr dom,
+                          int eventID,
+                          virConnectDomainEventGenericCallback callback,
+                          void *opaque,
+                          virFreeCallback freecb)
+{
+    struct uml_driver *driver = conn->privateData;
+    int ret;
+
+    umlDriverLock(driver);
+    ret = virDomainEventCallbackListAddID(conn,
+                                          driver->domainEventState->callbacks,
+                                          dom, eventID,
+                                          callback, opaque, freecb);
+    umlDriverUnlock(driver);
+
+    return ret;
+}
+
+
+static int
+umlDomainEventDeregisterAny(virConnectPtr conn,
+                            int callbackID)
+{
+    struct uml_driver *driver = conn->privateData;
+    int ret;
+
+    umlDriverLock(driver);
+    ret = virDomainEventStateDeregisterAny(conn,
+                                           driver->domainEventState,
+                                           callbackID);
+    umlDriverUnlock(driver);
+
+    return ret;
+}
+
+
+static void umlDomainEventDispatchFunc(virConnectPtr conn,
+                                       virDomainEventPtr event,
+                                       virConnectDomainEventGenericCallback cb,
+                                       void *cbopaque,
+                                       void *opaque)
+{
+    struct uml_driver *driver = opaque;
+
+    /* Drop the lock whle dispatching, for sake of re-entrancy */
+    umlDriverUnlock(driver);
+    virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL);
+    umlDriverLock(driver);
+}
+
+
+static void umlDomainEventFlush(int timer ATTRIBUTE_UNUSED, void *opaque)
+{
+    struct uml_driver *driver = opaque;
+
+    umlDriverLock(driver);
+    virDomainEventStateFlush(driver->domainEventState,
+                             umlDomainEventDispatchFunc,
+                             driver);
+    umlDriverUnlock(driver);
+}
+
+
+/* driver must be locked before calling */
+static void umlDomainEventQueue(struct uml_driver *driver,
+                                virDomainEventPtr event)
+{
+    virDomainEventStateQueue(driver->domainEventState, event);
+}
+
+
+
 static virDriver umlDriver = {
     .no = VIR_DRV_UML,
     .name = "UML",
@@ -2250,11 +2432,15 @@ static virDriver umlDriver = {
     .nodeGetMemoryStats = nodeGetMemoryStats, /* 0.9.3 */
     .nodeGetCellsFreeMemory = nodeGetCellsFreeMemory, /* 0.5.0 */
     .nodeGetFreeMemory = nodeGetFreeMemory, /* 0.5.0 */
+    .domainEventRegister = umlDomainEventRegister, /* 0.9.4 */
+    .domainEventDeregister = umlDomainEventDeregister, /* 0.9.4 */
     .isEncrypted = umlIsEncrypted, /* 0.7.3 */
     .isSecure = umlIsSecure, /* 0.7.3 */
     .domainIsActive = umlDomainIsActive, /* 0.7.3 */
     .domainIsPersistent = umlDomainIsPersistent, /* 0.7.3 */
     .domainIsUpdated = umlDomainIsUpdated, /* 0.8.6 */
+    .domainEventRegisterAny = umlDomainEventRegisterAny, /* 0.9.4 */
+    .domainEventDeregisterAny = umlDomainEventDeregisterAny, /* 0.9.4 */
     .domainOpenConsole = umlDomainOpenConsole, /* 0.8.6 */
 };
 
-- 
1.7.4.4




More information about the libvir-list mailing list