Skip to content

Commit e9f59e2

Browse files
authored
server: Adding showunique parameter to list templates and isos (#4140)
Adds a new parameter showunique to listTemplate and listIsos to return only unique templates / isos across all zones Fixes #4041
1 parent 88d51ce commit e9f59e2

6 files changed

Lines changed: 70 additions & 21 deletions

File tree

api/src/main/java/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ public class ApiConstants {
300300
public static final String SESSIONKEY = "sessionkey";
301301
public static final String SHOW_CAPACITIES = "showcapacities";
302302
public static final String SHOW_REMOVED = "showremoved";
303+
public static final String SHOW_UNIQUE = "showunique";
303304
public static final String SIGNATURE = "signature";
304305
public static final String SIGNATURE_VERSION = "signatureversion";
305306
public static final String SIZE = "size";

api/src/main/java/org/apache/cloudstack/api/command/user/iso/ListIsosCmd.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ public class ListIsosCmd extends BaseListTaggedResourcesCmd {
7878
@Parameter(name=ApiConstants.SHOW_REMOVED, type=CommandType.BOOLEAN, description="show removed ISOs as well")
7979
private Boolean showRemoved;
8080

81+
@Parameter(name = ApiConstants.SHOW_UNIQUE, type = CommandType.BOOLEAN, description = "If set to true, list only unique isos across zones", since = "4.13.2")
82+
private Boolean showUnique;
83+
8184
/////////////////////////////////////////////////////
8285
/////////////////// Accessors ///////////////////////
8386
/////////////////////////////////////////////////////
@@ -115,7 +118,11 @@ public Long getZoneId() {
115118
}
116119

117120
public Boolean getShowRemoved() {
118-
return (showRemoved != null ? showRemoved : false);
121+
return showRemoved != null && showRemoved;
122+
}
123+
124+
public Boolean getShowUnique() {
125+
return showUnique != null && showUnique;
119126
}
120127

121128
public boolean listInReadyState() {

api/src/main/java/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ public class ListTemplatesCmd extends BaseListTaggedResourcesCmd {
7575
@Parameter(name = ApiConstants.SHOW_REMOVED, type = CommandType.BOOLEAN, description = "show removed templates as well")
7676
private Boolean showRemoved;
7777

78+
@Parameter(name = ApiConstants.SHOW_UNIQUE, type = CommandType.BOOLEAN, description = "If set to true, list only unique templates across zones", since = "4.13.2")
79+
private Boolean showUnique;
80+
7881
@Parameter(name = ApiConstants.PARENT_TEMPLATE_ID, type = CommandType.UUID, entityType = TemplateResponse.class, description = "list datadisk templates by parent template id", since = "4.4")
7982
private Long parentTemplateId;
8083

@@ -103,7 +106,11 @@ public Long getZoneId() {
103106
}
104107

105108
public Boolean getShowRemoved() {
106-
return (showRemoved != null ? showRemoved : false);
109+
return showRemoved != null && showRemoved;
110+
}
111+
112+
public Boolean getShowUnique() {
113+
return showUnique != null && showUnique;
107114
}
108115

109116
public Long getParentTemplateId() {

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

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3154,12 +3154,12 @@ private Pair<List<TemplateJoinVO>, Integer> searchForTemplatesInternal(ListTempl
31543154
HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor());
31553155

31563156
return searchForTemplatesInternal(id, cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), hypervisorType,
3157-
showDomr, cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags, showRemovedTmpl, cmd.getIds(), parentTemplateId);
3157+
showDomr, cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags, showRemovedTmpl, cmd.getIds(), parentTemplateId, cmd.getShowUnique());
31583158
}
31593159

31603160
private Pair<List<TemplateJoinVO>, Integer> searchForTemplatesInternal(Long templateId, String name, String keyword, TemplateFilter templateFilter, boolean isIso, Boolean bootable, Long pageSize,
31613161
Long startIndex, Long zoneId, HypervisorType hyperType, boolean showDomr, boolean onlyReady, List<Account> permittedAccounts, Account caller,
3162-
ListProjectResourcesCriteria listProjectResourcesCriteria, Map<String, String> tags, boolean showRemovedTmpl, List<Long> ids, Long parentTemplateId) {
3162+
ListProjectResourcesCriteria listProjectResourcesCriteria, Map<String, String> tags, boolean showRemovedTmpl, List<Long> ids, Long parentTemplateId, Boolean showUnique) {
31633163

31643164
// check if zone is configured, if not, just return empty list
31653165
List<HypervisorType> hypers = null;
@@ -3176,7 +3176,11 @@ private Pair<List<TemplateJoinVO>, Integer> searchForTemplatesInternal(Long temp
31763176
searchFilter.addOrderBy(TemplateJoinVO.class, "tempZonePair", SortKeyAscending.value());
31773177

31783178
SearchBuilder<TemplateJoinVO> sb = _templateJoinDao.createSearchBuilder();
3179-
sb.select(null, Func.DISTINCT, sb.entity().getTempZonePair()); // select distinct (templateId, zoneId) pair
3179+
if (showUnique) {
3180+
sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct templateId
3181+
} else {
3182+
sb.select(null, Func.DISTINCT, sb.entity().getTempZonePair()); // select distinct (templateId, zoneId) pair
3183+
}
31803184
if (ids != null && !ids.isEmpty()) {
31813185
sb.and("idIN", sb.entity().getId(), SearchCriteria.Op.IN);
31823186
}
@@ -3413,23 +3417,16 @@ else if (!template.isPublicTemplate() && caller.getType() != Account.ACCOUNT_TYP
34133417
uniqueTmplPair = _templateJoinDao.searchIncludingRemovedAndCount(sc, searchFilter);
34143418
} else {
34153419
sc.addAnd("templateState", SearchCriteria.Op.IN, new State[] {State.Active, State.UploadAbandoned, State.UploadError, State.NotUploaded, State.UploadInProgress});
3416-
final String[] distinctColumns = {"temp_zone_pair"};
3417-
uniqueTmplPair = _templateJoinDao.searchAndDistinctCount(sc, searchFilter, distinctColumns);
3420+
if (showUnique) {
3421+
final String[] distinctColumns = {"id"};
3422+
uniqueTmplPair = _templateJoinDao.searchAndDistinctCount(sc, searchFilter, distinctColumns);
3423+
} else {
3424+
final String[] distinctColumns = {"temp_zone_pair"};
3425+
uniqueTmplPair = _templateJoinDao.searchAndDistinctCount(sc, searchFilter, distinctColumns);
3426+
}
34183427
}
34193428

3420-
Integer count = uniqueTmplPair.second();
3421-
if (count.intValue() == 0) {
3422-
// empty result
3423-
return uniqueTmplPair;
3424-
}
3425-
List<TemplateJoinVO> uniqueTmpls = uniqueTmplPair.first();
3426-
String[] tzIds = new String[uniqueTmpls.size()];
3427-
int i = 0;
3428-
for (TemplateJoinVO v : uniqueTmpls) {
3429-
tzIds[i++] = v.getTempZonePair();
3430-
}
3431-
List<TemplateJoinVO> vrs = _templateJoinDao.searchByTemplateZonePair(showRemovedTmpl, tzIds);
3432-
return new Pair<List<TemplateJoinVO>, Integer>(vrs, count);
3429+
return findTemplatesByIdOrTempZonePair(uniqueTmplPair, showRemovedTmpl, showUnique);
34333430

34343431
// TODO: revisit the special logic for iso search in
34353432
// VMTemplateDaoImpl.searchForTemplates and understand why we need to
@@ -3438,6 +3435,25 @@ else if (!template.isPublicTemplate() && caller.getType() != Account.ACCOUNT_TYP
34383435

34393436
}
34403437

3438+
// findTemplatesByIdOrTempZonePair returns the templates with the given ids if showUnique is true, or else by the TempZonePair
3439+
private Pair<List<TemplateJoinVO>, Integer> findTemplatesByIdOrTempZonePair(Pair<List<TemplateJoinVO>, Integer> templateDataPair, boolean showRemoved, boolean showUnique) {
3440+
Integer count = templateDataPair.second();
3441+
if (count.intValue() == 0) {
3442+
// empty result
3443+
return templateDataPair;
3444+
}
3445+
List<TemplateJoinVO> templateData = templateDataPair.first();
3446+
List<TemplateJoinVO> templates = null;
3447+
if (showUnique) {
3448+
Long[] templateIds = templateData.stream().map(template -> template.getId()).toArray(Long[]::new);
3449+
templates = _templateJoinDao.findByDistinctIds(templateIds);
3450+
} else {
3451+
String[] templateZonePairs = templateData.stream().map(template -> template.getTempZonePair()).toArray(String[]::new);
3452+
templates = _templateJoinDao.searchByTemplateZonePair(showRemoved, templateZonePairs);
3453+
}
3454+
return new Pair<List<TemplateJoinVO>, Integer>(templates, count);
3455+
}
3456+
34413457
@Override
34423458
public ListResponse<TemplateResponse> listIsos(ListIsosCmd cmd) {
34433459
Pair<List<TemplateJoinVO>, Integer> result = searchForIsosInternal(cmd);
@@ -3480,7 +3496,7 @@ private Pair<List<TemplateJoinVO>, Integer> searchForIsosInternal(ListIsosCmd cm
34803496
HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor());
34813497

34823498
return searchForTemplatesInternal(cmd.getId(), cmd.getIsoName(), cmd.getKeyword(), isoFilter, true, cmd.isBootable(), cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(),
3483-
hypervisorType, true, cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags, showRemovedISO, null, null);
3499+
hypervisorType, true, cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags, showRemovedISO, null, null, cmd.getShowUnique());
34843500
}
34853501

34863502
@Override

server/src/main/java/com/cloud/api/query/dao/TemplateJoinDao.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,5 @@ public interface TemplateJoinDao extends GenericDao<TemplateJoinVO, Long> {
4848

4949
Pair<List<TemplateJoinVO>, Integer> searchIncludingRemovedAndCount(final SearchCriteria<TemplateJoinVO> sc, final Filter filter);
5050

51+
List<TemplateJoinVO> findByDistinctIds(Long... ids);
5152
}

server/src/main/java/com/cloud/api/query/dao/TemplateJoinDaoImpl.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation<Templa
7373

7474
private final SearchBuilder<TemplateJoinVO> tmpltIdSearch;
7575

76+
private final SearchBuilder<TemplateJoinVO> tmpltIdsSearch;
77+
7678
private final SearchBuilder<TemplateJoinVO> tmpltZoneSearch;
7779

7880
private final SearchBuilder<TemplateJoinVO> activeTmpltSearch;
@@ -88,6 +90,11 @@ protected TemplateJoinDaoImpl() {
8890
tmpltIdSearch.and("id", tmpltIdSearch.entity().getId(), SearchCriteria.Op.EQ);
8991
tmpltIdSearch.done();
9092

93+
tmpltIdsSearch = createSearchBuilder();
94+
tmpltIdsSearch.and("idsIN", tmpltIdsSearch.entity().getId(), SearchCriteria.Op.IN);
95+
tmpltIdsSearch.groupBy(tmpltIdsSearch.entity().getId());
96+
tmpltIdsSearch.done();
97+
9198
tmpltZoneSearch = createSearchBuilder();
9299
tmpltZoneSearch.and("id", tmpltZoneSearch.entity().getId(), SearchCriteria.Op.EQ);
93100
tmpltZoneSearch.and("dataCenterId", tmpltZoneSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
@@ -481,4 +488,14 @@ public Pair<List<TemplateJoinVO>, Integer> searchIncludingRemovedAndCount(final
481488
return new Pair<List<TemplateJoinVO>, Integer>(objects, count);
482489
}
483490

491+
@Override
492+
public List<TemplateJoinVO> findByDistinctIds(Long... ids) {
493+
if (ids == null || ids.length == 0) {
494+
return new ArrayList<TemplateJoinVO>();
495+
}
496+
SearchCriteria<TemplateJoinVO> sc = tmpltIdsSearch.create();
497+
sc.setParameters("idsIN", ids);
498+
return searchIncludingRemoved(sc, null, null, false);
499+
}
500+
484501
}

0 commit comments

Comments
 (0)