Skip to content

Commit c21fdb0

Browse files
committed
Filter disk / service offerings by domain at DB level
1 parent 6446797 commit c21fdb0

6 files changed

Lines changed: 127 additions & 83 deletions

File tree

engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDetailsDao.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,6 @@ public interface ServiceOfferingDetailsDao extends GenericDao<ServiceOfferingDet
2727
List<Long> findDomainIds(final long resourceId);
2828
List<Long> findZoneIds(final long resourceId);
2929
String getDetail(Long diskOfferingId, String key);
30-
}
30+
List<Long> findOfferingIdsByDomainIds(List<Long> domainIds);
31+
}
32+

engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDetailsDaoImpl.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,16 @@
1919

2020
import java.util.ArrayList;
2121
import java.util.List;
22+
import java.util.stream.Collectors;
2223

2324
import org.apache.cloudstack.api.ApiConstants;
2425
import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase;
2526
import org.springframework.stereotype.Component;
2627

2728
import com.cloud.service.ServiceOfferingDetailsVO;
29+
import com.cloud.utils.db.GenericSearchBuilder;
30+
import com.cloud.utils.db.SearchCriteria;
31+
import com.cloud.utils.db.SearchCriteria.Op;
2832

2933
@Component
3034
public class ServiceOfferingDetailsDaoImpl extends ResourceDetailsDaoBase<ServiceOfferingDetailsVO> implements ServiceOfferingDetailsDao {
@@ -67,4 +71,23 @@ public String getDetail(Long serviceOfferingId, String key) {
6771
}
6872
return detailValue;
6973
}
74+
75+
@Override
76+
public List<Long> findOfferingIdsByDomainIds(List<Long> domainIds) {
77+
Object[] dIds = domainIds.stream().map(s -> String.valueOf(s)).collect(Collectors.toList()).toArray();
78+
79+
GenericSearchBuilder<ServiceOfferingDetailsVO, Long> sb = createSearchBuilder(Long.class);
80+
sb.selectFields(sb.entity().getResourceId());
81+
sb.and("name", sb.entity().getName(), Op.EQ);
82+
sb.and().op("value", sb.entity().getValue(), Op.IN);
83+
sb.or("valueNull", sb.entity().getValue(), Op.NULL);
84+
sb.cp();
85+
sb.done();
86+
87+
SearchCriteria<Long> sc = sb.create();
88+
sc.setParameters("name", "domainid");
89+
sc.setParameters("value", dIds);
90+
91+
return customSearch(sc, null);
92+
}
7093
}

engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/dao/DiskOfferingDetailsDao.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,6 @@ public interface DiskOfferingDetailsDao extends GenericDao<DiskOfferingDetailVO,
2727
List<Long> findDomainIds(final long resourceId);
2828
List<Long> findZoneIds(final long resourceId);
2929
String getDetail(Long diskOfferingId, String key);
30-
}
30+
List<Long> findOfferingIdsByDomainIds(List<Long> domainIds);
31+
}
32+

engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/dao/DiskOfferingDetailsDaoImpl.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@
1919

2020
import java.util.ArrayList;
2121
import java.util.List;
22+
import java.util.stream.Collectors;
23+
24+
import com.cloud.utils.db.GenericSearchBuilder;
25+
import com.cloud.utils.db.SearchCriteria;
26+
import com.cloud.utils.db.SearchCriteria.Op;
2227

