]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
conf: implement XML parsing/formating for <dataStore> element of a storage <source>
authorNikolai Barybin <nikolai.barybin@virtuozzo.com>
Wed, 20 Nov 2024 15:48:39 +0000 (18:48 +0300)
committerPeter Krempa <pkrempa@redhat.com>
Mon, 25 Nov 2024 21:31:13 +0000 (22:31 +0100)
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>
src/conf/domain_conf.c
src/conf/domain_validate.c

index 295707ec1f157193cfb36ad619d81b799e534a67..4ad8289b894ff955b2b0ac77277be97d435c7f5e 100644 (file)
@@ -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:
  * @node: XML node pointing to the source element to parse
@@ -7651,6 +7698,9 @@ virDomainStorageSourceParse(xmlNodePtr node,
                                           ctxt, flags) < 0)
         return -1;
 
+    if (virDomainDiskDataStoreParse(ctxt, src, flags, xmlopt) < 0)
+        return -1;
+
     /* 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 */
@@ -7720,6 +7770,7 @@ virDomainDiskBackingStoreParse(xmlXPathContextPtr ctxt,
     backingStore->readonly = true;
 
     if (virDomainStorageSourceParse(source, ctxt, backingStore, flags, xmlopt) < 0 ||
+        virDomainDiskDataStoreParse(ctxt, backingStore, flags, xmlopt) < 0 ||
         virDomainDiskBackingStoreParse(ctxt, backingStore, flags, xmlopt) < 0)
         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:
  * @buf: output buffer
@@ -22877,6 +22961,9 @@ virDomainDiskSourceFormat(virBuffer *buf,
     if (attrIndex && src->id != 0)
         virBufferAsprintf(&attrBuf, " index='%u'", src->id);
 
+    if (virDomainDiskDataStoreFormat(&childBuf, src, xmlopt, flags) < 0)
+        return -1;
+
     if (virDomainDiskSourceFormatPrivateData(&childBuf, src, flags, xmlopt) < 0)
         return -1;
 
index b352cd874abd77a0daadf09dd9c20c70b919dd35..1034bb57f500e61eab007e841e6c8370ebc7938e 100644 (file)
@@ -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: */
     if (virStorageSourceGetActualType(src) != VIR_STORAGE_TYPE_NETWORK &&
         src->protocol != VIR_STORAGE_NET_PROTOCOL_RBD) {