Skip to content

Commit e25cf43

Browse files
author
Daan Hoogland
committed
Merge branch '4.20' into 4.22
2 parents bc3d7c3 + ef1aaa0 commit e25cf43

File tree

6 files changed

+119
-14
lines changed

6 files changed

+119
-14
lines changed

api/src/main/java/com/cloud/vm/VmDetailConstants.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ public interface VmDetailConstants {
5555
String NIC_MULTIQUEUE_NUMBER = "nic.multiqueue.number";
5656
String NIC_PACKED_VIRTQUEUES_ENABLED = "nic.packed.virtqueues.enabled";
5757

58+
// KVM specific, disk controllers
59+
String KVM_SKIP_FORCE_DISK_CONTROLLER = "skip.force.disk.controller";
60+
5861
// Mac OSX guest specific (internal)
5962
String SMC_PRESENT = "smc.present";
6063
String FIRMWARE = "firmware";

engine/schema/src/main/java/com/cloud/capacity/dao/CapacityDaoImpl.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,8 @@ public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements
213213

214214
private static final String LEFT_JOIN_VM_TEMPLATE = "LEFT JOIN vm_template ON vm_template.id = vi.vm_template_id ";
215215

216+
private static final String STORAGE_POOLS_WITH_CHILDREN = "SELECT DISTINCT parent FROM storage_pool WHERE parent != 0 AND removed IS NULL";
217+
216218
public CapacityDaoImpl() {
217219
_hostIdTypeSearch = createSearchBuilder();
218220
_hostIdTypeSearch.and("hostId", _hostIdTypeSearch.entity().getHostOrPoolId(), SearchCriteria.Op.EQ);
@@ -379,6 +381,11 @@ public List<SummedCapacity> listCapacitiesGroupedByLevelAndType(Integer capacity
379381
finalQuery.append(" AND capacity_type = ?");
380382
resourceIdList.add(capacityType.longValue());
381383
}
384+
385+
// Exclude storage pools with children from capacity calculations to avoid double counting
386+
finalQuery.append(" AND NOT (capacity.capacity_type = ").append(Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED)
387+
.append(" AND capacity.host_id IN (").append(STORAGE_POOLS_WITH_CHILDREN).append("))");
388+
382389
if (CollectionUtils.isNotEmpty(hostIds)) {
383390
finalQuery.append(String.format(" AND capacity.host_id IN (%s)", StringUtils.join(hostIds, ",")));
384391
if (capacityType == null) {
@@ -541,6 +548,10 @@ public List<SummedCapacity> findFilteredCapacityBy(Integer capacityType, Long zo
541548
StringBuilder sql = new StringBuilder(LIST_CAPACITY_GROUP_BY_CAPACITY_PART1);
542549
List<Long> resourceIdList = new ArrayList<Long>();
543550

551+
// Exclude storage pools with children from capacity calculations to avoid double counting
552+
sql.append(" AND NOT (capacity.capacity_type = ").append(Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED)
553+
.append(" AND capacity.host_id IN (").append(STORAGE_POOLS_WITH_CHILDREN).append("))");
554+
544555
if (zoneId != null) {
545556
sql.append(" AND capacity.data_center_id = ?");
546557
resourceIdList.add(zoneId);

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3481,6 +3481,44 @@ public static DiskDef.DiskType getDiskType(KVMPhysicalDisk physicalDisk) {
34813481
return useBLOCKDiskType(physicalDisk) ? DiskDef.DiskType.BLOCK : DiskDef.DiskType.FILE;
34823482
}
34833483

3484+
/**
3485+
* Defines the disk configuration for the default pool type based on the provided parameters.
3486+
* It determines the appropriate disk settings depending on whether the disk is a data disk, whether
3487+
* it's a Windows template, whether UEFI is enabled, and whether secure boot is active.
3488+
*
3489+
* @param disk The disk definition object that will be configured with the disk settings.
3490+
* @param volume The volume (disk) object, containing information about the type of disk.
3491+
* @param isWindowsTemplate Flag indicating whether the template is a Windows template.
3492+
* @param isUefiEnabled Flag indicating whether UEFI is enabled.
3493+
* @param isSecureBoot Flag indicating whether secure boot is enabled.
3494+
* @param physicalDisk The physical disk object that contains the path to the disk.
3495+
* @param devId The device ID for the disk.
3496+
* @param diskBusType The disk bus type to use if not skipping force disk controller.
3497+
* @param diskBusTypeData The disk bus type to use for data disks, if applicable.
3498+
* @param details A map of VM details containing additional configuration values, such as whether to skip force
3499+
* disk controller.
3500+
*/
3501+
protected void defineDiskForDefaultPoolType(DiskDef disk, DiskTO volume, boolean isWindowsTemplate,
3502+
boolean isUefiEnabled, boolean isSecureBoot, KVMPhysicalDisk physicalDisk, int devId,
3503+
DiskDef.DiskBus diskBusType, DiskDef.DiskBus diskBusTypeData, Map<String, String> details) {
3504+
boolean skipForceDiskController = MapUtils.getBoolean(details, VmDetailConstants.KVM_SKIP_FORCE_DISK_CONTROLLER,
3505+
false);
3506+
if (skipForceDiskController) {
3507+
disk.defFileBasedDisk(physicalDisk.getPath(), devId, Volume.Type.DATADISK.equals(volume.getType()) ?
3508+
diskBusTypeData : diskBusType, DiskDef.DiskFmtType.QCOW2);
3509+
return;
3510+
}
3511+
if (volume.getType() == Volume.Type.DATADISK && !(isWindowsTemplate && isUefiEnabled)) {
3512+
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusTypeData, DiskDef.DiskFmtType.QCOW2);
3513+
} else {
3514+
if (isSecureBoot) {
3515+
disk.defFileBasedDisk(physicalDisk.getPath(), devId, DiskDef.DiskFmtType.QCOW2, isWindowsTemplate);
3516+
} else {
3517+
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusType, DiskDef.DiskFmtType.QCOW2);
3518+
}
3519+
}
3520+
}
3521+
34843522
public void createVbd(final Connect conn, final VirtualMachineTO vmSpec, final String vmName, final LibvirtVMDef vm) throws InternalErrorException, LibvirtException, URISyntaxException {
34853523
final Map<String, String> details = vmSpec.getDetails();
34863524
final List<DiskTO> disks = Arrays.asList(vmSpec.getDisks());
@@ -3642,15 +3680,8 @@ public int compare(final DiskTO arg0, final DiskTO arg1) {
36423680
disk.setDiscard(DiscardType.UNMAP);
36433681
}
36443682
} else {
3645-
if (volume.getType() == Volume.Type.DATADISK && !(isWindowsTemplate && isUefiEnabled)) {
3646-
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusTypeData, DiskDef.DiskFmtType.QCOW2);
3647-
} else {
3648-
if (isSecureBoot) {
3649-
disk.defFileBasedDisk(physicalDisk.getPath(), devId, DiskDef.DiskFmtType.QCOW2, isWindowsTemplate);
3650-
} else {
3651-
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusType, DiskDef.DiskFmtType.QCOW2);
3652-
}
3653-
}
3683+
defineDiskForDefaultPoolType(disk, volume, isWindowsTemplate, isUefiEnabled, isSecureBoot,
3684+
physicalDisk, devId, diskBusType, diskBusTypeData, details);
36543685
}
36553686
pool.customizeLibvirtDiskDef(disk);
36563687
}

plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,9 @@
6161
import javax.xml.xpath.XPathExpressionException;
6262
import javax.xml.xpath.XPathFactory;
6363

64-
import com.cloud.utils.net.NetUtils;
65-
66-
import com.cloud.vm.VmDetailConstants;
6764
import com.google.gson.JsonObject;
6865
import com.google.gson.JsonParser;
66+
6967
import org.apache.cloudstack.api.ApiConstants.IoDriverPolicy;
7068
import org.apache.cloudstack.storage.command.AttachAnswer;
7169
import org.apache.cloudstack.storage.command.AttachCommand;
@@ -227,13 +225,15 @@
227225
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
228226
import com.cloud.utils.Pair;
229227
import com.cloud.utils.exception.CloudRuntimeException;
230-
import com.cloud.utils.script.Script;
228+
import com.cloud.utils.net.NetUtils;
231229
import com.cloud.utils.script.OutputInterpreter.OneLineParser;
230+
import com.cloud.utils.script.Script;
232231
import com.cloud.utils.ssh.SshHelper;
233232
import com.cloud.vm.DiskProfile;
234233
import com.cloud.vm.VirtualMachine;
235234
import com.cloud.vm.VirtualMachine.PowerState;
236235
import com.cloud.vm.VirtualMachine.Type;
236+
import com.cloud.vm.VmDetailConstants;
237237

238238
@RunWith(MockitoJUnitRunner.class)
239239
public class LibvirtComputingResourceTest {
@@ -250,6 +250,19 @@ public class LibvirtComputingResourceTest {
250250
Connect connMock;
251251
@Mock
252252
LibvirtDomainXMLParser parserMock;
253+
@Mock
254+
private DiskDef diskDef;
255+
@Mock
256+
private DiskTO volume;
257+
@Mock
258+
private KVMPhysicalDisk physicalDisk;
259+
@Mock
260+
private Map<String, String> details;
261+
262+
private static final String PHYSICAL_DISK_PATH = "/path/to/disk";
263+
private static final int DEV_ID = 1;
264+
private static final DiskDef.DiskBus DISK_BUS_TYPE = DiskDef.DiskBus.VIRTIO;
265+
private static final DiskDef.DiskBus DISK_BUS_TYPE_DATA = DiskDef.DiskBus.SCSI;
253266

254267
@Mock
255268
DiskTO diskToMock;
@@ -7142,4 +7155,49 @@ public void parseCpuFeaturesTestReturnListOfCpuFeaturesAndIgnoreMultipleWhitespa
71427155
Assert.assertEquals("-mmx", cpuFeatures.get(2));
71437156
Assert.assertEquals("hle", cpuFeatures.get(3));
71447157
}
7158+
7159+
@Test
7160+
public void defineDiskForDefaultPoolTypeSkipsForceDiskController() {
7161+
Map<String, String> details = new HashMap<>();
7162+
details.put(VmDetailConstants.KVM_SKIP_FORCE_DISK_CONTROLLER, "true");
7163+
Mockito.when(volume.getType()).thenReturn(Volume.Type.DATADISK);
7164+
Mockito.when(physicalDisk.getPath()).thenReturn(PHYSICAL_DISK_PATH);
7165+
libvirtComputingResourceSpy.defineDiskForDefaultPoolType(diskDef, volume, false, false, false, physicalDisk, DEV_ID, DISK_BUS_TYPE, DISK_BUS_TYPE_DATA, details);
7166+
Mockito.verify(diskDef).defFileBasedDisk(PHYSICAL_DISK_PATH, DEV_ID, DISK_BUS_TYPE_DATA, DiskDef.DiskFmtType.QCOW2);
7167+
}
7168+
7169+
@Test
7170+
public void defineDiskForDefaultPoolTypeUsesDiskBusTypeDataForDataDiskWithoutWindowsAndUefi() {
7171+
Map<String, String> details = new HashMap<>();
7172+
Mockito.when(volume.getType()).thenReturn(Volume.Type.DATADISK);
7173+
Mockito.when(physicalDisk.getPath()).thenReturn(PHYSICAL_DISK_PATH);
7174+
libvirtComputingResourceSpy.defineDiskForDefaultPoolType(diskDef, volume, false, false, false, physicalDisk, DEV_ID, DISK_BUS_TYPE, DISK_BUS_TYPE_DATA, details);
7175+
Mockito.verify(diskDef).defFileBasedDisk(PHYSICAL_DISK_PATH, DEV_ID, DISK_BUS_TYPE_DATA, DiskDef.DiskFmtType.QCOW2);
7176+
}
7177+
7178+
@Test
7179+
public void defineDiskForDefaultPoolTypeUsesDiskBusTypeForRootDisk() {
7180+
Map<String, String> details = new HashMap<>();
7181+
Mockito.when(volume.getType()).thenReturn(Volume.Type.ROOT);
7182+
Mockito.when(physicalDisk.getPath()).thenReturn(PHYSICAL_DISK_PATH);
7183+
libvirtComputingResourceSpy.defineDiskForDefaultPoolType(diskDef, volume, false, false, false, physicalDisk, DEV_ID, DISK_BUS_TYPE, DISK_BUS_TYPE_DATA, details);
7184+
Mockito.verify(diskDef).defFileBasedDisk(PHYSICAL_DISK_PATH, DEV_ID, DISK_BUS_TYPE, DiskDef.DiskFmtType.QCOW2);
7185+
}
7186+
7187+
@Test
7188+
public void defineDiskForDefaultPoolTypeUsesSecureBootConfiguration() {
7189+
Map<String, String> details = new HashMap<>();
7190+
Mockito.when(volume.getType()).thenReturn(Volume.Type.ROOT);
7191+
Mockito.when(physicalDisk.getPath()).thenReturn(PHYSICAL_DISK_PATH);
7192+
libvirtComputingResourceSpy.defineDiskForDefaultPoolType(diskDef, volume, true, true, true, physicalDisk, DEV_ID, DISK_BUS_TYPE, DISK_BUS_TYPE_DATA, details);
7193+
Mockito.verify(diskDef).defFileBasedDisk(PHYSICAL_DISK_PATH, DEV_ID, DiskDef.DiskFmtType.QCOW2, true);
7194+
}
7195+
7196+
@Test
7197+
public void defineDiskForDefaultPoolTypeHandlesNullDetails() {
7198+
Mockito.when(volume.getType()).thenReturn(Volume.Type.DATADISK);
7199+
Mockito.when(physicalDisk.getPath()).thenReturn(PHYSICAL_DISK_PATH);
7200+
libvirtComputingResourceSpy.defineDiskForDefaultPoolType(diskDef, volume, false, false, false, physicalDisk, DEV_ID, DISK_BUS_TYPE, DISK_BUS_TYPE_DATA, null);
7201+
Mockito.verify(diskDef).defFileBasedDisk(PHYSICAL_DISK_PATH, DEV_ID, DISK_BUS_TYPE_DATA, DiskDef.DiskFmtType.QCOW2);
7202+
}
71457203
}

server/src/main/java/com/cloud/api/query/QueryManagerImpl.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5390,6 +5390,7 @@ private void fillVMOrTemplateDetailOptions(final Map<String, List<String>> optio
53905390
options.put(VmDetailConstants.VIRTUAL_TPM_VERSION, Arrays.asList("1.2", "2.0"));
53915391
options.put(VmDetailConstants.GUEST_CPU_MODE, Arrays.asList("custom", "host-model", "host-passthrough"));
53925392
options.put(VmDetailConstants.GUEST_CPU_MODEL, Collections.emptyList());
5393+
options.put(VmDetailConstants.KVM_SKIP_FORCE_DISK_CONTROLLER, Arrays.asList("true", "false"));
53935394
}
53945395

53955396
if (HypervisorType.VMware.equals(hypervisorType)) {

server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2457,7 +2457,8 @@ private void validateVolumeResizeWithSize(VolumeVO volume, long currentSize, Lon
24572457
}
24582458
}
24592459

2460-
if (volume != null && ImageFormat.QCOW2.equals(volume.getFormat()) && !Volume.State.Allocated.equals(volume.getState()) && !StoragePoolType.StorPool.equals(volume.getPoolType())) {
2460+
if (volume != null && ImageFormat.QCOW2.equals(volume.getFormat()) && !Volume.State.Allocated.equals(volume.getState()) &&
2461+
!Arrays.asList(StoragePoolType.StorPool, StoragePoolType.Linstor).contains(volume.getPoolType())) {
24612462
String message = "Unable to shrink volumes of type QCOW2";
24622463
logger.warn(message);
24632464
throw new InvalidParameterValueException(message);

0 commit comments

Comments
 (0)