2328
import org.apache.cloudstack.api.ApiConstants;
2429
import org.apache.cloudstack.resourcedetail.DiskOfferingDetailVO;
@@ -66,4 +71,25 @@ public String getDetail(Long diskOfferingId, String key) {
6671
}
6772
return detailValue;
6873
}
69-
}
74+
75+
@Override
76+
public List<Long> findOfferingIdsByDomainIds(List<Long> domainIds) {
77+
Object[] dIds = domainIds.stream().map(s -> String.valueOf(s)).collect(Collectors.toList()).toArray();
78+
79+
GenericSearchBuilder<DiskOfferingDetailVO, Long> sb = createSearchBuilder(Long.class);
80+
sb.selectFields(sb.entity().getResourceId());
81+
sb.and("name", sb.entity().getName(), Op.EQ);
82+
sb.and().op("value", sb.entity().getValue(), Op.IN);
83+
sb.or("valueNull", sb.entity().getValue(), Op.NULL);
84+
sb.cp();
85+
sb.done();
86+
87+
SearchCriteria<Long> sc = sb.create();
88+
sc.setParameters("name", "domainid");
89+
sc.setParameters("value", dIds);
90+
91+
return customSearch(sc, null);
92+
}
93+
94+
}
95+

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

Lines changed: 71 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import java.util.HashMap;
2424
import java.util.HashSet;
2525
import java.util.List;
26-
import java.util.ListIterator;
2726
import java.util.Map;
2827
import java.util.Set;
2928
import java.util.stream.Collectors;
@@ -119,7 +118,6 @@
119118
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
120119
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
121120
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
122-
import org.apache.commons.collections.CollectionUtils;
123121
import org.apache.log4j.Logger;
124122
import org.springframework.stereotype.Component;
125123

@@ -204,6 +202,7 @@
204202
import com.cloud.server.TaggedResourceService;
205203
import com.cloud.service.ServiceOfferingVO;
206204
import com.cloud.service.dao.ServiceOfferingDao;
205+
import com.cloud.service.dao.ServiceOfferingDetailsDao;
207206
import com.cloud.storage.DataStoreRole;
208207
import com.cloud.storage.DiskOfferingVO;
209208
import com.cloud.storage.ScopeType;
@@ -346,14 +345,17 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
346345
private DiskOfferingJoinDao _diskOfferingJoinDao;
347346

348347
@Inject
349-
private DiskOfferingDetailsDao diskOfferingDetailsDao;
348+
private DiskOfferingDetailsDao _diskOfferingDetailsDao;
350349

351350
@Inject
352351
private ServiceOfferingJoinDao _srvOfferingJoinDao;
353352

354353
@Inject
355354
private ServiceOfferingDao _srvOfferingDao;
356355

356+
@Inject
357+
private ServiceOfferingDetailsDao _srvOfferingDetailsDao;
358+
357359
@Inject
358360
private DataCenterJoinDao _dcJoinDao;
359361

@@ -2824,57 +2826,41 @@ private Pair<List<DiskOfferingJoinVO>, Integer> searchForDiskOfferingsInternal(L
28242826
sc.addAnd("zoneId", SearchCriteria.Op.SC, zoneSC);
28252827
}
28262828

