This is an automated email from the ASF dual-hosted git repository. rohit pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/master by this push: new 5fad841 CLOUDSTACK-10104: Optimize database transactions in ListDomain API to improve performance (#2282) 5fad841 is described below commit 5fad84174a199f798396fcacedae2c56bdcc2bba Author: PranaliM <pranali_ma...@accelerite.com> AuthorDate: Fri Jan 5 21:51:46 2018 +0530 CLOUDSTACK-10104: Optimize database transactions in ListDomain API to improve performance (#2282) While creating the response object for the 'listDomain' API, several database calls are triggered to fetch details like parent domain, project limit, IP limit, etc. These database calls are triggered for each record found in the main fetch query, which is causing the response to slow down. Fix: The database transactions are reduced to improve response of the Listdomain API --- api/src/com/cloud/user/ResourceLimitService.java | 8 + server/src/com/cloud/api/ApiDBUtils.java | 13 ++ .../src/com/cloud/api/query/QueryManagerImpl.java | 11 +- .../com/cloud/api/query/ViewResponseHelper.java | 161 ++++++++++++++++++++- .../com/cloud/api/query/dao/DomainJoinDaoImpl.java | 29 ++-- .../src/com/cloud/api/query/vo/DomainJoinVO.java | 37 +++++ .../resourcelimit/ResourceLimitManagerImpl.java | 11 ++ .../cloud/vpc/MockResourceLimitManagerImpl.java | 5 + test/integration/smoke/test_accounts.py | 90 +++++++++++- 9 files changed, 341 insertions(+), 24 deletions(-) diff --git a/api/src/com/cloud/user/ResourceLimitService.java b/api/src/com/cloud/user/ResourceLimitService.java index 901fa06..52e0356 100644 --- a/api/src/com/cloud/user/ResourceLimitService.java +++ b/api/src/com/cloud/user/ResourceLimitService.java @@ -105,6 +105,14 @@ public interface ResourceLimitService { public long findCorrectResourceLimitForDomain(Domain domain, ResourceType type); /** + * Finds the default resource limit for a specified type. + * + * @param resourceType + * @return resource limit + */ + public long findDefaultResourceLimitForDomain(ResourceType resourceType); + + /** * Increments the resource count * * @param accountId diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java index 9f67aa7..22ed243 100644 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -867,6 +867,15 @@ public class ApiDBUtils { return s_resourceLimitMgr.findCorrectResourceLimitForAccount(accountId, limit, type); } + public static long findCorrectResourceLimitForDomain(Long limit, ResourceType resourceType, long domainId) { + //-- No limits for Root domain + if (domainId == Domain.ROOT_DOMAIN) { + return Resource.RESOURCE_UNLIMITED; + } + //--If limit doesn't have a value then fetch default limit from the configs + return (limit == null) ? s_resourceLimitMgr.findDefaultResourceLimitForDomain(resourceType) : limit; + } + public static long getResourceCount(ResourceType type, long accountId) { AccountVO account = s_accountDao.findById(accountId); @@ -981,6 +990,10 @@ public class ApiDBUtils { return s_domainDao.findByIdIncludingRemoved(domainId); } + public static DomainJoinVO findDomainJoinVOById(Long domainId) { + return s_domainJoinDao.findByIdIncludingRemoved(domainId); + } + public static DomainVO findDomainByIdIncludingRemoved(Long domainId) { return s_domainDao.findByIdIncludingRemoved(domainId); } diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index efe31cb..4203455 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -1890,8 +1890,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q respView = ResponseView.Full; } - List<DomainResponse> domainResponses = ViewResponseHelper.createDomainResponse(respView, cmd.getDetails(), result.first().toArray( - new DomainJoinVO[result.first().size()])); + List<DomainResponse> domainResponses = ViewResponseHelper.createDomainResponse(respView, cmd.getDetails(), result.first()); response.setResponses(domainResponses, result.second()); return response; } @@ -1901,9 +1900,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Long domainId = cmd.getId(); boolean listAll = cmd.listAll(); boolean isRecursive = false; + Domain domain = null; if (domainId != null) { - Domain domain = _domainDao.findById(domainId); + domain = _domainDao.findById(domainId); if (domain == null) { throw new InvalidParameterValueException("Domain id=" + domainId + " doesn't exist"); } @@ -1947,7 +1947,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q if (domainId != null) { if (isRecursive) { - sc.setParameters("path", _domainDao.findById(domainId).getPath() + "%"); + if(domain == null){ + domain = _domainDao.findById(domainId); + } + sc.setParameters("path", domain.getPath() + "%"); } else { sc.setParameters("id", domainId); } diff --git a/server/src/com/cloud/api/query/ViewResponseHelper.java b/server/src/com/cloud/api/query/ViewResponseHelper.java index 11af5a9..940ae28 100644 --- a/server/src/com/cloud/api/query/ViewResponseHelper.java +++ b/server/src/com/cloud/api/query/ViewResponseHelper.java @@ -18,11 +18,16 @@ package com.cloud.api.query; import java.text.DecimalFormat; import java.util.ArrayList; +import java.util.Collections; import java.util.EnumSet; +import java.util.HashMap; import java.util.Hashtable; import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; +import com.cloud.configuration.Resource; +import com.cloud.domain.Domain; import org.apache.log4j.Logger; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.ApiConstants.DomainDetails; @@ -375,14 +380,164 @@ public class ViewResponseHelper { return new ArrayList<StoragePoolResponse>(vrDataList.values()); } - public static List<DomainResponse> createDomainResponse(ResponseView view, EnumSet<DomainDetails> details, DomainJoinVO... domains) { + public static List<DomainResponse> createDomainResponse(ResponseView view, EnumSet<DomainDetails> details, List<DomainJoinVO> domains) { List<DomainResponse> respList = new ArrayList<DomainResponse>(); - for (DomainJoinVO vt : domains){ - respList.add(ApiDBUtils.newDomainResponse(view, details, vt)); + //-- Coping the list to keep original order + List<DomainJoinVO> domainsCopy = new ArrayList<>(domains); + Collections.sort(domainsCopy, DomainJoinVO.domainIdComparator); + for (DomainJoinVO domainJoinVO : domains){ + //-- Set parent information + DomainJoinVO parentDomainJoinVO = searchParentDomainUsingBinary(domainsCopy, domainJoinVO); + if(parentDomainJoinVO == null && domainJoinVO.getParent() != null) { + //-- fetch the parent from the database + parentDomainJoinVO = ApiDBUtils.findDomainJoinVOById(domainJoinVO.getParent()); + if(parentDomainJoinVO != null) { + //-- Add parent domain to the domain copy for future use + domainsCopy.add(parentDomainJoinVO); + Collections.sort(domainsCopy, DomainJoinVO.domainIdComparator); + } + } + if(parentDomainJoinVO != null) { + domainJoinVO.setParentName(parentDomainJoinVO.getName()); + domainJoinVO.setParentUuid(parentDomainJoinVO.getUuid()); + } + //-- Set correct resource limits + if(domainJoinVO.getParent() != null && domainJoinVO.getParent() != Domain.ROOT_DOMAIN) { + Map<Resource.ResourceType, Long> resourceLimitMap = new HashMap<>(); + copyResourceLimitsIntoMap(resourceLimitMap, domainJoinVO); + //-- Fetching the parent domain resource limit if absent in current domain + setParentResourceLimitIfNeeded(resourceLimitMap, domainJoinVO, domainsCopy); + //-- copy the final correct resource limit + copyResourceLimitsFromMap(resourceLimitMap, domainJoinVO); + } + respList.add(ApiDBUtils.newDomainResponse(view, details, domainJoinVO)); } return respList; } + private static DomainJoinVO searchParentDomainUsingBinary(List<DomainJoinVO> domainsCopy, DomainJoinVO domainJoinVO){ + Long parentId = domainJoinVO.getParent() == null ? 0 : domainJoinVO.getParent(); + int totalDomains = domainsCopy.size(); + int left = 0; + int right = totalDomains -1; + while(left <= right){ + int middle = (left + right) /2; + DomainJoinVO middleObject = domainsCopy.get(middle); + if(middleObject.getId() == parentId){ + return middleObject; + } + if(middleObject.getId() > parentId){ + right = middle - 1 ; + } + else{ + left = middle + 1; + } + } + return null; + } + + private static void copyResourceLimitsIntoMap(Map<Resource.ResourceType, Long> resourceLimitMap, DomainJoinVO domainJoinVO){ + resourceLimitMap.put(Resource.ResourceType.user_vm, domainJoinVO.getVmLimit()); + resourceLimitMap.put(Resource.ResourceType.public_ip, domainJoinVO.getIpLimit()); + resourceLimitMap.put(Resource.ResourceType.volume, domainJoinVO.getVolumeLimit()); + resourceLimitMap.put(Resource.ResourceType.snapshot, domainJoinVO.getSnapshotLimit()); + resourceLimitMap.put(Resource.ResourceType.template, domainJoinVO.getTemplateLimit()); + resourceLimitMap.put(Resource.ResourceType.network, domainJoinVO.getNetworkLimit()); + resourceLimitMap.put(Resource.ResourceType.vpc, domainJoinVO.getVpcLimit()); + resourceLimitMap.put(Resource.ResourceType.cpu, domainJoinVO.getCpuLimit()); + resourceLimitMap.put(Resource.ResourceType.memory, domainJoinVO.getMemoryLimit()); + resourceLimitMap.put(Resource.ResourceType.primary_storage, domainJoinVO.getPrimaryStorageLimit()); + resourceLimitMap.put(Resource.ResourceType.secondary_storage, domainJoinVO.getSecondaryStorageLimit()); + resourceLimitMap.put(Resource.ResourceType.project, domainJoinVO.getProjectLimit()); + } + + private static void copyResourceLimitsFromMap(Map<Resource.ResourceType, Long> resourceLimitMap, DomainJoinVO domainJoinVO){ + domainJoinVO.setVmLimit(resourceLimitMap.get(Resource.ResourceType.user_vm)); + domainJoinVO.setIpLimit(resourceLimitMap.get(Resource.ResourceType.public_ip)); + domainJoinVO.setVolumeLimit(resourceLimitMap.get(Resource.ResourceType.volume)); + domainJoinVO.setSnapshotLimit(resourceLimitMap.get(Resource.ResourceType.snapshot)); + domainJoinVO.setTemplateLimit(resourceLimitMap.get(Resource.ResourceType.template)); + domainJoinVO.setNetworkLimit(resourceLimitMap.get(Resource.ResourceType.network)); + domainJoinVO.setVpcLimit(resourceLimitMap.get(Resource.ResourceType.vpc)); + domainJoinVO.setCpuLimit(resourceLimitMap.get(Resource.ResourceType.cpu)); + domainJoinVO.setMemoryLimit(resourceLimitMap.get(Resource.ResourceType.memory)); + domainJoinVO.setPrimaryStorageLimit(resourceLimitMap.get(Resource.ResourceType.primary_storage)); + domainJoinVO.setSecondaryStorageLimit(resourceLimitMap.get(Resource.ResourceType.secondary_storage)); + domainJoinVO.setProjectLimit(resourceLimitMap.get(Resource.ResourceType.project)); + } + + private static void setParentResourceLimitIfNeeded(Map<Resource.ResourceType, Long> resourceLimitMap, DomainJoinVO domainJoinVO, List<DomainJoinVO> domainsCopy) { + DomainJoinVO parentDomainJoinVO = searchParentDomainUsingBinary(domainsCopy, domainJoinVO); + + if(parentDomainJoinVO != null) { + Long vmLimit = resourceLimitMap.get(Resource.ResourceType.user_vm); + Long ipLimit = resourceLimitMap.get(Resource.ResourceType.public_ip); + Long volumeLimit = resourceLimitMap.get(Resource.ResourceType.volume); + Long snapshotLimit = resourceLimitMap.get(Resource.ResourceType.snapshot); + Long templateLimit = resourceLimitMap.get(Resource.ResourceType.template); + Long networkLimit = resourceLimitMap.get(Resource.ResourceType.network); + Long vpcLimit = resourceLimitMap.get(Resource.ResourceType.vpc); + Long cpuLimit = resourceLimitMap.get(Resource.ResourceType.cpu); + Long memoryLimit = resourceLimitMap.get(Resource.ResourceType.memory); + Long primaryStorageLimit = resourceLimitMap.get(Resource.ResourceType.primary_storage); + Long secondaryStorageLimit = resourceLimitMap.get(Resource.ResourceType.secondary_storage); + Long projectLimit = resourceLimitMap.get(Resource.ResourceType.project); + + if (vmLimit == null) { + vmLimit = parentDomainJoinVO.getVmLimit(); + resourceLimitMap.put(Resource.ResourceType.user_vm, vmLimit); + } + if (ipLimit == null) { + ipLimit = parentDomainJoinVO.getIpLimit(); + resourceLimitMap.put(Resource.ResourceType.public_ip, ipLimit); + } + if (volumeLimit == null) { + volumeLimit = parentDomainJoinVO.getVolumeLimit(); + resourceLimitMap.put(Resource.ResourceType.volume, volumeLimit); + } + if (snapshotLimit == null) { + snapshotLimit = parentDomainJoinVO.getSnapshotLimit(); + resourceLimitMap.put(Resource.ResourceType.snapshot, snapshotLimit); + } + if (templateLimit == null) { + templateLimit = parentDomainJoinVO.getTemplateLimit(); + resourceLimitMap.put(Resource.ResourceType.template, templateLimit); + } + if (networkLimit == null) { + networkLimit = parentDomainJoinVO.getNetworkLimit(); + resourceLimitMap.put(Resource.ResourceType.network, networkLimit); + } + if (vpcLimit == null) { + vpcLimit = parentDomainJoinVO.getVpcLimit(); + resourceLimitMap.put(Resource.ResourceType.vpc, vpcLimit); + } + if (cpuLimit == null) { + cpuLimit = parentDomainJoinVO.getCpuLimit(); + resourceLimitMap.put(Resource.ResourceType.cpu, cpuLimit); + } + if (memoryLimit == null) { + memoryLimit = parentDomainJoinVO.getMemoryLimit(); + resourceLimitMap.put(Resource.ResourceType.memory, memoryLimit); + } + if (primaryStorageLimit == null) { + primaryStorageLimit = parentDomainJoinVO.getPrimaryStorageLimit(); + resourceLimitMap.put(Resource.ResourceType.primary_storage, primaryStorageLimit); + } + if (secondaryStorageLimit == null) { + secondaryStorageLimit = parentDomainJoinVO.getSecondaryStorageLimit(); + resourceLimitMap.put(Resource.ResourceType.secondary_storage, secondaryStorageLimit); + } + if (projectLimit == null) { + projectLimit = parentDomainJoinVO.getProjectLimit(); + resourceLimitMap.put(Resource.ResourceType.project, projectLimit); + } + //-- try till parent present + if (parentDomainJoinVO.getParent() != null && parentDomainJoinVO.getParent() != Domain.ROOT_DOMAIN) { + setParentResourceLimitIfNeeded(resourceLimitMap, parentDomainJoinVO, domainsCopy); + } + } + } + public static List<AccountResponse> createAccountResponse(ResponseView view, AccountJoinVO... accounts) { List<AccountResponse> respList = new ArrayList<AccountResponse>(); for (AccountJoinVO vt : accounts){ diff --git a/server/src/com/cloud/api/query/dao/DomainJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/DomainJoinDaoImpl.java index 1f123cd..497fc2c 100644 --- a/server/src/com/cloud/api/query/dao/DomainJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/DomainJoinDaoImpl.java @@ -57,15 +57,14 @@ public class DomainJoinDaoImpl extends GenericDaoBase<DomainJoinVO, Long> implem domainResponse.setId(domain.getUuid()); domainResponse.setLevel(domain.getLevel()); domainResponse.setNetworkDomain(domain.getNetworkDomain()); - Domain parentDomain = ApiDBUtils.findDomainById(domain.getParent()); - if (parentDomain != null) { - domainResponse.setParentDomainId(parentDomain.getUuid()); + if (domain.getParentUuid() != null) { + domainResponse.setParentDomainId(domain.getParentUuid()); } StringBuilder domainPath = new StringBuilder("ROOT"); (domainPath.append(domain.getPath())).deleteCharAt(domainPath.length() - 1); domainResponse.setPath(domainPath.toString()); if (domain.getParent() != null) { - domainResponse.setParentDomainName(ApiDBUtils.findDomainById(domain.getParent()).getName()); + domainResponse.setParentDomainName(domain.getParentName()); } if (domain.getChildCount() > 0) { domainResponse.setHasChild(true); @@ -79,7 +78,7 @@ public class DomainJoinDaoImpl extends GenericDaoBase<DomainJoinVO, Long> implem setResourceLimits(domain, fullView, domainResponse); //get resource limits for projects - long projectLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getProjectLimit(), fullView, ResourceType.project, domain.getId()); + long projectLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getProjectLimit(), ResourceType.project, domain.getId()); String projectLimitDisplay = (fullView || projectLimit == -1) ? "Unlimited" : String.valueOf(projectLimit); long projectTotal = (domain.getProjectTotal() == null) ? 0 : domain.getProjectTotal(); String projectAvail = (fullView || projectLimit == -1) ? "Unlimited" : String.valueOf(projectLimit - projectTotal); @@ -104,7 +103,7 @@ public class DomainJoinDaoImpl extends GenericDaoBase<DomainJoinVO, Long> implem response.setVmTotal(vmTotal); response.setVmAvailable(vmAvail); - long ipLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getIpLimit(), fullView, ResourceType.public_ip, domain.getId()); + long ipLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getIpLimit(), ResourceType.public_ip, domain.getId()); String ipLimitDisplay = (fullView || ipLimit == -1) ? "Unlimited" : String.valueOf(ipLimit); long ipTotal = (domain.getIpTotal() == null) ? 0 : domain.getIpTotal(); String ipAvail = ((fullView || ipLimit == -1)) ? "Unlimited" : String.valueOf(ipLimit - ipTotal); @@ -112,7 +111,7 @@ public class DomainJoinDaoImpl extends GenericDaoBase<DomainJoinVO, Long> implem response.setIpTotal(ipTotal); response.setIpAvailable(ipAvail); - long volumeLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getVolumeLimit(), fullView, ResourceType.volume, domain.getId()); + long volumeLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getVolumeLimit(), ResourceType.volume, domain.getId()); String volumeLimitDisplay = (fullView || volumeLimit == -1) ? "Unlimited" : String.valueOf(volumeLimit); long volumeTotal = (domain.getVolumeTotal() == null) ? 0 : domain.getVolumeTotal(); String volumeAvail = (fullView || volumeLimit == -1) ? "Unlimited" : String.valueOf(volumeLimit - volumeTotal); @@ -120,7 +119,7 @@ public class DomainJoinDaoImpl extends GenericDaoBase<DomainJoinVO, Long> implem response.setVolumeTotal(volumeTotal); response.setVolumeAvailable(volumeAvail); - long snapshotLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getSnapshotLimit(), fullView, ResourceType.snapshot, domain.getId()); + long snapshotLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getSnapshotLimit(), ResourceType.snapshot, domain.getId()); String snapshotLimitDisplay = (fullView || snapshotLimit == -1) ? "Unlimited" : String.valueOf(snapshotLimit); long snapshotTotal = (domain.getSnapshotTotal() == null) ? 0 : domain.getSnapshotTotal(); String snapshotAvail = (fullView || snapshotLimit == -1) ? "Unlimited" : String.valueOf(snapshotLimit - snapshotTotal); @@ -128,7 +127,7 @@ public class DomainJoinDaoImpl extends GenericDaoBase<DomainJoinVO, Long> implem response.setSnapshotTotal(snapshotTotal); response.setSnapshotAvailable(snapshotAvail); - Long templateLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getTemplateLimit(), fullView, ResourceType.template, domain.getId()); + Long templateLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getTemplateLimit(), ResourceType.template, domain.getId()); String templateLimitDisplay = (fullView || templateLimit == -1) ? "Unlimited" : String.valueOf(templateLimit); Long templateTotal = (domain.getTemplateTotal() == null) ? 0 : domain.getTemplateTotal(); String templateAvail = (fullView || templateLimit == -1) ? "Unlimited" : String.valueOf(templateLimit - templateTotal); @@ -137,7 +136,7 @@ public class DomainJoinDaoImpl extends GenericDaoBase<DomainJoinVO, Long> implem response.setTemplateAvailable(templateAvail); //get resource limits for networks - long networkLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getNetworkLimit(), fullView, ResourceType.network, domain.getId()); + long networkLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getNetworkLimit(), ResourceType.network, domain.getId()); String networkLimitDisplay = (fullView || networkLimit == -1) ? "Unlimited" : String.valueOf(networkLimit); long networkTotal = (domain.getNetworkTotal() == null) ? 0 : domain.getNetworkTotal(); String networkAvail = (fullView || networkLimit == -1) ? "Unlimited" : String.valueOf(networkLimit - networkTotal); @@ -146,7 +145,7 @@ public class DomainJoinDaoImpl extends GenericDaoBase<DomainJoinVO, Long> implem response.setNetworkAvailable(networkAvail); //get resource limits for vpcs - long vpcLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getVpcLimit(), fullView, ResourceType.vpc, domain.getId()); + long vpcLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getVpcLimit(), ResourceType.vpc, domain.getId()); String vpcLimitDisplay = (fullView || vpcLimit == -1) ? "Unlimited" : String.valueOf(vpcLimit); long vpcTotal = (domain.getVpcTotal() == null) ? 0 : domain.getVpcTotal(); String vpcAvail = (fullView || vpcLimit == -1) ? "Unlimited" : String.valueOf(vpcLimit - vpcTotal); @@ -155,7 +154,7 @@ public class DomainJoinDaoImpl extends GenericDaoBase<DomainJoinVO, Long> implem response.setVpcAvailable(vpcAvail); //get resource limits for cpu cores - long cpuLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getCpuLimit(), fullView, ResourceType.cpu, domain.getId()); + long cpuLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getCpuLimit(), ResourceType.cpu, domain.getId()); String cpuLimitDisplay = (fullView || cpuLimit == -1) ? "Unlimited" : String.valueOf(cpuLimit); long cpuTotal = (domain.getCpuTotal() == null) ? 0 : domain.getCpuTotal(); String cpuAvail = (fullView || cpuLimit == -1) ? "Unlimited" : String.valueOf(cpuLimit - cpuTotal); @@ -164,7 +163,7 @@ public class DomainJoinDaoImpl extends GenericDaoBase<DomainJoinVO, Long> implem response.setCpuAvailable(cpuAvail); //get resource limits for memory - long memoryLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getMemoryLimit(), fullView, ResourceType.memory, domain.getId()); + long memoryLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getMemoryLimit(), ResourceType.memory, domain.getId()); String memoryLimitDisplay = (fullView || memoryLimit == -1) ? "Unlimited" : String.valueOf(memoryLimit); long memoryTotal = (domain.getMemoryTotal() == null) ? 0 : domain.getMemoryTotal(); String memoryAvail = (fullView || memoryLimit == -1) ? "Unlimited" : String.valueOf(memoryLimit - memoryTotal); @@ -173,7 +172,7 @@ public class DomainJoinDaoImpl extends GenericDaoBase<DomainJoinVO, Long> implem response.setMemoryAvailable(memoryAvail); //get resource limits for primary storage space and convert it from Bytes to GiB - long primaryStorageLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getPrimaryStorageLimit(), fullView, ResourceType.primary_storage, domain.getId()); + long primaryStorageLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getPrimaryStorageLimit(), ResourceType.primary_storage, domain.getId()); String primaryStorageLimitDisplay = (fullView || primaryStorageLimit == -1) ? "Unlimited" : String.valueOf(primaryStorageLimit / ResourceType.bytesToGiB); long primaryStorageTotal = (domain.getPrimaryStorageTotal() == null) ? 0 : (domain.getPrimaryStorageTotal() / ResourceType.bytesToGiB); String primaryStorageAvail = (fullView || primaryStorageLimit == -1) ? "Unlimited" : String.valueOf((primaryStorageLimit / ResourceType.bytesToGiB) - primaryStorageTotal); @@ -182,7 +181,7 @@ public class DomainJoinDaoImpl extends GenericDaoBase<DomainJoinVO, Long> implem response.setPrimaryStorageAvailable(primaryStorageAvail); //get resource limits for secondary storage space and convert it from Bytes to GiB - long secondaryStorageLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getSecondaryStorageLimit(), fullView, ResourceType.secondary_storage, domain.getId()); + long secondaryStorageLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getSecondaryStorageLimit(), ResourceType.secondary_storage, domain.getId()); String secondaryStorageLimitDisplay = (fullView || secondaryStorageLimit == -1) ? "Unlimited" : String.valueOf(secondaryStorageLimit / ResourceType.bytesToGiB); long secondaryStorageTotal = (domain.getSecondaryStorageTotal() == null) ? 0 : (domain.getSecondaryStorageTotal() / ResourceType.bytesToGiB); String secondaryStorageAvail = (fullView || secondaryStorageLimit == -1) ? "Unlimited" : String.valueOf((secondaryStorageLimit / ResourceType.bytesToGiB) - secondaryStorageTotal); diff --git a/server/src/com/cloud/api/query/vo/DomainJoinVO.java b/server/src/com/cloud/api/query/vo/DomainJoinVO.java index a7c4560..6f4d6b7 100644 --- a/server/src/com/cloud/api/query/vo/DomainJoinVO.java +++ b/server/src/com/cloud/api/query/vo/DomainJoinVO.java @@ -16,11 +16,13 @@ // under the License. package com.cloud.api.query.vo; +import java.util.Comparator; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; +import javax.persistence.Transient; import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; @@ -149,6 +151,12 @@ public class DomainJoinVO extends BaseViewVO implements InternalIdentity, Identi @Column(name="secondaryStorageTotal") private Long secondaryStorageTotal; + @Transient + private String parentName; + + @Transient + private String parentUuid; + public DomainJoinVO() { } @@ -498,4 +506,33 @@ public class DomainJoinVO extends BaseViewVO implements InternalIdentity, Identi this.secondaryStorageLimit = secondaryStorageLimit; } + public String getParentName() { + return parentName; + } + + public void setParentName(String parentName) { + this.parentName = parentName; + } + + public String getParentUuid() { + return parentUuid; + } + + public void setParentUuid(String parentUuid) { + this.parentUuid = parentUuid; + } + + public static Comparator<DomainJoinVO> domainIdComparator + = new Comparator<DomainJoinVO>() { + + public int compare(DomainJoinVO domainJoinVO1, DomainJoinVO domainJoinVO2) { + + Long domainId1 = domainJoinVO1.getId(); + Long domainId2 = domainJoinVO2.getId(); + + //-- ascending order + return domainId1.compareTo(domainId2); + } + + }; } diff --git a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java index 908483a..a187929 100644 --- a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java +++ b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java @@ -410,6 +410,17 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim return max; } + public long findDefaultResourceLimitForDomain(ResourceType resourceType) { + Long resourceLimit = null; + resourceLimit = domainResourceLimitMap.get(resourceType); + if (resourceLimit != null && (resourceType == ResourceType.primary_storage || resourceType == ResourceType.secondary_storage)) { + resourceLimit = resourceLimit * ResourceType.bytesToGiB; + } else { + resourceLimit = Long.valueOf(Resource.RESOURCE_UNLIMITED); + } + return resourceLimit; + } + @Override @DB public void checkResourceLimit(final Account account, final ResourceType type, long... count) throws ResourceAllocationException { diff --git a/server/test/com/cloud/vpc/MockResourceLimitManagerImpl.java b/server/test/com/cloud/vpc/MockResourceLimitManagerImpl.java index 0be5b1b..8ad08ee 100644 --- a/server/test/com/cloud/vpc/MockResourceLimitManagerImpl.java +++ b/server/test/com/cloud/vpc/MockResourceLimitManagerImpl.java @@ -86,6 +86,11 @@ public class MockResourceLimitManagerImpl extends ManagerBase implements Resourc return 0; } + @Override + public long findDefaultResourceLimitForDomain(ResourceType resourceType) { + return 0; + } + /* (non-Javadoc) * @see com.cloud.user.ResourceLimitService#incrementResourceCount(long, com.cloud.configuration.Resource.ResourceType, java.lang.Long[]) */ diff --git a/test/integration/smoke/test_accounts.py b/test/integration/smoke/test_accounts.py index dffb00a..08fa813 100644 --- a/test/integration/smoke/test_accounts.py +++ b/test/integration/smoke/test_accounts.py @@ -19,7 +19,8 @@ # Import Local Modules from marvin.cloudstackTestCase import cloudstackTestCase from marvin.lib.utils import (random_gen, - cleanup_resources) + cleanup_resources, + validateList) from marvin.cloudstackAPI import * from marvin.lib.base import (Domain, Account, @@ -42,11 +43,11 @@ from marvin.lib.common import (get_domain, wait_for_cleanup) from nose.plugins.attrib import attr from marvin.cloudstackException import CloudstackAPIException +from marvin.codes import PASS import time from pyVmomi.VmomiSupport import GetVersionFromVersionUri - class Services: """Test Account Services @@ -1470,6 +1471,91 @@ class TestUserLogin(cloudstackTestCase): ) return + @attr(tags=["simulator", "advanced", + "advancedns", "basic", "eip", "sg"]) + def test_ApiListDomain(self): + """Test case to check the correctness of List domain API, to make sure that no field is missed in the output. + """ + + # Steps for test scenario + # 1. create a domain + # 2. Create a sub-domain with domain created in step 1 as parent. + # Validate the following + # 1. listDomains returns created domain and sub-domain + # 2. The list Domain response has all the expected 44 elements/fields in it. + + listDomainResponseElements = ["id", "name", "level", "parentdomainid", "parentdomainname", "haschild", "path", + "state", + "vmlimit", "vmtotal", "vmavailable", "iplimit", "iptotal", "ipavailable", + "volumelimit", + "volumetotal", "volumeavailable", "snapshotlimit", "snapshottotal", + "snapshotavailable", + "templatelimit", "templatetotal", "templateavailable", "projectlimit", + "projecttotal", "projectavailable", + "networklimit", "networktotal", "networkavailable", "vpclimit", "vpctotal", + "vpcavailable", + "cpulimit", "cputotal", "cpuavailable", "memorylimit", "memorytotal", + "memoryavailable", "primarystoragelimit", + "primarystoragetotal", "primarystorageavailable", "secondarystoragelimit", + "secondarystoragetotal", "secondarystorageavailable" + ] + + self.debug("Creating a domain for testing list domain reponse") + domain = Domain.create( + self.apiclient, + self.services["domain"], + parentdomainid=self.domain.id + ) + + self.debug("Domain: %s is created successfully." % domain.name) + + self.debug("Validating the created domain") + list_domain = Domain.list(self.api_client, id=domain.id) + domain_list_validation_result = validateList(list_domain) + + self.assertEqual(domain_list_validation_result[0], PASS, + "Domain list validation failed due to %s" % + domain_list_validation_result[2]) + + subDomain = Domain.create( + self.apiclient, + self.services["domain"], + parentdomainid=domain.id + ) + + self.debug("Sub-Domain: %s is created successfully." % subDomain.name) + + self.cleanup.append(subDomain) + self.cleanup.append(domain) + + self.debug("Validating the created sub-domain") + list_sub_domain = Domain.list(self.api_client, id=subDomain.id) + subdomain_list_validation_result = validateList(list_sub_domain) + + self.assertEqual(subdomain_list_validation_result[0], PASS, + "Sub-Domain list validation failed due to %s" % + subdomain_list_validation_result[2]) + + self.debug("Checking that the listDomain response has all the elements.") + + domainOutputString = list_domain[0].__dict__ + + for element in listDomainResponseElements: + self.assertTrue((element.lower() in domainOutputString), element + " field is missing in list domain rsponse.") + + self.debug("Verified that the listDomain response has all the elements.") + + self.debug("Checking that the list sub-domain response has all the elements.") + + subdomainOutputString = list_sub_domain[0].__dict__ + + for element in listDomainResponseElements: + self.assertTrue((element.lower() in subdomainOutputString), element + " field is missing in list domain rsponse.") + + self.debug("Verified that the list sub-Domain response has all the elements.") + + return + @attr(tags=["login", "accounts", "simulator", "advanced", "advancedns", "basic", "eip", "sg"]) def test_LoginApiDomain(self): -- To stop receiving notification emails like this one, please contact ['"commits@cloudstack.apache.org" <commits@cloudstack.apache.org>'].