|
|
c1c534 |
From 996dfd6322782e72583384381ffebf91ef1d3e27 Mon Sep 17 00:00:00 2001
|
|
|
c1c534 |
Message-Id: <996dfd6322782e72583384381ffebf91ef1d3e27@dist-git>
|
|
|
c1c534 |
From: Peter Krempa <pkrempa@redhat.com>
|
|
|
c1c534 |
Date: Thu, 14 Dec 2017 14:31:51 +0100
|
|
|
c1c534 |
Subject: [PATCH] conf: Add infrastructure for disk source private data XML
|
|
|
c1c534 |
|
|
|
c1c534 |
VM drivers may need to store additional private data to the status XML
|
|
|
c1c534 |
so that it can be restored after libvirtd restart. Since not everything
|
|
|
c1c534 |
is needed add a callback infrastructure, where VM drivers can add only
|
|
|
c1c534 |
stuff they need.
|
|
|
c1c534 |
|
|
|
c1c534 |
Note that the private data is formatted as a <privateData> sub-element
|
|
|
c1c534 |
of the <disk> or <backingStore> <source> sub-element. This is done since
|
|
|
c1c534 |
storing it out of band (in the VM private data) would require a complex
|
|
|
c1c534 |
matching process to allow to put the data into correct place.
|
|
|
c1c534 |
|
|
|
c1c534 |
(cherry picked from commit aed3d038a6565f3b0e916bdb004ca90b302b200d)
|
|
|
c1c534 |
|
|
|
c1c534 |
Conflicts:
|
|
|
c1c534 |
tests/qemublocktest.c: This file does not exist downstream yet.
|
|
|
c1c534 |
|
|
|
c1c534 |
https://bugzilla.redhat.com/show_bug.cgi?id=1523261
|
|
|
c1c534 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
c1c534 |
---
|
|
|
c1c534 |
src/conf/domain_conf.c | 136 ++++++++++++++++++++++++++++++++++----------
|
|
|
c1c534 |
src/conf/domain_conf.h | 17 +++++-
|
|
|
c1c534 |
src/conf/snapshot_conf.c | 18 +++---
|
|
|
c1c534 |
src/network/bridge_driver.c | 2 +-
|
|
|
c1c534 |
src/qemu/qemu_domain.c | 2 +-
|
|
|
c1c534 |
tests/virstoragetest.c | 2 +-
|
|
|
c1c534 |
6 files changed, 134 insertions(+), 43 deletions(-)
|
|
|
c1c534 |
|
|
|
c1c534 |
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
|
|
|
c1c534 |
index 2d54037b71..ad9c16a1e0 100644
|
|
|
c1c534 |
--- a/src/conf/domain_conf.c
|
|
|
c1c534 |
+++ b/src/conf/domain_conf.c
|
|
|
c1c534 |
@@ -8550,11 +8550,43 @@ virDomainDiskSourceEncryptionParse(xmlNodePtr node,
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
|
|
|
c1c534 |
+static int
|
|
|
c1c534 |
+virDomainDiskSourcePrivateDataParse(xmlXPathContextPtr ctxt,
|
|
|
c1c534 |
+ virStorageSourcePtr src,
|
|
|
c1c534 |
+ unsigned int flags,
|
|
|
c1c534 |
+ virDomainXMLOptionPtr xmlopt)
|
|
|
c1c534 |
+{
|
|
|
c1c534 |
+ xmlNodePtr saveNode = ctxt->node;
|
|
|
c1c534 |
+ xmlNodePtr node;
|
|
|
c1c534 |
+ int ret = -1;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (!(flags & VIR_DOMAIN_DEF_PARSE_STATUS) ||
|
|
|
c1c534 |
+ !xmlopt || !xmlopt->privateData.storageParse)
|
|
|
c1c534 |
+ return 0;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (!(node = virXPathNode("./privateData", ctxt)))
|
|
|
c1c534 |
+ return 0;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ ctxt->node = node;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (xmlopt->privateData.storageParse(ctxt, src) < 0)
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ ret = 0;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ cleanup:
|
|
|
c1c534 |
+ ctxt->node = saveNode;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ return ret;
|
|
|
c1c534 |
+}
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+
|
|
|
c1c534 |
int
|
|
|
c1c534 |
virDomainDiskSourceParse(xmlNodePtr node,
|
|
|
c1c534 |
xmlXPathContextPtr ctxt,
|
|
|
c1c534 |
virStorageSourcePtr src,
|
|
|
c1c534 |
- unsigned int flags)
|
|
|
c1c534 |
+ unsigned int flags,
|
|
|
c1c534 |
+ virDomainXMLOptionPtr xmlopt)
|
|
|
c1c534 |
{
|
|
|
c1c534 |
int ret = -1;
|
|
|
c1c534 |
xmlNodePtr saveNode = ctxt->node;
|
|
|
c1c534 |
@@ -8593,6 +8625,9 @@ virDomainDiskSourceParse(xmlNodePtr node,
|
|
|
c1c534 |
if (virDomainDiskSourceEncryptionParse(node, &src->encryption) < 0)
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
|
|
|
c1c534 |
+ if (virDomainDiskSourcePrivateDataParse(ctxt, src, flags, xmlopt) < 0)
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
/* People sometimes pass a bogus '' source path when they mean to omit the
|
|
|
c1c534 |
* source element completely (e.g. CDROM without media). This is just a
|
|
|
c1c534 |
* little compatibility check to help those broken apps */
|
|
|
c1c534 |
@@ -8610,7 +8645,8 @@ virDomainDiskSourceParse(xmlNodePtr node,
|
|
|
c1c534 |
static int
|
|
|
c1c534 |
virDomainDiskBackingStoreParse(xmlXPathContextPtr ctxt,
|
|
|
c1c534 |
virStorageSourcePtr src,
|
|
|
c1c534 |
- unsigned int flags)
|
|
|
c1c534 |
+ unsigned int flags,
|
|
|
c1c534 |
+ virDomainXMLOptionPtr xmlopt)
|
|
|
c1c534 |
{
|
|
|
c1c534 |
virStorageSourcePtr backingStore = NULL;
|
|
|
c1c534 |
xmlNodePtr save_ctxt = ctxt->node;
|
|
|
c1c534 |
@@ -8668,8 +8704,8 @@ virDomainDiskBackingStoreParse(xmlXPathContextPtr ctxt,
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
- if (virDomainDiskSourceParse(source, ctxt, backingStore, flags) < 0 ||
|
|
|
c1c534 |
- virDomainDiskBackingStoreParse(ctxt, backingStore, flags) < 0)
|
|
|
c1c534 |
+ if (virDomainDiskSourceParse(source, ctxt, backingStore, flags, xmlopt) < 0 ||
|
|
|
c1c534 |
+ virDomainDiskBackingStoreParse(ctxt, backingStore, flags, xmlopt) < 0)
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
|
|
|
c1c534 |
VIR_STEAL_PTR(src->backingStore, backingStore);
|
|
|
c1c534 |
@@ -8771,7 +8807,8 @@ static int
|
|
|
c1c534 |
virDomainDiskDefMirrorParse(virDomainDiskDefPtr def,
|
|
|
c1c534 |
xmlNodePtr cur,
|
|
|
c1c534 |
xmlXPathContextPtr ctxt,
|
|
|
c1c534 |
- unsigned int flags)
|
|
|
c1c534 |
+ unsigned int flags,
|
|
|
c1c534 |
+ virDomainXMLOptionPtr xmlopt)
|
|
|
c1c534 |
{
|
|
|
c1c534 |
xmlNodePtr mirrorNode;
|
|
|
c1c534 |
char *mirrorFormat = NULL;
|
|
|
c1c534 |
@@ -8809,7 +8846,8 @@ virDomainDiskDefMirrorParse(virDomainDiskDefPtr def,
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
- if (virDomainDiskSourceParse(mirrorNode, ctxt, def->mirror, flags) < 0)
|
|
|
c1c534 |
+ if (virDomainDiskSourceParse(mirrorNode, ctxt, def->mirror,
|
|
|
c1c534 |
+ flags, xmlopt) < 0)
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
} else {
|
|
|
c1c534 |
/* For back-compat reasons, we handle a file name
|
|
|
c1c534 |
@@ -9235,7 +9273,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
|
|
|
c1c534 |
if (!source && virXMLNodeNameEqual(cur, "source")) {
|
|
|
c1c534 |
sourceNode = cur;
|
|
|
c1c534 |
|
|
|
c1c534 |
- if (virDomainDiskSourceParse(cur, ctxt, def->src, flags) < 0)
|
|
|
c1c534 |
+ if (virDomainDiskSourceParse(cur, ctxt, def->src, flags, xmlopt) < 0)
|
|
|
c1c534 |
goto error;
|
|
|
c1c534 |
|
|
|
c1c534 |
/* If we've already found an <auth> as a child of <disk> and
|
|
|
c1c534 |
@@ -9316,7 +9354,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
|
|
|
c1c534 |
} else if (!def->mirror &&
|
|
|
c1c534 |
virXMLNodeNameEqual(cur, "mirror") &&
|
|
|
c1c534 |
!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE)) {
|
|
|
c1c534 |
- if (virDomainDiskDefMirrorParse(def, cur, ctxt, flags) < 0)
|
|
|
c1c534 |
+ if (virDomainDiskDefMirrorParse(def, cur, ctxt, flags, xmlopt) < 0)
|
|
|
c1c534 |
goto error;
|
|
|
c1c534 |
} else if (!authdef &&
|
|
|
c1c534 |
virXMLNodeNameEqual(cur, "auth")) {
|
|
|
c1c534 |
@@ -9587,7 +9625,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
|
|
|
c1c534 |
product = NULL;
|
|
|
c1c534 |
|
|
|
c1c534 |
if (!(flags & VIR_DOMAIN_DEF_PARSE_DISK_SOURCE)) {
|
|
|
c1c534 |
- if (virDomainDiskBackingStoreParse(ctxt, def->src, flags) < 0)
|
|
|
c1c534 |
+ if (virDomainDiskBackingStoreParse(ctxt, def->src, flags, xmlopt) < 0)
|
|
|
c1c534 |
goto error;
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
@@ -22349,12 +22387,43 @@ virDomainDiskSourceFormatNetwork(virBufferPtr attrBuf,
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
|
|
|
c1c534 |
+static int
|
|
|
c1c534 |
+virDomainDiskSourceFormatPrivateData(virBufferPtr buf,
|
|
|
c1c534 |
+ virStorageSourcePtr src,
|
|
|
c1c534 |
+ unsigned int flags,
|
|
|
c1c534 |
+ virDomainXMLOptionPtr xmlopt)
|
|
|
c1c534 |
+{
|
|
|
c1c534 |
+ virBuffer childBuf = VIR_BUFFER_INITIALIZER;
|
|
|
c1c534 |
+ int ret = -1;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (!(flags & VIR_DOMAIN_DEF_FORMAT_STATUS) ||
|
|
|
c1c534 |
+ !xmlopt || !xmlopt->privateData.storageFormat)
|
|
|
c1c534 |
+ return 0;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ virBufferSetChildIndent(&childBuf, buf);
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (xmlopt->privateData.storageFormat(src, &childBuf) < 0)
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (virXMLFormatElement(buf, "privateData", NULL, &childBuf) < 0)
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ ret = 0;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ cleanup:
|
|
|
c1c534 |
+ virBufferFreeAndReset(&childBuf);
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ return ret;
|
|
|
c1c534 |
+}
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+
|
|
|
c1c534 |
static int
|
|
|
c1c534 |
virDomainDiskSourceFormatInternal(virBufferPtr buf,
|
|
|
c1c534 |
virStorageSourcePtr src,
|
|
|
c1c534 |
int policy,
|
|
|
c1c534 |
unsigned int flags,
|
|
|
c1c534 |
- bool skipSeclabels)
|
|
|
c1c534 |
+ bool skipSeclabels,
|
|
|
c1c534 |
+ virDomainXMLOptionPtr xmlopt)
|
|
|
c1c534 |
{
|
|
|
c1c534 |
const char *startupPolicy = NULL;
|
|
|
c1c534 |
virBuffer attrBuf = VIR_BUFFER_INITIALIZER;
|
|
|
c1c534 |
@@ -22436,6 +22505,9 @@ virDomainDiskSourceFormatInternal(virBufferPtr buf,
|
|
|
c1c534 |
virStorageEncryptionFormat(&childBuf, src->encryption) < 0)
|
|
|
c1c534 |
return -1;
|
|
|
c1c534 |
|
|
|
c1c534 |
+ if (virDomainDiskSourceFormatPrivateData(&childBuf, src, flags, xmlopt) < 0)
|
|
|
c1c534 |
+ return -1;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
if (virXMLFormatElement(buf, "source", &attrBuf, &childBuf) < 0)
|
|
|
c1c534 |
goto error;
|
|
|
c1c534 |
}
|
|
|
c1c534 |
@@ -22453,15 +22525,18 @@ int
|
|
|
c1c534 |
virDomainDiskSourceFormat(virBufferPtr buf,
|
|
|
c1c534 |
virStorageSourcePtr src,
|
|
|
c1c534 |
int policy,
|
|
|
c1c534 |
- unsigned int flags)
|
|
|
c1c534 |
+ unsigned int flags,
|
|
|
c1c534 |
+ virDomainXMLOptionPtr xmlopt)
|
|
|
c1c534 |
{
|
|
|
c1c534 |
- return virDomainDiskSourceFormatInternal(buf, src, policy, flags, false);
|
|
|
c1c534 |
+ return virDomainDiskSourceFormatInternal(buf, src, policy, flags, false, xmlopt);
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
|
|
|
c1c534 |
static int
|
|
|
c1c534 |
virDomainDiskBackingStoreFormat(virBufferPtr buf,
|
|
|
c1c534 |
- virStorageSourcePtr backingStore)
|
|
|
c1c534 |
+ virStorageSourcePtr backingStore,
|
|
|
c1c534 |
+ virDomainXMLOptionPtr xmlopt,
|
|
|
c1c534 |
+ unsigned int flags)
|
|
|
c1c534 |
{
|
|
|
c1c534 |
const char *format;
|
|
|
c1c534 |
|
|
|
c1c534 |
@@ -22490,9 +22565,9 @@ virDomainDiskBackingStoreFormat(virBufferPtr buf,
|
|
|
c1c534 |
|
|
|
c1c534 |
virBufferAsprintf(buf, "<format type='%s'/>\n", format);
|
|
|
c1c534 |
/* We currently don't output seclabels for backing chain element */
|
|
|
c1c534 |
- if (virDomainDiskSourceFormatInternal(buf, backingStore, 0, 0, true) < 0 ||
|
|
|
c1c534 |
- virDomainDiskBackingStoreFormat(buf,
|
|
|
c1c534 |
- backingStore->backingStore) < 0)
|
|
|
c1c534 |
+ if (virDomainDiskSourceFormatInternal(buf, backingStore, 0, flags, true, xmlopt) < 0 ||
|
|
|
c1c534 |
+ virDomainDiskBackingStoreFormat(buf, backingStore->backingStore,
|
|
|
c1c534 |
+ xmlopt, flags) < 0)
|
|
|
c1c534 |
return -1;
|
|
|
c1c534 |
|
|
|
c1c534 |
virBufferAdjustIndent(buf, -2);
|
|
|
c1c534 |
@@ -22510,7 +22585,8 @@ virDomainDiskBackingStoreFormat(virBufferPtr buf,
|
|
|
c1c534 |
static int
|
|
|
c1c534 |
virDomainDiskDefFormat(virBufferPtr buf,
|
|
|
c1c534 |
virDomainDiskDefPtr def,
|
|
|
c1c534 |
- unsigned int flags)
|
|
|
c1c534 |
+ unsigned int flags,
|
|
|
c1c534 |
+ virDomainXMLOptionPtr xmlopt)
|
|
|
c1c534 |
{
|
|
|
c1c534 |
const char *type = virStorageTypeToString(def->src->type);
|
|
|
c1c534 |
const char *device = virDomainDiskDeviceTypeToString(def->device);
|
|
|
c1c534 |
@@ -22623,13 +22699,14 @@ virDomainDiskDefFormat(virBufferPtr buf,
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
if (virDomainDiskSourceFormat(buf, def->src, def->startupPolicy,
|
|
|
c1c534 |
- flags) < 0)
|
|
|
c1c534 |
+ flags, xmlopt) < 0)
|
|
|
c1c534 |
return -1;
|
|
|
c1c534 |
|
|
|
c1c534 |
/* Don't format backingStore to inactive XMLs until the code for
|
|
|
c1c534 |
* persistent storage of backing chains is ready. */
|
|
|
c1c534 |
if (!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE) &&
|
|
|
c1c534 |
- virDomainDiskBackingStoreFormat(buf, def->src->backingStore) < 0)
|
|
|
c1c534 |
+ virDomainDiskBackingStoreFormat(buf, def->src->backingStore,
|
|
|
c1c534 |
+ xmlopt, flags) < 0)
|
|
|
c1c534 |
return -1;
|
|
|
c1c534 |
|
|
|
c1c534 |
virBufferEscapeString(buf, "<backenddomain name='%s'/>\n", def->domain_name);
|
|
|
c1c534 |
@@ -22666,7 +22743,7 @@ virDomainDiskDefFormat(virBufferPtr buf,
|
|
|
c1c534 |
virBufferAddLit(buf, ">\n");
|
|
|
c1c534 |
virBufferAdjustIndent(buf, 2);
|
|
|
c1c534 |
virBufferEscapeString(buf, "<format type='%s'/>\n", formatStr);
|
|
|
c1c534 |
- if (virDomainDiskSourceFormat(buf, def->mirror, 0, 0) < 0)
|
|
|
c1c534 |
+ if (virDomainDiskSourceFormat(buf, def->mirror, 0, 0, xmlopt) < 0)
|
|
|
c1c534 |
return -1;
|
|
|
c1c534 |
virBufferAdjustIndent(buf, -2);
|
|
|
c1c534 |
virBufferAddLit(buf, "</mirror>\n");
|
|
|
c1c534 |
@@ -25897,7 +25974,8 @@ int
|
|
|
c1c534 |
virDomainDefFormatInternal(virDomainDefPtr def,
|
|
|
c1c534 |
virCapsPtr caps,
|
|
|
c1c534 |
unsigned int flags,
|
|
|
c1c534 |
- virBufferPtr buf)
|
|
|
c1c534 |
+ virBufferPtr buf,
|
|
|
c1c534 |
+ virDomainXMLOptionPtr xmlopt)
|
|
|
c1c534 |
{
|
|
|
c1c534 |
unsigned char *uuid;
|
|
|
c1c534 |
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
c1c534 |
@@ -25952,10 +26030,10 @@ virDomainDefFormatInternal(virDomainDefPtr def,
|
|
|
c1c534 |
* but no leading indentation before the starting element.
|
|
|
c1c534 |
* Thankfully, libxml maps what looks like globals into
|
|
|
c1c534 |
* thread-local uses, so we are thread-safe. */
|
|
|
c1c534 |
- xmlIndentTreeOutput = 1;
|
|
|
c1c534 |
- xmlbuf = xmlBufferCreate();
|
|
|
c1c534 |
- if (xmlNodeDump(xmlbuf, def->metadata->doc, def->metadata,
|
|
|
c1c534 |
- virBufferGetIndent(buf, false) / 2, 1) < 0) {
|
|
|
c1c534 |
+ xmlIndentTreeOutput = 1;
|
|
|
c1c534 |
+ xmlbuf = xmlBufferCreate();
|
|
|
c1c534 |
+ if (xmlNodeDump(xmlbuf, def->metadata->doc, def->metadata,
|
|
|
c1c534 |
+ virBufferGetIndent(buf, false) / 2, 1) < 0) {
|
|
|
c1c534 |
xmlBufferFree(xmlbuf);
|
|
|
c1c534 |
xmlIndentTreeOutput = oldIndentTreeOutput;
|
|
|
c1c534 |
goto error;
|
|
|
c1c534 |
@@ -26528,7 +26606,7 @@ virDomainDefFormatInternal(virDomainDefPtr def,
|
|
|
c1c534 |
def->emulator);
|
|
|
c1c534 |
|
|
|
c1c534 |
for (n = 0; n < def->ndisks; n++)
|
|
|
c1c534 |
- if (virDomainDiskDefFormat(buf, def->disks[n], flags) < 0)
|
|
|
c1c534 |
+ if (virDomainDiskDefFormat(buf, def->disks[n], flags, xmlopt) < 0)
|
|
|
c1c534 |
goto error;
|
|
|
c1c534 |
|
|
|
c1c534 |
for (n = 0; n < def->ncontrollers; n++)
|
|
|
c1c534 |
@@ -26715,7 +26793,7 @@ virDomainDefFormat(virDomainDefPtr def, virCapsPtr caps, unsigned int flags)
|
|
|
c1c534 |
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
c1c534 |
|
|
|
c1c534 |
virCheckFlags(VIR_DOMAIN_DEF_FORMAT_COMMON_FLAGS, NULL);
|
|
|
c1c534 |
- if (virDomainDefFormatInternal(def, caps, flags, &buf) < 0)
|
|
|
c1c534 |
+ if (virDomainDefFormatInternal(def, caps, flags, &buf, NULL) < 0)
|
|
|
c1c534 |
return NULL;
|
|
|
c1c534 |
|
|
|
c1c534 |
return virBufferContentAndReset(&buf;;
|
|
|
c1c534 |
@@ -26750,7 +26828,7 @@ virDomainObjFormat(virDomainXMLOptionPtr xmlopt,
|
|
|
c1c534 |
xmlopt->privateData.format(&buf, obj) < 0)
|
|
|
c1c534 |
goto error;
|
|
|
c1c534 |
|
|
|
c1c534 |
- if (virDomainDefFormatInternal(obj->def, caps, flags, &buf) < 0)
|
|
|
c1c534 |
+ if (virDomainDefFormatInternal(obj->def, caps, flags, &buf, xmlopt) < 0)
|
|
|
c1c534 |
goto error;
|
|
|
c1c534 |
|
|
|
c1c534 |
virBufferAdjustIndent(&buf, -2);
|
|
|
c1c534 |
@@ -27704,7 +27782,7 @@ virDomainDeviceDefCopy(virDomainDeviceDefPtr src,
|
|
|
c1c534 |
|
|
|
c1c534 |
switch ((virDomainDeviceType) src->type) {
|
|
|
c1c534 |
case VIR_DOMAIN_DEVICE_DISK:
|
|
|
c1c534 |
- rc = virDomainDiskDefFormat(&buf, src->data.disk, flags);
|
|
|
c1c534 |
+ rc = virDomainDiskDefFormat(&buf, src->data.disk, flags, xmlopt);
|
|
|
c1c534 |
break;
|
|
|
c1c534 |
case VIR_DOMAIN_DEVICE_LEASE:
|
|
|
c1c534 |
rc = virDomainLeaseDefFormat(&buf, src->data.lease);
|
|
|
c1c534 |
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
|
|
|
c1c534 |
index 698d3280fe..5e67c9a9c1 100644
|
|
|
c1c534 |
--- a/src/conf/domain_conf.h
|
|
|
c1c534 |
+++ b/src/conf/domain_conf.h
|
|
|
c1c534 |
@@ -2626,6 +2626,12 @@ typedef int (*virDomainXMLPrivateDataParseFunc)(xmlXPathContextPtr,
|
|
|
c1c534 |
virDomainObjPtr,
|
|
|
c1c534 |
virDomainDefParserConfigPtr);
|
|
|
c1c534 |
|
|
|
c1c534 |
+typedef int (*virDomainXMLPrivateDataStorageSourceParseFunc)(xmlXPathContextPtr ctxt,
|
|
|
c1c534 |
+ virStorageSourcePtr src);
|
|
|
c1c534 |
+typedef int (*virDomainXMLPrivateDataStorageSourceFormatFunc)(virStorageSourcePtr src,
|
|
|
c1c534 |
+ virBufferPtr buf);
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+
|
|
|
c1c534 |
typedef struct _virDomainXMLPrivateDataCallbacks virDomainXMLPrivateDataCallbacks;
|
|
|
c1c534 |
typedef virDomainXMLPrivateDataCallbacks *virDomainXMLPrivateDataCallbacksPtr;
|
|
|
c1c534 |
struct _virDomainXMLPrivateDataCallbacks {
|
|
|
c1c534 |
@@ -2639,6 +2645,8 @@ struct _virDomainXMLPrivateDataCallbacks {
|
|
|
c1c534 |
virDomainXMLPrivateDataNewFunc chrSourceNew;
|
|
|
c1c534 |
virDomainXMLPrivateDataFormatFunc format;
|
|
|
c1c534 |
virDomainXMLPrivateDataParseFunc parse;
|
|
|
c1c534 |
+ virDomainXMLPrivateDataStorageSourceParseFunc storageParse;
|
|
|
c1c534 |
+ virDomainXMLPrivateDataStorageSourceFormatFunc storageFormat;
|
|
|
c1c534 |
};
|
|
|
c1c534 |
|
|
|
c1c534 |
typedef bool (*virDomainABIStabilityDomain)(const virDomainDef *src,
|
|
|
c1c534 |
@@ -2963,12 +2971,14 @@ char *virDomainObjFormat(virDomainXMLOptionPtr xmlopt,
|
|
|
c1c534 |
int virDomainDefFormatInternal(virDomainDefPtr def,
|
|
|
c1c534 |
virCapsPtr caps,
|
|
|
c1c534 |
unsigned int flags,
|
|
|
c1c534 |
- virBufferPtr buf);
|
|
|
c1c534 |
+ virBufferPtr buf,
|
|
|
c1c534 |
+ virDomainXMLOptionPtr xmlopt);
|
|
|
c1c534 |
|
|
|
c1c534 |
int virDomainDiskSourceFormat(virBufferPtr buf,
|
|
|
c1c534 |
virStorageSourcePtr src,
|
|
|
c1c534 |
int policy,
|
|
|
c1c534 |
- unsigned int flags);
|
|
|
c1c534 |
+ unsigned int flags,
|
|
|
c1c534 |
+ virDomainXMLOptionPtr xmlopt);
|
|
|
c1c534 |
|
|
|
c1c534 |
int virDomainNetDefFormat(virBufferPtr buf,
|
|
|
c1c534 |
virDomainNetDefPtr def,
|
|
|
c1c534 |
@@ -3017,7 +3027,8 @@ virDomainDiskRemoveByName(virDomainDefPtr def, const char *name);
|
|
|
c1c534 |
int virDomainDiskSourceParse(xmlNodePtr node,
|
|
|
c1c534 |
xmlXPathContextPtr ctxt,
|
|
|
c1c534 |
virStorageSourcePtr src,
|
|
|
c1c534 |
- unsigned int flags);
|
|
|
c1c534 |
+ unsigned int flags,
|
|
|
c1c534 |
+ virDomainXMLOptionPtr xmlopt);
|
|
|
c1c534 |
|
|
|
c1c534 |
int virDomainNetFindIdx(virDomainDefPtr def, virDomainNetDefPtr net);
|
|
|
c1c534 |
virDomainNetDefPtr virDomainNetFind(virDomainDefPtr def, const char *device);
|
|
|
c1c534 |
diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c
|
|
|
c1c534 |
index f0e852c92b..d7b086242b 100644
|
|
|
c1c534 |
--- a/src/conf/snapshot_conf.c
|
|
|
c1c534 |
+++ b/src/conf/snapshot_conf.c
|
|
|
c1c534 |
@@ -110,7 +110,8 @@ static int
|
|
|
c1c534 |
virDomainSnapshotDiskDefParseXML(xmlNodePtr node,
|
|
|
c1c534 |
xmlXPathContextPtr ctxt,
|
|
|
c1c534 |
virDomainSnapshotDiskDefPtr def,
|
|
|
c1c534 |
- unsigned int flags)
|
|
|
c1c534 |
+ unsigned int flags,
|
|
|
c1c534 |
+ virDomainXMLOptionPtr xmlopt)
|
|
|
c1c534 |
{
|
|
|
c1c534 |
int ret = -1;
|
|
|
c1c534 |
char *snapshot = NULL;
|
|
|
c1c534 |
@@ -155,7 +156,7 @@ virDomainSnapshotDiskDefParseXML(xmlNodePtr node,
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
if ((cur = virXPathNode("./source", ctxt)) &&
|
|
|
c1c534 |
- virDomainDiskSourceParse(cur, ctxt, def->src, flags) < 0)
|
|
|
c1c534 |
+ virDomainDiskSourceParse(cur, ctxt, def->src, flags, xmlopt) < 0)
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
|
|
|
c1c534 |
if ((driver = virXPathString("string(./driver/@type)", ctxt))) {
|
|
|
c1c534 |
@@ -348,8 +349,8 @@ virDomainSnapshotDefParse(xmlXPathContextPtr ctxt,
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
def->ndisks = n;
|
|
|
c1c534 |
for (i = 0; i < def->ndisks; i++) {
|
|
|
c1c534 |
- if (virDomainSnapshotDiskDefParseXML(nodes[i], ctxt,
|
|
|
c1c534 |
- &def->disks[i], flags) < 0)
|
|
|
c1c534 |
+ if (virDomainSnapshotDiskDefParseXML(nodes[i], ctxt, &def->disks[i],
|
|
|
c1c534 |
+ flags, xmlopt) < 0)
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
}
|
|
|
c1c534 |
VIR_FREE(nodes);
|
|
|
c1c534 |
@@ -663,7 +664,8 @@ virDomainSnapshotAlignDisks(virDomainSnapshotDefPtr def,
|
|
|
c1c534 |
|
|
|
c1c534 |
static void
|
|
|
c1c534 |
virDomainSnapshotDiskDefFormat(virBufferPtr buf,
|
|
|
c1c534 |
- virDomainSnapshotDiskDefPtr disk)
|
|
|
c1c534 |
+ virDomainSnapshotDiskDefPtr disk,
|
|
|
c1c534 |
+ virDomainXMLOptionPtr xmlopt)
|
|
|
c1c534 |
{
|
|
|
c1c534 |
int type = disk->src->type;
|
|
|
c1c534 |
|
|
|
c1c534 |
@@ -686,7 +688,7 @@ virDomainSnapshotDiskDefFormat(virBufferPtr buf,
|
|
|
c1c534 |
if (disk->src->format > 0)
|
|
|
c1c534 |
virBufferEscapeString(buf, "<driver type='%s'/>\n",
|
|
|
c1c534 |
virStorageFileFormatTypeToString(disk->src->format));
|
|
|
c1c534 |
- virDomainDiskSourceFormat(buf, disk->src, 0, 0);
|
|
|
c1c534 |
+ virDomainDiskSourceFormat(buf, disk->src, 0, 0, xmlopt);
|
|
|
c1c534 |
|
|
|
c1c534 |
virBufferAdjustIndent(buf, -2);
|
|
|
c1c534 |
virBufferAddLit(buf, "</disk>\n");
|
|
|
c1c534 |
@@ -740,13 +742,13 @@ virDomainSnapshotDefFormat(const char *domain_uuid,
|
|
|
c1c534 |
virBufferAddLit(&buf, "<disks>\n");
|
|
|
c1c534 |
virBufferAdjustIndent(&buf, 2);
|
|
|
c1c534 |
for (i = 0; i < def->ndisks; i++)
|
|
|
c1c534 |
- virDomainSnapshotDiskDefFormat(&buf, &def->disks[i]);
|
|
|
c1c534 |
+ virDomainSnapshotDiskDefFormat(&buf, &def->disks[i], xmlopt);
|
|
|
c1c534 |
virBufferAdjustIndent(&buf, -2);
|
|
|
c1c534 |
virBufferAddLit(&buf, "</disks>\n");
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
if (def->dom) {
|
|
|
c1c534 |
- if (virDomainDefFormatInternal(def->dom, caps, flags, &buf) < 0)
|
|
|
c1c534 |
+ if (virDomainDefFormatInternal(def->dom, caps, flags, &buf, xmlopt) < 0)
|
|
|
c1c534 |
goto error;
|
|
|
c1c534 |
} else if (domain_uuid) {
|
|
|
c1c534 |
virBufferAddLit(&buf, "<domain>\n");
|
|
|
c1c534 |
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
|
|
|
c1c534 |
index fcaa66df91..334da7a85d 100644
|
|
|
c1c534 |
--- a/src/network/bridge_driver.c
|
|
|
c1c534 |
+++ b/src/network/bridge_driver.c
|
|
|
c1c534 |
@@ -233,7 +233,7 @@ networkRunHook(virNetworkObjPtr obj,
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
if (virNetworkDefFormatBuf(&buf, def, 0) < 0)
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
- if (dom && virDomainDefFormatInternal(dom, NULL, 0, &buf) < 0)
|
|
|
c1c534 |
+ if (dom && virDomainDefFormatInternal(dom, NULL, 0, &buf, NULL) < 0)
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
|
|
|
c1c534 |
virBufferAdjustIndent(&buf, -2);
|
|
|
c1c534 |
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
|
|
|
c1c534 |
index 9dd9db049b..625bcb20d5 100644
|
|
|
c1c534 |
--- a/src/qemu/qemu_domain.c
|
|
|
c1c534 |
+++ b/src/qemu/qemu_domain.c
|
|
|
c1c534 |
@@ -5245,7 +5245,7 @@ qemuDomainDefFormatBufInternal(virQEMUDriverPtr driver,
|
|
|
c1c534 |
format:
|
|
|
c1c534 |
ret = virDomainDefFormatInternal(def, caps,
|
|
|
c1c534 |
virDomainDefFormatConvertXMLFlags(flags),
|
|
|
c1c534 |
- buf);
|
|
|
c1c534 |
+ buf, driver->xmlopt);
|
|
|
c1c534 |
|
|
|
c1c534 |
cleanup:
|
|
|
c1c534 |
virDomainDefFree(copy);
|
|
|
c1c534 |
diff --git a/tests/virstoragetest.c b/tests/virstoragetest.c
|
|
|
c1c534 |
index e1d8751728..bdd0829c21 100644
|
|
|
c1c534 |
--- a/tests/virstoragetest.c
|
|
|
c1c534 |
+++ b/tests/virstoragetest.c
|
|
|
c1c534 |
@@ -693,7 +693,7 @@ testBackingParse(const void *args)
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
- if (virDomainDiskSourceFormat(&buf, src, 0, 0) < 0 ||
|
|
|
c1c534 |
+ if (virDomainDiskSourceFormat(&buf, src, 0, 0, NULL) < 0 ||
|
|
|
c1c534 |
!(xml = virBufferContentAndReset(&buf))) {
|
|
|
c1c534 |
fprintf(stderr, "failed to format disk source xml\n");
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
--
|
|
|
c1c534 |
2.15.1
|
|
|
c1c534 |
|