VM drivers may need to store additional private data to the status XML so that it can be restored after libvirtd restart. Since not everything is needed add a callback infrastructure, where VM drivers can add only stuff they need. Note that the private data is formatted as a <privateData> sub-element of the <disk> or <backingStore> <source> sub-element. This is done since storing it out of band (in the VM private data) would require a complex matching process to allow to put the data into correct place. --- src/conf/domain_conf.c | 136 ++++++++++++++++++++++++++++++++++---------- src/conf/domain_conf.h | 17 +++++- src/conf/snapshot_conf.c | 18 +++--- src/network/bridge_driver.c | 2 +- src/qemu/qemu_domain.c | 2 +- tests/qemublocktest.c | 4 +- tests/virstoragetest.c | 2 +- 7 files changed, 136 insertions(+), 45 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 66e21c4bdb..9a62bc472c 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -8553,11 +8553,43 @@ virDomainDiskSourceEncryptionParse(xmlNodePtr node, } +static int +virDomainDiskSourcePrivateDataParse(xmlXPathContextPtr ctxt, + virStorageSourcePtr src, + unsigned int flags, + virDomainXMLOptionPtr xmlopt) +{ + xmlNodePtr saveNode = ctxt->node; + xmlNodePtr node; + int ret = -1; + + if (!(flags & VIR_DOMAIN_DEF_PARSE_STATUS) || + !xmlopt || !xmlopt->privateData.storageParse) + return 0; + + if (!(node = virXPathNode("./privateData", ctxt))) + return 0; + + ctxt->node = node; + + if (xmlopt->privateData.storageParse(ctxt, src) < 0) + goto cleanup; + + ret = 0; + + cleanup: + ctxt->node = saveNode; + + return ret; +} + + int virDomainDiskSourceParse(xmlNodePtr node, xmlXPathContextPtr ctxt, virStorageSourcePtr src, - unsigned int flags) + unsigned int flags, + virDomainXMLOptionPtr xmlopt) { int ret = -1; xmlNodePtr saveNode = ctxt->node; @@ -8596,6 +8628,9 @@ virDomainDiskSourceParse(xmlNodePtr node, if (virDomainDiskSourceEncryptionParse(node, &src->encryption) < 0) goto cleanup; + if (virDomainDiskSourcePrivateDataParse(ctxt, src, flags, xmlopt) < 0) + goto cleanup; + /* People sometimes pass a bogus '' source path when they mean to omit the * source element completely (e.g. CDROM without media). This is just a * little compatibility check to help those broken apps */ @@ -8613,7 +8648,8 @@ virDomainDiskSourceParse(xmlNodePtr node, static int virDomainDiskBackingStoreParse(xmlXPathContextPtr ctxt, virStorageSourcePtr src, - unsigned int flags) + unsigned int flags, + virDomainXMLOptionPtr xmlopt) { virStorageSourcePtr backingStore = NULL; xmlNodePtr save_ctxt = ctxt->node; @@ -8671,8 +8707,8 @@ virDomainDiskBackingStoreParse(xmlXPathContextPtr ctxt, goto cleanup; } - if (virDomainDiskSourceParse(source, ctxt, backingStore, flags) < 0 || - virDomainDiskBackingStoreParse(ctxt, backingStore, flags) < 0) + if (virDomainDiskSourceParse(source, ctxt, backingStore, flags, xmlopt) < 0 || + virDomainDiskBackingStoreParse(ctxt, backingStore, flags, xmlopt) < 0) goto cleanup; VIR_STEAL_PTR(src->backingStore, backingStore); @@ -8774,7 +8810,8 @@ static int virDomainDiskDefMirrorParse(virDomainDiskDefPtr def, xmlNodePtr cur, xmlXPathContextPtr ctxt, - unsigned int flags) + unsigned int flags, + virDomainXMLOptionPtr xmlopt) { xmlNodePtr mirrorNode; char *mirrorFormat = NULL; @@ -8812,7 +8849,8 @@ virDomainDiskDefMirrorParse(virDomainDiskDefPtr def, goto cleanup; } - if (virDomainDiskSourceParse(mirrorNode, ctxt, def->mirror, flags) < 0) + if (virDomainDiskSourceParse(mirrorNode, ctxt, def->mirror, + flags, xmlopt) < 0) goto cleanup; } else { /* For back-compat reasons, we handle a file name @@ -9238,7 +9276,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, if (!source && virXMLNodeNameEqual(cur, "source")) { sourceNode = cur; - if (virDomainDiskSourceParse(cur, ctxt, def->src, flags) < 0) + if (virDomainDiskSourceParse(cur, ctxt, def->src, flags, xmlopt) < 0) goto error; /* If we've already found an <auth> as a child of <disk> and @@ -9319,7 +9357,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, } else if (!def->mirror && virXMLNodeNameEqual(cur, "mirror") && !(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE)) { - if (virDomainDiskDefMirrorParse(def, cur, ctxt, flags) < 0) + if (virDomainDiskDefMirrorParse(def, cur, ctxt, flags, xmlopt) < 0) goto error; } else if (!authdef && virXMLNodeNameEqual(cur, "auth")) { @@ -9590,7 +9628,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, product = NULL; if (!(flags & VIR_DOMAIN_DEF_PARSE_DISK_SOURCE)) { - if (virDomainDiskBackingStoreParse(ctxt, def->src, flags) < 0) + if (virDomainDiskBackingStoreParse(ctxt, def->src, flags, xmlopt) < 0) goto error; } @@ -22356,12 +22394,43 @@ virDomainDiskSourceFormatNetwork(virBufferPtr attrBuf, } +static int +virDomainDiskSourceFormatPrivateData(virBufferPtr buf, + virStorageSourcePtr src, + unsigned int flags, + virDomainXMLOptionPtr xmlopt) +{ + virBuffer childBuf = VIR_BUFFER_INITIALIZER; + int ret = -1; + + if (!(flags & VIR_DOMAIN_DEF_FORMAT_STATUS) || + !xmlopt || !xmlopt->privateData.storageFormat) + return 0; + + virBufferSetChildIndent(&childBuf, buf); + + if (xmlopt->privateData.storageFormat(src, &childBuf) < 0) + goto cleanup; + + if (virXMLFormatElement(buf, "privateData", NULL, &childBuf) < 0) + goto cleanup; + + ret = 0; + + cleanup: + virBufferFreeAndReset(&childBuf); + + return ret; +} + + static int virDomainDiskSourceFormatInternal(virBufferPtr buf, virStorageSourcePtr src, int policy, unsigned int flags, - bool skipSeclabels) + bool skipSeclabels, + virDomainXMLOptionPtr xmlopt) { const char *startupPolicy = NULL; virBuffer attrBuf = VIR_BUFFER_INITIALIZER; @@ -22443,6 +22512,9 @@ virDomainDiskSourceFormatInternal(virBufferPtr buf, virStorageEncryptionFormat(&childBuf, src->encryption) < 0) return -1; + if (virDomainDiskSourceFormatPrivateData(&childBuf, src, flags, xmlopt) < 0) + return -1; + if (virXMLFormatElement(buf, "source", &attrBuf, &childBuf) < 0) goto error; } @@ -22460,15 +22532,18 @@ int virDomainDiskSourceFormat(virBufferPtr buf, virStorageSourcePtr src, int policy, - unsigned int flags) + unsigned int flags, + virDomainXMLOptionPtr xmlopt) { - return virDomainDiskSourceFormatInternal(buf, src, policy, flags, false); + return virDomainDiskSourceFormatInternal(buf, src, policy, flags, false, xmlopt); } static int virDomainDiskBackingStoreFormat(virBufferPtr buf, - virStorageSourcePtr backingStore) + virStorageSourcePtr backingStore, + virDomainXMLOptionPtr xmlopt, + unsigned int flags) { const char *format; @@ -22497,9 +22572,9 @@ virDomainDiskBackingStoreFormat(virBufferPtr buf, virBufferAsprintf(buf, "<format type='%s'/>\n", format); /* We currently don't output seclabels for backing chain element */ - if (virDomainDiskSourceFormatInternal(buf, backingStore, 0, 0, true) < 0 || - virDomainDiskBackingStoreFormat(buf, - backingStore->backingStore) < 0) + if (virDomainDiskSourceFormatInternal(buf, backingStore, 0, flags, true, xmlopt) < 0 || + virDomainDiskBackingStoreFormat(buf, backingStore->backingStore, + xmlopt, flags) < 0) return -1; virBufferAdjustIndent(buf, -2); @@ -22517,7 +22592,8 @@ virDomainDiskBackingStoreFormat(virBufferPtr buf, static int virDomainDiskDefFormat(virBufferPtr buf, virDomainDiskDefPtr def, - unsigned int flags) + unsigned int flags, + virDomainXMLOptionPtr xmlopt) { const char *type = virStorageTypeToString(def->src->type); const char *device = virDomainDiskDeviceTypeToString(def->device); @@ -22630,13 +22706,14 @@ virDomainDiskDefFormat(virBufferPtr buf, } if (virDomainDiskSourceFormat(buf, def->src, def->startupPolicy, - flags) < 0) + flags, xmlopt) < 0) return -1; /* Don't format backingStore to inactive XMLs until the code for * persistent storage of backing chains is ready. */ if (!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE) && - virDomainDiskBackingStoreFormat(buf, def->src->backingStore) < 0) + virDomainDiskBackingStoreFormat(buf, def->src->backingStore, + xmlopt, flags) < 0) return -1; virBufferEscapeString(buf, "<backenddomain name='%s'/>\n", def->domain_name); @@ -22673,7 +22750,7 @@ virDomainDiskDefFormat(virBufferPtr buf, virBufferAddLit(buf, ">\n"); virBufferAdjustIndent(buf, 2); virBufferEscapeString(buf, "<format type='%s'/>\n", formatStr); - if (virDomainDiskSourceFormat(buf, def->mirror, 0, 0) < 0) + if (virDomainDiskSourceFormat(buf, def->mirror, 0, 0, xmlopt) < 0) return -1; virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</mirror>\n"); @@ -25904,7 +25981,8 @@ int virDomainDefFormatInternal(virDomainDefPtr def, virCapsPtr caps, unsigned int flags, - virBufferPtr buf) + virBufferPtr buf, + virDomainXMLOptionPtr xmlopt) { unsigned char *uuid; char uuidstr[VIR_UUID_STRING_BUFLEN]; @@ -25959,10 +26037,10 @@ virDomainDefFormatInternal(virDomainDefPtr def, * 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) { + xmlIndentTreeOutput = 1; + xmlbuf = xmlBufferCreate(); + if (xmlNodeDump(xmlbuf, def->metadata->doc, def->metadata, + virBufferGetIndent(buf, false) / 2, 1) < 0) { xmlBufferFree(xmlbuf); xmlIndentTreeOutput = oldIndentTreeOutput; goto error; @@ -26535,7 +26613,7 @@ virDomainDefFormatInternal(virDomainDefPtr def, def->emulator); for (n = 0; n < def->ndisks; n++) - if (virDomainDiskDefFormat(buf, def->disks[n], flags) < 0) + if (virDomainDiskDefFormat(buf, def->disks[n], flags, xmlopt) < 0) goto error; for (n = 0; n < def->ncontrollers; n++) @@ -26722,7 +26800,7 @@ virDomainDefFormat(virDomainDefPtr def, virCapsPtr caps, unsigned int flags) virBuffer buf = VIR_BUFFER_INITIALIZER; virCheckFlags(VIR_DOMAIN_DEF_FORMAT_COMMON_FLAGS, NULL); - if (virDomainDefFormatInternal(def, caps, flags, &buf) < 0) + if (virDomainDefFormatInternal(def, caps, flags, &buf, NULL) < 0) return NULL; return virBufferContentAndReset(&buf); @@ -26757,7 +26835,7 @@ virDomainObjFormat(virDomainXMLOptionPtr xmlopt, xmlopt->privateData.format(&buf, obj) < 0) goto error; - if (virDomainDefFormatInternal(obj->def, caps, flags, &buf) < 0) + if (virDomainDefFormatInternal(obj->def, caps, flags, &buf, xmlopt) < 0) goto error; virBufferAdjustIndent(&buf, -2); @@ -27711,7 +27789,7 @@ virDomainDeviceDefCopy(virDomainDeviceDefPtr src, switch ((virDomainDeviceType) src->type) { case VIR_DOMAIN_DEVICE_DISK: - rc = virDomainDiskDefFormat(&buf, src->data.disk, flags); + rc = virDomainDiskDefFormat(&buf, src->data.disk, flags, xmlopt); break; case VIR_DOMAIN_DEVICE_LEASE: rc = virDomainLeaseDefFormat(&buf, src->data.lease); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 59f250ac96..6f7f96b3dd 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2631,6 +2631,12 @@ typedef int (*virDomainXMLPrivateDataParseFunc)(xmlXPathContextPtr, virDomainObjPtr, virDomainDefParserConfigPtr); +typedef int (*virDomainXMLPrivateDataStorageSourceParseFunc)(xmlXPathContextPtr ctxt, + virStorageSourcePtr src); +typedef int (*virDomainXMLPrivateDataStorageSourceFormatFunc)(virStorageSourcePtr src, + virBufferPtr buf); + + typedef struct _virDomainXMLPrivateDataCallbacks virDomainXMLPrivateDataCallbacks; typedef virDomainXMLPrivateDataCallbacks *virDomainXMLPrivateDataCallbacksPtr; struct _virDomainXMLPrivateDataCallbacks { @@ -2643,6 +2649,8 @@ struct _virDomainXMLPrivateDataCallbacks { virDomainXMLPrivateDataNewFunc chrSourceNew; virDomainXMLPrivateDataFormatFunc format; virDomainXMLPrivateDataParseFunc parse; + virDomainXMLPrivateDataStorageSourceParseFunc storageParse; + virDomainXMLPrivateDataStorageSourceFormatFunc storageFormat; }; typedef bool (*virDomainABIStabilityDomain)(const virDomainDef *src, @@ -2967,12 +2975,14 @@ char *virDomainObjFormat(virDomainXMLOptionPtr xmlopt, int virDomainDefFormatInternal(virDomainDefPtr def, virCapsPtr caps, unsigned int flags, - virBufferPtr buf); + virBufferPtr buf, + virDomainXMLOptionPtr xmlopt); int virDomainDiskSourceFormat(virBufferPtr buf, virStorageSourcePtr src, int policy, - unsigned int flags); + unsigned int flags, + virDomainXMLOptionPtr xmlopt); int virDomainNetDefFormat(virBufferPtr buf, virDomainNetDefPtr def, @@ -3021,7 +3031,8 @@ virDomainDiskRemoveByName(virDomainDefPtr def, const char *name); int virDomainDiskSourceParse(xmlNodePtr node, xmlXPathContextPtr ctxt, virStorageSourcePtr src, - unsigned int flags); + unsigned int flags, + virDomainXMLOptionPtr xmlopt); int virDomainNetFindIdx(virDomainDefPtr def, virDomainNetDefPtr net); virDomainNetDefPtr virDomainNetFind(virDomainDefPtr def, const char *device); diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c index f0e852c92b..d7b086242b 100644 --- a/src/conf/snapshot_conf.c +++ b/src/conf/snapshot_conf.c @@ -110,7 +110,8 @@ static int virDomainSnapshotDiskDefParseXML(xmlNodePtr node, xmlXPathContextPtr ctxt, virDomainSnapshotDiskDefPtr def, - unsigned int flags) + unsigned int flags, + virDomainXMLOptionPtr xmlopt) { int ret = -1; char *snapshot = NULL; @@ -155,7 +156,7 @@ virDomainSnapshotDiskDefParseXML(xmlNodePtr node, } if ((cur = virXPathNode("./source", ctxt)) && - virDomainDiskSourceParse(cur, ctxt, def->src, flags) < 0) + virDomainDiskSourceParse(cur, ctxt, def->src, flags, xmlopt) < 0) goto cleanup; if ((driver = virXPathString("string(./driver/@type)", ctxt))) { @@ -348,8 +349,8 @@ virDomainSnapshotDefParse(xmlXPathContextPtr ctxt, goto cleanup; def->ndisks = n; for (i = 0; i < def->ndisks; i++) { - if (virDomainSnapshotDiskDefParseXML(nodes[i], ctxt, - &def->disks[i], flags) < 0) + if (virDomainSnapshotDiskDefParseXML(nodes[i], ctxt, &def->disks[i], + flags, xmlopt) < 0) goto cleanup; } VIR_FREE(nodes); @@ -663,7 +664,8 @@ virDomainSnapshotAlignDisks(virDomainSnapshotDefPtr def, static void virDomainSnapshotDiskDefFormat(virBufferPtr buf, - virDomainSnapshotDiskDefPtr disk) + virDomainSnapshotDiskDefPtr disk, + virDomainXMLOptionPtr xmlopt) { int type = disk->src->type; @@ -686,7 +688,7 @@ virDomainSnapshotDiskDefFormat(virBufferPtr buf, if (disk->src->format > 0) virBufferEscapeString(buf, "<driver type='%s'/>\n", virStorageFileFormatTypeToString(disk->src->format)); - virDomainDiskSourceFormat(buf, disk->src, 0, 0); + virDomainDiskSourceFormat(buf, disk->src, 0, 0, xmlopt); virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</disk>\n"); @@ -740,13 +742,13 @@ virDomainSnapshotDefFormat(const char *domain_uuid, virBufferAddLit(&buf, "<disks>\n"); virBufferAdjustIndent(&buf, 2); for (i = 0; i < def->ndisks; i++) - virDomainSnapshotDiskDefFormat(&buf, &def->disks[i]); + virDomainSnapshotDiskDefFormat(&buf, &def->disks[i], xmlopt); virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</disks>\n"); } if (def->dom) { - if (virDomainDefFormatInternal(def->dom, caps, flags, &buf) < 0) + if (virDomainDefFormatInternal(def->dom, caps, flags, &buf, xmlopt) < 0) goto error; } else if (domain_uuid) { virBufferAddLit(&buf, "<domain>\n"); diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index fcaa66df91..334da7a85d 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -233,7 +233,7 @@ networkRunHook(virNetworkObjPtr obj, goto cleanup; if (virNetworkDefFormatBuf(&buf, def, 0) < 0) goto cleanup; - if (dom && virDomainDefFormatInternal(dom, NULL, 0, &buf) < 0) + if (dom && virDomainDefFormatInternal(dom, NULL, 0, &buf, NULL) < 0) goto cleanup; virBufferAdjustIndent(&buf, -2); diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 347fc07425..18c2d2cb8a 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5325,7 +5325,7 @@ qemuDomainDefFormatBufInternal(virQEMUDriverPtr driver, format: ret = virDomainDefFormatInternal(def, caps, virDomainDefFormatConvertXMLFlags(flags), - buf); + buf, driver->xmlopt); cleanup: virDomainDefFree(copy); diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c index d1665756ab..e8fac100dd 100644 --- a/tests/qemublocktest.c +++ b/tests/qemublocktest.c @@ -57,7 +57,7 @@ testBackingXMLjsonXML(const void *args) if (!(xml = virXMLParseStringCtxt(data->xml, "(test storage source XML)", &ctxt))) goto cleanup; - if (virDomainDiskSourceParse(ctxt->node, ctxt, xmlsrc, 0) < 0) { + if (virDomainDiskSourceParse(ctxt->node, ctxt, xmlsrc, 0, NULL) < 0) { fprintf(stderr, "failed to parse disk source xml\n"); goto cleanup; } @@ -83,7 +83,7 @@ testBackingXMLjsonXML(const void *args) goto cleanup; } - if (virDomainDiskSourceFormat(&buf, jsonsrc, 0, 0) < 0 || + if (virDomainDiskSourceFormat(&buf, jsonsrc, 0, 0, NULL) < 0 || !(actualxml = virBufferContentAndReset(&buf))) { fprintf(stderr, "failed to format disk source xml\n"); goto cleanup; diff --git a/tests/virstoragetest.c b/tests/virstoragetest.c index 806c5465ce..7a0d4a8260 100644 --- a/tests/virstoragetest.c +++ b/tests/virstoragetest.c @@ -693,7 +693,7 @@ testBackingParse(const void *args) goto cleanup; } - if (virDomainDiskSourceFormat(&buf, src, 0, 0) < 0 || + if (virDomainDiskSourceFormat(&buf, src, 0, 0, NULL) < 0 || !(xml = virBufferContentAndReset(&buf))) { fprintf(stderr, "failed to format disk source xml\n"); goto cleanup; -- 2.15.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list