diff --git a/daemon/remote.c b/daemon/remote.c index ae318b24e5..d2aafbe055 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -685,6 +685,7 @@ remoteRelayNetworkEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED, /* build return data */ memset(&data, 0, sizeof(data)); make_nonnull_network(&data.net, net); + data.callbackID = callback->callbackID; data.event = event; data.detail = detail; @@ -5285,7 +5286,7 @@ remoteDispatchConnectNetworkEventRegisterAny(virNetServerPtr server ATTRIBUTE_UN virNetMessagePtr msg ATTRIBUTE_UNUSED, virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED, remote_connect_network_event_register_any_args *args, - remote_connect_network_event_register_any_ret *ret ATTRIBUTE_UNUSED) + remote_connect_network_event_register_any_ret *ret) { int callbackID; int rv = -1; @@ -5293,6 +5294,7 @@ remoteDispatchConnectNetworkEventRegisterAny(virNetServerPtr server ATTRIBUTE_UN daemonClientEventCallbackPtr ref; struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client); + virNetworkPtr net = NULL; if (!priv->conn) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); @@ -5301,6 +5303,10 @@ remoteDispatchConnectNetworkEventRegisterAny(virNetServerPtr server ATTRIBUTE_UN virMutexLock(&priv->lock); + if (args->net && + !(net = get_nonnull_network(priv->conn, *args->net))) + goto cleanup; + if (args->eventID >= VIR_NETWORK_EVENT_ID_LAST || args->eventID < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported network event ID %d"), args->eventID); @@ -5325,7 +5331,7 @@ remoteDispatchConnectNetworkEventRegisterAny(virNetServerPtr server ATTRIBUTE_UN goto cleanup; if ((callbackID = virConnectNetworkEventRegisterAny(priv->conn, - NULL, + net, args->eventID, networkEventCallbacks[args->eventID], ref, @@ -5337,6 +5343,7 @@ remoteDispatchConnectNetworkEventRegisterAny(virNetServerPtr server ATTRIBUTE_UN } ref->callbackID = callbackID; + ret->callbackID = callbackID; rv = 0; @@ -5344,6 +5351,8 @@ cleanup: VIR_FREE(callback); if (rv < 0) virNetMessageSaveError(rerr); + if (net) + virNetworkFree(net); virMutexUnlock(&priv->lock); return rv; } @@ -5354,10 +5363,8 @@ remoteDispatchConnectNetworkEventDeregisterAny(virNetServerPtr server ATTRIBUTE_ virNetServerClientPtr client, virNetMessagePtr msg ATTRIBUTE_UNUSED, virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED, - remote_connect_network_event_deregister_any_args *args, - remote_connect_network_event_deregister_any_ret *ret ATTRIBUTE_UNUSED) + remote_connect_network_event_deregister_any_args *args) { - int callbackID = -1; int rv = -1; size_t i; struct daemonClientPrivate *priv = @@ -5370,25 +5377,18 @@ remoteDispatchConnectNetworkEventDeregisterAny(virNetServerPtr server ATTRIBUTE_ virMutexLock(&priv->lock); - if (args->eventID >= VIR_NETWORK_EVENT_ID_LAST || args->eventID < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unsupported event ID %d"), args->eventID); - goto cleanup; - } - for (i = 0; i < priv->nnetworkEventCallbacks; i++) { - if (priv->networkEventCallbacks[i]->eventID == args->eventID) { - callbackID = priv->networkEventCallbacks[i]->callbackID; + if (priv->networkEventCallbacks[i]->callbackID == args->callbackID) break; - } } - if (callbackID < 0) { + if (i == priv->nnetworkEventCallbacks) { virReportError(VIR_ERR_INTERNAL_ERROR, - _("network event %d not registered"), args->eventID); + _("network event callback %d not registered"), + args->callbackID); goto cleanup; } - if (virConnectNetworkEventDeregisterAny(priv->conn, callbackID) < 0) + if (virConnectNetworkEventDeregisterAny(priv->conn, args->callbackID) < 0) goto cleanup; VIR_DELETE_ELEMENT(priv->networkEventCallbacks, i, diff --git a/src/conf/network_event.c b/src/conf/network_event.c index d9c47b8a22..a0b60a0de0 100644 --- a/src/conf/network_event.c +++ b/src/conf/network_event.c @@ -189,12 +189,10 @@ virNetworkEventStateRegisterClient(virConnectPtr conn, if (virNetworkEventsInitialize() < 0) return -1; - /* FIXME: All servers that support network events should also support - * per-object filtering. */ return virObjectEventStateRegisterID(conn, state, net ? net->uuid : NULL, virNetworkEventClass, eventID, VIR_OBJECT_EVENT_CALLBACK(cb), - opaque, freecb, callbackID, false); + opaque, freecb, callbackID, true); } diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index d719a493fc..18eb454f58 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -2923,8 +2923,10 @@ remoteConnectNetworkEventRegisterAny(virConnectPtr conn, int rv = -1; struct private_data *priv = conn->privateData; remote_connect_network_event_register_any_args args; + remote_connect_network_event_register_any_ret ret; int callbackID; int count; + remote_nonnull_network network; remoteDriverLock(priv); @@ -2938,14 +2940,23 @@ remoteConnectNetworkEventRegisterAny(virConnectPtr conn, * events on the server */ if (count == 1) { args.eventID = eventID; + if (net) { + make_nonnull_network(&network, net); + args.net = &network; + } else { + args.net = NULL; + } + memset(&ret, 0, sizeof(ret)); if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NETWORK_EVENT_REGISTER_ANY, (xdrproc_t) xdr_remote_connect_network_event_register_any_args, (char *) &args, - (xdrproc_t) xdr_void, (char *)NULL) == -1) { + (xdrproc_t) xdr_remote_connect_network_event_register_any_ret, (char *) &ret) == -1) { virObjectEventStateDeregisterID(conn, priv->eventState, callbackID); goto done; } + virObjectEventStateSetRemote(conn, priv->eventState, callbackID, + ret.callbackID); } rv = callbackID; @@ -2980,7 +2991,7 @@ remoteConnectNetworkEventDeregisterAny(virConnectPtr conn, /* If that was the last callback for this eventID, we need to disable * events on the server */ if (count == 0) { - args.eventID = eventID; + args.callbackID = remoteID; if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NETWORK_EVENT_DEREGISTER_ANY, (xdrproc_t) xdr_remote_connect_network_event_deregister_any_args, (char *) &args, @@ -4924,7 +4935,7 @@ remoteNetworkBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, msg->detail); virNetworkFree(net); - remoteEventQueue(priv, event, -1); + remoteEventQueue(priv, event, msg->callbackID); } diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index c3d544fe22..ae27a7721f 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3,7 +3,7 @@ * remote_internal driver and libvirtd. This protocol is * internal and may change at any time. * - * 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 @@ -2851,21 +2851,19 @@ struct remote_connect_get_cpu_model_names_ret { struct remote_connect_network_event_register_any_args { int eventID; + remote_network net; }; struct remote_connect_network_event_register_any_ret { - int cb_registered; + int callbackID; }; struct remote_connect_network_event_deregister_any_args { - int eventID; -}; - -struct remote_connect_network_event_deregister_any_ret { - int cb_registered; + int callbackID; }; struct remote_network_event_lifecycle_msg { + int callbackID; remote_nonnull_network net; int event; int detail; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 7373d6573c..e58482e7f4 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2330,17 +2330,16 @@ struct remote_connect_get_cpu_model_names_ret { }; struct remote_connect_network_event_register_any_args { int eventID; + remote_network net; }; struct remote_connect_network_event_register_any_ret { - int cb_registered; + int callbackID; }; struct remote_connect_network_event_deregister_any_args { - int eventID; -}; -struct remote_connect_network_event_deregister_any_ret { - int cb_registered; + int callbackID; }; struct remote_network_event_lifecycle_msg { + int callbackID; remote_nonnull_network net; int event; int detail;