// 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.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);
        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 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.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)));
    }
}
