Skip to content

Commit 7742df2

Browse files
committed
Fix listing service offerings with different host tags
1 parent 59b6c32 commit 7742df2

File tree

4 files changed

+85
-1
lines changed

4 files changed

+85
-1
lines changed

engine/schema/src/main/java/com/cloud/host/dao/HostTagsDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,6 @@ public interface HostTagsDao extends GenericDao<HostTagVO, Long> {
4545
HostTagResponse newHostTagResponse(HostTagVO hostTag);
4646

4747
List<HostTagVO> searchByIds(Long... hostTagIds);
48+
49+
List<String> listByClusterId(Long clusterId);
4850
}

engine/schema/src/main/java/com/cloud/host/dao/HostTagsDaoImpl.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.apache.cloudstack.framework.config.Configurable;
2525
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
2626
import org.apache.commons.lang3.StringUtils;
27+
import org.springframework.beans.factory.annotation.Autowired;
2728
import org.springframework.stereotype.Component;
2829

2930
import com.cloud.host.HostTagVO;
@@ -43,9 +44,12 @@ public class HostTagsDaoImpl extends GenericDaoBase<HostTagVO, Long> implements
4344
private final SearchBuilder<HostTagVO> stSearch;
4445
private final SearchBuilder<HostTagVO> tagIdsearch;
4546
private final SearchBuilder<HostTagVO> ImplicitTagsSearch;
47+
private final GenericSearchBuilder<HostTagVO, String> tagSearch;
4648

4749
@Inject
4850
private ConfigurationDao _configDao;
51+
@Autowired
52+
private HostDao hostDao;
4953

5054
public HostTagsDaoImpl() {
5155
HostSearch = createSearchBuilder();
@@ -72,6 +76,11 @@ public HostTagsDaoImpl() {
7276
ImplicitTagsSearch.and("hostId", ImplicitTagsSearch.entity().getHostId(), SearchCriteria.Op.EQ);
7377
ImplicitTagsSearch.and("isImplicit", ImplicitTagsSearch.entity().getIsImplicit(), SearchCriteria.Op.EQ);
7478
ImplicitTagsSearch.done();
79+
80+
tagSearch = createSearchBuilder(String.class);
81+
tagSearch.selectFields(tagSearch.entity().getTag());
82+
tagSearch.and("idIN", tagSearch.entity().getId(), SearchCriteria.Op.IN);
83+
tagSearch.done();
7584
}
7685

7786
@Override
@@ -235,4 +244,12 @@ public List<HostTagVO> searchByIds(Long... tagIds) {
235244

236245
return tagList;
237246
}
247+
248+
@Override
249+
public List<String> listByClusterId(Long clusterId) {
250+
List<Long> hostIds = hostDao.listIdsByClusterId(clusterId);
251+
SearchCriteria<String> sc = tagSearch.create();
252+
sc.setParameters("idIN", hostIds.toArray());
253+
return customSearch(sc, null);
254+
}
238255
}

