abh1sar commented on code in PR #10140:
URL: https://github.com/apache/cloudstack/pull/10140#discussion_r2228962984


##########
server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java:
##########
@@ -1959,8 +1959,7 @@ private Pair<String, String> 
handleCheckAndRepairVolumeJob(Long vmId, Long volum
                 } else if (jobResult instanceof ResourceAllocationException) {
                     throw (ResourceAllocationException)jobResult;
                 } else if (jobResult instanceof Throwable) {
-                    Throwable throwable = (Throwable) jobResult;
-                    throw new RuntimeException(String.format("Unexpected 
exception: %s", throwable.getMessage()), throwable);
+                    throw new RuntimeException("Unexpected exception", 
(Throwable) jobResult);

Review Comment:
   To be honest, I don't remember why I changed this code (it might be a 
offshoot from one of the merges). will revert this change.



##########
server/src/main/java/com/cloud/vm/UserVmManagerImpl.java:
##########
@@ -9317,6 +9391,234 @@ public boolean unmanageUserVM(Long vmId) {
         return true;
     }
 
+    private void updateDetailsWithRootDiskAttributes(Map<String, String> 
details, VmDiskInfo rootVmDiskInfo) {
+        details.put(VmDetailConstants.ROOT_DISK_SIZE, 
rootVmDiskInfo.getSize().toString());
+        if (rootVmDiskInfo.getMinIops() != null) {
+            details.put(MIN_IOPS, rootVmDiskInfo.getMinIops().toString());
+        }
+        if (rootVmDiskInfo.getMaxIops() != null) {
+            details.put(MAX_IOPS, rootVmDiskInfo.getMaxIops().toString());
+        }
+    }
+
+    private void checkRootDiskSizeAgainstBackup(Long 
instanceVolumeSize,DiskOffering rootDiskOffering, Long backupVolumeSize) {
+        Long instanceRootDiskSize = rootDiskOffering.isCustomized() ? 
instanceVolumeSize : rootDiskOffering.getDiskSize() / GiB_TO_BYTES;
+        if (instanceRootDiskSize < backupVolumeSize) {
+            throw new InvalidParameterValueException(
+                    String.format("Instance volume root disk size %d[GiB] 
cannot be less than the backed-up volume size %d[GiB].",
+                            instanceVolumeSize, backupVolumeSize));
+        }
+    }
+
+    @Override
+    public UserVm allocateVMFromBackup(CreateVMFromBackupCmd cmd) throws 
InsufficientCapacityException, ResourceAllocationException, 
ResourceUnavailableException {
+        if (!backupManager.canCreateInstanceFromBackup(cmd.getBackupId())) {
+            throw new CloudRuntimeException("Create instance from backup is 
not supported for this provider.");
+        }
+        DataCenter zone = _dcDao.findById(cmd.getZoneId());
+        if (zone == null) {
+            throw new InvalidParameterValueException("Unable to find zone by 
id=" + cmd.getZoneId());
+        }
+
+        BackupVO backup = backupDao.findById(cmd.getBackupId());
+        if (backup == null) {
+            throw new InvalidParameterValueException("Backup " + 
cmd.getBackupId() + " does not exist");
+        }
+        if (backup.getZoneId() != cmd.getZoneId()) {
+            throw new InvalidParameterValueException("Instance should be 
created in the same zone as the backup");
+        }
+        backupManager.validateBackupForZone(backup.getZoneId());
+        backupDao.loadDetails(backup);
+
+        verifyDetails(cmd.getDetails());
+
+        UserVmVO backupVm = _vmDao.findByIdIncludingRemoved(backup.getVmId());
+        HypervisorType hypervisorType = backupVm.getHypervisorType();
+
+        Long serviceOfferingId = cmd.getServiceOfferingId();
+        ServiceOffering serviceOffering;
+        if (serviceOfferingId != null) {
+            serviceOffering = serviceOfferingDao.findById(serviceOfferingId);
+            if (serviceOffering == null) {
+                throw new InvalidParameterValueException("Unable to find 
service offering: " + serviceOffering.getId());
+            }
+        } else {
+            String serviceOfferingUuid = 
backup.getDetail(ApiConstants.SERVICE_OFFERING_ID);
+            if (serviceOfferingUuid == null) {
+                throw new CloudRuntimeException("Backup doesn't contain 
service offering uuid. Please specify a valid service offering id while 
creating the instance");
+            }
+            serviceOffering = 
serviceOfferingDao.findByUuid(serviceOfferingUuid);
+            if (serviceOffering == null) {
+                throw new CloudRuntimeException("Unable to find service 
offering with the uuid stored in backup. Please specify a valid service 
offering id while creating instance");
+            }
+        }
+        verifyServiceOffering(cmd, serviceOffering);
+
+        VirtualMachineTemplate template;
+        if (cmd.getTemplateId() != null) {
+            Long templateId = cmd.getTemplateId();
+            template = _templateDao.findById(templateId);
+            if (template == null) {
+                throw new InvalidParameterValueException("Unable to use 
template " + templateId);
+            }
+        } else {
+            String templateUuid = backup.getDetail(ApiConstants.TEMPLATE_ID);
+            if (templateUuid == null) {
+                throw new CloudRuntimeException("Backup doesn't contain 
Template uuid. Please specify a valid Template/ISO while creating the 
instance");
+            }
+            template = _templateDao.findByUuid(templateUuid);
+            if (template == null) {
+                throw new CloudRuntimeException("Unable to find template 
associated with the backup. Please specify a valid Template/ISO while creating 
instance");
+            }
+        }
+        verifyTemplate(cmd, template, serviceOffering.getId());
+
+        Long size = cmd.getSize();
+
+        Long diskOfferingId = cmd.getDiskOfferingId();
+        Boolean isIso = template.getFormat().equals(ImageFormat.ISO);
+        if (diskOfferingId != null) {
+            if (!isIso) {
+                throw new 
InvalidParameterValueException(ApiConstants.DISK_OFFERING_ID + " parameter is 
supported for creating instance from backup only for ISO. For creating VMs with 
templates, please use the parameter " + ApiConstants.DATADISKS_DETAILS);
+            }
+            DiskOffering diskOffering = 
_diskOfferingDao.findById(diskOfferingId);
+            if (diskOffering == null) {
+                throw new InvalidParameterValueException("Unable to find disk 
offering " + diskOfferingId);
+            }
+            if (diskOffering.isComputeOnly()) {
+                throw new InvalidParameterValueException(String.format("The 
disk offering %s provided is directly mapped to a service offering, please 
provide an individual disk offering", diskOffering));
+            }
+        }
+
+        Long overrideDiskOfferingId = cmd.getOverrideDiskOfferingId();
+
+        VmDiskInfo rootVmDiskInfoFromBackup = 
backupManager.getRootDiskInfoFromBackup(backup);
+
+        if (isIso) {
+            if (diskOfferingId == null) {
+                diskOfferingId = 
rootVmDiskInfoFromBackup.getDiskOffering().getId();
+                updateDetailsWithRootDiskAttributes(cmd.getDetails(), 
rootVmDiskInfoFromBackup);
+                size = rootVmDiskInfoFromBackup.getSize();
+            } else {
+                DiskOffering rootDiskOffering = 
_diskOfferingDao.findById(diskOfferingId);
+                checkRootDiskSizeAgainstBackup(size, rootDiskOffering, 
rootVmDiskInfoFromBackup.getSize());
+            }
+        } else {
+            if (overrideDiskOfferingId == null) {
+                overrideDiskOfferingId = serviceOffering.getDiskOfferingId();
+                updateDetailsWithRootDiskAttributes(cmd.getDetails(), 
rootVmDiskInfoFromBackup);
+            } else {
+                DiskOffering overrideDiskOffering = 
_diskOfferingDao.findById(overrideDiskOfferingId);
+                if (overrideDiskOffering.isComputeOnly()) {
+                    updateDetailsWithRootDiskAttributes(cmd.getDetails(), 
rootVmDiskInfoFromBackup);
+                } else {
+                    String diskSizeFromDetails = 
cmd.getDetails().get(VmDetailConstants.ROOT_DISK_SIZE);
+                    Long rootDiskSize = diskSizeFromDetails == null ? null : 
Long.parseLong(diskSizeFromDetails);
+                    checkRootDiskSizeAgainstBackup(rootDiskSize, 
overrideDiskOffering, rootVmDiskInfoFromBackup.getSize());
+                }
+            }
+        }
+
+        List<VmDiskInfo> dataDiskInfoList = cmd.getDataDiskInfoList();
+        if (dataDiskInfoList != null) {
+            backupManager.checkVmDisksSizeAgainstBackup(dataDiskInfoList, 
backup);
+        } else {
+            dataDiskInfoList = 
backupManager.getDataDiskInfoListFromBackup(backup);
+        }
+
+        List<Long> networkIds = cmd.getNetworkIds();
+        Account owner = 
_accountService.getActiveAccountById(cmd.getEntityOwnerId());
+        LinkedHashMap<Integer, Long> userVmNetworkMap = 
getVmOvfNetworkMapping(zone, owner, template, cmd.getVmNetworkMap());
+        if (MapUtils.isNotEmpty(userVmNetworkMap)) {
+            networkIds = new ArrayList<>(userVmNetworkMap.values());
+        }
+
+        Map<Long, IpAddresses> ipToNetworkMap = cmd.getIpToNetworkMap();
+        if (networkIds == null && ipToNetworkMap == null) {
+            networkIds = new ArrayList<Long>();
+            ipToNetworkMap = backupManager.getIpToNetworkMapFromBackup(backup, 
cmd.getPreserveIp(), networkIds);
+        }
+
+        UserVm vm = createVirtualMachine(cmd, zone, owner, serviceOffering, 
template, hypervisorType, diskOfferingId, size, overrideDiskOfferingId, 
dataDiskInfoList, networkIds, ipToNetworkMap, null, null);
+
+        String vmSettingsFromBackup = 
backup.getDetail(ApiConstants.VM_SETTINGS);
+        if (vm != null && vmSettingsFromBackup != null) {
+            UserVmVO vmVO = _vmDao.findById(vm.getId());
+            Map<String, String> details = 
vmInstanceDetailsDao.listDetailsKeyPairs(vm.getId());
+            vmVO.setDetails(details);
+
+            Type type = new TypeToken<Map<String, String>>(){}.getType();
+            Map<String, String> vmDetailsFromBackup = new 
Gson().fromJson(vmSettingsFromBackup, type);
+            for (Entry<String, String> entry : vmDetailsFromBackup.entrySet()) 
{
+                if (!details.containsKey(entry.getKey())) {
+                    vmVO.setDetail(entry.getKey(), entry.getValue());
+                }
+            }
+            _vmDao.saveDetails(vmVO);
+        }
+
+        return vm;
+    }
+
+    @Override
+    public UserVm restoreVMFromBackup(CreateVMFromBackupCmd cmd) throws 
ResourceUnavailableException, InsufficientCapacityException, 
ResourceAllocationException {
+        long vmId = cmd.getEntityId();
+        Map<Long, DiskOffering> diskOfferingMap = 
cmd.getDataDiskTemplateToDiskOfferingMap();
+        Map<VirtualMachineProfile.Param, Object> additonalParams = new 
HashMap<>();
+        UserVm vm;
+
+        try {
+            vm = startVirtualMachine(vmId, null, null, null, diskOfferingMap, 
additonalParams, null);
+
+            boolean status =  
stopVirtualMachine(CallContext.current().getCallingUserId(), vm.getId()) ;

Review Comment:
   The volumes need to be placed on the primary storages which will happen when 
VM is started.
   Stop is then needed because restore only works on stopped VMs.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to