mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 13:45:38 +00:00
QEMU domain event thread safety
This commit is contained in:
parent
3527f16a94
commit
bc898df2c7
15
ChangeLog
15
ChangeLog
@ -1,3 +1,18 @@
|
||||
Thu Dec 4 21:09:41 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
|
||||
|
||||
QEMU domain events thread safety
|
||||
* src/domain_event.c, src/domain_event.h: Add convenient
|
||||
methods for dispatching a list of events, and a single
|
||||
event to a list of callbacks. Change signature of push
|
||||
method to take a pre-allocated virDomainEventPtr object
|
||||
* src/libvirt_sym.version.in: Export new event methods
|
||||
to daemon code / drivers
|
||||
* src/qemu_conf.h, src/qemu_driver.c: Make event dispatch
|
||||
threadsafe by doing asynchronously
|
||||
* src/remote_internal.c, src/xen_inotify.c, src/xen_unified.c,
|
||||
src/xen_unified.h, src/xs_internal.c: Update for changes in
|
||||
domain event APIs
|
||||
|
||||
Thu Dec 4 21:05:41 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
|
||||
|
||||
* src/qemu_conf.h: Add a driver lock variable
|
||||
|
@ -125,6 +125,49 @@ virDomainEventCallbackListRemoveConn(virConnectPtr conn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int virDomainEventCallbackListMarkDelete(virConnectPtr conn,
|
||||
virDomainEventCallbackListPtr cbList,
|
||||
virConnectDomainEventCallback callback)
|
||||
{
|
||||
int i;
|
||||
for (i = 0 ; i < cbList->count ; i++) {
|
||||
if (cbList->callbacks[i]->conn == conn &&
|
||||
cbList->callbacks[i]->cb == callback) {
|
||||
cbList->callbacks[i]->deleted = 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int virDomainEventCallbackListPurgeMarked(virDomainEventCallbackListPtr cbList)
|
||||
{
|
||||
int old_count = cbList->count;
|
||||
int i;
|
||||
for (i = 0 ; i < cbList->count ; i++) {
|
||||
if (cbList->callbacks[i]->deleted) {
|
||||
virFreeCallback freecb = cbList->callbacks[i]->freecb;
|
||||
if (freecb)
|
||||
(*freecb)(cbList->callbacks[i]->opaque);
|
||||
virUnrefConnect(cbList->callbacks[i]->conn);
|
||||
VIR_FREE(cbList->callbacks[i]);
|
||||
|
||||
if (i < (cbList->count - 1))
|
||||
memmove(cbList->callbacks + i,
|
||||
cbList->callbacks + i + 1,
|
||||
sizeof(*(cbList->callbacks)) *
|
||||
(cbList->count - (i + 1)));
|
||||
cbList->count--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
if (cbList->count < old_count &&
|
||||
VIR_REALLOC_N(cbList->callbacks, cbList->count) < 0) {
|
||||
; /* Failure to reduce memory allocation isn't fatal */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* virDomainEventCallbackListAdd:
|
||||
* @conn: pointer to the connection
|
||||
@ -182,6 +225,62 @@ virDomainEventCallbackListAdd(virConnectPtr conn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void virDomainEventFree(virDomainEventPtr event)
|
||||
{
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
VIR_FREE(event->name);
|
||||
VIR_FREE(event);
|
||||
}
|
||||
|
||||
|
||||
virDomainEventQueuePtr virDomainEventQueueNew(void)
|
||||
{
|
||||
virDomainEventQueuePtr ret;
|
||||
|
||||
if (VIR_ALLOC(ret) < 0)
|
||||
return NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
virDomainEventPtr virDomainEventNew(int id, const char *name,
|
||||
const unsigned char *uuid,
|
||||
int type, int detail)
|
||||
{
|
||||
virDomainEventPtr event;
|
||||
|
||||
if (VIR_ALLOC(event) < 0)
|
||||
return NULL;
|
||||
|
||||
event->type = type;
|
||||
event->detail = detail;
|
||||
if (!(event->name = strdup(name))) {
|
||||
VIR_FREE(event);
|
||||
return NULL;
|
||||
}
|
||||
event->id = id;
|
||||
memcpy(event->uuid, uuid, VIR_UUID_BUFLEN);
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
virDomainEventPtr virDomainEventNewFromDom(virDomainPtr dom, int type, int detail)
|
||||
{
|
||||
return virDomainEventNew(dom->id, dom->name, dom->uuid, type, detail);
|
||||
}
|
||||
|
||||
virDomainEventPtr virDomainEventNewFromObj(virDomainObjPtr obj, int type, int detail)
|
||||
{
|
||||
return virDomainEventNewFromDef(obj->def, type, detail);
|
||||
}
|
||||
|
||||
virDomainEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int detail)
|
||||
{
|
||||
return virDomainEventNew(def->id, def->name, def->uuid, type, detail);
|
||||
}
|
||||
|
||||
/**
|
||||
* virDomainEventQueueFree:
|
||||
* @queue: pointer to the queue
|
||||
@ -192,14 +291,18 @@ void
|
||||
virDomainEventQueueFree(virDomainEventQueuePtr queue)
|
||||
{
|
||||
int i;
|
||||
for ( i=0 ; i<queue->count ; i++ ) {
|
||||
VIR_FREE(queue->events[i]);
|
||||
if (!queue)
|
||||
return;
|
||||
|
||||
for (i = 0; i < queue->count ; i++) {
|
||||
virDomainEventFree(queue->events[i]);
|
||||
}
|
||||
VIR_FREE(queue->events);
|
||||
VIR_FREE(queue);
|
||||
}
|
||||
|
||||
/**
|
||||
* virDomainEventCallbackQueuePop:
|
||||
* virDomainEventQueuePop:
|
||||
* @evtQueue: the queue of events
|
||||
*
|
||||
* Internal function to pop off, and return the front of the queue
|
||||
@ -208,7 +311,7 @@ virDomainEventQueueFree(virDomainEventQueuePtr queue)
|
||||
* Returns: virDomainEventPtr on success NULL on failure.
|
||||
*/
|
||||
virDomainEventPtr
|
||||
virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue)
|
||||
virDomainEventQueuePop(virDomainEventQueuePtr evtQueue)
|
||||
{
|
||||
virDomainEventPtr ret;
|
||||
|
||||
@ -232,9 +335,8 @@ virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue)
|
||||
}
|
||||
|
||||
/**
|
||||
* virDomainEventCallbackQueuePush:
|
||||
* virDomainEventQueuePush:
|
||||
* @evtQueue: the dom event queue
|
||||
* @dom: the domain to add
|
||||
* @event: the event to add
|
||||
*
|
||||
* Internal function to push onto the back of an virDomainEventQueue
|
||||
@ -242,37 +344,76 @@ virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int
|
||||
virDomainEventCallbackQueuePush(virDomainEventQueuePtr evtQueue,
|
||||
virDomainPtr dom,
|
||||
int event,
|
||||
int detail)
|
||||
virDomainEventQueuePush(virDomainEventQueuePtr evtQueue,
|
||||
virDomainEventPtr event)
|
||||
{
|
||||
virDomainEventPtr domEvent;
|
||||
|
||||
/* Check incoming */
|
||||
if ( !evtQueue ) {
|
||||
if (!evtQueue) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Allocate new event */
|
||||
if (VIR_ALLOC(domEvent) < 0) {
|
||||
DEBUG0("Error allocating event");
|
||||
return -1;
|
||||
}
|
||||
domEvent->dom = dom;
|
||||
domEvent->event = event;
|
||||
domEvent->detail = detail;
|
||||
|
||||
/* Make space on queue */
|
||||
if (VIR_REALLOC_N(evtQueue->events,
|
||||
evtQueue->count + 1) < 0) {
|
||||
DEBUG0("Error reallocating queue");
|
||||
VIR_FREE(domEvent);
|
||||
return -1;
|
||||
}
|
||||
|
||||
evtQueue->events[evtQueue->count] = domEvent;
|
||||
evtQueue->events[evtQueue->count] = event;
|
||||
evtQueue->count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void virDomainEventDispatchDefaultFunc(virConnectPtr conn,
|
||||
virDomainEventPtr event,
|
||||
virConnectDomainEventCallback cb,
|
||||
void *cbopaque,
|
||||
void *opaque ATTRIBUTE_UNUSED)
|
||||
{
|
||||
virDomainPtr dom = virGetDomain(conn, event->name, event->uuid);
|
||||
if (dom) {
|
||||
dom->id = event->id;
|
||||
(*cb)(conn, dom, event->type, event->detail, cbopaque);
|
||||
virDomainFree(dom);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void virDomainEventDispatch(virDomainEventPtr event,
|
||||
virDomainEventCallbackListPtr callbacks,
|
||||
virDomainEventDispatchFunc dispatch,
|
||||
void *opaque)
|
||||
{
|
||||
int i;
|
||||
/* Cache this now, since we may be dropping the lock,
|
||||
and have more callbacks added. We're guarenteed not
|
||||
to have any removed */
|
||||
int cbCount = callbacks->count;
|
||||
|
||||
for (i = 0 ; i < cbCount ; i++) {
|
||||
if (callbacks->callbacks[i] &&
|
||||
!callbacks->callbacks[i]->deleted) {
|
||||
(*dispatch)(callbacks->callbacks[i]->conn,
|
||||
event,
|
||||
callbacks->callbacks[i]->cb,
|
||||
callbacks->callbacks[i]->opaque,
|
||||
opaque);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void virDomainEventQueueDispatch(virDomainEventQueuePtr queue,
|
||||
virDomainEventCallbackListPtr callbacks,
|
||||
virDomainEventDispatchFunc dispatch,
|
||||
void *opaque)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < queue->count ; i++) {
|
||||
virDomainEventDispatch(queue->events[i], callbacks, dispatch, opaque);
|
||||
virDomainEventFree(queue->events[i]);
|
||||
}
|
||||
VIR_FREE(queue->events);
|
||||
queue->count = 0;
|
||||
}
|
||||
|
@ -22,16 +22,17 @@
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
#ifndef __DOMAIN_EVENT_H__
|
||||
#define __DOMAIN_EVENT_H__
|
||||
|
||||
#include "domain_conf.h"
|
||||
|
||||
struct _virDomainEventCallback {
|
||||
virConnectPtr conn;
|
||||
virConnectDomainEventCallback cb;
|
||||
void *opaque;
|
||||
virFreeCallback freecb;
|
||||
|
||||
int deleted;
|
||||
};
|
||||
typedef struct _virDomainEventCallback virDomainEventCallback;
|
||||
typedef virDomainEventCallback *virDomainEventCallbackPtr;
|
||||
@ -58,13 +59,20 @@ int virDomainEventCallbackListRemove(virConnectPtr conn,
|
||||
int virDomainEventCallbackListRemoveConn(virConnectPtr conn,
|
||||
virDomainEventCallbackListPtr cbList);
|
||||
|
||||
int virDomainEventCallbackListMarkDelete(virConnectPtr conn,
|
||||
virDomainEventCallbackListPtr cbList,
|
||||
virConnectDomainEventCallback callback);
|
||||
int virDomainEventCallbackListPurgeMarked(virDomainEventCallbackListPtr cbList);
|
||||
|
||||
/**
|
||||
* Dispatching domain events that come in while
|
||||
* in a call / response rpc
|
||||
*/
|
||||
struct _virDomainEvent {
|
||||
virDomainPtr dom;
|
||||
int event;
|
||||
int id;
|
||||
char *name;
|
||||
unsigned char uuid[VIR_UUID_BUFLEN];
|
||||
int type;
|
||||
int detail;
|
||||
};
|
||||
typedef struct _virDomainEvent virDomainEvent;
|
||||
@ -77,15 +85,40 @@ struct _virDomainEventQueue {
|
||||
typedef struct _virDomainEventQueue virDomainEventQueue;
|
||||
typedef virDomainEventQueue *virDomainEventQueuePtr;
|
||||
|
||||
int virDomainEventCallbackQueuePush(virDomainEventQueuePtr evtQueue,
|
||||
virDomainPtr dom,
|
||||
int event,
|
||||
int detail);
|
||||
virDomainEventQueuePtr virDomainEventQueueNew(void);
|
||||
|
||||
virDomainEventPtr virDomainEventNew(int id, const char *name, const unsigned char *uuid, int type, int detail);
|
||||
virDomainEventPtr virDomainEventNewFromDom(virDomainPtr dom, int type, int detail);
|
||||
virDomainEventPtr virDomainEventNewFromObj(virDomainObjPtr obj, int type, int detail);
|
||||
virDomainEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int detail);
|
||||
|
||||
int virDomainEventQueuePush(virDomainEventQueuePtr evtQueue,
|
||||
virDomainEventPtr event);
|
||||
|
||||
virDomainEventPtr
|
||||
virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue);
|
||||
virDomainEventQueuePop(virDomainEventQueuePtr evtQueue);
|
||||
|
||||
void virDomainEventFree(virDomainEventPtr event);
|
||||
void virDomainEventQueueFree(virDomainEventQueuePtr queue);
|
||||
|
||||
typedef void (*virDomainEventDispatchFunc)(virConnectPtr conn,
|
||||
virDomainEventPtr event,
|
||||
virConnectDomainEventCallback cb,
|
||||
void *cbopaque,
|
||||
void *opaque);
|
||||
void virDomainEventDispatchDefaultFunc(virConnectPtr conn,
|
||||
virDomainEventPtr event,
|
||||
virConnectDomainEventCallback cb,
|
||||
void *cbopaque,
|
||||
void *opaque);
|
||||
|
||||
void virDomainEventDispatch(virDomainEventPtr event,
|
||||
virDomainEventCallbackListPtr cbs,
|
||||
virDomainEventDispatchFunc dispatch,
|
||||
void *opaque);
|
||||
void virDomainEventQueueDispatch(virDomainEventQueuePtr queue,
|
||||
virDomainEventCallbackListPtr cbs,
|
||||
virDomainEventDispatchFunc dispatch,
|
||||
void *opaque);
|
||||
|
||||
#endif
|
||||
|
@ -383,9 +383,21 @@ LIBVIRT_PRIVATE_@VERSION@ {
|
||||
virDomainEventCallbackListFree;
|
||||
virDomainEventCallbackListRemove;
|
||||
virDomainEventCallbackListRemoveConn;
|
||||
virDomainEventCallbackListMarkDelete;
|
||||
virDomainEventCallbackListPurgeMarked;
|
||||
virDomainEventQueueNew;
|
||||
virDomainEventQueueFree;
|
||||
virDomainEventCallbackQueuePop;
|
||||
virDomainEventCallbackQueuePush;
|
||||
virDomainEventQueuePop;
|
||||
virDomainEventQueuePush;
|
||||
virDomainEventNew;
|
||||
virDomainEventNewFromDom;
|
||||
virDomainEventNewFromObj;
|
||||
virDomainEventNewFromDef;
|
||||
virDomainEventFree;
|
||||
virDomainEventDispatchDefaultFunc;
|
||||
virDomainEventDispatch;
|
||||
virDomainEventQueueDispatch;
|
||||
|
||||
|
||||
|
||||
/* driver.h */
|
||||
|
@ -71,6 +71,9 @@ struct qemud_driver {
|
||||
|
||||
/* An array of callbacks */
|
||||
virDomainEventCallbackListPtr domainEventCallbacks;
|
||||
virDomainEventQueuePtr domainEventQueue;
|
||||
int domainEventTimer;
|
||||
int domainEventDispatching;
|
||||
};
|
||||
|
||||
/* Port numbers used for KVM migration. */
|
||||
|
@ -115,10 +115,10 @@ static int qemudSetNonBlock(int fd) {
|
||||
}
|
||||
|
||||
|
||||
static void qemudDomainEventDispatch (struct qemud_driver *driver,
|
||||
virDomainObjPtr vm,
|
||||
int event,
|
||||
int detail);
|
||||
|
||||
static void qemuDomainEventFlush(int timer, void *opaque);
|
||||
static void qemuDomainEventQueue(struct qemud_driver *driver,
|
||||
virDomainEventPtr event);
|
||||
|
||||
static void qemudDispatchVMEvent(int watch,
|
||||
int fd,
|
||||
@ -160,8 +160,12 @@ qemudAutostartConfigs(struct qemud_driver *driver) {
|
||||
vm->def->name,
|
||||
err ? err->message : NULL);
|
||||
} else {
|
||||
qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_STARTED,
|
||||
VIR_DOMAIN_EVENT_STARTED_BOOTED);
|
||||
virDomainEventPtr event =
|
||||
virDomainEventNewFromObj(vm,
|
||||
VIR_DOMAIN_EVENT_STARTED,
|
||||
VIR_DOMAIN_EVENT_STARTED_BOOTED);
|
||||
if (event)
|
||||
qemuDomainEventQueue(driver, event);
|
||||
}
|
||||
}
|
||||
virDomainObjUnlock(vm);
|
||||
@ -192,6 +196,12 @@ qemudStartup(void) {
|
||||
/* Init callback list */
|
||||
if(VIR_ALLOC(qemu_driver->domainEventCallbacks) < 0)
|
||||
goto out_of_memory;
|
||||
if (!(qemu_driver->domainEventQueue = virDomainEventQueueNew()))
|
||||
goto out_of_memory;
|
||||
|
||||
if ((qemu_driver->domainEventTimer =
|
||||
virEventAddTimeout(-1, qemuDomainEventFlush, qemu_driver, NULL)) < 0)
|
||||
goto error;
|
||||
|
||||
if (!uid) {
|
||||
if (asprintf(&qemu_driver->logDir,
|
||||
@ -265,10 +275,14 @@ static void qemudNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
|
||||
{
|
||||
struct qemud_driver *driver = opaque;
|
||||
|
||||
if (newVM)
|
||||
qemudDomainEventDispatch(driver, vm,
|
||||
VIR_DOMAIN_EVENT_DEFINED,
|
||||
VIR_DOMAIN_EVENT_DEFINED_ADDED);
|
||||
if (newVM) {
|
||||
virDomainEventPtr event =
|
||||
virDomainEventNewFromObj(vm,
|
||||
VIR_DOMAIN_EVENT_DEFINED,
|
||||
VIR_DOMAIN_EVENT_DEFINED_ADDED);
|
||||
if (event)
|
||||
qemuDomainEventQueue(driver, event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -359,6 +373,10 @@ qemudShutdown(void) {
|
||||
|
||||
/* Free domain callback list */
|
||||
virDomainEventCallbackListFree(qemu_driver->domainEventCallbacks);
|
||||
virDomainEventQueueFree(qemu_driver->domainEventQueue);
|
||||
|
||||
if (qemu_driver->domainEventTimer != -1)
|
||||
virEventRemoveTimeout(qemu_driver->domainEventTimer);
|
||||
|
||||
if (qemu_driver->brctl)
|
||||
brShutdown(qemu_driver->brctl);
|
||||
@ -1075,6 +1093,7 @@ static void
|
||||
qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) {
|
||||
struct qemud_driver *driver = opaque;
|
||||
virDomainObjPtr vm = NULL;
|
||||
virDomainEventPtr event = NULL;
|
||||
unsigned int i;
|
||||
int quit = 0, failed = 0;
|
||||
|
||||
@ -1107,12 +1126,12 @@ qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) {
|
||||
}
|
||||
|
||||
if (failed || quit) {
|
||||
event = virDomainEventNewFromObj(vm,
|
||||
VIR_DOMAIN_EVENT_STOPPED,
|
||||
quit ?
|
||||
VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN :
|
||||
VIR_DOMAIN_EVENT_STOPPED_FAILED);
|
||||
qemudShutdownVMDaemon(NULL, driver, vm);
|
||||
qemudDomainEventDispatch(driver, vm,
|
||||
VIR_DOMAIN_EVENT_STOPPED,
|
||||
quit ?
|
||||
VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN :
|
||||
VIR_DOMAIN_EVENT_STOPPED_FAILED);
|
||||
if (!vm->persistent) {
|
||||
virDomainRemoveInactive(&driver->domains,
|
||||
vm);
|
||||
@ -1123,6 +1142,8 @@ qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) {
|
||||
cleanup:
|
||||
if (vm)
|
||||
virDomainObjUnlock(vm);
|
||||
if (event)
|
||||
qemuDomainEventQueue(driver, event);
|
||||
qemuDriverUnlock(driver);
|
||||
}
|
||||
|
||||
@ -1591,6 +1612,7 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
|
||||
virDomainDefPtr def;
|
||||
virDomainObjPtr vm = NULL;
|
||||
virDomainPtr dom = NULL;
|
||||
virDomainEventPtr event = NULL;
|
||||
|
||||
qemuDriverLock(driver);
|
||||
if (!(def = virDomainDefParseString(conn, driver->caps, xml)))
|
||||
@ -1627,9 +1649,10 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
|
||||
vm = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
qemudDomainEventDispatch(driver, vm,
|
||||
VIR_DOMAIN_EVENT_STARTED,
|
||||
VIR_DOMAIN_EVENT_STARTED_BOOTED);
|
||||
|
||||
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;
|
||||
@ -1638,6 +1661,8 @@ cleanup:
|
||||
virDomainDefFree(def);
|
||||
if (vm)
|
||||
virDomainObjUnlock(vm);
|
||||
if (event)
|
||||
qemuDomainEventQueue(driver, event);
|
||||
qemuDriverUnlock(driver);
|
||||
return dom;
|
||||
}
|
||||
@ -1648,6 +1673,7 @@ static int qemudDomainSuspend(virDomainPtr dom) {
|
||||
char *info;
|
||||
virDomainObjPtr vm;
|
||||
int ret = -1;
|
||||
virDomainEventPtr event = NULL;
|
||||
|
||||
qemuDriverLock(driver);
|
||||
vm = virDomainFindByID(&driver->domains, dom->id);
|
||||
@ -1670,9 +1696,9 @@ static int qemudDomainSuspend(virDomainPtr dom) {
|
||||
}
|
||||
vm->state = VIR_DOMAIN_PAUSED;
|
||||
qemudDebug("Reply %s", info);
|
||||
qemudDomainEventDispatch(driver, vm,
|
||||
VIR_DOMAIN_EVENT_SUSPENDED,
|
||||
VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
|
||||
event = virDomainEventNewFromObj(vm,
|
||||
VIR_DOMAIN_EVENT_SUSPENDED,
|
||||
VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
|
||||
VIR_FREE(info);
|
||||
}
|
||||
ret = 0;
|
||||
@ -1680,6 +1706,12 @@ static int qemudDomainSuspend(virDomainPtr dom) {
|
||||
cleanup:
|
||||
if (vm)
|
||||
virDomainObjUnlock(vm);
|
||||
|
||||
if (event) {
|
||||
qemuDriverLock(driver);
|
||||
qemuDomainEventQueue(driver, event);
|
||||
qemuDriverUnlock(driver);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1689,6 +1721,7 @@ static int qemudDomainResume(virDomainPtr dom) {
|
||||
char *info;
|
||||
virDomainObjPtr vm;
|
||||
int ret = -1;
|
||||
virDomainEventPtr event = NULL;
|
||||
|
||||
qemuDriverLock(driver);
|
||||
vm = virDomainFindByID(&driver->domains, dom->id);
|
||||
@ -1712,9 +1745,9 @@ static int qemudDomainResume(virDomainPtr dom) {
|
||||
}
|
||||
vm->state = VIR_DOMAIN_RUNNING;
|
||||
qemudDebug("Reply %s", info);
|
||||
qemudDomainEventDispatch(driver, vm,
|
||||
VIR_DOMAIN_EVENT_RESUMED,
|
||||
VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
|
||||
event = virDomainEventNewFromObj(vm,
|
||||
VIR_DOMAIN_EVENT_RESUMED,
|
||||
VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
|
||||
VIR_FREE(info);
|
||||
}
|
||||
ret = 0;
|
||||
@ -1722,6 +1755,11 @@ static int qemudDomainResume(virDomainPtr dom) {
|
||||
cleanup:
|
||||
if (vm)
|
||||
virDomainObjUnlock(vm);
|
||||
if (event) {
|
||||
qemuDriverLock(driver);
|
||||
qemuDomainEventQueue(driver, event);
|
||||
qemuDriverUnlock(driver);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1761,6 +1799,7 @@ static int qemudDomainDestroy(virDomainPtr dom) {
|
||||
struct qemud_driver *driver = dom->conn->privateData;
|
||||
virDomainObjPtr vm;
|
||||
int ret = -1;
|
||||
virDomainEventPtr event = NULL;
|
||||
|
||||
qemuDriverLock(driver);
|
||||
vm = virDomainFindByID(&driver->domains, dom->id);
|
||||
@ -1771,9 +1810,9 @@ static int qemudDomainDestroy(virDomainPtr dom) {
|
||||
}
|
||||
|
||||
qemudShutdownVMDaemon(dom->conn, driver, vm);
|
||||
qemudDomainEventDispatch(driver, vm,
|
||||
VIR_DOMAIN_EVENT_STOPPED,
|
||||
VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
|
||||
event = virDomainEventNewFromObj(vm,
|
||||
VIR_DOMAIN_EVENT_STOPPED,
|
||||
VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
|
||||
if (!vm->persistent) {
|
||||
virDomainRemoveInactive(&driver->domains,
|
||||
vm);
|
||||
@ -1784,6 +1823,8 @@ static int qemudDomainDestroy(virDomainPtr dom) {
|
||||
cleanup:
|
||||
if (vm)
|
||||
virDomainObjUnlock(vm);
|
||||
if (event)
|
||||
qemuDomainEventQueue(driver, event);
|
||||
qemuDriverUnlock(driver);
|
||||
return ret;
|
||||
}
|
||||
@ -2053,6 +2094,7 @@ static int qemudDomainSave(virDomainPtr dom,
|
||||
char *xml = NULL;
|
||||
struct qemud_save_header header;
|
||||
int ret = -1;
|
||||
virDomainEventPtr event = NULL;
|
||||
|
||||
memset(&header, 0, sizeof(header));
|
||||
memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic));
|
||||
@ -2154,9 +2196,9 @@ static int qemudDomainSave(virDomainPtr dom,
|
||||
|
||||
/* Shut it down */
|
||||
qemudShutdownVMDaemon(dom->conn, driver, vm);
|
||||
qemudDomainEventDispatch(driver, vm,
|
||||
VIR_DOMAIN_EVENT_STOPPED,
|
||||
VIR_DOMAIN_EVENT_STOPPED_SAVED);
|
||||
event = virDomainEventNewFromObj(vm,
|
||||
VIR_DOMAIN_EVENT_STOPPED,
|
||||
VIR_DOMAIN_EVENT_STOPPED_SAVED);
|
||||
if (!vm->persistent) {
|
||||
virDomainRemoveInactive(&driver->domains,
|
||||
vm);
|
||||
@ -2175,6 +2217,8 @@ cleanup:
|
||||
unlink(path);
|
||||
if (vm)
|
||||
virDomainObjUnlock(vm);
|
||||
if (event)
|
||||
qemuDomainEventQueue(driver, event);
|
||||
qemuDriverUnlock(driver);
|
||||
return ret;
|
||||
}
|
||||
@ -2412,6 +2456,7 @@ static int qemudDomainRestore(virConnectPtr conn,
|
||||
int ret = -1;
|
||||
char *xml = NULL;
|
||||
struct qemud_save_header header;
|
||||
virDomainEventPtr event = NULL;
|
||||
|
||||
qemuDriverLock(driver);
|
||||
/* Verify the header and read the XML */
|
||||
@ -2495,9 +2540,9 @@ static int qemudDomainRestore(virConnectPtr conn,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
qemudDomainEventDispatch(driver, vm,
|
||||
VIR_DOMAIN_EVENT_STARTED,
|
||||
VIR_DOMAIN_EVENT_STARTED_RESTORED);
|
||||
event = virDomainEventNewFromObj(vm,
|
||||
VIR_DOMAIN_EVENT_STARTED,
|
||||
VIR_DOMAIN_EVENT_STARTED_RESTORED);
|
||||
|
||||
/* If it was running before, resume it now. */
|
||||
if (header.was_running) {
|
||||
@ -2519,6 +2564,8 @@ cleanup:
|
||||
close(fd);
|
||||
if (vm)
|
||||
virDomainObjUnlock(vm);
|
||||
if (event)
|
||||
qemuDomainEventQueue(driver, event);
|
||||
qemuDriverUnlock(driver);
|
||||
return ret;
|
||||
}
|
||||
@ -2599,6 +2646,7 @@ static int qemudDomainStart(virDomainPtr dom) {
|
||||
struct qemud_driver *driver = dom->conn->privateData;
|
||||
virDomainObjPtr vm;
|
||||
int ret = -1;
|
||||
virDomainEventPtr event = NULL;
|
||||
|
||||
qemuDriverLock(driver);
|
||||
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
||||
@ -2612,13 +2660,18 @@ static int qemudDomainStart(virDomainPtr dom) {
|
||||
|
||||
ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL);
|
||||
if (ret != -1)
|
||||
qemudDomainEventDispatch(driver, vm,
|
||||
VIR_DOMAIN_EVENT_STARTED,
|
||||
VIR_DOMAIN_EVENT_STARTED_BOOTED);
|
||||
event = virDomainEventNewFromObj(vm,
|
||||
VIR_DOMAIN_EVENT_STARTED,
|
||||
VIR_DOMAIN_EVENT_STARTED_BOOTED);
|
||||
|
||||
cleanup:
|
||||
if (vm)
|
||||
virDomainObjUnlock(vm);
|
||||
if (event) {
|
||||
qemuDriverLock(driver);
|
||||
qemuDomainEventQueue(driver, event);
|
||||
qemuDriverUnlock(driver);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2628,6 +2681,7 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
|
||||
virDomainDefPtr def;
|
||||
virDomainObjPtr vm = NULL;
|
||||
virDomainPtr dom = NULL;
|
||||
virDomainEventPtr event = NULL;
|
||||
int newVM = 1;
|
||||
|
||||
qemuDriverLock(driver);
|
||||
@ -2657,11 +2711,11 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
qemudDomainEventDispatch(driver, vm,
|
||||
VIR_DOMAIN_EVENT_DEFINED,
|
||||
newVM ?
|
||||
VIR_DOMAIN_EVENT_DEFINED_ADDED :
|
||||
VIR_DOMAIN_EVENT_DEFINED_UPDATED);
|
||||
event = virDomainEventNewFromObj(vm,
|
||||
VIR_DOMAIN_EVENT_DEFINED,
|
||||
newVM ?
|
||||
VIR_DOMAIN_EVENT_DEFINED_ADDED :
|
||||
VIR_DOMAIN_EVENT_DEFINED_UPDATED);
|
||||
|
||||
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
||||
if (dom) dom->id = vm->def->id;
|
||||
@ -2669,6 +2723,8 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
|
||||
cleanup:
|
||||
if (vm)
|
||||
virDomainObjUnlock(vm);
|
||||
if (event)
|
||||
qemuDomainEventQueue(driver, event);
|
||||
qemuDriverUnlock(driver);
|
||||
return dom;
|
||||
}
|
||||
@ -2676,6 +2732,7 @@ cleanup:
|
||||
static int qemudDomainUndefine(virDomainPtr dom) {
|
||||
struct qemud_driver *driver = dom->conn->privateData;
|
||||
virDomainObjPtr vm;
|
||||
virDomainEventPtr event = NULL;
|
||||
int ret = -1;
|
||||
|
||||
qemuDriverLock(driver);
|
||||
@ -2702,9 +2759,9 @@ static int qemudDomainUndefine(virDomainPtr dom) {
|
||||
if (virDomainDeleteConfig(dom->conn, driver->configDir, driver->autostartDir, vm) < 0)
|
||||
goto cleanup;
|
||||
|
||||
qemudDomainEventDispatch(driver, vm,
|
||||
VIR_DOMAIN_EVENT_UNDEFINED,
|
||||
VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
|
||||
event = virDomainEventNewFromObj(vm,
|
||||
VIR_DOMAIN_EVENT_UNDEFINED,
|
||||
VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
|
||||
|
||||
virDomainRemoveInactive(&driver->domains,
|
||||
vm);
|
||||
@ -2714,6 +2771,8 @@ static int qemudDomainUndefine(virDomainPtr dom) {
|
||||
cleanup:
|
||||
if (vm)
|
||||
virDomainObjUnlock(vm);
|
||||
if (event)
|
||||
qemuDomainEventQueue(driver, event);
|
||||
qemuDriverUnlock(driver);
|
||||
return ret;
|
||||
}
|
||||
@ -3709,41 +3768,69 @@ qemudDomainEventDeregister (virConnectPtr conn,
|
||||
int ret;
|
||||
|
||||
qemuDriverLock(driver);
|
||||
ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks,
|
||||
callback);
|
||||
if (driver->domainEventDispatching)
|
||||
ret = virDomainEventCallbackListMarkDelete(conn, driver->domainEventCallbacks,
|
||||
callback);
|
||||
else
|
||||
ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks,
|
||||
callback);
|
||||
qemuDriverUnlock(driver);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void qemudDomainEventDispatch (struct qemud_driver *driver,
|
||||
virDomainObjPtr vm,
|
||||
int event,
|
||||
int detail)
|
||||
static void qemuDomainEventDispatchFunc(virConnectPtr conn,
|
||||
virDomainEventPtr event,
|
||||
virConnectDomainEventCallback cb,
|
||||
void *cbopaque,
|
||||
void *opaque)
|
||||
{
|
||||
int i;
|
||||
virDomainEventCallbackListPtr cbList;
|
||||
struct qemud_driver *driver = opaque;
|
||||
|
||||
cbList = driver->domainEventCallbacks;
|
||||
/* Drop the lock whle dispatching, for sake of re-entrancy */
|
||||
qemuDriverUnlock(driver);
|
||||
virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL);
|
||||
qemuDriverLock(driver);
|
||||
}
|
||||
|
||||
for(i=0 ; i < cbList->count ; i++) {
|
||||
if(cbList->callbacks[i] && cbList->callbacks[i]->cb) {
|
||||
virConnectPtr conn = cbList->callbacks[i]->conn;
|
||||
virDomainPtr dom = virGetDomain(conn, vm->def->name,
|
||||
vm->def->uuid);
|
||||
if (dom) {
|
||||
dom->id = virDomainIsActive(vm) ? vm->def->id : -1;
|
||||
DEBUG("Dispatching callback %p %p event %d detail %d",
|
||||
cbList->callbacks[i],
|
||||
cbList->callbacks[i]->cb, event, detail);
|
||||
cbList->callbacks[i]->cb(cbList->callbacks[i]->conn,
|
||||
dom, event, detail,
|
||||
cbList->callbacks[i]->opaque);
|
||||
virDomainFree(dom);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void qemuDomainEventFlush(int timer ATTRIBUTE_UNUSED, void *opaque)
|
||||
{
|
||||
struct qemud_driver *driver = opaque;
|
||||
virDomainEventQueue tempQueue;
|
||||
|
||||
qemuDriverLock(driver);
|
||||
|
||||
driver->domainEventDispatching = 1;
|
||||
|
||||
/* Copy the queue, so we're reentrant safe */
|
||||
tempQueue.count = driver->domainEventQueue->count;
|
||||
tempQueue.events = driver->domainEventQueue->events;
|
||||
driver->domainEventQueue->count = 0;
|
||||
driver->domainEventQueue->events = NULL;
|
||||
|
||||
virEventUpdateTimeout(driver->domainEventTimer, -1);
|
||||
virDomainEventQueueDispatch(&tempQueue,
|
||||
driver->domainEventCallbacks,
|
||||
qemuDomainEventDispatchFunc,
|
||||
driver);
|
||||
|
||||
/* Purge any deleted callbacks */
|
||||
virDomainEventCallbackListPurgeMarked(driver->domainEventCallbacks);
|
||||
|
||||
driver->domainEventDispatching = 0;
|
||||
qemuDriverUnlock(driver);
|
||||
}
|
||||
|
||||
|
||||
/* driver must be locked before calling */
|
||||
static void qemuDomainEventQueue(struct qemud_driver *driver,
|
||||
virDomainEventPtr event)
|
||||
{
|
||||
if (virDomainEventQueuePush(driver->domainEventQueue,
|
||||
event) < 0)
|
||||
virDomainEventFree(event);
|
||||
if (qemu_driver->domainEventQueue->count == 1)
|
||||
virEventUpdateTimeout(driver->domainEventTimer, 0);
|
||||
}
|
||||
|
||||
/* Migration support. */
|
||||
@ -3771,6 +3858,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
|
||||
char hostname [HOST_NAME_MAX+1];
|
||||
char migrateFrom [64];
|
||||
const char *p;
|
||||
virDomainEventPtr event = NULL;
|
||||
int ret = -1;;
|
||||
|
||||
*uri_out = NULL;
|
||||
@ -3892,9 +3980,10 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
qemudDomainEventDispatch(driver, vm,
|
||||
VIR_DOMAIN_EVENT_STARTED,
|
||||
VIR_DOMAIN_EVENT_STARTED_MIGRATED);
|
||||
|
||||
event = virDomainEventNewFromObj(vm,
|
||||
VIR_DOMAIN_EVENT_STARTED,
|
||||
VIR_DOMAIN_EVENT_STARTED_MIGRATED);
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
@ -3904,6 +3993,8 @@ cleanup:
|
||||
}
|
||||
if (vm)
|
||||
virDomainObjUnlock(vm);
|
||||
if (event)
|
||||
qemuDomainEventQueue(driver, event);
|
||||
qemuDriverUnlock(driver);
|
||||
return ret;
|
||||
}
|
||||
@ -3920,6 +4011,7 @@ qemudDomainMigratePerform (virDomainPtr dom,
|
||||
{
|
||||
struct qemud_driver *driver = dom->conn->privateData;
|
||||
virDomainObjPtr vm;
|
||||
virDomainEventPtr event = NULL;
|
||||
char *safe_uri;
|
||||
char cmd[HOST_NAME_MAX+50];
|
||||
char *info = NULL;
|
||||
@ -3946,9 +4038,12 @@ qemudDomainMigratePerform (virDomainPtr dom,
|
||||
DEBUG ("stop reply: %s", info);
|
||||
VIR_FREE(info);
|
||||
|
||||
qemudDomainEventDispatch(driver, vm,
|
||||
VIR_DOMAIN_EVENT_SUSPENDED,
|
||||
VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
|
||||
event = virDomainEventNewFromObj(vm,
|
||||
VIR_DOMAIN_EVENT_SUSPENDED,
|
||||
VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
|
||||
if (event)
|
||||
qemuDomainEventQueue(driver, event);
|
||||
event = NULL;
|
||||
}
|
||||
|
||||
if (resource > 0) {
|
||||
@ -3987,9 +4082,10 @@ qemudDomainMigratePerform (virDomainPtr dom,
|
||||
|
||||
/* Clean up the source domain. */
|
||||
qemudShutdownVMDaemon (dom->conn, driver, vm);
|
||||
qemudDomainEventDispatch(driver, vm,
|
||||
VIR_DOMAIN_EVENT_STOPPED,
|
||||
VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
|
||||
|
||||
event = virDomainEventNewFromObj(vm,
|
||||
VIR_DOMAIN_EVENT_STOPPED,
|
||||
VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
|
||||
if (!vm->persistent) {
|
||||
virDomainRemoveInactive(&driver->domains, vm);
|
||||
vm = NULL;
|
||||
@ -4000,6 +4096,8 @@ cleanup:
|
||||
VIR_FREE(info);
|
||||
if (vm)
|
||||
virDomainObjUnlock(vm);
|
||||
if (event)
|
||||
qemuDomainEventQueue(driver, event);
|
||||
qemuDriverUnlock(driver);
|
||||
return ret;
|
||||
}
|
||||
@ -4017,6 +4115,7 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
|
||||
struct qemud_driver *driver = dconn->privateData;
|
||||
virDomainObjPtr vm;
|
||||
virDomainPtr dom = NULL;
|
||||
virDomainEventPtr event = NULL;
|
||||
char *info = NULL;
|
||||
|
||||
qemuDriverLock(driver);
|
||||
@ -4034,14 +4133,14 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
|
||||
dom = virGetDomain (dconn, vm->def->name, vm->def->uuid);
|
||||
VIR_FREE(info);
|
||||
vm->state = VIR_DOMAIN_RUNNING;
|
||||
qemudDomainEventDispatch(driver, vm,
|
||||
VIR_DOMAIN_EVENT_RESUMED,
|
||||
VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
|
||||
event = virDomainEventNewFromObj(vm,
|
||||
VIR_DOMAIN_EVENT_RESUMED,
|
||||
VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
|
||||
} else {
|
||||
qemudShutdownVMDaemon (dconn, driver, vm);
|
||||
qemudDomainEventDispatch(driver, vm,
|
||||
VIR_DOMAIN_EVENT_STOPPED,
|
||||
VIR_DOMAIN_EVENT_STOPPED_FAILED);
|
||||
event = virDomainEventNewFromObj(vm,
|
||||
VIR_DOMAIN_EVENT_STOPPED,
|
||||
VIR_DOMAIN_EVENT_STOPPED_FAILED);
|
||||
if (!vm->persistent) {
|
||||
virDomainRemoveInactive(&driver->domains, vm);
|
||||
vm = NULL;
|
||||
@ -4051,6 +4150,8 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
|
||||
cleanup:
|
||||
if (vm)
|
||||
virDomainObjUnlock(vm);
|
||||
if (event)
|
||||
qemuDomainEventQueue(driver, event);
|
||||
qemuDriverUnlock(driver);
|
||||
return dom;
|
||||
}
|
||||
|
@ -5484,59 +5484,62 @@ remoteRegister (void)
|
||||
*
|
||||
* Read the event data off the wire
|
||||
*/
|
||||
static int
|
||||
remoteDomainReadEvent(virConnectPtr conn, XDR *xdr,
|
||||
virDomainPtr *dom, int *event, int *detail)
|
||||
static virDomainEventPtr
|
||||
remoteDomainReadEvent(virConnectPtr conn, XDR *xdr)
|
||||
{
|
||||
remote_domain_event_ret ret;
|
||||
virDomainPtr dom;
|
||||
virDomainEventPtr event = NULL;
|
||||
memset (&ret, 0, sizeof ret);
|
||||
|
||||
/* unmarshall parameters, and process it*/
|
||||
if (! xdr_remote_domain_event_ret(xdr, &ret) ) {
|
||||
error (conn, VIR_ERR_RPC,
|
||||
_("remoteDomainProcessEvent: unmarshalling ret"));
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*dom = get_nonnull_domain(conn,ret.dom);
|
||||
*event = ret.event;
|
||||
*detail = ret.detail;
|
||||
dom = get_nonnull_domain(conn,ret.dom);
|
||||
if (!dom)
|
||||
return NULL;
|
||||
|
||||
return 0;
|
||||
event = virDomainEventNewFromDom(dom, ret.event, ret.detail);
|
||||
|
||||
virDomainFree(dom);
|
||||
return event;
|
||||
}
|
||||
|
||||
static void
|
||||
remoteDomainProcessEvent(virConnectPtr conn, XDR *xdr)
|
||||
{
|
||||
virDomainPtr dom;
|
||||
int event, detail, i;
|
||||
struct private_data *priv = conn->privateData;
|
||||
virDomainEventPtr event;
|
||||
|
||||
if(!remoteDomainReadEvent(conn, xdr, &dom, &event, &detail)) {
|
||||
DEBUG0("Calling domain event callbacks (no queue)");
|
||||
for(i=0 ; i < priv->callbackList->count ; i++) {
|
||||
if (priv->callbackList->callbacks[i] )
|
||||
priv->callbackList->callbacks[i]->cb(
|
||||
conn, dom, event, detail,
|
||||
priv->callbackList->callbacks[i]->opaque);
|
||||
}
|
||||
}
|
||||
event = remoteDomainReadEvent(conn, xdr);
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
DEBUG0("Calling domain event callbacks (no queue)");
|
||||
virDomainEventDispatch(event, priv->callbackList,
|
||||
virDomainEventDispatchDefaultFunc, NULL);
|
||||
virDomainEventFree(event);
|
||||
}
|
||||
|
||||
static void
|
||||
remoteDomainQueueEvent(virConnectPtr conn, XDR *xdr)
|
||||
{
|
||||
virDomainPtr dom;
|
||||
int event, detail;
|
||||
struct private_data *priv = conn->privateData;
|
||||
virDomainEventPtr event;
|
||||
|
||||
if(!remoteDomainReadEvent(conn, xdr, &dom, &event, &detail))
|
||||
{
|
||||
if( virDomainEventCallbackQueuePush(priv->domainEvents,
|
||||
dom, event, detail) < 0 ) {
|
||||
DEBUG("%s", "Error adding event to queue");
|
||||
}
|
||||
}
|
||||
event = remoteDomainReadEvent(conn, xdr);
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
if (virDomainEventQueuePush(priv->domainEvents,
|
||||
event) < 0)
|
||||
DEBUG0("Error adding event to queue");
|
||||
|
||||
virDomainEventFree(event);
|
||||
}
|
||||
|
||||
/** remoteDomainEventFired:
|
||||
@ -5618,26 +5621,10 @@ remoteDomainEventFired(int watch,
|
||||
void
|
||||
remoteDomainEventQueueFlush(int timer ATTRIBUTE_UNUSED, void *opaque)
|
||||
{
|
||||
int i;
|
||||
virDomainEventPtr domEvent;
|
||||
void *user_data = NULL;
|
||||
virConnectPtr conn = opaque;
|
||||
struct private_data *priv = conn->privateData;
|
||||
|
||||
while( (domEvent = virDomainEventCallbackQueuePop(priv->domainEvents)) ) {
|
||||
DEBUG(" Flushing %p", domEvent);
|
||||
for (i=0 ; i < priv->callbackList->count ; i++) {
|
||||
if( priv->callbackList->callbacks[i] ) {
|
||||
user_data = priv->callbackList->callbacks[i]->opaque;
|
||||
priv->callbackList->callbacks[i]->cb(domEvent->dom->conn,
|
||||
domEvent->dom,
|
||||
domEvent->event,
|
||||
domEvent->detail,
|
||||
user_data);
|
||||
}
|
||||
}
|
||||
VIR_FREE(domEvent);
|
||||
}
|
||||
|
||||
virDomainEventQueueDispatch(priv->domainEvents, priv->callbackList,
|
||||
virDomainEventDispatchDefaultFunc, NULL);
|
||||
virEventUpdateTimeout(priv->eventFlushTimer, -1);
|
||||
}
|
||||
|
@ -92,30 +92,33 @@ struct xenUnifiedDriver xenInotifyDriver = {
|
||||
NULL, /* domainSetSchedulerParameters */
|
||||
};
|
||||
|
||||
static virDomainPtr
|
||||
xenInotifyXenCacheLookup(virConnectPtr conn, const char *filename) {
|
||||
static int
|
||||
xenInotifyXenCacheLookup(const char *filename,
|
||||
char **name, unsigned char *uuid) {
|
||||
xenXMConfCachePtr entry;
|
||||
virDomainPtr dom;
|
||||
|
||||
if (!(entry = virHashLookup(xenXMGetConfigCache(), filename))) {
|
||||
DEBUG("No config found for %s", filename);
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!(dom = virGetDomain(conn, entry->def->name,
|
||||
(unsigned char*)entry->def->uuid))) {
|
||||
*name = strdup(entry->def->name);
|
||||
memcpy(uuid, entry->def->uuid, VIR_UUID_BUFLEN);
|
||||
|
||||
if (!*name) {
|
||||
DEBUG0("Error getting dom from def");
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
return dom;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static virDomainPtr
|
||||
xenInotifyXendDomainsDirLookup(virConnectPtr conn, const char *filename) {
|
||||
static int
|
||||
xenInotifyXendDomainsDirLookup(virConnectPtr conn, const char *filename,
|
||||
char **name, unsigned char *uuid) {
|
||||
int i;
|
||||
virDomainPtr dom;
|
||||
const char *uuid_str;
|
||||
unsigned char uuid[VIR_UUID_BUFLEN];
|
||||
unsigned char rawuuid[VIR_UUID_BUFLEN];
|
||||
|
||||
/* xend is managing domains. we will get
|
||||
* a filename in the manner:
|
||||
@ -123,57 +126,70 @@ xenInotifyXendDomainsDirLookup(virConnectPtr conn, const char *filename) {
|
||||
*/
|
||||
uuid_str = filename + strlen(LIBVIRTD_DOMAINS_DIR) + 1;
|
||||
|
||||
if (virUUIDParse(uuid_str, uuid) < 0) {
|
||||
if (virUUIDParse(uuid_str, rawuuid) < 0) {
|
||||
virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
"parsing uuid %s", uuid_str);
|
||||
return (NULL);
|
||||
return -1;
|
||||
}
|
||||
/* call directly into xend here, as driver may not yet
|
||||
be set during open while we are building our
|
||||
initial list of domains */
|
||||
DEBUG("Looking for dom with uuid: %s", uuid_str);
|
||||
if(!(dom = xenDaemonLookupByUUID(conn, uuid))) {
|
||||
/* XXX Should not have to go via a virDomainPtr obj instance */
|
||||
if(!(dom = xenDaemonLookupByUUID(conn, rawuuid))) {
|
||||
/* If we are here, the domain has gone away.
|
||||
search for, and create a domain from the stored
|
||||
list info */
|
||||
for (i=0; i<configInfoList->count; i++) {
|
||||
if (!memcmp(uuid, configInfoList->doms[i]->uuid, VIR_UUID_BUFLEN)) {
|
||||
if(!(dom = virGetDomain(conn, configInfoList->doms[i]->name,
|
||||
configInfoList->doms[i]->uuid))) {
|
||||
*name = strdup(configInfoList->doms[i]->name);
|
||||
if (!*name) {
|
||||
virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
"finding dom for %s", uuid_str);
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
memcpy(uuid, configInfoList->doms[i]->uuid, VIR_UUID_BUFLEN);
|
||||
DEBUG0("Found dom on list");
|
||||
return dom;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("finding dom on config list"));
|
||||
return NULL;
|
||||
"%s", _("finding dom on config list"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(*name = strdup(dom->name)))
|
||||
return -1;
|
||||
memcpy(uuid, dom->uuid, VIR_UUID_BUFLEN);
|
||||
virDomainFree(dom);
|
||||
/* succeeded too find domain by uuid */
|
||||
return dom;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static virDomainPtr
|
||||
xenInotifyDomainLookup(virConnectPtr conn, const char *filename) {
|
||||
virDomainPtr dom;
|
||||
virDomainInfo info;
|
||||
static int
|
||||
xenInotifyDomainLookup(virConnectPtr conn,
|
||||
const char *filename,
|
||||
char **name, unsigned char *uuid) {
|
||||
if (useXenConfigCache)
|
||||
return xenInotifyXenCacheLookup(filename, name, uuid);
|
||||
else
|
||||
return xenInotifyXendDomainsDirLookup(conn, filename, name, uuid);
|
||||
}
|
||||
|
||||
dom = useXenConfigCache ? xenInotifyXenCacheLookup(conn, filename) :
|
||||
xenInotifyXendDomainsDirLookup(conn, filename);
|
||||
static virDomainEventPtr
|
||||
xenInotifyDomainEventFromFile(virConnectPtr conn,
|
||||
const char *filename,
|
||||
int type, int detail) {
|
||||
virDomainEventPtr event;
|
||||
char *name = NULL;
|
||||
unsigned char uuid[VIR_UUID_BUFLEN];
|
||||
|
||||
if(dom) {
|
||||
if ( (useXenConfigCache ? xenXMDomainGetInfo(dom, &info) :
|
||||
xenDaemonDomainGetInfo(dom, &info)) < 0)
|
||||
dom->id = -1;
|
||||
else
|
||||
dom->id = (info.state == VIR_DOMAIN_SHUTOFF) ? -1 : dom->id;
|
||||
return dom;
|
||||
}
|
||||
return NULL;
|
||||
if (xenInotifyDomainLookup(conn, filename, &name, uuid) < 0)
|
||||
return NULL;
|
||||
|
||||
event = virDomainEventNew(-1, name, uuid, type, detail);
|
||||
VIR_FREE(name);
|
||||
return event;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -215,21 +231,22 @@ xenInotifyXendDomainsDirRemoveEntry(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
static int
|
||||
xenInotifyXendDomainsDirAddEntry(virConnectPtr conn,
|
||||
const char *fname) {
|
||||
virDomainPtr dom = xenInotifyDomainLookup(conn, fname);
|
||||
if(!dom) {
|
||||
char *name = NULL;
|
||||
unsigned char uuid[VIR_UUID_BUFLEN];
|
||||
if (xenInotifyDomainLookup(conn, fname, &name, uuid) < 0) {
|
||||
virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("Error looking up domain"));
|
||||
"%s", _("Error looking up domain"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( xenUnifiedAddDomainInfo(configInfoList,
|
||||
dom->id, dom->name, dom->uuid) < 0) {
|
||||
-1, name, uuid) < 0) {
|
||||
virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("Error adding file to config cache"));
|
||||
virUnrefDomain(dom);
|
||||
VIR_FREE(name);
|
||||
return -1;
|
||||
}
|
||||
virUnrefDomain(dom);
|
||||
VIR_FREE(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -260,7 +277,6 @@ xenInotifyEvent(int watch ATTRIBUTE_UNUSED,
|
||||
char *tmp, *name;
|
||||
virConnectPtr conn = (virConnectPtr) data;
|
||||
xenUnifiedPrivatePtr priv = NULL;
|
||||
virDomainPtr dom = NULL;
|
||||
|
||||
DEBUG0("got inotify event");
|
||||
|
||||
@ -300,16 +316,15 @@ reread:
|
||||
snprintf(fname, 1024, "%s/%s", configDir, name);
|
||||
|
||||
if (e->mask & (IN_DELETE | IN_MOVED_FROM)) {
|
||||
if (!(dom = xenInotifyDomainLookup(conn, fname))) {
|
||||
virDomainEventPtr event =
|
||||
xenInotifyDomainEventFromFile(conn, fname,
|
||||
VIR_DOMAIN_EVENT_UNDEFINED,
|
||||
VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
|
||||
if (!event)
|
||||
xenUnifiedDomainEventDispatch(conn->privateData, event);
|
||||
else
|
||||
virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("looking up dom"));
|
||||
continue;
|
||||
}
|
||||
|
||||
xenUnifiedDomainEventDispatch(conn->privateData, dom,
|
||||
VIR_DOMAIN_EVENT_UNDEFINED,
|
||||
VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
|
||||
|
||||
"%s", _("looking up dom"));
|
||||
|
||||
if (xenInotifyRemoveDomainConfigInfo(conn, fname) < 0 ) {
|
||||
virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
@ -317,21 +332,23 @@ reread:
|
||||
return;
|
||||
}
|
||||
} else if (e->mask & ( IN_CREATE | IN_CLOSE_WRITE | IN_MOVED_TO) ) {
|
||||
virDomainEventPtr event;
|
||||
if (xenInotifyAddDomainConfigInfo(conn, fname) < 0 ) {
|
||||
virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("Error adding file to config cache"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(dom = xenInotifyDomainLookup(conn, fname))) {
|
||||
virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("looking up dom"));
|
||||
continue;
|
||||
}
|
||||
event = xenInotifyDomainEventFromFile(conn, fname,
|
||||
VIR_DOMAIN_EVENT_DEFINED,
|
||||
VIR_DOMAIN_EVENT_DEFINED_ADDED);
|
||||
|
||||
if (event)
|
||||
xenUnifiedDomainEventDispatch(conn->privateData, event);
|
||||
else
|
||||
virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("looking up dom"));
|
||||
|
||||
xenUnifiedDomainEventDispatch(conn->privateData, dom,
|
||||
VIR_DOMAIN_EVENT_DEFINED,
|
||||
VIR_DOMAIN_EVENT_DEFINED_ADDED);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1583,28 +1583,14 @@ xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr list,
|
||||
*
|
||||
*/
|
||||
void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv,
|
||||
virDomainPtr dom,
|
||||
int event,
|
||||
int detail)
|
||||
virDomainEventPtr event)
|
||||
{
|
||||
int i;
|
||||
virDomainEventCallbackListPtr cbList;
|
||||
if (!priv || !priv->domainEventCallbacks)
|
||||
return;
|
||||
|
||||
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, event);
|
||||
cbList->callbacks[i]->cb(cbList->callbacks[i]->conn,
|
||||
dom, event, detail,
|
||||
cbList->callbacks[i]->opaque);
|
||||
}
|
||||
}
|
||||
}
|
||||
virDomainEventDispatch(event,
|
||||
priv->domainEventCallbacks,
|
||||
virDomainEventDispatchDefaultFunc,
|
||||
NULL);
|
||||
virDomainEventFree(event);
|
||||
}
|
||||
|
@ -182,9 +182,7 @@ int xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr info,
|
||||
int id, char *name,
|
||||
unsigned char *uuid);
|
||||
void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv,
|
||||
virDomainPtr dom,
|
||||
int event,
|
||||
int detail);
|
||||
virDomainEventPtr event);
|
||||
unsigned long xenUnifiedVersion(void);
|
||||
|
||||
#endif /* __VIR_XEN_UNIFIED_H__ */
|
||||
|
@ -1215,7 +1215,7 @@ retry:
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
virDomainPtr dom;
|
||||
virDomainEventPtr event;
|
||||
char *name;
|
||||
unsigned char uuid[VIR_UUID_BUFLEN];
|
||||
|
||||
@ -1229,21 +1229,15 @@ retry:
|
||||
continue;
|
||||
}
|
||||
|
||||
dom = virGetDomain(conn, name, uuid);
|
||||
if (dom) {
|
||||
dom->id = new_domids[i];
|
||||
event = virDomainEventNew(new_domids[i], name, uuid,
|
||||
VIR_DOMAIN_EVENT_STARTED,
|
||||
VIR_DOMAIN_EVENT_STARTED_BOOTED);
|
||||
if (event)
|
||||
xenUnifiedDomainEventDispatch(priv, event);
|
||||
|
||||
/* This domain was not in the old list. Emit an event */
|
||||
xenUnifiedDomainEventDispatch(priv, dom,
|
||||
VIR_DOMAIN_EVENT_STARTED,
|
||||
VIR_DOMAIN_EVENT_STARTED_BOOTED);
|
||||
|
||||
/* Add to the list */
|
||||
xenUnifiedAddDomainInfo(activeDomainList,
|
||||
new_domids[i], name, uuid);
|
||||
|
||||
virUnrefDomain(dom);
|
||||
}
|
||||
/* Add to the list */
|
||||
xenUnifiedAddDomainInfo(activeDomainList,
|
||||
new_domids[i], name, uuid);
|
||||
|
||||
VIR_FREE(name);
|
||||
}
|
||||
@ -1299,24 +1293,22 @@ retry:
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
virDomainPtr dom = virGetDomain(conn,
|
||||
activeDomainList->doms[j]->name,
|
||||
activeDomainList->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,
|
||||
VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
|
||||
/* Remove from the list */
|
||||
xenUnifiedRemoveDomainInfo(activeDomainList,
|
||||
activeDomainList->doms[j]->id,
|
||||
activeDomainList->doms[j]->name,
|
||||
activeDomainList->doms[j]->uuid);
|
||||
virDomainEventPtr event =
|
||||
virDomainEventNew(-1,
|
||||
activeDomainList->doms[j]->name,
|
||||
activeDomainList->doms[j]->uuid,
|
||||
VIR_DOMAIN_EVENT_STOPPED,
|
||||
VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
|
||||
if (event)
|
||||
xenUnifiedDomainEventDispatch(priv, event);
|
||||
|
||||
virUnrefDomain(dom);
|
||||
removed = 1;
|
||||
}
|
||||
/* Remove from the list */
|
||||
xenUnifiedRemoveDomainInfo(activeDomainList,
|
||||
activeDomainList->doms[j]->id,
|
||||
activeDomainList->doms[j]->name,
|
||||
activeDomainList->doms[j]->uuid);
|
||||
|
||||
removed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user