2008-11-04 23:33:57 +00:00
|
|
|
/*
|
|
|
|
* domain_event.c: domain event queue processing helpers
|
|
|
|
*
|
2014-01-02 14:16:49 +00:00
|
|
|
* Copyright (C) 2010-2014 Red Hat, Inc.
|
2008-11-04 23:33:57 +00:00
|
|
|
* Copyright (C) 2008 VirtualIron
|
2013-11-26 14:10:15 +00:00
|
|
|
* Copyright (C) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
2008-11-04 23:33:57 +00:00
|
|
|
*
|
|
|
|
* 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
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2008-11-04 23:33:57 +00:00
|
|
|
*
|
|
|
|
* Author: Ben Guthro
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2014-02-06 21:46:52 +00:00
|
|
|
#include <regex.h>
|
|
|
|
|
2008-11-04 23:33:57 +00:00
|
|
|
#include "domain_event.h"
|
2013-11-26 14:10:15 +00:00
|
|
|
#include "object_event.h"
|
|
|
|
#include "object_event_private.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2008-11-04 23:33:57 +00:00
|
|
|
#include "datatypes.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2013-05-03 12:40:46 +00:00
|
|
|
#include "virstring.h"
|
2014-09-10 11:28:24 +00:00
|
|
|
#include "virtypedparam.h"
|
2010-01-13 18:11:33 +00:00
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("util.domain_event");
|
2013-11-26 13:32:58 +00:00
|
|
|
|
2013-11-21 16:04:33 +00:00
|
|
|
static virClassPtr virDomainEventClass;
|
2013-11-21 16:48:41 +00:00
|
|
|
static virClassPtr virDomainEventLifecycleClass;
|
2013-11-22 08:18:47 +00:00
|
|
|
static virClassPtr virDomainEventRTCChangeClass;
|
2013-11-22 09:00:56 +00:00
|
|
|
static virClassPtr virDomainEventWatchdogClass;
|
2013-11-22 09:15:35 +00:00
|
|
|
static virClassPtr virDomainEventIOErrorClass;
|
2013-11-22 09:32:51 +00:00
|
|
|
static virClassPtr virDomainEventGraphicsClass;
|
2013-11-22 09:42:49 +00:00
|
|
|
static virClassPtr virDomainEventBlockJobClass;
|
2013-11-22 09:52:46 +00:00
|
|
|
static virClassPtr virDomainEventDiskChangeClass;
|
2013-11-22 10:00:45 +00:00
|
|
|
static virClassPtr virDomainEventTrayChangeClass;
|
2013-11-22 10:08:20 +00:00
|
|
|
static virClassPtr virDomainEventBalloonChangeClass;
|
2013-11-22 12:03:31 +00:00
|
|
|
static virClassPtr virDomainEventDeviceRemovedClass;
|
2014-01-29 00:41:34 +00:00
|
|
|
static virClassPtr virDomainEventPMClass;
|
2013-12-31 13:33:42 +00:00
|
|
|
static virClassPtr virDomainQemuMonitorEventClass;
|
2014-09-10 11:28:24 +00:00
|
|
|
static virClassPtr virDomainEventTunableClass;
|
2014-11-19 09:32:20 +00:00
|
|
|
static virClassPtr virDomainEventAgentLifecycleClass;
|
2015-03-30 16:46:21 +00:00
|
|
|
static virClassPtr virDomainEventDeviceAddedClass;
|
2015-12-10 15:09:09 +00:00
|
|
|
static virClassPtr virDomainEventMigrationIterationClass;
|
2016-02-17 20:20:11 +00:00
|
|
|
static virClassPtr virDomainEventJobCompletedClass;
|
2016-03-30 16:09:45 +00:00
|
|
|
static virClassPtr virDomainEventDeviceRemovalFailedClass;
|
2013-11-26 14:10:15 +00:00
|
|
|
|
2013-11-21 16:04:33 +00:00
|
|
|
static void virDomainEventDispose(void *obj);
|
2013-11-21 16:48:41 +00:00
|
|
|
static void virDomainEventLifecycleDispose(void *obj);
|
2013-11-22 08:18:47 +00:00
|
|
|
static void virDomainEventRTCChangeDispose(void *obj);
|
2013-11-22 09:00:56 +00:00
|
|
|
static void virDomainEventWatchdogDispose(void *obj);
|
2013-11-22 09:15:35 +00:00
|
|
|
static void virDomainEventIOErrorDispose(void *obj);
|
2013-11-22 09:32:51 +00:00
|
|
|
static void virDomainEventGraphicsDispose(void *obj);
|
2013-11-22 09:42:49 +00:00
|
|
|
static void virDomainEventBlockJobDispose(void *obj);
|
2013-11-22 09:52:46 +00:00
|
|
|
static void virDomainEventDiskChangeDispose(void *obj);
|
2013-11-22 10:00:45 +00:00
|
|
|
static void virDomainEventTrayChangeDispose(void *obj);
|
2013-11-22 10:08:20 +00:00
|
|
|
static void virDomainEventBalloonChangeDispose(void *obj);
|
2013-11-22 12:03:31 +00:00
|
|
|
static void virDomainEventDeviceRemovedDispose(void *obj);
|
2014-01-29 00:41:34 +00:00
|
|
|
static void virDomainEventPMDispose(void *obj);
|
2013-12-31 13:33:42 +00:00
|
|
|
static void virDomainQemuMonitorEventDispose(void *obj);
|
2014-09-10 11:28:24 +00:00
|
|
|
static void virDomainEventTunableDispose(void *obj);
|
2014-11-19 09:32:20 +00:00
|
|
|
static void virDomainEventAgentLifecycleDispose(void *obj);
|
2015-03-30 16:46:21 +00:00
|
|
|
static void virDomainEventDeviceAddedDispose(void *obj);
|
2015-12-10 15:09:09 +00:00
|
|
|
static void virDomainEventMigrationIterationDispose(void *obj);
|
2016-02-17 20:20:11 +00:00
|
|
|
static void virDomainEventJobCompletedDispose(void *obj);
|
2016-03-30 16:09:45 +00:00
|
|
|
static void virDomainEventDeviceRemovalFailedDispose(void *obj);
|
2013-11-21 16:04:33 +00:00
|
|
|
|
2013-12-12 17:47:42 +00:00
|
|
|
static void
|
|
|
|
virDomainEventDispatchDefaultFunc(virConnectPtr conn,
|
|
|
|
virObjectEventPtr event,
|
|
|
|
virConnectObjectEventGenericCallback cb,
|
|
|
|
void *cbopaque);
|
2013-11-21 16:04:33 +00:00
|
|
|
|
2013-12-31 13:33:42 +00:00
|
|
|
static void
|
|
|
|
virDomainQemuMonitorEventDispatchFunc(virConnectPtr conn,
|
|
|
|
virObjectEventPtr event,
|
|
|
|
virConnectObjectEventGenericCallback cb,
|
|
|
|
void *cbopaque);
|
|
|
|
|
2013-11-21 16:04:33 +00:00
|
|
|
struct _virDomainEvent {
|
|
|
|
virObjectEvent parent;
|
2010-03-18 14:06:09 +00:00
|
|
|
|
2014-01-02 14:16:49 +00:00
|
|
|
/* Unused attribute to allow for subclass creation */
|
2013-11-22 14:38:05 +00:00
|
|
|
bool dummy;
|
2010-03-18 13:17:14 +00:00
|
|
|
};
|
2013-11-22 14:38:05 +00:00
|
|
|
typedef struct _virDomainEvent virDomainEvent;
|
|
|
|
typedef virDomainEvent *virDomainEventPtr;
|
2008-11-04 23:33:57 +00:00
|
|
|
|
2013-11-21 16:48:41 +00:00
|
|
|
struct _virDomainEventLifecycle {
|
|
|
|
virDomainEvent parent;
|
|
|
|
|
|
|
|
int type;
|
|
|
|
int detail;
|
|
|
|
};
|
|
|
|
typedef struct _virDomainEventLifecycle virDomainEventLifecycle;
|
|
|
|
typedef virDomainEventLifecycle *virDomainEventLifecyclePtr;
|
|
|
|
|
2013-11-22 08:18:47 +00:00
|
|
|
struct _virDomainEventRTCChange {
|
|
|
|
virDomainEvent parent;
|
|
|
|
|
|
|
|
long long offset;
|
|
|
|
};
|
|
|
|
typedef struct _virDomainEventRTCChange virDomainEventRTCChange;
|
|
|
|
typedef virDomainEventRTCChange *virDomainEventRTCChangePtr;
|
2013-11-21 16:48:41 +00:00
|
|
|
|
2013-11-22 09:00:56 +00:00
|
|
|
struct _virDomainEventWatchdog {
|
|
|
|
virDomainEvent parent;
|
|
|
|
|
|
|
|
int action;
|
|
|
|
};
|
|
|
|
typedef struct _virDomainEventWatchdog virDomainEventWatchdog;
|
|
|
|
typedef virDomainEventWatchdog *virDomainEventWatchdogPtr;
|
|
|
|
|
2013-11-22 09:15:35 +00:00
|
|
|
struct _virDomainEventIOError {
|
|
|
|
virDomainEvent parent;
|
|
|
|
|
|
|
|
char *srcPath;
|
|
|
|
char *devAlias;
|
|
|
|
int action;
|
|
|
|
char *reason;
|
|
|
|
};
|
|
|
|
typedef struct _virDomainEventIOError virDomainEventIOError;
|
|
|
|
typedef virDomainEventIOError *virDomainEventIOErrorPtr;
|
|
|
|
|
2013-11-22 09:42:49 +00:00
|
|
|
struct _virDomainEventBlockJob {
|
|
|
|
virDomainEvent parent;
|
|
|
|
|
blockjob: use stable disk string in job event
When the block job event was first added, it was for block pull,
where the active layer of the disk remains the same name. It was
also in a day where we only cared about local files, and so we
always had a canonical absolute file name. But two things have
changed since then: we now have network disks, where determining
a single absolute string does not really make sense; and we have
two-phase jobs (copy and active commit) where the name of the
active layer changes between the first event (ready, on the old
name) and second (complete, on the pivoted name).
Adam Litke reported that having an unstable string between events
makes life harder for clients. Furthermore, all of our API that
operate on a particular disk of a domain accept multiple strings:
not only the absolute name of the active layer, but also the
destination device name (such as 'vda'). As this latter name is
stable, even for network sources, it serves as a better string
to supply in block job events.
But backwards-compatibility demands that we should not change the
name handed to users unless they explicitly request it. Therefore,
this patch adds a new event, BLOCK_JOB_2 (alas, I couldn't think of
any nicer name - but at least Migrate2 and Migrate3 are precedent
for a number suffix). We must double up on emitting both old-style
and new-style events according to what clients have registered for
(see also how IOError and IOErrorReason emits double events, but
there the difference was a larger struct rather than changed
meaning of one of the struct members).
Unfortunately, adding a new event isn't something that can easily
be broken into pieces, so the commit is rather large.
* include/libvirt/libvirt.h.in (virDomainEventID): Add a new id
for VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2.
(virConnectDomainEventBlockJobCallback): Document new semantics.
* src/conf/domain_event.c (_virDomainEventBlockJob): Rename field,
to ensure we catch all clients.
(virDomainEventBlockJobNew): Add parameter.
(virDomainEventBlockJobDispose)
(virDomainEventBlockJobNewFromObj)
(virDomainEventBlockJobNewFromDom)
(virDomainEventDispatchDefaultFunc): Adjust clients.
(virDomainEventBlockJob2NewFromObj)
(virDomainEventBlockJob2NewFromDom): New functions.
* src/conf/domain_event.h: Add new prototypes.
* src/libvirt_private.syms (domain_event.h): Export new functions.
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl): Generate two
different events.
* src/qemu/qemu_process.c (qemuProcessHandleBlockJob): Likewise.
* src/remote/remote_protocol.x
(remote_domain_event_block_job_2_msg): New struct.
(REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_2): New RPC.
* src/remote/remote_driver.c
(remoteDomainBuildEventBlockJob2): New handler.
(remoteEvents): Register new event.
* daemon/remote.c (remoteRelayDomainEventBlockJob2): New handler.
(domainEventCallbacks): Register new event.
* tools/virsh-domain.c (vshEventCallbacks): Likewise.
(vshEventBlockJobPrint): Adjust client.
* src/remote_protocol-structs: Regenerate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-14 13:18:04 +00:00
|
|
|
char *disk; /* path or dst, depending on event id */
|
2013-11-22 09:42:49 +00:00
|
|
|
int type;
|
|
|
|
int status;
|
|
|
|
};
|
|
|
|
typedef struct _virDomainEventBlockJob virDomainEventBlockJob;
|
|
|
|
typedef virDomainEventBlockJob *virDomainEventBlockJobPtr;
|
|
|
|
|
2013-11-22 09:32:51 +00:00
|
|
|
struct _virDomainEventGraphics {
|
|
|
|
virDomainEvent parent;
|
|
|
|
|
|
|
|
int phase;
|
|
|
|
virDomainEventGraphicsAddressPtr local;
|
|
|
|
virDomainEventGraphicsAddressPtr remote;
|
|
|
|
char *authScheme;
|
|
|
|
virDomainEventGraphicsSubjectPtr subject;
|
|
|
|
};
|
|
|
|
typedef struct _virDomainEventGraphics virDomainEventGraphics;
|
|
|
|
typedef virDomainEventGraphics *virDomainEventGraphicsPtr;
|
|
|
|
|
2013-11-22 09:52:46 +00:00
|
|
|
struct _virDomainEventDiskChange {
|
|
|
|
virDomainEvent parent;
|
|
|
|
|
|
|
|
char *oldSrcPath;
|
|
|
|
char *newSrcPath;
|
|
|
|
char *devAlias;
|
|
|
|
int reason;
|
|
|
|
};
|
|
|
|
typedef struct _virDomainEventDiskChange virDomainEventDiskChange;
|
|
|
|
typedef virDomainEventDiskChange *virDomainEventDiskChangePtr;
|
|
|
|
|
2013-11-22 10:00:45 +00:00
|
|
|
struct _virDomainEventTrayChange {
|
|
|
|
virDomainEvent parent;
|
|
|
|
|
|
|
|
char *devAlias;
|
|
|
|
int reason;
|
|
|
|
};
|
|
|
|
typedef struct _virDomainEventTrayChange virDomainEventTrayChange;
|
|
|
|
typedef virDomainEventTrayChange *virDomainEventTrayChangePtr;
|
|
|
|
|
2013-11-22 10:08:20 +00:00
|
|
|
struct _virDomainEventBalloonChange {
|
|
|
|
virDomainEvent parent;
|
|
|
|
|
|
|
|
/* In unit of 1024 bytes */
|
|
|
|
unsigned long long actual;
|
|
|
|
};
|
|
|
|
typedef struct _virDomainEventBalloonChange virDomainEventBalloonChange;
|
|
|
|
typedef virDomainEventBalloonChange *virDomainEventBalloonChangePtr;
|
|
|
|
|
2013-11-22 12:03:31 +00:00
|
|
|
struct _virDomainEventDeviceRemoved {
|
|
|
|
virDomainEvent parent;
|
|
|
|
|
|
|
|
char *devAlias;
|
|
|
|
};
|
|
|
|
typedef struct _virDomainEventDeviceRemoved virDomainEventDeviceRemoved;
|
|
|
|
typedef virDomainEventDeviceRemoved *virDomainEventDeviceRemovedPtr;
|
|
|
|
|
2015-03-30 16:46:21 +00:00
|
|
|
struct _virDomainEventDeviceAdded {
|
|
|
|
virDomainEvent parent;
|
|
|
|
|
|
|
|
char *devAlias;
|
|
|
|
};
|
|
|
|
typedef struct _virDomainEventDeviceAdded virDomainEventDeviceAdded;
|
|
|
|
typedef virDomainEventDeviceAdded *virDomainEventDeviceAddedPtr;
|
|
|
|
|
2014-01-29 00:41:34 +00:00
|
|
|
struct _virDomainEventPM {
|
|
|
|
virDomainEvent parent;
|
|
|
|
|
|
|
|
int reason;
|
|
|
|
};
|
|
|
|
typedef struct _virDomainEventPM virDomainEventPM;
|
|
|
|
typedef virDomainEventPM *virDomainEventPMPtr;
|
|
|
|
|
2013-12-31 13:33:42 +00:00
|
|
|
struct _virDomainQemuMonitorEvent {
|
|
|
|
virObjectEvent parent;
|
|
|
|
|
|
|
|
char *event;
|
|
|
|
long long seconds;
|
|
|
|
unsigned int micros;
|
|
|
|
char *details;
|
|
|
|
};
|
|
|
|
typedef struct _virDomainQemuMonitorEvent virDomainQemuMonitorEvent;
|
|
|
|
typedef virDomainQemuMonitorEvent *virDomainQemuMonitorEventPtr;
|
|
|
|
|
2014-09-10 11:28:24 +00:00
|
|
|
struct _virDomainEventTunable {
|
|
|
|
virDomainEvent parent;
|
|
|
|
|
|
|
|
virTypedParameterPtr params;
|
|
|
|
int nparams;
|
|
|
|
};
|
|
|
|
typedef struct _virDomainEventTunable virDomainEventTunable;
|
|
|
|
typedef virDomainEventTunable *virDomainEventTunablePtr;
|
|
|
|
|
2014-11-19 09:32:20 +00:00
|
|
|
struct _virDomainEventAgentLifecycle {
|
|
|
|
virDomainEvent parent;
|
|
|
|
|
|
|
|
int state;
|
|
|
|
int reason;
|
|
|
|
};
|
|
|
|
typedef struct _virDomainEventAgentLifecycle virDomainEventAgentLifecycle;
|
|
|
|
typedef virDomainEventAgentLifecycle *virDomainEventAgentLifecyclePtr;
|
|
|
|
|
2015-12-10 15:09:09 +00:00
|
|
|
struct _virDomainEventMigrationIteration {
|
|
|
|
virDomainEvent parent;
|
|
|
|
|
|
|
|
int iteration;
|
|
|
|
};
|
|
|
|
typedef struct _virDomainEventMigrationIteration virDomainEventMigrationIteration;
|
|
|
|
typedef virDomainEventMigrationIteration *virDomainEventMigrationIterationPtr;
|
|
|
|
|
2016-02-17 20:20:11 +00:00
|
|
|
struct _virDomainEventJobCompleted {
|
|
|
|
virDomainEvent parent;
|
|
|
|
|
|
|
|
virTypedParameterPtr params;
|
|
|
|
int nparams;
|
|
|
|
};
|
|
|
|
typedef struct _virDomainEventJobCompleted virDomainEventJobCompleted;
|
|
|
|
typedef virDomainEventJobCompleted *virDomainEventJobCompletedPtr;
|
2013-11-22 09:52:46 +00:00
|
|
|
|
2016-03-30 16:09:45 +00:00
|
|
|
struct _virDomainEventDeviceRemovalFailed {
|
|
|
|
virDomainEvent parent;
|
|
|
|
|
|
|
|
char *devAlias;
|
|
|
|
};
|
|
|
|
typedef struct _virDomainEventDeviceRemovalFailed virDomainEventDeviceRemovalFailed;
|
|
|
|
typedef virDomainEventDeviceRemovalFailed *virDomainEventDeviceRemovalFailedPtr;
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-01-02 14:16:49 +00:00
|
|
|
static int
|
|
|
|
virDomainEventsOnceInit(void)
|
2013-11-26 13:32:58 +00:00
|
|
|
{
|
2013-11-21 16:04:33 +00:00
|
|
|
if (!(virDomainEventClass =
|
2013-11-26 13:32:58 +00:00
|
|
|
virClassNew(virClassForObjectEvent(),
|
2013-11-21 16:04:33 +00:00
|
|
|
"virDomainEvent",
|
|
|
|
sizeof(virDomainEvent),
|
|
|
|
virDomainEventDispose)))
|
|
|
|
return -1;
|
2013-11-21 16:48:41 +00:00
|
|
|
if (!(virDomainEventLifecycleClass =
|
|
|
|
virClassNew(virDomainEventClass,
|
|
|
|
"virDomainEventLifecycle",
|
|
|
|
sizeof(virDomainEventLifecycle),
|
|
|
|
virDomainEventLifecycleDispose)))
|
|
|
|
return -1;
|
2013-11-22 08:18:47 +00:00
|
|
|
if (!(virDomainEventRTCChangeClass =
|
|
|
|
virClassNew(virDomainEventClass,
|
|
|
|
"virDomainEventRTCChange",
|
|
|
|
sizeof(virDomainEventRTCChange),
|
|
|
|
virDomainEventRTCChangeDispose)))
|
|
|
|
return -1;
|
2013-11-22 09:00:56 +00:00
|
|
|
if (!(virDomainEventWatchdogClass =
|
|
|
|
virClassNew(virDomainEventClass,
|
|
|
|
"virDomainEventWatchdog",
|
|
|
|
sizeof(virDomainEventWatchdog),
|
|
|
|
virDomainEventWatchdogDispose)))
|
|
|
|
return -1;
|
2013-11-22 09:15:35 +00:00
|
|
|
if (!(virDomainEventIOErrorClass =
|
|
|
|
virClassNew(virDomainEventClass,
|
|
|
|
"virDomainEventIOError",
|
|
|
|
sizeof(virDomainEventIOError),
|
|
|
|
virDomainEventIOErrorDispose)))
|
|
|
|
return -1;
|
2013-11-22 09:32:51 +00:00
|
|
|
if (!(virDomainEventGraphicsClass =
|
|
|
|
virClassNew(virDomainEventClass,
|
|
|
|
"virDomainEventGraphics",
|
|
|
|
sizeof(virDomainEventGraphics),
|
|
|
|
virDomainEventGraphicsDispose)))
|
|
|
|
return -1;
|
2013-11-22 09:42:49 +00:00
|
|
|
if (!(virDomainEventBlockJobClass =
|
|
|
|
virClassNew(virDomainEventClass,
|
|
|
|
"virDomainEventBlockJob",
|
|
|
|
sizeof(virDomainEventBlockJob),
|
|
|
|
virDomainEventBlockJobDispose)))
|
|
|
|
return -1;
|
2013-11-22 09:52:46 +00:00
|
|
|
if (!(virDomainEventDiskChangeClass =
|
|
|
|
virClassNew(virDomainEventClass,
|
|
|
|
"virDomainEventDiskChange",
|
|
|
|
sizeof(virDomainEventDiskChange),
|
|
|
|
virDomainEventDiskChangeDispose)))
|
|
|
|
return -1;
|
2013-11-22 10:00:45 +00:00
|
|
|
if (!(virDomainEventTrayChangeClass =
|
|
|
|
virClassNew(virDomainEventClass,
|
|
|
|
"virDomainEventTrayChange",
|
|
|
|
sizeof(virDomainEventTrayChange),
|
|
|
|
virDomainEventTrayChangeDispose)))
|
|
|
|
return -1;
|
2013-11-22 10:08:20 +00:00
|
|
|
if (!(virDomainEventBalloonChangeClass =
|
|
|
|
virClassNew(virDomainEventClass,
|
|
|
|
"virDomainEventBalloonChange",
|
|
|
|
sizeof(virDomainEventBalloonChange),
|
|
|
|
virDomainEventBalloonChangeDispose)))
|
|
|
|
return -1;
|
2013-11-22 12:03:31 +00:00
|
|
|
if (!(virDomainEventDeviceRemovedClass =
|
|
|
|
virClassNew(virDomainEventClass,
|
|
|
|
"virDomainEventDeviceRemoved",
|
|
|
|
sizeof(virDomainEventDeviceRemoved),
|
|
|
|
virDomainEventDeviceRemovedDispose)))
|
|
|
|
return -1;
|
2015-03-30 16:46:21 +00:00
|
|
|
if (!(virDomainEventDeviceAddedClass =
|
|
|
|
virClassNew(virDomainEventClass,
|
|
|
|
"virDomainEventDeviceAdded",
|
|
|
|
sizeof(virDomainEventDeviceAdded),
|
|
|
|
virDomainEventDeviceAddedDispose)))
|
|
|
|
return -1;
|
2014-01-29 00:41:34 +00:00
|
|
|
if (!(virDomainEventPMClass =
|
|
|
|
virClassNew(virDomainEventClass,
|
|
|
|
"virDomainEventPM",
|
|
|
|
sizeof(virDomainEventPM),
|
|
|
|
virDomainEventPMDispose)))
|
|
|
|
return -1;
|
2013-12-31 13:33:42 +00:00
|
|
|
if (!(virDomainQemuMonitorEventClass =
|
|
|
|
virClassNew(virClassForObjectEvent(),
|
|
|
|
"virDomainQemuMonitorEvent",
|
|
|
|
sizeof(virDomainQemuMonitorEvent),
|
|
|
|
virDomainQemuMonitorEventDispose)))
|
|
|
|
return -1;
|
2014-09-10 11:28:24 +00:00
|
|
|
if (!(virDomainEventTunableClass =
|
|
|
|
virClassNew(virDomainEventClass,
|
|
|
|
"virDomainEventTunable",
|
|
|
|
sizeof(virDomainEventTunable),
|
|
|
|
virDomainEventTunableDispose)))
|
|
|
|
return -1;
|
2014-11-19 09:32:20 +00:00
|
|
|
if (!(virDomainEventAgentLifecycleClass =
|
|
|
|
virClassNew(virDomainEventClass,
|
|
|
|
"virDomainEventAgentLifecycle",
|
|
|
|
sizeof(virDomainEventAgentLifecycle),
|
|
|
|
virDomainEventAgentLifecycleDispose)))
|
|
|
|
return -1;
|
2015-12-10 15:09:09 +00:00
|
|
|
if (!(virDomainEventMigrationIterationClass =
|
|
|
|
virClassNew(virDomainEventClass,
|
|
|
|
"virDomainEventMigrationIteration",
|
|
|
|
sizeof(virDomainEventMigrationIteration),
|
|
|
|
virDomainEventMigrationIterationDispose)))
|
|
|
|
return -1;
|
2016-02-17 20:20:11 +00:00
|
|
|
if (!(virDomainEventJobCompletedClass =
|
|
|
|
virClassNew(virDomainEventClass,
|
|
|
|
"virDomainEventJobCompleted",
|
|
|
|
sizeof(virDomainEventJobCompleted),
|
|
|
|
virDomainEventJobCompletedDispose)))
|
|
|
|
return -1;
|
2016-03-30 16:09:45 +00:00
|
|
|
if (!(virDomainEventDeviceRemovalFailedClass =
|
|
|
|
virClassNew(virDomainEventClass,
|
|
|
|
"virDomainEventDeviceRemovalFailed",
|
|
|
|
sizeof(virDomainEventDeviceRemovalFailed),
|
|
|
|
virDomainEventDeviceRemovalFailedDispose)))
|
|
|
|
return -1;
|
2013-11-21 16:04:33 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
VIR_ONCE_GLOBAL_INIT(virDomainEvents)
|
2013-11-21 16:04:33 +00:00
|
|
|
|
|
|
|
|
2014-01-02 14:16:49 +00:00
|
|
|
static void
|
|
|
|
virDomainEventDispose(void *obj)
|
2013-11-21 16:04:33 +00:00
|
|
|
{
|
|
|
|
virDomainEventPtr event = obj;
|
|
|
|
|
|
|
|
VIR_DEBUG("obj=%p", event);
|
|
|
|
}
|
|
|
|
|
2014-01-02 14:16:49 +00:00
|
|
|
static void
|
|
|
|
virDomainEventLifecycleDispose(void *obj)
|
2013-11-21 16:48:41 +00:00
|
|
|
{
|
|
|
|
virDomainEventLifecyclePtr event = obj;
|
|
|
|
VIR_DEBUG("obj=%p", event);
|
|
|
|
}
|
|
|
|
|
2014-01-02 14:16:49 +00:00
|
|
|
static void
|
|
|
|
virDomainEventRTCChangeDispose(void *obj)
|
2013-11-22 08:18:47 +00:00
|
|
|
{
|
|
|
|
virDomainEventRTCChangePtr event = obj;
|
|
|
|
VIR_DEBUG("obj=%p", event);
|
|
|
|
}
|
|
|
|
|
2014-01-02 14:16:49 +00:00
|
|
|
static void
|
|
|
|
virDomainEventWatchdogDispose(void *obj)
|
2013-11-22 09:00:56 +00:00
|
|
|
{
|
|
|
|
virDomainEventWatchdogPtr event = obj;
|
|
|
|
VIR_DEBUG("obj=%p", event);
|
|
|
|
}
|
|
|
|
|
2014-01-02 14:16:49 +00:00
|
|
|
static void
|
|
|
|
virDomainEventIOErrorDispose(void *obj)
|
2013-11-22 09:15:35 +00:00
|
|
|
{
|
|
|
|
virDomainEventIOErrorPtr event = obj;
|
|
|
|
VIR_DEBUG("obj=%p", event);
|
|
|
|
|
|
|
|
VIR_FREE(event->srcPath);
|
|
|
|
VIR_FREE(event->devAlias);
|
|
|
|
VIR_FREE(event->reason);
|
|
|
|
}
|
|
|
|
|
2014-01-02 14:16:49 +00:00
|
|
|
static void
|
|
|
|
virDomainEventGraphicsDispose(void *obj)
|
2013-11-22 09:32:51 +00:00
|
|
|
{
|
|
|
|
virDomainEventGraphicsPtr event = obj;
|
|
|
|
VIR_DEBUG("obj=%p", event);
|
|
|
|
|
|
|
|
if (event->local) {
|
|
|
|
VIR_FREE(event->local->node);
|
|
|
|
VIR_FREE(event->local->service);
|
|
|
|
VIR_FREE(event->local);
|
|
|
|
}
|
|
|
|
if (event->remote) {
|
|
|
|
VIR_FREE(event->remote->node);
|
|
|
|
VIR_FREE(event->remote->service);
|
|
|
|
VIR_FREE(event->remote);
|
|
|
|
}
|
|
|
|
VIR_FREE(event->authScheme);
|
|
|
|
if (event->subject) {
|
|
|
|
size_t i;
|
|
|
|
for (i = 0; i < event->subject->nidentity; i++) {
|
|
|
|
VIR_FREE(event->subject->identities[i].type);
|
|
|
|
VIR_FREE(event->subject->identities[i].name);
|
|
|
|
}
|
|
|
|
VIR_FREE(event->subject);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-02 14:16:49 +00:00
|
|
|
static void
|
|
|
|
virDomainEventBlockJobDispose(void *obj)
|
2013-11-22 09:42:49 +00:00
|
|
|
{
|
|
|
|
virDomainEventBlockJobPtr event = obj;
|
|
|
|
VIR_DEBUG("obj=%p", event);
|
|
|
|
|
blockjob: use stable disk string in job event
When the block job event was first added, it was for block pull,
where the active layer of the disk remains the same name. It was
also in a day where we only cared about local files, and so we
always had a canonical absolute file name. But two things have
changed since then: we now have network disks, where determining
a single absolute string does not really make sense; and we have
two-phase jobs (copy and active commit) where the name of the
active layer changes between the first event (ready, on the old
name) and second (complete, on the pivoted name).
Adam Litke reported that having an unstable string between events
makes life harder for clients. Furthermore, all of our API that
operate on a particular disk of a domain accept multiple strings:
not only the absolute name of the active layer, but also the
destination device name (such as 'vda'). As this latter name is
stable, even for network sources, it serves as a better string
to supply in block job events.
But backwards-compatibility demands that we should not change the
name handed to users unless they explicitly request it. Therefore,
this patch adds a new event, BLOCK_JOB_2 (alas, I couldn't think of
any nicer name - but at least Migrate2 and Migrate3 are precedent
for a number suffix). We must double up on emitting both old-style
and new-style events according to what clients have registered for
(see also how IOError and IOErrorReason emits double events, but
there the difference was a larger struct rather than changed
meaning of one of the struct members).
Unfortunately, adding a new event isn't something that can easily
be broken into pieces, so the commit is rather large.
* include/libvirt/libvirt.h.in (virDomainEventID): Add a new id
for VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2.
(virConnectDomainEventBlockJobCallback): Document new semantics.
* src/conf/domain_event.c (_virDomainEventBlockJob): Rename field,
to ensure we catch all clients.
(virDomainEventBlockJobNew): Add parameter.
(virDomainEventBlockJobDispose)
(virDomainEventBlockJobNewFromObj)
(virDomainEventBlockJobNewFromDom)
(virDomainEventDispatchDefaultFunc): Adjust clients.
(virDomainEventBlockJob2NewFromObj)
(virDomainEventBlockJob2NewFromDom): New functions.
* src/conf/domain_event.h: Add new prototypes.
* src/libvirt_private.syms (domain_event.h): Export new functions.
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl): Generate two
different events.
* src/qemu/qemu_process.c (qemuProcessHandleBlockJob): Likewise.
* src/remote/remote_protocol.x
(remote_domain_event_block_job_2_msg): New struct.
(REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_2): New RPC.
* src/remote/remote_driver.c
(remoteDomainBuildEventBlockJob2): New handler.
(remoteEvents): Register new event.
* daemon/remote.c (remoteRelayDomainEventBlockJob2): New handler.
(domainEventCallbacks): Register new event.
* tools/virsh-domain.c (vshEventCallbacks): Likewise.
(vshEventBlockJobPrint): Adjust client.
* src/remote_protocol-structs: Regenerate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-14 13:18:04 +00:00
|
|
|
VIR_FREE(event->disk);
|
2013-11-22 09:42:49 +00:00
|
|
|
}
|
|
|
|
|
2014-01-02 14:16:49 +00:00
|
|
|
static void
|
|
|
|
virDomainEventDiskChangeDispose(void *obj)
|
2013-11-22 09:52:46 +00:00
|
|
|
{
|
|
|
|
virDomainEventDiskChangePtr event = obj;
|
|
|
|
VIR_DEBUG("obj=%p", event);
|
|
|
|
|
|
|
|
VIR_FREE(event->oldSrcPath);
|
|
|
|
VIR_FREE(event->newSrcPath);
|
|
|
|
VIR_FREE(event->devAlias);
|
|
|
|
}
|
|
|
|
|
2014-01-02 14:16:49 +00:00
|
|
|
static void
|
|
|
|
virDomainEventTrayChangeDispose(void *obj)
|
2013-11-22 10:00:45 +00:00
|
|
|
{
|
|
|
|
virDomainEventTrayChangePtr event = obj;
|
|
|
|
VIR_DEBUG("obj=%p", event);
|
|
|
|
|
|
|
|
VIR_FREE(event->devAlias);
|
|
|
|
}
|
|
|
|
|
2014-01-02 14:16:49 +00:00
|
|
|
static void
|
|
|
|
virDomainEventBalloonChangeDispose(void *obj)
|
2013-11-22 10:08:20 +00:00
|
|
|
{
|
|
|
|
virDomainEventBalloonChangePtr event = obj;
|
|
|
|
VIR_DEBUG("obj=%p", event);
|
|
|
|
}
|
|
|
|
|
2014-01-02 14:16:49 +00:00
|
|
|
static void
|
|
|
|
virDomainEventDeviceRemovedDispose(void *obj)
|
2013-11-22 12:03:31 +00:00
|
|
|
{
|
|
|
|
virDomainEventDeviceRemovedPtr event = obj;
|
|
|
|
VIR_DEBUG("obj=%p", event);
|
|
|
|
|
|
|
|
VIR_FREE(event->devAlias);
|
|
|
|
}
|
|
|
|
|
2015-03-30 16:46:21 +00:00
|
|
|
static void
|
|
|
|
virDomainEventDeviceAddedDispose(void *obj)
|
|
|
|
{
|
|
|
|
virDomainEventDeviceAddedPtr event = obj;
|
|
|
|
VIR_DEBUG("obj=%p", event);
|
|
|
|
|
|
|
|
VIR_FREE(event->devAlias);
|
|
|
|
}
|
|
|
|
|
2016-03-30 16:09:45 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
virDomainEventDeviceRemovalFailedDispose(void *obj)
|
|
|
|
{
|
|
|
|
virDomainEventDeviceRemovalFailedPtr event = obj;
|
|
|
|
VIR_DEBUG("obj=%p", event);
|
|
|
|
|
|
|
|
VIR_FREE(event->devAlias);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-01-29 00:41:34 +00:00
|
|
|
static void
|
|
|
|
virDomainEventPMDispose(void *obj)
|
|
|
|
{
|
|
|
|
virDomainEventPMPtr event = obj;
|
|
|
|
VIR_DEBUG("obj=%p", event);
|
|
|
|
}
|
|
|
|
|
2013-12-31 13:33:42 +00:00
|
|
|
static void
|
|
|
|
virDomainQemuMonitorEventDispose(void *obj)
|
|
|
|
{
|
|
|
|
virDomainQemuMonitorEventPtr event = obj;
|
|
|
|
VIR_DEBUG("obj=%p", event);
|
|
|
|
|
|
|
|
VIR_FREE(event->event);
|
|
|
|
VIR_FREE(event->details);
|
|
|
|
}
|
|
|
|
|
2014-09-10 11:28:24 +00:00
|
|
|
static void
|
|
|
|
virDomainEventTunableDispose(void *obj)
|
|
|
|
{
|
|
|
|
virDomainEventTunablePtr event = obj;
|
|
|
|
VIR_DEBUG("obj=%p", event);
|
|
|
|
|
|
|
|
virTypedParamsFree(event->params, event->nparams);
|
|
|
|
}
|
|
|
|
|
2014-11-19 09:32:20 +00:00
|
|
|
static void
|
|
|
|
virDomainEventAgentLifecycleDispose(void *obj)
|
|
|
|
{
|
|
|
|
virDomainEventAgentLifecyclePtr event = obj;
|
|
|
|
VIR_DEBUG("obj=%p", event);
|
|
|
|
};
|
|
|
|
|
2015-12-10 15:09:09 +00:00
|
|
|
static void
|
|
|
|
virDomainEventMigrationIterationDispose(void *obj)
|
|
|
|
{
|
|
|
|
virDomainEventMigrationIterationPtr event = obj;
|
|
|
|
VIR_DEBUG("obj=%p", event);
|
|
|
|
};
|
|
|
|
|
2016-02-17 20:20:11 +00:00
|
|
|
static void
|
|
|
|
virDomainEventJobCompletedDispose(void *obj)
|
|
|
|
{
|
|
|
|
virDomainEventJobCompletedPtr event = obj;
|
|
|
|
VIR_DEBUG("obj=%p", event);
|
|
|
|
|
|
|
|
virTypedParamsFree(event->params, event->nparams);
|
|
|
|
}
|
|
|
|
|
2010-03-18 14:06:09 +00:00
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
static void *
|
|
|
|
virDomainEventNew(virClassPtr klass,
|
|
|
|
int eventID,
|
|
|
|
int id,
|
|
|
|
const char *name,
|
|
|
|
const unsigned char *uuid)
|
2013-11-21 16:04:33 +00:00
|
|
|
{
|
|
|
|
virDomainEventPtr event;
|
2016-06-23 16:06:39 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
2013-11-21 16:04:33 +00:00
|
|
|
|
2013-11-26 14:10:15 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!virClassIsDerivedFrom(klass, virDomainEventClass)) {
|
|
|
|
virReportInvalidArg(klass,
|
|
|
|
_("Class %s must derive from virDomainEvent"),
|
|
|
|
virClassName(klass));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-06-23 16:06:39 +00:00
|
|
|
/* We use uuid for matching key. We ignore 'name' because
|
|
|
|
* Xen sometimes renames guests during migration, thus
|
|
|
|
* 'uuid' is the only truly reliable key we can use. */
|
|
|
|
virUUIDFormat(uuid, uuidstr);
|
2013-12-12 17:47:42 +00:00
|
|
|
if (!(event = virObjectEventNew(klass,
|
|
|
|
virDomainEventDispatchDefaultFunc,
|
|
|
|
eventID,
|
2016-06-23 16:06:39 +00:00
|
|
|
id, name, uuid, uuidstr)))
|
2008-12-04 21:09:20 +00:00
|
|
|
return NULL;
|
2010-03-18 14:06:09 +00:00
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
return (virObjectEventPtr)event;
|
2010-03-18 14:06:09 +00:00
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventLifecycleNew(int id,
|
|
|
|
const char *name,
|
|
|
|
const unsigned char *uuid,
|
|
|
|
int type,
|
|
|
|
int detail)
|
2010-03-18 14:06:09 +00:00
|
|
|
{
|
2013-11-21 16:48:41 +00:00
|
|
|
virDomainEventLifecyclePtr event;
|
2010-03-18 14:06:09 +00:00
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 08:00:01 +00:00
|
|
|
if (!(event = virDomainEventNew(virDomainEventLifecycleClass,
|
|
|
|
VIR_DOMAIN_EVENT_ID_LIFECYCLE,
|
|
|
|
id, name, uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-21 16:48:41 +00:00
|
|
|
event->type = type;
|
|
|
|
event->detail = detail;
|
2008-12-04 21:09:20 +00:00
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
return (virObjectEventPtr)event;
|
2008-12-04 21:09:20 +00:00
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventLifecycleNewFromDom(virDomainPtr dom,
|
|
|
|
int type,
|
|
|
|
int detail)
|
2008-12-04 21:09:20 +00:00
|
|
|
{
|
2013-11-21 17:03:26 +00:00
|
|
|
return virDomainEventLifecycleNew(dom->id, dom->name, dom->uuid,
|
|
|
|
type, detail);
|
2008-12-04 21:09:20 +00:00
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventLifecycleNewFromObj(virDomainObjPtr obj,
|
|
|
|
int type,
|
|
|
|
int detail)
|
2008-12-04 21:09:20 +00:00
|
|
|
{
|
2013-11-21 17:03:26 +00:00
|
|
|
return virDomainEventLifecycleNewFromDef(obj->def, type, detail);
|
2008-12-04 21:09:20 +00:00
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventLifecycleNewFromDef(virDomainDefPtr def,
|
|
|
|
int type,
|
|
|
|
int detail)
|
2008-12-04 21:09:20 +00:00
|
|
|
{
|
2013-11-21 17:03:26 +00:00
|
|
|
return virDomainEventLifecycleNew(def->id, def->name, def->uuid,
|
|
|
|
type, detail);
|
2008-12-04 21:09:20 +00:00
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventRebootNew(int id,
|
|
|
|
const char *name,
|
|
|
|
const unsigned char *uuid)
|
2011-04-25 11:35:23 +00:00
|
|
|
{
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 08:00:01 +00:00
|
|
|
return virDomainEventNew(virDomainEventClass,
|
|
|
|
VIR_DOMAIN_EVENT_ID_REBOOT,
|
|
|
|
id, name, uuid);
|
2011-04-25 11:35:23 +00:00
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventRebootNewFromDom(virDomainPtr dom)
|
2010-03-18 15:25:38 +00:00
|
|
|
{
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 08:00:01 +00:00
|
|
|
return virDomainEventNew(virDomainEventClass,
|
|
|
|
VIR_DOMAIN_EVENT_ID_REBOOT,
|
|
|
|
dom->id, dom->name, dom->uuid);
|
2010-03-18 15:25:38 +00:00
|
|
|
}
|
2011-04-25 11:35:23 +00:00
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventRebootNewFromObj(virDomainObjPtr obj)
|
2010-03-18 15:25:38 +00:00
|
|
|
{
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 08:00:01 +00:00
|
|
|
return virDomainEventNew(virDomainEventClass,
|
|
|
|
VIR_DOMAIN_EVENT_ID_REBOOT,
|
|
|
|
obj->def->id, obj->def->name, obj->def->uuid);
|
2010-03-18 15:25:38 +00:00
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventRTCChangeNewFromDom(virDomainPtr dom,
|
|
|
|
long long offset)
|
2010-03-18 18:28:15 +00:00
|
|
|
{
|
2013-11-22 08:18:47 +00:00
|
|
|
virDomainEventRTCChangePtr ev;
|
2013-11-21 16:04:33 +00:00
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 08:18:47 +00:00
|
|
|
if (!(ev = virDomainEventNew(virDomainEventRTCChangeClass,
|
2013-11-22 08:00:01 +00:00
|
|
|
VIR_DOMAIN_EVENT_ID_RTC_CHANGE,
|
|
|
|
dom->id, dom->name, dom->uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
2010-03-18 18:28:15 +00:00
|
|
|
|
2013-11-22 08:18:47 +00:00
|
|
|
ev->offset = offset;
|
2010-03-18 18:28:15 +00:00
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
return (virObjectEventPtr)ev;
|
2010-03-18 18:28:15 +00:00
|
|
|
}
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventRTCChangeNewFromObj(virDomainObjPtr obj,
|
|
|
|
long long offset)
|
2010-03-18 18:28:15 +00:00
|
|
|
{
|
2013-11-22 08:18:47 +00:00
|
|
|
virDomainEventRTCChangePtr ev;
|
2010-03-18 18:28:15 +00:00
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 08:18:47 +00:00
|
|
|
if (!(ev = virDomainEventNew(virDomainEventRTCChangeClass,
|
2013-11-22 08:00:01 +00:00
|
|
|
VIR_DOMAIN_EVENT_ID_RTC_CHANGE,
|
|
|
|
obj->def->id, obj->def->name,
|
|
|
|
obj->def->uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 08:18:47 +00:00
|
|
|
ev->offset = offset;
|
2010-03-18 18:28:15 +00:00
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
return (virObjectEventPtr)ev;
|
2010-03-18 18:28:15 +00:00
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventWatchdogNewFromDom(virDomainPtr dom,
|
|
|
|
int action)
|
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
|
|
|
{
|
2013-11-22 09:00:56 +00:00
|
|
|
virDomainEventWatchdogPtr 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
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 09:00:56 +00:00
|
|
|
if (!(ev = virDomainEventNew(virDomainEventWatchdogClass,
|
2013-11-22 08:00:01 +00:00
|
|
|
VIR_DOMAIN_EVENT_ID_WATCHDOG,
|
|
|
|
dom->id, dom->name, dom->uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 09:00:56 +00:00
|
|
|
ev->action = action;
|
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
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
return (virObjectEventPtr)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
|
|
|
}
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventWatchdogNewFromObj(virDomainObjPtr obj,
|
|
|
|
int action)
|
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
|
|
|
{
|
2013-11-22 09:00:56 +00:00
|
|
|
virDomainEventWatchdogPtr ev;
|
2013-11-21 16:04:33 +00:00
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
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
|
|
|
|
2013-11-22 09:00:56 +00:00
|
|
|
if (!(ev = virDomainEventNew(virDomainEventWatchdogClass,
|
2013-11-22 08:00:01 +00:00
|
|
|
VIR_DOMAIN_EVENT_ID_WATCHDOG,
|
|
|
|
obj->def->id, obj->def->name,
|
|
|
|
obj->def->uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 09:00:56 +00:00
|
|
|
ev->action = action;
|
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
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
return (virObjectEventPtr)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
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
static virObjectEventPtr
|
|
|
|
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
|
|
|
{
|
2013-11-22 09:15:35 +00:00
|
|
|
virDomainEventIOErrorPtr ev;
|
2013-11-21 16:04:33 +00:00
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 09:15:35 +00:00
|
|
|
if (!(ev = virDomainEventNew(virDomainEventIOErrorClass, event,
|
2013-11-22 08:00:01 +00:00
|
|
|
dom->id, dom->name, dom->uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 09:15:35 +00:00
|
|
|
ev->action = action;
|
|
|
|
if (VIR_STRDUP(ev->srcPath, srcPath) < 0 ||
|
|
|
|
VIR_STRDUP(ev->devAlias, devAlias) < 0 ||
|
|
|
|
VIR_STRDUP(ev->reason, reason) < 0) {
|
2013-11-21 16:04:33 +00:00
|
|
|
virObjectUnref(ev);
|
|
|
|
ev = NULL;
|
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
|
|
|
}
|
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
return (virObjectEventPtr)ev;
|
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
|
|
|
}
|
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
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
static virObjectEventPtr
|
|
|
|
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
|
|
|
{
|
2013-11-22 09:15:35 +00:00
|
|
|
virDomainEventIOErrorPtr ev;
|
2013-11-21 16:04:33 +00:00
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 09:15:35 +00:00
|
|
|
if (!(ev = virDomainEventNew(virDomainEventIOErrorClass, event,
|
2013-11-22 08:00:01 +00:00
|
|
|
obj->def->id, obj->def->name,
|
|
|
|
obj->def->uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 09:15:35 +00:00
|
|
|
ev->action = action;
|
|
|
|
if (VIR_STRDUP(ev->srcPath, srcPath) < 0 ||
|
|
|
|
VIR_STRDUP(ev->devAlias, devAlias) < 0 ||
|
|
|
|
VIR_STRDUP(ev->reason, reason) < 0) {
|
2013-11-21 16:04:33 +00:00
|
|
|
virObjectUnref(ev);
|
|
|
|
ev = NULL;
|
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
|
|
|
}
|
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
return (virObjectEventPtr)ev;
|
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
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventIOErrorNewFromDom(virDomainPtr dom,
|
|
|
|
const char *srcPath,
|
|
|
|
const 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
|
|
|
{
|
|
|
|
return virDomainEventIOErrorNewFromDomImpl(VIR_DOMAIN_EVENT_ID_IO_ERROR,
|
|
|
|
dom, srcPath, devAlias,
|
|
|
|
action, NULL);
|
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventIOErrorNewFromObj(virDomainObjPtr obj,
|
|
|
|
const char *srcPath,
|
|
|
|
const 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
|
|
|
{
|
|
|
|
return virDomainEventIOErrorNewFromObjImpl(VIR_DOMAIN_EVENT_ID_IO_ERROR,
|
|
|
|
obj, srcPath, devAlias,
|
|
|
|
action, NULL);
|
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventIOErrorReasonNewFromDom(virDomainPtr dom,
|
|
|
|
const char *srcPath,
|
|
|
|
const char *devAlias,
|
|
|
|
int action,
|
|
|
|
const char *reason)
|
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
|
|
|
{
|
|
|
|
return virDomainEventIOErrorNewFromDomImpl(VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON,
|
|
|
|
dom, srcPath, devAlias,
|
|
|
|
action, reason);
|
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventIOErrorReasonNewFromObj(virDomainObjPtr obj,
|
|
|
|
const char *srcPath,
|
|
|
|
const char *devAlias,
|
|
|
|
int action,
|
|
|
|
const char *reason)
|
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
|
|
|
{
|
|
|
|
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
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventGraphicsNewFromDom(virDomainPtr dom,
|
|
|
|
int phase,
|
|
|
|
virDomainEventGraphicsAddressPtr local,
|
|
|
|
virDomainEventGraphicsAddressPtr remote,
|
|
|
|
const char *authScheme,
|
|
|
|
virDomainEventGraphicsSubjectPtr subject)
|
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
|
|
|
{
|
2013-11-22 09:32:51 +00:00
|
|
|
virDomainEventGraphicsPtr ev;
|
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
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 09:32:51 +00:00
|
|
|
if (!(ev = virDomainEventNew(virDomainEventGraphicsClass,
|
2013-11-22 08:00:01 +00:00
|
|
|
VIR_DOMAIN_EVENT_ID_GRAPHICS,
|
|
|
|
dom->id, dom->name, dom->uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 09:32:51 +00:00
|
|
|
ev->phase = phase;
|
|
|
|
if (VIR_STRDUP(ev->authScheme, authScheme) < 0) {
|
2013-11-21 16:04:33 +00:00
|
|
|
virObjectUnref(ev);
|
|
|
|
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
|
|
|
}
|
2013-11-22 09:32:51 +00:00
|
|
|
ev->local = local;
|
|
|
|
ev->remote = remote;
|
|
|
|
ev->subject = subject;
|
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
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
return (virObjectEventPtr)ev;
|
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
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventGraphicsNewFromObj(virDomainObjPtr obj,
|
|
|
|
int phase,
|
|
|
|
virDomainEventGraphicsAddressPtr local,
|
|
|
|
virDomainEventGraphicsAddressPtr remote,
|
|
|
|
const char *authScheme,
|
|
|
|
virDomainEventGraphicsSubjectPtr subject)
|
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
|
|
|
{
|
2013-11-22 09:32:51 +00:00
|
|
|
virDomainEventGraphicsPtr ev;
|
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
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 09:32:51 +00:00
|
|
|
if (!(ev = virDomainEventNew(virDomainEventGraphicsClass,
|
2013-11-22 08:00:01 +00:00
|
|
|
VIR_DOMAIN_EVENT_ID_GRAPHICS,
|
|
|
|
obj->def->id, obj->def->name,
|
|
|
|
obj->def->uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 09:32:51 +00:00
|
|
|
ev->phase = phase;
|
|
|
|
if (VIR_STRDUP(ev->authScheme, authScheme) < 0) {
|
2013-11-21 16:04:33 +00:00
|
|
|
virObjectUnref(ev);
|
|
|
|
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
|
|
|
}
|
2013-11-22 09:32:51 +00:00
|
|
|
ev->local = local;
|
|
|
|
ev->remote = remote;
|
|
|
|
ev->subject = subject;
|
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
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
return (virObjectEventPtr)ev;
|
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
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
static virObjectEventPtr
|
blockjob: use stable disk string in job event
When the block job event was first added, it was for block pull,
where the active layer of the disk remains the same name. It was
also in a day where we only cared about local files, and so we
always had a canonical absolute file name. But two things have
changed since then: we now have network disks, where determining
a single absolute string does not really make sense; and we have
two-phase jobs (copy and active commit) where the name of the
active layer changes between the first event (ready, on the old
name) and second (complete, on the pivoted name).
Adam Litke reported that having an unstable string between events
makes life harder for clients. Furthermore, all of our API that
operate on a particular disk of a domain accept multiple strings:
not only the absolute name of the active layer, but also the
destination device name (such as 'vda'). As this latter name is
stable, even for network sources, it serves as a better string
to supply in block job events.
But backwards-compatibility demands that we should not change the
name handed to users unless they explicitly request it. Therefore,
this patch adds a new event, BLOCK_JOB_2 (alas, I couldn't think of
any nicer name - but at least Migrate2 and Migrate3 are precedent
for a number suffix). We must double up on emitting both old-style
and new-style events according to what clients have registered for
(see also how IOError and IOErrorReason emits double events, but
there the difference was a larger struct rather than changed
meaning of one of the struct members).
Unfortunately, adding a new event isn't something that can easily
be broken into pieces, so the commit is rather large.
* include/libvirt/libvirt.h.in (virDomainEventID): Add a new id
for VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2.
(virConnectDomainEventBlockJobCallback): Document new semantics.
* src/conf/domain_event.c (_virDomainEventBlockJob): Rename field,
to ensure we catch all clients.
(virDomainEventBlockJobNew): Add parameter.
(virDomainEventBlockJobDispose)
(virDomainEventBlockJobNewFromObj)
(virDomainEventBlockJobNewFromDom)
(virDomainEventDispatchDefaultFunc): Adjust clients.
(virDomainEventBlockJob2NewFromObj)
(virDomainEventBlockJob2NewFromDom): New functions.
* src/conf/domain_event.h: Add new prototypes.
* src/libvirt_private.syms (domain_event.h): Export new functions.
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl): Generate two
different events.
* src/qemu/qemu_process.c (qemuProcessHandleBlockJob): Likewise.
* src/remote/remote_protocol.x
(remote_domain_event_block_job_2_msg): New struct.
(REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_2): New RPC.
* src/remote/remote_driver.c
(remoteDomainBuildEventBlockJob2): New handler.
(remoteEvents): Register new event.
* daemon/remote.c (remoteRelayDomainEventBlockJob2): New handler.
(domainEventCallbacks): Register new event.
* tools/virsh-domain.c (vshEventCallbacks): Likewise.
(vshEventBlockJobPrint): Adjust client.
* src/remote_protocol-structs: Regenerate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-14 13:18:04 +00:00
|
|
|
virDomainEventBlockJobNew(int event,
|
|
|
|
int id,
|
2013-12-11 10:38:03 +00:00
|
|
|
const char *name,
|
|
|
|
unsigned char *uuid,
|
blockjob: use stable disk string in job event
When the block job event was first added, it was for block pull,
where the active layer of the disk remains the same name. It was
also in a day where we only cared about local files, and so we
always had a canonical absolute file name. But two things have
changed since then: we now have network disks, where determining
a single absolute string does not really make sense; and we have
two-phase jobs (copy and active commit) where the name of the
active layer changes between the first event (ready, on the old
name) and second (complete, on the pivoted name).
Adam Litke reported that having an unstable string between events
makes life harder for clients. Furthermore, all of our API that
operate on a particular disk of a domain accept multiple strings:
not only the absolute name of the active layer, but also the
destination device name (such as 'vda'). As this latter name is
stable, even for network sources, it serves as a better string
to supply in block job events.
But backwards-compatibility demands that we should not change the
name handed to users unless they explicitly request it. Therefore,
this patch adds a new event, BLOCK_JOB_2 (alas, I couldn't think of
any nicer name - but at least Migrate2 and Migrate3 are precedent
for a number suffix). We must double up on emitting both old-style
and new-style events according to what clients have registered for
(see also how IOError and IOErrorReason emits double events, but
there the difference was a larger struct rather than changed
meaning of one of the struct members).
Unfortunately, adding a new event isn't something that can easily
be broken into pieces, so the commit is rather large.
* include/libvirt/libvirt.h.in (virDomainEventID): Add a new id
for VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2.
(virConnectDomainEventBlockJobCallback): Document new semantics.
* src/conf/domain_event.c (_virDomainEventBlockJob): Rename field,
to ensure we catch all clients.
(virDomainEventBlockJobNew): Add parameter.
(virDomainEventBlockJobDispose)
(virDomainEventBlockJobNewFromObj)
(virDomainEventBlockJobNewFromDom)
(virDomainEventDispatchDefaultFunc): Adjust clients.
(virDomainEventBlockJob2NewFromObj)
(virDomainEventBlockJob2NewFromDom): New functions.
* src/conf/domain_event.h: Add new prototypes.
* src/libvirt_private.syms (domain_event.h): Export new functions.
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl): Generate two
different events.
* src/qemu/qemu_process.c (qemuProcessHandleBlockJob): Likewise.
* src/remote/remote_protocol.x
(remote_domain_event_block_job_2_msg): New struct.
(REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_2): New RPC.
* src/remote/remote_driver.c
(remoteDomainBuildEventBlockJob2): New handler.
(remoteEvents): Register new event.
* daemon/remote.c (remoteRelayDomainEventBlockJob2): New handler.
(domainEventCallbacks): Register new event.
* tools/virsh-domain.c (vshEventCallbacks): Likewise.
(vshEventBlockJobPrint): Adjust client.
* src/remote_protocol-structs: Regenerate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-14 13:18:04 +00:00
|
|
|
const char *disk,
|
2013-12-11 10:38:03 +00:00
|
|
|
int type,
|
|
|
|
int status)
|
2011-07-22 05:57:42 +00:00
|
|
|
{
|
2013-11-22 09:42:49 +00:00
|
|
|
virDomainEventBlockJobPtr ev;
|
2011-07-22 05:57:42 +00:00
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 09:42:49 +00:00
|
|
|
if (!(ev = virDomainEventNew(virDomainEventBlockJobClass,
|
blockjob: use stable disk string in job event
When the block job event was first added, it was for block pull,
where the active layer of the disk remains the same name. It was
also in a day where we only cared about local files, and so we
always had a canonical absolute file name. But two things have
changed since then: we now have network disks, where determining
a single absolute string does not really make sense; and we have
two-phase jobs (copy and active commit) where the name of the
active layer changes between the first event (ready, on the old
name) and second (complete, on the pivoted name).
Adam Litke reported that having an unstable string between events
makes life harder for clients. Furthermore, all of our API that
operate on a particular disk of a domain accept multiple strings:
not only the absolute name of the active layer, but also the
destination device name (such as 'vda'). As this latter name is
stable, even for network sources, it serves as a better string
to supply in block job events.
But backwards-compatibility demands that we should not change the
name handed to users unless they explicitly request it. Therefore,
this patch adds a new event, BLOCK_JOB_2 (alas, I couldn't think of
any nicer name - but at least Migrate2 and Migrate3 are precedent
for a number suffix). We must double up on emitting both old-style
and new-style events according to what clients have registered for
(see also how IOError and IOErrorReason emits double events, but
there the difference was a larger struct rather than changed
meaning of one of the struct members).
Unfortunately, adding a new event isn't something that can easily
be broken into pieces, so the commit is rather large.
* include/libvirt/libvirt.h.in (virDomainEventID): Add a new id
for VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2.
(virConnectDomainEventBlockJobCallback): Document new semantics.
* src/conf/domain_event.c (_virDomainEventBlockJob): Rename field,
to ensure we catch all clients.
(virDomainEventBlockJobNew): Add parameter.
(virDomainEventBlockJobDispose)
(virDomainEventBlockJobNewFromObj)
(virDomainEventBlockJobNewFromDom)
(virDomainEventDispatchDefaultFunc): Adjust clients.
(virDomainEventBlockJob2NewFromObj)
(virDomainEventBlockJob2NewFromDom): New functions.
* src/conf/domain_event.h: Add new prototypes.
* src/libvirt_private.syms (domain_event.h): Export new functions.
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl): Generate two
different events.
* src/qemu/qemu_process.c (qemuProcessHandleBlockJob): Likewise.
* src/remote/remote_protocol.x
(remote_domain_event_block_job_2_msg): New struct.
(REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_2): New RPC.
* src/remote/remote_driver.c
(remoteDomainBuildEventBlockJob2): New handler.
(remoteEvents): Register new event.
* daemon/remote.c (remoteRelayDomainEventBlockJob2): New handler.
(domainEventCallbacks): Register new event.
* tools/virsh-domain.c (vshEventCallbacks): Likewise.
(vshEventBlockJobPrint): Adjust client.
* src/remote_protocol-structs: Regenerate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-14 13:18:04 +00:00
|
|
|
event,
|
2013-11-22 08:00:01 +00:00
|
|
|
id, name, uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
blockjob: use stable disk string in job event
When the block job event was first added, it was for block pull,
where the active layer of the disk remains the same name. It was
also in a day where we only cared about local files, and so we
always had a canonical absolute file name. But two things have
changed since then: we now have network disks, where determining
a single absolute string does not really make sense; and we have
two-phase jobs (copy and active commit) where the name of the
active layer changes between the first event (ready, on the old
name) and second (complete, on the pivoted name).
Adam Litke reported that having an unstable string between events
makes life harder for clients. Furthermore, all of our API that
operate on a particular disk of a domain accept multiple strings:
not only the absolute name of the active layer, but also the
destination device name (such as 'vda'). As this latter name is
stable, even for network sources, it serves as a better string
to supply in block job events.
But backwards-compatibility demands that we should not change the
name handed to users unless they explicitly request it. Therefore,
this patch adds a new event, BLOCK_JOB_2 (alas, I couldn't think of
any nicer name - but at least Migrate2 and Migrate3 are precedent
for a number suffix). We must double up on emitting both old-style
and new-style events according to what clients have registered for
(see also how IOError and IOErrorReason emits double events, but
there the difference was a larger struct rather than changed
meaning of one of the struct members).
Unfortunately, adding a new event isn't something that can easily
be broken into pieces, so the commit is rather large.
* include/libvirt/libvirt.h.in (virDomainEventID): Add a new id
for VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2.
(virConnectDomainEventBlockJobCallback): Document new semantics.
* src/conf/domain_event.c (_virDomainEventBlockJob): Rename field,
to ensure we catch all clients.
(virDomainEventBlockJobNew): Add parameter.
(virDomainEventBlockJobDispose)
(virDomainEventBlockJobNewFromObj)
(virDomainEventBlockJobNewFromDom)
(virDomainEventDispatchDefaultFunc): Adjust clients.
(virDomainEventBlockJob2NewFromObj)
(virDomainEventBlockJob2NewFromDom): New functions.
* src/conf/domain_event.h: Add new prototypes.
* src/libvirt_private.syms (domain_event.h): Export new functions.
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl): Generate two
different events.
* src/qemu/qemu_process.c (qemuProcessHandleBlockJob): Likewise.
* src/remote/remote_protocol.x
(remote_domain_event_block_job_2_msg): New struct.
(REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_2): New RPC.
* src/remote/remote_driver.c
(remoteDomainBuildEventBlockJob2): New handler.
(remoteEvents): Register new event.
* daemon/remote.c (remoteRelayDomainEventBlockJob2): New handler.
(domainEventCallbacks): Register new event.
* tools/virsh-domain.c (vshEventCallbacks): Likewise.
(vshEventBlockJobPrint): Adjust client.
* src/remote_protocol-structs: Regenerate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-14 13:18:04 +00:00
|
|
|
if (VIR_STRDUP(ev->disk, disk) < 0) {
|
2013-11-21 16:04:33 +00:00
|
|
|
virObjectUnref(ev);
|
|
|
|
return NULL;
|
2011-07-22 05:57:42 +00:00
|
|
|
}
|
2013-11-22 09:42:49 +00:00
|
|
|
ev->type = type;
|
|
|
|
ev->status = status;
|
2011-07-22 05:57:42 +00:00
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
return (virObjectEventPtr)ev;
|
2011-07-22 05:57:42 +00:00
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventBlockJobNewFromObj(virDomainObjPtr obj,
|
|
|
|
const char *path,
|
|
|
|
int type,
|
|
|
|
int status)
|
2011-07-22 05:57:42 +00:00
|
|
|
{
|
blockjob: use stable disk string in job event
When the block job event was first added, it was for block pull,
where the active layer of the disk remains the same name. It was
also in a day where we only cared about local files, and so we
always had a canonical absolute file name. But two things have
changed since then: we now have network disks, where determining
a single absolute string does not really make sense; and we have
two-phase jobs (copy and active commit) where the name of the
active layer changes between the first event (ready, on the old
name) and second (complete, on the pivoted name).
Adam Litke reported that having an unstable string between events
makes life harder for clients. Furthermore, all of our API that
operate on a particular disk of a domain accept multiple strings:
not only the absolute name of the active layer, but also the
destination device name (such as 'vda'). As this latter name is
stable, even for network sources, it serves as a better string
to supply in block job events.
But backwards-compatibility demands that we should not change the
name handed to users unless they explicitly request it. Therefore,
this patch adds a new event, BLOCK_JOB_2 (alas, I couldn't think of
any nicer name - but at least Migrate2 and Migrate3 are precedent
for a number suffix). We must double up on emitting both old-style
and new-style events according to what clients have registered for
(see also how IOError and IOErrorReason emits double events, but
there the difference was a larger struct rather than changed
meaning of one of the struct members).
Unfortunately, adding a new event isn't something that can easily
be broken into pieces, so the commit is rather large.
* include/libvirt/libvirt.h.in (virDomainEventID): Add a new id
for VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2.
(virConnectDomainEventBlockJobCallback): Document new semantics.
* src/conf/domain_event.c (_virDomainEventBlockJob): Rename field,
to ensure we catch all clients.
(virDomainEventBlockJobNew): Add parameter.
(virDomainEventBlockJobDispose)
(virDomainEventBlockJobNewFromObj)
(virDomainEventBlockJobNewFromDom)
(virDomainEventDispatchDefaultFunc): Adjust clients.
(virDomainEventBlockJob2NewFromObj)
(virDomainEventBlockJob2NewFromDom): New functions.
* src/conf/domain_event.h: Add new prototypes.
* src/libvirt_private.syms (domain_event.h): Export new functions.
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl): Generate two
different events.
* src/qemu/qemu_process.c (qemuProcessHandleBlockJob): Likewise.
* src/remote/remote_protocol.x
(remote_domain_event_block_job_2_msg): New struct.
(REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_2): New RPC.
* src/remote/remote_driver.c
(remoteDomainBuildEventBlockJob2): New handler.
(remoteEvents): Register new event.
* daemon/remote.c (remoteRelayDomainEventBlockJob2): New handler.
(domainEventCallbacks): Register new event.
* tools/virsh-domain.c (vshEventCallbacks): Likewise.
(vshEventBlockJobPrint): Adjust client.
* src/remote_protocol-structs: Regenerate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-14 13:18:04 +00:00
|
|
|
return virDomainEventBlockJobNew(VIR_DOMAIN_EVENT_ID_BLOCK_JOB,
|
|
|
|
obj->def->id, obj->def->name,
|
2011-07-22 05:57:42 +00:00
|
|
|
obj->def->uuid, path, type, status);
|
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventBlockJobNewFromDom(virDomainPtr dom,
|
|
|
|
const char *path,
|
|
|
|
int type,
|
|
|
|
int status)
|
2011-07-22 05:57:42 +00:00
|
|
|
{
|
blockjob: use stable disk string in job event
When the block job event was first added, it was for block pull,
where the active layer of the disk remains the same name. It was
also in a day where we only cared about local files, and so we
always had a canonical absolute file name. But two things have
changed since then: we now have network disks, where determining
a single absolute string does not really make sense; and we have
two-phase jobs (copy and active commit) where the name of the
active layer changes between the first event (ready, on the old
name) and second (complete, on the pivoted name).
Adam Litke reported that having an unstable string between events
makes life harder for clients. Furthermore, all of our API that
operate on a particular disk of a domain accept multiple strings:
not only the absolute name of the active layer, but also the
destination device name (such as 'vda'). As this latter name is
stable, even for network sources, it serves as a better string
to supply in block job events.
But backwards-compatibility demands that we should not change the
name handed to users unless they explicitly request it. Therefore,
this patch adds a new event, BLOCK_JOB_2 (alas, I couldn't think of
any nicer name - but at least Migrate2 and Migrate3 are precedent
for a number suffix). We must double up on emitting both old-style
and new-style events according to what clients have registered for
(see also how IOError and IOErrorReason emits double events, but
there the difference was a larger struct rather than changed
meaning of one of the struct members).
Unfortunately, adding a new event isn't something that can easily
be broken into pieces, so the commit is rather large.
* include/libvirt/libvirt.h.in (virDomainEventID): Add a new id
for VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2.
(virConnectDomainEventBlockJobCallback): Document new semantics.
* src/conf/domain_event.c (_virDomainEventBlockJob): Rename field,
to ensure we catch all clients.
(virDomainEventBlockJobNew): Add parameter.
(virDomainEventBlockJobDispose)
(virDomainEventBlockJobNewFromObj)
(virDomainEventBlockJobNewFromDom)
(virDomainEventDispatchDefaultFunc): Adjust clients.
(virDomainEventBlockJob2NewFromObj)
(virDomainEventBlockJob2NewFromDom): New functions.
* src/conf/domain_event.h: Add new prototypes.
* src/libvirt_private.syms (domain_event.h): Export new functions.
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl): Generate two
different events.
* src/qemu/qemu_process.c (qemuProcessHandleBlockJob): Likewise.
* src/remote/remote_protocol.x
(remote_domain_event_block_job_2_msg): New struct.
(REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_2): New RPC.
* src/remote/remote_driver.c
(remoteDomainBuildEventBlockJob2): New handler.
(remoteEvents): Register new event.
* daemon/remote.c (remoteRelayDomainEventBlockJob2): New handler.
(domainEventCallbacks): Register new event.
* tools/virsh-domain.c (vshEventCallbacks): Likewise.
(vshEventBlockJobPrint): Adjust client.
* src/remote_protocol-structs: Regenerate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-14 13:18:04 +00:00
|
|
|
return virDomainEventBlockJobNew(VIR_DOMAIN_EVENT_ID_BLOCK_JOB,
|
|
|
|
dom->id, dom->name, dom->uuid,
|
2011-07-22 05:57:42 +00:00
|
|
|
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
|
|
|
|
blockjob: use stable disk string in job event
When the block job event was first added, it was for block pull,
where the active layer of the disk remains the same name. It was
also in a day where we only cared about local files, and so we
always had a canonical absolute file name. But two things have
changed since then: we now have network disks, where determining
a single absolute string does not really make sense; and we have
two-phase jobs (copy and active commit) where the name of the
active layer changes between the first event (ready, on the old
name) and second (complete, on the pivoted name).
Adam Litke reported that having an unstable string between events
makes life harder for clients. Furthermore, all of our API that
operate on a particular disk of a domain accept multiple strings:
not only the absolute name of the active layer, but also the
destination device name (such as 'vda'). As this latter name is
stable, even for network sources, it serves as a better string
to supply in block job events.
But backwards-compatibility demands that we should not change the
name handed to users unless they explicitly request it. Therefore,
this patch adds a new event, BLOCK_JOB_2 (alas, I couldn't think of
any nicer name - but at least Migrate2 and Migrate3 are precedent
for a number suffix). We must double up on emitting both old-style
and new-style events according to what clients have registered for
(see also how IOError and IOErrorReason emits double events, but
there the difference was a larger struct rather than changed
meaning of one of the struct members).
Unfortunately, adding a new event isn't something that can easily
be broken into pieces, so the commit is rather large.
* include/libvirt/libvirt.h.in (virDomainEventID): Add a new id
for VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2.
(virConnectDomainEventBlockJobCallback): Document new semantics.
* src/conf/domain_event.c (_virDomainEventBlockJob): Rename field,
to ensure we catch all clients.
(virDomainEventBlockJobNew): Add parameter.
(virDomainEventBlockJobDispose)
(virDomainEventBlockJobNewFromObj)
(virDomainEventBlockJobNewFromDom)
(virDomainEventDispatchDefaultFunc): Adjust clients.
(virDomainEventBlockJob2NewFromObj)
(virDomainEventBlockJob2NewFromDom): New functions.
* src/conf/domain_event.h: Add new prototypes.
* src/libvirt_private.syms (domain_event.h): Export new functions.
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl): Generate two
different events.
* src/qemu/qemu_process.c (qemuProcessHandleBlockJob): Likewise.
* src/remote/remote_protocol.x
(remote_domain_event_block_job_2_msg): New struct.
(REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_2): New RPC.
* src/remote/remote_driver.c
(remoteDomainBuildEventBlockJob2): New handler.
(remoteEvents): Register new event.
* daemon/remote.c (remoteRelayDomainEventBlockJob2): New handler.
(domainEventCallbacks): Register new event.
* tools/virsh-domain.c (vshEventCallbacks): Likewise.
(vshEventBlockJobPrint): Adjust client.
* src/remote_protocol-structs: Regenerate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-14 13:18:04 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventBlockJob2NewFromObj(virDomainObjPtr obj,
|
|
|
|
const char *dst,
|
|
|
|
int type,
|
|
|
|
int status)
|
|
|
|
{
|
|
|
|
return virDomainEventBlockJobNew(VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2,
|
|
|
|
obj->def->id, obj->def->name,
|
|
|
|
obj->def->uuid, dst, type, status);
|
|
|
|
}
|
|
|
|
|
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventBlockJob2NewFromDom(virDomainPtr dom,
|
|
|
|
const char *dst,
|
|
|
|
int type,
|
|
|
|
int status)
|
|
|
|
{
|
|
|
|
return virDomainEventBlockJobNew(VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2,
|
|
|
|
dom->id, dom->name, dom->uuid,
|
|
|
|
dst, type, status);
|
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventControlErrorNewFromDom(virDomainPtr dom)
|
2011-05-29 12:21:53 +00:00
|
|
|
{
|
2013-11-22 14:38:05 +00:00
|
|
|
virObjectEventPtr ev;
|
2013-11-21 16:04:33 +00:00
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 08:00:01 +00:00
|
|
|
if (!(ev = virDomainEventNew(virDomainEventClass,
|
|
|
|
VIR_DOMAIN_EVENT_ID_CONTROL_ERROR,
|
|
|
|
dom->id, dom->name, dom->uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
2011-05-29 12:21:53 +00:00
|
|
|
return ev;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventControlErrorNewFromObj(virDomainObjPtr obj)
|
2011-05-29 12:21:53 +00:00
|
|
|
{
|
2013-11-22 14:38:05 +00:00
|
|
|
virObjectEventPtr ev;
|
2013-11-21 16:04:33 +00:00
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 08:00:01 +00:00
|
|
|
if (!(ev = virDomainEventNew(virDomainEventClass,
|
|
|
|
VIR_DOMAIN_EVENT_ID_CONTROL_ERROR,
|
|
|
|
obj->def->id, obj->def->name,
|
|
|
|
obj->def->uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
2011-05-29 12:21:53 +00:00
|
|
|
return ev;
|
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
static virObjectEventPtr
|
|
|
|
virDomainEventDiskChangeNew(int id,
|
|
|
|
const char *name,
|
|
|
|
unsigned char *uuid,
|
|
|
|
const char *oldSrcPath,
|
|
|
|
const char *newSrcPath,
|
|
|
|
const char *devAlias,
|
|
|
|
int reason)
|
2011-10-18 14:15:42 +00:00
|
|
|
{
|
2013-11-22 09:52:46 +00:00
|
|
|
virDomainEventDiskChangePtr ev;
|
2011-10-18 14:15:42 +00:00
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
2011-10-18 14:15:42 +00:00
|
|
|
|
2013-11-22 09:52:46 +00:00
|
|
|
if (!(ev = virDomainEventNew(virDomainEventDiskChangeClass,
|
2013-11-22 08:00:01 +00:00
|
|
|
VIR_DOMAIN_EVENT_ID_DISK_CHANGE,
|
|
|
|
id, name, uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
2011-10-18 14:15:42 +00:00
|
|
|
|
2013-11-22 09:52:46 +00:00
|
|
|
if (VIR_STRDUP(ev->devAlias, devAlias) < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
goto error;
|
2011-10-18 14:15:42 +00:00
|
|
|
|
2013-11-22 09:52:46 +00:00
|
|
|
if (VIR_STRDUP(ev->oldSrcPath, oldSrcPath) < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
goto error;
|
|
|
|
|
2013-11-22 09:52:46 +00:00
|
|
|
if (VIR_STRDUP(ev->newSrcPath, newSrcPath) < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
goto error;
|
|
|
|
|
2013-11-22 09:52:46 +00:00
|
|
|
ev->reason = reason;
|
2011-10-18 14:15:42 +00:00
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
return (virObjectEventPtr)ev;
|
2011-10-18 14:15:42 +00:00
|
|
|
|
2014-03-25 06:48:31 +00:00
|
|
|
error:
|
2013-11-21 16:04:33 +00:00
|
|
|
virObjectUnref(ev);
|
2011-10-18 14:15:42 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventDiskChangeNewFromObj(virDomainObjPtr obj,
|
|
|
|
const char *oldSrcPath,
|
|
|
|
const char *newSrcPath,
|
|
|
|
const char *devAlias,
|
|
|
|
int reason)
|
2011-10-18 14:15:42 +00:00
|
|
|
{
|
|
|
|
return virDomainEventDiskChangeNew(obj->def->id, obj->def->name,
|
|
|
|
obj->def->uuid, oldSrcPath,
|
|
|
|
newSrcPath, devAlias, reason);
|
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventDiskChangeNewFromDom(virDomainPtr dom,
|
|
|
|
const char *oldSrcPath,
|
|
|
|
const char *newSrcPath,
|
|
|
|
const char *devAlias,
|
|
|
|
int reason)
|
2011-10-18 14:15:42 +00:00
|
|
|
{
|
|
|
|
return virDomainEventDiskChangeNew(dom->id, dom->name, dom->uuid,
|
|
|
|
oldSrcPath, newSrcPath,
|
|
|
|
devAlias, reason);
|
|
|
|
}
|
2011-05-29 12:21:53 +00:00
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
static virObjectEventPtr
|
2013-12-11 10:38:03 +00:00
|
|
|
virDomainEventTrayChangeNew(int id,
|
|
|
|
const char *name,
|
2012-03-23 13:44:50 +00:00
|
|
|
unsigned char *uuid,
|
|
|
|
const char *devAlias,
|
|
|
|
int reason)
|
|
|
|
{
|
2013-11-22 10:00:45 +00:00
|
|
|
virDomainEventTrayChangePtr ev;
|
2012-03-23 13:44:50 +00:00
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
2012-03-23 13:44:50 +00:00
|
|
|
|
2013-11-22 10:00:45 +00:00
|
|
|
if (!(ev = virDomainEventNew(virDomainEventTrayChangeClass,
|
2013-11-22 08:00:01 +00:00
|
|
|
VIR_DOMAIN_EVENT_ID_TRAY_CHANGE,
|
|
|
|
id, name, uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 10:00:45 +00:00
|
|
|
if (VIR_STRDUP(ev->devAlias, devAlias) < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
goto error;
|
|
|
|
|
2013-11-22 10:00:45 +00:00
|
|
|
ev->reason = reason;
|
2012-03-23 13:44:50 +00:00
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
return (virObjectEventPtr)ev;
|
2012-03-23 13:44:50 +00:00
|
|
|
|
2014-03-25 06:48:31 +00:00
|
|
|
error:
|
2013-11-21 16:04:33 +00:00
|
|
|
virObjectUnref(ev);
|
2012-03-23 13:44:50 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventTrayChangeNewFromObj(virDomainObjPtr obj,
|
|
|
|
const char *devAlias,
|
|
|
|
int reason)
|
2012-03-23 13:44:50 +00:00
|
|
|
{
|
|
|
|
return virDomainEventTrayChangeNew(obj->def->id,
|
|
|
|
obj->def->name,
|
|
|
|
obj->def->uuid,
|
|
|
|
devAlias,
|
|
|
|
reason);
|
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventTrayChangeNewFromDom(virDomainPtr dom,
|
|
|
|
const char *devAlias,
|
|
|
|
int reason)
|
2012-03-23 13:44:50 +00:00
|
|
|
{
|
|
|
|
return virDomainEventTrayChangeNew(dom->id, dom->name, dom->uuid,
|
|
|
|
devAlias, reason);
|
|
|
|
}
|
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
static virObjectEventPtr
|
2013-12-11 10:38:03 +00:00
|
|
|
virDomainEventPMWakeupNew(int id,
|
|
|
|
const char *name,
|
2014-01-29 00:41:34 +00:00
|
|
|
unsigned char *uuid,
|
|
|
|
int reason)
|
2012-03-23 14:43:14 +00:00
|
|
|
{
|
2014-01-29 00:41:34 +00:00
|
|
|
virDomainEventPMPtr ev;
|
2013-11-21 16:04:33 +00:00
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2014-01-29 00:41:34 +00:00
|
|
|
if (!(ev = virDomainEventNew(virDomainEventPMClass,
|
2013-11-22 08:00:01 +00:00
|
|
|
VIR_DOMAIN_EVENT_ID_PMWAKEUP,
|
|
|
|
id, name, uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
2012-03-23 14:43:14 +00:00
|
|
|
|
2014-01-29 00:41:34 +00:00
|
|
|
ev->reason = reason;
|
|
|
|
return (virObjectEventPtr)ev;
|
2012-03-23 14:43:14 +00:00
|
|
|
}
|
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
virObjectEventPtr
|
2012-03-23 14:43:14 +00:00
|
|
|
virDomainEventPMWakeupNewFromObj(virDomainObjPtr obj)
|
|
|
|
{
|
|
|
|
return virDomainEventPMWakeupNew(obj->def->id,
|
|
|
|
obj->def->name,
|
2014-01-29 00:41:34 +00:00
|
|
|
obj->def->uuid,
|
|
|
|
0);
|
2012-03-23 14:43:14 +00:00
|
|
|
}
|
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
virObjectEventPtr
|
2014-01-29 00:41:34 +00:00
|
|
|
virDomainEventPMWakeupNewFromDom(virDomainPtr dom, int reason)
|
2012-03-23 14:43:14 +00:00
|
|
|
{
|
2014-01-29 00:41:34 +00:00
|
|
|
return virDomainEventPMWakeupNew(dom->id, dom->name, dom->uuid, reason);
|
2012-03-23 14:43:14 +00:00
|
|
|
}
|
2008-11-04 23:33:57 +00:00
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
static virObjectEventPtr
|
2013-12-11 10:38:03 +00:00
|
|
|
virDomainEventPMSuspendNew(int id,
|
|
|
|
const char *name,
|
2014-01-29 00:41:34 +00:00
|
|
|
unsigned char *uuid,
|
|
|
|
int reason)
|
2012-03-23 14:50:36 +00:00
|
|
|
{
|
2014-01-29 00:41:34 +00:00
|
|
|
virDomainEventPMPtr ev;
|
2013-11-21 16:04:33 +00:00
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2014-01-29 00:41:34 +00:00
|
|
|
if (!(ev = virDomainEventNew(virDomainEventPMClass,
|
2013-11-22 08:00:01 +00:00
|
|
|
VIR_DOMAIN_EVENT_ID_PMSUSPEND,
|
|
|
|
id, name, uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
2012-03-23 14:50:36 +00:00
|
|
|
|
2014-01-29 00:41:34 +00:00
|
|
|
ev->reason = reason;
|
|
|
|
return (virObjectEventPtr)ev;
|
2012-03-23 14:50:36 +00:00
|
|
|
}
|
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
virObjectEventPtr
|
2012-03-23 14:50:36 +00:00
|
|
|
virDomainEventPMSuspendNewFromObj(virDomainObjPtr obj)
|
|
|
|
{
|
|
|
|
return virDomainEventPMSuspendNew(obj->def->id,
|
|
|
|
obj->def->name,
|
2014-01-29 00:41:34 +00:00
|
|
|
obj->def->uuid,
|
|
|
|
0);
|
2012-03-23 14:50:36 +00:00
|
|
|
}
|
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
virObjectEventPtr
|
2014-01-29 00:41:34 +00:00
|
|
|
virDomainEventPMSuspendNewFromDom(virDomainPtr dom, int reason)
|
2012-03-23 14:50:36 +00:00
|
|
|
{
|
2014-01-29 00:41:34 +00:00
|
|
|
return virDomainEventPMSuspendNew(dom->id, dom->name, dom->uuid, reason);
|
2012-03-23 14:50:36 +00:00
|
|
|
}
|
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
static virObjectEventPtr
|
2013-12-11 10:38:03 +00:00
|
|
|
virDomainEventPMSuspendDiskNew(int id,
|
|
|
|
const char *name,
|
2014-01-29 00:41:34 +00:00
|
|
|
unsigned char *uuid,
|
|
|
|
int reason)
|
2012-10-12 19:13:39 +00:00
|
|
|
{
|
2014-01-29 00:41:34 +00:00
|
|
|
virDomainEventPMPtr ev;
|
2013-11-21 16:04:33 +00:00
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2014-01-29 00:41:34 +00:00
|
|
|
if (!(ev = virDomainEventNew(virDomainEventPMClass,
|
2013-11-22 08:00:01 +00:00
|
|
|
VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK,
|
|
|
|
id, name, uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
2014-01-29 00:41:34 +00:00
|
|
|
|
|
|
|
ev->reason = reason;
|
|
|
|
return (virObjectEventPtr)ev;
|
2012-10-12 19:13:39 +00:00
|
|
|
}
|
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
virObjectEventPtr
|
2012-10-12 19:13:39 +00:00
|
|
|
virDomainEventPMSuspendDiskNewFromObj(virDomainObjPtr obj)
|
|
|
|
{
|
|
|
|
return virDomainEventPMSuspendDiskNew(obj->def->id,
|
|
|
|
obj->def->name,
|
2014-01-29 00:41:34 +00:00
|
|
|
obj->def->uuid,
|
|
|
|
0);
|
2012-10-12 19:13:39 +00:00
|
|
|
}
|
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
virObjectEventPtr
|
2014-01-29 00:41:34 +00:00
|
|
|
virDomainEventPMSuspendDiskNewFromDom(virDomainPtr dom, int reason)
|
2012-10-12 19:13:39 +00:00
|
|
|
{
|
2014-01-29 00:41:34 +00:00
|
|
|
return virDomainEventPMSuspendDiskNew(dom->id, dom->name, dom->uuid,
|
|
|
|
reason);
|
2012-10-12 19:13:39 +00:00
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventBalloonChangeNewFromDom(virDomainPtr dom,
|
|
|
|
unsigned long long actual)
|
2012-07-13 09:05:17 +00:00
|
|
|
{
|
2013-11-22 10:08:20 +00:00
|
|
|
virDomainEventBalloonChangePtr ev;
|
2013-11-21 16:04:33 +00:00
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 10:08:20 +00:00
|
|
|
if (!(ev = virDomainEventNew(virDomainEventBalloonChangeClass,
|
2013-11-22 08:00:01 +00:00
|
|
|
VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE,
|
|
|
|
dom->id, dom->name, dom->uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
2012-07-13 09:05:17 +00:00
|
|
|
|
2013-11-22 10:08:20 +00:00
|
|
|
ev->actual = actual;
|
2012-07-13 09:05:17 +00:00
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
return (virObjectEventPtr)ev;
|
2012-07-13 09:05:17 +00:00
|
|
|
}
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventBalloonChangeNewFromObj(virDomainObjPtr obj,
|
|
|
|
unsigned long long actual)
|
2012-07-13 09:05:17 +00:00
|
|
|
{
|
2013-11-22 10:08:20 +00:00
|
|
|
virDomainEventBalloonChangePtr ev;
|
2013-11-21 16:04:33 +00:00
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 10:08:20 +00:00
|
|
|
if (!(ev = virDomainEventNew(virDomainEventBalloonChangeClass,
|
2013-11-22 08:00:01 +00:00
|
|
|
VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE,
|
|
|
|
obj->def->id, obj->def->name, obj->def->uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
2012-07-13 09:05:17 +00:00
|
|
|
|
2013-11-22 10:08:20 +00:00
|
|
|
ev->actual = actual;
|
2012-07-13 09:05:17 +00:00
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
return (virObjectEventPtr)ev;
|
2012-07-13 09:05:17 +00:00
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
static virObjectEventPtr
|
|
|
|
virDomainEventDeviceRemovedNew(int id,
|
|
|
|
const char *name,
|
|
|
|
unsigned char *uuid,
|
|
|
|
const char *devAlias)
|
2013-06-19 13:27:29 +00:00
|
|
|
{
|
2013-11-22 12:03:31 +00:00
|
|
|
virDomainEventDeviceRemovedPtr ev;
|
2013-06-19 13:27:29 +00:00
|
|
|
|
2013-11-26 13:32:58 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 12:03:31 +00:00
|
|
|
if (!(ev = virDomainEventNew(virDomainEventDeviceRemovedClass,
|
2013-11-22 08:00:01 +00:00
|
|
|
VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED,
|
|
|
|
id, name, uuid)))
|
2013-11-21 16:04:33 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-11-22 12:03:31 +00:00
|
|
|
if (VIR_STRDUP(ev->devAlias, devAlias) < 0)
|
2013-11-21 16:04:33 +00:00
|
|
|
goto error;
|
2013-06-19 13:27:29 +00:00
|
|
|
|
2013-11-22 14:38:05 +00:00
|
|
|
return (virObjectEventPtr)ev;
|
2013-06-19 13:27:29 +00:00
|
|
|
|
2014-03-25 06:48:31 +00:00
|
|
|
error:
|
2013-11-21 16:04:33 +00:00
|
|
|
virObjectUnref(ev);
|
2013-06-19 13:27:29 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventDeviceRemovedNewFromObj(virDomainObjPtr obj,
|
|
|
|
const char *devAlias)
|
2013-06-19 13:27:29 +00:00
|
|
|
{
|
|
|
|
return virDomainEventDeviceRemovedNew(obj->def->id, obj->def->name,
|
|
|
|
obj->def->uuid, devAlias);
|
|
|
|
}
|
|
|
|
|
2013-12-11 10:38:03 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom,
|
|
|
|
const char *devAlias)
|
2013-06-19 13:27:29 +00:00
|
|
|
{
|
|
|
|
return virDomainEventDeviceRemovedNew(dom->id, dom->name, dom->uuid,
|
|
|
|
devAlias);
|
|
|
|
}
|
|
|
|
|
2015-03-30 16:46:21 +00:00
|
|
|
static virObjectEventPtr
|
|
|
|
virDomainEventDeviceAddedNew(int id,
|
|
|
|
const char *name,
|
|
|
|
unsigned char *uuid,
|
|
|
|
const char *devAlias)
|
|
|
|
{
|
|
|
|
virDomainEventDeviceAddedPtr ev;
|
|
|
|
|
|
|
|
if (virDomainEventsInitialize() < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(ev = virDomainEventNew(virDomainEventDeviceAddedClass,
|
|
|
|
VIR_DOMAIN_EVENT_ID_DEVICE_ADDED,
|
|
|
|
id, name, uuid)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(ev->devAlias, devAlias) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
return (virObjectEventPtr)ev;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virObjectUnref(ev);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventDeviceAddedNewFromObj(virDomainObjPtr obj,
|
|
|
|
const char *devAlias)
|
|
|
|
{
|
|
|
|
return virDomainEventDeviceAddedNew(obj->def->id, obj->def->name,
|
|
|
|
obj->def->uuid, devAlias);
|
|
|
|
}
|
|
|
|
|
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventDeviceAddedNewFromDom(virDomainPtr dom,
|
|
|
|
const char *devAlias)
|
|
|
|
{
|
|
|
|
return virDomainEventDeviceAddedNew(dom->id, dom->name, dom->uuid,
|
|
|
|
devAlias);
|
|
|
|
}
|
2014-11-19 09:32:20 +00:00
|
|
|
|
2016-03-30 16:09:45 +00:00
|
|
|
|
|
|
|
static virObjectEventPtr
|
|
|
|
virDomainEventDeviceRemovalFailedNew(int id,
|
|
|
|
const char *name,
|
|
|
|
unsigned char *uuid,
|
|
|
|
const char *devAlias)
|
|
|
|
{
|
|
|
|
virDomainEventDeviceRemovalFailedPtr ev;
|
|
|
|
|
|
|
|
if (virDomainEventsInitialize() < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(ev = virDomainEventNew(virDomainEventDeviceAddedClass,
|
|
|
|
VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED,
|
|
|
|
id, name, uuid)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(ev->devAlias, devAlias) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
return (virObjectEventPtr)ev;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virObjectUnref(ev);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventDeviceRemovalFailedNewFromObj(virDomainObjPtr obj,
|
|
|
|
const char *devAlias)
|
|
|
|
{
|
|
|
|
return virDomainEventDeviceRemovalFailedNew(obj->def->id, obj->def->name,
|
|
|
|
obj->def->uuid, devAlias);
|
|
|
|
}
|
|
|
|
|
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventDeviceRemovalFailedNewFromDom(virDomainPtr dom,
|
|
|
|
const char *devAlias)
|
|
|
|
{
|
|
|
|
return virDomainEventDeviceRemovalFailedNew(dom->id, dom->name, dom->uuid,
|
|
|
|
devAlias);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-11-19 09:32:20 +00:00
|
|
|
static virObjectEventPtr
|
|
|
|
virDomainEventAgentLifecycleNew(int id,
|
|
|
|
const char *name,
|
|
|
|
const unsigned char *uuid,
|
|
|
|
int state,
|
|
|
|
int reason)
|
|
|
|
{
|
|
|
|
virDomainEventAgentLifecyclePtr ev;
|
|
|
|
|
|
|
|
if (virDomainEventsInitialize() < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(ev = virDomainEventNew(virDomainEventAgentLifecycleClass,
|
|
|
|
VIR_DOMAIN_EVENT_ID_AGENT_LIFECYCLE,
|
|
|
|
id, name, uuid)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ev->state = state;
|
|
|
|
ev->reason = reason;
|
|
|
|
|
|
|
|
return (virObjectEventPtr)ev;
|
|
|
|
}
|
|
|
|
|
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventAgentLifecycleNewFromObj(virDomainObjPtr obj,
|
|
|
|
int state,
|
|
|
|
int reason)
|
|
|
|
{
|
|
|
|
return virDomainEventAgentLifecycleNew(obj->def->id, obj->def->name,
|
|
|
|
obj->def->uuid, state, reason);
|
|
|
|
}
|
|
|
|
|
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventAgentLifecycleNewFromDom(virDomainPtr dom,
|
|
|
|
int state,
|
|
|
|
int reason)
|
|
|
|
{
|
|
|
|
return virDomainEventAgentLifecycleNew(dom->id, dom->name, dom->uuid,
|
|
|
|
state, reason);
|
|
|
|
}
|
|
|
|
|
2015-12-10 15:09:09 +00:00
|
|
|
static virObjectEventPtr
|
|
|
|
virDomainEventMigrationIterationNew(int id,
|
|
|
|
const char *name,
|
|
|
|
const unsigned char *uuid,
|
|
|
|
int iteration)
|
|
|
|
{
|
|
|
|
virDomainEventMigrationIterationPtr ev;
|
|
|
|
|
|
|
|
if (virDomainEventsInitialize() < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(ev = virDomainEventNew(virDomainEventMigrationIterationClass,
|
|
|
|
VIR_DOMAIN_EVENT_ID_MIGRATION_ITERATION,
|
|
|
|
id, name, uuid)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ev->iteration = iteration;
|
|
|
|
|
|
|
|
return (virObjectEventPtr)ev;
|
|
|
|
}
|
|
|
|
|
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventMigrationIterationNewFromObj(virDomainObjPtr obj,
|
|
|
|
int iteration)
|
|
|
|
{
|
|
|
|
return virDomainEventMigrationIterationNew(obj->def->id, obj->def->name,
|
|
|
|
obj->def->uuid, iteration);
|
|
|
|
}
|
|
|
|
|
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventMigrationIterationNewFromDom(virDomainPtr dom,
|
|
|
|
int iteration)
|
|
|
|
{
|
|
|
|
return virDomainEventMigrationIterationNew(dom->id, dom->name, dom->uuid,
|
|
|
|
iteration);
|
|
|
|
}
|
|
|
|
|
2016-02-17 20:20:11 +00:00
|
|
|
/* This function consumes @params, the caller must not free it.
|
|
|
|
*/
|
|
|
|
static virObjectEventPtr
|
|
|
|
virDomainEventJobCompletedNew(int id,
|
|
|
|
const char *name,
|
|
|
|
const unsigned char *uuid,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int nparams)
|
|
|
|
{
|
|
|
|
virDomainEventJobCompletedPtr ev;
|
|
|
|
|
|
|
|
if (virDomainEventsInitialize() < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (!(ev = virDomainEventNew(virDomainEventJobCompletedClass,
|
|
|
|
VIR_DOMAIN_EVENT_ID_JOB_COMPLETED,
|
|
|
|
id, name, uuid)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
ev->params = params;
|
|
|
|
ev->nparams = nparams;
|
|
|
|
|
|
|
|
return (virObjectEventPtr) ev;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virTypedParamsFree(params, nparams);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventJobCompletedNewFromObj(virDomainObjPtr obj,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int nparams)
|
|
|
|
{
|
|
|
|
return virDomainEventJobCompletedNew(obj->def->id, obj->def->name,
|
|
|
|
obj->def->uuid, params, nparams);
|
|
|
|
}
|
|
|
|
|
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventJobCompletedNewFromDom(virDomainPtr dom,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int nparams)
|
|
|
|
{
|
|
|
|
return virDomainEventJobCompletedNew(dom->id, dom->name, dom->uuid,
|
|
|
|
params, nparams);
|
|
|
|
}
|
|
|
|
|
2014-11-19 09:32:20 +00:00
|
|
|
|
2014-09-10 11:28:24 +00:00
|
|
|
/* This function consumes the params so caller don't have to care about
|
|
|
|
* freeing it even if error occurs. The reason is to not have to do deep
|
|
|
|
* copy of params.
|
|
|
|
*/
|
|
|
|
static virObjectEventPtr
|
|
|
|
virDomainEventTunableNew(int id,
|
|
|
|
const char *name,
|
|
|
|
unsigned char *uuid,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int nparams)
|
|
|
|
{
|
|
|
|
virDomainEventTunablePtr ev;
|
|
|
|
|
|
|
|
if (virDomainEventsInitialize() < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (!(ev = virDomainEventNew(virDomainEventTunableClass,
|
|
|
|
VIR_DOMAIN_EVENT_ID_TUNABLE,
|
|
|
|
id, name, uuid)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
ev->params = params;
|
|
|
|
ev->nparams = nparams;
|
|
|
|
|
|
|
|
return (virObjectEventPtr)ev;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virTypedParamsFree(params, nparams);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventTunableNewFromObj(virDomainObjPtr obj,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int nparams)
|
|
|
|
{
|
|
|
|
return virDomainEventTunableNew(obj->def->id,
|
|
|
|
obj->def->name,
|
|
|
|
obj->def->uuid,
|
|
|
|
params,
|
|
|
|
nparams);
|
|
|
|
}
|
|
|
|
|
|
|
|
virObjectEventPtr
|
|
|
|
virDomainEventTunableNewFromDom(virDomainPtr dom,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int nparams)
|
|
|
|
{
|
|
|
|
return virDomainEventTunableNew(dom->id,
|
|
|
|
dom->name,
|
|
|
|
dom->uuid,
|
|
|
|
params,
|
|
|
|
nparams);
|
|
|
|
}
|
|
|
|
|
2008-12-04 21:09:20 +00:00
|
|
|
|
2013-12-12 17:47:42 +00:00
|
|
|
static void
|
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
|
|
|
virDomainEventDispatchDefaultFunc(virConnectPtr conn,
|
2013-11-22 14:38:05 +00:00
|
|
|
virObjectEventPtr event,
|
2013-12-12 17:47:42 +00:00
|
|
|
virConnectObjectEventGenericCallback cb,
|
|
|
|
void *cbopaque)
|
2008-12-04 21:09:20 +00:00
|
|
|
{
|
2013-11-21 10:17:22 +00:00
|
|
|
virDomainPtr dom = virGetDomain(conn, event->meta.name, event->meta.uuid);
|
2010-03-18 14:06:09 +00:00
|
|
|
if (!dom)
|
|
|
|
return;
|
2013-11-21 10:17:22 +00:00
|
|
|
dom->id = event->meta.id;
|
2010-03-18 14:06:09 +00:00
|
|
|
|
2014-01-02 14:40:50 +00:00
|
|
|
switch ((virDomainEventID) event->eventID) {
|
2010-03-18 14:06:09 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_LIFECYCLE:
|
2013-11-21 16:48:41 +00:00
|
|
|
{
|
|
|
|
virDomainEventLifecyclePtr lifecycleEvent;
|
|
|
|
|
|
|
|
lifecycleEvent = (virDomainEventLifecyclePtr)event;
|
|
|
|
((virConnectDomainEventCallback)cb)(conn, dom,
|
|
|
|
lifecycleEvent->type,
|
|
|
|
lifecycleEvent->detail,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2010-03-18 14:06:09 +00:00
|
|
|
|
2010-03-18 15:25:38 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_REBOOT:
|
|
|
|
(cb)(conn, dom,
|
|
|
|
cbopaque);
|
2013-06-19 13:27:29 +00:00
|
|
|
goto cleanup;
|
2010-03-18 15:25:38 +00:00
|
|
|
|
2010-03-18 18:28:15 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_RTC_CHANGE:
|
2013-11-22 08:18:47 +00:00
|
|
|
{
|
|
|
|
virDomainEventRTCChangePtr rtcChangeEvent;
|
|
|
|
|
|
|
|
rtcChangeEvent = (virDomainEventRTCChangePtr)event;
|
|
|
|
((virConnectDomainEventRTCChangeCallback)cb)(conn, dom,
|
|
|
|
rtcChangeEvent->offset,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2010-03-18 18:28:15 +00:00
|
|
|
|
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:
|
2013-11-22 09:00:56 +00:00
|
|
|
{
|
|
|
|
virDomainEventWatchdogPtr watchdogEvent;
|
|
|
|
|
|
|
|
watchdogEvent = (virDomainEventWatchdogPtr)event;
|
|
|
|
((virConnectDomainEventWatchdogCallback)cb)(conn, dom,
|
|
|
|
watchdogEvent->action,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
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
|
|
|
|
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:
|
2013-11-22 09:15:35 +00:00
|
|
|
{
|
|
|
|
virDomainEventIOErrorPtr ioErrorEvent;
|
|
|
|
|
|
|
|
ioErrorEvent = (virDomainEventIOErrorPtr)event;
|
|
|
|
((virConnectDomainEventIOErrorCallback)cb)(conn, dom,
|
|
|
|
ioErrorEvent->srcPath,
|
|
|
|
ioErrorEvent->devAlias,
|
|
|
|
ioErrorEvent->action,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
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
|
|
|
|
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:
|
2013-11-22 09:15:35 +00:00
|
|
|
{
|
|
|
|
virDomainEventIOErrorPtr ioErrorEvent;
|
|
|
|
|
|
|
|
ioErrorEvent = (virDomainEventIOErrorPtr)event;
|
|
|
|
((virConnectDomainEventIOErrorReasonCallback)cb)(conn, dom,
|
|
|
|
ioErrorEvent->srcPath,
|
|
|
|
ioErrorEvent->devAlias,
|
|
|
|
ioErrorEvent->action,
|
|
|
|
ioErrorEvent->reason,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
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
|
|
|
|
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:
|
2013-11-22 09:32:51 +00:00
|
|
|
{
|
|
|
|
virDomainEventGraphicsPtr graphicsEvent;
|
|
|
|
|
|
|
|
graphicsEvent = (virDomainEventGraphicsPtr)event;
|
|
|
|
((virConnectDomainEventGraphicsCallback)cb)(conn, dom,
|
|
|
|
graphicsEvent->phase,
|
|
|
|
graphicsEvent->local,
|
|
|
|
graphicsEvent->remote,
|
|
|
|
graphicsEvent->authScheme,
|
|
|
|
graphicsEvent->subject,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
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
|
|
|
case VIR_DOMAIN_EVENT_ID_CONTROL_ERROR:
|
|
|
|
(cb)(conn, dom,
|
|
|
|
cbopaque);
|
2013-06-19 13:27:29 +00:00
|
|
|
goto cleanup;
|
2011-05-29 12:21:53 +00:00
|
|
|
|
2011-07-22 05:57:42 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_BLOCK_JOB:
|
blockjob: use stable disk string in job event
When the block job event was first added, it was for block pull,
where the active layer of the disk remains the same name. It was
also in a day where we only cared about local files, and so we
always had a canonical absolute file name. But two things have
changed since then: we now have network disks, where determining
a single absolute string does not really make sense; and we have
two-phase jobs (copy and active commit) where the name of the
active layer changes between the first event (ready, on the old
name) and second (complete, on the pivoted name).
Adam Litke reported that having an unstable string between events
makes life harder for clients. Furthermore, all of our API that
operate on a particular disk of a domain accept multiple strings:
not only the absolute name of the active layer, but also the
destination device name (such as 'vda'). As this latter name is
stable, even for network sources, it serves as a better string
to supply in block job events.
But backwards-compatibility demands that we should not change the
name handed to users unless they explicitly request it. Therefore,
this patch adds a new event, BLOCK_JOB_2 (alas, I couldn't think of
any nicer name - but at least Migrate2 and Migrate3 are precedent
for a number suffix). We must double up on emitting both old-style
and new-style events according to what clients have registered for
(see also how IOError and IOErrorReason emits double events, but
there the difference was a larger struct rather than changed
meaning of one of the struct members).
Unfortunately, adding a new event isn't something that can easily
be broken into pieces, so the commit is rather large.
* include/libvirt/libvirt.h.in (virDomainEventID): Add a new id
for VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2.
(virConnectDomainEventBlockJobCallback): Document new semantics.
* src/conf/domain_event.c (_virDomainEventBlockJob): Rename field,
to ensure we catch all clients.
(virDomainEventBlockJobNew): Add parameter.
(virDomainEventBlockJobDispose)
(virDomainEventBlockJobNewFromObj)
(virDomainEventBlockJobNewFromDom)
(virDomainEventDispatchDefaultFunc): Adjust clients.
(virDomainEventBlockJob2NewFromObj)
(virDomainEventBlockJob2NewFromDom): New functions.
* src/conf/domain_event.h: Add new prototypes.
* src/libvirt_private.syms (domain_event.h): Export new functions.
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl): Generate two
different events.
* src/qemu/qemu_process.c (qemuProcessHandleBlockJob): Likewise.
* src/remote/remote_protocol.x
(remote_domain_event_block_job_2_msg): New struct.
(REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_2): New RPC.
* src/remote/remote_driver.c
(remoteDomainBuildEventBlockJob2): New handler.
(remoteEvents): Register new event.
* daemon/remote.c (remoteRelayDomainEventBlockJob2): New handler.
(domainEventCallbacks): Register new event.
* tools/virsh-domain.c (vshEventCallbacks): Likewise.
(vshEventBlockJobPrint): Adjust client.
* src/remote_protocol-structs: Regenerate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-14 13:18:04 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2:
|
2013-11-22 09:42:49 +00:00
|
|
|
{
|
|
|
|
virDomainEventBlockJobPtr blockJobEvent;
|
|
|
|
|
|
|
|
blockJobEvent = (virDomainEventBlockJobPtr)event;
|
|
|
|
((virConnectDomainEventBlockJobCallback)cb)(conn, dom,
|
blockjob: use stable disk string in job event
When the block job event was first added, it was for block pull,
where the active layer of the disk remains the same name. It was
also in a day where we only cared about local files, and so we
always had a canonical absolute file name. But two things have
changed since then: we now have network disks, where determining
a single absolute string does not really make sense; and we have
two-phase jobs (copy and active commit) where the name of the
active layer changes between the first event (ready, on the old
name) and second (complete, on the pivoted name).
Adam Litke reported that having an unstable string between events
makes life harder for clients. Furthermore, all of our API that
operate on a particular disk of a domain accept multiple strings:
not only the absolute name of the active layer, but also the
destination device name (such as 'vda'). As this latter name is
stable, even for network sources, it serves as a better string
to supply in block job events.
But backwards-compatibility demands that we should not change the
name handed to users unless they explicitly request it. Therefore,
this patch adds a new event, BLOCK_JOB_2 (alas, I couldn't think of
any nicer name - but at least Migrate2 and Migrate3 are precedent
for a number suffix). We must double up on emitting both old-style
and new-style events according to what clients have registered for
(see also how IOError and IOErrorReason emits double events, but
there the difference was a larger struct rather than changed
meaning of one of the struct members).
Unfortunately, adding a new event isn't something that can easily
be broken into pieces, so the commit is rather large.
* include/libvirt/libvirt.h.in (virDomainEventID): Add a new id
for VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2.
(virConnectDomainEventBlockJobCallback): Document new semantics.
* src/conf/domain_event.c (_virDomainEventBlockJob): Rename field,
to ensure we catch all clients.
(virDomainEventBlockJobNew): Add parameter.
(virDomainEventBlockJobDispose)
(virDomainEventBlockJobNewFromObj)
(virDomainEventBlockJobNewFromDom)
(virDomainEventDispatchDefaultFunc): Adjust clients.
(virDomainEventBlockJob2NewFromObj)
(virDomainEventBlockJob2NewFromDom): New functions.
* src/conf/domain_event.h: Add new prototypes.
* src/libvirt_private.syms (domain_event.h): Export new functions.
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl): Generate two
different events.
* src/qemu/qemu_process.c (qemuProcessHandleBlockJob): Likewise.
* src/remote/remote_protocol.x
(remote_domain_event_block_job_2_msg): New struct.
(REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_2): New RPC.
* src/remote/remote_driver.c
(remoteDomainBuildEventBlockJob2): New handler.
(remoteEvents): Register new event.
* daemon/remote.c (remoteRelayDomainEventBlockJob2): New handler.
(domainEventCallbacks): Register new event.
* tools/virsh-domain.c (vshEventCallbacks): Likewise.
(vshEventBlockJobPrint): Adjust client.
* src/remote_protocol-structs: Regenerate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-14 13:18:04 +00:00
|
|
|
blockJobEvent->disk,
|
2013-11-22 09:42:49 +00:00
|
|
|
blockJobEvent->type,
|
|
|
|
blockJobEvent->status,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-07-22 05:57:42 +00:00
|
|
|
|
2011-10-18 14:15:42 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_DISK_CHANGE:
|
2013-11-22 09:52:46 +00:00
|
|
|
{
|
|
|
|
virDomainEventDiskChangePtr diskChangeEvent;
|
|
|
|
|
|
|
|
diskChangeEvent = (virDomainEventDiskChangePtr)event;
|
|
|
|
((virConnectDomainEventDiskChangeCallback)cb)(conn, dom,
|
|
|
|
diskChangeEvent->oldSrcPath,
|
|
|
|
diskChangeEvent->newSrcPath,
|
|
|
|
diskChangeEvent->devAlias,
|
|
|
|
diskChangeEvent->reason,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-10-18 14:15:42 +00:00
|
|
|
|
2012-03-23 13:44:50 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_TRAY_CHANGE:
|
2013-11-22 10:00:45 +00:00
|
|
|
{
|
|
|
|
virDomainEventTrayChangePtr trayChangeEvent;
|
|
|
|
|
|
|
|
trayChangeEvent = (virDomainEventTrayChangePtr)event;
|
|
|
|
((virConnectDomainEventTrayChangeCallback)cb)(conn, dom,
|
|
|
|
trayChangeEvent->devAlias,
|
|
|
|
trayChangeEvent->reason,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2012-03-23 13:44:50 +00:00
|
|
|
|
2012-03-23 14:43:14 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_PMWAKEUP:
|
2014-01-29 00:41:34 +00:00
|
|
|
{
|
|
|
|
virDomainEventPMPtr pmEvent = (virDomainEventPMPtr)event;
|
|
|
|
|
|
|
|
((virConnectDomainEventPMWakeupCallback)cb)(conn, dom,
|
|
|
|
pmEvent->reason,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2012-03-23 14:43:14 +00:00
|
|
|
|
2012-03-23 14:50:36 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_PMSUSPEND:
|
2014-01-29 00:41:34 +00:00
|
|
|
{
|
|
|
|
virDomainEventPMPtr pmEvent = (virDomainEventPMPtr)event;
|
|
|
|
|
|
|
|
((virConnectDomainEventPMSuspendCallback)cb)(conn, dom,
|
|
|
|
pmEvent->reason,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2012-03-23 14:50:36 +00:00
|
|
|
|
2012-07-13 09:05:17 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE:
|
2013-11-22 10:08:20 +00:00
|
|
|
{
|
|
|
|
virDomainEventBalloonChangePtr balloonChangeEvent;
|
|
|
|
|
|
|
|
balloonChangeEvent = (virDomainEventBalloonChangePtr)event;
|
|
|
|
((virConnectDomainEventBalloonChangeCallback)cb)(conn, dom,
|
|
|
|
balloonChangeEvent->actual,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2012-07-13 09:05:17 +00:00
|
|
|
|
2012-10-12 19:13:39 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK:
|
2014-01-29 00:41:34 +00:00
|
|
|
{
|
|
|
|
virDomainEventPMPtr pmEvent = (virDomainEventPMPtr)event;
|
|
|
|
|
|
|
|
((virConnectDomainEventPMSuspendDiskCallback)cb)(conn, dom,
|
|
|
|
pmEvent->reason,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2012-10-12 19:13:39 +00:00
|
|
|
|
2013-06-19 13:27:29 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED:
|
2013-11-22 12:03:31 +00:00
|
|
|
{
|
|
|
|
virDomainEventDeviceRemovedPtr deviceRemovedEvent;
|
|
|
|
|
|
|
|
deviceRemovedEvent = (virDomainEventDeviceRemovedPtr)event;
|
|
|
|
((virConnectDomainEventDeviceRemovedCallback)cb)(conn, dom,
|
|
|
|
deviceRemovedEvent->devAlias,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-06-19 13:27:29 +00:00
|
|
|
|
2014-09-10 11:28:24 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_TUNABLE:
|
|
|
|
{
|
|
|
|
virDomainEventTunablePtr tunableEvent;
|
|
|
|
tunableEvent = (virDomainEventTunablePtr)event;
|
|
|
|
((virConnectDomainEventTunableCallback)cb)(conn, dom,
|
|
|
|
tunableEvent->params,
|
|
|
|
tunableEvent->nparams,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-11-19 09:32:20 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_AGENT_LIFECYCLE:
|
|
|
|
{
|
|
|
|
virDomainEventAgentLifecyclePtr agentLifecycleEvent;
|
|
|
|
agentLifecycleEvent = (virDomainEventAgentLifecyclePtr)event;
|
|
|
|
((virConnectDomainEventAgentLifecycleCallback)cb)(conn, dom,
|
|
|
|
agentLifecycleEvent->state,
|
|
|
|
agentLifecycleEvent->reason,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2015-03-30 16:46:21 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_DEVICE_ADDED:
|
|
|
|
{
|
|
|
|
virDomainEventDeviceAddedPtr deviceAddedEvent;
|
|
|
|
|
|
|
|
deviceAddedEvent = (virDomainEventDeviceAddedPtr)event;
|
|
|
|
((virConnectDomainEventDeviceAddedCallback)cb)(conn, dom,
|
|
|
|
deviceAddedEvent->devAlias,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2015-12-10 15:09:09 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_MIGRATION_ITERATION:
|
|
|
|
{
|
|
|
|
virDomainEventMigrationIterationPtr ev;
|
|
|
|
|
|
|
|
ev = (virDomainEventMigrationIterationPtr) event;
|
|
|
|
((virConnectDomainEventMigrationIterationCallback)cb)(conn, dom,
|
|
|
|
ev->iteration,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-02-17 20:20:11 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_JOB_COMPLETED:
|
|
|
|
{
|
|
|
|
virDomainEventJobCompletedPtr ev;
|
|
|
|
|
|
|
|
ev = (virDomainEventJobCompletedPtr) event;
|
|
|
|
((virConnectDomainEventJobCompletedCallback) cb)(conn, dom,
|
|
|
|
ev->params,
|
|
|
|
ev->nparams,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-03-30 16:09:45 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED:
|
|
|
|
{
|
|
|
|
virDomainEventDeviceRemovalFailedPtr deviceRemovalFailedEvent;
|
|
|
|
|
|
|
|
deviceRemovalFailedEvent = (virDomainEventDeviceRemovalFailedPtr)event;
|
|
|
|
((virConnectDomainEventDeviceRemovalFailedCallback)cb)(conn, dom,
|
|
|
|
deviceRemovalFailedEvent->devAlias,
|
|
|
|
cbopaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-06-19 13:27:29 +00:00
|
|
|
case VIR_DOMAIN_EVENT_ID_LAST:
|
2010-03-18 14:06:09 +00:00
|
|
|
break;
|
2008-12-04 21:09:20 +00:00
|
|
|
}
|
2010-03-18 14:06:09 +00:00
|
|
|
|
2014-01-02 14:40:50 +00:00
|
|
|
VIR_WARN("Unexpected event ID %d", event->eventID);
|
2013-06-19 13:27:29 +00:00
|
|
|
|
2014-03-25 06:48:31 +00:00
|
|
|
cleanup:
|
2014-11-30 14:57:02 +00:00
|
|
|
virObjectUnref(dom);
|
2008-12-04 21:09:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-31 13:33:42 +00:00
|
|
|
virObjectEventPtr
|
|
|
|
virDomainQemuMonitorEventNew(int id,
|
|
|
|
const char *name,
|
|
|
|
const unsigned char *uuid,
|
|
|
|
const char *event,
|
|
|
|
long long seconds,
|
|
|
|
unsigned int micros,
|
|
|
|
const char *details)
|
|
|
|
{
|
|
|
|
virDomainQemuMonitorEventPtr ev;
|
2016-06-23 16:06:39 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
2013-12-31 13:33:42 +00:00
|
|
|
|
|
|
|
if (virDomainEventsInitialize() < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2016-06-23 16:06:39 +00:00
|
|
|
virUUIDFormat(uuid, uuidstr);
|
2013-12-31 13:33:42 +00:00
|
|
|
if (!(ev = virObjectEventNew(virDomainQemuMonitorEventClass,
|
|
|
|
virDomainQemuMonitorEventDispatchFunc,
|
2016-06-23 16:06:39 +00:00
|
|
|
0, id, name, uuid, uuidstr)))
|
2013-12-31 13:33:42 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* event is mandatory, details are optional */
|
|
|
|
if (VIR_STRDUP(ev->event, event) <= 0)
|
|
|
|
goto error;
|
|
|
|
ev->seconds = seconds;
|
|
|
|
ev->micros = micros;
|
|
|
|
if (VIR_STRDUP(ev->details, details) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
return (virObjectEventPtr)ev;
|
|
|
|
|
2014-03-25 06:48:31 +00:00
|
|
|
error:
|
2013-12-31 13:33:42 +00:00
|
|
|
virObjectUnref(ev);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
qemu: enable monitor event filtering by name
Filtering monitor events by name requires tracking the name for
the duration of the filtering. In order to free the name, I
found it easiest to just piggyback on the user's freecb function,
which gets called when the event is deregistered.
For events without a name filter, we have the design of multiple
client registrations sharing a common server registration, because
the server side uses the same callback function and we reject
duplicate use of the same function. But with events in the mix,
we want to be able to allow the same function pointer to be used
with more than one event name. The solution is to tweak the
duplicate detection code to only act when there is no additional
filtering; if name filtering is in use, there is exactly one
client registration per server registration. Yes, this means
that there is no longer a bound on the number of server
registrations possible, so a malicious client could repeatedly
register for the same name event to exhaust server memory. On
the other hand, we already restricted monitor events to require
write access (compared to normal events only needing read access),
and separated it into the intentionally unsupported
libvirt-qemu.so, with documentation that using this function is
for debug purposes only; so it is not a security risk worth
worrying about a client trying to abuse multiple registrations.
* src/conf/domain_event.c (virDomainQemuMonitorEventData): New
struct.
(virDomainQemuMonitorEventFilter)
(virDomainQemuMonitorEventCleanup): New functions.
(virDomainQemuMonitorEventDispatchFunc)
(virDomainQemuMonitorEventStateRegisterID): Use new struct.
* src/conf/object_event.c (virObjectEventCallbackListCount)
(virObjectEventCallbackListAddID)
(virObjectEventCallbackListRemoveID)
(virObjectEventCallbackListMarkDeleteID): Drop duplicate detection
when filtering is in effect.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-31 14:02:25 +00:00
|
|
|
/* In order to filter by event name, we need to store a copy of the
|
|
|
|
* name to filter on. By wrapping the caller's freecb, we can
|
|
|
|
* piggyback our cleanup to happen at the same time the caller
|
|
|
|
* deregisters. */
|
|
|
|
struct virDomainQemuMonitorEventData {
|
|
|
|
char *event;
|
2014-02-06 21:46:52 +00:00
|
|
|
regex_t regex;
|
|
|
|
unsigned int flags;
|
qemu: enable monitor event filtering by name
Filtering monitor events by name requires tracking the name for
the duration of the filtering. In order to free the name, I
found it easiest to just piggyback on the user's freecb function,
which gets called when the event is deregistered.
For events without a name filter, we have the design of multiple
client registrations sharing a common server registration, because
the server side uses the same callback function and we reject
duplicate use of the same function. But with events in the mix,
we want to be able to allow the same function pointer to be used
with more than one event name. The solution is to tweak the
duplicate detection code to only act when there is no additional
filtering; if name filtering is in use, there is exactly one
client registration per server registration. Yes, this means
that there is no longer a bound on the number of server
registrations possible, so a malicious client could repeatedly
register for the same name event to exhaust server memory. On
the other hand, we already restricted monitor events to require
write access (compared to normal events only needing read access),
and separated it into the intentionally unsupported
libvirt-qemu.so, with documentation that using this function is
for debug purposes only; so it is not a security risk worth
worrying about a client trying to abuse multiple registrations.
* src/conf/domain_event.c (virDomainQemuMonitorEventData): New
struct.
(virDomainQemuMonitorEventFilter)
(virDomainQemuMonitorEventCleanup): New functions.
(virDomainQemuMonitorEventDispatchFunc)
(virDomainQemuMonitorEventStateRegisterID): Use new struct.
* src/conf/object_event.c (virObjectEventCallbackListCount)
(virObjectEventCallbackListAddID)
(virObjectEventCallbackListRemoveID)
(virObjectEventCallbackListMarkDeleteID): Drop duplicate detection
when filtering is in effect.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-31 14:02:25 +00:00
|
|
|
void *opaque;
|
|
|
|
virFreeCallback freecb;
|
|
|
|
};
|
|
|
|
typedef struct virDomainQemuMonitorEventData virDomainQemuMonitorEventData;
|
|
|
|
|
|
|
|
|
2013-12-31 13:33:42 +00:00
|
|
|
static void
|
|
|
|
virDomainQemuMonitorEventDispatchFunc(virConnectPtr conn,
|
|
|
|
virObjectEventPtr event,
|
|
|
|
virConnectObjectEventGenericCallback cb,
|
|
|
|
void *cbopaque)
|
|
|
|
{
|
|
|
|
virDomainPtr dom = virGetDomain(conn, event->meta.name, event->meta.uuid);
|
|
|
|
virDomainQemuMonitorEventPtr qemuMonitorEvent;
|
qemu: enable monitor event filtering by name
Filtering monitor events by name requires tracking the name for
the duration of the filtering. In order to free the name, I
found it easiest to just piggyback on the user's freecb function,
which gets called when the event is deregistered.
For events without a name filter, we have the design of multiple
client registrations sharing a common server registration, because
the server side uses the same callback function and we reject
duplicate use of the same function. But with events in the mix,
we want to be able to allow the same function pointer to be used
with more than one event name. The solution is to tweak the
duplicate detection code to only act when there is no additional
filtering; if name filtering is in use, there is exactly one
client registration per server registration. Yes, this means
that there is no longer a bound on the number of server
registrations possible, so a malicious client could repeatedly
register for the same name event to exhaust server memory. On
the other hand, we already restricted monitor events to require
write access (compared to normal events only needing read access),
and separated it into the intentionally unsupported
libvirt-qemu.so, with documentation that using this function is
for debug purposes only; so it is not a security risk worth
worrying about a client trying to abuse multiple registrations.
* src/conf/domain_event.c (virDomainQemuMonitorEventData): New
struct.
(virDomainQemuMonitorEventFilter)
(virDomainQemuMonitorEventCleanup): New functions.
(virDomainQemuMonitorEventDispatchFunc)
(virDomainQemuMonitorEventStateRegisterID): Use new struct.
* src/conf/object_event.c (virObjectEventCallbackListCount)
(virObjectEventCallbackListAddID)
(virObjectEventCallbackListRemoveID)
(virObjectEventCallbackListMarkDeleteID): Drop duplicate detection
when filtering is in effect.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-31 14:02:25 +00:00
|
|
|
virDomainQemuMonitorEventData *data = cbopaque;
|
2013-12-31 13:33:42 +00:00
|
|
|
|
|
|
|
if (!dom)
|
|
|
|
return;
|
|
|
|
dom->id = event->meta.id;
|
|
|
|
|
|
|
|
qemuMonitorEvent = (virDomainQemuMonitorEventPtr)event;
|
|
|
|
((virConnectDomainQemuMonitorEventCallback)cb)(conn, dom,
|
|
|
|
qemuMonitorEvent->event,
|
|
|
|
qemuMonitorEvent->seconds,
|
|
|
|
qemuMonitorEvent->micros,
|
|
|
|
qemuMonitorEvent->details,
|
qemu: enable monitor event filtering by name
Filtering monitor events by name requires tracking the name for
the duration of the filtering. In order to free the name, I
found it easiest to just piggyback on the user's freecb function,
which gets called when the event is deregistered.
For events without a name filter, we have the design of multiple
client registrations sharing a common server registration, because
the server side uses the same callback function and we reject
duplicate use of the same function. But with events in the mix,
we want to be able to allow the same function pointer to be used
with more than one event name. The solution is to tweak the
duplicate detection code to only act when there is no additional
filtering; if name filtering is in use, there is exactly one
client registration per server registration. Yes, this means
that there is no longer a bound on the number of server
registrations possible, so a malicious client could repeatedly
register for the same name event to exhaust server memory. On
the other hand, we already restricted monitor events to require
write access (compared to normal events only needing read access),
and separated it into the intentionally unsupported
libvirt-qemu.so, with documentation that using this function is
for debug purposes only; so it is not a security risk worth
worrying about a client trying to abuse multiple registrations.
* src/conf/domain_event.c (virDomainQemuMonitorEventData): New
struct.
(virDomainQemuMonitorEventFilter)
(virDomainQemuMonitorEventCleanup): New functions.
(virDomainQemuMonitorEventDispatchFunc)
(virDomainQemuMonitorEventStateRegisterID): Use new struct.
* src/conf/object_event.c (virObjectEventCallbackListCount)
(virObjectEventCallbackListAddID)
(virObjectEventCallbackListRemoveID)
(virObjectEventCallbackListMarkDeleteID): Drop duplicate detection
when filtering is in effect.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-31 14:02:25 +00:00
|
|
|
data->opaque);
|
2014-11-30 14:57:02 +00:00
|
|
|
virObjectUnref(dom);
|
2013-12-31 13:33:42 +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
|
2013-11-21 10:43:10 +00:00
|
|
|
* @state: object event state
|
2014-01-02 14:16:49 +00:00
|
|
|
* @callback: the callback to add
|
|
|
|
* @opaque: data blob to pass to @callback
|
2011-12-13 23:38:54 +00:00
|
|
|
* @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,
|
2013-11-21 10:43:10 +00:00
|
|
|
virObjectEventStatePtr state,
|
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
|
|
|
virConnectDomainEventCallback callback,
|
|
|
|
void *opaque,
|
|
|
|
virFreeCallback freecb)
|
2011-12-13 23:38:54 +00:00
|
|
|
{
|
2014-01-08 04:00:54 +00:00
|
|
|
int callbackID;
|
|
|
|
|
2013-12-11 14:10:34 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
|
|
|
return -1;
|
|
|
|
|
event: don't turn offline domain into global event
If a user registers for a domain event filtered to a particular
domain, but the persistent domain is offline at the time, then
the code silently failed to set up the filter. As a result,
the event fires for all domains, rather than being filtered.
Network events were immune, since they always passed an id
0 argument.
The key to this patch is realizing that
virObjectEventDispatchMatchCallback() only cared about uuid;
so refusing to create a meta for a negative id is pointless,
and in fact, malloc'ing meta at all was overkill; instead,
just directly store a uuid and a flag of whether to filter.
Note that virObjectEventPtr still needs all fields of meta,
because this is how we reconstruct a virDomainPtr inside the
dispatch handler before calling the end user's callback
pointer with the correct object, even though only the uuid
portion of meta is used in deciding whether a callback
matches the given event. So while uuid is optional for
callbacks, it is mandatory for events.
The change to testDomainCreateXMLMixed is merely on the setup
scenario (as you can't register for a domain unless it is either
running or persistent). I actually first wrote that test for
this patch, then rebased it to also cover a prior patch (commit
4221d64), but had to adjust it for that patch to use Create
instead of Define for setting up the domain long enough to
register the event in order to work around this bug. But while
the setup is changed, the main body of the test is still about
whether creation events fire as expected.
* src/conf/object_event_private.h (_virObjectEventCallback):
Replace meta with uuid and flag.
(virObjectEventCallbackListAddID): Update signature.
* src/conf/object_event.h (virObjectEventStateRegisterID):
Likewise.
* src/conf/object_event_private.h (virObjectEventNew): Document
use of name and uuid in events.
* src/conf/object_event.c (virObjectEventCallbackListAddID): Drop
arguments that don't affect filtering.
(virObjectEventCallbackListRemoveID)
(virObjectEventDispatchMatchCallback)
(virObjectEventStateRegisterID): Update clients.
* src/conf/domain_event.c (virDomainEventCallbackListAdd)
(virDomainEventStateRegisterID): Likewise.
* src/conf/network_event.c (virNetworkEventStateRegisterID):
Likewise.
* tests/objecteventtest.c (testDomainCreateXMLMixed): Enhance test.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-04 00:02:17 +00:00
|
|
|
return virObjectEventStateRegisterID(conn, state, NULL,
|
event: move event filtering to daemon (regression fix)
https://bugzilla.redhat.com/show_bug.cgi?id=1058839
Commit f9f56340 for CVE-2014-0028 almost had the right idea - we
need to check the ACL rules to filter which events to send. But
it overlooked one thing: the event dispatch queue is running in
the main loop thread, and therefore does not normally have a
current virIdentityPtr. But filter checks can be based on current
identity, so when libvirtd.conf contains access_drivers=["polkit"],
we ended up rejecting access for EVERY event due to failure to
look up the current identity, even if it should have been allowed.
Furthermore, even for events that are triggered by API calls, it
is important to remember that the point of events is that they can
be copied across multiple connections, which may have separate
identities and permissions. So even if events were dispatched
from a context where we have an identity, we must change to the
correct identity of the connection that will be receiving the
event, rather than basing a decision on the context that triggered
the event, when deciding whether to filter an event to a
particular connection.
If there were an easy way to get from virConnectPtr to the
appropriate virIdentityPtr, then object_event.c could adjust the
identity prior to checking whether to dispatch an event. But
setting up that back-reference is a bit invasive. Instead, it
is easier to delay the filtering check until lower down the
stack, at the point where we have direct access to the RPC
client object that owns an identity. As such, this patch ends
up reverting a large portion of the framework of commit f9f56340.
We also have to teach 'make check' to special-case the fact that
the event registration filtering is done at the point of dispatch,
rather than the point of registration. Note that even though we
don't actually use virConnectDomainEventRegisterCheckACL (because
the RegisterAny variant is sufficient), we still generate the
function for the purposes of documenting that the filtering
takes place.
Also note that I did not entirely delete the notion of a filter
from object_event.c; I still plan on using that for my upcoming
patch series for qemu monitor events in libvirt-qemu.so. In
other words, while this patch changes ACL filtering to live in
remote.c and therefore we have no current client of the filtering
in object_event.c, the notion of filtering in object_event.c is
still useful down the road.
* src/check-aclrules.pl: Exempt event registration from having to
pass checkACL filter down call stack.
* daemon/remote.c (remoteRelayDomainEventCheckACL)
(remoteRelayNetworkEventCheckACL): New functions.
(remoteRelay*Event*): Use new functions.
* src/conf/domain_event.h (virDomainEventStateRegister)
(virDomainEventStateRegisterID): Drop unused parameter.
* src/conf/network_event.h (virNetworkEventStateRegisterID):
Likewise.
* src/conf/domain_event.c (virDomainEventFilter): Delete unused
function.
* src/conf/network_event.c (virNetworkEventFilter): Likewise.
* src/libxl/libxl_driver.c: Adjust caller.
* src/lxc/lxc_driver.c: Likewise.
* src/network/bridge_driver.c: Likewise.
* src/qemu/qemu_driver.c: Likewise.
* src/remote/remote_driver.c: Likewise.
* src/test/test_driver.c: Likewise.
* src/uml/uml_driver.c: Likewise.
* src/vbox/vbox_tmpl.c: Likewise.
* src/xen/xen_driver.c: Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-28 21:50:02 +00:00
|
|
|
NULL, NULL, virDomainEventClass,
|
event: don't let old-style events clobber per-domain events
Right now, the older virConnectDomainEventRegister (takes a
function pointer, returns 0 on success) and the newer
virConnectDomainEventRegisterID (takes an eventID, returns a
callbackID) share the underlying implementation (the older
API ends up consuming a callbackID for eventID 0 under the
hood). We implemented that by a lot of copy and pasted
code between object_event.c and domain_event.c, according to
whether we are dealing with a function pointer or an eventID.
However, our copy and paste is not symmetric. Consider this
sequence:
id1 = virConnectDomainEventRegisterAny(conn, dom,
VIR_DOMAIN_EVENT_ID_LIFECYCLE,
VIR_DOMAIN_EVENT_CALLBACK(callback), NULL, NULL);
virConnectDomainEventRegister(conn, callback, NULL, NULL);
virConnectDomainEventDeregister(conn, callback);
virConnectDomainEventDeregsiterAny(conn, id1);
the first three calls would succeed, but the third call ended
up nuking the id1 callbackID (the per-domain new-style handler),
then the fourth call failed with an error about an unknown
callbackID, leaving us with the global handler (old-style) still
live and receiving events. It required another old-style
deregister to clean up the mess. Root cause was that
virDomainEventCallbackList{Remove,MarkDelete} were only
checking for function pointer match, rather than also checking
for whether the registration was global.
Rather than playing with the guts of object_event ourselves
in domain_event, it is nicer to add a mapping function for the
internal callback id, then share common code for event removal.
For now, the function-to-id mapping is used only internally;
I thought about whether a new public API to let a user learn
the callback would be useful, but decided exposing this to the
user is probably a disservice, since we already publicly
document that they should avoid the old style, and since this
patch already demonstrates that older libvirt versions have
weird behavior when mixing old and new styles.
And like all good bug fix patches, I enhanced the testsuite,
validating that the changes in tests/ expose the failure
without the rest of the patch.
* src/conf/object_event.c (virObjectEventCallbackLookup)
(virObjectEventStateCallbackID): New functions.
(virObjectEventCallbackLookup): Use helper function.
* src/conf/object_event_private.h (virObjectEventStateCallbackID):
Declare new function.
* src/conf/domain_event.c (virDomainEventStateRegister)
(virDomainEventStateDeregister): Let common code handle the
complexity.
(virDomainEventCallbackListRemove)
(virDomainEventCallbackListMarkDelete)
(virDomainEventCallbackListAdd): Drop unused functions.
* tests/objecteventtest.c (testDomainCreateXMLMixed): New test.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-03 23:50:14 +00:00
|
|
|
VIR_DOMAIN_EVENT_ID_LIFECYCLE,
|
|
|
|
VIR_OBJECT_EVENT_CALLBACK(callback),
|
2014-01-08 04:00:54 +00:00
|
|
|
opaque, freecb,
|
|
|
|
true, &callbackID, false);
|
2011-12-13 23:38:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virDomainEventStateRegisterID:
|
|
|
|
* @conn: connection to associate with callback
|
2013-11-21 10:43:10 +00:00
|
|
|
* @state: object event state
|
2014-01-02 14:16:49 +00:00
|
|
|
* @dom: optional domain for filtering the event
|
2011-12-13 23:38:54 +00:00
|
|
|
* @eventID: ID of the event type to register for
|
2014-01-02 14:16:49 +00:00
|
|
|
* @cb: function to invoke when event fires
|
|
|
|
* @opaque: data blob to pass to @callback
|
2011-12-13 23:38:54 +00:00
|
|
|
* @freecb: callback to free @opaque
|
|
|
|
* @callbackID: filled with callback ID
|
|
|
|
*
|
2014-01-02 14:16:49 +00:00
|
|
|
* Register the function @cb with connection @conn, from @state, for
|
|
|
|
* events of type @eventID, and return the registration handle in
|
|
|
|
* @callbackID.
|
2011-12-13 23:38:54 +00:00
|
|
|
*
|
|
|
|
* 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,
|
2013-11-21 10:43:10 +00:00
|
|
|
virObjectEventStatePtr state,
|
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
|
|
|
virDomainPtr dom,
|
|
|
|
int eventID,
|
|
|
|
virConnectDomainEventGenericCallback cb,
|
|
|
|
void *opaque,
|
|
|
|
virFreeCallback freecb,
|
|
|
|
int *callbackID)
|
2011-12-13 23:38:54 +00:00
|
|
|
{
|
2016-06-23 15:50:05 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
|
2013-12-11 14:10:34 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
|
|
|
return -1;
|
|
|
|
|
2016-06-23 15:50:05 +00:00
|
|
|
if (dom)
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
|
|
|
return virObjectEventStateRegisterID(conn, state, dom ? uuidstr : NULL,
|
event: move event filtering to daemon (regression fix)
https://bugzilla.redhat.com/show_bug.cgi?id=1058839
Commit f9f56340 for CVE-2014-0028 almost had the right idea - we
need to check the ACL rules to filter which events to send. But
it overlooked one thing: the event dispatch queue is running in
the main loop thread, and therefore does not normally have a
current virIdentityPtr. But filter checks can be based on current
identity, so when libvirtd.conf contains access_drivers=["polkit"],
we ended up rejecting access for EVERY event due to failure to
look up the current identity, even if it should have been allowed.
Furthermore, even for events that are triggered by API calls, it
is important to remember that the point of events is that they can
be copied across multiple connections, which may have separate
identities and permissions. So even if events were dispatched
from a context where we have an identity, we must change to the
correct identity of the connection that will be receiving the
event, rather than basing a decision on the context that triggered
the event, when deciding whether to filter an event to a
particular connection.
If there were an easy way to get from virConnectPtr to the
appropriate virIdentityPtr, then object_event.c could adjust the
identity prior to checking whether to dispatch an event. But
setting up that back-reference is a bit invasive. Instead, it
is easier to delay the filtering check until lower down the
stack, at the point where we have direct access to the RPC
client object that owns an identity. As such, this patch ends
up reverting a large portion of the framework of commit f9f56340.
We also have to teach 'make check' to special-case the fact that
the event registration filtering is done at the point of dispatch,
rather than the point of registration. Note that even though we
don't actually use virConnectDomainEventRegisterCheckACL (because
the RegisterAny variant is sufficient), we still generate the
function for the purposes of documenting that the filtering
takes place.
Also note that I did not entirely delete the notion of a filter
from object_event.c; I still plan on using that for my upcoming
patch series for qemu monitor events in libvirt-qemu.so. In
other words, while this patch changes ACL filtering to live in
remote.c and therefore we have no current client of the filtering
in object_event.c, the notion of filtering in object_event.c is
still useful down the road.
* src/check-aclrules.pl: Exempt event registration from having to
pass checkACL filter down call stack.
* daemon/remote.c (remoteRelayDomainEventCheckACL)
(remoteRelayNetworkEventCheckACL): New functions.
(remoteRelay*Event*): Use new functions.
* src/conf/domain_event.h (virDomainEventStateRegister)
(virDomainEventStateRegisterID): Drop unused parameter.
* src/conf/network_event.h (virNetworkEventStateRegisterID):
Likewise.
* src/conf/domain_event.c (virDomainEventFilter): Delete unused
function.
* src/conf/network_event.c (virNetworkEventFilter): Likewise.
* src/libxl/libxl_driver.c: Adjust caller.
* src/lxc/lxc_driver.c: Likewise.
* src/network/bridge_driver.c: Likewise.
* src/qemu/qemu_driver.c: Likewise.
* src/remote/remote_driver.c: Likewise.
* src/test/test_driver.c: Likewise.
* src/uml/uml_driver.c: Likewise.
* src/vbox/vbox_tmpl.c: Likewise.
* src/xen/xen_driver.c: Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-28 21:50:02 +00:00
|
|
|
NULL, NULL,
|
|
|
|
virDomainEventClass, eventID,
|
event: don't turn offline domain into global event
If a user registers for a domain event filtered to a particular
domain, but the persistent domain is offline at the time, then
the code silently failed to set up the filter. As a result,
the event fires for all domains, rather than being filtered.
Network events were immune, since they always passed an id
0 argument.
The key to this patch is realizing that
virObjectEventDispatchMatchCallback() only cared about uuid;
so refusing to create a meta for a negative id is pointless,
and in fact, malloc'ing meta at all was overkill; instead,
just directly store a uuid and a flag of whether to filter.
Note that virObjectEventPtr still needs all fields of meta,
because this is how we reconstruct a virDomainPtr inside the
dispatch handler before calling the end user's callback
pointer with the correct object, even though only the uuid
portion of meta is used in deciding whether a callback
matches the given event. So while uuid is optional for
callbacks, it is mandatory for events.
The change to testDomainCreateXMLMixed is merely on the setup
scenario (as you can't register for a domain unless it is either
running or persistent). I actually first wrote that test for
this patch, then rebased it to also cover a prior patch (commit
4221d64), but had to adjust it for that patch to use Create
instead of Define for setting up the domain long enough to
register the event in order to work around this bug. But while
the setup is changed, the main body of the test is still about
whether creation events fire as expected.
* src/conf/object_event_private.h (_virObjectEventCallback):
Replace meta with uuid and flag.
(virObjectEventCallbackListAddID): Update signature.
* src/conf/object_event.h (virObjectEventStateRegisterID):
Likewise.
* src/conf/object_event_private.h (virObjectEventNew): Document
use of name and uuid in events.
* src/conf/object_event.c (virObjectEventCallbackListAddID): Drop
arguments that don't affect filtering.
(virObjectEventCallbackListRemoveID)
(virObjectEventDispatchMatchCallback)
(virObjectEventStateRegisterID): Update clients.
* src/conf/domain_event.c (virDomainEventCallbackListAdd)
(virDomainEventStateRegisterID): Likewise.
* src/conf/network_event.c (virNetworkEventStateRegisterID):
Likewise.
* tests/objecteventtest.c (testDomainCreateXMLMixed): Enhance test.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-04 00:02:17 +00:00
|
|
|
VIR_OBJECT_EVENT_CALLBACK(cb),
|
2014-01-08 04:00:54 +00:00
|
|
|
opaque, freecb,
|
|
|
|
false, callbackID, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virDomainEventStateRegisterClient:
|
|
|
|
* @conn: connection to associate with callback
|
|
|
|
* @state: object event state
|
|
|
|
* @dom: optional domain for filtering the event
|
|
|
|
* @eventID: ID of the event type to register for
|
|
|
|
* @cb: function to invoke when event fires
|
|
|
|
* @opaque: data blob to pass to @callback
|
|
|
|
* @freecb: callback to free @opaque
|
|
|
|
* @legacy: true if callback is tracked by function instead of callbackID
|
|
|
|
* @callbackID: filled with callback ID
|
|
|
|
* @remoteID: true if server supports filtering
|
|
|
|
*
|
|
|
|
* Register the function @cb with connection @conn, from @state, for
|
|
|
|
* events of type @eventID, and return the registration handle in
|
|
|
|
* @callbackID. This version is intended for use on the client side
|
|
|
|
* of RPC.
|
|
|
|
*
|
|
|
|
* Returns: the number of callbacks now registered, or -1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virDomainEventStateRegisterClient(virConnectPtr conn,
|
|
|
|
virObjectEventStatePtr state,
|
|
|
|
virDomainPtr dom,
|
|
|
|
int eventID,
|
|
|
|
virConnectDomainEventGenericCallback cb,
|
|
|
|
void *opaque,
|
|
|
|
virFreeCallback freecb,
|
|
|
|
bool legacy,
|
|
|
|
int *callbackID,
|
|
|
|
bool remoteID)
|
|
|
|
{
|
2016-06-23 15:50:05 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
|
2014-01-08 04:00:54 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
|
|
|
return -1;
|
|
|
|
|
2016-06-23 15:50:05 +00:00
|
|
|
if (dom)
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
|
|
|
return virObjectEventStateRegisterID(conn, state, dom ? uuidstr : NULL,
|
2014-01-08 04:00:54 +00:00
|
|
|
NULL, NULL,
|
|
|
|
virDomainEventClass, eventID,
|
|
|
|
VIR_OBJECT_EVENT_CALLBACK(cb),
|
|
|
|
opaque, freecb,
|
|
|
|
legacy, callbackID, remoteID);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virDomainEventStateCallbackID:
|
|
|
|
* @conn: connection associated with callback
|
|
|
|
* @state: object event state
|
|
|
|
* @cb: function registered as a callback with virDomainEventStateRegister()
|
|
|
|
* @remoteID: associated remote id of the callback
|
|
|
|
*
|
|
|
|
* Returns the callbackID of @cb, or -1 with an error issued if the
|
|
|
|
* function is not currently registered.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virDomainEventStateCallbackID(virConnectPtr conn,
|
|
|
|
virObjectEventStatePtr state,
|
|
|
|
virConnectDomainEventCallback cb,
|
|
|
|
int *remoteID)
|
|
|
|
{
|
|
|
|
return virObjectEventStateCallbackID(conn, state, virDomainEventClass,
|
|
|
|
VIR_DOMAIN_EVENT_ID_LIFECYCLE,
|
|
|
|
VIR_OBJECT_EVENT_CALLBACK(cb),
|
|
|
|
remoteID);
|
2011-12-13 23:38:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virDomainEventStateDeregister:
|
2011-12-13 10:39:17 +00:00
|
|
|
* @conn: connection to associate with callback
|
2013-11-21 10:43:10 +00:00
|
|
|
* @state: object event state
|
event: don't let old-style events clobber per-domain events
Right now, the older virConnectDomainEventRegister (takes a
function pointer, returns 0 on success) and the newer
virConnectDomainEventRegisterID (takes an eventID, returns a
callbackID) share the underlying implementation (the older
API ends up consuming a callbackID for eventID 0 under the
hood). We implemented that by a lot of copy and pasted
code between object_event.c and domain_event.c, according to
whether we are dealing with a function pointer or an eventID.
However, our copy and paste is not symmetric. Consider this
sequence:
id1 = virConnectDomainEventRegisterAny(conn, dom,
VIR_DOMAIN_EVENT_ID_LIFECYCLE,
VIR_DOMAIN_EVENT_CALLBACK(callback), NULL, NULL);
virConnectDomainEventRegister(conn, callback, NULL, NULL);
virConnectDomainEventDeregister(conn, callback);
virConnectDomainEventDeregsiterAny(conn, id1);
the first three calls would succeed, but the third call ended
up nuking the id1 callbackID (the per-domain new-style handler),
then the fourth call failed with an error about an unknown
callbackID, leaving us with the global handler (old-style) still
live and receiving events. It required another old-style
deregister to clean up the mess. Root cause was that
virDomainEventCallbackList{Remove,MarkDelete} were only
checking for function pointer match, rather than also checking
for whether the registration was global.
Rather than playing with the guts of object_event ourselves
in domain_event, it is nicer to add a mapping function for the
internal callback id, then share common code for event removal.
For now, the function-to-id mapping is used only internally;
I thought about whether a new public API to let a user learn
the callback would be useful, but decided exposing this to the
user is probably a disservice, since we already publicly
document that they should avoid the old style, and since this
patch already demonstrates that older libvirt versions have
weird behavior when mixing old and new styles.
And like all good bug fix patches, I enhanced the testsuite,
validating that the changes in tests/ expose the failure
without the rest of the patch.
* src/conf/object_event.c (virObjectEventCallbackLookup)
(virObjectEventStateCallbackID): New functions.
(virObjectEventCallbackLookup): Use helper function.
* src/conf/object_event_private.h (virObjectEventStateCallbackID):
Declare new function.
* src/conf/domain_event.c (virDomainEventStateRegister)
(virDomainEventStateDeregister): Let common code handle the
complexity.
(virDomainEventCallbackListRemove)
(virDomainEventCallbackListMarkDelete)
(virDomainEventCallbackListAdd): Drop unused functions.
* tests/objecteventtest.c (testDomainCreateXMLMixed): New test.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-03 23:50:14 +00:00
|
|
|
* @cb: function to remove from event
|
2011-12-13 10:39:17 +00:00
|
|
|
*
|
event: don't let old-style events clobber per-domain events
Right now, the older virConnectDomainEventRegister (takes a
function pointer, returns 0 on success) and the newer
virConnectDomainEventRegisterID (takes an eventID, returns a
callbackID) share the underlying implementation (the older
API ends up consuming a callbackID for eventID 0 under the
hood). We implemented that by a lot of copy and pasted
code between object_event.c and domain_event.c, according to
whether we are dealing with a function pointer or an eventID.
However, our copy and paste is not symmetric. Consider this
sequence:
id1 = virConnectDomainEventRegisterAny(conn, dom,
VIR_DOMAIN_EVENT_ID_LIFECYCLE,
VIR_DOMAIN_EVENT_CALLBACK(callback), NULL, NULL);
virConnectDomainEventRegister(conn, callback, NULL, NULL);
virConnectDomainEventDeregister(conn, callback);
virConnectDomainEventDeregsiterAny(conn, id1);
the first three calls would succeed, but the third call ended
up nuking the id1 callbackID (the per-domain new-style handler),
then the fourth call failed with an error about an unknown
callbackID, leaving us with the global handler (old-style) still
live and receiving events. It required another old-style
deregister to clean up the mess. Root cause was that
virDomainEventCallbackList{Remove,MarkDelete} were only
checking for function pointer match, rather than also checking
for whether the registration was global.
Rather than playing with the guts of object_event ourselves
in domain_event, it is nicer to add a mapping function for the
internal callback id, then share common code for event removal.
For now, the function-to-id mapping is used only internally;
I thought about whether a new public API to let a user learn
the callback would be useful, but decided exposing this to the
user is probably a disservice, since we already publicly
document that they should avoid the old style, and since this
patch already demonstrates that older libvirt versions have
weird behavior when mixing old and new styles.
And like all good bug fix patches, I enhanced the testsuite,
validating that the changes in tests/ expose the failure
without the rest of the patch.
* src/conf/object_event.c (virObjectEventCallbackLookup)
(virObjectEventStateCallbackID): New functions.
(virObjectEventCallbackLookup): Use helper function.
* src/conf/object_event_private.h (virObjectEventStateCallbackID):
Declare new function.
* src/conf/domain_event.c (virDomainEventStateRegister)
(virDomainEventStateDeregister): Let common code handle the
complexity.
(virDomainEventCallbackListRemove)
(virDomainEventCallbackListMarkDelete)
(virDomainEventCallbackListAdd): Drop unused functions.
* tests/objecteventtest.c (testDomainCreateXMLMixed): New test.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-03 23:50:14 +00:00
|
|
|
* Unregister the function @cb with connection @conn, from @state, for
|
|
|
|
* lifecycle events.
|
2011-12-13 10:39:17 +00:00
|
|
|
*
|
|
|
|
* Returns: the number of lifecycle callbacks still registered, or -1 on error
|
|
|
|
*/
|
2011-01-05 22:51:45 +00:00
|
|
|
int
|
|
|
|
virDomainEventStateDeregister(virConnectPtr conn,
|
2013-11-21 10:43:10 +00:00
|
|
|
virObjectEventStatePtr state,
|
event: don't let old-style events clobber per-domain events
Right now, the older virConnectDomainEventRegister (takes a
function pointer, returns 0 on success) and the newer
virConnectDomainEventRegisterID (takes an eventID, returns a
callbackID) share the underlying implementation (the older
API ends up consuming a callbackID for eventID 0 under the
hood). We implemented that by a lot of copy and pasted
code between object_event.c and domain_event.c, according to
whether we are dealing with a function pointer or an eventID.
However, our copy and paste is not symmetric. Consider this
sequence:
id1 = virConnectDomainEventRegisterAny(conn, dom,
VIR_DOMAIN_EVENT_ID_LIFECYCLE,
VIR_DOMAIN_EVENT_CALLBACK(callback), NULL, NULL);
virConnectDomainEventRegister(conn, callback, NULL, NULL);
virConnectDomainEventDeregister(conn, callback);
virConnectDomainEventDeregsiterAny(conn, id1);
the first three calls would succeed, but the third call ended
up nuking the id1 callbackID (the per-domain new-style handler),
then the fourth call failed with an error about an unknown
callbackID, leaving us with the global handler (old-style) still
live and receiving events. It required another old-style
deregister to clean up the mess. Root cause was that
virDomainEventCallbackList{Remove,MarkDelete} were only
checking for function pointer match, rather than also checking
for whether the registration was global.
Rather than playing with the guts of object_event ourselves
in domain_event, it is nicer to add a mapping function for the
internal callback id, then share common code for event removal.
For now, the function-to-id mapping is used only internally;
I thought about whether a new public API to let a user learn
the callback would be useful, but decided exposing this to the
user is probably a disservice, since we already publicly
document that they should avoid the old style, and since this
patch already demonstrates that older libvirt versions have
weird behavior when mixing old and new styles.
And like all good bug fix patches, I enhanced the testsuite,
validating that the changes in tests/ expose the failure
without the rest of the patch.
* src/conf/object_event.c (virObjectEventCallbackLookup)
(virObjectEventStateCallbackID): New functions.
(virObjectEventCallbackLookup): Use helper function.
* src/conf/object_event_private.h (virObjectEventStateCallbackID):
Declare new function.
* src/conf/domain_event.c (virDomainEventStateRegister)
(virDomainEventStateDeregister): Let common code handle the
complexity.
(virDomainEventCallbackListRemove)
(virDomainEventCallbackListMarkDelete)
(virDomainEventCallbackListAdd): Drop unused functions.
* tests/objecteventtest.c (testDomainCreateXMLMixed): New test.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-03 23:50:14 +00:00
|
|
|
virConnectDomainEventCallback cb)
|
2011-01-05 22:51:45 +00:00
|
|
|
{
|
event: don't let old-style events clobber per-domain events
Right now, the older virConnectDomainEventRegister (takes a
function pointer, returns 0 on success) and the newer
virConnectDomainEventRegisterID (takes an eventID, returns a
callbackID) share the underlying implementation (the older
API ends up consuming a callbackID for eventID 0 under the
hood). We implemented that by a lot of copy and pasted
code between object_event.c and domain_event.c, according to
whether we are dealing with a function pointer or an eventID.
However, our copy and paste is not symmetric. Consider this
sequence:
id1 = virConnectDomainEventRegisterAny(conn, dom,
VIR_DOMAIN_EVENT_ID_LIFECYCLE,
VIR_DOMAIN_EVENT_CALLBACK(callback), NULL, NULL);
virConnectDomainEventRegister(conn, callback, NULL, NULL);
virConnectDomainEventDeregister(conn, callback);
virConnectDomainEventDeregsiterAny(conn, id1);
the first three calls would succeed, but the third call ended
up nuking the id1 callbackID (the per-domain new-style handler),
then the fourth call failed with an error about an unknown
callbackID, leaving us with the global handler (old-style) still
live and receiving events. It required another old-style
deregister to clean up the mess. Root cause was that
virDomainEventCallbackList{Remove,MarkDelete} were only
checking for function pointer match, rather than also checking
for whether the registration was global.
Rather than playing with the guts of object_event ourselves
in domain_event, it is nicer to add a mapping function for the
internal callback id, then share common code for event removal.
For now, the function-to-id mapping is used only internally;
I thought about whether a new public API to let a user learn
the callback would be useful, but decided exposing this to the
user is probably a disservice, since we already publicly
document that they should avoid the old style, and since this
patch already demonstrates that older libvirt versions have
weird behavior when mixing old and new styles.
And like all good bug fix patches, I enhanced the testsuite,
validating that the changes in tests/ expose the failure
without the rest of the patch.
* src/conf/object_event.c (virObjectEventCallbackLookup)
(virObjectEventStateCallbackID): New functions.
(virObjectEventCallbackLookup): Use helper function.
* src/conf/object_event_private.h (virObjectEventStateCallbackID):
Declare new function.
* src/conf/domain_event.c (virDomainEventStateRegister)
(virDomainEventStateDeregister): Let common code handle the
complexity.
(virDomainEventCallbackListRemove)
(virDomainEventCallbackListMarkDelete)
(virDomainEventCallbackListAdd): Drop unused functions.
* tests/objecteventtest.c (testDomainCreateXMLMixed): New test.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-03 23:50:14 +00:00
|
|
|
int callbackID;
|
2011-12-14 00:25:58 +00:00
|
|
|
|
event: don't let old-style events clobber per-domain events
Right now, the older virConnectDomainEventRegister (takes a
function pointer, returns 0 on success) and the newer
virConnectDomainEventRegisterID (takes an eventID, returns a
callbackID) share the underlying implementation (the older
API ends up consuming a callbackID for eventID 0 under the
hood). We implemented that by a lot of copy and pasted
code between object_event.c and domain_event.c, according to
whether we are dealing with a function pointer or an eventID.
However, our copy and paste is not symmetric. Consider this
sequence:
id1 = virConnectDomainEventRegisterAny(conn, dom,
VIR_DOMAIN_EVENT_ID_LIFECYCLE,
VIR_DOMAIN_EVENT_CALLBACK(callback), NULL, NULL);
virConnectDomainEventRegister(conn, callback, NULL, NULL);
virConnectDomainEventDeregister(conn, callback);
virConnectDomainEventDeregsiterAny(conn, id1);
the first three calls would succeed, but the third call ended
up nuking the id1 callbackID (the per-domain new-style handler),
then the fourth call failed with an error about an unknown
callbackID, leaving us with the global handler (old-style) still
live and receiving events. It required another old-style
deregister to clean up the mess. Root cause was that
virDomainEventCallbackList{Remove,MarkDelete} were only
checking for function pointer match, rather than also checking
for whether the registration was global.
Rather than playing with the guts of object_event ourselves
in domain_event, it is nicer to add a mapping function for the
internal callback id, then share common code for event removal.
For now, the function-to-id mapping is used only internally;
I thought about whether a new public API to let a user learn
the callback would be useful, but decided exposing this to the
user is probably a disservice, since we already publicly
document that they should avoid the old style, and since this
patch already demonstrates that older libvirt versions have
weird behavior when mixing old and new styles.
And like all good bug fix patches, I enhanced the testsuite,
validating that the changes in tests/ expose the failure
without the rest of the patch.
* src/conf/object_event.c (virObjectEventCallbackLookup)
(virObjectEventStateCallbackID): New functions.
(virObjectEventCallbackLookup): Use helper function.
* src/conf/object_event_private.h (virObjectEventStateCallbackID):
Declare new function.
* src/conf/domain_event.c (virDomainEventStateRegister)
(virDomainEventStateDeregister): Let common code handle the
complexity.
(virDomainEventCallbackListRemove)
(virDomainEventCallbackListMarkDelete)
(virDomainEventCallbackListAdd): Drop unused functions.
* tests/objecteventtest.c (testDomainCreateXMLMixed): New test.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-03 23:50:14 +00:00
|
|
|
callbackID = virObjectEventStateCallbackID(conn, state,
|
|
|
|
virDomainEventClass,
|
|
|
|
VIR_DOMAIN_EVENT_ID_LIFECYCLE,
|
2014-01-08 04:00:54 +00:00
|
|
|
VIR_OBJECT_EVENT_CALLBACK(cb),
|
|
|
|
NULL);
|
event: don't let old-style events clobber per-domain events
Right now, the older virConnectDomainEventRegister (takes a
function pointer, returns 0 on success) and the newer
virConnectDomainEventRegisterID (takes an eventID, returns a
callbackID) share the underlying implementation (the older
API ends up consuming a callbackID for eventID 0 under the
hood). We implemented that by a lot of copy and pasted
code between object_event.c and domain_event.c, according to
whether we are dealing with a function pointer or an eventID.
However, our copy and paste is not symmetric. Consider this
sequence:
id1 = virConnectDomainEventRegisterAny(conn, dom,
VIR_DOMAIN_EVENT_ID_LIFECYCLE,
VIR_DOMAIN_EVENT_CALLBACK(callback), NULL, NULL);
virConnectDomainEventRegister(conn, callback, NULL, NULL);
virConnectDomainEventDeregister(conn, callback);
virConnectDomainEventDeregsiterAny(conn, id1);
the first three calls would succeed, but the third call ended
up nuking the id1 callbackID (the per-domain new-style handler),
then the fourth call failed with an error about an unknown
callbackID, leaving us with the global handler (old-style) still
live and receiving events. It required another old-style
deregister to clean up the mess. Root cause was that
virDomainEventCallbackList{Remove,MarkDelete} were only
checking for function pointer match, rather than also checking
for whether the registration was global.
Rather than playing with the guts of object_event ourselves
in domain_event, it is nicer to add a mapping function for the
internal callback id, then share common code for event removal.
For now, the function-to-id mapping is used only internally;
I thought about whether a new public API to let a user learn
the callback would be useful, but decided exposing this to the
user is probably a disservice, since we already publicly
document that they should avoid the old style, and since this
patch already demonstrates that older libvirt versions have
weird behavior when mixing old and new styles.
And like all good bug fix patches, I enhanced the testsuite,
validating that the changes in tests/ expose the failure
without the rest of the patch.
* src/conf/object_event.c (virObjectEventCallbackLookup)
(virObjectEventStateCallbackID): New functions.
(virObjectEventCallbackLookup): Use helper function.
* src/conf/object_event_private.h (virObjectEventStateCallbackID):
Declare new function.
* src/conf/domain_event.c (virDomainEventStateRegister)
(virDomainEventStateDeregister): Let common code handle the
complexity.
(virDomainEventCallbackListRemove)
(virDomainEventCallbackListMarkDelete)
(virDomainEventCallbackListAdd): Drop unused functions.
* tests/objecteventtest.c (testDomainCreateXMLMixed): New test.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-03 23:50:14 +00:00
|
|
|
if (callbackID < 0)
|
|
|
|
return -1;
|
|
|
|
return virObjectEventStateDeregisterID(conn, state, callbackID);
|
2011-01-05 22:51:45 +00:00
|
|
|
}
|
2013-12-31 13:33:42 +00:00
|
|
|
|
|
|
|
|
qemu: enable monitor event filtering by name
Filtering monitor events by name requires tracking the name for
the duration of the filtering. In order to free the name, I
found it easiest to just piggyback on the user's freecb function,
which gets called when the event is deregistered.
For events without a name filter, we have the design of multiple
client registrations sharing a common server registration, because
the server side uses the same callback function and we reject
duplicate use of the same function. But with events in the mix,
we want to be able to allow the same function pointer to be used
with more than one event name. The solution is to tweak the
duplicate detection code to only act when there is no additional
filtering; if name filtering is in use, there is exactly one
client registration per server registration. Yes, this means
that there is no longer a bound on the number of server
registrations possible, so a malicious client could repeatedly
register for the same name event to exhaust server memory. On
the other hand, we already restricted monitor events to require
write access (compared to normal events only needing read access),
and separated it into the intentionally unsupported
libvirt-qemu.so, with documentation that using this function is
for debug purposes only; so it is not a security risk worth
worrying about a client trying to abuse multiple registrations.
* src/conf/domain_event.c (virDomainQemuMonitorEventData): New
struct.
(virDomainQemuMonitorEventFilter)
(virDomainQemuMonitorEventCleanup): New functions.
(virDomainQemuMonitorEventDispatchFunc)
(virDomainQemuMonitorEventStateRegisterID): Use new struct.
* src/conf/object_event.c (virObjectEventCallbackListCount)
(virObjectEventCallbackListAddID)
(virObjectEventCallbackListRemoveID)
(virObjectEventCallbackListMarkDeleteID): Drop duplicate detection
when filtering is in effect.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-31 14:02:25 +00:00
|
|
|
/**
|
|
|
|
* virDomainQemuMonitorEventFilter:
|
|
|
|
* @conn: the connection pointer
|
|
|
|
* @event: the event about to be dispatched
|
|
|
|
* @opaque: the opaque data registered with the filter
|
|
|
|
*
|
|
|
|
* Callback for filtering based on event names. Returns true if the
|
|
|
|
* event should be dispatched.
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
virDomainQemuMonitorEventFilter(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|
|
|
virObjectEventPtr event,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
virDomainQemuMonitorEventData *data = opaque;
|
|
|
|
virDomainQemuMonitorEventPtr monitorEvent;
|
|
|
|
|
|
|
|
monitorEvent = (virDomainQemuMonitorEventPtr) event;
|
|
|
|
|
2014-02-06 21:46:52 +00:00
|
|
|
if (data->flags == -1)
|
|
|
|
return true;
|
|
|
|
if (data->flags & VIR_CONNECT_DOMAIN_QEMU_MONITOR_EVENT_REGISTER_REGEX)
|
|
|
|
return regexec(&data->regex, monitorEvent->event, 0, NULL, 0) == 0;
|
|
|
|
if (data->flags & VIR_CONNECT_DOMAIN_QEMU_MONITOR_EVENT_REGISTER_NOCASE)
|
|
|
|
return STRCASEEQ(monitorEvent->event, data->event);
|
qemu: enable monitor event filtering by name
Filtering monitor events by name requires tracking the name for
the duration of the filtering. In order to free the name, I
found it easiest to just piggyback on the user's freecb function,
which gets called when the event is deregistered.
For events without a name filter, we have the design of multiple
client registrations sharing a common server registration, because
the server side uses the same callback function and we reject
duplicate use of the same function. But with events in the mix,
we want to be able to allow the same function pointer to be used
with more than one event name. The solution is to tweak the
duplicate detection code to only act when there is no additional
filtering; if name filtering is in use, there is exactly one
client registration per server registration. Yes, this means
that there is no longer a bound on the number of server
registrations possible, so a malicious client could repeatedly
register for the same name event to exhaust server memory. On
the other hand, we already restricted monitor events to require
write access (compared to normal events only needing read access),
and separated it into the intentionally unsupported
libvirt-qemu.so, with documentation that using this function is
for debug purposes only; so it is not a security risk worth
worrying about a client trying to abuse multiple registrations.
* src/conf/domain_event.c (virDomainQemuMonitorEventData): New
struct.
(virDomainQemuMonitorEventFilter)
(virDomainQemuMonitorEventCleanup): New functions.
(virDomainQemuMonitorEventDispatchFunc)
(virDomainQemuMonitorEventStateRegisterID): Use new struct.
* src/conf/object_event.c (virObjectEventCallbackListCount)
(virObjectEventCallbackListAddID)
(virObjectEventCallbackListRemoveID)
(virObjectEventCallbackListMarkDeleteID): Drop duplicate detection
when filtering is in effect.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-31 14:02:25 +00:00
|
|
|
return STREQ(monitorEvent->event, data->event);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
virDomainQemuMonitorEventCleanup(void *opaque)
|
|
|
|
{
|
|
|
|
virDomainQemuMonitorEventData *data = opaque;
|
|
|
|
|
|
|
|
VIR_FREE(data->event);
|
2014-02-06 21:46:52 +00:00
|
|
|
if (data->flags & VIR_CONNECT_DOMAIN_QEMU_MONITOR_EVENT_REGISTER_REGEX)
|
|
|
|
regfree(&data->regex);
|
qemu: enable monitor event filtering by name
Filtering monitor events by name requires tracking the name for
the duration of the filtering. In order to free the name, I
found it easiest to just piggyback on the user's freecb function,
which gets called when the event is deregistered.
For events without a name filter, we have the design of multiple
client registrations sharing a common server registration, because
the server side uses the same callback function and we reject
duplicate use of the same function. But with events in the mix,
we want to be able to allow the same function pointer to be used
with more than one event name. The solution is to tweak the
duplicate detection code to only act when there is no additional
filtering; if name filtering is in use, there is exactly one
client registration per server registration. Yes, this means
that there is no longer a bound on the number of server
registrations possible, so a malicious client could repeatedly
register for the same name event to exhaust server memory. On
the other hand, we already restricted monitor events to require
write access (compared to normal events only needing read access),
and separated it into the intentionally unsupported
libvirt-qemu.so, with documentation that using this function is
for debug purposes only; so it is not a security risk worth
worrying about a client trying to abuse multiple registrations.
* src/conf/domain_event.c (virDomainQemuMonitorEventData): New
struct.
(virDomainQemuMonitorEventFilter)
(virDomainQemuMonitorEventCleanup): New functions.
(virDomainQemuMonitorEventDispatchFunc)
(virDomainQemuMonitorEventStateRegisterID): Use new struct.
* src/conf/object_event.c (virObjectEventCallbackListCount)
(virObjectEventCallbackListAddID)
(virObjectEventCallbackListRemoveID)
(virObjectEventCallbackListMarkDeleteID): Drop duplicate detection
when filtering is in effect.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-31 14:02:25 +00:00
|
|
|
if (data->freecb)
|
|
|
|
(data->freecb)(data->opaque);
|
|
|
|
VIR_FREE(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-31 13:33:42 +00:00
|
|
|
/**
|
|
|
|
* virDomainQemuMonitorEventStateRegisterID:
|
|
|
|
* @conn: connection to associate with callback
|
|
|
|
* @state: object event state
|
|
|
|
* @dom: optional domain where event must occur
|
|
|
|
* @event: optional name of event to register for
|
|
|
|
* @cb: function to invoke when event occurs
|
|
|
|
* @opaque: data blob to pass to callback
|
|
|
|
* @freecb: callback to free @opaque
|
2014-02-06 21:46:52 +00:00
|
|
|
* @flags: -1 for client, valid virConnectDomainQemuMonitorEventRegisterFlags
|
|
|
|
* for server
|
2013-12-31 13:33:42 +00:00
|
|
|
* @callbackID: filled with callback ID
|
|
|
|
*
|
|
|
|
* Register the function @cb with connection @conn, from @state, for
|
|
|
|
* events of type @eventID.
|
|
|
|
*
|
|
|
|
* Returns: the number of callbacks now registered, or -1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virDomainQemuMonitorEventStateRegisterID(virConnectPtr conn,
|
|
|
|
virObjectEventStatePtr state,
|
|
|
|
virDomainPtr dom,
|
|
|
|
const char *event,
|
|
|
|
virConnectDomainQemuMonitorEventCallback cb,
|
|
|
|
void *opaque,
|
|
|
|
virFreeCallback freecb,
|
|
|
|
unsigned int flags,
|
|
|
|
int *callbackID)
|
|
|
|
{
|
qemu: enable monitor event filtering by name
Filtering monitor events by name requires tracking the name for
the duration of the filtering. In order to free the name, I
found it easiest to just piggyback on the user's freecb function,
which gets called when the event is deregistered.
For events without a name filter, we have the design of multiple
client registrations sharing a common server registration, because
the server side uses the same callback function and we reject
duplicate use of the same function. But with events in the mix,
we want to be able to allow the same function pointer to be used
with more than one event name. The solution is to tweak the
duplicate detection code to only act when there is no additional
filtering; if name filtering is in use, there is exactly one
client registration per server registration. Yes, this means
that there is no longer a bound on the number of server
registrations possible, so a malicious client could repeatedly
register for the same name event to exhaust server memory. On
the other hand, we already restricted monitor events to require
write access (compared to normal events only needing read access),
and separated it into the intentionally unsupported
libvirt-qemu.so, with documentation that using this function is
for debug purposes only; so it is not a security risk worth
worrying about a client trying to abuse multiple registrations.
* src/conf/domain_event.c (virDomainQemuMonitorEventData): New
struct.
(virDomainQemuMonitorEventFilter)
(virDomainQemuMonitorEventCleanup): New functions.
(virDomainQemuMonitorEventDispatchFunc)
(virDomainQemuMonitorEventStateRegisterID): Use new struct.
* src/conf/object_event.c (virObjectEventCallbackListCount)
(virObjectEventCallbackListAddID)
(virObjectEventCallbackListRemoveID)
(virObjectEventCallbackListMarkDeleteID): Drop duplicate detection
when filtering is in effect.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-31 14:02:25 +00:00
|
|
|
virDomainQemuMonitorEventData *data = NULL;
|
|
|
|
virObjectEventCallbackFilter filter = NULL;
|
2016-06-23 15:50:05 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
qemu: enable monitor event filtering by name
Filtering monitor events by name requires tracking the name for
the duration of the filtering. In order to free the name, I
found it easiest to just piggyback on the user's freecb function,
which gets called when the event is deregistered.
For events without a name filter, we have the design of multiple
client registrations sharing a common server registration, because
the server side uses the same callback function and we reject
duplicate use of the same function. But with events in the mix,
we want to be able to allow the same function pointer to be used
with more than one event name. The solution is to tweak the
duplicate detection code to only act when there is no additional
filtering; if name filtering is in use, there is exactly one
client registration per server registration. Yes, this means
that there is no longer a bound on the number of server
registrations possible, so a malicious client could repeatedly
register for the same name event to exhaust server memory. On
the other hand, we already restricted monitor events to require
write access (compared to normal events only needing read access),
and separated it into the intentionally unsupported
libvirt-qemu.so, with documentation that using this function is
for debug purposes only; so it is not a security risk worth
worrying about a client trying to abuse multiple registrations.
* src/conf/domain_event.c (virDomainQemuMonitorEventData): New
struct.
(virDomainQemuMonitorEventFilter)
(virDomainQemuMonitorEventCleanup): New functions.
(virDomainQemuMonitorEventDispatchFunc)
(virDomainQemuMonitorEventStateRegisterID): Use new struct.
* src/conf/object_event.c (virObjectEventCallbackListCount)
(virObjectEventCallbackListAddID)
(virObjectEventCallbackListRemoveID)
(virObjectEventCallbackListMarkDeleteID): Drop duplicate detection
when filtering is in effect.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-31 14:02:25 +00:00
|
|
|
|
2013-12-31 13:33:42 +00:00
|
|
|
if (virDomainEventsInitialize() < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (flags != -1)
|
2014-02-06 21:46:52 +00:00
|
|
|
virCheckFlags(VIR_CONNECT_DOMAIN_QEMU_MONITOR_EVENT_REGISTER_REGEX |
|
|
|
|
VIR_CONNECT_DOMAIN_QEMU_MONITOR_EVENT_REGISTER_NOCASE,
|
|
|
|
-1);
|
qemu: enable monitor event filtering by name
Filtering monitor events by name requires tracking the name for
the duration of the filtering. In order to free the name, I
found it easiest to just piggyback on the user's freecb function,
which gets called when the event is deregistered.
For events without a name filter, we have the design of multiple
client registrations sharing a common server registration, because
the server side uses the same callback function and we reject
duplicate use of the same function. But with events in the mix,
we want to be able to allow the same function pointer to be used
with more than one event name. The solution is to tweak the
duplicate detection code to only act when there is no additional
filtering; if name filtering is in use, there is exactly one
client registration per server registration. Yes, this means
that there is no longer a bound on the number of server
registrations possible, so a malicious client could repeatedly
register for the same name event to exhaust server memory. On
the other hand, we already restricted monitor events to require
write access (compared to normal events only needing read access),
and separated it into the intentionally unsupported
libvirt-qemu.so, with documentation that using this function is
for debug purposes only; so it is not a security risk worth
worrying about a client trying to abuse multiple registrations.
* src/conf/domain_event.c (virDomainQemuMonitorEventData): New
struct.
(virDomainQemuMonitorEventFilter)
(virDomainQemuMonitorEventCleanup): New functions.
(virDomainQemuMonitorEventDispatchFunc)
(virDomainQemuMonitorEventStateRegisterID): Use new struct.
* src/conf/object_event.c (virObjectEventCallbackListCount)
(virObjectEventCallbackListAddID)
(virObjectEventCallbackListRemoveID)
(virObjectEventCallbackListMarkDeleteID): Drop duplicate detection
when filtering is in effect.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-31 14:02:25 +00:00
|
|
|
if (VIR_ALLOC(data) < 0)
|
|
|
|
return -1;
|
2014-02-06 21:46:52 +00:00
|
|
|
data->flags = flags;
|
2014-09-22 11:54:52 +00:00
|
|
|
if (event && flags != -1) {
|
2014-02-06 21:46:52 +00:00
|
|
|
int rflags = REG_NOSUB;
|
|
|
|
|
|
|
|
if (flags & VIR_CONNECT_DOMAIN_QEMU_MONITOR_EVENT_REGISTER_NOCASE)
|
|
|
|
rflags |= REG_ICASE;
|
|
|
|
if (flags & VIR_CONNECT_DOMAIN_QEMU_MONITOR_EVENT_REGISTER_REGEX) {
|
|
|
|
int err = regcomp(&data->regex, event, rflags);
|
|
|
|
|
|
|
|
if (err) {
|
|
|
|
char error[100];
|
|
|
|
regerror(err, &data->regex, error, sizeof(error));
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("failed to compile regex '%s': %s"),
|
|
|
|
event, error);
|
|
|
|
regfree(&data->regex);
|
|
|
|
VIR_FREE(data);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else if (VIR_STRDUP(data->event, event) < 0) {
|
|
|
|
VIR_FREE(data);
|
|
|
|
return -1;
|
|
|
|
}
|
2013-12-31 13:33:42 +00:00
|
|
|
}
|
qemu: enable monitor event filtering by name
Filtering monitor events by name requires tracking the name for
the duration of the filtering. In order to free the name, I
found it easiest to just piggyback on the user's freecb function,
which gets called when the event is deregistered.
For events without a name filter, we have the design of multiple
client registrations sharing a common server registration, because
the server side uses the same callback function and we reject
duplicate use of the same function. But with events in the mix,
we want to be able to allow the same function pointer to be used
with more than one event name. The solution is to tweak the
duplicate detection code to only act when there is no additional
filtering; if name filtering is in use, there is exactly one
client registration per server registration. Yes, this means
that there is no longer a bound on the number of server
registrations possible, so a malicious client could repeatedly
register for the same name event to exhaust server memory. On
the other hand, we already restricted monitor events to require
write access (compared to normal events only needing read access),
and separated it into the intentionally unsupported
libvirt-qemu.so, with documentation that using this function is
for debug purposes only; so it is not a security risk worth
worrying about a client trying to abuse multiple registrations.
* src/conf/domain_event.c (virDomainQemuMonitorEventData): New
struct.
(virDomainQemuMonitorEventFilter)
(virDomainQemuMonitorEventCleanup): New functions.
(virDomainQemuMonitorEventDispatchFunc)
(virDomainQemuMonitorEventStateRegisterID): Use new struct.
* src/conf/object_event.c (virObjectEventCallbackListCount)
(virObjectEventCallbackListAddID)
(virObjectEventCallbackListRemoveID)
(virObjectEventCallbackListMarkDeleteID): Drop duplicate detection
when filtering is in effect.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-31 14:02:25 +00:00
|
|
|
data->opaque = opaque;
|
|
|
|
data->freecb = freecb;
|
|
|
|
if (event)
|
|
|
|
filter = virDomainQemuMonitorEventFilter;
|
|
|
|
freecb = virDomainQemuMonitorEventCleanup;
|
2013-12-31 13:33:42 +00:00
|
|
|
|
2016-06-23 15:50:05 +00:00
|
|
|
if (dom)
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
|
|
|
return virObjectEventStateRegisterID(conn, state, dom ? uuidstr : NULL,
|
qemu: enable monitor event filtering by name
Filtering monitor events by name requires tracking the name for
the duration of the filtering. In order to free the name, I
found it easiest to just piggyback on the user's freecb function,
which gets called when the event is deregistered.
For events without a name filter, we have the design of multiple
client registrations sharing a common server registration, because
the server side uses the same callback function and we reject
duplicate use of the same function. But with events in the mix,
we want to be able to allow the same function pointer to be used
with more than one event name. The solution is to tweak the
duplicate detection code to only act when there is no additional
filtering; if name filtering is in use, there is exactly one
client registration per server registration. Yes, this means
that there is no longer a bound on the number of server
registrations possible, so a malicious client could repeatedly
register for the same name event to exhaust server memory. On
the other hand, we already restricted monitor events to require
write access (compared to normal events only needing read access),
and separated it into the intentionally unsupported
libvirt-qemu.so, with documentation that using this function is
for debug purposes only; so it is not a security risk worth
worrying about a client trying to abuse multiple registrations.
* src/conf/domain_event.c (virDomainQemuMonitorEventData): New
struct.
(virDomainQemuMonitorEventFilter)
(virDomainQemuMonitorEventCleanup): New functions.
(virDomainQemuMonitorEventDispatchFunc)
(virDomainQemuMonitorEventStateRegisterID): Use new struct.
* src/conf/object_event.c (virObjectEventCallbackListCount)
(virObjectEventCallbackListAddID)
(virObjectEventCallbackListRemoveID)
(virObjectEventCallbackListMarkDeleteID): Drop duplicate detection
when filtering is in effect.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-31 14:02:25 +00:00
|
|
|
filter, data,
|
2013-12-31 13:33:42 +00:00
|
|
|
virDomainQemuMonitorEventClass, 0,
|
|
|
|
VIR_OBJECT_EVENT_CALLBACK(cb),
|
qemu: enable monitor event filtering by name
Filtering monitor events by name requires tracking the name for
the duration of the filtering. In order to free the name, I
found it easiest to just piggyback on the user's freecb function,
which gets called when the event is deregistered.
For events without a name filter, we have the design of multiple
client registrations sharing a common server registration, because
the server side uses the same callback function and we reject
duplicate use of the same function. But with events in the mix,
we want to be able to allow the same function pointer to be used
with more than one event name. The solution is to tweak the
duplicate detection code to only act when there is no additional
filtering; if name filtering is in use, there is exactly one
client registration per server registration. Yes, this means
that there is no longer a bound on the number of server
registrations possible, so a malicious client could repeatedly
register for the same name event to exhaust server memory. On
the other hand, we already restricted monitor events to require
write access (compared to normal events only needing read access),
and separated it into the intentionally unsupported
libvirt-qemu.so, with documentation that using this function is
for debug purposes only; so it is not a security risk worth
worrying about a client trying to abuse multiple registrations.
* src/conf/domain_event.c (virDomainQemuMonitorEventData): New
struct.
(virDomainQemuMonitorEventFilter)
(virDomainQemuMonitorEventCleanup): New functions.
(virDomainQemuMonitorEventDispatchFunc)
(virDomainQemuMonitorEventStateRegisterID): Use new struct.
* src/conf/object_event.c (virObjectEventCallbackListCount)
(virObjectEventCallbackListAddID)
(virObjectEventCallbackListRemoveID)
(virObjectEventCallbackListMarkDeleteID): Drop duplicate detection
when filtering is in effect.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-31 14:02:25 +00:00
|
|
|
data, freecb,
|
2013-12-31 13:33:42 +00:00
|
|
|
false, callbackID, false);
|
|
|
|
}
|