Monitor xenstore for domain changes
NOTE: this patch is currently untested
Signed-off-by: Ben Guthro <[EMAIL PROTECTED]>
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
[email protected]
https://www.redhat.com/mailman/listinfo/libvir-list