[libvirt] [PATCHv2 0/6] server-side domain event filtering

v1 was here: https://www.redhat.com/archives/libvir-list/2014-January/msg00689.html Since then, I've rebased it on top of this patch which still needs review: https://www.redhat.com/archives/libvir-list/2014-January/msg01406.html as well as added patch 6 so that we don't have to repeat the exercise of adding a new RPC down the road. Eric Blake (6): event: dynamically manage server-side RPC domain events event: server RPC protocol tweaks for domain lifecycle events event: prepare client to track domain callbackID event: client RPC protocol tweaks for domain lifecycle events event: convert remaining domain events to new style event: pass reason for PM events daemon/libvirtd.h | 3 +- daemon/remote.c | 665 ++++++++++++++++++++++++++------- src/conf/domain_event.c | 184 ++++++++-- src/conf/domain_event.h | 28 +- src/conf/network_event.c | 6 +- src/conf/object_event.c | 35 +- src/conf/object_event_private.h | 6 +- src/libvirt_internal.h | 7 +- src/remote/remote_driver.c | 796 ++++++++++++++++++++++++++++++++-------- src/remote/remote_protocol.x | 195 +++++++++- src/remote_protocol-structs | 95 +++++ 11 files changed, 1679 insertions(+), 341 deletions(-) -- 1.8.5.3

This patch continues the earlier conversion made for network events, with a goal of introducing server-side event filtering in a later patch. Actual behavior is unchanged without further RPC changes. * daemon/libvirtd.h (daemonClientPrivate): Alter the tracking of domain events. * daemon/remote.c (remoteClientInitHook, remoteClientFreeFunc) (remoteRelayDomainEvent*) (remoteDispatchConnectDomainEventRegister) (remoteDispatchConnectDomainEventRegisterAny): Track domain callbacks dynamically. --- daemon/libvirtd.h | 3 +- daemon/remote.c | 294 +++++++++++++++++++++++++++++++++++------------------- 2 files changed, 194 insertions(+), 103 deletions(-) diff --git a/daemon/libvirtd.h b/daemon/libvirtd.h index a260ea1..c4f1f27 100644 --- a/daemon/libvirtd.h +++ b/daemon/libvirtd.h @@ -51,7 +51,8 @@ struct daemonClientPrivate { /* Hold while accessing any data except conn */ virMutex lock; - int domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LAST]; + daemonClientEventCallbackPtr *domainEventCallbacks; + size_t ndomainEventCallbacks; daemonClientEventCallbackPtr *networkEventCallbacks; size_t nnetworkEventCallbacks; diff --git a/daemon/remote.c b/daemon/remote.c index 5baf0b6..be0af3d 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -192,13 +192,15 @@ remoteRelayDomainEventLifecycle(virConnectPtr conn, int detail, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_lifecycle_msg data; - if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) return -1; - VIR_DEBUG("Relaying domain lifecycle event %d %d", event, detail); + VIR_DEBUG("Relaying domain lifecycle event %d %d, callback %d", + event, detail, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); @@ -206,7 +208,7 @@ remoteRelayDomainEventLifecycle(virConnectPtr conn, data.event = event; data.detail = detail; - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE, (xdrproc_t)xdr_remote_domain_event_lifecycle_msg, &data); @@ -218,19 +220,21 @@ remoteRelayDomainEventReboot(virConnectPtr conn, virDomainPtr dom, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_reboot_msg data; - if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) return -1; - VIR_DEBUG("Relaying domain reboot event %s %d", dom->name, dom->id); + VIR_DEBUG("Relaying domain reboot event %s %d, callback %d", + dom->name, dom->id, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_REBOOT, (xdrproc_t)xdr_remote_domain_event_reboot_msg, &data); @@ -244,20 +248,22 @@ remoteRelayDomainEventRTCChange(virConnectPtr conn, long long offset, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_rtc_change_msg data; - if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) return -1; - VIR_DEBUG("Relaying domain rtc change event %s %d %lld", dom->name, dom->id, offset); + VIR_DEBUG("Relaying domain rtc change event %s %d %lld, callback %d", + dom->name, dom->id, offset, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); data.offset = offset; - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE, (xdrproc_t)xdr_remote_domain_event_rtc_change_msg, &data); @@ -271,20 +277,22 @@ remoteRelayDomainEventWatchdog(virConnectPtr conn, int action, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_watchdog_msg data; - if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) return -1; - VIR_DEBUG("Relaying domain watchdog event %s %d %d", dom->name, dom->id, action); + VIR_DEBUG("Relaying domain watchdog event %s %d %d, callback %d", + dom->name, dom->id, action, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); data.action = action; - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_WATCHDOG, (xdrproc_t)xdr_remote_domain_event_watchdog_msg, &data); @@ -300,13 +308,16 @@ remoteRelayDomainEventIOError(virConnectPtr conn, int action, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_io_error_msg data; - if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) return -1; - VIR_DEBUG("Relaying domain io error %s %d %s %s %d", dom->name, dom->id, srcPath, devAlias, action); + VIR_DEBUG("Relaying domain io error %s %d %s %s %d, callback %d", + dom->name, dom->id, srcPath, devAlias, action, + callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); @@ -316,7 +327,7 @@ remoteRelayDomainEventIOError(virConnectPtr conn, make_nonnull_domain(&data.dom, dom); data.action = action; - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_IO_ERROR, (xdrproc_t)xdr_remote_domain_event_io_error_msg, &data); @@ -337,14 +348,16 @@ remoteRelayDomainEventIOErrorReason(virConnectPtr conn, const char *reason, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_io_error_reason_msg data; - if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) return -1; - VIR_DEBUG("Relaying domain io error %s %d %s %s %d %s", - dom->name, dom->id, srcPath, devAlias, action, reason); + VIR_DEBUG("Relaying domain io error %s %d %s %s %d %s, callback %d", + dom->name, dom->id, srcPath, devAlias, action, reason, + callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); @@ -356,7 +369,7 @@ remoteRelayDomainEventIOErrorReason(virConnectPtr conn, make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON, (xdrproc_t)xdr_remote_domain_event_io_error_reason_msg, &data); @@ -380,17 +393,19 @@ remoteRelayDomainEventGraphics(virConnectPtr conn, virDomainEventGraphicsSubjectPtr subject, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_graphics_msg data; size_t i; - if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) return -1; - VIR_DEBUG("Relaying domain graphics event %s %d %d - %d %s %s - %d %s %s - %s", dom->name, dom->id, phase, + VIR_DEBUG("Relaying domain graphics event %s %d %d - %d %s %s - %d %s %s - %s, callback %d", + dom->name, dom->id, phase, local->family, local->service, local->node, remote->family, remote->service, remote->node, - authScheme); + authScheme, callback->callbackID); VIR_DEBUG("Subject %d", subject->nidentity); for (i = 0; i < subject->nidentity; i++) { @@ -420,7 +435,7 @@ remoteRelayDomainEventGraphics(virConnectPtr conn, } make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_GRAPHICS, (xdrproc_t)xdr_remote_domain_event_graphics_msg, &data); @@ -450,14 +465,15 @@ remoteRelayDomainEventBlockJob(virConnectPtr conn, int status, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_block_job_msg data; - if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) return -1; - VIR_DEBUG("Relaying domain block job event %s %d %s %i, %i", - dom->name, dom->id, path, type, status); + VIR_DEBUG("Relaying domain block job event %s %d %s %i, %i, callback %d", + dom->name, dom->id, path, type, status, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); @@ -467,7 +483,7 @@ remoteRelayDomainEventBlockJob(virConnectPtr conn, data.status = status; make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB, (xdrproc_t)xdr_remote_domain_event_block_job_msg, &data); @@ -483,19 +499,21 @@ remoteRelayDomainEventControlError(virConnectPtr conn, virDomainPtr dom, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_control_error_msg data; - if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) return -1; - VIR_DEBUG("Relaying domain control error %s %d", dom->name, dom->id); + VIR_DEBUG("Relaying domain control error %s %d, callback %d", + dom->name, dom->id, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_CONTROL_ERROR, (xdrproc_t)xdr_remote_domain_event_control_error_msg, &data); @@ -512,15 +530,17 @@ remoteRelayDomainEventDiskChange(virConnectPtr conn, int reason, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_disk_change_msg data; char **oldSrcPath_p = NULL, **newSrcPath_p = NULL; - if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) return -1; - VIR_DEBUG("Relaying domain %s %d disk change %s %s %s %d", - dom->name, dom->id, oldSrcPath, newSrcPath, devAlias, reason); + VIR_DEBUG("Relaying domain %s %d disk change %s %s %s %d, callback %d", + dom->name, dom->id, oldSrcPath, newSrcPath, devAlias, reason, + callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); @@ -542,7 +562,7 @@ remoteRelayDomainEventDiskChange(virConnectPtr conn, make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_DISK_CHANGE, (xdrproc_t)xdr_remote_domain_event_disk_change_msg, &data); @@ -562,14 +582,15 @@ remoteRelayDomainEventTrayChange(virConnectPtr conn, int reason, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_tray_change_msg data; - if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) return -1; - VIR_DEBUG("Relaying domain %s %d tray change devAlias: %s reason: %d", - dom->name, dom->id, devAlias, reason); + VIR_DEBUG("Relaying domain %s %d tray change devAlias: %s reason: %d, callback %d", + dom->name, dom->id, devAlias, reason, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); @@ -580,7 +601,7 @@ remoteRelayDomainEventTrayChange(virConnectPtr conn, make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_TRAY_CHANGE, (xdrproc_t)xdr_remote_domain_event_tray_change_msg, &data); @@ -593,19 +614,21 @@ remoteRelayDomainEventPMWakeup(virConnectPtr conn, int reason ATTRIBUTE_UNUSED, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_pmwakeup_msg data; - if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) return -1; - VIR_DEBUG("Relaying domain %s %d system pmwakeup", dom->name, dom->id); + VIR_DEBUG("Relaying domain %s %d system pmwakeup, callback %d", + dom->name, dom->id, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_PMWAKEUP, (xdrproc_t)xdr_remote_domain_event_pmwakeup_msg, &data); @@ -618,19 +641,21 @@ remoteRelayDomainEventPMSuspend(virConnectPtr conn, int reason ATTRIBUTE_UNUSED, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_pmsuspend_msg data; - if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) return -1; - VIR_DEBUG("Relaying domain %s %d system pmsuspend", dom->name, dom->id); + VIR_DEBUG("Relaying domain %s %d system pmsuspend, callback %d", + dom->name, dom->id, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_PMSUSPEND, (xdrproc_t)xdr_remote_domain_event_pmsuspend_msg, &data); @@ -643,20 +668,22 @@ remoteRelayDomainEventBalloonChange(virConnectPtr conn, unsigned long long actual, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_balloon_change_msg data; - if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) return -1; - VIR_DEBUG("Relaying domain balloon change event %s %d %lld", dom->name, dom->id, actual); + VIR_DEBUG("Relaying domain balloon change event %s %d %lld, callback %d", + dom->name, dom->id, actual, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); data.actual = actual; - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_BALLOON_CHANGE, (xdrproc_t)xdr_remote_domain_event_balloon_change_msg, &data); @@ -670,19 +697,21 @@ remoteRelayDomainEventPMSuspendDisk(virConnectPtr conn, int reason ATTRIBUTE_UNUSED, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_pmsuspend_disk_msg data; - if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) return -1; - VIR_DEBUG("Relaying domain %s %d system pmsuspend-disk", dom->name, dom->id); + VIR_DEBUG("Relaying domain %s %d system pmsuspend-disk, callback %d", + dom->name, dom->id, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_PMSUSPEND_DISK, (xdrproc_t)xdr_remote_domain_event_pmsuspend_disk_msg, &data); @@ -695,14 +724,15 @@ remoteRelayDomainEventDeviceRemoved(virConnectPtr conn, const char *devAlias, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_device_removed_msg data; - if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) return -1; - VIR_DEBUG("Relaying domain device removed event %s %d %s", - dom->name, dom->id, devAlias); + VIR_DEBUG("Relaying domain device removed event %s %d %s, callback %d", + dom->name, dom->id, devAlias, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); @@ -712,7 +742,7 @@ remoteRelayDomainEventDeviceRemoved(virConnectPtr conn, make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED, (xdrproc_t)xdr_remote_domain_event_device_removed_msg, &data); @@ -797,14 +827,19 @@ void remoteClientFreeFunc(void *data) virIdentitySetCurrent(sysident); - for (i = 0; i < VIR_DOMAIN_EVENT_ID_LAST; i++) { - if (priv->domainEventCallbackID[i] != -1) { - VIR_DEBUG("Deregistering to relay remote events %zu", i); - virConnectDomainEventDeregisterAny(priv->conn, - priv->domainEventCallbackID[i]); + for (i = 0; i < priv->ndomainEventCallbacks; i++) { + int callbackID = priv->domainEventCallbacks[i]->callbackID; + if (callbackID < 0) { + VIR_WARN("unexpected incomplete domain callback %zu", i); + continue; } - priv->domainEventCallbackID[i] = -1; + VIR_DEBUG("Deregistering remote domain event relay %d", + callbackID); + priv->domainEventCallbacks[i]->callbackID = -1; + if (virConnectDomainEventDeregisterAny(priv->conn, callbackID) < 0) + VIR_WARN("unexpected domain event deregister failure"); } + VIR_FREE(priv->domainEventCallbacks); for (i = 0; i < priv->nnetworkEventCallbacks; i++) { int callbackID = priv->networkEventCallbacks[i]->callbackID; @@ -843,7 +878,6 @@ void *remoteClientInitHook(virNetServerClientPtr client, void *opaque ATTRIBUTE_UNUSED) { struct daemonClientPrivate *priv; - size_t i; if (VIR_ALLOC(priv) < 0) return NULL; @@ -854,9 +888,6 @@ void *remoteClientInitHook(virNetServerClientPtr client, return NULL; } - for (i = 0; i < VIR_DOMAIN_EVENT_ID_LAST; i++) - priv->domainEventCallbackID[i] = -1; - virNetServerClientSetCloseHook(client, remoteClientCloseFunc); return priv; } @@ -3220,13 +3251,15 @@ cleanup: ***************************/ static int remoteDispatchConnectDomainEventRegister(virNetServerPtr server ATTRIBUTE_UNUSED, - virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetServerClientPtr client, virNetMessagePtr msg ATTRIBUTE_UNUSED, virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED, remote_connect_domain_event_register_ret *ret ATTRIBUTE_UNUSED) { int callbackID; int rv = -1; + daemonClientEventCallbackPtr callback = NULL; + daemonClientEventCallbackPtr ref; struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client); @@ -3237,23 +3270,41 @@ remoteDispatchConnectDomainEventRegister(virNetServerPtr server ATTRIBUTE_UNUSED virMutexLock(&priv->lock); - if (priv->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE] != -1) { - virReportError(VIR_ERR_INTERNAL_ERROR, _("domain event %d already registered"), VIR_DOMAIN_EVENT_ID_LIFECYCLE); + /* If we call register first, we could append a complete callback + * to our array, but on OOM append failure, we'd have to then hope + * deregister works to undo our register. So instead we append an + * incomplete callback to our array, then register, then fix up + * our callback; but since VIR_APPEND_ELEMENT clears 'callback' on + * success, we use 'ref' to save a copy of the pointer. */ + if (VIR_ALLOC(callback) < 0) + goto cleanup; + callback->client = client; + callback->eventID = VIR_DOMAIN_EVENT_ID_LIFECYCLE; + callback->callbackID = -1; + ref = callback; + if (VIR_APPEND_ELEMENT(priv->domainEventCallbacks, + priv->ndomainEventCallbacks, + callback) < 0) goto cleanup; - } if ((callbackID = virConnectDomainEventRegisterAny(priv->conn, NULL, VIR_DOMAIN_EVENT_ID_LIFECYCLE, VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle), - client, NULL)) < 0) + ref, + remoteEventCallbackFree)) < 0) { + VIR_SHRINK_N(priv->domainEventCallbacks, + priv->ndomainEventCallbacks, 1); + callback = ref; goto cleanup; + } - priv->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE] = callbackID; + ref->callbackID = callbackID; rv = 0; cleanup: + VIR_FREE(callback); if (rv < 0) virNetMessageSaveError(rerr); virMutexUnlock(&priv->lock); @@ -3262,12 +3313,14 @@ cleanup: static int remoteDispatchConnectDomainEventDeregister(virNetServerPtr server ATTRIBUTE_UNUSED, - virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetServerClientPtr client, virNetMessagePtr msg ATTRIBUTE_UNUSED, virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED, remote_connect_domain_event_deregister_ret *ret ATTRIBUTE_UNUSED) { + int callbackID = -1; int rv = -1; + size_t i; struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client); @@ -3278,16 +3331,25 @@ remoteDispatchConnectDomainEventDeregister(virNetServerPtr server ATTRIBUTE_UNUS virMutexLock(&priv->lock); - if (priv->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE] < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, _("domain event %d not registered"), VIR_DOMAIN_EVENT_ID_LIFECYCLE); + for (i = 0; i < priv->ndomainEventCallbacks; i++) { + if (priv->domainEventCallbacks[i]->eventID == VIR_DOMAIN_EVENT_ID_LIFECYCLE) { + callbackID = priv->domainEventCallbacks[i]->callbackID; + break; + } + } + + if (callbackID < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("domain event %d not registered"), + VIR_DOMAIN_EVENT_ID_LIFECYCLE); goto cleanup; } - if (virConnectDomainEventDeregisterAny(priv->conn, - priv->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE]) < 0) + if (virConnectDomainEventDeregisterAny(priv->conn, callbackID) < 0) goto cleanup; - priv->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE] = -1; + VIR_DELETE_ELEMENT(priv->domainEventCallbacks, i, + priv->ndomainEventCallbacks); rv = 0; @@ -3409,13 +3471,15 @@ cleanup: static int remoteDispatchConnectDomainEventRegisterAny(virNetServerPtr server ATTRIBUTE_UNUSED, - virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetServerClientPtr client, virNetMessagePtr msg ATTRIBUTE_UNUSED, virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED, remote_connect_domain_event_register_any_args *args) { int callbackID; int rv = -1; + daemonClientEventCallbackPtr callback = NULL; + daemonClientEventCallbackPtr ref; struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client); @@ -3432,23 +3496,41 @@ remoteDispatchConnectDomainEventRegisterAny(virNetServerPtr server ATTRIBUTE_UNU goto cleanup; } - if (priv->domainEventCallbackID[args->eventID] != -1) { - virReportError(VIR_ERR_INTERNAL_ERROR, _("domain event %d already registered"), args->eventID); + /* If we call register first, we could append a complete callback + * to our array, but on OOM append failure, we'd have to then hope + * deregister works to undo our register. So instead we append an + * incomplete callback to our array, then register, then fix up + * our callback; but since VIR_APPEND_ELEMENT clears 'callback' on + * success, we use 'ref' to save a copy of the pointer. */ + if (VIR_ALLOC(callback) < 0) + goto cleanup; + callback->client = client; + callback->eventID = args->eventID; + callback->callbackID = -1; + ref = callback; + if (VIR_APPEND_ELEMENT(priv->domainEventCallbacks, + priv->ndomainEventCallbacks, + callback) < 0) goto cleanup; - } if ((callbackID = virConnectDomainEventRegisterAny(priv->conn, NULL, args->eventID, domainEventCallbacks[args->eventID], - client, NULL)) < 0) + ref, + remoteEventCallbackFree)) < 0) { + VIR_SHRINK_N(priv->domainEventCallbacks, + priv->ndomainEventCallbacks, 1); + callback = ref; goto cleanup; + } - priv->domainEventCallbackID[args->eventID] = callbackID; + ref->callbackID = callbackID; rv = 0; cleanup: + VIR_FREE(callback); if (rv < 0) virNetMessageSaveError(rerr); virMutexUnlock(&priv->lock); @@ -3458,13 +3540,14 @@ cleanup: static int remoteDispatchConnectDomainEventDeregisterAny(virNetServerPtr server ATTRIBUTE_UNUSED, - virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetServerClientPtr client, virNetMessagePtr msg ATTRIBUTE_UNUSED, virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED, remote_connect_domain_event_deregister_any_args *args) { int callbackID = -1; int rv = -1; + size_t i; struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client); @@ -3481,16 +3564,23 @@ remoteDispatchConnectDomainEventDeregisterAny(virNetServerPtr server ATTRIBUTE_U goto cleanup; } - callbackID = priv->domainEventCallbackID[args->eventID]; + for (i = 0; i < priv->ndomainEventCallbacks; i++) { + if (priv->domainEventCallbacks[i]->eventID == args->eventID) { + callbackID = priv->domainEventCallbacks[i]->callbackID; + break; + } + } if (callbackID < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, _("domain event %d not registered"), args->eventID); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("domain event %d not registered"), args->eventID); goto cleanup; } if (virConnectDomainEventDeregisterAny(priv->conn, callbackID) < 0) goto cleanup; - priv->domainEventCallbackID[args->eventID] = -1; + VIR_DELETE_ELEMENT(priv->domainEventCallbacks, i, + priv->ndomainEventCallbacks); rv = 0; -- 1.8.5.3

