mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 13:45:38 +00:00
conf: implement XML parsing/formating for <dataStore> element of a storage <source>
Introduce parsing and formatting of <dataStore> element. The <dataStore represents a different storage volume meant for storing the actual blocks of guest-visible data. The original disk source is then just a metadata storage for any advanced features. This currently works only for 'qcow2' images. Signed-off-by: Nikolai Barybin <nikolai.barybin@virtuozzo.com> Signed-off-by: Peter Krempa <pkrempa@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com>
This commit is contained in:
parent
28d88e9fc3
commit
b3171cf8da
@ -7561,6 +7561,53 @@ virDomainStorageSourceParseSlices(virStorageSource *src,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virDomainDiskDataStoreParse(xmlXPathContextPtr ctxt,
|
||||||
|
virStorageSource *src,
|
||||||
|
unsigned int flags,
|
||||||
|
virDomainXMLOption *xmlopt)
|
||||||
|
{
|
||||||
|
VIR_XPATH_NODE_AUTORESTORE(ctxt)
|
||||||
|
xmlNodePtr source;
|
||||||
|
g_autofree char *type = NULL;
|
||||||
|
g_autofree char *format = NULL;
|
||||||
|
g_autofree char *idx = NULL;
|
||||||
|
g_autoptr(virStorageSource) dataFileStore = NULL;
|
||||||
|
|
||||||
|
if (!(ctxt->node = virXPathNode("./dataStore", ctxt)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(type = virXMLPropStringRequired(ctxt->node, "type")))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!(format = virXPathString("string(./format/@type)", ctxt))) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("missing data file store format"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(source = virXPathNode("./source", ctxt))) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("missing disk data file store source"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE))
|
||||||
|
idx = virXMLPropString(source, "index");
|
||||||
|
|
||||||
|
if (!(dataFileStore = virDomainStorageSourceParseBase(type, format, idx)))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (virDomainStorageSourceParse(source, ctxt, dataFileStore, flags, xmlopt) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
dataFileStore->readonly = src->readonly;
|
||||||
|
src->dataFileStore = g_steal_pointer(&dataFileStore);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virDomainStorageSourceParse:
|
* virDomainStorageSourceParse:
|
||||||
* @node: XML node pointing to the source element to parse
|
* @node: XML node pointing to the source element to parse
|
||||||
@ -7651,6 +7698,9 @@ virDomainStorageSourceParse(xmlNodePtr node,
|
|||||||
ctxt, flags) < 0)
|
ctxt, flags) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (virDomainDiskDataStoreParse(ctxt, src, flags, xmlopt) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
/* People sometimes pass a bogus '' source path when they mean to omit the
|
/* 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
|
* source element completely (e.g. CDROM without media). This is just a
|
||||||
* little compatibility check to help those broken apps */
|
* little compatibility check to help those broken apps */
|
||||||
@ -7720,6 +7770,7 @@ virDomainDiskBackingStoreParse(xmlXPathContextPtr ctxt,
|
|||||||
backingStore->readonly = true;
|
backingStore->readonly = true;
|
||||||
|
|
||||||
if (virDomainStorageSourceParse(source, ctxt, backingStore, flags, xmlopt) < 0 ||
|
if (virDomainStorageSourceParse(source, ctxt, backingStore, flags, xmlopt) < 0 ||
|
||||||
|
virDomainDiskDataStoreParse(ctxt, backingStore, flags, xmlopt) < 0 ||
|
||||||
virDomainDiskBackingStoreParse(ctxt, backingStore, flags, xmlopt) < 0)
|
virDomainDiskBackingStoreParse(ctxt, backingStore, flags, xmlopt) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -22762,6 +22813,39 @@ virDomainDiskSourceFormatSlices(virBuffer *buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virDomainDiskDataStoreFormat(virBuffer *buf,
|
||||||
|
virStorageSource *src,
|
||||||
|
virDomainXMLOption *xmlopt,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
|
||||||
|
g_auto(virBuffer) formatAttrBuf = VIR_BUFFER_INITIALIZER;
|
||||||
|
g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
|
||||||
|
bool inactive = flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE;
|
||||||
|
|
||||||
|
if (!src->dataFileStore)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* don't write detected data file member to inactive xml */
|
||||||
|
if (inactive && src->dataFileStore->detected)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
virBufferAsprintf(&attrBuf, " type='%s'",
|
||||||
|
virStorageTypeToString(src->dataFileStore->type));
|
||||||
|
|
||||||
|
virBufferAsprintf(&formatAttrBuf, " type='%s'", "raw");
|
||||||
|
virXMLFormatElement(&childBuf, "format", &formatAttrBuf, NULL);
|
||||||
|
|
||||||
|
if (virDomainDiskSourceFormat(&childBuf, src->dataFileStore, "source", 0,
|
||||||
|
true, flags, false, false, xmlopt) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
virXMLFormatElement(buf, "dataStore", &attrBuf, &childBuf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virDomainDiskSourceFormat:
|
* virDomainDiskSourceFormat:
|
||||||
* @buf: output buffer
|
* @buf: output buffer
|
||||||
@ -22877,6 +22961,9 @@ virDomainDiskSourceFormat(virBuffer *buf,
|
|||||||
if (attrIndex && src->id != 0)
|
if (attrIndex && src->id != 0)
|
||||||
virBufferAsprintf(&attrBuf, " index='%u'", src->id);
|
virBufferAsprintf(&attrBuf, " index='%u'", src->id);
|
||||||
|
|
||||||
|
if (virDomainDiskDataStoreFormat(&childBuf, src, xmlopt, flags) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (virDomainDiskSourceFormatPrivateData(&childBuf, src, flags, xmlopt) < 0)
|
if (virDomainDiskSourceFormatPrivateData(&childBuf, src, flags, xmlopt) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -542,6 +542,32 @@ virDomainDiskDefValidateSourceChainOne(const virStorageSource *src)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (src->dataFileStore) {
|
||||||
|
if (src->format != VIR_STORAGE_FILE_QCOW2) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("<dataStore> feature available only with qcow2 images"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->dataFileStore->format != VIR_STORAGE_FILE_RAW) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("only 'raw' images supported as <dataStore>"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->dataFileStore->dataFileStore || src->backingStore) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("The <source> of <dataStore> can't have another nested <dataStore> or <backingStore> element"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->dataFileStore->sliceStorage) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("slices are not supported for <dataStore>"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* internal snapshots and config files are currently supported only with rbd: */
|
/* internal snapshots and config files are currently supported only with rbd: */
|
||||||
if (virStorageSourceGetActualType(src) != VIR_STORAGE_TYPE_NETWORK &&
|
if (virStorageSourceGetActualType(src) != VIR_STORAGE_TYPE_NETWORK &&
|
||||||
src->protocol != VIR_STORAGE_NET_PROTOCOL_RBD) {
|
src->protocol != VIR_STORAGE_NET_PROTOCOL_RBD) {
|
||||||
|
Loading…
Reference in New Issue
Block a user