[libvirt PATCH 2/4] Adding Public Get and Set APIs for Network Metadata

K Shiva Kiran posted 4 patches 2 years, 7 months ago
There is a newer version of this series
[libvirt PATCH 2/4] Adding Public Get and Set APIs for Network Metadata
Posted by K Shiva Kiran 2 years, 7 months ago
This patch introduces public Get and Set APIs for modifying <title>,
<description> and <metadata> elements of the Network object.

- Added enum to select one of the above elements to operate on.
- Added error code and messages for missing metadata.
- Added public API implementation.
- Added driver support.
- Defined wire protocol format.

Signed-off-by: K Shiva Kiran <shiva_kr@riseup.net>
---
 include/libvirt/libvirt-network.h |  29 ++++++
 include/libvirt/virterror.h       |   1 +
 src/driver-network.h              |  16 +++
 src/libvirt-network.c             | 167 ++++++++++++++++++++++++++++++
 src/libvirt_public.syms           |   6 ++
 src/remote/remote_driver.c        |   2 +
 src/remote/remote_protocol.x      |  36 ++++++-
 src/remote_protocol-structs       |  19 ++++
 src/util/virerror.c               |   3 +
 9 files changed, 278 insertions(+), 1 deletion(-)

diff --git a/include/libvirt/libvirt-network.h b/include/libvirt/libvirt-network.h
index 90cde0cf24..147dc8c6b8 100644
--- a/include/libvirt/libvirt-network.h
+++ b/include/libvirt/libvirt-network.h
@@ -547,4 +547,33 @@ virNetworkPortFree(virNetworkPortPtr port);
 int
 virNetworkPortRef(virNetworkPortPtr port);
 
+/**
+ * virNetworkMetadataType:
+ *
+ * Since: 9.6.0
+ */
+typedef enum {
+    VIR_NETWORK_METADATA_DESCRIPTION = 0, /* Operate on <description> (Since: 9.6.0) */
+    VIR_NETWORK_METADATA_TITLE       = 1, /* Operate on <title> (Since: 9.6.0) */
+    VIR_NETWORK_METADATA_ELEMENT     = 2, /* Operate on <metadata> (Since: 9.6.0) */
+
+# ifdef VIR_ENUM_SENTINELS
+    VIR_NETWORK_METADATA_LAST /* (Since: 9.6.0) */
+# endif
+} virNetworkMetadataType;
+
+int
+virNetworkSetMetadata(virNetworkPtr network,
+                      int type,
+                      const char *metadata,
+                      const char *key,
+                      const char *uri,
+                      unsigned int flags);
+
+char *
+virNetworkGetMetadata(virNetworkPtr network,
+                      int type,
+                      const char *uri,
+                      unsigned int flags);
+
 #endif /* LIBVIRT_NETWORK_H */
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index df13e4f11e..55bc4431d9 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -348,6 +348,7 @@ typedef enum {
     VIR_ERR_NO_HOSTNAME = 108,          /* no domain's hostname found (Since: 6.1.0) */
     VIR_ERR_CHECKPOINT_INCONSISTENT = 109, /* checkpoint can't be used (Since: 6.10.0) */
     VIR_ERR_MULTIPLE_DOMAINS = 110,     /* more than one matching domain found (Since: 7.1.0) */
+    VIR_ERR_NO_NETWORK_METADATA = 111,  /* Network metadata is not present (Since: 9.6.0) */
 
 # ifdef VIR_ENUM_SENTINELS
     VIR_ERR_NUMBER_LAST /* (Since: 5.0.0) */
diff --git a/src/driver-network.h b/src/driver-network.h
index 99efd4c8aa..1d19b013c9 100644
--- a/src/driver-network.h
+++ b/src/driver-network.h
@@ -161,6 +161,20 @@ typedef int
                              virNetworkPortPtr **ports,
                              unsigned int flags);
 
