Monitor xenstore for domain changes NOTE: this patch is currently untested Signed-off-by: Ben Guthro <bguthro@xxxxxxxxxxxxxxx> 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__ */
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list