[PATCH 0/8] network: Add callback for metadata changes

This patchset adds support to trigger an event upon changes in the content of `<title>`, `<description>` or `<metadata>` in the network. K Shiva Kiran (8): Define Network Metadata change callback function Define Network event struct for Metadata change Add Event ID, Server side dispatcher and virsh print function Add methods to create Metadata change events Implement RPC Client for Network Metadata change callbacks Test driver implementation for Network metadata change callbacks Add Bridge Driver implementation for Network metadata change callbacks examples: Add Testing for metadata change callbacks examples/c/misc/event-test.c | 85 ++++++++++++++++++++++++++--- include/libvirt/libvirt-network.h | 22 ++++++++ src/conf/network_event.c | 84 ++++++++++++++++++++++++++++ src/conf/network_event.h | 11 ++++ src/libvirt_private.syms | 2 + src/network/bridge_driver.c | 6 ++ src/remote/remote_daemon_dispatch.c | 38 +++++++++++++ src/remote/remote_driver.c | 31 +++++++++++ src/remote/remote_protocol.x | 15 ++++- src/remote_protocol-structs | 6 ++ src/test/test_driver.c | 7 +++ tools/virsh-network.c | 46 +++++++++++++++- 12 files changed, 342 insertions(+), 11 deletions(-) -- 2.42.0

Signed-off-by: K Shiva Kiran <shiva_kr@riseup.net> --- include/libvirt/libvirt-network.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/include/libvirt/libvirt-network.h b/include/libvirt/libvirt-network.h index 0f7ad8300f..4b121ae0e7 100644 --- a/include/libvirt/libvirt-network.h +++ b/include/libvirt/libvirt-network.h @@ -576,4 +576,25 @@ virNetworkGetMetadata(virNetworkPtr network, const char *uri, unsigned int flags); +/** + * virConnectNetworkEventMetadataChangeCallback: + * @conn: connection object + * @net: network on which the event occurred + * @type: a value from virNetworkMetadataType + * @nsuri: XML namespace URI + * @opaque: application specified data + * + * This callback is triggered when the Network XML metadata changes + * + * The callback signature to use when registering for an event of type + * VIR_NETWORK_EVENT_ID_METADATA_CHANGE with virConnectNetworkEventRegisterAny(). + * + * Since: 9.8.0 + */ +typedef void (*virConnectNetworkEventMetadataChangeCallback)(virConnectPtr conn, + virNetworkPtr net, + int type, + const char *nsuri, + void *opaque); + #endif /* LIBVIRT_NETWORK_H */ -- 2.42.0

Adds: - New struct virNetworkEventMetadataChange. - virNetworkEvent*Dispose() function for the same. Signed-off-by: K Shiva Kiran <shiva_kr@riseup.net> --- src/conf/network_event.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/conf/network_event.c b/src/conf/network_event.c index 6f25e43711..51fa092ffd 100644 --- a/src/conf/network_event.c +++ b/src/conf/network_event.c @@ -45,10 +45,21 @@ struct _virNetworkEventLifecycle { }; typedef struct _virNetworkEventLifecycle virNetworkEventLifecycle; +struct _virNetworkEventMetadataChange { + virNetworkEvent parent; + + int type; + char *nsuri; +}; +typedef struct _virNetworkEventMetadataChange virNetworkEventMetadataChange; + static virClass *virNetworkEventClass; static virClass *virNetworkEventLifecycleClass; +static virClass *virNetworkEventMetadataChangeClass; + static void virNetworkEventDispose(void *obj); static void virNetworkEventLifecycleDispose(void *obj); +static void virNetworkEventMetadataChangeDispose(void *obj); static int virNetworkEventsOnceInit(void) @@ -59,6 +70,9 @@ virNetworkEventsOnceInit(void) if (!VIR_CLASS_NEW(virNetworkEventLifecycle, virNetworkEventClass)) return -1; + if (!VIR_CLASS_NEW(virNetworkEventMetadataChange, virNetworkEventClass)) + return -1; + return 0; } @@ -231,3 +245,13 @@ virNetworkEventLifecycleNew(const char *name, return (virObjectEvent *)event; } + + +static void +virNetworkEventMetadataChangeDispose(void *obj) +{ + virNetworkEventMetadataChange *event = obj; + VIR_DEBUG("obj=%p", event); + + g_free(event->nsuri); +} -- 2.42.0

