This is an automated email from the ASF dual-hosted git repository.
sureshanaparti pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/main by this push:
new 5ea1ada59a4 Allow full clone volumes with thin provisioning in KVM
(#11177)
5ea1ada59a4 is described below
commit 5ea1ada59a43bccc699f09efb3a7a89df1562017
Author: João Jandre <[email protected]>
AuthorDate: Thu Jul 31 07:42:17 2025 -0300
Allow full clone volumes with thin provisioning in KVM (#11177)
It adds a configuration called create.full.clone to the agent.properties
file. When set to true, all QCOW2 volumes created will be full-clone. If false
(default), the current behavior remains, where only FAT and SPARSE volumes are
full-clone and THIN volumes are linked-clone.
---
agent/conf/agent.properties | 3 +++
.../java/com/cloud/agent/properties/AgentProperties.java | 8 ++++++++
.../hypervisor/kvm/storage/LibvirtStorageAdaptor.java | 16 +++++++++++++---
3 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/agent/conf/agent.properties b/agent/conf/agent.properties
index e70acee229d..cd31b0db56d 100644
--- a/agent/conf/agent.properties
+++ b/agent/conf/agent.properties
@@ -447,3 +447,6 @@ iscsi.session.cleanup.enabled=false
# Timeout (in seconds) to wait for the incremental snapshot to complete.
# incremental.snapshot.timeout=10800
+
+# If set to true, creates VMs as full clones of their templates on KVM
hypervisor. Creates as linked clones otherwise.
+# create.full.clone=false
diff --git
a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java
b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java
index 47255762a05..847d1bb2396 100644
--- a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java
+++ b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java
@@ -863,6 +863,14 @@ public class AgentProperties{
* */
public static final Property<Integer> REVERT_SNAPSHOT_TIMEOUT = new
Property<>("revert.snapshot.timeout", 10800);
+ /**
+ * If set to true, creates VMs as full clones of their templates on KVM
hypervisor. Creates as linked clones otherwise. <br>
+ * Data type: Boolean. <br>
+ * Default value: <code>false</code>
+ */
+ public static final Property<Boolean> CREATE_FULL_CLONE = new
Property<>("create.full.clone", false);
+
+
public static class Property <T>{
private String name;
private T defaultValue;
diff --git
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java
index 7c66a91876f..bf851831cd0 100644
---
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java
+++
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java
@@ -32,6 +32,8 @@ import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
+import com.cloud.agent.properties.AgentProperties;
+import com.cloud.agent.properties.AgentPropertiesFileHandler;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.utils.cryptsetup.KeyFile;
import org.apache.cloudstack.utils.qemu.QemuImageOptions;
@@ -1315,14 +1317,22 @@ public class LibvirtStorageAdaptor implements
StorageAdaptor {
passphraseObjects.add(QemuObject.prepareSecretForQemuImg(format,
QemuObject.EncryptFormat.LUKS, keyFile.toString(), "sec0", options));
disk.setQemuEncryptFormat(QemuObject.EncryptFormat.LUKS);
}
+
+ QemuImgFile srcFile = new QemuImgFile(template.getPath(),
template.getFormat());
+ Boolean createFullClone =
AgentPropertiesFileHandler.getPropertyValue(AgentProperties.CREATE_FULL_CLONE);
switch(provisioningType){
case THIN:
- QemuImgFile backingFile = new
QemuImgFile(template.getPath(), template.getFormat());
- qemu.create(destFile, backingFile, options,
passphraseObjects);
+ logger.info("Creating volume [{}] {} backing file [{}]
as the property [{}] is [{}].", destFile.getFileName(), createFullClone ?
"without" : "with",
+ template.getPath(),
AgentProperties.CREATE_FULL_CLONE.getName(), createFullClone);
+ if (createFullClone) {
+ qemu.convert(srcFile, destFile, options,
passphraseObjects, null, false);
+ } else {
+ qemu.create(destFile, srcFile, options,
passphraseObjects);
+ }
break;
case SPARSE:
case FAT:
- QemuImgFile srcFile = new
QemuImgFile(template.getPath(), template.getFormat());
+ srcFile = new QemuImgFile(template.getPath(),
template.getFormat());
qemu.convert(srcFile, destFile, options,
passphraseObjects, null, false);
break;
}