From ad1076f21d34e2819258b8439652dc016e0064a1 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Thu, 19 Jan 2012 10:04:06 -0800 Subject: [PATCH] bug 12983: resource limits for projects --- .../com/cloud/api/commands/UpdateProjectCmd.java | 5 +++-- api/src/com/cloud/configuration/Resource.java | 2 +- api/src/com/cloud/projects/ProjectService.java | 2 +- .../com/cloud/projects/ProjectManagerImpl.java | 14 ++++++++++---- .../cloud/projects/dao/ProjectAccountDao.java | 3 +++ .../projects/dao/ProjectAccountDaoImpl.java | 16 ++++++++++++++++ .../resourcelimit/ResourceLimitManagerImpl.java | 7 +++++++ 7 files changed, 41 insertions(+), 8 deletions(-) diff --git a/api/src/com/cloud/api/commands/UpdateProjectCmd.java b/api/src/com/cloud/api/commands/UpdateProjectCmd.java index c0288f58956..dd2d0f2ea79 100644 --- a/api/src/com/cloud/api/commands/UpdateProjectCmd.java +++ b/api/src/com/cloud/api/commands/UpdateProjectCmd.java @@ -30,6 +30,7 @@ import com.cloud.api.ServerApiException; import com.cloud.api.response.ProjectResponse; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceAllocationException; import com.cloud.projects.Project; import com.cloud.user.UserContext; @@ -47,7 +48,7 @@ public class UpdateProjectCmd extends BaseAsyncCmd { @Parameter(name=ApiConstants.ID, type=CommandType.LONG, required=true, description="id of the project to be modified") private Long id; - @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="new Admin account for the project, should be specified with domainId") + @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="new Admin account for the project") private String accountName; @Parameter(name=ApiConstants.DISPLAY_TEXT, type=CommandType.STRING, description="display text of the project") @@ -91,7 +92,7 @@ public class UpdateProjectCmd extends BaseAsyncCmd { ///////////////////////////////////////////////////// @Override - public void execute(){ + public void execute() throws ResourceAllocationException{ UserContext.current().setEventDetails("Project id: "+ getId()); Project project = _projectService.updateProject(getId(), getDisplayText(), getAccountName()); if (project != null) { diff --git a/api/src/com/cloud/configuration/Resource.java b/api/src/com/cloud/configuration/Resource.java index f9a05f09143..1dcdc762f2d 100644 --- a/api/src/com/cloud/configuration/Resource.java +++ b/api/src/com/cloud/configuration/Resource.java @@ -27,7 +27,7 @@ public interface Resource { volume ("volume", 2, ResourceOwnerType.Account, ResourceOwnerType.Domain), snapshot ("snapshot", 3, ResourceOwnerType.Account, ResourceOwnerType.Domain), template ("template", 4, ResourceOwnerType.Account, ResourceOwnerType.Domain), - project ("project", 5, ResourceOwnerType.Domain); + project ("project", 5, ResourceOwnerType.Account, ResourceOwnerType.Domain); private String name; private ResourceOwnerType[] supportedOwners; diff --git a/api/src/com/cloud/projects/ProjectService.java b/api/src/com/cloud/projects/ProjectService.java index 534ec0a6010..37484528fdb 100644 --- a/api/src/com/cloud/projects/ProjectService.java +++ b/api/src/com/cloud/projects/ProjectService.java @@ -50,7 +50,7 @@ public interface ProjectService { Project findByNameAndDomainId(String name, long domainId); - Project updateProject(long id, String displayText, String newOwnerName); + Project updateProject(long id, String displayText, String newOwnerName) throws ResourceAllocationException; boolean addAccountToProject(long projectId, String accountName, String email); diff --git a/server/src/com/cloud/projects/ProjectManagerImpl.java b/server/src/com/cloud/projects/ProjectManagerImpl.java index b985a7ed3fe..7fd1c094a0a 100755 --- a/server/src/com/cloud/projects/ProjectManagerImpl.java +++ b/server/src/com/cloud/projects/ProjectManagerImpl.java @@ -214,8 +214,8 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ UserContext.current().setEventDetails("Project id=" + project.getId()); } - //Increment resource count for the Owner's domain - _resourceLimitMgr.incrementResourceCount(owner.getAccountId(), ResourceType.project); + //Increment resource count + _resourceLimitMgr.incrementResourceCount(owner.getId(), ResourceType.project); txn.commit(); @@ -266,7 +266,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ s_logger.debug("Marking project id=" + projectId + " with state " + State.Disabled + " as a part of project delete..."); project.setState(State.Disabled); boolean updateResult = _projectDao.update(projectId, project); - _resourceLimitMgr.decrementResourceCount(project.getProjectAccountId(), ResourceType.project); + _resourceLimitMgr.decrementResourceCount(getProjectOwner(projectId).getId(), ResourceType.project); txn.commit(); if (updateResult) { @@ -494,7 +494,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ @Override @DB @ActionEvent(eventType = EventTypes.EVENT_PROJECT_UPDATE, eventDescription = "updating project", async=true) - public Project updateProject(long projectId, String displayText, String newOwnerName) { + public Project updateProject(long projectId, String displayText, String newOwnerName) throws ResourceAllocationException{ Account caller = UserContext.current().getCaller(); //check that the project exists @@ -527,14 +527,20 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ throw new InvalidParameterValueException("Account " + newOwnerName + " doesn't belong to the project. Add it to the project first and then change the project's ownership"); } + //do resource limit check + _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(futureOwnerAccount.getId()), ResourceType.project); + //unset the role for the old owner ProjectAccountVO currentOwner = _projectAccountDao.findByProjectIdAccountId(projectId, currentOwnerAccount.getId()); currentOwner.setAccountRole(Role.Regular); _projectAccountDao.update(currentOwner.getId(), currentOwner); + _resourceLimitMgr.decrementResourceCount(currentOwnerAccount.getId(), ResourceType.project); //set new owner futureOwner.setAccountRole(Role.Admin); _projectAccountDao.update(futureOwner.getId(), futureOwner); + _resourceLimitMgr.incrementResourceCount(futureOwnerAccount.getId(), ResourceType.project); + } else { s_logger.trace("Future owner " + newOwnerName + "is already the owner of the project id=" + projectId); diff --git a/server/src/com/cloud/projects/dao/ProjectAccountDao.java b/server/src/com/cloud/projects/dao/ProjectAccountDao.java index 658ec8fbf9f..47d8cdf8a1e 100644 --- a/server/src/com/cloud/projects/dao/ProjectAccountDao.java +++ b/server/src/com/cloud/projects/dao/ProjectAccountDao.java @@ -19,6 +19,7 @@ package com.cloud.projects.dao; import java.util.List; +import com.cloud.projects.ProjectAccount; import com.cloud.projects.ProjectAccountVO; import com.cloud.utils.db.GenericDao; @@ -34,4 +35,6 @@ public interface ProjectAccountDao extends GenericDao{ List listPermittedAccountIds(long accountId); List listAdministratedProjects(long adminAccountId); + + Long countByAccountIdAndRole(long accountId, ProjectAccount.Role role); } diff --git a/server/src/com/cloud/projects/dao/ProjectAccountDaoImpl.java b/server/src/com/cloud/projects/dao/ProjectAccountDaoImpl.java index 802f3fe9a61..c527f350745 100644 --- a/server/src/com/cloud/projects/dao/ProjectAccountDaoImpl.java +++ b/server/src/com/cloud/projects/dao/ProjectAccountDaoImpl.java @@ -27,6 +27,7 @@ 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.SearchCriteria.Func; import com.cloud.utils.db.SearchCriteria.Op; @Local(value={ProjectAccountDao.class}) @@ -34,6 +35,7 @@ public class ProjectAccountDaoImpl extends GenericDaoBase AllFieldsSearch; final GenericSearchBuilder AdminSearch; final GenericSearchBuilder ProjectAccountSearch; + final GenericSearchBuilder CountByRoleSearch; protected ProjectAccountDaoImpl() { AllFieldsSearch = createSearchBuilder(); @@ -53,6 +55,12 @@ public class ProjectAccountDaoImpl extends GenericDaoBase sc = CountByRoleSearch.create(); + sc.setParameters("accountId", accountId); + sc.setParameters("role", role); + return customSearch(sc, null).get(0); + } } diff --git a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java index 381db1f52cf..d84767d7d13 100755 --- a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java +++ b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java @@ -52,6 +52,8 @@ import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; import com.cloud.network.dao.IPAddressDao; import com.cloud.projects.Project; +import com.cloud.projects.ProjectAccount.Role; +import com.cloud.projects.dao.ProjectAccountDao; import com.cloud.projects.dao.ProjectDao; import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.VMTemplateDao; @@ -112,6 +114,9 @@ public class ResourceLimitManagerImpl implements ResourceLimitService, Manager{ private EntityManager _entityMgr; @Inject private ProjectDao _projectDao; + @Inject + private ProjectAccountDao _projectAccountDao; + protected SearchBuilder ResourceCountSearch; ScheduledExecutorService _rcExecutor; @@ -690,6 +695,8 @@ public class ResourceLimitManagerImpl implements ResourceLimitService, Manager{ newCount = _ipAddressDao.countAllocatedIPsForAccount(accountId); } else if (type == Resource.ResourceType.template) { newCount = _vmTemplateDao.countTemplatesForAccount(accountId); + } else if (type == Resource.ResourceType.project) { + newCount = _projectAccountDao.countByAccountIdAndRole(accountId, Role.Admin); } else { throw new InvalidParameterValueException("Unsupported resource type " + type); }