Define Network Metadata change event

When changing the metadata via virNetworkSetMetadata(), we can
now emit an event to notify the app of changes. This is useful
when co-ordinating different applications read/write of custom
metadata.

Signed-off-by: K Shiva Kiran <shiva_kr@riseup.net>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
K Shiva Kiran 2023-09-03 20:28:33 +05:30 committed by Michal Privoznik
parent 47230842aa
commit 95ee416a75
6 changed files with 162 additions and 2 deletions

View File

@ -330,6 +330,7 @@ typedef void (*virConnectNetworkEventLifecycleCallback)(virConnectPtr conn,
*/ */
typedef enum { typedef enum {
VIR_NETWORK_EVENT_ID_LIFECYCLE = 0, /* virConnectNetworkEventLifecycleCallback (Since: 1.2.1) */ 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 # ifdef VIR_ENUM_SENTINELS
VIR_NETWORK_EVENT_ID_LAST VIR_NETWORK_EVENT_ID_LAST
@ -576,4 +577,25 @@ virNetworkGetMetadata(virNetworkPtr network,
const char *uri, const char *uri,
unsigned int flags); 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 */ #endif /* LIBVIRT_NETWORK_H */

View File

@ -45,10 +45,21 @@ struct _virNetworkEventLifecycle {
}; };
typedef struct _virNetworkEventLifecycle virNetworkEventLifecycle; typedef struct _virNetworkEventLifecycle virNetworkEventLifecycle;
struct _virNetworkEventMetadataChange {
virNetworkEvent parent;
int type;
char *nsuri;
};
typedef struct _virNetworkEventMetadataChange virNetworkEventMetadataChange;
static virClass *virNetworkEventClass; static virClass *virNetworkEventClass;
static virClass *virNetworkEventLifecycleClass; static virClass *virNetworkEventLifecycleClass;
static virClass *virNetworkEventMetadataChangeClass;
static void virNetworkEventDispose(void *obj); static void virNetworkEventDispose(void *obj);
static void virNetworkEventLifecycleDispose(void *obj); static void virNetworkEventLifecycleDispose(void *obj);
static void virNetworkEventMetadataChangeDispose(void *obj);
static int static int
virNetworkEventsOnceInit(void) virNetworkEventsOnceInit(void)
@ -59,6 +70,9 @@ virNetworkEventsOnceInit(void)
if (!VIR_CLASS_NEW(virNetworkEventLifecycle, virNetworkEventClass)) if (!VIR_CLASS_NEW(virNetworkEventLifecycle, virNetworkEventClass))
return -1; return -1;
if (!VIR_CLASS_NEW(virNetworkEventMetadataChange, virNetworkEventClass))
return -1;
return 0; return 0;
} }
@ -104,6 +118,18 @@ virNetworkEventDispatchDefaultFunc(virConnectPtr conn,
return; 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: case VIR_NETWORK_EVENT_ID_LAST:
break; break;
} }
@ -231,3 +257,13 @@ virNetworkEventLifecycleNew(const char *name,
return (virObjectEvent *)event; return (virObjectEvent *)event;
} }
static void
virNetworkEventMetadataChangeDispose(void *obj)
{
virNetworkEventMetadataChange *event = obj;
VIR_DEBUG("obj=%p", event);
g_free(event->nsuri);
}

View File

@ -1385,8 +1385,46 @@ remoteRelayNetworkEventLifecycle(virConnectPtr conn,
return 0; 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[] = { static virConnectNetworkEventGenericCallback networkEventCallbacks[] = {
VIR_NETWORK_EVENT_CALLBACK(remoteRelayNetworkEventLifecycle), VIR_NETWORK_EVENT_CALLBACK(remoteRelayNetworkEventLifecycle),
VIR_NETWORK_EVENT_CALLBACK(remoteRelayNetworkEventMetadataChange),
}; };
G_STATIC_ASSERT(G_N_ELEMENTS(networkEventCallbacks) == VIR_NETWORK_EVENT_ID_LAST); G_STATIC_ASSERT(G_N_ELEMENTS(networkEventCallbacks) == VIR_NETWORK_EVENT_ID_LAST);

View File

@ -3323,6 +3323,13 @@ struct remote_network_event_lifecycle_msg {
int detail; 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 { struct remote_network_set_metadata_args {
remote_nonnull_network network; remote_nonnull_network network;
int type; int type;
@ -7008,5 +7015,11 @@ enum remote_procedure {
* @generate: both * @generate: both
* @acl: network:read * @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
}; };

View File

@ -2687,6 +2687,12 @@ struct remote_network_event_lifecycle_msg {
int event; int event;
int detail; 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 { struct remote_network_set_metadata_args {
remote_nonnull_network network; remote_nonnull_network network;
int type; int type;
@ -3736,4 +3742,5 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_FD_ASSOCIATE = 443, REMOTE_PROC_DOMAIN_FD_ASSOCIATE = 443,
REMOTE_PROC_NETWORK_SET_METADATA = 444, REMOTE_PROC_NETWORK_SET_METADATA = 444,
REMOTE_PROC_NETWORK_GET_METADATA = 445, REMOTE_PROC_NETWORK_GET_METADATA = 445,
REMOTE_PROC_NETWORK_EVENT_CALLBACK_METADATA_CHANGE = 446,
}; };

View File

@ -1581,7 +1581,8 @@ typedef struct virshNetEventData virshNetEventData;
VIR_ENUM_DECL(virshNetworkEventId); VIR_ENUM_DECL(virshNetworkEventId);
VIR_ENUM_IMPL(virshNetworkEventId, VIR_ENUM_IMPL(virshNetworkEventId,
VIR_NETWORK_EVENT_ID_LAST, VIR_NETWORK_EVENT_ID_LAST,
"lifecycle"); "lifecycle",
"metadata-change");
static void static void
vshEventLifecyclePrint(virConnectPtr conn G_GNUC_UNUSED, vshEventLifecyclePrint(virConnectPtr conn G_GNUC_UNUSED,
@ -1614,9 +1615,52 @@ vshEventLifecyclePrint(virConnectPtr conn G_GNUC_UNUSED,
vshEventDone(data->ctl); 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[] = { virshNetworkEventCallback virshNetworkEventCallbacks[] = {
{ "lifecycle", { "lifecycle",
VIR_NETWORK_EVENT_CALLBACK(vshEventLifecyclePrint), }, VIR_NETWORK_EVENT_CALLBACK(vshEventLifecyclePrint), },
{ "metadata-change",
VIR_NETWORK_EVENT_CALLBACK(vshEventMetadataChangePrint), },
}; };
G_STATIC_ASSERT(VIR_NETWORK_EVENT_ID_LAST == G_N_ELEMENTS(virshNetworkEventCallbacks)); G_STATIC_ASSERT(VIR_NETWORK_EVENT_ID_LAST == G_N_ELEMENTS(virshNetworkEventCallbacks));