Adds the following for Network Metadata change callback events: - New Event ID VIR_NETWORK_EVENT_ID_METADATA_CHANGE - Server side dispatcher virsh: - New event type `metadata-change` - vshEventMetadataChangePrint() to display the above defined event type in virsh via `net-event` Signed-off-by: K Shiva Kiran <shiva_kr@riseup.net> --- I was unable to split this patch due to static assertions (perfomed against VIR_NETWORK_EVENT_ID_LAST) in remote_daemon_dispatch.c and virsh-network.c Please let me know if there is a way to split patches in such cases. include/libvirt/libvirt-network.h | 1 + src/conf/network_event.c | 12 ++++++++ src/remote/remote_daemon_dispatch.c | 38 ++++++++++++++++++++++++ src/remote/remote_protocol.x | 15 +++++++++- src/remote_protocol-structs | 6 ++++ tools/virsh-network.c | 46 ++++++++++++++++++++++++++++- 6 files changed, 116 insertions(+), 2 deletions(-) diff --git a/include/libvirt/libvirt-network.h b/include/libvirt/libvirt-network.h index 4b121ae0e7..58591be7ac 100644 --- a/include/libvirt/libvirt-network.h +++ b/include/libvirt/libvirt-network.h @@ -330,6 +330,7 @@ typedef void (*virConnectNetworkEventLifecycleCallback)(virConnectPtr conn, */ typedef enum { VIR_NETWORK_EVENT_ID_LIFECYCLE = 0, /* virConnectNetworkEventLifecycleCallback (Since: 1.2.1) */ + VIR_NETWORK_EVENT_ID_METADATA_CHANGE = 1, /* virConnectNetworkEventMetadataChangeCallback (Since: 9.8.0) */ # ifdef VIR_ENUM_SENTINELS VIR_NETWORK_EVENT_ID_LAST diff --git a/src/conf/network_event.c b/src/conf/network_event.c index 51fa092ffd..d1b3aa5721 100644 --- a/src/conf/network_event.c +++ b/src/conf/network_event.c @@ -118,6 +118,18 @@ virNetworkEventDispatchDefaultFunc(virConnectPtr conn, return; } + case VIR_NETWORK_EVENT_ID_METADATA_CHANGE: + { + virNetworkEventMetadataChange *metadataChangeEvent; + + metadataChangeEvent = (virNetworkEventMetadataChange *)event; + ((virConnectNetworkEventMetadataChangeCallback)cb)(conn, net, + metadataChangeEvent->type, + metadataChangeEvent->nsuri, + cbopaque); + return; + } + case VIR_NETWORK_EVENT_ID_LAST: break; } diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c index 2bb9e306a4..7daf503b51 100644 --- a/src/remote/remote_daemon_dispatch.c +++ b/src/remote/remote_daemon_dispatch.c @@ -1385,8 +1385,46 @@ remoteRelayNetworkEventLifecycle(virConnectPtr conn, return 0; } +static int +remoteRelayNetworkEventMetadataChange(virConnectPtr conn, + virNetworkPtr net, + int type, + const char *nsuri, + void *opaque) +{ + daemonClientEventCallback *callback = opaque; + remote_network_event_callback_metadata_change_msg data; + + if (callback->callbackID < 0 || + !remoteRelayNetworkEventCheckACL(callback->client, conn, net)) + return -1; + + VIR_DEBUG("Relaying network metadata change %s %d %s, callback %d", + net->name, type, NULLSTR(nsuri), callback->callbackID); + + /* build return data */ + memset(&data, 0, sizeof(data)); + + data.type = type; + if (nsuri) { + data.nsuri = g_new0(remote_nonnull_string, 1); + *(data.nsuri) = g_strdup(nsuri); + } + + make_nonnull_network(&data.net, net); + data.callbackID = callback->callbackID; + + remoteDispatchObjectEventSend(callback->client, callback->program, + REMOTE_PROC_NETWORK_EVENT_CALLBACK_METADATA_CHANGE, + (xdrproc_t)xdr_remote_network_event_callback_metadata_change_msg, + &data); + return 0; +} + + static virConnectNetworkEventGenericCallback networkEventCallbacks[] = { VIR_NETWORK_EVENT_CALLBACK(remoteRelayNetworkEventLifecycle), + VIR_NETWORK_EVENT_CALLBACK(remoteRelayNetworkEventMetadataChange), }; G_STATIC_ASSERT(G_N_ELEMENTS(networkEventCallbacks) == VIR_NETWORK_EVENT_ID_LAST); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 7ff059e393..e295b0acc3 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3323,6 +3323,13 @@ struct remote_network_event_lifecycle_msg { int detail; }; +struct remote_network_event_callback_metadata_change_msg { + int callbackID; + remote_nonnull_network net; + int type; + remote_string nsuri; +}; + struct remote_network_set_metadata_args { remote_nonnull_network network; int type; @@ -7008,5 +7015,11 @@ enum remote_procedure { * @generate: both * @acl: network:read */ - REMOTE_PROC_NETWORK_GET_METADATA = 445 + REMOTE_PROC_NETWORK_GET_METADATA = 445, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_NETWORK_EVENT_CALLBACK_METADATA_CHANGE = 446 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index c07e0af1e6..e6132bee71 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2687,6 +2687,12 @@ struct remote_network_event_lifecycle_msg { int event; int detail; }; +struct remote_network_event_callback_metadata_change_msg { + int callbackID; + remote_nonnull_network net; + int type; + remote_string nsuri; +}; struct remote_network_set_metadata_args { remote_nonnull_network network; int type; diff --git a/tools/virsh-network.c b/tools/virsh-network.c index de5d60593a..8965d87c9c 100644 --- a/tools/virsh-network.c +++ b/tools/virsh-network.c @@ -1582,7 +1582,8 @@ typedef struct virshNetEventData virshNetEventData; VIR_ENUM_DECL(virshNetworkEventId); VIR_ENUM_IMPL(virshNetworkEventId, VIR_NETWORK_EVENT_ID_LAST, - "lifecycle"); + "lifecycle", + "metadata-change"); static void vshEventLifecyclePrint(virConnectPtr conn G_GNUC_UNUSED, @@ -1615,9 +1616,52 @@ vshEventLifecyclePrint(virConnectPtr conn G_GNUC_UNUSED, vshEventDone(data->ctl); } +VIR_ENUM_DECL(virshNetworkEventMetadataChangeType); +VIR_ENUM_IMPL(virshNetworkEventMetadataChangeType, + VIR_NETWORK_METADATA_LAST, + N_("description"), + N_("title"), + N_("element")); + +#define UNKNOWNSTR(str) (str ? str : N_("unsupported value")) + +static void +vshEventMetadataChangePrint(virConnectPtr conn G_GNUC_UNUSED, + virNetworkPtr net, + int type, + const char *nsuri, + void *opaque) +{ + virshNetEventData *data = opaque; + + if (!data->loop && data->count) + return; + + if (data->timestamp) { + char timestamp[VIR_TIME_STRING_BUFLEN]; + + if (virTimeStringNowRaw(timestamp) < 0) + timestamp[0] = '\0'; + + vshPrint(data->ctl, _("%1$s: event 'metadata-change' for network %2$s: type %3$s, uri %4$s\n"), + timestamp, virNetworkGetName(net), + UNKNOWNSTR(virshNetworkEventMetadataChangeTypeTypeToString(type)), NULLSTR(nsuri)); + } else { + vshPrint(data->ctl, _("event 'metadata-change' for network %1$s: type %2$s, uri %3$s\n"), + virNetworkGetName(net), + UNKNOWNSTR(virshNetworkEventMetadataChangeTypeTypeToString(type)), NULLSTR(nsuri)); + } + + data->count++; + if (!data->loop) + vshEventDone(data->ctl); +} + virshNetworkEventCallback virshNetworkEventCallbacks[] = { { "lifecycle", VIR_NETWORK_EVENT_CALLBACK(vshEventLifecyclePrint), }, + { "metadata-change", + VIR_NETWORK_EVENT_CALLBACK(vshEventMetadataChangePrint), }, }; G_STATIC_ASSERT(VIR_NETWORK_EVENT_ID_LAST == G_N_ELEMENTS(virshNetworkEventCallbacks)); -- 2.42.0

On 9/3/23 16:58, K Shiva Kiran wrote:
Adds the following for Network Metadata change callback events:
- New Event ID VIR_NETWORK_EVENT_ID_METADATA_CHANGE - Server side dispatcher
virsh: - New event type `metadata-change` - vshEventMetadataChangePrint() to display the above defined event type in virsh via `net-event`
Signed-off-by: K Shiva Kiran <shiva_kr@riseup.net> --- I was unable to split this patch due to static assertions (perfomed against VIR_NETWORK_EVENT_ID_LAST) in remote_daemon_dispatch.c and virsh-network.c Please let me know if there is a way to split patches in such cases.
include/libvirt/libvirt-network.h | 1 + src/conf/network_event.c | 12 ++++++++ src/remote/remote_daemon_dispatch.c | 38 ++++++++++++++++++++++++ src/remote/remote_protocol.x | 15 +++++++++- src/remote_protocol-structs | 6 ++++ tools/virsh-network.c | 46 ++++++++++++++++++++++++++++- 6 files changed, 116 insertions(+), 2 deletions(-)
diff --git a/include/libvirt/libvirt-network.h b/include/libvirt/libvirt-network.h index 4b121ae0e7..58591be7ac 100644 --- a/include/libvirt/libvirt-network.h +++ b/include/libvirt/libvirt-network.h @@ -330,6 +330,7 @@ typedef void (*virConnectNetworkEventLifecycleCallback)(virConnectPtr conn, */ typedef enum { VIR_NETWORK_EVENT_ID_LIFECYCLE = 0, /* virConnectNetworkEventLifecycleCallback (Since: 1.2.1) */ + VIR_NETWORK_EVENT_ID_METADATA_CHANGE = 1, /* virConnectNetworkEventMetadataChangeCallback (Since: 9.8.0) */
# ifdef VIR_ENUM_SENTINELS VIR_NETWORK_EVENT_ID_LAST diff --git a/src/conf/network_event.c b/src/conf/network_event.c index 51fa092ffd..d1b3aa5721 100644 --- a/src/conf/network_event.c +++ b/src/conf/network_event.c @@ -118,6 +118,18 @@ virNetworkEventDispatchDefaultFunc(virConnectPtr conn, return; }
+ case VIR_NETWORK_EVENT_ID_METADATA_CHANGE: + { + virNetworkEventMetadataChange *metadataChangeEvent; + + metadataChangeEvent = (virNetworkEventMetadataChange *)event; + ((virConnectNetworkEventMetadataChangeCallback)cb)(conn, net, + metadataChangeEvent->type, + metadataChangeEvent->nsuri, + cbopaque); + return; + } + case VIR_NETWORK_EVENT_ID_LAST: break; } diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c index 2bb9e306a4..7daf503b51 100644 --- a/src/remote/remote_daemon_dispatch.c +++ b/src/remote/remote_daemon_dispatch.c @@ -1385,8 +1385,46 @@ remoteRelayNetworkEventLifecycle(virConnectPtr conn, return 0; }
+static int +remoteRelayNetworkEventMetadataChange(virConnectPtr conn, + virNetworkPtr net, + int type, + const char *nsuri, + void *opaque) +{ + daemonClientEventCallback *callback = opaque; + remote_network_event_callback_metadata_change_msg data; + + if (callback->callbackID < 0 || + !remoteRelayNetworkEventCheckACL(callback->client, conn, net)) + return -1; + + VIR_DEBUG("Relaying network metadata change %s %d %s, callback %d", + net->name, type, NULLSTR(nsuri), callback->callbackID); + + /* build return data */ + memset(&data, 0, sizeof(data));
Declaring the variable with = { 0 } initializer is preferred (see v9.7.0-rc1~160).
+ + data.type = type; + if (nsuri) { + data.nsuri = g_new0(remote_nonnull_string, 1); + *(data.nsuri) = g_strdup(nsuri); + } + + make_nonnull_network(&data.net, net); + data.callbackID = callback->callbackID; + + remoteDispatchObjectEventSend(callback->client, callback->program, + REMOTE_PROC_NETWORK_EVENT_CALLBACK_METADATA_CHANGE, + (xdrproc_t)xdr_remote_network_event_callback_metadata_change_msg, + &data); + return 0; +} + + static virConnectNetworkEventGenericCallback networkEventCallbacks[] = { VIR_NETWORK_EVENT_CALLBACK(remoteRelayNetworkEventLifecycle), + VIR_NETWORK_EVENT_CALLBACK(remoteRelayNetworkEventMetadataChange), };
G_STATIC_ASSERT(G_N_ELEMENTS(networkEventCallbacks) == VIR_NETWORK_EVENT_ID_LAST); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 7ff059e393..e295b0acc3 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3323,6 +3323,13 @@ struct remote_network_event_lifecycle_msg { int detail; };
+struct remote_network_event_callback_metadata_change_msg { + int callbackID; + remote_nonnull_network net; + int type; + remote_string nsuri; +}; + struct remote_network_set_metadata_args { remote_nonnull_network network; int type; @@ -7008,5 +7015,11 @@ enum remote_procedure { * @generate: both * @acl: network:read */ - REMOTE_PROC_NETWORK_GET_METADATA = 445 + REMOTE_PROC_NETWORK_GET_METADATA = 445, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_NETWORK_EVENT_CALLBACK_METADATA_CHANGE = 446 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index c07e0af1e6..e6132bee71 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2687,6 +2687,12 @@ struct remote_network_event_lifecycle_msg { int event; int detail; }; +struct remote_network_event_callback_metadata_change_msg { + int callbackID; + remote_nonnull_network net; + int type; + remote_string nsuri; +}; struct remote_network_set_metadata_args { remote_nonnull_network network; int type;
REMOTE_PROC_NETWORK_EVENT_CALLBACK_METADATA_CHANGE = 446 is missing Michal

Adds two new private methods to create metadata change events: - virNetworkEventMetadataChangeNewFromNet() - virNetworkEventMetadataChangeNewFromObj() Signed-off-by: K Shiva Kiran <shiva_kr@riseup.net> --- src/conf/network_event.c | 48 ++++++++++++++++++++++++++++++++++++++++ src/conf/network_event.h | 11 +++++++++ src/libvirt_private.syms | 2 ++ 3 files changed, 61 insertions(+) diff --git a/src/conf/network_event.c b/src/conf/network_event.c index d1b3aa5721..5eb9c3d48f 100644 --- a/src/conf/network_event.c +++ b/src/conf/network_event.c @@ -267,3 +267,51 @@ virNetworkEventMetadataChangeDispose(void *obj) g_free(event->nsuri); } + + +static virObjectEvent * +virNetworkEventMetadataChangeNew(const char *name, + unsigned char *uuid, + int type, + const char *nsuri) +{ + virNetworkEventMetadataChange *event; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + + if (virNetworkEventsInitialize() < 0) + return NULL; + + virUUIDFormat(uuid, uuidstr); + if (!(event = virObjectEventNew(virNetworkEventMetadataChangeClass, + virNetworkEventDispatchDefaultFunc, + VIR_NETWORK_EVENT_ID_METADATA_CHANGE, + 0, name, uuid, uuidstr))) + return NULL; + + event->type = type; + if (nsuri) + event->nsuri = g_strdup(nsuri); + + return (virObjectEvent *)event; +} + + +virObjectEvent * +virNetworkEventMetadataChangeNewFromObj(virNetworkObj *obj, + int type, + const char *nsuri) +{ + virNetworkDef *def = virNetworkObjGetDef(obj); + return virNetworkEventMetadataChangeNew(def->name, def->uuid, + type, nsuri); +} + + +virObjectEvent * +virNetworkEventMetadataChangeNewFromNet(virNetworkPtr net, + int type, + const char *nsuri) +{ + return virNetworkEventMetadataChangeNew(net->name, net->uuid, + type, nsuri); +} diff --git a/src/conf/network_event.h b/src/conf/network_event.h index 4502bfcaef..a91a238fed 100644 --- a/src/conf/network_event.h +++ b/src/conf/network_event.h @@ -23,6 +23,7 @@ #include "internal.h" #include "object_event.h" +#include "virnetworkobj.h" int virNetworkEventStateRegisterID(virConnectPtr conn, @@ -53,3 +54,13 @@ virNetworkEventLifecycleNew(const char *name, const unsigned char *uuid, int type, int detail); + +virObjectEvent * +virNetworkEventMetadataChangeNewFromObj(virNetworkObj *obj, + int type, + const char *nsuri); + +virObjectEvent * +virNetworkEventMetadataChangeNewFromNet(virNetworkPtr net, + int type, + const char *nsuri); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 1e3e407097..7a59828af0 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -861,6 +861,8 @@ virPortGroupFindByName; # conf/network_event.h virNetworkEventLifecycleNew; +virNetworkEventMetadataChangeNewFromNet; +virNetworkEventMetadataChangeNewFromObj; virNetworkEventStateRegisterID; -- 2.42.0

On 9/3/23 16:58, K Shiva Kiran wrote:
Adds two new private methods to create metadata change events: - virNetworkEventMetadataChangeNewFromNet() - virNetworkEventMetadataChangeNewFromObj()
Signed-off-by: K Shiva Kiran <shiva_kr@riseup.net> --- src/conf/network_event.c | 48 ++++++++++++++++++++++++++++++++++++++++ src/conf/network_event.h | 11 +++++++++ src/libvirt_private.syms | 2 ++ 3 files changed, 61 insertions(+)
diff --git a/src/conf/network_event.c b/src/conf/network_event.c index d1b3aa5721..5eb9c3d48f 100644 --- a/src/conf/network_event.c +++ b/src/conf/network_event.c @@ -267,3 +267,51 @@ virNetworkEventMetadataChangeDispose(void *obj)
g_free(event->nsuri); } + + +static virObjectEvent * +virNetworkEventMetadataChangeNew(const char *name, + unsigned char *uuid, + int type, + const char *nsuri) +{ + virNetworkEventMetadataChange *event; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + + if (virNetworkEventsInitialize() < 0) + return NULL; + + virUUIDFormat(uuid, uuidstr); + if (!(event = virObjectEventNew(virNetworkEventMetadataChangeClass, + virNetworkEventDispatchDefaultFunc, + VIR_NETWORK_EVENT_ID_METADATA_CHANGE, + 0, name, uuid, uuidstr))) + return NULL; + + event->type = type; + if (nsuri) + event->nsuri = g_strdup(nsuri);
This check if effectively a dead code. The first thing g_strdup() does is check for NULL. There are a few places in our code where this pattern occurs, I'll be sending a patch that fixes them.
+ + return (virObjectEvent *)event; +} +
Michal

Signed-off-by: K Shiva Kiran <shiva_kr@riseup.net> --- src/remote/remote_driver.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index b81c9bc611..5d581dae48 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -378,6 +378,11 @@ remoteNetworkBuildEventLifecycle(virNetClientProgram *prog G_GNUC_UNUSED, virNetClient *client G_GNUC_UNUSED, void *evdata, void *opaque); +static void +remoteNetworkBuildEventCallbackMetadataChange(virNetClientProgram *prog, + virNetClient *client, + void *evdata, void *opaque); + static void remoteStoragePoolBuildEventLifecycle(virNetClientProgram *prog G_GNUC_UNUSED, virNetClient *client G_GNUC_UNUSED, @@ -505,6 +510,10 @@ static virNetClientProgramEvent remoteEvents[] = { remoteNetworkBuildEventLifecycle, sizeof(remote_network_event_lifecycle_msg), (xdrproc_t)xdr_remote_network_event_lifecycle_msg }, + { REMOTE_PROC_NETWORK_EVENT_CALLBACK_METADATA_CHANGE, + remoteNetworkBuildEventCallbackMetadataChange, + sizeof(remote_network_event_callback_metadata_change_msg), + (xdrproc_t)xdr_remote_network_event_callback_metadata_change_msg }, { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_LIFECYCLE, remoteDomainBuildEventCallbackLifecycle, sizeof(remote_domain_event_callback_lifecycle_msg), @@ -4944,6 +4953,28 @@ remoteNetworkBuildEventLifecycle(virNetClientProgram *prog G_GNUC_UNUSED, virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID); } +static void +remoteNetworkBuildEventCallbackMetadataChange(virNetClientProgram *prog G_GNUC_UNUSED, + virNetClient *client G_GNUC_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_network_event_callback_metadata_change_msg *msg = evdata; + struct private_data *priv = conn->privateData; + virNetworkPtr net; + virObjectEvent *event = NULL; + + if (!(net = get_nonnull_network(conn, msg->net))) + return; + + event = virNetworkEventMetadataChangeNewFromNet(net, msg->type, msg->nsuri ? *msg->nsuri : NULL); + + virObjectUnref(net); + + virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID); +} + + static void remoteStoragePoolBuildEventLifecycle(virNetClientProgram *prog G_GNUC_UNUSED, virNetClient *client G_GNUC_UNUSED, -- 2.42.0

Signed-off-by: K Shiva Kiran <shiva_kr@riseup.net> --- src/test/test_driver.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 0174b28bac..0144df164e 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -9989,6 +9989,7 @@ testNetworkSetMetadata(virNetworkPtr net, const char *uri, unsigned int flags) { + testDriver *privconn = net->conn->privateData; virNetworkObj *privnet; int ret; @@ -10002,6 +10003,12 @@ testNetworkSetMetadata(virNetworkPtr net, key, uri, NULL, NULL, NULL, flags); + if (ret == 0) { + virObjectEvent *ev = NULL; + ev = virNetworkEventMetadataChangeNewFromObj(privnet, type, uri); + virObjectEventStateQueue(privconn->eventState, ev); + } + virNetworkObjEndAPI(&privnet); return ret; } -- 2.42.0

Signed-off-by: K Shiva Kiran <shiva_kr@riseup.net> --- src/network/bridge_driver.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index caad085192..34c88278cd 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -5149,6 +5149,12 @@ networkSetMetadata(virNetworkPtr net, driver->xmlopt, cfg->stateDir, cfg->networkConfigDir, flags); + if (ret == 0) { + virObjectEvent *event = NULL; + event = virNetworkEventMetadataChangeNewFromObj(obj, type, uri); + virObjectEventStateQueue(driver->networkEventState, event); + } + cleanup: virNetworkObjEndAPI(&obj); return ret; -- 2.42.0

Signed-off-by: K Shiva Kiran <shiva_kr@riseup.net> --- examples/c/misc/event-test.c | 85 ++++++++++++++++++++++++++++++++---- 1 file changed, 76 insertions(+), 9 deletions(-) diff --git a/examples/c/misc/event-test.c b/examples/c/misc/event-test.c index 64652b0153..813bca2699 100644 --- a/examples/c/misc/event-test.c +++ b/examples/c/misc/event-test.c @@ -1065,6 +1065,43 @@ myDomainEventMetadataChangeCallback(virConnectPtr conn G_GNUC_UNUSED, } +static const char * +networkMetadataTypeToStr(int type) +{ + switch ((virNetworkMetadataType) type) { + case VIR_NETWORK_METADATA_DESCRIPTION: + return "description"; + + case VIR_NETWORK_METADATA_TITLE: + return "title"; + + case VIR_NETWORK_METADATA_ELEMENT: + return "element"; + + case VIR_NETWORK_METADATA_LAST: + break; + } + return "unknown"; +} + +static int +myNetworkEventMetadataChangeCallback(virConnectPtr conn G_GNUC_UNUSED, + virNetworkPtr net, + int type, + const char *nsuri, + void *opaque G_GNUC_UNUSED) +{ + const char *typestr = networkMetadataTypeToStr(type); + char uuid[VIR_UUID_STRING_BUFLEN]; + virNetworkGetUUIDString(net, uuid); + + printf("%s EVENT: Network: (%s) uuid: (%s) metadata type: (%s) nsuri: (%s)\n", + __func__, virNetworkGetName(net), uuid, typestr, nsuri ? nsuri : "n/a"); + + return 0; +} + + static void myFreeFunc(void *opaque) @@ -1170,11 +1207,27 @@ struct secretEventData secretEvents[] = { SECRET_EVENT(VIR_SECRET_EVENT_ID_VALUE_CHANGED, mySecretEventValueChanged), }; +struct networkEventData { + int event; + int id; + virConnectNetworkEventGenericCallback cb; + const char *name; +}; + +#define NETWORK_EVENT(event, callback) \ + {event, -1, VIR_NETWORK_EVENT_CALLBACK(callback), #event} + +struct networkEventData networkEvents[] = { + NETWORK_EVENT(VIR_NETWORK_EVENT_ID_LIFECYCLE, myNetworkEventCallback), + NETWORK_EVENT(VIR_NETWORK_EVENT_ID_METADATA_CHANGE, myNetworkEventMetadataChangeCallback), +}; + /* make sure that the events are kept in sync */ G_STATIC_ASSERT(G_N_ELEMENTS(domainEvents) == VIR_DOMAIN_EVENT_ID_LAST); G_STATIC_ASSERT(G_N_ELEMENTS(storagePoolEvents) == VIR_STORAGE_POOL_EVENT_ID_LAST); G_STATIC_ASSERT(G_N_ELEMENTS(nodeDeviceEvents) == VIR_NODE_DEVICE_EVENT_ID_LAST); G_STATIC_ASSERT(G_N_ELEMENTS(secretEvents) == VIR_SECRET_EVENT_ID_LAST); +G_STATIC_ASSERT(G_N_ELEMENTS(networkEvents) == VIR_NETWORK_EVENT_ID_LAST); int main(int argc, char **argv) @@ -1182,7 +1235,6 @@ main(int argc, char **argv) int ret = EXIT_FAILURE; virConnectPtr dconn = NULL; int callback1ret = -1; - int callback16ret = -1; size_t i; if (argc > 1 && STREQ(argv[1], "--help")) { @@ -1241,11 +1293,21 @@ main(int argc, char **argv) } } - callback16ret = virConnectNetworkEventRegisterAny(dconn, - NULL, - VIR_NETWORK_EVENT_ID_LIFECYCLE, - VIR_NETWORK_EVENT_CALLBACK(myNetworkEventCallback), - strdup("net callback"), myFreeFunc); + /* register common network callbacks */ + for (i = 0; i < G_N_ELEMENTS(networkEvents); i++) { + struct networkEventData *event = networkEvents + i; + + event->id = virConnectNetworkEventRegisterAny(dconn, NULL, + event->event, + event->cb, + strdup(event->name), + myFreeFunc); + + if (event->id < 0) { + fprintf(stderr, "Failed to register event '%s'\n", event->name); + goto cleanup; + } + } /* register common storage pool callbacks */ for (i = 0; i < G_N_ELEMENTS(storagePoolEvents); i++) { @@ -1295,8 +1357,7 @@ main(int argc, char **argv) } } - if ((callback1ret == -1) || - (callback16ret == -1)) + if (callback1ret == -1) goto cleanup; if (virConnectSetKeepAlive(dconn, 5, 3) < 0) { @@ -1314,7 +1375,6 @@ main(int argc, char **argv) printf("Deregistering event callbacks\n"); virConnectDomainEventDeregister(dconn, myDomainEventCallback1); - virConnectNetworkEventDeregisterAny(dconn, callback16ret); printf("Deregistering domain event callbacks\n"); @@ -1324,6 +1384,13 @@ main(int argc, char **argv) } + printf("Deregistering network event callbacks\n"); + for (i = 0; i < G_N_ELEMENTS(networkEvents); i++) { + if (networkEvents[i].id > 0) + virConnectNetworkEventDeregisterAny(dconn, networkEvents[i].id); + } + + printf("Deregistering storage pool event callbacks\n"); for (i = 0; i < G_N_ELEMENTS(storagePoolEvents); i++) { if (storagePoolEvents[i].id > 0) -- 2.42.0

Signed-off-by: K Shiva Kiran <shiva_kr@riseup.net> --- NEWS.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS.rst b/NEWS.rst index a03ef20bc2..3381637fe5 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -15,6 +15,12 @@ v9.8.0 (unreleased) * **Removed features** + * New event for metadata changes in Networks + + The network object now has a new event ID ``VIR_NETWORK_EVENT_ID_METADATA_CHANGE`` + that can be used to get notifications upon changes in any of ``<title>``, + ``<description>`` or ``<metadata>``. + * **New features** * **Improvements** -- 2.42.0

On 9/3/23 16:58, K Shiva Kiran wrote:
This patchset adds support to trigger an event upon changes in the content of `<title>`, `<description>` or `<metadata>` in the network.
K Shiva Kiran (8): Define Network Metadata change callback function Define Network event struct for Metadata change Add Event ID, Server side dispatcher and virsh print function Add methods to create Metadata change events Implement RPC Client for Network Metadata change callbacks Test driver implementation for Network metadata change callbacks Add Bridge Driver implementation for Network metadata change callbacks examples: Add Testing for metadata change callbacks
examples/c/misc/event-test.c | 85 ++++++++++++++++++++++++++--- include/libvirt/libvirt-network.h | 22 ++++++++ src/conf/network_event.c | 84 ++++++++++++++++++++++++++++ src/conf/network_event.h | 11 ++++ src/libvirt_private.syms | 2 + src/network/bridge_driver.c | 6 ++ src/remote/remote_daemon_dispatch.c | 38 +++++++++++++ src/remote/remote_driver.c | 31 +++++++++++ src/remote/remote_protocol.x | 15 ++++- src/remote_protocol-structs | 6 ++ src/test/test_driver.c | 7 +++ tools/virsh-network.c | 46 +++++++++++++++- 12 files changed, 342 insertions(+), 11 deletions(-)
Couple of points: Patches 1-3 can be squashed together. There is no value in having them separate (nobody will ever backport just the callback function definition). Commit message subject usually have a prefix (see git log) respecting the part of the code they are changing. For instance, instead of: Add Bridge Driver implementation for Network metadata change callbacks we would have: network: Implement network metadata change callbacks or: bridge_driver: Implement network metadata change callbacks This makes it easy to "pattern match" when skimming through git log. Nevertheless, these are small nits and I'll fix hem before merging. Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Michal
participants (2)
-
K Shiva Kiran
-
Michal Prívozník