[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [libvirt] [PATCH 2/3] Domain events - xen



Monitor xenstore for domain changes
NOTE: this patch is currently untested

Signed-off-by: Ben Guthro <bguthro virtualiron com>

 proxy/Makefile.am |    1
 src/xen_unified.c |    8 ++
 src/xen_unified.h |    3
 src/xs_internal.c |  176 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/xs_internal.h |   39 +++++++++++
 5 files changed, 227 insertions(+)
diff --git a/proxy/Makefile.am b/proxy/Makefile.am
index 5902cab..75ba6b4 100644
--- a/proxy/Makefile.am
+++ b/proxy/Makefile.am
@@ -17,6 +17,7 @@ libvirt_proxy_SOURCES = libvirt_proxy.c @top_srcdir@/src/xend_internal.c \
             @top_srcdir@/src/memory.c \
             @top_srcdir@/src/domain_conf.c \
             @top_srcdir@/src/util.c \
+	    @top_srcdir@/src/event.c \
 	    @top_srcdir@/src/uuid.c
 libvirt_proxy_LDFLAGS = $(WARN_CFLAGS)
 libvirt_proxy_DEPENDENCIES =
diff --git a/src/xen_unified.c b/src/xen_unified.c
index dae68d3..4ebf347 100644
--- a/src/xen_unified.c
+++ b/src/xen_unified.c
@@ -1294,6 +1294,12 @@ xenUnifiedNodeGetFreeMemory (virConnectPtr conn)
     return(0);
 }
 
+static int
+xenUnifiedDomainEventEmitted (virDomainEventType evt)
+{
+    return xenStoreDomainEventEmitted(evt);
+}
+
 /*----- Register with libvirt.c, and initialise Xen drivers. -----*/
 
 #define HV_VERSION ((DOM0_INTERFACE_VERSION >> 24) * 1000000 +         \
@@ -1305,6 +1311,7 @@ static virDriver xenUnifiedDriver = {
     .no = VIR_DRV_XEN_UNIFIED,
     .name = "Xen",
     .ver = HV_VERSION,
+    .conns = NULL,
     .probe 			= xenUnifiedProbe,
     .open 			= xenUnifiedOpen,
     .close 			= xenUnifiedClose,
@@ -1359,6 +1366,7 @@ static virDriver xenUnifiedDriver = {
     .domainBlockPeek	= xenUnifiedDomainBlockPeek,
     .nodeGetCellsFreeMemory = xenUnifiedNodeGetCellsFreeMemory,
     .getFreeMemory = xenUnifiedNodeGetFreeMemory,
+    .domainEventEmitted = xenUnifiedDomainEventEmitted,
 };
 
 /**
diff --git a/src/xen_unified.h b/src/xen_unified.h
index c17b498..e4e7a59 100644
--- a/src/xen_unified.h
+++ b/src/xen_unified.h
@@ -12,6 +12,7 @@
 #define __VIR_XEN_UNIFIED_H__
 
 #include "internal.h"
+#include "xs_internal.h"
 #include "capabilities.h"
 
 #ifndef HAVE_WINSOCK2_H
@@ -110,6 +111,8 @@ struct _xenUnifiedPrivate {
      * xen_unified.c.
      */
     int opened[XEN_UNIFIED_NR_DRIVERS];
+
+    xenStoreWatchListPtr xsWatchHead;
 };
 
 typedef struct _xenUnifiedPrivate *xenUnifiedPrivatePtr;
diff --git a/src/xs_internal.c b/src/xs_internal.c
index 316604a..e60549b 100644
--- a/src/xs_internal.c
+++ b/src/xs_internal.c
@@ -17,6 +17,7 @@
 #include <fcntl.h>
 #include <sys/mman.h>
 #include <sys/ioctl.h>
+#include <sys/poll.h>
 
 #include <stdint.h>
 
@@ -28,6 +29,8 @@
 
 #include "internal.h"
 #include "driver.h"
+#include "memory.h"
+#include "event.h"
 #include "xen_unified.h"
 #include "xs_internal.h"
 #include "xen_internal.h" /* for xenHypervisorCheckID */
@@ -40,6 +43,9 @@
 #error "unsupported platform"
 #endif
 
