Merge branch '4.15' into main

This commit is contained in:
nicolas 2021-09-03 00:06:08 -03:00
commit 13d8489478
No known key found for this signature in database
GPG Key ID: 656E1BCC8CB54F84
8 changed files with 125 additions and 98 deletions

View File

@ -27,4 +27,6 @@ public interface ServiceOfferingDetailsDao extends GenericDao<ServiceOfferingDet
List<Long> findDomainIds(final long resourceId);
List<Long> findZoneIds(final long resourceId);
String getDetail(Long diskOfferingId, String key);
}
List<Long> findOfferingIdsByDomainIds(List<Long> domainIds);
}

View File

@ -19,6 +19,7 @@ package com.cloud.service.dao;
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;
@ -67,4 +68,10 @@ public class ServiceOfferingDetailsDaoImpl extends ResourceDetailsDaoBase<Servic
}
return detailValue;
}
@Override
public List<Long> findOfferingIdsByDomainIds(List<Long> domainIds) {
Object[] dIds = domainIds.stream().map(s -> String.valueOf(s)).collect(Collectors.toList()).toArray();
return findResouceIdsByNameAndValueIn("domainid", dIds);
}
}

View File

@ -96,4 +96,5 @@ public interface ResourceDetailsDao<R extends ResourceDetail> extends GenericDao
public void addDetail(long resourceId, String key, String value, boolean display);
public List<Long> findResouceIdsByNameAndValueIn(String name, Object[] values);
}

View File

@ -23,9 +23,11 @@ import java.util.Map;
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<R extends ResourceDetail> extends GenericDaoBase<R, Long> implements ResourceDetailsDao<R> {
private SearchBuilder<R> AllFieldsSearch;
@ -182,4 +184,21 @@ public abstract class ResourceDetailsDaoBase<R extends ResourceDetail> extends G
List<R> results = search(sc, null);
return results;
}
@Override
public List<Long> findResouceIdsByNameAndValueIn(String name, Object[] values) {
GenericSearchBuilder<R, Long> 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<Long> sc = sb.create();
sc.setParameters("name", name);
sc.setParameters("value", values);
return customSearch(sc, null);
}
}

View File

@ -27,4 +27,6 @@ public interface DiskOfferingDetailsDao extends GenericDao<DiskOfferingDetailVO,
List<Long> findDomainIds(final long resourceId);
List<Long> findZoneIds(final long resourceId);
String getDetail(Long diskOfferingId, String key);
}
List<Long> findOfferingIdsByDomainIds(List<Long> domainIds);
}

View File

@ -19,6 +19,7 @@ package org.apache.cloudstack.resourcedetail.dao;
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 class DiskOfferingDetailsDaoImpl extends ResourceDetailsDaoBase<DiskOffer
}
return detailValue;
}
}
@Override
public List<Long> findOfferingIdsByDomainIds(List<Long> domainIds) {
Object[] dIds = domainIds.stream().map(s -> String.valueOf(s)).collect(Collectors.toList()).toArray();
return findResouceIdsByNameAndValueIn("domainid", dIds);
}
}

View File

@ -23,7 +23,6 @@ import java.util.Date;
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;
@ -121,7 +120,6 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO;
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
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;
@ -207,6 +205,7 @@ import com.cloud.server.ResourceTag.ResourceObjectType;
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;
@ -350,7 +349,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
private DiskOfferingJoinDao _diskOfferingJoinDao;
@Inject
private DiskOfferingDetailsDao diskOfferingDetailsDao;
private DiskOfferingDetailsDao _diskOfferingDetailsDao;
@Inject
private ServiceOfferingJoinDao _srvOfferingJoinDao;
@ -358,6 +357,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Inject
private ServiceOfferingDao _srvOfferingDao;
@Inject
private ServiceOfferingDetailsDao _srvOfferingDetailsDao;
@Inject
private DataCenterJoinDao _dcJoinDao;
@ -2869,75 +2871,41 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
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()); }
*/
// 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<Long> domainIds = findRelatedDomainIds(callerDomain, isRecursive);
// 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() + "%"); // }
*/
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);
// 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();
}
}
}
}
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
@ -3111,39 +3079,60 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
sc.addAnd("cpuspeedconstraints", SearchCriteria.Op.SC, cpuSpeedSearchCriteria);
}
Pair<List<ServiceOfferingJoinVO>, Integer> result = _srvOfferingJoinDao.searchAndCount(sc, searchFilter);
// 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<Long> domainIds = findRelatedDomainIds(callerDomain, isRecursive);
//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();
}
List<Long> ids = _srvOfferingDetailsDao.findOfferingIdsByDomainIds(domainIds);
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

View File

@ -145,5 +145,4 @@ public class ServiceOfferingJoinDaoImpl extends GenericDaoBase<ServiceOfferingJo
assert offerings != null && offerings.size() == 1 : "No service offering found for offering id " + offering.getId();
return offerings.get(0);
}
}