On Wed, Jan 29, 2014 at 10:49:21AM -0700, Eric Blake wrote:
This patch continues the earlier conversion made for network events, with a goal of introducing server-side event filtering in a later patch. Actual behavior is unchanged without further RPC changes.
* daemon/libvirtd.h (daemonClientPrivate): Alter the tracking of domain events. * daemon/remote.c (remoteClientInitHook, remoteClientFreeFunc) (remoteRelayDomainEvent*) (remoteDispatchConnectDomainEventRegister) (remoteDispatchConnectDomainEventRegisterAny): Track domain callbacks dynamically. --- daemon/libvirtd.h | 3 +- daemon/remote.c | 294 +++++++++++++++++++++++++++++++++++------------------- 2 files changed, 194 insertions(+), 103 deletions(-)
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

This patch adds some new RPC call numbers, but for ease of review, they sit idle until a later patch adds the client counterpart to drive the new RPCs. Also for ease of review, I limited this patch to just the lifecycle event; although converting the remaining 15 domain events will be quite mechanical. On the server side, we have to have a function per RPC call, largely with duplicated bodies (the key difference being that we store in our callback opaque pointer whether events should be fired with old or new style); meanwhile, a single function can drive multiple RPC messages, along with a strategic choice of XDR struct layout, makes the event generation code for both styles fairly compact. I debated about adding a tri-state witness variable per connection (values 'unknown', 'legacy', 'modern'). It would start as 'unknown', move to 'legacy' if any RPC call is made to a legacy event call, and move to 'modern' if the feature probe is made; then the event code could issue an error if the witness state is incorrect (a legacy RPC call while in 'modern', a modern RPC call while in 'unknown' or 'legacy', and a feature probe while in 'legacy' or 'modern'). But while it might prevent odd behavior caused by protocol fuzzing, I don't see that it would prevent any security holes, so I considered it bloat. * src/libvirt_internal.h (VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK): New feature. * src/remote/remote_protocol.x (REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_REGISTER_ANY) (REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_DEREGISTER_ANY) (REMOTE_PROC_DOMAIN_EVENT_CALLBACK_LIFECYCLE): New RPCs. * daemon/remote.c (daemonClientCallback): Add field. (remoteDispatchConnectDomainEventCallbackRegisterAny) (remoteDispatchConnectDomainEventCallbackDeregisterAny): New functions. (remoteDispatchConnectDomainEventRegisterAny) (remoteDispatchConnectDomainEventDeregisterAny): Mark legacy use. (remoteRelayDomainEventLifecycle): Change message based on legacy or new use. (remoteDispatchConnectSupportsFeature): Advertise new feature. * src/remote_protocol-structs: Regenerate. Signed-off-by: Eric Blake <eblake@redhat.com> --- daemon/remote.c | 173 ++++++++++++++++++++++++++++++++++++++++--- src/libvirt_internal.h | 7 +- src/remote/remote_protocol.x | 39 +++++++++- src/remote_protocol-structs | 17 +++++ 4 files changed, 225 insertions(+), 11 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index be0af3d..1dfcb65 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -79,6 +79,7 @@ struct daemonClientEventCallback { virNetServerClientPtr client; int eventID; int callbackID; + bool legacy; }; static virDomainPtr get_nonnull_domain(virConnectPtr conn, remote_nonnull_domain domain); @@ -199,8 +200,8 @@ remoteRelayDomainEventLifecycle(virConnectPtr conn, !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) return -1; - VIR_DEBUG("Relaying domain lifecycle event %d %d, callback %d", - event, detail, callback->callbackID); + VIR_DEBUG("Relaying domain lifecycle event %d %d, callback %d legacy %d", + event, detail, callback->callbackID, callback->legacy); /* build return data */ memset(&data, 0, sizeof(data)); @@ -208,9 +209,20 @@ remoteRelayDomainEventLifecycle(virConnectPtr conn, data.event = event; data.detail = detail; - remoteDispatchObjectEventSend(callback->client, remoteProgram, - REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE, - (xdrproc_t)xdr_remote_domain_event_lifecycle_msg, &data); + if (callback->legacy) { + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE, + (xdrproc_t)xdr_remote_domain_event_lifecycle_msg, + &data); + } else { + remote_domain_event_callback_lifecycle_msg msg = { callback->callbackID, + data }; + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_LIFECYCLE, + (xdrproc_t)xdr_remote_domain_event_callback_lifecycle_msg, + &msg); + } return 0; } @@ -3281,6 +3293,7 @@ remoteDispatchConnectDomainEventRegister(virNetServerPtr server ATTRIBUTE_UNUSED callback->client = client; callback->eventID = VIR_DOMAIN_EVENT_ID_LIFECYCLE; callback->callbackID = -1; + callback->legacy = true; ref = callback; if (VIR_APPEND_ELEMENT(priv->domainEventCallbacks, priv->ndomainEventCallbacks, @@ -3469,6 +3482,12 @@ cleanup: return rv; } + +/* Due to back-compat reasons, two RPC calls map to the same libvirt + * API of virConnectDomainEventRegisterAny. A client should only use + * the new call if they have probed + * VIR_DRV_SUPPORTS_FEATURE(VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK), + * and must not mix the two styles. */ static int remoteDispatchConnectDomainEventRegisterAny(virNetServerPtr server ATTRIBUTE_UNUSED, virNetServerClientPtr client, @@ -3490,9 +3509,13 @@ remoteDispatchConnectDomainEventRegisterAny(virNetServerPtr server ATTRIBUTE_UNU virMutexLock(&priv->lock); - if (args->eventID >= VIR_DOMAIN_EVENT_ID_LAST || + /* We intentionally do not use VIR_DOMAIN_EVENT_ID_LAST here; any + * new domain events added after this point should only use the + * modern callback style of RPC. */ + if (args->eventID > VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED || args->eventID < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported event ID %d"), args->eventID); + virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported event ID %d"), + args->eventID); goto cleanup; } @@ -3507,6 +3530,7 @@ remoteDispatchConnectDomainEventRegisterAny(virNetServerPtr server ATTRIBUTE_UNU callback->client = client; callback->eventID = args->eventID; callback->callbackID = -1; + callback->legacy = true; ref = callback; if (VIR_APPEND_ELEMENT(priv->domainEventCallbacks, priv->ndomainEventCallbacks, @@ -3539,6 +3563,85 @@ cleanup: static int +remoteDispatchConnectDomainEventCallbackRegisterAny(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED, + remote_connect_domain_event_callback_register_any_args *args, + remote_connect_domain_event_callback_register_any_ret *ret) +{ + int callbackID; + int rv = -1; + daemonClientEventCallbackPtr callback = NULL; + daemonClientEventCallbackPtr ref; + struct daemonClientPrivate *priv = + virNetServerClientGetPrivateData(client); + virDomainPtr dom = NULL; + + if (!priv->conn) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + virMutexLock(&priv->lock); + + if (args->dom && + !(dom = get_nonnull_domain(priv->conn, *args->dom))) + goto cleanup; + + /* FIXME: support all domain events */ + if (args->eventID != VIR_DOMAIN_EVENT_ID_LIFECYCLE) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported event ID %d"), + args->eventID); + goto cleanup; + } + + /* If we call register first, we could append a complete callback + * to our array, but on OOM append failure, we'd have to then hope + * deregister works to undo our register. So instead we append an + * incomplete callback to our array, then register, then fix up + * our callback; but since VIR_APPEND_ELEMENT clears 'callback' on + * success, we use 'ref' to save a copy of the pointer. */ + if (VIR_ALLOC(callback) < 0) + goto cleanup; + callback->client = client; + callback->eventID = args->eventID; + callback->callbackID = -1; + ref = callback; + if (VIR_APPEND_ELEMENT(priv->domainEventCallbacks, + priv->ndomainEventCallbacks, + callback) < 0) + goto cleanup; + + if ((callbackID = virConnectDomainEventRegisterAny(priv->conn, + dom, + args->eventID, + domainEventCallbacks[args->eventID], + ref, + remoteEventCallbackFree)) < 0) { + VIR_SHRINK_N(priv->domainEventCallbacks, + priv->ndomainEventCallbacks, 1); + callback = ref; + goto cleanup; + } + + ref->callbackID = callbackID; + ret->callbackID = callbackID; + + rv = 0; + +cleanup: + VIR_FREE(callback); + if (rv < 0) + virNetMessageSaveError(rerr); + if (dom) + virDomainFree(dom); + virMutexUnlock(&priv->lock); + return rv; +} + + +static int remoteDispatchConnectDomainEventDeregisterAny(virNetServerPtr server ATTRIBUTE_UNUSED, virNetServerClientPtr client, virNetMessagePtr msg ATTRIBUTE_UNUSED, @@ -3558,9 +3661,13 @@ remoteDispatchConnectDomainEventDeregisterAny(virNetServerPtr server ATTRIBUTE_U virMutexLock(&priv->lock); - if (args->eventID >= VIR_DOMAIN_EVENT_ID_LAST || + /* We intentionally do not use VIR_DOMAIN_EVENT_ID_LAST here; any + * new domain events added after this point should only use the + * modern callback style of RPC. */ + if (args->eventID > VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED || args->eventID < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported event ID %d"), args->eventID); + virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported event ID %d"), + args->eventID); goto cleanup; } @@ -3591,6 +3698,53 @@ cleanup: return rv; } + +static int +remoteDispatchConnectDomainEventCallbackDeregisterAny(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED, + remote_connect_domain_event_callback_deregister_any_args *args) +{ + int rv = -1; + size_t i; + struct daemonClientPrivate *priv = + virNetServerClientGetPrivateData(client); + + if (!priv->conn) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + virMutexLock(&priv->lock); + + for (i = 0; i < priv->ndomainEventCallbacks; i++) { + if (priv->domainEventCallbacks[i]->callbackID == args->callbackID) + break; + } + if (i == priv->ndomainEventCallbacks) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("domain event callback %d not registered"), + args->callbackID); + goto cleanup; + } + + if (virConnectDomainEventDeregisterAny(priv->conn, args->callbackID) < 0) + goto cleanup; + + VIR_DELETE_ELEMENT(priv->domainEventCallbacks, i, + priv->ndomainEventCallbacks); + + rv = 0; + +cleanup: + if (rv < 0) + virNetMessageSaveError(rerr); + virMutexUnlock(&priv->lock); + return rv; +} + + static int qemuDispatchDomainMonitorCommand(virNetServerPtr server ATTRIBUTE_UNUSED, virNetServerClientPtr client ATTRIBUTE_UNUSED, @@ -3911,6 +4065,7 @@ static int remoteDispatchConnectSupportsFeature(virNetServerPtr server ATTRIBUTE switch (args->feature) { case VIR_DRV_FEATURE_FD_PASSING: + case VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK: supported = 1; break; diff --git a/src/libvirt_internal.h b/src/libvirt_internal.h index 115d8d1..ebf2acf 100644 --- a/src/libvirt_internal.h +++ b/src/libvirt_internal.h @@ -1,7 +1,7 @@ /* * libvirt_internal.h: internally exported APIs, not for public use * - * Copyright (C) 2006-2013 Red Hat, Inc. + * Copyright (C) 2006-2014 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -115,6 +115,11 @@ enum { * Support for migration parameters. */ VIR_DRV_FEATURE_MIGRATION_PARAMS = 13, + + /* + * Support for server-side event filtering via callback ids in events. + */ + VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK = 14, }; diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 790a020..982ab1f 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -1972,6 +1972,10 @@ struct remote_domain_event_lifecycle_msg { int event; int detail; }; +struct remote_domain_event_callback_lifecycle_msg { + int callbackID; + remote_domain_event_lifecycle_msg msg; +}; struct remote_connect_domain_xml_from_native_args { @@ -2248,6 +2252,19 @@ struct remote_connect_domain_event_deregister_any_args { int eventID; }; +struct remote_connect_domain_event_callback_register_any_args { + int eventID; + remote_domain dom; +}; + +struct remote_connect_domain_event_callback_register_any_ret { + int callbackID; +}; + +struct remote_connect_domain_event_callback_deregister_any_args { + int callbackID; +}; + struct remote_domain_event_reboot_msg { remote_nonnull_domain dom; }; @@ -5068,5 +5085,25 @@ enum remote_procedure { * @generate: both * @acl: none */ - REMOTE_PROC_NETWORK_EVENT_LIFECYCLE = 315 + REMOTE_PROC_NETWORK_EVENT_LIFECYCLE = 315, + + /** + * @generate: none + * @priority: high + * @acl: none + */ + REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_REGISTER_ANY = 316, + + /** + * @generate: none + * @priority: high + * @acl: none + */ + REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_DEREGISTER_ANY = 317, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_LIFECYCLE = 318 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index e58482e..39d3981 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -1491,6 +1491,10 @@ struct remote_domain_event_lifecycle_msg { int event; int detail; }; +struct remote_domain_event_callback_lifecycle_msg { + int callbackID; + remote_domain_event_lifecycle_msg msg; +}; struct remote_connect_domain_xml_from_native_args { remote_nonnull_string nativeFormat; remote_nonnull_string nativeConfig; @@ -1707,6 +1711,16 @@ struct remote_connect_domain_event_register_any_args { struct remote_connect_domain_event_deregister_any_args { int eventID; }; +struct remote_connect_domain_event_callback_register_any_args { + int eventID; + remote_domain dom; +}; +struct remote_connect_domain_event_callback_register_any_ret { + int callbackID; +}; +struct remote_connect_domain_event_callback_deregister_any_args { + int callbackID; +}; struct remote_domain_event_reboot_msg { remote_nonnull_domain dom; }; @@ -2660,4 +2674,7 @@ enum remote_procedure { REMOTE_PROC_CONNECT_NETWORK_EVENT_REGISTER_ANY = 313, REMOTE_PROC_CONNECT_NETWORK_EVENT_DEREGISTER_ANY = 314, REMOTE_PROC_NETWORK_EVENT_LIFECYCLE = 315, + REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_REGISTER_ANY = 316, + REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_DEREGISTER_ANY = 317, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_LIFECYCLE = 318, }; -- 1.8.5.3

On Wed, Jan 29, 2014 at 10:49:22AM -0700, Eric Blake wrote:
This patch adds some new RPC call numbers, but for ease of review, they sit idle until a later patch adds the client counterpart to drive the new RPCs. Also for ease of review, I limited this patch to just the lifecycle event; although converting the remaining 15 domain events will be quite mechanical. On the server side, we have to have a function per RPC call, largely with duplicated bodies (the key difference being that we store in our callback opaque pointer whether events should be fired with old or new style); meanwhile, a single function can drive multiple RPC messages, along with a strategic choice of XDR struct layout, makes the event generation code for both styles fairly compact.
I debated about adding a tri-state witness variable per connection (values 'unknown', 'legacy', 'modern'). It would start as 'unknown', move to 'legacy' if any RPC call is made to a legacy event call, and move to 'modern' if the feature probe is made; then the event code could issue an error if the witness state is incorrect (a legacy RPC call while in 'modern', a modern RPC call while in 'unknown' or 'legacy', and a feature probe while in 'legacy' or 'modern'). But while it might prevent odd behavior caused by protocol fuzzing, I don't see that it would prevent any security holes, so I considered it bloat.
* src/libvirt_internal.h (VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK): New feature. * src/remote/remote_protocol.x (REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_REGISTER_ANY) (REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_DEREGISTER_ANY) (REMOTE_PROC_DOMAIN_EVENT_CALLBACK_LIFECYCLE): New RPCs. * daemon/remote.c (daemonClientCallback): Add field. (remoteDispatchConnectDomainEventCallbackRegisterAny) (remoteDispatchConnectDomainEventCallbackDeregisterAny): New functions. (remoteDispatchConnectDomainEventRegisterAny) (remoteDispatchConnectDomainEventDeregisterAny): Mark legacy use. (remoteRelayDomainEventLifecycle): Change message based on legacy or new use. (remoteDispatchConnectSupportsFeature): Advertise new feature. * src/remote_protocol-structs: Regenerate.
Signed-off-by: Eric Blake <eblake@redhat.com> --- daemon/remote.c | 173 ++++++++++++++++++++++++++++++++++++++++--- src/libvirt_internal.h | 7 +- src/remote/remote_protocol.x | 39 +++++++++- src/remote_protocol-structs | 17 +++++ 4 files changed, 225 insertions(+), 11 deletions(-)
ACK
@@ -5068,5 +5085,25 @@ enum remote_procedure { * @generate: both * @acl: none */ - REMOTE_PROC_NETWORK_EVENT_LIFECYCLE = 315 + REMOTE_PROC_NETWORK_EVENT_LIFECYCLE = 315, + + /** + * @generate: none + * @priority: high + * @acl: none + */ + REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_REGISTER_ANY = 316, + + /** + * @generate: none + * @priority: high + * @acl: none + */ + REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_DEREGISTER_ANY = 317,
I believe these ACLs need to be non-none now Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 02/11/2014 08:57 AM, Daniel P. Berrange wrote:
On Wed, Jan 29, 2014 at 10:49:22AM -0700, Eric Blake wrote:
This patch adds some new RPC call numbers, but for ease of review, they sit idle until a later patch adds the client counterpart to drive the new RPCs. Also for ease of review, I limited this patch
ACK
Thanks for the review.
@@ -5068,5 +5085,25 @@ enum remote_procedure { * @generate: both * @acl: none */ - REMOTE_PROC_NETWORK_EVENT_LIFECYCLE = 315 + REMOTE_PROC_NETWORK_EVENT_LIFECYCLE = 315, + + /** + * @generate: none + * @priority: high + * @acl: none + */ + REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_REGISTER_ANY = 316, + + /** + * @generate: none + * @priority: high + * @acl: none + */ + REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_DEREGISTER_ANY = 317,
I believe these ACLs need to be non-none now
The way 'make -C src check-aclrules' works is by correlating all RPC calls back into their API names - but I'm not inventing any new API names. These new RPC calls are already covered by existing APIs, and the ACL checks performed there are already sufficient. But it turns out that it doesn't hurt to make these ACLs match the other register RPC numbers, so I'm inclined to squash this in, unless you think that generating unused functions in src/access/viraccessapicheck.c is not worth the pollution: diff --git i/src/remote/remote_protocol.x w/src/remote/remote_protocol.x index 982ab1f..26abcdd 100644 --- i/src/remote/remote_protocol.x +++ w/src/remote/remote_protocol.x @@ -5090,14 +5090,15 @@ enum remote_procedure { /** * @generate: none * @priority: high - * @acl: none + * @acl: connect:search_domains + * @aclfilter: domain:getattr */ REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_REGISTER_ANY = 316, /** * @generate: none * @priority: high - * @acl: none + * @acl: connect:read */ REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_DEREGISTER_ANY = 317, -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On Tue, Feb 11, 2014 at 02:07:06PM -0700, Eric Blake wrote:
On 02/11/2014 08:57 AM, Daniel P. Berrange wrote:
On Wed, Jan 29, 2014 at 10:49:22AM -0700, Eric Blake wrote:
This patch adds some new RPC call numbers, but for ease of review, they sit idle until a later patch adds the client counterpart to drive the new RPCs. Also for ease of review, I limited this patch
ACK
Thanks for the review.
@@ -5068,5 +5085,25 @@ enum remote_procedure { * @generate: both * @acl: none */ - REMOTE_PROC_NETWORK_EVENT_LIFECYCLE = 315 + REMOTE_PROC_NETWORK_EVENT_LIFECYCLE = 315, + + /** + * @generate: none + * @priority: high + * @acl: none + */ + REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_REGISTER_ANY = 316, + + /** + * @generate: none + * @priority: high + * @acl: none + */ + REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_DEREGISTER_ANY = 317,
I believe these ACLs need to be non-none now
The way 'make -C src check-aclrules' works is by correlating all RPC calls back into their API names - but I'm not inventing any new API names. These new RPC calls are already covered by existing APIs, and the ACL checks performed there are already sufficient. But it turns out that it doesn't hurt to make these ACLs match the other register RPC numbers, so I'm inclined to squash this in, unless you think that generating unused functions in src/access/viraccessapicheck.c is not worth the pollution:
diff --git i/src/remote/remote_protocol.x w/src/remote/remote_protocol.x index 982ab1f..26abcdd 100644 --- i/src/remote/remote_protocol.x +++ w/src/remote/remote_protocol.x @@ -5090,14 +5090,15 @@ enum remote_procedure { /** * @generate: none * @priority: high - * @acl: none + * @acl: connect:search_domains + * @aclfilter: domain:getattr */ REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_REGISTER_ANY = 316,
/** * @generate: none * @priority: high - * @acl: none + * @acl: connect:read */ REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_DEREGISTER_ANY = 317,
ACK to this - it makes it clearer i think Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 02/12/2014 03:23 AM, Daniel P. Berrange wrote:
On Tue, Feb 11, 2014 at 02:07:06PM -0700, Eric Blake wrote:
On 02/11/2014 08:57 AM, Daniel P. Berrange wrote:
On Wed, Jan 29, 2014 at 10:49:22AM -0700, Eric Blake wrote:
This patch adds some new RPC call numbers, but for ease of review, they sit idle until a later patch adds the client counterpart to drive the new RPCs. Also for ease of review, I limited this patch
ACK
Thanks for the review.
/** * @generate: none * @priority: high - * @acl: none + * @acl: connect:read */ REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_DEREGISTER_ANY = 317,
ACK to this - it makes it clearer i think
Series now pushed with this in. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

We want to convert over to server-side events, even for older APIs. To do that, the client side of the remote driver wants to distinguish between legacy virConnectDomainEventRegister and normal virConnectDomainEventRegisterAny, while knowing the client callbackID and the server's serverID for both types of registration. The client also needs to probe whether the server supports server-side filtering. However, for ease of review, we don't actually use the new RPCs until a later patch. * src/conf/object_event_private.h (virObjectEventStateCallbackID): Add parameter. * src/conf/object_event.c (virObjectEventCallbackListAddID) (virObjectEventStateRegisterID): Separate legacy from callbackID. (virObjectEventStateCallbackID): Pass through parameter. (virObjectEventCallbackLookup): Let legacy and global domain lifecycle events share a common remoteID. * src/conf/network_event.c (virNetworkEventStateRegisterID): Update caller. * src/conf/domain_event.c (virDomainEventStateRegister) (virDomainEventStateRegisterID, virDomainEventStateDeregister): Likewise. (virDomainEventStateRegisterClient) (virDomainEventStateCallbackID): Implement new functions. * src/conf/domain_event.h (virDomainEventStateRegisterClient) (virDomainEventStateCallbackID): New prototypes. * src/remote/remote_driver.c (private_data): Add field. (doRemoteOpen): Probe server feature. (remoteConnectDomainEventRegister) (remoteConnectDomainEventRegisterAny): Use new function. Signed-off-by: Eric Blake <eblake@redhat.com> --- src/conf/domain_event.c | 78 +++++++++++++++++++++++++++++++++++++++-- src/conf/domain_event.h | 22 ++++++++++++ src/conf/network_event.c | 6 ++-- src/conf/object_event.c | 35 +++++++++--------- src/conf/object_event_private.h | 6 ++-- src/remote/remote_driver.c | 36 +++++++++++++++---- 6 files changed, 154 insertions(+), 29 deletions(-) diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c index 8639a01..a490fe5 100644 --- a/src/conf/domain_event.c +++ b/src/conf/domain_event.c @@ -1281,6 +1281,8 @@ virDomainEventStateRegister(virConnectPtr conn, void *opaque, virFreeCallback freecb) { + int callbackID; + if (virDomainEventsInitialize() < 0) return -1; @@ -1288,7 +1290,8 @@ virDomainEventStateRegister(virConnectPtr conn, NULL, NULL, virDomainEventClass, VIR_DOMAIN_EVENT_ID_LIFECYCLE, VIR_OBJECT_EVENT_CALLBACK(callback), - opaque, freecb, NULL, false); + opaque, freecb, + true, &callbackID, false); } @@ -1326,7 +1329,75 @@ virDomainEventStateRegisterID(virConnectPtr conn, NULL, NULL, virDomainEventClass, eventID, VIR_OBJECT_EVENT_CALLBACK(cb), - opaque, freecb, callbackID, false); + opaque, freecb, + false, callbackID, false); +} + + +/** + * virDomainEventStateRegisterClient: + * @conn: connection to associate with callback + * @state: object event state + * @dom: optional domain for filtering the event + * @eventID: ID of the event type to register for + * @cb: function to invoke when event fires + * @opaque: data blob to pass to @callback + * @freecb: callback to free @opaque + * @legacy: true if callback is tracked by function instead of callbackID + * @callbackID: filled with callback ID + * @remoteID: true if server supports filtering + * + * Register the function @cb with connection @conn, from @state, for + * events of type @eventID, and return the registration handle in + * @callbackID. This version is intended for use on the client side + * of RPC. + * + * Returns: the number of callbacks now registered, or -1 on error + */ +int +virDomainEventStateRegisterClient(virConnectPtr conn, + virObjectEventStatePtr state, + virDomainPtr dom, + int eventID, + virConnectDomainEventGenericCallback cb, + void *opaque, + virFreeCallback freecb, + bool legacy, + int *callbackID, + bool remoteID) +{ + if (virDomainEventsInitialize() < 0) + return -1; + + return virObjectEventStateRegisterID(conn, state, dom ? dom->uuid : NULL, + NULL, NULL, + virDomainEventClass, eventID, + VIR_OBJECT_EVENT_CALLBACK(cb), + opaque, freecb, + legacy, callbackID, remoteID); +} + + +/** + * virDomainEventStateCallbackID: + * @conn: connection associated with callback + * @state: object event state + * @cb: function registered as a callback with virDomainEventStateRegister() + * @remoteID: associated remote id of the callback + * + * Returns the callbackID of @cb, or -1 with an error issued if the + * function is not currently registered. + */ +int +virDomainEventStateCallbackID(virConnectPtr conn, + virObjectEventStatePtr state, + virConnectDomainEventCallback cb, + int *remoteID) +{ + return virObjectEventStateCallbackID(conn, state, virDomainEventClass, + VIR_DOMAIN_EVENT_ID_LIFECYCLE, + VIR_OBJECT_EVENT_CALLBACK(cb), + remoteID); } @@ -1351,7 +1422,8 @@ virDomainEventStateDeregister(virConnectPtr conn, callbackID = virObjectEventStateCallbackID(conn, state, virDomainEventClass, VIR_DOMAIN_EVENT_ID_LIFECYCLE, - VIR_OBJECT_EVENT_CALLBACK(cb)); + VIR_OBJECT_EVENT_CALLBACK(cb), + NULL); if (callbackID < 0) return -1; return virObjectEventStateDeregisterID(conn, state, callbackID); diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h index b033b23..be577e9 100644 --- a/src/conf/domain_event.h +++ b/src/conf/domain_event.h @@ -192,6 +192,28 @@ virDomainEventStateRegisterID(virConnectPtr conn, int *callbackID) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(5); int +virDomainEventStateRegisterClient(virConnectPtr conn, + virObjectEventStatePtr state, + virDomainPtr dom, + int eventID, + virConnectDomainEventGenericCallback cb, + void *opaque, + virFreeCallback freecb, + bool legacy, + int *callbackID, + bool remoteID) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(5) + ATTRIBUTE_NONNULL(9); + +int +virDomainEventStateCallbackID(virConnectPtr conn, + virObjectEventStatePtr state, + virConnectDomainEventCallback callback, + int *remoteID) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) + ATTRIBUTE_NONNULL(4); + +int virDomainEventStateDeregister(virConnectPtr conn, virObjectEventStatePtr state, virConnectDomainEventCallback callback) diff --git a/src/conf/network_event.c b/src/conf/network_event.c index 4c59356..f2cfefe 100644 --- a/src/conf/network_event.c +++ b/src/conf/network_event.c @@ -155,7 +155,8 @@ virNetworkEventStateRegisterID(virConnectPtr conn, NULL, NULL, virNetworkEventClass, eventID, VIR_OBJECT_EVENT_CALLBACK(cb), - opaque, freecb, callbackID, false); + opaque, freecb, + false, callbackID, false); } @@ -194,7 +195,8 @@ virNetworkEventStateRegisterClient(virConnectPtr conn, NULL, NULL, virNetworkEventClass, eventID, VIR_OBJECT_EVENT_CALLBACK(cb), - opaque, freecb, callbackID, true); + opaque, freecb, + false, callbackID, true); } diff --git a/src/conf/object_event.c b/src/conf/object_event.c index aff4956..de45257 100644 --- a/src/conf/object_event.c +++ b/src/conf/object_event.c @@ -334,13 +334,13 @@ virObjectEventCallbackLookup(virConnectPtr conn, if (cb->klass == klass && cb->eventID == eventID && cb->conn == conn && - cb->legacy == legacy && ((uuid && cb->uuid_filter && memcmp(cb->uuid, uuid, VIR_UUID_BUFLEN) == 0) || (!uuid && !cb->uuid_filter))) { if (remoteID) *remoteID = cb->remoteID; - if (cb->cb == callback) + if (cb->legacy == legacy && + cb->cb == callback) return cb->callbackID; } } @@ -360,6 +360,7 @@ virObjectEventCallbackLookup(virConnectPtr conn, * @callback: the callback to add * @opaque: opaque data to pass to @callback * @freecb: callback to free @opaque + * @legacy: true if callback is tracked by function instead of callbackID * @callbackID: filled with callback ID * @serverFilter: true if server supports object filtering * @@ -376,6 +377,7 @@ virObjectEventCallbackListAddID(virConnectPtr conn, virConnectObjectEventGenericCallback callback, void *opaque, virFreeCallback freecb, + bool legacy, int *callbackID, bool serverFilter) { @@ -384,9 +386,10 @@ virObjectEventCallbackListAddID(virConnectPtr conn, int remoteID = -1; VIR_DEBUG("conn=%p cblist=%p uuid=%p filter=%p filter_opaque=%p " - "klass=%p eventID=%d callback=%p opaque=%p", - conn, cbList, uuid, filter, filter_opaque, - klass, eventID, callback, opaque); + "klass=%p eventID=%d callback=%p opaque=%p " + "legacy=%d callbackID=%p serverFilter=%d", + conn, cbList, uuid, filter, filter_opaque, klass, eventID, + callback, opaque, legacy, callbackID, serverFilter); /* Check incoming */ if (!cbList) { @@ -395,8 +398,7 @@ virObjectEventCallbackListAddID(virConnectPtr conn, /* check if we already have this callback on our list */ if (virObjectEventCallbackLookup(conn, cbList, uuid, - klass, eventID, callback, - !callbackID, + klass, eventID, callback, legacy, serverFilter ? &remoteID : NULL) != -1) { virReportError(VIR_ERR_INVALID_ARG, "%s", _("event callback already tracked")); @@ -406,7 +408,7 @@ virObjectEventCallbackListAddID(virConnectPtr conn, if (VIR_ALLOC(event) < 0) goto cleanup; event->conn = virObjectRef(conn); - event->callbackID = cbList->nextID++; + *callbackID = event->callbackID = cbList->nextID++; event->cb = callback; event->klass = klass; event->eventID = eventID; @@ -423,11 +425,7 @@ virObjectEventCallbackListAddID(virConnectPtr conn, } event->filter = filter; event->filter_opaque = filter_opaque; - - if (callbackID) - *callbackID = event->callbackID; - else - event->legacy = true; + event->legacy = legacy; if (VIR_APPEND_ELEMENT(cbList->callbacks, cbList->count, event) < 0) goto cleanup; @@ -833,6 +831,7 @@ virObjectEventStateFlush(virObjectEventStatePtr state) * @cb: function to invoke when event occurs * @opaque: data blob to pass to @callback * @freecb: callback to free @opaque + * @legacy: true if callback is tracked by function instead of callbackID * @callbackID: filled with callback ID * @serverFilter: true if server supports object filtering * @@ -867,6 +866,7 @@ virObjectEventStateRegisterID(virConnectPtr conn, virConnectObjectEventGenericCallback cb, void *opaque, virFreeCallback freecb, + bool legacy, int *callbackID, bool serverFilter) { @@ -889,7 +889,7 @@ virObjectEventStateRegisterID(virConnectPtr conn, uuid, filter, filter_opaque, klass, eventID, cb, opaque, freecb, - callbackID, serverFilter); + legacy, callbackID, serverFilter); if (ret == -1 && state->callbacks->count == 0 && @@ -949,6 +949,7 @@ virObjectEventStateDeregisterID(virConnectPtr conn, * @klass: the base event class * @eventID: the event ID * @callback: function registered as a callback + * @remoteID: optional output, containing resulting remote id * * Returns the callbackID of @callback, or -1 with an error issued if the * function is not currently registered. This only finds functions @@ -960,13 +961,15 @@ virObjectEventStateCallbackID(virConnectPtr conn, virObjectEventStatePtr state, virClassPtr klass, int eventID, - virConnectObjectEventGenericCallback callback) + virConnectObjectEventGenericCallback callback, + int *remoteID) { int ret = -1; virObjectEventStateLock(state); ret = virObjectEventCallbackLookup(conn, state->callbacks, NULL, - klass, eventID, callback, true, NULL); + klass, eventID, callback, true, + remoteID); virObjectEventStateUnlock(state); if (ret < 0) diff --git a/src/conf/object_event_private.h b/src/conf/object_event_private.h index 8e265f9..a19a0d3 100644 --- a/src/conf/object_event_private.h +++ b/src/conf/object_event_private.h @@ -80,17 +80,19 @@ virObjectEventStateRegisterID(virConnectPtr conn, virConnectObjectEventGenericCallback cb, void *opaque, virFreeCallback freecb, + bool legacy, int *callbackID, bool remoteFilter) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(6) - ATTRIBUTE_NONNULL(8); + ATTRIBUTE_NONNULL(8) ATTRIBUTE_NONNULL(12); int virObjectEventStateCallbackID(virConnectPtr conn, virObjectEventStatePtr state, virClassPtr klass, int eventID, - virConnectObjectEventGenericCallback callback) + virConnectObjectEventGenericCallback callback, + int *remoteID) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(5); diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 18eb454..b0257c2 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -92,6 +92,7 @@ struct private_data { int localUses; /* Ref count for private data */ char *hostname; /* Original hostname */ bool serverKeepAlive; /* Does server support keepalive protocol? */ + bool serverEventFilter; /* Does server support modern event filtering */ virObjectEventStatePtr eventState; }; @@ -890,8 +891,26 @@ doRemoteOpen(virConnectPtr conn, goto failed; } + /* Set up events */ if (!(priv->eventState = virObjectEventStateNew())) goto failed; + { + remote_connect_supports_feature_args args = + { VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK }; + remote_connect_supports_feature_ret ret = { 0 }; + int rc; + + rc = call(conn, priv, 0, REMOTE_PROC_CONNECT_SUPPORTS_FEATURE, + (xdrproc_t)xdr_remote_connect_supports_feature_args, (char *) &args, + (xdrproc_t)xdr_remote_connect_supports_feature_ret, (char *) &ret); + + if (rc != -1 && ret.supported) { + priv->serverEventFilter = true; + } else { + VIR_INFO("Avoiding server event filtering since it is not " + "supported by the server"); + } + } /* Successful. */ retcode = VIR_DRV_OPEN_SUCCESS; @@ -4421,14 +4440,19 @@ remoteConnectDomainEventRegister(virConnectPtr conn, void *opaque, virFreeCallback freecb) { + int callbackID; int rv = -1; struct private_data *priv = conn->privateData; int count; remoteDriverLock(priv); - if ((count = virDomainEventStateRegister(conn, priv->eventState, - callback, opaque, freecb)) < 0) + if ((count = virDomainEventStateRegisterClient(conn, priv->eventState, + NULL, + VIR_DOMAIN_EVENT_ID_LIFECYCLE, + VIR_DOMAIN_EVENT_CALLBACK(callback), + opaque, freecb, true, + &callbackID, false)) < 0) goto done; if (count == 1) { @@ -5245,10 +5269,10 @@ remoteConnectDomainEventRegisterAny(virConnectPtr conn, remoteDriverLock(priv); - if ((count = virDomainEventStateRegisterID(conn, priv->eventState, - dom, eventID, - callback, opaque, freecb, - &callbackID)) < 0) + if ((count = virDomainEventStateRegisterClient(conn, priv->eventState, + dom, eventID, callback, + opaque, freecb, false, + &callbackID, false)) < 0) goto done; /* If this is the first callback for this eventID, we need to enable -- 1.8.5.3

On Wed, Jan 29, 2014 at 10:49:23AM -0700, Eric Blake wrote:
We want to convert over to server-side events, even for older APIs. To do that, the client side of the remote driver wants to distinguish between legacy virConnectDomainEventRegister and normal virConnectDomainEventRegisterAny, while knowing the client callbackID and the server's serverID for both types of registration. The client also needs to probe whether the server supports server-side filtering. However, for ease of review, we don't actually use the new RPCs until a later patch.
* src/conf/object_event_private.h (virObjectEventStateCallbackID): Add parameter. * src/conf/object_event.c (virObjectEventCallbackListAddID) (virObjectEventStateRegisterID): Separate legacy from callbackID. (virObjectEventStateCallbackID): Pass through parameter. (virObjectEventCallbackLookup): Let legacy and global domain lifecycle events share a common remoteID. * src/conf/network_event.c (virNetworkEventStateRegisterID): Update caller. * src/conf/domain_event.c (virDomainEventStateRegister) (virDomainEventStateRegisterID, virDomainEventStateDeregister): Likewise. (virDomainEventStateRegisterClient) (virDomainEventStateCallbackID): Implement new functions. * src/conf/domain_event.h (virDomainEventStateRegisterClient) (virDomainEventStateCallbackID): New prototypes. * src/remote/remote_driver.c (private_data): Add field. (doRemoteOpen): Probe server feature. (remoteConnectDomainEventRegister) (remoteConnectDomainEventRegisterAny): Use new function.
Signed-off-by: Eric Blake <eblake@redhat.com> --- src/conf/domain_event.c | 78 +++++++++++++++++++++++++++++++++++++++-- src/conf/domain_event.h | 22 ++++++++++++ src/conf/network_event.c | 6 ++-- src/conf/object_event.c | 35 +++++++++--------- src/conf/object_event_private.h | 6 ++-- src/remote/remote_driver.c | 36 +++++++++++++++---- 6 files changed, 154 insertions(+), 29 deletions(-)
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

The counterpart to the server RPC additions; here, a single function can serve both old and new calls, while incoming events must be serviced by two different functions. Again, some wise choices in our XDR makes event sharing easier. While this only supports lifecycle events, it covers the harder part of how Register and RegisterAny interact; the remaining 15 events will be a mechanical change in a later patch. For Register, we now have a callbackID locally for more efficient cleanup if the RPC fails; we also prefer to use the newer RPC where we know it is supported (the older RPC must be used if we don't know if RegisterAny is supported). * src/remote/remote_driver.c (remoteEvents): Register new RPC event handler. (remoteDomainBuildEventLifecycle): Move guts... (remoteDomainBuildEventLifecycleHelper): ...here. (remoteDomainBuildEventCallbackLifecycle): New function. (remoteConnectDomainEventRegister) (remoteConnectDomainEventDeregister) (remoteConnectDomainEventRegisterAny) (remoteConnectDomainEventDeregisterAny): Use new RPC when supported. --- src/remote/remote_driver.c | 191 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 157 insertions(+), 34 deletions(-) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index b0257c2..35baaeb 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -209,6 +209,11 @@ remoteDomainBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virNetClientPtr client ATTRIBUTE_UNUSED, void *evdata, void *opaque); static void +remoteDomainBuildEventCallbackLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque); + +static void remoteDomainBuildEventReboot(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virNetClientPtr client ATTRIBUTE_UNUSED, void *evdata, void *opaque); @@ -345,10 +350,23 @@ static virNetClientProgramEvent remoteEvents[] = { remoteDomainBuildEventDeviceRemoved, sizeof(remote_domain_event_device_removed_msg), (xdrproc_t)xdr_remote_domain_event_device_removed_msg }, + /* All events above here are legacy events, missing the callback + * ID, which means the server has a single global registration and + * we do full filtering in the client. If the server lacks + * VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK, those are the only + * events we should ever receive. Conversely, all events below + * here should only be triggered by modern servers, and all + * contain a callbackID. Although we have to duplicate the first + * 16 domain events in both styles for back-compat, any future + * domain event additions should only use the modern style. */ { REMOTE_PROC_NETWORK_EVENT_LIFECYCLE, remoteNetworkBuildEventLifecycle, sizeof(remote_network_event_lifecycle_msg), (xdrproc_t)xdr_remote_network_event_lifecycle_msg }, + { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_LIFECYCLE, + remoteDomainBuildEventCallbackLifecycle, + sizeof(remote_domain_event_callback_lifecycle_msg), + (xdrproc_t)xdr_remote_domain_event_callback_lifecycle_msg }, }; enum virDrvOpenRemoteFlags { @@ -4452,16 +4470,38 @@ remoteConnectDomainEventRegister(virConnectPtr conn, VIR_DOMAIN_EVENT_ID_LIFECYCLE, VIR_DOMAIN_EVENT_CALLBACK(callback), opaque, freecb, true, - &callbackID, false)) < 0) + &callbackID, + priv->serverEventFilter)) < 0) goto done; if (count == 1) { /* Tell the server when we are the first callback registering */ - if (call(conn, priv, 0, REMOTE_PROC_CONNECT_DOMAIN_EVENT_REGISTER, - (xdrproc_t) xdr_void, (char *) NULL, - (xdrproc_t) xdr_void, (char *) NULL) == -1) { - virDomainEventStateDeregister(conn, priv->eventState, callback); - goto done; + if (priv->serverEventFilter) { + remote_connect_domain_event_callback_register_any_args args; + remote_connect_domain_event_callback_register_any_ret ret; + + args.eventID = VIR_DOMAIN_EVENT_ID_LIFECYCLE; + args.dom = NULL; + + memset(&ret, 0, sizeof(ret)); + if (call(conn, priv, 0, + REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_REGISTER_ANY, + (xdrproc_t) xdr_remote_connect_domain_event_callback_register_any_args, (char *) &args, + (xdrproc_t) xdr_remote_connect_domain_event_callback_register_any_ret, (char *) &ret) == -1) { + virObjectEventStateDeregisterID(conn, priv->eventState, + callbackID); + goto done; + } + virObjectEventStateSetRemote(conn, priv->eventState, callbackID, + ret.callbackID); + } else { + if (call(conn, priv, 0, REMOTE_PROC_CONNECT_DOMAIN_EVENT_REGISTER, + (xdrproc_t) xdr_void, (char *) NULL, + (xdrproc_t) xdr_void, (char *) NULL) == -1) { + virObjectEventStateDeregisterID(conn, priv->eventState, + callbackID); + goto done; + } } } @@ -4472,26 +4512,45 @@ done: return rv; } + static int remoteConnectDomainEventDeregister(virConnectPtr conn, virConnectDomainEventCallback callback) { struct private_data *priv = conn->privateData; int rv = -1; + remote_connect_domain_event_callback_deregister_any_args args; + int callbackID; + int remoteID; int count; remoteDriverLock(priv); - if ((count = virDomainEventStateDeregister(conn, priv->eventState, - callback)) < 0) + if ((callbackID = virDomainEventStateCallbackID(conn, priv->eventState, + callback, + &remoteID)) < 0) + goto done; + + if ((count = virObjectEventStateDeregisterID(conn, priv->eventState, + callbackID)) < 0) goto done; if (count == 0) { /* Tell the server when we are the last callback deregistering */ - if (call(conn, priv, 0, REMOTE_PROC_CONNECT_DOMAIN_EVENT_DEREGISTER, - (xdrproc_t) xdr_void, (char *) NULL, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; + if (priv->serverEventFilter) { + args.callbackID = remoteID; + + if (call(conn, priv, 0, + REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_DEREGISTER_ANY, + (xdrproc_t) xdr_remote_connect_domain_event_callback_deregister_any_args, (char *) &args, + (xdrproc_t) xdr_void, (char *) NULL) == -1) + goto done; + } else { + if (call(conn, priv, 0, REMOTE_PROC_CONNECT_DOMAIN_EVENT_DEREGISTER, + (xdrproc_t) xdr_void, (char *) NULL, + (xdrproc_t) xdr_void, (char *) NULL) == -1) + goto done; + } } rv = 0; @@ -4512,13 +4571,11 @@ remoteEventQueue(struct private_data *priv, virObjectEventPtr event, static void -remoteDomainBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, - virNetClientPtr client ATTRIBUTE_UNUSED, - void *evdata, void *opaque) +remoteDomainBuildEventLifecycleHelper(virConnectPtr conn, + remote_domain_event_lifecycle_msg *msg, + int callbackID) { - virConnectPtr conn = opaque; struct private_data *priv = conn->privateData; - remote_domain_event_lifecycle_msg *msg = evdata; virDomainPtr dom; virObjectEventPtr event = NULL; @@ -4529,7 +4586,25 @@ remoteDomainBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, event = virDomainEventLifecycleNewFromDom(dom, msg->event, msg->detail); virDomainFree(dom); - remoteEventQueue(priv, event, -1); + remoteEventQueue(priv, event, callbackID); +} +static void +remoteDomainBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_lifecycle_msg *msg = evdata; + remoteDomainBuildEventLifecycleHelper(conn, msg, -1); +} +static void +remoteDomainBuildEventCallbackLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_callback_lifecycle_msg *msg = evdata; + remoteDomainBuildEventLifecycleHelper(conn, &msg->msg, msg->callbackID); } @@ -5263,29 +5338,61 @@ remoteConnectDomainEventRegisterAny(virConnectPtr conn, { int rv = -1; struct private_data *priv = conn->privateData; - remote_connect_domain_event_register_any_args args; int callbackID; int count; + remote_nonnull_domain domain; + bool serverFilter; remoteDriverLock(priv); + serverFilter = priv->serverEventFilter; + /* FIXME support more than just lifecycle events */ + serverFilter &= eventID == VIR_DOMAIN_EVENT_ID_LIFECYCLE; + if ((count = virDomainEventStateRegisterClient(conn, priv->eventState, dom, eventID, callback, opaque, freecb, false, - &callbackID, false)) < 0) + &callbackID, + serverFilter)) < 0) goto done; /* If this is the first callback for this eventID, we need to enable * events on the server */ if (count == 1) { - args.eventID = eventID; + if (serverFilter) { + remote_connect_domain_event_callback_register_any_args args; + remote_connect_domain_event_callback_register_any_ret ret; + + args.eventID = eventID; + if (dom) { + make_nonnull_domain(&domain, dom); + args.dom = &domain; + } else { + args.dom = NULL; + } - if (call(conn, priv, 0, REMOTE_PROC_CONNECT_DOMAIN_EVENT_REGISTER_ANY, - (xdrproc_t) xdr_remote_connect_domain_event_register_any_args, (char *) &args, - (xdrproc_t) xdr_void, (char *)NULL) == -1) { - virObjectEventStateDeregisterID(conn, priv->eventState, - callbackID); - goto done; + memset(&ret, 0, sizeof(ret)); + if (call(conn, priv, 0, REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_REGISTER_ANY, + (xdrproc_t) xdr_remote_connect_domain_event_callback_register_any_args, (char *) &args, + (xdrproc_t) xdr_remote_connect_domain_event_callback_register_any_ret, (char *) &ret) == -1) { + virObjectEventStateDeregisterID(conn, priv->eventState, + callbackID); + goto done; + } + virObjectEventStateSetRemote(conn, priv->eventState, callbackID, + ret.callbackID); + } else { + remote_connect_domain_event_register_any_args args; + + args.eventID = eventID; + + if (call(conn, priv, 0, REMOTE_PROC_CONNECT_DOMAIN_EVENT_REGISTER_ANY, + (xdrproc_t) xdr_remote_connect_domain_event_register_any_args, (char *) &args, + (xdrproc_t) xdr_void, (char *)NULL) == -1) { + virObjectEventStateDeregisterID(conn, priv->eventState, + callbackID); + goto done; + } } } @@ -5303,14 +5410,14 @@ remoteConnectDomainEventDeregisterAny(virConnectPtr conn, { struct private_data *priv = conn->privateData; int rv = -1; - remote_connect_domain_event_deregister_any_args args; int eventID; + int remoteID; int count; remoteDriverLock(priv); if ((eventID = virObjectEventStateEventID(conn, priv->eventState, - callbackID, NULL)) < 0) + callbackID, &remoteID)) < 0) goto done; if ((count = virObjectEventStateDeregisterID(conn, priv->eventState, @@ -5319,13 +5426,29 @@ remoteConnectDomainEventDeregisterAny(virConnectPtr conn, /* If that was the last callback for this eventID, we need to disable * events on the server */ + /* FIXME support more than just lifecycle events */ if (count == 0) { - args.eventID = eventID; + if (priv->serverEventFilter && + eventID == VIR_DOMAIN_EVENT_ID_LIFECYCLE) { + remote_connect_domain_event_callback_deregister_any_args args; - if (call(conn, priv, 0, REMOTE_PROC_CONNECT_DOMAIN_EVENT_DEREGISTER_ANY, - (xdrproc_t) xdr_remote_connect_domain_event_deregister_any_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; + args.callbackID = remoteID; + + if (call(conn, priv, 0, + REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_DEREGISTER_ANY, + (xdrproc_t) xdr_remote_connect_domain_event_callback_deregister_any_args, (char *) &args, + (xdrproc_t) xdr_void, (char *) NULL) == -1) + goto done; + } else { + remote_connect_domain_event_deregister_any_args args; + + args.eventID = eventID; + + if (call(conn, priv, 0, REMOTE_PROC_CONNECT_DOMAIN_EVENT_DEREGISTER_ANY, + (xdrproc_t) xdr_remote_connect_domain_event_deregister_any_args, (char *) &args, + (xdrproc_t) xdr_void, (char *) NULL) == -1) + goto done; + } } rv = 0; -- 1.8.5.3

On Wed, Jan 29, 2014 at 10:49:24AM -0700, Eric Blake wrote:
The counterpart to the server RPC additions; here, a single function can serve both old and new calls, while incoming events must be serviced by two different functions. Again, some wise choices in our XDR makes event sharing easier.
While this only supports lifecycle events, it covers the harder part of how Register and RegisterAny interact; the remaining 15 events will be a mechanical change in a later patch. For Register, we now have a callbackID locally for more efficient cleanup if the RPC fails; we also prefer to use the newer RPC where we know it is supported (the older RPC must be used if we don't know if RegisterAny is supported).
* src/remote/remote_driver.c (remoteEvents): Register new RPC event handler. (remoteDomainBuildEventLifecycle): Move guts... (remoteDomainBuildEventLifecycleHelper): ...here. (remoteDomainBuildEventCallbackLifecycle): New function. (remoteConnectDomainEventRegister) (remoteConnectDomainEventDeregister) (remoteConnectDomainEventRegisterAny) (remoteConnectDomainEventDeregisterAny): Use new RPC when supported.
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Following the patterns established by lifecycle events, this creates all the new RPC calls needed to pass callback IDs for every domain event, and changes the limits in client and server codes to use modern style when possible. I've tested all combinations: both 'old client and new server' and 'new client and old server' continue to work with the old RPCs, and 'new client and new server' benefit from server-side filtering with the new RPCs. * src/remote/remote_protocol.x (REMOTE_PROC_DOMAIN_EVENT_*): Add REMOTE_PROC_DOMAIN_EVENT_CALLBACK_* counterparts. * daemon/remote.c (remoteRelayDomainEvent*): Send callbackID via newer RPC when used with new-style registration. (remoteDispatchConnectDomainEventCallbackRegisterAny): Extend to cover all domain events. * src/remote/remote_driver.c (remoteDomainBuildEvent*): Add new Callback and Helper functions. (remoteEvents): Match order of RPC numbers, register new handlers. (remoteConnectDomainEventRegisterAny) (remoteConnectDomainEventDeregisterAny): Extend to cover all domain events. * src/remote_protocol-structs: Regenerate. Signed-off-by: Eric Blake <eblake@redhat.com> --- daemon/remote.c | 240 ++++++++++++++---- src/remote/remote_driver.c | 581 ++++++++++++++++++++++++++++++++++--------- src/remote/remote_protocol.x | 155 +++++++++++- src/remote_protocol-structs | 75 ++++++ 4 files changed, 886 insertions(+), 165 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 1dfcb65..48c707d 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -239,16 +239,25 @@ remoteRelayDomainEventReboot(virConnectPtr conn, !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) return -1; - VIR_DEBUG("Relaying domain reboot event %s %d, callback %d", - dom->name, dom->id, callback->callbackID); + VIR_DEBUG("Relaying domain reboot event %s %d, callback %d legacy %d", + dom->name, dom->id, callback->callbackID, callback->legacy); /* build return data */ memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(callback->client, remoteProgram, - REMOTE_PROC_DOMAIN_EVENT_REBOOT, - (xdrproc_t)xdr_remote_domain_event_reboot_msg, &data); + if (callback->legacy) { + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_REBOOT, + (xdrproc_t)xdr_remote_domain_event_reboot_msg, &data); + } else { + remote_domain_event_callback_reboot_msg msg = { callback->callbackID, + data }; + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_REBOOT, + (xdrproc_t)xdr_remote_domain_event_callback_reboot_msg, &msg); + } return 0; } @@ -267,17 +276,27 @@ remoteRelayDomainEventRTCChange(virConnectPtr conn, !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) return -1; - VIR_DEBUG("Relaying domain rtc change event %s %d %lld, callback %d", - dom->name, dom->id, offset, callback->callbackID); + VIR_DEBUG("Relaying domain rtc change event %s %d %lld, callback %d legacy %d", + dom->name, dom->id, offset, + callback->callbackID, callback->legacy); /* build return data */ memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); data.offset = offset; - remoteDispatchObjectEventSend(callback->client, remoteProgram, - REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE, - (xdrproc_t)xdr_remote_domain_event_rtc_change_msg, &data); + if (callback->legacy) { + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE, + (xdrproc_t)xdr_remote_domain_event_rtc_change_msg, &data); + } else { + remote_domain_event_callback_rtc_change_msg msg = { callback->callbackID, + data }; + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_RTC_CHANGE, + (xdrproc_t)xdr_remote_domain_event_callback_rtc_change_msg, &msg); + } return 0; } @@ -304,9 +323,18 @@ remoteRelayDomainEventWatchdog(virConnectPtr conn, make_nonnull_domain(&data.dom, dom); data.action = action; - remoteDispatchObjectEventSend(callback->client, remoteProgram, - REMOTE_PROC_DOMAIN_EVENT_WATCHDOG, - (xdrproc_t)xdr_remote_domain_event_watchdog_msg, &data); + if (callback->legacy) { + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_WATCHDOG, + (xdrproc_t)xdr_remote_domain_event_watchdog_msg, &data); + } else { + remote_domain_event_callback_watchdog_msg msg = { callback->callbackID, + data }; + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_WATCHDOG, + (xdrproc_t)xdr_remote_domain_event_callback_watchdog_msg, &msg); + } return 0; } @@ -339,9 +367,18 @@ remoteRelayDomainEventIOError(virConnectPtr conn, make_nonnull_domain(&data.dom, dom); data.action = action; - remoteDispatchObjectEventSend(callback->client, remoteProgram, - REMOTE_PROC_DOMAIN_EVENT_IO_ERROR, - (xdrproc_t)xdr_remote_domain_event_io_error_msg, &data); + if (callback->legacy) { + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_IO_ERROR, + (xdrproc_t)xdr_remote_domain_event_io_error_msg, &data); + } else { + remote_domain_event_callback_io_error_msg msg = { callback->callbackID, + data }; + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_IO_ERROR, + (xdrproc_t)xdr_remote_domain_event_callback_io_error_msg, &msg); + } return 0; error: @@ -381,9 +418,18 @@ remoteRelayDomainEventIOErrorReason(virConnectPtr conn, make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(callback->client, remoteProgram, - REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON, - (xdrproc_t)xdr_remote_domain_event_io_error_reason_msg, &data); + if (callback->legacy) { + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON, + (xdrproc_t)xdr_remote_domain_event_io_error_reason_msg, &data); + } else { + remote_domain_event_callback_io_error_reason_msg msg = { callback->callbackID, + data }; + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_IO_ERROR_REASON, + (xdrproc_t)xdr_remote_domain_event_callback_io_error_reason_msg, &msg); + } return 0; @@ -447,9 +493,18 @@ remoteRelayDomainEventGraphics(virConnectPtr conn, } make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(callback->client, remoteProgram, - REMOTE_PROC_DOMAIN_EVENT_GRAPHICS, - (xdrproc_t)xdr_remote_domain_event_graphics_msg, &data); + if (callback->legacy) { + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_GRAPHICS, + (xdrproc_t)xdr_remote_domain_event_graphics_msg, &data); + } else { + remote_domain_event_callback_graphics_msg msg = { callback->callbackID, + data }; + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_GRAPHICS, + (xdrproc_t)xdr_remote_domain_event_callback_graphics_msg, &msg); + } return 0; @@ -495,9 +550,18 @@ remoteRelayDomainEventBlockJob(virConnectPtr conn, data.status = status; make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(callback->client, remoteProgram, - REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB, - (xdrproc_t)xdr_remote_domain_event_block_job_msg, &data); + if (callback->legacy) { + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB, + (xdrproc_t)xdr_remote_domain_event_block_job_msg, &data); + } else { + remote_domain_event_callback_block_job_msg msg = { callback->callbackID, + data }; + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_BLOCK_JOB, + (xdrproc_t)xdr_remote_domain_event_callback_block_job_msg, &msg); + } return 0; error: @@ -525,9 +589,18 @@ remoteRelayDomainEventControlError(virConnectPtr conn, memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(callback->client, remoteProgram, - REMOTE_PROC_DOMAIN_EVENT_CONTROL_ERROR, - (xdrproc_t)xdr_remote_domain_event_control_error_msg, &data); + if (callback->legacy) { + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_CONTROL_ERROR, + (xdrproc_t)xdr_remote_domain_event_control_error_msg, &data); + } else { + remote_domain_event_callback_control_error_msg msg = { callback->callbackID, + data }; + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_CONTROL_ERROR, + (xdrproc_t)xdr_remote_domain_event_callback_control_error_msg, &msg); + } return 0; } @@ -574,9 +647,18 @@ remoteRelayDomainEventDiskChange(virConnectPtr conn, make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(callback->client, remoteProgram, - REMOTE_PROC_DOMAIN_EVENT_DISK_CHANGE, - (xdrproc_t)xdr_remote_domain_event_disk_change_msg, &data); + if (callback->legacy) { + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_DISK_CHANGE, + (xdrproc_t)xdr_remote_domain_event_disk_change_msg, &data); + } else { + remote_domain_event_callback_disk_change_msg msg = { callback->callbackID, + data }; + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DISK_CHANGE, + (xdrproc_t)xdr_remote_domain_event_callback_disk_change_msg, &msg); + } return 0; @@ -613,9 +695,18 @@ remoteRelayDomainEventTrayChange(virConnectPtr conn, make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(callback->client, remoteProgram, - REMOTE_PROC_DOMAIN_EVENT_TRAY_CHANGE, - (xdrproc_t)xdr_remote_domain_event_tray_change_msg, &data); + if (callback->legacy) { + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_TRAY_CHANGE, + (xdrproc_t)xdr_remote_domain_event_tray_change_msg, &data); + } else { + remote_domain_event_callback_tray_change_msg msg = { callback->callbackID, + data }; + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_TRAY_CHANGE, + (xdrproc_t)xdr_remote_domain_event_callback_tray_change_msg, &msg); + } return 0; } @@ -640,9 +731,18 @@ remoteRelayDomainEventPMWakeup(virConnectPtr conn, memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(callback->client, remoteProgram, - REMOTE_PROC_DOMAIN_EVENT_PMWAKEUP, - (xdrproc_t)xdr_remote_domain_event_pmwakeup_msg, &data); + if (callback->legacy) { + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_PMWAKEUP, + (xdrproc_t)xdr_remote_domain_event_pmwakeup_msg, &data); + } else { + remote_domain_event_callback_pmwakeup_msg msg = { callback->callbackID, + data }; + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_PMWAKEUP, + (xdrproc_t)xdr_remote_domain_event_callback_pmwakeup_msg, &msg); + } return 0; } @@ -667,9 +767,18 @@ remoteRelayDomainEventPMSuspend(virConnectPtr conn, memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(callback->client, remoteProgram, - REMOTE_PROC_DOMAIN_EVENT_PMSUSPEND, - (xdrproc_t)xdr_remote_domain_event_pmsuspend_msg, &data); + if (callback->legacy) { + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_PMSUSPEND, + (xdrproc_t)xdr_remote_domain_event_pmsuspend_msg, &data); + } else { + remote_domain_event_callback_pmsuspend_msg msg = { callback->callbackID, + data }; + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_PMSUSPEND, + (xdrproc_t)xdr_remote_domain_event_callback_pmsuspend_msg, &msg); + } return 0; } @@ -695,9 +804,18 @@ remoteRelayDomainEventBalloonChange(virConnectPtr conn, make_nonnull_domain(&data.dom, dom); data.actual = actual; - remoteDispatchObjectEventSend(callback->client, remoteProgram, - REMOTE_PROC_DOMAIN_EVENT_BALLOON_CHANGE, - (xdrproc_t)xdr_remote_domain_event_balloon_change_msg, &data); + if (callback->legacy) { + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_BALLOON_CHANGE, + (xdrproc_t)xdr_remote_domain_event_balloon_change_msg, &data); + } else { + remote_domain_event_callback_balloon_change_msg msg = { callback->callbackID, + data }; + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_BALLOON_CHANGE, + (xdrproc_t)xdr_remote_domain_event_callback_balloon_change_msg, &msg); + } return 0; } @@ -723,9 +841,18 @@ remoteRelayDomainEventPMSuspendDisk(virConnectPtr conn, memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(callback->client, remoteProgram, - REMOTE_PROC_DOMAIN_EVENT_PMSUSPEND_DISK, - (xdrproc_t)xdr_remote_domain_event_pmsuspend_disk_msg, &data); + if (callback->legacy) { + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_PMSUSPEND_DISK, + (xdrproc_t)xdr_remote_domain_event_pmsuspend_disk_msg, &data); + } else { + remote_domain_event_callback_pmsuspend_disk_msg msg = { callback->callbackID, + data }; + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_PMSUSPEND_DISK, + (xdrproc_t)xdr_remote_domain_event_callback_pmsuspend_disk_msg, &msg); + } return 0; } @@ -754,10 +881,20 @@ remoteRelayDomainEventDeviceRemoved(virConnectPtr conn, make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(callback->client, remoteProgram, - REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED, - (xdrproc_t)xdr_remote_domain_event_device_removed_msg, - &data); + if (callback->legacy) { + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED, + (xdrproc_t)xdr_remote_domain_event_device_removed_msg, + &data); + } else { + remote_domain_event_callback_device_removed_msg msg = { callback->callbackID, + data }; + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_REMOVED, + (xdrproc_t)xdr_remote_domain_event_callback_device_removed_msg, + &msg); + } return 0; } @@ -3589,8 +3726,7 @@ remoteDispatchConnectDomainEventCallbackRegisterAny(virNetServerPtr server ATTRI !(dom = get_nonnull_domain(priv->conn, *args->dom))) goto cleanup; - /* FIXME: support all domain events */ - if (args->eventID != VIR_DOMAIN_EVENT_ID_LIFECYCLE) { + if (args->eventID >= VIR_DOMAIN_EVENT_ID_LAST || args->eventID < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported event ID %d"), args->eventID); goto cleanup; diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 35baaeb..4cdce81 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -218,67 +218,136 @@ remoteDomainBuildEventReboot(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virNetClientPtr client ATTRIBUTE_UNUSED, void *evdata, void *opaque); static void +remoteDomainBuildEventCallbackReboot(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque); + +static void remoteDomainBuildEventRTCChange(virNetClientProgramPtr prog, virNetClientPtr client, void *evdata, void *opaque); static void +remoteDomainBuildEventCallbackRTCChange(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); + +static void remoteDomainBuildEventWatchdog(virNetClientProgramPtr prog, virNetClientPtr client, void *evdata, void *opaque); static void +remoteDomainBuildEventCallbackWatchdog(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); + +static void remoteDomainBuildEventIOError(virNetClientProgramPtr prog, virNetClientPtr client, void *evdata, void *opaque); static void +remoteDomainBuildEventCallbackIOError(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); + +static void remoteDomainBuildEventIOErrorReason(virNetClientProgramPtr prog, virNetClientPtr client, void *evdata, void *opaque); static void +remoteDomainBuildEventCallbackIOErrorReason(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); + +static void remoteDomainBuildEventGraphics(virNetClientProgramPtr prog, virNetClientPtr client, void *evdata, void *opaque); static void +remoteDomainBuildEventCallbackGraphics(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); + +static void remoteDomainBuildEventControlError(virNetClientProgramPtr prog, virNetClientPtr client, void *evdata, void *opaque); +static void +remoteDomainBuildEventCallbackControlError(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); static void remoteDomainBuildEventBlockJob(virNetClientProgramPtr prog, virNetClientPtr client, void *evdata, void *opaque); +static void +remoteDomainBuildEventCallbackBlockJob(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); + static void remoteDomainBuildEventDiskChange(virNetClientProgramPtr prog, virNetClientPtr client, void *evdata, void *opaque); +static void +remoteDomainBuildEventCallbackDiskChange(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); static void remoteDomainBuildEventTrayChange(virNetClientProgramPtr prog, virNetClientPtr client, void *evdata, void *opaque); +static void +remoteDomainBuildEventCallbackTrayChange(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); static void remoteDomainBuildEventPMWakeup(virNetClientProgramPtr prog, virNetClientPtr client, void *evdata, void *opaque); +static void +remoteDomainBuildEventCallbackPMWakeup(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); static void remoteDomainBuildEventPMSuspend(virNetClientProgramPtr prog, virNetClientPtr client, void *evdata, void *opaque); static void +remoteDomainBuildEventCallbackPMSuspend(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); + +static void remoteDomainBuildEventBalloonChange(virNetClientProgramPtr prog, virNetClientPtr client, void *evdata, void *opaque); static void +remoteDomainBuildEventCallbackBalloonChange(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); + +static void remoteDomainBuildEventPMSuspendDisk(virNetClientProgramPtr prog, virNetClientPtr client, void *evdata, void *opaque); +static void +remoteDomainBuildEventCallbackPMSuspendDisk(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); static void remoteDomainBuildEventDeviceRemoved(virNetClientProgramPtr prog, virNetClientPtr client, void *evdata, void *opaque); +static void +remoteDomainBuildEventCallbackDeviceRemoved(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); static void remoteNetworkBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, @@ -286,18 +355,18 @@ remoteNetworkBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, void *evdata, void *opaque); static virNetClientProgramEvent remoteEvents[] = { - { REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE, - remoteDomainBuildEventRTCChange, - sizeof(remote_domain_event_rtc_change_msg), - (xdrproc_t)xdr_remote_domain_event_rtc_change_msg }, - { REMOTE_PROC_DOMAIN_EVENT_REBOOT, - remoteDomainBuildEventReboot, - sizeof(remote_domain_event_reboot_msg), - (xdrproc_t)xdr_remote_domain_event_reboot_msg }, { REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE, remoteDomainBuildEventLifecycle, sizeof(remote_domain_event_lifecycle_msg), (xdrproc_t)xdr_remote_domain_event_lifecycle_msg }, + { REMOTE_PROC_DOMAIN_EVENT_REBOOT, + remoteDomainBuildEventReboot, + sizeof(remote_domain_event_reboot_msg), + (xdrproc_t)xdr_remote_domain_event_reboot_msg }, + { REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE, + remoteDomainBuildEventRTCChange, + sizeof(remote_domain_event_rtc_change_msg), + (xdrproc_t)xdr_remote_domain_event_rtc_change_msg }, { REMOTE_PROC_DOMAIN_EVENT_WATCHDOG, remoteDomainBuildEventWatchdog, sizeof(remote_domain_event_watchdog_msg), @@ -306,14 +375,14 @@ static virNetClientProgramEvent remoteEvents[] = { remoteDomainBuildEventIOError, sizeof(remote_domain_event_io_error_msg), (xdrproc_t)xdr_remote_domain_event_io_error_msg }, - { REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON, - remoteDomainBuildEventIOErrorReason, - sizeof(remote_domain_event_io_error_reason_msg), - (xdrproc_t)xdr_remote_domain_event_io_error_reason_msg }, { REMOTE_PROC_DOMAIN_EVENT_GRAPHICS, remoteDomainBuildEventGraphics, sizeof(remote_domain_event_graphics_msg), (xdrproc_t)xdr_remote_domain_event_graphics_msg }, + { REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON, + remoteDomainBuildEventIOErrorReason, + sizeof(remote_domain_event_io_error_reason_msg), + (xdrproc_t)xdr_remote_domain_event_io_error_reason_msg }, { REMOTE_PROC_DOMAIN_EVENT_CONTROL_ERROR, remoteDomainBuildEventControlError, sizeof(remote_domain_event_control_error_msg), @@ -367,6 +436,66 @@ static virNetClientProgramEvent remoteEvents[] = { remoteDomainBuildEventCallbackLifecycle, sizeof(remote_domain_event_callback_lifecycle_msg), (xdrproc_t)xdr_remote_domain_event_callback_lifecycle_msg }, + { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_REBOOT, + remoteDomainBuildEventCallbackReboot, + sizeof(remote_domain_event_callback_reboot_msg), + (xdrproc_t)xdr_remote_domain_event_callback_reboot_msg }, + { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_RTC_CHANGE, + remoteDomainBuildEventCallbackRTCChange, + sizeof(remote_domain_event_callback_rtc_change_msg), + (xdrproc_t)xdr_remote_domain_event_callback_rtc_change_msg }, + { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_WATCHDOG, + remoteDomainBuildEventCallbackWatchdog, + sizeof(remote_domain_event_callback_watchdog_msg), + (xdrproc_t)xdr_remote_domain_event_callback_watchdog_msg}, + { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_IO_ERROR, + remoteDomainBuildEventCallbackIOError, + sizeof(remote_domain_event_callback_io_error_msg), + (xdrproc_t)xdr_remote_domain_event_callback_io_error_msg }, + { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_GRAPHICS, + remoteDomainBuildEventCallbackGraphics, + sizeof(remote_domain_event_callback_graphics_msg), + (xdrproc_t)xdr_remote_domain_event_callback_graphics_msg }, + { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_IO_ERROR_REASON, + remoteDomainBuildEventCallbackIOErrorReason, + sizeof(remote_domain_event_callback_io_error_reason_msg), + (xdrproc_t)xdr_remote_domain_event_callback_io_error_reason_msg }, + { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_CONTROL_ERROR, + remoteDomainBuildEventCallbackControlError, + sizeof(remote_domain_event_callback_control_error_msg), + (xdrproc_t)xdr_remote_domain_event_callback_control_error_msg }, + { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_BLOCK_JOB, + remoteDomainBuildEventCallbackBlockJob, + sizeof(remote_domain_event_callback_block_job_msg), + (xdrproc_t)xdr_remote_domain_event_callback_block_job_msg }, + { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DISK_CHANGE, + remoteDomainBuildEventCallbackDiskChange, + sizeof(remote_domain_event_callback_disk_change_msg), + (xdrproc_t)xdr_remote_domain_event_callback_disk_change_msg }, + { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_TRAY_CHANGE, + remoteDomainBuildEventCallbackTrayChange, + sizeof(remote_domain_event_callback_tray_change_msg), + (xdrproc_t)xdr_remote_domain_event_callback_tray_change_msg }, + { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_PMWAKEUP, + remoteDomainBuildEventCallbackPMWakeup, + sizeof(remote_domain_event_callback_pmwakeup_msg), + (xdrproc_t)xdr_remote_domain_event_callback_pmwakeup_msg }, + { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_PMSUSPEND, + remoteDomainBuildEventCallbackPMSuspend, + sizeof(remote_domain_event_callback_pmsuspend_msg), + (xdrproc_t)xdr_remote_domain_event_callback_pmsuspend_msg }, + { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_BALLOON_CHANGE, + remoteDomainBuildEventCallbackBalloonChange, + sizeof(remote_domain_event_callback_balloon_change_msg), + (xdrproc_t)xdr_remote_domain_event_callback_balloon_change_msg }, + { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_PMSUSPEND_DISK, + remoteDomainBuildEventCallbackPMSuspendDisk, + sizeof(remote_domain_event_callback_pmsuspend_disk_msg), + (xdrproc_t)xdr_remote_domain_event_callback_pmsuspend_disk_msg }, + { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_REMOVED, + remoteDomainBuildEventCallbackDeviceRemoved, + sizeof(remote_domain_event_callback_device_removed_msg), + (xdrproc_t)xdr_remote_domain_event_callback_device_removed_msg }, }; enum virDrvOpenRemoteFlags { @@ -4609,13 +4738,11 @@ remoteDomainBuildEventCallbackLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UN static void -remoteDomainBuildEventReboot(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, - virNetClientPtr client ATTRIBUTE_UNUSED, - void *evdata, void *opaque) +remoteDomainBuildEventRebootHelper(virConnectPtr conn, + remote_domain_event_reboot_msg *msg, + int callbackID) { - virConnectPtr conn = opaque; struct private_data *priv = conn->privateData; - remote_domain_event_reboot_msg *msg = evdata; virDomainPtr dom; virObjectEventPtr event = NULL; @@ -4626,18 +4753,33 @@ remoteDomainBuildEventReboot(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, event = virDomainEventRebootNewFromDom(dom); virDomainFree(dom); - remoteEventQueue(priv, event, -1); + remoteEventQueue(priv, event, callbackID); } - - static void -remoteDomainBuildEventRTCChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, - virNetClientPtr client ATTRIBUTE_UNUSED, - void *evdata, void *opaque) +remoteDomainBuildEventReboot(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_reboot_msg *msg = evdata; + remoteDomainBuildEventRebootHelper(conn, msg, -1); +} +static void +remoteDomainBuildEventCallbackReboot(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) { virConnectPtr conn = opaque; + remote_domain_event_callback_reboot_msg *msg = evdata; + remoteDomainBuildEventRebootHelper(conn, &msg->msg, msg->callbackID); +} + +static void +remoteDomainBuildEventRTCChangeHelper(virConnectPtr conn, + remote_domain_event_rtc_change_msg *msg, + int callbackID) +{ struct private_data *priv = conn->privateData; - remote_domain_event_rtc_change_msg *msg = evdata; virDomainPtr dom; virObjectEventPtr event = NULL; @@ -4648,18 +4790,33 @@ remoteDomainBuildEventRTCChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, event = virDomainEventRTCChangeNewFromDom(dom, msg->offset); virDomainFree(dom); - remoteEventQueue(priv, event, -1); + remoteEventQueue(priv, event, callbackID); } - - static void -remoteDomainBuildEventWatchdog(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, - virNetClientPtr client ATTRIBUTE_UNUSED, - void *evdata, void *opaque) +remoteDomainBuildEventRTCChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) { virConnectPtr conn = opaque; + remote_domain_event_rtc_change_msg *msg = evdata; + remoteDomainBuildEventRTCChangeHelper(conn, msg, -1); +} +static void +remoteDomainBuildEventCallbackRTCChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_callback_rtc_change_msg *msg = evdata; + remoteDomainBuildEventRTCChangeHelper(conn, &msg->msg, msg->callbackID); +} + +static void +remoteDomainBuildEventWatchdogHelper(virConnectPtr conn, + remote_domain_event_watchdog_msg *msg, + int callbackID) +{ struct private_data *priv = conn->privateData; - remote_domain_event_watchdog_msg *msg = evdata; virDomainPtr dom; virObjectEventPtr event = NULL; @@ -4670,18 +4827,33 @@ remoteDomainBuildEventWatchdog(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, event = virDomainEventWatchdogNewFromDom(dom, msg->action); virDomainFree(dom); - remoteEventQueue(priv, event, -1); + remoteEventQueue(priv, event, callbackID); } - - static void -remoteDomainBuildEventIOError(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, - virNetClientPtr client ATTRIBUTE_UNUSED, - void *evdata, void *opaque) +remoteDomainBuildEventWatchdog(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_watchdog_msg *msg = evdata; + remoteDomainBuildEventWatchdogHelper(conn, msg, -1); +} +static void +remoteDomainBuildEventCallbackWatchdog(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) { virConnectPtr conn = opaque; + remote_domain_event_callback_watchdog_msg *msg = evdata; + remoteDomainBuildEventWatchdogHelper(conn, &msg->msg, msg->callbackID); +} + +static void +remoteDomainBuildEventIOErrorHelper(virConnectPtr conn, + remote_domain_event_io_error_msg *msg, + int callbackID) +{ struct private_data *priv = conn->privateData; - remote_domain_event_io_error_msg *msg = evdata; virDomainPtr dom; virObjectEventPtr event = NULL; @@ -4695,18 +4867,33 @@ remoteDomainBuildEventIOError(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, msg->action); virDomainFree(dom); - remoteEventQueue(priv, event, -1); + remoteEventQueue(priv, event, callbackID); } - - static void -remoteDomainBuildEventIOErrorReason(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, - virNetClientPtr client ATTRIBUTE_UNUSED, - void *evdata, void *opaque) +remoteDomainBuildEventIOError(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_io_error_msg *msg = evdata; + remoteDomainBuildEventIOErrorHelper(conn, msg, -1); +} +static void +remoteDomainBuildEventCallbackIOError(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) { virConnectPtr conn = opaque; + remote_domain_event_callback_io_error_msg *msg = evdata; + remoteDomainBuildEventIOErrorHelper(conn, &msg->msg, msg->callbackID); +} + +static void +remoteDomainBuildEventIOErrorReasonHelper(virConnectPtr conn, + remote_domain_event_io_error_reason_msg *msg, + int callbackID) +{ struct private_data *priv = conn->privateData; - remote_domain_event_io_error_reason_msg *msg = evdata; virDomainPtr dom; virObjectEventPtr event = NULL; @@ -4722,17 +4909,33 @@ remoteDomainBuildEventIOErrorReason(virNetClientProgramPtr prog ATTRIBUTE_UNUSED virDomainFree(dom); - remoteEventQueue(priv, event, -1); + remoteEventQueue(priv, event, callbackID); } - static void -remoteDomainBuildEventBlockJob(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, - virNetClientPtr client ATTRIBUTE_UNUSED, - void *evdata, void *opaque) +remoteDomainBuildEventIOErrorReason(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) { virConnectPtr conn = opaque; + remote_domain_event_io_error_reason_msg *msg = evdata; + remoteDomainBuildEventIOErrorReasonHelper(conn, msg, -1); +} +static void +remoteDomainBuildEventCallbackIOErrorReason(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_callback_io_error_reason_msg *msg = evdata; + remoteDomainBuildEventIOErrorReasonHelper(conn, &msg->msg, msg->callbackID); +} + +static void +remoteDomainBuildEventBlockJobHelper(virConnectPtr conn, + remote_domain_event_block_job_msg *msg, + int callbackID) +{ struct private_data *priv = conn->privateData; - remote_domain_event_block_job_msg *msg = evdata; virDomainPtr dom; virObjectEventPtr event = NULL; @@ -4745,17 +4948,33 @@ remoteDomainBuildEventBlockJob(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virDomainFree(dom); - remoteEventQueue(priv, event, -1); + remoteEventQueue(priv, event, callbackID); } - static void -remoteDomainBuildEventGraphics(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, +remoteDomainBuildEventBlockJob(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virNetClientPtr client ATTRIBUTE_UNUSED, void *evdata, void *opaque) { virConnectPtr conn = opaque; + remote_domain_event_block_job_msg *msg = evdata; + remoteDomainBuildEventBlockJobHelper(conn, msg, -1); +} +static void +remoteDomainBuildEventCallbackBlockJob(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_callback_block_job_msg *msg = evdata; + remoteDomainBuildEventBlockJobHelper(conn, &msg->msg, msg->callbackID); +} + +static void +remoteDomainBuildEventGraphicsHelper(virConnectPtr conn, + remote_domain_event_graphics_msg *msg, + int callbackID) +{ struct private_data *priv = conn->privateData; - remote_domain_event_graphics_msg *msg = evdata; virDomainPtr dom; virObjectEventPtr event = NULL; virDomainEventGraphicsAddressPtr localAddr = NULL; @@ -4801,7 +5020,7 @@ remoteDomainBuildEventGraphics(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virDomainFree(dom); - remoteEventQueue(priv, event, -1); + remoteEventQueue(priv, event, callbackID); return; error: @@ -4826,16 +5045,31 @@ error: virDomainFree(dom); return; } - - static void -remoteDomainBuildEventControlError(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, - virNetClientPtr client ATTRIBUTE_UNUSED, - void *evdata, void *opaque) +remoteDomainBuildEventGraphics(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) { virConnectPtr conn = opaque; + remote_domain_event_graphics_msg *msg = evdata; + remoteDomainBuildEventGraphicsHelper(conn, msg, -1); +} +static void +remoteDomainBuildEventCallbackGraphics(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_callback_graphics_msg *msg = evdata; + remoteDomainBuildEventGraphicsHelper(conn, &msg->msg, msg->callbackID); +} + +static void +remoteDomainBuildEventControlErrorHelper(virConnectPtr conn, + remote_domain_event_control_error_msg *msg, + int callbackID) +{ struct private_data *priv = conn->privateData; - remote_domain_event_control_error_msg *msg = evdata; virDomainPtr dom; virObjectEventPtr event = NULL; @@ -4847,18 +5081,34 @@ remoteDomainBuildEventControlError(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virDomainFree(dom); - remoteEventQueue(priv, event, -1); + remoteEventQueue(priv, event, callbackID); +} +static void +remoteDomainBuildEventControlError(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_control_error_msg *msg = evdata; + remoteDomainBuildEventControlErrorHelper(conn, msg, -1); +} +static void +remoteDomainBuildEventCallbackControlError(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_callback_control_error_msg *msg = evdata; + remoteDomainBuildEventControlErrorHelper(conn, &msg->msg, msg->callbackID); } static void -remoteDomainBuildEventDiskChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, - virNetClientPtr client ATTRIBUTE_UNUSED, - void *evdata, void *opaque) +remoteDomainBuildEventDiskChangeHelper(virConnectPtr conn, + remote_domain_event_disk_change_msg *msg, + int callbackID) { - virConnectPtr conn = opaque; struct private_data *priv = conn->privateData; - remote_domain_event_disk_change_msg *msg = evdata; virDomainPtr dom; virObjectEventPtr event = NULL; @@ -4874,18 +5124,34 @@ remoteDomainBuildEventDiskChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virDomainFree(dom); - remoteEventQueue(priv, event, -1); + remoteEventQueue(priv, event, callbackID); } - - static void -remoteDomainBuildEventTrayChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, +remoteDomainBuildEventDiskChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virNetClientPtr client ATTRIBUTE_UNUSED, void *evdata, void *opaque) { virConnectPtr conn = opaque; + remote_domain_event_disk_change_msg *msg = evdata; + remoteDomainBuildEventDiskChangeHelper(conn, msg, -1); +} +static void +remoteDomainBuildEventCallbackDiskChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_callback_disk_change_msg *msg = evdata; + remoteDomainBuildEventDiskChangeHelper(conn, &msg->msg, msg->callbackID); +} + + +static void +remoteDomainBuildEventTrayChangeHelper(virConnectPtr conn, + remote_domain_event_tray_change_msg *msg, + int callbackID) +{ struct private_data *priv = conn->privateData; - remote_domain_event_tray_change_msg *msg = evdata; virDomainPtr dom; virObjectEventPtr event = NULL; @@ -4899,17 +5165,33 @@ remoteDomainBuildEventTrayChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virDomainFree(dom); - remoteEventQueue(priv, event, -1); + remoteEventQueue(priv, event, callbackID); } - static void -remoteDomainBuildEventPMWakeup(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, - virNetClientPtr client ATTRIBUTE_UNUSED, - void *evdata, void *opaque) +remoteDomainBuildEventTrayChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_tray_change_msg *msg = evdata; + remoteDomainBuildEventTrayChangeHelper(conn, msg, -1); +} +static void +remoteDomainBuildEventCallbackTrayChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) { virConnectPtr conn = opaque; + remote_domain_event_callback_tray_change_msg *msg = evdata; + remoteDomainBuildEventTrayChangeHelper(conn, &msg->msg, msg->callbackID); +} + +static void +remoteDomainBuildEventPMWakeupHelper(virConnectPtr conn, + remote_domain_event_pmwakeup_msg *msg, + int callbackID) +{ struct private_data *priv = conn->privateData; - remote_domain_event_pmwakeup_msg *msg = evdata; virDomainPtr dom; virObjectEventPtr event = NULL; @@ -4921,17 +5203,33 @@ remoteDomainBuildEventPMWakeup(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virDomainFree(dom); - remoteEventQueue(priv, event, -1); + remoteEventQueue(priv, event, callbackID); } - static void -remoteDomainBuildEventPMSuspend(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, - virNetClientPtr client ATTRIBUTE_UNUSED, - void *evdata, void *opaque) +remoteDomainBuildEventPMWakeup(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_pmwakeup_msg *msg = evdata; + remoteDomainBuildEventPMWakeupHelper(conn, msg, -1); +} +static void +remoteDomainBuildEventCallbackPMWakeup(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) { virConnectPtr conn = opaque; + remote_domain_event_callback_pmwakeup_msg *msg = evdata; + remoteDomainBuildEventPMWakeupHelper(conn, &msg->msg, msg->callbackID); +} + +static void +remoteDomainBuildEventPMSuspendHelper(virConnectPtr conn, + remote_domain_event_pmsuspend_msg *msg, + int callbackID) +{ struct private_data *priv = conn->privateData; - remote_domain_event_pmsuspend_msg *msg = evdata; virDomainPtr dom; virObjectEventPtr event = NULL; @@ -4943,18 +5241,34 @@ remoteDomainBuildEventPMSuspend(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virDomainFree(dom); - remoteEventQueue(priv, event, -1); + remoteEventQueue(priv, event, callbackID); +} +static void +remoteDomainBuildEventPMSuspend(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_pmsuspend_msg *msg = evdata; + remoteDomainBuildEventPMSuspendHelper(conn, msg, -1); +} +static void +remoteDomainBuildEventCallbackPMSuspend(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_callback_pmsuspend_msg *msg = evdata; + remoteDomainBuildEventPMSuspendHelper(conn, &msg->msg, msg->callbackID); } static void -remoteDomainBuildEventBalloonChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, - virNetClientPtr client ATTRIBUTE_UNUSED, - void *evdata, void *opaque) +remoteDomainBuildEventBalloonChangeHelper(virConnectPtr conn, + remote_domain_event_balloon_change_msg *msg, + int callbackID) { - virConnectPtr conn = opaque; struct private_data *priv = conn->privateData; - remote_domain_event_balloon_change_msg *msg = evdata; virDomainPtr dom; virObjectEventPtr event = NULL; @@ -4965,18 +5279,34 @@ remoteDomainBuildEventBalloonChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED event = virDomainEventBalloonChangeNewFromDom(dom, msg->actual); virDomainFree(dom); - remoteEventQueue(priv, event, -1); + remoteEventQueue(priv, event, callbackID); } - - static void -remoteDomainBuildEventPMSuspendDisk(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, +remoteDomainBuildEventBalloonChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virNetClientPtr client ATTRIBUTE_UNUSED, void *evdata, void *opaque) { virConnectPtr conn = opaque; + remote_domain_event_balloon_change_msg *msg = evdata; + remoteDomainBuildEventBalloonChangeHelper(conn, msg, -1); +} +static void +remoteDomainBuildEventCallbackBalloonChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_callback_balloon_change_msg *msg = evdata; + remoteDomainBuildEventBalloonChangeHelper(conn, &msg->msg, msg->callbackID); +} + + +static void +remoteDomainBuildEventPMSuspendDiskHelper(virConnectPtr conn, + remote_domain_event_pmsuspend_disk_msg *msg, + int callbackID) +{ struct private_data *priv = conn->privateData; - remote_domain_event_pmsuspend_disk_msg *msg = evdata; virDomainPtr dom; virObjectEventPtr event = NULL; @@ -4988,18 +5318,34 @@ remoteDomainBuildEventPMSuspendDisk(virNetClientProgramPtr prog ATTRIBUTE_UNUSED virDomainFree(dom); - remoteEventQueue(priv, event, -1); + remoteEventQueue(priv, event, callbackID); } - - static void -remoteDomainBuildEventDeviceRemoved(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, +remoteDomainBuildEventPMSuspendDisk(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virNetClientPtr client ATTRIBUTE_UNUSED, void *evdata, void *opaque) { virConnectPtr conn = opaque; + remote_domain_event_pmsuspend_disk_msg *msg = evdata; + remoteDomainBuildEventPMSuspendDiskHelper(conn, msg, -1); +} +static void +remoteDomainBuildEventCallbackPMSuspendDisk(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_callback_pmsuspend_disk_msg *msg = evdata; + remoteDomainBuildEventPMSuspendDiskHelper(conn, &msg->msg, msg->callbackID); +} + + +static void +remoteDomainBuildEventDeviceRemovedHelper(virConnectPtr conn, + remote_domain_event_device_removed_msg *msg, + int callbackID) +{ struct private_data *priv = conn->privateData; - remote_domain_event_device_removed_msg *msg = evdata; virDomainPtr dom; virObjectEventPtr event = NULL; @@ -5011,7 +5357,25 @@ remoteDomainBuildEventDeviceRemoved(virNetClientProgramPtr prog ATTRIBUTE_UNUSED virDomainFree(dom); - remoteEventQueue(priv, event, -1); + remoteEventQueue(priv, event, callbackID); +} +static void +remoteDomainBuildEventDeviceRemoved(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_device_removed_msg *msg = evdata; + remoteDomainBuildEventDeviceRemovedHelper(conn, msg, -1); +} +static void +remoteDomainBuildEventCallbackDeviceRemoved(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_callback_device_removed_msg *msg = evdata; + remoteDomainBuildEventDeviceRemovedHelper(conn, &msg->msg, msg->callbackID); } @@ -5341,25 +5705,20 @@ remoteConnectDomainEventRegisterAny(virConnectPtr conn, int callbackID; int count; remote_nonnull_domain domain; - bool serverFilter; remoteDriverLock(priv); - serverFilter = priv->serverEventFilter; - /* FIXME support more than just lifecycle events */ - serverFilter &= eventID == VIR_DOMAIN_EVENT_ID_LIFECYCLE; - if ((count = virDomainEventStateRegisterClient(conn, priv->eventState, dom, eventID, callback, opaque, freecb, false, &callbackID, - serverFilter)) < 0) + priv->serverEventFilter)) < 0) goto done; /* If this is the first callback for this eventID, we need to enable * events on the server */ if (count == 1) { - if (serverFilter) { + if (priv->serverEventFilter) { remote_connect_domain_event_callback_register_any_args args; remote_connect_domain_event_callback_register_any_ret ret; @@ -5426,10 +5785,8 @@ remoteConnectDomainEventDeregisterAny(virConnectPtr conn, /* If that was the last callback for this eventID, we need to disable * events on the server */ - /* FIXME support more than just lifecycle events */ if (count == 0) { - if (priv->serverEventFilter && - eventID == VIR_DOMAIN_EVENT_ID_LIFECYCLE) { + if (priv->serverEventFilter) { remote_connect_domain_event_callback_deregister_any_args args; args.callbackID = remoteID; diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 982ab1f..8238405 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -2268,16 +2268,28 @@ struct remote_connect_domain_event_callback_deregister_any_args { struct remote_domain_event_reboot_msg { remote_nonnull_domain dom; }; +struct remote_domain_event_callback_reboot_msg { + int callbackID; + remote_domain_event_reboot_msg msg; +}; struct remote_domain_event_rtc_change_msg { remote_nonnull_domain dom; hyper offset; }; +struct remote_domain_event_callback_rtc_change_msg { + int callbackID; + remote_domain_event_rtc_change_msg msg; +}; struct remote_domain_event_watchdog_msg { remote_nonnull_domain dom; int action; }; +struct remote_domain_event_callback_watchdog_msg { + int callbackID; + remote_domain_event_watchdog_msg msg; +}; struct remote_domain_event_io_error_msg { remote_nonnull_domain dom; @@ -2285,6 +2297,10 @@ struct remote_domain_event_io_error_msg { remote_nonnull_string devAlias; int action; }; +struct remote_domain_event_callback_io_error_msg { + int callbackID; + remote_domain_event_io_error_msg msg; +}; struct remote_domain_event_io_error_reason_msg { remote_nonnull_domain dom; @@ -2293,6 +2309,10 @@ struct remote_domain_event_io_error_reason_msg { int action; remote_nonnull_string reason; }; +struct remote_domain_event_callback_io_error_reason_msg { + int callbackID; + remote_domain_event_io_error_reason_msg msg; +}; struct remote_domain_event_graphics_address { int family; @@ -2315,6 +2335,10 @@ struct remote_domain_event_graphics_msg { remote_nonnull_string authScheme; remote_domain_event_graphics_identity subject<REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX>; }; +struct remote_domain_event_callback_graphics_msg { + int callbackID; + remote_domain_event_graphics_msg msg; +}; struct remote_domain_event_block_job_msg { remote_nonnull_domain dom; @@ -2322,6 +2346,10 @@ struct remote_domain_event_block_job_msg { int type; int status; }; +struct remote_domain_event_callback_block_job_msg { + int callbackID; + remote_domain_event_block_job_msg msg; +}; struct remote_domain_event_disk_change_msg { remote_nonnull_domain dom; @@ -2330,29 +2358,53 @@ struct remote_domain_event_disk_change_msg { remote_nonnull_string devAlias; int reason; }; +struct remote_domain_event_callback_disk_change_msg { + int callbackID; + remote_domain_event_disk_change_msg msg; +}; struct remote_domain_event_tray_change_msg { remote_nonnull_domain dom; remote_nonnull_string devAlias; int reason; }; +struct remote_domain_event_callback_tray_change_msg { + int callbackID; + remote_domain_event_tray_change_msg msg; +}; struct remote_domain_event_pmwakeup_msg { remote_nonnull_domain dom; }; +struct remote_domain_event_callback_pmwakeup_msg { + int callbackID; + remote_domain_event_pmwakeup_msg msg; +}; struct remote_domain_event_pmsuspend_msg { remote_nonnull_domain dom; }; +struct remote_domain_event_callback_pmsuspend_msg { + int callbackID; + remote_domain_event_pmsuspend_msg msg; +}; struct remote_domain_event_balloon_change_msg { remote_nonnull_domain dom; unsigned hyper actual; }; +struct remote_domain_event_callback_balloon_change_msg { + int callbackID; + remote_domain_event_balloon_change_msg msg; +}; struct remote_domain_event_pmsuspend_disk_msg { remote_nonnull_domain dom; }; +struct remote_domain_event_callback_pmsuspend_disk_msg { + int callbackID; + remote_domain_event_pmsuspend_disk_msg msg; +}; struct remote_domain_managed_save_args { remote_nonnull_domain dom; @@ -2631,6 +2683,10 @@ struct remote_domain_migrate_confirm3_args { struct remote_domain_event_control_error_msg { remote_nonnull_domain dom; }; +struct remote_domain_event_callback_control_error_msg { + int callbackID; + remote_domain_event_control_error_msg msg; +}; struct remote_domain_get_control_info_args { remote_nonnull_domain dom; @@ -2850,10 +2906,17 @@ struct remote_domain_migrate_confirm3_params_args { int cancelled; }; +/* The device removed event is the last event where we have to support + * dual forms for back-compat to older clients; all future events can + * use just the modern form with callbackID. */ struct remote_domain_event_device_removed_msg { remote_nonnull_domain dom; remote_nonnull_string devAlias; }; +struct remote_domain_event_callback_device_removed_msg { + int callbackID; + remote_domain_event_device_removed_msg msg; +}; struct remote_connect_get_cpu_model_names_args { remote_nonnull_string arch; @@ -5105,5 +5168,95 @@ enum remote_procedure { * @generate: both * @acl: none */ - REMOTE_PROC_DOMAIN_EVENT_CALLBACK_LIFECYCLE = 318 + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_LIFECYCLE = 318, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_REBOOT = 319, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_RTC_CHANGE = 320, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_WATCHDOG = 321, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_IO_ERROR = 322, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_GRAPHICS = 323, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_IO_ERROR_REASON = 324, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_CONTROL_ERROR = 325, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_BLOCK_JOB = 326, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DISK_CHANGE = 327, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_TRAY_CHANGE = 328, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_PMWAKEUP = 329, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_PMSUSPEND = 330, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_BALLOON_CHANGE = 331, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_PMSUSPEND_DISK = 332, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_REMOVED = 333 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 39d3981..fdff787 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -1724,20 +1724,36 @@ struct remote_connect_domain_event_callback_deregister_any_args { struct remote_domain_event_reboot_msg { remote_nonnull_domain dom; }; +struct remote_domain_event_callback_reboot_msg { + int callbackID; + remote_domain_event_reboot_msg msg; +}; struct remote_domain_event_rtc_change_msg { remote_nonnull_domain dom; int64_t offset; }; +struct remote_domain_event_callback_rtc_change_msg { + int callbackID; + remote_domain_event_rtc_change_msg msg; +}; struct remote_domain_event_watchdog_msg { remote_nonnull_domain dom; int action; }; +struct remote_domain_event_callback_watchdog_msg { + int callbackID; + remote_domain_event_watchdog_msg msg; +}; struct remote_domain_event_io_error_msg { remote_nonnull_domain dom; remote_nonnull_string srcPath; remote_nonnull_string devAlias; int action; }; +struct remote_domain_event_callback_io_error_msg { + int callbackID; + remote_domain_event_io_error_msg msg; +}; struct remote_domain_event_io_error_reason_msg { remote_nonnull_domain dom; remote_nonnull_string srcPath; @@ -1745,6 +1761,10 @@ struct remote_domain_event_io_error_reason_msg { int action; remote_nonnull_string reason; }; +struct remote_domain_event_callback_io_error_reason_msg { + int callbackID; + remote_domain_event_io_error_reason_msg msg; +}; struct remote_domain_event_graphics_address { int family; remote_nonnull_string node; @@ -1765,12 +1785,20 @@ struct remote_domain_event_graphics_msg { remote_domain_event_graphics_identity * subject_val; } subject; }; +struct remote_domain_event_callback_graphics_msg { + int callbackID; + remote_domain_event_graphics_msg msg; +}; struct remote_domain_event_block_job_msg { remote_nonnull_domain dom; remote_nonnull_string path; int type; int status; }; +struct remote_domain_event_callback_block_job_msg { + int callbackID; + remote_domain_event_block_job_msg msg; +}; struct remote_domain_event_disk_change_msg { remote_nonnull_domain dom; remote_string oldSrcPath; @@ -1778,24 +1806,48 @@ struct remote_domain_event_disk_change_msg { remote_nonnull_string devAlias; int reason; }; +struct remote_domain_event_callback_disk_change_msg { + int callbackID; + remote_domain_event_disk_change_msg msg; +}; struct remote_domain_event_tray_change_msg { remote_nonnull_domain dom; remote_nonnull_string devAlias; int reason; }; +struct remote_domain_event_callback_tray_change_msg { + int callbackID; + remote_domain_event_tray_change_msg msg; +}; struct remote_domain_event_pmwakeup_msg { remote_nonnull_domain dom; }; +struct remote_domain_event_callback_pmwakeup_msg { + int callbackID; + remote_domain_event_pmwakeup_msg msg; +}; struct remote_domain_event_pmsuspend_msg { remote_nonnull_domain dom; }; +struct remote_domain_event_callback_pmsuspend_msg { + int callbackID; + remote_domain_event_pmsuspend_msg msg; +}; struct remote_domain_event_balloon_change_msg { remote_nonnull_domain dom; uint64_t actual; }; +struct remote_domain_event_callback_balloon_change_msg { + int callbackID; + remote_domain_event_balloon_change_msg msg; +}; struct remote_domain_event_pmsuspend_disk_msg { remote_nonnull_domain dom; }; +struct remote_domain_event_callback_pmsuspend_disk_msg { + int callbackID; + remote_domain_event_pmsuspend_disk_msg msg; +}; struct remote_domain_managed_save_args { remote_nonnull_domain dom; u_int flags; @@ -2064,6 +2116,10 @@ struct remote_domain_migrate_confirm3_args { struct remote_domain_event_control_error_msg { remote_nonnull_domain dom; }; +struct remote_domain_event_callback_control_error_msg { + int callbackID; + remote_domain_event_control_error_msg msg; +}; struct remote_domain_get_control_info_args { remote_nonnull_domain dom; u_int flags; @@ -2330,6 +2386,10 @@ struct remote_domain_event_device_removed_msg { remote_nonnull_domain dom; remote_nonnull_string devAlias; }; +struct remote_domain_event_callback_device_removed_msg { + int callbackID; + remote_domain_event_device_removed_msg msg; +}; struct remote_connect_get_cpu_model_names_args { remote_nonnull_string arch; int need_results; @@ -2677,4 +2737,19 @@ enum remote_procedure { REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_REGISTER_ANY = 316, REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_DEREGISTER_ANY = 317, REMOTE_PROC_DOMAIN_EVENT_CALLBACK_LIFECYCLE = 318, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_REBOOT = 319, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_RTC_CHANGE = 320, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_WATCHDOG = 321, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_IO_ERROR = 322, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_GRAPHICS = 323, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_IO_ERROR_REASON = 324, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_CONTROL_ERROR = 325, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_BLOCK_JOB = 326, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DISK_CHANGE = 327, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_TRAY_CHANGE = 328, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_PMWAKEUP = 329, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_PMSUSPEND = 330, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_BALLOON_CHANGE = 331, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_PMSUSPEND_DISK = 332, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_REMOVED = 333, }; -- 1.8.5.3

On Wed, Jan 29, 2014 at 10:49:25AM -0700, Eric Blake wrote:
Following the patterns established by lifecycle events, this creates all the new RPC calls needed to pass callback IDs for every domain event, and changes the limits in client and server codes to use modern style when possible.
I've tested all combinations: both 'old client and new server' and 'new client and old server' continue to work with the old RPCs, and 'new client and new server' benefit from server-side filtering with the new RPCs.
* src/remote/remote_protocol.x (REMOTE_PROC_DOMAIN_EVENT_*): Add REMOTE_PROC_DOMAIN_EVENT_CALLBACK_* counterparts. * daemon/remote.c (remoteRelayDomainEvent*): Send callbackID via newer RPC when used with new-style registration. (remoteDispatchConnectDomainEventCallbackRegisterAny): Extend to cover all domain events. * src/remote/remote_driver.c (remoteDomainBuildEvent*): Add new Callback and Helper functions. (remoteEvents): Match order of RPC numbers, register new handlers. (remoteConnectDomainEventRegisterAny) (remoteConnectDomainEventDeregisterAny): Extend to cover all domain events. * src/remote_protocol-structs: Regenerate.
Signed-off-by: Eric Blake <eblake@redhat.com> --- daemon/remote.c | 240 ++++++++++++++---- src/remote/remote_driver.c | 581 ++++++++++++++++++++++++++++++++++--------- src/remote/remote_protocol.x | 155 +++++++++++- src/remote_protocol-structs | 75 ++++++ 4 files changed, 886 insertions(+), 165 deletions(-)
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Commit 57ddcc23 (v0.9.11) introduced the pmwakeup event, with an optional 'reason' field reserved for possible future expansion. But it failed to wire the field through RPC, so even if we do add a reason in the future, we will be unable to get it back to the user. Worse, commit 7ba5defb (v1.0.0) repeated the same mistake with the pmsuspend_disk event. As long as we are adding new RPC calls, we might as well fix the events to actually match the signature so that we don't have to add yet another RPC in the future if we do decide to start using the reason field. * src/remote/remote_protocol.x (remote_domain_event_callback_pmwakeup_msg) (remote_domain_event_callback_pmsuspend_msg) (remote_domain_event_callback_pmsuspend_disk_msg): Add reason field. * daemon/remote.c (remoteRelayDomainEventPMWakeup) (remoteRelayDomainEventPMSuspend) (remoteRelayDomainEventPMSuspendDisk): Pass reason to client. * src/conf/domain_event.h (virDomainEventPMWakeupNewFromDom) (virDomainEventPMSuspendNewFromDom) (virDomainEventPMSuspendDiskNewFromDom): Require additional parameter. * src/conf/domain_event.c (virDomainEventPMClass): New class. (virDomainEventPMDispose): New function. (virDomainEventPMWakeupNew*, virDomainEventPMSuspendNew*) (virDomainEventPMSuspendDiskNew*) (virDomainEventDispatchDefaultFunc): Use new class. * src/remote/remote_driver.c (remoteDomainBuildEvent*PM*): Pass reason through. * src/remote_protocol-structs: Regenerate. Signed-off-by: Eric Blake <eblake@redhat.com> --- daemon/remote.c | 12 ++--- src/conf/domain_event.c | 106 ++++++++++++++++++++++++++++++++----------- src/conf/domain_event.h | 6 +-- src/remote/remote_driver.c | 30 +++++++----- src/remote/remote_protocol.x | 3 ++ src/remote_protocol-structs | 3 ++ 6 files changed, 112 insertions(+), 48 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 48c707d..932f65f 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -714,7 +714,7 @@ remoteRelayDomainEventTrayChange(virConnectPtr conn, static int remoteRelayDomainEventPMWakeup(virConnectPtr conn, virDomainPtr dom, - int reason ATTRIBUTE_UNUSED, + int reason, void *opaque) { daemonClientEventCallbackPtr callback = opaque; @@ -737,7 +737,7 @@ remoteRelayDomainEventPMWakeup(virConnectPtr conn, (xdrproc_t)xdr_remote_domain_event_pmwakeup_msg, &data); } else { remote_domain_event_callback_pmwakeup_msg msg = { callback->callbackID, - data }; + reason, data }; remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_CALLBACK_PMWAKEUP, @@ -750,7 +750,7 @@ remoteRelayDomainEventPMWakeup(virConnectPtr conn, static int remoteRelayDomainEventPMSuspend(virConnectPtr conn, virDomainPtr dom, - int reason ATTRIBUTE_UNUSED, + int reason, void *opaque) { daemonClientEventCallbackPtr callback = opaque; @@ -773,7 +773,7 @@ remoteRelayDomainEventPMSuspend(virConnectPtr conn, (xdrproc_t)xdr_remote_domain_event_pmsuspend_msg, &data); } else { remote_domain_event_callback_pmsuspend_msg msg = { callback->callbackID, - data }; + reason, data }; remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_CALLBACK_PMSUSPEND, @@ -824,7 +824,7 @@ remoteRelayDomainEventBalloonChange(virConnectPtr conn, static int remoteRelayDomainEventPMSuspendDisk(virConnectPtr conn, virDomainPtr dom, - int reason ATTRIBUTE_UNUSED, + int reason, void *opaque) { daemonClientEventCallbackPtr callback = opaque; @@ -847,7 +847,7 @@ remoteRelayDomainEventPMSuspendDisk(virConnectPtr conn, (xdrproc_t)xdr_remote_domain_event_pmsuspend_disk_msg, &data); } else { remote_domain_event_callback_pmsuspend_disk_msg msg = { callback->callbackID, - data }; + reason, data }; remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_CALLBACK_PMSUSPEND_DISK, diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c index a490fe5..9c18922 100644 --- a/src/conf/domain_event.c +++ b/src/conf/domain_event.c @@ -47,6 +47,7 @@ static virClassPtr virDomainEventDiskChangeClass; static virClassPtr virDomainEventTrayChangeClass; static virClassPtr virDomainEventBalloonChangeClass; static virClassPtr virDomainEventDeviceRemovedClass; +static virClassPtr virDomainEventPMClass; static void virDomainEventDispose(void *obj); @@ -60,6 +61,7 @@ static void virDomainEventDiskChangeDispose(void *obj); static void virDomainEventTrayChangeDispose(void *obj); static void virDomainEventBalloonChangeDispose(void *obj); static void virDomainEventDeviceRemovedDispose(void *obj); +static void virDomainEventPMDispose(void *obj); static void virDomainEventDispatchDefaultFunc(virConnectPtr conn, @@ -171,6 +173,14 @@ struct _virDomainEventDeviceRemoved { typedef struct _virDomainEventDeviceRemoved virDomainEventDeviceRemoved; typedef virDomainEventDeviceRemoved *virDomainEventDeviceRemovedPtr; +struct _virDomainEventPM { + virDomainEvent parent; + + int reason; +}; +typedef struct _virDomainEventPM virDomainEventPM; +typedef virDomainEventPM *virDomainEventPMPtr; + static int virDomainEventsOnceInit(void) @@ -241,6 +251,12 @@ virDomainEventsOnceInit(void) sizeof(virDomainEventDeviceRemoved), virDomainEventDeviceRemovedDispose))) return -1; + if (!(virDomainEventPMClass = + virClassNew(virDomainEventClass, + "virDomainEventPM", + sizeof(virDomainEventPM), + virDomainEventPMDispose))) + return -1; return 0; } @@ -359,6 +375,13 @@ virDomainEventDeviceRemovedDispose(void *obj) VIR_FREE(event->devAlias); } +static void +virDomainEventPMDispose(void *obj) +{ + virDomainEventPMPtr event = obj; + VIR_DEBUG("obj=%p", event); +} + static void * virDomainEventNew(virClassPtr klass, @@ -907,19 +930,21 @@ virDomainEventTrayChangeNewFromDom(virDomainPtr dom, static virObjectEventPtr virDomainEventPMWakeupNew(int id, const char *name, - unsigned char *uuid) + unsigned char *uuid, + int reason) { - virObjectEventPtr ev; + virDomainEventPMPtr ev; if (virDomainEventsInitialize() < 0) return NULL; - if (!(ev = virDomainEventNew(virDomainEventClass, + if (!(ev = virDomainEventNew(virDomainEventPMClass, VIR_DOMAIN_EVENT_ID_PMWAKEUP, id, name, uuid))) return NULL; - return ev; + ev->reason = reason; + return (virObjectEventPtr)ev; } virObjectEventPtr @@ -927,31 +952,34 @@ virDomainEventPMWakeupNewFromObj(virDomainObjPtr obj) { return virDomainEventPMWakeupNew(obj->def->id, obj->def->name, - obj->def->uuid); + obj->def->uuid, + 0); } virObjectEventPtr -virDomainEventPMWakeupNewFromDom(virDomainPtr dom) +virDomainEventPMWakeupNewFromDom(virDomainPtr dom, int reason) { - return virDomainEventPMWakeupNew(dom->id, dom->name, dom->uuid); + return virDomainEventPMWakeupNew(dom->id, dom->name, dom->uuid, reason); } static virObjectEventPtr virDomainEventPMSuspendNew(int id, const char *name, - unsigned char *uuid) + unsigned char *uuid, + int reason) { - virObjectEventPtr ev; + virDomainEventPMPtr ev; if (virDomainEventsInitialize() < 0) return NULL; - if (!(ev = virDomainEventNew(virDomainEventClass, + if (!(ev = virDomainEventNew(virDomainEventPMClass, VIR_DOMAIN_EVENT_ID_PMSUSPEND, id, name, uuid))) return NULL; - return ev; + ev->reason = reason; + return (virObjectEventPtr)ev; } virObjectEventPtr @@ -959,30 +987,34 @@ virDomainEventPMSuspendNewFromObj(virDomainObjPtr obj) { return virDomainEventPMSuspendNew(obj->def->id, obj->def->name, - obj->def->uuid); + obj->def->uuid, + 0); } virObjectEventPtr -virDomainEventPMSuspendNewFromDom(virDomainPtr dom) +virDomainEventPMSuspendNewFromDom(virDomainPtr dom, int reason) { - return virDomainEventPMSuspendNew(dom->id, dom->name, dom->uuid); + return virDomainEventPMSuspendNew(dom->id, dom->name, dom->uuid, reason); } static virObjectEventPtr virDomainEventPMSuspendDiskNew(int id, const char *name, - unsigned char *uuid) + unsigned char *uuid, + int reason) { - virObjectEventPtr ev; + virDomainEventPMPtr ev; if (virDomainEventsInitialize() < 0) return NULL; - if (!(ev = virDomainEventNew(virDomainEventClass, + if (!(ev = virDomainEventNew(virDomainEventPMClass, VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK, id, name, uuid))) return NULL; - return ev; + + ev->reason = reason; + return (virObjectEventPtr)ev; } virObjectEventPtr @@ -990,13 +1022,15 @@ virDomainEventPMSuspendDiskNewFromObj(virDomainObjPtr obj) { return virDomainEventPMSuspendDiskNew(obj->def->id, obj->def->name, - obj->def->uuid); + obj->def->uuid, + 0); } virObjectEventPtr -virDomainEventPMSuspendDiskNewFromDom(virDomainPtr dom) +virDomainEventPMSuspendDiskNewFromDom(virDomainPtr dom, int reason) { - return virDomainEventPMSuspendDiskNew(dom->id, dom->name, dom->uuid); + return virDomainEventPMSuspendDiskNew(dom->id, dom->name, dom->uuid, + reason); } virObjectEventPtr @@ -1217,12 +1251,24 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn, } case VIR_DOMAIN_EVENT_ID_PMWAKEUP: - ((virConnectDomainEventPMWakeupCallback)cb)(conn, dom, 0, cbopaque); - goto cleanup; + { + virDomainEventPMPtr pmEvent = (virDomainEventPMPtr)event; + + ((virConnectDomainEventPMWakeupCallback)cb)(conn, dom, + pmEvent->reason, + cbopaque); + goto cleanup; + } case VIR_DOMAIN_EVENT_ID_PMSUSPEND: - ((virConnectDomainEventPMSuspendCallback)cb)(conn, dom, 0, cbopaque); - goto cleanup; + { + virDomainEventPMPtr pmEvent = (virDomainEventPMPtr)event; + + ((virConnectDomainEventPMSuspendCallback)cb)(conn, dom, + pmEvent->reason, + cbopaque); + goto cleanup; + } case VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE: { @@ -1236,8 +1282,14 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn, } case VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK: - ((virConnectDomainEventPMSuspendDiskCallback)cb)(conn, dom, 0, cbopaque); - goto cleanup; + { + virDomainEventPMPtr pmEvent = (virDomainEventPMPtr)event; + + ((virConnectDomainEventPMSuspendDiskCallback)cb)(conn, dom, + pmEvent->reason, + cbopaque); + goto cleanup; + } case VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED: { diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h index be577e9..300c41b 100644 --- a/src/conf/domain_event.h +++ b/src/conf/domain_event.h @@ -149,11 +149,11 @@ virDomainEventTrayChangeNewFromDom(virDomainPtr dom, virObjectEventPtr virDomainEventPMWakeupNewFromObj(virDomainObjPtr obj); virObjectEventPtr -virDomainEventPMWakeupNewFromDom(virDomainPtr dom); +virDomainEventPMWakeupNewFromDom(virDomainPtr dom, int reason); virObjectEventPtr virDomainEventPMSuspendNewFromObj(virDomainObjPtr obj); virObjectEventPtr -virDomainEventPMSuspendNewFromDom(virDomainPtr dom); +virDomainEventPMSuspendNewFromDom(virDomainPtr dom, int reason); virObjectEventPtr virDomainEventBalloonChangeNewFromDom(virDomainPtr dom, @@ -165,7 +165,7 @@ virDomainEventBalloonChangeNewFromObj(virDomainObjPtr obj, virObjectEventPtr virDomainEventPMSuspendDiskNewFromObj(virDomainObjPtr obj); virObjectEventPtr -virDomainEventPMSuspendDiskNewFromDom(virDomainPtr dom); +virDomainEventPMSuspendDiskNewFromDom(virDomainPtr dom, int reason); virObjectEventPtr virDomainEventDeviceRemovedNewFromObj(virDomainObjPtr obj, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 4cdce81..955465a 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -5189,7 +5189,8 @@ remoteDomainBuildEventCallbackTrayChange(virNetClientProgramPtr prog ATTRIBUTE_U static void remoteDomainBuildEventPMWakeupHelper(virConnectPtr conn, remote_domain_event_pmwakeup_msg *msg, - int callbackID) + int callbackID, + int reason) { struct private_data *priv = conn->privateData; virDomainPtr dom; @@ -5199,7 +5200,7 @@ remoteDomainBuildEventPMWakeupHelper(virConnectPtr conn, if (!dom) return; - event = virDomainEventPMWakeupNewFromDom(dom); + event = virDomainEventPMWakeupNewFromDom(dom, reason); virDomainFree(dom); @@ -5212,7 +5213,7 @@ remoteDomainBuildEventPMWakeup(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, { virConnectPtr conn = opaque; remote_domain_event_pmwakeup_msg *msg = evdata; - remoteDomainBuildEventPMWakeupHelper(conn, msg, -1); + remoteDomainBuildEventPMWakeupHelper(conn, msg, -1, 0); } static void remoteDomainBuildEventCallbackPMWakeup(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, @@ -5221,13 +5222,15 @@ remoteDomainBuildEventCallbackPMWakeup(virNetClientProgramPtr prog ATTRIBUTE_UNU { virConnectPtr conn = opaque; remote_domain_event_callback_pmwakeup_msg *msg = evdata; - remoteDomainBuildEventPMWakeupHelper(conn, &msg->msg, msg->callbackID); + remoteDomainBuildEventPMWakeupHelper(conn, &msg->msg, msg->callbackID, + msg->reason); } static void remoteDomainBuildEventPMSuspendHelper(virConnectPtr conn, remote_domain_event_pmsuspend_msg *msg, - int callbackID) + int callbackID, + int reason) { struct private_data *priv = conn->privateData; virDomainPtr dom; @@ -5237,7 +5240,7 @@ remoteDomainBuildEventPMSuspendHelper(virConnectPtr conn, if (!dom) return; - event = virDomainEventPMSuspendNewFromDom(dom); + event = virDomainEventPMSuspendNewFromDom(dom, reason); virDomainFree(dom); @@ -5250,7 +5253,7 @@ remoteDomainBuildEventPMSuspend(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, { virConnectPtr conn = opaque; remote_domain_event_pmsuspend_msg *msg = evdata; - remoteDomainBuildEventPMSuspendHelper(conn, msg, -1); + remoteDomainBuildEventPMSuspendHelper(conn, msg, -1, 0); } static void remoteDomainBuildEventCallbackPMSuspend(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, @@ -5259,7 +5262,8 @@ remoteDomainBuildEventCallbackPMSuspend(virNetClientProgramPtr prog ATTRIBUTE_UN { virConnectPtr conn = opaque; remote_domain_event_callback_pmsuspend_msg *msg = evdata; - remoteDomainBuildEventPMSuspendHelper(conn, &msg->msg, msg->callbackID); + remoteDomainBuildEventPMSuspendHelper(conn, &msg->msg, msg->callbackID, + msg->reason); } @@ -5304,7 +5308,8 @@ remoteDomainBuildEventCallbackBalloonChange(virNetClientProgramPtr prog ATTRIBUT static void remoteDomainBuildEventPMSuspendDiskHelper(virConnectPtr conn, remote_domain_event_pmsuspend_disk_msg *msg, - int callbackID) + int callbackID, + int reason) { struct private_data *priv = conn->privateData; virDomainPtr dom; @@ -5314,7 +5319,7 @@ remoteDomainBuildEventPMSuspendDiskHelper(virConnectPtr conn, if (!dom) return; - event = virDomainEventPMSuspendDiskNewFromDom(dom); + event = virDomainEventPMSuspendDiskNewFromDom(dom, reason); virDomainFree(dom); @@ -5327,7 +5332,7 @@ remoteDomainBuildEventPMSuspendDisk(virNetClientProgramPtr prog ATTRIBUTE_UNUSED { virConnectPtr conn = opaque; remote_domain_event_pmsuspend_disk_msg *msg = evdata; - remoteDomainBuildEventPMSuspendDiskHelper(conn, msg, -1); + remoteDomainBuildEventPMSuspendDiskHelper(conn, msg, -1, 0); } static void remoteDomainBuildEventCallbackPMSuspendDisk(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, @@ -5336,7 +5341,8 @@ remoteDomainBuildEventCallbackPMSuspendDisk(virNetClientProgramPtr prog ATTRIBUT { virConnectPtr conn = opaque; remote_domain_event_callback_pmsuspend_disk_msg *msg = evdata; - remoteDomainBuildEventPMSuspendDiskHelper(conn, &msg->msg, msg->callbackID); + remoteDomainBuildEventPMSuspendDiskHelper(conn, &msg->msg, msg->callbackID, + msg->reason); } diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 8238405..9dc8253 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -2378,6 +2378,7 @@ struct remote_domain_event_pmwakeup_msg { }; struct remote_domain_event_callback_pmwakeup_msg { int callbackID; + int reason; remote_domain_event_pmwakeup_msg msg; }; @@ -2386,6 +2387,7 @@ struct remote_domain_event_pmsuspend_msg { }; struct remote_domain_event_callback_pmsuspend_msg { int callbackID; + int reason; remote_domain_event_pmsuspend_msg msg; }; @@ -2403,6 +2405,7 @@ struct remote_domain_event_pmsuspend_disk_msg { }; struct remote_domain_event_callback_pmsuspend_disk_msg { int callbackID; + int reason; remote_domain_event_pmsuspend_disk_msg msg; }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index fdff787..5636d55 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -1824,6 +1824,7 @@ struct remote_domain_event_pmwakeup_msg { }; struct remote_domain_event_callback_pmwakeup_msg { int callbackID; + int reason; remote_domain_event_pmwakeup_msg msg; }; struct remote_domain_event_pmsuspend_msg { @@ -1831,6 +1832,7 @@ struct remote_domain_event_pmsuspend_msg { }; struct remote_domain_event_callback_pmsuspend_msg { int callbackID; + int reason; remote_domain_event_pmsuspend_msg msg; }; struct remote_domain_event_balloon_change_msg { @@ -1846,6 +1848,7 @@ struct remote_domain_event_pmsuspend_disk_msg { }; struct remote_domain_event_callback_pmsuspend_disk_msg { int callbackID; + int reason; remote_domain_event_pmsuspend_disk_msg msg; }; struct remote_domain_managed_save_args { -- 1.8.5.3

On Wed, Jan 29, 2014 at 10:49:26AM -0700, Eric Blake wrote:
Commit 57ddcc23 (v0.9.11) introduced the pmwakeup event, with an optional 'reason' field reserved for possible future expansion. But it failed to wire the field through RPC, so even if we do add a reason in the future, we will be unable to get it back to the user.
Worse, commit 7ba5defb (v1.0.0) repeated the same mistake with the pmsuspend_disk event.
Urgh I've caught cases of new events not doing that before and fixed it, guess i missed this one.
As long as we are adding new RPC calls, we might as well fix the events to actually match the signature so that we don't have to add yet another RPC in the future if we do decide to start using the reason field.
* src/remote/remote_protocol.x (remote_domain_event_callback_pmwakeup_msg) (remote_domain_event_callback_pmsuspend_msg) (remote_domain_event_callback_pmsuspend_disk_msg): Add reason field. * daemon/remote.c (remoteRelayDomainEventPMWakeup) (remoteRelayDomainEventPMSuspend) (remoteRelayDomainEventPMSuspendDisk): Pass reason to client. * src/conf/domain_event.h (virDomainEventPMWakeupNewFromDom) (virDomainEventPMSuspendNewFromDom) (virDomainEventPMSuspendDiskNewFromDom): Require additional parameter. * src/conf/domain_event.c (virDomainEventPMClass): New class. (virDomainEventPMDispose): New function. (virDomainEventPMWakeupNew*, virDomainEventPMSuspendNew*) (virDomainEventPMSuspendDiskNew*) (virDomainEventDispatchDefaultFunc): Use new class. * src/remote/remote_driver.c (remoteDomainBuildEvent*PM*): Pass reason through. * src/remote_protocol-structs: Regenerate.
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
participants (2)
-
Daniel P. Berrange
-
Eric Blake