Put all network-events related code in src/conf/network_event.[ch]
---
include/libvirt/libvirt.h.in | 80 ++++++++++++++++++++++
src/Makefile.am | 5 ++
src/conf/network_event.c | 154 +++++++++++++++++++++++++++++++++++++++++++
src/conf/network_event.h | 51 ++++++++++++++
src/conf/object_event.c | 9 +++
src/conf/object_event.h | 1 +
src/driver.h | 14 ++++
src/libvirt.c | 125 +++++++++++++++++++++++++++++++++++
src/libvirt_private.syms | 2 +
src/libvirt_public.syms | 7 ++
10 files changed, 448 insertions(+)
create mode 100644 src/conf/network_event.c
create mode 100644 src/conf/network_event.h
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 29d4dce..73a77c0 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -4974,6 +4974,86 @@ int virConnectDomainEventRegisterAny(virConnectPtr conn,
int virConnectDomainEventDeregisterAny(virConnectPtr conn,
int callbackID);
+/**
+ * virNetworkEventLifecycleType:
+ *
+ * a virNetworkEventLifecycleType is emitted during network lifecycle events
+ */
+typedef enum {
+ VIR_NETWORK_EVENT_DEFINED = 0,
+ VIR_NETWORK_EVENT_UNDEFINED = 1,
+ VIR_NETWORK_EVENT_STARTED = 2,
+ VIR_NETWORK_EVENT_STOPPED = 3,
+
+#ifdef VIR_ENUM_SENTINELS
+ VIR_NETWORK_EVENT_LAST
+#endif
+} virNetworkEventLifecycleType;
+
+/**
+ * virConnectNetworkEventLifecycleCallback:
+ * @conn: connection object
+ * @net: network on which the event occurred
+ * @event: The specific virNetworkEventLifeCycleType which occurred
+ * @detail: contains some details on the reason of the event.
+ * It will be 0 for the while.
+ * @opaque: application specified data
+ *
+ * This callback occurs when the network is started or stopped.
+ *
+ * The callback signature to use when registering for an event of type
+ * VIR_NETWORK_EVENT_ID_LIFECYCLE with virConnectNetworkEventRegisterAny()
+ */
+typedef void (*virConnectNetworkEventLifecycleCallback)(virConnectPtr conn,
+ virNetworkPtr net,
+ int event,
+ int detail,
+ void *opaque);
+
+/**
+ * VIR_NETWORK_EVENT_CALLBACK:
+ *
+ * Used to cast the event specific callback into the generic one
+ * for use for virNetworkEventRegister
+ */
+#define VIR_NETWORK_EVENT_CALLBACK(cb) ((virConnectNetworkEventGenericCallback)(cb))
+
+typedef enum {
+ VIR_NETWORK_EVENT_ID_LIFECYCLE = 0, /* virConnectNetworkEventLifecycleCallback
*/
+
+#ifdef VIR_ENUM_SENTINELS
+ VIR_NETWORK_EVENT_ID_LAST
+ /*
+ * NB: this enum value will increase over time as new events are
+ * added to the libvirt API. It reflects the last event ID supported
+ * by this version of the libvirt API.
+ */
+#endif
+} virNetworkEventID;
+
+/*
+ * virConnectNetworkEventGenericCallback:
+ * @conn: the connection pointer
+ * @net: the network pointer
+ * @opaque: application specified data
+ *
+ * A generic network event callback handler. Specific events usually
+ * have a customization with extra parameters
+ */
+typedef void (*virConnectNetworkEventGenericCallback)(virConnectPtr conn,
+ virNetworkPtr net,
+ void *opaque);
+
+/* Use VIR_NETWORK_EVENT_CALLBACK() to cast the 'cb' parameter */
+int virConnectNetworkEventRegisterAny(virConnectPtr conn,
+ virNetworkPtr net, /* Optional, to filter */
+ int eventID,
+ virConnectNetworkEventGenericCallback cb,
+ void *opaque,
+ virFreeCallback freecb);
+
+int virConnectNetworkEventDeregisterAny(virConnectPtr conn,
+ int callbackID);
/**
* virNWFilter:
diff --git a/src/Makefile.am b/src/Makefile.am
index a3ea55c..57e163f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -248,6 +248,9 @@ OBJECT_EVENT_SOURCES = \
DOMAIN_EVENT_SOURCES = \
conf/domain_event.c conf/domain_event.h
+NETWORK_EVENT_SOURCES = \
+ conf/network_event.c conf/network_event.h
+
# Network driver generic impl APIs
NETWORK_CONF_SOURCES = \
conf/network_conf.c conf/network_conf.h
@@ -298,6 +301,7 @@ CONF_SOURCES = \
$(DOMAIN_CONF_SOURCES) \
$(OBJECT_EVENT_SOURCES) \
$(DOMAIN_EVENT_SOURCES) \
+ $(NETWORK_EVENT_SOURCES) \
$(NETWORK_CONF_SOURCES) \
$(NWFILTER_CONF_SOURCES) \
$(NODE_DEVICE_CONF_SOURCES) \
@@ -2026,6 +2030,7 @@ libvirt_setuid_rpc_client_la_SOURCES = \
util/virutil.c \
util/viruuid.c \
conf/domain_event.c \
+ conf/network_event.c \
conf/object_event.c \
rpc/virnetsocket.c \
rpc/virnetsocket.h \
diff --git a/src/conf/network_event.c b/src/conf/network_event.c
new file mode 100644
index 0000000..74e9d3d
--- /dev/null
+++ b/src/conf/network_event.c
@@ -0,0 +1,154 @@
+/*
+ * network_event.c: network event queue processing helpers
+ *
+ * Copyright (C) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <
http://www.gnu.org/licenses/>.
+ *
+ * Author: Cedric Bosdonnat
+ */
+
+#include <config.h>
+
+#include "network_event.h"
+#include "object_event.h"
+#include "object_event_private.h"
+#include "datatypes.h"
+#include "virlog.h"
+
+struct _virNetworkEventLifecycle {
+ virObjectEvent parent;
+
+ int type;
+};
+typedef struct _virNetworkEventLifecycle virNetworkEventLifecycle;
+typedef virNetworkEventLifecycle *virNetworkEventLifecyclePtr;
+
+static virClassPtr virNetworkEventLifecycleClass;
+static void virNetworkEventLifecycleDispose(void *obj);
+
+static int
+virNetworkEventsOnceInit(void)
+{
+ if (!(virNetworkEventLifecycleClass =
+ virClassNew(virClassForObjectEvent(),
+ "virNetworkEventLifecycle",
+ sizeof(virNetworkEventLifecycle),
+ virNetworkEventLifecycleDispose)))
+ return -1;
+ return 0;
+}
+
+VIR_ONCE_GLOBAL_INIT(virNetworkEvents)
+
+void
+virNetworkEventLifecycleDispose(void *obj)
+{
+ virNetworkEventLifecyclePtr event = obj;
+ VIR_DEBUG("obj=%p", event);
+}
+
+
+void
+virNetworkEventDispatchDefaultFunc(virConnectPtr conn,
+ virObjectEventPtr event,
+ virConnectNetworkEventGenericCallback cb
ATTRIBUTE_UNUSED,
+ void *cbopaque ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
+{
+ virNetworkPtr net = virGetNetwork(conn, event->meta.name, event->meta.uuid);
+ if (!net)
+ return;
+
+ switch ((virNetworkEventID) (event->eventID &0xFF)) {
+ case VIR_NETWORK_EVENT_ID_LIFECYCLE:
+ {
+ virNetworkEventLifecyclePtr networkLifecycleEvent;
+
+ networkLifecycleEvent = (virNetworkEventLifecyclePtr)event;
+ ((virConnectNetworkEventLifecycleCallback)cb)(conn, net,
+
networkLifecycleEvent->type,
+ 0,
+ cbopaque);
+ goto cleanup;
+ }
+
+ case VIR_NETWORK_EVENT_ID_LAST:
+ break;
+ }
+ VIR_WARN("Unexpected event ID %d", event->eventID);
+
+cleanup:
+ virNetworkFree(net);
+}
+
+
+/**
+ * virNetworkEventStateRegisterID:
+ * @conn: connection to associate with callback
+ * @state: object event state
+ * @net: network to filter on or NULL for all networks
+ * @eventID: ID of the event type to register for
+ * @cb: function to add to event
+ * @opaque: data blob to pass to callback
+ * @freecb: callback to free @opaque
+ * @callbackID: filled with callback ID
+ *
+ * Register the function @callbackID with connection @conn,
+ * from @state, for events of type @eventID.
+ *
+ * Returns: the number of callbacks now registered, or -1 on error
+ */
+int
+virNetworkEventStateRegisterID(virConnectPtr conn,
+ virObjectEventStatePtr state,
+ virNetworkPtr net,
+ int eventID,
+ virConnectObjectEventGenericCallback cb,
+ void *opaque,
+ virFreeCallback freecb,
+ int *callbackID)
+{
+ int nsEventID = (VIR_EVENT_NAMESPACE_NETWORK << 8) + eventID;
+ if (net)
+ return virObjectEventStateRegisterID(conn, state,
+ net->uuid, net->name, 0, nsEventID,
+ cb, opaque, freecb, callbackID);
+ else
+ return virObjectEventStateRegisterID(conn, state,
+ NULL, NULL, 0, nsEventID,
+ cb, opaque, freecb, callbackID);
+}
+
+void
+*virNetworkEventLifecycleNew(const char *name,
+ const unsigned char *uuid,
+ int type)
+{
+ virNetworkEventLifecyclePtr event;
+ int eventId = (VIR_EVENT_NAMESPACE_NETWORK << 8) +
VIR_NETWORK_EVENT_ID_LIFECYCLE;
+
+ if (virNetworkEventsInitialize() < 0)
+ return NULL;
+
+ if (!(event = virObjectEventNew(virNetworkEventLifecycleClass,
+ eventId,
+ 0, name, uuid)))
+ return NULL;
+
+ event->type = type;
+
+ return event;
+}
diff --git a/src/conf/network_event.h b/src/conf/network_event.h
new file mode 100644
index 0000000..385d618
--- /dev/null
+++ b/src/conf/network_event.h
@@ -0,0 +1,51 @@
+/*
+ * network_event.h: network event queue processing helpers
+ *
+ * Copyright (C) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <
http://www.gnu.org/licenses/>.
+ *
+ * Author: Cedric Bosdonnat
+ */
+
+#include "internal.h"
+#include "object_event.h"
+#include "object_event_private.h"
+
+#ifndef __NETWORK_EVENT_H__
+# define __NETWORK_EVENT_H__
+
+int
+virNetworkEventStateRegisterID(virConnectPtr conn,
+ virObjectEventStatePtr state,
+ virNetworkPtr net,
+ int eventID,
+ virConnectObjectEventGenericCallback cb,
+ void *opaque,
+ virFreeCallback freecb,
+ int *callbackID);
+
+void
+*virNetworkEventLifecycleNew(const char *name,
+ const unsigned char *uuid,
+ int type);
+
+void
+virNetworkEventDispatchDefaultFunc(virConnectPtr conn,
+ virObjectEventPtr event,
+ virConnectNetworkEventGenericCallback cb,
+ void *cbopaque,
+ void *opaque);
+#endif
diff --git a/src/conf/object_event.c b/src/conf/object_event.c
index fc4d9bb..065a3b0 100644
--- a/src/conf/object_event.c
+++ b/src/conf/object_event.c
@@ -25,6 +25,7 @@
#include <config.h>
#include "domain_event.h"
+#include "network_event.h"
#include "object_event.h"
#include "object_event_private.h"
#include "virlog.h"
@@ -42,6 +43,7 @@ struct _virObjectEventQueue {
static virClassPtr virObjectEventClass;
+static virClassPtr virObjectEventClass;
static void virObjectEventDispose(void *obj);
static int virObjectEventOnceInit(void)
@@ -635,6 +637,10 @@ virObjectEventStateDispatchFunc(virConnectPtr conn,
virDomainEventDispatchDefaultFunc(conn, event,
VIR_DOMAIN_EVENT_CALLBACK(cb), cbopaque, NULL);
break;
+ case VIR_EVENT_NAMESPACE_NETWORK:
+ virNetworkEventDispatchDefaultFunc(conn, event,
+ VIR_NETWORK_EVENT_CALLBACK(cb), cbopaque, NULL);
+ break;
}
virObjectEventStateLock(state);
}
@@ -787,6 +793,9 @@ virObjectEventStateEventID(virConnectPtr conn,
virObjectEventStateLock(state);
ret = virObjectEventCallbackListEventID(conn,
state->callbacks, callbackID);
+ /* Callers don't need to know we are namespacing the event Ids */
+ if (ret >= 0)
+ ret = (0xFF & ret);
virObjectEventStateUnlock(state);
return ret;
}
diff --git a/src/conf/object_event.h b/src/conf/object_event.h
index edd3e87..50cfe19 100644
--- a/src/conf/object_event.h
+++ b/src/conf/object_event.h
@@ -32,6 +32,7 @@
*/
typedef enum {
VIR_EVENT_NAMESPACE_DOMAIN = 0, /* 0 to keep value of virDomainEventId unchanged */
+ VIR_EVENT_NAMESPACE_NETWORK = 1,
} virEventNamespaceID;
typedef struct _virObjectEventCallback virObjectEventCallback;
diff --git a/src/driver.h b/src/driver.h
index 8cd164a..3c7b536 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -1366,6 +1366,18 @@ typedef int
virNetworkPtr **nets,
unsigned int flags);
+typedef int
+(*virDrvConnectNetworkEventRegisterAny)(virConnectPtr conn,
+ virNetworkPtr dom,
+ int eventID,
+ virConnectNetworkEventGenericCallback cb,
+ void *opaque,
+ virFreeCallback freecb);
+
+typedef int
+(*virDrvConnectNetworkEventDeregisterAny)(virConnectPtr conn,
+ int callbackID);
+
typedef virNetworkPtr
(*virDrvNetworkLookupByUUID)(virConnectPtr conn,
const unsigned char *uuid);
@@ -1444,6 +1456,8 @@ struct _virNetworkDriver {
virDrvConnectNumOfDefinedNetworks connectNumOfDefinedNetworks;
virDrvConnectListDefinedNetworks connectListDefinedNetworks;
virDrvConnectListAllNetworks connectListAllNetworks;
+ virDrvConnectNetworkEventRegisterAny connectNetworkEventRegisterAny;
+ virDrvConnectNetworkEventDeregisterAny connectNetworkEventDeregisterAny;
virDrvNetworkLookupByUUID networkLookupByUUID;
virDrvNetworkLookupByName networkLookupByName;
virDrvNetworkCreateXML networkCreateXML;
diff --git a/src/libvirt.c b/src/libvirt.c
index b3543d0..97175b2 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -19177,6 +19177,131 @@ error:
}
/**
+ * virConnectNetworkEventRegisterAny:
+ * @conn: pointer to the connection
+ * @net: pointer to the network
+ * @eventID: the event type to receive
+ * @cb: callback to the function handling network events
+ * @opaque: opaque data to pass on to the callback
+ * @freecb: optional function to deallocate opaque when not used anymore
+ *
+ * Adds a callback to receive notifications of arbitrary network events
+ * occurring on a network.
+ *
+ * If net is NULL, then events will be monitored for any network. If net
+ * is non-NULL, then only the specific network will be monitored
+ *
+ * Most types of event have a callback providing a custom set of parameters
+ * for the event. When registering an event, it is thus necessary to use
+ * the VIR_NETWORK_EVENT_CALLBACK() macro to cast the supplied function pointer
+ * to match the signature of this method.
+ *
+ * The virNetworkPtr object handle passed into the callback upon delivery
+ * of an event is only valid for the duration of execution of the callback.
+ * If the callback wishes to keep the network object after the callback
+ * returns, it shall take a reference to it, by calling virNetworkRef.
+ * The reference can be released once the object is no longer required
+ * by calling virNetworkFree.
+ *
+ * The return value from this method is a positive integer identifier
+ * for the callback. To unregister a callback, this callback ID should
+ * be passed to the virNetworkEventUnregisterAny method
+ *
+ * Returns a callback identifier on success, -1 on failure
+ */
+int
+virConnectNetworkEventRegisterAny(virConnectPtr conn,
+ virNetworkPtr net,
+ int eventID,
+ virConnectNetworkEventGenericCallback cb,
+ void *opaque,
+ virFreeCallback freecb)
+{
+ VIR_DEBUG("conn=%p, eventID=%d, cb=%p, opaque=%p, freecb=%p",
+ conn, eventID, cb, opaque, freecb);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECT(conn)) {
+ virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+ if (net != NULL &&
+ !(VIR_IS_CONNECTED_NETWORK(net) && net->conn == conn)) {
+ virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
+ virDispatchError(conn);
+ return -1;
+ }
+ virCheckNonNullArgGoto(cb, error);
+ virCheckNonNegativeArgGoto(eventID, error);
+
+ if (eventID >= VIR_NETWORK_EVENT_ID_LAST) {
+ virReportInvalidArg(eventID,
+ _("eventID in %s must be less than %d"),
+ __FUNCTION__, VIR_NETWORK_EVENT_ID_LAST);
+ goto error;
+ }
+
+ if ((conn->networkDriver) &&
(conn->networkDriver->connectNetworkEventRegisterAny)) {
+ int ret;
+ ret = conn->networkDriver->connectNetworkEventRegisterAny(conn, net,
+ eventID,
+ cb, opaque,
+ freecb);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+ virDispatchError(conn);
+ return -1;
+}
+
+/**
+ * virConnectNetworkEventDeregisterAny:
+ * @conn: pointer to the connection
+ * @callbackID: the callback identifier
+ *
+ * Removes an event callback. The callbackID parameter should be the
+ * vaule obtained from a previous virNetworkEventRegisterAny method.
+ *
+ * Returns 0 on success, -1 on failure
+ */
+int
+virConnectNetworkEventDeregisterAny(virConnectPtr conn,
+ int callbackID)
+{
+ VIR_DEBUG("conn=%p, callbackID=%d", conn, callbackID);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECT(conn)) {
+ virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+ virCheckNonNegativeArgGoto(callbackID, error);
+
+ if ((conn->networkDriver) &&
+ (conn->networkDriver->connectNetworkEventDeregisterAny)) {
+ int ret;
+ ret = conn->networkDriver->connectNetworkEventDeregisterAny(conn,
+ callbackID);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+ virDispatchError(conn);
+ return -1;
+}
+
+/**
* virDomainManagedSave:
* @dom: pointer to the domain
* @flags: bitwise-OR of virDomainSaveRestoreFlags
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 3ca20e4..0e749b1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -624,6 +624,8 @@ virNWFilterVarValueGetSimple;
# conf/object_event.h
+virNetworkEventLifecycleNew;
+virNetworkEventStateRegisterID;
virObjectEventStateDeregisterID;
virObjectEventStateEventID;
virObjectEventStateFree;
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index fe9b497..6ed6ce6 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -639,4 +639,11 @@ LIBVIRT_1.1.3 {
virConnectGetCPUModelNames;
} LIBVIRT_1.1.1;
+LIBVIRT_1.2.1 {
+ global:
+ virConnectNetworkEventRegisterAny;
+ virConnectNetworkEventDeregisterAny;
+} LIBVIRT_1.1.3;
+
+
# .... define new API here using predicted next version number ....
--
1.8.4.4