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

Reply via email to