diff --git a/api/src/main/java/com/cloud/agent/api/to/DeployAsIsInfoTO.java b/api/src/main/java/com/cloud/agent/api/to/DeployAsIsInfoTO.java index 37d481ea20a..9400de09652 100644 --- a/api/src/main/java/com/cloud/agent/api/to/DeployAsIsInfoTO.java +++ b/api/src/main/java/com/cloud/agent/api/to/DeployAsIsInfoTO.java @@ -26,42 +26,23 @@ import java.util.Map; */ public class DeployAsIsInfoTO { - private String templatePath; - private String destStoragePool; @LogLevel(LogLevel.Log4jLevel.Off) private Map properties = new HashMap<>(); private Map nicAdapterMap = new HashMap(); - private boolean replaceVm; public DeployAsIsInfoTO() { } - public DeployAsIsInfoTO(String templatePath, String destStoragePool, Map properties, - Map nicAdapterMap, boolean replaceVm) { - this.templatePath = templatePath; - this.destStoragePool = destStoragePool; + public DeployAsIsInfoTO(Map properties, Map nicAdapterMap) { this.properties = properties; this.nicAdapterMap = nicAdapterMap; - this.replaceVm = replaceVm; - } - - public String getTemplatePath() { - return templatePath; } public Map getProperties() { return properties; } - public String getDestStoragePool() { - return destStoragePool; - } - public Map getNicAdapterMap() { return nicAdapterMap; } - - public boolean isReplaceVm() { - return replaceVm; - } } diff --git a/api/src/main/java/com/cloud/vm/VirtualMachineProfile.java b/api/src/main/java/com/cloud/vm/VirtualMachineProfile.java index be90b12e91a..c17a716666d 100644 --- a/api/src/main/java/com/cloud/vm/VirtualMachineProfile.java +++ b/api/src/main/java/com/cloud/vm/VirtualMachineProfile.java @@ -69,7 +69,6 @@ public interface VirtualMachineProfile { public static final Param BootType = new Param("BootType"); public static final Param BootIntoSetup = new Param("enterHardwareSetup"); public static final Param PreserveNics = new Param("PreserveNics"); - public static final Param ReplaceDeployAsIs = new Param("ReplaceDeployAsIs"); private String name; diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/guru/VmwareVmImplementer.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/guru/VmwareVmImplementer.java index c5a01979105..b8de0bbe1b6 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/guru/VmwareVmImplementer.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/guru/VmwareVmImplementer.java @@ -186,17 +186,9 @@ class VmwareVmImplementer { * Set the information relevant for deploy-as-is VMs on the VM TO */ private void setDeployAsIsInfoTO(VirtualMachineProfile vm, VirtualMachineTO to, Map details) { - String configuration = details.getOrDefault(VmDetailConstants.DEPLOY_AS_IS_CONFIGURATION, null); Map properties = deployAsIsHelper.getVirtualMachineDeployAsIsProperties(vm); - String templatePath = null; - String destStoragePool = null; - if (vm.getVirtualMachine().getState() == VirtualMachine.State.Starting) { - destStoragePool = deployAsIsHelper.getAllocatedVirtualMachineDestinationStoragePool(vm); - templatePath = deployAsIsHelper.getAllocatedVirtualMachineTemplatePath(vm, configuration, destStoragePool); - } Map nicsAdapterMapping = deployAsIsHelper.getAllocatedVirtualMachineNicsAdapterMapping(vm, to.getNics()); - boolean replaceVm = vm.getParameter(VirtualMachineProfile.Param.ReplaceDeployAsIs) != null ? (Boolean) vm.getParameter(VirtualMachineProfile.Param.ReplaceDeployAsIs) : false; - DeployAsIsInfoTO info = new DeployAsIsInfoTO(templatePath, destStoragePool, properties, nicsAdapterMapping, replaceVm); + DeployAsIsInfoTO info = new DeployAsIsInfoTO(properties, nicsAdapterMapping); to.setDeployAsIsInfo(info); } diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 544d779daf2..0090833491c 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -48,7 +48,6 @@ import javax.xml.datatype.XMLGregorianCalendar; import com.cloud.agent.api.to.DataTO; import com.cloud.agent.api.to.DeployAsIsInfoTO; import com.cloud.agent.api.ValidateVcenterDetailsCommand; -import com.cloud.storage.resource.VmwareStorageLayoutType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.storage.configdrive.ConfigDrive; import org.apache.cloudstack.storage.to.TemplateObjectTO; @@ -1739,57 +1738,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } - private void restoreVirtualMachineVolumesFromTemplate(String vmInternalCSName, VirtualMachineTO vmSpec, - VmwareHypervisorHost host, VirtualMachineMO virtualMachineMO, - VmwareContext context, DatacenterMO dcMo) throws Exception { - DeployAsIsInfoTO deployAsIsInfo = vmSpec.getDeployAsIsInfo(); - if (s_logger.isInfoEnabled()) { - s_logger.info("Restoring VM " + vmInternalCSName + " volumes from template as-is"); - } - String deployAsIsTemplate = deployAsIsInfo.getTemplatePath(); - String destDatastore = deployAsIsInfo.getDestStoragePool(); - - String auxVMName = vmInternalCSName + "-aux"; - _storageProcessor.cloneVMFromTemplate(host, deployAsIsTemplate, auxVMName, destDatastore); - VirtualMachineMO auxVM = host.findVmOnHyperHost(auxVMName); - if (auxVM == null) { - s_logger.info("Cloned deploy-as-is VM " + auxVMName + " is not in this host, relocating it"); - auxVM = takeVmFromOtherHyperHost(host, auxVMName); - } - ManagedObjectReference morDatastore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(host, destDatastore); - DatastoreMO dsMo = new DatastoreMO(context, morDatastore); - List vmdkFileBaseNames = auxVM.getVmdkFileBaseNames(); - for (String vmdkFileBaseName : vmdkFileBaseNames) { - s_logger.info("Move volume out of volume-wrapper VM " + vmdkFileBaseName); - String[] vmwareLayoutFilePair = VmwareStorageLayoutHelper.getVmdkFilePairDatastorePath(dsMo, auxVMName, vmdkFileBaseName, VmwareStorageLayoutType.VMWARE, !_fullCloneFlag); - String[] legacyCloudStackLayoutFilePair = VmwareStorageLayoutHelper.getVmdkFilePairDatastorePath(dsMo, auxVMName, vmdkFileBaseName, VmwareStorageLayoutType.CLOUDSTACK_LEGACY, !_fullCloneFlag); - for (int i=0; i[]{VirtualDisk.class}); - s_logger.info("Changing VM datastore to " + dsMo); - virtualMachineMO.changeDatastore(morDatastore); - for (String vmdkFileBaseName : vmdkFileBaseNames) { - if (dsMo.folderExists(String.format("[%s]", dsMo.getName()), vmNameInVcenter)) { - String newPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmNameInVcenter, dsMo, vmdkFileBaseName, null); - s_logger.info("Attaching disk to restored VM at: " + newPath + " on datastore: " + destDatastore); - virtualMachineMO.attachDisk(new String[] {newPath}, morDatastore); - } - } - } - - private boolean isRestoreParameterSet(VirtualMachineTO vmSpec) { - DeployAsIsInfoTO deployAsIsInfo = vmSpec.getDeployAsIsInfo(); - if (deployAsIsInfo != null) { - return deployAsIsInfo.isReplaceVm(); - } - return false; - } - protected StartAnswer execute(StartCommand cmd) { if (s_logger.isInfoEnabled()) { s_logger.info("Executing resource StartCommand: " + getHumanReadableBytesJson(_gson.toJson(cmd))); @@ -1908,18 +1856,11 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } if (deployAsIs) { - if (s_logger.isTraceEnabled()) { - s_logger.trace("Deploying OVA from template as-is"); - } - String deployAsIsTemplate = deployAsIsInfo.getTemplatePath(); - String destDatastore = deployAsIsInfo.getDestStoragePool(); - _storageProcessor.cloneVMFromTemplate(hyperHost, deployAsIsTemplate, vmInternalCSName, destDatastore); vmMo = hyperHost.findVmOnHyperHost(vmInternalCSName); if (vmMo == null) { s_logger.info("Cloned deploy-as-is VM " + vmInternalCSName + " is not in this host, relocating it"); vmMo = takeVmFromOtherHyperHost(hyperHost, vmInternalCSName); } - mapSpecDisksToClonedDisks(vmMo, vmInternalCSName, specDisks); } else { DiskTO rootDisk = null; for (DiskTO vol : disks) { @@ -1970,10 +1911,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa throw new Exception("Failed to find the newly create or relocated VM. vmName: " + vmInternalCSName); } } - - if (deployAsIs && isRestoreParameterSet(vmSpec)) { - restoreVirtualMachineVolumesFromTemplate(vmInternalCSName, vmSpec, hyperHost, vmMo, context, dcMo); - mapSpecDisksToClonedDisks(vmMo, vmInternalCSName, specDisks); + if (deployAsIs) { + s_logger.info("Mapping VM disks to spec disks and tearing down datadisks (if any)"); + mapSpecDisksToClonedDisksAndTearDownDatadisks(vmMo, vmInternalCSName, specDisks); } int disksChanges = getDisksChangesNumberFromDisksSpec(disks, deployAsIs); @@ -2569,6 +2509,12 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } + private void tearDownVMDisks(VirtualMachineMO vmMo, List disks) throws Exception { + for (VirtualDisk disk : disks) { + vmMo.tearDownDevice(disk); + } + } + private String getGuestOsIdFromVmSpec(VirtualMachineTO vmSpec, boolean deployAsIs) { return translateGuestOsIdentifier(vmSpec.getArch(), vmSpec.getOs(), vmSpec.getPlatformEmulator()).value(); } @@ -2624,21 +2570,18 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa /** * Modify the specDisks information to match the cloned VM's disks (from vmMo VM) */ - private void mapSpecDisksToClonedDisks(VirtualMachineMO vmMo, String vmInternalCSName, DiskTO[] specDisks) { + private void mapSpecDisksToClonedDisksAndTearDownDatadisks(VirtualMachineMO vmMo, String vmInternalCSName, DiskTO[] specDisks) { try { s_logger.debug("Mapping spec disks information to cloned VM disks for VM " + vmInternalCSName); if (vmMo != null && ArrayUtils.isNotEmpty(specDisks)) { List vmDisks = vmMo.getVirtualDisks(); - List sortedDisks = Arrays.asList(sortVolumesByDeviceId(specDisks)) + List rootDisks = new ArrayList<>(); + List sortedRootDisksFromSpec = Arrays.asList(sortVolumesByDeviceId(specDisks)) .stream() .filter(x -> x.getType() == Volume.Type.ROOT) .collect(Collectors.toList()); - if (sortedDisks.size() != vmDisks.size()) { - s_logger.error("Different number of root disks spec vs cloned deploy-as-is VM disks: " + sortedDisks.size() + " - " + vmDisks.size()); - return; - } - for (int i = 0; i < sortedDisks.size(); i++) { - DiskTO specDisk = sortedDisks.get(i); + for (int i = 0; i < sortedRootDisksFromSpec.size(); i++) { + DiskTO specDisk = sortedRootDisksFromSpec.get(i); VirtualDisk vmDisk = vmDisks.get(i); DataTO dataVolume = specDisk.getData(); if (dataVolume instanceof VolumeObjectTO) { @@ -2662,6 +2605,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } volumeObjectTO.setPath(relativePath); specDisk.setPath(relativePath); + rootDisks.add(vmDisk); } else { s_logger.error("Empty backing filename for volume " + volumeObjectTO.getName()); } @@ -2670,6 +2614,11 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } } + vmDisks.removeAll(rootDisks); + if (CollectionUtils.isNotEmpty(vmDisks)) { + s_logger.info("Tearing down datadisks for deploy-as-is VM"); + tearDownVMDisks(vmMo, vmDisks); + } } } catch (Exception e) { String msg = "Error mapping deploy-as-is VM disks from cloned VM " + vmInternalCSName; diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java index 7127031ae9b..85aacd34f42 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java @@ -810,9 +810,21 @@ public class VmwareStorageProcessor implements StorageProcessor { DatastoreMO dsMo = new DatastoreMO(context, morDatastore); String vmdkName = volume.getName(); + String vmName = volume.getVmName(); String vmdkFileBaseName = null; if (template.isDeployAsIs() && volume.getVolumeType() == Volume.Type.ROOT) { - s_logger.info("ROOT Volume from deploy-as-is template, no need to create the volume at this point, will be cloned from template"); + VirtualMachineMO existingVm = dcMo.findVm(vmName); + if (volume.getDeviceId().equals(0L)) { + if (existingVm != null) { + s_logger.info("Found existing VM " + vmName + " before cloning from template, destroying it"); + existingVm.detachAllDisks(); + existingVm.destroy(); + } + s_logger.info("ROOT Volume from deploy-as-is template, cloning template"); + cloneVMFromTemplate(hyperHost, template.getPath(), vmName, primaryStore.getUuid()); + } else { + s_logger.info("ROOT Volume from deploy-as-is template, volume already created at this point"); + } } else { if (srcStore == null) { // create a root volume for blank VM (created from ISO) diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index 227ee5abbbc..ac55e404459 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -6724,6 +6724,47 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir return _itMgr.restoreVirtualMachine(vm.getId(), newTemplateId); } + private VMTemplateVO getRestoreVirtualMachineTemplate(Account caller, Long newTemplateId, List rootVols, UserVmVO vm) { + VMTemplateVO template = null; + if (CollectionUtils.isNotEmpty(rootVols)) { + VolumeVO root = rootVols.get(0); + Long templateId = root.getTemplateId(); + boolean isISO = false; + if (templateId == null) { + // Assuming that for a vm deployed using ISO, template ID is set to NULL + isISO = true; + templateId = vm.getIsoId(); + } + //newTemplateId can be either template or ISO id. In the following snippet based on the vm deployment (from template or ISO) it is handled accordingly + if (newTemplateId != null) { + template = _templateDao.findById(newTemplateId); + _accountMgr.checkAccess(caller, null, true, template); + if (isISO) { + if (!template.getFormat().equals(ImageFormat.ISO)) { + throw new InvalidParameterValueException("Invalid ISO id provided to restore the VM "); + } + } else { + if (template.getFormat().equals(ImageFormat.ISO)) { + throw new InvalidParameterValueException("Invalid template id provided to restore the VM "); + } + } + } else { + if (isISO && templateId == null) { + throw new CloudRuntimeException("Cannot restore the VM since there is no ISO attached to VM"); + } + template = _templateDao.findById(templateId); + if (template == null) { + InvalidParameterValueException ex = new InvalidParameterValueException("Cannot find template/ISO for specified volumeid and vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); + ex.addProxyObject(root.getUuid(), "volumeId"); + throw ex; + } + } + } + + return template; + } + @Override public UserVm restoreVirtualMachine(final Account caller, final long vmId, final Long newTemplateId) throws InsufficientCapacityException, ResourceUnavailableException { Long userId = caller.getId(); @@ -6761,163 +6802,137 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } - VolumeVO root = rootVols.get(0); - if ( !Volume.State.Allocated.equals(root.getState()) || newTemplateId != null ){ - Long templateId = root.getTemplateId(); - boolean isISO = false; - if (templateId == null) { - // Assuming that for a vm deployed using ISO, template ID is set to NULL - isISO = true; - templateId = vm.getIsoId(); - } - // If target VM has associated VM snapshots then don't allow restore of VM - List vmSnapshots = _vmSnapshotDao.findByVm(vmId); - if (vmSnapshots.size() > 0) { - throw new InvalidParameterValueException("Unable to restore VM, please remove VM snapshots before restoring VM"); - } + // If target VM has associated VM snapshots then don't allow restore of VM + List vmSnapshots = _vmSnapshotDao.findByVm(vmId); + if (vmSnapshots.size() > 0) { + throw new InvalidParameterValueException("Unable to restore VM, please remove VM snapshots before restoring VM"); + } - VMTemplateVO template = null; - //newTemplateId can be either template or ISO id. In the following snippet based on the vm deployment (from template or ISO) it is handled accordingly - if (newTemplateId != null) { - template = _templateDao.findById(newTemplateId); - _accountMgr.checkAccess(caller, null, true, template); - if (isISO) { - if (!template.getFormat().equals(ImageFormat.ISO)) { - throw new InvalidParameterValueException("Invalid ISO id provided to restore the VM "); + VMTemplateVO template = getRestoreVirtualMachineTemplate(caller, newTemplateId, rootVols, vm); + checkRestoreVmFromTemplate(vm, template); + + if (needRestart) { + try { + _itMgr.stop(vm.getUuid()); + } catch (ResourceUnavailableException e) { + s_logger.debug("Stop vm " + vm.getUuid() + " failed", e); + CloudRuntimeException ex = new CloudRuntimeException("Stop vm failed for specified vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); + throw ex; + } + } + + List newVols = new ArrayList<>(); + for (VolumeVO root : rootVols) { + if ( !Volume.State.Allocated.equals(root.getState()) || newTemplateId != null ){ + Long templateId = root.getTemplateId(); + boolean isISO = false; + if (templateId == null) { + // Assuming that for a vm deployed using ISO, template ID is set to NULL + isISO = true; + templateId = vm.getIsoId(); + } + + /* If new template/ISO is provided allocate a new volume from new template/ISO otherwise allocate new volume from original template/ISO */ + Volume newVol = null; + if (newTemplateId != null) { + if (isISO) { + newVol = volumeMgr.allocateDuplicateVolume(root, null); + vm.setIsoId(newTemplateId); + vm.setGuestOSId(template.getGuestOSId()); + vm.setTemplateId(newTemplateId); + _vmDao.update(vmId, vm); + } else { + newVol = volumeMgr.allocateDuplicateVolume(root, newTemplateId); + vm.setGuestOSId(template.getGuestOSId()); + vm.setTemplateId(newTemplateId); + _vmDao.update(vmId, vm); } } else { - if (template.getFormat().equals(ImageFormat.ISO)) { - throw new InvalidParameterValueException("Invalid template id provided to restore the VM "); - } - } - } else { - if (isISO && templateId == null) { - throw new CloudRuntimeException("Cannot restore the VM since there is no ISO attached to VM"); - } - template = _templateDao.findById(templateId); - if (template == null) { - InvalidParameterValueException ex = new InvalidParameterValueException("Cannot find template/ISO for specified volumeid and vmId"); - ex.addProxyObject(vm.getUuid(), "vmId"); - ex.addProxyObject(root.getUuid(), "volumeId"); - throw ex; - } - } - - checkRestoreVmFromTemplate(vm, template); - - if (needRestart) { - try { - _itMgr.stop(vm.getUuid()); - } catch (ResourceUnavailableException e) { - s_logger.debug("Stop vm " + vm.getUuid() + " failed", e); - CloudRuntimeException ex = new CloudRuntimeException("Stop vm failed for specified vmId"); - ex.addProxyObject(vm.getUuid(), "vmId"); - throw ex; - } - } - - /* If new template/ISO is provided allocate a new volume from new template/ISO otherwise allocate new volume from original template/ISO */ - Volume newVol = null; - if (newTemplateId != null) { - if (isISO) { newVol = volumeMgr.allocateDuplicateVolume(root, null); - vm.setIsoId(newTemplateId); - vm.setGuestOSId(template.getGuestOSId()); - vm.setTemplateId(newTemplateId); - _vmDao.update(vmId, vm); - } else { - newVol = volumeMgr.allocateDuplicateVolume(root, newTemplateId); - vm.setGuestOSId(template.getGuestOSId()); - vm.setTemplateId(newTemplateId); - _vmDao.update(vmId, vm); } - } else { - newVol = volumeMgr.allocateDuplicateVolume(root, null); - } + newVols.add(newVol); - // 1. Save usage event and update resource count for user vm volumes - _resourceLimitMgr.incrementResourceCount(newVol.getAccountId(), ResourceType.volume, newVol.isDisplay()); - _resourceLimitMgr.incrementResourceCount(newVol.getAccountId(), ResourceType.primary_storage, newVol.isDisplay(), new Long(newVol.getSize())); - // 2. Create Usage event for the newly created volume - UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, newVol.getAccountId(), newVol.getDataCenterId(), newVol.getId(), newVol.getName(), newVol.getDiskOfferingId(), template.getId(), newVol.getSize()); - _usageEventDao.persist(usageEvent); + // 1. Save usage event and update resource count for user vm volumes + _resourceLimitMgr.incrementResourceCount(newVol.getAccountId(), ResourceType.volume, newVol.isDisplay()); + _resourceLimitMgr.incrementResourceCount(newVol.getAccountId(), ResourceType.primary_storage, newVol.isDisplay(), new Long(newVol.getSize())); + // 2. Create Usage event for the newly created volume + UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, newVol.getAccountId(), newVol.getDataCenterId(), newVol.getId(), newVol.getName(), newVol.getDiskOfferingId(), template.getId(), newVol.getSize()); + _usageEventDao.persist(usageEvent); - handleManagedStorage(vm, root); + handleManagedStorage(vm, root); - _volsDao.attachVolume(newVol.getId(), vmId, newVol.getDeviceId()); + _volsDao.attachVolume(newVol.getId(), vmId, newVol.getDeviceId()); - // Detach, destroy and create the usage event for the old root volume. - _volsDao.detachVolume(root.getId()); - volumeMgr.destroyVolume(root); + // Detach, destroy and create the usage event for the old root volume. + _volsDao.detachVolume(root.getId()); + volumeMgr.destroyVolume(root); - // For VMware hypervisor since the old root volume is replaced by the new root volume, force expunge old root volume if it has been created in storage - if (vm.getHypervisorType() == HypervisorType.VMware) { - VolumeInfo volumeInStorage = volFactory.getVolume(root.getId()); - if (volumeInStorage != null) { - s_logger.info("Expunging volume " + root.getId() + " from primary data store"); - AsyncCallFuture future = _volService.expungeVolumeAsync(volFactory.getVolume(root.getId())); - try { - future.get(); - } catch (Exception e) { - s_logger.debug("Failed to expunge volume:" + root.getId(), e); - } - } - } - - Map params = null; - String password = null; - - if (template.isEnablePassword()) { - password = _mgr.generateRandomPassword(); - boolean result = resetVMPasswordInternal(vmId, password); - if (!result) { - throw new CloudRuntimeException("VM reset is completed but failed to reset password for the virtual machine "); - } - vm.setPassword(password); - } - - if (needRestart) { - try { - if (vm.getDetail(VmDetailConstants.PASSWORD) != null) { - params = new HashMap<>(); - params.put(VirtualMachineProfile.Param.VmPassword, password); - } - if (template.isDeployAsIs()) { - if (params == null) { - params = new HashMap<>(); - } - params.put(VirtualMachineProfile.Param.ReplaceDeployAsIs, true); - } - _itMgr.start(vm.getUuid(), params); - vm = _vmDao.findById(vmId); - if (template.isEnablePassword()) { - // this value is not being sent to the backend; need only for api - // display purposes - vm.setPassword(password); - if (vm.isUpdateParameters()) { - vm.setUpdateParameters(false); - _vmDao.loadDetails(vm); - if (vm.getDetail(VmDetailConstants.PASSWORD) != null) { - userVmDetailsDao.removeDetail(vm.getId(), VmDetailConstants.PASSWORD); - } - _vmDao.update(vm.getId(), vm); + // For VMware hypervisor since the old root volume is replaced by the new root volume, force expunge old root volume if it has been created in storage + if (vm.getHypervisorType() == HypervisorType.VMware) { + VolumeInfo volumeInStorage = volFactory.getVolume(root.getId()); + if (volumeInStorage != null) { + s_logger.info("Expunging volume " + root.getId() + " from primary data store"); + AsyncCallFuture future = _volService.expungeVolumeAsync(volFactory.getVolume(root.getId())); + try { + future.get(); + } catch (Exception e) { + s_logger.debug("Failed to expunge volume:" + root.getId(), e); } } - } catch (Exception e) { - s_logger.debug("Unable to start VM " + vm.getUuid(), e); - CloudRuntimeException ex = new CloudRuntimeException("Unable to start VM with specified id" + e.getMessage()); - ex.addProxyObject(vm.getUuid(), "vmId"); - throw ex; } } } + Map params = null; + String password = null; + + if (template.isEnablePassword()) { + password = _mgr.generateRandomPassword(); + boolean result = resetVMPasswordInternal(vmId, password); + if (!result) { + throw new CloudRuntimeException("VM reset is completed but failed to reset password for the virtual machine "); + } + vm.setPassword(password); + } + if (needRestart) { + try { + if (vm.getDetail(VmDetailConstants.PASSWORD) != null) { + params = new HashMap<>(); + params.put(VirtualMachineProfile.Param.VmPassword, password); + } + _itMgr.start(vm.getUuid(), params); + vm = _vmDao.findById(vmId); + if (template.isEnablePassword()) { + // this value is not being sent to the backend; need only for api + // display purposes + vm.setPassword(password); + if (vm.isUpdateParameters()) { + vm.setUpdateParameters(false); + _vmDao.loadDetails(vm); + if (vm.getDetail(VmDetailConstants.PASSWORD) != null) { + userVmDetailsDao.removeDetail(vm.getId(), VmDetailConstants.PASSWORD); + } + _vmDao.update(vm.getId(), vm); + } + } + } catch (Exception e) { + s_logger.debug("Unable to start VM " + vm.getUuid(), e); + CloudRuntimeException ex = new CloudRuntimeException("Unable to start VM with specified id" + e.getMessage()); + ex.addProxyObject(vm.getUuid(), "vmId"); + throw ex; + } + } + s_logger.debug("Restore VM " + vmId + " done successfully"); return vm; } + private void recreateDeployAsIsVirtualMachine(UserVmVO vm, List newVols) { + } + /** * Perform basic checkings to make sure restore is possible. If not, #InvalidParameterValueException is thrown. *