server/src/main/java/com/cloud/api/query/QueryManagerImpl.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4330,6 +4330,7 @@ private Pair<List<Long>, Integer> searchForServiceOfferingIdsAndCount(ListServic
43304330
List<String> hostTags = new ArrayList<>();
43314331
if (currentVmOffering != null) {
43324332
hostTags.addAll(com.cloud.utils.StringUtils.csvTagsToList(currentVmOffering.getHostTag()));
4333+
addVmCurrentClusterHostTags(vmInstance, hostTags);
43334334
}
43344335

43354336
if (!hostTags.isEmpty()) {
@@ -4341,7 +4342,7 @@ private Pair<List<Long>, Integer> searchForServiceOfferingIdsAndCount(ListServic
43414342
flag = false;
43424343
serviceOfferingSearch.op("hostTag" + tag, serviceOfferingSearch.entity().getHostTag(), Op.FIND_IN_SET);
43434344
} else {
4344-
serviceOfferingSearch.and("hostTag" + tag, serviceOfferingSearch.entity().getHostTag(), Op.FIND_IN_SET);
4345+
serviceOfferingSearch.or("hostTag" + tag, serviceOfferingSearch.entity().getHostTag(), Op.FIND_IN_SET);
43454346
}
43464347
}
43474348
serviceOfferingSearch.cp().cp();
@@ -4486,6 +4487,30 @@ private Pair<List<Long>, Integer> searchForServiceOfferingIdsAndCount(ListServic
44864487
return new Pair<>(offeringIds, count);
44874488
}
44884489

4490+
protected void addVmCurrentClusterHostTags(VMInstanceVO vmInstance, List<String> hostTags) {
4491+
if (vmInstance == null) {
4492+
return;
4493+
}
4494+
Long hostId = vmInstance.getHostId() == null ? vmInstance.getLastHostId() : vmInstance.getHostId();
4495+
if (hostId == null) {
4496+
return;
4497+
}
4498+
HostVO host = hostDao.findById(hostId);
4499+
if (host == null) {
4500+
logger.warn("Unable to find host with id " + hostId);
4501+
return;
4502+
}
4503+
List<String> clusterTags = _hostTagDao.listByClusterId(host.getClusterId());
4504+
if (CollectionUtils.isEmpty(clusterTags)) {
4505+
logger.warn("No host tags defined for hosts in the cluster " + host.getClusterId());
4506+
return;
4507+
}
4508+
Set<String> existingTagsSet = new HashSet<>(hostTags);
4509+
clusterTags.stream()
4510+
.filter(tag -> !existingTagsSet.contains(tag))
4511+
.forEach(hostTags::add);
4512+
}
4513+
44894514
@Override
44904515
public ListResponse<ZoneResponse> listDataCenters(ListZonesCmd cmd) {
44914516
Pair<List<DataCenterJoinVO>, Integer> result = listDataCentersInternal(cmd);

server/src/test/java/com/cloud/api/query/QueryManagerImplTest.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package com.cloud.api.query;
1919

2020
import static org.junit.Assert.assertEquals;
21+
import static org.junit.Assert.assertTrue;
2122
import static org.mockito.ArgumentMatchers.any;
2223
import static org.mockito.Mockito.mock;
2324
import static org.mockito.Mockito.verify;
@@ -33,6 +34,7 @@
3334
import java.util.UUID;
3435
import java.util.stream.Collectors;
3536

37+
import com.cloud.host.dao.HostTagsDao;
3638
import org.apache.cloudstack.acl.SecurityChecker;
3739
import org.apache.cloudstack.api.ApiCommandResourceType;
3840
import org.apache.cloudstack.api.ResponseObject;
@@ -156,6 +158,9 @@ public class QueryManagerImplTest {
156158
@Mock
157159
HostDao hostDao;
158160

161+
@Mock
162+
HostTagsDao hostTagsDao;
163+
159164
@Mock
160165
ClusterDao clusterDao;
161166

@@ -622,4 +627,39 @@ public void updateHostsExtensions_withHostResponses_setsExtension() {
622627
verify(host1).setExtensionId("a");
623628
verify(host2).setExtensionId("b");
624629
}
630+
631+
@Test
632+
public void testAddVmCurrentClusterHostTags() {
633+
String tag1 = "tag1";
634+
String tag2 = "tag2";
635+
VMInstanceVO vmInstance = mock(VMInstanceVO.class);
636+
HostVO host = mock(HostVO.class);
637+
when(vmInstance.getHostId()).thenReturn(null);
638+
when(vmInstance.getLastHostId()).thenReturn(1L);
639+
when(hostDao.findById(1L)).thenReturn(host);
640+
when(host.getClusterId()).thenReturn(1L);
641+
when(hostTagsDao.listByClusterId(1L)).thenReturn(Arrays.asList(tag1, tag2));
642+
643+
List<String> hostTags = new ArrayList<>(Collections.singleton(tag1));
644+
queryManagerImplSpy.addVmCurrentClusterHostTags(vmInstance, hostTags);
645+
assertEquals(2, hostTags.size());
646+
assertTrue(hostTags.contains(tag2));
647+
}
648+
649+
@Test
650+
public void testAddVmCurrentClusterHostTagsEmptyHostTagsInCluster() {
651+
String tag1 = "tag1";
652+
VMInstanceVO vmInstance = mock(VMInstanceVO.class);
653+
HostVO host = mock(HostVO.class);
654+
when(vmInstance.getHostId()).thenReturn(null);
655+
when(vmInstance.getLastHostId()).thenReturn(1L);
656+
when(hostDao.findById(1L)).thenReturn(host);
657+
when(host.getClusterId()).thenReturn(1L);
658+
when(hostTagsDao.listByClusterId(1L)).thenReturn(null);
659+
660+
List<String> hostTags = new ArrayList<>(Collections.singleton(tag1));
661+
queryManagerImplSpy.addVmCurrentClusterHostTags(vmInstance, hostTags);
662+
assertEquals(1, hostTags.size());
663+
assertTrue(hostTags.contains(tag1));
664+
}
625665
}

0 commit comments

Comments
 (0)