+#define DEBUG(fmt,...) VIR_DEBUG(__FILE__, fmt,__VA_ARGS__)
+#define DEBUG0(msg) VIR_DEBUG(__FILE__, "%s", msg)
+
 #ifndef PROXY
 static char *xenStoreDomainGetOSType(virDomainPtr domain);
 
@@ -319,6 +325,19 @@ xenStoreOpen(virConnectPtr conn,
         }
         return (-1);
     }
+
+    /* Register for domain watch callbacks */
+    xenStoreAddWatch(priv->xsWatchHead, "@introduceDomain",
+                     "introduceDomain", xenStoreDomainIntroduced, priv);
+    xenStoreAddWatch(priv->xsWatchHead, "@releaseDomain",
+                     "releaseDomain", xenStoreDomainReleased, priv);
+    /* Add an event handle */
+    if (virEventAddHandle(xs_fileno(priv->xshandle),
+                          POLLIN | POLLPRI,
+                          xenStoreWatchEvent,
+                          conn) < 0) {
+        return (-1);
+    }
     return (0);
 }
 
@@ -344,6 +363,7 @@ xenStoreClose(virConnectPtr conn)
     if (priv->xshandle == NULL)
         return(-1);
 
+    xenStoreWatchListFree(priv->xsWatchHead);
     xs_daemon_close(priv->xshandle);
     return (0);
 }
@@ -937,3 +957,159 @@ char *xenStoreDomainGetName(virConnectPtr conn,
     return xs_read(priv->xshandle, 0, prop, &len);
 }
 
