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

Daniel P. Berrange berrange at redhat.com
Tue Jul 12 16:04:30 UTC 2011


Any thoughts on this patch..

Regards,
Daniel

On Mon, Jul 04, 2011 at 01:32:23PM +0100, Daniel P. Berrange wrote:
> * 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
> 

-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|




More information about the libvir-list mailing list