+typedef int
+(*virDrvNetworkSetMetadata)(virNetworkPtr network,
+                            int type,
+                            const char *metadata,
+                            const char *key,
+                            const char *uri,
+                            unsigned int flags);
+
+typedef char *
+(*virDrvNetworkGetMetadata)(virNetworkPtr network,
+                            int type,
+                            const char *uri,
+                            unsigned int flags);
+
 typedef struct _virNetworkDriver virNetworkDriver;
 
 /**
@@ -202,4 +216,6 @@ struct _virNetworkDriver {
     virDrvNetworkPortGetParameters networkPortGetParameters;
     virDrvNetworkPortDelete networkPortDelete;
     virDrvNetworkListAllPorts networkListAllPorts;
+    virDrvNetworkSetMetadata networkSetMetadata;
+    virDrvNetworkGetMetadata networkGetMetadata;
 };
diff --git a/src/libvirt-network.c b/src/libvirt-network.c
index 236dfe2f5d..2dd11cf205 100644
--- a/src/libvirt-network.c
+++ b/src/libvirt-network.c
@@ -1915,3 +1915,170 @@ virNetworkPortRef(virNetworkPortPtr port)
     virObjectRef(port);
     return 0;
 }
+
+
+/**
+ * virNetworkSetMetadata:
+ * @network: a network object
+ * @type: type of metadata, from virNetworkMetadataType
+ * @metadata: new metadata text
+ * @key: XML namespace key, or NULL
+ * @uri: XML namespace URI, or NULL
+ * @flags: bitwise-OR of virNetworkUpdateFlags
+ *
+ * Sets the appropriate network element given by @type to the
+ * value of @metadata.  A @type of VIR_NETWORK_METADATA_DESCRIPTION
+ * is free-form text; VIR_NETWORK_METADATA_TITLE is free-form, but no
+ * newlines are permitted, and should be short (although the length is
+ * not enforced). For these two options @key and @uri are irrelevant and
+ * must be set to NULL.
+ *
+ * For type VIR_NETWORK_METADATA_ELEMENT @metadata must be well-formed
+ * XML belonging to namespace defined by @uri with local name @key.
+ *
+ * Passing NULL for @metadata says to remove that element from the
+ * network XML (passing the empty string leaves the element present).
+ *
+ * The resulting metadata will be present in virNetworkGetXMLDesc(),
+ * as well as quick access through virNetworkGetMetadata().
+ *
+ * @flags controls whether the live network state, persistent configuration,
+ * or both will be modified.
+ *
+ * Returns 0 on success, -1 in case of failure.
+ *
+ * Since: 9.6.0
+ */
+int
+virNetworkSetMetadata(virNetworkPtr network,
+                      int type,
+                      const char *metadata,
+                      const char *key,
+                      const char *uri,
+                      unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DEBUG("network=%p, type=%d, metadata='%s', key='%s', uri='%s', flags=0x%x",
+              network, type, NULLSTR(metadata), NULLSTR(key), NULLSTR(uri),
+              flags);
+
+    virResetLastError();
+
+    virCheckNetworkReturn(network, -1);
+    conn = network->conn;
+
+    virCheckReadOnlyGoto(conn->flags, error);
+
+    switch (type) {
+    case VIR_NETWORK_METADATA_TITLE:
+        if (metadata && strchr(metadata, '\n')) {
+            virReportInvalidArg(metadata, "%s",
+                                _("metadata title can't contain "
+                                  "newlines"));
+            goto error;
+        }
+        G_GNUC_FALLTHROUGH;
+    case VIR_NETWORK_METADATA_DESCRIPTION:
+        virCheckNullArgGoto(uri, error);
+        virCheckNullArgGoto(key, error);
+        break;
+    case VIR_NETWORK_METADATA_ELEMENT:
+        virCheckNonNullArgGoto(uri, error);
+        if (metadata)
+            virCheckNonNullArgGoto(key, error);
+        break;
+    default:
+        /* For future expansion */
+        break;
+    }
+
+    if (conn->networkDriver->networkSetMetadata) {
+        int ret;
+        ret = conn->networkDriver->networkSetMetadata(network, type, metadata, key, uri,
+                                                      flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+
+ error:
+    virDispatchError(network->conn);
+    return -1;
+}
+
+
+/**
+ * virNetworkGetMetadata:
+ * @network: a network object
+ * @type: type of metadata, from virNetworkMetadataType
+ * @uri: XML namespace identifier
+ * @flags: bitwise-OR of virNetworkUpdateFlags
+ *
+ * Retrieves the appropriate network element given by @type.
+ * If VIR_NETWORK_METADATA_ELEMENT is requested parameter @uri
+ * must be set to the name of the namespace the requested elements
+ * belong to, otherwise must be NULL.
+ *
+ * If an element of the network XML is not present, the resulting
+ * error will be VIR_ERR_NO_NETWORK_METADATA.  This method forms
+ * a shortcut for seeing information from virNetworkSetMetadata()
+ * without having to go through virNetworkGetXMLDesc().
+ *
+ * @flags controls whether the live network state or persistent
+ * configuration will be queried.
+ *
+ * Returns the metadata string on success (caller must free),
+ * or NULL in case of failure.
+ *
+ * Since: 9.6.0
+ */
+char *
+virNetworkGetMetadata(virNetworkPtr network,
+                      int type,
+                      const char *uri,
+                      unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DEBUG("network=%p, type=%d, uri='%s', flags=0x%x",
+               network, type, NULLSTR(uri), flags);
+
+    virResetLastError();
+
+    virCheckNetworkReturn(network, NULL);
+
+    VIR_EXCLUSIVE_FLAGS_GOTO(VIR_NETWORK_UPDATE_AFFECT_LIVE,
+                             VIR_NETWORK_UPDATE_AFFECT_CONFIG,
+                             error);
+
+    switch (type) {
+    case VIR_NETWORK_METADATA_TITLE:
+    case VIR_NETWORK_METADATA_DESCRIPTION:
+        virCheckNullArgGoto(uri, error);
+        break;
+    case VIR_NETWORK_METADATA_ELEMENT:
+        virCheckNonNullArgGoto(uri, error);
+        break;
+    default:
+        /* For future expansion */
+        break;
+    }
+
+    conn = network->conn;
+
+    if (conn->networkDriver->networkGetMetadata) {
+        char *ret;
+        if (!(ret = conn->networkDriver->networkGetMetadata(network, type, uri, flags)))
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+
+ error:
+    virDispatchError(network->conn);
+    return NULL;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 80742f268e..4523700a0f 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -932,4 +932,10 @@ LIBVIRT_9.0.0 {
         virDomainFDAssociate;
 } LIBVIRT_8.5.0;
 
+LIBVIRT_9.6.0 {
+    global:
+        virNetworkGetMetadata;
+        virNetworkSetMetadata;
+} LIBVIRT_9.0.0;
+
 # .... define new API here using predicted next version number ....
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 65ec239fb7..4e277f668a 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -8160,6 +8160,8 @@ static virNetworkDriver network_driver = {
     .networkPortSetParameters = remoteNetworkPortSetParameters, /* 5.5.0 */
     .networkPortGetParameters = remoteNetworkPortGetParameters, /* 5.5.0 */
     .networkPortDelete = remoteNetworkPortDelete, /* 5.5.0 */
+    .networkSetMetadata = remoteNetworkSetMetadata, /* 9.6.0 */
+    .networkGetMetadata = remoteNetworkGetMetadata, /* 9.6.0 */
 };
 
 static virInterfaceDriver interface_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 5d86a51116..7ff059e393 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -3323,6 +3323,26 @@ struct remote_network_event_lifecycle_msg {
     int detail;
 };
 
+struct remote_network_set_metadata_args {
+    remote_nonnull_network network;
+    int type;
+    remote_string metadata;
+    remote_string key;
+    remote_string uri;
+    unsigned int flags;
+};
+
+struct remote_network_get_metadata_args {
+    remote_nonnull_network network;
+    int type;
+    remote_string uri;
+    unsigned int flags;
+};
+
+struct remote_network_get_metadata_ret {
+    remote_nonnull_string metadata;
+};
+
 struct remote_connect_storage_pool_event_register_any_args {
     int eventID;
     remote_storage_pool pool;
@@ -6974,5 +6994,19 @@ enum remote_procedure {
      * @generate: none
      * @acl: domain:write
      */
-    REMOTE_PROC_DOMAIN_FD_ASSOCIATE = 443
+    REMOTE_PROC_DOMAIN_FD_ASSOCIATE = 443,
+
+    /**
+     * @generate: both
+     * @acl: network:write
+     * @acl: network:save:!VIR_NETWORK_UPDATE_AFFECT_CONFIG|VIR_NETWORK_UPDATE_AFFECT_LIVE
+     * @acl: network:save:VIR_NETWORK_UPDATE_AFFECT_CONFIG
+     */
+    REMOTE_PROC_NETWORK_SET_METADATA = 444,
+
+    /**
+     * @generate: both
+     * @acl: network:read
+     */
+    REMOTE_PROC_NETWORK_GET_METADATA = 445
 };
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 3c6c230a16..14898a0bc7 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -3130,6 +3130,23 @@ struct remote_network_port_delete_args {
         remote_nonnull_network_port port;
         u_int                      flags;
 };
+struct remote_network_set_metadata_args {
+        remote_nonnull_network     network;
+        int                        type;
+        remote_string              metadata;
+        remote_string              key;
+        remote_string              uri;
+        u_int                      flags;
+};
+struct remote_network_get_metadata_args {
+        remote_nonnull_network     network;
+        int                        type;
+        remote_string              uri;
+        u_int                      flags;
+};
+struct remote_network_get_metadata_ret {
+        remote_nonnull_string      metadata;
+};
 struct remote_domain_checkpoint_create_xml_args {
         remote_nonnull_domain      dom;
         remote_nonnull_string      xml_desc;
@@ -3717,4 +3734,6 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_RESTORE_PARAMS = 441,
         REMOTE_PROC_DOMAIN_ABORT_JOB_FLAGS = 442,
         REMOTE_PROC_DOMAIN_FD_ASSOCIATE = 443,
+        REMOTE_PROC_NETWORK_SET_METADATA = 444,
+        REMOTE_PROC_NETWORK_GET_METADATA = 445
 };
diff --git a/src/util/virerror.c b/src/util/virerror.c
index 453f19514e..227a182417 100644
--- a/src/util/virerror.c
+++ b/src/util/virerror.c
@@ -1287,6 +1287,9 @@ static const virErrorMsgTuple virErrorMsgStrings[] = {
     [VIR_ERR_MULTIPLE_DOMAINS] = {
         N_("multiple matching domains found"),
         N_("multiple matching domains found: %1$s") },
+    [VIR_ERR_NO_NETWORK_METADATA] = {
+        N_("metadata not found"),
+        N_("metadata not found: %1$s") },
 };
 
 G_STATIC_ASSERT(G_N_ELEMENTS(virErrorMsgStrings) == VIR_ERR_NUMBER_LAST);
-- 
2.41.0
Re: [libvirt PATCH 2/4] Adding Public Get and Set APIs for Network Metadata
Posted by Michal Prívozník 2 years, 6 months ago
On 7/11/23 08:47, K Shiva Kiran wrote:
> This patch introduces public Get and Set APIs for modifying <title>,
> <description> and <metadata> elements of the Network object.
> 
> - Added enum to select one of the above elements to operate on.
> - Added error code and messages for missing metadata.
> - Added public API implementation.
> - Added driver support.
> - Defined wire protocol format.
> 
> Signed-off-by: K Shiva Kiran <shiva_kr@riseup.net>
> ---
>  include/libvirt/libvirt-network.h |  29 ++++++
>  include/libvirt/virterror.h       |   1 +
>  src/driver-network.h              |  16 +++
>  src/libvirt-network.c             | 167 ++++++++++++++++++++++++++++++
>  src/libvirt_public.syms           |   6 ++
>  src/remote/remote_driver.c        |   2 +
>  src/remote/remote_protocol.x      |  36 ++++++-
>  src/remote_protocol-structs       |  19 ++++
>  src/util/virerror.c               |   3 +
>  9 files changed, 278 insertions(+), 1 deletion(-)
> 

We usually introduce public APIs in one patch and implement remote
driver in another. But I guess I can live with this.

> diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
> index 3c6c230a16..14898a0bc7 100644
> --- a/src/remote_protocol-structs
> +++ b/src/remote_protocol-structs
> @@ -3130,6 +3130,23 @@ struct remote_network_port_delete_args {
>          remote_nonnull_network_port port;
>          u_int                      flags;
>  };
> +struct remote_network_set_metadata_args {
> +        remote_nonnull_network     network;
> +        int                        type;
> +        remote_string              metadata;
> +        remote_string              key;
> +        remote_string              uri;
> +        u_int                      flags;
> +};
> +struct remote_network_get_metadata_args {
> +        remote_nonnull_network     network;
> +        int                        type;
> +        remote_string              uri;
> +        u_int                      flags;
> +};
> +struct remote_network_get_metadata_ret {
> +        remote_nonnull_string      metadata;
> +};

This is misplaced. 

>  struct remote_domain_checkpoint_create_xml_args {
>          remote_nonnull_domain      dom;
>          remote_nonnull_string      xml_desc;
> @@ -3717,4 +3734,6 @@ enum remote_procedure {
>          REMOTE_PROC_DOMAIN_RESTORE_PARAMS = 441,
>          REMOTE_PROC_DOMAIN_ABORT_JOB_FLAGS = 442,
>          REMOTE_PROC_DOMAIN_FD_ASSOCIATE = 443,
> +        REMOTE_PROC_NETWORK_SET_METADATA = 444,
> +        REMOTE_PROC_NETWORK_GET_METADATA = 445

Here we want the trailing comma.

>  };

Squash in the following:

diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 14898a0bc7..c07e0af1e6 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -2687,6 +2687,23 @@ struct remote_network_event_lifecycle_msg {
         int                        event;
         int                        detail;
 };
+struct remote_network_set_metadata_args {
+        remote_nonnull_network     network;
+        int                        type;
+        remote_string              metadata;
+        remote_string              key;
+        remote_string              uri;
+        u_int                      flags;
+};
+struct remote_network_get_metadata_args {
+        remote_nonnull_network     network;
+        int                        type;
+        remote_string              uri;
+        u_int                      flags;
+};
+struct remote_network_get_metadata_ret {
+        remote_nonnull_string      metadata;
+};
 struct remote_connect_storage_pool_event_register_any_args {
         int                        eventID;
         remote_storage_pool        pool;
@@ -3130,23 +3147,6 @@ struct remote_network_port_delete_args {
         remote_nonnull_network_port port;
         u_int                      flags;
 };
-struct remote_network_set_metadata_args {
-        remote_nonnull_network     network;
-        int                        type;
-        remote_string              metadata;
-        remote_string              key;
-        remote_string              uri;
-        u_int                      flags;
-};
-struct remote_network_get_metadata_args {
-        remote_nonnull_network     network;
-        int                        type;
-        remote_string              uri;
-        u_int                      flags;
-};
-struct remote_network_get_metadata_ret {
-        remote_nonnull_string      metadata;
-};
 struct remote_domain_checkpoint_create_xml_args {
         remote_nonnull_domain      dom;
         remote_nonnull_string      xml_desc;
@@ -3735,5 +3735,5 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_ABORT_JOB_FLAGS = 442,
         REMOTE_PROC_DOMAIN_FD_ASSOCIATE = 443,
         REMOTE_PROC_NETWORK_SET_METADATA = 444,
-        REMOTE_PROC_NETWORK_GET_METADATA = 445
+        REMOTE_PROC_NETWORK_GET_METADATA = 445,
 };


Michal
Re: [libvirt PATCH 2/4] Adding Public Get and Set APIs for Network Metadata
Posted by K Shiva Kiran 2 years, 6 months ago
On 19/07/23 14:48, Michal Prívozník wrote:
> On 7/11/23 08:47, K Shiva Kiran wrote:
>> This patch introduces public Get and Set APIs for modifying <title>,
>> <description> and <metadata> elements of the Network object.
>>
>> - Added enum to select one of the above elements to operate on.
>> - Added error code and messages for missing metadata.
>> - Added public API implementation.
>> - Added driver support.
>> - Defined wire protocol format.
>>
>> Signed-off-by: K Shiva Kiran <shiva_kr@riseup.net>
>> ---
>>   include/libvirt/libvirt-network.h |  29 ++++++
>>   include/libvirt/virterror.h       |   1 +
>>   src/driver-network.h              |  16 +++
>>   src/libvirt-network.c             | 167 ++++++++++++++++++++++++++++++
>>   src/libvirt_public.syms           |   6 ++
>>   src/remote/remote_driver.c        |   2 +
>>   src/remote/remote_protocol.x      |  36 ++++++-
>>   src/remote_protocol-structs       |  19 ++++
>>   src/util/virerror.c               |   3 +
>>   9 files changed, 278 insertions(+), 1 deletion(-)
>>
> We usually introduce public APIs in one patch and implement remote
> driver in another. But I guess I can live with this.
>
>> diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
>> index 3c6c230a16..14898a0bc7 100644
>> --- a/src/remote_protocol-structs
>> +++ b/src/remote_protocol-structs
>> @@ -3130,6 +3130,23 @@ struct remote_network_port_delete_args {
>>           remote_nonnull_network_port port;
>>           u_int                      flags;
>>   };
>> +struct remote_network_set_metadata_args {
>> +        remote_nonnull_network     network;
>> +        int                        type;
>> +        remote_string              metadata;
>> +        remote_string              key;
>> +        remote_string              uri;
>> +        u_int                      flags;
>> +};
>> +struct remote_network_get_metadata_args {
>> +        remote_nonnull_network     network;
>> +        int                        type;
>> +        remote_string              uri;
>> +        u_int                      flags;
>> +};
>> +struct remote_network_get_metadata_ret {
>> +        remote_nonnull_string      metadata;
>> +};
> This is misplaced.
>
>>   struct remote_domain_checkpoint_create_xml_args {
>>           remote_nonnull_domain      dom;
>>           remote_nonnull_string      xml_desc;
>> @@ -3717,4 +3734,6 @@ enum remote_procedure {
>>           REMOTE_PROC_DOMAIN_RESTORE_PARAMS = 441,
>>           REMOTE_PROC_DOMAIN_ABORT_JOB_FLAGS = 442,
>>           REMOTE_PROC_DOMAIN_FD_ASSOCIATE = 443,
>> +        REMOTE_PROC_NETWORK_SET_METADATA = 444,
>> +        REMOTE_PROC_NETWORK_GET_METADATA = 445
> Here we want the trailing comma.
>
>>   };
> Squash in the following:
>
> diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
> index 14898a0bc7..c07e0af1e6 100644
> --- a/src/remote_protocol-structs
> +++ b/src/remote_protocol-structs
> @@ -2687,6 +2687,23 @@ struct remote_network_event_lifecycle_msg {
>           int                        event;
>           int                        detail;
>   };
> +struct remote_network_set_metadata_args {
> +        remote_nonnull_network     network;
> +        int                        type;
> +        remote_string              metadata;
> +        remote_string              key;
> +        remote_string              uri;
> +        u_int                      flags;
> +};
> +struct remote_network_get_metadata_args {
> +        remote_nonnull_network     network;
> +        int                        type;
> +        remote_string              uri;
> +        u_int                      flags;
> +};
> +struct remote_network_get_metadata_ret {
> +        remote_nonnull_string      metadata;
> +};
>   struct remote_connect_storage_pool_event_register_any_args {
>           int                        eventID;
>           remote_storage_pool        pool;
> @@ -3130,23 +3147,6 @@ struct remote_network_port_delete_args {
>           remote_nonnull_network_port port;
>           u_int                      flags;
>   };
> -struct remote_network_set_metadata_args {
> -        remote_nonnull_network     network;
> -        int                        type;
> -        remote_string              metadata;
> -        remote_string              key;
> -        remote_string              uri;
> -        u_int                      flags;
> -};
> -struct remote_network_get_metadata_args {
> -        remote_nonnull_network     network;
> -        int                        type;
> -        remote_string              uri;
> -        u_int                      flags;
> -};
> -struct remote_network_get_metadata_ret {
> -        remote_nonnull_string      metadata;
> -};
>   struct remote_domain_checkpoint_create_xml_args {
>           remote_nonnull_domain      dom;
>           remote_nonnull_string      xml_desc;
> @@ -3735,5 +3735,5 @@ enum remote_procedure {
>           REMOTE_PROC_DOMAIN_ABORT_JOB_FLAGS = 442,
>           REMOTE_PROC_DOMAIN_FD_ASSOCIATE = 443,
>           REMOTE_PROC_NETWORK_SET_METADATA = 444,
> -        REMOTE_PROC_NETWORK_GET_METADATA = 445
> +        REMOTE_PROC_NETWORK_GET_METADATA = 445,
>   };
>
>
> Michal
>
Squashed in v2:
https://listman.redhat.com/archives/libvir-list/2023-July/240830.html
I realize it's a mistake to send a v2 patch as a reply to the same 
thread and
won't be repeating it.

Shiva
[libvirt PATCH v2 2/4] Adding Public Get and Set APIs for Network Metadata
Posted by K Shiva Kiran 2 years, 6 months ago
 From 61d699de0603ca49a67cc898a219cce2613b82ba Mon Sep 17 00:00:00 2001
From: K Shiva Kiran <shiva_kr@riseup.net>
Date: Tue, 27 Jun 2023 20:48:52 +0530
Subject: [libvirt PATCH v2 2/4] Adding Public Get and Set APIs for 
Network Metadata

This patch introduces public Get and Set APIs for modifying <title>,
<description> and <metadata> elements of the Network object.

- Added enum to select one of the above elements to operate on.
- Added error code and messages for missing metadata.
- Added public API implementation.
- Added driver support.
- Defined wire protocol format.
---

This is a v2 of:
https://listman.redhat.com/archives/libvir-list/2023-July/240666.html

  include/libvirt/libvirt-network.h |  29 ++++++
  include/libvirt/virterror.h       |   1 +
  src/driver-network.h              |  16 +++
  src/libvirt-network.c             | 167 ++++++++++++++++++++++++++++++
  src/libvirt_public.syms           |   6 ++
  src/remote/remote_driver.c        |   2 +
  src/remote/remote_protocol.x      |  36 ++++++-
  src/remote_protocol-structs       |  19 ++++
  src/util/virerror.c               |   3 +
  9 files changed, 278 insertions(+), 1 deletion(-)

diff --git a/include/libvirt/libvirt-network.h 
b/include/libvirt/libvirt-network.h
index 90cde0cf24..147dc8c6b8 100644
--- a/include/libvirt/libvirt-network.h
+++ b/include/libvirt/libvirt-network.h
@@ -547,4 +547,33 @@ virNetworkPortFree(virNetworkPortPtr port);
  int
  virNetworkPortRef(virNetworkPortPtr port);

+/**
+ * virNetworkMetadataType:
+ *
+ * Since: 9.6.0
+ */
+typedef enum {
+    VIR_NETWORK_METADATA_DESCRIPTION = 0, /* Operate on <description> 
(Since: 9.6.0) */
+    VIR_NETWORK_METADATA_TITLE       = 1, /* Operate on <title> (Since: 
9.6.0) */
+    VIR_NETWORK_METADATA_ELEMENT     = 2, /* Operate on <metadata> 
(Since: 9.6.0) */
+
+# ifdef VIR_ENUM_SENTINELS
+    VIR_NETWORK_METADATA_LAST /* (Since: 9.6.0) */
+# endif
+} virNetworkMetadataType;
+
+int
+virNetworkSetMetadata(virNetworkPtr network,
+                      int type,
+                      const char *metadata,
+                      const char *key,
+                      const char *uri,
+                      unsigned int flags);
+
+char *
+virNetworkGetMetadata(virNetworkPtr network,
+                      int type,
+                      const char *uri,
+                      unsigned int flags);
+
  #endif /* LIBVIRT_NETWORK_H */
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index df13e4f11e..55bc4431d9 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -348,6 +348,7 @@ typedef enum {
      VIR_ERR_NO_HOSTNAME = 108,          /* no domain's hostname found 
(Since: 6.1.0) */
      VIR_ERR_CHECKPOINT_INCONSISTENT = 109, /* checkpoint can't be used 
(Since: 6.10.0) */
      VIR_ERR_MULTIPLE_DOMAINS = 110,     /* more than one matching 
domain found (Since: 7.1.0) */
+    VIR_ERR_NO_NETWORK_METADATA = 111,  /* Network metadata is not 
present (Since: 9.6.0) */

  # ifdef VIR_ENUM_SENTINELS
      VIR_ERR_NUMBER_LAST /* (Since: 5.0.0) */
diff --git a/src/driver-network.h b/src/driver-network.h
index 99efd4c8aa..1d19b013c9 100644
--- a/src/driver-network.h
+++ b/src/driver-network.h
@@ -161,6 +161,20 @@ typedef int
                               virNetworkPortPtr **ports,
                               unsigned int flags);

+typedef int
+(*virDrvNetworkSetMetadata)(virNetworkPtr network,
+                            int type,
+                            const char *metadata,
+                            const char *key,
+                            const char *uri,
+                            unsigned int flags);
+
+typedef char *
+(*virDrvNetworkGetMetadata)(virNetworkPtr network,
+                            int type,
+                            const char *uri,
+                            unsigned int flags);
+
  typedef struct _virNetworkDriver virNetworkDriver;

  /**
@@ -202,4 +216,6 @@ struct _virNetworkDriver {
      virDrvNetworkPortGetParameters networkPortGetParameters;
      virDrvNetworkPortDelete networkPortDelete;
      virDrvNetworkListAllPorts networkListAllPorts;
+    virDrvNetworkSetMetadata networkSetMetadata;
+    virDrvNetworkGetMetadata networkGetMetadata;
  };
diff --git a/src/libvirt-network.c b/src/libvirt-network.c
index 236dfe2f5d..2dd11cf205 100644
--- a/src/libvirt-network.c
+++ b/src/libvirt-network.c
@@ -1915,3 +1915,170 @@ virNetworkPortRef(virNetworkPortPtr port)
      virObjectRef(port);
      return 0;
  }
+
+
+/**
+ * virNetworkSetMetadata:
+ * @network: a network object
+ * @type: type of metadata, from virNetworkMetadataType
+ * @metadata: new metadata text
+ * @key: XML namespace key, or NULL
+ * @uri: XML namespace URI, or NULL
+ * @flags: bitwise-OR of virNetworkUpdateFlags
+ *
+ * Sets the appropriate network element given by @type to the
+ * value of @metadata.  A @type of VIR_NETWORK_METADATA_DESCRIPTION
+ * is free-form text; VIR_NETWORK_METADATA_TITLE is free-form, but no
+ * newlines are permitted, and should be short (although the length is
+ * not enforced). For these two options @key and @uri are irrelevant and
+ * must be set to NULL.
+ *
+ * For type VIR_NETWORK_METADATA_ELEMENT @metadata must be well-formed
+ * XML belonging to namespace defined by @uri with local name @key.
+ *
+ * Passing NULL for @metadata says to remove that element from the
+ * network XML (passing the empty string leaves the element present).
+ *
+ * The resulting metadata will be present in virNetworkGetXMLDesc(),
+ * as well as quick access through virNetworkGetMetadata().
+ *
+ * @flags controls whether the live network state, persistent 
configuration,
+ * or both will be modified.
+ *
+ * Returns 0 on success, -1 in case of failure.
+ *
+ * Since: 9.6.0
+ */
+int
+virNetworkSetMetadata(virNetworkPtr network,
+                      int type,
+                      const char *metadata,
+                      const char *key,
+                      const char *uri,
+                      unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DEBUG("network=%p, type=%d, metadata='%s', key='%s', uri='%s', 
flags=0x%x",
+              network, type, NULLSTR(metadata), NULLSTR(key), NULLSTR(uri),
+              flags);
+
+    virResetLastError();
+
+    virCheckNetworkReturn(network, -1);
+    conn = network->conn;
+
+    virCheckReadOnlyGoto(conn->flags, error);
+
+    switch (type) {
+    case VIR_NETWORK_METADATA_TITLE:
+        if (metadata && strchr(metadata, '\n')) {
+            virReportInvalidArg(metadata, "%s",
+                                _("metadata title can't contain "
+                                  "newlines"));
+            goto error;
+        }
+        G_GNUC_FALLTHROUGH;
+    case VIR_NETWORK_METADATA_DESCRIPTION:
+        virCheckNullArgGoto(uri, error);
+        virCheckNullArgGoto(key, error);
+        break;
+    case VIR_NETWORK_METADATA_ELEMENT:
+        virCheckNonNullArgGoto(uri, error);
+        if (metadata)
+            virCheckNonNullArgGoto(key, error);
+        break;
+    default:
+        /* For future expansion */
+        break;
+    }
+
+    if (conn->networkDriver->networkSetMetadata) {
+        int ret;
+        ret = conn->networkDriver->networkSetMetadata(network, type, 
metadata, key, uri,
+                                                      flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+
+ error:
+    virDispatchError(network->conn);
+    return -1;
+}
+
+
+/**
+ * virNetworkGetMetadata:
+ * @network: a network object
+ * @type: type of metadata, from virNetworkMetadataType
+ * @uri: XML namespace identifier
+ * @flags: bitwise-OR of virNetworkUpdateFlags
+ *
+ * Retrieves the appropriate network element given by @type.
+ * If VIR_NETWORK_METADATA_ELEMENT is requested parameter @uri
+ * must be set to the name of the namespace the requested elements
+ * belong to, otherwise must be NULL.
+ *
+ * If an element of the network XML is not present, the resulting
+ * error will be VIR_ERR_NO_NETWORK_METADATA.  This method forms
+ * a shortcut for seeing information from virNetworkSetMetadata()
+ * without having to go through virNetworkGetXMLDesc().
+ *
+ * @flags controls whether the live network state or persistent
+ * configuration will be queried.
+ *
+ * Returns the metadata string on success (caller must free),
+ * or NULL in case of failure.
+ *
+ * Since: 9.6.0
+ */
+char *
+virNetworkGetMetadata(virNetworkPtr network,
+                      int type,
+                      const char *uri,
+                      unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DEBUG("network=%p, type=%d, uri='%s', flags=0x%x",
+               network, type, NULLSTR(uri), flags);
+
+    virResetLastError();
+
+    virCheckNetworkReturn(network, NULL);
+
+    VIR_EXCLUSIVE_FLAGS_GOTO(VIR_NETWORK_UPDATE_AFFECT_LIVE,
+                             VIR_NETWORK_UPDATE_AFFECT_CONFIG,
+                             error);
+
+    switch (type) {
+    case VIR_NETWORK_METADATA_TITLE:
+    case VIR_NETWORK_METADATA_DESCRIPTION:
+        virCheckNullArgGoto(uri, error);
+        break;
+    case VIR_NETWORK_METADATA_ELEMENT:
+        virCheckNonNullArgGoto(uri, error);
+        break;
+    default:
+        /* For future expansion */
+        break;
+    }
+
+    conn = network->conn;
+
+    if (conn->networkDriver->networkGetMetadata) {
+        char *ret;
+        if (!(ret = conn->networkDriver->networkGetMetadata(network, 
type, uri, flags)))
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+
+ error:
+    virDispatchError(network->conn);
+    return NULL;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 80742f268e..4523700a0f 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -932,4 +932,10 @@ LIBVIRT_9.0.0 {
          virDomainFDAssociate;
  } LIBVIRT_8.5.0;

+LIBVIRT_9.6.0 {
+    global:
+        virNetworkGetMetadata;
+        virNetworkSetMetadata;
+} LIBVIRT_9.0.0;
+
  # .... define new API here using predicted next version number ....
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 65ec239fb7..4e277f668a 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -8160,6 +8160,8 @@ static virNetworkDriver network_driver = {
      .networkPortSetParameters = remoteNetworkPortSetParameters, /* 
5.5.0 */
      .networkPortGetParameters = remoteNetworkPortGetParameters, /* 
5.5.0 */
      .networkPortDelete = remoteNetworkPortDelete, /* 5.5.0 */
+    .networkSetMetadata = remoteNetworkSetMetadata, /* 9.6.0 */
+    .networkGetMetadata = remoteNetworkGetMetadata, /* 9.6.0 */
  };

  static virInterfaceDriver interface_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 5d86a51116..7ff059e393 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -3323,6 +3323,26 @@ struct remote_network_event_lifecycle_msg {
      int detail;
  };

+struct remote_network_set_metadata_args {
+    remote_nonnull_network network;
+    int type;
+    remote_string metadata;
+    remote_string key;
+    remote_string uri;
+    unsigned int flags;
+};
+
+struct remote_network_get_metadata_args {
+    remote_nonnull_network network;
+    int type;
+    remote_string uri;
+    unsigned int flags;
+};
+
+struct remote_network_get_metadata_ret {
+    remote_nonnull_string metadata;
+};
+
  struct remote_connect_storage_pool_event_register_any_args {
      int eventID;
      remote_storage_pool pool;
@@ -6974,5 +6994,19 @@ enum remote_procedure {
       * @generate: none
       * @acl: domain:write
       */
-    REMOTE_PROC_DOMAIN_FD_ASSOCIATE = 443
+    REMOTE_PROC_DOMAIN_FD_ASSOCIATE = 443,
+
+    /**
+     * @generate: both
+     * @acl: network:write
+     * @acl: 
network:save:!VIR_NETWORK_UPDATE_AFFECT_CONFIG|VIR_NETWORK_UPDATE_AFFECT_LIVE
+     * @acl: network:save:VIR_NETWORK_UPDATE_AFFECT_CONFIG
+     */
+    REMOTE_PROC_NETWORK_SET_METADATA = 444,
+
+    /**
+     * @generate: both
+     * @acl: network:read
+     */
+    REMOTE_PROC_NETWORK_GET_METADATA = 445
  };
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 3c6c230a16..c07e0af1e6 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -2687,6 +2687,23 @@ struct remote_network_event_lifecycle_msg {
          int                        event;
          int                        detail;
  };
+struct remote_network_set_metadata_args {
+        remote_nonnull_network     network;
+        int                        type;
+        remote_string              metadata;
+        remote_string              key;
+        remote_string              uri;
+        u_int                      flags;
+};
+struct remote_network_get_metadata_args {
+        remote_nonnull_network     network;
+        int                        type;
+        remote_string              uri;
+        u_int                      flags;
+};
+struct remote_network_get_metadata_ret {
+        remote_nonnull_string      metadata;
+};
  struct remote_connect_storage_pool_event_register_any_args {
          int                        eventID;
          remote_storage_pool        pool;
@@ -3717,4 +3734,6 @@ enum remote_procedure {
          REMOTE_PROC_DOMAIN_RESTORE_PARAMS = 441,
          REMOTE_PROC_DOMAIN_ABORT_JOB_FLAGS = 442,
          REMOTE_PROC_DOMAIN_FD_ASSOCIATE = 443,
+        REMOTE_PROC_NETWORK_SET_METADATA = 444,
+        REMOTE_PROC_NETWORK_GET_METADATA = 445,
  };
diff --git a/src/util/virerror.c b/src/util/virerror.c
index 453f19514e..227a182417 100644
--- a/src/util/virerror.c
+++ b/src/util/virerror.c
@@ -1287,6 +1287,9 @@ static const virErrorMsgTuple virErrorMsgStrings[] = {
      [VIR_ERR_MULTIPLE_DOMAINS] = {
          N_("multiple matching domains found"),
          N_("multiple matching domains found: %1$s") },
+    [VIR_ERR_NO_NETWORK_METADATA] = {
+        N_("metadata not found"),
+        N_("metadata not found: %1$s") },
  };

  G_STATIC_ASSERT(G_N_ELEMENTS(virErrorMsgStrings) == VIR_ERR_NUMBER_LAST);
-- 
2.41.0