+void xenStoreWatchListFree(xenStoreWatchListPtr head)
+{
+    while (head) {
+        xenStoreWatchListPtr p = head->next;
+        VIR_FREE(head->path);
+        VIR_FREE(head->token);
+        VIR_FREE(head);
+        head = p;
+    }
+}
+
+int xenStoreAddWatch(xenStoreWatchListPtr head,
+                                 const char *path,
+                                 const char *token,
+                                 xenStoreWatchCallback cb,
+                                 void *opaque)
+{
+    xenStoreWatchListPtr watch;
+    xenStoreWatchListPtr p = head;
+
+    if (VIR_ALLOC(watch) < 0)
+        return -1;
+    watch->path   = strdup(path);
+    watch->token  = strdup(token);
+    watch->cb     = cb;
+    watch->opaque = opaque;
+
+    /* find end of list */
+    while(p) p = p->next;
+
+    DEBUG("Added xs watch %s %s", path, token);
+    p = watch;
+    return 0;
+}
+
+int xenStoreRemoveWatch(xenStoreWatchListPtr head,
+                                    const char *path,
+                                    const char *token)
+{
+    xenStoreWatchListPtr p = head;
+    xenStoreWatchListPtr last = head;
+    while(p) {
+        if( STREQ(path, p->path) &&
+            STREQ(token, p->token) ) {
+            if(last == p)
+                last = p->next;
+            else
+                last->next = p->next;
+            VIR_FREE(p->path);
+            VIR_FREE(p->token);
+            VIR_FREE(p);
+            DEBUG("Removed xs watch %s %s", path, token);
+            return 0;
+        }
+        last = p;
+        p = p->next;
+    }
+    return -1;
+}
+
+xenStoreWatchListPtr xenStoreFindWatch(xenStoreWatchListPtr head,
+                                  const char *path,
+                                  const char *token)
+{
+    xenStoreWatchListPtr p = head;
+    while(p) {
+        if( p &&
+            STREQ(path, p->path) &&
+            STREQ(token, p->token) ) {
+            return p;
+        }
+    }
+    return NULL;
+}
+
+void xenStoreWatchEvent(int fd ATTRIBUTE_UNUSED,
+                                 int events ATTRIBUTE_UNUSED,
+                                 void *data)
+{
+    char		 **event;
+    char		 *path;
+    char		 *token;
+    unsigned int	 stringCount;
+    xenStoreWatchListPtr sw;
+
+    virConnectPtr        conn = data;
+    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    if(!priv) return;
+    if(!priv->xshandle) return;
+
+    event = xs_read_watch(priv->xshandle, &stringCount);
+    if (event == NULL) {
+        /* Nothing to process here */
+        return;
+    }
+
+    path  = event[XS_WATCH_PATH];
+    token = event[XS_WATCH_TOKEN];
+
+    sw = xenStoreFindWatch(priv->xsWatchHead, path, token);
+    if( sw ) {
+        DEBUG("%s Calling watch callback for %s %s", __FUNCTION__, sw->path, sw->token);
+        sw->cb(conn, path, token, sw->opaque);
+    }
+    VIR_FREE(event);
+}
+
+static void
+xenStoreCheckDomainExists(const void *payload,
+                         const char *name ATTRIBUTE_UNUSED,
+                         const void *data ATTRIBUTE_UNUSED)
+{
+    virDomainPtr dom = (virDomainPtr)payload;
+    virBroadcastDomainEvent(dom, VIR_DOMAIN_EVENT_STOPPED);
+}
+
+/* The domain callback for the @introduceDomain watch */
+int xenStoreDomainIntroduced(virConnectPtr conn ATTRIBUTE_UNUSED,
+                             const char *path ATTRIBUTE_UNUSED,
+                             const char *token ATTRIBUTE_UNUSED,
+                             void *opaque ATTRIBUTE_UNUSED)
+{
+    /* TODO: Get dom somehow, and emit event
+        virConnectDispatchDomainEvent(conn, dom, VIR_DOMAIN_EVENT_STARTED);
+    */
+    return 0;
+}
+
+/* The domain callback for the @destroyDomain watch */
+int xenStoreDomainReleased(virConnectPtr conn ATTRIBUTE_UNUSED,
+                            const char *path  ATTRIBUTE_UNUSED,
+                            const char *token ATTRIBUTE_UNUSED,
+                            void *opaque ATTRIBUTE_UNUSED)
+{
+    /*
+    This will iterate over the domain list, and notice ones that
+    have potentially shut down of their own accord, and no longer
+    have a xenstore key.
+
+    TODO: Find a public way of doing this
+    virHashForEach(conn->domains, xenStoreCheckDomainExists, NULL);
+    */
+    return 0;
+}
+
+int xenStoreDomainEventEmitted(virDomainEventType evt)
+{
+    switch(evt) {
+        case VIR_DOMAIN_EVENT_STOPPED:
+            return true;
+        default:
+            return false;
+    }
+    return false;
+}
diff --git a/src/xs_internal.h b/src/xs_internal.h
index 6163ebc..39d59cb 100644
--- a/src/xs_internal.h
+++ b/src/xs_internal.h
@@ -53,4 +53,43 @@ char *		xenStoreDomainGetDiskID(virConnectPtr conn,
 char *          xenStoreDomainGetName(virConnectPtr conn,
                                       int id);
 
+typedef int (*xenStoreWatchCallback)(virConnectPtr conn,
+                                     const char *path,
+                                     const char *token,
+                                     void *opaque);
+typedef struct _xenStoreWatchList *xenStoreWatchListPtr;
+struct _xenStoreWatchList {
+    char *path;
+    char *token;
+    xenStoreWatchCallback cb;
+    void *opaque;
+    struct _xenStoreWatchList *next;
+};
+
+void            xenStoreWatchListFree(xenStoreWatchListPtr head);
+
+int             xenStoreAddWatch(xenStoreWatchListPtr head,
+                                 const char *path,
+                                 const char *token,
+                                 xenStoreWatchCallback cb,
+                                 void *opaque);
+int             xenStoreRemoveWatch(xenStoreWatchListPtr head,
+                                    const char *path,
+                                    const char *token);
+xenStoreWatchListPtr xenStoreFindWatch(xenStoreWatchListPtr head,
+                                  const char *path,
+                                  const char *token);
+void            xenStoreWatchEvent(int fd, int events, void *data);
+
+/* domain events */
+int xenStoreDomainIntroduced(virConnectPtr conn,
+                             const char *path,
+                             const char *token,
+                             void *opaque);
+int xenStoreDomainReleased(virConnectPtr conn,
+                            const char *path,
+                            const char *token,
+                            void *opaque);
+
+int xenStoreDomainEventEmitted(virDomainEventType evt);
 #endif /* __VIR_XS_INTERNAL_H__ */

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]