提交 3566599a 编写于 作者: E Eric Blake

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: NEric Blake <eblake@redhat.com>
上级 e7708a1c
...@@ -16355,6 +16355,55 @@ cleanup: ...@@ -16355,6 +16355,55 @@ cleanup:
return result; 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 static int
qemuDomainFSTrim(virDomainPtr dom, qemuDomainFSTrim(virDomainPtr dom,
const char *mountPoint, const char *mountPoint,
...@@ -16688,6 +16737,8 @@ static virDriver qemuDriver = { ...@@ -16688,6 +16737,8 @@ static virDriver qemuDriver = {
.domainQemuMonitorCommand = qemuDomainQemuMonitorCommand, /* 0.8.3 */ .domainQemuMonitorCommand = qemuDomainQemuMonitorCommand, /* 0.8.3 */
.domainQemuAttach = qemuDomainQemuAttach, /* 0.9.4 */ .domainQemuAttach = qemuDomainQemuAttach, /* 0.9.4 */
.domainQemuAgentCommand = qemuDomainQemuAgentCommand, /* 0.10.0 */ .domainQemuAgentCommand = qemuDomainQemuAgentCommand, /* 0.10.0 */
.connectDomainQemuMonitorEventRegister = qemuConnectDomainQemuMonitorEventRegister, /* 1.2.3 */
.connectDomainQemuMonitorEventDeregister = qemuConnectDomainQemuMonitorEventDeregister, /* 1.2.3 */
.domainOpenConsole = qemuDomainOpenConsole, /* 0.8.6 */ .domainOpenConsole = qemuDomainOpenConsole, /* 0.8.6 */
.domainOpenGraphics = qemuDomainOpenGraphics, /* 0.9.7 */ .domainOpenGraphics = qemuDomainOpenGraphics, /* 0.9.7 */
.domainInjectNMI = qemuDomainInjectNMI, /* 0.9.2 */ .domainInjectNMI = qemuDomainInjectNMI, /* 0.9.2 */
......
...@@ -1168,6 +1168,20 @@ int qemuMonitorGetDiskSecret(qemuMonitorPtr mon, ...@@ -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 qemuMonitorEmitShutdown(qemuMonitorPtr mon)
{ {
int ret = -1; int ret = -1;
......
/* /*
* qemu_monitor.h: interaction with QEMU monitor console * 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 * Copyright (C) 2006 Daniel P. Berrange
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
...@@ -90,6 +90,13 @@ typedef int (*qemuMonitorDiskSecretLookupCallback)(qemuMonitorPtr mon, ...@@ -90,6 +90,13 @@ typedef int (*qemuMonitorDiskSecretLookupCallback)(qemuMonitorPtr mon,
char **secret, char **secret,
size_t *secretLen, size_t *secretLen,
void *opaque); 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, typedef int (*qemuMonitorDomainShutdownCallback)(qemuMonitorPtr mon,
virDomainObjPtr vm, virDomainObjPtr vm,
void *opaque); void *opaque);
...@@ -171,6 +178,7 @@ struct _qemuMonitorCallbacks { ...@@ -171,6 +178,7 @@ struct _qemuMonitorCallbacks {
qemuMonitorEofNotifyCallback eofNotify; qemuMonitorEofNotifyCallback eofNotify;
qemuMonitorErrorNotifyCallback errorNotify; qemuMonitorErrorNotifyCallback errorNotify;
qemuMonitorDiskSecretLookupCallback diskSecretLookup; qemuMonitorDiskSecretLookupCallback diskSecretLookup;
qemuMonitorDomainEventCallback domainEvent;
qemuMonitorDomainShutdownCallback domainShutdown; qemuMonitorDomainShutdownCallback domainShutdown;
qemuMonitorDomainResetCallback domainReset; qemuMonitorDomainResetCallback domainReset;
qemuMonitorDomainPowerdownCallback domainPowerdown; qemuMonitorDomainPowerdownCallback domainPowerdown;
...@@ -236,6 +244,9 @@ int qemuMonitorGetDiskSecret(qemuMonitorPtr mon, ...@@ -236,6 +244,9 @@ int qemuMonitorGetDiskSecret(qemuMonitorPtr mon,
char **secret, char **secret,
size_t *secretLen); size_t *secretLen);
int qemuMonitorEmitEvent(qemuMonitorPtr mon, const char *event,
long long seconds, unsigned int micros,
const char *details);
int qemuMonitorEmitShutdown(qemuMonitorPtr mon); int qemuMonitorEmitShutdown(qemuMonitorPtr mon);
int qemuMonitorEmitReset(qemuMonitorPtr mon); int qemuMonitorEmitReset(qemuMonitorPtr mon);
int qemuMonitorEmitPowerdown(qemuMonitorPtr mon); int qemuMonitorEmitPowerdown(qemuMonitorPtr mon);
......
...@@ -129,6 +129,12 @@ qemuMonitorJSONIOProcessEvent(qemuMonitorPtr mon, ...@@ -129,6 +129,12 @@ qemuMonitorJSONIOProcessEvent(qemuMonitorPtr mon,
{ {
const char *type; const char *type;
qemuEventHandler *handler; 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); VIR_DEBUG("mon=%p obj=%p", mon, obj);
type = virJSONValueObjectGetString(obj, "event"); type = virJSONValueObjectGetString(obj, "event");
...@@ -138,10 +144,23 @@ qemuMonitorJSONIOProcessEvent(qemuMonitorPtr mon, ...@@ -138,10 +144,23 @@ qemuMonitorJSONIOProcessEvent(qemuMonitorPtr mon,
return -1; 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, &micros));
}
qemuMonitorEmitEvent(mon, type, seconds, micros, details);
VIR_FREE(details);
handler = bsearch(type, eventHandlers, ARRAY_CARDINALITY(eventHandlers), handler = bsearch(type, eventHandlers, ARRAY_CARDINALITY(eventHandlers),
sizeof(eventHandlers[0]), qemuMonitorEventCompare); sizeof(eventHandlers[0]), qemuMonitorEventCompare);
if (handler) { if (handler) {
virJSONValuePtr data = virJSONValueObjectGet(obj, "data");
VIR_DEBUG("handle %s handler=%p data=%p", type, VIR_DEBUG("handle %s handler=%p data=%p", type,
handler->handler, data); handler->handler, data);
(handler->handler)(mon, data); (handler->handler)(mon, data);
......
...@@ -648,6 +648,34 @@ qemuProcessShutdownOrReboot(virQEMUDriverPtr driver, ...@@ -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 static int
qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED, qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
virDomainObjPtr vm, virDomainObjPtr vm,
...@@ -1369,6 +1397,7 @@ static qemuMonitorCallbacks monitorCallbacks = { ...@@ -1369,6 +1397,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
.eofNotify = qemuProcessHandleMonitorEOF, .eofNotify = qemuProcessHandleMonitorEOF,
.errorNotify = qemuProcessHandleMonitorError, .errorNotify = qemuProcessHandleMonitorError,
.diskSecretLookup = qemuProcessFindVolumeQcowPassphrase, .diskSecretLookup = qemuProcessFindVolumeQcowPassphrase,
.domainEvent = qemuProcessHandleEvent,
.domainShutdown = qemuProcessHandleShutdown, .domainShutdown = qemuProcessHandleShutdown,
.domainStop = qemuProcessHandleStop, .domainStop = qemuProcessHandleStop,
.domainResume = qemuProcessHandleResume, .domainResume = qemuProcessHandleResume,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册