Allow custom metadata in network configuration XML

This replicates the metadata field found in the domain configuration
    and adds it to the network configuration XML.
This commit is contained in:
Brandon Bennett 2016-06-22 16:05:50 -06:00 committed by Laine Stump
parent b874f26b8b
commit 47a0866bce
9 changed files with 98 additions and 23 deletions

View File

@ -38,6 +38,10 @@
<network ipv6='yes' trustGuestRxFilters='no'>
<name>default</name>
<uuid>3e3fce45-4f53-4fa7-bb32-11f34168b82b</uuid>
<metadata>
<app1:foo xmlns:app1="http://app1.org/app1/">..</app1:foo>
<app2:bar xmlns:app2="http://app1.org/app2/">..</app2:bar>
</metadata>
...</pre>
<dl>
@ -54,6 +58,12 @@
The format must be RFC 4122 compliant, eg <code>3e3fce45-4f53-4fa7-bb32-11f34168b82b</code>.
If omitted when defining/creating a new network, a random
UUID is generated. <span class="since">Since 0.3.0</span></dd>
<dd>The <code>metadata</code> node can be used by applications to
store custom metadata in the form of XML nodes/trees. Applications
must use custom namespaces on their XML nodes/trees, with only
one top-level element per namespace (if the application needs
structure, they should have sub-elements to their namespace
element). <span class="since">Since 2.1.0</span></dd>
<dt><code>ipv6</code></dt>
<dd>When set to <code>yes</code>, the optional parameter
<code>ipv6</code> enables

View File

@ -495,4 +495,27 @@
</choice>
</define>
<define name="metadata">
<element name="metadata">
<zeroOrMore>
<ref name="customElement"/>
</zeroOrMore>
</element>
</define>
<define name="customElement">
<element>
<anyName/>
<zeroOrMore>
<choice>
<attribute>
<anyName/>
</attribute>
<text/>
<ref name="customElement"/>
</choice>
</zeroOrMore>
</element>
</define>
</grammar>

View File

@ -5322,29 +5322,6 @@
</element>
</define>
<define name="metadata">
<element name="metadata">
<zeroOrMore>
<ref name="customElement"/>
</zeroOrMore>
</element>
</define>
<define name="customElement">
<element>
<anyName/>
<zeroOrMore>
<choice>
<attribute>
<anyName/>
</attribute>
<text/>
<ref name="customElement"/>
</choice>
</zeroOrMore>
</element>
</define>
<!--
Type library
-->

View File

@ -37,6 +37,11 @@
<text/>
</element>
<!-- <metadata> element -->
<optional>
<ref name="metadata"/>
</optional>
<!-- <uuid> element -->
<optional>
<element name="uuid"><ref name="UUID"/></element>

View File

@ -419,6 +419,9 @@ virNetworkDefFree(virNetworkDefPtr def)
virNetDevBandwidthFree(def->bandwidth);
virNetDevVlanClear(&def->vlan);
xmlFreeNode(def->metadata);
VIR_FREE(def);
}
@ -2059,6 +2062,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
xmlNodePtr save = ctxt->node;
xmlNodePtr bandwidthNode = NULL;
xmlNodePtr vlanNode;
xmlNodePtr metadataNode = NULL;
if (VIR_ALLOC(def) < 0)
return NULL;
@ -2390,6 +2394,13 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
}
VIR_FREE(stp);
/* Extract custom metadata */
if ((metadataNode = virXPathNode("./metadata[1]", ctxt)) != NULL) {
def->metadata = xmlCopyNode(metadataNode, 1);
virXMLNodeSanitizeNamespaces(def->metadata);
}
ctxt->node = save;
return def;
@ -2412,12 +2423,14 @@ virNetworkDefParse(const char *xmlStr,
{
xmlDocPtr xml;
virNetworkDefPtr def = NULL;
int keepBlanksDefault = xmlKeepBlanksDefault(0);
if ((xml = virXMLParse(filename, xmlStr, _("(network_definition)")))) {
def = virNetworkDefParseNode(xml, xmlDocGetRootElement(xml));
xmlFreeDoc(xml);
}
xmlKeepBlanksDefault(keepBlanksDefault);
return def;
}
@ -2736,6 +2749,29 @@ virNetworkDefFormatBuf(virBufferPtr buf,
virUUIDFormat(uuid, uuidstr);
virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuidstr);
if (def->metadata) {
xmlBufferPtr xmlbuf;
int oldIndentTreeOutput = xmlIndentTreeOutput;
/* Indentation on output requires that we previously set
* xmlKeepBlanksDefault to 0 when parsing; also, libxml does 2
* spaces per level of indentation of intermediate elements,
* but no leading indentation before the starting element.
* Thankfully, libxml maps what looks like globals into
* thread-local uses, so we are thread-safe. */
xmlIndentTreeOutput = 1;
xmlbuf = xmlBufferCreate();
if (xmlNodeDump(xmlbuf, def->metadata->doc, def->metadata,
virBufferGetIndent(buf, false) / 2, 1) < 0) {
xmlBufferFree(xmlbuf);
xmlIndentTreeOutput = oldIndentTreeOutput;
goto error;
}
virBufferAsprintf(buf, "%s\n", (char *) xmlBufferContent(xmlbuf));
xmlBufferFree(xmlbuf);
xmlIndentTreeOutput = oldIndentTreeOutput;
}
if (def->forward.type != VIR_NETWORK_FORWARD_NONE) {
const char *dev = NULL;
if (!def->forward.npfs)

View File

@ -253,6 +253,9 @@ struct _virNetworkDef {
virNetDevBandwidthPtr bandwidth;
virNetDevVlan vlan;
int trustGuestRxFilters; /* enum virTristateBool */
/* Application-specific custom metadata */
xmlNodePtr metadata;
};
typedef struct _virNetworkObj virNetworkObj;

View File

@ -0,0 +1,10 @@
<network>
<name>host-bridge-net</name>
<uuid>81ff0d90-c91e-6742-64da-4a736edb9a8e</uuid>
<forward mode='bridge'/>
<bridge name='br0'/>
<metadata>
<app1:foo xmlns:app1="http://foo.org/">fooish</app1:foo>
<app2:bar xmlns:app2="http://bar.com/" maman="baz">barish</app2:bar>
</metadata>
</network>

View File

@ -0,0 +1,10 @@
<network>
<name>host-bridge-net</name>
<uuid>81ff0d90-c91e-6742-64da-4a736edb9a8e</uuid>
<metadata>
<app1:foo xmlns:app1="http://foo.org/">fooish</app1:foo>
<app2:bar xmlns:app2="http://bar.com/" maman="baz">barish</app2:bar>
</metadata>
<forward mode='bridge'/>
<bridge name='br0'/>
</network>

View File

@ -153,6 +153,7 @@ mymain(void)
DO_TEST("host-bridge-no-flood");
DO_TEST_PARSE_ERROR("hostdev-duplicate");
DO_TEST_PARSE_ERROR("passthrough-duplicate");
DO_TEST("metadata");
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}