diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index fdbc244997d0..d6322ab3afad 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -94,6 +94,7 @@ import com.vmware.vim25.VirtualMachineRelocateSpec; import com.vmware.vim25.VirtualMachineRelocateSpecDiskLocator; import com.vmware.vim25.VirtualMachineRuntimeInfo; +import com.vmware.vim25.VirtualMachineVideoCard; import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec; import org.apache.cloudstack.storage.command.StorageSubSystemCommand; @@ -1895,6 +1896,8 @@ protected StartAnswer execute(StartCommand cmd) { postDiskConfigBeforeStart(vmMo, vmSpec, sortedDisks, ideControllerKey, scsiControllerKey, iqnToPath, hyperHost, context); + postVideoCardMemoryConfigBeforeStart(vmMo, vmSpec); + // // Power-on VM // @@ -1943,6 +1946,79 @@ protected StartAnswer execute(StartCommand cmd) { } } + /** + * Sets video card memory to the one provided in detail svga.vramSize (if provided). + * 64MB was always set before. + * Size must be in KB. + * @param vmMo virtual machine mo + * @param vmSpec virtual machine specs + */ + protected void postVideoCardMemoryConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachineTO vmSpec) { + String paramVRamSize = "svga.vramSize"; + if (vmSpec.getDetails().containsKey(paramVRamSize)){ + String value = vmSpec.getDetails().get(paramVRamSize); + try { + long svgaVmramSize = Long.parseLong(value); + setNewVRamSizeVmVideoCard(vmMo, svgaVmramSize); + } + catch (NumberFormatException e){ + s_logger.error("Unexpected value, cannot parse " + value + " to long due to: " + e.getMessage()); + } + catch (Exception e){ + s_logger.error("Error while reconfiguring vm due to: " + e.getMessage()); + } + } + } + + /** + * Search for vm video card iterating through vm device list + * @param vmMo virtual machine mo + * @param svgaVmramSize new svga vram size (in KB) + */ + private void setNewVRamSizeVmVideoCard(VirtualMachineMO vmMo, long svgaVmramSize) throws Exception { + for (VirtualDevice device : vmMo.getAllDeviceList()){ + if (device instanceof VirtualMachineVideoCard){ + VirtualMachineVideoCard videoCard = (VirtualMachineVideoCard) device; + modifyVmVideoCardVRamSize(videoCard, vmMo, svgaVmramSize); + } + } + } + + /** + * Modifies vm vram size if it was set to a different size to the one provided in svga.vramSize (user_vm_details or template_vm_details) + * @param videoCard vm's video card device + * @param vmMo virtual machine mo + * @param svgaVmramSize new svga vram size (in KB) + */ + private void modifyVmVideoCardVRamSize(VirtualMachineVideoCard videoCard, VirtualMachineMO vmMo, long svgaVmramSize) throws Exception { + if (videoCard.getVideoRamSizeInKB().longValue() != svgaVmramSize){ + s_logger.info("Video card memory was set " + videoCard.getVideoRamSizeInKB().longValue() + "kb instead of " + svgaVmramSize + "kb"); + VirtualMachineConfigSpec newSizeSpecs = configSpecVideoCardNewVRamSize(videoCard, svgaVmramSize); + boolean res = vmMo.configureVm(newSizeSpecs); + if (res) { + s_logger.info("Video card memory successfully updated to " + svgaVmramSize + "kb"); + } + } + } + + /** + * Returns a VirtualMachineConfigSpec to edit its svga vram size + * @param videoCard video card device to edit providing the svga vram size + * @param svgaVmramSize new svga vram size (in KB) + */ + private VirtualMachineConfigSpec configSpecVideoCardNewVRamSize(VirtualMachineVideoCard videoCard, long svgaVmramSize){ + videoCard.setVideoRamSizeInKB(svgaVmramSize); + videoCard.setUseAutoDetect(false); + + VirtualDeviceConfigSpec arrayVideoCardConfigSpecs = new VirtualDeviceConfigSpec(); + arrayVideoCardConfigSpecs.setDevice(videoCard); + arrayVideoCardConfigSpecs.setOperation(VirtualDeviceConfigSpecOperation.EDIT); + + VirtualMachineConfigSpec changeVideoCardSpecs = new VirtualMachineConfigSpec(); + changeVideoCardSpecs.getDeviceChange().add(arrayVideoCardConfigSpecs); + return changeVideoCardSpecs; + } + private void tearDownVm(VirtualMachineMO vmMo) throws Exception{ if(vmMo == null) return; diff --git a/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java b/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java index 2e3d41c0485d..f554da9b3951 100644 --- a/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java +++ b/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java @@ -19,6 +19,12 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.any; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import org.junit.Before; import org.junit.Test; @@ -26,8 +32,9 @@ import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import com.vmware.vim25.VirtualDevice; import com.vmware.vim25.VirtualMachineConfigSpec; - +import com.vmware.vim25.VirtualMachineVideoCard; import com.cloud.agent.api.Command; import com.cloud.agent.api.ScaleVmAnswer; import com.cloud.agent.api.ScaleVmCommand; @@ -64,6 +71,10 @@ public VmwareHypervisorHost getHyperHost(VmwareContext context, Command cmd) { VirtualMachineMO vmMo; @Mock VirtualMachineConfigSpec vmConfigSpec; + @Mock + VirtualMachineMO vmMo3dgpu; + @Mock + VirtualMachineTO vmSpec3dgpu; @Before public void setup() { @@ -90,4 +101,20 @@ public void testScaleVMF1() throws Exception { verify(_resource).execute(cmd); } + @Test + public void testStartVm3dgpuEnabled() throws Exception{ + Map specDetails = new HashMap(); + specDetails.put("svga.vramSize", "131072"); + when(vmSpec3dgpu.getDetails()).thenReturn(specDetails); + + VirtualMachineVideoCard videoCard = mock(VirtualMachineVideoCard.class); + when(videoCard.getVideoRamSizeInKB()).thenReturn(65536l); + when(vmMo3dgpu.getAllDeviceList()).thenReturn(Arrays.asList((VirtualDevice) videoCard)); + + when(vmMo3dgpu.configureVm(any(VirtualMachineConfigSpec.class))).thenReturn(true); + + _resource.postVideoCardMemoryConfigBeforeStart(vmMo3dgpu, vmSpec3dgpu); + verify(vmMo3dgpu).configureVm(any(VirtualMachineConfigSpec.class)); + } + }