mirror of https://github.com/apache/cloudstack.git
Merge branch '4.20' into 4.22
This commit is contained in:
commit
e25cf437c0
|
|
@ -55,6 +55,9 @@ public interface VmDetailConstants {
|
||||||
String NIC_MULTIQUEUE_NUMBER = "nic.multiqueue.number";
|
String NIC_MULTIQUEUE_NUMBER = "nic.multiqueue.number";
|
||||||
String NIC_PACKED_VIRTQUEUES_ENABLED = "nic.packed.virtqueues.enabled";
|
String NIC_PACKED_VIRTQUEUES_ENABLED = "nic.packed.virtqueues.enabled";
|
||||||
|
|
||||||
|
// KVM specific, disk controllers
|
||||||
|
String KVM_SKIP_FORCE_DISK_CONTROLLER = "skip.force.disk.controller";
|
||||||
|
|
||||||
// Mac OSX guest specific (internal)
|
// Mac OSX guest specific (internal)
|
||||||
String SMC_PRESENT = "smc.present";
|
String SMC_PRESENT = "smc.present";
|
||||||
String FIRMWARE = "firmware";
|
String FIRMWARE = "firmware";
|
||||||
|
|
|
||||||
|
|
@ -213,6 +213,8 @@ public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements
|
||||||
|
|
||||||
private static final String LEFT_JOIN_VM_TEMPLATE = "LEFT JOIN vm_template ON vm_template.id = vi.vm_template_id ";
|
private static final String LEFT_JOIN_VM_TEMPLATE = "LEFT JOIN vm_template ON vm_template.id = vi.vm_template_id ";
|
||||||
|
|
||||||
|
private static final String STORAGE_POOLS_WITH_CHILDREN = "SELECT DISTINCT parent FROM storage_pool WHERE parent != 0 AND removed IS NULL";
|
||||||
|
|
||||||
public CapacityDaoImpl() {
|
public CapacityDaoImpl() {
|
||||||
_hostIdTypeSearch = createSearchBuilder();
|
_hostIdTypeSearch = createSearchBuilder();
|
||||||
_hostIdTypeSearch.and("hostId", _hostIdTypeSearch.entity().getHostOrPoolId(), SearchCriteria.Op.EQ);
|
_hostIdTypeSearch.and("hostId", _hostIdTypeSearch.entity().getHostOrPoolId(), SearchCriteria.Op.EQ);
|
||||||
|
|
@ -379,6 +381,11 @@ public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements
|
||||||
finalQuery.append(" AND capacity_type = ?");
|
finalQuery.append(" AND capacity_type = ?");
|
||||||
resourceIdList.add(capacityType.longValue());
|
resourceIdList.add(capacityType.longValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Exclude storage pools with children from capacity calculations to avoid double counting
|
||||||
|
finalQuery.append(" AND NOT (capacity.capacity_type = ").append(Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED)
|
||||||
|
.append(" AND capacity.host_id IN (").append(STORAGE_POOLS_WITH_CHILDREN).append("))");
|
||||||
|
|
||||||
if (CollectionUtils.isNotEmpty(hostIds)) {
|
if (CollectionUtils.isNotEmpty(hostIds)) {
|
||||||
finalQuery.append(String.format(" AND capacity.host_id IN (%s)", StringUtils.join(hostIds, ",")));
|
finalQuery.append(String.format(" AND capacity.host_id IN (%s)", StringUtils.join(hostIds, ",")));
|
||||||
if (capacityType == null) {
|
if (capacityType == null) {
|
||||||
|
|
@ -541,6 +548,10 @@ public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements
|
||||||
StringBuilder sql = new StringBuilder(LIST_CAPACITY_GROUP_BY_CAPACITY_PART1);
|
StringBuilder sql = new StringBuilder(LIST_CAPACITY_GROUP_BY_CAPACITY_PART1);
|
||||||
List<Long> resourceIdList = new ArrayList<Long>();
|
List<Long> resourceIdList = new ArrayList<Long>();
|
||||||
|
|
||||||
|
// Exclude storage pools with children from capacity calculations to avoid double counting
|
||||||
|
sql.append(" AND NOT (capacity.capacity_type = ").append(Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED)
|
||||||
|
.append(" AND capacity.host_id IN (").append(STORAGE_POOLS_WITH_CHILDREN).append("))");
|
||||||
|
|
||||||
if (zoneId != null) {
|
if (zoneId != null) {
|
||||||
sql.append(" AND capacity.data_center_id = ?");
|
sql.append(" AND capacity.data_center_id = ?");
|
||||||
resourceIdList.add(zoneId);
|
resourceIdList.add(zoneId);
|
||||||
|
|
|
||||||
|
|
@ -3481,6 +3481,44 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
||||||
return useBLOCKDiskType(physicalDisk) ? DiskDef.DiskType.BLOCK : DiskDef.DiskType.FILE;
|
return useBLOCKDiskType(physicalDisk) ? DiskDef.DiskType.BLOCK : DiskDef.DiskType.FILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the disk configuration for the default pool type based on the provided parameters.
|
||||||
|
* It determines the appropriate disk settings depending on whether the disk is a data disk, whether
|
||||||
|
* it's a Windows template, whether UEFI is enabled, and whether secure boot is active.
|
||||||
|
*
|
||||||
|
* @param disk The disk definition object that will be configured with the disk settings.
|
||||||
|
* @param volume The volume (disk) object, containing information about the type of disk.
|
||||||
|
* @param isWindowsTemplate Flag indicating whether the template is a Windows template.
|
||||||
|
* @param isUefiEnabled Flag indicating whether UEFI is enabled.
|
||||||
|
* @param isSecureBoot Flag indicating whether secure boot is enabled.
|
||||||
|
* @param physicalDisk The physical disk object that contains the path to the disk.
|
||||||
|
* @param devId The device ID for the disk.
|
||||||
|
* @param diskBusType The disk bus type to use if not skipping force disk controller.
|
||||||
|
* @param diskBusTypeData The disk bus type to use for data disks, if applicable.
|
||||||
|
* @param details A map of VM details containing additional configuration values, such as whether to skip force
|
||||||
|
* disk controller.
|
||||||
|
*/
|
||||||
|
protected void defineDiskForDefaultPoolType(DiskDef disk, DiskTO volume, boolean isWindowsTemplate,
|
||||||
|
boolean isUefiEnabled, boolean isSecureBoot, KVMPhysicalDisk physicalDisk, int devId,
|
||||||
|
DiskDef.DiskBus diskBusType, DiskDef.DiskBus diskBusTypeData, Map<String, String> details) {
|
||||||
|
boolean skipForceDiskController = MapUtils.getBoolean(details, VmDetailConstants.KVM_SKIP_FORCE_DISK_CONTROLLER,
|
||||||
|
false);
|
||||||
|
if (skipForceDiskController) {
|
||||||
|
disk.defFileBasedDisk(physicalDisk.getPath(), devId, Volume.Type.DATADISK.equals(volume.getType()) ?
|
||||||
|
diskBusTypeData : diskBusType, DiskDef.DiskFmtType.QCOW2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (volume.getType() == Volume.Type.DATADISK && !(isWindowsTemplate && isUefiEnabled)) {
|
||||||
|
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusTypeData, DiskDef.DiskFmtType.QCOW2);
|
||||||
|
} else {
|
||||||
|
if (isSecureBoot) {
|
||||||
|
disk.defFileBasedDisk(physicalDisk.getPath(), devId, DiskDef.DiskFmtType.QCOW2, isWindowsTemplate);
|
||||||
|
} else {
|
||||||
|
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusType, DiskDef.DiskFmtType.QCOW2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void createVbd(final Connect conn, final VirtualMachineTO vmSpec, final String vmName, final LibvirtVMDef vm) throws InternalErrorException, LibvirtException, URISyntaxException {
|
public void createVbd(final Connect conn, final VirtualMachineTO vmSpec, final String vmName, final LibvirtVMDef vm) throws InternalErrorException, LibvirtException, URISyntaxException {
|
||||||
final Map<String, String> details = vmSpec.getDetails();
|
final Map<String, String> details = vmSpec.getDetails();
|
||||||
final List<DiskTO> disks = Arrays.asList(vmSpec.getDisks());
|
final List<DiskTO> disks = Arrays.asList(vmSpec.getDisks());
|
||||||
|
|
@ -3642,15 +3680,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
||||||
disk.setDiscard(DiscardType.UNMAP);
|
disk.setDiscard(DiscardType.UNMAP);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (volume.getType() == Volume.Type.DATADISK && !(isWindowsTemplate && isUefiEnabled)) {
|
defineDiskForDefaultPoolType(disk, volume, isWindowsTemplate, isUefiEnabled, isSecureBoot,
|
||||||
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusTypeData, DiskDef.DiskFmtType.QCOW2);
|
physicalDisk, devId, diskBusType, diskBusTypeData, details);
|
||||||
} else {
|
|
||||||
if (isSecureBoot) {
|
|
||||||
disk.defFileBasedDisk(physicalDisk.getPath(), devId, DiskDef.DiskFmtType.QCOW2, isWindowsTemplate);
|
|
||||||
} else {
|
|
||||||
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusType, DiskDef.DiskFmtType.QCOW2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pool.customizeLibvirtDiskDef(disk);
|
pool.customizeLibvirtDiskDef(disk);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,11 +61,9 @@ import javax.xml.xpath.XPathConstants;
|
||||||
import javax.xml.xpath.XPathExpressionException;
|
import javax.xml.xpath.XPathExpressionException;
|
||||||
import javax.xml.xpath.XPathFactory;
|
import javax.xml.xpath.XPathFactory;
|
||||||
|
|
||||||
import com.cloud.utils.net.NetUtils;
|
|
||||||
|
|
||||||
import com.cloud.vm.VmDetailConstants;
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
|
|
||||||
import org.apache.cloudstack.api.ApiConstants.IoDriverPolicy;
|
import org.apache.cloudstack.api.ApiConstants.IoDriverPolicy;
|
||||||
import org.apache.cloudstack.storage.command.AttachAnswer;
|
import org.apache.cloudstack.storage.command.AttachAnswer;
|
||||||
import org.apache.cloudstack.storage.command.AttachCommand;
|
import org.apache.cloudstack.storage.command.AttachCommand;
|
||||||
|
|
@ -227,13 +225,15 @@ import com.cloud.storage.template.TemplateLocation;
|
||||||
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
|
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
|
||||||
import com.cloud.utils.Pair;
|
import com.cloud.utils.Pair;
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
import com.cloud.utils.script.Script;
|
import com.cloud.utils.net.NetUtils;
|
||||||
import com.cloud.utils.script.OutputInterpreter.OneLineParser;
|
import com.cloud.utils.script.OutputInterpreter.OneLineParser;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
import com.cloud.utils.ssh.SshHelper;
|
import com.cloud.utils.ssh.SshHelper;
|
||||||
import com.cloud.vm.DiskProfile;
|
import com.cloud.vm.DiskProfile;
|
||||||
import com.cloud.vm.VirtualMachine;
|
import com.cloud.vm.VirtualMachine;
|
||||||
import com.cloud.vm.VirtualMachine.PowerState;
|
import com.cloud.vm.VirtualMachine.PowerState;
|
||||||
import com.cloud.vm.VirtualMachine.Type;
|
import com.cloud.vm.VirtualMachine.Type;
|
||||||
|
import com.cloud.vm.VmDetailConstants;
|
||||||
|
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
public class LibvirtComputingResourceTest {
|
public class LibvirtComputingResourceTest {
|
||||||
|
|
@ -250,6 +250,19 @@ public class LibvirtComputingResourceTest {
|
||||||
Connect connMock;
|
Connect connMock;
|
||||||
@Mock
|
@Mock
|
||||||
LibvirtDomainXMLParser parserMock;
|
LibvirtDomainXMLParser parserMock;
|
||||||
|
@Mock
|
||||||
|
private DiskDef diskDef;
|
||||||
|
@Mock
|
||||||
|
private DiskTO volume;
|
||||||
|
@Mock
|
||||||
|
private KVMPhysicalDisk physicalDisk;
|
||||||
|
@Mock
|
||||||
|
private Map<String, String> details;
|
||||||
|
|
||||||
|
private static final String PHYSICAL_DISK_PATH = "/path/to/disk";
|
||||||
|
private static final int DEV_ID = 1;
|
||||||
|
private static final DiskDef.DiskBus DISK_BUS_TYPE = DiskDef.DiskBus.VIRTIO;
|
||||||
|
private static final DiskDef.DiskBus DISK_BUS_TYPE_DATA = DiskDef.DiskBus.SCSI;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
DiskTO diskToMock;
|
DiskTO diskToMock;
|
||||||
|
|
@ -7142,4 +7155,49 @@ public class LibvirtComputingResourceTest {
|
||||||
Assert.assertEquals("-mmx", cpuFeatures.get(2));
|
Assert.assertEquals("-mmx", cpuFeatures.get(2));
|
||||||
Assert.assertEquals("hle", cpuFeatures.get(3));
|
Assert.assertEquals("hle", cpuFeatures.get(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void defineDiskForDefaultPoolTypeSkipsForceDiskController() {
|
||||||
|
Map<String, String> details = new HashMap<>();
|
||||||
|
details.put(VmDetailConstants.KVM_SKIP_FORCE_DISK_CONTROLLER, "true");
|
||||||
|
Mockito.when(volume.getType()).thenReturn(Volume.Type.DATADISK);
|
||||||
|
Mockito.when(physicalDisk.getPath()).thenReturn(PHYSICAL_DISK_PATH);
|
||||||
|
libvirtComputingResourceSpy.defineDiskForDefaultPoolType(diskDef, volume, false, false, false, physicalDisk, DEV_ID, DISK_BUS_TYPE, DISK_BUS_TYPE_DATA, details);
|
||||||
|
Mockito.verify(diskDef).defFileBasedDisk(PHYSICAL_DISK_PATH, DEV_ID, DISK_BUS_TYPE_DATA, DiskDef.DiskFmtType.QCOW2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void defineDiskForDefaultPoolTypeUsesDiskBusTypeDataForDataDiskWithoutWindowsAndUefi() {
|
||||||
|
Map<String, String> details = new HashMap<>();
|
||||||
|
Mockito.when(volume.getType()).thenReturn(Volume.Type.DATADISK);
|
||||||
|
Mockito.when(physicalDisk.getPath()).thenReturn(PHYSICAL_DISK_PATH);
|
||||||
|
libvirtComputingResourceSpy.defineDiskForDefaultPoolType(diskDef, volume, false, false, false, physicalDisk, DEV_ID, DISK_BUS_TYPE, DISK_BUS_TYPE_DATA, details);
|
||||||
|
Mockito.verify(diskDef).defFileBasedDisk(PHYSICAL_DISK_PATH, DEV_ID, DISK_BUS_TYPE_DATA, DiskDef.DiskFmtType.QCOW2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void defineDiskForDefaultPoolTypeUsesDiskBusTypeForRootDisk() {
|
||||||
|
Map<String, String> details = new HashMap<>();
|
||||||
|
Mockito.when(volume.getType()).thenReturn(Volume.Type.ROOT);
|
||||||
|
Mockito.when(physicalDisk.getPath()).thenReturn(PHYSICAL_DISK_PATH);
|
||||||
|
libvirtComputingResourceSpy.defineDiskForDefaultPoolType(diskDef, volume, false, false, false, physicalDisk, DEV_ID, DISK_BUS_TYPE, DISK_BUS_TYPE_DATA, details);
|
||||||
|
Mockito.verify(diskDef).defFileBasedDisk(PHYSICAL_DISK_PATH, DEV_ID, DISK_BUS_TYPE, DiskDef.DiskFmtType.QCOW2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void defineDiskForDefaultPoolTypeUsesSecureBootConfiguration() {
|
||||||
|
Map<String, String> details = new HashMap<>();
|
||||||
|
Mockito.when(volume.getType()).thenReturn(Volume.Type.ROOT);
|
||||||
|
Mockito.when(physicalDisk.getPath()).thenReturn(PHYSICAL_DISK_PATH);
|
||||||
|
libvirtComputingResourceSpy.defineDiskForDefaultPoolType(diskDef, volume, true, true, true, physicalDisk, DEV_ID, DISK_BUS_TYPE, DISK_BUS_TYPE_DATA, details);
|
||||||
|
Mockito.verify(diskDef).defFileBasedDisk(PHYSICAL_DISK_PATH, DEV_ID, DiskDef.DiskFmtType.QCOW2, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void defineDiskForDefaultPoolTypeHandlesNullDetails() {
|
||||||
|
Mockito.when(volume.getType()).thenReturn(Volume.Type.DATADISK);
|
||||||
|
Mockito.when(physicalDisk.getPath()).thenReturn(PHYSICAL_DISK_PATH);
|
||||||
|
libvirtComputingResourceSpy.defineDiskForDefaultPoolType(diskDef, volume, false, false, false, physicalDisk, DEV_ID, DISK_BUS_TYPE, DISK_BUS_TYPE_DATA, null);
|
||||||
|
Mockito.verify(diskDef).defFileBasedDisk(PHYSICAL_DISK_PATH, DEV_ID, DISK_BUS_TYPE_DATA, DiskDef.DiskFmtType.QCOW2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5390,6 +5390,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||||
options.put(VmDetailConstants.VIRTUAL_TPM_VERSION, Arrays.asList("1.2", "2.0"));
|
options.put(VmDetailConstants.VIRTUAL_TPM_VERSION, Arrays.asList("1.2", "2.0"));
|
||||||
options.put(VmDetailConstants.GUEST_CPU_MODE, Arrays.asList("custom", "host-model", "host-passthrough"));
|
options.put(VmDetailConstants.GUEST_CPU_MODE, Arrays.asList("custom", "host-model", "host-passthrough"));
|
||||||
options.put(VmDetailConstants.GUEST_CPU_MODEL, Collections.emptyList());
|
options.put(VmDetailConstants.GUEST_CPU_MODEL, Collections.emptyList());
|
||||||
|
options.put(VmDetailConstants.KVM_SKIP_FORCE_DISK_CONTROLLER, Arrays.asList("true", "false"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HypervisorType.VMware.equals(hypervisorType)) {
|
if (HypervisorType.VMware.equals(hypervisorType)) {
|
||||||
|
|
|
||||||
|
|
@ -2457,7 +2457,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (volume != null && ImageFormat.QCOW2.equals(volume.getFormat()) && !Volume.State.Allocated.equals(volume.getState()) && !StoragePoolType.StorPool.equals(volume.getPoolType())) {
|
if (volume != null && ImageFormat.QCOW2.equals(volume.getFormat()) && !Volume.State.Allocated.equals(volume.getState()) &&
|
||||||
|
!Arrays.asList(StoragePoolType.StorPool, StoragePoolType.Linstor).contains(volume.getPoolType())) {
|
||||||
String message = "Unable to shrink volumes of type QCOW2";
|
String message = "Unable to shrink volumes of type QCOW2";
|
||||||
logger.warn(message);
|
logger.warn(message);
|
||||||
throw new InvalidParameterValueException(message);
|
throw new InvalidParameterValueException(message);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue