Signed-off-by: Prerna Saxena <saxenap.ltc@xxxxxxxxx> --- src/qemu/qemu_event.c | 11 + src/qemu/qemu_event.h | 8 + src/qemu/qemu_monitor.c | 592 +++++++++++++++++++++++++++----- src/qemu/qemu_monitor.h | 80 +++-- src/qemu/qemu_monitor_json.c | 291 ++++++++++------ src/qemu/qemu_process.c | 789 +++++++++++++++++++++++++++---------------- src/qemu/qemu_process.h | 2 + tests/qemumonitortestutils.c | 2 +- 8 files changed, 1273 insertions(+), 502 deletions(-) diff --git a/src/qemu/qemu_event.c b/src/qemu/qemu_event.c index d52fad2..beb309f 100644 --- a/src/qemu/qemu_event.c +++ b/src/qemu/qemu_event.c @@ -50,6 +50,7 @@ VIR_ENUM_IMPL(qemuMonitorEvent, "RTC Change", "Shutdown", "Stop", "Suspend", "Suspend To Disk", "Virtual Serial Port Change", + "Spice migrated", "Wakeup", "Watchdog"); virQemuEventList* virQemuEventListInit(void) @@ -302,3 +303,13 @@ void virDomainConsumeVMEvents(virDomainObjPtr vm, void *opaque) } return; } + +extern void qemuProcessEmitMonitorEvent(qemuEventPtr ev, void *opaque); + +void virEventRunHandler(qemuEventPtr ev, void *opaque) +{ + if (!ev) + return; + + return qemuProcessEmitMonitorEvent(ev, opaque); +} diff --git a/src/qemu/qemu_event.h b/src/qemu/qemu_event.h index 4173834..8552fd1 100644 --- a/src/qemu/qemu_event.h +++ b/src/qemu/qemu_event.h @@ -51,6 +51,7 @@ typedef enum { QEMU_EVENT_SUSPEND, QEMU_EVENT_SUSPEND_DISK, QEMU_EVENT_SERIAL_CHANGE, + QEMU_EVENT_SPICE_MIGRATED, QEMU_EVENT_WAKEUP, QEMU_EVENT_WATCHDOG, @@ -102,7 +103,12 @@ struct qemuEventTrayChangeData { int reason; }; +struct qemuEventShutdownData { + virTristateBool guest_initiated; +}; + struct qemuEventGuestPanicData { + void *info; }; struct qemuEventMigrationStatusData { @@ -159,6 +165,7 @@ struct _qemuEvent { struct qemuEventBlockThresholdData ev_threshold; struct qemuEventDeviceDeletedData ev_deviceDel; struct qemuEventTrayChangeData ev_tray; + struct qemuEventShutdownData ev_shutdown; struct qemuEventGuestPanicData ev_panic; struct qemuEventMigrationStatusData ev_migStatus; struct qemuEventMigrationPassData ev_migPass; @@ -219,5 +226,6 @@ int virQemuVmEventListInit(virDomainObjPtr vm); int virEnqueueVMEvent(virQemuEventList *qlist, qemuEventPtr ev); qemuEventPtr virDequeueVMEvent(virQemuEventList *qlist, virDomainObjPtr vm); void virEventWorkerScanQueue(void *dummy, void *opaque); +void virEventRunHandler(qemuEventPtr ev, void *opaque); void virDomainConsumeVMEvents(virDomainObjPtr vm, void *opaque); #endif diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 7a26785..4e45cf9 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -34,6 +34,7 @@ #include "qemu_monitor_json.h" #include "qemu_domain.h" #include "qemu_process.h" +#include "qemu_event.h" #include "virerror.h" #include "viralloc.h" #include "virlog.h" @@ -1316,6 +1317,14 @@ qemuMonitorGetDiskSecret(qemuMonitorPtr mon, return ret; } +static int +qemuMonitorEnqueueEvent(qemuMonitorPtr mon, qemuEventPtr ev) +{ + int ret = -1; + QEMU_MONITOR_CALLBACK(mon, ret, domainEnqueueEvent, ev->vm, ev); + + return ret; +} int qemuMonitorEmitEvent(qemuMonitorPtr mon, const char *event, @@ -1332,90 +1341,189 @@ qemuMonitorEmitEvent(qemuMonitorPtr mon, const char *event, int -qemuMonitorEmitShutdown(qemuMonitorPtr mon, virTristateBool guest) +qemuMonitorEmitShutdown(qemuMonitorPtr mon, virTristateBool guest, + long long seconds, unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p guest=%u", mon, guest); mon->willhangup = 1; + qemuEventPtr ev; + + if (VIR_ALLOC(ev) < 0){ + return ret; + } + + ev->ev_type = QEMU_EVENT_SHUTDOWN; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + ev->evData.ev_shutdown.guest_initiated = guest; - QEMU_MONITOR_CALLBACK(mon, ret, domainShutdown, mon->vm, guest); + VIR_DEBUG("Vm %s received shutdown event initiated by %u", + mon->vm->def->name, guest); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } int -qemuMonitorEmitReset(qemuMonitorPtr mon) +qemuMonitorEmitReset(qemuMonitorPtr mon, long long seconds, unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p", mon); + qemuEventPtr ev; + + if (VIR_ALLOC(ev) < 0){ + return ret; + } + + ev->ev_type = QEMU_EVENT_RESET; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; - QEMU_MONITOR_CALLBACK(mon, ret, domainReset, mon->vm); + VIR_DEBUG("Vm %s received reset event", mon->vm->def->name); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } int -qemuMonitorEmitPowerdown(qemuMonitorPtr mon) +qemuMonitorEmitPowerdown(qemuMonitorPtr mon, long long seconds, unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p", mon); + qemuEventPtr ev; + + if (VIR_ALLOC(ev) < 0){ + return ret; + } + + ev->ev_type = QEMU_EVENT_POWERDOWN; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; - QEMU_MONITOR_CALLBACK(mon, ret, domainPowerdown, mon->vm); + VIR_DEBUG("Vm %s received powerdown event", mon->vm->def->name); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } int -qemuMonitorEmitStop(qemuMonitorPtr mon) +qemuMonitorEmitStop(qemuMonitorPtr mon, long long seconds, unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p", mon); + qemuEventPtr ev; + + if (VIR_ALLOC(ev) < 0){ + return ret; + } + + ev->ev_type = QEMU_EVENT_STOP; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; - QEMU_MONITOR_CALLBACK(mon, ret, domainStop, mon->vm); + VIR_DEBUG("Vm %s received stop event", mon->vm->def->name); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } int -qemuMonitorEmitResume(qemuMonitorPtr mon) +qemuMonitorEmitResume(qemuMonitorPtr mon, long long seconds, unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p", mon); + qemuEventPtr ev; + + if (VIR_ALLOC(ev) < 0){ + return ret; + } + + ev->ev_type = QEMU_EVENT_RESUME; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; - QEMU_MONITOR_CALLBACK(mon, ret, domainResume, mon->vm); + VIR_DEBUG("Vm %s received resume event", mon->vm->def->name); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } int qemuMonitorEmitGuestPanic(qemuMonitorPtr mon, - qemuMonitorEventPanicInfoPtr info) + qemuMonitorEventPanicInfoPtr info, + long long seconds, unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p", mon); - QEMU_MONITOR_CALLBACK(mon, ret, domainGuestPanic, mon->vm, info); + qemuEventPtr ev; + + if (VIR_ALLOC(ev) < 0){ + return ret; + } + + ev->ev_type = QEMU_EVENT_GUEST_PANICKED; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + ev->evData.ev_panic.info = info; + + VIR_DEBUG("Vm %s received guest panic event", mon->vm->def->name); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } int -qemuMonitorEmitRTCChange(qemuMonitorPtr mon, long long offset) +qemuMonitorEmitRTCChange(qemuMonitorPtr mon, long long offset, + long long seconds, unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p", mon); + qemuEventPtr ev; + + if (VIR_ALLOC(ev) < 0){ + return ret; + } - QEMU_MONITOR_CALLBACK(mon, ret, domainRTCChange, mon->vm, offset); + ev->ev_type = QEMU_EVENT_RTC_CHANGE; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + ev->evData.ev_rtc.offset = offset; + + VIR_DEBUG("Vm %s received RTC change event", mon->vm->def->name); + + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } int -qemuMonitorEmitWatchdog(qemuMonitorPtr mon, int action) +qemuMonitorEmitWatchdog(qemuMonitorPtr mon, int action, + long long seconds, unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p", mon); + qemuEventPtr ev; + + if (VIR_ALLOC(ev) < 0){ + return ret; + } + + ev->ev_type = QEMU_EVENT_WATCHDOG; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + ev->evData.ev_watchdog.action = action; - QEMU_MONITOR_CALLBACK(mon, ret, domainWatchdog, mon->vm, action); + VIR_DEBUG("Vm %s received watchdog event", mon->vm->def->name); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } @@ -1424,13 +1532,39 @@ int qemuMonitorEmitIOError(qemuMonitorPtr mon, const char *diskAlias, int action, - const char *reason) + const char *reason, + long long seconds, unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p", mon); + qemuEventPtr ev; + struct qemuEventIOErrorData *d = NULL; + + if (VIR_ALLOC(ev) < 0){ + return ret; + } + + ev->ev_type = QEMU_EVENT_BLOCK_IO_ERROR; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + d = &(ev->evData.ev_IOErr); + d->action = action; - QEMU_MONITOR_CALLBACK(mon, ret, domainIOError, mon->vm, - diskAlias, action, reason); + if (VIR_STRDUP(d->device, diskAlias) < 0) { + goto cleanup; + } + if (VIR_STRDUP(d->reason, reason) < 0) { + goto cleanup; + } + VIR_DEBUG("Vm %s received block IO error event", mon->vm->def->name); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); + return ret +; +cleanup: + if (d->device) + VIR_FREE(d->device); + VIR_FREE(ev); return ret; } @@ -1446,15 +1580,73 @@ qemuMonitorEmitGraphics(qemuMonitorPtr mon, const char *remoteService, const char *authScheme, const char *x509dname, - const char *saslUsername) + const char *saslUsername, + long long seconds, unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p", mon); + qemuEventPtr ev; + struct qemuEventGraphicsData *d; + + if (VIR_ALLOC(ev) < 0){ + return ret; + } + + ev->ev_type = QEMU_EVENT_GRAPHICS; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + d = &(ev->evData.ev_graphics); + + d->phase = phase; + d->localFamilyID = localFamily; + d->remoteFamilyID = remoteFamily; + + if (VIR_STRDUP((d->localNode), localNode) < 0) { + goto cleanup; + } + + if (VIR_STRDUP((d->localService), localService) < 0) { + goto cleanup; + } + + if (VIR_STRDUP((d->remoteNode), remoteNode) < 0) { + goto cleanup; + } + + if (VIR_STRDUP((d->remoteService), remoteService) < 0) { + goto cleanup; + } + + if (VIR_STRDUP((d->authScheme), authScheme) < 0) { + goto cleanup; + } + + if (VIR_STRDUP((d->x509dname), x509dname) < 0) { + goto cleanup; + } - QEMU_MONITOR_CALLBACK(mon, ret, domainGraphics, mon->vm, phase, - localFamily, localNode, localService, - remoteFamily, remoteNode, remoteService, - authScheme, x509dname, saslUsername); + if (VIR_STRDUP((d->saslUsername), saslUsername) < 0) { + goto cleanup; + } + + VIR_DEBUG("Vm %s received Graphics event", mon->vm->def->name); + virObjectRef(ev->vm); + return ret; + +cleanup: + if (d->localNode) + VIR_FREE(d->localNode); + if (d->localService) + VIR_FREE(d->localService); + if (d->remoteNode) + VIR_FREE(d->remoteNode); + if (d->remoteService) + VIR_FREE(d->remoteService); + if (d->authScheme) + VIR_FREE(d->authScheme); + if (d->x509dname) + VIR_FREE(d->x509dname); + VIR_FREE(ev); return ret; } @@ -1462,50 +1654,101 @@ qemuMonitorEmitGraphics(qemuMonitorPtr mon, int qemuMonitorEmitTrayChange(qemuMonitorPtr mon, const char *devAlias, - int reason) + int reason, + long long seconds, + unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p", mon); + qemuEventPtr ev; + struct qemuEventTrayChangeData *d; - QEMU_MONITOR_CALLBACK(mon, ret, domainTrayChange, mon->vm, - devAlias, reason); + if (VIR_ALLOC(ev) < 0){ + return ret; + } + ev->ev_type = QEMU_EVENT_DEVICE_TRAY_MOVED; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + d = &(ev->evData.ev_tray); + + if (VIR_STRDUP((d->devAlias), devAlias) < 0) { + VIR_FREE(ev); + return ret; + } + d->reason = reason; + VIR_DEBUG("Vm %s received tray change event", mon->vm->def->name); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } int -qemuMonitorEmitPMWakeup(qemuMonitorPtr mon) +qemuMonitorEmitPMWakeup(qemuMonitorPtr mon, long long seconds, + unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p", mon); + qemuEventPtr ev; + + if (VIR_ALLOC(ev) < 0){ + return ret; + } - QEMU_MONITOR_CALLBACK(mon, ret, domainPMWakeup, mon->vm); + ev->ev_type = QEMU_EVENT_WAKEUP; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + VIR_DEBUG("Vm %s received PM Wakeup event", mon->vm->def->name); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } int -qemuMonitorEmitPMSuspend(qemuMonitorPtr mon) +qemuMonitorEmitPMSuspend(qemuMonitorPtr mon, long long seconds, + unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p", mon); + qemuEventPtr ev; - QEMU_MONITOR_CALLBACK(mon, ret, domainPMSuspend, mon->vm); + if (VIR_ALLOC(ev) < 0){ + return ret; + } + ev->ev_type = QEMU_EVENT_SUSPEND; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + + VIR_DEBUG("Vm %s received PM Suspend event", mon->vm->def->name); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } int -qemuMonitorEmitPMSuspendDisk(qemuMonitorPtr mon) +qemuMonitorEmitPMSuspendDisk(qemuMonitorPtr mon, long long seconds, + unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p", mon); + qemuEventPtr ev; - QEMU_MONITOR_CALLBACK(mon, ret, domainPMSuspendDisk, mon->vm); + if (VIR_ALLOC(ev) < 0){ + return ret; + } + + ev->ev_type = QEMU_EVENT_SUSPEND_DISK; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + VIR_DEBUG("Vm %s received PM Suspend Disk event", mon->vm->def->name); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } @@ -1514,51 +1757,122 @@ int qemuMonitorEmitBlockJob(qemuMonitorPtr mon, const char *diskAlias, int type, - int status) + int status, long long seconds, + unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p", mon); + qemuEventPtr ev; + struct qemuEventBlockJobData *d = NULL; + if (VIR_ALLOC(ev) < 0){ + return ret; + } + + ev->ev_type = QEMU_EVENT_BLOCK_JOB; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + d = &(ev->evData.ev_blockJob); + + if (VIR_STRDUP(d->device, diskAlias) < 0) { + VIR_FREE(ev); + return ret; + } - QEMU_MONITOR_CALLBACK(mon, ret, domainBlockJob, mon->vm, - diskAlias, type, status); + d->type = type; + d->status = status; + VIR_DEBUG("Vm %s received Block Job event", mon->vm->def->name); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } int qemuMonitorEmitBalloonChange(qemuMonitorPtr mon, - unsigned long long actual) + unsigned long long actual, + long long seconds, + unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p", mon); + qemuEventPtr ev; + + if (VIR_ALLOC(ev) < 0){ + return ret; + } + + ev->ev_type = QEMU_EVENT_BALLOON_CHANGE; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + ev->evData.ev_balloon.actual = actual; - QEMU_MONITOR_CALLBACK(mon, ret, domainBalloonChange, mon->vm, actual); + VIR_DEBUG("Vm %s received balloon change event", mon->vm->def->name); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } int qemuMonitorEmitDeviceDeleted(qemuMonitorPtr mon, - const char *devAlias) + const char *devAlias, + long long seconds, + unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p", mon); + qemuEventPtr ev; + struct qemuEventDeviceDeletedData *d = NULL; - QEMU_MONITOR_CALLBACK(mon, ret, domainDeviceDeleted, mon->vm, devAlias); + if (VIR_ALLOC(ev) < 0){ + return ret; + } + ev->ev_type = QEMU_EVENT_DEVICE_DELETED; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + d = &(ev->evData.ev_deviceDel); + + if (VIR_STRDUP(d->device, devAlias) < 0) { + VIR_FREE(ev); + return ret; + } + VIR_DEBUG("Vm %s received device deleted event for %s", mon->vm->def->name, + devAlias); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } int qemuMonitorEmitNicRxFilterChanged(qemuMonitorPtr mon, - const char *devAlias) + const char *devAlias, + long long seconds, + unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p", mon); + qemuEventPtr ev; + struct qemuEventNicRxFilterChangeData *d = NULL; + + if (VIR_ALLOC(ev) < 0){ + return ret; + } - QEMU_MONITOR_CALLBACK(mon, ret, domainNicRxFilterChanged, mon->vm, devAlias); + ev->ev_type = QEMU_EVENT_NIC_RX_FILTER_CHANGED; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + d = &(ev->evData.ev_nic); + if (VIR_STRDUP(d->devAlias, devAlias) < 0) { + VIR_FREE(ev); + return ret; + } + VIR_DEBUG("Vm %s received nic RX filter change event for %s", mon->vm->def->name, + devAlias); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } @@ -1566,52 +1880,110 @@ qemuMonitorEmitNicRxFilterChanged(qemuMonitorPtr mon, int qemuMonitorEmitSerialChange(qemuMonitorPtr mon, const char *devAlias, - bool connected) + bool connected, + long long seconds, + unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p, devAlias='%s', connected=%d", mon, devAlias, connected); + qemuEventPtr ev; + struct qemuEventSerialChangeData *d = NULL; + + if (VIR_ALLOC(ev) < 0){ + return ret; + } - QEMU_MONITOR_CALLBACK(mon, ret, domainSerialChange, mon->vm, devAlias, connected); + ev->ev_type = QEMU_EVENT_SERIAL_CHANGE; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + d = &(ev->evData.ev_serial); + d->connected = connected; + if (VIR_STRDUP(d->devAlias, devAlias) < 0) { + VIR_FREE(ev); + return ret; + } + VIR_DEBUG("Vm %s received Serial change event for %s", mon->vm->def->name, + devAlias); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } int -qemuMonitorEmitSpiceMigrated(qemuMonitorPtr mon) +qemuMonitorEmitSpiceMigrated(qemuMonitorPtr mon, long long seconds, + unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p", mon); + qemuEventPtr ev; + + if (VIR_ALLOC(ev) < 0){ + return ret; + } - QEMU_MONITOR_CALLBACK(mon, ret, domainSpiceMigrated, mon->vm); + ev->ev_type = QEMU_EVENT_SPICE_MIGRATED; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + VIR_DEBUG("Vm %s received spice migrated event", mon->vm->def->name); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } int qemuMonitorEmitMigrationStatus(qemuMonitorPtr mon, - int status) + int status, + long long seconds, + unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p, status=%s", - mon, NULLSTR(qemuMonitorMigrationStatusTypeToString(status))); + qemuEventPtr ev; - QEMU_MONITOR_CALLBACK(mon, ret, domainMigrationStatus, mon->vm, status); + if (VIR_ALLOC(ev) < 0){ + return ret; + } + ev->ev_type = QEMU_EVENT_MIGRATION; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + ev->evData.ev_migStatus.status = status; + + VIR_DEBUG("Vm %s received migration status %s", mon->vm->def->name, + NULLSTR(qemuMonitorMigrationStatusTypeToString(status))); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } int qemuMonitorEmitMigrationPass(qemuMonitorPtr mon, - int pass) + int pass, + long long seconds, + unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p, pass=%d", mon, pass); + qemuEventPtr ev; + + if (VIR_ALLOC(ev) < 0){ + return ret; + } - QEMU_MONITOR_CALLBACK(mon, ret, domainMigrationPass, mon->vm, pass); + ev->ev_type = QEMU_EVENT_MIGRATION_PASS; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + ev->evData.ev_migPass.pass = pass; + VIR_DEBUG("Vm %s received migration pass %d", mon->vm->def->name, + pass); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } @@ -1622,15 +1994,49 @@ qemuMonitorEmitAcpiOstInfo(qemuMonitorPtr mon, const char *slotType, const char *slot, unsigned int source, - unsigned int status) + unsigned int status, + long long seconds, + unsigned int micros) { int ret = -1; - VIR_DEBUG("mon=%p, alias='%s', slotType='%s', slot='%s', source='%u' status=%u", - mon, NULLSTR(alias), slotType, slot, source, status); + qemuEventPtr ev; + struct qemuEventAcpiOstInfoData *d = NULL; + + if (VIR_ALLOC(ev) < 0){ + return ret; + } + + ev->ev_type = QEMU_EVENT_ACPI_OST; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + ev->evData.ev_acpi.source = source; + ev->evData.ev_acpi.status = status; + + d = &(ev->evData.ev_acpi); + + if (VIR_STRDUP(d->alias, alias) < 0) { + goto cleanup; + } + if (VIR_STRDUP(d->slotType, slotType) < 0) { + goto cleanup; + } + if (VIR_STRDUP(d->slot, slot) < 0) { + goto cleanup; + } - QEMU_MONITOR_CALLBACK(mon, ret, domainAcpiOstInfo, mon->vm, - alias, slotType, slot, source, status); + VIR_DEBUG("Vm %s received ACPI OST event: alias[%s] slotType [%s] slot[%s]" + " status[%d]", mon->vm->def->name, alias, slotType, slot, status); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); + return ret; +cleanup: + if (d->alias) + VIR_FREE(d->alias); + if (d->slotType) + VIR_FREE(d->slotType); + VIR_FREE(ev); return ret; } @@ -1639,16 +2045,36 @@ int qemuMonitorEmitBlockThreshold(qemuMonitorPtr mon, const char *nodename, unsigned long long threshold, - unsigned long long excess) + unsigned long long excess, + long long seconds, + unsigned int micros) { int ret = -1; + qemuEventPtr ev; + struct qemuEventBlockThresholdData *d = NULL; - VIR_DEBUG("mon=%p, node-name='%s', threshold='%llu', excess='%llu'", - mon, nodename, threshold, excess); + if (VIR_ALLOC(ev) < 0){ + return ret; + } + + ev->ev_type = QEMU_EVENT_BLOCK_WRITE_THRESHOLD; + ev->vm = mon->vm; + ev->seconds = seconds; + ev->micros = micros; + ev->evData.ev_threshold.threshold = threshold; + ev->evData.ev_threshold.excess = excess; - QEMU_MONITOR_CALLBACK(mon, ret, domainBlockThreshold, mon->vm, - nodename, threshold, excess); + d = &(ev->evData.ev_threshold); + if (VIR_STRDUP(d->nodename, nodename) < 0) { + VIR_FREE(ev); + return ret; + } + VIR_DEBUG("Vm %s received Block Threshold event:" + "node-name='%s', threshold='%llu', excess='%llu'", + mon->vm->def->name, nodename, threshold, excess); + virObjectRef(ev->vm); + ret = qemuMonitorEnqueueEvent(mon, ev); return ret; } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index d9c27ac..7b5a984 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -35,6 +35,7 @@ # include "device_conf.h" # include "cpu/cpu.h" # include "util/virgic.h" +# include "qemu_event.h" typedef struct _qemuMonitor qemuMonitor; typedef qemuMonitor *qemuMonitorPtr; @@ -89,7 +90,7 @@ struct _qemuMonitorEventPanicInfoHyperv { }; typedef struct _qemuMonitorEventPanicInfo qemuMonitorEventPanicInfo; -typedef qemuMonitorEventPanicInfo *qemuMonitorEventPanicInfoPtr; +typedef qemuMonitorEventPanicInfo * qemuMonitorEventPanicInfoPtr; struct _qemuMonitorEventPanicInfo { qemuMonitorEventPanicInfoType type; union { @@ -128,6 +129,10 @@ typedef int (*qemuMonitorDomainEventCallback)(qemuMonitorPtr mon, unsigned int micros, const char *details, void *opaque); +typedef int (*qemuMonitorDomainEnqueueEventCallback)(qemuMonitorPtr mon, + virDomainObjPtr vm, + qemuEventPtr ev, + void *opaque); typedef int (*qemuMonitorDomainShutdownCallback)(qemuMonitorPtr mon, virDomainObjPtr vm, virTristateBool guest, @@ -254,6 +259,7 @@ struct _qemuMonitorCallbacks { qemuMonitorErrorNotifyCallback errorNotify; qemuMonitorDiskSecretLookupCallback diskSecretLookup; qemuMonitorDomainEventCallback domainEvent; + qemuMonitorDomainEnqueueEventCallback domainEnqueueEvent; qemuMonitorDomainShutdownCallback domainShutdown; qemuMonitorDomainResetCallback domainReset; qemuMonitorDomainPowerdownCallback domainPowerdown; @@ -345,17 +351,25 @@ int qemuMonitorGetDiskSecret(qemuMonitorPtr mon, int qemuMonitorEmitEvent(qemuMonitorPtr mon, const char *event, long long seconds, unsigned int micros, const char *details); -int qemuMonitorEmitShutdown(qemuMonitorPtr mon, virTristateBool guest); -int qemuMonitorEmitReset(qemuMonitorPtr mon); -int qemuMonitorEmitPowerdown(qemuMonitorPtr mon); -int qemuMonitorEmitStop(qemuMonitorPtr mon); -int qemuMonitorEmitResume(qemuMonitorPtr mon); -int qemuMonitorEmitRTCChange(qemuMonitorPtr mon, long long offset); -int qemuMonitorEmitWatchdog(qemuMonitorPtr mon, int action); +int qemuMonitorEmitShutdown(qemuMonitorPtr mon, virTristateBool guest, + long long seconds, unsigned int micros); +int qemuMonitorEmitReset(qemuMonitorPtr mon, + long long seconds, unsigned int micros); +int qemuMonitorEmitPowerdown(qemuMonitorPtr mon, + long long seconds, unsigned int micros); +int qemuMonitorEmitStop(qemuMonitorPtr mon, + long long seconds, unsigned int micros); +int qemuMonitorEmitResume(qemuMonitorPtr mon, + long long seconds, unsigned int micros); +int qemuMonitorEmitRTCChange(qemuMonitorPtr mon, long long offset, + long long seconds, unsigned int micros); +int qemuMonitorEmitWatchdog(qemuMonitorPtr mon, int action, + long long seconds, unsigned int micros); int qemuMonitorEmitIOError(qemuMonitorPtr mon, const char *diskAlias, int action, - const char *reason); + const char *reason, + long long seconds, unsigned int micros); int qemuMonitorEmitGraphics(qemuMonitorPtr mon, int phase, int localFamily, @@ -366,45 +380,61 @@ int qemuMonitorEmitGraphics(qemuMonitorPtr mon, const char *remoteService, const char *authScheme, const char *x509dname, - const char *saslUsername); + const char *saslUsername, + long long seconds, unsigned int micros); int qemuMonitorEmitTrayChange(qemuMonitorPtr mon, const char *devAlias, - int reason); -int qemuMonitorEmitPMWakeup(qemuMonitorPtr mon); -int qemuMonitorEmitPMSuspend(qemuMonitorPtr mon); + int reason, + long long seconds, unsigned int micros); +int qemuMonitorEmitPMWakeup(qemuMonitorPtr mon, + long long seconds, unsigned int micros); +int qemuMonitorEmitPMSuspend(qemuMonitorPtr mon, + long long seconds, unsigned int micros); int qemuMonitorEmitBlockJob(qemuMonitorPtr mon, const char *diskAlias, int type, - int status); + int status, + long long seconds, unsigned int micros); int qemuMonitorEmitBalloonChange(qemuMonitorPtr mon, - unsigned long long actual); -int qemuMonitorEmitPMSuspendDisk(qemuMonitorPtr mon); + unsigned long long actual, + long long seconds, unsigned int micros); +int qemuMonitorEmitPMSuspendDisk(qemuMonitorPtr mon, + long long seconds, unsigned int micros); int qemuMonitorEmitGuestPanic(qemuMonitorPtr mon, - qemuMonitorEventPanicInfoPtr info); + qemuMonitorEventPanicInfoPtr info, + long long seconds, unsigned int micros); int qemuMonitorEmitDeviceDeleted(qemuMonitorPtr mon, - const char *devAlias); + const char *devAlias, + long long seconds, unsigned int micros); int qemuMonitorEmitNicRxFilterChanged(qemuMonitorPtr mon, - const char *devAlias); + const char *devAlias, + long long seconds, unsigned int micros); int qemuMonitorEmitSerialChange(qemuMonitorPtr mon, const char *devAlias, - bool connected); -int qemuMonitorEmitSpiceMigrated(qemuMonitorPtr mon); + bool connected, + long long seconds, unsigned int micros); +int qemuMonitorEmitSpiceMigrated(qemuMonitorPtr mon, + long long seconds, unsigned int micros); int qemuMonitorEmitMigrationStatus(qemuMonitorPtr mon, - int status); + int status, + long long seconds, unsigned int micros); int qemuMonitorEmitMigrationPass(qemuMonitorPtr mon, - int pass); + int pass, + long long seconds, unsigned int micros); int qemuMonitorEmitAcpiOstInfo(qemuMonitorPtr mon, const char *alias, const char *slotType, const char *slot, unsigned int source, - unsigned int status); + unsigned int status, + long long seconds, unsigned int micros); int qemuMonitorEmitBlockThreshold(qemuMonitorPtr mon, const char *nodename, unsigned long long threshold, - unsigned long long excess); + unsigned long long excess, + long long seconds, unsigned int micros); int qemuMonitorStartCPUs(qemuMonitorPtr mon, virConnectPtr conn); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index a9070fe..b4c7118 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -59,41 +59,73 @@ VIR_LOG_INIT("qemu.qemu_monitor_json"); #define LINE_ENDING "\r\n" -static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleReset(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandlePowerdown(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleStop(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleResume(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleRTCChange(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleWatchdog(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleIOError(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleVNCConnect(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleVNCInitialize(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleVNCDisconnect(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleSPICEConnect(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleSPICEInitialize(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleSPICEDisconnect(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleTrayChange(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandlePMWakeup(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandlePMSuspend(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleBlockJobCompleted(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleBlockJobCanceled(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleBlockJobReady(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleBalloonChange(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandlePMSuspendDisk(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleGuestPanic(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleDeviceDeleted(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleSerialChange(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleSpiceMigrated(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleMigrationStatus(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleMigrationPass(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleAcpiOstInfo(qemuMonitorPtr mon, virJSONValuePtr data); -static void qemuMonitorJSONHandleBlockThreshold(qemuMonitorPtr mon, virJSONValuePtr data); +static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleReset(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandlePowerdown(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleStop(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleResume(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleRTCChange(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleWatchdog(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleIOError(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleVNCConnect(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleVNCInitialize(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleVNCDisconnect(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleSPICEConnect(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleSPICEInitialize(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleSPICEDisconnect(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleTrayChange(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandlePMWakeup(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandlePMSuspend(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleBlockJobCompleted(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleBlockJobCanceled(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleBlockJobReady(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleBalloonChange(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandlePMSuspendDisk(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleGuestPanic(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleDeviceDeleted(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleSerialChange(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleSpiceMigrated(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleMigrationStatus(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleMigrationPass(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleAcpiOstInfo(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); +static void qemuMonitorJSONHandleBlockThreshold(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); typedef struct { const char *type; - void (*handler)(qemuMonitorPtr mon, virJSONValuePtr data); + void (*handler)(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros); } qemuEventHandler; static qemuEventHandler eventHandlers[] = { @@ -146,7 +178,6 @@ qemuMonitorJSONIOProcessEvent(qemuMonitorPtr mon, const char *type; qemuEventHandler *handler; virJSONValuePtr data; - char *details = NULL; virJSONValuePtr timestamp; long long seconds = -1; unsigned int micros = 0; @@ -161,23 +192,20 @@ qemuMonitorJSONIOProcessEvent(qemuMonitorPtr mon, } /* Not all events have data; and event reporting is best-effort only */ - if ((data = virJSONValueObjectGet(obj, "data"))) - details = virJSONValueToString(data, false); + ignore_value(data = virJSONValueObjectGet(obj, "data")); if ((timestamp = virJSONValueObjectGet(obj, "timestamp"))) { ignore_value(virJSONValueObjectGetNumberLong(timestamp, "seconds", &seconds)); ignore_value(virJSONValueObjectGetNumberUint(timestamp, "microseconds", µs)); } - qemuMonitorEmitEvent(mon, type, seconds, micros, details); - VIR_FREE(details); handler = bsearch(type, eventHandlers, ARRAY_CARDINALITY(eventHandlers), sizeof(eventHandlers[0]), qemuMonitorEventCompare); if (handler) { VIR_DEBUG("handle %s handler=%p data=%p", type, handler->handler, data); - (handler->handler)(mon, data); + (handler->handler)(mon, data, seconds, micros); } return 0; } @@ -523,7 +551,8 @@ qemuMonitorJSONKeywordStringToJSON(const char *str, const char *firstkeyword) } -static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, virJSONValuePtr data) +static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros) { bool guest = false; virTristateBool guest_initiated = VIR_TRISTATE_BOOL_ABSENT; @@ -531,27 +560,35 @@ static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, virJSONValuePtr da if (data && virJSONValueObjectGetBoolean(data, "guest", &guest) == 0) guest_initiated = guest ? VIR_TRISTATE_BOOL_YES : VIR_TRISTATE_BOOL_NO; - qemuMonitorEmitShutdown(mon, guest_initiated); + qemuMonitorEmitShutdown(mon, guest_initiated, seconds, micros); } -static void qemuMonitorJSONHandleReset(qemuMonitorPtr mon, virJSONValuePtr data ATTRIBUTE_UNUSED) +static void qemuMonitorJSONHandleReset(qemuMonitorPtr mon, + virJSONValuePtr data ATTRIBUTE_UNUSED, + long long seconds, unsigned int micros) { - qemuMonitorEmitReset(mon); + qemuMonitorEmitReset(mon, seconds, micros); } -static void qemuMonitorJSONHandlePowerdown(qemuMonitorPtr mon, virJSONValuePtr data ATTRIBUTE_UNUSED) +static void qemuMonitorJSONHandlePowerdown(qemuMonitorPtr mon, + virJSONValuePtr data ATTRIBUTE_UNUSED, + long long seconds, unsigned int micros) { - qemuMonitorEmitPowerdown(mon); + qemuMonitorEmitPowerdown(mon, seconds, micros); } -static void qemuMonitorJSONHandleStop(qemuMonitorPtr mon, virJSONValuePtr data ATTRIBUTE_UNUSED) +static void qemuMonitorJSONHandleStop(qemuMonitorPtr mon, + virJSONValuePtr data ATTRIBUTE_UNUSED, + long long seconds, unsigned int micros) { - qemuMonitorEmitStop(mon); + qemuMonitorEmitStop(mon, seconds, micros); } -static void qemuMonitorJSONHandleResume(qemuMonitorPtr mon, virJSONValuePtr data ATTRIBUTE_UNUSED) +static void qemuMonitorJSONHandleResume(qemuMonitorPtr mon, + virJSONValuePtr data ATTRIBUTE_UNUSED, + long long seconds, unsigned int micros) { - qemuMonitorEmitResume(mon); + qemuMonitorEmitResume(mon, seconds, micros); } @@ -599,7 +636,9 @@ qemuMonitorJSONGuestPanicExtractInfo(virJSONValuePtr data) static void qemuMonitorJSONHandleGuestPanic(qemuMonitorPtr mon, - virJSONValuePtr data) + virJSONValuePtr data, + long long seconds, + unsigned int micros) { virJSONValuePtr infojson = virJSONValueObjectGetObject(data, "info"); qemuMonitorEventPanicInfoPtr info = NULL; @@ -607,25 +646,27 @@ qemuMonitorJSONHandleGuestPanic(qemuMonitorPtr mon, if (infojson) info = qemuMonitorJSONGuestPanicExtractInfo(infojson); - qemuMonitorEmitGuestPanic(mon, info); + qemuMonitorEmitGuestPanic(mon, info, seconds, micros); } -static void qemuMonitorJSONHandleRTCChange(qemuMonitorPtr mon, virJSONValuePtr data) +static void qemuMonitorJSONHandleRTCChange(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros) { long long offset = 0; if (virJSONValueObjectGetNumberLong(data, "offset", &offset) < 0) { VIR_WARN("missing offset in RTC change event"); offset = 0; } - qemuMonitorEmitRTCChange(mon, offset); + qemuMonitorEmitRTCChange(mon, offset, seconds, micros); } VIR_ENUM_DECL(qemuMonitorWatchdogAction) VIR_ENUM_IMPL(qemuMonitorWatchdogAction, VIR_DOMAIN_EVENT_WATCHDOG_LAST, "none", "pause", "reset", "poweroff", "shutdown", "debug", "inject-nmi"); -static void qemuMonitorJSONHandleWatchdog(qemuMonitorPtr mon, virJSONValuePtr data) +static void qemuMonitorJSONHandleWatchdog(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros) { const char *action; int actionID; @@ -639,7 +680,7 @@ static void qemuMonitorJSONHandleWatchdog(qemuMonitorPtr mon, virJSONValuePtr da } else { actionID = VIR_DOMAIN_EVENT_WATCHDOG_NONE; } - qemuMonitorEmitWatchdog(mon, actionID); + qemuMonitorEmitWatchdog(mon, actionID, seconds, micros); } VIR_ENUM_DECL(qemuMonitorIOErrorAction) @@ -648,7 +689,8 @@ VIR_ENUM_IMPL(qemuMonitorIOErrorAction, VIR_DOMAIN_EVENT_IO_ERROR_LAST, static void -qemuMonitorJSONHandleIOError(qemuMonitorPtr mon, virJSONValuePtr data) +qemuMonitorJSONHandleIOError(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros) { const char *device; const char *action; @@ -676,7 +718,7 @@ qemuMonitorJSONHandleIOError(qemuMonitorPtr mon, virJSONValuePtr data) actionID = VIR_DOMAIN_EVENT_IO_ERROR_NONE; } - qemuMonitorEmitIOError(mon, device, actionID, reason); + qemuMonitorEmitIOError(mon, device, actionID, reason, seconds, micros); } @@ -688,7 +730,8 @@ VIR_ENUM_IMPL(qemuMonitorGraphicsAddressFamily, static void qemuMonitorJSONHandleGraphicsVNC(qemuMonitorPtr mon, virJSONValuePtr data, - int phase) + int phase, + long long seconds, unsigned int micros) { const char *localNode, *localService, *localFamily; const char *remoteNode, *remoteService, *remoteFamily; @@ -753,31 +796,39 @@ qemuMonitorJSONHandleGraphicsVNC(qemuMonitorPtr mon, qemuMonitorEmitGraphics(mon, phase, localFamilyID, localNode, localService, remoteFamilyID, remoteNode, remoteService, - authScheme, x509dname, saslUsername); + authScheme, x509dname, saslUsername, + seconds, micros); } -static void qemuMonitorJSONHandleVNCConnect(qemuMonitorPtr mon, virJSONValuePtr data) +static void qemuMonitorJSONHandleVNCConnect(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros) { - qemuMonitorJSONHandleGraphicsVNC(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_CONNECT); + qemuMonitorJSONHandleGraphicsVNC(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_CONNECT, + seconds, micros); } -static void qemuMonitorJSONHandleVNCInitialize(qemuMonitorPtr mon, virJSONValuePtr data) +static void qemuMonitorJSONHandleVNCInitialize(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros) { - qemuMonitorJSONHandleGraphicsVNC(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE); + qemuMonitorJSONHandleGraphicsVNC(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE, + seconds, micros); } -static void qemuMonitorJSONHandleVNCDisconnect(qemuMonitorPtr mon, virJSONValuePtr data) +static void qemuMonitorJSONHandleVNCDisconnect(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros) { - qemuMonitorJSONHandleGraphicsVNC(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT); + qemuMonitorJSONHandleGraphicsVNC(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT, + seconds, micros); } static void qemuMonitorJSONHandleGraphicsSPICE(qemuMonitorPtr mon, virJSONValuePtr data, - int phase) + int phase, + long long seconds, unsigned int micros) { const char *lhost, *lport, *lfamily; const char *rhost, *rport, *rfamily; @@ -834,31 +885,39 @@ qemuMonitorJSONHandleGraphicsSPICE(qemuMonitorPtr mon, } qemuMonitorEmitGraphics(mon, phase, lfamilyID, lhost, lport, rfamilyID, - rhost, rport, auth, NULL, NULL); + rhost, rport, auth, NULL, NULL, + seconds, micros); } -static void qemuMonitorJSONHandleSPICEConnect(qemuMonitorPtr mon, virJSONValuePtr data) +static void qemuMonitorJSONHandleSPICEConnect(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros) { - qemuMonitorJSONHandleGraphicsSPICE(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_CONNECT); + qemuMonitorJSONHandleGraphicsSPICE(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_CONNECT, + seconds, micros); } -static void qemuMonitorJSONHandleSPICEInitialize(qemuMonitorPtr mon, virJSONValuePtr data) +static void qemuMonitorJSONHandleSPICEInitialize(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros) { - qemuMonitorJSONHandleGraphicsSPICE(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE); + qemuMonitorJSONHandleGraphicsSPICE(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE, + seconds, micros); } -static void qemuMonitorJSONHandleSPICEDisconnect(qemuMonitorPtr mon, virJSONValuePtr data) +static void qemuMonitorJSONHandleSPICEDisconnect(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros) { - qemuMonitorJSONHandleGraphicsSPICE(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT); + qemuMonitorJSONHandleGraphicsSPICE(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT, + seconds, micros); } static void qemuMonitorJSONHandleBlockJobImpl(qemuMonitorPtr mon, virJSONValuePtr data, - int event) + int event, + long long seconds, unsigned int micros) { const char *device; const char *type_str; @@ -908,12 +967,13 @@ qemuMonitorJSONHandleBlockJobImpl(qemuMonitorPtr mon, } out: - qemuMonitorEmitBlockJob(mon, device, type, event); + qemuMonitorEmitBlockJob(mon, device, type, event, seconds, micros); } static void qemuMonitorJSONHandleTrayChange(qemuMonitorPtr mon, - virJSONValuePtr data) + virJSONValuePtr data, + long long seconds, unsigned int micros) { const char *devAlias = NULL; bool trayOpened; @@ -934,50 +994,58 @@ qemuMonitorJSONHandleTrayChange(qemuMonitorPtr mon, else reason = VIR_DOMAIN_EVENT_TRAY_CHANGE_CLOSE; - qemuMonitorEmitTrayChange(mon, devAlias, reason); + qemuMonitorEmitTrayChange(mon, devAlias, reason, seconds, micros); } static void qemuMonitorJSONHandlePMWakeup(qemuMonitorPtr mon, - virJSONValuePtr data ATTRIBUTE_UNUSED) + virJSONValuePtr data ATTRIBUTE_UNUSED, + long long seconds, unsigned int micros) { - qemuMonitorEmitPMWakeup(mon); + qemuMonitorEmitPMWakeup(mon, micros, seconds); } static void qemuMonitorJSONHandlePMSuspend(qemuMonitorPtr mon, - virJSONValuePtr data ATTRIBUTE_UNUSED) + virJSONValuePtr data ATTRIBUTE_UNUSED, + long long seconds, unsigned int micros) { - qemuMonitorEmitPMSuspend(mon); + qemuMonitorEmitPMSuspend(mon, seconds, micros); } static void qemuMonitorJSONHandleBlockJobCompleted(qemuMonitorPtr mon, - virJSONValuePtr data) + virJSONValuePtr data, + long long seconds, unsigned int micros) { qemuMonitorJSONHandleBlockJobImpl(mon, data, - VIR_DOMAIN_BLOCK_JOB_COMPLETED); + VIR_DOMAIN_BLOCK_JOB_COMPLETED, + seconds, micros); } static void qemuMonitorJSONHandleBlockJobCanceled(qemuMonitorPtr mon, - virJSONValuePtr data) + virJSONValuePtr data, + long long seconds, unsigned int micros) { qemuMonitorJSONHandleBlockJobImpl(mon, data, - VIR_DOMAIN_BLOCK_JOB_CANCELED); + VIR_DOMAIN_BLOCK_JOB_CANCELED, + seconds, micros); } static void qemuMonitorJSONHandleBlockJobReady(qemuMonitorPtr mon, - virJSONValuePtr data) + virJSONValuePtr data, + long long seconds, unsigned int micros) { qemuMonitorJSONHandleBlockJobImpl(mon, data, - VIR_DOMAIN_BLOCK_JOB_READY); + VIR_DOMAIN_BLOCK_JOB_READY, seconds, micros); } static void qemuMonitorJSONHandleBalloonChange(qemuMonitorPtr mon, - virJSONValuePtr data) + virJSONValuePtr data, + long long seconds, unsigned int micros) { unsigned long long actual = 0; if (virJSONValueObjectGetNumberUlong(data, "actual", &actual) < 0) { @@ -985,18 +1053,20 @@ qemuMonitorJSONHandleBalloonChange(qemuMonitorPtr mon, return; } actual = VIR_DIV_UP(actual, 1024); - qemuMonitorEmitBalloonChange(mon, actual); + qemuMonitorEmitBalloonChange(mon, actual, seconds, micros); } static void qemuMonitorJSONHandlePMSuspendDisk(qemuMonitorPtr mon, - virJSONValuePtr data ATTRIBUTE_UNUSED) + virJSONValuePtr data ATTRIBUTE_UNUSED, + long long seconds, unsigned int micros) { - qemuMonitorEmitPMSuspendDisk(mon); + qemuMonitorEmitPMSuspendDisk(mon, seconds, micros); } static void -qemuMonitorJSONHandleDeviceDeleted(qemuMonitorPtr mon, virJSONValuePtr data) +qemuMonitorJSONHandleDeviceDeleted(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros) { const char *device; @@ -1005,12 +1075,13 @@ qemuMonitorJSONHandleDeviceDeleted(qemuMonitorPtr mon, virJSONValuePtr data) return; } - qemuMonitorEmitDeviceDeleted(mon, device); + qemuMonitorEmitDeviceDeleted(mon, device, seconds, micros); } static void -qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitorPtr mon, virJSONValuePtr data) +qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros) { const char *name; @@ -1019,13 +1090,14 @@ qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitorPtr mon, virJSONValuePtr data return; } - qemuMonitorEmitNicRxFilterChanged(mon, name); + qemuMonitorEmitNicRxFilterChanged(mon, name, seconds, micros); } static void qemuMonitorJSONHandleSerialChange(qemuMonitorPtr mon, - virJSONValuePtr data) + virJSONValuePtr data, + long long seconds, unsigned int micros) { const char *name; bool connected; @@ -1040,21 +1112,23 @@ qemuMonitorJSONHandleSerialChange(qemuMonitorPtr mon, return; } - qemuMonitorEmitSerialChange(mon, name, connected); + qemuMonitorEmitSerialChange(mon, name, connected, seconds, micros); } static void qemuMonitorJSONHandleSpiceMigrated(qemuMonitorPtr mon, - virJSONValuePtr data ATTRIBUTE_UNUSED) + virJSONValuePtr data ATTRIBUTE_UNUSED, + long long seconds, unsigned int micros) { - qemuMonitorEmitSpiceMigrated(mon); + qemuMonitorEmitSpiceMigrated(mon, seconds, micros); } static void qemuMonitorJSONHandleMigrationStatus(qemuMonitorPtr mon, - virJSONValuePtr data) + virJSONValuePtr data, + long long seconds, unsigned int micros) { const char *str; int status; @@ -1069,13 +1143,14 @@ qemuMonitorJSONHandleMigrationStatus(qemuMonitorPtr mon, return; } - qemuMonitorEmitMigrationStatus(mon, status); + qemuMonitorEmitMigrationStatus(mon, status, seconds, micros); } static void qemuMonitorJSONHandleMigrationPass(qemuMonitorPtr mon, - virJSONValuePtr data) + virJSONValuePtr data, + long long seconds, unsigned int micros) { int pass; @@ -1084,12 +1159,13 @@ qemuMonitorJSONHandleMigrationPass(qemuMonitorPtr mon, return; } - qemuMonitorEmitMigrationPass(mon, pass); + qemuMonitorEmitMigrationPass(mon, pass, seconds, micros); } static void -qemuMonitorJSONHandleAcpiOstInfo(qemuMonitorPtr mon, virJSONValuePtr data) +qemuMonitorJSONHandleAcpiOstInfo(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros) { virJSONValuePtr info; const char *alias; @@ -1116,7 +1192,8 @@ qemuMonitorJSONHandleAcpiOstInfo(qemuMonitorPtr mon, virJSONValuePtr data) if (virJSONValueObjectGetNumberUint(info, "status", &status) < 0) goto error; - qemuMonitorEmitAcpiOstInfo(mon, alias, slotType, slot, source, status); + qemuMonitorEmitAcpiOstInfo(mon, alias, slotType, slot, source, status, + seconds, micros); return; error: @@ -1126,7 +1203,8 @@ qemuMonitorJSONHandleAcpiOstInfo(qemuMonitorPtr mon, virJSONValuePtr data) static void -qemuMonitorJSONHandleBlockThreshold(qemuMonitorPtr mon, virJSONValuePtr data) +qemuMonitorJSONHandleBlockThreshold(qemuMonitorPtr mon, virJSONValuePtr data, + long long seconds, unsigned int micros) { const char *nodename; unsigned long long threshold; @@ -1141,7 +1219,8 @@ qemuMonitorJSONHandleBlockThreshold(qemuMonitorPtr mon, virJSONValuePtr data) if (virJSONValueObjectGetNumberUlong(data, "amount-exceeded", &excess) < 0) goto error; - qemuMonitorEmitBlockThreshold(mon, nodename, threshold, excess); + qemuMonitorEmitBlockThreshold(mon, nodename, threshold, excess, + seconds, micros); return; error: diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 8e6498e..ee8bae5 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -82,6 +82,12 @@ VIR_LOG_INIT("qemu.qemu_process"); +typedef struct { + qemuMonitorEventType type; + void (*handler_func)(qemuEventPtr ev, void *opaque); +} qemuEventFuncTable; + + /** * qemuProcessRemoveDomainStatus * @@ -474,20 +480,24 @@ qemuProcessFindVolumeQcowPassphrase(qemuMonitorPtr mon ATTRIBUTE_UNUSED, return ret; } - -static int -qemuProcessHandleReset(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - void *opaque) +static void +qemuProcessEventHandleReset(qemuEventPtr ev, + void *opaque) { virQEMUDriverPtr driver = opaque; virObjectEventPtr event; qemuDomainObjPrivatePtr priv; + virDomainObjPtr vm; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); - int ret = -1; - virObjectLock(vm); + if (!ev) + return; + if (!ev->vm) { + VIR_INFO("Dropping reset event for unknown VM"); + return; + } + vm = ev->vm; event = virDomainEventRebootNewFromObj(vm); priv = vm->privateData; if (priv->agent) @@ -516,12 +526,10 @@ qemuProcessHandleReset(qemuMonitorPtr mon ATTRIBUTE_UNUSED, qemuDomainObjEndJob(driver, vm); } - ret = 0; cleanup: - virObjectUnlock(vm); qemuDomainEventQueue(driver, event); virObjectUnref(cfg); - return ret; + return; } @@ -623,60 +631,69 @@ 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) + +void +qemuProcessEmitMonitorEvent(qemuEventPtr ev, + void *opaque) { virQEMUDriverPtr driver = opaque; virObjectEventPtr event = NULL; + virDomainObjPtr vm; + const char * eventName; - VIR_DEBUG("vm=%p", vm); + if (!ev) + return; + + vm = ev->vm; + + eventName = qemuMonitorEventTypeToString(ev->ev_type); + VIR_DEBUG("vm=%s monitor event %s", vm->def->name, eventName); - virObjectLock(vm); event = virDomainQemuMonitorEventNew(vm->def->id, vm->def->name, vm->def->uuid, eventName, - seconds, micros, details); - - virObjectUnlock(vm); - qemuDomainEventQueue(driver, event); + ev->seconds, ev->micros, NULL); + if (event) + qemuDomainEventQueue(driver, event); - return 0; + return; } -static int -qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - virTristateBool guest_initiated, - void *opaque) +static void +qemuProcessEventHandleShutdown(qemuEventPtr ev, + + void *opaque) { virQEMUDriverPtr driver = opaque; qemuDomainObjPrivatePtr priv; + virDomainObjPtr vm; + virTristateBool guest_initiated; virObjectEventPtr event = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); int detail = 0; - VIR_DEBUG("vm=%p", vm); + if (!ev) + return; + vm = ev->vm; - virObjectLock(vm); + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping SHUTDOWN event"); + goto exit; + } + VIR_DEBUG("Processing SHUTDOWN event for VM %s", vm->def->name); priv = vm->privateData; if (priv->gotShutdown) { VIR_DEBUG("Ignoring repeated SHUTDOWN event from domain %s", vm->def->name); - goto unlock; + goto exit; } else if (!virDomainObjIsActive(vm)) { VIR_DEBUG("Ignoring SHUTDOWN event from inactive domain %s", vm->def->name); - goto unlock; + goto exit; } priv->gotShutdown = true; - + guest_initiated = ev->evData.ev_shutdown.guest_initiated; VIR_DEBUG("Transitioned guest %s to shutdown state", vm->def->name); virDomainObjSetState(vm, @@ -710,34 +727,39 @@ qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED, qemuAgentNotifyEvent(priv->agent, QEMU_AGENT_EVENT_SHUTDOWN); qemuProcessShutdownOrReboot(driver, vm); - - unlock: - virObjectUnlock(vm); qemuDomainEventQueue(driver, event); - virObjectUnref(cfg); - return 0; + virObjectUnref(cfg); +exit: + return; } - -static int -qemuProcessHandleStop(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - void *opaque) +static void +qemuProcessEventHandleStop(qemuEventPtr ev, + void *opaque) { virQEMUDriverPtr driver = opaque; virObjectEventPtr event = NULL; virDomainPausedReason reason = VIR_DOMAIN_PAUSED_UNKNOWN; virDomainEventSuspendedDetailType detail = VIR_DOMAIN_EVENT_SUSPENDED_PAUSED; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + virDomainObjPtr vm; + + if (!ev) + return; + vm = ev->vm; + + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping STOP event"); + goto exit; + } - virObjectLock(vm); if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { qemuDomainObjPrivatePtr priv = vm->privateData; if (priv->gotShutdown) { VIR_DEBUG("Ignoring STOP event after SHUTDOWN"); - goto unlock; + goto exit; } if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT) { @@ -776,31 +798,38 @@ qemuProcessHandleStop(qemuMonitorPtr mon ATTRIBUTE_UNUSED, } } - unlock: - virObjectUnlock(vm); +exit: qemuDomainEventQueue(driver, event); virObjectUnref(cfg); - return 0; + return; } -static int -qemuProcessHandleResume(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, +static void +qemuProcessEventHandleResume(qemuEventPtr ev, void *opaque) { virQEMUDriverPtr driver = opaque; virObjectEventPtr event = NULL; + virDomainObjPtr vm; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); - virObjectLock(vm); + if (!ev) + return; + vm = ev->vm; + + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping RESUME event"); + goto exit; + } + if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) { qemuDomainObjPrivatePtr priv = vm->privateData; if (priv->gotShutdown) { VIR_DEBUG("Ignoring RESUME event after SHUTDOWN"); - goto unlock; + goto exit; } VIR_DEBUG("Transitioned guest %s out of paused into resumed state", @@ -818,25 +847,32 @@ qemuProcessHandleResume(qemuMonitorPtr mon ATTRIBUTE_UNUSED, } } - unlock: - virObjectUnlock(vm); +exit: qemuDomainEventQueue(driver, event); virObjectUnref(cfg); - return 0; + return; } -static int -qemuProcessHandleRTCChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - long long offset, - void *opaque) +static void +qemuProcessEventHandleRTCChange(qemuEventPtr ev, + void *opaque) { virQEMUDriverPtr driver = opaque; virObjectEventPtr event = NULL; + virDomainObjPtr vm; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + unsigned long long offset; - virObjectLock(vm); + if (!ev) + return; + vm = ev->vm; + + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping RTC event"); + goto exit; + } + offset = ev->evData.ev_rtc.offset; if (vm->def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_VARIABLE) { /* when a basedate is manually given on the qemu commandline * rather than simply "-rtc base=utc", the offset sent by qemu @@ -862,26 +898,33 @@ qemuProcessHandleRTCChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED, event = virDomainEventRTCChangeNewFromObj(vm, offset); - virObjectUnlock(vm); - - qemuDomainEventQueue(driver, event); + if (event) + qemuDomainEventQueue(driver, event); virObjectUnref(cfg); - return 0; +exit: + return; } - -static int -qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - int action, - void *opaque) +static void +qemuProcessEventHandleWatchdog1(qemuEventPtr ev, + void *opaque) { virQEMUDriverPtr driver = opaque; virObjectEventPtr watchdogEvent = NULL; virObjectEventPtr lifecycleEvent = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + virDomainObjPtr vm; + int action; - virObjectLock(vm); + if (!ev) + return; + vm = ev->vm; + + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping Watchdog event"); + goto exit; + } + action = ev->evData.ev_watchdog.action; watchdogEvent = virDomainEventWatchdogNewFromObj(vm, action); if (action == VIR_DOMAIN_EVENT_WATCHDOG_PAUSE && @@ -923,22 +966,16 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, } } - if (vm) - virObjectUnlock(vm); qemuDomainEventQueue(driver, watchdogEvent); qemuDomainEventQueue(driver, lifecycleEvent); virObjectUnref(cfg); - return 0; +exit: + return; } - -static int -qemuProcessHandleIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - const char *diskAlias, - int action, - const char *reason, +static void +qemuProcessEventHandleIOError(qemuEventPtr ev, void *opaque) { virQEMUDriverPtr driver = opaque; @@ -949,8 +986,24 @@ qemuProcessHandleIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED, const char *devAlias; virDomainDiskDefPtr disk; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + virDomainObjPtr vm; + const char *diskAlias; + int action; + const char *reason; + + if (!ev) + return; + vm = ev->vm; + + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping IO Error event"); + goto exit; + } + + diskAlias = ev->evData.ev_IOErr.device; + action = ev->evData.ev_IOErr.action; + reason = ev->evData.ev_IOErr.reason; - virObjectLock(vm); disk = qemuProcessFindDomainDiskByAlias(vm, diskAlias); if (disk) { @@ -975,7 +1028,7 @@ qemuProcessHandleIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED, virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_IOERROR); lifecycleEvent = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED, - VIR_DOMAIN_EVENT_SUSPENDED_IOERROR); + VIR_DOMAIN_PAUSED_IOERROR); VIR_FREE(priv->lockState); if (virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState) < 0) @@ -985,32 +1038,45 @@ qemuProcessHandleIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED, if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) VIR_WARN("Unable to save status on vm %s after IO error", vm->def->name); } - virObjectUnlock(vm); qemuDomainEventQueue(driver, ioErrorEvent); qemuDomainEventQueue(driver, ioErrorEvent2); qemuDomainEventQueue(driver, lifecycleEvent); + +exit: virObjectUnref(cfg); - return 0; + VIR_FREE(ev->evData.ev_IOErr.device); + VIR_FREE(ev->evData.ev_IOErr.reason); + return; } -static int -qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - const char *diskAlias, - int type, - int status, - void *opaque) +static void +qemuProcessEventHandleBlockJob(qemuEventPtr ev, + void *opaque) { virQEMUDriverPtr driver = opaque; struct qemuProcessEvent *processEvent = NULL; virDomainDiskDefPtr disk; qemuDomainDiskPrivatePtr diskPriv; char *data = NULL; + virDomainObjPtr vm; + const char *diskAlias; + int type, status; - virObjectLock(vm); + if (!ev) + return; + vm = ev->vm; - VIR_DEBUG("Block job for device %s (domain: %p,%s) type %d status %d", + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping Block Job event"); + goto cleanup; + } + + diskAlias = ev->evData.ev_blockJob.device; + type = ev->evData.ev_blockJob.type; + status = ev->evData.ev_blockJob.status; + + VIR_INFO("Block job for device %s (domain: %p,%s) type %d status %d", diskAlias, vm, vm->def->name, type, status); if (!(disk = qemuProcessFindDomainDiskByAlias(vm, diskAlias))) @@ -1043,8 +1109,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED, } cleanup: - virObjectUnlock(vm); - return 0; + return; error: if (processEvent) VIR_FREE(processEvent->data); @@ -1052,21 +1117,9 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED, goto cleanup; } - -static int -qemuProcessHandleGraphics(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - int phase, - int localFamily, - const char *localNode, - const char *localService, - int remoteFamily, - const char *remoteNode, - const char *remoteService, - const char *authScheme, - const char *x509dname, - const char *saslUsername, - void *opaque) +static void +qemuProcessEventHandleGraphics(qemuEventPtr ev, + void *opaque) { virQEMUDriverPtr driver = opaque; virObjectEventPtr event; @@ -1074,49 +1127,65 @@ qemuProcessHandleGraphics(qemuMonitorPtr mon ATTRIBUTE_UNUSED, virDomainEventGraphicsAddressPtr remoteAddr = NULL; virDomainEventGraphicsSubjectPtr subject = NULL; size_t i; + virDomainObjPtr vm; + struct qemuEventGraphicsData *data; + + if (!ev) + return; + vm = ev->vm; + + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping Graphics event"); + goto exit; + } + data = &(ev->evData.ev_graphics); if (VIR_ALLOC(localAddr) < 0) goto error; - localAddr->family = localFamily; - if (VIR_STRDUP(localAddr->service, localService) < 0 || - VIR_STRDUP(localAddr->node, localNode) < 0) + + localAddr->family = data->localFamilyID; + if (VIR_STRDUP(localAddr->service, data->localService) < 0 || + VIR_STRDUP(localAddr->node, data->localNode) < 0) goto error; if (VIR_ALLOC(remoteAddr) < 0) goto error; - remoteAddr->family = remoteFamily; - if (VIR_STRDUP(remoteAddr->service, remoteService) < 0 || - VIR_STRDUP(remoteAddr->node, remoteNode) < 0) + remoteAddr->family = data->remoteFamilyID; + if (VIR_STRDUP(remoteAddr->service, data->remoteService) < 0 || + VIR_STRDUP(remoteAddr->node, data->remoteNode) < 0) goto error; if (VIR_ALLOC(subject) < 0) goto error; - if (x509dname) { + if (data->x509dname) { if (VIR_REALLOC_N(subject->identities, subject->nidentity+1) < 0) goto error; subject->nidentity++; if (VIR_STRDUP(subject->identities[subject->nidentity-1].type, "x509dname") < 0 || - VIR_STRDUP(subject->identities[subject->nidentity-1].name, x509dname) < 0) + VIR_STRDUP(subject->identities[subject->nidentity-1].name, + data->x509dname) < 0) goto error; } - if (saslUsername) { + if (data->saslUsername) { if (VIR_REALLOC_N(subject->identities, subject->nidentity+1) < 0) goto error; subject->nidentity++; if (VIR_STRDUP(subject->identities[subject->nidentity-1].type, "saslUsername") < 0 || - VIR_STRDUP(subject->identities[subject->nidentity-1].name, saslUsername) < 0) + VIR_STRDUP(subject->identities[subject->nidentity-1].name, + data->saslUsername) < 0) goto error; } - virObjectLock(vm); - event = virDomainEventGraphicsNewFromObj(vm, phase, localAddr, remoteAddr, authScheme, subject); - virObjectUnlock(vm); + event = virDomainEventGraphicsNewFromObj(vm, data->phase, + localAddr, remoteAddr, + data->authScheme, + subject); qemuDomainEventQueue(driver, event); - return 0; + goto exit; - error: +error: if (localAddr) { VIR_FREE(localAddr->service); VIR_FREE(localAddr->node); @@ -1136,22 +1205,41 @@ qemuProcessHandleGraphics(qemuMonitorPtr mon ATTRIBUTE_UNUSED, VIR_FREE(subject); } - return -1; +exit: + VIR_FREE(ev->evData.ev_graphics.localNode); + VIR_FREE(ev->evData.ev_graphics.localService); + VIR_FREE(ev->evData.ev_graphics.remoteNode); + VIR_FREE(ev->evData.ev_graphics.remoteService); + VIR_FREE(ev->evData.ev_graphics.x509dname); + VIR_FREE(ev->evData.ev_graphics.saslUsername); + VIR_FREE(ev->evData.ev_graphics.authScheme); + return; } -static int -qemuProcessHandleTrayChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - const char *devAlias, - int reason, - void *opaque) +static void +qemuProcessEventHandleTrayChange(qemuEventPtr ev, + void *opaque) { virQEMUDriverPtr driver = opaque; virObjectEventPtr event = NULL; virDomainDiskDefPtr disk; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + virDomainObjPtr vm; + const char *devAlias; + int reason; + + if (!ev) + return; + vm = ev->vm; + + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping Graphics event"); + goto exit; + } + + devAlias = ev->evData.ev_tray.devAlias; + reason = ev->evData.ev_tray.reason; - virObjectLock(vm); disk = qemuProcessFindDomainDiskByAlias(vm, devAlias); if (disk) { @@ -1168,27 +1256,36 @@ qemuProcessHandleTrayChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED, VIR_WARN("Unable to save status on vm %s after tray moved event", vm->def->name); } - - virDomainObjBroadcast(vm); +// Why the broadcast here? +// virDomainObjBroadcast(vm); } - virObjectUnlock(vm); qemuDomainEventQueue(driver, event); virObjectUnref(cfg); - return 0; +exit: + VIR_FREE(ev->evData.ev_tray.devAlias); + return; } -static int -qemuProcessHandlePMWakeup(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - void *opaque) +static void +qemuProcessEventHandlePMWakeup(qemuEventPtr ev, + void *opaque) { virQEMUDriverPtr driver = opaque; virObjectEventPtr event = NULL; virObjectEventPtr lifecycleEvent = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + virDomainObjPtr vm; + + if (!ev) + return; + vm = ev->vm; + + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping PM Wakeup event"); + goto exit; + } - virObjectLock(vm); event = virDomainEventPMWakeupNewFromObj(vm); /* Don't set domain status back to running if it wasn't paused @@ -1210,24 +1307,32 @@ qemuProcessHandlePMWakeup(qemuMonitorPtr mon ATTRIBUTE_UNUSED, } } - virObjectUnlock(vm); qemuDomainEventQueue(driver, event); qemuDomainEventQueue(driver, lifecycleEvent); virObjectUnref(cfg); - return 0; +exit: + return; } -static int -qemuProcessHandlePMSuspend(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - void *opaque) +static void +qemuProcessEventHandlePMSuspend(qemuEventPtr ev, + void *opaque) { virQEMUDriverPtr driver = opaque; virObjectEventPtr event = NULL; virObjectEventPtr lifecycleEvent = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + virDomainObjPtr vm; + + if (!ev) + return; + vm = ev->vm; + + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping PM Suspend event"); + goto exit; + } - virObjectLock(vm); event = virDomainEventPMSuspendNewFromObj(vm); if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { @@ -1251,25 +1356,33 @@ qemuProcessHandlePMSuspend(qemuMonitorPtr mon ATTRIBUTE_UNUSED, qemuAgentNotifyEvent(priv->agent, QEMU_AGENT_EVENT_SUSPEND); } - virObjectUnlock(vm); - qemuDomainEventQueue(driver, event); qemuDomainEventQueue(driver, lifecycleEvent); virObjectUnref(cfg); - return 0; +exit: + return; } -static int -qemuProcessHandleBalloonChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - unsigned long long actual, - void *opaque) +static void +qemuProcessEventHandleBalloonChange(qemuEventPtr ev, + void *opaque) { virQEMUDriverPtr driver = opaque; virObjectEventPtr event = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + virDomainObjPtr vm; + unsigned long long actual; - virObjectLock(vm); + if (!ev) + return; + vm = ev->vm; + + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping Balloon event"); + goto exit; + } + + actual = ev->evData.ev_balloon.actual; event = virDomainEventBalloonChangeNewFromObj(vm, actual); VIR_DEBUG("Updating balloon from %lld to %lld kb", @@ -1279,24 +1392,30 @@ qemuProcessHandleBalloonChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED, if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) VIR_WARN("unable to save domain status with balloon change"); - virObjectUnlock(vm); - qemuDomainEventQueue(driver, event); virObjectUnref(cfg); - return 0; +exit: + return; } -static int -qemuProcessHandlePMSuspendDisk(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - void *opaque) +static void +qemuProcessEventHandlePMSuspendDisk(qemuEventPtr ev, + void *opaque) { virQEMUDriverPtr driver = opaque; virObjectEventPtr event = NULL; virObjectEventPtr lifecycleEvent = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + virDomainObjPtr vm; - virObjectLock(vm); + if (!ev) + return; + vm = ev->vm; + + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping PM Suspend disk event"); + goto exit; + } event = virDomainEventPMSuspendDiskNewFromObj(vm); if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { @@ -1320,28 +1439,35 @@ qemuProcessHandlePMSuspendDisk(qemuMonitorPtr mon ATTRIBUTE_UNUSED, qemuAgentNotifyEvent(priv->agent, QEMU_AGENT_EVENT_SUSPEND); } - virObjectUnlock(vm); - qemuDomainEventQueue(driver, event); qemuDomainEventQueue(driver, lifecycleEvent); virObjectUnref(cfg); - - return 0; +exit: + return; } -static int -qemuProcessHandleGuestPanic(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - qemuMonitorEventPanicInfoPtr info, - void *opaque) +static void +qemuProcessEventHandleGuestPanic(qemuEventPtr ev, + void *opaque) { virQEMUDriverPtr driver = opaque; struct qemuProcessEvent *processEvent; + virDomainObjPtr vm; + qemuMonitorEventPanicInfoPtr info; - virObjectLock(vm); + if (!ev) + return; + vm = ev->vm; + + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping Guest Panic event"); + goto exit; + } + + info = ev->evData.ev_panic.info; if (VIR_ALLOC(processEvent) < 0) - goto cleanup; + goto exit; processEvent->eventType = QEMU_PROCESS_EVENT_GUESTPANIC; processEvent->action = vm->def->onCrash; @@ -1357,26 +1483,31 @@ qemuProcessHandleGuestPanic(qemuMonitorPtr mon ATTRIBUTE_UNUSED, VIR_FREE(processEvent); } - cleanup: - if (vm) - virObjectUnlock(vm); - - return 0; +exit: + return; } -int -qemuProcessHandleDeviceDeleted(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - const char *devAlias, - void *opaque) +static void +qemuProcessEventHandleDeviceDeleted(qemuEventPtr ev, + void *opaque) { virQEMUDriverPtr driver = opaque; struct qemuProcessEvent *processEvent = NULL; char *data; + virDomainObjPtr vm; + const char *devAlias; - virObjectLock(vm); + if (!ev) + return; + vm = ev->vm; + + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping Device deleted event"); + goto cleanup; + } + devAlias = ev->evData.ev_deviceDel.device; VIR_DEBUG("Device %s removed from domain %p %s", devAlias, vm, vm->def->name); @@ -1400,8 +1531,8 @@ qemuProcessHandleDeviceDeleted(qemuMonitorPtr mon ATTRIBUTE_UNUSED, } cleanup: - virObjectUnlock(vm); - return 0; + VIR_FREE(ev->evData.ev_deviceDel.device); + return; error: if (processEvent) VIR_FREE(processEvent->data); @@ -1444,20 +1575,34 @@ qemuProcessHandleDeviceDeleted(qemuMonitorPtr mon ATTRIBUTE_UNUSED, * Note that qemu does not emit the event for all the documented sources or * devices. */ -static int -qemuProcessHandleAcpiOstInfo(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - const char *alias, - const char *slotType, - const char *slot, - unsigned int source, - unsigned int status, - void *opaque) + +static void +qemuProcessEventHandleAcpiOstInfo(qemuEventPtr ev, + void *opaque) { virQEMUDriverPtr driver = opaque; virObjectEventPtr event = NULL; + virDomainObjPtr vm; + const char *alias; + const char *slotType; + const char *slot; + unsigned int source; + unsigned int status; - virObjectLock(vm); + if (!ev) + return; + vm = ev->vm; + + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping ACPI event"); + goto exit; + } + + alias = ev->evData.ev_acpi.alias; + slotType = ev->evData.ev_acpi.slotType; + slot = ev->evData.ev_acpi.slot; + source = ev->evData.ev_acpi.source; + status = ev->evData.ev_acpi.status; VIR_DEBUG("ACPI OST info for device %s domain %p %s. " "slotType='%s' slot='%s' source=%u status=%u", @@ -1471,20 +1616,19 @@ qemuProcessHandleAcpiOstInfo(qemuMonitorPtr mon ATTRIBUTE_UNUSED, event = virDomainEventDeviceRemovalFailedNewFromObj(vm, alias); } - virObjectUnlock(vm); qemuDomainEventQueue(driver, event); - return 0; +exit: + VIR_FREE(ev->evData.ev_acpi.alias); + VIR_FREE(ev->evData.ev_acpi.slotType); + VIR_FREE(ev->evData.ev_acpi.slot); + return; } -static int -qemuProcessHandleBlockThreshold(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - const char *nodename, - unsigned long long threshold, - unsigned long long excess, - void *opaque) +static void +qemuProcessEventHandleBlockThreshold(qemuEventPtr ev, + void *opaque) { virQEMUDriverPtr driver = opaque; virObjectEventPtr event = NULL; @@ -1493,8 +1637,23 @@ qemuProcessHandleBlockThreshold(qemuMonitorPtr mon ATTRIBUTE_UNUSED, unsigned int idx; char *dev = NULL; const char *path = NULL; + virDomainObjPtr vm; + const char *nodename; + unsigned long long threshold; + unsigned long long excess; - virObjectLock(vm); + if (!ev) + return; + vm = ev->vm; + + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping Block Threshold event"); + goto exit; + } + + nodename = ev->evData.ev_threshold.nodename; + threshold = ev->evData.ev_threshold.threshold; + excess = ev->evData.ev_threshold.excess; VIR_DEBUG("BLOCK_WRITE_THRESHOLD event for block node '%s' in domain %p %s:" "threshold '%llu' exceeded by '%llu'", @@ -1511,25 +1670,33 @@ qemuProcessHandleBlockThreshold(qemuMonitorPtr mon ATTRIBUTE_UNUSED, } } - virObjectUnlock(vm); qemuDomainEventQueue(driver, event); - - return 0; +exit: + VIR_FREE(ev->evData.ev_threshold.nodename); + return; } -static int -qemuProcessHandleNicRxFilterChanged(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - const char *devAlias, - void *opaque) +static void +qemuProcessEventHandleNicRxFilterChanged(qemuEventPtr ev, + void *opaque) { virQEMUDriverPtr driver = opaque; struct qemuProcessEvent *processEvent = NULL; char *data; + virDomainObjPtr vm; + char *devAlias; - virObjectLock(vm); + if (!ev) + return; + vm = ev->vm; + + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping Nic Filter Change event"); + goto exit; + } + devAlias = ev->evData.ev_nic.devAlias; VIR_DEBUG("Device %s RX Filter changed in domain %p %s", devAlias, vm, vm->def->name); @@ -1548,30 +1715,39 @@ qemuProcessHandleNicRxFilterChanged(qemuMonitorPtr mon ATTRIBUTE_UNUSED, goto error; } - cleanup: - virObjectUnlock(vm); - return 0; +exit: + VIR_FREE(ev->evData.ev_nic.devAlias); + return; error: if (processEvent) VIR_FREE(processEvent->data); VIR_FREE(processEvent); - goto cleanup; + goto exit; } -static int -qemuProcessHandleSerialChanged(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - const char *devAlias, - bool connected, - void *opaque) +static void +qemuProcessEventHandleSerialChanged(qemuEventPtr ev, + void *opaque) { virQEMUDriverPtr driver = opaque; struct qemuProcessEvent *processEvent = NULL; char *data; + virDomainObjPtr vm; + char *devAlias; + bool connected; - virObjectLock(vm); + if (!ev) + return; + vm = ev->vm; + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping Serial Change event"); + goto cleanup; + } + + devAlias = ev->evData.ev_serial.devAlias; + connected = ev->evData.ev_serial.connected; VIR_DEBUG("Serial port %s state changed to '%d' in domain %p %s", devAlias, connected, vm, vm->def->name); @@ -1592,8 +1768,8 @@ qemuProcessHandleSerialChanged(qemuMonitorPtr mon ATTRIBUTE_UNUSED, } cleanup: - virObjectUnlock(vm); - return 0; + VIR_FREE(ev->evData.ev_serial.devAlias); + return; error: if (processEvent) VIR_FREE(processEvent->data); @@ -1602,14 +1778,21 @@ qemuProcessHandleSerialChanged(qemuMonitorPtr mon ATTRIBUTE_UNUSED, } -static int -qemuProcessHandleSpiceMigrated(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - void *opaque ATTRIBUTE_UNUSED) +static void +qemuProcessEventHandleSpiceMigrated(qemuEventPtr ev, + void *opaque ATTRIBUTE_UNUSED) { qemuDomainObjPrivatePtr priv; + virDomainObjPtr vm; - virObjectLock(vm); + if (!ev) + return; + vm = ev->vm; + + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping Spice Migrated event"); + goto cleanup; + } VIR_DEBUG("Spice migration completed for domain %p %s", vm, vm->def->name); @@ -1621,28 +1804,37 @@ qemuProcessHandleSpiceMigrated(qemuMonitorPtr mon ATTRIBUTE_UNUSED, } priv->job.spiceMigrated = true; - virDomainObjBroadcast(vm); +// virDomainObjBroadcast(vm); cleanup: - virObjectUnlock(vm); - return 0; + return; } -static int -qemuProcessHandleMigrationStatus(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - int status, - void *opaque ATTRIBUTE_UNUSED) +static void +qemuProcessEventHandleMigrationStatus(qemuEventPtr ev, + void *opaque ATTRIBUTE_UNUSED) { qemuDomainObjPrivatePtr priv; + virDomainObjPtr vm; + int status; - virObjectLock(vm); + if (!ev) + return; + vm = ev->vm; + + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping Migration Status event"); + goto cleanup; + } + + status = ev->evData.ev_migStatus.status; VIR_DEBUG("Migration of domain %p %s changed state to %s", vm, vm->def->name, qemuMonitorMigrationStatusTypeToString(status)); + priv = vm->privateData; if (priv->job.asyncJob == QEMU_ASYNC_JOB_NONE) { VIR_DEBUG("got MIGRATION event without a migration job"); @@ -1650,25 +1842,32 @@ qemuProcessHandleMigrationStatus(qemuMonitorPtr mon ATTRIBUTE_UNUSED, } priv->job.current->stats.status = status; - virDomainObjBroadcast(vm); +// virDomainObjBroadcast(vm); cleanup: - virObjectUnlock(vm); - return 0; + return; } -static int -qemuProcessHandleMigrationPass(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - int pass, - void *opaque) +static void +qemuProcessEventHandleMigrationPass(qemuEventPtr ev, + void *opaque) { virQEMUDriverPtr driver = opaque; qemuDomainObjPrivatePtr priv; + virDomainObjPtr vm; + int pass; - virObjectLock(vm); + if (!ev) + return; + vm = ev->vm; + if (!ev->vm) { + VIR_WARN("Unable to locate VM, dropping Migration Pass event"); + goto cleanup; + } + + pass = ev->evData.ev_migPass.pass; VIR_DEBUG("Migrating domain %p %s, iteration %d", vm, vm->def->name, pass); @@ -1681,42 +1880,58 @@ qemuProcessHandleMigrationPass(qemuMonitorPtr mon ATTRIBUTE_UNUSED, qemuDomainEventQueue(driver, virDomainEventMigrationIterationNewFromObj(vm, pass)); - cleanup: - virObjectUnlock(vm); - return 0; +cleanup: + return; } +static qemuEventFuncTable qemuEventFunctions[] = { + { QEMU_EVENT_ACPI_OST, qemuProcessEventHandleAcpiOstInfo, }, + { QEMU_EVENT_BALLOON_CHANGE, qemuProcessEventHandleBalloonChange, }, + { QEMU_EVENT_BLOCK_IO_ERROR, qemuProcessEventHandleIOError, }, + { QEMU_EVENT_BLOCK_JOB, qemuProcessEventHandleBlockJob, }, + { QEMU_EVENT_BLOCK_WRITE_THRESHOLD, qemuProcessEventHandleBlockThreshold, }, + { QEMU_EVENT_DEVICE_DELETED, qemuProcessEventHandleDeviceDeleted, }, + { QEMU_EVENT_DEVICE_TRAY_MOVED, qemuProcessEventHandleTrayChange, }, + { QEMU_EVENT_GRAPHICS, qemuProcessEventHandleGraphics,}, + { QEMU_EVENT_GUEST_PANICKED, qemuProcessEventHandleGuestPanic,}, + { QEMU_EVENT_MIGRATION, qemuProcessEventHandleMigrationStatus,}, + { QEMU_EVENT_MIGRATION_PASS, qemuProcessEventHandleMigrationPass,}, + { QEMU_EVENT_NIC_RX_FILTER_CHANGED, qemuProcessEventHandleNicRxFilterChanged, }, + { QEMU_EVENT_POWERDOWN, NULL, }, + { QEMU_EVENT_RESET, qemuProcessEventHandleReset, }, + { QEMU_EVENT_RESUME, qemuProcessEventHandleResume, }, + { QEMU_EVENT_RTC_CHANGE, qemuProcessEventHandleRTCChange, }, + { QEMU_EVENT_SHUTDOWN, qemuProcessEventHandleShutdown,}, + { QEMU_EVENT_SPICE_MIGRATED, qemuProcessEventHandleSpiceMigrated, }, + { QEMU_EVENT_STOP, qemuProcessEventHandleStop, }, + { QEMU_EVENT_SUSPEND, qemuProcessEventHandlePMSuspend,}, + { QEMU_EVENT_SUSPEND_DISK, qemuProcessEventHandlePMSuspendDisk,}, + { QEMU_EVENT_SERIAL_CHANGE, qemuProcessEventHandleSerialChanged,}, + { QEMU_EVENT_WAKEUP, qemuProcessEventHandlePMWakeup,}, + { QEMU_EVENT_WATCHDOG, qemuProcessEventHandleWatchdog1,}, +}; + +static int +qemuProcessEnqueueEvent(qemuMonitorPtr mon ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + qemuEventPtr ev, + void *opaque) +{ + virQEMUDriverPtr driver = opaque; + /* Bad code alert: Fix this lookup to scan table for correct index. + * Works for now since event table is sorted */ + ev->handler = qemuEventFunctions[ev->ev_type].handler_func; + return virEnqueueVMEvent(driver->ev_list, ev); +} static qemuMonitorCallbacks monitorCallbacks = { .eofNotify = qemuProcessHandleMonitorEOF, .errorNotify = qemuProcessHandleMonitorError, .diskSecretLookup = qemuProcessFindVolumeQcowPassphrase, - .domainEvent = qemuProcessHandleEvent, - .domainShutdown = qemuProcessHandleShutdown, - .domainStop = qemuProcessHandleStop, - .domainResume = qemuProcessHandleResume, - .domainReset = qemuProcessHandleReset, - .domainRTCChange = qemuProcessHandleRTCChange, - .domainWatchdog = qemuProcessHandleWatchdog, - .domainIOError = qemuProcessHandleIOError, - .domainGraphics = qemuProcessHandleGraphics, - .domainBlockJob = qemuProcessHandleBlockJob, - .domainTrayChange = qemuProcessHandleTrayChange, - .domainPMWakeup = qemuProcessHandlePMWakeup, - .domainPMSuspend = qemuProcessHandlePMSuspend, - .domainBalloonChange = qemuProcessHandleBalloonChange, - .domainPMSuspendDisk = qemuProcessHandlePMSuspendDisk, - .domainGuestPanic = qemuProcessHandleGuestPanic, - .domainDeviceDeleted = qemuProcessHandleDeviceDeleted, - .domainNicRxFilterChanged = qemuProcessHandleNicRxFilterChanged, - .domainSerialChange = qemuProcessHandleSerialChanged, - .domainSpiceMigrated = qemuProcessHandleSpiceMigrated, - .domainMigrationStatus = qemuProcessHandleMigrationStatus, - .domainMigrationPass = qemuProcessHandleMigrationPass, - .domainAcpiOstInfo = qemuProcessHandleAcpiOstInfo, - .domainBlockThreshold = qemuProcessHandleBlockThreshold, + .domainEnqueueEvent = qemuProcessEnqueueEvent, }; + static void qemuProcessMonitorReportLogError(qemuMonitorPtr mon, const char *msg, diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h index 814b86d..a2bbc4f 100644 --- a/src/qemu/qemu_process.h +++ b/src/qemu/qemu_process.h @@ -129,6 +129,8 @@ int qemuProcessFinishStartup(virConnectPtr conn, bool startCPUs, virDomainPausedReason pausedReason); +void qemuProcessEmitMonitorEvent(qemuEventPtr ev, + void *opaque); typedef enum { VIR_QEMU_PROCESS_STOP_MIGRATED = 1 << 0, VIR_QEMU_PROCESS_STOP_NO_RELABEL = 1 << 1, diff --git a/tests/qemumonitortestutils.c b/tests/qemumonitortestutils.c index 5e30fb0..94375a3 100644 --- a/tests/qemumonitortestutils.c +++ b/tests/qemumonitortestutils.c @@ -1013,7 +1013,7 @@ qemuMonitorTestErrorNotify(qemuMonitorPtr mon ATTRIBUTE_UNUSED, static qemuMonitorCallbacks qemuMonitorTestCallbacks = { .eofNotify = qemuMonitorTestEOFNotify, .errorNotify = qemuMonitorTestErrorNotify, - .domainDeviceDeleted = qemuProcessHandleDeviceDeleted, + .domainDeviceDeleted = NULL, //qemuProcessHandleDeviceDeleted, }; -- 2.9.5 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list