[libvirt] [PATCH 0/5] server-side filtering of domain events

This work was originally done with the thought that the fix for CVE-2014-0028 would require server-side filtering to make the check of connect:search_domains conditional on whether the user passed NULL or a domain when registering for an event. The final version of the CVE fix no longer needs the conditional behavior, so there is no longer a rush to get this in to 1.2.1; but for 1.2.2, the code changes offer a nice efficiency gain for the use case of libvirtd managing lots of domains while a client only cares about events from a small subset of domains. While this will not be in 1.2.1 proper, I also tested that the entire series can be backported without breaking the .so versioning, if any downstream distro wants to include the efficiency gain as part of their value added maintenance of an older version. Eric Blake (5): 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 daemon/libvirtd.h | 3 +- daemon/remote.c | 801 +++++++++++++++++++++++++++++----------- src/conf/domain_event.c | 78 +++- src/conf/domain_event.h | 22 ++ src/conf/network_event.c | 6 +- src/conf/object_event.c | 31 +- src/conf/object_event_private.h | 6 +- src/libvirt_internal.h | 7 +- src/remote/remote_driver.c | 784 ++++++++++++++++++++++++++++++++------- src/remote/remote_protocol.x | 192 +++++++++- src/remote_protocol-structs | 92 +++++ 11 files changed, 1649 insertions(+), 373 deletions(-) -- 1.8.4.2

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 | 436 +++++++++++++++++++++++++++++++++--------------------- 2 files changed, 266 insertions(+), 173 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 d2aafbe..f0b9922 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -127,19 +127,21 @@ remoteEventCallbackFree(void *opaque) VIR_FREE(opaque); } -static int remoteRelayDomainEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - int event, - int detail, - void *opaque) +static int +remoteRelayDomainEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + int event, + int detail, + void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_lifecycle_msg data; - if (!client) + if (callback->callbackID < 0) 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)); @@ -147,30 +149,32 @@ static int remoteRelayDomainEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED, 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); return 0; } -static int remoteRelayDomainEventReboot(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - void *opaque) +static int +remoteRelayDomainEventReboot(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_reboot_msg data; - if (!client) + if (callback->callbackID < 0) 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); @@ -178,25 +182,27 @@ static int remoteRelayDomainEventReboot(virConnectPtr conn ATTRIBUTE_UNUSED, } -static int remoteRelayDomainEventRTCChange(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - long long offset, - void *opaque) +static int +remoteRelayDomainEventRTCChange(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + long long offset, + void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_rtc_change_msg data; - if (!client) + if (callback->callbackID < 0) 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); @@ -204,25 +210,27 @@ static int remoteRelayDomainEventRTCChange(virConnectPtr conn ATTRIBUTE_UNUSED, } -static int remoteRelayDomainEventWatchdog(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - int action, - void *opaque) +static int +remoteRelayDomainEventWatchdog(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + int action, + void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_watchdog_msg data; - if (!client) + if (callback->callbackID < 0) 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); @@ -230,20 +238,23 @@ static int remoteRelayDomainEventWatchdog(virConnectPtr conn ATTRIBUTE_UNUSED, } -static int remoteRelayDomainEventIOError(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - const char *srcPath, - const char *devAlias, - int action, - void *opaque) +static int +remoteRelayDomainEventIOError(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + const char *srcPath, + const char *devAlias, + int action, + void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_io_error_msg data; - if (!client) + if (callback->callbackID < 0) 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)); @@ -253,7 +264,7 @@ static int remoteRelayDomainEventIOError(virConnectPtr conn ATTRIBUTE_UNUSED, 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); @@ -265,22 +276,24 @@ error: } -static int remoteRelayDomainEventIOErrorReason(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - const char *srcPath, - const char *devAlias, - int action, - const char *reason, - void *opaque) +static int +remoteRelayDomainEventIOErrorReason(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + const char *srcPath, + const char *devAlias, + int action, + const char *reason, + void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_io_error_reason_msg data; - if (!client) + if (callback->callbackID < 0) 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)); @@ -292,7 +305,7 @@ static int remoteRelayDomainEventIOErrorReason(virConnectPtr conn ATTRIBUTE_UNUS 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); @@ -306,26 +319,28 @@ error: } -static int remoteRelayDomainEventGraphics(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - int phase, - virDomainEventGraphicsAddressPtr local, - virDomainEventGraphicsAddressPtr remote, - const char *authScheme, - virDomainEventGraphicsSubjectPtr subject, - void *opaque) +static int +remoteRelayDomainEventGraphics(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + int phase, + virDomainEventGraphicsAddressPtr local, + virDomainEventGraphicsAddressPtr remote, + const char *authScheme, + virDomainEventGraphicsSubjectPtr subject, + void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_graphics_msg data; size_t i; - if (!client) + if (callback->callbackID < 0) 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++) { @@ -355,7 +370,7 @@ static int remoteRelayDomainEventGraphics(virConnectPtr conn ATTRIBUTE_UNUSED, } 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); @@ -377,21 +392,22 @@ error: return -1; } -static int remoteRelayDomainEventBlockJob(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - const char *path, - int type, - int status, - void *opaque) +static int +remoteRelayDomainEventBlockJob(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + const char *path, + int type, + int status, + void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_block_job_msg data; - if (!client) + if (callback->callbackID < 0) 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)); @@ -401,7 +417,7 @@ static int remoteRelayDomainEventBlockJob(virConnectPtr conn ATTRIBUTE_UNUSED, 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); @@ -412,23 +428,25 @@ error: } -static int remoteRelayDomainEventControlError(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - void *opaque) +static int +remoteRelayDomainEventControlError(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_control_error_msg data; - if (!client) + if (callback->callbackID < 0) 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); @@ -436,23 +454,25 @@ static int remoteRelayDomainEventControlError(virConnectPtr conn ATTRIBUTE_UNUSE } -static int remoteRelayDomainEventDiskChange(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - const char *oldSrcPath, - const char *newSrcPath, - const char *devAlias, - int reason, - void *opaque) +static int +remoteRelayDomainEventDiskChange(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + const char *oldSrcPath, + const char *newSrcPath, + const char *devAlias, + 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) + if (callback->callbackID < 0) 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)); @@ -474,7 +494,7 @@ static int remoteRelayDomainEventDiskChange(virConnectPtr conn ATTRIBUTE_UNUSED, 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); @@ -487,19 +507,21 @@ error: } -static int remoteRelayDomainEventTrayChange(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - const char *devAlias, - int reason, - void *opaque) { - virNetServerClientPtr client = opaque; +static int +remoteRelayDomainEventTrayChange(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + const char *devAlias, + int reason, + void *opaque) +{ + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_tray_change_msg data; - if (!client) + if (callback->callbackID < 0) 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)); @@ -510,53 +532,59 @@ static int remoteRelayDomainEventTrayChange(virConnectPtr conn ATTRIBUTE_UNUSED, 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); return 0; } -static int remoteRelayDomainEventPMWakeup(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - int reason ATTRIBUTE_UNUSED, - void *opaque) { - virNetServerClientPtr client = opaque; +static int +remoteRelayDomainEventPMWakeup(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + int reason ATTRIBUTE_UNUSED, + void *opaque) +{ + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_pmwakeup_msg data; - if (!client) + if (callback->callbackID < 0) 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); return 0; } -static int remoteRelayDomainEventPMSuspend(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - int reason ATTRIBUTE_UNUSED, - void *opaque) { - virNetServerClientPtr client = opaque; +static int +remoteRelayDomainEventPMSuspend(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + int reason ATTRIBUTE_UNUSED, + void *opaque) +{ + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_pmsuspend_msg data; - if (!client) + if (callback->callbackID < 0) 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); @@ -569,20 +597,21 @@ remoteRelayDomainEventBalloonChange(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long long actual, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_balloon_change_msg data; - if (!client) + if (callback->callbackID < 0) 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); @@ -590,23 +619,26 @@ remoteRelayDomainEventBalloonChange(virConnectPtr conn ATTRIBUTE_UNUSED, } -static int remoteRelayDomainEventPMSuspendDisk(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - int reason ATTRIBUTE_UNUSED, - void *opaque) { - virNetServerClientPtr client = opaque; +static int +remoteRelayDomainEventPMSuspendDisk(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + int reason ATTRIBUTE_UNUSED, + void *opaque) +{ + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_pmsuspend_disk_msg data; - if (!client) + if (callback->callbackID < 0) 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); @@ -619,14 +651,14 @@ remoteRelayDomainEventDeviceRemoved(virConnectPtr conn ATTRIBUTE_UNUSED, const char *devAlias, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_device_removed_msg data; - if (!client) + if (callback->callbackID < 0) 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)); @@ -636,7 +668,7 @@ remoteRelayDomainEventDeviceRemoved(virConnectPtr conn ATTRIBUTE_UNUSED, 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); @@ -720,14 +752,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; @@ -766,7 +803,6 @@ void *remoteClientInitHook(virNetServerClientPtr client, void *opaque ATTRIBUTE_UNUSED) { struct daemonClientPrivate *priv; - size_t i; if (VIR_ALLOC(priv) < 0) return NULL; @@ -777,9 +813,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; } @@ -3143,13 +3176,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); @@ -3160,23 +3195,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); @@ -3185,12 +3238,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); @@ -3201,16 +3256,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; @@ -3332,13 +3396,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); @@ -3355,23 +3421,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); @@ -3381,13 +3465,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); @@ -3404,16 +3489,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.4.2

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 f0b9922..05fb708 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -76,6 +76,7 @@ struct daemonClientEventCallback { virNetServerClientPtr client; int eventID; int callbackID; + bool legacy; }; static virDomainPtr get_nonnull_domain(virConnectPtr conn, remote_nonnull_domain domain); @@ -140,8 +141,8 @@ remoteRelayDomainEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED, if (callback->callbackID < 0) 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)); @@ -149,9 +150,20 @@ remoteRelayDomainEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED, 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; } @@ -3206,6 +3218,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, @@ -3394,6 +3407,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, @@ -3415,9 +3434,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; } @@ -3432,6 +3455,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, @@ -3464,6 +3488,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, @@ -3483,9 +3586,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; } @@ -3516,6 +3623,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, @@ -3836,6 +3990,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 f94a38a..96838ba 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; }; @@ -5063,5 +5080,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.4.2

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. * 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 | 31 ++++++++-------- src/conf/object_event_private.h | 6 ++-- src/remote/remote_driver.c | 36 +++++++++++++++---- 6 files changed, 152 insertions(+), 27 deletions(-) diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c index f56aed3..29fc525 100644 --- a/src/conf/domain_event.c +++ b/src/conf/domain_event.c @@ -1307,6 +1307,8 @@ virDomainEventStateRegister(virConnectPtr conn, void *opaque, virFreeCallback freecb) { + int callbackID; + if (virDomainEventsInitialize() < 0) return -1; @@ -1315,7 +1317,8 @@ virDomainEventStateRegister(virConnectPtr conn, filter, virDomainEventClass, VIR_DOMAIN_EVENT_ID_LIFECYCLE, VIR_OBJECT_EVENT_CALLBACK(callback), - opaque, freecb, NULL, false); + opaque, freecb, + true, &callbackID, false); } @@ -1355,7 +1358,75 @@ virDomainEventStateRegisterID(virConnectPtr conn, filter ? virDomainEventFilter : NULL, filter, 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); } @@ -1380,7 +1451,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 b39d5cd..011bb04 100644 --- a/src/conf/domain_event.h +++ b/src/conf/domain_event.h @@ -196,6 +196,28 @@ virDomainEventStateRegisterID(virConnectPtr conn, ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(6); 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 f27b7e9..d919ec2 100644 --- a/src/conf/network_event.c +++ b/src/conf/network_event.c @@ -182,7 +182,8 @@ virNetworkEventStateRegisterID(virConnectPtr conn, filter ? virNetworkEventFilter : NULL, filter, virNetworkEventClass, eventID, VIR_OBJECT_EVENT_CALLBACK(cb), - opaque, freecb, callbackID, false); + opaque, freecb, + false, callbackID, false); } @@ -221,7 +222,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..c5770bf 100644 --- a/src/conf/object_event.c +++ b/src/conf/object_event.c @@ -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 ca86e3c..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, NULL, - 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, NULL, - 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.4.2

