Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ public interface HostDao extends GenericDao<HostVO, Long>, StateDao<Status, Stat
List<String> listOrderedHostsHypervisorVersionsInDatacenter(long datacenterId, HypervisorType hypervisorType);

List<HostVO> findHostsWithTagRuleThatMatchComputeOferringTags(String computeOfferingTags);
List<HostVO> findHostsWithTagRuleThatMatchComputeOferringTags(String computeOfferingTags, Long clusterId, Long podId, Long dcId);

List<Long> findClustersThatMatchHostTagRule(String computeOfferingTags);

Expand Down
15 changes: 15 additions & 0 deletions engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -1456,6 +1456,7 @@ private List<Long> findHostIdsByHostTags(String hostTags){
}
}

@Override
public List<HostVO> findHostsWithTagRuleThatMatchComputeOferringTags(String computeOfferingTags) {
List<HostTagVO> hostTagVOList = _hostTagsDao.findHostRuleTags();
List<HostVO> result = new ArrayList<>();
Expand All @@ -1468,6 +1469,20 @@ public List<HostVO> findHostsWithTagRuleThatMatchComputeOferringTags(String comp
return result;
}

@Override
public List<HostVO> findHostsWithTagRuleThatMatchComputeOferringTags(String computeOfferingTags, Long clusterId, Long podId, Long dcId) {
List<HostVO> hosts = findHostsWithTagRuleThatMatchComputeOferringTags(computeOfferingTags);
if (dcId == null && podId == null && clusterId == null) {
return hosts;
}

return hosts.stream()
.filter(host -> host != null && (dcId == null || host.getDataCenterId() == dcId))
.filter(host -> podId == null || Objects.equals(host.getPodId(), podId))
.filter(host -> clusterId == null || Objects.equals(host.getClusterId(), clusterId))
.collect(Collectors.toList());
}

public List<Long> findClustersThatMatchHostTagRule(String computeOfferingTags) {
Set<Long> result = new HashSet<>();
List<HostVO> hosts = findHostsWithTagRuleThatMatchComputeOferringTags(computeOfferingTags);
Expand Down
109 changes: 109 additions & 0 deletions engine/schema/src/test/java/com/cloud/host/dao/HostDaoImplTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -230,6 +231,114 @@ public void testListDistinctHypervisorArchTypes_WithoutZone() {
assertEquals(CPU.CPUArch.amd64, result.get(0).second());
}

@Test
public void testFindHostsWithTagRuleThatMatchComputeOferringTagsScopedNoScopeReturnsAllMatches() {
String offeringTag = "ssd";
HostVO host1 = mock(HostVO.class);
HostVO host2 = mock(HostVO.class);
List<HostVO> unscopedMatches = List.of(host1, host2);
doReturn(unscopedMatches).when(hostDao).findHostsWithTagRuleThatMatchComputeOferringTags(offeringTag);

List<HostVO> result = hostDao.findHostsWithTagRuleThatMatchComputeOferringTags(offeringTag, null, null, null);

assertEquals(unscopedMatches, result);
}

@Test
public void testFindHostsWithTagRuleThatMatchComputeOferringTagsScopedFiltersByDataCenter() {
String offeringTag = "ssd";
long dcId = 1L;
HostVO hostInZone = mock(HostVO.class);
when(hostInZone.getDataCenterId()).thenReturn(dcId);
HostVO hostInOtherZone = mock(HostVO.class);
when(hostInOtherZone.getDataCenterId()).thenReturn(2L);
doReturn(List.of(hostInZone, hostInOtherZone)).when(hostDao).findHostsWithTagRuleThatMatchComputeOferringTags(offeringTag);

List<HostVO> result = hostDao.findHostsWithTagRuleThatMatchComputeOferringTags(offeringTag, null, null, dcId);

assertEquals(1, result.size());
Assert.assertSame(hostInZone, result.get(0));
}

@Test
public void testFindHostsWithTagRuleThatMatchComputeOferringTagsScopedFiltersByPodAndCluster() {
String offeringTag = "ssd";
long dcId = 1L;
Long podId = 2L;
Long clusterId = 3L;

HostVO matchingHost = mock(HostVO.class);
when(matchingHost.getDataCenterId()).thenReturn(dcId);
when(matchingHost.getPodId()).thenReturn(podId);
when(matchingHost.getClusterId()).thenReturn(clusterId);

HostVO wrongPodHost = mock(HostVO.class);
when(wrongPodHost.getDataCenterId()).thenReturn(dcId);
when(wrongPodHost.getPodId()).thenReturn(99L);

HostVO wrongClusterHost = mock(HostVO.class);
when(wrongClusterHost.getDataCenterId()).thenReturn(dcId);
when(wrongClusterHost.getPodId()).thenReturn(podId);
when(wrongClusterHost.getClusterId()).thenReturn(99L);

doReturn(List.of(matchingHost, wrongPodHost, wrongClusterHost)).when(hostDao)
.findHostsWithTagRuleThatMatchComputeOferringTags(offeringTag);

List<HostVO> result = hostDao.findHostsWithTagRuleThatMatchComputeOferringTags(offeringTag, clusterId, podId, dcId);

assertEquals(1, result.size());
Assert.assertSame(matchingHost, result.get(0));
}

@Test
public void testFindHostsWithTagRuleThatMatchComputeOferringTagsScopedExcludesHostWithNullPod() {
String offeringTag = "ssd";
long dcId = 1L;
Long podId = 2L;
Long clusterId = 3L;

HostVO hostWithNoPod = mock(HostVO.class);
when(hostWithNoPod.getDataCenterId()).thenReturn(dcId);
when(hostWithNoPod.getPodId()).thenReturn(null);

doReturn(List.of(hostWithNoPod)).when(hostDao)
.findHostsWithTagRuleThatMatchComputeOferringTags(offeringTag);

List<HostVO> result = hostDao.findHostsWithTagRuleThatMatchComputeOferringTags(offeringTag, clusterId, podId, dcId);

Assert.assertTrue(result.isEmpty());
}

@Test
public void testFindHostsWithTagRuleThatMatchComputeOferringTagsScopedExcludesHostWithNullCluster() {
String offeringTag = "ssd";
long dcId = 1L;
Long podId = 2L;
Long clusterId = 3L;

HostVO hostWithNoCluster = mock(HostVO.class);
when(hostWithNoCluster.getDataCenterId()).thenReturn(dcId);
when(hostWithNoCluster.getPodId()).thenReturn(podId);
when(hostWithNoCluster.getClusterId()).thenReturn(null);

doReturn(List.of(hostWithNoCluster)).when(hostDao)
.findHostsWithTagRuleThatMatchComputeOferringTags(offeringTag);

List<HostVO> result = hostDao.findHostsWithTagRuleThatMatchComputeOferringTags(offeringTag, clusterId, podId, dcId);

Assert.assertTrue(result.isEmpty());
}

@Test
public void testFindHostsWithTagRuleThatMatchComputeOferringTagsScopedNoMatchesReturnsEmpty() {
String offeringTag = "ssd";
doReturn(new ArrayList<>()).when(hostDao).findHostsWithTagRuleThatMatchComputeOferringTags(offeringTag);

List<HostVO> result = hostDao.findHostsWithTagRuleThatMatchComputeOferringTags(offeringTag, 3L, 2L, 1L);

Assert.assertTrue(result.isEmpty());
}

@Test
public void testListDistinctArchTypes() {
Long clusterId = 1L;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ private List<Host> findSuitableHosts(VirtualMachineProfile vmProfile, Deployment
hostsCopy = _hostDao.listAllHostsThatHaveNoRuleTag(type, clusterId, podId, dcId);
}
}
hostsCopy = ListUtils.union(hostsCopy, _hostDao.findHostsWithTagRuleThatMatchComputeOferringTags(offeringHostTag));
hostsCopy = ListUtils.union(hostsCopy, _hostDao.findHostsWithTagRuleThatMatchComputeOferringTags(offeringHostTag, clusterId, podId, dcId));

if (hostsCopy.isEmpty()) {
logger.info("No suitable host found for VM [{}] in {}.", vmProfile, hostTag);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,29 @@
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;

import com.cloud.deploy.DeploymentPlan;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.capacity.CapacityManager;
import com.cloud.offering.ServiceOffering;
import com.cloud.storage.VMTemplateVO;
import com.cloud.utils.Pair;
import com.cloud.vm.VirtualMachineProfile;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class RandomAllocatorTest {

@Mock
HostDao hostDao;
@Mock
CapacityManager capacityManager;
@InjectMocks
RandomAllocator randomAllocator;

Expand All @@ -46,23 +60,23 @@ public void testListHostsByTags() {
Long id = 1L;
String templateTag = "tag1";
String offeringTag = "tag2";
HostVO host1 = Mockito.mock(HostVO.class);
HostVO host2 = Mockito.mock(HostVO.class);
Mockito.when(hostDao.listByHostTag(type, id, id, id, offeringTag)).thenReturn(List.of(host1, host2));
HostVO host1 = mock(HostVO.class);
HostVO host2 = mock(HostVO.class);
when(hostDao.listByHostTag(type, id, id, id, offeringTag)).thenReturn(List.of(host1, host2));

// No template tagged host
Mockito.when(hostDao.listByHostTag(type, id, id, id, templateTag)).thenReturn(new ArrayList<>());
when(hostDao.listByHostTag(type, id, id, id, templateTag)).thenReturn(new ArrayList<>());
List<HostVO> result = randomAllocator.listHostsByTags(type, id, id, id, offeringTag, templateTag);
Assert.assertTrue(CollectionUtils.isEmpty(result));

// Different template tagged host
HostVO host3 = Mockito.mock(HostVO.class);
Mockito.when(hostDao.listByHostTag(type, id, id, id, templateTag)).thenReturn(List.of(host3));
HostVO host3 = mock(HostVO.class);
when(hostDao.listByHostTag(type, id, id, id, templateTag)).thenReturn(List.of(host3));
result = randomAllocator.listHostsByTags(type, id, id, id, offeringTag, templateTag);
Assert.assertTrue(CollectionUtils.isEmpty(result));

// Matching template tagged host
Mockito.when(hostDao.listByHostTag(type, id, id, id, templateTag)).thenReturn(List.of(host1));
when(hostDao.listByHostTag(type, id, id, id, templateTag)).thenReturn(List.of(host1));
result = randomAllocator.listHostsByTags(type, id, id, id, offeringTag, templateTag);
Assert.assertFalse(CollectionUtils.isEmpty(result));
Assert.assertEquals(1, result.size());
Expand All @@ -77,4 +91,37 @@ public void testListHostsByTags() {
Assert.assertFalse(CollectionUtils.isEmpty(result));
Assert.assertEquals(1, result.size());
}

@Test
public void testAllocateToUsesScopedRuleTagLookup() {
Host.Type type = Host.Type.Routing;
long dcId = 1L;
Long podId = 2L;
Long clusterId = 3L;
String offeringTag = "compute";

DeploymentPlan plan = mock(DeploymentPlan.class);
when(plan.getDataCenterId()).thenReturn(dcId);
when(plan.getPodId()).thenReturn(podId);
when(plan.getClusterId()).thenReturn(clusterId);

VirtualMachineProfile vmProfile = mock(VirtualMachineProfile.class);
ServiceOffering offering = mock(ServiceOffering.class);
VMTemplateVO template = mock(VMTemplateVO.class);
when(vmProfile.getServiceOffering()).thenReturn(offering);
when(vmProfile.getTemplate()).thenReturn(template);
when(offering.getHostTag()).thenReturn(offeringTag);

HostVO host = mock(HostVO.class);
List<Host> hosts = List.of(host);
when(hostDao.listByHostTag(type, clusterId, podId, dcId, offeringTag)).thenReturn(List.of(host));
when(hostDao.findHostsWithTagRuleThatMatchComputeOferringTags(offeringTag, clusterId, podId, dcId)).thenReturn(new ArrayList<>());
when(capacityManager.checkIfHostHasCpuCapabilityAndCapacity(host, offering, true)).thenReturn(new Pair<>(true, true));

List<Host> result = randomAllocator.allocateTo(vmProfile, plan, type, new ExcludeList(), hosts, 1, true);

Assert.assertEquals(1, result.size());
verify(hostDao).findHostsWithTagRuleThatMatchComputeOferringTags(offeringTag, clusterId, podId, dcId);
verify(hostDao, never()).findHostsWithTagRuleThatMatchComputeOferringTags(offeringTag);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan pla
clusterHosts.retainAll(hostsMatchingUefiTag);
}

clusterHosts.addAll(_hostDao.findHostsWithTagRuleThatMatchComputeOferringTags(hostTagOnOffering));
clusterHosts.addAll(_hostDao.findHostsWithTagRuleThatMatchComputeOferringTags(hostTagOnOffering, clusterId, podId, dcId));


if (clusterHosts.isEmpty()) {
Expand Down Expand Up @@ -274,7 +274,7 @@ public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan pla
}
}

hostsCopy.addAll(_hostDao.findHostsWithTagRuleThatMatchComputeOferringTags(hostTagOnOffering));
hostsCopy.addAll(_hostDao.findHostsWithTagRuleThatMatchComputeOferringTags(hostTagOnOffering, clusterId, podId, dcId));

if (!hostsCopy.isEmpty()) {
suitableHosts = allocateTo(plan, offering, template, avoid, hostsCopy, returnUpTo, considerReservedCapacity, account);
Expand Down
Loading
Loading