Skip to content

Commit 1593944

Browse files
DaanHooglandDaan Hoogland
authored andcommitted
[20.3] Implement/fix limit validation for projects
1 parent 4dd91fe commit 1593944

4 files changed

Lines changed: 68 additions & 16 deletions

File tree

server/src/main/java/com/cloud/projects/ProjectManagerImpl.java

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import javax.mail.MessagingException;
3737
import javax.naming.ConfigurationException;
3838

39+
import com.cloud.resourcelimit.CheckedReservation;
3940
import org.apache.cloudstack.acl.ControlledEntity;
4041
import org.apache.cloudstack.acl.ProjectRole;
4142
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
@@ -47,6 +48,7 @@
4748
import org.apache.cloudstack.framework.messagebus.MessageBus;
4849
import org.apache.cloudstack.framework.messagebus.PublishScope;
4950
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
51+
import org.apache.cloudstack.reservation.dao.ReservationDao;
5052
import org.apache.cloudstack.utils.mailing.MailAddress;
5153
import org.apache.cloudstack.utils.mailing.SMTPMailProperties;
5254
import org.apache.cloudstack.utils.mailing.SMTPMailSender;
@@ -159,6 +161,8 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager, C
159161
private VpcManager _vpcMgr;
160162
@Inject
161163
MessageBus messageBus;
164+
@Inject
165+
private ReservationDao reservationDao;
162166

163167
protected boolean _invitationRequired = false;
164168
protected long _invitationTimeOut = 86400000;
@@ -272,8 +276,7 @@ public Project createProject(final String name, final String displayText, String
272276
owner = _accountDao.findById(user.getAccountId());
273277
}
274278

275-
//do resource limit check
276-
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.project);
279+
try (CheckedReservation projectReservation = new CheckedReservation(owner, ResourceType.project, null, null, 1L, reservationDao, _resourceLimitMgr)) {
277280

278281
final Account ownerFinal = owner;
279282
User finalUser = user;
@@ -308,6 +311,7 @@ public Project doInTransaction(TransactionStatus status) {
308311
messageBus.publish(_name, ProjectManager.MESSAGE_CREATE_TUNGSTEN_PROJECT_EVENT, PublishScope.LOCAL, project);
309312

310313
return project;
314+
}
311315
}
312316

313317
@Override
@@ -491,6 +495,9 @@ public Boolean doInTransaction(TransactionStatus status) {
491495
//remove account
492496
ProjectAccountVO projectAccount = _projectAccountDao.findByProjectIdAccountId(projectId, account.getId());
493497
success = _projectAccountDao.remove(projectAccount.getId());
498+
if (projectAccount.getAccountRole() == Role.Admin) {
499+
_resourceLimitMgr.decrementResourceCount(account.getId(), ResourceType.project);
500+
}
494501

495502
//remove all invitations for account
496503
if (success) {
@@ -594,12 +601,22 @@ public boolean addUserToProject(Long projectId, String username, String email, L
594601
if (username == null) {
595602
throw new InvalidParameterValueException("User information (ID) is required to add user to the project");
596603
}
604+
605+
boolean shouldIncrementResourceCount = projectRole != null && Role.Admin == projectRole;
606+
try (CheckedReservation cr = new CheckedReservation(userAccount, ResourceType.project, shouldIncrementResourceCount ? 1L : 0L, reservationDao, _resourceLimitMgr)) {
597607
if (assignUserToProject(project, user.getId(), user.getAccountId(), projectRole,
598608
Optional.ofNullable(role).map(ProjectRole::getId).orElse(null)) != null) {
609+
if (shouldIncrementResourceCount) {
610+
_resourceLimitMgr.incrementResourceCount(userAccount.getId(), ResourceType.project);
611+
}
599612
return true;
613+
} else {
614+
logger.warn("Failed to add user to project: {}", project);
615+
return false;
616+
}
617+
} catch (ResourceAllocationException e) {
618+
throw new RuntimeException(e);
600619
}
601-
logger.warn("Failed to add user to project: {}", project);
602-
return false;
603620
}
604621
}
605622

@@ -652,14 +669,18 @@ public boolean canModifyProjectAccount(Account caller, long accountId) {
652669
}
653670

654671
private void updateProjectAccount(ProjectAccountVO futureOwner, Role newAccRole, Long accountId) throws ResourceAllocationException {
655-
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(accountId), ResourceType.project);
672+
Account account = _accountMgr.getAccount(accountId);
673+
boolean shouldIncrementResourceCount = Role.Admin == newAccRole;
674+
675+
try (CheckedReservation checkedReservation = new CheckedReservation(account, ResourceType.project, shouldIncrementResourceCount ? 1L : 0L, reservationDao, _resourceLimitMgr)) {
656676
futureOwner.setAccountRole(newAccRole);
657677
_projectAccountDao.update(futureOwner.getId(), futureOwner);
658-
if (newAccRole != null && Role.Admin == newAccRole) {
678+
if (shouldIncrementResourceCount) {
659679
_resourceLimitMgr.incrementResourceCount(accountId, ResourceType.project);
660680
} else {
661681
_resourceLimitMgr.decrementResourceCount(accountId, ResourceType.project);
662682
}
683+
}
663684
}
664685

665686
@Override
@@ -701,7 +722,8 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws Resour
701722
" doesn't belong to the project. Add it to the project first and then change the project's ownership");
702723
}
703724