On 01/15/2014 04:23 PM, 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. * 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.
Based on my additional testing, I need to squash this in for global domain lifecycle events (lookup of a remoteID should match the same conditions as virObjectEventCallbackListCount, which ignores legacy). Thankfully, no impact to 1.2.1 (network events are never marked legacy). diff --git i/src/conf/object_event.c w/src/conf/object_event.c index c5770bf..de45257 100644 --- i/src/conf/object_event.c +++ w/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; } } -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

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.4.2

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 05fb708..2d5c9d1 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -179,16 +179,25 @@ remoteRelayDomainEventReboot(virConnectPtr conn ATTRIBUTE_UNUSED, if (callback->callbackID < 0) 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; } @@ -206,17 +215,27 @@ remoteRelayDomainEventRTCChange(virConnectPtr conn ATTRIBUTE_UNUSED, if (callback->callbackID < 0) 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; } @@ -242,9 +261,18 @@ remoteRelayDomainEventWatchdog(virConnectPtr conn ATTRIBUTE_UNUSED, 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; } @@ -276,9 +304,18 @@ remoteRelayDomainEventIOError(virConnectPtr conn ATTRIBUTE_UNUSED, 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: @@ -317,9 +354,18 @@ remoteRelayDomainEventIOErrorReason(virConnectPtr conn ATTRIBUTE_UNUSED, 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; @@ -382,9 +428,18 @@ remoteRelayDomainEventGraphics(virConnectPtr conn ATTRIBUTE_UNUSED, } 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; @@ -429,9 +484,18 @@ remoteRelayDomainEventBlockJob(virConnectPtr conn ATTRIBUTE_UNUSED, 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: @@ -458,9 +522,18 @@ remoteRelayDomainEventControlError(virConnectPtr conn ATTRIBUTE_UNUSED, 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; } @@ -506,9 +579,18 @@ remoteRelayDomainEventDiskChange(virConnectPtr conn ATTRIBUTE_UNUSED, 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; @@ -544,9 +626,18 @@ remoteRelayDomainEventTrayChange(virConnectPtr conn ATTRIBUTE_UNUSED, 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; } @@ -570,9 +661,18 @@ remoteRelayDomainEventPMWakeup(virConnectPtr conn ATTRIBUTE_UNUSED, 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; } @@ -596,9 +696,18 @@ remoteRelayDomainEventPMSuspend(virConnectPtr conn ATTRIBUTE_UNUSED, 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; } @@ -623,9 +732,18 @@ remoteRelayDomainEventBalloonChange(virConnectPtr conn ATTRIBUTE_UNUSED, 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; } @@ -650,9 +768,18 @@ remoteRelayDomainEventPMSuspendDisk(virConnectPtr conn ATTRIBUTE_UNUSED, 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; } @@ -680,10 +807,20 @@ remoteRelayDomainEventDeviceRemoved(virConnectPtr conn ATTRIBUTE_UNUSED, 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; } @@ -3514,8 +3651,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 96838ba..5a82395 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; @@ -5100,5 +5163,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.4.2
participants (1)
-
Eric Blake