mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 06:05:27 +00:00
qemu: enable monitor event reporting
Wire up all the pieces to send arbitrary qemu events to a client using libvirt-qemu.so. If the extra bookkeeping of generating event objects even when no one is listening turns out to be noticeable, we can try to further optimize things by adding a counter for how many connections are using events, and only dump events when the counter is non-zero; but for now, I didn't think it was worth the code complexity. * src/qemu/qemu_driver.c (qemuConnectDomainQemuMonitorEventRegister) (qemuConnectDomainQemuMonitorEventDeregister): New functions. * src/qemu/qemu_monitor.h (qemuMonitorEmitEvent): New prototype. (qemuMonitorDomainEventCallback): New typedef. * src/qemu/qemu_monitor_json.c (qemuMonitorJSONIOProcessEvent): Report events. * src/qemu/qemu_monitor.c (qemuMonitorEmitEvent): New function, to pass events through. * src/qemu/qemu_process.c (qemuProcessHandleEvent): Likewise. Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
e7708a1c47
commit
3566599a2f
@ -16355,6 +16355,55 @@ cleanup:
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuConnectDomainQemuMonitorEventRegister(virConnectPtr conn,
|
||||
virDomainPtr dom,
|
||||
const char *event,
|
||||
virConnectDomainQemuMonitorEventCallback callback,
|
||||
void *opaque,
|
||||
virFreeCallback freecb,
|
||||
unsigned int flags)
|
||||
{
|
||||
virQEMUDriverPtr driver = conn->privateData;
|
||||
int ret = -1;
|
||||
|
||||
if (virConnectDomainQemuMonitorEventRegisterEnsureACL(conn) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (virDomainQemuMonitorEventStateRegisterID(conn,
|
||||
driver->domainEventState,
|
||||
dom, event, callback,
|
||||
opaque, freecb, flags,
|
||||
&ret) < 0)
|
||||
ret = -1;
|
||||
|
||||
cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuConnectDomainQemuMonitorEventDeregister(virConnectPtr conn,
|
||||
int callbackID)
|
||||
{
|
||||
virQEMUDriverPtr driver = conn->privateData;
|
||||
int ret = -1;
|
||||
|
||||
if (virConnectDomainQemuMonitorEventDeregisterEnsureACL(conn) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (virObjectEventStateDeregisterID(conn, driver->domainEventState,
|
||||
callbackID) < 0)
|
||||
goto cleanup;
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuDomainFSTrim(virDomainPtr dom,
|
||||
const char *mountPoint,
|
||||
@ -16688,6 +16737,8 @@ static virDriver qemuDriver = {
|
||||
.domainQemuMonitorCommand = qemuDomainQemuMonitorCommand, /* 0.8.3 */
|
||||
.domainQemuAttach = qemuDomainQemuAttach, /* 0.9.4 */
|
||||
.domainQemuAgentCommand = qemuDomainQemuAgentCommand, /* 0.10.0 */
|
||||
.connectDomainQemuMonitorEventRegister = qemuConnectDomainQemuMonitorEventRegister, /* 1.2.3 */
|
||||
.connectDomainQemuMonitorEventDeregister = qemuConnectDomainQemuMonitorEventDeregister, /* 1.2.3 */
|
||||
.domainOpenConsole = qemuDomainOpenConsole, /* 0.8.6 */
|
||||
.domainOpenGraphics = qemuDomainOpenGraphics, /* 0.9.7 */
|
||||
.domainInjectNMI = qemuDomainInjectNMI, /* 0.9.2 */
|
||||
|
@ -1168,6 +1168,20 @@ int qemuMonitorGetDiskSecret(qemuMonitorPtr mon,
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuMonitorEmitEvent(qemuMonitorPtr mon, const char *event,
|
||||
long long seconds, unsigned int micros,
|
||||
const char *details)
|
||||
{
|
||||
int ret = -1;
|
||||
VIR_DEBUG("mon=%p event=%s", mon, event);
|
||||
|
||||
QEMU_MONITOR_CALLBACK(mon, ret, domainEvent, mon->vm, event, seconds,
|
||||
micros, details);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int qemuMonitorEmitShutdown(qemuMonitorPtr mon)
|
||||
{
|
||||
int ret = -1;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* qemu_monitor.h: interaction with QEMU monitor console
|
||||
*
|
||||
* Copyright (C) 2006-2013 Red Hat, Inc.
|
||||
* Copyright (C) 2006-2014 Red Hat, Inc.
|
||||
* Copyright (C) 2006 Daniel P. Berrange
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
@ -90,6 +90,13 @@ typedef int (*qemuMonitorDiskSecretLookupCallback)(qemuMonitorPtr mon,
|
||||
char **secret,
|
||||
size_t *secretLen,
|
||||
void *opaque);
|
||||
typedef int (*qemuMonitorDomainEventCallback)(qemuMonitorPtr mon,
|
||||
virDomainObjPtr vm,
|
||||
const char *event,
|
||||
long long seconds,
|
||||
unsigned int micros,
|
||||
const char *details,
|
||||
void *opaque);
|
||||
typedef int (*qemuMonitorDomainShutdownCallback)(qemuMonitorPtr mon,
|
||||
virDomainObjPtr vm,
|
||||
void *opaque);
|
||||
@ -171,6 +178,7 @@ struct _qemuMonitorCallbacks {
|
||||
qemuMonitorEofNotifyCallback eofNotify;
|
||||
qemuMonitorErrorNotifyCallback errorNotify;
|
||||
qemuMonitorDiskSecretLookupCallback diskSecretLookup;
|
||||
qemuMonitorDomainEventCallback domainEvent;
|
||||
qemuMonitorDomainShutdownCallback domainShutdown;
|
||||
qemuMonitorDomainResetCallback domainReset;
|
||||
qemuMonitorDomainPowerdownCallback domainPowerdown;
|
||||
@ -236,6 +244,9 @@ int qemuMonitorGetDiskSecret(qemuMonitorPtr mon,
|
||||
char **secret,
|
||||
size_t *secretLen);
|
||||
|
||||
int qemuMonitorEmitEvent(qemuMonitorPtr mon, const char *event,
|
||||
long long seconds, unsigned int micros,
|
||||
const char *details);
|
||||
int qemuMonitorEmitShutdown(qemuMonitorPtr mon);
|
||||
int qemuMonitorEmitReset(qemuMonitorPtr mon);
|
||||
int qemuMonitorEmitPowerdown(qemuMonitorPtr mon);
|
||||
|
@ -129,6 +129,12 @@ qemuMonitorJSONIOProcessEvent(qemuMonitorPtr mon,
|
||||
{
|
||||
const char *type;
|
||||
qemuEventHandler *handler;
|
||||
virJSONValuePtr data;
|
||||
char *details = NULL;
|
||||
virJSONValuePtr timestamp;
|
||||
long long seconds = -1;
|
||||
unsigned int micros = 0;
|
||||
|
||||
VIR_DEBUG("mon=%p obj=%p", mon, obj);
|
||||
|
||||
type = virJSONValueObjectGetString(obj, "event");
|
||||
@ -138,10 +144,23 @@ qemuMonitorJSONIOProcessEvent(qemuMonitorPtr mon,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Not all events have data; and event reporting is best-effort only */
|
||||
if ((data = virJSONValueObjectGet(obj, "data")))
|
||||
details = virJSONValueToString(data, false);
|
||||
if ((timestamp = virJSONValueObjectGet(obj, "timestamp"))) {
|
||||
virJSONValuePtr elt;
|
||||
|
||||
if ((elt = virJSONValueObjectGet(timestamp, "seconds")))
|
||||
ignore_value(virJSONValueGetNumberLong(elt, &seconds));
|
||||
if ((elt = virJSONValueObjectGet(timestamp, "microseconds")))
|
||||
ignore_value(virJSONValueGetNumberUint(elt, µs));
|
||||
}
|
||||
qemuMonitorEmitEvent(mon, type, seconds, micros, details);
|
||||
VIR_FREE(details);
|
||||
|
||||
handler = bsearch(type, eventHandlers, ARRAY_CARDINALITY(eventHandlers),
|
||||
sizeof(eventHandlers[0]), qemuMonitorEventCompare);
|
||||
if (handler) {
|
||||
virJSONValuePtr data = virJSONValueObjectGet(obj, "data");
|
||||
VIR_DEBUG("handle %s handler=%p data=%p", type,
|
||||
handler->handler, data);
|
||||
(handler->handler)(mon, data);
|
||||
|
@ -648,6 +648,34 @@ qemuProcessShutdownOrReboot(virQEMUDriverPtr driver,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuProcessHandleEvent(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
||||
virDomainObjPtr vm,
|
||||
const char *eventName,
|
||||
long long seconds,
|
||||
unsigned int micros,
|
||||
const char *details,
|
||||
void *opaque)
|
||||
{
|
||||
virQEMUDriverPtr driver = opaque;
|
||||
virObjectEventPtr event = NULL;
|
||||
|
||||
VIR_DEBUG("vm=%p", vm);
|
||||
|
||||
virObjectLock(vm);
|
||||
event = virDomainQemuMonitorEventNew(vm->def->id, vm->def->name,
|
||||
vm->def->uuid, eventName,
|
||||
seconds, micros, details);
|
||||
|
||||
virObjectUnlock(vm);
|
||||
if (event)
|
||||
qemuDomainEventQueue(driver, event);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
||||
virDomainObjPtr vm,
|
||||
@ -1369,6 +1397,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
|
||||
.eofNotify = qemuProcessHandleMonitorEOF,
|
||||
.errorNotify = qemuProcessHandleMonitorError,
|
||||
.diskSecretLookup = qemuProcessFindVolumeQcowPassphrase,
|
||||
.domainEvent = qemuProcessHandleEvent,
|
||||
.domainShutdown = qemuProcessHandleShutdown,
|
||||
.domainStop = qemuProcessHandleStop,
|
||||
.domainResume = qemuProcessHandleResume,
|
||||
|
Loading…
Reference in New Issue
Block a user