704-
//do resource limit check
725+
try (CheckedReservation checkedReservation = new CheckedReservation(futureOwnerAccount, ResourceType.project, null, null, 1L, reservationDao, _resourceLimitMgr)) {
726+
705727
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(futureOwnerAccount.getId()), ResourceType.project);
706728

707729
//unset the role for the old owner
@@ -714,7 +736,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws Resour
714736
futureOwner.setAccountRole(Role.Admin);
715737
_projectAccountDao.update(futureOwner.getId(), futureOwner);
716738
_resourceLimitMgr.incrementResourceCount(futureOwnerAccount.getId(), ResourceType.project);
717-
739+
}
718740
} else {
719741
logger.trace("Future owner {}is already the owner of the project {}", newOwnerName, project);
720742
}
@@ -857,13 +879,22 @@ public boolean addAccountToProject(long projectId, String accountName, String em
857879
if (account == null) {
858880
throw new InvalidParameterValueException("Account information is required for assigning account to the project");
859881
}
882+
883+
boolean shouldIncrementResourceCount = projectRoleType != null && Role.Admin == projectRoleType;
884+
try (CheckedReservation cr = new CheckedReservation(account, ResourceType.project, shouldIncrementResourceCount ? 1L : 0L, reservationDao, _resourceLimitMgr)) {
860885
if (assignAccountToProject(project, account.getId(), projectRoleType, null,
861886
Optional.ofNullable(projectRole).map(ProjectRole::getId).orElse(null)) != null) {
887+
if (shouldIncrementResourceCount) {
888+
_resourceLimitMgr.incrementResourceCount(account.getId(), ResourceType.project);
889+
}
862890
return true;
863891
} else {
864892
logger.warn("Failed to add account {} to project {}", accountName, project);
865893
return false;
866894
}
895+
} catch (ResourceAllocationException e) {
896+
throw new RuntimeException(e);
897+
}
867898
}
868899
}
869900

@@ -1042,7 +1073,9 @@ public Boolean doInTransaction(TransactionStatus status) {
10421073
boolean success = true;
10431074
ProjectAccountVO projectAccount = _projectAccountDao.findByProjectIdUserId(projectId, user.getAccountId(), user.getId());
10441075
success = _projectAccountDao.remove(projectAccount.getId());
1045-
1076+
if (projectAccount.getAccountRole() == Role.Admin) {
1077+
_resourceLimitMgr.decrementResourceCount(user.getAccountId(), ResourceType.project);
1078+
}
10461079
if (success) {
10471080
logger.debug("Removed user {} from project. Removing any invite sent to the user", user);
10481081
ProjectInvitation invite = _projectInvitationDao.findByUserIdProjectId(user.getId(), user.getAccountId(), projectId);

server/src/main/java/com/cloud/resourcelimit/CheckedReservation.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
import com.cloud.utils.exception.CloudRuntimeException;
4141

4242

43-
public class CheckedReservation implements AutoCloseable {
43+
public class CheckedReservation implements Reserver {
4444
protected Logger logger = LogManager.getLogger(getClass());
4545

4646
private static final int TRY_TO_GET_LOCK_TIME = 120;
@@ -174,7 +174,7 @@ protected void setQuotaLimitLock(GlobalLock quotaLimitLock) {
174174
}
175175

176176
@Override
177-
public void close() throws Exception {
177+
public void close() {
178178
removeAllReservations();
179179
}
180180

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package com.cloud.resourcelimit;
19+
20+
public interface Reserver extends AutoCloseable {
21+
22+
void close();
23+
24+
}

server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,11 +1199,6 @@ public long recalculateDomainResourceCount(final long domainId, final ResourceTy
11991199
long newResourceCount = 0L;
12001200
ResourceCountVO domainRC = null;
12011201

1202-
// calculate project count here
1203-
if (type == ResourceType.project) {
1204-
newResourceCount += _projectDao.countProjectsForDomain(domainId);
1205-
}
1206-
12071202
if (type == ResourceType.network) {
12081203
newResourceCount += networkDomainDao.listDomainNetworkMapByDomain(domainId).size();
12091204
}

0 commit comments

Comments
 (0)