Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
import org.apache.cloudstack.vm.UnmanagedInstanceTO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

import com.cloud.agent.api.BackupSnapshotCommand;
Expand Down Expand Up @@ -1393,6 +1394,9 @@ public Pair<UnmanagedInstanceTO, Boolean> getHypervisorVMOutOfBandAndCloneIfRequ
String datacenter = params.get(VmDetailConstants.VMWARE_DATACENTER_NAME);
String username = params.get(VmDetailConstants.VMWARE_VCENTER_USERNAME);
String password = params.get(VmDetailConstants.VMWARE_VCENTER_PASSWORD);
Integer requestedCpuNumber = params.containsKey(VmDetailConstants.CPU_NUMBER) ? Integer.parseInt(params.get(VmDetailConstants.CPU_NUMBER)) : null;
Integer requestedCpuSpeed = params.containsKey(VmDetailConstants.CPU_SPEED) ? Integer.parseInt(params.get(VmDetailConstants.CPU_SPEED)) : null;
Integer requestedMemory = params.containsKey(VmDetailConstants.MEMORY) ? Integer.parseInt(params.get(VmDetailConstants.MEMORY)) : null;

try {
VmwareContext context = connectToVcenter(vcenter, username, password);
Expand Down Expand Up @@ -1428,6 +1432,8 @@ public Pair<UnmanagedInstanceTO, Boolean> getHypervisorVMOutOfBandAndCloneIfRequ
}
}

checkSourceVmResourcesAgainstSelectedOfferingResources(vmMo, requestedCpuNumber, requestedCpuSpeed, requestedMemory);

logger.debug(String.format("Cloning VM %s at VMware host %s on vCenter %s", vmName, hostIp, vcenter));
VirtualMachineMO clonedVM = createCloneFromSourceVM(vmName, vmMo, dataCenterMO);
logger.debug(String.format("VM %s cloned successfully, to VM %s", vmName, clonedVM.getName()));
Expand All @@ -1444,6 +1450,29 @@ public Pair<UnmanagedInstanceTO, Boolean> getHypervisorVMOutOfBandAndCloneIfRequ
}
}

protected void checkSourceVmResourcesAgainstSelectedOfferingResources(VirtualMachineMO vmMo, Integer requestedCpuNumber, Integer requestedCpuSpeed, Integer requestedMemory) throws Exception {
if (ObjectUtils.allNull(requestedCpuNumber, requestedCpuSpeed, requestedMemory)) {
return;
}
VirtualMachineConfigSummary configSummary = vmMo.getConfigSummary();
if (configSummary != null) {
compareSourceVmResourceAgainstRequested(configSummary.getNumCpu(), requestedCpuNumber, "CPU number");
compareSourceVmResourceAgainstRequested(configSummary.getCpuReservation(), requestedCpuSpeed, "CPU speed");
compareSourceVmResourceAgainstRequested(configSummary.getMemorySizeMB(), requestedMemory, "Memory");
}
}

protected void compareSourceVmResourceAgainstRequested(Integer actualResource, Integer requestedResource, String resourceName) throws Exception {
if (ObjectUtils.anyNull(actualResource, requestedResource)) {
return;
}
if (requestedResource < actualResource) {
String err = String.format("The requested %s (%d) is less than the source VM %s (%d)", resourceName, requestedResource, resourceName, actualResource);
logger.error(err);
throw new CloudRuntimeException(err);
}
}

