mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com> Co-authored-by: Suresh Kumar Anaparti <sureshkumar.anaparti@gmail.com> Co-authored-by: dahn <daan@onecht.net>
1292 lines
53 KiB
Java
1292 lines
53 KiB
Java
// 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.cpu.CPU;
|
|
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.VMInstanceDetailsDao;
|
|
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
|
|
VMInstanceDetailsDao 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);
|
|
VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class);
|
|
Mockito.when(template.getArch()).thenReturn(CPU.CPUArch.amd64);
|
|
Mockito.when(vmProfile.getTemplate()).thenReturn(template);
|
|
Mockito.when(_clusterDao.listClustersByArchAndZoneId(dataCenterId, CPU.CPUArch.arm64)).thenReturn(null);
|
|
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);
|
|
VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class);
|
|
Mockito.when(template.getArch()).thenReturn(CPU.CPUArch.amd64);
|
|
Mockito.when(vmProfile.getTemplate()).thenReturn(template);
|
|
Mockito.when(_clusterDao.listClustersByArchAndZoneId(dataCenterId, CPU.CPUArch.arm64)).thenReturn(null);
|
|
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);
|
|
VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class);
|
|
Mockito.when(template.getArch()).thenReturn(CPU.CPUArch.amd64);
|
|
Mockito.when(vmProfile.getTemplate()).thenReturn(template);
|
|
Mockito.when(_clusterDao.listClustersByArchAndZoneId(dataCenterId, CPU.CPUArch.arm64)).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.any(Host.class), ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())).thenReturn(true);
|
|
Mockito.when(capacityMgr.checkIfHostHasCapacity(
|
|
ArgumentMatchers.any(),
|
|
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.any(Host.class), 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 VMInstanceDetailsDao vmInstanceDetailsDao() {
|
|
return Mockito.mock(VMInstanceDetailsDao.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.listAllClusterIds(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)));
|
|
}
|
|
}
|