2827-
// FIXME: disk offerings should search back up the hierarchy for
2828-
// available disk offerings...
2829-
/*
2830-
* sb.addAnd("domainId", sb.entity().getDomainId(),
2831-
* SearchCriteria.Op.EQ); if (domainId != null) {
2832-
* SearchBuilder<DomainVO> domainSearch =
2833-
* _domainDao.createSearchBuilder(); domainSearch.addAnd("path",
2834-
* domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
2835-
* sb.join("domainSearch", domainSearch, sb.entity().getDomainId(),
2836-
* domainSearch.entity().getId()); }
2837-
*/
2838-
2839-
// FIXME: disk offerings should search back up the hierarchy for
2840-
// available disk offerings...
2841-
/*
2842-
* if (domainId != null) { sc.setParameters("domainId", domainId); //
2843-
* //DomainVO domain = _domainDao.findById((Long)domainId); // // I want
2844-
* to join on user_vm.domain_id = domain.id where domain.path like
2845-
* 'foo%' //sc.setJoinParameters("domainSearch", "path",
2846-
* domain.getPath() + "%"); // }
2847-
*/
2829+
// Filter offerings that are not associated with caller's domain
2830+
// Fetch the offering ids from the details table since theres no smart way to filter them in the join ... yet!
2831+
Account caller = CallContext.current().getCallingAccount();
2832+
if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) {
2833+
Domain callerDomain = _domainDao.findById(caller.getDomainId());
2834+
List<Long> domainIds = _domainDao.getDomainParentIds(callerDomain.getId())
2835+
.stream().collect(Collectors.toList());
2836+
if (isRecursive) {
2837+
List<Long> childrenIds = _domainDao.getDomainChildrenIds(callerDomain.getPath());
2838+
if (childrenIds != null && !childrenIds.isEmpty())
2839+
domainIds.addAll(childrenIds);
2840+
}
28482841

2849-
Pair<List<DiskOfferingJoinVO>, Integer> result = _diskOfferingJoinDao.searchAndCount(sc, searchFilter);
2850-
// Remove offerings that are not associated with caller's domain
2851-
if (account.getType() != Account.ACCOUNT_TYPE_ADMIN && CollectionUtils.isNotEmpty(result.first())) {
2852-
ListIterator<DiskOfferingJoinVO> it = result.first().listIterator();
2853-
while (it.hasNext()) {
2854-
DiskOfferingJoinVO offering = it.next();
2855-
if(!Strings.isNullOrEmpty(offering.getDomainId())) {
2856-
boolean toRemove = true;
2857-
String[] domainIdsArray = offering.getDomainId().split(",");
2858-
for (String domainIdString : domainIdsArray) {
2859-
Long dId = Long.valueOf(domainIdString.trim());
2860-
if (isRecursive) {
2861-
if (_domainDao.isChildDomain(account.getDomainId(), dId)) {
2862-
toRemove = false;
2863-
break;
2864-
}
2865-
} else {
2866-
if (_domainDao.isChildDomain(dId, account.getDomainId())) {
2867-
toRemove = false;
2868-
break;
2869-
}
2870-
}
2871-
}
2872-
if (toRemove) {
2873-
it.remove();
2874-
}
2875-
}
2842+
List<Long> ids = _diskOfferingDetailsDao.findOfferingIdsByDomainIds(domainIds);
2843+
2844+
if (ids == null || ids.isEmpty()) {
2845+
SearchBuilder<DiskOfferingJoinVO> sb = _diskOfferingJoinDao.createSearchBuilder();
2846+
sb.or("domainId", sb.entity().getDomainId(), Op.NULL);
2847+
sb.done();
2848+
2849+
SearchCriteria<DiskOfferingJoinVO> scc = sb.create();
2850+
sc.addAnd("domainId", SearchCriteria.Op.SC, scc);
2851+
} else {
2852+
SearchBuilder<DiskOfferingJoinVO> sb = _diskOfferingJoinDao.createSearchBuilder();
2853+
sb.and("id", sb.entity().getId(), Op.IN);
2854+
sb.or("domainId", sb.entity().getDomainId(), Op.NULL);
2855+
sb.done();
2856+
2857+
SearchCriteria<DiskOfferingJoinVO> scc = sb.create();
2858+
scc.setParameters("id", ids.toArray());
2859+
sc.addAnd("domainId", SearchCriteria.Op.SC, scc);
28762860
}
28772861
}
2862+
2863+
Pair<List<DiskOfferingJoinVO>, Integer> result = _diskOfferingJoinDao.searchAndCount(sc, searchFilter);
28782864
return new Pair<>(result.first(), result.second());
28792865
}
28802866

@@ -3064,38 +3050,44 @@ private Pair<List<ServiceOfferingJoinVO>, Integer> searchForServiceOfferingsInte
30643050
sc.addAnd("cpuspeedconstraints", SearchCriteria.Op.SC, cpuSpeedSearchCriteria);
30653051
}
30663052

