2008-11-04 23:33:57 +00:00
|
|
|
/*
|
|
|
|
* domain_event.c: domain event queue processing helpers
|
|
|
|
*
|
2011-06-02 22:54:09 +00:00
|
|
|
* Copyright (C) 2010-2011 Red Hat, Inc.
|
2008-11-04 23:33:57 +00:00
|
|
|
* Copyright (C) 2008 VirtualIron
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
* Author: Ben Guthro
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include "domain_event.h"
|
2008-11-06 16:36:07 +00:00
|
|
|
#include "logging.h"
|
2008-11-04 23:33:57 +00:00
|
|
|
#include "datatypes.h"
|
|
|
|
#include "memory.h"
|
2010-01-13 18:11:33 +00:00
|
|
|
#include "virterror_internal.h"
|
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
|
|
|
|
2010-04-03 13:22:58 +00:00
|
|
|
#define eventReportError(code, ...) \
|
2011-04-16 08:30:22 +00:00
|
|
|
virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \
|
2010-03-01 23:38:28 +00:00
|
|
|
__FUNCTION__, __LINE__, __VA_ARGS__)
|
2008-11-04 23:33:57 +00:00
|
|
|
|
2010-03-18 14:06:09 +00:00
|
|
|
struct _virDomainMeta {
|
|
|
|
int id;
|
|
|
|
char *name;
|
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
|
|
|
};
|
|
|
|
typedef struct _virDomainMeta virDomainMeta;
|
|
|
|
typedef virDomainMeta *virDomainMetaPtr;
|
|
|
|
|
2011-12-13 11:35:00 +00:00
|
|
|
struct _virDomainEventCallbackList {
|
|
|
|
unsigned int nextID;
|
|
|
|
unsigned int count;
|
|
|
|
virDomainEventCallbackPtr *callbacks;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _virDomainEventQueue {
|
|
|
|
unsigned int count;
|
|
|
|
virDomainEventPtr *events;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _virDomainEventState {
|
|
|
|
/* The list of domain event callbacks */
|
|
|
|
virDomainEventCallbackListPtr callbacks;
|
|
|
|
/* The queue of domain events */
|
|
|
|
virDomainEventQueuePtr queue;
|
|
|
|
/* Timer for flushing events queue */
|
|
|
|
int timer;
|
|
|
|
/* Flag if we're in process of dispatching */
|
|
|
|
bool isDispatching;
|
|
|
|
virMutex lock;
|
|
|
|
};
|
|
|
|
|
2010-03-18 13:17:14 +00:00
|
|
|
struct _virDomainEventCallback {
|
2010-03-18 14:06:09 +00:00
|
|
|
int callbackID;
|
|
|
|
int eventID;
|
2010-03-18 13:17:14 +00:00
|
|
|
virConnectPtr conn;
|
2010-03-18 14:06:09 +00:00
|
|
|
virDomainMetaPtr dom;
|
|
|
|
virConnectDomainEventGenericCallback cb;
|
2010-03-18 13:17:14 +00:00
|
|
|
void *opaque;
|
|
|
|
virFreeCallback freecb;
|
|
|
|
int deleted;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _virDomainEvent {
|
2010-03-18 14:06:09 +00:00
|
|
|
int eventID;
|
|
|
|
|
|
|
|
virDomainMeta dom;
|
|
|
|
|
|
|
|
union {
|
|
|
|
struct {
|
|
|
|
int type;
|
|
|
|
int detail;
|
|
|
|
} lifecycle;
|
2010-03-18 18:28:15 +00:00
|
|
|
struct {
|
|
|
|
long long offset;
|
|
|
|
} rtcChange;
|
Add support for an explicit watchdog event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_WATCHDOG
This event includes the action that is about to be taken
as a result of the watchdog triggering
typedef enum {
VIR_DOMAIN_EVENT_WATCHDOG_NONE = 0,
VIR_DOMAIN_EVENT_WATCHDOG_PAUSE,
VIR_DOMAIN_EVENT_WATCHDOG_RESET,
VIR_DOMAIN_EVENT_WATCHDOG_POWEROFF,
VIR_DOMAIN_EVENT_WATCHDOG_SHUTDOWN,
VIR_DOMAIN_EVENT_WATCHDOG_DEBUG,
} virDomainEventWatchdogAction;
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventWatchdogCallback)(virConnectPtr conn,
virDomainPtr dom,
int action,
void *opaque);
* daemon/remote.c: Dispatch watchdog events to client
* examples/domain-events/events-c/event-test.c: Watch for
watchdog events
* include/libvirt/libvirt.h.in: Define new watchdg event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle watchdog events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for watchdogs and emit a libvirt watchdog event
* src/remote/remote_driver.c: Receive and dispatch watchdog
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
watchdog events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for WATCHDOG event
from QEMU monitor
2010-03-18 19:07:48 +00:00
|
|
|
struct {
|
|
|
|
int action;
|
|
|
|
} watchdog;
|
Add support for an explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR
This event includes the action that is about to be taken
as a result of the watchdog triggering
typedef enum {
VIR_DOMAIN_EVENT_IO_ERROR_NONE = 0,
VIR_DOMAIN_EVENT_IO_ERROR_PAUSE,
VIR_DOMAIN_EVENT_IO_ERROR_REPORT,
} virDomainEventIOErrorAction;
In addition it has the source path of the disk that had the
error and its unique device alias. It does not include the
target device name (/dev/sda), since this would preclude
triggering IO errors from other file backed devices (eg
serial ports connected to a file)
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
struct {
|
|
|
|
char *srcPath;
|
|
|
|
char *devAlias;
|
|
|
|
int action;
|
Add support for another explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON
This event is the same as the previous VIR_DOMAIN_ID_IO_ERROR
event, but also includes a string describing the cause of
the event.
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorReasonCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
const char *reason,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
char *reason;
|
Add support for an explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR
This event includes the action that is about to be taken
as a result of the watchdog triggering
typedef enum {
VIR_DOMAIN_EVENT_IO_ERROR_NONE = 0,
VIR_DOMAIN_EVENT_IO_ERROR_PAUSE,
VIR_DOMAIN_EVENT_IO_ERROR_REPORT,
} virDomainEventIOErrorAction;
In addition it has the source path of the disk that had the
error and its unique device alias. It does not include the
target device name (/dev/sda), since this would preclude
triggering IO errors from other file backed devices (eg
serial ports connected to a file)
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
} ioError;
|
Add domain events for graphics network clients
This introduces a new event type
VIR_DOMAIN_EVENT_ID_GRAPHICS
The same event can be emitted in 3 scenarios
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_CONNECT = 0,
VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE,
VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT,
} virDomainEventGraphicsPhase;
Connect/disconnect are triggered at socket accept/close.
The initialize phase is immediately after the protocol
setup and authentication has completed. ie when the
client is authorized and about to start interacting with
the graphical desktop
This event comes with *a lot* of potential information
- IP address, port & address family of client
- IP address, port & address family of server
- Authentication scheme (arbitrary string)
- Authenticated subject identity. A subject may have
multiple identities with some authentication schemes.
For example, vencrypt+sasl results in a x509dname
and saslUsername identities.
This results in a very complicated callback :-(
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4,
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6,
} virDomainEventGraphicsAddressType;
struct _virDomainEventGraphicsAddress {
int family;
const char *node;
const char *service;
};
typedef struct _virDomainEventGraphicsAddress virDomainEventGraphicsAddress;
typedef virDomainEventGraphicsAddress *virDomainEventGraphicsAddressPtr;
struct _virDomainEventGraphicsSubject {
int nidentity;
struct {
const char *type;
const char *name;
} *identities;
};
typedef struct _virDomainEventGraphicsSubject virDomainEventGraphicsSubject;
typedef virDomainEventGraphicsSubject *virDomainEventGraphicsSubjectPtr;
typedef void (*virConnectDomainEventGraphicsCallback)(virConnectPtr conn,
virDomainPtr dom,
int phase,
virDomainEventGraphicsAddressPtr local,
virDomainEventGraphicsAddressPtr remote,
const char *authScheme,
virDomainEventGraphicsSubjectPtr subject,
void *opaque);
The wire protocol is similarly complex
struct remote_domain_event_graphics_address {
int family;
remote_nonnull_string node;
remote_nonnull_string service;
};
const REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX = 20;
struct remote_domain_event_graphics_identity {
remote_nonnull_string type;
remote_nonnull_string name;
};
struct remote_domain_event_graphics_msg {
remote_nonnull_domain dom;
int phase;
remote_domain_event_graphics_address local;
remote_domain_event_graphics_address remote;
remote_nonnull_string authScheme;
remote_domain_event_graphics_identity subject<REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX>;
};
This is currently implemented in QEMU for the VNC graphics
protocol, but designed to be usable with SPICE graphics in
the future too.
* daemon/remote.c: Dispatch graphics events to client
* examples/domain-events/events-c/event-test.c: Watch for
graphics events
* include/libvirt/libvirt.h.in: Define new graphics event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle graphics events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for VNC events and emit a libvirt graphics event
* src/remote/remote_driver.c: Receive and dispatch graphics
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
graphics events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for VNC_CONNECTED,
VNC_INITIALIZED & VNC_DISCONNETED events from QEMU monitor
2010-03-19 13:27:45 +00:00
|
|
|
struct {
|
|
|
|
int phase;
|
|
|
|
virDomainEventGraphicsAddressPtr local;
|
|
|
|
virDomainEventGraphicsAddressPtr remote;
|
|
|
|
char *authScheme;
|
|
|
|
virDomainEventGraphicsSubjectPtr subject;
|
|
|
|
} graphics;
|
2011-07-22 05:57:42 +00:00
|
|
|
struct {
|
|
|
|
char *path;
|
|
|
|
int type;
|
|
|
|
int status;
|
|
|
|
} blockJob;
|
2011-10-18 14:15:42 +00:00
|
|
|
struct {
|
|
|
|
char *oldSrcPath;
|
|
|
|
char *newSrcPath;
|
|
|
|
char *devAlias;
|
|
|
|
int reason;
|
|
|
|
} diskChange;
|
2012-03-23 13:44:50 +00:00
|
|
|
struct {
|
|
|
|
char *devAlias;
|
|
|
|
int reason;
|
|
|
|
} trayChange;
|
2010-03-18 14:06:09 +00:00
|
|
|
} data;
|
2010-03-18 13:17:14 +00:00
|
|
|
};
|
2008-11-04 23:33:57 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* virDomainEventCallbackListFree:
|
|
|
|
* @list: event callback list head
|
|
|
|
*
|
|
|
|
* Free the memory in the domain event callback list
|
|
|
|
*/
|
2011-12-13 11:41:01 +00:00
|
|
|
static void
|
2008-11-04 23:33:57 +00:00
|
|
|
virDomainEventCallbackListFree(virDomainEventCallbackListPtr list)
|
|
|
|
{
|
|
|
|
int i;
|
2009-08-12 10:07:41 +00:00
|
|
|
if (!list)
|
|
|
|
return;
|
|
|
|
|
2008-11-04 23:33:57 +00:00
|
|
|
for (i=0; i<list->count; i++) {
|
2008-11-19 15:25:24 +00:00
|
|
|
virFreeCallback freecb = list->callbacks[i]->freecb;
|
|
|
|
if (freecb)
|
|
|
|
(*freecb)(list->callbacks[i]->opaque);
|
2008-11-04 23:33:57 +00:00
|
|
|
VIR_FREE(list->callbacks[i]);
|
|
|
|
}
|
|
|
|
VIR_FREE(list);
|
|
|
|
}
|
2010-03-18 14:06:09 +00:00
|
|
|
|
|
|
|
|
2008-11-04 23:33:57 +00:00
|
|
|
/**
|
|
|
|
* virDomainEventCallbackListRemove:
|
|
|
|
* @conn: pointer to the connection
|
|
|
|
* @cbList: the list
|
|
|
|
* @callback: the callback to remove
|
|
|
|
*
|
|
|
|
* Internal function to remove a callback from a virDomainEventCallbackListPtr
|
|
|
|
*/
|
2011-12-13 11:41:01 +00:00
|
|
|
static int
|
2008-11-04 23:33:57 +00:00
|
|
|
virDomainEventCallbackListRemove(virConnectPtr conn,
|
|
|
|
virDomainEventCallbackListPtr cbList,
|
|
|
|
virConnectDomainEventCallback callback)
|
|
|
|
{
|
2011-12-13 10:39:17 +00:00
|
|
|
int ret = 0;
|
2008-11-04 23:33:57 +00:00
|
|
|
int i;
|
|
|
|
for (i = 0 ; i < cbList->count ; i++) {
|
2010-03-18 14:06:09 +00:00
|
|
|
if (cbList->callbacks[i]->cb == VIR_DOMAIN_EVENT_CALLBACK(callback) &&
|
|
|
|
cbList->callbacks[i]->eventID == VIR_DOMAIN_EVENT_ID_LIFECYCLE &&
|
|
|
|
cbList->callbacks[i]->conn == conn) {
|
2008-11-19 15:25:24 +00:00
|
|
|
virFreeCallback freecb = cbList->callbacks[i]->freecb;
|
|
|
|
if (freecb)
|
|
|
|
(*freecb)(cbList->callbacks[i]->opaque);
|
2008-11-04 23:33:57 +00:00
|
|
|
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)));
|
|
|
|
|
|
|
|
if (VIR_REALLOC_N(cbList->callbacks,
|
|
|
|
cbList->count - 1) < 0) {
|
|
|
|
; /* Failure to reduce memory allocation isn't fatal */
|
|
|
|
}
|
|
|
|
cbList->count--;
|
|
|
|
|
2011-12-13 10:39:17 +00:00
|
|
|
for (i = 0 ; i < cbList->count ; i++) {
|
|
|
|
if (!cbList->callbacks[i]->deleted)
|
|
|
|
ret++;
|
|
|
|
}
|
|
|
|
return ret;
|
2008-11-04 23:33:57 +00:00
|
|
|
}
|
|
|
|
}
|
2010-01-13 18:11:33 +00:00
|
|
|
|
2010-04-03 13:22:58 +00:00
|
|
|
eventReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
2010-01-13 18:11:33 +00:00
|
|
|
_("could not find event callback for removal"));
|
2008-11-04 23:33:57 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-03-18 14:06:09 +00:00
|
|
|
|
2010-03-18 14:20:53 +00:00
|
|
|
/**
|
|
|
|
* virDomainEventCallbackListRemoveID:
|
|
|
|
* @conn: pointer to the connection
|
|
|
|
* @cbList: the list
|
|
|
|
* @callback: the callback to remove
|
|
|
|
*
|
|
|
|
* Internal function to remove a callback from a virDomainEventCallbackListPtr
|
|
|
|
*/
|
2011-12-13 11:41:01 +00:00
|
|
|
static int
|
2010-03-18 14:20:53 +00:00
|
|
|
virDomainEventCallbackListRemoveID(virConnectPtr conn,
|
|
|
|
virDomainEventCallbackListPtr cbList,
|
|
|
|
int callbackID)
|
|
|
|
{
|
2011-12-13 10:39:17 +00:00
|
|
|
int ret = 0;
|
2010-03-18 14:20:53 +00:00
|
|
|
int i;
|
|
|
|
for (i = 0 ; i < cbList->count ; i++) {
|
|
|
|
if (cbList->callbacks[i]->callbackID == callbackID &&
|
|
|
|
cbList->callbacks[i]->conn == conn) {
|
|
|
|
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)));
|
|
|
|
|
|
|
|
if (VIR_REALLOC_N(cbList->callbacks,
|
|
|
|
cbList->count - 1) < 0) {
|
|
|
|
; /* Failure to reduce memory allocation isn't fatal */
|
|
|
|
}
|
|
|
|
cbList->count--;
|
|
|
|
|
2011-12-13 10:39:17 +00:00
|
|
|
for (i = 0 ; i < cbList->count ; i++) {
|
|
|
|
if (!cbList->callbacks[i]->deleted)
|
|
|
|
ret++;
|
|
|
|
}
|
|
|
|
return ret;
|
2010-03-18 14:20:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-03 13:22:58 +00:00
|
|
|
eventReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
2010-03-18 14:20:53 +00:00
|
|
|
_("could not find event callback for removal"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-13 11:41:01 +00:00
|
|
|
static int
|
|
|
|
virDomainEventCallbackListMarkDelete(virConnectPtr conn,
|
|
|
|
virDomainEventCallbackListPtr cbList,
|
|
|
|
virConnectDomainEventCallback callback)
|
2008-12-04 21:09:20 +00:00
|
|
|
{
|
2011-12-13 10:39:17 +00:00
|
|
|
int ret = 0;
|
2008-12-04 21:09:20 +00:00
|
|
|
int i;
|
|
|
|
for (i = 0 ; i < cbList->count ; i++) {
|
2010-03-18 14:06:09 +00:00
|
|
|
if (cbList->callbacks[i]->cb == VIR_DOMAIN_EVENT_CALLBACK(callback) &&
|
|
|
|
cbList->callbacks[i]->eventID == VIR_DOMAIN_EVENT_ID_LIFECYCLE &&
|
|
|
|
cbList->callbacks[i]->conn == conn) {
|
2008-12-04 21:09:20 +00:00
|
|
|
cbList->callbacks[i]->deleted = 1;
|
2011-12-13 10:39:17 +00:00
|
|
|
for (i = 0 ; i < cbList->count ; i++) {
|
|
|
|
if (!cbList->callbacks[i]->deleted)
|
|
|
|
ret++;
|
|
|
|
}
|
|
|
|
return ret;
|
2008-12-04 21:09:20 +00:00
|
|
|
}
|
|
|
|
}
|
2010-01-13 18:11:33 +00:00
|
|
|
|
2010-04-03 13:22:58 +00:00
|
|
|
eventReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
2010-01-13 18:11:33 +00:00
|
|
|
_("could not find event callback for deletion"));
|
2008-12-04 21:09:20 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-03-18 14:06:09 +00:00
|
|
|
|
2011-12-13 11:41:01 +00:00
|
|
|
static int
|
|
|
|
virDomainEventCallbackListMarkDeleteID(virConnectPtr conn,
|
|
|
|
virDomainEventCallbackListPtr cbList,
|
|
|
|
int callbackID)
|
2010-03-18 14:20:53 +00:00
|
|
|
{
|
2011-12-13 10:39:17 +00:00
|
|
|
int ret = 0;
|
2010-03-18 14:20:53 +00:00
|
|
|
int i;
|
|
|
|
for (i = 0 ; i < cbList->count ; i++) {
|
|
|
|
if (cbList->callbacks[i]->callbackID == callbackID &&
|
|
|
|
cbList->callbacks[i]->conn == conn) {
|
|
|
|
cbList->callbacks[i]->deleted = 1;
|
2011-12-13 10:39:17 +00:00
|
|
|
for (i = 0 ; i < cbList->count ; i++) {
|
|
|
|
if (!cbList->callbacks[i]->deleted)
|
|
|
|
ret++;
|
|
|
|
}
|
|
|
|
return ret;
|
2010-03-18 14:20:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-03 13:22:58 +00:00
|
|
|
eventReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
2010-03-18 14:20:53 +00:00
|
|
|
_("could not find event callback for deletion"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-13 11:41:01 +00:00
|
|
|
static int
|
|
|
|
virDomainEventCallbackListPurgeMarked(virDomainEventCallbackListPtr cbList)
|
2008-12-04 21:09:20 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-03-18 14:06:09 +00:00
|
|
|
|
2010-03-18 14:20:53 +00:00
|
|
|
/**
|
|
|
|
* virDomainEventCallbackListAddID:
|
|
|
|
* @conn: pointer to the connection
|
|
|
|
* @cbList: the list
|
|
|
|
* @eventID: the event ID
|
|
|
|
* @callback: the callback to add
|
|
|
|
* @opaque: opaque data tio pass to callback
|
Return count of callbacks when registering callbacks
When registering a callback for a particular event some callers
need to know how many callbacks already exist for that event.
While it is possible to ask for a count, this is not free from
race conditions when threaded. Thus the API for registering
callbacks should return the count of callbacks. Also rename
virDomainEventStateDeregisterAny to virDomainEventStateDeregisterID
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Return count of callbacks when
registering callbacks
* src/libxl/libxl_driver.c, src/libxl/libxl_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/remote/remote_driver.c, src/uml/uml_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xen_driver.c: Update
for change in APIs
2011-12-13 23:38:54 +00:00
|
|
|
* @callbackID: filled with callback ID
|
2010-03-18 14:20:53 +00:00
|
|
|
*
|
|
|
|
* Internal function to add a callback from a virDomainEventCallbackListPtr
|
|
|
|
*/
|
2011-12-13 11:41:01 +00:00
|
|
|
static int
|
2010-03-18 14:20:53 +00:00
|
|
|
virDomainEventCallbackListAddID(virConnectPtr conn,
|
|
|
|
virDomainEventCallbackListPtr cbList,
|
|
|
|
virDomainPtr dom,
|
|
|
|
int eventID,
|
|
|
|
virConnectDomainEventGenericCallback callback,
|
|
|
|
void *opaque,
|
Return count of callbacks when registering callbacks
When registering a callback for a particular event some callers
need to know how many callbacks already exist for that event.
While it is possible to ask for a count, this is not free from
race conditions when threaded. Thus the API for registering
callbacks should return the count of callbacks. Also rename
virDomainEventStateDeregisterAny to virDomainEventStateDeregisterID
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Return count of callbacks when
registering callbacks
* src/libxl/libxl_driver.c, src/libxl/libxl_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/remote/remote_driver.c, src/uml/uml_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xen_driver.c: Update
for change in APIs
2011-12-13 23:38:54 +00:00
|
|
|
virFreeCallback freecb,
|
|
|
|
int *callbackID)
|
2008-11-04 23:33:57 +00:00
|
|
|
{
|
|
|
|
virDomainEventCallbackPtr event;
|
2010-03-18 14:06:09 +00:00
|
|
|
int i;
|
Return count of callbacks when registering callbacks
When registering a callback for a particular event some callers
need to know how many callbacks already exist for that event.
While it is possible to ask for a count, this is not free from
race conditions when threaded. Thus the API for registering
callbacks should return the count of callbacks. Also rename
virDomainEventStateDeregisterAny to virDomainEventStateDeregisterID
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Return count of callbacks when
registering callbacks
* src/libxl/libxl_driver.c, src/libxl/libxl_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/remote/remote_driver.c, src/uml/uml_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xen_driver.c: Update
for change in APIs
2011-12-13 23:38:54 +00:00
|
|
|
int ret = 0;
|
2008-11-04 23:33:57 +00:00
|
|
|
|
|
|
|
/* Check incoming */
|
|
|
|
if ( !cbList ) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check if we already have this callback on our list */
|
2010-03-18 14:06:09 +00:00
|
|
|
for (i = 0 ; i < cbList->count ; i++) {
|
|
|
|
if (cbList->callbacks[i]->cb == VIR_DOMAIN_EVENT_CALLBACK(callback) &&
|
2012-01-13 20:44:42 +00:00
|
|
|
cbList->callbacks[i]->eventID == eventID &&
|
2012-06-27 10:06:45 +00:00
|
|
|
cbList->callbacks[i]->conn == conn &&
|
|
|
|
((dom && cbList->callbacks[i]->dom &&
|
|
|
|
memcmp(cbList->callbacks[i]->dom->uuid,
|
|
|
|
dom->uuid, VIR_UUID_BUFLEN) == 0) ||
|
|
|
|
(!dom && !cbList->callbacks[i]->dom))) {
|
2010-04-03 13:22:58 +00:00
|
|
|
eventReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
2010-01-13 18:11:33 +00:00
|
|
|
_("event callback already tracked"));
|
2008-11-04 23:33:57 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Allocate new event */
|
2010-03-18 14:20:53 +00:00
|
|
|
if (VIR_ALLOC(event) < 0)
|
|
|
|
goto no_memory;
|
2008-11-04 23:33:57 +00:00
|
|
|
event->conn = conn;
|
2010-03-18 14:20:53 +00:00
|
|
|
event->cb = callback;
|
|
|
|
event->eventID = eventID;
|
2008-11-04 23:33:57 +00:00
|
|
|
event->opaque = opaque;
|
2008-11-19 15:25:24 +00:00
|
|
|
event->freecb = freecb;
|
2008-11-04 23:33:57 +00:00
|
|
|
|
2010-03-18 14:20:53 +00:00
|
|
|
if (dom) {
|
|
|
|
if (VIR_ALLOC(event->dom) < 0)
|
|
|
|
goto no_memory;
|
|
|
|
if (!(event->dom->name = strdup(dom->name)))
|
|
|
|
goto no_memory;
|
|
|
|
memcpy(event->dom->uuid, dom->uuid, VIR_UUID_BUFLEN);
|
|
|
|
event->dom->id = dom->id;
|
2008-11-04 23:33:57 +00:00
|
|
|
}
|
|
|
|
|
2010-03-18 14:20:53 +00:00
|
|
|
/* Make space on list */
|
|
|
|
if (VIR_REALLOC_N(cbList->callbacks, cbList->count + 1) < 0)
|
|
|
|
goto no_memory;
|
|
|
|
|
2008-11-04 23:33:57 +00:00
|
|
|
event->conn->refs++;
|
|
|
|
|
2010-03-18 14:06:09 +00:00
|
|
|
cbList->callbacks[cbList->count] = event;
|
2008-11-04 23:33:57 +00:00
|
|
|
cbList->count++;
|
2010-03-18 14:06:09 +00:00
|
|
|
|
|
|
|
event->callbackID = cbList->nextID++;
|
|
|
|
|
Return count of callbacks when registering callbacks
When registering a callback for a particular event some callers
need to know how many callbacks already exist for that event.
While it is possible to ask for a count, this is not free from
race conditions when threaded. Thus the API for registering
callbacks should return the count of callbacks. Also rename
virDomainEventStateDeregisterAny to virDomainEventStateDeregisterID
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Return count of callbacks when
registering callbacks
* src/libxl/libxl_driver.c, src/libxl/libxl_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/remote/remote_driver.c, src/uml/uml_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xen_driver.c: Update
for change in APIs
2011-12-13 23:38:54 +00:00
|
|
|
for (i = 0 ; i < cbList->count ; i++) {
|
2012-01-13 20:44:42 +00:00
|
|
|
if (cbList->callbacks[i]->eventID == eventID &&
|
Return count of callbacks when registering callbacks
When registering a callback for a particular event some callers
need to know how many callbacks already exist for that event.
While it is possible to ask for a count, this is not free from
race conditions when threaded. Thus the API for registering
callbacks should return the count of callbacks. Also rename
virDomainEventStateDeregisterAny to virDomainEventStateDeregisterID
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Return count of callbacks when
registering callbacks
* src/libxl/libxl_driver.c, src/libxl/libxl_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/remote/remote_driver.c, src/uml/uml_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xen_driver.c: Update
for change in APIs
2011-12-13 23:38:54 +00:00
|
|
|
cbList->callbacks[i]->conn == conn &&
|
|
|
|
!cbList->callbacks[i]->deleted)
|
|
|
|
ret++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (callbackID)
|
|
|
|
*callbackID = event->callbackID;
|
|
|
|
|
|
|
|
return ret;
|
2010-03-18 14:20:53 +00:00
|
|
|
|
|
|
|
no_memory:
|
|
|
|
virReportOOMError();
|
|
|
|
|
|
|
|
if (event) {
|
|
|
|
if (event->dom)
|
|
|
|
VIR_FREE(event->dom->name);
|
|
|
|
VIR_FREE(event->dom);
|
|
|
|
}
|
|
|
|
VIR_FREE(event);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-13 11:41:01 +00:00
|
|
|
/**
|
|
|
|
* virDomainEventCallbackListAdd:
|
|
|
|
* @conn: pointer to the connection
|
|
|
|
* @cbList: the list
|
|
|
|
* @callback: the callback to add
|
|
|
|
* @opaque: opaque data tio pass to callback
|
|
|
|
*
|
|
|
|
* Internal function to add a callback from a virDomainEventCallbackListPtr
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
virDomainEventCallbackListAdd(virConnectPtr conn,
|
|
|
|
virDomainEventCallbackListPtr cbList,
|
|
|
|
virConnectDomainEventCallback callback,
|
|
|
|
void *opaque,
|
|
|
|
virFreeCallback freecb)
|
2010-03-18 14:20:53 +00:00
|
|
|
{
|
2011-12-13 11:41:01 +00:00
|
|
|
return virDomainEventCallbackListAddID(conn, cbList, NULL,
|
|
|
|
VIR_DOMAIN_EVENT_ID_LIFECYCLE,
|
|
|
|
VIR_DOMAIN_EVENT_CALLBACK(callback),
|
|
|
|
opaque, freecb, NULL);
|
2010-03-18 14:20:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-13 11:41:01 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
virDomainEventCallbackListEventID(virConnectPtr conn,
|
|
|
|
virDomainEventCallbackListPtr cbList,
|
|
|
|
int callbackID)
|
2010-03-18 14:20:53 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0 ; i < cbList->count ; i++) {
|
|
|
|
if (cbList->callbacks[i]->deleted)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (cbList->callbacks[i]->callbackID == callbackID &&
|
|
|
|
cbList->callbacks[i]->conn == conn)
|
|
|
|
return cbList->callbacks[i]->eventID;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
2008-11-04 23:33:57 +00:00
|
|
|
}
|
|
|
|
|
2010-03-18 13:17:14 +00:00
|
|
|
|
2008-12-04 21:09:20 +00:00
|
|
|
void virDomainEventFree(virDomainEventPtr event)
|
|
|
|
{
|
|
|
|
if (!event)
|
|
|
|
return;
|
|
|
|
|
Add domain events for graphics network clients
This introduces a new event type
VIR_DOMAIN_EVENT_ID_GRAPHICS
The same event can be emitted in 3 scenarios
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_CONNECT = 0,
VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE,
VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT,
} virDomainEventGraphicsPhase;
Connect/disconnect are triggered at socket accept/close.
The initialize phase is immediately after the protocol
setup and authentication has completed. ie when the
client is authorized and about to start interacting with
the graphical desktop
This event comes with *a lot* of potential information
- IP address, port & address family of client
- IP address, port & address family of server
- Authentication scheme (arbitrary string)
- Authenticated subject identity. A subject may have
multiple identities with some authentication schemes.
For example, vencrypt+sasl results in a x509dname
and saslUsername identities.
This results in a very complicated callback :-(
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4,
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6,
} virDomainEventGraphicsAddressType;
struct _virDomainEventGraphicsAddress {
int family;
const char *node;
const char *service;
};
typedef struct _virDomainEventGraphicsAddress virDomainEventGraphicsAddress;
typedef virDomainEventGraphicsAddress *virDomainEventGraphicsAddressPtr;
struct _virDomainEventGraphicsSubject {
int nidentity;
struct {
const char *type;
const char *name;
} *identities;
};
typedef struct _virDomainEventGraphicsSubject virDomainEventGraphicsSubject;
typedef virDomainEventGraphicsSubject *virDomainEventGraphicsSubjectPtr;
typedef void (*virConnectDomainEventGraphicsCallback)(virConnectPtr conn,
virDomainPtr dom,
int phase,
virDomainEventGraphicsAddressPtr local,
virDomainEventGraphicsAddressPtr remote,
const char *authScheme,
virDomainEventGraphicsSubjectPtr subject,
void *opaque);
The wire protocol is similarly complex
struct remote_domain_event_graphics_address {
int family;
remote_nonnull_string node;
remote_nonnull_string service;
};
const REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX = 20;
struct remote_domain_event_graphics_identity {
remote_nonnull_string type;
remote_nonnull_string name;
};
struct remote_domain_event_graphics_msg {
remote_nonnull_domain dom;
int phase;
remote_domain_event_graphics_address local;
remote_domain_event_graphics_address remote;
remote_nonnull_string authScheme;
remote_domain_event_graphics_identity subject<REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX>;
};
This is currently implemented in QEMU for the VNC graphics
protocol, but designed to be usable with SPICE graphics in
the future too.
* daemon/remote.c: Dispatch graphics events to client
* examples/domain-events/events-c/event-test.c: Watch for
graphics events
* include/libvirt/libvirt.h.in: Define new graphics event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle graphics events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for VNC events and emit a libvirt graphics event
* src/remote/remote_driver.c: Receive and dispatch graphics
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
graphics events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for VNC_CONNECTED,
VNC_INITIALIZED & VNC_DISCONNETED events from QEMU monitor
2010-03-19 13:27:45 +00:00
|
|
|
switch (event->eventID) {
|
2010-12-01 15:29:31 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON:
|
Add domain events for graphics network clients
This introduces a new event type
VIR_DOMAIN_EVENT_ID_GRAPHICS
The same event can be emitted in 3 scenarios
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_CONNECT = 0,
VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE,
VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT,
} virDomainEventGraphicsPhase;
Connect/disconnect are triggered at socket accept/close.
The initialize phase is immediately after the protocol
setup and authentication has completed. ie when the
client is authorized and about to start interacting with
the graphical desktop
This event comes with *a lot* of potential information
- IP address, port & address family of client
- IP address, port & address family of server
- Authentication scheme (arbitrary string)
- Authenticated subject identity. A subject may have
multiple identities with some authentication schemes.
For example, vencrypt+sasl results in a x509dname
and saslUsername identities.
This results in a very complicated callback :-(
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4,
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6,
} virDomainEventGraphicsAddressType;
struct _virDomainEventGraphicsAddress {
int family;
const char *node;
const char *service;
};
typedef struct _virDomainEventGraphicsAddress virDomainEventGraphicsAddress;
typedef virDomainEventGraphicsAddress *virDomainEventGraphicsAddressPtr;
struct _virDomainEventGraphicsSubject {
int nidentity;
struct {
const char *type;
const char *name;
} *identities;
};
typedef struct _virDomainEventGraphicsSubject virDomainEventGraphicsSubject;
typedef virDomainEventGraphicsSubject *virDomainEventGraphicsSubjectPtr;
typedef void (*virConnectDomainEventGraphicsCallback)(virConnectPtr conn,
virDomainPtr dom,
int phase,
virDomainEventGraphicsAddressPtr local,
virDomainEventGraphicsAddressPtr remote,
const char *authScheme,
virDomainEventGraphicsSubjectPtr subject,
void *opaque);
The wire protocol is similarly complex
struct remote_domain_event_graphics_address {
int family;
remote_nonnull_string node;
remote_nonnull_string service;
};
const REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX = 20;
struct remote_domain_event_graphics_identity {
remote_nonnull_string type;
remote_nonnull_string name;
};
struct remote_domain_event_graphics_msg {
remote_nonnull_domain dom;
int phase;
remote_domain_event_graphics_address local;
remote_domain_event_graphics_address remote;
remote_nonnull_string authScheme;
remote_domain_event_graphics_identity subject<REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX>;
};
This is currently implemented in QEMU for the VNC graphics
protocol, but designed to be usable with SPICE graphics in
the future too.
* daemon/remote.c: Dispatch graphics events to client
* examples/domain-events/events-c/event-test.c: Watch for
graphics events
* include/libvirt/libvirt.h.in: Define new graphics event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle graphics events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for VNC events and emit a libvirt graphics event
* src/remote/remote_driver.c: Receive and dispatch graphics
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
graphics events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for VNC_CONNECTED,
VNC_INITIALIZED & VNC_DISCONNETED events from QEMU monitor
2010-03-19 13:27:45 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_IO_ERROR:
|
Add support for an explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR
This event includes the action that is about to be taken
as a result of the watchdog triggering
typedef enum {
VIR_DOMAIN_EVENT_IO_ERROR_NONE = 0,
VIR_DOMAIN_EVENT_IO_ERROR_PAUSE,
VIR_DOMAIN_EVENT_IO_ERROR_REPORT,
} virDomainEventIOErrorAction;
In addition it has the source path of the disk that had the
error and its unique device alias. It does not include the
target device name (/dev/sda), since this would preclude
triggering IO errors from other file backed devices (eg
serial ports connected to a file)
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
VIR_FREE(event->data.ioError.srcPath);
|
|
|
|
VIR_FREE(event->data.ioError.devAlias);
|
Add support for another explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON
This event is the same as the previous VIR_DOMAIN_ID_IO_ERROR
event, but also includes a string describing the cause of
the event.
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorReasonCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
const char *reason,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
VIR_FREE(event->data.ioError.reason);
|
Add domain events for graphics network clients
This introduces a new event type
VIR_DOMAIN_EVENT_ID_GRAPHICS
The same event can be emitted in 3 scenarios
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_CONNECT = 0,
VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE,
VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT,
} virDomainEventGraphicsPhase;
Connect/disconnect are triggered at socket accept/close.
The initialize phase is immediately after the protocol
setup and authentication has completed. ie when the
client is authorized and about to start interacting with
the graphical desktop
This event comes with *a lot* of potential information
- IP address, port & address family of client
- IP address, port & address family of server
- Authentication scheme (arbitrary string)
- Authenticated subject identity. A subject may have
multiple identities with some authentication schemes.
For example, vencrypt+sasl results in a x509dname
and saslUsername identities.
This results in a very complicated callback :-(
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4,
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6,
} virDomainEventGraphicsAddressType;
struct _virDomainEventGraphicsAddress {
int family;
const char *node;
const char *service;
};
typedef struct _virDomainEventGraphicsAddress virDomainEventGraphicsAddress;
typedef virDomainEventGraphicsAddress *virDomainEventGraphicsAddressPtr;
struct _virDomainEventGraphicsSubject {
int nidentity;
struct {
const char *type;
const char *name;
} *identities;
};
typedef struct _virDomainEventGraphicsSubject virDomainEventGraphicsSubject;
typedef virDomainEventGraphicsSubject *virDomainEventGraphicsSubjectPtr;
typedef void (*virConnectDomainEventGraphicsCallback)(virConnectPtr conn,
virDomainPtr dom,
int phase,
virDomainEventGraphicsAddressPtr local,
virDomainEventGraphicsAddressPtr remote,
const char *authScheme,
virDomainEventGraphicsSubjectPtr subject,
void *opaque);
The wire protocol is similarly complex
struct remote_domain_event_graphics_address {
int family;
remote_nonnull_string node;
remote_nonnull_string service;
};
const REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX = 20;
struct remote_domain_event_graphics_identity {
remote_nonnull_string type;
remote_nonnull_string name;
};
struct remote_domain_event_graphics_msg {
remote_nonnull_domain dom;
int phase;
remote_domain_event_graphics_address local;
remote_domain_event_graphics_address remote;
remote_nonnull_string authScheme;
remote_domain_event_graphics_identity subject<REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX>;
};
This is currently implemented in QEMU for the VNC graphics
protocol, but designed to be usable with SPICE graphics in
the future too.
* daemon/remote.c: Dispatch graphics events to client
* examples/domain-events/events-c/event-test.c: Watch for
graphics events
* include/libvirt/libvirt.h.in: Define new graphics event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle graphics events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for VNC events and emit a libvirt graphics event
* src/remote/remote_driver.c: Receive and dispatch graphics
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
graphics events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for VNC_CONNECTED,
VNC_INITIALIZED & VNC_DISCONNETED events from QEMU monitor
2010-03-19 13:27:45 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_EVENT_ID_GRAPHICS:
|
|
|
|
if (event->data.graphics.local) {
|
|
|
|
VIR_FREE(event->data.graphics.local->node);
|
|
|
|
VIR_FREE(event->data.graphics.local->service);
|
|
|
|
VIR_FREE(event->data.graphics.local);
|
|
|
|
}
|
|
|
|
if (event->data.graphics.remote) {
|
|
|
|
VIR_FREE(event->data.graphics.remote->node);
|
|
|
|
VIR_FREE(event->data.graphics.remote->service);
|
|
|
|
VIR_FREE(event->data.graphics.remote);
|
|
|
|
}
|
|
|
|
VIR_FREE(event->data.graphics.authScheme);
|
|
|
|
if (event->data.graphics.subject) {
|
|
|
|
int i;
|
|
|
|
for (i = 0 ; i < event->data.graphics.subject->nidentity ; i++) {
|
|
|
|
VIR_FREE(event->data.graphics.subject->identities[i].type);
|
|
|
|
VIR_FREE(event->data.graphics.subject->identities[i].name);
|
|
|
|
}
|
|
|
|
VIR_FREE(event->data.graphics.subject);
|
|
|
|
}
|
2011-07-22 05:57:42 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_EVENT_ID_BLOCK_JOB:
|
|
|
|
VIR_FREE(event->data.blockJob.path);
|
|
|
|
break;
|
2011-10-18 14:15:42 +00:00
|
|
|
|
|
|
|
case VIR_DOMAIN_EVENT_ID_DISK_CHANGE:
|
|
|
|
VIR_FREE(event->data.diskChange.oldSrcPath);
|
|
|
|
VIR_FREE(event->data.diskChange.newSrcPath);
|
|
|
|
VIR_FREE(event->data.diskChange.devAlias);
|
|
|
|
break;
|
2012-03-23 13:44:50 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_TRAY_CHANGE:
|
|
|
|
VIR_FREE(event->data.trayChange.devAlias);
|
|
|
|
break;
|
Add support for an explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR
This event includes the action that is about to be taken
as a result of the watchdog triggering
typedef enum {
VIR_DOMAIN_EVENT_IO_ERROR_NONE = 0,
VIR_DOMAIN_EVENT_IO_ERROR_PAUSE,
VIR_DOMAIN_EVENT_IO_ERROR_REPORT,
} virDomainEventIOErrorAction;
In addition it has the source path of the disk that had the
error and its unique device alias. It does not include the
target device name (/dev/sda), since this would preclude
triggering IO errors from other file backed devices (eg
serial ports connected to a file)
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
}
|
|
|
|
|
2010-03-18 14:06:09 +00:00
|
|
|
VIR_FREE(event->dom.name);
|
2008-12-04 21:09:20 +00:00
|
|
|
VIR_FREE(event);
|
|
|
|
}
|
|
|
|
|
2011-01-05 22:27:40 +00:00
|
|
|
/**
|
|
|
|
* virDomainEventQueueFree:
|
|
|
|
* @queue: pointer to the queue
|
|
|
|
*
|
|
|
|
* Free the memory in the queue. We process this like a list here
|
|
|
|
*/
|
2011-12-13 11:41:01 +00:00
|
|
|
static void
|
2011-01-05 22:27:40 +00:00
|
|
|
virDomainEventQueueFree(virDomainEventQueuePtr queue)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
if (!queue)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < queue->count ; i++) {
|
|
|
|
virDomainEventFree(queue->events[i]);
|
|
|
|
}
|
|
|
|
VIR_FREE(queue->events);
|
|
|
|
VIR_FREE(queue);
|
|
|
|
}
|
2008-12-04 21:09:20 +00:00
|
|
|
|
2011-12-13 11:41:01 +00:00
|
|
|
static virDomainEventQueuePtr
|
|
|
|
virDomainEventQueueNew(void)
|
2008-12-04 21:09:20 +00:00
|
|
|
{
|
|
|
|
virDomainEventQueuePtr ret;
|
|
|
|
|
2010-01-13 18:11:33 +00:00
|
|
|
if (VIR_ALLOC(ret) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-12-04 21:09:20 +00:00
|
|
|
return NULL;
|
2010-01-13 18:11:33 +00:00
|
|
|
}
|
2008-12-04 21:09:20 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-10-06 16:44:13 +00:00
|
|
|
static void
|
|
|
|
virDomainEventStateLock(virDomainEventStatePtr state)
|
|
|
|
{
|
|
|
|
virMutexLock(&state->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
virDomainEventStateUnlock(virDomainEventStatePtr state)
|
|
|
|
{
|
|
|
|
virMutexUnlock(&state->lock);
|
|
|
|
}
|
|
|
|
|
2011-01-05 22:27:40 +00:00
|
|
|
/**
|
|
|
|
* virDomainEventStateFree:
|
|
|
|
* @list: virDomainEventStatePtr to free
|
|
|
|
*
|
|
|
|
* Free a virDomainEventStatePtr and its members, and unregister the timer.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
virDomainEventStateFree(virDomainEventStatePtr state)
|
|
|
|
{
|
|
|
|
if (!state)
|
|
|
|
return;
|
|
|
|
|
|
|
|
virDomainEventCallbackListFree(state->callbacks);
|
|
|
|
virDomainEventQueueFree(state->queue);
|
|
|
|
|
|
|
|
if (state->timer != -1)
|
|
|
|
virEventRemoveTimeout(state->timer);
|
2011-10-06 16:44:13 +00:00
|
|
|
|
|
|
|
virMutexDestroy(&state->lock);
|
2011-06-02 22:54:09 +00:00
|
|
|
VIR_FREE(state);
|
2011-01-05 22:27:40 +00:00
|
|
|
}
|
|
|
|
|
Hide use of timers for domain event dispatch
Currently all drivers using domain events need to provide a callback
for handling a timer to dispatch events in a clean stack. There is
no technical reason for dispatch to go via driver specific code. It
could trivially be dispatched directly from the domain event code,
thus removing tedious boilerplate code from all drivers
Also fix the libxl & xen drivers to pass 'true' when creating the
virDomainEventState, since they run inside the daemon & thus always
expect events to be present.
* src/conf/domain_event.c, src/conf/domain_event.h: Internalize
dispatch of events from timer callback
* src/libxl/libxl_driver.c, src/lxc/lxc_driver.c,
src/qemu/qemu_domain.c, src/qemu/qemu_driver.c,
src/remote/remote_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c: Remove all timer dispatch functions
2011-12-13 13:46:28 +00:00
|
|
|
|
|
|
|
static void virDomainEventStateFlush(virDomainEventStatePtr state);
|
|
|
|
|
|
|
|
static void
|
|
|
|
virDomainEventTimer(int timer ATTRIBUTE_UNUSED, void *opaque)
|
|
|
|
{
|
|
|
|
virDomainEventStatePtr state = opaque;
|
|
|
|
|
|
|
|
virDomainEventStateFlush(state);
|
|
|
|
}
|
|
|
|
|
2011-01-05 22:51:45 +00:00
|
|
|
/**
|
|
|
|
* virDomainEventStateNew:
|
|
|
|
*/
|
2011-01-05 22:27:40 +00:00
|
|
|
virDomainEventStatePtr
|
2011-12-14 00:25:58 +00:00
|
|
|
virDomainEventStateNew(void)
|
2011-01-05 22:27:40 +00:00
|
|
|
{
|
|
|
|
virDomainEventStatePtr state = NULL;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(state) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2011-10-06 16:44:13 +00:00
|
|
|
if (virMutexInit(&state->lock) < 0) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("unable to initialize state mutex"));
|
|
|
|
VIR_FREE(state);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2011-01-05 22:27:40 +00:00
|
|
|
if (VIR_ALLOC(state->callbacks) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2011-12-14 00:25:58 +00:00
|
|
|
if (!(state->queue = virDomainEventQueueNew()))
|
2011-01-05 22:27:40 +00:00
|
|
|
goto error;
|
|
|
|
|
2011-12-14 00:25:58 +00:00
|
|
|
state->timer = -1;
|
2011-01-05 22:27:40 +00:00
|
|
|
|
|
|
|
return state;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virDomainEventStateFree(state);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-03-18 14:06:09 +00:00
|
|
|
static virDomainEventPtr virDomainEventNewInternal(int eventID,
|
|
|
|
int id,
|
|
|
|
const char *name,
|
|
|
|
const unsigned char *uuid)
|
2008-12-04 21:09:20 +00:00
|
|
|
{
|
|
|
|
virDomainEventPtr event;
|
|
|
|
|
2010-01-13 18:11:33 +00:00
|
|
|
if (VIR_ALLOC(event) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-12-04 21:09:20 +00:00
|
|
|
return NULL;
|
2010-01-13 18:11:33 +00:00
|
|
|
}
|
2008-12-04 21:09:20 +00:00
|
|
|
|
2010-03-18 14:06:09 +00:00
|
|
|
event->eventID = eventID;
|
|
|
|
if (!(event->dom.name = strdup(name))) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-12-04 21:09:20 +00:00
|
|
|
VIR_FREE(event);
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-03-18 14:06:09 +00:00
|
|
|
event->dom.id = id;
|
|
|
|
memcpy(event->dom.uuid, uuid, VIR_UUID_BUFLEN);
|
|
|
|
|
|
|
|
return event;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainEventPtr virDomainEventNew(int id, const char *name,
|
|
|
|
const unsigned char *uuid,
|
|
|
|
int type, int detail)
|
|
|
|
{
|
|
|
|
virDomainEventPtr event = virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_LIFECYCLE,
|
|
|
|
id, name, uuid);
|
|
|
|
|
|
|
|
if (event) {
|
|
|
|
event->data.lifecycle.type = type;
|
|
|
|
event->data.lifecycle.detail = detail;
|
|
|
|
}
|
2008-12-04 21:09:20 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2011-04-25 11:35:23 +00:00
|
|
|
virDomainEventPtr virDomainEventRebootNew(int id, const char *name,
|
|
|
|
const unsigned char *uuid)
|
|
|
|
{
|
|
|
|
return virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_REBOOT,
|
|
|
|
id, name, uuid);
|
|
|
|
}
|
|
|
|
|
2010-03-18 15:25:38 +00:00
|
|
|
virDomainEventPtr virDomainEventRebootNewFromDom(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_REBOOT,
|
|
|
|
dom->id, dom->name, dom->uuid);
|
|
|
|
}
|
2011-04-25 11:35:23 +00:00
|
|
|
|
2010-03-18 15:25:38 +00:00
|
|
|
virDomainEventPtr virDomainEventRebootNewFromObj(virDomainObjPtr obj)
|
|
|
|
{
|
|
|
|
return virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_REBOOT,
|
|
|
|
obj->def->id, obj->def->name, obj->def->uuid);
|
|
|
|
}
|
|
|
|
|
2010-03-18 18:28:15 +00:00
|
|
|
virDomainEventPtr virDomainEventRTCChangeNewFromDom(virDomainPtr dom,
|
|
|
|
long long offset)
|
|
|
|
{
|
|
|
|
virDomainEventPtr ev =
|
|
|
|
virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_RTC_CHANGE,
|
|
|
|
dom->id, dom->name, dom->uuid);
|
|
|
|
|
|
|
|
if (ev)
|
|
|
|
ev->data.rtcChange.offset = offset;
|
|
|
|
|
|
|
|
return ev;
|
|
|
|
}
|
|
|
|
virDomainEventPtr virDomainEventRTCChangeNewFromObj(virDomainObjPtr obj,
|
|
|
|
long long offset)
|
|
|
|
{
|
|
|
|
virDomainEventPtr ev =
|
|
|
|
virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_RTC_CHANGE,
|
|
|
|
obj->def->id, obj->def->name, obj->def->uuid);
|
|
|
|
|
|
|
|
if (ev)
|
|
|
|
ev->data.rtcChange.offset = offset;
|
|
|
|
|
|
|
|
return ev;
|
|
|
|
}
|
|
|
|
|
Add support for an explicit watchdog event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_WATCHDOG
This event includes the action that is about to be taken
as a result of the watchdog triggering
typedef enum {
VIR_DOMAIN_EVENT_WATCHDOG_NONE = 0,
VIR_DOMAIN_EVENT_WATCHDOG_PAUSE,
VIR_DOMAIN_EVENT_WATCHDOG_RESET,
VIR_DOMAIN_EVENT_WATCHDOG_POWEROFF,
VIR_DOMAIN_EVENT_WATCHDOG_SHUTDOWN,
VIR_DOMAIN_EVENT_WATCHDOG_DEBUG,
} virDomainEventWatchdogAction;
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventWatchdogCallback)(virConnectPtr conn,
virDomainPtr dom,
int action,
void *opaque);
* daemon/remote.c: Dispatch watchdog events to client
* examples/domain-events/events-c/event-test.c: Watch for
watchdog events
* include/libvirt/libvirt.h.in: Define new watchdg event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle watchdog events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for watchdogs and emit a libvirt watchdog event
* src/remote/remote_driver.c: Receive and dispatch watchdog
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
watchdog events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for WATCHDOG event
from QEMU monitor
2010-03-18 19:07:48 +00:00
|
|
|
virDomainEventPtr virDomainEventWatchdogNewFromDom(virDomainPtr dom,
|
|
|
|
int action)
|
|
|
|
{
|
|
|
|
virDomainEventPtr ev =
|
|
|
|
virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_WATCHDOG,
|
|
|
|
dom->id, dom->name, dom->uuid);
|
|
|
|
|
|
|
|
if (ev)
|
|
|
|
ev->data.watchdog.action = action;
|
|
|
|
|
|
|
|
return ev;
|
|
|
|
}
|
|
|
|
virDomainEventPtr virDomainEventWatchdogNewFromObj(virDomainObjPtr obj,
|
|
|
|
int action)
|
|
|
|
{
|
|
|
|
virDomainEventPtr ev =
|
|
|
|
virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_WATCHDOG,
|
|
|
|
obj->def->id, obj->def->name, obj->def->uuid);
|
|
|
|
|
|
|
|
if (ev)
|
|
|
|
ev->data.watchdog.action = action;
|
|
|
|
|
|
|
|
return ev;
|
|
|
|
}
|
|
|
|
|
Add support for another explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON
This event is the same as the previous VIR_DOMAIN_ID_IO_ERROR
event, but also includes a string describing the cause of
the event.
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorReasonCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
const char *reason,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
static virDomainEventPtr virDomainEventIOErrorNewFromDomImpl(int event,
|
|
|
|
virDomainPtr dom,
|
|
|
|
const char *srcPath,
|
|
|
|
const char *devAlias,
|
|
|
|
int action,
|
|
|
|
const char *reason)
|
Add support for an explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR
This event includes the action that is about to be taken
as a result of the watchdog triggering
typedef enum {
VIR_DOMAIN_EVENT_IO_ERROR_NONE = 0,
VIR_DOMAIN_EVENT_IO_ERROR_PAUSE,
VIR_DOMAIN_EVENT_IO_ERROR_REPORT,
} virDomainEventIOErrorAction;
In addition it has the source path of the disk that had the
error and its unique device alias. It does not include the
target device name (/dev/sda), since this would preclude
triggering IO errors from other file backed devices (eg
serial ports connected to a file)
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
{
|
|
|
|
virDomainEventPtr ev =
|
Add support for another explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON
This event is the same as the previous VIR_DOMAIN_ID_IO_ERROR
event, but also includes a string describing the cause of
the event.
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorReasonCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
const char *reason,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
virDomainEventNewInternal(event,
|
Add support for an explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR
This event includes the action that is about to be taken
as a result of the watchdog triggering
typedef enum {
VIR_DOMAIN_EVENT_IO_ERROR_NONE = 0,
VIR_DOMAIN_EVENT_IO_ERROR_PAUSE,
VIR_DOMAIN_EVENT_IO_ERROR_REPORT,
} virDomainEventIOErrorAction;
In addition it has the source path of the disk that had the
error and its unique device alias. It does not include the
target device name (/dev/sda), since this would preclude
triggering IO errors from other file backed devices (eg
serial ports connected to a file)
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
dom->id, dom->name, dom->uuid);
|
|
|
|
|
|
|
|
if (ev) {
|
|
|
|
ev->data.ioError.action = action;
|
|
|
|
if (!(ev->data.ioError.srcPath = strdup(srcPath)) ||
|
Add support for another explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON
This event is the same as the previous VIR_DOMAIN_ID_IO_ERROR
event, but also includes a string describing the cause of
the event.
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorReasonCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
const char *reason,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
!(ev->data.ioError.devAlias = strdup(devAlias)) ||
|
|
|
|
(reason && !(ev->data.ioError.reason = strdup(reason)))) {
|
Add support for an explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR
This event includes the action that is about to be taken
as a result of the watchdog triggering
typedef enum {
VIR_DOMAIN_EVENT_IO_ERROR_NONE = 0,
VIR_DOMAIN_EVENT_IO_ERROR_PAUSE,
VIR_DOMAIN_EVENT_IO_ERROR_REPORT,
} virDomainEventIOErrorAction;
In addition it has the source path of the disk that had the
error and its unique device alias. It does not include the
target device name (/dev/sda), since this would preclude
triggering IO errors from other file backed devices (eg
serial ports connected to a file)
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
virDomainEventFree(ev);
|
|
|
|
ev = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ev;
|
|
|
|
}
|
Add support for another explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON
This event is the same as the previous VIR_DOMAIN_ID_IO_ERROR
event, but also includes a string describing the cause of
the event.
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorReasonCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
const char *reason,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
|
|
|
|
static virDomainEventPtr virDomainEventIOErrorNewFromObjImpl(int event,
|
|
|
|
virDomainObjPtr obj,
|
|
|
|
const char *srcPath,
|
|
|
|
const char *devAlias,
|
|
|
|
int action,
|
|
|
|
const char *reason)
|
Add support for an explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR
This event includes the action that is about to be taken
as a result of the watchdog triggering
typedef enum {
VIR_DOMAIN_EVENT_IO_ERROR_NONE = 0,
VIR_DOMAIN_EVENT_IO_ERROR_PAUSE,
VIR_DOMAIN_EVENT_IO_ERROR_REPORT,
} virDomainEventIOErrorAction;
In addition it has the source path of the disk that had the
error and its unique device alias. It does not include the
target device name (/dev/sda), since this would preclude
triggering IO errors from other file backed devices (eg
serial ports connected to a file)
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
{
|
|
|
|
virDomainEventPtr ev =
|
Add support for another explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON
This event is the same as the previous VIR_DOMAIN_ID_IO_ERROR
event, but also includes a string describing the cause of
the event.
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorReasonCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
const char *reason,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
virDomainEventNewInternal(event,
|
Add support for an explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR
This event includes the action that is about to be taken
as a result of the watchdog triggering
typedef enum {
VIR_DOMAIN_EVENT_IO_ERROR_NONE = 0,
VIR_DOMAIN_EVENT_IO_ERROR_PAUSE,
VIR_DOMAIN_EVENT_IO_ERROR_REPORT,
} virDomainEventIOErrorAction;
In addition it has the source path of the disk that had the
error and its unique device alias. It does not include the
target device name (/dev/sda), since this would preclude
triggering IO errors from other file backed devices (eg
serial ports connected to a file)
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
obj->def->id, obj->def->name, obj->def->uuid);
|
|
|
|
|
|
|
|
if (ev) {
|
2010-04-08 15:01:00 +00:00
|
|
|
ev->data.ioError.action = action;
|
Add support for an explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR
This event includes the action that is about to be taken
as a result of the watchdog triggering
typedef enum {
VIR_DOMAIN_EVENT_IO_ERROR_NONE = 0,
VIR_DOMAIN_EVENT_IO_ERROR_PAUSE,
VIR_DOMAIN_EVENT_IO_ERROR_REPORT,
} virDomainEventIOErrorAction;
In addition it has the source path of the disk that had the
error and its unique device alias. It does not include the
target device name (/dev/sda), since this would preclude
triggering IO errors from other file backed devices (eg
serial ports connected to a file)
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
if (!(ev->data.ioError.srcPath = strdup(srcPath)) ||
|
Add support for another explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON
This event is the same as the previous VIR_DOMAIN_ID_IO_ERROR
event, but also includes a string describing the cause of
the event.
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorReasonCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
const char *reason,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
!(ev->data.ioError.devAlias = strdup(devAlias)) ||
|
2010-05-11 14:34:38 +00:00
|
|
|
(reason && !(ev->data.ioError.reason = strdup(reason)))) {
|
Add support for an explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR
This event includes the action that is about to be taken
as a result of the watchdog triggering
typedef enum {
VIR_DOMAIN_EVENT_IO_ERROR_NONE = 0,
VIR_DOMAIN_EVENT_IO_ERROR_PAUSE,
VIR_DOMAIN_EVENT_IO_ERROR_REPORT,
} virDomainEventIOErrorAction;
In addition it has the source path of the disk that had the
error and its unique device alias. It does not include the
target device name (/dev/sda), since this would preclude
triggering IO errors from other file backed devices (eg
serial ports connected to a file)
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
virDomainEventFree(ev);
|
|
|
|
ev = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ev;
|
|
|
|
}
|
|
|
|
|
Add support for another explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON
This event is the same as the previous VIR_DOMAIN_ID_IO_ERROR
event, but also includes a string describing the cause of
the event.
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorReasonCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
const char *reason,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
virDomainEventPtr virDomainEventIOErrorNewFromDom(virDomainPtr dom,
|
|
|
|
const char *srcPath,
|
|
|
|
const char *devAlias,
|
|
|
|
int action)
|
|
|
|
{
|
|
|
|
return virDomainEventIOErrorNewFromDomImpl(VIR_DOMAIN_EVENT_ID_IO_ERROR,
|
|
|
|
dom, srcPath, devAlias,
|
|
|
|
action, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainEventPtr virDomainEventIOErrorNewFromObj(virDomainObjPtr obj,
|
|
|
|
const char *srcPath,
|
|
|
|
const char *devAlias,
|
|
|
|
int action)
|
|
|
|
{
|
|
|
|
return virDomainEventIOErrorNewFromObjImpl(VIR_DOMAIN_EVENT_ID_IO_ERROR,
|
|
|
|
obj, srcPath, devAlias,
|
|
|
|
action, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainEventPtr virDomainEventIOErrorReasonNewFromDom(virDomainPtr dom,
|
|
|
|
const char *srcPath,
|
|
|
|
const char *devAlias,
|
|
|
|
int action,
|
|
|
|
const char *reason)
|
|
|
|
{
|
|
|
|
return virDomainEventIOErrorNewFromDomImpl(VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON,
|
|
|
|
dom, srcPath, devAlias,
|
|
|
|
action, reason);
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainEventPtr virDomainEventIOErrorReasonNewFromObj(virDomainObjPtr obj,
|
|
|
|
const char *srcPath,
|
|
|
|
const char *devAlias,
|
|
|
|
int action,
|
|
|
|
const char *reason)
|
|
|
|
{
|
|
|
|
return virDomainEventIOErrorNewFromObjImpl(VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON,
|
|
|
|
obj, srcPath, devAlias,
|
|
|
|
action, reason);
|
|
|
|
}
|
|
|
|
|
Add domain events for graphics network clients
This introduces a new event type
VIR_DOMAIN_EVENT_ID_GRAPHICS
The same event can be emitted in 3 scenarios
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_CONNECT = 0,
VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE,
VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT,
} virDomainEventGraphicsPhase;
Connect/disconnect are triggered at socket accept/close.
The initialize phase is immediately after the protocol
setup and authentication has completed. ie when the
client is authorized and about to start interacting with
the graphical desktop
This event comes with *a lot* of potential information
- IP address, port & address family of client
- IP address, port & address family of server
- Authentication scheme (arbitrary string)
- Authenticated subject identity. A subject may have
multiple identities with some authentication schemes.
For example, vencrypt+sasl results in a x509dname
and saslUsername identities.
This results in a very complicated callback :-(
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4,
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6,
} virDomainEventGraphicsAddressType;
struct _virDomainEventGraphicsAddress {
int family;
const char *node;
const char *service;
};
typedef struct _virDomainEventGraphicsAddress virDomainEventGraphicsAddress;
typedef virDomainEventGraphicsAddress *virDomainEventGraphicsAddressPtr;
struct _virDomainEventGraphicsSubject {
int nidentity;
struct {
const char *type;
const char *name;
} *identities;
};
typedef struct _virDomainEventGraphicsSubject virDomainEventGraphicsSubject;
typedef virDomainEventGraphicsSubject *virDomainEventGraphicsSubjectPtr;
typedef void (*virConnectDomainEventGraphicsCallback)(virConnectPtr conn,
virDomainPtr dom,
int phase,
virDomainEventGraphicsAddressPtr local,
virDomainEventGraphicsAddressPtr remote,
const char *authScheme,
virDomainEventGraphicsSubjectPtr subject,
void *opaque);
The wire protocol is similarly complex
struct remote_domain_event_graphics_address {
int family;
remote_nonnull_string node;
remote_nonnull_string service;
};
const REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX = 20;
struct remote_domain_event_graphics_identity {
remote_nonnull_string type;
remote_nonnull_string name;
};
struct remote_domain_event_graphics_msg {
remote_nonnull_domain dom;
int phase;
remote_domain_event_graphics_address local;
remote_domain_event_graphics_address remote;
remote_nonnull_string authScheme;
remote_domain_event_graphics_identity subject<REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX>;
};
This is currently implemented in QEMU for the VNC graphics
protocol, but designed to be usable with SPICE graphics in
the future too.
* daemon/remote.c: Dispatch graphics events to client
* examples/domain-events/events-c/event-test.c: Watch for
graphics events
* include/libvirt/libvirt.h.in: Define new graphics event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle graphics events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for VNC events and emit a libvirt graphics event
* src/remote/remote_driver.c: Receive and dispatch graphics
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
graphics events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for VNC_CONNECTED,
VNC_INITIALIZED & VNC_DISCONNETED events from QEMU monitor
2010-03-19 13:27:45 +00:00
|
|
|
|
|
|
|
virDomainEventPtr virDomainEventGraphicsNewFromDom(virDomainPtr dom,
|
|
|
|
int phase,
|
|
|
|
virDomainEventGraphicsAddressPtr local,
|
|
|
|
virDomainEventGraphicsAddressPtr remote,
|
|
|
|
const char *authScheme,
|
|
|
|
virDomainEventGraphicsSubjectPtr subject)
|
|
|
|
{
|
|
|
|
virDomainEventPtr ev =
|
|
|
|
virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_GRAPHICS,
|
|
|
|
dom->id, dom->name, dom->uuid);
|
|
|
|
|
|
|
|
if (ev) {
|
|
|
|
ev->data.graphics.phase = phase;
|
|
|
|
if (!(ev->data.graphics.authScheme = strdup(authScheme))) {
|
|
|
|
virDomainEventFree(ev);
|
2010-03-29 15:43:01 +00:00
|
|
|
return NULL;
|
Add domain events for graphics network clients
This introduces a new event type
VIR_DOMAIN_EVENT_ID_GRAPHICS
The same event can be emitted in 3 scenarios
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_CONNECT = 0,
VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE,
VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT,
} virDomainEventGraphicsPhase;
Connect/disconnect are triggered at socket accept/close.
The initialize phase is immediately after the protocol
setup and authentication has completed. ie when the
client is authorized and about to start interacting with
the graphical desktop
This event comes with *a lot* of potential information
- IP address, port & address family of client
- IP address, port & address family of server
- Authentication scheme (arbitrary string)
- Authenticated subject identity. A subject may have
multiple identities with some authentication schemes.
For example, vencrypt+sasl results in a x509dname
and saslUsername identities.
This results in a very complicated callback :-(
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4,
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6,
} virDomainEventGraphicsAddressType;
struct _virDomainEventGraphicsAddress {
int family;
const char *node;
const char *service;
};
typedef struct _virDomainEventGraphicsAddress virDomainEventGraphicsAddress;
typedef virDomainEventGraphicsAddress *virDomainEventGraphicsAddressPtr;
struct _virDomainEventGraphicsSubject {
int nidentity;
struct {
const char *type;
const char *name;
} *identities;
};
typedef struct _virDomainEventGraphicsSubject virDomainEventGraphicsSubject;
typedef virDomainEventGraphicsSubject *virDomainEventGraphicsSubjectPtr;
typedef void (*virConnectDomainEventGraphicsCallback)(virConnectPtr conn,
virDomainPtr dom,
int phase,
virDomainEventGraphicsAddressPtr local,
virDomainEventGraphicsAddressPtr remote,
const char *authScheme,
virDomainEventGraphicsSubjectPtr subject,
void *opaque);
The wire protocol is similarly complex
struct remote_domain_event_graphics_address {
int family;
remote_nonnull_string node;
remote_nonnull_string service;
};
const REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX = 20;
struct remote_domain_event_graphics_identity {
remote_nonnull_string type;
remote_nonnull_string name;
};
struct remote_domain_event_graphics_msg {
remote_nonnull_domain dom;
int phase;
remote_domain_event_graphics_address local;
remote_domain_event_graphics_address remote;
remote_nonnull_string authScheme;
remote_domain_event_graphics_identity subject<REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX>;
};
This is currently implemented in QEMU for the VNC graphics
protocol, but designed to be usable with SPICE graphics in
the future too.
* daemon/remote.c: Dispatch graphics events to client
* examples/domain-events/events-c/event-test.c: Watch for
graphics events
* include/libvirt/libvirt.h.in: Define new graphics event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle graphics events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for VNC events and emit a libvirt graphics event
* src/remote/remote_driver.c: Receive and dispatch graphics
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
graphics events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for VNC_CONNECTED,
VNC_INITIALIZED & VNC_DISCONNETED events from QEMU monitor
2010-03-19 13:27:45 +00:00
|
|
|
}
|
|
|
|
ev->data.graphics.local = local;
|
|
|
|
ev->data.graphics.remote = remote;
|
|
|
|
ev->data.graphics.subject = subject;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ev;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainEventPtr virDomainEventGraphicsNewFromObj(virDomainObjPtr obj,
|
|
|
|
int phase,
|
|
|
|
virDomainEventGraphicsAddressPtr local,
|
|
|
|
virDomainEventGraphicsAddressPtr remote,
|
|
|
|
const char *authScheme,
|
|
|
|
virDomainEventGraphicsSubjectPtr subject)
|
|
|
|
{
|
|
|
|
virDomainEventPtr ev =
|
|
|
|
virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_GRAPHICS,
|
|
|
|
obj->def->id, obj->def->name, obj->def->uuid);
|
|
|
|
|
|
|
|
if (ev) {
|
|
|
|
ev->data.graphics.phase = phase;
|
|
|
|
if (!(ev->data.graphics.authScheme = strdup(authScheme))) {
|
|
|
|
virDomainEventFree(ev);
|
2010-03-29 15:43:01 +00:00
|
|
|
return NULL;
|
Add domain events for graphics network clients
This introduces a new event type
VIR_DOMAIN_EVENT_ID_GRAPHICS
The same event can be emitted in 3 scenarios
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_CONNECT = 0,
VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE,
VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT,
} virDomainEventGraphicsPhase;
Connect/disconnect are triggered at socket accept/close.
The initialize phase is immediately after the protocol
setup and authentication has completed. ie when the
client is authorized and about to start interacting with
the graphical desktop
This event comes with *a lot* of potential information
- IP address, port & address family of client
- IP address, port & address family of server
- Authentication scheme (arbitrary string)
- Authenticated subject identity. A subject may have
multiple identities with some authentication schemes.
For example, vencrypt+sasl results in a x509dname
and saslUsername identities.
This results in a very complicated callback :-(
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4,
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6,
} virDomainEventGraphicsAddressType;
struct _virDomainEventGraphicsAddress {
int family;
const char *node;
const char *service;
};
typedef struct _virDomainEventGraphicsAddress virDomainEventGraphicsAddress;
typedef virDomainEventGraphicsAddress *virDomainEventGraphicsAddressPtr;
struct _virDomainEventGraphicsSubject {
int nidentity;
struct {
const char *type;
const char *name;
} *identities;
};
typedef struct _virDomainEventGraphicsSubject virDomainEventGraphicsSubject;
typedef virDomainEventGraphicsSubject *virDomainEventGraphicsSubjectPtr;
typedef void (*virConnectDomainEventGraphicsCallback)(virConnectPtr conn,
virDomainPtr dom,
int phase,
virDomainEventGraphicsAddressPtr local,
virDomainEventGraphicsAddressPtr remote,
const char *authScheme,
virDomainEventGraphicsSubjectPtr subject,
void *opaque);
The wire protocol is similarly complex
struct remote_domain_event_graphics_address {
int family;
remote_nonnull_string node;
remote_nonnull_string service;
};
const REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX = 20;
struct remote_domain_event_graphics_identity {
remote_nonnull_string type;
remote_nonnull_string name;
};
struct remote_domain_event_graphics_msg {
remote_nonnull_domain dom;
int phase;
remote_domain_event_graphics_address local;
remote_domain_event_graphics_address remote;
remote_nonnull_string authScheme;
remote_domain_event_graphics_identity subject<REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX>;
};
This is currently implemented in QEMU for the VNC graphics
protocol, but designed to be usable with SPICE graphics in
the future too.
* daemon/remote.c: Dispatch graphics events to client
* examples/domain-events/events-c/event-test.c: Watch for
graphics events
* include/libvirt/libvirt.h.in: Define new graphics event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle graphics events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for VNC events and emit a libvirt graphics event
* src/remote/remote_driver.c: Receive and dispatch graphics
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
graphics events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for VNC_CONNECTED,
VNC_INITIALIZED & VNC_DISCONNETED events from QEMU monitor
2010-03-19 13:27:45 +00:00
|
|
|
}
|
|
|
|
ev->data.graphics.local = local;
|
|
|
|
ev->data.graphics.remote = remote;
|
|
|
|
ev->data.graphics.subject = subject;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ev;
|
|
|
|
}
|
|
|
|
|
2011-07-22 05:57:42 +00:00
|
|
|
static virDomainEventPtr
|
|
|
|
virDomainEventBlockJobNew(int id, const char *name, unsigned char *uuid,
|
|
|
|
const char *path, int type, int status)
|
|
|
|
{
|
|
|
|
virDomainEventPtr ev =
|
|
|
|
virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_BLOCK_JOB,
|
|
|
|
id, name, uuid);
|
|
|
|
|
|
|
|
if (ev) {
|
|
|
|
if (!(ev->data.blockJob.path = strdup(path))) {
|
|
|
|
virReportOOMError();
|
|
|
|
virDomainEventFree(ev);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
ev->data.blockJob.type = type;
|
|
|
|
ev->data.blockJob.status = status;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ev;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainEventPtr virDomainEventBlockJobNewFromObj(virDomainObjPtr obj,
|
|
|
|
const char *path,
|
|
|
|
int type,
|
|
|
|
int status)
|
|
|
|
{
|
|
|
|
return virDomainEventBlockJobNew(obj->def->id, obj->def->name,
|
|
|
|
obj->def->uuid, path, type, status);
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainEventPtr virDomainEventBlockJobNewFromDom(virDomainPtr dom,
|
|
|
|
const char *path,
|
|
|
|
int type,
|
|
|
|
int status)
|
|
|
|
{
|
|
|
|
return virDomainEventBlockJobNew(dom->id, dom->name, dom->uuid,
|
|
|
|
path, type, status);
|
|
|
|
}
|
Add domain events for graphics network clients
This introduces a new event type
VIR_DOMAIN_EVENT_ID_GRAPHICS
The same event can be emitted in 3 scenarios
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_CONNECT = 0,
VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE,
VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT,
} virDomainEventGraphicsPhase;
Connect/disconnect are triggered at socket accept/close.
The initialize phase is immediately after the protocol
setup and authentication has completed. ie when the
client is authorized and about to start interacting with
the graphical desktop
This event comes with *a lot* of potential information
- IP address, port & address family of client
- IP address, port & address family of server
- Authentication scheme (arbitrary string)
- Authenticated subject identity. A subject may have
multiple identities with some authentication schemes.
For example, vencrypt+sasl results in a x509dname
and saslUsername identities.
This results in a very complicated callback :-(
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4,
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6,
} virDomainEventGraphicsAddressType;
struct _virDomainEventGraphicsAddress {
int family;
const char *node;
const char *service;
};
typedef struct _virDomainEventGraphicsAddress virDomainEventGraphicsAddress;
typedef virDomainEventGraphicsAddress *virDomainEventGraphicsAddressPtr;
struct _virDomainEventGraphicsSubject {
int nidentity;
struct {
const char *type;
const char *name;
} *identities;
};
typedef struct _virDomainEventGraphicsSubject virDomainEventGraphicsSubject;
typedef virDomainEventGraphicsSubject *virDomainEventGraphicsSubjectPtr;
typedef void (*virConnectDomainEventGraphicsCallback)(virConnectPtr conn,
virDomainPtr dom,
int phase,
virDomainEventGraphicsAddressPtr local,
virDomainEventGraphicsAddressPtr remote,
const char *authScheme,
virDomainEventGraphicsSubjectPtr subject,
void *opaque);
The wire protocol is similarly complex
struct remote_domain_event_graphics_address {
int family;
remote_nonnull_string node;
remote_nonnull_string service;
};
const REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX = 20;
struct remote_domain_event_graphics_identity {
remote_nonnull_string type;
remote_nonnull_string name;
};
struct remote_domain_event_graphics_msg {
remote_nonnull_domain dom;
int phase;
remote_domain_event_graphics_address local;
remote_domain_event_graphics_address remote;
remote_nonnull_string authScheme;
remote_domain_event_graphics_identity subject<REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX>;
};
This is currently implemented in QEMU for the VNC graphics
protocol, but designed to be usable with SPICE graphics in
the future too.
* daemon/remote.c: Dispatch graphics events to client
* examples/domain-events/events-c/event-test.c: Watch for
graphics events
* include/libvirt/libvirt.h.in: Define new graphics event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle graphics events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for VNC events and emit a libvirt graphics event
* src/remote/remote_driver.c: Receive and dispatch graphics
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
graphics events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for VNC_CONNECTED,
VNC_INITIALIZED & VNC_DISCONNETED events from QEMU monitor
2010-03-19 13:27:45 +00:00
|
|
|
|
2011-05-29 12:21:53 +00:00
|
|
|
virDomainEventPtr virDomainEventControlErrorNewFromDom(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
virDomainEventPtr ev =
|
|
|
|
virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_CONTROL_ERROR,
|
|
|
|
dom->id, dom->name, dom->uuid);
|
|
|
|
return ev;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
virDomainEventPtr virDomainEventControlErrorNewFromObj(virDomainObjPtr obj)
|
|
|
|
{
|
|
|
|
virDomainEventPtr ev =
|
|
|
|
virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_CONTROL_ERROR,
|
|
|
|
obj->def->id, obj->def->name, obj->def->uuid);
|
|
|
|
return ev;
|
|
|
|
}
|
|
|
|
|
2011-10-18 14:15:42 +00:00
|
|
|
static virDomainEventPtr
|
|
|
|
virDomainEventDiskChangeNew(int id, const char *name,
|
|
|
|
unsigned char *uuid,
|
|
|
|
const char *oldSrcPath,
|
|
|
|
const char *newSrcPath,
|
|
|
|
const char *devAlias, int reason)
|
|
|
|
{
|
|
|
|
virDomainEventPtr ev =
|
|
|
|
virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_DISK_CHANGE,
|
|
|
|
id, name, uuid);
|
|
|
|
|
|
|
|
if (ev) {
|
|
|
|
if (!(ev->data.diskChange.devAlias = strdup(devAlias)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (oldSrcPath &&
|
|
|
|
!(ev->data.diskChange.oldSrcPath = strdup(oldSrcPath)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (newSrcPath &&
|
|
|
|
!(ev->data.diskChange.newSrcPath = strdup(newSrcPath)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
ev->data.diskChange.reason = reason;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ev;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virReportOOMError();
|
|
|
|
virDomainEventFree(ev);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainEventPtr virDomainEventDiskChangeNewFromObj(virDomainObjPtr obj,
|
|
|
|
const char *oldSrcPath,
|
|
|
|
const char *newSrcPath,
|
|
|
|
const char *devAlias,
|
|
|
|
int reason)
|
|
|
|
{
|
|
|
|
return virDomainEventDiskChangeNew(obj->def->id, obj->def->name,
|
|
|
|
obj->def->uuid, oldSrcPath,
|
|
|
|
newSrcPath, devAlias, reason);
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainEventPtr virDomainEventDiskChangeNewFromDom(virDomainPtr dom,
|
|
|
|
const char *oldSrcPath,
|
|
|
|
const char *newSrcPath,
|
|
|
|
const char *devAlias,
|
|
|
|
int reason)
|
|
|
|
{
|
|
|
|
return virDomainEventDiskChangeNew(dom->id, dom->name, dom->uuid,
|
|
|
|
oldSrcPath, newSrcPath,
|
|
|
|
devAlias, reason);
|
|
|
|
}
|
2011-05-29 12:21:53 +00:00
|
|
|
|
2012-03-23 13:44:50 +00:00
|
|
|
static virDomainEventPtr
|
|
|
|
virDomainEventTrayChangeNew(int id, const char *name,
|
|
|
|
unsigned char *uuid,
|
|
|
|
const char *devAlias,
|
|
|
|
int reason)
|
|
|
|
{
|
|
|
|
virDomainEventPtr ev =
|
|
|
|
virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_TRAY_CHANGE,
|
|
|
|
id, name, uuid);
|
|
|
|
|
|
|
|
if (ev) {
|
|
|
|
if (!(ev->data.trayChange.devAlias = strdup(devAlias)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
ev->data.trayChange.reason = reason;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ev;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virReportOOMError();
|
|
|
|
virDomainEventFree(ev);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainEventPtr virDomainEventTrayChangeNewFromObj(virDomainObjPtr obj,
|
|
|
|
const char *devAlias,
|
|
|
|
int reason)
|
|
|
|
{
|
|
|
|
return virDomainEventTrayChangeNew(obj->def->id,
|
|
|
|
obj->def->name,
|
|
|
|
obj->def->uuid,
|
|
|
|
devAlias,
|
|
|
|
reason);
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainEventPtr virDomainEventTrayChangeNewFromDom(virDomainPtr dom,
|
|
|
|
const char *devAlias,
|
|
|
|
int reason)
|
|
|
|
{
|
|
|
|
return virDomainEventTrayChangeNew(dom->id, dom->name, dom->uuid,
|
|
|
|
devAlias, reason);
|
|
|
|
}
|
|
|
|
|
2012-03-23 14:43:14 +00:00
|
|
|
static virDomainEventPtr
|
|
|
|
virDomainEventPMWakeupNew(int id, const char *name,
|
|
|
|
unsigned char *uuid)
|
|
|
|
{
|
|
|
|
virDomainEventPtr ev =
|
|
|
|
virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_PMWAKEUP,
|
|
|
|
id, name, uuid);
|
|
|
|
|
|
|
|
return ev;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainEventPtr
|
|
|
|
virDomainEventPMWakeupNewFromObj(virDomainObjPtr obj)
|
|
|
|
{
|
|
|
|
return virDomainEventPMWakeupNew(obj->def->id,
|
|
|
|
obj->def->name,
|
|
|
|
obj->def->uuid);
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainEventPtr
|
|
|
|
virDomainEventPMWakeupNewFromDom(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return virDomainEventPMWakeupNew(dom->id, dom->name, dom->uuid);
|
|
|
|
}
|
2008-11-04 23:33:57 +00:00
|
|
|
|
2012-03-23 14:50:36 +00:00
|
|
|
static virDomainEventPtr
|
|
|
|
virDomainEventPMSuspendNew(int id, const char *name,
|
|
|
|
unsigned char *uuid)
|
|
|
|
{
|
|
|
|
virDomainEventPtr ev =
|
|
|
|
virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_PMSUSPEND,
|
|
|
|
id, name, uuid);
|
|
|
|
|
|
|
|
return ev;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainEventPtr
|
|
|
|
virDomainEventPMSuspendNewFromObj(virDomainObjPtr obj)
|
|
|
|
{
|
|
|
|
return virDomainEventPMSuspendNew(obj->def->id,
|
|
|
|
obj->def->name,
|
|
|
|
obj->def->uuid);
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainEventPtr
|
|
|
|
virDomainEventPMSuspendNewFromDom(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return virDomainEventPMSuspendNew(dom->id, dom->name, dom->uuid);
|
|
|
|
}
|
|
|
|
|
2008-11-04 23:33:57 +00:00
|
|
|
/**
|
2008-12-04 21:09:20 +00:00
|
|
|
* virDomainEventQueuePush:
|
2008-11-04 23:33:57 +00:00
|
|
|
* @evtQueue: the dom event queue
|
|
|
|
* @event: the event to add
|
|
|
|
*
|
2011-12-04 00:06:07 +00:00
|
|
|
* Internal function to push onto the back of a virDomainEventQueue
|
2008-11-04 23:33:57 +00:00
|
|
|
*
|
|
|
|
* Returns: 0 on success, -1 on failure
|
|
|
|
*/
|
2011-12-13 11:41:01 +00:00
|
|
|
static int
|
2008-12-04 21:09:20 +00:00
|
|
|
virDomainEventQueuePush(virDomainEventQueuePtr evtQueue,
|
|
|
|
virDomainEventPtr event)
|
2008-11-04 23:33:57 +00:00
|
|
|
{
|
2008-12-04 21:09:20 +00:00
|
|
|
if (!evtQueue) {
|
2008-11-04 23:33:57 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make space on queue */
|
|
|
|
if (VIR_REALLOC_N(evtQueue->events,
|
|
|
|
evtQueue->count + 1) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-11-04 23:33:57 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-12-04 21:09:20 +00:00
|
|
|
evtQueue->events[evtQueue->count] = event;
|
2008-11-04 23:33:57 +00:00
|
|
|
evtQueue->count++;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-12-04 21:09:20 +00:00
|
|
|
|
Hide use of timers for domain event dispatch
Currently all drivers using domain events need to provide a callback
for handling a timer to dispatch events in a clean stack. There is
no technical reason for dispatch to go via driver specific code. It
could trivially be dispatched directly from the domain event code,
thus removing tedious boilerplate code from all drivers
Also fix the libxl & xen drivers to pass 'true' when creating the
virDomainEventState, since they run inside the daemon & thus always
expect events to be present.
* src/conf/domain_event.c, src/conf/domain_event.h: Internalize
dispatch of events from timer callback
* src/libxl/libxl_driver.c, src/lxc/lxc_driver.c,
src/qemu/qemu_domain.c, src/qemu/qemu_driver.c,
src/remote/remote_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c: Remove all timer dispatch functions
2011-12-13 13:46:28 +00:00
|
|
|
typedef void (*virDomainEventDispatchFunc)(virConnectPtr conn,
|
|
|
|
virDomainEventPtr event,
|
|
|
|
virConnectDomainEventGenericCallback cb,
|
|
|
|
void *cbopaque,
|
|
|
|
void *opaque);
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
virDomainEventDispatchDefaultFunc(virConnectPtr conn,
|
|
|
|
virDomainEventPtr event,
|
|
|
|
virConnectDomainEventGenericCallback cb,
|
|
|
|
void *cbopaque,
|
|
|
|
void *opaque ATTRIBUTE_UNUSED)
|
2008-12-04 21:09:20 +00:00
|
|
|
{
|
2010-03-18 14:06:09 +00:00
|
|
|
virDomainPtr dom = virGetDomain(conn, event->dom.name, event->dom.uuid);
|
|
|
|
if (!dom)
|
|
|
|
return;
|
|
|
|
dom->id = event->dom.id;
|
|
|
|
|
|
|
|
switch (event->eventID) {
|
|
|
|
case VIR_DOMAIN_EVENT_ID_LIFECYCLE:
|
|
|
|
((virConnectDomainEventCallback)cb)(conn, dom,
|
|
|
|
event->data.lifecycle.type,
|
|
|
|
event->data.lifecycle.detail,
|
|
|
|
cbopaque);
|
|
|
|
break;
|
|
|
|
|
2010-03-18 15:25:38 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_REBOOT:
|
|
|
|
(cb)(conn, dom,
|
|
|
|
cbopaque);
|
|
|
|
break;
|
|
|
|
|
2010-03-18 18:28:15 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_RTC_CHANGE:
|
|
|
|
((virConnectDomainEventRTCChangeCallback)cb)(conn, dom,
|
|
|
|
event->data.rtcChange.offset,
|
|
|
|
cbopaque);
|
|
|
|
break;
|
|
|
|
|
Add support for an explicit watchdog event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_WATCHDOG
This event includes the action that is about to be taken
as a result of the watchdog triggering
typedef enum {
VIR_DOMAIN_EVENT_WATCHDOG_NONE = 0,
VIR_DOMAIN_EVENT_WATCHDOG_PAUSE,
VIR_DOMAIN_EVENT_WATCHDOG_RESET,
VIR_DOMAIN_EVENT_WATCHDOG_POWEROFF,
VIR_DOMAIN_EVENT_WATCHDOG_SHUTDOWN,
VIR_DOMAIN_EVENT_WATCHDOG_DEBUG,
} virDomainEventWatchdogAction;
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventWatchdogCallback)(virConnectPtr conn,
virDomainPtr dom,
int action,
void *opaque);
* daemon/remote.c: Dispatch watchdog events to client
* examples/domain-events/events-c/event-test.c: Watch for
watchdog events
* include/libvirt/libvirt.h.in: Define new watchdg event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle watchdog events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for watchdogs and emit a libvirt watchdog event
* src/remote/remote_driver.c: Receive and dispatch watchdog
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
watchdog events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for WATCHDOG event
from QEMU monitor
2010-03-18 19:07:48 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_WATCHDOG:
|
|
|
|
((virConnectDomainEventWatchdogCallback)cb)(conn, dom,
|
|
|
|
event->data.watchdog.action,
|
|
|
|
cbopaque);
|
|
|
|
break;
|
|
|
|
|
Add support for an explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR
This event includes the action that is about to be taken
as a result of the watchdog triggering
typedef enum {
VIR_DOMAIN_EVENT_IO_ERROR_NONE = 0,
VIR_DOMAIN_EVENT_IO_ERROR_PAUSE,
VIR_DOMAIN_EVENT_IO_ERROR_REPORT,
} virDomainEventIOErrorAction;
In addition it has the source path of the disk that had the
error and its unique device alias. It does not include the
target device name (/dev/sda), since this would preclude
triggering IO errors from other file backed devices (eg
serial ports connected to a file)
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_IO_ERROR:
|
|
|
|
((virConnectDomainEventIOErrorCallback)cb)(conn, dom,
|
|
|
|
event->data.ioError.srcPath,
|
|
|
|
event->data.ioError.devAlias,
|
|
|
|
event->data.ioError.action,
|
|
|
|
cbopaque);
|
|
|
|
break;
|
|
|
|
|
Add support for another explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON
This event is the same as the previous VIR_DOMAIN_ID_IO_ERROR
event, but also includes a string describing the cause of
the event.
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorReasonCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
const char *reason,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON:
|
|
|
|
((virConnectDomainEventIOErrorReasonCallback)cb)(conn, dom,
|
|
|
|
event->data.ioError.srcPath,
|
|
|
|
event->data.ioError.devAlias,
|
|
|
|
event->data.ioError.action,
|
|
|
|
event->data.ioError.reason,
|
|
|
|
cbopaque);
|
|
|
|
break;
|
|
|
|
|
Add domain events for graphics network clients
This introduces a new event type
VIR_DOMAIN_EVENT_ID_GRAPHICS
The same event can be emitted in 3 scenarios
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_CONNECT = 0,
VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE,
VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT,
} virDomainEventGraphicsPhase;
Connect/disconnect are triggered at socket accept/close.
The initialize phase is immediately after the protocol
setup and authentication has completed. ie when the
client is authorized and about to start interacting with
the graphical desktop
This event comes with *a lot* of potential information
- IP address, port & address family of client
- IP address, port & address family of server
- Authentication scheme (arbitrary string)
- Authenticated subject identity. A subject may have
multiple identities with some authentication schemes.
For example, vencrypt+sasl results in a x509dname
and saslUsername identities.
This results in a very complicated callback :-(
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4,
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6,
} virDomainEventGraphicsAddressType;
struct _virDomainEventGraphicsAddress {
int family;
const char *node;
const char *service;
};
typedef struct _virDomainEventGraphicsAddress virDomainEventGraphicsAddress;
typedef virDomainEventGraphicsAddress *virDomainEventGraphicsAddressPtr;
struct _virDomainEventGraphicsSubject {
int nidentity;
struct {
const char *type;
const char *name;
} *identities;
};
typedef struct _virDomainEventGraphicsSubject virDomainEventGraphicsSubject;
typedef virDomainEventGraphicsSubject *virDomainEventGraphicsSubjectPtr;
typedef void (*virConnectDomainEventGraphicsCallback)(virConnectPtr conn,
virDomainPtr dom,
int phase,
virDomainEventGraphicsAddressPtr local,
virDomainEventGraphicsAddressPtr remote,
const char *authScheme,
virDomainEventGraphicsSubjectPtr subject,
void *opaque);
The wire protocol is similarly complex
struct remote_domain_event_graphics_address {
int family;
remote_nonnull_string node;
remote_nonnull_string service;
};
const REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX = 20;
struct remote_domain_event_graphics_identity {
remote_nonnull_string type;
remote_nonnull_string name;
};
struct remote_domain_event_graphics_msg {
remote_nonnull_domain dom;
int phase;
remote_domain_event_graphics_address local;
remote_domain_event_graphics_address remote;
remote_nonnull_string authScheme;
remote_domain_event_graphics_identity subject<REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX>;
};
This is currently implemented in QEMU for the VNC graphics
protocol, but designed to be usable with SPICE graphics in
the future too.
* daemon/remote.c: Dispatch graphics events to client
* examples/domain-events/events-c/event-test.c: Watch for
graphics events
* include/libvirt/libvirt.h.in: Define new graphics event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle graphics events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for VNC events and emit a libvirt graphics event
* src/remote/remote_driver.c: Receive and dispatch graphics
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
graphics events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for VNC_CONNECTED,
VNC_INITIALIZED & VNC_DISCONNETED events from QEMU monitor
2010-03-19 13:27:45 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_GRAPHICS:
|
|
|
|
((virConnectDomainEventGraphicsCallback)cb)(conn, dom,
|
|
|
|
event->data.graphics.phase,
|
|
|
|
event->data.graphics.local,
|
|
|
|
event->data.graphics.remote,
|
|
|
|
event->data.graphics.authScheme,
|
|
|
|
event->data.graphics.subject,
|
|
|
|
cbopaque);
|
|
|
|
break;
|
|
|
|
|
2011-05-29 12:21:53 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_CONTROL_ERROR:
|
|
|
|
(cb)(conn, dom,
|
|
|
|
cbopaque);
|
|
|
|
break;
|
|
|
|
|
2011-07-22 05:57:42 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_BLOCK_JOB:
|
|
|
|
((virConnectDomainEventBlockJobCallback)cb)(conn, dom,
|
|
|
|
event->data.blockJob.path,
|
|
|
|
event->data.blockJob.type,
|
|
|
|
event->data.blockJob.status,
|
|
|
|
cbopaque);
|
|
|
|
break;
|
|
|
|
|
2011-10-18 14:15:42 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_DISK_CHANGE:
|
|
|
|
((virConnectDomainEventDiskChangeCallback)cb)(conn, dom,
|
|
|
|
event->data.diskChange.oldSrcPath,
|
|
|
|
event->data.diskChange.newSrcPath,
|
|
|
|
event->data.diskChange.devAlias,
|
|
|
|
event->data.diskChange.reason,
|
|
|
|
cbopaque);
|
|
|
|
break;
|
|
|
|
|
2012-03-23 13:44:50 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_TRAY_CHANGE:
|
|
|
|
((virConnectDomainEventTrayChangeCallback)cb)(conn, dom,
|
|
|
|
event->data.trayChange.devAlias,
|
|
|
|
event->data.trayChange.reason,
|
|
|
|
cbopaque);
|
|
|
|
break;
|
|
|
|
|
2012-03-23 14:43:14 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_PMWAKEUP:
|
|
|
|
((virConnectDomainEventPMWakeupCallback)cb)(conn, dom, 0, cbopaque);
|
|
|
|
break;
|
|
|
|
|
2012-03-23 14:50:36 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_PMSUSPEND:
|
|
|
|
((virConnectDomainEventPMSuspendCallback)cb)(conn, dom, 0, cbopaque);
|
|
|
|
break;
|
|
|
|
|
2010-03-18 14:06:09 +00:00
|
|
|
default:
|
|
|
|
VIR_WARN("Unexpected event ID %d", event->eventID);
|
|
|
|
break;
|
2008-12-04 21:09:20 +00:00
|
|
|
}
|
2010-03-18 14:06:09 +00:00
|
|
|
|
|
|
|
virDomainFree(dom);
|
2008-12-04 21:09:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-18 14:06:09 +00:00
|
|
|
static int virDomainEventDispatchMatchCallback(virDomainEventPtr event,
|
|
|
|
virDomainEventCallbackPtr cb)
|
|
|
|
{
|
|
|
|
if (!cb)
|
|
|
|
return 0;
|
|
|
|
if (cb->deleted)
|
|
|
|
return 0;
|
|
|
|
if (cb->eventID != event->eventID)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (cb->dom) {
|
2011-08-23 17:02:02 +00:00
|
|
|
/* Deliberately ignoring 'id' for matching, since that
|
2010-03-18 14:06:09 +00:00
|
|
|
* will cause problems when a domain switches between
|
|
|
|
* running & shutoff states & ignoring 'name' since
|
|
|
|
* Xen sometimes renames guests during migration, thus
|
2011-08-23 17:02:02 +00:00
|
|
|
* leaving 'uuid' as the only truly reliable ID we can use*/
|
2010-03-18 14:06:09 +00:00
|
|
|
|
|
|
|
if (memcmp(event->dom.uuid, cb->dom->uuid, VIR_UUID_BUFLEN) == 0)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Hide use of timers for domain event dispatch
Currently all drivers using domain events need to provide a callback
for handling a timer to dispatch events in a clean stack. There is
no technical reason for dispatch to go via driver specific code. It
could trivially be dispatched directly from the domain event code,
thus removing tedious boilerplate code from all drivers
Also fix the libxl & xen drivers to pass 'true' when creating the
virDomainEventState, since they run inside the daemon & thus always
expect events to be present.
* src/conf/domain_event.c, src/conf/domain_event.h: Internalize
dispatch of events from timer callback
* src/libxl/libxl_driver.c, src/lxc/lxc_driver.c,
src/qemu/qemu_domain.c, src/qemu/qemu_driver.c,
src/remote/remote_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c: Remove all timer dispatch functions
2011-12-13 13:46:28 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
virDomainEventDispatch(virDomainEventPtr event,
|
|
|
|
virDomainEventCallbackListPtr callbacks,
|
|
|
|
virDomainEventDispatchFunc dispatch,
|
|
|
|
void *opaque)
|
2008-12-04 21:09:20 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
/* Cache this now, since we may be dropping the lock,
|
2011-07-20 22:53:31 +00:00
|
|
|
and have more callbacks added. We're guaranteed not
|
2008-12-04 21:09:20 +00:00
|
|
|
to have any removed */
|
|
|
|
int cbCount = callbacks->count;
|
|
|
|
|
|
|
|
for (i = 0 ; i < cbCount ; i++) {
|
2010-03-18 14:06:09 +00:00
|
|
|
if (!virDomainEventDispatchMatchCallback(event, callbacks->callbacks[i]))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
(*dispatch)(callbacks->callbacks[i]->conn,
|
|
|
|
event,
|
|
|
|
callbacks->callbacks[i]->cb,
|
|
|
|
callbacks->callbacks[i]->opaque,
|
|
|
|
opaque);
|
2008-12-04 21:09:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Hide use of timers for domain event dispatch
Currently all drivers using domain events need to provide a callback
for handling a timer to dispatch events in a clean stack. There is
no technical reason for dispatch to go via driver specific code. It
could trivially be dispatched directly from the domain event code,
thus removing tedious boilerplate code from all drivers
Also fix the libxl & xen drivers to pass 'true' when creating the
virDomainEventState, since they run inside the daemon & thus always
expect events to be present.
* src/conf/domain_event.c, src/conf/domain_event.h: Internalize
dispatch of events from timer callback
* src/libxl/libxl_driver.c, src/lxc/lxc_driver.c,
src/qemu/qemu_domain.c, src/qemu/qemu_driver.c,
src/remote/remote_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c: Remove all timer dispatch functions
2011-12-13 13:46:28 +00:00
|
|
|
static void
|
|
|
|
virDomainEventQueueDispatch(virDomainEventQueuePtr queue,
|
|
|
|
virDomainEventCallbackListPtr callbacks,
|
|
|
|
virDomainEventDispatchFunc dispatch,
|
|
|
|
void *opaque)
|
2008-12-04 21:09:20 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
2011-01-05 22:51:45 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
virDomainEventStateQueue(virDomainEventStatePtr state,
|
|
|
|
virDomainEventPtr event)
|
|
|
|
{
|
|
|
|
if (state->timer < 0) {
|
|
|
|
virDomainEventFree(event);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-10-06 16:44:13 +00:00
|
|
|
virDomainEventStateLock(state);
|
|
|
|
|
2011-01-05 22:51:45 +00:00
|
|
|
if (virDomainEventQueuePush(state->queue, event) < 0) {
|
|
|
|
VIR_DEBUG("Error adding event to queue");
|
|
|
|
virDomainEventFree(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (state->queue->count == 1)
|
|
|
|
virEventUpdateTimeout(state->timer, 0);
|
2011-10-06 16:44:13 +00:00
|
|
|
virDomainEventStateUnlock(state);
|
2011-01-05 22:51:45 +00:00
|
|
|
}
|
|
|
|
|
Hide use of timers for domain event dispatch
Currently all drivers using domain events need to provide a callback
for handling a timer to dispatch events in a clean stack. There is
no technical reason for dispatch to go via driver specific code. It
could trivially be dispatched directly from the domain event code,
thus removing tedious boilerplate code from all drivers
Also fix the libxl & xen drivers to pass 'true' when creating the
virDomainEventState, since they run inside the daemon & thus always
expect events to be present.
* src/conf/domain_event.c, src/conf/domain_event.h: Internalize
dispatch of events from timer callback
* src/libxl/libxl_driver.c, src/lxc/lxc_driver.c,
src/qemu/qemu_domain.c, src/qemu/qemu_driver.c,
src/remote/remote_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c: Remove all timer dispatch functions
2011-12-13 13:46:28 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
virDomainEventStateDispatchFunc(virConnectPtr conn,
|
|
|
|
virDomainEventPtr event,
|
|
|
|
virConnectDomainEventGenericCallback cb,
|
|
|
|
void *cbopaque,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
virDomainEventStatePtr state = opaque;
|
|
|
|
|
|
|
|
/* Drop the lock whle dispatching, for sake of re-entrancy */
|
|
|
|
virDomainEventStateUnlock(state);
|
|
|
|
virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL);
|
|
|
|
virDomainEventStateLock(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
virDomainEventStateFlush(virDomainEventStatePtr state)
|
2011-01-05 22:51:45 +00:00
|
|
|
{
|
|
|
|
virDomainEventQueue tempQueue;
|
|
|
|
|
2011-10-06 16:44:13 +00:00
|
|
|
virDomainEventStateLock(state);
|
2011-01-05 22:51:45 +00:00
|
|
|
state->isDispatching = true;
|
|
|
|
|
|
|
|
/* Copy the queue, so we're reentrant safe when dispatchFunc drops the
|
|
|
|
* driver lock */
|
|
|
|
tempQueue.count = state->queue->count;
|
|
|
|
tempQueue.events = state->queue->events;
|
|
|
|
state->queue->count = 0;
|
|
|
|
state->queue->events = NULL;
|
|
|
|
virEventUpdateTimeout(state->timer, -1);
|
2011-10-06 16:44:13 +00:00
|
|
|
|
2011-01-05 22:51:45 +00:00
|
|
|
virDomainEventQueueDispatch(&tempQueue,
|
|
|
|
state->callbacks,
|
Hide use of timers for domain event dispatch
Currently all drivers using domain events need to provide a callback
for handling a timer to dispatch events in a clean stack. There is
no technical reason for dispatch to go via driver specific code. It
could trivially be dispatched directly from the domain event code,
thus removing tedious boilerplate code from all drivers
Also fix the libxl & xen drivers to pass 'true' when creating the
virDomainEventState, since they run inside the daemon & thus always
expect events to be present.
* src/conf/domain_event.c, src/conf/domain_event.h: Internalize
dispatch of events from timer callback
* src/libxl/libxl_driver.c, src/lxc/lxc_driver.c,
src/qemu/qemu_domain.c, src/qemu/qemu_driver.c,
src/remote/remote_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c: Remove all timer dispatch functions
2011-12-13 13:46:28 +00:00
|
|
|
virDomainEventStateDispatchFunc,
|
|
|
|
state);
|
2011-01-05 22:51:45 +00:00
|
|
|
|
|
|
|
/* Purge any deleted callbacks */
|
|
|
|
virDomainEventCallbackListPurgeMarked(state->callbacks);
|
|
|
|
|
|
|
|
state->isDispatching = false;
|
2011-10-06 16:44:13 +00:00
|
|
|
virDomainEventStateUnlock(state);
|
2011-01-05 22:51:45 +00:00
|
|
|
}
|
|
|
|
|
2011-12-13 10:39:17 +00:00
|
|
|
|
|
|
|
/**
|
2011-12-13 23:38:54 +00:00
|
|
|
* virDomainEventStateRegister:
|
|
|
|
* @conn: connection to associate with callback
|
2011-12-13 10:39:17 +00:00
|
|
|
* @state: domain event state
|
2011-12-13 23:38:54 +00:00
|
|
|
* @callback: function to remove from event
|
|
|
|
* @opaque: data blob to pass to callback
|
|
|
|
* @freecb: callback to free @opaque
|
|
|
|
*
|
|
|
|
* Register the function @callback with connection @conn,
|
|
|
|
* from @state, for lifecycle events.
|
|
|
|
*
|
|
|
|
* Returns: the number of lifecycle callbacks now registered, or -1 on error
|
|
|
|
*/
|
Hide use of timers for domain event dispatch
Currently all drivers using domain events need to provide a callback
for handling a timer to dispatch events in a clean stack. There is
no technical reason for dispatch to go via driver specific code. It
could trivially be dispatched directly from the domain event code,
thus removing tedious boilerplate code from all drivers
Also fix the libxl & xen drivers to pass 'true' when creating the
virDomainEventState, since they run inside the daemon & thus always
expect events to be present.
* src/conf/domain_event.c, src/conf/domain_event.h: Internalize
dispatch of events from timer callback
* src/libxl/libxl_driver.c, src/lxc/lxc_driver.c,
src/qemu/qemu_domain.c, src/qemu/qemu_driver.c,
src/remote/remote_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c: Remove all timer dispatch functions
2011-12-13 13:46:28 +00:00
|
|
|
int
|
|
|
|
virDomainEventStateRegister(virConnectPtr conn,
|
|
|
|
virDomainEventStatePtr state,
|
|
|
|
virConnectDomainEventCallback callback,
|
|
|
|
void *opaque,
|
|
|
|
virFreeCallback freecb)
|
2011-12-13 23:38:54 +00:00
|
|
|
{
|
2011-12-14 00:25:58 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
2011-12-13 23:38:54 +00:00
|
|
|
virDomainEventStateLock(state);
|
2011-12-14 00:25:58 +00:00
|
|
|
|
|
|
|
if ((state->callbacks->count == 0) &&
|
|
|
|
(state->timer == -1) &&
|
|
|
|
(state->timer = virEventAddTimeout(-1,
|
|
|
|
virDomainEventTimer,
|
|
|
|
state,
|
|
|
|
NULL)) < 0) {
|
|
|
|
eventReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("could not initialize domain event timer"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-12-13 23:38:54 +00:00
|
|
|
ret = virDomainEventCallbackListAdd(conn, state->callbacks,
|
|
|
|
callback, opaque, freecb);
|
2011-12-14 00:25:58 +00:00
|
|
|
|
|
|
|
if (ret == -1 &&
|
|
|
|
state->callbacks->count == 0 &&
|
|
|
|
state->timer != -1) {
|
|
|
|
virEventRemoveTimeout(state->timer);
|
|
|
|
state->timer = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
2011-12-13 23:38:54 +00:00
|
|
|
virDomainEventStateUnlock(state);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virDomainEventStateRegisterID:
|
|
|
|
* @conn: connection to associate with callback
|
|
|
|
* @state: domain event state
|
|
|
|
* @eventID: ID of the event type to register for
|
|
|
|
* @cb: function to remove from event
|
|
|
|
* @opaque: data blob to pass to callback
|
|
|
|
* @freecb: callback to free @opaque
|
|
|
|
* @callbackID: filled with callback ID
|
|
|
|
*
|
|
|
|
* Register the function @callbackID with connection @conn,
|
|
|
|
* from @state, for events of type @eventID.
|
|
|
|
*
|
|
|
|
* Returns: the number of callbacks now registered, or -1 on error
|
|
|
|
*/
|
Hide use of timers for domain event dispatch
Currently all drivers using domain events need to provide a callback
for handling a timer to dispatch events in a clean stack. There is
no technical reason for dispatch to go via driver specific code. It
could trivially be dispatched directly from the domain event code,
thus removing tedious boilerplate code from all drivers
Also fix the libxl & xen drivers to pass 'true' when creating the
virDomainEventState, since they run inside the daemon & thus always
expect events to be present.
* src/conf/domain_event.c, src/conf/domain_event.h: Internalize
dispatch of events from timer callback
* src/libxl/libxl_driver.c, src/lxc/lxc_driver.c,
src/qemu/qemu_domain.c, src/qemu/qemu_driver.c,
src/remote/remote_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c: Remove all timer dispatch functions
2011-12-13 13:46:28 +00:00
|
|
|
int
|
|
|
|
virDomainEventStateRegisterID(virConnectPtr conn,
|
|
|
|
virDomainEventStatePtr state,
|
|
|
|
virDomainPtr dom,
|
|
|
|
int eventID,
|
|
|
|
virConnectDomainEventGenericCallback cb,
|
|
|
|
void *opaque,
|
|
|
|
virFreeCallback freecb,
|
|
|
|
int *callbackID)
|
2011-12-13 23:38:54 +00:00
|
|
|
{
|
2011-12-14 00:25:58 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
2011-12-13 23:38:54 +00:00
|
|
|
virDomainEventStateLock(state);
|
2011-12-14 00:25:58 +00:00
|
|
|
|
|
|
|
if ((state->callbacks->count == 0) &&
|
|
|
|
(state->timer == -1) &&
|
|
|
|
(state->timer = virEventAddTimeout(-1,
|
|
|
|
virDomainEventTimer,
|
|
|
|
state,
|
|
|
|
NULL)) < 0) {
|
|
|
|
eventReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("could not initialize domain event timer"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-12-13 23:38:54 +00:00
|
|
|
ret = virDomainEventCallbackListAddID(conn, state->callbacks,
|
|
|
|
dom, eventID, cb, opaque, freecb,
|
|
|
|
callbackID);
|
2011-12-14 00:25:58 +00:00
|
|
|
|
|
|
|
if (ret == -1 &&
|
|
|
|
state->callbacks->count == 0 &&
|
|
|
|
state->timer != -1) {
|
|
|
|
virEventRemoveTimeout(state->timer);
|
|
|
|
state->timer = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
2011-12-13 23:38:54 +00:00
|
|
|
virDomainEventStateUnlock(state);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virDomainEventStateDeregister:
|
2011-12-13 10:39:17 +00:00
|
|
|
* @conn: connection to associate with callback
|
2011-12-13 23:38:54 +00:00
|
|
|
* @state: domain event state
|
2011-12-13 10:39:17 +00:00
|
|
|
* @callback: function to remove from event
|
|
|
|
*
|
|
|
|
* Unregister the function @callback with connection @conn,
|
|
|
|
* from @state, for lifecycle events.
|
|
|
|
*
|
|
|
|
* Returns: the number of lifecycle callbacks still registered, or -1 on error
|
|
|
|
*/
|
2011-01-05 22:51:45 +00:00
|
|
|
int
|
|
|
|
virDomainEventStateDeregister(virConnectPtr conn,
|
|
|
|
virDomainEventStatePtr state,
|
|
|
|
virConnectDomainEventCallback callback)
|
|
|
|
{
|
2011-10-06 16:44:13 +00:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
virDomainEventStateLock(state);
|
2011-01-05 22:51:45 +00:00
|
|
|
if (state->isDispatching)
|
2011-10-06 16:44:13 +00:00
|
|
|
ret = virDomainEventCallbackListMarkDelete(conn,
|
|
|
|
state->callbacks, callback);
|
2011-01-05 22:51:45 +00:00
|
|
|
else
|
2011-10-06 16:44:13 +00:00
|
|
|
ret = virDomainEventCallbackListRemove(conn, state->callbacks, callback);
|
2011-12-14 00:25:58 +00:00
|
|
|
|
|
|
|
if (state->callbacks->count == 0 &&
|
|
|
|
state->timer != -1) {
|
|
|
|
virEventRemoveTimeout(state->timer);
|
|
|
|
state->timer = -1;
|
|
|
|
}
|
|
|
|
|
2011-10-06 16:44:13 +00:00
|
|
|
virDomainEventStateUnlock(state);
|
|
|
|
return ret;
|
2011-01-05 22:51:45 +00:00
|
|
|
}
|
|
|
|
|
2011-12-13 10:39:17 +00:00
|
|
|
|
|
|
|
/**
|
Return count of callbacks when registering callbacks
When registering a callback for a particular event some callers
need to know how many callbacks already exist for that event.
While it is possible to ask for a count, this is not free from
race conditions when threaded. Thus the API for registering
callbacks should return the count of callbacks. Also rename
virDomainEventStateDeregisterAny to virDomainEventStateDeregisterID
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Return count of callbacks when
registering callbacks
* src/libxl/libxl_driver.c, src/libxl/libxl_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/remote/remote_driver.c, src/uml/uml_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xen_driver.c: Update
for change in APIs
2011-12-13 23:38:54 +00:00
|
|
|
* virDomainEventStateDeregisterID:
|
2011-12-13 10:39:17 +00:00
|
|
|
* @conn: connection to associate with callback
|
2011-12-13 23:38:54 +00:00
|
|
|
* @state: domain event state
|
2011-12-13 10:39:17 +00:00
|
|
|
* @callbackID: ID of the function to remove from event
|
|
|
|
*
|
|
|
|
* Unregister the function @callbackID with connection @conn,
|
Return count of callbacks when registering callbacks
When registering a callback for a particular event some callers
need to know how many callbacks already exist for that event.
While it is possible to ask for a count, this is not free from
race conditions when threaded. Thus the API for registering
callbacks should return the count of callbacks. Also rename
virDomainEventStateDeregisterAny to virDomainEventStateDeregisterID
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Return count of callbacks when
registering callbacks
* src/libxl/libxl_driver.c, src/libxl/libxl_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/remote/remote_driver.c, src/uml/uml_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xen_driver.c: Update
for change in APIs
2011-12-13 23:38:54 +00:00
|
|
|
* from @state, for events.
|
2011-12-13 10:39:17 +00:00
|
|
|
*
|
Return count of callbacks when registering callbacks
When registering a callback for a particular event some callers
need to know how many callbacks already exist for that event.
While it is possible to ask for a count, this is not free from
race conditions when threaded. Thus the API for registering
callbacks should return the count of callbacks. Also rename
virDomainEventStateDeregisterAny to virDomainEventStateDeregisterID
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Return count of callbacks when
registering callbacks
* src/libxl/libxl_driver.c, src/libxl/libxl_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/remote/remote_driver.c, src/uml/uml_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xen_driver.c: Update
for change in APIs
2011-12-13 23:38:54 +00:00
|
|
|
* Returns: the number of callbacks still registered, or -1 on error
|
2011-12-13 10:39:17 +00:00
|
|
|
*/
|
2011-01-05 22:51:45 +00:00
|
|
|
int
|
Return count of callbacks when registering callbacks
When registering a callback for a particular event some callers
need to know how many callbacks already exist for that event.
While it is possible to ask for a count, this is not free from
race conditions when threaded. Thus the API for registering
callbacks should return the count of callbacks. Also rename
virDomainEventStateDeregisterAny to virDomainEventStateDeregisterID
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Return count of callbacks when
registering callbacks
* src/libxl/libxl_driver.c, src/libxl/libxl_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/remote/remote_driver.c, src/uml/uml_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xen_driver.c: Update
for change in APIs
2011-12-13 23:38:54 +00:00
|
|
|
virDomainEventStateDeregisterID(virConnectPtr conn,
|
|
|
|
virDomainEventStatePtr state,
|
|
|
|
int callbackID)
|
2011-01-05 22:51:45 +00:00
|
|
|
{
|
2011-10-06 16:44:13 +00:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
virDomainEventStateLock(state);
|
2011-01-05 22:51:45 +00:00
|
|
|
if (state->isDispatching)
|
2011-10-06 16:44:13 +00:00
|
|
|
ret = virDomainEventCallbackListMarkDeleteID(conn,
|
|
|
|
state->callbacks, callbackID);
|
2011-01-05 22:51:45 +00:00
|
|
|
else
|
2011-10-06 16:44:13 +00:00
|
|
|
ret = virDomainEventCallbackListRemoveID(conn,
|
|
|
|
state->callbacks, callbackID);
|
2011-12-14 00:25:58 +00:00
|
|
|
|
|
|
|
if (state->callbacks->count == 0 &&
|
|
|
|
state->timer != -1) {
|
|
|
|
virEventRemoveTimeout(state->timer);
|
|
|
|
state->timer = -1;
|
|
|
|
}
|
|
|
|
|
2011-10-06 16:44:13 +00:00
|
|
|
virDomainEventStateUnlock(state);
|
|
|
|
return ret;
|
2011-01-05 22:51:45 +00:00
|
|
|
}
|
2011-12-13 23:38:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virDomainEventStateEventID:
|
|
|
|
* @conn: connection associated with the callback
|
|
|
|
* @state: domain event state
|
|
|
|
* @callbackID: the callback to query
|
|
|
|
*
|
|
|
|
* Query what event ID type is associated with the
|
|
|
|
* callback @callbackID for connection @conn
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virDomainEventStateEventID(virConnectPtr conn,
|
|
|
|
virDomainEventStatePtr state,
|
|
|
|
int callbackID)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
virDomainEventStateLock(state);
|
|
|
|
ret = virDomainEventCallbackListEventID(conn,
|
|
|
|
state->callbacks, callbackID);
|
|
|
|
virDomainEventStateUnlock(state);
|
|
|
|
return ret;
|
|
|
|
}
|