|
70 | 70 | import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; |
71 | 71 | import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; |
72 | 72 | import org.apache.cloudstack.engine.service.api.OrchestrationService; |
| 73 | +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; |
| 74 | +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; |
73 | 75 | import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; |
74 | 76 | import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; |
75 | 77 | import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; |
|
81 | 83 | import org.apache.cloudstack.framework.config.dao.ConfigurationDao; |
82 | 84 | import org.apache.cloudstack.framework.jobs.AsyncJobManager; |
83 | 85 | import org.apache.cloudstack.managed.context.ManagedContextRunnable; |
| 86 | +import org.apache.cloudstack.storage.command.DettachCommand; |
84 | 87 | import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; |
85 | 88 | import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; |
86 | 89 |
|
87 | 90 | import com.cloud.agent.AgentManager; |
88 | 91 | import com.cloud.agent.api.Answer; |
| 92 | +import com.cloud.agent.api.Command; |
89 | 93 | import com.cloud.agent.api.GetVmDiskStatsAnswer; |
90 | 94 | import com.cloud.agent.api.GetVmDiskStatsCommand; |
91 | 95 | import com.cloud.agent.api.GetVmStatsAnswer; |
|
94 | 98 | import com.cloud.agent.api.StartAnswer; |
95 | 99 | import com.cloud.agent.api.VmDiskStatsEntry; |
96 | 100 | import com.cloud.agent.api.VmStatsEntry; |
| 101 | +import com.cloud.agent.api.to.DataTO; |
| 102 | +import com.cloud.agent.api.to.DiskTO; |
97 | 103 | import com.cloud.agent.api.to.NicTO; |
98 | 104 | import com.cloud.agent.api.to.VirtualMachineTO; |
99 | 105 | import com.cloud.agent.manager.Commands; |
|
199 | 205 | import com.cloud.storage.Storage; |
200 | 206 | import com.cloud.storage.Storage.ImageFormat; |
201 | 207 | import com.cloud.storage.Storage.TemplateType; |
| 208 | +import com.cloud.storage.DataStoreRole; |
202 | 209 | import com.cloud.storage.StorageManager; |
203 | 210 | import com.cloud.storage.StoragePool; |
204 | 211 | import com.cloud.storage.StoragePoolStatus; |
@@ -448,6 +455,8 @@ public enum UserVmCloneType { |
448 | 455 | DeploymentPlanningManager _planningMgr; |
449 | 456 | @Inject |
450 | 457 | VolumeApiService _volumeService; |
| 458 | + @Inject |
| 459 | + DataStoreManager _dataStoreMgr; |
451 | 460 |
|
452 | 461 | protected ScheduledExecutorService _executor = null; |
453 | 462 | protected int _expungeInterval; |
@@ -4651,6 +4660,9 @@ public UserVm restoreVMInternal(Account caller, UserVmVO vm, Long newTemplateId) |
4651 | 4660 | /* Detach and destory the old root volume */ |
4652 | 4661 |
|
4653 | 4662 | _volsDao.detachVolume(root.getId()); |
| 4663 | + |
| 4664 | + handleManagedStorage(vm, root); |
| 4665 | + |
4654 | 4666 | volumeMgr.destroyVolume(root); |
4655 | 4667 |
|
4656 | 4668 | // 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 |
@@ -4698,6 +4710,59 @@ public UserVm restoreVMInternal(Account caller, UserVmVO vm, Long newTemplateId) |
4698 | 4710 |
|
4699 | 4711 | } |
4700 | 4712 |
|
| 4713 | + private void handleManagedStorage(UserVmVO vm, VolumeVO root) { |
| 4714 | + StoragePoolVO storagePool = _storagePoolDao.findById(root.getPoolId()); |
| 4715 | + |
| 4716 | + if (storagePool.isManaged()) { |
| 4717 | + Long hostId = vm.getHostId() != null ? vm.getHostId() : vm.getLastHostId(); |
| 4718 | + |
| 4719 | + if (hostId != null) { |
| 4720 | + DataTO volTO = volFactory.getVolume(root.getId()).getTO(); |
| 4721 | + DiskTO disk = new DiskTO(volTO, root.getDeviceId(), root.getPath(), root.getVolumeType()); |
| 4722 | + |
| 4723 | + // it's OK in this case to send a detach command to the host for a root volume as this |
| 4724 | + // will simply lead to the SR that supports the root volume being removed |
| 4725 | + DettachCommand cmd = new DettachCommand(disk, vm.getInstanceName()); |
| 4726 | + |
| 4727 | + cmd.setManaged(true); |
| 4728 | + |
| 4729 | + cmd.setStorageHost(storagePool.getHostAddress()); |
| 4730 | + cmd.setStoragePort(storagePool.getPort()); |
| 4731 | + |
| 4732 | + cmd.set_iScsiName(root.get_iScsiName()); |
| 4733 | + |
| 4734 | + Commands cmds = new Commands(Command.OnError.Stop); |
| 4735 | + |
| 4736 | + cmds.addCommand(cmd); |
| 4737 | + |
| 4738 | + try { |
| 4739 | + _agentMgr.send(hostId, cmds); |
| 4740 | + } |
| 4741 | + catch (Exception ex) { |
| 4742 | + throw new CloudRuntimeException(ex.getMessage()); |
| 4743 | + } |
| 4744 | + |
| 4745 | + if (!cmds.isSuccessful()) { |
| 4746 | + for (Answer answer : cmds.getAnswers()) { |
| 4747 | + if (!answer.getResult()) { |
| 4748 | + s_logger.warn("Failed to reset vm due to: " + answer.getDetails()); |
| 4749 | + |
| 4750 | + throw new CloudRuntimeException("Unable to reset " + vm + " due to " + answer.getDetails()); |
| 4751 | + } |
| 4752 | + } |
| 4753 | + } |
| 4754 | + |
| 4755 | + if (hostId != null) { |
| 4756 | + // root.getPoolId() should be null if the VM we are attaching the disk to has never been started before |
| 4757 | + DataStore dataStore = root.getPoolId() != null ? _dataStoreMgr.getDataStore(root.getPoolId(), DataStoreRole.Primary) : null; |
| 4758 | + Host host = this._hostDao.findById(hostId); |
| 4759 | + |
| 4760 | + volumeMgr.disconnectVolumeFromHost(volFactory.getVolume(root.getId()), host, dataStore); |
| 4761 | + } |
| 4762 | + } |
| 4763 | + } |
| 4764 | + } |
| 4765 | + |
4701 | 4766 | @Override |
4702 | 4767 | public void prepareStop(VirtualMachineProfile profile) { |
4703 | 4768 | UserVmVO vm = _vmDao.findById(profile.getId()); |
|
0 commit comments