private boolean isWindowsVm(VirtualMachineMO vmMo) throws Exception {
UnmanagedInstanceTO sourceInstance = VmwareHelper.getUnmanagedInstance(vmMo.getRunningHost(), vmMo);
return sourceInstance.getOperatingSystem().toLowerCase().contains("windows");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.util.List;
import java.util.Map;

import com.vmware.vim25.VirtualMachineConfigSummary;
import org.apache.cloudstack.storage.NfsMountManager;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
Expand Down Expand Up @@ -626,4 +627,24 @@ public void testRemoveVMTemplateFileOutOfBand() throws Exception {
boolean result = vMwareGuru.removeVMTemplateOutOfBand(dataStore, templateDir);
assertTrue(result);
}

@Test(expected = CloudRuntimeException.class)
public void testCheckSourceVmResourcesAgainstSelectedOfferingResourcesInsufficientMemory() throws Exception {
VirtualMachineMO virtualMachineMO = Mockito.mock(VirtualMachineMO.class);
VirtualMachineConfigSummary configSummary = Mockito.mock(VirtualMachineConfigSummary.class);
Mockito.when(virtualMachineMO.getConfigSummary()).thenReturn(configSummary);
Mockito.when(configSummary.getNumCpu()).thenReturn(1);
Mockito.when(configSummary.getMemorySizeMB()).thenReturn(2048);
vMwareGuru.checkSourceVmResourcesAgainstSelectedOfferingResources(virtualMachineMO, 1, 500, 1024);
}

@Test
public void testCheckSourceVmResourcesAgainstSelectedOfferingResourcesGreaterOffering() throws Exception {
VirtualMachineMO virtualMachineMO = Mockito.mock(VirtualMachineMO.class);
VirtualMachineConfigSummary configSummary = Mockito.mock(VirtualMachineConfigSummary.class);
Mockito.when(virtualMachineMO.getConfigSummary()).thenReturn(configSummary);
Mockito.when(configSummary.getNumCpu()).thenReturn(1);
Mockito.when(configSummary.getMemorySizeMB()).thenReturn(1024);
vMwareGuru.checkSourceVmResourcesAgainstSelectedOfferingResources(virtualMachineMO, 2, 1500, 2048);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1644,16 +1644,45 @@ private UserVm importUnmanagedInstanceFromHypervisor(DataCenter zone, Cluster cl
}

private Pair<UnmanagedInstanceTO, Boolean> getSourceVmwareUnmanagedInstance(String vcenter, String datacenterName, String username,
String password, String clusterName, String sourceHostName,
String sourceVM) {
String password, String clusterName, String sourceHostName,
String sourceVM, ServiceOfferingVO serviceOffering) {
HypervisorGuru vmwareGuru = hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware);

Map<String, String> params = createParamsForTemplateFromVmwareVmMigration(vcenter, datacenterName,
username, password, clusterName, sourceHostName, sourceVM);
addServiceOfferingDetailsToParams(params, serviceOffering);

return vmwareGuru.getHypervisorVMOutOfBandAndCloneIfRequired(sourceHostName, sourceVM, params);
}

/**
* Add the minimum resources to check on the hypervisor source VM before converting the instance against the selected offering resources
* @param params sets the minimum CPU number, CPU speed and memory to be checked against the source VM
* @param serviceOffering service offering for the converted VM
*/
protected void addServiceOfferingDetailsToParams(Map<String, String> params, ServiceOfferingVO serviceOffering) {
if (serviceOffering != null) {
serviceOfferingDao.loadDetails(serviceOffering);
Map<String, String> serviceOfferingDetails = serviceOffering.getDetails();

if (serviceOffering.getCpu() != null) {
params.put(VmDetailConstants.CPU_NUMBER, String.valueOf(serviceOffering.getCpu()));
} else if (MapUtils.isNotEmpty(serviceOfferingDetails) && serviceOfferingDetails.containsKey(ApiConstants.MIN_CPU_NUMBER)) {
params.put(VmDetailConstants.CPU_NUMBER, serviceOfferingDetails.get(ApiConstants.MIN_CPU_NUMBER));
}

if (serviceOffering.getSpeed() != null) {
params.put(VmDetailConstants.CPU_SPEED, String.valueOf(serviceOffering.getSpeed()));
}

if (serviceOffering.getRamSize() != null) {
params.put(VmDetailConstants.MEMORY, String.valueOf(serviceOffering.getRamSize()));
} else if (MapUtils.isNotEmpty(serviceOfferingDetails) && serviceOfferingDetails.containsKey(ApiConstants.MIN_MEMORY)) {
params.put(VmDetailConstants.MEMORY, serviceOfferingDetails.get(ApiConstants.MIN_MEMORY));
}
}
}

private String createOvfTemplateOfSourceVmwareUnmanagedInstance(String vcenter, String datacenterName, String username,
String password, String clusterName, String sourceHostName,
String sourceVMwareInstanceName, DataStoreTO convertLocation, int threadsCountToExportOvf) {
Expand Down Expand Up @@ -1734,7 +1763,7 @@ protected UserVm importUnmanagedInstanceFromVmwareToKvm(DataCenter zone, Cluster
// sourceVMwareInstance could be a cloned instance from sourceVMName, of the sourceVMName itself if its powered off.
// isClonedInstance indicates if the VM is a clone of sourceVMName

Pair<UnmanagedInstanceTO, Boolean> sourceInstanceDetails = getSourceVmwareUnmanagedInstance(vcenter, datacenterName, username, password, clusterName, sourceHostName, sourceVMName);
Pair<UnmanagedInstanceTO, Boolean> sourceInstanceDetails = getSourceVmwareUnmanagedInstance(vcenter, datacenterName, username, password, clusterName, sourceHostName, sourceVMName, serviceOffering);
sourceVMwareInstance = sourceInstanceDetails.first();
isClonedInstance = sourceInstanceDetails.second();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

import com.cloud.offering.DiskOffering;
import com.cloud.vm.ImportVMTaskVO;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ResponseGenerator;
import org.apache.cloudstack.api.ResponseObject;
import org.apache.cloudstack.api.ServerApiException;
Expand Down Expand Up @@ -1309,4 +1310,45 @@ public void testCheckExtraParamsAllowedEnabledParamNotInTheAllowedList() {
Mockito.when(configKeyMockParamsAllowedList.value()).thenReturn("network,x");
unmanagedVMsManager.checkExtraParamsAllowed("--mac 00:0c:29:e6:3d:9d:ip:192.168.0.89,192.168.0.1,24,192.168.0.254 -x");
}

@Test
public void testAddServiceOfferingDetailsToParamsFixedOffering() {
Map<String, String> params = new HashMap<>();
ServiceOfferingVO serviceOfferingVO = mock(ServiceOfferingVO.class);
Mockito.when(serviceOfferingVO.getCpu()).thenReturn(2);
Mockito.when(serviceOfferingVO.getRamSize()).thenReturn(2048);
unmanagedVMsManager.addServiceOfferingDetailsToParams(params, serviceOfferingVO);
Assert.assertEquals("2", params.get(VmDetailConstants.CPU_NUMBER));
Assert.assertEquals("2048", params.get(VmDetailConstants.MEMORY));
}

@Test
public void testAddServiceOfferingDetailsToParamsCustomConstrainedOffering() {
Map<String, String> params = new HashMap<>();
ServiceOfferingVO serviceOfferingVO = mock(ServiceOfferingVO.class);
Map<String, String> details = new HashMap<>();
details.put(ApiConstants.MIN_CPU_NUMBER, "1");
details.put(ApiConstants.MIN_MEMORY, "1024");
Mockito.when(serviceOfferingVO.getDetails()).thenReturn(details);
Mockito.when(serviceOfferingVO.getCpu()).thenReturn(null);
Mockito.when(serviceOfferingVO.getSpeed()).thenReturn(1500);
Mockito.when(serviceOfferingVO.getRamSize()).thenReturn(null);
unmanagedVMsManager.addServiceOfferingDetailsToParams(params, serviceOfferingVO);
Assert.assertEquals("1", params.get(VmDetailConstants.CPU_NUMBER));
Assert.assertEquals("1500", params.get(VmDetailConstants.CPU_SPEED));
Assert.assertEquals("1024", params.get(VmDetailConstants.MEMORY));
}

@Test
public void testAddServiceOfferingDetailsToParamsCustomUnconstrainedOffering() {
Map<String, String> params = new HashMap<>();
ServiceOfferingVO serviceOfferingVO = mock(ServiceOfferingVO.class);
Mockito.when(serviceOfferingVO.getCpu()).thenReturn(null);
Mockito.when(serviceOfferingVO.getSpeed()).thenReturn(null);
Mockito.when(serviceOfferingVO.getRamSize()).thenReturn(null);
unmanagedVMsManager.addServiceOfferingDetailsToParams(params, serviceOfferingVO);
Assert.assertFalse(params.containsKey(VmDetailConstants.CPU_NUMBER));
Assert.assertFalse(params.containsKey(VmDetailConstants.CPU_SPEED));
Assert.assertFalse(params.containsKey(VmDetailConstants.MEMORY));
}
}
Loading