From: Masayoshi Mizuma <m.mizuma(a)jp.fujitsu.com>
Here is the implementation of transient option for qcow2 file.
This gets available <transient/> directive in domain xml file
like as:
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/var/lib/libvirt/images/guest.qcow2'/>
<target dev='vda' bus='virtio'/>
<transient/>
</disk>
The internal procedure is as follows.
When the qemu command line options are built, a new qcow2 image is created
with backing qcow2 image by using qemu-img command. The backing image is the
qcow2 file which is set as <source>.
The filename of the new qcow2 image is original-source-file.TRANSIENT.
The qemu-img will be:
qemu-img create -f qcow2 -F qcow2 \
-b /var/lib/libvirt/images/guest.qcow2 \
/var/lib/libvirt/images/guest.qcow2.TRANSIENT
Then, it switches the disk path, virStorageSourcePtr src->path, to
the new qcow2 image. The new image and the backing image is handled and
the blockdev option of qemu will be built like as:
-blockdev
'{"driver":"file","filename":"/var/lib/libvirt/images/guest.qcow2",
"node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}'
\
-blockdev
'{"node-name":"libvirt-2-format","read-only":true,"driver":"qcow2",
"file":"libvirt-2-storage","backing":null}' \
-blockdev
'{"driver":"file","filename":"/var/lib/libvirt/images/guest.qcow2.TRANSIENT",
"node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}'
\
-blockdev
'{"node-name":"libvirt-1-format","read-only":false,"driver":"qcow2",
"file":"libvirt-1-storage","backing":"libvirt-2-format"}'
The new qcow2 image is removed when the Guest is shutdowned,
Signed-off-by: Masayoshi Mizuma <m.mizuma(a)jp.fujitsu.com>
---
src/qemu/qemu_block.c | 71 ++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_block.h | 7 ++++
src/qemu/qemu_domain.c | 4 +++
src/qemu/qemu_process.c | 3 ++
src/qemu/qemu_validate.c | 2 +-
5 files changed, 86 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 6f9c707..5eb0225 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -27,6 +27,7 @@
#include "viralloc.h"
#include "virstring.h"
#include "virlog.h"
+#include "virqemu.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -3438,3 +3439,73 @@ qemuBlockUpdateRelativeBacking(virDomainObjPtr vm,
return 0;
}
+
+int
+qemuBlockCreateTransientDisk(virStorageSourcePtr src,
+ qemuDomainObjPrivatePtr priv)
+{
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ virCommandPtr cmd = NULL;
+ g_autofree char *filename = NULL;
+ g_autofree char *dirname = NULL;
+ const char *qemuImgPath;
+ char *newpath;
+ int err = -1;
+
+ if ((src->format != VIR_STORAGE_FILE_QCOW2)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("transient option supports qcow2"));
+ return -1;
+ }
+
+ if (!(qemuImgPath = qemuFindQemuImgBinary(priv->driver)))
+ return -1;
+
+ newpath = g_strdup_printf("%s.TRANSIENT", src->path);
+
+ if (virFileExists(newpath)) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _(" '%s' is already exists. Please remove it."),
newpath);
+ goto cleanup;
+ }
+
+ if (!(cmd = virCommandNewArgList(qemuImgPath,
+ "create",
+ "-f",
+ "qcow2",
+ "-F",
+ "qcow2",
+ "-b",
+ NULL)))
+ goto cleanup;
+
+ virQEMUBuildBufferEscapeComma(&buf, src->path);
+ virCommandAddArgBuffer(cmd, &buf);
+
+ virQEMUBuildBufferEscapeComma(&buf, newpath);
+ virCommandAddArgBuffer(cmd, &buf);
+
+ if (virCommandRun(cmd, NULL) < 0)
+ goto cleanup;
+
+ VIR_DEBUG("Original disk: %s Transient disk: %s", src->path, newpath);
+
+ g_free(src->path);
+ src->path = newpath;
+
+ err = 0;
+ cleanup:
+ virBufferFreeAndReset(&buf);
+ virCommandFree(cmd);
+ if (err)
+ g_free(newpath);
+
+ return err;
+}
+
+void
+qemuBlockRemoveTransientDisk(virStorageSourcePtr src)
+{
+ VIR_DEBUG("unlink transient disk: %s ", src->path);
+ unlink(src->path);
+}
diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h
index 2ad2ce1..60c6898 100644
--- a/src/qemu/qemu_block.h
+++ b/src/qemu/qemu_block.h
@@ -266,3 +266,10 @@ int
qemuBlockUpdateRelativeBacking(virDomainObjPtr vm,
virStorageSourcePtr src,
virStorageSourcePtr topsrc);
+
+int
+qemuBlockCreateTransientDisk(virStorageSourcePtr src,
+ qemuDomainObjPrivatePtr priv);
+
+void
+qemuBlockRemoveTransientDisk(virStorageSourcePtr src);
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index d5e3d1a..9dbf73c 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -8301,6 +8301,10 @@ qemuDomainDetermineDiskChain(virQEMUDriverPtr driver,
qemuDomainGetImageIds(cfg, vm, src, disksrc, &uid, &gid);
+ if (disk->transient)
+ if (qemuBlockCreateTransientDisk(src, vm->privateData) < 0)
+ return -1;
+
if (virStorageFileGetMetadata(src, uid, gid, report_broken) < 0)
return -1;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 999e576..859ef82 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7597,6 +7597,9 @@ void qemuProcessStop(virQEMUDriverPtr driver,
}
qemuBlockRemoveImageMetadata(driver, vm, disk->dst, disk->src);
+
+ if (disk->transient)
+ qemuBlockRemoveTransientDisk(disk->src);
}
}
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 584d137..cdda6ac 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -2098,7 +2098,7 @@ qemuValidateDomainDeviceDefDiskFrontend(const virDomainDiskDef
*disk,
}
}
- if (disk->transient) {
+ if ((disk->transient) && (disk->src->format !=
VIR_STORAGE_FILE_QCOW2)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("transient disks not supported yet"));
return -1;
--
2.27.0