From c21fdb0878cc5e5a7e88b4b321525b486c31375d Mon Sep 17 00:00:00 2001 From: davidjumani Date: Wed, 18 Aug 2021 14:59:09 +0530 Subject: [PATCH 1/5] Filter disk / service offerings by domain at DB level --- .../dao/ServiceOfferingDetailsDao.java | 4 +- .../dao/ServiceOfferingDetailsDaoImpl.java | 23 +++ .../dao/DiskOfferingDetailsDao.java | 4 +- .../dao/DiskOfferingDetailsDaoImpl.java | 28 +++- .../com/cloud/api/query/QueryManagerImpl.java | 150 +++++++++--------- .../query/dao/ServiceOfferingJoinDaoImpl.java | 1 - 6 files changed, 127 insertions(+), 83 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDetailsDao.java b/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDetailsDao.java index 10ba8d574a17..1645f2dc4484 100644 --- a/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDetailsDao.java +++ b/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDetailsDao.java @@ -27,4 +27,6 @@ public interface ServiceOfferingDetailsDao extends GenericDao findDomainIds(final long resourceId); List findZoneIds(final long resourceId); String getDetail(Long diskOfferingId, String key); -} \ No newline at end of file + List findOfferingIdsByDomainIds(List domainIds); +} + diff --git a/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDetailsDaoImpl.java b/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDetailsDaoImpl.java index 0080174874d9..9d553b4e8f9b 100644 --- a/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDetailsDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDetailsDaoImpl.java @@ -19,12 +19,16 @@ import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase; import org.springframework.stereotype.Component; import com.cloud.service.ServiceOfferingDetailsVO; +import com.cloud.utils.db.GenericSearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; @Component public class ServiceOfferingDetailsDaoImpl extends ResourceDetailsDaoBase implements ServiceOfferingDetailsDao { @@ -67,4 +71,23 @@ public String getDetail(Long serviceOfferingId, String key) { } return detailValue; } + + @Override + public List findOfferingIdsByDomainIds(List domainIds) { + Object[] dIds = domainIds.stream().map(s -> String.valueOf(s)).collect(Collectors.toList()).toArray(); + + GenericSearchBuilder sb = createSearchBuilder(Long.class); + sb.selectFields(sb.entity().getResourceId()); + sb.and("name", sb.entity().getName(), Op.EQ); + sb.and().op("value", sb.entity().getValue(), Op.IN); + sb.or("valueNull", sb.entity().getValue(), Op.NULL); + sb.cp(); + sb.done(); + + SearchCriteria sc = sb.create(); + sc.setParameters("name", "domainid"); + sc.setParameters("value", dIds); + + return customSearch(sc, null); + } } diff --git a/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/dao/DiskOfferingDetailsDao.java b/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/dao/DiskOfferingDetailsDao.java index 815f1693ee54..812102a70aab 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/dao/DiskOfferingDetailsDao.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/dao/DiskOfferingDetailsDao.java @@ -27,4 +27,6 @@ public interface DiskOfferingDetailsDao extends GenericDao findDomainIds(final long resourceId); List findZoneIds(final long resourceId); String getDetail(Long diskOfferingId, String key); -} \ No newline at end of file + List findOfferingIdsByDomainIds(List domainIds); +} + diff --git a/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/dao/DiskOfferingDetailsDaoImpl.java b/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/dao/DiskOfferingDetailsDaoImpl.java index 5408f2d7f036..932b7bb73784 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/dao/DiskOfferingDetailsDaoImpl.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/dao/DiskOfferingDetailsDaoImpl.java @@ -19,6 +19,11 @@ import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; + +import com.cloud.utils.db.GenericSearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.resourcedetail.DiskOfferingDetailVO; @@ -66,4 +71,25 @@ public String getDetail(Long diskOfferingId, String key) { } return detailValue; } -} \ No newline at end of file + + @Override + public List findOfferingIdsByDomainIds(List domainIds) { + Object[] dIds = domainIds.stream().map(s -> String.valueOf(s)).collect(Collectors.toList()).toArray(); + + GenericSearchBuilder sb = createSearchBuilder(Long.class); + sb.selectFields(sb.entity().getResourceId()); + sb.and("name", sb.entity().getName(), Op.EQ); + sb.and().op("value", sb.entity().getValue(), Op.IN); + sb.or("valueNull", sb.entity().getValue(), Op.NULL); + sb.cp(); + sb.done(); + + SearchCriteria sc = sb.create(); + sc.setParameters("name", "domainid"); + sc.setParameters("value", dIds); + + return customSearch(sc, null); + } + +} + diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java index 206e67ca81fe..943c85c6d8eb 100644 --- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java @@ -23,7 +23,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.ListIterator; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -119,7 +118,6 @@ import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; -import org.apache.commons.collections.CollectionUtils; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -204,6 +202,7 @@ import com.cloud.server.TaggedResourceService; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.service.dao.ServiceOfferingDetailsDao; import com.cloud.storage.DataStoreRole; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.ScopeType; @@ -346,7 +345,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q private DiskOfferingJoinDao _diskOfferingJoinDao; @Inject - private DiskOfferingDetailsDao diskOfferingDetailsDao; + private DiskOfferingDetailsDao _diskOfferingDetailsDao; @Inject private ServiceOfferingJoinDao _srvOfferingJoinDao; @@ -354,6 +353,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q @Inject private ServiceOfferingDao _srvOfferingDao; + @Inject + private ServiceOfferingDetailsDao _srvOfferingDetailsDao; + @Inject private DataCenterJoinDao _dcJoinDao; @@ -2824,57 +2826,41 @@ private Pair, Integer> searchForDiskOfferingsInternal(L sc.addAnd("zoneId", SearchCriteria.Op.SC, zoneSC); } - // FIXME: disk offerings should search back up the hierarchy for - // available disk offerings... - /* - * sb.addAnd("domainId", sb.entity().getDomainId(), - * SearchCriteria.Op.EQ); if (domainId != null) { - * SearchBuilder domainSearch = - * _domainDao.createSearchBuilder(); domainSearch.addAnd("path", - * domainSearch.entity().getPath(), SearchCriteria.Op.LIKE); - * sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), - * domainSearch.entity().getId()); } - */ - - // FIXME: disk offerings should search back up the hierarchy for - // available disk offerings... - /* - * if (domainId != null) { sc.setParameters("domainId", domainId); // - * //DomainVO domain = _domainDao.findById((Long)domainId); // // I want - * to join on user_vm.domain_id = domain.id where domain.path like - * 'foo%' //sc.setJoinParameters("domainSearch", "path", - * domain.getPath() + "%"); // } - */ + // Filter offerings that are not associated with caller's domain + // Fetch the offering ids from the details table since theres no smart way to filter them in the join ... yet! + Account caller = CallContext.current().getCallingAccount(); + if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + Domain callerDomain = _domainDao.findById(caller.getDomainId()); + List domainIds = _domainDao.getDomainParentIds(callerDomain.getId()) + .stream().collect(Collectors.toList()); + if (isRecursive) { + List childrenIds = _domainDao.getDomainChildrenIds(callerDomain.getPath()); + if (childrenIds != null && !childrenIds.isEmpty()) + domainIds.addAll(childrenIds); + } - Pair, Integer> result = _diskOfferingJoinDao.searchAndCount(sc, searchFilter); - // Remove offerings that are not associated with caller's domain - if (account.getType() != Account.ACCOUNT_TYPE_ADMIN && CollectionUtils.isNotEmpty(result.first())) { - ListIterator it = result.first().listIterator(); - while (it.hasNext()) { - DiskOfferingJoinVO offering = it.next(); - if(!Strings.isNullOrEmpty(offering.getDomainId())) { - boolean toRemove = true; - String[] domainIdsArray = offering.getDomainId().split(","); - for (String domainIdString : domainIdsArray) { - Long dId = Long.valueOf(domainIdString.trim()); - if (isRecursive) { - if (_domainDao.isChildDomain(account.getDomainId(), dId)) { - toRemove = false; - break; - } - } else { - if (_domainDao.isChildDomain(dId, account.getDomainId())) { - toRemove = false; - break; - } - } - } - if (toRemove) { - it.remove(); - } - } + List ids = _diskOfferingDetailsDao.findOfferingIdsByDomainIds(domainIds); + + if (ids == null || ids.isEmpty()) { + SearchBuilder sb = _diskOfferingJoinDao.createSearchBuilder(); + sb.or("domainId", sb.entity().getDomainId(), Op.NULL); + sb.done(); + + SearchCriteria scc = sb.create(); + sc.addAnd("domainId", SearchCriteria.Op.SC, scc); + } else { + SearchBuilder sb = _diskOfferingJoinDao.createSearchBuilder(); + sb.and("id", sb.entity().getId(), Op.IN); + sb.or("domainId", sb.entity().getDomainId(), Op.NULL); + sb.done(); + + SearchCriteria scc = sb.create(); + scc.setParameters("id", ids.toArray()); + sc.addAnd("domainId", SearchCriteria.Op.SC, scc); } } + + Pair, Integer> result = _diskOfferingJoinDao.searchAndCount(sc, searchFilter); return new Pair<>(result.first(), result.second()); } @@ -3064,38 +3050,44 @@ private Pair, Integer> searchForServiceOfferingsInte sc.addAnd("cpuspeedconstraints", SearchCriteria.Op.SC, cpuSpeedSearchCriteria); } + // Filter offerings that are not associated with caller's domain + // Fetch the offering ids from the details table since theres no smart way to filter them in the join ... yet! + if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + Domain callerDomain = _domainDao.findById(caller.getDomainId()); + List domainIds = _domainDao.getDomainParentIds(callerDomain.getId()) + .stream().collect(Collectors.toList()); + if (isRecursive) { + List childrenIds = _domainDao.getDomainChildrenIds(callerDomain.getPath()); + if (childrenIds != null && !childrenIds.isEmpty()) + domainIds.addAll(childrenIds); + } + + List ids = _srvOfferingDetailsDao.findOfferingIdsByDomainIds(domainIds); + + if (ids == null || ids.isEmpty()) { + SearchBuilder sb = _srvOfferingJoinDao.createSearchBuilder(); + sb.or("domainId", sb.entity().getDomainId(), Op.NULL); + sb.done(); + + SearchCriteria scc = sb.create(); + sc.addAnd("domainId", SearchCriteria.Op.SC, scc); + } else { + SearchBuilder sb = _srvOfferingJoinDao.createSearchBuilder(); + sb.and("id", sb.entity().getId(), Op.IN); + sb.or("domainId", sb.entity().getDomainId(), Op.NULL); + sb.done(); + + SearchCriteria scc = sb.create(); + scc.setParameters("id", ids.toArray()); + sc.addAnd("domainId", SearchCriteria.Op.SC, scc); + } + } + Pair, Integer> result = _srvOfferingJoinDao.searchAndCount(sc, searchFilter); //Couldn't figure out a smart way to filter offerings based on tags in sql so doing it in Java. List filteredOfferings = filterOfferingsOnCurrentTags(result.first(), currentVmOffering); - // Remove offerings that are not associated with caller's domain - if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN && CollectionUtils.isNotEmpty(filteredOfferings)) { - ListIterator it = filteredOfferings.listIterator(); - while (it.hasNext()) { - ServiceOfferingJoinVO offering = it.next(); - if(!Strings.isNullOrEmpty(offering.getDomainId())) { - boolean toRemove = true; - String[] domainIdsArray = offering.getDomainId().split(","); - for (String domainIdString : domainIdsArray) { - Long dId = Long.valueOf(domainIdString.trim()); - if (isRecursive) { - if (_domainDao.isChildDomain(caller.getDomainId(), dId)) { - toRemove = false; - break; - } - } else { - if (_domainDao.isChildDomain(dId, caller.getDomainId())) { - toRemove = false; - break; - } - } - } - if (toRemove) { - it.remove(); - } - } - } - } + return new Pair<>(filteredOfferings, result.second()); } diff --git a/server/src/main/java/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java index 9950b90a2f26..224a3c2d191b 100644 --- a/server/src/main/java/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java @@ -144,5 +144,4 @@ public ServiceOfferingJoinVO newServiceOfferingView(ServiceOffering offering) { assert offerings != null && offerings.size() == 1 : "No service offering found for offering id " + offering.getId(); return offerings.get(0); } - } From 693214dd69797261835765a933b7a7fa21540ab8 Mon Sep 17 00:00:00 2001 From: davidjumani Date: Fri, 20 Aug 2021 10:50:32 +0530 Subject: [PATCH 2/5] Search for tags in the db --- .../com/cloud/api/query/QueryManagerImpl.java | 35 ++++++++----------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java index 943c85c6d8eb..1ea7fd2ad827 100644 --- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java @@ -2864,23 +2864,6 @@ private Pair, Integer> searchForDiskOfferingsInternal(L return new Pair<>(result.first(), result.second()); } - private List filterOfferingsOnCurrentTags(List offerings, ServiceOfferingVO currentVmOffering) { - if (currentVmOffering == null) { - return offerings; - } - List currentTagsList = StringUtils.csvTagsToList(currentVmOffering.getTags()); - - // New service offering should have all the tags of the current service offering. - List filteredOfferings = new ArrayList<>(); - for (ServiceOfferingJoinVO offering : offerings) { - List newTagsList = StringUtils.csvTagsToList(offering.getTags()); - if (newTagsList.containsAll(currentTagsList)) { - filteredOfferings.add(offering); - } - } - return filteredOfferings; - } - @Override public ListResponse searchForServiceOfferings(ListServiceOfferingsCmd cmd) { Pair, Integer> result = searchForServiceOfferingsInternal(cmd); @@ -3083,12 +3066,22 @@ private Pair, Integer> searchForServiceOfferingsInte } } - Pair, Integer> result = _srvOfferingJoinDao.searchAndCount(sc, searchFilter); + if (currentVmOffering != null) { + List tags = StringUtils.csvTagsToList(currentVmOffering.getTags()); + SearchBuilder sb = _srvOfferingJoinDao.createSearchBuilder(); + for(String tag: tags) { + sb.and(tag, sb.entity().getTags(), Op.FIND_IN_SET); + } + sb.done(); - //Couldn't figure out a smart way to filter offerings based on tags in sql so doing it in Java. - List filteredOfferings = filterOfferingsOnCurrentTags(result.first(), currentVmOffering); + SearchCriteria scc = sb.create(); + for(String tag: tags) { + scc.setParameters(tag, tag); + } + sc.addAnd("tags", SearchCriteria.Op.SC, scc); + } - return new Pair<>(filteredOfferings, result.second()); + return _srvOfferingJoinDao.searchAndCount(sc, searchFilter); } @Override From 465c513af3443f128f3d3f4b8b5e73b7be4bbc0c Mon Sep 17 00:00:00 2001 From: davidjumani Date: Fri, 20 Aug 2021 13:16:30 +0530 Subject: [PATCH 3/5] Update search to include host tags --- .../com/cloud/api/query/QueryManagerImpl.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java index 1ea7fd2ad827..23a7aac3123c 100644 --- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java @@ -3068,17 +3068,20 @@ private Pair, Integer> searchForServiceOfferingsInte if (currentVmOffering != null) { List tags = StringUtils.csvTagsToList(currentVmOffering.getTags()); - SearchBuilder sb = _srvOfferingJoinDao.createSearchBuilder(); - for(String tag: tags) { - sb.and(tag, sb.entity().getTags(), Op.FIND_IN_SET); - } - sb.done(); + tags.addAll(StringUtils.csvTagsToList(currentVmOffering.getHostTag())); + if (!tags.isEmpty()) { + SearchBuilder sb = _srvOfferingJoinDao.createSearchBuilder(); + for(int i = 0; i < tags.size(); i++) { + sb.and(Integer.toString(i), sb.entity().getTags(), Op.FIND_IN_SET); + } + sb.done(); - SearchCriteria scc = sb.create(); - for(String tag: tags) { - scc.setParameters(tag, tag); + SearchCriteria scc = sb.create(); + for(int i = 0; i < tags.size(); i++) { + scc.setParameters(Integer.toString(i), tags.get(i)); + } + sc.addAnd("tags", SearchCriteria.Op.SC, scc); } - sc.addAnd("tags", SearchCriteria.Op.SC, scc); } return _srvOfferingJoinDao.searchAndCount(sc, searchFilter); From bd87ce51c1fd94edd356e2f48d93a6ef4fe8b108 Mon Sep 17 00:00:00 2001 From: davidjumani Date: Fri, 20 Aug 2021 13:58:04 +0530 Subject: [PATCH 4/5] Differenciate between tags --- .../com/cloud/api/query/QueryManagerImpl.java | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java index 23a7aac3123c..bdcda865272c 100644 --- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java @@ -3067,20 +3067,34 @@ private Pair, Integer> searchForServiceOfferingsInte } if (currentVmOffering != null) { - List tags = StringUtils.csvTagsToList(currentVmOffering.getTags()); - tags.addAll(StringUtils.csvTagsToList(currentVmOffering.getHostTag())); - if (!tags.isEmpty()) { + List storageTags = StringUtils.csvTagsToList(currentVmOffering.getTags()); + if (!storageTags.isEmpty()) { SearchBuilder sb = _srvOfferingJoinDao.createSearchBuilder(); - for(int i = 0; i < tags.size(); i++) { - sb.and(Integer.toString(i), sb.entity().getTags(), Op.FIND_IN_SET); + for(String tag : storageTags) { + sb.and(tag, sb.entity().getTags(), Op.FIND_IN_SET); } sb.done(); SearchCriteria scc = sb.create(); - for(int i = 0; i < tags.size(); i++) { - scc.setParameters(Integer.toString(i), tags.get(i)); + for(String tag : storageTags) { + scc.setParameters(tag, tag); } - sc.addAnd("tags", SearchCriteria.Op.SC, scc); + sc.addAnd("storageTags", SearchCriteria.Op.SC, scc); + } + + List hostTags = StringUtils.csvTagsToList(currentVmOffering.getHostTag()); + if (!hostTags.isEmpty()) { + SearchBuilder sb = _srvOfferingJoinDao.createSearchBuilder(); + for(String tag : hostTags) { + sb.and(tag, sb.entity().getHostTag(), Op.FIND_IN_SET); + } + sb.done(); + + SearchCriteria scc = sb.create(); + for(String tag : hostTags) { + scc.setParameters(tag, tag); + } + sc.addAnd("hostTags", SearchCriteria.Op.SC, scc); } } From 5c3546d5e187056c847cf946efc0aa538e2e2986 Mon Sep 17 00:00:00 2001 From: davidjumani Date: Thu, 2 Sep 2021 14:31:34 +0530 Subject: [PATCH 5/5] Refactor --- .../dao/ServiceOfferingDetailsDaoImpl.java | 18 +---- .../resourcedetail/ResourceDetailsDao.java | 1 + .../ResourceDetailsDaoBase.java | 19 +++++ .../dao/DiskOfferingDetailsDaoImpl.java | 20 +----- .../com/cloud/api/query/QueryManagerImpl.java | 71 ++++++++----------- 5 files changed, 51 insertions(+), 78 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDetailsDaoImpl.java b/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDetailsDaoImpl.java index 9d553b4e8f9b..0d14882fa291 100644 --- a/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDetailsDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDetailsDaoImpl.java @@ -26,9 +26,6 @@ import org.springframework.stereotype.Component; import com.cloud.service.ServiceOfferingDetailsVO; -import com.cloud.utils.db.GenericSearchBuilder; -import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.db.SearchCriteria.Op; @Component public class ServiceOfferingDetailsDaoImpl extends ResourceDetailsDaoBase implements ServiceOfferingDetailsDao { @@ -75,19 +72,6 @@ public String getDetail(Long serviceOfferingId, String key) { @Override public List findOfferingIdsByDomainIds(List domainIds) { Object[] dIds = domainIds.stream().map(s -> String.valueOf(s)).collect(Collectors.toList()).toArray(); - - GenericSearchBuilder sb = createSearchBuilder(Long.class); - sb.selectFields(sb.entity().getResourceId()); - sb.and("name", sb.entity().getName(), Op.EQ); - sb.and().op("value", sb.entity().getValue(), Op.IN); - sb.or("valueNull", sb.entity().getValue(), Op.NULL); - sb.cp(); - sb.done(); - - SearchCriteria sc = sb.create(); - sc.setParameters("name", "domainid"); - sc.setParameters("value", dIds); - - return customSearch(sc, null); + return findResouceIdsByNameAndValueIn("domainid", dIds); } } diff --git a/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/ResourceDetailsDao.java b/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/ResourceDetailsDao.java index 52d901293ad6..bde71b350ac8 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/ResourceDetailsDao.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/ResourceDetailsDao.java @@ -96,4 +96,5 @@ public interface ResourceDetailsDao extends GenericDao public void addDetail(long resourceId, String key, String value, boolean display); + public List findResouceIdsByNameAndValueIn(String name, Object[] values); } diff --git a/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/ResourceDetailsDaoBase.java b/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/ResourceDetailsDaoBase.java index 0f153dbbf081..b33a1fc25994 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/ResourceDetailsDaoBase.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/ResourceDetailsDaoBase.java @@ -23,9 +23,11 @@ import org.apache.cloudstack.api.ResourceDetail; import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.GenericSearchBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.TransactionLegacy; +import com.cloud.utils.db.SearchCriteria.Op; public abstract class ResourceDetailsDaoBase extends GenericDaoBase implements ResourceDetailsDao { private SearchBuilder AllFieldsSearch; @@ -182,4 +184,21 @@ public List listDetails(long resourceId, boolean forDisplay) { List results = search(sc, null); return results; } + + @Override + public List findResouceIdsByNameAndValueIn(String name, Object[] values) { + GenericSearchBuilder sb = createSearchBuilder(Long.class); + sb.selectFields(sb.entity().getResourceId()); + sb.and("name", sb.entity().getName(), Op.EQ); + sb.and().op("value", sb.entity().getValue(), Op.IN); + sb.or("valueNull", sb.entity().getValue(), Op.NULL); + sb.cp(); + sb.done(); + + SearchCriteria sc = sb.create(); + sc.setParameters("name", name); + sc.setParameters("value", values); + + return customSearch(sc, null); + } } diff --git a/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/dao/DiskOfferingDetailsDaoImpl.java b/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/dao/DiskOfferingDetailsDaoImpl.java index 932b7bb73784..4d29dda560f7 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/dao/DiskOfferingDetailsDaoImpl.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/dao/DiskOfferingDetailsDaoImpl.java @@ -21,10 +21,6 @@ import java.util.List; import java.util.stream.Collectors; -import com.cloud.utils.db.GenericSearchBuilder; -import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.db.SearchCriteria.Op; - import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.resourcedetail.DiskOfferingDetailVO; import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase; @@ -75,21 +71,7 @@ public String getDetail(Long diskOfferingId, String key) { @Override public List findOfferingIdsByDomainIds(List domainIds) { Object[] dIds = domainIds.stream().map(s -> String.valueOf(s)).collect(Collectors.toList()).toArray(); - - GenericSearchBuilder sb = createSearchBuilder(Long.class); - sb.selectFields(sb.entity().getResourceId()); - sb.and("name", sb.entity().getName(), Op.EQ); - sb.and().op("value", sb.entity().getValue(), Op.IN); - sb.or("valueNull", sb.entity().getValue(), Op.NULL); - sb.cp(); - sb.done(); - - SearchCriteria sc = sb.create(); - sc.setParameters("name", "domainid"); - sc.setParameters("value", dIds); - - return customSearch(sc, null); + return findResouceIdsByNameAndValueIn("domainid", dIds); } - } diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java index bdcda865272c..1d7f5308ab59 100644 --- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java @@ -2831,39 +2831,38 @@ private Pair, Integer> searchForDiskOfferingsInternal(L Account caller = CallContext.current().getCallingAccount(); if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { Domain callerDomain = _domainDao.findById(caller.getDomainId()); - List domainIds = _domainDao.getDomainParentIds(callerDomain.getId()) - .stream().collect(Collectors.toList()); - if (isRecursive) { - List childrenIds = _domainDao.getDomainChildrenIds(callerDomain.getPath()); - if (childrenIds != null && !childrenIds.isEmpty()) - domainIds.addAll(childrenIds); - } + List domainIds = findRelatedDomainIds(callerDomain, isRecursive); List ids = _diskOfferingDetailsDao.findOfferingIdsByDomainIds(domainIds); - - if (ids == null || ids.isEmpty()) { - SearchBuilder sb = _diskOfferingJoinDao.createSearchBuilder(); - sb.or("domainId", sb.entity().getDomainId(), Op.NULL); - sb.done(); - - SearchCriteria scc = sb.create(); - sc.addAnd("domainId", SearchCriteria.Op.SC, scc); - } else { - SearchBuilder sb = _diskOfferingJoinDao.createSearchBuilder(); + SearchBuilder sb = _diskOfferingJoinDao.createSearchBuilder(); + if (ids != null && !ids.isEmpty()) { sb.and("id", sb.entity().getId(), Op.IN); - sb.or("domainId", sb.entity().getDomainId(), Op.NULL); - sb.done(); + } + sb.or("domainId", sb.entity().getDomainId(), Op.NULL); + sb.done(); - SearchCriteria scc = sb.create(); + SearchCriteria scc = sb.create(); + if (ids != null && !ids.isEmpty()) { scc.setParameters("id", ids.toArray()); - sc.addAnd("domainId", SearchCriteria.Op.SC, scc); } + sc.addAnd("domainId", SearchCriteria.Op.SC, scc); } Pair, Integer> result = _diskOfferingJoinDao.searchAndCount(sc, searchFilter); return new Pair<>(result.first(), result.second()); } + private List findRelatedDomainIds(Domain domain, boolean isRecursive) { + List domainIds = _domainDao.getDomainParentIds(domain.getId()) + .stream().collect(Collectors.toList()); + if (isRecursive) { + List childrenIds = _domainDao.getDomainChildrenIds(domain.getPath()); + if (childrenIds != null && !childrenIds.isEmpty()) + domainIds.addAll(childrenIds); + } + return domainIds; + } + @Override public ListResponse searchForServiceOfferings(ListServiceOfferingsCmd cmd) { Pair, Integer> result = searchForServiceOfferingsInternal(cmd); @@ -3037,33 +3036,21 @@ private Pair, Integer> searchForServiceOfferingsInte // Fetch the offering ids from the details table since theres no smart way to filter them in the join ... yet! if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { Domain callerDomain = _domainDao.findById(caller.getDomainId()); - List domainIds = _domainDao.getDomainParentIds(callerDomain.getId()) - .stream().collect(Collectors.toList()); - if (isRecursive) { - List childrenIds = _domainDao.getDomainChildrenIds(callerDomain.getPath()); - if (childrenIds != null && !childrenIds.isEmpty()) - domainIds.addAll(childrenIds); - } + List domainIds = findRelatedDomainIds(callerDomain, isRecursive); List ids = _srvOfferingDetailsDao.findOfferingIdsByDomainIds(domainIds); - - if (ids == null || ids.isEmpty()) { - SearchBuilder sb = _srvOfferingJoinDao.createSearchBuilder(); - sb.or("domainId", sb.entity().getDomainId(), Op.NULL); - sb.done(); - - SearchCriteria scc = sb.create(); - sc.addAnd("domainId", SearchCriteria.Op.SC, scc); - } else { - SearchBuilder sb = _srvOfferingJoinDao.createSearchBuilder(); + SearchBuilder sb = _srvOfferingJoinDao.createSearchBuilder(); + if (ids != null && !ids.isEmpty()) { sb.and("id", sb.entity().getId(), Op.IN); - sb.or("domainId", sb.entity().getDomainId(), Op.NULL); - sb.done(); + } + sb.or("domainId", sb.entity().getDomainId(), Op.NULL); + sb.done(); - SearchCriteria scc = sb.create(); + SearchCriteria scc = sb.create(); + if (ids != null && !ids.isEmpty()) { scc.setParameters("id", ids.toArray()); - sc.addAnd("domainId", SearchCriteria.Op.SC, scc); } + sc.addAnd("domainId", SearchCriteria.Op.SC, scc); } if (currentVmOffering != null) {