Allow deploy Admin VMs and VRs in disabled zones/pods/clusters (#3600)

This commit is contained in:
Gabriel Beims Bräscher 2021-05-28 05:45:30 -03:00 committed by GitHub
parent 6531ee5871
commit a3cdd1f836
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 372 additions and 99 deletions

View File

@ -22,9 +22,17 @@ import com.cloud.exception.AffinityConflictException;
import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.utils.component.Manager;
import com.cloud.vm.VirtualMachineProfile;
import org.apache.cloudstack.framework.config.ConfigKey;
public interface DeploymentPlanningManager extends Manager {
static final ConfigKey<Boolean> allowRouterOnDisabledResource = new ConfigKey<Boolean>("Advanced", Boolean.class, "allow.router.on.disabled.resources", "false",
"Allow deploying VR in disabled Zones, Pods, and Clusters", true);
static final ConfigKey<Boolean> allowAdminVmOnDisabledResource = new ConfigKey<Boolean>("Advanced", Boolean.class, "allow.admin.vm.on.disabled.resources", "false",
"Allow deploying VMs owned by the admin account in disabled Clusters, Pods, and Zones", true);
/**
* Manages vm deployment stages: First Process Affinity/Anti-affinity - Call
* the chain of AffinityGroupProcessor adapters to set deploymentplan scope

View File

@ -83,8 +83,21 @@ public interface HostDao extends GenericDao<HostVO, Long>, StateDao<Status, Stat
List<HostVO> findByClusterId(Long clusterId);
/**
* Returns hosts that are 'Up' and 'Enabled' from the given Data Center/Zone
*/
List<HostVO> listByDataCenterId(long id);
/**
* Returns hosts that are from the given Data Center/Zone and at a given state (e.g. Creating, Enabled, Disabled, etc).
*/
List<HostVO> listByDataCenterIdAndState(long id, ResourceState state);
/**
* Returns hosts that are 'Up' and 'Disabled' from the given Data Center/Zone
*/
List<HostVO> listDisabledByDataCenterId(long id);
List<HostVO> listByDataCenterIdAndHypervisorType(long zoneId, Hypervisor.HypervisorType hypervisorType);
List<Long> listAllHosts(long zoneId);

View File

@ -463,13 +463,27 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
@Override
public List<HostVO> listByDataCenterId(long id) {
return listByDataCenterIdAndState(id, ResourceState.Enabled);
}
@Override
public List<HostVO> listByDataCenterIdAndState(long id, ResourceState state) {
SearchCriteria<HostVO> sc = scHostsFromZoneUpRouting(id);
sc.setParameters("resourceState", state);
return listBy(sc);
}
@Override
public List<HostVO> listDisabledByDataCenterId(long id) {
return listByDataCenterIdAndState(id, ResourceState.Disabled);
}
private SearchCriteria<HostVO> scHostsFromZoneUpRouting(long id) {
SearchCriteria<HostVO> sc = DcSearch.create();
sc.setParameters("dc", id);
sc.setParameters("status", Status.Up);
sc.setParameters("type", Host.Type.Routing);
sc.setParameters("resourceState", ResourceState.Enabled);
return listBy(sc);
return sc;
}
@Override

View File

@ -238,7 +238,7 @@ public class VMInstanceVO implements VirtualMachine, FiniteStateObject<State, Vi
this.diskOfferingId = diskOfferingId;
}
protected VMInstanceVO() {
public VMInstanceVO() {
}
public Date getRemoved() {

View File

@ -45,7 +45,6 @@ import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.host.Host;
import com.cloud.host.Host.Type;
import com.cloud.host.dao.HostDao;
import com.cloud.org.Grouping;
import com.cloud.resource.ResourceManager;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.VolumeDao;
@ -122,21 +121,7 @@ public class RecreateHostAllocator extends FirstFitRoutingAllocator {
}
for (PodCluster p : pcs) {
if (p.getPod().getAllocationState() != Grouping.AllocationState.Enabled) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Pod name: " + p.getPod().getName() + ", podId: " + p.getPod().getId() + " is in " + p.getPod().getAllocationState().name() +
" state, skipping this and trying other pods");
}
continue;
}
Long clusterId = p.getCluster() == null ? null : p.getCluster().getId();
if (p.getCluster() != null && p.getCluster().getAllocationState() != Grouping.AllocationState.Enabled) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Cluster name: " + p.getCluster().getName() + ", clusterId: " + clusterId + " is in " + p.getCluster().getAllocationState().name() +
" state, skipping this and trying other pod-clusters");
}
continue;
}
DataCenterDeployment newPlan = new DataCenterDeployment(plan.getDataCenterId(), p.getPod().getId(), clusterId, null, null, null);
hosts = super.allocateTo(vm, newPlan, type, avoid, returnUpTo);
if (hosts != null && !hosts.isEmpty()) {

View File

@ -31,6 +31,20 @@ import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.user.AccountVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.StringUtils;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.utils.db.Filter;
import com.cloud.utils.fsm.StateMachine2;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.log4j.Logger;
import org.apache.cloudstack.affinity.AffinityGroupProcessor;
import org.apache.cloudstack.affinity.AffinityGroupService;
import org.apache.cloudstack.affinity.AffinityGroupVMMapVO;
@ -50,9 +64,6 @@ import org.apache.cloudstack.managed.context.ManagedContextTimerTask;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.utils.identity.ManagementServerNode;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.Listener;
@ -84,7 +95,6 @@ import com.cloud.deploy.dao.PlannerHostReservationDao;
import com.cloud.exception.AffinityConflictException;
import com.cloud.exception.ConnectionException;
import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.gpu.GPU;
import com.cloud.host.DetailVO;
import com.cloud.host.Host;
@ -97,7 +107,6 @@ import com.cloud.offering.ServiceOffering;
import com.cloud.org.Cluster;
import com.cloud.org.Grouping;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ResourceState;
import com.cloud.service.ServiceOfferingDetailsVO;
import com.cloud.service.dao.ServiceOfferingDetailsDao;
import com.cloud.storage.DiskOfferingVO;
@ -107,31 +116,26 @@ import com.cloud.storage.Storage;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolHostVO;
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.user.AccountManager;
import com.cloud.utils.DateUtil;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.StringUtils;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.TransactionCallback;
import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.StateListener;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.vm.DiskProfile;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
@ -144,12 +148,14 @@ import com.cloud.vm.dao.VMInstanceDao;
import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
public class DeploymentPlanningManagerImpl extends ManagerBase implements DeploymentPlanningManager, Manager, Listener,
StateListener<State, VirtualMachine.Event, VirtualMachine> {
StateListener<State, VirtualMachine.Event, VirtualMachine>, Configurable {
private static final Logger s_logger = Logger.getLogger(DeploymentPlanningManagerImpl.class);
@Inject
AgentManager _agentMgr;
@Inject
private AccountDao accountDao;
@Inject
protected UserVmDao _vmDao;
@Inject
protected VMInstanceDao _vmInstanceDao;
@ -177,6 +183,7 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> {
@Inject
private VMTemplateDao templateDao;
private static final long ADMIN_ACCOUNT_ROLE_ID = 1l;
private static final long INITIAL_RESERVATION_RELEASE_CHECKER_DELAY = 30L * 1000L; // thirty seconds expressed in milliseconds
protected long _nodeId = -1;
@ -283,6 +290,8 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> {
s_logger.debug("Is ROOT volume READY (pool already allocated)?: " + (plan.getPoolId() != null ? "Yes" : "No"));
}
avoidDisabledResources(vmProfile, dc, avoids);
String haVmTag = (String)vmProfile.getParameter(VirtualMachineProfile.Param.HaTag);
String uefiFlag = (String)vmProfile.getParameter(VirtualMachineProfile.Param.UefiFlag);
@ -311,17 +320,8 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> {
}
Pod pod = _podDao.findById(host.getPodId());
// check if the cluster or the pod is disabled
if (pod.getAllocationState() != Grouping.AllocationState.Enabled) {
s_logger.warn("The Pod containing this host is in disabled state, PodId= " + pod.getId());
return null;
}
Cluster cluster = _clusterDao.findById(host.getClusterId());
if (cluster.getAllocationState() != Grouping.AllocationState.Enabled) {
s_logger.warn("The Cluster containing this host is in disabled state, PodId= " + cluster.getId());
return null;
}
boolean displayStorage = getDisplayStorageFromVmProfile(vmProfile);
if (vm.getHypervisorType() == HypervisorType.BareMetal) {
@ -422,8 +422,15 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> {
s_logger.debug("The last host of this VM does not have required GPU devices available");
}
} else {
if (host.getStatus() == Status.Up && host.getResourceState() == ResourceState.Enabled) {
if (checkVmProfileAndHost(vmProfile, host)) {
if (host.getStatus() == Status.Up) {
boolean hostTagsMatch = true;
if(offering.getHostTag() != null){
_hostDao.loadHostTags(host);
if (!(host.getHostTags() != null && host.getHostTags().contains(offering.getHostTag()))) {
hostTagsMatch = false;
}
}
if (hostTagsMatch) {
long cluster_id = host.getClusterId();
ClusterDetailsVO cluster_detail_cpu = _clusterDetailsDao.findDetail(cluster_id,
"cpuOvercommitRatio");
@ -573,6 +580,86 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> {
return vmProfile == null || vmProfile.getTemplate() == null || !vmProfile.getTemplate().isDeployAsIs();
}
/**
* Adds disabled resources (Data centers, Pods, Clusters, and hosts) to exclude list (avoid) in case of disabled state.
*/
public void avoidDisabledResources(VirtualMachineProfile vmProfile, DataCenter dc, ExcludeList avoids) {
if (vmProfile.getType().isUsedBySystem() && isRouterDeployableInDisabledResources()) {
return;
}
VMInstanceVO vm = _vmInstanceDao.findById(vmProfile.getId());
AccountVO owner = accountDao.findById(vm.getAccountId());
boolean isOwnerRoleIdAdmin = false;
if (owner != null && owner.getRoleId() != null && owner.getRoleId() == ADMIN_ACCOUNT_ROLE_ID) {
isOwnerRoleIdAdmin = true;
}
if (isOwnerRoleIdAdmin && isAdminVmDeployableInDisabledResources()) {
return;
}
avoidDisabledDataCenters(dc, avoids);
avoidDisabledPods(dc, avoids);
avoidDisabledClusters(dc, avoids);
avoidDisabledHosts(dc, avoids);
}
/**
* Returns the value of the ConfigKey 'allow.router.on.disabled.resources'.
* @note this method allows mocking and testing with the respective ConfigKey parameter.
*/
protected boolean isRouterDeployableInDisabledResources() {
return allowRouterOnDisabledResource.value();
}
/**
* Returns the value of the ConfigKey 'allow.admin.vm.on.disabled.resources'.
* @note this method allows mocking and testing with the respective ConfigKey parameter.
*/
protected boolean isAdminVmDeployableInDisabledResources() {
return allowAdminVmOnDisabledResource.value();
}
/**
* Adds disabled Hosts to the ExcludeList in order to avoid them at the deployment planner.
*/
protected void avoidDisabledHosts(DataCenter dc, ExcludeList avoids) {
List<HostVO> disabledHosts = _hostDao.listDisabledByDataCenterId(dc.getId());
for (HostVO host : disabledHosts) {
avoids.addHost(host.getId());
}
}
/**
* Adds disabled Clusters to the ExcludeList in order to avoid them at the deployment planner.
*/
protected void avoidDisabledClusters(DataCenter dc, ExcludeList avoids) {
List<Long> pods = _podDao.listAllPods(dc.getId());
for (Long podId : pods) {
List<Long> disabledClusters = _clusterDao.listDisabledClusters(dc.getId(), podId);
avoids.addClusterList(disabledClusters);
}
}
/**
* Adds disabled Pods to the ExcludeList in order to avoid them at the deployment planner.
*/
protected void avoidDisabledPods(DataCenter dc, ExcludeList avoids) {
List<Long> disabledPods = _podDao.listDisabledPods(dc.getId());
avoids.addPodList(disabledPods);
}
/**
* Adds disabled Data Centers (Zones) to the ExcludeList in order to avoid them at the deployment planner.
*/
protected void avoidDisabledDataCenters(DataCenter dc, ExcludeList avoids) {
if (dc.getAllocationState() == Grouping.AllocationState.Disabled) {
avoids.addDataCenter(dc.getId());
}
}
@Override
public DeploymentPlanner getDeploymentPlannerByName(String plannerName) {
if (plannerName != null) {
@ -1092,11 +1179,6 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> {
for (Long clusterId : clusterList) {
ClusterVO clusterVO = _clusterDao.findById(clusterId);
if (clusterVO.getAllocationState() == Grouping.AllocationState.Disabled && !plan.isMigrationPlan()) {
s_logger.debug("Cannot deploy in disabled cluster " + clusterId + ", skipping this cluster");
avoid.addCluster(clusterVO.getId());
}
if (clusterVO.getHypervisorType() != vmProfile.getHypervisorType()) {
s_logger.debug("Cluster: " + clusterId + " has HyperVisorType that does not match the VM, skipping this cluster");
avoid.addCluster(clusterVO.getId());
@ -1110,7 +1192,9 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> {
new DataCenterDeployment(plan.getDataCenterId(), clusterVO.getPodId(), clusterVO.getId(), null, plan.getPoolId(), null, plan.getReservationContext());
Pod pod = _podDao.findById(clusterVO.getPodId());
if (pod.getAllocationState() == Grouping.AllocationState.Enabled ) {
if (CollectionUtils.isNotEmpty(avoid.getPodsToAvoid()) && avoid.getPodsToAvoid().contains(pod.getId())) {
s_logger.debug("The cluster is in a disabled pod : " + pod.getId());
} else {
// find suitable hosts under this cluster, need as many hosts as we
// get.
List<Host> suitableHosts = findSuitableHosts(vmProfile, potentialPlan, avoid, HostAllocator.RETURN_UPTO_ALL);
@ -1151,9 +1235,6 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> {
s_logger.debug("No suitable hosts found under this Cluster: " + clusterId);
}
}
else {
s_logger.debug("The cluster is in a disabled pod : " + pod.getId());
}
if (canAvoidCluster(clusterVO, avoid, plannerAvoidOutput, vmProfile)) {
avoid.addCluster(clusterVO.getId());
@ -1739,4 +1820,14 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> {
}
return true;
}
@Override
public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey<?>[] {allowRouterOnDisabledResource, allowAdminVmOnDisabledResource};
}
@Override
public String getConfigComponentName() {
return DeploymentPlanningManager.class.getSimpleName();
}
}

View File

@ -260,15 +260,6 @@ public class FirstFitPlanner extends AdapterBase implements DeploymentClusterPla
}
podsWithCapacity.removeAll(avoid.getPodsToAvoid());
}
if (!isRootAdmin(vmProfile)) {
List<Long> disabledPods = listDisabledPods(plan.getDataCenterId());
if (!disabledPods.isEmpty()) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Removing from the podId list these pods that are disabled: " + disabledPods);
}
podsWithCapacity.removeAll(disabledPods);
}
}
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("No pods found having a host with enough capacity, returning.");
@ -402,21 +393,6 @@ public class FirstFitPlanner extends AdapterBase implements DeploymentClusterPla
prioritizedClusterIds.removeAll(avoid.getClustersToAvoid());
}
if (!isRootAdmin(vmProfile)) {
List<Long> disabledClusters = new ArrayList<Long>();
if (isZone) {
disabledClusters = listDisabledClusters(plan.getDataCenterId(), null);
} else {
disabledClusters = listDisabledClusters(plan.getDataCenterId(), id);
}
if (!disabledClusters.isEmpty()) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Removing from the clusterId list these clusters that are disabled/clusters under disabled pods: " + disabledClusters);
}
prioritizedClusterIds.removeAll(disabledClusters);
}
}
removeClustersCrossingThreshold(prioritizedClusterIds, avoid, vmProfile, plan);
String hostTagOnOffering = offering.getHostTag();
if (hostTagOnOffering != null) {
@ -465,21 +441,6 @@ public class FirstFitPlanner extends AdapterBase implements DeploymentClusterPla
return podIdsByCapacity;
}
private List<Long> listDisabledClusters(long zoneId, Long podId) {
List<Long> disabledClusters = clusterDao.listDisabledClusters(zoneId, podId);
if (podId == null) {
//list all disabled clusters under this zone + clusters under any disabled pod of this zone
List<Long> clustersWithDisabledPods = clusterDao.listClustersWithDisabledPods(zoneId);
disabledClusters.addAll(clustersWithDisabledPods);
}
return disabledClusters;
}
private List<Long> listDisabledPods(long zoneId) {
List<Long> disabledPods = podDao.listDisabledPods(zoneId);
return disabledPods;
}
protected Pair<List<Long>, Map<Long, Double>> listClustersByCapacity(long id, int requiredCpu, long requiredRam, ExcludeList avoid, boolean isZone) {
//look at the aggregate available cpu and ram per cluster
//although an aggregate value may be false indicator that a cluster can host a vm, it will at the least eliminate those clusters which definitely cannot

View File

@ -14,7 +14,7 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.vm;
package com.cloud.deploy;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
@ -28,18 +28,30 @@ import java.util.List;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.dc.DataCenter;
import com.cloud.host.Host;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.user.AccountVO;
import com.cloud.user.dao.AccountDao;
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 org.apache.cloudstack.affinity.dao.AffinityGroupDomainMapDao;
import org.apache.commons.collections.CollectionUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Matchers;
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;
@ -73,15 +85,8 @@ 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.DataCenterDeployment;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentClusterPlanner;
import com.cloud.deploy.DeploymentPlanner;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.deploy.DeploymentPlanner.PlannerResourceUsage;
import com.cloud.deploy.DeploymentPlanningManagerImpl;
import com.cloud.deploy.FirstFitPlanner;
import com.cloud.deploy.PlannerHostReservationVO;
import com.cloud.deploy.dao.PlannerHostReservationDao;
import com.cloud.exception.AffinityConflictException;
import com.cloud.exception.InsufficientServerCapacityException;
@ -90,6 +95,7 @@ import com.cloud.host.dao.HostDao;
import com.cloud.host.dao.HostTagsDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.resource.ResourceManager;
import com.cloud.org.Grouping.AllocationState;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDetailsDao;
import com.cloud.storage.Storage.ProvisioningType;
@ -110,7 +116,8 @@ import com.cloud.host.dao.HostDetailsDao;
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class DeploymentPlanningManagerImplTest {
@Inject
@Spy
@InjectMocks
DeploymentPlanningManagerImpl _dpm;
@Inject
@ -119,6 +126,12 @@ public class DeploymentPlanningManagerImplTest {
@Inject
VirtualMachineProfileImpl vmProfile;
@Inject
private AccountDao accountDao;
@Inject
private VMInstanceDao vmInstanceDao;
@Inject
AffinityGroupVMMapDao _affinityGroupVMMapDao;
@ -146,11 +159,15 @@ public class DeploymentPlanningManagerImplTest {
@Inject
VMTemplateDao templateDao;
@Inject
HostPodDao hostPodDao;
@Mock
Host host;
private static long dataCenterId = 1L;
private static long hostId = 1l;
private static final long ADMIN_ACCOUNT_ROLE_ID = 1l;
@BeforeClass
public static void setUp() throws ConfigurationException {
@ -189,6 +206,7 @@ public class DeploymentPlanningManagerImplTest {
_dpm.setPlanners(planners);
Mockito.when(host.getId()).thenReturn(hostId);
Mockito.doNothing().when(_dpm).avoidDisabledResources(vmProfile, dc, avoids);
}
@Test
@ -259,6 +277,184 @@ public class DeploymentPlanningManagerImplTest {
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));
}
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)
@ -461,10 +657,15 @@ public class DeploymentPlanningManagerImplTest {
}
@Bean
public HostGpuGroupsDao hostGpuGroupsDap() {
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);