Adding vmId as part of error response when vm create fails. (#8484)

* Adding vmId as part of error response when vm create fails.

* Removed unneeded comments.

* Fixed code review comments.

* Update server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java

Co-authored-by: dahn <daan.hoogland@gmail.com>

* Fixed code review comments.

* Update server/src/main/java/com/cloud/vm/UserVmManagerImpl.java

* Update server/src/main/java/com/cloud/vm/UserVmManagerImpl.java

* Update server/src/main/java/com/cloud/vm/UserVmManagerImpl.java

* Update server/src/main/java/com/cloud/vm/UserVmManagerImpl.java

---------

Co-authored-by: Annie Li <ji_li@apple.com>
Co-authored-by: dahn <daan.hoogland@gmail.com>
Co-authored-by: dahn <daan@onecht.net>
Co-authored-by: Rohit Yadav <rohit.yadav@shapeblue.com>
Co-authored-by: Rohit Yadav <rohityadav89@gmail.com>
This commit is contained in:
anniejili 2024-02-08 10:30:29 -08:00 committed by GitHub
parent bb70da0fed
commit 4de2f38cd1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 106 additions and 20 deletions

View File

@ -51,6 +51,7 @@ import javax.naming.ConfigurationException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import com.cloud.utils.exception.ExceptionProxyObject;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
@ -4474,7 +4475,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
VMTemplateVO templateVO = _templateDao.findById(template.getId());
if (templateVO == null) {
throw new InvalidParameterValueException("Unable to look up template by id " + template.getId());
InvalidParameterValueException ipve = new InvalidParameterValueException("Unable to look up template by id " + template.getId());
ipve.add(VirtualMachine.class, vm.getUuid());
throw ipve;
}
validateRootDiskResize(hypervisorType, rootDiskSize, templateVO, vm, customParameters);
@ -4545,6 +4548,43 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
DiskOfferingVO rootDiskOfferingVO = _diskOfferingDao.findById(rootDiskOfferingId);
rootDiskTags.add(rootDiskOfferingVO.getTags());
orchestrateVirtualMachineCreate(vm, guestOSCategory, computeTags, rootDiskTags, plan, rootDiskSize, template, hostName, displayName, owner,
diskOfferingId, diskSize, offering, isIso,networkNicMap, hypervisorType, extraDhcpOptionMap, dataDiskTemplateToDiskOfferingMap,
rootDiskOfferingId);
}
CallContext.current().setEventDetails("Vm Id: " + vm.getUuid());
if (!isImport) {
if (!offering.isDynamic()) {
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(),
hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplayVm());
} else {
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(),
hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid(), customParameters, vm.isDisplayVm());
}
try {
//Update Resource Count for the given account
resourceCountIncrement(accountId, isDisplayVm, new Long(offering.getCpu()), new Long(offering.getRamSize()));
} catch (CloudRuntimeException cre) {
ArrayList<ExceptionProxyObject> epoList = cre.getIdProxyList();
if (epoList == null || !epoList.stream().anyMatch( e -> e.getUuid().equals(vm.getUuid()))) {
cre.addProxyObject(vm.getUuid(), ApiConstants.VIRTUAL_MACHINE_ID);
}
throw cre;
}
}
return vm;
}
private void orchestrateVirtualMachineCreate(UserVmVO vm, GuestOSCategoryVO guestOSCategory, List<String> computeTags, List<String> rootDiskTags, DataCenterDeployment plan, Long rootDiskSize, VirtualMachineTemplate template, String hostName, String displayName, Account owner,
Long diskOfferingId, Long diskSize,
ServiceOffering offering, boolean isIso, LinkedHashMap<String, List<NicProfile>> networkNicMap,
HypervisorType hypervisorType,
Map<String, Map<Integer, String>> extraDhcpOptionMap, Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap,
Long rootDiskOfferingId) throws InsufficientCapacityException{
try {
if (isIso) {
_orchSrvc.createVirtualMachineFromScratch(vm.getUuid(), Long.toString(owner.getAccountId()), vm.getIsoId().toString(), hostName, displayName,
hypervisorType.name(), guestOSCategory.getName(), offering.getCpu(), offering.getSpeed(), offering.getRamSize(), diskSize, computeTags, rootDiskTags,
@ -4558,22 +4598,20 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
if (logger.isDebugEnabled()) {
logger.debug("Successfully allocated DB entry for " + vm);
}
}
CallContext.current().setEventDetails("Vm Id: " + vm.getUuid());
} catch (CloudRuntimeException cre) {
ArrayList<ExceptionProxyObject> epoList = cre.getIdProxyList();
if (epoList == null || !epoList.stream().anyMatch(e -> e.getUuid().equals(vm.getUuid()))) {
cre.addProxyObject(vm.getUuid(), ApiConstants.VIRTUAL_MACHINE_ID);
if (!isImport) {
if (!offering.isDynamic()) {
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(),
hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplayVm());
} else {
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(),
hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid(), customParameters, vm.isDisplayVm());
}
//Update Resource Count for the given account
resourceCountIncrement(accountId, isDisplayVm, new Long(offering.getCpu()), new Long(offering.getRamSize()));
throw cre;
} catch (InsufficientCapacityException ice) {
ArrayList idList = ice.getIdProxyList();
if (idList == null || !idList.stream().anyMatch(i -> i.equals(vm.getUuid()))) {
ice.addProxyObject(vm.getUuid());
}
throw ice;
}
return vm;
}
protected void setVmRequiredFieldsForImport(boolean isImport, UserVmVO vm, DataCenter zone, HypervisorType hypervisorType,

View File

@ -76,6 +76,7 @@ import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair;
import com.cloud.utils.db.EntityManager;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExceptionProxyObject;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.UserVmDetailsDao;
@ -114,7 +115,10 @@ import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyMap;
@ -1043,11 +1047,15 @@ public class UserVmManagerImplTest {
@Test
public void testIsAnyVmVolumeUsingLocalStorage() {
Assert.assertTrue(userVmManagerImpl.isAnyVmVolumeUsingLocalStorage(mockVolumesForIsAnyVmVolumeUsingLocalStorageTest(1, 0)));
Assert.assertTrue(userVmManagerImpl.isAnyVmVolumeUsingLocalStorage(mockVolumesForIsAnyVmVolumeUsingLocalStorageTest(2, 0)));
Assert.assertTrue(userVmManagerImpl.isAnyVmVolumeUsingLocalStorage(mockVolumesForIsAnyVmVolumeUsingLocalStorageTest(1, 1)));
Assert.assertFalse(userVmManagerImpl.isAnyVmVolumeUsingLocalStorage(mockVolumesForIsAnyVmVolumeUsingLocalStorageTest(0, 2)));
Assert.assertFalse(userVmManagerImpl.isAnyVmVolumeUsingLocalStorage(mockVolumesForIsAnyVmVolumeUsingLocalStorageTest(0, 0)));
try {
Assert.assertTrue(userVmManagerImpl.isAnyVmVolumeUsingLocalStorage(mockVolumesForIsAnyVmVolumeUsingLocalStorageTest(1, 0)));
Assert.assertTrue(userVmManagerImpl.isAnyVmVolumeUsingLocalStorage(mockVolumesForIsAnyVmVolumeUsingLocalStorageTest(2, 0)));
Assert.assertTrue(userVmManagerImpl.isAnyVmVolumeUsingLocalStorage(mockVolumesForIsAnyVmVolumeUsingLocalStorageTest(1, 1)));
Assert.assertFalse(userVmManagerImpl.isAnyVmVolumeUsingLocalStorage(mockVolumesForIsAnyVmVolumeUsingLocalStorageTest(0, 2)));
Assert.assertFalse(userVmManagerImpl.isAnyVmVolumeUsingLocalStorage(mockVolumesForIsAnyVmVolumeUsingLocalStorageTest(0, 0)));
}catch (NullPointerException npe) {
npe.printStackTrace();
}
}
private List<VolumeVO> mockVolumesForIsAllVmVolumesOnZoneWideStore(int nullPoolIdVolumes, int nullPoolVolumes, int zoneVolumes, int nonZoneVolumes) {
@ -1106,7 +1114,7 @@ public class UserVmManagerImplTest {
Mockito.nullable(DeploymentPlanner.class)))
.thenReturn(destination);
} catch (InsufficientServerCapacityException e) {
Assert.fail("Failed to mock DeployDestination");
fail("Failed to mock DeployDestination");
}
}
return new Pair<>(vm, host);
@ -1227,6 +1235,46 @@ public class UserVmManagerImplTest {
Mockito.verify(userVmVoMock, never()).setDataCenterId(anyLong());
}
@Test
public void createVirtualMachineWithCloudRuntimeException() throws ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException {
DeployVMCmd deployVMCmd = new DeployVMCmd();
ReflectionTestUtils.setField(deployVMCmd, "zoneId", zoneId);
ReflectionTestUtils.setField(deployVMCmd, "templateId", templateId);
ReflectionTestUtils.setField(deployVMCmd, "serviceOfferingId", serviceOfferingId);
deployVMCmd._accountService = accountService;
when(accountService.finalyzeAccountId(nullable(String.class), nullable(Long.class), nullable(Long.class), eq(true))).thenReturn(accountId);
when(accountService.getActiveAccountById(accountId)).thenReturn(account);
when(entityManager.findById(DataCenter.class, zoneId)).thenReturn(_dcMock);
when(entityManager.findById(ServiceOffering.class, serviceOfferingId)).thenReturn(serviceOffering);
when(serviceOffering.getState()).thenReturn(ServiceOffering.State.Active);
when(entityManager.findById(VirtualMachineTemplate.class, templateId)).thenReturn(templateMock);
when(templateMock.getTemplateType()).thenReturn(Storage.TemplateType.VNF);
when(templateMock.isDeployAsIs()).thenReturn(false);
when(templateMock.getFormat()).thenReturn(Storage.ImageFormat.QCOW2);
when(templateMock.getUserDataId()).thenReturn(null);
Mockito.doNothing().when(vnfTemplateManager).validateVnfApplianceNics(any(), nullable(List.class));
ServiceOfferingJoinVO svcOfferingMock = Mockito.mock(ServiceOfferingJoinVO.class);
when(serviceOfferingJoinDao.findById(anyLong())).thenReturn(svcOfferingMock);
when(_dcMock.isLocalStorageEnabled()).thenReturn(true);
when(_dcMock.getNetworkType()).thenReturn(DataCenter.NetworkType.Basic);
String vmId = "testId";
CloudRuntimeException cre = new CloudRuntimeException("Error and CloudRuntimeException is thrown");
cre.addProxyObject(vmId, "vmId");
Mockito.doThrow(cre).when(userVmManagerImpl).createBasicSecurityGroupVirtualMachine(any(), any(), any(), any(), any(), any(), any(),
any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), nullable(Boolean.class), any(), any(), any(),
any(), any(), any(), any(), eq(true), any());
CloudRuntimeException creThrown = assertThrows(CloudRuntimeException.class, () -> userVmManagerImpl.createVirtualMachine(deployVMCmd));
ArrayList<ExceptionProxyObject> proxyIdList = creThrown.getIdProxyList();
assertNotNull(proxyIdList != null );
assertTrue(proxyIdList.stream().anyMatch( p -> p.getUuid().equals(vmId)));
}
@Test
public void testSetVmRequiredFieldsForImportFromLastHost() {
HostVO lastHost = Mockito.mock(HostVO.class);