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