-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Filter disk / service offerings by domain at DB level #5307
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c21fdb0
693214d
465c513
bd87ce5
5c3546d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ | |
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| import org.apache.cloudstack.api.ApiConstants; | ||
| import org.apache.cloudstack.resourcedetail.DiskOfferingDetailVO; | ||
|
|
@@ -66,4 +67,11 @@ public String getDetail(Long diskOfferingId, String key) { | |
| } | ||
| return detailValue; | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public List<Long> findOfferingIdsByDomainIds(List<Long> domainIds) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @davidjumani This part is duplicated code right? this can be in a common place for both service and disk offering
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refactored and updated |
||
| Object[] dIds = domainIds.stream().map(s -> String.valueOf(s)).collect(Collectors.toList()).toArray(); | ||
| return findResouceIdsByNameAndValueIn("domainid", dIds); | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -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,14 +345,17 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q | |||||
| private DiskOfferingJoinDao _diskOfferingJoinDao; | ||||||
|
|
||||||
| @Inject | ||||||
| private DiskOfferingDetailsDao diskOfferingDetailsDao; | ||||||
| private DiskOfferingDetailsDao _diskOfferingDetailsDao; | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why add the '_'? we are trying to get away from that convention.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consistency in the file, unless you'd like me to rename all the class variables ?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't see the use of this consistency. the underscore does not value in field names, does it?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm for changing all variables, not just one, which can be done in a separate PR |
||||||
|
|
||||||
| @Inject | ||||||
| private ServiceOfferingJoinDao _srvOfferingJoinDao; | ||||||
|
|
||||||
| @Inject | ||||||
| private ServiceOfferingDao _srvOfferingDao; | ||||||
|
|
||||||
| @Inject | ||||||
| private ServiceOfferingDetailsDao _srvOfferingDetailsDao; | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| @Inject | ||||||
| private DataCenterJoinDao _dcJoinDao; | ||||||
|
|
||||||
|
|
@@ -2824,75 +2826,41 @@ private Pair<List<DiskOfferingJoinVO>, 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<DomainVO> 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 | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good method name ;) maybe factor out the below. |
||||||
| // 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<Long> domainIds = findRelatedDomainIds(callerDomain, isRecursive); | ||||||
|
|
||||||
| Pair<List<DiskOfferingJoinVO>, 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<DiskOfferingJoinVO> 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<Long> ids = _diskOfferingDetailsDao.findOfferingIdsByDomainIds(domainIds); | ||||||
| SearchBuilder<DiskOfferingJoinVO> 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(); | ||||||
|
|
||||||
| SearchCriteria<DiskOfferingJoinVO> scc = sb.create(); | ||||||
| if (ids != null && !ids.isEmpty()) { | ||||||
| scc.setParameters("id", ids.toArray()); | ||||||
| } | ||||||
| sc.addAnd("domainId", SearchCriteria.Op.SC, scc); | ||||||
| } | ||||||
|
|
||||||
| Pair<List<DiskOfferingJoinVO>, Integer> result = _diskOfferingJoinDao.searchAndCount(sc, searchFilter); | ||||||
| return new Pair<>(result.first(), result.second()); | ||||||
| } | ||||||
|
|
||||||
| private List<ServiceOfferingJoinVO> filterOfferingsOnCurrentTags(List<ServiceOfferingJoinVO> offerings, ServiceOfferingVO currentVmOffering) { | ||||||
| if (currentVmOffering == null) { | ||||||
| return offerings; | ||||||
| private List<Long> findRelatedDomainIds(Domain domain, boolean isRecursive) { | ||||||
| List<Long> domainIds = _domainDao.getDomainParentIds(domain.getId()) | ||||||
| .stream().collect(Collectors.toList()); | ||||||
| if (isRecursive) { | ||||||
| List<Long> childrenIds = _domainDao.getDomainChildrenIds(domain.getPath()); | ||||||
| if (childrenIds != null && !childrenIds.isEmpty()) | ||||||
| domainIds.addAll(childrenIds); | ||||||
| } | ||||||
| List<String> currentTagsList = StringUtils.csvTagsToList(currentVmOffering.getTags()); | ||||||
|
|
||||||
| // New service offering should have all the tags of the current service offering. | ||||||
| List<ServiceOfferingJoinVO> filteredOfferings = new ArrayList<>(); | ||||||
| for (ServiceOfferingJoinVO offering : offerings) { | ||||||
| List<String> newTagsList = StringUtils.csvTagsToList(offering.getTags()); | ||||||
| if (newTagsList.containsAll(currentTagsList)) { | ||||||
| filteredOfferings.add(offering); | ||||||
| } | ||||||
| } | ||||||
| return filteredOfferings; | ||||||
| return domainIds; | ||||||
| } | ||||||
|
|
||||||
| @Override | ||||||
|
|
@@ -3064,39 +3032,60 @@ private Pair<List<ServiceOfferingJoinVO>, Integer> searchForServiceOfferingsInte | |||||
| sc.addAnd("cpuspeedconstraints", SearchCriteria.Op.SC, cpuSpeedSearchCriteria); | ||||||
| } | ||||||
|
|
||||||
| Pair<List<ServiceOfferingJoinVO>, 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<ServiceOfferingJoinVO> 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<ServiceOfferingJoinVO> 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(); | ||||||
| } | ||||||
| // Filter offerings that are not associated with caller's domain | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. once again, a this comment is a good method name to extract the code below to. |
||||||
| // 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<Long> domainIds = findRelatedDomainIds(callerDomain, isRecursive); | ||||||
|
|
||||||
| List<Long> ids = _srvOfferingDetailsDao.findOfferingIdsByDomainIds(domainIds); | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Most of this is duplicated code. can be extracted to a single function. |
||||||
| SearchBuilder<ServiceOfferingJoinVO> 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(); | ||||||
|
|
||||||
| SearchCriteria<ServiceOfferingJoinVO> scc = sb.create(); | ||||||
| if (ids != null && !ids.isEmpty()) { | ||||||
| scc.setParameters("id", ids.toArray()); | ||||||
| } | ||||||
| sc.addAnd("domainId", SearchCriteria.Op.SC, scc); | ||||||
| } | ||||||
|
|
||||||
| if (currentVmOffering != null) { | ||||||
| List<String> storageTags = StringUtils.csvTagsToList(currentVmOffering.getTags()); | ||||||
| if (!storageTags.isEmpty()) { | ||||||
| SearchBuilder<ServiceOfferingJoinVO> sb = _srvOfferingJoinDao.createSearchBuilder(); | ||||||
| for(String tag : storageTags) { | ||||||
| sb.and(tag, sb.entity().getTags(), Op.FIND_IN_SET); | ||||||
| } | ||||||
| sb.done(); | ||||||
|
|
||||||
| SearchCriteria<ServiceOfferingJoinVO> scc = sb.create(); | ||||||
| for(String tag : storageTags) { | ||||||
| scc.setParameters(tag, tag); | ||||||
| } | ||||||
| sc.addAnd("storageTags", SearchCriteria.Op.SC, scc); | ||||||
| } | ||||||
|
|
||||||
| List<String> hostTags = StringUtils.csvTagsToList(currentVmOffering.getHostTag()); | ||||||
| if (!hostTags.isEmpty()) { | ||||||
| SearchBuilder<ServiceOfferingJoinVO> sb = _srvOfferingJoinDao.createSearchBuilder(); | ||||||
| for(String tag : hostTags) { | ||||||
| sb.and(tag, sb.entity().getHostTag(), Op.FIND_IN_SET); | ||||||
| } | ||||||
| sb.done(); | ||||||
|
|
||||||
| SearchCriteria<ServiceOfferingJoinVO> scc = sb.create(); | ||||||
| for(String tag : hostTags) { | ||||||
| scc.setParameters(tag, tag); | ||||||
| } | ||||||
| sc.addAnd("hostTags", SearchCriteria.Op.SC, scc); | ||||||
| } | ||||||
| } | ||||||
| return new Pair<>(filteredOfferings, result.second()); | ||||||
|
|
||||||
| return _srvOfferingJoinDao.searchAndCount(sc, searchFilter); | ||||||
| } | ||||||
|
|
||||||
| @Override | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better to mention String[] rather than Object[] since you are explicitly getting string value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactored and updated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@davidjumani this can be simplified to
domainIds.stream().map(String::valueOf).toArray();