blob: 3afd3dc4a958042bf43021fd4bdfb0409a120ebb [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.deploy;
import com.cloud.agent.AgentManager;
import com.cloud.capacity.CapacityManager;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.configuration.ConfigurationManagerImpl;
import com.cloud.dc.ClusterDetailsDao;
import com.cloud.dc.ClusterDetailsVO;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.DedicatedResourceDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.deploy.DeploymentPlanner.PlannerResourceUsage;
import com.cloud.deploy.dao.PlannerHostReservationDao;
import com.cloud.exception.AffinityConflictException;
import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.gpu.GPU;
import com.cloud.gpu.dao.HostGpuGroupsDao;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
import com.cloud.host.dao.HostDetailsDao;
import com.cloud.host.dao.HostTagsDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.org.Grouping.AllocationState;
import com.cloud.resource.ResourceManager;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDetailsDao;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.ScopeType;
import com.cloud.storage.Storage;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolStatus;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.GuestOSCategoryDao;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ComponentContext;
import com.cloud.vm.DiskProfile;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.VirtualMachineProfileImpl;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.UserVmDetailsDao;
import com.cloud.vm.dao.VMInstanceDao;
import org.apache.cloudstack.affinity.AffinityGroupProcessor;
import org.apache.cloudstack.affinity.AffinityGroupService;
import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
import org.apache.cloudstack.affinity.dao.AffinityGroupDomainMapDao;
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
import org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMReservationDao;
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.StoragePoolAllocator;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.framework.messagebus.MessageBus;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.test.utils.SpringUtils;
import org.apache.commons.collections.CollectionUtils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class DeploymentPlanningManagerImplTest {
@Spy
@InjectMocks
DeploymentPlanningManagerImpl _dpm;
@Inject
PlannerHostReservationDao _plannerHostReserveDao;
@Inject
VirtualMachineProfileImpl vmProfile;
@Inject
private AccountDao accountDao;
@Inject
private VMInstanceDao vmInstanceDao;
@Inject
AffinityGroupVMMapDao _affinityGroupVMMapDao;
@Inject
ExcludeList avoids;
@Inject
DataCenterVO dc;
@Inject
DataCenterDao _dcDao;
@Mock
FirstFitPlanner _planner;
@Inject
ClusterDao _clusterDao;
@Inject
DedicatedResourceDao _dedicatedDao;
@Inject
UserVmDetailsDao vmDetailsDao;
@Inject
VMTemplateDao templateDao;
@Inject
HostPodDao hostPodDao;
@Inject
VolumeDao volDao;
@Inject
HostDao hostDao;
@Inject
CapacityManager capacityMgr;
@Inject
ServiceOfferingDetailsDao serviceOfferingDetailsDao;
@Inject
ClusterDetailsDao clusterDetailsDao;
@Inject
PrimaryDataStoreDao primaryDataStoreDao;
@Mock
Host host;
@Mock
ConfigurationDao configDao;
@Mock
AccountManager _accountMgr;
@Inject
DiskOfferingDao _diskOfferingDao;
@Mock
DataStoreManager _dataStoreManager;
@Inject
HostPodDao _podDao;
private static final long dataCenterId = 1L;
private static final long instanceId = 123L;
private static final long hostId = 0L;
private static final long podId = 2L;
private static final long clusterId = 3L;
private static final long ADMIN_ACCOUNT_ROLE_ID = 1L;
private AutoCloseable closeable;
@BeforeClass
public static void setUp() throws ConfigurationException {
}
@Before
public void testSetUp() {
closeable = MockitoAnnotations.openMocks(this);
ComponentContext.initComponentsLifeCycle();
PlannerHostReservationVO reservationVO = new PlannerHostReservationVO(hostId, dataCenterId, podId, clusterId, PlannerResourceUsage.Shared);
Mockito.when(_plannerHostReserveDao.persist(ArgumentMatchers.any(PlannerHostReservationVO.class))).thenReturn(reservationVO);
Mockito.when(_plannerHostReserveDao.findById(ArgumentMatchers.anyLong())).thenReturn(reservationVO);
Mockito.when(_affinityGroupVMMapDao.countAffinityGroupsForVm(ArgumentMatchers.anyLong())).thenReturn(0L);
VMTemplateVO template = Mockito.mock(VMTemplateVO.class);
Mockito.when(template.isDeployAsIs()).thenReturn(false);
Mockito.when(templateDao.findById(Mockito.anyLong())).thenReturn(template);
VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
Mockito.when(vm.getType()).thenReturn(Type.Instance);
Mockito.when(vm.getLastHostId()).thenReturn(null);
Mockito.when(vmProfile.getVirtualMachine()).thenReturn(vm);
Mockito.when(vmProfile.getId()).thenReturn(instanceId);
Mockito.when(vmDetailsDao.listDetailsKeyPairs(ArgumentMatchers.anyLong())).thenReturn(null);
Mockito.when(volDao.findByInstance(ArgumentMatchers.anyLong())).thenReturn(new ArrayList<>());
Mockito.when(_dcDao.findById(ArgumentMatchers.anyLong())).thenReturn(dc);
Mockito.when(dc.getId()).thenReturn(dataCenterId);
ClusterVO clusterVO = new ClusterVO();
clusterVO.setHypervisorType(HypervisorType.XenServer.toString());
Mockito.when(_clusterDao.findById(ArgumentMatchers.anyLong())).thenReturn(clusterVO);
Mockito.when(_planner.getName()).thenReturn("FirstFitPlanner");
List<DeploymentPlanner> planners = new ArrayList<DeploymentPlanner>();
planners.add(_planner);
_dpm.setPlanners(planners);
StoragePoolAllocator allocator = Mockito.mock(StoragePoolAllocator.class);
_dpm.setStoragePoolAllocators(Arrays.asList(allocator));
Mockito.when(host.getId()).thenReturn(hostId);
Mockito.doNothing().when(_dpm).avoidDisabledResources(vmProfile, dc, avoids);
}
@After
public void tearDown() throws Exception {
closeable.close();
}
@Test
public void dataCenterAvoidTest() throws InsufficientServerCapacityException, AffinityConflictException {
ServiceOfferingVO svcOffering =
new ServiceOfferingVO("testOffering", 1, 512, 500, 1, 1, false, false, false, "test dpm",
false, VirtualMachine.Type.User, null, "FirstFitPlanner", true, false);
Mockito.when(vmProfile.getServiceOffering()).thenReturn(svcOffering);
DataCenterDeployment plan = new DataCenterDeployment(dataCenterId);
Mockito.when(avoids.shouldAvoid((DataCenterVO) ArgumentMatchers.any())).thenReturn(true);
DeployDestination dest = _dpm.planDeployment(vmProfile, plan, avoids, null);
assertNull("DataCenter is in avoid set, destination should be null! ", dest);
}
@Test
public void plannerCannotHandleTest() throws InsufficientServerCapacityException, AffinityConflictException {
ServiceOfferingVO svcOffering =
new ServiceOfferingVO("testOffering", 1, 512, 500, 1, 1, false, false, false, "test dpm",
false, VirtualMachine.Type.User, null, "UserDispersingPlanner", true, false);
Mockito.when(vmProfile.getServiceOffering()).thenReturn(svcOffering);
DataCenterDeployment plan = new DataCenterDeployment(dataCenterId);
Mockito.when(avoids.shouldAvoid((DataCenterVO) ArgumentMatchers.any())).thenReturn(false);
Mockito.when(_planner.canHandle(vmProfile, plan, avoids)).thenReturn(false);
DeployDestination dest = _dpm.planDeployment(vmProfile, plan, avoids, null);
assertNull("Planner cannot handle, destination should be null! ", dest);
}
@Test
public void emptyClusterListTest() throws InsufficientServerCapacityException, AffinityConflictException {
ServiceOfferingVO svcOffering =
new ServiceOfferingVO("testOffering", 1, 512, 500, 1, 1, false, false, false, "test dpm",
false, VirtualMachine.Type.User, null, "FirstFitPlanner", true, false);
Mockito.when(vmProfile.getServiceOffering()).thenReturn(svcOffering);
DataCenterDeployment plan = new DataCenterDeployment(dataCenterId);
Mockito.when(avoids.shouldAvoid((DataCenterVO) ArgumentMatchers.any())).thenReturn(false);
Mockito.when(_planner.canHandle(vmProfile, plan, avoids)).thenReturn(true);
Mockito.when(((DeploymentClusterPlanner) _planner).orderClusters(vmProfile, plan, avoids)).thenReturn(null);
DeployDestination dest = _dpm.planDeployment(vmProfile, plan, avoids, null);
assertNull("Planner cannot handle, destination should be null! ", dest);
}
@Test
public void testCheckAffinityEmptyPreferredHosts() {
assertTrue(_dpm.checkAffinity(host, new ArrayList<>()));
}
@Test
public void testCheckAffinityNullPreferredHosts() {
assertTrue(_dpm.checkAffinity(host, null));
}
@Test
public void testCheckAffinityNotEmptyPreferredHostsContainingHost() {
assertTrue(_dpm.checkAffinity(host, Arrays.asList(3l, 4l, hostId, 2l)));
}
@Test
public void testCheckAffinityNotEmptyPreferredHostsNotContainingHost() {
assertFalse(_dpm.checkAffinity(host, Arrays.asList(3l, 4l, 2l)));
}
@Test
public void routerInDisabledResourceAssertFalse() {
Assert.assertFalse(DeploymentPlanningManager.allowRouterOnDisabledResource.value());
}
@Test
public void adminVmInDisabledResourceAssertFalse() {
Assert.assertFalse(DeploymentPlanningManager.allowAdminVmOnDisabledResource.value());
}
@Test
public void avoidDisabledResourcesTestAdminAccount() {
Type[] vmTypes = VirtualMachine.Type.values();
for (int i = 0; i < vmTypes.length - 1; ++i) {
Mockito.when(vmProfile.getType()).thenReturn(vmTypes[i]);
if (vmTypes[i].isUsedBySystem()) {
prepareAndVerifyAvoidDisabledResourcesTest(1, 0, 0, ADMIN_ACCOUNT_ROLE_ID, vmTypes[i], true, false);
} else {
prepareAndVerifyAvoidDisabledResourcesTest(0, 1, 1, ADMIN_ACCOUNT_ROLE_ID, vmTypes[i], true, false);
}
}
}
@Test
public void avoidDisabledResourcesTestUserAccounAdminCannotDeployOnDisabled() {
Type[] vmTypes = VirtualMachine.Type.values();
for (int i = 0; i < vmTypes.length - 1; ++i) {
Mockito.when(vmProfile.getType()).thenReturn(vmTypes[i]);
long userAccountId = ADMIN_ACCOUNT_ROLE_ID + 1;
if (vmTypes[i].isUsedBySystem()) {
prepareAndVerifyAvoidDisabledResourcesTest(1, 0, 0, userAccountId, vmTypes[i], true, false);
} else {
prepareAndVerifyAvoidDisabledResourcesTest(0, 0, 1, userAccountId, vmTypes[i], true, false);
}
}
}
@Test
public void avoidDisabledResourcesTestUserAccounAdminCanDeployOnDisabled() {
Type[] vmTypes = VirtualMachine.Type.values();
for (int i = 0; i < vmTypes.length - 1; ++i) {
Mockito.when(vmProfile.getType()).thenReturn(vmTypes[i]);
long userAccountId = ADMIN_ACCOUNT_ROLE_ID + 1;
if (vmTypes[i].isUsedBySystem()) {
prepareAndVerifyAvoidDisabledResourcesTest(1, 0, 0, userAccountId, vmTypes[i], true, true);
} else {
prepareAndVerifyAvoidDisabledResourcesTest(0, 0, 1, userAccountId, vmTypes[i], true, true);
}
}
}
private void prepareAndVerifyAvoidDisabledResourcesTest(int timesRouter, int timesAdminVm,
int timesDisabledResource, long roleId, Type vmType, boolean isSystemDepolyable,
boolean isAdminVmDeployable) {
Mockito.doReturn(isSystemDepolyable).when(_dpm).isRouterDeployableInDisabledResources();
Mockito.doReturn(isAdminVmDeployable).when(_dpm).isAdminVmDeployableInDisabledResources();
VirtualMachineProfile vmProfile = Mockito.mock(VirtualMachineProfile.class);
DataCenter dc = Mockito.mock(DataCenter.class);
ExcludeList avoids = Mockito.mock(ExcludeList.class);
Mockito.when(vmProfile.getType()).thenReturn(vmType);
Mockito.when(vmProfile.getId()).thenReturn(1l);
Mockito.doNothing().when(_dpm).avoidDisabledDataCenters(dc, avoids);
Mockito.doNothing().when(_dpm).avoidDisabledPods(dc, avoids);
Mockito.doNothing().when(_dpm).avoidDisabledClusters(dc, avoids);
Mockito.doNothing().when(_dpm).avoidDisabledHosts(dc, avoids);
VMInstanceVO vmInstanceVO = Mockito.mock(VMInstanceVO.class);
Mockito.when(vmInstanceDao.findById(Mockito.anyLong())).thenReturn(vmInstanceVO);
AccountVO owner = Mockito.mock(AccountVO.class);
Mockito.when(owner.getRoleId()).thenReturn(roleId);
Mockito.when(accountDao.findById(Mockito.anyLong())).thenReturn(owner);
_dpm.avoidDisabledResources(vmProfile, dc, avoids);
Mockito.verify(_dpm, Mockito.times(timesRouter)).isRouterDeployableInDisabledResources();
Mockito.verify(_dpm, Mockito.times(timesAdminVm)).isAdminVmDeployableInDisabledResources();
Mockito.verify(_dpm, Mockito.times(timesDisabledResource)).avoidDisabledDataCenters(dc, avoids);
Mockito.verify(_dpm, Mockito.times(timesDisabledResource)).avoidDisabledPods(dc, avoids);
Mockito.verify(_dpm, Mockito.times(timesDisabledResource)).avoidDisabledClusters(dc, avoids);
Mockito.verify(_dpm, Mockito.times(timesDisabledResource)).avoidDisabledHosts(dc, avoids);
Mockito.reset(_dpm);
}
@Test
public void avoidDisabledDataCentersTest() {
DataCenter dc = Mockito.mock(DataCenter.class);
Mockito.when(dc.getId()).thenReturn(123l);
ExcludeList avoids = new ExcludeList();
AllocationState[] allocationStates = AllocationState.values();
for (int i = 0; i < allocationStates.length - 1; ++i) {
Mockito.when(dc.getAllocationState()).thenReturn(allocationStates[i]);
_dpm.avoidDisabledDataCenters(dc, avoids);
if (allocationStates[i] == AllocationState.Disabled) {
assertAvoidIsEmpty(avoids, false, true, true, true);
Assert.assertTrue(avoids.getDataCentersToAvoid().size() == 1);
Assert.assertTrue(avoids.getDataCentersToAvoid().contains(dc.getId()));
} else {
assertAvoidIsEmpty(avoids, true, true, true, true);
}
}
}
@Test
public void avoidDisabledPodsTestNoDisabledPod() {
DataCenter dc = Mockito.mock(DataCenter.class);
List<Long> podIds = new ArrayList<>();
long expectedPodId = 123l;
podIds.add(expectedPodId);
Mockito.doReturn(new ArrayList<>()).when(hostPodDao).listDisabledPods(Mockito.anyLong());
ExcludeList avoids = new ExcludeList();
_dpm.avoidDisabledPods(dc, avoids);
assertAvoidIsEmpty(avoids, true, true, true, true);
}
@Test
public void avoidDisabledPodsTestHasDisabledPod() {
DataCenter dc = Mockito.mock(DataCenter.class);
List<Long> podIds = new ArrayList<>();
long expectedPodId = 123l;
podIds.add(expectedPodId);
Mockito.doReturn(podIds).when(hostPodDao).listDisabledPods(Mockito.anyLong());
ExcludeList avoids = new ExcludeList();
_dpm.avoidDisabledPods(dc, avoids);
assertAvoidIsEmpty(avoids, true, false, true, true);
Assert.assertTrue(avoids.getPodsToAvoid().size() == 1);
Assert.assertTrue(avoids.getPodsToAvoid().contains(expectedPodId));
}
@Test
public void avoidDisabledClustersTestNoDisabledCluster() {
DataCenter dc = prepareAvoidDisabledTests();
Mockito.doReturn(new ArrayList<>()).when(_clusterDao).listDisabledClusters(Mockito.anyLong(), Mockito.anyLong());
ExcludeList avoids = new ExcludeList();
_dpm.avoidDisabledClusters(dc, avoids);
assertAvoidIsEmpty(avoids, true, true, true, true);
}
@Test
public void avoidDisabledClustersTestHasDisabledCluster() {
DataCenter dc = prepareAvoidDisabledTests();
long expectedClusterId = 123l;
List<Long> disabledClusters = new ArrayList<>();
disabledClusters.add(expectedClusterId);
Mockito.doReturn(disabledClusters).when(_clusterDao).listDisabledClusters(Mockito.anyLong(), Mockito.anyLong());
ExcludeList avoids = new ExcludeList();
_dpm.avoidDisabledClusters(dc, avoids);
assertAvoidIsEmpty(avoids, true, true, false, true);
Assert.assertTrue(avoids.getClustersToAvoid().size() == 1);
Assert.assertTrue(avoids.getClustersToAvoid().contains(expectedClusterId));
}
@Test
public void volumesRequireEncryptionTest() {
VolumeVO vol1 = new VolumeVO("vol1", dataCenterId, podId, 1L, 1L, instanceId, "folder", "path", Storage.ProvisioningType.THIN, (long) 10 << 30, Volume.Type.ROOT);
VolumeVO vol2 = new VolumeVO("vol2", dataCenterId, podId, 1L, 1L, instanceId, "folder", "path", Storage.ProvisioningType.THIN, (long) 10 << 30, Volume.Type.DATADISK);
VolumeVO vol3 = new VolumeVO("vol3", dataCenterId, podId, 1L, 1L, instanceId, "folder", "path", Storage.ProvisioningType.THIN, (long) 10 << 30, Volume.Type.DATADISK);
vol2.setPassphraseId(1L);
List<VolumeVO> volumes = List.of(vol1, vol2, vol3);
Assert.assertTrue("Volumes require encryption, but not reporting", _dpm.anyVolumeRequiresEncryption(volumes));
}
@Test
public void volumesDoNotRequireEncryptionTest() {
VolumeVO vol1 = new VolumeVO("vol1", dataCenterId, podId, 1L, 1L, instanceId, "folder", "path", Storage.ProvisioningType.THIN, (long) 10 << 30, Volume.Type.ROOT);
VolumeVO vol2 = new VolumeVO("vol2", dataCenterId, podId, 1L, 1L, instanceId, "folder", "path", Storage.ProvisioningType.THIN, (long) 10 << 30, Volume.Type.DATADISK);
VolumeVO vol3 = new VolumeVO("vol3", dataCenterId, podId, 1L, 1L, instanceId, "folder", "path", Storage.ProvisioningType.THIN, (long) 10 << 30, Volume.Type.DATADISK);
List<VolumeVO> volumes = List.of(vol1, vol2, vol3);
Assert.assertFalse("Volumes do not require encryption, but reporting they do", _dpm.anyVolumeRequiresEncryption(volumes));
}
/**
* Root requires encryption, chosen host supports it
*/
@Test
public void passEncRootProvidedHostSupportingEncryptionTest() {
HostVO host = new HostVO("host");
Map<String, String> hostDetails = new HashMap<>() {{
put(Host.HOST_VOLUME_ENCRYPTION, "true");
}};
host.setDetails(hostDetails);
VolumeVO vol1 = new VolumeVO("vol1", dataCenterId, podId, 1L, 1L, instanceId, "folder", "path", Storage.ProvisioningType.THIN, (long) 10 << 30, Volume.Type.ROOT);
vol1.setPassphraseId(1L);
setupMocksForPlanDeploymentHostTests(host, vol1);
DataCenterDeployment plan = new DataCenterDeployment(dataCenterId, podId, clusterId, hostId, null, null);
try {
DeployDestination dest = _dpm.planDeployment(vmProfile, plan, avoids, null);
Assert.assertEquals(dest.getHost(), host);
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Root requires encryption, chosen host does not support it
*/
@Test
public void failEncRootProvidedHostNotSupportingEncryptionTest() {
HostVO host = new HostVO("host");
Map<String, String> hostDetails = new HashMap<>() {{
put(Host.HOST_VOLUME_ENCRYPTION, "false");
}};
host.setDetails(hostDetails);
VolumeVO vol1 = new VolumeVO("vol1", dataCenterId, podId, 1L, 1L, instanceId, "folder", "path", Storage.ProvisioningType.THIN, (long) 10 << 30, Volume.Type.ROOT);
vol1.setPassphraseId(1L);
setupMocksForPlanDeploymentHostTests(host, vol1);
DataCenterDeployment plan = new DataCenterDeployment(dataCenterId, podId, clusterId, hostId, null, null);
try {
DeployDestination dest = _dpm.planDeployment(vmProfile, plan, avoids, null);
Assert.assertNull("Destination should be null since host doesn't support encryption and root requires it", dest);
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Root does not require encryption, chosen host does not support it
*/
@Test
public void passNoEncRootProvidedHostNotSupportingEncryptionTest() {
HostVO host = new HostVO("host");
Map<String, String> hostDetails = new HashMap<>() {{
put(Host.HOST_VOLUME_ENCRYPTION, "false");
}};
host.setDetails(hostDetails);
VolumeVO vol1 = new VolumeVO("vol1", dataCenterId, podId, 1L, 1L, instanceId, "folder", "path", Storage.ProvisioningType.THIN, (long) 10 << 30, Volume.Type.ROOT);
setupMocksForPlanDeploymentHostTests(host, vol1);
DataCenterDeployment plan = new DataCenterDeployment(dataCenterId, podId, clusterId, hostId, null, null);
try {
DeployDestination dest = _dpm.planDeployment(vmProfile, plan, avoids, null);
Assert.assertEquals(dest.getHost(), host);
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Root does not require encryption, chosen host does support it
*/
@Test
public void passNoEncRootProvidedHostSupportingEncryptionTest() {
HostVO host = new HostVO("host");
Map<String, String> hostDetails = new HashMap<>() {{
put(Host.HOST_VOLUME_ENCRYPTION, "true");
}};
host.setDetails(hostDetails);
VolumeVO vol1 = new VolumeVO("vol1", dataCenterId, podId, 1L, 1L, instanceId, "folder", "path", Storage.ProvisioningType.THIN, (long) 10 << 30, Volume.Type.ROOT);
setupMocksForPlanDeploymentHostTests(host, vol1);
DataCenterDeployment plan = new DataCenterDeployment(dataCenterId, podId, clusterId, hostId, null, null);
try {
DeployDestination dest = _dpm.planDeployment(vmProfile, plan, avoids, null);
Assert.assertEquals(dest.getHost(), host);
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Root requires encryption, last host supports it
*/
@Test
public void passEncRootLastHostSupportingEncryptionTest() {
HostVO host = Mockito.spy(new HostVO("host"));
Map<String, String> hostDetails = new HashMap<>() {{
put(Host.HOST_VOLUME_ENCRYPTION, "true");
}};
host.setDetails(hostDetails);
Mockito.when(host.getStatus()).thenReturn(Status.Up);
VolumeVO vol1 = new VolumeVO("vol1", dataCenterId, podId, 1L, 1L, instanceId, "folder", "path", Storage.ProvisioningType.THIN, (long) 10 << 30, Volume.Type.ROOT);
vol1.setPassphraseId(1L);
setupMocksForPlanDeploymentHostTests(host, vol1);
VMInstanceVO vm = (VMInstanceVO) vmProfile.getVirtualMachine();
vm.setLastHostId(hostId);
// host id is null here so we pick up last host id
DataCenterDeployment plan = new DataCenterDeployment(dataCenterId, podId, clusterId, null, null, null);
try {
DeployDestination dest = _dpm.planDeployment(vmProfile, plan, avoids, null);
Assert.assertEquals(dest.getHost(), host);
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Root requires encryption, last host does not support it
*/
@Test
public void failEncRootLastHostNotSupportingEncryptionTest() {
HostVO host = Mockito.spy(new HostVO("host"));
Map<String, String> hostDetails = new HashMap<>() {{
put(Host.HOST_VOLUME_ENCRYPTION, "false");
}};
host.setDetails(hostDetails);
Mockito.when(host.getStatus()).thenReturn(Status.Up);
VolumeVO vol1 = new VolumeVO("vol1", dataCenterId, podId, 1L, 1L, instanceId, "folder", "path", Storage.ProvisioningType.THIN, (long) 10 << 30, Volume.Type.ROOT);
vol1.setPassphraseId(1L);
setupMocksForPlanDeploymentHostTests(host, vol1);
VMInstanceVO vm = (VMInstanceVO) vmProfile.getVirtualMachine();
vm.setLastHostId(hostId);
// host id is null here so we pick up last host id
DataCenterDeployment plan = new DataCenterDeployment(dataCenterId, podId, clusterId, null, null, null);
try {
DeployDestination dest = _dpm.planDeployment(vmProfile, plan, avoids, null);
Assert.assertNull("Destination should be null since last host doesn't support encryption and root requires it", dest);
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Test
public void passEncRootPlannerHostSupportingEncryptionTest() {
HostVO host = Mockito.spy(new HostVO("host"));
Map<String, String> hostDetails = new HashMap<>() {{
put(Host.HOST_VOLUME_ENCRYPTION, "true");
}};
host.setDetails(hostDetails);
Mockito.when(host.getStatus()).thenReturn(Status.Up);
VolumeVO vol1 = new VolumeVO("vol1", dataCenterId, podId, 1L, 1L, instanceId, "folder", "path", Storage.ProvisioningType.THIN, (long) 10 << 30, Volume.Type.ROOT);
vol1.setPassphraseId(1L);
DeploymentClusterPlanner planner = setupMocksForPlanDeploymentHostTests(host, vol1);
// host id is null here so we pick up last host id
DataCenterDeployment plan = new DataCenterDeployment(dataCenterId, podId, clusterId, null, null, null);
try {
DeployDestination dest = _dpm.planDeployment(vmProfile, plan, avoids, planner);
Assert.assertEquals(host, dest.getHost());
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Test
public void failEncRootPlannerHostSupportingEncryptionTest() {
HostVO host = Mockito.spy(new HostVO("host"));
Map<String, String> hostDetails = new HashMap<>() {{
put(Host.HOST_VOLUME_ENCRYPTION, "false");
}};
host.setDetails(hostDetails);
Mockito.when(host.getStatus()).thenReturn(Status.Up);
VolumeVO vol1 = new VolumeVO("vol1", dataCenterId, podId, 1L, 1L, instanceId, "folder", "path", Storage.ProvisioningType.THIN, (long) 10 << 30, Volume.Type.ROOT);
vol1.setPassphraseId(1L);
DeploymentClusterPlanner planner = setupMocksForPlanDeploymentHostTests(host, vol1);
// host id is null here so we pick up last host id
DataCenterDeployment plan = new DataCenterDeployment(dataCenterId, podId, clusterId, null, null, null);
try {
DeployDestination dest = _dpm.planDeployment(vmProfile, plan, avoids, planner);
Assert.assertNull("Destination should be null since last host doesn't support encryption and root requires it", dest);
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Test
public void findSuitablePoolsForVolumesTest() throws Exception {
Long diskOfferingId = 1L;
HostVO host = Mockito.spy(new HostVO("host"));
Map<String, String> hostDetails = new HashMap<>() {
{
put(Host.HOST_VOLUME_ENCRYPTION, "true");
}
};
host.setDetails(hostDetails);
Mockito.when(host.getStatus()).thenReturn(Status.Up);
VolumeVO vol1 = Mockito.spy(new VolumeVO("vol1", dataCenterId, podId, 1L, 1L, instanceId, "folder", "path",
Storage.ProvisioningType.THIN, (long) 10 << 30, Volume.Type.ROOT));
Mockito.when(vol1.getId()).thenReturn(1L);
vol1.setState(Volume.State.Allocated);
vol1.setPassphraseId(1L);
vol1.setPoolId(1L);
vol1.setDiskOfferingId(diskOfferingId);
StoragePoolVO storagePool = new StoragePoolVO();
storagePool.setStatus(StoragePoolStatus.Maintenance);
storagePool.setId(vol1.getPoolId());
storagePool.setDataCenterId(dataCenterId);
storagePool.setPodId(podId);
storagePool.setClusterId(clusterId);
DiskProfile diskProfile = Mockito.mock(DiskProfile.class);
StoragePoolAllocator allocator = Mockito.mock(StoragePoolAllocator.class);
DataCenterDeployment plan = new DataCenterDeployment(dataCenterId, podId, clusterId, null, null, null);
Account account = Mockito.mock(Account.class);
Mockito.when(account.getId()).thenReturn(1L);
Mockito.when(vmProfile.getOwner()).thenReturn(account);
Mockito.when(_accountMgr.isRootAdmin(account.getId())).thenReturn(Boolean.FALSE);
Mockito.when(_dcDao.findById(dataCenterId)).thenReturn(dc);
Mockito.when(dc.getAllocationState()).thenReturn(AllocationState.Enabled);
HostPodVO podVo = Mockito.mock(HostPodVO.class);
Mockito.when(podVo.getAllocationState()).thenReturn(AllocationState.Enabled);
Mockito.doReturn(podVo).when(_podDao).findById(podId);
ClusterVO cluster = Mockito.mock(ClusterVO.class);
Mockito.when(cluster.getAllocationState()).thenReturn(AllocationState.Enabled);
Mockito.when(_clusterDao.findById(clusterId)).thenReturn(cluster);
DiskOfferingVO diskOffering = Mockito.mock(DiskOfferingVO.class);
Mockito.when(_diskOfferingDao.findById(vol1.getDiskOfferingId())).thenReturn(diskOffering);
VirtualMachineTemplate vmt = Mockito.mock(VirtualMachineTemplate.class);
ServiceOfferingVO serviceOffering = Mockito.mock(ServiceOfferingVO.class);
Mockito.when(vmProfile.getServiceOffering()).thenReturn(serviceOffering);
PrimaryDataStore primaryDataStore = Mockito.mock(PrimaryDataStore.class);
Mockito.when(vmt.getFormat()).thenReturn(Storage.ImageFormat.ISO);
Mockito.when(vmProfile.getTemplate()).thenReturn(vmt);
Mockito.when(vmProfile.getId()).thenReturn(1L);
Mockito.when(vmProfile.getType()).thenReturn(VirtualMachine.Type.User);
Mockito.when(volDao.findUsableVolumesForInstance(1L)).thenReturn(Arrays.asList(vol1));
Mockito.when(volDao.findByInstanceAndType(1L, Volume.Type.ROOT)).thenReturn(Arrays.asList(vol1));
Mockito.when(_dataStoreManager.getPrimaryDataStore(vol1.getPoolId())).thenReturn((DataStore) primaryDataStore);
Mockito.when(avoids.shouldAvoid(storagePool)).thenReturn(Boolean.FALSE);
Mockito.doReturn(Arrays.asList(storagePool)).when(allocator).allocateToPool(diskProfile, vmProfile, plan,
avoids, 10);
Mockito.when(volDao.update(vol1.getId(), vol1)).thenReturn(true);
_dpm.findSuitablePoolsForVolumes(vmProfile, plan, avoids, 10);
verify(vol1, times(1)).setPoolId(null);
assertTrue(vol1.getPoolId() == null);
}
// This is so ugly but everything is so intertwined...
private DeploymentClusterPlanner setupMocksForPlanDeploymentHostTests(HostVO host, VolumeVO vol1) {
long diskOfferingId = 345L;
List<VolumeVO> volumeVOs = new ArrayList<>();
List<Volume> volumes = new ArrayList<>();
vol1.setDiskOfferingId(diskOfferingId);
volumes.add(vol1);
volumeVOs.add(vol1);
DiskOfferingVO diskOffering = new DiskOfferingVO();
diskOffering.setEncrypt(true);
VMTemplateVO template = new VMTemplateVO();
template.setFormat(Storage.ImageFormat.QCOW2);
host.setClusterId(clusterId);
StoragePool pool = new StoragePoolVO();
Map<Volume, List<StoragePool>> suitableVolumeStoragePools = new HashMap<>() {{
put(vol1, List.of(pool));
}};
Pair<Map<Volume, List<StoragePool>>, List<Volume>> suitable = new Pair<>(suitableVolumeStoragePools, volumes);
ServiceOfferingVO svcOffering = new ServiceOfferingVO("test", 1, 256, 1, 1, 1, false, "vm", false, Type.User, false);
Mockito.when(vmProfile.getServiceOffering()).thenReturn(svcOffering);
Mockito.when(vmProfile.getHypervisorType()).thenReturn(HypervisorType.KVM);
Mockito.when(hostDao.findById(hostId)).thenReturn(host);
Mockito.doNothing().when(hostDao).loadDetails(host);
Mockito.doReturn(volumeVOs).when(volDao).findByInstance(ArgumentMatchers.anyLong());
Mockito.doReturn(suitable).when(_dpm).findSuitablePoolsForVolumes(
ArgumentMatchers.any(VirtualMachineProfile.class),
ArgumentMatchers.any(DataCenterDeployment.class),
ArgumentMatchers.any(ExcludeList.class),
ArgumentMatchers.anyInt()
);
ClusterVO clusterVO = new ClusterVO();
clusterVO.setHypervisorType(HypervisorType.KVM.toString());
Mockito.when(_clusterDao.findById(ArgumentMatchers.anyLong())).thenReturn(clusterVO);
Mockito.doReturn(List.of(host)).when(_dpm).findSuitableHosts(
ArgumentMatchers.any(VirtualMachineProfile.class),
ArgumentMatchers.any(DeploymentPlan.class),
ArgumentMatchers.any(ExcludeList.class),
ArgumentMatchers.anyInt()
);
Map<Volume, StoragePool> suitableVolumeStoragePoolMap = new HashMap<>() {{
put(vol1, pool);
}};
Mockito.doReturn(true).when(_dpm).hostCanAccessSPool(ArgumentMatchers.any(Host.class), ArgumentMatchers.any(StoragePool.class));
Pair<Host, Map<Volume, StoragePool>> potentialResources = new Pair<>(host, suitableVolumeStoragePoolMap);
Mockito.when(capacityMgr.checkIfHostReachMaxGuestLimit(host)).thenReturn(false);
Mockito.when(capacityMgr.checkIfHostHasCpuCapability(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())).thenReturn(true);
Mockito.when(capacityMgr.checkIfHostHasCapacity(
ArgumentMatchers.anyLong(),
ArgumentMatchers.anyInt(),
ArgumentMatchers.anyLong(),
ArgumentMatchers.anyBoolean(),
ArgumentMatchers.anyFloat(),
ArgumentMatchers.anyFloat(),
ArgumentMatchers.anyBoolean()
)).thenReturn(true);
Mockito.when(serviceOfferingDetailsDao.findDetail(vmProfile.getServiceOfferingId(), GPU.Keys.vgpuType.toString())).thenReturn(null);
Mockito.doReturn(true).when(_dpm).checkVmProfileAndHost(vmProfile, host);
Mockito.doReturn(true).when(_dpm).checkIfHostFitsPlannerUsage(ArgumentMatchers.anyLong(), ArgumentMatchers.nullable(PlannerResourceUsage.class));
Mockito.when(clusterDetailsDao.findDetail(ArgumentMatchers.anyLong(), ArgumentMatchers.anyString())).thenReturn(new ClusterDetailsVO(clusterId, "mock", "1"));
DeploymentClusterPlanner planner = Mockito.spy(new FirstFitPlanner());
try {
Mockito.doReturn(List.of(clusterId), List.of()).when(planner).orderClusters(
ArgumentMatchers.any(VirtualMachineProfile.class),
ArgumentMatchers.any(DeploymentPlan.class),
ArgumentMatchers.any(ExcludeList.class)
);
} catch (Exception ex) {
ex.printStackTrace();
}
return planner;
}
private DataCenter prepareAvoidDisabledTests() {
DataCenter dc = Mockito.mock(DataCenter.class);
Mockito.when(dc.getId()).thenReturn(123l);
List<Long> podIds = new ArrayList<>();
podIds.add(1l);
Mockito.doReturn(podIds).when(hostPodDao).listAllPods(Mockito.anyLong());
return dc;
}
private void assertAvoidIsEmpty(ExcludeList avoids, boolean isDcEmpty, boolean isPodsEmpty, boolean isClustersEmpty,
boolean isHostsEmpty) {
Assert.assertEquals(isDcEmpty, CollectionUtils.isEmpty(avoids.getDataCentersToAvoid()));
Assert.assertEquals(isPodsEmpty, CollectionUtils.isEmpty(avoids.getPodsToAvoid()));
Assert.assertEquals(isClustersEmpty, CollectionUtils.isEmpty(avoids.getClustersToAvoid()));
Assert.assertEquals(isHostsEmpty, CollectionUtils.isEmpty(avoids.getHostsToAvoid()));
}
@Configuration
@ComponentScan(basePackageClasses = {DeploymentPlanningManagerImpl.class},
includeFilters = {@Filter(value = TestConfiguration.Library.class,
type = FilterType.CUSTOM)}, useDefaultFilters = false)
public static class TestConfiguration extends SpringUtils.CloudStackTestConfiguration {
@Bean
public FirstFitPlanner firstFitPlanner() {
return Mockito.mock(FirstFitPlanner.class);
}
@Bean
public DeploymentPlanner deploymentPlanner() {
return Mockito.mock(DeploymentPlanner.class);
}
@Bean
public DataCenterVO dataCenter() {
return Mockito.mock(DataCenterVO.class);
}
@Bean
public ExcludeList excludeList() {
return Mockito.mock(ExcludeList.class);
}
@Bean
public VirtualMachineProfileImpl virtualMachineProfileImpl() {
return Mockito.mock(VirtualMachineProfileImpl.class);
}
@Bean
public HostTagsDao hostTagsDao() {
return Mockito.mock(HostTagsDao.class);
}
@Bean
public HostDetailsDao hostDetailsDao() {
return Mockito.mock(HostDetailsDao.class);
}
@Bean
public ClusterDetailsDao clusterDetailsDao() {
return Mockito.mock(ClusterDetailsDao.class);
}
@Bean
public ResourceManager resourceManager() {
return Mockito.mock(ResourceManager.class);
}
@Bean
public ServiceOfferingDetailsDao serviceOfferingDetailsDao() {
return Mockito.mock(ServiceOfferingDetailsDao.class);
}
@Bean
public AffinityGroupDomainMapDao affinityGroupDomainMapDao() {
return Mockito.mock(AffinityGroupDomainMapDao.class);
}
@Bean
public DataStoreManager cataStoreManager() {
return Mockito.mock(DataStoreManager.class);
}
@Bean
public StorageManager storageManager() {
return Mockito.mock(StorageManager.class);
}
@Bean
public HostDao hostDao() {
return Mockito.mock(HostDao.class);
}
@Bean
public HostPodDao hostPodDao() {
return Mockito.mock(HostPodDao.class);
}
@Bean
public ClusterDao clusterDao() {
return Mockito.mock(ClusterDao.class);
}
@Bean
public DedicatedResourceDao dedicatedResourceDao() {
return Mockito.mock(DedicatedResourceDao.class);
}
@Bean
public GuestOSDao guestOSDao() {
return Mockito.mock(GuestOSDao.class);
}
@Bean
public GuestOSCategoryDao guestOSCategoryDao() {
return Mockito.mock(GuestOSCategoryDao.class);
}
@Bean
public CapacityManager capacityManager() {
return Mockito.mock(CapacityManager.class);
}
@Bean
public StoragePoolHostDao storagePoolHostDao() {
return Mockito.mock(StoragePoolHostDao.class);
}
@Bean
public VolumeDao volumeDao() {
return Mockito.mock(VolumeDao.class);
}
@Bean
public ConfigurationDao configurationDao() {
return Mockito.mock(ConfigurationDao.class);
}
@Bean
public DiskOfferingDao diskOfferingDao() {
return Mockito.mock(DiskOfferingDao.class);
}
@Bean
public PrimaryDataStoreDao primaryDataStoreDao() {
return Mockito.mock(PrimaryDataStoreDao.class);
}
@Bean
public CapacityDao capacityDao() {
return Mockito.mock(CapacityDao.class);
}
@Bean
public PlannerHostReservationDao plannerHostReservationDao() {
return Mockito.mock(PlannerHostReservationDao.class);
}
@Bean
public AffinityGroupProcessor affinityGroupProcessor() {
return Mockito.mock(AffinityGroupProcessor.class);
}
@Bean
public AffinityGroupDao affinityGroupDao() {
return Mockito.mock(AffinityGroupDao.class);
}
@Bean
public AffinityGroupVMMapDao affinityGroupVMMapDao() {
return Mockito.mock(AffinityGroupVMMapDao.class);
}
@Bean
public AccountManager accountManager() {
return Mockito.mock(AccountManager.class);
}
@Bean
public AgentManager agentManager() {
return Mockito.mock(AgentManager.class);
}
@Bean
public MessageBus messageBus() {
return Mockito.mock(MessageBus.class);
}
@Bean
public UserVmDao userVMDao() {
return Mockito.mock(UserVmDao.class);
}
@Bean
public UserVmDetailsDao userVmDetailsDao() {
return Mockito.mock(UserVmDetailsDao.class);
}
@Bean
public VMInstanceDao vmInstanceDao() {
return Mockito.mock(VMInstanceDao.class);
}
@Bean
public DataCenterDao dataCenterDao() {
return Mockito.mock(DataCenterDao.class);
}
@Bean
public VMReservationDao reservationDao() {
return Mockito.mock(VMReservationDao.class);
}
@Bean
public AffinityGroupService affinityGroupService() {
return Mockito.mock(AffinityGroupService.class);
}
@Bean
public HostGpuGroupsDao hostGpuGroupsDao() {
return Mockito.mock(HostGpuGroupsDao.class);
}
@Bean
public AccountDao accountDao() {
return Mockito.mock(AccountDao.class);
}
@Bean
public VMTemplateDao vmTemplateDao() {
return Mockito.mock(VMTemplateDao.class);
}
public static class Library implements TypeFilter {
@Override
public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException {
ComponentScan cs = TestConfiguration.class.getAnnotation(ComponentScan.class);
return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs);
}
}
}
@Test
public void testReorderHostsByPriority() {
Map<Long, Integer> priorities = new LinkedHashMap<>();
priorities.put(1L, 3);
priorities.put(2L, -6);
priorities.put(3L, 5);
priorities.put(5L, 8);
priorities.put(6L, -1);
priorities.put(8L, 5);
priorities.put(9L, DataCenterDeployment.PROHIBITED_HOST_PRIORITY);
Host host1 = Mockito.mock(Host.class);
Mockito.when(host1.getId()).thenReturn(1L);
Host host2 = Mockito.mock(Host.class);
Mockito.when(host2.getId()).thenReturn(2L);
Host host3 = Mockito.mock(Host.class);
Mockito.when(host3.getId()).thenReturn(3L);
Host host4 = Mockito.mock(Host.class);
Mockito.when(host4.getId()).thenReturn(4L);
Host host5 = Mockito.mock(Host.class);
Mockito.when(host5.getId()).thenReturn(5L);
Host host6 = Mockito.mock(Host.class);
Mockito.when(host6.getId()).thenReturn(6L);
Host host7 = Mockito.mock(Host.class);
Mockito.when(host7.getId()).thenReturn(7L);
Host host8 = Mockito.mock(Host.class);
Mockito.when(host8.getId()).thenReturn(8L);
Host host9 = Mockito.mock(Host.class);
Mockito.when(host9.getId()).thenReturn(9L);
List<Host> hosts = new ArrayList<>(Arrays.asList(host1, host2, host3, host4, host5, host6, host7, host8, host9));
_dpm.reorderHostsByPriority(priorities, hosts);
Assert.assertEquals(8, hosts.size());
Assert.assertEquals(5, hosts.get(0).getId());
Assert.assertEquals(3, hosts.get(1).getId());
Assert.assertEquals(8, hosts.get(2).getId());
Assert.assertEquals(1, hosts.get(3).getId());
Assert.assertEquals(4, hosts.get(4).getId());
Assert.assertEquals(7, hosts.get(5).getId());
Assert.assertEquals(6, hosts.get(6).getId());
Assert.assertEquals(2, hosts.get(7).getId());
}
private List<Long> prepareMockForAvoidOtherClustersForDeploymentIfMigrationDisabled(boolean configValue,
boolean mockVolumes, boolean mockClusterStoreVolume) {
try {
Field f = ConfigKey.class.getDeclaredField("_defaultValue");
f.setAccessible(true);
f.set(ConfigurationManagerImpl.MIGRATE_VM_ACROSS_CLUSTERS, String.valueOf(configValue));
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
List<Long> allClusters = List.of(101L, 102L, 103L, 104L);
Mockito.when(_clusterDao.listAllClusters(Mockito.anyLong())).thenReturn(allClusters);
if (mockVolumes) {
VolumeVO vol1 = Mockito.mock(VolumeVO.class);
Mockito.when(vol1.getPoolId()).thenReturn(1L);
VolumeVO vol2 = Mockito.mock(VolumeVO.class);
Mockito.when(vol2.getPoolId()).thenReturn(2L);
StoragePoolVO pool1 = Mockito.mock(StoragePoolVO.class);
Mockito.when(pool1.getScope()).thenReturn(ScopeType.ZONE);
Mockito.when(primaryDataStoreDao.findById(1L)).thenReturn(pool1);
StoragePoolVO pool2 = Mockito.mock(StoragePoolVO.class);
Mockito.when(pool2.getScope()).thenReturn(mockClusterStoreVolume ? ScopeType.CLUSTER : ScopeType.GLOBAL);
Mockito.when(primaryDataStoreDao.findById(2L)).thenReturn(pool2);
Mockito.when(volDao.findUsableVolumesForInstance(1L)).thenReturn(List.of(vol1, vol2));
} else {
Mockito.when(volDao.findUsableVolumesForInstance(1L)).thenReturn(new ArrayList<>());
}
return allClusters;
}
@Test
public void avoidOtherClustersForDeploymentIfMigrationDisabledNonValidHost() {
prepareMockForAvoidOtherClustersForDeploymentIfMigrationDisabled(false, false, false);
VirtualMachine vm = Mockito.mock(VirtualMachine.class);
ExcludeList excludeList = new ExcludeList();
_dpm.avoidOtherClustersForDeploymentIfMigrationDisabled(vm, null, excludeList);
Assert.assertTrue(CollectionUtils.isEmpty(excludeList.getClustersToAvoid()));
Host lastHost = Mockito.mock(Host.class);
Mockito.when(lastHost.getClusterId()).thenReturn(null);
_dpm.avoidOtherClustersForDeploymentIfMigrationDisabled(vm, lastHost, excludeList);
Assert.assertTrue(CollectionUtils.isEmpty(excludeList.getClustersToAvoid()));
}
private Set<Long> runAvoidOtherClustersForDeploymentIfMigrationDisabledTest() {
VirtualMachine vm = Mockito.mock(VirtualMachine.class);
Mockito.when(vm.getId()).thenReturn(1L);
ExcludeList excludeList = new ExcludeList();
Host lastHost = Mockito.mock(Host.class);
Long sourceClusterId = 101L;
Mockito.when(lastHost.getClusterId()).thenReturn(sourceClusterId);
_dpm.avoidOtherClustersForDeploymentIfMigrationDisabled(vm, lastHost, excludeList);
return excludeList.getClustersToAvoid();
}
@Test
public void avoidOtherClustersForDeploymentIfMigrationDisabledConfigAllows() {
prepareMockForAvoidOtherClustersForDeploymentIfMigrationDisabled(true, false, false);
Assert.assertTrue(CollectionUtils.isEmpty(runAvoidOtherClustersForDeploymentIfMigrationDisabledTest()));
}
@Test
public void avoidOtherClustersForDeploymentIfMigrationDisabledNoVmVolumes() {
prepareMockForAvoidOtherClustersForDeploymentIfMigrationDisabled(false, false, false);
Assert.assertTrue(CollectionUtils.isEmpty(runAvoidOtherClustersForDeploymentIfMigrationDisabledTest()));
}
@Test
public void avoidOtherClustersForDeploymentIfMigrationDisabledVmVolumesNonValidScope() {
prepareMockForAvoidOtherClustersForDeploymentIfMigrationDisabled(false, true, false);
Assert.assertTrue(CollectionUtils.isEmpty(runAvoidOtherClustersForDeploymentIfMigrationDisabledTest()));
}
@Test
public void avoidOtherClustersForDeploymentIfMigrationDisabledValid() {
List<Long> allClusters = prepareMockForAvoidOtherClustersForDeploymentIfMigrationDisabled(false, true, true);
Set<Long> avoidedClusters = runAvoidOtherClustersForDeploymentIfMigrationDisabledTest();
Assert.assertTrue(CollectionUtils.isNotEmpty(avoidedClusters));
Assert.assertEquals(allClusters.size() - 1, avoidedClusters.size());
Assert.assertFalse(avoidedClusters.contains(allClusters.get(0)));
}
}