3053+
// Filter offerings that are not associated with caller's domain
3054+
// Fetch the offering ids from the details table since theres no smart way to filter them in the join ... yet!
3055+
if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) {
3056+
Domain callerDomain = _domainDao.findById(caller.getDomainId());
3057+
List<Long> domainIds = _domainDao.getDomainParentIds(callerDomain.getId())
3058+
.stream().collect(Collectors.toList());
3059+
if (isRecursive) {
3060+
List<Long> childrenIds = _domainDao.getDomainChildrenIds(callerDomain.getPath());
3061+
if (childrenIds != null && !childrenIds.isEmpty())
3062+
domainIds.addAll(childrenIds);
3063+
}
3064+
3065+
List<Long> ids = _srvOfferingDetailsDao.findOfferingIdsByDomainIds(domainIds);
3066+
3067+
if (ids == null || ids.isEmpty()) {
3068+
SearchBuilder<ServiceOfferingJoinVO> sb = _srvOfferingJoinDao.createSearchBuilder();
3069+
sb.or("domainId", sb.entity().getDomainId(), Op.NULL);
3070+
sb.done();
3071+
3072+
SearchCriteria<ServiceOfferingJoinVO> scc = sb.create();
3073+
sc.addAnd("domainId", SearchCriteria.Op.SC, scc);
3074+
} else {
3075+
SearchBuilder<ServiceOfferingJoinVO> sb = _srvOfferingJoinDao.createSearchBuilder();
3076+
sb.and("id", sb.entity().getId(), Op.IN);
3077+
sb.or("domainId", sb.entity().getDomainId(), Op.NULL);
3078+
sb.done();
3079+
3080+
SearchCriteria<ServiceOfferingJoinVO> scc = sb.create();
3081+
scc.setParameters("id", ids.toArray());
3082+
sc.addAnd("domainId", SearchCriteria.Op.SC, scc);
3083+
}
3084+
}
3085+
30673086
Pair<List<ServiceOfferingJoinVO>, Integer> result = _srvOfferingJoinDao.searchAndCount(sc, searchFilter);
30683087

30693088
//Couldn't figure out a smart way to filter offerings based on tags in sql so doing it in Java.
30703089
List<ServiceOfferingJoinVO> filteredOfferings = filterOfferingsOnCurrentTags(result.first(), currentVmOffering);
3071-
// Remove offerings that are not associated with caller's domain
3072-
if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN && CollectionUtils.isNotEmpty(filteredOfferings)) {
3073-
ListIterator<ServiceOfferingJoinVO> it = filteredOfferings.listIterator();
3074-
while (it.hasNext()) {
3075-
ServiceOfferingJoinVO offering = it.next();
3076-
if(!Strings.isNullOrEmpty(offering.getDomainId())) {
3077-
boolean toRemove = true;
3078-
String[] domainIdsArray = offering.getDomainId().split(",");
3079-
for (String domainIdString : domainIdsArray) {
3080-
Long dId = Long.valueOf(domainIdString.trim());
3081-
if (isRecursive) {
3082-
if (_domainDao.isChildDomain(caller.getDomainId(), dId)) {
3083-
toRemove = false;
3084-
break;
3085-
}
3086-
} else {
3087-
if (_domainDao.isChildDomain(dId, caller.getDomainId())) {
3088-
toRemove = false;
3089-
break;
3090-
}
3091-
}
3092-
}
3093-
if (toRemove) {
3094-
it.remove();
3095-
}
3096-
}
3097-
}
3098-
}
3090+
30993091
return new Pair<>(filteredOfferings, result.second());
31003092
}
31013093

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,5 +144,4 @@ public ServiceOfferingJoinVO newServiceOfferingView(ServiceOffering offering) {
144144
assert offerings != null && offerings.size() == 1 : "No service offering found for offering id " + offering.getId();
145145
return offerings.get(0);
146146
}
147-
148147
}

0 commit comments

Comments
 (0)