- The definition of struct virNetworkObj has been moved from
virnetworkobj.c to its header as it was needed by network_event.h.
- Added functions to parse and save the XML along with helper functions
that resolve the live/persistent state of the network.
Signed-off-by: K Shiva <shiva_kr@riseup.net>
---
src/conf/network_conf.c | 3 +
src/conf/network_conf.h | 2 +
src/conf/virnetworkobj.c | 347 ++++++++++++++++++++++++++++++++++++---
src/conf/virnetworkobj.h | 56 +++++++
4 files changed, 386 insertions(+), 22 deletions(-)
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 73788b6d87..84952db041 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -2546,6 +2546,9 @@ virNetworkSaveXML(const char *configDir,
char uuidstr[VIR_UUID_STRING_BUFLEN];
g_autofree char *configFile = NULL;
+ if (!configDir)
+ return 0;
+
if ((configFile = virNetworkConfigFile(configDir, def->name)) == NULL)
return -1;
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 2b2e9d15f0..5a1bdb1284 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -249,6 +249,8 @@ struct _virNetworkDef {
unsigned char uuid[VIR_UUID_BUFLEN];
bool uuid_specified;
char *name;
+ char *title;
+ char *description;
int connections; /* # of guest interfaces connected to this network */
char *bridge; /* Name of bridge device */
diff --git a/src/conf/virnetworkobj.c b/src/conf/virnetworkobj.c
index b8b86da06f..82f90937bc 100644
--- a/src/conf/virnetworkobj.c
+++ b/src/conf/virnetworkobj.c
@@ -39,28 +39,6 @@ VIR_LOG_INIT("conf.virnetworkobj");
* that big. */
#define INIT_CLASS_ID_BITMAP_SIZE (1<<4)
-struct _virNetworkObj {
- virObjectLockable parent;
-
- pid_t dnsmasqPid;
- bool active;
- bool autostart;
- bool persistent;
-
- virNetworkDef *def; /* The current definition */
- virNetworkDef *newDef; /* New definition to activate at shutdown */
-
- virBitmap *classIdMap; /* bitmap of class IDs for QoS */
- unsigned long long floor_sum; /* sum of all 'floor'-s of attached NICs */
-
- unsigned int taint;
-
- /* Immutable pointer, self locking APIs */
- virMacMap *macmap;
-
- GHashTable *ports; /* uuid -> virNetworkPortDef **/
-};
-
struct _virNetworkObjList {
virObjectRWLockable parent;
@@ -1822,3 +1800,328 @@ virNetworkObjLoadAllPorts(virNetworkObj *net,
return 0;
}
+
+
+/**
+ * virNetworkObjUpdateModificationImpact:
+ *
+ * @net: network object
+ * @flags: flags to update the modification impact on
+ *
+ * Resolves virNetworkUpdateFlags in @flags so that they correctly
+ * apply to the actual state of @net. @flags may be modified after call to this
+ * function.
+ *
+ * Returns 0 on success if @flags point to a valid combination for @net or -1 on
+ * error.
+ */
+int
+virNetworkObjUpdateModificationImpact(virNetworkObj *net,
+ unsigned int *flags)
+{
+ bool isActive = virNetworkObjIsActive(net);
+
+ if ((*flags & (VIR_NETWORK_UPDATE_AFFECT_LIVE | VIR_NETWORK_UPDATE_AFFECT_CONFIG)) ==
+ VIR_NETWORK_UPDATE_AFFECT_CURRENT) {
+ if (isActive)
+ *flags |= VIR_NETWORK_UPDATE_AFFECT_LIVE;
+ else
+ *flags |= VIR_NETWORK_UPDATE_AFFECT_CONFIG;
+ }
+
+ if (!isActive && (*flags & VIR_NETWORK_UPDATE_AFFECT_LIVE)) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("network is not running"));
+ return -1;
+ }
+
+ if (!net->persistent && (*flags & VIR_NETWORK_UPDATE_AFFECT_CONFIG)) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("transient networks do not have any "
+ "persistent config"));
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/**
+ * virNetworkObjGetDefs:
+ *
+ * @net: network object
+ * @flags: for virNetworkUpdateFlags
+ * @liveDef: Set the pointer to the live definition of @net.
+ * @persDef: Set the pointer to the config definition of @net.
+ *
+ * Helper function to resolve @flags and retrieve correct network pointer
+ * objects. This function should be used only when the network driver
+ * creates net->newDef once the network has started.
+ *
+ * If @liveDef or @persDef are set it implies that @flags request modification
+ * thereof.
+ *
+ * Returns 0 on success and sets @liveDef and @persDef; -1 if @flags are
+ * inappropriate.
+ */
+int
+virNetworkObjGetDefs(virNetworkObj *net,
+ unsigned int flags,
+ virNetworkDef **liveDef,
+ virNetworkDef **persDef)
+{
+ if (liveDef)
+ *liveDef = NULL;
+
+ if (persDef)
+ *persDef = NULL;
+
+ if (virNetworkObjUpdateModificationImpact(net, &flags) < 0)
+ return -1;
+
+ if (virNetworkObjIsActive(net)) {
+ if (liveDef && (flags & VIR_NETWORK_UPDATE_AFFECT_LIVE))
+ *liveDef = net->def;
+
+ if (persDef && (flags & VIR_NETWORK_UPDATE_AFFECT_CONFIG))
+ *persDef = net->newDef;
+ } else {
+ if (persDef)
+ *persDef = net->def;
+ }
+
+ return 0;
+}
+
+
+/**
+ * virNetworkObjGetOneDefState:
+ *
+ * @net: Network object
+ * @flags: for virNetworkUpdateFlags
+ * @live: set to true if live config was returned (may be omitted)
+ *
+ * Helper function to resolve @flags and return the correct network pointer
+ * object. This function returns one of @net->def or @net->persistentDef
+ * according to @flags. @live is set to true if the live net config will be
+ * returned. This helper should be used only in APIs that guarantee
+ * that @flags contains exactly one of VIR_NETWORK_UPDATE_AFFECT_LIVE or
+ * VIR_NETWORK_UPDATE_AFFECT_CONFIG and not both.
+ *
+ * Returns the correct definition pointer or NULL on error.
+ */
+virNetworkDef *
+virNetworkObjGetOneDefState(virNetworkObj *net,
+ unsigned int flags,
+ bool *live)
+{
+ if (flags & VIR_NETWORK_UPDATE_AFFECT_LIVE &&
+ flags & VIR_NETWORK_UPDATE_AFFECT_CONFIG) {
+ virReportInvalidArg(flags, "%s",
+ _("Flags 'VIR_NETWORK_UPDATE_AFFECT_LIVE' and "
+ "'VIR_NETWORK_UPDATE_AFFECT_CONFIG' are mutually "
+ "exclusive"));
+ return NULL;
+ }
+
+ if (virNetworkObjUpdateModificationImpact(net, &flags) < 0)
+ return NULL;
+
+ if (live)
+ *live = flags & VIR_NETWORK_UPDATE_AFFECT_LIVE;
+
+ if (virNetworkObjIsActive(net) && flags & VIR_NETWORK_UPDATE_AFFECT_CONFIG)
+ return net->newDef;
+
+ return net->def;
+}
+
+
+/**
+ * virNetworkObjGetOneDef:
+ *
+ * @net: Network object
+ * @flags: for virNetworkUpdateFlags
+ *
+ * Helper function to resolve @flags and return the correct network pointer
+ * object. This function returns one of @net->def or @net->persistentDef
+ * according to @flags. This helper should be used only in APIs that guarantee
+ * that @flags contains exactly one of VIR_NETWORK_UPDATE_AFFECT_LIVE or
+ * VIR_NETWORK_UPDATE_AFFECT_CONFIG and not both.
+ *
+ * Returns the correct definition pointer or NULL on error.
+ */
+virNetworkDef *
+virNetworkObjGetOneDef(virNetworkObj *net,
+ unsigned int flags)
+{
+ return virNetworkObjGetOneDefState(net, flags, NULL);
+}
+
+
+char *
+virNetworkObjGetMetadata(virNetworkObj *net,
+ int type,
+ const char *uri,
+ unsigned int flags)
+{
+ virNetworkDef *def;
+ char *ret = NULL;
+
+ virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
+ VIR_NETWORK_UPDATE_AFFECT_CONFIG, NULL);
+
+ if (type >= VIR_NETWORK_METADATA_LAST) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("unknown metadata type '%1$d'"), type);
+ return NULL;
+ }
+
+ if (!(def = virNetworkObjGetOneDef(net, flags)))
+ return NULL;
+
+ switch ((virNetworkMetadataType) type) {
+ case VIR_NETWORK_METADATA_DESCRIPTION:
+ ret = g_strdup(def->description);
+ break;
+
+ case VIR_NETWORK_METADATA_TITLE:
+ ret = g_strdup(def->title);
+ break;
+
+ case VIR_NETWORK_METADATA_ELEMENT:
+ if (!def->metadata)
+ break;
+
+ if (virXMLExtractNamespaceXML(def->metadata, uri, &ret) < 0)
+ return NULL;
+ break;
+
+ case VIR_NETWORK_METADATA_LAST:
+ break;
+ }
+
+ if (!ret)
+ virReportError(VIR_ERR_NO_NETWORK_METADATA, "%s",
+ _("Requested metadata element is not present"));
+
+ return ret;
+}
+
+
+static int
+virNetworkDefSetMetadata(virNetworkDef *def,
+ int type,
+ const char *metadata,
+ const char *key,
+ const char *uri)
+{
+ g_autoptr(xmlDoc) doc = NULL;
+ xmlNodePtr old;
+ g_autoptr(xmlNode) new = NULL;
+
+ if (type >= VIR_NETWORK_METADATA_LAST) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("unknown metadata type '%1$d'"), type);
+ return -1;
+ }
+
+ switch ((virNetworkMetadataType) type) {
+ case VIR_NETWORK_METADATA_DESCRIPTION:
+ g_clear_pointer(&def->description, g_free);
+
+ if (STRNEQ_NULLABLE(metadata, ""))
+ def->description = g_strdup(metadata);
+ break;
+
+ case VIR_NETWORK_METADATA_TITLE:
+ g_clear_pointer(&def->title, g_free);
+
+ if (STRNEQ_NULLABLE(metadata, ""))
+ def->title = g_strdup(metadata);
+ break;
+
+ case VIR_NETWORK_METADATA_ELEMENT:
+ if (metadata) {
+
+ /* parse and modify the xml from the user */
+ if (!(doc = virXMLParseStringCtxt(metadata, _("(metadata_xml)"), NULL)))
+ return -1;
+
+ if (virXMLInjectNamespace(doc->children, uri, key) < 0)
+ return -1;
+
+ /* create the root node if needed */
+ if (!def->metadata)
+ def->metadata = virXMLNewNode(NULL, "metadata");
+
+ if (!(new = xmlCopyNode(doc->children, 1))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Failed to copy XML node"));
+ return -1;
+ }
+ }
+
+ /* remove possible other nodes sharing the namespace */
+ while ((old = virXMLFindChildNodeByNs(def->metadata, uri))) {
+ xmlUnlinkNode(old);
+ xmlFreeNode(old);
+ }
+
+ if (new) {
+ if (!(xmlAddChild(def->metadata, new))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to add metadata to XML document"));
+ return -1;
+ }
+ new = NULL;
+ }
+ break;
+
+ case VIR_NETWORK_METADATA_LAST:
+ break;
+ }
+
+ return 0;
+}
+
+
+int
+virNetworkObjSetMetadata(virNetworkObj *net,
+ int type,
+ const char *metadata,
+ const char *key,
+ const char *uri,
+ virNetworkXMLOption *xmlopt,
+ const char *stateDir,
+ const char *configDir,
+ unsigned int flags)
+{
+ virNetworkDef *def;
+ virNetworkDef *persistentDef;
+
+ virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
+ VIR_NETWORK_UPDATE_AFFECT_CONFIG, -1);
+
+ if (virNetworkObjGetDefs(net, flags, &def, &persistentDef) < 0)
+ return -1;
+
+ if (def) {
+ if (virNetworkDefSetMetadata(def, type, metadata, key, uri) < 0)
+ return -1;
+
+ if (virNetworkObjSaveStatus(stateDir, net, xmlopt) < 0)
+ return -1;
+ }
+
+ if (persistentDef) {
+ if (virNetworkDefSetMetadata(persistentDef, type, metadata, key,
+ uri) < 0)
+ return -1;
+
+ if (virNetworkSaveConfig(configDir, persistentDef, xmlopt) < 0)
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/conf/virnetworkobj.h b/src/conf/virnetworkobj.h
index 7d34fa3204..d17a43d7bb 100644
--- a/src/conf/virnetworkobj.h
+++ b/src/conf/virnetworkobj.h
@@ -26,6 +26,28 @@
typedef struct _virNetworkObj virNetworkObj;
+struct _virNetworkObj {
+ virObjectLockable parent;
+
+ pid_t dnsmasqPid;
+ bool active;
+ bool autostart;
+ bool persistent;
+
+ virNetworkDef *def; /* The current definition */
+ virNetworkDef *newDef; /* New definition to activate at shutdown */
+
+ virBitmap *classIdMap; /* bitmap of class IDs for QoS */
+ unsigned long long floor_sum; /* sum of all 'floor'-s of attached NICs */
+
+ unsigned int taint;
+
+ /* Immutable pointer, self locking APIs */
+ virMacMap *macmap;
+
+ GHashTable *ports; /* uuid -> virNetworkPortDef **/
+};
+
virNetworkObj *
virNetworkObjNew(void);
@@ -258,3 +280,37 @@ virNetworkObjListNumOfNetworks(virNetworkObjList *nets,
void
virNetworkObjListPrune(virNetworkObjList *nets,
unsigned int flags);
+
+int virNetworkObjUpdateModificationImpact(virNetworkObj *net,
+ unsigned int *flags);
+
+int
+virNetworkObjGetDefs(virNetworkObj *net,
+ unsigned int flags,
+ virNetworkDef **liveDef,
+ virNetworkDef **persDef);
+
+virNetworkDef *
+virNetworkObjGetOneDefState(virNetworkObj *net,
+ unsigned int flags,
+ bool *state);
+virNetworkDef *
+virNetworkObjGetOneDef(virNetworkObj *net,
+ unsigned int flags);
+
+char *
+virNetworkObjGetMetadata(virNetworkObj *network,
+ int type,
+ const char *uri,
+ unsigned int flags);
+
+int
+virNetworkObjSetMetadata(virNetworkObj *network,
+ int type,
+ const char *metadata,
+ const char *key,
+ const char *uri,
+ virNetworkXMLOption *xmlopt,
+ const char *stateDir,
+ const char *configDir,
+ unsigned int flags);
--
2.41.0
On 6/26/23 15:55, K Shiva wrote:
> - The definition of struct virNetworkObj has been moved from
> virnetworkobj.c to its header as it was needed by network_event.h.
> - Added functions to parse and save the XML along with helper functions
> that resolve the live/persistent state of the network.
>
> Signed-off-by: K Shiva <shiva_kr@riseup.net>
> ---
> src/conf/network_conf.c | 3 +
> src/conf/network_conf.h | 2 +
> src/conf/virnetworkobj.c | 347 ++++++++++++++++++++++++++++++++++++---
> src/conf/virnetworkobj.h | 56 +++++++
> 4 files changed, 386 insertions(+), 22 deletions(-)
>
> diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
> index 73788b6d87..84952db041 100644
> --- a/src/conf/network_conf.c
> +++ b/src/conf/network_conf.c
> @@ -2546,6 +2546,9 @@ virNetworkSaveXML(const char *configDir,
> char uuidstr[VIR_UUID_STRING_BUFLEN];
> g_autofree char *configFile = NULL;
>
> + if (!configDir)
> + return 0;
> +
> if ((configFile = virNetworkConfigFile(configDir, def->name)) == NULL)
> return -1;
>
This seems orthogonal to the rest of the changes. I'm not sure why it's
needed but definitely does not belong into this patch.
> diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
> index 2b2e9d15f0..5a1bdb1284 100644
> --- a/src/conf/network_conf.h
> +++ b/src/conf/network_conf.h
> @@ -249,6 +249,8 @@ struct _virNetworkDef {
> unsigned char uuid[VIR_UUID_BUFLEN];
> bool uuid_specified;
> char *name;
> + char *title;
> + char *description;
> int connections; /* # of guest interfaces connected to this network */
>
> char *bridge; /* Name of bridge device */
> diff --git a/src/conf/virnetworkobj.c b/src/conf/virnetworkobj.c
> index b8b86da06f..82f90937bc 100644
> --- a/src/conf/virnetworkobj.c
> +++ b/src/conf/virnetworkobj.c
> @@ -39,28 +39,6 @@ VIR_LOG_INIT("conf.virnetworkobj");
> * that big. */
> #define INIT_CLASS_ID_BITMAP_SIZE (1<<4)
>
> -struct _virNetworkObj {
> - virObjectLockable parent;
> -
> - pid_t dnsmasqPid;
> - bool active;
> - bool autostart;
> - bool persistent;
> -
> - virNetworkDef *def; /* The current definition */
> - virNetworkDef *newDef; /* New definition to activate at shutdown */
> -
> - virBitmap *classIdMap; /* bitmap of class IDs for QoS */
> - unsigned long long floor_sum; /* sum of all 'floor'-s of attached NICs */
> -
> - unsigned int taint;
> -
> - /* Immutable pointer, self locking APIs */
> - virMacMap *macmap;
> -
> - GHashTable *ports; /* uuid -> virNetworkPortDef **/
> -};
> -
> struct _virNetworkObjList {
> virObjectRWLockable parent;
>
> @@ -1822,3 +1800,328 @@ virNetworkObjLoadAllPorts(virNetworkObj *net,
>
> return 0;
> }
> +
> +
> +/**
> + * virNetworkObjUpdateModificationImpact:
> + *
> + * @net: network object
> + * @flags: flags to update the modification impact on
> + *
> + * Resolves virNetworkUpdateFlags in @flags so that they correctly
> + * apply to the actual state of @net. @flags may be modified after call to this
> + * function.
> + *
> + * Returns 0 on success if @flags point to a valid combination for @net or -1 on
> + * error.
> + */
> +int
> +virNetworkObjUpdateModificationImpact(virNetworkObj *net,
> + unsigned int *flags)
> +{
> + bool isActive = virNetworkObjIsActive(net);
> +
> + if ((*flags & (VIR_NETWORK_UPDATE_AFFECT_LIVE | VIR_NETWORK_UPDATE_AFFECT_CONFIG)) ==
> + VIR_NETWORK_UPDATE_AFFECT_CURRENT) {
> + if (isActive)
> + *flags |= VIR_NETWORK_UPDATE_AFFECT_LIVE;
> + else
> + *flags |= VIR_NETWORK_UPDATE_AFFECT_CONFIG;
> + }
> +
> + if (!isActive && (*flags & VIR_NETWORK_UPDATE_AFFECT_LIVE)) {
> + virReportError(VIR_ERR_OPERATION_INVALID, "%s",
> + _("network is not running"));
> + return -1;
> + }
> +
> + if (!net->persistent && (*flags & VIR_NETWORK_UPDATE_AFFECT_CONFIG)) {
> + virReportError(VIR_ERR_OPERATION_INVALID, "%s",
> + _("transient networks do not have any "
> + "persistent config"));
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +
> +/**
> + * virNetworkObjGetDefs:
> + *
> + * @net: network object
> + * @flags: for virNetworkUpdateFlags
> + * @liveDef: Set the pointer to the live definition of @net.
> + * @persDef: Set the pointer to the config definition of @net.
> + *
> + * Helper function to resolve @flags and retrieve correct network pointer
> + * objects. This function should be used only when the network driver
> + * creates net->newDef once the network has started.
> + *
> + * If @liveDef or @persDef are set it implies that @flags request modification
> + * thereof.
> + *
> + * Returns 0 on success and sets @liveDef and @persDef; -1 if @flags are
> + * inappropriate.
> + */
> +int
> +virNetworkObjGetDefs(virNetworkObj *net,
> + unsigned int flags,
> + virNetworkDef **liveDef,
> + virNetworkDef **persDef)
> +{
> + if (liveDef)
> + *liveDef = NULL;
> +
> + if (persDef)
> + *persDef = NULL;
> +
> + if (virNetworkObjUpdateModificationImpact(net, &flags) < 0)
> + return -1;
> +
> + if (virNetworkObjIsActive(net)) {
> + if (liveDef && (flags & VIR_NETWORK_UPDATE_AFFECT_LIVE))
> + *liveDef = net->def;
> +
> + if (persDef && (flags & VIR_NETWORK_UPDATE_AFFECT_CONFIG))
> + *persDef = net->newDef;
> + } else {
> + if (persDef)
> + *persDef = net->def;
> + }
> +
> + return 0;
> +}
> +
> +
> +/**
> + * virNetworkObjGetOneDefState:
> + *
> + * @net: Network object
> + * @flags: for virNetworkUpdateFlags
> + * @live: set to true if live config was returned (may be omitted)
> + *
> + * Helper function to resolve @flags and return the correct network pointer
> + * object. This function returns one of @net->def or @net->persistentDef
> + * according to @flags. @live is set to true if the live net config will be
> + * returned. This helper should be used only in APIs that guarantee
> + * that @flags contains exactly one of VIR_NETWORK_UPDATE_AFFECT_LIVE or
> + * VIR_NETWORK_UPDATE_AFFECT_CONFIG and not both.
> + *
> + * Returns the correct definition pointer or NULL on error.
> + */
> +virNetworkDef *
> +virNetworkObjGetOneDefState(virNetworkObj *net,
> + unsigned int flags,
> + bool *live)
> +{
> + if (flags & VIR_NETWORK_UPDATE_AFFECT_LIVE &&
> + flags & VIR_NETWORK_UPDATE_AFFECT_CONFIG) {
> + virReportInvalidArg(flags, "%s",
> + _("Flags 'VIR_NETWORK_UPDATE_AFFECT_LIVE' and "
> + "'VIR_NETWORK_UPDATE_AFFECT_CONFIG' are mutually "
> + "exclusive"));
> + return NULL;
> + }
> +
> + if (virNetworkObjUpdateModificationImpact(net, &flags) < 0)
> + return NULL;
> +
> + if (live)
> + *live = flags & VIR_NETWORK_UPDATE_AFFECT_LIVE;
> +
> + if (virNetworkObjIsActive(net) && flags & VIR_NETWORK_UPDATE_AFFECT_CONFIG)
> + return net->newDef;
> +
> + return net->def;
> +}
> +
> +
> +/**
> + * virNetworkObjGetOneDef:
> + *
> + * @net: Network object
> + * @flags: for virNetworkUpdateFlags
> + *
> + * Helper function to resolve @flags and return the correct network pointer
> + * object. This function returns one of @net->def or @net->persistentDef
> + * according to @flags. This helper should be used only in APIs that guarantee
> + * that @flags contains exactly one of VIR_NETWORK_UPDATE_AFFECT_LIVE or
> + * VIR_NETWORK_UPDATE_AFFECT_CONFIG and not both.
> + *
> + * Returns the correct definition pointer or NULL on error.
> + */
> +virNetworkDef *
> +virNetworkObjGetOneDef(virNetworkObj *net,
> + unsigned int flags)
> +{
> + return virNetworkObjGetOneDefState(net, flags, NULL);
> +}
> +
> +
> +char *
> +virNetworkObjGetMetadata(virNetworkObj *net,
> + int type,
> + const char *uri,
> + unsigned int flags)
> +{
> + virNetworkDef *def;
> + char *ret = NULL;
> +
> + virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
> + VIR_NETWORK_UPDATE_AFFECT_CONFIG, NULL);
> +
> + if (type >= VIR_NETWORK_METADATA_LAST) {
> + virReportError(VIR_ERR_INVALID_ARG,
> + _("unknown metadata type '%1$d'"), type);
> + return NULL;
> + }
> +
> + if (!(def = virNetworkObjGetOneDef(net, flags)))
> + return NULL;
> +
> + switch ((virNetworkMetadataType) type) {
> + case VIR_NETWORK_METADATA_DESCRIPTION:
> + ret = g_strdup(def->description);
> + break;
> +
> + case VIR_NETWORK_METADATA_TITLE:
> + ret = g_strdup(def->title);
> + break;
> +
> + case VIR_NETWORK_METADATA_ELEMENT:
> + if (!def->metadata)
> + break;
> +
> + if (virXMLExtractNamespaceXML(def->metadata, uri, &ret) < 0)
> + return NULL;
> + break;
> +
> + case VIR_NETWORK_METADATA_LAST:
> + break;
> + }
> +
> + if (!ret)
> + virReportError(VIR_ERR_NO_NETWORK_METADATA, "%s",
> + _("Requested metadata element is not present"));
> +
> + return ret;
> +}
> +
> +
> +static int
> +virNetworkDefSetMetadata(virNetworkDef *def,
> + int type,
> + const char *metadata,
> + const char *key,
> + const char *uri)
> +{
> + g_autoptr(xmlDoc) doc = NULL;
> + xmlNodePtr old;
> + g_autoptr(xmlNode) new = NULL;
> +
> + if (type >= VIR_NETWORK_METADATA_LAST) {
> + virReportError(VIR_ERR_INVALID_ARG,
> + _("unknown metadata type '%1$d'"), type);
> + return -1;
> + }
> +
> + switch ((virNetworkMetadataType) type) {
> + case VIR_NETWORK_METADATA_DESCRIPTION:
> + g_clear_pointer(&def->description, g_free);
> +
> + if (STRNEQ_NULLABLE(metadata, ""))
> + def->description = g_strdup(metadata);
> + break;
> +
> + case VIR_NETWORK_METADATA_TITLE:
> + g_clear_pointer(&def->title, g_free);
> +
> + if (STRNEQ_NULLABLE(metadata, ""))
> + def->title = g_strdup(metadata);
> + break;
> +
> + case VIR_NETWORK_METADATA_ELEMENT:
> + if (metadata) {
> +
> + /* parse and modify the xml from the user */
> + if (!(doc = virXMLParseStringCtxt(metadata, _("(metadata_xml)"), NULL)))
> + return -1;
> +
> + if (virXMLInjectNamespace(doc->children, uri, key) < 0)
> + return -1;
> +
> + /* create the root node if needed */
> + if (!def->metadata)
> + def->metadata = virXMLNewNode(NULL, "metadata");
> +
> + if (!(new = xmlCopyNode(doc->children, 1))) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Failed to copy XML node"));
> + return -1;
> + }
> + }
> +
> + /* remove possible other nodes sharing the namespace */
> + while ((old = virXMLFindChildNodeByNs(def->metadata, uri))) {
> + xmlUnlinkNode(old);
> + xmlFreeNode(old);
> + }
> +
> + if (new) {
> + if (!(xmlAddChild(def->metadata, new))) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("failed to add metadata to XML document"));
> + return -1;
> + }
> + new = NULL;
> + }
> + break;
> +
> + case VIR_NETWORK_METADATA_LAST:
> + break;
> + }
> +
> + return 0;
> +}
> +
> +
> +int
> +virNetworkObjSetMetadata(virNetworkObj *net,
> + int type,
> + const char *metadata,
> + const char *key,
> + const char *uri,
> + virNetworkXMLOption *xmlopt,
> + const char *stateDir,
> + const char *configDir,
> + unsigned int flags)
> +{
> + virNetworkDef *def;
> + virNetworkDef *persistentDef;
> +
> + virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
> + VIR_NETWORK_UPDATE_AFFECT_CONFIG, -1);
> +
> + if (virNetworkObjGetDefs(net, flags, &def, &persistentDef) < 0)
> + return -1;
> +
> + if (def) {
> + if (virNetworkDefSetMetadata(def, type, metadata, key, uri) < 0)
> + return -1;
> +
> + if (virNetworkObjSaveStatus(stateDir, net, xmlopt) < 0)
> + return -1;
> + }
> +
> + if (persistentDef) {
> + if (virNetworkDefSetMetadata(persistentDef, type, metadata, key,
> + uri) < 0)
> + return -1;
> +
> + if (virNetworkSaveConfig(configDir, persistentDef, xmlopt) < 0)
> + return -1;
> + }
> +
> + return 0;
> +}
> diff --git a/src/conf/virnetworkobj.h b/src/conf/virnetworkobj.h
> index 7d34fa3204..d17a43d7bb 100644
> --- a/src/conf/virnetworkobj.h
> +++ b/src/conf/virnetworkobj.h
> @@ -26,6 +26,28 @@
>
> typedef struct _virNetworkObj virNetworkObj;
>
> +struct _virNetworkObj {
> + virObjectLockable parent;
> +
> + pid_t dnsmasqPid;
> + bool active;
> + bool autostart;
> + bool persistent;
> +
> + virNetworkDef *def; /* The current definition */
> + virNetworkDef *newDef; /* New definition to activate at shutdown */
> +
> + virBitmap *classIdMap; /* bitmap of class IDs for QoS */
> + unsigned long long floor_sum; /* sum of all 'floor'-s of attached NICs */
> +
> + unsigned int taint;
> +
> + /* Immutable pointer, self locking APIs */
> + virMacMap *macmap;
> +
> + GHashTable *ports; /* uuid -> virNetworkPortDef **/
> +};
> +
No, the struct was hidden for a reason: we don't want the rest of the
code to fiddle with struct members directly but use so called getter and
setter functions (functions which get/set value of individual struct
members), e.g. virNetworkObjIsActive() / virNetworkObjSetActive(). This
way, code is more auditable, i.e. it's easy to see where a given struct
member is set. Not only that, but individual getters/setters might
perform additional tasks tied to the struct member, e.g. lock the object.
> virNetworkObj *
> virNetworkObjNew(void);
>
> @@ -258,3 +280,37 @@ virNetworkObjListNumOfNetworks(virNetworkObjList *nets,
> void
> virNetworkObjListPrune(virNetworkObjList *nets,
> unsigned int flags);
> +
> +int virNetworkObjUpdateModificationImpact(virNetworkObj *net,
> + unsigned int *flags);
> +
> +int
> +virNetworkObjGetDefs(virNetworkObj *net,
> + unsigned int flags,
> + virNetworkDef **liveDef,
> + virNetworkDef **persDef);
> +
> +virNetworkDef *
> +virNetworkObjGetOneDefState(virNetworkObj *net,
> + unsigned int flags,
> + bool *state);
> +virNetworkDef *
> +virNetworkObjGetOneDef(virNetworkObj *net,
> + unsigned int flags);
Neither of these ^^^ functions is called from outside of
virnetworkobj.c. What's the reason for their exposure?
> +
> +char *
> +virNetworkObjGetMetadata(virNetworkObj *network,
> + int type,
> + const char *uri,
> + unsigned int flags);
> +
> +int
> +virNetworkObjSetMetadata(virNetworkObj *network,
> + int type,
> + const char *metadata,
> + const char *key,
> + const char *uri,
> + virNetworkXMLOption *xmlopt,
> + const char *stateDir,
> + const char *configDir,
> + unsigned int flags);
BTW: this is where I stop my review, as these patches need to be split
differently.
Michal
© 2016 - 2026 Red Hat, Inc.