virMutex lock;
int domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LAST];
+ int networkEventCallbackID[VIR_NETWORK_EVENT_ID_LAST];
# if WITH_SASL
virNetSASLSessionPtr sasl;
#include "qemu_protocol.h"
#include "lxc_protocol.h"
#include "virstring.h"
+#include "object_event.h"
#define VIR_FROM_THIS VIR_FROM_RPC
verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
+static int remoteRelayNetworkEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virNetworkPtr net,
+ int event,
+ int detail,
+ void *opaque)
+{
+ virNetServerClientPtr client = opaque;
+ remote_network_event_lifecycle_msg data;
+
+ if (!client)
+ return -1;
+
+ VIR_DEBUG("Relaying network lifecycle event %d, detail %d", event, detail);
+
+ /* build return data */
+ memset(&data, 0, sizeof(data));
+ make_nonnull_network(&data.net, net);
+ data.event = event;
+ data.detail = detail;
+
+ remoteDispatchObjectEventSend(client, remoteProgram,
+ REMOTE_PROC_NETWORK_EVENT_LIFECYCLE,
+ (xdrproc_t)xdr_remote_network_event_lifecycle_msg, &data);
+
+ return 0;
+}
+
+static virConnectNetworkEventGenericCallback networkEventCallbacks[] = {
+ VIR_NETWORK_EVENT_CALLBACK(remoteRelayNetworkEventLifecycle),
+};
+
+verify(ARRAY_CARDINALITY(networkEventCallbacks) == VIR_NETWORK_EVENT_ID_LAST);
+
/*
* You must hold lock for at least the client
* We don't free stuff here, merely disconnect the client's
priv->domainEventCallbackID[i] = -1;
}
+ for (i = 0; i < VIR_NETWORK_EVENT_ID_LAST; i++) {
+ if (priv->networkEventCallbackID[i] != -1) {
+ VIR_DEBUG("Deregistering to relay remote events %zu", i);
+ virConnectNetworkEventDeregisterAny(priv->conn,
+ priv->networkEventCallbackID[i]);
+ }
+ priv->networkEventCallbackID[i] = -1;
+ }
+
virConnectClose(priv->conn);
virIdentitySetCurrent(NULL);
for (i = 0; i < VIR_DOMAIN_EVENT_ID_LAST; i++)
priv->domainEventCallbackID[i] = -1;
+ for (i = 0; i < VIR_NETWORK_EVENT_ID_LAST; i++)
+ priv->networkEventCallbackID[i] = -1;
+
virNetServerClientSetCloseHook(client, remoteClientCloseFunc);
return priv;
}
}
+static int
+remoteDispatchConnectNetworkEventRegisterAny(virNetServerPtr server ATTRIBUTE_UNUSED,
+ virNetServerClientPtr client ATTRIBUTE_UNUSED,
+ 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)
+{
+ int callbackID;
+ int rv = -1;
+ struct daemonClientPrivate *priv =
+ virNetServerClientGetPrivateData(client);
+
+ if (!priv->conn) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+ goto cleanup;
+ }
+
+ virMutexLock(&priv->lock);
+
+ if (args->eventID >= VIR_NETWORK_EVENT_ID_LAST) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported network event ID %d"), args->eventID);
+ goto cleanup;
+ }
+
+ if (priv->networkEventCallbackID[args->eventID] != -1) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("network event %d already registered"), args->eventID);
+ goto cleanup;
+ }
+
+ if ((callbackID = virConnectNetworkEventRegisterAny(priv->conn,
+ NULL,
+ args->eventID,
+ networkEventCallbacks[args->eventID],
+ client, NULL)) < 0)
+ goto cleanup;
+
+ priv->networkEventCallbackID[args->eventID] = callbackID;
+
+ rv = 0;
+
+cleanup:
+ if (rv < 0)
+ virNetMessageSaveError(rerr);
+ virMutexUnlock(&priv->lock);
+ return rv;
+}
+
+
+static int
+remoteDispatchConnectNetworkEventDeregisterAny(virNetServerPtr server ATTRIBUTE_UNUSED,
+ virNetServerClientPtr client ATTRIBUTE_UNUSED,
+ 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)
+{
+ int callbackID = -1;
+ int rv = -1;
+ struct daemonClientPrivate *priv =
+ virNetServerClientGetPrivateData(client);
+
+ if (!priv->conn) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+ goto cleanup;
+ }
+
+ virMutexLock(&priv->lock);
+
+ if (args->eventID >= VIR_NETWORK_EVENT_ID_LAST) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported event ID %d"), args->eventID);
+ goto cleanup;
+ }
+
+ callbackID = priv->networkEventCallbackID[args->eventID];
+ if (callbackID < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("network event %d not registered"), args->eventID);
+ goto cleanup;
+ }
+
+ if (virConnectNetworkEventDeregisterAny(priv->conn, callbackID) < 0)
+ goto cleanup;
+
+ priv->networkEventCallbackID[args->eventID] = -1;
+
+ rv = 0;
+
+cleanup:
+ if (rv < 0)
+ virNetMessageSaveError(rerr);
+ virMutexUnlock(&priv->lock);
+ return rv;
+}
+
/*----- Helpers. -----*/
#include "virlog.h"
#include "datatypes.h"
#include "domain_event.h"
+#include "network_event.h"
#include "driver.h"
#include "virbuffer.h"
#include "remote_driver.h"
virNetClientPtr client,
void *evdata, void *opaque);
+static void
+remoteNetworkBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
+ virNetClientPtr client ATTRIBUTE_UNUSED,
+ void *evdata, void *opaque);
+
static virNetClientProgramEvent remoteDomainEvents[] = {
{ REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE,
remoteDomainBuildEventRTCChange,
remoteDomainBuildEventDeviceRemoved,
sizeof(remote_domain_event_device_removed_msg),
(xdrproc_t)xdr_remote_domain_event_device_removed_msg },
+ { REMOTE_PROC_NETWORK_EVENT_LIFECYCLE,
+ remoteNetworkBuildEventLifecycle,
+ sizeof(remote_network_event_lifecycle_msg),
+ (xdrproc_t)xdr_remote_network_event_lifecycle_msg },
};
enum virDrvOpenRemoteFlags {
return rv;
}
+static int
+remoteConnectNetworkEventRegisterAny(virConnectPtr conn,
+ virNetworkPtr net,
+ int eventID,
+ virConnectNetworkEventGenericCallback callback,
+ void *opaque,
+ virFreeCallback freecb)
+{
+ int rv = -1;
+ struct private_data *priv = conn->privateData;
+ remote_connect_network_event_register_any_args args;
+ int callbackID;
+ int count;
+
+ remoteDriverLock(priv);
+
+ if ((count = virNetworkEventStateRegisterID(conn,
+ priv->domainEventState,
+ net, eventID,
+ VIR_OBJECT_EVENT_CALLBACK(callback),
+ opaque, freecb,
+ &callbackID)) < 0) {
+ virReportError(VIR_ERR_RPC, "%s", _("adding cb to list"));
+ 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 (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) {
+ virObjectEventStateDeregisterID(conn,
+ priv->domainEventState,
+ callbackID);
+ goto done;
+ }
+ }
+
+ rv = callbackID;
+
+done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
+
+
+static int
+remoteConnectNetworkEventDeregisterAny(virConnectPtr conn,
+ int callbackID)
+{
+ struct private_data *priv = conn->privateData;
+ int rv = -1;
+ remote_connect_network_event_deregister_any_args args;
+ int eventID;
+ int count;
+
+ remoteDriverLock(priv);
+
+ if ((eventID = virObjectEventStateEventID(conn,
+ priv->domainEventState,
+ callbackID)) < 0) {
+ virReportError(VIR_ERR_RPC, _("unable to find callback ID %d"), callbackID);
+ goto done;
+ }
+
+ if ((count = virObjectEventStateDeregisterID(conn,
+ priv->domainEventState,
+ callbackID)) < 0) {
+ virReportError(VIR_ERR_RPC, _("unable to find callback ID %d"), callbackID);
+ goto done;
+ }
+
+ /* If that was the last callback for this eventID, we need to disable
+ * events on the server */
+ if (count == 0) {
+ args.eventID = eventID;
+
+ if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NETWORK_EVENT_DEREGISTER_ANY,
+ (xdrproc_t) xdr_remote_connect_network_event_deregister_any_args, (char *) &args,
+ (xdrproc_t) xdr_void, (char *) NULL) == -1)
+ goto done;
+ }
+
+ rv = 0;
+
+done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
+
static int
remoteConnectListAllInterfaces(virConnectPtr conn,
virInterfacePtr **ifaces,
}
+static void
+remoteNetworkBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
+ virNetClientPtr client ATTRIBUTE_UNUSED,
+ void *evdata, void *opaque)
+{
+ virConnectPtr conn = opaque;
+ struct private_data *priv = conn->privateData;
+ remote_network_event_lifecycle_msg *msg = evdata;
+ virNetworkPtr net;
+ virObjectEventPtr event = NULL;
+
+ net = get_nonnull_network(conn, msg->net);
+ if (!net)
+ return;
+
+ event = virNetworkEventLifecycleNew(net->name, net->uuid, msg->event);
+ virNetworkFree(net);
+
+ remoteDomainEventQueue(priv, event);
+}
+
+
static virDrvOpenStatus ATTRIBUTE_NONNULL(1)
remoteSecretOpen(virConnectPtr conn, virConnectAuthPtr auth,
unsigned int flags)
.connectNumOfDefinedNetworks = remoteConnectNumOfDefinedNetworks, /* 0.3.0 */
.connectListDefinedNetworks = remoteConnectListDefinedNetworks, /* 0.3.0 */
.connectListAllNetworks = remoteConnectListAllNetworks, /* 0.10.2 */
+ .connectNetworkEventDeregisterAny = remoteConnectNetworkEventDeregisterAny, /* 1.2.1 */
+ .connectNetworkEventRegisterAny = remoteConnectNetworkEventRegisterAny, /* 1.2.1 */
.networkLookupByUUID = remoteNetworkLookupByUUID, /* 0.3.0 */
.networkLookupByName = remoteNetworkLookupByName, /* 0.3.0 */
.networkCreateXML = remoteNetworkCreateXML, /* 0.3.0 */
int ret;
};
+struct remote_connect_network_event_register_any_args {
+ int eventID;
+};
+
+struct remote_connect_network_event_register_any_ret {
+ int cb_registered;
+};
+
+struct remote_connect_network_event_deregister_any_args {
+ int eventID;
+};
+
+struct remote_connect_network_event_deregister_any_ret {
+ int cb_registered;
+};
+
+struct remote_network_event_lifecycle_msg {
+ remote_nonnull_network net;
+ int event;
+ int detail;
+};
+
+
+
/*----- Protocol. -----*/
/* Define the program number, protocol version and procedure numbers here. */
* @generate: none
* @acl: connect:read
*/
- REMOTE_PROC_CONNECT_GET_CPU_MODEL_NAMES = 312
+ REMOTE_PROC_CONNECT_GET_CPU_MODEL_NAMES = 312,
+
+ /**
+ * @generate: none
+ * @priority: high
+ * @acl: connect:read
+ */
+ REMOTE_PROC_CONNECT_NETWORK_EVENT_REGISTER_ANY = 313,
+
+ /**
+ * @generate: none
+ * @priority: high
+ * @acl: connect:read
+ */
+ REMOTE_PROC_CONNECT_NETWORK_EVENT_DEREGISTER_ANY = 314,
+
+ /**
+ * @generate: both
+ * @acl: none
+ */
+ REMOTE_PROC_NETWORK_EVENT_LIFECYCLE = 315
};
} models;
int ret;
};
+struct remote_connect_network_event_register_any_args {
+ int eventID;
+};
+struct remote_connect_network_event_register_any_ret {
+ int cb_registered;
+};
+struct remote_connect_network_event_deregister_any_args {
+ int eventID;
+};
+struct remote_connect_network_event_deregister_any_ret {
+ int cb_registered;
+};
+struct remote_network_event_lifecycle_msg {
+ remote_nonnull_network net;
+ int event;
+ int detail;
+};
enum remote_procedure {
REMOTE_PROC_CONNECT_OPEN = 1,
REMOTE_PROC_CONNECT_CLOSE = 2,
REMOTE_PROC_DOMAIN_CREATE_WITH_FILES = 310,
REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED = 311,
REMOTE_PROC_CONNECT_GET_CPU_MODEL_NAMES = 312,
+ REMOTE_PROC_CONNECT_NETWORK_EVENT_REGISTER_ANY = 313,
+ REMOTE_PROC_CONNECT_NETWORK_EVENT_DEREGISTER_ANY = 314,
+ REMOTE_PROC_NETWORK_EVENT_LIFECYCLE = 315,
};