Skip to content

Commit 29df047

Browse files
committed
[4.22] Prevent unmanaging VM from CloudStack if it is part of a CKS cluster
1 parent 09ee092 commit 29df047

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
import com.cloud.hypervisor.Hypervisor;
7272
import com.cloud.hypervisor.HypervisorGuru;
7373
import com.cloud.hypervisor.HypervisorGuruManager;
74+
import com.cloud.kubernetes.cluster.KubernetesServiceHelper;
7475
import com.cloud.network.Network;
7576
import com.cloud.network.NetworkModel;
7677
import com.cloud.network.Networks;
@@ -313,6 +314,8 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
313314
private DataStoreManager dataStoreManager;
314315
@Inject
315316
private ImportVmTasksManager importVmTasksManager;
317+
@Inject
318+
private KubernetesServiceHelper kubernetesServiceHelper;
316319

317320
protected Gson gson;
318321

@@ -2365,6 +2368,8 @@ public List<Class<?>> getCommands() {
23652368
* Perform validations before attempting to unmanage a VM from CloudStack:
23662369
* - VM must not have any associated volume snapshot
23672370
* - VM must not have an attached ISO
2371+
* - VM must not belong to any CKS cluster
2372+
* @throws UnsupportedServiceException in case any of the validations above fail
23682373
*/
23692374
void performUnmanageVMInstancePrechecks(VMInstanceVO vmVO) {
23702375
if (hasVolumeSnapshotsPriorToUnmanageVM(vmVO)) {
@@ -2376,6 +2381,15 @@ void performUnmanageVMInstancePrechecks(VMInstanceVO vmVO) {
23762381
throw new UnsupportedServiceException("Cannot unmanage VM with id = " + vmVO.getUuid() +
23772382
" as there is an ISO attached. Please detach ISO before unmanaging.");
23782383
}
2384+
2385+
if (belongsToCksCluster(vmVO)) {
2386+
throw new UnsupportedServiceException("Cannot unmanage VM with id = " + vmVO.getUuid() +
2387+
" as it belongs to a CKS cluster. Please remove the VM from the CKS cluster before unmanaging.");
2388+
}
2389+
}
2390+
2391+
private boolean belongsToCksCluster(VMInstanceVO vmVO) {
2392+
return kubernetesServiceHelper.findByVmId(vmVO.getId()) != null;
23792393
}
23802394

23812395
private boolean hasVolumeSnapshotsPriorToUnmanageVM(VMInstanceVO vmVO) {

server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,21 @@
3131

3232
import java.net.URI;
3333
import java.util.ArrayList;
34+
import java.util.Collections;
3435
import java.util.Date;
3536
import java.util.HashMap;
3637
import java.util.LinkedHashMap;
3738
import java.util.List;
3839
import java.util.Map;
3940
import java.util.UUID;
4041

42+
import com.cloud.kubernetes.cluster.KubernetesServiceHelper;
4143
import com.cloud.offering.DiskOffering;
44+
import com.cloud.storage.Snapshot;
45+
import com.cloud.storage.SnapshotVO;
46+
import com.cloud.storage.dao.SnapshotDao;
4247
import com.cloud.vm.ImportVMTaskVO;
48+
import org.apache.cloudstack.acl.ControlledEntity;
4349
import org.apache.cloudstack.api.ApiConstants;
4450
import org.apache.cloudstack.api.ResponseGenerator;
4551
import org.apache.cloudstack.api.ResponseObject;
@@ -241,6 +247,10 @@ public class UnmanagedVMsManagerImplTest {
241247
private StoragePoolHostDao storagePoolHostDao;
242248
@Mock
243249
private ImportVmTasksManager importVmTasksManager;
250+
@Mock
251+
private KubernetesServiceHelper kubernetesServiceHelper;
252+
@Mock
253+
private SnapshotDao snapshotDao;
244254

245255
@Mock
246256
private VMInstanceVO virtualMachine;
@@ -568,6 +578,53 @@ public void unmanageVMInstanceStoppedInstanceTest() {
568578
unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false);
569579
}
570580

581+
@Test(expected = UnsupportedServiceException.class)
582+
public void testUnmanageVMInstanceWithVolumeSnapshotsFail() {
583+
when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User);
584+
when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM);
585+
when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped);
586+
when(virtualMachine.getId()).thenReturn(virtualMachineId);
587+
UserVmVO userVmVO = mock(UserVmVO.class);
588+
when(userVmDao.findById(anyLong())).thenReturn(userVmVO);
589+
when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine);
590+
VolumeVO volumeVO = mock(VolumeVO.class);
591+
long volumeId = 20L;
592+
when(volumeVO.getId()).thenReturn(volumeId);
593+
SnapshotVO snapshotVO = mock(SnapshotVO.class);
594+
when(snapshotVO.getState()).thenReturn(Snapshot.State.BackedUp);
595+
when(snapshotDao.listByVolumeId(volumeId)).thenReturn(Collections.singletonList(snapshotVO));
596+
when(volumeDao.findByInstance(virtualMachineId)).thenReturn(Collections.singletonList(volumeVO));
597+
unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false);
598+
}
599+
600+
@Test(expected = UnsupportedServiceException.class)
601+
public void testUnmanageVMInstanceWithAssociatedIsoFail() {
602+
when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User);
603+
when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM);
604+
when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped);
605+
when(virtualMachine.getId()).thenReturn(virtualMachineId);
606+
UserVmVO userVmVO = mock(UserVmVO.class);
607+
when(userVmVO.getIsoId()).thenReturn(null);
608+
when(userVmDao.findById(anyLong())).thenReturn(userVmVO);
609+
when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine);
610+
when(userVmVO.getIsoId()).thenReturn(1L);
611+
unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false);
612+
}
613+
614+
@Test(expected = UnsupportedServiceException.class)
615+
public void testUnmanageVMInstanceBelongingToCksClusterFail() {
616+
when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User);
617+
when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM);
618+
when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped);
619+
when(virtualMachine.getId()).thenReturn(virtualMachineId);
620+
UserVmVO userVmVO = mock(UserVmVO.class);
621+
when(userVmVO.getIsoId()).thenReturn(null);
622+
when(userVmDao.findById(anyLong())).thenReturn(userVmVO);
623+
when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine);
624+
when(kubernetesServiceHelper.findByVmId(virtualMachineId)).thenReturn(mock(ControlledEntity.class));
625+
unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false);
626+
}
627+
571628
@Test
572629
public void testListRemoteInstancesTest() {
573630
ListVmsForImportCmd cmd = Mockito.mock(ListVmsForImportCmd.class);

0 commit comments

Comments
 (0)