This is an automated email from the ASF dual-hosted git repository.
dahn pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/main by this push:
new 9363f64 Fix full backup VM restore (#5680)
9363f64 is described below
commit 9363f6490bba4cc16a14081f85ccf9b08530ffa0
Author: SadiJr <[email protected]>
AuthorDate: Fri Dec 10 03:16:42 2021 -0300
Fix full backup VM restore (#5680)
Co-authored-by: SadiJr <[email protected]>
---
.../java/com/cloud/hypervisor/guru/VMwareGuru.java | 22 +++++++++++--
.../com/cloud/hypervisor/HypervisorGuruBase.java | 25 +++++++++++---
.../cloudstack/backup/BackupManagerImpl.java | 3 +-
.../java/com/cloud/hypervisor/KVMGuruTest.java | 38 ++++++++++++++++++++++
4 files changed, 80 insertions(+), 8 deletions(-)
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 ce7da76..fa5c642 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.command.StorageSubSystemCommand;
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 @@ public class VMwareGuru extends HypervisorGuruBase
implements HypervisorGuru, Co
*/
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 @@ public class VMwareGuru extends HypervisorGuruBase
implements HypervisorGuru, Co
* 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 @@ public class VMwareGuru extends HypervisorGuruBase
implements HypervisorGuru, Co
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 @@ public class VMwareGuru extends HypervisorGuruBase
implements HypervisorGuru, Co
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 @@ public class VMwareGuru extends HypervisorGuruBase
implements HypervisorGuru, Co
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 6a0b575..e99b2fd 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.backup.Backup;
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 @@ public abstract class HypervisorGuruBase extends
AdapterBase implements Hypervis
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 @@ public abstract class HypervisorGuruBase extends
AdapterBase implements Hypervis
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 ed1f54e..fd92faa 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 class BackupManagerImpl extends ManagerBase
implements BackupManager {
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 22f54d0..1f88173 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 class KVMGuruTest {
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