-
Notifications
You must be signed in to change notification settings - Fork 7
Destroyvm also removes volumes #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 14 commits
4a154b6
880b38e
eb929a0
12e627b
e953db9
fbc3fdf
d2f3b35
bff19b3
3c7e0cc
83ae447
6129eb6
ff5004e
eb02664
9590da1
d996e77
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1849,6 +1849,14 @@ private void validateRootVolumeDetachAttach(VolumeVO volume, UserVmVO vm) { | |
| } | ||
| } | ||
|
|
||
| @ActionEvent(eventType = EventTypes.EVENT_VOLUME_DETACH, eventDescription = "detaching volume") | ||
| public Volume detachVolumeViaDestroyVM(long vmId, long volumeId) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. couple of questions here: |
||
|
|
||
| Volume result = orchestrateDetachVolumeFromVM(vmId, volumeId); | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| private Volume orchestrateDetachVolumeFromVM(long vmId, long volumeId) { | ||
|
|
||
| Volume volume = _volsDao.findById(volumeId); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,86 +16,6 @@ | |
| // under the License. | ||
| package com.cloud.vm; | ||
|
|
||
| import java.io.UnsupportedEncodingException; | ||
| import java.net.URLDecoder; | ||
| import java.util.ArrayList; | ||
| import java.util.Arrays; | ||
| import java.util.Date; | ||
| import java.util.HashMap; | ||
| import java.util.HashSet; | ||
| import java.util.LinkedHashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Map.Entry; | ||
| import java.util.Set; | ||
| import java.util.UUID; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
| import java.util.concurrent.ExecutorService; | ||
| import java.util.concurrent.Executors; | ||
| import java.util.concurrent.ScheduledExecutorService; | ||
| import java.util.concurrent.TimeUnit; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| import javax.inject.Inject; | ||
| import javax.naming.ConfigurationException; | ||
|
|
||
| import org.apache.cloudstack.acl.ControlledEntity.ACLType; | ||
| import org.apache.cloudstack.acl.SecurityChecker.AccessType; | ||
| import org.apache.cloudstack.affinity.AffinityGroupService; | ||
| import org.apache.cloudstack.affinity.AffinityGroupVO; | ||
| import org.apache.cloudstack.affinity.dao.AffinityGroupDao; | ||
| import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; | ||
| import org.apache.cloudstack.api.ApiConstants; | ||
| import org.apache.cloudstack.api.BaseCmd.HTTPMethod; | ||
| import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd; | ||
| import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.AddNicToVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.DeployVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.DestroyVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.RebootVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.RemoveNicFromVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.ResetVMPasswordCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.ResetVMSSHKeyCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.RestoreVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.ScaleVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.SecurityGroupAction; | ||
| import org.apache.cloudstack.api.command.user.vm.StartVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.UpdateDefaultNicForVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.UpdateVmNicIpCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd; | ||
| import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd; | ||
| import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd; | ||
| import org.apache.cloudstack.context.CallContext; | ||
| import org.apache.cloudstack.engine.cloud.entity.api.VirtualMachineEntity; | ||
| import org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMNetworkMapDao; | ||
| import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; | ||
| import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; | ||
| import org.apache.cloudstack.engine.service.api.OrchestrationService; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult; | ||
| import org.apache.cloudstack.framework.async.AsyncCallFuture; | ||
| import org.apache.cloudstack.framework.config.ConfigKey; | ||
| import org.apache.cloudstack.framework.config.Configurable; | ||
| import org.apache.cloudstack.framework.config.dao.ConfigurationDao; | ||
| import org.apache.cloudstack.managed.context.ManagedContextRunnable; | ||
| import org.apache.cloudstack.storage.command.DeleteCommand; | ||
| import org.apache.cloudstack.storage.command.DettachCommand; | ||
| import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; | ||
| import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; | ||
| import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; | ||
| import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; | ||
| import org.apache.commons.codec.binary.Base64; | ||
| import org.apache.commons.collections.MapUtils; | ||
| import org.apache.commons.lang3.StringUtils; | ||
| import org.apache.log4j.Logger; | ||
|
|
||
| import com.cloud.agent.AgentManager; | ||
| import com.cloud.agent.api.Answer; | ||
| import com.cloud.agent.api.Command; | ||
|
|
@@ -301,6 +221,84 @@ | |
| import com.cloud.vm.snapshot.VMSnapshotManager; | ||
| import com.cloud.vm.snapshot.VMSnapshotVO; | ||
| import com.cloud.vm.snapshot.dao.VMSnapshotDao; | ||
| import org.apache.cloudstack.acl.ControlledEntity.ACLType; | ||
| import org.apache.cloudstack.acl.SecurityChecker.AccessType; | ||
| import org.apache.cloudstack.affinity.AffinityGroupService; | ||
| import org.apache.cloudstack.affinity.AffinityGroupVO; | ||
| import org.apache.cloudstack.affinity.dao.AffinityGroupDao; | ||
| import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; | ||
| import org.apache.cloudstack.api.ApiConstants; | ||
| import org.apache.cloudstack.api.BaseCmd.HTTPMethod; | ||
| import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd; | ||
| import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.AddNicToVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.DeployVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.DestroyVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.RebootVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.RemoveNicFromVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.ResetVMPasswordCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.ResetVMSSHKeyCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.RestoreVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.ScaleVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.SecurityGroupAction; | ||
| import org.apache.cloudstack.api.command.user.vm.StartVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.UpdateDefaultNicForVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.UpdateVmNicIpCmd; | ||
| import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd; | ||
| import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd; | ||
| import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd; | ||
| import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd; | ||
| import org.apache.cloudstack.context.CallContext; | ||
| import org.apache.cloudstack.engine.cloud.entity.api.VirtualMachineEntity; | ||
| import org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMNetworkMapDao; | ||
| import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; | ||
| import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; | ||
| import org.apache.cloudstack.engine.service.api.OrchestrationService; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult; | ||
| import org.apache.cloudstack.framework.async.AsyncCallFuture; | ||
| import org.apache.cloudstack.framework.config.ConfigKey; | ||
| import org.apache.cloudstack.framework.config.Configurable; | ||
| import org.apache.cloudstack.framework.config.dao.ConfigurationDao; | ||
| import org.apache.cloudstack.managed.context.ManagedContextRunnable; | ||
| import org.apache.cloudstack.storage.command.DeleteCommand; | ||
| import org.apache.cloudstack.storage.command.DettachCommand; | ||
| import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; | ||
| import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; | ||
| import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; | ||
| import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; | ||
| import org.apache.commons.codec.binary.Base64; | ||
| import org.apache.commons.collections.MapUtils; | ||
| import org.apache.commons.lang3.StringUtils; | ||
| import org.apache.log4j.Logger; | ||
|
|
||
| import javax.inject.Inject; | ||
| import javax.naming.ConfigurationException; | ||
| import java.io.UnsupportedEncodingException; | ||
| import java.net.URLDecoder; | ||
| import java.util.ArrayList; | ||
| import java.util.Arrays; | ||
| import java.util.Date; | ||
| import java.util.HashMap; | ||
| import java.util.HashSet; | ||
| import java.util.LinkedHashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Map.Entry; | ||
| import java.util.Set; | ||
| import java.util.UUID; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
| import java.util.concurrent.ExecutorService; | ||
| import java.util.concurrent.Executors; | ||
| import java.util.concurrent.ScheduledExecutorService; | ||
| import java.util.concurrent.TimeUnit; | ||
| import java.util.stream.Collectors; | ||
|
|
||
|
|
||
| public class UserVmManagerImpl extends ManagerBase implements UserVmManager, VirtualMachineGuru, UserVmService, Configurable { | ||
|
|
@@ -2751,27 +2749,55 @@ public UserVm destroyVm(DestroyVMCmd cmd) throws ResourceUnavailableException, C | |
| // check if VM exists | ||
| UserVmVO vm = _vmDao.findById(vmId); | ||
|
|
||
| if (vm == null) { | ||
| if (vm == null || vm.getRemoved() != null) { | ||
| throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId); | ||
| } | ||
|
|
||
| if (vm.getState() == State.Destroyed || vm.getState() == State.Expunging) { | ||
| s_logger.trace("Vm id=" + vmId + " is already destroyed"); | ||
| return vm; | ||
| } | ||
|
|
||
| // check if there are active volume snapshots tasks | ||
| s_logger.debug("Checking if there are any ongoing snapshots on the ROOT volumes associated with VM with ID " + vmId); | ||
| if (checkStatusOfVolumeSnapshots(vmId, Volume.Type.ROOT)) { | ||
| throw new CloudRuntimeException("There is/are unbacked up snapshot(s) on ROOT volume, vm destroy is not permitted, please try again later."); | ||
| } | ||
| s_logger.debug("Found no ongoing snapshots on volume of type ROOT, for the vm with id " + vmId); | ||
|
|
||
| List<VolumeVO> volumes = getVolumesFromIds(cmd); | ||
|
|
||
| checkForUnattachedVolumes(vmId, volumes); | ||
| validateVolumes(volumes); | ||
| detachVolumesFromVm(volumes); | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. detach here |
||
| UserVm destroyedVm = destroyVm(vmId, expunge); | ||
| if (expunge) { | ||
| if (!expunge(vm, ctx.getCallingUserId(), ctx.getCallingAccount())) { | ||
| throw new CloudRuntimeException("Failed to expunge vm " + destroyedVm); | ||
| } | ||
| } | ||
|
|
||
| deleteVolumesFromVm(volumes); | ||
|
|
||
| return destroyedVm; | ||
| } | ||
|
|
||
| private List<VolumeVO> getVolumesFromIds(DestroyVMCmd cmd) { | ||
| List<VolumeVO> volumes = new ArrayList<>(); | ||
| if (cmd.getVolumeIds() != null) { | ||
| for (Long volId : cmd.getVolumeIds()) { | ||
| VolumeVO vol = _volsDao.findById(volId); | ||
|
|
||
| if (vol == null) { | ||
| throw new InvalidParameterValueException("Unable to find volume with ID: " + volId); | ||
| } | ||
| volumes.add(vol); | ||
| } | ||
| } | ||
| return volumes; | ||
| } | ||
|
|
||
| @Override | ||
| @DB | ||
| public InstanceGroupVO createVmGroup(CreateVMGroupCmd cmd) { | ||
|
|
@@ -6446,4 +6472,52 @@ private boolean checkStatusOfVolumeSnapshots(long vmId, Volume.Type type) { | |
| } | ||
| return false; | ||
| } | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the below methods can do with unit tests |
||
| private void checkForUnattachedVolumes(long vmId, List<VolumeVO> volumes) { | ||
|
|
||
| StringBuilder sb = new StringBuilder(); | ||
|
|
||
| for (VolumeVO volume : volumes) { | ||
| if (volume.getInstanceId() == null || vmId != volume.getInstanceId()) { | ||
| sb.append(volume.toString() + "; "); | ||
| } | ||
| } | ||
|
|
||
| if (!StringUtils.isEmpty(sb.toString())) { | ||
| throw new InvalidParameterValueException("The following supplied volumes are not attached to the VM: " + sb.toString()); | ||
| } | ||
| } | ||
|
|
||
| private void validateVolumes(List<VolumeVO> volumes) { | ||
|
|
||
| for (VolumeVO volume : volumes) { | ||
| if (!(volume.getVolumeType() == Volume.Type.ROOT || volume.getVolumeType() == Volume.Type.DATADISK)) { | ||
| throw new InvalidParameterValueException("Please specify volume of type " + Volume.Type.DATADISK.toString() + " or " + Volume.Type.ROOT.toString()); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private void detachVolumesFromVm(List<VolumeVO> volumes) { | ||
|
|
||
| for (VolumeVO volume : volumes) { | ||
|
|
||
| Volume detachResult = _volumeService.detachVolumeViaDestroyVM(volume.getInstanceId(), volume.getId()); | ||
|
|
||
| if (detachResult == null) { | ||
| s_logger.error("DestroyVM remove volume - failed to detach and delete volume " + volume.getInstanceId() + " from instance " + volume.getId()); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private void deleteVolumesFromVm(List<VolumeVO> volumes) { | ||
|
|
||
| for (VolumeVO volume : volumes) { | ||
|
|
||
| boolean deleteResult = _volumeService.deleteVolume(volume.getId(), CallContext.current().getCallingAccount()); | ||
|
|
||
| if (!deleteResult) { | ||
| s_logger.error("DestroyVM remove volume - failed to delete volume " + volume.getInstanceId() + " from instance " + volume.getId()); | ||
| } | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would this be specific to destroy vm ? isn't it just a detach method and didn't it already exist?