]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Add domain events support to UML driver
authorDaniel P. Berrange <berrange@redhat.com>
Mon, 6 Jul 2009 15:06:11 +0000 (16:06 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Fri, 15 Jul 2011 13:13:20 +0000 (14:13 +0100)
* 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
src/uml/uml_driver.c

index 1105f84080aa38ef7137aa6a129a0176c18098b3..5401a7eaa6c1fd8b1e383de5265b9f5828e94bbd 100644 (file)
@@ -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;
 };
 
 
index 6eede55b40354b147407ec00dac987e300963481..d0374ea4acb61e42aa83b00d5d2007dc896dcb36 100644 (file)
@@ -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 umlStartVMDaemon(virConnectPtr conn,
                             struct uml_driver *driver,
@@ -153,6 +156,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);
@@ -172,7 +182,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);
@@ -253,6 +265,7 @@ umlInotifyEvent(int watch,
     char *tmp, *name;
     struct uml_driver *driver = data;
     virDomainObjPtr dom;
+    virDomainEventPtr event = NULL;
 
     umlDriverLock(driver);
     if (watch != driver->inotifyWatch)
@@ -298,6 +311,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);
@@ -324,6 +340,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);
@@ -334,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);
@@ -346,6 +368,8 @@ reread:
     }
 
 cleanup:
+    if (event)
+        umlDomainEventQueue(driver, event);
     umlDriverUnlock(driver);
 }
 
@@ -379,6 +403,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;
@@ -457,9 +488,10 @@ umlStartup(int privileged)
                                 NULL, NULL) < 0)
         goto error;
 
+    umlDriverUnlock(uml_driver);
+
     umlAutostartConfigs(uml_driver);
 
-    umlDriverUnlock(uml_driver);
     VIR_FREE(userdir);
 
     return 0;
@@ -475,6 +507,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:
  *
@@ -492,10 +539,10 @@ umlReload(void) {
                             uml_driver->configDir,
                             uml_driver->autostartDir,
                             0, 1 << VIR_DOMAIN_VIRT_UML,
-                            NULL, NULL);
+                            umlNotifyLoadDomain, uml_driver);
+    umlDriverUnlock(uml_driver);
 
     umlAutostartConfigs(uml_driver);
-    umlDriverUnlock(uml_driver);
 
     return 0;
 }
@@ -558,6 +605,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);
@@ -918,6 +967,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;
 }
@@ -1017,7 +1067,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;
 
@@ -1285,6 +1340,7 @@ static virDomainPtr umlDomainCreate(virConnectPtr conn, const char *xml,
     virDomainDefPtr def;
     virDomainObjPtr vm = NULL;
     virDomainPtr dom = NULL;
+    virDomainEventPtr event = NULL;
 
     virCheckFlags(0, NULL);
 
@@ -1311,6 +1367,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;
@@ -1319,6 +1378,8 @@ cleanup:
     virDomainDefFree(def);
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        umlDomainEventQueue(driver, event);
     umlDriverUnlock(driver);
     return dom;
 }
@@ -1359,6 +1420,7 @@ cleanup:
 static int umlDomainDestroy(virDomainPtr dom) {
     struct uml_driver *driver = dom->conn->privateData;
     virDomainObjPtr vm;
+    virDomainEventPtr event = NULL;
     int ret = -1;
 
     umlDriverLock(driver);
@@ -1371,6 +1433,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);
@@ -1381,6 +1446,8 @@ static int umlDomainDestroy(virDomainPtr dom) {
 cleanup:
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        umlDomainEventQueue(driver, event);
     umlDriverUnlock(driver);
     return ret;
 }
@@ -1638,6 +1705,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);
@@ -1653,10 +1721,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;
 }
@@ -2207,6 +2281,115 @@ 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",
@@ -2249,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 */
 };