diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/guru/VMwareGuru.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/guru/VMwareGuru.java index d1bce216f184..22a1cc06564a 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/guru/VMwareGuru.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/guru/VMwareGuru.java @@ -42,6 +42,7 @@ import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils; import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.BooleanUtils; @@ -500,7 +501,9 @@ private boolean isRootDisk(VirtualDisk disk, Map disksMap */ private void checkBackingInfo(VirtualDeviceBackingInfo backingInfo) { if (!(backingInfo instanceof VirtualDiskFlatVer2BackingInfo)) { - throw new CloudRuntimeException("Unsopported backing, expected " + VirtualDiskFlatVer2BackingInfo.class.getSimpleName()); + String errorMessage = String.format("Unsupported backing info. Expected: [%s], but received: [%s].", VirtualDiskFlatVer2BackingInfo.class.getSimpleName(), backingInfo.getClass().getSimpleName()); + s_logger.error(errorMessage); + throw new CloudRuntimeException(errorMessage); } } @@ -642,8 +645,11 @@ private Long getImportingVMTemplate(List virtualDisks, DatacenterMO * If VM exists: update VM */ private VMInstanceVO getVM(String vmInternalName, long templateId, long guestOsId, long serviceOfferingId, long zoneId, long accountId, long userId, long domainId) { + s_logger.debug(String.format("Trying to get VM with specs: [vmInternalName: %s, templateId: %s, guestOsId: %s, serviceOfferingId: %s].", vmInternalName, + templateId, guestOsId, serviceOfferingId)); VMInstanceVO vm = _vmDao.findVMByInstanceNameIncludingRemoved(vmInternalName); if (vm != null) { + s_logger.debug(String.format("Found an existing VM [id: %s, removed: %s] with internalName: [%s].", vm.getUuid(), vm.getRemoved() != null ? "yes" : "no", vmInternalName)); vm.setState(VirtualMachine.State.Stopped); vm.setPowerState(VirtualMachine.PowerState.PowerOff); _vmDao.update(vm.getId(), vm); @@ -655,6 +661,9 @@ private VMInstanceVO getVM(String vmInternalName, long templateId, long guestOsI return _vmDao.findById(vm.getId()); } else { long id = userVmDao.getNextInSequence(Long.class, "id"); + s_logger.debug(String.format("Can't find an existing VM with internalName: [%s]. Creating a new VM with: [id: %s, name: %s, templateId: %s, guestOsId: %s, serviceOfferingId: %s].", + vmInternalName, id, vmInternalName, templateId, guestOsId, serviceOfferingId)); + UserVmVO vmInstanceVO = new UserVmVO(id, vmInternalName, vmInternalName, templateId, HypervisorType.VMware, guestOsId, false, false, domainId, accountId, userId, serviceOfferingId, null, vmInternalName, null); vmInstanceVO.setDataCenterId(zoneId); @@ -743,15 +752,19 @@ private void syncVMVolumes(VMInstanceVO vmInstanceVO, List virtualD long templateId = vmInstanceVO.getTemplateId(); long instanceId = vmInstanceVO.getId(); + String operation = ""; for (VirtualDisk disk : virtualDisks) { Long poolId = getPoolId(disk); Volume volume = null; if (disksMapping.containsKey(disk) && disksMapping.get(disk) != null) { volume = updateVolume(disk, disksMapping, vmToImport, poolId, vmInstanceVO); + operation = "updated"; } else { volume = createVolume(disk, vmToImport, domainId, zoneId, accountId, instanceId, poolId, templateId, backup, true); + operation = "created"; } - s_logger.debug("VM backup restored (updated/created) volume id:" + volume.getId() + " for VM id:" + instanceId); + s_logger.debug(String.format("VM [id: %s, instanceName: %s] backup restore operation %s volume [id: %s].", instanceId, vmInstanceVO.getInstanceName(), + operation, volume.getUuid())); } } @@ -968,7 +981,10 @@ private ManagedObjectReference getDestStoreMor(VirtualMachineMO vmMo) throws Exc return info.getDatastore(); } - @Override public VirtualMachine importVirtualMachineFromBackup(long zoneId, long domainId, long accountId, long userId, String vmInternalName, Backup backup) throws Exception { + @Override + public VirtualMachine importVirtualMachineFromBackup(long zoneId, long domainId, long accountId, long userId, String vmInternalName, Backup backup) throws Exception { + s_logger.debug(String.format("Trying to import VM [vmInternalName: %s] from Backup [%s].", vmInternalName, + ReflectionToStringBuilderUtils.reflectOnlySelectedFields(backup, "id", "uuid", "vmId", "externalId", "backupType"))); DatacenterMO dcMo = getDatacenterMO(zoneId); VirtualMachineMO vmToImport = dcMo.findVm(vmInternalName); if (vmToImport == null) { diff --git a/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java index 6a0b575396cf..e99b2fd6757a 100644 --- a/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java +++ b/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java @@ -27,6 +27,7 @@ import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; +import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; @@ -199,13 +200,13 @@ protected void addServiceOfferingExtraConfiguration(ServiceOffering offering, Vi protected VirtualMachineTO toVirtualMachineTO(VirtualMachineProfile vmProfile) { ServiceOffering offering = _serviceOfferingDao.findById(vmProfile.getId(), vmProfile.getServiceOfferingId()); VirtualMachine vm = vmProfile.getVirtualMachine(); - HostVO host = hostDao.findById(vm.getHostId()); + Long clusterId = findClusterOfVm(vm); boolean divideMemoryByOverprovisioning = true; boolean divideCpuByOverprovisioning = true; - if (host != null) { - divideMemoryByOverprovisioning = VmMinMemoryEqualsMemoryDividedByMemOverprovisioningFactor.valueIn(host.getClusterId()); - divideCpuByOverprovisioning = VmMinCpuSpeedEqualsCpuSpeedDividedByCpuOverprovisioningFactor.valueIn(host.getClusterId()); + if (clusterId != null) { + divideMemoryByOverprovisioning = VmMinMemoryEqualsMemoryDividedByMemOverprovisioningFactor.valueIn(clusterId); + divideCpuByOverprovisioning = VmMinCpuSpeedEqualsCpuSpeedDividedByCpuOverprovisioningFactor.valueIn(clusterId); } Long minMemory = (long)(offering.getRamSize() / (divideMemoryByOverprovisioning ? vmProfile.getMemoryOvercommitRatio() : 1)); @@ -280,6 +281,22 @@ protected VirtualMachineTO toVirtualMachineTO(VirtualMachineProfile vmProfile) { return to; } + protected Long findClusterOfVm(VirtualMachine vm) { + HostVO host = hostDao.findById(vm.getHostId()); + if (host != null) { + return host.getClusterId(); + } + + s_logger.debug(String.format("VM [%s] does not have a host id. Trying the last host.", ReflectionToStringBuilderUtils.reflectOnlySelectedFields(vm, "instanceName", "id", "uuid"))); + host = hostDao.findById(vm.getLastHostId()); + if (host != null) { + return host.getClusterId(); + } + + s_logger.debug(String.format("VM [%s] does not have a last host id.", ReflectionToStringBuilderUtils.reflectOnlySelectedFields(vm, "instanceName", "id", "uuid"))); + return null; + } + @Override /** * The basic implementation assumes that the initial "host" defined to execute the command is the host that is in fact going to execute it. diff --git a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java index 0ef2ada28004..07f641e30118 100644 --- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java @@ -533,7 +533,8 @@ public boolean importRestoredVM(long zoneId, long domainId, long accountId, long try { vm = guru.importVirtualMachineFromBackup(zoneId, domainId, accountId, userId, vmInternalName, backup); } catch (final Exception e) { - LOG.error("Failed to import VM from backup restoration", e); + LOG.error(String.format("Failed to import VM [vmInternalName: %s] from backup restoration [%s] with hypervisor [type: %s] due to: [%s].", vmInternalName, + ReflectionToStringBuilderUtils.reflectOnlySelectedFields(backup, "id", "uuid", "vmId", "externalId", "backupType"), hypervisorType, e.getMessage()), e); throw new CloudRuntimeException("Error during vm backup restoration and import: " + e.getMessage()); } if (vm == null) { diff --git a/server/src/test/java/com/cloud/hypervisor/KVMGuruTest.java b/server/src/test/java/com/cloud/hypervisor/KVMGuruTest.java index 22f54d0b13e2..1f88173df2ba 100644 --- a/server/src/test/java/com/cloud/hypervisor/KVMGuruTest.java +++ b/server/src/test/java/com/cloud/hypervisor/KVMGuruTest.java @@ -452,4 +452,42 @@ public void validateConfigureVmOsDescriptionHostNullAndGuestOsMappingNullAndGues Assert.assertEquals(platformEmulator, virtualMachineTo.getPlatformEmulator()); } + @Test + public void testGetClusterIdFromVMHost() { + Mockito.when(vm.getHostId()).thenReturn(123l); + HostVO vo = new HostVO(""); + Long expected = 5l; + vo.setClusterId(expected); + + Mockito.when(hostDao.findById(123l)).thenReturn(vo); + + Long clusterId = guru.findClusterOfVm(vm); + + Assert.assertEquals(expected, clusterId); + } + + @Test + public void testGetClusterIdFromLastVMHost() { + Mockito.when(vm.getHostId()).thenReturn(null); + Mockito.when(vm.getLastHostId()).thenReturn(321l); + HostVO vo = new HostVO(""); + Long expected = 7l; + vo.setClusterId(expected); + + Mockito.when(hostDao.findById(321l)).thenReturn(vo); + + Long clusterId = guru.findClusterOfVm(vm); + + Assert.assertEquals(expected, clusterId); + } + + @Test + public void testGetNullWhenVMThereIsNoInformationOfUsedHosts() { + Mockito.when(vm.getHostId()).thenReturn(null); + Mockito.when(vm.getLastHostId()).thenReturn(null); + + Long clusterId = guru.findClusterOfVm(vm); + + Assert.assertNull(clusterId); + } } \ No newline at end of file