New patch attached with changes recommended in prior email from Daniel V.
Ben
diff --git a/src/xen_unified.c b/src/xen_unified.c
index 1ab204d..c5f84c8 100644
--- a/src/xen_unified.c
+++ b/src/xen_unified.c
@@ -222,6 +222,7 @@ xenUnifiedOpen (virConnectPtr conn, xmlURIPtr uri, virConnectAuthPtr auth, int f
{
int i, ret = VIR_DRV_OPEN_DECLINED;
xenUnifiedPrivatePtr priv;
+ virDomainEventCallbackListPtr cbList;
/* Refuse any scheme which isn't "xen://" or "http://". */
if (uri->scheme &&
@@ -248,6 +249,13 @@ xenUnifiedOpen (virConnectPtr conn, xmlURIPtr uri, virConnectAuthPtr auth, int f
}
conn->privateData = priv;
+ /* Allocate callback list */
+ if (VIR_ALLOC(cbList) < 0) {
+ xenUnifiedError (NULL, VIR_ERR_NO_MEMORY, "allocating callback list");
+ return VIR_DRV_OPEN_ERROR;
+ }
+ priv->domainEventCallbacks = cbList;
+
priv->handle = -1;
priv->xendConfigVersion = -1;
priv->type = -1;
@@ -345,6 +353,8 @@ xenUnifiedClose (virConnectPtr conn)
int i;
virCapabilitiesFree(priv->caps);
+ virDomainEventCallbackListFree(priv->domainEventCallbacks);
+
for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
if (priv->opened[i] && drivers[i]->close)
(void) drivers[i]->close (conn);
@@ -1280,6 +1290,29 @@ xenUnifiedNodeGetFreeMemory (virConnectPtr conn)
return(0);
}
+static int
+xenUnifiedDomainEventRegister (virConnectPtr conn,
+ void *callback,
+ void *opaque)
+{
+ GET_PRIVATE (conn);
+ conn->refs++;
+ return virDomainEventCallbackListAdd(conn, priv->domainEventCallbacks,
+ callback, opaque);
+}
+
+static int
+xenUnifiedDomainEventDeregister (virConnectPtr conn,
+ void *callback)
+{
+ int ret;
+ GET_PRIVATE (conn);
+ ret = virDomainEventCallbackListRemove(conn, priv->domainEventCallbacks,
+ callback);
+ virUnrefConnect(conn);
+ return ret;
+}
+
/*----- Register with libvirt.c, and initialise Xen drivers. -----*/
#define HV_VERSION ((DOM0_INTERFACE_VERSION >> 24) * 1000000 + \
@@ -1345,6 +1378,8 @@ static virDriver xenUnifiedDriver = {
.domainBlockPeek = xenUnifiedDomainBlockPeek,
.nodeGetCellsFreeMemory = xenUnifiedNodeGetCellsFreeMemory,
.getFreeMemory = xenUnifiedNodeGetFreeMemory,
+ .domainEventRegister = xenUnifiedDomainEventRegister,
+ .domainEventDeregister = xenUnifiedDomainEventDeregister,
};
/**
@@ -1364,3 +1399,141 @@ xenUnifiedRegister (void)
return virRegisterDriver (&xenUnifiedDriver);
}
+/**
+ * xenUnifiedDomainInfoListFree:
+ *
+ * Free the Domain Info List
+ */
+void
+xenUnifiedDomainInfoListFree(xenUnifiedDomainInfoListPtr list)
+{
+ int i;
+ for (i=0; i<list->count; i++) {
+ VIR_FREE(list->doms[i]->name);
+ VIR_FREE(list->doms[i]->uuid);
+ VIR_FREE(list->doms[i]);
+ }
+ VIR_FREE(list);
+}
+
+/**
+ * xenUnifiedAddDomainInfo:
+ *
+ * Add name and uuid to the domain info list
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+int
+xenUnifiedAddDomainInfo(xenUnifiedDomainInfoListPtr list,
+ int id, char *name, char *uuid)
+{
+ xenUnifiedDomainInfoPtr info;
+ int n;
+
+ /* check if we already have this callback on our list */
+ for (n=0; n < list->count; n++) {
+ if( STREQ(list->doms[n]->name, name) &&
+ STREQ(list->doms[n]->uuid, uuid)) {
+ DEBUG0("WARNING: dom already tracked");
+ return -1;
+ }
+ }
+
+ if (VIR_ALLOC(info) < 0)
+ goto memory_error;
+ if (!(info->name = strdup(name)))
+ goto memory_error;
+ if (!(info->uuid = strdup(uuid)))
+ goto memory_error;
+ info->id = id;
+
+ /* Make space on list */
+ n = list->count;
+ if (VIR_REALLOC_N(list->doms, n + 1) < 0) {
+ goto memory_error;
+ }
+
+ list->doms[n] = info;
+ list->count++;
+ return 0;
+memory_error:
+ xenUnifiedError (NULL, VIR_ERR_NO_MEMORY, "allocating domain info");
+ if (info && info->name)
+ VIR_FREE(info->name);
+ if (info && info->uuid)
+ VIR_FREE(info->uuid);
+ if (info)
+ VIR_FREE(info);
+ return -1;
+}
+
+/**
+ * xenUnifiedRemoveDomainInfo:
+ *
+ * Removes name and uuid to the domain info list
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+int
+xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr list,
+ int id, char *name, char *uuid)
+{
+ int i;
+ for (i = 0 ; i < list->count ; i++) {
+ if( list->doms[i]->id == id &&
+ STREQ(list->doms[i]->name, name) &&
+ STREQ(list->doms[i]->uuid, uuid)) {
+
+ VIR_FREE(list->doms[i]->name);
+ VIR_FREE(list->doms[i]->uuid);
+ VIR_FREE(list->doms[i]);
+
+ if (i < (list->count - 1))
+ memmove(list->doms + i,
+ list->doms + i + 1,
+ sizeof(*(list->doms)) *
+ (list->count - (i + 1)));
+
+ if (VIR_REALLOC_N(list->doms,
+ list->count - 1) < 0) {
+ ; /* Failure to reduce memory allocation isn't fatal */
+ }
+ list->count--;
+
+ return 0;
+ }
+ }
+ return -1;
+}
+
+/**
+ * xenUnifiedDomainEventDispatch:
+ *
+ * Dispatch domain events to registered callbacks
+ *
+ */
+ void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv,
+ virDomainPtr dom,
+ virDomainEventType evt)
+{
+ int i;
+ virDomainEventCallbackListPtr cbList;
+
+ if(!priv) return;
+
+ cbList = priv->domainEventCallbacks;
+ if(!cbList) return;
+
+ for(i=0 ; i < cbList->count ; i++) {
+ if(cbList->callbacks[i] && cbList->callbacks[i]->cb) {
+ if (dom) {
+ DEBUG("Dispatching callback %p %p event %d",
+ cbList->callbacks[i],
+ cbList->callbacks[i]->cb, evt);
+ cbList->callbacks[i]->cb(cbList->callbacks[i]->conn,
+ dom, evt,
+ cbList->callbacks[i]->opaque);
+ }
+ }
+ }
+}
diff --git a/src/xen_unified.h b/src/xen_unified.h
index 48415a8..e0e5243 100644
--- a/src/xen_unified.h
+++ b/src/xen_unified.h
@@ -14,6 +14,8 @@
#include "internal.h"
#include "capabilities.h"
#include "driver.h"
+#include "xs_internal.h"
+#include "domain_event.h"
#ifndef HAVE_WINSOCK2_H
#include <sys/un.h>
@@ -85,6 +87,26 @@ struct xenUnifiedDriver {
virDrvDomainSetSchedulerParameters domainSetSchedulerParameters;
};
+/* xenUnifiedDomainInfoPtr:
+ * The minimal state we have about active domains
+ * This is the minmal info necessary to still get a
+ * virDomainPtr when the domain goes away
+ */
+struct _xenUnifiedDomainInfo {
+ int id;
+ char *name;
+ char *uuid;
+};
+typedef struct _xenUnifiedDomainInfo xenUnifiedDomainInfo;
+typedef xenUnifiedDomainInfo *xenUnifiedDomainInfoPtr;
+
+struct _xenUnifiedDomainInfoList {
+ unsigned int count;
+ xenUnifiedDomainInfoPtr *doms;
+};
+typedef struct _xenUnifiedDomainInfoList xenUnifiedDomainInfoList;
+typedef xenUnifiedDomainInfoList *xenUnifiedDomainInfoListPtr;
+
/* xenUnifiedPrivatePtr:
*
* Per-connection private data, stored in conn->privateData. All Xen
@@ -113,6 +135,15 @@ struct _xenUnifiedPrivate {
* xen_unified.c.
*/
int opened[XEN_UNIFIED_NR_DRIVERS];
+
+ /* A list of xenstore watches */
+ xenStoreWatchListPtr xsWatchList;
+
+ /* An list of active domain name/uuids */
+ xenUnifiedDomainInfoListPtr domInfoList;
+
+ /* An list of callbacks */
+ virDomainEventCallbackListPtr domainEventCallbacks;
};
typedef struct _xenUnifiedPrivate *xenUnifiedPrivatePtr;
@@ -122,4 +153,12 @@ int xenNbCells(virConnectPtr conn);
int xenNbCpus(virConnectPtr conn);
char *xenDomainUsedCpus(virDomainPtr dom);
+void xenUnifiedDomainInfoListFree(xenUnifiedDomainInfoListPtr info);
+int xenUnifiedAddDomainInfo(xenUnifiedDomainInfoListPtr info,
+ int id, char *name, char *uuid);
+int xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr info,
+ int id, char *name, char *uuid);
+void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv,
+ virDomainPtr dom,
+ virDomainEventType evt);
#endif /* __VIR_XEN_UNIFIED_H__ */
diff --git a/src/xs_internal.c b/src/xs_internal.c
index b096acd..68fda46 100644
--- a/src/xs_internal.c
+++ b/src/xs_internal.c
@@ -29,6 +29,8 @@
#include "virterror_internal.h"
#include "datatypes.h"
#include "driver.h"
+#include "memory.h"
+#include "event.h"
#include "xen_unified.h"
#include "xs_internal.h"
#include "xen_internal.h" /* for xenHypervisorCheckID */
@@ -303,7 +305,53 @@ xenStoreOpen(virConnectPtr conn,
}
return (-1);
}
- return (0);
+
+#ifndef PROXY
+ /* Init domInfoList */
+ if ( VIR_ALLOC(priv->domInfoList ) < 0) {
+ virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("failed to allocate domInfoList"));
+ return -1;
+ }
+
+ /* Init watch list before filling in domInfoList,
+ so we can know if it is the first time through
+ when the callback fires */
+ if ( VIR_ALLOC(priv->xsWatchList) < 0 ) {
+ virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("failed to allocate xsWatchList"));
+ return -1;
+ }
+
+ /* This will get called once at start */
+ if ( xenStoreAddWatch(conn, "@releaseDomain",
+ "releaseDomain", xenStoreDomainReleased, priv) < 0 )
+ {
+ DEBUG0("Error Adding Watch @releaseDomain\n");
+ return -1;
+ }
+
+ /* The initial call of this will fill domInfoList */
+ if( xenStoreAddWatch(conn, "@introduceDomain",
+ "introduceDomain", xenStoreDomainIntroduced, priv) < 0 )
+ {
+ DEBUG0("Error Adding Watch @introduceDomain\n");
+ return -1;
+ }
+
+ /* Add an event handle */
+ if (virEventAddHandle(xs_fileno(priv->xshandle),
+ VIR_EVENT_HANDLE_READABLE,
+ xenStoreWatchEvent,
+ conn) < 0) {
+ virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("failed to handle"));
+
+ return -1;
+ }
+
+#endif //PROXY
+ return 0;
}
/**
@@ -317,6 +365,7 @@ xenStoreOpen(virConnectPtr conn,
int
xenStoreClose(virConnectPtr conn)
{
+ int fd;
xenUnifiedPrivatePtr priv;
if (conn == NULL) {
@@ -325,10 +374,30 @@ xenStoreClose(virConnectPtr conn)
}
priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+ if (xenStoreRemoveWatch(conn, "@introduceDomain", "introduceDomain") < 0) {
+ DEBUG0("Warning, could not remove @introduceDomain watch");
+ /* not fatal */
+ }
+
+ if (xenStoreRemoveWatch(conn, "@releaseDomain", "releaseDomain") < 0) {
+ DEBUG0("Warning, could not remove @releaseDomain watch");
+ /* not fatal */
+ }
+
+ xenStoreWatchListFree(priv->xsWatchList);
+#ifndef PROXY
+ xenUnifiedDomainInfoListFree(priv->domInfoList);
+#endif
if (priv->xshandle == NULL)
return(-1);
+ fd = xs_fileno(priv->xshandle);
+ virEventRemoveHandle(fd);
+ close(fd);
xs_daemon_close(priv->xshandle);
+ priv->xshandle = NULL;
+
return (0);
}
@@ -921,3 +990,357 @@ char *xenStoreDomainGetName(virConnectPtr conn,
return xs_read(priv->xshandle, 0, prop, &len);
}
+#ifndef PROXY
+char *xenStoreDomainGetUUID(virConnectPtr conn,
+ int id) {
+ char prop[200];
+ xenUnifiedPrivatePtr priv;
+ unsigned int len;
+ char *vm_string;
+ char *ret;
+
+ priv = (xenUnifiedPrivatePtr) conn->privateData;
+ if (priv->xshandle == NULL)
+ return(NULL);
+
+ snprintf(prop, 199, "/local/domain/%d/vm", id);
+ prop[199] = 0;
+ // This will return something like
+ // /vm/00000000-0000-0000-0000-000000000000
+ vm_string = xs_read(priv->xshandle, 0, prop, &len);
+
+ // remove "/vm/"
+ ret = strdup(vm_string + 4);
+
+ VIR_FREE(vm_string);
+
+ return ret;
+}
+#endif //PROXY
+
+void xenStoreWatchListFree(xenStoreWatchListPtr list)
+{
+ int i;
+ for (i=0; i<list->count; i++) {
+ VIR_FREE(list->watches[i]->path);
+ VIR_FREE(list->watches[i]->token);
+ VIR_FREE(list->watches[i]);
+ }
+ VIR_FREE(list);
+}
+
+int xenStoreAddWatch(virConnectPtr conn,
+ const char *path,
+ const char *token,
+ xenStoreWatchCallback cb,
+ void *opaque)
+{
+ xenStoreWatchPtr watch;
+ int n;
+ xenStoreWatchListPtr list;
+ xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+ if (priv->xshandle == NULL)
+ return -1;
+
+ list = priv->xsWatchList;
+ if(!list)
+ return -1;
+
+ /* check if we already have this callback on our list */
+ for (n=0; n < list->count; n++) {
+ if( STREQ(list->watches[n]->path, path) &&
+ STREQ(list->watches[n]->token, token)) {
+ DEBUG0("WARNING: Watch already tracked");
+ return -1;
+ }
+ }
+
+ if (VIR_ALLOC(watch) < 0)
+ return -1;
+ watch->path = strdup(path);
+ watch->token = strdup(token);
+ watch->cb = cb;
+ watch->opaque = opaque;
+
+ /* Make space on list */
+ n = list->count;
+ if (VIR_REALLOC_N(list->watches, n + 1) < 0) {
+ DEBUG0("Error reallocating list");
+ VIR_FREE(watch);
+ return -1;
+ }
+
+ list->watches[n] = watch;
+ list->count++;
+
+ conn->refs++;
+
+ return xs_watch(priv->xshandle, watch->path, watch->token);
+}
+
+int xenStoreRemoveWatch(virConnectPtr conn,
+ const char *path,
+ const char *token)
+{
+ int i;
+ xenStoreWatchListPtr list;
+ xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+ if (priv->xshandle == NULL)
+ return -1;
+
+ list = priv->xsWatchList;
+ if(!list)
+ return -1;
+
+ for (i = 0 ; i < list->count ; i++) {
+ if( STREQ(list->watches[i]->path, path) &&
+ STREQ(list->watches[i]->token, token)) {
+
+ if (!xs_unwatch(priv->xshandle,
+ list->watches[i]->path,
+ list->watches[i]->path))
+ {
+ DEBUG0("WARNING: Could not remove watch");
+ /* Not fatal, continue */
+ }
+
+ VIR_FREE(list->watches[i]->path);
+ VIR_FREE(list->watches[i]->token);
+ VIR_FREE(list->watches[i]);
+
+ if (i < (list->count - 1))
+ memmove(list->watches + i,
+ list->watches + i + 1,
+ sizeof(*(list->watches)) *
+ (list->count - (i + 1)));
+
+ if (VIR_REALLOC_N(list->watches,
+ list->count - 1) < 0) {
+ ; /* Failure to reduce memory allocation isn't fatal */
+ }
+ list->count--;
+#ifndef PROXY
+ virUnrefConnect(conn);
+#endif
+ return 0;
+ }
+ }
+ return -1;
+}
+
+xenStoreWatchPtr xenStoreFindWatch(xenStoreWatchListPtr list,
+ const char *path,
+ const char *token)
+{
+ int i;
+ for (i = 0 ; i < list->count ; i++)
+ if( STREQ(path, list->watches[i]->path) &&
+ STREQ(token, list->watches[i]->token) )
+ return list->watches[i];
+
+ return NULL;
+}
+
+void xenStoreWatchEvent(int fd ATTRIBUTE_UNUSED,
+ int events ATTRIBUTE_UNUSED,
+ void *data)
+{
+ char **event;
+ char *path;
+ char *token;
+ unsigned int stringCount;
+ xenStoreWatchPtr 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)
+ return;
+
+ path = event[XS_WATCH_PATH];
+ token = event[XS_WATCH_TOKEN];
+
+ sw = xenStoreFindWatch(priv->xsWatchList, path, token);
+ if( sw )
+ sw->cb(conn, path, token, sw->opaque);
+ VIR_FREE(event);
+}
+
+#ifndef PROXY
+/* The domain callback for the @introduceDomain watch */
+int xenStoreDomainIntroduced(virConnectPtr conn,
+ const char *path ATTRIBUTE_UNUSED,
+ const char *token ATTRIBUTE_UNUSED,
+ void *opaque)
+{
+ int i, j;
+ int new_domain_cnt;
+ int *new_domids;
+ char *name;
+ char *uuid;
+ int nread;
+
+ xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) opaque;
+
+retry:
+ new_domain_cnt = xenStoreNumOfDomains(conn);
+ if( VIR_ALLOC_N(new_domids,new_domain_cnt) < 0 ) {
+ virXenStoreError(NULL, VIR_ERR_NO_MEMORY,
+ "%s", _("failed to allocate domids"));
+ return -1;
+ }
+ nread = xenStoreListDomains(conn, new_domids, new_domain_cnt);
+ if (nread != new_domain_cnt) {
+ // mismatch. retry this read
+ VIR_FREE(new_domids);
+ goto retry;
+ }
+
+ // Initial callback, fill list (This should at least contain dom0)
+ if(!priv->domInfoList->count) {
+ for (i=0 ; i < new_domain_cnt ; i++) {
+ if (!(name = xenStoreDomainGetName(conn, new_domids[i]))) {
+ continue;
+ }
+ if (!(uuid = xenStoreDomainGetUUID(conn, new_domids[i]))) {
+ VIR_FREE(name);
+ continue;
+ }
+ xenUnifiedAddDomainInfo(priv->domInfoList, new_domids[i],
+ name, uuid);
+ VIR_FREE(name);
+ VIR_FREE(uuid);
+ }
+ VIR_FREE(new_domids);
+ return 0;
+ }
+
+ for (i=0 ; i < new_domain_cnt ; i++) {
+ if (!(name = xenStoreDomainGetName(conn, new_domids[i]))) {
+ continue;
+ }
+ if (!(uuid = xenStoreDomainGetUUID(conn, new_domids[i]))) {
+ VIR_FREE(name);
+ continue;
+ }
+ /* We must iterate over both lists to avoid a race where
+ 2 domains were created by the time we get here */
+ for (j=0 ; j < priv->domInfoList->count ; j++) {
+ if( !STREQ(name, priv->domInfoList->doms[j]->name) ||
+ !STREQ(uuid, priv->domInfoList->doms[j]->uuid) ) {
+ virDomainPtr dom = virGetDomain(conn, name, (unsigned char*)uuid);
+ if(dom) {
+ dom->id = new_domids[i];
+
+ /* This domain was not in the old list. Emit an event */
+ xenUnifiedDomainEventDispatch(priv, dom,
+ VIR_DOMAIN_EVENT_STARTED);
+
+ /* Add to the list */
+ xenUnifiedAddDomainInfo(priv->domInfoList,
+ new_domids[i], name, uuid);
+ }
+ virUnrefDomain(dom);
+ }
+ }
+
+ VIR_FREE(name);
+ VIR_FREE(uuid);
+ }
+ VIR_FREE(new_domids);
+ return 0;
+}
+
+/* The domain callback for the @destroyDomain watch */
+int xenStoreDomainReleased(virConnectPtr conn,
+ const char *path ATTRIBUTE_UNUSED,
+ const char *token ATTRIBUTE_UNUSED,
+ void *opaque)
+{
+ int i, j, found, removed;
+ int new_domain_cnt;
+ int *new_domids;
+ char *name;
+ char *uuid;
+ int nread;
+
+ xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) opaque;
+
+ if(!priv->domInfoList->count) return 0;
+
+retry:
+ new_domain_cnt = xenStoreNumOfDomains(conn);
+
+ if( VIR_ALLOC_N(new_domids,new_domain_cnt) < 0 ) {
+ virXenStoreError(NULL, VIR_ERR_NO_MEMORY,
+ "%s", _("failed to allocate domids"));
+ return -1;
+ }
+ nread = xenStoreListDomains(conn, new_domids, new_domain_cnt);
+ if (nread != new_domain_cnt) {
+ // mismatch. retry this read
+ VIR_FREE(new_domids);
+ goto retry;
+ }
+
+ removed = 0;
+ for (j=0 ; j < priv->domInfoList->count ; j++) {
+ found = 0;
+ for (i=0 ; i < new_domain_cnt ; i++) {
+ if (!(name = xenStoreDomainGetName(conn, new_domids[i]))) {
+ continue;
+ }
+
+ if (!(uuid = xenStoreDomainGetUUID(conn, new_domids[i]))) {
+ VIR_FREE(name);
+ continue;
+ }
+
+ if( STREQ(name, priv->domInfoList->doms[j]->name) ||
+ STREQ(uuid, priv->domInfoList->doms[j]->uuid) ) {
+ found = 1;
+ VIR_FREE(name);
+ VIR_FREE(uuid);
+ break;
+ }
+
+ VIR_FREE(name);
+ VIR_FREE(uuid);
+ }
+
+ if (!found) {
+ virDomainPtr dom = virGetDomain(conn,
+ priv->domInfoList->doms[j]->name,
+ (unsigned char*)priv->domInfoList->doms[j]->uuid);
+ if(dom) {
+ dom->id = -1;
+ /* This domain was not in the new list. Emit an event */
+ xenUnifiedDomainEventDispatch(priv, dom,
+ VIR_DOMAIN_EVENT_STOPPED);
+ /* Remove from the list */
+ xenUnifiedRemoveDomainInfo(priv->domInfoList,
+ priv->domInfoList->doms[j]->id,
+ priv->domInfoList->doms[j]->name,
+ priv->domInfoList->doms[j]->uuid);
+
+ virUnrefDomain(dom);
+ removed=1;
+ }
+ }
+ }
+
+ VIR_FREE(new_domids);
+ if(!removed) {
+ // xenstore sometimes calls us back before
+ // domids are fully torn down
+ usleep(1000);
+ goto retry;
+ }
+ return 0;
+}
+#endif //PROXY
diff --git a/src/xs_internal.h b/src/xs_internal.h
index 6163ebc..006e0e1 100644
--- a/src/xs_internal.h
+++ b/src/xs_internal.h
@@ -52,5 +52,56 @@ char * xenStoreDomainGetDiskID(virConnectPtr conn,
const char *dev);
char * xenStoreDomainGetName(virConnectPtr conn,
int id);
+char * xenStoreDomainGetUUID(virConnectPtr conn,
+ int id);
+
+typedef int (*xenStoreWatchCallback)(virConnectPtr conn,
+ const char *path,
+ const char *token,
+ void *opaque);
+
+struct _xenStoreWatch {
+ char *path;
+ char *token;
+ xenStoreWatchCallback cb;
+ void *opaque;
+};
+typedef struct _xenStoreWatch xenStoreWatch;
+typedef xenStoreWatch *xenStoreWatchPtr;
+
+struct _xenStoreWatchList {
+ unsigned int count;
+ xenStoreWatchPtr *watches;
+};
+typedef struct _xenStoreWatchList xenStoreWatchList;
+typedef xenStoreWatchList *xenStoreWatchListPtr;
+
+
+void xenStoreWatchListFree(xenStoreWatchListPtr head);
+
+int xenStoreAddWatch(virConnectPtr conn,
+ const char *path,
+ const char *token,
+ xenStoreWatchCallback cb,
+ void *opaque);
+int xenStoreRemoveWatch(virConnectPtr conn,
+ const char *path,
+ const char *token);
+xenStoreWatchPtr xenStoreFindWatch(xenStoreWatchListPtr list,
+ 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