Fix restore VM workflow - clone and replace existing VM instead of cloning and moving disks

This commit is contained in:
nvazquez 2020-10-20 19:47:27 -03:00
parent 67794aba23
commit f1f490b151
6 changed files with 185 additions and 237 deletions

View File

@ -26,42 +26,23 @@ import java.util.Map;
*/
public class DeployAsIsInfoTO {
private String templatePath;
private String destStoragePool;
@LogLevel(LogLevel.Log4jLevel.Off)
private Map<String, String> properties = new HashMap<>();
private Map<Integer, String> nicAdapterMap = new HashMap();
private boolean replaceVm;
public DeployAsIsInfoTO() {
}
public DeployAsIsInfoTO(String templatePath, String destStoragePool, Map<String, String> properties,
Map<Integer, String> nicAdapterMap, boolean replaceVm) {
this.templatePath = templatePath;
this.destStoragePool = destStoragePool;
public DeployAsIsInfoTO(Map<String, String> properties, Map<Integer, String> nicAdapterMap) {
this.properties = properties;
this.nicAdapterMap = nicAdapterMap;
this.replaceVm = replaceVm;
}
public String getTemplatePath() {
return templatePath;
}
public Map<String, String> getProperties() {
return properties;
}
public String getDestStoragePool() {
return destStoragePool;
}
public Map<Integer, String> getNicAdapterMap() {
return nicAdapterMap;
}
public boolean isReplaceVm() {
return replaceVm;
}
}

View File

@ -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;

View File

@ -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<String, String> details) {
String configuration = details.getOrDefault(VmDetailConstants.DEPLOY_AS_IS_CONFIGURATION, null);
Map<String, String> 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<Integer, String> 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);
}

View File

@ -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<String> 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<vmwareLayoutFilePair.length; i++) {
dsMo.moveDatastoreFile(vmwareLayoutFilePair[i], dcMo.getMor(), dsMo.getMor(), legacyCloudStackLayoutFilePair[i], dcMo.getMor(), true);
}
}
auxVM.detachAllDisks();
auxVM.destroy();
String vmNameInVcenter = virtualMachineMO.getName();
virtualMachineMO.tearDownDevices(new Class<?>[]{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<VirtualDisk> 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<VirtualDisk> vmDisks = vmMo.getVirtualDisks();
List<DiskTO> sortedDisks = Arrays.asList(sortVolumesByDeviceId(specDisks))
List<VirtualDisk> rootDisks = new ArrayList<>();
List<DiskTO> 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;

View File

@ -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)

View File

@ -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<VolumeVO> 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<VMSnapshotVO> 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<VMSnapshotVO> 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<Volume> 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<VolumeApiResult> future = _volService.expungeVolumeAsync(volFactory.getVolume(root.getId()));
try {
future.get();
} catch (Exception e) {
s_logger.debug("Failed to expunge volume:" + root.getId(), e);
}
}
}
Map<VirtualMachineProfile.Param, Object> 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<VolumeApiResult> 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<VirtualMachineProfile.Param, Object> 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<Volume> newVols) {
}
/**
* Perform basic checkings to make sure restore is possible. If not, #InvalidParameterValueException is thrown.
*