Deepak C Shetty <deepakcs@linux.vnet.ibm.com>
Martin Kletzander <mkletzan@redhat.com>
Laszlo Ersek <lersek@redhat.com>
+ Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
[....send patches to get your name here....]
sub-element <code>label</code> are supported.
</p>
+ <h3><a name="customMetadata">Custom metadata</a></h3>
+
+<pre>
+ ...
+ <metadata>
+ <app1:foo xmlns:app1="http://app1.org/app1/">..</app1:foo>
+ <app2:bar xmlns:app2="http://app1.org/app2/">..</app2:bar>
+ </metadata>
+ ...</pre>
+
+ <dl>
+ <dt><code>metadata</code></dt>
+ <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 0.9.10</span></dd>
+ </dl>
+
<h2><a name="examples">Example configs</a></h2>
<p>
<optional>
<ref name="description"/>
</optional>
+ <optional>
+ <ref name="metadata"/>
+ </optional>
<optional>
<ref name="cpu"/>
</optional>
</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
if (def->namespaceData && def->ns.free)
(def->ns.free)(def->namespaceData);
+ xmlFreeNode(def->metadata);
+
VIR_FREE(def);
}
def->os.smbios_mode = VIR_DOMAIN_SMBIOS_NONE; /* not present */
}
+ /* Extract custom metadata */
+ if ((node = virXPathNode("./metadata[1]", ctxt)) != NULL) {
+ def->metadata = xmlCopyNode(node, 1);
+ }
+
/* we have to make a copy of all of the callback pointers here since
* we won't have the virCaps structure available during free
*/
{
xmlDocPtr xml;
virDomainDefPtr def = NULL;
+ int keepBlanksDefault = xmlKeepBlanksDefault(0);
if ((xml = virXMLParse(filename, xmlStr, _("(domain_definition)")))) {
def = virDomainDefParseNode(caps, xml, xmlDocGetRootElement(xml),
xmlFreeDoc(xml);
}
+ xmlKeepBlanksDefault(keepBlanksDefault);
return def;
}
{
xmlDocPtr xml;
virDomainObjPtr obj = NULL;
+ int keepBlanksDefault = xmlKeepBlanksDefault(0);
if ((xml = virXMLParseFile(filename))) {
obj = virDomainObjParseNode(caps, xml,
xmlFreeDoc(xml);
}
+ xmlKeepBlanksDefault(keepBlanksDefault);
return obj;
}
goto cleanup;
}
+ /* Custom metadata comes at the end */
+ 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, 1) < 0) {
+ xmlBufferFree(xmlbuf);
+ xmlIndentTreeOutput = oldIndentTreeOutput;
+ goto cleanup;
+ }
+ virBufferAsprintf(buf, " %s\n", (char *) xmlBufferContent(xmlbuf));
+ xmlBufferFree(xmlbuf);
+ xmlIndentTreeOutput = oldIndentTreeOutput;
+ }
+
virBufferAddLit(buf, "</domain>\n");
if (virBufferError(buf))
struct timeval tv;
int active;
char *tmp;
+ int keepBlanksDefault = xmlKeepBlanksDefault(0);
xml = virXMLParseCtxt(NULL, xmlStr, _("(domain_snapshot)"), &ctxt);
if (!xml) {
+ xmlKeepBlanksDefault(keepBlanksDefault);
return NULL;
}
+ xmlKeepBlanksDefault(keepBlanksDefault);
if (VIR_ALLOC(def) < 0) {
virReportOOMError();
void *namespaceData;
virDomainXMLNamespace ns;
+
+ /* Application-specific custom metadata */
+ xmlNodePtr metadata;
};
enum virDomainTaintFlags {
--- /dev/null
+<domainsnapshot>
+ <name>my snap name</name>
+ <description>!@#$%^</description>
+ <state>running</state>
+ <parent>
+ <name>earlier_snap</name>
+ </parent>
+ <creationTime>1272917631</creationTime>
+ <domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219100</memory>
+ <currentMemory>219100</currentMemory>
+ <vcpu cpuset='1-4,8-20,525'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' unit='0'/>
+ </disk>
+ <controller type='ide' index='0'/>
+ <memballoon model='virtio'/>
+ </devices>
+ <metadata>
+ <app1:foo xmlns:app1="http://foo.org/">fooish</app1:foo>
+ <app2:bar xmlns:app2="http://bar.com/" maman="baz">barish</app2:bar>
+ </metadata>
+ </domain>
+</domainsnapshot>
DO_TEST("noparent_nodescription_noactive", NULL, 0);
DO_TEST("noparent_nodescription", NULL, 1);
DO_TEST("noparent", "9d37b878-a7cc-9f9a-b78f-49b3abad25a8", 0);
+ DO_TEST("metadata", "c7a5fdbd-edaf-9455-926a-d65c16db1809", 0);
virCapabilitiesFree(driver.caps);
--- /dev/null
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \
+pc -m 214 -smp 1 -name QEMUGuest1 -nographic -monitor unix:/tmp/test-monitor,\
+server,nowait -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial \
+none -parallel none -usb
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219100</memory>
+ <currentMemory>219100</currentMemory>
+ <vcpu cpuset='1-4,8-20,525'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' unit='0'/>
+ </disk>
+ <controller type='ide' index='0'/>
+ <memballoon model='virtio'/>
+ </devices>
+ <!-- intentional mis-indentation -->
+ <metadata>
+ <app1:foo xmlns:app1="http://foo.org/">fooish</app1:foo>
+ <app2:bar xmlns:app2="http://bar.com/" maman="baz">barish</app2:bar>
+ </metadata>
+</domain>
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219100</memory>
+ <currentMemory>219100</currentMemory>
+ <vcpu cpuset='1-4,8-20,525'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' unit='0'/>
+ </disk>
+ <controller type='ide' index='0'/>
+ <memballoon model='virtio'/>
+ </devices>
+ <metadata>
+ <app1:foo xmlns:app1="http://foo.org/">fooish</app1:foo>
+ <app2:bar xmlns:app2="http://bar.com/" maman="baz">barish</app2:bar>
+ </metadata>
+</domain>
DO_TEST_DIFFERENT("graphics-listen-network2");
DO_TEST_DIFFERENT("graphics-spice-timeout");
+ DO_TEST_DIFFERENT("metadata");
+
virCapabilitiesFree(driver.caps);
return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);