[libvirt] [PATCH] Allow custom metadata in network configuration XML

Brnadon Bennett bbennett at fb.com
Wed Jun 22 22:05:50 UTC 2016


From: Brandon Bennett <bbennett at fb.com>

    This replicates the metadata field found in the domain configuration
    and adds it to the network configuration XML.
---
 docs/formatnetwork.html.in           | 13 +++++++++++++
 docs/schemas/basictypes.rng          | 23 +++++++++++++++++++++++
 docs/schemas/domaincommon.rng        | 23 -----------------------
 docs/schemas/network.rng             |  5 +++++
 src/conf/network_conf.c              | 35 ++++++++++++++++++++++++++++++++++-
 src/conf/network_conf.h              |  3 +++
 tests/networkxml2xmlin/metadata.xml  | 10 ++++++++++
 tests/networkxml2xmlout/metadata.xml | 10 ++++++++++
 tests/networkxml2xmltest.c           |  1 +
 9 files changed, 99 insertions(+), 24 deletions(-)
 create mode 100644 tests/networkxml2xmlin/metadata.xml
 create mode 100644 tests/networkxml2xmlout/metadata.xml

diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index 1cea931..15ebf0c 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -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 1.3.6</span></dd>
       <dt><code>ipv6</code></dt>
       <dd>When set to <code>yes</code>, the optional parameter
         <code>ipv6</code> enables
@@ -73,6 +83,9 @@
         override the setting in the network.</dd>
     </dl>

++
+
+
     <h3><a name="elementsConnect">Connectivity</a></h3>

     <p>
diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng
index 83fd4ec..474ad77 100644
--- a/docs/schemas/basictypes.rng
+++ b/docs/schemas/basictypes.rng
@@ -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>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 162c2e0..78eb3f5 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -5338,29 +5338,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
     -->
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index 4edb6eb..b67a5ea 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -37,6 +37,11 @@
           <text/>
         </element>

+        <!-- <metadata> element -->
+        <optional>
+          <ref name="metadata"/>
+        </optional>
+
         <!-- <uuid> element -->
         <optional>
           <element name="uuid"><ref name="UUID"/></element>
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 02b8cd7..4239c32 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -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;
@@ -2388,8 +2392,12 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
         }
         break;
     }
-
     VIR_FREE(stp);
+
+    /* Extract custom metadata */
+    if ((metadataNode = virXPathNode("./metadata[1]", ctxt)) != NULL)
+        def->metadata = xmlCopyNode(metadataNode, 1);
+
     ctxt->node = save;
     return def;

@@ -2412,12 +2420,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 +2746,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)
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 0d34dfe..4481f60 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -253,6 +253,9 @@ struct _virNetworkDef {
     virNetDevBandwidthPtr bandwidth;
     virNetDevVlan vlan;
     int trustGuestRxFilters; /* enum virTristateBool */
+
+    /* Application-specific custom metadata */
+    xmlNodePtr metadata;
 };

 typedef struct _virNetworkObj virNetworkObj;
diff --git a/tests/networkxml2xmlin/metadata.xml b/tests/networkxml2xmlin/metadata.xml
new file mode 100644
index 0000000..c075f93
--- /dev/null
+++ b/tests/networkxml2xmlin/metadata.xml
@@ -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>
diff --git a/tests/networkxml2xmlout/metadata.xml b/tests/networkxml2xmlout/metadata.xml
new file mode 100644
index 0000000..a9364ab
--- /dev/null
+++ b/tests/networkxml2xmlout/metadata.xml
@@ -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>
diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c
index d65f6aa..2a2c348 100644
--- a/tests/networkxml2xmltest.c
+++ b/tests/networkxml2xmltest.c
@@ -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;
 }
--
2.7.4




More information about the libvir-list mailing list