Skip to content

Commit a419b97

Browse files
committed
SharedMountPoint storage improvements
SharedMountPoint pools were treated as a generic libvirt-managed pool type instead of the plain directory-based pool they actually are (same libvirt DIR backend as Filesystem/NetworkFilesystem), causing: - Data disks (fresh empty volumes) created via createPhysicalDisk() went through createPhysicalDiskByLibVirt() (libvirt's virStorageVolCreateXML()), which defaults new qcow2 volumes to compat=0.10 on libvirt < 10.2.0. ROOT disks cloned from a template already ended up at compat=1.1 regardless of pool type, since createDiskFromTemplate() always finishes with a direct qemu-img call — so the same SharedMountPoint pool produced inconsistent qcow2 versions depending on whether the disk came from a template or was created empty. - SharedMountPoint destinations were missing from poolTypesThatEnableCreateDiskFromTemplateBacking, so migrating a linked-clone volume onto a SharedMountPoint pool silently no-op'd disk creation (no exception, no fallback), even though the orchestration layer already assumes SharedMountPoint supports linked clones. - SharedMountPoint volumes never received the thin/sparse/fat preallocation option that NFS/Filesystem volumes get. - Volume encryption was silently broken: SharedMountPoint already declares EncryptionSupport.Hypervisor and the allocator/API layers already allow requesting an encrypted disk offering on it, but createPhysicalDiskByLibVirt() has no passphrase parameter at all, so the passphrase generated for the volume was silently dropped and the disk was created unencrypted with no error. This was a real, reachable data-at-rest security bug, not a dormant path. Fix: extract NetworkFilesystem/Filesystem/SharedMountPoint into a single QEMU_IMG_MANAGED_POOL_TYPES constant and route SharedMountPoint through the same qemu-img-based creation path as NFS/Filesystem everywhere that set is consulted, so it now creates qcow2 v3 (compat=1.1) volumes consistently, supports linked-clone migration, honors provisioning-type preallocation, and correctly encrypts volumes when requested (verified via qemu-img info showing encrypted: yes / format: luks on a freshly created SharedMountPoint disk).
1 parent 21b2025 commit a419b97

1 file changed

Lines changed: 11 additions & 8 deletions

File tree

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import java.util.ArrayList;
2525
import java.util.Arrays;
2626
import java.util.HashMap;
27-
import java.util.HashSet;
2827
import java.util.List;
2928
import java.util.Map;
3029
import java.util.Set;
@@ -97,8 +96,12 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
9796
public static final int RBD_FEATURES = RBD_FEATURE_LAYERING + RBD_FEATURE_EXCLUSIVE_LOCK + RBD_FEATURE_OBJECT_MAP + RBD_FEATURE_FAST_DIFF + RBD_FEATURE_DEEP_FLATTEN;
9897
private int rbdOrder = 0; /* Order 0 means 4MB blocks (the default) */
9998

100-
private static final Set<StoragePoolType> poolTypesThatEnableCreateDiskFromTemplateBacking = new HashSet<>(Arrays.asList(StoragePoolType.NetworkFilesystem,
101-
StoragePoolType.Filesystem));
99+
/**
100+
* Pool types whose physical disks are created directly via {@code qemu-img} against a plain host directory
101+
* path (rather than through libvirt's {@code virStorageVolCreateXML()}).
102+
*/
103+
private static final Set<StoragePoolType> QEMU_IMG_MANAGED_POOL_TYPES = Set.of(StoragePoolType.NetworkFilesystem,
104+
StoragePoolType.Filesystem, StoragePoolType.SharedMountPoint);
102105

103106
public LibvirtStorageAdaptor(StorageLayer storage) {
104107
_storageLayer = storage;
@@ -134,8 +137,8 @@ public KVMPhysicalDisk createDiskFromTemplateBacking(KVMPhysicalDisk template, S
134137
String volumeDesc = String.format("volume [%s], with template backing [%s], in pool [%s] (%s), with size [%s] and encryption is %s", name, template.getName(), destPool.getUuid(),
135138
destPool.getType(), size, passphrase != null && passphrase.length > 0);
136139

137-
if (!poolTypesThatEnableCreateDiskFromTemplateBacking.contains(destPool.getType())) {
138-
logger.info(String.format("Skipping creation of %s due to pool type is none of the following types %s.", volumeDesc, poolTypesThatEnableCreateDiskFromTemplateBacking.stream()
140+
if (!QEMU_IMG_MANAGED_POOL_TYPES.contains(destPool.getType())) {
141+
logger.info(String.format("Skipping creation of %s due to pool type is none of the following types %s.", volumeDesc, QEMU_IMG_MANAGED_POOL_TYPES.stream()
139142
.map(type -> type.toString()).collect(Collectors.joining(", "))));
140143

141144
return null;
@@ -979,7 +982,7 @@ public boolean deleteStoragePool(String uuid) {
979982
* </ul>
980983
* </li>
981984
* <li>
982-
* {@link StoragePoolType#NetworkFilesystem} and {@link StoragePoolType#Filesystem}
985+
* {@link StoragePoolType#NetworkFilesystem}, {@link StoragePoolType#Filesystem} and {@link StoragePoolType#SharedMountPoint}
983986
* <ul>
984987
* <li>
985988
* If the format is {@link PhysicalDiskFormat#QCOW2} or {@link PhysicalDiskFormat#RAW}, utilizes QemuImg to create the physical disk through the method
@@ -1010,7 +1013,7 @@ public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool,
10101013

10111014
return (dataPool == null) ? createPhysicalDiskByLibVirt(name, pool, PhysicalDiskFormat.RAW, provisioningType, size) :
10121015
createPhysicalDiskByQemuImg(name, pool, PhysicalDiskFormat.RAW, provisioningType, size, passphrase);
1013-
} else if (StoragePoolType.NetworkFilesystem.equals(poolType) || StoragePoolType.Filesystem.equals(poolType)) {
1016+
} else if (QEMU_IMG_MANAGED_POOL_TYPES.contains(poolType)) {
10141017
switch (format) {
10151018
case QCOW2:
10161019
case RAW:
@@ -1080,7 +1083,7 @@ private KVMPhysicalDisk createPhysicalDiskByQemuImg(String name, KVMStoragePool
10801083
destFile.setFormat(format);
10811084
destFile.setSize(size);
10821085
Map<String, String> options = new HashMap<String, String>();
1083-
if (List.of(StoragePoolType.NetworkFilesystem, StoragePoolType.Filesystem).contains(pool.getType())) {
1086+
if (QEMU_IMG_MANAGED_POOL_TYPES.contains(pool.getType())) {
10841087
options.put(QemuImg.PREALLOCATION, QemuImg.PreallocationType.getPreallocationType(provisioningType).toString());
10851088
}
10861089

0 commit comments

Comments
 (0)