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: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]