Refactor listNetworks logic to use new IAM model.

This commit is contained in:
Min Chen 2014-03-18 16:07:22 -07:00
parent 4723fbb83f
commit ec5ee761d9
1 changed files with 76 additions and 272 deletions

View File

@ -105,20 +105,19 @@ import com.cloud.network.dao.AccountGuestVlanMapVO;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.dao.LoadBalancerVMMapVO;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkDomainDao;
import com.cloud.network.dao.NetworkDomainVO;
import com.cloud.network.dao.NetworkServiceMapDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.dao.OvsProviderDao;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao;
import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO;
import com.cloud.network.dao.PhysicalNetworkVO;
import com.cloud.network.dao.LoadBalancerVMMapVO;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.element.OvsProviderVO;
import com.cloud.network.element.VirtualRouterElement;
@ -141,13 +140,13 @@ import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
import com.cloud.org.Grouping;
import com.cloud.projects.Project;
import com.cloud.projects.Project.ListProjectResourcesCriteria;
import com.cloud.projects.ProjectManager;
import com.cloud.server.ResourceTag.ResourceObjectType;
import com.cloud.tags.ResourceTagVO;
import com.cloud.tags.dao.ResourceTagDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.DomainManager;
import com.cloud.user.ResourceLimitService;
import com.cloud.user.User;
@ -157,6 +156,7 @@ import com.cloud.user.dao.UserDao;
import com.cloud.utils.Journal;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.EntityManager;
@ -1390,14 +1390,10 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
String trafficType = cmd.getTrafficType();
Boolean isSystem = cmd.getIsSystem();
String aclType = cmd.getAclType();
Long projectId = cmd.getProjectId();
List<Long> permittedAccounts = new ArrayList<Long>();
String path = null;
Long physicalNetworkId = cmd.getPhysicalNetworkId();
List<String> supportedServicesStr = cmd.getSupportedServices();
Boolean restartRequired = cmd.getRestartRequired();
boolean listAll = cmd.listAll();
boolean isRecursive = cmd.isRecursive();
Boolean specifyIpRanges = cmd.getSpecifyIpRanges();
Long vpcId = cmd.getVpcId();
Boolean canUseForDeploy = cmd.canUseForDeploy();
@ -1416,66 +1412,16 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
throw new InvalidParameterValueException("System network belongs to system, account and domainId parameters can't be specified");
}
if (domainId != null) {
DomainVO domain = _domainDao.findById(domainId);
if (domain == null) {
// see DomainVO.java
throw new InvalidParameterValueException("Specified domain id doesn't exist in the system");
}
List<Long> permittedDomains = new ArrayList<Long>();
List<Long> permittedAccounts = new ArrayList<Long>();
List<Long> permittedResources = new ArrayList<Long>();
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(cmd.getDomainId(),
cmd.isRecursive(), null);
_accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedDomains, permittedAccounts, permittedResources,
domainIdRecursiveListProject, cmd.listAll(), false, "listNetworks");
Boolean isRecursive = domainIdRecursiveListProject.second();
ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
_accountMgr.checkAccess(caller, domain);
if (accountName != null) {
Account owner = _accountMgr.getActiveAccountByName(accountName, domainId);
if (owner == null) {
// see DomainVO.java
throw new InvalidParameterValueException("Unable to find account " + accountName + " in specified domain");
}
_accountMgr.checkAccess(caller, null, true, owner);
permittedAccounts.add(owner.getId());
}
}
if (!_accountMgr.isAdmin(caller.getType()) || (projectId != null && projectId.longValue() != -1 && domainId == null)) {
permittedAccounts.add(caller.getId());
domainId = caller.getDomainId();
}
// set project information
boolean skipProjectNetworks = true;
if (projectId != null) {
if (projectId.longValue() == -1) {
if (!_accountMgr.isAdmin(caller.getType())) {
permittedAccounts.addAll(_projectMgr.listPermittedProjectAccounts(caller.getId()));
}
} else {
permittedAccounts.clear();
Project project = _projectMgr.getProject(projectId);
if (project == null) {
throw new InvalidParameterValueException("Unable to find project by specified id");
}
if (!_projectMgr.canAccessProjectAccount(caller, project.getProjectAccountId())) {
// getProject() returns type ProjectVO.
InvalidParameterValueException ex = new InvalidParameterValueException("Account " + caller + " cannot access specified project id");
ex.addProxyObject(project.getUuid(), "projectId");
throw ex;
}
//add project account
permittedAccounts.add(project.getProjectAccountId());
//add caller account (if admin)
if (_accountMgr.isAdmin(caller.getType())) {
permittedAccounts.add(caller.getId());
}
}
skipProjectNetworks = false;
}
if (domainId != null) {
path = _domainDao.findById(domainId).getPath();
} else {
path = _domainDao.findById(caller.getDomainId()).getPath();
}
if (listAll && domainId == null) {
isRecursive = true;
@ -1483,6 +1429,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
Filter searchFilter = new Filter(NetworkVO.class, "id", false, null, null);
SearchBuilder<NetworkVO> sb = _networksDao.createSearchBuilder();
_accountMgr.buildACLSearchBuilder(sb, isRecursive, permittedDomains, permittedAccounts, permittedResources, listProjectResourcesCriteria);
if (forVpc != null) {
if (forVpc) {
@ -1517,122 +1464,9 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER);
}
if (permittedAccounts.isEmpty()) {
SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
}
SearchBuilder<AccountVO> accountSearch = _accountDao.createSearchBuilder();
accountSearch.and("typeNEQ", accountSearch.entity().getType(), SearchCriteria.Op.NEQ);
accountSearch.and("typeEQ", accountSearch.entity().getType(), SearchCriteria.Op.EQ);
sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinBuilder.JoinType.INNER);
List<NetworkVO> networksToReturn = new ArrayList<NetworkVO>();
if (isSystem == null || !isSystem) {
if (!permittedAccounts.isEmpty()) {
//get account level networks
networksToReturn.addAll(listAccountSpecificNetworks(
buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, skipProjectNetworks, restartRequired,
specifyIpRanges, vpcId, tags, display), searchFilter, permittedAccounts));
//get domain level networks
if (domainId != null) {
networksToReturn.addAll(listDomainLevelNetworks(
buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, true, restartRequired,
specifyIpRanges, vpcId, tags, display), searchFilter, domainId, false));
}
} else {
//add account specific networks
networksToReturn.addAll(listAccountSpecificNetworksByDomainPath(
buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, skipProjectNetworks, restartRequired,
specifyIpRanges, vpcId, tags, display), searchFilter, path, isRecursive));
//add domain specific networks of domain + parent domains
networksToReturn.addAll(listDomainSpecificNetworksByDomainPath(
buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, skipProjectNetworks, restartRequired,
specifyIpRanges, vpcId, tags, display), searchFilter, path, isRecursive));
//add networks of subdomains
if (domainId == null) {
networksToReturn.addAll(listDomainLevelNetworks(
buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, true, restartRequired,
specifyIpRanges, vpcId, tags, display), searchFilter, caller.getDomainId(), true));
}
}
} else {
networksToReturn = _networksDao.search(
buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, null, skipProjectNetworks, restartRequired,
specifyIpRanges, vpcId, tags, display), searchFilter);
}
if (supportedServicesStr != null && !supportedServicesStr.isEmpty() && !networksToReturn.isEmpty()) {
List<NetworkVO> supportedNetworks = new ArrayList<NetworkVO>();
Service[] suppportedServices = new Service[supportedServicesStr.size()];
int i = 0;
for (String supportedServiceStr : supportedServicesStr) {
Service service = Service.getService(supportedServiceStr);
if (service == null) {
throw new InvalidParameterValueException("Invalid service specified " + supportedServiceStr);
} else {
suppportedServices[i] = service;
}
i++;
}
for (NetworkVO network : networksToReturn) {
if (areServicesSupportedInNetwork(network.getId(), suppportedServices)) {
supportedNetworks.add(network);
}
}
networksToReturn = supportedNetworks;
}
if (canUseForDeploy != null) {
List<NetworkVO> networksForDeploy = new ArrayList<NetworkVO>();
for (NetworkVO network : networksToReturn) {
if (_networkModel.canUseForDeploy(network) == canUseForDeploy) {
networksForDeploy.add(network);
}
}
networksToReturn = networksForDeploy;
}
//Now apply pagination
//Most likely pageSize will never exceed int value, and we need integer to partition the listToReturn
boolean notNull = cmd.getStartIndex() != null && cmd.getPageSizeVal() != null;
if (notNull && cmd.getStartIndex() <= Integer.MAX_VALUE && cmd.getStartIndex() >= Integer.MIN_VALUE && cmd.getPageSizeVal() <= Integer.MAX_VALUE
&& cmd.getPageSizeVal() >= Integer.MIN_VALUE) {
int index = cmd.getStartIndex().intValue() == 0 ? 0 : cmd.getStartIndex().intValue() / cmd.getPageSizeVal().intValue();
List<NetworkVO> wPagination = new ArrayList<NetworkVO>();
List<List<NetworkVO>> partitions = partitionNetworks(networksToReturn, cmd.getPageSizeVal().intValue());
if (index < partitions.size()) {
wPagination = partitions.get(index);
}
return new Pair<List<? extends Network>, Integer>(wPagination, networksToReturn.size());
}
return new Pair<List<? extends Network>, Integer>(networksToReturn, networksToReturn.size());
}
private static List<List<NetworkVO>> partitionNetworks(List<NetworkVO> originalList, int chunkSize) {
List<List<NetworkVO>> listOfChunks = new ArrayList<List<NetworkVO>>();
for (int i = 0; i < originalList.size() / chunkSize; i++) {
listOfChunks.add(originalList.subList(i * chunkSize, i * chunkSize + chunkSize));
}
if (originalList.size() % chunkSize != 0) {
listOfChunks.add(originalList.subList(originalList.size() - originalList.size() % chunkSize, originalList.size()));
}
return listOfChunks;
}
private SearchCriteria<NetworkVO> buildNetworkSearchCriteria(SearchBuilder<NetworkVO> sb, String keyword, Long id, Boolean isSystem, Long zoneId, String guestIpType,
String trafficType, Long physicalNetworkId, String aclType, boolean skipProjectNetworks, Boolean restartRequired, Boolean specifyIpRanges, Long vpcId,
Map<String, String> tags, Boolean display) {
// build network search criteria
SearchCriteria<NetworkVO> sc = sb.create();
_accountMgr.buildACLSearchCriteria(sc, isRecursive, permittedDomains, permittedAccounts, permittedResources, listProjectResourcesCriteria);
if (isSystem != null) {
sc.setJoinParameters("networkOfferingSearch", "systemOnly", isSystem);
}
@ -1671,12 +1505,6 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
sc.addAnd("physicalNetworkId", SearchCriteria.Op.EQ, physicalNetworkId);
}
if (skipProjectNetworks) {
sc.setJoinParameters("accountSearch", "typeNEQ", Account.ACCOUNT_TYPE_PROJECT);
} else {
sc.setJoinParameters("accountSearch", "typeEQ", Account.ACCOUNT_TYPE_PROJECT);
}
if (restartRequired != null) {
sc.addAnd("restartRequired", SearchCriteria.Op.EQ, restartRequired);
}
@ -1699,94 +1527,70 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
}
}
return sc;
List<NetworkVO> networksToReturn = _networksDao.search(sc, searchFilter);
// filter by supported services
if (supportedServicesStr != null && !supportedServicesStr.isEmpty() && !networksToReturn.isEmpty()) {
List<NetworkVO> supportedNetworks = new ArrayList<NetworkVO>();
Service[] suppportedServices = new Service[supportedServicesStr.size()];
int i = 0;
for (String supportedServiceStr : supportedServicesStr) {
Service service = Service.getService(supportedServiceStr);
if (service == null) {
throw new InvalidParameterValueException("Invalid service specified " + supportedServiceStr);
} else {
suppportedServices[i] = service;
}
i++;
}
for (NetworkVO network : networksToReturn) {
if (areServicesSupportedInNetwork(network.getId(), suppportedServices)) {
supportedNetworks.add(network);
}
}
networksToReturn = supportedNetworks;
}
// filter by usability to deploy
if (canUseForDeploy != null) {
List<NetworkVO> networksForDeploy = new ArrayList<NetworkVO>();
for (NetworkVO network : networksToReturn) {
if (_networkModel.canUseForDeploy(network) == canUseForDeploy) {
networksForDeploy.add(network);
}
}
networksToReturn = networksForDeploy;
}
//Now apply pagination
//Most likely pageSize will never exceed int value, and we need integer to partition the listToReturn
boolean notNull = cmd.getStartIndex() != null && cmd.getPageSizeVal() != null;
if (notNull && cmd.getStartIndex() <= Integer.MAX_VALUE && cmd.getStartIndex() >= Integer.MIN_VALUE && cmd.getPageSizeVal() <= Integer.MAX_VALUE
&& cmd.getPageSizeVal() >= Integer.MIN_VALUE) {
int index = cmd.getStartIndex().intValue() == 0 ? 0 : cmd.getStartIndex().intValue() / cmd.getPageSizeVal().intValue();
List<NetworkVO> wPagination = new ArrayList<NetworkVO>();
List<List<NetworkVO>> partitions = partitionNetworks(networksToReturn, cmd.getPageSizeVal().intValue());
if (index < partitions.size()) {
wPagination = partitions.get(index);
}
return new Pair<List<? extends Network>, Integer>(wPagination, networksToReturn.size());
}
return new Pair<List<? extends Network>, Integer>(networksToReturn, networksToReturn.size());
}
private List<NetworkVO> listDomainLevelNetworks(SearchCriteria<NetworkVO> sc, Filter searchFilter, long domainId, boolean parentDomainsOnly) {
List<Long> networkIds = new ArrayList<Long>();
Set<Long> allowedDomains = _domainMgr.getDomainParentIds(domainId);
List<NetworkDomainVO> maps = _networkDomainDao.listDomainNetworkMapByDomain(allowedDomains.toArray());
for (NetworkDomainVO map : maps) {
if (map.getDomainId() == domainId && parentDomainsOnly) {
continue;
}
boolean subdomainAccess = (map.isSubdomainAccess() != null) ? map.isSubdomainAccess() : getAllowSubdomainAccessGlobal();
if (map.getDomainId() == domainId || subdomainAccess) {
networkIds.add(map.getNetworkId());
}
private static List<List<NetworkVO>> partitionNetworks(List<NetworkVO> originalList, int chunkSize) {
List<List<NetworkVO>> listOfChunks = new ArrayList<List<NetworkVO>>();
for (int i = 0; i < originalList.size() / chunkSize; i++) {
listOfChunks.add(originalList.subList(i * chunkSize, i * chunkSize + chunkSize));
}
if (!networkIds.isEmpty()) {
SearchCriteria<NetworkVO> domainSC = _networksDao.createSearchCriteria();
domainSC.addAnd("id", SearchCriteria.Op.IN, networkIds.toArray());
domainSC.addAnd("aclType", SearchCriteria.Op.EQ, ACLType.Domain.toString());
sc.addAnd("id", SearchCriteria.Op.SC, domainSC);
return _networksDao.search(sc, searchFilter);
} else {
return new ArrayList<NetworkVO>();
}
}
private List<NetworkVO> listAccountSpecificNetworks(SearchCriteria<NetworkVO> sc, Filter searchFilter, List<Long> permittedAccounts) {
SearchCriteria<NetworkVO> accountSC = _networksDao.createSearchCriteria();
if (!permittedAccounts.isEmpty()) {
accountSC.addAnd("accountId", SearchCriteria.Op.IN, permittedAccounts.toArray());
}
accountSC.addAnd("aclType", SearchCriteria.Op.EQ, ACLType.Account.toString());
sc.addAnd("id", SearchCriteria.Op.SC, accountSC);
return _networksDao.search(sc, searchFilter);
}
private List<NetworkVO> listAccountSpecificNetworksByDomainPath(SearchCriteria<NetworkVO> sc, Filter searchFilter, String path, boolean isRecursive) {
SearchCriteria<NetworkVO> accountSC = _networksDao.createSearchCriteria();
accountSC.addAnd("aclType", SearchCriteria.Op.EQ, ACLType.Account.toString());
if (path != null) {
if (isRecursive) {
sc.setJoinParameters("domainSearch", "path", path + "%");
} else {
sc.setJoinParameters("domainSearch", "path", path);
}
}
sc.addAnd("id", SearchCriteria.Op.SC, accountSC);
return _networksDao.search(sc, searchFilter);
}
private List<NetworkVO> listDomainSpecificNetworksByDomainPath(SearchCriteria<NetworkVO> sc, Filter searchFilter, String path, boolean isRecursive) {
Set<Long> allowedDomains = new HashSet<Long>();
if (path != null) {
if (isRecursive) {
allowedDomains = _domainMgr.getDomainChildrenIds(path);
} else {
Domain domain = _domainDao.findDomainByPath(path);
allowedDomains.add(domain.getId());
}
}
List<Long> networkIds = new ArrayList<Long>();
List<NetworkDomainVO> maps = _networkDomainDao.listDomainNetworkMapByDomain(allowedDomains.toArray());
for (NetworkDomainVO map : maps) {
networkIds.add(map.getNetworkId());
}
if (!networkIds.isEmpty()) {
SearchCriteria<NetworkVO> domainSC = _networksDao.createSearchCriteria();
domainSC.addAnd("id", SearchCriteria.Op.IN, networkIds.toArray());
domainSC.addAnd("aclType", SearchCriteria.Op.EQ, ACLType.Domain.toString());
sc.addAnd("id", SearchCriteria.Op.SC, domainSC);
return _networksDao.search(sc, searchFilter);
} else {
return new ArrayList<NetworkVO>();
if (originalList.size() % chunkSize != 0) {
listOfChunks.add(originalList.subList(originalList.size() - originalList.size() % chunkSize, originalList.size()));
}
return listOfChunks;
}
@Override