server: fix listing resource limits (#12188)

This commit is contained in:
Abhishek Kumar 2026-01-29 17:06:16 +05:30 committed by GitHub
parent d700e2db64
commit 3626c515e8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 96 additions and 45 deletions

View File

@ -21,6 +21,7 @@ import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@ -36,9 +37,6 @@ import java.util.stream.Stream;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.event.ActionEventUtils;
import com.cloud.event.EventTypes;
import com.cloud.utils.Ternary;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.response.AccountResponse;
@ -86,6 +84,8 @@ import com.cloud.dc.dao.VlanDao;
import com.cloud.domain.Domain;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEventUtils;
import com.cloud.event.EventTypes;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
@ -118,6 +118,7 @@ import com.cloud.user.AccountVO;
import com.cloud.user.ResourceLimitService;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
@ -804,45 +805,46 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
limits.addAll(foundLimits);
}
} else {
limits.addAll(foundLimits);
// see if any limits are missing from the table, and if yes - get it from the config table and add
ResourceType[] resourceTypes = ResourceCount.ResourceType.values();
if (foundLimits.size() != resourceTypes.length) {
List<String> accountLimitStr = new ArrayList<>();
List<String> domainLimitStr = new ArrayList<>();
for (ResourceLimitVO foundLimit : foundLimits) {
if (foundLimit.getAccountId() != null) {
accountLimitStr.add(foundLimit.getType().toString());
} else {
domainLimitStr.add(foundLimit.getType().toString());
}
}
// get default from config values
if (isAccount) {
if (accountLimitStr.size() < resourceTypes.length) {
for (ResourceType rt : resourceTypes) {
if (!accountLimitStr.contains(rt.toString())) {
limits.add(new ResourceLimitVO(rt, findCorrectResourceLimitForAccount(_accountMgr.getAccount(accountId), rt, null), accountId, ResourceOwnerType.Account));
}
}
}
} else {
if (domainLimitStr.size() < resourceTypes.length) {
for (ResourceType rt : resourceTypes) {
if (!domainLimitStr.contains(rt.toString())) {
limits.add(new ResourceLimitVO(rt, findCorrectResourceLimitForDomain(_domainDao.findById(domainId), rt, null), domainId, ResourceOwnerType.Domain));
}
}
}
}
}
limits = getConsolidatedResourceLimitsForAllResourceTypes(accountId, domainId, foundLimits, isAccount);
}
addTaggedResourceLimits(limits, resourceType, isAccount ? ResourceOwnerType.Account : ResourceOwnerType.Domain, isAccount ? accountId : domainId, hostTags, storageTags);
return limits;
}
protected List<ResourceLimitVO> getConsolidatedResourceLimitsForAllResourceTypes(Long accountId, Long domainId,
List<ResourceLimitVO> foundLimits, boolean isAccount) {
List<ResourceLimitVO> limits = new ArrayList<>(foundLimits);
Set<ResourceType> allResourceTypes = EnumSet.allOf(ResourceType.class);
Set<ResourceType> foundUntaggedTypes = foundLimits.stream()
.filter(l -> StringUtils.isEmpty(l.getTag()))
.map(ResourceLimitVO::getType)
.collect(Collectors.toSet());
if (foundUntaggedTypes.containsAll(allResourceTypes)) {
return limits;
}
ResourceOwnerType ownerType = isAccount ? ResourceOwnerType.Account : ResourceOwnerType.Domain;
long ownerId = isAccount ? accountId : domainId;
for (ResourceType rt : allResourceTypes) {
if (foundUntaggedTypes.contains(rt)) {
continue;
}
long max;
if (isAccount) {
Account acct = _accountMgr.getAccount(accountId);
max = findCorrectResourceLimitForAccount(acct, rt, null);
} else {
DomainVO dom = _domainDao.findById(domainId);
max = findCorrectResourceLimitForDomain(dom, rt, null);
}
limits.add(new ResourceLimitVO(rt, max, ownerId, ownerType));
}
return limits;
}
protected void addTaggedResourceLimits(List<ResourceLimitVO> limits, List<ResourceType> types, List<String> tags, ResourceOwnerType ownerType, long ownerId) {
if (CollectionUtils.isEmpty(tags)) {
return;

View File

@ -16,17 +16,17 @@
// under the License.
package com.cloud.resourcelimit;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.cloud.event.ActionEventUtils;
import com.cloud.event.EventTypes;
import com.cloud.utils.db.EntityManager;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.DomainResponse;
@ -62,6 +62,8 @@ import com.cloud.configuration.dao.ResourceLimitDao;
import com.cloud.domain.Domain;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEventUtils;
import com.cloud.event.EventTypes;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.ServiceOffering;
@ -75,21 +77,19 @@ import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.user.Account;
import com.cloud.user.User;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.ResourceLimitService;
import com.cloud.user.User;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.Pair;
import com.cloud.utils.db.EntityManager;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vpc.MockResourceLimitManagerImpl;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class ResourceLimitManagerImplTest {
private Logger logger = LogManager.getLogger(ResourceLimitManagerImplTest.class);
@ -1397,4 +1397,53 @@ public class ResourceLimitManagerImplTest {
domainId, ApiCommandResourceType.Domain.toString()));
}
}
@Test
public void consolidatedResourceLimitsForAllResourceTypesWithAccountId() {
Long accountId = 1L;
Long domainId = null;
List<ResourceLimitVO> foundLimits = new ArrayList<>();
ResourceLimitVO limit = new ResourceLimitVO(Resource.ResourceType.cpu, 10L, accountId, Resource.ResourceOwnerType.Account);
foundLimits.add(limit);
Mockito.when(accountManager.getAccount(accountId)).thenReturn(Mockito.mock(Account.class));
Mockito.doReturn(20L).when(resourceLimitManager).findCorrectResourceLimitForAccount(Mockito.any(Account.class), Mockito.any(Resource.ResourceType.class), Mockito.isNull());
List<ResourceLimitVO> result = resourceLimitManager.getConsolidatedResourceLimitsForAllResourceTypes(accountId, domainId, foundLimits, true);
Assert.assertEquals(EnumSet.allOf(Resource.ResourceType.class).size(), result.size());
Assert.assertTrue(result.contains(limit));
}
@Test
public void consolidatedResourceLimitsForAllResourceTypesWithDomainId() {
Long accountId = null;
Long domainId = 1L;
List<ResourceLimitVO> foundLimits = new ArrayList<>();
ResourceLimitVO limit = new ResourceLimitVO(Resource.ResourceType.memory, 15L, domainId, Resource.ResourceOwnerType.Domain);
foundLimits.add(limit);
Mockito.when(domainDao.findById(domainId)).thenReturn(Mockito.mock(DomainVO.class));
Mockito.doReturn(30L).when(resourceLimitManager).findCorrectResourceLimitForDomain(Mockito.any(Domain.class), Mockito.any(Resource.ResourceType.class), Mockito.isNull());
List<ResourceLimitVO> result = resourceLimitManager.getConsolidatedResourceLimitsForAllResourceTypes(accountId, domainId, foundLimits, false);
Assert.assertEquals(EnumSet.allOf(Resource.ResourceType.class).size(), result.size());
Assert.assertTrue(result.contains(limit));
}
@Test
public void consolidatedResourceLimitsForAllResourceTypesWithEmptyFoundLimits() {
Long accountId = 1L;
Long domainId = null;
List<ResourceLimitVO> foundLimits = new ArrayList<>();
Mockito.when(accountManager.getAccount(accountId)).thenReturn(Mockito.mock(Account.class));
Mockito.doReturn(25L).when(resourceLimitManager).findCorrectResourceLimitForAccount(Mockito.any(Account.class), Mockito.any(Resource.ResourceType.class), Mockito.isNull());
List<ResourceLimitVO> result = resourceLimitManager.getConsolidatedResourceLimitsForAllResourceTypes(accountId, domainId, foundLimits, true);
Assert.assertEquals(EnumSet.allOf(Resource.ResourceType.class).size(), result.size());
Assert.assertEquals(25L, result.get(0).getMax().longValue());
}
}